Iriver UDA1380 volume and balance handling is now done in sound.c, similar to archos player; removed pcm_set_volume(). Implemented a dB-linear scale. Sorted & bumped plugin api. Removed audio test from the debug menu.


git-svn-id: svn://svn.rockbox.org/rockbox/trunk@6741 a1c6a512-1295-4272-9138-f99709370657
diff --git a/apps/debug_menu.c b/apps/debug_menu.c
index f978bc1..71f730d 100644
--- a/apps/debug_menu.c
+++ b/apps/debug_menu.c
@@ -59,212 +59,6 @@
 #endif
 #include "logfdisp.h"
 
-#ifdef IRIVER_H100
-#include "uda1380.h"
-#include "pcm_playback.h"
-#include "buffer.h"
-
-#define CHUNK_SIZE      0x100000    /* Transfer CHUNK_SIZE bytes on
-                                       each DMA transfer */
-
-static unsigned char line = 0;
-static unsigned char *audio_buffer;
-static int           audio_pos;
-static int           audio_size;
-
-static void puts(const char *fmt, ...)
-{
-    char buf[80];
-
-    if (line > 15)
-    {
-        lcd_clear_display();
-        line = 0;
-    }
-
-    va_list ap;
-    va_start(ap, fmt);
-    vsnprintf(buf, sizeof(buf)-1, fmt, ap);
-    va_end(ap);
-
-    lcd_puts(0, line, buf);
-    lcd_update();
-    
-    line++;
-}
-
-/* Very basic WAVE-file support.. Just for testing purposes.. */
-int load_wave(char *filename)
-{
-    int f, i, num;
-    unsigned char buf[32];
-    unsigned short *p, *end;
-
-    puts("Loading %s..", filename);
-
-    f = open(filename, O_RDONLY);
-    if (f == -1)
-    {
-        puts("File not found");
-        return -1;
-    }
-
-    memset(buf,0,32);
-    read(f, buf, 32);
-    if (memcmp(buf, "RIFF", 4) != 0 || memcmp(buf+8, "WAVE", 4) != 0)
-    {
-        puts("Not WAVE");
-        return -1;
-    }
-    if (buf[12+8] != 1 || buf[12+9] != 0 ||       /* Check PCM format */
-        buf[12+10] != 2 || buf[12+11] != 0)       /* Check stereo */
-    {
-        puts("Unsupported format");
-        return -1;
-    }
-
-    audio_size = filesize(f) - 0x30;
-    if (audio_size > 8*1024*1024)
-        audio_size = 8*1024*1024;
-
-    audio_buffer = audiobuf;
-
-    puts("Reading %d bytes..", audio_size);
-
-    lseek(f, 0x30, SEEK_SET);    /* Skip wave header */
-
-    read(f, audio_buffer, audio_size);
-    close(f);
-
-    puts("Changing byte order..");
-    end = (unsigned short *)(audio_buffer + audio_size);
-    p = (unsigned short *)audio_buffer;
-    while(p < end)
-    {
-        /* Swap 128k at a time, to allow the other threads to run */
-        num = MIN(0x20000, (int)(end - p));
-        for(i = 0;i < num;i++)
-        {
-            *p = SWAB16(*p);
-            p++;
-        }
-        yield();
-    }
-
-    return 0;
-}
-
-/* 
-    Test routined of the UDA1380 codec 
-    - Loads a WAVE file and plays it..
-    - Control play/stop, master volume and analog mixer volume
-
-*/
-
-int test_tracknum;
-static void test_trackchange(void)
-{
-    test_tracknum++;
-}
-
-extern int pcmbuf_unplayed_bytes;
-
-bool uda1380_test(void)
-{
-    long button;
-    int vol = 0x50;
-    bool done = false;
-    char buf[80];
-    bool play = true;
-    int sz;
-    char *ptr;
-
-    lcd_setmargins(0, 0);
-    lcd_clear_display(); 
-    lcd_update();
-
-    test_tracknum = 1;
-    
-    line = 0;
-    
-    if (load_wave("/sample.wav") == -1)
-        goto exit;
-
-    audio_pos = 0;
-
-    puts("Playing..");
-
-    audio_pos = 0;
-    pcm_play_init();
-    pcm_set_frequency(44100);
-    pcm_set_volume(0xff - vol);
-
-    ptr = audio_buffer;
-    for(sz = 0;sz < audio_size;sz += CHUNK_SIZE)
-    {
-        if(!pcm_play_add_chunk(ptr, CHUNK_SIZE, test_trackchange))
-            break;
-        ptr += MIN(CHUNK_SIZE, (audio_size - sz));
-    }
-
-    pcm_play_start();
-
-    while(!done)
-    {
-        snprintf(buf, sizeof(buf), "SAR0: %08lx", SAR0);
-        lcd_puts(0, line, buf);
-        snprintf(buf, sizeof(buf), "DAR0: %08lx", DAR0);
-        lcd_puts(0, line+1, buf);
-        snprintf(buf, sizeof(buf), "BCR0: %08lx", BCR0);
-        lcd_puts(0, line+2, buf);
-        snprintf(buf, sizeof(buf), "DCR0: %08lx", DCR0);
-        lcd_puts(0, line+3, buf);
-        snprintf(buf, sizeof(buf), "DSR0: %02x", DSR0);
-        lcd_puts(0, line+4, buf);
-        snprintf(buf, sizeof(buf), "Track: %d", test_tracknum);
-        lcd_puts(0, line+5, buf);
-        snprintf(buf, sizeof(buf), "Unplayed: %08x", pcmbuf_unplayed_bytes);
-        lcd_puts(0, line+6, buf);
-        lcd_update();
-
-        button = button_get_w_tmo(HZ/2);
-        switch(button)
-        {
-        case BUTTON_ON:
-            play = !play;
-            pcm_play_pause(play);
-            break;
-            
-        case BUTTON_UP:
-            if (vol)
-                vol--;
-
-            uda1380_setvol(vol);
-            break;
-        case BUTTON_DOWN:
-            if (vol < 255)
-                vol++;
-
-            uda1380_setvol(vol);
-            break;
-        case BUTTON_OFF:
-            done = true;
-            break;
-        }
-        
-        if(!pcm_is_playing())
-            done = true;
-    }
-     
-    pcm_play_stop();
-
-exit:
-    sleep(HZ >> 1);  /* Sleep 1/2 second to fade out sound */
-
-    return false;
-}
-#endif
-
 /*---------------------------------------------------*/
 /*    SPECIAL DEBUG STUFF                            */
 /*---------------------------------------------------*/
