Work-in-progress rework of charging status reading & display: * Changed several charging related HAVE_* macros into one multi-value CONFIG_CHARGING. * Always use proper macros for charging states. * Battery symbol charging animation now starts from current level on all targets with charging. Two-colour animation kept for non-b&w targets. Round down fill level while charging as before, but round to nearest pixel value for discharging on all targets. * Charging anim fixed on player. * Some code cleanup.


git-svn-id: svn://svn.rockbox.org/rockbox/trunk@10080 a1c6a512-1295-4272-9138-f99709370657
diff --git a/apps/debug_menu.c b/apps/debug_menu.c
index fac570d..d426356 100644
--- a/apps/debug_menu.c
+++ b/apps/debug_menu.c
@@ -1334,8 +1334,8 @@
                 snprintf(buf, 30, "External: %d.%02d V", y / 100, y % 100);
                 lcd_puts(0, 2, buf);
 #endif
-#ifdef HAVE_CHARGING
-#ifdef HAVE_CHARGE_CTRL
+#ifdef CONFIG_CHARGING
+#if CONFIG_CHARGING == CHARGING_CONTROL
                 snprintf(buf, 30, "Chgr: %s %s", 
                          charger_inserted() ? "present" : "absent",
                          charger_enabled ? "on" : "off");
@@ -1345,8 +1345,8 @@
                 snprintf(buf, 30, "long delta: %d", long_delta);
                 lcd_puts(0, 6, buf);
                 lcd_puts(0, 7, power_message);
-#else /* !HAVE_CHARGE_CTRL */
-#if defined IPOD_NANO || defined IPOD_VIDEO 
+#else /* CONFIG_CHARGING != CHARGING_CONTROL */
+#if defined IPOD_NANO || defined IPOD_VIDEO
                 int usb_pwr  = (GPIOL_INPUT_VAL & 0x10)?true:false;
                 int ext_pwr  = (GPIOL_INPUT_VAL & 0x08)?false:true;
                 int dock     = (GPIOA_INPUT_VAL & 0x10)?true:false;
@@ -1373,8 +1373,8 @@
                          charger_inserted() ? "present" : "absent");
                 lcd_puts(0, 3, buf);
 #endif
-#endif /* !HAVE_CHARGE_CTRL */
-#endif /* HAVE_CHARGING */
+#endif /* CONFIG_CHARGING != CHARGING_CONTROL */
+#endif /* CONFIG_CHARGING */
                 break;
                 
             case 2: /* voltage deltas: */
@@ -1393,7 +1393,7 @@
             case 3: /* remaining time estimation: */
                 lcd_clear_display();
 
-#ifdef HAVE_CHARGE_CTRL
+#if CONFIG_CHARGING == CHARGING_CONTROL
                 snprintf(buf, 30, "charge_state: %d", charge_state);
                 lcd_puts(0, 0, buf);
 
@@ -1408,7 +1408,7 @@
 
                 snprintf(buf, 30, "Trickle sec: %d/60", trickle_sec);
                 lcd_puts(0, 4, buf);
