General: changed local adc to voltage conversions in several places to use battery_voltage. Added battery_read_info function for unfiltered battery information. x5: removed adc_read as a distinct function. Removed adc tick task. adc_init is empty inline. Adjusted battery scale, voltage to level array and read 10 bits from the ADC for battery since 255 levels is not enough for true centivolt resolution.


git-svn-id: svn://svn.rockbox.org/rockbox/trunk@11396 a1c6a512-1295-4272-9138-f99709370657
diff --git a/apps/debug_menu.c b/apps/debug_menu.c
index 9d721d0..47a2042 100644
--- a/apps/debug_menu.c
+++ b/apps/debug_menu.c
@@ -318,7 +318,7 @@
                 break;
             case ACTION_STD_CANCEL:
                 done = true;
-                break;      
+                break;
         }
         action_signalscreenchange();
         line = 0;
@@ -968,8 +968,7 @@
     unsigned short portb;
     unsigned char portc;
     char buf[32];
-    int battery_voltage;
-    int batt_int, batt_frac;
+    int adc_battery_voltage, adc_battery_level;
 
     lcd_setfont(FONT_SYSFIXED);
     lcd_setmargins(0, 0);
@@ -995,12 +994,10 @@
         snprintf(buf, 32, "AN3: %03x AN7: %03x", adc_read(3), adc_read(7));
         lcd_puts(0, 5, buf);
 
-        battery_voltage = (adc_read(ADC_UNREG_POWER) * BATTERY_SCALE_FACTOR) / 10000;
-        batt_int = battery_voltage / 100;
-        batt_frac = battery_voltage % 100;
-
-        snprintf(buf, 32, "Batt: %d.%02dV %d%%  ", batt_int, batt_frac,
-                 battery_level());
+        battery_read_info(NULL, &adc_battery_voltage,
+                          &adc_battery_level);
+        snprintf(buf, 32, "Batt: %d.%02dV %d%%  ", adc_battery_voltage / 100,
+                 adc_battery_voltage % 100, adc_battery_level);
         lcd_puts(0, 6, buf);
 #ifndef HAVE_MMC /* have ATA */
         snprintf(buf, 32, "ATA: %s, 0x%x",
@@ -1020,14 +1017,10 @@
     unsigned int gpio1_function;
     unsigned int gpio_enable;
     unsigned int gpio1_enable;
-    int adc_buttons, adc_remote, adc_battery;
-#if defined(IRIVER_H100_SERIES) || defined(IRIVER_H300_SERIES)
-    int adc_remotedetect;
-#endif
+    int adc_buttons, adc_remote;
+    int adc_battery, adc_battery_voltage, adc_battery_level;
     char buf[128];
     int line;
-    int battery_voltage;
-    int batt_int, batt_frac;
 
     lcd_setmargins(0, 0);
     lcd_clear_display();
@@ -1064,12 +1057,9 @@
         lcd_puts(0, line++, buf);
 
         adc_buttons = adc_read(ADC_BUTTONS);
-        adc_remote = adc_read(ADC_REMOTE);
-        adc_battery = adc_read(ADC_BATTERY);
-#if defined(IRIVER_H100_SERIES) || defined(IRIVER_H300_SERIES)
-        adc_remotedetect = adc_read(ADC_REMOTEDETECT);
-#endif
-
+        adc_remote  = adc_read(ADC_REMOTE);
+        battery_read_info(&adc_battery, &adc_battery_voltage,
+                          &adc_battery_level);
 #if defined(IAUDIO_X5) || defined(IRIVER_H300_SERIES)
         snprintf(buf, sizeof(buf), "ADC_BUTTONS (%c): %02x",
             button_scan_enabled() ? '+' : '-', adc_buttons);
@@ -1083,20 +1073,18 @@
 #else
         snprintf(buf, sizeof(buf), "ADC_REMOTE:  %02x", adc_remote);
 #endif
+
         lcd_puts(0, line++, buf);
         snprintf(buf, sizeof(buf), "ADC_BATTERY: %02x", adc_battery);
         lcd_puts(0, line++, buf);
 #if defined(IRIVER_H100_SERIES) || defined(IRIVER_H300_SERIES)
-        snprintf(buf, sizeof(buf), "ADC_REMOTEDETECT: %02x", adc_remotedetect);
+        snprintf(buf, sizeof(buf), "ADC_REMOTEDETECT: %02x",
+                 adc_read(ADC_REMOTEDETECT));
         lcd_puts(0, line++, buf);
 #endif
 
-        battery_voltage = (adc_battery * BATTERY_SCALE_FACTOR) / 10000;
-        batt_int = battery_voltage / 100;
-        batt_frac = battery_voltage % 100;
-
-        snprintf(buf, 32, "Batt: %d.%02dV %d%%  ", batt_int, batt_frac,
-                 battery_level());
+        snprintf(buf, 32, "Batt: %d.%02dV %d%%  ", adc_battery_voltage / 100,
+                 adc_battery_voltage % 100, adc_battery_level);
         lcd_puts(0, line++, buf);
 
 #if defined(IRIVER_H100_SERIES) || defined(IRIVER_H300_SERIES)
@@ -1209,8 +1197,7 @@
     unsigned char portc;
     char buf[32];
     int button;
-    int battery_voltage;
-    int batt_int, batt_frac;
+    int adc_battery_voltage;
     int currval = 0;
 
     lcd_clear_display();
@@ -1260,12 +1247,9 @@
         }
         lcd_puts(0, 0, buf);
 
