Backlight handling: * Added 'Caption Backlight' and 'Backlight On When Charging' for the iriver remote LCD. * Enabled the backlight code for the simulator, and prepared backlight simulation. It's only a stub atm, writing messages to the console window. * Added tick task handling to the simulators for this to work. * Code cleanup in backlight.c, less dead code.


git-svn-id: svn://svn.rockbox.org/rockbox/trunk@8034 a1c6a512-1295-4272-9138-f99709370657
diff --git a/apps/gui/gwps-common.c b/apps/gui/gwps-common.c
index c2a4dff..16f3a6f 100644
--- a/apps/gui/gwps-common.c
+++ b/apps/gui/gwps-common.c
@@ -1612,12 +1612,12 @@
     data->peak_meter_enabled = enable_pm;
 #endif
 
-#if defined(CONFIG_BACKLIGHT) && !defined(SIMULATOR)
+#ifdef CONFIG_BACKLIGHT
     if (global_settings.caption_backlight && state->id3) {
         /* turn on backlight n seconds before track ends, and turn it off n
            seconds into the new track. n == backlight_timeout, or 5s */
-        int n =
-            backlight_timeout_value[global_settings.backlight_timeout] * 1000;
+        int n = backlight_timeout_value[global_settings.backlight_timeout] 
+              * 1000;
 
         if ( n < 1000 )
             n = 5000; /* use 5s if backlight is always on or off */
@@ -1627,6 +1627,22 @@
             backlight_on();
     }
 #endif
+#ifdef HAVE_REMOTE_LCD
+    if (global_settings.remote_caption_backlight && state->id3) {
+        /* turn on remote backlight n seconds before track ends, and turn it
+           off n seconds into the new track. n == remote_backlight_timeout,
+           or 5s */
+        int n = backlight_timeout_value[global_settings.remote_backlight_timeout]
+              * 1000;
+
+        if ( n < 1000 )
+            n = 5000; /* use 5s if backlight is always on or off */
+
+        if ((state->id3->elapsed < 1000) ||
+            ((state->id3->length - state->id3->elapsed) < (unsigned)n))
+            remote_backlight_on();
+    }
+#endif
     return true;
 }
 
diff --git a/apps/main.c b/apps/main.c
index 9afb3e9..7472eb4 100644
--- a/apps/main.c
+++ b/apps/main.c
@@ -147,6 +147,8 @@
 #endif
     font_init();
     show_logo();
+    button_init();
+    backlight_init();
     lang_init();
     /* Must be done before any code uses the multi-screen APi */
     screen_access_init();
diff --git a/apps/plugin.c b/apps/plugin.c
index d5607aa..7d92998 100644
--- a/apps/plugin.c
+++ b/apps/plugin.c
@@ -169,8 +169,8 @@
     lcd_remote_update,
     lcd_remote_update_rect,
 
-    lcd_remote_backlight_on,
-    lcd_remote_backlight_off,
+    remote_backlight_on,
+    remote_backlight_off,
 #endif
     /* button */
     button_get,
diff --git a/apps/settings.c b/apps/settings.c
index 7d68dae..939d488 100644
--- a/apps/settings.c
+++ b/apps/settings.c
@@ -277,9 +277,15 @@
     {1, S_O(bidi_support), false, "bidi hebrew/arabic", off_on },
 #endif
 
-#ifdef HAVE_REMOTE_LCD_TICKING /* move to REMOTE_LCD next time we bump version */
+#ifdef HAVE_REMOTE_LCD   /* move to REMOTE_LCD next time we bump version */
+#ifdef HAVE_REMOTE_LCD_TICKING
     {1, S_O(remote_reduce_ticking), false, "remote reduce ticking", off_on },
 #endif
+#ifdef HAVE_CHARGING
+    {1, S_O(remote_backlight_on_when_charging), false,
+        "remote backlight when plugged", off_on },
+#endif
+#endif
 
     /* new stuff to be added here */
     /* If values are just added to the end, no need to bump the version. */
@@ -475,6 +481,10 @@
     {8|SIGNED, S_O(rec_adc_right_gain), 0, /* 0dB */   "adc right gain", NULL }, /* -128...48 */
 #endif
 
+#ifdef HAVE_REMOTE_LCD
+    {1, S_O(remote_caption_backlight), false, 
+        "remote caption backlight", off_on },
+#endif
     /* If values are just added to the end, no need to bump the version. */
     /* new stuff to be added at the end */
 
@@ -862,12 +872,16 @@
 #endif
     remote_backlight_set_timeout(global_settings.remote_backlight_timeout);
 #endif
+#ifdef CONFIG_BACKLIGHT
     backlight_set_timeout(global_settings.backlight_timeout);
+#ifdef HAVE_CHARGING
     backlight_set_on_when_charging(global_settings.backlight_on_when_charging);
-#if CONFIG_BACKLIGHT == BL_IRIVER_H100
+#endif
+#if (CONFIG_BACKLIGHT == BL_IRIVER_H100) && !defined(SIMULATOR)
     backlight_set_fade_in(global_settings.backlight_fade_in);
     backlight_set_fade_out(global_settings.backlight_fade_out);
 #endif
+#endif
     ata_spindown(global_settings.disk_spindown);
 #if (CONFIG_CODEC == MAS3507D) && !defined(SIMULATOR)
     dac_line_in(global_settings.line_in);
diff --git a/apps/settings.h b/apps/settings.h
index a4401f8..689dffc 100644
--- a/apps/settings.h
+++ b/apps/settings.h
@@ -343,7 +343,9 @@
     int remote_backlight_timeout;  /* backlight off timeout:  0-18 0=never,
                                1=always,
                                then according to timeout_values[] */
