diff --git a/companion/src/firmwares/opentx/opentxGruvin9xsimulator.cpp b/companion/src/firmwares/opentx/opentxGruvin9xsimulator.cpp index f81b8b20e..a721d414b 100644 --- a/companion/src/firmwares/opentx/opentxGruvin9xsimulator.cpp +++ b/companion/src/firmwares/opentx/opentxGruvin9xsimulator.cpp @@ -74,6 +74,10 @@ namespace Open9xGruvin9x { #include "radio/src/stamp.cpp" #include "radio/src/maths.cpp" #include "radio/src/vario.cpp" +#include "radio/src/gui/9X/widgets.cpp" +#include "radio/src/gui/9X/navigation.cpp" +#include "radio/src/gui/9X/popups.cpp" +#include "radio/src/gui/9X/helpers.cpp" #include "radio/src/gui/menus.cpp" #include "radio/src/gui/menu_model.cpp" #include "radio/src/gui/9X/menu_model_select.cpp" @@ -88,15 +92,15 @@ namespace Open9xGruvin9x { #include "radio/src/gui/9X/menu_model_telemetry.cpp" #include "radio/src/gui/9X/menu_model_templates.cpp" #include "radio/src/gui/menu_general.cpp" -#include "radio/src/gui/menu_general_setup.cpp" -#include "radio/src/gui/menu_general_trainer.cpp" -#include "radio/src/gui/menu_general_version.cpp" -#include "radio/src/gui/menu_general_diagkeys.cpp" -#include "radio/src/gui/menu_general_diaganas.cpp" -#include "radio/src/gui/menu_general_calib.cpp" +#include "radio/src/gui/9X/menu_general_setup.cpp" +#include "radio/src/gui/9X/menu_general_trainer.cpp" +#include "radio/src/gui/9X/menu_general_version.cpp" +#include "radio/src/gui/9X/menu_general_diagkeys.cpp" +#include "radio/src/gui/9X/menu_general_diaganas.cpp" +#include "radio/src/gui/9X/menu_general_calib.cpp" #include "radio/src/gui/9X/view_main.cpp" -#include "radio/src/gui/view_statistics.cpp" -#include "radio/src/gui/view_telemetry.cpp" +#include "radio/src/gui/9X/view_statistics.cpp" +#include "radio/src/gui/9X/view_telemetry.cpp" #include "radio/src/lcd_common.cpp" #include "radio/src/lcd_default.cpp" #include "radio/src/keys.cpp" diff --git a/companion/src/firmwares/opentx/opentxM128simulator.cpp b/companion/src/firmwares/opentx/opentxM128simulator.cpp index 6b551a803..a062a6c96 100644 --- a/companion/src/firmwares/opentx/opentxM128simulator.cpp +++ b/companion/src/firmwares/opentx/opentxM128simulator.cpp @@ -75,6 +75,10 @@ namespace OpenTxM128 { #include "radio/src/stamp.cpp" #include "radio/src/maths.cpp" #include "radio/src/vario.cpp" +#include "radio/src/gui/9X/widgets.cpp" +#include "radio/src/gui/9X/navigation.cpp" +#include "radio/src/gui/9X/popups.cpp" +#include "radio/src/gui/9X/helpers.cpp" #include "radio/src/gui/menus.cpp" #include "radio/src/gui/menu_model.cpp" #include "radio/src/gui/9X/menu_model_select.cpp" @@ -89,15 +93,15 @@ namespace OpenTxM128 { #include "radio/src/gui/9X/menu_model_telemetry.cpp" #include "radio/src/gui/9X/menu_model_templates.cpp" #include "radio/src/gui/menu_general.cpp" -#include "radio/src/gui/menu_general_setup.cpp" -#include "radio/src/gui/menu_general_trainer.cpp" -#include "radio/src/gui/menu_general_version.cpp" -#include "radio/src/gui/menu_general_diagkeys.cpp" -#include "radio/src/gui/menu_general_diaganas.cpp" -#include "radio/src/gui/menu_general_calib.cpp" +#include "radio/src/gui/9X/menu_general_setup.cpp" +#include "radio/src/gui/9X/menu_general_trainer.cpp" +#include "radio/src/gui/9X/menu_general_version.cpp" +#include "radio/src/gui/9X/menu_general_diagkeys.cpp" +#include "radio/src/gui/9X/menu_general_diaganas.cpp" +#include "radio/src/gui/9X/menu_general_calib.cpp" #include "radio/src/gui/9X/view_main.cpp" -#include "radio/src/gui/view_statistics.cpp" -#include "radio/src/gui/view_telemetry.cpp" +#include "radio/src/gui/9X/view_statistics.cpp" +#include "radio/src/gui/9X/view_telemetry.cpp" #include "radio/src/lcd_common.cpp" #include "radio/src/lcd_default.cpp" #include "radio/src/keys.cpp" diff --git a/companion/src/firmwares/opentx/opentxM64simulator.cpp b/companion/src/firmwares/opentx/opentxM64simulator.cpp index a91c16d94..1fafe32c3 100644 --- a/companion/src/firmwares/opentx/opentxM64simulator.cpp +++ b/companion/src/firmwares/opentx/opentxM64simulator.cpp @@ -78,6 +78,10 @@ namespace OpenTxM64 { #include "radio/src/stamp.cpp" #include "radio/src/maths.cpp" #include "radio/src/vario.cpp" +#include "radio/src/gui/9X/widgets.cpp" +#include "radio/src/gui/9X/navigation.cpp" +#include "radio/src/gui/9X/popups.cpp" +#include "radio/src/gui/9X/helpers.cpp" #include "radio/src/gui/menus.cpp" #include "radio/src/gui/menu_model.cpp" #include "radio/src/gui/9X/menu_model_select.cpp" @@ -92,15 +96,15 @@ namespace OpenTxM64 { #include "radio/src/gui/9X/menu_model_telemetry.cpp" #include "radio/src/gui/9X/menu_model_templates.cpp" #include "radio/src/gui/menu_general.cpp" -#include "radio/src/gui/menu_general_setup.cpp" -#include "radio/src/gui/menu_general_trainer.cpp" -#include "radio/src/gui/menu_general_version.cpp" -#include "radio/src/gui/menu_general_diagkeys.cpp" -#include "radio/src/gui/menu_general_diaganas.cpp" -#include "radio/src/gui/menu_general_calib.cpp" +#include "radio/src/gui/9X/menu_general_setup.cpp" +#include "radio/src/gui/9X/menu_general_trainer.cpp" +#include "radio/src/gui/9X/menu_general_version.cpp" +#include "radio/src/gui/9X/menu_general_diagkeys.cpp" +#include "radio/src/gui/9X/menu_general_diaganas.cpp" +#include "radio/src/gui/9X/menu_general_calib.cpp" #include "radio/src/gui/9X/view_main.cpp" -#include "radio/src/gui/view_statistics.cpp" -#include "radio/src/gui/view_telemetry.cpp" +#include "radio/src/gui/9X/view_statistics.cpp" +#include "radio/src/gui/9X/view_telemetry.cpp" #include "radio/src/lcd_common.cpp" #include "radio/src/lcd_default.cpp" #include "radio/src/keys.cpp" diff --git a/companion/src/firmwares/opentx/opentxSky9xsimulator.cpp b/companion/src/firmwares/opentx/opentxSky9xsimulator.cpp index 45ef2a1e1..5a52cb040 100644 --- a/companion/src/firmwares/opentx/opentxSky9xsimulator.cpp +++ b/companion/src/firmwares/opentx/opentxSky9xsimulator.cpp @@ -90,6 +90,10 @@ namespace Open9xSky9x { #include "radio/src/maths.cpp" #include "radio/src/vario.cpp" #include "radio/src/sdcard.cpp" +#include "radio/src/gui/9X/widgets.cpp" +#include "radio/src/gui/9X/navigation.cpp" +#include "radio/src/gui/9X/popups.cpp" +#include "radio/src/gui/9X/helpers.cpp" #include "radio/src/gui/menus.cpp" #include "radio/src/gui/menu_model.cpp" #include "radio/src/gui/9X/menu_model_select.cpp" @@ -104,19 +108,19 @@ namespace Open9xSky9x { #include "radio/src/gui/9X/menu_model_telemetry.cpp" #include "radio/src/gui/9X/menu_model_templates.cpp" #include "radio/src/gui/menu_general.cpp" -#include "radio/src/gui/menu_general_setup.cpp" -#include "radio/src/gui/menu_general_sdmanager.cpp" -#include "radio/src/gui/menu_general_trainer.cpp" -#include "radio/src/gui/menu_general_version.cpp" -#include "radio/src/gui/menu_general_diagkeys.cpp" -#include "radio/src/gui/menu_general_diaganas.cpp" -#include "radio/src/gui/menu_general_hardware.cpp" -#include "radio/src/gui/menu_general_calib.cpp" +#include "radio/src/gui/9X/menu_general_setup.cpp" +#include "radio/src/gui/9X/menu_general_sdmanager.cpp" +#include "radio/src/gui/9X/menu_general_trainer.cpp" +#include "radio/src/gui/9X/menu_general_version.cpp" +#include "radio/src/gui/9X/menu_general_diagkeys.cpp" +#include "radio/src/gui/9X/menu_general_diaganas.cpp" +#include "radio/src/gui/9X/menu_general_hardware.cpp" +#include "radio/src/gui/9X/menu_general_calib.cpp" #include "radio/src/gui/9X/view_main.cpp" -#include "radio/src/gui/view_statistics.cpp" -#include "radio/src/gui/view_telemetry.cpp" +#include "radio/src/gui/9X/view_statistics.cpp" +#include "radio/src/gui/9X/view_telemetry.cpp" #include "radio/src/gui/view_about.cpp" -#include "radio/src/gui/view_text.cpp" +#include "radio/src/gui/9X/view_text.cpp" #include "radio/src/lcd_common.cpp" #include "radio/src/lcd_default.cpp" #include "radio/src/logs.cpp" diff --git a/companion/src/firmwares/opentx/opentxTaranisSimulator.cpp b/companion/src/firmwares/opentx/opentxTaranisSimulator.cpp index e628ad2be..c4c784b1a 100644 --- a/companion/src/firmwares/opentx/opentxTaranisSimulator.cpp +++ b/companion/src/firmwares/opentx/opentxTaranisSimulator.cpp @@ -95,6 +95,10 @@ inline int geteepromsize() { #include "radio/src/stamp.cpp" #include "radio/src/maths.cpp" #include "radio/src/vario.cpp" +#include "radio/src/gui/Taranis/widgets.cpp" +#include "radio/src/gui/Taranis/navigation.cpp" +#include "radio/src/gui/Taranis/popups.cpp" +#include "radio/src/gui/Taranis/helpers.cpp" #include "radio/src/gui/menus.cpp" #include "radio/src/gui/menu_model.cpp" #include "radio/src/gui/Taranis/menu_model_select.cpp" @@ -110,19 +114,19 @@ inline int geteepromsize() { #include "radio/src/gui/Taranis/menu_model_limits.cpp" #include "radio/src/gui/Taranis/menu_model_telemetry.cpp" #include "radio/src/gui/menu_general.cpp" -#include "radio/src/gui/menu_general_setup.cpp" -#include "radio/src/gui/menu_general_sdmanager.cpp" -#include "radio/src/gui/menu_general_trainer.cpp" -#include "radio/src/gui/menu_general_version.cpp" -#include "radio/src/gui/menu_general_diagkeys.cpp" -#include "radio/src/gui/menu_general_diaganas.cpp" -#include "radio/src/gui/menu_general_hardware.cpp" -#include "radio/src/gui/menu_general_calib.cpp" +#include "radio/src/gui/Taranis/menu_general_setup.cpp" +#include "radio/src/gui/Taranis/menu_general_sdmanager.cpp" +#include "radio/src/gui/Taranis/menu_general_trainer.cpp" +#include "radio/src/gui/Taranis/menu_general_version.cpp" +#include "radio/src/gui/Taranis/menu_general_diagkeys.cpp" +#include "radio/src/gui/Taranis/menu_general_diaganas.cpp" +#include "radio/src/gui/Taranis/menu_general_hardware.cpp" +#include "radio/src/gui/Taranis/menu_general_calib.cpp" #include "radio/src/gui/Taranis/view_main.cpp" -#include "radio/src/gui/view_statistics.cpp" +#include "radio/src/gui/Taranis/view_statistics.cpp" #include "radio/src/gui/view_channels.cpp" -#include "radio/src/gui/view_telemetry.cpp" -#include "radio/src/gui/view_text.cpp" +#include "radio/src/gui/Taranis/view_telemetry.cpp" +#include "radio/src/gui/Taranis/view_text.cpp" #include "radio/src/gui/view_about.cpp" #include "radio/src/lcd_common.cpp" #include "radio/src/lcd_taranis.cpp" diff --git a/companion/src/firmwares/opentx/opentxTaranisX9ESimulator.cpp b/companion/src/firmwares/opentx/opentxTaranisX9ESimulator.cpp index b92311226..d1942e1c3 100755 --- a/companion/src/firmwares/opentx/opentxTaranisX9ESimulator.cpp +++ b/companion/src/firmwares/opentx/opentxTaranisX9ESimulator.cpp @@ -97,6 +97,10 @@ inline int geteepromsize() { #include "radio/src/stamp.cpp" #include "radio/src/maths.cpp" #include "radio/src/vario.cpp" +#include "radio/src/gui/Taranis/widgets.cpp" +#include "radio/src/gui/Taranis/navigation.cpp" +#include "radio/src/gui/Taranis/popups.cpp" +#include "radio/src/gui/Taranis/helpers.cpp" #include "radio/src/gui/menus.cpp" #include "radio/src/gui/menu_model.cpp" #include "radio/src/gui/Taranis/menu_model_select.cpp" @@ -112,19 +116,19 @@ inline int geteepromsize() { #include "radio/src/gui/Taranis/menu_model_limits.cpp" #include "radio/src/gui/Taranis/menu_model_telemetry.cpp" #include "radio/src/gui/menu_general.cpp" -#include "radio/src/gui/menu_general_setup.cpp" -#include "radio/src/gui/menu_general_sdmanager.cpp" -#include "radio/src/gui/menu_general_trainer.cpp" -#include "radio/src/gui/menu_general_version.cpp" -#include "radio/src/gui/menu_general_diagkeys.cpp" -#include "radio/src/gui/menu_general_diaganas.cpp" -#include "radio/src/gui/menu_general_hardware.cpp" -#include "radio/src/gui/menu_general_calib.cpp" +#include "radio/src/gui/Taranis/menu_general_setup.cpp" +#include "radio/src/gui/Taranis/menu_general_sdmanager.cpp" +#include "radio/src/gui/Taranis/menu_general_trainer.cpp" +#include "radio/src/gui/Taranis/menu_general_version.cpp" +#include "radio/src/gui/Taranis/menu_general_diagkeys.cpp" +#include "radio/src/gui/Taranis/menu_general_diaganas.cpp" +#include "radio/src/gui/Taranis/menu_general_hardware.cpp" +#include "radio/src/gui/Taranis/menu_general_calib.cpp" #include "radio/src/gui/Taranis/view_main.cpp" -#include "radio/src/gui/view_statistics.cpp" +#include "radio/src/gui/Taranis/view_statistics.cpp" #include "radio/src/gui/view_channels.cpp" -#include "radio/src/gui/view_telemetry.cpp" -#include "radio/src/gui/view_text.cpp" +#include "radio/src/gui/Taranis/view_telemetry.cpp" +#include "radio/src/gui/Taranis/view_text.cpp" #include "radio/src/gui/view_about.cpp" #include "radio/src/lcd_common.cpp" #include "radio/src/lcd_taranis.cpp" diff --git a/companion/src/radiointerface.cpp b/companion/src/radiointerface.cpp index f10bcfbcb..de78c4152 100755 --- a/companion/src/radiointerface.cpp +++ b/companion/src/radiointerface.cpp @@ -396,7 +396,9 @@ QString findMassstoragePath(const QString &filename) eepromfile.append("/" + filename); #if !defined __APPLE__ QString fstype = entry->me_type; - if (QFile::exists(eepromfile) && fstype.contains("fat") ) { + // qDebug() << eepromfile; + + if (fstype.contains("fat") && QFile::exists(eepromfile)) { #else if (QFile::exists(eepromfile)) { #endif diff --git a/radio/src/Makefile b/radio/src/Makefile index 029d34da6..2bac1f46f 100644 --- a/radio/src/Makefile +++ b/radio/src/Makefile @@ -366,7 +366,7 @@ M2561_VARIANT = +16384 EEPROM_VARIANT = 0 GUIMODELSRC = gui/menu_model.cpp gui/$(GUIDIRECTORY)/menu_model_select.cpp gui/$(GUIDIRECTORY)/menu_model_setup.cpp gui/$(GUIDIRECTORY)/menu_model_inputs_mixes.cpp gui/$(GUIDIRECTORY)/menu_model_limits.cpp gui/$(GUIDIRECTORY)/menu_model_logical_switches.cpp gui/$(GUIDIRECTORY)/menu_model_custom_functions.cpp gui/$(GUIDIRECTORY)/menu_model_telemetry.cpp -GUIGENERALSRC = gui/menu_general.cpp gui/menu_general_setup.cpp gui/menu_general_trainer.cpp gui/menu_general_version.cpp gui/menu_general_diagkeys.cpp gui/menu_general_diaganas.cpp gui/menu_general_calib.cpp +GUIGENERALSRC = gui/menu_general.cpp gui/$(GUIDIRECTORY)/menu_general_setup.cpp gui/$(GUIDIRECTORY)/menu_general_trainer.cpp gui/$(GUIDIRECTORY)/menu_general_version.cpp gui/$(GUIDIRECTORY)/menu_general_calib.cpp BITMAPS = bitmaps/sticks.lbm @@ -391,6 +391,7 @@ ifeq ($(PCB), $(filter $(PCB), STD 9X 9XR)) PULSESSRC = pulses/pulses_avr.cpp CPPSRC += debug.cpp BITMAPS += bitmaps/9X/splash.lbm bitmaps/9X/asterisk.lbm bitmaps/9X/about.lbm + GUIGENERALSRC += gui/$(GUIDIRECTORY)/menu_general_diagkeys.cpp gui/$(GUIDIRECTORY)/menu_general_diaganas.cpp ifeq ($(PCB), 9XR) FLAVOUR = 9xr @@ -461,6 +462,7 @@ ifeq ($(PCB), $(filter $(PCB), STD128 9X128 9XR128)) PULSESSRC = pulses/pulses_avr.cpp CPPSRC += debug.cpp BITMAPS += bitmaps/9X/splash.lbm bitmaps/9X/asterisk.lbm bitmaps/9X/about.lbm + GUIGENERALSRC += gui/$(GUIDIRECTORY)/menu_general_diagkeys.cpp gui/$(GUIDIRECTORY)/menu_general_diaganas.cpp ifeq ($(PCB), 9XR128) FLAVOUR = 9xr128 @@ -527,6 +529,7 @@ ifeq ($(PCB), $(filter $(PCB), 9X2561)) PULSESSRC = pulses/pulses_avr.cpp CPPSRC += debug.cpp BITMAPS += bitmaps/9X/splash.lbm bitmaps/9X/asterisk.lbm bitmaps/9X/about.lbm + GUIGENERALSRC += gui/$(GUIDIRECTORY)/menu_general_diagkeys.cpp gui/$(GUIDIRECTORY)/menu_general_diaganas.cpp ifeq ($(PCB), 9XR2561) FLAVOUR = 9xr2561 @@ -595,11 +598,12 @@ ifeq ($(PCB), GRUVIN9X) PULSESSRC = pulses/pulses_avr.cpp CPPSRC += audio_avr.cpp haptic.cpp debug.cpp BITMAPS += bitmaps/9X/splash.lbm bitmaps/9X/asterisk.lbm bitmaps/9X/about.lbm + GUIGENERALSRC += gui/$(GUIDIRECTORY)/menu_general_diagkeys.cpp gui/$(GUIDIRECTORY)/menu_general_diaganas.cpp ifeq ($(SDCARD), YES) CPPDEFS += -DRTCLOCK -DSDCARD CPPSRC += rtc.cpp sdcard.cpp logs.cpp targets/gruvin9x/rtc_driver.cpp - GUIGENERALSRC += gui/menu_general_sdmanager.cpp + GUIGENERALSRC += gui/$(GUIDIRECTORY)/menu_general_sdmanager.cpp EXTRABOARDSRC += FatFs/ff.c FatFs/fattime.c FatFs/option/ccsbcs.c targets/gruvin9x/diskio.cpp endif @@ -639,6 +643,7 @@ ifeq ($(PCB), MEGA2560) PULSESSRC = pulses/pulses_avr.cpp CPPSRC += audio_avr.cpp debug.cpp BITMAPS += bitmaps/9X/splash.lbm bitmaps/9X/asterisk.lbm bitmaps/9X/about.lbm + GUIGENERALSRC += gui/$(GUIDIRECTORY)/menu_general_diagkeys.cpp gui/$(GUIDIRECTORY)/menu_general_diaganas.cpp ifeq ($(PCBREV), ST7565P) EXTRABOARDSRC = targets/stock/lcd_driver.cpp targets/common_avr/telemetry_driver.cpp @@ -649,7 +654,7 @@ ifeq ($(PCB), MEGA2560) ifeq ($(SDCARD), YES) EXTRABOARDSRC += FatFs/ff.c FatFs/fattime.c FatFs/option/ccsbcs.c targets/gruvin9x/diskio.cpp CPPDEFS += -DSDCARD -DRTCLOCK - GUIGENERALSRC += gui/menu_general_sdmanager.cpp + GUIGENERALSRC += gui/$(GUIDIRECTORY)/menu_general_sdmanager.cpp CPPSRC += rtc.cpp sdcard.cpp logs.cpp targets/gruvin9x/rtc_driver.cpp endif @@ -710,7 +715,7 @@ ifeq ($(PCB), $(filter $(PCB), SKY9X 9XRPRO)) CPPDEFS += -DSPORT_FILE_LOG endif INCDIRS += targets/sky9x CoOS/kernel CoOS/portable - GUIGENERALSRC += gui/menu_general_hardware.cpp + GUIGENERALSRC += gui/$(GUIDIRECTORY)/menu_general_hardware.cpp gui/$(GUIDIRECTORY)/menu_general_diagkeys.cpp gui/$(GUIDIRECTORY)/menu_general_diaganas.cpp BOARDSRC = main_arm.cpp targets/sky9x/board_sky9x.cpp EXTRABOARDSRC = targets/sky9x/lcd_driver.cpp SRC += targets/sky9x/core_cm3.c targets/sky9x/board_lowlevel.c targets/sky9x/crt.c targets/sky9x/vectors_sam3s.c @@ -722,7 +727,7 @@ ifeq ($(PCB), $(filter $(PCB), SKY9X 9XRPRO)) EEPROMSRC = eeprom_common.cpp eeprom_raw.cpp eeprom_conversions.cpp LCDSRC = lcd_common.cpp lcd_default.cpp PULSESSRC = pulses/pulses_arm.cpp pulses/ppm_arm.cpp pulses/pxx_arm.cpp pulses/dsm2_arm.cpp - CPPSRC += tasks_arm.cpp audio_arm.cpp haptic.cpp gui/view_about.cpp gui/view_text.cpp telemetry/telemetry.cpp + CPPSRC += tasks_arm.cpp audio_arm.cpp haptic.cpp gui/view_about.cpp gui/$(GUIDIRECTORY)/view_text.cpp telemetry/telemetry.cpp CPPSRC += targets/sky9x/telemetry_driver.cpp targets/sky9x/second_serial_driver.cpp targets/sky9x/pwr_driver.cpp targets/sky9x/adc_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 CPPSRC += loadboot.cpp debug.cpp BITMAPS += bitmaps/9X/splash.lbm bitmaps/9X/asterisk.lbm bitmaps/9X/about.lbm @@ -730,7 +735,7 @@ ifeq ($(PCB), $(filter $(PCB), SKY9X 9XRPRO)) CPPDEFS += -DSDCARD -DVOICE INCDIRS += FatFs FatFs/option CPPSRC += sdcard.cpp logs.cpp - GUIGENERALSRC += gui/menu_general_sdmanager.cpp + GUIGENERALSRC += gui/$(GUIDIRECTORY)/menu_general_sdmanager.cpp EXTRABOARDSRC += FatFs/ff.c FatFs/fattime.c FatFs/option/ccsbcs.c targets/sky9x/diskio.cpp endif ifeq ($(BUZZER), YES) @@ -820,7 +825,7 @@ ifeq ($(PCB), TARANIS) EXTRAINCDIRS += targets/taranis/STM32F2xx_StdPeriph_Lib_V1.1.0/Libraries/STM32F2xx_StdPeriph_Driver/inc targets/taranis/STM32F2xx_StdPeriph_Lib_V1.1.0/Libraries/CMSIS/Device/ST/STM32F2xx/Include targets/taranis/STM32F2xx_StdPeriph_Lib_V1.1.0/Libraries/CMSIS/include EXTRAINCDIRS += targets/taranis/STM32_USB-Host-Device_Lib_V2.1.0/Libraries/STM32_USB_OTG_Driver/inc targets/taranis/STM32_USB-Host-Device_Lib_V2.1.0/Libraries/STM32_USB_Device_Library/Core/inc EXTRAINCDIRS += targets/taranis/STM32_USB-Host-Device_Lib_V2.1.0/Libraries/STM32_USB_Device_Library/Class/msc/inc targets/taranis/STM32_USB-Host-Device_Lib_V2.1.0/Libraries/STM32_USB_Device_Library/Class/hid/inc - GUIGENERALSRC += gui/menu_general_hardware.cpp + GUIGENERALSRC += gui/$(GUIDIRECTORY)/menu_general_hardware.cpp BOARDSRC = main_arm.cpp targets/taranis/board_taranis.cpp EXTRABOARDSRC += targets/taranis/configure_pins.cpp targets/taranis/lcd_driver.cpp targets/taranis/flash_driver.cpp targets/taranis/aspi.c targets/taranis/i2c.c targets/taranis/delays.c SRC += CoOS/kernel/core.c CoOS/kernel/hook.c CoOS/kernel/task.c CoOS/kernel/event.c CoOS/kernel/time.c CoOS/kernel/timer.c CoOS/kernel/flag.c CoOS/kernel/mutex.c CoOS/kernel/serviceReq.c CoOS/portable/GCC/port.c CoOS/portable/arch.c @@ -830,7 +835,7 @@ ifeq ($(PCB), TARANIS) PULSESSRC = pulses/pulses_arm.cpp pulses/ppm_arm.cpp pulses/pxx_arm.cpp CPPSRC += tasks_arm.cpp audio_arm.cpp sbus.cpp telemetry/telemetry.cpp CPPSRC += targets/taranis/pulses_driver.cpp targets/taranis/keys_driver.cpp targets/taranis/adc_driver.cpp targets/taranis/trainer_driver.cpp targets/taranis/audio_driver.cpp targets/taranis/uart3_driver.cpp targets/taranis/telemetry_driver.cpp - CPPSRC += bmp.cpp gui/view_channels.cpp gui/view_about.cpp gui/view_text.cpp loadboot.cpp debug.cpp + CPPSRC += bmp.cpp gui/view_channels.cpp gui/view_about.cpp gui/$(GUIDIRECTORY)/view_text.cpp loadboot.cpp debug.cpp SRC += targets/taranis/STM32F2xx_StdPeriph_Lib_V1.1.0/Libraries/CMSIS/Device/ST/STM32F2xx/Source/Templates/system_stm32f2xx.c SRC += targets/taranis/STM32F2xx_StdPeriph_Lib_V1.1.0/Libraries/STM32F2xx_StdPeriph_Driver/src/misc.c SRC += targets/taranis/STM32F2xx_StdPeriph_Lib_V1.1.0/Libraries/STM32F2xx_StdPeriph_Driver/src/stm32f2xx_gpio.c @@ -890,7 +895,7 @@ ifeq ($(PCB), TARANIS) endif EXTRABOARDSRC += FatFs/ff.c FatFs/fattime.c FatFs/option/ccsbcs.c targets/taranis/diskio.cpp CPPSRC += sdcard.cpp logs.cpp rtc.cpp targets/taranis/rtc_driver.cpp - GUIGENERALSRC += gui/menu_general_sdmanager.cpp + GUIGENERALSRC += gui/$(GUIDIRECTORY)/menu_general_sdmanager.cpp gui/$(GUIDIRECTORY)/menu_general_diagkeys.cpp gui/$(GUIDIRECTORY)/menu_general_diaganas.cpp CPPDEFS += -DSDCARD -DVOICE -DRTCLOCK INCDIRS += FatFs FatFs/option ifeq ($(DSM2), PPM) @@ -944,7 +949,7 @@ else TTS_SRC = $(shell sh -c "if test -f $(STD_TTS_SRC); then echo $(STD_TTS_SRC); else echo translations/tts_en.cpp; fi") endif -GUISRC = gui/menus.cpp $(GUIMODELSRC) $(GUIGENERALSRC) gui/$(GUIDIRECTORY)/view_main.cpp gui/view_statistics.cpp +GUISRC = gui/$(GUIDIRECTORY)/helpers.cpp gui/$(GUIDIRECTORY)/navigation.cpp gui/$(GUIDIRECTORY)/popups.cpp gui/$(GUIDIRECTORY)/widgets.cpp gui/menus.cpp $(GUIMODELSRC) $(GUIGENERALSRC) gui/$(GUIDIRECTORY)/view_main.cpp gui/$(GUIDIRECTORY)/view_statistics.cpp CPPSRC += opentx.cpp functions.cpp strhelpers.cpp $(PULSESSRC) switches.cpp curves.cpp mixer.cpp stamp.cpp $(GUISRC) $(EEPROMSRC) $(LCDSRC) keys.cpp maths.cpp translations.cpp fonts.cpp $(TTS_SRC) @@ -1043,6 +1048,7 @@ ifneq ($(FONT), STD) INCDIRS += fonts/$(FONTDIR) endif +INCDIRS += gui INCDIRS += fonts/std ifeq ($(THR_TRACE), YES) @@ -1126,7 +1132,8 @@ ifeq ($(EXT), $(filter $(EXT), FRSKY FRSKY_SPORT TELEMETREZ)) else CPPSRC += telemetry/frsky.cpp telemetry/frsky_d.cpp endif - CPPSRC += gui/view_telemetry.cpp + + CPPSRC += gui/$(GUIDIRECTORY)/view_telemetry.cpp ifeq ($(FRSKY_HUB), YES) CPPDEFS += -DFRSKY_HUB diff --git a/radio/src/eeprom_conversions.cpp b/radio/src/eeprom_conversions.cpp index 0fb2c4fc3..9d3c67a18 100644 --- a/radio/src/eeprom_conversions.cpp +++ b/radio/src/eeprom_conversions.cpp @@ -1530,7 +1530,8 @@ bool eeConvert() s_eeDirtyMsk = EE_GENERAL; eeCheck(true); -#if LCD_W >= 212 +#if defined(COLORLCD) +#elif LCD_W >= 212 lcd_rect(60, 6*FH+4, 132, 3); #else lcd_rect(10, 6*FH+4, 102, 3); @@ -1538,7 +1539,8 @@ bool eeConvert() // Models conversion for (uint8_t id=0; id= 212 +#if defined(COLORLCD) +#elif LCD_W >= 212 lcd_hline(61, 6*FH+5, 10+id*2, FORCE); #else lcd_hline(11, 6*FH+5, 10+(id*3)/2, FORCE); diff --git a/radio/src/fonts.cpp b/radio/src/fonts.cpp index 37db2a744..7134b170e 100644 --- a/radio/src/fonts.cpp +++ b/radio/src/fonts.cpp @@ -36,6 +36,11 @@ #include "opentx.h" +#if defined(COLORLCD) +const pm_uchar font_5x7[] PROGMEM = { +#include "fonts/font_stdsize.lbm" +}; +#else const pm_uchar font_5x7[] PROGMEM = { #if defined (CPUARM) #include "font_05x07.lbm" @@ -62,6 +67,7 @@ const pm_uchar font_5x7[] PROGMEM = { #include "font_se_05x07.lbm" #endif }; +#endif #if defined(BOLD_FONT) && (!defined(CPUM64) || defined(EXTSTD)) const pm_uchar font_5x7_B[] PROGMEM = { @@ -70,6 +76,11 @@ const pm_uchar font_5x7_B[] PROGMEM = { #endif #if !defined(BOOT) +#if defined(COLORLCD) +const pm_uchar font_10x14[] PROGMEM = { +#include "fonts/font_dblsize.lbm" +}; +#else const pm_uchar font_10x14[] PROGMEM = { #include "font_10x14_compressed.lbm" #if defined(CPUARM) @@ -95,6 +106,7 @@ const pm_uchar font_10x14[] PROGMEM = { #endif }; #endif +#endif #if defined(CPUARM) && !defined(BOOT) const pm_uchar font_3x5[] PROGMEM = { @@ -124,6 +136,11 @@ const pm_uchar font_4x6[] PROGMEM = { #endif }; +#if defined(COLORLCD) +const pm_uchar font_8x10[] PROGMEM = { +#include "fonts/font_midsize.lbm" +}; +#else const pm_uchar font_8x10[] PROGMEM = { #include "font_08x10.lbm" #if defined(TRANSLATIONS_DE) @@ -146,6 +163,7 @@ const pm_uchar font_8x10[] PROGMEM = { #include "font_se_08x10.lbm" #endif }; +#endif const pm_uchar font_22x38_num[] PROGMEM = { #include "font_22x38_num.lbm" diff --git a/radio/src/fonts/.gitignore b/radio/src/fonts/.gitignore index 6deff3475..2acf3f6bf 100644 --- a/radio/src/fonts/.gitignore +++ b/radio/src/fonts/.gitignore @@ -1 +1,4 @@ /*/*.lbm +/font_dblsize.png +/font_midsize.png +/font_stdsize.png diff --git a/radio/src/gui/9X/gui.h b/radio/src/gui/9X/gui.h new file mode 100755 index 000000000..8335e1ec6 --- /dev/null +++ b/radio/src/gui/9X/gui.h @@ -0,0 +1,48 @@ +/* + * Authors (alphabetical order) + * - Andre Bernet + * - Andreas Weitl + * - Bertrand Songis + * - Bryan J. Rentoul (Gruvin) + * - Cameron Weeks + * - Erez Raviv + * - Gabriel Birkus + * - Jean-Pierre Parisy + * - Karl Szmutny + * - Michael Blandford + * - Michal Hlavinka + * - Pat Mackenzie + * - Philip Moss + * - Rob Thomson + * - Romolo Manfredini + * - Thomas Husterer + * + * opentx is based on code named + * gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/, + * er9x by Erez Raviv: http://code.google.com/p/er9x/, + * and the original (and ongoing) project by + * Thomas Husterer, th9x: http://code.google.com/p/th9x/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#define NUM_BODY_LINES LCD_LINES-1 +#define MENU_TITLE_HEIGHT FH +#define MENU_NAVIG_HEIGHT 0 + +void displayScreenIndex(uint8_t index, uint8_t count, uint8_t attr); + +#if !defined(CPUM64) + #define DEFAULT_SCROLLBAR_X (LCD_W-1) + void displayScrollbar(coord_t x, coord_t y, coord_t h, uint16_t offset, uint16_t count, uint8_t visible); +#endif + +#define SET_SCROLLBAR_X(x) diff --git a/radio/src/gui/9X/helpers.cpp b/radio/src/gui/9X/helpers.cpp new file mode 100755 index 000000000..3978a6c4c --- /dev/null +++ b/radio/src/gui/9X/helpers.cpp @@ -0,0 +1,279 @@ +/* + * Authors (alphabetical order) + * - Andre Bernet + * - Andreas Weitl + * - Bertrand Songis + * - Bryan J. Rentoul (Gruvin) + * - Cameron Weeks + * - Erez Raviv + * - Gabriel Birkus + * - Jean-Pierre Parisy + * - Karl Szmutny + * - Michael Blandford + * - Michal Hlavinka + * - Pat Mackenzie + * - Philip Moss + * - Rob Thomson + * - Romolo Manfredini + * - Thomas Husterer + * + * opentx is based on code named + * gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/, + * er9x by Erez Raviv: http://code.google.com/p/er9x/, + * and the original (and ongoing) project by + * Thomas Husterer, th9x: http://code.google.com/p/th9x/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include "../../opentx.h" + +uint8_t switchToMix(uint8_t source) +{ + if (source <= 3) + return MIXSRC_3POS; + else + return MIXSRC_FIRST_SWITCH - 3 + source; +} + +#if defined(CPUARM) +bool isSourceAvailable(int source) +{ +#if !defined(HELI) + if (source>=MIXSRC_CYC1 && source<=MIXSRC_CYC3) + return false; +#endif + + if (source>=MIXSRC_CH1 && source<=MIXSRC_LAST_CH) { + uint8_t destCh = source-MIXSRC_CH1; + for (uint8_t i = 0; i < MAX_MIXERS; i++) { + MixData *md = mixAddress(i); + if (md->srcRaw == 0) return false; + if (md->destCh==destCh) return true; + } + return false; + } + + if (source>=MIXSRC_SW1 && source<=MIXSRC_LAST_LOGICAL_SWITCH) { + LogicalSwitchData * cs = lswAddress(source-MIXSRC_SW1); + return (cs->func != LS_FUNC_NONE); + } + +#if !defined(GVARS) + if (source>=MIXSRC_GVAR1 && source<=MIXSRC_LAST_GVAR) + return false; +#endif + + if (source>=MIXSRC_RESERVE1 && source<=MIXSRC_RESERVE5) + return false; + + if (source>=MIXSRC_FIRST_TELEM && source<=MIXSRC_LAST_TELEM) { + div_t qr = div(source-MIXSRC_FIRST_TELEM, 3); + if (qr.rem == 0) + return isTelemetryFieldAvailable(qr.quot); + else + return isTelemetryFieldComparisonAvailable(qr.quot); + } + + return true; +} + +bool isSourceAvailableInCustomSwitches(int source) +{ + bool result = isSourceAvailable(source); + +#if defined(FRSKY) + if (result && source>=MIXSRC_FIRST_TELEM && source<=MIXSRC_LAST_TELEM) { + div_t qr = div(source-MIXSRC_FIRST_TELEM, 3); + result = isTelemetryFieldComparisonAvailable(qr.quot); + } +#endif + + return result; +} + +bool isInputSourceAvailable(int source) +{ + if (source>=MIXSRC_Rud && source<=MIXSRC_MAX) + return true; + + if (source>=MIXSRC_Rud && source<=MIXSRC_MAX) + return true; + + if (source>=MIXSRC_TrimRud && source=MIXSRC_FIRST_CH && source<=MIXSRC_LAST_CH) + return true; + + if (source>=MIXSRC_FIRST_TRAINER && source<=MIXSRC_LAST_TRAINER) + return true; + + if (source>=MIXSRC_FIRST_TELEM && source<=MIXSRC_LAST_TELEM) + return isTelemetryFieldAvailable(source-MIXSRC_FIRST_TELEM); + + return false; +} + +enum SwitchContext +{ + LogicalSwitchesContext, + ModelCustomFunctionsContext, + GeneralCustomFunctionsContext, + TimersContext, + MixesContext +}; + +bool isSwitchAvailable(int swtch, SwitchContext context) +{ + if (swtch < 0) { + if (swtch == -SWSRC_ON || swtch == -SWSRC_One) { + return false; + } + swtch = -swtch; + } + + if (swtch >= SWSRC_FIRST_LOGICAL_SWITCH && swtch <= SWSRC_LAST_LOGICAL_SWITCH) { + if (context == GeneralCustomFunctionsContext) { + return false; + } + else if (context != LogicalSwitchesContext) { + LogicalSwitchData * cs = lswAddress(swtch-SWSRC_FIRST_LOGICAL_SWITCH); + return (cs->func != LS_FUNC_NONE); + } + } + + if (context != ModelCustomFunctionsContext && context != GeneralCustomFunctionsContext && (swtch == SWSRC_ON || swtch == SWSRC_One)) { + return false; + } + + if (swtch >= SWSRC_FIRST_FLIGHT_MODE && swtch <= SWSRC_LAST_FLIGHT_MODE) { + if (context == MixesContext || context == GeneralCustomFunctionsContext) { + return false; + } + else { + swtch -= SWSRC_FIRST_FLIGHT_MODE; + if (swtch == 0) { + return true; + } + FlightModeData * fm = flightModeAddress(swtch); + return (fm->swtch != SWSRC_NONE); + } + } + + return true; +} + +bool isSwitchAvailableInLogicalSwitches(int swtch) +{ + return isSwitchAvailable(swtch, LogicalSwitchesContext); +} + +bool isSwitchAvailableInCustomFunctions(int swtch) +{ + if (g_menuStack[g_menuStackPtr] == menuModelCustomFunctions) + return isSwitchAvailable(swtch, ModelCustomFunctionsContext); + else + return isSwitchAvailable(swtch, GeneralCustomFunctionsContext); +} + +bool isSwitchAvailableInMixes(int swtch) +{ + return isSwitchAvailable(swtch, MixesContext); +} + +bool isSwitchAvailableInTimers(int swtch) +{ + if (swtch >= 0) { + if (swtch < TMRMODE_COUNT) + return true; + else + swtch -= TMRMODE_COUNT-1; + } + else { + if (swtch > -TMRMODE_COUNT) + return false; + else + swtch += TMRMODE_COUNT-1; + } + + return isSwitchAvailable(swtch, TimersContext); +} + +bool isThrottleSourceAvailable(int source) +{ + return true; +} + +bool isLogicalSwitchFunctionAvailable(int function) +{ + return function != LS_FUNC_RANGE; +} + +bool isAssignableFunctionAvailable(int function) +{ + bool modelFunctions = (g_menuStack[g_menuStackPtr] == menuModelCustomFunctions); + + switch (function) { + case FUNC_OVERRIDE_CHANNEL: +#if defined(OVERRIDE_CHANNEL_FUNCTION) + return modelFunctions; +#else + return false; +#endif + case FUNC_ADJUST_GVAR: +#if defined(GVARS) + return modelFunctions; +#else + return false; +#endif +#if !defined(HAPTIC) + case FUNC_HAPTIC: +#endif + case FUNC_PLAY_DIFF: +#if !defined(DANGEROUS_MODULE_FUNCTIONS) + case FUNC_RANGECHECK: + case FUNC_BIND: + case FUNC_MODULE_OFF: +#endif + case FUNC_PLAY_SCRIPT: + case FUNC_RESERVE5: + return false; + + default: + return true; + } +} + +bool isModuleAvailable(int module) +{ +#if defined(PCBSKY9X) + if (module == MODULE_TYPE_NONE) + return false; +#endif + +#if !defined(PXX) + if (module == MODULE_TYPE_XJT) + return false; +#endif + + return true; +} + +bool modelHasNotes() +{ + char filename[sizeof(MODELS_PATH)+1+sizeof(g_model.header.name)+sizeof(TEXT_EXT)] = MODELS_PATH "/"; + char *buf = strcat_modelname(&filename[sizeof(MODELS_PATH)], g_eeGeneral.currModel); + strcpy(buf, TEXT_EXT); + return isFileAvailable(filename); +} + +#endif diff --git a/radio/src/gui/9X/menu_general_calib.cpp b/radio/src/gui/9X/menu_general_calib.cpp new file mode 100755 index 000000000..0e092ce8a --- /dev/null +++ b/radio/src/gui/9X/menu_general_calib.cpp @@ -0,0 +1,142 @@ +/* + * Authors (alphabetical order) + * - Andre Bernet + * - Andreas Weitl + * - Bertrand Songis + * - Bryan J. Rentoul (Gruvin) + * - Cameron Weeks + * - Erez Raviv + * - Gabriel Birkus + * - Jean-Pierre Parisy + * - Karl Szmutny + * - Michael Blandford + * - Michal Hlavinka + * - Pat Mackenzie + * - Philip Moss + * - Rob Thomson + * - Romolo Manfredini + * - Thomas Husterer + * + * opentx is based on code named + * gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/, + * er9x by Erez Raviv: http://code.google.com/p/er9x/, + * and the original (and ongoing) project by + * Thomas Husterer, th9x: http://code.google.com/p/th9x/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include "../../opentx.h" + +#define XPOT_DELTA 10 +#define XPOT_DELAY 10 /* cycles */ + +void menuCommonCalib(uint8_t event) +{ + for (uint8_t i=0; i= POT1 && i <= POT_LAST) { + if (IS_POT_WITHOUT_DETENT(i)) { + reusableBuffer.calib.midVals[i] = (reusableBuffer.calib.hiVals[i] + reusableBuffer.calib.loVals[i]) / 2; + } + } + } + + calibrationState = reusableBuffer.calib.state; // make sure we don't scroll while calibrating + + switch (event) + { + case EVT_ENTRY: + reusableBuffer.calib.state = 0; + break; + + case EVT_KEY_BREAK(KEY_ENTER): + reusableBuffer.calib.state++; + break; + } + + switch (reusableBuffer.calib.state) { + case 0: + // START CALIBRATION + if (!READ_ONLY()) { + lcd_putsLeft(MENU_TITLE_HEIGHT+2*FH, STR_MENUTOSTART); + } + break; + + case 1: + // SET MIDPOINT + lcd_putsAtt(0*FW, MENU_TITLE_HEIGHT+FH, STR_SETMIDPOINT, INVERS); + lcd_putsLeft(MENU_TITLE_HEIGHT+2*FH, STR_MENUWHENDONE); + + for (uint8_t i=0; i 50) { + g_eeGeneral.calib[i].mid = reusableBuffer.calib.midVals[i]; + int16_t v = reusableBuffer.calib.midVals[i] - reusableBuffer.calib.loVals[i]; + g_eeGeneral.calib[i].spanNeg = v - v/STICK_TOLERANCE; + v = reusableBuffer.calib.hiVals[i] - reusableBuffer.calib.midVals[i]; + g_eeGeneral.calib[i].spanPos = v - v/STICK_TOLERANCE; + } + } + break; + + case 3: + g_eeGeneral.chkSum = evalChkSum(); + eeDirty(EE_GENERAL); + reusableBuffer.calib.state = 4; + break; + + default: + reusableBuffer.calib.state = 0; + break; + } + + doMainScreenGraphics(); +} + +void menuGeneralCalib(uint8_t event) +{ + check_simple(event, e_Calib, menuTabGeneral, DIM(menuTabGeneral), 0); + + if (menuEvent) { + calibrationState = 0; + } + + TITLE(STR_MENUCALIBRATION); + menuCommonCalib(READ_ONLY() ? 0 : event); +} + +void menuFirstCalib(uint8_t event) +{ + if (event == EVT_KEY_BREAK(KEY_EXIT) || reusableBuffer.calib.state == 4) { + calibrationState = 0; + chainMenu(menuMainView); + } + else { + lcd_putsCenter(0*FH, MENUCALIBRATION); + lcd_invert_line(0); + menuCommonCalib(event); + } +} diff --git a/radio/src/gui/9X/menu_general_diaganas.cpp b/radio/src/gui/9X/menu_general_diaganas.cpp new file mode 100755 index 000000000..12910c135 --- /dev/null +++ b/radio/src/gui/9X/menu_general_diaganas.cpp @@ -0,0 +1,107 @@ +/* + * Authors (alphabetical order) + * - Andre Bernet + * - Andreas Weitl + * - Bertrand Songis + * - Bryan J. Rentoul (Gruvin) + * - Cameron Weeks + * - Erez Raviv + * - Gabriel Birkus + * - Jean-Pierre Parisy + * - Karl Szmutny + * - Michael Blandford + * - Michal Hlavinka + * - Pat Mackenzie + * - Philip Moss + * - Rob Thomson + * - Romolo Manfredini + * - Thomas Husterer + * + * opentx is based on code named + * gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/, + * er9x by Erez Raviv: http://code.google.com/p/er9x/, + * and the original (and ongoing) project by + * Thomas Husterer, th9x: http://code.google.com/p/th9x/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include "../../opentx.h" + +void menuGeneralDiagAna(uint8_t event) +{ +#if defined(PCBSKY9X) && !defined(REVA) + #define ANAS_ITEMS_COUNT 4 +#elif defined(PCBSKY9X) + #define ANAS_ITEMS_COUNT 3 +#else + #define ANAS_ITEMS_COUNT 2 +#endif + + SIMPLE_MENU(STR_MENUANA, menuTabGeneral, e_Ana, ANAS_ITEMS_COUNT); + + STICK_SCROLL_DISABLE(); + + for (uint8_t i=0; i 9 + coord_t y = MENU_TITLE_HEIGHT + 1 + (i/3)*FH; + const uint8_t x_coord[] = {0, 70, 154}; + uint8_t x = x_coord[i%3]; + lcd_outdezNAtt(x, y, i+1, LEADING0|LEFT, 2); + lcd_putc(x+2*FW-2, y, ':'); +#else + coord_t y = MENU_TITLE_HEIGHT + 1 + (i/2)*FH; + uint8_t x = i&1 ? 64+5 : 0; + putsStrIdx(x, y, PSTR("A"), i+1); + lcd_putc(lcdNextPos, y, ':'); +#endif + lcd_outhex4(x+3*FW-1, y, anaIn(i)); + lcd_outdez8(x+10*FW-1, y, (int16_t)calibratedStick[CONVERT_MODE(i)]*25/256); + } + +#if !defined(CPUARM) + // Display raw BandGap result (debug) + lcd_puts(64+5, MENU_TITLE_HEIGHT+1+3*FH, STR_BG); + lcd_outdezAtt(64+5+6*FW-3, 1+4*FH, BandGap, 0); +#endif + +#if defined(PCBSKY9X) + lcd_putsLeft(MENU_TITLE_HEIGHT+1+4*FH, STR_BATT_CALIB); + static int32_t adcBatt; + adcBatt = ((adcBatt * 7) + anaIn(TX_VOLTAGE)) / 8; + uint32_t batCalV = (adcBatt + adcBatt*(g_eeGeneral.vBatCalib)/128) * 4191; + batCalV /= 55296; + putsVolts(LEN_CALIB_FIELDS*FW+4*FW, MENU_TITLE_HEIGHT+1+4*FH, batCalV, (m_posVert==1 ? INVERS : 0)); +#elif defined(PCBGRUVIN9X) + lcd_putsLeft(6*FH-2, STR_BATT_CALIB); + // Gruvin wants 2 decimal places and instant update of volts calib field when button pressed + static uint16_t adcBatt; + adcBatt = ((adcBatt * 7) + anaIn(TX_VOLTAGE)) / 8; // running average, sourced directly (to avoid unending debate :P) + uint32_t batCalV = ((uint32_t)adcBatt*1390 + (10*(int32_t)adcBatt*g_eeGeneral.vBatCalib)/8) / BandGap; + lcd_outdezNAtt(LEN_CALIB_FIELDS*FW+4*FW, 6*FH-2, batCalV, PREC2|(m_posVert==1 ? INVERS : 0)); +#else + lcd_putsLeft(6*FH-2, STR_BATT_CALIB); + putsVolts(LEN_CALIB_FIELDS*FW+4*FW, 6*FH-2, g_vbat100mV, (m_posVert==1 ? INVERS : 0)); +#endif + if (m_posVert==1) CHECK_INCDEC_GENVAR(event, g_eeGeneral.vBatCalib, -127, 127); + +#if defined(PCBSKY9X) && !defined(REVA) + lcd_putsLeft(6*FH+1, STR_CURRENT_CALIB); + putsValueWithUnit(LEN_CALIB_FIELDS*FW+4*FW, 6*FH+1, getCurrent(), UNIT_MILLIAMPS, (m_posVert==2 ? INVERS : 0)) ; + if (m_posVert==2) CHECK_INCDEC_GENVAR(event, g_eeGeneral.currentCalib, -49, 49); +#endif + +#if defined(PCBSKY9X) + lcd_putsLeft(7*FH+1, STR_TEMP_CALIB); + putsValueWithUnit(LEN_CALIB_FIELDS*FW+4*FW, 7*FH+1, getTemperature(), UNIT_TEMPERATURE, (m_posVert==3 ? INVERS : 0)) ; + if (m_posVert==3) CHECK_INCDEC_GENVAR(event, g_eeGeneral.temperatureCalib, -100, 100); +#endif +} diff --git a/radio/src/gui/9X/menu_general_diagkeys.cpp b/radio/src/gui/9X/menu_general_diagkeys.cpp new file mode 100755 index 000000000..2b341346d --- /dev/null +++ b/radio/src/gui/9X/menu_general_diagkeys.cpp @@ -0,0 +1,81 @@ +/* + * Authors (alphabetical order) + * - Andre Bernet + * - Andreas Weitl + * - Bertrand Songis + * - Bryan J. Rentoul (Gruvin) + * - Cameron Weeks + * - Erez Raviv + * - Gabriel Birkus + * - Jean-Pierre Parisy + * - Karl Szmutny + * - Michael Blandford + * - Michal Hlavinka + * - Pat Mackenzie + * - Philip Moss + * - Rob Thomson + * - Romolo Manfredini + * - Thomas Husterer + * + * opentx is based on code named + * gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/, + * er9x by Erez Raviv: http://code.google.com/p/er9x/, + * and the original (and ongoing) project by + * Thomas Husterer, th9x: http://code.google.com/p/th9x/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include "../../opentx.h" + +void displayKeyState(uint8_t x, uint8_t y, EnumKeys key) +{ + uint8_t t = switchState(key); + lcd_putcAtt(x, y, t+'0', t ? INVERS : 0); +} + +void menuGeneralDiagKeys(uint8_t event) +{ + SIMPLE_MENU(STR_MENUDIAG, menuTabGeneral, e_Keys, 1); + + lcd_puts(14*FW, MENU_TITLE_HEIGHT+2*FH, STR_VTRIM); + + for(uint8_t i=0; i<9; i++) { + coord_t y; + + if (i<8) { + y = MENU_TITLE_HEIGHT + FH*3 + FH*(i/2); + if (i&1) lcd_img(14*FW, y, sticks, i/2, 0); + displayKeyState(i&1? 20*FW : 18*FW, y, (EnumKeys)(TRM_BASE+i)); + } + + if (i<6) { + y = i*FH+MENU_TITLE_HEIGHT+FH; + lcd_putsiAtt(0, y, STR_VKEYS, (5-i), 0); + displayKeyState(5*FW+2, y, (EnumKeys)(KEY_MENU+(5-i))); + } + + if (i != SW_ID0-SW_BASE) { + y = MENU_TITLE_HEIGHT+i*FH-2*FH; + putsSwitches(8*FW, y, i+1, 0); //ohne off,on + displayKeyState(11*FW+2, y, (EnumKeys)(SW_BASE+i)); + } + } + +#if defined(ROTARY_ENCODERS) || defined(ROTARY_ENCODER_NAVIGATION) + for(uint8_t i=0; i + * - Andreas Weitl + * - Bertrand Songis + * - Bryan J. Rentoul (Gruvin) + * - Cameron Weeks + * - Erez Raviv + * - Gabriel Birkus + * - Jean-Pierre Parisy + * - Karl Szmutny + * - Michael Blandford + * - Michal Hlavinka + * - Pat Mackenzie + * - Philip Moss + * - Rob Thomson + * - Romolo Manfredini + * - Thomas Husterer + * + * opentx is based on code named + * gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/, + * er9x by Erez Raviv: http://code.google.com/p/er9x/, + * and the original (and ongoing) project by + * Thomas Husterer, th9x: http://code.google.com/p/th9x/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include "../../opentx.h" + +enum menuGeneralHwItems { + ITEM_SETUP_HW_OPTREX_DISPLAY, + ITEM_SETUP_HW_STICKS_GAINS_LABELS, + ITEM_SETUP_HW_STICK_LV_GAIN, + ITEM_SETUP_HW_STICK_LH_GAIN, + ITEM_SETUP_HW_STICK_RV_GAIN, + ITEM_SETUP_HW_STICK_RH_GAIN, + IF_ROTARY_ENCODERS(ITEM_SETUP_HW_ROTARY_ENCODER) + CASE_BLUETOOTH(ITEM_SETUP_HW_BT_BAUDRATE) + ITEM_SETUP_HW_MAX +}; + +#define GENERAL_HW_PARAM_OFS (2+(15*FW)) +void menuGeneralHardware(uint8_t event) +{ + MENU(STR_HARDWARE, menuTabGeneral, e_Hardware, ITEM_SETUP_HW_MAX+1, {0, 0, (uint8_t)-1, 0, 0, 0, IF_ROTARY_ENCODERS(0) CASE_BLUETOOTH(0)}); + + uint8_t sub = m_posVert - 1; + + for (uint8_t i=0; i0) ? BLINK|INVERS : INVERS); + uint8_t attr = (sub == k ? blink : 0); + + switch(k) { + case ITEM_SETUP_HW_OPTREX_DISPLAY: + g_eeGeneral.optrexDisplay = selectMenuItem(GENERAL_HW_PARAM_OFS, y, STR_LCD, STR_VLCD, g_eeGeneral.optrexDisplay, 0, 1, attr, event); + break; + + case ITEM_SETUP_HW_STICKS_GAINS_LABELS: + lcd_putsLeft(y, PSTR("Sticks")); + break; + + case ITEM_SETUP_HW_STICK_LV_GAIN: + case ITEM_SETUP_HW_STICK_LH_GAIN: + case ITEM_SETUP_HW_STICK_RV_GAIN: + case ITEM_SETUP_HW_STICK_RH_GAIN: + { + lcd_putsiAtt(INDENT_WIDTH, y, PSTR("\002LVLHRVRH"), k-ITEM_SETUP_HW_STICK_LV_GAIN, 0); + lcd_puts(INDENT_WIDTH+3*FW, y, PSTR("Gain")); + uint8_t mask = (1<<(k-ITEM_SETUP_HW_STICK_LV_GAIN)); + uint8_t val = (g_eeGeneral.sticksGain & mask ? 1 : 0); + lcd_putcAtt(GENERAL_HW_PARAM_OFS, y, val ? '2' : '1', attr); + if (attr) { + CHECK_INCDEC_GENVAR(event, val, 0, 1); + if (checkIncDec_Ret) { + g_eeGeneral.sticksGain ^= mask; + setSticksGain(g_eeGeneral.sticksGain); + } + } + break; + } + +#if defined(ROTARY_ENCODERS) + case ITEM_SETUP_HW_ROTARY_ENCODER: + g_eeGeneral.rotarySteps = selectMenuItem(GENERAL_HW_PARAM_OFS, y, PSTR("Rotary Encoder"), PSTR("\0062steps4steps"), g_eeGeneral.rotarySteps, 0, 1, attr, event); + break; +#endif + +#if defined(BLUETOOTH) + case ITEM_SETUP_HW_BT_BAUDRATE: + g_eeGeneral.btBaudrate = selectMenuItem(GENERAL_HW_PARAM_OFS, y, STR_BAUDRATE, PSTR("\005115k 9600 19200"), g_eeGeneral.btBaudrate, 0, 2, attr, event); + if (attr && checkIncDec_Ret) { + btInit(); + } + break; +#endif + + } + } +} diff --git a/radio/src/gui/9X/menu_general_sdmanager.cpp b/radio/src/gui/9X/menu_general_sdmanager.cpp new file mode 100755 index 000000000..bbbfdc34c --- /dev/null +++ b/radio/src/gui/9X/menu_general_sdmanager.cpp @@ -0,0 +1,293 @@ +/* + * Authors (alphabetical order) + * - Andre Bernet + * - Andreas Weitl + * - Bertrand Songis + * - Bryan J. Rentoul (Gruvin) + * - Cameron Weeks + * - Erez Raviv + * - Gabriel Birkus + * - Jean-Pierre Parisy + * - Karl Szmutny + * - Michael Blandford + * - Michal Hlavinka + * - Pat Mackenzie + * - Philip Moss + * - Rob Thomson + * - Romolo Manfredini + * - Thomas Husterer + * + * opentx is based on code named + * gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/, + * er9x by Erez Raviv: http://code.google.com/p/er9x/, + * and the original (and ongoing) project by + * Thomas Husterer, th9x: http://code.google.com/p/th9x/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include "../../opentx.h" + +void menuGeneralSdManagerInfo(uint8_t event) +{ + SIMPLE_SUBMENU(STR_SD_INFO_TITLE, 1); + + lcd_putsLeft(2*FH, STR_SD_TYPE); + lcd_puts(10*FW, 2*FH, SD_IS_HC() ? STR_SDHC_CARD : STR_SD_CARD); + + lcd_putsLeft(3*FH, STR_SD_SIZE); + lcd_outdezAtt(10*FW, 3*FH, SD_GET_SIZE_MB(), LEFT); + lcd_putc(lcdLastPos, 3*FH, 'M'); + + lcd_putsLeft(4*FH, STR_SD_SECTORS); + lcd_outdezAtt(10*FW, 4*FH, SD_GET_BLOCKNR()/1000, LEFT); + lcd_putc(lcdLastPos, 4*FH, 'k'); + + lcd_putsLeft(5*FH, STR_SD_SPEED); + lcd_outdezAtt(10*FW, 5*FH, SD_GET_SPEED()/1000, LEFT); + lcd_puts(lcdLastPos, 5*FH, "kb/s"); +} + +inline bool isFilenameGreater(bool isfile, const char * fn, const char * line) +{ + return (isfile && !line[SD_SCREEN_FILE_LENGTH+1]) || (isfile==(bool)line[SD_SCREEN_FILE_LENGTH+1] && strcasecmp(fn, line) > 0); +} + +inline bool isFilenameLower(bool isfile, const char * fn, const char * line) +{ + return (!isfile && line[SD_SCREEN_FILE_LENGTH+1]) || (isfile==(bool)line[SD_SCREEN_FILE_LENGTH+1] && strcasecmp(fn, line) < 0); +} + +void onSdManagerMenu(const char *result) +{ + TCHAR lfn[_MAX_LFN+1]; + + uint8_t index = m_posVert-1-s_pgOfs; + if (result == STR_SD_INFO) { + pushMenu(menuGeneralSdManagerInfo); + } + else if (result == STR_SD_FORMAT) { + POPUP_CONFIRMATION(STR_CONFIRM_FORMAT); + } + else if (result == STR_DELETE_FILE) { + f_getcwd(lfn, _MAX_LFN); + strcat_P(lfn, PSTR("/")); + strcat(lfn, reusableBuffer.sdmanager.lines[index]); + f_unlink(lfn); + strncpy(statusLineMsg, reusableBuffer.sdmanager.lines[index], 13); + strcpy_P(statusLineMsg+min((uint8_t)strlen(statusLineMsg), (uint8_t)13), STR_REMOVED); + showStatusLine(); + if ((uint16_t)m_posVert == reusableBuffer.sdmanager.count) m_posVert--; + reusableBuffer.sdmanager.offset = s_pgOfs-1; + } +#if defined(CPUARM) + /* TODO else if (result == STR_LOAD_FILE) { + f_getcwd(lfn, _MAX_LFN); + strcat(lfn, "/"); + strcat(lfn, reusableBuffer.sdmanager.lines[index]); + POPUP_WARNING(eeLoadModelSD(lfn)); + } */ + else if (result == STR_PLAY_FILE) { + f_getcwd(lfn, _MAX_LFN); + strcat(lfn, "/"); + strcat(lfn, reusableBuffer.sdmanager.lines[index]); + audioQueue.stopAll(); + audioQueue.playFile(lfn, 0, ID_PLAY_FROM_SD_MANAGER); + } +#endif +} + +void menuGeneralSdManager(uint8_t _event) +{ + FILINFO fno; + DIR dir; + char *fn; /* This function is assuming non-Unicode cfg. */ + TCHAR lfn[_MAX_LFN + 1]; + fno.lfname = lfn; + fno.lfsize = sizeof(lfn); + +#if defined(SDCARD) + if (s_warning_result) { + s_warning_result = 0; + displayPopup(STR_FORMATTING); + closeLogs(); +#if defined(PCBSKY9X) + Card_state = SD_ST_DATA; +#endif +#if defined(CPUARM) + audioQueue.stopSD(); +#endif + if (f_mkfs(0, 1, 0) == FR_OK) { + f_chdir("/"); + reusableBuffer.sdmanager.offset = -1; + } + else { + POPUP_WARNING(STR_SDCARD_ERROR); + } + } +#endif + + uint8_t event = ((READ_ONLY() && EVT_KEY_MASK(_event) == KEY_ENTER) ? 0 : _event); + SIMPLE_MENU(SD_IS_HC() ? STR_SDHC_CARD : STR_SD_CARD, menuTabGeneral, e_Sd, 1+reusableBuffer.sdmanager.count); + + if (s_editMode > 0) + s_editMode = 0; + + switch(_event) { + case EVT_ENTRY: + f_chdir(ROOT_PATH); + reusableBuffer.sdmanager.offset = 65535; + break; + + CASE_EVT_ROTARY_BREAK + case EVT_KEY_FIRST(KEY_RIGHT): + case EVT_KEY_FIRST(KEY_ENTER): + { + if (m_posVert > 0) { + vertpos_t index = m_posVert-1-s_pgOfs; + if (!reusableBuffer.sdmanager.lines[index][SD_SCREEN_FILE_LENGTH+1]) { + f_chdir(reusableBuffer.sdmanager.lines[index]); + s_pgOfs = 0; + m_posVert = 1; + reusableBuffer.sdmanager.offset = 65535; + killEvents(_event); + break; + } + } + if (!IS_ROTARY_BREAK(_event) || m_posVert==0) + break; + // no break; + } + + case EVT_KEY_LONG(KEY_ENTER): + killEvents(_event); + if (m_posVert == 0) { + MENU_ADD_ITEM(STR_SD_INFO); + MENU_ADD_ITEM(STR_SD_FORMAT); + } + else + { +#if defined(CPUARM) + uint8_t index = m_posVert-1-s_pgOfs; + // TODO duplicated code for finding extension + char * ext = reusableBuffer.sdmanager.lines[index]; + int len = strlen(ext) - 4; + ext += len; + /* TODO if (!strcasecmp(ext, MODELS_EXT)) { + s_menu[s_menu_count++] = STR_LOAD_FILE; + } + else */ if (!strcasecmp(ext, SOUNDS_EXT)) { + MENU_ADD_ITEM(STR_PLAY_FILE); + } +#endif + if (!READ_ONLY()) { + MENU_ADD_ITEM(STR_DELETE_FILE); + // MENU_ADD_ITEM(STR_RENAME_FILE); TODO: Implement + // MENU_ADD_ITEM(STR_COPY_FILE); TODO: Implement + } + } + menuHandler = onSdManagerMenu; + break; + } + + if (reusableBuffer.sdmanager.offset != s_pgOfs) { + if (s_pgOfs == 0) { + reusableBuffer.sdmanager.offset = 0; + memset(reusableBuffer.sdmanager.lines, 0, sizeof(reusableBuffer.sdmanager.lines)); + } + else if (s_pgOfs == reusableBuffer.sdmanager.count-7) { + reusableBuffer.sdmanager.offset = s_pgOfs; + memset(reusableBuffer.sdmanager.lines, 0, sizeof(reusableBuffer.sdmanager.lines)); + } + else if (s_pgOfs > reusableBuffer.sdmanager.offset) { + memmove(reusableBuffer.sdmanager.lines[0], reusableBuffer.sdmanager.lines[1], 6*sizeof(reusableBuffer.sdmanager.lines[0])); + memset(reusableBuffer.sdmanager.lines[6], 0xff, SD_SCREEN_FILE_LENGTH); + reusableBuffer.sdmanager.lines[6][SD_SCREEN_FILE_LENGTH+1] = 1; + } + else { + memmove(reusableBuffer.sdmanager.lines[1], reusableBuffer.sdmanager.lines[0], 6*sizeof(reusableBuffer.sdmanager.lines[0])); + memset(reusableBuffer.sdmanager.lines[0], 0, sizeof(reusableBuffer.sdmanager.lines[0])); + } + + reusableBuffer.sdmanager.count = 0; + + FRESULT res = f_opendir(&dir, "."); /* Open the directory */ + if (res == FR_OK) { + for (;;) { + res = f_readdir(&dir, &fno); /* Read a directory item */ + if (res != FR_OK || fno.fname[0] == 0) break; /* Break on error or end of dir */ + if (fno.fname[0] == '.' && fno.fname[1] == '\0') continue; /* Ignore dot entry */ +#if _USE_LFN + fn = *fno.lfname ? fno.lfname : fno.fname; +#else + fn = fno.fname; +#endif + if (strlen(fn) > SD_SCREEN_FILE_LENGTH) continue; + + reusableBuffer.sdmanager.count++; + + bool isfile = !(fno.fattrib & AM_DIR); + + if (s_pgOfs == 0) { + for (uint8_t i=0; i=0; i--) { + char *line = reusableBuffer.sdmanager.lines[i]; + if (line[0] == '\0' || isFilenameGreater(isfile, fn, line)) { + if (i > 0) memmove(reusableBuffer.sdmanager.lines[0], reusableBuffer.sdmanager.lines[1], sizeof(reusableBuffer.sdmanager.lines[0]) * i); + memset(line, 0, sizeof(reusableBuffer.sdmanager.lines[i])); + strcpy(line, fn); + line[SD_SCREEN_FILE_LENGTH+1] = isfile; + break; + } + } + } + else if (s_pgOfs > reusableBuffer.sdmanager.offset) { + if (isFilenameGreater(isfile, fn, reusableBuffer.sdmanager.lines[5]) && isFilenameLower(isfile, fn, reusableBuffer.sdmanager.lines[6])) { + memset(reusableBuffer.sdmanager.lines[6], 0, sizeof(reusableBuffer.sdmanager.lines[0])); + strcpy(reusableBuffer.sdmanager.lines[6], fn); + reusableBuffer.sdmanager.lines[6][SD_SCREEN_FILE_LENGTH+1] = isfile; + } + } + else { + if (isFilenameLower(isfile, fn, reusableBuffer.sdmanager.lines[1]) && isFilenameGreater(isfile, fn, reusableBuffer.sdmanager.lines[0])) { + memset(reusableBuffer.sdmanager.lines[0], 0, sizeof(reusableBuffer.sdmanager.lines[0])); + strcpy(reusableBuffer.sdmanager.lines[0], fn); + reusableBuffer.sdmanager.lines[0][SD_SCREEN_FILE_LENGTH+1] = isfile; + } + } + } + } + } + + reusableBuffer.sdmanager.offset = s_pgOfs; + + for (uint8_t i=0; i + * - Andreas Weitl + * - Bertrand Songis + * - Bryan J. Rentoul (Gruvin) + * - Cameron Weeks + * - Erez Raviv + * - Gabriel Birkus + * - Jean-Pierre Parisy + * - Karl Szmutny + * - Michael Blandford + * - Michal Hlavinka + * - Pat Mackenzie + * - Philip Moss + * - Rob Thomson + * - Romolo Manfredini + * - Thomas Husterer + * + * opentx is based on code named + * gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/, + * er9x by Erez Raviv: http://code.google.com/p/er9x/, + * and the original (and ongoing) project by + * Thomas Husterer, th9x: http://code.google.com/p/th9x/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include "../../opentx.h" + +const pm_uchar sticks[] PROGMEM = { +#include "../../bitmaps/sticks.lbm" +}; + +#define RADIO_SETUP_2ND_COLUMN (LCD_W-6*FW-3-MENUS_SCROLLBAR_WIDTH) +#define RADIO_SETUP_TIME_COLUMN (FW*15+9) +#define RADIO_SETUP_DATE_COLUMN (FW*15+7) + +#if !defined(CPUM64) + #define SLIDER_5POS(y, value, label, event, attr) { \ + int8_t tmp = value; \ + displaySlider(RADIO_SETUP_2ND_COLUMN, y, 2+tmp, 4, attr); \ + value = selectMenuItem(RADIO_SETUP_2ND_COLUMN, y, label, NULL, tmp, -2, +2, attr, event); \ + } +#elif defined(GRAPHICS) + #define SLIDER_5POS(y, value, label, event, attr) { \ + int8_t tmp = value; \ + display5posSlider(RADIO_SETUP_2ND_COLUMN, y, tmp, attr); \ + value = selectMenuItem(RADIO_SETUP_2ND_COLUMN, y, label, NULL, tmp, -2, +2, attr, event); \ + } +#else + #define SLIDER_5POS(y, value, label, event, attr) value = selectMenuItem(RADIO_SETUP_2ND_COLUMN, y, label, STR_VBEEPLEN, value, -2, +2, attr, event) +#endif + +#if defined(SPLASH) && !defined(FSPLASH) + #define CASE_SPLASH_PARAM(x) x, +#else + #define CASE_SPLASH_PARAM(x) +#endif + +enum menuGeneralSetupItems { + CASE_RTCLOCK(ITEM_SETUP_DATE) + CASE_RTCLOCK(ITEM_SETUP_TIME) + CASE_BATTGRAPH(ITEM_SETUP_BATT_RANGE) + ITEM_SETUP_SOUND_LABEL, + CASE_AUDIO(ITEM_SETUP_BEEP_MODE) + CASE_BUZZER(ITEM_SETUP_BUZZER_MODE) + CASE_VOICE(ITEM_SETUP_SPEAKER_VOLUME) + CASE_CPUARM(ITEM_SETUP_BEEP_VOLUME) + ITEM_SETUP_BEEP_LENGTH, + CASE_AUDIO(ITEM_SETUP_SPEAKER_PITCH) + CASE_CPUARM(ITEM_SETUP_WAV_VOLUME) + CASE_CPUARM(ITEM_SETUP_BACKGROUND_VOLUME) + CASE_VARIO_CPUARM(ITEM_SETUP_VARIO_LABEL) + CASE_VARIO_CPUARM(ITEM_SETUP_VARIO_VOLUME) + CASE_VARIO_CPUARM(ITEM_SETUP_VARIO_PITCH) + CASE_VARIO_CPUARM(ITEM_SETUP_VARIO_RANGE) + CASE_VARIO_CPUARM(ITEM_SETUP_VARIO_REPEAT) + CASE_HAPTIC(ITEM_SETUP_HAPTIC_LABEL) + CASE_HAPTIC(ITEM_SETUP_HAPTIC_MODE) + CASE_HAPTIC(ITEM_SETUP_HAPTIC_LENGTH) + CASE_HAPTIC(ITEM_SETUP_HAPTIC_STRENGTH) + ITEM_SETUP_CONTRAST, + ITEM_SETUP_ALARMS_LABEL, + ITEM_SETUP_BATTERY_WARNING, + CASE_PCBSKY9X(ITEM_SETUP_CAPACITY_WARNING) + CASE_PCBSKY9X(ITEM_SETUP_TEMPERATURE_WARNING) + ITEM_SETUP_INACTIVITY_ALARM, + ITEM_SETUP_MEMORY_WARNING, + ITEM_SETUP_ALARM_WARNING, + IF_ROTARY_ENCODERS(ITEM_SETUP_RE_NAVIGATION) + ITEM_SETUP_BACKLIGHT_LABEL, + ITEM_SETUP_BACKLIGHT_MODE, + ITEM_SETUP_BACKLIGHT_DELAY, + CASE_CPUARM(ITEM_SETUP_BRIGHTNESS) + CASE_PWM_BACKLIGHT(ITEM_SETUP_BACKLIGHT_BRIGHTNESS_OFF) + CASE_PWM_BACKLIGHT(ITEM_SETUP_BACKLIGHT_BRIGHTNESS_ON) + ITEM_SETUP_FLASH_BEEP, + CASE_SPLASH_PARAM(ITEM_SETUP_DISABLE_SPLASH) + CASE_GPS(ITEM_SETUP_TIMEZONE) + CASE_GPS(ITEM_SETUP_GPSFORMAT) + CASE_PXX(ITEM_SETUP_COUNTRYCODE) + CASE_CPUARM(ITEM_SETUP_LANGUAGE) + CASE_CPUARM(ITEM_SETUP_IMPERIAL) + IF_FAI_CHOICE(ITEM_SETUP_FAI) + CASE_MAVLINK(ITEM_MAVLINK_BAUD) + CASE_CPUARM(ITEM_SETUP_SWITCHES_DELAY) + ITEM_SETUP_RX_CHANNEL_ORD, + ITEM_SETUP_STICK_MODE_LABELS, + ITEM_SETUP_STICK_MODE, + ITEM_SETUP_MAX +}; + +#if defined(FRSKY_STICKS) + #define COL_TX_MODE 0 +#else + #define COL_TX_MODE LABEL(TX_MODE) +#endif + +void menuGeneralSetup(uint8_t event) +{ +#if defined(RTCLOCK) + struct gtm t; + gettime(&t); + + if ((m_posVert==ITEM_SETUP_DATE+1 || m_posVert==ITEM_SETUP_TIME+1) && + (s_editMode>0) && + (event==EVT_KEY_FIRST(KEY_ENTER) || event==EVT_KEY_FIRST(KEY_EXIT) || IS_ROTARY_BREAK(event) || IS_ROTARY_LONG(event))) { + // set the date and time into RTC chip + rtcSetTime(&t); + } +#endif + +#if defined(FAI_CHOICE) + if (s_warning_result) { + s_warning_result = 0; + g_eeGeneral.fai = true; + eeDirty(EE_GENERAL); + } +#endif + + MENU(STR_MENURADIOSETUP, menuTabGeneral, e_Setup, ITEM_SETUP_MAX+1, {0, CASE_RTCLOCK(2) CASE_RTCLOCK(2) CASE_BATTGRAPH(1) LABEL(SOUND), CASE_AUDIO(0) CASE_BUZZER(0) CASE_VOICE(0) CASE_CPUARM(0) CASE_CPUARM(0) CASE_CPUARM(0) 0, CASE_AUDIO(0) CASE_VARIO_CPUARM(LABEL(VARIO)) CASE_VARIO_CPUARM(0) CASE_VARIO_CPUARM(0) CASE_VARIO_CPUARM(0) CASE_VARIO_CPUARM(0) CASE_HAPTIC(LABEL(HAPTIC)) CASE_HAPTIC(0) CASE_HAPTIC(0) CASE_HAPTIC(0) 0, LABEL(ALARMS), 0, CASE_PCBSKY9X(0) CASE_PCBSKY9X(0) 0, 0, 0, IF_ROTARY_ENCODERS(0) LABEL(BACKLIGHT), 0, 0, CASE_CPUARM(0) CASE_PWM_BACKLIGHT(0) CASE_PWM_BACKLIGHT(0) 0, CASE_SPLASH_PARAM(0) CASE_GPS(0) CASE_GPS(0) CASE_PXX(0) CASE_CPUARM(0) CASE_CPUARM(0) IF_FAI_CHOICE(0) CASE_MAVLINK(0) CASE_CPUARM(0) 0, COL_TX_MODE, 1/*to force edit mode*/}); + + uint8_t sub = m_posVert - 1; + + for (uint8_t i=0; i0) ? BLINK|INVERS : INVERS); + uint8_t attr = (sub == k ? blink : 0); + + switch(k) { +#if defined(RTCLOCK) + case ITEM_SETUP_DATE: + lcd_putsLeft(y, STR_DATE); + lcd_putc(RADIO_SETUP_DATE_COLUMN, y, '-'); lcd_putc(RADIO_SETUP_DATE_COLUMN+3*FW-2, y, '-'); + for (uint8_t j=0; j<3; j++) { + uint8_t rowattr = (m_posHorz==j ? attr : 0); + switch (j) { + case 0: + lcd_outdezAtt(RADIO_SETUP_DATE_COLUMN, y, t.tm_year+1900, rowattr); + if (rowattr && (s_editMode>0 || p1valdiff)) t.tm_year = checkIncDec(event, t.tm_year, 112, 200, 0); + break; + case 1: + lcd_outdezNAtt(RADIO_SETUP_DATE_COLUMN+3*FW-2, y, t.tm_mon+1, rowattr|LEADING0, 2); + if (rowattr && (s_editMode>0 || p1valdiff)) t.tm_mon = checkIncDec(event, t.tm_mon, 0, 11, 0); + break; + case 2: + { + int16_t year = 1900 + t.tm_year; + int8_t dlim = (((((year%4==0) && (year%100!=0)) || (year%400==0)) && (t.tm_mon==1)) ? 1 : 0); + static const pm_uint8_t dmon[] PROGMEM = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; + dlim += pgm_read_byte(&dmon[t.tm_mon]); + lcd_outdezNAtt(RADIO_SETUP_DATE_COLUMN+6*FW-4, y, t.tm_mday, rowattr|LEADING0, 2); + if (rowattr && (s_editMode>0 || p1valdiff)) t.tm_mday = checkIncDec(event, t.tm_mday, 1, dlim, 0); + break; + } + } + } + if (attr && checkIncDec_Ret) { + g_rtcTime = gmktime(&t); // update local timestamp and get wday calculated + } + break; + + case ITEM_SETUP_TIME: + lcd_putsLeft(y, STR_TIME); + lcd_putc(RADIO_SETUP_TIME_COLUMN+1, y, ':'); lcd_putc(RADIO_SETUP_TIME_COLUMN+3*FW-2, y, ':'); + for (uint8_t j=0; j<3; j++) { + uint8_t rowattr = (m_posHorz==j ? attr : 0); + switch (j) { + case 0: + lcd_outdezNAtt(RADIO_SETUP_TIME_COLUMN, y, t.tm_hour, rowattr|LEADING0, 2); + if (rowattr && (s_editMode>0 || p1valdiff)) t.tm_hour = checkIncDec(event, t.tm_hour, 0, 23, 0); + break; + case 1: + lcd_outdezNAtt(RADIO_SETUP_TIME_COLUMN+3*FWNUM, y, t.tm_min, rowattr|LEADING0, 2); + if (rowattr && (s_editMode>0 || p1valdiff)) t.tm_min = checkIncDec(event, t.tm_min, 0, 59, 0); + break; + case 2: + lcd_outdezNAtt(RADIO_SETUP_TIME_COLUMN+6*FWNUM, y, t.tm_sec, rowattr|LEADING0, 2); + if (rowattr && (s_editMode>0 || p1valdiff)) t.tm_sec = checkIncDec(event, t.tm_sec, 0, 59, 0); + break; + } + } + if (attr && checkIncDec_Ret) + g_rtcTime = gmktime(&t); // update local timestamp and get wday calculated + break; +#endif + +#if defined(BATTGRAPH) + case ITEM_SETUP_BATT_RANGE: + lcd_putsLeft(y, STR_BATTERY_RANGE); + putsVolts(RADIO_SETUP_2ND_COLUMN, y, 90+g_eeGeneral.vBatMin, (m_posHorz==0 ? attr : 0)|LEFT|NO_UNIT); + lcd_putc(lcdLastPos, y, '-'); + putsVolts(lcdLastPos+FW, y, 120+g_eeGeneral.vBatMax, (m_posHorz>0 ? attr : 0)|LEFT|NO_UNIT); + if (attr && s_editMode>0) { + if (m_posHorz==0) + CHECK_INCDEC_GENVAR(event, g_eeGeneral.vBatMin, -50, g_eeGeneral.vBatMax+29); // min=4.0V + else + CHECK_INCDEC_GENVAR(event, g_eeGeneral.vBatMax, g_eeGeneral.vBatMin-29, +40); // max=16.0V + } + break; +#endif + + case ITEM_SETUP_SOUND_LABEL: + lcd_putsLeft(y, STR_SOUND_LABEL); + break; + +#if defined(AUDIO) + case ITEM_SETUP_BEEP_MODE: + g_eeGeneral.beepMode = selectMenuItem(RADIO_SETUP_2ND_COLUMN, y, STR_SPEAKER, STR_VBEEPMODE, g_eeGeneral.beepMode, -2, 1, attr, event); +#if defined(FRSKY) + if (attr && checkIncDec_Ret) frskySendAlarms(); +#endif + break; + +#if defined(BUZZER) + case ITEM_SETUP_BUZZER_MODE: + g_eeGeneral.buzzerMode = selectMenuItem(RADIO_SETUP_2ND_COLUMN, y, STR_BUZZER, STR_VBEEPMODE, g_eeGeneral.buzzerMode, -2, 1, attr, event); +#if defined(FRSKY) + if (attr && checkIncDec_Ret) frskySendAlarms(); +#endif + break; +#endif +#else + case ITEM_SETUP_BUZZER_MODE: + g_eeGeneral.beepMode = selectMenuItem(RADIO_SETUP_2ND_COLUMN, y, STR_SPEAKER, STR_VBEEPMODE, g_eeGeneral.beepMode, -2, 1, attr, event); +#if defined(FRSKY) + if (attr && checkIncDec_Ret) frskySendAlarms(); +#endif + break; +#endif + +#if defined(VOICE) + case ITEM_SETUP_SPEAKER_VOLUME: + { + lcd_putsLeft(y, STR_SPEAKER_VOLUME); + uint8_t b = g_eeGeneral.speakerVolume+VOLUME_LEVEL_DEF; + displaySlider(RADIO_SETUP_2ND_COLUMN, y, b, VOLUME_LEVEL_MAX, attr); + if (attr) { + CHECK_INCDEC_GENVAR(event, b, 0, VOLUME_LEVEL_MAX); + if (checkIncDec_Ret) { + g_eeGeneral.speakerVolume = (int8_t)b-VOLUME_LEVEL_DEF; +#if !defined(CPUARM) + setVolume(b); +#endif + } + } + break; + } +#endif + +#if defined(CPUARM) + case ITEM_SETUP_BEEP_VOLUME: + SLIDER_5POS(y, g_eeGeneral.beepVolume, STR_BEEP_VOLUME, event, attr); + break; + case ITEM_SETUP_WAV_VOLUME: + SLIDER_5POS(y, g_eeGeneral.wavVolume, STR_WAV_VOLUME, event, attr); + break; + case ITEM_SETUP_BACKGROUND_VOLUME: + SLIDER_5POS(y, g_eeGeneral.backgroundVolume, STR_BG_VOLUME, event, attr); + break; +#endif + + case ITEM_SETUP_BEEP_LENGTH: + SLIDER_5POS(y, g_eeGeneral.beepLength, STR_BEEP_LENGTH, event, attr); + break; + +#if defined(AUDIO) + case ITEM_SETUP_SPEAKER_PITCH: + lcd_putsLeft( y, STR_SPKRPITCH); +#if defined(CPUARM) + lcd_putcAtt(RADIO_SETUP_2ND_COLUMN, y, '+', attr); + lcd_outdezAtt(RADIO_SETUP_2ND_COLUMN+FW, y, g_eeGeneral.speakerPitch*15, attr|LEFT); + lcd_putsAtt(lcdLastPos, y, "Hz", attr); +#else + lcd_outdezAtt(RADIO_SETUP_2ND_COLUMN, y, g_eeGeneral.speakerPitch, attr|LEFT); +#endif + if (attr) { + CHECK_INCDEC_GENVAR(event, g_eeGeneral.speakerPitch, 0, 20); + } + break; +#endif + +#if defined(CPUARM) && defined(VARIO) + case ITEM_SETUP_VARIO_LABEL: + lcd_putsLeft(y, STR_VARIO); + break; + case ITEM_SETUP_VARIO_VOLUME: + SLIDER_5POS(y, g_eeGeneral.varioVolume, TR_SPEAKER_VOLUME, event, attr); + break; + case ITEM_SETUP_VARIO_PITCH: + lcd_putsLeft(y, STR_PITCH_AT_ZERO); + lcd_outdezAtt(RADIO_SETUP_2ND_COLUMN, y, VARIO_FREQUENCY_ZERO+(g_eeGeneral.varioPitch*10), attr|LEFT); + lcd_putsAtt(lcdLastPos, y, "Hz", attr); + if (attr) CHECK_INCDEC_GENVAR(event, g_eeGeneral.varioPitch, -40, 40); + break; + case ITEM_SETUP_VARIO_RANGE: + lcd_putsLeft(y, STR_PITCH_AT_MAX); + lcd_outdezAtt(RADIO_SETUP_2ND_COLUMN, y, VARIO_FREQUENCY_ZERO+(g_eeGeneral.varioPitch*10)+VARIO_FREQUENCY_RANGE+(g_eeGeneral.varioRange*10), attr|LEFT); + lcd_putsAtt(lcdLastPos, y, "Hz", attr); + if (attr) CHECK_INCDEC_GENVAR(event, g_eeGeneral.varioRange, -80, 80); + break; + case ITEM_SETUP_VARIO_REPEAT: + lcd_putsLeft(y, STR_REPEAT_AT_ZERO); + lcd_outdezAtt(RADIO_SETUP_2ND_COLUMN, y, VARIO_REPEAT_ZERO+(g_eeGeneral.varioRepeat*10), attr|LEFT); + lcd_putsAtt(lcdLastPos, y, STR_MS, attr); + if (attr) CHECK_INCDEC_GENVAR(event, g_eeGeneral.varioRepeat, -30, 50); + break; +#endif + +#if defined(HAPTIC) + case ITEM_SETUP_HAPTIC_LABEL: + lcd_putsLeft(y, STR_HAPTIC_LABEL); + break; + + case ITEM_SETUP_HAPTIC_MODE: + g_eeGeneral.hapticMode = selectMenuItem(RADIO_SETUP_2ND_COLUMN, y, STR_MODE, STR_VBEEPMODE, g_eeGeneral.hapticMode, -2, 1, attr, event); + break; + + case ITEM_SETUP_HAPTIC_LENGTH: + SLIDER_5POS(y, g_eeGeneral.hapticLength, STR_LENGTH, event, attr); + break; + + case ITEM_SETUP_HAPTIC_STRENGTH: + SLIDER_5POS(y, g_eeGeneral.hapticStrength, STR_HAPTICSTRENGTH, event, attr); + break; +#endif + + case ITEM_SETUP_CONTRAST: + lcd_putsLeft(y, STR_CONTRAST); + lcd_outdezAtt(RADIO_SETUP_2ND_COLUMN, y, g_eeGeneral.contrast, attr|LEFT); + if (attr) { + CHECK_INCDEC_GENVAR(event, g_eeGeneral.contrast, CONTRAST_MIN, CONTRAST_MAX); + lcdSetContrast(); + } + break; + + case ITEM_SETUP_ALARMS_LABEL: + lcd_putsLeft(y, STR_ALARMS_LABEL); + break; + + case ITEM_SETUP_BATTERY_WARNING: + lcd_putsLeft(y, STR_BATTERYWARNING); + putsVolts(RADIO_SETUP_2ND_COLUMN, y, g_eeGeneral.vBatWarn, attr|LEFT); + if(attr) CHECK_INCDEC_GENVAR(event, g_eeGeneral.vBatWarn, 40, 120); //4-12V + break; + + case ITEM_SETUP_MEMORY_WARNING: + { + uint8_t b = 1-g_eeGeneral.disableMemoryWarning; + g_eeGeneral.disableMemoryWarning = 1 - onoffMenuItem(b, RADIO_SETUP_2ND_COLUMN, y, STR_MEMORYWARNING, attr, event); + break; + } + + case ITEM_SETUP_ALARM_WARNING: + { + uint8_t b = 1-g_eeGeneral.disableAlarmWarning; + g_eeGeneral.disableAlarmWarning = 1 - onoffMenuItem(b, RADIO_SETUP_2ND_COLUMN, y, STR_ALARMWARNING, attr, event); + break; + } + +#if defined(PCBSKY9X) + case ITEM_SETUP_CAPACITY_WARNING: + lcd_putsLeft(y, STR_CAPAWARNING); + putsValueWithUnit(RADIO_SETUP_2ND_COLUMN, y, g_eeGeneral.mAhWarn*50, UNIT_MAH, attr|LEFT) ; + if(attr) CHECK_INCDEC_GENVAR(event, g_eeGeneral.mAhWarn, 0, 100); + break; +#endif + +#if defined(PCBSKY9X) + case ITEM_SETUP_TEMPERATURE_WARNING: + lcd_putsLeft(y, STR_TEMPWARNING); + putsValueWithUnit(RADIO_SETUP_2ND_COLUMN, y, g_eeGeneral.temperatureWarn, UNIT_TEMPERATURE, attr|LEFT) ; + if(attr) CHECK_INCDEC_GENVAR(event, g_eeGeneral.temperatureWarn, 0, 120); // 0 means no alarm + break; +#endif + + case ITEM_SETUP_INACTIVITY_ALARM: + lcd_putsLeft( y,STR_INACTIVITYALARM); + lcd_outdezAtt(RADIO_SETUP_2ND_COLUMN, y, g_eeGeneral.inactivityTimer, attr|LEFT); + lcd_putc(lcdLastPos, y, 'm'); + if(attr) g_eeGeneral.inactivityTimer = checkIncDec(event, g_eeGeneral.inactivityTimer, 0, 250, EE_GENERAL); //0..250minutes + break; + +#if ROTARY_ENCODERS > 0 + case ITEM_SETUP_RE_NAVIGATION: + g_eeGeneral.reNavigation = selectMenuItem(RADIO_SETUP_2ND_COLUMN, y, STR_RENAVIG, STR_VRENAVIG, g_eeGeneral.reNavigation, 0, NUM_ROTARY_ENCODERS, attr, event); + if (attr && checkIncDec_Ret) { + g_rotenc[NAVIGATION_RE_IDX()] = 0; + } + break; +#endif + + case ITEM_SETUP_BACKLIGHT_LABEL: + lcd_putsLeft(y, STR_BACKLIGHT_LABEL); + break; + + case ITEM_SETUP_BACKLIGHT_MODE: + g_eeGeneral.backlightMode = selectMenuItem(RADIO_SETUP_2ND_COLUMN, y, STR_MODE, STR_VBLMODE, g_eeGeneral.backlightMode, e_backlight_mode_off, e_backlight_mode_on, attr, event); + break; + + case ITEM_SETUP_FLASH_BEEP: + g_eeGeneral.alarmsFlash = onoffMenuItem(g_eeGeneral.alarmsFlash, RADIO_SETUP_2ND_COLUMN, y, STR_ALARM, attr, event ) ; + break; + + case ITEM_SETUP_BACKLIGHT_DELAY: + lcd_putsLeft(y, STR_BLDELAY); + lcd_outdezAtt(RADIO_SETUP_2ND_COLUMN, y, g_eeGeneral.lightAutoOff*5, attr|LEFT); + lcd_putc(lcdLastPos, y, 's'); + if (attr) CHECK_INCDEC_GENVAR(event, g_eeGeneral.lightAutoOff, 0, 600/5); + break; + +#if defined(CPUARM) + case ITEM_SETUP_BRIGHTNESS: + lcd_putsLeft(y, STR_BRIGHTNESS); + lcd_outdezAtt(RADIO_SETUP_2ND_COLUMN, y, 100-g_eeGeneral.backlightBright, attr|LEFT) ; + if (attr) { + uint8_t b = 100 - g_eeGeneral.backlightBright; + CHECK_INCDEC_GENVAR(event, b, 0, 100); + g_eeGeneral.backlightBright = 100 - b; + } + break; +#endif + +#if defined(PWM_BACKLIGHT) + case ITEM_SETUP_BACKLIGHT_BRIGHTNESS_OFF: + lcd_putsLeft(y, STR_BLOFFBRIGHTNESS); + lcd_outdezAtt(RADIO_SETUP_2ND_COLUMN, y, g_eeGeneral.blOffBright, attr|LEFT); + if (attr) CHECK_INCDEC_GENVAR(event, g_eeGeneral.blOffBright, 0, 15); + break; + + case ITEM_SETUP_BACKLIGHT_BRIGHTNESS_ON: + lcd_putsLeft(y, STR_BLONBRIGHTNESS); + lcd_outdezAtt(RADIO_SETUP_2ND_COLUMN, y, 15-g_eeGeneral.blOnBright, attr|LEFT); + if (attr) g_eeGeneral.blOnBright = 15 - checkIncDecGen(event, 15-g_eeGeneral.blOnBright, 0, 15); + break; +#endif + +#if defined(SPLASH) && !defined(FSPLASH) + case ITEM_SETUP_DISABLE_SPLASH: + { + uint8_t b = 1-g_eeGeneral.splashMode; + g_eeGeneral.splashMode = 1 - onoffMenuItem(b, RADIO_SETUP_2ND_COLUMN, y, STR_SPLASHSCREEN, attr, event); + break; + } +#endif + +#if defined(FRSKY) && defined(FRSKY_HUB) && defined(GPS) + case ITEM_SETUP_TIMEZONE: + lcd_putsLeft(y, STR_TIMEZONE); + lcd_outdezAtt(RADIO_SETUP_2ND_COLUMN, y, g_eeGeneral.timezone, attr|LEFT); + if (attr) CHECK_INCDEC_GENVAR(event, g_eeGeneral.timezone, -12, 12); + break; + + case ITEM_SETUP_GPSFORMAT: + g_eeGeneral.gpsFormat = selectMenuItem(RADIO_SETUP_2ND_COLUMN, y, STR_GPSCOORD, STR_GPSFORMAT, g_eeGeneral.gpsFormat, 0, 1, attr, event); + break; +#endif + +#if defined(PXX) + case ITEM_SETUP_COUNTRYCODE: + g_eeGeneral.countryCode = selectMenuItem(RADIO_SETUP_2ND_COLUMN, y, STR_COUNTRYCODE, STR_COUNTRYCODES, g_eeGeneral.countryCode, 0, 2, attr, event); + break; +#endif + +#if defined(CPUARM) + case ITEM_SETUP_LANGUAGE: + lcd_putsLeft(y, STR_VOICELANG); + lcd_putsAtt(RADIO_SETUP_2ND_COLUMN, y, currentLanguagePack->name, attr); + if (attr) { + currentLanguagePackIdx = checkIncDec(event, currentLanguagePackIdx, 0, DIM(languagePacks)-2, EE_GENERAL); + if (checkIncDec_Ret) { + currentLanguagePack = languagePacks[currentLanguagePackIdx]; + strncpy(g_eeGeneral.ttsLanguage, currentLanguagePack->id, 2); + } + } + break; + + case ITEM_SETUP_IMPERIAL: + g_eeGeneral.imperial = selectMenuItem(RADIO_SETUP_2ND_COLUMN, y, STR_UNITSSYSTEM, STR_VUNITSSYSTEM, g_eeGeneral.imperial, 0, 1, attr, event); + break; +#endif + +#if defined(FAI_CHOICE) + case ITEM_SETUP_FAI: + onoffMenuItem(g_eeGeneral.fai, RADIO_SETUP_2ND_COLUMN, y, PSTR("FAI Mode"), attr, event); + if (attr && checkIncDec_Ret) { + if (g_eeGeneral.fai) + POPUP_WARNING(PSTR("FAI\001mode blocked!")); + else + POPUP_CONFIRMATION(PSTR("FAI mode?")); + } + break; +#endif + +#if defined(MAVLINK) + case ITEM_MAVLINK_BAUD: + g_eeGeneral.mavbaud = selectMenuItem(RADIO_SETUP_2ND_COLUMN, y, STR_MAVLINK_BAUD_LABEL, STR_MAVLINK_BAUDS, g_eeGeneral.mavbaud, 0, 7, attr, event); + break; +#endif + +#if defined(CPUARM) + case ITEM_SETUP_SWITCHES_DELAY: + lcd_putsLeft(y, STR_SWITCHES_DELAY); + lcd_outdezAtt(RADIO_SETUP_2ND_COLUMN, y, 10*SWITCHES_DELAY(), attr|LEFT); + lcd_putsAtt(lcdLastPos, y, STR_MS, attr); + if (attr) CHECK_INCDEC_GENVAR(event, g_eeGeneral.switchesDelay, -15, +15); + break; +#endif + + case ITEM_SETUP_RX_CHANNEL_ORD: + lcd_putsLeft(y, STR_RXCHANNELORD); // RAET->AETR + for (uint8_t i=1; i<=4; i++) { + putsChnLetter(RADIO_SETUP_2ND_COLUMN - FW + i*FW, y, channel_order(i), attr); + } + if (attr) CHECK_INCDEC_GENVAR(event, g_eeGeneral.templateSetup, 0, 23); + break; + + case ITEM_SETUP_STICK_MODE_LABELS: + lcd_putsLeft(y, NO_INDENT(STR_MODE)); + for (uint8_t i=0; i<4; i++) { + lcd_img((6+4*i)*FW, y, sticks, i, 0); +#if defined(FRSKY_STICKS) + if (g_eeGeneral.stickReverse & (1<0) { + CHECK_INCDEC_GENVAR(event, g_eeGeneral.stickMode, 0, 3); + } + else if (stickMode != g_eeGeneral.stickMode) { + pausePulses(); + stickMode = g_eeGeneral.stickMode; + checkTHR(); + resumePulses(); + clearKeyEvents(); + } +#if defined(ROTARY_ENCODER_NAVIGATION) + MOVE_CURSOR_FROM_HERE(); +#endif + break; + } + } +} diff --git a/radio/src/gui/9X/menu_general_trainer.cpp b/radio/src/gui/9X/menu_general_trainer.cpp new file mode 100755 index 000000000..2555e6fc2 --- /dev/null +++ b/radio/src/gui/9X/menu_general_trainer.cpp @@ -0,0 +1,114 @@ +/* + * Authors (alphabetical order) + * - Andre Bernet + * - Andreas Weitl + * - Bertrand Songis + * - Bryan J. Rentoul (Gruvin) + * - Cameron Weeks + * - Erez Raviv + * - Gabriel Birkus + * - Jean-Pierre Parisy + * - Karl Szmutny + * - Michael Blandford + * - Michal Hlavinka + * - Pat Mackenzie + * - Philip Moss + * - Rob Thomson + * - Romolo Manfredini + * - Thomas Husterer + * + * opentx is based on code named + * gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/, + * er9x by Erez Raviv: http://code.google.com/p/er9x/, + * and the original (and ongoing) project by + * Thomas Husterer, th9x: http://code.google.com/p/th9x/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include "../../opentx.h" + +#define TRAINER_CALIB_POS 8 + +void menuGeneralTrainer(uint8_t event) +{ + uint8_t y; + bool slave = SLAVE_MODE(); + + MENU(STR_MENUTRAINER, menuTabGeneral, e_Trainer, (slave ? 1 : 7), {0, 2, 2, 2, 2, 0/*, 0*/}); + + if (slave) { + lcd_puts(7*FW, 4*FH, STR_SLAVE); + } + else { + uint8_t attr; + uint8_t blink = ((s_editMode>0) ? BLINK|INVERS : INVERS); + + lcd_puts(3*FW, MENU_TITLE_HEIGHT+1, STR_MODESRC); + + y = MENU_TITLE_HEIGHT + 1 + FH; + + for (uint8_t i=1; i<=NUM_STICKS; i++) { + uint8_t chan = channel_order(i); + volatile TrainerMix *td = &g_eeGeneral.trainer.mix[chan-1]; + + putsMixerSource(0, y, MIXSRC_Rud-1+chan, (m_posVert==i && CURSOR_ON_LINE()) ? INVERS : 0); + + for (uint8_t j=0; j<3; j++) { + + attr = ((m_posVert==i && m_posHorz==j) ? blink : 0); + + switch(j) { + case 0: + lcd_putsiAtt(4*FW, y, STR_TRNMODE, td->mode, attr); + if (attr&BLINK) CHECK_INCDEC_GENVAR(event, td->mode, 0, 2); + break; + + case 1: + lcd_outdezAtt(11*FW, y, td->studWeight, attr); + if (attr&BLINK) CHECK_INCDEC_GENVAR(event, td->studWeight, -125, 125); + break; + + case 2: + lcd_putsiAtt(12*FW, y, STR_TRNCHN, td->srcChn, attr); + if (attr&BLINK) CHECK_INCDEC_GENVAR(event, td->srcChn, 0, 3); + break; + } + } + y += FH; + } + + attr = (m_posVert==5) ? blink : 0; + lcd_putsLeft(MENU_TITLE_HEIGHT+1+5*FH, STR_MULTIPLIER); + lcd_outdezAtt(LEN_MULTIPLIER*FW+3*FW, MENU_TITLE_HEIGHT+1+5*FH, g_eeGeneral.PPM_Multiplier+10, attr|PREC1); + if (attr) CHECK_INCDEC_GENVAR(event, g_eeGeneral.PPM_Multiplier, -10, 40); + + attr = (m_posVert==6) ? INVERS : 0; + if (attr) s_editMode = 0; + lcd_putsAtt(0*FW, MENU_TITLE_HEIGHT+1+6*FH, STR_CAL, attr); + for (uint8_t i=0; i<4; i++) { + uint8_t x = (i*TRAINER_CALIB_POS+16)*FW/2; +#if defined (PPM_UNIT_PERCENT_PREC1) + lcd_outdezAtt(x, MENU_TITLE_HEIGHT+1+6*FH, (g_ppmIns[i]-g_eeGeneral.trainer.calib[i])*2, PREC1); +#else + lcd_outdezAtt(x, MENU_TITLE_HEIGHT+1+6*FH, (g_ppmIns[i]-g_eeGeneral.trainer.calib[i])/5, 0); +#endif + } + + if (attr) { + if (event==EVT_KEY_LONG(KEY_ENTER)){ + memcpy(g_eeGeneral.trainer.calib, g_ppmIns, sizeof(g_eeGeneral.trainer.calib)); + eeDirty(EE_GENERAL); + AUDIO_WARNING1(); + } + } + } +} diff --git a/radio/src/gui/9X/menu_general_version.cpp b/radio/src/gui/9X/menu_general_version.cpp new file mode 100755 index 000000000..c842a3a9d --- /dev/null +++ b/radio/src/gui/9X/menu_general_version.cpp @@ -0,0 +1,54 @@ +/* + * Authors (alphabetical order) + * - Andre Bernet + * - Andreas Weitl + * - Bertrand Songis + * - Bryan J. Rentoul (Gruvin) + * - Cameron Weeks + * - Erez Raviv + * - Gabriel Birkus + * - Jean-Pierre Parisy + * - Karl Szmutny + * - Michael Blandford + * - Michal Hlavinka + * - Pat Mackenzie + * - Philip Moss + * - Rob Thomson + * - Romolo Manfredini + * - Thomas Husterer + * + * opentx is based on code named + * gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/, + * er9x by Erez Raviv: http://code.google.com/p/er9x/, + * and the original (and ongoing) project by + * Thomas Husterer, th9x: http://code.google.com/p/th9x/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include "../../opentx.h" + +void menuGeneralVersion(uint8_t event) +{ + SIMPLE_MENU(STR_MENUVERSION, menuTabGeneral, e_Vers, 1); + + lcd_putsLeft(MENU_TITLE_HEIGHT+FH, vers_stamp); + +#if defined(COPROCESSOR) + if (Coproc_valid == 1) { + lcd_putsLeft(6*FH, PSTR("CoPr:")); + lcd_outdez8(10*FW, 6*FH, Coproc_read); + } + else { + lcd_putsLeft(6*FH, PSTR("CoPr: ---")); + } +#endif +} diff --git a/radio/src/gui/9X/menu_model_setup.cpp b/radio/src/gui/9X/menu_model_setup.cpp index 8476a1584..dbd46e702 100644 --- a/radio/src/gui/9X/menu_model_setup.cpp +++ b/radio/src/gui/9X/menu_model_setup.cpp @@ -155,7 +155,7 @@ void menuModelSetup(uint8_t event) int8_t editMode = s_editMode; for (uint8_t i=0; i + * - Andreas Weitl + * - Bertrand Songis + * - Bryan J. Rentoul (Gruvin) + * - Cameron Weeks + * - Erez Raviv + * - Gabriel Birkus + * - Jean-Pierre Parisy + * - Karl Szmutny + * - Michael Blandford + * - Michal Hlavinka + * - Pat Mackenzie + * - Philip Moss + * - Rob Thomson + * - Romolo Manfredini + * - Thomas Husterer + * + * opentx is based on code named + * gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/, + * er9x by Erez Raviv: http://code.google.com/p/er9x/, + * and the original (and ongoing) project by + * Thomas Husterer, th9x: http://code.google.com/p/th9x/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include "../../opentx.h" + +vertpos_t s_pgOfs; +int8_t s_editMode; +uint8_t s_noHi; +uint8_t calibrationState; +vertpos_t m_posVert; +horzpos_t m_posHorz; + +#if defined(NAVIGATION_POT1) +int16_t p1valdiff; +#endif + +#if defined(NAVIGATION_POT2) +int8_t p2valdiff; +#endif + +#if defined(AUTOSWITCH) +int8_t checkIncDecMovedSwitch(int8_t val) +{ + if (s_editMode>0) { + int8_t swtch = getMovedSwitch(); + if (swtch) { + if (IS_MOMENTARY(val) && swtch==val) + val = -val; + else + val = swtch; + } + } + return val; +} +#endif + +int8_t checkIncDec_Ret; + +#if defined(CPUARM) +INIT_STOPS(stops100, 3, -100, 0, 100) +INIT_STOPS(stops1000, 3, -1000, 0, 1000) +INIT_STOPS(stopsSwitch, 15, SWSRC_FIRST, CATEGORY_END(-SWSRC_FIRST_LOGICAL_SWITCH), CATEGORY_END(-SWSRC_FIRST_TRIM), CATEGORY_END(-SWSRC_LAST_SWITCH+1), 0, CATEGORY_END(SWSRC_LAST_SWITCH), CATEGORY_END(SWSRC_FIRST_TRIM-1), CATEGORY_END(SWSRC_FIRST_LOGICAL_SWITCH-1), SWSRC_LAST) + +int checkIncDec(unsigned int event, int val, int i_min, int i_max, unsigned int i_flags, IsValueAvailable isValueAvailable, const CheckIncDecStops &stops) +{ + int16_t newval = val; + +#if defined(DBLKEYS) + uint8_t in = KEYS_PRESSED(); + if (!(i_flags & NO_DBLKEYS) && (EVT_KEY_MASK(event))) { + bool dblkey = true; + if (DBLKEYS_PRESSED_RGT_LFT(in)) + newval = -val; + else if (DBLKEYS_PRESSED_RGT_UP(in)) { + newval = (i_max > 100 ? 100 : i_max); + } + else if (DBLKEYS_PRESSED_LFT_DWN(in)) { + newval = (i_min < -100 ? -100 : i_min); + } + else if (DBLKEYS_PRESSED_UP_DWN(in)) { + newval = 0; + } + else { + dblkey = false; + } + + if (dblkey) { + killEvents(KEY_UP); + killEvents(KEY_DOWN); + killEvents(KEY_RIGHT); + killEvents(KEY_LEFT); + event = 0; + } + } +#endif + + if (event==EVT_KEY_FIRST(KEY_RIGHT) || event==EVT_KEY_REPT(KEY_RIGHT) || (s_editMode>0 && (IS_ROTARY_RIGHT(event) || event==EVT_KEY_FIRST(KEY_UP) || event==EVT_KEY_REPT(KEY_UP)))) { + newval++; + AUDIO_KEYPAD_UP(); + } + else if (event==EVT_KEY_FIRST(KEY_LEFT) || event==EVT_KEY_REPT(KEY_LEFT) || (s_editMode>0 && (IS_ROTARY_LEFT(event) || event==EVT_KEY_FIRST(KEY_DOWN) || event==EVT_KEY_REPT(KEY_DOWN)))) { + newval--; + AUDIO_KEYPAD_DOWN(); + } + + if (!READ_ONLY() && i_min==0 && i_max==1 && (event==EVT_KEY_BREAK(KEY_ENTER) || IS_ROTARY_BREAK(event))) { + s_editMode = 0; + newval = !val; + } + +#if defined(NAVIGATION_POT1) + // change values based on P1 + newval -= p1valdiff; + p1valdiff = 0; +#endif + +#if defined(AUTOSWITCH) + if (i_flags & INCDEC_SWITCH) { + newval = checkIncDecMovedSwitch(newval); + } +#endif + +#if defined(AUTOSOURCE) + if (i_flags & INCDEC_SOURCE) { + if (s_editMode>0) { + int8_t source = GET_MOVED_SOURCE(i_min, i_max); + if (source) { + newval = source; + } +#if defined(AUTOSWITCH) + else { + uint8_t swtch = abs(getMovedSwitch()); + if (swtch) { + newval = switchToMix(swtch); + } + } +#endif + } + } +#endif + + if (newval > i_max || newval < i_min) { + newval = (newval > i_max ? i_max : i_min); + killEvents(event); + AUDIO_WARNING2(); + } + + if (newval != val) { + if (!(i_flags & NO_INCDEC_MARKS) && (newval != i_max) && (newval != i_min) && (newval==0 || newval==-100 || newval==+100) && !IS_ROTARY_EVENT(event)) { + pauseEvents(event); // delay before auto-repeat continues + if (newval>val) // without AUDIO it's optimized, because the 2 sounds are the same + AUDIO_KEYPAD_UP(); + else + AUDIO_KEYPAD_DOWN(); + } + eeDirty(i_flags & (EE_GENERAL|EE_MODEL)); + checkIncDec_Ret = (newval > val ? 1 : -1); + } + else { + checkIncDec_Ret = 0; + } + return newval; +} +#else +int16_t checkIncDec(uint8_t event, int16_t val, int16_t i_min, int16_t i_max, uint8_t i_flags) +{ + int16_t newval = val; + +#if defined(DBLKEYS) + uint8_t in = KEYS_PRESSED(); + if (!(i_flags & NO_DBLKEYS) && (EVT_KEY_MASK(event))) { + bool dblkey = true; + if (DBLKEYS_PRESSED_RGT_LFT(in)) + newval = -val; + else if (DBLKEYS_PRESSED_RGT_UP(in)) { + newval = (i_max > 100 ? 100 : i_max); + } + else if (DBLKEYS_PRESSED_LFT_DWN(in)) { + newval = (i_min < -100 ? -100 : i_min); + } + else if (DBLKEYS_PRESSED_UP_DWN(in)) { + newval = 0; + } + else { + dblkey = false; + } + + if (dblkey) { + killEvents(KEY_UP); + killEvents(KEY_DOWN); + killEvents(KEY_RIGHT); + killEvents(KEY_LEFT); + event = 0; + } + } +#endif + + if (event==EVT_KEY_FIRST(KEY_RIGHT) || event==EVT_KEY_REPT(KEY_RIGHT) || (s_editMode>0 && (IS_ROTARY_RIGHT(event) || event==EVT_KEY_FIRST(KEY_UP) || event==EVT_KEY_REPT(KEY_UP)))) { + newval++; + AUDIO_KEYPAD_UP(); + } + else if (event==EVT_KEY_FIRST(KEY_LEFT) || event==EVT_KEY_REPT(KEY_LEFT) || (s_editMode>0 && (IS_ROTARY_LEFT(event) || event==EVT_KEY_FIRST(KEY_DOWN) || event==EVT_KEY_REPT(KEY_DOWN)))) { + newval--; + AUDIO_KEYPAD_DOWN(); + } + + if (!READ_ONLY() && i_min==0 && i_max==1 && (event==EVT_KEY_BREAK(KEY_ENTER) || IS_ROTARY_BREAK(event))) { + s_editMode = 0; + newval = !val; + } + +#if defined(NAVIGATION_POT1) + // change values based on P1 + newval -= p1valdiff; + p1valdiff = 0; +#endif + +#if defined(AUTOSWITCH) + if (i_flags & INCDEC_SWITCH) { + newval = checkIncDecMovedSwitch(newval); + } +#endif + +#if defined(AUTOSOURCE) + if (i_flags & INCDEC_SOURCE) { + if (s_editMode>0) { + int8_t source = GET_MOVED_SOURCE(i_min, i_max); + if (source) { + newval = source; + } +#if defined(AUTOSWITCH) + else { + uint8_t swtch = abs(getMovedSwitch()); + if (swtch) { + newval = switchToMix(swtch); + } + } +#endif + } + } +#endif + + if (newval > i_max || newval < i_min) { + newval = (newval > i_max ? i_max : i_min); + killEvents(event); + AUDIO_WARNING2(); + } + + if (newval != val) { + if (!(i_flags & NO_INCDEC_MARKS) && (newval != i_max) && (newval != i_min) && (newval==0 || newval==-100 || newval==+100) && !IS_ROTARY_EVENT(event)) { + pauseEvents(event); // delay before auto-repeat continues + if (newval>val) // without AUDIO it's optimized, because the 2 sounds are the same + AUDIO_KEYPAD_UP(); + else + AUDIO_KEYPAD_DOWN(); + } + eeDirty(i_flags & (EE_GENERAL|EE_MODEL)); + checkIncDec_Ret = (newval > val ? 1 : -1); + } + else { + checkIncDec_Ret = 0; + } + return newval; +} +#endif + +#if defined(CPUM64) +int8_t checkIncDecModel(uint8_t event, int8_t i_val, int8_t i_min, int8_t i_max) +{ + return checkIncDec(event, i_val, i_min, i_max, EE_MODEL); +} + +int8_t checkIncDecModelZero(uint8_t event, int8_t i_val, int8_t i_max) +{ + return checkIncDecModel(event, i_val, 0, i_max); +} + +int8_t checkIncDecGen(uint8_t event, int8_t i_val, int8_t i_min, int8_t i_max) +{ + return checkIncDec(event, i_val, i_min, i_max, EE_GENERAL); +} +#endif + +#define SCROLL_TH 64 +#define SCROLL_POT1_TH 32 + +#if defined(CPUARM) + #define CURSOR_NOT_ALLOWED_IN_ROW(row) ((int8_t)MAXCOL(row) < 0) +#else + #define CURSOR_NOT_ALLOWED_IN_ROW(row) (MAXCOL(row) == TITLE_ROW) +#endif + +#define MAXCOL(row) (horTab ? pgm_read_byte(horTab+min(row, (vertpos_t)horTabMax)) : (const uint8_t)0) +#define INC(val, min, max) if (valmin) {val--;} else {val=max;} + +#if defined(CPUARM) +tmr10ms_t menuEntryTime; +#endif + +void check(check_event_t event, uint8_t curr, const MenuFuncP *menuTab, uint8_t menuTabSize, const pm_uint8_t *horTab, uint8_t horTabMax, vertpos_t maxrow) +{ + vertpos_t l_posVert = m_posVert; + horzpos_t l_posHorz = m_posHorz; + + uint8_t maxcol = MAXCOL(l_posVert); + +#if defined(NAVIGATION_POT1) + // check pot 1 - if changed -> scroll values + static int16_t p1val; + static int16_t p1valprev; + p1valdiff = (p1val-calibratedStick[6]) / SCROLL_POT1_TH; + if (p1valdiff) { + p1valdiff = (p1valprev-calibratedStick[6]) / 2; + p1val = calibratedStick[6]; + } + p1valprev = calibratedStick[6]; +#endif + +#if defined(NAVIGATION_POT2) + // check pot 2 - if changed -> scroll menu + static int16_t p2valprev; + p2valdiff = (p2valprev-calibratedStick[4]) / SCROLL_TH; + if (p2valdiff) p2valprev = calibratedStick[4]; +#endif + +#if defined(NAVIGATION_POT3) + // check pot 3 if changed -> cursor down/up + static int16_t p3valprev; + int8_t scrollUD = (p3valprev-calibratedStick[5]) / SCROLL_TH; + if (scrollUD) p3valprev = calibratedStick[5]; +#else + #define scrollUD 0 +#endif + + if (p2valdiff || scrollUD || p1valdiff) backlightOn(); // on keypress turn the light on + + if (menuTab) { + uint8_t attr = 0; + + + if (l_posVert==0 && !calibrationState) { + attr = INVERS; + + int8_t cc = curr; + + if (p2valdiff) { + cc = limit((int8_t)0, (int8_t)(cc - p2valdiff), (int8_t)(menuTabSize-1)); + } + + switch(event) { +#if defined(ROTARY_ENCODER_NAVIGATION) + case EVT_ROTARY_BREAK: + if (s_editMode < 0 && maxrow > 0) { + s_editMode = 0; + // TODO ? l_posVert = (horTab && horTab[1]==0xff) ? 2 : 1; + l_posHorz = 0; + } + else { + s_editMode = -1; + } + event = 0; + break; +#endif + +#if defined(ROTARY_ENCODER_NAVIGATION) + case EVT_ROTARY_LEFT: + if (s_editMode >= 0) + break; +#endif + case EVT_KEY_FIRST(KEY_LEFT): + if (curr > 0) + cc = curr - 1; + else + cc = menuTabSize-1; + break; + +#if defined(ROTARY_ENCODER_NAVIGATION) + case EVT_ROTARY_RIGHT: + if (s_editMode >= 0) + break; +#endif + case EVT_KEY_FIRST(KEY_RIGHT): + if (curr < (menuTabSize-1)) + cc = curr + 1; + else + cc = 0; + break; + } + + if (cc != curr) { + chainMenu((MenuFuncP)pgm_read_adr(&menuTab[cc])); + } + +#if defined(ROTARY_ENCODER_NAVIGATION) + if (IS_RE_NAVIGATION_ENABLE() && s_editMode < 0) + attr = INVERS|BLINK; +#endif + } + + calibrationState = 0; + displayScreenIndex(curr, menuTabSize, attr); + + } + + DISPLAY_PROGRESS_BAR(menuTab ? lcdLastPos-2*FW-((curr+1)/10*FWNUM)-2 : 20*FW+1); + + if (s_editMode<=0) { + if (scrollUD) { + l_posVert = limit((int8_t)0, (int8_t)(l_posVert - scrollUD), (int8_t)maxrow); + l_posHorz = min((uint8_t)l_posHorz, MAXCOL(l_posVert)); + } + + if (p2valdiff && l_posVert>0) { + l_posHorz = limit((int8_t)0, (int8_t)((uint8_t)l_posHorz - p2valdiff), (int8_t)maxcol); + } + } + + switch(event) + { + case EVT_ENTRY: +#if defined(CPUARM) + menuEntryTime = get_tmr10ms(); +#endif + l_posVert = POS_VERT_INIT; + l_posHorz = POS_HORZ_INIT(l_posVert); + SET_SCROLLBAR_X(LCD_W-1); +#if defined(ROTARY_ENCODER_NAVIGATION) + if (menuTab) { + s_editMode = EDIT_MODE_INIT; + break; + } + // no break +#else + s_editMode = EDIT_MODE_INIT; + break; +#endif + +#if defined(ROTARY_ENCODER_NAVIGATION) + case EVT_ENTRY_UP: + s_editMode = 0; + SET_SCROLLBAR_X(LCD_W-1); + break; + + case EVT_ROTARY_BREAK: + if (s_editMode > 1) break; +#endif + + case EVT_KEY_FIRST(KEY_ENTER): + if (!menuTab || l_posVert>0) { + if (READ_ONLY_UNLOCKED()) { + s_editMode = (s_editMode<=0); + } + } + break; + +#if defined(ROTARY_ENCODER_NAVIGATION) + case EVT_ROTARY_LONG: + if (s_editMode > 1) break; + killEvents(event); + if (l_posVert != POS_VERT_INIT) { + l_posVert = POS_VERT_INIT; + s_editMode = EDIT_MODE_INIT; + break; + } + // no break +#endif + case EVT_KEY_LONG(KEY_EXIT): + s_editMode = 0; // TODO needed? we call ENTRY_UP after which does the same + popMenu(); + break; + + case EVT_KEY_BREAK(KEY_EXIT): +#if defined(ROTARY_ENCODER_NAVIGATION) + if (s_editMode == 0) + s_editMode = EDIT_MODE_INIT; + else +#endif + if (s_editMode>0) { + s_editMode = 0; + break; + } + + if (l_posVert==0 || !menuTab) { + popMenu(); // beeps itself + } + else { + AUDIO_MENUS(); + l_posVert = 0; + l_posHorz = 0; + } + break; + + case EVT_KEY_REPT(KEY_RIGHT): //inc + if (l_posHorz==maxcol) break; + // no break + + case EVT_KEY_FIRST(KEY_RIGHT)://inc + if (!horTab || s_editMode>0) break; + +#if defined(ROTARY_ENCODER_NAVIGATION) + CASE_EVT_ROTARY_MOVE_RIGHT + if (s_editMode != 0) break; + if (l_posHorz < maxcol) { + l_posHorz++; + break; + } + else { + l_posHorz = 0; + if (!IS_ROTARY_MOVE_RIGHT(event)) + break; + } +#else + INC(l_posHorz, 0, maxcol); + break; +#endif + + case EVT_KEY_REPT(KEY_DOWN): //inc + if (!IS_ROTARY_RIGHT(event) && l_posVert==maxrow) break; + // no break + + case EVT_KEY_FIRST(KEY_DOWN): //inc + if (s_editMode>0) break; + do { + INC(l_posVert, POS_VERT_INIT, maxrow); + } while (CURSOR_NOT_ALLOWED_IN_ROW(l_posVert)); + +#if defined(ROTARY_ENCODER_NAVIGATION) + s_editMode = 0; // if we go down, we must be in this mode +#endif + + l_posHorz = min(l_posHorz, MAXCOL(l_posVert)); + break; + + case EVT_KEY_REPT(KEY_LEFT): //dec + if (l_posHorz==0) break; + // no break + + case EVT_KEY_FIRST(KEY_LEFT)://dec + if (!horTab || s_editMode>0) break; + +#if defined(ROTARY_ENCODER_NAVIGATION) + CASE_EVT_ROTARY_MOVE_LEFT + if (s_editMode != 0) break; + if (l_posHorz > 0) { + l_posHorz--; + break; + } + else if (IS_ROTARY_MOVE_LEFT(event) && s_editMode == 0) { + l_posHorz = 0xff; + } + else { + l_posHorz = maxcol; + break; + } +#else + DEC(l_posHorz, 0, maxcol); + break; +#endif + + case EVT_KEY_REPT(KEY_UP): //dec + if (!IS_ROTARY_LEFT(event) && l_posVert==0) break; + // no break + case EVT_KEY_FIRST(KEY_UP): //dec + if (s_editMode>0) break; + + do { + DEC(l_posVert, POS_VERT_INIT, maxrow); + } while (CURSOR_NOT_ALLOWED_IN_ROW(l_posVert)); + +#if defined(ROTARY_ENCODER_NAVIGATION) + s_editMode = 0; // if we go up, we must be in this mode +#endif + + l_posHorz = min((uint8_t)l_posHorz, MAXCOL(l_posVert)); + break; + } + +#if defined(CPUARM) + if (l_posVert<1) { + s_pgOfs=0; + } + else if (menuTab && horTab) { + vertpos_t realPosVert = l_posVert; + vertpos_t realPgOfs = s_pgOfs; + vertpos_t realMaxrow = maxrow; + for (vertpos_t i=1; i<=maxrow; i++) { + if (MAXCOL(i) == HIDDEN_ROW) { + realMaxrow--; + if (i < l_posVert) + realPosVert--; + if (i < s_pgOfs) + realPgOfs--; + } + } + if (realPosVert>(LCD_LINES-1)+realPgOfs) realPgOfs = realPosVert-(LCD_LINES-1); + else if (realPosVert<1+realPgOfs) realPgOfs = realPosVert-1; + s_pgOfs = realPgOfs; + for (vertpos_t i=1; i<=realPgOfs; i++) { + if (MAXCOL(i) == HIDDEN_ROW) { + s_pgOfs++; + } + } + maxrow = realMaxrow; + } + else { + uint8_t max = menuTab ? LCD_LINES-1 : LCD_LINES-2; + if (l_posVert>max+s_pgOfs) s_pgOfs = l_posVert-max; + else if (l_posVert<1+s_pgOfs) s_pgOfs = l_posVert-1; + } +#else + uint8_t max = menuTab ? LCD_LINES-1 : LCD_LINES-2; + if (l_posVert<1) s_pgOfs=0; + else if (l_posVert>max+s_pgOfs) s_pgOfs = l_posVert-max; + else if (l_posVert<1+s_pgOfs) s_pgOfs = l_posVert-1; +#endif + m_posVert = l_posVert; + m_posHorz = l_posHorz; +#if !defined(CPUM64) + // cosmetics on 9x + if (s_pgOfs > 0) { + l_posVert--; + if (l_posVert == s_pgOfs && CURSOR_NOT_ALLOWED_IN_ROW(l_posVert)) { + s_pgOfs = l_posVert-1; + } + } +#endif +} + +void check_simple(check_event_t event, uint8_t curr, const MenuFuncP *menuTab, uint8_t menuTabSize, vertpos_t maxrow) +{ + check(event, curr, menuTab, menuTabSize, 0, 0, maxrow); +} + +void check_submenu_simple(check_event_t event, uint8_t maxrow) +{ + check_simple(event, 0, 0, 0, maxrow); +} + +void repeatLastCursorMove(uint8_t event) +{ + if (CURSOR_MOVED_LEFT(event) || CURSOR_MOVED_RIGHT(event)) { + putEvent(event); + } + else { + m_posHorz = 0; + } +} diff --git a/radio/src/gui/9X/popups.cpp b/radio/src/gui/9X/popups.cpp new file mode 100755 index 000000000..312e46886 --- /dev/null +++ b/radio/src/gui/9X/popups.cpp @@ -0,0 +1,206 @@ +/* + * Authors (alphabetical order) + * - Andre Bernet + * - Andreas Weitl + * - Bertrand Songis + * - Bryan J. Rentoul (Gruvin) + * - Cameron Weeks + * - Erez Raviv + * - Gabriel Birkus + * - Jean-Pierre Parisy + * - Karl Szmutny + * - Michael Blandford + * - Michal Hlavinka + * - Pat Mackenzie + * - Philip Moss + * - Rob Thomson + * - Romolo Manfredini + * - Thomas Husterer + * + * opentx is based on code named + * gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/, + * er9x by Erez Raviv: http://code.google.com/p/er9x/, + * and the original (and ongoing) project by + * Thomas Husterer, th9x: http://code.google.com/p/th9x/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include "../../opentx.h" + +const pm_char * s_warning = NULL; +const pm_char * s_warning_info; +uint8_t s_warning_info_len; +uint8_t s_warning_type; +uint8_t s_warning_result = 0; + +#if defined(CPUARM) +uint8_t s_warning_info_flags = ZCHAR; +int16_t s_warning_input_value; +int16_t s_warning_input_min; +int16_t s_warning_input_max; +#endif + +void displayBox() +{ + drawFilledRect(10, 16, LCD_W-20, 40, SOLID, ERASE); + lcd_rect(10, 16, LCD_W-20, 40); +#if defined(CPUARM) + lcd_putsn(WARNING_LINE_X, WARNING_LINE_Y, s_warning, WARNING_LINE_LEN); +#else + lcd_puts(WARNING_LINE_X, WARNING_LINE_Y, s_warning); +#endif + // could be a place for a s_warning_info +} + +void displayPopup(const pm_char * pstr) +{ + s_warning = pstr; + displayBox(); + s_warning = NULL; + lcdRefresh(); +} + +void displayWarning(uint8_t event) +{ + s_warning_result = false; + displayBox(); + if (s_warning_info) { + lcd_putsnAtt(WARNING_LINE_X, WARNING_LINE_Y+FH, s_warning_info, s_warning_info_len, WARNING_INFO_FLAGS); + } + lcd_puts(WARNING_LINE_X, WARNING_LINE_Y+2*FH, s_warning_type == WARNING_TYPE_ASTERISK ? STR_EXIT : STR_POPUPS); + switch (event) { +#if defined(ROTARY_ENCODER_NAVIGATION) + case EVT_ROTARY_BREAK: +#endif + case EVT_KEY_BREAK(KEY_ENTER): + if (s_warning_type == WARNING_TYPE_ASTERISK) + break; + s_warning_result = true; + // no break +#if defined(ROTARY_ENCODER_NAVIGATION) + case EVT_ROTARY_LONG: + killEvents(event); +#endif + case EVT_KEY_BREAK(KEY_EXIT): + s_warning = NULL; + s_warning_type = WARNING_TYPE_ASTERISK; + break; +#if defined(CPUARM) + default: + if (s_warning_type != WARNING_TYPE_INPUT) break; + s_editMode = EDIT_MODIFY_FIELD; + s_warning_input_value = checkIncDec(event, s_warning_input_value, s_warning_input_min, s_warning_input_max); + s_editMode = EDIT_SELECT_FIELD; + break; +#endif + } +} + +#if defined(CPUARM) +void (*popupFunc)(uint8_t event) = NULL; +#endif + +#if defined(NAVIGATION_MENUS) +const char *s_menu[MENU_MAX_LINES]; +uint8_t s_menu_item = 0; +uint16_t s_menu_count = 0; +uint8_t s_menu_flags = 0; +uint16_t s_menu_offset = 0; +void (*menuHandler)(const char *result); +const char * displayMenu(uint8_t event) +{ + const char * result = NULL; + + uint8_t display_count = min(s_menu_count, (uint16_t)MENU_MAX_LINES); + + uint8_t y = (display_count >= 5 ? MENU_Y - FH - 1 : MENU_Y); + drawFilledRect(MENU_X, y, MENU_W, display_count * (FH+1) + 2, SOLID, ERASE); + lcd_rect(MENU_X, y, MENU_W, display_count * (FH+1) + 2); + + for (uint8_t i=0; i display_count) { + displayScrollbar(MENU_X+MENU_W-1, y+1, MENU_MAX_LINES * (FH+1), s_menu_offset, s_menu_count, MENU_MAX_LINES); + } + + switch(event) { +#if defined(ROTARY_ENCODER_NAVIGATION) + CASE_EVT_ROTARY_LEFT +#endif + case EVT_KEY_FIRST(KEY_MOVE_UP): + case EVT_KEY_REPT(KEY_MOVE_UP): + if (s_menu_item > 0) { + s_menu_item--; + } +#if defined(SDCARD) + else if (s_menu_offset > 0) { + s_menu_offset--; + result = STR_UPDATE_LIST; + } +#endif + else { + s_menu_item = display_count - 1; +#if defined(SDCARD) + if (s_menu_count > MENU_MAX_LINES) { + s_menu_offset = s_menu_count - display_count; + result = STR_UPDATE_LIST; + } +#endif + } + break; + +#if defined(ROTARY_ENCODER_NAVIGATION) + CASE_EVT_ROTARY_RIGHT +#endif + case EVT_KEY_FIRST(KEY_MOVE_DOWN): + case EVT_KEY_REPT(KEY_MOVE_DOWN): + if (s_menu_item < display_count - 1 && s_menu_offset + s_menu_item + 1 < s_menu_count) { + s_menu_item++; + } +#if defined(SDCARD) + else if (s_menu_count > s_menu_offset + display_count) { + s_menu_offset++; + result = STR_UPDATE_LIST; + } +#endif + else { + s_menu_item = 0; +#if defined(SDCARD) + if (s_menu_offset) { + s_menu_offset = 0; + result = STR_UPDATE_LIST; + } +#endif + } + break; + CASE_EVT_ROTARY_BREAK + case EVT_KEY_BREAK(KEY_ENTER): + result = s_menu[s_menu_item]; + // no break +#if defined(ROTARY_ENCODER_NAVIGATION) + CASE_EVT_ROTARY_LONG + killEvents(event); +#endif + case EVT_KEY_BREAK(KEY_EXIT): + s_menu_count = 0; + s_menu_item = 0; + s_menu_flags = 0; + s_menu_offset = 0; + break; + } + + return result; +} +#endif diff --git a/radio/src/gui/9X/view_main.cpp b/radio/src/gui/9X/view_main.cpp index 30e831f8f..63d78eb21 100644 --- a/radio/src/gui/9X/view_main.cpp +++ b/radio/src/gui/9X/view_main.cpp @@ -37,8 +37,6 @@ #include "../../opentx.h" #define BIGSIZE DBLSIZE -#define BOX_WIDTH 23 -#define BOX_CENTERY (LCD_H-9-BOX_WIDTH/2) #define LBOX_CENTERX (LCD_W/4 + 10) #define RBOX_CENTERX (3*LCD_W/4 - 10) #define MODELNAME_X (2*FW-2) @@ -60,8 +58,6 @@ #define TRIM_RH_X (LCD_W*3/4-2) #define TRIM_LEN 27 -#define MARKER_WIDTH 5 -#define BOX_LIMIT (BOX_WIDTH-MARKER_WIDTH) void drawPotsBars() { @@ -75,13 +71,6 @@ void drawPotsBars() } } -void drawStick(coord_t centrex, int16_t xval, int16_t yval) -{ - lcd_square(centrex-BOX_WIDTH/2, BOX_CENTERY-BOX_WIDTH/2, BOX_WIDTH); - DO_CROSS(centrex, BOX_CENTERY, 3); - lcd_square(centrex + (xval/((2*RESX)/BOX_LIMIT)) - MARKER_WIDTH/2, BOX_CENTERY - (yval/((2*RESX)/BOX_LIMIT)) - MARKER_WIDTH/2, MARKER_WIDTH, ROUND); -} - void doMainScreenGraphics() { int16_t calibStickVert = calibratedStick[CONVERT_MODE(1)]; diff --git a/radio/src/gui/9X/view_statistics.cpp b/radio/src/gui/9X/view_statistics.cpp new file mode 100755 index 000000000..f7b80cfd4 --- /dev/null +++ b/radio/src/gui/9X/view_statistics.cpp @@ -0,0 +1,224 @@ +/* + * Authors (alphabetical order) + * - Andre Bernet + * - Andreas Weitl + * - Bertrand Songis + * - Bryan J. Rentoul (Gruvin) + * - Cameron Weeks + * - Erez Raviv + * - Gabriel Birkus + * - Jean-Pierre Parisy + * - Karl Szmutny + * - Michael Blandford + * - Michal Hlavinka + * - Pat Mackenzie + * - Philip Moss + * - Rob Thomson + * - Romolo Manfredini + * - Thomas Husterer + * + * opentx is based on code named + * gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/, + * er9x by Erez Raviv: http://code.google.com/p/er9x/, + * and the original (and ongoing) project by + * Thomas Husterer, th9x: http://code.google.com/p/th9x/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include "../../opentx.h" + +void menuStatisticsView(uint8_t event) +{ + TITLE(STR_MENUSTAT); + + switch(event) + { + case EVT_KEY_FIRST(KEY_UP): + chainMenu(menuStatisticsDebug); + break; + +#if defined(CPUARM) + case EVT_KEY_LONG(KEY_MENU): + g_eeGeneral.globalTimer = 0; + eeDirty(EE_GENERAL); + sessionTimer = 0; + break; +#endif + case EVT_KEY_FIRST(KEY_EXIT): + chainMenu(menuMainView); + break; + } + + lcd_puts( 1*FW, FH*0, STR_TOTTM1TM2THRTHP); + putsTimer( 5*FW+5*FWNUM+1, FH*1, timersStates[0].val, 0, 0); + putsTimer( 12*FW+5*FWNUM+1, FH*1, timersStates[1].val, 0, 0); + + putsTimer( 5*FW+5*FWNUM+1, FH*2, s_timeCumThr, 0, 0); + putsTimer( 12*FW+5*FWNUM+1, FH*2, s_timeCum16ThrP/16, 0, 0); + + putsTimer( 12*FW+5*FWNUM+1, FH*0, sessionTimer, 0, 0); + +#if defined(CPUARM) + putsTimer(21*FW+5*FWNUM+1, 0*FH, g_eeGeneral.globalTimer + sessionTimer, TIMEHOUR, 0); +#endif + +#if defined(THRTRACE) + coord_t traceRd = (s_traceCnt < 0 ? s_traceWr : 0); + const coord_t x = 5; + const coord_t y = 60; + lcd_hline(x-3, y, MAXTRACE+3+3); + lcd_vline(x, y-32, 32+3); + + for (coord_t i=0; i=MAXTRACE) traceRd = 0; + if (traceRd==s_traceWr) break; + } +#endif +} + +#if defined(PCBSKY9X) + #define MENU_DEBUG_COL1_OFS (11*FW-3) + #define MENU_DEBUG_COL2_OFS (17*FW) + #define MENU_DEBUG_Y_CURRENT (1*FH) + #define MENU_DEBUG_Y_MAH (2*FH) + #define MENU_DEBUG_Y_CPU_TEMP (3*FH) + #define MENU_DEBUG_Y_COPROC (4*FH) + #define MENU_DEBUG_Y_MIXMAX (5*FH) + #define MENU_DEBUG_Y_RTOS (6*FH) +#else + #define MENU_DEBUG_COL1_OFS (14*FW) +#endif + +void menuStatisticsDebug(uint8_t event) +{ + TITLE(STR_MENUDEBUG); + + switch(event) + { +#if defined(CPUARM) + case EVT_KEY_LONG(KEY_ENTER): + g_eeGeneral.mAhUsed = 0; + g_eeGeneral.globalTimer = 0; + eeDirty(EE_GENERAL); +#if defined(PCBSKY9X) + Current_used = 0; +#endif + sessionTimer = 0; + killEvents(event); + AUDIO_KEYPAD_UP(); + break; +#endif + case EVT_KEY_FIRST(KEY_ENTER): +#if !defined(CPUARM) + g_tmr1Latency_min = 0xff; + g_tmr1Latency_max = 0; +#endif + maxMixerDuration = 0; + AUDIO_KEYPAD_UP(); + break; + +#if defined(DEBUG_TRACE_BUFFER) + case EVT_KEY_FIRST(KEY_UP): + pushMenu(menuTraceBuffer); + return; +#endif + + case EVT_KEY_FIRST(KEY_DOWN): + chainMenu(menuStatisticsView); + break; + case EVT_KEY_FIRST(KEY_EXIT): + chainMenu(menuMainView); + break; + } + +#if defined(PCBSKY9X) + if ((ResetReason&RSTC_SR_RSTTYP) == (2<<8)) { + lcd_puts(LCD_W-8*FW, 0*FH, "WATCHDOG"); + } + else if (unexpectedShutdown) { + lcd_puts(LCD_W-13*FW, 0*FH, "UNEXP.SHTDOWN"); + } +#endif + +#if defined(PCBSKY9X) && !defined(REVA) + // current + lcd_putsLeft(MENU_DEBUG_Y_CURRENT, STR_CPU_CURRENT); + putsValueWithUnit(MENU_DEBUG_COL1_OFS, MENU_DEBUG_Y_CURRENT, getCurrent(), UNIT_MILLIAMPS, LEFT); + uint32_t current_scale = 488 + g_eeGeneral.currentCalib; + lcd_putc(MENU_DEBUG_COL2_OFS, MENU_DEBUG_Y_CURRENT, '>'); + putsValueWithUnit(MENU_DEBUG_COL2_OFS+FW+1, MENU_DEBUG_Y_CURRENT, Current_max*10*current_scale/8192, UNIT_RAW, LEFT); + // consumption + lcd_putsLeft(MENU_DEBUG_Y_MAH, STR_CPU_MAH); + putsValueWithUnit(MENU_DEBUG_COL1_OFS, MENU_DEBUG_Y_MAH, g_eeGeneral.mAhUsed + Current_used*current_scale/8192/36, UNIT_MAH, LEFT|PREC1); +#endif + +#if defined(PCBSKY9X) + lcd_putsLeft(MENU_DEBUG_Y_CPU_TEMP, STR_CPU_TEMP); + putsValueWithUnit(MENU_DEBUG_COL1_OFS, MENU_DEBUG_Y_CPU_TEMP, getTemperature(), UNIT_TEMPERATURE, LEFT); + lcd_putc(MENU_DEBUG_COL2_OFS, MENU_DEBUG_Y_CPU_TEMP, '>'); + putsValueWithUnit(MENU_DEBUG_COL2_OFS+FW+1, MENU_DEBUG_Y_CPU_TEMP, maxTemperature+g_eeGeneral.temperatureCalib, UNIT_TEMPERATURE, LEFT); +#endif + +#if defined(COPROCESSOR) + lcd_putsLeft(MENU_DEBUG_Y_COPROC, STR_COPROC_TEMP); + + if (Coproc_read==0) { + lcd_putsAtt(MENU_DEBUG_COL1_OFS, MENU_DEBUG_Y_COPROC, PSTR("Co Proc NACK"),INVERS); + } + else if (Coproc_read==0x81) { + lcd_putsAtt(MENU_DEBUG_COL1_OFS, MENU_DEBUG_Y_COPROC, PSTR("Inst.TinyApp"),INVERS); + } + else if (Coproc_read<3) { + lcd_putsAtt(MENU_DEBUG_COL1_OFS, MENU_DEBUG_Y_COPROC, PSTR("Upgr.TinyApp"),INVERS); + } + else { + putsValueWithUnit(MENU_DEBUG_COL1_OFS, MENU_DEBUG_Y_COPROC, Coproc_temp, UNIT_TEMPERATURE, LEFT); + putsValueWithUnit(MENU_DEBUG_COL2_OFS, MENU_DEBUG_Y_COPROC, Coproc_maxtemp, UNIT_TEMPERATURE, LEFT); + } +#endif + +#if defined(CPUARM) + lcd_putsLeft(MENU_DEBUG_Y_MIXMAX, STR_TMIXMAXMS); + lcd_outdezAtt(MENU_DEBUG_COL1_OFS, MENU_DEBUG_Y_MIXMAX, DURATION_MS_PREC2(maxMixerDuration), PREC2|LEFT); + lcd_puts(lcdLastPos, MENU_DEBUG_Y_MIXMAX, "ms"); +#endif + +#if defined(PCBSKY9X) + lcd_putsLeft(MENU_DEBUG_Y_RTOS, STR_FREESTACKMINB); + lcd_outdezAtt(MENU_DEBUG_COL1_OFS, MENU_DEBUG_Y_RTOS, stack_free(0), UNSIGN|LEFT); + lcd_puts(lcdLastPos, MENU_DEBUG_Y_RTOS, "/"); + lcd_outdezAtt(lcdLastPos, MENU_DEBUG_Y_RTOS, stack_free(1), UNSIGN|LEFT); + lcd_puts(lcdLastPos, MENU_DEBUG_Y_RTOS, "/"); + lcd_outdezAtt(lcdLastPos, MENU_DEBUG_Y_RTOS, stack_free(2), UNSIGN|LEFT); +#endif + +#if !defined(CPUARM) + lcd_putsLeft(1*FH, STR_TMR1LATMAXUS); + lcd_outdez8(MENU_DEBUG_COL1_OFS , 1*FH, g_tmr1Latency_max/2 ); + lcd_putsLeft(2*FH, STR_TMR1LATMINUS); + lcd_outdez8(MENU_DEBUG_COL1_OFS , 2*FH, g_tmr1Latency_min/2 ); + lcd_putsLeft(3*FH, STR_TMR1JITTERUS); + lcd_outdez8(MENU_DEBUG_COL1_OFS , 3*FH, (g_tmr1Latency_max - g_tmr1Latency_min) /2 ); + lcd_putsLeft(4*FH, STR_TMIXMAXMS); + lcd_outdezAtt(MENU_DEBUG_COL1_OFS, 4*FH, DURATION_MS_PREC2(maxMixerDuration), PREC2); + lcd_putsLeft(5*FH, STR_FREESTACKMINB); + lcd_outdezAtt(14*FW, 5*FH, stack_free(), UNSIGN) ; +#endif + + lcd_puts(3*FW, 7*FH+1, STR_MENUTORESET); + lcd_status_line(); +} diff --git a/radio/src/gui/9X/view_telemetry.cpp b/radio/src/gui/9X/view_telemetry.cpp new file mode 100755 index 000000000..79df6265b --- /dev/null +++ b/radio/src/gui/9X/view_telemetry.cpp @@ -0,0 +1,562 @@ +/* + * Authors (alphabetical order) + * - Andre Bernet + * - Andreas Weitl + * - Bertrand Songis + * - Bryan J. Rentoul (Gruvin) + * - Cameron Weeks + * - Erez Raviv + * - Gabriel Birkus + * - Jean-Pierre Parisy + * - Karl Szmutny + * - Michael Blandford + * - Michal Hlavinka + * - Pat Mackenzie + * - Philip Moss + * - Rob Thomson + * - Romolo Manfredini + * - Thomas Husterer + * + * opentx is based on code named + * gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/, + * er9x by Erez Raviv: http://code.google.com/p/er9x/, + * and the original (and ongoing) project by + * Thomas Husterer, th9x: http://code.google.com/p/th9x/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include "../../opentx.h" + +#define STATUS_BAR_Y (7*FH+1) +#define TELEM_2ND_COLUMN (10*FW) + +#if defined(FRSKY_HUB) && defined(GAUGES) +bar_threshold_t barsThresholds[THLD_MAX]; +#endif + +uint8_t s_frsky_view = 0; + +#define BAR_LEFT 25 +#define BAR_WIDTH 100 + +void displayRssiLine() +{ + if (TELEMETRY_STREAMING()) { + lcd_hline(0, 55, 128, 0); // separator + uint8_t rssi; +#if !defined(CPUARM) + rssi = min((uint8_t)99, frskyData.rssi[1].value); + lcd_putsLeft(STATUS_BAR_Y, STR_TX); lcd_outdezNAtt(4*FW+1, STATUS_BAR_Y, rssi, LEADING0, 2); + lcd_rect(BAR_LEFT+1, 57, 38, 7); + drawFilledRect(BAR_LEFT+1, 58, 4*rssi/11, 5, (rssi < getRssiAlarmValue(0)) ? DOTTED : SOLID); +#endif + rssi = min((uint8_t)99, TELEMETRY_RSSI()); + lcd_puts(104, STATUS_BAR_Y, STR_RX); lcd_outdezNAtt(105+4*FW, STATUS_BAR_Y, rssi, LEADING0, 2); + lcd_rect(65, 57, 38, 7); + uint8_t v = 4*rssi/11; + drawFilledRect(66+36-v, 58, v, 5, (rssi < getRssiAlarmValue(0)) ? DOTTED : SOLID); + } + else { + lcd_putsAtt(7*FW, STATUS_BAR_Y, STR_NODATA, BLINK); + lcd_status_line(); + } +} + +#if defined(FRSKY) && defined(FRSKY_HUB) && defined(GPS) && !defined(CPUARM) +void displayGpsTime() +{ + uint8_t att = (TELEMETRY_STREAMING() ? LEFT|LEADING0 : LEFT|LEADING0|BLINK); + lcd_outdezNAtt(CENTER_OFS+6*FW+7, STATUS_BAR_Y, frskyData.hub.hour, att, 2); + lcd_putcAtt(CENTER_OFS+8*FW+4, STATUS_BAR_Y, ':', att); + lcd_outdezNAtt(CENTER_OFS+9*FW+2, STATUS_BAR_Y, frskyData.hub.min, att, 2); + lcd_putcAtt(CENTER_OFS+11*FW-1, STATUS_BAR_Y, ':', att); + lcd_outdezNAtt(CENTER_OFS+12*FW-3, STATUS_BAR_Y, frskyData.hub.sec, att, 2); + lcd_status_line(); +} + +void displayGpsCoord(uint8_t y, char direction, int16_t bp, int16_t ap) +{ + if (frskyData.hub.gpsFix >= 0) { + if (!direction) direction = '-'; + lcd_outdezAtt(TELEM_2ND_COLUMN, y, bp / 100, LEFT); // ddd before '.' + lcd_putc(lcdLastPos, y, '@'); + uint8_t mn = bp % 100; // TODO div_t + if (g_eeGeneral.gpsFormat == 0) { + lcd_putc(lcdLastPos+FWNUM, y, direction); + lcd_outdezNAtt(lcdLastPos+FW+FW+1, y, mn, LEFT|LEADING0, 2); // mm before '.' + lcd_vline(lcdLastPos, y, 2); + uint16_t ss = ap * 6; + lcd_outdezAtt(lcdLastPos+3, y, ss / 1000, LEFT); // '' + lcd_plot(lcdLastPos, y+FH-2, 0); // small decimal point + lcd_outdezAtt(lcdLastPos+2, y, ss % 1000, LEFT); // '' + lcd_vline(lcdLastPos, y, 2); + lcd_vline(lcdLastPos+2, y, 2); + } + else { + lcd_outdezNAtt(lcdLastPos+FW, y, mn, LEFT|LEADING0, 2); // mm before '.' + lcd_plot(lcdLastPos, y+FH-2, 0); // small decimal point + lcd_outdezNAtt(lcdLastPos+2, y, ap, LEFT|UNSIGN|LEADING0, 4); // after '.' + lcd_putc(lcdLastPos+1, y, direction); + } + } + else { + // no fix + lcd_puts(TELEM_2ND_COLUMN, y, STR_VCSWFUNC+1/*----*/); + } +} +#elif !defined(CPUARM) +#define displayGpsTime() +#define displayGpsCoord(...) +#endif + +NOINLINE uint8_t getRssiAlarmValue(uint8_t alarm) +{ + return (45 - 3*alarm + g_model.frsky.rssiAlarms[alarm].value); +} + +#if !defined(CPUARM) +void displayVoltageScreenLine(uint8_t y, uint8_t index) +{ + putsStrIdx(0, y, STR_A, index+1, 0); + if (TELEMETRY_STREAMING()) { + putsTelemetryChannelValue(3*FW+6*FW+4, y-FH, index+TELEM_A1-1, frskyData.analog[index].value, DBLSIZE); + lcd_putc(12*FW-1, y-FH, '<'); putsTelemetryChannelValue(17*FW, y-FH, index+TELEM_A1-1, frskyData.analog[index].min, NO_UNIT); + lcd_putc(12*FW, y, '>'); putsTelemetryChannelValue(17*FW, y, index+TELEM_A1-1, frskyData.analog[index].max, NO_UNIT); + } +} +#endif + +uint8_t barCoord(int16_t value, int16_t min, int16_t max) +{ +#if defined(CPUARM) + if (value <= min) + return 0; + else if (value >= max) + return BAR_WIDTH-1; + else + return ((int32_t)(BAR_WIDTH-1) * (value - min)) / (max - min); +#else + return limit((uint8_t)0, (uint8_t)(((int32_t)(BAR_WIDTH-1) * (value - min)) / (max - min)), (uint8_t)BAR_WIDTH); +#endif +} + +#if !defined(CPUARM) +void displayVoltagesScreen() +{ + // Volts / Amps / Watts / mAh + uint8_t analog = 0; + lcd_putsiAtt(0, 2*FH, STR_AMPSRC, g_model.frsky.voltsSource+1, 0); + switch (g_model.frsky.voltsSource) { + case FRSKY_VOLTS_SOURCE_A1: + case FRSKY_VOLTS_SOURCE_A2: + displayVoltageScreenLine(2*FH, g_model.frsky.voltsSource); + analog = 1+g_model.frsky.voltsSource; + break; +#if defined(FRSKY_HUB) + case FRSKY_VOLTS_SOURCE_FAS: + putsTelemetryChannelValue(3*FW+6*FW+4, FH, TELEM_VFAS-1, frskyData.hub.vfas, DBLSIZE); + break; + case FRSKY_VOLTS_SOURCE_CELLS: + putsTelemetryChannelValue(3*FW+6*FW+4, FH, TELEM_CELLS_SUM-1, frskyData.hub.cellsSum, DBLSIZE); + break; +#endif + } + + if (g_model.frsky.currentSource) { + lcd_putsiAtt(0, 4*FH, STR_AMPSRC, g_model.frsky.currentSource, 0); + switch(g_model.frsky.currentSource) { + case FRSKY_CURRENT_SOURCE_A1: + case FRSKY_CURRENT_SOURCE_A2: + displayVoltageScreenLine(4*FH, g_model.frsky.currentSource-1); + break; +#if defined(FRSKY_HUB) + case FRSKY_CURRENT_SOURCE_FAS: + putsTelemetryChannelValue(3*FW+6*FW+4, 3*FH, TELEM_CURRENT-1, frskyData.hub.current, DBLSIZE); + break; +#endif + } + + putsTelemetryChannelValue(4, 5*FH, TELEM_POWER-1, frskyData.hub.power, LEFT|DBLSIZE); + putsTelemetryChannelValue(3*FW+4+4*FW+6*FW+FW, 5*FH, TELEM_CONSUMPTION-1, frskyData.hub.currentConsumption, DBLSIZE); + } + else { + displayVoltageScreenLine(analog > 0 ? 5*FH : 4*FH, analog ? 2-analog : 0); + if (analog == 0) displayVoltageScreenLine(6*FH, 1); + } + +#if defined(FRSKY_HUB) + // Cells voltage + if (frskyData.hub.cellsCount > 0) { + uint8_t y = 1*FH; + for (uint8_t k=0; k=0; i--) { + FrSkyBarData & bar = screen.bars[i]; + source_t source = bar.source; +#if defined(CPUARM) + getvalue_t barMin = bar.barMin; + getvalue_t barMax = bar.barMax; +#else + getvalue_t barMin = convertBarTelemValue(source, bar.barMin); + getvalue_t barMax = convertBarTelemValue(source, 255-bar.barMax); +#endif + if (source && barMax > barMin) { + uint8_t y = barHeight+6+i*(barHeight+6); +#if defined(CPUARM) + putsMixerSource(0, y+barHeight-5, source, 0); +#else + lcd_putsiAtt(0, y+barHeight-5, STR_VTELEMCHNS, source, 0); +#endif + lcd_rect(BAR_LEFT, y, BAR_WIDTH+1, barHeight+2); +#if defined(CPUARM) + getvalue_t value = getValue(source); +#else + getvalue_t value = getValue(MIXSRC_FIRST_TELEM+source-1); +#endif + + uint8_t thresholdX = 0; + +#if !defined(CPUARM) + getvalue_t threshold = 0; + if (source <= TELEM_TIMER_MAX) + threshold = 0; + else if (source <= TELEM_RSSI_RX) + threshold = getRssiAlarmValue(source-TELEM_RSSI_TX); + else if (source <= TELEM_A2) + threshold = g_model.frsky.channels[source-TELEM_A1].alarms_value[0]; +#if defined(FRSKY_HUB) + else { +#if defined(GAUGES) + threshold = convertBarTelemValue(source, barsThresholds[source-TELEM_ALT]); +#endif + } +#endif + + if (threshold) { + thresholdX = barCoord(threshold, barMin, barMax); + if (thresholdX == 100) + thresholdX = 0; + } +#endif + + uint8_t width = barCoord(value, barMin, barMax); + +#if defined(CPUARM) + uint8_t barShade = SOLID; +#else + // reversed barshade for T1/T2 + uint8_t barShade = ((threshold > value) ? DOTTED : SOLID); + if (source == TELEM_T1 || source == TELEM_T2) { + barShade = -barShade; + } +#endif + + drawFilledRect(BAR_LEFT+1, y+1, width, barHeight, barShade); + + for (uint8_t j=24; j<99; j+=25) { + if (j>thresholdX || j>width) { + lcd_vline(j*BAR_WIDTH/100+BAR_LEFT+1, y+1, barHeight); + } + } + + if (thresholdX) { + lcd_vlineStip(BAR_LEFT+1+thresholdX, y-2, barHeight+3, DOTTED); + lcd_hline(BAR_LEFT+thresholdX, y-2, 3); + } + } + else { + barHeight += 2; + } + } + displayRssiLine(); + return barHeight < 13; +} + +#if defined(CPUARM) +bool displayNumbersTelemetryScreen(FrSkyScreenData & screen) +{ + // Custom Screen with numbers + uint8_t fields_count = 0; + for (uint8_t i=0; i<4; i++) { + for (uint8_t j=0; j 0) { + fields_count++; + } + if (i==3) { + lcd_vline(63, 8, 48); + if (!TELEMETRY_STREAMING()) { + displayRssiLine(); + return fields_count; + } + } + if (field) { + LcdFlags att = (i==3 ? NO_UNIT : DBLSIZE|NO_UNIT); + coord_t pos[] = {0, 65, 130}; + if (field >= MIXSRC_FIRST_TIMER && field <= MIXSRC_LAST_TIMER && i!=3) { + // there is not enough space on LCD for displaying "Tmr1" or "Tmr2" and still see the - sign, we write "T1" or "T2" instead + putsStrIdx(pos[j], 1+FH+2*FH*i, "T", field-MIXSRC_FIRST_TIMER+1, 0); + } + else if (field >= MIXSRC_FIRST_TELEM && isGPSSensor(1+(field-MIXSRC_FIRST_TELEM)/3) && telemetryItems[(field-MIXSRC_FIRST_TELEM)/3].isAvailable()) { + // we don't display GPS name, no space for it + } + else { + putsMixerSource(pos[j], 1+FH+2*FH*i, field, 0); + } + + if (field >= MIXSRC_FIRST_TELEM) { + TelemetryItem & telemetryItem = telemetryItems[(field-MIXSRC_FIRST_TELEM)/3]; // TODO macro to convert a source to a telemetry index + if (!telemetryItem.isAvailable()) { + continue; + } + else if (telemetryItem.isOld()) { + att |= INVERS|BLINK; + } + } + + putsChannel(pos[j+1]-2, (i==3 ? 1+FH+2*FH*i:FH+2*FH*i), field, att); + + } + } + } + lcd_status_line(); + return fields_count; +} +#else +bool displayNumbersTelemetryScreen(FrSkyScreenData & screen) +{ + // Custom Screen with numbers + uint8_t fields_count = 0; + for (uint8_t i=0; i<4; i++) { + for (uint8_t j=0; j 0) { + fields_count++; + } + if (i==3) { + lcd_vline(63, 8, 48); + if (TELEMETRY_STREAMING()) { +#if defined(FRSKY_HUB) + if (field == TELEM_ACC) { + lcd_putsLeft(STATUS_BAR_Y, STR_ACCEL); + lcd_outdezNAtt(4*FW, STATUS_BAR_Y, frskyData.hub.accelX, LEFT|PREC2); + lcd_outdezNAtt(10*FW, STATUS_BAR_Y, frskyData.hub.accelY, LEFT|PREC2); + lcd_outdezNAtt(16*FW, STATUS_BAR_Y, frskyData.hub.accelZ, LEFT|PREC2); + break; + } +#endif +#if defined(FRSKY_HUB) && defined(GPS) + else if (field == TELEM_GPS_TIME) { + displayGpsTime(); + break; + } +#endif + } + else { + displayRssiLine(); + return fields_count; + } + } + if (field) { + getvalue_t value = getValue(MIXSRC_FIRST_TELEM+field-1); + uint8_t att = (i==3 ? NO_UNIT : DBLSIZE|NO_UNIT); + coord_t pos[] = {0, 65, 130}; + putsTelemetryChannelValue(pos[j+1]-2, FH+2*FH*i, field-1, value, att); + + if (field >= TELEM_TIMER1 && field <= TELEM_TIMER_MAX && i!=3) { + // there is not enough space on LCD for displaying "Tmr1" or "Tmr2" and still see the - sign, we write "T1" or "T2" instead + field = field-TELEM_TIMER1+TELEM_T1; + } + + lcd_putsiAtt(pos[j], 1+FH+2*FH*i, STR_VTELEMCHNS, field, 0); + } + } + } + lcd_status_line(); + return fields_count; +} +#endif + +#if defined(CPUARM) +bool displayCustomTelemetryScreen(uint8_t index) +{ + FrSkyScreenData & screen = g_model.frsky.screens[index]; + +#if defined(GAUGES) + if (IS_BARS_SCREEN(s_frsky_view)) { + return displayGaugesTelemetryScreen(screen); + } +#endif + + displayNumbersTelemetryScreen(screen); + + return true; +} +#else +bool displayCustomTelemetryScreen(uint8_t index) +{ + FrSkyScreenData & screen = g_model.frsky.screens[index]; + +#if defined(GAUGES) + if (IS_BARS_SCREEN(s_frsky_view)) { + return displayGaugesTelemetryScreen(screen); + } +#endif + + return displayNumbersTelemetryScreen(screen); +} +#endif + +bool displayTelemetryScreen() +{ +#if defined(CPUARM) + if (TELEMETRY_SCREEN_TYPE(s_frsky_view) == TELEMETRY_SCREEN_TYPE_NONE) { + return false; + } +#endif + + lcdDrawTelemetryTopBar(); + + if (s_frsky_view < MAX_TELEMETRY_SCREENS) { + return displayCustomTelemetryScreen(s_frsky_view); + } + +#if !defined(CPUARM) + if (s_frsky_view == TELEMETRY_VOLTAGES_SCREEN) { + displayVoltagesScreen(); + } +#endif + +#if !defined(CPUARM) && defined(FRSKY_HUB) + else { + displayAfterFlightScreen(); + } +#endif + + return true; +} + +#if defined(CPUARM) +enum NavigationDirection { + none, + up, + down +}; +#define decrTelemetryScreen() direction = up +#define incrTelemetryScreen() direction = down +#else +void decrTelemetryScreen() +{ + if (s_frsky_view-- == 0) + s_frsky_view = TELEMETRY_VIEW_MAX; +} +void incrTelemetryScreen() +{ + if (s_frsky_view++ == TELEMETRY_VIEW_MAX) + s_frsky_view = 0; +} +#endif + +void menuTelemetryFrsky(uint8_t event) +{ +#if defined(CPUARM) + enum NavigationDirection direction = none; +#endif + + switch (event) { + case EVT_KEY_FIRST(KEY_EXIT): + killEvents(event); + chainMenu(menuMainView); + break; + + case EVT_KEY_FIRST(KEY_UP): + decrTelemetryScreen(); + break; + + case EVT_KEY_FIRST(KEY_DOWN): + incrTelemetryScreen(); + break; + + case EVT_KEY_FIRST(KEY_ENTER): + telemetryReset(); + break; + } + +#if defined(CPUARM) + for (int i=0; i<=TELEMETRY_SCREEN_TYPE_MAX; i++) { + if (direction == up) { + if (s_frsky_view-- == 0) + s_frsky_view = TELEMETRY_VIEW_MAX; + } + else if (direction == down) { + if (s_frsky_view++ == TELEMETRY_VIEW_MAX) + s_frsky_view = 0; + } + else { + direction = down; + } + if (displayTelemetryScreen()) { + return; + } + } + + lcdDrawTelemetryTopBar(); + lcd_puts(8*FW, 3*FH, "No Telemetry Screens"); + displayRssiLine(); +#else + if (!displayTelemetryScreen()) { + putEvent(event == EVT_KEY_FIRST(KEY_UP) ? event : EVT_KEY_FIRST(KEY_DOWN)); + } +#endif +} + diff --git a/radio/src/gui/9X/view_text.cpp b/radio/src/gui/9X/view_text.cpp new file mode 100755 index 000000000..4c5af8948 --- /dev/null +++ b/radio/src/gui/9X/view_text.cpp @@ -0,0 +1,164 @@ +/* + * Authors (alphabetical order) + * - Andre Bernet + * - Andreas Weitl + * - Bertrand Songis + * - Bryan J. Rentoul (Gruvin) + * - Cameron Weeks + * - Erez Raviv + * - Gabriel Birkus + * - Jean-Pierre Parisy + * - Karl Szmutny + * - Michael Blandford + * - Michal Hlavinka + * - Pat Mackenzie + * - Philip Moss + * - Rob Thomson + * - Romolo Manfredini + * - Thomas Husterer + * + * opentx is based on code named + * gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/, + * er9x by Erez Raviv: http://code.google.com/p/er9x/, + * and the original (and ongoing) project by + * Thomas Husterer, th9x: http://code.google.com/p/th9x/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include "../../opentx.h" + +#define TEXT_FILENAME_MAXLEN 40 +#define TEXT_FILE_MAXSIZE 2048 + +char s_text_file[TEXT_FILENAME_MAXLEN]; +char s_text_screen[LCD_LINES-1][LCD_COLS+1]; + +void readTextFile(int & lines_count) +{ + FIL file; + int result; + char c; + unsigned int sz; + int line_length = 0; + int escape = 0; + char escape_chars[2]; + int current_line = 0; + + memset(s_text_screen, 0, sizeof(s_text_screen)); + + result = f_open(&file, s_text_file, FA_OPEN_EXISTING | FA_READ); + if (result == FR_OK) { + for (int i=0; i=s_pgOfs && current_line-s_pgOfs0 && escape<3) { + escape_chars[escape-1] = c; + if (escape == 2 && !strncmp(escape_chars, "up", 2)) { + c = '\300'; + escape = 0; + } + else if (escape == 2 && !strncmp(escape_chars, "dn", 2)) { + c = '\301'; + escape = 0; + } + else { + escape++; + continue; + } + } + else if (c=='~') { + c = 'z'+1; + } + else if (c=='\t') { + c = 0x1D; //tab + } + escape = 0; + s_text_screen[current_line-s_pgOfs][line_length++] = c; + } + } + if (c != '\n') { + current_line += 1; + } + f_close(&file); + } + + if (lines_count == 0) { + lines_count = current_line; + } +} + +void menuTextView(uint8_t event) +{ + static int lines_count; + + switch (event) { + case EVT_ENTRY: + s_pgOfs = 0; + lines_count = 0; + readTextFile(lines_count); + break; + + case EVT_KEY_FIRST(KEY_UP): + if (s_pgOfs == 0) + break; + else + s_pgOfs--; + // no break; + + case EVT_KEY_FIRST(KEY_DOWN): + // if (event == EVT_KEY_BREAK(KEY_DOWN)) { + if (s_pgOfs+LCD_LINES-1 >= lines_count) + break; + else + ++s_pgOfs; + // } + readTextFile(lines_count); + break; + + case EVT_KEY_BREAK(KEY_EXIT): + popMenu(); + break; + } + + for (int i=0; i LCD_LINES-1) { + displayScrollbar(LCD_W-1, FH, LCD_H-FH, s_pgOfs, lines_count, LCD_LINES-1); + } +} + +void pushMenuTextView(const char *filename) +{ + if (strlen(filename) < TEXT_FILENAME_MAXLEN) { + strcpy(s_text_file, filename); + pushMenu(menuTextView); + } +} diff --git a/radio/src/gui/9X/widgets.cpp b/radio/src/gui/9X/widgets.cpp new file mode 100755 index 000000000..5d1b09aa7 --- /dev/null +++ b/radio/src/gui/9X/widgets.cpp @@ -0,0 +1,263 @@ +/* + * Authors (alphabetical order) + * - Andre Bernet + * - Andreas Weitl + * - Bertrand Songis + * - Bryan J. Rentoul (Gruvin) + * - Cameron Weeks + * - Erez Raviv + * - Gabriel Birkus + * - Jean-Pierre Parisy + * - Karl Szmutny + * - Michael Blandford + * - Michal Hlavinka + * - Pat Mackenzie + * - Philip Moss + * - Rob Thomson + * - Romolo Manfredini + * - Thomas Husterer + * + * opentx is based on code named + * gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/, + * er9x by Erez Raviv: http://code.google.com/p/er9x/, + * and the original (and ongoing) project by + * Thomas Husterer, th9x: http://code.google.com/p/th9x/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include "../../opentx.h" + +void drawStick(coord_t centrex, int16_t xval, int16_t yval) +{ +#define BOX_CENTERY (LCD_H-9-BOX_WIDTH/2) +#define MARKER_WIDTH 5 + lcd_square(centrex-BOX_WIDTH/2, BOX_CENTERY-BOX_WIDTH/2, BOX_WIDTH); + lcd_vline(centrex, BOX_CENTERY-1, 3); + lcd_hline(centrex-1, BOX_CENTERY, 3); + lcd_square(centrex + (xval/((2*RESX)/(BOX_WIDTH-MARKER_WIDTH))) - MARKER_WIDTH/2, BOX_CENTERY - (yval/((2*RESX)/(BOX_WIDTH-MARKER_WIDTH))) - MARKER_WIDTH/2, MARKER_WIDTH, ROUND); +#undef BOX_CENTERY +#undef MARKER_WIDTH +} + +void menu_lcd_onoff(coord_t x, coord_t y, uint8_t value, LcdFlags attr) +{ +#if defined(GRAPHICS) + if (value) + lcd_putc(x+1, y, '#'); + if (attr) + drawFilledRect(x, y, 7, 7); + else + lcd_square(x, y, 7); +#else + /* ON / OFF version */ + lcd_putsiAtt(x, y, STR_OFFON, value, attr ? INVERS:0) ; +#endif +} + +void displayScreenIndex(uint8_t index, uint8_t count, uint8_t attr) +{ + lcd_outdezAtt(LCD_W, 0, count, attr); + coord_t x = 1+LCD_W-FW*(count>9 ? 3 : 2); + lcd_putcAtt(x, 0, '/', attr); + lcd_outdezAtt(x, 0, index+1, attr); +} + +#if !defined(CPUM64) +void displayScrollbar(coord_t x, coord_t y, coord_t h, uint16_t offset, uint16_t count, uint8_t visible) +{ + lcd_vlineStip(x, y, h, DOTTED); + coord_t yofs = (h * offset) / count; + coord_t yhgt = (h * visible) / count; + if (yhgt + yofs > h) + yhgt = h - yofs; + lcd_vlineStip(x, y + yofs, yhgt, SOLID, FORCE); +} +#endif + +void title(const pm_char * s) +{ + lcd_putsAtt(0, 0, s, INVERS); +} + +select_menu_value_t selectMenuItem(coord_t x, coord_t y, const pm_char *label, const pm_char *values, select_menu_value_t value, select_menu_value_t min, select_menu_value_t max, LcdFlags attr, uint8_t event) +{ + lcd_putsColumnLeft(x, y, label); + if (values) lcd_putsiAtt(x, y, values, value-min, attr); + if (attr) value = checkIncDec(event, value, min, max, (g_menuPos[0] == 0) ? EE_MODEL : EE_GENERAL); + return value; +} + +uint8_t onoffMenuItem(uint8_t value, coord_t x, coord_t y, const pm_char *label, LcdFlags attr, uint8_t event ) +{ +#if defined(GRAPHICS) + menu_lcd_onoff(x, y, value, attr); + return selectMenuItem(x, y, label, NULL, value, 0, 1, attr, event); +#else + return selectMenuItem(x, y, label, STR_OFFON, value, 0, 1, attr, event); +#endif +} + +int8_t switchMenuItem(coord_t x, coord_t y, int8_t value, LcdFlags attr, uint8_t event) +{ + lcd_putsColumnLeft(x, y, STR_SWITCH); + putsSwitches(x, y, value, attr); + if (attr) CHECK_INCDEC_MODELSWITCH(event, value, SWSRC_FIRST_IN_MIXES, SWSRC_LAST_IN_MIXES, isSwitchAvailableInMixes); + return value; +} + +#if !defined(CPUM64) +void displaySlider(coord_t x, coord_t y, uint8_t value, uint8_t max, uint8_t attr) +{ + lcd_putc(x+(value*4*FW)/max, y, '$'); + lcd_hline(x, y+3, 5*FW-1, FORCE); + if (attr && (!(attr & BLINK) || !BLINK_ON_PHASE)) drawFilledRect(x, y, 5*FW-1, FH-1); +} +#elif defined(GRAPHICS) +void display5posSlider(coord_t x, coord_t y, uint8_t value, uint8_t attr) +{ + lcd_putc(x+2*FW+(value*FW), y, '$'); + lcd_hline(x, y+3, 5*FW-1, SOLID); + if (attr && (!(attr & BLINK) || !BLINK_ON_PHASE)) drawFilledRect(x, y, 5*FW-1, FH-1); +} +#endif + +#if defined(GVARS) && defined(CPUARM) +bool noZero(int val) +{ + return val != 0; +} + +int16_t gvarMenuItem(coord_t x, coord_t y, int16_t value, int16_t min, int16_t max, LcdFlags attr, uint8_t editflags, uint8_t event) +{ + uint16_t delta = GV_GET_GV1_VALUE(max); + bool invers = (attr & INVERS); + + // TRACE("gvarMenuItem(val=%d min=%d max=%d)", value, min, max); + + if (invers && event == EVT_KEY_LONG(KEY_ENTER)) { + s_editMode = !s_editMode; + if (attr & PREC1) + value = (GV_IS_GV_VALUE(value, min, max) ? GET_GVAR(value, min, max, mixerCurrentFlightMode)*10 : delta); + else + value = (GV_IS_GV_VALUE(value, min, max) ? GET_GVAR(value, min, max, mixerCurrentFlightMode) : delta); + eeDirty(EE_MODEL); + } + + if (GV_IS_GV_VALUE(value, min, max)) { + if (attr & LEFT) + attr -= LEFT; /* because of ZCHAR */ + else + x -= 2*FW+FWNUM; + + attr &= ~PREC1; + + int8_t idx = (int16_t) GV_INDEX_CALC_DELTA(value, delta); + if (idx >= 0) ++idx; // transform form idx=0=GV1 to idx=1=GV1 in order to handle double keys invert + if (invers) { + CHECK_INCDEC_MODELVAR_CHECK(event, idx, -MAX_GVARS, MAX_GVARS, noZero); + if (idx == 0) idx = 1; // handle reset to zero, map to GV1 + } + if (idx < 0) { + value = (int16_t) GV_CALC_VALUE_IDX_NEG(idx, delta); + idx = -idx; + lcd_putcAtt(x-6, y, '-', attr); + } + else { + value = (int16_t) GV_CALC_VALUE_IDX_POS(idx-1, delta); + } + putsStrIdx(x, y, STR_GV, idx, attr); + } + else { + lcd_outdezAtt(x, y, value, attr); + if (invers) value = checkIncDec(event, value, min, max, EE_MODEL | editflags); + } + return value; +} +#elif defined(GVARS) +int16_t gvarMenuItem(coord_t x, coord_t y, int16_t value, int16_t min, int16_t max, LcdFlags attr, uint8_t event) +{ + uint16_t delta = GV_GET_GV1_VALUE(max); + bool invers = (attr & INVERS); + + // TRACE("gvarMenuItem(val=%d min=%d max=%d)", value, min, max); + + 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, mixerCurrentFlightMode) : delta); + eeDirty(EE_MODEL); + } + 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); + if (invers) { + idx = checkIncDec(event, idx, -MAX_GVARS, MAX_GVARS-1, EE_MODEL|NO_DBLKEYS); // disable double keys + } + if (idx < 0) { + value = (int16_t) GV_CALC_VALUE_IDX_NEG(idx, delta); + idx = -idx; + lcd_putcAtt(x-6, y, '-', attr); + } + else { + value = (int16_t) GV_CALC_VALUE_IDX_POS(idx, delta); + idx++; + } + putsStrIdx(x, y, STR_GV, idx, attr); + } + else { + lcd_outdezAtt(x, y, value, attr); + if (invers) value = checkIncDec(event, value, min, max, EE_MODEL); + } + return value; +} +#else +int16_t gvarMenuItem(coord_t x, coord_t y, int16_t value, int16_t min, int16_t max, LcdFlags attr, uint8_t event) +{ + lcd_outdezAtt(x, y, value, attr); + if (attr&INVERS) value = checkIncDec(event, value, min, max, EE_MODEL); + return value; +} +#endif + +#if defined(SDCARD) +char statusLineMsg[STATUS_LINE_LENGTH]; +tmr10ms_t statusLineTime = 0; +uint8_t statusLineHeight = 0; + +void showStatusLine() +{ + statusLineTime = get_tmr10ms(); +} + +#define STATUS_LINE_DELAY (3 * 100) /* 3s */ +void drawStatusLine() +{ + if (statusLineTime) { + if ((tmr10ms_t)(get_tmr10ms() - statusLineTime) <= (tmr10ms_t)STATUS_LINE_DELAY) { + if (statusLineHeight < FH) statusLineHeight++; + } + else if (statusLineHeight) { + statusLineHeight--; + } + else { + statusLineTime = 0; + } + + drawFilledRect(0, LCD_H-statusLineHeight, LCD_W, FH, SOLID, ERASE); + lcd_putsAtt(5, LCD_H+1-statusLineHeight, statusLineMsg, BSS); + drawFilledRect(0, LCD_H-statusLineHeight, LCD_W, FH, SOLID); + } +} +#endif diff --git a/radio/src/gui/Taranis/gui.h b/radio/src/gui/Taranis/gui.h new file mode 100755 index 000000000..8bf89da73 --- /dev/null +++ b/radio/src/gui/Taranis/gui.h @@ -0,0 +1,47 @@ +/* + * Authors (alphabetical order) + * - Andre Bernet + * - Andreas Weitl + * - Bertrand Songis + * - Bryan J. Rentoul (Gruvin) + * - Cameron Weeks + * - Erez Raviv + * - Gabriel Birkus + * - Jean-Pierre Parisy + * - Karl Szmutny + * - Michael Blandford + * - Michal Hlavinka + * - Pat Mackenzie + * - Philip Moss + * - Rob Thomson + * - Romolo Manfredini + * - Thomas Husterer + * + * opentx is based on code named + * gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/, + * er9x by Erez Raviv: http://code.google.com/p/er9x/, + * and the original (and ongoing) project by + * Thomas Husterer, th9x: http://code.google.com/p/th9x/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#define DEFAULT_SCROLLBAR_X (LCD_W-1) +#define NUM_BODY_LINES (LCD_LINES-1) +#define MENU_TITLE_HEIGHT FH +#define MENU_NAVIG_HEIGHT 0 + +void displayScreenIndex(uint8_t index, uint8_t count, uint8_t attr); +void displayScrollbar(coord_t x, coord_t y, coord_t h, uint16_t offset, uint16_t count, uint8_t visible); + +extern coord_t scrollbar_X; +#define SET_SCROLLBAR_X(x) scrollbar_X = (x); + diff --git a/radio/src/gui/Taranis/helpers.cpp b/radio/src/gui/Taranis/helpers.cpp new file mode 100755 index 000000000..de6bf595b --- /dev/null +++ b/radio/src/gui/Taranis/helpers.cpp @@ -0,0 +1,348 @@ +/* + * Authors (alphabetical order) + * - Andre Bernet + * - Andreas Weitl + * - Bertrand Songis + * - Bryan J. Rentoul (Gruvin) + * - Cameron Weeks + * - Erez Raviv + * - Gabriel Birkus + * - Jean-Pierre Parisy + * - Karl Szmutny + * - Michael Blandford + * - Michal Hlavinka + * - Pat Mackenzie + * - Philip Moss + * - Rob Thomson + * - Romolo Manfredini + * - Thomas Husterer + * + * opentx is based on code named + * gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/, + * er9x by Erez Raviv: http://code.google.com/p/er9x/, + * and the original (and ongoing) project by + * Thomas Husterer, th9x: http://code.google.com/p/th9x/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include "../../opentx.h" + +uint8_t switchToMix(uint8_t source) +{ + if (source <= 5*3) + return MIXSRC_FIRST_SWITCH + (source-1) / 3; + else if (source <= 17) + return MIXSRC_SF; + else if (source <= 20) + return MIXSRC_SG; + else + return MIXSRC_SH; +} + +bool isInputAvailable(int input) +{ + for (int i=0; ichn == input) + return true; + } + return false; +} + +bool isSourceAvailable(int source) +{ + if (source>=MIXSRC_FIRST_INPUT && source<=MIXSRC_LAST_INPUT) { + return isInputAvailable(source - MIXSRC_FIRST_INPUT); + } + +#if defined(LUA_MODEL_SCRIPTS) + if (source>=MIXSRC_FIRST_LUA && source<=MIXSRC_LAST_LUA) { + div_t qr = div(source-MIXSRC_FIRST_LUA, MAX_SCRIPT_OUTPUTS); + return (qr.rem=MIXSRC_FIRST_LUA && source<=MIXSRC_LAST_LUA) + return false; +#endif + + if (source>=MIXSRC_FIRST_POT && source<=MIXSRC_LAST_POT) { + return IS_POT_AVAILABLE(POT1+source-MIXSRC_FIRST_POT); + } + +#if !defined(HELI) + if (source>=MIXSRC_CYC1 && source<=MIXSRC_CYC3) + return false; +#endif + + if (source>=MIXSRC_CH1 && source<=MIXSRC_LAST_CH) { + uint8_t destCh = source-MIXSRC_CH1; + for (uint8_t i = 0; i < MAX_MIXERS; i++) { + MixData *md = mixAddress(i); + if (md->srcRaw == 0) return false; + if (md->destCh==destCh) return true; + } + return false; + } + + if (source>=MIXSRC_SI && source<=MIXSRC_SN) { + if (!IS_2x2POS(source-MIXSRC_SI)) { + return false; + } + } + + if (source>=MIXSRC_SW1 && source<=MIXSRC_LAST_LOGICAL_SWITCH) { + LogicalSwitchData * cs = lswAddress(source-MIXSRC_SW1); + return (cs->func != LS_FUNC_NONE); + } + +#if !defined(GVARS) + if (source>=MIXSRC_GVAR1 && source<=MIXSRC_LAST_GVAR) + return false; +#endif + + if (source>=MIXSRC_RESERVE1 && source<=MIXSRC_RESERVE5) + return false; + + if (source>=MIXSRC_FIRST_TELEM && source<=MIXSRC_LAST_TELEM) { + div_t qr = div(source-MIXSRC_FIRST_TELEM, 3); + if (qr.rem == 0) + return isTelemetryFieldAvailable(qr.quot); + else + return isTelemetryFieldComparisonAvailable(qr.quot); + } + + return true; +} + +bool isSourceAvailableInCustomSwitches(int source) +{ + bool result = isSourceAvailable(source); + +#if defined(FRSKY) + if (result && source>=MIXSRC_FIRST_TELEM && source<=MIXSRC_LAST_TELEM) { + div_t qr = div(source-MIXSRC_FIRST_TELEM, 3); + result = isTelemetryFieldComparisonAvailable(qr.quot); + } +#endif + + return result; +} + +bool isInputSourceAvailable(int source) +{ +#if !defined(REVPLUS) + if (source == MIXSRC_POT3) + return false; +#endif + + if (source>=MIXSRC_Rud && source<=MIXSRC_MAX) + return true; + + if (source>=MIXSRC_Rud && source<=MIXSRC_MAX) + return true; + + if (source>=MIXSRC_TrimRud && source=MIXSRC_FIRST_CH && source<=MIXSRC_LAST_CH) + return true; + + if (source>=MIXSRC_FIRST_TRAINER && source<=MIXSRC_LAST_TRAINER) + return true; + + if (source>=MIXSRC_FIRST_TELEM && source<=MIXSRC_LAST_TELEM) + return isTelemetryFieldAvailable(source-MIXSRC_FIRST_TELEM); + + return false; +} + +enum SwitchContext +{ + LogicalSwitchesContext, + ModelCustomFunctionsContext, + GeneralCustomFunctionsContext, + TimersContext, + MixesContext +}; + +bool isSwitchAvailable(int swtch, SwitchContext context) +{ + uint32_t index = switchInfo(abs(swtch)).quot; + + if (swtch < 0) { + if (!IS_3POS(index)) + return false; + if (swtch == -SWSRC_ON || swtch == -SWSRC_One) { + return false; + } + swtch = -swtch; + } + +#if defined(REV9E) + if (swtch >= SWSRC_SA1 && swtch <= SWSRC_SR1 && (swtch-SWSRC_SA1)%3 == 0) { + return IS_3POS(index); + } +#else + if (swtch == SWSRC_SA1 || swtch == SWSRC_SB1 || swtch == SWSRC_SC1 || swtch == SWSRC_SD1 || swtch == SWSRC_SE1 || swtch == SWSRC_SG1) { + return IS_3POS(index); + } + if (swtch >= SWSRC_SI0 && swtch <= SWSRC_SM2) { + return IS_2x2POS((swtch-SWSRC_SI0)/2); + } + if (swtch >= SWSRC_SN0 && swtch <= SWSRC_SN2) { + return IS_2x2POS(6); + } +#endif + + if (swtch >= SWSRC_FIRST_MULTIPOS_SWITCH && swtch <= SWSRC_LAST_MULTIPOS_SWITCH) { + int index = (swtch - SWSRC_FIRST_MULTIPOS_SWITCH) / XPOTS_MULTIPOS_COUNT; + if (IS_POT_MULTIPOS(POT1+index)) { + StepsCalibData * calib = (StepsCalibData *) &g_eeGeneral.calib[POT1+index]; + return (calib->count >= ((swtch - SWSRC_FIRST_MULTIPOS_SWITCH) % XPOTS_MULTIPOS_COUNT)); + } + else { + return false; + } + } + + if (swtch >= SWSRC_FIRST_LOGICAL_SWITCH && swtch <= SWSRC_LAST_LOGICAL_SWITCH) { + if (context == GeneralCustomFunctionsContext) { + return false; + } + else if (context != LogicalSwitchesContext) { + LogicalSwitchData * cs = lswAddress(swtch-SWSRC_FIRST_LOGICAL_SWITCH); + return (cs->func != LS_FUNC_NONE); + } + } + + if (context != ModelCustomFunctionsContext && context != GeneralCustomFunctionsContext && (swtch == SWSRC_ON || swtch == SWSRC_One)) { + return false; + } + + if (swtch >= SWSRC_FIRST_FLIGHT_MODE && swtch <= SWSRC_LAST_FLIGHT_MODE) { + if (context == MixesContext || context == GeneralCustomFunctionsContext) { + return false; + } + else { + swtch -= SWSRC_FIRST_FLIGHT_MODE; + if (swtch == 0) { + return true; + } + FlightModeData * fm = flightModeAddress(swtch); + return (fm->swtch != SWSRC_NONE); + } + } + + return true; +} + +bool isSwitchAvailableInLogicalSwitches(int swtch) +{ + return isSwitchAvailable(swtch, LogicalSwitchesContext); +} + +bool isSwitchAvailableInCustomFunctions(int swtch) +{ + if (g_menuStack[g_menuStackPtr] == menuModelCustomFunctions) + return isSwitchAvailable(swtch, ModelCustomFunctionsContext); + else + return isSwitchAvailable(swtch, GeneralCustomFunctionsContext); +} + +bool isSwitchAvailableInMixes(int swtch) +{ + return isSwitchAvailable(swtch, MixesContext); +} + +bool isSwitchAvailableInTimers(int swtch) +{ + if (swtch >= 0) { + if (swtch < TMRMODE_COUNT) + return true; + else + swtch -= TMRMODE_COUNT-1; + } + else { + if (swtch > -TMRMODE_COUNT) + return false; + else + swtch += TMRMODE_COUNT-1; + } + + return isSwitchAvailable(swtch, TimersContext); +} + +bool isThrottleSourceAvailable(int source) +{ + if (source == THROTTLE_SOURCE_S3 && !IS_POT_AVAILABLE(POT3)) + return false; + else + return true; +} + +bool isLogicalSwitchFunctionAvailable(int function) +{ + return function != LS_FUNC_RANGE; +} + +bool isAssignableFunctionAvailable(int function) +{ + bool modelFunctions = (g_menuStack[g_menuStackPtr] == menuModelCustomFunctions); + + switch (function) { + case FUNC_OVERRIDE_CHANNEL: +#if defined(OVERRIDE_CHANNEL_FUNCTION) + return modelFunctions; +#else + return false; +#endif + case FUNC_ADJUST_GVAR: +#if defined(GVARS) + return modelFunctions; +#else + return false; +#endif +#if !defined(HAPTIC) + case FUNC_HAPTIC: +#endif + case FUNC_PLAY_DIFF: +#if !defined(DANGEROUS_MODULE_FUNCTIONS) + case FUNC_RANGECHECK: + case FUNC_BIND: + case FUNC_MODULE_OFF: +#endif +#if !defined(LUA) + case FUNC_PLAY_SCRIPT: +#endif + case FUNC_RESERVE5: + return false; + + default: + return true; + } +} + +bool isModuleAvailable(int module) +{ + return true; +} + +bool modelHasNotes() +{ + char filename[sizeof(MODELS_PATH)+1+sizeof(g_model.header.name)+sizeof(TEXT_EXT)] = MODELS_PATH "/"; + char *buf = strcat_modelname(&filename[sizeof(MODELS_PATH)], g_eeGeneral.currModel); + strcpy(buf, TEXT_EXT); + return isFileAvailable(filename); +} + diff --git a/radio/src/gui/Taranis/menu_general_calib.cpp b/radio/src/gui/Taranis/menu_general_calib.cpp new file mode 100755 index 000000000..0364f49b8 --- /dev/null +++ b/radio/src/gui/Taranis/menu_general_calib.cpp @@ -0,0 +1,212 @@ +/* + * Authors (alphabetical order) + * - Andre Bernet + * - Andreas Weitl + * - Bertrand Songis + * - Bryan J. Rentoul (Gruvin) + * - Cameron Weeks + * - Erez Raviv + * - Gabriel Birkus + * - Jean-Pierre Parisy + * - Karl Szmutny + * - Michael Blandford + * - Michal Hlavinka + * - Pat Mackenzie + * - Philip Moss + * - Rob Thomson + * - Romolo Manfredini + * - Thomas Husterer + * + * opentx is based on code named + * gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/, + * er9x by Erez Raviv: http://code.google.com/p/er9x/, + * and the original (and ongoing) project by + * Thomas Husterer, th9x: http://code.google.com/p/th9x/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include "../../opentx.h" + +#define XPOT_DELTA 10 +#define XPOT_DELAY 10 /* cycles */ + +void menuCommonCalib(uint8_t event) +{ + for (uint8_t i=0; i= POT1 && i <= POT_LAST) { + if (IS_POT_WITHOUT_DETENT(i)) { + reusableBuffer.calib.midVals[i] = (reusableBuffer.calib.hiVals[i] + reusableBuffer.calib.loVals[i]) / 2; + } + uint8_t idx = i - POT1; + int count = reusableBuffer.calib.xpotsCalib[idx].stepsCount; + if (IS_POT_MULTIPOS(i) && count <= XPOTS_MULTIPOS_COUNT) { + if (reusableBuffer.calib.xpotsCalib[idx].lastCount == 0 || vt < reusableBuffer.calib.xpotsCalib[idx].lastPosition - XPOT_DELTA || vt > reusableBuffer.calib.xpotsCalib[idx].lastPosition + XPOT_DELTA) { + reusableBuffer.calib.xpotsCalib[idx].lastPosition = vt; + reusableBuffer.calib.xpotsCalib[idx].lastCount = 1; + } + else { + if (reusableBuffer.calib.xpotsCalib[idx].lastCount < 255) reusableBuffer.calib.xpotsCalib[idx].lastCount++; + } + if (reusableBuffer.calib.xpotsCalib[idx].lastCount == XPOT_DELAY) { + int16_t position = reusableBuffer.calib.xpotsCalib[idx].lastPosition; + bool found = false; + for (int j=0; j= step-XPOT_DELTA && position <= step+XPOT_DELTA) { + found = true; + break; + } + } + if (!found) { + if (count < XPOTS_MULTIPOS_COUNT) { + reusableBuffer.calib.xpotsCalib[idx].steps[count] = position; + } + reusableBuffer.calib.xpotsCalib[idx].stepsCount += 1; + } + } + } + } + } + + calibrationState = reusableBuffer.calib.state; // make sure we don't scroll while calibrating + + switch (event) + { + case EVT_ENTRY: + reusableBuffer.calib.state = 0; + break; + + case EVT_KEY_BREAK(KEY_ENTER): + reusableBuffer.calib.state++; + break; + } + + switch (reusableBuffer.calib.state) { + case 0: + // START CALIBRATION + if (!READ_ONLY()) { + lcd_putsLeft(MENU_TITLE_HEIGHT+2*FH, STR_MENUTOSTART); + } + break; + + case 1: + // SET MIDPOINT + lcd_putsAtt(0*FW, MENU_TITLE_HEIGHT+FH, STR_SETMIDPOINT, INVERS); + lcd_putsLeft(MENU_TITLE_HEIGHT+2*FH, STR_MENUWHENDONE); + + for (uint8_t i=0; i 50) { + g_eeGeneral.calib[i].mid = reusableBuffer.calib.midVals[i]; + int16_t v = reusableBuffer.calib.midVals[i] - reusableBuffer.calib.loVals[i]; + g_eeGeneral.calib[i].spanNeg = v - v/STICK_TOLERANCE; + v = reusableBuffer.calib.hiVals[i] - reusableBuffer.calib.midVals[i]; + g_eeGeneral.calib[i].spanPos = v - v/STICK_TOLERANCE; + } + } + break; + + case 3: + for (uint8_t i=POT1; i<=POT_LAST; i++) { + int idx = i - POT1; + int count = reusableBuffer.calib.xpotsCalib[idx].stepsCount; + if (IS_POT_MULTIPOS(i)) { + if (count > 1 && count <= XPOTS_MULTIPOS_COUNT) { + for (int j=0; jcount = count - 1; + for (int j=0; jcount; j++) { + calib->steps[j] = (reusableBuffer.calib.xpotsCalib[idx].steps[j+1] + reusableBuffer.calib.xpotsCalib[idx].steps[j]) >> 5; + } + } + else { + g_eeGeneral.potsType &= ~(0x03<<(2*idx)); + } + } + } + g_eeGeneral.chkSum = evalChkSum(); + eeDirty(EE_GENERAL); + reusableBuffer.calib.state = 4; + break; + + default: + reusableBuffer.calib.state = 0; + break; + } + + doMainScreenGraphics(); + + drawPotsBars(); + for (int i=POT1; i<=POT_LAST; i++) { + uint8_t steps = 0; + if (reusableBuffer.calib.state == 2) { + steps = reusableBuffer.calib.xpotsCalib[i-POT1].stepsCount; + } + else if (IS_POT_MULTIPOS(i)) { + StepsCalibData * calib = (StepsCalibData *) &g_eeGeneral.calib[i]; + steps = calib->count + 1; + } + if (steps > 0 && steps <= XPOTS_MULTIPOS_COUNT) { + lcd_outdezAtt(LCD_W/2-2+(i-POT1)*5, LCD_H-6, steps, TINSIZE); + } + } +} + +void menuGeneralCalib(uint8_t event) +{ + check_simple(event, e_Calib, menuTabGeneral, DIM(menuTabGeneral), 0); + + if (menuEvent) { + calibrationState = 0; + } + + TITLE(STR_MENUCALIBRATION); + menuCommonCalib(READ_ONLY() ? 0 : event); +} + +void menuFirstCalib(uint8_t event) +{ + if (event == EVT_KEY_BREAK(KEY_EXIT) || reusableBuffer.calib.state == 4) { + calibrationState = 0; + chainMenu(menuMainView); + } + else { + lcd_putsCenter(0*FH, MENUCALIBRATION); + lcd_invert_line(0); + menuCommonCalib(event); + } +} diff --git a/radio/src/gui/Taranis/menu_general_diaganas.cpp b/radio/src/gui/Taranis/menu_general_diaganas.cpp new file mode 100755 index 000000000..5cdfbf3cd --- /dev/null +++ b/radio/src/gui/Taranis/menu_general_diaganas.cpp @@ -0,0 +1,71 @@ +/* + * Authors (alphabetical order) + * - Andre Bernet + * - Andreas Weitl + * - Bertrand Songis + * - Bryan J. Rentoul (Gruvin) + * - Cameron Weeks + * - Erez Raviv + * - Gabriel Birkus + * - Jean-Pierre Parisy + * - Karl Szmutny + * - Michael Blandford + * - Michal Hlavinka + * - Pat Mackenzie + * - Philip Moss + * - Rob Thomson + * - Romolo Manfredini + * - Thomas Husterer + * + * opentx is based on code named + * gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/, + * er9x by Erez Raviv: http://code.google.com/p/er9x/, + * and the original (and ongoing) project by + * Thomas Husterer, th9x: http://code.google.com/p/th9x/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include "../../opentx.h" + +void menuGeneralDiagAna(uint8_t event) +{ + SIMPLE_MENU(STR_MENUANA, menuTabGeneral, e_Ana, 2); + + STICK_SCROLL_DISABLE(); + + for (uint8_t i=0; i 9 + coord_t y = MENU_TITLE_HEIGHT + 1 + (i/3)*FH; + const uint8_t x_coord[] = {0, 70, 154}; + uint8_t x = x_coord[i%3]; + lcd_outdezNAtt(x, y, i+1, LEADING0|LEFT, 2); + lcd_putc(x+2*FW-2, y, ':'); +#else + coord_t y = MENU_TITLE_HEIGHT + 1 + (i/2)*FH; + uint8_t x = i&1 ? 64+5 : 0; + putsStrIdx(x, y, PSTR("A"), i+1); + lcd_putc(lcdNextPos, y, ':'); +#endif + lcd_outhex4(x+3*FW-1, y, anaIn(i)); + lcd_outdez8(x+10*FW-1, y, (int16_t)calibratedStick[CONVERT_MODE(i)]*25/256); + } + + lcd_putsLeft(MENU_TITLE_HEIGHT+1+5*FH, STR_BATT_CALIB); + static int32_t adcBatt; + adcBatt = ((adcBatt * 7) + anaIn(TX_VOLTAGE)) / 8; + uint32_t batCalV = (adcBatt + (adcBatt*g_eeGeneral.vBatCalib)/128) * BATT_SCALE; + batCalV >>= 11; + batCalV += 2; // because of the diode + putsVolts(LEN_CALIB_FIELDS*FW+4*FW, MENU_TITLE_HEIGHT+1+5*FH, batCalV, (m_posVert==1 ? INVERS : 0)); + + if (m_posVert==1) CHECK_INCDEC_GENVAR(event, g_eeGeneral.vBatCalib, -127, 127); +} diff --git a/radio/src/gui/Taranis/menu_general_diagkeys.cpp b/radio/src/gui/Taranis/menu_general_diagkeys.cpp new file mode 100755 index 000000000..02658b418 --- /dev/null +++ b/radio/src/gui/Taranis/menu_general_diagkeys.cpp @@ -0,0 +1,66 @@ +/* + * Authors (alphabetical order) + * - Andre Bernet + * - Andreas Weitl + * - Bertrand Songis + * - Bryan J. Rentoul (Gruvin) + * - Cameron Weeks + * - Erez Raviv + * - Gabriel Birkus + * - Jean-Pierre Parisy + * - Karl Szmutny + * - Michael Blandford + * - Michal Hlavinka + * - Pat Mackenzie + * - Philip Moss + * - Rob Thomson + * - Romolo Manfredini + * - Thomas Husterer + * + * opentx is based on code named + * gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/, + * er9x by Erez Raviv: http://code.google.com/p/er9x/, + * and the original (and ongoing) project by + * Thomas Husterer, th9x: http://code.google.com/p/th9x/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include "../../opentx.h" + +void displayKeyState(uint8_t x, uint8_t y, EnumKeys key) +{ + uint8_t t = switchState(key); + lcd_putcAtt(x, y, t+'0', t ? INVERS : 0); +} + +void menuGeneralDiagKeys(uint8_t event) +{ + SIMPLE_MENU(STR_MENUDIAG, menuTabGeneral, e_Keys, 1); + + lcd_puts(14*FW, MENU_TITLE_HEIGHT+2*FH, STR_VTRIM); + + for(uint8_t i=0; i<9; i++) { + coord_t y; + + if (i<8) { + y = MENU_TITLE_HEIGHT + FH*3 + FH*(i/2); + if (i&1) lcd_img(14*FW, y, sticks, i/2, 0); + displayKeyState(i&1? 20*FW : 18*FW, y, (EnumKeys)(TRM_BASE+i)); + } + + if (i<6) { + y = i*FH+MENU_TITLE_HEIGHT+FH; + lcd_putsiAtt(0, y, STR_VKEYS, (5-i), 0); + displayKeyState(5*FW+2, y, (EnumKeys)(KEY_MENU+(5-i))); + } + } +} diff --git a/radio/src/gui/Taranis/menu_general_hardware.cpp b/radio/src/gui/Taranis/menu_general_hardware.cpp new file mode 100755 index 000000000..2192ea087 --- /dev/null +++ b/radio/src/gui/Taranis/menu_general_hardware.cpp @@ -0,0 +1,220 @@ +/* + * Authors (alphabetical order) + * - Andre Bernet + * - Andreas Weitl + * - Bertrand Songis + * - Bryan J. Rentoul (Gruvin) + * - Cameron Weeks + * - Erez Raviv + * - Gabriel Birkus + * - Jean-Pierre Parisy + * - Karl Szmutny + * - Michael Blandford + * - Michal Hlavinka + * - Pat Mackenzie + * - Philip Moss + * - Rob Thomson + * - Romolo Manfredini + * - Thomas Husterer + * + * opentx is based on code named + * gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/, + * er9x by Erez Raviv: http://code.google.com/p/er9x/, + * and the original (and ongoing) project by + * Thomas Husterer, th9x: http://code.google.com/p/th9x/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include "../../opentx.h" + +enum menuGeneralHwItems { + ITEM_SETUP_HW_LABEL_STICKS, + ITEM_SETUP_HW_STICK1, + ITEM_SETUP_HW_STICK2, + ITEM_SETUP_HW_STICK3, + ITEM_SETUP_HW_STICK4, + ITEM_SETUP_HW_LABEL_POTS, + ITEM_SETUP_HW_POT1, + ITEM_SETUP_HW_POT2, + CASE_REVPLUS(ITEM_SETUP_HW_POT3) + CASE_REV9E(ITEM_SETUP_HW_POT4) + ITEM_SETUP_HW_LS, + ITEM_SETUP_HW_RS, + CASE_REV9E(ITEM_SETUP_HW_LS2) + CASE_REV9E(ITEM_SETUP_HW_RS2) + ITEM_SETUP_HW_LABEL_SWITCHES, + ITEM_SETUP_HW_SA, + ITEM_SETUP_HW_SB, + ITEM_SETUP_HW_SC, + ITEM_SETUP_HW_SD, + ITEM_SETUP_HW_SE, + ITEM_SETUP_HW_SF, + ITEM_SETUP_HW_SG, + ITEM_SETUP_HW_SH, + ITEM_SETUP_HW_SI, + ITEM_SETUP_HW_SJ, + ITEM_SETUP_HW_SK, + ITEM_SETUP_HW_SL, + ITEM_SETUP_HW_SM, + ITEM_SETUP_HW_SN, + CASE_REV9E(ITEM_SETUP_HW_SO) + CASE_REV9E(ITEM_SETUP_HW_SP) + CASE_REV9E(ITEM_SETUP_HW_SQ) + CASE_REV9E(ITEM_SETUP_HW_SR) + ITEM_SETUP_HW_UART3_MODE, + ITEM_SETUP_HW_MAX +}; + +#define HW_SETTINGS_COLUMN 15*FW + +#if defined(REVPLUS) + #define POTS_ROWS NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, 0, 0 +#else + #define POTS_ROWS NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, 0, 0 +#endif + +#if defined(REV9E) + #define SWITCHES_ROWS NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1 +#else + #define SWITCH_ROWS(x) uint8_t(IS_2x2POS(x) ? 0 : HIDDEN_ROW) + #define SWITCHES_ROWS NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, SWITCH_ROWS(0), SWITCH_ROWS(1), SWITCH_ROWS(2), SWITCH_ROWS(3), SWITCH_ROWS(4), SWITCH_ROWS(6) +#endif + +void menuGeneralHardware(uint8_t event) +{ + MENU(STR_HARDWARE, menuTabGeneral, e_Hardware, ITEM_SETUP_HW_MAX+1, {0, LABEL(Sticks), 0, 0, 0, 0, LABEL(Pots), POTS_ROWS, LABEL(Switches), SWITCHES_ROWS, 0}); + + uint8_t sub = m_posVert - 1; + + for (uint8_t i=0; i0) ? BLINK|INVERS : INVERS) : 0); + switch (k) { + case ITEM_SETUP_HW_LABEL_STICKS: + lcd_putsLeft(y, "Sticks"); + break; + case ITEM_SETUP_HW_STICK1: + case ITEM_SETUP_HW_STICK2: + case ITEM_SETUP_HW_STICK3: + case ITEM_SETUP_HW_STICK4: + case ITEM_SETUP_HW_LS: + case ITEM_SETUP_HW_RS: +#if defined(REV9E) + case ITEM_SETUP_HW_LS2: + case ITEM_SETUP_HW_RS2: +#endif + { + int idx = (k<=ITEM_SETUP_HW_STICK4 ? k-ITEM_SETUP_HW_STICK1 : k-ITEM_SETUP_HW_LS+7); + lcd_putsiAtt(INDENT_WIDTH, y, STR_VSRCRAW, idx+1, 0); + if (ZEXIST(g_eeGeneral.anaNames[idx]) || attr) + editName(HW_SETTINGS_COLUMN, y, g_eeGeneral.anaNames[idx], LEN_ANA_NAME, event, attr); + else + lcd_putsiAtt(HW_SETTINGS_COLUMN, y, STR_MMMINV, 0, 0); + break; + } + case ITEM_SETUP_HW_LABEL_POTS: + lcd_putsLeft(y, "Pots"); + break; + case ITEM_SETUP_HW_POT1: + case ITEM_SETUP_HW_POT2: +#if defined(REVPLUS) + case ITEM_SETUP_HW_POT3: +#endif +#if defined(REV9E) + case ITEM_SETUP_HW_POT4: +#endif + { + int idx = k - ITEM_SETUP_HW_POT1; + uint8_t shift = (2*idx); + uint8_t mask = (0x03 << shift); + lcd_putsiAtt(INDENT_WIDTH, y, STR_VSRCRAW, NUM_STICKS+idx+1, m_posHorz < 0 ? attr : 0); + if (ZEXIST(g_eeGeneral.anaNames[NUM_STICKS+idx]) || (attr && m_posHorz == 0)) + editName(HW_SETTINGS_COLUMN, y, g_eeGeneral.anaNames[NUM_STICKS+idx], LEN_ANA_NAME, event, attr && m_posHorz == 0); + else + lcd_putsiAtt(HW_SETTINGS_COLUMN, y, STR_MMMINV, 0, 0); + + uint8_t potType = (g_eeGeneral.potsType & mask) >> shift; + if (potType == POT_TYPE_NONE && k <= ITEM_SETUP_HW_POT2) + potType = POT_TYPE_DETENT; + potType = selectMenuItem(HW_SETTINGS_COLUMN+5*FW, y, "", STR_POTTYPES, potType, 0, POT_TYPE_MAX, m_posHorz == 1 ? attr : 0, event); + if (potType == POT_TYPE_DETENT && k <= ITEM_SETUP_HW_POT2) + potType = POT_TYPE_NONE; + g_eeGeneral.potsType &= ~mask; + g_eeGeneral.potsType |= (potType << shift); + break; + } + case ITEM_SETUP_HW_LABEL_SWITCHES: + lcd_putsLeft(y, "Switches"); + break; + case ITEM_SETUP_HW_SA: + case ITEM_SETUP_HW_SB: + case ITEM_SETUP_HW_SC: + case ITEM_SETUP_HW_SD: + case ITEM_SETUP_HW_SE: + case ITEM_SETUP_HW_SF: + case ITEM_SETUP_HW_SG: + case ITEM_SETUP_HW_SH: + case ITEM_SETUP_HW_SI: + case ITEM_SETUP_HW_SJ: + case ITEM_SETUP_HW_SK: + case ITEM_SETUP_HW_SL: + case ITEM_SETUP_HW_SM: + case ITEM_SETUP_HW_SN: +#if defined(REV9E) + case ITEM_SETUP_HW_SO: + case ITEM_SETUP_HW_SP: + case ITEM_SETUP_HW_SQ: + case ITEM_SETUP_HW_SR: +#endif + { + int index = k-ITEM_SETUP_HW_SA; + char label[] = INDENT "S*"; + label[2] = 'A' + index; + int config = SWITCH_CONFIG(index); + lcd_putsAtt(0, y, label, m_posHorz < 0 ? attr : 0); + if (ZEXIST(g_eeGeneral.switchNames[index]) || (attr && m_posHorz == 0)) + editName(HW_SETTINGS_COLUMN, y, g_eeGeneral.switchNames[index], LEN_SWITCH_NAME, event, m_posHorz == 0 ? attr : 0); + else + lcd_putsiAtt(HW_SETTINGS_COLUMN, y, STR_MMMINV, 0, 0); +#if defined(REV9E) + config = selectMenuItem(HW_SETTINGS_COLUMN+5*FW, y, "", "\007None\0 DefaultToggle\0""2POS\0 3POS\0", config, SWITCH_NONE, SWITCH_3POS, m_posHorz == 1 ? attr : 0, event); + if (attr && checkIncDec_Ret) { + uint32_t mask = 0x0f << (4*index); + TRACE("avant %x", g_eeGeneral.switchConfig); + g_eeGeneral.switchConfig = (g_eeGeneral.switchConfig & ~mask) | ((uint32_t(config)&0xf) << (4*index)); + TRACE("apres %x", g_eeGeneral.switchConfig); + } +#else + if (k <= ITEM_SETUP_HW_SH) { + config = selectMenuItem(HW_SETTINGS_COLUMN+5*FW, y, "", "\007DefaultToggle\0""2POS\0 3POS\0 2x2POS\0", config, SWITCH_NONE, SWITCH_2x2POS, m_posHorz == 1 ? attr : 0, event); + if (attr && checkIncDec_Ret) { + uint32_t mask = 0x0f << (4*index); + g_eeGeneral.switchConfig = (g_eeGeneral.switchConfig & ~mask) | (((uint32_t)(config)&0xf) << (4*index)); + } + } +#endif + break; + } + case ITEM_SETUP_HW_UART3_MODE: + g_eeGeneral.uart3Mode = selectMenuItem(HW_SETTINGS_COLUMN, y, STR_UART3MODE, STR_UART3MODES, g_eeGeneral.uart3Mode, 0, UART_MODE_MAX, attr, event); + if (attr && checkIncDec_Ret) { + uart3Init(g_eeGeneral.uart3Mode, MODEL_TELEMETRY_PROTOCOL()); + } + break; + } + } +} diff --git a/radio/src/gui/Taranis/menu_general_sdmanager.cpp b/radio/src/gui/Taranis/menu_general_sdmanager.cpp new file mode 100755 index 000000000..a26884c74 --- /dev/null +++ b/radio/src/gui/Taranis/menu_general_sdmanager.cpp @@ -0,0 +1,388 @@ +/* + * Authors (alphabetical order) + * - Andre Bernet + * - Andreas Weitl + * - Bertrand Songis + * - Bryan J. Rentoul (Gruvin) + * - Cameron Weeks + * - Erez Raviv + * - Gabriel Birkus + * - Jean-Pierre Parisy + * - Karl Szmutny + * - Michael Blandford + * - Michal Hlavinka + * - Pat Mackenzie + * - Philip Moss + * - Rob Thomson + * - Romolo Manfredini + * - Thomas Husterer + * + * opentx is based on code named + * gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/, + * er9x by Erez Raviv: http://code.google.com/p/er9x/, + * and the original (and ongoing) project by + * Thomas Husterer, th9x: http://code.google.com/p/th9x/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include "../../opentx.h" + +void menuGeneralSdManagerInfo(uint8_t event) +{ + SIMPLE_SUBMENU(STR_SD_INFO_TITLE, 1); + + lcd_putsLeft(2*FH, STR_SD_TYPE); + lcd_puts(10*FW, 2*FH, SD_IS_HC() ? STR_SDHC_CARD : STR_SD_CARD); + + lcd_putsLeft(3*FH, STR_SD_SIZE); + lcd_outdezAtt(10*FW, 3*FH, SD_GET_SIZE_MB(), LEFT); + lcd_putc(lcdLastPos, 3*FH, 'M'); + + lcd_putsLeft(4*FH, STR_SD_SECTORS); + lcd_outdezAtt(10*FW, 4*FH, SD_GET_BLOCKNR()/1000, LEFT); + lcd_putc(lcdLastPos, 4*FH, 'k'); + + lcd_putsLeft(5*FH, STR_SD_SPEED); + lcd_outdezAtt(10*FW, 5*FH, SD_GET_SPEED()/1000, LEFT); + lcd_puts(lcdLastPos, 5*FH, "kb/s"); +} + +inline bool isFilenameGreater(bool isfile, const char * fn, const char * line) +{ + return (isfile && !line[SD_SCREEN_FILE_LENGTH+1]) || (isfile==(bool)line[SD_SCREEN_FILE_LENGTH+1] && strcasecmp(fn, line) > 0); +} + +inline bool isFilenameLower(bool isfile, const char * fn, const char * line) +{ + return (!isfile && line[SD_SCREEN_FILE_LENGTH+1]) || (isfile==(bool)line[SD_SCREEN_FILE_LENGTH+1] && strcasecmp(fn, line) < 0); +} + +void flashBootloader(const char * filename) +{ + FIL file; + f_open(&file, filename, FA_READ); + uint8_t buffer[1024]; + UINT count; + + lcd_clear(); + lcd_putsLeft(4*FH, STR_WRITING); + lcd_rect(3, 6*FH+4, 204, 7); + lcdRefresh(); + + static uint8_t unlocked = 0; + if (!unlocked) { + unlocked = 1; + unlockFlash(); + } + + for (int i=0; i 0) + s_editMode = 0; + + switch(_event) { + case EVT_ENTRY: + f_chdir(ROOT_PATH); + reusableBuffer.sdmanager.offset = 65535; + break; + + case EVT_KEY_LONG(KEY_MENU): + if (!READ_ONLY()) { + killEvents(_event); + // MENU_ADD_ITEM(STR_SD_INFO); TODO: Implement + MENU_ADD_ITEM(STR_SD_FORMAT); + menuHandler = onSdManagerMenu; + } + break; + + case EVT_KEY_BREAK(KEY_ENTER): + { + if (m_posVert > 0) { + vertpos_t index = m_posVert-1-s_pgOfs; + if (!reusableBuffer.sdmanager.lines[index][SD_SCREEN_FILE_LENGTH+1]) { + f_chdir(reusableBuffer.sdmanager.lines[index]); + s_pgOfs = 0; + m_posVert = 1; + reusableBuffer.sdmanager.offset = 65535; + killEvents(_event); + break; + } + } + if (!IS_ROTARY_BREAK(_event) || m_posVert==0) + break; + // no break; + } + + case EVT_KEY_LONG(KEY_ENTER): + killEvents(_event); + { + uint8_t index = m_posVert-1-s_pgOfs; + // TODO duplicated code for finding extension + char * ext = reusableBuffer.sdmanager.lines[index]; + int len = strlen(ext) - 4; + ext += len; + /* TODO if (!strcasecmp(ext, MODELS_EXT)) { + s_menu[s_menu_count++] = STR_LOAD_FILE; + } + else */ if (!strcasecmp(ext, SOUNDS_EXT)) { + MENU_ADD_ITEM(STR_PLAY_FILE); + } + else if (!strcasecmp(ext, BITMAPS_EXT) && !READ_ONLY() && len <= (int)sizeof(g_model.header.bitmap)) { + MENU_ADD_ITEM(STR_ASSIGN_BITMAP); + } + else if (!strcasecmp(ext, TEXT_EXT)) { + MENU_ADD_ITEM(STR_VIEW_TEXT); + } + else if (!strcasecmp(ext, FIRMWARE_EXT) && !READ_ONLY()) { + MENU_ADD_ITEM(STR_FLASH_BOOTLOADER); + } +#if defined(LUA) + else if (!strcasecmp(ext, SCRIPTS_EXT)) { + MENU_ADD_ITEM(STR_EXECUTE_FILE); + } +#endif + if (!READ_ONLY()) { + MENU_ADD_ITEM(STR_DELETE_FILE); + // MENU_ADD_ITEM(STR_RENAME_FILE); TODO: Implement + // MENU_ADD_ITEM(STR_COPY_FILE); TODO: Implement + } + } + menuHandler = onSdManagerMenu; + break; + } + + if (reusableBuffer.sdmanager.offset != s_pgOfs) { + if (s_pgOfs == 0) { + reusableBuffer.sdmanager.offset = 0; + memset(reusableBuffer.sdmanager.lines, 0, sizeof(reusableBuffer.sdmanager.lines)); + } + else if (s_pgOfs == reusableBuffer.sdmanager.count-7) { + reusableBuffer.sdmanager.offset = s_pgOfs; + memset(reusableBuffer.sdmanager.lines, 0, sizeof(reusableBuffer.sdmanager.lines)); + } + else if (s_pgOfs > reusableBuffer.sdmanager.offset) { + memmove(reusableBuffer.sdmanager.lines[0], reusableBuffer.sdmanager.lines[1], 6*sizeof(reusableBuffer.sdmanager.lines[0])); + memset(reusableBuffer.sdmanager.lines[6], 0xff, SD_SCREEN_FILE_LENGTH); + reusableBuffer.sdmanager.lines[6][SD_SCREEN_FILE_LENGTH+1] = 1; + } + else { + memmove(reusableBuffer.sdmanager.lines[1], reusableBuffer.sdmanager.lines[0], 6*sizeof(reusableBuffer.sdmanager.lines[0])); + memset(reusableBuffer.sdmanager.lines[0], 0, sizeof(reusableBuffer.sdmanager.lines[0])); + } + + reusableBuffer.sdmanager.count = 0; + + FRESULT res = f_opendir(&dir, "."); /* Open the directory */ + if (res == FR_OK) { + for (;;) { + res = f_readdir(&dir, &fno); /* Read a directory item */ + if (res != FR_OK || fno.fname[0] == 0) break; /* Break on error or end of dir */ + if (fno.fname[0] == '.' && fno.fname[1] == '\0') continue; /* Ignore dot entry */ +#if _USE_LFN + fn = *fno.lfname ? fno.lfname : fno.fname; +#else + fn = fno.fname; +#endif + if (strlen(fn) > SD_SCREEN_FILE_LENGTH) continue; + + reusableBuffer.sdmanager.count++; + + bool isfile = !(fno.fattrib & AM_DIR); + + if (s_pgOfs == 0) { + for (uint8_t i=0; i=0; i--) { + char *line = reusableBuffer.sdmanager.lines[i]; + if (line[0] == '\0' || isFilenameGreater(isfile, fn, line)) { + if (i > 0) memmove(reusableBuffer.sdmanager.lines[0], reusableBuffer.sdmanager.lines[1], sizeof(reusableBuffer.sdmanager.lines[0]) * i); + memset(line, 0, sizeof(reusableBuffer.sdmanager.lines[i])); + strcpy(line, fn); + line[SD_SCREEN_FILE_LENGTH+1] = isfile; + break; + } + } + } + else if (s_pgOfs > reusableBuffer.sdmanager.offset) { + if (isFilenameGreater(isfile, fn, reusableBuffer.sdmanager.lines[5]) && isFilenameLower(isfile, fn, reusableBuffer.sdmanager.lines[6])) { + memset(reusableBuffer.sdmanager.lines[6], 0, sizeof(reusableBuffer.sdmanager.lines[0])); + strcpy(reusableBuffer.sdmanager.lines[6], fn); + reusableBuffer.sdmanager.lines[6][SD_SCREEN_FILE_LENGTH+1] = isfile; + } + } + else { + if (isFilenameLower(isfile, fn, reusableBuffer.sdmanager.lines[1]) && isFilenameGreater(isfile, fn, reusableBuffer.sdmanager.lines[0])) { + memset(reusableBuffer.sdmanager.lines[0], 0, sizeof(reusableBuffer.sdmanager.lines[0])); + strcpy(reusableBuffer.sdmanager.lines[0], fn); + reusableBuffer.sdmanager.lines[0][SD_SCREEN_FILE_LENGTH+1] = isfile; + } + } + } + } + } + + reusableBuffer.sdmanager.offset = s_pgOfs; + + for (uint8_t i=0; i 0) { + char * ext = reusableBuffer.sdmanager.lines[index]; + ext += strlen(ext) - 4; + if (!strcasecmp(ext, BITMAPS_EXT)) { + if (sdBitmapIdx != m_posVert) { + sdBitmapIdx = m_posVert; + uint8_t *dest = sdBitmap; + if (bmpLoad(dest, reusableBuffer.sdmanager.lines[index], MODEL_BITMAP_WIDTH, MODEL_BITMAP_HEIGHT)) { + memcpy(sdBitmap, logo_taranis, MODEL_BITMAP_SIZE); + } + } + lcd_bmp(22*FW+2, 2*FH+FH/2, sdBitmap); + } + } +} diff --git a/radio/src/gui/Taranis/menu_general_setup.cpp b/radio/src/gui/Taranis/menu_general_setup.cpp new file mode 100755 index 000000000..3ce1c9844 --- /dev/null +++ b/radio/src/gui/Taranis/menu_general_setup.cpp @@ -0,0 +1,518 @@ +/* + * Authors (alphabetical order) + * - Andre Bernet + * - Andreas Weitl + * - Bertrand Songis + * - Bryan J. Rentoul (Gruvin) + * - Cameron Weeks + * - Erez Raviv + * - Gabriel Birkus + * - Jean-Pierre Parisy + * - Karl Szmutny + * - Michael Blandford + * - Michal Hlavinka + * - Pat Mackenzie + * - Philip Moss + * - Rob Thomson + * - Romolo Manfredini + * - Thomas Husterer + * + * opentx is based on code named + * gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/, + * er9x by Erez Raviv: http://code.google.com/p/er9x/, + * and the original (and ongoing) project by + * Thomas Husterer, th9x: http://code.google.com/p/th9x/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include "../../opentx.h" + +const pm_uchar sticks[] PROGMEM = { +#include "../../bitmaps/sticks.lbm" +}; + +#define RADIO_SETUP_2ND_COLUMN (LCD_W-10*FW-MENUS_SCROLLBAR_WIDTH) +#define RADIO_SETUP_DATE_COLUMN RADIO_SETUP_2ND_COLUMN + 4*FWNUM +#define RADIO_SETUP_TIME_COLUMN RADIO_SETUP_2ND_COLUMN + 2*FWNUM + +#define SLIDER_5POS(y, value, label, event, attr) { \ + int8_t tmp = value; \ + displaySlider(RADIO_SETUP_2ND_COLUMN, y, 2+tmp, 4, attr); \ + value = selectMenuItem(RADIO_SETUP_2ND_COLUMN, y, label, NULL, tmp, -2, +2, attr, event); \ +} + +#if defined(SPLASH) && !defined(FSPLASH) + #define CASE_SPLASH_PARAM(x) x, +#else + #define CASE_SPLASH_PARAM(x) +#endif + +enum menuGeneralSetupItems { + CASE_RTCLOCK(ITEM_SETUP_DATE) + CASE_RTCLOCK(ITEM_SETUP_TIME) + ITEM_SETUP_BATT_RANGE, + ITEM_SETUP_SOUND_LABEL, + ITEM_SETUP_BEEP_MODE, + ITEM_SETUP_SPEAKER_VOLUME, + ITEM_SETUP_BEEP_VOLUME, + ITEM_SETUP_BEEP_LENGTH, + ITEM_SETUP_SPEAKER_PITCH, + ITEM_SETUP_WAV_VOLUME, + ITEM_SETUP_BACKGROUND_VOLUME, + CASE_VARIO_CPUARM(ITEM_SETUP_VARIO_LABEL) + CASE_VARIO_CPUARM(ITEM_SETUP_VARIO_VOLUME) + CASE_VARIO_CPUARM(ITEM_SETUP_VARIO_PITCH) + CASE_VARIO_CPUARM(ITEM_SETUP_VARIO_RANGE) + CASE_VARIO_CPUARM(ITEM_SETUP_VARIO_REPEAT) + CASE_HAPTIC(ITEM_SETUP_HAPTIC_LABEL) + CASE_HAPTIC(ITEM_SETUP_HAPTIC_MODE) + CASE_HAPTIC(ITEM_SETUP_HAPTIC_LENGTH) + CASE_HAPTIC(ITEM_SETUP_HAPTIC_STRENGTH) + ITEM_SETUP_CONTRAST, + ITEM_SETUP_ALARMS_LABEL, + ITEM_SETUP_BATTERY_WARNING, + ITEM_SETUP_INACTIVITY_ALARM, + ITEM_SETUP_MEMORY_WARNING, + ITEM_SETUP_ALARM_WARNING, + ITEM_SETUP_BACKLIGHT_LABEL, + ITEM_SETUP_BACKLIGHT_MODE, + ITEM_SETUP_BACKLIGHT_DELAY, + ITEM_SETUP_BRIGHTNESS, + CASE_REVPLUS(ITEM_SETUP_BACKLIGHT_COLOR) + ITEM_SETUP_FLASH_BEEP, + CASE_SPLASH_PARAM(ITEM_SETUP_DISABLE_SPLASH) + CASE_GPS(ITEM_SETUP_TIMEZONE) + CASE_GPS(ITEM_SETUP_GPSFORMAT) + CASE_PXX(ITEM_SETUP_COUNTRYCODE) + ITEM_SETUP_LANGUAGE, + ITEM_SETUP_IMPERIAL, + IF_FAI_CHOICE(ITEM_SETUP_FAI) + CASE_MAVLINK(ITEM_MAVLINK_BAUD) + ITEM_SETUP_SWITCHES_DELAY, + ITEM_SETUP_RX_CHANNEL_ORD, + ITEM_SETUP_STICK_MODE_LABELS, + ITEM_SETUP_STICK_MODE, + ITEM_SETUP_MAX +}; + +void menuGeneralSetup(uint8_t event) +{ +#if defined(RTCLOCK) + struct gtm t; + gettime(&t); + + if ((m_posVert==ITEM_SETUP_DATE+1 || m_posVert==ITEM_SETUP_TIME+1) && + (s_editMode>0) && + (event==EVT_KEY_FIRST(KEY_ENTER) || event==EVT_KEY_FIRST(KEY_EXIT) || IS_ROTARY_BREAK(event) || IS_ROTARY_LONG(event))) { + // set the date and time into RTC chip + rtcSetTime(&t); + } +#endif + +#if defined(FAI_CHOICE) + if (s_warning_result) { + s_warning_result = 0; + g_eeGeneral.fai = true; + eeDirty(EE_GENERAL); + } +#endif + + MENU(STR_MENURADIOSETUP, menuTabGeneral, e_Setup, ITEM_SETUP_MAX+1, { 0, 2, 2, 1, LABEL(SOUND), 0, 0, 0, 0, 0, 0, 0, CASE_VARIO_CPUARM(LABEL(VARIO)) CASE_VARIO_CPUARM(0) CASE_VARIO_CPUARM(0) CASE_VARIO_CPUARM(0) CASE_VARIO_CPUARM(0) CASE_HAPTIC(LABEL(HAPTIC)) CASE_HAPTIC(0) CASE_HAPTIC(0) CASE_HAPTIC(0) 0, LABEL(ALARMS), 0, 0, 0, 0, IF_ROTARY_ENCODERS(0) LABEL(BACKLIGHT), 0, 0, 0, CASE_REVPLUS(0) CASE_PWM_BACKLIGHT(0) CASE_PWM_BACKLIGHT(0) 0, CASE_SPLASH_PARAM(0) CASE_GPS(0) CASE_GPS(0) CASE_PXX(0) 0, 0, IF_FAI_CHOICE(0) CASE_MAVLINK(0) 0, 0, LABEL(TX_MODE), 0, 1/*to force edit mode*/ }); + + uint8_t sub = m_posVert - 1; + + for (unsigned int i=0; i0) ? BLINK|INVERS : INVERS); + uint8_t attr = (sub == k ? blink : 0); + + switch(k) { + case ITEM_SETUP_DATE: + lcd_putsLeft(y, STR_DATE); + lcd_putc(RADIO_SETUP_DATE_COLUMN, y, '-'); lcd_putc(RADIO_SETUP_DATE_COLUMN+3*FW-2, y, '-'); + for (uint8_t j=0; j<3; j++) { + uint8_t rowattr = (m_posHorz==j ? attr : 0); + switch (j) { + case 0: + lcd_outdezAtt(RADIO_SETUP_DATE_COLUMN, y, t.tm_year+1900, rowattr); + if (rowattr && (s_editMode>0 || p1valdiff)) t.tm_year = checkIncDec(event, t.tm_year, 112, 200, 0); + break; + case 1: + lcd_outdezNAtt(RADIO_SETUP_DATE_COLUMN+3*FW-2, y, t.tm_mon+1, rowattr|LEADING0, 2); + if (rowattr && (s_editMode>0 || p1valdiff)) t.tm_mon = checkIncDec(event, t.tm_mon, 0, 11, 0); + break; + case 2: + { + int16_t year = 1900 + t.tm_year; + int8_t dlim = (((((year%4==0) && (year%100!=0)) || (year%400==0)) && (t.tm_mon==1)) ? 1 : 0); + static const pm_uint8_t dmon[] PROGMEM = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; + dlim += pgm_read_byte(&dmon[t.tm_mon]); + lcd_outdezNAtt(RADIO_SETUP_DATE_COLUMN+6*FW-4, y, t.tm_mday, rowattr|LEADING0, 2); + if (rowattr && (s_editMode>0 || p1valdiff)) t.tm_mday = checkIncDec(event, t.tm_mday, 1, dlim, 0); + break; + } + } + } + if (attr && m_posHorz < 0) drawFilledRect(RADIO_SETUP_2ND_COLUMN, y, LCD_W-RADIO_SETUP_2ND_COLUMN-MENUS_SCROLLBAR_WIDTH, 8); + if (attr && checkIncDec_Ret) { + g_rtcTime = gmktime(&t); // update local timestamp and get wday calculated + } + break; + + case ITEM_SETUP_TIME: + lcd_putsLeft(y, STR_TIME); + lcd_putc(RADIO_SETUP_TIME_COLUMN+1, y, ':'); lcd_putc(RADIO_SETUP_TIME_COLUMN+3*FW-2, y, ':'); + for (uint8_t j=0; j<3; j++) { + uint8_t rowattr = (m_posHorz==j ? attr : 0); + switch (j) { + case 0: + lcd_outdezNAtt(RADIO_SETUP_TIME_COLUMN, y, t.tm_hour, rowattr|LEADING0, 2); + if (rowattr && (s_editMode>0 || p1valdiff)) t.tm_hour = checkIncDec(event, t.tm_hour, 0, 23, 0); + break; + case 1: + lcd_outdezNAtt(RADIO_SETUP_TIME_COLUMN+3*FWNUM, y, t.tm_min, rowattr|LEADING0, 2); + if (rowattr && (s_editMode>0 || p1valdiff)) t.tm_min = checkIncDec(event, t.tm_min, 0, 59, 0); + break; + case 2: + lcd_outdezNAtt(RADIO_SETUP_TIME_COLUMN+6*FWNUM, y, t.tm_sec, rowattr|LEADING0, 2); + if (rowattr && (s_editMode>0 || p1valdiff)) t.tm_sec = checkIncDec(event, t.tm_sec, 0, 59, 0); + break; + } + } + if (attr && m_posHorz < 0) drawFilledRect(RADIO_SETUP_2ND_COLUMN, y, LCD_W-RADIO_SETUP_2ND_COLUMN-MENUS_SCROLLBAR_WIDTH, 8); + if (attr && checkIncDec_Ret) + g_rtcTime = gmktime(&t); // update local timestamp and get wday calculated + break; + + case ITEM_SETUP_BATT_RANGE: + lcd_putsLeft(y, STR_BATTERY_RANGE); + putsVolts(RADIO_SETUP_2ND_COLUMN, y, 90+g_eeGeneral.vBatMin, (m_posHorz==0 ? attr : 0)|LEFT|NO_UNIT); + lcd_putc(lcdLastPos, y, '-'); + putsVolts(lcdLastPos+FW, y, 120+g_eeGeneral.vBatMax, (m_posHorz>0 ? attr : 0)|LEFT|NO_UNIT); + if (attr && m_posHorz < 0) drawFilledRect(RADIO_SETUP_2ND_COLUMN, y, LCD_W-RADIO_SETUP_2ND_COLUMN-MENUS_SCROLLBAR_WIDTH, 8); + if (attr && s_editMode>0) { + if (m_posHorz==0) + CHECK_INCDEC_GENVAR(event, g_eeGeneral.vBatMin, -50, g_eeGeneral.vBatMax+29); // min=4.0V + else + CHECK_INCDEC_GENVAR(event, g_eeGeneral.vBatMax, g_eeGeneral.vBatMin-29, +40); // max=16.0V + } + break; + + case ITEM_SETUP_SOUND_LABEL: + lcd_putsLeft(y, STR_SOUND_LABEL); + break; + + case ITEM_SETUP_BEEP_MODE: + g_eeGeneral.beepMode = selectMenuItem(RADIO_SETUP_2ND_COLUMN, y, STR_SPEAKER, STR_VBEEPMODE, g_eeGeneral.beepMode, -2, 1, attr, event); +#if defined(FRSKY) + if (attr && checkIncDec_Ret) frskySendAlarms(); +#endif + break; + + case ITEM_SETUP_SPEAKER_VOLUME: + { + lcd_putsLeft(y, STR_SPEAKER_VOLUME); + uint8_t b = g_eeGeneral.speakerVolume+VOLUME_LEVEL_DEF; + displaySlider(RADIO_SETUP_2ND_COLUMN, y, b, VOLUME_LEVEL_MAX, attr); + if (attr) { + CHECK_INCDEC_GENVAR(event, b, 0, VOLUME_LEVEL_MAX); + if (checkIncDec_Ret) { + g_eeGeneral.speakerVolume = (int8_t)b-VOLUME_LEVEL_DEF; + } + } + break; + } + + case ITEM_SETUP_BEEP_VOLUME: + SLIDER_5POS(y, g_eeGeneral.beepVolume, STR_BEEP_VOLUME, event, attr); + break; + case ITEM_SETUP_WAV_VOLUME: + SLIDER_5POS(y, g_eeGeneral.wavVolume, STR_WAV_VOLUME, event, attr); + break; + case ITEM_SETUP_BACKGROUND_VOLUME: + SLIDER_5POS(y, g_eeGeneral.backgroundVolume, STR_BG_VOLUME, event, attr); + break; + + case ITEM_SETUP_BEEP_LENGTH: + SLIDER_5POS(y, g_eeGeneral.beepLength, STR_BEEP_LENGTH, event, attr); + break; + + case ITEM_SETUP_SPEAKER_PITCH: + lcd_putsLeft( y, STR_SPKRPITCH); + lcd_putcAtt(RADIO_SETUP_2ND_COLUMN, y, '+', attr); + lcd_outdezAtt(RADIO_SETUP_2ND_COLUMN+FW, y, g_eeGeneral.speakerPitch*15, attr|LEFT); + lcd_putsAtt(lcdLastPos, y, "Hz", attr); + if (attr) { + CHECK_INCDEC_GENVAR(event, g_eeGeneral.speakerPitch, 0, 20); + } + break; + +#if defined(VARIO) + case ITEM_SETUP_VARIO_LABEL: + lcd_putsLeft(y, STR_VARIO); + break; + case ITEM_SETUP_VARIO_VOLUME: + SLIDER_5POS(y, g_eeGeneral.varioVolume, TR_SPEAKER_VOLUME, event, attr); + break; + case ITEM_SETUP_VARIO_PITCH: + lcd_putsLeft(y, STR_PITCH_AT_ZERO); + lcd_outdezAtt(RADIO_SETUP_2ND_COLUMN, y, VARIO_FREQUENCY_ZERO+(g_eeGeneral.varioPitch*10), attr|LEFT); + lcd_putsAtt(lcdLastPos, y, "Hz", attr); + if (attr) CHECK_INCDEC_GENVAR(event, g_eeGeneral.varioPitch, -40, 40); + break; + case ITEM_SETUP_VARIO_RANGE: + lcd_putsLeft(y, STR_PITCH_AT_MAX); + lcd_outdezAtt(RADIO_SETUP_2ND_COLUMN, y, VARIO_FREQUENCY_ZERO+(g_eeGeneral.varioPitch*10)+VARIO_FREQUENCY_RANGE+(g_eeGeneral.varioRange*10), attr|LEFT); + lcd_putsAtt(lcdLastPos, y, "Hz", attr); + if (attr) CHECK_INCDEC_GENVAR(event, g_eeGeneral.varioRange, -80, 80); + break; + case ITEM_SETUP_VARIO_REPEAT: + lcd_putsLeft(y, STR_REPEAT_AT_ZERO); + lcd_outdezAtt(RADIO_SETUP_2ND_COLUMN, y, VARIO_REPEAT_ZERO+(g_eeGeneral.varioRepeat*10), attr|LEFT); + lcd_putsAtt(lcdLastPos, y, STR_MS, attr); + if (attr) CHECK_INCDEC_GENVAR(event, g_eeGeneral.varioRepeat, -30, 50); + break; +#endif + +#if defined(HAPTIC) + case ITEM_SETUP_HAPTIC_LABEL: + lcd_putsLeft(y, STR_HAPTIC_LABEL); + break; + + case ITEM_SETUP_HAPTIC_MODE: + g_eeGeneral.hapticMode = selectMenuItem(RADIO_SETUP_2ND_COLUMN, y, STR_MODE, STR_VBEEPMODE, g_eeGeneral.hapticMode, -2, 1, attr, event); + break; + + case ITEM_SETUP_HAPTIC_LENGTH: + SLIDER_5POS(y, g_eeGeneral.hapticLength, STR_LENGTH, event, attr); + break; + + case ITEM_SETUP_HAPTIC_STRENGTH: + SLIDER_5POS(y, g_eeGeneral.hapticStrength, STR_HAPTICSTRENGTH, event, attr); + break; +#endif + + case ITEM_SETUP_CONTRAST: + lcd_putsLeft(y, STR_CONTRAST); + lcd_outdezAtt(RADIO_SETUP_2ND_COLUMN, y, g_eeGeneral.contrast, attr|LEFT); + if (attr) { + CHECK_INCDEC_GENVAR(event, g_eeGeneral.contrast, CONTRAST_MIN, CONTRAST_MAX); + lcdSetContrast(); + } + break; + + case ITEM_SETUP_ALARMS_LABEL: + lcd_putsLeft(y, STR_ALARMS_LABEL); + break; + + case ITEM_SETUP_BATTERY_WARNING: + lcd_putsLeft(y, STR_BATTERYWARNING); + putsVolts(RADIO_SETUP_2ND_COLUMN, y, g_eeGeneral.vBatWarn, attr|LEFT); + if(attr) CHECK_INCDEC_GENVAR(event, g_eeGeneral.vBatWarn, 40, 120); //4-12V + break; + + case ITEM_SETUP_MEMORY_WARNING: + { + uint8_t b = 1-g_eeGeneral.disableMemoryWarning; + g_eeGeneral.disableMemoryWarning = 1 - onoffMenuItem(b, RADIO_SETUP_2ND_COLUMN, y, STR_MEMORYWARNING, attr, event); + break; + } + + case ITEM_SETUP_ALARM_WARNING: + { + uint8_t b = 1-g_eeGeneral.disableAlarmWarning; + g_eeGeneral.disableAlarmWarning = 1 - onoffMenuItem(b, RADIO_SETUP_2ND_COLUMN, y, STR_ALARMWARNING, attr, event); + break; + } + +#if defined(PCBSKY9X) + case ITEM_SETUP_CAPACITY_WARNING: + lcd_putsLeft(y, STR_CAPAWARNING); + putsValueWithUnit(RADIO_SETUP_2ND_COLUMN, y, g_eeGeneral.mAhWarn*50, UNIT_MAH, attr|LEFT) ; + if(attr) CHECK_INCDEC_GENVAR(event, g_eeGeneral.mAhWarn, 0, 100); + break; +#endif + +#if defined(PCBSKY9X) + case ITEM_SETUP_TEMPERATURE_WARNING: + lcd_putsLeft(y, STR_TEMPWARNING); + putsValueWithUnit(RADIO_SETUP_2ND_COLUMN, y, g_eeGeneral.temperatureWarn, UNIT_TEMPERATURE, attr|LEFT) ; + if(attr) CHECK_INCDEC_GENVAR(event, g_eeGeneral.temperatureWarn, 0, 120); // 0 means no alarm + break; +#endif + + case ITEM_SETUP_INACTIVITY_ALARM: + lcd_putsLeft( y,STR_INACTIVITYALARM); + lcd_outdezAtt(RADIO_SETUP_2ND_COLUMN, y, g_eeGeneral.inactivityTimer, attr|LEFT); + lcd_putc(lcdLastPos, y, 'm'); + if(attr) g_eeGeneral.inactivityTimer = checkIncDec(event, g_eeGeneral.inactivityTimer, 0, 250, EE_GENERAL); //0..250minutes + break; + + case ITEM_SETUP_BACKLIGHT_LABEL: + lcd_putsLeft(y, STR_BACKLIGHT_LABEL); + break; + + case ITEM_SETUP_BACKLIGHT_MODE: + g_eeGeneral.backlightMode = selectMenuItem(RADIO_SETUP_2ND_COLUMN, y, STR_MODE, STR_VBLMODE, g_eeGeneral.backlightMode, e_backlight_mode_off, e_backlight_mode_on, attr, event); + break; + + case ITEM_SETUP_FLASH_BEEP: + g_eeGeneral.alarmsFlash = onoffMenuItem(g_eeGeneral.alarmsFlash, RADIO_SETUP_2ND_COLUMN, y, STR_ALARM, attr, event ) ; + break; + + case ITEM_SETUP_BACKLIGHT_DELAY: + lcd_putsLeft(y, STR_BLDELAY); + lcd_outdezAtt(RADIO_SETUP_2ND_COLUMN, y, g_eeGeneral.lightAutoOff*5, attr|LEFT); + lcd_putc(lcdLastPos, y, 's'); + if (attr) CHECK_INCDEC_GENVAR(event, g_eeGeneral.lightAutoOff, 0, 600/5); + break; + + case ITEM_SETUP_BRIGHTNESS: + lcd_putsLeft(y, STR_BRIGHTNESS); + lcd_outdezAtt(RADIO_SETUP_2ND_COLUMN, y, 100-g_eeGeneral.backlightBright, attr|LEFT) ; + if (attr) { + uint8_t b = 100 - g_eeGeneral.backlightBright; + CHECK_INCDEC_GENVAR(event, b, 0, 100); + g_eeGeneral.backlightBright = 100 - b; + } + break; + +#if defined(REVPLUS) + case ITEM_SETUP_BACKLIGHT_COLOR: + lcd_putsLeft(y, STR_BLCOLOR); + displaySlider(RADIO_SETUP_2ND_COLUMN, y, g_eeGeneral.backlightColor, 20, attr); + if (attr) g_eeGeneral.backlightColor = checkIncDec(event, g_eeGeneral.backlightColor, 0, 20, EE_GENERAL | NO_INCDEC_MARKS); + break; +#endif + +#if defined(SPLASH) && !defined(FSPLASH) + case ITEM_SETUP_DISABLE_SPLASH: + { + lcd_putsLeft(y, STR_SPLASHSCREEN); + if (SPLASH_NEEDED()) { + lcd_outdezAtt(RADIO_SETUP_2ND_COLUMN, y, SPLASH_TIMEOUT/100, attr|LEFT); + lcd_putc(lcdLastPos, y, 's'); + } + else { + lcd_putsiAtt(RADIO_SETUP_2ND_COLUMN, y, STR_MMMINV, 0, attr); // TODO define + } + if (attr) g_eeGeneral.splashMode = -checkIncDecGen(event, -g_eeGeneral.splashMode, -3, 4); + break; + } +#endif + +#if defined(FRSKY) && defined(FRSKY_HUB) && defined(GPS) + case ITEM_SETUP_TIMEZONE: + lcd_putsLeft(y, STR_TIMEZONE); + lcd_outdezAtt(RADIO_SETUP_2ND_COLUMN, y, g_eeGeneral.timezone, attr|LEFT); + if (attr) CHECK_INCDEC_GENVAR(event, g_eeGeneral.timezone, -12, 12); + break; + + case ITEM_SETUP_GPSFORMAT: + g_eeGeneral.gpsFormat = selectMenuItem(RADIO_SETUP_2ND_COLUMN, y, STR_GPSCOORD, STR_GPSFORMAT, g_eeGeneral.gpsFormat, 0, 1, attr, event); + break; +#endif + +#if defined(PXX) + case ITEM_SETUP_COUNTRYCODE: + g_eeGeneral.countryCode = selectMenuItem(RADIO_SETUP_2ND_COLUMN, y, STR_COUNTRYCODE, STR_COUNTRYCODES, g_eeGeneral.countryCode, 0, 2, attr, event); + break; +#endif + + case ITEM_SETUP_LANGUAGE: + lcd_putsLeft(y, STR_VOICELANG); + lcd_putsAtt(RADIO_SETUP_2ND_COLUMN, y, currentLanguagePack->name, attr); + if (attr) { + currentLanguagePackIdx = checkIncDec(event, currentLanguagePackIdx, 0, DIM(languagePacks)-2, EE_GENERAL); + if (checkIncDec_Ret) { + currentLanguagePack = languagePacks[currentLanguagePackIdx]; + strncpy(g_eeGeneral.ttsLanguage, currentLanguagePack->id, 2); + } + } + break; + + case ITEM_SETUP_IMPERIAL: + g_eeGeneral.imperial = selectMenuItem(RADIO_SETUP_2ND_COLUMN, y, STR_UNITSSYSTEM, STR_VUNITSSYSTEM, g_eeGeneral.imperial, 0, 1, attr, event); + break; + +#if defined(FAI_CHOICE) + case ITEM_SETUP_FAI: + onoffMenuItem(g_eeGeneral.fai, RADIO_SETUP_2ND_COLUMN, y, PSTR("FAI Mode"), attr, event); + if (attr && checkIncDec_Ret) { + if (g_eeGeneral.fai) + POPUP_WARNING(PSTR("FAI\001mode blocked!")); + else + POPUP_CONFIRMATION(PSTR("FAI mode?")); + } + break; +#endif + +#if defined(MAVLINK) + case ITEM_MAVLINK_BAUD: + g_eeGeneral.mavbaud = selectMenuItem(RADIO_SETUP_2ND_COLUMN, y, STR_MAVLINK_BAUD_LABEL, STR_MAVLINK_BAUDS, g_eeGeneral.mavbaud, 0, 7, attr, event); + break; +#endif + + case ITEM_SETUP_SWITCHES_DELAY: + lcd_putsLeft(y, STR_SWITCHES_DELAY); + lcd_outdezAtt(RADIO_SETUP_2ND_COLUMN, y, 10*SWITCHES_DELAY(), attr|LEFT); + lcd_putsAtt(lcdLastPos, y, STR_MS, attr); + if (attr) CHECK_INCDEC_GENVAR(event, g_eeGeneral.switchesDelay, -15, +15); + break; + + case ITEM_SETUP_RX_CHANNEL_ORD: + lcd_putsLeft(y, STR_RXCHANNELORD); // RAET->AETR + for (uint8_t i=1; i<=4; i++) { + putsChnLetter(RADIO_SETUP_2ND_COLUMN - FW + i*FW, y, channel_order(i), attr); + } + if (attr) CHECK_INCDEC_GENVAR(event, g_eeGeneral.templateSetup, 0, 23); + break; + + case ITEM_SETUP_STICK_MODE_LABELS: + lcd_putsLeft(y, NO_INDENT(STR_MODE)); + for (uint8_t i=0; i<4; i++) { + lcd_img((6+4*i)*FW, y, sticks, i, 0); +#if defined(FRSKY_STICKS) + if (g_eeGeneral.stickReverse & (1<0) { + CHECK_INCDEC_GENVAR(event, g_eeGeneral.stickMode, 0, 3); + } + else if (stickMode != g_eeGeneral.stickMode) { + pausePulses(); + stickMode = g_eeGeneral.stickMode; + checkTHR(); + resumePulses(); + clearKeyEvents(); + } + break; + } + } +} diff --git a/radio/src/gui/Taranis/menu_general_trainer.cpp b/radio/src/gui/Taranis/menu_general_trainer.cpp new file mode 100755 index 000000000..7cfb8d9f9 --- /dev/null +++ b/radio/src/gui/Taranis/menu_general_trainer.cpp @@ -0,0 +1,114 @@ +/* + * Authors (alphabetical order) + * - Andre Bernet + * - Andreas Weitl + * - Bertrand Songis + * - Bryan J. Rentoul (Gruvin) + * - Cameron Weeks + * - Erez Raviv + * - Gabriel Birkus + * - Jean-Pierre Parisy + * - Karl Szmutny + * - Michael Blandford + * - Michal Hlavinka + * - Pat Mackenzie + * - Philip Moss + * - Rob Thomson + * - Romolo Manfredini + * - Thomas Husterer + * + * opentx is based on code named + * gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/, + * er9x by Erez Raviv: http://code.google.com/p/er9x/, + * and the original (and ongoing) project by + * Thomas Husterer, th9x: http://code.google.com/p/th9x/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include "../../opentx.h" + +#define TRAINER_CALIB_POS 12 + +void menuGeneralTrainer(uint8_t event) +{ + uint8_t y; + bool slave = SLAVE_MODE(); + + MENU(STR_MENUTRAINER, menuTabGeneral, e_Trainer, (slave ? 1 : 7), {0, 2, 2, 2, 2, 0/*, 0*/}); + + if (slave) { + lcd_puts(7*FW, 4*FH, STR_SLAVE); + } + else { + uint8_t attr; + uint8_t blink = ((s_editMode>0) ? BLINK|INVERS : INVERS); + + lcd_puts(3*FW, MENU_TITLE_HEIGHT+1, STR_MODESRC); + + y = MENU_TITLE_HEIGHT + 1 + FH; + + for (uint8_t i=1; i<=NUM_STICKS; i++) { + uint8_t chan = channel_order(i); + volatile TrainerMix *td = &g_eeGeneral.trainer.mix[chan-1]; + + putsMixerSource(0, y, MIXSRC_Rud-1+chan, (m_posVert==i && CURSOR_ON_LINE()) ? INVERS : 0); + + for (uint8_t j=0; j<3; j++) { + + attr = ((m_posVert==i && m_posHorz==j) ? blink : 0); + + switch(j) { + case 0: + lcd_putsiAtt(4*FW, y, STR_TRNMODE, td->mode, attr); + if (attr&BLINK) CHECK_INCDEC_GENVAR(event, td->mode, 0, 2); + break; + + case 1: + lcd_outdezAtt(11*FW, y, td->studWeight, attr); + if (attr&BLINK) CHECK_INCDEC_GENVAR(event, td->studWeight, -125, 125); + break; + + case 2: + lcd_putsiAtt(12*FW, y, STR_TRNCHN, td->srcChn, attr); + if (attr&BLINK) CHECK_INCDEC_GENVAR(event, td->srcChn, 0, 3); + break; + } + } + y += FH; + } + + attr = (m_posVert==5) ? blink : 0; + lcd_putsLeft(MENU_TITLE_HEIGHT+1+5*FH, STR_MULTIPLIER); + lcd_outdezAtt(LEN_MULTIPLIER*FW+3*FW, MENU_TITLE_HEIGHT+1+5*FH, g_eeGeneral.PPM_Multiplier+10, attr|PREC1); + if (attr) CHECK_INCDEC_GENVAR(event, g_eeGeneral.PPM_Multiplier, -10, 40); + + attr = (m_posVert==6) ? INVERS : 0; + if (attr) s_editMode = 0; + lcd_putsAtt(0*FW, MENU_TITLE_HEIGHT+1+6*FH, STR_CAL, attr); + for (uint8_t i=0; i<4; i++) { + uint8_t x = (i*TRAINER_CALIB_POS+16)*FW/2; +#if defined (PPM_UNIT_PERCENT_PREC1) + lcd_outdezAtt(x, MENU_TITLE_HEIGHT+1+6*FH, (g_ppmIns[i]-g_eeGeneral.trainer.calib[i])*2, PREC1); +#else + lcd_outdezAtt(x, MENU_TITLE_HEIGHT+1+6*FH, (g_ppmIns[i]-g_eeGeneral.trainer.calib[i])/5, 0); +#endif + } + + if (attr) { + if (event==EVT_KEY_LONG(KEY_ENTER)){ + memcpy(g_eeGeneral.trainer.calib, g_ppmIns, sizeof(g_eeGeneral.trainer.calib)); + eeDirty(EE_GENERAL); + AUDIO_WARNING1(); + } + } + } +} diff --git a/radio/src/gui/Taranis/menu_general_version.cpp b/radio/src/gui/Taranis/menu_general_version.cpp new file mode 100755 index 000000000..03ab5d183 --- /dev/null +++ b/radio/src/gui/Taranis/menu_general_version.cpp @@ -0,0 +1,104 @@ +/* + * Authors (alphabetical order) + * - Andre Bernet + * - Andreas Weitl + * - Bertrand Songis + * - Bryan J. Rentoul (Gruvin) + * - Cameron Weeks + * - Erez Raviv + * - Gabriel Birkus + * - Jean-Pierre Parisy + * - Karl Szmutny + * - Michael Blandford + * - Michal Hlavinka + * - Pat Mackenzie + * - Philip Moss + * - Rob Thomson + * - Romolo Manfredini + * - Thomas Husterer + * + * opentx is based on code named + * gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/, + * er9x by Erez Raviv: http://code.google.com/p/er9x/, + * and the original (and ongoing) project by + * Thomas Husterer, th9x: http://code.google.com/p/th9x/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include "../../opentx.h" + +void backupEeprom() +{ + char filename[60]; + uint8_t buffer[1024]; + FIL file; + + lcd_clear(); + lcd_putsLeft(4*FH, STR_WRITING); + lcd_rect(3, 6*FH+4, 204, 7); + lcdRefresh(); + + //reset unexpectedShutdown to prevent warning when user restores EEPROM backup + g_eeGeneral.unexpectedShutdown = 0; + eeDirty(EE_GENERAL); + eeCheck(true); + + // create the directory if needed... + DIR folder; + FRESULT result = f_opendir(&folder, EEPROMS_PATH); + if (result != FR_OK) { + if (result == FR_NO_PATH) + result = f_mkdir(EEPROMS_PATH); + if (result != FR_OK) { + POPUP_WARNING(SDCARD_ERROR(result)); + return; + } + } + + // prepare the filename... + char * tmp = strAppend(filename, EEPROMS_PATH "/eeprom"); + tmp = strAppendDate(tmp, true); + strAppend(tmp, EEPROM_EXT); + + // open the file for writing... + f_open(&file, filename, FA_WRITE | FA_CREATE_ALWAYS); + + for (int i=0; i + * - Andreas Weitl + * - Bertrand Songis + * - Bryan J. Rentoul (Gruvin) + * - Cameron Weeks + * - Erez Raviv + * - Gabriel Birkus + * - Jean-Pierre Parisy + * - Karl Szmutny + * - Michael Blandford + * - Michal Hlavinka + * - Pat Mackenzie + * - Philip Moss + * - Rob Thomson + * - Romolo Manfredini + * - Thomas Husterer + * + * opentx is based on code named + * gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/, + * er9x by Erez Raviv: http://code.google.com/p/er9x/, + * and the original (and ongoing) project by + * Thomas Husterer, th9x: http://code.google.com/p/th9x/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include "../../opentx.h" + +vertpos_t s_pgOfs; +vertpos_t m_posVert; +horzpos_t m_posHorz; +int8_t s_editMode; +uint8_t s_noHi; +uint8_t calibrationState; + +#if defined(AUTOSWITCH) +int8_t checkIncDecMovedSwitch(int8_t val) +{ + if (s_editMode>0) { + int8_t swtch = getMovedSwitch(); + if (swtch) { + div_t info = switchInfo(swtch); + if (IS_TOGGLE(info.quot)) { + if (info.rem != 0) { + val = (val == swtch ? swtch+2 : swtch); + } + } + else { + val = swtch; + } + } + } + return val; +} +#endif + +int8_t checkIncDec_Ret; + +INIT_STOPS(stops100, 3, -100, 0, 100) +INIT_STOPS(stops1000, 3, -1000, 0, 1000) +INIT_STOPS(stopsSwitch, 15, SWSRC_FIRST, CATEGORY_END(-SWSRC_FIRST_LOGICAL_SWITCH), CATEGORY_END(-SWSRC_FIRST_TRIM), CATEGORY_END(-SWSRC_LAST_SWITCH+1), 0, CATEGORY_END(SWSRC_LAST_SWITCH), CATEGORY_END(SWSRC_FIRST_TRIM-1), CATEGORY_END(SWSRC_FIRST_LOGICAL_SWITCH-1), SWSRC_LAST) + +int checkIncDec(unsigned int event, int val, int i_min, int i_max, unsigned int i_flags, IsValueAvailable isValueAvailable, const CheckIncDecStops &stops) +{ + int newval = val; + +#if defined(DBLKEYS) + unsigned int in = KEYS_PRESSED(); + if (!(i_flags & NO_DBLKEYS) && (EVT_KEY_MASK(event))) { + bool dblkey = true; + if (DBLKEYS_PRESSED_RGT_LFT(in)) { + if (!isValueAvailable || isValueAvailable(-val)) + newval = -val; + } + else if (DBLKEYS_PRESSED_RGT_UP(in)) { + newval = (i_max > stops.max() ? stops.max() : i_max); + while (isValueAvailable && !isValueAvailable(newval) && newval>i_min) { + --newval; + } + } + else if (DBLKEYS_PRESSED_LFT_DWN(in)) { + newval = (i_min < stops.min() ? stops.min() : i_min); + while (isValueAvailable && !isValueAvailable(newval) && newval0 && (IS_ROTARY_RIGHT(event) || event==EVT_KEY_FIRST(KEY_UP) || event==EVT_KEY_REPT(KEY_UP))) { + do { + if (IS_KEY_REPT(event) && (i_flags & INCDEC_REP10)) { + newval += min(10, i_max-val); + } + else { + newval++; + } + } while (isValueAvailable && !isValueAvailable(newval) && newval<=i_max); + + if (newval > i_max) { + newval = val; + killEvents(event); + AUDIO_WARNING2(); + } + else { + AUDIO_KEYPAD_UP(); + } + } + else if (s_editMode>0 && (IS_ROTARY_LEFT(event) || event==EVT_KEY_FIRST(KEY_DOWN) || event==EVT_KEY_REPT(KEY_DOWN))) { + do { + if (IS_KEY_REPT(event) && (i_flags & INCDEC_REP10)) { + newval -= min(10, val-i_min); + } + else { + newval--; + } + } while (isValueAvailable && !isValueAvailable(newval) && newval>=i_min); + + if (newval < i_min) { + newval = val; + killEvents(event); + AUDIO_WARNING2(); + } + else { + AUDIO_KEYPAD_DOWN(); + } + } + + if (!READ_ONLY() && i_min==0 && i_max==1 && (event==EVT_KEY_BREAK(KEY_ENTER) || IS_ROTARY_BREAK(event))) { + s_editMode = 0; + newval = !val; + } + +#if defined(AUTOSWITCH) + if (i_flags & INCDEC_SWITCH) { + newval = checkIncDecMovedSwitch(newval); + } +#endif + +#if defined(AUTOSOURCE) + if (i_flags & INCDEC_SOURCE) { + if (s_editMode>0) { + int source = GET_MOVED_SOURCE(i_min, i_max); + if (source) { + newval = source; + } +#if defined(AUTOSWITCH) + else { + unsigned int swtch = abs(getMovedSwitch()); + if (swtch) { + newval = switchToMix(swtch); + } + } +#endif + } + } +#endif + + if (newval > i_max || newval < i_min) { + newval = (newval > i_max ? i_max : i_min); + killEvents(event); + AUDIO_WARNING2(); + } + + if (newval != val) { + if (!(i_flags & NO_INCDEC_MARKS) && (newval != i_max) && (newval != i_min) && stops.contains(newval) && !IS_ROTARY_EVENT(event)) { + bool pause = (newval > val ? !stops.contains(newval+1) : !stops.contains(newval-1)); + if (pause) { + pauseEvents(event); // delay before auto-repeat continues + if (newval>val) // without AUDIO it's optimized, because the 2 sounds are the same + AUDIO_KEYPAD_UP(); + else + AUDIO_KEYPAD_DOWN(); + } + } + eeDirty(i_flags & (EE_GENERAL|EE_MODEL)); + checkIncDec_Ret = (newval > val ? 1 : -1); + } + else { + checkIncDec_Ret = 0; + } + return newval; +} + +#define CURSOR_NOT_ALLOWED_IN_ROW(row) ((int8_t)MAXCOL(row) < 0) +#define MAXCOL_RAW(row) (horTab ? pgm_read_byte(horTab+min(row, (vertpos_t)horTabMax)) : (const uint8_t)0) +#define MAXCOL(row) (MAXCOL_RAW(row) >= HIDDEN_ROW ? MAXCOL_RAW(row) : (const uint8_t)(MAXCOL_RAW(row) & (~NAVIGATION_LINE_BY_LINE))) +#define COLATTR(row) (MAXCOL_RAW(row) == (uint8_t)-1 ? (const uint8_t)0 : (const uint8_t)(MAXCOL_RAW(row) & NAVIGATION_LINE_BY_LINE)) +#define INC(val, min, max) if (valmin) {val--;} else {val=max;} + +coord_t scrollbar_X = DEFAULT_SCROLLBAR_X; + +void onLongMenuPress(const char *result) +{ + if (result == STR_VIEW_CHANNELS) { + pushMenu(menuChannelsView); + } + else if (result == STR_VIEW_NOTES) { + pushModelNotes(); + } +} + +tmr10ms_t menuEntryTime; + +void check(check_event_t event, uint8_t curr, const MenuFuncP *menuTab, uint8_t menuTabSize, const pm_uint8_t *horTab, uint8_t horTabMax, vertpos_t maxrow, uint8_t flags) +{ + vertpos_t l_posVert = m_posVert; + horzpos_t l_posHorz = m_posHorz; + + uint8_t maxcol = MAXCOL(l_posVert); + + if (p2valdiff || 0 || p1valdiff) backlightOn(); // on keypress turn the light on + + if (menuTab) { + int8_t cc = curr; + switch (event) { + case EVT_KEY_LONG(KEY_MENU): + if (menuTab == menuTabModel) { + killEvents(event); + if (modelHasNotes()) { + MENU_ADD_SD_ITEM(STR_VIEW_CHANNELS); + MENU_ADD_ITEM(STR_VIEW_NOTES); + menuHandler = onLongMenuPress; + } + else { + pushMenu(menuChannelsView); + } + } + break; + + case EVT_KEY_LONG(KEY_PAGE): + if (curr > 0) + cc = curr - 1; + else + cc = menuTabSize-1; + killEvents(event); + break; + + case EVT_KEY_BREAK(KEY_PAGE): + if (curr < (menuTabSize-1)) + cc = curr + 1; + else + cc = 0; + break; + } + + if (!calibrationState && cc != curr) { + chainMenu((MenuFuncP)pgm_read_adr(&menuTab[cc])); + } + + if (!(flags&CHECK_FLAG_NO_SCREEN_INDEX)) { + displayScreenIndex(curr, menuTabSize, 0); + } + + drawFilledRect(0, 0, LCD_W, MENU_TITLE_HEIGHT, SOLID, FILL_WHITE|GREY_DEFAULT); + } + + DISPLAY_PROGRESS_BAR(menuTab ? lcdLastPos-2*FW-((curr+1)/10*FWNUM)-2 : 20*FW+1); + + if (s_editMode<=0) { + if (0) { + l_posVert = limit((int8_t)0, (int8_t)(l_posVert - 0), (int8_t)maxrow); + l_posHorz = min((uint8_t)l_posHorz, MAXCOL(l_posVert)); + } + + if (p2valdiff && l_posVert>0) { + l_posHorz = limit((int8_t)0, (int8_t)((uint8_t)l_posHorz - p2valdiff), (int8_t)maxcol); + } + } + + switch(event) + { + case EVT_ENTRY: + menuEntryTime = get_tmr10ms(); + l_posVert = POS_VERT_INIT; + l_posHorz = POS_HORZ_INIT(l_posVert); + SET_SCROLLBAR_X(LCD_W-1); + s_editMode = EDIT_MODE_INIT; + break; + + case EVT_ENTRY_UP: + menuEntryTime = get_tmr10ms(); + s_editMode = 0; + l_posHorz = POS_HORZ_INIT(l_posVert); + SET_SCROLLBAR_X(LCD_W-1); + break; + + case EVT_ROTARY_BREAK: + if (s_editMode > 1) break; + if (m_posHorz < 0 && maxcol > 0 && READ_ONLY_UNLOCKED()) { + l_posHorz = 0; + break; + } + if (!menuTab || l_posVert>0) { + if (READ_ONLY_UNLOCKED()) { + s_editMode = (s_editMode<=0); + } + } + break; + + case EVT_KEY_LONG(KEY_EXIT): + s_editMode = 0; // TODO needed? we call ENTRY_UP after which does the same + popMenu(); + break; + + case EVT_KEY_BREAK(KEY_EXIT): + if (s_editMode>0) { + s_editMode = 0; + break; + } + + if (l_posHorz >= 0 && (COLATTR(l_posVert) & NAVIGATION_LINE_BY_LINE)) { + l_posHorz = -1; + } + else + { + uint8_t posVertInit = POS_VERT_INIT; + if (s_pgOfs != 0 || l_posVert != posVertInit) { + s_pgOfs = 0; + l_posVert = posVertInit; + l_posHorz = POS_HORZ_INIT(l_posVert); + } + else { + popMenu(); + } + } + break; + + CASE_EVT_ROTARY_MOVE_RIGHT + if (s_editMode != 0) break; + if ((COLATTR(l_posVert) & NAVIGATION_LINE_BY_LINE)) { + if (l_posHorz >= 0) { + INC(l_posHorz, 0, maxcol); + break; + } + } + else { + if (l_posHorz < maxcol) { + l_posHorz++; + break; + } + else { + l_posHorz = 0; + if (!IS_ROTARY_MOVE_RIGHT(event)) + break; + } + } + + do { + INC(l_posVert, POS_VERT_INIT, maxrow); + } while (CURSOR_NOT_ALLOWED_IN_ROW(l_posVert)); + + s_editMode = 0; // if we go down, we must be in this mode + + l_posHorz = POS_HORZ_INIT(l_posVert); + break; + + CASE_EVT_ROTARY_MOVE_LEFT + if (s_editMode != 0) break; + if ((COLATTR(l_posVert) & NAVIGATION_LINE_BY_LINE)) { + if (l_posHorz >= 0) { + DEC(l_posHorz, 0, maxcol); + break; + } + } + else { + if (l_posHorz > 0) { + l_posHorz--; + break; + } + else if (IS_ROTARY_MOVE_LEFT(event) && s_editMode == 0) { + l_posHorz = 0xff; + } + else { + l_posHorz = maxcol; + break; + } + } + + do { + DEC(l_posVert, POS_VERT_INIT, maxrow); + } while (CURSOR_NOT_ALLOWED_IN_ROW(l_posVert)); + + s_editMode = 0; // if we go up, we must be in this mode + + if ((COLATTR(l_posVert) & NAVIGATION_LINE_BY_LINE)) + l_posHorz = -1; + else + l_posHorz = min((uint8_t)l_posHorz, MAXCOL(l_posVert)); + + break; + } + + if (l_posVert == 0 || (l_posVert==2 && MAXCOL(vertpos_t(1)) >= HIDDEN_ROW) || (l_posVert==3 && MAXCOL(vertpos_t(1)) >= HIDDEN_ROW && MAXCOL(vertpos_t(2)) >= HIDDEN_ROW)) { + s_pgOfs = 0; + } + else if (horTab) { + uint8_t max = menuTab ? NUM_BODY_LINES : NUM_BODY_LINES-1; + if (maxrow > max) { + while (1) { + vertpos_t firstLine = 0; + for (int numLines=0; firstLine<=maxrow && numLines lastLine) { + s_pgOfs++; + } + else { + break; + } + } + } + } + } + else { + uint8_t max = menuTab ? NUM_BODY_LINES : NUM_BODY_LINES-1; + if (l_posVert>max+s_pgOfs) { + s_pgOfs = l_posVert-max; + } + else if (l_posVert<1+s_pgOfs) { + s_pgOfs = l_posVert-1; + } + } + + if (maxrow > NUM_BODY_LINES && scrollbar_X) { + displayScrollbar(scrollbar_X, MENU_TITLE_HEIGHT, LCD_H-MENU_TITLE_HEIGHT-MENU_NAVIG_HEIGHT, s_pgOfs, menuTab ? maxrow : maxrow+1, NUM_BODY_LINES); + } + + m_posVert = l_posVert; + m_posHorz = l_posHorz; +} + + +void check_simple(check_event_t event, uint8_t curr, const MenuFuncP *menuTab, uint8_t menuTabSize, vertpos_t maxrow) +{ + check(event, curr, menuTab, menuTabSize, 0, 0, maxrow); +} + +void check_submenu_simple(check_event_t event, uint8_t maxrow) +{ + check_simple(event, 0, 0, 0, maxrow); +} + +void repeatLastCursorMove(uint8_t event) +{ + if (CURSOR_MOVED_LEFT(event) || CURSOR_MOVED_RIGHT(event)) { + putEvent(event); + } + else { + m_posHorz = 0; + } +} diff --git a/radio/src/gui/Taranis/popups.cpp b/radio/src/gui/Taranis/popups.cpp new file mode 100755 index 000000000..5614149b8 --- /dev/null +++ b/radio/src/gui/Taranis/popups.cpp @@ -0,0 +1,166 @@ +/* + * Authors (alphabetical order) + * - Andre Bernet + * - Andreas Weitl + * - Bertrand Songis + * - Bryan J. Rentoul (Gruvin) + * - Cameron Weeks + * - Erez Raviv + * - Gabriel Birkus + * - Jean-Pierre Parisy + * - Karl Szmutny + * - Michael Blandford + * - Michal Hlavinka + * - Pat Mackenzie + * - Philip Moss + * - Rob Thomson + * - Romolo Manfredini + * - Thomas Husterer + * + * opentx is based on code named + * gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/, + * er9x by Erez Raviv: http://code.google.com/p/er9x/, + * and the original (and ongoing) project by + * Thomas Husterer, th9x: http://code.google.com/p/th9x/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include "../../opentx.h" + +const char *s_warning = NULL; +const char *s_warning_info; +uint8_t s_warning_info_len; +uint8_t s_warning_type; +uint8_t s_warning_result = 0; +uint8_t s_warning_info_flags = ZCHAR; +int16_t s_warning_input_value; +int16_t s_warning_input_min; +int16_t s_warning_input_max; +void (*popupFunc)(uint8_t event) = NULL; +const char *s_menu[MENU_MAX_LINES]; +uint8_t s_menu_item = 0; +uint16_t s_menu_count = 0; +uint8_t s_menu_flags = 0; +uint16_t s_menu_offset = 0; +void (*menuHandler)(const char *result); + +void displayBox() +{ + drawFilledRect(10, 16, LCD_W-20, 40, SOLID, ERASE); + lcd_rect(10, 16, LCD_W-20, 40); + lcd_putsn(WARNING_LINE_X, WARNING_LINE_Y, s_warning, WARNING_LINE_LEN); + // could be a place for a s_warning_info +} + +void displayPopup(const pm_char * pstr) +{ + s_warning = pstr; + displayBox(); + s_warning = NULL; + lcdRefresh(); +} + +void displayWarning(uint8_t event) +{ + s_warning_result = false; + displayBox(); + if (s_warning_info) { + lcd_putsnAtt(WARNING_LINE_X, WARNING_LINE_Y+FH, s_warning_info, s_warning_info_len, WARNING_INFO_FLAGS); + } + lcd_puts(WARNING_LINE_X, WARNING_LINE_Y+2*FH, s_warning_type == WARNING_TYPE_ASTERISK ? STR_EXIT : STR_POPUPS); + switch (event) { + case EVT_KEY_BREAK(KEY_ENTER): + if (s_warning_type == WARNING_TYPE_ASTERISK) + break; + s_warning_result = true; + // no break + case EVT_KEY_BREAK(KEY_EXIT): + s_warning = NULL; + s_warning_type = WARNING_TYPE_ASTERISK; + break; + default: + if (s_warning_type != WARNING_TYPE_INPUT) break; + s_editMode = EDIT_MODIFY_FIELD; + s_warning_input_value = checkIncDec(event, s_warning_input_value, s_warning_input_min, s_warning_input_max); + s_editMode = EDIT_SELECT_FIELD; + break; + } +} + +const char * displayMenu(uint8_t event) +{ + const char * result = NULL; + + uint8_t display_count = min(s_menu_count, (uint16_t)MENU_MAX_LINES); + uint8_t y = (display_count >= 5 ? MENU_Y - FH - 1 : MENU_Y); + drawFilledRect(MENU_X, y, MENU_W, display_count * (FH+1) + 2, SOLID, ERASE); + lcd_rect(MENU_X, y, MENU_W, display_count * (FH+1) + 2); + + for (uint8_t i=0; i display_count) { + displayScrollbar(MENU_X+MENU_W-1, y+1, MENU_MAX_LINES * (FH+1), s_menu_offset, s_menu_count, MENU_MAX_LINES); + } + + switch(event) { + case EVT_KEY_FIRST(KEY_MOVE_UP): + case EVT_KEY_REPT(KEY_MOVE_UP): + if (s_menu_item > 0) { + s_menu_item--; + } + else if (s_menu_offset > 0) { + s_menu_offset--; + result = STR_UPDATE_LIST; + } + else { + s_menu_item = display_count - 1; + if (s_menu_count > MENU_MAX_LINES) { + s_menu_offset = s_menu_count - display_count; + result = STR_UPDATE_LIST; + } + } + break; + + case EVT_KEY_FIRST(KEY_MOVE_DOWN): + case EVT_KEY_REPT(KEY_MOVE_DOWN): + if (s_menu_item < display_count - 1 && s_menu_offset + s_menu_item + 1 < s_menu_count) { + s_menu_item++; + } + else if (s_menu_count > s_menu_offset + display_count) { + s_menu_offset++; + result = STR_UPDATE_LIST; + } + else { + s_menu_item = 0; + if (s_menu_offset) { + s_menu_offset = 0; + result = STR_UPDATE_LIST; + } + } + break; + CASE_EVT_ROTARY_BREAK + case EVT_KEY_BREAK(KEY_ENTER): + result = s_menu[s_menu_item]; + // no break + case EVT_KEY_BREAK(KEY_EXIT): + s_menu_count = 0; + s_menu_item = 0; + s_menu_flags = 0; + s_menu_offset = 0; + break; + } + + return result; +} diff --git a/radio/src/gui/Taranis/view_main.cpp b/radio/src/gui/Taranis/view_main.cpp index 024f1ef59..46d9abf2f 100755 --- a/radio/src/gui/Taranis/view_main.cpp +++ b/radio/src/gui/Taranis/view_main.cpp @@ -37,8 +37,6 @@ #include "../../opentx.h" #define BIGSIZE MIDSIZE -#define BOX_WIDTH 31 -#define BOX_CENTERY (LCD_H-BOX_WIDTH/2-10) #define LBOX_CENTERX (BOX_WIDTH/2 + 17) #define RBOX_CENTERX (LCD_W-LBOX_CENTERX) #define MODELNAME_X (15) @@ -67,7 +65,6 @@ #define TRIM_LEN 27 #define MARKER_WIDTH 5 -#define BOX_LIMIT (BOX_WIDTH-MARKER_WIDTH) const pm_uchar logo_taranis[] PROGMEM = { #include "../../bitmaps/Taranis/logo.lbm" @@ -104,13 +101,6 @@ void drawPotsBars() } } -void drawStick(coord_t centrex, int16_t xval, int16_t yval) -{ - lcd_square(centrex-BOX_WIDTH/2, BOX_CENTERY-BOX_WIDTH/2, BOX_WIDTH); - DO_CROSS(centrex, BOX_CENTERY, 3); - lcd_square(centrex + (xval/((2*RESX)/BOX_LIMIT)) - MARKER_WIDTH/2, BOX_CENTERY - (yval/((2*RESX)/BOX_LIMIT)) - MARKER_WIDTH/2, MARKER_WIDTH, ROUND); -} - void doMainScreenGraphics() { int16_t calibStickVert = calibratedStick[CONVERT_MODE(1)]; diff --git a/radio/src/gui/Taranis/view_statistics.cpp b/radio/src/gui/Taranis/view_statistics.cpp new file mode 100755 index 000000000..3c050f05c --- /dev/null +++ b/radio/src/gui/Taranis/view_statistics.cpp @@ -0,0 +1,215 @@ +/* + * Authors (alphabetical order) + * - Andre Bernet + * - Andreas Weitl + * - Bertrand Songis + * - Bryan J. Rentoul (Gruvin) + * - Cameron Weeks + * - Erez Raviv + * - Gabriel Birkus + * - Jean-Pierre Parisy + * - Karl Szmutny + * - Michael Blandford + * - Michal Hlavinka + * - Pat Mackenzie + * - Philip Moss + * - Rob Thomson + * - Romolo Manfredini + * - Thomas Husterer + * + * opentx is based on code named + * gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/, + * er9x by Erez Raviv: http://code.google.com/p/er9x/, + * and the original (and ongoing) project by + * Thomas Husterer, th9x: http://code.google.com/p/th9x/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include "../../opentx.h" + +void menuStatisticsView(uint8_t event) +{ + TITLE(STR_MENUSTAT); + + switch(event) + { + case EVT_KEY_FIRST(KEY_UP): + chainMenu(menuStatisticsDebug); + break; + + case EVT_KEY_LONG(KEY_MENU): + g_eeGeneral.globalTimer = 0; + eeDirty(EE_GENERAL); + sessionTimer = 0; + break; + + case EVT_KEY_FIRST(KEY_EXIT): + chainMenu(menuMainView); + break; + } + + lcd_puts( 1*FW, FH*0, STR_TOTTM1TM2THRTHP); + putsTimer( 5*FW+5*FWNUM+1, FH*1, timersStates[0].val, 0, 0); + putsTimer( 12*FW+5*FWNUM+1, FH*1, timersStates[1].val, 0, 0); + + putsTimer( 5*FW+5*FWNUM+1, FH*2, s_timeCumThr, 0, 0); + putsTimer( 12*FW+5*FWNUM+1, FH*2, s_timeCum16ThrP/16, 0, 0); + + putsTimer( 12*FW+5*FWNUM+1, FH*0, sessionTimer, 0, 0); + + putsTimer(21*FW+5*FWNUM+1, 0*FH, g_eeGeneral.globalTimer + sessionTimer, TIMEHOUR, 0); + +#if defined(THRTRACE) + coord_t traceRd = (s_traceCnt < 0 ? s_traceWr : 0); + const coord_t x = 5; + const coord_t y = 60; + lcd_hline(x-3, y, MAXTRACE+3+3); + lcd_vline(x, y-32, 32+3); + + for (coord_t i=0; i=MAXTRACE) traceRd = 0; + if (traceRd==s_traceWr) break; + } +#endif +} + +#define MENU_DEBUG_COL1_OFS (11*FW-2) +#define MENU_DEBUG_Y_MIXMAX (2*FH-3) +#define MENU_DEBUG_Y_LUA (3*FH-2) +#define MENU_DEBUG_Y_FREE_RAM (4*FH-1) +#define MENU_DEBUG_Y_STACK (5*FH) +#define MENU_DEBUG_Y_RTOS (6*FH) + +void menuStatisticsDebug(uint8_t event) +{ + TITLE(STR_MENUDEBUG); + + switch(event) + { + case EVT_KEY_LONG(KEY_ENTER): + g_eeGeneral.mAhUsed = 0; + g_eeGeneral.globalTimer = 0; + eeDirty(EE_GENERAL); + sessionTimer = 0; + killEvents(event); + AUDIO_KEYPAD_UP(); + break; + case EVT_KEY_FIRST(KEY_ENTER): +#if defined(LUA) + maxLuaInterval = 0; + maxLuaDuration = 0; +#endif + maxMixerDuration = 0; + AUDIO_KEYPAD_UP(); + break; + +#if defined(DEBUG_TRACE_BUFFER) + case EVT_KEY_FIRST(KEY_UP): + pushMenu(menuTraceBuffer); + return; +#endif + + case EVT_KEY_FIRST(KEY_DOWN): + chainMenu(menuStatisticsView); + break; + case EVT_KEY_FIRST(KEY_EXIT): + chainMenu(menuMainView); + break; + } + + lcd_putsLeft(MENU_DEBUG_Y_FREE_RAM, "Free Mem"); + lcd_outdezAtt(MENU_DEBUG_COL1_OFS, MENU_DEBUG_Y_FREE_RAM, getAvailableMemory(), LEFT); + lcd_puts(lcdLastPos, MENU_DEBUG_Y_FREE_RAM, "b"); + +#if defined(LUA) + lcd_putsLeft(MENU_DEBUG_Y_LUA, "Lua scripts"); + lcd_putsAtt(MENU_DEBUG_COL1_OFS, MENU_DEBUG_Y_LUA+1, "[Duration]", SMLSIZE); + lcd_outdezAtt(lcdLastPos, MENU_DEBUG_Y_LUA, 10*maxLuaDuration, LEFT); + lcd_putsAtt(lcdLastPos+2, MENU_DEBUG_Y_LUA+1, "[Interval]", SMLSIZE); + lcd_outdezAtt(lcdLastPos, MENU_DEBUG_Y_LUA, 10*maxLuaInterval, LEFT); +#endif + + lcd_putsLeft(MENU_DEBUG_Y_MIXMAX, STR_TMIXMAXMS); + lcd_outdezAtt(MENU_DEBUG_COL1_OFS, MENU_DEBUG_Y_MIXMAX, DURATION_MS_PREC2(maxMixerDuration), PREC2|LEFT); + lcd_puts(lcdLastPos, MENU_DEBUG_Y_MIXMAX, "ms"); + + lcd_putsLeft(MENU_DEBUG_Y_RTOS, STR_FREESTACKMINB); + lcd_putsAtt(MENU_DEBUG_COL1_OFS, MENU_DEBUG_Y_RTOS+1, "[Main]", SMLSIZE); + lcd_outdezAtt(lcdLastPos, MENU_DEBUG_Y_RTOS, stack_free(0), UNSIGN|LEFT); + lcd_putsAtt(lcdLastPos+2, MENU_DEBUG_Y_RTOS+1, "[Mix]", SMLSIZE); + lcd_outdezAtt(lcdLastPos, MENU_DEBUG_Y_RTOS, stack_free(1), UNSIGN|LEFT); + lcd_putsAtt(lcdLastPos+2, MENU_DEBUG_Y_RTOS+1, "[Audio]", SMLSIZE); + lcd_outdezAtt(lcdLastPos, MENU_DEBUG_Y_RTOS, stack_free(2), UNSIGN|LEFT); + + lcd_puts(3*FW, 7*FH+1, STR_MENUTORESET); + lcd_status_line(); +} + + +#if defined(DEBUG_TRACE_BUFFER) +#include "stamp-opentx.h" + +void menuTraceBuffer(uint8_t event) +{ + switch(event) + { + case EVT_KEY_LONG(KEY_ENTER): + dumpTraceBuffer(); + killEvents(event); + break; + } + + SIMPLE_SUBMENU("Trace Buffer " VERS_STR, TRACE_BUFFER_LEN); + /* RTC time */ + struct gtm t; + gettime(&t); + putsTime(LCD_W+1, 0, t, TIMEBLINK); + + uint8_t y = 0; + uint8_t k = 0; + int8_t sub = m_posVert; + + lcd_putc(0, FH, '#'); + lcd_puts(4*FW, FH, "Time"); + lcd_puts(14*FW, FH, "Event"); + lcd_puts(20*FW, FH, "Data"); + + for (uint8_t i=0; itime % SECS_PER_DAY; + putsTimer(4*FW, y, tme, TIMEHOUR|LEFT, TIMEHOUR|LEFT); + //event + lcd_outdezNAtt(14*FW, y, te->event, LEADING0|LEFT, 3); + //data + lcd_putsn (20*FW, y, "0x", 2); + lcd_outhex4(22*FW-2, y, (uint16_t)(te->data >> 16)); + lcd_outhex4(25*FW, y, (uint16_t)(te->data & 0xFFFF)); + } + + } + + +} +#endif //#if defined(DEBUG_TRACE_BUFFER) diff --git a/radio/src/gui/Taranis/view_telemetry.cpp b/radio/src/gui/Taranis/view_telemetry.cpp new file mode 100755 index 000000000..2f6596f0c --- /dev/null +++ b/radio/src/gui/Taranis/view_telemetry.cpp @@ -0,0 +1,265 @@ +/* + * Authors (alphabetical order) + * - Andre Bernet + * - Andreas Weitl + * - Bertrand Songis + * - Bryan J. Rentoul (Gruvin) + * - Cameron Weeks + * - Erez Raviv + * - Gabriel Birkus + * - Jean-Pierre Parisy + * - Karl Szmutny + * - Michael Blandford + * - Michal Hlavinka + * - Pat Mackenzie + * - Philip Moss + * - Rob Thomson + * - Romolo Manfredini + * - Thomas Husterer + * + * opentx is based on code named + * gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/, + * er9x by Erez Raviv: http://code.google.com/p/er9x/, + * and the original (and ongoing) project by + * Thomas Husterer, th9x: http://code.google.com/p/th9x/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include "../../opentx.h" + +#define STATUS_BAR_Y (7*FH+1) +#define TELEM_2ND_COLUMN (11*FW) + +#if defined(FRSKY_HUB) && defined(GAUGES) +bar_threshold_t barsThresholds[THLD_MAX]; +#endif + +uint8_t s_frsky_view = 0; + +#define BAR_LEFT 26 +#define BAR_WIDTH 157 + +void displayRssiLine() +{ + if (TELEMETRY_STREAMING()) { + lcd_hline(0, 55, 212, 0); // separator + uint8_t rssi = min((uint8_t)99, TELEMETRY_RSSI()); + lcd_putsn(0, STATUS_BAR_Y, STR_RX, 2); lcd_outdezNAtt(4*FW, STATUS_BAR_Y, rssi, LEADING0, 2); + lcd_rect(BAR_LEFT, 57, 78, 7); + drawFilledRect(BAR_LEFT+1, 58, 19*rssi/25, 5, (rssi < getRssiAlarmValue(0)) ? DOTTED : SOLID); + } + else { + lcd_putsAtt(7*FW, STATUS_BAR_Y, STR_NODATA, BLINK); + lcd_status_line(); + } +} + +NOINLINE uint8_t getRssiAlarmValue(uint8_t alarm) +{ + return (45 - 3*alarm + g_model.frsky.rssiAlarms[alarm].value); +} + +uint8_t barCoord(int16_t value, int16_t min, int16_t max) +{ + if (value <= min) + return 0; + else if (value >= max) + return BAR_WIDTH-1; + else + return ((int32_t)(BAR_WIDTH-1) * (value - min)) / (max - min); +} + +bool displayGaugesTelemetryScreen(FrSkyScreenData & screen) +{ + // Custom Screen with gauges + uint8_t barHeight = 5; + for (int8_t i=3; i>=0; i--) { + FrSkyBarData & bar = screen.bars[i]; + source_t source = bar.source; + getvalue_t barMin = bar.barMin; + getvalue_t barMax = bar.barMax; + if (source && barMax > barMin) { + uint8_t y = barHeight+6+i*(barHeight+6); + putsMixerSource(0, y+barHeight-5, source, 0); + lcd_rect(BAR_LEFT, y, BAR_WIDTH+1, barHeight+2); + getvalue_t value = getValue(source); + putsChannel(BAR_LEFT+2+BAR_WIDTH, y+barHeight-5, source, LEFT); + uint8_t thresholdX = 0; + uint8_t width = barCoord(value, barMin, barMax); + uint8_t barShade = SOLID; + drawFilledRect(BAR_LEFT+1, y+1, width, barHeight, barShade); + for (uint8_t j=24; j<99; j+=25) { + if (j>thresholdX || j>width) { + lcd_vline(j*BAR_WIDTH/100+BAR_LEFT+1, y+1, barHeight); + } + } + if (thresholdX) { + lcd_vlineStip(BAR_LEFT+1+thresholdX, y-2, barHeight+3, DOTTED); + lcd_hline(BAR_LEFT+thresholdX, y-2, 3); + } + } + else { + barHeight += 2; + } + } + displayRssiLine(); + return barHeight < 13; +} + +bool displayNumbersTelemetryScreen(FrSkyScreenData & screen) +{ + // Custom Screen with numbers + uint8_t fields_count = 0; + for (uint8_t i=0; i<4; i++) { + for (uint8_t j=0; j 0) { + fields_count++; + } + if (i==3) { + lcd_vline(69, 8, 48); + lcd_vline(141, 8, 48); + if (!TELEMETRY_STREAMING()) { + displayRssiLine(); + return fields_count; + } + } + if (field) { + LcdFlags att = (i==3 ? NO_UNIT : DBLSIZE|NO_UNIT); + coord_t pos[] = {0, 71, 143, 214}; + if (field >= MIXSRC_FIRST_TIMER && field <= MIXSRC_LAST_TIMER && i!=3) { + // there is not enough space on LCD for displaying "Tmr1" or "Tmr2" and still see the - sign, we write "T1" or "T2" instead + putsStrIdx(pos[j], 1+FH+2*FH*i, "T", field-MIXSRC_FIRST_TIMER+1, 0); + } + else if (field >= MIXSRC_FIRST_TELEM && isGPSSensor(1+(field-MIXSRC_FIRST_TELEM)/3) && telemetryItems[(field-MIXSRC_FIRST_TELEM)/3].isAvailable()) { + // we don't display GPS name, no space for it + } + else { + putsMixerSource(pos[j], 1+FH+2*FH*i, field, 0); + } + + if (field >= MIXSRC_FIRST_TELEM) { + TelemetryItem & telemetryItem = telemetryItems[(field-MIXSRC_FIRST_TELEM)/3]; // TODO macro to convert a source to a telemetry index + if (!telemetryItem.isAvailable()) { + continue; + } + else if (telemetryItem.isOld()) { + att |= INVERS|BLINK; + } + } + + putsChannel(pos[j+1]-2, (i==3 ? 1+FH+2*FH*i:FH+2*FH*i), field, att); + + } + } + } + lcd_status_line(); + return fields_count; +} + +bool displayCustomTelemetryScreen(uint8_t index) +{ + FrSkyScreenData & screen = g_model.frsky.screens[index]; + +#if defined(GAUGES) + if (IS_BARS_SCREEN(s_frsky_view)) { + return displayGaugesTelemetryScreen(screen); + } +#endif + + displayNumbersTelemetryScreen(screen); + + return true; +} + +bool displayTelemetryScreen() +{ +#if defined(LUA) + if (TELEMETRY_SCREEN_TYPE(s_frsky_view) == TELEMETRY_SCREEN_TYPE_SCRIPT) { + return true; + } +#endif + + if (TELEMETRY_SCREEN_TYPE(s_frsky_view) == TELEMETRY_SCREEN_TYPE_NONE) { + return false; + } + + lcdDrawTelemetryTopBar(); + + if (s_frsky_view < MAX_TELEMETRY_SCREENS) { + return displayCustomTelemetryScreen(s_frsky_view); + } + + return true; +} + +enum NavigationDirection { + none, + up, + down +}; + +#define decrTelemetryScreen() direction = up +#define incrTelemetryScreen() direction = down + +void menuTelemetryFrsky(uint8_t event) +{ + enum NavigationDirection direction = none; + + switch (event) { + case EVT_KEY_FIRST(KEY_EXIT): + killEvents(event); + chainMenu(menuMainView); + break; + + case EVT_KEY_LONG(KEY_PAGE): + killEvents(event); + // no break; + + case EVT_KEY_FIRST(KEY_UP): + decrTelemetryScreen(); + break; + + case EVT_KEY_BREAK(KEY_PAGE): + case EVT_KEY_FIRST(KEY_DOWN): + incrTelemetryScreen(); + break; + + case EVT_KEY_LONG(KEY_ENTER): + killEvents(event); + MENU_ADD_ITEM(STR_RESET_TELEMETRY); + MENU_ADD_ITEM(STR_RESET_FLIGHT); + menuHandler = onMainViewMenu; + break; + } + + for (int i=0; i<=TELEMETRY_SCREEN_TYPE_MAX; i++) { + if (direction == up) { + if (s_frsky_view-- == 0) + s_frsky_view = TELEMETRY_VIEW_MAX; + } + else if (direction == down) { + if (s_frsky_view++ == TELEMETRY_VIEW_MAX) + s_frsky_view = 0; + } + else { + direction = down; + } + if (displayTelemetryScreen()) { + return; + } + } + + lcdDrawTelemetryTopBar(); + lcd_puts(8*FW, 3*FH, "No Telemetry Screens"); + displayRssiLine(); +} diff --git a/radio/src/gui/Taranis/view_text.cpp b/radio/src/gui/Taranis/view_text.cpp new file mode 100755 index 000000000..4c5af8948 --- /dev/null +++ b/radio/src/gui/Taranis/view_text.cpp @@ -0,0 +1,164 @@ +/* + * Authors (alphabetical order) + * - Andre Bernet + * - Andreas Weitl + * - Bertrand Songis + * - Bryan J. Rentoul (Gruvin) + * - Cameron Weeks + * - Erez Raviv + * - Gabriel Birkus + * - Jean-Pierre Parisy + * - Karl Szmutny + * - Michael Blandford + * - Michal Hlavinka + * - Pat Mackenzie + * - Philip Moss + * - Rob Thomson + * - Romolo Manfredini + * - Thomas Husterer + * + * opentx is based on code named + * gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/, + * er9x by Erez Raviv: http://code.google.com/p/er9x/, + * and the original (and ongoing) project by + * Thomas Husterer, th9x: http://code.google.com/p/th9x/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include "../../opentx.h" + +#define TEXT_FILENAME_MAXLEN 40 +#define TEXT_FILE_MAXSIZE 2048 + +char s_text_file[TEXT_FILENAME_MAXLEN]; +char s_text_screen[LCD_LINES-1][LCD_COLS+1]; + +void readTextFile(int & lines_count) +{ + FIL file; + int result; + char c; + unsigned int sz; + int line_length = 0; + int escape = 0; + char escape_chars[2]; + int current_line = 0; + + memset(s_text_screen, 0, sizeof(s_text_screen)); + + result = f_open(&file, s_text_file, FA_OPEN_EXISTING | FA_READ); + if (result == FR_OK) { + for (int i=0; i=s_pgOfs && current_line-s_pgOfs0 && escape<3) { + escape_chars[escape-1] = c; + if (escape == 2 && !strncmp(escape_chars, "up", 2)) { + c = '\300'; + escape = 0; + } + else if (escape == 2 && !strncmp(escape_chars, "dn", 2)) { + c = '\301'; + escape = 0; + } + else { + escape++; + continue; + } + } + else if (c=='~') { + c = 'z'+1; + } + else if (c=='\t') { + c = 0x1D; //tab + } + escape = 0; + s_text_screen[current_line-s_pgOfs][line_length++] = c; + } + } + if (c != '\n') { + current_line += 1; + } + f_close(&file); + } + + if (lines_count == 0) { + lines_count = current_line; + } +} + +void menuTextView(uint8_t event) +{ + static int lines_count; + + switch (event) { + case EVT_ENTRY: + s_pgOfs = 0; + lines_count = 0; + readTextFile(lines_count); + break; + + case EVT_KEY_FIRST(KEY_UP): + if (s_pgOfs == 0) + break; + else + s_pgOfs--; + // no break; + + case EVT_KEY_FIRST(KEY_DOWN): + // if (event == EVT_KEY_BREAK(KEY_DOWN)) { + if (s_pgOfs+LCD_LINES-1 >= lines_count) + break; + else + ++s_pgOfs; + // } + readTextFile(lines_count); + break; + + case EVT_KEY_BREAK(KEY_EXIT): + popMenu(); + break; + } + + for (int i=0; i LCD_LINES-1) { + displayScrollbar(LCD_W-1, FH, LCD_H-FH, s_pgOfs, lines_count, LCD_LINES-1); + } +} + +void pushMenuTextView(const char *filename) +{ + if (strlen(filename) < TEXT_FILENAME_MAXLEN) { + strcpy(s_text_file, filename); + pushMenu(menuTextView); + } +} diff --git a/radio/src/gui/Taranis/widgets.cpp b/radio/src/gui/Taranis/widgets.cpp new file mode 100755 index 000000000..54cb08765 --- /dev/null +++ b/radio/src/gui/Taranis/widgets.cpp @@ -0,0 +1,208 @@ +/* + * Authors (alphabetical order) + * - Andre Bernet + * - Andreas Weitl + * - Bertrand Songis + * - Bryan J. Rentoul (Gruvin) + * - Cameron Weeks + * - Erez Raviv + * - Gabriel Birkus + * - Jean-Pierre Parisy + * - Karl Szmutny + * - Michael Blandford + * - Michal Hlavinka + * - Pat Mackenzie + * - Philip Moss + * - Rob Thomson + * - Romolo Manfredini + * - Thomas Husterer + * + * opentx is based on code named + * gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/, + * er9x by Erez Raviv: http://code.google.com/p/er9x/, + * and the original (and ongoing) project by + * Thomas Husterer, th9x: http://code.google.com/p/th9x/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include "../../opentx.h" + +void drawStick(coord_t centrex, int16_t xval, int16_t yval) +{ +#define BOX_CENTERY (LCD_H-BOX_WIDTH/2-10) +#define MARKER_WIDTH 5 + lcd_square(centrex-BOX_WIDTH/2, BOX_CENTERY-BOX_WIDTH/2, BOX_WIDTH); + lcd_vline(centrex, BOX_CENTERY-1, 3); + lcd_hline(centrex-1, BOX_CENTERY, 3); + lcd_square(centrex + (xval/((2*RESX)/(BOX_WIDTH-MARKER_WIDTH))) - MARKER_WIDTH/2, BOX_CENTERY - (yval/((2*RESX)/(BOX_WIDTH-MARKER_WIDTH))) - MARKER_WIDTH/2, MARKER_WIDTH, ROUND); +#undef BOX_CENTERY +#undef MARKER_WIDTH +} + +void displayColumnHeader(const char * const *headers, uint8_t index) +{ + lcd_putsAtt(17*FW, 0, headers[index], 0); +} + +void menu_lcd_onoff(coord_t x, coord_t y, uint8_t value, LcdFlags attr) +{ + if (value) + lcd_putc(x+1, y, '#'); + if (attr) + drawFilledRect(x, y, 7, 7); + else + lcd_square(x, y, 7); +} + +void displayScreenIndex(uint8_t index, uint8_t count, uint8_t attr) +{ + lcd_outdezAtt(LCD_W, 0, count, attr); + coord_t x = 1+LCD_W-FW*(count>9 ? 3 : 2); + lcd_putcAtt(x, 0, '/', attr); + lcd_outdezAtt(x, 0, index+1, attr); +} + +void displayScrollbar(coord_t x, coord_t y, coord_t h, uint16_t offset, uint16_t count, uint8_t visible) +{ + lcd_vlineStip(x, y, h, DOTTED); + coord_t yofs = (h * offset) / count; + coord_t yhgt = (h * visible) / count; + if (yhgt + yofs > h) + yhgt = h - yofs; + lcd_vlineStip(x, y + yofs, yhgt, SOLID, FORCE); +} + +void title(const pm_char * s) +{ + lcd_putsAtt(0, 0, s, INVERS); +} + +select_menu_value_t selectMenuItem(coord_t x, coord_t y, const pm_char *label, const pm_char *values, select_menu_value_t value, select_menu_value_t min, select_menu_value_t max, LcdFlags attr, uint8_t event) +{ + lcd_putsColumnLeft(x, y, label); + if (values) lcd_putsiAtt(x, y, values, value-min, attr); + if (attr) value = checkIncDec(event, value, min, max, (g_menuPos[0] == 0) ? EE_MODEL : EE_GENERAL); + return value; +} + +uint8_t onoffMenuItem(uint8_t value, coord_t x, coord_t y, const pm_char *label, LcdFlags attr, uint8_t event ) +{ + menu_lcd_onoff(x, y, value, attr); + return selectMenuItem(x, y, label, NULL, value, 0, 1, attr, event); +} + +int8_t switchMenuItem(coord_t x, coord_t y, int8_t value, LcdFlags attr, uint8_t event) +{ + lcd_putsColumnLeft(x, y, STR_SWITCH); + putsSwitches(x, y, value, attr); + if (attr) CHECK_INCDEC_MODELSWITCH(event, value, SWSRC_FIRST_IN_MIXES, SWSRC_LAST_IN_MIXES, isSwitchAvailableInMixes); + return value; +} + +void displaySlider(coord_t x, coord_t y, uint8_t value, uint8_t max, uint8_t attr) +{ + lcd_putc(x+(value*4*FW)/max, y, '$'); + lcd_hline(x, y+3, 5*FW-1, FORCE); + if (attr && (!(attr & BLINK) || !BLINK_ON_PHASE)) drawFilledRect(x, y, 5*FW-1, FH-1); +} + +#if defined(GVARS) +bool noZero(int val) +{ + return val != 0; +} + +int16_t gvarMenuItem(coord_t x, coord_t y, int16_t value, int16_t min, int16_t max, LcdFlags attr, uint8_t editflags, uint8_t event) +{ + uint16_t delta = GV_GET_GV1_VALUE(max); + bool invers = (attr & INVERS); + + // TRACE("gvarMenuItem(val=%d min=%d max=%d)", value, min, max); + + if (invers && event == EVT_KEY_LONG(KEY_ENTER)) { + s_editMode = !s_editMode; + if (attr & PREC1) + value = (GV_IS_GV_VALUE(value, min, max) ? GET_GVAR(value, min, max, mixerCurrentFlightMode)*10 : delta); + else + value = (GV_IS_GV_VALUE(value, min, max) ? GET_GVAR(value, min, max, mixerCurrentFlightMode) : delta); + eeDirty(EE_MODEL); + } + + if (GV_IS_GV_VALUE(value, min, max)) { + if (attr & LEFT) + attr -= LEFT; /* because of ZCHAR */ + else + x -= 2*FW+FWNUM; + + attr &= ~PREC1; + + int8_t idx = (int16_t) GV_INDEX_CALC_DELTA(value, delta); + if (idx >= 0) ++idx; // transform form idx=0=GV1 to idx=1=GV1 in order to handle double keys invert + if (invers) { + CHECK_INCDEC_MODELVAR_CHECK(event, idx, -MAX_GVARS, MAX_GVARS, noZero); + if (idx == 0) idx = 1; // handle reset to zero, map to GV1 + } + if (idx < 0) { + value = (int16_t) GV_CALC_VALUE_IDX_NEG(idx, delta); + idx = -idx; + lcd_putcAtt(x-6, y, '-', attr); + } + else { + value = (int16_t) GV_CALC_VALUE_IDX_POS(idx-1, delta); + } + putsStrIdx(x, y, STR_GV, idx, attr); + } + else { + lcd_outdezAtt(x, y, value, attr); + if (invers) value = checkIncDec(event, value, min, max, EE_MODEL | editflags); + } + return value; +} +#else +int16_t gvarMenuItem(coord_t x, coord_t y, int16_t value, int16_t min, int16_t max, LcdFlags attr, uint8_t event) +{ + lcd_outdezAtt(x, y, value, attr); + if (attr&INVERS) value = checkIncDec(event, value, min, max, EE_MODEL); + return value; +} +#endif + +#if defined(SDCARD) +char statusLineMsg[STATUS_LINE_LENGTH]; +tmr10ms_t statusLineTime = 0; +uint8_t statusLineHeight = 0; + +void showStatusLine() +{ + statusLineTime = get_tmr10ms(); +} + +#define STATUS_LINE_DELAY (3 * 100) /* 3s */ +void drawStatusLine() +{ + if (statusLineTime) { + if ((tmr10ms_t)(get_tmr10ms() - statusLineTime) <= (tmr10ms_t)STATUS_LINE_DELAY) { + if (statusLineHeight < FH) statusLineHeight++; + } + else if (statusLineHeight) { + statusLineHeight--; + } + else { + statusLineTime = 0; + } + + drawFilledRect(0, LCD_H-statusLineHeight, LCD_W, FH, SOLID, ERASE); + lcd_putsAtt(5, LCD_H+1-statusLineHeight, statusLineMsg, BSS); + drawFilledRect(0, LCD_H-statusLineHeight, LCD_W, FH, SOLID); + } +} +#endif diff --git a/radio/src/gui/gui.h b/radio/src/gui/gui.h new file mode 100755 index 000000000..6b2f02df6 --- /dev/null +++ b/radio/src/gui/gui.h @@ -0,0 +1,46 @@ +/* + * Authors (alphabetical order) + * - Andre Bernet + * - Andreas Weitl + * - Bertrand Songis + * - Bryan J. Rentoul (Gruvin) + * - Cameron Weeks + * - Erez Raviv + * - Gabriel Birkus + * - Jean-Pierre Parisy + * - Karl Szmutny + * - Michael Blandford + * - Michal Hlavinka + * - Pat Mackenzie + * - Philip Moss + * - Rob Thomson + * - Romolo Manfredini + * - Thomas Husterer + * + * opentx is based on code named + * gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/, + * er9x by Erez Raviv: http://code.google.com/p/er9x/, + * and the original (and ongoing) project by + * Thomas Husterer, th9x: http://code.google.com/p/th9x/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef _GUI_H_ +#define _GUI_H_ + +#if defined(PCBTARANIS) + #include "Taranis/gui.h" +#else + #include "9X/gui.h" +#endif + +#endif // _GUI_H_ diff --git a/radio/src/gui/menu_general.cpp b/radio/src/gui/menu_general.cpp index 40fa6d790..b0573930c 100644 --- a/radio/src/gui/menu_general.cpp +++ b/radio/src/gui/menu_general.cpp @@ -36,10 +36,6 @@ #include "../opentx.h" -const pm_uchar sticks[] PROGMEM = { -#include "../bitmaps/sticks.lbm" -}; - #if defined(CPUARM) extern LP_CONST LanguagePack czLanguagePack; extern LP_CONST LanguagePack enLanguagePack; @@ -70,6 +66,16 @@ const LanguagePack * LP_CONST languagePacks[] = { }; #endif +void menuGeneralSetup(uint8_t event); +void menuGeneralSdManager(uint8_t event); +void menuGeneralCustomFunctions(uint8_t event); +void menuGeneralTrainer(uint8_t event); +void menuGeneralVersion(uint8_t event); +void menuGeneralDiagKeys(uint8_t event); +void menuGeneralDiagAna(uint8_t event); +void menuGeneralHardware(uint8_t event); +void menuGeneralCalib(uint8_t event); + enum EnumTabDiag { e_Setup, CASE_SDCARD(e_Sd) @@ -82,16 +88,6 @@ enum EnumTabDiag { e_Calib }; -void menuGeneralSetup(uint8_t event); -void menuGeneralSdManager(uint8_t event); -void menuGeneralCustomFunctions(uint8_t event); -void menuGeneralTrainer(uint8_t event); -void menuGeneralVersion(uint8_t event); -void menuGeneralDiagKeys(uint8_t event); -void menuGeneralDiagAna(uint8_t event); -void menuGeneralHardware(uint8_t event); -void menuGeneralCalib(uint8_t event); - const MenuFuncP_PROGMEM menuTabGeneral[] PROGMEM = { menuGeneralSetup, CASE_SDCARD(menuGeneralSdManager) diff --git a/radio/src/gui/menu_model.cpp b/radio/src/gui/menu_model.cpp index e5f80d594..e9179736d 100644 --- a/radio/src/gui/menu_model.cpp +++ b/radio/src/gui/menu_model.cpp @@ -241,9 +241,6 @@ void editName(coord_t x, coord_t y, char *name, uint8_t size, uint8_t event, uin } lcd_putcAtt(x+editNameCursorPos*FW, y, idx2char(v), ERASEBG|INVERS|FIXEDWIDTH); -#if defined(PCBHORUS) - lcd_putcAtt(x+editNameCursorPos*FW, y, idx2char(v), FIXEDWIDTH|WHITE); -#endif } else { cur = 0; diff --git a/radio/src/gui/menus.cpp b/radio/src/gui/menus.cpp index cedac2e40..e119c7e3a 100644 --- a/radio/src/gui/menus.cpp +++ b/radio/src/gui/menus.cpp @@ -36,1068 +36,10 @@ #include "../opentx.h" -vertpos_t s_pgOfs; -int8_t s_editMode; -uint8_t s_noHi; -uint8_t calibrationState; - -void menu_lcd_onoff(coord_t x, coord_t y, uint8_t value, LcdFlags attr) -{ -#if defined(GRAPHICS) - if (value) - lcd_putc(x+1, y, '#'); - if (attr) - drawFilledRect(x, y, 7, 7); - else - lcd_square(x, y, 7); -#else - /* ON / OFF version */ - lcd_putsiAtt(x, y, STR_OFFON, value, attr ? INVERS:0) ; -#endif -} - -void displayScreenIndex(uint8_t index, uint8_t count, uint8_t attr) -{ - lcd_outdezAtt(LCD_W, 0, count, attr); - coord_t x = 1+LCD_W-FW*(count>9 ? 3 : 2); - lcd_putcAtt(x, 0, '/', attr); - lcd_outdezAtt(x, 0, index+1, attr); -} - -#if !defined(CPUM64) -void displayScrollbar(coord_t x, coord_t y, coord_t h, uint16_t offset, uint16_t count, uint8_t visible) -{ - lcd_vlineStip(x, y, h, SOLID, ERASE); - lcd_vlineStip(x, y, h, DOTTED); - coord_t yofs = (h * offset) / count; - coord_t yhgt = (h * visible) / count; - if (yhgt + yofs > h) - yhgt = h - yofs; - lcd_vlineStip(x, y + yofs, yhgt, SOLID, FORCE); -} -#endif - -#if defined(NAVIGATION_POT1) -int16_t p1valdiff; -#endif - -#if defined(NAVIGATION_POT2) -int8_t p2valdiff; -#endif - -uint8_t switchToMix(uint8_t source) -{ -#if defined(PCBTARANIS) - if (source <= 5*3) - return MIXSRC_FIRST_SWITCH + (source-1) / 3; - else if (source <= 17) - return MIXSRC_SF; - else if (source <= 20) - return MIXSRC_SG; - else - return MIXSRC_SH; -#else - if (source <= 3) - return MIXSRC_3POS; - else - return MIXSRC_FIRST_SWITCH - 3 + source; -#endif -} - -#if defined(AUTOSWITCH) -int8_t checkIncDecMovedSwitch(int8_t val) -{ - if (s_editMode>0) { - int8_t swtch = getMovedSwitch(); - if (swtch) { -#if defined(PCBTARANIS) - div_t info = switchInfo(swtch); - if (IS_TOGGLE(info.quot)) { - if (info.rem != 0) { - val = (val == swtch ? swtch+2 : swtch); - } - } - else { - val = swtch; - } -#else - if (IS_MOMENTARY(val) && swtch==val) - val = -val; - else - val = swtch; -#endif - } - } - return val; -} -#endif - -int8_t checkIncDec_Ret; - -#if defined(CPUARM) -INIT_STOPS(stops100, 3, -100, 0, 100) -INIT_STOPS(stops1000, 3, -1000, 0, 1000) -INIT_STOPS(stopsSwitch, 15, SWSRC_FIRST, CATEGORY_END(-SWSRC_FIRST_LOGICAL_SWITCH), CATEGORY_END(-SWSRC_FIRST_TRIM), CATEGORY_END(-SWSRC_LAST_SWITCH+1), 0, CATEGORY_END(SWSRC_LAST_SWITCH), CATEGORY_END(SWSRC_FIRST_TRIM-1), CATEGORY_END(SWSRC_FIRST_LOGICAL_SWITCH-1), SWSRC_LAST) - -int checkIncDec(unsigned int event, int val, int i_min, int i_max, unsigned int i_flags, IsValueAvailable isValueAvailable, const CheckIncDecStops &stops) -{ - int newval = val; - -#if defined(DBLKEYS) - unsigned int in = KEYS_PRESSED(); - if (!(i_flags & NO_DBLKEYS) && (EVT_KEY_MASK(event))) { - bool dblkey = true; - if (DBLKEYS_PRESSED_RGT_LFT(in)) { - if (!isValueAvailable || isValueAvailable(-val)) - newval = -val; - } - else if (DBLKEYS_PRESSED_RGT_UP(in)) { - newval = (i_max > stops.max() ? stops.max() : i_max); - while (isValueAvailable && !isValueAvailable(newval) && newval>i_min) { - --newval; - } - } - else if (DBLKEYS_PRESSED_LFT_DWN(in)) { - newval = (i_min < stops.min() ? stops.min() : i_min); - while (isValueAvailable && !isValueAvailable(newval) && newval0 && (IS_ROTARY_RIGHT(event) || event==EVT_KEY_FIRST(KEY_UP) || event==EVT_KEY_REPT(KEY_UP))) { -#else - if (event==EVT_KEY_FIRST(KEY_RIGHT) || event==EVT_KEY_REPT(KEY_RIGHT) || (s_editMode>0 && (IS_ROTARY_RIGHT(event) || event==EVT_KEY_FIRST(KEY_UP) || event==EVT_KEY_REPT(KEY_UP)))) { -#endif - - do { - if (IS_KEY_REPT(event) && (i_flags & INCDEC_REP10)) { - newval += min(10, i_max-val); - } - else { - newval++; - } - } while (isValueAvailable && !isValueAvailable(newval) && newval<=i_max); - - if (newval > i_max) { - newval = val; - killEvents(event); - AUDIO_WARNING2(); - } - else { - AUDIO_KEYPAD_UP(); - } - } -#if defined(PCBTARANIS) - else if (s_editMode>0 && (IS_ROTARY_LEFT(event) || event==EVT_KEY_FIRST(KEY_DOWN) || event==EVT_KEY_REPT(KEY_DOWN))) { -#else - else if (event==EVT_KEY_FIRST(KEY_LEFT) || event==EVT_KEY_REPT(KEY_LEFT) || (s_editMode>0 && (IS_ROTARY_LEFT(event) || event==EVT_KEY_FIRST(KEY_DOWN) || event==EVT_KEY_REPT(KEY_DOWN)))) { -#endif - - do { - if (IS_KEY_REPT(event) && (i_flags & INCDEC_REP10)) { - newval -= min(10, val-i_min); - } - else { - newval--; - } - } while (isValueAvailable && !isValueAvailable(newval) && newval>=i_min); - - if (newval < i_min) { - newval = val; - killEvents(event); - AUDIO_WARNING2(); - } - else { - AUDIO_KEYPAD_DOWN(); - } - } - - if (!READ_ONLY() && i_min==0 && i_max==1 && (event==EVT_KEY_BREAK(KEY_ENTER) || IS_ROTARY_BREAK(event))) { - s_editMode = 0; - newval = !val; - } - -#if defined(NAVIGATION_POT1) - // change values based on P1 - newval -= p1valdiff; - p1valdiff = 0; -#endif - -#if defined(AUTOSWITCH) - if (i_flags & INCDEC_SWITCH) { - newval = checkIncDecMovedSwitch(newval); - } -#endif - -#if defined(AUTOSOURCE) - if (i_flags & INCDEC_SOURCE) { - if (s_editMode>0) { - int source = GET_MOVED_SOURCE(i_min, i_max); - if (source) { - newval = source; - } -#if defined(AUTOSWITCH) - else { - unsigned int swtch = abs(getMovedSwitch()); - if (swtch) { - newval = switchToMix(swtch); - } - } -#endif - } - } -#endif - - if (newval > i_max || newval < i_min) { - newval = (newval > i_max ? i_max : i_min); - killEvents(event); - AUDIO_WARNING2(); - } - - if (newval != val) { - if (!(i_flags & NO_INCDEC_MARKS) && (newval != i_max) && (newval != i_min) && stops.contains(newval) && !IS_ROTARY_EVENT(event)) { - bool pause = (newval > val ? !stops.contains(newval+1) : !stops.contains(newval-1)); - if (pause) { - pauseEvents(event); // delay before auto-repeat continues - if (newval>val) // without AUDIO it's optimized, because the 2 sounds are the same - AUDIO_KEYPAD_UP(); - else - AUDIO_KEYPAD_DOWN(); - } - } - eeDirty(i_flags & (EE_GENERAL|EE_MODEL)); - checkIncDec_Ret = (newval > val ? 1 : -1); - } - else { - checkIncDec_Ret = 0; - } - return newval; -} -#else -int16_t checkIncDec(uint8_t event, int16_t val, int16_t i_min, int16_t i_max, uint8_t i_flags) -{ - int16_t newval = val; - -#if defined(DBLKEYS) - uint8_t in = KEYS_PRESSED(); - if (!(i_flags & NO_DBLKEYS) && (EVT_KEY_MASK(event))) { - bool dblkey = true; - if (DBLKEYS_PRESSED_RGT_LFT(in)) - newval = -val; - else if (DBLKEYS_PRESSED_RGT_UP(in)) { - newval = (i_max > 100 ? 100 : i_max); - } - else if (DBLKEYS_PRESSED_LFT_DWN(in)) { - newval = (i_min < -100 ? -100 : i_min); - } - else if (DBLKEYS_PRESSED_UP_DWN(in)) { - newval = 0; - } - else { - dblkey = false; - } - - if (dblkey) { - killEvents(KEY_UP); - killEvents(KEY_DOWN); - killEvents(KEY_RIGHT); - killEvents(KEY_LEFT); - event = 0; - } - } -#endif - - if (event==EVT_KEY_FIRST(KEY_RIGHT) || event==EVT_KEY_REPT(KEY_RIGHT) || (s_editMode>0 && (IS_ROTARY_RIGHT(event) || event==EVT_KEY_FIRST(KEY_UP) || event==EVT_KEY_REPT(KEY_UP)))) { - newval++; - AUDIO_KEYPAD_UP(); - } - else if (event==EVT_KEY_FIRST(KEY_LEFT) || event==EVT_KEY_REPT(KEY_LEFT) || (s_editMode>0 && (IS_ROTARY_LEFT(event) || event==EVT_KEY_FIRST(KEY_DOWN) || event==EVT_KEY_REPT(KEY_DOWN)))) { - newval--; - AUDIO_KEYPAD_DOWN(); - } - - if (!READ_ONLY() && i_min==0 && i_max==1 && (event==EVT_KEY_BREAK(KEY_ENTER) || IS_ROTARY_BREAK(event))) { - s_editMode = 0; - newval = !val; - } - -#if defined(NAVIGATION_POT1) - // change values based on P1 - newval -= p1valdiff; - p1valdiff = 0; -#endif - -#if defined(AUTOSWITCH) - if (i_flags & INCDEC_SWITCH) { - newval = checkIncDecMovedSwitch(newval); - } -#endif - -#if defined(AUTOSOURCE) - if (i_flags & INCDEC_SOURCE) { - if (s_editMode>0) { - int8_t source = GET_MOVED_SOURCE(i_min, i_max); - if (source) { - newval = source; - } -#if defined(AUTOSWITCH) - else { - uint8_t swtch = abs(getMovedSwitch()); - if (swtch) { - newval = switchToMix(swtch); - } - } -#endif - } - } -#endif - - if (newval > i_max || newval < i_min) { - newval = (newval > i_max ? i_max : i_min); - killEvents(event); - AUDIO_WARNING2(); - } - - if (newval != val) { - if (!(i_flags & NO_INCDEC_MARKS) && (newval != i_max) && (newval != i_min) && (newval==0 || newval==-100 || newval==+100) && !IS_ROTARY_EVENT(event)) { - pauseEvents(event); // delay before auto-repeat continues - if (newval>val) // without AUDIO it's optimized, because the 2 sounds are the same - AUDIO_KEYPAD_UP(); - else - AUDIO_KEYPAD_DOWN(); - } - eeDirty(i_flags & (EE_GENERAL|EE_MODEL)); - checkIncDec_Ret = (newval > val ? 1 : -1); - } - else { - checkIncDec_Ret = 0; - } - return newval; -} -#endif - -#if defined(CPUM64) -int8_t checkIncDecModel(uint8_t event, int8_t i_val, int8_t i_min, int8_t i_max) -{ - return checkIncDec(event, i_val, i_min, i_max, EE_MODEL); -} - -int8_t checkIncDecModelZero(uint8_t event, int8_t i_val, int8_t i_max) -{ - return checkIncDecModel(event, i_val, 0, i_max); -} - -int8_t checkIncDecGen(uint8_t event, int8_t i_val, int8_t i_min, int8_t i_max) -{ - return checkIncDec(event, i_val, i_min, i_max, EE_GENERAL); -} -#endif - -void check_simple(check_event_t event, uint8_t curr, const MenuFuncP *menuTab, uint8_t menuTabSize, vertpos_t maxrow) -{ - check(event, curr, menuTab, menuTabSize, 0, 0, maxrow); -} - -void check_submenu_simple(check_event_t event, uint8_t maxrow) -{ - check_simple(event, 0, 0, 0, maxrow); -} - -void title(const pm_char * s) -{ - lcd_putsAtt(0, 0, s, INVERS); -} - -#define SCROLL_TH 64 -#define SCROLL_POT1_TH 32 - -#if defined(CPUARM) - #define CURSOR_NOT_ALLOWED_IN_ROW(row) ((int8_t)MAXCOL(row) < 0) -#else - #define CURSOR_NOT_ALLOWED_IN_ROW(row) (MAXCOL(row) == TITLE_ROW) -#endif - -#if defined(PCBTARANIS) - #define MAXCOL_RAW(row) (horTab ? pgm_read_byte(horTab+min(row, (vertpos_t)horTabMax)) : (const uint8_t)0) - #define MAXCOL(row) (MAXCOL_RAW(row) >= HIDDEN_ROW ? MAXCOL_RAW(row) : (const uint8_t)(MAXCOL_RAW(row) & (~NAVIGATION_LINE_BY_LINE))) - #define COLATTR(row) (MAXCOL_RAW(row) == (uint8_t)-1 ? (const uint8_t)0 : (const uint8_t)(MAXCOL_RAW(row) & NAVIGATION_LINE_BY_LINE)) -#else - #define MAXCOL(row) (horTab ? pgm_read_byte(horTab+min(row, (vertpos_t)horTabMax)) : (const uint8_t)0) -#endif - -#define INC(val, min, max) if (valmin) {val--;} else {val=max;} - -#if LCD_W >= 212 -coord_t scrollbar_X = LCD_W-1; -#endif - -#if defined(CPUARM) -bool modelHasNotes() -{ - char filename[sizeof(MODELS_PATH)+1+sizeof(g_model.header.name)+sizeof(TEXT_EXT)] = MODELS_PATH "/"; - char *buf = strcat_modelname(&filename[sizeof(MODELS_PATH)], g_eeGeneral.currModel); - strcpy(buf, TEXT_EXT); - return isFileAvailable(filename); -} - -void pushModelNotes() -{ - char filename[sizeof(MODELS_PATH)+1+sizeof(g_model.header.name)+sizeof(TEXT_EXT)] = MODELS_PATH "/"; - char *buf = strcat_modelname(&filename[sizeof(MODELS_PATH)], g_eeGeneral.currModel); - strcpy(buf, TEXT_EXT); - pushMenuTextView(filename); -} -#endif - -#if defined(PCBTARANIS) -void onLongMenuPress(const char *result) -{ - if (result == STR_VIEW_CHANNELS) { - pushMenu(menuChannelsView); - } - else if (result == STR_VIEW_NOTES) { - pushModelNotes(); - } -} -#endif - -#if defined(CPUARM) -tmr10ms_t menuEntryTime; -#endif - -#if defined(PCBTARANIS) -void check(check_event_t event, uint8_t curr, const MenuFuncP *menuTab, uint8_t menuTabSize, const pm_uint8_t *horTab, uint8_t horTabMax, vertpos_t maxrow, uint8_t flags) -{ - vertpos_t l_posVert = m_posVert; - horzpos_t l_posHorz = m_posHorz; - - uint8_t maxcol = MAXCOL(l_posVert); - -#define scrollUD 0 - - if (p2valdiff || scrollUD || p1valdiff) backlightOn(); // on keypress turn the light on - - if (menuTab) { - int8_t cc = curr; - switch (event) { - case EVT_KEY_LONG(KEY_MENU): - if (menuTab == menuTabModel) { - killEvents(event); - if (modelHasNotes()) { - MENU_ADD_SD_ITEM(STR_VIEW_CHANNELS); - MENU_ADD_ITEM(STR_VIEW_NOTES); - menuHandler = onLongMenuPress; - } - else { - pushMenu(menuChannelsView); - } - } - break; - - case EVT_KEY_LONG(KEY_PAGE): - if (curr > 0) - cc = curr - 1; - else - cc = menuTabSize-1; - killEvents(event); - break; - - case EVT_KEY_BREAK(KEY_PAGE): - if (curr < (menuTabSize-1)) - cc = curr + 1; - else - cc = 0; - break; - } - - if (!calibrationState && cc != curr) { - chainMenu((MenuFuncP)pgm_read_adr(&menuTab[cc])); - } - - if (!(flags&CHECK_FLAG_NO_SCREEN_INDEX)) { - displayScreenIndex(curr, menuTabSize, 0); - } - - drawFilledRect(0, 0, LCD_W, MENU_TITLE_HEIGHT, SOLID, FILL_WHITE|GREY_DEFAULT); - } - - DISPLAY_PROGRESS_BAR(menuTab ? lcdLastPos-2*FW-((curr+1)/10*FWNUM)-2 : 20*FW+1); - - if (s_editMode<=0) { - if (scrollUD) { - l_posVert = limit((int8_t)0, (int8_t)(l_posVert - scrollUD), (int8_t)maxrow); - l_posHorz = min((uint8_t)l_posHorz, MAXCOL(l_posVert)); - } - - if (p2valdiff && l_posVert>0) { - l_posHorz = limit((int8_t)0, (int8_t)((uint8_t)l_posHorz - p2valdiff), (int8_t)maxcol); - } - } - - switch(event) - { - case EVT_ENTRY: - menuEntryTime = get_tmr10ms(); - l_posVert = POS_VERT_INIT; - l_posHorz = POS_HORZ_INIT(l_posVert); - SET_SCROLLBAR_X(LCD_W-1); -#if defined(ROTARY_ENCODER_NAVIGATION) - if (menuTab) { - s_editMode = EDIT_MODE_INIT; - break; - } - // no break -#else - s_editMode = EDIT_MODE_INIT; - break; -#endif - - case EVT_ENTRY_UP: - menuEntryTime = get_tmr10ms(); - s_editMode = 0; - l_posHorz = POS_HORZ_INIT(l_posVert); - SET_SCROLLBAR_X(LCD_W-1); - break; - - case EVT_ROTARY_BREAK: - if (s_editMode > 1) break; - if (m_posHorz < 0 && maxcol > 0 && READ_ONLY_UNLOCKED()) { - l_posHorz = 0; - break; - } - if (!menuTab || l_posVert>0) { - if (READ_ONLY_UNLOCKED()) { - s_editMode = (s_editMode<=0); - } - } - break; - -#if defined(ROTARY_ENCODER_NAVIGATION) - case EVT_ROTARY_LONG: - if (s_editMode > 1) break; - killEvents(event); - if (l_posVert != POS_VERT_INIT) { - l_posVert = POS_VERT_INIT; - s_editMode = EDIT_MODE_INIT; - break; - } - // no break -#endif - case EVT_KEY_LONG(KEY_EXIT): - s_editMode = 0; // TODO needed? we call ENTRY_UP after which does the same - popMenu(); - break; - - case EVT_KEY_BREAK(KEY_EXIT): -#if defined(ROTARY_ENCODER_NAVIGATION) - if (s_editMode == 0) - s_editMode = EDIT_MODE_INIT; - else -#endif - if (s_editMode>0) { - s_editMode = 0; - break; - } - - if (l_posHorz >= 0 && (COLATTR(l_posVert) & NAVIGATION_LINE_BY_LINE)) { - l_posHorz = -1; - } - else - { - uint8_t posVertInit = POS_VERT_INIT; - if (s_pgOfs != 0 || l_posVert != posVertInit) { - s_pgOfs = 0; - l_posVert = posVertInit; - l_posHorz = POS_HORZ_INIT(l_posVert); - } - else { - popMenu(); - } - } - break; - - CASE_EVT_ROTARY_MOVE_RIGHT - if (s_editMode != 0) break; - if ((COLATTR(l_posVert) & NAVIGATION_LINE_BY_LINE)) { - if (l_posHorz >= 0) { - INC(l_posHorz, 0, maxcol); - break; - } - } - else { - if (l_posHorz < maxcol) { - l_posHorz++; - break; - } - else { - l_posHorz = 0; - if (!IS_ROTARY_MOVE_RIGHT(event)) - break; - } - } - - do { - INC(l_posVert, POS_VERT_INIT, maxrow); - } while (CURSOR_NOT_ALLOWED_IN_ROW(l_posVert)); - - s_editMode = 0; // if we go down, we must be in this mode - - l_posHorz = POS_HORZ_INIT(l_posVert); - break; - - CASE_EVT_ROTARY_MOVE_LEFT - if (s_editMode != 0) break; - if ((COLATTR(l_posVert) & NAVIGATION_LINE_BY_LINE)) { - if (l_posHorz >= 0) { - DEC(l_posHorz, 0, maxcol); - break; - } - } - else { - if (l_posHorz > 0) { - l_posHorz--; - break; - } - else if (IS_ROTARY_MOVE_LEFT(event) && s_editMode == 0) { - l_posHorz = 0xff; - } - else { - l_posHorz = maxcol; - break; - } - } - - do { - DEC(l_posVert, POS_VERT_INIT, maxrow); - } while (CURSOR_NOT_ALLOWED_IN_ROW(l_posVert)); - - s_editMode = 0; // if we go up, we must be in this mode - - if ((COLATTR(l_posVert) & NAVIGATION_LINE_BY_LINE)) - l_posHorz = -1; - else - l_posHorz = min((uint8_t)l_posHorz, MAXCOL(l_posVert)); - - break; - } - - if (l_posVert == 0 || (l_posVert==2 && MAXCOL(vertpos_t(1)) >= HIDDEN_ROW) || (l_posVert==3 && MAXCOL(vertpos_t(1)) >= HIDDEN_ROW && MAXCOL(vertpos_t(2)) >= HIDDEN_ROW)) { - s_pgOfs = 0; - } - else if (horTab) { - uint8_t max = menuTab ? LCD_LINES-1 : LCD_LINES-2; - if (maxrow > max) { - while (1) { - vertpos_t firstLine = 0; - for (int numLines=0; firstLine<=maxrow && numLines lastLine) { - s_pgOfs++; - } - else { - break; - } - } - } - } - } - else { - uint8_t max = menuTab ? LCD_LINES-1 : LCD_LINES-2; - if (l_posVert>max+s_pgOfs) { - s_pgOfs = l_posVert-max; - } - else if (l_posVert<1+s_pgOfs) { - s_pgOfs = l_posVert-1; - } - } - - if (maxrow > LCD_LINES-1 && scrollbar_X) { - displayScrollbar(scrollbar_X, MENU_TITLE_HEIGHT, LCD_H-MENU_TITLE_HEIGHT-MENU_NAVIG_HEIGHT, s_pgOfs, menuTab ? maxrow : maxrow+1, LCD_LINES-1); - } - - m_posVert = l_posVert; - m_posHorz = l_posHorz; -} - -#else // defined(PCBTARANIS) - -void check(check_event_t event, uint8_t curr, const MenuFuncP *menuTab, uint8_t menuTabSize, const pm_uint8_t *horTab, uint8_t horTabMax, vertpos_t maxrow) -{ - vertpos_t l_posVert = m_posVert; - horzpos_t l_posHorz = m_posHorz; - - uint8_t maxcol = MAXCOL(l_posVert); - -#if defined(NAVIGATION_POT1) - // check pot 1 - if changed -> scroll values - static int16_t p1val; - static int16_t p1valprev; - p1valdiff = (p1val-calibratedStick[6]) / SCROLL_POT1_TH; - if (p1valdiff) { - p1valdiff = (p1valprev-calibratedStick[6]) / 2; - p1val = calibratedStick[6]; - } - p1valprev = calibratedStick[6]; -#endif - -#if defined(NAVIGATION_POT2) - // check pot 2 - if changed -> scroll menu - static int16_t p2valprev; - p2valdiff = (p2valprev-calibratedStick[4]) / SCROLL_TH; - if (p2valdiff) p2valprev = calibratedStick[4]; -#endif - -#if defined(NAVIGATION_POT3) - // check pot 3 if changed -> cursor down/up - static int16_t p3valprev; - int8_t scrollUD = (p3valprev-calibratedStick[5]) / SCROLL_TH; - if (scrollUD) p3valprev = calibratedStick[5]; -#else - #define scrollUD 0 -#endif - - if (p2valdiff || scrollUD || p1valdiff) backlightOn(); // on keypress turn the light on - - if (menuTab) { - uint8_t attr = 0; - - - if (l_posVert==0 && !calibrationState) { - attr = INVERS; - - int8_t cc = curr; - - if (p2valdiff) { - cc = limit((int8_t)0, (int8_t)(cc - p2valdiff), (int8_t)(menuTabSize-1)); - } - - switch(event) { -#if defined(ROTARY_ENCODER_NAVIGATION) - case EVT_ROTARY_BREAK: - if (s_editMode < 0 && maxrow > 0) { - s_editMode = 0; - // TODO ? l_posVert = (horTab && horTab[1]==0xff) ? 2 : 1; - l_posHorz = 0; - } - else { - s_editMode = -1; - } - event = 0; - break; -#endif - -#if defined(ROTARY_ENCODER_NAVIGATION) - case EVT_ROTARY_LEFT: - if (s_editMode >= 0) - break; -#endif - case EVT_KEY_FIRST(KEY_LEFT): - if (curr > 0) - cc = curr - 1; - else - cc = menuTabSize-1; - break; - -#if defined(ROTARY_ENCODER_NAVIGATION) - case EVT_ROTARY_RIGHT: - if (s_editMode >= 0) - break; -#endif - case EVT_KEY_FIRST(KEY_RIGHT): - if (curr < (menuTabSize-1)) - cc = curr + 1; - else - cc = 0; - break; - } - - if (cc != curr) { - chainMenu((MenuFuncP)pgm_read_adr(&menuTab[cc])); - } - -#if defined(ROTARY_ENCODER_NAVIGATION) - if (IS_RE_NAVIGATION_ENABLE() && s_editMode < 0) - attr = INVERS|BLINK; -#endif - } - - calibrationState = 0; - displayScreenIndex(curr, menuTabSize, attr); - - } - - DISPLAY_PROGRESS_BAR(menuTab ? lcdLastPos-2*FW-((curr+1)/10*FWNUM)-2 : 20*FW+1); - - if (s_editMode<=0) { - if (scrollUD) { - l_posVert = limit((int8_t)0, (int8_t)(l_posVert - scrollUD), (int8_t)maxrow); - l_posHorz = min((uint8_t)l_posHorz, MAXCOL(l_posVert)); - } - - if (p2valdiff && l_posVert>0) { - l_posHorz = limit((int8_t)0, (int8_t)((uint8_t)l_posHorz - p2valdiff), (int8_t)maxcol); - } - } - - switch(event) - { - case EVT_ENTRY: -#if defined(CPUARM) - menuEntryTime = get_tmr10ms(); -#endif - l_posVert = POS_VERT_INIT; - l_posHorz = POS_HORZ_INIT(l_posVert); - SET_SCROLLBAR_X(LCD_W-1); -#if defined(ROTARY_ENCODER_NAVIGATION) - if (menuTab) { - s_editMode = EDIT_MODE_INIT; - break; - } - // no break -#else - s_editMode = EDIT_MODE_INIT; - break; -#endif - -#if defined(ROTARY_ENCODER_NAVIGATION) - case EVT_ENTRY_UP: - s_editMode = 0; - SET_SCROLLBAR_X(LCD_W-1); - break; - - case EVT_ROTARY_BREAK: - if (s_editMode > 1) break; -#endif - - case EVT_KEY_FIRST(KEY_ENTER): - if (!menuTab || l_posVert>0) { - if (READ_ONLY_UNLOCKED()) { - s_editMode = (s_editMode<=0); - } - } - break; - -#if defined(ROTARY_ENCODER_NAVIGATION) - case EVT_ROTARY_LONG: - if (s_editMode > 1) break; - killEvents(event); - if (l_posVert != POS_VERT_INIT) { - l_posVert = POS_VERT_INIT; - s_editMode = EDIT_MODE_INIT; - break; - } - // no break -#endif - case EVT_KEY_LONG(KEY_EXIT): - s_editMode = 0; // TODO needed? we call ENTRY_UP after which does the same - popMenu(); - break; - - case EVT_KEY_BREAK(KEY_EXIT): -#if defined(ROTARY_ENCODER_NAVIGATION) - if (s_editMode == 0) - s_editMode = EDIT_MODE_INIT; - else -#endif - if (s_editMode>0) { - s_editMode = 0; - break; - } - - if (l_posVert==0 || !menuTab) { - popMenu(); // beeps itself - } - else { - AUDIO_MENUS(); - l_posVert = 0; - l_posHorz = 0; - } - break; - - case EVT_KEY_REPT(KEY_RIGHT): //inc - if (l_posHorz==maxcol) break; - // no break - - case EVT_KEY_FIRST(KEY_RIGHT)://inc - if (!horTab || s_editMode>0) break; - -#if defined(ROTARY_ENCODER_NAVIGATION) - CASE_EVT_ROTARY_MOVE_RIGHT - if (s_editMode != 0) break; - if (l_posHorz < maxcol) { - l_posHorz++; - break; - } - else { - l_posHorz = 0; - if (!IS_ROTARY_MOVE_RIGHT(event)) - break; - } -#else - INC(l_posHorz, 0, maxcol); - break; -#endif - - case EVT_KEY_REPT(KEY_DOWN): //inc - if (!IS_ROTARY_RIGHT(event) && l_posVert==maxrow) break; - // no break - - case EVT_KEY_FIRST(KEY_DOWN): //inc - if (s_editMode>0) break; - do { - INC(l_posVert, POS_VERT_INIT, maxrow); - } while (CURSOR_NOT_ALLOWED_IN_ROW(l_posVert)); - -#if defined(ROTARY_ENCODER_NAVIGATION) - s_editMode = 0; // if we go down, we must be in this mode -#endif - - l_posHorz = min(l_posHorz, MAXCOL(l_posVert)); - break; - - case EVT_KEY_REPT(KEY_LEFT): //dec - if (l_posHorz==0) break; - // no break - - case EVT_KEY_FIRST(KEY_LEFT)://dec - if (!horTab || s_editMode>0) break; - -#if defined(ROTARY_ENCODER_NAVIGATION) - CASE_EVT_ROTARY_MOVE_LEFT - if (s_editMode != 0) break; - if (l_posHorz > 0) { - l_posHorz--; - break; - } - else if (IS_ROTARY_MOVE_LEFT(event) && s_editMode == 0) { - l_posHorz = 0xff; - } - else { - l_posHorz = maxcol; - break; - } -#else - DEC(l_posHorz, 0, maxcol); - break; -#endif - - case EVT_KEY_REPT(KEY_UP): //dec - if (!IS_ROTARY_LEFT(event) && l_posVert==0) break; - // no break - case EVT_KEY_FIRST(KEY_UP): //dec - if (s_editMode>0) break; - - do { - DEC(l_posVert, POS_VERT_INIT, maxrow); - } while (CURSOR_NOT_ALLOWED_IN_ROW(l_posVert)); - -#if defined(ROTARY_ENCODER_NAVIGATION) || defined(PCBTARANIS) - s_editMode = 0; // if we go up, we must be in this mode -#endif - - l_posHorz = min((uint8_t)l_posHorz, MAXCOL(l_posVert)); - break; - } - -#if defined(CPUARM) - if (l_posVert<1) s_pgOfs=0; - else if (menuTab && horTab) { - vertpos_t realPosVert = l_posVert; - vertpos_t realPgOfs = s_pgOfs; - vertpos_t realMaxrow = maxrow; - for (vertpos_t i=1; i<=maxrow; i++) { - if (MAXCOL(i) == HIDDEN_ROW) { - realMaxrow--; - if (i < l_posVert) - realPosVert--; - if (i < s_pgOfs) - realPgOfs--; - } - } - if (realPosVert>(LCD_LINES-1)+realPgOfs) realPgOfs = realPosVert-(LCD_LINES-1); - else if (realPosVert<1+realPgOfs) realPgOfs = realPosVert-1; - s_pgOfs = realPgOfs; - for (vertpos_t i=1; i<=realPgOfs; i++) { - if (MAXCOL(i) == HIDDEN_ROW) { - s_pgOfs++; - } - } - maxrow = realMaxrow; - } - else { - uint8_t max = menuTab ? LCD_LINES-1 : LCD_LINES-2; - if (l_posVert>max+s_pgOfs) s_pgOfs = l_posVert-max; - else if (l_posVert<1+s_pgOfs) s_pgOfs = l_posVert-1; - } - -#if LCD_W >= 212 - if (maxrow > LCD_LINES-1 && scrollbar_X) - displayScrollbar(scrollbar_X, FH, LCD_H-FH, s_pgOfs, menuTab ? maxrow : maxrow+1, LCD_LINES-1); -#endif - -#else - uint8_t max = menuTab ? LCD_LINES-1 : LCD_LINES-2; - if (l_posVert<1) s_pgOfs=0; - else if (l_posVert>max+s_pgOfs) s_pgOfs = l_posVert-max; - else if (l_posVert<1+s_pgOfs) s_pgOfs = l_posVert-1; -#endif - m_posVert = l_posVert; - m_posHorz = l_posHorz; -#if !defined(CPUM64) - // cosmetics on 9x - if (s_pgOfs > 0) { - l_posVert--; - if (l_posVert == s_pgOfs && CURSOR_NOT_ALLOWED_IN_ROW(l_posVert)) { - s_pgOfs = l_posVert-1; - } - } -#endif -} -#endif - MenuFuncP g_menuStack[5]; uint8_t menuEvent = 0; uint8_t g_menuPos[4]; uint8_t g_menuStackPtr = 0; -vertpos_t m_posVert; -horzpos_t m_posHorz; void popMenu() { @@ -1134,665 +76,12 @@ void pushMenu(MenuFuncP newMenu) menuEvent = EVT_ENTRY; } -const pm_char * s_warning = NULL; -const pm_char * s_warning_info; -uint8_t s_warning_info_len; -uint8_t s_warning_type; -uint8_t s_warning_result = 0; - #if defined(CPUARM) -uint8_t s_warning_info_flags = ZCHAR; -int16_t s_warning_input_value; -int16_t s_warning_input_min; -int16_t s_warning_input_max; -#endif - -void displayBox() +void pushModelNotes() { - drawFilledRect(10, 16, LCD_W-20, 40, SOLID, ERASE); - lcd_rect(10, 16, LCD_W-20, 40); -#if defined(CPUARM) - lcd_putsn(WARNING_LINE_X, WARNING_LINE_Y, s_warning, WARNING_LINE_LEN); -#else - lcd_puts(WARNING_LINE_X, WARNING_LINE_Y, s_warning); -#endif - // could be a place for a s_warning_info -} - -void displayPopup(const pm_char * pstr) -{ - s_warning = pstr; - displayBox(); - s_warning = NULL; - lcdRefresh(); -} - -void displayWarning(uint8_t event) -{ - s_warning_result = false; - displayBox(); - if (s_warning_info) { - lcd_putsnAtt(16, WARNING_LINE_Y+FH, s_warning_info, s_warning_info_len, WARNING_INFO_FLAGS); - } - lcd_puts(16, WARNING_LINE_Y+2*FH, s_warning_type == WARNING_TYPE_ASTERISK ? STR_EXIT : STR_POPUPS); - switch (event) { -#if defined(ROTARY_ENCODER_NAVIGATION) - case EVT_ROTARY_BREAK: -#endif - case EVT_KEY_BREAK(KEY_ENTER): - if (s_warning_type == WARNING_TYPE_ASTERISK) - break; - s_warning_result = true; - // no break -#if defined(ROTARY_ENCODER_NAVIGATION) - case EVT_ROTARY_LONG: - killEvents(event); -#endif - case EVT_KEY_BREAK(KEY_EXIT): - s_warning = NULL; - s_warning_type = WARNING_TYPE_ASTERISK; - break; -#if defined(CPUARM) - default: - if (s_warning_type != WARNING_TYPE_INPUT) break; - s_editMode = EDIT_MODIFY_FIELD; - s_warning_input_value = checkIncDec(event, s_warning_input_value, s_warning_input_min, s_warning_input_max); - s_editMode = EDIT_SELECT_FIELD; - break; -#endif - } -} - -select_menu_value_t selectMenuItem(coord_t x, coord_t y, const pm_char *label, const pm_char *values, select_menu_value_t value, select_menu_value_t min, select_menu_value_t max, LcdFlags attr, uint8_t event) -{ - lcd_putsColumnLeft(x, y, label); - if (values) lcd_putsiAtt(x, y, values, value-min, attr); - if (attr) value = checkIncDec(event, value, min, max, (g_menuPos[0] == 0) ? EE_MODEL : EE_GENERAL); - return value; -} - -uint8_t onoffMenuItem(uint8_t value, coord_t x, coord_t y, const pm_char *label, LcdFlags attr, uint8_t event ) -{ -#if defined(GRAPHICS) - menu_lcd_onoff(x, y, value, attr); - return selectMenuItem(x, y, label, NULL, value, 0, 1, attr, event); -#else - return selectMenuItem(x, y, label, STR_OFFON, value, 0, 1, attr, event); -#endif -} - -int8_t switchMenuItem(coord_t x, coord_t y, int8_t value, LcdFlags attr, uint8_t event) -{ - lcd_putsColumnLeft(x, y, STR_SWITCH); - putsSwitches(x, y, value, attr); - if (attr) CHECK_INCDEC_MODELSWITCH(event, value, SWSRC_FIRST_IN_MIXES, SWSRC_LAST_IN_MIXES, isSwitchAvailableInMixes); - return value; -} - -#if !defined(CPUM64) -void displaySlider(coord_t x, coord_t y, uint8_t value, uint8_t max, uint8_t attr) -{ - lcd_putc(x+(value*4*FW)/max, y, '$'); - lcd_hline(x, y+3, 5*FW-1, FORCE); - if (attr && (!(attr & BLINK) || !BLINK_ON_PHASE)) drawFilledRect(x, y, 5*FW-1, FH-1); -} -#elif defined(GRAPHICS) -void display5posSlider(coord_t x, coord_t y, uint8_t value, uint8_t attr) -{ - lcd_putc(x+2*FW+(value*FW), y, '$'); - lcd_hline(x, y+3, 5*FW-1, SOLID); - if (attr && (!(attr & BLINK) || !BLINK_ON_PHASE)) drawFilledRect(x, y, 5*FW-1, FH-1); + char filename[sizeof(MODELS_PATH)+1+sizeof(g_model.header.name)+sizeof(TEXT_EXT)] = MODELS_PATH "/"; + char *buf = strcat_modelname(&filename[sizeof(MODELS_PATH)], g_eeGeneral.currModel); + strcpy(buf, TEXT_EXT); + pushMenuTextView(filename); } #endif - -bool noZero(int val) { - return val != 0; -} - -#if defined(GVARS) -#if defined(CPUARM) -int16_t gvarMenuItem(coord_t x, coord_t y, int16_t value, int16_t min, int16_t max, LcdFlags attr, uint8_t editflags, uint8_t event) -#else -int16_t gvarMenuItem(coord_t x, coord_t y, int16_t value, int16_t min, int16_t max, LcdFlags attr, uint8_t event) -#endif -{ - uint16_t delta = GV_GET_GV1_VALUE(max); - bool invers = (attr & INVERS); - - // TRACE("gvarMenuItem(val=%d min=%d max=%d)", value, min, max); - - if (invers && event == EVT_KEY_LONG(KEY_ENTER)) { - s_editMode = !s_editMode; -#if defined(CPUARM) - if (attr & PREC1) - value = (GV_IS_GV_VALUE(value, min, max) ? GET_GVAR(value, min, max, mixerCurrentFlightMode)*10 : delta); - else - value = (GV_IS_GV_VALUE(value, min, max) ? GET_GVAR(value, min, max, mixerCurrentFlightMode) : delta); -#else - value = (GV_IS_GV_VALUE(value, min, max) ? GET_GVAR(value, min, max, mixerCurrentFlightMode) : delta); -#endif - eeDirty(EE_MODEL); - } - if (GV_IS_GV_VALUE(value, min, max)) { - if (attr & LEFT) - attr -= LEFT; /* because of ZCHAR */ - else - x -= 2*FW+FWNUM; - -#if defined(CPUARM) - attr &= ~PREC1; -#endif - - int8_t idx = (int16_t) GV_INDEX_CALC_DELTA(value, delta); -#if defined(CPUARM) - if (idx >= 0) ++idx; // transform form idx=0=GV1 to idx=1=GV1 in order to handle double keys invert -#endif - if (invers) { -#if defined(CPUARM) - CHECK_INCDEC_MODELVAR_CHECK(event, idx, -MAX_GVARS, MAX_GVARS, noZero); - if (idx == 0) idx = 1; // handle reset to zero, map to GV1 -#else - idx = checkIncDec(event, idx, -MAX_GVARS, MAX_GVARS-1, EE_MODEL|NO_DBLKEYS); // disable double keys -#endif - } - if (idx < 0) { - value = (int16_t) GV_CALC_VALUE_IDX_NEG(idx, delta); - idx = -idx; - lcd_putcAtt(x-6, y, '-', attr); - } - else { -#if defined(CPUARM) - value = (int16_t) GV_CALC_VALUE_IDX_POS(idx-1, delta); -#else - value = (int16_t) GV_CALC_VALUE_IDX_POS(idx, delta); - idx++; -#endif - } - putsStrIdx(x, y, STR_GV, idx, attr); - } - else { - lcd_outdezAtt(x, y, value, attr); -#if defined(CPUARM) - if (invers) value = checkIncDec(event, value, min, max, EE_MODEL | editflags); -#else - if (invers) value = checkIncDec(event, value, min, max, EE_MODEL); -#endif - } - return value; -} -#else -int16_t gvarMenuItem(coord_t x, coord_t y, int16_t value, int16_t min, int16_t max, LcdFlags attr, uint8_t event) -{ - lcd_outdezAtt(x, y, value, attr); - if (attr&INVERS) value = checkIncDec(event, value, min, max, EE_MODEL); - return value; -} -#endif - -void repeatLastCursorMove(uint8_t event) -{ - if (CURSOR_MOVED_LEFT(event) || CURSOR_MOVED_RIGHT(event)) { - putEvent(event); - } - else { - m_posHorz = 0; - } -} - -#if LCD_W >= 212 -#define MENU_X 30 -#define MENU_Y 16 -#define MENU_W LCD_W-60 -#else -#define MENU_X 10 -#define MENU_Y 16 -#define MENU_W LCD_W-20 -#endif - -#if defined(CPUARM) -void (*popupFunc)(uint8_t event) = NULL; -#endif - -#if defined(NAVIGATION_MENUS) -const char *s_menu[MENU_MAX_LINES]; -uint8_t s_menu_item = 0; -uint16_t s_menu_count = 0; -uint8_t s_menu_flags = 0; -uint16_t s_menu_offset = 0; -void (*menuHandler)(const char *result); -const char * displayMenu(uint8_t event) -{ - const char * result = NULL; - - uint8_t display_count = min(s_menu_count, (uint16_t)MENU_MAX_LINES); - uint8_t y = (display_count >= 5 ? MENU_Y - FH - 1 : MENU_Y); - drawFilledRect(MENU_X, y, MENU_W, display_count * (FH+1) + 2, SOLID, ERASE); - lcd_rect(MENU_X, y, MENU_W, display_count * (FH+1) + 2); - - for (uint8_t i=0; i display_count) { - displayScrollbar(MENU_X+MENU_W-1, y+1, MENU_MAX_LINES * (FH+1), s_menu_offset, s_menu_count, MENU_MAX_LINES); - } - - switch(event) { -#if defined(ROTARY_ENCODER_NAVIGATION) - CASE_EVT_ROTARY_LEFT -#endif - case EVT_KEY_FIRST(KEY_MOVE_UP): - case EVT_KEY_REPT(KEY_MOVE_UP): - if (s_menu_item > 0) { - s_menu_item--; - } -#if defined(SDCARD) - else if (s_menu_offset > 0) { - s_menu_offset--; - result = STR_UPDATE_LIST; - } -#endif - else { - s_menu_item = display_count - 1; -#if defined(SDCARD) - if (s_menu_count > MENU_MAX_LINES) { - s_menu_offset = s_menu_count - display_count; - result = STR_UPDATE_LIST; - } -#endif - } - break; - -#if defined(ROTARY_ENCODER_NAVIGATION) - CASE_EVT_ROTARY_RIGHT -#endif - case EVT_KEY_FIRST(KEY_MOVE_DOWN): - case EVT_KEY_REPT(KEY_MOVE_DOWN): - if (s_menu_item < display_count - 1 && s_menu_offset + s_menu_item + 1 < s_menu_count) { - s_menu_item++; - } -#if defined(SDCARD) - else if (s_menu_count > s_menu_offset + display_count) { - s_menu_offset++; - result = STR_UPDATE_LIST; - } -#endif - else { - s_menu_item = 0; -#if defined(SDCARD) - if (s_menu_offset) { - s_menu_offset = 0; - result = STR_UPDATE_LIST; - } -#endif - } - break; - CASE_EVT_ROTARY_BREAK - case EVT_KEY_BREAK(KEY_ENTER): - result = s_menu[s_menu_item]; - // no break -#if defined(ROTARY_ENCODER_NAVIGATION) - CASE_EVT_ROTARY_LONG - killEvents(event); -#endif - case EVT_KEY_BREAK(KEY_EXIT): - s_menu_count = 0; - s_menu_item = 0; - s_menu_flags = 0; - s_menu_offset = 0; - break; - } - - return result; -} -#endif - -#if defined(SDCARD) -char statusLineMsg[STATUS_LINE_LENGTH]; -tmr10ms_t statusLineTime = 0; -uint8_t statusLineHeight = 0; - -void showStatusLine() -{ - statusLineTime = get_tmr10ms(); -} - -#define STATUS_LINE_DELAY (3 * 100) /* 3s */ -void drawStatusLine() -{ - if (statusLineTime) { - if ((tmr10ms_t)(get_tmr10ms() - statusLineTime) <= (tmr10ms_t)STATUS_LINE_DELAY) { - if (statusLineHeight < FH) statusLineHeight++; - } - else if (statusLineHeight) { - statusLineHeight--; - } - else { - statusLineTime = 0; - } - - drawFilledRect(0, LCD_H-statusLineHeight, LCD_W, FH, SOLID, ERASE); - lcd_putsAtt(5, LCD_H+1-statusLineHeight, statusLineMsg, BSS); - drawFilledRect(0, LCD_H-statusLineHeight, LCD_W, FH, SOLID); - } -} -#endif - -#if defined(PCBTARANIS) -bool isInputAvailable(int input) -{ - for (int i=0; ichn == input) - return true; - } - return false; -} -#endif - -#if defined(CPUARM) -bool isSourceAvailable(int source) -{ -#if defined(PCBTARANIS) - if (source>=MIXSRC_FIRST_INPUT && source<=MIXSRC_LAST_INPUT) { - return isInputAvailable(source - MIXSRC_FIRST_INPUT); - } -#endif - -#if defined(LUA_MODEL_SCRIPTS) - if (source>=MIXSRC_FIRST_LUA && source<=MIXSRC_LAST_LUA) { - div_t qr = div(source-MIXSRC_FIRST_LUA, MAX_SCRIPT_OUTPUTS); - return (qr.rem=MIXSRC_FIRST_LUA && source<=MIXSRC_LAST_LUA) - return false; -#endif - -#if defined(PCBTARANIS) - if (source>=MIXSRC_FIRST_POT && source<=MIXSRC_LAST_POT) { - return IS_POT_AVAILABLE(POT1+source-MIXSRC_FIRST_POT); - } -#endif - -#if !defined(HELI) - if (source>=MIXSRC_CYC1 && source<=MIXSRC_CYC3) - return false; -#endif - - if (source>=MIXSRC_CH1 && source<=MIXSRC_LAST_CH) { - uint8_t destCh = source-MIXSRC_CH1; - for (uint8_t i = 0; i < MAX_MIXERS; i++) { - MixData *md = mixAddress(i); - if (md->srcRaw == 0) return false; - if (md->destCh==destCh) return true; - } - return false; - } - -#if defined(PCBTARANIS) - if (source>=MIXSRC_SI && source<=MIXSRC_SN) { - if (!IS_2x2POS(source-MIXSRC_SI)) { - return false; - } - } -#endif - - if (source>=MIXSRC_SW1 && source<=MIXSRC_LAST_LOGICAL_SWITCH) { - LogicalSwitchData * cs = lswAddress(source-MIXSRC_SW1); - return (cs->func != LS_FUNC_NONE); - } - -#if !defined(GVARS) - if (source>=MIXSRC_GVAR1 && source<=MIXSRC_LAST_GVAR) - return false; -#endif - - if (source>=MIXSRC_RESERVE1 && source<=MIXSRC_RESERVE5) - return false; - - if (source>=MIXSRC_FIRST_TELEM && source<=MIXSRC_LAST_TELEM) { - div_t qr = div(source-MIXSRC_FIRST_TELEM, 3); - if (qr.rem == 0) - return isTelemetryFieldAvailable(qr.quot); - else - return isTelemetryFieldComparisonAvailable(qr.quot); - } - - return true; -} - -bool isSourceAvailableInCustomSwitches(int source) -{ - bool result = isSourceAvailable(source); - -#if defined(FRSKY) - if (result && source>=MIXSRC_FIRST_TELEM && source<=MIXSRC_LAST_TELEM) { - div_t qr = div(source-MIXSRC_FIRST_TELEM, 3); - result = isTelemetryFieldComparisonAvailable(qr.quot); - } -#endif - - return result; -} - -bool isInputSourceAvailable(int source) -{ -#if defined(PCBTARANIS) && !defined(REVPLUS) - if (source == MIXSRC_POT3) - return false; -#endif - - if (source>=MIXSRC_Rud && source<=MIXSRC_MAX) - return true; - - if (source>=MIXSRC_Rud && source<=MIXSRC_MAX) - return true; - - if (source>=MIXSRC_TrimRud && source=MIXSRC_FIRST_CH && source<=MIXSRC_LAST_CH) - return true; - - if (source>=MIXSRC_FIRST_TRAINER && source<=MIXSRC_LAST_TRAINER) - return true; - - if (source>=MIXSRC_FIRST_TELEM && source<=MIXSRC_LAST_TELEM) - return isTelemetryFieldAvailable(source-MIXSRC_FIRST_TELEM); - - return false; -} - -enum SwitchContext -{ - LogicalSwitchesContext, - ModelCustomFunctionsContext, - GeneralCustomFunctionsContext, - TimersContext, - MixesContext -}; - -bool isSwitchAvailable(int swtch, SwitchContext context) -{ -#if defined(PCBTARANIS) - uint32_t index = switchInfo(abs(swtch)).quot; -#endif - - if (swtch < 0) { -#if defined(PCBTARANIS) - if (!IS_3POS(index)) - return false; -#endif - if (swtch == -SWSRC_ON || swtch == -SWSRC_One) { - return false; - } - swtch = -swtch; - } - -#if defined(PCBTARANIS) && defined(REV9E) - if (swtch >= SWSRC_SA1 && swtch <= SWSRC_SR1 && (swtch-SWSRC_SA1)%3 == 0) { - return IS_3POS(index); - } -#elif defined(PCBTARANIS) - if (swtch == SWSRC_SA1 || swtch == SWSRC_SB1 || swtch == SWSRC_SC1 || swtch == SWSRC_SD1 || swtch == SWSRC_SE1 || swtch == SWSRC_SG1) { - return IS_3POS(index); - } - if (swtch >= SWSRC_SI0 && swtch <= SWSRC_SM2) { - return IS_2x2POS((swtch-SWSRC_SI0)/2); - } - if (swtch >= SWSRC_SN0 && swtch <= SWSRC_SN2) { - return IS_2x2POS(6); - } -#endif - -#if defined(PCBTARANIS) - if (swtch >= SWSRC_FIRST_MULTIPOS_SWITCH && swtch <= SWSRC_LAST_MULTIPOS_SWITCH) { - int index = (swtch - SWSRC_FIRST_MULTIPOS_SWITCH) / XPOTS_MULTIPOS_COUNT; - if (IS_POT_MULTIPOS(POT1+index)) { - StepsCalibData * calib = (StepsCalibData *) &g_eeGeneral.calib[POT1+index]; - return (calib->count >= ((swtch - SWSRC_FIRST_MULTIPOS_SWITCH) % XPOTS_MULTIPOS_COUNT)); - } - else { - return false; - } - } -#endif - - if (swtch >= SWSRC_FIRST_LOGICAL_SWITCH && swtch <= SWSRC_LAST_LOGICAL_SWITCH) { - if (context == GeneralCustomFunctionsContext) { - return false; - } - else if (context != LogicalSwitchesContext) { - LogicalSwitchData * cs = lswAddress(swtch-SWSRC_FIRST_LOGICAL_SWITCH); - return (cs->func != LS_FUNC_NONE); - } - } - - if (context != ModelCustomFunctionsContext && context != GeneralCustomFunctionsContext && (swtch == SWSRC_ON || swtch == SWSRC_One)) { - return false; - } - - if (swtch >= SWSRC_FIRST_FLIGHT_MODE && swtch <= SWSRC_LAST_FLIGHT_MODE) { - if (context == MixesContext || context == GeneralCustomFunctionsContext) { - return false; - } - else { - swtch -= SWSRC_FIRST_FLIGHT_MODE; - if (swtch == 0) { - return true; - } - FlightModeData * fm = flightModeAddress(swtch); - return (fm->swtch != SWSRC_NONE); - } - } - - return true; -} - -bool isSwitchAvailableInLogicalSwitches(int swtch) -{ - return isSwitchAvailable(swtch, LogicalSwitchesContext); -} - -bool isSwitchAvailableInCustomFunctions(int swtch) -{ - if (g_menuStack[g_menuStackPtr] == menuModelCustomFunctions) - return isSwitchAvailable(swtch, ModelCustomFunctionsContext); - else - return isSwitchAvailable(swtch, GeneralCustomFunctionsContext); -} - -bool isSwitchAvailableInMixes(int swtch) -{ - return isSwitchAvailable(swtch, MixesContext); -} - -bool isSwitchAvailableInTimers(int swtch) -{ - if (swtch >= 0) { - if (swtch < TMRMODE_COUNT) - return true; - else - swtch -= TMRMODE_COUNT-1; - } - else { - if (swtch > -TMRMODE_COUNT) - return false; - else - swtch += TMRMODE_COUNT-1; - } - - return isSwitchAvailable(swtch, TimersContext); -} - -bool isThrottleSourceAvailable(int source) -{ -#if defined(PCBTARANIS) - if (source == THROTTLE_SOURCE_S3 && !IS_POT_AVAILABLE(POT3)) - return false; -#endif - return true; -} - -bool isLogicalSwitchFunctionAvailable(int function) -{ - return function != LS_FUNC_RANGE; -} - -bool isAssignableFunctionAvailable(int function) -{ - bool modelFunctions = (g_menuStack[g_menuStackPtr] == menuModelCustomFunctions); - - switch (function) { - case FUNC_OVERRIDE_CHANNEL: -#if defined(OVERRIDE_CHANNEL_FUNCTION) - return modelFunctions; -#else - return false; -#endif - case FUNC_ADJUST_GVAR: -#if defined(GVARS) - return modelFunctions; -#else - return false; -#endif -#if !defined(HAPTIC) - case FUNC_HAPTIC: -#endif - case FUNC_PLAY_DIFF: -#if !defined(DANGEROUS_MODULE_FUNCTIONS) - case FUNC_RANGECHECK: - case FUNC_BIND: - case FUNC_MODULE_OFF: -#endif -#if !defined(LUA) - case FUNC_PLAY_SCRIPT: -#endif - case FUNC_RESERVE5: - return false; - - default: - return true; - } -} - -bool isModuleAvailable(int module) -{ -#if defined(PCBSKY9X) - if (module == MODULE_TYPE_NONE) - return false; -#endif - -#if !defined(PXX) - if (module == MODULE_TYPE_XJT) - return false; -#endif - - return true; -} - -#endif diff --git a/radio/src/gui/menus.h b/radio/src/gui/menus.h index 5b4e11b75..412eb5b8c 100644 --- a/radio/src/gui/menus.h +++ b/radio/src/gui/menus.h @@ -34,28 +34,11 @@ * */ -#ifndef menus_h -#define menus_h +#ifndef _MENUS_H_ +#define _MENUS_H_ #define NO_HI_LEN 25 -void displayScreenIndex(uint8_t index, uint8_t count, uint8_t attr); -inline void displayColumnHeader(const char * const *headers, uint8_t index) -{ - lcd_putsAtt(17*FW, 0, headers[index], 0); -} - -#if !defined(CPUM64) - void displayScrollbar(coord_t x, coord_t y, coord_t h, uint16_t offset, uint16_t count, uint8_t visible); -#endif - -#if LCD_W >= 212 - extern coord_t scrollbar_X; - #define SET_SCROLLBAR_X(x) scrollbar_X = (x); -#else - #define SET_SCROLLBAR_X(x) -#endif - #if LCD_W >= 212 #if defined(TRANSLATIONS_FR) #define MENU_COLUMNS 1 @@ -414,14 +397,22 @@ extern uint8_t s_warning_info_len; extern uint8_t s_warning_result; extern uint8_t s_warning_type; -#define WARNING_LINE_X 16 -#define WARNING_LINE_Y 3*FH #if LCD_W >= 212 + #define MENU_X 30 + #define MENU_Y 16 #define WARNING_LINE_LEN 32 + #define WARNING_LINE_X 16 + #define WARNING_LINE_Y 3*FH #else + #define MENU_X 10 + #define MENU_Y 16 #define WARNING_LINE_LEN 20 + #define WARNING_LINE_X 16 + #define WARNING_LINE_Y 3*FH #endif +#define MENU_W LCD_W-(2*MENU_X) + void displayBox(); void displayPopup(const pm_char * pstr); void displayWarning(uint8_t event); @@ -545,4 +536,4 @@ void displayWarning(uint8_t event); typedef int16_t (*FnFuncP) (int16_t x); void DrawFunction(FnFuncP fn, uint8_t offset=0); -#endif +#endif // _MENUS_H_ diff --git a/radio/src/gui/view_about.cpp b/radio/src/gui/view_about.cpp index 90a392bfe..c994476b8 100644 --- a/radio/src/gui/view_about.cpp +++ b/radio/src/gui/view_about.cpp @@ -36,7 +36,8 @@ #include "../opentx.h" -#if defined(PCBTARANIS) +#if defined(COLORLCD) +#elif defined(PCBTARANIS) const pm_uchar about_bmp[] PROGMEM = { #include "../bitmaps/Taranis/about.lbm" }; @@ -93,7 +94,9 @@ void menuAboutView(uint8_t event) break; } -#if defined(PCBTARANIS) +#if defined(COLORLCD) + LcdFlags att = GREY(max(0, 15-greyIndex/2)); +#elif defined(PCBTARANIS) lcd_bmp(0, 0, about_bmp); lcd_putsAtt(64, 0, STR_ABOUTUS, DBLSIZE); lcd_hline(ABOUT_X, 18, 120); diff --git a/radio/src/gui/view_channels.cpp b/radio/src/gui/view_channels.cpp index ec9352901..758ca4891 100644 --- a/radio/src/gui/view_channels.cpp +++ b/radio/src/gui/view_channels.cpp @@ -59,7 +59,10 @@ void menuChannelsView(uint8_t event) else ch = 0; +#if !defined(COLORLCD) lcd_putsCenter(0*FH, CHANNELS_MONITOR); +#endif + lcd_invert_line(0); // Column separator diff --git a/radio/src/lcd.h b/radio/src/lcd.h index c6243a5ef..7b1c0fca1 100644 --- a/radio/src/lcd.h +++ b/radio/src/lcd.h @@ -40,6 +40,7 @@ #if defined(PCBTARANIS) #define LCD_W 212 #define LCD_H 64 + #define BOX_WIDTH 31 #define coord_t int #define scoord_t int #define CENTER "\015" @@ -49,6 +50,7 @@ #else #define LCD_W 128 #define LCD_H 64 + #define BOX_WIDTH 23 #define coord_t uint8_t #define scoord_t int8_t #define CENTER @@ -80,19 +82,23 @@ /* lcd text flags */ #define INVERS 0x02 -#ifdef BOLD_FONT +#if defined(BOLD_FONT) #define BOLD 0x40 #else #define BOLD 0x00 #endif /* lcd putc flags */ -#define CONDENSED 0x08 +#define CONDENSED 0x08 // TODO remove on TARANIS #define FIXEDWIDTH 0x10 /* lcd puts flags */ /* no 0x80 here because of "GV"1 which is aligned LEFT */ /* no 0x10 here because of "MODEL"01 which uses LEADING0 */ -#define BSS 0x20 +#if defined(CPUARM) + #define BSS 0x00 +#else + #define BSS 0x20 +#endif #define ZCHAR 0x80 /* lcd outdez flags */ @@ -157,7 +163,7 @@ #define display_t uint8_t #define DISPLAY_BUF_SIZE (LCD_W*LCD_H*4/8) #else - #define display_t uint8_t + #define display_t uint8_t #define DISPLAY_BUF_SIZE (LCD_W*((LCD_H+7)/8)) #endif @@ -205,15 +211,21 @@ void lcd_putsnAtt(coord_t x, coord_t y, const pm_char * s,unsigned char len, Lcd void lcd_puts(coord_t x, coord_t y, const pm_char * s); void lcd_putsn(coord_t x, coord_t y, const pm_char * s, unsigned char len); void lcd_putsLeft(coord_t y, const pm_char * s); -#define lcd_putsCenter(y, s) lcd_puts((LCD_W-sizeof(TR_##s)*FW+FW+1)/2, y, STR_##s) + +#if defined(COLORLCD) + void lcd_putsCenter(coord_t y, const pm_char * s, LcdFlags attr=0); +#else + #define lcd_putsCenter(y, s) lcd_puts((LCD_W-sizeof(TR_##s)*FW+FW+1)/2, y, STR_##s) +#endif #if defined(CPUARM) -void lcd_outhex4(coord_t x, coord_t y, uint32_t val, LcdFlags mode=0); + void lcd_outhex4(coord_t x, coord_t y, uint32_t val, LcdFlags mode=0); #else -void lcd_outhex4(coord_t x, coord_t y, uint16_t val); + void lcd_outhex4(coord_t x, coord_t y, uint16_t val); #endif -void lcd_outdezAtt(coord_t x, coord_t y, lcdint_t val, LcdFlags mode=0); + void lcd_outdezNAtt(coord_t x, coord_t y, lcdint_t val, LcdFlags mode=0, uint8_t len=0); +void lcd_outdezAtt(coord_t x, coord_t y, lcdint_t val, LcdFlags mode=0); void lcd_outdez8(coord_t x, coord_t y, int8_t val); void putsStrIdx(coord_t x, coord_t y, const pm_char *str, uint8_t idx, LcdFlags att=0); @@ -279,14 +291,10 @@ inline void lcd_square(coord_t x, coord_t y, coord_t w, LcdFlags att=0) { lcd_re void lcdDrawTelemetryTopBar(); -#define DO_CROSS(xx,yy,ww) \ - lcd_vline(xx,yy-ww/2,ww); \ - lcd_hline(xx-ww/2,yy,ww); - -#define V_BAR(xx,yy,ll) \ - lcd_vline(xx-1,yy-ll,ll); \ - lcd_vline(xx ,yy-ll,ll); \ - lcd_vline(xx+1,yy-ll,ll); +#define V_BAR(xx, yy, ll) \ + lcd_vline(xx-1,yy-ll,ll); \ + lcd_vline(xx ,yy-ll,ll); \ + lcd_vline(xx+1,yy-ll,ll); void lcd_img(coord_t x, coord_t y, const pm_uchar * img, uint8_t idx, LcdFlags att=0); @@ -328,12 +336,11 @@ void lcdInit(); extern display_t lcd_buf[DISPLAY_BUF_SIZE]; #endif -char * strAppend(char * dest, const char * source); -char * strAppendDate(char * str, bool time=false); -char * strAppendFilename(char * dest, const char * filename, const int size); +char *strAppend(char * dest, const char * source, int len=0); +char *strSetCursor(char *dest, int position); +char *strAppendDate(char * str, bool time=false); +char *strAppendFilename(char * dest, const char * filename, const int size); -#define NUM_BODY_LINES LCD_LINES-1 -#define HEIGHT_BODY_LINE FH #define MENU_TITLE_HEIGHT FH #define MENU_NAVIG_HEIGHT 0 diff --git a/radio/src/lcd_common.cpp b/radio/src/lcd_common.cpp index 2a8a5fd64..7e53be250 100644 --- a/radio/src/lcd_common.cpp +++ b/radio/src/lcd_common.cpp @@ -36,7 +36,6 @@ #include "opentx.h" - #if defined(PCBTARANIS) && defined(REVPLUS) && defined(LCD_DUAL_BUFFER) display_t displayBuf1[DISPLAY_BUF_SIZE]; display_t displayBuf2[DISPLAY_BUF_SIZE]; @@ -250,10 +249,6 @@ void lcd_putsnAtt(coord_t x, coord_t y, const pm_char * s, uint8_t len, LcdFlags lcd_putcAtt(x, y, c, flags); x = lcdNextPos; } - else if (setx) { - x = c; - setx = false; - } else if (c == 0x1F) { //X-coord prefix setx = true; } diff --git a/radio/src/main_avr.cpp b/radio/src/main_avr.cpp index 1d9eb119d..27f48fd03 100644 --- a/radio/src/main_avr.cpp +++ b/radio/src/main_avr.cpp @@ -116,7 +116,7 @@ void perMain() if (evt && (g_eeGeneral.backlightMode & e_backlight_mode_keys)) backlightOn(); // on keypress turn the light on checkBacklight(); -#if defined(FRSKY) || defined(MAVLINK) || defined(SIMU) +#if defined(FRSKY) || defined(MAVLINK) telemetryWakeup(); #endif diff --git a/radio/src/opentx.cpp b/radio/src/opentx.cpp index 7af7288e2..5491973ed 100644 --- a/radio/src/opentx.cpp +++ b/radio/src/opentx.cpp @@ -38,7 +38,8 @@ #if defined(SPLASH) const pm_uchar splashdata[] PROGMEM = { 'S','P','S',0, -#if defined(PCBTARANIS) +#if defined(COLORLCD) +#elif defined(PCBTARANIS) #include "bitmaps/Taranis/splash.lbm" #else #include "bitmaps/9X/splash.lbm" @@ -47,7 +48,8 @@ const pm_uchar splashdata[] PROGMEM = { 'S','P','S',0, const pm_uchar * const splash_lbm = splashdata+4; #endif -#if defined(PCBTARANIS) +#if defined(COLORLCD) +#elif defined(PCBTARANIS) const pm_uchar asterisk_lbm[] PROGMEM = { #include "bitmaps/Taranis/asterisk.lbm" }; @@ -76,8 +78,10 @@ void loadModelBitmap(char *name, uint8_t *bitmap) } } +#if !defined(COLORLCD) // In all error cases, we set the default logo memcpy(bitmap, logo_taranis, MODEL_BITMAP_SIZE); +#endif } #endif @@ -206,7 +210,7 @@ void per10ms() } #endif -#if defined(FRSKY) || defined(JETI) || defined(SIMU) +#if defined(FRSKY) || defined(JETI) if (!IS_DSM2_SERIAL_PROTOCOL(s_current_protocol[0])) telemetryInterrupt10ms(); #endif @@ -959,7 +963,8 @@ bool readonlyUnlocked() inline void Splash() { lcd_clear(); -#if defined(PCBTARANIS) +#if defined(COLORLCD) +#elif defined(PCBTARANIS) lcd_bmp(0, 0, splash_lbm); #else lcd_img(0, 0, splash_lbm, 0, 0); @@ -1185,7 +1190,10 @@ void message(const pm_char *title, const pm_char *t, const char *last MESSAGE_SO { lcd_clear(); -#if LCD_W >= 212 +#if defined(COLORLCD) + #define MESSAGE_LCD_OFFSET 60 + drawFilledRect(30, 20, 252, 100, SOLID, BLACK); +#elif defined(PCBTARANIS) lcd_bmp(0, 0, asterisk_lbm); #define MESSAGE_LCD_OFFSET 60 #else @@ -1193,7 +1201,10 @@ void message(const pm_char *title, const pm_char *t, const char *last MESSAGE_SO #define MESSAGE_LCD_OFFSET 6*FW #endif -#if defined(TRANSLATIONS_FR) || defined(TRANSLATIONS_IT) || defined(TRANSLATIONS_CZ) +#if defined(COLORLCD) + lcd_putsAtt(MESSAGE_LCD_OFFSET, 30, STR_WARNING, WHITE|DBLSIZE); + lcd_putsAtt(MESSAGE_LCD_OFFSET, 46, title, WHITE|DBLSIZE); +#elif defined(TRANSLATIONS_FR) || defined(TRANSLATIONS_IT) || defined(TRANSLATIONS_CZ) lcd_putsAtt(MESSAGE_LCD_OFFSET, 0, STR_WARNING, DBLSIZE); lcd_putsAtt(MESSAGE_LCD_OFFSET, 2*FH, title, DBLSIZE); #else @@ -1201,7 +1212,13 @@ void message(const pm_char *title, const pm_char *t, const char *last MESSAGE_SO lcd_putsAtt(MESSAGE_LCD_OFFSET, 2*FH, STR_WARNING, DBLSIZE); #endif -#if LCD_W >= 212 +#if defined(COLORLCD) + if (t) lcd_putsAtt(MESSAGE_LCD_OFFSET, 80, t, WHITE); + if (last) { + lcd_putsAtt(MESSAGE_LCD_OFFSET, 92, last, WHITE); + AUDIO_ERROR_MESSAGE(sound); + } +#elif LCD_W >= 212 drawFilledRect(MESSAGE_LCD_OFFSET, 0, LCD_W-MESSAGE_LCD_OFFSET, 32); if (t) lcd_puts(MESSAGE_LCD_OFFSET, 5*FH, t); if (last) { @@ -2146,10 +2163,13 @@ uint8_t getSticksNavigationEvent() void checkBattery() { static uint8_t counter = 0; +#if !defined(COLORLCD) + // TODO not the right menu I think ... if (g_menuStack[g_menuStackPtr] == menuGeneralDiagAna) { g_vbat100mV = 0; counter = 0; } +#endif if (counter-- == 0) { counter = 10; int32_t instant_vbat = anaIn(TX_VOLTAGE); diff --git a/radio/src/opentx.h b/radio/src/opentx.h index 38f0a66e8..3639b842e 100644 --- a/radio/src/opentx.h +++ b/radio/src/opentx.h @@ -667,7 +667,9 @@ extern uint8_t flightModeTransitionLast; #define bitfield_channels_t uint16_t #endif -#if defined(CPUARM) && !defined(SIMU) +#if defined(SIMU) + inline int getAvailableMemory() { return 1000; } +#elif defined(CPUARM) && !defined(SIMU) extern unsigned char *heap; extern int _end; extern int _estack; @@ -1094,7 +1096,14 @@ extern int16_t calcRESXto1000(int16_t x); extern int8_t calcRESXto100(int16_t x); #endif +#if defined(COLORLCD) extern const char vers_stamp[]; +extern const char date_stamp[]; +extern const char time_stamp[]; +extern const char eeprom_stamp[]; +#else +extern const char vers_stamp[]; +#endif extern uint8_t g_vbat100mV; #define g_blinkTmr10ms (*(uint8_t*)&g_tmr10ms) @@ -1336,6 +1345,7 @@ void evalFunctions(); extern volatile rotenc_t g_rotenc[1]; #endif +#include "gui/gui.h" #include "gui/menus.h" #if defined(CPUARM) @@ -1557,7 +1567,7 @@ void convertUnit(getvalue_t & val, uint8_t & unit); // TODO check FORCEINLINE on #if defined(CPUARM) uint8_t zlen(const char *str, uint8_t size); bool zexist(const char *str, uint8_t size); -char * strcat_zchar(char * dest, char * name, uint8_t size, const char *defaultName, uint8_t defaultNameSize, uint8_t defaultIdx); +char * strcat_zchar(char *dest, const char *name, uint8_t size, const char *defaultName=NULL, uint8_t defaultNameSize=0, uint8_t defaultIdx=0); #define strcat_modelname(dest, idx) strcat_zchar(dest, modelHeaders[idx].name, LEN_MODEL_NAME, STR_MODEL, PSIZE(TR_MODEL), idx+1) #define strcat_phasename(dest, idx) strcat_zchar(dest, g_model.flightModeData[idx].name, LEN_FLIGHT_MODE_NAME, STR_FP, PSIZE(TR_FP), idx+1) #define ZLEN(s) zlen(s, sizeof(s)) diff --git a/radio/src/simu.cpp b/radio/src/simu.cpp index abdcd25b7..aba58a0d6 100644 --- a/radio/src/simu.cpp +++ b/radio/src/simu.cpp @@ -43,8 +43,10 @@ #include #include -#define W2 LCD_W*2 -#define H2 LCD_H*2 +#define LCD_ZOOM 2 + +#define W2 LCD_W*LCD_ZOOM +#define H2 LCD_H*LCD_ZOOM int g_snapshot_idx = 0; @@ -61,6 +63,7 @@ class Open9xSim: public FXMainWindow void makeSnapshot(const FXDrawable* drawable); void doEvents(); void refreshDisplay(); + void setPixel(int x, int y, FXColor color); private: FXImage *bmp; @@ -192,7 +195,7 @@ long Open9xSim::onKeypress(FXObject*,FXSelector,void*v) { FXEvent *evt=(FXEvent*)v; // printf("keypress %x\n", evt->code); - if (evt->code=='s'){ + if (evt->code=='s') { makeSnapshot(bmf); } return 0; @@ -332,6 +335,15 @@ long Open9xSim::onTimeout(FXObject*, FXSelector, void*) #define BL_COLOR FXRGB(150,200,152) #endif +void Open9xSim::setPixel(int x, int y, FXColor color) +{ + for (int i=0; isetPixel(LCD_ZOOM*x+i, LCD_ZOOM*y+j, color); + } + } +} + void Open9xSim::refreshDisplay() { if (lcd_refresh) { @@ -351,24 +363,15 @@ void Open9xSim::refreshDisplay() color = FXRGB(47-(z*47)/15, 123-(z*123)/15, 227-(z*227)/15); else color = FXRGB(200-(z*200)/15, 200-(z*200)/15, 200-(z*200)/15); - bmp->setPixel(2*x, 2*y, color); - bmp->setPixel(2*x+1, 2*y, color); - bmp->setPixel(2*x, 2*y+1, color); - bmp->setPixel(2*x+1, 2*y+1, color); + setPixel(x, y, color); } #else if (lcd_buf[x+(y/8)*LCD_W] & (1<<(y%8))) { - bmp->setPixel(2*x, 2*y, onColor); - bmp->setPixel(2*x+1, 2*y, onColor); - bmp->setPixel(2*x, 2*y+1, onColor); - bmp->setPixel(2*x+1, 2*y+1, onColor); + setPixel(x, y, onColor); } #endif else { - bmp->setPixel(2*x, 2*y, offColor); - bmp->setPixel(2*x+1, 2*y, offColor); - bmp->setPixel(2*x, 2*y+1, offColor); - bmp->setPixel(2*x+1, 2*y+1, offColor); + setPixel(x, y, offColor); } } } diff --git a/radio/src/stamp.cpp b/radio/src/stamp.cpp index 8cd446cfb..6bbd73037 100644 --- a/radio/src/stamp.cpp +++ b/radio/src/stamp.cpp @@ -46,4 +46,11 @@ #define EEPROM_STR DEFNUMSTR(EEPROM_VER); #endif -const pm_char vers_stamp[] PROGMEM = "VERS\037\033: " "opentx-" FLAVOUR "-" VERS_STR "\036DATE\037\033: " DATE_STR"\036TIME\037\033: " TIME_STR "\036EEPR\037\033: " EEPROM_STR; +#if defined(COLORLCD) + const pm_char vers_stamp[] PROGMEM = "VERS\037\050: " "opentx-" FLAVOUR "-" VERS_STR; + const pm_char date_stamp[] PROGMEM = "DATE\037\050: " DATE_STR; + const pm_char time_stamp[] PROGMEM = "TIME\037\050: " TIME_STR; + const pm_char eeprom_stamp[] PROGMEM = "EEPR\037\050: " EEPROM_STR; +#else + const pm_char vers_stamp[] PROGMEM = "VERS\037\033: " "opentx-" FLAVOUR "-" VERS_STR "\036DATE\037\033: " DATE_STR"\036TIME\037\033: " TIME_STR "\036EEPR\037\033: " EEPROM_STR; +#endif diff --git a/radio/src/strhelpers.cpp b/radio/src/strhelpers.cpp index 21c6d8fbc..856a67e7b 100644 --- a/radio/src/strhelpers.cpp +++ b/radio/src/strhelpers.cpp @@ -116,7 +116,7 @@ uint8_t zlen(const char *str, uint8_t size) return size; } -char * strcat_zchar(char * dest, char * name, uint8_t size, const char *defaultName, uint8_t defaultNameSize, uint8_t defaultIdx) +char *strcat_zchar(char * dest, const char * name, uint8_t size, const char *defaultName, uint8_t defaultNameSize, uint8_t defaultIdx) { int8_t len = 0; @@ -151,14 +151,36 @@ char * strcat_zchar(char * dest, char * name, uint8_t size, const char *defaultN #endif #endif -#if defined(CPUARM) || defined(SDCARD) -char * strAppend(char * dest, const char * source) +#if defined(COLORLCD) +char *strAppendDigits(char *dest, int value) { - while ((*dest++ = *source++)) - ; + div_t qr = div(value, 10); + *dest++ = '0' + qr.quot; + *dest++ = '0' + qr.rem; + *dest = '\0'; + return dest; +} +#endif + +#if defined(CPUARM) || defined(SDCARD) +char *strAppend(char *dest, const char *source, int len) +{ + while ((*dest++ = *source++)) { + if (--len == 0) { + *dest++ = '\0'; + } + } return dest - 1; } +char *strSetCursor(char *dest, int position) +{ + *dest++ = 0x1F; + *dest++ = position; + *dest = '\0'; + return dest; +} + char * strAppendFilename(char * dest, const char * filename, const int size) { memset(dest, 0, size); diff --git a/radio/src/translations/en.h.txt b/radio/src/translations/en.h.txt index afcc4c103..25652f2ff 100644 --- a/radio/src/translations/en.h.txt +++ b/radio/src/translations/en.h.txt @@ -444,9 +444,9 @@ #endif #if defined(CPUARM) - #define TR_LOGICALSW "L1\0""L2\0""L3\0""L4\0""L5\0""L6\0""L7\0""L8\0""L9\0""L10""L11""L12""L13""L14""L15""L16""L17""L18""L19""L20""L21""L22""L23""L24""L25""L26""L27""L28""L29""L30""L31""L32" + #define TR_LOGICALSW "L1\0""L2\0""L3\0""L4\0""L5\0""L6\0""L7\0""L8\0""L9\0""L10""L11""L12""L13""L14""L15""L16""L17""L18""L19""L20""L21""L22""L23""L24""L25""L26""L27""L28""L29""L30""L31""L32" #else - #define TR_LOGICALSW "L1\0""L2\0""L3\0""L4\0""L5\0""L6\0""L7\0""L8\0""L9\0""L10""L11""L12" + #define TR_LOGICALSW "L1\0""L2\0""L3\0""L4\0""L5\0""L6\0""L7\0""L8\0""L9\0""L10""L11""L12" #endif #define TR_TRIMS_SWITCHES "tRl""tRr""tEd""tEu""tTd""tTu""tAl""tAr" @@ -515,9 +515,15 @@ #endif // ZERO TERMINATED STRINGS -#define INDENT "\001" -#define LEN_INDENT 1 -#define INDENT_WIDTH (FW/2) +#if defined(COLORLCD) + #define INDENT "\007" + #define LEN_INDENT 1 + #define INDENT_WIDTH 12 +#else + #define INDENT "\001" + #define LEN_INDENT 1 + #define INDENT_WIDTH (FW/2) +#endif #if defined(PCBTARANIS) #define TR_ENTER "[ENTER]" @@ -649,9 +655,15 @@ #define TR_CAL "Cal" #define TR_VTRIM "Trim- +" #define TR_BG "BG:" -#define TR_MENUTOSTART CENTER "\010" TR_ENTER " TO START" -#define TR_SETMIDPOINT TR(CENTER "\004SET STICKS MIDPOINT",CENTER "\004CENTER STICKS/SLIDERS") -#define TR_MOVESTICKSPOTS CENTER "\006MOVE STICKS/POTS" +#if defined(COLORLCD) + #define TR_MENUTOSTART TR_ENTER " TO START" + #define TR_SETMIDPOINT "CENTER STICKS/SLIDERS" + #define TR_MOVESTICKSPOTS "MOVE STICKS/POTS" +#else + #define TR_MENUTOSTART CENTER "\010" TR_ENTER " TO START" + #define TR_SETMIDPOINT TR(CENTER "\004SET STICKS MIDPOINT", CENTER "\004CENTER STICKS/SLIDERS") + #define TR_MOVESTICKSPOTS CENTER "\006MOVE STICKS/POTS" +#endif #define TR_RXBATT "Rx Batt:" #define TR_TXnRX "Tx:\0Rx:" #define OFS_RX 4 @@ -694,11 +706,21 @@ #define TR_MENUDIAG TR("SWITCHES","SWITCH TEST") #define TR_MENUANA TR("ANAS","ANALOG INPUTS") #define TR_MENUCALIBRATION "CALIBRATION" -#define TR_TRIMS2OFFSETS "\006Trims => Subtrims" -#define TR_MENUMODELSEL TR("MODELSEL","MODEL SELECTION") -#define TR_MENUSETUP TR("SETUP","MODEL SETUP") +#if defined(COLORLCD) + #define TR_TRIMS2OFFSETS "Trims >> Subtrims" +#else + #define TR_TRIMS2OFFSETS "\006Trims => Subtrims" +#endif +#if defined(COLORLCD) + #define TR_MENUMODELSEL "Model Selection" + #define TR_MENUSETUP "Model Setup" + #define TR_MENUFLIGHTPHASES "Flight Modes" +#else + #define TR_MENUMODELSEL TR("MODELSEL", "MODEL SELECTION") + #define TR_MENUSETUP TR("SETUP", "MODEL SETUP") + #define TR_MENUFLIGHTPHASES "FLIGHT MODES" +#endif #define TR_MENUFLIGHTPHASE "FLIGHT MODE" -#define TR_MENUFLIGHTPHASES "FLIGHT MODES" #define TR_MENUHELISETUP "HELI SETUP" #if defined(PCBTARANIS) diff --git a/radio/util/font2png.py b/radio/util/font2png.py index 589f291ac..f322dc0e5 100755 --- a/radio/util/font2png.py +++ b/radio/util/font2png.py @@ -3,37 +3,47 @@ import sys from PyQt4 import Qt, QtGui -from wx import Width -chars = u""" !"#$%&'()*+, ./0123456789:;<=>?°ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|} """ +chars = u""" !"#$%&'()*+,-./0123456789:;<=>?°ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz~ ≥→←↑↓ △Ⓘ""" font = sys.argv[1] size = int(sys.argv[2]) -filename = sys.argv[3] app = QtGui.QApplication(sys.argv) font = QtGui.QFont(font) -font.setBold(True) font.setPointSize(size) metrics = QtGui.QFontMetrics(font) -width = 0 -for c in chars: - rect = metrics.boundingRect(c) - if rect.width() > width: - width = rect.width() +def getCharWidth(): + width = 0 + for c in chars: + rect = metrics.boundingRect(c) + if rect.width() > width: + width = rect.width() + return width -image = QtGui.QImage(width*len(chars), size+4, QtGui.QImage.Format_RGB32) -image.fill(0xffffff) -painter = QtGui.QPainter() -painter.begin(image) -painter.setFont(font) -for i, c in enumerate(chars): - rect = metrics.boundingRect(c) - if i == 0: - rect.setWidth(4) - painter.drawText(width*i-rect.left(), size+1, c) - for j in range(rect.width(), width): - painter.drawLine(width*i+j, 0, width*i+j, width) -painter.end() -image.save(filename) +width = getCharWidth() + +def createFontBitmap(filename, foreground, background): + image = QtGui.QImage(width*len(chars), size+4, QtGui.QImage.Format_RGB32) + image.fill(background) + painter = QtGui.QPainter() + painter.begin(image) + painter.setFont(font) + pen = QtGui.QPen(foreground) + painter.setPen(pen) + for i, c in enumerate(chars): + rect = metrics.boundingRect(c) + if i == 0: + rect.setWidth(4) + elif i == 14: + rect.setLeft(rect.left()+1) + rect.setWidth(1) + painter.drawText(width*i-rect.left(), size+1, c) + for j in range(rect.width(), width): + painter.drawLine(width*i+j, 0, width*i+j, size+4) + painter.end() + image.save(filename) + +if len(sys.argv) == 4: + createFontBitmap(sys.argv[3], QtGui.QColor(0x00, 0x00, 0x00), QtGui.QColor(0xFF, 0xFF, 0xFF))