@@ -469,7 +263,7 @@
    Only chips which could be reprogrammed in system will return values.
    (The mode switch addresses vary between flash manufacturers, hence addr1/2) */
    /* In IRAM to avoid problems when running directly from Flash */
-bool dbg_flash_id(unsigned* p_manufacturer, unsigned* p_device, 
+bool dbg_flash_id(unsigned* p_manufacturer, unsigned* p_device,
                   unsigned addr1, unsigned addr2)
                   __attribute__ ((section (".icode")));
 bool dbg_flash_id(unsigned* p_manufacturer, unsigned* p_device,
@@ -2006,9 +1800,6 @@
 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
         { "CPU frequency", dbg_cpufreq },
 #endif
-#ifdef IRIVER_H100
-        { "Audio test", uda1380_test },
-#endif
 #if CONFIG_CPU == SH7034
 #ifdef HAVE_LCD_BITMAP
 #ifdef HAVE_RTC
diff --git a/apps/plugin.c b/apps/plugin.c
index b4a3d5c..90b64ef 100644
--- a/apps/plugin.c
+++ b/apps/plugin.c
@@ -136,6 +136,7 @@
     backlight_set_timeout,
     splash,
 #ifdef HAVE_REMOTE_LCD
+    /* remote lcd */
     lcd_remote_clear_display,
     lcd_remote_puts,
     lcd_remote_puts_scroll,
@@ -158,9 +159,7 @@
     lcd_remote_getstringsize,
     lcd_remote_update,
     lcd_remote_update_rect,
-    //id (*scrollbar)(int x, int y, int width, int height, int items,
-    //                int min_shown, int max_shown, int orientation);
-    //void (*remote_checkbox)(int x, int y, int width, int height, bool checked);
+
     lcd_remote_backlight_on,
     lcd_remote_backlight_off,
     &lcd_remote_framebuffer[0][0],
@@ -170,6 +169,9 @@
     button_get_w_tmo,
     button_status,
     button_clear_queue,
+#if CONFIG_KEYPAD == IRIVER_H100_PAD
+    button_hold,
+#endif
 
     /* file */
     (open_func)PREFIX(open),
@@ -193,6 +195,7 @@
     PREFIX(opendir),
     PREFIX(closedir),
     PREFIX(readdir),
+    PREFIX(mkdir),
 
     /* kernel/ system */
     PREFIX(sleep),
@@ -205,6 +208,10 @@
     reset_poweroff_timer,
 #ifndef SIMULATOR
     system_memory_guard,
+    &cpu_frequency,
+#ifdef HAVE_ADJUSTABLE_CPU_FREQ
+    cpu_boost,
+#endif
 #endif
 
     /* strings and memory */
@@ -223,6 +230,7 @@
     strchr,
     strcat,
     memcmp,
+    strcasestr,
 
     /* sound */
     sound_set,
@@ -234,8 +242,15 @@
 #if CONFIG_HWCODEC != MASNONE
     bitswap,
 #endif
+#if CONFIG_HWCODEC == MASNONE
+    pcm_play_data,    
+    pcm_play_stop,
+    pcm_set_frequency,
+    pcm_is_playing,
+    pcm_play_pause,
 #endif
-    
+#endif
+
     /* playback control */
     PREFIX(audio_play),
     audio_stop,
@@ -270,6 +285,12 @@
 #endif
 #endif /* !simulator and HWCODEC != MASNONE */
 
+    /* tag database */
+    &tagdbheader,
+    &tagdb_fd,
+    &tagdb_initialized,
+    tagdb_init,
+
     /* misc */
     srand,
     rand,
@@ -299,35 +320,13 @@
     peak_meter_set_use_dbfs,
     peak_meter_get_use_dbfs,
 #endif
-
-    /* new stuff at the end, sort into place next time
-       the API gets incompatible */
-#ifndef SIMULATOR
-    &cpu_frequency,
-#ifdef HAVE_ADJUSTABLE_CPU_FREQ
-    cpu_boost,
-#endif
-#endif
-    PREFIX(mkdir),
-#if CONFIG_KEYPAD == IRIVER_H100_PAD
-    button_hold,
-#endif
-#if (CONFIG_HWCODEC == MASNONE) && !defined(SIMULATOR)
-    pcm_play_data,    
-    pcm_play_stop,
-    pcm_set_frequency,
-    pcm_is_playing,
-    pcm_set_volume,
-    pcm_play_pause,
-#endif
 #ifdef HAVE_LCD_BITMAP
     read_bmp_file,
 #endif
-    &tagdbheader,
-    &tagdb_fd,
-    &tagdb_initialized,
-    tagdb_init,
-    strcasestr,
+
+    /* new stuff at the end, sort into place next time
+       the API gets incompatible */
+
 };
 
 #if CONFIG_HWCODEC == MASNONE
diff --git a/apps/plugin.h b/apps/plugin.h
index b4c1189..3990ffe 100644
--- a/apps/plugin.h
+++ b/apps/plugin.h
@@ -78,12 +78,12 @@
 #endif
 
 /* increase this every time the api struct changes */
-#define PLUGIN_API_VERSION 39
+#define PLUGIN_API_VERSION 40
 
 /* update this to latest version if a change to the api struct breaks
    backwards compatibility (and please take the opportunity to sort in any 
    new function which are "waiting" at the end of the function table) */
-#define PLUGIN_MIN_API_VERSION 32
+#define PLUGIN_MIN_API_VERSION 40
 
 /* plugin return codes */
 enum plugin_status {
@@ -177,6 +177,7 @@
     void (*splash)(int ticks, bool center, const char *fmt, ...);
 
 #ifdef HAVE_REMOTE_LCD
+    /* remote lcd */
     void (*remote_clear_display)(void);
     void (*remote_puts)(int x, int y, const unsigned char *string);
     void (*remote_lcd_puts_scroll)(int x, int y, const unsigned char* string);
@@ -202,12 +203,10 @@
     int  (*remote_getstringsize)(const unsigned char *str, int *w, int *h);
     void (*remote_update)(void);
     void (*remote_update_rect)(int x, int y, int width, int height);
-//    void (*remote_scrollbar)(int x, int y, int width, int height, int items,
-//                      int min_shown, int max_shown, int orientation);
-    //void (*remote_checkbox)(int x, int y, int width, int height, bool checked);
+
     void (*remote_backlight_on)(void);
-    void (*remote_backlight_off)(void);    
-	 unsigned char* lcd_remote_framebuffer;
+    void (*remote_backlight_off)(void);
+    unsigned char* lcd_remote_framebuffer;
 #endif
 
     /* button */
@@ -215,6 +214,9 @@
     long (*button_get_w_tmo)(int ticks);
     int (*button_status)(void);
     void (*button_clear_queue)(void);
+#if CONFIG_KEYPAD == IRIVER_H100_PAD
+    bool (*button_hold)(void);
+#endif
 
     /* file */
     int (*PREFIX(open))(const char* pathname, int flags);
@@ -238,6 +240,7 @@
     DIR* (*PREFIX(opendir))(const char* name);
     int (*PREFIX(closedir))(DIR* dir);
     struct dirent* (*PREFIX(readdir))(DIR* dir);
+    int (*PREFIX(mkdir))(const char *name, int mode);
 
     /* kernel/ system */
     void (*PREFIX(sleep))(int ticks);
@@ -250,6 +253,10 @@
     void (*reset_poweroff_timer)(void);
 #ifndef SIMULATOR
     int (*system_memory_guard)(int newmode);
+    long *cpu_frequency;
+#ifdef HAVE_ADJUSTABLE_CPU_FREQ
+    void (*cpu_boost)(bool on_off);
+#endif
 #endif
 
     /* strings and memory */
@@ -268,6 +275,7 @@
     char *(*strchr)(const char *s, int c);
     char *(*strcat)(char *s1, const char *s2);
     int (*memcmp)(const void *s1, const void *s2, size_t n);
+    char *(*strcasestr) (const char* phaystack, const char* pneedle);
 
     /* sound */
     void (*sound_set)(int setting, int value);
@@ -279,7 +287,15 @@
 #if CONFIG_HWCODEC != MASNONE
     void (*bitswap)(unsigned char *data, int length);
 #endif
+#if CONFIG_HWCODEC == MASNONE
+    void (*pcm_play_data)(const unsigned char *start, int size,
+		    void (*get_more)(unsigned char** start, long*size));
+    void (*pcm_play_stop)(void);
+    void (*pcm_set_frequency)(unsigned int frequency);
+    bool (*pcm_is_playing)(void);
+    void (*pcm_play_pause)(bool play);
 #endif
+#endif /* !SIMULATOR */
 
     /* playback control */
     void (*PREFIX(audio_play))(int offset);
@@ -315,6 +331,12 @@
 #endif
 #endif
 
+    /* tag database */
+    struct tagdb_header *tagdbheader;
+    int *tagdb_fd;
+    int *tagdb_initialized;
+    int (*tagdb_init) (void);
+
     /* misc */
     void (*srand)(unsigned int seed);
     int  (*rand)(void);
@@ -351,37 +373,14 @@
     void (*peak_meter_set_use_dbfs)(int use);
     int (*peak_meter_get_use_dbfs)(void);
 #endif
-
-    /* new stuff at the end, sort into place next time
-       the API gets incompatible */
-#ifndef SIMULATOR
-    long *cpu_frequency;
-#ifdef HAVE_ADJUSTABLE_CPU_FREQ
-    void (*cpu_boost)(bool on_off);
-#endif
-#endif
-    int (*PREFIX(mkdir))(const char *name, int mode);
-#if CONFIG_KEYPAD == IRIVER_H100_PAD
-    bool (*button_hold)(void);
-#endif
-#if (CONFIG_HWCODEC == MASNONE) && !defined(SIMULATOR)
-    void (*pcm_play_data)(const unsigned char *start, int size,
-		    void (*get_more)(unsigned char** start, long*size));
-    void (*pcm_play_stop)(void);    
-    void (*pcm_set_frequency)(unsigned int frequency);
-    bool (*pcm_is_playing)(void);
-    void (*pcm_set_volume)(int volume);
-    void (*pcm_play_pause)(bool play);
-#endif
 #ifdef HAVE_LCD_BITMAP
     int (*read_bmp_file)(char* filename, int *get_width, int *get_height,
                          char *bitmap, int maxsize);
 #endif
-    struct tagdb_header *tagdbheader;
-    int *tagdb_fd;
-    int *tagdb_initialized;
-    int (*tagdb_init) (void);
-    char *(*strcasestr) (const char* phaystack, const char* pneedle);
+
+    /* new stuff at the end, sort into place next time
+       the API gets incompatible */     
+       
 };
 
 /* defined by the plugin loader (plugin.c) */
diff --git a/firmware/drivers/uda1380.c b/firmware/drivers/uda1380.c
index 7170b70..23d917f 100644
--- a/firmware/drivers/uda1380.c
+++ b/firmware/drivers/uda1380.c
@@ -85,33 +85,15 @@
 }
 
 /**
- * Sets the master volume
- *
- * \param vol Range [0..255] 0=max, 255=mute
- *
+ * Sets left and right master volume  (0(max) to 252(muted))
  */
