summaryrefslogtreecommitdiff
path: root/firmware/mp3_playback.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/mp3_playback.c')
-rw-r--r--firmware/mp3_playback.c939
1 files changed, 939 insertions, 0 deletions
diff --git a/firmware/mp3_playback.c b/firmware/mp3_playback.c
new file mode 100644
index 0000000000..9ded720248
--- /dev/null
+++ b/firmware/mp3_playback.c
@@ -0,0 +1,939 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
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.
12 *
13 * Copyright (C) 2004 by Linus Nielsen Feltzing
14 *
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.
17 *
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
20 *
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
36
37static char *units[] =
38{
39 "%", /* Volume */
40 "dB", /* Bass */
41 "dB", /* Treble */
42 "%", /* Balance */
43 "dB", /* Loudness */
44 "%", /* Bass boost */
45 "", /* AVC */
46 "", /* Channels */
47 "dB", /* Left gain */
48 "dB", /* Right gain */
49 "dB", /* Mic gain */
50};
51
52static int numdecimals[] =
53{
54 0, /* Volume */
55 0, /* Bass */
56 0, /* Treble */
57 0, /* Balance */
58 0, /* Loudness */
59 0, /* Bass boost */
60 0, /* AVC */
61 0, /* Channels */
62 1, /* Left gain */
63 1, /* Right gain */
64 1, /* Mic gain */
65};
66
67static int minval[] =
68{
69 0, /* Volume */
70 0, /* Bass */
71 0, /* Treble */
72 -50, /* Balance */
73 0, /* Loudness */
74 0, /* Bass boost */
75 -1, /* AVC */
76 0, /* Channels */
77 0, /* Left gain */
78 0, /* Right gain */
79 0, /* Mic gain */
80};
81
82static int maxval[] =
83{
84 100, /* Volume */
85#ifdef HAVE_MAS3587F
86 24, /* Bass */
87 24, /* Treble */
88#else
89 30, /* Bass */
90 30, /* Treble */
91#endif
92 50, /* Balance */
93 17, /* Loudness */
94 10, /* Bass boost */
95 3, /* AVC */
96 6, /* Channels */
97 15, /* Left gain */
98 15, /* Right gain */
99 15, /* Mic gain */
100};
101
102static int defaultval[] =
103{
104 70, /* Volume */
105#ifdef HAVE_MAS3587F
106 12+6, /* Bass */
107 12+6, /* Treble */
108#else
109 15+7, /* Bass */
110 15+7, /* Treble */
111#endif
112 0, /* Balance */
113 0, /* Loudness */
114 0, /* Bass boost */
115 0, /* AVC */
116 0, /* Channels */
117 8, /* Left gain */
118 8, /* Right gain */
119 2, /* Mic gain */
120};
121
122char *mpeg_sound_unit(int setting)
123{
124 return units[setting];
125}
126
127int mpeg_sound_numdecimals(int setting)
128{
129 return numdecimals[setting];
130}
131
132int mpeg_sound_min(int setting)
133{
134 return minval[setting];
135}
136
137int mpeg_sound_max(int setting)
138{
139 return maxval[setting];
140}
141
142int mpeg_sound_default(int setting)
143{
144 return defaultval[setting];
145}
146
147/* list of tracks in memory */
148#define MAX_ID3_TAGS (1<<4) /* Must be power of 2 */
149#define MAX_ID3_TAGS_MASK (MAX_ID3_TAGS - 1)
150
151#ifndef SIMULATOR
152static bool mpeg_is_initialized = false;
153#endif
154
155#ifndef SIMULATOR
156
157unsigned long mas_version_code;
158
159#ifdef HAVE_MAS3507D
160
161static unsigned int bass_table[] =
162{
163 0x9e400, /* -15dB */
164 0xa2800, /* -14dB */
165 0xa7400, /* -13dB */
166 0xac400, /* -12dB */
167 0xb1800, /* -11dB */
168 0xb7400, /* -10dB */
169 0xbd400, /* -9dB */
170 0xc3c00, /* -8dB */
171 0xca400, /* -7dB */
172 0xd1800, /* -6dB */
173 0xd8c00, /* -5dB */
174 0xe0400, /* -4dB */
175 0xe8000, /* -3dB */
176 0xefc00, /* -2dB */
177 0xf7c00, /* -1dB */
178 0,
179 0x800, /* 1dB */
180 0x10000, /* 2dB */
181 0x17c00, /* 3dB */
182 0x1f800, /* 4dB */
183 0x27000, /* 5dB */
184 0x2e400, /* 6dB */
185 0x35800, /* 7dB */
186 0x3c000, /* 8dB */
187 0x42800, /* 9dB */
188 0x48800, /* 10dB */
189 0x4e400, /* 11dB */
190 0x53800, /* 12dB */
191 0x58800, /* 13dB */
192 0x5d400, /* 14dB */
193 0x61800 /* 15dB */
194};
195
196static unsigned int treble_table[] =
197{
198 0xb2c00, /* -15dB */
199 0xbb400, /* -14dB */
200 0xc1800, /* -13dB */
201 0xc6c00, /* -12dB */
202 0xcbc00, /* -11dB */
203 0xd0400, /* -10dB */
204 0xd5000, /* -9dB */
205 0xd9800, /* -8dB */
206 0xde000, /* -7dB */
207 0xe2800, /* -6dB */
208 0xe7e00, /* -5dB */
209 0xec000, /* -4dB */
210 0xf0c00, /* -3dB */
211 0xf5c00, /* -2dB */
212 0xfac00, /* -1dB */
213 0,
214 0x5400, /* 1dB */
215 0xac00, /* 2dB */
216 0x10400, /* 3dB */
217 0x16000, /* 4dB */
218 0x1c000, /* 5dB */
219 0x22400, /* 6dB */
220 0x28400, /* 7dB */
221 0x2ec00, /* 8dB */
222 0x35400, /* 9dB */
223 0x3c000, /* 10dB */
224 0x42c00, /* 11dB */
225 0x49c00, /* 12dB */
226 0x51800, /* 13dB */
227 0x58400, /* 14dB */
228 0x5f800 /* 15dB */
229};
230
231static unsigned int prescale_table[] =
232{
233 0x80000, /* 0db */
234 0x8e000, /* 1dB */
235 0x9a400, /* 2dB */
236 0xa5800, /* 3dB */
237 0xaf400, /* 4dB */
238 0xb8000, /* 5dB */
239 0xbfc00, /* 6dB */
240 0xc6c00, /* 7dB */
241 0xcd000, /* 8dB */
242 0xd25c0, /* 9dB */
243 0xd7800, /* 10dB */
244 0xdc000, /* 11dB */
245 0xdfc00, /* 12dB */
246 0xe3400, /* 13dB */
247 0xe6800, /* 14dB */
248 0xe9400 /* 15dB */
249};
250#endif
251
252bool dma_on; /* The DMA is active */
253
254#ifdef HAVE_MAS3507D
255static void mas_poll_start(int interval_in_ms)
256{
257 unsigned int count;
258
259 count = (FREQ * interval_in_ms) / 1000 / 8;
260
261 if(count > 0xffff)
262 {
263 panicf("Error! The MAS poll interval is too long (%d ms)\n",
264 interval_in_ms);
265 return;
266 }
267
268 /* We are using timer 1 */
269
270 TSTR &= ~0x02; /* Stop the timer */
271 TSNC &= ~0x02; /* No synchronization */
272 TMDR &= ~0x02; /* Operate normally */
273
274 TCNT1 = 0; /* Start counting at 0 */
275 GRA1 = count;
276 TCR1 = 0x23; /* Clear at GRA match, sysclock/8 */
277
278 /* Enable interrupt on level 5 */
279 IPRC = (IPRC & ~0x000f) | 0x0005;
280
281 TSR1 &= ~0x02;
282 TIER1 = 0xf9; /* Enable GRA match interrupt */
283
284 TSTR |= 0x02; /* Start timer 1 */
285}
286#endif
287
288/* the registered callback function ta ask for more mp3 data */
289static void (*callback_for_more)(unsigned char**, int*);
290
291#pragma interrupt
292void DEI3(void)
293{
294 unsigned char* start;
295 int size = 0;
296
297 if (callback_for_more != NULL)
298 {
299 callback_for_more(&start, &size);
300 }
301
302 if (size > 0)
303 {
304 DTCR3 = size & 0xffff;
305 SAR3 = (unsigned int) start;
306 }
307 else
308 {
309 CHCR3 &= ~0x0001; /* Disable the DMA interrupt */
310 }
311
312 CHCR3 &= ~0x0002; /* Clear DMA interrupt */
313}
314
315#pragma interrupt
316void IRQ6(void) /* PB14: MAS stop demand IRQ */
317{
318 mp3_play_pause(false);
319}
320
321static void setup_sci0(void)
322{
323 /* PB15 is I/O, PB14 is IRQ6, PB12 is SCK0, PB9 is TxD0 */
324 PBCR1 = (PBCR1 & 0x0cff) | 0x1208;
325
326 /* Set PB12 to output */
327 or_b(0x10, &PBIORH);
328
329 /* Disable serial port */
330 SCR0 = 0x00;
331
332 /* Synchronous, no prescale */
333 SMR0 = 0x80;
334
335 /* Set baudrate 1Mbit/s */
336 BRR0 = 0x03;
337
338 /* use SCK as serial clock output */
339 SCR0 = 0x01;
340
341 /* Clear FER and PER */
342 SSR0 &= 0xe7;
343
344 /* Set interrupt ITU2 and SCI0 priority to 0 */
345 IPRD &= 0x0ff0;
346
347 /* set PB15 and PB14 to inputs */
348 and_b(~0x80, &PBIORH);
349 and_b(~0x40, &PBIORH);
350
351 /* Enable End of DMA interrupt at prio 8 */
352 IPRC = (IPRC & 0xf0ff) | 0x0800;
353
354 /* Enable Tx (only!) */
355 SCR0 |= 0x20;
356}
357#endif /* SIMULATOR */
358
359#ifdef HAVE_MAS3587F
360static void init_playback(void)
361{
362 unsigned long val;
363 int rc;
364
365 mp3_play_pause(false);
366
367 mas_reset();
368
369 /* Enable the audio CODEC and the DSP core, max analog voltage range */
370 rc = mas_direct_config_write(MAS_CONTROL, 0x8c00);
371 if(rc < 0)
372 panicf("mas_ctrl_w: %d", rc);
373
374 /* Stop the current application */
375 val = 0;
376 mas_writemem(MAS_BANK_D0,0x7f6,&val,1);
377 do
378 {
379 mas_readmem(MAS_BANK_D0, 0x7f7, &val, 1);
380 } while(val);
381
382 /* Enable the D/A Converter */
383 mas_codec_writereg(0x0, 0x0001);
384
385 /* ADC scale 0%, DSP scale 100% */
386 mas_codec_writereg(6, 0x0000);
387 mas_codec_writereg(7, 0x4000);
388
389 /* Disable SDO and SDI */
390 val = 0x0d;
391 mas_writemem(MAS_BANK_D0,0x7f2,&val,1);
392
393 /* Set Demand mode and validate all settings */
394 val = 0x25;
395 mas_writemem(MAS_BANK_D0,0x7f1,&val,1);
396
397 /* Start the Layer2/3 decoder applications */
398 val = 0x0c;
399 mas_writemem(MAS_BANK_D0,0x7f6,&val,1);
400 do
401 {
402 mas_readmem(MAS_BANK_D0, 0x7f7, &val, 1);
403 } while((val & 0x0c) != 0x0c);
404
405 mpeg_sound_channel_config(MPEG_SOUND_STEREO);
406
407 /* set IRQ6 to edge detect */
408 ICR |= 0x02;
409
410 /* set IRQ6 prio 8 */
411 IPRB = ( IPRB & 0xff0f ) | 0x0080;
412
413 DEBUGF("MAS Decoding application started\n");
414}
415#endif /* #ifdef HAVE_MAS3587F */
416
417#ifndef SIMULATOR
418#ifdef HAVE_MAS3507D
419int current_left_volume = 0; /* all values in tenth of dB */
420int current_right_volume = 0; /* all values in tenth of dB */
421int current_treble = 0;
422int current_bass = 0;
423int current_balance = 0;
424
425/* convert tenth of dB volume to register value */
426static int tenthdb2reg(int db) {
427 if (db < -540)
428 return (db + 780) / 30;
429 else
430 return (db + 660) / 15;
431}
432
433void set_prescaled_volume(void)
434{
435 int prescale;
436 int l, r;
437
438 prescale = MAX(current_bass, current_treble);
439 if (prescale < 0)
440 prescale = 0; /* no need to prescale if we don't boost
441 bass or treble */
442
443 mas_writereg(MAS_REG_KPRESCALE, prescale_table[prescale/10]);
444
445 /* gain up the analog volume to compensate the prescale reduction gain */
446 l = current_left_volume + prescale;
447 r = current_right_volume + prescale;
448
449 dac_volume(tenthdb2reg(l), tenthdb2reg(r), false);
450}
451#endif /* HAVE_MAS3507D */
452#endif /* !SIMULATOR */
453
454void mpeg_sound_set(int setting, int value)
455{
456#ifdef SIMULATOR
457 setting = value;
458#else
459#ifdef HAVE_MAS3507D
460 int l, r;
461#else
462 int tmp;
463#endif
464
465 if(!mpeg_is_initialized)
466 return;
467
468 switch(setting)
469 {
470 case SOUND_VOLUME:
471#ifdef HAVE_MAS3587F
472 tmp = 0x7f00 * value / 100;
473 mas_codec_writereg(0x10, tmp & 0xff00);
474#else
475 l = value;
476 r = value;
477
478 if(current_balance > 0)
479 {
480 l -= current_balance;
481 if(l < 0)
482 l = 0;
483 }
484
485 if(current_balance < 0)
486 {
487 r += current_balance;
488 if(r < 0)
489 r = 0;
490 }
491
492 l = 0x38 * l / 100;
493 r = 0x38 * r / 100;
494
495 /* store volume in tenth of dB */
496 current_left_volume = ( l < 0x08 ? l*30 - 780 : l*15 - 660 );
497 current_right_volume = ( r < 0x08 ? r*30 - 780 : r*15 - 660 );
498
499 set_prescaled_volume();
500#endif
501 break;
502
503 case SOUND_BALANCE:
504#ifdef HAVE_MAS3587F
505 tmp = ((value * 127 / 100) & 0xff) << 8;
506 mas_codec_writereg(0x11, tmp & 0xff00);
507#else
508 /* Convert to percent */
509 current_balance = value * 2;
510#endif
511 break;
512
513 case SOUND_BASS:
514#ifdef HAVE_MAS3587F
515 tmp = (((value-12) * 8) & 0xff) << 8;
516 mas_codec_writereg(0x14, tmp & 0xff00);
517#else
518 mas_writereg(MAS_REG_KBASS, bass_table[value]);
519 current_bass = (value-15) * 10;
520 set_prescaled_volume();
521#endif
522 break;
523
524 case SOUND_TREBLE:
525#ifdef HAVE_MAS3587F
526 tmp = (((value-12) * 8) & 0xff) << 8;
527 mas_codec_writereg(0x15, tmp & 0xff00);
528#else
529 mas_writereg(MAS_REG_KTREBLE, treble_table[value]);
530 current_treble = (value-15) * 10;
531 set_prescaled_volume();
532#endif
533 break;
534
535#ifdef HAVE_MAS3587F
536 case SOUND_SUPERBASS:
537 if (value) {
538 tmp = MAX(MIN(value * 12, 0x7f), 0);
539 mas_codec_writereg(MAS_REG_KMDB_STR, (tmp & 0xff) << 8);
540 tmp = 0x30; /* MDB_HAR: Space for experiment here */
541 mas_codec_writereg(MAS_REG_KMDB_HAR, (tmp & 0xff) << 8);
542 tmp = 60 / 10; /* calculate MDB_FC, 60hz - experiment here,
543 this would depend on the earphones...
544 perhaps make it tunable? */
545 mas_codec_writereg(MAS_REG_KMDB_FC, (tmp & 0xff) << 8);
546 tmp = (3 * tmp) / 2; /* calculate MDB_SHAPE */
547 mas_codec_writereg(MAS_REG_KMDB_SWITCH,
548 ((tmp & 0xff) << 8) /* MDB_SHAPE */
549 | 2); /* MDB_SWITCH enable */
550 } else {
551 mas_codec_writereg(MAS_REG_KMDB_STR, 0);
552 mas_codec_writereg(MAS_REG_KMDB_HAR, 0);
553 mas_codec_writereg(MAS_REG_KMDB_SWITCH, 0); /* MDB_SWITCH disable */
554 }
555 break;
556
557 case SOUND_LOUDNESS:
558 tmp = MAX(MIN(value * 4, 0x44), 0);
559 mas_codec_writereg(MAS_REG_KLOUDNESS, (tmp & 0xff) << 8);
560 break;
561
562 case SOUND_AVC:
563 switch (value) {
564 case 1: /* 2s */
565 tmp = (0x2 << 8) | (0x8 << 12);
566 break;
567 case 2: /* 4s */
568 tmp = (0x4 << 8) | (0x8 << 12);
569 break;
570 case 3: /* 8s */
571 tmp = (0x8 << 8) | (0x8 << 12);
572 break;
573 case -1: /* turn off and then turn on again to decay quickly */
574 tmp = mas_codec_readreg(MAS_REG_KAVC);
575 mas_codec_writereg(MAS_REG_KAVC, 0);
576 break;
577 default: /* off */
578 tmp = 0;
579 break;
580 }
581 mas_codec_writereg(MAS_REG_KAVC, tmp);
582 break;
583#endif
584 case SOUND_CHANNELS:
585 mpeg_sound_channel_config(value);
586 break;
587 }
588#endif /* SIMULATOR */
589}
590
591int mpeg_val2phys(int setting, int value)
592{
593 int result = 0;
594
595 switch(setting)
596 {
597 case SOUND_VOLUME:
598 result = value;
599 break;
600
601 case SOUND_BALANCE:
602 result = value * 2;
603 break;
604
605 case SOUND_BASS:
606#ifdef HAVE_MAS3587F
607 result = value - 12;
608#else
609 result = value - 15;
610#endif
611 break;
612
613 case SOUND_TREBLE:
614#ifdef HAVE_MAS3587F
615 result = value - 12;
616#else
617 result = value - 15;
618#endif
619 break;
620
621#ifdef HAVE_MAS3587F
622 case SOUND_LOUDNESS:
623 result = value;
624 break;
625
626 case SOUND_SUPERBASS:
627 result = value * 10;
628 break;
629
630 case SOUND_LEFT_GAIN:
631 case SOUND_RIGHT_GAIN:
632 result = (value - 2) * 15;
633 break;
634
635 case SOUND_MIC_GAIN:
636 result = value * 15 + 210;
637 break;
638#endif
639 }
640 return result;
641}
642
643int mpeg_phys2val(int setting, int value)
644{
645 int result = 0;
646
647 switch(setting)
648 {
649 case SOUND_VOLUME:
650 result = value;
651 break;
652
653 case SOUND_BALANCE:
654 result = value / 2;
655 break;
656
657 case SOUND_BASS:
658#ifdef HAVE_MAS3587F
659 result = value + 12;
660#else
661 result = value + 15;
662#endif
663 break;
664
665 case SOUND_TREBLE:
666#ifdef HAVE_MAS3587F
667 result = value + 12;
668#else
669 result = value + 15;
670#endif
671 break;
672
673#ifdef HAVE_MAS3587F
674 case SOUND_SUPERBASS:
675 result = value / 10;
676 break;
677
678 case SOUND_LOUDNESS:
679 case SOUND_AVC:
680 case SOUND_LEFT_GAIN:
681 case SOUND_RIGHT_GAIN:
682 case SOUND_MIC_GAIN:
683 result = value;
684 break;
685#endif
686 }
687
688 return result;
689}
690
691
692void mpeg_sound_channel_config(int configuration)
693{
694#ifdef SIMULATOR
695 (void)configuration;
696#else
697 unsigned long val_ll = 0x80000;
698 unsigned long val_lr = 0;
699 unsigned long val_rl = 0;
700 unsigned long val_rr = 0x80000;
701
702 switch(configuration)
703 {
704 case MPEG_SOUND_STEREO:
705 val_ll = 0x80000;
706 val_lr = 0;
707 val_rl = 0;
708 val_rr = 0x80000;
709 break;
710
711 case MPEG_SOUND_MONO:
712 val_ll = 0xc0000;
713 val_lr = 0xc0000;
714 val_rl = 0xc0000;
715 val_rr = 0xc0000;
716 break;
717
718 case MPEG_SOUND_MONO_LEFT:
719 val_ll = 0x80000;
720 val_lr = 0x80000;
721 val_rl = 0;
722 val_rr = 0;
723 break;
724
725 case MPEG_SOUND_MONO_RIGHT:
726 val_ll = 0;
727 val_lr = 0;
728 val_rl = 0x80000;
729 val_rr = 0x80000;
730 break;
731
732 case MPEG_SOUND_STEREO_NARROW:
733 val_ll = 0xa0000;
734 val_lr = 0xe0000;
735 val_rl = 0xe0000;
736 val_rr = 0xa0000;
737 break;
738
739 case MPEG_SOUND_STEREO_WIDE:
740 val_ll = 0x80000;
741 val_lr = 0x40000;
742 val_rl = 0x40000;
743 val_rr = 0x80000;
744 break;
745
746 case MPEG_SOUND_KARAOKE:
747 val_ll = 0x80001;
748 val_lr = 0x7ffff;
749 val_rl = 0x7ffff;
750 val_rr = 0x80001;
751 break;
752 }
753
754#ifdef HAVE_MAS3587F
755 mas_writemem(MAS_BANK_D0, 0x7fc, &val_ll, 1); /* LL */
756 mas_writemem(MAS_BANK_D0, 0x7fd, &val_lr, 1); /* LR */
757 mas_writemem(MAS_BANK_D0, 0x7fe, &val_rl, 1); /* RL */
758 mas_writemem(MAS_BANK_D0, 0x7ff, &val_rr, 1); /* RR */
759#else
760 mas_writemem(MAS_BANK_D1, 0x7f8, &val_ll, 1); /* LL */
761 mas_writemem(MAS_BANK_D1, 0x7f9, &val_lr, 1); /* LR */
762 mas_writemem(MAS_BANK_D1, 0x7fa, &val_rl, 1); /* RL */
763 mas_writemem(MAS_BANK_D1, 0x7fb, &val_rr, 1); /* RR */
764#endif
765#endif
766}
767
768#ifdef HAVE_MAS3587F
769/* This function works by telling the decoder that we have another
770 crystal frequency than we actually have. It will adjust its internal
771 parameters and the result is that the audio is played at another pitch.
772
773 The pitch value is in tenths of percent.
774*/
775void mpeg_set_pitch(int pitch)
776{
777 unsigned long val;
778
779 /* invert pitch value */
780 pitch = 1000000/pitch;
781
782 /* Calculate the new (bogus) frequency */
783 val = 18432*pitch/1000;
784
785 mas_writemem(MAS_BANK_D0,0x7f3,&val,1);
786
787 /* We must tell the MAS that the frequency has changed.
788 This will unfortunately cause a short silence. */
789 val = 0x25;
790 mas_writemem(MAS_BANK_D0,0x7f1,&val,1);
791}
792#endif
793
794void mp3_init(int volume, int bass, int treble, int balance, int loudness,
795 int bass_boost, int avc, int channel_config)
796{
797#ifdef SIMULATOR
798 volume = bass = treble = balance = loudness
799 = bass_boost = avc = channel_config;
800#else
801#ifdef HAVE_MAS3507D
802 unsigned long val;
803 loudness = bass_boost = avc;
804#endif
805
806 setup_sci0();
807
808#ifdef HAVE_MAS3587F
809 or_b(0x08, &PAIORH); /* output for /PR */
810 init_playback();
811
812 mas_version_code = mas_readver();
813 DEBUGF("MAS3587 derivate %d, version B%d\n",
814 (mas_version_code & 0xff00) >> 8, mas_version_code & 0xff);
815#endif
816
817#ifdef HAVE_DAC3550A
818 dac_init();
819#endif
820
821#ifdef HAVE_MAS3507D
822 and_b(~0x20, &PBDRL);
823 sleep(HZ/5);
824 or_b(0x20, &PBDRL);
825 sleep(HZ/5);
826
827 /* set IRQ6 to edge detect */
828 ICR |= 0x02;
829
830 /* set IRQ6 prio 8 */
831 IPRB = ( IPRB & 0xff0f ) | 0x0080;
832
833 mas_readmem(MAS_BANK_D1, 0xff7, &mas_version_code, 1);
834
835 mas_writereg(0x3b, 0x20); /* Don't ask why. The data sheet doesn't say */
836 mas_run(1);
837 sleep(HZ);
838
839 /* Clear the upper 12 bits of the 32-bit samples */
840 mas_writereg(0xc5, 0);
841 mas_writereg(0xc6, 0);
842
843 /* We need to set the PLL for a 14.1318MHz crystal */
844 if(mas_version_code == 0x0601) /* Version F10? */
845 {
846 val = 0x5d9d0;
847 mas_writemem(MAS_BANK_D0, 0x32d, &val, 1);
848 val = 0xfffceceb;
849 mas_writemem(MAS_BANK_D0, 0x32e, &val, 1);
850 val = 0x0;
851 mas_writemem(MAS_BANK_D0, 0x32f, &val, 1);
852 mas_run(0x475);
853 }
854 else
855 {
856 val = 0x5d9d0;
857 mas_writemem(MAS_BANK_D0, 0x36d, &val, 1);
858 val = 0xfffceceb;
859 mas_writemem(MAS_BANK_D0, 0x36e, &val, 1);
860 val = 0x0;
861 mas_writemem(MAS_BANK_D0, 0x36f, &val, 1);
862 mas_run(0xfcb);
863 }
864
865#endif
866
867#ifdef HAVE_MAS3507D
868 mas_poll_start(1);
869
870 mas_writereg(MAS_REG_KPRESCALE, 0xe9400);
871 dac_enable(true);
872
873 mpeg_sound_channel_config(channel_config);
874#endif
875
876#ifdef HAVE_MAS3587F
877 ICR &= ~0x0010; /* IRQ3 level sensitive */
878 PACR1 = (PACR1 & 0x3fff) | 0x4000; /* PA15 is IRQ3 */
879#endif
880
881 /* Must be done before calling mpeg_sound_set() */
882 mpeg_is_initialized = true;
883
884 mpeg_sound_set(SOUND_BASS, bass);
885 mpeg_sound_set(SOUND_TREBLE, treble);
886 mpeg_sound_set(SOUND_BALANCE, balance);
887 mpeg_sound_set(SOUND_VOLUME, volume);
888
889#ifdef HAVE_MAS3587F
890 mpeg_sound_channel_config(channel_config);
891 mpeg_sound_set(SOUND_LOUDNESS, loudness);
892 mpeg_sound_set(SOUND_SUPERBASS, bass_boost);
893 mpeg_sound_set(SOUND_AVC, avc);
894#endif
895#endif /* !SIMULATOR */
896}
897
898
899/* new functions, to be exported to plugin API */
900
901void mp3_play_init(void)
902{
903#ifdef HAVE_MAS3587F
904 init_playback();
905#endif
906 callback_for_more = NULL;
907}
908
909void mp3_play_data(unsigned char* start, int size,
910 void (*get_more)(unsigned char** start, int* size) /* callback fn */
911)
912{
913 /* init DMA */
914 DAR3 = 0x5FFFEC3;
915 CHCR3 &= ~0x0002; /* Clear interrupt */
916 CHCR3 = 0x1504; /* Single address destination, TXI0, IE=1 */
917 DMAOR = 0x0001; /* Enable DMA */
918
919 callback_for_more = get_more;
920
921 SAR3 = (unsigned int)start;
922 DTCR3 = size & 0xffff;
923
924 CHCR3 |= 0x0001; /* Enable DMA IRQ */
925}
926
927void mp3_play_pause(bool play)
928{
929 if (play)
930 SCR0 |= 0x80;
931 else
932 SCR0 &= 0x7f;
933}
934
935void mp3_play_stop(void)
936{
937 mp3_play_pause(false);
938 CHCR3 &= ~0x0001; /* Disable the DMA interrupt */
939}