summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/debug_menu.c211
-rw-r--r--apps/plugin.c59
-rw-r--r--apps/plugin.h67
-rw-r--r--firmware/drivers/uda1380.c22
-rw-r--r--firmware/export/pcm_playback.h1
-rw-r--r--firmware/export/uda1380.h3
-rw-r--r--firmware/pcm_playback.c14
-rw-r--r--firmware/sound.c58
8 files changed, 116 insertions, 319 deletions
diff --git a/apps/debug_menu.c b/apps/debug_menu.c
index f978bc1a54..71f730d2c5 100644
--- a/apps/debug_menu.c
+++ b/apps/debug_menu.c
@@ -59,212 +59,6 @@
59#endif 59#endif
60#include "logfdisp.h" 60#include "logfdisp.h"
61 61
62#ifdef IRIVER_H100
63#include "uda1380.h"
64#include "pcm_playback.h"
65#include "buffer.h"
66
67#define CHUNK_SIZE 0x100000 /* Transfer CHUNK_SIZE bytes on
68 each DMA transfer */
69
70static unsigned char line = 0;
71static unsigned char *audio_buffer;
72static int audio_pos;
73static int audio_size;
74
75static void puts(const char *fmt, ...)
76{
77 char buf[80];
78
79 if (line > 15)
80 {
81 lcd_clear_display();
82 line = 0;
83 }
84
85 va_list ap;
86 va_start(ap, fmt);
87 vsnprintf(buf, sizeof(buf)-1, fmt, ap);
88 va_end(ap);
89
90 lcd_puts(0, line, buf);
91 lcd_update();
92
93 line++;
94}
95
96/* Very basic WAVE-file support.. Just for testing purposes.. */
97int load_wave(char *filename)
98{
99 int f, i, num;
100 unsigned char buf[32];
101 unsigned short *p, *end;
102
103 puts("Loading %s..", filename);
104
105 f = open(filename, O_RDONLY);
106 if (f == -1)
107 {
108 puts("File not found");
109 return -1;
110 }
111
112 memset(buf,0,32);
113 read(f, buf, 32);
114 if (memcmp(buf, "RIFF", 4) != 0 || memcmp(buf+8, "WAVE", 4) != 0)
115 {
116 puts("Not WAVE");
117 return -1;
118 }
119 if (buf[12+8] != 1 || buf[12+9] != 0 || /* Check PCM format */
120 buf[12+10] != 2 || buf[12+11] != 0) /* Check stereo */
121 {
122 puts("Unsupported format");
123 return -1;
124 }
125
126 audio_size = filesize(f) - 0x30;
127 if (audio_size > 8*1024*1024)
128 audio_size = 8*1024*1024;
129
130 audio_buffer = audiobuf;
131
132 puts("Reading %d bytes..", audio_size);
133
134 lseek(f, 0x30, SEEK_SET); /* Skip wave header */
135
136 read(f, audio_buffer, audio_size);
137 close(f);
138
139 puts("Changing byte order..");
140 end = (unsigned short *)(audio_buffer + audio_size);
141 p = (unsigned short *)audio_buffer;
142 while(p < end)
143 {
144 /* Swap 128k at a time, to allow the other threads to run */
145 num = MIN(0x20000, (int)(end - p));
146 for(i = 0;i < num;i++)
147 {
148 *p = SWAB16(*p);
149 p++;
150 }
151 yield();
152 }
153
154 return 0;
155}
156
157/*
158 Test routined of the UDA1380 codec
159 - Loads a WAVE file and plays it..
160 - Control play/stop, master volume and analog mixer volume
161
162*/
163
164int test_tracknum;
165static void test_trackchange(void)
166{
167 test_tracknum++;
168}
169
170extern int pcmbuf_unplayed_bytes;
171
172bool uda1380_test(void)
173{
174 long button;
175 int vol = 0x50;
176 bool done = false;
177 char buf[80];
178 bool play = true;
179 int sz;
180 char *ptr;
181
182 lcd_setmargins(0, 0);
183 lcd_clear_display();
184 lcd_update();
185
186 test_tracknum = 1;
187
188 line = 0;
189
190 if (load_wave("/sample.wav") == -1)
191 goto exit;
192
193 audio_pos = 0;
194
195 puts("Playing..");
196
197 audio_pos = 0;
198 pcm_play_init();
199 pcm_set_frequency(44100);
200 pcm_set_volume(0xff - vol);
201
202 ptr = audio_buffer;
203 for(sz = 0;sz < audio_size;sz += CHUNK_SIZE)
204 {
205 if(!pcm_play_add_chunk(ptr, CHUNK_SIZE, test_trackchange))
206 break;
207 ptr += MIN(CHUNK_SIZE, (audio_size - sz));
208 }
209
210 pcm_play_start();
211
212 while(!done)
213 {
214 snprintf(buf, sizeof(buf), "SAR0: %08lx", SAR0);
215 lcd_puts(0, line, buf);
216 snprintf(buf, sizeof(buf), "DAR0: %08lx", DAR0);
217 lcd_puts(0, line+1, buf);
218 snprintf(buf, sizeof(buf), "BCR0: %08lx", BCR0);
219 lcd_puts(0, line+2, buf);
220 snprintf(buf, sizeof(buf), "DCR0: %08lx", DCR0);
221 lcd_puts(0, line+3, buf);
222 snprintf(buf, sizeof(buf), "DSR0: %02x", DSR0);
223 lcd_puts(0, line+4, buf);
224 snprintf(buf, sizeof(buf), "Track: %d", test_tracknum);
225 lcd_puts(0, line+5, buf);
226 snprintf(buf, sizeof(buf), "Unplayed: %08x", pcmbuf_unplayed_bytes);
227 lcd_puts(0, line+6, buf);
228 lcd_update();
229
230 button = button_get_w_tmo(HZ/2);
231 switch(button)
232 {
233 case BUTTON_ON:
234 play = !play;
235 pcm_play_pause(play);
236 break;
237
238 case BUTTON_UP:
239 if (vol)
240 vol--;
241
242 uda1380_setvol(vol);
243 break;
244 case BUTTON_DOWN:
245 if (vol < 255)
246 vol++;
247
248 uda1380_setvol(vol);
249 break;
250 case BUTTON_OFF:
251 done = true;
252 break;
253 }
254
255 if(!pcm_is_playing())
256 done = true;
257 }
258
259 pcm_play_stop();
260
261exit:
262 sleep(HZ >> 1); /* Sleep 1/2 second to fade out sound */
263
264 return false;
265}
266#endif
267
268/*---------------------------------------------------*/ 62/*---------------------------------------------------*/
269/* SPECIAL DEBUG STUFF */ 63/* SPECIAL DEBUG STUFF */
270/*---------------------------------------------------*/ 64/*---------------------------------------------------*/
@@ -469,7 +263,7 @@ static unsigned flash_read_word(unsigned addr) {
469 Only chips which could be reprogrammed in system will return values. 263 Only chips which could be reprogrammed in system will return values.
470 (The mode switch addresses vary between flash manufacturers, hence addr1/2) */ 264 (The mode switch addresses vary between flash manufacturers, hence addr1/2) */
471 /* In IRAM to avoid problems when running directly from Flash */ 265 /* In IRAM to avoid problems when running directly from Flash */
472bool dbg_flash_id(unsigned* p_manufacturer, unsigned* p_device, 266bool dbg_flash_id(unsigned* p_manufacturer, unsigned* p_device,
473 unsigned addr1, unsigned addr2) 267 unsigned addr1, unsigned addr2)
474 __attribute__ ((section (".icode"))); 268 __attribute__ ((section (".icode")));
475bool dbg_flash_id(unsigned* p_manufacturer, unsigned* p_device, 269bool dbg_flash_id(unsigned* p_manufacturer, unsigned* p_device,
@@ -2006,9 +1800,6 @@ bool debug_menu(void)
2006#ifdef HAVE_ADJUSTABLE_CPU_FREQ 1800#ifdef HAVE_ADJUSTABLE_CPU_FREQ
2007 { "CPU frequency", dbg_cpufreq }, 1801 { "CPU frequency", dbg_cpufreq },
2008#endif 1802#endif
2009#ifdef IRIVER_H100
2010 { "Audio test", uda1380_test },
2011#endif
2012#if CONFIG_CPU == SH7034 1803#if CONFIG_CPU == SH7034
2013#ifdef HAVE_LCD_BITMAP 1804#ifdef HAVE_LCD_BITMAP
2014#ifdef HAVE_RTC 1805#ifdef HAVE_RTC
diff --git a/apps/plugin.c b/apps/plugin.c
index b4a3d5c5c0..90b64efa66 100644
--- a/apps/plugin.c
+++ b/apps/plugin.c
@@ -136,6 +136,7 @@ static const struct plugin_api rockbox_api = {
136 backlight_set_timeout, 136 backlight_set_timeout,
137 splash, 137 splash,
138#ifdef HAVE_REMOTE_LCD 138#ifdef HAVE_REMOTE_LCD
139 /* remote lcd */
139 lcd_remote_clear_display, 140 lcd_remote_clear_display,
140 lcd_remote_puts, 141 lcd_remote_puts,
141 lcd_remote_puts_scroll, 142 lcd_remote_puts_scroll,
@@ -158,9 +159,7 @@ static const struct plugin_api rockbox_api = {
158 lcd_remote_getstringsize, 159 lcd_remote_getstringsize,
159 lcd_remote_update, 160 lcd_remote_update,
160 lcd_remote_update_rect, 161 lcd_remote_update_rect,
161 //id (*scrollbar)(int x, int y, int width, int height, int items, 162
162 // int min_shown, int max_shown, int orientation);
163 //void (*remote_checkbox)(int x, int y, int width, int height, bool checked);
164 lcd_remote_backlight_on, 163 lcd_remote_backlight_on,
165 lcd_remote_backlight_off, 164 lcd_remote_backlight_off,
166 &lcd_remote_framebuffer[0][0], 165 &lcd_remote_framebuffer[0][0],
@@ -170,6 +169,9 @@ static const struct plugin_api rockbox_api = {
170 button_get_w_tmo, 169 button_get_w_tmo,
171 button_status, 170 button_status,
172 button_clear_queue, 171 button_clear_queue,
172#if CONFIG_KEYPAD == IRIVER_H100_PAD
173 button_hold,
174#endif
173 175
174 /* file */ 176 /* file */
175 (open_func)PREFIX(open), 177 (open_func)PREFIX(open),
@@ -193,6 +195,7 @@ static const struct plugin_api rockbox_api = {
193 PREFIX(opendir), 195 PREFIX(opendir),
194 PREFIX(closedir), 196 PREFIX(closedir),
195 PREFIX(readdir), 197 PREFIX(readdir),
198 PREFIX(mkdir),
196 199
197 /* kernel/ system */ 200 /* kernel/ system */
198 PREFIX(sleep), 201 PREFIX(sleep),
@@ -205,6 +208,10 @@ static const struct plugin_api rockbox_api = {
205 reset_poweroff_timer, 208 reset_poweroff_timer,
206#ifndef SIMULATOR 209#ifndef SIMULATOR
207 system_memory_guard, 210 system_memory_guard,
211 &cpu_frequency,
212#ifdef HAVE_ADJUSTABLE_CPU_FREQ
213 cpu_boost,
214#endif
208#endif 215#endif
209 216
210 /* strings and memory */ 217 /* strings and memory */
@@ -223,6 +230,7 @@ static const struct plugin_api rockbox_api = {
223 strchr, 230 strchr,
224 strcat, 231 strcat,
225 memcmp, 232 memcmp,
233 strcasestr,
226 234
227 /* sound */ 235 /* sound */
228 sound_set, 236 sound_set,
@@ -234,8 +242,15 @@ static const struct plugin_api rockbox_api = {
234#if CONFIG_HWCODEC != MASNONE 242#if CONFIG_HWCODEC != MASNONE
235 bitswap, 243 bitswap,
236#endif 244#endif
245#if CONFIG_HWCODEC == MASNONE
246 pcm_play_data,
247 pcm_play_stop,
248 pcm_set_frequency,
249 pcm_is_playing,
250 pcm_play_pause,
251#endif
237#endif 252#endif
238 253
239 /* playback control */ 254 /* playback control */
240 PREFIX(audio_play), 255 PREFIX(audio_play),
241 audio_stop, 256 audio_stop,
@@ -270,6 +285,12 @@ static const struct plugin_api rockbox_api = {
270#endif 285#endif
271#endif /* !simulator and HWCODEC != MASNONE */ 286#endif /* !simulator and HWCODEC != MASNONE */
272 287
288 /* tag database */
289 &tagdbheader,
290 &tagdb_fd,
291 &tagdb_initialized,
292 tagdb_init,
293
273 /* misc */ 294 /* misc */
274 srand, 295 srand,
275 rand, 296 rand,
@@ -299,35 +320,13 @@ static const struct plugin_api rockbox_api = {
299 peak_meter_set_use_dbfs, 320 peak_meter_set_use_dbfs,
300 peak_meter_get_use_dbfs, 321 peak_meter_get_use_dbfs,
301#endif 322#endif
302
303 /* new stuff at the end, sort into place next time
304 the API gets incompatible */
305#ifndef SIMULATOR
306 &cpu_frequency,
307#ifdef HAVE_ADJUSTABLE_CPU_FREQ
308 cpu_boost,
309#endif
310#endif
311 PREFIX(mkdir),
312#if CONFIG_KEYPAD == IRIVER_H100_PAD
313 button_hold,
314#endif
315#if (CONFIG_HWCODEC == MASNONE) && !defined(SIMULATOR)
316 pcm_play_data,
317 pcm_play_stop,
318 pcm_set_frequency,
319 pcm_is_playing,
320 pcm_set_volume,
321 pcm_play_pause,
322#endif
323#ifdef HAVE_LCD_BITMAP 323#ifdef HAVE_LCD_BITMAP
324 read_bmp_file, 324 read_bmp_file,
325#endif 325#endif
326 &tagdbheader, 326
327 &tagdb_fd, 327 /* new stuff at the end, sort into place next time
328 &tagdb_initialized, 328 the API gets incompatible */
329 tagdb_init, 329
330 strcasestr,
331}; 330};
332 331
333#if CONFIG_HWCODEC == MASNONE 332#if CONFIG_HWCODEC == MASNONE
diff --git a/apps/plugin.h b/apps/plugin.h
index b4c1189635..3990ffeed4 100644
--- a/apps/plugin.h
+++ b/apps/plugin.h
@@ -78,12 +78,12 @@
78#endif 78#endif
79 79
80/* increase this every time the api struct changes */ 80/* increase this every time the api struct changes */
81#define PLUGIN_API_VERSION 39 81#define PLUGIN_API_VERSION 40
82 82
83/* update this to latest version if a change to the api struct breaks 83/* update this to latest version if a change to the api struct breaks
84 backwards compatibility (and please take the opportunity to sort in any 84 backwards compatibility (and please take the opportunity to sort in any
85 new function which are "waiting" at the end of the function table) */ 85 new function which are "waiting" at the end of the function table) */
86#define PLUGIN_MIN_API_VERSION 32 86#define PLUGIN_MIN_API_VERSION 40
87 87
88/* plugin return codes */ 88/* plugin return codes */
89enum plugin_status { 89enum plugin_status {
@@ -177,6 +177,7 @@ struct plugin_api {
177 void (*splash)(int ticks, bool center, const char *fmt, ...); 177 void (*splash)(int ticks, bool center, const char *fmt, ...);
178 178
179#ifdef HAVE_REMOTE_LCD 179#ifdef HAVE_REMOTE_LCD
180 /* remote lcd */
180 void (*remote_clear_display)(void); 181 void (*remote_clear_display)(void);
181 void (*remote_puts)(int x, int y, const unsigned char *string); 182 void (*remote_puts)(int x, int y, const unsigned char *string);
182 void (*remote_lcd_puts_scroll)(int x, int y, const unsigned char* string); 183 void (*remote_lcd_puts_scroll)(int x, int y, const unsigned char* string);
@@ -202,12 +203,10 @@ struct plugin_api {
202 int (*remote_getstringsize)(const unsigned char *str, int *w, int *h); 203 int (*remote_getstringsize)(const unsigned char *str, int *w, int *h);
203 void (*remote_update)(void); 204 void (*remote_update)(void);
204 void (*remote_update_rect)(int x, int y, int width, int height); 205 void (*remote_update_rect)(int x, int y, int width, int height);
205// void (*remote_scrollbar)(int x, int y, int width, int height, int items, 206
206// int min_shown, int max_shown, int orientation);
207 //void (*remote_checkbox)(int x, int y, int width, int height, bool checked);
208 void (*remote_backlight_on)(void); 207 void (*remote_backlight_on)(void);
209 void (*remote_backlight_off)(void); 208 void (*remote_backlight_off)(void);
210 unsigned char* lcd_remote_framebuffer; 209 unsigned char* lcd_remote_framebuffer;
211#endif 210#endif
212 211
213 /* button */ 212 /* button */
@@ -215,6 +214,9 @@ struct plugin_api {
215 long (*button_get_w_tmo)(int ticks); 214 long (*button_get_w_tmo)(int ticks);
216 int (*button_status)(void); 215 int (*button_status)(void);
217 void (*button_clear_queue)(void); 216 void (*button_clear_queue)(void);
217#if CONFIG_KEYPAD == IRIVER_H100_PAD
218 bool (*button_hold)(void);
219#endif
218 220
219 /* file */ 221 /* file */
220 int (*PREFIX(open))(const char* pathname, int flags); 222 int (*PREFIX(open))(const char* pathname, int flags);
@@ -238,6 +240,7 @@ struct plugin_api {
238 DIR* (*PREFIX(opendir))(const char* name); 240 DIR* (*PREFIX(opendir))(const char* name);
239 int (*PREFIX(closedir))(DIR* dir); 241 int (*PREFIX(closedir))(DIR* dir);
240 struct dirent* (*PREFIX(readdir))(DIR* dir); 242 struct dirent* (*PREFIX(readdir))(DIR* dir);
243 int (*PREFIX(mkdir))(const char *name, int mode);
241 244
242 /* kernel/ system */ 245 /* kernel/ system */
243 void (*PREFIX(sleep))(int ticks); 246 void (*PREFIX(sleep))(int ticks);
@@ -250,6 +253,10 @@ struct plugin_api {
250 void (*reset_poweroff_timer)(void); 253 void (*reset_poweroff_timer)(void);
251#ifndef SIMULATOR 254#ifndef SIMULATOR
252 int (*system_memory_guard)(int newmode); 255 int (*system_memory_guard)(int newmode);
256 long *cpu_frequency;
257#ifdef HAVE_ADJUSTABLE_CPU_FREQ
258 void (*cpu_boost)(bool on_off);
259#endif
253#endif 260#endif
254 261
255 /* strings and memory */ 262 /* strings and memory */
@@ -268,6 +275,7 @@ struct plugin_api {
268 char *(*strchr)(const char *s, int c); 275 char *(*strchr)(const char *s, int c);
269 char *(*strcat)(char *s1, const char *s2); 276 char *(*strcat)(char *s1, const char *s2);
270 int (*memcmp)(const void *s1, const void *s2, size_t n); 277 int (*memcmp)(const void *s1, const void *s2, size_t n);
278 char *(*strcasestr) (const char* phaystack, const char* pneedle);
271 279
272 /* sound */ 280 /* sound */
273 void (*sound_set)(int setting, int value); 281 void (*sound_set)(int setting, int value);
@@ -279,7 +287,15 @@ struct plugin_api {
279#if CONFIG_HWCODEC != MASNONE 287#if CONFIG_HWCODEC != MASNONE
280 void (*bitswap)(unsigned char *data, int length); 288 void (*bitswap)(unsigned char *data, int length);
281#endif 289#endif
290#if CONFIG_HWCODEC == MASNONE
291 void (*pcm_play_data)(const unsigned char *start, int size,
292 void (*get_more)(unsigned char** start, long*size));
293 void (*pcm_play_stop)(void);
294 void (*pcm_set_frequency)(unsigned int frequency);
295 bool (*pcm_is_playing)(void);
296 void (*pcm_play_pause)(bool play);
282#endif 297#endif
298#endif /* !SIMULATOR */
283 299
284 /* playback control */ 300 /* playback control */
285 void (*PREFIX(audio_play))(int offset); 301 void (*PREFIX(audio_play))(int offset);
@@ -315,6 +331,12 @@ struct plugin_api {
315#endif 331#endif
316#endif 332#endif
317 333
334 /* tag database */
335 struct tagdb_header *tagdbheader;
336 int *tagdb_fd;
337 int *tagdb_initialized;
338 int (*tagdb_init) (void);
339
318 /* misc */ 340 /* misc */
319 void (*srand)(unsigned int seed); 341 void (*srand)(unsigned int seed);
320 int (*rand)(void); 342 int (*rand)(void);
@@ -351,37 +373,14 @@ struct plugin_api {
351 void (*peak_meter_set_use_dbfs)(int use); 373 void (*peak_meter_set_use_dbfs)(int use);
352 int (*peak_meter_get_use_dbfs)(void); 374 int (*peak_meter_get_use_dbfs)(void);
353#endif 375#endif
354
355 /* new stuff at the end, sort into place next time
356 the API gets incompatible */
357#ifndef SIMULATOR
358 long *cpu_frequency;
359#ifdef HAVE_ADJUSTABLE_CPU_FREQ
360 void (*cpu_boost)(bool on_off);
361#endif
362#endif
363 int (*PREFIX(mkdir))(const char *name, int mode);
364#if CONFIG_KEYPAD == IRIVER_H100_PAD
365 bool (*button_hold)(void);
366#endif
367#if (CONFIG_HWCODEC == MASNONE) && !defined(SIMULATOR)
368 void (*pcm_play_data)(const unsigned char *start, int size,
369 void (*get_more)(unsigned char** start, long*size));
370 void (*pcm_play_stop)(void);
371 void (*pcm_set_frequency)(unsigned int frequency);
372 bool (*pcm_is_playing)(void);
373 void (*pcm_set_volume)(int volume);
374 void (*pcm_play_pause)(bool play);
375#endif
376#ifdef HAVE_LCD_BITMAP 376#ifdef HAVE_LCD_BITMAP
377 int (*read_bmp_file)(char* filename, int *get_width, int *get_height, 377 int (*read_bmp_file)(char* filename, int *get_width, int *get_height,
378 char *bitmap, int maxsize); 378 char *bitmap, int maxsize);
379#endif 379#endif
380 struct tagdb_header *tagdbheader; 380
381 int *tagdb_fd; 381 /* new stuff at the end, sort into place next time
382 int *tagdb_initialized; 382 the API gets incompatible */
383 int (*tagdb_init) (void); 383
384 char *(*strcasestr) (const char* phaystack, const char* pneedle);
385}; 384};
386 385
387/* defined by the plugin loader (plugin.c) */ 386/* defined by the plugin loader (plugin.c) */
diff --git a/firmware/drivers/uda1380.c b/firmware/drivers/uda1380.c
index 7170b707e4..23d917f8ae 100644
--- a/firmware/drivers/uda1380.c
+++ b/firmware/drivers/uda1380.c
@@ -85,33 +85,15 @@ int uda1380_write_reg(unsigned char reg, unsigned short value)
85} 85}
86 86
87/** 87/**
88 * Sets the master volume 88 * Sets left and right master volume (0(max) to 252(muted))
89 *
90 * \param vol Range [0..255] 0=max, 255=mute
91 *
92 */ 89 */
93int uda1380_setvol(int vol) 90int uda1380_setvol(int vol_l, int vol_r)
94{ 91{
95 int vol_l, vol_r;
96
97 uda1380_volume = vol;
98 /* Simple linear volume crossfade curves */
99 vol_l = MAX(uda1380_balance*(255 - vol)/100 + vol, vol);
100 vol_r = MAX(-uda1380_balance*(255 - vol)/100 + vol, vol);
101 return uda1380_write_reg(REG_MASTER_VOL, 92 return uda1380_write_reg(REG_MASTER_VOL,
102 MASTER_VOL_LEFT(vol_l) | MASTER_VOL_RIGHT(vol_r)); 93 MASTER_VOL_LEFT(vol_l) | MASTER_VOL_RIGHT(vol_r));
103} 94}
104 95
105/** 96/**
106 * Sets stereo balance
107 */
108void uda1380_set_balance(int bal)
109{
110 uda1380_balance = bal;
111 uda1380_setvol(uda1380_volume);
112}
113
114/**
115 * Sets the bass value (0-15) 97 * Sets the bass value (0-15)
116 */ 98 */
117void uda1380_set_bass(int value) 99void uda1380_set_bass(int value)
diff --git a/firmware/export/pcm_playback.h b/firmware/export/pcm_playback.h
index c78936a3f2..874ed6ac6c 100644
--- a/firmware/export/pcm_playback.h
+++ b/firmware/export/pcm_playback.h
@@ -31,7 +31,6 @@ void pcm_play_data(const unsigned char* start, int size,
31void pcm_play_stop(void); 31void pcm_play_stop(void);
32void pcm_play_pause(bool play); 32void pcm_play_pause(bool play);
33bool pcm_is_playing(void); 33bool pcm_is_playing(void);
34void pcm_set_volume(int volume);
35 34
36/* These functions are for playing chained buffers of PCM data */ 35/* These functions are for playing chained buffers of PCM data */
37void pcm_play_init(void); 36void pcm_play_init(void);
diff --git a/firmware/export/uda1380.h b/firmware/export/uda1380.h
index b09d271808..503b59d102 100644
--- a/firmware/export/uda1380.h
+++ b/firmware/export/uda1380.h
@@ -22,8 +22,7 @@
22 22
23extern int uda1380_init(void); 23extern int uda1380_init(void);
24extern void uda1380_enable_output(bool enable); 24extern void uda1380_enable_output(bool enable);
25extern int uda1380_setvol(int vol); 25extern int uda1380_setvol(int vol_l, int vol_r);
26extern void uda1380_set_balance(int bal);
27extern void uda1380_set_bass(int value); 26extern void uda1380_set_bass(int value);
28extern void uda1380_set_treble(int value); 27extern void uda1380_set_treble(int value);
29extern int uda1380_mute(int mute); 28extern int uda1380_mute(int mute);
diff --git a/firmware/pcm_playback.c b/firmware/pcm_playback.c
index 45e91ac3be..eab6fe1f15 100644
--- a/firmware/pcm_playback.c
+++ b/firmware/pcm_playback.c
@@ -123,20 +123,6 @@ static void dma_stop(void)
123 IIS2CONFIG = 0x800; 123 IIS2CONFIG = 0x800;
124} 124}
125 125
126/* set volume of the main channel */
127void pcm_set_volume(int volume)
128{
129 if(volume > 0)
130 {
131 uda1380_mute(0);
132 uda1380_setvol(0xff - volume);
133 }
134 else
135 {
136 uda1380_mute(1);
137 }
138}
139
140/* sets frequency of input to DAC */ 126/* sets frequency of input to DAC */
141void pcm_set_frequency(unsigned int frequency) 127void pcm_set_frequency(unsigned int frequency)
142{ 128{
diff --git a/firmware/sound.c b/firmware/sound.c
index 7dd1fbf98e..cd6448c754 100644
--- a/firmware/sound.c
+++ b/firmware/sound.c
@@ -334,7 +334,7 @@ static int tenthdb2reg(int db) {
334 return (db + 660) / 15; 334 return (db + 660) / 15;
335} 335}
336 336
337void set_prescaled_volume(void) 337static void set_prescaled_volume(void)
338{ 338{
339 int prescale; 339 int prescale;
340 int l, r; 340 int l, r;
@@ -367,7 +367,47 @@ void set_prescaled_volume(void)
367 367
368 dac_volume(tenthdb2reg(l), tenthdb2reg(r), false); 368 dac_volume(tenthdb2reg(l), tenthdb2reg(r), false);
369} 369}
370#endif /* MAS3507D */ 370#elif CONFIG_HWCODEC == MASNONE
371#ifdef HAVE_UDA1380 /* iriver H1x0 + H3x0 */
372/* all values in tenth of dB */
373int current_volume = 0; /* -840..0 */
374int current_balance = 0; /* -840..+840 */
375
376/* convert tenth of dB volume to register value */
377static int tenthdb2reg(int db) {
378 if (db < -720) /* 1.5 dB steps */
379 return (2940 - db) / 15;
380 else if (db < -660) /* 0.75 dB steps */
381 return (1110 - db) * 2 / 15;
382 else if (db < -520) /* 0.5 dB steps */
383 return (520 - db) / 5;
384 else /* 0.25 dB steps */
385 return -db * 2 / 5;
386}
387
388static void set_volume(void)
389{
390 int l, r;
391
392 l = r = current_volume;
393
394 if (current_balance > 0)
395 {
396 l -= current_balance;
397 if (l < -840)
398 l = -840;
399 }
400 if (current_balance < 0)
401 {
402 r += current_balance;
403 if (r < -840)
404 r = -840;
405 }
406
407 uda1380_setvol(tenthdb2reg(l), tenthdb2reg(r));
408}
409#endif
410#endif /* MASNONE */
371#endif /* !SIMULATOR */ 411#endif /* !SIMULATOR */
372 412
373int channel_configuration = SOUND_CHAN_STEREO; 413int channel_configuration = SOUND_CHAN_STEREO;
@@ -480,7 +520,8 @@ void sound_set(int setting, int value)
480 current_volume = -780 + (value * 960 / 100); /* tenth of dB */ 520 current_volume = -780 + (value * 960 / 100); /* tenth of dB */
481 set_prescaled_volume(); 521 set_prescaled_volume();
482#elif CONFIG_HWCODEC == MASNONE 522#elif CONFIG_HWCODEC == MASNONE
483 pcm_set_volume((value*167117) >> 16); 523 current_volume = -840 + (value * 840 / 100); /* tenth of dB */
524 set_volume();
484#endif 525#endif
485 break; 526 break;
486 527
@@ -492,7 +533,8 @@ void sound_set(int setting, int value)
492 current_balance = value * 960 / 100; /* tenth of dB */ 533 current_balance = value * 960 / 100; /* tenth of dB */
493 set_prescaled_volume(); 534 set_prescaled_volume();
494#elif defined(HAVE_UDA1380) 535#elif defined(HAVE_UDA1380)
495 uda1380_set_balance(value); 536 current_balance = value * 840 / 100; /* tenth of dB */
537 set_volume();
496#endif 538#endif
497 break; 539 break;
498 540
@@ -500,12 +542,12 @@ void sound_set(int setting, int value)
500#if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F) 542#if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F)
501 tmp = ((value * 8) & 0xff) << 8; 543 tmp = ((value * 8) & 0xff) << 8;
502 mas_codec_writereg(0x14, tmp & 0xff00); 544 mas_codec_writereg(0x14, tmp & 0xff00);
503#elif defined(HAVE_UDA1380)
504 uda1380_set_bass(value >> 1);
505#elif CONFIG_HWCODEC == MAS3507D 545#elif CONFIG_HWCODEC == MAS3507D
506 mas_writereg(MAS_REG_KBASS, bass_table[value+15]); 546 mas_writereg(MAS_REG_KBASS, bass_table[value+15]);
507 current_bass = value * 10; 547 current_bass = value * 10;
508 set_prescaled_volume(); 548 set_prescaled_volume();
549#elif defined(HAVE_UDA1380)
550 uda1380_set_bass(value >> 1);
509#endif 551#endif
510 break; 552 break;
511 553
@@ -513,12 +555,12 @@ void sound_set(int setting, int value)
513#if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F) 555#if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F)
514 tmp = ((value * 8) & 0xff) << 8; 556 tmp = ((value * 8) & 0xff) << 8;
515 mas_codec_writereg(0x15, tmp & 0xff00); 557 mas_codec_writereg(0x15, tmp & 0xff00);
516#elif defined(HAVE_UDA1380)
517 uda1380_set_treble(value >> 1);
518#elif CONFIG_HWCODEC == MAS3507D 558#elif CONFIG_HWCODEC == MAS3507D
519 mas_writereg(MAS_REG_KTREBLE, treble_table[value+15]); 559 mas_writereg(MAS_REG_KTREBLE, treble_table[value+15]);
520 current_treble = value * 10; 560 current_treble = value * 10;
521 set_prescaled_volume(); 561 set_prescaled_volume();
562#elif defined(HAVE_UDA1380)
563 uda1380_set_treble(value >> 1);
522#endif 564#endif
523 break; 565 break;
524 566