-int uda1380_setvol(int vol)
+int uda1380_setvol(int vol_l, int vol_r)
 {
-    int vol_l, vol_r;
-
-    uda1380_volume = vol;
-    /* Simple linear volume crossfade curves */
-    vol_l = MAX(uda1380_balance*(255 - vol)/100 + vol, vol);
-    vol_r = MAX(-uda1380_balance*(255 - vol)/100 + vol, vol);
     return uda1380_write_reg(REG_MASTER_VOL,
                              MASTER_VOL_LEFT(vol_l) | MASTER_VOL_RIGHT(vol_r));
 }
 
 /**
- * Sets stereo balance
- */
-void uda1380_set_balance(int bal)
-{
-    uda1380_balance = bal;
-    uda1380_setvol(uda1380_volume);
-}
-
-/** 
  * Sets the bass value (0-15)
  */
 void uda1380_set_bass(int value)
diff --git a/firmware/export/pcm_playback.h b/firmware/export/pcm_playback.h
index c78936a..874ed6a 100644
--- a/firmware/export/pcm_playback.h
+++ b/firmware/export/pcm_playback.h
@@ -31,7 +31,6 @@
 void pcm_play_stop(void);
 void pcm_play_pause(bool play);
 bool pcm_is_playing(void);
-void pcm_set_volume(int volume);
 
 /* These functions are for playing chained buffers of PCM data */
 void pcm_play_init(void);