-#endif /* HAVE_CHARGE_CTRL */
+#endif /* CONFIG_CHARGING == CHARGING_CONTROL */
 
                 snprintf(buf, 30, "Last PwrHist: %d.%02d V",
                     power_history[0] / 100,
@@ -1465,7 +1465,7 @@
 #endif
 
         if (state & 1) {
-#ifdef HAVE_CHARGING
+#ifdef CONFIG_CHARGING
             if (charger_inserted()
 #ifdef HAVE_USB_POWER
                     || usb_powered()
diff --git a/apps/gui/gwps-common.c b/apps/gui/gwps-common.c
index 5ab6ce8..171784c 100644
--- a/apps/gui/gwps-common.c
+++ b/apps/gui/gwps-common.c
@@ -823,7 +823,7 @@
                     }
                 }
                 
-#ifdef HAVE_CHARGING
+#ifdef CONFIG_CHARGING
                 case 'p': /* External power plugged in? */
                 {
                     if(charger_input_state==CHARGER)
@@ -832,9 +832,7 @@
                         return NULL;
                 }
 #endif
-#if defined(HAVE_CHARGE_CTRL) || \
-    defined (HAVE_CHARGE_STATE) || \
-    CONFIG_BATTERY == BATT_LIION2200
+#if CONFIG_CHARGING >= CHARGING_MONITOR
                 case 'c': /* Charging */
                 {
                     if (charge_state == CHARGING || charge_state == TOPOFF) {
diff --git a/apps/gui/statusbar.c b/apps/gui/statusbar.c
index c9b27ae..b5d8b7c 100644
--- a/apps/gui/statusbar.c
+++ b/apps/gui/statusbar.c
@@ -107,37 +107,73 @@
 
 void gui_statusbar_init(struct gui_statusbar * bar)
 {
-    bar->last_volume = -1000; /* -1000 means "first update ever" */
-    bar->battery_icon_switch_tick = 0;
-    bar->animated_level = 0;
+    bar->redraw_volume = true;
+    bar->volume_icon_switch_tick = bar->battery_icon_switch_tick = current_tick;
 }
 
 void gui_statusbar_draw(struct gui_statusbar * bar, bool force_redraw)
 {
     struct screen * display = bar->display;
-#ifdef CONFIG_RTC
-    struct tm* tm; /* For Time */
-#endif /* CONFIG_RTC */
 
 #ifdef HAVE_LCD_CHARCELLS
-    int vol;
+    int val;
     (void)force_redraw; /* players always "redraw" */
 #endif /* HAVE_LCD_CHARCELLS */
 
-    bar->info.volume = sound_val2phys(SOUND_VOLUME, global_settings.volume);
-#ifdef HAVE_CHARGING
-    bar->info.inserted = (charger_input_state == CHARGER);
-#endif
     bar->info.battlevel = battery_level();
-    bar->info.battery_safe = battery_level_safe();
+#ifdef HAVE_USB_POWER
+    bar->info.usb_power = usb_powered();
+#endif
+#ifdef CONFIG_CHARGING
+    bar->info.inserted = (charger_input_state == CHARGER);
+    if (bar->info.inserted)
+    {
+        bar->info.battery_state = true;
 
+#if CONFIG_CHARGING >= CHARGING_MONITOR
+
+        /* zero battery run time if charging */
+        if (charge_state > DISCHARGING)
+            lasttime = current_tick;
+
+        /* animate battery if charging */
+        if ((charge_state == DISCHARGING) || (charge_state == TRICKLE))
+        {
+            bar->info.batt_charge_step = -1;
+        }
+        else
+        {
+#else
+        lasttime = current_tick;
+        {
+#endif
+            /* animate in (max.) 4 steps, starting near the current charge level */
+            if (TIME_AFTER(current_tick, bar->battery_icon_switch_tick)) 
+            {
+                if (++bar->info.batt_charge_step > 3)
+                    bar->info.batt_charge_step = bar->info.battlevel / 34;
+                bar->battery_icon_switch_tick = current_tick + HZ;
+            }
+        }
+    }
+    else
+#endif
+    {
+        bar->info.batt_charge_step = -1;
+        if (battery_level_safe())
+            bar->info.battery_state = true;
+        else
+            /* blink battery if level is low */
+            if (TIME_AFTER(current_tick, bar->battery_icon_switch_tick) &&
+               (bar->info.battlevel > -1))
+            {
+                bar->info.battery_state = !bar->info.battery_state;
+                bar->battery_icon_switch_tick = current_tick + HZ;
+            }
+    }
+
+    bar->info.volume = sound_val2phys(SOUND_VOLUME, global_settings.volume);
 #ifdef HAVE_LCD_BITMAP
-#ifdef CONFIG_RTC
-    tm = get_time();
-    bar->info.hour = tm->tm_hour;
-    bar->info.minute = tm->tm_min;
-#endif /* CONFIG_RTC */
-
     bar->info.shuffle = global_settings.playlist_shuffle;
 #ifdef HAS_BUTTON_HOLD
     bar->info.keylock = button_hold();
@@ -149,24 +185,25 @@
 #endif
     bar->info.repeat = global_settings.repeat_mode;
     bar->info.playmode = current_playmode();
+
 #if (CONFIG_LED == LED_VIRTUAL) || defined(HAVE_REMOTE_LCD)
     if(!display->has_disk_led)
         bar->info.led = led_read(HZ/2); /* delay should match polling interval */
 #endif
-
-#ifdef HAVE_USB_POWER
-    bar->info.usb_power = usb_powered();
-#endif /* HAVE_USB_POWER */
+#ifdef CONFIG_RTC
+    {
+        struct tm* tm = get_time();
+        bar->info.hour = tm->tm_hour;
+        bar->info.minute = tm->tm_min;
+    }
+#endif /* CONFIG_RTC */
 
     /* only redraw if forced to, or info has changed */
-    if (force_redraw ||
-        bar->info.inserted ||
-        !bar->info.battery_safe ||
-        bar->info.redraw_volume ||
+    if (force_redraw || bar->redraw_volume ||
         memcmp(&(bar->info), &(bar->lastinfo), sizeof(struct status_info)))
     {
         display->set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
-        display->fillrect(0,0,display->width,8);
+        display->fillrect(0, 0, display->width, STATUSBAR_HEIGHT);
         display->set_drawmode(DRMODE_SOLID);
 
 #else
@@ -175,65 +212,10 @@
     {
 #endif /* HAVE_LCD_BITMAP */
 
-#ifdef HAVE_CHARGING
-        if (bar->info.inserted) {
-            battery_state = true;
-#if defined(HAVE_CHARGE_CTRL) || \
-    defined(HAVE_CHARGE_STATE) || \
-    CONFIG_BATTERY == BATT_LIION2200
-            /* zero battery run time if charging */
-            if (charge_state > DISCHARGING) {
-                lasttime = current_tick;
-            }
-
-            /* animate battery if charging */
-            if ((charge_state == CHARGING)
-#ifdef HAVE_CHARGE_CTRL
-                    || (charge_state == TOPOFF)
-#endif
-                ) {
-#else
-            lasttime = current_tick;
-            {
-#endif
-                /* animate in three steps (34% per step for a better look) */
-#ifndef HAVE_CHARGE_STATE
-                bar->info.battlevel = 0;
-#endif
-                if(TIME_AFTER(current_tick, bar->battery_icon_switch_tick)) {
-                    if (bar->animated_level == 100)
-                    {
-                        bar->animated_level = bar->info.battlevel;
-                    }
-                    else
-                    {
-                        bar->animated_level += 34;
-                        if (bar->animated_level > 100)
-                            bar->animated_level = 100;
-                    }
-                    bar->battery_icon_switch_tick = current_tick + HZ;
-                }
-            }
-        }
-        else
-#endif /* HAVE_CHARGING */
-        {
-            bar->animated_level = 0;
-            if (bar->info.battery_safe)
-                battery_state = true;
-            else {
-                /* blink battery if level is low */
-                if(TIME_AFTER(current_tick, bar->battery_icon_switch_tick) &&
-                   (bar->info.battlevel > -1)) {
-                    bar->battery_icon_switch_tick = current_tick+HZ;
-                    battery_state = !battery_state;
-                }
-            }
-        }
 #ifdef HAVE_LCD_BITMAP
-        if (battery_state)
+        if (bar->info.battery_state)
             gui_statusbar_icon_battery(display, bar->info.battlevel, 
-                                       bar->animated_level);
+                                       bar->info.batt_charge_step);
 #ifdef HAVE_USB_POWER
         if (bar->info.usb_power)
             display->mono_bitmap(bitmap_icons_7x8[Icon_USBPlug],
@@ -243,14 +225,15 @@
         else
 #endif /* HAVE_USB_POWER */
         /* draw power plug if charging */
+#ifdef CONFIG_CHARGING
         if (bar->info.inserted)
             display->mono_bitmap(bitmap_icons_7x8[Icon_Plug],
                                     STATUSBAR_PLUG_X_POS,
                                     STATUSBAR_Y_POS, STATUSBAR_PLUG_WIDTH,
                                     STATUSBAR_HEIGHT);
+#endif
 
-        bar->info.redraw_volume = gui_statusbar_icon_volume(bar,
-                                                bar->info.volume);
+        bar->redraw_volume = gui_statusbar_icon_volume(bar, bar->info.volume);
         gui_statusbar_icon_play_state(display, current_playmode() +
                                                 Icon_Play);
 
@@ -292,20 +275,24 @@
 
 
 #ifdef HAVE_LCD_CHARCELLS
-    if (bar->info.battlevel > -1)
-        display->icon(ICON_BATTERY, battery_state);
-    display->icon(ICON_BATTERY_1, bar->info.battlevel > 25);
-    display->icon(ICON_BATTERY_2, bar->info.battlevel > 50);
-    display->icon(ICON_BATTERY_3, bar->info.battlevel > 75);
+    display->icon(ICON_BATTERY, bar->info.battery_state);
+    
+    if (bar->info.batt_charge_step > -1)
+        val = bar->info.batt_charge_step;
+    else
+        val = (bar->info.battlevel * 3 + 50) / 100;
+    display->icon(ICON_BATTERY_1, val >= 1);
+    display->icon(ICON_BATTERY_2, val >= 2);
+    display->icon(ICON_BATTERY_3, val >= 3);
 
-    vol = 100 * (bar->info.volume - sound_min(SOUND_VOLUME))
+    val = 10 * (bar->info.volume - sound_min(SOUND_VOLUME))
            / (sound_max(SOUND_VOLUME) - sound_min(SOUND_VOLUME));
     display->icon(ICON_VOLUME, true);
-    display->icon(ICON_VOLUME_1, vol > 10);
-    display->icon(ICON_VOLUME_2, vol > 30);
-    display->icon(ICON_VOLUME_3, vol > 50);
-    display->icon(ICON_VOLUME_4, vol > 70);
-    display->icon(ICON_VOLUME_5, vol > 90);
+    display->icon(ICON_VOLUME_1, val >= 1);
+    display->icon(ICON_VOLUME_2, val >= 3);
+    display->icon(ICON_VOLUME_3, val >= 5);
+    display->icon(ICON_VOLUME_4, val >= 7);
+    display->icon(ICON_VOLUME_5, val >= 9);
 
     display->icon(ICON_PLAY, current_playmode() == STATUS_PLAY);
     display->icon(ICON_PAUSE, current_playmode() == STATUS_PAUSE);
@@ -326,40 +313,41 @@
  * Print battery icon to status bar
  */
 void gui_statusbar_icon_battery(struct screen * display, int percent, 
-                                int animated_percent)
+                                int batt_charge_step)
 {
     int fill, endfill;
     char buffer[5];
     unsigned int width, height;
 #if LCD_DEPTH > 1
-    unsigned int prevfg = LCD_DEFAULT_FG;
+    unsigned int prevfg = 0;
 #endif
 
-    /* fill battery */
-    fill = percent;
-    if (fill < 0)
-        fill = 0;
-    if (fill > 100)
-        fill = 100;
+#ifdef CONFIG_CHARGING
+    if (batt_charge_step >= 0)
+    {
+        fill = percent * (STATUSBAR_BATTERY_WIDTH-3) / 100;
+        endfill = 34 * batt_charge_step * (STATUSBAR_BATTERY_WIDTH-3) / 100;
+    }
+    else
+#else
+    (void)batt_charge_step;
+#endif
+    {
+        fill = endfill = (percent * (STATUSBAR_BATTERY_WIDTH-3) + 50) / 100;
+    }
 
-    endfill = animated_percent;
-    if (endfill < 0)
-        endfill = 0;
-    if (endfill > 100)
-        endfill = 100;
-    
-#if (defined(HAVE_CHARGE_CTRL) || defined(HAVE_CHARGE_STATE)) && \
-    !defined(SIMULATOR) /* Certain charge controlled targets */
+#if CONFIG_CHARGING == CHARGING_MONITOR && !defined(SIMULATOR) 
+    /* Certain charge controlled targets */
     /* show graphical animation when charging instead of numbers */
     if ((global_settings.battery_display) &&
-        (charge_state != 1) &&
+        (charge_state != CHARGING) &&
         (percent > -1)) {
 #else /* all others */
     if (global_settings.battery_display && (percent > -1)) {
 #endif
         /* Numeric display */
         display->setfont(FONT_SYSFIXED);
-        snprintf(buffer, sizeof(buffer), "%3d", fill);
+        snprintf(buffer, sizeof(buffer), "%3d", percent);
         display->getstringsize(buffer, &width, &height);
         if (height <= STATUSBAR_HEIGHT)
             display->putsxy(STATUSBAR_BATTERY_X_POS
@@ -374,7 +362,6 @@
         display->vline(STATUSBAR_BATTERY_X_POS + 17, STATUSBAR_Y_POS + 2,
                        STATUSBAR_Y_POS + 4);
 
-        fill = fill * 15 / 100;
         display->fillrect(STATUSBAR_BATTERY_X_POS + 1, STATUSBAR_Y_POS + 1,
                           fill, 5);
 #if LCD_DEPTH > 1
@@ -384,9 +371,8 @@
             display->set_foreground(LCD_DARKGRAY);
         }
 #endif
-        endfill = endfill * 15 / 100 - fill;
-        display->fillrect(STATUSBAR_BATTERY_X_POS + 1 + fill, 
-                          STATUSBAR_Y_POS + 1, endfill, 5);
+        display->fillrect(STATUSBAR_BATTERY_X_POS + 1 + fill,
+                          STATUSBAR_Y_POS + 1, endfill - fill, 5);
 #if LCD_DEPTH > 1
         if (display->depth > 1)
             display->set_foreground(prevfg);
@@ -507,6 +493,7 @@
                          STATUSBAR_LOCKM_WIDTH, STATUSBAR_HEIGHT);
 }
 
+#ifdef HAS_REMOTE_BUTTON_HOLD
 /*
  * Print remote lock when remote hold is enabled
  */
@@ -516,6 +503,7 @@
                          STATUSBAR_LOCKR_X_POS, STATUSBAR_Y_POS,
                          STATUSBAR_LOCKR_WIDTH, STATUSBAR_HEIGHT);
 }
+#endif
 
 #if (CONFIG_LED == LED_VIRTUAL) || defined(HAVE_REMOTE_LCD)
 /*
diff --git a/apps/gui/statusbar.h b/apps/gui/statusbar.h
index 03add6a..a03c294 100644
--- a/apps/gui/statusbar.h
+++ b/apps/gui/statusbar.h
@@ -31,38 +31,40 @@
 
 struct status_info {
     int battlevel;
+    int batt_charge_step;
     int volume;
+    int playmode;
+    int repeat;
 #ifdef CONFIG_RTC
     int hour;
     int minute;
 #endif
-    int playmode;
-    int repeat;
+
+#ifdef CONFIG_CHARGING
     bool inserted;
+#endif
+#ifdef HAVE_USB_POWER
+    bool usb_power;
+#endif
+    bool battery_state;
     bool shuffle;
     bool keylock;
 #ifdef HAS_REMOTE_BUTTON_HOLD
     bool keylockremote;
 #endif
-    bool battery_safe;
-    bool redraw_volume; /* true if the volume gauge needs updating */
 #if (CONFIG_LED == LED_VIRTUAL) || defined(HAVE_REMOTE_LCD)
     bool led; /* disk LED simulation in the status bar */
 #endif
 
-#ifdef HAVE_USB_POWER
-    bool usb_power;
-#endif
 };
 
 struct gui_statusbar
 {
-    /* Volume icon stuffs */
+    long battery_icon_switch_tick;
+
     long volume_icon_switch_tick;
     int last_volume;
-    
-    long battery_icon_switch_tick;
-    int animated_level;
+    bool redraw_volume; /* true if the volume gauge needs updating */
 
     struct status_info info;
     struct status_info lastinfo;
@@ -95,7 +97,7 @@
  */
 extern void gui_statusbar_draw(struct gui_statusbar * bar, bool force_redraw);
 
-void gui_statusbar_icon_battery(struct screen * display, int percent, int animated_percent);
+void gui_statusbar_icon_battery(struct screen * display, int percent, int batt_charge_step);
 bool gui_statusbar_icon_volume(struct gui_statusbar * bar, int volume);
 void gui_statusbar_icon_play_state(struct screen * display, int state);
 void gui_statusbar_icon_play_mode(struct screen * display, int mode);
diff --git a/apps/main.c b/apps/main.c
index 0771b28..5867f79 100644
--- a/apps/main.c
+++ b/apps/main.c
@@ -228,7 +228,7 @@
 {
     int rc;
     bool mounted = false;
-#if defined(HAVE_CHARGING) && (CONFIG_CPU == SH7034)
+#if defined(CONFIG_CHARGING) && (CONFIG_CPU == SH7034)
     /* if nobody initialized ATA before, I consider this a cold start */
     bool coldstart = (PACR2 & 0x4000) != 0; /* starting from Flash */
 #endif
@@ -295,7 +295,7 @@
     screen_access_init();
     gui_syncstatusbar_init(&statusbars);
 
-#if defined(HAVE_CHARGING) && (CONFIG_CPU == SH7034)
+#if defined(CONFIG_CHARGING) && (CONFIG_CPU == SH7034)
     if (coldstart && charger_inserted()
         && !global_settings.car_adapter_mode
 #ifdef ATA_POWER_PLAYERSTYLE
@@ -433,7 +433,7 @@
     }
 #endif /* #ifdef AUTOROCK */
 
-#ifdef HAVE_CHARGING
+#ifdef CONFIG_CHARGING
     car_adapter_mode_init();
 #endif
 }
diff --git a/apps/main_menu.c b/apps/main_menu.c
index e6c2bb7..eb94498 100644
--- a/apps/main_menu.c
+++ b/apps/main_menu.c
@@ -169,12 +169,12 @@
 #endif
             lcd_puts_scroll(0, y++, (unsigned char *)s);
 
-#ifdef HAVE_CHARGE_CTRL
-            if (charge_state == 1)
+#if CONFIG_CHARGING == CHARGING_CONTROL
+            if (charge_state == CHARGING)
                 snprintf(s, sizeof(s), (char *)str(LANG_BATTERY_CHARGE));
-            else if (charge_state == 2)
+            else if (charge_state == TOPOFF)
                 snprintf(s, sizeof(s), (char *)str(LANG_BATTERY_TOPOFF_CHARGE));
-            else if (charge_state == 3)
+            else if (charge_state == TRICKLE)
                 snprintf(s, sizeof(s), (char *)str(LANG_BATTERY_TRICKLE_CHARGE));
             else
 #endif
diff --git a/apps/misc.c b/apps/misc.c
index 96f913a..0ab826c 100644
--- a/apps/misc.c
+++ b/apps/misc.c
@@ -491,7 +491,7 @@
         return false;
     }
     
-#if defined(HAVE_CHARGING) && !defined(HAVE_POWEROFF_WHILE_CHARGING)
+#if defined(CONFIG_CHARGING) && !defined(HAVE_POWEROFF_WHILE_CHARGING)
     if(!charger_inserted())
 #endif
     {
@@ -509,7 +509,7 @@
     return false;
 }
 
-#ifdef HAVE_CHARGING
+#ifdef CONFIG_CHARGING
 static bool waiting_to_resume_play = false;
 static long play_resume_tick;
 
@@ -584,7 +584,7 @@
             if (!clean_shutdown(callback, parameter))
                 return SYS_POWEROFF;
             break;
-#ifdef HAVE_CHARGING
+#ifdef CONFIG_CHARGING
         case SYS_CHARGER_CONNECTED:
             car_adapter_mode_processing(true);
             return SYS_CHARGER_CONNECTED;
diff --git a/apps/plugin.c b/apps/plugin.c
index 1b1c406..1bc4817 100644
--- a/apps/plugin.c
+++ b/apps/plugin.c
@@ -58,7 +58,7 @@
 #include "dsp.h"
 #endif
 
-#ifdef HAVE_CHARGING
+#ifdef CONFIG_CHARGING
 #include "power.h"
 #endif
 
@@ -359,9 +359,9 @@
 #ifndef SIMULATOR
     battery_voltage,
 #endif
-#ifdef HAVE_CHARGING
+#ifdef CONFIG_CHARGING
     charger_inserted,
-# ifdef HAVE_CHARGE_STATE
+# if CONFIG_CHARGING == CHARGING_MONITOR
     charging_state,
 # endif
 #endif
diff --git a/apps/plugin.h b/apps/plugin.h
index de8f267..b4990b8 100644
--- a/apps/plugin.h
+++ b/apps/plugin.h
@@ -421,9 +421,9 @@
 #ifndef SIMULATOR
     unsigned int (*battery_voltage)(void);
 #endif
-#ifdef HAVE_CHARGING
+#ifdef CONFIG_CHARGING
     bool (*charger_inserted)(void);
-# ifdef HAVE_CHARGE_STATE
+# if CONFIG_CHARGING == CHARGING_MONITOR
     bool (*charging_state)(void);
 # endif
 #endif
diff --git a/apps/plugins/battery_bench.c b/apps/plugins/battery_bench.c
index 552be8a..210ecbd 100644
--- a/apps/plugins/battery_bench.c
+++ b/apps/plugins/battery_bench.c
@@ -128,14 +128,14 @@
 /* use long for aligning */
 unsigned long thread_stack[THREAD_STACK_SIZE/sizeof(long)];
 
-#if defined(HAVE_CHARGING) || defined(HAVE_USB_POWER)
+#if defined(CONFIG_CHARGING) || defined(HAVE_USB_POWER)
 unsigned int charge_state(void)
 {
     unsigned int ret = 0;
-#ifdef HAVE_CHARGING
+#ifdef CONFIG_CHARGING
     if(rb->charger_inserted())
         ret = BIT_CHARGER;
-#ifdef HAVE_CHARGE_STATE
+#if CONFIG_CHARGING == CHARGING_MONITOR
     if(rb->charging_state())
         ret |= BIT_CHARGING;
 #endif
@@ -154,7 +154,7 @@
     int fd, buffelements, tick = 1, i = 0, skipped = 0, exit = 0;
     int fst = 0, lst = 0; /* first and last skipped tick */
     unsigned int last_voltage = 0;
-#if  defined(HAVE_CHARGING) || defined(HAVE_USB_POWER) 
+#if  defined(CONFIG_CHARGING) || defined(HAVE_USB_POWER) 
     unsigned int last_state = 0;
 #endif    
     long sleep_time;
@@ -202,9 +202,9 @@
                          rb->fdprintf(fd,
                                 "%02d:%02d:%02d,  %05d,     %03d%%,     "
                                 "%02d:%02d,           %04d,     %04d"
-#ifdef HAVE_CHARGING
+#ifdef CONFIG_CHARGING
                                 ",  %c"
-#ifdef HAVE_CHARGE_STATE
+#if CONFIG_CHARGING == CHARGING_MONITOR
                                 ",  %c"
 #endif
 #endif
@@ -215,7 +215,7 @@
                                 
                                 HMS(secs), secs, bat[j].level,
                                 bat[j].eta / 60, bat[j].eta % 60, 
-#if defined(HAVE_CHARGING) || defined(HAVE_USB_POWER)
+#if defined(CONFIG_CHARGING) || defined(HAVE_USB_POWER)
                                 (bat[j].voltage & 
                                  (~(BIT_CHARGER|BIT_CHARGING|BIT_USB_POWER)))
                                 *10,
@@ -223,9 +223,9 @@
                                 bat[j].voltage * 10,
 #endif
                                 temp + 1 + (j-i)
-#ifdef HAVE_CHARGING
+#ifdef CONFIG_CHARGING
                                 ,(bat[j].voltage & BIT_CHARGER)?'A':'-' 
-#ifdef HAVE_CHARGE_STATE
+#if CONFIG_CHARGING == CHARGING_MONITOR
                                 ,(bat[j].voltage & BIT_CHARGING)?'C':'-'
 #endif
 #endif
@@ -260,7 +260,7 @@
                 timeflag = true;
             
             if(last_voltage != (current_voltage=rb->battery_voltage())
-#if defined(HAVE_CHARGING) || defined(HAVE_USB_POWER)
+#if defined(CONFIG_CHARGING) || defined(HAVE_USB_POWER)
                 || last_state != charge_state()
 #endif
                             )
@@ -280,7 +280,7 @@
                 bat[i].level = rb->battery_level();
                 bat[i].eta = rb->battery_time();
                 last_voltage = bat[i].voltage = current_voltage;
-#if defined(HAVE_CHARGING) || defined(HAVE_USB_POWER)
+#if defined(CONFIG_CHARGING) || defined(HAVE_USB_POWER)
                 bat[i].voltage |= last_state = charge_state();
 #endif                
                 i++;
@@ -421,10 +421,10 @@
                 "Battery type: %d mAh      Buffer Entries: %d\n"
                 "  Time:,  Seconds:,  Level:,  Time Left:,  Voltage[mV]:,"
                 "  M/DA:"
-#ifdef HAVE_CHARGING
+#ifdef CONFIG_CHARGING
                 ", C:"
 #endif
-#ifdef HAVE_CHARGE_STATE
+#if CONFIG_CHARGING == CHARGING_MONITOR
                 ", S:"
 #endif
 #ifdef HAVE_USB_POWER
diff --git a/apps/screens.c b/apps/screens.c
index 20a0b58..5120152 100644
--- a/apps/screens.c
+++ b/apps/screens.c
@@ -149,7 +149,7 @@
 }
 #endif
 
-#if defined(HAVE_CHARGING) && !defined(HAVE_POWEROFF_WHILE_CHARGING)
+#if defined(CONFIG_CHARGING) && !defined(HAVE_POWEROFF_WHILE_CHARGING)
 
 #ifdef HAVE_LCD_BITMAP
 void charging_display_info(bool animate)
@@ -178,16 +178,16 @@
         lcd_puts(0, 7, buf);
     }
 
-#ifdef HAVE_CHARGE_CTRL
+#if CONFIG_CHARGING == CHARGING_CONTROL
 
     snprintf(buf, 32, "Charge mode:");
     lcd_puts(0, 2, buf);
 
-    if (charge_state == 1)
+    if (charge_state == CHARGING)
         snprintf(buf, 32, str(LANG_BATTERY_CHARGE));
-    else if (charge_state == 2)
+    else if (charge_state == TOPOFF)
         snprintf(buf, 32, str(LANG_BATTERY_TOPOFF_CHARGE));
-    else if (charge_state == 3)
+    else if (charge_state == TRICKLE)
         snprintf(buf, 32, str(LANG_BATTERY_TRICKLE_CHARGE));
     else
         snprintf(buf, 32, "not charging");
@@ -195,7 +195,7 @@
     lcd_puts(0, 3, buf);
     if (!charger_enabled)
         animate = false;
-#endif /* HAVE_CHARGE_CTRL */
+#endif /* CONFIG_CHARGING == CHARGING_CONTROL */
 
 
     /* middle part */
@@ -351,7 +351,7 @@
 #endif
     return rc;
 }
-#endif /* HAVE_CHARGING && !HAVE_POWEROFF_WHILE_CHARGING */
+#endif /* CONFIG_CHARGING && !HAVE_POWEROFF_WHILE_CHARGING */
 
 #if (CONFIG_KEYPAD != PLAYER_PAD)
 /* returns:
@@ -660,7 +660,7 @@
 #endif /* BUTTON_F3 */
 #endif /* CONFIG_KEYPAD in (RECORDER_PAD |IRIVER_H100_PAD | IRIVER_H300_PAD) */
 
-#if defined(HAVE_CHARGING) || defined(SIMULATOR)
+#if defined(CONFIG_CHARGING) || defined(SIMULATOR)
 void charging_splash(void)
 {
     gui_syncsplash(2*HZ, true, (unsigned char *)str(LANG_BATTERY_CHARGE));
diff --git a/apps/settings.c b/apps/settings.c
index 0d6ee1d..6d7f250 100644
--- a/apps/settings.c
+++ b/apps/settings.c
@@ -243,7 +243,7 @@
     {6, S_O(contrast), 40, "contrast", NULL },
 #ifdef CONFIG_BACKLIGHT
     {5, S_O(backlight_timeout), 5, "backlight timeout", backlight_times_conf },
-#ifdef HAVE_CHARGING
+#ifdef CONFIG_CHARGING
     {5, S_O(backlight_timeout_plugged), 11, "backlight timeout plugged",
         backlight_times_conf },
 #endif
@@ -276,7 +276,7 @@
     {12, S_O(battery_capacity), BATTERY_CAPACITY_DEFAULT, "battery capacity",
          NULL }, /* 1500...3200 for NiMH, 2200...3200 for LiIon,
                      500...1500 for Alkaline */
-#ifdef HAVE_CHARGING
+#ifdef CONFIG_CHARGING
     {1, S_O(car_adapter_mode), false, "car adapter mode", off_on },
 #endif
     /* tuner */
@@ -296,7 +296,7 @@
     {1, S_O(remote_flip_display), false, "remote flip display", off_on },
     {5, S_O(remote_backlight_timeout), 5, "remote backlight timeout",
         backlight_times_conf },
-#ifdef HAVE_CHARGING
+#ifdef CONFIG_CHARGING
     {5, S_O(remote_backlight_timeout_plugged), 11,
         "remote backlight timeout plugged", backlight_times_conf },
 #endif
@@ -1018,13 +1018,13 @@
     lcd_remote_emireduce(global_settings.remote_reduce_ticking);
 #endif
     remote_backlight_set_timeout(global_settings.remote_backlight_timeout);
-#ifdef HAVE_CHARGING
+#ifdef CONFIG_CHARGING
     remote_backlight_set_timeout_plugged(global_settings.remote_backlight_timeout_plugged);
 #endif
 #endif
 #ifdef CONFIG_BACKLIGHT
     backlight_set_timeout(global_settings.backlight_timeout);
-#ifdef HAVE_CHARGING
+#ifdef CONFIG_CHARGING
     backlight_set_timeout_plugged(global_settings.backlight_timeout_plugged);
 #endif
 #if defined(HAVE_BACKLIGHT_PWM_FADING) && !defined(SIMULATOR)
diff --git a/apps/settings_menu.c b/apps/settings_menu.c
index bcf5a78..821ad53 100644
--- a/apps/settings_menu.c
+++ b/apps/settings_menu.c
@@ -81,7 +81,7 @@
 #include "backdrop.h"
 #endif
 
-#ifdef HAVE_CHARGING
+#ifdef CONFIG_CHARGING
 static bool car_adapter_mode(void)
 {
     return set_bool( str(LANG_CAR_ADAPTER_MODE),
@@ -177,7 +177,7 @@
                      &global_settings.caption_backlight);
 }
 
-#ifdef HAVE_CHARGING
+#ifdef CONFIG_CHARGING
 static bool backlight_timer_plugged(void)
 {
     return set_option((char *)str(LANG_BACKLIGHT_ON_WHEN_CHARGING),
@@ -248,7 +248,7 @@
                       remote_backlight_set_timeout );
 }
 
-#ifdef HAVE_CHARGING
+#ifdef CONFIG_CHARGING
 static bool remote_backlight_timer_plugged(void)
 {
     return set_option((char *)str(LANG_BACKLIGHT_ON_WHEN_CHARGING),
@@ -1715,7 +1715,7 @@
     static const struct menu_item items[] = {
 #ifdef CONFIG_BACKLIGHT
         { ID2P(LANG_BACKLIGHT),       backlight_timer },
-#ifdef HAVE_CHARGING
+#ifdef CONFIG_CHARGING
         { ID2P(LANG_BACKLIGHT_ON_WHEN_CHARGING), backlight_timer_plugged },
 #endif
         { ID2P(LANG_CAPTION_BACKLIGHT), caption_backlight },
@@ -1763,7 +1763,7 @@
 
     static const struct menu_item items[] = {
         { ID2P(LANG_BACKLIGHT),       remote_backlight_timer },
-#ifdef HAVE_CHARGING
+#ifdef CONFIG_CHARGING
         { ID2P(LANG_BACKLIGHT_ON_WHEN_CHARGING),
                                       remote_backlight_timer_plugged },
 #endif
@@ -1860,10 +1860,8 @@
         { ID2P(LANG_BATTERY_TYPE),     battery_type },
 #endif
 #else
-#ifndef HAVE_CHARGE_CTRL
         { "Dummy", NULL }, /* to have an entry at all, in the simulator */
 #endif
-#endif
     };
 
     m=menu_init( items, sizeof(items) / sizeof(*items), NULL,
@@ -1975,7 +1973,7 @@
 #if CONFIG_CODEC == MAS3507D
         { ID2P(LANG_LINE_IN),          line_in                },
 #endif
-#ifdef HAVE_CHARGING
+#ifdef CONFIG_CHARGING
         { ID2P(LANG_CAR_ADAPTER_MODE), car_adapter_mode       },
 #endif
     };
diff --git a/apps/status.c b/apps/status.c
index 5c5fb3e..ca8a4d6 100644
--- a/apps/status.c
+++ b/apps/status.c
@@ -49,12 +49,6 @@
 
 enum playmode ff_mode;
 
-long switch_tick;
-bool battery_state = true;
-#ifdef HAVE_CHARGING
-int battery_charge_step = 0;
-#endif
-
 void status_init(void)
 {
     ff_mode = 0;
diff --git a/apps/status.h b/apps/status.h
index 6831925..f42352b 100644
--- a/apps/status.h
+++ b/apps/status.h
@@ -21,12 +21,6 @@
 
 extern enum playmode ff_mode;
 
-extern long switch_tick;
-extern bool battery_state;
-#ifdef HAVE_CHARGING
-extern int battery_charge_step;
-#endif
-
 #if defined(HAVE_LCD_CHARCELLS)
 extern bool record;
 extern bool audio;
diff --git a/apps/tree.c b/apps/tree.c
index 35cefb1..72e7bc4 100644
--- a/apps/tree.c
+++ b/apps/tree.c
@@ -644,7 +644,7 @@
                         if (!global_settings.party_mode)
                             audio_stop();
                     }
-#if defined(HAVE_CHARGING) && \
+#if defined(CONFIG_CHARGING) && \
     (CONFIG_KEYPAD == RECORDER_PAD) && !defined(HAVE_SW_POWEROFF)
                     else {
                         if (!charger_inserted()) {
@@ -658,7 +658,7 @@
 #endif
                 }
                 break;
-#if defined(HAVE_CHARGING) && !defined(HAVE_POWEROFF_WHILE_CHARGING)
+#if defined(CONFIG_CHARGING) && !defined(HAVE_POWEROFF_WHILE_CHARGING)
             case TREE_OFF | BUTTON_REPEAT:
                 if (charger_inserted()) {
                     charging_splash();
diff --git a/firmware/backlight.c b/firmware/backlight.c
index aac438c..76ffc6f 100644
--- a/firmware/backlight.c
+++ b/firmware/backlight.c
@@ -156,14 +156,14 @@
 
 static int backlight_timer;
 static int backlight_timeout = 5*HZ;
-#ifdef HAVE_CHARGING
+#ifdef CONFIG_CHARGING
 static int backlight_timeout_plugged = 5*HZ;
 #endif
 
 #ifdef HAVE_REMOTE_LCD
 static int remote_backlight_timer;
 static int remote_backlight_timeout = 5*HZ;
-#ifdef HAVE_CHARGING
+#ifdef CONFIG_CHARGING
 static int remote_backlight_timeout_plugged = 5*HZ;
 #endif
 #endif
@@ -370,7 +370,7 @@
         {
 #ifdef HAVE_REMOTE_LCD
             case REMOTE_BACKLIGHT_ON:
-#ifdef HAVE_CHARGING
+#ifdef CONFIG_CHARGING
                 if (charger_inserted()
 #ifdef HAVE_USB_POWER
                         || usb_powered()
@@ -399,7 +399,7 @@
                 
 #endif /* HAVE_REMOTE_LCD */
             case BACKLIGHT_ON:
-#ifdef HAVE_CHARGING
+#ifdef CONFIG_CHARGING
                 if (charger_inserted()
 #ifdef HAVE_USB_POWER
                         || usb_powered()
@@ -447,7 +447,7 @@
 
 static void backlight_tick(void)
 {
-#ifdef HAVE_CHARGING
+#ifdef CONFIG_CHARGING
     static bool charger_was_inserted = false;
     bool charger_is_inserted = charger_inserted()
 #ifdef HAVE_USB_POWER
@@ -463,7 +463,7 @@
 #endif
     }
     charger_was_inserted = charger_is_inserted;
-#endif /* HAVE_CHARGING */
+#endif /* CONFIG_CHARGING */
 
     if(backlight_timer)
     {
@@ -535,7 +535,7 @@
 /* return value in ticks; 0 means always on, <0 means always off */
 int backlight_get_current_timeout(void)
 {
-#ifdef HAVE_CHARGING
+#ifdef CONFIG_CHARGING
     if (charger_inserted()
 #ifdef HAVE_USB_POWER
             || usb_powered()
@@ -558,7 +558,7 @@
     backlight_on();
 }
 
-#ifdef HAVE_CHARGING
+#ifdef CONFIG_CHARGING
 void backlight_set_timeout_plugged(int index)
 {
     if((unsigned)index >= sizeof(backlight_timeout_value))
@@ -589,7 +589,7 @@
     remote_backlight_on();
 }
 
-#ifdef HAVE_CHARGING
+#ifdef CONFIG_CHARGING
 void remote_backlight_set_timeout_plugged(int index)
 {
     if((unsigned)index >= sizeof(backlight_timeout_value))
@@ -603,7 +603,7 @@
 /* return value in ticks; 0 means always on, <0 means always off */
 int remote_backlight_get_current_timeout(void)
 {
-#ifdef HAVE_CHARGING
+#ifdef CONFIG_CHARGING
     if (charger_inserted()
 #ifdef HAVE_USB_POWER
             || usb_powered()
diff --git a/firmware/drivers/button.c b/firmware/drivers/button.c
index 6513fb4..216c51e 100644
--- a/firmware/drivers/button.c
+++ b/firmware/drivers/button.c
@@ -490,7 +490,7 @@
                                     || btn == BUTTON_RC_STOP
 #endif
                                     ) &&
-#if defined(HAVE_CHARGING) && !defined(HAVE_POWEROFF_WHILE_CHARGING)
+#if defined(CONFIG_CHARGING) && !defined(HAVE_POWEROFF_WHILE_CHARGING)
                                 !charger_inserted() &&
 #endif
                                 repeat_count > POWEROFF_COUNT)
@@ -1248,7 +1248,7 @@
         backlight_on();
     }
     /* TODO: add light handling for the remote */
-    
+
     hold_button = button_hold();
     remote_hold_button = remote_button_hold();
 
diff --git a/firmware/drivers/power.c b/firmware/drivers/power.c
index c4b9fb5..bda03b0 100644
--- a/firmware/drivers/power.c
+++ b/firmware/drivers/power.c
@@ -29,7 +29,7 @@
 #include "pcf50606.h"
 #include "usb.h"
 
-#ifdef HAVE_CHARGE_CTRL
+#if CONFIG_CHARGING == CHARGING_CONTROL
 bool charger_enabled;
 #endif
 
@@ -92,7 +92,7 @@
     or_b(0x20, &PBIORL); 
     or_b(0x20, &PBDRL);  /* hold power */
 #endif
-#ifdef HAVE_CHARGE_CTRL
+#if CONFIG_CHARGING == CHARGING_CONTROL
     PBCR2 &= ~0x0c00;    /* GPIO for PB5 */
     or_b(0x20, &PBIORL); /* Set charging control bit to output */
     charger_enable(false); /* Default to charger OFF */
@@ -106,7 +106,7 @@
 }
 
 
-#ifdef HAVE_CHARGING
+#ifdef CONFIG_CHARGING
 bool charger_inserted(void)
 {     
 #if defined(IRIVER_H100_SERIES) || defined(IRIVER_H300_SERIES)
@@ -115,7 +115,7 @@
     return (P7 & 0x80) == 0;
 #elif defined(IAUDIO_X5)
     return (GPIO1_READ & 0x01000000)?true:false;
-#elif defined(HAVE_CHARGE_CTRL)
+#elif CONFIG_CHARGING == CHARGING_CONTROL
     /* Recorder */
     return adc_read(ADC_EXT_POWER) > 0x100;
 #elif defined (HAVE_FMADC)
@@ -133,9 +133,9 @@
     return (PADR & 1) == 0;
 #endif
 }
-#endif /* HAVE_CHARGING */
+#endif /* CONFIG_CHARGING */
 
-#ifdef HAVE_CHARGE_CTRL
+#if CONFIG_CHARGING == CHARGING_CONTROL
 void charger_enable(bool on)
 {
     if(on)
@@ -151,14 +151,22 @@
 }
 #endif
 
-#ifdef HAVE_CHARGE_STATE
+#if CONFIG_CHARGING == CHARGING_MONITOR
 /* Returns true if the unit is charging the batteries. */
 bool charging_state(void) {
-#if defined(IRIVER_H100_SERIES)
+#if CONFIG_BATTERY == BATT_LIION2200
+  /* We use the information from the ADC_EXT_POWER ADC channel, which
+    tells us the charging current from the LTC1734. When DC is
+    connected (either via the external adapter, or via USB), we try
+    to determine if it is actively charging or only maintaining the
+    charge. My tests show that ADC readings below about 0x80 means
+    that the LTC1734 is only maintaining the charge. */
+    return adc_read(ADC_EXT_POWER) >= 0x80;
+#elif defined(IRIVER_H100_SERIES) /* FIXME */
     return charger_inserted();
-#elif defined(IRIVER_H300_SERIES)
+#elif defined IRIVER_H300_SERIES
     return (GPIO_READ & 0x00800000)?true:false;
-#elif defined(IPOD_VIDEO)
+#elif defined IPOD_VIDEO
     return (GPIOB_INPUT_VAL & 0x01)?false:true;
 #endif
 }
diff --git a/firmware/export/config-fmrecorder.h b/firmware/export/config-fmrecorder.h
index 8711640..7a78d48 100644
--- a/firmware/export/config-fmrecorder.h
+++ b/firmware/export/config-fmrecorder.h
@@ -90,8 +90,8 @@
 /* How to detect USB */
 #define USB_FMRECORDERSTYLE 1
 
-/* Define this if the platform can charge batteries */
-#define HAVE_CHARGING 1
+/* Hardware controlled charging with monitoring */
+#define CONFIG_CHARGING CHARGING_MONITOR
 
 /* The start address index for ROM builds */
 /* #define ROM_START 0x14010 for behind original Archos */
diff --git a/firmware/export/config-gigabeat.h b/firmware/export/config-gigabeat.h
index 83a92ce..1ebbdbf 100644
--- a/firmware/export/config-gigabeat.h
+++ b/firmware/export/config-gigabeat.h
@@ -61,8 +61,8 @@
 
 #define BATTERY_SCALE_FACTOR 23437 /* FIX: this value is picked at random */
 
-/* Define this if the platform can charge batteries */
-#define HAVE_CHARGING 1
+/* Hardware controlled charging? FIXME */
+#define CONFIG_CHARGING CHARGING_SIMPLE
 
 /* define this if the hardware can be powered off while charging */
 #define HAVE_POWEROFF_WHILE_CHARGING
diff --git a/firmware/export/config-gmini120.h b/firmware/export/config-gmini120.h
index 42424bb..66ba7af 100644
--- a/firmware/export/config-gmini120.h
+++ b/firmware/export/config-gmini120.h
@@ -54,8 +54,8 @@
 #define BATTERY_SCALE_FACTOR 6465
 /* chosen values at random -- jyp */
 
-/* Define this if the platform can charge batteries */
-#define HAVE_CHARGING 1
+/* Hardware controlled charging? FIXME */
+#define CONFIG_CHARGING CHARGING_SIMPLE
 
 #define CPU_FREQ 30000000
 /* approximate value (and false in general since freq is variable) */
diff --git a/firmware/export/config-gminisp.h b/firmware/export/config-gminisp.h
index e066661..8df7b0f 100644
--- a/firmware/export/config-gminisp.h
+++ b/firmware/export/config-gminisp.h
@@ -45,8 +45,8 @@
 #define BATTERY_SCALE_FACTOR 6465
 /* chosen values at random -- jyp */
 
-/* Define this if the platform can charge batteries */
-#define HAVE_CHARGING 1
+/* Hardware controlled charging? FIXME */
+#define CONFIG_CHARGING CHARGING_SIMPLE
 
 #define CPU_FREQ 30000000
 /* approximate value (and false in general since freq is variable) */
diff --git a/firmware/export/config-h100.h b/firmware/export/config-h100.h
index d53adce..4461cc2 100644
--- a/firmware/export/config-h100.h
+++ b/firmware/export/config-h100.h
@@ -89,11 +89,9 @@
 #define BATTERY_TYPES_COUNT  1    /* only one type */
 #define BATTERY_SCALE_FACTOR 16665 /* FIX: this value is picked at random */
 
-/* Define this if the platform can charge batteries */
-#define HAVE_CHARGING 1
-
-/* For units with a hardware charger that reports charge state */
-#define HAVE_CHARGE_STATE 1
+/* Hardware controlled charging */
+//#define CONFIG_CHARGING CHARGING_SIMPLE
+#define CONFIG_CHARGING CHARGING_MONITOR /* FIXME: remove that once monitoring is fixed properly */
 
 /* define this if the hardware can be powered off while charging */
 #define HAVE_POWEROFF_WHILE_CHARGING
diff --git a/firmware/export/config-h120.h b/firmware/export/config-h120.h
index 34f5059..f2cd8c2 100644
--- a/firmware/export/config-h120.h
+++ b/firmware/export/config-h120.h
@@ -84,11 +84,9 @@
 /* Define if we have a hardware defect that causes ticking on the audio line */
 #define HAVE_REMOTE_LCD_TICKING
 
-/* Define this if the platform can charge batteries */
-#define HAVE_CHARGING 1
-
-/* For units with a hardware charger that reports charge state */
-#define HAVE_CHARGE_STATE 1
+/* Hardware controlled charging */
+//#define CONFIG_CHARGING CHARGING_SIMPLE
+#define CONFIG_CHARGING CHARGING_MONITOR /* FIXME: remove that once monitoring is fixed properly */
 
 /* define this if the hardware can be powered off while charging */
 #define HAVE_POWEROFF_WHILE_CHARGING
diff --git a/firmware/export/config-h300.h b/firmware/export/config-h300.h
index ae1940c..7ed5495 100644
--- a/firmware/export/config-h300.h
+++ b/firmware/export/config-h300.h
@@ -85,14 +85,8 @@
 /* Define if we have a hardware defect that causes ticking on the audio line */
 #define HAVE_REMOTE_LCD_TICKING
 
-/* Define this if the platform can charge batteries */
-#define HAVE_CHARGING 1
-
-/* For units with a hardware charger that reports charge state */
-#define HAVE_CHARGE_STATE 1
-
-/* define this if the hardware can be powered off while charging */
-#define HAVE_POWEROFF_WHILE_CHARGING
+/* Hardware controlled charging with monitoring */
+#define CONFIG_CHARGING CHARGING_MONITOR
 
 /* The size of the flash ROM */
 #define FLASH_SIZE 0x400000
diff --git a/firmware/export/config-iaudiox5.h b/firmware/export/config-iaudiox5.h
index 4690feb..b16a142 100644
--- a/firmware/export/config-iaudiox5.h
+++ b/firmware/export/config-iaudiox5.h
@@ -65,8 +65,8 @@
 
 #define HAVE_TLV320
 
-/* Define this if the platform can charge batteries */
-#define HAVE_CHARGING 1
+/* Hardware controlled charging? FIXME */
+#define CONFIG_CHARGING CHARGING_SIMPLE
 
 /* define this if the hardware can be powered off while charging */
 #define HAVE_POWEROFF_WHILE_CHARGING
diff --git a/firmware/export/config-ifp7xx.h b/firmware/export/config-ifp7xx.h
index 9e5a432..6247625 100644
--- a/firmware/export/config-ifp7xx.h
+++ b/firmware/export/config-ifp7xx.h
@@ -56,8 +56,8 @@
 
 #define BATTERY_SCALE_FACTOR 16665 /* FIX: this value is picked at random */
 
-/* Define this if the platform can charge batteries */
-//#define HAVE_CHARGING 1
+/* Hardware controlled charging? FIXME */
+//#define CONFIG_CHARGING CHARGING_SIMPLE
 
 /* define this if the hardware can be powered off while charging */
 //#define HAVE_POWEROFF_WHILE_CHARGING
diff --git a/firmware/export/config-ipod3g.h b/firmware/export/config-ipod3g.h
index a611dfd..b3b5d14 100644
--- a/firmware/export/config-ipod3g.h
+++ b/firmware/export/config-ipod3g.h
@@ -68,8 +68,8 @@
 #define BATTERY_TYPES_COUNT  1    /* only one type */
 #define BATTERY_SCALE_FACTOR 5865
 
-/* Define this if the platform can charge batteries */
-//#define HAVE_CHARGING 1
+/* Hardware controlled charging? FIXME */
+//#define CONFIG_CHARGING CHARGING_SIMPLE
 
 /* define this if the hardware can be powered off while charging */
 //#define HAVE_POWEROFF_WHILE_CHARGING
diff --git a/firmware/export/config-ipod4g.h b/firmware/export/config-ipod4g.h
index fa664ac..46abbdf 100644
--- a/firmware/export/config-ipod4g.h
+++ b/firmware/export/config-ipod4g.h
@@ -70,8 +70,8 @@
 #define BATTERY_TYPES_COUNT  1    /* only one type */
 #define BATTERY_SCALE_FACTOR 5865
 
-/* Define this if the platform can charge batteries */
-//#define HAVE_CHARGING 1
+/* Hardware controlled charging? FIXME */
+//#define CONFIG_CHARGING CHARGING_SIMPLE
 
 /* define this if the hardware can be powered off while charging */
 //#define HAVE_POWEROFF_WHILE_CHARGING
diff --git a/firmware/export/config-ipodcolor.h b/firmware/export/config-ipodcolor.h
index b8f3d89..e063e93 100644
--- a/firmware/export/config-ipodcolor.h
+++ b/firmware/export/config-ipodcolor.h
@@ -69,8 +69,8 @@
 #define BATTERY_TYPES_COUNT  1    /* only one type */
 #define BATTERY_SCALE_FACTOR 5865
 
-/* Define this if the platform can charge batteries */
-//#define HAVE_CHARGING 1
+/* Hardware controlled charging? FIXME */
+//#define CONFIG_CHARGING CHARGING_SIMPLE
 
 /* define this if the hardware can be powered off while charging */
 //#define HAVE_POWEROFF_WHILE_CHARGING
diff --git a/firmware/export/config-ipodmini.h b/firmware/export/config-ipodmini.h
index 64be801..4871ea0 100644
--- a/firmware/export/config-ipodmini.h
+++ b/firmware/export/config-ipodmini.h
@@ -70,8 +70,8 @@
 #define BATTERY_TYPES_COUNT  1   /* only one type */
 #define BATTERY_SCALE_FACTOR 5865
 
-/* Define this if the platform can charge batteries */
-//#define HAVE_CHARGING 1
+/* Hardware controlled charging? FIXME */
+//#define CONFIG_CHARGING CHARGING_SIMPLE
 
 /* define this if the hardware can be powered off while charging */
 //#define HAVE_POWEROFF_WHILE_CHARGING
diff --git a/firmware/export/config-ipodmini2g.h b/firmware/export/config-ipodmini2g.h
index 454309a..adbb097 100755
--- a/firmware/export/config-ipodmini2g.h
+++ b/firmware/export/config-ipodmini2g.h
@@ -73,8 +73,8 @@
 #define BATTERY_TYPES_COUNT  1   /* only one type */
 #define BATTERY_SCALE_FACTOR 5865
 
-/* Define this if the platform can charge batteries */
-//#define HAVE_CHARGING 1
+/* Hardware controlled charging? FIXME */
+//#define CONFIG_CHARGING CHARGING_SIMPLE
 
 /* define this if the hardware can be powered off while charging */
 //#define HAVE_POWEROFF_WHILE_CHARGING
diff --git a/firmware/export/config-ipodnano.h b/firmware/export/config-ipodnano.h
index b7116bf..3d4deb3 100644
--- a/firmware/export/config-ipodnano.h
+++ b/firmware/export/config-ipodnano.h
@@ -74,8 +74,8 @@
 #define BATTERY_TYPES_COUNT  1    /* only one type */
 #define BATTERY_SCALE_FACTOR 5865
 
-/* Define this if the platform can charge batteries */
-//#define HAVE_CHARGING 1
+/* Hardware controlled charging? FIXME */
+//#define CONFIG_CHARGING CHARGING_SIMPLE
 
 /* define this if the hardware can be powered off while charging */
 //#define HAVE_POWEROFF_WHILE_CHARGING
diff --git a/firmware/export/config-ipodvideo.h b/firmware/export/config-ipodvideo.h
index 1bbcfec..79ef1a8 100644
--- a/firmware/export/config-ipodvideo.h
+++ b/firmware/export/config-ipodvideo.h
@@ -74,14 +74,12 @@
 #define BATTERY_TYPES_COUNT  1    /* only one type */
 #define BATTERY_SCALE_FACTOR 5865
 
-/* Define this if the platform can charge batteries */
-#define HAVE_CHARGING 1
+/* Hardware controlled charging with monitoring */
+#define CONFIG_CHARGING CHARGING_MONITOR
 
 /* define this if the hardware can be powered off while charging */
 //#define HAVE_POWEROFF_WHILE_CHARGING
 
-#define HAVE_CHARGE_STATE 1
-
 /* The start address index for ROM builds */
 #define ROM_START 0x00000000
 
diff --git a/firmware/export/config-player.h b/firmware/export/config-player.h
index 324a0a2..3dfdb0e 100644
--- a/firmware/export/config-player.h
+++ b/firmware/export/config-player.h
@@ -67,8 +67,8 @@
 /* How to detect USB */
 #define USB_PLAYERSTYLE 1
 
-/* Define this if the platform can charge batteries */
-#define HAVE_CHARGING 1
+/* Hardware controlled charging */
+#define CONFIG_CHARGING CHARGING_SIMPLE
 
 /* The start address index for ROM builds */
 /* #define ROM_START 0xD010 for behind original Archos */
diff --git a/firmware/export/config-recorder.h b/firmware/export/config-recorder.h
index 92dd076..854b1c1 100644
--- a/firmware/export/config-recorder.h
+++ b/firmware/export/config-recorder.h
@@ -45,9 +45,6 @@
 /* Define this if you have a SH7034 */
 #define CONFIG_CPU SH7034
 
-/* Define this if you have charging control */
-#define HAVE_CHARGE_CTRL
-
 /* Define this if you have ATA power-off control */
 #define HAVE_ATA_POWER_OFF
 
@@ -80,8 +77,8 @@
 /* How to detect USB */
 #define USB_RECORDERSTYLE 1
 
-/* Define this if the platform can charge batteries */
-#define HAVE_CHARGING 1
+/* Software controlled charging */
+#define CONFIG_CHARGING CHARGING_CONTROL
 
 /* The start address index for ROM builds */
 /* #define ROM_START 0x11010 for behind original Archos */
diff --git a/firmware/export/config-recorderv2.h b/firmware/export/config-recorderv2.h
index b508836..09823cf 100644
--- a/firmware/export/config-recorderv2.h
+++ b/firmware/export/config-recorderv2.h
@@ -90,8 +90,8 @@
 /* How to detect USB */
 #define USB_FMRECORDERSTYLE 1
 
-/* Define this if the platform can charge batteries */
-#define HAVE_CHARGING 1
+/* Hardware controlled charging with monitoring */
+#define CONFIG_CHARGING CHARGING_MONITOR
 
 /* The start address index for ROM builds */
 /* #define ROM_START 0x12010 for behind original Archos */
diff --git a/firmware/export/config.h b/firmware/export/config.h
index d919b8b..910aeca 100644
--- a/firmware/export/config.h
+++ b/firmware/export/config.h
@@ -68,6 +68,11 @@
 #define BATT_3AAA       1000 /* Ondio */
 #define BATT_LIPOL1300  1300 /* the type used in iRiver h1x0 models */
 
+/* CONFIG_CHARGING */
+#define CHARGING_SIMPLE  1 /* Simple, hardware controlled charging */
+#define CHARGING_MONITOR 2 /* Hardware controlled charging with monitoring */
+#define CHARGING_CONTROL 3 /* Software controlled charging */
+
 /* CONFIG_LCD */
 #define LCD_GMINI100  0
 #define LCD_SSD1815   1 /* as used by Archos Recorders and Ondios */
diff --git a/firmware/export/power.h b/firmware/export/power.h
index be8ebda..dc6c09d 100644
--- a/firmware/export/power.h
+++ b/firmware/export/power.h
@@ -19,12 +19,12 @@
 #ifndef _POWER_H_
 #define _POWER_H_
 
-#ifdef HAVE_CHARGE_CTRL
+#if CONFIG_CHARGING == CHARGING_CONTROL
 extern bool charger_enabled;
 void charger_enable(bool on);
 #endif
 
-#ifdef HAVE_CHARGING
+#ifdef CONFIG_CHARGING
 bool charger_inserted(void);
 #endif
 
@@ -35,7 +35,7 @@
 
 void power_init(void);
 
-# ifdef HAVE_CHARGE_STATE
+# if CONFIG_CHARGING == CHARGING_MONITOR
 bool charging_state(void);
 # endif
 
diff --git a/firmware/export/powermgmt.h b/firmware/export/powermgmt.h
index 6c31aee..30fe60c 100644
--- a/firmware/export/powermgmt.h
+++ b/firmware/export/powermgmt.h
@@ -28,7 +28,7 @@
 
 #ifndef SIMULATOR
 
-#ifdef HAVE_CHARGE_CTRL
+#if CONFIG_CHARGING == CHARGING_CONTROL
 #define START_TOPOFF_CHG    85  /* Battery % to start at top-off */
 #define START_TRICKLE_CHG   95  /* Battery % to start at trickle */
 
@@ -59,23 +59,21 @@
 extern int pid_i;                /* PID integral term */
 extern int trickle_sec;          /* trickle charge: How many seconds per minute are we charging actually? */
 
-#endif /* HAVE_CHARGE_CTRL */
+#endif /* CONFIG_CHARGING == CHARGING_CONTROL */
 
-#if defined(HAVE_CHARGE_CTRL) || \
-    (CONFIG_BATTERY == BATT_LIION2200) || \
-    defined(HAVE_CHARGE_STATE)
-typedef enum {
-    DISCHARGING,
-    CHARGING,
-    TOPOFF,
-    TRICKLE
+#if CONFIG_CHARGING >= CHARGING_MONITOR
+typedef enum {       /* sorted by increasing charging current */
+    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 */
 } charge_state_type;
 
 /* tells what the charger is doing */
 extern charge_state_type charge_state;
-#endif /* defined(HAVE_CHARGE_CTRL) || (CONFIG_BATTERY == BATT_LIION2200) */
+#endif /* CONFIG_CHARGING >= CHARGING_MONITOR */
 
-#ifdef HAVE_CHARGING
+#ifdef CONFIG_CHARGING
 /*
  * Flag that the charger has been plugged in/removed: this is set for exactly
  * one time through the power loop when the charger has been plugged in.
diff --git a/firmware/powermgmt.c b/firmware/powermgmt.c
index 15977ca..ee01fd8 100644
--- a/firmware/powermgmt.c
+++ b/firmware/powermgmt.c
@@ -64,7 +64,7 @@
  * in it (one sample per minute).  This is only for very low level debug.
  */
 #undef  DEBUG_FILE
-#if defined(DEBUG_FILE) && defined(HAVE_CHARGE_CTRL)
+#if defined(DEBUG_FILE) && (CONFIG_CHARGING == CHARGING_CONTROL)
 #include "file.h"
 #define DEBUG_FILE_NAME   "/powermgmt.csv"
 #define DEBUG_MESSAGE_LEN 133
@@ -190,7 +190,7 @@
 #endif
 };
 
-#ifdef HAVE_CHARGING
+#ifdef CONFIG_CHARGING
 charger_input_state_type charger_input_state IDATA_ATTR;
 
 /* voltages (centivolt) of 0%, 10%, ... 100% when charging enabled */
@@ -207,15 +207,13 @@
     476, 544, 551, 556, 561, 564, 566, 576, 582, 584, 585 /* NiMH */
 #endif
 };
-#endif /* HAVE_CHARGING */
+#endif /* CONFIG_CHARGING */
 
-#if defined(HAVE_CHARGE_CTRL) || \
-    CONFIG_BATTERY == BATT_LIION2200 || \
-    defined(HAVE_CHARGE_STATE)
+#if CONFIG_CHARGING >= CHARGING_MONITOR
 charge_state_type charge_state;     /* charging mode */
 #endif
 
-#ifdef HAVE_CHARGE_CTRL
+#if CONFIG_CHARGING == CHARGING_CONTROL
 int long_delta;                     /* long term delta battery voltage */
 int short_delta;                    /* short term delta battery voltage */
 bool disk_activity_last_cycle = false;         /* flag set to aid charger time
@@ -235,7 +233,7 @@
                                                   charging? */
 int pid_p = 0;                      /* PID proportional term */
 int pid_i = 0;                      /* PID integral term */
-#endif /* HAVE_CHARGE_CTRL */
+#endif /* CONFIG_CHARGING == CHARGING_CONTROL */
 
 /*
  * Average battery voltage and charger voltage, filtered via a digital
@@ -366,7 +364,7 @@
 {
     int level;
 
-#if defined(HAVE_CHARGE_CTRL) || defined(HAVE_CHARGE_STATE)
+#if CONFIG_CHARGING >= CHARGING_MONITOR
     if (charge_state == DISCHARGING) {
         level = voltage_to_percent(battery_centivolts,
                 percent_to_volt_discharge[battery_type]);
@@ -397,7 +395,7 @@
     /* calculate estimated remaining running time */
     /* discharging: remaining running time */
     /* charging:    remaining charging time */
-#if defined(HAVE_CHARGE_CTRL) || defined(HAVE_CHARGE_STATE)
+#if CONFIG_CHARGING >= CHARGING_MONITOR
     if (charge_state == CHARGING) {
         powermgmt_est_runningtime_min = (100 - level) * battery_capacity / 100
                                       * 60 / (CURRENT_MAX_CHG - runcurrent());
@@ -425,7 +423,7 @@
     long timeout = poweroff_idle_timeout_value[poweroff_timeout]*60*HZ;
     int  audio_stat = audio_status();
 
-#ifdef HAVE_CHARGING
+#ifdef CONFIG_CHARGING
     /*
      * Inhibit shutdown as long as the charger is plugged in.  If it is
      * unplugged, wait for a timeout period and then shut down.
@@ -458,7 +456,7 @@
             if(TIME_AFTER(current_tick, sleeptimer_endtick))
             {
                 audio_stop();
-#if defined(HAVE_CHARGING) && !defined(HAVE_POWEROFF_WHILE_CHARGING)
+#if defined(CONFIG_CHARGING) && !defined(HAVE_POWEROFF_WHILE_CHARGING)
                 if((charger_input_state == CHARGER) ||
                    (charger_input_state == CHARGER_PLUGGED))
                 {
@@ -538,7 +536,7 @@
 
     while (ticks > 0) {
 
-#ifdef HAVE_CHARGING
+#ifdef CONFIG_CHARGING
         /*
          * Detect charger plugged/unplugged transitions.  On a plugged or
          * unplugged event, we return immediately, run once through the main
@@ -577,7 +575,7 @@
             }
         }
 #endif
-#ifdef HAVE_CHARGE_STATE
+#if CONFIG_CHARGING == CHARGING_MONITOR
         switch (charger_input_state) {
             case CHARGER_UNPLUGGED:
             case NO_CHARGER:
@@ -593,7 +591,7 @@
                 break;
         }
 
-#endif /* HAVE_CHARGE_STATE */
+#endif /* CONFIG_CHARGING == CHARGING_MONITOR */
 
         small_ticks = MIN(HZ/2, ticks);
         sleep(small_ticks);
@@ -628,13 +626,13 @@
             battery_status_update();
 
         }
-#ifdef HAVE_CHARGE_CTRL
+#if CONFIG_CHARGING == CHARGING_CONTROL
         if (ata_disk_is_active()) {
             /* flag hdd use for charging calculation */
             disk_activity_last_cycle = true;
         }
 #endif
-#if defined(DEBUG_FILE) && defined(HAVE_CHARGE_CTRL)
+#if defined(DEBUG_FILE) && (CONFIG_CHARGING == CHARGING_CONTROL)
         /*
          * If we have a lot of pending writes or if the disk is spining,
          * fsync the debug log file.
@@ -660,7 +658,7 @@
 {
     int i;
     short *phps, *phpd;         /* power history rotation pointers */
-#ifdef HAVE_CHARGE_CTRL
+#if CONFIG_CHARGING == CHARGING_CONTROL
     unsigned int target_voltage = TRICKLE_VOLTAGE;    /* desired topoff/trickle
                                        * voltage level */
     int charge_max_time_idle = 0;     /* max. charging duration, calculated at
@@ -678,7 +676,7 @@
         BATT_AVE_SAMPLES;
     battery_centivolts = avgbat / BATT_AVE_SAMPLES / 10000;
 
-#if defined(DEBUG_FILE) && defined(HAVE_CHARGE_CTRL)
+#if defined(DEBUG_FILE) && (CONFIG_CHARGING == CHARGING_CONTROL)
     fd      = -1;
     wrcount = 0;
 #endif
@@ -694,25 +692,7 @@
         /* insert new value at the start, in centivolts 8-) */
         power_history[0] = battery_centivolts;
 
-#if CONFIG_BATTERY == BATT_LIION2200
-        /* We use the information from the ADC_EXT_POWER ADC channel, which
-           tells us the charging current from the LTC1734. When DC is
-           connected (either via the external adapter, or via USB), we try
-           to determine if it is actively charging or only maintaining the
-           charge. My tests show that ADC readings below about 0x80 means
-           that the LTC1734 is only maintaining the charge. */
-        if(charger_inserted()) {
-            if(adc_read(ADC_EXT_POWER) < 0x80) {
-                charge_state = TRICKLE;
-            } else {
-                charge_state = CHARGING;
-            }
-        } else {
-            charge_state = DISCHARGING;
-        }
-#endif /* # if CONFIG_BATTERY == BATT_LIION2200 */
-
-#ifdef HAVE_CHARGE_CTRL
+#if CONFIG_CHARGING == CHARGING_CONTROL
         if (charger_input_state == CHARGER_PLUGGED) {
             pid_p = 0;
             pid_i = 0;
@@ -876,7 +856,7 @@
                 }
             }
         }
-        else if (charge_state > CHARGING)  /* top off or trickle */
+        else if (charge_state != DISCHARGING)  /* top off or trickle */
         {
             /*
              *Time to switch from topoff to trickle?
@@ -946,11 +926,11 @@
             snprintf(power_message, POWER_MESSAGE_LEN, "Charger: discharge");
         }
 
-#endif /* end HAVE_CHARGE_CTRL */
+#endif /* CONFIG_CHARGING == CHARGING_CONTROL */
 
         /* sleep for a minute */
 
-#ifdef HAVE_CHARGE_CTRL
+#if CONFIG_CHARGING == CHARGING_CONTROL
         if(trickle_sec > 0) {
             charger_enable(true);
             power_thread_sleep(HZ * trickle_sec);
@@ -962,7 +942,7 @@
         power_thread_sleep(HZ * 60);
 #endif
 
-#if defined(DEBUG_FILE) && defined(HAVE_CHARGE_CTRL)
+#if defined(DEBUG_FILE) && (CONFIG_CHARGING == CHARGING_CONTROL)
         if(usb_inserted()) {
             if(fd >= 0) {
                 /* It is probably too late to close the file but we can try...*/
@@ -992,7 +972,7 @@
 #endif
         handle_auto_poweroff();
 
-#ifdef HAVE_CHARGE_CTRL
+#if CONFIG_CHARGING == CHARGING_CONTROL
         powermgmt_last_cycle_startstop_min++;
 #endif
     }
@@ -1029,7 +1009,7 @@
 void shutdown_hw(void)
 {
 #ifndef SIMULATOR
-#if defined(DEBUG_FILE) && defined(HAVE_CHARGE_CTRL)
+#if defined(DEBUG_FILE) && (CONFIG_CHARGING == CHARGING_CONTROL)
     if(fd >= 0) {
         close(fd);
         fd = -1;
diff --git a/flash/bootbox/main.c b/flash/bootbox/main.c
index ef215c0..4f5efdd 100644
--- a/flash/bootbox/main.c
+++ b/flash/bootbox/main.c
@@ -65,7 +65,7 @@
     return 0;
 }
 
-#ifdef HAVE_CHARGING
+#ifdef CONFIG_CHARGING
 /*
 bool backlight_get_on_when_charging(void)
 {
@@ -83,12 +83,12 @@
 
     do
     {
-#ifdef HAVE_CHARGE_CTRL
-        if (charge_state == 1)
+#if CONFIG_CHARGING == CHARGING_CONTROL
+        if (charge_state == CHARGING)
             msg = "charging";
-        else if (charge_state == 2)
+        else if (charge_state == TOPOFF)
             msg = "topoff charge";
-        else if (charge_state == 3)
+        else if (charge_state == TRICKLE)
             msg = "trickle charge";
         else
             msg = "not charging";
@@ -130,7 +130,7 @@
         }
     } while (1);
 }
-#endif /* HAVE_CHARGING */
+#endif /* CONFIG_CHARGING */
 
 /* prompt user to plug USB and fix a problem */
 void prompt_usb(const char* msg1, const char* msg2)
@@ -172,7 +172,7 @@
     button_init();
     powermgmt_init();
 
-#if defined(HAVE_CHARGING) && (CONFIG_CPU == SH7034)
+#if defined(CONFIG_CHARGING) && (CONFIG_CPU == SH7034)
     if (charger_inserted()
 #ifdef ATA_POWER_PLAYERSTYLE
         && !ide_powered() /* relies on probing result from bootloader */