-#ifdef HAVE_REMOTE_LCD_TICKING    
+    bool remote_backlight_on_when_charging;
+    bool remote_caption_backlight; /* turn on backlight at end and start of track */
+#ifdef HAVE_REMOTE_LCD_TICKING
     bool remote_reduce_ticking; /* 0=normal operation,
                                    1=EMI reduce on with cost more CPU. */
 #endif
diff --git a/apps/settings_menu.c b/apps/settings_menu.c
index fc54436..5230dd2 100644
--- a/apps/settings_menu.c
+++ b/apps/settings_menu.c
@@ -137,10 +137,8 @@
 #ifdef CONFIG_BACKLIGHT
 static bool caption_backlight(void)
 {
-    bool rc = set_bool( str(LANG_CAPTION_BACKLIGHT),
-                        &global_settings.caption_backlight);
-
-    return rc;
+    return set_bool( str(LANG_CAPTION_BACKLIGHT),
+                     &global_settings.caption_backlight);
 }
 
 #ifdef HAVE_CHARGING
@@ -180,7 +178,7 @@
                       INT, names, 19, backlight_set_timeout );
 }
 
-#if CONFIG_BACKLIGHT == BL_IRIVER_H100
+#if (CONFIG_BACKLIGHT == BL_IRIVER_H100) && !defined(SIMULATOR)
 static bool backlight_fade_in(void)
 {
     static const struct opt_items names[] = {
@@ -242,6 +240,22 @@
                       INT, names, 19, remote_backlight_set_timeout );
 }
 
+#ifdef HAVE_CHARGING
+static bool remote_backlight_on_when_charging(void)
+{
+    bool result = set_bool(str(LANG_BACKLIGHT_ON_WHEN_CHARGING),
+                           &global_settings.remote_backlight_on_when_charging);
+    remote_backlight_set_on_when_charging(
+                     global_settings.remote_backlight_on_when_charging);
+    return result;
+}
+#endif
+
+static bool remote_caption_backlight(void)
+{
+    return set_bool( str(LANG_CAPTION_BACKLIGHT),
+                     &global_settings.remote_caption_backlight);
+}
 #endif /* HAVE_REMOTE_LCD */
 
 static bool contrast(void)
@@ -1521,7 +1535,7 @@
         { ID2P(LANG_BACKLIGHT_ON_WHEN_CHARGING), backlight_on_when_charging },
 #endif
         { ID2P(LANG_CAPTION_BACKLIGHT), caption_backlight },
-#if CONFIG_BACKLIGHT == BL_IRIVER_H100
+#if (CONFIG_BACKLIGHT == BL_IRIVER_H100) && !defined(SIMULATOR)
         { ID2P(LANG_BACKLIGHT_FADE_IN), backlight_fade_in },
         { ID2P(LANG_BACKLIGHT_FADE_OUT), backlight_fade_out },
 #endif