diff --git a/firmware/export/uda1380.h b/firmware/export/uda1380.h
index b09d271..503b59d 100644
--- a/firmware/export/uda1380.h
+++ b/firmware/export/uda1380.h
@@ -22,8 +22,7 @@
 
 extern int uda1380_init(void);
 extern void uda1380_enable_output(bool enable);
-extern int uda1380_setvol(int vol);
-extern void uda1380_set_balance(int bal);
+extern int uda1380_setvol(int vol_l, int vol_r);
 extern void uda1380_set_bass(int value);
 extern void uda1380_set_treble(int value);
 extern int uda1380_mute(int mute);
diff --git a/firmware/pcm_playback.c b/firmware/pcm_playback.c
index 45e91ac..eab6fe1 100644
--- a/firmware/pcm_playback.c
+++ b/firmware/pcm_playback.c
@@ -123,20 +123,6 @@
     IIS2CONFIG = 0x800;
 }
 
-/* set volume of the main channel */
-void pcm_set_volume(int volume)
-{
-   if(volume > 0)
-   {
-       uda1380_mute(0);
-       uda1380_setvol(0xff - volume); 
-   }
-   else
-   {
-       uda1380_mute(1);
-   } 
-}
-
 /* sets frequency of input to DAC */
 void pcm_set_frequency(unsigned int frequency)
 {
diff --git a/firmware/sound.c b/firmware/sound.c
index 7dd1fbf..cd6448c 100644
--- a/firmware/sound.c
+++ b/firmware/sound.c
@@ -334,7 +334,7 @@
         return (db + 660) / 15;
 }
 
