4 #include "teensy3/core_pins.h"
5 #include "teensy3/usb_seremu.h"
6 #include "teensy3/usb_rawhid.h"
10 #define STREAM_BUF_SIZE 512
11 #define STREAM_BUF_MASK (512 - 1)
13 /* ?0SA 00DU, ?1CB RLDU */
15 uint8_t stream[STREAM_BUF_SIZE][2];
16 uint8_t fixed_state[4];
17 uint32_t stream_enable:1;
18 uint32_t stream_started:1;
19 uint32_t stream_received:1;
20 uint32_t use_readinc:1;
27 #define STREAM_EL_SZ sizeof(g.stream[0])
29 ssize_t _write(int fd, const void *buf, size_t nbyte)
34 if (fd != 1 && fd != 2) {
35 snprintf(tbuf, sizeof(tbuf), "write to fd %d\n", fd);
36 usb_seremu_write(tbuf, strlen(tbuf));
39 ret = usb_seremu_write(buf, nbyte);
40 return ret < 0 ? ret : nbyte;
47 static void portb_isr_fixed(void)
53 th = (GPIOB_PDIR >> CORE_PIN0_BIT) & 1;
55 GPIOD_PDOR = g.fixed_state[th];
59 static void portb_isr_readinc(void)
65 th = (GPIOB_PDIR >> CORE_PIN0_BIT) & 1;
67 GPIOD_PDOR = g.stream[g.o][th];
69 g.o = (g.o + 1) & STREAM_BUF_MASK;
72 attachInterruptVector(IRQ_PORTB, portb_isr_fixed);
78 static void portb_isr_read(void)
84 th = (GPIOB_PDIR >> CORE_PIN0_BIT) & 1;
86 GPIOD_PDOR = g.stream[g.o][th];
90 static void portc_isr_nop(void)
98 // /vsync starts at line 235/259 (ntsc/pal), just as vcounter jumps back
99 // we care when it comes out (/vsync goes high) after 3 lines at 238/262
100 static void portc_isr_frameinc(void)
107 g.o = (g.o + 1) & STREAM_BUF_MASK;
109 attachInterruptVector(IRQ_PORTB, portb_isr_fixed);
110 attachInterruptVector(IRQ_PORTC, portc_isr_nop);
115 static void udelay(uint32_t us)
117 uint32_t start = micros();
119 while ((micros() - start) < us) {
120 asm volatile("nop; nop; nop; nop");
125 static void do_start_seq(void)
127 uint32_t edge_cnt_last;
129 uint32_t start, t1, t2;
133 edge_cnt = g.edge_cnt;
137 g.fixed_state[1] = 0x25;
139 for (tout = 10000; tout > 0; tout--) {
140 edge_cnt_last = edge_cnt;
142 edge_cnt = g.edge_cnt;
144 if (edge_cnt != edge_cnt_last)
146 if (!(GPIOB_PDIR & CORE_PIN0_BITMASK))
150 g.fixed_state[0] = 0x33;
151 g.fixed_state[1] = 0x3f;
156 printf("start_seq timeout1, t=%u\n", t1 - start);
160 for (tout = 100000; tout > 0; tout--) {
163 if (GPIOB_PDIR & CORE_PIN0_BITMASK)
169 printf("start_seq timeout2, t1=%u, t2=%u\n",
170 t1 - start, t2 - t1);
174 //printf(" t1=%u, t2=%u\n", t1 - start, t2 - t1);
176 if (g.stream_started) {
177 printf("got start_seq when already started\n");
181 if (!g.stream_enable) {
182 printf("got start_seq, without enable from USB\n");
187 printf("got start_seq while buffer is empty\n");
192 g.stream_started = 1;
194 attachInterruptVector(IRQ_PORTB, portb_isr_readinc);
195 attachInterruptVector(IRQ_PORTC, portc_isr_nop);
198 attachInterruptVector(IRQ_PORTB, portb_isr_read);
199 attachInterruptVector(IRQ_PORTC, portc_isr_frameinc);
204 static int get_space(void)
206 return STREAM_BUF_SIZE - ((g.i - g.o) & STREAM_BUF_MASK);
209 static void do_usb(void *buf)
211 struct tas_pkt *pkt = buf;
216 case PKT_FIXED_STATE:
217 memcpy(g.fixed_state, pkt->data, sizeof(g.fixed_state));
219 case PKT_STREAM_ENABLE:
221 /* wait for start from MD */
223 g.stream_started = 0;
224 g.stream_received = 0;
225 g.use_readinc = pkt->start.use_readinc;
228 attachInterruptVector(IRQ_PORTB, portb_isr_fixed);
229 attachInterruptVector(IRQ_PORTC, portc_isr_nop);
233 g.stream_received = 1;
234 printf("end of stream\n");
236 case PKT_STREAM_DATA:
239 if (space <= sizeof(pkt->data) / STREAM_EL_SZ) {
240 printf("got data pkt while space=%d\n", space);
243 for (i = 0; i < sizeof(pkt->data) / STREAM_EL_SZ; i++) {
244 memcpy(&g.stream[g_i++],
245 pkt->data + i * STREAM_EL_SZ,
247 g_i &= STREAM_BUF_MASK;
252 printf("got unknown pkt type: %04x\n", pkt->type);
259 uint32_t edge_cnt_last;
265 delay(1000); // wait for usb..
267 /* ?0SA 00DU, ?1CB RLDU */
268 g.fixed_state[0] = 0x33;
269 g.fixed_state[1] = 0x3f;
271 printf("starting, rawhid: %d\n", usb_rawhid_available());
273 // md pin th tr tl r l d u vsync
274 // md bit* 6 5 4 3 2 1 0
275 // t bit b16 d5 d4 d3 d2 d1 d0 c6
276 // t pin 0 20 6 8 7 14 2 11
277 // * - note: tl/tr mixed in most docs
279 attachInterrupt(0, portb_isr_fixed, CHANGE);
280 attachInterruptVector(IRQ_PORTB, portb_isr_fixed);
282 attachInterrupt(11, portc_isr_nop, RISING);
283 attachInterruptVector(IRQ_PORTC, portc_isr_nop);
285 NVIC_SET_PRIORITY(IRQ_PORTB, 0);
286 NVIC_SET_PRIORITY(IRQ_PORTC, 16);
298 // CORE_PIN0_PORTSET CORE_PIN0_BITMASK PORTB_PCR16
299 printf("GPIOB PDDR, PDIR: %08x %08x\n", GPIOB_PDIR, GPIOB_PDDR);
300 printf("GPIOC PDDR, PDIR: %08x %08x\n", GPIOC_PDIR, GPIOC_PDDR);
301 printf("GPIOD PDDR, PDIR: %08x %08x\n", GPIOD_PDIR, GPIOD_PDDR);
302 printf("PORTB_PCR16: %08x\n", PORTB_PCR16);
303 printf("PORTC_PCR6: %08x\n", PORTC_PCR6);
305 asm("mrs %0, BASEPRI" : "=r"(ret));
306 printf("BASEPRI: %d\n", ret);
309 edge_cnt_last = g.edge_cnt;
313 while (g.stream_enable && !g.stream_received
314 && get_space() > sizeof(pkt.data) / STREAM_EL_SZ)
316 pkt.type = PKT_STREAM_REQ;
317 pkt.req.frame = g.frame_cnt;
319 ret = usb_rawhid_send(&pkt, 1000);
320 if (ret != sizeof(pkt)) {
321 printf("send STREAM_REQ: %d\n", ret);
325 ret = usb_rawhid_recv(buf, 1000);
327 printf("usb_rawhid_recv/s: %d\n", ret);
332 if (timeout == 1000) {
333 edge_cnt = g.edge_cnt;
334 //printf("e: %d th: %d\n", edge_cnt - edge_cnt_last,
335 // (GPIOB_PDIR >> CORE_PIN0_BIT) & 1);
336 if (edge_cnt - edge_cnt_last > 10000) {
338 edge_cnt = g.edge_cnt;
340 edge_cnt_last = edge_cnt;
343 ret = usb_rawhid_recv(buf, timeout);
345 CORE_PIN13_PORTSET = CORE_PIN13_BITMASK;
351 CORE_PIN13_PORTCLEAR = CORE_PIN13_BITMASK;
355 printf("usb_rawhid_recv: %d\n", ret);