@@ -1549,6 +1563,11 @@
 
     static const struct menu_item items[] = {
         { ID2P(LANG_BACKLIGHT),       remote_backlight_timer },
+#ifdef HAVE_CHARGING
+        { ID2P(LANG_BACKLIGHT_ON_WHEN_CHARGING),
+                               remote_backlight_on_when_charging },
+#endif
+        { ID2P(LANG_CAPTION_BACKLIGHT), remote_caption_backlight },
         { ID2P(LANG_CONTRAST),        remote_contrast },
         { ID2P(LANG_INVERT),          remote_invert },
         { ID2P(LANG_FLIP_DISPLAY),    remote_flip_display },
diff --git a/firmware/SOURCES b/firmware/SOURCES
index e5056c5..aba4e3b 100644
--- a/firmware/SOURCES
+++ b/firmware/SOURCES
@@ -1,9 +1,7 @@
 #ifdef ROCKBOX_HAS_LOGF
 logf.c
 #endif
-#ifndef SIMULATOR
 backlight.c
-#endif
 buffer.c
 common/atoi.c
 common/ctype.c
diff --git a/firmware/backlight.c b/firmware/backlight.c
index 26d0362..9cec4ea 100644
--- a/firmware/backlight.c
+++ b/firmware/backlight.c
@@ -28,6 +28,7 @@
 #include "power.h"
 #include "system.h"
 #include "timer.h"
+#include "backlight.h"
 
 #ifdef HAVE_REMOTE_LCD
 #include "lcd-remote.h"
@@ -51,17 +52,17 @@
 static const char backlight_thread_name[] = "backlight";
 static struct event_queue backlight_queue;
 
-static bool charger_was_inserted = 0;
-static bool backlight_on_when_charging = 0;
-
+static bool backlight_on_when_charging = false;
 static int backlight_timer;
 static unsigned int backlight_timeout = 5;
+
 #ifdef HAVE_REMOTE_LCD
+static bool remote_backlight_on_when_charging = false;
 static int remote_backlight_timer;
 static unsigned int remote_backlight_timeout = 5;
 #endif
 
-#if CONFIG_BACKLIGHT == BL_IRIVER_H100
+#if (CONFIG_BACKLIGHT == BL_IRIVER_H100) && !defined(SIMULATOR)
 /* backlight fading */
 #define BL_PWM_INTERVAL 5000  /* Cycle interval in µs */
 #define BL_PWM_COUNT    100
@@ -191,45 +192,13 @@
 {
     fade_out_count = backlight_fade_value[index];
 }
-#endif
-
-static void __backlight_off(void)
-{
-#if CONFIG_BACKLIGHT == BL_IRIVER_H100
-    if (fade_out_count > 0)
-        backlight_dim(0);
-    else
-    {
-        bl_dim_target = bl_dim_current = 0;
-        or_l(0x00020000, &GPIO1_OUT);
-    }
-#elif CONFIG_BACKLIGHT == BL_IRIVER_H300
-    and_l(~0x00020000, &GPIO1_OUT);
-#elif CONFIG_BACKLIGHT == BL_RTC
-    /* Disable square wave */
-    rtc_write(0x0a, rtc_read(0x0a) & ~0x40);
-#elif CONFIG_BACKLIGHT == BL_PA14_LO /* Player */
-    and_b(~0x40, &PAIORH); /* let it float (up) */
-#elif CONFIG_BACKLIGHT == BL_PA14_HI /* Ondio */
-    and_b(~0x40, &PADRH); /* drive it low */
-#elif CONFIG_BACKLIGHT == BL_GMINI
-    P1 &= ~0x10;
-#elif CONFIG_BACKLIGHT == BL_IPOD4G
-   /* fades backlight off on 4g */
-   outl(inl(0x70000084) & ~0x2000000, 0x70000084);
-   outl(0x80000000, 0x7000a010);
-#elif CONFIG_BACKLIGHT==BL_IPODNANO
-    /* set port B03 off */
-    outl(((0x100 | 0) << 3), 0x6000d824);
-
-    /* set port L07 off */
-    outl(((0x100 | 0) << 7), 0x6000d12c);
-#endif
-}
+#endif /* (CONFIG_BACKLIGHT == BL_IRIVER_H100) && !defined(SIMULATOR) */
 
 static void __backlight_on(void)
 {
-#if CONFIG_BACKLIGHT == BL_IRIVER_H100
+#ifdef SIMULATOR
+    sim_backlight(100);
+#elif CONFIG_BACKLIGHT == BL_IRIVER_H100
     if (fade_in_count > 0)
         backlight_dim(BL_PWM_COUNT);
     else
@@ -264,6 +233,66 @@
 #endif
 }
 
+static void __backlight_off(void)
+{
+#ifdef SIMULATOR
+    sim_backlight(0);
+#elif CONFIG_BACKLIGHT == BL_IRIVER_H100
+    if (fade_out_count > 0)
+        backlight_dim(0);
+    else
+    {
+        bl_dim_target = bl_dim_current = 0;
+        or_l(0x00020000, &GPIO1_OUT);
+    }
+#elif CONFIG_BACKLIGHT == BL_IRIVER_H300
+    and_l(~0x00020000, &GPIO1_OUT);
+#elif CONFIG_BACKLIGHT == BL_RTC
+    /* Disable square wave */
+    rtc_write(0x0a, rtc_read(0x0a) & ~0x40);
+#elif CONFIG_BACKLIGHT == BL_PA14_LO /* Player */
+    and_b(~0x40, &PAIORH); /* let it float (up) */
+#elif CONFIG_BACKLIGHT == BL_PA14_HI /* Ondio */
+    and_b(~0x40, &PADRH); /* drive it low */
+#elif CONFIG_BACKLIGHT == BL_GMINI
+    P1 &= ~0x10;
+#elif CONFIG_BACKLIGHT == BL_IPOD4G
+   /* fades backlight off on 4g */
+   outl(inl(0x70000084) & ~0x2000000, 0x70000084);
+   outl(0x80000000, 0x7000a010);
+#elif CONFIG_BACKLIGHT==BL_IPODNANO
+    /* set port B03 off */
+    outl(((0x100 | 0) << 3), 0x6000d824);
+
+    /* set port L07 off */
+    outl(((0x100 | 0) << 7), 0x6000d12c);
+#endif
+}
+
+#ifdef HAVE_REMOTE_LCD
+static void __remote_backlight_on(void)
+{
+#ifdef SIMULATOR
+    sim_remote_backlight(100);
+#elif defined(IRIVER_H300_SERIES)
+    and_l(~0x00000002, &GPIO1_OUT);
+#else
+    and_l(~0x00000800, &GPIO_OUT);
+#endif
+}
+
+static void __remote_backlight_off(void)
+{
+#ifdef SIMULATOR
+    sim_remote_backlight(0);
+#elif defined(IRIVER_H300_SERIES)
+    or_l(0x00000002, &GPIO1_OUT);
+#else
+    or_l(0x00000800, &GPIO_OUT);
+#endif
+}
+#endif /* HAVE_REMOTE_LCD */
+
 void backlight_thread(void)
 {
     struct event ev;
@@ -275,26 +304,34 @@
         {
 #ifdef HAVE_REMOTE_LCD
             case REMOTE_BACKLIGHT_ON:
-                remote_backlight_timer =
-                    HZ*backlight_timeout_value[remote_backlight_timeout];
+                if( remote_backlight_on_when_charging && charger_inserted() )
+                {
+                    /* Forcing to zero keeps the lights on */
+                    remote_backlight_timer = 0;
+                }
+                else
+                {
+                    remote_backlight_timer =
+                        HZ*backlight_timeout_value[remote_backlight_timeout];
+                }
 
                 /* Backlight == OFF in the setting? */
                 if(remote_backlight_timer < 0)
                 {
                     remote_backlight_timer = 0; /* Disable the timeout */
-                    lcd_remote_backlight_off();
+                    __remote_backlight_off();
                 }
                 else 
                 {
-                    lcd_remote_backlight_on();
+                    __remote_backlight_on();
                 }
                 break;
 
             case REMOTE_BACKLIGHT_OFF:
-                lcd_remote_backlight_off();
+                __remote_backlight_off();
                 break;
                 
-#endif
+#endif /* HAVE_REMOTE_LCD */
             case BACKLIGHT_ON:
                 if( backlight_on_when_charging && charger_inserted() )
                 {
@@ -321,7 +358,7 @@
                 __backlight_off();
                 break;
 
-#if CONFIG_BACKLIGHT == BL_IRIVER_H100
+#if (CONFIG_BACKLIGHT == BL_IRIVER_H100) && !defined(SIMULATOR)
             case BACKLIGHT_UNBOOST_CPU:
                 cpu_boost(false);
                 break;
@@ -340,74 +377,24 @@
     }
 }
 
-void backlight_on(void)
+static void backlight_tick(void)
 {
-    queue_post(&backlight_queue, BACKLIGHT_ON, NULL);
-}
-
-void backlight_off(void)
-{
-    queue_post(&backlight_queue, BACKLIGHT_OFF, NULL);
-}
-
-#ifdef HAVE_REMOTE_LCD
-void remote_backlight_on(void)
-{
-    queue_post(&backlight_queue, REMOTE_BACKLIGHT_ON, NULL);
-}
-
-void remote_backlight_off(void)
-{
-    queue_post(&backlight_queue, REMOTE_BACKLIGHT_OFF, NULL);
-}
-
-void remote_backlight_set_timeout(int index)
-{
-    if((unsigned)index >= sizeof(backlight_timeout_value))
-        /* if given a weird value, use 0 */
-        index=0;
-    remote_backlight_timeout = index; /* index in the backlight_timeout_value table */
-    remote_backlight_on();
-}
-#endif
-
-int backlight_get_timeout(void)
-{
-    return backlight_timeout;
-}
-
-void backlight_set_timeout(int index)
-{
-    if((unsigned)index >= sizeof(backlight_timeout_value))
-        /* if given a weird value, use 0 */
-        index=0;
-    backlight_timeout = index; /* index in the backlight_timeout_value table */
-    backlight_on();
-}
-
-#ifdef HAVE_CHARGE_CTRL
-bool backlight_get_on_when_charging(void)
-{
-    return backlight_on_when_charging;
-}
-#endif
-
-void backlight_set_on_when_charging(bool yesno)
-{
-    backlight_on_when_charging = yesno;
-    backlight_on();
-}
-
-void backlight_tick(void)
-{
+#ifdef HAVE_CHARGING
+    static bool charger_was_inserted = false;
     bool charger_is_inserted = charger_inserted();
-    if( backlight_on_when_charging &&
-        (charger_was_inserted != charger_is_inserted) )
+
+    if( charger_was_inserted != charger_is_inserted )
     {
-        backlight_on();
+        if( backlight_on_when_charging  )
+            backlight_on();
+#ifdef HAVE_REMOTE_LCD
+        if( remote_backlight_on_when_charging  )
+            remote_backlight_on();
+#endif
     }
     charger_was_inserted = charger_is_inserted;
-    
+#endif /* HAVE_CHARGING */
+
     if(backlight_timer)
     {
         backlight_timer--;
@@ -433,8 +420,10 @@
     queue_init(&backlight_queue);
     create_thread(backlight_thread, backlight_stack,
                   sizeof(backlight_stack), backlight_thread_name);
-                  
-#if CONFIG_BACKLIGHT == BL_IRIVER_H100
+    tick_add_task(backlight_tick);
+#ifdef SIMULATOR
+    /* do nothing */
+#elif CONFIG_BACKLIGHT == BL_IRIVER_H100
     or_l(0x00020000, &GPIO1_ENABLE);
     or_l(0x00020000, &GPIO1_FUNCTION);
     and_l(~0x00020000, &GPIO1_OUT);  /* Start with the backlight ON */
@@ -454,22 +443,77 @@
 #endif
 }
 
+void backlight_on(void)
+{
+    queue_post(&backlight_queue, BACKLIGHT_ON, NULL);
+}
+
+void backlight_off(void)
+{
+    queue_post(&backlight_queue, BACKLIGHT_OFF, NULL);
+}
+
+int backlight_get_timeout(void)
+{
+    return backlight_timeout;
+}
+
+void backlight_set_timeout(int index)
+{
+    if((unsigned)index >= sizeof(backlight_timeout_value))
+        /* if given a weird value, use 0 */
+        index=0;
+    backlight_timeout = index; /* index in the backlight_timeout_value table */
+    backlight_on();
+}
+
+#ifdef HAVE_CHARGING
+bool backlight_get_on_when_charging(void)
+{
+    return backlight_on_when_charging;
+}
+
+void backlight_set_on_when_charging(bool yesno)
+{
+    backlight_on_when_charging = yesno;
+    backlight_on();
+}
+#endif
+
+#ifdef HAVE_REMOTE_LCD
+void remote_backlight_on(void)
+{
+    queue_post(&backlight_queue, REMOTE_BACKLIGHT_ON, NULL);
+}
+
+void remote_backlight_off(void)
+{
+    queue_post(&backlight_queue, REMOTE_BACKLIGHT_OFF, NULL);
+}
+
+void remote_backlight_set_timeout(int index)
+{
+    if((unsigned)index >= sizeof(backlight_timeout_value))
+        /* if given a weird value, use 0 */
+        index=0;
+    remote_backlight_timeout = index; /* index in the backlight_timeout_value table */
+    remote_backlight_on();
+}
+
+#ifdef HAVE_CHARGING
+void remote_backlight_set_on_when_charging(bool yesno)
+{
+    remote_backlight_on_when_charging = yesno;
+    remote_backlight_on();
+}
+#endif
+#endif /* HAVE_REMOTE_LCD */
+
 #else /* no backlight, empty dummy functions */
 
-void backlight_init(void)
-{
-#if defined(IRIVER_H300_SERIES) && defined(BOOTLOADER)
-    or_l(0x00020000, &GPIO1_OUT);
-    or_l(0x00020000, &GPIO1_ENABLE);
-    or_l(0x00020000, &GPIO1_FUNCTION);
-#endif
-}
 void backlight_on(void) {}
 void backlight_off(void) {}
-void backlight_tick(void) {}
-int  backlight_get_timeout(void) {return 0;}
 void backlight_set_timeout(int index) {(void)index;}
-void backlight_set_on_when_charging(bool yesno) {(void)yesno;}
 #ifdef HAVE_REMOTE_LCD
 void remote_backlight_on(void) {}
 void remote_backlight_off(void) {}
diff --git a/firmware/drivers/button.c b/firmware/drivers/button.c
index 918705e..c764e13 100644
--- a/firmware/drivers/button.c
+++ b/firmware/drivers/button.c
@@ -181,8 +181,6 @@
         lastbtn = btn & ~(BUTTON_REL | BUTTON_REPEAT);
         tick = 0;
     }
-
-    backlight_tick();
 }
 
 long button_get(bool block)
diff --git a/firmware/drivers/lcd-h100-remote.c b/firmware/drivers/lcd-h100-remote.c
index 02a907d..05e7791 100644
--- a/firmware/drivers/lcd-h100-remote.c
+++ b/firmware/drivers/lcd-h100-remote.c
@@ -122,24 +122,6 @@
 /*** driver routines ***/
 
 #ifndef SIMULATOR
-void lcd_remote_backlight_on(void)
-{
-#ifdef IRIVER_H300_SERIES
-    and_l(~0x00000002, &GPIO1_OUT);
-#else
-    and_l(~0x00000800, &GPIO_OUT);
-#endif
-}
-
-void lcd_remote_backlight_off(void)
-{
-#ifdef IRIVER_H300_SERIES
-    or_l(0x00000002, &GPIO1_OUT);
-#else
-    or_l(0x00000800, &GPIO_OUT);
-#endif
-}
-
 void lcd_remote_write_command(int cmd)
 {
     int i;
diff --git a/firmware/export/backlight.h b/firmware/export/backlight.h
index 6fee2c0..6d3d4d5 100644
--- a/firmware/export/backlight.h
+++ b/firmware/export/backlight.h
@@ -21,24 +21,32 @@
 
 #include "config.h"
 
-void backlight_init(void);
 void backlight_on(void);
 void backlight_off(void);
-void backlight_tick(void);
-int  backlight_get_timeout(void);
 void backlight_set_timeout(int index);
+#ifdef CONFIG_BACKLIGHT
+void backlight_init(void);
+int  backlight_get_timeout(void);
 #if CONFIG_BACKLIGHT == BL_IRIVER_H100
 void backlight_set_fade_in(int index);
 void backlight_set_fade_out(int index);
 #endif
 bool backlight_get_on_when_charging(void);
 void backlight_set_on_when_charging(bool yesno);
-void remote_backlight_on(void);
-void remote_backlight_off(void);
 extern const char backlight_timeout_value[];
-
-#ifdef HAVE_REMOTE_LCD
-void remote_backlight_set_timeout(int index);
+#else
+#define backlight_init()
 #endif
 
+#ifdef HAVE_REMOTE_LCD
+void remote_backlight_on(void);
+void remote_backlight_off(void);
+void remote_backlight_set_timeout(int index);
+void remote_backlight_set_on_when_charging(bool yesno);
+#endif
+
+#ifdef SIMULATOR
+void sim_backlight(int value);
+void sim_remote_backlight(int value);
+#endif
 #endif
diff --git a/firmware/export/config-fmrecorder.h b/firmware/export/config-fmrecorder.h
index ac6f37c..28d8239 100644
--- a/firmware/export/config-fmrecorder.h
+++ b/firmware/export/config-fmrecorder.h
@@ -32,6 +32,9 @@
 /* Define this for S/PDIF input available */
 #define HAVE_SPDIF_IN
 
+/* Define this for LCD backlight available */
+#define CONFIG_BACKLIGHT BL_RTC /* on I2C controlled RTC port */
+
 #ifndef SIMULATOR
 
 /* Define this if you have a SH7034 */
@@ -83,9 +86,6 @@
 /* Software controlled LED */
 #define CONFIG_LED LED_REAL
 
-/* Define this for LCD backlight available */
-#define CONFIG_BACKLIGHT BL_RTC /* on I2C controlled RTC port */
-
 /* define this if the unit can be powered or charged via USB */
 #define HAVE_USB_POWER
 
diff --git a/firmware/export/config-h100.h b/firmware/export/config-h100.h
index ef13380..1327be7 100644
--- a/firmware/export/config-h100.h
+++ b/firmware/export/config-h100.h
@@ -38,6 +38,9 @@
 
 #define CONFIG_LCD LCD_S1D15E06
 
+/* Define this for LCD backlight available */
+#define CONFIG_BACKLIGHT BL_IRIVER_H100 /* port controlled */
+
 /* Define this if you have a software controlled poweroff */
 #define HAVE_SW_POWEROFF
 
@@ -77,9 +80,6 @@
 /* The size of the flash ROM */
 #define FLASH_SIZE 0x200000
 
-/* Define this for LCD backlight available */
-#define CONFIG_BACKLIGHT BL_IRIVER_H100 /* port controlled */
-
 /* Define this to the CPU frequency */
 #define CPU_FREQ      11289600
 
diff --git a/firmware/export/config-h120.h b/firmware/export/config-h120.h
index d67973c..fd001a4 100644
--- a/firmware/export/config-h120.h
+++ b/firmware/export/config-h120.h
@@ -31,6 +31,9 @@
 
 #define CONFIG_LCD LCD_S1D15E06
 
+/* Define this for LCD backlight available */
+#define CONFIG_BACKLIGHT BL_IRIVER_H100 /* port controlled */
+
 /* Define this if you have a software controlled poweroff */
 #define HAVE_SW_POWEROFF
 
@@ -72,9 +75,6 @@
 /* The size of the flash ROM */
 #define FLASH_SIZE 0x200000
 
-/* Define this for LCD backlight available */
-#define CONFIG_BACKLIGHT BL_IRIVER_H100 /* port controlled */
-
 /* Define this to the CPU frequency */
 #define CPU_FREQ      11289600
 
diff --git a/firmware/export/config-h300.h b/firmware/export/config-h300.h
index 256cdea..5524a55 100644
--- a/firmware/export/config-h300.h
+++ b/firmware/export/config-h300.h
@@ -36,6 +36,9 @@
 /* Define this if you have an remote lcd */
 #define HAVE_REMOTE_LCD
 
+/* Define this for LCD backlight available */
+#define CONFIG_BACKLIGHT BL_IRIVER_H300 /* port controlled PWM */
+
 /* Define this if you have a software controlled poweroff */
 #define HAVE_SW_POWEROFF
 
@@ -69,9 +72,6 @@
 /* The size of the flash ROM */
 #define FLASH_SIZE 0x400000
 
-/* Define this for LCD backlight available */
-#define CONFIG_BACKLIGHT BL_IRIVER_H300 /* port controlled PWM */
-
 /* Define this to the CPU frequency */
 #define CPU_FREQ      11289600
 
diff --git a/firmware/export/config-ipodcolor.h b/firmware/export/config-ipodcolor.h
index 0e1637d..c1068b0 100644
--- a/firmware/export/config-ipodcolor.h
+++ b/firmware/export/config-ipodcolor.h
@@ -38,6 +38,9 @@
 /* Define this if you have the WM8975 audio codec */
 #define HAVE_WM8975
 
+/* Define this for LCD backlight available */
+#define CONFIG_BACKLIGHT BL_IPOD4G /* port controlled */
+
 #ifndef SIMULATOR
 
 /* Define this if you have a PortalPlayer PP5020 */
@@ -60,9 +63,6 @@
 /* The start address index for ROM builds */
 #define ROM_START 0x00000000
 
-/* Define this for LCD backlight available */
-#define CONFIG_BACKLIGHT BL_IPOD4G /* port controlled */
-
 /* Define this to the CPU frequency */
 #define CPU_FREQ      11289600
 
diff --git a/firmware/export/config-ipodnano.h b/firmware/export/config-ipodnano.h
index 3423079..99eb67b 100644
--- a/firmware/export/config-ipodnano.h
+++ b/firmware/export/config-ipodnano.h
@@ -38,6 +38,9 @@
 /* Define this if you have the WM8975 audio codec */
 #define HAVE_WM8975
 
+/* Define this for LCD backlight available */
+#define CONFIG_BACKLIGHT BL_IPODNANO /* port controlled */
+
 #ifndef SIMULATOR
 
 /* The Nano actually has a PP5021 - but it's register compatible with 
@@ -62,9 +65,6 @@
 /* The start address index for ROM builds */
 #define ROM_START 0x00000000
 
-/* Define this for LCD backlight available */
-#define CONFIG_BACKLIGHT BL_IPODNANO /* port controlled */
-
 /* Define this to the CPU frequency */
 #define CPU_FREQ      11289600
 
diff --git a/firmware/export/config-player.h b/firmware/export/config-player.h
index e12e223..f3b1bbd 100644
--- a/firmware/export/config-player.h
+++ b/firmware/export/config-player.h
@@ -20,6 +20,9 @@
 /* Define this if you have a DAC3550A */
 #define HAVE_DAC3550A
 
+/* Define this for LCD backlight available */
+#define CONFIG_BACKLIGHT BL_PA14_LO /* port PA14, low active */
+
 #ifndef SIMULATOR
 
 /* Define this if you have a SH7034 */
@@ -70,9 +73,6 @@
 /* Software controlled LED */
 #define CONFIG_LED LED_REAL
 
-/* Define this for LCD backlight available */
-#define CONFIG_BACKLIGHT BL_PA14_LO /* port PA14, low active */
-
 #define CONFIG_LCD LCD_SSD1801
 
 #define BOOTFILE_EXT "mod"
diff --git a/firmware/export/config-recorder.h b/firmware/export/config-recorder.h
index c674b63..32c29b2 100644
--- a/firmware/export/config-recorder.h
+++ b/firmware/export/config-recorder.h
@@ -26,6 +26,9 @@
 /* Define this for S/PDIF input available */
 #define HAVE_SPDIF_IN
 
+/* Define this for LCD backlight available */
+#define CONFIG_BACKLIGHT BL_RTC /* on I2C controlled RTC port */
+
 #ifndef SIMULATOR
 
 /* Define this if you have a SH7034 */
@@ -74,9 +77,6 @@
 /* Software controlled LED */
 #define CONFIG_LED LED_REAL
 
-/* Define this for LCD backlight available */
-#define CONFIG_BACKLIGHT BL_RTC /* on I2C controlled RTC port */
-
 /* Define this for S/PDIF output available */
 #define HAVE_SPDIF_OUT
 
diff --git a/firmware/export/config-recorderv2.h b/firmware/export/config-recorderv2.h
index 1de3217..fbe9981 100644
--- a/firmware/export/config-recorderv2.h
+++ b/firmware/export/config-recorderv2.h
@@ -29,6 +29,9 @@
 /* Define this for S/PDIF input available */
 #define HAVE_SPDIF_IN
 
+/* Define this for LCD backlight available */
+#define CONFIG_BACKLIGHT BL_RTC /* on I2C controlled RTC port */
+
 #ifndef SIMULATOR
 
 /* Define this if you have a SH7034 */
@@ -83,9 +86,6 @@
 /* Software controlled LED */
 #define CONFIG_LED LED_REAL
 
-/* Define this for LCD backlight available */
-#define CONFIG_BACKLIGHT BL_RTC /* on I2C controlled RTC port */
-
 /* define this if the unit can be powered or charged via USB */
 #define HAVE_USB_POWER
 
diff --git a/firmware/export/lcd-remote.h b/firmware/export/lcd-remote.h
index 6d5091f..491e055 100644
--- a/firmware/export/lcd-remote.h
+++ b/firmware/export/lcd-remote.h
@@ -30,8 +30,6 @@
 #define STYLE_INVERT  1
 
 extern void lcd_remote_init(void);
-extern void lcd_remote_backlight_on(void);
-extern void lcd_remote_backlight_off(void);
 extern int  lcd_remote_default_contrast(void);
 extern void lcd_remote_set_contrast(int val);
 extern void lcd_remote_emireduce(bool state);
diff --git a/firmware/powermgmt.c b/firmware/powermgmt.c
index ed3f422..72a9b90 100644
--- a/firmware/powermgmt.c
+++ b/firmware/powermgmt.c
@@ -448,7 +448,7 @@
         current = CURRENT_USB;
     }
 
-#ifndef BOOTLOADER
+#if defined(CONFIG_BACKLIGHT) && !defined(BOOTLOADER)
     if ((backlight_get_timeout() == 1) /* LED always on */
 #ifdef HAVE_CHARGE_CTRL
         || (charger_inserted() && backlight_get_on_when_charging())
@@ -915,13 +915,11 @@
 #elif HAVE_TLV320
     tlv320_close();
 #endif
-#if CONFIG_KEYPAD == ONDIO_PAD
     backlight_off();
-    sleep(1);
     lcd_set_contrast(0);
-#endif
 #ifdef HAVE_REMOTE_LCD
-    lcd_remote_backlight_off();
+    remote_backlight_off();
+    lcd_remote_set_contrast(0);
 #endif
     power_off();
 #endif /* #ifndef SIMULATOR */
diff --git a/uisimulator/common/stubs.c b/uisimulator/common/stubs.c
index 0bbecda..ff66c1f 100644
--- a/uisimulator/common/stubs.c
+++ b/uisimulator/common/stubs.c
@@ -78,21 +78,19 @@
 }
 #endif
 
-/* Generic firmware stubs. */
-void backlight_on(void)
+#ifdef CONFIG_BACKLIGHT
+void sim_backlight(int value)
 {
-  /* we could do something better here! */
+    DEBUGF("backlight: %s\n", (value > 0) ? "on" : "off");
 }
+#endif
 
-void backlight_off(void)
+#ifdef HAVE_REMOTE_LCD
+void sim_remote_backlight(int value)
 {
-  /* we could do something better here! */
+    DEBUGF("remote backlight: %s\n", (value > 0) ? "on" : "off");
 }
-
-void backlight_time(int dummy)
-{
-    (void)dummy;
-}
+#endif
 
 int fat_startsector(void)
 {
@@ -167,21 +165,6 @@
     return false;
 }
 
-void backlight_set_timeout(int index)
-{
-  (void)index;
-}
-
-void backlight_set_on_when_charging(bool beep)
-{
-  (void)beep;
-}
-
-void remote_backlight_set_timeout(int index)
-{
-  (void)index;
-}
-
 int rtc_read(int address)
 {
   time_t now = time(NULL);
diff --git a/uisimulator/win32/button.c b/uisimulator/win32/button.c
index 08ef5e1..47adbb4 100644
--- a/uisimulator/win32/button.c
+++ b/uisimulator/win32/button.c
@@ -202,7 +202,13 @@
                 else
                     queue_post(&button_queue, btn, NULL);
 
-                backlight_on();
+#ifdef HAVE_REMOTE_LCD
+                if(btn & BUTTON_REMOTE)
+                    remote_backlight_on();
+                else
+#endif
+                    backlight_on();
+
             }
         }
         else
