diff options
author | Michiel Van Der Kolk <not.valid@email.address> | 2005-03-28 00:00:24 +0000 |
---|---|---|
committer | Michiel Van Der Kolk <not.valid@email.address> | 2005-03-28 00:00:24 +0000 |
commit | 451dd48adc2ef29fd2f900693393cc9b9b4a849b (patch) | |
tree | e15d20e602261866617210bde007966ce9b19293 | |
parent | 853bc3dcf85aa1284a0e5b550277c40beb7697a9 (diff) | |
download | rockbox-451dd48adc2ef29fd2f900693393cc9b9b4a849b.tar.gz rockbox-451dd48adc2ef29fd2f900693393cc9b9b4a849b.zip |
Sound api improvements, rockboy sound, contributed by xshock.
Playback of sound currently only works in boost mode, needs fixing.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@6226 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r-- | apps/debug_menu.c | 35 | ||||
-rw-r--r-- | apps/main.c | 7 | ||||
-rw-r--r-- | apps/plugin.c | 8 | ||||
-rw-r--r-- | apps/plugin.h | 7 | ||||
-rw-r--r-- | apps/plugins/rockboy/pcm.h | 2 | ||||
-rw-r--r-- | apps/plugins/rockboy/rbsound.c | 111 | ||||
-rw-r--r-- | apps/plugins/rockboy/rockboy.c | 4 | ||||
-rw-r--r-- | apps/plugins/rockboy/sound.c | 12 | ||||
-rw-r--r-- | firmware/drivers/uda1380.c | 4 | ||||
-rw-r--r-- | firmware/export/pcm_playback.h | 2 | ||||
-rw-r--r-- | firmware/pcm_playback.c | 78 |
11 files changed, 208 insertions, 62 deletions
diff --git a/apps/debug_menu.c b/apps/debug_menu.c index 9d5028af7c..74d1cb94fb 100644 --- a/apps/debug_menu.c +++ b/apps/debug_menu.c | |||
@@ -169,27 +169,29 @@ static void test_get_more(unsigned char **ptr, long *size) | |||
169 | bool uda1380_test(void) | 169 | bool uda1380_test(void) |
170 | { | 170 | { |
171 | long button; | 171 | long button; |
172 | int vol = 0x7f; | 172 | int vol = 0x50; |
173 | bool done = false; | 173 | bool done = false; |
174 | 174 | ||
175 | lcd_setmargins(0, 0); | 175 | lcd_setmargins(0, 0); |
176 | lcd_clear_display(); | 176 | lcd_clear_display(); |
177 | lcd_update(); | 177 | lcd_update(); |
178 | cpu_boost(true); | ||
178 | 179 | ||
179 | if (load_wave("/sample.wav") == -1) | 180 | if (load_wave("/sample.wav") == -1) |
180 | goto exit; | 181 | goto exit; |
181 | 182 | ||
182 | audio_pos = 0; | 183 | audio_pos = 0; |
183 | 184 | ||
185 | puts("Playing.."); | ||
184 | puts("uda1380_init"); | 186 | puts("uda1380_init"); |
185 | if (uda1380_init() == -1) | 187 | if (uda1380_init() == -1) |
186 | { | 188 | { |
187 | puts("Init failed.."); | 189 | puts("UDA1380 init failed"); |
188 | goto exit; | ||
189 | } | 190 | } |
190 | 191 | ||
191 | puts("Playing.."); | ||
192 | audio_pos = 0; | 192 | audio_pos = 0; |
193 | pcm_set_frequency(44100); | ||
194 | pcm_set_volume(0xff - vol); | ||
193 | pcm_play_data(audio_buffer, CHUNK_SIZE, | 195 | pcm_play_data(audio_buffer, CHUNK_SIZE, |
194 | test_get_more); | 196 | test_get_more); |
195 | 197 | ||
@@ -224,6 +226,7 @@ bool uda1380_test(void) | |||
224 | 226 | ||
225 | exit: | 227 | exit: |
226 | sleep(HZ >> 1); /* Sleep 1/2 second to fade out sound */ | 228 | sleep(HZ >> 1); /* Sleep 1/2 second to fade out sound */ |
229 | cpu_boost(false); | ||
227 | 230 | ||
228 | return false; | 231 | return false; |
229 | } | 232 | } |
@@ -1247,10 +1250,9 @@ bool view_battery(void) | |||
1247 | lcd_puts(0, 3, buf); | 1250 | lcd_puts(0, 3, buf); |
1248 | #endif | 1251 | #endif |
1249 | #ifdef HAVE_CHARGE_CTRL | 1252 | #ifdef HAVE_CHARGE_CTRL |
1250 | snprintf(buf, 30, "Chgr: %s %s", | 1253 | snprintf(buf, 30, "Charging: %s", |
1251 | charger_inserted() ? "present" : "absent", | 1254 | charger_enabled ? "yes" : "no"); |
1252 | charger_enabled ? "on" : "off"); | 1255 | lcd_puts(0, 4, buf); |
1253 | lcd_puts(0, 3, buf); | ||
1254 | snprintf(buf, 30, "short delta: %d", short_delta); | 1256 | snprintf(buf, 30, "short delta: %d", short_delta); |
1255 | lcd_puts(0, 5, buf); | 1257 | lcd_puts(0, 5, buf); |
1256 | snprintf(buf, 30, "long delta: %d", long_delta); | 1258 | snprintf(buf, 30, "long delta: %d", long_delta); |
@@ -1272,7 +1274,7 @@ bool view_battery(void) | |||
1272 | } | 1274 | } |
1273 | break; | 1275 | break; |
1274 | 1276 | ||
1275 | case 3: /* remaining time estimation: */ | 1277 | case 3: /* remeining time estimation: */ |
1276 | lcd_clear_display(); | 1278 | lcd_clear_display(); |
1277 | 1279 | ||
1278 | #ifdef HAVE_CHARGE_CTRL | 1280 | #ifdef HAVE_CHARGE_CTRL |
@@ -1284,24 +1286,23 @@ bool view_battery(void) | |||
1284 | 1286 | ||
1285 | snprintf(buf, 30, "Lvl@cyc st: %d%%", powermgmt_last_cycle_level); | 1287 | snprintf(buf, 30, "Lvl@cyc st: %d%%", powermgmt_last_cycle_level); |
1286 | lcd_puts(0, 2, buf); | 1288 | lcd_puts(0, 2, buf); |
1287 | |||
1288 | snprintf(buf, 30, "P=%2d I=%2d", pid_p, pid_i); | ||
1289 | lcd_puts(0, 3, buf); | ||
1290 | |||
1291 | snprintf(buf, 30, "Trickle sec: %d/60", trickle_sec); | ||
1292 | lcd_puts(0, 4, buf); | ||
1293 | #endif | 1289 | #endif |
1294 | 1290 | ||
1295 | snprintf(buf, 30, "Last PwrHist: %d.%02d V", | 1291 | snprintf(buf, 30, "Last PwrHist: %d.%02d V", |
1296 | power_history[0] / 100, | 1292 | power_history[0] / 100, |
1297 | power_history[0] % 100); | 1293 | power_history[0] % 100); |
1298 | lcd_puts(0, 5, buf); | 1294 | lcd_puts(0, 3, buf); |
1299 | 1295 | ||
1300 | snprintf(buf, 30, "battery level: %d%%", battery_level()); | 1296 | snprintf(buf, 30, "battery level: %d%%", battery_level()); |
1301 | lcd_puts(0, 6, buf); | 1297 | lcd_puts(0, 5, buf); |
1302 | 1298 | ||
1303 | snprintf(buf, 30, "Est. remain: %d m", battery_time()); | 1299 | snprintf(buf, 30, "Est. remain: %d m", battery_time()); |
1300 | lcd_puts(0, 6, buf); | ||
1301 | |||
1302 | #ifdef HAVE_CHARGE_CTRL | ||
1303 | snprintf(buf, 30, "Trickle sec: %d/60", trickle_sec); | ||
1304 | lcd_puts(0, 7, buf); | 1304 | lcd_puts(0, 7, buf); |
1305 | #endif | ||
1305 | break; | 1306 | break; |
1306 | } | 1307 | } |
1307 | 1308 | ||
diff --git a/apps/main.c b/apps/main.c index c5e5492337..36f26c9154 100644 --- a/apps/main.c +++ b/apps/main.c | |||
@@ -58,6 +58,10 @@ | |||
58 | #include "power.h" | 58 | #include "power.h" |
59 | #include "talk.h" | 59 | #include "talk.h" |
60 | #include "plugin.h" | 60 | #include "plugin.h" |
61 | |||
62 | |||
63 | #include "uda1380.h" | ||
64 | |||
61 | #ifdef CONFIG_TUNER | 65 | #ifdef CONFIG_TUNER |
62 | #include "radio.h" | 66 | #include "radio.h" |
63 | #endif | 67 | #endif |
@@ -261,6 +265,9 @@ void init(void) | |||
261 | } | 265 | } |
262 | } | 266 | } |
263 | #endif /* #ifdef AUTOROCK */ | 267 | #endif /* #ifdef AUTOROCK */ |
268 | |||
269 | uda1380_init(); | ||
270 | |||
264 | } | 271 | } |
265 | 272 | ||
266 | int main(void) | 273 | int main(void) |
diff --git a/apps/plugin.c b/apps/plugin.c index b4239bb8d9..ecd5025e2c 100644 --- a/apps/plugin.c +++ b/apps/plugin.c | |||
@@ -44,7 +44,7 @@ | |||
44 | #include "mp3data.h" | 44 | #include "mp3data.h" |
45 | #include "powermgmt.h" | 45 | #include "powermgmt.h" |
46 | #include "system.h" | 46 | #include "system.h" |
47 | #if (CONFIG_HWCODEC == MASNONE) && !defined(SIMULATOR) | 47 | #if (CONFIG_HWCODEC == MASNONE) |
48 | #include "pcm_playback.h" | 48 | #include "pcm_playback.h" |
49 | #endif | 49 | #endif |
50 | 50 | ||
@@ -271,10 +271,12 @@ static const struct plugin_api rockbox_api = { | |||
271 | #if CONFIG_KEYPAD == IRIVER_H100_PAD | 271 | #if CONFIG_KEYPAD == IRIVER_H100_PAD |
272 | button_hold, | 272 | button_hold, |
273 | #endif | 273 | #endif |
274 | #if (CONFIG_HWCODEC == MASNONE) && !defined(SIMULATOR) | 274 | #if (CONFIG_HWCODEC == MASNONE) |
275 | pcm_play_data, | 275 | pcm_play_data, |
276 | pcm_play_stop, | 276 | pcm_play_stop, |
277 | pcm_set_frequency, | ||
277 | pcm_is_playing, | 278 | pcm_is_playing, |
279 | pcm_set_volume | ||
278 | #endif | 280 | #endif |
279 | }; | 281 | }; |
280 | 282 | ||
diff --git a/apps/plugin.h b/apps/plugin.h index 3755018d6d..30ecfc7963 100644 --- a/apps/plugin.h +++ b/apps/plugin.h | |||
@@ -43,6 +43,7 @@ | |||
43 | #include "id3.h" | 43 | #include "id3.h" |
44 | #include "mpeg.h" | 44 | #include "mpeg.h" |
45 | #include "mp3_playback.h" | 45 | #include "mp3_playback.h" |
46 | #include "pcm_playback.h" | ||
46 | #include "settings.h" | 47 | #include "settings.h" |
47 | #include "thread.h" | 48 | #include "thread.h" |
48 | #include "playlist.h" | 49 | #include "playlist.h" |
@@ -317,11 +318,13 @@ struct plugin_api { | |||
317 | #if CONFIG_KEYPAD == IRIVER_H100_PAD | 318 | #if CONFIG_KEYPAD == IRIVER_H100_PAD |
318 | bool (*button_hold)(void); | 319 | bool (*button_hold)(void); |
319 | #endif | 320 | #endif |
320 | #if (CONFIG_HWCODEC == MASNONE) && !defined(SIMULATOR) | 321 | #if (CONFIG_HWCODEC == MASNONE) |
321 | void (*pcm_play_data)(const unsigned char *start, int size, | 322 | void (*pcm_play_data)(const unsigned char *start, int size, |
322 | void (*get_more)(unsigned char** start, long*size)); | 323 | void (*get_more)(unsigned char** start, long*size)); |
323 | void (*pcm_play_stop)(void); | 324 | void (*pcm_play_stop)(void); |
325 | void (*pcm_set_frequency)(unsigned int frequency); | ||
324 | bool (*pcm_is_playing)(void); | 326 | bool (*pcm_is_playing)(void); |
327 | void (*pcm_set_volume)(int volume); | ||
325 | #endif | 328 | #endif |
326 | }; | 329 | }; |
327 | 330 | ||
diff --git a/apps/plugins/rockboy/pcm.h b/apps/plugins/rockboy/pcm.h index 3719933520..742f0e5a95 100644 --- a/apps/plugins/rockboy/pcm.h +++ b/apps/plugins/rockboy/pcm.h | |||
@@ -9,7 +9,7 @@ struct pcm | |||
9 | { | 9 | { |
10 | int hz, len; | 10 | int hz, len; |
11 | int stereo; | 11 | int stereo; |
12 | byte *buf; | 12 | short *buf; |
13 | int pos; | 13 | int pos; |
14 | }; | 14 | }; |
15 | 15 | ||
diff --git a/apps/plugins/rockboy/rbsound.c b/apps/plugins/rockboy/rbsound.c index 6d1b24fd9a..92f824aa3b 100644 --- a/apps/plugins/rockboy/rbsound.c +++ b/apps/plugins/rockboy/rbsound.c | |||
@@ -1,47 +1,120 @@ | |||
1 | |||
2 | |||
3 | |||
4 | #include "rockmacros.h" | 1 | #include "rockmacros.h" |
5 | #include "defs.h" | 2 | #include "defs.h" |
6 | #include "pcm.h" | 3 | #include "pcm.h" |
7 | #include "rc.h" | 4 | #include "rc.h" |
8 | 5 | ||
6 | #define RBSOUND | ||
9 | 7 | ||
10 | struct pcm pcm; | 8 | struct pcm pcm; |
11 | 9 | ||
12 | static byte buf[4096]; | 10 | #define BUF_SIZE (8192) |
11 | #define DMA_PORTION (1024) | ||
12 | |||
13 | static short buf1_unal[(BUF_SIZE / sizeof(short)) + 2]; // to make sure 4 byte aligned | ||
14 | static short* buf1; | ||
13 | 15 | ||
16 | static short front_buf[512]; | ||
17 | |||
18 | static short* last_back_pos; | ||
19 | |||
20 | static bool newly_started; | ||
21 | static int turns; | ||
14 | 22 | ||
15 | rcvar_t pcm_exports[] = | 23 | rcvar_t pcm_exports[] = |
16 | { | 24 | { |
17 | RCV_END | 25 | RCV_END |
18 | }; | 26 | }; |
19 | 27 | ||
20 | |||
21 | void pcm_init(void) | 28 | void pcm_init(void) |
22 | { | 29 | { |
23 | pcm.hz = 44100; | 30 | buf1 = (signed short*)((((unsigned int)buf1_unal) >> 2) << 2); /* here i just make sure that buffer is aligned to 4 bytes*/ |
24 | pcm.stereo = 1; | 31 | newly_started = true; |
25 | pcm.buf = buf; | 32 | last_back_pos = buf1; |
26 | pcm.len = sizeof buf; | 33 | turns = 0; |
27 | pcm.pos = 0; | 34 | |
35 | pcm.hz = 11025; | ||
36 | pcm.stereo = 1; | ||
37 | pcm.buf = front_buf; | ||
38 | pcm.len = (sizeof(front_buf)) / sizeof(short); /* length in shorts, not bytes */ | ||
39 | pcm.pos = 0; | ||
40 | |||
41 | |||
42 | rb->pcm_play_stop(); | ||
43 | rb->pcm_set_frequency(11025); | ||
44 | rb->pcm_set_volume(200); | ||
28 | } | 45 | } |
29 | 46 | ||
30 | void pcm_close(void) | 47 | void pcm_close(void) |
31 | { | 48 | { |
32 | memset(&pcm, 0, sizeof pcm); | 49 | memset(&pcm, 0, sizeof pcm); |
50 | newly_started = true; | ||
51 | last_back_pos = buf1; | ||
52 | rb->pcm_play_stop(); | ||
33 | } | 53 | } |
34 | 54 | ||
55 | void get_more(unsigned char** start, long* size) | ||
56 | { | ||
57 | int length; | ||
58 | unsigned int sar = (unsigned int)SAR0; | ||
59 | length = ((unsigned int)buf1) + BUF_SIZE - sar; | ||
60 | |||
61 | if(turns > 0) | ||
62 | { | ||
63 | newly_started = true; | ||
64 | last_back_pos = buf1; | ||
65 | turns = 0; | ||
66 | return; | ||
67 | } /* sound will stop if no one feeds data*/ | ||
68 | |||
69 | if(length <= 0) | ||
70 | { | ||
71 | *start = (unsigned char*)buf1; | ||
72 | *size = DMA_PORTION; | ||
73 | turns++; | ||
74 | } | ||
75 | else | ||
76 | { | ||
77 | *start = (unsigned char*)sar; | ||
78 | if(length > DMA_PORTION) | ||
79 | *size = DMA_PORTION; | ||
80 | else | ||
81 | *size = length; | ||
82 | } | ||
83 | |||
84 | } | ||
85 | |||
35 | int pcm_submit(void) | 86 | int pcm_submit(void) |
36 | { | 87 | { |
37 | #ifdef RBSOUND | 88 | #ifdef RBSOUND |
38 | rb->pcm_play_data(pcm.buf,pcm.pos,NULL); | 89 | while( (turns < 0) && ((((unsigned int)last_back_pos) + pcm.pos * sizeof(short)) > ((unsigned int)SAR0)) && !newly_started) rb->yield(); /* wait until data is passed through DAC or until exit*/ |
39 | while(rb->pcm_is_playing()); /* spinlock */ | 90 | int shorts_left = ((((unsigned int)buf1) + BUF_SIZE) - ((unsigned int)last_back_pos)) / sizeof(short); |
40 | pcm.pos = 0; | 91 | if( shorts_left >= pcm.pos ) |
41 | return 1; | 92 | { |
93 | memcpy(last_back_pos,pcm.buf,pcm.pos * sizeof(short)); | ||
94 | last_back_pos = &last_back_pos[pcm.pos]; | ||
95 | } | ||
96 | else | ||
97 | { | ||
98 | int last_pos = shorts_left; | ||
99 | memcpy(last_back_pos,pcm.buf,shorts_left * sizeof(short)); | ||
100 | last_back_pos = buf1; | ||
101 | shorts_left = pcm.pos - shorts_left; | ||
102 | memcpy(last_back_pos,&pcm.buf[last_pos],shorts_left * sizeof(short)); | ||
103 | last_back_pos = &buf1[shorts_left]; | ||
104 | turns--; | ||
105 | } | ||
106 | |||
107 | if(newly_started) | ||
108 | { | ||
109 | rb->pcm_play_data((unsigned char*)buf1,pcm.pos * sizeof(short),&get_more); | ||
110 | newly_started = false; | ||
111 | } | ||
112 | |||
113 | pcm.pos = 0; | ||
114 | return 1; | ||
42 | #else | 115 | #else |
43 | pcm.pos = 0; | 116 | pcm.pos = 0; |
44 | return 0; | 117 | return 0; |
45 | #endif | 118 | #endif |
46 | } | 119 | } |
47 | 120 | ||
diff --git a/apps/plugins/rockboy/rockboy.c b/apps/plugins/rockboy/rockboy.c index a34fd7bf69..c6d006a131 100644 --- a/apps/plugins/rockboy/rockboy.c +++ b/apps/plugins/rockboy/rockboy.c | |||
@@ -51,6 +51,7 @@ struct plugin_api* rb; | |||
51 | int shut,cleanshut; | 51 | int shut,cleanshut; |
52 | char *errormsg; | 52 | char *errormsg; |
53 | int gnuboy_main(char *rom); | 53 | int gnuboy_main(char *rom); |
54 | void pcm_close(void); | ||
54 | 55 | ||
55 | void die(char *message, ...) | 56 | void die(char *message, ...) |
56 | { | 57 | { |
@@ -124,10 +125,11 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter) | |||
124 | rb->splash(HZ*2, true, errormsg); | 125 | rb->splash(HZ*2, true, errormsg); |
125 | return PLUGIN_ERROR; | 126 | return PLUGIN_ERROR; |
126 | } | 127 | } |
127 | 128 | pcm_close(); | |
128 | rb->splash(HZ*2, true, "Shutting down.. byebye ^^"); | 129 | rb->splash(HZ*2, true, "Shutting down.. byebye ^^"); |
129 | 130 | ||
130 | cleanup(); | 131 | cleanup(); |
131 | 132 | ||
133 | |||
132 | return PLUGIN_OK; | 134 | return PLUGIN_OK; |
133 | } | 135 | } |
diff --git a/apps/plugins/rockboy/sound.c b/apps/plugins/rockboy/sound.c index edf31d81b7..10fc504063 100644 --- a/apps/plugins/rockboy/sound.c +++ b/apps/plugins/rockboy/sound.c | |||
@@ -60,9 +60,9 @@ int pcm_submit(void); | |||
60 | #define S4 (snd.ch[3]) | 60 | #define S4 (snd.ch[3]) |
61 | 61 | ||
62 | rcvar_t sound_exports[] = | 62 | rcvar_t sound_exports[] = |
63 | { | 63 | { |
64 | RCV_END | 64 | RCV_END |
65 | }; | 65 | }; |
66 | 66 | ||
67 | 67 | ||
68 | static void s1_freq_d(int d) | 68 | static void s1_freq_d(int d) |
@@ -275,10 +275,10 @@ void sound_mix(void) | |||
275 | pcm_submit(); | 275 | pcm_submit(); |
276 | if (pcm.stereo) | 276 | if (pcm.stereo) |
277 | { | 277 | { |
278 | pcm.buf[pcm.pos++] = l+128; | 278 | pcm.buf[pcm.pos++] = (signed short)(l * 256); |
279 | pcm.buf[pcm.pos++] = r+128; | 279 | pcm.buf[pcm.pos++] = (signed short)(r * 256); |
280 | } | 280 | } |
281 | else pcm.buf[pcm.pos++] = ((l+r)>>1)+128; | 281 | else pcm.buf[pcm.pos++] = (signed short)((r+l) * 128); |
282 | } | 282 | } |
283 | } | 283 | } |
284 | R_NR52 = (R_NR52&0xf0) | S1.on | (S2.on<<1) | (S3.on<<2) | (S4.on<<3); | 284 | R_NR52 = (R_NR52&0xf0) | S1.on | (S2.on<<1) | (S3.on<<2) | (S4.on<<3); |
diff --git a/firmware/drivers/uda1380.c b/firmware/drivers/uda1380.c index e8b8c14399..8c3cf61eae 100644 --- a/firmware/drivers/uda1380.c +++ b/firmware/drivers/uda1380.c | |||
@@ -49,7 +49,7 @@ unsigned short uda1380_defaults[2*NUM_DEFAULT_REGS] = | |||
49 | REG_I2S, I2S_IFMT_IIS, | 49 | REG_I2S, I2S_IFMT_IIS, |
50 | REG_PWR, PON_PLL | PON_HP | PON_DAC | EN_AVC | PON_AVC | PON_BIAS, | 50 | REG_PWR, PON_PLL | PON_HP | PON_DAC | EN_AVC | PON_AVC | PON_BIAS, |
51 | REG_AMIX, AMIX_RIGHT(0x10) | AMIX_LEFT(0x10), /* 00=max, 3f=mute */ | 51 | REG_AMIX, AMIX_RIGHT(0x10) | AMIX_LEFT(0x10), /* 00=max, 3f=mute */ |
52 | REG_MASTER_VOL, MASTER_VOL_LEFT(0x7f) | MASTER_VOL_RIGHT(0x7f), /* 00=max, ff=mute */ | 52 | REG_MASTER_VOL, MASTER_VOL_LEFT(0x20) | MASTER_VOL_RIGHT(0x20), /* 00=max, ff=mute */ |
53 | REG_MIX_VOL, MIX_VOL_CHANNEL_1(0) | MIX_VOL_CHANNEL_2(0xff), /* 00=max, ff=mute */ | 53 | REG_MIX_VOL, MIX_VOL_CHANNEL_1(0) | MIX_VOL_CHANNEL_2(0xff), /* 00=max, ff=mute */ |
54 | REG_EQ, 0, | 54 | REG_EQ, 0, |
55 | REG_MUTE, MUTE_CH2, /* Mute channel 2 (digital decimation filter) */ | 55 | REG_MUTE, MUTE_CH2, /* Mute channel 2 (digital decimation filter) */ |
@@ -131,6 +131,8 @@ int uda1380_set_regs(void) | |||
131 | /* Initialize UDA1380 codec with default register values (uda1380_defaults) */ | 131 | /* Initialize UDA1380 codec with default register values (uda1380_defaults) */ |
132 | int uda1380_init(void) | 132 | int uda1380_init(void) |
133 | { | 133 | { |
134 | PLLCR &= ~(1 << 22); /* Set AudioClk = FXTAL/2*/ | ||
135 | |||
134 | if (uda1380_set_regs() == -1) | 136 | if (uda1380_set_regs() == -1) |
135 | return -1; | 137 | return -1; |
136 | 138 | ||
diff --git a/firmware/export/pcm_playback.h b/firmware/export/pcm_playback.h index c44fb283ec..6010293bbd 100644 --- a/firmware/export/pcm_playback.h +++ b/firmware/export/pcm_playback.h | |||
@@ -19,9 +19,11 @@ | |||
19 | #ifndef PCM_PLAYBACK_H | 19 | #ifndef PCM_PLAYBACK_H |
20 | #define PCM_PLAYBACK_H | 20 | #define PCM_PLAYBACK_H |
21 | 21 | ||
22 | void pcm_set_frequency(unsigned int frequency); | ||
22 | void pcm_play_data(const unsigned char* start, int size, | 23 | void pcm_play_data(const unsigned char* start, int size, |
23 | void (*get_more)(unsigned char** start, long* size)); | 24 | void (*get_more)(unsigned char** start, long* size)); |
24 | void pcm_play_stop(void); | 25 | void pcm_play_stop(void); |
25 | bool pcm_is_playing(void); | 26 | bool pcm_is_playing(void); |
27 | void pcm_set_volume(int volume); | ||
26 | 28 | ||
27 | #endif | 29 | #endif |
diff --git a/firmware/pcm_playback.c b/firmware/pcm_playback.c index fba85f083b..bc2218be69 100644 --- a/firmware/pcm_playback.c +++ b/firmware/pcm_playback.c | |||
@@ -37,20 +37,32 @@ | |||
37 | #include "file.h" | 37 | #include "file.h" |
38 | #include "buffer.h" | 38 | #include "buffer.h" |
39 | 39 | ||
40 | bool pcm_playing; | 40 | #include "sprintf.h" |
41 | #include "button.h" | ||
42 | #include <string.h> | ||
43 | |||
44 | static bool pcm_playing; | ||
45 | static int pcm_freq = 0x6; // 44.1 in default | ||
41 | 46 | ||
42 | /* Set up the DMA transfer that kicks in when the audio FIFO gets empty */ | 47 | /* Set up the DMA transfer that kicks in when the audio FIFO gets empty */ |
43 | static void dma_start(const void *addr, long size) | 48 | static void dma_start(const void *addr_r, long size) |
44 | { | 49 | { |
45 | pcm_playing = 1; | 50 | pcm_playing = 1; |
51 | int i; | ||
52 | |||
53 | int align; | ||
54 | align = 4; | ||
55 | |||
56 | void* addr = (void*)((((unsigned int)addr_r) >> 2) << 2); // always align data, never pass unaligned data | ||
57 | size = (size >> 2) << 2; // size shoudl also be always multiple of 4 | ||
46 | 58 | ||
47 | BUSMASTER_CTRL = 0x81; /* PARK[1,0]=10 + BCR24BIT */ | 59 | BUSMASTER_CTRL = 0x81; /* PARK[1,0]=10 + BCR24BIT */ |
48 | 60 | ||
49 | /* Set up DMA transfer */ | 61 | /* Set up DMA transfer */ |
50 | DIVR0 = 54; /* DMA0 is mapped into vector 54 in system.c */ | 62 | DIVR0 = 54; /* DMA0 is mapped into vector 54 in system.c */ |
51 | SAR0 = (unsigned long)addr; /* Source address */ | 63 | SAR0 = ((unsigned long)addr) + align*4; /* Source address */ |
52 | DAR0 = (unsigned long)&PDOR3; /* Destination address */ | 64 | DAR0 = (unsigned long)&PDOR3; /* Destination address */ |
53 | BCR0 = size; /* Bytes to transfer */ | 65 | BCR0 = size-(align*4); /* Bytes to transfer */ |
54 | DMAROUTE = (DMAROUTE & 0xffffff00) | DMA0_REQ_AUDIO_1; | 66 | DMAROUTE = (DMAROUTE & 0xffffff00) | DMA0_REQ_AUDIO_1; |
55 | DMACONFIG = 1; /* Enable DMA0Req => set DMAROUTE |= DMA0_REQ_AUDIO_1 */ | 67 | DMACONFIG = 1; /* Enable DMA0Req => set DMAROUTE |= DMA0_REQ_AUDIO_1 */ |
56 | 68 | ||
@@ -61,14 +73,10 @@ static void dma_start(const void *addr, long size) | |||
61 | ICR4 = (ICR4 & 0xffff00ff) | 0x00001c00; | 73 | ICR4 = (ICR4 & 0xffff00ff) | 0x00001c00; |
62 | IMR &= ~(1<<14); /* bit 14 is DMA0 */ | 74 | IMR &= ~(1<<14); /* bit 14 is DMA0 */ |
63 | 75 | ||
64 | IIS2CONFIG = 0x4300; /* CLOCKSEL = AudioClk/8 (44.1kHz), | 76 | IIS2CONFIG = (pcm_freq << 12) | 0x300; /* CLOCKSEL for right frequency + data source = PDOR3 */ |
65 | data source = PDOR3 */ | ||
66 | 77 | ||
67 | PDOR3 = 0; /* These are needed to generate FIFO empty request to DMA.. */ | 78 | for(i = 0; i < align; i++) |
68 | PDOR3 = 0; | 79 | PDOR3 = ((unsigned int*)(addr))[i]; /* These are needed to generate FIFO empty request to DMA.. */ |
69 | PDOR3 = 0; | ||
70 | PDOR3 = 0; | ||
71 | PDOR3 = 0; | ||
72 | } | 80 | } |
73 | 81 | ||
74 | /* Stops the DMA transfer and interrupt */ | 82 | /* Stops the DMA transfer and interrupt */ |
@@ -76,12 +84,51 @@ static void dma_stop(void) | |||
76 | { | 84 | { |
77 | pcm_playing = 0; | 85 | pcm_playing = 0; |
78 | DCR0 = 0; | 86 | DCR0 = 0; |
87 | |||
88 | /* DMAROUTE &= 0xffffff00; | ||
89 | DMACONFIG = 0;*/ | ||
90 | |||
91 | IIS2CONFIG = 0x800; | ||
79 | 92 | ||
80 | /* Disable DMA0 interrupt */ | 93 | /* Disable DMA0 interrupt */ |
81 | IMR |= (1<<14); | 94 | IMR |= (1<<14); |
82 | ICR4 &= 0xffff00ff; | 95 | ICR4 &= 0xffff00ff; |
83 | } | 96 | } |
84 | 97 | ||
98 | |||
99 | /* set volume of the main channel */ | ||
100 | void pcm_set_volume(int volume) | ||
101 | { | ||
102 | if(volume > 0) | ||
103 | { | ||
104 | uda1380_mute(0); | ||
105 | uda1380_setvol(0xff - volume); | ||
106 | } | ||
107 | else | ||
108 | { | ||
109 | uda1380_mute(1); | ||
110 | } | ||
111 | } | ||
112 | |||
113 | /* sets frequency of input to DAC */ | ||
114 | void pcm_set_frequency(unsigned int frequency) | ||
115 | { | ||
116 | switch(frequency) | ||
117 | { | ||
118 | case 11025: | ||
119 | pcm_freq = 0x2; | ||
120 | break; | ||
121 | case 22050: | ||
122 | pcm_freq = 0x4; | ||
123 | break; | ||
124 | case 44100: | ||
125 | pcm_freq = 0x6; | ||
126 | break; | ||
127 | default: | ||
128 | pcm_freq = 0x6; | ||
129 | } | ||
130 | } | ||
131 | |||
85 | /* the registered callback function to ask for more mp3 data */ | 132 | /* the registered callback function to ask for more mp3 data */ |
86 | static void (*callback_for_more)(unsigned char**, long*) = NULL; | 133 | static void (*callback_for_more)(unsigned char**, long*) = NULL; |
87 | 134 | ||
@@ -110,8 +157,15 @@ void DMA0(void) | |||
110 | unsigned char* start; | 157 | unsigned char* start; |
111 | long size = 0; | 158 | long size = 0; |
112 | 159 | ||
160 | int res = DSR0; | ||
161 | |||
113 | DSR0 = 1; /* Clear interrupt */ | 162 | DSR0 = 1; /* Clear interrupt */ |
114 | 163 | ||
164 | if(res == 0x41) | ||
165 | { | ||
166 | dma_stop(); | ||
167 | } | ||
168 | |||
115 | if (callback_for_more) | 169 | if (callback_for_more) |
116 | { | 170 | { |
117 | callback_for_more(&start, &size); | 171 | callback_for_more(&start, &size); |