forked from len0rd/rockbox
Moved the low-level playback functionality into a new, separate module "mp3_playback". This e.g. allows to export a memory playback API to the plugins, opens the door to games with sound, UI sounds, etc.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@4192 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
974c2f0d43
commit
f993365447
11 changed files with 1081 additions and 930 deletions
35
apps/main.c
35
apps/main.c
|
@ -37,6 +37,7 @@
|
|||
#include "serial.h"
|
||||
#endif
|
||||
#include "mpeg.h"
|
||||
#include "mp3_playback.h"
|
||||
#include "main_menu.h"
|
||||
#include "thread.h"
|
||||
#include "settings.h"
|
||||
|
@ -78,14 +79,15 @@ void init(void)
|
|||
sleep(HZ/2);
|
||||
tree_init();
|
||||
playlist_init();
|
||||
mpeg_init( global_settings.volume,
|
||||
global_settings.bass,
|
||||
global_settings.treble,
|
||||
global_settings.balance,
|
||||
global_settings.loudness,
|
||||
global_settings.bass_boost,
|
||||
global_settings.avc,
|
||||
global_settings.channel_config );
|
||||
mp3_init( global_settings.volume,
|
||||
global_settings.bass,
|
||||
global_settings.treble,
|
||||
global_settings.balance,
|
||||
global_settings.loudness,
|
||||
global_settings.bass_boost,
|
||||
global_settings.avc,
|
||||
global_settings.channel_config );
|
||||
mpeg_init();
|
||||
while (button_get(false) != 0)
|
||||
; /* Empty the keyboard buffer */
|
||||
}
|
||||
|
@ -197,14 +199,15 @@ void init(void)
|
|||
|
||||
/* No buffer allocation (see buffer.c) may take place after the call to
|
||||
mpeg_init() since the mpeg thread takes the rest of the buffer space */
|
||||
mpeg_init( global_settings.volume,
|
||||
global_settings.bass,
|
||||
global_settings.treble,
|
||||
global_settings.balance,
|
||||
global_settings.loudness,
|
||||
global_settings.bass_boost,
|
||||
global_settings.avc,
|
||||
global_settings.channel_config );
|
||||
mp3_init( global_settings.volume,
|
||||
global_settings.bass,
|
||||
global_settings.treble,
|
||||
global_settings.balance,
|
||||
global_settings.loudness,
|
||||
global_settings.bass_boost,
|
||||
global_settings.avc,
|
||||
global_settings.channel_config );
|
||||
mpeg_init();
|
||||
|
||||
/* no auto-rolo on startup any more, but I leave it here for reference */
|
||||
#if 0
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "system.h"
|
||||
#include "lcd.h"
|
||||
#include "mpeg.h"
|
||||
#include "mp3_playback.h"
|
||||
#include "mas.h"
|
||||
#include "button.h"
|
||||
#include "kernel.h"
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "icons.h"
|
||||
#include "font.h"
|
||||
#include "mpeg.h"
|
||||
#include "mp3_playback.h"
|
||||
#include "usb.h"
|
||||
#include "settings.h"
|
||||
#include "status.h"
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include "backlight.h"
|
||||
#include "lcd.h"
|
||||
#include "mpeg.h"
|
||||
#include "mp3_playback.h"
|
||||
#include "string.h"
|
||||
#include "ata.h"
|
||||
#include "fat.h"
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
#include "lcd.h"
|
||||
#include "menu.h"
|
||||
#include "button.h"
|
||||
#include "mpeg.h"
|
||||
#include "mp3_playback.h"
|
||||
#include "settings.h"
|
||||
#include "status.h"
|
||||
#include "screens.h"
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
#include "thread.h"
|
||||
#include "settings.h"
|
||||
#include "status.h"
|
||||
#include "mpeg.h"
|
||||
#include "mp3_playback.h"
|
||||
#include "wps.h"
|
||||
#ifdef HAVE_RTC
|
||||
#include "timefuncs.h"
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include "wps.h"
|
||||
#include "wps-display.h"
|
||||
#include "mpeg.h"
|
||||
#include "mp3_playback.h"
|
||||
#include "usb.h"
|
||||
#include "status.h"
|
||||
#include "main_menu.h"
|
||||
|
|
73
firmware/export/mp3_playback.h
Normal file
73
firmware/export/mp3_playback.h
Normal file
|
@ -0,0 +1,73 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id$
|
||||
*
|
||||
* Code that has been in mpeg.c/h before, now creating an encapsulated play
|
||||
* data module, to be used by other sources than file playback as well.
|
||||
*
|
||||
* Copyright (C) 2004 by Linus Nielsen Feltzing
|
||||
*
|
||||
* All files in this archive are subject to the GNU General Public License.
|
||||
* See the file COPYING in the source tree root for full license agreement.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
****************************************************************************/
|
||||
#ifndef _MP3_PLAYBACK_H_
|
||||
#define _MP3_PLAYBACK_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
/* functions formerly in mpeg.c */
|
||||
void mp3_init(int volume, int bass, int treble, int balance,
|
||||
int loudness, int bass_boost, int avc, int channel_config);
|
||||
void mpeg_sound_set(int setting, int value);
|
||||
int mpeg_sound_min(int setting);
|
||||
int mpeg_sound_max(int setting);
|
||||
int mpeg_sound_default(int setting);
|
||||
void mpeg_sound_channel_config(int configuration);
|
||||
int mpeg_val2phys(int setting, int value);
|
||||
int mpeg_phys2val(int setting, int value);
|
||||
char *mpeg_sound_unit(int setting);
|
||||
int mpeg_sound_numdecimals(int setting);
|
||||
#if defined(HAVE_MAS3587F) || defined(SIMULATOR)
|
||||
void mpeg_set_pitch(int percent);
|
||||
#endif
|
||||
|
||||
/* new functions, to be exported to plugin API */
|
||||
void mp3_play_init(void);
|
||||
void mp3_play_data(unsigned char* start, int size,
|
||||
void (*get_more)(unsigned char** start, int* size) /* callback fn */
|
||||
);
|
||||
void mp3_play_pause(bool play);
|
||||
void mp3_play_stop(void);
|
||||
|
||||
|
||||
#define SOUND_VOLUME 0
|
||||
#define SOUND_BASS 1
|
||||
#define SOUND_TREBLE 2
|
||||
#define SOUND_BALANCE 3
|
||||
#define SOUND_LOUDNESS 4
|
||||
#define SOUND_SUPERBASS 5
|
||||
#define SOUND_AVC 6
|
||||
#define SOUND_CHANNELS 7
|
||||
#define SOUND_LEFT_GAIN 8
|
||||
#define SOUND_RIGHT_GAIN 9
|
||||
#define SOUND_MIC_GAIN 10
|
||||
#define SOUND_NUMSETTINGS 11
|
||||
|
||||
#define MPEG_SOUND_STEREO 0
|
||||
#define MPEG_SOUND_STEREO_NARROW 1
|
||||
#define MPEG_SOUND_MONO 2
|
||||
#define MPEG_SOUND_MONO_LEFT 3
|
||||
#define MPEG_SOUND_MONO_RIGHT 4
|
||||
#define MPEG_SOUND_KARAOKE 5
|
||||
#define MPEG_SOUND_STEREO_WIDE 6
|
||||
|
||||
#endif /* #ifndef _MP3_PLAYBACK_H_ */
|
|
@ -61,8 +61,7 @@ struct mpeg_debug
|
|||
int lowest_watermark_level;
|
||||
};
|
||||
|
||||
void mpeg_init(int volume, int bass, int treble, int balance,
|
||||
int loudness, int bass_boost, int avc, int channel_config);
|
||||
void mpeg_init(void);
|
||||
void mpeg_play(int offset);
|
||||
void mpeg_stop(void);
|
||||
void mpeg_pause(void);
|
||||
|
@ -71,20 +70,10 @@ void mpeg_next(void);
|
|||
void mpeg_prev(void);
|
||||
void mpeg_ff_rewind(int newtime);
|
||||
void mpeg_flush_and_reload_tracks(void);
|
||||
void mpeg_sound_set(int setting, int value);
|
||||
int mpeg_sound_min(int setting);
|
||||
int mpeg_sound_max(int setting);
|
||||
int mpeg_sound_default(int setting);
|
||||
void mpeg_sound_channel_config(int configuration);
|
||||
int mpeg_val2phys(int setting, int value);
|
||||
int mpeg_phys2val(int setting, int value);
|
||||
char *mpeg_sound_unit(int setting);
|
||||
int mpeg_sound_numdecimals(int setting);
|
||||
struct mp3entry* mpeg_current_track(void);
|
||||
bool mpeg_has_changed_track(void);
|
||||
int mpeg_status(void);
|
||||
#if defined(HAVE_MAS3587F) || defined(SIMULATOR)
|
||||
void mpeg_set_pitch(int percent);
|
||||
void mpeg_init_recording(void);
|
||||
void mpeg_init_playback(void);
|
||||
void mpeg_record(char *filename);
|
||||
|
@ -101,27 +90,6 @@ void mpeg_set_buffer_margin(int seconds);
|
|||
unsigned int mpeg_error(void);
|
||||
void mpeg_error_clear(void);
|
||||
|
||||
#define SOUND_VOLUME 0
|
||||
#define SOUND_BASS 1
|
||||
#define SOUND_TREBLE 2
|
||||
#define SOUND_BALANCE 3
|
||||
#define SOUND_LOUDNESS 4
|
||||
#define SOUND_SUPERBASS 5
|
||||
#define SOUND_AVC 6
|
||||
#define SOUND_CHANNELS 7
|
||||
#define SOUND_LEFT_GAIN 8
|
||||
#define SOUND_RIGHT_GAIN 9
|
||||
#define SOUND_MIC_GAIN 10
|
||||
#define SOUND_NUMSETTINGS 11
|
||||
|
||||
#define MPEG_SOUND_STEREO 0
|
||||
#define MPEG_SOUND_STEREO_NARROW 1
|
||||
#define MPEG_SOUND_MONO 2
|
||||
#define MPEG_SOUND_MONO_LEFT 3
|
||||
#define MPEG_SOUND_MONO_RIGHT 4
|
||||
#define MPEG_SOUND_KARAOKE 5
|
||||
#define MPEG_SOUND_STEREO_WIDE 6
|
||||
|
||||
#define MPEG_STATUS_PLAY 1
|
||||
#define MPEG_STATUS_PAUSE 2
|
||||
#define MPEG_STATUS_RECORD 4
|
||||
|
|
939
firmware/mp3_playback.c
Normal file
939
firmware/mp3_playback.c
Normal file
|
@ -0,0 +1,939 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id$
|
||||
*
|
||||
* Code that has been in mpeg.c before, now creating an encapsulated play
|
||||
* data module, to be used by other sources than file playback as well.
|
||||
*
|
||||
* Copyright (C) 2004 by Linus Nielsen Feltzing
|
||||
*
|
||||
* All files in this archive are subject to the GNU General Public License.
|
||||
* See the file COPYING in the source tree root for full license agreement.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
****************************************************************************/
|
||||
#include <stdbool.h>
|
||||
#include "config.h"
|
||||
#include "debug.h"
|
||||
#include "panic.h"
|
||||
#include <kernel.h>
|
||||
#include "mpeg.h" /* ToDo: remove crosslinks */
|
||||
#include "mp3_playback.h"
|
||||
#ifndef SIMULATOR
|
||||
#include "i2c.h"
|
||||
#include "mas.h"
|
||||
#include "dac.h"
|
||||
#include "system.h"
|
||||
#include "hwcompat.h"
|
||||
#endif
|
||||
|
||||
static char *units[] =
|
||||
{
|
||||
"%", /* Volume */
|
||||
"dB", /* Bass */
|
||||
"dB", /* Treble */
|
||||
"%", /* Balance */
|
||||
"dB", /* Loudness */
|
||||
"%", /* Bass boost */
|
||||
"", /* AVC */
|
||||
"", /* Channels */
|
||||
"dB", /* Left gain */
|
||||
"dB", /* Right gain */
|
||||
"dB", /* Mic gain */
|
||||
};
|
||||
|
||||
static int numdecimals[] =
|
||||
{
|
||||
0, /* Volume */
|
||||
0, /* Bass */
|
||||
0, /* Treble */
|
||||
0, /* Balance */
|
||||
0, /* Loudness */
|
||||
0, /* Bass boost */
|
||||
0, /* AVC */
|
||||
0, /* Channels */
|
||||
1, /* Left gain */
|
||||
1, /* Right gain */
|
||||
1, /* Mic gain */
|
||||
};
|
||||
|
||||
static int minval[] =
|
||||
{
|
||||
0, /* Volume */
|
||||
0, /* Bass */
|
||||
0, /* Treble */
|
||||
-50, /* Balance */
|
||||
0, /* Loudness */
|
||||
0, /* Bass boost */
|
||||
-1, /* AVC */
|
||||
0, /* Channels */
|
||||
0, /* Left gain */
|
||||
0, /* Right gain */
|
||||
0, /* Mic gain */
|
||||
};
|
||||
|
||||
static int maxval[] =
|
||||
{
|
||||
100, /* Volume */
|
||||
#ifdef HAVE_MAS3587F
|
||||
24, /* Bass */
|
||||
24, /* Treble */
|
||||
#else
|
||||
30, /* Bass */
|
||||
30, /* Treble */
|
||||
#endif
|
||||
50, /* Balance */
|
||||
17, /* Loudness */
|
||||
10, /* Bass boost */
|
||||
3, /* AVC */
|
||||
6, /* Channels */
|
||||
15, /* Left gain */
|
||||
15, /* Right gain */
|
||||
15, /* Mic gain */
|
||||
};
|
||||
|
||||
static int defaultval[] =
|
||||
{
|
||||
70, /* Volume */
|
||||
#ifdef HAVE_MAS3587F
|
||||
12+6, /* Bass */
|
||||
12+6, /* Treble */
|
||||
#else
|
||||
15+7, /* Bass */
|
||||
15+7, /* Treble */
|
||||
#endif
|
||||
0, /* Balance */
|
||||
0, /* Loudness */
|
||||
0, /* Bass boost */
|
||||
0, /* AVC */
|
||||
0, /* Channels */
|
||||
8, /* Left gain */
|
||||
8, /* Right gain */
|
||||
2, /* Mic gain */
|
||||
};
|
||||
|
||||
char *mpeg_sound_unit(int setting)
|
||||
{
|
||||
return units[setting];
|
||||
}
|
||||
|
||||
int mpeg_sound_numdecimals(int setting)
|
||||
{
|
||||
return numdecimals[setting];
|
||||
}
|
||||
|
||||
int mpeg_sound_min(int setting)
|
||||
{
|
||||
return minval[setting];
|
||||
}
|
||||
|
||||
int mpeg_sound_max(int setting)
|
||||
{
|
||||
return maxval[setting];
|
||||
}
|
||||
|
||||
int mpeg_sound_default(int setting)
|
||||
{
|
||||
return defaultval[setting];
|
||||
}
|
||||
|
||||
/* list of tracks in memory */
|
||||
#define MAX_ID3_TAGS (1<<4) /* Must be power of 2 */
|
||||
#define MAX_ID3_TAGS_MASK (MAX_ID3_TAGS - 1)
|
||||
|
||||
#ifndef SIMULATOR
|
||||
static bool mpeg_is_initialized = false;
|
||||
#endif
|
||||
|
||||
#ifndef SIMULATOR
|
||||
|
||||
unsigned long mas_version_code;
|
||||
|
||||
#ifdef HAVE_MAS3507D
|
||||
|
||||
static unsigned int bass_table[] =
|
||||
{
|
||||
0x9e400, /* -15dB */
|
||||
0xa2800, /* -14dB */
|
||||
0xa7400, /* -13dB */
|
||||
0xac400, /* -12dB */
|
||||
0xb1800, /* -11dB */
|
||||
0xb7400, /* -10dB */
|
||||
0xbd400, /* -9dB */
|
||||
0xc3c00, /* -8dB */
|
||||
0xca400, /* -7dB */
|
||||
0xd1800, /* -6dB */
|
||||
0xd8c00, /* -5dB */
|
||||
0xe0400, /* -4dB */
|
||||
0xe8000, /* -3dB */
|
||||
0xefc00, /* -2dB */
|
||||
0xf7c00, /* -1dB */
|
||||
0,
|
||||
0x800, /* 1dB */
|
||||
0x10000, /* 2dB */
|
||||
0x17c00, /* 3dB */
|
||||
0x1f800, /* 4dB */
|
||||
0x27000, /* 5dB */
|
||||
0x2e400, /* 6dB */
|
||||
0x35800, /* 7dB */
|
||||
0x3c000, /* 8dB */
|
||||
0x42800, /* 9dB */
|
||||
0x48800, /* 10dB */
|
||||
0x4e400, /* 11dB */
|
||||
0x53800, /* 12dB */
|
||||
0x58800, /* 13dB */
|
||||
0x5d400, /* 14dB */
|
||||
0x61800 /* 15dB */
|
||||
};
|
||||
|
||||
static unsigned int treble_table[] =
|
||||
{
|
||||
0xb2c00, /* -15dB */
|
||||
0xbb400, /* -14dB */
|
||||
0xc1800, /* -13dB */
|
||||
0xc6c00, /* -12dB */
|
||||
0xcbc00, /* -11dB */
|
||||
0xd0400, /* -10dB */
|
||||
0xd5000, /* -9dB */
|
||||
0xd9800, /* -8dB */
|
||||
0xde000, /* -7dB */
|
||||
0xe2800, /* -6dB */
|
||||
0xe7e00, /* -5dB */
|
||||
0xec000, /* -4dB */
|
||||
0xf0c00, /* -3dB */
|
||||
0xf5c00, /* -2dB */
|
||||
0xfac00, /* -1dB */
|
||||
0,
|
||||
0x5400, /* 1dB */
|
||||
0xac00, /* 2dB */
|
||||
0x10400, /* 3dB */
|
||||
0x16000, /* 4dB */
|
||||
0x1c000, /* 5dB */
|
||||
0x22400, /* 6dB */
|
||||
0x28400, /* 7dB */
|
||||
0x2ec00, /* 8dB */
|
||||
0x35400, /* 9dB */
|
||||
0x3c000, /* 10dB */
|
||||
0x42c00, /* 11dB */
|
||||
0x49c00, /* 12dB */
|
||||
0x51800, /* 13dB */
|
||||
0x58400, /* 14dB */
|
||||
0x5f800 /* 15dB */
|
||||
};
|
||||
|
||||
static unsigned int prescale_table[] =
|
||||
{
|
||||
0x80000, /* 0db */
|
||||
0x8e000, /* 1dB */
|
||||
0x9a400, /* 2dB */
|
||||
0xa5800, /* 3dB */
|
||||
0xaf400, /* 4dB */
|
||||
0xb8000, /* 5dB */
|
||||
0xbfc00, /* 6dB */
|
||||
0xc6c00, /* 7dB */
|
||||
0xcd000, /* 8dB */
|
||||
0xd25c0, /* 9dB */
|
||||
0xd7800, /* 10dB */
|
||||
0xdc000, /* 11dB */
|
||||
0xdfc00, /* 12dB */
|
||||
0xe3400, /* 13dB */
|
||||
0xe6800, /* 14dB */
|
||||
0xe9400 /* 15dB */
|
||||
};
|
||||
#endif
|
||||
|
||||
bool dma_on; /* The DMA is active */
|
||||
|
||||
#ifdef HAVE_MAS3507D
|
||||
static void mas_poll_start(int interval_in_ms)
|
||||
{
|
||||
unsigned int count;
|
||||
|
||||
count = (FREQ * interval_in_ms) / 1000 / 8;
|
||||
|
||||
if(count > 0xffff)
|
||||
{
|
||||
panicf("Error! The MAS poll interval is too long (%d ms)\n",
|
||||
interval_in_ms);
|
||||
return;
|
||||
}
|
||||
|
||||
/* We are using timer 1 */
|
||||
|
||||
TSTR &= ~0x02; /* Stop the timer */
|
||||
TSNC &= ~0x02; /* No synchronization */
|
||||
TMDR &= ~0x02; /* Operate normally */
|
||||
|
||||
TCNT1 = 0; /* Start counting at 0 */
|
||||
GRA1 = count;
|
||||
TCR1 = 0x23; /* Clear at GRA match, sysclock/8 */
|
||||
|
||||
/* Enable interrupt on level 5 */
|
||||
IPRC = (IPRC & ~0x000f) | 0x0005;
|
||||
|
||||
TSR1 &= ~0x02;
|
||||
TIER1 = 0xf9; /* Enable GRA match interrupt */
|
||||
|
||||
TSTR |= 0x02; /* Start timer 1 */
|
||||
}
|
||||
#endif
|
||||
|
||||
/* the registered callback function ta ask for more mp3 data */
|
||||
static void (*callback_for_more)(unsigned char**, int*);
|
||||
|
||||
#pragma interrupt
|
||||
void DEI3(void)
|
||||
{
|
||||
unsigned char* start;
|
||||
int size = 0;
|
||||
|
||||
if (callback_for_more != NULL)
|
||||
{
|
||||
callback_for_more(&start, &size);
|
||||
}
|
||||
|
||||
if (size > 0)
|
||||
{
|
||||
DTCR3 = size & 0xffff;
|
||||
SAR3 = (unsigned int) start;
|
||||
}
|
||||
else
|
||||
{
|
||||
CHCR3 &= ~0x0001; /* Disable the DMA interrupt */
|
||||
}
|
||||
|
||||
CHCR3 &= ~0x0002; /* Clear DMA interrupt */
|
||||
}
|
||||
|
||||
#pragma interrupt
|
||||
void IRQ6(void) /* PB14: MAS stop demand IRQ */
|
||||
{
|
||||
mp3_play_pause(false);
|
||||
}
|
||||
|
||||
static void setup_sci0(void)
|
||||
{
|
||||
/* PB15 is I/O, PB14 is IRQ6, PB12 is SCK0, PB9 is TxD0 */
|
||||
PBCR1 = (PBCR1 & 0x0cff) | 0x1208;
|
||||
|
||||
/* Set PB12 to output */
|
||||
or_b(0x10, &PBIORH);
|
||||
|
||||
/* Disable serial port */
|
||||
SCR0 = 0x00;
|
||||
|
||||
/* Synchronous, no prescale */
|
||||
SMR0 = 0x80;
|
||||
|
||||
/* Set baudrate 1Mbit/s */
|
||||
BRR0 = 0x03;
|
||||
|
||||
/* use SCK as serial clock output */
|
||||
SCR0 = 0x01;
|
||||
|
||||
/* Clear FER and PER */
|
||||
SSR0 &= 0xe7;
|
||||
|
||||
/* Set interrupt ITU2 and SCI0 priority to 0 */
|
||||
IPRD &= 0x0ff0;
|
||||
|
||||
/* set PB15 and PB14 to inputs */
|
||||
and_b(~0x80, &PBIORH);
|
||||
and_b(~0x40, &PBIORH);
|
||||
|
||||
/* Enable End of DMA interrupt at prio 8 */
|
||||
IPRC = (IPRC & 0xf0ff) | 0x0800;
|
||||
|
||||
/* Enable Tx (only!) */
|
||||
SCR0 |= 0x20;
|
||||
}
|
||||
#endif /* SIMULATOR */
|
||||
|
||||
#ifdef HAVE_MAS3587F
|
||||
static void init_playback(void)
|
||||
{
|
||||
unsigned long val;
|
||||
int rc;
|
||||
|
||||
mp3_play_pause(false);
|
||||
|
||||
mas_reset();
|
||||
|
||||
/* Enable the audio CODEC and the DSP core, max analog voltage range */
|
||||
rc = mas_direct_config_write(MAS_CONTROL, 0x8c00);
|
||||
if(rc < 0)
|
||||
panicf("mas_ctrl_w: %d", rc);
|
||||
|
||||
/* Stop the current application */
|
||||
val = 0;
|
||||
mas_writemem(MAS_BANK_D0,0x7f6,&val,1);
|
||||
do
|
||||
{
|
||||
mas_readmem(MAS_BANK_D0, 0x7f7, &val, 1);
|
||||
} while(val);
|
||||
|
||||
/* Enable the D/A Converter */
|
||||
mas_codec_writereg(0x0, 0x0001);
|
||||
|
||||
/* ADC scale 0%, DSP scale 100% */
|
||||
mas_codec_writereg(6, 0x0000);
|
||||
mas_codec_writereg(7, 0x4000);
|
||||
|
||||
/* Disable SDO and SDI */
|
||||
val = 0x0d;
|
||||
mas_writemem(MAS_BANK_D0,0x7f2,&val,1);
|
||||
|
||||
/* Set Demand mode and validate all settings */
|
||||
val = 0x25;
|
||||
mas_writemem(MAS_BANK_D0,0x7f1,&val,1);
|
||||
|
||||
/* Start the Layer2/3 decoder applications */
|
||||
val = 0x0c;
|
||||
mas_writemem(MAS_BANK_D0,0x7f6,&val,1);
|
||||
do
|
||||
{
|
||||
mas_readmem(MAS_BANK_D0, 0x7f7, &val, 1);
|
||||
} while((val & 0x0c) != 0x0c);
|
||||
|
||||
mpeg_sound_channel_config(MPEG_SOUND_STEREO);
|
||||
|
||||
/* set IRQ6 to edge detect */
|
||||
ICR |= 0x02;
|
||||
|
||||
/* set IRQ6 prio 8 */
|
||||
IPRB = ( IPRB & 0xff0f ) | 0x0080;
|
||||
|
||||
DEBUGF("MAS Decoding application started\n");
|
||||
}
|
||||
#endif /* #ifdef HAVE_MAS3587F */
|
||||
|
||||
#ifndef SIMULATOR
|
||||
#ifdef HAVE_MAS3507D
|
||||
int current_left_volume = 0; /* all values in tenth of dB */
|
||||
int current_right_volume = 0; /* all values in tenth of dB */
|
||||
int current_treble = 0;
|
||||
int current_bass = 0;
|
||||
int current_balance = 0;
|
||||
|
||||
/* convert tenth of dB volume to register value */
|
||||
static int tenthdb2reg(int db) {
|
||||
if (db < -540)
|
||||
return (db + 780) / 30;
|
||||
else
|
||||
return (db + 660) / 15;
|
||||
}
|
||||
|
||||
void set_prescaled_volume(void)
|
||||
{
|
||||
int prescale;
|
||||
int l, r;
|
||||
|
||||
prescale = MAX(current_bass, current_treble);
|
||||
if (prescale < 0)
|
||||
prescale = 0; /* no need to prescale if we don't boost
|
||||
bass or treble */
|
||||
|
||||
mas_writereg(MAS_REG_KPRESCALE, prescale_table[prescale/10]);
|
||||
|
||||
/* gain up the analog volume to compensate the prescale reduction gain */
|
||||
l = current_left_volume + prescale;
|
||||
r = current_right_volume + prescale;
|
||||
|
||||
dac_volume(tenthdb2reg(l), tenthdb2reg(r), false);
|
||||
}
|
||||
#endif /* HAVE_MAS3507D */
|
||||
#endif /* !SIMULATOR */
|
||||
|
||||
void mpeg_sound_set(int setting, int value)
|
||||
{
|
||||
#ifdef SIMULATOR
|
||||
setting = value;
|
||||
#else
|
||||
#ifdef HAVE_MAS3507D
|
||||
int l, r;
|
||||
#else
|
||||
int tmp;
|
||||
#endif
|
||||
|
||||
if(!mpeg_is_initialized)
|
||||
return;
|
||||
|
||||
switch(setting)
|
||||
{
|
||||
case SOUND_VOLUME:
|
||||
#ifdef HAVE_MAS3587F
|
||||
tmp = 0x7f00 * value / 100;
|
||||
mas_codec_writereg(0x10, tmp & 0xff00);
|
||||
#else
|
||||
l = value;
|
||||
r = value;
|
||||
|
||||
if(current_balance > 0)
|
||||
{
|
||||
l -= current_balance;
|
||||
if(l < 0)
|
||||
l = 0;
|
||||
}
|
||||
|
||||
if(current_balance < 0)
|
||||
{
|
||||
r += current_balance;
|
||||
if(r < 0)
|
||||
r = 0;
|
||||
}
|
||||
|
||||
l = 0x38 * l / 100;
|
||||
r = 0x38 * r / 100;
|
||||
|
||||
/* store volume in tenth of dB */
|
||||
current_left_volume = ( l < 0x08 ? l*30 - 780 : l*15 - 660 );
|
||||
current_right_volume = ( r < 0x08 ? r*30 - 780 : r*15 - 660 );
|
||||
|
||||
set_prescaled_volume();
|
||||
#endif
|
||||
break;
|
||||
|
||||
case SOUND_BALANCE:
|
||||
#ifdef HAVE_MAS3587F
|
||||
tmp = ((value * 127 / 100) & 0xff) << 8;
|
||||
mas_codec_writereg(0x11, tmp & 0xff00);
|
||||
#else
|
||||
/* Convert to percent */
|
||||
current_balance = value * 2;
|
||||
#endif
|
||||
break;
|
||||
|
||||
case SOUND_BASS:
|
||||
#ifdef HAVE_MAS3587F
|
||||
tmp = (((value-12) * 8) & 0xff) << 8;
|
||||
mas_codec_writereg(0x14, tmp & 0xff00);
|
||||
#else
|
||||
mas_writereg(MAS_REG_KBASS, bass_table[value]);
|
||||
current_bass = (value-15) * 10;
|
||||
set_prescaled_volume();
|
||||
#endif
|
||||
break;
|
||||
|
||||
case SOUND_TREBLE:
|
||||
#ifdef HAVE_MAS3587F
|
||||
tmp = (((value-12) * 8) & 0xff) << 8;
|
||||
mas_codec_writereg(0x15, tmp & 0xff00);
|
||||
#else
|
||||
mas_writereg(MAS_REG_KTREBLE, treble_table[value]);
|
||||
current_treble = (value-15) * 10;
|
||||
set_prescaled_volume();
|
||||
#endif
|
||||
break;
|
||||
|
||||
#ifdef HAVE_MAS3587F
|
||||
case SOUND_SUPERBASS:
|
||||
if (value) {
|
||||
tmp = MAX(MIN(value * 12, 0x7f), 0);
|
||||
mas_codec_writereg(MAS_REG_KMDB_STR, (tmp & 0xff) << 8);
|
||||
tmp = 0x30; /* MDB_HAR: Space for experiment here */
|
||||
mas_codec_writereg(MAS_REG_KMDB_HAR, (tmp & 0xff) << 8);
|
||||
tmp = 60 / 10; /* calculate MDB_FC, 60hz - experiment here,
|
||||
this would depend on the earphones...
|
||||
perhaps make it tunable? */
|
||||
mas_codec_writereg(MAS_REG_KMDB_FC, (tmp & 0xff) << 8);
|
||||
tmp = (3 * tmp) / 2; /* calculate MDB_SHAPE */
|
||||
mas_codec_writereg(MAS_REG_KMDB_SWITCH,
|
||||
((tmp & 0xff) << 8) /* MDB_SHAPE */
|
||||
| 2); /* MDB_SWITCH enable */
|
||||
} else {
|
||||
mas_codec_writereg(MAS_REG_KMDB_STR, 0);
|
||||
mas_codec_writereg(MAS_REG_KMDB_HAR, 0);
|
||||
mas_codec_writereg(MAS_REG_KMDB_SWITCH, 0); /* MDB_SWITCH disable */
|
||||
}
|
||||
break;
|
||||
|
||||
case SOUND_LOUDNESS:
|
||||
tmp = MAX(MIN(value * 4, 0x44), 0);
|
||||
mas_codec_writereg(MAS_REG_KLOUDNESS, (tmp & 0xff) << 8);
|
||||
break;
|
||||
|
||||
case SOUND_AVC:
|
||||
switch (value) {
|
||||
case 1: /* 2s */
|
||||
tmp = (0x2 << 8) | (0x8 << 12);
|
||||
break;
|
||||
case 2: /* 4s */
|
||||
tmp = (0x4 << 8) | (0x8 << 12);
|
||||
break;
|
||||
case 3: /* 8s */
|
||||
tmp = (0x8 << 8) | (0x8 << 12);
|
||||
break;
|
||||
case -1: /* turn off and then turn on again to decay quickly */
|
||||
tmp = mas_codec_readreg(MAS_REG_KAVC);
|
||||
mas_codec_writereg(MAS_REG_KAVC, 0);
|
||||
break;
|
||||
default: /* off */
|
||||
tmp = 0;
|
||||
break;
|
||||
}
|
||||
mas_codec_writereg(MAS_REG_KAVC, tmp);
|
||||
break;
|
||||
#endif
|
||||
case SOUND_CHANNELS:
|
||||
mpeg_sound_channel_config(value);
|
||||
break;
|
||||
}
|
||||
#endif /* SIMULATOR */
|
||||
}
|
||||
|
||||
int mpeg_val2phys(int setting, int value)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
switch(setting)
|
||||
{
|
||||
case SOUND_VOLUME:
|
||||
result = value;
|
||||
break;
|
||||
|
||||
case SOUND_BALANCE:
|
||||
result = value * 2;
|
||||
break;
|
||||
|
||||
case SOUND_BASS:
|
||||
#ifdef HAVE_MAS3587F
|
||||
result = value - 12;
|
||||
#else
|
||||
result = value - 15;
|
||||
#endif
|
||||
break;
|
||||
|
||||
case SOUND_TREBLE:
|
||||
#ifdef HAVE_MAS3587F
|
||||
result = value - 12;
|
||||
#else
|
||||
result = value - 15;
|
||||
#endif
|
||||
break;
|
||||
|
||||
#ifdef HAVE_MAS3587F
|
||||
case SOUND_LOUDNESS:
|
||||
result = value;
|
||||
break;
|
||||
|
||||
case SOUND_SUPERBASS:
|
||||
result = value * 10;
|
||||
break;
|
||||
|
||||
case SOUND_LEFT_GAIN:
|
||||
case SOUND_RIGHT_GAIN:
|
||||
result = (value - 2) * 15;
|
||||
break;
|
||||
|
||||
case SOUND_MIC_GAIN:
|
||||
result = value * 15 + 210;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int mpeg_phys2val(int setting, int value)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
switch(setting)
|
||||
{
|
||||
case SOUND_VOLUME:
|
||||
result = value;
|
||||
break;
|
||||
|
||||
case SOUND_BALANCE:
|
||||
result = value / 2;
|
||||
break;
|
||||
|
||||
case SOUND_BASS:
|
||||
#ifdef HAVE_MAS3587F
|
||||
result = value + 12;
|
||||
#else
|
||||
result = value + 15;
|
||||
#endif
|
||||
break;
|
||||
|
||||
case SOUND_TREBLE:
|
||||
#ifdef HAVE_MAS3587F
|
||||
result = value + 12;
|
||||
#else
|
||||
result = value + 15;
|
||||
#endif
|
||||
break;
|
||||
|
||||
#ifdef HAVE_MAS3587F
|
||||
case SOUND_SUPERBASS:
|
||||
result = value / 10;
|
||||
break;
|
||||
|
||||
case SOUND_LOUDNESS:
|
||||
case SOUND_AVC:
|
||||
case SOUND_LEFT_GAIN:
|
||||
case SOUND_RIGHT_GAIN:
|
||||
case SOUND_MIC_GAIN:
|
||||
result = value;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void mpeg_sound_channel_config(int configuration)
|
||||
{
|
||||
#ifdef SIMULATOR
|
||||
(void)configuration;
|
||||
#else
|
||||
unsigned long val_ll = 0x80000;
|
||||
unsigned long val_lr = 0;
|
||||
unsigned long val_rl = 0;
|
||||
unsigned long val_rr = 0x80000;
|
||||
|
||||
switch(configuration)
|
||||
{
|
||||
case MPEG_SOUND_STEREO:
|
||||
val_ll = 0x80000;
|
||||
val_lr = 0;
|
||||
val_rl = 0;
|
||||
val_rr = 0x80000;
|
||||
break;
|
||||
|
||||
case MPEG_SOUND_MONO:
|
||||
val_ll = 0xc0000;
|
||||
val_lr = 0xc0000;
|
||||
val_rl = 0xc0000;
|
||||
val_rr = 0xc0000;
|
||||
break;
|
||||
|
||||
case MPEG_SOUND_MONO_LEFT:
|
||||
val_ll = 0x80000;
|
||||
val_lr = 0x80000;
|
||||
val_rl = 0;
|
||||
val_rr = 0;
|
||||
break;
|
||||
|
||||
case MPEG_SOUND_MONO_RIGHT:
|
||||
val_ll = 0;
|
||||
val_lr = 0;
|
||||
val_rl = 0x80000;
|
||||
val_rr = 0x80000;
|
||||
break;
|
||||
|
||||
case MPEG_SOUND_STEREO_NARROW:
|
||||
val_ll = 0xa0000;
|
||||
val_lr = 0xe0000;
|
||||
val_rl = 0xe0000;
|
||||
val_rr = 0xa0000;
|
||||
break;
|
||||
|
||||
case MPEG_SOUND_STEREO_WIDE:
|
||||
val_ll = 0x80000;
|
||||
val_lr = 0x40000;
|
||||
val_rl = 0x40000;
|
||||
val_rr = 0x80000;
|
||||
break;
|
||||
|
||||
case MPEG_SOUND_KARAOKE:
|
||||
val_ll = 0x80001;
|
||||
val_lr = 0x7ffff;
|
||||
val_rl = 0x7ffff;
|
||||
val_rr = 0x80001;
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef HAVE_MAS3587F
|
||||
mas_writemem(MAS_BANK_D0, 0x7fc, &val_ll, 1); /* LL */
|
||||
mas_writemem(MAS_BANK_D0, 0x7fd, &val_lr, 1); /* LR */
|
||||
mas_writemem(MAS_BANK_D0, 0x7fe, &val_rl, 1); /* RL */
|
||||
mas_writemem(MAS_BANK_D0, 0x7ff, &val_rr, 1); /* RR */
|
||||
#else
|
||||
mas_writemem(MAS_BANK_D1, 0x7f8, &val_ll, 1); /* LL */
|
||||
mas_writemem(MAS_BANK_D1, 0x7f9, &val_lr, 1); /* LR */
|
||||
mas_writemem(MAS_BANK_D1, 0x7fa, &val_rl, 1); /* RL */
|
||||
mas_writemem(MAS_BANK_D1, 0x7fb, &val_rr, 1); /* RR */
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef HAVE_MAS3587F
|
||||
/* This function works by telling the decoder that we have another
|
||||
crystal frequency than we actually have. It will adjust its internal
|
||||
parameters and the result is that the audio is played at another pitch.
|
||||
|
||||
The pitch value is in tenths of percent.
|
||||
*/
|
||||
void mpeg_set_pitch(int pitch)
|
||||
{
|
||||
unsigned long val;
|
||||
|
||||
/* invert pitch value */
|
||||
pitch = 1000000/pitch;
|
||||
|
||||
/* Calculate the new (bogus) frequency */
|
||||
val = 18432*pitch/1000;
|
||||
|
||||
mas_writemem(MAS_BANK_D0,0x7f3,&val,1);
|
||||
|
||||
/* We must tell the MAS that the frequency has changed.
|
||||
This will unfortunately cause a short silence. */
|
||||
val = 0x25;
|
||||
mas_writemem(MAS_BANK_D0,0x7f1,&val,1);
|
||||
}
|
||||
#endif
|
||||
|
||||
void mp3_init(int volume, int bass, int treble, int balance, int loudness,
|
||||
int bass_boost, int avc, int channel_config)
|
||||
{
|
||||
#ifdef SIMULATOR
|
||||
volume = bass = treble = balance = loudness
|
||||
= bass_boost = avc = channel_config;
|
||||
#else
|
||||
#ifdef HAVE_MAS3507D
|
||||
unsigned long val;
|
||||
loudness = bass_boost = avc;
|
||||
#endif
|
||||
|
||||
setup_sci0();
|
||||
|
||||
#ifdef HAVE_MAS3587F
|
||||
or_b(0x08, &PAIORH); /* output for /PR */
|
||||
init_playback();
|
||||
|
||||
mas_version_code = mas_readver();
|
||||
DEBUGF("MAS3587 derivate %d, version B%d\n",
|
||||
(mas_version_code & 0xff00) >> 8, mas_version_code & 0xff);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_DAC3550A
|
||||
dac_init();
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_MAS3507D
|
||||
and_b(~0x20, &PBDRL);
|
||||
sleep(HZ/5);
|
||||
or_b(0x20, &PBDRL);
|
||||
sleep(HZ/5);
|
||||
|
||||
/* set IRQ6 to edge detect */
|
||||
ICR |= 0x02;
|
||||
|
||||
/* set IRQ6 prio 8 */
|
||||
IPRB = ( IPRB & 0xff0f ) | 0x0080;
|
||||
|
||||
mas_readmem(MAS_BANK_D1, 0xff7, &mas_version_code, 1);
|
||||
|
||||
mas_writereg(0x3b, 0x20); /* Don't ask why. The data sheet doesn't say */
|
||||
mas_run(1);
|
||||
sleep(HZ);
|
||||
|
||||
/* Clear the upper 12 bits of the 32-bit samples */
|
||||
mas_writereg(0xc5, 0);
|
||||
mas_writereg(0xc6, 0);
|
||||
|
||||
/* We need to set the PLL for a 14.1318MHz crystal */
|
||||
if(mas_version_code == 0x0601) /* Version F10? */
|
||||
{
|
||||
val = 0x5d9d0;
|
||||
mas_writemem(MAS_BANK_D0, 0x32d, &val, 1);
|
||||
val = 0xfffceceb;
|
||||
mas_writemem(MAS_BANK_D0, 0x32e, &val, 1);
|
||||
val = 0x0;
|
||||
mas_writemem(MAS_BANK_D0, 0x32f, &val, 1);
|
||||
mas_run(0x475);
|
||||
}
|
||||
else
|
||||
{
|
||||
val = 0x5d9d0;
|
||||
mas_writemem(MAS_BANK_D0, 0x36d, &val, 1);
|
||||
val = 0xfffceceb;
|
||||
mas_writemem(MAS_BANK_D0, 0x36e, &val, 1);
|
||||
val = 0x0;
|
||||
mas_writemem(MAS_BANK_D0, 0x36f, &val, 1);
|
||||
mas_run(0xfcb);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_MAS3507D
|
||||
mas_poll_start(1);
|
||||
|
||||
mas_writereg(MAS_REG_KPRESCALE, 0xe9400);
|
||||
dac_enable(true);
|
||||
|
||||
mpeg_sound_channel_config(channel_config);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_MAS3587F
|
||||
ICR &= ~0x0010; /* IRQ3 level sensitive */
|
||||
PACR1 = (PACR1 & 0x3fff) | 0x4000; /* PA15 is IRQ3 */
|
||||
#endif
|
||||
|
||||
/* Must be done before calling mpeg_sound_set() */
|
||||
mpeg_is_initialized = true;
|
||||
|
||||
mpeg_sound_set(SOUND_BASS, bass);
|
||||
mpeg_sound_set(SOUND_TREBLE, treble);
|
||||
mpeg_sound_set(SOUND_BALANCE, balance);
|
||||
mpeg_sound_set(SOUND_VOLUME, volume);
|
||||
|
||||
#ifdef HAVE_MAS3587F
|
||||
mpeg_sound_channel_config(channel_config);
|
||||
mpeg_sound_set(SOUND_LOUDNESS, loudness);
|
||||
mpeg_sound_set(SOUND_SUPERBASS, bass_boost);
|
||||
mpeg_sound_set(SOUND_AVC, avc);
|
||||
#endif
|
||||
#endif /* !SIMULATOR */
|
||||
}
|
||||
|
||||
|
||||
/* new functions, to be exported to plugin API */
|
||||
|
||||
void mp3_play_init(void)
|
||||
{
|
||||
#ifdef HAVE_MAS3587F
|
||||
init_playback();
|
||||
#endif
|
||||
callback_for_more = NULL;
|
||||
}
|
||||
|
||||
void mp3_play_data(unsigned char* start, int size,
|
||||
void (*get_more)(unsigned char** start, int* size) /* callback fn */
|
||||
)
|
||||
{
|
||||
/* init DMA */
|
||||
DAR3 = 0x5FFFEC3;
|
||||
CHCR3 &= ~0x0002; /* Clear interrupt */
|
||||
CHCR3 = 0x1504; /* Single address destination, TXI0, IE=1 */
|
||||
DMAOR = 0x0001; /* Enable DMA */
|
||||
|
||||
callback_for_more = get_more;
|
||||
|
||||
SAR3 = (unsigned int)start;
|
||||
DTCR3 = size & 0xffff;
|
||||
|
||||
CHCR3 |= 0x0001; /* Enable DMA IRQ */
|
||||
}
|
||||
|
||||
void mp3_play_pause(bool play)
|
||||
{
|
||||
if (play)
|
||||
SCR0 |= 0x80;
|
||||
else
|
||||
SCR0 &= 0x7f;
|
||||
}
|
||||
|
||||
void mp3_play_stop(void)
|
||||
{
|
||||
mp3_play_pause(false);
|
||||
CHCR3 &= ~0x0001; /* Disable the DMA interrupt */
|
||||
}
|
922
firmware/mpeg.c
922
firmware/mpeg.c
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue