first working gmv streamer
[megadrive.git] / main.c
CommitLineData
0c1e003e 1#include <stdint.h>
2#include <stdio.h>
3#include <string.h>
4#include "teensy3/core_pins.h"
5#include "teensy3/usb_seremu.h"
6#include "teensy3/usb_rawhid.h"
f20de073 7#include "pkts.h"
8
9// use power of 2
10#define STREAM_BUF_SIZE 512
11#define STREAM_BUF_MASK (512 - 1)
0c1e003e 12
9c4f55f4 13/* ?0SA 00DU, ?1CB RLDU */
f20de073 14static struct {
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 edge_cnt;
21 uint32_t i;
22 uint32_t o;
23} g;
24
25#define STREAM_EL_SZ sizeof(g.stream[0])
9c4f55f4 26
0c1e003e 27ssize_t _write(int fd, const void *buf, size_t nbyte)
28{
29 char tbuf[64];
30 int ret;
31
32 if (fd != 1 && fd != 2) {
33 snprintf(tbuf, sizeof(tbuf), "write to fd %d\n", fd);
34 usb_seremu_write(tbuf, strlen(tbuf));
35 }
36
37 ret = usb_seremu_write(buf, nbyte);
38 return ret < 0 ? ret : nbyte;
39}
40
41void yield(void)
42{
43}
44
a773ac06 45static void my_portb_isr(void)
9c4f55f4 46{
f20de073 47 uint32_t isfr, th;
9c4f55f4 48
49 //printf("irq, GPIOB_PDIR: %08x\n", GPIOB_PDIR);
50
9c4f55f4 51 isfr = PORTB_ISFR;
52 PORTB_ISFR = isfr;
f20de073 53 th = (GPIOB_PDIR >> CORE_PIN0_BIT) & 1;
54
55 if (g.stream_started) {
56 GPIOD_PDOR = g.stream[g.o][th];
57 if (th) {
58 g.o = (g.o + 1) & STREAM_BUF_MASK;
59 if (g.o == g.i) {
60 g.stream_started = 0;
61 g.stream_enable = 0;
62 }
63 }
64 }
65 else {
66 GPIOD_PDOR = g.fixed_state[th];
67 }
68 g.edge_cnt++;
69}
70
71static void udelay(uint32_t us)
72{
73 uint32_t start = micros();
74
75 while ((micros() - start) < us) {
76 asm volatile("nop; nop; nop; nop");
77 yield();
78 }
79}
80
81static void do_start_seq(void)
82{
83 uint32_t edge_cnt_last;
84 uint32_t edge_cnt;
85 uint32_t start, t1, t2;
86 int tout;
87
88 start = micros();
89 edge_cnt = g.edge_cnt;
90
91 /* magic value */
92 g.fixed_state[0] =
93 g.fixed_state[1] = 0x25;
94
95 for (tout = 10000; tout > 0; tout--) {
96 edge_cnt_last = edge_cnt;
97 udelay(100);
98 edge_cnt = g.edge_cnt;
99
100 if (edge_cnt != edge_cnt_last)
101 continue;
102 if (!(GPIOB_PDIR & CORE_PIN0_BITMASK))
103 break;
104 }
105
106 g.fixed_state[0] = 0x33;
107 g.fixed_state[1] = 0x3f;
108 GPIOD_PDOR = 0x33;
109
110 t1 = micros();
111 if (tout == 0) {
112 printf("start_seq timeout1, t=%u\n", t1 - start);
113 return;
114 }
115
116 for (tout = 100000; tout > 0; tout--) {
117 udelay(1);
118
119 if (GPIOB_PDIR & CORE_PIN0_BITMASK)
120 break;
121 }
122
123 t2 = micros();
124 if (tout == 0) {
125 printf("start_seq timeout2, t1=%u, t2=%u\n",
126 t1 - start, t2 - t1);
127 return;
128 }
129
130 //printf(" t1=%u, t2=%u\n", t1 - start, t2 - t1);
131
132 if (g.stream_started) {
133 printf("got start_seq when already started\n");
134 return;
135 }
136
137 if (!g.stream_enable) {
138 printf("got start_seq, without enable from USB\n");
139 return;
140 }
141
142 if (g.i == g.o) {
143 printf("got start_seq while buffer is empty\n");
144 return;
145 }
146
147 g.stream_started = 1;
148}
149
150static int get_space(void)
151{
152 return STREAM_BUF_SIZE - ((g.i - g.o) & STREAM_BUF_MASK);
153}
154
155static void do_usb(void *buf)
156{
157 struct tas_pkt *pkt = buf;
158 uint32_t i, g_i;
159 int space;
160
161 switch (pkt->type) {
162 case PKT_FIXED_STATE:
163 memcpy(g.fixed_state, pkt->data, sizeof(g.fixed_state));
164 break;
165 case PKT_STREAM_ENABLE:
166 g.stream_enable = 1;
167 g.stream_started = 0;
168 g.stream_received = 0;
169 g.i = g.o = 0;
170 break;
171 case PKT_STREAM_END:
172 g.stream_received = 1;
173 printf("end of data\n");
174 break;
175 case PKT_STREAM_DATA:
176 g_i = g.i;
177 space = get_space();
178 if (space <= sizeof(pkt->data) / STREAM_EL_SZ) {
179 printf("got data pkt while space=%d\n", space);
180 return;
181 }
182 for (i = 0; i < sizeof(pkt->data) / STREAM_EL_SZ; i++) {
183 memcpy(&g.stream[g_i++],
184 pkt->data + i * STREAM_EL_SZ,
185 STREAM_EL_SZ);
186 g_i &= STREAM_BUF_MASK;
187 }
188 g.i = g_i;
189 break;
190 default:
191 printf("got unknown pkt type: %04x\n", pkt->type);
192 break;
193 }
9c4f55f4 194}
195
0c1e003e 196int main(void)
197{
f20de073 198 uint32_t edge_cnt_last;
199 uint32_t edge_cnt;
200 uint8_t buf[64];
1cb2822f 201 int timeout;
202 int ret;
0c1e003e 203
204 delay(1000); // wait for usb..
205
f20de073 206 /* ?0SA 00DU, ?1CB RLDU */
207 g.fixed_state[0] = 0x33;
208 g.fixed_state[1] = 0x3f;
209
0c1e003e 210 printf("starting, rawhid: %d\n", usb_rawhid_available());
211
9c4f55f4 212 // md pin th tr tl r l d u
213 // md bit* 6 5 4 3 2 1 0
214 // t bit b16 d5 d4 d3 d2 d1 d0
215 // t pin 0 20 6 8 7 14 2
216 // * - note: tl/tr mixed in most docs
217 pinMode(0, INPUT);
a773ac06 218 attachInterrupt(0, my_portb_isr, CHANGE);
219 attachInterruptVector(IRQ_PORTB, my_portb_isr);
9c4f55f4 220
f20de073 221 // NVIC_SET_PRIORITY(104, 0); // portb
222 NVIC_SET_PRIORITY(IRQ_PORTB, 0); // portb
223
9c4f55f4 224 pinMode( 2, OUTPUT);
225 pinMode(14, OUTPUT);
226 pinMode( 7, OUTPUT);
227 pinMode( 8, OUTPUT);
228 pinMode( 6, OUTPUT);
229 pinMode(20, OUTPUT);
230
231 // led
232 pinMode(13, OUTPUT);
9c4f55f4 233
234 // CORE_PIN0_PORTSET CORE_PIN0_BITMASK PORTB_PCR16
235 printf("GPIOC PDDR, PDIR: %08x %08x\n", GPIOC_PDIR, GPIOC_PDDR);
236 printf("GPIOD PDDR, PDIR: %08x %08x\n", GPIOD_PDIR, GPIOD_PDDR);
237 printf("PORTB_PCR16: %08x\n", PORTB_PCR16);
238
f20de073 239 asm("mrs %0, BASEPRI" : "=r"(ret));
240 printf("BASEPRI: %d\n", ret);
0c1e003e 241
1cb2822f 242 timeout = 1000;
f20de073 243 edge_cnt_last = g.edge_cnt;
9c4f55f4 244
1cb2822f 245 while (1) {
f20de073 246 struct tas_pkt pkt;
247 while (g.stream_enable && !g.stream_received
248 && get_space() > sizeof(pkt.data) / STREAM_EL_SZ)
249 {
250 pkt.type = PKT_STREAM_REQ;
251 ret = usb_rawhid_send(&pkt, 1000);
252 if (ret != sizeof(pkt)) {
253 printf("send STREAM_REQ: %d\n", ret);
254 break;
255 }
256
257 ret = usb_rawhid_recv(buf, 1000);
258 if (ret != 64)
259 printf("usb_rawhid_recv/s: %d\n", ret);
260 else
261 do_usb(buf);
262 }
263
264 if (timeout == 1000) {
265 edge_cnt = g.edge_cnt;
266 //printf("e: %d th: %d\n", edge_cnt - edge_cnt_last,
267 // (GPIOB_PDIR >> CORE_PIN0_BIT) & 1);
268 if (edge_cnt - edge_cnt_last > 10000) {
269 do_start_seq();
270 edge_cnt = g.edge_cnt;
271 }
272 edge_cnt_last = edge_cnt;
273 }
274
1cb2822f 275 ret = usb_rawhid_recv(buf, timeout);
276 if (ret == 64) {
277 CORE_PIN13_PORTSET = CORE_PIN13_BITMASK;
278
f20de073 279 do_usb(buf);
1cb2822f 280 timeout = 20;
281 }
282 else if (ret == 0) {
283 CORE_PIN13_PORTCLEAR = CORE_PIN13_BITMASK;
284 timeout = 1000;
285 }
286 else {
287 printf("usb_rawhid_recv: %d\n", ret);
288 timeout = 1000;
289 }
0c1e003e 290 }
1cb2822f 291
292 return 0;
0c1e003e 293}