diff --git a/radio/src/gui/Taranis/menu_model_telemetry.cpp b/radio/src/gui/Taranis/menu_model_telemetry.cpp index 5e33c064b..8df933de1 100644 --- a/radio/src/gui/Taranis/menu_model_telemetry.cpp +++ b/radio/src/gui/Taranis/menu_model_telemetry.cpp @@ -82,6 +82,9 @@ enum menuModelTelemetryItems { ITEM_TELEMETRY_TOP_BAR_LABEL, ITEM_TELEMETRY_TOP_BAR_VOLTAGE, ITEM_TELEMETRY_TOP_BAR_ALTITUDE, +#if defined(REV9E) + ITEM_TELEMETRY_TOP_LCD_TIMER, +#endif ITEM_TELEMETRY_SCREEN_LABEL1, ITEM_TELEMETRY_SCREEN_LINE1, ITEM_TELEMETRY_SCREEN_LINE2, @@ -433,9 +436,15 @@ void onTelemetryScriptFileSelectionMenu(const char *result) } #endif +#if defined(REV9E) + #define TOPLCD_ROWS 0, +#else + #define TOPLCD_ROWS +#endif + void menuModelTelemetry(uint8_t event) { - MENU(STR_MENUTELEMETRY, menuTabModel, e_Telemetry, ITEM_TELEMETRY_MAX, { TELEMETRY_TYPE_ROWS RSSI_ROWS SENSORS_ROWS USRDATA_ROWS CASE_VARIO(LABEL(Vario)) CASE_VARIO(0) CASE_VARIO(VARIO_RANGE_ROWS) LABEL(TopBar), 0, 0, TELEMETRY_SCREEN_ROWS(0), TELEMETRY_SCREEN_ROWS(1), CASE_CPUARM(TELEMETRY_SCREEN_ROWS(2)) CASE_CPUARM(TELEMETRY_SCREEN_ROWS(3)) }); + MENU(STR_MENUTELEMETRY, menuTabModel, e_Telemetry, ITEM_TELEMETRY_MAX, { TELEMETRY_TYPE_ROWS RSSI_ROWS SENSORS_ROWS USRDATA_ROWS CASE_VARIO(LABEL(Vario)) CASE_VARIO(0) CASE_VARIO(VARIO_RANGE_ROWS) LABEL(TopBar), 0, 0, TOPLCD_ROWS TELEMETRY_SCREEN_ROWS(0), TELEMETRY_SCREEN_ROWS(1), CASE_CPUARM(TELEMETRY_SCREEN_ROWS(2)) CASE_CPUARM(TELEMETRY_SCREEN_ROWS(3)) }); int sub = m_posVert; @@ -579,6 +588,16 @@ void menuModelTelemetry(uint8_t event) } break; +#if defined(REV9E) + case ITEM_TELEMETRY_TOP_LCD_TIMER: + lcd_putsLeft(y, "Top LCD Timer"); + putsStrIdx(TELEM_COL2, y, "Timer", g_model.topLcdTimer+1, attr); + if (attr) { + g_model.topLcdTimer = checkIncDec(event, g_model.topLcdTimer, 0, MAX_TIMERS-1, EE_MODEL); + } + break; +#endif + case ITEM_TELEMETRY_SCREEN_LABEL1: case ITEM_TELEMETRY_SCREEN_LABEL2: case ITEM_TELEMETRY_SCREEN_LABEL3: diff --git a/radio/src/main_arm.cpp b/radio/src/main_arm.cpp index d3b550698..4327b0849 100644 --- a/radio/src/main_arm.cpp +++ b/radio/src/main_arm.cpp @@ -187,8 +187,15 @@ void perMain() lcdRefresh(); -#if defined(REV9E) - topLcdRefresh(); +#if defined(REV9E) && !defined(SIMU) + topLcdRefreshStart(); + setTopFirstTimer(getValue(MIXSRC_FIRST_TIMER+g_model.topLcdTimer)); + setTopSecondTimer(g_eeGeneral.globalTimer + sessionTimer); + setTopRssi(TELEMETRY_RSSI()); + setTopBatteryValue(g_vbat100mV); + int state = 5 * (g_vbat100mV - g_eeGeneral.vBatMin - 90) / (30 + g_eeGeneral.vBatMax - g_eeGeneral.vBatMin); + setTopBatteryState(state); + topLcdRefreshEnd(); #endif } diff --git a/radio/src/myeeprom.h b/radio/src/myeeprom.h index a7ad88a9c..18259375c 100644 --- a/radio/src/myeeprom.h +++ b/radio/src/myeeprom.h @@ -2137,6 +2137,10 @@ PACK(typedef struct { MODELDATA_EXTRA ARM_FIELD(TelemetrySensor telemetrySensors[TELEM_VALUES_MAX]) + +#if defined(PCBTARANIS) && defined(REV9E) + uint8_t topLcdTimer; +#endif }) ModelData; extern EEGeneral g_eeGeneral; diff --git a/radio/src/targets/taranis/board_taranis.h b/radio/src/targets/taranis/board_taranis.h index f0b279daa..c8a0190e3 100644 --- a/radio/src/targets/taranis/board_taranis.h +++ b/radio/src/targets/taranis/board_taranis.h @@ -317,7 +317,13 @@ int bt_read(void *buffer, int len); // Top LCD driver #if defined(REV9E) void topLcdInit(void); -void topLcdRefresh(void); +void topLcdRefreshStart(void); +void topLcdRefreshEnd(void); +void setTopFirstTimer(uint32_t value); +void setTopSecondTimer(uint32_t value); +void setTopRssi(uint32_t rssi); +void setTopBatteryState(uint32_t state); +void setTopBatteryValue(uint32_t volts); #endif #define USART_FLAG_ERRORS (USART_FLAG_ORE | USART_FLAG_NE | USART_FLAG_FE | USART_FLAG_PE) diff --git a/radio/src/targets/taranis/top_lcd_driver.cpp b/radio/src/targets/taranis/top_lcd_driver.cpp index 1896ac74e..6959f02c4 100755 --- a/radio/src/targets/taranis/top_lcd_driver.cpp +++ b/radio/src/targets/taranis/top_lcd_driver.cpp @@ -34,7 +34,12 @@ * */ -uint8_t top_lcd_data[16] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; +const uint8_t TimeLCDsegs[] = { 0xAF, 0x06, 0x6D, 0x4F, 0xC6, 0xCB, 0xEB, 0x0E, 0xEF, 0xCF }; +const uint8_t RssiLCDsegs[] = { 0xFA, 0x60, 0xBC, 0xF4, 0x66, 0xD6, 0xDE, 0x70, 0xFE, 0xF6 }; +const uint8_t OpTimeLCDsegs[] = { 0x5F, 0x06, 0x6B, 0x2F, 0x36, 0x3D, 0x7D, 0x07, 0x7F, 0x3F }; + +uint8_t Ht1621Data1[11] = { 0 }; +uint8_t Ht1621Data2[7] = { 0 }; void delay1_7us() { @@ -117,14 +122,19 @@ void ht1621WrData(uint8_t data, uint8_t count) void ht1621WrAllData(uint8_t chip, uint8_t *pData) { - if (chip) + int len; + if (chip) { + len = sizeof(Ht1621Data2); CS2_LOW; - else + } + else { + len = sizeof(Ht1621Data1); CS1_LOW; + } delay1_7us(); ht1621WrData(0xa0, 3); ht1621WrData(0, 6); // HT1621 6 bit,left 2 bit; - for (int i=0; i<16; i++) { + for (int i=0; iAPB1ENR |= RCC_APB1ENR_TIM12EN ; // Enable clock + TIM12->ARR = 17 ; // 1.7uS + TIM12->PSC = (PERI1_FREQUENCY * TIMER_MULT_APB1) / 10000000 - 1 ; // 0.1uS from 30MHz + TIM12->CCER = 0 ; + TIM12->CCMR1 = 0 ; + TIM12->EGR = 0 ; + TIM12->CR1 = 5 ; + // TIM12->DIER |= 1 ; + NVIC_SetPriority(TIM8_BRK_TIM12_IRQn, 2 ) ; + NVIC_EnableIRQ(TIM8_BRK_TIM12_IRQn) ; +} + +extern "C" void TIM8_BRK_TIM12_IRQHandler() +{ + struct t_top_lcd_control *pc ; + TIM12->SR &= ~TIM_SR_UIF ; + pc = &TopLcdControl ; + + if ( pc->state == TOP_LCD_CKLOW ) + { + WR_LOW ; //PRESENT 100 COMMAND CODE + if ((*pc->data & 0x80) !=0) + { + DATA_HIGH ; + } + else + { + DATA_LOW ; + } + *pc->data <<= 1 ; + pc->state = TOP_LCD_CKHI ; + } + else if ( pc->state == TOP_LCD_CKHI ) + { + WR_HIGH ; + if ( --pc->count == 0 ) + { + pc->state = TOP_LCD_END ; + } + else + { + pc->state = TOP_LCD_CKLOW ; + } + } + else if ( pc->state == TOP_LCD_END ) + { + if ( pc->chip ) + { + CS2_HIGH ; + pc->state = TOP_LCD_IDLE ; + TIM12->DIER &= ~1 ; + } + else + { + CS1_HIGH ; + pc->chip = 1 ; + pc->data = pc->data2 ; + pc->count = pc->count2 ; + pc->state = TOP_LCD_IDLE ; + } + } + else if ( pc->state == TOP_LCD_IDLE ) + { + WR_HIGH; + if ( pc->chip ) CS2_LOW ; else CS1_LOW ; + pc->state = TOP_LCD_1CKLOW ; + } + else if ( pc->state == TOP_LCD_1CKLOW ) + { + WR_LOW ; + DATA_HIGH ; // First 1 bit + pc->state = TOP_LCD_1CKHI ; + } + else if ( pc->state == TOP_LCD_1CKHI ) + { + WR_HIGH ; + if ( --pc->count == 0 ) + { + pc->state = TOP_LCD_END ; + } + else + { + pc->state = TOP_LCD_CKLOW ; + } + } +} +#endif + void topLcdInit() { RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_VA, ENABLE); @@ -154,10 +256,163 @@ void topLcdInit() ht1621SendCommand(1, 0x03); ht1621SendCommand(1, 0x01); ht1621SendCommand(1, 0x29); + + topLcdRefreshStart(); + topLcdRefreshEnd(); } -void topLcdRefresh() +void setTopFirstTimer(uint32_t value) { - ht1621WrAllData(0, top_lcd_data); - ht1621WrAllData(1, top_lcd_data); + div_t qr = div(value, 60); + uint32_t r = qr.rem; + qr = div(qr.quot, 10) ; + Ht1621Data1[0] |= TimeLCDsegs[qr.quot] ; + Ht1621Data1[1] |= TimeLCDsegs[qr.rem] ; + qr = div(r, 10) ; + Ht1621Data1[2] |= TimeLCDsegs[qr.quot] | 0x10 ; // ":" + Ht1621Data1[3] |= TimeLCDsegs[qr.rem] | 0x10 ; // "Operation Time" +} + +/*void setTopFirstTimer(uint32_t value) +{ + div_t qr ; + uint32_t r ; + qr = div(value, 60) ; + r = qr.rem ; + + qr = div(qr.quot, 10); + + Ht1621Data1[1] |= TimeLCDsegs[qr.quot] ; + Ht1621Data1[2] |= TimeLCDsegs[qr.rem] ; + + qr = div(r, 10) ; + Ht1621Data1[3] |= TimeLCDsegs[qr.quot] | 0x10 ; // ":" + Ht1621Data1[4] |= TimeLCDsegs[qr.rem] | 0x10 ; // "Operation Time" +}*/ + + +void setTopRssiValue(uint32_t rssi) +{ + div_t qr = div(rssi, 10); + uint32_t r = 0; + if (qr.quot > 9) { + r = 1; + qr.quot -= 10; + } + Ht1621Data2[2] |= r ? RssiLCDsegs[1] : 0; + Ht1621Data2[1] |= (r || qr.quot) ? RssiLCDsegs[qr.quot] : 0; + Ht1621Data2[0] |= RssiLCDsegs[qr.rem]; +} + +void setTopRssiBar(uint32_t rssi) +{ + if (rssi > 42) + Ht1621Data2[2] |= 1 ; + if (rssi > 45) + Ht1621Data2[1] |= 1 ; + if (rssi > 50) + Ht1621Data2[0] |= 1 ; + if (rssi > 60) + Ht1621Data2[3] |= 0x10 ; + if (rssi > 70) + Ht1621Data2[3] |= 0x20 ; + if (rssi > 80) + Ht1621Data2[3] |= 0x40 ; + if (rssi > 90) + Ht1621Data2[3] |= 0x80 ; +} + +void setTopRssi(uint32_t rssi) +{ + Ht1621Data1[4] |= 0x10; // "RSSI" + Ht1621Data2[3] |= 0x01; // "dB" + Ht1621Data2[4] |= 0x01; // Horizontal line + setTopRssiValue(rssi); + setTopRssiBar(rssi); +} + +void setTopBatteryState(uint32_t state) +{ + Ht1621Data1[4] |= 0x40; // Battery border + if (state > 0) + Ht1621Data1[7] |= 0x80 ; + if (state > 1) + Ht1621Data1[9] |= 0x80 ; + if (state > 2) + Ht1621Data1[5] |= 0x80 ; + if (state > 3) + Ht1621Data1[10] |= 0x80 ; + if (state > 4) + Ht1621Data1[4] |= 0x80 ; +} + +void setTopBatteryValue(uint32_t volts) +{ + div_t qr ; + uint32_t r = 0 ; + uint32_t segs ; + qr = div(volts, 10) ; + if (qr.quot > 9) { + r = 1 ; + qr.quot -= 10 ; + } + segs = r ? RssiLCDsegs[1] : 0 ; + Ht1621Data2[3] |= ((segs & 7) << 1); + Ht1621Data2[4] |= segs & 0xF0 ; + segs = (r || qr.quot) ? RssiLCDsegs[qr.quot] : 0 ; + Ht1621Data2[4] |= (segs & 0x0E); + Ht1621Data2[5] |= segs & 0xF0 ; + segs = RssiLCDsegs[qr.rem] ; + Ht1621Data2[5] |= (segs & 0x0E) | 1; // Decimal point + Ht1621Data2[6] |= segs & 0xF0 ; + Ht1621Data1[4] |= 0x20; // "V" +} + +void setTopSecondTimer(uint32_t value) +{ + div_t qr ; + uint32_t segs ; + uint32_t segs2 ; + + qr = div(value, 60); + uint32_t secs = qr.rem; + qr = div(qr.quot, 60); + uint32_t mins = qr.rem; + uint32_t hours = qr.quot; + + qr = div(secs, 10) ; + segs = OpTimeLCDsegs[qr.rem] ; + Ht1621Data1[4] |= (segs & 0x0F) | 0x70 ; + segs &= 0x70 ; + segs2 = OpTimeLCDsegs[qr.quot] ; + Ht1621Data1[5] |= segs | (segs2 & 0x0F) ; + + qr = div(mins, 10) ; + segs = OpTimeLCDsegs[qr.rem] ; + segs2 &= 0x70 ; + Ht1621Data1[6] |= segs2 | (segs & 0x0F) | 0x80 ; // ":" + segs &= 0x70 ; + segs2 = OpTimeLCDsegs[qr.quot] ; + Ht1621Data1[7] |= segs | (segs2 & 0x0F) ; + + qr = div(hours, 10) ; + segs = OpTimeLCDsegs[qr.rem] ; + segs2 &= 0x70 ; + Ht1621Data1[8] |= segs2 | (segs & 0x0F) | 0x80 ; // ":" + segs &= 0x70 ; + segs2 = OpTimeLCDsegs[qr.quot] ; + Ht1621Data1[9] |= segs | (segs2 & 0x0F) ; + Ht1621Data1[10] |= segs2 & 0xF0 ; +} + +void topLcdRefreshStart() +{ + memset(Ht1621Data1, 0, sizeof(Ht1621Data1)); + memset(Ht1621Data2, 0, sizeof(Ht1621Data2)); +} + +void topLcdRefreshEnd() +{ + ht1621WrAllData(0, Ht1621Data1); + ht1621WrAllData(1, Ht1621Data2); }