as3525*: initialize cpu_frequency correctly
[kugel-rb.git] / firmware / test / i2c / main.c
blobad0f8efcbde1ccb30aed86d3418f941a8ec28aed
1 /***************************************************************************
3 * __________ __ ___.
5 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
7 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
9 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
11 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
13 * \/ \/ \/ \/ \/
15 * $Id$
19 * Copyright (C) 2002 by Linus Nielsen Feltzing
24 * This program is free software; you can redistribute it and/or
25 * modify it under the terms of the GNU General Public License
26 * as published by the Free Software Foundation; either version 2
27 * of the License, or (at your option) any later version.
31 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
33 * KIND, either express or implied.
37 ****************************************************************************/
39 #include <stdio.h>
41 #include <stdlib.h>
43 #include <stdbool.h>
45 #include <string.h>
47 #include "i2c.h"
49 #include "mas.h"
51 #include "dac.h"
53 #include "sh7034.h"
55 #include "system.h"
57 #include "debug.h"
59 #include "kernel.h"
61 #include "thread.h"
63 #include "ata.h"
65 #include "disk.h"
67 #include "fat.h"
69 #include "file.h"
71 #include "dir.h"
73 #include "panic.h"
77 #ifndef MIN
79 #define MIN(a, b) (((a)<(b))?(a):(b))
81 #endif
85 #define MPEG_PLAY 1
87 #define MPEG_STOP 2
89 #define MPEG_PAUSE 3
91 #define MPEG_RESUME 4
93 #define MPEG_NEED_DATA 100
97 #define MP3_LOW_WATER 0x30000
99 #define MP3_CHUNK_SIZE 0x20000
103 unsigned int bass_table[] =
109 0x800, /* 1dB */
111 0x10000, /* 2dB */
113 0x17c00, /* 3dB */
115 0x1f800, /* 4dB */
117 0x27000, /* 5dB */
119 0x2e400, /* 6dB */
121 0x35800, /* 7dB */
123 0x3c000, /* 8dB */
125 0x42800, /* 9dB */
127 0x48800, /* 10dB */
129 0x4e400, /* 11dB */
131 0x53800, /* 12dB */
133 0x58800, /* 13dB */
135 0x5d400, /* 14dB */
137 0x61800 /* 15dB */
143 unsigned int treble_table[] =
149 0x5400, /* 1dB */
151 0xac00, /* 2dB */
153 0x10400, /* 3dB */
155 0x16000, /* 4dB */
157 0x1c000, /* 5dB */
159 0x22400, /* 6dB */
161 0x28400, /* 7dB */
163 0x2ec00, /* 8dB */
165 0x35400, /* 9dB */
167 0x3c000, /* 10dB */
169 0x42c00, /* 11dB */
171 0x49c00, /* 12dB */
173 0x51800, /* 13dB */
175 0x58400, /* 14dB */
177 0x5f800 /* 15dB */
183 unsigned char fliptable[] =
187 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
189 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
191 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
193 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
195 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
197 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
199 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
201 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
203 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
205 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
207 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
209 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
211 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
213 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
215 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
217 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
219 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
221 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
223 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
225 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
227 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
229 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
231 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
233 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
235 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
237 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
239 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
241 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
243 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
245 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
247 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
249 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
255 extern unsigned int stack[];
257 /* Place the MP3 data right after the stack */
261 #define MP3BUF_LEN 0x100000 /* 1 Mbyte */
265 unsigned char *mp3buf = (unsigned char *)stack;
269 char *tracks[100];
271 int num_tracks;
275 int mp3buf_write;
277 int mp3buf_read;
279 int last_dma_chunk_size;
283 bool dma_on; /* The DMA is active */
285 bool playing; /* We are playing an MP3 stream */
287 bool filling; /* We are filling the buffer with data from disk */
291 struct event_queue mpeg_queue;
295 static void mas_poll_start(unsigned int interval_in_ms);
297 void mpeg_thread(void);
301 void reset_mp3_buffer(void)
305 mp3buf_read = 0;
307 mp3buf_write = 0;
313 void setup_sci0(void)
317 /* PB15 is I/O, PB14 is IRQ6, PB12 is SCK0 */
319 PBCR1 = (PBCR1 & 0x0cff) | 0x1200;
323 /* Set PB12 to output */
325 PBIOR |= 0x1000;
329 /* Disable serial port */
331 SCR0 = 0x00;
335 /* Synchronous, no prescale */
337 SMR0 = 0x80;
341 /* Set baudrate 1Mbit/s */
343 BRR0 = 0x03;
347 /* use SCK as serial clock output */
349 SCR0 = 0x01;
353 /* Clear FER and PER */
355 SSR0 &= 0xe7;
359 /* Set interrupt ITU2 and SCI0 priority to 0 */
361 IPRD &= 0x0ff0;
365 /* set IRQ6 and IRQ7 to edge detect */
367 ICR |= 0x03;
371 /* set PB15 and PB14 to inputs */
373 PBIOR &= 0x7fff;
375 PBIOR &= 0xbfff;
379 /* set IRQ6 prio 8 and IRQ7 prio 0 */
381 IPRB = ( IPRB & 0xff00 ) | 0x0080;
385 /* Enable End of DMA interrupt at prio 8 */
387 IPRC = (IPRC & 0xf0ff) | 0x0800;
391 /* Enable Tx (only!) */
393 SCR0 |= 0x20;
401 void init_dma(void)
405 SAR3 = (unsigned int) mp3buf + mp3buf_read;
407 DAR3 = 0x5FFFEC3;
409 CHCR3 &= ~0x0002; /* Clear interrupt */
411 CHCR3 = 0x1504; /* Single address destination, TXI0, IE=1 */
413 last_dma_chunk_size = MIN(65536, mp3buf_write - mp3buf_read);
415 DTCR3 = last_dma_chunk_size & 0xffff;
417 DMAOR = 0x0001; /* Enable DMA */
419 CHCR3 |= 0x0001; /* Enable DMA IRQ */
425 void start_dma(void)
429 SCR0 |= 0x80;
431 dma_on = true;
437 void stop_dma(void)
441 SCR0 &= 0x7f;
443 dma_on = false;
449 void dma_tick(void)
453 /* Start DMA if it isn't running */
455 if(playing && !dma_on)
459 if(PBDR & 0x4000)
463 if(!(SCR0 & 0x80))
465 start_dma();
475 void bitswap(unsigned char *data, int length)
479 int i;
481 for(i = 0;i < length;i++)
485 data[i] = fliptable[data[i]];
493 int main(void)
497 char buf[40];
499 char str[32];
501 int i=0;
503 DIR *d;
505 struct dirent *dent;
507 char *tmp;
509 int volume, bass, treble;
511 unsigned short frame_count;
515 /* Clear it all! */
517 SSR1 &= ~(SCI_RDRF | SCI_ORER | SCI_PER | SCI_FER);
521 /* This enables the serial Rx interrupt, to be able to exit into the
523 debugger when you hit CTRL-C */
525 SCR1 |= 0x40;
527 SCR1 &= ~0x80;
531 IPRE |= 0xf000; /* Highest priority */
535 i2c_init();
539 dma_on = true;
543 kernel_init();
547 enable_irq();
551 setup_sci0();
555 i=mas_readmem(MAS_BANK_D1,0xff6,(unsigned long*)buf,2);
557 if (i) {
559 debugf("Error - mas_readmem() returned %d\n", i);
561 while(1);
567 i = buf[0] | buf[1] << 8;
569 debugf("MAS version: %x\n", i);
571 i = buf[4] | buf[5] << 8;
573 debugf("MAS revision: %x\n", i);
577 i=mas_readmem(MAS_BANK_D1,0xff9,(unsigned long*)buf,7);
579 if (i) {
581 debugf("Error - mas_readmem() returned %d\n", i);
583 while(1);
589 for(i = 0;i < 7;i++)
593 str[i*2+1] = buf[i*4];
595 str[i*2] = buf[i*4+1];
599 str[i*2] = 0;
601 debugf("Description: %s\n", str);
605 i=mas_writereg(0x3b, 0x20);
607 if (i < 0) {
609 debugf("Error - mas_writereg() returned %d\n", i);
611 while(1);
617 i = mas_run(1);
619 if (i < 0) {
621 debugf("Error - mas_run() returned %d\n", i);
623 while(1);
629 i = ata_init();
631 debugf("ata_init() returned %d\n", i);
635 i = disk_init();
637 debugf("disk_init() returned %d\n", i);
641 debugf("part[0] starts at sector %d\n", part[0].start);
645 i = fat_mount(IF_MV2(0,) IF_MD2(0,) part[0].start);
647 debugf("fat_mount() returned %d\n", i);
651 num_tracks = 0;
653 if((d = opendir("/")))
657 while((dent = readdir(d)))
661 debugf("%s\n", dent->d_name);
663 i = strlen(dent->d_name);
665 tmp = dent->d_name + i - 4;
667 debugf("%s\n", tmp);
669 if(!stricmp(tmp, ".mp3"))
673 tmp = malloc(i+1);
675 if(tmp)
679 debugf("Adding track %s\n", dent->d_name);
681 snprintf(tmp, i+1, "/%s", dent->d_name);
683 tracks[num_tracks++] = tmp;
687 else
691 panicf("Out of memory\n");
699 closedir(d);
705 debugf("Number of tracks: %d\n");
709 queue_init(&mpeg_queue);
713 create_thread(mpeg_thread, stack - 0x2000, 0x4000, 0);
717 mas_poll_start(2);
721 debugf("let's play...\n");
725 queue_post(&mpeg_queue, MPEG_PLAY, 0);
729 volume = 0x2c;
733 if(dac_config(0x04) < 0)
735 debugf("DAC write failed\n");
739 if(dac_volume(volume) < 0)
741 debugf("DAC write failed\n");
745 bass = 12;
747 treble = 8;
751 mas_writereg(MAS_REG_KPRESCALE, 0xe9400);
753 mas_writereg(MAS_REG_KBASS, bass_table[bass]);
755 mas_writereg(MAS_REG_KTREBLE, treble_table[treble]);
759 while(1)
763 sleep(HZ*4);
771 void IRQ6(void) __attribute__((interrupt_handler));
773 void IRQ6(void)
777 stop_dma();
783 void DEI3(void) __attribute__((interrupt_handler));
785 void DEI3(void)
789 int unplayed_space_left;
791 int space_until_end_of_buffer;
795 if(playing)
799 mp3buf_read += last_dma_chunk_size;
801 if(mp3buf_read >= MP3BUF_LEN)
803 mp3buf_read = 0;
807 unplayed_space_left = mp3buf_write - mp3buf_read;
809 if(unplayed_space_left < 0)
811 unplayed_space_left = MP3BUF_LEN + unplayed_space_left;
815 space_until_end_of_buffer = MP3BUF_LEN - mp3buf_read;
819 if(!filling && unplayed_space_left < MP3_LOW_WATER)
823 queue_post(&mpeg_queue, MPEG_NEED_DATA, 0);
829 if(unplayed_space_left)
833 last_dma_chunk_size = MIN(65536, unplayed_space_left);
835 last_dma_chunk_size = MIN(last_dma_chunk_size, space_until_end_of_buffer);
837 DTCR3 = last_dma_chunk_size & 0xffff;
839 SAR3 = (unsigned int)mp3buf + mp3buf_read;
843 else
847 debugf("No more MP3 data. Stopping.\n");
849 CHCR3 = 0; /* Stop DMA interrupt */
857 CHCR3 &= ~0x0002; /* Clear DMA interrupt */
863 static void mas_poll_start(unsigned int interval_in_ms)
867 unsigned int count;
871 count = FREQ / 1000 / 8 * interval_in_ms;
875 if(count > 0xffff)
879 panicf("Error! The MAS poll interval is too long (%d ms)\n",
881 interval_in_ms);
883 return;
889 /* We are using timer 1 */
893 TSTR &= ~0x02; /* Stop the timer */
895 TSNC &= ~0x02; /* No synchronization */
897 TMDR &= ~0x02; /* Operate normally */
901 TCNT1 = 0; /* Start counting at 0 */
903 GRA1 = count;
905 TCR1 = 0x23; /* Clear at GRA match, sysclock/8 */
909 /* Enable interrupt on level 2 */
911 IPRC = (IPRC & ~0x000f) | 0x0002;
915 TSR1 &= ~0x02;
917 TIER1 = 0xf9; /* Enable GRA match interrupt */
921 TSTR |= 0x02; /* Start timer 2 */
927 void IMIA1(void) __attribute__((interrupt_handler));
929 void IMIA1(void)
933 dma_tick();
935 TSR1 &= ~0x01;
941 int track_index = 0;
943 char *peek_next_track(int index)
947 if(track_index < num_tracks)
949 return tracks[track_index+index];
951 else
953 return NULL;
959 void next_track(void)
963 track_index++;
969 int mpeg_file = -1;
973 int new_file(void)
977 char *trackname;
981 trackname = peek_next_track(0);
985 debugf("playing %s\n", trackname);
987 mpeg_file = open(trackname, O_RDONLY);
989 if(mpeg_file < 0)
993 debugf("Couldn't open file\n");
995 return -1;
999 return 0;
1005 void mpeg_thread(void)
1009 struct queue_event ev;
1011 int len;
1013 int free_space_left;
1015 int amount_to_read;
1017 bool play_pending;
1021 play_pending = false;
1023 playing = false;
1027 while(1)
1031 debugf("S\n");
1033 queue_wait(&mpeg_queue, &ev);
1035 switch(ev.id)
1039 case MPEG_PLAY:
1041 /* Stop the current stream */
1043 play_pending = false;
1045 playing = false;
1047 stop_dma();
1051 reset_mp3_buffer();
1055 new_file();
1059 /* Make it read more data */
1061 filling = true;
1063 queue_post(&mpeg_queue, MPEG_NEED_DATA, 0);
1067 /* Tell the file loading code that we want to start playing
1069 as soon as we have some data */
1071 play_pending = true;
1073 break;
1077 case MPEG_STOP:
1079 /* Stop the current stream */
1081 playing = false;
1083 stop_dma();
1085 break;
1089 case MPEG_PAUSE:
1091 /* Stop the current stream */
1093 playing = false;
1095 stop_dma();
1097 break;
1101 case MPEG_RESUME:
1103 /* Stop the current stream */
1105 playing = true;
1107 start_dma();
1109 break;
1113 case MPEG_NEED_DATA:
1115 free_space_left = mp3buf_read - mp3buf_write;
1119 /* We interpret 0 as "empty buffer" */
1121 if(free_space_left <= 0)
1123 free_space_left = MP3BUF_LEN + free_space_left;
1127 if(free_space_left <= MP3_CHUNK_SIZE)
1131 debugf("0\n");
1133 ata_spindown(-1);
1135 filling = false;
1137 break;
1143 amount_to_read = MIN(MP3_CHUNK_SIZE, free_space_left);
1145 amount_to_read = MIN(MP3BUF_LEN - mp3buf_write, amount_to_read);
1149 /* Read in a few seconds worth of MP3 data. We don't want to
1151 read too large chunks because the bitswapping will take
1153 too much time. We must keep the DMA happy and also give
1155 the other threads a chance to run. */
1157 debugf("R\n");
1159 len = read(mpeg_file, mp3buf+mp3buf_write, amount_to_read);
1161 if(len)
1165 debugf("B\n");
1167 bitswap(mp3buf + mp3buf_write, len);
1171 mp3buf_write += len;
1173 if(mp3buf_write >= MP3BUF_LEN)
1177 mp3buf_write = 0;
1179 debugf("W\n");
1185 /* Tell ourselves that we want more data */
1187 queue_post(&mpeg_queue, MPEG_NEED_DATA, 0);
1191 /* And while we're at it, see if we have startet playing
1193 yet. If not, do it. */
1195 if(play_pending)
1199 play_pending = false;
1201 playing = true;
1205 init_dma();
1207 start_dma();
1213 else
1217 close(mpeg_file);
1221 /* Make sure that the write pointer is at a word
1223 boundary */
1225 mp3buf_write &= 0xfffffffe;
1229 next_track();
1231 if(new_file() < 0)
1235 /* No more data to play */
1237 debugf("Finished playing\n");
1239 playing = false;
1241 ata_spindown(-1);
1243 filling = false;
1247 else
1251 /* Tell ourselves that we want more data */
1253 queue_post(&mpeg_queue, MPEG_NEED_DATA, 0);
1259 break;
1269 /* Newlib trap honeypot */
1271 void __trap34(void)
1275 debugf("newlib trap34\n");
1277 while(1);