diff --git a/uisimulator/win32/kernel.c b/uisimulator/win32/kernel.c
index 8e7bb88..eb55bf7 100644
--- a/uisimulator/win32/kernel.c
+++ b/uisimulator/win32/kernel.c
@@ -22,12 +22,15 @@
 #include "kernel.h"
 #include "thread-win32.h"
 #include "thread.h"
+#include "debug.h"
 
 /* (Daniel 2002-10-31) Mingw32 requires this errno variable to be present.
    I'm not quite sure why and I don't know if this breaks the MSVC compile.
    If it does, we should put this within #ifdef __MINGW32__ */
 int errno;
 
+static void (*tick_funcs[MAX_NUM_TICK_TASKS])(void);
+
 int set_irq_level (int level)
 {
     static int _lv = 0;
@@ -99,6 +102,54 @@
     yield ();
 }
 
+void sim_tick_tasks(void)
+{
+    int i;
+
+    /* Run through the list of tick tasks */
+    for(i = 0;i < MAX_NUM_TICK_TASKS;i++)
+    {
+        if(tick_funcs[i])
+        {
+            tick_funcs[i]();
+        }
+    }
+}
+
+int tick_add_task(void (*f)(void))
+{
+    int i;
+
+    /* Add a task if there is room */
+    for(i = 0;i < MAX_NUM_TICK_TASKS;i++)
+    {
+        if(tick_funcs[i] == NULL)
+        {
+            tick_funcs[i] = f;
+            return 0;
+        }
+    }
+    DEBUGF("Error! tick_add_task(): out of tasks");
+    return -1;
+}
+
+int tick_remove_task(void (*f)(void))
+{
+    int i;
+
+    /* Remove a task if it is there */
+    for(i = 0;i < MAX_NUM_TICK_TASKS;i++)
+    {
+        if(tick_funcs[i] == f)
+        {
+            tick_funcs[i] = NULL;
+            return 0;
+        }
+    }
+    
+    return -1;
+}
+
 /* TODO: Implement mutexes for win32 */
 void mutex_init(struct mutex *m)
 {
diff --git a/uisimulator/win32/uisw32.c b/uisimulator/win32/uisw32.c
index d098c6e..b31eccf 100644
--- a/uisimulator/win32/uisw32.c
+++ b/uisimulator/win32/uisw32.c
@@ -36,7 +36,8 @@
 
 // extern functions
 extern void                 app_main (void *); // mod entry point
-extern void					new_key(int key);
+extern void                 new_key(int key);
+extern void                 sim_tick_tasks(void);
 
 void button_event(int key, bool pressed);
 
@@ -67,12 +68,18 @@
     static HDC hMemDc;
 
     static LARGE_INTEGER    persec, tick1, ticknow;
+    long new_tick;
 
     switch (uMsg)
     {
     case WM_TIMER:
         QueryPerformanceCounter(&ticknow);
-        current_tick = ((ticknow.QuadPart-tick1.QuadPart)*HZ)/persec.QuadPart;
+        new_tick = ((ticknow.QuadPart-tick1.QuadPart)*HZ)/persec.QuadPart;
+        if (new_tick != current_tick)
+        {
+            sim_tick_tasks();
+            current_tick = new_tick;
+        }
         return TRUE;
     case WM_ACTIVATE:
         if (LOWORD(wParam) == WA_ACTIVE || LOWORD(wParam) == WA_CLICKACTIVE)
diff --git a/uisimulator/x11/button-x11.c b/uisimulator/x11/button-x11.c
index b2d8ab6..e037867 100644
--- a/uisimulator/x11/button-x11.c
+++ b/uisimulator/x11/button-x11.c
@@ -21,6 +21,7 @@
 #include "button.h"
 #include "kernel.h"
 #include "debug.h"
+#include "backlight.h"
 #include "misc.h"
 
 #include "X11/keysym.h"
@@ -47,7 +48,7 @@
 /* mostly copied from real button.c */
 void button_read (void);
 
-void button_tick(void)
+static void button_tick(void)
 {
     static int tick = 0;
     static int count = 0;
@@ -117,6 +118,13 @@
                         queue_post(&button_queue, BUTTON_REPEAT | btn, NULL);
                     else
                         queue_post(&button_queue, btn, NULL);
+#ifdef HAVE_REMOTE_LCD
+                    if(btn & BUTTON_REMOTE)
+                        remote_backlight_on();
+                    else
+#endif
+                        backlight_on();
+
                 }
             }
             else
@@ -276,6 +284,7 @@
 
 void button_init(void)
 {
+    tick_add_task(button_tick);
 }
 
 int button_status(void)
diff --git a/uisimulator/x11/kernel.c b/uisimulator/x11/kernel.c
index 7405fec..25f2df2 100644
--- a/uisimulator/x11/kernel.c
+++ b/uisimulator/x11/kernel.c
@@ -17,8 +17,12 @@
  *
  ****************************************************************************/
 
+#include <stddef.h>
 #include "kernel.h"
 #include "thread.h"
+#include "debug.h"
+
+static void (*tick_funcs[MAX_NUM_TICK_TASKS])(void);
 
 int set_irq_level (int level)
 {
@@ -91,6 +95,54 @@
     yield ();
 }
 
+void sim_tick_tasks(void)
+{
+    int i;
+
+    /* Run through the list of tick tasks */
+    for(i = 0;i < MAX_NUM_TICK_TASKS;i++)
+    {
+        if(tick_funcs[i])
+        {
+            tick_funcs[i]();
+        }
+    }
+}
+
+int tick_add_task(void (*f)(void))
+{
+    int i;
+
+    /* Add a task if there is room */
+    for(i = 0;i < MAX_NUM_TICK_TASKS;i++)
+    {
+        if(tick_funcs[i] == NULL)
+        {
+            tick_funcs[i] = f;
+            return 0;
+        }
+    }
+    DEBUGF("Error! tick_add_task(): out of tasks");
+    return -1;
+}
+
+int tick_remove_task(void (*f)(void))
+{
+    int i;
+
+    /* Remove a task if it is there */
+    for(i = 0;i < MAX_NUM_TICK_TASKS;i++)
+    {
+        if(tick_funcs[i] == f)
+        {
+            tick_funcs[i] = NULL;
+            return 0;
+        }
+    }
+    
+    return -1;
+}
+
 void mutex_init(struct mutex *m)
 {
     (void)m;
diff --git a/uisimulator/x11/thread.c b/uisimulator/x11/thread.c
index f3fe868..6d9139c 100644
--- a/uisimulator/x11/thread.c
+++ b/uisimulator/x11/thread.c
@@ -30,7 +30,7 @@
 #endif
 
 long current_tick = 0;
-extern void button_tick(void);
+extern void sim_tick_tasks(void);
 
 static void msleep(int msec)
 {
@@ -59,10 +59,8 @@
                    + (now.tv_usec - start.tv_usec) / (1000000/HZ);
         if (new_tick > current_tick)
         {
+            sim_tick_tasks();
             current_tick = new_tick;
-            button_tick();  /* Dirty call to button.c. This should probably
-                             * be implemented as a tick task the same way 
-                             * as on the target. */
         }
     }
 }