From a539add0205a4d762d9d21029b26cbb8e2e215a8 Mon Sep 17 00:00:00 2001 From: Damjan Adamic Date: Wed, 3 Dec 2014 20:47:16 +0100 Subject: [PATCH] Re #1875 and #1849: implemented LCD initialization for low temperatures. Initialization skipped in case of watchdog reset or boot-loader exit. --- radio/src/bootloader/boot.cpp | 13 ++- radio/src/lcd.h | 9 +- radio/src/opentx.cpp | 26 +++--- radio/src/targets/taranis/aspi.c | 15 ++-- radio/src/targets/taranis/board_taranis.cpp | 1 + radio/src/targets/taranis/board_taranis.h | 2 + radio/src/targets/taranis/lcd_driver.cpp | 95 +++++++++++++++------ radio/src/tasks_arm.cpp | 2 +- 8 files changed, 118 insertions(+), 45 deletions(-) diff --git a/radio/src/bootloader/boot.cpp b/radio/src/bootloader/boot.cpp index c4edd59a3..1e540bbcc 100644 --- a/radio/src/bootloader/boot.cpp +++ b/radio/src/bootloader/boot.cpp @@ -485,7 +485,15 @@ int main() start_timer0(); #endif +#if defined(PCBTARANIS) + init_hw_timer(); //needed for lcdInitxxx() + lcdInitStart(); + //nothing to do here + lcdInitFinish(); +#else lcdInit(); +#endif + #if defined(PCBSKY9X) extern uint8_t OptrexDisplay; OptrexDisplay = 1; @@ -505,7 +513,6 @@ int main() #endif keysInit(); I2C_EE_Init(); - init_hw_timer(); #endif __enable_irq(); @@ -789,6 +796,7 @@ int main() } if (pwrCheck() == e_power_off && state != ST_FLASHING && state != ST_USB) { + lcdOff(); // this drains LCD caps pwrOff(); for (;;) { // Wait for power to go off @@ -797,6 +805,9 @@ int main() if (state == ST_REBOOT) { if ((~readKeys() & 0x7E) == 0) { + lcd_clear(); + lcdRefresh(); + RCC->CSR |= RCC_CSR_RMVF; //clear the reset flags in RCC clock control & status register NVIC_SystemReset(); } } diff --git a/radio/src/lcd.h b/radio/src/lcd.h index 988bd4ae9..c6f71e7e1 100644 --- a/radio/src/lcd.h +++ b/radio/src/lcd.h @@ -282,9 +282,16 @@ void lcd_img(coord_t x, coord_t y, const pm_uchar * img, uint8_t idx, LcdFlags a #endif void lcdSetRefVolt(unsigned char val); -void lcdInit(); void lcd_clear(); void lcdSetContrast(); +#if defined(PCBTARANIS) + void lcdInitStart(); + void lcdInitFinish(); + void lcdOff(); +#else + void lcdInit(); + #define lcdOff() +#endif #if defined(PCBTARANIS) && defined(REVPLUS) && !defined(SIMU) void lcdRefresh(bool wait=true); diff --git a/radio/src/opentx.cpp b/radio/src/opentx.cpp index dd0f3dcd1..cb2a67331 100644 --- a/radio/src/opentx.cpp +++ b/radio/src/opentx.cpp @@ -2872,16 +2872,18 @@ uint16_t stack_free() void opentxInit(OPENTX_INIT_ARGS) { -#if defined(PCBTARANIS) && !defined(SIMU) - CoTickDelay(100); //200ms - lcdInit(); - lcdSetRefVolt(g_eeGeneral.contrast); - BACKLIGHT_ON(); - CoTickDelay(20); //20ms - Splash(); + eeReadAll(); + +#if defined(CPUARM) + if (UNEXPECTED_SHUTDOWN()) + unexpectedShutdown = 1; #endif - eeReadAll(); +#if defined(PCBTARANIS) + lcdInitFinish(); + BACKLIGHT_ON(); + Splash(); +#endif #if MENUS_LOCK == 1 getMovedSwitch(); @@ -2890,12 +2892,10 @@ void opentxInit(OPENTX_INIT_ARGS) } #endif -#if defined(CPUARM) - if (UNEXPECTED_SHUTDOWN()) - unexpectedShutdown = 1; -#endif - #if defined(VOICE) +#if defined(CPUARM) + currentSpeakerVolume = requiredSpeakerVolume = g_eeGeneral.speakerVolume+VOLUME_LEVEL_DEF; +#endif setVolume(g_eeGeneral.speakerVolume+VOLUME_LEVEL_DEF); #endif diff --git a/radio/src/targets/taranis/aspi.c b/radio/src/targets/taranis/aspi.c index f0ad3035d..ce435faa0 100644 --- a/radio/src/targets/taranis/aspi.c +++ b/radio/src/targets/taranis/aspi.c @@ -54,8 +54,8 @@ void AspiCmd(u8 Command_Byte) LCD_A0_LOW(); LCD_CLK_HIGH(); - __no_operation(); - LCD_NCS_LOW(); + LCD_CLK_HIGH(); + LCD_NCS_LOW(); while (i--) { LCD_CLK_LOW(); @@ -66,9 +66,11 @@ void AspiCmd(u8 Command_Byte) LCD_MOSI_LOW(); Command_Byte <<= 1; + LCD_CLK_LOW(); \ + LCD_CLK_LOW(); \ LCD_CLK_HIGH(); - __no_operation(); + LCD_CLK_HIGH(); } LCD_NCS_HIGH(); @@ -104,6 +106,7 @@ void AspiData(u8 Para_data) { int i=8; LCD_CLK_HIGH(); + LCD_CLK_HIGH(); LCD_A0_HIGH(); LCD_NCS_LOW(); while (i--) { @@ -113,9 +116,11 @@ void AspiData(u8 Para_data) else LCD_MOSI_LOW(); Para_data <<= 1; - __no_operation(); + LCD_CLK_LOW(); + LCD_CLK_LOW(); + + LCD_CLK_HIGH(); LCD_CLK_HIGH(); - __no_operation(); } LCD_NCS_HIGH(); LCD_A0_HIGH(); diff --git a/radio/src/targets/taranis/board_taranis.cpp b/radio/src/targets/taranis/board_taranis.cpp index 2f3cf6327..d162e7a83 100644 --- a/radio/src/targets/taranis/board_taranis.cpp +++ b/radio/src/targets/taranis/board_taranis.cpp @@ -128,6 +128,7 @@ void boardInit() keysInit(); adcInit(); delaysInit(); + lcdInitStart(); audioInit(); init2MhzTimer(); init5msTimer(); diff --git a/radio/src/targets/taranis/board_taranis.h b/radio/src/targets/taranis/board_taranis.h index 825eca820..d09e81782 100644 --- a/radio/src/targets/taranis/board_taranis.h +++ b/radio/src/targets/taranis/board_taranis.h @@ -185,6 +185,8 @@ void checkRotaryEncoder(); void watchdogInit(unsigned int duration); #define wdt_enable(x) watchdogInit(1500) #define wdt_reset() IWDG->KR = 0xAAAA +#define WAS_RESET_BY_WATCHDOG() (RCC->CSR & (RCC_CSR_WDGRSTF | RCC_CSR_WWDGRSTF)) +#define WAS_RESET_BY_SOFTWARE() (RCC->CSR & RCC_CSR_SFTRSTF) #endif // ADC driver diff --git a/radio/src/targets/taranis/lcd_driver.cpp b/radio/src/targets/taranis/lcd_driver.cpp index 7c5cfb2ba..77b667970 100644 --- a/radio/src/targets/taranis/lcd_driver.cpp +++ b/radio/src/targets/taranis/lcd_driver.cpp @@ -16,18 +16,28 @@ #if defined(REVPLUS) #define CONTRAST_OFS 160 + #define RESET_WAIT_DELAY_MS 300 //wait time after LCD reset before first command #else #define CONTRAST_OFS 5 + #define RESET_WAIT_DELAY_MS 1300 //wait time after LCD reset before first command #endif -//275us -void Delay(volatile unsigned int ms) +#if defined(BOOT) + extern void hw_delay(uint16_t time); +#endif + +/* + In boot-loader: init_hw_timer() must be called before the first call to this function! + In opentx: delaysInit() must be called before the first call to this function! +*/ +static void Delay(uint32_t ms) { - volatile u8 i; - while(ms != 0) { - for(i=0;i<250;i++) {} - for(i=0;i<75;i++) {} - ms--; + while(ms--) { +#if !defined(BOOT) + delay_01us(10000); +#else + hw_delay(10000); +#endif } } @@ -110,6 +120,7 @@ static void LCD_Init() static void LCD_Init() { AspiCmd(0x2B); //Panel loading set ,Internal VLCD. + Delay(20); AspiCmd(0x25); //Temperature compensation curve definition: 0x25 = -0.05%/oC AspiCmd(0xEA); //set bias=1/10 :Command table NO.27 AspiCmd(0x81); //Set Vop @@ -157,7 +168,9 @@ void Set_Address(u8 x, u8 y) else \ LCD_MOSI_LOW(); \ LCD_CLK_LOW(); \ - __no_operation(); \ + LCD_CLK_LOW(); \ + LCD_CLK_LOW(); \ + LCD_CLK_HIGH(); \ LCD_CLK_HIGH(); #if defined(REVPLUS) @@ -298,35 +311,69 @@ static void LCD_Hardware_Init() GPIO_Init(GPIO_LCD_RST, &GPIO_InitStructure); } -void LCD_OFF() +/* + Proper method for turning of LCD module. It must be used, + otherwise we might damage LCD crystals in the long run! +*/ +void lcdOff() { - AspiCmd(0xE2); - Delay(20); + AspiCmd(0xE2); //system reset + Delay(3); //wait for caps to drain } -void lcdInit() +/* + Starts LCD initialization routine. It should be called as + soon as possible after the reset because LCD takes a lot of + time to properly power-on. + + Make sure that Delay() is functional before calling this function! +*/ +void lcdInitStart() { LCD_BL_Config(); LCD_Hardware_Init(); + + if (WAS_RESET_BY_WATCHDOG()|WAS_RESET_BY_SOFTWARE()) return; //no need to reset LCD module + + //reset LCD module + LCD_RST_LOW(); + Delay(1); // only 3 us needed according to data-sheet, we use 1 ms + LCD_RST_HIGH(); +} + +/* + Finishes LCD initialization. Must be called after the lcdInitStart(). +*/ +void lcdInitFinish() +{ #if defined(REVPLUS) - initLcdSpi() ; + initLcdSpi(); #endif - LCD_RST_HIGH(); - Delay(5); + if (WAS_RESET_BY_WATCHDOG()|WAS_RESET_BY_SOFTWARE()) return; //no need to initialize LCD module - LCD_RST_LOW(); - Delay(120); //11ms + /* + LCD needs longer time to initialize in low temperatures. The data-sheet + mentions a time of at least 150 ms. The delay of 1300 ms was obtained + experimentally. It was tested down to -10 deg Celsius. + + The longer initialization time seems to only be needed for regular Taranis, + the Taranis Plus has been reported by users to work without any problems. + Therefore the delay for T+ is lower. + + If radio is reset by watchdog or boot-loader LCD initialization is skipped, + because it was already initialized in previous run. + */ + +#if !defined(BOOT) + while(g_tmr10ms < (RESET_WAIT_DELAY_MS/10)) {}; //wait measured from the power-on +#else + Delay(RESET_WAIT_DELAY_MS); +#endif - LCD_RST_HIGH(); - Delay(2500); - - AspiCmd(0xE2); - Delay(2500); LCD_Init(); - Delay(120); - AspiCmd(0xAF); //dc2=1, IC into exit SLEEP MODE, dc3=1 gray=ON, dc4=1 Green Enhanc mode disabled + Delay(20); //needed for internal DC-DC converter startup } void lcdSetRefVolt(uint8_t val) diff --git a/radio/src/tasks_arm.cpp b/radio/src/tasks_arm.cpp index 84dc124f0..828e851b9 100644 --- a/radio/src/tasks_arm.cpp +++ b/radio/src/tasks_arm.cpp @@ -166,7 +166,7 @@ void menusTask(void * pdata) lcd_clear(); lcdRefresh(); - lcdSetRefVolt(0); + lcdOff(); #if !defined(SIMU) SysTick->CTRL = 0; // turn off systick