diff --git a/apps/features.txt b/apps/features.txt index 118465a535..0a01eb92c7 100644 --- a/apps/features.txt +++ b/apps/features.txt @@ -20,7 +20,7 @@ albumart backlight_brightness #endif -#if defined(HAVE_BACKLIGHT_PWM_FADING) +#if defined(HAVE_BACKLIGHT_PWM_FADING) || defined(USE_BACKLIGHT_SW_FADING) backlight_fade #endif diff --git a/apps/menus/display_menu.c b/apps/menus/display_menu.c index 016255bad1..744a9e9354 100644 --- a/apps/menus/display_menu.c +++ b/apps/menus/display_menu.c @@ -91,7 +91,8 @@ MENUITEM_SETTING(backlight_on_button_hold, &global_settings.backlight_on_button_hold, NULL); #endif MENUITEM_SETTING(caption_backlight, &global_settings.caption_backlight, NULL); -#if defined(HAVE_BACKLIGHT_PWM_FADING) && !defined(SIMULATOR) +#if (defined(HAVE_BACKLIGHT_PWM_FADING) && !defined(SIMULATOR)) || \ + defined(USE_BACKLIGHT_SW_FADING) MENUITEM_SETTING(backlight_fade_in, &global_settings.backlight_fade_in, NULL); MENUITEM_SETTING(backlight_fade_out, &global_settings.backlight_fade_out, NULL); #endif @@ -130,9 +131,10 @@ MAKE_MENU(lcd_settings,ID2P(LANG_LCD_MENU), ,&backlight_on_button_hold # endif ,&caption_backlight -# if defined(HAVE_BACKLIGHT_PWM_FADING) && !defined(SIMULATOR) +#if (defined(HAVE_BACKLIGHT_PWM_FADING) && !defined(SIMULATOR)) || \ + defined(USE_BACKLIGHT_SW_FADING) ,&backlight_fade_in, &backlight_fade_out -# endif +#endif ,&bl_filter_first_keypress # ifdef HAVE_LCD_SLEEP_SETTING ,&lcd_sleep_after_backlight_off diff --git a/apps/settings.c b/apps/settings.c index bdfaba2f44..2cab26a4a1 100644 --- a/apps/settings.c +++ b/apps/settings.c @@ -768,7 +768,8 @@ void settings_apply(bool read_disk) #if CONFIG_CHARGING backlight_set_timeout_plugged(global_settings.backlight_timeout_plugged); #endif -#if defined(HAVE_BACKLIGHT_PWM_FADING) && !defined(SIMULATOR) +#if (defined(HAVE_BACKLIGHT_PWM_FADING) && !defined(SIMULATOR)) \ + || defined(USE_BACKLIGHT_SW_FADING) backlight_set_fade_in(global_settings.backlight_fade_in); backlight_set_fade_out(global_settings.backlight_fade_out); #endif diff --git a/apps/settings.h b/apps/settings.h index c5658aaf09..56b7d3e80a 100644 --- a/apps/settings.h +++ b/apps/settings.h @@ -421,10 +421,14 @@ struct user_settings int backlight_timeout_plugged; #endif -#ifdef HAVE_BACKLIGHT_PWM_FADING +#if defined(HAVE_BACKLIGHT_PWM_FADING) int backlight_fade_in; /* backlight fade in timing: 0..3 */ int backlight_fade_out; /* backlight fade in timing: 0..7 */ +#elif defined(USE_BACKLIGHT_SW_FADING) + bool backlight_fade_in; + bool backlight_fade_out; #endif + #ifdef HAVE_BACKLIGHT_BRIGHTNESS int brightness; #endif diff --git a/apps/settings_list.c b/apps/settings_list.c index 6a7fcc3aec..f4519f5975 100644 --- a/apps/settings_list.c +++ b/apps/settings_list.c @@ -679,6 +679,11 @@ const struct settings_list settings[] = { UNIT_MS, formatter_unit_0_is_off, getlang_unit_0_is_off, backlight_set_fade_out, 10, 0,100,200,300,500,1000,2000,3000,5000,10000), +#elif defined(USE_BACKLIGHT_SW_FADING) + OFFON_SETTING(0, backlight_fade_in, LANG_BACKLIGHT_FADE_IN, + true, "backlight fade in", backlight_set_fade_in), + OFFON_SETTING(0, backlight_fade_out, LANG_BACKLIGHT_FADE_OUT, + true, "backlight fade out", backlight_set_fade_out), #endif INT_SETTING(F_PADTITLE, scroll_speed, LANG_SCROLL_SPEED, 9,"scroll speed", UNIT_INT, 0, 15, 1, NULL, NULL, lcd_scroll_speed), diff --git a/firmware/SOURCES b/firmware/SOURCES index 4e40d11cf7..47dcfe5c86 100644 --- a/firmware/SOURCES +++ b/firmware/SOURCES @@ -96,6 +96,10 @@ drivers/lcd-remote-2bit-vi.c #endif /* LCD_REMOTE_DEPTH */ #endif /* HAVE_REMOTE_LCD */ +#ifdef USE_BACKLIGHT_SW_FADING +backlight-thread-fading.c +#endif /* USE_BACKLIGHT_SW_FADING */ + /* Misc. */ drivers/led.c drivers/button.c diff --git a/firmware/backlight-thread-fading.c b/firmware/backlight-thread-fading.c new file mode 100644 index 0000000000..30778a9912 --- /dev/null +++ b/firmware/backlight-thread-fading.c @@ -0,0 +1,87 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2008 by Thomas Martitz + * Copyright (C) 2008 by Martin Ritter + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#include +#include "backlight-target.h" +#include "config.h" +#include "system.h" +#include "backlight.h" +#include "backlight-thread-fading.h" + +/* To adapt a target do: + * - make sure _backlight_on doesn't set the brightness to something other than + * the previous value (lowest brightness in most cases) + * - #define USE_BACKLIGHT_SW_FADING in config-.h + */ + +/* can be MIN_BRIGHTNESS_SETTING-1 */ +static int current_brightness = DEFAULT_BRIGHTNESS_SETTING; + +void _backlight_fade_update_state(int brightness) +{ + current_brightness = brightness; +} + +/* returns true if fade is finished */ +static bool _backlight_fade_up(void) +{ + if (LIKELY(current_brightness < backlight_brightness)) + { + _backlight_set_brightness(++current_brightness); + } + return(current_brightness >= backlight_brightness); +} + +/* returns true if fade is finished */ +static bool _backlight_fade_down(void) +{ + if (LIKELY(current_brightness > MIN_BRIGHTNESS_SETTING)) + { + _backlight_set_brightness(--current_brightness); + return false; + } + else + { + /* decrement once more, since backlight is off */ + current_brightness--; + _backlight_off(); + return true; + } +} + +bool _backlight_fade_step(int direction) +{ + bool done; + switch(direction) + { + case FADING_UP: + done = _backlight_fade_up(); + break; + case FADING_DOWN: + done = _backlight_fade_down(); + break; + default: + done = true; + break; + } + return(done); +} diff --git a/firmware/backlight.c b/firmware/backlight.c index b8becfa69f..fe9c215af5 100644 --- a/firmware/backlight.c +++ b/firmware/backlight.c @@ -8,6 +8,8 @@ * $Id$ * * Copyright (C) 2002 by Linus Nielsen Feltzing + * Additional work by Martin Ritter (2007) and Thomas Martitz (2008) + * for backlight thread fading * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -46,6 +48,9 @@ #define BACKLIGHT_FULL_INIT #endif +#ifdef USE_BACKLIGHT_SW_FADING +#include "backlight-thread-fading.h" +#endif #ifdef SIMULATOR /* TODO: find a better way to do it but we need a kernel thread somewhere to handle this */ @@ -134,6 +139,10 @@ static int backlight_timeout_plugged = 5*HZ; static int backlight_on_button_hold = 0; #endif +#ifdef HAVE_BACKLIGHT_BRIGHTNESS +int backlight_brightness = DEFAULT_BRIGHTNESS_SETTING; +#endif + #ifdef HAVE_BUTTON_LIGHT static int buttonlight_timer; int _buttonlight_timeout = 5*HZ; @@ -221,6 +230,12 @@ void backlight_lcd_sleep_countdown(bool start) } #endif /* HAVE_LCD_SLEEP */ +#ifdef USE_BACKLIGHT_SW_FADING +static int backlight_fading_type = (FADING_UP|FADING_DOWN); +static int backlight_fading_state = NOT_FADING; +#endif + + #if defined(HAVE_BACKLIGHT_PWM_FADING) && !defined(SIMULATOR) /* backlight fading */ #define BL_PWM_INTERVAL 5 /* Cycle interval in ms */ @@ -397,6 +412,66 @@ void backlight_set_fade_out(int value) } #endif /* defined(HAVE_BACKLIGHT_PWM_FADING) && !defined(SIMULATOR) */ +#ifdef USE_BACKLIGHT_SW_FADING + +void backlight_set_fade_out(bool value) +{ + if(value) /* on */ + backlight_fading_type |= FADING_DOWN; + else + backlight_fading_type &= FADING_UP; +} + +void backlight_set_fade_in(bool value) +{ + if(value) /* on */ + backlight_fading_type |= FADING_UP; + else + backlight_fading_type &= FADING_DOWN; +} + +static void backlight_set_up_fade_up(void) +{ + if (backlight_fading_type & FADING_UP) + { + if (backlight_fading_state == NOT_FADING) + { + /* make sure the backlight is at lowest level */ + _backlight_on(); + } + backlight_fading_state = FADING_UP; + } + else + { + backlight_fading_state = NOT_FADING; + _backlight_fade_update_state(backlight_brightness); + _backlight_on(); + _backlight_set_brightness(backlight_brightness); + } +} + +static void backlight_set_up_fade_down(void) +{ + if (backlight_fading_type & FADING_DOWN) + { + backlight_fading_state = FADING_DOWN; + } + else + { + backlight_fading_state = NOT_FADING; + _backlight_fade_update_state(MIN_BRIGHTNESS_SETTING-1); + _backlight_off(); + /* h300/x5/d2 go to the last known brightness level at backight_on(),which + * should be the lowest level to keep fading up glitch free + * sansa e200/c200 make the backlight on only by setting the brightness, + * so this step would be noticeable */ +#if !defined(SANSA_E200) && !defined(SANSA_C200) + _backlight_set_brightness(MIN_BRIGHTNESS_SETTING); +#endif + } +} +#endif /* USE_BACKLIGHT_SW_FADING */ + /* Update state of backlight according to timeout setting */ static void backlight_update_state(void) { @@ -424,15 +499,25 @@ static void backlight_update_state(void) backlight_timeout = backlight_timeout_normal; /* Backlight == OFF in the setting? */ - if (backlight_timeout < 0) + if (UNLIKELY(backlight_timeout < 0)) { backlight_timer = 0; /* Disable the timeout */ +#ifdef USE_BACKLIGHT_SW_FADING + backlight_set_up_fade_down(); + /* necessary step to issue fading down when the setting is selected */ + queue_post(&backlight_queue, SYS_TIMEOUT, 0); +#else _backlight_off(); +#endif } else { backlight_timer = backlight_timeout; +#if defined(USE_BACKLIGHT_SW_FADING) + backlight_set_up_fade_up(); +#else _backlight_on(); +#endif } } @@ -478,7 +563,15 @@ void backlight_thread(void) while(1) { - queue_wait(&backlight_queue, &ev); +#if defined(USE_BACKLIGHT_SW_FADING) + if (backlight_fading_state) + queue_wait_w_tmo(&backlight_queue, &ev, FADE_DELAY); + else +#endif + queue_wait(&backlight_queue, &ev); +/* +#endif +*/ switch(ev.id) { /* These events must always be processed */ #ifdef _BACKLIGHT_FADE_BOOST @@ -558,9 +651,12 @@ void backlight_thread(void) case BACKLIGHT_OFF: backlight_timer = 0; /* Disable the timeout */ +#ifndef USE_BACKLIGHT_SW_FADING _backlight_off(); +#else + backlight_set_up_fade_down(); +#endif /* USE_BACKLIGHT_SW_FADING */ break; - #ifdef HAVE_LCD_SLEEP case LCD_SLEEP: lcd_sleep(); @@ -589,6 +685,12 @@ void backlight_thread(void) remote_backlight_update_state(); #endif break; +#if defined(USE_BACKLIGHT_SW_FADING) + case SYS_TIMEOUT: + if ((_backlight_fade_step(backlight_fading_state))) + backlight_fading_state = NOT_FADING; + break; +#endif /* USE_BACKLIGHT_SW_FADING */ } } /* end while */ } @@ -597,8 +699,7 @@ static void backlight_tick(void) { if(backlight_timer) { - backlight_timer--; - if(backlight_timer == 0) + if(--backlight_timer == 0) { backlight_off(); } @@ -606,20 +707,17 @@ static void backlight_tick(void) #ifdef HAVE_LCD_SLEEP else if(lcd_sleep_timer) { - lcd_sleep_timer--; - if(lcd_sleep_timer == 0) + if(--lcd_sleep_timer == 0) { /* Queue on bl thread or freeze! */ queue_post(&backlight_queue, LCD_SLEEP, 0); } } #endif /* HAVE_LCD_SLEEP */ - #ifdef HAVE_REMOTE_LCD if(remote_backlight_timer) { - remote_backlight_timer--; - if(remote_backlight_timer == 0) + if(--remote_backlight_timer == 0) { remote_backlight_off(); } @@ -628,8 +726,7 @@ static void backlight_tick(void) #ifdef HAVE_BUTTON_LIGHT if (buttonlight_timer) { - buttonlight_timer--; - if (buttonlight_timer == 0) + if (--buttonlight_timer == 0) { buttonlight_off(); } @@ -832,6 +929,11 @@ void backlight_set_brightness(int val) val = MAX_BRIGHTNESS_SETTING; _backlight_set_brightness(val); + backlight_brightness = val; +#ifdef USE_BACKLIGHT_SW_FADING + /* receive backlight brightness */ + _backlight_fade_update_state(val); +#endif } #endif /* HAVE_BACKLIGHT_BRIGHTNESS */ diff --git a/firmware/export/backlight-thread-fading.h b/firmware/export/backlight-thread-fading.h new file mode 100644 index 0000000000..ca9c195480 --- /dev/null +++ b/firmware/export/backlight-thread-fading.h @@ -0,0 +1,46 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id:$ + * + * Copyright (C) 2007 by Will Robertson + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#ifndef BACKLIGHT_THREAD_FADING_H +#define BACKLIGHT_THREAD_FADING_H + +#include "config.h" + +#ifdef USE_BACKLIGHT_SW_FADING + +/* delay supposed to be MAX_BRIGHTNESS_SETTING*2 rounded to the next multiple + * of 5, however not more than 40 */ +#define _FADE_DELAY (((MAX_BRIGHTNESS_SETTING*2+4)/5)*5) +#define FADE_DELAY (HZ/(MIN(_FADE_DELAY, 40))) + +void _backlight_fade_update_state(int brightness); +bool _backlight_fade_step(int direction); + +/* enum used for both, fading state and fading type selected through the settings */ + +enum { + NOT_FADING = 0, + FADING_UP, + FADING_DOWN, +}; +#endif /* USE_BACKLIGHT_SW_FADING */ + +#endif /* _BACKLIGHT_THREAD_FADING_ */ diff --git a/firmware/export/backlight.h b/firmware/export/backlight.h index e0980658dc..a177fe740f 100644 --- a/firmware/export/backlight.h +++ b/firmware/export/backlight.h @@ -34,10 +34,16 @@ void backlight_close(void); int backlight_get_current_timeout(void); -#ifdef HAVE_BACKLIGHT_PWM_FADING +#if defined(HAVE_BACKLIGHT_PWM_FADING) void backlight_set_fade_in(int value); void backlight_set_fade_out(int value); #endif +#ifdef USE_BACKLIGHT_SW_FADING +void backlight_set_fade_in(bool value); +void backlight_set_fade_out(bool value); +#endif + +extern int backlight_brightness; void backlight_set_timeout_plugged(int value); diff --git a/firmware/export/config-c200.h b/firmware/export/config-c200.h index a96b9c7ef8..8e26585e94 100644 --- a/firmware/export/config-c200.h +++ b/firmware/export/config-c200.h @@ -132,6 +132,10 @@ /** Non-simulator section **/ #ifndef SIMULATOR +/* define this if the backlight thread is used for fade, not for sim, needs + * HAVE_BACKLIGHT_BRIGHTNESS */ +#define USE_BACKLIGHT_SW_FADING + /* Define this if you have a PortalPlayer PP5024 */ #define CONFIG_CPU PP5022 diff --git a/firmware/export/config-cowond2.h b/firmware/export/config-cowond2.h index fd696aae66..b723201340 100644 --- a/firmware/export/config-cowond2.h +++ b/firmware/export/config-cowond2.h @@ -122,6 +122,10 @@ #ifndef SIMULATOR +/* define this if the backlight thread is used for fade, not for sim, needs + * HAVE_BACKLIGHT_BRIGHTNESS */ +#define USE_BACKLIGHT_SW_FADING + /* Define this if you have a TCC7801 */ #define CONFIG_CPU TCC7801 diff --git a/firmware/export/config-e200.h b/firmware/export/config-e200.h index 075f490ee4..d9bebef9bc 100644 --- a/firmware/export/config-e200.h +++ b/firmware/export/config-e200.h @@ -129,6 +129,10 @@ /** Non-simulator section **/ #ifndef SIMULATOR +/* define this if the backlight thread is used for fade, not for sim, needs + * HAVE_BACKLIGHT_BRIGHTNESS */ +#define USE_BACKLIGHT_SW_FADING + /* Define this if you have a PortalPlayer PP5024 */ #define CONFIG_CPU PP5024 diff --git a/firmware/export/config-h300.h b/firmware/export/config-h300.h index f45b694fe0..2af426f048 100644 --- a/firmware/export/config-h300.h +++ b/firmware/export/config-h300.h @@ -114,6 +114,11 @@ #ifndef SIMULATOR +/* define this if the backlight thread is used for fade, not for sim, needs + * HAVE_BACKLIGHT_BRIGHTNESS */ +#define USE_BACKLIGHT_SW_FADING + + /* Define this if your LCD can be enabled/disabled */ #define HAVE_LCD_ENABLE diff --git a/firmware/export/config-iaudiox5.h b/firmware/export/config-iaudiox5.h index cdae55af4f..089d219534 100644 --- a/firmware/export/config-iaudiox5.h +++ b/firmware/export/config-iaudiox5.h @@ -124,6 +124,9 @@ #ifndef SIMULATOR +/* define this if the backlight thread is used for fade, not for sim */ +#define USE_BACKLIGHT_SW_FADING + /* Define this if your LCD can set contrast */ #define HAVE_LCD_CONTRAST diff --git a/firmware/target/arm/sandisk/backlight-c200_e200.c b/firmware/target/arm/sandisk/backlight-c200_e200.c index b3984ca9ad..67e0cddac9 100644 --- a/firmware/target/arm/sandisk/backlight-c200_e200.c +++ b/firmware/target/arm/sandisk/backlight-c200_e200.c @@ -26,16 +26,9 @@ #include "ascodec.h" #include "as3514.h" -static unsigned short backlight_brightness = DEFAULT_BRIGHTNESS_SETTING; - void _backlight_set_brightness(int brightness) { - backlight_brightness = brightness; - - if (brightness > 0) - _backlight_on(); - else - _backlight_off(); + ascodec_write(AS3514_DCDC15, brightness); } void _backlight_on(void) @@ -46,7 +39,10 @@ void _backlight_on(void) #ifdef HAVE_LCD_ENABLE lcd_enable(true); /* power on lcd + visible display */ #endif - ascodec_write(AS3514_DCDC15, backlight_brightness); +#ifndef USE_BACKLIGHT_SW_FADING + /* that part ain't useful when fading */ + _backlight_set_brightness(backlight_brightness); +#endif } void _backlight_off(void) diff --git a/firmware/target/arm/sandisk/backlight-target.h b/firmware/target/arm/sandisk/backlight-target.h index 21fad6d22e..1f5e475a42 100644 --- a/firmware/target/arm/sandisk/backlight-target.h +++ b/firmware/target/arm/sandisk/backlight-target.h @@ -25,7 +25,6 @@ void _backlight_on(void); void _backlight_off(void); void _backlight_set_brightness(int brightness); -int __backlight_is_on(void); void _buttonlight_on(void); void _buttonlight_off(void); diff --git a/firmware/target/arm/tcc780x/cowond2/backlight-cowond2.c b/firmware/target/arm/tcc780x/cowond2/backlight-cowond2.c index 6d286aee8f..39a9abf073 100644 --- a/firmware/target/arm/tcc780x/cowond2/backlight-cowond2.c +++ b/firmware/target/arm/tcc780x/cowond2/backlight-cowond2.c @@ -24,27 +24,20 @@ #include "pcf50606.h" #include "tcc780x.h" -static unsigned short backlight_brightness = DEFAULT_BRIGHTNESS_SETTING; - int _backlight_init(void) { _backlight_set_brightness(DEFAULT_BRIGHTNESS_SETTING); + /* set backlight on by default, since the screen is unreadable without it */ + _backlight_on(); return true; } void _backlight_set_brightness(int brightness) { - backlight_brightness = brightness; - int level = disable_irq_save(); - pcf50606_write(PCF5060X_PWMC1, 0xe1 | (14-backlight_brightness)<<1); + pcf50606_write(PCF5060X_PWMC1, 0xe1 | (MAX_BRIGHTNESS_SETTING-brightness)<<1); pcf50606_write(PCF5060X_GPOC1, 0x3); restore_irq(level); - - if (brightness > 0) - _backlight_on(); - else - _backlight_off(); } void _backlight_on(void)