Fix remote screen check in graphic equalizer, so that it can be used on logf-enabled...
[Rockbox.git] / firmware / mp3_playback.c
bloba5a251160e60352d184ecf0b6a47ac230b9e1b97
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 #include "sound.h"
30 #ifndef SIMULATOR
31 #include "i2c.h"
32 #include "mas.h"
33 #include "dac.h"
34 #include "system.h"
35 #include "hwcompat.h"
36 #endif
38 /* hacking into mpeg.c, recording is still there */
39 #if CONFIG_CODEC == MAS3587F
40 enum
42 MPEG_DECODER,
43 MPEG_ENCODER
44 } mpeg_mode;
45 #endif /* #ifdef MAS3587F */
47 #if ((CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)) && !defined(SIMULATOR)
48 extern unsigned long shadow_io_control_main;
49 extern unsigned shadow_codec_reg0;
50 #endif
52 /**** globals ****/
54 /* own version, independent of mpeg.c */
55 static bool paused; /* playback is paused */
56 static bool playing; /* We are playing an MP3 stream */
58 #ifndef SIMULATOR
59 /* for measuring the play time */
60 static long playstart_tick;
61 static long cumulative_ticks;
63 /* the registered callback function to ask for more mp3 data */
64 static void (*callback_for_more)(unsigned char**, int*);
65 #endif /* #ifndef SIMULATOR */
67 /* list of tracks in memory */
68 #define MAX_ID3_TAGS (1<<4) /* Must be power of 2 */
69 #define MAX_ID3_TAGS_MASK (MAX_ID3_TAGS - 1)
71 #ifndef SIMULATOR
72 bool audio_is_initialized = false;
73 #endif
75 #if CONFIG_CODEC != SWCODEC
76 /* FIX: this code pretty much assumes a MAS */
78 #ifndef SIMULATOR
80 unsigned long mas_version_code;
82 #if CONFIG_CODEC == MAS3507D
83 static void mas_poll_start(void)
85 unsigned int count;
87 count = 9 * FREQ / 10000 / 8; /* 0.9 ms */
89 /* We are using timer 1 */
91 TSTR &= ~0x02; /* Stop the timer */
92 TSNC &= ~0x02; /* No synchronization */
93 TMDR &= ~0x02; /* Operate normally */
95 TCNT1 = 0; /* Start counting at 0 */
96 GRA1 = count;
97 TCR1 = 0x23; /* Clear at GRA match, sysclock/8 */
99 /* Enable interrupt on level 5 */
100 IPRC = (IPRC & ~0x000f) | 0x0005;
102 TSR1 &= ~0x02;
103 TIER1 = 0xf9; /* Enable GRA match interrupt */
105 TSTR |= 0x02; /* Start timer 1 */
107 #elif CONFIG_CODEC != SWCODEC
108 static void postpone_dma_tick(void)
110 unsigned int count;
112 count = 8 * FREQ / 10000 / 8; /* 0.8 ms */
114 /* We are using timer 1 */
116 TSTR &= ~0x02; /* Stop the timer */
117 TSNC &= ~0x02; /* No synchronization */
118 TMDR &= ~0x02; /* Operate normally */
120 TCNT1 = 0; /* Start counting at 0 */
121 GRA1 = count;
122 TCR1 = 0x23; /* Clear at GRA match, sysclock/8 */
124 /* Enable interrupt on level 5 */
125 IPRC = (IPRC & ~0x000f) | 0x0005;
127 TSR1 &= ~0x02;
128 TIER1 = 0xf9; /* Enable GRA match interrupt */
130 TSTR |= 0x02; /* Start timer 1 */
132 #endif
135 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
136 void demand_irq_enable(bool on)
138 int oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL);
140 if(on)
142 IPRA = (IPRA & 0xfff0) | 0x000b;
143 ICR &= ~0x0010; /* IRQ3 level sensitive */
145 else
146 IPRA &= 0xfff0;
148 set_irq_level(oldlevel);
150 #endif /* #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) */
153 void play_tick(void)
155 if(playing && !paused)
157 /* Start DMA if it is disabled and the DEMAND pin is high */
158 if(!(SCR0 & 0x80) && (PBDR & 0x4000))
160 SCR0 |= 0x80;
163 playback_tick(); /* dirty call to mpeg.c */
167 void DEI3(void) __attribute__((interrupt_handler));
168 void DEI3(void)
170 unsigned char* start;
171 int size = 0;
173 if (callback_for_more != NULL)
175 callback_for_more(&start, &size);
178 if (size > 0)
180 DTCR3 = size & 0xffff;
181 SAR3 = (unsigned int) start;
183 else
185 CHCR3 &= ~0x0001; /* Disable the DMA interrupt */
188 CHCR3 &= ~0x0002; /* Clear DMA interrupt */
191 void IMIA1(void) __attribute__((interrupt_handler));
192 void IMIA1(void) /* Timer 1 interrupt */
194 if(playing)
195 play_tick();
196 TSR1 &= ~0x01;
197 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
198 /* Disable interrupt */
199 IPRC &= ~0x000f;
200 #endif
203 void IRQ6(void) __attribute__((interrupt_handler));
204 void IRQ6(void) /* PB14: MAS stop demand IRQ */
206 SCR0 &= ~0x80;
209 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
210 void IRQ3(void) __attribute__((interrupt_handler));
211 void IRQ3(void) /* PA15: MAS demand IRQ */
213 /* Begin with setting the IRQ to edge sensitive */
214 ICR |= 0x0010;
216 #if CONFIG_CODEC == MAS3587F
217 if(mpeg_mode == MPEG_ENCODER)
218 rec_tick();
219 else
220 #endif
221 postpone_dma_tick();
223 /* Workaround for sh-elf-gcc 3.3.x bug with -O2 or -Os and ISRs
224 * (invalid cross-jump optimisation) */
225 asm volatile ("");
227 #endif /* #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) */
229 static void setup_sci0(void)
231 /* PB15 is I/O, PB14 is IRQ6, PB12 is SCK0, PB9 is TxD0 */
232 PBCR1 = (PBCR1 & 0x0cff) | 0x1208;
234 /* Set PB12 to output */
235 or_b(0x10, &PBIORH);
237 /* Disable serial port */
238 SCR0 = 0x00;
240 /* Synchronous, no prescale */
241 SMR0 = 0x80;
243 /* Set baudrate 1Mbit/s */
244 BRR0 = 0x02;
246 /* use SCK as serial clock output */
247 SCR0 = 0x01;
249 /* Clear FER and PER */
250 SSR0 &= 0xe7;
252 /* Set interrupt ITU2 and SCI0 priority to 0 */
253 IPRD &= 0x0ff0;
255 /* set PB15 and PB14 to inputs */
256 and_b(~0x80, &PBIORH);
257 and_b(~0x40, &PBIORH);
259 /* Enable End of DMA interrupt at prio 8 */
260 IPRC = (IPRC & 0xf0ff) | 0x0800;
262 /* Enable Tx (only!) */
263 SCR0 |= 0x20;
266 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
267 static void init_playback(void)
269 unsigned long val;
270 int rc;
272 mp3_play_pause(false);
274 mas_reset();
276 /* Enable the audio CODEC and the DSP core, max analog voltage range */
277 rc = mas_direct_config_write(MAS_CONTROL, 0x8c00);
278 if(rc < 0)
279 panicf("mas_ctrl_w: %d", rc);
281 /* Stop the current application */
282 val = 0;
283 mas_writemem(MAS_BANK_D0, MAS_D0_APP_SELECT, &val, 1);
286 mas_readmem(MAS_BANK_D0, MAS_D0_APP_RUNNING, &val, 1);
287 } while(val);
289 /* Enable the D/A Converter */
290 shadow_codec_reg0 = 0x0001;
291 mas_codec_writereg(0x0, shadow_codec_reg0);
293 /* ADC scale 0%, DSP scale 100% */
294 mas_codec_writereg(6, 0x0000);
295 mas_codec_writereg(7, 0x4000);
297 #ifdef HAVE_SPDIF_OUT
298 val = 0x09; /* Disable SDO and SDI, low impedance S/PDIF outputs */
299 #else
300 val = 0x2d; /* Disable SDO and SDI, disable S/PDIF output */
301 #endif
302 mas_writemem(MAS_BANK_D0, MAS_D0_INTERFACE_CONTROL, &val, 1);
304 /* Set Demand mode and validate all settings */
305 shadow_io_control_main = 0x25;
306 mas_writemem(MAS_BANK_D0, MAS_D0_IO_CONTROL_MAIN, &shadow_io_control_main, 1);
308 /* Start the Layer2/3 decoder applications */
309 val = 0x0c;
310 mas_writemem(MAS_BANK_D0, MAS_D0_APP_SELECT, &val, 1);
313 mas_readmem(MAS_BANK_D0, MAS_D0_APP_RUNNING, &val, 1);
314 } while((val & 0x0c) != 0x0c);
316 #if CONFIG_CODEC == MAS3587F
317 mpeg_mode = MPEG_DECODER;
318 #endif
320 /* set IRQ6 to edge detect */
321 ICR |= 0x02;
323 /* set IRQ6 prio 8 */
324 IPRB = ( IPRB & 0xff0f ) | 0x0080;
326 DEBUGF("MAS Decoding application started\n");
328 #endif /* #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) */
329 #endif /* SIMULATOR */
331 void mp3_init(int volume, int bass, int treble, int balance, int loudness,
332 int avc, int channel_config, int stereo_width,
333 int mdb_strength, int mdb_harmonics,
334 int mdb_center, int mdb_shape, bool mdb_enable,
335 bool superbass)
337 #ifdef SIMULATOR
338 (void)volume;
339 (void)bass;
340 (void)treble;
341 (void)balance;
342 (void)loudness;
343 (void)avc;
344 (void)channel_config;
345 (void)stereo_width;
346 (void)mdb_strength;
347 (void)mdb_harmonics;
348 (void)mdb_center;
349 (void)mdb_shape;
350 (void)mdb_enable;
351 (void)superbass;
352 #else
353 #if CONFIG_CODEC == MAS3507D
354 unsigned long val;
355 (void)loudness;
356 (void)avc;
357 (void)mdb_strength;
358 (void)mdb_harmonics;
359 (void)mdb_center;
360 (void)mdb_shape;
361 (void)mdb_enable;
362 (void)superbass;
363 #endif
365 setup_sci0();
367 #ifdef HAVE_MAS_SIBI_CONTROL
368 and_b(~0x01, &PBDRH); /* drive SIBI low */
369 or_b(0x01, &PBIORH); /* output for PB8 */
370 #endif
372 #if CONFIG_CODEC == MAS3507D
373 mas_reset();
374 #elif CONFIG_CODEC == MAS3587F
375 or_b(0x08, &PAIORH); /* output for /PR */
376 init_playback();
378 mas_version_code = mas_readver();
379 DEBUGF("MAS3587 derivate %d, version %c%d\n",
380 (mas_version_code & 0xf000) >> 12,
381 'A' + ((mas_version_code & 0x0f00) >> 8), mas_version_code & 0xff);
382 #elif CONFIG_CODEC == MAS3539F
383 or_b(0x08, &PAIORH); /* output for /PR */
384 init_playback();
386 mas_version_code = mas_readver();
387 DEBUGF("MAS3539 derivate %d, version %c%d\n",
388 (mas_version_code & 0xf000) >> 12,
389 'A' + ((mas_version_code & 0x0f00) >> 8), mas_version_code & 0xff);
390 #endif
392 #ifdef HAVE_DAC3550A
393 dac_init();
394 #endif
396 #if CONFIG_CODEC == MAS3507D
397 /* set IRQ6 to edge detect */
398 ICR |= 0x02;
400 /* set IRQ6 prio 8 */
401 IPRB = ( IPRB & 0xff0f ) | 0x0080;
403 mas_readmem(MAS_BANK_D1, 0xff7, &mas_version_code, 1);
405 mas_writereg(0x3b, 0x20); /* Don't ask why. The data sheet doesn't say */
406 mas_run(1);
407 sleep(HZ);
409 /* Clear the upper 12 bits of the 32-bit samples */
410 mas_writereg(0xc5, 0);
411 mas_writereg(0xc6, 0);
413 /* We need to set the PLL for a 14.31818MHz crystal */
414 if(mas_version_code == 0x0601) /* Version F10? */
416 val = 0x5d9d0;
417 mas_writemem(MAS_BANK_D0, 0x32d, &val, 1);
418 val = 0xfffceceb;
419 mas_writemem(MAS_BANK_D0, 0x32e, &val, 1);
420 val = 0x0;
421 mas_writemem(MAS_BANK_D0, 0x32f, &val, 1);
422 mas_run(0x475);
424 else
426 val = 0x5d9d0;
427 mas_writemem(MAS_BANK_D0, 0x36d, &val, 1);
428 val = 0xfffceceb;
429 mas_writemem(MAS_BANK_D0, 0x36e, &val, 1);
430 val = 0x0;
431 mas_writemem(MAS_BANK_D0, 0x36f, &val, 1);
432 mas_run(0xfcb);
435 #endif
437 #if CONFIG_CODEC == MAS3507D
438 mas_poll_start();
440 mas_writereg(MAS_REG_KPRESCALE, 0xe9400);
441 dac_enable(true);
442 #endif
444 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
445 ICR &= ~0x0010; /* IRQ3 level sensitive */
446 PACR1 = (PACR1 & 0x3fff) | 0x4000; /* PA15 is IRQ3 */
447 #endif
449 /* Must be done before calling sound_set() */
450 audio_is_initialized = true;
452 sound_set(SOUND_BASS, bass);
453 sound_set(SOUND_TREBLE, treble);
454 sound_set(SOUND_BALANCE, balance);
455 sound_set(SOUND_VOLUME, volume);
456 sound_set(SOUND_CHANNELS, channel_config);
457 sound_set(SOUND_STEREO_WIDTH, stereo_width);
459 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
460 sound_set(SOUND_LOUDNESS, loudness);
461 sound_set(SOUND_AVC, avc);
462 sound_set(SOUND_MDB_STRENGTH, mdb_strength);
463 sound_set(SOUND_MDB_HARMONICS, mdb_harmonics);
464 sound_set(SOUND_MDB_CENTER, mdb_center);
465 sound_set(SOUND_MDB_SHAPE, mdb_shape);
466 sound_set(SOUND_MDB_ENABLE, mdb_enable);
467 sound_set(SOUND_SUPERBASS, superbass);
468 #endif
469 #endif /* !SIMULATOR */
471 playing = false;
472 paused = true;
475 void mp3_shutdown(void)
477 #ifndef SIMULATOR
478 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
479 unsigned long val = 1;
480 mas_writemem(MAS_BANK_D0, MAS_D0_SOFT_MUTE, &val, 1); /* Mute */
481 #endif
483 #if CONFIG_CODEC == MAS3507D
484 dac_volume(0, 0, false);
485 #endif
487 #endif
490 /* new functions, to be exported to plugin API */
492 #ifndef SIMULATOR
494 void mp3_play_init(void)
496 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
497 init_playback();
498 #endif
499 playing = false;
500 paused = true;
501 callback_for_more = NULL;
502 mp3_reset_playtime();
505 void mp3_play_data(const unsigned char* start, int size,
506 void (*get_more)(unsigned char** start, int* size) /* callback fn */
509 /* init DMA */
510 DAR3 = 0x5FFFEC3;
511 CHCR3 &= ~0x0002; /* Clear interrupt */
512 CHCR3 = 0x1504; /* Single address destination, TXI0, IE=1 */
513 DMAOR = 0x0001; /* Enable DMA */
515 callback_for_more = get_more;
517 SAR3 = (unsigned int)start;
518 DTCR3 = size & 0xffff;
520 playing = true;
521 paused = true;
523 CHCR3 |= 0x0001; /* Enable DMA IRQ */
525 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
526 demand_irq_enable(true);
527 #endif
530 void mp3_play_pause(bool play)
532 if (paused && play)
533 { /* resume playback */
534 SCR0 |= 0x80;
535 paused = false;
536 playstart_tick = current_tick;
538 else if (!paused && !play)
539 { /* stop playback */
540 SCR0 &= 0x7f;
541 paused = true;
542 cumulative_ticks += current_tick - playstart_tick;
546 bool mp3_pause_done(void)
548 unsigned long frame_count;
550 if (!paused)
551 return false;
553 mas_readmem(MAS_BANK_D0, MAS_D0_MPEG_FRAME_COUNT, &frame_count, 1);
554 /* This works because the frame counter never wraps,
555 * i.e. zero always means lost sync. */
556 return frame_count == 0;
559 void mp3_play_stop(void)
561 playing = false;
562 mp3_play_pause(false);
563 CHCR3 &= ~0x0001; /* Disable the DMA interrupt */
564 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
565 demand_irq_enable(false);
566 #endif
569 long mp3_get_playtime(void)
571 if (paused)
572 return cumulative_ticks;
573 else
574 return cumulative_ticks + current_tick - playstart_tick;
577 void mp3_reset_playtime(void)
579 cumulative_ticks = 0;
580 playstart_tick = current_tick;
583 bool mp3_is_playing(void)
585 return playing;
589 /* returns the next byte position which would be transferred */
590 unsigned char* mp3_get_pos(void)
592 return (unsigned char*)SAR3;
596 #endif /* #ifndef SIMULATOR */
598 #else /* CONFIG_CODEC != SWCODEC */
599 void mp3_init(int volume, int bass, int treble, int balance, int loudness,
600 int avc, int channel_config, int stereo_width,
601 int mdb_strength, int mdb_harmonics,
602 int mdb_center, int mdb_shape, bool mdb_enable,
603 bool superbass)
605 /* a dummy */
606 (void)volume;
607 (void)bass;
608 (void)treble;
609 (void)balance;
610 (void)loudness;
611 (void)avc;
612 (void)channel_config;
613 (void)stereo_width;
614 (void)mdb_strength;
615 (void)mdb_harmonics;
616 (void)mdb_center;
617 (void)mdb_shape;
618 (void)mdb_enable;
619 (void)superbass;
621 paused = false;
622 playing = false;
623 #ifndef SIMULATOR
624 playstart_tick = 0;
625 cumulative_ticks = 0;
626 callback_for_more = 0;
627 #endif
630 void mp3_shutdown(void)
632 /* a dummy */
635 void mp3_play_pause(bool play)
637 /* a dummy */
638 (void)play;
641 unsigned char* mp3_get_pos(void)
643 /* a dummy */
644 return (unsigned char *)0x1234;
647 bool mp3_is_playing(void)
649 return playing;
652 #endif /* CONFIG_CODEC == SWCODEC */