-        battery_voltage = (adc_read(ADC_UNREG_POWER) *
-                           BATTERY_SCALE_FACTOR) / 10000;
-        batt_int = battery_voltage / 100;
-        batt_frac = battery_voltage % 100;
-
-        snprintf(buf, 32, "Batt: %d.%02dV", batt_int, batt_frac);
+        battery_read_info(NULL, &adc_battery_voltage, NULL);
+        snprintf(buf, 32, "Batt: %d.%02dV", adc_battery_voltage / 100,
+                 adc_battery_voltage % 100);
         lcd_puts(0, 1, buf);
 
         button = get_action(CONTEXT_SETTINGS,HZ/5);
@@ -1418,7 +1402,7 @@
                 lcd_clear_display();
                 lcd_puts(0, 0, "Power status:");
 
-                y = (adc_read(ADC_UNREG_POWER) * BATTERY_SCALE_FACTOR) / 10000;
+                battery_read_info(NULL, &y, NULL);
                 snprintf(buf, 30, "Battery: %d.%02d V", y / 100, y % 100);
                 lcd_puts(0, 1, buf);
 #ifdef ADC_EXT_POWER
diff --git a/apps/screens.c b/apps/screens.c
index 9787e68..b81932b 100644
--- a/apps/screens.c
+++ b/apps/screens.c
@@ -98,8 +98,8 @@
 
 #ifdef HAVE_REMOTE_LCD
     lcd_remote_clear_display();
