Fixed red build...
[kugel-rb.git] / firmware / mp3_playback.c
blobf2c588c6b5cccad294b73cb63de09bd209c19906
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 #if CONFIG_HWCODEC == MAS3587F
39 enum
41 MPEG_DECODER,
42 MPEG_ENCODER
43 } mpeg_mode;
44 #endif /* #ifdef MAS3587F */
46 #if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F)
47 extern unsigned long shadow_io_control_main;
48 extern unsigned shadow_codec_reg0;
49 #endif
51 /**** globals ****/
53 /* own version, independent of mpeg.c */
54 static bool paused; /* playback is paused */
55 static bool playing; /* We are playing an MP3 stream */
57 #ifndef SIMULATOR
58 /* for measuring the play time */
59 static long playstart_tick;
60 static long cumulative_ticks;
62 /* the registered callback function to ask for more mp3 data */
63 static void (*callback_for_more)(unsigned char**, int*);
64 #endif /* #ifndef SIMULATOR */
66 static const char* const units[] =
68 "%", /* Volume */
69 "dB", /* Bass */
70 "dB", /* Treble */
71 "%", /* Balance */
72 "dB", /* Loudness */
73 "", /* AVC */
74 "", /* Channels */
75 "%", /* Stereo width */
76 "dB", /* Left gain */
77 "dB", /* Right gain */
78 "dB", /* Mic gain */
79 "dB", /* MDB Strength */
80 "%", /* MDB Harmonics */
81 "Hz", /* MDB Center */
82 "Hz", /* MDB Shape */
83 "", /* MDB Enable */
84 "", /* Super bass */
87 static const int numdecimals[] =
89 0, /* Volume */
90 0, /* Bass */
91 0, /* Treble */
92 0, /* Balance */
93 0, /* Loudness */
94 0, /* AVC */
95 0, /* Channels */
96 0, /* Stereo width */
97 1, /* Left gain */
98 1, /* Right gain */
99 1, /* Mic gain */
100 0, /* MDB Strength */
101 0, /* MDB Harmonics */
102 0, /* MDB Center */
103 0, /* MDB Shape */
104 0, /* MDB Enable */
105 0, /* Super bass */
108 static const int steps[] =
110 1, /* Volume */
111 1, /* Bass */
112 1, /* Treble */
113 1, /* Balance */
114 1, /* Loudness */
115 1, /* AVC */
116 1, /* Channels */
117 1, /* Stereo width */
118 1, /* Left gain */
119 1, /* Right gain */
120 1, /* Mic gain */
121 1, /* MDB Strength */
122 1, /* MDB Harmonics */
123 10, /* MDB Center */
124 10, /* MDB Shape */
125 1, /* MDB Enable */
126 1, /* Super bass */
129 static const int minval[] =
131 0, /* Volume */
132 #if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F)
133 -12, /* Bass */
134 -12, /* Treble */
135 #else
136 -15, /* Bass */
137 -15, /* Treble */
138 #endif
139 -100, /* Balance */
140 0, /* Loudness */
141 -1, /* AVC */
142 0, /* Channels */
143 0, /* Stereo width */
144 0, /* Left gain */
145 0, /* Right gain */
146 0, /* Mic gain */
147 0, /* MDB Strength */
148 0, /* MDB Harmonics */
149 20, /* MDB Center */
150 50, /* MDB Shape */
151 0, /* MDB Enable */
152 0, /* Super bass */
155 static const int maxval[] =
157 100, /* Volume */
158 #if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F)
159 12, /* Bass */
160 12, /* Treble */
161 #else
162 15, /* Bass */
163 15, /* Treble */
164 #endif
165 100, /* Balance */
166 17, /* Loudness */
167 4, /* AVC */
168 5, /* Channels */
169 255, /* Stereo width */
170 15, /* Left gain */
171 15, /* Right gain */
172 15, /* Mic gain */
173 127, /* MDB Strength */
174 100, /* MDB Harmonics */
175 300, /* MDB Center */
176 300, /* MDB Shape */
177 1, /* MDB Enable */
178 1, /* Super bass */
181 static const int defaultval[] =
183 70, /* Volume */
184 #if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F)
185 6, /* Bass */
186 6, /* Treble */
187 #else
188 7, /* Bass */
189 7, /* Treble */
190 #endif
191 0, /* Balance */
192 0, /* Loudness */
193 0, /* AVC */
194 0, /* Channels */
195 100, /* Stereo width */
196 8, /* Left gain */
197 8, /* Right gain */
198 2, /* Mic gain */
199 50, /* MDB Strength */
200 48, /* MDB Harmonics */
201 60, /* MDB Center */
202 90, /* MDB Shape */
203 0, /* MDB Enable */
204 0, /* Super bass */
207 const char *mpeg_sound_unit(int setting)
209 return units[setting];
212 int mpeg_sound_numdecimals(int setting)
214 return numdecimals[setting];
217 int mpeg_sound_steps(int setting)
219 return steps[setting];
222 int mpeg_sound_min(int setting)
224 return minval[setting];
227 int mpeg_sound_max(int setting)
229 return maxval[setting];
232 int mpeg_sound_default(int setting)
234 return defaultval[setting];
237 /* list of tracks in memory */
238 #define MAX_ID3_TAGS (1<<4) /* Must be power of 2 */
239 #define MAX_ID3_TAGS_MASK (MAX_ID3_TAGS - 1)
241 #ifndef SIMULATOR
242 static bool mpeg_is_initialized = false;
243 #endif
245 #ifndef SIMULATOR
247 unsigned long mas_version_code;
249 #if CONFIG_HWCODEC == MAS3507D
251 static const unsigned int bass_table[] =
253 0x9e400, /* -15dB */
254 0xa2800, /* -14dB */
255 0xa7400, /* -13dB */
256 0xac400, /* -12dB */
257 0xb1800, /* -11dB */
258 0xb7400, /* -10dB */
259 0xbd400, /* -9dB */
260 0xc3c00, /* -8dB */
261 0xca400, /* -7dB */
262 0xd1800, /* -6dB */
263 0xd8c00, /* -5dB */
264 0xe0400, /* -4dB */
265 0xe8000, /* -3dB */
266 0xefc00, /* -2dB */
267 0xf7c00, /* -1dB */
269 0x800, /* 1dB */
270 0x10000, /* 2dB */
271 0x17c00, /* 3dB */
272 0x1f800, /* 4dB */
273 0x27000, /* 5dB */
274 0x2e400, /* 6dB */
275 0x35800, /* 7dB */
276 0x3c000, /* 8dB */
277 0x42800, /* 9dB */
278 0x48800, /* 10dB */
279 0x4e400, /* 11dB */
280 0x53800, /* 12dB */
281 0x58800, /* 13dB */
282 0x5d400, /* 14dB */
283 0x61800 /* 15dB */
286 static const unsigned int treble_table[] =
288 0xb2c00, /* -15dB */
289 0xbb400, /* -14dB */
290 0xc1800, /* -13dB */
291 0xc6c00, /* -12dB */
292 0xcbc00, /* -11dB */
293 0xd0400, /* -10dB */
294 0xd5000, /* -9dB */
295 0xd9800, /* -8dB */
296 0xde000, /* -7dB */
297 0xe2800, /* -6dB */
298 0xe7e00, /* -5dB */
299 0xec000, /* -4dB */
300 0xf0c00, /* -3dB */
301 0xf5c00, /* -2dB */
302 0xfac00, /* -1dB */
304 0x5400, /* 1dB */
305 0xac00, /* 2dB */
306 0x10400, /* 3dB */
307 0x16000, /* 4dB */
308 0x1c000, /* 5dB */
309 0x22400, /* 6dB */
310 0x28400, /* 7dB */
311 0x2ec00, /* 8dB */
312 0x35400, /* 9dB */
313 0x3c000, /* 10dB */
314 0x42c00, /* 11dB */
315 0x49c00, /* 12dB */
316 0x51800, /* 13dB */
317 0x58400, /* 14dB */
318 0x5f800 /* 15dB */
321 static const unsigned int prescale_table[] =
323 0x80000, /* 0db */
324 0x8e000, /* 1dB */
325 0x9a400, /* 2dB */
326 0xa5800, /* 3dB */
327 0xaf400, /* 4dB */
328 0xb8000, /* 5dB */
329 0xbfc00, /* 6dB */
330 0xc6c00, /* 7dB */
331 0xcd000, /* 8dB */
332 0xd25c0, /* 9dB */
333 0xd7800, /* 10dB */
334 0xdc000, /* 11dB */
335 0xdfc00, /* 12dB */
336 0xe3400, /* 13dB */
337 0xe6800, /* 14dB */
338 0xe9400 /* 15dB */
340 #endif
342 bool dma_on; /* The DMA is active */
344 #if CONFIG_HWCODEC == MAS3507D
345 static void mas_poll_start(void)
347 unsigned int count;
349 count = 9 * FREQ / 10000 / 8; /* 0.9 ms */
351 /* We are using timer 1 */
353 TSTR &= ~0x02; /* Stop the timer */
354 TSNC &= ~0x02; /* No synchronization */
355 TMDR &= ~0x02; /* Operate normally */
357 TCNT1 = 0; /* Start counting at 0 */
358 GRA1 = count;
359 TCR1 = 0x23; /* Clear at GRA match, sysclock/8 */
361 /* Enable interrupt on level 5 */
362 IPRC = (IPRC & ~0x000f) | 0x0005;
364 TSR1 &= ~0x02;
365 TIER1 = 0xf9; /* Enable GRA match interrupt */
367 TSTR |= 0x02; /* Start timer 1 */
369 #else
370 static void postpone_dma_tick(void)
372 unsigned int count;
374 count = 8 * FREQ / 10000 / 8; /* 0.8 ms */
376 /* We are using timer 1 */
378 TSTR &= ~0x02; /* Stop the timer */
379 TSNC &= ~0x02; /* No synchronization */
380 TMDR &= ~0x02; /* Operate normally */
382 TCNT1 = 0; /* Start counting at 0 */
383 GRA1 = count;
384 TCR1 = 0x23; /* Clear at GRA match, sysclock/8 */
386 /* Enable interrupt on level 5 */
387 IPRC = (IPRC & ~0x000f) | 0x0005;
389 TSR1 &= ~0x02;
390 TIER1 = 0xf9; /* Enable GRA match interrupt */
392 TSTR |= 0x02; /* Start timer 1 */
394 #endif
397 #if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F)
398 void demand_irq_enable(bool on)
400 int oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL);
402 if(on)
404 IPRA = (IPRA & 0xfff0) | 0x000b;
405 ICR &= ~0x0010; /* IRQ3 level sensitive */
407 else
408 IPRA &= 0xfff0;
410 set_irq_level(oldlevel);
412 #endif /* #if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F) */
415 void play_tick(void)
417 if(playing && !paused)
419 /* Start DMA if it is disabled and the DEMAND pin is high */
420 if(!(SCR0 & 0x80) && (PBDR & 0x4000))
422 SCR0 |= 0x80;
425 playback_tick(); /* dirty call to mpeg.c */
429 #pragma interrupt
430 void DEI3(void)
432 unsigned char* start;
433 int size = 0;
435 if (callback_for_more != NULL)
437 callback_for_more(&start, &size);
440 if (size > 0)
442 DTCR3 = size & 0xffff;
443 SAR3 = (unsigned int) start;
445 else
447 CHCR3 &= ~0x0001; /* Disable the DMA interrupt */
450 CHCR3 &= ~0x0002; /* Clear DMA interrupt */
453 #pragma interrupt
454 void IMIA1(void) /* Timer 1 interrupt */
456 if(playing)
457 play_tick();
458 TSR1 &= ~0x01;
459 #if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F)
460 /* Disable interrupt */
461 IPRC &= ~0x000f;
462 #endif
465 #pragma interrupt
466 void IRQ6(void) /* PB14: MAS stop demand IRQ */
468 SCR0 &= ~0x80;
471 #if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F)
472 #pragma interrupt
473 void IRQ3(void) /* PA15: MAS demand IRQ */
475 /* Begin with setting the IRQ to edge sensitive */
476 ICR |= 0x0010;
478 #if CONFIG_HWCODEC == MAS3587F
479 if(mpeg_mode == MPEG_ENCODER)
480 rec_tick();
481 else
482 #endif
483 postpone_dma_tick();
485 #endif /* #if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F) */
487 static void setup_sci0(void)
489 /* PB15 is I/O, PB14 is IRQ6, PB12 is SCK0, PB9 is TxD0 */
490 PBCR1 = (PBCR1 & 0x0cff) | 0x1208;
492 /* Set PB12 to output */
493 or_b(0x10, &PBIORH);
495 /* Disable serial port */
496 SCR0 = 0x00;
498 /* Synchronous, no prescale */
499 SMR0 = 0x80;
501 /* Set baudrate 1Mbit/s */
502 BRR0 = 0x02;
504 /* use SCK as serial clock output */
505 SCR0 = 0x01;
507 /* Clear FER and PER */
508 SSR0 &= 0xe7;
510 /* Set interrupt ITU2 and SCI0 priority to 0 */
511 IPRD &= 0x0ff0;
513 /* set PB15 and PB14 to inputs */
514 and_b(~0x80, &PBIORH);
515 and_b(~0x40, &PBIORH);
517 /* Enable End of DMA interrupt at prio 8 */
518 IPRC = (IPRC & 0xf0ff) | 0x0800;
520 /* Enable Tx (only!) */
521 SCR0 |= 0x20;
523 #endif /* SIMULATOR */
525 #if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F)
526 static void init_playback(void)
528 unsigned long val;
529 int rc;
531 mp3_play_pause(false);
533 mas_reset();
535 /* Enable the audio CODEC and the DSP core, max analog voltage range */
536 rc = mas_direct_config_write(MAS_CONTROL, 0x8c00);
537 if(rc < 0)
538 panicf("mas_ctrl_w: %d", rc);
540 /* Stop the current application */
541 val = 0;
542 mas_writemem(MAS_BANK_D0, MAS_D0_APP_SELECT, &val, 1);
545 mas_readmem(MAS_BANK_D0, MAS_D0_APP_RUNNING, &val, 1);
546 } while(val);
548 /* Enable the D/A Converter */
549 shadow_codec_reg0 = 0x0001;
550 mas_codec_writereg(0x0, shadow_codec_reg0);
552 /* ADC scale 0%, DSP scale 100% */
553 mas_codec_writereg(6, 0x0000);
554 mas_codec_writereg(7, 0x4000);
556 #ifdef HAVE_SPDIF_OUT
557 val = 0x09; /* Disable SDO and SDI, low impedance S/PDIF outputs */
558 #else
559 val = 0x2d; /* Disable SDO and SDI, disable S/PDIF output */
560 #endif
561 mas_writemem(MAS_BANK_D0, MAS_D0_INTERFACE_CONTROL, &val, 1);
563 /* Set Demand mode and validate all settings */
564 shadow_io_control_main = 0x25;
565 mas_writemem(MAS_BANK_D0, MAS_D0_IO_CONTROL_MAIN, &shadow_io_control_main, 1);
567 /* Start the Layer2/3 decoder applications */
568 val = 0x0c;
569 mas_writemem(MAS_BANK_D0, MAS_D0_APP_SELECT, &val, 1);
572 mas_readmem(MAS_BANK_D0, MAS_D0_APP_RUNNING, &val, 1);
573 } while((val & 0x0c) != 0x0c);
575 #if CONFIG_HWCODEC == MAS3587F
576 mpeg_mode = MPEG_DECODER;
577 #endif
579 /* set IRQ6 to edge detect */
580 ICR |= 0x02;
582 /* set IRQ6 prio 8 */
583 IPRB = ( IPRB & 0xff0f ) | 0x0080;
585 DEBUGF("MAS Decoding application started\n");
587 #endif /* #if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F) */
589 #ifndef SIMULATOR
590 #if CONFIG_HWCODEC == MAS3507D
591 int current_left_volume = 0; /* all values in tenth of dB */
592 int current_right_volume = 0; /* all values in tenth of dB */
593 int current_treble = 0;
594 int current_bass = 0;
595 int current_balance = 0;
597 /* convert tenth of dB volume to register value */
598 static int tenthdb2reg(int db) {
599 if (db < -540)
600 return (db + 780) / 30;
601 else
602 return (db + 660) / 15;
605 void set_prescaled_volume(void)
607 int prescale;
608 int l, r;
610 prescale = MAX(current_bass, current_treble);
611 if (prescale < 0)
612 prescale = 0; /* no need to prescale if we don't boost
613 bass or treble */
615 mas_writereg(MAS_REG_KPRESCALE, prescale_table[prescale/10]);
617 /* gain up the analog volume to compensate the prescale reduction gain */
618 l = current_left_volume + prescale;
619 r = current_right_volume + prescale;
621 dac_volume(tenthdb2reg(l), tenthdb2reg(r), false);
623 #endif /* MAS3507D */
624 #endif /* !SIMULATOR */
626 int channel_configuration = MPEG_SOUND_STEREO;
627 int stereo_width = 100;
629 #ifndef SIMULATOR
630 static void set_channel_config(void)
632 /* default values: stereo */
633 unsigned long val_ll = 0x80000;
634 unsigned long val_lr = 0;
635 unsigned long val_rl = 0;
636 unsigned long val_rr = 0x80000;
638 switch(channel_configuration)
640 /* case MPEG_SOUND_STEREO unnecessary */
642 case MPEG_SOUND_MONO:
643 val_ll = 0xc0000;
644 val_lr = 0xc0000;
645 val_rl = 0xc0000;
646 val_rr = 0xc0000;
647 break;
649 case MPEG_SOUND_CUSTOM:
651 /* fixed point variables (matching MAS internal format)
652 integer part: upper 13 bits (inlcuding sign)
653 fractional part: lower 19 bits */
654 long fp_width, fp_straight, fp_cross;
656 fp_width = (stereo_width << 19) / 100;
657 if (stereo_width <= 100)
659 fp_straight = - ((1<<19) + fp_width) / 2;
660 fp_cross = fp_straight + fp_width;
662 else
664 fp_straight = - (1<<19);
665 fp_cross = ((2 * fp_width / (((1<<19) + fp_width) >> 10))
666 << 9) - (1<<19);
668 val_ll = val_rr = fp_straight & 0xFFFFF;
669 val_lr = val_rl = fp_cross & 0xFFFFF;
671 break;
673 case MPEG_SOUND_MONO_LEFT:
674 val_ll = 0x80000;
675 val_lr = 0x80000;
676 val_rl = 0;
677 val_rr = 0;
678 break;
680 case MPEG_SOUND_MONO_RIGHT:
681 val_ll = 0;
682 val_lr = 0;
683 val_rl = 0x80000;
684 val_rr = 0x80000;
685 break;
687 case MPEG_SOUND_KARAOKE:
688 val_ll = 0x80001;
689 val_lr = 0x7ffff;
690 val_rl = 0x7ffff;
691 val_rr = 0x80001;
692 break;
695 #if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F)
696 mas_writemem(MAS_BANK_D0, MAS_D0_OUT_LL, &val_ll, 1); /* LL */
697 mas_writemem(MAS_BANK_D0, MAS_D0_OUT_LR, &val_lr, 1); /* LR */
698 mas_writemem(MAS_BANK_D0, MAS_D0_OUT_RL, &val_rl, 1); /* RL */
699 mas_writemem(MAS_BANK_D0, MAS_D0_OUT_RR, &val_rr, 1); /* RR */
700 #elif CONFIG_HWCODEC == MAS3507D
701 mas_writemem(MAS_BANK_D1, 0x7f8, &val_ll, 1); /* LL */
702 mas_writemem(MAS_BANK_D1, 0x7f9, &val_lr, 1); /* LR */
703 mas_writemem(MAS_BANK_D1, 0x7fa, &val_rl, 1); /* RL */
704 mas_writemem(MAS_BANK_D1, 0x7fb, &val_rr, 1); /* RR */
705 #endif
707 #endif /* !SIMULATOR */
709 #if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F)
710 unsigned long mdb_shape_shadow = 0;
711 unsigned long loudness_shadow = 0;
712 #endif
714 void mpeg_sound_set(int setting, int value)
716 #ifdef SIMULATOR
717 setting = value;
718 #else
719 #if CONFIG_HWCODEC == MAS3507D
720 int l, r;
721 #else
722 int tmp;
723 #endif
725 if(!mpeg_is_initialized)
726 return;
728 switch(setting)
730 case SOUND_VOLUME:
731 #if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F)
732 tmp = 0x7f00 * value / 100;
733 mas_codec_writereg(0x10, tmp & 0xff00);
734 #else
735 l = value;
736 r = value;
738 if(current_balance > 0)
740 l -= current_balance;
741 if(l < 0)
742 l = 0;
745 if(current_balance < 0)
747 r += current_balance;
748 if(r < 0)
749 r = 0;
752 l = 0x38 * l / 100;
753 r = 0x38 * r / 100;
755 /* store volume in tenth of dB */
756 current_left_volume = ( l < 0x08 ? l*30 - 780 : l*15 - 660 );
757 current_right_volume = ( r < 0x08 ? r*30 - 780 : r*15 - 660 );
759 set_prescaled_volume();
760 #endif
761 break;
763 case SOUND_BALANCE:
764 #if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F)
765 tmp = ((value * 127 / 100) & 0xff) << 8;
766 mas_codec_writereg(0x11, tmp & 0xff00);
767 #else
768 current_balance = value;
769 #endif
770 break;
772 case SOUND_BASS:
773 #if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F)
774 tmp = ((value * 8) & 0xff) << 8;
775 mas_codec_writereg(0x14, tmp & 0xff00);
776 #else
777 mas_writereg(MAS_REG_KBASS, bass_table[value+15]);
778 current_bass = (value) * 10;
779 set_prescaled_volume();
780 #endif
781 break;
783 case SOUND_TREBLE:
784 #if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F)
785 tmp = ((value * 8) & 0xff) << 8;
786 mas_codec_writereg(0x15, tmp & 0xff00);
787 #else
788 mas_writereg(MAS_REG_KTREBLE, treble_table[value+15]);
789 current_treble = (value) * 10;
790 set_prescaled_volume();
791 #endif
792 break;
794 #if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F)
795 case SOUND_LOUDNESS:
796 loudness_shadow = (loudness_shadow & 0x04) |
797 (MAX(MIN(value * 4, 0x44), 0) << 8);
798 mas_codec_writereg(MAS_REG_KLOUDNESS, loudness_shadow);
799 break;
801 case SOUND_AVC:
802 switch (value) {
803 case 1: /* 20ms */
804 tmp = (0x1 << 8) | (0x8 << 12);
805 break;
806 case 2: /* 2s */
807 tmp = (0x2 << 8) | (0x8 << 12);
808 break;
809 case 3: /* 4s */
810 tmp = (0x4 << 8) | (0x8 << 12);
811 break;
812 case 4: /* 8s */
813 tmp = (0x8 << 8) | (0x8 << 12);
814 break;
815 case -1: /* turn off and then turn on again to decay quickly */
816 tmp = mas_codec_readreg(MAS_REG_KAVC);
817 mas_codec_writereg(MAS_REG_KAVC, 0);
818 break;
819 default: /* off */
820 tmp = 0;
821 break;
823 mas_codec_writereg(MAS_REG_KAVC, tmp);
824 break;
826 case SOUND_MDB_STRENGTH:
827 mas_codec_writereg(MAS_REG_KMDB_STR, (value & 0x7f) << 8);
828 break;
830 case SOUND_MDB_HARMONICS:
831 tmp = value * 127 / 100;
832 mas_codec_writereg(MAS_REG_KMDB_HAR, (tmp & 0x7f) << 8);
833 break;
835 case SOUND_MDB_CENTER:
836 mas_codec_writereg(MAS_REG_KMDB_FC, (value/10) << 8);
837 break;
839 case SOUND_MDB_SHAPE:
840 mdb_shape_shadow = (mdb_shape_shadow & 0x02) | ((value/10) << 8);
841 mas_codec_writereg(MAS_REG_KMDB_SWITCH, mdb_shape_shadow);
842 break;
844 case SOUND_MDB_ENABLE:
845 mdb_shape_shadow = (mdb_shape_shadow & ~0x02) | (value?2:0);
846 mas_codec_writereg(MAS_REG_KMDB_SWITCH, mdb_shape_shadow);
847 break;
849 case SOUND_SUPERBASS:
850 loudness_shadow = (loudness_shadow & ~0x04) |
851 (value?4:0);
852 mas_codec_writereg(MAS_REG_KLOUDNESS, loudness_shadow);
853 break;
854 #endif
855 case SOUND_CHANNELS:
856 channel_configuration = value;
857 set_channel_config();
858 break;
860 case SOUND_STEREO_WIDTH:
861 stereo_width = value;
862 if (channel_configuration == MPEG_SOUND_CUSTOM)
863 set_channel_config();
864 break;
866 #endif /* SIMULATOR */
869 int mpeg_val2phys(int setting, int value)
871 #if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F)
872 int result = 0;
874 switch(setting)
876 case SOUND_LEFT_GAIN:
877 case SOUND_RIGHT_GAIN:
878 result = (value - 2) * 15;
879 break;
881 case SOUND_MIC_GAIN:
882 result = value * 15 + 210;
883 break;
885 default:
886 result = value;
887 break;
889 return result;
890 #else
891 (void)setting;
892 return value;
893 #endif
896 #if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F)
897 /* This function works by telling the decoder that we have another
898 crystal frequency than we actually have. It will adjust its internal
899 parameters and the result is that the audio is played at another pitch.
901 The pitch value is in tenths of percent.
903 void mpeg_set_pitch(int pitch)
905 unsigned long val;
907 /* invert pitch value */
908 pitch = 1000000/pitch;
910 /* Calculate the new (bogus) frequency */
911 val = 18432*pitch/1000;
913 mas_writemem(MAS_BANK_D0, MAS_D0_OFREQ_CONTROL, &val, 1);
915 /* We must tell the MAS that the frequency has changed.
916 This will unfortunately cause a short silence. */
917 mas_writemem(MAS_BANK_D0, MAS_D0_IO_CONTROL_MAIN, &shadow_io_control_main, 1);
919 #endif
921 void mp3_init(int volume, int bass, int treble, int balance, int loudness,
922 int avc, int channel_config, int stereo_width,
923 int mdb_strength, int mdb_harmonics,
924 int mdb_center, int mdb_shape, bool mdb_enable,
925 bool superbass)
927 #ifdef SIMULATOR
928 (void)volume;
929 (void)bass;
930 (void)treble;
931 (void)balance;
932 (void)loudness;
933 (void)avc;
934 (void)channel_config;
935 (void)stereo_width;
936 (void)mdb_strength;
937 (void)mdb_harmonics;
938 (void)mdb_center;
939 (void)mdb_shape;
940 (void)mdb_enable;
941 (void)superbass;
942 #else
943 #if CONFIG_HWCODEC == MAS3507D
944 unsigned long val;
945 (void)loudness;
946 (void)avc;
947 (void)mdb_strength;
948 (void)mdb_harmonics;
949 (void)mdb_center;
950 (void)mdb_shape;
951 (void)mdb_enable;
952 (void)superbass;
953 #endif
955 setup_sci0();
957 #ifdef HAVE_MAS_SIBI_CONTROL
958 and_b(~0x01, &PBDRH); /* drive SIBI low */
959 or_b(0x01, &PBIORH); /* output for PB8 */
960 #endif
962 #if CONFIG_HWCODEC == MAS3507D
963 mas_reset();
964 #elif CONFIG_HWCODEC == MAS3587F
965 or_b(0x08, &PAIORH); /* output for /PR */
966 init_playback();
968 mas_version_code = mas_readver();
969 DEBUGF("MAS3587 derivate %d, version %c%d\n",
970 (mas_version_code & 0xf000) >> 12,
971 'A' + ((mas_version_code & 0x0f00) >> 8), mas_version_code & 0xff);
972 #elif CONFIG_HWCODEC == MAS3539F
973 or_b(0x08, &PAIORH); /* output for /PR */
974 init_playback();
976 mas_version_code = mas_readver();
977 DEBUGF("MAS3539 derivate %d, version %c%d\n",
978 (mas_version_code & 0xf000) >> 12,
979 'A' + ((mas_version_code & 0x0f00) >> 8), mas_version_code & 0xff);
980 #endif
982 #ifdef HAVE_DAC3550A
983 dac_init();
984 #endif
986 #if CONFIG_HWCODEC == MAS3507D
987 and_b(~0x20, &PBDRL);
988 sleep(HZ/5);
989 or_b(0x20, &PBDRL);
990 sleep(HZ/5);
992 /* set IRQ6 to edge detect */
993 ICR |= 0x02;
995 /* set IRQ6 prio 8 */
996 IPRB = ( IPRB & 0xff0f ) | 0x0080;
998 mas_readmem(MAS_BANK_D1, 0xff7, &mas_version_code, 1);
1000 mas_writereg(0x3b, 0x20); /* Don't ask why. The data sheet doesn't say */
1001 mas_run(1);
1002 sleep(HZ);
1004 /* Clear the upper 12 bits of the 32-bit samples */
1005 mas_writereg(0xc5, 0);
1006 mas_writereg(0xc6, 0);
1008 /* We need to set the PLL for a 14.31818MHz crystal */
1009 if(mas_version_code == 0x0601) /* Version F10? */
1011 val = 0x5d9d0;
1012 mas_writemem(MAS_BANK_D0, 0x32d, &val, 1);
1013 val = 0xfffceceb;
1014 mas_writemem(MAS_BANK_D0, 0x32e, &val, 1);
1015 val = 0x0;
1016 mas_writemem(MAS_BANK_D0, 0x32f, &val, 1);
1017 mas_run(0x475);
1019 else
1021 val = 0x5d9d0;
1022 mas_writemem(MAS_BANK_D0, 0x36d, &val, 1);
1023 val = 0xfffceceb;
1024 mas_writemem(MAS_BANK_D0, 0x36e, &val, 1);
1025 val = 0x0;
1026 mas_writemem(MAS_BANK_D0, 0x36f, &val, 1);
1027 mas_run(0xfcb);
1030 #endif
1032 #if CONFIG_HWCODEC == MAS3507D
1033 mas_poll_start();
1035 mas_writereg(MAS_REG_KPRESCALE, 0xe9400);
1036 dac_enable(true);
1037 #endif
1039 #if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F)
1040 ICR &= ~0x0010; /* IRQ3 level sensitive */
1041 PACR1 = (PACR1 & 0x3fff) | 0x4000; /* PA15 is IRQ3 */
1042 #endif
1044 /* Must be done before calling mpeg_sound_set() */
1045 mpeg_is_initialized = true;
1047 mpeg_sound_set(SOUND_BASS, bass);
1048 mpeg_sound_set(SOUND_TREBLE, treble);
1049 mpeg_sound_set(SOUND_BALANCE, balance);
1050 mpeg_sound_set(SOUND_VOLUME, volume);
1051 mpeg_sound_set(SOUND_CHANNELS, channel_config);
1052 mpeg_sound_set(SOUND_STEREO_WIDTH, stereo_width);
1054 #if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F)
1055 mpeg_sound_set(SOUND_LOUDNESS, loudness);
1056 mpeg_sound_set(SOUND_AVC, avc);
1057 mpeg_sound_set(SOUND_MDB_STRENGTH, mdb_strength);
1058 mpeg_sound_set(SOUND_MDB_HARMONICS, mdb_harmonics);
1059 mpeg_sound_set(SOUND_MDB_CENTER, mdb_center);
1060 mpeg_sound_set(SOUND_MDB_SHAPE, mdb_shape);
1061 mpeg_sound_set(SOUND_MDB_ENABLE, mdb_enable);
1062 mpeg_sound_set(SOUND_SUPERBASS, superbass);
1063 #endif
1064 #endif /* !SIMULATOR */
1066 playing = false;
1067 paused = true;
1070 void mp3_shutdown(void)
1072 #ifndef SIMULATOR
1073 #if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F)
1074 unsigned long val = 1;
1075 mas_writemem(MAS_BANK_D0, MAS_D0_SOFT_MUTE, &val, 1); /* Mute */
1076 #endif
1078 #if CONFIG_HWCODEC == MAS3507D
1079 dac_volume(0, 0, false);
1080 #endif
1082 #endif
1085 /* new functions, to be exported to plugin API */
1087 #ifndef SIMULATOR
1089 void mp3_play_init(void)
1091 #if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F)
1092 init_playback();
1093 #endif
1094 playing = false;
1095 paused = true;
1096 callback_for_more = NULL;
1097 mp3_reset_playtime();
1100 void mp3_play_data(const unsigned char* start, int size,
1101 void (*get_more)(unsigned char** start, int* size) /* callback fn */
1104 /* init DMA */
1105 DAR3 = 0x5FFFEC3;
1106 CHCR3 &= ~0x0002; /* Clear interrupt */
1107 CHCR3 = 0x1504; /* Single address destination, TXI0, IE=1 */
1108 DMAOR = 0x0001; /* Enable DMA */
1110 callback_for_more = get_more;
1112 SAR3 = (unsigned int)start;
1113 DTCR3 = size & 0xffff;
1115 playing = true;
1116 paused = true;
1118 CHCR3 |= 0x0001; /* Enable DMA IRQ */
1120 #if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F)
1121 demand_irq_enable(true);
1122 #endif
1125 void mp3_play_pause(bool play)
1127 if (paused && play)
1128 { /* resume playback */
1129 SCR0 |= 0x80;
1130 paused = false;
1131 playstart_tick = current_tick;
1133 else if (!paused && !play)
1134 { /* stop playback */
1135 SCR0 &= 0x7f;
1136 paused = true;
1137 cumulative_ticks += current_tick - playstart_tick;
1141 void mp3_play_stop(void)
1143 playing = false;
1144 mp3_play_pause(false);
1145 CHCR3 &= ~0x0001; /* Disable the DMA interrupt */
1146 #if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F)
1147 demand_irq_enable(false);
1148 #endif
1151 long mp3_get_playtime(void)
1153 if (paused)
1154 return cumulative_ticks;
1155 else
1156 return cumulative_ticks + current_tick - playstart_tick;
1159 void mp3_reset_playtime(void)
1161 cumulative_ticks = 0;
1162 playstart_tick = current_tick;
1166 bool mp3_is_playing(void)
1168 return playing;
1172 /* returns the next byte position which would be transferred */
1173 unsigned char* mp3_get_pos(void)
1175 return (unsigned char*)SAR3;
1179 #endif /* #ifndef SIMULATOR */