summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/main.c35
-rw-r--r--apps/recorder/recording.c1
-rw-r--r--apps/screens.c1
-rw-r--r--apps/settings.c1
-rw-r--r--apps/sound_menu.c2
-rw-r--r--apps/status.c2
-rw-r--r--apps/wps.c1
-rw-r--r--firmware/export/mp3_playback.h73
-rw-r--r--firmware/export/mpeg.h34
-rw-r--r--firmware/mp3_playback.c939
-rw-r--r--firmware/mpeg.c922
11 files changed, 1081 insertions, 930 deletions
diff --git a/apps/main.c b/apps/main.c
index 04154f54fe..d6be594d07 100644
--- a/apps/main.c
+++ b/apps/main.c
@@ -37,6 +37,7 @@
37#include "serial.h" 37#include "serial.h"
38#endif 38#endif
39#include "mpeg.h" 39#include "mpeg.h"
40#include "mp3_playback.h"
40#include "main_menu.h" 41#include "main_menu.h"
41#include "thread.h" 42#include "thread.h"
42#include "settings.h" 43#include "settings.h"
@@ -78,14 +79,15 @@ void init(void)
78 sleep(HZ/2); 79 sleep(HZ/2);
79 tree_init(); 80 tree_init();
80 playlist_init(); 81 playlist_init();
81 mpeg_init( global_settings.volume, 82 mp3_init( global_settings.volume,
82 global_settings.bass, 83 global_settings.bass,
83 global_settings.treble, 84 global_settings.treble,
84 global_settings.balance, 85 global_settings.balance,
85 global_settings.loudness, 86 global_settings.loudness,
86 global_settings.bass_boost, 87 global_settings.bass_boost,
87 global_settings.avc, 88 global_settings.avc,
88 global_settings.channel_config ); 89 global_settings.channel_config );
90 mpeg_init();
89 while (button_get(false) != 0) 91 while (button_get(false) != 0)
90 ; /* Empty the keyboard buffer */ 92 ; /* Empty the keyboard buffer */
91} 93}
@@ -197,14 +199,15 @@ void init(void)
197 199
198 /* No buffer allocation (see buffer.c) may take place after the call to 200 /* No buffer allocation (see buffer.c) may take place after the call to
199 mpeg_init() since the mpeg thread takes the rest of the buffer space */ 201 mpeg_init() since the mpeg thread takes the rest of the buffer space */
200 mpeg_init( global_settings.volume, 202 mp3_init( global_settings.volume,
201 global_settings.bass, 203 global_settings.bass,
202 global_settings.treble, 204 global_settings.treble,
203 global_settings.balance, 205 global_settings.balance,
204 global_settings.loudness, 206 global_settings.loudness,
205 global_settings.bass_boost, 207 global_settings.bass_boost,
206 global_settings.avc, 208 global_settings.avc,
207 global_settings.channel_config ); 209 global_settings.channel_config );
210 mpeg_init();
208 211
209 /* no auto-rolo on startup any more, but I leave it here for reference */ 212 /* no auto-rolo on startup any more, but I leave it here for reference */
210#if 0 213#if 0
diff --git a/apps/recorder/recording.c b/apps/recorder/recording.c
index bc26ff8495..c1a5f96ab6 100644
--- a/apps/recorder/recording.c
+++ b/apps/recorder/recording.c
@@ -26,6 +26,7 @@
26#include "system.h" 26#include "system.h"
27#include "lcd.h" 27#include "lcd.h"
28#include "mpeg.h" 28#include "mpeg.h"
29#include "mp3_playback.h"
29#include "mas.h" 30#include "mas.h"
30#include "button.h" 31#include "button.h"
31#include "kernel.h" 32#include "kernel.h"
diff --git a/apps/screens.c b/apps/screens.c
index 8f7881a916..1b269d93bc 100644
--- a/apps/screens.c
+++ b/apps/screens.c
@@ -26,6 +26,7 @@
26#include "icons.h" 26#include "icons.h"
27#include "font.h" 27#include "font.h"
28#include "mpeg.h" 28#include "mpeg.h"
29#include "mp3_playback.h"
29#include "usb.h" 30#include "usb.h"
30#include "settings.h" 31#include "settings.h"
31#include "status.h" 32#include "status.h"
diff --git a/apps/settings.c b/apps/settings.c
index 35e75d12ca..b08ed8475d 100644
--- a/apps/settings.c
+++ b/apps/settings.c
@@ -31,6 +31,7 @@
31#include "backlight.h" 31#include "backlight.h"
32#include "lcd.h" 32#include "lcd.h"
33#include "mpeg.h" 33#include "mpeg.h"
34#include "mp3_playback.h"
34#include "string.h" 35#include "string.h"
35#include "ata.h" 36#include "ata.h"
36#include "fat.h" 37#include "fat.h"
diff --git a/apps/sound_menu.c b/apps/sound_menu.c
index 557013df8a..11a5581ecb 100644
--- a/apps/sound_menu.c
+++ b/apps/sound_menu.c
@@ -23,7 +23,7 @@
23#include "lcd.h" 23#include "lcd.h"
24#include "menu.h" 24#include "menu.h"
25#include "button.h" 25#include "button.h"
26#include "mpeg.h" 26#include "mp3_playback.h"
27#include "settings.h" 27#include "settings.h"
28#include "status.h" 28#include "status.h"
29#include "screens.h" 29#include "screens.h"
diff --git a/apps/status.c b/apps/status.c
index 68d6ac74c1..65eff70e81 100644
--- a/apps/status.c
+++ b/apps/status.c
@@ -24,7 +24,7 @@
24#include "thread.h" 24#include "thread.h"
25#include "settings.h" 25#include "settings.h"
26#include "status.h" 26#include "status.h"
27#include "mpeg.h" 27#include "mp3_playback.h"
28#include "wps.h" 28#include "wps.h"
29#ifdef HAVE_RTC 29#ifdef HAVE_RTC
30#include "timefuncs.h" 30#include "timefuncs.h"
diff --git a/apps/wps.c b/apps/wps.c
index 10cc0c00fb..9e988d3721 100644
--- a/apps/wps.c
+++ b/apps/wps.c
@@ -33,6 +33,7 @@
33#include "wps.h" 33#include "wps.h"
34#include "wps-display.h" 34#include "wps-display.h"
35#include "mpeg.h" 35#include "mpeg.h"
36#include "mp3_playback.h"
36#include "usb.h" 37#include "usb.h"
37#include "status.h" 38#include "status.h"
38#include "main_menu.h" 39#include "main_menu.h"
diff --git a/firmware/export/mp3_playback.h b/firmware/export/mp3_playback.h
new file mode 100644
index 0000000000..2767092b75
--- /dev/null
+++ b/firmware/export/mp3_playback.h
@@ -0,0 +1,73 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Code that has been in mpeg.c/h 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#ifndef _MP3_PLAYBACK_H_
23#define _MP3_PLAYBACK_H_
24
25#include <stdbool.h>
26
27/* functions formerly in mpeg.c */
28void mp3_init(int volume, int bass, int treble, int balance,
29 int loudness, int bass_boost, int avc, int channel_config);
30void mpeg_sound_set(int setting, int value);
31int mpeg_sound_min(int setting);
32int mpeg_sound_max(int setting);
33int mpeg_sound_default(int setting);
34void mpeg_sound_channel_config(int configuration);
35int mpeg_val2phys(int setting, int value);
36int mpeg_phys2val(int setting, int value);
37char *mpeg_sound_unit(int setting);
38int mpeg_sound_numdecimals(int setting);
39#if defined(HAVE_MAS3587F) || defined(SIMULATOR)
40void mpeg_set_pitch(int percent);
41#endif
42
43/* new functions, to be exported to plugin API */
44void mp3_play_init(void);
45void mp3_play_data(unsigned char* start, int size,
46 void (*get_more)(unsigned char** start, int* size) /* callback fn */
47);
48void mp3_play_pause(bool play);
49void mp3_play_stop(void);
50
51
52#define SOUND_VOLUME 0
53#define SOUND_BASS 1
54#define SOUND_TREBLE 2
55#define SOUND_BALANCE 3
56#define SOUND_LOUDNESS 4
57#define SOUND_SUPERBASS 5
58#define SOUND_AVC 6
59#define SOUND_CHANNELS 7
60#define SOUND_LEFT_GAIN 8
61#define SOUND_RIGHT_GAIN 9
62#define SOUND_MIC_GAIN 10
63#define SOUND_NUMSETTINGS 11
64
65#define MPEG_SOUND_STEREO 0
66#define MPEG_SOUND_STEREO_NARROW 1
67#define MPEG_SOUND_MONO 2
68#define MPEG_SOUND_MONO_LEFT 3
69#define MPEG_SOUND_MONO_RIGHT 4
70#define MPEG_SOUND_KARAOKE 5
71#define MPEG_SOUND_STEREO_WIDE 6
72
73#endif /* #ifndef _MP3_PLAYBACK_H_ */
diff --git a/firmware/export/mpeg.h b/firmware/export/mpeg.h
index bbace28ecd..2a629f4b45 100644
--- a/firmware/export/mpeg.h
+++ b/firmware/export/mpeg.h
@@ -61,8 +61,7 @@ struct mpeg_debug
61 int lowest_watermark_level; 61 int lowest_watermark_level;
62}; 62};
63 63
64void mpeg_init(int volume, int bass, int treble, int balance, 64void mpeg_init(void);
65 int loudness, int bass_boost, int avc, int channel_config);
66void mpeg_play(int offset); 65void mpeg_play(int offset);
67void mpeg_stop(void); 66void mpeg_stop(void);
68void mpeg_pause(void); 67void mpeg_pause(void);
@@ -71,20 +70,10 @@ void mpeg_next(void);
71void mpeg_prev(void); 70void mpeg_prev(void);
72void mpeg_ff_rewind(int newtime); 71void mpeg_ff_rewind(int newtime);
73void mpeg_flush_and_reload_tracks(void); 72void mpeg_flush_and_reload_tracks(void);
74void mpeg_sound_set(int setting, int value);
75int mpeg_sound_min(int setting);
76int mpeg_sound_max(int setting);
77int mpeg_sound_default(int setting);
78void mpeg_sound_channel_config(int configuration);
79int mpeg_val2phys(int setting, int value);
80int mpeg_phys2val(int setting, int value);
81char *mpeg_sound_unit(int setting);
82int mpeg_sound_numdecimals(int setting);
83struct mp3entry* mpeg_current_track(void); 73struct mp3entry* mpeg_current_track(void);
84bool mpeg_has_changed_track(void); 74bool mpeg_has_changed_track(void);
85int mpeg_status(void); 75int mpeg_status(void);
86#if defined(HAVE_MAS3587F) || defined(SIMULATOR) 76#if defined(HAVE_MAS3587F) || defined(SIMULATOR)
87void mpeg_set_pitch(int percent);
88void mpeg_init_recording(void); 77void mpeg_init_recording(void);
89void mpeg_init_playback(void); 78void mpeg_init_playback(void);
90void mpeg_record(char *filename); 79void mpeg_record(char *filename);
@@ -101,27 +90,6 @@ void mpeg_set_buffer_margin(int seconds);
101unsigned int mpeg_error(void); 90unsigned int mpeg_error(void);
102void mpeg_error_clear(void); 91void mpeg_error_clear(void);
103 92
104#define SOUND_VOLUME 0
105#define SOUND_BASS 1
106#define SOUND_TREBLE 2
107#define SOUND_BALANCE 3
108#define SOUND_LOUDNESS 4
109#define SOUND_SUPERBASS 5
110#define SOUND_AVC 6
111#define SOUND_CHANNELS 7
112#define SOUND_LEFT_GAIN 8
113#define SOUND_RIGHT_GAIN 9
114#define SOUND_MIC_GAIN 10
115#define SOUND_NUMSETTINGS 11
116
117#define MPEG_SOUND_STEREO 0
118#define MPEG_SOUND_STEREO_NARROW 1
119#define MPEG_SOUND_MONO 2
120#define MPEG_SOUND_MONO_LEFT 3
121#define MPEG_SOUND_MONO_RIGHT 4
122#define MPEG_SOUND_KARAOKE 5
123#define MPEG_SOUND_STEREO_WIDE 6
124
125#define MPEG_STATUS_PLAY 1 93#define MPEG_STATUS_PLAY 1
126#define MPEG_STATUS_PAUSE 2 94#define MPEG_STATUS_PAUSE 2
127#define MPEG_STATUS_RECORD 4 95#define MPEG_STATUS_RECORD 4
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}
diff --git a/firmware/mpeg.c b/firmware/mpeg.c
index 43da221800..1dd489a290 100644
--- a/firmware/mpeg.c
+++ b/firmware/mpeg.c
@@ -29,6 +29,7 @@
29#include "errno.h" 29#include "errno.h"
30#include "mp3data.h" 30#include "mp3data.h"
31#include "buffer.h" 31#include "buffer.h"
32#include "mp3_playback.h"
32#ifndef SIMULATOR 33#ifndef SIMULATOR
33#include "i2c.h" 34#include "i2c.h"
34#include "mas.h" 35#include "mas.h"
@@ -43,7 +44,6 @@ extern void bitswap(unsigned char *data, int length);
43 44
44#ifdef HAVE_MAS3587F 45#ifdef HAVE_MAS3587F
45static void init_recording(void); 46static void init_recording(void);
46static void init_playback(void);
47static void start_prerecording(void); 47static void start_prerecording(void);
48static void start_recording(void); 48static void start_recording(void);
49static void stop_recording(void); 49static void stop_recording(void);
@@ -87,116 +87,6 @@ extern int playlist_next(int steps);
87extern int playlist_amount(void); 87extern int playlist_amount(void);
88extern void update_file_pos( int id, int pos ); 88extern void update_file_pos( int id, int pos );
89 89
90static char *units[] =
91{
92 "%", /* Volume */
93 "dB", /* Bass */
94 "dB", /* Treble */
95 "%", /* Balance */
96 "dB", /* Loudness */
97 "%", /* Bass boost */
98 "", /* AVC */
99 "", /* Channels */
100 "dB", /* Left gain */
101 "dB", /* Right gain */
102 "dB", /* Mic gain */
103};
104
105static int numdecimals[] =
106{
107 0, /* Volume */
108 0, /* Bass */
109 0, /* Treble */
110 0, /* Balance */
111 0, /* Loudness */
112 0, /* Bass boost */
113 0, /* AVC */
114 0, /* Channels */
115 1, /* Left gain */
116 1, /* Right gain */
117 1, /* Mic gain */
118};
119
120static int minval[] =
121{
122 0, /* Volume */
123 0, /* Bass */
124 0, /* Treble */
125 -50, /* Balance */
126 0, /* Loudness */
127 0, /* Bass boost */
128 -1, /* AVC */
129 0, /* Channels */
130 0, /* Left gain */
131 0, /* Right gain */
132 0, /* Mic gain */
133};
134
135static int maxval[] =
136{
137 100, /* Volume */
138#ifdef HAVE_MAS3587F
139 24, /* Bass */
140 24, /* Treble */
141#else
142 30, /* Bass */
143 30, /* Treble */
144#endif
145 50, /* Balance */
146 17, /* Loudness */
147 10, /* Bass boost */
148 3, /* AVC */
149 6, /* Channels */
150 15, /* Left gain */
151 15, /* Right gain */
152 15, /* Mic gain */
153};
154
155static int defaultval[] =
156{
157 70, /* Volume */
158#ifdef HAVE_MAS3587F
159 12+6, /* Bass */
160 12+6, /* Treble */
161#else
162 15+7, /* Bass */
163 15+7, /* Treble */
164#endif
165 0, /* Balance */
166 0, /* Loudness */
167 0, /* Bass boost */
168 0, /* AVC */
169 0, /* Channels */
170 8, /* Left gain */
171 8, /* Right gain */
172 2, /* Mic gain */
173};
174
175char *mpeg_sound_unit(int setting)
176{
177 return units[setting];
178}
179
180int mpeg_sound_numdecimals(int setting)
181{
182 return numdecimals[setting];
183}
184
185int mpeg_sound_min(int setting)
186{
187 return minval[setting];
188}
189
190int mpeg_sound_max(int setting)
191{
192 return maxval[setting];
193}
194
195int mpeg_sound_default(int setting)
196{
197 return defaultval[setting];
198}
199
200/* list of tracks in memory */ 90/* list of tracks in memory */
201#define MAX_ID3_TAGS (1<<4) /* Must be power of 2 */ 91#define MAX_ID3_TAGS (1<<4) /* Must be power of 2 */
202#define MAX_ID3_TAGS_MASK (MAX_ID3_TAGS - 1) 92#define MAX_ID3_TAGS_MASK (MAX_ID3_TAGS - 1)
@@ -216,8 +106,6 @@ static unsigned int last_track_counter = 0;
216 106
217#ifndef SIMULATOR 107#ifndef SIMULATOR
218 108
219static bool mpeg_is_initialized = false;
220
221static int tag_read_idx = 0; 109static int tag_read_idx = 0;
222static int tag_write_idx = 0; 110static int tag_write_idx = 0;
223 111
@@ -371,100 +259,7 @@ static bool playing = false;
371#else 259#else
372static int last_dma_tick = 0; 260static int last_dma_tick = 0;
373 261
374static unsigned long mas_version_code; 262extern unsigned long mas_version_code;
375
376#ifdef HAVE_MAS3507D
377
378static unsigned int bass_table[] =
379{
380 0x9e400, /* -15dB */
381 0xa2800, /* -14dB */
382 0xa7400, /* -13dB */
383 0xac400, /* -12dB */
384 0xb1800, /* -11dB */
385 0xb7400, /* -10dB */
386 0xbd400, /* -9dB */
387 0xc3c00, /* -8dB */
388 0xca400, /* -7dB */
389 0xd1800, /* -6dB */
390 0xd8c00, /* -5dB */
391 0xe0400, /* -4dB */
392 0xe8000, /* -3dB */
393 0xefc00, /* -2dB */
394 0xf7c00, /* -1dB */
395 0,
396 0x800, /* 1dB */
397 0x10000, /* 2dB */
398 0x17c00, /* 3dB */
399 0x1f800, /* 4dB */
400 0x27000, /* 5dB */
401 0x2e400, /* 6dB */
402 0x35800, /* 7dB */
403 0x3c000, /* 8dB */
404 0x42800, /* 9dB */
405 0x48800, /* 10dB */
406 0x4e400, /* 11dB */
407 0x53800, /* 12dB */
408 0x58800, /* 13dB */
409 0x5d400, /* 14dB */
410 0x61800 /* 15dB */
411};
412
413static unsigned int treble_table[] =
414{
415 0xb2c00, /* -15dB */
416 0xbb400, /* -14dB */
417 0xc1800, /* -13dB */
418 0xc6c00, /* -12dB */
419 0xcbc00, /* -11dB */
420 0xd0400, /* -10dB */
421 0xd5000, /* -9dB */
422 0xd9800, /* -8dB */
423 0xde000, /* -7dB */
424 0xe2800, /* -6dB */
425 0xe7e00, /* -5dB */
426 0xec000, /* -4dB */
427 0xf0c00, /* -3dB */
428 0xf5c00, /* -2dB */
429 0xfac00, /* -1dB */
430 0,
431 0x5400, /* 1dB */
432 0xac00, /* 2dB */
433 0x10400, /* 3dB */
434 0x16000, /* 4dB */
435 0x1c000, /* 5dB */
436 0x22400, /* 6dB */
437 0x28400, /* 7dB */
438 0x2ec00, /* 8dB */
439 0x35400, /* 9dB */
440 0x3c000, /* 10dB */
441 0x42c00, /* 11dB */
442 0x49c00, /* 12dB */
443 0x51800, /* 13dB */
444 0x58400, /* 14dB */
445 0x5f800 /* 15dB */
446};
447
448static unsigned int prescale_table[] =
449{
450 0x80000, /* 0db */
451 0x8e000, /* 1dB */
452 0x9a400, /* 2dB */
453 0xa5800, /* 3dB */
454 0xaf400, /* 4dB */
455 0xb8000, /* 5dB */
456 0xbfc00, /* 6dB */
457 0xc6c00, /* 7dB */
458 0xcd000, /* 8dB */
459 0xd25c0, /* 9dB */
460 0xd7800, /* 10dB */
461 0xdc000, /* 11dB */
462 0xdfc00, /* 12dB */
463 0xe3400, /* 13dB */
464 0xe6800, /* 14dB */
465 0xe9400 /* 15dB */
466};
467#endif
468 263
469static struct event_queue mpeg_queue; 264static struct event_queue mpeg_queue;
470static char mpeg_stack[DEFAULT_STACK_SIZE + 0x1000]; 265static char mpeg_stack[DEFAULT_STACK_SIZE + 0x1000];
@@ -477,7 +272,6 @@ static int mp3buf_read;
477 272
478static int last_dma_chunk_size; 273static int last_dma_chunk_size;
479 274
480static bool dma_on; /* The DMA is active */
481static bool playing; /* We are playing an MP3 stream */ 275static bool playing; /* We are playing an MP3 stream */
482static bool play_pending; /* We are about to start playing */ 276static bool play_pending; /* We are about to start playing */
483static bool is_playing; /* We are (attempting to) playing MP3 files */ 277static bool is_playing; /* We are (attempting to) playing MP3 files */
@@ -562,7 +356,7 @@ void mpeg_get_debugdata(struct mpeg_debug *dbgdata)
562 356
563 dbgdata->last_dma_chunk_size = last_dma_chunk_size; 357 dbgdata->last_dma_chunk_size = last_dma_chunk_size;
564 358
565 dbgdata->dma_on = dma_on; 359 dbgdata->dma_on = (SCR0 & 0x80) != 0;
566 dbgdata->playing = playing; 360 dbgdata->playing = playing;
567 dbgdata->play_pending = play_pending; 361 dbgdata->play_pending = play_pending;
568 dbgdata->is_playing = is_playing; 362 dbgdata->is_playing = is_playing;
@@ -577,39 +371,7 @@ void mpeg_get_debugdata(struct mpeg_debug *dbgdata)
577 dbgdata->lowest_watermark_level = lowest_watermark_level; 371 dbgdata->lowest_watermark_level = lowest_watermark_level;
578} 372}
579 373
580#ifdef HAVE_MAS3507D 374#ifndef HAVE_MAS3507D
581static void mas_poll_start(int interval_in_ms)
582{
583 unsigned int count;
584
585 count = (FREQ * interval_in_ms) / 1000 / 8;
586
587 if(count > 0xffff)
588 {
589 panicf("Error! The MAS poll interval is too long (%d ms)\n",
590 interval_in_ms);
591 return;
592 }
593
594 /* We are using timer 1 */
595
596 TSTR &= ~0x02; /* Stop the timer */
597 TSNC &= ~0x02; /* No synchronization */
598 TMDR &= ~0x02; /* Operate normally */
599
600 TCNT1 = 0; /* Start counting at 0 */
601 GRA1 = count;
602 TCR1 = 0x23; /* Clear at GRA match, sysclock/8 */
603
604 /* Enable interrupt on level 5 */
605 IPRC = (IPRC & ~0x000f) | 0x0005;
606
607 TSR1 &= ~0x02;
608 TIER1 = 0xf9; /* Enable GRA match interrupt */
609
610 TSTR |= 0x02; /* Start timer 1 */
611}
612#else
613static void postpone_dma_tick(void) 375static void postpone_dma_tick(void)
614{ 376{
615 unsigned int count; 377 unsigned int count;
@@ -712,31 +474,6 @@ static int get_unsaved_space(void)
712} 474}
713#endif 475#endif
714 476
715static void init_dma(void)
716{
717 SAR3 = (unsigned int) mp3buf + mp3buf_read;
718 DAR3 = 0x5FFFEC3;
719 CHCR3 &= ~0x0002; /* Clear interrupt */
720 CHCR3 = 0x1504; /* Single address destination, TXI0, IE=1 */
721 last_dma_chunk_size = MIN(0x2000, get_unplayed_space_current_song());
722 DTCR3 = last_dma_chunk_size & 0xffff;
723 DMAOR = 0x0001; /* Enable DMA */
724 CHCR3 |= 0x0001; /* Enable DMA IRQ */
725 dma_underrun = false;
726}
727
728static void start_dma(void)
729{
730 SCR0 |= 0x80;
731 dma_on = true;
732}
733
734static void stop_dma(void)
735{
736 SCR0 &= 0x7f;
737 dma_on = false;
738}
739
740#ifdef HAVE_MAS3587F 477#ifdef HAVE_MAS3587F
741#ifdef DEBUG 478#ifdef DEBUG
742static long timing_info_index = 0; 479static long timing_info_index = 0;
@@ -746,7 +483,7 @@ static bool inverted_pr;
746static unsigned long num_rec_bytes; 483static unsigned long num_rec_bytes;
747static unsigned long num_recorded_frames; 484static unsigned long num_recorded_frames;
748 485
749void drain_dma_buffer(void) 486static void drain_dma_buffer(void)
750{ 487{
751 if(inverted_pr) 488 if(inverted_pr)
752 { 489 {
@@ -784,7 +521,8 @@ void drain_dma_buffer(void)
784 } 521 }
785 } 522 }
786} 523}
787#endif 524
525#endif /* #ifdef HAVE_MAS3587F */
788 526
789static void dma_tick (void) __attribute__ ((section (".icode"))); 527static void dma_tick (void) __attribute__ ((section (".icode")));
790static void dma_tick(void) 528static void dma_tick(void)
@@ -796,10 +534,9 @@ static void dma_tick(void)
796 if(playing && !paused) 534 if(playing && !paused)
797 { 535 {
798 /* Start DMA if it is disabled and the DEMAND pin is high */ 536 /* Start DMA if it is disabled and the DEMAND pin is high */
799 if(!dma_on && (PBDR & 0x4000)) 537 if(!(SCR0 & 0x80) && (PBDR & 0x4000))
800 { 538 {
801 if(!(SCR0 & 0x80)) 539 mp3_play_pause(true);
802 start_dma();
803 } 540 }
804 id3tags[tag_read_idx]->id3.elapsed += 541 id3tags[tag_read_idx]->id3.elapsed +=
805 (current_tick - last_dma_tick) * 1000 / HZ; 542 (current_tick - last_dma_tick) * 1000 / HZ;
@@ -807,7 +544,7 @@ static void dma_tick(void)
807 } 544 }
808#ifdef HAVE_MAS3587F 545#ifdef HAVE_MAS3587F
809 } 546 }
810 else 547 else /* MPEG_ENCODER */
811 { 548 {
812 int i; 549 int i;
813 int num_bytes; 550 int num_bytes;
@@ -845,7 +582,7 @@ static void dma_tick(void)
845 /* No wait for /RTW, cause it's not necessary */ 582 /* No wait for /RTW, cause it's not necessary */
846 } 583 }
847 } 584 }
848 else 585 else /* !inverted_pr */
849 { 586 {
850 i = 0; 587 i = 0;
851 while((*((volatile unsigned char *)PBDR_ADDR) & 0x40) 588 while((*((volatile unsigned char *)PBDR_ADDR) & 0x40)
@@ -923,8 +660,8 @@ static void reset_mp3_buffer(void)
923 lowest_watermark_level = mp3buflen; 660 lowest_watermark_level = mp3buflen;
924} 661}
925 662
926#pragma interrupt 663 /* DMA transfer end interrupt callback */
927void DEI3(void) 664static void transfer_end(unsigned char** ppbuf, int* psize)
928{ 665{
929 if(playing && !paused) 666 if(playing && !paused)
930 { 667 {
@@ -976,8 +713,8 @@ void DEI3(void)
976 } 713 }
977 } 714 }
978 715
979 DTCR3 = last_dma_chunk_size & 0xffff; 716 *psize = last_dma_chunk_size & 0xffff;
980 SAR3 = (unsigned int)mp3buf + mp3buf_read; 717 *ppbuf = mp3buf + mp3buf_read;
981 id3tags[tag_read_idx]->id3.offset += last_dma_chunk_size; 718 id3tags[tag_read_idx]->id3.offset += last_dma_chunk_size;
982 719
983 /* Update the watermark debug level */ 720 /* Update the watermark debug level */
@@ -1007,11 +744,10 @@ void DEI3(void)
1007 playing = false; 744 playing = false;
1008 is_playing = false; 745 is_playing = false;
1009 } 746 }
1010 CHCR3 &= ~0x0001; /* Disable the DMA interrupt */ 747 *psize = 0; /* no more transfer */
1011 } 748 }
1012 } 749 }
1013 750
1014 CHCR3 &= ~0x0002; /* Clear DMA interrupt */
1015 wake_up_thread(); 751 wake_up_thread();
1016} 752}
1017 753
@@ -1033,7 +769,7 @@ static void demand_irq_enable(bool on)
1033#endif 769#endif
1034 770
1035#pragma interrupt 771#pragma interrupt
1036void IMIA1(void) 772void IMIA1(void) /* Timer 1 interrupt */
1037{ 773{
1038 dma_tick(); 774 dma_tick();
1039 TSR1 &= ~0x01; 775 TSR1 &= ~0x01;
@@ -1043,15 +779,9 @@ void IMIA1(void)
1043#endif 779#endif
1044} 780}
1045 781
1046#pragma interrupt
1047void IRQ6(void)
1048{
1049 stop_dma();
1050}
1051
1052#ifdef HAVE_MAS3587F 782#ifdef HAVE_MAS3587F
1053#pragma interrupt 783#pragma interrupt
1054void IRQ3(void) 784void IRQ3(void) /* PA15: MAS demand IRQ */
1055{ 785{
1056 /* Begin with setting the IRQ to edge sensitive */ 786 /* Begin with setting the IRQ to edge sensitive */
1057 ICR |= 0x0010; 787 ICR |= 0x0010;
@@ -1170,7 +900,7 @@ static void stop_playing(void)
1170 if(mpeg_file >= 0) 900 if(mpeg_file >= 0)
1171 close(mpeg_file); 901 close(mpeg_file);
1172 mpeg_file = -1; 902 mpeg_file = -1;
1173 stop_dma(); 903 mp3_play_pause(false);
1174 remove_all_tags(); 904 remove_all_tags();
1175} 905}
1176 906
@@ -1237,11 +967,14 @@ static void start_playback_if_ready(void)
1237 play_pending = false; 967 play_pending = false;
1238 playing = true; 968 playing = true;
1239 969
1240 init_dma(); 970 last_dma_chunk_size = MIN(0x2000, get_unplayed_space_current_song());
971 mp3_play_data(mp3buf + mp3buf_read, last_dma_chunk_size, transfer_end);
972 dma_underrun = false;
973
1241 if (!paused) 974 if (!paused)
1242 { 975 {
1243 last_dma_tick = current_tick; 976 last_dma_tick = current_tick;
1244 start_dma(); 977 mp3_play_pause(true);
1245#ifdef HAVE_MAS3587F 978#ifdef HAVE_MAS3587F
1246 demand_irq_enable(true); 979 demand_irq_enable(true);
1247#endif 980#endif
@@ -1376,7 +1109,7 @@ static void mpeg_thread(void)
1376 play_pending = false; 1109 play_pending = false;
1377 playing = false; 1110 playing = false;
1378 paused = false; 1111 paused = false;
1379 stop_dma(); 1112 mp3_play_pause(false);
1380 1113
1381 reset_mp3_buffer(); 1114 reset_mp3_buffer();
1382 remove_all_tags(); 1115 remove_all_tags();
@@ -1435,7 +1168,7 @@ static void mpeg_thread(void)
1435 playing = false; 1168 playing = false;
1436 pause_tick = current_tick; 1169 pause_tick = current_tick;
1437 pause_track = current_track_counter; 1170 pause_track = current_track_counter;
1438 stop_dma(); 1171 mp3_play_pause(false);
1439 break; 1172 break;
1440 1173
1441 case MPEG_RESUME: 1174 case MPEG_RESUME:
@@ -1450,7 +1183,7 @@ static void mpeg_thread(void)
1450 else 1183 else
1451 last_dma_tick = current_tick; 1184 last_dma_tick = current_tick;
1452 pause_tick = 0; 1185 pause_tick = 0;
1453 start_dma(); 1186 mp3_play_pause(true);
1454 } 1187 }
1455 break; 1188 break;
1456 1189
@@ -1463,11 +1196,13 @@ static void mpeg_thread(void)
1463 /* stop the current stream */ 1196 /* stop the current stream */
1464 play_pending = false; 1197 play_pending = false;
1465 playing = false; 1198 playing = false;
1466 stop_dma(); 1199 mp3_play_pause(false);
1467 1200
1468 track_change(); 1201 track_change();
1469 mp3buf_read = id3tags[tag_read_idx]->mempos; 1202 mp3buf_read = id3tags[tag_read_idx]->mempos;
1470 init_dma(); 1203 last_dma_chunk_size = MIN(0x2000, get_unplayed_space_current_song());
1204 mp3_play_data(mp3buf + mp3buf_read, last_dma_chunk_size, transfer_end);
1205 dma_underrun = false;
1471 last_dma_tick = current_tick; 1206 last_dma_tick = current_tick;
1472 1207
1473 unplayed_space_left = get_unplayed_space(); 1208 unplayed_space_left = get_unplayed_space();
@@ -1486,7 +1221,7 @@ static void mpeg_thread(void)
1486 } else { 1221 } else {
1487 playing = true; 1222 playing = true;
1488 if (!paused) 1223 if (!paused)
1489 start_dma(); 1224 mp3_play_pause(true);
1490 } 1225 }
1491 } 1226 }
1492 else { 1227 else {
@@ -1496,7 +1231,7 @@ static void mpeg_thread(void)
1496 /* stop the current stream */ 1231 /* stop the current stream */
1497 play_pending = false; 1232 play_pending = false;
1498 playing = false; 1233 playing = false;
1499 stop_dma(); 1234 mp3_play_pause(false);
1500 1235
1501 reset_mp3_buffer(); 1236 reset_mp3_buffer();
1502 remove_all_tags(); 1237 remove_all_tags();
@@ -1532,7 +1267,7 @@ static void mpeg_thread(void)
1532 /* stop the current stream */ 1267 /* stop the current stream */
1533 play_pending = false; 1268 play_pending = false;
1534 playing = false; 1269 playing = false;
1535 stop_dma(); 1270 mp3_play_pause(false);
1536 1271
1537 reset_mp3_buffer(); 1272 reset_mp3_buffer();
1538 remove_all_tags(); 1273 remove_all_tags();
@@ -1685,7 +1420,11 @@ static void mpeg_thread(void)
1685 else 1420 else
1686 { 1421 {
1687 /* resume will start at new position */ 1422 /* resume will start at new position */
1688 init_dma(); 1423 last_dma_chunk_size =
1424 MIN(0x2000, get_unplayed_space_current_song());
1425 mp3_play_data(mp3buf + mp3buf_read,
1426 last_dma_chunk_size, transfer_end);
1427 dma_underrun = false;
1689 } 1428 }
1690 } 1429 }
1691 else 1430 else
@@ -2261,7 +2000,9 @@ static void mpeg_thread(void)
2261 break; 2000 break;
2262 2001
2263 case MPEG_INIT_PLAYBACK: 2002 case MPEG_INIT_PLAYBACK:
2264 init_playback(); 2003 mp3_play_init();
2004 mpeg_mode = MPEG_DECODER;
2005
2265 init_playback_done = true; 2006 init_playback_done = true;
2266 break; 2007 break;
2267 2008
@@ -2288,43 +2029,6 @@ static void mpeg_thread(void)
2288#endif 2029#endif
2289 } 2030 }
2290} 2031}
2291
2292static void setup_sci0(void)
2293{
2294 /* PB15 is I/O, PB14 is IRQ6, PB12 is SCK0, PB9 is TxD0 */
2295 PBCR1 = (PBCR1 & 0x0cff) | 0x1208;
2296
2297 /* Set PB12 to output */
2298 or_b(0x10, &PBIORH);
2299
2300 /* Disable serial port */
2301 SCR0 = 0x00;
2302
2303 /* Synchronous, no prescale */
2304 SMR0 = 0x80;
2305
2306 /* Set baudrate 1Mbit/s */
2307 BRR0 = 0x03;
2308
2309 /* use SCK as serial clock output */
2310 SCR0 = 0x01;
2311
2312 /* Clear FER and PER */
2313 SSR0 &= 0xe7;
2314
2315 /* Set interrupt ITU2 and SCI0 priority to 0 */
2316 IPRD &= 0x0ff0;
2317
2318 /* set PB15 and PB14 to inputs */
2319 and_b(~0x80, &PBIORH);
2320 and_b(~0x40, &PBIORH);
2321
2322 /* Enable End of DMA interrupt at prio 8 */
2323 IPRC = (IPRC & 0xf0ff) | 0x0800;
2324
2325 /* Enable Tx (only!) */
2326 SCR0 |= 0x20;
2327}
2328#endif /* SIMULATOR */ 2032#endif /* SIMULATOR */
2329 2033
2330#ifdef SIMULATOR 2034#ifdef SIMULATOR
@@ -2364,66 +2068,6 @@ void mpeg_init_playback(void)
2364 wake_up_thread(); 2068 wake_up_thread();
2365} 2069}
2366 2070
2367static void init_playback(void)
2368{
2369 unsigned long val;
2370 int rc;
2371
2372 if(mpeg_mode == MPEG_ENCODER)
2373 stop_recording();
2374
2375 stop_dma();
2376
2377 mas_reset();
2378
2379 /* Enable the audio CODEC and the DSP core, max analog voltage range */
2380 rc = mas_direct_config_write(MAS_CONTROL, 0x8c00);
2381 if(rc < 0)
2382 panicf("mas_ctrl_w: %d", rc);
2383
2384 /* Stop the current application */
2385 val = 0;
2386 mas_writemem(MAS_BANK_D0,0x7f6,&val,1);
2387 do
2388 {
2389 mas_readmem(MAS_BANK_D0, 0x7f7, &val, 1);
2390 } while(val);
2391
2392 /* Enable the D/A Converter */
2393 mas_codec_writereg(0x0, 0x0001);
2394
2395 /* ADC scale 0%, DSP scale 100% */
2396 mas_codec_writereg(6, 0x0000);
2397 mas_codec_writereg(7, 0x4000);
2398
2399 /* Disable SDO and SDI */
2400 val = 0x0d;
2401 mas_writemem(MAS_BANK_D0,0x7f2,&val,1);
2402
2403 /* Set Demand mode and validate all settings */
2404 val = 0x25;
2405 mas_writemem(MAS_BANK_D0,0x7f1,&val,1);
2406
2407 /* Start the Layer2/3 decoder applications */
2408 val = 0x0c;
2409 mas_writemem(MAS_BANK_D0,0x7f6,&val,1);
2410 do
2411 {
2412 mas_readmem(MAS_BANK_D0, 0x7f7, &val, 1);
2413 } while((val & 0x0c) != 0x0c);
2414
2415 mpeg_sound_channel_config(MPEG_SOUND_STEREO);
2416
2417 mpeg_mode = MPEG_DECODER;
2418
2419 /* set IRQ6 to edge detect */
2420 ICR |= 0x02;
2421
2422 /* set IRQ6 prio 8 */
2423 IPRB = ( IPRB & 0xff0f ) | 0x0080;
2424
2425 DEBUGF("MAS Decoding application started\n");
2426}
2427 2071
2428/**************************************************************************** 2072/****************************************************************************
2429 ** 2073 **
@@ -2965,383 +2609,6 @@ void mpeg_error_clear(void)
2965 mpeg_errno = 0; 2609 mpeg_errno = 0;
2966} 2610}
2967 2611
2968#ifndef SIMULATOR
2969#ifdef HAVE_MAS3507D
2970int current_left_volume = 0; /* all values in tenth of dB */
2971int current_right_volume = 0; /* all values in tenth of dB */
2972int current_treble = 0;
2973int current_bass = 0;
2974int current_balance = 0;
2975
2976/* convert tenth of dB volume to register value */
2977static int tenthdb2reg(int db) {
2978 if (db < -540)
2979 return (db + 780) / 30;
2980 else
2981 return (db + 660) / 15;
2982}
2983
2984void set_prescaled_volume(void)
2985{
2986 int prescale;
2987 int l, r;
2988
2989 prescale = MAX(current_bass, current_treble);
2990 if (prescale < 0)
2991 prescale = 0; /* no need to prescale if we don't boost
2992 bass or treble */
2993
2994 mas_writereg(MAS_REG_KPRESCALE, prescale_table[prescale/10]);
2995
2996 /* gain up the analog volume to compensate the prescale reduction gain */
2997 l = current_left_volume + prescale;
2998 r = current_right_volume + prescale;
2999
3000 dac_volume(tenthdb2reg(l), tenthdb2reg(r), false);
3001}
3002#endif /* HAVE_MAS3507D */
3003#endif /* !SIMULATOR */
3004
3005void mpeg_sound_set(int setting, int value)
3006{
3007#ifdef SIMULATOR
3008 setting = value;
3009#else
3010#ifdef HAVE_MAS3507D
3011 int l, r;
3012#else
3013 int tmp;
3014#endif
3015
3016 if(!mpeg_is_initialized)
3017 return;
3018
3019 switch(setting)
3020 {
3021 case SOUND_VOLUME:
3022#ifdef HAVE_MAS3587F
3023 tmp = 0x7f00 * value / 100;
3024 mas_codec_writereg(0x10, tmp & 0xff00);
3025#else
3026 l = value;
3027 r = value;
3028
3029 if(current_balance > 0)
3030 {
3031 l -= current_balance;
3032 if(l < 0)
3033 l = 0;
3034 }
3035
3036 if(current_balance < 0)
3037 {
3038 r += current_balance;
3039 if(r < 0)
3040 r = 0;
3041 }
3042
3043 l = 0x38 * l / 100;
3044 r = 0x38 * r / 100;
3045
3046 /* store volume in tenth of dB */
3047 current_left_volume = ( l < 0x08 ? l*30 - 780 : l*15 - 660 );
3048 current_right_volume = ( r < 0x08 ? r*30 - 780 : r*15 - 660 );
3049
3050 set_prescaled_volume();
3051#endif
3052 break;
3053
3054 case SOUND_BALANCE:
3055#ifdef HAVE_MAS3587F
3056 tmp = ((value * 127 / 100) & 0xff) << 8;
3057 mas_codec_writereg(0x11, tmp & 0xff00);
3058#else
3059 /* Convert to percent */
3060 current_balance = value * 2;
3061#endif
3062 break;
3063
3064 case SOUND_BASS:
3065#ifdef HAVE_MAS3587F
3066 tmp = (((value-12) * 8) & 0xff) << 8;
3067 mas_codec_writereg(0x14, tmp & 0xff00);
3068#else
3069 mas_writereg(MAS_REG_KBASS, bass_table[value]);
3070 current_bass = (value-15) * 10;
3071 set_prescaled_volume();
3072#endif
3073 break;
3074
3075 case SOUND_TREBLE:
3076#ifdef HAVE_MAS3587F
3077 tmp = (((value-12) * 8) & 0xff) << 8;
3078 mas_codec_writereg(0x15, tmp & 0xff00);
3079#else
3080 mas_writereg(MAS_REG_KTREBLE, treble_table[value]);
3081 current_treble = (value-15) * 10;
3082 set_prescaled_volume();
3083#endif
3084 break;
3085
3086#ifdef HAVE_MAS3587F
3087 case SOUND_SUPERBASS:
3088 if (value) {
3089 tmp = MAX(MIN(value * 12, 0x7f), 0);
3090 mas_codec_writereg(MAS_REG_KMDB_STR, (tmp & 0xff) << 8);
3091 tmp = 0x30; /* MDB_HAR: Space for experiment here */
3092 mas_codec_writereg(MAS_REG_KMDB_HAR, (tmp & 0xff) << 8);
3093 tmp = 60 / 10; /* calculate MDB_FC, 60hz - experiment here,
3094 this would depend on the earphones...
3095 perhaps make it tunable? */
3096 mas_codec_writereg(MAS_REG_KMDB_FC, (tmp & 0xff) << 8);
3097 tmp = (3 * tmp) / 2; /* calculate MDB_SHAPE */
3098 mas_codec_writereg(MAS_REG_KMDB_SWITCH,
3099 ((tmp & 0xff) << 8) /* MDB_SHAPE */
3100 | 2); /* MDB_SWITCH enable */
3101 } else {
3102 mas_codec_writereg(MAS_REG_KMDB_STR, 0);
3103 mas_codec_writereg(MAS_REG_KMDB_HAR, 0);
3104 mas_codec_writereg(MAS_REG_KMDB_SWITCH, 0); /* MDB_SWITCH disable */
3105 }
3106 break;
3107
3108 case SOUND_LOUDNESS:
3109 tmp = MAX(MIN(value * 4, 0x44), 0);
3110 mas_codec_writereg(MAS_REG_KLOUDNESS, (tmp & 0xff) << 8);
3111 break;
3112
3113 case SOUND_AVC:
3114 switch (value) {
3115 case 1: /* 2s */
3116 tmp = (0x2 << 8) | (0x8 << 12);
3117 break;
3118 case 2: /* 4s */
3119 tmp = (0x4 << 8) | (0x8 << 12);
3120 break;
3121 case 3: /* 8s */
3122 tmp = (0x8 << 8) | (0x8 << 12);
3123 break;
3124 case -1: /* turn off and then turn on again to decay quickly */
3125 tmp = mas_codec_readreg(MAS_REG_KAVC);
3126 mas_codec_writereg(MAS_REG_KAVC, 0);
3127 break;
3128 default: /* off */
3129 tmp = 0;
3130 break;
3131 }
3132 mas_codec_writereg(MAS_REG_KAVC, tmp);
3133 break;
3134#endif
3135 case SOUND_CHANNELS:
3136 mpeg_sound_channel_config(value);
3137 break;
3138 }
3139#endif /* SIMULATOR */
3140}
3141
3142int mpeg_val2phys(int setting, int value)
3143{
3144 int result = 0;
3145
3146 switch(setting)
3147 {
3148 case SOUND_VOLUME:
3149 result = value;
3150 break;
3151
3152 case SOUND_BALANCE:
3153 result = value * 2;
3154 break;
3155
3156 case SOUND_BASS:
3157#ifdef HAVE_MAS3587F
3158 result = value - 12;
3159#else
3160 result = value - 15;
3161#endif
3162 break;
3163
3164 case SOUND_TREBLE:
3165#ifdef HAVE_MAS3587F
3166 result = value - 12;
3167#else
3168 result = value - 15;
3169#endif
3170 break;
3171
3172#ifdef HAVE_MAS3587F
3173 case SOUND_LOUDNESS:
3174 result = value;
3175 break;
3176
3177 case SOUND_SUPERBASS:
3178 result = value * 10;
3179 break;
3180
3181 case SOUND_LEFT_GAIN:
3182 case SOUND_RIGHT_GAIN:
3183 result = (value - 2) * 15;
3184 break;
3185
3186 case SOUND_MIC_GAIN:
3187 result = value * 15 + 210;
3188 break;
3189#endif
3190 }
3191 return result;
3192}
3193
3194int mpeg_phys2val(int setting, int value)
3195{
3196 int result = 0;
3197
3198 switch(setting)
3199 {
3200 case SOUND_VOLUME:
3201 result = value;
3202 break;
3203
3204 case SOUND_BALANCE:
3205 result = value / 2;
3206 break;
3207
3208 case SOUND_BASS:
3209#ifdef HAVE_MAS3587F
3210 result = value + 12;
3211#else
3212 result = value + 15;
3213#endif
3214 break;
3215
3216 case SOUND_TREBLE:
3217#ifdef HAVE_MAS3587F
3218 result = value + 12;
3219#else
3220 result = value + 15;
3221#endif
3222 break;
3223
3224#ifdef HAVE_MAS3587F
3225 case SOUND_SUPERBASS:
3226 result = value / 10;
3227 break;
3228
3229 case SOUND_LOUDNESS:
3230 case SOUND_AVC:
3231 case SOUND_LEFT_GAIN:
3232 case SOUND_RIGHT_GAIN:
3233 case SOUND_MIC_GAIN:
3234 result = value;
3235 break;
3236#endif
3237 }
3238
3239 return result;
3240}
3241
3242
3243void mpeg_sound_channel_config(int configuration)
3244{
3245#ifdef SIMULATOR
3246 (void)configuration;
3247#else
3248 unsigned long val_ll = 0x80000;
3249 unsigned long val_lr = 0;
3250 unsigned long val_rl = 0;
3251 unsigned long val_rr = 0x80000;
3252
3253 switch(configuration)
3254 {
3255 case MPEG_SOUND_STEREO:
3256 val_ll = 0x80000;
3257 val_lr = 0;
3258 val_rl = 0;
3259 val_rr = 0x80000;
3260 break;
3261
3262 case MPEG_SOUND_MONO:
3263 val_ll = 0xc0000;
3264 val_lr = 0xc0000;
3265 val_rl = 0xc0000;
3266 val_rr = 0xc0000;
3267 break;
3268
3269 case MPEG_SOUND_MONO_LEFT:
3270 val_ll = 0x80000;
3271 val_lr = 0x80000;
3272 val_rl = 0;
3273 val_rr = 0;
3274 break;
3275
3276 case MPEG_SOUND_MONO_RIGHT:
3277 val_ll = 0;
3278 val_lr = 0;
3279 val_rl = 0x80000;
3280 val_rr = 0x80000;
3281 break;
3282
3283 case MPEG_SOUND_STEREO_NARROW:
3284 val_ll = 0xa0000;
3285 val_lr = 0xe0000;
3286 val_rl = 0xe0000;
3287 val_rr = 0xa0000;
3288 break;
3289
3290 case MPEG_SOUND_STEREO_WIDE:
3291 val_ll = 0x80000;
3292 val_lr = 0x40000;
3293 val_rl = 0x40000;
3294 val_rr = 0x80000;
3295 break;
3296
3297 case MPEG_SOUND_KARAOKE:
3298 val_ll = 0x80001;
3299 val_lr = 0x7ffff;
3300 val_rl = 0x7ffff;
3301 val_rr = 0x80001;
3302 break;
3303 }
3304
3305#ifdef HAVE_MAS3587F
3306 mas_writemem(MAS_BANK_D0, 0x7fc, &val_ll, 1); /* LL */
3307 mas_writemem(MAS_BANK_D0, 0x7fd, &val_lr, 1); /* LR */
3308 mas_writemem(MAS_BANK_D0, 0x7fe, &val_rl, 1); /* RL */
3309 mas_writemem(MAS_BANK_D0, 0x7ff, &val_rr, 1); /* RR */
3310#else
3311 mas_writemem(MAS_BANK_D1, 0x7f8, &val_ll, 1); /* LL */
3312 mas_writemem(MAS_BANK_D1, 0x7f9, &val_lr, 1); /* LR */
3313 mas_writemem(MAS_BANK_D1, 0x7fa, &val_rl, 1); /* RL */
3314 mas_writemem(MAS_BANK_D1, 0x7fb, &val_rr, 1); /* RR */
3315#endif
3316#endif
3317}
3318
3319#ifdef HAVE_MAS3587F
3320/* This function works by telling the decoder that we have another
3321 crystal frequency than we actually have. It will adjust its internal
3322 parameters and the result is that the audio is played at another pitch.
3323
3324 The pitch value is in tenths of percent.
3325*/
3326void mpeg_set_pitch(int pitch)
3327{
3328 unsigned long val;
3329
3330 /* invert pitch value */
3331 pitch = 1000000/pitch;
3332
3333 /* Calculate the new (bogus) frequency */
3334 val = 18432*pitch/1000;
3335
3336 mas_writemem(MAS_BANK_D0,0x7f3,&val,1);
3337
3338 /* We must tell the MAS that the frequency has changed.
3339 This will unfortunately cause a short silence. */
3340 val = 0x25;
3341 mas_writemem(MAS_BANK_D0,0x7f1,&val,1);
3342}
3343#endif
3344
3345#ifdef SIMULATOR 2612#ifdef SIMULATOR
3346static char mpeg_stack[DEFAULT_STACK_SIZE]; 2613static char mpeg_stack[DEFAULT_STACK_SIZE];
3347static char mpeg_thread_name[] = "mpeg"; 2614static char mpeg_thread_name[] = "mpeg";
@@ -3364,82 +2631,9 @@ static void mpeg_thread(void)
3364} 2631}
3365#endif 2632#endif
3366 2633
3367void mpeg_init(int volume, int bass, int treble, int balance, int loudness, 2634void mpeg_init(void)
3368 int bass_boost, int avc, int channel_config)
3369{ 2635{
3370 mpeg_errno = 0; 2636 mpeg_errno = 0;
3371
3372#ifdef SIMULATOR
3373 volume = bass = treble = balance = loudness
3374 = bass_boost = avc = channel_config;
3375 create_thread(mpeg_thread, mpeg_stack,
3376 sizeof(mpeg_stack), mpeg_thread_name);
3377#else
3378#ifdef HAVE_MAS3507D
3379 unsigned long val;
3380 loudness = bass_boost = avc;
3381#endif
3382
3383 setup_sci0();
3384
3385#ifdef HAVE_MAS3587F
3386 or_b(0x08, &PAIORH); /* output for /PR */
3387 init_playback();
3388
3389 mas_version_code = mas_readver();
3390 DEBUGF("MAS3587 derivate %d, version B%d\n",
3391 (mas_version_code & 0xff00) >> 8, mas_version_code & 0xff);
3392#endif
3393
3394#ifdef HAVE_DAC3550A
3395 dac_init();
3396#endif
3397
3398#ifdef HAVE_MAS3507D
3399 and_b(~0x20, &PBDRL);
3400 sleep(HZ/5);
3401 or_b(0x20, &PBDRL);
3402 sleep(HZ/5);
3403
3404 /* set IRQ6 to edge detect */
3405 ICR |= 0x02;
3406
3407 /* set IRQ6 prio 8 */
3408 IPRB = ( IPRB & 0xff0f ) | 0x0080;
3409
3410 mas_readmem(MAS_BANK_D1, 0xff7, &mas_version_code, 1);
3411
3412 mas_writereg(0x3b, 0x20); /* Don't ask why. The data sheet doesn't say */
3413 mas_run(1);
3414 sleep(HZ);
3415
3416 /* Clear the upper 12 bits of the 32-bit samples */
3417 mas_writereg(0xc5, 0);
3418 mas_writereg(0xc6, 0);
3419
3420 /* We need to set the PLL for a 14.1318MHz crystal */
3421 if(mas_version_code == 0x0601) /* Version F10? */
3422 {
3423 val = 0x5d9d0;
3424 mas_writemem(MAS_BANK_D0, 0x32d, &val, 1);
3425 val = 0xfffceceb;
3426 mas_writemem(MAS_BANK_D0, 0x32e, &val, 1);
3427 val = 0x0;
3428 mas_writemem(MAS_BANK_D0, 0x32f, &val, 1);
3429 mas_run(0x475);
3430 }
3431 else
3432 {
3433 val = 0x5d9d0;
3434 mas_writemem(MAS_BANK_D0, 0x36d, &val, 1);
3435 val = 0xfffceceb;
3436 mas_writemem(MAS_BANK_D0, 0x36e, &val, 1);
3437 val = 0x0;
3438 mas_writemem(MAS_BANK_D0, 0x36f, &val, 1);
3439 mas_run(0xfcb);
3440 }
3441
3442#endif
3443 2637
3444 mp3buflen = mp3end - mp3buf; 2638 mp3buflen = mp3end - mp3buf;
3445 2639
@@ -3447,36 +2641,6 @@ void mpeg_init(int volume, int bass, int treble, int balance, int loudness,
3447 create_thread(mpeg_thread, mpeg_stack, 2641 create_thread(mpeg_thread, mpeg_stack,
3448 sizeof(mpeg_stack), mpeg_thread_name); 2642 sizeof(mpeg_stack), mpeg_thread_name);
3449 2643
3450#ifdef HAVE_MAS3507D
3451 mas_poll_start(1);
3452
3453 mas_writereg(MAS_REG_KPRESCALE, 0xe9400);
3454 dac_enable(true);
3455
3456 mpeg_sound_channel_config(channel_config);
3457#endif
3458
3459#ifdef HAVE_MAS3587F
3460 ICR &= ~0x0010; /* IRQ3 level sensitive */
3461 PACR1 = (PACR1 & 0x3fff) | 0x4000; /* PA15 is IRQ3 */
3462#endif
3463
3464 /* Must be done before calling mpeg_sound_set() */
3465 mpeg_is_initialized = true;
3466
3467 mpeg_sound_set(SOUND_BASS, bass);
3468 mpeg_sound_set(SOUND_TREBLE, treble);
3469 mpeg_sound_set(SOUND_BALANCE, balance);
3470 mpeg_sound_set(SOUND_VOLUME, volume);
3471
3472#ifdef HAVE_MAS3587F
3473 mpeg_sound_channel_config(channel_config);
3474 mpeg_sound_set(SOUND_LOUDNESS, loudness);
3475 mpeg_sound_set(SOUND_SUPERBASS, bass_boost);
3476 mpeg_sound_set(SOUND_AVC, avc);
3477#endif
3478#endif /* !SIMULATOR */
3479
3480 memset(id3tags, sizeof(id3tags), 0); 2644 memset(id3tags, sizeof(id3tags), 0);
3481 memset(_id3tags, sizeof(id3tags), 0); 2645 memset(_id3tags, sizeof(id3tags), 0);
3482 2646