From c84501fbd1b2dde3def95bbad10c10915afef2ee Mon Sep 17 00:00:00 2001 From: "bsongis@gmail.com" Date: Wed, 5 Jun 2013 21:11:28 +0000 Subject: [PATCH] [all] Bug introduced in last revision in TELEMETRY screen! [sky9x] About screen [all] Expos/DRs screen cosmetics [all] CSW Timer better range (0.1, 0.5 and 1.0 precision) --- src/Makefile | 10 +- src/bitmaps/about_9x.lbm | 4 + src/bitmaps/about_9x.png | Bin 0 -> 212 bytes src/bitmaps/{about.lbm => about_taranis.lbm} | 0 src/bitmaps/{about.png => about_taranis.png} | Bin src/gui/menu_model.cpp | 94 +++++------ src/gui/menus.cpp | 14 +- src/gui/view_about.cpp | 96 ++++++----- src/gui/view_main.cpp | 4 +- src/gui/view_telemetry.cpp | 8 +- src/lcd.cpp | 2 + src/maths.cpp | 7 +- src/opentx.cpp | 161 ++++++++++--------- src/opentx.h | 7 +- src/simpgmspace.cpp | 2 +- src/telemetry/frsky.cpp | 44 ++--- src/translations.cpp | 2 +- src/translations.h | 2 +- src/translations/en.h | 34 ++-- 19 files changed, 259 insertions(+), 232 deletions(-) create mode 100644 src/bitmaps/about_9x.lbm create mode 100644 src/bitmaps/about_9x.png rename src/bitmaps/{about.lbm => about_taranis.lbm} (100%) rename src/bitmaps/{about.png => about_taranis.png} (100%) diff --git a/src/Makefile b/src/Makefile index 7af67af82..278a642f9 100644 --- a/src/Makefile +++ b/src/Makefile @@ -333,7 +333,7 @@ ifeq ($(PCB), $(filter $(PCB), STD128 9X128 9XR128)) EXTRABOARDSRC = targets/stock/lcd_driver.cpp EEPROMSRC = eeprom_common.cpp eeprom_rlc.cpp PULSESSRC = protocols/pulses_avr.cpp - + ifeq ($(PCB), 9XR128) CPPDEFS += -DPCB9XR128 else @@ -537,7 +537,7 @@ ifeq ($(PCB), SKY9X) SRC += targets/sky9x/MEDSdcard.c EEPROMSRC = eeprom_common.cpp eeprom_raw.cpp eeprom_conversions.cpp PULSESSRC = protocols/pulses_arm.cpp protocols/ppm_arm.cpp protocols/pxx_arm.cpp protocols/dsm2_arm.cpp - CPPSRC += audio_arm.cpp haptic.cpp + CPPSRC += audio_arm.cpp haptic.cpp gui/view_about.cpp CPPSRC += targets/sky9x/pwr_driver.cpp targets/sky9x/adc_driver.cpp targets/sky9x/coproc_driver.cpp targets/sky9x/rotenc_driver.cpp targets/sky9x/eeprom_driver.cpp targets/sky9x/pulses_driver.cpp targets/sky9x/keys_driver.cpp targets/sky9x/audio_driver.cpp targets/sky9x/buzzer_driver.cpp targets/sky9x/haptic_driver.cpp targets/sky9x/sdcard_driver.cpp targets/sky9x/massstorage.cpp ifeq ($(SDCARD), YES) @@ -620,7 +620,6 @@ ifeq ($(PCB), TARANIS) SRC += targets/taranis/STM32_USB-Host-Device_Lib_V2.1.0/Libraries/STM32_USB_Device_Library/Class/msc/src/usbd_msc_scsi.c SRC += targets/taranis/STM32_USB-Host-Device_Lib_V2.1.0/Libraries/STM32_USB_Device_Library/Class/msc/src/usbd_msc_bot.c SRC += targets/taranis/STM32_USB-Host-Device_Lib_V2.1.0/Libraries/STM32_USB_Device_Library/Class/msc/src/usbd_msc_core.c - # SRC += targets/taranis/STM32_USB-Host-Device_Lib_V2.1.0/Libraries/STM32_USB_Device_Library/Class/hid/src/usbd_hid_core.c EXTRABOARDSRC += targets/taranis/usbd_usr.cpp targets/taranis/usbd_storage_msd.cpp ifeq ($(SDCARD), YES) @@ -1126,7 +1125,7 @@ bitmaps/font.lbm: bitmaps/font.xbm bitmaps/font_extra.xbm bitmaps/font_tiny.xbm $(IMG2LBM) translations/font_se_08x10.xbm translations/font_se_08x10.lbm 8x10 $(IMG2LBM) translations/font_se_10x14.xbm translations/font_se_10x14.lbm 10x14 -bitmaps/sticks.lbm: bitmaps/sticks_4x1.xbm bitmaps/splash_9x.xbm bitmaps/splash_taranis.png bitmaps/logo_taranis.bmp bitmaps/icons.png bitmaps/asterisk.xbm bitmaps/about.png bitmaps/asterisk_4bits.png +bitmaps/sticks.lbm: bitmaps/sticks_4x1.xbm bitmaps/splash_9x.xbm bitmaps/splash_taranis.png bitmaps/logo_taranis.bmp bitmaps/icons.png bitmaps/asterisk.xbm bitmaps/about_9x.png bitmaps/about_taranis.png bitmaps/asterisk_4bits.png @echo @echo "Convert bitmaps from xbm to lbm:" $(IMG2LBM) bitmaps/sticks_4x1.xbm bitmaps/sticks.lbm img 4 @@ -1135,7 +1134,8 @@ bitmaps/sticks.lbm: bitmaps/sticks_4x1.xbm bitmaps/splash_9x.xbm bitmaps/splash_ $(IMG2LBM) bitmaps/logo_taranis.bmp bitmaps/logo_taranis.lbm bmp $(IMG2LBM) bitmaps/icons.png bitmaps/icons.lbm bmp $(IMG2LBM) bitmaps/asterisk.xbm bitmaps/asterisk.lbm img - $(IMG2LBM) bitmaps/about.png bitmaps/about.lbm bmp + $(IMG2LBM) bitmaps/about_taranis.png bitmaps/about_taranis.lbm bmp + $(IMG2LBM) bitmaps/about_9x.png bitmaps/about_9x.lbm img $(IMG2LBM) bitmaps/asterisk_4bits.png bitmaps/asterisk_4bits.lbm bmp # Eye candy. diff --git a/src/bitmaps/about_9x.lbm b/src/bitmaps/about_9x.lbm new file mode 100644 index 000000000..8b45bad17 --- /dev/null +++ b/src/bitmaps/about_9x.lbm @@ -0,0 +1,4 @@ +11,17, +0x00,0x80,0x80,0xbe,0xe3,0xc1,0xc1,0xc1,0xe3,0xff,0xff, +0x00,0xe7,0x24,0x3c,0x00,0x00,0x00,0x00,0x3f,0x3f,0xff, +0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, diff --git a/src/bitmaps/about_9x.png b/src/bitmaps/about_9x.png new file mode 100644 index 0000000000000000000000000000000000000000..3a9fe2027a5bef901a26f0976773223bf56635f2 GIT binary patch literal 212 zcmeAS@N?(olHy`uVBq!ia0vp^+(0bI!3JVI47&}a7>k44ofy`glX(f`uqAoByDx`7I;J!0~HH{FeAgPITAoY_7YEDSN6MXtekQj{0ns!0);|6T^vI+&aa)| z$;Y6;!7Tac|Nb6zVHLd{U)VC8CC{8W!Z~5)sS__g+pRH_5!?^ZDRE#~weight = 100; } resumeMixerCalculations(); - STORE_MODELVARS; + eeDirty(EE_MODEL); } void copyExpoMix(uint8_t expo, uint8_t idx) @@ -2543,7 +2543,7 @@ void copyExpoMix(uint8_t expo, uint8_t idx) memmove(mix+1, mix, (MAX_MIXERS-(idx+1))*sizeof(MixData)); } resumeMixerCalculations(); - STORE_MODELVARS; + eeDirty(EE_MODEL); } void memswap(void *a, void *b, uint8_t size) @@ -2948,23 +2948,21 @@ static uint8_t s_copySrcCh; #define STR_MAX(x) _STR_MAX(x) #if LCD_W >= 212 -#define EXPO_LINE_WEIGHT_POS 7*FW -#define EXPO_LINE_EXPO_POS 12*FW -#define EXPO_LINE_SWITCH_POS 13*FW+4 -#define EXPO_LINE_SIDE_POS 19*FW -#define EXPO_LINE_SELECT_POS 18 -#elif defined(TRANSLATIONS_CZ) -#define EXPO_LINE_WEIGHT_POS 7*FW-2 -#define EXPO_LINE_EXPO_POS 10*FW+2 -#define EXPO_LINE_SWITCH_POS 13*FW+5 -#define EXPO_LINE_SIDE_POS 17*FW -#define EXPO_LINE_SELECT_POS 24 + #define EXPO_LINE_WEIGHT_POS 7*FW + #define EXPO_LINE_EXPO_POS 12*FW + #define EXPO_LINE_SWITCH_POS 13*FW+4 + #define EXPO_LINE_SIDE_POS 19*FW + #define EXPO_LINE_SELECT_POS 18 #else -#define EXPO_LINE_WEIGHT_POS 6*FW-2 -#define EXPO_LINE_EXPO_POS 9*FW+1 -#define EXPO_LINE_SWITCH_POS 13*FW+4 -#define EXPO_LINE_SIDE_POS 17*FW -#define EXPO_LINE_SELECT_POS 18 + #define EXPO_LINE_WEIGHT_POS 7*FW-1 + #define EXPO_LINE_EXPO_POS 10*FW+5 + #define EXPO_LINE_SWITCH_POS 11*FW+2 + #if MAX_PHASES == 6 + #define EXPO_LINE_SIDE_POS 14*FW+2 + #else + #define EXPO_LINE_SIDE_POS 14*FW+5 + #endif + #define EXPO_LINE_SELECT_POS 24 #endif #if defined(NAVIGATION_MENUS) @@ -3049,7 +3047,7 @@ void menuModelExpoMix(uint8_t expo, uint8_t event) swapExpoMix(expo, s_currIdx, s_copyTgtOfs > 0); s_copyTgtOfs += (s_copyTgtOfs < 0 ? +1 : -1); } while (s_copyTgtOfs != 0); - STORE_MODELVARS; + eeDirty(EE_MODEL); } m_posVert = s_copySrcRow; s_copyTgtOfs = 0; @@ -3147,7 +3145,7 @@ void menuModelExpoMix(uint8_t expo, uint8_t event) else { // only swap the mix with its neighbor if (!swapExpoMix(expo, s_currIdx, IS_ROTARY_UP(event) || key==KEY_MOVE_UP)) break; - STORE_MODELVARS; + eeDirty(EE_MODEL); } s_copyTgtOfs = next_ofs; @@ -3201,22 +3199,14 @@ void menuModelExpoMix(uint8_t expo, uint8_t event) else displayGVar(EXPO_LINE_EXPO_POS, y, ed->curveParam, -100, 100); -#if defined(PCBTARANIS) - putsSwitches(EXPO_LINE_SWITCH_POS, y, ed->swtch, 0); // normal switches - if (ed->name[0]) lcd_putsnAtt(LCD_W-sizeof(ed->name)*FW-MENUS_SCROLLBAR_WIDTH, y, ed->name, sizeof(ed->name), ZCHAR | (isExpoActive(i) ? BOLD : 0)); + putsSwitches(EXPO_LINE_SWITCH_POS, y, ed->swtch, 0); + if (ed->mode!=3) lcd_putc(EXPO_LINE_SIDE_POS, y, ed->mode == 2 ? 126 : 127); -#else + #if defined(CPUARM) - if (ed->name[0]) { - putsSwitches(11*FW, y, ed->swtch, 0); - lcd_putsnAtt(LCD_W-sizeof(ed->name)*FW-MENUS_SCROLLBAR_WIDTH, y, ed->name, sizeof(ed->name), ZCHAR | (isExpoActive(i) ? BOLD : 0)); - } - else -#endif - { - putsSwitches(EXPO_LINE_SWITCH_POS, y, ed->swtch, 0); // normal switches - if (ed->mode!=3) lcd_putc(EXPO_LINE_SIDE_POS, y, ed->mode == 2 ? 126 : 127);//'|' : (stkVal[i] ? '<' : '>'),0);*/ - } + if (ed->name[0]) lcd_putsnAtt(LCD_W-sizeof(ed->name)*FW-MENUS_SCROLLBAR_WIDTH, y, ed->name, sizeof(ed->name), ZCHAR | (isExpoActive(i) ? BOLD : 0)); +#else + editFlightModes(LCD_W-MAX_PHASES*FW-MENUS_SCROLLBAR_WIDTH, y, 0, ed->phases, 0); #endif } else { @@ -3419,7 +3409,7 @@ void menuModelLimits(uint8_t event) LimitData *ld = limitAddress(sub); ld->revert = !ld->revert; s_warning_result = 0; - AUDIO_WARNING2(); + eeDirty(EE_MODEL); } for (uint8_t i=0; ioffset = (ld->revert) ? -zero : zero; resumeMixerCalculations(); s_editMode = 0; - STORE_MODELVARS; + eeDirty(EE_MODEL); } break; case ITEM_LIMITS_MIN: @@ -3920,7 +3910,7 @@ void menuModelCustomSwitches(uint8_t event) #else uint8_t incdecFlag; #define INCDEC_SET_FLAG(f) incdecFlag = (EE_MODEL|(f)) - #define CHECK_INCDEC_CSPARAM(event, var, min, max) var=checkIncDec(event,var,min,max,incdecFlag) + #define CHECK_INCDEC_CSPARAM(event, var, min, max) var = checkIncDec(event, var, min, max, incdecFlag) #endif MENU(STR_MENUCUSTOMSWITCHES, menuTabModel, e_CustomSwitches, NUM_CSW+1, {0, NAVIGATION_LINE_BY_LINE|CSW_FIELD_LAST/*repeated...*/}); @@ -3968,9 +3958,10 @@ void menuModelCustomSwitches(uint8_t event) INCDEC_SET_FLAG(INCDEC_SOURCE); } else if (cstate == CS_VTIMER) { - lcd_outdezAtt(CSW_2ND_COLUMN, y, cs->v1+1, LEFT|attr1); - lcd_outdezAtt(CSW_3RD_COLUMN, y, cs->v2+1, LEFT|attr2); - v1_max = 99; v2_max = 99; + lcd_outdezAtt(CSW_2ND_COLUMN, y, cswTimerValue(cs->v1), LEFT|PREC1|attr1); + lcd_outdezAtt(CSW_3RD_COLUMN, y, cswTimerValue(cs->v2), LEFT|PREC1|attr2); + v1_min = v2_min = -128; + v1_max = v2_max = 122; INCDEC_SET_FLAG(0); } else { @@ -4032,12 +4023,13 @@ void menuModelCustomSwitches(uint8_t event) if ((s_editMode>0 || p1valdiff) && attr) { switch (horz) { case CSW_FIELD_FUNCTION: + { CHECK_INCDEC_MODELVAR_ZERO(event, cs->func, CS_MAXF); - if (cstate != cswFamily(cs->func)) { - cs->v1 = 0; - cs->v2 = 0; - } + uint8_t new_cstate = cswFamily(cs->func); + if (cstate != new_cstate) + cs->v1 = cs->v2 = (new_cstate==CS_VTIMER ? -119/*1.0*/ : 0); break; + } case CSW_FIELD_V1: CHECK_INCDEC_CSPARAM(event, cs->v1, v1_min, v1_max); break; diff --git a/src/gui/menus.cpp b/src/gui/menus.cpp index 11db65b46..d42fa0040 100644 --- a/src/gui/menus.cpp +++ b/src/gui/menus.cpp @@ -889,26 +889,20 @@ int16_t gvarMenuItem(uint8_t x, uint8_t y, int16_t value, int16_t min, int16_t m bool invers = (attr & INVERS); if (invers && event == EVT_KEY_LONG(KEY_ENTER)) { s_editMode = !s_editMode; - value = (GV_IS_GV_VALUE(value,min,max) ? GET_GVAR(value, min, max, s_perout_flight_phase) : delta); + value = (GV_IS_GV_VALUE(value, min, max) ? GET_GVAR(value, min, max, s_perout_flight_phase) : delta); eeDirty(EE_MODEL); } - if (GV_IS_GV_VALUE(value,min,max) ) { + if (GV_IS_GV_VALUE(value, min, max)) { if (attr & LEFT) attr -= LEFT; /* because of ZCHAR */ else x -= 2*FW+FWNUM; - int8_t idx = (int16_t) GV_INDEX_CALC_DELTA(value,delta); + int8_t idx = (int16_t) GV_INDEX_CALC_DELTA(value, delta); if (invers) { CHECK_INCDEC_MODELVAR(event, idx, -MAX_GVARS, MAX_GVARS-1); } -/* sometimes this implementation was smaller, but sometimes not.... - value=delta+(int16_t) idx; - if (idx < 0) {idx = -1-idx; lcd_putcAtt(x-6, y, '-', attr); } - else value|=~(delta-1); - idx++; */ - if (idx < 0) { value = (int16_t) GV_CALC_VALUE_IDX_NEG(idx,delta); idx = -idx; @@ -918,7 +912,6 @@ int16_t gvarMenuItem(uint8_t x, uint8_t y, int16_t value, int16_t min, int16_t m value = (int16_t) GV_CALC_VALUE_IDX_POS(idx,delta); idx++; } - putsStrIdx(x, y, STR_GV, idx, attr); } else { @@ -927,7 +920,6 @@ int16_t gvarMenuItem(uint8_t x, uint8_t y, int16_t value, int16_t min, int16_t m } return value; } - #else int8_t gvarMenuItem(uint8_t x, uint8_t y, int8_t value, int16_t min, int16_t max, LcdFlags attr, uint8_t event) { diff --git a/src/gui/view_about.cpp b/src/gui/view_about.cpp index 1b07633b6..b87f7fbdd 100644 --- a/src/gui/view_about.cpp +++ b/src/gui/view_about.cpp @@ -38,7 +38,11 @@ #if defined(PCBTARANIS) const pm_uchar about_bmp[] PROGMEM = { - #include "../bitmaps/about.lbm" + #include "../bitmaps/about_taranis.lbm" + }; +#else + const pm_uchar about_bmp[] PROGMEM = { + #include "../bitmaps/about_9x.lbm" }; #endif @@ -56,10 +60,18 @@ enum AboutScreens { ABOUT_COUNT, }; +#if defined(PCBTARANIS) + #define ABOUT_X 62 + #define ABOUT_INDENT 6 +#else + #define ABOUT_X 2 + #define ABOUT_INDENT 4 +#endif + void menuAboutView(uint8_t event) { - static int screenIndex; - static int greyIndex; + static uint8_t screenIndex; + static uint8_t greyIndex; switch(event) { @@ -80,73 +92,79 @@ void menuAboutView(uint8_t event) return; } +#if defined(PCBTARANIS) lcd_bmp(0, 0, about_bmp); lcd_putsAtt(64, 0, STR_ABOUTUS, DBLSIZE); - lcd_hline(62, 18, 120); - lcd_hline(62, 19, 130, GREY_DEFAULT); - + lcd_hline(ABOUT_X, 18, 120); + lcd_hline(ABOUT_X, 19, 130, GREY_DEFAULT); LcdFlags att = GREY(max(0, 15-greyIndex/2)); - int screenDuration = 150; +#else + lcd_putsAtt(17, 0, STR_ABOUTUS, DBLSIZE|INVERS); + lcd_hline(17, 16, LCD_W-17); + lcd_img(8, 0, about_bmp, 0); + LcdFlags att = 0; +#endif + + uint8_t screenDuration = 150; switch (screenIndex) { case ABOUT_OPENTX: case ABOUT_END: - lcd_putsAtt(62, 22, STR_ABOUT_OPENTX_1, SMLSIZE); - lcd_putsAtt(62, 30, STR_ABOUT_OPENTX_2, SMLSIZE); - lcd_putsAtt(62, 38, STR_ABOUT_OPENTX_3, SMLSIZE); - lcd_putsAtt(62, 46, STR_ABOUT_OPENTX_4, SMLSIZE); - lcd_putsAtt(62, 54, STR_ABOUT_OPENTX_5, SMLSIZE); - screenDuration = 300; + lcd_putsAtt(ABOUT_X, 22, STR_ABOUT_OPENTX_1, SMLSIZE); + lcd_putsAtt(ABOUT_X, 30, STR_ABOUT_OPENTX_2, SMLSIZE); + lcd_putsAtt(ABOUT_X, 38, STR_ABOUT_OPENTX_3, SMLSIZE); + lcd_putsAtt(ABOUT_X, 46, STR_ABOUT_OPENTX_4, SMLSIZE); + lcd_putsAtt(ABOUT_X, 54, STR_ABOUT_OPENTX_5, SMLSIZE); + screenDuration = 255; break; case ABOUT_BERTRAND: - lcd_putsAtt(62, 24, STR_ABOUT_BERTRAND_1, att); - lcd_putsAtt(68, 36, STR_ABOUT_BERTRAND_2, att|SMLSIZE); - lcd_putsAtt(68, 44, STR_ABOUT_BERTRAND_3, att|SMLSIZE); + lcd_putsAtt(ABOUT_X, 24, STR_ABOUT_BERTRAND_1, att); + lcd_putsAtt(ABOUT_X+ABOUT_INDENT, 36, STR_ABOUT_BERTRAND_2, att|SMLSIZE); + lcd_putsAtt(ABOUT_X+ABOUT_INDENT, 44, STR_ABOUT_BERTRAND_3, att|SMLSIZE); break; case ABOUT_MIKE: - lcd_putsAtt(62, 24, STR_ABOUT_MIKE_1, att); - lcd_putsAtt(68, 36, STR_ABOUT_MIKE_2, att|SMLSIZE); - lcd_putsAtt(68, 44, STR_ABOUT_MIKE_3, att|SMLSIZE); - lcd_putsAtt(67, 52, STR_ABOUT_MIKE_4, att|SMLSIZE); + lcd_putsAtt(ABOUT_X, 24, STR_ABOUT_MIKE_1, att); + lcd_putsAtt(ABOUT_X+ABOUT_INDENT, 36, STR_ABOUT_MIKE_2, att|SMLSIZE); + lcd_putsAtt(ABOUT_X+ABOUT_INDENT, 44, STR_ABOUT_MIKE_3, att|SMLSIZE); + lcd_putsAtt(ABOUT_X+ABOUT_INDENT-1, 52, STR_ABOUT_MIKE_4, att|SMLSIZE); break; case ABOUT_ROMOLO: - lcd_putsAtt(62, 24, STR_ABOUT_ROMOLO_1, att); - lcd_putsAtt(68, 36, STR_ABOUT_ROMOLO_2, att|SMLSIZE); - lcd_putsAtt(68, 44, STR_ABOUT_ROMOLO_3, att|SMLSIZE); + lcd_putsAtt(ABOUT_X, 24, STR_ABOUT_ROMOLO_1, att); + lcd_putsAtt(ABOUT_X+ABOUT_INDENT, 36, STR_ABOUT_ROMOLO_2, att|SMLSIZE); + lcd_putsAtt(ABOUT_X+ABOUT_INDENT, 44, STR_ABOUT_ROMOLO_3, att|SMLSIZE); break; case ABOUT_ANDRE: - lcd_putsAtt(62, 24, STR_ABOUT_ANDRE_1, att); - lcd_putsAtt(68, 36, STR_ABOUT_ANDRE_2, att|SMLSIZE); - lcd_putsAtt(68, 44, STR_ABOUT_ANDRE_3, att|SMLSIZE); + lcd_putsAtt(ABOUT_X, 24, STR_ABOUT_ANDRE_1, att); + lcd_putsAtt(ABOUT_X+ABOUT_INDENT, 36, STR_ABOUT_ANDRE_2, att|SMLSIZE); + lcd_putsAtt(ABOUT_X+ABOUT_INDENT, 44, STR_ABOUT_ANDRE_3, att|SMLSIZE); break; case ABOUT_ROB: - lcd_putsAtt(62, 24, STR_ABOUT_ROB_1, att); - lcd_putsAtt(68, 36, STR_ABOUT_ROB_2, att|SMLSIZE); + lcd_putsAtt(ABOUT_X, 24, STR_ABOUT_ROB_1, att); + lcd_putsAtt(ABOUT_X+ABOUT_INDENT, 36, STR_ABOUT_ROB_2, att|SMLSIZE); break; case ABOUT_MARTIN: - lcd_putsAtt(62, 24, STR_ABOUT_MARTIN_1, att); - lcd_putsAtt(68, 36, STR_ABOUT_MARTIN_2, att|SMLSIZE); + lcd_putsAtt(ABOUT_X, 24, STR_ABOUT_MARTIN_1, att); + lcd_putsAtt(ABOUT_X+ABOUT_INDENT, 36, STR_ABOUT_MARTIN_2, att|SMLSIZE); break; case ABOUT_HARDWARE: - lcd_putsAtt(62, 24, STR_ABOUT_HARDWARE_1, att); - lcd_putsAtt(68, 36, STR_ABOUT_HARDWARE_2, att|SMLSIZE); - lcd_putsAtt(68, 44, STR_ABOUT_HARDWARE_3, att|SMLSIZE); - screenDuration = 300; + lcd_putsAtt(ABOUT_X, 24, STR_ABOUT_HARDWARE_1, att); + lcd_putsAtt(ABOUT_X+ABOUT_INDENT, 36, STR_ABOUT_HARDWARE_2, att|SMLSIZE); + lcd_putsAtt(ABOUT_X+ABOUT_INDENT, 44, STR_ABOUT_HARDWARE_3, att|SMLSIZE); break; case ABOUT_PARENTS: - lcd_putsAtt(62, 24, STR_ABOUT_PARENTS_1, att); - lcd_putsAtt(68, 36, STR_ABOUT_PARENTS_2, att|SMLSIZE); - lcd_putsAtt(68, 44, STR_ABOUT_PARENTS_3, att|SMLSIZE); - lcd_putsAtt(67, 52, STR_ABOUT_PARENTS_4, att|SMLSIZE); - screenDuration = 300; + lcd_putsAtt(ABOUT_X, 24, STR_ABOUT_PARENTS_1, att); + lcd_putsAtt(ABOUT_X+ABOUT_INDENT, 36, STR_ABOUT_PARENTS_2, att|SMLSIZE); + lcd_putsAtt(ABOUT_X+ABOUT_INDENT, 44, STR_ABOUT_PARENTS_3, att|SMLSIZE); + lcd_putsAtt(ABOUT_X+ABOUT_INDENT-1, 52, STR_ABOUT_PARENTS_4, att|SMLSIZE); + screenDuration = 255; break; } diff --git a/src/gui/view_main.cpp b/src/gui/view_main.cpp index a657c4fba..9d5ee81f8 100644 --- a/src/gui/view_main.cpp +++ b/src/gui/view_main.cpp @@ -444,7 +444,7 @@ void onMainViewMenu(const char *result) else if (result == STR_STATISTICS) { chainMenu(menuStatisticsView); } -#if defined(PCBTARANIS) +#if !defined(CPUM64) else if (result == STR_ABOUT_US) { chainMenu(menuAboutView); } @@ -511,7 +511,7 @@ void menuMainView(uint8_t event) MENU_ADD_ITEM(STR_RESET_TELEMETRY); #endif MENU_ADD_ITEM(STR_STATISTICS); -#if defined(PCBTARANIS) +#if !defined(CPUM64) MENU_ADD_ITEM(STR_ABOUT_US); #endif menuHandler = onMainViewMenu; diff --git a/src/gui/view_telemetry.cpp b/src/gui/view_telemetry.cpp index a7e33aa07..85378dcd9 100644 --- a/src/gui/view_telemetry.cpp +++ b/src/gui/view_telemetry.cpp @@ -150,9 +150,11 @@ NOINLINE uint8_t getRssiAlarmValue(uint8_t alarm) void displayVoltageScreenLine(uint8_t y, uint8_t index) { putsStrIdx(0, y, STR_A, index+1, 0); - putsTelemetryChannel(3*FW+6*FW+4, y-FH+1, index+TELEM_A1-1, frskyData.analog[index].value, DBLSIZE); - lcd_putc(12*FW-1, y-FH, '<'); putsTelemetryChannel(17*FW, y-FH, index+TELEM_A1-1, frskyData.analog[index].min, NO_UNIT); - lcd_putc(12*FW, y, '>'); putsTelemetryChannel(17*FW, y, index+TELEM_A1-1, frskyData.analog[index].max, NO_UNIT); + if (TELEMETRY_STREAMING()) { + putsTelemetryChannel(3*FW+6*FW+4, y-FH+1, index+TELEM_A1-1, frskyData.analog[index].value, DBLSIZE); + lcd_putc(12*FW-1, y-FH, '<'); putsTelemetryChannel(17*FW, y-FH, index+TELEM_A1-1, frskyData.analog[index].min, NO_UNIT); + lcd_putc(12*FW, y, '>'); putsTelemetryChannel(17*FW, y, index+TELEM_A1-1, frskyData.analog[index].max, NO_UNIT); + } } #if LCD_W >= 212 diff --git a/src/lcd.cpp b/src/lcd.cpp index c7e60ff0d..74298731d 100644 --- a/src/lcd.cpp +++ b/src/lcd.cpp @@ -992,6 +992,7 @@ void putsTelemetryChannel(xcoord_t x, uint8_t y, uint8_t channel, lcdint_t val, att &= ~NO_UNIT; putsTime(x, y, val, att, att); break; +#if defined(FRSKY) case TELEM_MIN_A1-1: case TELEM_MIN_A2-1: channel -= TELEM_MIN_A1-TELEM_A1; @@ -1021,6 +1022,7 @@ void putsTelemetryChannel(xcoord_t x, uint8_t y, uint8_t channel, lcdint_t val, putsTelemetryValue(x, y, converted_value, g_model.frsky.channels[channel].type, att); break; } +#endif case TELEM_CELL-1: putsTelemetryValue(x, y, val, UNIT_VOLTS, att|PREC2); diff --git a/src/maths.cpp b/src/maths.cpp index 1891b4fd7..12c5dd010 100644 --- a/src/maths.cpp +++ b/src/maths.cpp @@ -36,7 +36,7 @@ #include "opentx.h" -#if defined(FRSKY) || defined(CPUARM) +#if defined(FRSKY) uint16_t getChannelRatio(uint8_t channel) { return (uint16_t)g_model.frsky.channels[channel].ratio << g_model.frsky.channels[channel].multiplier; @@ -44,10 +44,7 @@ uint16_t getChannelRatio(uint8_t channel) lcdint_t applyChannelRatio(uint8_t channel, lcdint_t val) { - if (TELEMETRY_STREAMING()) - return ((int32_t)val+g_model.frsky.channels[channel].offset) * getChannelRatio(channel) * 2 / 51; - else - return 0; + return ((int32_t)val+g_model.frsky.channels[channel].offset) * getChannelRatio(channel) * 2 / 51; } #endif diff --git a/src/opentx.cpp b/src/opentx.cpp index 3eeac014e..f823c7430 100644 --- a/src/opentx.cpp +++ b/src/opentx.cpp @@ -368,6 +368,11 @@ uint8_t cswFamily(uint8_t func) return (funcsrcRaw = channel_order(i+1); } - STORE_MODELVARS; + eeDirty(EE_MODEL); } #endif @@ -919,7 +924,6 @@ uint8_t cswStates[NUM_CSW]; int16_t csLastValue[NUM_CSW]; #define CS_LAST_VALUE_INIT -32768 - bool __getSwitch(int8_t swtch) { bool result; @@ -968,7 +972,7 @@ bool __getSwitch(int8_t swtch) } } else if (s == CS_VTIMER) { - result = int8_t(csLastValue[cs_idx]) >= 0; + result = csLastValue[cs_idx] <= 0; } else { getvalue_t x = getValue(cs->v1-1); @@ -1226,7 +1230,7 @@ void setTrimValue(uint8_t phase, uint8_t idx, int16_t trim) #else p->trim[idx] = trim; #endif - STORE_MODELVARS; + eeDirty(EE_MODEL); } uint8_t getTrimFlightPhase(uint8_t phase, uint8_t idx) @@ -1298,8 +1302,8 @@ uint8_t s_gvar_last = 0; #if defined(PCBSTD) int16_t getGVarValue(int16_t x, int16_t min, int16_t max) { - if (GV_IS_GV_VALUE(x,min,max)) { - int8_t idx = GV_INDEX_CALCULATION(x,max); + if (GV_IS_GV_VALUE(x, min, max)) { + int8_t idx = GV_INDEX_CALCULATION(x, max); int8_t mul = 1; if (idx < 0) { @@ -2303,12 +2307,14 @@ PLAY_FUNCTION(playValue, uint8_t idx) idx -= (MIXSRC_FIRST_TELEM-1+TELEM_A1-1); // A1 and A2 { - uint8_t att = 0; - int16_t converted_value = applyChannelRatio(idx, val) / 10; - if (g_model.frsky.channels[idx].type < UNIT_RAW) { - att = PREC1; + if (TELEMETRY_STREAMING()) { + uint8_t att = 0; + int16_t converted_value = applyChannelRatio(idx, val) / 10; + if (g_model.frsky.channels[idx].type < UNIT_RAW) { + att = PREC1; + } + PLAY_NUMBER(converted_value, 1+g_model.frsky.channels[idx].type, att); } - PLAY_NUMBER(converted_value, 1+g_model.frsky.channels[idx].type, att); break; } @@ -3325,85 +3331,90 @@ void doMixerCalculations() } } //endfor timer loop (only two) - static tmr10ms_t s_time_tot; - static uint8_t s_cnt_1s; - static uint16_t s_sum_1s; + static tmr10ms_t s_cnt_100ms; + static uint8_t s_cnt_1s; + static uint8_t s_cnt_samples_thr_1s; + static uint16_t s_sum_samples_thr_1s; #if defined(THRTRACE) - static tmr10ms_t s_time_trace; - static uint16_t s_cnt_10s; - static uint16_t s_sum_10s; + static uint8_t s_cnt_10s; + static uint16_t s_cnt_samples_thr_10s; + static uint16_t s_sum_samples_thr_10s; #endif - s_cnt_1s++; - s_sum_1s+=val; + s_cnt_samples_thr_1s++; + s_sum_samples_thr_1s+=val; - // @@@ open.20.fsguruh: moved code here; at least val variable conflicts with calculations above, safer here? - // even reduced code size about 8 bytes, why ever? - if ((tmr10ms_t)(tmr10ms - s_time_tot) >= 100) { // 1sec - s_time_tot += 100; - s_timeCumTot += 1; - - struct t_inactivity *ptrInactivity = &inactivity; - FORCE_INDIRECT(ptrInactivity) ; - ptrInactivity->counter++; - if ((((uint8_t)ptrInactivity->counter)&0x07)==0x01 && g_eeGeneral.inactivityTimer && g_vbat100mV>50 && ptrInactivity->counter > ((uint16_t)g_eeGeneral.inactivityTimer*60)) - AUDIO_INACTIVITY(); - -#if defined(AUDIO) - if (mixWarning & 1) if ((s_timeCumTot&0x03)==0) AUDIO_MIX_WARNING(1); - if (mixWarning & 2) if ((s_timeCumTot&0x03)==1) AUDIO_MIX_WARNING(2); - if (mixWarning & 4) if ((s_timeCumTot&0x03)==2) AUDIO_MIX_WARNING(3); -#endif - -#if defined(ACCURAT_THROTTLE_TIMER) - val = s_sum_1s / s_cnt_1s; - s_timeCum16ThrP += (val>>3); // s_timeCum16ThrP would overrun if we would store throttle value with higher accuracy; therefore stay with 16 steps - if (val) s_timeCumThr += 1; - s_sum_1s>>=2; // correct better accuracy now, because trace graph can show this information; in case thrtrace is not active, the compile should remove this -#else - val = s_sum_1s / s_cnt_1s; - s_timeCum16ThrP += (val>>1); - if (val) s_timeCumThr += 1; -#endif - -#if defined(THRTRACE) - // throttle trace is done every 10 seconds; Tracebuffer is adjusted to screen size. - // in case buffer runs out, it wraps around - // resolution for y axis is only 32, therefore no higher value makes sense - s_cnt_10s += s_cnt_1s; - s_sum_10s += s_sum_1s; - - if ((tmr10ms_t)(tmr10ms - s_time_trace) >= 1000) { // 10s - s_time_trace += 1000; - val = s_sum_10s / s_cnt_10s; - s_sum_10s = 0; - s_cnt_10s = 0; - - s_traceBuf[s_traceWr++] = val; - if (s_traceWr >= MAXTRACE) s_traceWr = 0; - if (s_traceCnt >= 0) s_traceCnt++; - } -#endif - - s_cnt_1s = 0; - s_sum_1s = 0; + if ((tmr10ms_t)(tmr10ms - s_cnt_100ms) >= 10) { // 0.1sec + s_cnt_100ms += 10; + s_cnt_1s += 1; for (uint8_t i=0; ifunc == CS_TIMER) { - if (*lastValue == 0) { - *lastValue = -cs->v1-1; + int16_t *lastValue = &csLastValue[i]; + if (*lastValue == 0 || *lastValue == CS_LAST_VALUE_INIT) { + *lastValue = -cswTimerValue(cs->v1); } else if (*lastValue < 0) { if (++(*lastValue) == 0) - *lastValue = cs->v2; + *lastValue = cswTimerValue(cs->v2); } else { // if (*lastValue > 0) *lastValue -= 1; } } } + + if (s_cnt_1s >= 10) { // 1sec + s_cnt_1s -= 10; + s_timeCumTot += 1; + + struct t_inactivity *ptrInactivity = &inactivity; + FORCE_INDIRECT(ptrInactivity) ; + ptrInactivity->counter++; + if ((((uint8_t)ptrInactivity->counter)&0x07)==0x01 && g_eeGeneral.inactivityTimer && g_vbat100mV>50 && ptrInactivity->counter > ((uint16_t)g_eeGeneral.inactivityTimer*60)) + AUDIO_INACTIVITY(); + +#if defined(AUDIO) + if (mixWarning & 1) if ((s_timeCumTot&0x03)==0) AUDIO_MIX_WARNING(1); + if (mixWarning & 2) if ((s_timeCumTot&0x03)==1) AUDIO_MIX_WARNING(2); + if (mixWarning & 4) if ((s_timeCumTot&0x03)==2) AUDIO_MIX_WARNING(3); +#endif + +#if defined(ACCURAT_THROTTLE_TIMER) + val = s_sum_samples_thr_1s / s_cnt_samples_thr_1s; + s_timeCum16ThrP += (val>>3); // s_timeCum16ThrP would overrun if we would store throttle value with higher accuracy; therefore stay with 16 steps + if (val) s_timeCumThr += 1; + s_sum_samples_thr_1s>>=2; // correct better accuracy now, because trace graph can show this information; in case thrtrace is not active, the compile should remove this +#else + val = s_sum_samples_thr_1s / s_cnt_samples_thr_1s; + s_timeCum16ThrP += (val>>1); + if (val) s_timeCumThr += 1; +#endif + +#if defined(THRTRACE) + // throttle trace is done every 10 seconds; Tracebuffer is adjusted to screen size. + // in case buffer runs out, it wraps around + // resolution for y axis is only 32, therefore no higher value makes sense + s_cnt_10s += 1; + s_cnt_samples_thr_10s += s_cnt_samples_thr_1s; + s_sum_samples_thr_10s += s_sum_samples_thr_1s; + + if (s_cnt_10s >= 10) { // 10s + s_cnt_1s -= 10; + val = s_sum_samples_thr_10s / s_cnt_samples_thr_10s; + s_sum_samples_thr_10s = 0; + s_cnt_samples_thr_10s = 0; + + s_traceBuf[s_traceWr++] = val; + if (s_traceWr >= MAXTRACE) s_traceWr = 0; + if (s_traceCnt >= 0) s_traceCnt++; + } +#endif + + s_cnt_samples_thr_1s = 0; + s_sum_samples_thr_1s = 0; + } } if (s_fade_flight_phases) { @@ -3998,7 +4009,7 @@ void instantTrim() } } - STORE_MODELVARS; + eeDirty(EE_MODEL); AUDIO_WARNING2(); } @@ -4038,7 +4049,7 @@ void moveTrimsToOffsets() // copy state of 3 primary to subtrim resumeMixerCalculations(); - STORE_MODELVARS; + eeDirty(EE_MODEL); AUDIO_WARNING2(); } diff --git a/src/opentx.h b/src/opentx.h index 33a548743..5b905d724 100644 --- a/src/opentx.h +++ b/src/opentx.h @@ -602,6 +602,7 @@ enum CswFunctions { #define CS_VDIFF 3 #define CS_VTIMER 4 uint8_t cswFamily(uint8_t func); +int16_t cswTimerValue(int8_t val); #define NUM_CYC 3 #define NUM_CAL_PPM 4 @@ -891,6 +892,9 @@ extern int8_t safetyCh[NUM_CHNOUT]; extern uint8_t trimsCheckTimer; +extern int16_t csLastValue[NUM_CSW]; +#define CS_LAST_VALUE_INIT -32768 + #define TMR_OFF 0 #define TMR_RUNNING 1 #define TMR_BEEPING 2 @@ -947,9 +951,6 @@ void checkAll(); void getADC(); #endif -#define STORE_MODELVARS eeDirty(EE_MODEL) -#define STORE_GENERALVARS eeDirty(EE_GENERAL) - extern void backlightOn(); enum Analogs { diff --git a/src/simpgmspace.cpp b/src/simpgmspace.cpp index 91093a363..e769ec8f6 100644 --- a/src/simpgmspace.cpp +++ b/src/simpgmspace.cpp @@ -308,7 +308,7 @@ void *main_thread(void *) while (main_thread_running) { perMain(); - sleep(1/*ms*/); + sleep(10/*ms*/); } #ifdef SIMU_EXCEPTIONS } diff --git a/src/telemetry/frsky.cpp b/src/telemetry/frsky.cpp index 4afbbf48c..11c1475e0 100644 --- a/src/telemetry/frsky.cpp +++ b/src/telemetry/frsky.cpp @@ -662,40 +662,42 @@ void telemetryInterrupt10ms() frskyData.hub.cellsSum = voltage; #endif - uint8_t channel = g_model.frsky.voltsSource; - if (channel <= 1) { - voltage = applyChannelRatio(channel, frskyData.analog[channel].value) / 10; - } + if (TELEMETRY_STREAMING()) { + uint8_t channel = g_model.frsky.voltsSource; + if (channel <= 1) { + voltage = applyChannelRatio(channel, frskyData.analog[channel].value) / 10; + } #if defined(FRSKY_HUB) - else if (channel == 2) { - voltage = frskyData.hub.vfas; - } + else if (channel == 2) { + voltage = frskyData.hub.vfas; + } #endif #if defined(FRSKY_HUB) - uint16_t current = frskyData.hub.current; /* unit: 1/10 amps */ + uint16_t current = frskyData.hub.current; /* unit: 1/10 amps */ #else - uint16_t current = 0; + uint16_t current = 0; #endif - channel = g_model.frsky.currentSource - FRSKY_SOURCE_A1; - if (channel <= 1) { - current = applyChannelRatio(channel, frskyData.analog[channel].value) / 10; - } + channel = g_model.frsky.currentSource - FRSKY_SOURCE_A1; + if (channel <= 1) { + current = applyChannelRatio(channel, frskyData.analog[channel].value) / 10; + } #if defined(CPUARM) - frskyData.hub.power = (current * voltage) / 100; + frskyData.hub.power = (current * voltage) / 100; #else - frskyData.hub.power = ((current>>1) * (voltage>>1)) / 25; + frskyData.hub.power = ((current>>1) * (voltage>>1)) / 25; #endif - if (frskyData.hub.power > frskyData.hub.maxPower) - frskyData.hub.maxPower = frskyData.hub.power; + if (frskyData.hub.power > frskyData.hub.maxPower) + frskyData.hub.maxPower = frskyData.hub.power; - frskyData.hub.currentPrescale += current; - if (frskyData.hub.currentPrescale >= 3600) { - frskyData.hub.currentConsumption += 1; - frskyData.hub.currentPrescale -= 3600; + frskyData.hub.currentPrescale += current; + if (frskyData.hub.currentPrescale >= 3600) { + frskyData.hub.currentConsumption += 1; + frskyData.hub.currentPrescale -= 3600; + } } } diff --git a/src/translations.cpp b/src/translations.cpp index 1e53ddd1b..8cb9b6fec 100644 --- a/src/translations.cpp +++ b/src/translations.cpp @@ -457,7 +457,7 @@ const pm_char STR_CHANNELS_MONITOR[] PROGMEM = TR_CHANNELS_MONITOR; const pm_char STR_CRITICALALARM[] PROGMEM = TR_CRITICALALARM; #endif -#if defined(PCBTARANIS) +#if !defined(CPUM64) const pm_char STR_ABOUTUS[] PROGMEM = TR_ABOUTUS; const pm_char STR_ABOUT_OPENTX_1[] PROGMEM = TR_ABOUT_OPENTX_1; const pm_char STR_ABOUT_OPENTX_2[] PROGMEM = TR_ABOUT_OPENTX_2; diff --git a/src/translations.h b/src/translations.h index 581c8d2fa..731abdd0a 100644 --- a/src/translations.h +++ b/src/translations.h @@ -631,7 +631,7 @@ extern const pm_char STR_CHANNELS_MONITOR[]; extern const pm_char STR_CRITICALALARM[]; #endif -#if defined(PCBTARANIS) +#if !defined(CPUM64) extern const pm_char STR_ABOUTUS[]; extern const pm_char STR_ABOUT_OPENTX_1[]; extern const pm_char STR_ABOUT_OPENTX_2[]; diff --git a/src/translations/en.h b/src/translations/en.h index 13247956a..c8ededd76 100644 --- a/src/translations/en.h +++ b/src/translations/en.h @@ -646,26 +646,26 @@ #define TR_LIMITS_HEADERS { " Name ", " Subtrim ", " Min ", " Max ", " Direction ", " PPM Center ", " Subtrim mode " } #define TR_CSW_HEADERS { " Function ", " V1 ", " V2 ", " AND Switch ", " Duration ", " Delay " } -//Taranis About screen -#define TR_ABOUTUS "ABOUT US" +// About screen +#define TR_ABOUTUS TR(" ABOUT US ", "ABOUT US") -#define TR_ABOUT_OPENTX_1 "OpenTX is open source, non-" -#define TR_ABOUT_OPENTX_2 "commercial and comes with no" -#define TR_ABOUT_OPENTX_3 "warranties. It was developed" -#define TR_ABOUT_OPENTX_4 "for free. Support through" -#define TR_ABOUT_OPENTX_5 "donations is welcome!" +#define TR_ABOUT_OPENTX_1 TR("OpenTX\001is\001open\001source,\001non", "OpenTX is open source, non-") +#define TR_ABOUT_OPENTX_2 TR("commercial,\001wo\001warranties.", "commercial and comes with no") +#define TR_ABOUT_OPENTX_3 TR("It\001was\001developed\001for\001free.", "warranties. It was developed") +#define TR_ABOUT_OPENTX_4 TR("Support through donations", "for free. Support through") +#define TR_ABOUT_OPENTX_5 TR("is welcome!", "donations is welcome!") #define TR_ABOUT_BERTRAND_1 "Bertrand Songis" #define TR_ABOUT_BERTRAND_2 "OpenTX main author" -#define TR_ABOUT_BERTRAND_3 "Companion9x co-developer" +#define TR_ABOUT_BERTRAND_3 "Companion9x co-author" #define TR_ABOUT_MIKE_1 "Mike Blandford" #define TR_ABOUT_MIKE_2 "Code and drivers guru" -#define TR_ABOUT_MIKE_3 "Arguably, one of the best" +#define TR_ABOUT_MIKE_3 TR("Arguably,\001one\001of\001the\001best", "Arguably, one of the best") #define TR_ABOUT_MIKE_4 "Inspirational" #define TR_ABOUT_ROMOLO_1 "Romolo Manfredini" -#define TR_ABOUT_ROMOLO_2 "Companion9x main developer" +#define TR_ABOUT_ROMOLO_2 "Companion9x co-author" #define TR_ABOUT_ROMOLO_3 "" #define TR_ABOUT_ANDRE_1 "Andre Bernet" @@ -678,12 +678,18 @@ #define TR_ABOUT_MARTIN_1 "Martin Hotar" #define TR_ABOUT_MARTIN_2 "Graphics designer" -#define TR_ABOUT_HARDWARE_1 "FrSky" -#define TR_ABOUT_HARDWARE_2 "Hardware designer/producer" -#define TR_ABOUT_HARDWARE_3 "" +#if defined(PCBTARANIS) + #define TR_ABOUT_HARDWARE_1 "FrSky" + #define TR_ABOUT_HARDWARE_2 "Hardware designer/producer" + #define TR_ABOUT_HARDWARE_3 "" +#else + #define TR_ABOUT_HARDWARE_1 "Brent Nelson" + #define TR_ABOUT_HARDWARE_2 "Sky9x designer/producer" + #define TR_ABOUT_HARDWARE_3 "" +#endif #define TR_ABOUT_PARENTS_1 "Parent projects" -#define TR_ABOUT_PARENTS_2 "ersky9x (Mike Blandford)" +#define TR_ABOUT_PARENTS_2 TR("Ersky9x (Mike Blandford)", "Ersky9x (Mike Blandford)") #define TR_ABOUT_PARENTS_3 "ER9X (Erez Raviv)" #define TR_ABOUT_PARENTS_4 "TH9X (Thomas Husterer)"