-    lcd_remote_bitmap(remote_usblogo, 
-                      (LCD_REMOTE_WIDTH-BMPWIDTH_remote_usblogo)/2, 
+    lcd_remote_bitmap(remote_usblogo,
+                      (LCD_REMOTE_WIDTH-BMPWIDTH_remote_usblogo)/2,
                       (LCD_REMOTE_HEIGHT-BMPHEIGHT_remote_usblogo)/2,
                       BMPWIDTH_remote_usblogo, BMPHEIGHT_remote_usblogo);
     lcd_remote_update();
@@ -107,7 +107,7 @@
 
     lcd_clear_display();
 #ifdef HAVE_LCD_BITMAP
-    lcd_bitmap(usblogo, (LCD_WIDTH-BMPWIDTH_usblogo)/2, 
+    lcd_bitmap(usblogo, (LCD_WIDTH-BMPWIDTH_usblogo)/2,
                         (LCD_HEIGHT-BMPHEIGHT_usblogo)/2,
                         BMPWIDTH_usblogo, BMPHEIGHT_usblogo);
     lcd_update();
@@ -167,17 +167,6 @@
 }
 #endif
 
-
-/* some simulator dummies */
-#ifdef SIMULATOR
-#define BATTERY_SCALE_FACTOR 7000
-unsigned short adc_read(int channel)
-{
-   (void)channel;
-   return 100;
-}
-#endif
-
 #if defined(CONFIG_CHARGING) && !defined(HAVE_POWEROFF_WHILE_CHARGING)
 
 #ifdef HAVE_LCD_BITMAP
@@ -195,15 +184,9 @@
     if (ide_powered()) /* FM and V2 can only measure when ATA power is on */
 #endif
     {
-        int battery_voltage;
-        int batt_int, batt_frac;
-
-        battery_voltage = (adc_read(ADC_UNREG_POWER) * BATTERY_SCALE_FACTOR) / 10000;
-        batt_int = battery_voltage / 100;
-        batt_frac = battery_voltage % 100;
-
-        snprintf(buf, 32, "  Batt: %d.%02dV %d%%  ", batt_int, batt_frac,
-                 battery_level());
+        int battv = battery_voltage();
+        snprintf(buf, 32, "  Batt: %d.%02dV %d%%  ", battv / 100,
+                 battv % 100, battery_level());
         lcd_puts(0, 7, buf);
     }
 
@@ -294,15 +277,14 @@
 
 void charging_display_info(bool animate)
 {
-    int battery_voltage;
+    int battv;
     unsigned i, ypos;
     static unsigned phase = 3;
     char buf[28];
 
-    battery_voltage = (adc_read(ADC_UNREG_POWER) * BATTERY_SCALE_FACTOR)
-                      / 10000;
+    battv = battery_voltage();
     snprintf(buf, sizeof(buf), "%s %d.%02dV", logo_chars,
-             battery_voltage / 100, battery_voltage % 100);
+             battv / 100, battv % 100);
     lcd_puts(0, 1, buf);
 
     memcpy(buf, logo_pattern, 28); /* copy logo patterns */
@@ -337,7 +319,7 @@
    2 if Off/Stop key was pressed
    3 if On key was pressed
    4 if USB was connected */
-   
+
 int charging_screen(void)
 {
     unsigned int button;
@@ -391,7 +373,7 @@
     int w, h;
 
     display->clear_display();
-    
+
     if (display->nb_lines < 4) /* very small screen, just show the pitch value */
     {
         w = snprintf((char *)buf, sizeof(buf), "%s: %d.%d%%",str(LANG_SYSFONT_PITCH),
@@ -415,21 +397,21 @@
         display->putsxy((display->width-w)/2, display->height - h, ptr);
         display->mono_bitmap(bitmap_icons_7x8[Icon_DownArrow],
                              display->width/2 - 3, display->height - h*2, 7, 8);
-    
+
         /* RIGHT: +2% */
         ptr = "+2%";
         display->getstringsize(ptr,&w,&h);
         display->putsxy(display->width-w, (display->height-h)/2, ptr);
         display->mono_bitmap(bitmap_icons_7x8[Icon_FastForward],
                              display->width-w-8, (display->height-h)/2, 7, 8);
-    
+
         /* LEFT: -2% */
         ptr = "-2%";
         display->getstringsize(ptr,&w,&h);
         display->putsxy(0, (display->height-h)/2, ptr);
         display->mono_bitmap(bitmap_icons_7x8[Icon_FastBackward],
                              w+1, (display->height-h)/2, 7, 8);
-    
+
         /* "Pitch" */
         snprintf((char *)buf, sizeof(buf), str(LANG_SYSFONT_PITCH));
         display->getstringsize(buf,&w,&h);
@@ -1027,7 +1009,7 @@
                 break;
 
             /* do nothing here, because ACTION_UNKNOWN might be caused
-             * by timeout or button release. In case of timeout the loop 
+             * by timeout or button release. In case of timeout the loop
              * is terminated by TIME_BEFORE */
             case ACTION_UNKNOWN:
                 break;
@@ -1164,8 +1146,8 @@
     while (true) {
         gui_syncstatusbar_draw(&statusbars, false);
         key = get_action(CONTEXT_LIST,HZ/2);
-        if(key!=ACTION_NONE && key!=ACTION_UNKNOWN 
-	    && !gui_synclist_do_button(&id3_lists, key))
+        if(key!=ACTION_NONE && key!=ACTION_UNKNOWN
+        && !gui_synclist_do_button(&id3_lists, key))
         {
             action_signalscreenchange();
             return(default_event_handler(key) == SYS_USB_CONNECTED);
diff --git a/bootloader/main.c b/bootloader/main.c
index 7786657..99eb449 100644
--- a/bootloader/main.c
+++ b/bootloader/main.c
@@ -99,7 +99,7 @@
     unsigned long sum;
     int i;
     unsigned char *buf = (unsigned char *)DRAM_START;
-    
+
     fd = open("/.rockbox/" BOOTFILE, O_RDONLY);
     if(fd < 0)
     {
@@ -114,7 +114,7 @@
     lcd_update();
 
     lseek(fd, FIRMWARE_OFFSET_FILE_CRC, SEEK_SET);
-    
+
     rc = read(fd, &chksum, 4);
     if(rc < 4)
         return -2;
@@ -127,7 +127,7 @@
         return -3;
 
     model[4] = 0;
-    
+
     printf("Model name: %s", model);
     lcd_update();
 
@@ -140,7 +140,7 @@
     close(fd);
 
     sum = MODEL_NUMBER;
-    
+
     for(i = 0;i < len;i++) {
         sum += buf[i];
     }
@@ -159,7 +159,7 @@
     struct flash_header hdr;
     unsigned char *buf = (unsigned char *)DRAM_START;
     uint8_t *src = (uint8_t *)FLASH_ENTRYPOINT;
-    
+
     cpu_boost(true);
     memcpy(&hdr, src, sizeof(struct flash_header));
     src += sizeof(struct flash_header);
@@ -221,7 +221,7 @@
     battery_voltage = (adc_battery * BATTERY_SCALE_FACTOR) / 10000;
     batt_int = battery_voltage / 100;
     batt_frac = battery_voltage % 100;
-    
+
     printf("Batt: %d.%02dV", batt_int, batt_frac);
     lcd_update();
 
@@ -248,12 +248,12 @@
     i = load_firmware();
     printf("Result: %d", i);
     lcd_update();
-    
+
     if(i == 0)
         start_firmware();
 
     power_off();
-    
+
 #else
     /* We want to read the buttons as early as possible, before the user
        releases the ON button */
@@ -266,19 +266,19 @@
     data = GPIO1_READ;
     if ((data & 0x20) == 0)
         on_button = true;
-    
+
     if ((data & 0x40) == 0)
         rc_on_button = true;
 
     /* Set the default state of the hard drive power to OFF */
     ide_power_enable(false);
-    
+
     power_init();
 
     /* Turn off if neither ON button is pressed */
     if(!(on_button || rc_on_button || usb_detect()))
         power_off();
-    
+
     /* Backlight ON */
     or_l(0x00020000, &GPIO1_ENABLE);
     or_l(0x00020000, &GPIO1_FUNCTION);
@@ -304,7 +304,7 @@
         ide_power_enable(true);
     }
 #endif
-    
+
     system_init();
     kernel_init();
 
@@ -316,7 +316,7 @@
 #ifdef HAVE_UDA1380
     uda1380_reset();
 #endif
-    
+
     backlight_init();
     set_irq_level(0);
     lcd_init();
@@ -331,9 +331,9 @@
     lcd_update();
 
     sleep(HZ/50); /* Allow the button driver to check the buttons */
-    rec_button = ((button_status() & BUTTON_REC) == BUTTON_REC) 
+    rec_button = ((button_status() & BUTTON_REC) == BUTTON_REC)
         || ((button_status() & BUTTON_RC_REC) == BUTTON_RC_REC);
-    
+
     /* Don't start if the Hold button is active on the device you
        are starting with */
     if (!usb_detect() && ((on_button && button_hold()) ||
@@ -363,7 +363,7 @@
     if (detect_flashed_rockbox())
     {
         bool load_from_flash;
-        
+
         load_from_flash = !rec_button;
 #ifdef HAVE_EEPROM_SETTINGS
         if (eeprom_settings_init())
@@ -372,7 +372,7 @@
              * not be intact. */
             if (firmware_settings.bl_version)
                 firmware_settings.disk_clean = false;
-            
+
             firmware_settings.bl_version = 7;
             /* Invert the record button if we want to load from disk
              * by default. */
@@ -380,7 +380,7 @@
                 load_from_flash = rec_button;
         }
 #endif
-        
+
         if (load_from_flash)
         {
             /* Load firmware from flash */
@@ -400,7 +400,7 @@
                 power_off();
             }
         }
-        
+
         printf("Loading from disk...");
         lcd_update();
     }
@@ -416,13 +416,13 @@
     }
 
     usb_init();
-    
+
     adc_battery = adc_read(ADC_BATTERY);
 
     battery_voltage = (adc_battery * BATTERY_SCALE_FACTOR) / 10000;
     batt_int = battery_voltage / 100;
     batt_frac = battery_voltage % 100;
-    
+
     printf("Batt: %d.%02dV", batt_int, batt_frac);
     lcd_update();
 
@@ -431,7 +431,7 @@
         lcd_update();
         sleep(HZ*2);
     }
-    
+
     rc = ata_init();
     if(rc)
     {
@@ -456,7 +456,7 @@
 #ifdef IRIVER_H300_SERIES
         sleep(HZ);
 #endif
-    
+
 #ifdef HAVE_EEPROM_SETTINGS
         if (firmware_settings.initialized)
         {
@@ -472,7 +472,7 @@
         {
             ata_spin(); /* Prevent the drive from spinning down */
             sleep(HZ);
-            
+
             /* Backlight OFF */
             or_l(0x00020000, &GPIO1_OUT);
         }
@@ -480,12 +480,12 @@
         cpu_idle_mode(false);
         usb_enable(false);
         ata_init(); /* Reinitialize ATA and continue booting */
-        
+
         lcd_clear_display();
         line = 0;
         lcd_update();
     }
-    
+
     disk_init();
 
     rc = disk_mount_all();
@@ -507,10 +507,10 @@
     if (firmware_settings.initialized)
         eeprom_settings_store();
 #endif
-    
+
     if (i == 0)
         start_firmware();
-    
+
     if (detect_flashed_rockbox())
     {
         printf("No firmware found on disk");
diff --git a/firmware/export/config-iaudiox5.h b/firmware/export/config-iaudiox5.h
index df24850..3e83560 100644
--- a/firmware/export/config-iaudiox5.h
+++ b/firmware/export/config-iaudiox5.h
@@ -113,12 +113,13 @@
 #define CPU_FREQ      11289600
 
 /* Type of mobile power */
-#define CONFIG_BATTERY BATT_LIPOL1300
-#define BATTERY_CAPACITY_MIN 950   /* min. capacity selectable */
-#define BATTERY_CAPACITY_MAX 2250  /* max. capacity selectable */
-#define BATTERY_CAPACITY_INC 50    /* capacity increment */
-#define BATTERY_TYPES_COUNT  1     /* only one type */
-#define BATTERY_SCALE_FACTOR 23437 /* FIX: this value is picked at random */
+#define X5_BATT_CONFIG          2
+#define CONFIG_BATTERY          BATT_IAUDIO_X5
+#define BATTERY_CAPACITY_MIN    950   /* min. capacity selectable */
+#define BATTERY_CAPACITY_MAX    2250  /* max. capacity selectable */
+#define BATTERY_CAPACITY_INC    50    /* capacity increment */
+#define BATTERY_TYPES_COUNT     1     /* only one type */
+#define BATTERY_SCALE_FACTOR    5859  /* (420703125 + 35900) / 71800 */
 
 /* define this if you have a real-time clock */
 #define CONFIG_RTC RTC_PCF50606
diff --git a/firmware/export/config.h b/firmware/export/config.h
index 6f6d253..765bcfd 100644
--- a/firmware/export/config.h
+++ b/firmware/export/config.h
@@ -70,6 +70,7 @@
 #define BATT_LIION2200  2200 /* FM/V2 recorder type */
 #define BATT_4AA_NIMH   1500
 #define BATT_3AAA       1000 /* Ondio */
+#define BATT_IAUDIO_X5   950
 #define BATT_LIPOL1300  1300 /* the type used in iRiver h1x0 models */
 #define BATT_LPCS355385 1550 /* iriver h10 20Gb - SKC LPCS355385 */
 #define BATT_BP009       820 /* iriver H10 5/6Gb - iriver BP009 */
diff --git a/firmware/export/powermgmt.h b/firmware/export/powermgmt.h
index 30fe60c..ba2cc02 100644
--- a/firmware/export/powermgmt.h
+++ b/firmware/export/powermgmt.h
@@ -63,7 +63,7 @@
 
 #if CONFIG_CHARGING >= CHARGING_MONITOR
 typedef enum {       /* sorted by increasing charging current */
-    DISCHARGING = 0, 
+    DISCHARGING = 0,
     TRICKLE,         /* Can occur for CONFIG_CHARGING >= CHARGING_MONITOR */
     TOPOFF,          /* Can occur for CONFIG_CHARGING == CHARGING_CONTROL */
     CHARGING         /* Can occur for all CONFIG_CHARGING options */
@@ -126,6 +126,9 @@
 
 unsigned int battery_voltage(void); /* filtered batt. voltage in centivolts */
 
+/* read unfiltered battery info */
+void battery_read_info(int *adc, int *voltage, int *level);
+
 /* Tells if the battery level is safe for disk writes */
 bool battery_level_safe(void);
 
diff --git a/firmware/powermgmt.c b/firmware/powermgmt.c
index 50b734b..f18ea3c 100644
--- a/firmware/powermgmt.c
+++ b/firmware/powermgmt.c
@@ -112,6 +112,20 @@
     }
 }
 
+void battery_read_info(int *adc, int *voltage, int *level)
+{
+    battery_status_update();
+
+    if (adc)
+        *adc = batt_centivolts*10000 / BATTERY_SCALE_FACTOR;
+
+    if (voltage)
+        *voltage = batt_centivolts;
+
+    if (level)
+        *level = batt_level;
+}
+
 unsigned int battery_voltage(void)
 {
     battery_status_update();
@@ -167,6 +181,8 @@
     105, 115    /* alkaline, NiHM */
 #elif CONFIG_BATTERY == BATT_LIPOL1300 /* iRiver H1x0 */
     339
+#elif CONFIG_BATTERY == BATT_IAUDIO_X5
+    354
 #elif CONFIG_BATTERY == BATT_LPCS355385 /* iriver H10 20GB */
     376
 #elif CONFIG_BATTERY == BATT_BP009 /* iriver H10 5/6GB */
@@ -192,6 +208,13 @@
      * for the 1300 mAh stock battery. */
 //  { 337, 358, 365, 369, 372, 377, 383, 389, 397, 406, 413 }
     { 337, 366, 372, 374, 378, 381, 385, 392, 399, 408, 417 }
+#elif CONFIG_BATTERY == BATT_IAUDIO_X5
+    /* iAudio x5 series  - still experimenting with best curve */
+// Lithium ion discharge curve
+    { 355, 356, 357, 359, 362, 365, 369, 374, 380, 387, 395 }
+// Linear
+//  { 355, 360, 364, 369, 373, 378, 382, 387, 391, 390, 400 }
+//  { 355, 359, 363, 367, 371, 375, 379, 383, 387, 391, 395 }
 #elif CONFIG_BATTERY == BATT_LPCS355385
     /* iriver H10 20GB */
     { 376, 380, 385, 387, 390, 395, 402, 407, 411, 418, 424 }
@@ -289,9 +312,25 @@
 
 static long last_event_tick;
 
+static int voltage_to_battery_level(int battery_centivolts);
 static void battery_status_update(void);
 static int runcurrent(void);
 
+void battery_read_info(int *adc, int *voltage, int *level)
+{
+    int adc_battery = adc_read(ADC_UNREG_POWER);
+    int centivolts  = adc_battery*BATTERY_SCALE_FACTOR / 10000;
+
+    if (adc)
+        *adc = adc_battery;
+
+    if (voltage)
+        *voltage = centivolts;
+
+    if (level)
+        *level = voltage_to_battery_level(centivolts);
+}
+
 unsigned int battery_voltage(void)
 {
     return battery_centivolts;
@@ -387,14 +426,14 @@
 
 /* update battery level and estimated runtime, called once per minute or
  * when battery capacity / type settings are changed */
-static void battery_status_update(void)
+static int voltage_to_battery_level(int battery_centivolts)
 {
     int level;
 
 #if CONFIG_CHARGING >= CHARGING_MONITOR
     if (charge_state == DISCHARGING) {
         level = voltage_to_percent(battery_centivolts,
-                percent_to_volt_discharge[battery_type]);
+                    percent_to_volt_discharge[battery_type]);
     }
     else if (charge_state == CHARGING) {
         /* battery level is defined to be < 100% until charging is finished */
@@ -407,9 +446,16 @@
 #else
     /* always use the discharge table */
     level = voltage_to_percent(battery_centivolts,
-            percent_to_volt_discharge[battery_type]);
+                percent_to_volt_discharge[battery_type]);
 #endif
 
+    return level;
+}
+
+static void battery_status_update(void)
+{
+    int level = voltage_to_battery_level(battery_centivolts);
+
 #ifndef HAVE_MMC  /* this adjustment is only needed for HD based */
     if (battery_percent == -1) { /* first run of this procedure */
         /* The battery voltage is usually a little lower directly after
@@ -699,7 +745,6 @@
 #endif
 
     /* initialize the voltages for the exponential filter */
-
     avgbat = adc_read(ADC_UNREG_POWER) * BATTERY_SCALE_FACTOR *
         BATT_AVE_SAMPLES;
     battery_centivolts = avgbat / BATT_AVE_SAMPLES / 10000;
@@ -1010,7 +1055,6 @@
 {
     /* init history to 0 */
     memset(power_history, 0x00, sizeof(power_history));
-
     create_thread(power_thread, power_stack, sizeof(power_stack),
                   power_thread_name IF_PRIO(, PRIORITY_SYSTEM));
 }
diff --git a/firmware/target/coldfire/iaudio/x5/adc-target.h b/firmware/target/coldfire/iaudio/x5/adc-target.h
index 4081562..28ba622 100644
--- a/firmware/target/coldfire/iaudio/x5/adc-target.h
+++ b/firmware/target/coldfire/iaudio/x5/adc-target.h
@@ -28,5 +28,8 @@
 
 /* Force a scan now */
 unsigned short adc_scan(int channel);
-
+static inline unsigned short adc_read(int channel)
+    { return adc_scan(channel); }
+static inline void adc_init(void)
+    {}
 #endif /* _ADC_TARGET_H_ */
diff --git a/firmware/target/coldfire/iaudio/x5/adc-x5.c b/firmware/target/coldfire/iaudio/x5/adc-x5.c
index 72aec7d..1895cac 100755
--- a/firmware/target/coldfire/iaudio/x5/adc-x5.c
+++ b/firmware/target/coldfire/iaudio/x5/adc-x5.c
@@ -24,49 +24,35 @@
 #include "adc.h"
 #include "pcf50606.h"
 
-static unsigned short adcdata[NUM_ADC_CHANNELS];
-
-static const int adcc2_parms[] =
+/* get remaining 2 bits and return 10 bit value */
+static int get_10bit_voltage(int msbdata)
 {
-    [ADC_BUTTONS] = 0x80 | (5 << 1) | 1, /* ADCIN2 */
-    [ADC_REMOTE]  = 0x80 | (6 << 1) | 1, /* ADCIN3 */
-    [ADC_BATTERY] = 0x80 | (0 << 1) | 1, /* BATVOLT, resistive divider */
-};
+    int data = msbdata << 2;
+    data |= pcf50606_read(0x31) & 0x3;
+    return data;
+}
 
 unsigned short adc_scan(int channel)
 {
+    static const int adcc2_parms[] =
+    {
+        [ADC_BUTTONS] = 0x81 | (5 << 1), /* 8b  - ADCIN2 */
+        [ADC_REMOTE]  = 0x81 | (6 << 1), /* 8b  - ADCIN3 */
+        [ADC_BATTERY] = 0x01 | (0 << 1), /* 10b - BATVOLT, resistive divider */
+    };
+
     int level;
-    unsigned char data;
+    int data;
 
     level = set_irq_level(HIGHEST_IRQ_LEVEL);
 
     pcf50606_write(0x2f, adcc2_parms[channel]);
     data = pcf50606_read(0x30);
 
-    adcdata[channel] = data;
+    if (channel == ADC_BATTERY)
+        data = get_10bit_voltage(data);
 
     set_irq_level(level);
-    return data;
-}
 
-unsigned short adc_read(int channel)
-{
-    return adcdata[channel];
-}
-
-static int adc_counter;
-
-static void adc_tick(void)
-{
-    if (++adc_counter == HZ)
-    {
-        adc_counter = 0;
-        adc_scan(ADC_BATTERY);
-    }
-}
-
-void adc_init(void)
-{
-    adc_scan(ADC_BATTERY);
-    tick_add_task(adc_tick);
+    return (unsigned short)data;
 }
diff --git a/firmware/target/coldfire/iaudio/x5/pcf50606-x5.c b/firmware/target/coldfire/iaudio/x5/pcf50606-x5.c
index 3443d1e..5914066 100644
--- a/firmware/target/coldfire/iaudio/x5/pcf50606-x5.c
+++ b/firmware/target/coldfire/iaudio/x5/pcf50606-x5.c
@@ -128,8 +128,8 @@
     if (data[2] & 0x06)
     {
         /* ACDINS/ACDREM */
-        /* Check if adc_scan should actually scan main buttons or not -
-           bias towards "yes" out of paranoia. */
+        /* Check if main buttons should be actually be scanned or not
+           - bias towards "yes" out of paranoia. */
         button_enable_scan((data[2] & 0x02) != 0 ||
                            (pcf50606_read(0x33) & 0x01) != 0);
     }
diff --git a/flash/bootbox/main.c b/flash/bootbox/main.c
index 4f5efdd..af822b4 100644
--- a/flash/bootbox/main.c
+++ b/flash/bootbox/main.c
@@ -99,21 +99,16 @@
         lcd_puts(0, 0, msg);
         {
             char buf[32];
-            int battery_voltage;
-            int batt_int, batt_frac;
-            battery_voltage = (adc_read(ADC_UNREG_POWER) * BATTERY_SCALE_FACTOR) / 10000;
-            batt_int = battery_voltage / 100;
-            batt_frac = battery_voltage % 100;
-
+            int battv = battery_voltage();
             snprintf(buf, sizeof(buf), "%d.%02dV %d%%",
-                batt_int, batt_frac, battery_level());
+                battv / 100, battv % 100, battery_level());
             lcd_puts(0, 1, buf);
         }
 
 #ifdef HAVE_LCD_BITMAP
         lcd_update();
 #endif
-        
+
         button = button_get_w_tmo(HZ/2);
 #ifdef BUTTON_ON
         if (button == (BUTTON_ON | BUTTON_REL))
@@ -144,7 +139,7 @@
     lcd_puts(0, 3, "and fix it.");
     lcd_update();
 #endif
-    do 
+    do
     {
         button = button_get(true);
         if (button == SYS_POWEROFF)
@@ -215,7 +210,7 @@
     }
 
     {   // rolo the firmware
-        static const char filename[] = "/" BOOTFILE; 
+        static const char filename[] = "/" BOOTFILE;
         rolo_load((char*)filename); /* won't return if started */
 
         prompt_usb("No firmware", filename);