Added "check that the bug isnt already fixed".
[kugel-rb.git] / firmware / mp3_playback.c
blob5d43458445ee7121aa3d09776e8e194d465c1862
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Code that has been in mpeg.c before, now creating an encapsulated play
11 * data module, to be used by other sources than file playback as well.
13 * Copyright (C) 2004 by Linus Nielsen Feltzing
15 * All files in this archive are subject to the GNU General Public License.
16 * See the file COPYING in the source tree root for full license agreement.
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
21 ****************************************************************************/
22 #include <stdbool.h>
23 #include "config.h"
24 #include "debug.h"
25 #include "panic.h"
26 #include <kernel.h>
27 #include "mpeg.h" /* ToDo: remove crosslinks */
28 #include "mp3_playback.h"
29 #ifndef SIMULATOR
30 #include "i2c.h"
31 #include "mas.h"
32 #include "dac.h"
33 #include "system.h"
34 #include "hwcompat.h"
35 #endif
37 /* hacking into mpeg.c, recording is still there */
38 #ifdef HAVE_MAS3587F
39 enum
41 MPEG_DECODER,
42 MPEG_ENCODER
43 } mpeg_mode;
45 unsigned long shadow_7f1;
47 #endif /* #ifdef HAVE_MAS3587F */
49 /**** globals ****/
51 /* own version, independent of mpeg.c */
52 static bool paused; /* playback is paused */
53 static bool playing; /* We are playing an MP3 stream */
55 #ifndef SIMULATOR
56 /* for measuring the play time */
57 static long playstart_tick;
58 static long cumulative_ticks;
60 /* the registered callback function to ask for more mp3 data */
61 static void (*callback_for_more)(unsigned char**, int*);
62 #endif /* #ifndef SIMULATOR */
64 static char *units[] =
66 "%", /* Volume */
67 "dB", /* Bass */
68 "dB", /* Treble */
69 "%", /* Balance */
70 "dB", /* Loudness */
71 "%", /* Bass boost */
72 "", /* AVC */
73 "", /* Channels */
74 "dB", /* Left gain */
75 "dB", /* Right gain */
76 "dB", /* Mic gain */
79 static int numdecimals[] =
81 0, /* Volume */
82 0, /* Bass */
83 0, /* Treble */
84 0, /* Balance */
85 0, /* Loudness */
86 0, /* Bass boost */
87 0, /* AVC */
88 0, /* Channels */
89 1, /* Left gain */
90 1, /* Right gain */
91 1, /* Mic gain */
94 static int minval[] =
96 0, /* Volume */
97 #ifdef HAVE_MAS3587F
98 -12, /* Bass */
99 -12, /* Treble */
100 #else
101 -15, /* Bass */
102 -15, /* Treble */
103 #endif
104 -100, /* Balance */
105 0, /* Loudness */
106 0, /* Bass boost */
107 -1, /* AVC */
108 0, /* Channels */
109 0, /* Left gain */
110 0, /* Right gain */
111 0, /* Mic gain */
114 static int maxval[] =
116 100, /* Volume */
117 #ifdef HAVE_MAS3587F
118 12, /* Bass */
119 12, /* Treble */
120 #else
121 15, /* Bass */
122 15, /* Treble */
123 #endif
124 100, /* Balance */
125 17, /* Loudness */
126 100, /* Bass boost */
127 4, /* AVC */
128 6, /* Channels */
129 15, /* Left gain */
130 15, /* Right gain */
131 15, /* Mic gain */
134 static int defaultval[] =
136 70, /* Volume */
137 #ifdef HAVE_MAS3587F
138 6, /* Bass */
139 6, /* Treble */
140 #else
141 7, /* Bass */
142 7, /* Treble */
143 #endif
144 0, /* Balance */
145 0, /* Loudness */
146 0, /* Bass boost */
147 0, /* AVC */
148 0, /* Channels */
149 8, /* Left gain */
150 8, /* Right gain */
151 2, /* Mic gain */
154 char *mpeg_sound_unit(int setting)
156 return units[setting];
159 int mpeg_sound_numdecimals(int setting)
161 return numdecimals[setting];
164 int mpeg_sound_min(int setting)
166 return minval[setting];
169 int mpeg_sound_max(int setting)
171 return maxval[setting];
174 int mpeg_sound_default(int setting)
176 return defaultval[setting];
179 /* list of tracks in memory */
180 #define MAX_ID3_TAGS (1<<4) /* Must be power of 2 */
181 #define MAX_ID3_TAGS_MASK (MAX_ID3_TAGS - 1)
183 #ifndef SIMULATOR
184 static bool mpeg_is_initialized = false;
185 #endif
187 #ifndef SIMULATOR
189 unsigned long mas_version_code;
191 #ifdef HAVE_MAS3507D
193 static unsigned int bass_table[] =
195 0x9e400, /* -15dB */
196 0xa2800, /* -14dB */
197 0xa7400, /* -13dB */
198 0xac400, /* -12dB */
199 0xb1800, /* -11dB */
200 0xb7400, /* -10dB */
201 0xbd400, /* -9dB */
202 0xc3c00, /* -8dB */
203 0xca400, /* -7dB */
204 0xd1800, /* -6dB */
205 0xd8c00, /* -5dB */
206 0xe0400, /* -4dB */
207 0xe8000, /* -3dB */
208 0xefc00, /* -2dB */
209 0xf7c00, /* -1dB */
211 0x800, /* 1dB */
212 0x10000, /* 2dB */
213 0x17c00, /* 3dB */
214 0x1f800, /* 4dB */
215 0x27000, /* 5dB */
216 0x2e400, /* 6dB */
217 0x35800, /* 7dB */
218 0x3c000, /* 8dB */
219 0x42800, /* 9dB */
220 0x48800, /* 10dB */
221 0x4e400, /* 11dB */
222 0x53800, /* 12dB */
223 0x58800, /* 13dB */
224 0x5d400, /* 14dB */
225 0x61800 /* 15dB */
228 static unsigned int treble_table[] =
230 0xb2c00, /* -15dB */
231 0xbb400, /* -14dB */
232 0xc1800, /* -13dB */
233 0xc6c00, /* -12dB */
234 0xcbc00, /* -11dB */
235 0xd0400, /* -10dB */
236 0xd5000, /* -9dB */
237 0xd9800, /* -8dB */
238 0xde000, /* -7dB */
239 0xe2800, /* -6dB */
240 0xe7e00, /* -5dB */
241 0xec000, /* -4dB */
242 0xf0c00, /* -3dB */
243 0xf5c00, /* -2dB */
244 0xfac00, /* -1dB */
246 0x5400, /* 1dB */
247 0xac00, /* 2dB */
248 0x10400, /* 3dB */
249 0x16000, /* 4dB */
250 0x1c000, /* 5dB */
251 0x22400, /* 6dB */
252 0x28400, /* 7dB */
253 0x2ec00, /* 8dB */
254 0x35400, /* 9dB */
255 0x3c000, /* 10dB */
256 0x42c00, /* 11dB */
257 0x49c00, /* 12dB */
258 0x51800, /* 13dB */
259 0x58400, /* 14dB */
260 0x5f800 /* 15dB */
263 static unsigned int prescale_table[] =
265 0x80000, /* 0db */
266 0x8e000, /* 1dB */
267 0x9a400, /* 2dB */
268 0xa5800, /* 3dB */
269 0xaf400, /* 4dB */
270 0xb8000, /* 5dB */
271 0xbfc00, /* 6dB */
272 0xc6c00, /* 7dB */
273 0xcd000, /* 8dB */
274 0xd25c0, /* 9dB */
275 0xd7800, /* 10dB */
276 0xdc000, /* 11dB */
277 0xdfc00, /* 12dB */
278 0xe3400, /* 13dB */
279 0xe6800, /* 14dB */
280 0xe9400 /* 15dB */
282 #endif
284 bool dma_on; /* The DMA is active */
286 #ifdef HAVE_MAS3507D
287 static void mas_poll_start(int interval_in_ms)
289 unsigned int count;
291 count = (FREQ * interval_in_ms) / 1000 / 8;
293 if(count > 0xffff)
295 panicf("Error! The MAS poll interval is too long (%d ms)\n",
296 interval_in_ms);
297 return;
300 /* We are using timer 1 */
302 TSTR &= ~0x02; /* Stop the timer */
303 TSNC &= ~0x02; /* No synchronization */
304 TMDR &= ~0x02; /* Operate normally */
306 TCNT1 = 0; /* Start counting at 0 */
307 GRA1 = count;
308 TCR1 = 0x23; /* Clear at GRA match, sysclock/8 */
310 /* Enable interrupt on level 5 */
311 IPRC = (IPRC & ~0x000f) | 0x0005;
313 TSR1 &= ~0x02;
314 TIER1 = 0xf9; /* Enable GRA match interrupt */
316 TSTR |= 0x02; /* Start timer 1 */
318 #else
319 static void postpone_dma_tick(void)
321 unsigned int count;
323 count = FREQ / 2000 / 8;
325 /* We are using timer 1 */
327 TSTR &= ~0x02; /* Stop the timer */
328 TSNC &= ~0x02; /* No synchronization */
329 TMDR &= ~0x02; /* Operate normally */
331 TCNT1 = 0; /* Start counting at 0 */
332 GRA1 = count;
333 TCR1 = 0x23; /* Clear at GRA match, sysclock/8 */
335 /* Enable interrupt on level 5 */
336 IPRC = (IPRC & ~0x000f) | 0x0005;
338 TSR1 &= ~0x02;
339 TIER1 = 0xf9; /* Enable GRA match interrupt */
341 TSTR |= 0x02; /* Start timer 1 */
343 #endif
346 #ifdef HAVE_MAS3587F
347 void demand_irq_enable(bool on)
349 int oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL);
351 if(on)
353 IPRA = (IPRA & 0xfff0) | 0x000b;
354 ICR &= ~0x0010; /* IRQ3 level sensitive */
356 else
357 IPRA &= 0xfff0;
359 set_irq_level(oldlevel);
361 #endif /* #ifdef HAVE_MAS3587F */
364 void play_tick(void)
366 if(playing && !paused)
368 /* Start DMA if it is disabled and the DEMAND pin is high */
369 if(!(SCR0 & 0x80) && (PBDR & 0x4000))
371 SCR0 |= 0x80;
374 playback_tick(); /* dirty call to mpeg.c */
378 #pragma interrupt
379 void DEI3(void)
381 unsigned char* start;
382 int size = 0;
384 if (callback_for_more != NULL)
386 callback_for_more(&start, &size);
389 if (size > 0)
391 DTCR3 = size & 0xffff;
392 SAR3 = (unsigned int) start;
394 else
396 CHCR3 &= ~0x0001; /* Disable the DMA interrupt */
399 CHCR3 &= ~0x0002; /* Clear DMA interrupt */
402 #pragma interrupt
403 void IMIA1(void) /* Timer 1 interrupt */
405 if(playing)
406 play_tick();
407 TSR1 &= ~0x01;
408 #ifdef HAVE_MAS3587F
409 /* Disable interrupt */
410 IPRC &= ~0x000f;
411 #endif /* #ifdef HAVE_MAS3587F */
414 #pragma interrupt
415 void IRQ6(void) /* PB14: MAS stop demand IRQ */
417 SCR0 &= ~0x80;
420 #ifdef HAVE_MAS3587F
421 #pragma interrupt
422 void IRQ3(void) /* PA15: MAS demand IRQ */
424 /* Begin with setting the IRQ to edge sensitive */
425 ICR |= 0x0010;
427 if(mpeg_mode == MPEG_ENCODER)
428 rec_tick();
429 else
430 postpone_dma_tick();
432 #endif /* #ifdef HAVE_MAS3587F */
434 static void setup_sci0(void)
436 /* PB15 is I/O, PB14 is IRQ6, PB12 is SCK0, PB9 is TxD0 */
437 PBCR1 = (PBCR1 & 0x0cff) | 0x1208;
439 /* Set PB12 to output */
440 or_b(0x10, &PBIORH);
442 /* Disable serial port */
443 SCR0 = 0x00;
445 /* Synchronous, no prescale */
446 SMR0 = 0x80;
448 /* Set baudrate 1Mbit/s */
449 BRR0 = 0x03;
451 /* use SCK as serial clock output */
452 SCR0 = 0x01;
454 /* Clear FER and PER */
455 SSR0 &= 0xe7;
457 /* Set interrupt ITU2 and SCI0 priority to 0 */
458 IPRD &= 0x0ff0;
460 /* set PB15 and PB14 to inputs */
461 and_b(~0x80, &PBIORH);
462 and_b(~0x40, &PBIORH);
464 /* Enable End of DMA interrupt at prio 8 */
465 IPRC = (IPRC & 0xf0ff) | 0x0800;
467 /* Enable Tx (only!) */
468 SCR0 |= 0x20;
470 #endif /* SIMULATOR */
472 #ifdef HAVE_MAS3587F
473 static void init_playback(void)
475 unsigned long val;
476 int rc;
478 mp3_play_pause(false);
480 mas_reset();
482 /* Enable the audio CODEC and the DSP core, max analog voltage range */
483 rc = mas_direct_config_write(MAS_CONTROL, 0x8c00);
484 if(rc < 0)
485 panicf("mas_ctrl_w: %d", rc);
487 /* Stop the current application */
488 val = 0;
489 mas_writemem(MAS_BANK_D0,0x7f6,&val,1);
492 mas_readmem(MAS_BANK_D0, 0x7f7, &val, 1);
493 } while(val);
495 /* Enable the D/A Converter */
496 mas_codec_writereg(0x0, 0x0001);
498 /* ADC scale 0%, DSP scale 100% */
499 mas_codec_writereg(6, 0x0000);
500 mas_codec_writereg(7, 0x4000);
502 /* Disable SDO and SDI */
503 val = 0x0d;
504 mas_writemem(MAS_BANK_D0,0x7f2,&val,1);
506 /* Set Demand mode and validate all settings */
507 val = 0x25;
508 mas_writemem(MAS_BANK_D0,0x7f1,&val,1);
510 /* Start the Layer2/3 decoder applications */
511 val = 0x0c;
512 mas_writemem(MAS_BANK_D0,0x7f6,&val,1);
515 mas_readmem(MAS_BANK_D0, 0x7f7, &val, 1);
516 } while((val & 0x0c) != 0x0c);
518 mpeg_sound_channel_config(MPEG_SOUND_STEREO);
520 mpeg_mode = MPEG_DECODER;
522 /* set IRQ6 to edge detect */
523 ICR |= 0x02;
525 /* set IRQ6 prio 8 */
526 IPRB = ( IPRB & 0xff0f ) | 0x0080;
528 DEBUGF("MAS Decoding application started\n");
530 #endif /* #ifdef HAVE_MAS3587F */
532 #ifndef SIMULATOR
533 #ifdef HAVE_MAS3507D
534 int current_left_volume = 0; /* all values in tenth of dB */
535 int current_right_volume = 0; /* all values in tenth of dB */
536 int current_treble = 0;
537 int current_bass = 0;
538 int current_balance = 0;
540 /* convert tenth of dB volume to register value */
541 static int tenthdb2reg(int db) {
542 if (db < -540)
543 return (db + 780) / 30;
544 else
545 return (db + 660) / 15;
548 void set_prescaled_volume(void)
550 int prescale;
551 int l, r;
553 prescale = MAX(current_bass, current_treble);
554 if (prescale < 0)
555 prescale = 0; /* no need to prescale if we don't boost
556 bass or treble */
558 mas_writereg(MAS_REG_KPRESCALE, prescale_table[prescale/10]);
560 /* gain up the analog volume to compensate the prescale reduction gain */
561 l = current_left_volume + prescale;
562 r = current_right_volume + prescale;
564 dac_volume(tenthdb2reg(l), tenthdb2reg(r), false);
566 #endif /* HAVE_MAS3507D */
567 #endif /* !SIMULATOR */
569 void mpeg_sound_set(int setting, int value)
571 #ifdef SIMULATOR
572 setting = value;
573 #else
574 #ifdef HAVE_MAS3507D
575 int l, r;
576 #else
577 int tmp;
578 #endif
580 if(!mpeg_is_initialized)
581 return;
583 switch(setting)
585 case SOUND_VOLUME:
586 #ifdef HAVE_MAS3587F
587 tmp = 0x7f00 * value / 100;
588 mas_codec_writereg(0x10, tmp & 0xff00);
589 #else
590 l = value;
591 r = value;
593 if(current_balance > 0)
595 l -= current_balance;
596 if(l < 0)
597 l = 0;
600 if(current_balance < 0)
602 r += current_balance;
603 if(r < 0)
604 r = 0;
607 l = 0x38 * l / 100;
608 r = 0x38 * r / 100;
610 /* store volume in tenth of dB */
611 current_left_volume = ( l < 0x08 ? l*30 - 780 : l*15 - 660 );
612 current_right_volume = ( r < 0x08 ? r*30 - 780 : r*15 - 660 );
614 set_prescaled_volume();
615 #endif
616 break;
618 case SOUND_BALANCE:
619 #ifdef HAVE_MAS3587F
620 tmp = ((value * 127 / 100) & 0xff) << 8;
621 mas_codec_writereg(0x11, tmp & 0xff00);
622 #endif
623 break;
625 case SOUND_BASS:
626 #ifdef HAVE_MAS3587F
627 tmp = ((value * 8) & 0xff) << 8;
628 mas_codec_writereg(0x14, tmp & 0xff00);
629 #else
630 mas_writereg(MAS_REG_KBASS, bass_table[value+15]);
631 current_bass = (value) * 10;
632 set_prescaled_volume();
633 #endif
634 break;
636 case SOUND_TREBLE:
637 #ifdef HAVE_MAS3587F
638 tmp = ((value * 8) & 0xff) << 8;
639 mas_codec_writereg(0x15, tmp & 0xff00);
640 #else
641 mas_writereg(MAS_REG_KTREBLE, treble_table[value+15]);
642 current_treble = (value) * 10;
643 set_prescaled_volume();
644 #endif
645 break;
647 #ifdef HAVE_MAS3587F
648 case SOUND_SUPERBASS:
649 if (value) {
650 tmp = MAX(MIN(value * 127 / 100, 0x7f), 0);
651 mas_codec_writereg(MAS_REG_KMDB_STR, (tmp & 0xff) << 8);
652 tmp = 0x30; /* MDB_HAR: Space for experiment here */
653 mas_codec_writereg(MAS_REG_KMDB_HAR, (tmp & 0xff) << 8);
654 tmp = 60 / 10; /* calculate MDB_FC, 60hz - experiment here,
655 this would depend on the earphones...
656 perhaps make it tunable? */
657 mas_codec_writereg(MAS_REG_KMDB_FC, (tmp & 0xff) << 8);
658 tmp = (3 * tmp) / 2; /* calculate MDB_SHAPE */
659 mas_codec_writereg(MAS_REG_KMDB_SWITCH,
660 ((tmp & 0xff) << 8) /* MDB_SHAPE */
661 | 2); /* MDB_SWITCH enable */
662 } else {
663 mas_codec_writereg(MAS_REG_KMDB_STR, 0);
664 mas_codec_writereg(MAS_REG_KMDB_HAR, 0);
665 mas_codec_writereg(MAS_REG_KMDB_SWITCH, 0); /* MDB_SWITCH disable */
667 break;
669 case SOUND_LOUDNESS:
670 tmp = MAX(MIN(value * 4, 0x44), 0);
671 mas_codec_writereg(MAS_REG_KLOUDNESS, (tmp & 0xff) << 8);
672 break;
674 case SOUND_AVC:
675 switch (value) {
676 case 1: /* 20ms */
677 tmp = (0x1 << 8) | (0x8 << 12);
678 break;
679 case 2: /* 2s */
680 tmp = (0x2 << 8) | (0x8 << 12);
681 break;
682 case 3: /* 4s */
683 tmp = (0x4 << 8) | (0x8 << 12);
684 break;
685 case 4: /* 8s */
686 tmp = (0x8 << 8) | (0x8 << 12);
687 break;
688 case -1: /* turn off and then turn on again to decay quickly */
689 tmp = mas_codec_readreg(MAS_REG_KAVC);
690 mas_codec_writereg(MAS_REG_KAVC, 0);
691 break;
692 default: /* off */
693 tmp = 0;
694 break;
696 mas_codec_writereg(MAS_REG_KAVC, tmp);
697 break;
698 #endif
699 case SOUND_CHANNELS:
700 mpeg_sound_channel_config(value);
701 break;
703 #endif /* SIMULATOR */
706 int mpeg_val2phys(int setting, int value)
708 #ifdef HAVE_MAS3587F
709 int result = 0;
711 switch(setting)
713 case SOUND_LEFT_GAIN:
714 case SOUND_RIGHT_GAIN:
715 result = (value - 2) * 15;
716 break;
718 case SOUND_MIC_GAIN:
719 result = value * 15 + 210;
720 break;
722 default:
723 result = value;
724 break;
726 return result;
727 #else
728 (void)setting;
729 return value;
730 #endif
733 void mpeg_sound_channel_config(int configuration)
735 #ifdef SIMULATOR
736 (void)configuration;
737 #else
738 unsigned long val_ll = 0x80000;
739 unsigned long val_lr = 0;
740 unsigned long val_rl = 0;
741 unsigned long val_rr = 0x80000;
743 switch(configuration)
745 case MPEG_SOUND_STEREO:
746 val_ll = 0x80000;
747 val_lr = 0;
748 val_rl = 0;
749 val_rr = 0x80000;
750 break;
752 case MPEG_SOUND_MONO:
753 val_ll = 0xc0000;
754 val_lr = 0xc0000;
755 val_rl = 0xc0000;
756 val_rr = 0xc0000;
757 break;
759 case MPEG_SOUND_MONO_LEFT:
760 val_ll = 0x80000;
761 val_lr = 0x80000;
762 val_rl = 0;
763 val_rr = 0;
764 break;
766 case MPEG_SOUND_MONO_RIGHT:
767 val_ll = 0;
768 val_lr = 0;
769 val_rl = 0x80000;
770 val_rr = 0x80000;
771 break;
773 case MPEG_SOUND_STEREO_NARROW:
774 val_ll = 0xa0000;
775 val_lr = 0xe0000;
776 val_rl = 0xe0000;
777 val_rr = 0xa0000;
778 break;
780 case MPEG_SOUND_STEREO_WIDE:
781 val_ll = 0x80000;
782 val_lr = 0x40000;
783 val_rl = 0x40000;
784 val_rr = 0x80000;
785 break;
787 case MPEG_SOUND_KARAOKE:
788 val_ll = 0x80001;
789 val_lr = 0x7ffff;
790 val_rl = 0x7ffff;
791 val_rr = 0x80001;
792 break;
795 #ifdef HAVE_MAS3587F
796 mas_writemem(MAS_BANK_D0, 0x7fc, &val_ll, 1); /* LL */
797 mas_writemem(MAS_BANK_D0, 0x7fd, &val_lr, 1); /* LR */
798 mas_writemem(MAS_BANK_D0, 0x7fe, &val_rl, 1); /* RL */
799 mas_writemem(MAS_BANK_D0, 0x7ff, &val_rr, 1); /* RR */
800 #else
801 mas_writemem(MAS_BANK_D1, 0x7f8, &val_ll, 1); /* LL */
802 mas_writemem(MAS_BANK_D1, 0x7f9, &val_lr, 1); /* LR */
803 mas_writemem(MAS_BANK_D1, 0x7fa, &val_rl, 1); /* RL */
804 mas_writemem(MAS_BANK_D1, 0x7fb, &val_rr, 1); /* RR */
805 #endif
806 #endif
809 #ifdef HAVE_MAS3587F
810 /* This function works by telling the decoder that we have another
811 crystal frequency than we actually have. It will adjust its internal
812 parameters and the result is that the audio is played at another pitch.
814 The pitch value is in tenths of percent.
816 void mpeg_set_pitch(int pitch)
818 unsigned long val;
820 /* invert pitch value */
821 pitch = 1000000/pitch;
823 /* Calculate the new (bogus) frequency */
824 val = 18432*pitch/1000;
826 mas_writemem(MAS_BANK_D0,0x7f3,&val,1);
828 /* We must tell the MAS that the frequency has changed.
829 This will unfortunately cause a short silence. */
830 mas_writemem(MAS_BANK_D0,0x7f1,&shadow_7f1,1);
832 #endif
834 void mp3_init(int volume, int bass, int treble, int balance, int loudness,
835 int bass_boost, int avc, int channel_config)
837 #ifdef SIMULATOR
838 volume = bass = treble = balance = loudness
839 = bass_boost = avc = channel_config;
840 #else
841 #ifdef HAVE_MAS3507D
842 unsigned long val;
843 loudness = bass_boost = avc;
844 #endif
846 setup_sci0();
848 #ifdef HAVE_MAS3587F
849 or_b(0x08, &PAIORH); /* output for /PR */
850 init_playback();
852 mas_version_code = mas_readver();
853 DEBUGF("MAS3587 derivate %d, version B%d\n",
854 (mas_version_code & 0xff00) >> 8, mas_version_code & 0xff);
855 #endif
857 #ifdef HAVE_DAC3550A
858 dac_init();
859 #endif
861 #ifdef HAVE_MAS3507D
862 and_b(~0x20, &PBDRL);
863 sleep(HZ/5);
864 or_b(0x20, &PBDRL);
865 sleep(HZ/5);
867 /* set IRQ6 to edge detect */
868 ICR |= 0x02;
870 /* set IRQ6 prio 8 */
871 IPRB = ( IPRB & 0xff0f ) | 0x0080;
873 mas_readmem(MAS_BANK_D1, 0xff7, &mas_version_code, 1);
875 mas_writereg(0x3b, 0x20); /* Don't ask why. The data sheet doesn't say */
876 mas_run(1);
877 sleep(HZ);
879 /* Clear the upper 12 bits of the 32-bit samples */
880 mas_writereg(0xc5, 0);
881 mas_writereg(0xc6, 0);
883 /* We need to set the PLL for a 14.1318MHz crystal */
884 if(mas_version_code == 0x0601) /* Version F10? */
886 val = 0x5d9d0;
887 mas_writemem(MAS_BANK_D0, 0x32d, &val, 1);
888 val = 0xfffceceb;
889 mas_writemem(MAS_BANK_D0, 0x32e, &val, 1);
890 val = 0x0;
891 mas_writemem(MAS_BANK_D0, 0x32f, &val, 1);
892 mas_run(0x475);
894 else
896 val = 0x5d9d0;
897 mas_writemem(MAS_BANK_D0, 0x36d, &val, 1);
898 val = 0xfffceceb;
899 mas_writemem(MAS_BANK_D0, 0x36e, &val, 1);
900 val = 0x0;
901 mas_writemem(MAS_BANK_D0, 0x36f, &val, 1);
902 mas_run(0xfcb);
905 #endif
907 #ifdef HAVE_MAS3507D
908 mas_poll_start(1);
910 mas_writereg(MAS_REG_KPRESCALE, 0xe9400);
911 dac_enable(true);
913 mpeg_sound_channel_config(channel_config);
914 #endif
916 #ifdef HAVE_MAS3587F
917 ICR &= ~0x0010; /* IRQ3 level sensitive */
918 PACR1 = (PACR1 & 0x3fff) | 0x4000; /* PA15 is IRQ3 */
919 #endif
921 /* Must be done before calling mpeg_sound_set() */
922 mpeg_is_initialized = true;
924 mpeg_sound_set(SOUND_BASS, bass);
925 mpeg_sound_set(SOUND_TREBLE, treble);
926 mpeg_sound_set(SOUND_BALANCE, balance);
927 mpeg_sound_set(SOUND_VOLUME, volume);
929 #ifdef HAVE_MAS3587F
930 mpeg_sound_channel_config(channel_config);
931 mpeg_sound_set(SOUND_LOUDNESS, loudness);
932 mpeg_sound_set(SOUND_SUPERBASS, bass_boost);
933 mpeg_sound_set(SOUND_AVC, avc);
934 #endif
935 #endif /* !SIMULATOR */
937 playing = false;
938 paused = true;
942 /* new functions, to be exported to plugin API */
944 #ifndef SIMULATOR
946 void mp3_play_init(void)
948 #ifdef HAVE_MAS3587F
949 init_playback();
950 #endif
951 playing = false;
952 paused = true;
953 callback_for_more = NULL;
954 mp3_reset_playtime();
957 void mp3_play_data(unsigned char* start, int size,
958 void (*get_more)(unsigned char** start, int* size) /* callback fn */
961 /* init DMA */
962 DAR3 = 0x5FFFEC3;
963 CHCR3 &= ~0x0002; /* Clear interrupt */
964 CHCR3 = 0x1504; /* Single address destination, TXI0, IE=1 */
965 DMAOR = 0x0001; /* Enable DMA */
967 callback_for_more = get_more;
969 SAR3 = (unsigned int)start;
970 DTCR3 = size & 0xffff;
972 playing = true;
973 paused = true;
975 CHCR3 |= 0x0001; /* Enable DMA IRQ */
977 #ifdef HAVE_MAS3587F
978 demand_irq_enable(true);
979 #endif
982 void mp3_play_pause(bool play)
984 if (paused && play)
985 { /* resume playback */
986 SCR0 |= 0x80;
987 paused = false;
988 playstart_tick = current_tick;
990 else if (!paused && !play)
991 { /* stop playback */
992 SCR0 &= 0x7f;
993 paused = true;
994 cumulative_ticks += current_tick - playstart_tick;
998 void mp3_play_stop(void)
1000 playing = false;
1001 mp3_play_pause(false);
1002 CHCR3 &= ~0x0001; /* Disable the DMA interrupt */
1003 #ifdef HAVE_MAS3587F
1004 demand_irq_enable(false);
1005 #endif
1008 long mp3_get_playtime(void)
1010 if (paused)
1011 return cumulative_ticks;
1012 else
1013 return cumulative_ticks + current_tick - playstart_tick;
1016 void mp3_reset_playtime(void)
1018 cumulative_ticks = 0;
1019 playstart_tick = current_tick;
1023 bool mp3_is_playing(void)
1025 return playing;
1029 /* returns the next byte position which would be transferred */
1030 unsigned char* mp3_get_pos(void)
1032 return (unsigned char*)SAR3;
1036 #endif /* #ifndef SIMULATOR */