diff options
Diffstat (limited to 'firmware/test')
-rw-r--r-- | firmware/test/i2c/Makefile | 10 | ||||
-rw-r--r-- | firmware/test/i2c/main.c | 210 |
2 files changed, 186 insertions, 34 deletions
diff --git a/firmware/test/i2c/Makefile b/firmware/test/i2c/Makefile index 9089020fae..0d3ff884ed 100644 --- a/firmware/test/i2c/Makefile +++ b/firmware/test/i2c/Makefile | |||
@@ -8,13 +8,13 @@ INCLUDES=-I../../common -I../.. -I../../drivers | |||
8 | 8 | ||
9 | TARGET = -DARCHOS_PLAYER_OLD=1 | 9 | TARGET = -DARCHOS_PLAYER_OLD=1 |
10 | 10 | ||
11 | CFLAGS = -g -Wall -m1 -nostdlib -Wstrict-prototypes -fschedule-insns -fno-builtin $(INCLUDES) $(TARGET) -DDEBUG | 11 | CFLAGS = -g -Wall -m1 -save-temps -nostdlib -Wstrict-prototypes -fschedule-insns -fno-builtin $(INCLUDES) $(TARGET) -DDEBUG |
12 | AFLAGS += -small -relax | 12 | AFLAGS += -small -relax |
13 | 13 | ||
14 | OBJS= ../../crt0.o main.o ../../drivers/i2c.o ../../drivers/mas.o \ | 14 | OBJS= ../../crt0.o main.o ../../drivers/i2c.o ../../drivers/mas.o \ |
15 | ../../debug.o ../../kernel.o thread.o ../../common/sprintf.o \ | 15 | ../../debug.o ../../kernel.o thread.o ../../common/sprintf.o \ |
16 | ../../panic.o ../../system.o ../../drivers/led.o \ | 16 | ../../panic.o ../../system.o ../../drivers/led.o \ |
17 | ../../drivers/lcd.o ../../drivers/ata.o ../../drivers/fat.o \ | 17 | ../../drivers/lcd.o ata.o ../../drivers/fat.o \ |
18 | ../../common/disk.o ../../common/file.o ../../common/dir.o | 18 | ../../common/disk.o ../../common/file.o ../../common/dir.o |
19 | 19 | ||
20 | %.o: %.S | 20 | %.o: %.S |
@@ -52,3 +52,9 @@ install: | |||
52 | thread.o: ../../thread.c | 52 | thread.o: ../../thread.c |
53 | $(CC) -O $(CFLAGS) -c $< | 53 | $(CC) -O $(CFLAGS) -c $< |
54 | 54 | ||
55 | ata.o: ../../drivers/ata.c | ||
56 | $(CC) -O $(CFLAGS) -c $< | ||
57 | |||
58 | main.o: main.c | ||
59 | $(CC) -O $(CFLAGS) -c $< | ||
60 | |||
diff --git a/firmware/test/i2c/main.c b/firmware/test/i2c/main.c index 68f5e9b030..58f15dd911 100644 --- a/firmware/test/i2c/main.c +++ b/firmware/test/i2c/main.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include "i2c.h" | 20 | #include "i2c.h" |
21 | #include "mas.h" | 21 | #include "mas.h" |
22 | #include "sh7034.h" | 22 | #include "sh7034.h" |
23 | #include "system.h" | ||
23 | #include "debug.h" | 24 | #include "debug.h" |
24 | #include "kernel.h" | 25 | #include "kernel.h" |
25 | #include "ata.h" | 26 | #include "ata.h" |
@@ -27,6 +28,11 @@ | |||
27 | #include "fat.h" | 28 | #include "fat.h" |
28 | #include "file.h" | 29 | #include "file.h" |
29 | #include "dir.h" | 30 | #include "dir.h" |
31 | #include "panic.h" | ||
32 | |||
33 | #ifndef MIN | ||
34 | #define MIN(a, b) (((a)<(b))?(a):(b)) | ||
35 | #endif | ||
30 | 36 | ||
31 | unsigned char fliptable[] = | 37 | unsigned char fliptable[] = |
32 | { | 38 | { |
@@ -66,13 +72,17 @@ unsigned char fliptable[] = | |||
66 | 72 | ||
67 | extern unsigned int stack[]; | 73 | extern unsigned int stack[]; |
68 | /* Place the MP3 data right after the stack */ | 74 | /* Place the MP3 data right after the stack */ |
75 | |||
76 | #define MP3BUF_LEN 0x100000 /* 1 Mbyte */ | ||
77 | |||
69 | unsigned char *mp3buf = (unsigned char *)stack; | 78 | unsigned char *mp3buf = (unsigned char *)stack; |
70 | int mp3datalen; | ||
71 | 79 | ||
72 | unsigned char *mp3dataptr; | 80 | int mp3buf_write; |
73 | int mp3_transmitted; | 81 | int mp3buf_read; |
82 | int last_dma_chunk_size; | ||
74 | 83 | ||
75 | bool dma_on; | 84 | bool dma_on; |
85 | static void mas_poll_start(unsigned int interval_in_ms); | ||
76 | 86 | ||
77 | void setup_sci0(void) | 87 | void setup_sci0(void) |
78 | { | 88 | { |
@@ -124,11 +134,12 @@ int mas_tx_ready(void) | |||
124 | 134 | ||
125 | void init_dma(void) | 135 | void init_dma(void) |
126 | { | 136 | { |
127 | SAR3 = (unsigned int) mp3buf; | 137 | SAR3 = (unsigned int) mp3buf + mp3buf_read; |
128 | DAR3 = 0x5FFFEC3; | 138 | DAR3 = 0x5FFFEC3; |
129 | CHCR3 &= ~0x0002; /* Clear interrupt */ | 139 | CHCR3 &= ~0x0002; /* Clear interrupt */ |
130 | CHCR3 = 0x1504; /* Single address destination, TXI0, IE=1 */ | 140 | CHCR3 = 0x1504; /* Single address destination, TXI0, IE=1 */ |
131 | DTCR3 = 64000; | 141 | last_dma_chunk_size = MIN(65536, mp3buf_write - mp3buf_read); |
142 | DTCR3 = last_dma_chunk_size & 0xffff; | ||
132 | DMAOR = 0x0001; /* Enable DMA */ | 143 | DMAOR = 0x0001; /* Enable DMA */ |
133 | } | 144 | } |
134 | 145 | ||
@@ -156,6 +167,18 @@ void dma_tick(void) | |||
156 | } | 167 | } |
157 | } | 168 | } |
158 | 169 | ||
170 | void bitswap(unsigned char *data, int length) | ||
171 | { | ||
172 | unsigned int i; | ||
173 | for(i = 0;i < length;i++) | ||
174 | { | ||
175 | data[i] = fliptable[data[i]]; | ||
176 | } | ||
177 | } | ||
178 | |||
179 | struct event_queue disk_queue; | ||
180 | int filling; | ||
181 | |||
159 | int main(void) | 182 | int main(void) |
160 | { | 183 | { |
161 | char buf[40]; | 184 | char buf[40]; |
@@ -164,6 +187,11 @@ int main(void) | |||
164 | DIR *d; | 187 | DIR *d; |
165 | struct dirent *dent; | 188 | struct dirent *dent; |
166 | int f; | 189 | int f; |
190 | int free_space_left; | ||
191 | int mp3_space_left; | ||
192 | int amount_to_read; | ||
193 | int play_song; | ||
194 | struct event *ev; | ||
167 | 195 | ||
168 | /* Clear it all! */ | 196 | /* Clear it all! */ |
169 | SSR1 &= ~(SCI_RDRF | SCI_ORER | SCI_PER | SCI_FER); | 197 | SSR1 &= ~(SCI_RDRF | SCI_ORER | SCI_PER | SCI_FER); |
@@ -173,12 +201,13 @@ int main(void) | |||
173 | SCR1 |= 0x40; | 201 | SCR1 |= 0x40; |
174 | SCR1 &= ~0x80; | 202 | SCR1 &= ~0x80; |
175 | 203 | ||
204 | IPRE |= 0xf000; /* Highest priority */ | ||
205 | |||
176 | i2c_init(); | 206 | i2c_init(); |
177 | 207 | ||
178 | dma_on = TRUE; | 208 | dma_on = TRUE; |
179 | 209 | ||
180 | kernel_init(); | 210 | kernel_init(); |
181 | tick_add_task(dma_tick); | ||
182 | 211 | ||
183 | set_irq_level(0); | 212 | set_irq_level(0); |
184 | 213 | ||
@@ -247,37 +276,94 @@ int main(void) | |||
247 | debugf("Couldn't open file\n"); | 276 | debugf("Couldn't open file\n"); |
248 | } | 277 | } |
249 | 278 | ||
250 | i = read(f, mp3buf, 1000000); | 279 | mp3buf_read = mp3buf_write = 0; |
280 | |||
281 | /* First read in a few seconds worth of MP3 data */ | ||
282 | i = read(f, mp3buf, 0x20000); | ||
251 | debugf("Read %d bytes\n", i); | 283 | debugf("Read %d bytes\n", i); |
252 | 284 | ||
253 | mp3datalen = i; | ||
254 | |||
255 | ata_spindown(-1); | 285 | ata_spindown(-1); |
256 | 286 | ||
257 | debugf("bit swapping...\n"); | 287 | debugf("bit swapping...\n"); |
258 | for(i = 0;i < mp3datalen;i++) | 288 | bitswap(mp3buf + mp3buf_write, i); |
259 | { | 289 | |
260 | mp3buf[i] = fliptable[mp3buf[i]]; | 290 | mp3buf_write = i; |
261 | } | ||
262 | 291 | ||
263 | while(1) | 292 | queue_init(&disk_queue); |
264 | { | 293 | |
265 | debugf("let's play...\n"); | 294 | mas_poll_start(1); |
266 | init_dma(); | 295 | |
296 | debugf("let's play...\n"); | ||
297 | init_dma(); | ||
298 | |||
299 | dma_on = TRUE; | ||
300 | |||
301 | /* Enable Tx & TXIE */ | ||
302 | SCR0 |= 0xa0; | ||
267 | 303 | ||
268 | mp3dataptr = mp3buf; | 304 | CHCR3 |= 1; |
269 | mp3_transmitted = 0; | 305 | |
270 | 306 | #define MP3_LOW_WATER 0x30000 | |
271 | dma_on = TRUE; | 307 | #define MP3_CHUNK_SIZE 0x20000 |
272 | 308 | ||
273 | /* Enable Tx & TXIE */ | 309 | play_song = 1; |
274 | SCR0 |= 0xa0; | 310 | filling = 1; |
275 | 311 | ||
276 | CHCR3 |= 1; | 312 | while(play_song) |
277 | 313 | { | |
278 | debugf("sleeping...\n"); | 314 | if(filling) |
279 | sleep(1000000); | 315 | { |
316 | free_space_left = mp3buf_read - mp3buf_write; | ||
317 | if(free_space_left < 0) | ||
318 | free_space_left = MP3BUF_LEN + free_space_left; | ||
319 | |||
320 | if(free_space_left <= MP3_CHUNK_SIZE) | ||
321 | { | ||
322 | debugf("0\n"); | ||
323 | ata_spindown(-1); | ||
324 | filling = 0; | ||
325 | continue; | ||
326 | } | ||
327 | |||
328 | amount_to_read = MIN(MP3_CHUNK_SIZE, free_space_left); | ||
329 | amount_to_read = MIN(MP3BUF_LEN - mp3buf_write, amount_to_read); | ||
330 | |||
331 | /* Read in a few seconds worth of MP3 data. We don't want to | ||
332 | read too large chunks because the bitswapping will take | ||
333 | too much time. We must keep the DMA happy and also give | ||
334 | the other threads a chance to run. */ | ||
335 | debugf("R\n", i); | ||
336 | i = read(f, mp3buf+mp3buf_write, amount_to_read); | ||
337 | if(i) | ||
338 | { | ||
339 | debugf("B\n"); | ||
340 | bitswap(mp3buf + mp3buf_write, i); | ||
341 | |||
342 | mp3buf_write += i; | ||
343 | if(mp3buf_write >= MP3BUF_LEN) | ||
344 | { | ||
345 | mp3buf_write = 0; | ||
346 | debugf("W\n"); | ||
347 | } | ||
348 | } | ||
349 | else | ||
350 | { | ||
351 | play_song = 0; | ||
352 | ata_spindown(-1); | ||
353 | filling = 0; | ||
354 | } | ||
355 | } | ||
356 | else | ||
357 | { | ||
358 | debugf("S\n"); | ||
359 | ev = queue_wait(&disk_queue); | ||
360 | debugf("Q\n"); | ||
361 | debugf("1\n"); | ||
362 | filling = 1; | ||
363 | } | ||
280 | } | 364 | } |
365 | debugf("Song is finished\n"); | ||
366 | while(1); | ||
281 | } | 367 | } |
282 | 368 | ||
283 | #pragma interrupt | 369 | #pragma interrupt |
@@ -289,14 +375,74 @@ void IRQ6(void) | |||
289 | #pragma interrupt | 375 | #pragma interrupt |
290 | void DEI3(void) | 376 | void DEI3(void) |
291 | { | 377 | { |
292 | mp3_transmitted += 64000; | 378 | int unplayed_space_left; |
293 | if(mp3_transmitted < mp3datalen) | 379 | int space_until_end_of_buffer; |
380 | mp3buf_read += last_dma_chunk_size; | ||
381 | if(mp3buf_read >= MP3BUF_LEN) | ||
382 | mp3buf_read = 0; | ||
383 | |||
384 | unplayed_space_left = mp3buf_write - mp3buf_read; | ||
385 | if(unplayed_space_left < 0) | ||
386 | unplayed_space_left = MP3BUF_LEN + unplayed_space_left; | ||
387 | |||
388 | space_until_end_of_buffer = MP3BUF_LEN - mp3buf_read; | ||
389 | |||
390 | if(!filling && unplayed_space_left < MP3_LOW_WATER) | ||
294 | { | 391 | { |
295 | DTCR3 = 64000; | 392 | queue_post(&disk_queue, 1, 0); |
393 | } | ||
394 | |||
395 | if(unplayed_space_left) | ||
396 | { | ||
397 | last_dma_chunk_size = MIN(65536, unplayed_space_left); | ||
398 | last_dma_chunk_size = MIN(last_dma_chunk_size, space_until_end_of_buffer); | ||
399 | DTCR3 = last_dma_chunk_size & 0xffff; | ||
400 | SAR3 = (unsigned int)mp3buf + mp3buf_read; | ||
296 | CHCR3 &= ~0x0002; | 401 | CHCR3 &= ~0x0002; |
297 | } | 402 | } |
298 | else | 403 | else |
299 | { | 404 | { |
405 | debugf("No more MP3 data. Stopping.\n"); | ||
300 | CHCR3 = 0; | 406 | CHCR3 = 0; |
301 | } | 407 | } |
302 | } | 408 | } |
409 | |||
410 | static void mas_poll_start(unsigned int interval_in_ms) | ||
411 | { | ||
412 | unsigned int count; | ||
413 | |||
414 | count = FREQ / 1000 / 8 * interval_in_ms; | ||
415 | |||
416 | if(count > 0xffff) | ||
417 | { | ||
418 | panicf("Error! The MAS poll interval is too long (%d ms)\n", | ||
419 | interval_in_ms); | ||
420 | return; | ||
421 | } | ||
422 | |||
423 | /* We are using timer 1 */ | ||
424 | |||
425 | TSTR &= ~0x02; /* Stop the timer */ | ||
426 | TSNC &= ~0x02; /* No synchronization */ | ||
427 | TMDR &= ~0x02; /* Operate normally */ | ||
428 | |||
429 | TCNT1 = 0; /* Start counting at 0 */ | ||
430 | GRA1 = count; | ||
431 | TCR1 = 0x23; /* Clear at GRA match, sysclock/8 */ | ||
432 | |||
433 | /* Enable interrupt on level 2 */ | ||
434 | IPRC = (IPRC & ~0x000f) | 0x0002; | ||
435 | |||
436 | TSR1 &= ~0x02; | ||
437 | TIER1 = 0xf9; /* Enable GRA match interrupt */ | ||
438 | |||
439 | TSTR |= 0x02; /* Start timer 2 */ | ||
440 | } | ||
441 | |||
442 | #pragma interrupt | ||
443 | void IMIA1(void) | ||
444 | { | ||
445 | dma_tick(); | ||
446 | TSR1 &= ~0x01; | ||
447 | } | ||
448 | |||