-void set_prescaled_volume(void)
+static void set_prescaled_volume(void)
 {
     int prescale;
     int l, r;
@@ -367,7 +367,47 @@
 
     dac_volume(tenthdb2reg(l), tenthdb2reg(r), false);
 }
-#endif /* MAS3507D */
+#elif CONFIG_HWCODEC == MASNONE
+#ifdef HAVE_UDA1380  /* iriver H1x0 + H3x0 */
+/* all values in tenth of dB */
+int current_volume = 0;   /* -840..0 */
+int current_balance = 0;  /* -840..+840 */
+
+/* convert tenth of dB volume to register value */
+static int tenthdb2reg(int db) {
+    if (db < -720)                  /* 1.5 dB steps */
+        return (2940 - db) / 15;
+    else if (db < -660)             /* 0.75 dB steps */
+        return (1110 - db) * 2 / 15;
+    else if (db < -520)             /* 0.5 dB steps */
+        return (520 - db) / 5;
+    else                            /* 0.25 dB steps */
+        return -db * 2 / 5;
+}
+
+static void set_volume(void)
+{
+    int l, r;
+
+    l = r = current_volume;
+
+    if (current_balance > 0)
+    {
+        l -= current_balance;
+        if (l < -840)
+            l = -840;
+    }
+    if (current_balance < 0)
+    {
+        r += current_balance;
+        if (r < -840)
+            r = -840;
+    }
+
+    uda1380_setvol(tenthdb2reg(l), tenthdb2reg(r));
+}
+#endif
+#endif /* MASNONE */
 #endif /* !SIMULATOR */
 
 int channel_configuration = SOUND_CHAN_STEREO;
@@ -480,7 +520,8 @@
             current_volume = -780 + (value * 960 / 100); /* tenth of dB */
             set_prescaled_volume();
 #elif CONFIG_HWCODEC == MASNONE
-	    pcm_set_volume((value*167117) >> 16);
+            current_volume = -840 + (value * 840 / 100); /* tenth of dB */
+            set_volume();
 #endif
             break;
 
@@ -492,7 +533,8 @@
             current_balance = value * 960 / 100; /* tenth of dB */
             set_prescaled_volume();
 #elif defined(HAVE_UDA1380)
-            uda1380_set_balance(value);
+            current_balance = value * 840 / 100; /* tenth of dB */
+            set_volume();
 #endif
             break;
 
@@ -500,12 +542,12 @@
 #if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F)
             tmp = ((value * 8) & 0xff) << 8;
             mas_codec_writereg(0x14, tmp & 0xff00);
-#elif defined(HAVE_UDA1380)
-            uda1380_set_bass(value >> 1);
 #elif CONFIG_HWCODEC == MAS3507D
             mas_writereg(MAS_REG_KBASS, bass_table[value+15]);
             current_bass = value * 10;
             set_prescaled_volume();
+#elif defined(HAVE_UDA1380)
+            uda1380_set_bass(value >> 1);
 #endif
             break;
 
@@ -513,12 +555,12 @@
 #if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F)
             tmp = ((value * 8) & 0xff) << 8;
             mas_codec_writereg(0x15, tmp & 0xff00);
-#elif defined(HAVE_UDA1380)
-            uda1380_set_treble(value >> 1);
 #elif CONFIG_HWCODEC == MAS3507D
             mas_writereg(MAS_REG_KTREBLE, treble_table[value+15]);
             current_treble = value * 10;
             set_prescaled_volume();
+#elif defined(HAVE_UDA1380)
+            uda1380_set_treble(value >> 1);
 #endif
             break;