Horus simulator should now be OK
This commit is contained in:
+334
-39
@@ -409,7 +409,7 @@ LUADEP =
|
||||
DEBUG_TRACE_BUFFER = NO
|
||||
|
||||
# MCU name
|
||||
ifneq ($(PCB), $(filter $(PCB), STD 9X 9XR STD128 9X128 9XR128 9X2561 9XR2561 GRUVIN9X MEGA2560 SKY9X 9XRPRO AR9X TARANIS))
|
||||
ifneq ($(PCB), $(filter $(PCB), STD 9X 9XR STD128 9X128 9XR128 9X2561 9XR2561 GRUVIN9X MEGA2560 SKY9X 9XRPRO AR9X TARANIS FLAMENCO HORUS))
|
||||
$(error Sorry, the PCB $(PCB) is not supported yet in OpenTX)
|
||||
endif
|
||||
|
||||
@@ -424,7 +424,7 @@ EEPROM_VARIANT = 0
|
||||
GUIMODELSRC = gui/$(GUIDIRECTORY)/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/$(GUIDIRECTORY)/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
|
||||
BITMAPS = bitmaps/sticks.lbm
|
||||
|
||||
FONTS = $(patsubst %.png,%.lbm,$(wildcard fonts/std/*.png))
|
||||
|
||||
@@ -439,7 +439,7 @@ ifeq ($(PCB), $(filter $(PCB), STD 9X 9XR))
|
||||
SDCARD = NO
|
||||
THR_TRACE = NO
|
||||
INCDIRS += targets/stock
|
||||
CPPDEFS = -DF_CPU=$(F_CPU)UL -DPCBSTD -DCPUM64 -DEEPROM_RLC -DEEPROM_VARIANT=$(shell echo ${EEPROM_VARIANT} | bc)
|
||||
CPPDEFS = -DF_CPU=$(F_CPU)UL -DPCBSTD -DCPUM64 -DEEPROM -DEEPROM_RLC -DEEPROM_VARIANT=$(shell echo ${EEPROM_VARIANT} | bc)
|
||||
BOARDSRC = main_avr.cpp targets/stock/board_stock.cpp
|
||||
EXTRABOARDSRC = targets/common_avr/adc_driver.cpp targets/common_avr/telemetry_driver.cpp
|
||||
ifeq ($(GUI), YES)
|
||||
@@ -520,7 +520,7 @@ ifeq ($(PCB), $(filter $(PCB), STD128 9X128 9XR128))
|
||||
SDCARD = NO
|
||||
THR_TRACE = NO
|
||||
EEPROM_VARIANT += ${M128_VARIANT}
|
||||
CPPDEFS = -DF_CPU=$(F_CPU)UL -DPCBSTD -DCPUM128 -DEEPROM_RLC -DEEPROM_VARIANT=$(shell echo ${EEPROM_VARIANT} | bc)
|
||||
CPPDEFS = -DF_CPU=$(F_CPU)UL -DPCBSTD -DCPUM128 -DEEPROM -DEEPROM_RLC -DEEPROM_VARIANT=$(shell echo ${EEPROM_VARIANT} | bc)
|
||||
INCDIRS += targets/stock
|
||||
BOARDSRC = main_avr.cpp targets/stock/board_stock.cpp
|
||||
EXTRABOARDSRC = targets/common_avr/adc_driver.cpp targets/stock/lcd_driver.cpp targets/common_avr/telemetry_driver.cpp
|
||||
@@ -595,7 +595,7 @@ ifeq ($(PCB), $(filter $(PCB), 9X2561))
|
||||
SDCARD = NO
|
||||
THR_TRACE = YES
|
||||
EEPROM_VARIANT += ${M2561_VARIANT}
|
||||
CPPDEFS = -DF_CPU=$(F_CPU)UL -DPCBSTD -DCPUM2561 -DEEPROM_RLC -DEEPROM_VARIANT=$(shell echo ${EEPROM_VARIANT} | bc)
|
||||
CPPDEFS = -DF_CPU=$(F_CPU)UL -DPCBSTD -DCPUM2561 -DEEPROM -DEEPROM_RLC -DEEPROM_VARIANT=$(shell echo ${EEPROM_VARIANT} | bc)
|
||||
INCDIRS += targets/stock
|
||||
BOARDSRC = main_avr.cpp targets/stock/board_stock.cpp
|
||||
EXTRABOARDSRC = targets/common_avr/adc_driver.cpp targets/stock/lcd_driver.cpp targets/common_avr/telemetry_driver.cpp
|
||||
@@ -665,7 +665,7 @@ ifeq ($(PCB), GRUVIN9X)
|
||||
TRGT = avr-
|
||||
MCU = atmega2560
|
||||
OPT = s
|
||||
CPPDEFS += -DF_CPU=$(F_CPU)UL -DPCBGRUVIN9X -DCPUM2560 -DEEPROM_RLC -DEEPROM_VARIANT=0 -DAUDIO -DHAPTIC
|
||||
CPPDEFS += -DF_CPU=$(F_CPU)UL -DPCBGRUVIN9X -DCPUM2560 -DEEPROM -DEEPROM_RLC -DEEPROM_VARIANT=0 -DAUDIO -DHAPTIC
|
||||
SDCARD = NO
|
||||
BUZZER = NO
|
||||
THR_TRACE = YES
|
||||
@@ -710,7 +710,7 @@ ifeq ($(PCB), MEGA2560)
|
||||
TRGT = avr-
|
||||
MCU = atmega2560
|
||||
OPT = s
|
||||
CPPDEFS = -DF_CPU=$(F_CPU)UL -DPCBMEGA2560 -DCPUM2560 -DEEPROM_RLC -DEEPROM_VARIANT=0 -DAUDIO
|
||||
CPPDEFS = -DF_CPU=$(F_CPU)UL -DPCBMEGA2560 -DCPUM2560 -DEEPROM -DEEPROM_RLC -DEEPROM_VARIANT=0 -DAUDIO
|
||||
SDCARD = NO
|
||||
BUZZER = YES
|
||||
THR_TRACE = YES
|
||||
@@ -769,7 +769,7 @@ ifeq ($(PCB), $(filter $(PCB), SKY9X 9XRPRO AR9X))
|
||||
GUIDIRECTORY = 9X
|
||||
ARCH = ARM
|
||||
LCDSIZE = 128
|
||||
CPPDEFS = -Dat91sam3s4
|
||||
CPPDEFS = -Dat91sam3s4 -DPPM_PIN_HW_SERIAL
|
||||
ifeq ($(PCB), 9XRPRO)
|
||||
CPPDEFS = -Dat91sam3s8
|
||||
FLAVOUR = 9xrpro
|
||||
@@ -803,7 +803,7 @@ ifeq ($(PCB), $(filter $(PCB), SKY9X 9XRPRO AR9X))
|
||||
BUZZER = NO
|
||||
THR_TRACE = YES
|
||||
EXT = FRSKY_SPORT
|
||||
CPPDEFS += -DPCBSKY9X -DCPUARM -DEEPROM_VARIANT=0 -DAUDIO -DHAPTIC -DDSM2 -DDSM2_PPM -DPXX
|
||||
CPPDEFS += -DPCBSKY9X -DCPUARM -DEEPROM -DEEPROM_VARIANT=0 -DAUDIO -DHAPTIC -DDSM2 -DDSM2_PPM -DPXX
|
||||
ifeq ($(PCB), SKY9X)
|
||||
CPPDEFS += -DROTARY_ENCODERS=1
|
||||
CPPSRC += targets/sky9x/rotenc_driver.cpp
|
||||
@@ -926,7 +926,7 @@ ifeq ($(PCB), TARANIS)
|
||||
PPM_LIMITS_SYMETRICAL = YES
|
||||
PPM_CENTER_ADJUSTABLE = YES
|
||||
DSM2 = PPM
|
||||
CPPDEFS += -DPCBTARANIS -DCPUARM -DCPUSTM32 -DVIRTUALINPUTS -DLUAINPUTS -DXCURVES -DEEPROM_RLC -DAUDIO -DPXX
|
||||
CPPDEFS += -DPCBTARANIS -DCPUARM -DCPUSTM32 -DVIRTUALINPUTS -DLUAINPUTS -DXCURVES -DEEPROM -DEEPROM_RLC -DAUDIO -DPXX
|
||||
INCDIRS += targets/taranis $(THIRDPARTY) $(COOSDIR) $(COOSDIR)/kernel $(COOSDIR)/portable
|
||||
CPPDEFS += -DHSE_VALUE=12000000
|
||||
ifeq ($(PCBREV), REV9E)
|
||||
@@ -1029,7 +1029,7 @@ ifeq ($(PCB), TARANIS)
|
||||
$(LUADIR)/lobject.c $(LUADIR)/lopcodes.c $(LUADIR)/lparser.c $(LUADIR)/lstate.c $(LUADIR)/lstring.c $(LUADIR)/ltable.c $(LUADIR)/lrotable.c $(LUADIR)/ltm.c $(LUADIR)/lundump.c $(LUADIR)/lvm.c $(LUADIR)/lzio.c \
|
||||
$(LUADIR)/lbaselib.c $(LUADIR)/linit.c $(LUADIR)/lmathlib.c $(LUADIR)/lbitlib.c $(LUADIR)/loadlib.c $(LUADIR)/lauxlib.c $(LUADIR)/ltablib.c $(LUADIR)/lcorolib.c $(LUADIR)/liolib.c
|
||||
SRC += $(LUASRC)
|
||||
LUADEP = lua_exports.inc
|
||||
LUADEP = lua_exports_taranis.inc
|
||||
ifeq ($(USE_BIN_ALLOCATOR), YES)
|
||||
CPPDEFS += -DUSE_BIN_ALLOCATOR
|
||||
CPPSRC += bin_allocator.cpp
|
||||
@@ -1061,6 +1061,257 @@ ifeq ($(PCB), TARANIS)
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(PCB), FLAMENCO)
|
||||
# FLAMENCO radio
|
||||
ARCH = ARM
|
||||
LCDSIZE = 320
|
||||
GUIDIRECTORY = Flamenco
|
||||
FLAVOUR = FLAMENCO
|
||||
LDSCRIPT = targets/Flamenco/stm32f4_flash.ld
|
||||
STM32LIBPATH = $(THIRDPARTY)/STM32F4xx_DSP_StdPeriph_Lib_V1.4.0/Libraries
|
||||
STM32USBPATH = $(THIRDPARTY)/STM32_USB-Host-Device_Lib_V2.1.0/Libraries
|
||||
TRGT = arm-none-eabi-
|
||||
MCU = cortex-m4
|
||||
OPT = 2
|
||||
CPPDEFS += -DHSE_VALUE=12000000 -DCOLORLCD -DSTM32F40_41xxx
|
||||
BITMAPS += $(patsubst %.png,%.lbm,$(wildcard bitmaps/Flamenco/*.png))
|
||||
FONTS = fonts/font_stdsize.lbm fonts/font_tinsize.lbm fonts/font_smlsize.lbm fonts/font_midsize.lbm fonts/font_dblsize.lbm fonts/font_xxlsize.lbm
|
||||
SDCARD = YES
|
||||
THR_TRACE = YES
|
||||
EXT = FRSKY_SPORT
|
||||
AUTOSWITCH = YES
|
||||
AUTOSOURCE = YES
|
||||
DBLKEYS = YES
|
||||
PPM_LIMITS_SYMETRICAL = YES
|
||||
PPM_CENTER_ADJUSTABLE = YES
|
||||
DSM2 = PPM
|
||||
TIMERS = 2
|
||||
CPPDEFS += -DTIMERS=$(TIMERS)
|
||||
CPPDEFS += -DPCBFLAMENCO -DCPUARM -DCPUSTM32 -DEEPROM -DVIRTUALINPUTS -DLUAINPUTS -DXCURVES -DEEPROM_VARIANT=0 -DAUDIO -DPXX
|
||||
INCDIRS += targets/Flamenco $(THIRDPARTY) $(COOSDIR) $(COOSDIR)/kernel $(COOSDIR)/portable
|
||||
INCDIRS += $(STM32LIBPATH)/STM32F4xx_StdPeriph_Driver/inc $(STM32LIBPATH)/CMSIS/Device/ST/STM32F4xx/Include $(STM32LIBPATH)/CMSIS/include
|
||||
STM32USBPATH = $(THIRDPARTY)/STM32_USB-Host-Device_Lib_V2.1.0/Libraries
|
||||
INCDIRS += $(STM32USBPATH)/STM32_USB_OTG_Driver/inc
|
||||
INCDIRS += $(STM32USBPATH)/STM32_USB_Device_Library/Core/inc
|
||||
INCDIRS += $(STM32USBPATH)/STM32_USB_Device_Library/Class/msc/inc
|
||||
INCDIRS += $(STM32USBPATH)/STM32_USB_Device_Library/Class/hid/inc
|
||||
INCDIRS += $(STM32USBPATH)/STM32_USB_Device_Library/Class/cdc/inc
|
||||
BOARDSRC = main_arm.cpp targets/Flamenco/board_flamenco.cpp
|
||||
EXTRABOARDSRC += targets/Flamenco/lcd_driver.cpp targets/Flamenco/delays.c targets/Flamenco/i2c_driver.cpp targets/taranis/configure_pins.cpp serial.cpp # targets/taranis/flash_driver.cpp
|
||||
SRC += $(COOSDIR)/kernel/core.c $(COOSDIR)/kernel/hook.c $(COOSDIR)/kernel/task.c $(COOSDIR)/kernel/event.c $(COOSDIR)/kernel/time.c $(COOSDIR)/kernel/timer.c $(COOSDIR)/kernel/flag.c $(COOSDIR)/kernel/mutex.c $(COOSDIR)/kernel/serviceReq.c $(COOSDIR)/portable/GCC/port.c $(COOSDIR)/portable/arch.c
|
||||
SRC += targets/Flamenco/pwr_driver.c targets/Flamenco/usb_driver.c
|
||||
EEPROMSRC = eeprom_common.cpp eeprom_raw.cpp
|
||||
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/Flamenco/tw8823_driver.cpp targets/Flamenco/pulses_driver.cpp targets/Flamenco/keys_driver.cpp targets/Flamenco/adc_driver.cpp targets/Flamenco/eeprom_driver.cpp targets/Flamenco/trainer_driver.cpp targets/Flamenco/audio_driver.cpp targets/Flamenco/serial2_driver.cpp targets/Flamenco/telemetry_driver.cpp
|
||||
CPPSRC += gui/$(GUIDIRECTORY)/view_channels.cpp gui/$(GUIDIRECTORY)/view_about.cpp gui/$(GUIDIRECTORY)/view_text.cpp debug.cpp
|
||||
SRC += targets/Flamenco/system_stm32f4xx.c
|
||||
SRC += $(STM32LIBPATH)/STM32F4xx_StdPeriph_Driver/src/misc.c
|
||||
SRC += $(STM32LIBPATH)/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_gpio.c
|
||||
SRC += $(STM32LIBPATH)/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_dbgmcu.c
|
||||
SRC += $(STM32LIBPATH)/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_rcc.c
|
||||
SRC += $(STM32LIBPATH)/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_spi.c
|
||||
SRC += $(STM32LIBPATH)/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_i2c.c
|
||||
SRC += $(STM32LIBPATH)/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_dma.c
|
||||
SRC += $(STM32LIBPATH)/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_rtc.c
|
||||
SRC += $(STM32LIBPATH)/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_pwr.c
|
||||
SRC += $(STM32LIBPATH)/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_usart.c
|
||||
SRC += $(STM32LIBPATH)/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_sdio.c
|
||||
SRC += $(STM32LIBPATH)/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc_ride7/startup_stm32f40_41xxx.s
|
||||
SRC += targets/Flamenco/sdio_sd.c targets/Flamenco/usb_bsp.c targets/Flamenco/usbd_desc.c
|
||||
SRC += $(STM32USBPATH)/STM32_USB_OTG_Driver/src/usb_core.c
|
||||
SRC += $(STM32USBPATH)/STM32_USB_OTG_Driver/src/usb_dcd.c
|
||||
SRC += $(STM32USBPATH)/STM32_USB_OTG_Driver/src/usb_dcd_int.c
|
||||
SRC += $(STM32USBPATH)/STM32_USB_Device_Library/Core/src/usbd_core.c
|
||||
SRC += $(STM32USBPATH)/STM32_USB_Device_Library/Core/src/usbd_ioreq.c
|
||||
SRC += $(STM32USBPATH)/STM32_USB_Device_Library/Core/src/usbd_req.c
|
||||
EXTRABOARDSRC += targets/Flamenco/usbd_usr.cpp
|
||||
SRC += syscalls.c
|
||||
ifeq ($(USB), JOYSTICK)
|
||||
CPPDEFS += -DUSB_JOYSTICK
|
||||
SRC += targets/Flamenco/usbd_hid_joystick.c
|
||||
else
|
||||
CPPDEFS += -DUSB_MASS_STORAGE
|
||||
SRC += $(STM32USBPATH)/STM32_USB_Device_Library/Class/msc/src/usbd_msc_data.c
|
||||
SRC += $(STM32USBPATH)/STM32_USB_Device_Library/Class/msc/src/usbd_msc_scsi.c
|
||||
SRC += $(STM32USBPATH)/STM32_USB_Device_Library/Class/msc/src/usbd_msc_bot.c
|
||||
SRC += $(STM32USBPATH)/STM32_USB_Device_Library/Class/msc/src/usbd_msc_core.c
|
||||
EXTRABOARDSRC += targets/Flamenco/usbd_storage_msd.cpp
|
||||
endif
|
||||
ifeq ($(GVARS), YES)
|
||||
GUIMODELSRC += gui/$(GUIDIRECTORY)/menu_model_gvars.cpp
|
||||
endif
|
||||
ifneq ($(LUA), NO)
|
||||
ifeq ($(LUA), YES)
|
||||
CPPDEFS += -DLUA_MODEL_SCRIPTS
|
||||
endif
|
||||
CPPDEFS += -DLUA
|
||||
INCDIRS += $(LUADIR)
|
||||
CPPSRC += lua_api.cpp
|
||||
LUASRC = $(LUADIR)/lapi.c $(LUADIR)/lcode.c $(LUADIR)/lctype.c $(LUADIR)/ldebug.c $(LUADIR)/ldo.c $(LUADIR)/ldump.c $(LUADIR)/lfunc.c $(LUADIR)/lgc.c $(LUADIR)/llex.c $(LUADIR)/lmem.c \
|
||||
$(LUADIR)/lobject.c $(LUADIR)/lopcodes.c $(LUADIR)/lparser.c $(LUADIR)/lstate.c $(LUADIR)/lstring.c $(LUADIR)/ltable.c $(LUADIR)/lrotable.c $(LUADIR)/ltm.c $(LUADIR)/lundump.c $(LUADIR)/lvm.c $(LUADIR)/lzio.c \
|
||||
$(LUADIR)/lbaselib.c $(LUADIR)/linit.c $(LUADIR)/lmathlib.c $(LUADIR)/lbitlib.c $(LUADIR)/loadlib.c $(LUADIR)/lauxlib.c $(LUADIR)/ltablib.c $(LUADIR)/lcorolib.c $(LUADIR)/liolib.c
|
||||
SRC += $(LUASRC)
|
||||
LUADEP = lua_exports_flamenco.inc
|
||||
endif
|
||||
|
||||
EXTRABOARDSRC += $(FATFSDIR)/ff.c $(FATFSDIR)/fattime.c $(FATFSDIR)/option/ccsbcs.c targets/Flamenco/diskio.cpp
|
||||
CPPDEFS += -DSDCARD -DVOICE -DRTCLOCK
|
||||
CPPSRC += sdcard.cpp rtc.cpp logs.cpp targets/taranis/rtc_driver.cpp
|
||||
GUIGENERALSRC += gui/$(GUIDIRECTORY)/menu_general_sdmanager.cpp
|
||||
INCDIRS += $(FATFSDIR) $(FATFSDIR)/option
|
||||
|
||||
ifeq ($(DSM2), PPM)
|
||||
CPPSRC += pulses/dsm2_arm.cpp
|
||||
endif
|
||||
|
||||
CPPDEFS += -DHAPTIC
|
||||
CPPSRC += haptic.cpp
|
||||
CPPSRC += targets/Flamenco/haptic_driver.cpp
|
||||
EXTRABOARDSRC +=
|
||||
|
||||
ifeq ($(TW8823_TRACES), YES)
|
||||
CPPDEFS += -DTW8823_TRACES
|
||||
endif
|
||||
|
||||
ifeq ($(TW8823_BITMAPS), YES)
|
||||
CPPDEFS += -DTW8823_BITMAPS
|
||||
endif
|
||||
|
||||
ifeq ($(TW8823_SERIAL), YES)
|
||||
CPPDEFS += -DTW8823_SERIAL
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(PCB), HORUS)
|
||||
# HORUS radio
|
||||
ARCH = ARM
|
||||
LCDSIZE = 320
|
||||
GUIDIRECTORY = Horus
|
||||
FLAVOUR = HORUS
|
||||
LDSCRIPT = targets/Horus/stm32f4_flash.ld
|
||||
STM32LIBPATH = $(THIRDPARTY)/STM32F4xx_DSP_StdPeriph_Lib_V1.4.0/Libraries
|
||||
STM32USBPATH = $(THIRDPARTY)/STM32_USB-Host-Device_Lib_V2.1.0/Libraries
|
||||
TRGT = arm-none-eabi-
|
||||
MCU = cortex-m4
|
||||
OPT = 2
|
||||
CPPDEFS += -DHSE_VALUE=12000000 -DCOLORLCD -DSTM32F429_439xx
|
||||
BITMAPS += $(patsubst %.png,%.lbm,$(wildcard bitmaps/Horus/*.png))
|
||||
FONTS = fonts/font_stdsize.lbm fonts/font_tinsize.lbm fonts/font_smlsize.lbm fonts/font_midsize.lbm fonts/font_dblsize.lbm fonts/font_xxlsize.lbm
|
||||
SDCARD = YES
|
||||
THR_TRACE = YES
|
||||
EXT = FRSKY_SPORT
|
||||
AUTOSWITCH = YES
|
||||
AUTOSOURCE = YES
|
||||
DBLKEYS = YES
|
||||
PPM_LIMITS_SYMETRICAL = YES
|
||||
PPM_CENTER_ADJUSTABLE = YES
|
||||
DSM2 = PPM
|
||||
TIMERS = 2
|
||||
CPPDEFS += -DTIMERS=$(TIMERS)
|
||||
CPPDEFS += -DPCBHORUS -DCPUARM -DCPUSTM32 -DVIRTUALINPUTS -DLUAINPUTS -DXCURVES -DEEPROM_VARIANT=0 -DAUDIO -DPXX
|
||||
INCDIRS += targets/Horus $(THIRDPARTY) $(COOSDIR) $(COOSDIR)/kernel $(COOSDIR)/portable
|
||||
INCDIRS += $(STM32LIBPATH)/STM32F4xx_StdPeriph_Driver/inc $(STM32LIBPATH)/CMSIS/Device/ST/STM32F4xx/Include $(STM32LIBPATH)/CMSIS/include
|
||||
STM32USBPATH = $(THIRDPARTY)/STM32_USB-Host-Device_Lib_V2.1.0/Libraries
|
||||
INCDIRS += $(STM32USBPATH)/STM32_USB_OTG_Driver/inc
|
||||
INCDIRS += $(STM32USBPATH)/STM32_USB_Device_Library/Core/inc
|
||||
INCDIRS += $(STM32USBPATH)/STM32_USB_Device_Library/Class/msc/inc
|
||||
INCDIRS += $(STM32USBPATH)/STM32_USB_Device_Library/Class/hid/inc
|
||||
INCDIRS += $(STM32USBPATH)/STM32_USB_Device_Library/Class/cdc/inc
|
||||
BOARDSRC = main_arm.cpp targets/Horus/board_horus.cpp targets/Horus/led_driver.cpp
|
||||
EXTRABOARDSRC += targets/Horus/lcd_driver.cpp targets/Horus/delays.c targets/Horus/i2c_driver.cpp targets/taranis/configure_pins.cpp serial.cpp # targets/taranis/flash_driver.cpp
|
||||
SRC += $(COOSDIR)/kernel/core.c $(COOSDIR)/kernel/hook.c $(COOSDIR)/kernel/task.c $(COOSDIR)/kernel/event.c $(COOSDIR)/kernel/time.c $(COOSDIR)/kernel/timer.c $(COOSDIR)/kernel/flag.c $(COOSDIR)/kernel/mutex.c $(COOSDIR)/kernel/serviceReq.c $(COOSDIR)/portable/GCC/port.c $(COOSDIR)/portable/arch.c
|
||||
SRC += targets/Horus/pwr_driver.c targets/Horus/usb_driver.c targets/Horus/sdram_driver.c
|
||||
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/Horus/pulses_driver.cpp targets/Horus/keys_driver.cpp targets/Horus/adc_driver.cpp targets/Horus/trainer_driver.cpp targets/Horus/audio_driver.cpp targets/Horus/serial2_driver.cpp targets/Horus/telemetry_driver.cpp
|
||||
CPPSRC += gui/$(GUIDIRECTORY)/view_channels.cpp gui/$(GUIDIRECTORY)/view_about.cpp gui/$(GUIDIRECTORY)/view_text.cpp debug.cpp
|
||||
SRC += targets/Horus/system_stm32f4xx.c
|
||||
SRC += $(STM32LIBPATH)/STM32F4xx_StdPeriph_Driver/src/misc.c
|
||||
SRC += $(STM32LIBPATH)/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_gpio.c
|
||||
SRC += $(STM32LIBPATH)/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_dbgmcu.c
|
||||
SRC += $(STM32LIBPATH)/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_rcc.c
|
||||
SRC += $(STM32LIBPATH)/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_spi.c
|
||||
SRC += $(STM32LIBPATH)/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_i2c.c
|
||||
SRC += $(STM32LIBPATH)/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_dma.c
|
||||
SRC += $(STM32LIBPATH)/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_rtc.c
|
||||
SRC += $(STM32LIBPATH)/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_pwr.c
|
||||
SRC += $(STM32LIBPATH)/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_usart.c
|
||||
SRC += $(STM32LIBPATH)/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_sdio.c
|
||||
SRC += $(STM32LIBPATH)/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_fmc.c
|
||||
SRC += $(STM32LIBPATH)/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_ltdc.c
|
||||
SRC += $(STM32LIBPATH)/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_tim.c
|
||||
SRC += $(STM32LIBPATH)/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_dma2d.c
|
||||
SRC += $(STM32LIBPATH)/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc_ride7/startup_stm32f40_41xxx.s
|
||||
SRC += targets/Horus/sdio_sd.c targets/Horus/usb_bsp.c targets/Horus/usbd_desc.c
|
||||
SRC += $(STM32USBPATH)/STM32_USB_OTG_Driver/src/usb_core.c
|
||||
SRC += $(STM32USBPATH)/STM32_USB_OTG_Driver/src/usb_dcd.c
|
||||
SRC += $(STM32USBPATH)/STM32_USB_OTG_Driver/src/usb_dcd_int.c
|
||||
SRC += $(STM32USBPATH)/STM32_USB_Device_Library/Core/src/usbd_core.c
|
||||
SRC += $(STM32USBPATH)/STM32_USB_Device_Library/Core/src/usbd_ioreq.c
|
||||
SRC += $(STM32USBPATH)/STM32_USB_Device_Library/Core/src/usbd_req.c
|
||||
EXTRABOARDSRC += targets/Horus/usbd_usr.cpp
|
||||
SRC += syscalls.c
|
||||
ifeq ($(USB), JOYSTICK)
|
||||
CPPDEFS += -DUSB_JOYSTICK
|
||||
SRC += targets/Horus/usbd_hid_joystick.c
|
||||
else ifeq ($(USB), SERIAL)
|
||||
CPPDEFS += -DUSB_SERIAL
|
||||
SRC += $(STM32USBPATH)/STM32_USB_Device_Library/Class/cdc/src/usbd_cdc_core.c
|
||||
EXTRABOARDSRC += targets/Horus/usbd_cdc.cpp
|
||||
else
|
||||
CPPDEFS += -DUSB_MASS_STORAGE
|
||||
SRC += $(STM32USBPATH)/STM32_USB_Device_Library/Class/msc/src/usbd_msc_data.c
|
||||
SRC += $(STM32USBPATH)/STM32_USB_Device_Library/Class/msc/src/usbd_msc_scsi.c
|
||||
SRC += $(STM32USBPATH)/STM32_USB_Device_Library/Class/msc/src/usbd_msc_bot.c
|
||||
SRC += $(STM32USBPATH)/STM32_USB_Device_Library/Class/msc/src/usbd_msc_core.c
|
||||
EXTRABOARDSRC += targets/Horus/usbd_storage_msd.cpp
|
||||
endif
|
||||
ifeq ($(GVARS), YES)
|
||||
GUIMODELSRC += gui/$(GUIDIRECTORY)/menu_model_gvars.cpp
|
||||
endif
|
||||
ifneq ($(LUA), NO)
|
||||
ifeq ($(LUA), YES)
|
||||
CPPDEFS += -DLUA_MODEL_SCRIPTS
|
||||
endif
|
||||
CPPDEFS += -DLUA
|
||||
INCDIRS += $(LUADIR)
|
||||
CPPSRC += lua_api.cpp
|
||||
LUASRC = $(LUADIR)/lapi.c $(LUADIR)/lcode.c $(LUADIR)/lctype.c $(LUADIR)/ldebug.c $(LUADIR)/ldo.c $(LUADIR)/ldump.c $(LUADIR)/lfunc.c $(LUADIR)/lgc.c $(LUADIR)/llex.c $(LUADIR)/lmem.c \
|
||||
$(LUADIR)/lobject.c $(LUADIR)/lopcodes.c $(LUADIR)/lparser.c $(LUADIR)/lstate.c $(LUADIR)/lstring.c $(LUADIR)/ltable.c $(LUADIR)/lrotable.c $(LUADIR)/ltm.c $(LUADIR)/lundump.c $(LUADIR)/lvm.c $(LUADIR)/lzio.c \
|
||||
$(LUADIR)/lbaselib.c $(LUADIR)/linit.c $(LUADIR)/lmathlib.c $(LUADIR)/lbitlib.c $(LUADIR)/loadlib.c $(LUADIR)/lauxlib.c $(LUADIR)/ltablib.c $(LUADIR)/lcorolib.c $(LUADIR)/liolib.c
|
||||
SRC += $(LUASRC)
|
||||
LUADEP = lua_exports_flamenco.inc
|
||||
endif
|
||||
|
||||
EXTRABOARDSRC += $(FATFSDIR)/ff.c $(FATFSDIR)/fattime.c $(FATFSDIR)/option/ccsbcs.c targets/Horus/diskio.cpp
|
||||
CPPDEFS += -DSDCARD -DVOICE -DRTCLOCK
|
||||
CPPSRC += sdcard.cpp rtc.cpp logs.cpp targets/taranis/rtc_driver.cpp
|
||||
GUIGENERALSRC += gui/$(GUIDIRECTORY)/menu_general_sdmanager.cpp
|
||||
INCDIRS += $(FATFSDIR) $(FATFSDIR)/option
|
||||
|
||||
ifeq ($(DSM2), PPM)
|
||||
CPPSRC += pulses/dsm2_arm.cpp
|
||||
endif
|
||||
|
||||
CPPDEFS += -DHAPTIC
|
||||
CPPSRC += haptic.cpp
|
||||
CPPSRC += targets/Horus/haptic_driver.cpp
|
||||
EXTRABOARDSRC +=
|
||||
|
||||
ifeq ($(TW8823_TRACES), YES)
|
||||
CPPDEFS += -DTW8823_TRACES
|
||||
endif
|
||||
|
||||
ifeq ($(TW8823_BITMAPS), YES)
|
||||
CPPDEFS += -DTW8823_BITMAPS
|
||||
endif
|
||||
|
||||
ifeq ($(TW8823_SERIAL), YES)
|
||||
CPPDEFS += -DTW8823_SERIAL
|
||||
endif
|
||||
endif
|
||||
|
||||
CC = $(TRGT)gcc
|
||||
CPP = $(TRGT)cpp
|
||||
AS = $(TRGT)as
|
||||
@@ -1084,7 +1335,7 @@ FORMAT = ihex
|
||||
TARGET = opentx
|
||||
|
||||
# List C++ source files here. (C dependencies are automatically generated.)
|
||||
ifeq ($(PCB), $(filter $(PCB), SKY9X 9XRPRO AR9X TARANIS))
|
||||
ifeq ($(PCB), $(filter $(PCB), SKY9X 9XRPRO AR9X TARANIS FLAMENCO HORUS))
|
||||
TTS_SRC = translations/tts_cz.cpp translations/tts_de.cpp translations/tts_en.cpp translations/tts_es.cpp translations/tts_fr.cpp translations/tts_it.cpp translations/tts_nl.cpp translations/tts_pt.cpp translations/tts_sk.cpp translations/tts_se.cpp translations/tts_pl.cpp translations/tts_hu.cpp
|
||||
else
|
||||
STD_TTS_SRC = translations/tts_$(shell sh -c "echo $(TTS) | tr '[:upper:]' '[:lower:]'").cpp
|
||||
@@ -1144,7 +1395,7 @@ ifeq ($(NAVIGATION), ROTENC)
|
||||
endif
|
||||
|
||||
ifeq ($(TURNIGY_TRANSMITTER_FIX), YES)
|
||||
ifeq ($(PCB), $(filter $(PCB), TARANIS))
|
||||
ifeq ($(PCB), $(filter $(PCB), TARANIS FLAMENCO HORUS))
|
||||
$(warning TURNIGY_TRANSMITTER_FIX is not available on this radio)
|
||||
else
|
||||
CPPDEFS += -DMODULE_ALWAYS_SEND_PULSES
|
||||
@@ -1195,7 +1446,7 @@ ifeq ($(BOLD), YES)
|
||||
CPPDEFS += -DBOLD_FONT
|
||||
endif
|
||||
|
||||
ifneq ($(PCB), $(filter $(PCB), TARANIS))
|
||||
ifneq ($(PCB), $(filter $(PCB), TARANIS FLAMENCO HORUS))
|
||||
ifeq ($(BATTGRAPH), YES)
|
||||
CPPDEFS += -DBATTGRAPH
|
||||
endif
|
||||
@@ -1389,7 +1640,7 @@ ifeq ($(HELI), YES)
|
||||
endif
|
||||
|
||||
ifeq ($(TEMPLATES), YES)
|
||||
ifneq ($(PCB), $(filter $(PCB), TARANIS))
|
||||
ifneq ($(PCB), $(filter $(PCB), TARANIS FLAMENCO HORUS))
|
||||
CPPDEFS += -DTEMPLATES
|
||||
CPPSRC += templates.cpp
|
||||
GUIMODELSRC += gui/$(GUIDIRECTORY)/menu_model_templates.cpp
|
||||
@@ -1592,30 +1843,51 @@ translations/se.h: translations/se.h.txt
|
||||
@echo "Create Swedish language specific header files"
|
||||
$(TRANSLATE) translations/se.h.txt translations/se.h se
|
||||
|
||||
FONTNAME = Roboto
|
||||
ifeq ($(PCB), $(filter $(PCB), HORUS))
|
||||
FONTNAME = DejaVu\ Sans
|
||||
TINSIZE = 5
|
||||
SMLSIZE = 7
|
||||
STDSIZE = 16
|
||||
MIDSIZE = 16
|
||||
DBLSIZE = 20
|
||||
XXLSIZE = 38
|
||||
else
|
||||
FONTNAME = Roboto
|
||||
TINSIZE = 5
|
||||
SMLSIZE = 7
|
||||
STDSIZE = 8
|
||||
MIDSIZE = 11
|
||||
DBLSIZE = 14
|
||||
XXLSIZE = 38
|
||||
endif
|
||||
|
||||
.PHONY: fonts
|
||||
fonts: $(FONTS)
|
||||
|
||||
fonts/font_%size.lbm: fonts/font_%size.png
|
||||
$(IMG2LBM) $^ $@ $(LCDSIZE) 8bits
|
||||
|
||||
fonts/font_tinsize.png:
|
||||
$(FONT2PNG) $(FONTNAME) $(TINSIZE) fonts/font_tinsize
|
||||
|
||||
fonts/font_smlsize.png:
|
||||
$(FONT2PNG) $(FONTNAME) $(SMLSIZE) fonts/font_smlsize
|
||||
|
||||
fonts/font_stdsize.png:
|
||||
$(FONT2PNG) $(FONTNAME) $(STDSIZE) fonts/font_stdsize
|
||||
|
||||
fonts/font_midsize.png:
|
||||
$(FONT2PNG) $(FONTNAME) $(MIDSIZE) fonts/font_midsize
|
||||
|
||||
fonts/font_dblsize.png:
|
||||
$(FONT2PNG) $(FONTNAME) $(DBLSIZE) fonts/font_dblsize
|
||||
|
||||
fonts/font_xxlsize.png:
|
||||
$(FONT2PNG) $(FONTNAME) $(XXLSIZE) fonts/font_xxlsize
|
||||
|
||||
fonts/%.lbm: fonts/%.png
|
||||
$(IMG2LBM) $^ $@ $(LCDSIZE)
|
||||
|
||||
fonts/font_tinsize.lbm:
|
||||
$(FONT2PNG) $(FONTNAME) 5 fonts/font_tinsize.png
|
||||
$(IMG2LBM) fonts/font_tinsize.png $@ $(LCDSIZE) 4bits
|
||||
|
||||
fonts/font_stdsize.lbm:
|
||||
$(FONT2PNG) $(FONTNAME) 8 fonts/font_stdsize.png
|
||||
$(IMG2LBM) fonts/font_stdsize.png $@ $(LCDSIZE) 4bits
|
||||
|
||||
fonts/font_midsize.lbm:
|
||||
$(FONT2PNG) $(FONTNAME) 10 fonts/font_midsize.png
|
||||
$(IMG2LBM) fonts/font_midsize.png $@ $(LCDSIZE) 4bits
|
||||
|
||||
fonts/font_dblsize.lbm:
|
||||
$(FONT2PNG) $(FONTNAME) 14 fonts/font_dblsize.png
|
||||
$(IMG2LBM) fonts/font_dblsize.png $@ $(LCDSIZE) 4bits
|
||||
|
||||
.PHONY: bitmaps
|
||||
bitmaps: $(BITMAPS)
|
||||
|
||||
@@ -1631,18 +1903,41 @@ bitmaps/Taranis/%.lbm: bitmaps/Taranis/%.png
|
||||
bitmaps/Taranis/mainmenu.png: ../util/taranisicons.py $(wildcard bitmaps/Taranis/std/*.png)
|
||||
@$(PYTHON) ../util/taranisicons.py
|
||||
|
||||
bitmaps/Flamenco/%.lbm: bitmaps/Flamenco/%.png
|
||||
$(IMG2LBM) $^ $@ $(LCDSIZE) 4/4/4/4
|
||||
|
||||
bitmaps/Horus/mask_%.lbm: bitmaps/Horus/mask_%.png
|
||||
$(IMG2LBM) $^ $@ $(LCDSIZE) 8bits
|
||||
|
||||
bitmaps/Horus/%.lbm: bitmaps/Horus/%.png
|
||||
$(IMG2LBM) $^ $@ $(LCDSIZE) 5/6/5
|
||||
|
||||
ifeq ($(OS),Windows_NT)
|
||||
PARSER = avr-cpp
|
||||
else
|
||||
PARSER = gcc -E -x c++
|
||||
endif
|
||||
|
||||
lua_exports.inc: myeeprom.h ../util/luaexport.py
|
||||
@echo "Generating a list of Lua exported constants in lua_exports.txt"
|
||||
@$(PARSER) -DPCBTARANIS -DCPUARM -DCPUSTM32 -DLUA -DEXPORT myeeprom.h | grep LEXP > lua_exports.txt
|
||||
@echo "Parsing and generating C Lua exports in lua_exports.inc"
|
||||
@$(PYTHON) ../util/luaexport.py $(VERSION) lua_exports.txt lua_exports.inc lua_fields.txt
|
||||
@rm lua_exports.txt
|
||||
lua_exports_taranis.inc: myeeprom.h ../util/luaexport.py
|
||||
@echo "Generating a list of Lua exported constants in lua_exports_taranis.txt"
|
||||
@$(PARSER) -DPCBTARANIS -DCPUARM -DCPUSTM32 -DLUA -DEXPORT myeeprom.h | grep LEXP > lua_exports_taranis.txt
|
||||
@echo "Parsing and generating C Lua exports in lua_exports_taranis.inc"
|
||||
@$(PYTHON) ../util/luaexport.py $(VERSION) lua_exports_taranis.txt lua_exports_taranis.inc lua_fields_taranis.txt
|
||||
@rm lua_exports_taranis.txt
|
||||
|
||||
lua_exports_horus.inc: myeeprom.h ../util/luaexport.py
|
||||
@echo "Generating a list of Lua exported constants in lua_exports_horus.txt"
|
||||
@$(PARSER) -DPCBFLAMENCO -DCPUARM -DCPUSTM32 -DLUA -DEXPORT myeeprom.h | grep LEXP > lua_exports_horus.txt
|
||||
@echo "Parsing and generating C Lua exports in lua_exports_horus.inc"
|
||||
@$(PYTHON) ../util/luaexport.py $(VERSION) lua_exports_horus.txt lua_exports_horus.inc lua_fields_horus.txt
|
||||
@rm lua_exports_horus.txt
|
||||
|
||||
lua_exports_flamenco.inc: myeeprom.h ../util/luaexport.py
|
||||
@echo "Generating a list of Lua exported constants in lua_exports_flamenco.txt"
|
||||
@$(PARSER) -DPCBFLAMENCO -DCPUARM -DCPUSTM32 -DLUA -DEXPORT myeeprom.h | grep LEXP > lua_exports_flamenco.txt
|
||||
@echo "Parsing and generating C Lua exports in lua_exports_flamenco.inc"
|
||||
@$(PYTHON) ../util/luaexport.py $(VERSION) lua_exports_flamenco.txt lua_exports_flamenco.inc lua_fields_flamenco.txt
|
||||
@rm lua_exports_flamenco.txt
|
||||
|
||||
# Eye candy.
|
||||
# AVR Studio 3.x does not check make's exit code but relies on
|
||||
@@ -1803,7 +2098,7 @@ clean_list :
|
||||
$(REMOVE) bitmaps/*/*/*.lbm
|
||||
$(REMOVE) fonts/*.lbm
|
||||
$(REMOVE) fonts/*/*.lbm
|
||||
$(REMOVE) lua_exports.txt lua_exports.inc lua_fields.txt
|
||||
$(REMOVE) lua_exports* lua_fields.txt
|
||||
$(MAKE) -C targets/taranis/bootloader clean
|
||||
|
||||
#### Install
|
||||
|
||||
@@ -189,7 +189,7 @@ const char * const audioFilenames[] = {
|
||||
"midstck2",
|
||||
"midstck3",
|
||||
"midstck4",
|
||||
#if defined(PCBTARANIS)
|
||||
#if defined(PCBTARANIS) || defined(PCBFLAMENCO) || defined(PCBHORUS)
|
||||
"midpot1",
|
||||
"midpot2",
|
||||
"midslid1",
|
||||
@@ -265,6 +265,8 @@ void referenceSystemAudioFiles()
|
||||
fn = *fno.lfname ? fno.lfname : fno.fname;
|
||||
uint8_t len = strlen(fn);
|
||||
|
||||
TRACE("%s", fn);
|
||||
|
||||
// Eliminates directories / non wav files
|
||||
if (len < 5 || strcasecmp(fn+len-4, SOUNDS_EXT) || (fno.fattrib & AM_DIR)) continue;
|
||||
|
||||
@@ -520,6 +522,7 @@ void audioTask(void* pdata)
|
||||
setSampleRate(AUDIO_SAMPLE_RATE);
|
||||
|
||||
#if defined(SDCARD)
|
||||
TRACE("unexpectedShutdown = %d", unexpectedShutdown);
|
||||
if (!unexpectedShutdown) {
|
||||
sdInit();
|
||||
AUDIO_TADA();
|
||||
@@ -1096,7 +1099,7 @@ void audioEvent(unsigned int index, unsigned int freq)
|
||||
case AU_STICK4_MIDDLE:
|
||||
case AU_POT1_MIDDLE:
|
||||
case AU_POT2_MIDDLE:
|
||||
#if defined(PCBTARANIS)
|
||||
#if defined(PCBTARANIS) || defined(PCBFLAMENCO) || defined(PCBHORUS)
|
||||
case AU_SLIDER1_MIDDLE:
|
||||
case AU_SLIDER2_MIDDLE:
|
||||
#else
|
||||
|
||||
+1
-1
@@ -65,7 +65,7 @@ inline void _beep(uint8_t b)
|
||||
|
||||
void beep(uint8_t val);
|
||||
#else /* BUZZER */
|
||||
#define beep(...)
|
||||
inline void beep(uint8_t) { }
|
||||
#endif /* BUZZER */
|
||||
|
||||
#if !defined(AUDIO)
|
||||
|
||||
+101
-6
@@ -43,7 +43,7 @@
|
||||
OS_TID cliTaskId;
|
||||
TaskStack<CLI_STACK_SIZE> cliStack;
|
||||
Fifo<256> cliRxFifo;
|
||||
uint8_t cliTracesEnabled = false;
|
||||
uint8_t cliTracesEnabled = true;
|
||||
|
||||
typedef int (* CliFunction) (const char ** args);
|
||||
|
||||
@@ -66,7 +66,7 @@ void cliPrompt()
|
||||
serialPutc('>');
|
||||
}
|
||||
|
||||
int toInt(const char ** argv, int index, int * val)
|
||||
int toLongLongInt(const char ** argv, int index, long long int * val)
|
||||
{
|
||||
if (*argv[index] == '\0') {
|
||||
return 0;
|
||||
@@ -79,7 +79,7 @@ int toInt(const char ** argv, int index, int * val)
|
||||
s = &argv[index][2];
|
||||
}
|
||||
char * endptr = NULL;
|
||||
*val = strtol(s, &endptr, base);
|
||||
*val = strtoll(s, &endptr, base);
|
||||
if (*endptr == '\0')
|
||||
return 1;
|
||||
else {
|
||||
@@ -89,6 +89,14 @@ int toInt(const char ** argv, int index, int * val)
|
||||
}
|
||||
}
|
||||
|
||||
int toInt(const char ** argv, int index, int * val)
|
||||
{
|
||||
long long int lval = 0;
|
||||
int result = toLongLongInt(argv, index, &lval);
|
||||
*val = (int)lval;
|
||||
return result;
|
||||
}
|
||||
|
||||
int cliBeep(const char ** argv)
|
||||
{
|
||||
int freq = BEEP_DEFAULT_FREQ;
|
||||
@@ -200,6 +208,33 @@ int cliVolume(const char ** argv)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(PCBFLAMENCO)
|
||||
int cliReadBQ24195(const char ** argv)
|
||||
{
|
||||
int index = 0;
|
||||
if (toInt(argv, 1, &index) > 0) {
|
||||
serialPrint("BQ24195[%d] = 0x%02x", index, i2cReadBQ24195(index));
|
||||
}
|
||||
else {
|
||||
serialPrint("%s: Invalid arguments \"%s\" \"%s\"", argv[0], argv[1]);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cliWriteBQ24195(const char ** argv)
|
||||
{
|
||||
int index = 0;
|
||||
int data = 0;
|
||||
if (toInt(argv, 1, &index) > 0 && toInt(argv, 2, &data) > 0) {
|
||||
i2cWriteBQ24195(index, data);
|
||||
}
|
||||
else {
|
||||
serialPrint("%s: Invalid arguments \"%s\" \"%s\"", argv[0], argv[1], argv[2]);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
const MemArea memAreas[] = {
|
||||
{ "RCC", RCC, sizeof(RCC_TypeDef) },
|
||||
{ "GPIOA", GPIOA, sizeof(GPIO_TypeDef) },
|
||||
@@ -210,13 +245,14 @@ const MemArea memAreas[] = {
|
||||
{ "GPIOF", GPIOF, sizeof(GPIO_TypeDef) },
|
||||
{ "GPIOG", GPIOG, sizeof(GPIO_TypeDef) },
|
||||
{ "USART1", USART1, sizeof(USART_TypeDef) },
|
||||
{ "USART2", USART2, sizeof(USART_TypeDef) },
|
||||
{ "USART3", USART3, sizeof(USART_TypeDef) },
|
||||
{ NULL, NULL, 0 },
|
||||
};
|
||||
|
||||
int cliDisplay(const char ** argv)
|
||||
{
|
||||
int address = 0;
|
||||
long long int address = 0;
|
||||
|
||||
for (const MemArea * area = memAreas; area->name != NULL; area++) {
|
||||
if (!strcmp(area->name, argv[1])) {
|
||||
@@ -225,7 +261,26 @@ int cliDisplay(const char ** argv)
|
||||
}
|
||||
}
|
||||
|
||||
if (!strcmp(argv[1], "adc")) {
|
||||
if (!strcmp(argv[1], "keys")) {
|
||||
for (int i=0; i<TRM_BASE; i++) {
|
||||
char name[8];
|
||||
uint8_t len = STR_VKEYS[0];
|
||||
strncpy(name, STR_VKEYS+1+len*i, len);
|
||||
name[len] = '\0';
|
||||
serialPrint("[%s] = %s", name, switchState(EnumKeys(i)) ? "on" : "off");
|
||||
}
|
||||
serialPrint("[Enc.] = %d", rotencValue / 2);
|
||||
for (int i=TRM_BASE; i<=TRM_LAST; i++) {
|
||||
serialPrint("[Trim%d] = %s", i-TRM_BASE, switchState(EnumKeys(i)) ? "on" : "off");
|
||||
}
|
||||
for (int i=MIXSRC_FIRST_SWITCH; i<=MIXSRC_LAST_SWITCH; i++) {
|
||||
mixsrc_t sw = i - MIXSRC_FIRST_SWITCH;
|
||||
if (SWITCH_EXISTS(sw)) {
|
||||
serialPrint("[S%c] = %s", 'A'+sw, (switchState((EnumKeys)(SW_BASE+(3*sw))) ? "down" : (switchState((EnumKeys)(SW_BASE+(3*sw)+1)) ? "mid" : "up")));
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!strcmp(argv[1], "adc")) {
|
||||
for (int i=0; i<NUMBER_ANALOG; i++) {
|
||||
serialPrint("adc[%d] = %04X", i, Analog_values[i]);
|
||||
}
|
||||
@@ -240,7 +295,43 @@ int cliDisplay(const char ** argv)
|
||||
gettime(&utm);
|
||||
serialPrint("time = %4d-%02d-%02d %02d:%02d:%02d.%02d0", utm.tm_year+1900, utm.tm_mon+1, utm.tm_mday, utm.tm_hour, utm.tm_min, utm.tm_sec, g_ms100);
|
||||
}
|
||||
else if (toInt(argv, 1, &address) > 0) {
|
||||
#if defined(PCBFLAMENCO)
|
||||
else if (!strcmp(argv[1], "bq24195")) {
|
||||
{
|
||||
uint8_t reg = i2cReadBQ24195(0x00);
|
||||
serialPrint(reg & 0x80 ? "HIZ enable" : "HIZ disable");
|
||||
}
|
||||
{
|
||||
uint8_t reg = i2cReadBQ24195(0x08);
|
||||
serialPrint(reg & 0x01 ? "VBatt < VSysMin" : "VBatt > VSysMin");
|
||||
serialPrint(reg & 0x02 ? "Thermal sensor bad" : "Thermal sensor ok");
|
||||
serialPrint(reg & 0x04 ? "Power ok" : "Power bad");
|
||||
serialPrint(reg & 0x08 ? "Connected to charger" : "Not connected to charger");
|
||||
const char * CHARGE_STATUS[] = { "Not Charging", "Precharge", "Fast Charging", "Charge done" };
|
||||
serialPrint(CHARGE_STATUS[(reg & 0x30) >> 4]);
|
||||
const char * INPUT_STATUS[] = { "Unknown input", "USB host input", "USB adapter port input", "OTG input" };
|
||||
serialPrint(INPUT_STATUS[(reg & 0xC0) >> 6]);
|
||||
}
|
||||
{
|
||||
uint8_t reg = i2cReadBQ24195(0x09);
|
||||
if (reg & 0x80) serialPrint("Watchdog timer expiration");
|
||||
uint8_t chargerFault = (reg & 0x30) >> 4;
|
||||
if (chargerFault == 0x01)
|
||||
serialPrint("Input fault");
|
||||
else if (chargerFault == 0x02)
|
||||
serialPrint("Thermal shutdown");
|
||||
else if (chargerFault == 0x03)
|
||||
serialPrint("Charge safety timer expiration");
|
||||
if (reg & 0x08) serialPrint("Battery over voltage fault");
|
||||
uint8_t ntcFault = (reg & 0x07);
|
||||
if (ntcFault == 0x05)
|
||||
serialPrint("NTC cold");
|
||||
else if (ntcFault == 0x06)
|
||||
serialPrint("NTC hot");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
else if (toLongLongInt(argv, 1, &address) > 0) {
|
||||
int size = 256;
|
||||
if (toInt(argv, 2, &size) >= 0) {
|
||||
dump((uint8_t *)address, size);
|
||||
@@ -259,6 +350,10 @@ const CliCommand cliCommands[] = {
|
||||
{ "stackinfo", cliStackInfo, "<tid>" },
|
||||
{ "trace", cliTrace, "on | off" },
|
||||
{ "volume", cliVolume, "<level>" },
|
||||
#if defined(PCBFLAMENCO)
|
||||
{ "read_bq24195", cliReadBQ24195, "<register>" },
|
||||
{ "write_bq24195", cliWriteBQ24195, "<register> <data>" },
|
||||
#endif
|
||||
{ "help", cliHelp, "[<command>]" },
|
||||
{ NULL, NULL, NULL } /* sentinel */
|
||||
};
|
||||
|
||||
@@ -50,5 +50,7 @@ extern TaskStack<CLI_STACK_SIZE> cliStack;
|
||||
#endif
|
||||
|
||||
void cliStart();
|
||||
void cliStackPaint();
|
||||
uint32_t cliStackFree();
|
||||
|
||||
#endif // _CLI_H_
|
||||
|
||||
@@ -69,15 +69,15 @@ PACK(struct EepromFileHeader
|
||||
uint16_t size;
|
||||
});
|
||||
|
||||
EepromHeader eepromHeader;
|
||||
EepromWriteState eepromWriteState = EEPROM_IDLE;
|
||||
EepromHeader eepromHeader __DMA;
|
||||
volatile EepromWriteState eepromWriteState = EEPROM_IDLE;
|
||||
uint8_t eepromWriteZoneIndex = FIRST_FILE_AVAILABLE;
|
||||
uint8_t eepromWriteFileIndex;
|
||||
uint16_t eepromWriteSize;
|
||||
uint8_t * eepromWriteSourceAddr;
|
||||
uint32_t eepromWriteDestinationAddr;
|
||||
uint16_t eepromFatAddr = 0;
|
||||
uint8_t eepromWriteBuffer[EEPROM_BUFFER_SIZE];
|
||||
uint8_t eepromWriteBuffer[EEPROM_BUFFER_SIZE] __DMA;
|
||||
|
||||
void eepromWaitSpiComplete()
|
||||
{
|
||||
@@ -424,6 +424,8 @@ void eepromFormat()
|
||||
|
||||
void eeErase(bool warn)
|
||||
{
|
||||
TRACE("eeErase()");
|
||||
|
||||
generalDefault();
|
||||
modelDefault(0);
|
||||
|
||||
@@ -442,6 +444,10 @@ void eeErase(bool warn)
|
||||
void eepromWriteWait(EepromWriteState state/* = EEPROM_IDLE*/)
|
||||
{
|
||||
while (eepromWriteState != state) {
|
||||
#if defined(CPUSTM32)
|
||||
// Waits a little bit for CS transitions
|
||||
CoTickDelay(1/*2ms*/);
|
||||
#endif
|
||||
eepromWriteProcess();
|
||||
#ifdef SIMU
|
||||
sleep(5/*ms*/);
|
||||
|
||||
@@ -75,7 +75,7 @@ enum EepromWriteState {
|
||||
EEPROM_END_WRITE
|
||||
};
|
||||
|
||||
extern EepromWriteState eepromWriteState;
|
||||
extern volatile EepromWriteState eepromWriteState;
|
||||
inline bool eepromIsWriting()
|
||||
{
|
||||
return (eepromWriteState != EEPROM_IDLE);
|
||||
|
||||
@@ -933,7 +933,7 @@ void eeLoadModelName(uint8_t id, char *name)
|
||||
|
||||
bool eeModelExists(uint8_t id)
|
||||
{
|
||||
return EFile::exists(FILE_MODEL(id));
|
||||
return EFile::exists(FILE_MODEL(id));
|
||||
}
|
||||
|
||||
// TODO Now the 2 functions in eeprom_rlc.cpp and eeprom_raw.cpp are really close, should be merged.
|
||||
|
||||
@@ -47,6 +47,11 @@ class Fifo
|
||||
{
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
widx = ridx = 0;
|
||||
}
|
||||
|
||||
void push(uint8_t byte) {
|
||||
uint32_t next = (widx+1) & (N-1);
|
||||
if (next != ridx) {
|
||||
|
||||
@@ -37,6 +37,13 @@
|
||||
#ifndef fonts_h
|
||||
#define fonts_h
|
||||
|
||||
#if defined(COLORLCD)
|
||||
|
||||
extern const uint16_t *fontspecsTable[16];
|
||||
extern const pm_uchar *fontsTable[16];
|
||||
|
||||
#else
|
||||
|
||||
extern const pm_uchar font_5x7[];
|
||||
extern const pm_uchar font_10x14[];
|
||||
|
||||
@@ -56,3 +63,5 @@ extern const pm_uchar font_4x6_extra[];
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -324,7 +324,7 @@ void evalFunctions()
|
||||
if (!isFunctionActive(FUNCTION_INSTANT_TRIM)) {
|
||||
#if defined(GUI)
|
||||
if (g_menuStack[0] == menuMainView
|
||||
#if defined(FRSKY)
|
||||
#if defined(FRSKY) && !defined(PCBFLAMENCO) && !defined(PCBHORUS)
|
||||
|| g_menuStack[0] == menuTelemetryFrsky
|
||||
#endif
|
||||
#if defined(PCBTARANIS)
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Authors (alphabetical order)
|
||||
* - Andre Bernet <bernet.andre@gmail.com>
|
||||
* - Andreas Weitl
|
||||
* - Bertrand Songis <bsongis@gmail.com>
|
||||
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
|
||||
* - Cameron Weeks <th9xer@gmail.com>
|
||||
* - Erez Raviv
|
||||
* - Gabriel Birkus
|
||||
* - Jean-Pierre Parisy
|
||||
* - Karl Szmutny
|
||||
* - Michael Blandford
|
||||
* - Michal Hlavinka
|
||||
* - Pat Mackenzie
|
||||
* - Philip Moss
|
||||
* - Rob Thomson
|
||||
* - Romolo Manfredini <romolo.manfredini@gmail.com>
|
||||
* - 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 uint16_t font_tinsize_specs[] PROGMEM =
|
||||
#include "fonts/font_tinsize.specs"
|
||||
;
|
||||
|
||||
const pm_uchar font_tinsize[] PROGMEM = {
|
||||
#include "fonts/font_tinsize.lbm"
|
||||
};
|
||||
|
||||
const uint16_t font_smlsize_specs[] PROGMEM =
|
||||
#include "fonts/font_smlsize.specs"
|
||||
;
|
||||
|
||||
const pm_uchar font_smlsize[] PROGMEM = {
|
||||
#include "fonts/font_smlsize.lbm"
|
||||
};
|
||||
|
||||
const uint16_t font_stdsize_specs[] PROGMEM =
|
||||
#include "fonts/font_stdsize.specs"
|
||||
;
|
||||
|
||||
const pm_uchar font_stdsize[] PROGMEM = {
|
||||
#include "fonts/font_stdsize.lbm"
|
||||
};
|
||||
|
||||
const uint16_t font_midsize_specs[] PROGMEM =
|
||||
#include "fonts/font_midsize.specs"
|
||||
;
|
||||
|
||||
const pm_uchar font_midsize[] PROGMEM = {
|
||||
#include "fonts/font_midsize.lbm"
|
||||
};
|
||||
|
||||
const uint16_t font_dblsize_specs[] PROGMEM =
|
||||
#include "fonts/font_dblsize.specs"
|
||||
;
|
||||
|
||||
const pm_uchar font_dblsize[] PROGMEM = {
|
||||
#include "fonts/font_dblsize.lbm"
|
||||
};
|
||||
|
||||
const uint16_t font_xxlsize_specs[] PROGMEM =
|
||||
#include "fonts/font_xxlsize.specs"
|
||||
;
|
||||
|
||||
const pm_uchar font_xxlsize[] PROGMEM = {
|
||||
#include "fonts/font_xxlsize.lbm"
|
||||
};
|
||||
|
||||
const uint16_t *fontspecsTable[16] = { font_stdsize_specs, font_tinsize_specs, font_smlsize_specs, font_midsize_specs, font_dblsize_specs, font_xxlsize_specs };
|
||||
const pm_uchar *fontsTable[16] = { font_stdsize, font_tinsize, font_smlsize, font_midsize, font_dblsize, font_xxlsize };
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Authors (alphabetical order)
|
||||
* - Andre Bernet <bernet.andre@gmail.com>
|
||||
* - Andreas Weitl
|
||||
* - Bertrand Songis <bsongis@gmail.com>
|
||||
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
|
||||
* - Cameron Weeks <th9xer@gmail.com>
|
||||
* - Erez Raviv
|
||||
* - Gabriel Birkus
|
||||
* - Jean-Pierre Parisy
|
||||
* - Karl Szmutny
|
||||
* - Michael Blandford
|
||||
* - Michal Hlavinka
|
||||
* - Pat Mackenzie
|
||||
* - Philip Moss
|
||||
* - Rob Thomson
|
||||
* - Romolo Manfredini <romolo.manfredini@gmail.com>
|
||||
* - 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 "lcd.h"
|
||||
#include "menus.h"
|
||||
|
||||
#define MENU_HEADER_HEIGHT 45
|
||||
#define MENU_TITLE_TOP 48
|
||||
#define MENU_TITLE_HEIGHT 21
|
||||
#define MENU_BODY_TOP 70
|
||||
#define MENU_CONTENT_TOP 72
|
||||
#define MENU_BODY_HEIGHT 182
|
||||
#define MENU_FOOTER_TOP 251
|
||||
#define MENU_FOOTER_HEIGHT 21
|
||||
|
||||
#define MENU_TITLE_LEFT 6
|
||||
|
||||
#define DEFAULT_SCROLLBAR_X LCD_W-10
|
||||
#define DEFAULT_SCROLLBAR_Y MENU_CONTENT_TOP
|
||||
#define DEFAULT_SCROLLBAR_H (MENU_FOOTER_TOP - DEFAULT_SCROLLBAR_Y - 6)
|
||||
|
||||
#define NUM_BODY_LINES 9
|
||||
#define FH 20
|
||||
|
||||
#define INVERT_HORZ_MARGIN 3
|
||||
#define INVERT_VERT_MARGIN 1
|
||||
#define INVERT_LINE_HEIGHT 18
|
||||
|
||||
void displaySplash();
|
||||
void displayScreenIndex(uint8_t index, uint8_t count);
|
||||
void displayScrollbar(coord_t x, coord_t y, coord_t h, uint16_t offset, uint16_t count, uint8_t visible);
|
||||
void drawHeader(int index);
|
||||
void drawFooter();
|
||||
#define drawStatusLine(...)
|
||||
void displayProgressBar(const char *label);
|
||||
void updateProgressBar(int num, int den);
|
||||
|
||||
@@ -0,0 +1,341 @@
|
||||
/*
|
||||
* Authors (alphabetical order)
|
||||
* - Andre Bernet <bernet.andre@gmail.com>
|
||||
* - Andreas Weitl
|
||||
* - Bertrand Songis <bsongis@gmail.com>
|
||||
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
|
||||
* - Cameron Weeks <th9xer@gmail.com>
|
||||
* - Erez Raviv
|
||||
* - Gabriel Birkus
|
||||
* - Jean-Pierre Parisy
|
||||
* - Karl Szmutny
|
||||
* - Michael Blandford
|
||||
* - Michal Hlavinka
|
||||
* - Pat Mackenzie
|
||||
* - Philip Moss
|
||||
* - Rob Thomson
|
||||
* - Romolo Manfredini <romolo.manfredini@gmail.com>
|
||||
* - 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)
|
||||
{
|
||||
#warning en double !
|
||||
return 0;
|
||||
}
|
||||
|
||||
int circularIncDec(int current, int incr, int min, int max, IsValueAvailable isValueAvailable)
|
||||
{
|
||||
do {
|
||||
current += incr;
|
||||
if (current < min)
|
||||
current = max;
|
||||
else if (current > max)
|
||||
current = min;
|
||||
if (!isValueAvailable || isValueAvailable(current))
|
||||
return current;
|
||||
} while(1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool isInputAvailable(int input)
|
||||
{
|
||||
for (int i=0; i<MAX_EXPOS; i++) {
|
||||
ExpoData * expo = expoAddress(i);
|
||||
if (!EXPO_VALID(expo))
|
||||
break;
|
||||
if (expo->chn == input)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isChannelUsed(int channel)
|
||||
{
|
||||
for (int i=0; i<MAX_MIXERS; ++i) {
|
||||
MixData *md = mixAddress(i);
|
||||
if (md->srcRaw == 0) return false;
|
||||
if (md->destCh == channel) return true;
|
||||
if (md->destCh > channel) return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int getChannelsUsed()
|
||||
{
|
||||
int result = 0;
|
||||
int lastCh = -1;
|
||||
for (int i=0; i<MAX_MIXERS; ++i) {
|
||||
MixData *md = mixAddress(i);
|
||||
if (md->srcRaw == 0) return result;
|
||||
if (md->destCh != lastCh) { ++result; lastCh = md->destCh; }
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
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<scriptInputsOutputs[qr.quot].outputsCount);
|
||||
}
|
||||
#else
|
||||
if (source>=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) {
|
||||
return isChannelUsed(source-MIXSRC_CH1);
|
||||
}
|
||||
|
||||
if (source>=MIXSRC_FIRST_LOGICAL_SWITCH && source<=MIXSRC_LAST_LOGICAL_SWITCH) {
|
||||
LogicalSwitchData * cs = lswAddress(source-MIXSRC_FIRST_LOGICAL_SWITCH);
|
||||
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_SW1)
|
||||
return true;
|
||||
|
||||
if (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 (swtch <= SWSRC_FIRST_SWITCH) {
|
||||
return true;
|
||||
}
|
||||
|
||||
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 isLogicalSwitchFunctionAvailable(int function)
|
||||
{
|
||||
return function != LS_FUNC_RANGE;
|
||||
}
|
||||
|
||||
bool isAssignableFunctionAvailable(int function)
|
||||
{
|
||||
#if defined(OVERRIDE_CHANNEL_FUNCTION) || defined(GVARS)
|
||||
bool modelFunctions = (g_menuStack[g_menuStackPtr] == menuModelCustomFunctions);
|
||||
#endif
|
||||
|
||||
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
|
||||
#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_RESERVE4:
|
||||
case FUNC_RESERVE5:
|
||||
return false;
|
||||
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool isModuleAvailable(int module)
|
||||
{
|
||||
if (module == MODULE_TYPE_NONE)
|
||||
return false;
|
||||
|
||||
#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);
|
||||
}
|
||||
@@ -0,0 +1,964 @@
|
||||
/*
|
||||
* Authors (alphabetical order)
|
||||
* - Andre Bernet <bernet.andre@gmail.com>
|
||||
* - Andreas Weitl
|
||||
* - Bertrand Songis <bsongis@gmail.com>
|
||||
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
|
||||
* - Cameron Weeks <th9xer@gmail.com>
|
||||
* - Erez Raviv
|
||||
* - Gabriel Birkus
|
||||
* - Jean-Pierre Parisy
|
||||
* - Karl Szmutny
|
||||
* - Michael Blandford
|
||||
* - Michal Hlavinka
|
||||
* - Pat Mackenzie
|
||||
* - Philip Moss
|
||||
* - Rob Thomson
|
||||
* - Romolo Manfredini <romolo.manfredini@gmail.com>
|
||||
* - 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"
|
||||
|
||||
#if defined(SIMU)
|
||||
display_t displayBuf[DISPLAY_BUF_SIZE];
|
||||
#endif
|
||||
|
||||
uint16_t lcdColorTable[LCD_COLOR_COUNT];
|
||||
|
||||
#define PIXEL_PTR(x, y) &displayBuf[(y)*LCD_W + (x)]
|
||||
|
||||
void lcdColorsInit()
|
||||
{
|
||||
lcdColorTable[TEXT_COLOR_INDEX] = BLACK;
|
||||
lcdColorTable[TEXT_BGCOLOR_INDEX] = WHITE;
|
||||
lcdColorTable[TEXT_INVERTED_COLOR_INDEX] = WHITE;
|
||||
lcdColorTable[TEXT_INVERTED_BGCOLOR_INDEX] = RED;
|
||||
lcdColorTable[LINE_COLOR_INDEX] = RGB(88, 88, 90);
|
||||
lcdColorTable[SCROLLBOX_COLOR_INDEX] = RED;
|
||||
lcdColorTable[MENU_TITLE_BGCOLOR_INDEX] = DARKGREY;
|
||||
lcdColorTable[MENU_TITLE_COLOR_INDEX] = WHITE;
|
||||
lcdColorTable[HEADER_COLOR_INDEX] = DARKGREY;
|
||||
lcdColorTable[ALARM_COLOR_INDEX] = RED;
|
||||
lcdColorTable[WARNING_COLOR_INDEX] = YELLOW;
|
||||
lcdColorTable[TEXT_DISABLE_COLOR_INDEX] = RGB(0x60, 0x60, 0x60);
|
||||
lcdColorTable[CURVE_AXIS_COLOR_INDEX] = BLUE;
|
||||
lcdColorTable[TITLE_BGCOLOR_INDEX] = RED;
|
||||
lcdColorTable[HEADER_BGCOLOR_INDEX] = DARKRED;
|
||||
}
|
||||
|
||||
coord_t lcdLastPos;
|
||||
coord_t lcdNextPos;
|
||||
|
||||
#define FONT_CHARS_COUNT 103
|
||||
|
||||
char getMappedChar(unsigned char c)
|
||||
{
|
||||
if (c == 0)
|
||||
return 0;
|
||||
else if (c < 0xC0)
|
||||
return c - 0x20;
|
||||
else
|
||||
return c - 0xC0 + 96;
|
||||
}
|
||||
|
||||
int getFontPatternWidth(const uint16_t *spec, int index)
|
||||
{
|
||||
return spec[index+1] - spec[index];
|
||||
}
|
||||
|
||||
int getCharWidth(char c, const uint16_t *spec)
|
||||
{
|
||||
return getFontPatternWidth(spec, getMappedChar(c));
|
||||
}
|
||||
|
||||
void lcdDrawBitmapPattern(coord_t x, coord_t y, const uint8_t * img, LcdFlags flags, coord_t offset, coord_t width)
|
||||
{
|
||||
coord_t w = *((uint16_t *)img);
|
||||
coord_t height = *(((uint16_t *)img)+1);
|
||||
|
||||
if (!width || width > w) {
|
||||
width = w;
|
||||
}
|
||||
|
||||
if (x+width > LCD_W) {
|
||||
width = LCD_W-x;
|
||||
}
|
||||
|
||||
display_t color = lcdColorTable[COLOR_IDX(flags)];
|
||||
|
||||
for (coord_t row=0; row<height; row++) {
|
||||
display_t * p = PIXEL_PTR(x, y+row);
|
||||
const uint8_t * q = img + 4 + row*w + offset;
|
||||
for (coord_t col=0; col<width; col++) {
|
||||
lcdDrawTransparentPixel(p, *q, color);
|
||||
p++; q++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define FONT_MAX_HEIGHT 42
|
||||
void lcdPutFontPattern(coord_t x, coord_t y, const uint8_t * font, const uint16_t * spec, int index, LcdFlags flags)
|
||||
{
|
||||
bool blink = false;
|
||||
bool inv = false;
|
||||
if (flags & BLINK) {
|
||||
if (BLINK_ON_PHASE) {
|
||||
if (flags & INVERS)
|
||||
inv = true;
|
||||
else {
|
||||
blink = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (flags & INVERS) {
|
||||
inv = true;
|
||||
}
|
||||
|
||||
coord_t w = *((uint16_t *)font);
|
||||
coord_t width = getFontPatternWidth(spec, index);
|
||||
coord_t height = *(((uint16_t *)font)+1);
|
||||
|
||||
assert(height <= FONT_MAX_HEIGHT);
|
||||
|
||||
for (int i=0; i<width+2; i++) {
|
||||
if (x < LCD_W) {
|
||||
uint8_t b[FONT_MAX_HEIGHT] = { 0 };
|
||||
if (i == 0) {
|
||||
if (x==0 || !inv) {
|
||||
lcdNextPos++;
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
// we need to work on the previous x when INVERS
|
||||
x--;
|
||||
}
|
||||
}
|
||||
else if (i <= width) {
|
||||
for (coord_t j=0; j<height; ++j) {
|
||||
uint8_t p = *(font + 4 + j*w + spec[index] + i - 1);
|
||||
b[j] = p;
|
||||
}
|
||||
}
|
||||
|
||||
for (int j=-1; j<=height; ++j) {
|
||||
uint8_t plot;
|
||||
if (j < 0 || j == height) {
|
||||
plot = 0;
|
||||
if (j<0 && !inv) continue;
|
||||
if (y+j < 0) continue;
|
||||
}
|
||||
else {
|
||||
plot = b[j];
|
||||
}
|
||||
if (inv) plot = !plot;
|
||||
if (!blink) {
|
||||
if (plot) {
|
||||
lcdDrawTransparentPixel(x, y+j, plot, lcdColorTable[COLOR_IDX(flags)]);
|
||||
}
|
||||
// TODO needed?
|
||||
// else if (flags & ERASEBG) {
|
||||
// lcdDrawPoint(x, y+j, 0x0FFF0000);
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
x++;
|
||||
lcdNextPos++;
|
||||
}
|
||||
|
||||
lcdNextPos--;
|
||||
}
|
||||
|
||||
void lcd_putcAtt(coord_t x, coord_t y, const unsigned char c, LcdFlags flags)
|
||||
{
|
||||
lcdNextPos = x-1;
|
||||
int fontindex = FONTSIZE(flags) >> 8;
|
||||
const pm_uchar * font = fontsTable[fontindex];
|
||||
const uint16_t * fontspecs = fontspecsTable[fontindex];
|
||||
lcdPutFontPattern(x, y, font, fontspecs, getMappedChar(c), flags);
|
||||
}
|
||||
|
||||
void lcd_putc(coord_t x, coord_t y, const unsigned char c)
|
||||
{
|
||||
lcd_putcAtt(x, y, c, 0);
|
||||
}
|
||||
|
||||
uint8_t getStringInfo(const char *s)
|
||||
{
|
||||
uint8_t result = 0;
|
||||
for (int i=0; s[i]; i++) {
|
||||
result += s[i];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int getFontHeight(LcdFlags flags)
|
||||
{
|
||||
static const int heightTable[16] = { 12, 10, 11, 14, 18, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12 };
|
||||
return heightTable[FONTSIZE(flags) >> 8];
|
||||
}
|
||||
|
||||
int getTextWidth(const pm_char *s, int len, LcdFlags flags)
|
||||
{
|
||||
const uint16_t *specs = fontspecsTable[FONTSIZE(flags) >> 8];
|
||||
int result = 0;
|
||||
for (int i=0; (len==0 || i<len) && (*s!='\0'); ++i) {
|
||||
char c;
|
||||
if (flags & ZCHAR)
|
||||
c = idx2char(*s);
|
||||
else
|
||||
c = pgm_read_byte(s);
|
||||
result += getCharWidth(c, specs);
|
||||
++s;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void lcd_putsnAtt(coord_t x, coord_t y, const pm_char * s, uint8_t len, LcdFlags flags)
|
||||
{
|
||||
int width = getTextWidth(s, len, flags);
|
||||
int height = getFontHeight(flags);
|
||||
|
||||
if ((flags&INVERS) && ((~flags & BLINK) || BLINK_ON_PHASE)) {
|
||||
if ((COLOR_IDX(flags) == TEXT_COLOR_INDEX)) {
|
||||
flags += TEXT_INVERTED_COLOR - TEXT_COLOR;
|
||||
if (FONTSIZE(flags) == TINSIZE)
|
||||
lcdDrawFilledRect(x-INVERT_HORZ_MARGIN+2, y-INVERT_VERT_MARGIN+2, width+2*INVERT_HORZ_MARGIN-5, INVERT_LINE_HEIGHT-7, TEXT_INVERTED_BGCOLOR);
|
||||
else if (FONTSIZE(flags) == SMLSIZE)
|
||||
lcdDrawFilledRect(x-INVERT_HORZ_MARGIN+1, y-INVERT_VERT_MARGIN, width+2*INVERT_HORZ_MARGIN-2, INVERT_LINE_HEIGHT, TEXT_INVERTED_BGCOLOR);
|
||||
else
|
||||
lcdDrawFilledRect(x-INVERT_HORZ_MARGIN, y-INVERT_VERT_MARGIN, width+2*INVERT_HORZ_MARGIN, INVERT_LINE_HEIGHT, TEXT_INVERTED_BGCOLOR);
|
||||
}
|
||||
flags &= ~(INVERS|BLINK);
|
||||
}
|
||||
|
||||
char str[256];
|
||||
if (flags & ZCHAR)
|
||||
strcat_zchar(str, s, len);
|
||||
else
|
||||
strAppend(str, s, len);
|
||||
|
||||
const coord_t orig_x = x;
|
||||
bool setx = false;
|
||||
while (len--) {
|
||||
unsigned char c;
|
||||
if (flags & ZCHAR)
|
||||
c = idx2char(*s);
|
||||
else
|
||||
c = pgm_read_byte(s);
|
||||
if (setx) {
|
||||
x = c;
|
||||
setx = false;
|
||||
}
|
||||
else if (!c) {
|
||||
break;
|
||||
}
|
||||
else if (c >= 0x20) {
|
||||
lcd_putcAtt(x, y, c, flags);
|
||||
x = lcdNextPos;
|
||||
}
|
||||
else if (c == 0x1F) { // X-coord prefix
|
||||
setx = true;
|
||||
}
|
||||
else if (c == 0x1E) {
|
||||
x = orig_x;
|
||||
y += height;
|
||||
}
|
||||
else if (c == 1) {
|
||||
x += 1;
|
||||
}
|
||||
else {
|
||||
x += 2*(c-1);
|
||||
}
|
||||
s++;
|
||||
}
|
||||
lcdLastPos = x;
|
||||
lcdNextPos = x;
|
||||
}
|
||||
|
||||
void lcd_putsn(coord_t x, coord_t y, const pm_char * s, uint8_t len)
|
||||
{
|
||||
lcd_putsnAtt(x, y, s, len, TEXT_COLOR);
|
||||
}
|
||||
|
||||
void lcd_putsAtt(coord_t x, coord_t y, const pm_char * s, LcdFlags flags)
|
||||
{
|
||||
lcd_putsnAtt(x, y, s, 255, flags);
|
||||
}
|
||||
|
||||
void lcd_puts(coord_t x, coord_t y, const pm_char * s)
|
||||
{
|
||||
lcd_putsAtt(x, y, s, 0);
|
||||
}
|
||||
|
||||
void lcd_putsLeft(coord_t y, const pm_char * s)
|
||||
{
|
||||
lcd_puts(MENU_TITLE_LEFT, y, s);
|
||||
}
|
||||
|
||||
void lcd_putsCenter(coord_t y, const pm_char * s, LcdFlags attr)
|
||||
{
|
||||
int x = (LCD_W - getTextWidth(s)) / 2;
|
||||
lcd_putsAtt(x, y, s, attr);
|
||||
}
|
||||
|
||||
void lcd_putsiAtt(coord_t x, coord_t y, const pm_char * s,uint8_t idx, LcdFlags flags)
|
||||
{
|
||||
uint8_t length;
|
||||
length = pgm_read_byte(s++);
|
||||
lcd_putsnAtt(x, y, s+length*idx, length, flags & ~ZCHAR);
|
||||
}
|
||||
|
||||
void lcd_outhex4(coord_t x, coord_t y, uint32_t val, LcdFlags flags)
|
||||
{
|
||||
char s[5];
|
||||
for (int i=0; i<4; i++) {
|
||||
char c = val & 0xf;
|
||||
s[3-i] = c>9 ? c+'A'-10 : c+'0';
|
||||
val >>= 4;
|
||||
}
|
||||
s[4] = '\0';
|
||||
if (!(flags & LEFT))
|
||||
x -= getTextWidth(s);
|
||||
else
|
||||
flags -= LEFT;
|
||||
lcd_putsAtt(x, y, s, flags);
|
||||
}
|
||||
|
||||
void lcd_outdez8(coord_t x, coord_t y, int8_t val)
|
||||
{
|
||||
lcd_outdezAtt(x, y, val);
|
||||
}
|
||||
|
||||
void lcd_outdezAtt(coord_t x, coord_t y, lcdint_t val, LcdFlags flags, const char *suffix, const char *prefix)
|
||||
{
|
||||
lcd_outdezNAtt(x, y, val, flags, 0, suffix, prefix);
|
||||
}
|
||||
|
||||
void lcd_outdezNAtt(coord_t x, coord_t y, lcdint_t val, LcdFlags flags, int len, const char *suffix, const char *prefix)
|
||||
{
|
||||
char str[48+1]; // max=16 for the prefix, 16 chars for the number, 16 chars for the suffix
|
||||
char *s = str+32;
|
||||
*s = '\0';
|
||||
int idx = 0;
|
||||
int mode = MODE(flags);
|
||||
bool neg = false;
|
||||
if (val < 0) {
|
||||
val = -val;
|
||||
neg = true;
|
||||
}
|
||||
do {
|
||||
*--s = '0' + (val % 10);
|
||||
++idx;
|
||||
val /= 10;
|
||||
if (mode!=0 && idx==mode) {
|
||||
mode = 0;
|
||||
*--s = '.';
|
||||
if (val==0)
|
||||
*--s = '0';
|
||||
}
|
||||
} while (val!=0 || mode>0 || (mode==MODE(LEADING0) && idx<len));
|
||||
if (neg) *--s = '-';
|
||||
if (!(flags & LEFT))
|
||||
x -= getTextWidth(s, 0, flags);
|
||||
// TODO needs check on all string lengths ...
|
||||
if (prefix) {
|
||||
int len = strlen(prefix);
|
||||
if (len <= 16) {
|
||||
s -= len;
|
||||
strncpy(s, prefix, len);
|
||||
}
|
||||
}
|
||||
if (suffix) {
|
||||
strncpy(&str[32], suffix, 16);
|
||||
}
|
||||
flags &= ~(LEADING0|LEFT);
|
||||
lcd_putsAtt(x, y, s, flags);
|
||||
}
|
||||
|
||||
void lcd_hline(coord_t x, coord_t y, coord_t w, LcdFlags att)
|
||||
{
|
||||
lcd_hlineStip(x, y, w, 0xff, att);
|
||||
}
|
||||
|
||||
#if !defined(BOOT)
|
||||
void lcd_line(coord_t x1, coord_t y1, coord_t x2, coord_t y2, uint8_t pat, LcdFlags att)
|
||||
{
|
||||
int dx = x2-x1; /* the horizontal distance of the line */
|
||||
int dy = y2-y1; /* the vertical distance of the line */
|
||||
int dxabs = abs(dx);
|
||||
int dyabs = abs(dy);
|
||||
int sdx = sgn(dx);
|
||||
int sdy = sgn(dy);
|
||||
int x = dyabs>>1;
|
||||
int y = dxabs>>1;
|
||||
int px = x1;
|
||||
int py = y1;
|
||||
|
||||
if (dxabs >= dyabs) {
|
||||
/* the line is more horizontal than vertical */
|
||||
for (int i=0; i<=dxabs; i++) {
|
||||
y += dyabs;
|
||||
if (y>=dxabs) {
|
||||
y -= dxabs;
|
||||
py += sdy;
|
||||
}
|
||||
if ((1<<(px%8)) & pat) {
|
||||
lcdDrawPoint(px, py, att);
|
||||
}
|
||||
px += sdx;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* the line is more vertical than horizontal */
|
||||
for (int i=0; i<=dyabs; i++) {
|
||||
x += dxabs;
|
||||
if (x >= dyabs) {
|
||||
x -= dyabs;
|
||||
px += sdx;
|
||||
}
|
||||
if ((1<<(py%8)) & pat) {
|
||||
lcdDrawPoint(px, py, att);
|
||||
}
|
||||
py += sdy;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void lcd_vline(coord_t x, scoord_t y, scoord_t h)
|
||||
{
|
||||
lcd_vlineStip(x, y, h, SOLID);
|
||||
}
|
||||
|
||||
void lcd_rect(coord_t x, coord_t y, coord_t w, coord_t h, uint8_t pat, LcdFlags att)
|
||||
{
|
||||
if (att & ROUND) {
|
||||
lcd_vlineStip(x, y+1, h-2, pat, att);
|
||||
lcd_vlineStip(x+w-1, y+1, h-2, pat, att);
|
||||
lcd_hlineStip(x+1, y+h-1, w-2, pat, att);
|
||||
lcd_hlineStip(x+1, y, w-2, pat, att);
|
||||
}
|
||||
else {
|
||||
lcd_vlineStip(x, y, h, pat, att);
|
||||
lcd_vlineStip(x+w-1, y, h, pat, att);
|
||||
lcd_hlineStip(x+1, y+h-1, w-2, pat, att);
|
||||
lcd_hlineStip(x+1, y, w-2, pat, att);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(SIMU)
|
||||
void lcdDrawFilledRect(coord_t x, scoord_t y, coord_t w, coord_t h, LcdFlags att)
|
||||
{
|
||||
for (scoord_t i=y; i<y+h; i++) {
|
||||
lcd_hlineStip(x, i, w, SOLID, att);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(BOOT)
|
||||
void lcdDrawFilledRectWithAttributes(coord_t x, scoord_t y, coord_t w, coord_t h, uint8_t pat, LcdFlags att)
|
||||
{
|
||||
for (scoord_t i=y; i<y+h; i++) {
|
||||
if ((att&ROUND) && (i==y || i==y+h-1))
|
||||
lcd_hlineStip(x+1, i, w-2, pat, att);
|
||||
else
|
||||
lcd_hlineStip(x, i, w, pat, att);
|
||||
pat = (pat >> 1) + ((pat & 1) << 7);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void putsRtcTime(coord_t x, coord_t y, LcdFlags att)
|
||||
{
|
||||
putsTimer(x, y, getValue(MIXSRC_TX_TIME), att);
|
||||
}
|
||||
|
||||
void putsTimer(coord_t x, coord_t y, putstime_t tme, LcdFlags att)
|
||||
{
|
||||
div_t qr;
|
||||
|
||||
char str[10]; // "-00:00:00"
|
||||
char *s = str;
|
||||
|
||||
att &= ~LEFT;
|
||||
|
||||
if (tme < 0) {
|
||||
// TODO lcd_putcAtt(x - ((att & DBLSIZE) ? FW+2 : ((att & MIDSIZE) ? FW+0 : FWNUM)), y, '-', att);
|
||||
tme = -tme;
|
||||
*s++ = '-';
|
||||
}
|
||||
|
||||
qr = div(tme, 60);
|
||||
|
||||
if (att & TIMEHOUR) {
|
||||
div_t qr2 = div(qr.quot, 60);
|
||||
*s++ = '0' + (qr2.quot/10);
|
||||
*s++ = '0' + (qr2.quot%10);
|
||||
*s++ = ':';
|
||||
qr.quot = qr2.rem;
|
||||
}
|
||||
|
||||
*s++ = '0' + (qr.quot/10);
|
||||
*s++ = '0' + (qr.quot%10);
|
||||
*s++ = ':';
|
||||
*s++ = '0' + (qr.rem/10);
|
||||
*s++ = '0' + (qr.rem%10);
|
||||
*s = '\0';
|
||||
|
||||
lcd_putsAtt(x, y, str, att);
|
||||
}
|
||||
|
||||
// TODO to be optimized with putsValueWithUnit
|
||||
void putsVolts(coord_t x, coord_t y, uint16_t volts, LcdFlags att)
|
||||
{
|
||||
lcd_outdezAtt(x, y, (int16_t)volts, (~NO_UNIT) & (att | ((att&PREC2)==PREC2 ? 0 : PREC1)), (~att & NO_UNIT) ? "v" : NULL);
|
||||
}
|
||||
|
||||
void putsVBat(coord_t x, coord_t y, LcdFlags att)
|
||||
{
|
||||
putsVolts(x, y, g_vbat100mV, att);
|
||||
}
|
||||
|
||||
void putsStrIdx(coord_t x, coord_t y, const pm_char *str, int idx, LcdFlags att, const char *prefix)
|
||||
{
|
||||
// TODO quick & dirty, dangerous
|
||||
char s[32];
|
||||
sprintf(s, "%s%s%d", prefix, str, abs(idx));
|
||||
lcd_putsAtt(x, y, s, att);
|
||||
}
|
||||
|
||||
void putsMixerSource(coord_t x, coord_t y, uint8_t idx, LcdFlags att)
|
||||
{
|
||||
if (idx == 0) {
|
||||
lcd_putsiAtt(x, y, STR_VSRCRAW, 0, att); // TODO macro
|
||||
}
|
||||
else if (idx <= MIXSRC_LAST_INPUT) {
|
||||
char s[32] = "\307";
|
||||
if (ZEXIST(g_model.inputNames[idx-MIXSRC_FIRST_INPUT])) {
|
||||
zchar2str(s+1, g_model.inputNames[idx-MIXSRC_FIRST_INPUT], LEN_INPUT_NAME);
|
||||
s[1+LEN_INPUT_NAME] = '\0';
|
||||
}
|
||||
else {
|
||||
sprintf(s+1, "%02d", idx);
|
||||
}
|
||||
lcd_putsAtt(x, y, s, att);
|
||||
}
|
||||
|
||||
else if (idx <= MIXSRC_LAST_LUA) {
|
||||
div_t qr = div(idx-MIXSRC_FIRST_LUA, MAX_SCRIPT_OUTPUTS);
|
||||
#if defined(LUA_MODEL_SCRIPTS)
|
||||
if (qr.quot < MAX_SCRIPTS && qr.rem < scriptInputsOutputs[qr.quot].outputsCount) {
|
||||
lcd_putcAtt(x+2, y+1, '1'+qr.quot, TINSIZE);
|
||||
lcdDrawFilledRect(x, y, 7, 7);
|
||||
lcd_putsnAtt(x+8, y, scriptInputsOutputs[qr.quot].outputs[qr.rem].name, att & STREXPANDED ? 9 : 4, att);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
putsStrIdx(x, y, "LUA", qr.quot+1, att);
|
||||
lcd_putcAtt(x+20, y, 'a'+qr.rem, att);
|
||||
}
|
||||
}
|
||||
|
||||
else if (idx < MIXSRC_LAST_POT) {
|
||||
idx = idx-MIXSRC_Rud;
|
||||
if (ZEXIST(g_eeGeneral.anaNames[idx]))
|
||||
lcd_putsnAtt(x, y, g_eeGeneral.anaNames[idx], LEN_ANA_NAME, ZCHAR|att);
|
||||
else
|
||||
lcd_putsiAtt(x, y, STR_VSRCRAW, idx+1, att);
|
||||
}
|
||||
else if (idx >= MIXSRC_FIRST_SWITCH && idx < MIXSRC_FIRST_LOGICAL_SWITCH) {
|
||||
idx = idx-MIXSRC_FIRST_SWITCH;
|
||||
if (ZEXIST(g_eeGeneral.switchNames[idx]))
|
||||
lcd_putsnAtt(x, y, g_eeGeneral.switchNames[idx], LEN_SWITCH_NAME, ZCHAR|att);
|
||||
else
|
||||
lcd_putsiAtt(x, y, STR_VSRCRAW, idx+MIXSRC_FIRST_SWITCH-MIXSRC_Rud+1, att);
|
||||
}
|
||||
else if (idx < MIXSRC_SW1)
|
||||
lcd_putsiAtt(x, y, STR_VSRCRAW, idx-MIXSRC_Rud+1, att);
|
||||
else if (idx <= MIXSRC_LAST_LOGICAL_SWITCH)
|
||||
putsSwitches(x, y, SWSRC_SW1+idx-MIXSRC_SW1, att);
|
||||
else if (idx < MIXSRC_CH1)
|
||||
putsStrIdx(x, y, STR_PPM_TRAINER, idx-MIXSRC_FIRST_TRAINER+1, att);
|
||||
else if (idx <= MIXSRC_LAST_CH) {
|
||||
putsStrIdx(x, y, STR_CH, idx-MIXSRC_CH1+1, att);
|
||||
#if 0
|
||||
if (ZEXIST(g_model.limitData[idx-MIXSRC_CH1].name) && (att & STREXPANDED)) {
|
||||
lcd_putcAtt(lcdLastPos, y, ' ', att);
|
||||
lcd_putsnAtt(lcdLastPos+3, y, g_model.limitData[idx-MIXSRC_CH1].name, LEN_CHANNEL_NAME, ZCHAR|att);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else if (idx <= MIXSRC_LAST_GVAR)
|
||||
putsStrIdx(x, y, STR_GV, idx-MIXSRC_GVAR1+1, att);
|
||||
else if (idx < MIXSRC_FIRST_TELEM) {
|
||||
lcd_putsiAtt(x, y, STR_VSRCRAW, idx-MIXSRC_Rud+1-NUM_LOGICAL_SWITCH-NUM_TRAINER-NUM_CHNOUT-MAX_GVARS, att);
|
||||
}
|
||||
else {
|
||||
idx -= MIXSRC_FIRST_TELEM;
|
||||
div_t qr = div(idx, 3);
|
||||
char s[sizeof(g_model.telemetrySensors[qr.quot].label)+2];
|
||||
int pos = zchar2str(s, g_model.telemetrySensors[qr.quot].label, sizeof(g_model.telemetrySensors[qr.quot].label));
|
||||
if (qr.rem) s[pos++] = (qr.rem==2 ? '+' : '-');
|
||||
s[pos] = '\0';
|
||||
lcd_putsAtt(x, y, s, att);
|
||||
}
|
||||
}
|
||||
|
||||
void putsChnLetter(coord_t x, coord_t y, uint8_t idx, LcdFlags att)
|
||||
{
|
||||
lcd_putsiAtt(x, y, STR_RETA123, idx-1, att);
|
||||
}
|
||||
|
||||
void putsModelName(coord_t x, coord_t y, char *name, uint8_t id, LcdFlags att)
|
||||
{
|
||||
uint8_t len = sizeof(g_model.header.name);
|
||||
while (len>0 && !name[len-1]) --len;
|
||||
if (len==0) {
|
||||
putsStrIdx(x, y, STR_MODEL, id+1, att|LEADING0);
|
||||
}
|
||||
else {
|
||||
lcd_putsnAtt(x, y, name, sizeof(g_model.header.name), ZCHAR|att);
|
||||
}
|
||||
}
|
||||
|
||||
void putsSwitches(coord_t x, coord_t y, int8_t idx, LcdFlags att)
|
||||
{
|
||||
if (idx == SWSRC_OFF)
|
||||
return lcd_putsiAtt(x, y, STR_OFFON, 0, att);
|
||||
|
||||
char s[8];
|
||||
int pos = 0;
|
||||
if (idx < 0) {
|
||||
s[pos++] = '!';
|
||||
}
|
||||
|
||||
int absidx = abs(idx);
|
||||
|
||||
#if defined(FLIGHT_MODES)
|
||||
if (absidx >= SWSRC_FIRST_FLIGHT_MODE) {
|
||||
return putsStrIdx(x, y, STR_FP, absidx-SWSRC_FIRST_FLIGHT_MODE, att, idx < 0 ? "!" : "");
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (absidx >= SWSRC_FIRST_SWITCH && absidx <= SWSRC_LAST_SWITCH) {
|
||||
div_t swinfo = switchInfo(absidx);
|
||||
if (ZEXIST(g_eeGeneral.switchNames[swinfo.quot])) {
|
||||
pos = zchar2str(&s[pos], g_eeGeneral.switchNames[swinfo.quot], LEN_SWITCH_NAME);
|
||||
s[pos++] = "\300-\301"[swinfo.rem];
|
||||
s[pos] = '\0';
|
||||
lcd_putsAtt(x, y, s, att);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
strAppend(&s[pos], STR_VSWITCHES+1+absidx*STR_VSWITCHES[0], STR_VSWITCHES[0]);
|
||||
lcd_putsAtt(x, y, s, att);
|
||||
}
|
||||
|
||||
#if defined(FLIGHT_MODES)
|
||||
void putsFlightMode(coord_t x, coord_t y, int8_t idx, LcdFlags att)
|
||||
{
|
||||
if (idx==0) {
|
||||
lcd_putsiAtt(x, y, STR_MMMINV, 0, att);
|
||||
}
|
||||
else {
|
||||
putsStrIdx(x, y, STR_FP, abs(idx)-1, att);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void putsCurveRef(coord_t x, coord_t y, CurveRef &curve, LcdFlags att)
|
||||
{
|
||||
if (curve.value != 0) {
|
||||
switch (curve.type) {
|
||||
case CURVE_REF_DIFF:
|
||||
lcd_putsAtt(x, y, "D", att);
|
||||
GVAR_MENU_ITEM(x+8, y, curve.value, -100, 100, LEFT|att, 0, 0);
|
||||
break;
|
||||
|
||||
case CURVE_REF_EXPO:
|
||||
lcd_putsAtt(x, y, "E", att);
|
||||
GVAR_MENU_ITEM(x+8, y, curve.value, -100, 100, LEFT|att, 0, 0);
|
||||
break;
|
||||
|
||||
case CURVE_REF_FUNC:
|
||||
lcd_putsiAtt(x, y, STR_VCURVEFUNC, curve.value, att);
|
||||
break;
|
||||
|
||||
case CURVE_REF_CUSTOM:
|
||||
putsCurve(x, y, curve.value, att);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void putsCurve(coord_t x, coord_t y, int8_t idx, LcdFlags att)
|
||||
{
|
||||
if (idx == 0) {
|
||||
return lcd_putsiAtt(x, y, STR_MMMINV, 0, att);
|
||||
}
|
||||
bool neg = false;
|
||||
if (idx < 0) {
|
||||
idx = -idx;
|
||||
neg = true;
|
||||
}
|
||||
putsStrIdx(x, y, STR_CV, idx, att);
|
||||
if (neg) {
|
||||
if ((att&INVERS) && ((~att&BLINK) || BLINK_ON_PHASE))
|
||||
att &= ~(INVERS|BLINK);
|
||||
lcd_putcAtt(x-3, y, '!', att);
|
||||
}
|
||||
}
|
||||
|
||||
void putsTimerMode(coord_t x, coord_t y, int8_t mode, LcdFlags att)
|
||||
{
|
||||
if (mode >= 0) {
|
||||
if (mode < TMRMODE_COUNT)
|
||||
return lcd_putsiAtt(x, y, STR_VTMRMODES, mode, att);
|
||||
else
|
||||
mode -= (TMRMODE_COUNT-1);
|
||||
}
|
||||
putsSwitches(x, y, mode, att);
|
||||
}
|
||||
|
||||
void putsTrimMode(coord_t x, coord_t y, uint8_t phase, uint8_t idx, LcdFlags att)
|
||||
{
|
||||
trim_t v = getRawTrimValue(phase, idx);
|
||||
unsigned int mode = v.mode;
|
||||
unsigned int p = mode >> 1;
|
||||
|
||||
if (mode == TRIM_MODE_NONE) {
|
||||
lcd_putsAtt(x, y, "--", att);
|
||||
}
|
||||
else {
|
||||
char s[2];
|
||||
s[0] = (mode % 2 == 0) ? ':' : '+';
|
||||
s[1] = '0'+p;
|
||||
lcd_putsnAtt(x, y, s, 2, att);
|
||||
}
|
||||
}
|
||||
|
||||
const pm_uint8_t bchunit_ar[] PROGMEM = {
|
||||
UNIT_DIST, // Alt
|
||||
UNIT_RAW, // Rpm
|
||||
UNIT_PERCENT, // Fuel
|
||||
UNIT_TEMPERATURE, // T1
|
||||
UNIT_TEMPERATURE, // T2
|
||||
UNIT_KTS, // Speed
|
||||
UNIT_DIST, // Dist
|
||||
UNIT_DIST, // GPS Alt
|
||||
};
|
||||
|
||||
void putsValueWithUnit(coord_t x, coord_t y, lcdint_t val, uint8_t unit, LcdFlags att)
|
||||
{
|
||||
// convertUnit(val, unit);
|
||||
if (!(att & NO_UNIT) && unit != UNIT_RAW) {
|
||||
char unitStr[8];
|
||||
strAppend(unitStr, STR_VTELEMUNIT+1+unit*STR_VTELEMUNIT[0], STR_VTELEMUNIT[0]);
|
||||
lcd_outdezAtt(x, y, val, att, unitStr);
|
||||
}
|
||||
else {
|
||||
lcd_outdezAtt(x, y, val, att);
|
||||
}
|
||||
}
|
||||
|
||||
void displayDate(coord_t x, coord_t y, TelemetryItem & telemetryItem, LcdFlags att)
|
||||
{
|
||||
}
|
||||
|
||||
void displayGpsCoords(coord_t x, coord_t y, TelemetryItem & telemetryItem, LcdFlags att)
|
||||
{
|
||||
}
|
||||
|
||||
void putsTelemetryChannelValue(coord_t x, coord_t y, uint8_t channel, lcdint_t value, LcdFlags att)
|
||||
{
|
||||
TelemetryItem & telemetryItem = telemetryItems[channel];
|
||||
TelemetrySensor & telemetrySensor = g_model.telemetrySensors[channel];
|
||||
|
||||
if (telemetrySensor.unit == UNIT_DATETIME) {
|
||||
displayDate(x, y, telemetryItem, att);
|
||||
}
|
||||
else if (telemetrySensor.unit == UNIT_GPS) {
|
||||
displayGpsCoords(x, y, telemetryItem, att);
|
||||
}
|
||||
else {
|
||||
LcdFlags flags = att;
|
||||
if (telemetrySensor.prec==2)
|
||||
flags |= PREC2;
|
||||
else if (telemetrySensor.prec==1)
|
||||
flags |= PREC1;
|
||||
putsValueWithUnit(x, y, value, telemetrySensor.unit == UNIT_CELLS ? UNIT_VOLTS : telemetrySensor.unit, flags);
|
||||
}
|
||||
}
|
||||
|
||||
void putsChannelValue(coord_t x, coord_t y, source_t channel, lcdint_t value, LcdFlags att)
|
||||
{
|
||||
if (channel >= MIXSRC_FIRST_TELEM) {
|
||||
channel = (channel-MIXSRC_FIRST_TELEM) / 3;
|
||||
putsTelemetryChannelValue(x, y, channel, value, att);
|
||||
}
|
||||
else if (channel >= MIXSRC_FIRST_TIMER || channel == MIXSRC_TX_TIME) {
|
||||
putsTimer(x, y, value, att);
|
||||
}
|
||||
else if (channel == MIXSRC_TX_VOLTAGE) {
|
||||
lcd_outdezAtt(x, y, value, att|PREC1);
|
||||
}
|
||||
else if (channel < MIXSRC_FIRST_CH) {
|
||||
lcd_outdezAtt(x, y, calcRESXto100(value), att);
|
||||
}
|
||||
else if (channel <= MIXSRC_LAST_CH) {
|
||||
#if defined(PPM_UNIT_PERCENT_PREC1)
|
||||
lcd_outdezAtt(x, y, calcRESXto1000(value), att|PREC1);
|
||||
#else
|
||||
lcd_outdezAtt(x, y, calcRESXto100(value), att);
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
lcd_outdezAtt(x, y, value, att);
|
||||
}
|
||||
}
|
||||
|
||||
void putsChannel(coord_t x, coord_t y, source_t channel, LcdFlags att)
|
||||
{
|
||||
getvalue_t value = getValue(channel);
|
||||
putsChannelValue(x, y, channel, value, att);
|
||||
}
|
||||
|
||||
void lcdSetContrast()
|
||||
{
|
||||
lcdSetRefVolt(g_eeGeneral.contrast);
|
||||
}
|
||||
|
||||
void lcdDrawPixel(display_t * p, display_t value)
|
||||
{
|
||||
*p = value;
|
||||
}
|
||||
|
||||
void lcdDrawTransparentPixel(coord_t x, coord_t y, uint8_t opacity, uint16_t color)
|
||||
{
|
||||
display_t * p = PIXEL_PTR(x, y);
|
||||
lcdDrawTransparentPixel(p, opacity, color);
|
||||
}
|
||||
|
||||
void lcdDrawTransparentPixel(display_t * p, uint8_t opacity, uint16_t color)
|
||||
{
|
||||
ASSERT_IN_DISPLAY(p);
|
||||
|
||||
if (opacity != OPACITY_MAX) {
|
||||
uint8_t bgWeight = OPACITY_MAX - opacity;
|
||||
COLOR_SPLIT(color, red, green, blue);
|
||||
COLOR_SPLIT(*p, bgRed, bgGreen, bgBlue);
|
||||
uint16_t r = (bgRed * bgWeight + red * opacity) / OPACITY_MAX;
|
||||
uint16_t g = (bgGreen * bgWeight + green * opacity) / OPACITY_MAX;
|
||||
uint16_t b = (bgBlue * bgWeight + blue * opacity) / OPACITY_MAX;
|
||||
lcdDrawPixel(p, COLOR_JOIN(r, g, b));
|
||||
}
|
||||
else if (opacity != 0) {
|
||||
lcdDrawPixel(p, color);
|
||||
}
|
||||
}
|
||||
|
||||
void lcdDrawPoint(coord_t x, coord_t y, LcdFlags att)
|
||||
{
|
||||
display_t * p = PIXEL_PTR(x, y);
|
||||
display_t color = lcdColorTable[COLOR_IDX(att)];
|
||||
if (p < DISPLAY_END) {
|
||||
*p = color;
|
||||
}
|
||||
}
|
||||
|
||||
void lcd_hlineStip(coord_t x, coord_t y, coord_t w, uint8_t pat, LcdFlags att)
|
||||
{
|
||||
if (y >= LCD_H) return;
|
||||
if (x+w > LCD_W) { w = LCD_W - x; }
|
||||
|
||||
display_t * p = PIXEL_PTR(x, y);
|
||||
display_t color = lcdColorTable[COLOR_IDX(att)];
|
||||
|
||||
while (w--) {
|
||||
if (pat&1) {
|
||||
*p = color;
|
||||
// lcd_mask(p, mask, 0);
|
||||
pat = (pat >> 1) | 0x80;
|
||||
}
|
||||
else {
|
||||
pat = pat >> 1;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
}
|
||||
|
||||
void lcd_vlineStip(coord_t x, coord_t y, coord_t h, uint8_t pat, LcdFlags att)
|
||||
{
|
||||
if (x >= LCD_W) return;
|
||||
if (y >= LCD_H) return;
|
||||
if (h<0) { y+=h; h=-h; }
|
||||
if (y<0) { h+=y; y=0; if (h<=0) return; }
|
||||
if (y+h > LCD_H) { h = LCD_H - y; }
|
||||
|
||||
if (pat==DOTTED && !(y%2)) {
|
||||
pat = ~pat;
|
||||
}
|
||||
|
||||
while (h--) {
|
||||
if (pat & 1) {
|
||||
lcdDrawPoint(x, y, att);
|
||||
pat = (pat >> 1) | 0x80;
|
||||
}
|
||||
else {
|
||||
pat = pat >> 1;
|
||||
}
|
||||
y++;
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(BOOT)
|
||||
void lcdDrawBitmap(coord_t x, coord_t y, const uint16_t * img, coord_t offset, coord_t width)
|
||||
{
|
||||
const uint16_t * q = img;
|
||||
coord_t w = *q++;
|
||||
coord_t height = *q++;
|
||||
|
||||
if (!width || width > w) {
|
||||
width = w;
|
||||
}
|
||||
|
||||
if (x+width > LCD_W) {
|
||||
width = LCD_W-x;
|
||||
}
|
||||
|
||||
for (coord_t row=0; row<height; row++) {
|
||||
display_t * p = &displayBuf[(row+y)*LCD_W + x];
|
||||
q = img + 2 + row*w + offset;
|
||||
for (coord_t col=0; col<width; col++) {
|
||||
lcdDrawPixel(p, *q);
|
||||
p++; q++;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void drawBlackOverlay()
|
||||
{
|
||||
// TODO drawFilledRect(0, 0, LCD_W, LCD_H, SOLID, OPAQUE(10, GREY(3)));
|
||||
}
|
||||
@@ -0,0 +1,325 @@
|
||||
/*
|
||||
* Authors (alphabetical order)
|
||||
* - Andre Bernet <bernet.andre@gmail.com>
|
||||
* - Andreas Weitl
|
||||
* - Bertrand Songis <bsongis@gmail.com>
|
||||
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
|
||||
* - Cameron Weeks <th9xer@gmail.com>
|
||||
* - Erez Raviv
|
||||
* - Gabriel Birkus
|
||||
* - Jean-Pierre Parisy
|
||||
* - Karl Szmutny
|
||||
* - Michael Blandford
|
||||
* - Michal Hlavinka
|
||||
* - Pat Mackenzie
|
||||
* - Philip Moss
|
||||
* - Rob Thomson
|
||||
* - Romolo Manfredini <romolo.manfredini@gmail.com>
|
||||
* - 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 _LCD_H_
|
||||
#define _LCD_H_
|
||||
|
||||
#define LCD_W 480
|
||||
#define LCD_H 272
|
||||
|
||||
#define BOX_WIDTH 61
|
||||
#define coord_t int
|
||||
#define scoord_t int
|
||||
#define CENTER
|
||||
#define CENTER_OFS 0
|
||||
#define CONTRAST_MIN 0
|
||||
#define CONTRAST_MAX 45
|
||||
|
||||
#define lcdint_t int32_t
|
||||
#define lcduint_t uint32_t
|
||||
|
||||
#define LCD_LINES 17 // TODO change this constant which has no sense here, the header uses more than one line
|
||||
#define LCD_COLS 30
|
||||
|
||||
#define BSS 0x00
|
||||
#define ERASE 0x00
|
||||
#define FORCE 0x00
|
||||
#define FIXEDWIDTH 0x00
|
||||
#define FILLWHITE 0x00
|
||||
#define BOLD 0x00
|
||||
|
||||
/* lcd common flags */
|
||||
#define BLINK 0x01
|
||||
|
||||
/* lcd text flags */
|
||||
#define INVERS 0x02
|
||||
#define LEFT 0x08 /* align left */
|
||||
|
||||
/* lcd puts flags */
|
||||
#define ZCHAR 0x04
|
||||
|
||||
/* lcd outdez flags */
|
||||
#define LEADING0 0x10
|
||||
#define PREC1 0x20
|
||||
#define PREC2 0x30
|
||||
#define MODE(flags) ((((int8_t)(flags) & 0x30) - 0x10) >> 4)
|
||||
|
||||
/* rect, square flags */
|
||||
#define ROUND 0x02
|
||||
|
||||
/* telemetry flags */
|
||||
#define NO_UNIT 0x40
|
||||
|
||||
#define FONTSIZE(x) ((x) & 0x0700)
|
||||
#define TINSIZE 0x0100
|
||||
#define SMLSIZE 0x0200
|
||||
#define MIDSIZE 0x0300
|
||||
#define DBLSIZE 0x0400
|
||||
#define XXLSIZE 0x0500
|
||||
#define ERASEBG 0x8000
|
||||
#define VERTICAL 0x0800
|
||||
|
||||
#define TIMEBLINK 0x1000
|
||||
#define TIMEHOUR 0x2000
|
||||
#define STREXPANDED 0x4000
|
||||
|
||||
// remove windows default definitions
|
||||
#undef OPAQUE
|
||||
#undef RGB
|
||||
|
||||
#define TO5BITS(x) ((x) >> 3)
|
||||
#define TO6BITS(x) ((x) >> 2)
|
||||
#define RGB(r, g, b) ((TO5BITS(r) << 11) + (TO6BITS(g) << 5) + (TO5BITS(b) << 0))
|
||||
#define WHITE RGB(0xF0, 0xF0, 0xF0)
|
||||
#define BLACK RGB(0, 0, 0)
|
||||
#define YELLOW RGB(0xF0, 0xD0, 0x10)
|
||||
#define BLUE RGB(0x30, 0xA0, 0xE0)
|
||||
#define DARKGREY RGB(0x40, 0x40, 0x40)
|
||||
#define RED RGB(229, 32, 30)
|
||||
#define DARKRED RGB(160, 0, 6)
|
||||
|
||||
#define LcdFlags uint32_t
|
||||
|
||||
enum LcdColorIndex
|
||||
{
|
||||
TEXT_COLOR_INDEX,
|
||||
TEXT_BGCOLOR_INDEX,
|
||||
TEXT_INVERTED_COLOR_INDEX,
|
||||
TEXT_INVERTED_BGCOLOR_INDEX,
|
||||
LINE_COLOR_INDEX,
|
||||
SCROLLBOX_COLOR_INDEX,
|
||||
MENU_TITLE_BGCOLOR_INDEX,
|
||||
MENU_TITLE_COLOR_INDEX,
|
||||
HEADER_COLOR_INDEX,
|
||||
ALARM_COLOR_INDEX,
|
||||
WARNING_COLOR_INDEX,
|
||||
TEXT_DISABLE_COLOR_INDEX,
|
||||
CURVE_AXIS_COLOR_INDEX,
|
||||
HEADER_BGCOLOR_INDEX,
|
||||
TITLE_BGCOLOR_INDEX,
|
||||
LCD_COLOR_COUNT
|
||||
};
|
||||
|
||||
extern uint16_t lcdColorTable[LCD_COLOR_COUNT];
|
||||
void lcdColorsInit();
|
||||
|
||||
#define OPACITY_MAX 0x0F
|
||||
|
||||
#define COLOR(index) ((index) << 16)
|
||||
#define TEXT_COLOR COLOR(TEXT_COLOR_INDEX)
|
||||
#define TEXT_BGCOLOR COLOR(TEXT_BGCOLOR_INDEX)
|
||||
#define TEXT_INVERTED_COLOR COLOR(TEXT_INVERTED_COLOR_INDEX)
|
||||
#define TEXT_INVERTED_BGCOLOR COLOR(TEXT_INVERTED_BGCOLOR_INDEX)
|
||||
#define LINE_COLOR COLOR(LINE_COLOR_INDEX)
|
||||
#define SCROLLBOX_COLOR COLOR(SCROLLBOX_COLOR_INDEX)
|
||||
#define HEADER_SEPARATOR_COLOR COLOR(HEADER_SEPARATOR_COLOR_INDEX)
|
||||
#define MENU_TITLE_BGCOLOR COLOR(MENU_TITLE_BGCOLOR_INDEX)
|
||||
#define MENU_TITLE_COLOR COLOR(MENU_TITLE_COLOR_INDEX)
|
||||
#define HEADER_COLOR COLOR(HEADER_COLOR_INDEX)
|
||||
#define ALARM_COLOR COLOR(ALARM_COLOR_INDEX)
|
||||
#define WARNING_COLOR COLOR(WARNING_COLOR_INDEX)
|
||||
#define TEXT_DISABLE_COLOR COLOR(TEXT_DISABLE_COLOR_INDEX)
|
||||
#define CURVE_AXIS_COLOR COLOR(CURVE_AXIS_COLOR_INDEX)
|
||||
#define TITLE_BGCOLOR COLOR(TITLE_BGCOLOR_INDEX)
|
||||
#define HEADER_BGCOLOR COLOR(HEADER_BGCOLOR_INDEX)
|
||||
|
||||
#define COLOR_IDX(att) uint8_t((att) >> 16)
|
||||
|
||||
#define COLOR_SPLIT(color, r, g, b) \
|
||||
uint16_t r = ((color) & 0xF800) >> 11; \
|
||||
uint16_t g = ((color) & 0x07E0) >> 5; \
|
||||
uint16_t b = ((color) & 0x001F)
|
||||
|
||||
#define COLOR_JOIN(r, g, b) \
|
||||
(((r) << 11) + ((g) << 5) + (b))
|
||||
|
||||
#define display_t uint16_t
|
||||
#define DISPLAY_BUF_SIZE (LCD_W*LCD_H)
|
||||
|
||||
#if defined(SIMU)
|
||||
extern display_t displayBuf[DISPLAY_BUF_SIZE];
|
||||
#else
|
||||
extern uint32_t CurrentFrameBuffer;
|
||||
#define displayBuf ((uint16_t *)CurrentFrameBuffer)
|
||||
#endif
|
||||
|
||||
#define lcdRefreshWait()
|
||||
|
||||
#define DISPLAY_BUFFER_SIZE (sizeof(display_t)*DISPLAY_BUF_SIZE)
|
||||
#define DISPLAY_END (displayBuf + DISPLAY_BUF_SIZE)
|
||||
#define ASSERT_IN_DISPLAY(p) assert((p) >= displayBuf && (p) < DISPLAY_END)
|
||||
|
||||
void lcdStartScreen();
|
||||
void lcd_putc(coord_t x, coord_t y, const unsigned char c);
|
||||
void lcd_putcAtt(coord_t x, coord_t y, const unsigned char c, LcdFlags attr=TEXT_COLOR);
|
||||
void lcd_putsAtt(coord_t x, coord_t y, const pm_char * s, LcdFlags attr=TEXT_COLOR);
|
||||
void lcd_putsiAtt(coord_t x, coord_t y, const pm_char * s, uint8_t idx, LcdFlags attr=TEXT_COLOR);
|
||||
void lcd_putsnAtt(coord_t x, coord_t y, const pm_char * s, unsigned char len, LcdFlags attr=TEXT_COLOR);
|
||||
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);
|
||||
void lcd_putsCenter(coord_t y, const pm_char * s, LcdFlags attr=0);
|
||||
void lcd_outhex4(coord_t x, coord_t y, uint32_t val, LcdFlags mode=0);
|
||||
void lcd_outdezNAtt(coord_t x, coord_t y, lcdint_t val, LcdFlags flags, int len, const char *suffix=NULL, const char *prefix=NULL);
|
||||
void lcd_outdezAtt(coord_t x, coord_t y, lcdint_t val, LcdFlags mode=0, const char *suffix=NULL, const char *prefix=NULL);
|
||||
void lcd_outdez8(coord_t x, coord_t y, int8_t val);
|
||||
|
||||
void putsStrIdx(coord_t x, coord_t y, const pm_char *str, int idx, LcdFlags att=0, const char *prefix="");
|
||||
void putsModelName(coord_t x, coord_t y, char *name, uint8_t id, LcdFlags att);
|
||||
void putsSwitches(coord_t x, coord_t y, int8_t swtch, LcdFlags att=0);
|
||||
void putsMixerSource(coord_t x, coord_t y, uint8_t idx, LcdFlags att=0);
|
||||
void putsFlightMode(coord_t x, coord_t y, int8_t idx, LcdFlags att=0);
|
||||
void putsCurveRef(coord_t x, coord_t y, CurveRef &curve, LcdFlags att=0);
|
||||
void putsCurve(coord_t x, coord_t y, int8_t idx, LcdFlags att=0);
|
||||
void putsTimerMode(coord_t x, coord_t y, int8_t mode, LcdFlags att=0);
|
||||
void putsTrimMode(coord_t x, coord_t y, uint8_t phase, uint8_t idx, LcdFlags att);
|
||||
|
||||
#define putsChn(x, y, idx, att) putsMixerSource(x, y, MIXSRC_CH1+idx-1, att)
|
||||
void putsChnLetter(coord_t x, coord_t y, uint8_t idx, LcdFlags attr);
|
||||
|
||||
void putsVolts(coord_t x, coord_t y, uint16_t volts, LcdFlags att);
|
||||
void putsVBat(coord_t x, coord_t y, LcdFlags att);
|
||||
|
||||
void putsChannelValue(coord_t x, coord_t y, source_t channel, lcdint_t val, LcdFlags att=0);
|
||||
void putsChannel(coord_t x, coord_t y, source_t channel, LcdFlags att=0);
|
||||
void putsTelemetryChannelValue(coord_t x, coord_t y, uint8_t channel, lcdint_t val, LcdFlags att=0);
|
||||
|
||||
#define putstime_t int32_t
|
||||
|
||||
void putsRtcTime(coord_t x, coord_t y, LcdFlags att=0);
|
||||
void putsTimer(coord_t x, coord_t y, putstime_t tme, LcdFlags att=0);
|
||||
|
||||
#define SOLID 0xff
|
||||
#define DOTTED 0x55
|
||||
|
||||
void lcdDrawTransparentPixel(coord_t x, coord_t y, uint8_t opacity, uint16_t color);
|
||||
void lcdDrawTransparentPixel(display_t * p, uint8_t opacity, uint16_t color);
|
||||
void lcdDrawPoint(coord_t x, coord_t y, LcdFlags att=0);
|
||||
void lcd_mask(uint8_t *p, uint8_t mask, LcdFlags att=0);
|
||||
void lcd_hline(coord_t x, coord_t y, coord_t w, LcdFlags att=0);
|
||||
void lcd_hlineStip(coord_t x, coord_t y, coord_t w, uint8_t pat, LcdFlags att=0);
|
||||
void lcd_vline(coord_t x, scoord_t y, scoord_t h);
|
||||
void lcd_vlineStip(coord_t x, scoord_t y, scoord_t h, uint8_t pat, LcdFlags att=0);
|
||||
void lcd_line(coord_t x1, coord_t y1, coord_t x2, coord_t y2, uint8_t pat=SOLID, LcdFlags att=0);
|
||||
|
||||
#if !defined(SIMU)
|
||||
inline void lcdDrawFilledRect(coord_t x, scoord_t y, coord_t w, coord_t h, LcdFlags att)
|
||||
{
|
||||
lcdFillRectangle(x, y, w, h, lcdColorTable[COLOR_IDX(att)]);
|
||||
}
|
||||
#else
|
||||
void lcdDrawFilledRect(coord_t x, scoord_t y, coord_t w, coord_t h, LcdFlags att);
|
||||
#endif
|
||||
|
||||
inline void lcdDrawHorizontalLine(coord_t x, scoord_t y, coord_t w, LcdFlags att)
|
||||
{
|
||||
lcdDrawFilledRect(x, y, w, 1, att);
|
||||
}
|
||||
|
||||
inline void lcdDrawVerticalLine(coord_t x, scoord_t y, coord_t h, LcdFlags att)
|
||||
{
|
||||
lcdDrawFilledRect(x, y, 1, h, att);
|
||||
}
|
||||
|
||||
inline void lcdDrawRect(coord_t x, scoord_t y, coord_t w, coord_t h, LcdFlags att)
|
||||
{
|
||||
lcdDrawVerticalLine(x, y, h, att);
|
||||
lcdDrawVerticalLine(x+w-1, y, h, att);
|
||||
lcdDrawHorizontalLine(x, y, w, att);
|
||||
lcdDrawHorizontalLine(x, y+h-1, w, att);
|
||||
}
|
||||
|
||||
void lcdDrawFilledRectWithAttributes(coord_t x, scoord_t y, coord_t w, coord_t h, uint8_t pat, LcdFlags att);
|
||||
void drawBlackOverlay();
|
||||
void lcd_rect(coord_t x, coord_t y, coord_t w, coord_t h, uint8_t pat=SOLID, LcdFlags att=0);
|
||||
|
||||
inline void lcd_square(coord_t x, coord_t y, coord_t w, LcdFlags att=0) { lcd_rect(x, y, w, w, SOLID, att); }
|
||||
|
||||
void lcdDrawTelemetryTopBar();
|
||||
|
||||
#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);
|
||||
|
||||
int getTextWidth(const pm_char *s, int len=0, LcdFlags flags=0);
|
||||
void lcdDrawBitmap(coord_t x, coord_t y, const uint16_t * img, coord_t offset=0, coord_t width=0);
|
||||
void lcdDrawBitmapPattern(coord_t x, coord_t y, const uint8_t * img, LcdFlags flags=0, coord_t offset=0, coord_t width=0);
|
||||
|
||||
#define lcdSetRefVolt(...)
|
||||
void lcdSetContrast();
|
||||
void lcdInit();
|
||||
#define lcdOff(...)
|
||||
|
||||
void lcdRefresh();
|
||||
void lcdSendByte(uint8_t data);
|
||||
void lcdSend(const uint8_t * data, uint32_t size);
|
||||
void lcdSendString(const char * s);
|
||||
uint32_t lcdReceive(uint8_t * data, uint32_t len);
|
||||
void lcdClearRxBuffer();
|
||||
|
||||
const pm_char * bmpLoad(uint8_t *dest, const char *filename, const unsigned int width, const unsigned int height);
|
||||
|
||||
#if defined(BOOT)
|
||||
#define BLINK_ON_PHASE (0)
|
||||
#else
|
||||
#define BLINK_ON_PHASE (g_blinkTmr10ms & (1<<6))
|
||||
#endif
|
||||
|
||||
#ifdef SIMU
|
||||
extern bool lcd_refresh;
|
||||
extern display_t lcd_buf[DISPLAY_BUF_SIZE];
|
||||
#endif
|
||||
|
||||
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 BITMAP_IDX_SPLASH 0x00
|
||||
#define BITMAP_IDX_ALERT 0x01
|
||||
#define BITMAP_IDX_WARNING 0x02
|
||||
#define BITMAP_IDX_MESSAGE 0x03
|
||||
#define BITMAP_IDX_USB 0x04
|
||||
#define BITMAP_IDX_STICKS_FIRST 0x05 // 4 bitmaps
|
||||
#define BITMAP_IDX_BATTERY_FIRST 0x09 // 5 bitmaps
|
||||
#define BITMAP_IDX_RSSI_FIRST 0x0E // 6 bitmaps
|
||||
#define BITMAP_IDX_CHECKBOX_FIRST 0x14 // 4 bitmaps
|
||||
#define BITMAP_IDX_MODEL_FIRST 0x80
|
||||
|
||||
#endif // _LCD_H_
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Authors (alphabetical order)
|
||||
* - Andre Bernet <bernet.andre@gmail.com>
|
||||
* - Andreas Weitl
|
||||
* - Bertrand Songis <bsongis@gmail.com>
|
||||
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
|
||||
* - Cameron Weeks <th9xer@gmail.com>
|
||||
* - Erez Raviv
|
||||
* - Gabriel Birkus
|
||||
* - Jean-Pierre Parisy
|
||||
* - Karl Szmutny
|
||||
* - Michael Blandford
|
||||
* - Michal Hlavinka
|
||||
* - Pat Mackenzie
|
||||
* - Philip Moss
|
||||
* - Rob Thomson
|
||||
* - Romolo Manfredini <romolo.manfredini@gmail.com>
|
||||
* - 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"
|
||||
|
||||
extern LP_CONST LanguagePack czLanguagePack;
|
||||
extern LP_CONST LanguagePack enLanguagePack;
|
||||
extern LP_CONST LanguagePack esLanguagePack;
|
||||
extern LP_CONST LanguagePack frLanguagePack;
|
||||
extern LP_CONST LanguagePack deLanguagePack;
|
||||
extern LP_CONST LanguagePack itLanguagePack;
|
||||
extern LP_CONST LanguagePack plLanguagePack;
|
||||
extern LP_CONST LanguagePack ptLanguagePack;
|
||||
extern LP_CONST LanguagePack skLanguagePack;
|
||||
extern LP_CONST LanguagePack seLanguagePack;
|
||||
extern LP_CONST LanguagePack huLanguagePack;
|
||||
|
||||
const LanguagePack * LP_CONST languagePacks[] = {
|
||||
// alphabetical order
|
||||
&czLanguagePack,
|
||||
&deLanguagePack,
|
||||
&enLanguagePack,
|
||||
&esLanguagePack,
|
||||
&frLanguagePack,
|
||||
&huLanguagePack,
|
||||
&itLanguagePack,
|
||||
&plLanguagePack,
|
||||
&ptLanguagePack,
|
||||
&seLanguagePack,
|
||||
&skLanguagePack,
|
||||
NULL
|
||||
};
|
||||
|
||||
void menuGeneralSetup(evt_t event);
|
||||
void menuGeneralSdManager(evt_t event);
|
||||
void menuGeneralCustomFunctions(evt_t event);
|
||||
void menuGeneralTrainer(evt_t event);
|
||||
void menuGeneralVersion(evt_t event);
|
||||
void menuGeneralCalib(evt_t event);
|
||||
|
||||
enum EnumTabDiag {
|
||||
e_Setup,
|
||||
e_Sd,
|
||||
e_GeneralCustomFunctions,
|
||||
e_Trainer,
|
||||
e_Calib,
|
||||
e_Vers,
|
||||
};
|
||||
|
||||
const MenuFuncP_PROGMEM menuTabGeneral[] PROGMEM = {
|
||||
menuGeneralSetup,
|
||||
CASE_SDCARD(menuGeneralSdManager)
|
||||
CASE_CPUARM(menuGeneralCustomFunctions)
|
||||
menuGeneralTrainer,
|
||||
menuGeneralCalib,
|
||||
menuGeneralVersion,
|
||||
};
|
||||
|
||||
void menuGeneralCustomFunctions(evt_t event)
|
||||
{
|
||||
MENU(STR_MENUGLOBALFUNCS, menuTabGeneral, e_GeneralCustomFunctions, NUM_CFN, DEFAULT_SCROLLBAR_X, { NAVIGATION_LINE_BY_LINE|4/*repeated*/ });
|
||||
return menuCustomFunctions(event, g_eeGeneral.customFn, globalFunctionsContext);
|
||||
}
|
||||
@@ -0,0 +1,216 @@
|
||||
/*
|
||||
* Authors (alphabetical order)
|
||||
* - Andre Bernet <bernet.andre@gmail.com>
|
||||
* - Andreas Weitl
|
||||
* - Bertrand Songis <bsongis@gmail.com>
|
||||
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
|
||||
* - Cameron Weeks <th9xer@gmail.com>
|
||||
* - Erez Raviv
|
||||
* - Gabriel Birkus
|
||||
* - Jean-Pierre Parisy
|
||||
* - Karl Szmutny
|
||||
* - Michael Blandford
|
||||
* - Michal Hlavinka
|
||||
* - Pat Mackenzie
|
||||
* - Philip Moss
|
||||
* - Rob Thomson
|
||||
* - Romolo Manfredini <romolo.manfredini@gmail.com>
|
||||
* - 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(evt_t event)
|
||||
{
|
||||
for (uint8_t i=0; i<NUM_STICKS+NUM_POTS; i++) { // get low and high vals for sticks and trims
|
||||
int16_t vt = anaIn(i);
|
||||
reusableBuffer.calib.loVals[i] = min(vt, reusableBuffer.calib.loVals[i]);
|
||||
reusableBuffer.calib.hiVals[i] = max(vt, reusableBuffer.calib.hiVals[i]);
|
||||
if (i >= POT1 && i <= POT_LAST) {
|
||||
if (IS_POT_WITHOUT_DETENT(i)) {
|
||||
reusableBuffer.calib.midVals[i] = (reusableBuffer.calib.hiVals[i] + reusableBuffer.calib.loVals[i]) / 2;
|
||||
}
|
||||
#if 0
|
||||
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<count; j++) {
|
||||
int16_t step = reusableBuffer.calib.xpotsCalib[idx].steps[j];
|
||||
if (position >= 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
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_putsCenter(MENU_HEADER_HEIGHT+FH, STR_MENUTOSTART);
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
// SET MIDPOINT
|
||||
lcd_putsCenter(MENU_HEADER_HEIGHT+FH, STR_SETMIDPOINT, INVERS);
|
||||
lcd_putsCenter(MENU_HEADER_HEIGHT+2*FH, STR_MENUWHENDONE);
|
||||
|
||||
for (int i=0; i<NUM_STICKS+NUM_POTS; i++) {
|
||||
reusableBuffer.calib.loVals[i] = 15000;
|
||||
reusableBuffer.calib.hiVals[i] = -15000;
|
||||
reusableBuffer.calib.midVals[i] = anaIn(i);
|
||||
if (i<NUM_XPOTS) {
|
||||
reusableBuffer.calib.xpotsCalib[i].stepsCount = 0;
|
||||
reusableBuffer.calib.xpotsCalib[i].lastCount = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
// MOVE STICKS/POTS
|
||||
STICK_SCROLL_DISABLE();
|
||||
lcd_putsCenter(MENU_HEADER_HEIGHT+FH, STR_MOVESTICKSPOTS, INVERS);
|
||||
lcd_putsCenter(MENU_HEADER_HEIGHT+2*FH, STR_MENUWHENDONE);
|
||||
|
||||
for (int i=0; i<NUM_STICKS+NUM_POTS; i++) {
|
||||
if (abs(reusableBuffer.calib.loVals[i]-reusableBuffer.calib.hiVals[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:
|
||||
#if 0
|
||||
for (int 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; j<count; j++) {
|
||||
for (int k=j+1; k<count; k++) {
|
||||
if (reusableBuffer.calib.xpotsCalib[idx].steps[k] < reusableBuffer.calib.xpotsCalib[idx].steps[j]) {
|
||||
SWAP(reusableBuffer.calib.xpotsCalib[idx].steps[j], reusableBuffer.calib.xpotsCalib[idx].steps[k]);
|
||||
}
|
||||
}
|
||||
}
|
||||
StepsCalibData * calib = (StepsCalibData *) &g_eeGeneral.calib[i];
|
||||
calib->count = count - 1;
|
||||
for (int j=0; j<calib->count; 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));
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
g_eeGeneral.chkSum = evalChkSum();
|
||||
eeDirty(EE_GENERAL);
|
||||
reusableBuffer.calib.state = 4;
|
||||
break;
|
||||
|
||||
default:
|
||||
reusableBuffer.calib.state = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
doMainScreenGraphics();
|
||||
drawPotsBars();
|
||||
|
||||
#if 0
|
||||
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);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void menuGeneralCalib(evt_t event)
|
||||
{
|
||||
SIMPLE_MENU(STR_MENUCALIBRATION, menuTabGeneral, e_Calib, 0, DEFAULT_SCROLLBAR_X);
|
||||
|
||||
if (menuEvent) {
|
||||
calibrationState = 0;
|
||||
}
|
||||
|
||||
menuCommonCalib(READ_ONLY() ? 0 : event);
|
||||
}
|
||||
|
||||
void menuFirstCalib(evt_t event)
|
||||
{
|
||||
if (event == EVT_KEY_BREAK(KEY_EXIT) || reusableBuffer.calib.state == 4) {
|
||||
calibrationState = 0;
|
||||
chainMenu(menuMainView);
|
||||
}
|
||||
else {
|
||||
drawMenuTemplate(STR_MENUCALIBRATION, event);
|
||||
menuCommonCalib(event);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,358 @@
|
||||
/*
|
||||
* Authors (alphabetical order)
|
||||
* - Andre Bernet <bernet.andre@gmail.com>
|
||||
* - Andreas Weitl
|
||||
* - Bertrand Songis <bsongis@gmail.com>
|
||||
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
|
||||
* - Cameron Weeks <th9xer@gmail.com>
|
||||
* - Erez Raviv
|
||||
* - Gabriel Birkus
|
||||
* - Jean-Pierre Parisy
|
||||
* - Karl Szmutny
|
||||
* - Michael Blandford
|
||||
* - Michal Hlavinka
|
||||
* - Pat Mackenzie
|
||||
* - Philip Moss
|
||||
* - Rob Thomson
|
||||
* - Romolo Manfredini <romolo.manfredini@gmail.com>
|
||||
* - 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 REFRESH_FILES() reusableBuffer.sdmanager.offset = 65535
|
||||
|
||||
void menuGeneralSdManagerInfo(evt_t event)
|
||||
{
|
||||
SIMPLE_SUBMENU(STR_SD_INFO_TITLE, 1, DEFAULT_SCROLLBAR_X);
|
||||
|
||||
lcd_putsLeft(2*FH, STR_SD_TYPE);
|
||||
lcd_puts(100, 2*FH, SD_IS_HC() ? STR_SDHC_CARD : STR_SD_CARD);
|
||||
|
||||
lcd_putsLeft(3*FH, STR_SD_SIZE);
|
||||
lcd_outdezAtt(100, 3*FH, sdGetSize(), LEFT, "M");
|
||||
|
||||
lcd_putsLeft(4*FH, STR_SD_SECTORS);
|
||||
#if defined(SD_GET_FREE_BLOCKNR)
|
||||
lcd_outdezAtt(100, 4*FH, SD_GET_FREE_BLOCKNR()/1000, LEFT, "/");
|
||||
lcd_outdezAtt(150, 4*FH, sdGetNoSectors()/1000, LEFT);
|
||||
#else
|
||||
lcd_outdezAtt(100, 4*FH, sdGetNoSectors()/1000, LEFT, "k");
|
||||
#endif
|
||||
|
||||
lcd_putsLeft(5*FH, STR_SD_SPEED);
|
||||
lcd_outdezAtt(100, 5*FH, SD_GET_SPEED()/1000, LEFT, "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];
|
||||
|
||||
// TODO possible buffer overflows here!
|
||||
|
||||
uint8_t index = m_posVert-s_pgOfs;
|
||||
char *line = reusableBuffer.sdmanager.lines[index];
|
||||
|
||||
if (result == STR_SD_INFO) {
|
||||
pushMenu(menuGeneralSdManagerInfo);
|
||||
}
|
||||
else if (result == STR_SD_FORMAT) {
|
||||
POPUP_CONFIRMATION(STR_CONFIRM_FORMAT);
|
||||
}
|
||||
else if (result == STR_COPY_FILE) {
|
||||
clipboard.type = CLIPBOARD_TYPE_SD_FILE;
|
||||
f_getcwd(clipboard.data.sd.directory, CLIPBOARD_PATH_LEN);
|
||||
strncpy(clipboard.data.sd.filename, line, CLIPBOARD_PATH_LEN-1);
|
||||
}
|
||||
else if (result == STR_PASTE) {
|
||||
f_getcwd(lfn, _MAX_LFN);
|
||||
POPUP_WARNING(fileCopy(clipboard.data.sd.filename, clipboard.data.sd.directory, lfn));
|
||||
REFRESH_FILES();
|
||||
}
|
||||
else if (result == STR_RENAME_FILE) {
|
||||
char *ext = getFileExtension(line, SD_SCREEN_FILE_LENGTH+1);
|
||||
if (ext) {
|
||||
memcpy(reusableBuffer.sdmanager.originalName, line, sizeof(reusableBuffer.sdmanager.originalName));
|
||||
// write spaces to allow a longer filename
|
||||
memset(ext, ' ', SD_SCREEN_FILE_LENGTH-LEN_FILE_EXTENSION-(ext-line));
|
||||
line[SD_SCREEN_FILE_LENGTH-LEN_FILE_EXTENSION] = '\0';
|
||||
s_editMode = EDIT_MODIFY_STRING;
|
||||
editNameCursorPos = 0;
|
||||
}
|
||||
}
|
||||
else if (result == STR_DELETE_FILE) {
|
||||
f_getcwd(lfn, _MAX_LFN);
|
||||
strcat(lfn, PSTR("/"));
|
||||
strcat(lfn, line);
|
||||
f_unlink(lfn);
|
||||
REFRESH_FILES();
|
||||
if (m_posVert == reusableBuffer.sdmanager.count-1)
|
||||
m_posVert--;
|
||||
}
|
||||
/* TODO else if (result == STR_LOAD_FILE) {
|
||||
f_getcwd(lfn, _MAX_LFN);
|
||||
strcat(lfn, "/");
|
||||
strcat(lfn, line);
|
||||
POPUP_WARNING(eeLoadModelSD(lfn));
|
||||
} */
|
||||
else if (result == STR_PLAY_FILE) {
|
||||
f_getcwd(lfn, _MAX_LFN);
|
||||
strcat(lfn, "/");
|
||||
strcat(lfn, line);
|
||||
audioQueue.stopAll();
|
||||
audioQueue.playFile(lfn, 0, ID_PLAY_FROM_SD_MANAGER);
|
||||
}
|
||||
#if 0
|
||||
else if (result == STR_ASSIGN_BITMAP) {
|
||||
strAppendFilename(g_model.header.bitmap, line, sizeof(g_model.header.bitmap));
|
||||
memcpy(modelHeaders[g_eeGeneral.currModel].bitmap, g_model.header.bitmap, sizeof(g_model.header.bitmap));
|
||||
eeDirty(EE_MODEL);
|
||||
}
|
||||
#endif
|
||||
else if (result == STR_VIEW_TEXT) {
|
||||
f_getcwd(lfn, _MAX_LFN);
|
||||
strcat(lfn, "/");
|
||||
strcat(lfn, line);
|
||||
pushMenuTextView(lfn);
|
||||
}
|
||||
#if 0
|
||||
else if (result == STR_FLASH_BOOTLOADER) {
|
||||
f_getcwd(lfn, _MAX_LFN);
|
||||
strcat(lfn, "/");
|
||||
strcat(lfn, line);
|
||||
flashBootloader(lfn);
|
||||
}
|
||||
#endif
|
||||
#if defined(LUA)
|
||||
else if (result == STR_EXECUTE_FILE) {
|
||||
f_getcwd(lfn, _MAX_LFN);
|
||||
strcat(lfn, "/");
|
||||
strcat(lfn, line);
|
||||
luaExec(lfn);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void menuGeneralSdManager(evt_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 (s_warning_result) {
|
||||
s_warning_result = 0;
|
||||
displayPopup(STR_FORMATTING);
|
||||
closeLogs();
|
||||
audioQueue.stopSD();
|
||||
if (f_mkfs(0, 1, 0) == FR_OK) {
|
||||
f_chdir("/");
|
||||
REFRESH_FILES();
|
||||
}
|
||||
else {
|
||||
POPUP_WARNING(STR_SDCARD_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
evt_t event = (EVT_KEY_MASK(_event) == KEY_ENTER ? 0 : _event);
|
||||
SIMPLE_MENU(SD_IS_HC() ? STR_SDHC_CARD : STR_SD_CARD, menuTabGeneral, e_Sd, reusableBuffer.sdmanager.count, DEFAULT_SCROLLBAR_X);
|
||||
|
||||
int index = m_posVert-s_pgOfs;
|
||||
|
||||
switch(_event) {
|
||||
case EVT_ENTRY:
|
||||
f_chdir(ROOT_PATH);
|
||||
REFRESH_FILES();
|
||||
break;
|
||||
|
||||
#if 0
|
||||
case EVT_KEY_LONG(KEY_MENU):
|
||||
if (!READ_ONLY() && s_editMode == 0) {
|
||||
killEvents(_event);
|
||||
MENU_ADD_ITEM(STR_SD_INFO); TODO: Implement
|
||||
MENU_ADD_ITEM(STR_SD_FORMAT);
|
||||
menuHandler = onSdManagerMenu;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
case EVT_KEY_BREAK(KEY_EXIT):
|
||||
REFRESH_FILES();
|
||||
break;
|
||||
|
||||
case EVT_KEY_BREAK(KEY_ENTER):
|
||||
if (s_editMode > 0) {
|
||||
break;
|
||||
}
|
||||
else {
|
||||
if (!reusableBuffer.sdmanager.lines[index][SD_SCREEN_FILE_LENGTH+1]) {
|
||||
f_chdir(reusableBuffer.sdmanager.lines[index]);
|
||||
s_pgOfs = 0;
|
||||
m_posVert = 1;
|
||||
index = 1;
|
||||
REFRESH_FILES();
|
||||
killEvents(_event);
|
||||
return;
|
||||
}
|
||||
}
|
||||
// no break
|
||||
|
||||
case EVT_KEY_LONG(KEY_ENTER):
|
||||
killEvents(_event);
|
||||
if (s_editMode == 0) {
|
||||
char *line = reusableBuffer.sdmanager.lines[index];
|
||||
char *ext = getFileExtension(line, SD_SCREEN_FILE_LENGTH+1);
|
||||
if (ext) {
|
||||
if (!strcasecmp(ext, SOUNDS_EXT)) {
|
||||
MENU_ADD_ITEM(STR_PLAY_FILE);
|
||||
}
|
||||
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()) {
|
||||
if (line[SD_SCREEN_FILE_LENGTH+1]) // it's a file
|
||||
MENU_ADD_ITEM(STR_COPY_FILE);
|
||||
if (clipboard.type == CLIPBOARD_TYPE_SD_FILE)
|
||||
MENU_ADD_ITEM(STR_PASTE);
|
||||
// MENU_ADD_ITEM(STR_RENAME_FILE);
|
||||
MENU_ADD_ITEM(STR_DELETE_FILE);
|
||||
}
|
||||
}
|
||||
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-NUM_BODY_LINES) {
|
||||
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], (NUM_BODY_LINES-1)*sizeof(reusableBuffer.sdmanager.lines[0]));
|
||||
memset(reusableBuffer.sdmanager.lines[NUM_BODY_LINES-1], 0xff, SD_SCREEN_FILE_LENGTH);
|
||||
reusableBuffer.sdmanager.lines[NUM_BODY_LINES-1][SD_SCREEN_FILE_LENGTH+1] = 1;
|
||||
}
|
||||
else {
|
||||
memmove(reusableBuffer.sdmanager.lines[1], reusableBuffer.sdmanager.lines[0], (NUM_BODY_LINES-1)*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 (int i=0; i<NUM_BODY_LINES; i++) {
|
||||
char *line = reusableBuffer.sdmanager.lines[i];
|
||||
if (line[0] == '\0' || isFilenameLower(isfile, fn, line)) {
|
||||
if (i < NUM_BODY_LINES-1) memmove(reusableBuffer.sdmanager.lines[i+1], line, sizeof(reusableBuffer.sdmanager.lines[i]) * (NUM_BODY_LINES-1-i));
|
||||
memset(line, 0, sizeof(reusableBuffer.sdmanager.lines[i]));
|
||||
strcpy(line, fn);
|
||||
line[SD_SCREEN_FILE_LENGTH+1] = isfile;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (reusableBuffer.sdmanager.offset == s_pgOfs) {
|
||||
for (int8_t i=NUM_BODY_LINES-1; 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[NUM_BODY_LINES-2]) && isFilenameLower(isfile, fn, reusableBuffer.sdmanager.lines[NUM_BODY_LINES-1])) {
|
||||
memset(reusableBuffer.sdmanager.lines[NUM_BODY_LINES-1], 0, sizeof(reusableBuffer.sdmanager.lines[0]));
|
||||
strcpy(reusableBuffer.sdmanager.lines[NUM_BODY_LINES-1], fn);
|
||||
reusableBuffer.sdmanager.lines[NUM_BODY_LINES-1][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 (int i=0; i<NUM_BODY_LINES; i++) {
|
||||
coord_t y = MENU_CONTENT_TOP + i*FH;
|
||||
LcdFlags attr = (index == i ? INVERS : 0);
|
||||
if (reusableBuffer.sdmanager.lines[i][0]) {
|
||||
if (!reusableBuffer.sdmanager.lines[i][SD_SCREEN_FILE_LENGTH+1]) {
|
||||
char s[SD_SCREEN_FILE_LENGTH+1+2];
|
||||
sprintf(s, "[%s]", reusableBuffer.sdmanager.lines[i]);
|
||||
lcd_putsAtt(MENU_TITLE_LEFT, y, s, attr);
|
||||
}
|
||||
else {
|
||||
lcd_putsAtt(MENU_TITLE_LEFT, y, reusableBuffer.sdmanager.lines[i], attr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,521 @@
|
||||
/*
|
||||
* Authors (alphabetical order)
|
||||
* - Andre Bernet <bernet.andre@gmail.com>
|
||||
* - Andreas Weitl
|
||||
* - Bertrand Songis <bsongis@gmail.com>
|
||||
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
|
||||
* - Cameron Weeks <th9xer@gmail.com>
|
||||
* - Erez Raviv
|
||||
* - Gabriel Birkus
|
||||
* - Jean-Pierre Parisy
|
||||
* - Karl Szmutny
|
||||
* - Michael Blandford
|
||||
* - Michal Hlavinka
|
||||
* - Pat Mackenzie
|
||||
* - Philip Moss
|
||||
* - Rob Thomson
|
||||
* - Romolo Manfredini <romolo.manfredini@gmail.com>
|
||||
* - 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 RADIO_SETUP_2ND_COLUMN 220
|
||||
|
||||
#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,
|
||||
// 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(evt_t event)
|
||||
{
|
||||
#if defined(RTCLOCK)
|
||||
struct gtm t;
|
||||
gettime(&t);
|
||||
|
||||
if ((m_posVert==ITEM_SETUP_DATE || m_posVert==ITEM_SETUP_TIME) &&
|
||||
(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, DEFAULT_SCROLLBAR_X, { 2|NAVIGATION_LINE_BY_LINE, 2|NAVIGATION_LINE_BY_LINE, 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) LABEL(ALARMS), 0, 0, 0, CASE_GPS(0) CASE_GPS(0) CASE_PXX(0) 0, 0, CASE_MAVLINK(0) 0, 0, LABEL(TX_MODE), 0, 1/*to force edit mode*/ });
|
||||
|
||||
int sub = m_posVert;
|
||||
|
||||
for (int i=0; i<NUM_BODY_LINES; i++) {
|
||||
coord_t y = MENU_CONTENT_TOP + i*FH;
|
||||
int k = i+s_pgOfs;
|
||||
LcdFlags blink = ((s_editMode>0) ? BLINK|INVERS : INVERS);
|
||||
LcdFlags attr = (sub == k ? blink : 0);
|
||||
|
||||
switch(k) {
|
||||
case ITEM_SETUP_DATE:
|
||||
{
|
||||
lcd_putsLeft(y, STR_DATE);
|
||||
LcdFlags flags = 0;
|
||||
if (attr && m_posHorz < 0) {
|
||||
flags |= INVERS;
|
||||
lcdDrawFilledRect(RADIO_SETUP_2ND_COLUMN-INVERT_HORZ_MARGIN, y-INVERT_VERT_MARGIN, 85, INVERT_LINE_HEIGHT, TEXT_INVERTED_BGCOLOR);
|
||||
}
|
||||
lcd_putsAtt(RADIO_SETUP_2ND_COLUMN+28, y, "-", flags);
|
||||
lcd_putsAtt(RADIO_SETUP_2ND_COLUMN+53, y, "-", flags);
|
||||
for (uint8_t j=0; j<3; j++) {
|
||||
uint8_t rowattr = (m_posHorz==j ? attr : 0);
|
||||
switch (j) {
|
||||
case 0:
|
||||
lcd_outdezAtt(RADIO_SETUP_2ND_COLUMN, y, t.tm_year+1900, LEFT|flags|rowattr);
|
||||
if (rowattr && s_editMode>0) t.tm_year = checkIncDec(event, t.tm_year, 112, 200, 0);
|
||||
break;
|
||||
case 1:
|
||||
lcd_outdezNAtt(RADIO_SETUP_2ND_COLUMN+36, y, t.tm_mon+1, LEFT|flags|rowattr|LEADING0, 2);
|
||||
if (rowattr && s_editMode>0) 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_2ND_COLUMN+61, y, t.tm_mday, LEFT|flags|rowattr|LEADING0, 2);
|
||||
if (rowattr && s_editMode>0) 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);
|
||||
LcdFlags flags = 0;
|
||||
if (attr && m_posHorz < 0) {
|
||||
flags |= INVERS;
|
||||
lcdDrawFilledRect(RADIO_SETUP_2ND_COLUMN-INVERT_HORZ_MARGIN, y-INVERT_VERT_MARGIN, 85, INVERT_LINE_HEIGHT, TEXT_INVERTED_BGCOLOR);
|
||||
}
|
||||
lcd_putsAtt(RADIO_SETUP_2ND_COLUMN+15, y, ":", flags);
|
||||
lcd_putsAtt(RADIO_SETUP_2ND_COLUMN+35, y, ":", flags);
|
||||
for (uint8_t j=0; j<3; j++) {
|
||||
uint8_t rowattr = (m_posHorz==j ? attr : 0);
|
||||
switch (j) {
|
||||
case 0:
|
||||
lcd_outdezNAtt(RADIO_SETUP_2ND_COLUMN, y, t.tm_hour, flags|rowattr|LEFT|LEADING0, 2);
|
||||
if (rowattr && s_editMode>0) t.tm_hour = checkIncDec(event, t.tm_hour, 0, 23, 0);
|
||||
break;
|
||||
case 1:
|
||||
lcd_outdezNAtt(RADIO_SETUP_2ND_COLUMN+20, y, t.tm_min, flags|rowattr|LEFT|LEADING0, 2);
|
||||
if (rowattr && s_editMode>0) t.tm_min = checkIncDec(event, t.tm_min, 0, 59, 0);
|
||||
break;
|
||||
case 2:
|
||||
lcd_outdezNAtt(RADIO_SETUP_2ND_COLUMN+40, y, t.tm_sec, flags|rowattr|LEFT|LEADING0, 2);
|
||||
if (rowattr && s_editMode>0) 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;
|
||||
}
|
||||
|
||||
#if 0
|
||||
case ITEM_SETUP_BATT_RANGE:
|
||||
{
|
||||
lcd_putsLeft(y, STR_BATTERY_RANGE);
|
||||
LcdFlags color = WHITE;
|
||||
if (attr && m_posHorz < 0) {
|
||||
color = BLACK;
|
||||
lcdDrawFilledRect(RADIO_SETUP_2ND_COLUMN-INVERT_HORZ_MARGIN, y-INVERT_VERT_MARGIN, 90, INVERT_LINE_HEIGHT, TEXT_INVERTED_BGCOLOR);
|
||||
}
|
||||
putsVolts(RADIO_SETUP_2ND_COLUMN, y, 90+g_eeGeneral.vBatMin, color|(m_posHorz==0 ? attr : 0)|LEFT|NO_UNIT);
|
||||
lcd_puts(RADIO_SETUP_2ND_COLUMN+20, y, "-");
|
||||
putsVolts(RADIO_SETUP_2ND_COLUMN+28, y, 120+g_eeGeneral.vBatMax, color|(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;
|
||||
|
||||
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_outdezAtt(RADIO_SETUP_2ND_COLUMN, y, g_eeGeneral.speakerPitch*15, attr|LEFT, "Hz", "+");
|
||||
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, "Hz");
|
||||
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, "Hz");
|
||||
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, STR_MS);
|
||||
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
|
||||
|
||||
#if 0
|
||||
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;
|
||||
#endif
|
||||
|
||||
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, 27, 42); // 2.7-4.2V
|
||||
break;
|
||||
|
||||
#if 0
|
||||
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;
|
||||
}
|
||||
#endif
|
||||
|
||||
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, "m");
|
||||
if (attr) g_eeGeneral.inactivityTimer = checkIncDec(event, g_eeGeneral.inactivityTimer, 0, 250, EE_GENERAL); //0..250minutes
|
||||
break;
|
||||
|
||||
#if 0
|
||||
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, "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;
|
||||
|
||||
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 0
|
||||
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, "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
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
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 0
|
||||
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, STR_MS);
|
||||
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
|
||||
char s[5];
|
||||
for (uint8_t i=0; i<4; i++) {
|
||||
s[i] = STR_RETA123[channel_order(i+1)];
|
||||
}
|
||||
s[4] = '\0';
|
||||
lcd_putsAtt(RADIO_SETUP_2ND_COLUMN, y, s, 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 (int i=0; i<4; i++) {
|
||||
// lcdDrawBitmap((6+4*i)*12, y, ...);
|
||||
}
|
||||
break;
|
||||
|
||||
case ITEM_SETUP_STICK_MODE:
|
||||
{
|
||||
char s[2] = " ";
|
||||
s[0] = '1'+g_eeGeneral.stickMode;
|
||||
lcd_putsAtt(INDENT_WIDTH, y, s, attr);
|
||||
for (uint8_t i=0; i<4; i++) {
|
||||
putsMixerSource((6+4*i)*12, y, MIXSRC_Rud + pgm_read_byte(modn12x3 + 4*g_eeGeneral.stickMode + i));
|
||||
}
|
||||
if (attr && s_editMode>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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* Authors (alphabetical order)
|
||||
* - Andre Bernet <bernet.andre@gmail.com>
|
||||
* - Andreas Weitl
|
||||
* - Bertrand Songis <bsongis@gmail.com>
|
||||
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
|
||||
* - Cameron Weeks <th9xer@gmail.com>
|
||||
* - Erez Raviv
|
||||
* - Gabriel Birkus
|
||||
* - Jean-Pierre Parisy
|
||||
* - Karl Szmutny
|
||||
* - Michael Blandford
|
||||
* - Michal Hlavinka
|
||||
* - Pat Mackenzie
|
||||
* - Philip Moss
|
||||
* - Rob Thomson
|
||||
* - Romolo Manfredini <romolo.manfredini@gmail.com>
|
||||
* - 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_COLUMN_WIDTH 60
|
||||
#define TRAINER_COLUMN_1 MENU_TITLE_LEFT+80
|
||||
#define TRAINER_COLUMN_2 TRAINER_COLUMN_1+TRAINER_COLUMN_WIDTH
|
||||
#define TRAINER_COLUMN_3 TRAINER_COLUMN_2+TRAINER_COLUMN_WIDTH
|
||||
|
||||
#define TRAINER_CALIB_POS 12
|
||||
|
||||
void menuGeneralTrainer(evt_t event)
|
||||
{
|
||||
uint8_t y;
|
||||
bool slave = SLAVE_MODE();
|
||||
|
||||
MENU(STR_MENUTRAINER, menuTabGeneral, e_Trainer, (slave ? 0 : 6), DEFAULT_SCROLLBAR_X, { 2, 2, 2, 2, 0/*, 0*/ });
|
||||
|
||||
if (slave) {
|
||||
lcd_putsCenter(5*FH, STR_SLAVE, TEXT_COLOR);
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t attr;
|
||||
uint8_t blink = ((s_editMode>0) ? BLINK|INVERS : INVERS);
|
||||
|
||||
lcd_putsAtt(TRAINER_COLUMN_1, MENU_HEADER_HEIGHT+1, "Mode", HEADER_COLOR);
|
||||
lcd_putsAtt(TRAINER_COLUMN_2, MENU_HEADER_HEIGHT+1, "Weight", HEADER_COLOR);
|
||||
lcd_putsAtt(TRAINER_COLUMN_3, MENU_HEADER_HEIGHT+1, "Source", HEADER_COLOR);
|
||||
|
||||
y = MENU_CONTENT_TOP + FH;
|
||||
int sub = m_posVert + 1;
|
||||
|
||||
for (int i=1; i<=NUM_STICKS; i++) {
|
||||
uint8_t chan = channel_order(i);
|
||||
volatile TrainerMix *td = &g_eeGeneral.trainer.mix[chan-1];
|
||||
|
||||
putsMixerSource(MENU_TITLE_LEFT, y, MIXSRC_Rud-1+chan, ((sub==i && CURSOR_ON_LINE()) ? INVERS : 0));
|
||||
|
||||
for (int j=0; j<3; j++) {
|
||||
|
||||
attr = ((sub==i && m_posHorz==j) ? blink : 0);
|
||||
|
||||
switch(j) {
|
||||
case 0:
|
||||
lcd_putsiAtt(TRAINER_COLUMN_1, y, STR_TRNMODE, td->mode, attr);
|
||||
if (attr&BLINK) CHECK_INCDEC_GENVAR(event, td->mode, 0, 2);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
lcd_outdezAtt(TRAINER_COLUMN_2, y, td->studWeight, LEFT|attr, "%");
|
||||
if (attr&BLINK) CHECK_INCDEC_GENVAR(event, td->studWeight, -125, 125);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
lcd_putsiAtt(TRAINER_COLUMN_3, y, STR_TRNCHN, td->srcChn, attr);
|
||||
if (attr&BLINK) CHECK_INCDEC_GENVAR(event, td->srcChn, 0, 3);
|
||||
break;
|
||||
}
|
||||
}
|
||||
y += FH;
|
||||
}
|
||||
|
||||
attr = (sub==5) ? blink : 0;
|
||||
lcd_putsLeft(MENU_CONTENT_TOP + 5*FH, STR_MULTIPLIER);
|
||||
lcd_outdezAtt(TRAINER_COLUMN_1, MENU_CONTENT_TOP + 5*FH, g_eeGeneral.PPM_Multiplier+10, LEFT|attr|PREC1);
|
||||
if (attr) CHECK_INCDEC_GENVAR(event, g_eeGeneral.PPM_Multiplier, -10, 40);
|
||||
|
||||
attr = (sub==6) ? INVERS : 0;
|
||||
if (attr) s_editMode = 0;
|
||||
lcd_putsAtt(MENU_TITLE_LEFT, MENU_CONTENT_TOP + 6*FH, STR_CAL, attr);
|
||||
for (int i=0; i<4; i++) {
|
||||
#if defined (PPM_UNIT_PERCENT_PREC1)
|
||||
lcd_outdezAtt(TRAINER_COLUMN_1+i*TRAINER_COLUMN_WIDTH, MENU_CONTENT_TOP + 6*FH, (ppmInput[i]-g_eeGeneral.trainer.calib[i])*2, LEFT|PREC1);
|
||||
#else
|
||||
lcd_outdezAtt(TRAINER_COLUMN_1+i*TRAINER_COLUMN_WIDTH, MENU_CONTENT_TOP + 6*FH, (ppmInput[i]-g_eeGeneral.trainer.calib[i])/5, LEFT);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (attr) {
|
||||
if (event==EVT_KEY_LONG(KEY_ENTER)){
|
||||
memcpy(g_eeGeneral.trainer.calib, ppmInput, sizeof(g_eeGeneral.trainer.calib));
|
||||
eeDirty(EE_GENERAL);
|
||||
AUDIO_WARNING1();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Authors (alphabetical order)
|
||||
* - Andre Bernet <bernet.andre@gmail.com>
|
||||
* - Andreas Weitl
|
||||
* - Bertrand Songis <bsongis@gmail.com>
|
||||
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
|
||||
* - Cameron Weeks <th9xer@gmail.com>
|
||||
* - Erez Raviv
|
||||
* - Gabriel Birkus
|
||||
* - Jean-Pierre Parisy
|
||||
* - Karl Szmutny
|
||||
* - Michael Blandford
|
||||
* - Michal Hlavinka
|
||||
* - Pat Mackenzie
|
||||
* - Philip Moss
|
||||
* - Rob Thomson
|
||||
* - Romolo Manfredini <romolo.manfredini@gmail.com>
|
||||
* - 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(evt_t event)
|
||||
{
|
||||
SIMPLE_MENU(STR_MENUVERSION, menuTabGeneral, e_Vers, 1, DEFAULT_SCROLLBAR_X);
|
||||
|
||||
lcd_putsLeft(MENU_CONTENT_TOP + FH, vers_stamp);
|
||||
lcd_putsLeft(MENU_CONTENT_TOP + 2*FH, date_stamp);
|
||||
lcd_putsLeft(MENU_CONTENT_TOP + 3*FH, time_stamp);
|
||||
lcd_putsLeft(MENU_CONTENT_TOP + 4*FH, eeprom_stamp);
|
||||
|
||||
// TODO EEPROM erase + backup
|
||||
// lcd_putsCenter(MENU_HEADER_HEIGHT+6*FH, STR_EEBACKUP);
|
||||
// if (event == EVT_KEY_LONG(KEY_ENTER)) {
|
||||
// backupEeprom();
|
||||
// }
|
||||
}
|
||||
@@ -0,0 +1,203 @@
|
||||
/*
|
||||
* Authors (alphabetical order)
|
||||
* - Andre Bernet <bernet.andre@gmail.com>
|
||||
* - Andreas Weitl
|
||||
* - Bertrand Songis <bsongis@gmail.com>
|
||||
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
|
||||
* - Cameron Weeks <th9xer@gmail.com>
|
||||
* - Erez Raviv
|
||||
* - Gabriel Birkus
|
||||
* - Jean-Pierre Parisy
|
||||
* - Karl Szmutny
|
||||
* - Michael Blandford
|
||||
* - Michal Hlavinka
|
||||
* - Pat Mackenzie
|
||||
* - Philip Moss
|
||||
* - Rob Thomson
|
||||
* - 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"
|
||||
|
||||
// TODO elsewhere!
|
||||
#define WCHART 64
|
||||
#define X0 (LCD_W-WCHART-8)
|
||||
#define Y0 118
|
||||
|
||||
enum EnumTabModel {
|
||||
// e_ModelSelect,
|
||||
e_ModelSetup,
|
||||
CASE_HELI(e_Heli)
|
||||
CASE_FLIGHT_MODES(e_FlightModesAll)
|
||||
e_InputsAll,
|
||||
e_MixAll,
|
||||
e_Limits,
|
||||
CASE_CURVES(e_CurvesAll)
|
||||
CASE_GVARS(e_GVars)
|
||||
e_LogicalSwitches,
|
||||
e_CustomFunctions,
|
||||
#if defined(LUA_MODEL_SCRIPTS)
|
||||
e_CustomScripts,
|
||||
#endif
|
||||
CASE_FRSKY(e_Telemetry)
|
||||
};
|
||||
|
||||
void menuModelSelect(evt_t event);
|
||||
void menuModelSetup(evt_t event);
|
||||
void menuModelHeli(evt_t event);
|
||||
void menuModelFlightModesAll(evt_t event);
|
||||
void menuModelExposAll(evt_t event);
|
||||
void menuModelMixAll(evt_t event);
|
||||
void menuModelLimits(evt_t event);
|
||||
void menuModelCurvesAll(evt_t event);
|
||||
void menuModelCurveOne(evt_t event);
|
||||
void menuModelGVars(evt_t event);
|
||||
void menuModelLogicalSwitches(evt_t event);
|
||||
void menuModelCustomFunctions(evt_t event);
|
||||
void menuModelCustomScripts(evt_t event);
|
||||
void menuModelTelemetry(evt_t event);
|
||||
void menuModelExpoOne(evt_t event);
|
||||
|
||||
extern uint8_t s_curveChan;
|
||||
|
||||
#define FlightModesType uint16_t
|
||||
|
||||
void editCurveRef(coord_t x, coord_t y, CurveRef & curve, evt_t event, uint8_t attr);
|
||||
|
||||
#define MIXES_2ND_COLUMN 80
|
||||
|
||||
uint8_t editDelay(const coord_t x, const coord_t y, const evt_t event, const uint8_t attr, const pm_char *str, uint8_t delay)
|
||||
{
|
||||
lcd_putsAtt(x+MENU_TITLE_LEFT, y, str, TEXT_COLOR);
|
||||
lcd_outdezAtt(x+MIXES_2ND_COLUMN, y, (10/DELAY_STEP)*delay, attr|PREC1|LEFT);
|
||||
if (attr) CHECK_INCDEC_MODELVAR_ZERO(event, delay, DELAY_MAX);
|
||||
return delay;
|
||||
}
|
||||
#define EDIT_DELAY(x, y, event, attr, str, delay) editDelay(x, y, event, attr, str, delay)
|
||||
|
||||
const MenuFuncP_PROGMEM menuTabModel[] PROGMEM = {
|
||||
// menuModelSelect,
|
||||
menuModelSetup,
|
||||
CASE_HELI(menuModelHeli)
|
||||
CASE_FLIGHT_MODES(menuModelFlightModesAll)
|
||||
menuModelExposAll,
|
||||
menuModelMixAll,
|
||||
menuModelLimits,
|
||||
CASE_CURVES(menuModelCurvesAll)
|
||||
#if defined(GVARS) && defined(FLIGHT_MODES)
|
||||
CASE_GVARS(menuModelGVars)
|
||||
#endif
|
||||
menuModelLogicalSwitches,
|
||||
menuModelCustomFunctions,
|
||||
#if defined(LUA_MODEL_SCRIPTS)
|
||||
menuModelCustomScripts,
|
||||
#endif
|
||||
CASE_FRSKY(menuModelTelemetry)
|
||||
CASE_MAVLINK(menuTelemetryMavlinkSetup)
|
||||
CASE_TEMPLATES(menuModelTemplates)
|
||||
};
|
||||
|
||||
#define COPY_MODE 1
|
||||
#define MOVE_MODE 2
|
||||
static uint8_t s_copyMode = 0;
|
||||
static int8_t s_copySrcRow;
|
||||
static int8_t s_copyTgtOfs;
|
||||
|
||||
static uint8_t editNameCursorPos = 0;
|
||||
|
||||
void editName(coord_t x, coord_t y, char *name, uint8_t size, evt_t event, uint8_t active)
|
||||
{
|
||||
uint8_t mode = 0;
|
||||
if (active && s_editMode <= 0) {
|
||||
mode = INVERS;
|
||||
}
|
||||
|
||||
if (!active || s_editMode <= 0) {
|
||||
if (zlen(name, size) == 0) {
|
||||
char tmp[] = "---";
|
||||
lcd_putsnAtt(x, y, tmp, size, mode);
|
||||
}
|
||||
else {
|
||||
lcd_putsnAtt(x, y, name, size, ZCHAR | mode);
|
||||
}
|
||||
}
|
||||
|
||||
if (active) {
|
||||
uint8_t cur = editNameCursorPos;
|
||||
if (s_editMode > 0) {
|
||||
int8_t c = name[cur];
|
||||
int8_t v = c;
|
||||
|
||||
if (IS_ROTARY_RIGHT(event) || IS_ROTARY_LEFT(event) || event==EVT_KEY_FIRST(KEY_DOWN) || event==EVT_KEY_FIRST(KEY_UP)
|
||||
|| event==EVT_KEY_REPT(KEY_DOWN) || event==EVT_KEY_REPT(KEY_UP)) {
|
||||
v = checkIncDec(event, abs(v), 0, ZCHAR_MAX, 0);
|
||||
if (c <= 0) v = -v;
|
||||
}
|
||||
|
||||
switch (event) {
|
||||
case EVT_ROTARY_BREAK:
|
||||
if (s_editMode == EDIT_MODIFY_FIELD) {
|
||||
s_editMode = EDIT_MODIFY_STRING;
|
||||
cur = 0;
|
||||
}
|
||||
else if (cur<size-1)
|
||||
cur++;
|
||||
else
|
||||
s_editMode = 0;
|
||||
break;
|
||||
|
||||
case EVT_ROTARY_LONG:
|
||||
if (v==0) {
|
||||
s_editMode = 0;
|
||||
killEvents(event);
|
||||
break;
|
||||
}
|
||||
if (v>=-26 && v<=26) {
|
||||
v = -v; // toggle case
|
||||
if (event==EVT_KEY_LONG(KEY_LEFT))
|
||||
killEvents(KEY_LEFT);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (c != v) {
|
||||
name[cur] = v;
|
||||
eeDirty(g_menuPos[0] == 0 ? EE_MODEL : EE_GENERAL);
|
||||
}
|
||||
|
||||
lcd_putsnAtt(x, y, name, size, ZCHAR | mode);
|
||||
coord_t w = (editNameCursorPos == 0 ? 0 : getTextWidth(name, editNameCursorPos, ZCHAR));
|
||||
char s[] = { idx2char(v), '\0' };
|
||||
lcdDrawFilledRect(x+w, y-1, getTextWidth(s, 1)-1, 12, TEXT_INVERTED_BGCOLOR);
|
||||
lcd_putsAtt(x+w, y, s, TEXT_INVERTED_COLOR);
|
||||
}
|
||||
else {
|
||||
cur = 0;
|
||||
}
|
||||
editNameCursorPos = cur;
|
||||
}
|
||||
}
|
||||
|
||||
void editSingleName(coord_t x, coord_t y, const pm_char *label, char *name, uint8_t size, evt_t event, uint8_t active)
|
||||
{
|
||||
lcd_putsLeft(y, label);
|
||||
editName(x, y, name, size, event, active);
|
||||
}
|
||||
|
||||
static uint8_t s_currIdx;
|
||||
@@ -0,0 +1,325 @@
|
||||
/*
|
||||
* Authors (alphabetical order)
|
||||
* - Andre Bernet <bernet.andre@gmail.com>
|
||||
* - Andreas Weitl
|
||||
* - Bertrand Songis <bsongis@gmail.com>
|
||||
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
|
||||
* - Cameron Weeks <th9xer@gmail.com>
|
||||
* - Erez Raviv
|
||||
* - Gabriel Birkus
|
||||
* - Jean-Pierre Parisy
|
||||
* - Karl Szmutny
|
||||
* - Michael Blandford
|
||||
* - Michal Hlavinka
|
||||
* - Pat Mackenzie
|
||||
* - Philip Moss
|
||||
* - Rob Thomson
|
||||
* - 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 s_curveChan;
|
||||
|
||||
int curveFn(int x)
|
||||
{
|
||||
return applyCustomCurve(x, s_curveChan);
|
||||
}
|
||||
|
||||
struct point_t {
|
||||
coord_t x;
|
||||
coord_t y;
|
||||
};
|
||||
|
||||
point_t getPoint(uint8_t i)
|
||||
{
|
||||
point_t result = {0, 0};
|
||||
CurveInfo &crv = g_model.curves[s_curveChan];
|
||||
int8_t *points = curveAddress(s_curveChan);
|
||||
bool custom = (crv.type == CURVE_TYPE_CUSTOM);
|
||||
uint8_t count = 5+crv.points;
|
||||
if (i < count) {
|
||||
result.x = X0-1-WCHART+i*WCHART*2/(count-1);
|
||||
result.y = Y0 - (points[i]) * (WCHART-1) / 100;
|
||||
if (custom && i>0 && i<count-1)
|
||||
result.x = X0-1-WCHART + (100 + (100 + points[count+i-1]) * (2*WCHART)) / 200;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void DrawCurve(int offset=0)
|
||||
{
|
||||
DrawFunction(curveFn, offset);
|
||||
|
||||
int i = 0;
|
||||
do {
|
||||
point_t point = getPoint(i++);
|
||||
if (point.x == 0) break;
|
||||
lcdDrawFilledRect(point.x-offset, point.y-1, 3, 3, TEXT_COLOR); // do markup square
|
||||
} while(1);
|
||||
}
|
||||
|
||||
extern int8_t * curveEnd[MAX_CURVES];
|
||||
bool moveCurve(uint8_t index, int8_t shift)
|
||||
{
|
||||
if (curveEnd[MAX_CURVES-1] + shift > g_model.points + sizeof(g_model.points)) {
|
||||
AUDIO_WARNING2();
|
||||
return false;
|
||||
}
|
||||
|
||||
int8_t *nextCrv = curveAddress(index+1);
|
||||
memmove(nextCrv+shift, nextCrv, 5*(MAX_CURVES-index-1)+curveEnd[MAX_CURVES-1]-curveEnd[index]);
|
||||
if (shift < 0) memclear(&g_model.points[NUM_POINTS-1] + shift, -shift);
|
||||
while (index<MAX_CURVES) {
|
||||
curveEnd[index++] += shift;
|
||||
}
|
||||
|
||||
eeDirty(EE_MODEL);
|
||||
return true;
|
||||
}
|
||||
|
||||
void displayPresetChoice(evt_t event)
|
||||
{
|
||||
displayWarning(event);
|
||||
lcd_outdezAtt(WARNING_LINE_X, WARNING_INFOLINE_Y-10, 45*s_warning_input_value/4, LEFT|INVERS, "@");
|
||||
|
||||
if (s_warning_result) {
|
||||
s_warning_result = 0;
|
||||
CurveInfo & crv = g_model.curves[s_curveChan];
|
||||
int8_t * points = curveAddress(s_curveChan);
|
||||
for (int i=0; i<5+crv.points; i++)
|
||||
points[i] = (i-((5+crv.points)/2)) * s_warning_input_value * 50 / (4+crv.points);
|
||||
if (crv.type == CURVE_TYPE_CUSTOM) {
|
||||
for (int i=0; i<3+crv.points; i++)
|
||||
points[crv.points+i] = -100 + ((i+1)*200) / (4+crv.points);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void onCurveOneMenu(const char *result)
|
||||
{
|
||||
if (result == STR_CURVE_PRESET) {
|
||||
POPUP_INPUT(STR_PRESET, displayPresetChoice, 0, -4, 4);
|
||||
}
|
||||
else if (result == STR_MIRROR) {
|
||||
CurveInfo & crv = g_model.curves[s_curveChan];
|
||||
int8_t * points = curveAddress(s_curveChan);
|
||||
for (int i=0; i<5+crv.points; i++)
|
||||
points[i] = -points[i];
|
||||
}
|
||||
else if (result == STR_CLEAR) {
|
||||
CurveInfo & crv = g_model.curves[s_curveChan];
|
||||
int8_t * points = curveAddress(s_curveChan);
|
||||
for (int i=0; i<5+crv.points; i++)
|
||||
points[i] = 0;
|
||||
if (crv.type == CURVE_TYPE_CUSTOM) {
|
||||
for (int i=0; i<3+crv.points; i++)
|
||||
points[crv.points+i] = -100 + ((i+1)*200) / (4+crv.points);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void menuModelCurveOne(evt_t event)
|
||||
{
|
||||
static uint8_t pointsOfs = 0;
|
||||
CurveInfo & crv = g_model.curves[s_curveChan];
|
||||
int8_t * points = curveAddress(s_curveChan);
|
||||
|
||||
SIMPLE_SUBMENU(STR_MENUCURVE, 4 + 5+crv.points + (crv.type==CURVE_TYPE_CUSTOM ? 5+crv.points-2 : 0), 0);
|
||||
|
||||
lcd_outdezAtt(60, MENU_FOOTER_TOP, s_curveChan+1, LEFT);
|
||||
|
||||
lcd_putsLeft(MENU_HEADER_HEIGHT+1, STR_NAME);
|
||||
editName(MENU_TITLE_LEFT+INDENT_WIDTH, MENU_CONTENT_TOP + FH, g_model.curveNames[s_curveChan], sizeof(g_model.curveNames[s_curveChan]), event, m_posVert==0);
|
||||
|
||||
LcdFlags attr = (m_posVert==1 ? (s_editMode>0 ? INVERS|BLINK : INVERS) : 0);
|
||||
lcd_putsLeft(MENU_CONTENT_TOP + 2*FH, "Type");
|
||||
lcd_putsiAtt(MENU_TITLE_LEFT+INDENT_WIDTH, MENU_CONTENT_TOP + 3*FH, STR_CURVE_TYPES, crv.type, attr);
|
||||
if (attr) {
|
||||
uint8_t newType = checkIncDecModelZero(event, crv.type, CURVE_TYPE_LAST);
|
||||
if (newType != crv.type) {
|
||||
for (int i=1; i<4+crv.points; i++)
|
||||
points[i] = calcRESXto100(applyCustomCurve(calc100toRESX(-100 + i*200/(4+crv.points)), s_curveChan));
|
||||
moveCurve(s_curveChan, checkIncDec_Ret > 0 ? 3+crv.points : -3-crv.points);
|
||||
if (newType == CURVE_TYPE_CUSTOM) {
|
||||
for (int i=0; i<3+crv.points; i++)
|
||||
points[5+crv.points+i] = -100 + ((i+1)*200) / (4+crv.points);
|
||||
}
|
||||
crv.type = newType;
|
||||
}
|
||||
}
|
||||
|
||||
attr = (m_posVert==2 ? (s_editMode>0 ? INVERS|BLINK : INVERS) : 0);
|
||||
lcd_putsLeft(MENU_CONTENT_TOP + 4*FH, STR_COUNT);
|
||||
lcd_outdezAtt(MENU_TITLE_LEFT+INDENT_WIDTH, MENU_CONTENT_TOP + 5*FH, 5+crv.points, LEFT|attr, STR_PTS);
|
||||
if (attr) {
|
||||
int count = checkIncDecModel(event, crv.points, -3, 12); // 2pts - 17pts
|
||||
if (checkIncDec_Ret) {
|
||||
int newPoints[MAX_POINTS];
|
||||
newPoints[0] = points[0];
|
||||
newPoints[4+count] = points[4+crv.points];
|
||||
for (int i=1; i<4+count; i++)
|
||||
newPoints[i] = calcRESXto100(applyCustomCurve(calc100toRESX(-100 + (i*200) / (4+count)), s_curveChan));
|
||||
moveCurve(s_curveChan, checkIncDec_Ret*(crv.type==CURVE_TYPE_CUSTOM?2:1));
|
||||
for (int i=0; i<5+count; i++) {
|
||||
points[i] = newPoints[i];
|
||||
if (crv.type == CURVE_TYPE_CUSTOM && i!=0 && i!=4+count)
|
||||
points[5+count+i-1] = -100 + (i*200) / (4+count);
|
||||
}
|
||||
crv.points = count;
|
||||
}
|
||||
}
|
||||
|
||||
lcd_putsLeft(MENU_CONTENT_TOP + 6*FH, STR_SMOOTH);
|
||||
lcdDrawCheckBox(70, MENU_CONTENT_TOP + 6*FH, crv.smooth, m_posVert==3 ? INVERS : 0);
|
||||
if (m_posVert==3) crv.smooth = checkIncDecModel(event, crv.smooth, 0, 1);
|
||||
|
||||
switch(event) {
|
||||
case EVT_ENTRY:
|
||||
pointsOfs = 0;
|
||||
break;
|
||||
case EVT_KEY_LONG(KEY_ENTER):
|
||||
if (m_posVert > 1) {
|
||||
killEvents(event);
|
||||
MENU_ADD_ITEM(STR_CURVE_PRESET);
|
||||
MENU_ADD_ITEM(STR_MIRROR);
|
||||
MENU_ADD_ITEM(STR_CLEAR);
|
||||
menuHandler = onCurveOneMenu;
|
||||
}
|
||||
break;
|
||||
case EVT_KEY_LONG(KEY_MENU):
|
||||
pushMenu(menuChannelsView);
|
||||
killEvents(event);
|
||||
}
|
||||
|
||||
if (m_posVert >= 0) {
|
||||
DrawCurve(6);
|
||||
}
|
||||
|
||||
lcd_putsAtt(115, MENU_FOOTER_TOP, "X", HEADER_COLOR);
|
||||
lcd_putsAtt(145, MENU_FOOTER_TOP, "Y", HEADER_COLOR);
|
||||
|
||||
coord_t posY = MENU_HEADER_HEIGHT+1;
|
||||
attr = (s_editMode > 0 ? INVERS|BLINK : INVERS);
|
||||
for (int i=0; i<5+crv.points; i++) {
|
||||
point_t point = getPoint(i);
|
||||
uint8_t selectionMode = 0;
|
||||
if (crv.type==CURVE_TYPE_CUSTOM) {
|
||||
if (m_posVert==4+2*i || (i==5+crv.points-1 && m_posVert==4+5+crv.points+5+crv.points-2-1))
|
||||
selectionMode = 2;
|
||||
else if (i>0 && m_posVert==3+2*i)
|
||||
selectionMode = 1;
|
||||
}
|
||||
else if (m_posVert == 4+i) {
|
||||
selectionMode = 2;
|
||||
}
|
||||
|
||||
if (i>=pointsOfs && i<pointsOfs+NUM_BODY_LINES) {
|
||||
int8_t x = -100 + 200*i/(5+crv.points-1);
|
||||
if (crv.type==CURVE_TYPE_CUSTOM && i>0 && i<5+crv.points-1) x = points[5+crv.points+i-1];
|
||||
lcd_outdezAtt(100, posY, i+1, LEFT);
|
||||
lcd_outdezAtt(115, posY, x, LEFT|(selectionMode==1?attr:0));
|
||||
lcd_outdezAtt(145, posY, points[i], LEFT|(selectionMode==2?attr:0));
|
||||
posY += FH;
|
||||
}
|
||||
|
||||
if (selectionMode > 0) {
|
||||
// do selection square
|
||||
lcdDrawFilledRect(point.x-7, point.y-2, 5, 5, TEXT_INVERTED_BGCOLOR);
|
||||
if (s_editMode > 0) {
|
||||
if (selectionMode == 1)
|
||||
CHECK_INCDEC_MODELVAR(event, points[5+crv.points+i-1], i==1 ? -100 : points[5+crv.points+i-2], i==5+crv.points-2 ? 100 : points[5+crv.points+i]); // edit X
|
||||
else if (selectionMode == 2)
|
||||
CHECK_INCDEC_MODELVAR(event, points[i], -100, 100);
|
||||
}
|
||||
if (i < pointsOfs)
|
||||
pointsOfs = i;
|
||||
else if (i > pointsOfs+NUM_BODY_LINES-1)
|
||||
pointsOfs = i-NUM_BODY_LINES+1;
|
||||
}
|
||||
}
|
||||
|
||||
if (5+crv.points > NUM_BODY_LINES) {
|
||||
displayScrollbar(167, DEFAULT_SCROLLBAR_Y, DEFAULT_SCROLLBAR_H, pointsOfs, 5+crv.points, NUM_BODY_LINES);
|
||||
}
|
||||
}
|
||||
|
||||
void editCurveRef(coord_t x, coord_t y, CurveRef & curve, evt_t event, uint8_t attr)
|
||||
{
|
||||
lcd_putsiAtt(x, y, "\004DiffExpoFuncCstm", curve.type, (m_posHorz==0 ? attr : 0));
|
||||
if (attr && m_posHorz==0) {
|
||||
CHECK_INCDEC_MODELVAR_ZERO(event, curve.type, CURVE_REF_CUSTOM);
|
||||
if (checkIncDec_Ret) curve.value = 0;
|
||||
}
|
||||
switch (curve.type) {
|
||||
case CURVE_REF_DIFF:
|
||||
case CURVE_REF_EXPO:
|
||||
curve.value = GVAR_MENU_ITEM(x+40, y, curve.value, -100, 100, m_posHorz==1 ? LEFT|attr : LEFT, 0, event);
|
||||
break;
|
||||
case CURVE_REF_FUNC:
|
||||
lcd_putsiAtt(x+40, y, STR_VCURVEFUNC, curve.value, (m_posHorz==1 ? attr : 0));
|
||||
if (attr && m_posHorz==1) CHECK_INCDEC_MODELVAR_ZERO(event, curve.value, CURVE_BASE-1);
|
||||
break;
|
||||
case CURVE_REF_CUSTOM:
|
||||
putsCurve(x+40, y, curve.value, (m_posHorz==1 ? attr : 0));
|
||||
if (attr && m_posHorz==1) {
|
||||
if (event==EVT_KEY_LONG(KEY_ENTER) && curve.value!=0) {
|
||||
s_curveChan = (curve.value<0 ? -curve.value-1 : curve.value-1);
|
||||
pushMenu(menuModelCurveOne);
|
||||
}
|
||||
else {
|
||||
CHECK_INCDEC_MODELVAR(event, curve.value, -MAX_CURVES, MAX_CURVES);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void menuModelCurvesAll(evt_t event)
|
||||
{
|
||||
SIMPLE_MENU(STR_MENUCURVES, menuTabModel, e_CurvesAll, MAX_CURVES, DEFAULT_SCROLLBAR_X);
|
||||
|
||||
int8_t sub = m_posVert;
|
||||
|
||||
switch (event) {
|
||||
case EVT_KEY_BREAK(KEY_ENTER):
|
||||
if (!READ_ONLY()) {
|
||||
s_curveChan = sub;
|
||||
pushMenu(menuModelCurveOne);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
for (int i=0; i<NUM_BODY_LINES; ++i) {
|
||||
coord_t y = MENU_CONTENT_TOP + i*FH;
|
||||
uint8_t k = i + s_pgOfs;
|
||||
LcdFlags attr = (sub == k ? INVERS : 0);
|
||||
{
|
||||
putsStrIdx(MENU_TITLE_LEFT, y, STR_CV, k+1, attr);
|
||||
editName(50, y, g_model.curveNames[k], sizeof(g_model.curveNames[k]), 0, 0);
|
||||
CurveInfo & crv = g_model.curves[k];
|
||||
lcd_outdezAtt(100, y, 5+crv.points, LEFT, STR_PTS);
|
||||
}
|
||||
}
|
||||
|
||||
if (sub >= 0) {
|
||||
s_curveChan = sub;
|
||||
DrawCurve(23);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,372 @@
|
||||
/*
|
||||
* Authors (alphabetical order)
|
||||
* - Andre Bernet <bernet.andre@gmail.com>
|
||||
* - Andreas Weitl
|
||||
* - Bertrand Songis <bsongis@gmail.com>
|
||||
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
|
||||
* - Cameron Weeks <th9xer@gmail.com>
|
||||
* - Erez Raviv
|
||||
* - Gabriel Birkus
|
||||
* - Jean-Pierre Parisy
|
||||
* - Karl Szmutny
|
||||
* - Michael Blandford
|
||||
* - Michal Hlavinka
|
||||
* - Pat Mackenzie
|
||||
* - Philip Moss
|
||||
* - Rob Thomson
|
||||
* - 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 MODEL_CUSTOM_FUNC_1ST_COLUMN 50
|
||||
#define MODEL_CUSTOM_FUNC_2ND_COLUMN 100
|
||||
#define MODEL_CUSTOM_FUNC_2ND_COLUMN_EXT 150
|
||||
#define MODEL_CUSTOM_FUNC_3RD_COLUMN 200
|
||||
#define MODEL_CUSTOM_FUNC_4TH_COLUMN 286
|
||||
#define MODEL_CUSTOM_FUNC_4TH_COLUMN_ONOFF 290
|
||||
|
||||
void onCustomFunctionsFileSelectionMenu(const char *result)
|
||||
{
|
||||
int sub = m_posVert;
|
||||
CustomFunctionData * cf = &g_model.customFn[sub];
|
||||
uint8_t func = CFN_FUNC(cf);
|
||||
|
||||
if (result == STR_UPDATE_LIST) {
|
||||
char directory[256];
|
||||
if (func == FUNC_PLAY_SCRIPT) {
|
||||
strcpy(directory, SCRIPTS_FUNCS_PATH);
|
||||
}
|
||||
else {
|
||||
strcpy(directory, SOUNDS_PATH);
|
||||
strncpy(directory+SOUNDS_PATH_LNG_OFS, currentLanguagePack->id, 2);
|
||||
}
|
||||
if (!listSdFiles(directory, func==FUNC_PLAY_SCRIPT ? SCRIPTS_EXT : SOUNDS_EXT, sizeof(cf->play.name), NULL)) {
|
||||
POPUP_WARNING(func==FUNC_PLAY_SCRIPT ? STR_NO_SCRIPTS_ON_SD : STR_NO_SOUNDS_ON_SD);
|
||||
s_menu_flags = 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// The user choosed a file in the list
|
||||
memcpy(cf->play.name, result, sizeof(cf->play.name));
|
||||
eeDirty(EE_MODEL);
|
||||
if (func == FUNC_PLAY_SCRIPT) {
|
||||
LUA_LOAD_MODEL_SCRIPTS();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void onCustomFunctionsMenu(const char *result)
|
||||
{
|
||||
int sub = m_posVert;
|
||||
CustomFunctionData * cfn;
|
||||
uint8_t eeFlags;
|
||||
|
||||
if (g_menuStack[g_menuStackPtr] == menuModelCustomFunctions) {
|
||||
cfn = &g_model.customFn[sub];
|
||||
eeFlags = EE_MODEL;
|
||||
}
|
||||
else {
|
||||
cfn = &g_eeGeneral.customFn[sub];
|
||||
eeFlags = EE_GENERAL;
|
||||
}
|
||||
|
||||
if (result == STR_COPY) {
|
||||
clipboard.type = CLIPBOARD_TYPE_CUSTOM_FUNCTION;
|
||||
clipboard.data.cfn = *cfn;
|
||||
}
|
||||
else if (result == STR_PASTE) {
|
||||
*cfn = clipboard.data.cfn;
|
||||
eeDirty(eeFlags);
|
||||
}
|
||||
else if (result == STR_CLEAR) {
|
||||
memset(cfn, 0, sizeof(CustomFunctionData));
|
||||
eeDirty(eeFlags);
|
||||
}
|
||||
else if (result == STR_INSERT) {
|
||||
memmove(cfn+1, cfn, (NUM_CFN-sub-1)*sizeof(CustomFunctionData));
|
||||
memset(cfn, 0, sizeof(CustomFunctionData));
|
||||
eeDirty(eeFlags);
|
||||
}
|
||||
else if (result == STR_DELETE) {
|
||||
memmove(cfn, cfn+1, (NUM_CFN-sub-1)*sizeof(CustomFunctionData));
|
||||
memset(&g_model.customFn[NUM_CFN-1], 0, sizeof(CustomFunctionData));
|
||||
eeDirty(eeFlags);
|
||||
}
|
||||
}
|
||||
|
||||
void menuCustomFunctions(evt_t event, CustomFunctionData * functions, CustomFunctionsContext & functionsContext)
|
||||
{
|
||||
uint32_t sub = m_posVert;
|
||||
|
||||
uint8_t eeFlags = (functions == g_model.customFn) ? EE_MODEL : EE_GENERAL;
|
||||
|
||||
if (m_posHorz<0 && event==EVT_KEY_LONG(KEY_ENTER) && !READ_ONLY()) {
|
||||
killEvents(event);
|
||||
CustomFunctionData *cfn = &functions[sub];
|
||||
if (!CFN_EMPTY(cfn))
|
||||
MENU_ADD_ITEM(STR_COPY);
|
||||
if (clipboard.type == CLIPBOARD_TYPE_CUSTOM_FUNCTION)
|
||||
MENU_ADD_ITEM(STR_PASTE);
|
||||
if (!CFN_EMPTY(cfn) && CFN_EMPTY(&functions[NUM_CFN-1]))
|
||||
MENU_ADD_ITEM(STR_INSERT);
|
||||
if (!CFN_EMPTY(cfn))
|
||||
MENU_ADD_ITEM(STR_CLEAR);
|
||||
for (int i=sub+1; i<NUM_CFN; i++) {
|
||||
if (!CFN_EMPTY(&functions[i])) {
|
||||
MENU_ADD_ITEM(STR_DELETE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
menuHandler = onCustomFunctionsMenu;
|
||||
}
|
||||
|
||||
for (int i=0; i<NUM_BODY_LINES; i++) {
|
||||
coord_t y = MENU_CONTENT_TOP + i*FH;
|
||||
unsigned int k = i+s_pgOfs;
|
||||
|
||||
putsStrIdx(MENU_TITLE_LEFT, y, functions == g_model.customFn ? STR_SF : STR_GF, k+1, (sub==k && m_posHorz<0) ? INVERS : 0);
|
||||
|
||||
CustomFunctionData *cfn = &functions[k];
|
||||
unsigned int func = CFN_FUNC(cfn);
|
||||
for (int j=0; j<5; j++) {
|
||||
LcdFlags attr = ((sub==k && m_posHorz==j) ? ((s_editMode>0) ? BLINK|INVERS : INVERS) : 0);
|
||||
LcdFlags active = (attr && s_editMode>0);
|
||||
switch (j) {
|
||||
case 0:
|
||||
putsSwitches(MODEL_CUSTOM_FUNC_1ST_COLUMN, y, CFN_SWITCH(cfn), attr | ((functionsContext.activeSwitches & ((MASK_CFN_TYPE)1 << k)) ? BOLD : 0));
|
||||
if (active || AUTOSWITCH_ENTER_LONG()) CHECK_INCDEC_SWITCH(event, CFN_SWITCH(cfn), SWSRC_FIRST, SWSRC_LAST, eeFlags, isSwitchAvailableInCustomFunctions);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
if (CFN_SWITCH(cfn)) {
|
||||
lcd_putsiAtt(MODEL_CUSTOM_FUNC_2ND_COLUMN, y, STR_VFSWFUNC, func, attr);
|
||||
if (active) {
|
||||
func = CFN_FUNC(cfn) = checkIncDec(event, CFN_FUNC(cfn), 0, FUNC_MAX-1, eeFlags, isAssignableFunctionAvailable);
|
||||
if (checkIncDec_Ret) CFN_RESET(cfn);
|
||||
}
|
||||
}
|
||||
else {
|
||||
j = 4; // skip other fields
|
||||
if (sub==k && m_posHorz > 0) {
|
||||
REPEAT_LAST_CURSOR_MOVE();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
{
|
||||
int8_t maxParam = NUM_CHNOUT-1;
|
||||
#if defined(OVERRIDE_CHANNEL_FUNCTION)
|
||||
if (func == FUNC_OVERRIDE_CHANNEL) {
|
||||
putsChn(MODEL_CUSTOM_FUNC_2ND_COLUMN_EXT, y, CFN_CH_INDEX(cfn)+1, attr);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (func == FUNC_TRAINER) {
|
||||
maxParam = 4;
|
||||
putsMixerSource(MODEL_CUSTOM_FUNC_2ND_COLUMN_EXT, y, CFN_CH_INDEX(cfn)==0 ? 0 : MIXSRC_Rud+CFN_CH_INDEX(cfn)-1, attr);
|
||||
}
|
||||
#if defined(GVARS)
|
||||
else if (func == FUNC_ADJUST_GVAR) {
|
||||
maxParam = MAX_GVARS-1;
|
||||
putsStrIdx(MODEL_CUSTOM_FUNC_2ND_COLUMN_EXT, y, STR_GV, CFN_GVAR_INDEX(cfn)+1, attr);
|
||||
if (active) CFN_GVAR_INDEX(cfn) = checkIncDec(event, CFN_GVAR_INDEX(cfn), 0, maxParam, eeFlags);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
else if (func == FUNC_SET_TIMER) {
|
||||
maxParam = MAX_TIMERS-1;
|
||||
putsStrIdx(MODEL_CUSTOM_FUNC_2ND_COLUMN_EXT, y, STR_TIMER, CFN_TIMER_INDEX(cfn)+1, attr);
|
||||
if (active) CFN_TIMER_INDEX(cfn) = checkIncDec(event, CFN_TIMER_INDEX(cfn), 0, maxParam, eeFlags);
|
||||
break;
|
||||
}
|
||||
else if (attr) {
|
||||
REPEAT_LAST_CURSOR_MOVE();
|
||||
}
|
||||
if (active) CHECK_INCDEC_MODELVAR_ZERO(event, CFN_CH_INDEX(cfn), maxParam);
|
||||
break;
|
||||
}
|
||||
|
||||
case 3:
|
||||
{
|
||||
INCDEC_DECLARE_VARS(eeFlags);
|
||||
int16_t val_displayed = CFN_PARAM(cfn);
|
||||
int16_t val_min = 0;
|
||||
int16_t val_max = 255;
|
||||
if (func == FUNC_RESET) {
|
||||
val_max = FUNC_RESET_PARAM_LAST;
|
||||
lcd_putsiAtt(MODEL_CUSTOM_FUNC_3RD_COLUMN, y, STR_VFSWRESET, CFN_PARAM(cfn), attr);
|
||||
}
|
||||
#if defined(OVERRIDE_CHANNEL_FUNCTION)
|
||||
else if (func == FUNC_OVERRIDE_CHANNEL) {
|
||||
val_min = -LIMIT_EXT_PERCENT; val_max = +LIMIT_EXT_PERCENT;
|
||||
lcd_outdezAtt(MODEL_CUSTOM_FUNC_3RD_COLUMN, y, val_displayed, attr|LEFT);
|
||||
}
|
||||
#endif
|
||||
#if defined(DANGEROUS_MODULE_FUNCTIONS)
|
||||
else if (func >= FUNC_RANGECHECK && func <= FUNC_MODULE_OFF) {
|
||||
val_max = NUM_MODULES-1;
|
||||
lcd_putsiAtt(MODEL_CUSTOM_FUNC_3RD_COLUMN, y, "\004Int.Ext.", CFN_PARAM(cfn), attr);
|
||||
}
|
||||
#endif
|
||||
else if (func == FUNC_SET_TIMER) {
|
||||
val_max = 59*60+59;
|
||||
putsTimer(MODEL_CUSTOM_FUNC_3RD_COLUMN, y, val_displayed, attr|LEFT);
|
||||
}
|
||||
else if (func == FUNC_PLAY_SOUND) {
|
||||
val_max = AU_FRSKY_LAST-AU_FRSKY_FIRST-1;
|
||||
lcd_putsiAtt(MODEL_CUSTOM_FUNC_3RD_COLUMN, y, STR_FUNCSOUNDS, val_displayed, attr);
|
||||
}
|
||||
#if defined(HAPTIC)
|
||||
else if (func == FUNC_HAPTIC) {
|
||||
val_max = 3;
|
||||
lcd_outdezAtt(MODEL_CUSTOM_FUNC_3RD_COLUMN, y, val_displayed, attr|LEFT);
|
||||
}
|
||||
#endif
|
||||
#if defined(SDCARD)
|
||||
else if (func == FUNC_PLAY_TRACK || func == FUNC_BACKGND_MUSIC || func == FUNC_PLAY_SCRIPT) {
|
||||
coord_t x = MODEL_CUSTOM_FUNC_3RD_COLUMN;
|
||||
if (ZEXIST(cfn->play.name))
|
||||
lcd_putsnAtt(x, y, cfn->play.name, sizeof(cfn->play.name), attr);
|
||||
else
|
||||
lcd_putsiAtt(x, y, STR_VCSWFUNC, 0, attr);
|
||||
if (active && event==EVT_KEY_BREAK(KEY_ENTER)) {
|
||||
s_editMode = 0;
|
||||
char directory[256];
|
||||
if (func==FUNC_PLAY_SCRIPT) {
|
||||
strcpy(directory, SCRIPTS_FUNCS_PATH);
|
||||
}
|
||||
else {
|
||||
strcpy(directory, SOUNDS_PATH);
|
||||
strncpy(directory+SOUNDS_PATH_LNG_OFS, currentLanguagePack->id, 2);
|
||||
}
|
||||
if (listSdFiles(directory, func==FUNC_PLAY_SCRIPT ? SCRIPTS_EXT : SOUNDS_EXT, sizeof(cfn->play.name), cfn->play.name)) {
|
||||
menuHandler = onCustomFunctionsFileSelectionMenu;
|
||||
}
|
||||
else {
|
||||
POPUP_WARNING(func==FUNC_PLAY_SCRIPT ? STR_NO_SCRIPTS_ON_SD : STR_NO_SOUNDS_ON_SD);
|
||||
s_menu_flags = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
else if (func == FUNC_PLAY_VALUE) {
|
||||
val_max = MIXSRC_LAST_TELEM;
|
||||
putsMixerSource(MODEL_CUSTOM_FUNC_3RD_COLUMN, y, val_displayed, attr);
|
||||
INCDEC_ENABLE_CHECK(isSourceAvailable);
|
||||
}
|
||||
#endif
|
||||
else if (func == FUNC_VOLUME) {
|
||||
val_max = MIXSRC_LAST_CH;
|
||||
putsMixerSource(MODEL_CUSTOM_FUNC_3RD_COLUMN, y, val_displayed, attr);
|
||||
INCDEC_SET_FLAG(eeFlags | INCDEC_SOURCE);
|
||||
INCDEC_ENABLE_CHECK(isSourceAvailable);
|
||||
}
|
||||
else if (func == FUNC_LOGS) {
|
||||
if (val_displayed) {
|
||||
lcd_outdezAtt(MODEL_CUSTOM_FUNC_3RD_COLUMN, y, val_displayed, attr|PREC1|LEFT, "s");
|
||||
}
|
||||
else {
|
||||
lcd_putsiAtt(MODEL_CUSTOM_FUNC_3RD_COLUMN, y, STR_MMMINV, 0, attr);
|
||||
}
|
||||
}
|
||||
#if defined(REVPLUS)
|
||||
else if (func == FUNC_BACKLIGHT) {
|
||||
displaySlider(MODEL_CUSTOM_FUNC_3RD_COLUMN, y, CFN_PARAM(cfn), 100, attr);
|
||||
INCDEC_SET_FLAG(eeFlags | NO_INCDEC_MARKS);
|
||||
val_min = 0;
|
||||
val_max = 100;
|
||||
}
|
||||
#endif
|
||||
#if defined(GVARS)
|
||||
else if (func == FUNC_ADJUST_GVAR) {
|
||||
switch (CFN_GVAR_MODE(cfn)) {
|
||||
case FUNC_ADJUST_GVAR_CONSTANT:
|
||||
val_displayed = (int16_t)CFN_PARAM(cfn);
|
||||
val_min = -CFN_GVAR_CST_MAX; val_max = +CFN_GVAR_CST_MAX;
|
||||
lcd_outdezAtt(MODEL_CUSTOM_FUNC_3RD_COLUMN, y, val_displayed, attr|LEFT);
|
||||
break;
|
||||
case FUNC_ADJUST_GVAR_SOURCE:
|
||||
val_max = MIXSRC_LAST_CH;
|
||||
putsMixerSource(MODEL_CUSTOM_FUNC_3RD_COLUMN, y, val_displayed, attr);
|
||||
INCDEC_SET_FLAG(eeFlags | INCDEC_SOURCE);
|
||||
INCDEC_ENABLE_CHECK(isSourceAvailable);
|
||||
break;
|
||||
case FUNC_ADJUST_GVAR_GVAR:
|
||||
val_max = MAX_GVARS-1;
|
||||
putsStrIdx(MODEL_CUSTOM_FUNC_3RD_COLUMN, y, STR_GV, val_displayed+1, attr);
|
||||
break;
|
||||
default: // FUNC_ADJUST_GVAR_INC
|
||||
val_max = 1;
|
||||
lcd_putsiAtt(MODEL_CUSTOM_FUNC_3RD_COLUMN, y, PSTR("\003-=1+=1"), val_displayed, attr);
|
||||
break;
|
||||
}
|
||||
|
||||
if (attr && event==EVT_KEY_LONG(KEY_ENTER)) {
|
||||
killEvents(event);
|
||||
s_editMode = !s_editMode;
|
||||
active = true;
|
||||
CFN_GVAR_MODE(cfn) += 1;
|
||||
CFN_GVAR_MODE(cfn) &= 0x03;
|
||||
val_displayed = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
else if (attr) {
|
||||
REPEAT_LAST_CURSOR_MOVE();
|
||||
}
|
||||
|
||||
if (active) {
|
||||
CFN_PARAM(cfn) = CHECK_INCDEC_PARAM(event, val_displayed, val_min, val_max);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 4:
|
||||
if (HAS_ENABLE_PARAM(func)) {
|
||||
lcdDrawCheckBox(MODEL_CUSTOM_FUNC_4TH_COLUMN_ONOFF, y, CFN_ACTIVE(cfn), attr);
|
||||
if (active) CFN_ACTIVE(cfn) = checkIncDec(event, CFN_ACTIVE(cfn), 0, 1, eeFlags);
|
||||
}
|
||||
else if (HAS_REPEAT_PARAM(func)) {
|
||||
if (CFN_PLAY_REPEAT(cfn) == 0) {
|
||||
lcd_putsAtt(MODEL_CUSTOM_FUNC_4TH_COLUMN+2, y, "1x", attr);
|
||||
}
|
||||
else if (CFN_PLAY_REPEAT(cfn) == CFN_PLAY_REPEAT_NOSTART) {
|
||||
lcd_putsAtt(MODEL_CUSTOM_FUNC_4TH_COLUMN-1, y, "!1x", attr);
|
||||
}
|
||||
else {
|
||||
lcd_outdezAtt(MODEL_CUSTOM_FUNC_4TH_COLUMN+12, y, CFN_PLAY_REPEAT(cfn)*CFN_PLAY_REPEAT_MUL, attr, "s");
|
||||
}
|
||||
if (active) CFN_PLAY_REPEAT(cfn) = checkIncDec(event, CFN_PLAY_REPEAT(cfn)==CFN_PLAY_REPEAT_NOSTART?-1:CFN_PLAY_REPEAT(cfn), -1, 60/CFN_PLAY_REPEAT_MUL, eeFlags);
|
||||
}
|
||||
else if (attr) {
|
||||
REPEAT_LAST_CURSOR_MOVE();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void menuModelCustomFunctions(evt_t event)
|
||||
{
|
||||
MENU(STR_MENUCUSTOMFUNC, menuTabModel, e_CustomFunctions, NUM_CFN, DEFAULT_SCROLLBAR_X, { NAVIGATION_LINE_BY_LINE|4/*repeated*/ });
|
||||
return menuCustomFunctions(event, g_model.customFn, modelFunctionsContext);
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
* Authors (alphabetical order)
|
||||
* - Andre Bernet <bernet.andre@gmail.com>
|
||||
* - Andreas Weitl
|
||||
* - Bertrand Songis <bsongis@gmail.com>
|
||||
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
|
||||
* - Cameron Weeks <th9xer@gmail.com>
|
||||
* - Erez Raviv
|
||||
* - Gabriel Birkus
|
||||
* - Jean-Pierre Parisy
|
||||
* - Karl Szmutny
|
||||
* - Michael Blandford
|
||||
* - Michal Hlavinka
|
||||
* - Pat Mackenzie
|
||||
* - Philip Moss
|
||||
* - Rob Thomson
|
||||
* - 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 FlightModesItems {
|
||||
ITEM_FLIGHT_MODES_NAME,
|
||||
ITEM_FLIGHT_MODES_SWITCH,
|
||||
ITEM_FLIGHT_MODES_TRIM_RUD,
|
||||
ITEM_FLIGHT_MODES_TRIM_ELE,
|
||||
ITEM_FLIGHT_MODES_TRIM_THR,
|
||||
ITEM_FLIGHT_MODES_TRIM_AIL,
|
||||
ITEM_FLIGHT_MODES_FADE_IN,
|
||||
ITEM_FLIGHT_MODES_FADE_OUT,
|
||||
ITEM_FLIGHT_MODES_COUNT,
|
||||
ITEM_FLIGHT_MODES_LAST = ITEM_FLIGHT_MODES_COUNT-1
|
||||
};
|
||||
|
||||
bool isTrimModeAvailable(int mode)
|
||||
{
|
||||
return (mode < 0 || (mode%2) == 0 || (mode/2) != m_posVert);
|
||||
}
|
||||
|
||||
void menuModelFlightModesAll(evt_t event)
|
||||
{
|
||||
MENU(STR_MENUFLIGHTPHASES, menuTabModel, e_FlightModesAll, MAX_FLIGHT_MODES+1, DEFAULT_SCROLLBAR_X, { NAVIGATION_LINE_BY_LINE|(ITEM_FLIGHT_MODES_LAST-1), NAVIGATION_LINE_BY_LINE|ITEM_FLIGHT_MODES_LAST, NAVIGATION_LINE_BY_LINE|ITEM_FLIGHT_MODES_LAST, NAVIGATION_LINE_BY_LINE|NAVIGATION_LINE_BY_LINE|ITEM_FLIGHT_MODES_LAST, NAVIGATION_LINE_BY_LINE|ITEM_FLIGHT_MODES_LAST, NAVIGATION_LINE_BY_LINE|ITEM_FLIGHT_MODES_LAST, NAVIGATION_LINE_BY_LINE|ITEM_FLIGHT_MODES_LAST, NAVIGATION_LINE_BY_LINE|ITEM_FLIGHT_MODES_LAST, NAVIGATION_LINE_BY_LINE|ITEM_FLIGHT_MODES_LAST, 0});
|
||||
|
||||
int sub = m_posVert;
|
||||
|
||||
horzpos_t posHorz = m_posHorz;
|
||||
if (sub==0 && posHorz > 0) { posHorz += 1; }
|
||||
|
||||
if (sub<MAX_FLIGHT_MODES && posHorz>=0) {
|
||||
displayColumnHeader(STR_PHASES_HEADERS, posHorz);
|
||||
}
|
||||
|
||||
for (int i=0; i<NUM_BODY_LINES; i++) {
|
||||
coord_t y = MENU_CONTENT_TOP + i*FH;
|
||||
int k = i+s_pgOfs;
|
||||
|
||||
if (k==MAX_FLIGHT_MODES) {
|
||||
// last line available - add the "check trims" line
|
||||
LcdFlags attr = 0;
|
||||
if (sub==MAX_FLIGHT_MODES) {
|
||||
if (!trimsCheckTimer) {
|
||||
if (event == EVT_KEY_FIRST(KEY_ENTER)) {
|
||||
trimsCheckTimer = 200; // 2 seconds trims cancelled
|
||||
s_editMode = 1;
|
||||
killEvents(event);
|
||||
}
|
||||
else {
|
||||
attr |= INVERS;
|
||||
s_editMode = 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (event == EVT_KEY_FIRST(KEY_EXIT)) {
|
||||
trimsCheckTimer = 0;
|
||||
s_editMode = 0;
|
||||
killEvents(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
char s[32];
|
||||
sprintf(s, "Check FM%d Trims", mixerCurrentFlightMode);
|
||||
lcd_putsCenter(y, s, attr);
|
||||
return;
|
||||
}
|
||||
|
||||
FlightModeData *p = flightModeAddress(k);
|
||||
|
||||
putsFlightMode(MENU_TITLE_LEFT, y, k+1, (getFlightMode()==k ? 0/*BOLD*/ : 0) | ((sub==k && m_posHorz<0) ? INVERS : 0));
|
||||
|
||||
for (int j=0; j<ITEM_FLIGHT_MODES_COUNT; j++) {
|
||||
LcdFlags attr = ((sub==k && posHorz==j) ? ((s_editMode>0) ? BLINK|INVERS : INVERS) : 0);
|
||||
LcdFlags active = (attr && s_editMode>0) ;
|
||||
switch (j) {
|
||||
case ITEM_FLIGHT_MODES_NAME:
|
||||
editName(45, y, p->name, sizeof(p->name), event, attr);
|
||||
break;
|
||||
|
||||
case ITEM_FLIGHT_MODES_SWITCH:
|
||||
if (k == 0)
|
||||
lcd_puts(145, y, "N/A");
|
||||
else
|
||||
putsSwitches(145, y, p->swtch, attr);
|
||||
if (active) CHECK_INCDEC_MODELSWITCH(event, p->swtch, SWSRC_FIRST_IN_MIXES, SWSRC_LAST_IN_MIXES, isSwitchAvailableInMixes);
|
||||
break;
|
||||
|
||||
case ITEM_FLIGHT_MODES_TRIM_RUD:
|
||||
case ITEM_FLIGHT_MODES_TRIM_ELE:
|
||||
case ITEM_FLIGHT_MODES_TRIM_THR:
|
||||
case ITEM_FLIGHT_MODES_TRIM_AIL:
|
||||
{
|
||||
uint8_t t = j-ITEM_FLIGHT_MODES_TRIM_RUD;
|
||||
putsTrimMode(155+j*15, y, k, t, attr);
|
||||
if (active) {
|
||||
trim_t & v = p->trim[t];
|
||||
v.mode = checkIncDec(event, v.mode==TRIM_MODE_NONE ? -1 : v.mode, -1, k==0 ? 0 : 2*MAX_FLIGHT_MODES-1, EE_MODEL, isTrimModeAvailable);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case ITEM_FLIGHT_MODES_FADE_IN:
|
||||
lcd_outdezAtt(272, y, (10/DELAY_STEP)*p->fadeIn, attr|PREC1);
|
||||
if (active) p->fadeIn = checkIncDec(event, p->fadeIn, 0, DELAY_MAX, EE_MODEL|NO_INCDEC_MARKS);
|
||||
break;
|
||||
|
||||
case ITEM_FLIGHT_MODES_FADE_OUT:
|
||||
lcd_outdezAtt(300, y, (10/DELAY_STEP)*p->fadeOut, attr|PREC1);
|
||||
if (active) p->fadeOut = checkIncDec(event, p->fadeOut, 0, DELAY_MAX, EE_MODEL|NO_INCDEC_MARKS);
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* Authors (alphabetical order)
|
||||
* - Andre Bernet <bernet.andre@gmail.com>
|
||||
* - Andreas Weitl
|
||||
* - Bertrand Songis <bsongis@gmail.com>
|
||||
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
|
||||
* - Cameron Weeks <th9xer@gmail.com>
|
||||
* - Erez Raviv
|
||||
* - Gabriel Birkus
|
||||
* - Jean-Pierre Parisy
|
||||
* - Karl Szmutny
|
||||
* - Michael Blandford
|
||||
* - Michal Hlavinka
|
||||
* - Pat Mackenzie
|
||||
* - Philip Moss
|
||||
* - Rob Thomson
|
||||
* - 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 onGVARSMenu(const char *result)
|
||||
{
|
||||
int8_t sub = m_posVert;
|
||||
|
||||
if (result == STR_ENABLE_POPUP) {
|
||||
g_model.gvars[sub].popup = true;
|
||||
eeDirty(EE_MODEL);
|
||||
}
|
||||
else if (result == STR_DISABLE_POPUP) {
|
||||
g_model.gvars[sub].popup = false;
|
||||
eeDirty(EE_MODEL);
|
||||
}
|
||||
else if (result == STR_CLEAR) {
|
||||
for (int i=0; i<MAX_FLIGHT_MODES; i++) {
|
||||
g_model.flightModeData[i].gvars[sub] = 0;
|
||||
}
|
||||
eeDirty(EE_MODEL);
|
||||
}
|
||||
}
|
||||
|
||||
#define GVARS_FM_COLUMN(p) (123 + (p)*24)
|
||||
|
||||
void menuModelGVars(evt_t event)
|
||||
{
|
||||
MENU(STR_MENUGLOBALVARS, menuTabModel, e_GVars/* TODO, first2seconds ? CHECK_FLAG_NO_SCREEN_INDEX : 0*/, MAX_GVARS, DEFAULT_SCROLLBAR_X, { NAVIGATION_LINE_BY_LINE|MAX_FLIGHT_MODES, NAVIGATION_LINE_BY_LINE|MAX_FLIGHT_MODES, NAVIGATION_LINE_BY_LINE|MAX_FLIGHT_MODES, NAVIGATION_LINE_BY_LINE|MAX_FLIGHT_MODES, NAVIGATION_LINE_BY_LINE|MAX_FLIGHT_MODES, NAVIGATION_LINE_BY_LINE|MAX_FLIGHT_MODES, NAVIGATION_LINE_BY_LINE|MAX_FLIGHT_MODES, NAVIGATION_LINE_BY_LINE|MAX_FLIGHT_MODES, NAVIGATION_LINE_BY_LINE|MAX_FLIGHT_MODES});
|
||||
|
||||
int sub = m_posVert;
|
||||
|
||||
for (int l=0; l<NUM_BODY_LINES; l++) {
|
||||
int i = l+s_pgOfs;
|
||||
coord_t y = MENU_CONTENT_TOP + l*FH;
|
||||
if (g_model.gvars[i].popup) lcd_puts(MENU_TITLE_LEFT+25, y, "!");
|
||||
putsStrIdx(MENU_TITLE_LEFT, y, STR_GV, i+1, ((sub==i && m_posHorz<0) ? INVERS : 0));
|
||||
|
||||
for (int j=0; j<1+MAX_FLIGHT_MODES; j++) {
|
||||
LcdFlags attr = ((sub==i && m_posHorz==j) ? ((s_editMode>0) ? BLINK|INVERS : INVERS) : 0);
|
||||
coord_t x = GVARS_FM_COLUMN(j-1);
|
||||
switch(j)
|
||||
{
|
||||
case 0:
|
||||
editName(MENU_TITLE_LEFT+30, y, g_model.gvars[i].name, LEN_GVAR_NAME, event, attr);
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
FlightModeData *fm = &g_model.flightModeData[j-1];
|
||||
int16_t & v = fm->gvars[i];
|
||||
int16_t vmin, vmax;
|
||||
if (v > GVAR_MAX) {
|
||||
uint8_t p = v - GVAR_MAX - 1;
|
||||
if (p >= j-1) p++;
|
||||
putsFlightMode(x-21, y, p+1, attr);
|
||||
vmin = GVAR_MAX+1; vmax = GVAR_MAX+MAX_FLIGHT_MODES-1;
|
||||
}
|
||||
else {
|
||||
if (abs(v) >= 1000)
|
||||
lcd_outdezAtt(x, y+1, v, TINSIZE|attr);
|
||||
else
|
||||
lcd_outdezAtt(x, y, v, attr);
|
||||
vmin = -GVAR_MAX; vmax = GVAR_MAX;
|
||||
}
|
||||
if (attr) {
|
||||
if (event == EVT_KEY_LONG(KEY_ENTER)) {
|
||||
v = (v > GVAR_MAX ? 0 : GVAR_MAX+1);
|
||||
eeDirty(EE_MODEL);
|
||||
}
|
||||
else if (s_editMode>0) {
|
||||
v = checkIncDec(event, v, vmin, vmax, EE_MODEL);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (m_posHorz < 0 && event==EVT_KEY_LONG(KEY_ENTER)) {
|
||||
killEvents(event);
|
||||
if (g_model.gvars[sub].popup)
|
||||
MENU_ADD_ITEM(STR_DISABLE_POPUP);
|
||||
else
|
||||
MENU_ADD_ITEM(STR_ENABLE_POPUP);
|
||||
MENU_ADD_ITEM(STR_CLEAR);
|
||||
menuHandler = onGVARSMenu;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Authors (alphabetical order)
|
||||
* - Andre Bernet <bernet.andre@gmail.com>
|
||||
* - Andreas Weitl
|
||||
* - Bertrand Songis <bsongis@gmail.com>
|
||||
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
|
||||
* - Cameron Weeks <th9xer@gmail.com>
|
||||
* - Erez Raviv
|
||||
* - Gabriel Birkus
|
||||
* - Jean-Pierre Parisy
|
||||
* - Karl Szmutny
|
||||
* - Michael Blandford
|
||||
* - Michal Hlavinka
|
||||
* - Pat Mackenzie
|
||||
* - Philip Moss
|
||||
* - Rob Thomson
|
||||
* - 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 menuModelHeliItems {
|
||||
ITEM_HELI_SWASHTYPE,
|
||||
ITEM_HELI_SWASHRING,
|
||||
ITEM_HELI_ELE,
|
||||
ITEM_HELI_ELE_WEIGHT,
|
||||
ITEM_HELI_AIL,
|
||||
ITEM_HELI_AIL_WEIGHT,
|
||||
ITEM_HELI_COL,
|
||||
ITEM_HELI_COL_WEIGHT,
|
||||
ITEM_HELI_MAX
|
||||
};
|
||||
|
||||
#define MODEL_HELI_2ND_COLUMN (230)
|
||||
|
||||
void menuModelHeli(evt_t event)
|
||||
{
|
||||
SIMPLE_MENU(STR_MENUHELISETUP, menuTabModel, e_Heli, ITEM_HELI_MAX, DEFAULT_SCROLLBAR_X);
|
||||
|
||||
int sub = m_posVert;
|
||||
|
||||
for (unsigned int i=0; i<NUM_BODY_LINES; i++) {
|
||||
coord_t y = MENU_CONTENT_TOP + i*FH;
|
||||
int k = i+s_pgOfs;
|
||||
LcdFlags blink = ((s_editMode>0) ? BLINK|INVERS : INVERS);
|
||||
LcdFlags attr = (sub == k ? blink : 0);
|
||||
|
||||
switch(k) {
|
||||
case ITEM_HELI_SWASHTYPE:
|
||||
g_model.swashR.type = selectMenuItem(MODEL_HELI_2ND_COLUMN, y, STR_SWASHTYPE, STR_VSWASHTYPE, g_model.swashR.type, 0, SWASH_TYPE_MAX, attr, event);
|
||||
break;
|
||||
|
||||
case ITEM_HELI_SWASHRING:
|
||||
lcd_putsLeft(y, STR_SWASHRING);
|
||||
lcd_outdezAtt(MODEL_HELI_2ND_COLUMN, y, g_model.swashR.value, LEFT|attr);
|
||||
if (attr) CHECK_INCDEC_MODELVAR_ZERO(event, g_model.swashR.value, 100);
|
||||
break;
|
||||
|
||||
case ITEM_HELI_ELE:
|
||||
lcd_putsLeft(y, STR_ELEVATOR);
|
||||
putsMixerSource(MODEL_HELI_2ND_COLUMN, y, g_model.swashR.elevatorSource, attr);
|
||||
if (attr) CHECK_INCDEC_MODELSOURCE(event, g_model.swashR.elevatorSource, 0, MIXSRC_LAST_CH);
|
||||
break;
|
||||
|
||||
case ITEM_HELI_ELE_WEIGHT:
|
||||
lcd_puts(MENU_TITLE_LEFT+INDENT_WIDTH, y, STR_WEIGHT);
|
||||
lcd_outdezAtt(MODEL_HELI_2ND_COLUMN, y, g_model.swashR.elevatorWeight, LEFT|attr);
|
||||
if (attr) CHECK_INCDEC_MODELVAR(event, g_model.swashR.elevatorWeight, -100, 100);
|
||||
break;
|
||||
|
||||
case ITEM_HELI_AIL:
|
||||
lcd_putsLeft(y, STR_AILERON);
|
||||
putsMixerSource(MODEL_HELI_2ND_COLUMN, y, g_model.swashR.aileronSource, attr);
|
||||
if (attr) CHECK_INCDEC_MODELSOURCE(event, g_model.swashR.aileronSource, 0, MIXSRC_LAST_CH);
|
||||
break;
|
||||
|
||||
case ITEM_HELI_AIL_WEIGHT:
|
||||
lcd_puts(MENU_TITLE_LEFT+INDENT_WIDTH, y, STR_WEIGHT);
|
||||
lcd_outdezAtt(MODEL_HELI_2ND_COLUMN, y, g_model.swashR.aileronWeight, LEFT|attr);
|
||||
if (attr) CHECK_INCDEC_MODELVAR(event, g_model.swashR.aileronWeight, -100, 100);
|
||||
break;
|
||||
|
||||
case ITEM_HELI_COL:
|
||||
lcd_putsLeft(y, STR_COLLECTIVE);
|
||||
putsMixerSource(MODEL_HELI_2ND_COLUMN, y, g_model.swashR.collectiveSource, attr);
|
||||
if (attr) CHECK_INCDEC_MODELSOURCE(event, g_model.swashR.collectiveSource, 0, MIXSRC_LAST_CH);
|
||||
break;
|
||||
|
||||
case ITEM_HELI_COL_WEIGHT:
|
||||
lcd_puts(MENU_TITLE_LEFT+INDENT_WIDTH, y, STR_WEIGHT);
|
||||
lcd_outdezAtt(MODEL_HELI_2ND_COLUMN, y, g_model.swashR.collectiveWeight, LEFT|attr);
|
||||
if (attr) CHECK_INCDEC_MODELVAR(event, g_model.swashR.collectiveWeight, -100, 100);
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,971 @@
|
||||
/*
|
||||
* Authors (alphabetical order)
|
||||
* - Andre Bernet <bernet.andre@gmail.com>
|
||||
* - Andreas Weitl
|
||||
* - Bertrand Songis <bsongis@gmail.com>
|
||||
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
|
||||
* - Cameron Weeks <th9xer@gmail.com>
|
||||
* - Erez Raviv
|
||||
* - Gabriel Birkus
|
||||
* - Jean-Pierre Parisy
|
||||
* - Karl Szmutny
|
||||
* - Michael Blandford
|
||||
* - Michal Hlavinka
|
||||
* - Pat Mackenzie
|
||||
* - Philip Moss
|
||||
* - Rob Thomson
|
||||
* - 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 EXPO_ONE_2ND_COLUMN 80
|
||||
|
||||
#if defined(FLIGHT_MODES)
|
||||
void displayFlightModes(coord_t x, coord_t y, FlightModesType value, uint8_t attr)
|
||||
{
|
||||
for (int i=0; i<MAX_FLIGHT_MODES; i++) {
|
||||
LcdFlags flags = ((m_posHorz==i && attr) ? INVERS : 0);
|
||||
flags |= ((value & (1<<i))) ? TEXT_DISABLE_COLOR : TEXT_COLOR;
|
||||
if (attr && m_posHorz < 0) flags |= INVERS;
|
||||
char s[] = " ";
|
||||
s[0] = '0' + i;
|
||||
lcd_putsAtt(x, y, s, flags);
|
||||
x += 9;
|
||||
}
|
||||
}
|
||||
|
||||
FlightModesType editFlightModes(coord_t x, coord_t y, evt_t event, FlightModesType value, uint8_t attr)
|
||||
{
|
||||
lcd_putsColumnLeft(x, y, STR_FLMODE);
|
||||
|
||||
int posHorz = m_posHorz;
|
||||
|
||||
displayFlightModes(x, y, value, attr);
|
||||
|
||||
if (attr) {
|
||||
if (s_editMode && event==EVT_KEY_BREAK(KEY_ENTER)) {
|
||||
s_editMode = 0;
|
||||
value ^= (1<<posHorz);
|
||||
eeDirty(EE_MODEL);
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
#else
|
||||
#define displayFlightModes(...)
|
||||
#endif
|
||||
|
||||
int expoFn(int x)
|
||||
{
|
||||
ExpoData *ed = expoAddress(s_currIdx);
|
||||
int16_t anas[NUM_INPUTS] = {0};
|
||||
applyExpos(anas, e_perout_mode_inactive_flight_mode, ed->srcRaw, x);
|
||||
return anas[ed->chn];
|
||||
}
|
||||
|
||||
coord_t getYCoord(FnFuncP fn, coord_t x)
|
||||
{
|
||||
return limit(0, Y0 - (fn(x * (RESX/WCHART)) * WCHART / RESX), LCD_H-1);
|
||||
}
|
||||
|
||||
void DrawFunction(FnFuncP fn, int offset)
|
||||
{
|
||||
lcd_vlineStip(X0-offset, Y0-WCHART, WCHART*2, 0xee, CURVE_AXIS_COLOR);
|
||||
lcd_hlineStip(X0-WCHART-offset, Y0, WCHART*2, 0xee, CURVE_AXIS_COLOR);
|
||||
|
||||
coord_t ymin=0, ymax=0, info=0;
|
||||
for (int xv=-WCHART; xv<=WCHART; xv++) {
|
||||
coord_t yv = getYCoord(fn, xv);
|
||||
|
||||
if (ymin == 0 || yv < ymin)
|
||||
ymin = yv;
|
||||
if (ymax == 0 || yv > ymax)
|
||||
ymax = yv;
|
||||
info += yv*xv;
|
||||
}
|
||||
}
|
||||
|
||||
int getLinesCount(uint8_t expo)
|
||||
{
|
||||
int lastch = -1;
|
||||
uint8_t count = (expo ? MAX_INPUTS : NUM_CHNOUT);
|
||||
for (int i=0; i<(expo ? MAX_EXPOS : MAX_MIXERS); i++) {
|
||||
bool valid = (expo ? EXPO_VALID(expoAddress(i)) : mixAddress(i)->srcRaw);
|
||||
if (!valid)
|
||||
break;
|
||||
int ch = (expo ? expoAddress(i)->chn : mixAddress(i)->destCh);
|
||||
if (ch == lastch) {
|
||||
count++;
|
||||
}
|
||||
else {
|
||||
lastch = ch;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
uint8_t getExpoMixCount(uint8_t expo)
|
||||
{
|
||||
uint8_t count = 0;
|
||||
uint8_t ch ;
|
||||
|
||||
for(int8_t i=(expo ? MAX_EXPOS-1 : MAX_MIXERS-1); i>=0; i--) {
|
||||
ch = (expo ? EXPO_VALID(expoAddress(i)) : mixAddress(i)->srcRaw);
|
||||
if (ch != 0) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
bool reachExpoMixCountLimit(uint8_t expo)
|
||||
{
|
||||
// check mixers count limit
|
||||
if (getExpoMixCount(expo) >= (expo ? MAX_EXPOS : MAX_MIXERS)) {
|
||||
POPUP_WARNING(expo ? STR_NOFREEEXPO : STR_NOFREEMIXER);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void deleteExpoMix(uint8_t expo, uint8_t idx)
|
||||
{
|
||||
pauseMixerCalculations();
|
||||
if (expo) {
|
||||
ExpoData *expo = expoAddress(idx);
|
||||
int input = expo->chn;
|
||||
memmove(expo, expo+1, (MAX_EXPOS-(idx+1))*sizeof(ExpoData));
|
||||
memclear(&g_model.expoData[MAX_EXPOS-1], sizeof(ExpoData));
|
||||
if (!isInputAvailable(input)) {
|
||||
memclear(&g_model.inputNames[input], LEN_INPUT_NAME);
|
||||
}
|
||||
}
|
||||
else {
|
||||
MixData *mix = mixAddress(idx);
|
||||
memmove(mix, mix+1, (MAX_MIXERS-(idx+1))*sizeof(MixData));
|
||||
memclear(&g_model.mixData[MAX_MIXERS-1], sizeof(MixData));
|
||||
}
|
||||
resumeMixerCalculations();
|
||||
eeDirty(EE_MODEL);
|
||||
}
|
||||
|
||||
// TODO avoid this global s_currCh on ARM boards ...
|
||||
int8_t s_currCh;
|
||||
void insertExpoMix(uint8_t expo, uint8_t idx)
|
||||
{
|
||||
pauseMixerCalculations();
|
||||
if (expo) {
|
||||
ExpoData *expo = expoAddress(idx);
|
||||
memmove(expo+1, expo, (MAX_EXPOS-(idx+1))*sizeof(ExpoData));
|
||||
memclear(expo, sizeof(ExpoData));
|
||||
expo->srcRaw = (s_currCh > 4 ? MIXSRC_Rud - 1 + s_currCh : MIXSRC_Rud - 1 + channel_order(s_currCh));
|
||||
expo->curve.type = CURVE_REF_EXPO;
|
||||
expo->mode = 3; // pos&neg
|
||||
expo->chn = s_currCh - 1;
|
||||
expo->weight = 100;
|
||||
}
|
||||
else {
|
||||
MixData *mix = mixAddress(idx);
|
||||
memmove(mix+1, mix, (MAX_MIXERS-(idx+1))*sizeof(MixData));
|
||||
memclear(mix, sizeof(MixData));
|
||||
mix->destCh = s_currCh-1;
|
||||
mix->srcRaw = s_currCh;
|
||||
if (!isSourceAvailable(mix->srcRaw)) {
|
||||
mix->srcRaw = (s_currCh > 4 ? MIXSRC_Rud - 1 + s_currCh : MIXSRC_Rud - 1 + channel_order(s_currCh));
|
||||
while (!isSourceAvailable(mix->srcRaw)) {
|
||||
mix->srcRaw += 1;
|
||||
}
|
||||
}
|
||||
mix->weight = 100;
|
||||
}
|
||||
resumeMixerCalculations();
|
||||
eeDirty(EE_MODEL);
|
||||
}
|
||||
|
||||
void copyExpoMix(uint8_t expo, uint8_t idx)
|
||||
{
|
||||
pauseMixerCalculations();
|
||||
if (expo) {
|
||||
ExpoData *expo = expoAddress(idx);
|
||||
memmove(expo+1, expo, (MAX_EXPOS-(idx+1))*sizeof(ExpoData));
|
||||
}
|
||||
else {
|
||||
MixData *mix = mixAddress(idx);
|
||||
memmove(mix+1, mix, (MAX_MIXERS-(idx+1))*sizeof(MixData));
|
||||
}
|
||||
resumeMixerCalculations();
|
||||
eeDirty(EE_MODEL);
|
||||
}
|
||||
|
||||
void memswap(void *a, void *b, uint8_t size)
|
||||
{
|
||||
uint8_t *x = (uint8_t*)a;
|
||||
uint8_t *y = (uint8_t*)b;
|
||||
uint8_t temp ;
|
||||
|
||||
while (size--) {
|
||||
temp = *x;
|
||||
*x++ = *y;
|
||||
*y++ = temp;
|
||||
}
|
||||
}
|
||||
|
||||
bool swapExpoMix(uint8_t expo, uint8_t &idx, uint8_t up)
|
||||
{
|
||||
void *x, *y;
|
||||
uint8_t size;
|
||||
int8_t tgt_idx = (up ? idx-1 : idx+1);
|
||||
|
||||
if (expo) {
|
||||
x = (ExpoData *)expoAddress(idx);
|
||||
|
||||
if (tgt_idx < 0) {
|
||||
if (((ExpoData *)x)->chn == 0)
|
||||
return false;
|
||||
((ExpoData *)x)->chn--;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (tgt_idx == MAX_EXPOS) {
|
||||
if (((ExpoData *)x)->chn == NUM_INPUTS-1)
|
||||
return false;
|
||||
((ExpoData *)x)->chn++;
|
||||
return true;
|
||||
}
|
||||
|
||||
y = (ExpoData *)expoAddress(tgt_idx);
|
||||
if(((ExpoData *)x)->chn != ((ExpoData *)y)->chn || !EXPO_VALID((ExpoData *)y)) {
|
||||
if (up) {
|
||||
if (((ExpoData *)x)->chn>0) ((ExpoData *)x)->chn--;
|
||||
else return false;
|
||||
}
|
||||
else {
|
||||
if (((ExpoData *)x)->chn<NUM_INPUTS-1) ((ExpoData *)x)->chn++;
|
||||
else return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
size = sizeof(ExpoData);
|
||||
}
|
||||
else {
|
||||
x = (MixData *)mixAddress(idx);
|
||||
|
||||
if (tgt_idx < 0) {
|
||||
if (((MixData *)x)->destCh == 0)
|
||||
return false;
|
||||
((MixData *)x)->destCh--;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (tgt_idx == MAX_MIXERS) {
|
||||
if (((MixData *)x)->destCh == NUM_CHNOUT-1)
|
||||
return false;
|
||||
((MixData *)x)->destCh++;
|
||||
return true;
|
||||
}
|
||||
|
||||
y = (MixData *)mixAddress(tgt_idx);
|
||||
uint8_t destCh = ((MixData *)x)->destCh;
|
||||
if(!((MixData *)y)->srcRaw || destCh != ((MixData *)y)->destCh) {
|
||||
if (up) {
|
||||
if (destCh>0) ((MixData *)x)->destCh--;
|
||||
else return false;
|
||||
}
|
||||
else {
|
||||
if (destCh<NUM_CHNOUT-1) ((MixData *)x)->destCh++;
|
||||
else return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
size = sizeof(MixData);
|
||||
}
|
||||
|
||||
pauseMixerCalculations();
|
||||
memswap(x, y, size);
|
||||
resumeMixerCalculations();
|
||||
|
||||
idx = tgt_idx;
|
||||
return true;
|
||||
}
|
||||
|
||||
enum ExposFields {
|
||||
EXPO_FIELD_INPUT_NAME,
|
||||
EXPO_FIELD_NAME,
|
||||
EXPO_FIELD_SOURCE,
|
||||
EXPO_FIELD_SCALE,
|
||||
EXPO_FIELD_WEIGHT,
|
||||
EXPO_FIELD_OFFSET,
|
||||
CASE_CURVES(EXPO_FIELD_CURVE)
|
||||
CASE_FLIGHT_MODES(EXPO_FIELD_FLIGHT_MODES)
|
||||
EXPO_FIELD_SWITCH,
|
||||
EXPO_FIELD_SIDE,
|
||||
EXPO_FIELD_TRIM,
|
||||
EXPO_FIELD_MAX
|
||||
};
|
||||
|
||||
#define CURVE_ROWS 1
|
||||
|
||||
void menuModelExpoOne(evt_t event)
|
||||
{
|
||||
ExpoData *ed = expoAddress(s_currIdx);
|
||||
|
||||
SUBMENU(STR_MENUINPUTS, EXPO_FIELD_MAX, EXPO_ONE_2ND_COLUMN+85, { 0, 0, 0, (ed->srcRaw >= MIXSRC_FIRST_TELEM ? (uint8_t)0 : (uint8_t)HIDDEN_ROW), 0, 0, CASE_CURVES(CURVE_ROWS) CASE_FLIGHT_MODES((MAX_FLIGHT_MODES-1) | NAVIGATION_LINE_BY_LINE) 0 /*, ...*/});
|
||||
|
||||
putsMixerSource(60, MENU_FOOTER_TOP, MIXSRC_FIRST_INPUT+ed->chn, HEADER_COLOR);
|
||||
|
||||
int8_t sub = m_posVert;
|
||||
|
||||
coord_t y = MENU_CONTENT_TOP;
|
||||
|
||||
DrawFunction(expoFn);
|
||||
|
||||
{
|
||||
int x = getValue(ed->srcRaw);
|
||||
if (ed->srcRaw >= MIXSRC_FIRST_TELEM) {
|
||||
putsTelemetryChannelValue(LCD_W-8, 6*FH, ed->srcRaw - MIXSRC_FIRST_TELEM, x);
|
||||
if (ed->scale > 0) x = (x * 1024) / convertTelemValue(ed->srcRaw - MIXSRC_FIRST_TELEM + 1, ed->scale);
|
||||
}
|
||||
else {
|
||||
lcd_outdezAtt(X0+WCHART, MENU_HEADER_HEIGHT+6*FH, calcRESXto1000(x), PREC1);
|
||||
}
|
||||
|
||||
x = limit(-1024, x, 1024);
|
||||
int y = limit<int>(-1024, expoFn(x), 1024);
|
||||
lcd_outdezAtt(X0-WCHART, MENU_HEADER_HEIGHT+1, calcRESXto1000(y), LEFT|PREC1);
|
||||
|
||||
x = x / (RESX/WCHART);
|
||||
y = getYCoord(expoFn, x);
|
||||
|
||||
lcd_vlineStip(X0+x, y-3, 7, SOLID, TEXT_INVERTED_BGCOLOR);
|
||||
lcd_hlineStip(X0+x-3, y, 7, SOLID, TEXT_INVERTED_BGCOLOR);
|
||||
}
|
||||
|
||||
for (unsigned int k=0; k<NUM_BODY_LINES; k++) {
|
||||
int i = k + s_pgOfs;
|
||||
for (int j=0; j<=i; ++j) {
|
||||
if (j<(int)DIM(mstate_tab) && mstate_tab[j] == HIDDEN_ROW) {
|
||||
++i;
|
||||
}
|
||||
}
|
||||
LcdFlags attr = (sub==i ? (s_editMode>0 ? BLINK|INVERS : INVERS) : 0);
|
||||
switch(i)
|
||||
{
|
||||
case EXPO_FIELD_INPUT_NAME:
|
||||
editSingleName(EXPO_ONE_2ND_COLUMN, y, STR_INPUTNAME, g_model.inputNames[ed->chn], sizeof(g_model.inputNames[ed->chn]), event, attr);
|
||||
break;
|
||||
|
||||
case EXPO_FIELD_NAME:
|
||||
editSingleName(EXPO_ONE_2ND_COLUMN, y, STR_EXPONAME, ed->name, sizeof(ed->name), event, attr);
|
||||
break;
|
||||
|
||||
case EXPO_FIELD_SOURCE:
|
||||
lcd_putsLeft(y, NO_INDENT(STR_SOURCE));
|
||||
putsMixerSource(EXPO_ONE_2ND_COLUMN, y, ed->srcRaw, STREXPANDED|attr);
|
||||
if (attr) ed->srcRaw = checkIncDec(event, ed->srcRaw, INPUTSRC_FIRST, INPUTSRC_LAST, EE_MODEL|INCDEC_SOURCE|NO_INCDEC_MARKS, isInputSourceAvailable);
|
||||
break;
|
||||
|
||||
case EXPO_FIELD_SCALE:
|
||||
lcd_putsLeft(y, STR_SCALE);
|
||||
putsTelemetryChannelValue(EXPO_ONE_2ND_COLUMN, y, (ed->srcRaw - MIXSRC_FIRST_TELEM)/3, convertTelemValue(ed->srcRaw - MIXSRC_FIRST_TELEM + 1, ed->scale), LEFT|attr);
|
||||
if (attr) ed->scale = checkIncDec(event, ed->scale, 0, maxTelemValue(ed->srcRaw - MIXSRC_FIRST_TELEM + 1), EE_MODEL);
|
||||
break;
|
||||
|
||||
case EXPO_FIELD_WEIGHT:
|
||||
lcd_putsLeft(y, STR_WEIGHT);
|
||||
ed->weight = GVAR_MENU_ITEM(EXPO_ONE_2ND_COLUMN, y, ed->weight, MIN_EXPO_WEIGHT, 100, LEFT|attr, 0, event);
|
||||
break;
|
||||
|
||||
case EXPO_FIELD_OFFSET:
|
||||
lcd_putsLeft(y, NO_INDENT(STR_OFFSET));
|
||||
ed->offset = GVAR_MENU_ITEM(EXPO_ONE_2ND_COLUMN, y, ed->offset, -100, 100, LEFT|attr, 0, event);
|
||||
break;
|
||||
|
||||
#if defined(CURVES)
|
||||
case EXPO_FIELD_CURVE:
|
||||
lcd_putsLeft(y, STR_CURVE);
|
||||
editCurveRef(EXPO_ONE_2ND_COLUMN, y, ed->curve, event, attr);
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if defined(FLIGHT_MODES)
|
||||
case EXPO_FIELD_FLIGHT_MODES:
|
||||
ed->flightModes = editFlightModes(EXPO_ONE_2ND_COLUMN, y, event, ed->flightModes, attr);
|
||||
break;
|
||||
#endif
|
||||
|
||||
case EXPO_FIELD_SWITCH:
|
||||
ed->swtch = switchMenuItem(EXPO_ONE_2ND_COLUMN, y, ed->swtch, attr, event);
|
||||
break;
|
||||
|
||||
case EXPO_FIELD_SIDE:
|
||||
ed->mode = 4 - selectMenuItem(EXPO_ONE_2ND_COLUMN, y, STR_SIDE, STR_VSIDE, 4-ed->mode, 1, 3, attr, event);
|
||||
break;
|
||||
|
||||
case EXPO_FIELD_TRIM:
|
||||
uint8_t not_stick = (ed->srcRaw > MIXSRC_Ail);
|
||||
int8_t carryTrim = -ed->carryTrim;
|
||||
lcd_putsLeft(y, STR_TRIM);
|
||||
lcd_putsiAtt(EXPO_ONE_2ND_COLUMN, y, STR_VMIXTRIMS, (not_stick && carryTrim == 0) ? 0 : carryTrim+1, m_posHorz==0 ? attr : 0);
|
||||
if (attr) ed->carryTrim = -checkIncDecModel(event, carryTrim, not_stick ? TRIM_ON : -TRIM_OFF, -TRIM_AIL);
|
||||
break;
|
||||
}
|
||||
y += FH;
|
||||
}
|
||||
}
|
||||
|
||||
enum MixFields {
|
||||
MIX_FIELD_NAME,
|
||||
MIX_FIELD_SOURCE,
|
||||
MIX_FIELD_WEIGHT,
|
||||
MIX_FIELD_OFFSET,
|
||||
MIX_FIELD_TRIM,
|
||||
CASE_CURVES(MIX_FIELD_CURVE)
|
||||
CASE_FLIGHT_MODES(MIX_FIELD_FLIGHT_PHASE)
|
||||
MIX_FIELD_SWITCH,
|
||||
// MIX_FIELD_WARNING,
|
||||
MIX_FIELD_MLTPX,
|
||||
MIX_FIELD_DELAY_UP,
|
||||
MIX_FIELD_DELAY_DOWN,
|
||||
MIX_FIELD_SLOW_UP,
|
||||
MIX_FIELD_SLOW_DOWN,
|
||||
MIX_FIELD_COUNT
|
||||
};
|
||||
|
||||
void gvarWeightItem(coord_t x, coord_t y, MixData *md, uint8_t attr, evt_t event)
|
||||
{
|
||||
u_int8int16_t weight;
|
||||
MD_WEIGHT_TO_UNION(md, weight);
|
||||
weight.word = GVAR_MENU_ITEM(x, y, weight.word, GV_RANGELARGE_WEIGHT_NEG, GV_RANGELARGE_WEIGHT, attr, 0, event);
|
||||
MD_UNION_TO_WEIGHT(weight, md);
|
||||
}
|
||||
|
||||
#define GAUGE_WIDTH 33
|
||||
#define GAUGE_HEIGHT 6
|
||||
void drawOffsetBar(uint8_t x, uint8_t y, MixData * md)
|
||||
{
|
||||
int offset = GET_GVAR(MD_OFFSET(md), GV_RANGELARGE_NEG, GV_RANGELARGE, mixerCurrentFlightMode);
|
||||
int weight = abs(GET_GVAR(MD_WEIGHT(md), GV_RANGELARGE_NEG, GV_RANGELARGE, mixerCurrentFlightMode));
|
||||
int barMin = offset - weight;
|
||||
int barMax = offset + weight;
|
||||
if (y > 15) {
|
||||
lcd_outdezAtt(x-((barMin >= 0) ? 2 : 3), y-6, barMin, TINSIZE|LEFT);
|
||||
lcd_outdezAtt(x+GAUGE_WIDTH+1, y-6, barMax, TINSIZE);
|
||||
}
|
||||
if (barMin < -101)
|
||||
barMin = -101;
|
||||
if (barMax > 101)
|
||||
barMax = 101;
|
||||
lcd_hlineStip(x-2, y, GAUGE_WIDTH+2, DOTTED);
|
||||
lcd_hlineStip(x-2, y+GAUGE_HEIGHT, GAUGE_WIDTH+2, DOTTED);
|
||||
lcd_vline(x-2, y+1, GAUGE_HEIGHT-1);
|
||||
lcd_vline(x+GAUGE_WIDTH-1, y+1, GAUGE_HEIGHT-1);
|
||||
if (barMin <= barMax) {
|
||||
int8_t right = (barMax * GAUGE_WIDTH) / 200;
|
||||
int8_t left = ((barMin * GAUGE_WIDTH) / 200)-1;
|
||||
// TODO lcdDrawFilledRect(x+GAUGE_WIDTH/2+left, y+2, right-left, GAUGE_HEIGHT-3);
|
||||
}
|
||||
lcd_vline(x+GAUGE_WIDTH/2-1, y, GAUGE_HEIGHT+1);
|
||||
#if 0 // TODO
|
||||
if (barMin == -101) {
|
||||
for (uint8_t i=0; i<3; ++i) {
|
||||
lcdDrawPoint(x+i, y+4-i);
|
||||
lcdDrawPoint(x+3+i, y+4-i);
|
||||
}
|
||||
}
|
||||
if (barMax == 101) {
|
||||
for (uint8_t i=0; i<3; ++i) {
|
||||
lcdDrawPoint(x+GAUGE_WIDTH-8+i, y+4-i);
|
||||
lcdDrawPoint(x+GAUGE_WIDTH-5+i, y+4-i);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#undef GAUGE_WIDTH
|
||||
#undef GAUGE_HEIGHT
|
||||
|
||||
void menuModelMixOne(evt_t event)
|
||||
{
|
||||
MixData *md2 = mixAddress(s_currIdx) ;
|
||||
|
||||
SUBMENU(s_currCh ? STR_INSERTMIX : STR_EDITMIX, MIX_FIELD_COUNT, 0, { 0, 0, 0, 0, 0, CASE_CURVES(1) CASE_FLIGHT_MODES((MAX_FLIGHT_MODES-1) | NAVIGATION_LINE_BY_LINE) 0 /*, ...*/ });
|
||||
|
||||
putsChn(80, MENU_FOOTER_TOP, md2->destCh+1, HEADER_COLOR);
|
||||
|
||||
// The separation line between 2 columns
|
||||
lcd_vlineStip(MENU_COLUMN2_X, DEFAULT_SCROLLBAR_Y, DEFAULT_SCROLLBAR_H, SOLID, HEADER_COLOR);
|
||||
|
||||
int8_t sub = m_posVert;
|
||||
int8_t editMode = s_editMode;
|
||||
|
||||
for (int k=0; k<2*NUM_BODY_LINES; k++) {
|
||||
coord_t y;
|
||||
coord_t x;
|
||||
if (k >= NUM_BODY_LINES) {
|
||||
y = MENU_CONTENT_TOP + (k-NUM_BODY_LINES)*FH;
|
||||
x = MENU_COLUMN2_X;
|
||||
}
|
||||
else {
|
||||
y = MENU_CONTENT_TOP + k*FH;
|
||||
x = 0;
|
||||
}
|
||||
int8_t i = k;
|
||||
|
||||
LcdFlags attr = (sub==i ? (editMode>0 ? BLINK|INVERS : INVERS) : 0);
|
||||
switch(i) {
|
||||
case MIX_FIELD_NAME:
|
||||
editSingleName(x+MIXES_2ND_COLUMN, y, STR_MIXNAME, md2->name, sizeof(md2->name), event, attr);
|
||||
break;
|
||||
case MIX_FIELD_SOURCE:
|
||||
lcd_putsLeft(y, NO_INDENT(STR_SOURCE));
|
||||
putsMixerSource(x+MIXES_2ND_COLUMN, y, md2->srcRaw, STREXPANDED|attr);
|
||||
if (attr) CHECK_INCDEC_MODELSOURCE(event, md2->srcRaw, 1, MIXSRC_LAST);
|
||||
break;
|
||||
case MIX_FIELD_WEIGHT:
|
||||
lcd_putsColumnLeft(x, y, STR_WEIGHT);
|
||||
gvarWeightItem(x+MIXES_2ND_COLUMN, y, md2, attr|LEFT, event);
|
||||
break;
|
||||
case MIX_FIELD_OFFSET:
|
||||
{
|
||||
lcd_putsColumnLeft(x, y, NO_INDENT(STR_OFFSET));
|
||||
u_int8int16_t offset;
|
||||
MD_OFFSET_TO_UNION(md2, offset);
|
||||
offset.word = GVAR_MENU_ITEM(x+MIXES_2ND_COLUMN, y, offset.word, GV_RANGELARGE_OFFSET_NEG, GV_RANGELARGE_OFFSET, attr|LEFT, 0, event);
|
||||
MD_UNION_TO_OFFSET(offset, md2);
|
||||
#if 0
|
||||
drawOffsetBar(x+MIXES_2ND_COLUMN+22, y, md2);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case MIX_FIELD_TRIM:
|
||||
lcd_putsColumnLeft(x, y, STR_TRIM);
|
||||
lcdDrawCheckBox(x+MIXES_2ND_COLUMN, y, !md2->carryTrim, attr);
|
||||
if (attr) md2->carryTrim = !checkIncDecModel(event, !md2->carryTrim, 0, 1);
|
||||
break;
|
||||
#if defined(CURVES)
|
||||
case MIX_FIELD_CURVE:
|
||||
{
|
||||
lcd_putsColumnLeft(x, y, STR_CURVE);
|
||||
editCurveRef(x+MIXES_2ND_COLUMN, y, md2->curve, event, attr);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#if defined(FLIGHT_MODES)
|
||||
case MIX_FIELD_FLIGHT_PHASE:
|
||||
md2->flightModes = editFlightModes(x+MIXES_2ND_COLUMN, y, event, md2->flightModes, attr);
|
||||
break;
|
||||
#endif
|
||||
case MIX_FIELD_SWITCH:
|
||||
md2->swtch = switchMenuItem(x+MIXES_2ND_COLUMN, y, md2->swtch, attr, event);
|
||||
break;
|
||||
#if 0
|
||||
case MIX_FIELD_WARNING:
|
||||
lcd_putsColumnLeft(x+MIXES_2ND_COLUMN, y, STR_MIXWARNING);
|
||||
if (md2->mixWarn)
|
||||
lcd_outdezAtt(x+MIXES_2ND_COLUMN, y, md2->mixWarn, attr|LEFT);
|
||||
else
|
||||
lcd_putsAtt(x+MIXES_2ND_COLUMN, y, STR_OFF, attr);
|
||||
if (attr) CHECK_INCDEC_MODELVAR_ZERO(event, md2->mixWarn, 3);
|
||||
break;
|
||||
#endif
|
||||
case MIX_FIELD_MLTPX:
|
||||
md2->mltpx = selectMenuItem(x+MIXES_2ND_COLUMN, y, STR_MULTPX, STR_VMLTPX, md2->mltpx, 0, 2, attr, event);
|
||||
break;
|
||||
case MIX_FIELD_DELAY_UP:
|
||||
md2->delayUp = EDIT_DELAY(x, y, event, attr, STR_DELAYUP, md2->delayUp);
|
||||
break;
|
||||
case MIX_FIELD_DELAY_DOWN:
|
||||
md2->delayDown = EDIT_DELAY(x, y, event, attr, STR_DELAYDOWN, md2->delayDown);
|
||||
break;
|
||||
case MIX_FIELD_SLOW_UP:
|
||||
md2->speedUp = EDIT_DELAY(x, y, event, attr, STR_SLOWUP, md2->speedUp);
|
||||
break;
|
||||
case MIX_FIELD_SLOW_DOWN:
|
||||
md2->speedDown = EDIT_DELAY(x, y, event, attr, STR_SLOWDOWN, md2->speedDown);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t s_copySrcIdx;
|
||||
static uint8_t s_copySrcCh;
|
||||
|
||||
#define _STR_MAX(x) PSTR("/" #x)
|
||||
#define STR_MAX(x) _STR_MAX(x)
|
||||
|
||||
#define EXPO_LINE_WEIGHT_POS 89
|
||||
#define EXPO_LINE_SRC_POS 102
|
||||
#define EXPO_LINE_FM_POS 138
|
||||
#define EXPO_LINE_CURVE_POS 138
|
||||
#define EXPO_LINE_SWITCH_POS 182
|
||||
#define EXPO_LINE_SIDE_POS 215
|
||||
#define EXPO_LINE_SELECT_POS 61
|
||||
#define EXPO_LINE_SELECT_WIDTH 244
|
||||
#define EXPO_LINE_NAME_POS 238
|
||||
|
||||
#define MIX_LINE_WEIGHT_POS 69
|
||||
#define MIX_LINE_SRC_POS 83
|
||||
#define MIX_LINE_FM_POS 142
|
||||
#define MIX_LINE_CURVE_POS 142
|
||||
#define MIX_LINE_SWITCH_POS 190
|
||||
#define MIX_LINE_DELAY_POS 225
|
||||
#define MIX_LINE_SELECT_POS 40
|
||||
#define MIX_LINE_SELECT_WIDTH 265
|
||||
|
||||
void lineSurround(bool expo, coord_t y, LcdFlags flags=CURVE_AXIS_COLOR)
|
||||
{
|
||||
lcd_rect(expo ? EXPO_LINE_SELECT_POS : MIX_LINE_SELECT_POS, y-INVERT_VERT_MARGIN, expo ? EXPO_LINE_SELECT_WIDTH : MIX_LINE_SELECT_WIDTH, INVERT_LINE_HEIGHT, WARNING_COLOR|(s_copyMode == COPY_MODE ? SOLID : DOTTED), flags);
|
||||
}
|
||||
|
||||
void onExpoMixMenu(const char *result)
|
||||
{
|
||||
bool expo = (g_menuStack[g_menuStackPtr] == menuModelExposAll);
|
||||
uint8_t chn = (expo ? expoAddress(s_currIdx)->chn+1 : mixAddress(s_currIdx)->destCh+1);
|
||||
|
||||
if (result == STR_EDIT) {
|
||||
pushMenu(expo ? menuModelExpoOne : menuModelMixOne);
|
||||
}
|
||||
else if (result == STR_INSERT_BEFORE || result == STR_INSERT_AFTER) {
|
||||
if (!reachExpoMixCountLimit(expo)) {
|
||||
s_currCh = chn;
|
||||
if (result == STR_INSERT_AFTER) { s_currIdx++; m_posVert++; }
|
||||
insertExpoMix(expo, s_currIdx);
|
||||
pushMenu(expo ? menuModelExpoOne : menuModelMixOne);
|
||||
}
|
||||
}
|
||||
else if (result == STR_COPY || result == STR_MOVE) {
|
||||
s_copyMode = (result == STR_COPY ? COPY_MODE : MOVE_MODE);
|
||||
s_copySrcIdx = s_currIdx;
|
||||
s_copySrcCh = chn;
|
||||
s_copySrcRow = m_posVert;
|
||||
}
|
||||
else if (result == STR_DELETE) {
|
||||
deleteExpoMix(expo, s_currIdx);
|
||||
}
|
||||
}
|
||||
|
||||
void displayHeaderChannelName(uint8_t ch)
|
||||
{
|
||||
uint8_t len = zlen(g_model.limitData[ch-1].name, sizeof(g_model.limitData[ch-1].name));
|
||||
if (len) {
|
||||
lcd_putsnAtt(COLUMN_HEADER_X, MENU_FOOTER_TOP, g_model.limitData[ch-1].name, len, HEADER_COLOR|ZCHAR);
|
||||
}
|
||||
}
|
||||
|
||||
void displayMixInfos(coord_t y, MixData *md)
|
||||
{
|
||||
putsCurveRef(MIX_LINE_CURVE_POS, y, md->curve);
|
||||
|
||||
if (md->swtch) {
|
||||
putsSwitches(MIX_LINE_SWITCH_POS, y, md->swtch);
|
||||
}
|
||||
}
|
||||
|
||||
void displayMixLine(coord_t y, MixData *md)
|
||||
{
|
||||
if (md->name[0])
|
||||
lcd_putsnAtt(EXPO_LINE_NAME_POS, y, md->name, sizeof(md->name), ZCHAR);
|
||||
if (!md->flightModes || ((md->curve.value || md->swtch) && ((get_tmr10ms() / 200) & 1)))
|
||||
displayMixInfos(y, md);
|
||||
else
|
||||
displayFlightModes(MIX_LINE_FM_POS, y, md->flightModes, 0);
|
||||
}
|
||||
|
||||
void displayExpoInfos(coord_t y, ExpoData *ed)
|
||||
{
|
||||
putsCurveRef(EXPO_LINE_CURVE_POS, y, ed->curve);
|
||||
if (ed->swtch) {
|
||||
putsSwitches(EXPO_LINE_SWITCH_POS, y, ed->swtch);
|
||||
}
|
||||
if (ed->mode != 3) {
|
||||
lcd_puts(EXPO_LINE_SIDE_POS, y, ed->mode == 2 ? "\176" : "\177");
|
||||
}
|
||||
}
|
||||
|
||||
void displayExpoLine(coord_t y, ExpoData *ed)
|
||||
{
|
||||
putsMixerSource(EXPO_LINE_SRC_POS, y, ed->srcRaw);
|
||||
|
||||
if (!ed->flightModes || ((ed->curve.value || ed->swtch) && ((get_tmr10ms() / 200) & 1)))
|
||||
displayExpoInfos(y, ed);
|
||||
else
|
||||
displayFlightModes(EXPO_LINE_FM_POS, y, ed->flightModes, 0);
|
||||
|
||||
if (ed->name[0]) {
|
||||
lcd_putsnAtt(EXPO_LINE_NAME_POS, y, ed->name, sizeof(ed->name), ZCHAR);
|
||||
}
|
||||
}
|
||||
|
||||
void menuModelExpoMix(uint8_t expo, evt_t event)
|
||||
{
|
||||
int sub = m_posVert;
|
||||
|
||||
if (s_editMode > 0)
|
||||
s_editMode = 0;
|
||||
|
||||
uint8_t chn = (expo ? expoAddress(s_currIdx)->chn+1 : mixAddress(s_currIdx)->destCh+1);
|
||||
|
||||
switch (event)
|
||||
{
|
||||
case EVT_ENTRY:
|
||||
case EVT_ENTRY_UP:
|
||||
s_copyMode = 0;
|
||||
s_copyTgtOfs = 0;
|
||||
break;
|
||||
case EVT_KEY_LONG(KEY_EXIT):
|
||||
if (s_copyMode && s_copyTgtOfs == 0) {
|
||||
deleteExpoMix(expo, s_currIdx);
|
||||
killEvents(event);
|
||||
event = 0;
|
||||
}
|
||||
// no break
|
||||
case EVT_KEY_BREAK(KEY_EXIT):
|
||||
if (s_copyMode) {
|
||||
if (s_copyTgtOfs) {
|
||||
// cancel the current copy / move operation
|
||||
if (s_copyMode == COPY_MODE) {
|
||||
deleteExpoMix(expo, s_currIdx);
|
||||
}
|
||||
else {
|
||||
do {
|
||||
swapExpoMix(expo, s_currIdx, s_copyTgtOfs > 0);
|
||||
s_copyTgtOfs += (s_copyTgtOfs < 0 ? +1 : -1);
|
||||
} while (s_copyTgtOfs != 0);
|
||||
eeDirty(EE_MODEL);
|
||||
}
|
||||
m_posVert = s_copySrcRow;
|
||||
s_copyTgtOfs = 0;
|
||||
}
|
||||
s_copyMode = 0;
|
||||
event = 0;
|
||||
}
|
||||
break;
|
||||
case EVT_KEY_BREAK(KEY_ENTER):
|
||||
if ((!s_currCh || (s_copyMode && !s_copyTgtOfs)) && !READ_ONLY()) {
|
||||
s_copyMode = (s_copyMode == COPY_MODE ? MOVE_MODE : COPY_MODE);
|
||||
s_copySrcIdx = s_currIdx;
|
||||
s_copySrcCh = chn;
|
||||
s_copySrcRow = sub;
|
||||
break;
|
||||
}
|
||||
// no break
|
||||
|
||||
CASE_EVT_ROTARY_BREAK
|
||||
case EVT_KEY_LONG(KEY_ENTER):
|
||||
killEvents(event);
|
||||
if (s_copyTgtOfs) {
|
||||
s_copyMode = 0;
|
||||
s_copyTgtOfs = 0;
|
||||
}
|
||||
else {
|
||||
if (READ_ONLY()) {
|
||||
if (!s_currCh) {
|
||||
pushMenu(expo ? menuModelExpoOne : menuModelMixOne);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (s_copyMode) s_currCh = 0;
|
||||
if (s_currCh) {
|
||||
if (reachExpoMixCountLimit(expo)) break;
|
||||
insertExpoMix(expo, s_currIdx);
|
||||
pushMenu(expo ? menuModelExpoOne : menuModelMixOne);
|
||||
s_copyMode = 0;
|
||||
}
|
||||
else {
|
||||
event = 0;
|
||||
s_copyMode = 0;
|
||||
MENU_ADD_ITEM(STR_EDIT);
|
||||
MENU_ADD_ITEM(STR_INSERT_BEFORE);
|
||||
MENU_ADD_ITEM(STR_INSERT_AFTER);
|
||||
MENU_ADD_ITEM(STR_COPY);
|
||||
MENU_ADD_ITEM(STR_MOVE);
|
||||
MENU_ADD_ITEM(STR_DELETE);
|
||||
menuHandler = onExpoMixMenu;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case EVT_KEY_LONG(KEY_LEFT):
|
||||
case EVT_KEY_LONG(KEY_RIGHT):
|
||||
if (s_copyMode && !s_copyTgtOfs) {
|
||||
if (reachExpoMixCountLimit(expo)) break;
|
||||
s_currCh = chn;
|
||||
if (event == EVT_KEY_LONG(KEY_RIGHT)) { s_currIdx++; m_posVert++; }
|
||||
insertExpoMix(expo, s_currIdx);
|
||||
pushMenu(expo ? menuModelExpoOne : menuModelMixOne);
|
||||
s_copyMode = 0;
|
||||
killEvents(event);
|
||||
}
|
||||
break;
|
||||
case EVT_KEY_FIRST(KEY_MOVE_UP):
|
||||
case EVT_KEY_REPT(KEY_MOVE_UP):
|
||||
case EVT_KEY_FIRST(KEY_MOVE_DOWN):
|
||||
case EVT_KEY_REPT(KEY_MOVE_DOWN):
|
||||
if (s_copyMode) {
|
||||
uint8_t key = (event & 0x1f);
|
||||
uint8_t next_ofs = ((IS_ROTARY_UP(event) || key==KEY_MOVE_UP) ? s_copyTgtOfs - 1 : s_copyTgtOfs + 1);
|
||||
|
||||
if (s_copyTgtOfs==0 && s_copyMode==COPY_MODE) {
|
||||
// insert a mix on the same channel (just above / just below)
|
||||
if (reachExpoMixCountLimit(expo)) break;
|
||||
copyExpoMix(expo, s_currIdx);
|
||||
if (IS_ROTARY_DOWN(event) || key==KEY_MOVE_DOWN) s_currIdx++;
|
||||
else if (sub-s_pgOfs >= 6) s_pgOfs++;
|
||||
}
|
||||
else if (next_ofs==0 && s_copyMode==COPY_MODE) {
|
||||
// delete the mix
|
||||
deleteExpoMix(expo, s_currIdx);
|
||||
if (IS_ROTARY_UP(event) || key==KEY_MOVE_UP) s_currIdx--;
|
||||
}
|
||||
else {
|
||||
// only swap the mix with its neighbor
|
||||
if (!swapExpoMix(expo, s_currIdx, IS_ROTARY_UP(event) || key==KEY_MOVE_UP)) break;
|
||||
eeDirty(EE_MODEL);
|
||||
}
|
||||
|
||||
s_copyTgtOfs = next_ofs;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
int linesCount = getLinesCount(expo);
|
||||
SIMPLE_MENU(expo ? STR_MENUINPUTS : STR_MIXER, menuTabModel, expo ? e_InputsAll : e_MixAll, linesCount, DEFAULT_SCROLLBAR_X);
|
||||
|
||||
char str[6];
|
||||
sprintf(str, "%d/%d", getExpoMixCount(expo), expo ? MAX_EXPOS : MAX_MIXERS);
|
||||
lcd_putsAtt(60, MENU_FOOTER_TOP, str, HEADER_COLOR);
|
||||
|
||||
sub = m_posVert;
|
||||
s_currCh = 0;
|
||||
int cur = 0;
|
||||
int i = 0;
|
||||
|
||||
for (int ch=1; ch<=(expo ? NUM_INPUTS : NUM_CHNOUT); ch++) {
|
||||
void *pointer = NULL; MixData * &md = (MixData * &)pointer; ExpoData * &ed = (ExpoData * &)pointer;
|
||||
coord_t y = MENU_CONTENT_TOP + (cur-s_pgOfs)*FH;
|
||||
if (expo ? (i<MAX_EXPOS && (ed=expoAddress(i))->chn+1 == ch && EXPO_VALID(ed)) : (i<MAX_MIXERS && (md=mixAddress(i))->srcRaw && md->destCh+1 == ch)) {
|
||||
if (cur-s_pgOfs >= 0 && cur-s_pgOfs < NUM_BODY_LINES) {
|
||||
if (expo) {
|
||||
putsMixerSource(MENU_TITLE_LEFT, y, ch);
|
||||
}
|
||||
else {
|
||||
putsChn(MENU_TITLE_LEFT, y, ch, 0); // show CHx
|
||||
}
|
||||
}
|
||||
uint8_t mixCnt = 0;
|
||||
do {
|
||||
if (s_copyMode) {
|
||||
if (s_copyMode == MOVE_MODE && cur-s_pgOfs >= 0 && cur-s_pgOfs < NUM_BODY_LINES && s_copySrcCh == ch && s_copyTgtOfs != 0 && i == (s_copySrcIdx + (s_copyTgtOfs<0))) {
|
||||
lineSurround(expo, y);
|
||||
cur++; y+=FH;
|
||||
}
|
||||
if (s_currIdx == i) {
|
||||
sub = m_posVert = cur;
|
||||
s_currCh = ch;
|
||||
}
|
||||
}
|
||||
else if (sub == cur) {
|
||||
s_currIdx = i;
|
||||
}
|
||||
if (cur-s_pgOfs >= 0 && cur-s_pgOfs < NUM_BODY_LINES) {
|
||||
LcdFlags attr = ((s_copyMode || sub != cur) ? 0 : INVERS);
|
||||
if (expo) {
|
||||
ed->weight = GVAR_MENU_ITEM(EXPO_LINE_WEIGHT_POS, y, ed->weight, MIN_EXPO_WEIGHT, 100, attr | (isExpoActive(i) ? BOLD : 0), 0, 0);
|
||||
displayExpoLine(y, ed);
|
||||
}
|
||||
else {
|
||||
if (attr) {
|
||||
displayHeaderChannelName(ch);
|
||||
}
|
||||
|
||||
if (mixCnt > 0) lcd_putsiAtt(6, y, STR_VMLTPX2, md->mltpx, 0);
|
||||
|
||||
putsMixerSource(MIX_LINE_SRC_POS, y, md->srcRaw);
|
||||
|
||||
gvarWeightItem(MIX_LINE_WEIGHT_POS, y, md, attr | (isMixActive(i) ? BOLD : 0), event);
|
||||
|
||||
displayMixLine(y, md);
|
||||
|
||||
char cs[] = " ";
|
||||
if (md->speedDown || md->speedUp)
|
||||
cs[0] = 'S';
|
||||
if (md->delayUp || md->delayDown)
|
||||
cs[0] = (cs[0] =='S' ? '*' : 'D');
|
||||
lcd_puts(MIX_LINE_DELAY_POS, y, cs);
|
||||
}
|
||||
if (s_copyMode) {
|
||||
if ((s_copyMode==COPY_MODE || s_copyTgtOfs == 0) && s_copySrcCh == ch && i == (s_copySrcIdx + (s_copyTgtOfs<0))) {
|
||||
/* draw a border around the raw on selection mode (copy/move) */
|
||||
lineSurround(expo, y);
|
||||
}
|
||||
if (cur == sub) {
|
||||
/* invert the raw when it's the current one */
|
||||
lineSurround(expo, y, WARNING_COLOR);
|
||||
}
|
||||
}
|
||||
}
|
||||
cur++; y+=FH; mixCnt++; i++; if (expo) ed++; else md++;
|
||||
} while (expo ? (i<MAX_EXPOS && ed->chn+1 == ch && EXPO_VALID(ed)) : (i<MAX_MIXERS && md->srcRaw && md->destCh+1 == ch));
|
||||
if (s_copyMode == MOVE_MODE && cur-s_pgOfs >= 0 && cur-s_pgOfs < NUM_BODY_LINES && s_copySrcCh == ch && i == (s_copySrcIdx + (s_copyTgtOfs<0))) {
|
||||
lineSurround(expo, y);
|
||||
cur++; y+=FH;
|
||||
}
|
||||
}
|
||||
else {
|
||||
uint8_t attr = 0;
|
||||
if (sub == cur) {
|
||||
s_currIdx = i;
|
||||
s_currCh = ch;
|
||||
if (!s_copyMode) {
|
||||
attr = INVERS;
|
||||
}
|
||||
}
|
||||
if (cur-s_pgOfs >= 0 && cur-s_pgOfs < NUM_BODY_LINES) {
|
||||
if (expo) {
|
||||
putsMixerSource(MENU_TITLE_LEFT, y, ch, attr);
|
||||
}
|
||||
else {
|
||||
putsChn(MENU_TITLE_LEFT, y, ch, attr); // show CHx
|
||||
if (attr) {
|
||||
displayHeaderChannelName(ch);
|
||||
}
|
||||
}
|
||||
if (s_copyMode == MOVE_MODE && s_copySrcCh == ch) {
|
||||
lineSurround(expo, y);
|
||||
}
|
||||
}
|
||||
cur++; y+=FH;
|
||||
}
|
||||
}
|
||||
|
||||
if (sub >= linesCount-1) m_posVert = linesCount-1;
|
||||
}
|
||||
|
||||
void menuModelExposAll(evt_t event)
|
||||
{
|
||||
return menuModelExpoMix(1, event);
|
||||
}
|
||||
|
||||
void menuModelMixAll(evt_t event)
|
||||
{
|
||||
return menuModelExpoMix(0, event);
|
||||
}
|
||||
@@ -0,0 +1,290 @@
|
||||
/*
|
||||
* Authors (alphabetical order)
|
||||
* - Andre Bernet <bernet.andre@gmail.com>
|
||||
* - Andreas Weitl
|
||||
* - Bertrand Songis <bsongis@gmail.com>
|
||||
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
|
||||
* - Cameron Weeks <th9xer@gmail.com>
|
||||
* - Erez Raviv
|
||||
* - Gabriel Birkus
|
||||
* - Jean-Pierre Parisy
|
||||
* - Karl Szmutny
|
||||
* - Michael Blandford
|
||||
* - Michal Hlavinka
|
||||
* - Pat Mackenzie
|
||||
* - Philip Moss
|
||||
* - Rob Thomson
|
||||
* - 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"
|
||||
|
||||
bool isThrottleOutput(uint8_t ch)
|
||||
{
|
||||
for (uint8_t i=0; i<MAX_MIXERS; i++) {
|
||||
MixData *mix = mixAddress(i);
|
||||
if (mix->destCh==ch && mix->srcRaw==MIXSRC_Thr)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
enum LimitsItems {
|
||||
ITEM_LIMITS_CH_NAME,
|
||||
ITEM_LIMITS_OFFSET,
|
||||
ITEM_LIMITS_MIN,
|
||||
ITEM_LIMITS_MAX,
|
||||
ITEM_LIMITS_DIRECTION,
|
||||
#if defined(CURVES)
|
||||
ITEM_LIMITS_CURVE,
|
||||
#endif
|
||||
#if defined(PPM_CENTER_ADJUSTABLE)
|
||||
ITEM_LIMITS_PPM_CENTER,
|
||||
#endif
|
||||
#if defined(PPM_LIMITS_SYMETRICAL)
|
||||
ITEM_LIMITS_SYMETRICAL,
|
||||
#endif
|
||||
ITEM_LIMITS_COUNT,
|
||||
ITEM_LIMITS_MAXROW = ITEM_LIMITS_COUNT-1
|
||||
};
|
||||
|
||||
#if defined(PPM_CENTER_ADJUSTABLE)
|
||||
#define LIMITS_NAME_POS 44
|
||||
#define LIMITS_OFFSET_POS 136
|
||||
#define LIMITS_MIN_POS 175
|
||||
#define LIMITS_DIRECTION_POS 177
|
||||
#define LIMITS_MAX_POS 214
|
||||
#define LIMITS_REVERT_POS 218
|
||||
#define LIMITS_CURVE_POS 232
|
||||
#define LIMITS_PPM_CENTER_POS 292
|
||||
#define LIMITS_SYMETRICAL_POS 298
|
||||
#else
|
||||
#define LIMITS_NAME_POS 44
|
||||
#define LIMITS_OFFSET_POS 136
|
||||
#define LIMITS_MIN_POS 178
|
||||
#define LIMITS_DIRECTION_POS 181
|
||||
#define LIMITS_MAX_POS 218
|
||||
#define LIMITS_REVERT_POS 228
|
||||
#define LIMITS_CURVE_POS 258
|
||||
#define LIMITS_SYMETRICAL_POS 294
|
||||
#endif
|
||||
|
||||
#define LIMITS_MIN_MAX_OFFSET 1000
|
||||
#define CONVERT_US_MIN_MAX(x) (((x)*1280)/250)
|
||||
|
||||
#if defined(PPM_UNIT_US)
|
||||
#define SET_MIN_MAX(x, val) x = ((val)*250)/128
|
||||
#define MIN_MAX_DISPLAY(x) CONVERT_US_MIN_MAX(x)
|
||||
#else
|
||||
#define MIN_MAX_DISPLAY(x) (x)
|
||||
#define SET_MIN_MAX(x, val) x = (val)
|
||||
#endif
|
||||
|
||||
void onLimitsMenu(const char *result)
|
||||
{
|
||||
uint8_t ch = m_posVert - 1;
|
||||
|
||||
if (result == STR_RESET) {
|
||||
LimitData *ld = limitAddress(ch);
|
||||
ld->min = 0;
|
||||
ld->max = 0;
|
||||
ld->offset = 0;
|
||||
ld->ppmCenter = 0;
|
||||
ld->revert = false;
|
||||
ld->curve = 0;
|
||||
}
|
||||
else if (result == STR_COPY_STICKS_TO_OFS) {
|
||||
copySticksToOffset(ch);
|
||||
}
|
||||
else if (result == STR_COPY_TRIMS_TO_OFS) {
|
||||
copyTrimsToOffset(ch);
|
||||
}
|
||||
}
|
||||
|
||||
void menuModelLimits(evt_t event)
|
||||
{
|
||||
MENU(STR_MENULIMITS, menuTabModel, e_Limits, NUM_CHNOUT+1, DEFAULT_SCROLLBAR_X,
|
||||
{ NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW,
|
||||
NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW,
|
||||
NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW,
|
||||
NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW,
|
||||
0 });
|
||||
|
||||
uint32_t sub = m_posVert;
|
||||
|
||||
if (sub < NUM_CHNOUT) {
|
||||
#if defined(PPM_CENTER_ADJUSTABLE) || defined(PPM_UNIT_US)
|
||||
lcd_outdezAtt(100, MENU_FOOTER_TOP, PPM_CH_CENTER(sub)+channelOutputs[sub]/2, HEADER_COLOR, STR_US);
|
||||
#else
|
||||
lcd_outdezAtt(100, MENU_FOOTER_TOP, calcRESXto1000(channelOutputs[sub]), HEADER_COLOR|PREC1);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (sub<NUM_CHNOUT && m_posHorz>=0) {
|
||||
displayColumnHeader(STR_LIMITS_HEADERS, m_posHorz);
|
||||
}
|
||||
|
||||
if (s_warning_result) {
|
||||
s_warning_result = 0;
|
||||
LimitData *ld = limitAddress(sub);
|
||||
ld->revert = !ld->revert;
|
||||
eeDirty(EE_MODEL);
|
||||
}
|
||||
|
||||
for (int i=0; i<NUM_BODY_LINES; i++) {
|
||||
coord_t y = MENU_CONTENT_TOP + i*FH;
|
||||
uint8_t k = i+s_pgOfs;
|
||||
|
||||
if (k==NUM_CHNOUT) {
|
||||
// last line available - add the "copy trim menu" line
|
||||
uint8_t attr = (sub==NUM_CHNOUT) ? INVERS : 0;
|
||||
// TODO CENTER attribute
|
||||
lcd_putsAtt(100, y, STR_TRIMS2OFFSETS, s_noHi ? 0 : attr);
|
||||
if (attr) {
|
||||
s_editMode = 0;
|
||||
if (event==EVT_KEY_LONG(KEY_ENTER)) {
|
||||
s_noHi = NO_HI_LEN;
|
||||
killEvents(event);
|
||||
moveTrimsToOffsets(); // if highlighted and menu pressed - move trims to offsets
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
LimitData *ld = limitAddress(k);
|
||||
|
||||
int16_t v = (ld->revert) ? -LIMIT_OFS(ld) : LIMIT_OFS(ld);
|
||||
char swVal[2] = "-"; // '-', '<', '>'
|
||||
if ((channelOutputs[k] - v) > 50) swVal[0] = (ld->revert ? 127 : 126); // Switch to raw inputs? - remove trim!
|
||||
if ((channelOutputs[k] - v) < -50) swVal[0] = (ld->revert ? 126 : 127);
|
||||
lcd_puts(LIMITS_DIRECTION_POS, y, swVal);
|
||||
|
||||
int limit = (g_model.extendedLimits ? LIMIT_EXT_MAX : 1000);
|
||||
|
||||
putsChn(MENU_TITLE_LEFT, y, k+1, (sub==k && m_posHorz < 0) ? INVERS : 0);
|
||||
if (sub==k && m_posHorz < 0 && event==EVT_KEY_LONG(KEY_ENTER) && !READ_ONLY()) {
|
||||
killEvents(event);
|
||||
MENU_ADD_ITEM(STR_RESET);
|
||||
MENU_ADD_ITEM(STR_COPY_TRIMS_TO_OFS);
|
||||
MENU_ADD_ITEM(STR_COPY_STICKS_TO_OFS);
|
||||
menuHandler = onLimitsMenu;
|
||||
}
|
||||
|
||||
for (uint8_t j=0; j<ITEM_LIMITS_COUNT; j++) {
|
||||
uint8_t attr = ((sub==k && m_posHorz==j) ? ((s_editMode>0) ? BLINK|INVERS : INVERS) : 0);
|
||||
uint8_t active = (attr && s_editMode>0) ;
|
||||
if (active) STICK_SCROLL_DISABLE();
|
||||
switch(j)
|
||||
{
|
||||
case ITEM_LIMITS_CH_NAME:
|
||||
editName(LIMITS_NAME_POS, y, ld->name, sizeof(ld->name), event, attr);
|
||||
break;
|
||||
|
||||
case ITEM_LIMITS_OFFSET:
|
||||
if (GV_IS_GV_VALUE(ld->offset, -1000, 1000) || (attr && event == EVT_KEY_LONG(KEY_ENTER))) {
|
||||
ld->offset = GVAR_MENU_ITEM(LIMITS_OFFSET_POS, y, ld->offset, -1000, 1000, attr|PREC1, 0, event);
|
||||
break;
|
||||
}
|
||||
|
||||
#if defined(PPM_UNIT_US)
|
||||
lcd_outdezAtt(LIMITS_OFFSET_POS, y, ((int32_t)ld->offset*128) / 25, attr|PREC1);
|
||||
#else
|
||||
lcd_outdezAtt(LIMITS_OFFSET_POS, y, ld->offset, attr|PREC1);
|
||||
#endif
|
||||
if (active) {
|
||||
ld->offset = checkIncDec(event, ld->offset, -1000, 1000, EE_MODEL, NULL, stops1000);
|
||||
}
|
||||
else if (attr && event==EVT_KEY_LONG(KEY_MENU)) {
|
||||
copySticksToOffset(k);
|
||||
s_editMode = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case ITEM_LIMITS_MIN:
|
||||
if (GV_IS_GV_VALUE(ld->min, -GV_RANGELARGE, GV_RANGELARGE) || (attr && event == EVT_KEY_LONG(KEY_ENTER))) {
|
||||
ld->min = GVAR_MENU_ITEM(LIMITS_MIN_POS, y, ld->min, -LIMIT_EXT_MAX, LIMIT_EXT_MAX, attr|PREC1, 0, event);
|
||||
break;
|
||||
}
|
||||
lcd_outdezAtt(LIMITS_MIN_POS, y, MIN_MAX_DISPLAY(ld->min-LIMITS_MIN_MAX_OFFSET), attr|PREC1);
|
||||
if (active) ld->min = LIMITS_MIN_MAX_OFFSET + checkIncDec(event, ld->min-LIMITS_MIN_MAX_OFFSET, -limit, 0, EE_MODEL, NULL, stops1000);
|
||||
break;
|
||||
|
||||
case ITEM_LIMITS_MAX:
|
||||
if (GV_IS_GV_VALUE(ld->max, -GV_RANGELARGE, GV_RANGELARGE) || (attr && event == EVT_KEY_LONG(KEY_ENTER))) {
|
||||
ld->max = GVAR_MENU_ITEM(LIMITS_MAX_POS, y, ld->max, -LIMIT_EXT_MAX, LIMIT_EXT_MAX, attr|PREC1, 0, event);
|
||||
break;
|
||||
}
|
||||
lcd_outdezAtt(LIMITS_MAX_POS, y, MIN_MAX_DISPLAY(ld->max+LIMITS_MIN_MAX_OFFSET), attr|PREC1);
|
||||
if (active) ld->max = -LIMITS_MIN_MAX_OFFSET + checkIncDec(event, ld->max+LIMITS_MIN_MAX_OFFSET, 0, +limit, EE_MODEL, NULL, stops1000);
|
||||
break;
|
||||
|
||||
case ITEM_LIMITS_DIRECTION:
|
||||
{
|
||||
uint8_t revert = ld->revert;
|
||||
#if defined(PPM_CENTER_ADJUSTABLE)
|
||||
lcd_putsAtt(LIMITS_REVERT_POS, y, revert ? "\177" : "\176", attr);
|
||||
#else
|
||||
lcd_putsiAtt(LIMITS_REVERT_POS, y, STR_MMMINV, revert, attr);
|
||||
#endif
|
||||
if (active) {
|
||||
uint8_t revert_new = checkIncDecModel(event, revert, 0, 1);
|
||||
if (checkIncDec_Ret && isThrottleOutput(k)) {
|
||||
POPUP_CONFIRMATION(STR_INVERT_THR);
|
||||
}
|
||||
else {
|
||||
ld->revert = revert_new;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
#if defined(CURVES)
|
||||
case ITEM_LIMITS_CURVE:
|
||||
putsCurve(LIMITS_CURVE_POS, y, ld->curve, attr);
|
||||
if (attr && event==EVT_KEY_LONG(KEY_ENTER) && ld->curve>0) {
|
||||
s_curveChan = (ld->curve<0 ? -ld->curve-1 : ld->curve-1);
|
||||
pushMenu(menuModelCurveOne);
|
||||
}
|
||||
if (active) {
|
||||
CHECK_INCDEC_MODELVAR(event, ld->curve, -MAX_CURVES, +MAX_CURVES);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if defined(PPM_CENTER_ADJUSTABLE)
|
||||
case ITEM_LIMITS_PPM_CENTER:
|
||||
lcd_outdezAtt(LIMITS_PPM_CENTER_POS, y, PPM_CENTER+ld->ppmCenter, attr);
|
||||
if (active) {
|
||||
CHECK_INCDEC_MODELVAR(event, ld->ppmCenter, -PPM_CENTER_MAX, +PPM_CENTER_MAX);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if defined(PPM_LIMITS_SYMETRICAL)
|
||||
case ITEM_LIMITS_SYMETRICAL:
|
||||
lcd_putsAtt(LIMITS_SYMETRICAL_POS, y, ld->symetrical ? "=" : "\306", attr);
|
||||
if (active) {
|
||||
CHECK_INCDEC_MODELVAR_ZERO(event, ld->symetrical, 1);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,275 @@
|
||||
/*
|
||||
* Authors (alphabetical order)
|
||||
* - Andre Bernet <bernet.andre@gmail.com>
|
||||
* - Andreas Weitl
|
||||
* - Bertrand Songis <bsongis@gmail.com>
|
||||
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
|
||||
* - Cameron Weeks <th9xer@gmail.com>
|
||||
* - Erez Raviv
|
||||
* - Gabriel Birkus
|
||||
* - Jean-Pierre Parisy
|
||||
* - Karl Szmutny
|
||||
* - Michael Blandford
|
||||
* - Michal Hlavinka
|
||||
* - Pat Mackenzie
|
||||
* - Philip Moss
|
||||
* - Rob Thomson
|
||||
* - 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 LogicalSwitchFields {
|
||||
LS_FIELD_FUNCTION,
|
||||
LS_FIELD_V1,
|
||||
LS_FIELD_V2,
|
||||
LS_FIELD_V3,
|
||||
LS_FIELD_ANDSW,
|
||||
LS_FIELD_DURATION,
|
||||
LS_FIELD_DELAY,
|
||||
LS_FIELD_COUNT,
|
||||
LS_FIELD_LAST = LS_FIELD_COUNT-1
|
||||
};
|
||||
|
||||
#define CSW_1ST_COLUMN 40
|
||||
#define CSW_2ND_COLUMN 85
|
||||
#define CSW_3RD_COLUMN 130
|
||||
#define CSW_4TH_COLUMN 185
|
||||
#define CSW_5TH_COLUMN 225
|
||||
#define CSW_6TH_COLUMN 270
|
||||
|
||||
#define INCDEC_DECLARE_VARS(f) uint8_t incdecFlag = (f); IsValueAvailable isValueAvailable = NULL
|
||||
#define INCDEC_SET_FLAG(f) incdecFlag = (f)
|
||||
#define INCDEC_ENABLE_CHECK(fn) isValueAvailable = fn
|
||||
#define CHECK_INCDEC_PARAM(event, var, min, max) checkIncDec(event, var, min, max, incdecFlag, isValueAvailable)
|
||||
|
||||
void putsEdgeDelayParam(coord_t x, coord_t y, LogicalSwitchData *cs, uint8_t lattr, uint8_t rattr)
|
||||
{
|
||||
char s[32];
|
||||
div_t left = div(lswTimerValue(cs->v2), 10);
|
||||
char sleft[10];
|
||||
sprintf(sleft, "%d.%d", left.quot, left.rem);
|
||||
div_t right = div(lswTimerValue(cs->v2+cs->v3), 10);
|
||||
char sright[10];
|
||||
sprintf(sright, "%d.%d", right.quot, right.rem);
|
||||
sprintf(s, "[%s:%s]", sleft, sright);
|
||||
lcd_puts(x-4, y, s);
|
||||
/* if (cs->v3 < 0)
|
||||
lcd_putsAtt(lcdLastPos+3, y, "<<", rattr);
|
||||
else if (cs->v3 == 0)
|
||||
lcd_putsAtt(lcdLastPos+3, y, "--", rattr); */
|
||||
}
|
||||
|
||||
void onLogicalSwitchesMenu(const char *result)
|
||||
{
|
||||
int8_t sub = m_posVert;
|
||||
LogicalSwitchData * cs = lswAddress(sub);
|
||||
|
||||
if (result == STR_COPY) {
|
||||
clipboard.type = CLIPBOARD_TYPE_CUSTOM_SWITCH;
|
||||
clipboard.data.csw = *cs;
|
||||
}
|
||||
else if (result == STR_PASTE) {
|
||||
*cs = clipboard.data.csw;
|
||||
eeDirty(EE_MODEL);
|
||||
}
|
||||
else if (result == STR_CLEAR) {
|
||||
memset(cs, 0, sizeof(LogicalSwitchData));
|
||||
eeDirty(EE_MODEL);
|
||||
}
|
||||
}
|
||||
|
||||
void menuModelLogicalSwitches(evt_t event)
|
||||
{
|
||||
INCDEC_DECLARE_VARS(EE_MODEL);
|
||||
|
||||
MENU(STR_MENULOGICALSWITCHES, menuTabModel, e_LogicalSwitches, NUM_LOGICAL_SWITCH, DEFAULT_SCROLLBAR_X, { NAVIGATION_LINE_BY_LINE|LS_FIELD_LAST/*repeated...*/} );
|
||||
|
||||
int k = 0;
|
||||
int sub = m_posVert;
|
||||
horzpos_t horz = m_posHorz;
|
||||
|
||||
if (horz>=0) {
|
||||
displayColumnHeader(STR_CSW_HEADERS, horz);
|
||||
}
|
||||
|
||||
if (horz<0 && event==EVT_KEY_LONG(KEY_ENTER) && !READ_ONLY()) {
|
||||
killEvents(event);
|
||||
LogicalSwitchData * cs = lswAddress(sub);
|
||||
if (cs->func)
|
||||
MENU_ADD_ITEM(STR_COPY);
|
||||
if (clipboard.type == CLIPBOARD_TYPE_CUSTOM_SWITCH)
|
||||
MENU_ADD_ITEM(STR_PASTE);
|
||||
if (cs->func || cs->v1 || cs->v2 || cs->delay || cs->duration || cs->andsw)
|
||||
MENU_ADD_ITEM(STR_CLEAR);
|
||||
menuHandler = onLogicalSwitchesMenu;
|
||||
}
|
||||
|
||||
for (int i=0; i<NUM_BODY_LINES; ++i) {
|
||||
coord_t y = MENU_CONTENT_TOP + i*FH;
|
||||
k = i+s_pgOfs;
|
||||
LcdFlags attr = (sub==k ? ((s_editMode>0) ? BLINK|INVERS : INVERS) : 0);
|
||||
LcdFlags attr1 = (horz==1 ? attr : 0);
|
||||
LcdFlags attr2 = (horz==2 ? attr : 0);
|
||||
LogicalSwitchData * cs = lswAddress(k);
|
||||
|
||||
// CSW name
|
||||
unsigned int sw = SWSRC_SW1+k;
|
||||
putsSwitches(MENU_TITLE_LEFT, y, sw, (getSwitch(sw) ? 0/*BOLD*/ : 0) | ((sub==k && CURSOR_ON_LINE()) ? INVERS : 0));
|
||||
|
||||
// CSW func
|
||||
lcd_putsiAtt(CSW_1ST_COLUMN, y, STR_VCSWFUNC, cs->func, horz==0 ? attr : 0);
|
||||
|
||||
// CSW params
|
||||
unsigned int cstate = lswFamily(cs->func);
|
||||
int v1_val=cs->v1, v1_min=0, v1_max=MIXSRC_LAST_TELEM;
|
||||
int v2_min=0, v2_max=MIXSRC_LAST_TELEM;
|
||||
int v3_min=-1, v3_max=100;
|
||||
|
||||
if (cstate == LS_FAMILY_BOOL || cstate == LS_FAMILY_STICKY) {
|
||||
putsSwitches(CSW_2ND_COLUMN, y, cs->v1, attr1);
|
||||
putsSwitches(CSW_3RD_COLUMN, y, cs->v2, attr2);
|
||||
v1_min = SWSRC_FIRST_IN_LOGICAL_SWITCHES; v1_max = SWSRC_LAST_IN_LOGICAL_SWITCHES;
|
||||
v2_min = SWSRC_FIRST_IN_LOGICAL_SWITCHES; v2_max = SWSRC_LAST_IN_LOGICAL_SWITCHES;
|
||||
INCDEC_SET_FLAG(EE_MODEL | INCDEC_SWITCH);
|
||||
INCDEC_ENABLE_CHECK(isSwitchAvailableInLogicalSwitches);
|
||||
}
|
||||
else if (cstate == LS_FAMILY_EDGE) {
|
||||
putsSwitches(CSW_2ND_COLUMN, y, cs->v1, attr1);
|
||||
putsEdgeDelayParam(CSW_3RD_COLUMN, y, cs, attr2, (horz==LS_FIELD_V3 ? attr : 0));
|
||||
v1_min = SWSRC_FIRST_IN_LOGICAL_SWITCHES; v1_max = SWSRC_LAST_IN_LOGICAL_SWITCHES;
|
||||
v2_min=-129; v2_max = 122;
|
||||
v3_max = 222 - cs->v2;
|
||||
if (horz == 1) {
|
||||
INCDEC_SET_FLAG(EE_MODEL | INCDEC_SWITCH);
|
||||
INCDEC_ENABLE_CHECK(isSwitchAvailableInLogicalSwitches);
|
||||
}
|
||||
else {
|
||||
INCDEC_SET_FLAG(EE_MODEL);
|
||||
INCDEC_ENABLE_CHECK(NULL);
|
||||
}
|
||||
}
|
||||
else if (cstate == LS_FAMILY_COMP) {
|
||||
v1_val = (uint8_t)cs->v1;
|
||||
putsMixerSource(CSW_2ND_COLUMN, y, v1_val, attr1);
|
||||
putsMixerSource(CSW_3RD_COLUMN, y, cs->v2, attr2);
|
||||
INCDEC_SET_FLAG(EE_MODEL | INCDEC_SOURCE);
|
||||
INCDEC_ENABLE_CHECK(isSourceAvailable);
|
||||
}
|
||||
else if (cstate == LS_FAMILY_TIMER) {
|
||||
lcd_outdezAtt(CSW_2ND_COLUMN, y, lswTimerValue(cs->v1), LEFT|PREC1|attr1);
|
||||
lcd_outdezAtt(CSW_3RD_COLUMN, y, lswTimerValue(cs->v2), LEFT|PREC1|attr2);
|
||||
v1_min = v2_min = -128;
|
||||
v1_max = v2_max = 122;
|
||||
INCDEC_SET_FLAG(EE_MODEL);
|
||||
INCDEC_ENABLE_CHECK(NULL);
|
||||
}
|
||||
else {
|
||||
v1_val = (uint8_t)cs->v1;
|
||||
putsMixerSource(CSW_2ND_COLUMN, y, v1_val, attr1);
|
||||
if (horz == 1) {
|
||||
INCDEC_SET_FLAG(EE_MODEL | INCDEC_SOURCE);
|
||||
INCDEC_ENABLE_CHECK(isSourceAvailableInCustomSwitches);
|
||||
}
|
||||
else {
|
||||
INCDEC_SET_FLAG(EE_MODEL);
|
||||
INCDEC_ENABLE_CHECK(NULL);
|
||||
}
|
||||
v2_max = getMaximumValue(v1_val);
|
||||
v2_min = - v2_min;
|
||||
putsChannelValue(CSW_3RD_COLUMN, y, v1_val, v1_val <= MIXSRC_LAST_CH ? calc100toRESX(cs->v2) : cs->v2, LEFT|attr2);
|
||||
}
|
||||
|
||||
// CSW AND switch
|
||||
putsSwitches(CSW_4TH_COLUMN, y, cs->andsw, horz==LS_FIELD_ANDSW ? attr : 0);
|
||||
|
||||
// CSW duration
|
||||
if (cs->duration > 0)
|
||||
lcd_outdezAtt(CSW_5TH_COLUMN, y, cs->duration, (horz==LS_FIELD_DURATION ? attr : 0)|PREC1|LEFT);
|
||||
else
|
||||
lcd_putsiAtt(CSW_5TH_COLUMN, y, STR_MMMINV, 0, horz==LS_FIELD_DURATION ? attr : 0);
|
||||
|
||||
// CSW delay
|
||||
if (cstate == LS_FAMILY_EDGE) {
|
||||
lcd_puts(CSW_6TH_COLUMN, y, STR_NA);
|
||||
if (attr && horz == LS_FIELD_DELAY) {
|
||||
REPEAT_LAST_CURSOR_MOVE();
|
||||
}
|
||||
}
|
||||
else if (cs->delay > 0) {
|
||||
lcd_outdezAtt(CSW_6TH_COLUMN, y, cs->delay, (horz==LS_FIELD_DELAY ? attr : 0)|PREC1|LEFT);
|
||||
}
|
||||
else {
|
||||
lcd_putsiAtt(CSW_6TH_COLUMN, y, STR_MMMINV, 0, horz==LS_FIELD_DELAY ? attr : 0);
|
||||
}
|
||||
|
||||
if (attr && horz == LS_FIELD_V3 && cstate != LS_FAMILY_EDGE) {
|
||||
REPEAT_LAST_CURSOR_MOVE();
|
||||
}
|
||||
|
||||
if (s_editMode>0 && attr) {
|
||||
switch (horz) {
|
||||
case LS_FIELD_FUNCTION:
|
||||
{
|
||||
cs->func = checkIncDec(event, cs->func, 0, LS_FUNC_MAX, EE_MODEL, isLogicalSwitchFunctionAvailable);
|
||||
uint8_t new_cstate = lswFamily(cs->func);
|
||||
if (cstate != new_cstate) {
|
||||
if (new_cstate == LS_FAMILY_TIMER) {
|
||||
cs->v1 = cs->v2 = -119;
|
||||
}
|
||||
else if (new_cstate == LS_FAMILY_EDGE) {
|
||||
cs->v1 = 0; cs->v2 = -129; cs->v3 = 0;
|
||||
}
|
||||
else {
|
||||
cs->v1 = cs->v2 = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case LS_FIELD_V1:
|
||||
cs->v1 = CHECK_INCDEC_PARAM(event, v1_val, v1_min, v1_max);
|
||||
break;
|
||||
case LS_FIELD_V2:
|
||||
cs->v2 = CHECK_INCDEC_PARAM(event, cs->v2, v2_min, v2_max);
|
||||
if (cstate==LS_FAMILY_OFS && cs->v1!=0 && event==EVT_KEY_LONG(KEY_ENTER)) {
|
||||
killEvents(event);
|
||||
getvalue_t x = getValue(v1_val);
|
||||
if (v1_val <= MIXSRC_LAST_CH)
|
||||
cs->v2 = calcRESXto100(x);
|
||||
eeDirty(EE_MODEL);
|
||||
}
|
||||
break;
|
||||
case LS_FIELD_V3:
|
||||
cs->v3 = CHECK_INCDEC_PARAM(event, cs->v3, v3_min, v3_max);
|
||||
break;
|
||||
case LS_FIELD_ANDSW:
|
||||
INCDEC_SET_FLAG(EE_MODEL | INCDEC_SWITCH);
|
||||
INCDEC_ENABLE_CHECK(isSwitchAvailableInLogicalSwitches);
|
||||
cs->andsw = CHECK_INCDEC_PARAM(event, cs->andsw, -MAX_LS_ANDSW, MAX_LS_ANDSW);
|
||||
break;
|
||||
case LS_FIELD_DURATION:
|
||||
CHECK_INCDEC_MODELVAR_ZERO(event, cs->duration, MAX_LS_DURATION);
|
||||
break;
|
||||
case LS_FIELD_DELAY:
|
||||
CHECK_INCDEC_MODELVAR_ZERO(event, cs->delay, MAX_LS_DELAY);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,293 @@
|
||||
/*
|
||||
* Authors (alphabetical order)
|
||||
* - Andre Bernet <bernet.andre@gmail.com>
|
||||
* - Andreas Weitl
|
||||
* - Bertrand Songis <bsongis@gmail.com>
|
||||
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
|
||||
* - Cameron Weeks <th9xer@gmail.com>
|
||||
* - Erez Raviv
|
||||
* - Gabriel Birkus
|
||||
* - Jean-Pierre Parisy
|
||||
* - Karl Szmutny
|
||||
* - Michael Blandford
|
||||
* - Michal Hlavinka
|
||||
* - Pat Mackenzie
|
||||
* - Philip Moss
|
||||
* - Rob Thomson
|
||||
* - 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 POS_MODEL_NAME 35
|
||||
#define POS_MODEL_SIZE 170
|
||||
|
||||
void onModelSelectMenu(const char *result)
|
||||
{
|
||||
int sub = m_posVert;
|
||||
|
||||
if (result == STR_SELECT_MODEL || result == STR_CREATE_MODEL) {
|
||||
selectModel(sub);
|
||||
}
|
||||
else if (result == STR_COPY_MODEL) {
|
||||
s_copyMode = COPY_MODE;
|
||||
s_copyTgtOfs = 0;
|
||||
s_copySrcRow = -1;
|
||||
}
|
||||
else if (result == STR_MOVE_MODEL) {
|
||||
s_copyMode = MOVE_MODE;
|
||||
s_copyTgtOfs = 0;
|
||||
s_copySrcRow = -1;
|
||||
}
|
||||
else if (result == STR_BACKUP_MODEL) {
|
||||
eeCheck(true); // force writing of current model data before this is changed
|
||||
POPUP_WARNING(eeBackupModel(sub));
|
||||
}
|
||||
else if (result == STR_RESTORE_MODEL || result == STR_UPDATE_LIST) {
|
||||
if (!listSdFiles(MODELS_PATH, MODELS_EXT, MENU_LINE_LENGTH-1, NULL)) {
|
||||
POPUP_WARNING(STR_NO_MODELS_ON_SD);
|
||||
s_menu_flags = 0;
|
||||
}
|
||||
}
|
||||
else if (result == STR_DELETE_MODEL) {
|
||||
POPUP_CONFIRMATION(STR_DELETEMODEL);
|
||||
SET_WARNING_INFO(modelHeaders[sub].name, sizeof(g_model.header.name), ZCHAR);
|
||||
}
|
||||
else {
|
||||
// The user choosed a file on SD to restore
|
||||
POPUP_WARNING(eeRestoreModel(sub, (char *)result));
|
||||
if (!s_warning && g_eeGeneral.currModel == sub)
|
||||
eeLoadModel(sub);
|
||||
}
|
||||
}
|
||||
|
||||
char *strAppendModelSize(char *dest, int size)
|
||||
{
|
||||
char s[8] = "---";
|
||||
if (size) sprintf(s, "%d", size);
|
||||
dest = strSetCursor(dest, POS_MODEL_SIZE-getTextWidth(s));
|
||||
return strAppend(dest, s);
|
||||
}
|
||||
|
||||
void menuModelSelect(evt_t event)
|
||||
{
|
||||
if (s_warning_result) {
|
||||
s_warning_result = 0;
|
||||
eeDeleteModel(m_posVert); // delete file
|
||||
s_copyMode = 0;
|
||||
event = EVT_ENTRY_UP;
|
||||
}
|
||||
|
||||
evt_t _event_ = event;
|
||||
event = (IS_ROTARY_BREAK(event) || IS_ROTARY_LONG(event) ? 0 : event);
|
||||
if ((s_copyMode && EVT_KEY_MASK(event) == KEY_EXIT) || event == EVT_KEY_BREAK(KEY_EXIT)) {
|
||||
event = 0;
|
||||
}
|
||||
|
||||
int8_t oldSub = m_posVert;
|
||||
|
||||
// TODO SIMPLE_MENU(STR_MENUMODELSEL, menuTabModel, e_ModelSelect, MAX_MODELS, DEFAULT_SCROLLBAR_X);
|
||||
|
||||
if (s_editMode > 0) s_editMode = 0;
|
||||
|
||||
int8_t sub = m_posVert;
|
||||
|
||||
switch (_event_)
|
||||
{
|
||||
case EVT_ENTRY:
|
||||
m_posVert = sub = g_eeGeneral.currModel;
|
||||
if (sub >= NUM_BODY_LINES) s_pgOfs = sub-(NUM_BODY_LINES-1);
|
||||
s_copyMode = 0;
|
||||
s_editMode = EDIT_MODE_INIT;
|
||||
eeCheck(true);
|
||||
break;
|
||||
case EVT_KEY_LONG(KEY_EXIT):
|
||||
if (s_copyMode && s_copyTgtOfs == 0 && g_eeGeneral.currModel != sub && eeModelExists(sub)) {
|
||||
POPUP_CONFIRMATION(STR_DELETEMODEL);
|
||||
SET_WARNING_INFO(modelHeaders[sub].name, sizeof(g_model.header.name), ZCHAR);
|
||||
killEvents(_event_);
|
||||
break;
|
||||
}
|
||||
// no break
|
||||
case EVT_KEY_BREAK(KEY_EXIT):
|
||||
if (s_copyMode) {
|
||||
sub = m_posVert = (s_copyMode == MOVE_MODE || s_copySrcRow<0) ? (MAX_MODELS+sub+s_copyTgtOfs) % MAX_MODELS : s_copySrcRow;
|
||||
s_copyMode = 0;
|
||||
}
|
||||
else {
|
||||
if (m_posVert != g_eeGeneral.currModel) {
|
||||
m_posVert = g_eeGeneral.currModel;
|
||||
s_pgOfs = 0;
|
||||
}
|
||||
else if (_event_ != EVT_KEY_LONG(KEY_EXIT)) {
|
||||
popMenu();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case EVT_KEY_LONG(KEY_ENTER):
|
||||
case EVT_KEY_BREAK(KEY_ENTER):
|
||||
s_editMode = 0;
|
||||
if (READ_ONLY()) {
|
||||
if (g_eeGeneral.currModel != sub && eeModelExists(sub)) {
|
||||
selectModel(sub);
|
||||
}
|
||||
}
|
||||
else if (s_copyMode && (s_copyTgtOfs || s_copySrcRow>=0)) {
|
||||
eeCheck(true); // force writing of current model data before this is changed
|
||||
uint8_t cur = (MAX_MODELS + sub + s_copyTgtOfs) % MAX_MODELS;
|
||||
if (s_copyMode == COPY_MODE) {
|
||||
if (!eeCopyModel(cur, s_copySrcRow)) {
|
||||
cur = sub;
|
||||
}
|
||||
}
|
||||
|
||||
s_copySrcRow = g_eeGeneral.currModel; // to update the currModel value
|
||||
while (sub != cur) {
|
||||
uint8_t src = cur;
|
||||
cur = (s_copyTgtOfs > 0 ? cur+MAX_MODELS-1 : cur+1) % MAX_MODELS;
|
||||
eeSwapModels(src, cur);
|
||||
if (src == s_copySrcRow)
|
||||
s_copySrcRow = cur;
|
||||
else if (cur == s_copySrcRow)
|
||||
s_copySrcRow = src;
|
||||
}
|
||||
|
||||
if (s_copySrcRow != g_eeGeneral.currModel) {
|
||||
g_eeGeneral.currModel = s_copySrcRow;
|
||||
eeDirty(EE_GENERAL);
|
||||
}
|
||||
|
||||
s_copyMode = 0;
|
||||
_event_ = EVT_ENTRY_UP;
|
||||
}
|
||||
else if (_event_ == EVT_KEY_LONG(KEY_ENTER)) {
|
||||
s_copyMode = 0;
|
||||
killEvents(_event_);
|
||||
if (g_eeGeneral.currModel != sub) {
|
||||
if (eeModelExists(sub)) {
|
||||
MENU_ADD_ITEM(STR_SELECT_MODEL);
|
||||
MENU_ADD_SD_ITEM(STR_BACKUP_MODEL);
|
||||
MENU_ADD_ITEM(STR_COPY_MODEL);
|
||||
MENU_ADD_ITEM(STR_MOVE_MODEL);
|
||||
MENU_ADD_ITEM(STR_DELETE_MODEL);
|
||||
}
|
||||
else {
|
||||
MENU_ADD_ITEM(STR_CREATE_MODEL);
|
||||
MENU_ADD_ITEM(STR_RESTORE_MODEL);
|
||||
}
|
||||
}
|
||||
else {
|
||||
MENU_ADD_SD_ITEM(STR_BACKUP_MODEL);
|
||||
MENU_ADD_ITEM(STR_COPY_MODEL);
|
||||
MENU_ADD_ITEM(STR_MOVE_MODEL);
|
||||
}
|
||||
menuHandler = onModelSelectMenu;
|
||||
}
|
||||
else if (eeModelExists(sub)) {
|
||||
s_copyMode = (s_copyMode == COPY_MODE ? MOVE_MODE : COPY_MODE);
|
||||
s_copyTgtOfs = 0;
|
||||
s_copySrcRow = -1;
|
||||
}
|
||||
break;
|
||||
|
||||
#if 0
|
||||
case EVT_KEY_BREAK(KEY_PAGE):
|
||||
case EVT_KEY_LONG(KEY_PAGE):
|
||||
chainMenu(_event_ == EVT_KEY_BREAK(KEY_PAGE) ? menuModelSetup : menuTabModel[DIM(menuTabModel)-1]);
|
||||
killEvents(_event_);
|
||||
break;
|
||||
#endif
|
||||
|
||||
case EVT_KEY_FIRST(KEY_MOVE_UP):
|
||||
case EVT_KEY_REPT(KEY_MOVE_UP):
|
||||
case EVT_KEY_FIRST(KEY_MOVE_DOWN):
|
||||
case EVT_KEY_REPT(KEY_MOVE_DOWN):
|
||||
if (s_copyMode) {
|
||||
int8_t next_ofs = s_copyTgtOfs + oldSub - m_posVert;
|
||||
if (next_ofs == MAX_MODELS || next_ofs == -MAX_MODELS)
|
||||
next_ofs = 0;
|
||||
|
||||
if (s_copySrcRow < 0 && s_copyMode==COPY_MODE) {
|
||||
s_copySrcRow = oldSub;
|
||||
// find a hole (in the first empty slot above / below)
|
||||
sub = eeFindEmptyModel(s_copySrcRow, IS_ROTARY_DOWN(_event_) || _event_==EVT_KEY_FIRST(KEY_MOVE_DOWN));
|
||||
if (sub < 0) {
|
||||
// no free room for duplicating the model
|
||||
AUDIO_ERROR();
|
||||
sub = oldSub;
|
||||
s_copyMode = 0;
|
||||
}
|
||||
next_ofs = 0;
|
||||
m_posVert = sub;
|
||||
}
|
||||
s_copyTgtOfs = next_ofs;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
for (int i=0; i<NUM_BODY_LINES; i++) {
|
||||
coord_t y = MENU_CONTENT_TOP + i*FH;
|
||||
int k = i+s_pgOfs;
|
||||
|
||||
LcdFlags flags = 0;
|
||||
if (sub==k && s_copyMode == 0) {
|
||||
flags |= TEXT_INVERTED_COLOR;
|
||||
lcdDrawFilledRect(MENU_TITLE_LEFT-INVERT_HORZ_MARGIN, y-INVERT_VERT_MARGIN, 150, INVERT_LINE_HEIGHT, TEXT_INVERTED_BGCOLOR);
|
||||
}
|
||||
|
||||
char str[20];
|
||||
strAppendDigits(str, k+1);
|
||||
lcd_putsAtt(MENU_TITLE_LEFT, y, str, flags);
|
||||
|
||||
if (s_copyMode == MOVE_MODE || (s_copyMode == COPY_MODE && s_copySrcRow >= 0)) {
|
||||
if (k == sub) {
|
||||
if (s_copyMode == COPY_MODE) {
|
||||
k = s_copySrcRow;
|
||||
// lcd_rect(MENU_TITLE_LEFT-5, y-3, 170, 16, SOLID, YELLOW);
|
||||
}
|
||||
else {
|
||||
k = sub + s_copyTgtOfs;
|
||||
}
|
||||
}
|
||||
else if (s_copyTgtOfs < 0 && ((k < sub && k >= sub+s_copyTgtOfs) || (k-MAX_MODELS < sub && k-MAX_MODELS >= sub+s_copyTgtOfs)))
|
||||
k += 1;
|
||||
else if (s_copyTgtOfs > 0 && ((k > sub && k <= sub+s_copyTgtOfs) || (k+MAX_MODELS > sub && k+MAX_MODELS <= sub+s_copyTgtOfs)))
|
||||
k += MAX_MODELS-1;
|
||||
}
|
||||
|
||||
k %= MAX_MODELS;
|
||||
|
||||
if (eeModelExists(k)) {
|
||||
strcat_modelname(str, k);
|
||||
lcd_putsAtt(POS_MODEL_NAME, y, str, flags);
|
||||
if (k==g_eeGeneral.currModel && (s_copyMode!=COPY_MODE || s_copySrcRow<0 || i+s_pgOfs!=(vertpos_t)sub)) {
|
||||
lcd_puts(1, y, "*");
|
||||
}
|
||||
}
|
||||
else {
|
||||
lcd_putsAtt(POS_MODEL_NAME, y, "---", flags);
|
||||
}
|
||||
|
||||
if (s_copyMode && (vertpos_t)sub==i+s_pgOfs) {
|
||||
lcd_rect(MENU_TITLE_LEFT-INVERT_HORZ_MARGIN, y-INVERT_VERT_MARGIN, 150, INVERT_LINE_HEIGHT, s_copyMode == COPY_MODE ? SOLID : DOTTED, WARNING_COLOR);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO lcdDrawBitmap(200, 67, logos, 60*g_model.header.bitmap, 60);
|
||||
}
|
||||
@@ -0,0 +1,741 @@
|
||||
/*
|
||||
* Authors (alphabetical order)
|
||||
* - Andre Bernet <bernet.andre@gmail.com>
|
||||
* - Andreas Weitl
|
||||
* - Bertrand Songis <bsongis@gmail.com>
|
||||
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
|
||||
* - Cameron Weeks <th9xer@gmail.com>
|
||||
* - Erez Raviv
|
||||
* - Gabriel Birkus
|
||||
* - Jean-Pierre Parisy
|
||||
* - Karl Szmutny
|
||||
* - Michael Blandford
|
||||
* - Michal Hlavinka
|
||||
* - Pat Mackenzie
|
||||
* - Philip Moss
|
||||
* - Rob Thomson
|
||||
* - 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 g_moduleIdx;
|
||||
void menuModelFailsafe(evt_t event);
|
||||
|
||||
enum menuModelSetupItems {
|
||||
ITEM_MODEL_NAME,
|
||||
ITEM_MODEL_BITMAP,
|
||||
ITEM_MODEL_TIMER1,
|
||||
ITEM_MODEL_TIMER1_NAME,
|
||||
ITEM_MODEL_TIMER1_PERSISTENT,
|
||||
ITEM_MODEL_TIMER1_MINUTE_BEEP,
|
||||
ITEM_MODEL_TIMER1_COUNTDOWN_BEEP,
|
||||
#if TIMERS > 1
|
||||
ITEM_MODEL_TIMER2,
|
||||
ITEM_MODEL_TIMER2_NAME,
|
||||
ITEM_MODEL_TIMER2_PERSISTENT,
|
||||
ITEM_MODEL_TIMER2_MINUTE_BEEP,
|
||||
ITEM_MODEL_TIMER2_COUNTDOWN_BEEP,
|
||||
#endif
|
||||
#if TIMERS > 2
|
||||
ITEM_MODEL_TIMER3,
|
||||
ITEM_MODEL_TIMER3_NAME,
|
||||
ITEM_MODEL_TIMER3_PERSISTENT,
|
||||
ITEM_MODEL_TIMER3_MINUTE_BEEP,
|
||||
ITEM_MODEL_TIMER3_COUNTDOWN_BEEP,
|
||||
#endif
|
||||
ITEM_MODEL_EXTENDED_LIMITS,
|
||||
ITEM_MODEL_EXTENDED_TRIMS,
|
||||
ITEM_MODEL_DISPLAY_TRIMS,
|
||||
ITEM_MODEL_TRIM_INC,
|
||||
ITEM_MODEL_THROTTLE_LABEL,
|
||||
// ITEM_MODEL_THROTTLE_REVERSED,
|
||||
ITEM_MODEL_THROTTLE_TRACE,
|
||||
ITEM_MODEL_THROTTLE_TRIM,
|
||||
ITEM_MODEL_PREFLIGHT_LABEL,
|
||||
ITEM_MODEL_CHECKLIST_DISPLAY,
|
||||
ITEM_MODEL_THROTTLE_WARNING,
|
||||
ITEM_MODEL_SWITCHES_WARNING,
|
||||
ITEM_MODEL_POT_WARNING,
|
||||
ITEM_MODEL_BEEP_CENTER,
|
||||
ITEM_MODEL_USE_GLOBAL_FUNCTIONS,
|
||||
ITEM_MODEL_EXTERNAL_MODULE_LABEL,
|
||||
ITEM_MODEL_EXTERNAL_MODULE_MODE,
|
||||
ITEM_MODEL_EXTERNAL_MODULE_CHANNELS,
|
||||
ITEM_MODEL_EXTERNAL_MODULE_BIND,
|
||||
ITEM_MODEL_EXTERNAL_MODULE_FAILSAFE,
|
||||
ITEM_MODEL_TRAINER_LABEL,
|
||||
ITEM_MODEL_TRAINER_MODE,
|
||||
ITEM_MODEL_TRAINER_CHANNELS,
|
||||
ITEM_MODEL_TRAINER_SETTINGS,
|
||||
ITEM_MODEL_SETUP_MAX
|
||||
};
|
||||
|
||||
#define FIELD_PROTOCOL_MAX 1
|
||||
|
||||
#define MODEL_SETUP_2ND_COLUMN 200
|
||||
#define MODEL_SETUP_BIND_OFS 20
|
||||
#define MODEL_SETUP_RANGE_OFS 40
|
||||
#define MODEL_SETUP_SET_FAILSAFE_OFS 60
|
||||
|
||||
void copySelection(char *dst, const char *src, uint8_t size)
|
||||
{
|
||||
if (memcmp(src, "---", 3) == 0)
|
||||
memset(dst, 0, size);
|
||||
else
|
||||
memcpy(dst, src, size);
|
||||
}
|
||||
|
||||
void editTimerMode(int timerIdx, coord_t y, LcdFlags attr, evt_t event)
|
||||
{
|
||||
TimerData * timer = &g_model.timers[timerIdx];
|
||||
if (attr && m_posHorz < 0) {
|
||||
lcdDrawFilledRect(MODEL_SETUP_2ND_COLUMN-INVERT_HORZ_MARGIN, y-INVERT_VERT_MARGIN, 80+2*INVERT_HORZ_MARGIN, INVERT_LINE_HEIGHT, TEXT_INVERTED_BGCOLOR);
|
||||
}
|
||||
putsStrIdx(MENU_TITLE_LEFT, y, STR_TIMER, timerIdx+1);
|
||||
putsTimerMode(MODEL_SETUP_2ND_COLUMN, y, timer->mode, (m_posHorz<=0 ? attr : 0));
|
||||
putsTimer(MODEL_SETUP_2ND_COLUMN+50, y, timer->start, (m_posHorz!=0 ? attr : 0));
|
||||
if (attr && s_editMode>0) {
|
||||
switch (m_posHorz) {
|
||||
case 0:
|
||||
{
|
||||
int8_t timerMode = timer->mode;
|
||||
if (timerMode < 0) timerMode -= TMRMODE_COUNT-1;
|
||||
CHECK_INCDEC_MODELVAR_CHECK(event, timerMode, -TMRMODE_COUNT-SWSRC_LAST+1, TMRMODE_COUNT+SWSRC_LAST-1, isSwitchAvailableInTimers);
|
||||
if (timerMode < 0) timerMode += TMRMODE_COUNT-1;
|
||||
timer->mode = timerMode;
|
||||
#if defined(AUTOSWITCH)
|
||||
if (s_editMode>0) {
|
||||
int8_t val = timer->mode - (TMRMODE_COUNT-1);
|
||||
int8_t switchVal = checkIncDecMovedSwitch(val);
|
||||
if (val != switchVal) {
|
||||
timer->mode = switchVal + (TMRMODE_COUNT-1);
|
||||
eeDirty(EE_MODEL);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
const int stopsMinutes[] = { 8, 60, 120, 180, 240, 300, 600, 900, 1200 };
|
||||
timer->start = checkIncDec(event, timer->start, 0, 60*60, EE_MODEL, NULL, (const CheckIncDecStops&)stopsMinutes);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define CURRENT_MODULE_EDITED(k) (k>=ITEM_MODEL_TRAINER_LABEL ? TRAINER_MODULE : EXTERNAL_MODULE)
|
||||
|
||||
int getSwitchWarningsCount()
|
||||
{
|
||||
int count = 0;
|
||||
for (int i=0; i<NUM_SWITCHES; ++i) {
|
||||
if (SWITCH_WARNING_ALLOWED(i)) {
|
||||
++count;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
void menuModelSetup(evt_t event)
|
||||
{
|
||||
horzpos_t l_posHorz = m_posHorz;
|
||||
#define IF_EXTERNAL_MODULE_ON(x) (g_model.externalModule == MODULE_TYPE_NONE ? HIDDEN_ROW : (uint8_t)(x))
|
||||
#define IF_TRAINER_ON(x) (g_model.trainerMode == TRAINER_MODE_SLAVE ? (uint8_t)(x) : HIDDEN_ROW)
|
||||
#define IF_EXTERNAL_MODULE_XJT(x) (IS_MODULE_XJT(EXTERNAL_MODULE) ? (uint8_t)x : HIDDEN_ROW)
|
||||
#define IS_D8_RX(x) (g_model.moduleData[x].rfProtocol == RF_PROTO_D8)
|
||||
#define EXTERNAL_MODULE_CHANNELS_ROWS() IF_EXTERNAL_MODULE_ON(IS_MODULE_DSM2(EXTERNAL_MODULE) ? (uint8_t)0 : (uint8_t)1)
|
||||
#define TRAINER_CHANNELS_ROWS() IF_TRAINER_ON(1)
|
||||
#define PORT_CHANNELS_ROWS(x) (x==EXTERNAL_MODULE ? EXTERNAL_MODULE_CHANNELS_ROWS() : TRAINER_CHANNELS_ROWS())
|
||||
#define FAILSAFE_ROWS(x) ((g_model.moduleData[x].rfProtocol==RF_PROTO_X16 || g_model.moduleData[x].rfProtocol==RF_PROTO_LR12) ? (g_model.moduleData[x].failsafeMode==FAILSAFE_CUSTOM ? (uint8_t)1 : (uint8_t)0) : HIDDEN_ROW)
|
||||
#define POT_WARN_ITEMS() ((g_model.potsWarnMode >> 6) ? (uint8_t)NUM_POTS : (uint8_t)0)
|
||||
#define TIMER_ROWS NAVIGATION_LINE_BY_LINE|1, 0, CASE_PERSISTENT_TIMERS(0) 0, 0
|
||||
#if TIMERS == 1
|
||||
#define TIMERS_ROWS TIMER_ROWS
|
||||
#elif TIMERS == 2
|
||||
#define TIMERS_ROWS TIMER_ROWS, TIMER_ROWS
|
||||
#elif TIMERS == 3
|
||||
#define TIMERS_ROWS TIMER_ROWS, TIMER_ROWS, TIMER_ROWS
|
||||
#endif
|
||||
bool CURSOR_ON_CELL = (m_posHorz >= 0);
|
||||
|
||||
MENU(STR_MENUSETUP, menuTabModel, e_ModelSetup, ITEM_MODEL_SETUP_MAX, DEFAULT_SCROLLBAR_X, { 0, 0, TIMERS_ROWS, 0, 1, 0, 0, LABEL(Throttle), 0, 0, LABEL(PreflightCheck), 0, 0, uint8_t(NAVIGATION_LINE_BY_LINE|(getSwitchWarningsCount()-1)), POT_WARN_ITEMS(), NAVIGATION_LINE_BY_LINE|(NUM_STICKS+NUM_POTS+NUM_ROTARY_ENCODERS-1), 0, LABEL(ExternalModule), (IS_MODULE_XJT(EXTERNAL_MODULE) || IS_MODULE_DSM2(EXTERNAL_MODULE)) ? (uint8_t)1 : (uint8_t)0, EXTERNAL_MODULE_CHANNELS_ROWS(), (IS_MODULE_XJT(EXTERNAL_MODULE) && IS_D8_RX(EXTERNAL_MODULE)) ? (uint8_t)1 : (IS_MODULE_PPM(EXTERNAL_MODULE) || IS_MODULE_XJT(EXTERNAL_MODULE) || IS_MODULE_DSM2(EXTERNAL_MODULE)) ? (uint8_t)2 : HIDDEN_ROW, IF_EXTERNAL_MODULE_XJT(FAILSAFE_ROWS(EXTERNAL_MODULE)), LABEL(Trainer), 0, TRAINER_CHANNELS_ROWS(), IF_TRAINER_ON(2) });
|
||||
|
||||
#if (defined(DSM2) || defined(PXX))
|
||||
if (menuEvent) {
|
||||
moduleFlag[0] = 0;
|
||||
#if NUM_MODULES > 1
|
||||
moduleFlag[1] = 0;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
int sub = m_posVert;
|
||||
|
||||
for (int i=0; i<NUM_BODY_LINES; ++i) {
|
||||
coord_t y = MENU_CONTENT_TOP + i*FH;
|
||||
int k = i+s_pgOfs;
|
||||
for (int j=0; j<=k; j++) {
|
||||
if (mstate_tab[j] == HIDDEN_ROW)
|
||||
k++;
|
||||
}
|
||||
|
||||
LcdFlags blink = ((s_editMode>0) ? BLINK|INVERS : INVERS);
|
||||
LcdFlags attr = (sub == k ? blink : 0);
|
||||
|
||||
switch(k) {
|
||||
case ITEM_MODEL_NAME:
|
||||
editSingleName(MODEL_SETUP_2ND_COLUMN, y, STR_MODELNAME, g_model.header.name, sizeof(g_model.header.name), event, attr);
|
||||
memcpy(modelHeaders[g_eeGeneral.currModel].name, g_model.header.name, sizeof(g_model.header.name));
|
||||
break;
|
||||
|
||||
case ITEM_MODEL_BITMAP:
|
||||
lcd_putsLeft(y, STR_BITMAP);
|
||||
lcd_outdezAtt(MODEL_SETUP_2ND_COLUMN, y, g_model.header.bitmap, LEFT|attr);
|
||||
if (attr) CHECK_INCDEC_MODELVAR_ZERO(event, g_model.header.bitmap, 3);
|
||||
break;
|
||||
|
||||
case ITEM_MODEL_TIMER1:
|
||||
editTimerMode(0, y, attr, event);
|
||||
break;
|
||||
|
||||
case ITEM_MODEL_TIMER1_NAME:
|
||||
editSingleName(MODEL_SETUP_2ND_COLUMN, y, STR_TIMER_NAME, g_model.timers[0].name, LEN_TIMER_NAME, event, attr);
|
||||
break;
|
||||
|
||||
case ITEM_MODEL_TIMER1_MINUTE_BEEP:
|
||||
g_model.timers[0].minuteBeep = onoffMenuItem(g_model.timers[0].minuteBeep, MODEL_SETUP_2ND_COLUMN, y, STR_MINUTEBEEP, attr, event);
|
||||
break;
|
||||
|
||||
case ITEM_MODEL_TIMER1_COUNTDOWN_BEEP:
|
||||
g_model.timers[0].countdownBeep = selectMenuItem(MODEL_SETUP_2ND_COLUMN, y, STR_BEEPCOUNTDOWN, STR_VBEEPCOUNTDOWN, g_model.timers[0].countdownBeep, 0, 2, attr, event);
|
||||
break;
|
||||
|
||||
case ITEM_MODEL_TIMER1_PERSISTENT:
|
||||
g_model.timers[0].persistent = selectMenuItem(MODEL_SETUP_2ND_COLUMN, y, STR_PERSISTENT, STR_VPERSISTENT, g_model.timers[0].persistent, 0, 2, attr, event);
|
||||
break;
|
||||
|
||||
#if TIMERS > 1
|
||||
case ITEM_MODEL_TIMER2:
|
||||
editTimerMode(1, y, attr, event);
|
||||
break;
|
||||
|
||||
case ITEM_MODEL_TIMER2_NAME:
|
||||
editSingleName(MODEL_SETUP_2ND_COLUMN, y, STR_TIMER_NAME, g_model.timers[1].name, LEN_TIMER_NAME, event, attr);
|
||||
break;
|
||||
|
||||
case ITEM_MODEL_TIMER2_MINUTE_BEEP:
|
||||
g_model.timers[1].minuteBeep = onoffMenuItem(g_model.timers[1].minuteBeep, MODEL_SETUP_2ND_COLUMN, y, STR_MINUTEBEEP, attr, event);
|
||||
break;
|
||||
|
||||
case ITEM_MODEL_TIMER2_COUNTDOWN_BEEP:
|
||||
g_model.timers[1].countdownBeep = selectMenuItem(MODEL_SETUP_2ND_COLUMN, y, STR_BEEPCOUNTDOWN, STR_VBEEPCOUNTDOWN, g_model.timers[1].countdownBeep, 0, 2, attr, event);
|
||||
break;
|
||||
|
||||
case ITEM_MODEL_TIMER2_PERSISTENT:
|
||||
g_model.timers[1].persistent = selectMenuItem(MODEL_SETUP_2ND_COLUMN, y, STR_PERSISTENT, STR_VPERSISTENT, g_model.timers[1].persistent, 0, 2, attr, event);
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if TIMERS > 2
|
||||
case ITEM_MODEL_TIMER3:
|
||||
editTimerMode(2, y, attr, event);
|
||||
break;
|
||||
|
||||
case ITEM_MODEL_TIMER3_NAME:
|
||||
editSingleName(MODEL_SETUP_2ND_COLUMN, y, STR_TIMER_NAME, g_model.timers[2].name, LEN_TIMER_NAME, event, attr);
|
||||
break;
|
||||
|
||||
case ITEM_MODEL_TIMER3_MINUTE_BEEP:
|
||||
g_model.timers[2].minuteBeep = onoffMenuItem(g_model.timers[2].minuteBeep, MODEL_SETUP_2ND_COLUMN, y, STR_MINUTEBEEP, attr, event);
|
||||
break;
|
||||
|
||||
case ITEM_MODEL_TIMER3_COUNTDOWN_BEEP:
|
||||
g_model.timers[2].countdownBeep = selectMenuItem(MODEL_SETUP_2ND_COLUMN, y, STR_BEEPCOUNTDOWN, STR_VBEEPCOUNTDOWN, g_model.timers[2].countdownBeep, 0, 2, attr, event);
|
||||
break;
|
||||
|
||||
case ITEM_MODEL_TIMER3_PERSISTENT:
|
||||
g_model.timers[2].persistent = selectMenuItem(MODEL_SETUP_2ND_COLUMN, y, STR_PERSISTENT, STR_VPERSISTENT, g_model.timers[2].persistent, 0, 2, attr, event);
|
||||
break;
|
||||
#endif
|
||||
|
||||
case ITEM_MODEL_EXTENDED_LIMITS:
|
||||
ON_OFF_MENU_ITEM(g_model.extendedLimits, MODEL_SETUP_2ND_COLUMN, y, STR_ELIMITS, attr, event);
|
||||
break;
|
||||
|
||||
case ITEM_MODEL_EXTENDED_TRIMS:
|
||||
ON_OFF_MENU_ITEM(g_model.extendedTrims, MODEL_SETUP_2ND_COLUMN, y, STR_ETRIMS, m_posHorz<=0 ? attr : 0, event==EVT_KEY_BREAK(KEY_ENTER) ? event : 0);
|
||||
lcd_putsAtt(MODEL_SETUP_2ND_COLUMN+18, y, STR_RESET_BTN, m_posHorz>0 && !s_noHi ? attr : 0);
|
||||
if (attr && m_posHorz>0) {
|
||||
s_editMode = 0;
|
||||
if (event==EVT_KEY_LONG(KEY_ENTER)) {
|
||||
s_noHi = NO_HI_LEN;
|
||||
for (uint8_t i=0; i<MAX_FLIGHT_MODES; i++) {
|
||||
memclear(&g_model.flightModeData[i], TRIMS_ARRAY_SIZE);
|
||||
}
|
||||
eeDirty(EE_MODEL);
|
||||
AUDIO_WARNING1();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ITEM_MODEL_DISPLAY_TRIMS:
|
||||
g_model.displayTrims = selectMenuItem(MODEL_SETUP_2ND_COLUMN, y, "Display Trims", "\006No\0 ChangeYes", g_model.displayTrims, 0, 2, attr, event);
|
||||
break;
|
||||
|
||||
case ITEM_MODEL_TRIM_INC:
|
||||
g_model.trimInc = selectMenuItem(MODEL_SETUP_2ND_COLUMN, y, STR_TRIMINC, STR_VTRIMINC, g_model.trimInc, -2, 2, attr, event);
|
||||
break;
|
||||
|
||||
case ITEM_MODEL_THROTTLE_LABEL:
|
||||
lcd_putsLeft(y, STR_THROTTLE_LABEL);
|
||||
break;
|
||||
|
||||
#if 0
|
||||
case ITEM_MODEL_THROTTLE_REVERSED:
|
||||
ON_OFF_MENU_ITEM(g_model.throttleReversed, MODEL_SETUP_2ND_COLUMN, y, STR_THROTTLEREVERSE, attr, event ) ;
|
||||
break;
|
||||
#endif
|
||||
|
||||
case ITEM_MODEL_THROTTLE_TRACE:
|
||||
{
|
||||
lcd_putsLeft(y, STR_TTRACE);
|
||||
if (attr) CHECK_INCDEC_MODELVAR_ZERO(event, g_model.thrTraceSrc, NUM_POTS+NUM_CHNOUT);
|
||||
uint8_t idx = g_model.thrTraceSrc + MIXSRC_Thr;
|
||||
if (idx > MIXSRC_Thr)
|
||||
idx += 1;
|
||||
if (idx >= MIXSRC_FIRST_POT+NUM_POTS)
|
||||
idx += MIXSRC_CH1 - MIXSRC_FIRST_POT - NUM_POTS;
|
||||
putsMixerSource(MODEL_SETUP_2ND_COLUMN, y, idx, attr);
|
||||
break;
|
||||
}
|
||||
|
||||
case ITEM_MODEL_THROTTLE_TRIM:
|
||||
ON_OFF_MENU_ITEM(g_model.thrTrim, MODEL_SETUP_2ND_COLUMN, y, STR_TTRIM, attr, event);
|
||||
break;
|
||||
|
||||
case ITEM_MODEL_PREFLIGHT_LABEL:
|
||||
lcd_putsLeft(y, STR_PREFLIGHT);
|
||||
break;
|
||||
|
||||
case ITEM_MODEL_CHECKLIST_DISPLAY:
|
||||
ON_OFF_MENU_ITEM(g_model.displayChecklist, MODEL_SETUP_2ND_COLUMN, y, STR_CHECKLIST, attr, event);
|
||||
break;
|
||||
|
||||
case ITEM_MODEL_THROTTLE_WARNING:
|
||||
g_model.disableThrottleWarning = !onoffMenuItem(!g_model.disableThrottleWarning, MODEL_SETUP_2ND_COLUMN, y, STR_THROTTLEWARNING, attr, event);
|
||||
break;
|
||||
|
||||
case ITEM_MODEL_SWITCHES_WARNING:
|
||||
{
|
||||
lcd_putsLeft(y, STR_SWITCHWARNING);
|
||||
if (!READ_ONLY() && attr && m_posHorz<0 && event==EVT_KEY_LONG(KEY_ENTER)) {
|
||||
killEvents(event);
|
||||
s_noHi = NO_HI_LEN;
|
||||
getMovedSwitch();
|
||||
g_model.switchWarningState = switches_states;
|
||||
AUDIO_WARNING1();
|
||||
eeDirty(EE_MODEL);
|
||||
}
|
||||
|
||||
if (attr && m_posHorz < 0) {
|
||||
lcdDrawFilledRect(MODEL_SETUP_2ND_COLUMN-INVERT_HORZ_MARGIN, y-INVERT_VERT_MARGIN, NUM_SWITCHES*18+INVERT_HORZ_MARGIN, INVERT_LINE_HEIGHT, TEXT_INVERTED_BGCOLOR);
|
||||
}
|
||||
|
||||
unsigned int newStates = 0;
|
||||
for (int i=0, current=0; i<NUM_SWITCHES; i++) {
|
||||
if (SWITCH_WARNING_ALLOWED(i)) {
|
||||
if (!READ_ONLY() && attr && l_posHorz==current) {
|
||||
// g_model.switchWarningEnable ^= (1 << i);
|
||||
eeDirty(EE_MODEL);
|
||||
}
|
||||
unsigned int state = ((g_model.switchWarningState >> (3*i)) & 0x07);
|
||||
LcdFlags color = (state > 0 ? TEXT_COLOR : TEXT_DISABLE_COLOR);
|
||||
if (attr && m_posHorz < 0) {
|
||||
color |= INVERS;
|
||||
}
|
||||
char s[3];
|
||||
s[0] = 'A' + i + (i >= 3 ? 1 : 0 /* skip SD which is a POT*/);
|
||||
int max;
|
||||
if (state == 0) {
|
||||
s[1] = 'x';
|
||||
max = 2;
|
||||
}
|
||||
else if (i == 2) {
|
||||
s[1] = '0' + state;
|
||||
max = 6;
|
||||
}
|
||||
else if (IS_3POS(i)) {
|
||||
s[1] = "\300-\301"[state-1];
|
||||
max = 3;
|
||||
}
|
||||
else {
|
||||
s[1] = "\300\301"[state-1];
|
||||
max = 2;
|
||||
}
|
||||
s[2] = '\0';
|
||||
lcd_putsAtt(MODEL_SETUP_2ND_COLUMN+i*18, y, s, color|(m_posHorz==current ? attr : 0));
|
||||
if (attr && m_posHorz==current) CHECK_INCDEC_MODELVAR_ZERO(event, state, max);
|
||||
newStates |= (state << (3*i));
|
||||
++current;
|
||||
}
|
||||
}
|
||||
g_model.switchWarningState = newStates;
|
||||
break;
|
||||
}
|
||||
|
||||
case ITEM_MODEL_POT_WARNING:
|
||||
{
|
||||
lcd_putsLeft(y, STR_POTWARNING);
|
||||
if (attr) {
|
||||
if (m_posHorz) s_editMode = 0;
|
||||
if (!READ_ONLY() && m_posHorz) {
|
||||
switch (event) {
|
||||
case EVT_KEY_LONG(KEY_ENTER):
|
||||
killEvents(event);
|
||||
if (g_model.potsWarnMode == POTS_WARN_MANUAL) {
|
||||
SAVE_POT_POSITION(m_posHorz-1);
|
||||
AUDIO_WARNING1();
|
||||
eeDirty(EE_MODEL);
|
||||
}
|
||||
break;
|
||||
case EVT_KEY_BREAK(KEY_ENTER):
|
||||
g_model.potsWarnEnabled ^= (1 << (m_posHorz-1));
|
||||
eeDirty(EE_MODEL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
lcd_putsiAtt(MODEL_SETUP_2ND_COLUMN, y, PSTR("\004""OFF\0""Man\0""Auto"), g_model.potsWarnMode, (m_posHorz == 0) ? attr : 0);
|
||||
if (g_model.potsWarnMode) {
|
||||
coord_t x = MODEL_SETUP_2ND_COLUMN+30;
|
||||
for (int i=0; i<NUM_POTS; ++i) {
|
||||
LcdFlags flags = (((m_posHorz==i+1) && attr) ? INVERS : 0);
|
||||
flags |= (g_model.potsWarnEnabled & (1 << i)) ? TEXT_DISABLE_COLOR : TEXT_COLOR;
|
||||
lcd_putsiAtt(x, y, STR_VSRCRAW, NUM_STICKS+1+i, flags);
|
||||
x += 20;
|
||||
}
|
||||
}
|
||||
|
||||
if (attr && (m_posHorz == 0)) {
|
||||
CHECK_INCDEC_MODELVAR(event, g_model.potsWarnMode, POTS_WARN_OFF, POTS_WARN_AUTO);
|
||||
eeDirty(EE_MODEL);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case ITEM_MODEL_BEEP_CENTER:
|
||||
lcd_putsLeft(y, STR_BEEPCTR);
|
||||
if (attr && m_posHorz < 0) {
|
||||
lcdDrawFilledRect(MODEL_SETUP_2ND_COLUMN-INVERT_HORZ_MARGIN, y-INVERT_VERT_MARGIN, (NUM_STICKS+NUM_POTS)*11+2*INVERT_HORZ_MARGIN, INVERT_LINE_HEIGHT, TEXT_INVERTED_BGCOLOR);
|
||||
}
|
||||
for (int i=0; i<NUM_STICKS+NUM_POTS; i++) {
|
||||
// TODO flash saving, \001 not needed in STR_RETA123
|
||||
coord_t x = MODEL_SETUP_2ND_COLUMN+i*11;
|
||||
LcdFlags flags = ((m_posHorz==i && attr) ? INVERS : 0);
|
||||
flags |= (g_model.beepANACenter & ((BeepANACenter)1<<i)) ? TEXT_COLOR : TEXT_DISABLE_COLOR;
|
||||
if (attr && m_posHorz < 0) flags |= INVERS;
|
||||
lcd_putsiAtt(x, y, STR_RETA123, i, flags);
|
||||
}
|
||||
if (attr && CURSOR_ON_CELL) {
|
||||
if (event==EVT_KEY_BREAK(KEY_ENTER)) {
|
||||
if (READ_ONLY_UNLOCKED()) {
|
||||
s_editMode = 0;
|
||||
g_model.beepANACenter ^= ((BeepANACenter)1<<m_posHorz);
|
||||
eeDirty(EE_MODEL);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ITEM_MODEL_USE_GLOBAL_FUNCTIONS:
|
||||
lcd_putsLeft(y, "Use Global Funcs");
|
||||
lcdDrawCheckBox(MODEL_SETUP_2ND_COLUMN, y, !g_model.noGlobalFunctions, attr);
|
||||
if (attr) g_model.noGlobalFunctions = !checkIncDecModel(event, !g_model.noGlobalFunctions, 0, 1);
|
||||
break;
|
||||
|
||||
case ITEM_MODEL_TRAINER_MODE:
|
||||
g_model.trainerMode = selectMenuItem(MODEL_SETUP_2ND_COLUMN, y, STR_MODE, STR_VTRAINERMODES, g_model.trainerMode, TRAINER_MODE_MASTER, TRAINER_MODE_SLAVE, attr, event);
|
||||
break;
|
||||
|
||||
case ITEM_MODEL_EXTERNAL_MODULE_LABEL:
|
||||
lcd_putsLeft(y, TR_EXTERNALRF);
|
||||
break;
|
||||
|
||||
case ITEM_MODEL_EXTERNAL_MODULE_MODE:
|
||||
lcd_putsLeft(y, STR_MODE);
|
||||
lcd_putsiAtt(MODEL_SETUP_2ND_COLUMN, y, STR_TARANIS_PROTOCOLS, g_model.externalModule, (m_posHorz==0 ? attr : 0));
|
||||
if (IS_MODULE_XJT(EXTERNAL_MODULE))
|
||||
lcd_putsiAtt(MODEL_SETUP_2ND_COLUMN+40, y, STR_XJT_PROTOCOLS, 1+g_model.moduleData[EXTERNAL_MODULE].rfProtocol, (m_posHorz==1 ? attr : 0));
|
||||
else if (IS_MODULE_DSM2(EXTERNAL_MODULE))
|
||||
lcd_putsiAtt(MODEL_SETUP_2ND_COLUMN+40, y, STR_DSM_PROTOCOLS, g_model.moduleData[EXTERNAL_MODULE].rfProtocol, (m_posHorz==1 ? attr : 0));
|
||||
if (attr && s_editMode>0) {
|
||||
switch (m_posHorz) {
|
||||
case 0:
|
||||
g_model.externalModule = checkIncDec(event, g_model.externalModule, MODULE_TYPE_NONE, MODULE_TYPE_COUNT-1, EE_MODEL, isModuleAvailable);
|
||||
if (checkIncDec_Ret) {
|
||||
g_model.moduleData[EXTERNAL_MODULE].rfProtocol = 0;
|
||||
g_model.moduleData[EXTERNAL_MODULE].channelsStart = 0;
|
||||
if (g_model.externalModule == MODULE_TYPE_PPM)
|
||||
g_model.moduleData[EXTERNAL_MODULE].channelsCount = 0;
|
||||
else
|
||||
g_model.moduleData[EXTERNAL_MODULE].channelsCount = MAX_EXTERNAL_MODULE_CHANNELS();
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if (IS_MODULE_DSM2(EXTERNAL_MODULE))
|
||||
CHECK_INCDEC_MODELVAR(event, g_model.moduleData[EXTERNAL_MODULE].rfProtocol, DSM2_PROTO_LP45, DSM2_PROTO_DSMX);
|
||||
else
|
||||
CHECK_INCDEC_MODELVAR(event, g_model.moduleData[EXTERNAL_MODULE].rfProtocol, RF_PROTO_X16, RF_PROTO_LAST);
|
||||
if (checkIncDec_Ret) {
|
||||
g_model.moduleData[EXTERNAL_MODULE].channelsStart = 0;
|
||||
g_model.moduleData[EXTERNAL_MODULE].channelsCount = MAX_EXTERNAL_MODULE_CHANNELS();
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ITEM_MODEL_TRAINER_LABEL:
|
||||
lcd_putsLeft(y, STR_TRAINER);
|
||||
break;
|
||||
|
||||
case ITEM_MODEL_EXTERNAL_MODULE_CHANNELS:
|
||||
case ITEM_MODEL_TRAINER_CHANNELS:
|
||||
{
|
||||
uint8_t moduleIdx = CURRENT_MODULE_EDITED(k);
|
||||
ModuleData & moduleData = g_model.moduleData[moduleIdx];
|
||||
lcd_putsLeft(y, STR_CHANNELRANGE);
|
||||
if ((int8_t)PORT_CHANNELS_ROWS(moduleIdx) >= 0) {
|
||||
putsStrIdx(MODEL_SETUP_2ND_COLUMN, y, STR_CH, moduleData.channelsStart+1, m_posHorz==0 ? attr : 0);
|
||||
lcd_puts(MODEL_SETUP_2ND_COLUMN+30, y, "-");
|
||||
putsStrIdx(MODEL_SETUP_2ND_COLUMN+40, y, STR_CH, moduleData.channelsStart+NUM_CHANNELS(moduleIdx), m_posHorz==1 ? attr : 0);
|
||||
if (attr && s_editMode>0) {
|
||||
switch (m_posHorz) {
|
||||
case 0:
|
||||
CHECK_INCDEC_MODELVAR_ZERO(event, moduleData.channelsStart, 32-8-moduleData.channelsCount);
|
||||
break;
|
||||
case 1:
|
||||
CHECK_INCDEC_MODELVAR(event, moduleData.channelsCount, -4, min<int8_t>(MAX_CHANNELS(moduleIdx), 32-8-moduleData.channelsStart));
|
||||
if ((k == ITEM_MODEL_EXTERNAL_MODULE_CHANNELS && g_model.externalModule == MODULE_TYPE_PPM)
|
||||
|| (k == ITEM_MODEL_TRAINER_CHANNELS)
|
||||
)
|
||||
SET_DEFAULT_PPM_FRAME_LENGTH(moduleIdx);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case ITEM_MODEL_EXTERNAL_MODULE_BIND:
|
||||
case ITEM_MODEL_TRAINER_SETTINGS:
|
||||
{
|
||||
uint8_t moduleIdx = CURRENT_MODULE_EDITED(k);
|
||||
ModuleData & moduleData = g_model.moduleData[moduleIdx];
|
||||
if (IS_MODULE_PPM(moduleIdx)) {
|
||||
lcd_putsLeft(y, STR_PPMFRAME);
|
||||
lcd_outdezAtt(MODEL_SETUP_2ND_COLUMN, y, (int16_t)moduleData.ppmFrameLength*5 + 225, (m_posHorz<=0 ? attr : 0) | PREC1|LEFT, STR_MS);
|
||||
lcd_outdezAtt(MODEL_SETUP_2ND_COLUMN+70, y, (moduleData.ppmDelay*50)+300, (CURSOR_ON_LINE() || m_posHorz==1) ? attr : 0, "us");
|
||||
lcd_putsAtt(MODEL_SETUP_2ND_COLUMN+90, y, moduleData.ppmPulsePol ? "+" : "-", (CURSOR_ON_LINE() || m_posHorz==2) ? attr : 0);
|
||||
|
||||
if (attr && s_editMode>0) {
|
||||
switch (m_posHorz) {
|
||||
case 0:
|
||||
CHECK_INCDEC_MODELVAR(event, moduleData.ppmFrameLength, -20, 35);
|
||||
break;
|
||||
case 1:
|
||||
CHECK_INCDEC_MODELVAR(event, moduleData.ppmDelay, -4, 10);
|
||||
break;
|
||||
case 2:
|
||||
CHECK_INCDEC_MODELVAR_ZERO(event, moduleData.ppmPulsePol, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
horzpos_t l_posHorz = m_posHorz;
|
||||
coord_t xOffsetBind = MODEL_SETUP_BIND_OFS;
|
||||
if (IS_MODULE_XJT(moduleIdx) && IS_D8_RX(moduleIdx)) {
|
||||
xOffsetBind = 0;
|
||||
lcd_putsLeft(y, INDENT "Receiver");
|
||||
if (attr) l_posHorz += 1;
|
||||
}
|
||||
else {
|
||||
lcd_putsLeft(y, STR_RXNUM);
|
||||
}
|
||||
if (IS_MODULE_XJT(moduleIdx) || IS_MODULE_DSM2(moduleIdx)) {
|
||||
if (xOffsetBind) lcd_outdezNAtt(MODEL_SETUP_2ND_COLUMN, y, g_model.header.modelId[moduleIdx], (l_posHorz==0 ? attr : 0) | LEADING0|LEFT, 2);
|
||||
if (attr && l_posHorz==0) {
|
||||
if (s_editMode>0) {
|
||||
CHECK_INCDEC_MODELVAR_ZERO(event, g_model.header.modelId[moduleIdx], IS_MODULE_DSM2(moduleIdx) ? 20 : 63);
|
||||
if (checkIncDec_Ret) {
|
||||
modelHeaders[g_eeGeneral.currModel].modelId[moduleIdx] = g_model.header.modelId[moduleIdx];
|
||||
}
|
||||
}
|
||||
if (s_editMode==0 && event==EVT_KEY_BREAK(KEY_ENTER)) {
|
||||
checkModelIdUnique(g_eeGeneral.currModel, moduleIdx);
|
||||
}
|
||||
}
|
||||
lcd_putsAtt(MODEL_SETUP_2ND_COLUMN+xOffsetBind, y, STR_MODULE_BIND, l_posHorz==1 ? attr : 0);
|
||||
lcd_putsAtt(MODEL_SETUP_2ND_COLUMN+MODEL_SETUP_RANGE_OFS+xOffsetBind, y, STR_MODULE_RANGE, l_posHorz==2 ? attr : 0);
|
||||
uint8_t newFlag = 0;
|
||||
if (attr && l_posHorz>0 && s_editMode>0) {
|
||||
if (l_posHorz == 1)
|
||||
newFlag = MODULE_BIND;
|
||||
else if (l_posHorz == 2) {
|
||||
newFlag = MODULE_RANGECHECK;
|
||||
}
|
||||
}
|
||||
moduleFlag[moduleIdx] = newFlag;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case ITEM_MODEL_EXTERNAL_MODULE_FAILSAFE:
|
||||
{
|
||||
uint8_t moduleIdx = CURRENT_MODULE_EDITED(k);
|
||||
ModuleData & moduleData = g_model.moduleData[moduleIdx];
|
||||
lcd_putsLeft(y, TR_FAILSAFE);
|
||||
if (IS_MODULE_XJT(moduleIdx)) {
|
||||
lcd_putsiAtt(MODEL_SETUP_2ND_COLUMN, y, STR_VFAILSAFE, moduleData.failsafeMode, m_posHorz==0 ? attr : 0);
|
||||
if (moduleData.failsafeMode == FAILSAFE_CUSTOM) lcd_putsAtt(MODEL_SETUP_2ND_COLUMN + MODEL_SETUP_SET_FAILSAFE_OFS, y, STR_SET, m_posHorz==1 ? attr : 0);
|
||||
if (attr) {
|
||||
if (moduleData.failsafeMode != FAILSAFE_CUSTOM)
|
||||
m_posHorz = 0;
|
||||
if (m_posHorz==0) {
|
||||
if (s_editMode>0) {
|
||||
CHECK_INCDEC_MODELVAR_ZERO(event, moduleData.failsafeMode, FAILSAFE_LAST);
|
||||
if (checkIncDec_Ret) SEND_FAILSAFE_NOW(moduleIdx);
|
||||
}
|
||||
}
|
||||
else if (m_posHorz==1) {
|
||||
s_editMode = 0;
|
||||
if (moduleData.failsafeMode==FAILSAFE_CUSTOM && event==EVT_KEY_FIRST(KEY_ENTER)) {
|
||||
g_moduleIdx = moduleIdx;
|
||||
pushMenu(menuModelFailsafe);
|
||||
}
|
||||
}
|
||||
else {
|
||||
lcdDrawFilledRect(MODEL_SETUP_2ND_COLUMN, y, LCD_W-MODEL_SETUP_2ND_COLUMN-MENUS_SCROLLBAR_WIDTH, 8, TEXT_COLOR);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (IS_RANGECHECK_ENABLE()) {
|
||||
displayPopup("RSSI :");
|
||||
lcd_outdezAtt(WARNING_LINE_X, WARNING_INFOLINE_Y, TELEMETRY_RSSI(), DBLSIZE|LEFT);
|
||||
}
|
||||
}
|
||||
|
||||
void menuModelFailsafe(evt_t event)
|
||||
{
|
||||
static bool longNames = false;
|
||||
bool newLongNames = false;
|
||||
uint8_t ch = 0;
|
||||
|
||||
if (event == EVT_KEY_LONG(KEY_ENTER) && s_editMode) {
|
||||
s_noHi = NO_HI_LEN;
|
||||
g_model.moduleData[g_moduleIdx].failsafeChannels[m_posVert] = channelOutputs[m_posVert];
|
||||
eeDirty(EE_MODEL);
|
||||
AUDIO_WARNING1();
|
||||
SEND_FAILSAFE_NOW(g_moduleIdx);
|
||||
}
|
||||
|
||||
SIMPLE_SUBMENU_NOTITLE(NUM_CHNOUT, 0);
|
||||
|
||||
#define COL_W (LCD_W/2)
|
||||
const uint8_t SLIDER_W = 64;
|
||||
// Column separator
|
||||
lcd_vline(LCD_W/2, FH, LCD_H-FH);
|
||||
|
||||
if (m_posVert >= 16) {
|
||||
ch = 16;
|
||||
}
|
||||
|
||||
// TODO lcd_putsCenter(0, FAILSAFESET);
|
||||
// TODO lcd_invert_line(0);
|
||||
|
||||
for (int col=0; col<2; col++) {
|
||||
coord_t x = col*COL_W+1;
|
||||
|
||||
// Channels
|
||||
for (int line=0; line<8; line++) {
|
||||
coord_t y = 9+line*7;
|
||||
int32_t val;
|
||||
int ofs = (col ? 0 : 1);
|
||||
|
||||
if (ch < g_model.moduleData[g_moduleIdx].channelsStart || ch >= NUM_CHANNELS(g_moduleIdx) + g_model.moduleData[g_moduleIdx].channelsStart)
|
||||
val = 0;
|
||||
else if (s_editMode && m_posVert == ch)
|
||||
val = channelOutputs[ch];
|
||||
else
|
||||
val = g_model.moduleData[g_moduleIdx].failsafeChannels[8*col+line];
|
||||
|
||||
// Channel name if present, number if not
|
||||
uint8_t lenLabel = ZLEN(g_model.limitData[ch].name);
|
||||
if (lenLabel > 4) {
|
||||
newLongNames = longNames = true;
|
||||
}
|
||||
|
||||
if (lenLabel > 0)
|
||||
lcd_putsnAtt(x+1-ofs, y, g_model.limitData[ch].name, sizeof(g_model.limitData[ch].name), ZCHAR | SMLSIZE);
|
||||
else
|
||||
putsChn(x+1-ofs, y, ch+1, SMLSIZE);
|
||||
|
||||
// Value
|
||||
LcdFlags flags = TINSIZE;
|
||||
if (m_posVert == ch && !s_noHi) {
|
||||
flags |= INVERS;
|
||||
if (s_editMode)
|
||||
flags |= BLINK;
|
||||
}
|
||||
#if defined(PPM_UNIT_US)
|
||||
uint8_t wbar = (longNames ? SLIDER_W-10 : SLIDER_W);
|
||||
lcd_outdezAtt(x+COL_W-4-wbar-ofs, y, PPM_CH_CENTER(ch)+val/2, flags);
|
||||
#elif defined(PPM_UNIT_PERCENT_PREC1)
|
||||
uint8_t wbar = (longNames ? SLIDER_W-16 : SLIDER_W-6);
|
||||
lcd_outdezAtt(x+COL_W-4-wbar-ofs, y, calcRESXto1000(val), PREC1|flags);
|
||||
#else
|
||||
uint8_t wbar = (longNames ? SLIDER_W-10 : SLIDER_W);
|
||||
lcd_outdezAtt(x+COL_W-4-wbar-ofs, y, calcRESXto1000(val)/10, flags);
|
||||
#endif
|
||||
|
||||
// Gauge
|
||||
lcd_rect(x+COL_W-3-wbar-ofs, y, wbar+1, 6);
|
||||
uint16_t lim = g_model.extendedLimits ? 640*2 : 512*2;
|
||||
uint8_t len = limit((uint8_t)1, uint8_t((abs(val) * wbar/2 + lim/2) / lim), uint8_t(wbar/2));
|
||||
coord_t x0 = (val>0) ? x+COL_W-ofs-3-wbar/2 : x+COL_W-ofs-2-wbar/2-len;
|
||||
lcd_hline(x0, y+1, len);
|
||||
lcd_hline(x0, y+2, len);
|
||||
lcd_hline(x0, y+3, len);
|
||||
lcd_hline(x0, y+4, len);
|
||||
|
||||
ch++;
|
||||
}
|
||||
}
|
||||
|
||||
longNames = newLongNames;
|
||||
}
|
||||
@@ -0,0 +1,728 @@
|
||||
/*
|
||||
* Authors (alphabetical order)
|
||||
* - Andre Bernet <bernet.andre@gmail.com>
|
||||
* - Andreas Weitl
|
||||
* - Bertrand Songis <bsongis@gmail.com>
|
||||
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
|
||||
* - Cameron Weeks <th9xer@gmail.com>
|
||||
* - Erez Raviv
|
||||
* - Gabriel Birkus
|
||||
* - Jean-Pierre Parisy
|
||||
* - Karl Szmutny
|
||||
* - Michael Blandford
|
||||
* - Michal Hlavinka
|
||||
* - Pat Mackenzie
|
||||
* - Philip Moss
|
||||
* - Rob Thomson
|
||||
* - 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 menuModelTelemetryItems {
|
||||
ITEM_TELEMETRY_PROTOCOL_TYPE,
|
||||
ITEM_TELEMETRY_RSSI_LABEL,
|
||||
ITEM_TELEMETRY_RSSI_ALARM1,
|
||||
ITEM_TELEMETRY_RSSI_ALARM2,
|
||||
ITEM_TELEMETRY_SENSORS_LABEL,
|
||||
ITEM_TELEMETRY_SENSOR1,
|
||||
ITEM_TELEMETRY_SENSOR2,
|
||||
ITEM_TELEMETRY_SENSOR3,
|
||||
ITEM_TELEMETRY_SENSOR4,
|
||||
ITEM_TELEMETRY_SENSOR5,
|
||||
ITEM_TELEMETRY_SENSOR6,
|
||||
ITEM_TELEMETRY_SENSOR7,
|
||||
ITEM_TELEMETRY_SENSOR8,
|
||||
ITEM_TELEMETRY_SENSOR9,
|
||||
ITEM_TELEMETRY_SENSOR10,
|
||||
ITEM_TELEMETRY_SENSOR11,
|
||||
ITEM_TELEMETRY_SENSOR12,
|
||||
ITEM_TELEMETRY_SENSOR13,
|
||||
ITEM_TELEMETRY_SENSOR14,
|
||||
ITEM_TELEMETRY_SENSOR15,
|
||||
ITEM_TELEMETRY_SENSOR16,
|
||||
ITEM_TELEMETRY_SENSOR17,
|
||||
ITEM_TELEMETRY_SENSOR18,
|
||||
ITEM_TELEMETRY_SENSOR19,
|
||||
ITEM_TELEMETRY_SENSOR20,
|
||||
ITEM_TELEMETRY_SENSOR21,
|
||||
ITEM_TELEMETRY_SENSOR22,
|
||||
ITEM_TELEMETRY_SENSOR23,
|
||||
ITEM_TELEMETRY_SENSOR24,
|
||||
ITEM_TELEMETRY_SENSOR25,
|
||||
ITEM_TELEMETRY_SENSOR26,
|
||||
ITEM_TELEMETRY_SENSOR27,
|
||||
ITEM_TELEMETRY_SENSOR28,
|
||||
ITEM_TELEMETRY_SENSOR29,
|
||||
ITEM_TELEMETRY_SENSOR30,
|
||||
ITEM_TELEMETRY_SENSOR31,
|
||||
ITEM_TELEMETRY_SENSOR32,
|
||||
ITEM_TELEMETRY_NEWSENSOR,
|
||||
CASE_VARIO(ITEM_TELEMETRY_VARIO_LABEL)
|
||||
#if defined(VARIO)
|
||||
ITEM_TELEMETRY_VARIO_SOURCE,
|
||||
#endif
|
||||
CASE_VARIO(ITEM_TELEMETRY_VARIO_RANGE)
|
||||
ITEM_TELEMETRY_TOP_BAR_LABEL,
|
||||
ITEM_TELEMETRY_TOP_BAR_VOLTAGE,
|
||||
ITEM_TELEMETRY_TOP_BAR_ALTITUDE,
|
||||
ITEM_TELEMETRY_SCREEN_LABEL1,
|
||||
ITEM_TELEMETRY_SCREEN_LINE1,
|
||||
ITEM_TELEMETRY_SCREEN_LINE2,
|
||||
ITEM_TELEMETRY_SCREEN_LINE3,
|
||||
ITEM_TELEMETRY_SCREEN_LINE4,
|
||||
ITEM_TELEMETRY_SCREEN_LABEL2,
|
||||
ITEM_TELEMETRY_SCREEN_LINE5,
|
||||
ITEM_TELEMETRY_SCREEN_LINE6,
|
||||
ITEM_TELEMETRY_SCREEN_LINE7,
|
||||
ITEM_TELEMETRY_SCREEN_LINE8,
|
||||
ITEM_TELEMETRY_SCREEN_LABEL3,
|
||||
ITEM_TELEMETRY_SCREEN_LINE9,
|
||||
ITEM_TELEMETRY_SCREEN_LINE10,
|
||||
ITEM_TELEMETRY_SCREEN_LINE11,
|
||||
ITEM_TELEMETRY_SCREEN_LINE12,
|
||||
ITEM_TELEMETRY_SCREEN_LABEL4,
|
||||
ITEM_TELEMETRY_SCREEN_LINE13,
|
||||
ITEM_TELEMETRY_SCREEN_LINE14,
|
||||
ITEM_TELEMETRY_SCREEN_LINE15,
|
||||
ITEM_TELEMETRY_SCREEN_LINE16,
|
||||
ITEM_TELEMETRY_MAX
|
||||
};
|
||||
|
||||
#define TELEM_COL1 10
|
||||
#define TELEM_COL2 150
|
||||
#define TELEM_COL3 200
|
||||
#define TELEM_SCRTYPE_COL TELEM_COL2
|
||||
|
||||
#define IF_FAS_OFFSET(x) x,
|
||||
#define IS_RANGE_DEFINED(k) (g_model.frsky.channels[k].ratio > 0)
|
||||
|
||||
#define SENSOR_ROWS(x) (isTelemetryFieldAvailable(x) ? (uint8_t)0 : HIDDEN_ROW)
|
||||
#define SENSORS_ROWS LABEL(Sensors), SENSOR_ROWS(0), SENSOR_ROWS(1), SENSOR_ROWS(2), SENSOR_ROWS(3), SENSOR_ROWS(4), SENSOR_ROWS(5), SENSOR_ROWS(6), SENSOR_ROWS(7), SENSOR_ROWS(8), SENSOR_ROWS(9), SENSOR_ROWS(10), SENSOR_ROWS(11), SENSOR_ROWS(12), SENSOR_ROWS(13), SENSOR_ROWS(14), SENSOR_ROWS(15), SENSOR_ROWS(16), SENSOR_ROWS(17), SENSOR_ROWS(18), SENSOR_ROWS(19), SENSOR_ROWS(20), SENSOR_ROWS(21), SENSOR_ROWS(22), SENSOR_ROWS(23), SENSOR_ROWS(24), SENSOR_ROWS(25), SENSOR_ROWS(26), SENSOR_ROWS(27), SENSOR_ROWS(28), SENSOR_ROWS(29), SENSOR_ROWS(30), SENSOR_ROWS(31), 0,
|
||||
#define USRDATA_ROWS
|
||||
#define RSSI_ROWS LABEL(RSSI), 0, 0,
|
||||
#if defined(LUA)
|
||||
#define SCREEN_TYPE_ROWS 1
|
||||
#else
|
||||
#define SCREEN_TYPE_ROWS 0
|
||||
#endif
|
||||
#define VARIO_RANGE_ROWS 3
|
||||
|
||||
#define TELEMETRY_TYPE_ROWS (g_model.externalModule == MODULE_TYPE_PPM ? (uint8_t)0 : HIDDEN_ROW),
|
||||
|
||||
#if defined(LUA)
|
||||
#define TELEMETRY_SCREEN_LINE(x) ((TELEMETRY_SCREEN_TYPE(x) == TELEMETRY_SCREEN_TYPE_NONE || TELEMETRY_SCREEN_TYPE(x) == TELEMETRY_SCREEN_TYPE_SCRIPT) ? HIDDEN_ROW : (uint8_t)2)
|
||||
#else
|
||||
#define TELEMETRY_SCREEN_LINE(x) (TELEMETRY_SCREEN_TYPE(x) == TELEMETRY_SCREEN_TYPE_NONE ? HIDDEN_ROW : (uint8_t)2)
|
||||
#endif
|
||||
#define TELEMETRY_SCREEN_ROWS(x) SCREEN_TYPE_ROWS, TELEMETRY_SCREEN_LINE(x), TELEMETRY_SCREEN_LINE(x), TELEMETRY_SCREEN_LINE(x), TELEMETRY_SCREEN_LINE(x)
|
||||
#define TELEMETRY_CURRENT_EDIT_SCREEN(k) (k < ITEM_TELEMETRY_SCREEN_LABEL2 ? 0 : (k < ITEM_TELEMETRY_SCREEN_LABEL3 ? 1 : (k < ITEM_TELEMETRY_SCREEN_LABEL4 ? 2 : 3)))
|
||||
|
||||
enum SensorFields {
|
||||
SENSOR_FIELD_NAME,
|
||||
SENSOR_FIELD_TYPE,
|
||||
SENSOR_FIELD_ID,
|
||||
SENSOR_FIELD_FORMULA=SENSOR_FIELD_ID,
|
||||
SENSOR_FIELD_UNIT,
|
||||
SENSOR_FIELD_PRECISION,
|
||||
SENSOR_FIELD_PARAM1,
|
||||
SENSOR_FIELD_PARAM2,
|
||||
SENSOR_FIELD_PARAM3,
|
||||
SENSOR_FIELD_PARAM4,
|
||||
SENSOR_FIELD_AUTOOFFSET,
|
||||
SENSOR_FIELD_FILTER,
|
||||
SENSOR_FIELD_PERSISTENT,
|
||||
SENSOR_FIELD_LOGS,
|
||||
SENSOR_FIELD_MAX
|
||||
};
|
||||
|
||||
bool isSensorUnit(int sensor, uint8_t unit)
|
||||
{
|
||||
if (sensor == 0)
|
||||
return true;
|
||||
|
||||
sensor -= 1;
|
||||
|
||||
return g_model.telemetrySensors[sensor].unit == unit;
|
||||
}
|
||||
|
||||
bool isCellsSensor(int sensor)
|
||||
{
|
||||
return isSensorUnit(sensor, UNIT_CELLS);
|
||||
}
|
||||
|
||||
bool isGPSSensor(int sensor)
|
||||
{
|
||||
return isSensorUnit(sensor, UNIT_GPS);
|
||||
}
|
||||
|
||||
bool isAltSensor(int sensor)
|
||||
{
|
||||
return isSensorUnit(sensor, UNIT_DIST);
|
||||
}
|
||||
|
||||
bool isVoltsSensor(int sensor)
|
||||
{
|
||||
return isSensorUnit(sensor, UNIT_VOLTS) || isSensorUnit(sensor, UNIT_CELLS);
|
||||
}
|
||||
|
||||
bool isCurrentSensor(int sensor)
|
||||
{
|
||||
return isSensorUnit(sensor, UNIT_AMPS);
|
||||
}
|
||||
|
||||
bool isSensorAvailable(int sensor)
|
||||
{
|
||||
if (sensor == 0)
|
||||
return true;
|
||||
else
|
||||
return isTelemetryFieldAvailable(abs(sensor) - 1);
|
||||
}
|
||||
|
||||
#define SENSOR_2ND_COLUMN 80
|
||||
#define SENSOR_3RD_COLUMN 120
|
||||
|
||||
#define SENSOR_UNIT_ROWS (sensor->isConfigurable() ? (uint8_t)0 : HIDDEN_ROW)
|
||||
#define SENSOR_PREC_ROWS (sensor->isConfigurable() ? (uint8_t)0 : HIDDEN_ROW)
|
||||
#define SENSOR_PARAM1_ROWS (sensor->unit >= UNIT_FIRST_VIRTUAL ? HIDDEN_ROW : (uint8_t)0)
|
||||
#define SENSOR_PARAM2_ROWS (sensor->unit == UNIT_RPMS || sensor->unit == UNIT_GPS || sensor->unit == UNIT_DATETIME || sensor->unit == UNIT_CELLS || (sensor->type==TELEM_TYPE_CALCULATED && (sensor->formula==TELEM_FORMULA_CONSUMPTION || sensor->formula==TELEM_FORMULA_TOTALIZE)) ? HIDDEN_ROW : (uint8_t)0)
|
||||
#define SENSOR_PARAM3_ROWS (sensor->type == TELEM_TYPE_CALCULATED && sensor->formula < TELEM_FORMULA_MULTIPLY) ? (uint8_t)0 : HIDDEN_ROW
|
||||
#define SENSOR_PARAM4_ROWS (sensor->type == TELEM_TYPE_CALCULATED && sensor->formula < TELEM_FORMULA_MULTIPLY) ? (uint8_t)0 : HIDDEN_ROW
|
||||
#define SENSOR_AUTOOFFSET_ROWS (sensor->isConfigurable() ? (uint8_t)0 : HIDDEN_ROW)
|
||||
#define SENSOR_FILTER_ROWS (sensor->isConfigurable() ? (uint8_t)0 : HIDDEN_ROW)
|
||||
#define SENSOR_PERSISTENT_ROWS (sensor->isConfigurable() ? (uint8_t)0 : HIDDEN_ROW)
|
||||
|
||||
void menuModelSensor(evt_t event)
|
||||
{
|
||||
TelemetrySensor *sensor = &g_model.telemetrySensors[s_currIdx];
|
||||
|
||||
SUBMENU(STR_MENUSENSOR, SENSOR_FIELD_MAX, DEFAULT_SCROLLBAR_X, { 0, 0, sensor->type == TELEM_TYPE_CALCULATED ? (uint8_t)0 : (uint8_t)1, SENSOR_UNIT_ROWS, SENSOR_PREC_ROWS, SENSOR_PARAM1_ROWS, SENSOR_PARAM2_ROWS, SENSOR_PARAM3_ROWS, SENSOR_PARAM4_ROWS, 0 });
|
||||
|
||||
lcd_outdezAtt(MENU_TITLE_LEFT+getTextWidth(TR_MENUSENSOR)+5, MENU_FOOTER_TOP, s_currIdx+1, HEADER_COLOR|LEFT);
|
||||
putsTelemetryChannelValue(SENSOR_2ND_COLUMN, MENU_FOOTER_TOP, s_currIdx, getValue(MIXSRC_FIRST_TELEM+3*s_currIdx), HEADER_COLOR|LEFT);
|
||||
|
||||
int sub = m_posVert;
|
||||
|
||||
for (unsigned int i=0; i<NUM_BODY_LINES; i++) {
|
||||
coord_t y = MENU_CONTENT_TOP + i*FH;
|
||||
int k = i + s_pgOfs;
|
||||
|
||||
for (int j=0; j<k; j++) {
|
||||
if (mstate_tab[j+1] == HIDDEN_ROW)
|
||||
k++;
|
||||
}
|
||||
|
||||
LcdFlags attr = (sub==k ? (s_editMode>0 ? BLINK|INVERS : INVERS) : 0);
|
||||
|
||||
switch (k) {
|
||||
|
||||
case SENSOR_FIELD_NAME:
|
||||
editSingleName(SENSOR_2ND_COLUMN, y, STR_NAME, sensor->label, TELEM_LABEL_LEN, event, attr);
|
||||
break;
|
||||
|
||||
case SENSOR_FIELD_TYPE:
|
||||
sensor->type = selectMenuItem(SENSOR_2ND_COLUMN, y, NO_INDENT(STR_TYPE), STR_VSENSORTYPES, sensor->type, 0, 1, attr, event);
|
||||
if (attr && checkIncDec_Ret) {
|
||||
sensor->instance = 0;
|
||||
if (sensor->type == TELEM_TYPE_CALCULATED) {
|
||||
sensor->param = 0;
|
||||
sensor->filter = 0;
|
||||
sensor->autoOffset = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case SENSOR_FIELD_ID:
|
||||
if (sensor->type == TELEM_TYPE_CUSTOM) {
|
||||
lcd_putsLeft(y, STR_ID);
|
||||
lcd_outhex4(SENSOR_2ND_COLUMN, y, sensor->id, LEFT|(m_posHorz==0 ? attr : 0));
|
||||
lcd_outdezAtt(SENSOR_3RD_COLUMN, y, sensor->instance, LEFT|(m_posHorz==1 ? attr : 0));
|
||||
if (attr) {
|
||||
switch (m_posHorz) {
|
||||
case 0:
|
||||
CHECK_INCDEC_MODELVAR_ZERO(event, sensor->id, 0xffff);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
CHECK_INCDEC_MODELVAR_ZERO(event, sensor->instance, 0xff);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
sensor->formula = selectMenuItem(SENSOR_2ND_COLUMN, y, STR_FORMULA, STR_VFORMULAS, sensor->formula, 0, TELEM_FORMULA_LAST, attr, event);
|
||||
if (attr && checkIncDec_Ret) {
|
||||
sensor->param = 0;
|
||||
if (sensor->formula == TELEM_FORMULA_CELL) {
|
||||
sensor->unit = UNIT_VOLTS;
|
||||
sensor->prec = 2;
|
||||
}
|
||||
else if (sensor->formula == TELEM_FORMULA_DIST) {
|
||||
sensor->unit = UNIT_DIST;
|
||||
sensor->prec = 0;
|
||||
}
|
||||
else if (sensor->formula == TELEM_FORMULA_CONSUMPTION) {
|
||||
sensor->unit = UNIT_MAH;
|
||||
sensor->prec = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case SENSOR_FIELD_UNIT:
|
||||
lcd_putsLeft(y, STR_UNIT);
|
||||
// TODO flash saving with selectMenuItem where I copied those 2 lines?
|
||||
lcd_putsiAtt(SENSOR_2ND_COLUMN, y, STR_VTELEMUNIT, sensor->unit, attr);
|
||||
if (attr) {
|
||||
CHECK_INCDEC_MODELVAR_ZERO(event, sensor->unit, UNIT_MAX);
|
||||
if (checkIncDec_Ret) {
|
||||
telemetryItems[s_currIdx].clear();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case SENSOR_FIELD_PRECISION:
|
||||
sensor->prec = selectMenuItem(SENSOR_2ND_COLUMN, y, STR_PRECISION, STR_VPREC, sensor->prec, 0, 2, attr, event);
|
||||
if (attr && checkIncDec_Ret) {
|
||||
telemetryItems[s_currIdx].clear();
|
||||
}
|
||||
break;
|
||||
|
||||
case SENSOR_FIELD_PARAM1:
|
||||
if (sensor->type == TELEM_TYPE_CALCULATED) {
|
||||
if (sensor->formula == TELEM_FORMULA_CELL) {
|
||||
lcd_putsLeft(y, STR_CELLSENSOR);
|
||||
putsMixerSource(SENSOR_2ND_COLUMN, y, sensor->cell.source ? MIXSRC_FIRST_TELEM+3*(sensor->cell.source-1) : 0, attr);
|
||||
if (attr) {
|
||||
sensor->cell.source = checkIncDec(event, sensor->cell.source, 0, MAX_SENSORS, EE_MODEL|NO_INCDEC_MARKS, isCellsSensor);
|
||||
}
|
||||
break;
|
||||
}
|
||||
else if (sensor->formula == TELEM_FORMULA_DIST) {
|
||||
lcd_putsLeft(y, "GPS sensor");
|
||||
putsMixerSource(SENSOR_2ND_COLUMN, y, sensor->dist.gps ? MIXSRC_FIRST_TELEM+3*(sensor->dist.gps-1) : 0, attr);
|
||||
if (attr) {
|
||||
sensor->dist.gps = checkIncDec(event, sensor->dist.gps, 0, MAX_SENSORS, EE_MODEL|NO_INCDEC_MARKS, isGPSSensor);
|
||||
}
|
||||
break;
|
||||
}
|
||||
else if (sensor->formula == TELEM_FORMULA_CONSUMPTION) {
|
||||
lcd_putsLeft(y, "Amps sensor");
|
||||
putsMixerSource(SENSOR_2ND_COLUMN, y, sensor->consumption.source ? MIXSRC_FIRST_TELEM+3*(sensor->consumption.source-1) : 0, attr);
|
||||
if (attr) {
|
||||
sensor->consumption.source = checkIncDec(event, sensor->consumption.source, 0, MAX_SENSORS, EE_MODEL|NO_INCDEC_MARKS, isCurrentSensor);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
lcd_putsLeft(y, "Ratio");
|
||||
if (attr) CHECK_INCDEC_MODELVAR(event, sensor->custom.ratio, 0, 30000);
|
||||
if (sensor->custom.ratio == 0)
|
||||
lcd_putsAtt(SENSOR_2ND_COLUMN, y, "-", attr);
|
||||
else
|
||||
lcd_outdezAtt(SENSOR_2ND_COLUMN, y, sensor->custom.ratio, LEFT|attr|PREC1);
|
||||
break;
|
||||
}
|
||||
// no break
|
||||
|
||||
case SENSOR_FIELD_PARAM2:
|
||||
if (sensor->type == TELEM_TYPE_CALCULATED) {
|
||||
if (sensor->formula == TELEM_FORMULA_CELL) {
|
||||
sensor->cell.index = selectMenuItem(SENSOR_2ND_COLUMN, y, "Cell index", "\007Lowest\0001\0 2\0 3\0 4\0 5\0 6\0 HighestDelta\0", sensor->cell.index, 0, 8, attr, event);
|
||||
break;
|
||||
}
|
||||
else if (sensor->formula == TELEM_FORMULA_DIST) {
|
||||
lcd_putsLeft(y, "Alt sensor");
|
||||
putsMixerSource(SENSOR_2ND_COLUMN, y, sensor->dist.alt ? MIXSRC_FIRST_TELEM+3*(sensor->dist.alt-1) : 0, attr);
|
||||
if (attr) {
|
||||
sensor->dist.alt = checkIncDec(event, sensor->dist.alt, 0, MAX_SENSORS, EE_MODEL|NO_INCDEC_MARKS, isAltSensor);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
lcd_putsLeft(y, NO_INDENT(STR_OFFSET));
|
||||
if (attr) CHECK_INCDEC_MODELVAR(event, sensor->custom.offset, -30000, +30000);
|
||||
if (sensor->prec > 0) attr |= (sensor->prec == 2 ? PREC2 : PREC1);
|
||||
lcd_outdezAtt(SENSOR_2ND_COLUMN, y, sensor->custom.offset, LEFT|attr);
|
||||
break;
|
||||
}
|
||||
// no break
|
||||
|
||||
case SENSOR_FIELD_PARAM3:
|
||||
// no break
|
||||
|
||||
case SENSOR_FIELD_PARAM4:
|
||||
{
|
||||
putsStrIdx(MENU_TITLE_LEFT, y, NO_INDENT(STR_SOURCE), k-SENSOR_FIELD_PARAM1+1);
|
||||
int8_t & source = sensor->calc.sources[k-SENSOR_FIELD_PARAM1];
|
||||
if (attr) {
|
||||
source = checkIncDec(event, source, -MAX_SENSORS, MAX_SENSORS, EE_MODEL|NO_INCDEC_MARKS, isSensorAvailable);
|
||||
}
|
||||
if (source < 0) {
|
||||
lcd_putsAtt(SENSOR_2ND_COLUMN, y, "-", attr);
|
||||
putsMixerSource(SENSOR_2ND_COLUMN+5, y, MIXSRC_FIRST_TELEM+3*(-1-source), attr);
|
||||
}
|
||||
else {
|
||||
putsMixerSource(SENSOR_2ND_COLUMN, y, source ? MIXSRC_FIRST_TELEM+3*(source-1) : 0, attr);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case SENSOR_FIELD_AUTOOFFSET:
|
||||
ON_OFF_MENU_ITEM(sensor->autoOffset, SENSOR_2ND_COLUMN, y, STR_AUTOOFFSET, attr, event);
|
||||
break;
|
||||
|
||||
case SENSOR_FIELD_FILTER:
|
||||
ON_OFF_MENU_ITEM(sensor->filter, SENSOR_2ND_COLUMN, y, STR_FILTER, attr, event);
|
||||
break;
|
||||
|
||||
case SENSOR_FIELD_PERSISTENT:
|
||||
ON_OFF_MENU_ITEM(sensor->persistent, SENSOR_2ND_COLUMN, y, NO_INDENT(STR_PERSISTENT), attr, event);
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void onSensorMenu(const char *result)
|
||||
{
|
||||
uint8_t index = m_posVert - ITEM_TELEMETRY_SENSOR1;
|
||||
|
||||
if (index < MAX_SENSORS) {
|
||||
if (result == STR_EDIT) {
|
||||
pushMenu(menuModelSensor);
|
||||
}
|
||||
else if (result == STR_DELETE) {
|
||||
delTelemetryIndex(index);
|
||||
index += 1;
|
||||
if (index<MAX_SENSORS && isTelemetryFieldAvailable(index))
|
||||
m_posVert += 1;
|
||||
else
|
||||
m_posVert = 1+ITEM_TELEMETRY_NEWSENSOR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(LUA)
|
||||
void onTelemetryScriptFileSelectionMenu(const char *result)
|
||||
{
|
||||
int8_t sub = m_posVert;
|
||||
uint8_t screenIndex = TELEMETRY_CURRENT_EDIT_SCREEN(sub);
|
||||
|
||||
if (result == STR_UPDATE_LIST) {
|
||||
if (!listSdFiles(SCRIPTS_TELEM_PATH, SCRIPTS_EXT, sizeof(g_model.frsky.screens[screenIndex].script.file), NULL)) {
|
||||
POPUP_WARNING(STR_NO_SCRIPTS_ON_SD);
|
||||
s_menu_flags = 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// The user choosed a file in the list
|
||||
memcpy(g_model.frsky.screens[screenIndex].script.file, result, sizeof(g_model.frsky.screens[screenIndex].script.file));
|
||||
eeDirty(EE_MODEL);
|
||||
LUA_LOAD_MODEL_SCRIPTS();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void menuModelTelemetry(evt_t event)
|
||||
{
|
||||
MENU(STR_MENUTELEMETRY, menuTabModel, e_Telemetry, ITEM_TELEMETRY_MAX, DEFAULT_SCROLLBAR_X, { TELEMETRY_TYPE_ROWS RSSI_ROWS SENSORS_ROWS USRDATA_ROWS CASE_VARIO(LABEL(Vario)) CASE_VARIO(0) CASE_VARIO(VARIO_RANGE_ROWS) LABEL(TopBar), 0, 0, TELEMETRY_SCREEN_ROWS(0), TELEMETRY_SCREEN_ROWS(1), TELEMETRY_SCREEN_ROWS(2), TELEMETRY_SCREEN_ROWS(3) });
|
||||
|
||||
int sub = m_posVert;
|
||||
|
||||
for (int i=0; i<NUM_BODY_LINES; i++) {
|
||||
coord_t y = MENU_CONTENT_TOP + i*FH;
|
||||
int k = i + s_pgOfs;
|
||||
for (int j=0; j<=k; j++) {
|
||||
if (mstate_tab[j] == HIDDEN_ROW)
|
||||
k++;
|
||||
}
|
||||
|
||||
LcdFlags blink = ((s_editMode>0) ? BLINK|INVERS : INVERS);
|
||||
LcdFlags attr = (sub == k ? blink : 0);
|
||||
|
||||
if (k>=ITEM_TELEMETRY_SENSOR1 && k<ITEM_TELEMETRY_SENSOR1+MAX_SENSORS) {
|
||||
int index = k-ITEM_TELEMETRY_SENSOR1;
|
||||
lcd_outdezAtt(MENU_TITLE_LEFT+INDENT_WIDTH, y, index+1, LEFT|attr, ":");
|
||||
lcd_putsnAtt(60, y, g_model.telemetrySensors[index].label, TELEM_LABEL_LEN, ZCHAR);
|
||||
if (telemetryItems[index].isFresh()) {
|
||||
lcd_puts(100, y, "*");
|
||||
}
|
||||
TelemetryItem & telemetryItem = telemetryItems[index];
|
||||
if (telemetryItem.isAvailable()) {
|
||||
LcdFlags color = telemetryItem.isOld() ? RED : WHITE;
|
||||
putsTelemetryChannelValue(TELEM_COL2, y, index, getValue(MIXSRC_FIRST_TELEM+3*index), LEFT|color);
|
||||
}
|
||||
else {
|
||||
lcd_puts(TELEM_COL2, y, "---"); // TODO shortcut
|
||||
}
|
||||
if (attr) {
|
||||
s_editMode = 0;
|
||||
s_currIdx = index;
|
||||
if (event == EVT_KEY_LONG(KEY_ENTER)) {
|
||||
killEvents(event);
|
||||
MENU_ADD_ITEM(STR_EDIT);
|
||||
MENU_ADD_ITEM(STR_DELETE);
|
||||
menuHandler = onSensorMenu;
|
||||
}
|
||||
else if (event == EVT_KEY_BREAK(KEY_ENTER)) {
|
||||
pushMenu(menuModelSensor);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
switch (k) {
|
||||
case ITEM_TELEMETRY_PROTOCOL_TYPE:
|
||||
g_model.telemetryProtocol = selectMenuItem(TELEM_COL2, y, STR_TELEMETRY_TYPE, "\017FrSky S.PORT\0 FrSky D\0 FrSky D (cable)", g_model.telemetryProtocol, PROTOCOL_TELEMETRY_FIRST, PROTOCOL_FRSKY_D, attr, event);
|
||||
break;
|
||||
|
||||
case ITEM_TELEMETRY_SENSORS_LABEL:
|
||||
lcd_putsLeft(y, STR_TELEMETRY_SENSORS);
|
||||
break;
|
||||
|
||||
case ITEM_TELEMETRY_NEWSENSOR:
|
||||
lcd_putsAtt(MENU_TITLE_LEFT+INDENT_WIDTH, y, NO_INDENT(STR_TELEMETRY_NEWSENSOR), attr);
|
||||
if (attr && event==EVT_KEY_BREAK(KEY_ENTER)) {
|
||||
s_editMode = 0;
|
||||
int res = availableTelemetryIndex();
|
||||
if (res >= 0) {
|
||||
s_currIdx = res;
|
||||
pushMenu(menuModelSensor);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ITEM_TELEMETRY_RSSI_LABEL:
|
||||
lcd_putsLeft(y, PSTR("RSSI"));
|
||||
break;
|
||||
|
||||
case ITEM_TELEMETRY_RSSI_ALARM1:
|
||||
case ITEM_TELEMETRY_RSSI_ALARM2: {
|
||||
uint8_t alarm = k-ITEM_TELEMETRY_RSSI_ALARM1;
|
||||
lcd_putsLeft(y, (alarm==0 ? STR_LOWALARM : STR_CRITICALALARM));
|
||||
lcd_outdezNAtt(TELEM_COL2, y, getRssiAlarmValue(alarm), LEFT|attr, 3);
|
||||
if (attr && s_editMode>0) {
|
||||
CHECK_INCDEC_MODELVAR(event, g_model.frsky.rssiAlarms[alarm].value, -30, 30);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
#if defined(VARIO)
|
||||
case ITEM_TELEMETRY_VARIO_LABEL:
|
||||
lcd_putsLeft(y, STR_VARIO);
|
||||
break;
|
||||
|
||||
case ITEM_TELEMETRY_VARIO_SOURCE:
|
||||
lcd_putsLeft(y, STR_SOURCE);
|
||||
putsMixerSource(TELEM_COL2, y, g_model.frsky.varioSource ? MIXSRC_FIRST_TELEM+3*(g_model.frsky.varioSource-1) : 0, attr);
|
||||
if (attr) {
|
||||
g_model.frsky.varioSource = checkIncDec(event, g_model.frsky.varioSource, 0, MAX_SENSORS, EE_MODEL|NO_INCDEC_MARKS, isSensorAvailable);
|
||||
}
|
||||
break;
|
||||
|
||||
case ITEM_TELEMETRY_VARIO_RANGE:
|
||||
lcd_putsLeft(y, STR_LIMIT);
|
||||
lcd_outdezAtt(TELEM_COL2, y, -10+g_model.frsky.varioMin, (m_posHorz<=0 ? attr : 0)|LEFT);
|
||||
lcd_outdezAtt(TELEM_COL2+50, y, -5+g_model.frsky.varioCenterMin, ((CURSOR_ON_LINE() || m_posHorz==1) ? attr : 0)|PREC1);
|
||||
lcd_outdezAtt(TELEM_COL2+75, y, 5+g_model.frsky.varioCenterMax, ((CURSOR_ON_LINE() || m_posHorz==2) ? attr : 0)|PREC1);
|
||||
lcd_outdezAtt(TELEM_COL2+100, y, 10+g_model.frsky.varioMax, ((CURSOR_ON_LINE() || m_posHorz==3) ? attr : 0));
|
||||
if (attr && s_editMode>0) {
|
||||
switch (m_posHorz) {
|
||||
case 0:
|
||||
CHECK_INCDEC_MODELVAR(event, g_model.frsky.varioMin, -7, 7);
|
||||
break;
|
||||
case 1:
|
||||
CHECK_INCDEC_MODELVAR(event, g_model.frsky.varioCenterMin, -16, 5+min<int8_t>(10, g_model.frsky.varioCenterMax+5));
|
||||
break;
|
||||
case 2:
|
||||
CHECK_INCDEC_MODELVAR(event, g_model.frsky.varioCenterMax, -5+max<int8_t>(-10, g_model.frsky.varioCenterMin-5), +15);
|
||||
break;
|
||||
case 3:
|
||||
CHECK_INCDEC_MODELVAR(event, g_model.frsky.varioMax, -7, 7);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
case ITEM_TELEMETRY_TOP_BAR_LABEL:
|
||||
lcd_putsLeft(y, "Main Telemetry Fields");
|
||||
break;
|
||||
|
||||
case ITEM_TELEMETRY_TOP_BAR_VOLTAGE:
|
||||
lcd_putsLeft(y, STR_VOLTAGE);
|
||||
putsMixerSource(TELEM_COL2, y, g_model.frsky.voltsSource ? MIXSRC_FIRST_TELEM+3*(g_model.frsky.voltsSource-1) : 0, attr);
|
||||
if (attr) {
|
||||
g_model.frsky.voltsSource = checkIncDec(event, g_model.frsky.voltsSource, 0, MAX_SENSORS, EE_MODEL|NO_INCDEC_MARKS, isVoltsSensor);
|
||||
}
|
||||
break;
|
||||
|
||||
case ITEM_TELEMETRY_TOP_BAR_ALTITUDE:
|
||||
lcd_putsLeft(y, INDENT "Altitude Source");
|
||||
putsMixerSource(TELEM_COL2, y, g_model.frsky.altitudeSource ? MIXSRC_FIRST_TELEM+3*(g_model.frsky.altitudeSource-1) : 0, attr);
|
||||
if (attr) {
|
||||
g_model.frsky.altitudeSource = checkIncDec(event, g_model.frsky.altitudeSource, 0, MAX_SENSORS, EE_MODEL|NO_INCDEC_MARKS, isAltSensor);
|
||||
}
|
||||
break;
|
||||
|
||||
case ITEM_TELEMETRY_SCREEN_LABEL1:
|
||||
case ITEM_TELEMETRY_SCREEN_LABEL2:
|
||||
case ITEM_TELEMETRY_SCREEN_LABEL3:
|
||||
case ITEM_TELEMETRY_SCREEN_LABEL4:
|
||||
{
|
||||
uint8_t screenIndex = TELEMETRY_CURRENT_EDIT_SCREEN(k);
|
||||
putsStrIdx(MENU_TITLE_LEFT, y, STR_SCREEN, screenIndex+1);
|
||||
TelemetryScreenType oldScreenType = TELEMETRY_SCREEN_TYPE(screenIndex);
|
||||
TelemetryScreenType newScreenType = (TelemetryScreenType)selectMenuItem(TELEM_SCRTYPE_COL, y, PSTR(""), STR_VTELEMSCREENTYPE, oldScreenType, 0, TELEMETRY_SCREEN_TYPE_MAX, (m_posHorz==0 ? attr : 0), event);
|
||||
if (newScreenType != oldScreenType) {
|
||||
g_model.frsky.screensType = (g_model.frsky.screensType & (~(0x03 << (2*screenIndex)))) | (newScreenType << (2*screenIndex));
|
||||
memset(&g_model.frsky.screens[screenIndex], 0, sizeof(g_model.frsky.screens[screenIndex]));
|
||||
}
|
||||
#if defined(LUA)
|
||||
if (newScreenType == TELEMETRY_SCREEN_TYPE_SCRIPT) {
|
||||
TelemetryScriptData & scriptData = g_model.frsky.screens[screenIndex].script;
|
||||
|
||||
// TODO better function name for ---
|
||||
// TODO function for these lines
|
||||
if (ZEXIST(scriptData.file))
|
||||
lcd_putsnAtt(TELEM_SCRTYPE_COL+70, y, scriptData.file, sizeof(scriptData.file), (m_posHorz==1 ? attr : 0));
|
||||
else
|
||||
lcd_putsiAtt(TELEM_SCRTYPE_COL+70, y, STR_VCSWFUNC, 0, (m_posHorz==1 ? attr : 0));
|
||||
|
||||
if (m_posHorz==1 && attr && event==EVT_KEY_BREAK(KEY_ENTER) && READ_ONLY_UNLOCKED()) {
|
||||
s_editMode = 0;
|
||||
if (listSdFiles(SCRIPTS_TELEM_PATH, SCRIPTS_EXT, sizeof(g_model.frsky.screens[screenIndex].script.file), g_model.frsky.screens[screenIndex].script.file)) {
|
||||
menuHandler = onTelemetryScriptFileSelectionMenu;
|
||||
}
|
||||
else {
|
||||
POPUP_WARNING(STR_NO_SCRIPTS_ON_SD);
|
||||
s_menu_flags = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (attr) {
|
||||
MOVE_CURSOR_FROM_HERE();
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
case ITEM_TELEMETRY_SCREEN_LINE1:
|
||||
case ITEM_TELEMETRY_SCREEN_LINE2:
|
||||
case ITEM_TELEMETRY_SCREEN_LINE3:
|
||||
case ITEM_TELEMETRY_SCREEN_LINE4:
|
||||
case ITEM_TELEMETRY_SCREEN_LINE5:
|
||||
case ITEM_TELEMETRY_SCREEN_LINE6:
|
||||
case ITEM_TELEMETRY_SCREEN_LINE7:
|
||||
case ITEM_TELEMETRY_SCREEN_LINE8:
|
||||
case ITEM_TELEMETRY_SCREEN_LINE9:
|
||||
case ITEM_TELEMETRY_SCREEN_LINE10:
|
||||
case ITEM_TELEMETRY_SCREEN_LINE11:
|
||||
case ITEM_TELEMETRY_SCREEN_LINE12:
|
||||
case ITEM_TELEMETRY_SCREEN_LINE13:
|
||||
case ITEM_TELEMETRY_SCREEN_LINE14:
|
||||
case ITEM_TELEMETRY_SCREEN_LINE15:
|
||||
case ITEM_TELEMETRY_SCREEN_LINE16:
|
||||
{
|
||||
uint8_t screenIndex, lineIndex;
|
||||
if (k < ITEM_TELEMETRY_SCREEN_LABEL2) {
|
||||
screenIndex = 0;
|
||||
lineIndex = k-ITEM_TELEMETRY_SCREEN_LINE1;
|
||||
}
|
||||
else if (k >= ITEM_TELEMETRY_SCREEN_LABEL4) {
|
||||
screenIndex = 3;
|
||||
lineIndex = k-ITEM_TELEMETRY_SCREEN_LINE13;
|
||||
}
|
||||
else if (k >= ITEM_TELEMETRY_SCREEN_LABEL3) {
|
||||
screenIndex = 2;
|
||||
lineIndex = k-ITEM_TELEMETRY_SCREEN_LINE9;
|
||||
}
|
||||
else {
|
||||
screenIndex = 1;
|
||||
lineIndex = k-ITEM_TELEMETRY_SCREEN_LINE5;
|
||||
}
|
||||
|
||||
#if defined(GAUGES)
|
||||
if (IS_BARS_SCREEN(screenIndex)) {
|
||||
FrSkyBarData & bar = g_model.frsky.screens[screenIndex].bars[lineIndex];
|
||||
source_t barSource = bar.source;
|
||||
putsMixerSource(MENU_TITLE_LEFT+INDENT_WIDTH, y, barSource, (m_posHorz==0 ? attr : 0));
|
||||
int barMax = getMaximumValue(barSource);
|
||||
int barMin = -barMax;
|
||||
if (barSource) {
|
||||
if (barSource <= MIXSRC_LAST_CH) {
|
||||
putsChannelValue(MENU_TITLE_LEFT+INDENT_WIDTH+100, y, barSource, calc100toRESX(bar.barMin), (m_posHorz==1 ? attr : 0) | LEFT);
|
||||
putsChannelValue(MENU_TITLE_LEFT+INDENT_WIDTH+200, y, barSource, calc100toRESX(bar.barMax), (m_posHorz==2 ? attr : 0) | LEFT);
|
||||
}
|
||||
else {
|
||||
putsChannelValue(MENU_TITLE_LEFT+INDENT_WIDTH+100, y, barSource, bar.barMin, (m_posHorz==1 ? attr : 0) | LEFT);
|
||||
putsChannelValue(MENU_TITLE_LEFT+INDENT_WIDTH+200, y, barSource, bar.barMax, (m_posHorz==2 ? attr : 0) | LEFT);
|
||||
}
|
||||
}
|
||||
else if (attr) {
|
||||
MOVE_CURSOR_FROM_HERE();
|
||||
}
|
||||
if (attr && s_editMode>0) {
|
||||
switch (m_posHorz) {
|
||||
case 0:
|
||||
bar.source = CHECK_INCDEC_MODELVAR_ZERO_CHECK(event, barSource, MIXSRC_LAST_TELEM, isSourceAvailable);
|
||||
if (checkIncDec_Ret) {
|
||||
if (barSource <= MIXSRC_LAST_CH) {
|
||||
bar.barMin = -100;
|
||||
bar.barMax = 100;
|
||||
}
|
||||
else {
|
||||
bar.barMin = 0;
|
||||
bar.barMax = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
bar.barMin = checkIncDec(event, bar.barMin, barMin, bar.barMax, EE_MODEL|NO_INCDEC_MARKS);
|
||||
break;
|
||||
case 2:
|
||||
bar.barMax = checkIncDec(event, bar.barMax, bar.barMin, barMax, EE_MODEL|NO_INCDEC_MARKS);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
for (int c=0; c<NUM_LINE_ITEMS; c++) {
|
||||
LcdFlags cellAttr = (m_posHorz==c ? attr : 0);
|
||||
source_t & value = g_model.frsky.screens[screenIndex].lines[lineIndex].sources[c];
|
||||
const coord_t pos[] = {MENU_TITLE_LEFT+INDENT_WIDTH, MENU_TITLE_LEFT+INDENT_WIDTH+100, MENU_TITLE_LEFT+INDENT_WIDTH+200};
|
||||
putsMixerSource(pos[c], y, value, cellAttr);
|
||||
if (cellAttr && s_editMode>0) {
|
||||
CHECK_INCDEC_MODELVAR_ZERO_CHECK(event, value, MIXSRC_LAST_TELEM, isSourceAvailable);
|
||||
}
|
||||
}
|
||||
if (attr && m_posHorz == NUM_LINE_ITEMS) {
|
||||
REPEAT_LAST_CURSOR_MOVE();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Authors (alphabetical order)
|
||||
* - Andre Bernet <bernet.andre@gmail.com>
|
||||
* - Andreas Weitl
|
||||
* - Bertrand Songis <bsongis@gmail.com>
|
||||
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
|
||||
* - Cameron Weeks <th9xer@gmail.com>
|
||||
* - Erez Raviv
|
||||
* - Gabriel Birkus
|
||||
* - Jean-Pierre Parisy
|
||||
* - Karl Szmutny
|
||||
* - Michael Blandford
|
||||
* - Michal Hlavinka
|
||||
* - Pat Mackenzie
|
||||
* - Philip Moss
|
||||
* - Rob Thomson
|
||||
* - Romolo Manfredini <romolo.manfredini@gmail.com>
|
||||
* - 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"
|
||||
|
||||
MenuFuncP g_menuStack[5];
|
||||
evt_t menuEvent = 0;
|
||||
uint8_t g_menuPos[4];
|
||||
uint8_t g_menuStackPtr = 0;
|
||||
|
||||
void popMenu()
|
||||
{
|
||||
assert(g_menuStackPtr>0);
|
||||
g_menuStackPtr = g_menuStackPtr-1;
|
||||
menuEvent = EVT_ENTRY_UP;
|
||||
}
|
||||
|
||||
void chainMenu(MenuFuncP newMenu)
|
||||
{
|
||||
g_menuStack[g_menuStackPtr] = newMenu;
|
||||
menuEvent = EVT_ENTRY;
|
||||
}
|
||||
|
||||
void pushMenu(MenuFuncP newMenu)
|
||||
{
|
||||
killEvents(KEY_ENTER);
|
||||
|
||||
if (g_menuStackPtr == 0) {
|
||||
if (newMenu == menuGeneralSetup)
|
||||
g_menuPos[0] = 1;
|
||||
if (newMenu == menuModelSelect)
|
||||
g_menuPos[0] = 0;
|
||||
}
|
||||
else {
|
||||
g_menuPos[g_menuStackPtr] = m_posVert;
|
||||
}
|
||||
|
||||
g_menuStackPtr++;
|
||||
|
||||
assert(g_menuStackPtr < DIM(g_menuStack));
|
||||
|
||||
g_menuStack[g_menuStackPtr] = newMenu;
|
||||
menuEvent = EVT_ENTRY;
|
||||
}
|
||||
|
||||
void menuModelNotes(evt_t event)
|
||||
{
|
||||
if (event == EVT_ENTRY) {
|
||||
strcpy(s_text_file, MODELS_PATH "/");
|
||||
char *buf = strcat_modelname(&s_text_file[sizeof(MODELS_PATH)], g_eeGeneral.currModel);
|
||||
strcpy(buf, TEXT_EXT);
|
||||
}
|
||||
|
||||
menuTextView(event);
|
||||
}
|
||||
|
||||
void pushModelNotes()
|
||||
{
|
||||
pushMenu(menuModelNotes);
|
||||
}
|
||||
@@ -0,0 +1,377 @@
|
||||
/*
|
||||
* Authors (alphabetical order)
|
||||
* - Andre Bernet <bernet.andre@gmail.com>
|
||||
* - Andreas Weitl
|
||||
* - Bertrand Songis <bsongis@gmail.com>
|
||||
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
|
||||
* - Cameron Weeks <th9xer@gmail.com>
|
||||
* - Erez Raviv
|
||||
* - Gabriel Birkus
|
||||
* - Jean-Pierre Parisy
|
||||
* - Karl Szmutny
|
||||
* - Michael Blandford
|
||||
* - Michal Hlavinka
|
||||
* - Pat Mackenzie
|
||||
* - Philip Moss
|
||||
* - Rob Thomson
|
||||
* - Romolo Manfredini <romolo.manfredini@gmail.com>
|
||||
* - 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 _MENUS_H_
|
||||
#define _MENUS_H_
|
||||
|
||||
#include "../../keys.h"
|
||||
|
||||
#define NO_HI_LEN 25
|
||||
|
||||
#if defined(TRANSLATIONS_FR)
|
||||
#define MENU_COLUMNS 1
|
||||
#define COLUMN_X 0
|
||||
#else
|
||||
#define MENU_COLUMNS 2
|
||||
#endif
|
||||
|
||||
#define MENUS_SCROLLBAR_WIDTH 2
|
||||
#define MENU_COLUMN2_X 180
|
||||
#define lcd_putsColumnLeft(x, y, str) lcd_puts((x > MENU_COLUMN2_X+MENU_TITLE_LEFT+68) ? MENU_COLUMN2_X+MENU_TITLE_LEFT : MENU_TITLE_LEFT, y, str)
|
||||
|
||||
typedef int16_t vertpos_t;
|
||||
|
||||
typedef evt_t & check_event_t;
|
||||
#define horzpos_t int8_t
|
||||
|
||||
extern vertpos_t m_posVert;
|
||||
extern horzpos_t m_posHorz;
|
||||
extern vertpos_t s_pgOfs;
|
||||
extern uint8_t s_noHi;
|
||||
extern uint8_t calibrationState;
|
||||
|
||||
void lcdDrawCheckBox(coord_t x, coord_t y, uint8_t value, LcdFlags attr);
|
||||
|
||||
typedef void (*MenuFuncP)(evt_t event);
|
||||
typedef void (*MenuFuncP_PROGMEM)(evt_t event);
|
||||
extern const MenuFuncP_PROGMEM menuTabModel[];
|
||||
extern const MenuFuncP_PROGMEM menuTabGeneral[];
|
||||
extern const MenuFuncP_PROGMEM menuTabTelemetry[];
|
||||
|
||||
extern MenuFuncP g_menuStack[5];
|
||||
extern uint8_t g_menuPos[4];
|
||||
extern uint8_t g_menuStackPtr;
|
||||
extern evt_t menuEvent;
|
||||
|
||||
/// goto given Menu, but substitute current menu in menuStack
|
||||
void chainMenu(MenuFuncP newMenu);
|
||||
/// goto given Menu, store current menu in menuStack
|
||||
void pushMenu(MenuFuncP newMenu);
|
||||
/// return to last menu in menustack
|
||||
void popMenu();
|
||||
///deliver address of last menu which was popped from
|
||||
inline MenuFuncP lastPopMenu()
|
||||
{
|
||||
return g_menuStack[g_menuStackPtr+1];
|
||||
}
|
||||
|
||||
void drawPotsBars();
|
||||
void doMainScreenGraphics();
|
||||
void menuFirstCalib(evt_t event);
|
||||
|
||||
void onMainViewMenu(const char *result);
|
||||
void menuMainView(evt_t event);
|
||||
void menuGeneralDiagAna(evt_t event);
|
||||
|
||||
void menuTelemetryFrsky(evt_t event);
|
||||
void menuGeneralSetup(evt_t event);
|
||||
void menuGeneralCalib(evt_t event);
|
||||
void menuCustomFunctions(evt_t event, CustomFunctionData * functions, CustomFunctionsContext & functionsContext);
|
||||
|
||||
void menuModelSelect(evt_t event);
|
||||
void menuModelCustomFunctions(evt_t event);
|
||||
void menuStatisticsView(evt_t event);
|
||||
void menuStatisticsDebug(evt_t event);
|
||||
void menuAboutView(evt_t event);
|
||||
|
||||
#if defined(DEBUG_TRACE_BUFFER)
|
||||
void menuTraceBuffer(evt_t event);
|
||||
#endif
|
||||
|
||||
void displaySlider(coord_t x, coord_t y, uint8_t value, uint8_t max, uint8_t attr);
|
||||
|
||||
void menuMainViewChannelsMonitor(evt_t event);
|
||||
void menuChannelsView(evt_t event);
|
||||
|
||||
extern int8_t checkIncDec_Ret; // global helper vars
|
||||
|
||||
#define EDIT_SELECT_MENU -1
|
||||
#define EDIT_SELECT_FIELD 0
|
||||
#define EDIT_MODIFY_FIELD 1
|
||||
#define EDIT_MODIFY_STRING 2
|
||||
extern int8_t s_editMode; // global editmode
|
||||
|
||||
// checkIncDec flags
|
||||
#define EE_GENERAL 0x01
|
||||
#define EE_MODEL 0x02
|
||||
#define NO_INCDEC_MARKS 0x04
|
||||
#define INCDEC_SWITCH 0x08
|
||||
#define INCDEC_SOURCE 0x10
|
||||
#define INCDEC_REP10 0x40
|
||||
#define NO_DBLKEYS 0x80
|
||||
|
||||
// mawrow special values
|
||||
#define TITLE_ROW ((uint8_t)-1)
|
||||
#define HIDDEN_ROW ((uint8_t)-2)
|
||||
|
||||
typedef bool (*IsValueAvailable)(int);
|
||||
struct CheckIncDecStops {
|
||||
const int count;
|
||||
const int stops[];
|
||||
int min() const
|
||||
{
|
||||
return stops[0];
|
||||
}
|
||||
int max() const
|
||||
{
|
||||
return stops[count-1];
|
||||
}
|
||||
bool contains(int value) const
|
||||
{
|
||||
for (int i=0; i<count; ++i) {
|
||||
int stop = stops[i];
|
||||
if (value == stop)
|
||||
return true;
|
||||
else if (value < stop)
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
extern const CheckIncDecStops &stops100;
|
||||
extern const CheckIncDecStops &stops1000;
|
||||
extern const CheckIncDecStops &stopsSwitch;
|
||||
|
||||
#define INIT_STOPS(var, ...) \
|
||||
const int _ ## var[] = { __VA_ARGS__ }; \
|
||||
const CheckIncDecStops &var = (const CheckIncDecStops&)_ ## var;
|
||||
#define CATEGORY_END(val) \
|
||||
(val), (val+1)
|
||||
|
||||
int checkIncDec(evt_t event, int val, int i_min, int i_max, unsigned int i_flags=0, IsValueAvailable isValueAvailable=NULL, const CheckIncDecStops &stops=stops100);
|
||||
int8_t checkIncDecMovedSwitch(int8_t val);
|
||||
#define checkIncDecModel(event, i_val, i_min, i_max) checkIncDec(event, i_val, i_min, i_max, EE_MODEL)
|
||||
#define checkIncDecModelZero(event, i_val, i_max) checkIncDec(event, i_val, 0, i_max, EE_MODEL)
|
||||
#define checkIncDecGen(event, i_val, i_min, i_max) checkIncDec(event, i_val, i_min, i_max, EE_GENERAL)
|
||||
|
||||
#define CHECK_INCDEC_MODELVAR(event, var, min, max) \
|
||||
var = checkIncDecModel(event, var, min, max)
|
||||
|
||||
#define CHECK_INCDEC_MODELVAR_ZERO(event, var, max) \
|
||||
var = checkIncDecModelZero(event, var, max)
|
||||
|
||||
#define CHECK_INCDEC_MODELVAR_CHECK(event, var, min, max, check) \
|
||||
var = checkIncDec(event, var, min, max, EE_MODEL, check)
|
||||
|
||||
#define CHECK_INCDEC_MODELVAR_ZERO_CHECK(event, var, max, check) \
|
||||
var = checkIncDec(event, var, 0, max, EE_MODEL, check)
|
||||
|
||||
bool isLogicalSwitchFunctionAvailable(int function);
|
||||
bool isAssignableFunctionAvailable(int function);
|
||||
bool isSwitchAvailableInLogicalSwitches(int swtch);
|
||||
bool isSwitchAvailableInCustomFunctions(int swtch);
|
||||
bool isSwitchAvailableInMixes(int swtch);
|
||||
bool isSwitchAvailableInTimers(int swtch);
|
||||
bool isModuleAvailable(int module);
|
||||
#define AUTOSWITCH_ENTER_LONG() (attr && event==EVT_KEY_LONG(KEY_ENTER))
|
||||
#define CHECK_INCDEC_SWITCH(event, var, min, max, flags, available) \
|
||||
var = checkIncDec(event, var, min, max, (flags)|INCDEC_SWITCH, available)
|
||||
#define CHECK_INCDEC_MODELSWITCH(event, var, min, max, available) \
|
||||
CHECK_INCDEC_SWITCH(event, var, min, max, EE_MODEL, available)
|
||||
|
||||
bool isInputAvailable(int input);
|
||||
bool isSourceAvailable(int source);
|
||||
bool isSourceAvailableInCustomSwitches(int source);
|
||||
bool isInputSourceAvailable(int source);
|
||||
#define CHECK_INCDEC_MODELSOURCE(event, var, min, max) \
|
||||
var = checkIncDec(event, var,min,max,EE_MODEL|INCDEC_SOURCE|NO_INCDEC_MARKS, isSourceAvailable)
|
||||
|
||||
#define CHECK_INCDEC_GENVAR(event, var, min, max) \
|
||||
var = checkIncDecGen(event, var, min, max)
|
||||
|
||||
#define NAVIGATION_LINE_BY_LINE 0x40
|
||||
#define CURSOR_ON_LINE() (m_posHorz<0)
|
||||
|
||||
#define CHECK_FLAG_NO_SCREEN_INDEX 1
|
||||
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, uint16_t scrollbar_X, uint8_t flags=0);
|
||||
void check_simple(check_event_t event, uint8_t curr, const MenuFuncP *menuTab, uint8_t menuTabSize, vertpos_t maxrow, uint16_t scrollbar_X);
|
||||
void check_submenu_simple(check_event_t event, uint8_t maxrow, uint16_t scrollbar_X);
|
||||
void title(const pm_char * s);
|
||||
#define TITLE(str) title(str)
|
||||
|
||||
#define MENU_TAB(...) const uint8_t mstate_tab[] = __VA_ARGS__
|
||||
|
||||
#define MENU_CHECK(tab, menu, lines_count, scrollbar_X) \
|
||||
check(event, menu, tab, DIM(tab), mstate_tab, DIM(mstate_tab)-1, lines_count, scrollbar_X)
|
||||
|
||||
#define MENU_CHECK_FLAGS(tab, menu, flags, lines_count, scrollbar_X) \
|
||||
check(event, menu, tab, DIM(tab), mstate_tab, DIM(mstate_tab)-1, lines_count, scrollbar_X, flags)
|
||||
|
||||
void drawMenuTemplate(const char *title, evt_t event, int pageIndex=0, int pageCount=0);
|
||||
|
||||
#define MENU(title, tab, menu, lines_count, scrollbar_X, ...) \
|
||||
if (event == EVT_ENTRY || event == EVT_ENTRY_UP) TRACE("Menu %s displayed ...", title); \
|
||||
MENU_TAB(__VA_ARGS__); \
|
||||
drawMenuTemplate(title, event, menu, DIM(tab)); \
|
||||
MENU_CHECK(tab, menu, lines_count, scrollbar_X)
|
||||
|
||||
#define MENU_FLAGS(title, tab, menu, flags, lines_count, scrollbar_X, ...) \
|
||||
MENU_TAB(__VA_ARGS__); \
|
||||
MENU_CHECK_FLAGS(tab, menu, flags, lines_count, scrollbar_X); \
|
||||
TITLE(title)
|
||||
|
||||
#define SIMPLE_MENU_NOTITLE(tab, menu, lines_count, scrollbar_X) \
|
||||
check_simple(event, menu, tab, DIM(tab), lines_count, scrollbar_X);
|
||||
|
||||
#define SIMPLE_MENU(title, tab, menu, lines_count, scrollbar_X) \
|
||||
drawMenuTemplate(title, event, menu, DIM(tab)); \
|
||||
SIMPLE_MENU_NOTITLE(tab, menu, lines_count, scrollbar_X)
|
||||
|
||||
#define SUBMENU(title, lines_count, scrollbar_X, ...) \
|
||||
MENU_TAB(__VA_ARGS__); \
|
||||
drawMenuTemplate(title, event); \
|
||||
check(event, 0, NULL, 0, mstate_tab, DIM(mstate_tab)-1, lines_count, scrollbar_X)
|
||||
|
||||
#define SIMPLE_SUBMENU_NOTITLE(lines_count, scrollbar_X) \
|
||||
check_submenu_simple(event, lines_count, scrollbar_X);
|
||||
|
||||
#define SIMPLE_SUBMENU(title, lines_count, scrollbar_X) \
|
||||
SIMPLE_SUBMENU_NOTITLE(lines_count, scrollbar_X); \
|
||||
drawMenuTemplate(title, event)
|
||||
|
||||
typedef int select_menu_value_t;
|
||||
|
||||
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, evt_t event);
|
||||
uint8_t onoffMenuItem(uint8_t value, coord_t x, coord_t y, const pm_char *label, LcdFlags attr, evt_t event);
|
||||
int8_t switchMenuItem(coord_t x, coord_t y, int8_t value, LcdFlags attr, evt_t event);
|
||||
|
||||
#define ON_OFF_MENU_ITEM(value, x, y, label, attr, event) value = onoffMenuItem(value, x, y, label, attr, event)
|
||||
|
||||
#if defined(GVARS)
|
||||
#define GVAR_MENU_ITEM(x, y, v, min, max, lcdattr, editflags, event) gvarMenuItem(x, y, v, min, max, lcdattr, editflags, event)
|
||||
#else
|
||||
#define GVAR_MENU_ITEM(x, y, v, min, max, lcdattr, editflags, event) gvarMenuItem(x, y, v, min, max, lcdattr, event)
|
||||
#endif
|
||||
|
||||
#if defined(GVARS)
|
||||
int16_t gvarMenuItem(coord_t x, coord_t y, int16_t value, int16_t min, int16_t max, LcdFlags attr, uint8_t editflags, evt_t event);
|
||||
#define displayGVar(x, y, v, min, max) GVAR_MENU_ITEM(x, y, v, min, max, 0, 0, 0)
|
||||
#else
|
||||
int16_t gvarMenuItem(coord_t x, coord_t y, int16_t value, int16_t min, int16_t max, LcdFlags attr, evt_t event);
|
||||
#define displayGVar(x, y, v, min, max) lcd_outdez8(x, y, v)
|
||||
#endif
|
||||
|
||||
void editName(coord_t x, coord_t y, char *name, uint8_t size, evt_t event, uint8_t active);
|
||||
|
||||
#define WARNING_TYPE_ASTERISK 0
|
||||
#define WARNING_TYPE_CONFIRM 1
|
||||
#define WARNING_TYPE_INPUT 2
|
||||
|
||||
extern const pm_char * s_warning;
|
||||
extern const pm_char * s_warning_info;
|
||||
extern uint8_t s_warning_info_len;
|
||||
extern uint8_t s_warning_result;
|
||||
extern uint8_t s_warning_type;
|
||||
|
||||
#define MENU_X 80
|
||||
#define MENU_W LCD_W-(2*MENU_X)
|
||||
#define POPUP_X 45
|
||||
#define POPUP_Y 70
|
||||
#define POPUP_W LCD_W-(2*POPUP_X)
|
||||
#define POPUP_H 90
|
||||
#define WARNING_LINE_LEN 32
|
||||
#define WARNING_LINE_X (POPUP_X+86)
|
||||
#define WARNING_LINE_Y (POPUP_Y+9)
|
||||
#define WARNING_INFOLINE_Y (WARNING_LINE_Y+43)
|
||||
|
||||
void displayBox();
|
||||
void displayPopup(const char *title);
|
||||
void displayWarning(evt_t event);
|
||||
|
||||
extern void (*popupFunc)(evt_t event);
|
||||
extern int16_t s_warning_input_value;
|
||||
extern int16_t s_warning_input_min;
|
||||
extern int16_t s_warning_input_max;
|
||||
extern uint8_t s_warning_info_flags;
|
||||
|
||||
#define DISPLAY_WARNING (*popupFunc)
|
||||
#define POPUP_WARNING(s) (s_warning = s, s_warning_info = 0, popupFunc = displayWarning)
|
||||
#define POPUP_CONFIRMATION(s) (s_warning = s, s_warning_type = WARNING_TYPE_CONFIRM, s_warning_info = 0, popupFunc = displayWarning)
|
||||
#define POPUP_INPUT(s, func, start, min, max) (s_warning = s, s_warning_type = WARNING_TYPE_INPUT, popupFunc = func, s_warning_input_value = start, s_warning_input_min = min, s_warning_input_max = max)
|
||||
#define WARNING_INFO_FLAGS s_warning_info_flags
|
||||
#define SET_WARNING_INFO(info, len, flags) (s_warning_info = info, s_warning_info_len = len, s_warning_info_flags = flags)
|
||||
|
||||
#define NAVIGATION_MENUS
|
||||
#define MENU_ADD_ITEM(s) s_menu[s_menu_count++] = s
|
||||
#define MENU_MAX_LINES 6
|
||||
#define MENU_MAX_DISPLAY_LINES 6
|
||||
#define MENU_ADD_SD_ITEM(s) MENU_ADD_ITEM(s)
|
||||
#define MENU_LINE_LENGTH (LEN_MODEL_NAME+12)
|
||||
extern const char *s_menu[MENU_MAX_LINES];
|
||||
extern uint16_t s_menu_count;
|
||||
extern uint8_t s_menu_flags;
|
||||
extern uint16_t s_menu_offset;
|
||||
const char * displayMenu(evt_t event);
|
||||
extern void (*menuHandler)(const char *result);
|
||||
|
||||
#define TEXT_FILENAME_MAXLEN 40
|
||||
extern char s_text_file[TEXT_FILENAME_MAXLEN];
|
||||
void menuTextView(evt_t event);
|
||||
void pushMenuTextView(const char *filename);
|
||||
bool modelHasNotes();
|
||||
void pushModelNotes();
|
||||
|
||||
void menuChannelsView(evt_t event);
|
||||
|
||||
#define LABEL(...) (uint8_t)-1
|
||||
|
||||
#define KEY_MOVE_UP KEY_PLUS
|
||||
#define KEY_MOVE_DOWN KEY_MINUS
|
||||
|
||||
#if defined(REV9E)
|
||||
#define CURSOR_MOVED_LEFT(event) (EVT_KEY_MASK(event) == KEY_MINUS)
|
||||
#define CURSOR_MOVED_RIGHT(event) (EVT_KEY_MASK(event) == KEY_PLUS)
|
||||
#else
|
||||
#define CURSOR_MOVED_LEFT(event) (EVT_KEY_MASK(event) == KEY_PLUS)
|
||||
#define CURSOR_MOVED_RIGHT(event) (EVT_KEY_MASK(event) == KEY_MINUS)
|
||||
#endif
|
||||
|
||||
#define CASE_EVT_ROTARY_MOVE_RIGHT CASE_EVT_ROTARY_LEFT
|
||||
#define CASE_EVT_ROTARY_MOVE_LEFT CASE_EVT_ROTARY_RIGHT
|
||||
#define IS_ROTARY_MOVE_RIGHT IS_ROTARY_LEFT
|
||||
#define IS_ROTARY_MOVE_LEFT IS_ROTARY_RIGHT
|
||||
|
||||
#define REPEAT_LAST_CURSOR_MOVE() { if (CURSOR_MOVED_LEFT(event) || CURSOR_MOVED_RIGHT(event)) putEvent(event); else m_posHorz = 0; }
|
||||
#define MOVE_CURSOR_FROM_HERE() if (m_posHorz > 0) REPEAT_LAST_CURSOR_MOVE()
|
||||
|
||||
#define POS_VERT_INIT (MAXCOL((uint16_t)0) >= HIDDEN_ROW ? (MAXCOL((uint16_t)1) >= HIDDEN_ROW ? 2 : 1) : 0)
|
||||
#define POS_HORZ_INIT(posVert) ((COLATTR(posVert) & NAVIGATION_LINE_BY_LINE) ? -1 : 0)
|
||||
#define EDIT_MODE_INIT 0 // TODO enum
|
||||
|
||||
typedef int (*FnFuncP) (int x);
|
||||
void DrawFunction(FnFuncP fn, int offset=0);
|
||||
|
||||
#endif // _MENUS_H_
|
||||
@@ -0,0 +1,468 @@
|
||||
/*
|
||||
* Authors (alphabetical order)
|
||||
* - Andre Bernet <bernet.andre@gmail.com>
|
||||
* - Andreas Weitl
|
||||
* - Bertrand Songis <bsongis@gmail.com>
|
||||
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
|
||||
* - Cameron Weeks <th9xer@gmail.com>
|
||||
* - Erez Raviv
|
||||
* - Gabriel Birkus
|
||||
* - Jean-Pierre Parisy
|
||||
* - Karl Szmutny
|
||||
* - Michael Blandford
|
||||
* - Michal Hlavinka
|
||||
* - Pat Mackenzie
|
||||
* - Philip Moss
|
||||
* - Rob Thomson
|
||||
* - Romolo Manfredini <romolo.manfredini@gmail.com>
|
||||
* - 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; // TODO rename this variable
|
||||
|
||||
#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(evt_t event, int val, int i_min, int i_max, unsigned int i_flags, IsValueAvailable isValueAvailable, const CheckIncDecStops &stops)
|
||||
{
|
||||
int newval = val;
|
||||
|
||||
#if defined(DBLKEYS)
|
||||
uint32_t 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) && newval<i_max) {
|
||||
++newval;
|
||||
}
|
||||
}
|
||||
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);
|
||||
killEvents(KEY_MENU);
|
||||
killEvents(KEY_ENTER);
|
||||
killEvents(KEY_EXIT);
|
||||
event = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (s_editMode>0 && (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<int>(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 (val<max) {val++;} else {val=min;}
|
||||
#define DEC(val, min, max) if (val>min) {val--;} else {val=max;}
|
||||
|
||||
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 rowcount, uint16_t scrollbar_X, uint8_t flags)
|
||||
{
|
||||
vertpos_t l_posVert = m_posVert;
|
||||
horzpos_t l_posHorz = m_posHorz;
|
||||
|
||||
uint8_t maxcol = MAXCOL(l_posVert);
|
||||
|
||||
if (menuTab && !calibrationState && l_posVert<0) {
|
||||
int cc = curr;
|
||||
switch (event) {
|
||||
case EVT_KEY_BREAK(KEY_RIGHT):
|
||||
case EVT_ROTARY_RIGHT:
|
||||
if (++cc == menuTabSize)
|
||||
cc = 0;
|
||||
break;
|
||||
|
||||
case EVT_KEY_BREAK(KEY_LEFT):
|
||||
case EVT_ROTARY_LEFT:
|
||||
if (cc-- == 0)
|
||||
cc = menuTabSize-1;
|
||||
break;
|
||||
|
||||
case EVT_KEY_BREAK(KEY_ENTER):
|
||||
l_posVert = POS_VERT_INIT;
|
||||
event = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (cc != curr) {
|
||||
chainMenu((MenuFuncP)pgm_read_adr(&menuTab[cc]));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
switch(event)
|
||||
{
|
||||
case EVT_ENTRY:
|
||||
l_posVert = -1;
|
||||
l_posHorz = POS_HORZ_INIT(l_posVert);
|
||||
s_editMode = EDIT_MODE_INIT;
|
||||
break;
|
||||
|
||||
case EVT_ENTRY_UP:
|
||||
s_editMode = 0;
|
||||
l_posHorz = POS_HORZ_INIT(l_posVert);
|
||||
break;
|
||||
|
||||
case EVT_ROTARY_BREAK:
|
||||
if (s_editMode > 1) break;
|
||||
if (m_posHorz < 0 && maxcol > 0 && READ_ONLY_UNLOCKED()) {
|
||||
l_posHorz = 0;
|
||||
break;
|
||||
}
|
||||
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 if (l_posVert >= 0) {
|
||||
l_posVert = -1;
|
||||
l_posHorz = 0;
|
||||
#if 0
|
||||
int posVertInit = -1;
|
||||
if (s_pgOfs != 0 || l_posVert != posVertInit) {
|
||||
s_pgOfs = 0;
|
||||
l_posVert = posVertInit;
|
||||
l_posHorz = POS_HORZ_INIT(l_posVert);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
popMenu();
|
||||
}
|
||||
break;
|
||||
|
||||
case EVT_KEY_FIRST(KEY_RIGHT):
|
||||
case EVT_KEY_REPT(KEY_RIGHT):
|
||||
if (s_editMode != 0) break;
|
||||
INC(l_posHorz, 0, maxcol);
|
||||
break;
|
||||
|
||||
case EVT_KEY_FIRST(KEY_LEFT):
|
||||
case EVT_KEY_REPT(KEY_LEFT):
|
||||
DEC(l_posHorz, 0, maxcol);
|
||||
break;
|
||||
break;
|
||||
|
||||
case EVT_ROTARY_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;
|
||||
}
|
||||
}
|
||||
// no break
|
||||
|
||||
case EVT_KEY_FIRST(KEY_DOWN):
|
||||
case EVT_KEY_REPT(KEY_DOWN):
|
||||
do {
|
||||
INC(l_posVert, POS_VERT_INIT, rowcount-1);
|
||||
} 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_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 {
|
||||
l_posHorz = 0xff;
|
||||
}
|
||||
}
|
||||
// no break
|
||||
|
||||
case EVT_KEY_FIRST(KEY_UP):
|
||||
case EVT_KEY_REPT(KEY_UP):
|
||||
do {
|
||||
DEC(l_posVert, POS_VERT_INIT, rowcount-1);
|
||||
} 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;
|
||||
}
|
||||
|
||||
int linesCount = rowcount;
|
||||
|
||||
if (l_posVert <= 0 || (l_posVert==1 && MAXCOL(vertpos_t(0)) >= HIDDEN_ROW) || (l_posVert==2 && MAXCOL(vertpos_t(0)) >= HIDDEN_ROW && MAXCOL(vertpos_t(1)) >= HIDDEN_ROW)) {
|
||||
s_pgOfs = 0;
|
||||
if (horTab) {
|
||||
linesCount = 0;
|
||||
for (int i=0; i<rowcount; i++) {
|
||||
if (i>=horTabMax || horTab[i] != HIDDEN_ROW) {
|
||||
linesCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (horTab) {
|
||||
if (rowcount > NUM_BODY_LINES) {
|
||||
while (1) {
|
||||
vertpos_t firstLine = 0;
|
||||
for (int numLines=0; firstLine<rowcount && numLines<s_pgOfs; firstLine++) {
|
||||
if (firstLine>=horTabMax || horTab[firstLine] != HIDDEN_ROW) {
|
||||
numLines++;
|
||||
}
|
||||
}
|
||||
if (l_posVert < firstLine) {
|
||||
s_pgOfs--;
|
||||
}
|
||||
else {
|
||||
vertpos_t lastLine = firstLine;
|
||||
for (int numLines=0; lastLine<rowcount && numLines<NUM_BODY_LINES; lastLine++) {
|
||||
if (lastLine>=horTabMax || horTab[lastLine] != HIDDEN_ROW) {
|
||||
numLines++;
|
||||
}
|
||||
}
|
||||
if (l_posVert >= lastLine) {
|
||||
s_pgOfs++;
|
||||
}
|
||||
else {
|
||||
linesCount = s_pgOfs + NUM_BODY_LINES;
|
||||
for (int i=lastLine; i<rowcount; i++) {
|
||||
if (i>=horTabMax || horTab[i] != HIDDEN_ROW) {
|
||||
linesCount++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (l_posVert>=NUM_BODY_LINES+s_pgOfs) {
|
||||
s_pgOfs = l_posVert-NUM_BODY_LINES+1;
|
||||
}
|
||||
else if (l_posVert<s_pgOfs) {
|
||||
s_pgOfs = l_posVert;
|
||||
}
|
||||
}
|
||||
|
||||
if (scrollbar_X && linesCount > NUM_BODY_LINES) {
|
||||
displayScrollbar(scrollbar_X, DEFAULT_SCROLLBAR_Y, DEFAULT_SCROLLBAR_H, s_pgOfs, linesCount, 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 rowcount, uint16_t scrollbar_X)
|
||||
{
|
||||
check(event, curr, menuTab, menuTabSize, 0, 0, rowcount, scrollbar_X);
|
||||
}
|
||||
|
||||
void check_submenu_simple(check_event_t event, uint8_t rowcount, uint16_t scrollbar_X)
|
||||
{
|
||||
check_simple(event, 0, 0, 0, rowcount, scrollbar_X);
|
||||
}
|
||||
|
||||
void repeatLastCursorMove(evt_t event)
|
||||
{
|
||||
if (CURSOR_MOVED_LEFT(event) || CURSOR_MOVED_RIGHT(event)) {
|
||||
putEvent(event);
|
||||
}
|
||||
else {
|
||||
m_posHorz = 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,236 @@
|
||||
/*
|
||||
* Authors (alphabetical order)
|
||||
* - Andre Bernet <bernet.andre@gmail.com>
|
||||
* - Andreas Weitl
|
||||
* - Bertrand Songis <bsongis@gmail.com>
|
||||
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
|
||||
* - Cameron Weeks <th9xer@gmail.com>
|
||||
* - Erez Raviv
|
||||
* - Gabriel Birkus
|
||||
* - Jean-Pierre Parisy
|
||||
* - Karl Szmutny
|
||||
* - Michael Blandford
|
||||
* - Michal Hlavinka
|
||||
* - Pat Mackenzie
|
||||
* - Philip Moss
|
||||
* - Rob Thomson
|
||||
* - Romolo Manfredini <romolo.manfredini@gmail.com>
|
||||
* - 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 displayAlertBox()
|
||||
{
|
||||
drawBlackOverlay();
|
||||
lcdDrawFilledRect(POPUP_X, POPUP_Y, POPUP_W, POPUP_H, TEXT_BGCOLOR);
|
||||
lcd_rect(POPUP_X, POPUP_Y, POPUP_W, POPUP_H, SOLID, ALARM_COLOR);
|
||||
lcd_rect(POPUP_X+1, POPUP_Y+1, POPUP_W-2, POPUP_H-2, SOLID, ALARM_COLOR);
|
||||
// lcdDrawBitmap(POPUP_X+15, POPUP_Y+20, LBM_ALERT);
|
||||
}
|
||||
|
||||
void displayWarningBox()
|
||||
{
|
||||
drawBlackOverlay();
|
||||
lcdDrawFilledRect(POPUP_X, POPUP_Y, POPUP_W, POPUP_H, TEXT_BGCOLOR);
|
||||
lcd_rect(POPUP_X, POPUP_Y, POPUP_W, POPUP_H, SOLID, ALARM_COLOR);
|
||||
lcd_rect(POPUP_X+1, POPUP_Y+1, POPUP_W-2, POPUP_H-2, SOLID, ALARM_COLOR);
|
||||
// lcdDrawBitmap(POPUP_X+15, POPUP_Y+20, LBM_WARNING);
|
||||
}
|
||||
|
||||
void displayMessageBox()
|
||||
{
|
||||
drawBlackOverlay();
|
||||
lcdDrawFilledRect(POPUP_X, POPUP_Y, POPUP_W, POPUP_H, TEXT_BGCOLOR);
|
||||
lcd_rect(POPUP_X, POPUP_Y, POPUP_W, POPUP_H, SOLID, WARNING_COLOR);
|
||||
lcd_rect(POPUP_X+1, POPUP_Y+1, POPUP_W-2, POPUP_H-2, SOLID, WARNING_COLOR);
|
||||
// lcdDrawBitmap(POPUP_X+15, POPUP_Y+20, LBM_MESSAGE);
|
||||
}
|
||||
|
||||
void message(const pm_char *title, const pm_char *t, const char *last MESSAGE_SOUND_ARG)
|
||||
{
|
||||
displayAlertBox();
|
||||
|
||||
#if defined(TRANSLATIONS_FR) || defined(TRANSLATIONS_IT) || defined(TRANSLATIONS_CZ)
|
||||
lcd_putsAtt(WARNING_LINE_X, WARNING_LINE_Y, STR_WARNING, ALARM_COLOR|DBLSIZE);
|
||||
lcd_putsAtt(WARNING_LINE_X, WARNING_LINE_Y+15, title, ALARM_COLOR|DBLSIZE);
|
||||
#else
|
||||
lcd_putsAtt(WARNING_LINE_X, WARNING_LINE_Y, title, ALARM_COLOR|DBLSIZE);
|
||||
lcd_putsAtt(WARNING_LINE_X, WARNING_LINE_Y+15, STR_WARNING, ALARM_COLOR|DBLSIZE);
|
||||
#endif
|
||||
|
||||
if (t) lcd_puts(WARNING_LINE_X, WARNING_INFOLINE_Y, t);
|
||||
if (last) {
|
||||
lcd_puts(WARNING_LINE_X, WARNING_INFOLINE_Y+12, last);
|
||||
AUDIO_ERROR_MESSAGE(sound);
|
||||
}
|
||||
|
||||
lcdRefresh();
|
||||
lcdSetContrast();
|
||||
clearKeyEvents();
|
||||
}
|
||||
|
||||
void displayPopup(const char *title)
|
||||
{
|
||||
displayMessageBox();
|
||||
lcd_putsnAtt(WARNING_LINE_X, WARNING_LINE_Y, title, WARNING_LINE_LEN, DBLSIZE|WARNING_COLOR);
|
||||
lcdRefresh();
|
||||
}
|
||||
|
||||
void displayWarning(evt_t event)
|
||||
{
|
||||
s_warning_result = false;
|
||||
if (s_warning_type == WARNING_TYPE_INPUT)
|
||||
displayMessageBox();
|
||||
else
|
||||
displayWarningBox();
|
||||
lcd_putsnAtt(WARNING_LINE_X, WARNING_LINE_Y, s_warning, WARNING_LINE_LEN, DBLSIZE | (s_warning_type == WARNING_TYPE_INPUT ? WARNING_COLOR : ALARM_COLOR));
|
||||
if (s_warning_info) {
|
||||
lcd_putsnAtt(WARNING_LINE_X, WARNING_INFOLINE_Y, s_warning_info, s_warning_info_len, WARNING_INFO_FLAGS);
|
||||
}
|
||||
lcd_puts(WARNING_LINE_X, WARNING_INFOLINE_Y+12, 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;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
void (*popupFunc)(evt_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);
|
||||
const char * displayMenu(evt_t event)
|
||||
{
|
||||
const char * result = NULL;
|
||||
|
||||
uint8_t display_count = min(s_menu_count, (uint16_t)MENU_MAX_LINES);
|
||||
|
||||
int y = (LCD_H - (display_count*(FH+1))) / 2;
|
||||
drawBlackOverlay();
|
||||
lcdDrawFilledRect(MENU_X, y, MENU_W, display_count * (FH+1), TEXT_BGCOLOR);
|
||||
lcd_rect(MENU_X, y, MENU_W, display_count * (FH+1), SOLID, WARNING_COLOR);
|
||||
|
||||
for (uint8_t i=0; i<display_count; i++) {
|
||||
if (i == s_menu_item) {
|
||||
lcdDrawFilledRect(MENU_X+1, i*(FH+1) + y + 1, MENU_W-2, 18, TEXT_INVERTED_BGCOLOR);
|
||||
lcd_putsAtt(MENU_X+6, i*(FH+1) + y + 5, s_menu[i], TEXT_INVERTED_COLOR|s_menu_flags);
|
||||
}
|
||||
else {
|
||||
lcd_putsAtt(MENU_X+6, i*(FH+1) + y + 5, s_menu[i], s_menu_flags);
|
||||
}
|
||||
}
|
||||
|
||||
if (s_menu_count > 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--;
|
||||
}
|
||||
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;
|
||||
|
||||
#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++;
|
||||
}
|
||||
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
|
||||
#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;
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Authors (alphabetical order)
|
||||
* - Andre Bernet <bernet.andre@gmail.com>
|
||||
* - Andreas Weitl
|
||||
* - Bertrand Songis <bsongis@gmail.com>
|
||||
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
|
||||
* - Cameron Weeks <th9xer@gmail.com>
|
||||
* - Erez Raviv
|
||||
* - Gabriel Birkus
|
||||
* - Jean-Pierre Parisy
|
||||
* - Karl Szmutny
|
||||
* - Michael Blandford
|
||||
* - Michal Hlavinka
|
||||
* - Pat Mackenzie
|
||||
* - Philip Moss
|
||||
* - Rob Thomson
|
||||
* - Romolo Manfredini <romolo.manfredini@gmail.com>
|
||||
* - 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 uint16_t LBM_SPLASH[] = {
|
||||
#include "../../bitmaps/Horus/splash.lbm"
|
||||
};
|
||||
|
||||
#if defined(SPLASH)
|
||||
void displaySplash()
|
||||
{
|
||||
lcdDrawBitmap((LCD_W-256)/2, (LCD_H-256)/2, LBM_SPLASH);
|
||||
|
||||
#if MENUS_LOCK == 1
|
||||
if (readonly == false) {
|
||||
lcdDrawFilledRect((LCD_W-(sizeof(TR_UNLOCKED)-1)*FW)/2 - 9, 50, (sizeof(TR_UNLOCKED)-1)*FW+16, 11, SOLID, ERASE|ROUND);
|
||||
lcd_puts((LCD_W-(sizeof(TR_UNLOCKED)-1)*FW)/2 , 53, STR_UNLOCKED);
|
||||
}
|
||||
#endif
|
||||
|
||||
lcdRefresh();
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
* Authors (alphabetical order)
|
||||
* - Andre Bernet <bernet.andre@gmail.com>
|
||||
* - Andreas Weitl
|
||||
* - Bertrand Songis <bsongis@gmail.com>
|
||||
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
|
||||
* - Cameron Weeks <th9xer@gmail.com>
|
||||
* - Erez Raviv
|
||||
* - Gabriel Birkus
|
||||
* - Jean-Pierre Parisy
|
||||
* - Karl Szmutny
|
||||
* - Michael Blandford
|
||||
* - Michal Hlavinka
|
||||
* - Pat Mackenzie
|
||||
* - Philip Moss
|
||||
* - Rob Thomson
|
||||
* - Romolo Manfredini <romolo.manfredini@gmail.com>
|
||||
* - 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 AboutScreens {
|
||||
ABOUT_OPENTX,
|
||||
ABOUT_BERTRAND,
|
||||
ABOUT_ANDRE,
|
||||
ABOUT_MIKE,
|
||||
ABOUT_KJELL,
|
||||
ABOUT_MARTIN,
|
||||
ABOUT_ROMOLO,
|
||||
ABOUT_ROB,
|
||||
ABOUT_HARDWARE,
|
||||
ABOUT_PARENTS,
|
||||
ABOUT_END,
|
||||
ABOUT_COUNT,
|
||||
};
|
||||
|
||||
#define ABOUT_X 62
|
||||
#define ABOUT_INDENT 16
|
||||
|
||||
void menuAboutView(evt_t event)
|
||||
{
|
||||
static uint8_t screenIndex = 0;
|
||||
static uint8_t greyIndex = 0;
|
||||
|
||||
switch(event)
|
||||
{
|
||||
case EVT_ENTRY:
|
||||
screenIndex = 0;
|
||||
greyIndex = 0;
|
||||
break;
|
||||
case EVT_KEY_FIRST(KEY_DOWN):
|
||||
screenIndex < ABOUT_PARENTS ? screenIndex++ : screenIndex = ABOUT_OPENTX;
|
||||
greyIndex = 0;
|
||||
break;
|
||||
case EVT_KEY_FIRST(KEY_UP):
|
||||
screenIndex > ABOUT_OPENTX ? screenIndex-- : screenIndex = ABOUT_PARENTS;
|
||||
greyIndex = 0;
|
||||
break;
|
||||
case EVT_KEY_FIRST(KEY_EXIT):
|
||||
chainMenu(menuMainView);
|
||||
break;
|
||||
}
|
||||
|
||||
drawMenuTemplate("About", event);
|
||||
|
||||
uint8_t screenDuration = 150;
|
||||
|
||||
switch (screenIndex) {
|
||||
case ABOUT_OPENTX:
|
||||
case ABOUT_END:
|
||||
lcd_puts(ABOUT_X, MENU_HEADER_HEIGHT+1, STR_ABOUT_OPENTX_1);
|
||||
lcd_puts(ABOUT_X, MENU_CONTENT_TOP + FH, STR_ABOUT_OPENTX_2);
|
||||
lcd_puts(ABOUT_X, MENU_CONTENT_TOP + 2*FH, STR_ABOUT_OPENTX_3);
|
||||
lcd_puts(ABOUT_X, MENU_CONTENT_TOP + 3*FH, STR_ABOUT_OPENTX_4);
|
||||
lcd_puts(ABOUT_X, MENU_CONTENT_TOP + 4*FH, STR_ABOUT_OPENTX_5);
|
||||
screenDuration = 255;
|
||||
break;
|
||||
|
||||
case ABOUT_BERTRAND:
|
||||
lcd_putsAtt(ABOUT_X, MENU_HEADER_HEIGHT+1, STR_ABOUT_BERTRAND_1, INVERS);
|
||||
lcd_puts(ABOUT_X+ABOUT_INDENT, MENU_CONTENT_TOP + FH, STR_ABOUT_BERTRAND_2);
|
||||
lcd_puts(ABOUT_X+ABOUT_INDENT, MENU_CONTENT_TOP + 2*FH, STR_ABOUT_BERTRAND_3);
|
||||
break;
|
||||
|
||||
case ABOUT_ANDRE:
|
||||
lcd_putsAtt(ABOUT_X, MENU_HEADER_HEIGHT+1, STR_ABOUT_ANDRE_1, INVERS);
|
||||
lcd_puts(ABOUT_X+ABOUT_INDENT, MENU_CONTENT_TOP + FH, STR_ABOUT_ANDRE_2);
|
||||
lcd_puts(ABOUT_X+ABOUT_INDENT, MENU_CONTENT_TOP + 2*FH, STR_ABOUT_ANDRE_3);
|
||||
break;
|
||||
|
||||
case ABOUT_MIKE:
|
||||
lcd_putsAtt(ABOUT_X, MENU_HEADER_HEIGHT+1, STR_ABOUT_MIKE_1, INVERS);
|
||||
lcd_puts(ABOUT_X+ABOUT_INDENT, MENU_CONTENT_TOP + FH, STR_ABOUT_MIKE_2);
|
||||
lcd_puts(ABOUT_X+ABOUT_INDENT, MENU_CONTENT_TOP + 2*FH, STR_ABOUT_MIKE_3);
|
||||
lcd_puts(ABOUT_X+ABOUT_INDENT, MENU_CONTENT_TOP + 3*FH, STR_ABOUT_MIKE_4);
|
||||
break;
|
||||
|
||||
case ABOUT_KJELL:
|
||||
lcd_putsAtt(ABOUT_X, MENU_HEADER_HEIGHT+1, STR_ABOUT_KJELL_1, INVERS);
|
||||
lcd_puts(ABOUT_X+ABOUT_INDENT, MENU_CONTENT_TOP + FH, STR_ABOUT_KJELL_2);
|
||||
lcd_puts(ABOUT_X+ABOUT_INDENT, MENU_CONTENT_TOP + 2*FH, STR_ABOUT_KJELL_3);
|
||||
lcd_puts(ABOUT_X+ABOUT_INDENT, MENU_CONTENT_TOP + 3*FH, STR_ABOUT_KJELL_4);
|
||||
break;
|
||||
|
||||
case ABOUT_MARTIN:
|
||||
lcd_putsAtt(ABOUT_X, MENU_HEADER_HEIGHT+1, STR_ABOUT_MARTIN_1, INVERS);
|
||||
lcd_puts(ABOUT_X+ABOUT_INDENT, MENU_CONTENT_TOP + FH, STR_ABOUT_MARTIN_2);
|
||||
break;
|
||||
|
||||
case ABOUT_ROMOLO:
|
||||
lcd_putsAtt(ABOUT_X, MENU_HEADER_HEIGHT+1, STR_ABOUT_ROMOLO_1, INVERS);
|
||||
lcd_puts(ABOUT_X+ABOUT_INDENT, MENU_CONTENT_TOP + FH, STR_ABOUT_ROMOLO_2);
|
||||
lcd_puts(ABOUT_X+ABOUT_INDENT, MENU_CONTENT_TOP + 2*FH, STR_ABOUT_ROMOLO_3);
|
||||
break;
|
||||
|
||||
case ABOUT_ROB:
|
||||
lcd_putsAtt(ABOUT_X, MENU_HEADER_HEIGHT+1, STR_ABOUT_ROB_1, INVERS);
|
||||
lcd_puts(ABOUT_X+ABOUT_INDENT, MENU_CONTENT_TOP + FH, STR_ABOUT_ROB_2);
|
||||
break;
|
||||
|
||||
case ABOUT_HARDWARE:
|
||||
lcd_putsAtt(ABOUT_X, MENU_HEADER_HEIGHT+1, "FrSky", INVERS);
|
||||
lcd_puts(ABOUT_X+ABOUT_INDENT, MENU_CONTENT_TOP + FH, STR_ABOUT_HARDWARE_2);
|
||||
lcd_puts(ABOUT_X+ABOUT_INDENT, MENU_CONTENT_TOP + 2*FH, STR_ABOUT_HARDWARE_3);
|
||||
break;
|
||||
|
||||
case ABOUT_PARENTS:
|
||||
lcd_putsAtt(ABOUT_X, MENU_HEADER_HEIGHT+1, STR_ABOUT_PARENTS_1, INVERS);
|
||||
lcd_puts(ABOUT_X+ABOUT_INDENT, MENU_CONTENT_TOP + FH, STR_ABOUT_PARENTS_2);
|
||||
lcd_puts(ABOUT_X+ABOUT_INDENT, MENU_CONTENT_TOP + 2*FH, STR_ABOUT_PARENTS_3);
|
||||
lcd_puts(ABOUT_X+ABOUT_INDENT, MENU_CONTENT_TOP + 3*FH, STR_ABOUT_PARENTS_4);
|
||||
screenDuration = 255;
|
||||
break;
|
||||
}
|
||||
|
||||
if (++greyIndex == screenDuration) {
|
||||
greyIndex = 0;
|
||||
if (++screenIndex == ABOUT_COUNT) {
|
||||
chainMenu(menuMainView);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* Authors (alphabetical order)
|
||||
* - Andre Bernet <bernet.andre@gmail.com>
|
||||
* - Andreas Weitl
|
||||
* - Bertrand Songis <bsongis@gmail.com>
|
||||
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
|
||||
* - Cameron Weeks <th9xer@gmail.com>
|
||||
* - Erez Raviv
|
||||
* - Gabriel Birkus
|
||||
* - Jean-Pierre Parisy
|
||||
* - Karl Szmutny
|
||||
* - Michael Blandford
|
||||
* - Michal Hlavinka
|
||||
* - Pat Mackenzie
|
||||
* - Philip Moss
|
||||
* - Rob Thomson
|
||||
* - Romolo Manfredini <romolo.manfredini@gmail.com>
|
||||
* - 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"
|
||||
|
||||
bool isChannelUsed(int channel);
|
||||
int getChannelsUsed();
|
||||
|
||||
void menuChannelsView(evt_t event)
|
||||
{
|
||||
const int CHANNEL_MARGIN = 16;
|
||||
const int CHANNEL_HEIGHT = 25;
|
||||
const int CHANNEL_WIDTH = (LCD_W - 3*CHANNEL_MARGIN) / 2;
|
||||
const int CHANNEL_PADDING_HORZ = 4;
|
||||
const int CHANNEL_PADDING_VERT = 2;
|
||||
const int BAR_WIDTH = CHANNEL_WIDTH-2*CHANNEL_PADDING_HORZ;
|
||||
|
||||
static int view = 0;
|
||||
int x=CHANNEL_MARGIN, y=CHANNEL_MARGIN;
|
||||
|
||||
int viewMax = (getChannelsUsed() - 1) / 8;
|
||||
if (viewMax <= 0 || view > viewMax) {
|
||||
view = 0;
|
||||
}
|
||||
else {
|
||||
switch (event) {
|
||||
case EVT_KEY_FIRST(KEY_RIGHT):
|
||||
if (++view > viewMax)
|
||||
view = 0;
|
||||
break;
|
||||
case EVT_KEY_FIRST(KEY_LEFT):
|
||||
if (--view < 0)
|
||||
view = viewMax;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int skipCount = view*8;
|
||||
for (int ch=0, index=0; index<skipCount+8 && ch<NUM_CHNOUT; ++ch) {
|
||||
if (isChannelUsed(ch)) {
|
||||
if (++index > skipCount) {
|
||||
// The black background
|
||||
lcdDrawFilledRect(x, y, CHANNEL_WIDTH, CHANNEL_HEIGHT, TEXT_BGCOLOR);
|
||||
|
||||
// The label
|
||||
unsigned int lenLabel = ZLEN(g_model.limitData[ch].name);
|
||||
if (lenLabel > 0)
|
||||
lcd_putsnAtt(x+CHANNEL_PADDING_HORZ, y+CHANNEL_PADDING_VERT, g_model.limitData[ch].name, sizeof(g_model.limitData[ch].name), ZCHAR);
|
||||
else
|
||||
putsChn(x+CHANNEL_PADDING_HORZ, y+CHANNEL_PADDING_VERT, ch+1, 0);
|
||||
|
||||
int32_t val = channelOutputs[ch];
|
||||
|
||||
// The bar
|
||||
lcdDrawFilledRect(x+CHANNEL_PADDING_HORZ, y+15, BAR_WIDTH, 6, TEXT_INVERTED_BGCOLOR);
|
||||
unsigned int lim = g_model.extendedLimits ? 640*2 : 512*2;
|
||||
unsigned int len = limit<unsigned int>(1, (abs(val) * BAR_WIDTH/2 + lim/2) / lim, BAR_WIDTH/2);
|
||||
unsigned int x0 = (val>0) ? x+CHANNEL_PADDING_HORZ-1+BAR_WIDTH/2 : x+CHANNEL_PADDING_HORZ+BAR_WIDTH/2+1-len;
|
||||
lcdDrawFilledRect(x0, y+16, len, 4, TEXT_BGCOLOR);
|
||||
|
||||
y += CHANNEL_HEIGHT + CHANNEL_MARGIN;
|
||||
if (y >= 4*(CHANNEL_HEIGHT + CHANNEL_MARGIN)) {
|
||||
x += CHANNEL_WIDTH + CHANNEL_MARGIN;
|
||||
y = CHANNEL_MARGIN;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
#if defined(CHANNELS_MONITOR_INV_HIDE)
|
||||
//if channel output is inverted, show it with oposite sign
|
||||
if (g_model.limitData[ch].revert) val = -val;
|
||||
#endif
|
||||
|
||||
// Value
|
||||
#if defined(PPM_UNIT_US)
|
||||
uint8_t wbar = (longNames ? 54 : 64);
|
||||
lcd_outdezAtt(x+LCD_W/2-3-wbar-ofs, y+1, PPM_CH_CENTER(ch)+val/2, TINSIZE);
|
||||
#elif defined(PPM_UNIT_PERCENT_PREC1)
|
||||
uint8_t wbar = (longNames ? 48 : 58);
|
||||
lcd_outdezAtt(x+LCD_W/2-3-wbar-ofs, y+1, calcRESXto1000(val), PREC1|TINSIZE);
|
||||
#else
|
||||
uint8_t wbar = (longNames ? 54 : 64);
|
||||
lcd_outdezAtt(x+LCD_W/2-3-wbar-ofs, y+1, calcRESXto1000(val)/10, TINSIZE); // G: Don't like the decimal part*
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,374 @@
|
||||
/*
|
||||
* Authors (alphabetical order)
|
||||
* - Andre Bernet <bernet.andre@gmail.com>
|
||||
* - Andreas Weitl
|
||||
* - Bertrand Songis <bsongis@gmail.com>
|
||||
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
|
||||
* - Cameron Weeks <th9xer@gmail.com>
|
||||
* - Erez Raviv
|
||||
* - Gabriel Birkus
|
||||
* - Jean-Pierre Parisy
|
||||
* - Karl Szmutny
|
||||
* - Michael Blandford
|
||||
* - Michal Hlavinka
|
||||
* - Pat Mackenzie
|
||||
* - Philip Moss
|
||||
* - Rob Thomson
|
||||
* - Romolo Manfredini <romolo.manfredini@gmail.com>
|
||||
* - 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 BIGSIZE MIDSIZE
|
||||
#define BAR_HEIGHT (BOX_WIDTH-9)
|
||||
#define LBOX_CENTERX (BOX_WIDTH/2 + 17)
|
||||
#define RBOX_CENTERX (LCD_W-LBOX_CENTERX)
|
||||
#define BITMAP_X ((LCD_W-64)/2)
|
||||
#define BITMAP_Y (LCD_H/2)
|
||||
#define TRIM_LH_X (32+9)
|
||||
#define TRIM_LV_X 10
|
||||
#define TRIM_RV_X (LCD_W-11)
|
||||
#define TRIM_RH_X (LCD_W-32-9)
|
||||
#define TRIM_LEN 27
|
||||
|
||||
void drawPotsBars()
|
||||
{
|
||||
// Optimization by Mike Blandford
|
||||
uint8_t x, i, len ; // declare temporary variables
|
||||
for (x=LCD_W/2-9, i=NUM_STICKS; i<NUM_STICKS+NUM_POTS; x+=9, i++) {
|
||||
if (IS_POT_AVAILABLE(i)) {
|
||||
len = ((calibratedStick[i]+RESX)*BAR_HEIGHT/(RESX*2))+1l; // calculate once per loop
|
||||
lcdDrawFilledRect(x, 170-FH-len, 5, len, TEXT_COLOR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void doMainScreenGraphics()
|
||||
{
|
||||
int16_t calibStickVert = calibratedStick[CONVERT_MODE(1)];
|
||||
if (g_model.throttleReversed && CONVERT_MODE(1) == THR_STICK)
|
||||
calibStickVert = -calibStickVert;
|
||||
drawStick(LBOX_CENTERX, calibratedStick[CONVERT_MODE(0)], calibStickVert);
|
||||
|
||||
calibStickVert = calibratedStick[CONVERT_MODE(2)];
|
||||
if (g_model.throttleReversed && CONVERT_MODE(2) == THR_STICK)
|
||||
calibStickVert = -calibStickVert;
|
||||
drawStick(RBOX_CENTERX, calibratedStick[CONVERT_MODE(3)], calibStickVert);
|
||||
}
|
||||
|
||||
void displayTrims(uint8_t phase)
|
||||
{
|
||||
for (uint8_t i=0; i<4; i++) {
|
||||
static coord_t x[4] = {TRIM_LH_X, TRIM_LV_X, TRIM_RV_X, TRIM_RH_X};
|
||||
static uint8_t vert[4] = {0,1,1,0};
|
||||
coord_t xm, ym;
|
||||
xm = x[CONVERT_MODE(i)];
|
||||
|
||||
uint8_t att = ROUND;
|
||||
int16_t val = getTrimValue(phase, i);
|
||||
|
||||
int16_t dir = val;
|
||||
bool exttrim = false;
|
||||
if (val < -125 || val > 125) {
|
||||
exttrim = true;
|
||||
}
|
||||
|
||||
if (val < -(TRIM_LEN+1)*4) {
|
||||
val = -(TRIM_LEN+1);
|
||||
}
|
||||
else if (val > (TRIM_LEN+1)*4) {
|
||||
val = TRIM_LEN+1;
|
||||
}
|
||||
else {
|
||||
val /= 4;
|
||||
}
|
||||
|
||||
if (vert[i]) {
|
||||
ym = 31;
|
||||
lcd_vline(xm, ym-TRIM_LEN, TRIM_LEN*2);
|
||||
if (i!=2 || !g_model.thrTrim) {
|
||||
lcd_vline(xm-1, ym-1, 3);
|
||||
lcd_vline(xm+1, ym-1, 3);
|
||||
}
|
||||
ym -= val;
|
||||
|
||||
// TODO lcdDrawFilledRect(xm-3, ym-3, 7, 7, SOLID, att);
|
||||
if (dir >= 0) {
|
||||
lcd_hline(xm-1, ym-1, 3);
|
||||
}
|
||||
if (dir <= 0) {
|
||||
lcd_hline(xm-1, ym+1, 3);
|
||||
}
|
||||
if (exttrim) {
|
||||
lcd_hline(xm-1, ym, 3);
|
||||
}
|
||||
}
|
||||
else {
|
||||
ym = 60;
|
||||
lcd_hline(xm-TRIM_LEN, ym, TRIM_LEN*2);
|
||||
lcd_hline(xm-1, ym-1, 3);
|
||||
lcd_hline(xm-1, ym+1, 3);
|
||||
xm += val;
|
||||
|
||||
// TODO lcdDrawFilledRect(xm-3, ym-3, 7, 7, SOLID, att);
|
||||
if (dir >= 0) {
|
||||
lcd_vline(xm+1, ym-1, 3);
|
||||
}
|
||||
if (dir <= 0) {
|
||||
lcd_vline(xm-1, ym-1, 3);
|
||||
}
|
||||
if (exttrim) {
|
||||
lcd_vline(xm, ym-1, 3);
|
||||
}
|
||||
}
|
||||
lcd_square(xm-3, ym-3, 7, att);
|
||||
}
|
||||
}
|
||||
|
||||
void displayTimers()
|
||||
{
|
||||
// const int TIMERS_W = 56;
|
||||
const int TIMERS_H = 30;
|
||||
const int TIMERS_MARGIN = 16;
|
||||
const int TIMERS_PADDING = 4;
|
||||
|
||||
for (int i=0; i<TIMERS; i++) {
|
||||
if (g_model.timers[i].mode) {
|
||||
TimerState & timerState = timersStates[i];
|
||||
TimerData & timerData = g_model.timers[i];
|
||||
int y = TIMERS_MARGIN + i*(TIMERS_H+TIMERS_MARGIN);
|
||||
unsigned int len = zlen(timerData.name, LEN_TIMER_NAME);
|
||||
LcdFlags color=TEXT_COLOR, bgColor=TEXT_BGCOLOR;
|
||||
if (timerState.val < 0) {
|
||||
color = ALARM_COLOR;
|
||||
}
|
||||
// TODO lcdDrawFilledRect(TIMERS_MARGIN, y, TIMERS_W, TIMERS_H, SOLID, bgColor);
|
||||
putsTimer(TIMERS_MARGIN+TIMERS_PADDING, y+12, abs(timerState.val), color|DBLSIZE|LEFT);
|
||||
if (len > 0)
|
||||
lcd_putsnAtt(TIMERS_MARGIN+TIMERS_PADDING, y+2, timerData.name, LEN_TIMER_NAME, color|ZCHAR);
|
||||
else
|
||||
putsTimerMode(TIMERS_MARGIN+TIMERS_PADDING, y+2, timerData.mode, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void displayMainTelemetryFields()
|
||||
{
|
||||
const int ALTITUDE_Y = 16;
|
||||
const int VOLTS_Y = 16+16+30;
|
||||
const int ALTITUDE_W = 56;
|
||||
const int ALTITUDE_X = LCD_W-ALTITUDE_Y-ALTITUDE_W;
|
||||
const int ALTITUDE_H = 30;
|
||||
const int PADDING = 4;
|
||||
|
||||
if (g_model.frsky.voltsSource) {
|
||||
TelemetryItem & item = telemetryItems[g_model.frsky.voltsSource-1];
|
||||
if (item.isAvailable()) {
|
||||
int32_t value = item.value;
|
||||
TelemetrySensor & sensor = g_model.telemetrySensors[g_model.frsky.altitudeSource-1];
|
||||
LcdFlags att = 0;
|
||||
if (sensor.prec == 2) {
|
||||
att |= PREC1;
|
||||
value /= 10;
|
||||
}
|
||||
else if (sensor.prec == 1) {
|
||||
att |= PREC1;
|
||||
}
|
||||
att |= (item.isOld() ? ALARM_COLOR : TEXT_COLOR);
|
||||
lcdDrawFilledRect(ALTITUDE_X, VOLTS_Y, ALTITUDE_W, ALTITUDE_H, TEXT_BGCOLOR);
|
||||
lcd_putsAtt(ALTITUDE_X+PADDING, VOLTS_Y+2, "Voltage", att);
|
||||
putsValueWithUnit(ALTITUDE_X+PADDING, VOLTS_Y+12, value, UNIT_VOLTS, DBLSIZE|LEFT|att);
|
||||
}
|
||||
}
|
||||
|
||||
if (g_model.frsky.altitudeSource) {
|
||||
TelemetryItem & item = telemetryItems[g_model.frsky.altitudeSource-1];
|
||||
if (item.isAvailable()) {
|
||||
int32_t value = item.value;
|
||||
TelemetrySensor & sensor = g_model.telemetrySensors[g_model.frsky.altitudeSource-1];
|
||||
if (sensor.prec) value /= sensor.prec == 2 ? 100 : 10;
|
||||
LcdFlags att = (item.isOld() ? ALARM_COLOR : TEXT_COLOR);
|
||||
lcdDrawFilledRect(ALTITUDE_X, ALTITUDE_Y, ALTITUDE_W, ALTITUDE_H, TEXT_BGCOLOR);
|
||||
lcd_putsAtt(ALTITUDE_X+PADDING, ALTITUDE_Y+2, "Alt", att);
|
||||
putsValueWithUnit(ALTITUDE_X+PADDING, ALTITUDE_Y+12, value, UNIT_METERS, DBLSIZE|LEFT|att);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool isViewAvailable(int index)
|
||||
{
|
||||
if (index <= VIEW_CHANNELS)
|
||||
return true;
|
||||
else
|
||||
return TELEMETRY_SCREEN_TYPE(index-VIEW_TELEM1) != TELEMETRY_SCREEN_TYPE_NONE;
|
||||
}
|
||||
|
||||
void displayMainViewIndex()
|
||||
{
|
||||
int x = LCD_W - 14;
|
||||
|
||||
for (int i=VIEW_COUNT; i>=0; --i) {
|
||||
if (isViewAvailable(i)) {
|
||||
if (g_eeGeneral.view == i) {
|
||||
lcdDrawFilledRect(x, MENU_FOOTER_TOP+17, 9, 9, TEXT_INVERTED_BGCOLOR);
|
||||
}
|
||||
else {
|
||||
lcdDrawRect(x+1, MENU_FOOTER_TOP+18, 7, 7, TEXT_COLOR);
|
||||
}
|
||||
x -= 11;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void onMainViewMenu(const char *result)
|
||||
{
|
||||
if (result == STR_RESET_TIMER1) {
|
||||
timerReset(0);
|
||||
}
|
||||
else if (result == STR_RESET_TIMER2) {
|
||||
timerReset(1);
|
||||
}
|
||||
#if defined(CPUARM)
|
||||
else if (result == STR_RESET_TIMER3) {
|
||||
timerReset(2);
|
||||
}
|
||||
else if (result == STR_VIEW_NOTES) {
|
||||
pushModelNotes();
|
||||
}
|
||||
else if (result == STR_RESET_SUBMENU) {
|
||||
MENU_ADD_ITEM(STR_RESET_FLIGHT);
|
||||
MENU_ADD_ITEM(STR_RESET_TIMER1);
|
||||
MENU_ADD_ITEM(STR_RESET_TIMER2);
|
||||
MENU_ADD_ITEM(STR_RESET_TIMER3);
|
||||
#if defined(FRSKY)
|
||||
MENU_ADD_ITEM(STR_RESET_TELEMETRY);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
#if defined(FRSKY)
|
||||
else if (result == STR_RESET_TELEMETRY) {
|
||||
telemetryReset();
|
||||
}
|
||||
#endif
|
||||
else if (result == STR_RESET_FLIGHT) {
|
||||
flightReset();
|
||||
}
|
||||
else if (result == STR_STATISTICS) {
|
||||
chainMenu(menuStatisticsView);
|
||||
}
|
||||
#if defined(CPUARM)
|
||||
else if (result == STR_ABOUT_US) {
|
||||
chainMenu(menuAboutView);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void displayTelemetryScreen(int index, unsigned int evt);
|
||||
|
||||
void menuMainView(evt_t event)
|
||||
{
|
||||
// clear the screen
|
||||
lcdDrawFilledRect(0, 0, LCD_W, LCD_H, TEXT_BGCOLOR);
|
||||
|
||||
switch (event) {
|
||||
case EVT_ENTRY:
|
||||
killEvents(KEY_EXIT);
|
||||
killEvents(KEY_UP);
|
||||
killEvents(KEY_DOWN);
|
||||
break;
|
||||
|
||||
case EVT_KEY_LONG(KEY_ENTER):
|
||||
killEvents(event);
|
||||
if (modelHasNotes()) {
|
||||
MENU_ADD_ITEM(STR_VIEW_NOTES);
|
||||
}
|
||||
MENU_ADD_ITEM(STR_RESET_SUBMENU);
|
||||
MENU_ADD_ITEM(STR_STATISTICS);
|
||||
MENU_ADD_ITEM(STR_ABOUT_US);
|
||||
menuHandler = onMainViewMenu;
|
||||
break;
|
||||
|
||||
case EVT_KEY_BREAK(KEY_MENU):
|
||||
pushMenu(menuModelSetup);
|
||||
break;
|
||||
|
||||
case EVT_KEY_LONG(KEY_MENU):
|
||||
killEvents(event);
|
||||
pushMenu(menuGeneralSetup);
|
||||
break;
|
||||
|
||||
case EVT_KEY_BREAK(KEY_DOWN):
|
||||
eeDirty(EE_GENERAL);
|
||||
g_eeGeneral.view = circularIncDec(g_eeGeneral.view, +1, 0, VIEW_COUNT-1, isViewAvailable);
|
||||
break;
|
||||
|
||||
case EVT_KEY_BREAK(KEY_UP):
|
||||
killEvents(event);
|
||||
eeDirty(EE_GENERAL);
|
||||
g_eeGeneral.view = circularIncDec(g_eeGeneral.view, -1, 0, VIEW_COUNT-1, isViewAvailable);
|
||||
break;
|
||||
|
||||
case EVT_KEY_FIRST(KEY_EXIT):
|
||||
#if defined(GVARS)
|
||||
if (s_gvar_timer > 0) {
|
||||
s_gvar_timer = 0;
|
||||
}
|
||||
#endif
|
||||
AUDIO_KEYPAD_UP();
|
||||
break;
|
||||
}
|
||||
|
||||
#if 0
|
||||
displayMainViewIndex();
|
||||
|
||||
if (g_eeGeneral.view == VIEW_TIMERS_ALTITUDE) {
|
||||
displayTimers();
|
||||
displayMainTelemetryFields();
|
||||
}
|
||||
else if (g_eeGeneral.view == VIEW_CHANNELS) {
|
||||
menuChannelsView(event);
|
||||
}
|
||||
else {
|
||||
displayTelemetryScreen(g_eeGeneral.view - VIEW_TELEM1, event);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(GVARS)
|
||||
if (s_gvar_timer > 0) {
|
||||
s_gvar_timer--;
|
||||
displayMessageBox();
|
||||
putsStrIdx(WARNING_LINE_X, WARNING_LINE_Y, STR_GV, s_gvar_last+1, DBLSIZE|YELLOW);
|
||||
lcd_putsnAtt(WARNING_LINE_X+45, WARNING_LINE_Y, g_model.gvars[s_gvar_last].name, LEN_GVAR_NAME, DBLSIZE|YELLOW|ZCHAR);
|
||||
lcd_outdezAtt(WARNING_LINE_X, WARNING_INFOLINE_Y, GVAR_VALUE(s_gvar_last, getGVarFlightPhase(mixerCurrentFlightMode, s_gvar_last)), DBLSIZE|LEFT);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void menuMainViewChannelsMonitor(evt_t event)
|
||||
{
|
||||
switch(event) {
|
||||
case EVT_KEY_BREAK(KEY_EXIT):
|
||||
chainMenu(menuMainView);
|
||||
event = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return menuChannelsView(event);
|
||||
}
|
||||
@@ -0,0 +1,213 @@
|
||||
/*
|
||||
* Authors (alphabetical order)
|
||||
* - Andre Bernet <bernet.andre@gmail.com>
|
||||
* - Andreas Weitl
|
||||
* - Bertrand Songis <bsongis@gmail.com>
|
||||
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
|
||||
* - Cameron Weeks <th9xer@gmail.com>
|
||||
* - Erez Raviv
|
||||
* - Gabriel Birkus
|
||||
* - Jean-Pierre Parisy
|
||||
* - Karl Szmutny
|
||||
* - Michael Blandford
|
||||
* - Michal Hlavinka
|
||||
* - Pat Mackenzie
|
||||
* - Philip Moss
|
||||
* - Rob Thomson
|
||||
* - Romolo Manfredini <romolo.manfredini@gmail.com>
|
||||
* - 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(evt_t event)
|
||||
{
|
||||
drawMenuTemplate("Statistics", event);
|
||||
|
||||
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_putsAtt( 10, MENU_CONTENT_TOP + FH*0, "\037\145TOT:\037\317BATT:", HEADER_COLOR);
|
||||
lcd_putsAtt( 10, MENU_CONTENT_TOP + FH*1, "TM1:\037\145TM2:", HEADER_COLOR);
|
||||
lcd_putsAtt( 10, MENU_CONTENT_TOP + FH*2, "THR:\037\145TH%:", HEADER_COLOR);
|
||||
|
||||
putsTimer( 45, MENU_CONTENT_TOP + FH*1, timersStates[0].val);
|
||||
putsTimer( 140, MENU_CONTENT_TOP + FH*1, timersStates[1].val);
|
||||
putsTimer( 45, MENU_CONTENT_TOP + FH*2, s_timeCumThr);
|
||||
putsTimer( 140, MENU_CONTENT_TOP + FH*2, s_timeCum16ThrP/16);
|
||||
putsTimer( 140, MENU_CONTENT_TOP + FH*0, sessionTimer);
|
||||
putsTimer( 250, MENU_CONTENT_TOP + 0*FH, g_eeGeneral.globalTimer+sessionTimer, TIMEHOUR);
|
||||
|
||||
#if defined(THRTRACE)
|
||||
coord_t traceRd = (s_traceCnt < 0 ? s_traceWr : 0);
|
||||
const coord_t x = 4;
|
||||
const coord_t y = 200;
|
||||
lcd_hlineStip(x-3, y, MAXTRACE+3+3, SOLID, TEXT_COLOR);
|
||||
lcd_vlineStip(x, y-96, 96+3, SOLID, TEXT_COLOR);
|
||||
|
||||
for (coord_t i=0; i<MAXTRACE; i+=6) {
|
||||
lcd_vlineStip(x+i+6, y-1, 3, SOLID, TEXT_COLOR);
|
||||
}
|
||||
for (coord_t i=1; i<=MAXTRACE; i++) {
|
||||
lcd_vlineStip(x+i, y-3*s_traceBuf[traceRd], 3*s_traceBuf[traceRd], SOLID, TEXT_COLOR);
|
||||
traceRd++;
|
||||
if (traceRd>=MAXTRACE) traceRd = 0;
|
||||
if (traceRd==s_traceWr) break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#define MENU_DEBUG_COL1_OFS (11*10-2)
|
||||
#define MENU_DEBUG_Y_MIXMAX (MENU_CONTENT_TOP + 2*FH)
|
||||
#define MENU_DEBUG_Y_LUA (MENU_CONTENT_TOP + 3*FH)
|
||||
#define MENU_DEBUG_Y_FREE_RAM (MENU_CONTENT_TOP + 4*FH)
|
||||
#define MENU_DEBUG_Y_STACK (MENU_CONTENT_TOP + 5*FH)
|
||||
#define MENU_DEBUG_Y_RTOS (MENU_CONTENT_TOP + 6*FH)
|
||||
|
||||
void menuStatisticsDebug(evt_t event)
|
||||
{
|
||||
drawMenuTemplate(STR_MENUDEBUG, event);
|
||||
|
||||
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, availableMemory(), LEFT, "b");
|
||||
|
||||
#if defined(LUA)
|
||||
lcd_putsLeft(MENU_DEBUG_Y_LUA, "Lua scripts");
|
||||
lcd_putsAtt(MENU_DEBUG_COL1_OFS, MENU_DEBUG_Y_LUA+1, "[Duration]", HEADER_COLOR|SMLSIZE);
|
||||
lcd_outdezAtt(MENU_DEBUG_COL1_OFS+30, MENU_DEBUG_Y_LUA, 10*maxLuaDuration, LEFT);
|
||||
lcd_putsAtt(MENU_DEBUG_COL1_OFS+60, MENU_DEBUG_Y_LUA+1, "[Interval]", HEADER_COLOR|SMLSIZE);
|
||||
lcd_outdezAtt(MENU_DEBUG_COL1_OFS+90, 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, "ms");
|
||||
|
||||
lcd_putsLeft(MENU_DEBUG_Y_RTOS, STR_FREESTACKMINB);
|
||||
lcd_putsAtt(MENU_DEBUG_COL1_OFS, MENU_DEBUG_Y_RTOS+1, "[Menus]", HEADER_COLOR|SMLSIZE);
|
||||
lcd_outdezAtt(MENU_DEBUG_COL1_OFS+30, MENU_DEBUG_Y_RTOS, menusStack.available(), LEFT);
|
||||
lcd_putsAtt(MENU_DEBUG_COL1_OFS+60, MENU_DEBUG_Y_RTOS+1, "[Mix]", HEADER_COLOR|SMLSIZE);
|
||||
lcd_outdezAtt(MENU_DEBUG_COL1_OFS+90, MENU_DEBUG_Y_RTOS, mixerStack.available(), LEFT);
|
||||
lcd_putsAtt(MENU_DEBUG_COL1_OFS+120, MENU_DEBUG_Y_RTOS+1, "[Audio]", HEADER_COLOR|SMLSIZE);
|
||||
lcd_outdezAtt(MENU_DEBUG_COL1_OFS+150, MENU_DEBUG_Y_RTOS, audioStack.available(), LEFT);
|
||||
|
||||
lcd_putsCenter(7*FH+1, STR_MENUTORESET);
|
||||
// lcd_status_line();
|
||||
}
|
||||
|
||||
|
||||
#if defined(DEBUG_TRACE_BUFFER)
|
||||
#include "stamp-opentx.h"
|
||||
|
||||
void menuTraceBuffer(evt_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*10, FH, "Time");
|
||||
lcd_puts(14*10, FH, "Event");
|
||||
lcd_puts(20*10, FH, "Data");
|
||||
|
||||
for (uint8_t i=0; i<LCD_LINES-2; i++) {
|
||||
y = 1 + (i+2)*FH;
|
||||
k = i+s_pgOfs;
|
||||
|
||||
//item
|
||||
lcd_outdezAtt(0, y, k, LEFT | (sub==k ? INVERS : 0));
|
||||
|
||||
const struct TraceElement * te = getTraceElement(k);
|
||||
if (te) {
|
||||
//time
|
||||
putstime_t tme = te->time % SECS_PER_DAY;
|
||||
putsTimer(4*10, y, tme, TIMEHOUR|LEFT);
|
||||
//event
|
||||
lcd_outdezNAtt(14*10, y, te->event, LEADING0|LEFT, 3);
|
||||
//data
|
||||
lcd_putsn (20*10, y, "0x", 2);
|
||||
lcd_outhex4(22*10-2, y, (uint16_t)(te->data >> 16));
|
||||
lcd_outhex4(25*10, y, (uint16_t)(te->data & 0xFFFF));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
#endif //#if defined(DEBUG_TRACE_BUFFER)
|
||||
@@ -0,0 +1,202 @@
|
||||
/*
|
||||
* Authors (alphabetical order)
|
||||
* - Andre Bernet <bernet.andre@gmail.com>
|
||||
* - Andreas Weitl
|
||||
* - Bertrand Songis <bsongis@gmail.com>
|
||||
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
|
||||
* - Cameron Weeks <th9xer@gmail.com>
|
||||
* - Erez Raviv
|
||||
* - Gabriel Birkus
|
||||
* - Jean-Pierre Parisy
|
||||
* - Karl Szmutny
|
||||
* - Michael Blandford
|
||||
* - Michal Hlavinka
|
||||
* - Pat Mackenzie
|
||||
* - Philip Moss
|
||||
* - Rob Thomson
|
||||
* - Romolo Manfredini <romolo.manfredini@gmail.com>
|
||||
* - 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*10)
|
||||
|
||||
#if defined(FRSKY_HUB) && defined(GAUGES)
|
||||
bar_threshold_t barsThresholds[THLD_MAX];
|
||||
#endif
|
||||
|
||||
NOINLINE uint8_t getRssiAlarmValue(uint8_t alarm)
|
||||
{
|
||||
return (45 - 3*alarm + g_model.frsky.rssiAlarms[alarm].value);
|
||||
}
|
||||
|
||||
int barCoord(int value, int min, int max, int width)
|
||||
{
|
||||
if (value <= min)
|
||||
return 0;
|
||||
else if (value >= max)
|
||||
return width;
|
||||
else
|
||||
return (width * (value - min) + (max - min)/2) / (max - min);
|
||||
}
|
||||
|
||||
void displayGaugesTelemetryScreen(FrSkyScreenData & screen)
|
||||
{
|
||||
const int GAUGE_MARGIN = 16;
|
||||
const int GAUGE_HEIGHT = 25;
|
||||
const int GAUGE_WIDTH = LCD_W - 2*GAUGE_MARGIN;
|
||||
const int GAUGE_PADDING_HORZ = 4;
|
||||
const int GAUGE_PADDING_VERT = 2;
|
||||
const int VAL_WIDTH = 50;
|
||||
const int BAR_WIDTH = GAUGE_WIDTH-2*GAUGE_PADDING_HORZ-VAL_WIDTH;
|
||||
|
||||
for (int i=0; i<4; ++i) {
|
||||
FrSkyBarData & bar = screen.bars[i];
|
||||
source_t source = bar.source;
|
||||
getvalue_t barMin = bar.barMin;
|
||||
getvalue_t barMax = bar.barMax;
|
||||
if (source <= MIXSRC_LAST_CH) {
|
||||
barMin = calc100toRESX(barMin);
|
||||
barMax = calc100toRESX(barMax);
|
||||
}
|
||||
if (source && barMax > barMin) {
|
||||
int y = GAUGE_MARGIN + i*(GAUGE_HEIGHT+GAUGE_MARGIN);
|
||||
|
||||
// The black background
|
||||
lcdDrawFilledRect(GAUGE_MARGIN, y, GAUGE_WIDTH, GAUGE_HEIGHT, TEXT_BGCOLOR);
|
||||
|
||||
getvalue_t value = getValue(source);
|
||||
LcdFlags color = TEXT_COLOR;
|
||||
if (source >= MIXSRC_FIRST_TELEM) {
|
||||
TelemetryItem & telemetryItem = telemetryItems[(source-MIXSRC_FIRST_TELEM)/3]; // TODO macro to convert a source to a telemetry index
|
||||
if (!telemetryItem.isAvailable()) {
|
||||
continue;
|
||||
}
|
||||
else if (telemetryItem.isOld()) {
|
||||
color = ALARM_COLOR;
|
||||
}
|
||||
}
|
||||
else if (source >= MIXSRC_FIRST_TIMER && source <= MIXSRC_LAST_TIMER) {
|
||||
if (value < 0) {
|
||||
putsMixerSource(GAUGE_MARGIN+GAUGE_PADDING_HORZ, y+GAUGE_PADDING_VERT, source, ALARM_COLOR);
|
||||
putsTimer(GAUGE_MARGIN+GAUGE_WIDTH-VAL_WIDTH, y+GAUGE_PADDING_VERT+3, -value, LEFT|DBLSIZE|ALARM_COLOR);
|
||||
// TODO lcdDrawFilledRect(GAUGE_MARGIN+GAUGE_PADDING_HORZ, y+15, BAR_WIDTH, 6, ALARM_BGCOLOR);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// The label
|
||||
putsMixerSource(GAUGE_MARGIN+GAUGE_PADDING_HORZ, y+GAUGE_PADDING_VERT, source, color);
|
||||
|
||||
// The value
|
||||
putsChannel(GAUGE_MARGIN+GAUGE_WIDTH-VAL_WIDTH, y+GAUGE_PADDING_VERT+3, source, LEFT|DBLSIZE|NO_UNIT|color);
|
||||
|
||||
// The bar
|
||||
// TODO lcdDrawFilledRect(GAUGE_MARGIN+GAUGE_PADDING_HORZ, y+15, BAR_WIDTH, 6, SOLID, color);
|
||||
//uint8_t thresholdX = 0;
|
||||
int width = barCoord(value, barMin, barMax, BAR_WIDTH-2);
|
||||
//uint8_t barShade = SOLID;
|
||||
lcdDrawFilledRect(GAUGE_MARGIN+GAUGE_PADDING_HORZ+1, y+16, width, 4, TEXT_BGCOLOR);
|
||||
/* 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);
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void displayNumbersTelemetryScreen(FrSkyScreenData & screen)
|
||||
{
|
||||
const int NUMBERS_W = 56;
|
||||
const int NUMBERS_H = 30;
|
||||
const int NUMBERS_MARGIN = 16;
|
||||
const int NUMBERS_PADDING = 4;
|
||||
|
||||
for (int i=0; i<4; i++) {
|
||||
for (int j=0; j<NUM_LINE_ITEMS; j++) {
|
||||
source_t field = screen.lines[i].sources[j];
|
||||
if (field) {
|
||||
LcdFlags color = WHITE;
|
||||
coord_t pos[] = { NUMBERS_MARGIN, (LCD_W-NUMBERS_W)/2, LCD_W-NUMBERS_MARGIN-NUMBERS_W };
|
||||
int x = pos[j];
|
||||
int y = NUMBERS_MARGIN + i*(NUMBERS_H+NUMBERS_MARGIN);
|
||||
lcdDrawFilledRect(x, y, NUMBERS_W, NUMBERS_H, TEXT_BGCOLOR);
|
||||
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()) {
|
||||
color = RED;
|
||||
}
|
||||
}
|
||||
else if (field >= MIXSRC_FIRST_TIMER && field <= MIXSRC_LAST_TIMER) {
|
||||
TimerState & timerState = timersStates[field-MIXSRC_FIRST_TIMER];
|
||||
if (timerState.val < 0) {
|
||||
color = RED;
|
||||
}
|
||||
putsMixerSource(x+NUMBERS_PADDING, y+2, field, color);
|
||||
putsTimer(x+NUMBERS_PADDING, y+12, abs(timerState.val), LEFT|DBLSIZE|color);
|
||||
continue;
|
||||
}
|
||||
putsMixerSource(x+NUMBERS_PADDING, y+2, field, color);
|
||||
putsChannel(x+NUMBERS_PADDING, y+12, field, LEFT|DBLSIZE|NO_UNIT|color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void displayCustomTelemetryScreen(uint8_t index)
|
||||
{
|
||||
FrSkyScreenData & screen = g_model.frsky.screens[index];
|
||||
|
||||
#if defined(GAUGES)
|
||||
if (IS_BARS_SCREEN(index)) {
|
||||
return displayGaugesTelemetryScreen(screen);
|
||||
}
|
||||
#endif
|
||||
|
||||
displayNumbersTelemetryScreen(screen);
|
||||
}
|
||||
|
||||
void displayTelemetryScreen(int index, unsigned int evt)
|
||||
{
|
||||
#if defined(LUA)
|
||||
if (TELEMETRY_SCREEN_TYPE(index) == TELEMETRY_SCREEN_TYPE_SCRIPT) {
|
||||
luaTask(evt, RUN_TELEM_FG_SCRIPT, true);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (TELEMETRY_SCREEN_TYPE(index) == TELEMETRY_SCREEN_TYPE_NONE) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (index < MAX_TELEMETRY_SCREENS) {
|
||||
return displayCustomTelemetryScreen(index);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
* Authors (alphabetical order)
|
||||
* - Andre Bernet <bernet.andre@gmail.com>
|
||||
* - Andreas Weitl
|
||||
* - Bertrand Songis <bsongis@gmail.com>
|
||||
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
|
||||
* - Cameron Weeks <th9xer@gmail.com>
|
||||
* - Erez Raviv
|
||||
* - Gabriel Birkus
|
||||
* - Jean-Pierre Parisy
|
||||
* - Karl Szmutny
|
||||
* - Michael Blandford
|
||||
* - Michal Hlavinka
|
||||
* - Pat Mackenzie
|
||||
* - Philip Moss
|
||||
* - Rob Thomson
|
||||
* - Romolo Manfredini <romolo.manfredini@gmail.com>
|
||||
* - 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_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<TEXT_FILE_MAXSIZE && f_read(&file, &c, 1, &sz)==FR_OK && sz==1 && (lines_count==0 || current_line-s_pgOfs<LCD_LINES-1); i++) {
|
||||
if (c == '\n') {
|
||||
++current_line;
|
||||
line_length = 0;
|
||||
escape = 0;
|
||||
}
|
||||
else if (c!='\r' && current_line>=s_pgOfs && current_line-s_pgOfs<LCD_LINES-1 && line_length<LCD_COLS) {
|
||||
if (c=='\\' && escape==0) {
|
||||
escape = 1;
|
||||
continue;
|
||||
}
|
||||
else if (c!='\\' && escape>0 && 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(evt_t event)
|
||||
{
|
||||
static int lines_count;
|
||||
|
||||
drawMenuTemplate("TEXT VIEWER", event);
|
||||
|
||||
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--;
|
||||
readTextFile(lines_count);
|
||||
break;
|
||||
|
||||
case EVT_KEY_FIRST(KEY_DOWN):
|
||||
if (s_pgOfs+NUM_BODY_LINES >= lines_count)
|
||||
break;
|
||||
else
|
||||
++s_pgOfs;
|
||||
readTextFile(lines_count);
|
||||
break;
|
||||
|
||||
case EVT_KEY_BREAK(KEY_EXIT):
|
||||
popMenu();
|
||||
break;
|
||||
}
|
||||
|
||||
for (int i=0; i<NUM_BODY_LINES; i++) {
|
||||
lcd_puts(MENU_TITLE_LEFT, MENU_CONTENT_TOP + i*FH, s_text_screen[i]);
|
||||
}
|
||||
|
||||
char *title = s_text_file;
|
||||
#if defined(SIMU)
|
||||
if (!strncmp(title, "./", 2)) title += 2;
|
||||
#endif
|
||||
lcd_putsCenter(MENU_FOOTER_TOP, title, HEADER_COLOR);
|
||||
|
||||
if (lines_count > NUM_BODY_LINES) {
|
||||
displayScrollbar(LCD_W-5, 30, MENU_FOOTER_TOP-34, s_pgOfs, lines_count, NUM_BODY_LINES);
|
||||
}
|
||||
}
|
||||
|
||||
void pushMenuTextView(const char *filename)
|
||||
{
|
||||
if (strlen(filename) < TEXT_FILENAME_MAXLEN) {
|
||||
strcpy(s_text_file, filename);
|
||||
pushMenu(menuTextView);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,315 @@
|
||||
/*
|
||||
* Authors (alphabetical order)
|
||||
* - Andre Bernet <bernet.andre@gmail.com>
|
||||
* - Andreas Weitl
|
||||
* - Bertrand Songis <bsongis@gmail.com>
|
||||
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
|
||||
* - Cameron Weeks <th9xer@gmail.com>
|
||||
* - Erez Raviv
|
||||
* - Gabriel Birkus
|
||||
* - Jean-Pierre Parisy
|
||||
* - Karl Szmutny
|
||||
* - Michael Blandford
|
||||
* - Michal Hlavinka
|
||||
* - Pat Mackenzie
|
||||
* - Philip Moss
|
||||
* - Rob Thomson
|
||||
* - Romolo Manfredini <romolo.manfredini@gmail.com>
|
||||
* - 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"
|
||||
#include <stdio.h>
|
||||
|
||||
#define COLUMN_HEADER_X 150
|
||||
void displayHeader(const char *header)
|
||||
{
|
||||
lcd_putsAtt(COLUMN_HEADER_X, MENU_FOOTER_TOP, header, HEADER_COLOR);
|
||||
}
|
||||
|
||||
void displayColumnHeader(const char * const *headers, uint8_t index)
|
||||
{
|
||||
displayHeader(headers[index]);
|
||||
}
|
||||
|
||||
void drawStick(coord_t centrex, int16_t xval, int16_t yval)
|
||||
{
|
||||
#define BOX_CENTERY (170 - FH - BOX_WIDTH/2)
|
||||
#define MARKER_WIDTH 5
|
||||
|
||||
lcd_square(centrex-BOX_WIDTH/2, BOX_CENTERY-BOX_WIDTH/2, BOX_WIDTH, TEXT_COLOR);
|
||||
lcd_vlineStip(centrex, BOX_CENTERY-1, 3, SOLID, TEXT_COLOR);
|
||||
lcd_hlineStip(centrex-1, BOX_CENTERY, 3, SOLID, TEXT_COLOR);
|
||||
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|TEXT_COLOR);
|
||||
|
||||
#undef BOX_CENTERY
|
||||
#undef MARKER_WIDTH
|
||||
}
|
||||
|
||||
void lcdDrawCheckBox(coord_t x, coord_t y, uint8_t value, LcdFlags attr)
|
||||
{
|
||||
if (attr) {
|
||||
lcdDrawFilledRect(x-1, y+2, 13, 13, TEXT_INVERTED_BGCOLOR);
|
||||
lcdDrawFilledRect(x+1, y+4, 9, 9, TEXT_BGCOLOR);
|
||||
if (value) {
|
||||
lcdDrawFilledRect(x+2, y+5, 7, 7, TEXT_INVERTED_BGCOLOR);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (value) {
|
||||
lcdDrawFilledRect(x+2, y+5, 7, 7, SCROLLBOX_COLOR);
|
||||
lcdDrawRect(x, y+3, 11, 11, LINE_COLOR);
|
||||
}
|
||||
else {
|
||||
lcdDrawRect(x, y+3, 11, 11, LINE_COLOR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void displayScreenIndex(uint8_t index, uint8_t count)
|
||||
{
|
||||
// char str[10];
|
||||
// sprintf(str, "%d/%d", index+1, count);
|
||||
// lcd_putsAtt(LCD_W-8-getTextWidth(str), MENU_FOOTER_TOP, str, m_posVert < 0 ? INVERS : TEXT_COLOR);
|
||||
}
|
||||
|
||||
void displayScrollbar(coord_t x, coord_t y, coord_t h, uint16_t offset, uint16_t count, uint8_t visible)
|
||||
{
|
||||
lcdDrawVerticalLine(x, y, h, LINE_COLOR);
|
||||
coord_t yofs = (h*offset + count/2) / count;
|
||||
coord_t yhgt = (h*visible + count/2) / count;
|
||||
if (yhgt + yofs > h)
|
||||
yhgt = h - yofs;
|
||||
lcdDrawFilledRect(x-1, y + yofs, 3, yhgt, SCROLLBOX_COLOR);
|
||||
}
|
||||
|
||||
void displayProgressBar(const char *label)
|
||||
{
|
||||
lcd_putsLeft(4*FH, label);
|
||||
lcd_rect(3, 6*FH+4, 204, 7);
|
||||
lcdRefresh();
|
||||
}
|
||||
|
||||
void updateProgressBar(int num, int den)
|
||||
{
|
||||
if (num > 0 && den > 0) {
|
||||
int width = (200*num)/den;
|
||||
lcd_hline(5, 6*FH+6, width, FORCE);
|
||||
lcd_hline(5, 6*FH+7, width, FORCE);
|
||||
lcd_hline(5, 6*FH+8, width, FORCE);
|
||||
lcdRefresh();
|
||||
}
|
||||
}
|
||||
|
||||
void title(const pm_char * s)
|
||||
{
|
||||
int width = getTextWidth(s);
|
||||
lcd_putsAtt(MENU_TITLE_LEFT, MENU_TITLE_TOP+2, s, MENU_TITLE_COLOR);
|
||||
}
|
||||
|
||||
const uint8_t LBM_MODEL_SETUP_ICON[] = {
|
||||
#include "../../bitmaps/Horus/mask_model_setup.lbm"
|
||||
};
|
||||
|
||||
const uint8_t LBM_HELI_ICON[] = {
|
||||
#include "../../bitmaps/Horus/mask_heli.lbm"
|
||||
};
|
||||
|
||||
const uint8_t LBM_FLIGHT_MODES_ICON[] = {
|
||||
#include "../../bitmaps/Horus/mask_flight_modes.lbm"
|
||||
};
|
||||
|
||||
const uint8_t LBM_INPUTS_ICON[] = {
|
||||
#include "../../bitmaps/Horus/mask_inputs.lbm"
|
||||
};
|
||||
|
||||
const uint8_t LBM_MIXER_ICON[] = {
|
||||
#include "../../bitmaps/Horus/mask_mixer.lbm"
|
||||
};
|
||||
|
||||
const uint8_t LBM_OUTPUTS_ICON[] = {
|
||||
#include "../../bitmaps/Horus/mask_outputs.lbm"
|
||||
};
|
||||
|
||||
const uint8_t LBM_CURVES_ICON[] = {
|
||||
#include "../../bitmaps/Horus/mask_curves.lbm"
|
||||
};
|
||||
|
||||
const uint8_t LBM_GVARS_ICON[] = {
|
||||
#include "../../bitmaps/Horus/mask_gvars.lbm"
|
||||
};
|
||||
|
||||
const uint8_t LBM_LOGICAL_SWITCHES_ICON[] = {
|
||||
#include "../../bitmaps/Horus/mask_logical_switches.lbm"
|
||||
};
|
||||
|
||||
const uint8_t LBM_SPECIAL_FUNCTIONS_ICON[] = {
|
||||
#include "../../bitmaps/Horus/mask_special_functions.lbm"
|
||||
};
|
||||
|
||||
const uint8_t LBM_LUA_SCRIPTS_ICON[] = {
|
||||
#include "../../bitmaps/Horus/mask_lua_scripts.lbm"
|
||||
};
|
||||
|
||||
const uint8_t LBM_TELEMETRY_ICON[] = {
|
||||
#include "../../bitmaps/Horus/mask_telemetry.lbm"
|
||||
};
|
||||
const uint8_t * const LBM_MODEL_ICONS[] = {
|
||||
LBM_MODEL_SETUP_ICON,
|
||||
CASE_HELI(LBM_HELI_ICON)
|
||||
CASE_FLIGHT_MODES(LBM_FLIGHT_MODES_ICON)
|
||||
LBM_INPUTS_ICON,
|
||||
LBM_MIXER_ICON,
|
||||
LBM_OUTPUTS_ICON,
|
||||
CASE_CURVES(LBM_CURVES_ICON)
|
||||
CASE_GVARS(LBM_GVARS_ICON)
|
||||
LBM_LOGICAL_SWITCHES_ICON,
|
||||
LBM_SPECIAL_FUNCTIONS_ICON,
|
||||
#if defined(LUA_MODEL_SCRIPTS)
|
||||
LBM_LUA_SCRIPTS_ICON,
|
||||
#endif
|
||||
LBM_TELEMETRY_ICON
|
||||
};
|
||||
|
||||
const uint8_t LBM_BALL[] = {
|
||||
#include "../../bitmaps/Horus/mask_ball.lbm"
|
||||
};
|
||||
|
||||
#define MENU_ICONS_SPACING 34
|
||||
|
||||
void drawMenuTemplate(const char *name, evt_t event, int pageIndex, int pageCount)
|
||||
{
|
||||
// clear the screen
|
||||
lcdDrawFilledRect(0, 0, LCD_W, MENU_HEADER_HEIGHT, HEADER_BGCOLOR);
|
||||
lcdDrawFilledRect(0, MENU_TITLE_TOP, LCD_W, MENU_TITLE_HEIGHT, TITLE_BGCOLOR);
|
||||
lcdDrawFilledRect(0, MENU_BODY_TOP, LCD_W, MENU_BODY_HEIGHT, TEXT_BGCOLOR);
|
||||
lcdDrawFilledRect(0, MENU_FOOTER_TOP, LCD_W, MENU_FOOTER_HEIGHT, HEADER_BGCOLOR);
|
||||
|
||||
lcdDrawFilledRect(58+pageIndex*MENU_ICONS_SPACING-11, 0, 36, MENU_HEADER_HEIGHT, TITLE_BGCOLOR);
|
||||
|
||||
for (int i=0; i<pageCount; i++) {
|
||||
lcdDrawBitmapPattern(50+i*MENU_ICONS_SPACING, 7, LBM_MODEL_ICONS[i], MENU_TITLE_COLOR);
|
||||
}
|
||||
|
||||
lcdDrawBitmapPattern(58+pageIndex*MENU_ICONS_SPACING, MENU_TITLE_TOP-9, LBM_BALL, MENU_TITLE_COLOR);
|
||||
|
||||
if (name) {
|
||||
// header
|
||||
title(name);
|
||||
}
|
||||
|
||||
if (pageCount > 0) {
|
||||
displayScreenIndex(pageIndex, pageCount);
|
||||
}
|
||||
}
|
||||
|
||||
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, evt_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, evt_t event )
|
||||
{
|
||||
lcdDrawCheckBox(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, evt_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)
|
||||
{
|
||||
const int width = 50;
|
||||
lcd_hlineStip(x, y+5, width, SOLID, TEXT_COLOR);
|
||||
if (attr && (!(attr & BLINK) || !BLINK_ON_PHASE)) {
|
||||
lcdDrawFilledRect(x+value*(width-5)/max, y, 5, 11, TEXT_INVERTED_BGCOLOR);
|
||||
}
|
||||
else {
|
||||
lcdDrawFilledRect(x+value*(width-5)/max, y, 5, 11, LINE_COLOR);
|
||||
}
|
||||
}
|
||||
|
||||
#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, evt_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 -= 20;
|
||||
|
||||
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;
|
||||
putsStrIdx(x, y, STR_GV, idx, attr, "-");
|
||||
}
|
||||
else {
|
||||
putsStrIdx(x, y, STR_GV, idx, attr);
|
||||
value = (int16_t) GV_CALC_VALUE_IDX_POS(idx-1, delta);
|
||||
}
|
||||
}
|
||||
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, evt_t event)
|
||||
{
|
||||
lcd_outdezAtt(x, y, value, attr, "%");
|
||||
if (attr&INVERS) value = checkIncDec(event, value, min, max, EE_MODEL);
|
||||
return value;
|
||||
}
|
||||
#endif
|
||||
+5
-1
@@ -37,7 +37,11 @@
|
||||
#ifndef _GUI_H_
|
||||
#define _GUI_H_
|
||||
|
||||
#if defined(PCBTARANIS)
|
||||
#if defined(PCBHORUS)
|
||||
#include "Horus/gui.h"
|
||||
#elif defined(PCBFLAMENCO)
|
||||
#include "Flamenco/gui.h"
|
||||
#elif defined(PCBTARANIS)
|
||||
#include "Taranis/gui.h"
|
||||
#else
|
||||
#include "9X/gui.h"
|
||||
|
||||
@@ -54,7 +54,8 @@ void hapticQueue::heartbeat()
|
||||
#else
|
||||
if (buzzTimeLeft > 0) {
|
||||
buzzTimeLeft--; // time gets counted down
|
||||
#if defined(PCBSKY9X) || (defined(PCBTARANIS) && defined(REVPLUS))
|
||||
#if defined(PCBSKY9X) || (defined(PCBTARANIS) && defined(REVPLUS)) || defined(PCBFLAMENCO) || defined(PCBHORUS)
|
||||
// TODO define HAPTIC_PWM option
|
||||
hapticOn(HAPTIC_STRENGTH() * 20);
|
||||
#else
|
||||
if (hapticTick-- > 0) {
|
||||
|
||||
+10
-11
@@ -36,15 +36,15 @@
|
||||
|
||||
#include "opentx.h"
|
||||
|
||||
uint8_t s_evt;
|
||||
evt_t s_evt;
|
||||
struct t_inactivity inactivity = {0};
|
||||
|
||||
#if defined(CPUARM)
|
||||
uint8_t getEvent(bool trim)
|
||||
evt_t getEvent(bool trim)
|
||||
{
|
||||
uint8_t evt = s_evt;
|
||||
evt_t evt = s_evt;
|
||||
int8_t k = EVT_KEY_MASK(s_evt) - TRM_BASE;
|
||||
bool trim_evt = (k>=0 && k<8);
|
||||
bool trim_evt = (k>=0 && k<TRM_LAST-TRM_BASE+1);
|
||||
|
||||
if (trim == trim_evt) {
|
||||
s_evt = 0;
|
||||
@@ -55,9 +55,9 @@ uint8_t getEvent(bool trim)
|
||||
}
|
||||
}
|
||||
#else
|
||||
uint8_t getEvent()
|
||||
evt_t getEvent()
|
||||
{
|
||||
uint8_t evt = s_evt;
|
||||
evt_t evt = s_evt;
|
||||
s_evt = 0;
|
||||
return evt;
|
||||
}
|
||||
@@ -70,26 +70,25 @@ void Key::input(bool val)
|
||||
{
|
||||
uint8_t t_vals = m_vals ;
|
||||
t_vals <<= 1 ;
|
||||
if (val) t_vals |= 1; //portbit einschieben
|
||||
if (val) t_vals |= 1;
|
||||
m_vals = t_vals ;
|
||||
|
||||
m_cnt++;
|
||||
|
||||
if (m_state && m_vals==0) { //gerade eben sprung auf 0
|
||||
if (m_state && m_vals==0) {
|
||||
if (m_state != KSTATE_KILLED) {
|
||||
putEvent(EVT_KEY_BREAK(key()));
|
||||
}
|
||||
m_cnt = 0;
|
||||
m_state = KSTATE_OFF;
|
||||
}
|
||||
switch(m_state){
|
||||
switch (m_state) {
|
||||
case KSTATE_OFF:
|
||||
if (m_vals == FFVAL) { //gerade eben sprung auf ff
|
||||
if (m_vals == FFVAL) {
|
||||
m_state = KSTATE_START;
|
||||
m_cnt = 0;
|
||||
}
|
||||
break;
|
||||
//fallthrough
|
||||
case KSTATE_START:
|
||||
putEvent(EVT_KEY_FIRST(key()));
|
||||
inactivity.counter = 0;
|
||||
|
||||
+86
-15
@@ -38,14 +38,24 @@
|
||||
#define keys_h
|
||||
|
||||
enum EnumKeys {
|
||||
#if defined(PCBHORUS)
|
||||
KEY_MENU,
|
||||
KEY_EXIT,
|
||||
KEY_ENTER,
|
||||
KEY_UP,
|
||||
KEY_DOWN,
|
||||
KEY_RIGHT,
|
||||
KEY_LEFT,
|
||||
#elif defined(PCBTARANIS) || defined(PCBFLAMENCO)
|
||||
KEY_MENU,
|
||||
KEY_EXIT,
|
||||
#if defined(PCBTARANIS)
|
||||
KEY_ENTER,
|
||||
KEY_PAGE,
|
||||
KEY_PLUS,
|
||||
KEY_MINUS,
|
||||
#else
|
||||
KEY_MENU,
|
||||
KEY_EXIT,
|
||||
KEY_DOWN,
|
||||
KEY_UP,
|
||||
KEY_RIGHT,
|
||||
@@ -62,6 +72,16 @@ enum EnumKeys {
|
||||
TRM_RH_DWN,
|
||||
TRM_RH_UP,
|
||||
|
||||
#if defined(PCBHORUS)
|
||||
TRM_LS_DWN,
|
||||
TRM_LS_UP,
|
||||
TRM_RS_DWN,
|
||||
TRM_RS_UP,
|
||||
TRM_LAST = TRM_RS_UP,
|
||||
#else
|
||||
TRM_LAST = TRM_RH_UP,
|
||||
#endif
|
||||
|
||||
#if ROTARY_ENCODERS > 0 || defined(ROTARY_ENCODER_NAVIGATION)
|
||||
BTN_REa,
|
||||
#endif
|
||||
@@ -72,7 +92,24 @@ enum EnumKeys {
|
||||
NUM_KEYS,
|
||||
SW_BASE=NUM_KEYS,
|
||||
|
||||
#if defined(PCBTARANIS)
|
||||
#if defined(PCBFLAMENCO)
|
||||
SW_SA0=SW_BASE,
|
||||
SW_SA1,
|
||||
SW_SA2,
|
||||
SW_SB0,
|
||||
SW_SB2,
|
||||
SW_SC0,
|
||||
SW_SC1,
|
||||
SW_SC2,
|
||||
SW_SC3,
|
||||
SW_SC4,
|
||||
SW_SC5,
|
||||
SW_SE0,
|
||||
SW_SE2,
|
||||
SW_SF0,
|
||||
SW_SF1,
|
||||
SW_SF2,
|
||||
#elif defined(PCBTARANIS) || defined(PCBHORUS)
|
||||
SW_SA0=SW_BASE,
|
||||
SW_SA1,
|
||||
SW_SA2,
|
||||
@@ -145,26 +182,42 @@ enum EnumKeys {
|
||||
|
||||
#define EVT_KEY_MASK(e) ((e) & 0x1f)
|
||||
|
||||
#if defined(PCBHORUS)
|
||||
#define _MSK_KEY_BREAK 0x0200
|
||||
#define _MSK_KEY_REPT 0x0400
|
||||
#define _MSK_KEY_FIRST 0x0600
|
||||
#define _MSK_KEY_LONG 0x0800
|
||||
#define _MSK_KEY_FLAGS 0x0e00
|
||||
#define EVT_ENTRY 0x1000
|
||||
#define EVT_ENTRY_UP 0x2000
|
||||
#define EVT_MENU_UP 0x4000
|
||||
#else
|
||||
#define _MSK_KEY_BREAK 0x20
|
||||
#define _MSK_KEY_REPT 0x40
|
||||
#define _MSK_KEY_FIRST 0x60
|
||||
#define _MSK_KEY_LONG 0x80
|
||||
#define _MSK_KEY_FLAGS 0xe0
|
||||
#define EVT_ENTRY 0xbf
|
||||
#define EVT_ENTRY_UP 0xbe
|
||||
#define EVT_MENU_UP 0xbd
|
||||
#endif
|
||||
|
||||
#define EVT_KEY_BREAK(key) ((key)|_MSK_KEY_BREAK)
|
||||
#define EVT_KEY_FIRST(key) ((key)|_MSK_KEY_FIRST)
|
||||
#define EVT_KEY_REPT(key) ((key)|_MSK_KEY_REPT)
|
||||
#define EVT_KEY_LONG(key) ((key)|_MSK_KEY_LONG)
|
||||
|
||||
#define IS_KEY_BREAK(evt) (((evt)&0xe0) == _MSK_KEY_BREAK)
|
||||
#define IS_KEY_FIRST(evt) (((evt)&0xe0) == _MSK_KEY_FIRST)
|
||||
#define IS_KEY_LONG(evt) (((evt)&0xe0) == _MSK_KEY_LONG)
|
||||
#define IS_KEY_REPT(evt) (((evt)&0xe0) == _MSK_KEY_REPT)
|
||||
#define IS_KEY_BREAK(evt) (((evt) & _MSK_KEY_FLAGS) == _MSK_KEY_BREAK)
|
||||
#define IS_KEY_FIRST(evt) (((evt) & _MSK_KEY_FLAGS) == _MSK_KEY_FIRST)
|
||||
#define IS_KEY_LONG(evt) (((evt) & _MSK_KEY_FLAGS) == _MSK_KEY_LONG)
|
||||
#define IS_KEY_REPT(evt) (((evt) & _MSK_KEY_FLAGS) == _MSK_KEY_REPT)
|
||||
|
||||
#define EVT_ENTRY 0xbf
|
||||
#define EVT_ENTRY_UP 0xbe
|
||||
#define EVT_MENU_UP 0xbd
|
||||
|
||||
#if defined(PCBTARANIS)
|
||||
#if defined(PCBHORUS)
|
||||
#define EVT_ROTARY_BREAK EVT_KEY_BREAK(KEY_ENTER)
|
||||
#define EVT_ROTARY_LONG EVT_KEY_LONG(KEY_ENTER)
|
||||
#define EVT_ROTARY_LEFT 0xDF00
|
||||
#define EVT_ROTARY_RIGHT 0xDE00
|
||||
#elif defined(PCBTARANIS) || defined(PCBFLAMENCO) || defined(PCBHORUS)
|
||||
#define EVT_ROTARY_BREAK EVT_KEY_BREAK(KEY_ENTER)
|
||||
#define EVT_ROTARY_LONG EVT_KEY_LONG(KEY_ENTER)
|
||||
#else
|
||||
@@ -174,7 +227,19 @@ enum EnumKeys {
|
||||
#define EVT_ROTARY_RIGHT 0xde
|
||||
#endif
|
||||
|
||||
#if defined(PCBTARANIS)
|
||||
#if defined(PCBHORUS)
|
||||
#define IS_ROTARY_LEFT(evt) (evt==EVT_KEY_FIRST(KEY_MINUS) || evt==EVT_KEY_REPT(KEY_MINUS))
|
||||
#define IS_ROTARY_RIGHT(evt) (evt==EVT_KEY_FIRST(KEY_PLUS) || evt==EVT_KEY_REPT(KEY_PLUS))
|
||||
#define IS_ROTARY_UP(evt) (evt==EVT_KEY_FIRST(KEY_PLUS) || evt==EVT_KEY_REPT(KEY_PLUS))
|
||||
#define IS_ROTARY_DOWN(evt) (evt==EVT_KEY_FIRST(KEY_MINUS) || evt==EVT_KEY_REPT(KEY_MINUS))
|
||||
#define IS_ROTARY_BREAK(evt) (evt==EVT_KEY_BREAK(KEY_ENTER))
|
||||
#define IS_ROTARY_LONG(evt) (evt==EVT_KEY_LONG(KEY_ENTER))
|
||||
#define IS_ROTARY_EVENT(evt) (0)
|
||||
#define CASE_EVT_ROTARY_BREAK /*case EVT_KEY_BREAK(KEY_ENTER):*/
|
||||
#define CASE_EVT_ROTARY_LONG /*case EVT_KEY_LONG(KEY_ENTER):*/
|
||||
#define CASE_EVT_ROTARY_LEFT case EVT_KEY_FIRST(KEY_MOVE_UP): case EVT_KEY_REPT(KEY_MOVE_UP):
|
||||
#define CASE_EVT_ROTARY_RIGHT case EVT_KEY_FIRST(KEY_MOVE_DOWN): case EVT_KEY_REPT(KEY_MOVE_DOWN):
|
||||
#elif defined(PCBTARANIS) || defined(PCBFLAMENCO)
|
||||
#define IS_ROTARY_LEFT(evt) (evt==EVT_KEY_FIRST(KEY_MINUS) || evt==EVT_KEY_REPT(KEY_MINUS))
|
||||
#define IS_ROTARY_RIGHT(evt) (evt==EVT_KEY_FIRST(KEY_PLUS) || evt==EVT_KEY_REPT(KEY_PLUS))
|
||||
#define IS_ROTARY_UP(evt) (evt==EVT_KEY_FIRST(KEY_PLUS) || evt==EVT_KEY_REPT(KEY_PLUS))
|
||||
@@ -247,7 +312,13 @@ class Key
|
||||
|
||||
extern Key keys[NUM_KEYS];
|
||||
|
||||
extern uint8_t s_evt;
|
||||
#if defined(PCBHORUS)
|
||||
typedef uint16_t evt_t;
|
||||
#else
|
||||
typedef uint8_t evt_t;
|
||||
#endif
|
||||
|
||||
extern evt_t s_evt;
|
||||
|
||||
#define putEvent(evt) s_evt = evt
|
||||
|
||||
@@ -256,10 +327,10 @@ void killEvents(uint8_t enuk);
|
||||
|
||||
#if defined(CPUARM)
|
||||
bool clearKeyEvents();
|
||||
uint8_t getEvent(bool trim=false);
|
||||
evt_t getEvent(bool trim=false);
|
||||
#else
|
||||
void clearKeyEvents();
|
||||
uint8_t getEvent();
|
||||
evt_t getEvent();
|
||||
#endif
|
||||
|
||||
uint8_t keyDown();
|
||||
|
||||
+10
-3
@@ -41,7 +41,7 @@ FIL g_oLogFile = {0};
|
||||
const pm_char * g_logError = NULL;
|
||||
uint8_t logDelay;
|
||||
|
||||
#if defined(PCBTARANIS)
|
||||
#if defined(PCBTARANIS) || defined(PCBFLAMENCO) || defined(PCBHORUS)
|
||||
#define get2PosState(sw) (switchState(SW_ ## sw ## 0) ? -1 : 1)
|
||||
#else
|
||||
#define get2PosState(sw) (switchState(SW_ ## sw) ? -1 : 1)
|
||||
@@ -49,7 +49,7 @@ uint8_t logDelay;
|
||||
|
||||
#define get3PosState(sw) (switchState(SW_ ## sw ## 0) ? -1 : (switchState(SW_ ## sw ## 2) ? 1 : 0))
|
||||
|
||||
const pm_char *openLogs()
|
||||
const pm_char * openLogs()
|
||||
{
|
||||
// Determine and set log file filename
|
||||
FRESULT result;
|
||||
@@ -330,7 +330,14 @@ void writeLogs()
|
||||
f_printf(&g_oLogFile, "%d,", calibratedStick[i]);
|
||||
}
|
||||
|
||||
#if defined(PCBTARANIS)
|
||||
#if defined(PCBFLAMENCO)
|
||||
int result = f_printf(&g_oLogFile, "%d,%d,%d,%d\n",
|
||||
get3PosState(SA),
|
||||
get3PosState(SB),
|
||||
// get3PosState(SC),
|
||||
get2PosState(SE),
|
||||
get3PosState(SF));
|
||||
#elif defined(PCBTARANIS) || defined(PCBHORUS)
|
||||
int result = f_printf(&g_oLogFile, "%d,%d,%d,%d,%d,%d,%d,%d\n",
|
||||
get3PosState(SA),
|
||||
get3PosState(SB),
|
||||
|
||||
+55
-5
@@ -52,7 +52,11 @@ extern "C" {
|
||||
}
|
||||
#endif
|
||||
|
||||
#include "lua_exports.inc" // this line must be after lua headers
|
||||
#if defined(PCBFLAMENCO)
|
||||
#include "lua_exports_flamenco.inc" // this line must be after lua headers
|
||||
#elif defined(PCBTARANIS)
|
||||
#include "lua_exports_taranis.inc" // this line must be after lua headers
|
||||
#endif
|
||||
|
||||
#define lua_registernumber(L, n, i) (lua_pushnumber(L, (i)), lua_setglobal(L, (n)))
|
||||
#define lua_registerint(L, n, i) (lua_pushinteger(L, (i)), lua_setglobal(L, (n)))
|
||||
@@ -463,7 +467,11 @@ static int luaLcdDrawTimer(lua_State *L)
|
||||
int y = luaL_checkinteger(L, 2);
|
||||
int seconds = luaL_checkinteger(L, 3);
|
||||
unsigned int att = luaL_optunsigned(L, 4, 0);
|
||||
#if defined(PCBFLAMENCO)
|
||||
putsTimer(x, y, seconds, att|LEFT);
|
||||
#else
|
||||
putsTimer(x, y, seconds, att|LEFT, att);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -530,6 +538,7 @@ static int luaLcdDrawSource(lua_State *L)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if !defined(PCBFLAMENCO)
|
||||
static int luaLcdDrawPixmap(lua_State *L)
|
||||
{
|
||||
if (!luaLcdAllowed) return 0;
|
||||
@@ -543,6 +552,7 @@ static int luaLcdDrawPixmap(lua_State *L)
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int luaLcdDrawRectangle(lua_State *L)
|
||||
{
|
||||
@@ -586,6 +596,7 @@ static int luaLcdDrawGauge(lua_State *L)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if !defined(PCBFLAMENCO)
|
||||
static int luaLcdDrawScreenTitle(lua_State *L)
|
||||
{
|
||||
if (!luaLcdAllowed) return 0;
|
||||
@@ -599,6 +610,7 @@ static int luaLcdDrawScreenTitle(lua_State *L)
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int luaLcdDrawCombobox(lua_State *L)
|
||||
{
|
||||
@@ -652,7 +664,11 @@ static int luaModelGetInfo(lua_State *L)
|
||||
{
|
||||
lua_newtable(L);
|
||||
lua_pushtablezstring(L, "name", g_model.header.name);
|
||||
#if defined(PCBFLAMENCO)
|
||||
lua_pushtableinteger(L, "bitmap", g_model.header.bitmap);
|
||||
#else
|
||||
lua_pushtablenzstring(L, "bitmap", g_model.header.bitmap);
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -668,8 +684,12 @@ static int luaModelSetInfo(lua_State *L)
|
||||
memcpy(modelHeaders[g_eeGeneral.currModel].name, g_model.header.name, sizeof(g_model.header.name));
|
||||
}
|
||||
else if (!strcmp(key, "bitmap")) {
|
||||
#if defined(PCBFLAMENCO)
|
||||
g_model.header.bitmap = luaL_checkinteger(L, -1);
|
||||
#else
|
||||
const char * name = luaL_checkstring(L, -1);
|
||||
strncpy(g_model.header.bitmap, name, sizeof(g_model.header.bitmap));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
eeDirty(EE_MODEL);
|
||||
@@ -1456,6 +1476,26 @@ const luaR_value_entry opentxConstants[] = {
|
||||
{ "MIDSIZE", MIDSIZE },
|
||||
{ "SMLSIZE", SMLSIZE },
|
||||
{ "INVERS", INVERS },
|
||||
#if defined(PCBFLAMENCO)
|
||||
{ "WHITE", WHITE },
|
||||
{ "BLACK", BLACK },
|
||||
{ "YELLOW", YELLOW },
|
||||
{ "BLUE", BLUE },
|
||||
{ "GREY_DEFAULT", GREY_DEFAULT },
|
||||
{ "DARKGREY", DARKGREY },
|
||||
{ "RED", RED },
|
||||
{ "LIGHTGREY", LIGHTGREY },
|
||||
{ "WHITE_ON_BLACK", WHITE_ON_BLACK },
|
||||
{ "RED_ON_BLACK", RED_ON_BLACK },
|
||||
{ "BLUE_ON_BLACK", BLUE_ON_BLACK },
|
||||
{ "GREY_ON_BLACK", GREY_ON_BLACK },
|
||||
{ "LIGHTGREY_ON_BLACK", LIGHTGREY_ON_BLACK },
|
||||
{ "YELLOW_ON_BLACK", YELLOW_ON_BLACK },
|
||||
{ "WHITE_ON_DARKGREY", WHITE_ON_DARKGREY },
|
||||
{ "WHITE_ON_BLUE", WHITE_ON_BLUE },
|
||||
{ "BLACK_ON_YELLOW", BLACK_ON_YELLOW },
|
||||
{ "LIGHTGREY_ON_YELLOW", LIGHTGREY_ON_YELLOW },
|
||||
#endif
|
||||
{ "BOLD", BOLD },
|
||||
{ "BLINK", BLINK },
|
||||
{ "FIXEDWIDTH", FIXEDWIDTH },
|
||||
@@ -1473,11 +1513,15 @@ const luaR_value_entry opentxConstants[] = {
|
||||
{ "MIXSRC_SA", MIXSRC_SA },
|
||||
{ "MIXSRC_SB", MIXSRC_SB },
|
||||
{ "MIXSRC_SC", MIXSRC_SC },
|
||||
#if defined(PCBTARANIS)
|
||||
{ "MIXSRC_SD", MIXSRC_SD },
|
||||
#endif
|
||||
{ "MIXSRC_SE", MIXSRC_SE },
|
||||
{ "MIXSRC_SF", MIXSRC_SF },
|
||||
#if defined(PCBTARANIS)
|
||||
{ "MIXSRC_SG", MIXSRC_SG },
|
||||
{ "MIXSRC_SH", MIXSRC_SH },
|
||||
#endif
|
||||
{ "MIXSRC_CH1", MIXSRC_CH1 },
|
||||
{ "SWSRC_LAST", SWSRC_LAST_LOGICAL_SWITCH },
|
||||
{ "EVT_MENU_BREAK", EVT_KEY_BREAK(KEY_MENU) },
|
||||
@@ -1553,8 +1597,10 @@ const luaL_Reg lcdLib[] = {
|
||||
{ "drawChannel", luaLcdDrawChannel },
|
||||
{ "drawSwitch", luaLcdDrawSwitch },
|
||||
{ "drawSource", luaLcdDrawSource },
|
||||
#if !defined(PCBFLAMENCO)
|
||||
{ "drawPixmap", luaLcdDrawPixmap },
|
||||
{ "drawScreenTitle", luaLcdDrawScreenTitle },
|
||||
#endif
|
||||
{ "drawCombobox", luaLcdDrawCombobox },
|
||||
{ NULL, NULL } /* sentinel */
|
||||
};
|
||||
@@ -1945,12 +1991,12 @@ void luaDoOneRunStandalone(uint8_t evt)
|
||||
return;
|
||||
}
|
||||
else if (luaDisplayStatistics) {
|
||||
lcd_hline(0, 7*FH-1, lcdLastPos+FW, ERASE);
|
||||
lcd_hline(0, 7*FH-1, lcdLastPos+6, ERASE);
|
||||
lcd_puts(0, 7*FH, "GV Use: ");
|
||||
lcd_outdezAtt(lcdLastPos, 7*FH, luaGetMemUsed(), LEFT);
|
||||
lcd_putc(lcdLastPos, 7*FH, 'b');
|
||||
lcd_hline(0, 7*FH-2, lcdLastPos+FW, FORCE);
|
||||
lcd_vlineStip(lcdLastPos+FW, 7*FH-2, FH+2, SOLID, FORCE);
|
||||
lcd_hline(0, 7*FH-2, lcdLastPos+6, FORCE);
|
||||
lcd_vlineStip(lcdLastPos+6, 7*FH-2, FH+2, SOLID, FORCE);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2021,8 +2067,12 @@ bool luaDoOneRunPermanentScript(uint8_t evt, int i, uint32_t scriptType)
|
||||
TelemetryScriptData & script = g_model.frsky.screens[sid.reference-SCRIPT_TELEMETRY_FIRST].script;
|
||||
filename = script.file;
|
||||
#endif
|
||||
if ((scriptType & RUN_TELEM_FG_SCRIPT) &&
|
||||
if ((scriptType & RUN_TELEM_FG_SCRIPT) &&
|
||||
#if defined(PCBFLAMENCO)
|
||||
(g_menuStack[0]==menuMainView && sid.reference==SCRIPT_TELEMETRY_FIRST+g_eeGeneral.view-VIEW_TELEM1)) {
|
||||
#else
|
||||
(g_menuStack[0]==menuTelemetryFrsky && sid.reference==SCRIPT_TELEMETRY_FIRST+s_frsky_view)) {
|
||||
#endif
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, sid.run);
|
||||
lua_pushinteger(L, evt);
|
||||
inputsCount = 1;
|
||||
|
||||
+111
-37
@@ -89,6 +89,7 @@ void checkSpeakerVolume()
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(EEPROM)
|
||||
void checkEeprom()
|
||||
{
|
||||
if (!usbPlugged()) {
|
||||
@@ -98,38 +99,70 @@ void checkEeprom()
|
||||
eeCheck(false);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void perMain()
|
||||
#if defined(PCBFLAMENCO)
|
||||
void guiMain(evt_t evt)
|
||||
{
|
||||
#if defined(PCBSKY9X) && !defined(REVA)
|
||||
calcConsumption();
|
||||
#endif
|
||||
checkSpeakerVolume();
|
||||
checkEeprom();
|
||||
sdMountPoll();
|
||||
writeLogs();
|
||||
handleUsbConnection();
|
||||
checkTrainerSettings();
|
||||
checkBattery();
|
||||
lcd_clear();
|
||||
|
||||
uint8_t evt = getEvent(false);
|
||||
if (evt && (g_eeGeneral.backlightMode & e_backlight_mode_keys)) backlightOn(); // on keypress turn the light on
|
||||
checkBacklight();
|
||||
#if defined(NAVIGATION_STICKS)
|
||||
uint8_t sticks_evt = getSticksNavigationEvent();
|
||||
if (sticks_evt) evt = sticks_evt;
|
||||
#endif
|
||||
|
||||
#if defined(USB_MASS_STORAGE)
|
||||
if (usbPlugged()) {
|
||||
// disable access to menus
|
||||
lcd_clear();
|
||||
menuMainView(0);
|
||||
lcdRefresh();
|
||||
return;
|
||||
#if defined(LUA)
|
||||
uint32_t t0 = get_tmr10ms();
|
||||
static uint32_t lastLuaTime = 0;
|
||||
uint16_t interval = (lastLuaTime == 0 ? 0 : (t0 - lastLuaTime));
|
||||
lastLuaTime = t0;
|
||||
if (interval > maxLuaInterval) {
|
||||
maxLuaInterval = interval;
|
||||
}
|
||||
|
||||
// run Lua scripts that don't use LCD (to use CPU time while LCD DMA is running)
|
||||
luaTask(0, RUN_MIX_SCRIPT | RUN_FUNC_SCRIPT | RUN_TELEM_BG_SCRIPT, false);
|
||||
|
||||
// wait for LCD DMA to finish before continuing, because code from this point
|
||||
// is allowed to change the contents of LCD buffer
|
||||
//
|
||||
// WARNING: make sure no code above this line does any change to the LCD display buffer!
|
||||
//
|
||||
|
||||
bool scriptWasRun = luaTask(evt, RUN_STNDAL_SCRIPT, true);
|
||||
|
||||
t0 = get_tmr10ms() - t0;
|
||||
if (t0 > maxLuaDuration) {
|
||||
maxLuaDuration = t0;
|
||||
}
|
||||
|
||||
if (!scriptWasRun)
|
||||
#endif
|
||||
|
||||
{
|
||||
// normal GUI from menus
|
||||
const char *warn = s_warning;
|
||||
uint8_t menu = s_menu_count;
|
||||
// lcd_clear();
|
||||
if (menuEvent) {
|
||||
m_posVert = menuEvent == EVT_ENTRY_UP ? g_menuPos[g_menuStackPtr] : 0;
|
||||
m_posHorz = 0;
|
||||
evt = menuEvent;
|
||||
menuEvent = 0;
|
||||
AUDIO_MENUS();
|
||||
}
|
||||
g_menuStack[g_menuStackPtr]((warn || menu) ? 0 : evt);
|
||||
if (warn) DISPLAY_WARNING(evt);
|
||||
if (menu) {
|
||||
const char * result = displayMenu(evt);
|
||||
if (result) {
|
||||
menuHandler(result);
|
||||
putEvent(EVT_MENU_UP);
|
||||
}
|
||||
}
|
||||
drawStatusLine();
|
||||
}
|
||||
|
||||
lcdRefresh();
|
||||
}
|
||||
#else
|
||||
void guiMain(evt_t evt)
|
||||
{
|
||||
#if defined(LUA)
|
||||
uint32_t t0 = get_tmr10ms();
|
||||
static uint32_t lastLuaTime = 0;
|
||||
@@ -172,9 +205,11 @@ void perMain()
|
||||
// normal GUI from menus
|
||||
const char *warn = s_warning;
|
||||
uint8_t menu = s_menu_count;
|
||||
#if !defined(COLORLCD)
|
||||
if (refreshScreen) {
|
||||
lcd_clear();
|
||||
}
|
||||
#endif
|
||||
if (menuEvent) {
|
||||
m_posVert = menuEvent == EVT_ENTRY_UP ? g_menuPos[g_menuStackPtr] : 0;
|
||||
m_posHorz = 0;
|
||||
@@ -195,19 +230,44 @@ void perMain()
|
||||
}
|
||||
|
||||
lcdRefresh();
|
||||
|
||||
#if defined(REV9E) && !defined(SIMU)
|
||||
topLcdRefreshStart();
|
||||
setTopFirstTimer(getValue(MIXSRC_FIRST_TIMER+g_model.topLcdTimer));
|
||||
setTopSecondTimer(g_eeGeneral.globalTimer + sessionTimer);
|
||||
setTopRssi(TELEMETRY_RSSI());
|
||||
setTopBatteryValue(g_vbat100mV);
|
||||
setTopBatteryState(GET_TXBATT_BARS(), IS_TXBATT_WARNING());
|
||||
topLcdRefreshEnd();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(REV9E) && !defined(SIMU)
|
||||
bluetoothWakeup();
|
||||
void perMain()
|
||||
{
|
||||
#if defined(PCBSKY9X) && !defined(REVA)
|
||||
calcConsumption();
|
||||
#endif
|
||||
checkSpeakerVolume();
|
||||
#if defined(EEPROM)
|
||||
checkEeprom();
|
||||
#endif
|
||||
sdMountPoll();
|
||||
writeLogs();
|
||||
handleUsbConnection();
|
||||
checkTrainerSettings();
|
||||
checkBattery();
|
||||
|
||||
evt_t evt = getEvent(false);
|
||||
if (evt && (g_eeGeneral.backlightMode & e_backlight_mode_keys)) backlightOn(); // on keypress turn the light on
|
||||
doLoopCommonActions();
|
||||
#if defined(NAVIGATION_STICKS)
|
||||
uint8_t sticks_evt = getSticksNavigationEvent();
|
||||
if (sticks_evt) evt = sticks_evt;
|
||||
#endif
|
||||
|
||||
#if defined(USB_MASS_STORAGE)
|
||||
if (usbPlugged()) {
|
||||
// disable access to menus
|
||||
lcd_clear();
|
||||
menuMainView(0);
|
||||
lcdRefresh();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(GUI)
|
||||
guiMain(evt);
|
||||
#endif
|
||||
|
||||
#if defined(PCBTARANIS)
|
||||
@@ -217,4 +277,18 @@ void perMain()
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(PCBTARANIS) && defined(REV9E) && !defined(SIMU)
|
||||
topLcdRefreshStart();
|
||||
setTopFirstTimer(getValue(MIXSRC_FIRST_TIMER+g_model.topLcdTimer));
|
||||
setTopSecondTimer(g_eeGeneral.globalTimer + sessionTimer);
|
||||
setTopRssi(TELEMETRY_RSSI());
|
||||
setTopBatteryValue(g_vbat100mV);
|
||||
setTopBatteryState(GET_TXBATT_BARS(), IS_TXBATT_WARNING());
|
||||
topLcdRefreshEnd();
|
||||
#endif
|
||||
|
||||
#if defined(PCBTARANIS) && defined(REV9E) && !defined(SIMU)
|
||||
bluetoothWakeup();
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
@@ -110,11 +110,11 @@ void perMain()
|
||||
writeLogs();
|
||||
#endif
|
||||
|
||||
uint8_t evt = getEvent();
|
||||
evt_t evt = getEvent();
|
||||
evt = checkTrim(evt);
|
||||
|
||||
if (evt && (g_eeGeneral.backlightMode & e_backlight_mode_keys)) backlightOn(); // on keypress turn the light on
|
||||
checkBacklight();
|
||||
doLoopCommonActions();
|
||||
|
||||
#if defined(FRSKY) || defined(MAVLINK)
|
||||
telemetryWakeup();
|
||||
|
||||
+8
-1
@@ -281,7 +281,14 @@ getvalue_t getValue(mixsrc_t i)
|
||||
|
||||
else if (i<=MIXSRC_TrimAil) return calc1000toRESX((int16_t)8 * getTrimValue(mixerCurrentFlightMode, i-MIXSRC_TrimRud));
|
||||
|
||||
#if defined(PCBTARANIS)
|
||||
#if defined(PCBFLAMENCO)
|
||||
else if (i==MIXSRC_SA) return (switchState(SW_SA0) ? -1024 : (switchState(SW_SA1) ? 0 : 1024));
|
||||
else if (i==MIXSRC_SB) return (switchState(SW_SB0) ? -1024 : 1024);
|
||||
else if (i==MIXSRC_SC) return (switchState(SW_SC0) ? -1024 : (switchState(SW_SC1) ? 0 : 1024));
|
||||
// else if (i==MIXSRC_SD) return (switchState(SW_SD0) ? -1024 : 1024);
|
||||
else if (i==MIXSRC_SE) return (switchState(SW_SE0) ? -1024 : 1024);
|
||||
else if (i==MIXSRC_SF) return (switchState(SW_SF0) ? -1024 : (switchState(SW_SF1) ? 0 : 1024));
|
||||
#elif defined(PCBTARANIS) || defined(PCBHORUS)
|
||||
else if ((i >= MIXSRC_FIRST_SWITCH) && (i <= MIXSRC_LAST_SWITCH)) {
|
||||
mixsrc_t sw = i-MIXSRC_FIRST_SWITCH;
|
||||
if (SWITCH_EXISTS(sw)) {
|
||||
|
||||
+177
-41
@@ -61,10 +61,7 @@
|
||||
#define WARN_MEM (!(g_eeGeneral.warnOpts & WARN_MEM_BIT))
|
||||
#define BEEP_VAL ( (g_eeGeneral.warnOpts & WARN_BVAL_BIT) >>3 )
|
||||
|
||||
#if defined(PCBTARANIS)
|
||||
#define EEPROM_VER 218
|
||||
#define FIRST_CONV_EEPROM_VER 216
|
||||
#elif defined(PCBSKY9X)
|
||||
#if defined(CPUARM)
|
||||
#define EEPROM_VER 218
|
||||
#define FIRST_CONV_EEPROM_VER 216
|
||||
#elif defined(CPUM2560) || defined(CPUM2561)
|
||||
@@ -110,7 +107,35 @@
|
||||
|
||||
#define NUM_STICKS 4
|
||||
|
||||
#if defined(PCBTARANIS)
|
||||
#if defined(PCBHORUS)
|
||||
#define MAX_MODELS 60
|
||||
#define NUM_CHNOUT 32 // number of real output channels CH1-CH32
|
||||
#define MAX_FLIGHT_MODES 9
|
||||
#define MAX_MIXERS 64
|
||||
#define MAX_EXPOS 64
|
||||
#define NUM_LOGICAL_SWITCH 32 // number of custom switches
|
||||
#define NUM_CFN 64 // number of functions assigned to switches
|
||||
#define MAX_SCRIPTS 7
|
||||
#define MAX_INPUTS 32
|
||||
#define NUM_TRAINER 16
|
||||
#define NUM_POTS 3
|
||||
#define NUM_XPOTS 0
|
||||
#define MAX_SENSORS 32
|
||||
#elif defined(PCBFLAMENCO)
|
||||
#define MAX_MODELS 60
|
||||
#define NUM_CHNOUT 32 // number of real output channels CH1-CH32
|
||||
#define MAX_FLIGHT_MODES 9
|
||||
#define MAX_MIXERS 64
|
||||
#define MAX_EXPOS 64
|
||||
#define NUM_LOGICAL_SWITCH 32 // number of custom switches
|
||||
#define NUM_CFN 64 // number of functions assigned to switches
|
||||
#define MAX_SCRIPTS 7
|
||||
#define MAX_INPUTS 32
|
||||
#define NUM_TRAINER 16
|
||||
#define NUM_POTS 3
|
||||
#define NUM_XPOTS 0
|
||||
#define MAX_SENSORS 32
|
||||
#elif defined(PCBTARANIS)
|
||||
#define MAX_MODELS 60
|
||||
#define NUM_CHNOUT 32 // number of real output channels CH1-CH32
|
||||
#define MAX_FLIGHT_MODES 9
|
||||
@@ -210,7 +235,27 @@ struct CurveInfo {
|
||||
extern CurveInfo curveInfo(uint8_t idx);
|
||||
#endif
|
||||
|
||||
#if defined(PCBTARANIS)
|
||||
#if defined(PCBHORUS)
|
||||
#define LEN_MODEL_NAME 12
|
||||
#define LEN_TIMER_NAME 8
|
||||
#define LEN_FLIGHT_MODE_NAME 10
|
||||
#define LEN_EXPOMIX_NAME 6
|
||||
#define LEN_CHANNEL_NAME 6
|
||||
#define LEN_INPUT_NAME 4
|
||||
#define MAX_CURVES 32
|
||||
#define NUM_POINTS 512
|
||||
#define CURVDATA CurveInfo
|
||||
#elif defined(PCBFLAMENCO)
|
||||
#define LEN_MODEL_NAME 12
|
||||
#define LEN_TIMER_NAME 8
|
||||
#define LEN_FLIGHT_MODE_NAME 10
|
||||
#define LEN_EXPOMIX_NAME 6
|
||||
#define LEN_CHANNEL_NAME 6
|
||||
#define LEN_INPUT_NAME 4
|
||||
#define MAX_CURVES 32
|
||||
#define NUM_POINTS 512
|
||||
#define CURVDATA CurveInfo
|
||||
#elif defined(PCBTARANIS)
|
||||
#define LEN_MODEL_NAME 12
|
||||
#define LEN_TIMER_NAME 8
|
||||
#define LEN_FLIGHT_MODE_NAME 10
|
||||
@@ -301,7 +346,18 @@ PACK(typedef struct {
|
||||
int8_t value:6;
|
||||
}) FrSkyRSSIAlarm;
|
||||
|
||||
#if defined(PCBTARANIS)
|
||||
#if defined(PCBFLAMENCO) || defined(PCBHORUS)
|
||||
enum MainViews {
|
||||
VIEW_BLANK,
|
||||
VIEW_TIMERS_ALTITUDE,
|
||||
VIEW_CHANNELS,
|
||||
VIEW_TELEM1,
|
||||
VIEW_TELEM2,
|
||||
VIEW_TELEM3,
|
||||
VIEW_TELEM4,
|
||||
VIEW_COUNT
|
||||
};
|
||||
#elif defined(PCBTARANIS)
|
||||
enum MainViews {
|
||||
VIEW_TIMERS,
|
||||
VIEW_INPUTS,
|
||||
@@ -365,20 +421,45 @@ enum BeeperMode {
|
||||
#define swarnenable_t uint8_t
|
||||
#endif
|
||||
|
||||
#if defined(PCBTARANIS)
|
||||
enum UartModes {
|
||||
UART_MODE_NONE,
|
||||
UART_MODE_TELEMETRY_MIRROR,
|
||||
UART_MODE_TELEMETRY,
|
||||
UART_MODE_SBUS_TRAINER,
|
||||
// UART_MODE_CPPM_TRAINER,
|
||||
#if defined(DEBUG)
|
||||
UART_MODE_DEBUG,
|
||||
#endif
|
||||
UART_MODE_COUNT,
|
||||
UART_MODE_MAX = UART_MODE_COUNT-1
|
||||
};
|
||||
enum UartModes {
|
||||
#if defined(CLI) || defined(DEBUG)
|
||||
UART_MODE_DEBUG,
|
||||
#else
|
||||
UART_MODE_NONE,
|
||||
#endif
|
||||
UART_MODE_TELEMETRY_MIRROR,
|
||||
UART_MODE_TELEMETRY,
|
||||
UART_MODE_SBUS_TRAINER,
|
||||
// UART_MODE_CPPM_TRAINER,
|
||||
UART_MODE_COUNT,
|
||||
UART_MODE_MAX = UART_MODE_COUNT-1
|
||||
};
|
||||
|
||||
#if defined(PCBHORUS)
|
||||
#define LEN_SWITCH_NAME 3
|
||||
#define LEN_ANA_NAME 3
|
||||
#define EXTRA_GENERAL_FIELDS \
|
||||
EXTRA_GENERAL_FIELDS_ARM \
|
||||
uint8_t serial2Mode:6; \
|
||||
uint8_t spare:2; \
|
||||
CustomFunctionData customFn[NUM_CFN]; \
|
||||
uint32_t switchConfig; \
|
||||
uint8_t potsType; /*two bits for every pot*/\
|
||||
char switchNames[NUM_SWITCHES][LEN_SWITCH_NAME]; \
|
||||
char anaNames[NUM_STICKS+NUM_POTS][LEN_ANA_NAME];
|
||||
#elif defined(PCBFLAMENCO)
|
||||
#define LEN_SWITCH_NAME 3
|
||||
#define LEN_ANA_NAME 3
|
||||
#define EXTRA_GENERAL_FIELDS \
|
||||
EXTRA_GENERAL_FIELDS_ARM \
|
||||
uint8_t serial2Mode:6; \
|
||||
uint8_t spare:2; \
|
||||
CustomFunctionData customFn[NUM_CFN]; \
|
||||
uint32_t switchConfig; \
|
||||
uint8_t potsType; /*two bits for every pot*/\
|
||||
char switchNames[NUM_SWITCHES][LEN_SWITCH_NAME]; \
|
||||
char anaNames[NUM_STICKS+NUM_POTS][LEN_ANA_NAME];
|
||||
#elif defined(PCBTARANIS)
|
||||
#define LEN_SWITCH_NAME 3
|
||||
#define LEN_ANA_NAME 3
|
||||
#define LEN_BLUETOOTH_NAME 10
|
||||
@@ -391,7 +472,6 @@ enum BeeperMode {
|
||||
#else
|
||||
#define BLUETOOTH_FIELDS
|
||||
#endif
|
||||
|
||||
#define EXTRA_GENERAL_FIELDS \
|
||||
EXTRA_GENERAL_FIELDS_ARM \
|
||||
uint8_t serial2Mode:6; \
|
||||
@@ -442,7 +522,35 @@ PACK(typedef struct {
|
||||
int8_t inputs[MAX_SCRIPT_INPUTS];
|
||||
}) ScriptData;
|
||||
|
||||
#if defined(PCBTARANIS)
|
||||
enum PotsWarnMode {
|
||||
POTS_WARN_OFF,
|
||||
POTS_WARN_MANUAL,
|
||||
POTS_WARN_AUTO
|
||||
};
|
||||
|
||||
#if defined(PCBHORUS)
|
||||
enum ModuleIndex {
|
||||
EXTERNAL_MODULE,
|
||||
TRAINER_MODULE,
|
||||
};
|
||||
enum TrainerMode {
|
||||
TRAINER_MODE_MASTER,
|
||||
TRAINER_MODE_SLAVE
|
||||
};
|
||||
#define MODELDATA_BITMAP uint8_t bitmap;
|
||||
#define MODELDATA_EXTRA uint8_t externalModule:3; uint8_t trainerMode:3; uint8_t potsWarnMode:2; ModuleData moduleData[NUM_MODULES+1]; char curveNames[MAX_CURVES][6]; ScriptData scriptsData[MAX_SCRIPTS]; char inputNames[MAX_INPUTS][LEN_INPUT_NAME]; uint8_t potsWarnEnabled; int8_t potsWarnPosition[NUM_POTS];
|
||||
#elif defined(PCBFLAMENCO)
|
||||
enum ModuleIndex {
|
||||
EXTERNAL_MODULE,
|
||||
TRAINER_MODULE,
|
||||
};
|
||||
enum TrainerMode {
|
||||
TRAINER_MODE_MASTER,
|
||||
TRAINER_MODE_SLAVE
|
||||
};
|
||||
#define MODELDATA_BITMAP uint8_t bitmap;
|
||||
#define MODELDATA_EXTRA uint8_t externalModule:3; uint8_t trainerMode:3; uint8_t potsWarnMode:2; ModuleData moduleData[NUM_MODULES+1]; char curveNames[MAX_CURVES][6]; ScriptData scriptsData[MAX_SCRIPTS]; char inputNames[MAX_INPUTS][LEN_INPUT_NAME]; uint8_t potsWarnEnabled; int8_t potsWarnPosition[NUM_POTS];
|
||||
#elif defined(PCBTARANIS)
|
||||
enum ModuleIndex {
|
||||
INTERNAL_MODULE,
|
||||
EXTERNAL_MODULE,
|
||||
@@ -455,11 +563,6 @@ PACK(typedef struct {
|
||||
TRAINER_MODE_MASTER_CPPM_EXTERNAL_MODULE,
|
||||
TRAINER_MODE_MASTER_BATTERY_COMPARTMENT,
|
||||
};
|
||||
enum PotsWarnMode {
|
||||
POTS_WARN_OFF,
|
||||
POTS_WARN_MANUAL,
|
||||
POTS_WARN_AUTO
|
||||
};
|
||||
#define IS_TRAINER_EXTERNAL_MODULE() (g_model.trainerMode == TRAINER_MODE_MASTER_SBUS_EXTERNAL_MODULE || g_model.trainerMode == TRAINER_MODE_MASTER_CPPM_EXTERNAL_MODULE)
|
||||
#define MODELDATA_BITMAP char bitmap[LEN_BITMAP_NAME];
|
||||
#define MODELDATA_EXTRA uint8_t spare:3; uint8_t trainerMode:3; uint8_t potsWarnMode:2; ModuleData moduleData[NUM_MODULES+1]; char curveNames[MAX_CURVES][6]; ScriptData scriptsData[MAX_SCRIPTS]; char inputNames[MAX_INPUTS][LEN_INPUT_NAME]; uint8_t potsWarnEnabled; int8_t potsWarnPosition[NUM_POTS];
|
||||
@@ -494,7 +597,7 @@ enum BacklightMode {
|
||||
|
||||
#define XPOTS_MULTIPOS_COUNT 6
|
||||
|
||||
#if defined(PCBTARANIS)
|
||||
#if defined(PCBTARANIS) || defined(PCBFLAMENCO) || defined(PCBHORUS)
|
||||
PACK(typedef struct {
|
||||
uint8_t count;
|
||||
uint8_t steps[XPOTS_MULTIPOS_COUNT-1];
|
||||
@@ -720,7 +823,7 @@ PACK(typedef struct {
|
||||
#define CFN_GVAR_CST_MAX 125
|
||||
#endif
|
||||
|
||||
#if defined(PCBTARANIS)
|
||||
#if defined(PCBTARANIS) || defined(PCBFLAMENCO) || defined(PCBHORUS)
|
||||
enum SwitchConfig {
|
||||
SWITCH_NONE,
|
||||
SWITCH_TOGGLE,
|
||||
@@ -815,7 +918,7 @@ PACK(typedef struct {
|
||||
#define MODE_CURVE 1
|
||||
#endif
|
||||
|
||||
#if defined(PCBTARANIS)
|
||||
#if defined(PCBTARANIS) || defined(PCBFLAMENCO) || defined(PCBHORUS)
|
||||
PACK(typedef struct {
|
||||
uint16_t mode:2;
|
||||
uint16_t scale:14;
|
||||
@@ -876,7 +979,7 @@ PACK(typedef struct {
|
||||
#define EXPO_MODE_ENABLE(ed, v) (((v)<0 && ((ed)->mode&1)) || ((v)>=0 && ((ed)->mode&2)))
|
||||
#endif
|
||||
|
||||
#if defined(PCBTARANIS)
|
||||
#if defined(PCBTARANIS) || defined(PCBFLAMENCO) || defined(PCBHORUS)
|
||||
#define limit_min_max_t int16_t
|
||||
#define LIMIT_EXT_PERCENT 150
|
||||
#define LIMIT_EXT_MAX (LIMIT_EXT_PERCENT*10)
|
||||
@@ -900,7 +1003,7 @@ PACK(typedef struct {
|
||||
#define LIMIT_OFS_RESX(lim) calc1000toRESX(LIMIT_OFS(lim))
|
||||
#endif
|
||||
|
||||
#if defined(PCBTARANIS)
|
||||
#if defined(PCBTARANIS) || defined(PCBFLAMENCO) || defined(PCBHORUS)
|
||||
PACK(typedef struct {
|
||||
int32_t min:11;
|
||||
int32_t max:11;
|
||||
@@ -943,7 +1046,7 @@ PACK(typedef struct {
|
||||
#define SLOW_STEP 10
|
||||
#define DELAY_MAX (25*DELAY_STEP) /* 25 seconds */
|
||||
#define SLOW_MAX (25*SLOW_STEP) /* 25 seconds */
|
||||
#if defined(PCBTARANIS)
|
||||
#if defined(PCBTARANIS) || defined(PCBFLAMENCO) || defined(PCBHORUS)
|
||||
PACK(typedef struct {
|
||||
int16_t weight:11; // GV1=-1024, -GV1=1023
|
||||
uint16_t destCh:5;
|
||||
@@ -1422,7 +1525,7 @@ PACK(typedef struct {
|
||||
ls_telemetry_value_t barMax; // ditto for max display (would usually = ratio)
|
||||
}) FrSkyBarData;
|
||||
|
||||
#if defined(PCBTARANIS)
|
||||
#if defined(PCBTARANIS) || defined(PCBFLAMENCO) || defined(PCBHORUS)
|
||||
#define NUM_LINE_ITEMS 3
|
||||
#else
|
||||
#define NUM_LINE_ITEMS 2
|
||||
@@ -1432,7 +1535,7 @@ PACK(typedef struct {
|
||||
source_t sources[NUM_LINE_ITEMS];
|
||||
}) FrSkyLineData;
|
||||
|
||||
#if defined(PCBTARANIS)
|
||||
#if defined(PCBTARANIS) || defined(PCBFLAMENCO) || defined(PCBHORUS)
|
||||
#define MAX_TELEM_SCRIPT_INPUTS 8
|
||||
PACK(typedef struct {
|
||||
char file[LEN_SCRIPT_FILENAME];
|
||||
@@ -1443,7 +1546,7 @@ PACK(typedef struct {
|
||||
typedef union {
|
||||
FrSkyBarData bars[4];
|
||||
FrSkyLineData lines[4];
|
||||
#if defined(PCBTARANIS)
|
||||
#if defined(PCBTARANIS) || defined(PCBFLAMENCO) || defined(PCBHORUS)
|
||||
TelemetryScriptData script;
|
||||
#endif
|
||||
} FrSkyScreenData;
|
||||
@@ -1602,7 +1705,7 @@ PACK(typedef struct {
|
||||
#define TRIMS_ARRAY_SIZE 5
|
||||
#define trim_t int16_t
|
||||
#else
|
||||
#if defined(PCBTARANIS)
|
||||
#if defined(PCBTARANIS) || defined(PCBFLAMENCO) || defined(PCBHORUS)
|
||||
PACK(typedef struct {
|
||||
int16_t value:11;
|
||||
uint16_t mode:5;
|
||||
@@ -1643,7 +1746,25 @@ enum SwitchSources {
|
||||
|
||||
SWSRC_FIRST_SWITCH,
|
||||
|
||||
#if defined(PCBTARANIS)
|
||||
#if defined(PCBFLAMENCO)
|
||||
SWSRC_SA0 = SWSRC_FIRST_SWITCH,
|
||||
SWSRC_SA1,
|
||||
SWSRC_SA2,
|
||||
SWSRC_SB0,
|
||||
SWSRC_SB2,
|
||||
SWSRC_SC0,
|
||||
SWSRC_SC1,
|
||||
SWSRC_SC2,
|
||||
SWSRC_SC3,
|
||||
SWSRC_SC4,
|
||||
SWSRC_SC5,
|
||||
SWSRC_SE0,
|
||||
SWSRC_SE2,
|
||||
SWSRC_SF0,
|
||||
SWSRC_SF1,
|
||||
SWSRC_SF2,
|
||||
SWSRC_LAST_SWITCH = SWSRC_SF2,
|
||||
#elif defined(PCBTARANIS)
|
||||
SWSRC_SA0 = SWSRC_FIRST_SWITCH,
|
||||
SWSRC_SA1,
|
||||
SWSRC_SA2,
|
||||
@@ -1809,7 +1930,12 @@ enum MixSources {
|
||||
MIXSRC_Ail, LUA_EXPORT("ail", "Aileron")
|
||||
|
||||
MIXSRC_FIRST_POT,
|
||||
#if defined(PCBTARANIS)
|
||||
#if defined(PCBFLAMENCO)
|
||||
MIXSRC_POT1 = MIXSRC_FIRST_POT, LUA_EXPORT("sd", "Potentiometer D")
|
||||
MIXSRC_SLIDER1, LUA_EXPORT("ls", "Left slider")
|
||||
MIXSRC_SLIDER2, LUA_EXPORT("rs", "Right slider")
|
||||
MIXSRC_LAST_POT = MIXSRC_SLIDER2,
|
||||
#elif defined(PCBTARANIS)
|
||||
MIXSRC_POT1 = MIXSRC_FIRST_POT, LUA_EXPORT("s1", "Potentiometer 1")
|
||||
MIXSRC_POT2, LUA_EXPORT("s2", "Potentiometer 2")
|
||||
MIXSRC_POT3, LUA_EXPORT("s3", "Potentiometer 3")
|
||||
@@ -1864,7 +1990,13 @@ enum MixSources {
|
||||
|
||||
MIXSRC_FIRST_SWITCH,
|
||||
|
||||
#if defined(PCBTARANIS)
|
||||
#if defined(PCBFLAMENCO)
|
||||
MIXSRC_SA = MIXSRC_FIRST_SWITCH, LUA_EXPORT("sa", "Switch A")
|
||||
MIXSRC_SB, LUA_EXPORT("sb", "Switch B")
|
||||
MIXSRC_SC, LUA_EXPORT("sc", "Switch C")
|
||||
MIXSRC_SE, LUA_EXPORT("se", "Switch E")
|
||||
MIXSRC_SF, LUA_EXPORT("sf", "Switch F")
|
||||
#elif defined(PCBTARANIS) || defined(PCBHORUS)
|
||||
MIXSRC_SA = MIXSRC_FIRST_SWITCH, LUA_EXPORT("sa", "Switch A")
|
||||
MIXSRC_SB, LUA_EXPORT("sb", "Switch B")
|
||||
MIXSRC_SC, LUA_EXPORT("sc", "Switch C")
|
||||
@@ -2109,7 +2241,11 @@ PACK(typedef struct {
|
||||
enum ThrottleSources {
|
||||
THROTTLE_SOURCE_THR,
|
||||
THROTTLE_SOURCE_FIRST_POT,
|
||||
#if defined(PCBTARANIS) && defined(REV9E)
|
||||
#if defined(PCBFLAMENCO)
|
||||
THROTTLE_SOURCE_SD,
|
||||
THROTTLE_SOURCE_LS,
|
||||
THROTTLE_SOURCE_RS,
|
||||
#elif defined(PCBTARANIS) && defined(REV9E)
|
||||
THROTTLE_SOURCE_F1 = THROTTLE_SOURCE_FIRST_POT,
|
||||
THROTTLE_SOURCE_F2,
|
||||
THROTTLE_SOURCE_F3,
|
||||
|
||||
+61
-12
@@ -262,7 +262,11 @@ void generalDefault()
|
||||
g_eeGeneral.variant = EEPROM_VARIANT;
|
||||
g_eeGeneral.contrast = 25;
|
||||
|
||||
#if defined(PCBTARANIS)
|
||||
#if defined(PCBFLAMENCO)
|
||||
g_eeGeneral.vBatWarn = 33;
|
||||
g_eeGeneral.vBatMin = -60; // 0 is 9.0V
|
||||
g_eeGeneral.vBatMax = -78; // 0 is 12.0V
|
||||
#elif defined(PCBTARANIS)
|
||||
g_eeGeneral.potsConfig = 0x05; // S1 and S2 = pots with detent
|
||||
g_eeGeneral.slidersConfig = 0x03; // LS and RS = sliders with detent
|
||||
#endif
|
||||
@@ -289,11 +293,15 @@ void generalDefault()
|
||||
g_eeGeneral.stickMode = DEFAULT_MODE-1;
|
||||
#endif
|
||||
|
||||
#if defined(PCBTARANIS)
|
||||
#if defined(PCBFLAMENCO)
|
||||
g_eeGeneral.templateSetup = 21; /* AETR */
|
||||
#elif defined(PCBTARANIS)
|
||||
g_eeGeneral.templateSetup = 17; /* TAER */
|
||||
#endif
|
||||
|
||||
#if !defined(CPUM64)
|
||||
#if defined(PCBFLAMENCO)
|
||||
g_eeGeneral.inactivityTimer = 50;
|
||||
#elif !defined(CPUM64)
|
||||
g_eeGeneral.backlightMode = e_backlight_mode_all;
|
||||
g_eeGeneral.lightAutoOff = 2;
|
||||
g_eeGeneral.inactivityTimer = 10;
|
||||
@@ -963,6 +971,25 @@ void checkBacklight()
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(PCBFLAMENCO)
|
||||
void checkUsbChip()
|
||||
{
|
||||
uint8_t reg = i2cReadBQ24195(0x00);
|
||||
if (reg & 0x80) {
|
||||
i2cWriteBQ24195(0x00, reg & 0x7F);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void doLoopCommonActions()
|
||||
{
|
||||
checkBacklight();
|
||||
|
||||
#if defined(PCBFLAMENCO)
|
||||
checkUsbChip();
|
||||
#endif
|
||||
}
|
||||
|
||||
void backlightOn()
|
||||
{
|
||||
lightOffCounter = ((uint16_t)g_eeGeneral.lightAutoOff*250) << 1;
|
||||
@@ -1058,7 +1085,7 @@ void doSplash()
|
||||
}
|
||||
#endif
|
||||
|
||||
checkBacklight();
|
||||
doLoopCommonActions();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1223,7 +1250,7 @@ void checkTHR()
|
||||
break;
|
||||
}
|
||||
|
||||
checkBacklight();
|
||||
doLoopCommonActions();
|
||||
|
||||
wdt_reset();
|
||||
}
|
||||
@@ -1255,7 +1282,7 @@ void alert(const pm_char * t, const pm_char *s MESSAGE_SOUND_ARG)
|
||||
|
||||
if (keyDown()) return; // wait for key release
|
||||
|
||||
checkBacklight();
|
||||
doLoopCommonActions();
|
||||
|
||||
wdt_reset();
|
||||
|
||||
@@ -1286,7 +1313,7 @@ int8_t trimGvar[NUM_STICKS] = { -1, -1, -1, -1 };
|
||||
#if defined(CPUARM)
|
||||
void checkTrims()
|
||||
{
|
||||
uint8_t event = getEvent(true);
|
||||
evt_t event = getEvent(true);
|
||||
if (event && !IS_KEY_BREAK(event)) {
|
||||
int8_t k = EVT_KEY_MASK(event) - TRM_BASE;
|
||||
#else
|
||||
@@ -2009,7 +2036,7 @@ void checkBattery()
|
||||
if (counter-- == 0) {
|
||||
counter = 10;
|
||||
int32_t instant_vbat = anaIn(TX_VOLTAGE);
|
||||
#if defined(PCBTARANIS)
|
||||
#if defined(PCBTARANIS) || defined(PCBFLAMENCO) || defined(PCBHORUS)
|
||||
instant_vbat = (instant_vbat + instant_vbat*(g_eeGeneral.txVoltageCalibration)/128) * BATT_SCALE;
|
||||
instant_vbat >>= 11;
|
||||
instant_vbat += 2; // because of the diode
|
||||
@@ -2382,7 +2409,11 @@ uint16_t stackAvailable()
|
||||
|
||||
void opentxInit(OPENTX_INIT_ARGS)
|
||||
{
|
||||
TRACE("opentxInit()");
|
||||
|
||||
#if defined(EEPROM)
|
||||
eeReadAll();
|
||||
#endif
|
||||
|
||||
#if defined(CPUARM)
|
||||
if (UNEXPECTED_SHUTDOWN()) {
|
||||
@@ -2401,10 +2432,14 @@ void opentxInit(OPENTX_INIT_ARGS)
|
||||
}
|
||||
#endif
|
||||
|
||||
TRACE("setVolume()");
|
||||
|
||||
#if defined(VOICE)
|
||||
setVolume(g_eeGeneral.speakerVolume+VOLUME_LEVEL_DEF);
|
||||
#endif
|
||||
|
||||
TRACE("audioQueue.start()");
|
||||
|
||||
#if defined(CPUARM)
|
||||
audioQueue.start();
|
||||
setBacklight(g_eeGeneral.backlightBright);
|
||||
@@ -2431,10 +2466,12 @@ void opentxInit(OPENTX_INIT_ARGS)
|
||||
unexpectedShutdown = 1;
|
||||
#endif
|
||||
#if defined(CPUARM)
|
||||
TRACE("eeLoadModel(g_eeGeneral.currModel)");
|
||||
eeLoadModel(g_eeGeneral.currModel);
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
TRACE("opentxStart()");
|
||||
opentxStart();
|
||||
}
|
||||
|
||||
@@ -2450,7 +2487,7 @@ void opentxInit(OPENTX_INIT_ARGS)
|
||||
#endif
|
||||
backlightOn();
|
||||
|
||||
#if defined(PCBTARANIS)
|
||||
#if defined(PCBTARANIS) || defined(PCBFLAMENCO)
|
||||
serial2Init(g_eeGeneral.serial2Mode, MODEL_TELEMETRY_PROTOCOL());
|
||||
#endif
|
||||
|
||||
@@ -2462,9 +2499,12 @@ void opentxInit(OPENTX_INIT_ARGS)
|
||||
doMixerCalculations();
|
||||
#endif
|
||||
|
||||
TRACE("startPulses()");
|
||||
startPulses();
|
||||
|
||||
wdt_enable(WDTO_500MS);
|
||||
|
||||
TRACE("opentxInit() end!");
|
||||
}
|
||||
|
||||
#if !defined(SIMU)
|
||||
@@ -2488,10 +2528,15 @@ int main(void)
|
||||
|
||||
boardInit();
|
||||
|
||||
#if defined(GUI) && !defined(PCBTARANIS)
|
||||
#if defined(GUI) && !defined(PCBTARANIS) && !defined(PCBFLAMENCO) && !defined(PCBHORUS)
|
||||
// TODO remove this
|
||||
lcdInit();
|
||||
#endif
|
||||
|
||||
#if defined(COLORLCD)
|
||||
lcdColorsInit();
|
||||
#endif
|
||||
|
||||
stackPaint();
|
||||
|
||||
#if defined(GUI)
|
||||
@@ -2502,7 +2547,7 @@ int main(void)
|
||||
#endif
|
||||
|
||||
#if defined(GUI) && !defined(PCBTARANIS)
|
||||
lcdSetRefVolt(25);
|
||||
// lcdSetRefVolt(25);
|
||||
#endif
|
||||
|
||||
#if defined(PCBTARANIS)
|
||||
@@ -2550,6 +2595,10 @@ int main(void)
|
||||
uint8_t shutdown_state = 0;
|
||||
#endif
|
||||
|
||||
#if defined(PCBFLAMENCO)
|
||||
menuEntryTime = get_tmr10ms() - 200;
|
||||
#endif
|
||||
|
||||
while (1) {
|
||||
#if defined(CPUM2560)
|
||||
if ((shutdown_state=pwrCheck()) > e_power_trainer)
|
||||
@@ -2625,7 +2674,7 @@ uint32_t pwrCheck()
|
||||
lcdRefreshWait();
|
||||
lcd_clear();
|
||||
POPUP_CONFIRMATION("Confirm Shutdown");
|
||||
uint8_t evt = getEvent(false);
|
||||
evt_t evt = getEvent(false);
|
||||
DISPLAY_WARNING(evt);
|
||||
lcdRefresh();
|
||||
if (s_warning_result == true) {
|
||||
|
||||
+79
-18
@@ -283,7 +283,11 @@
|
||||
#define RESXul 1024ul
|
||||
#define RESXl 1024l
|
||||
|
||||
#if defined(PCBTARANIS)
|
||||
#if defined(PCBHORUS)
|
||||
#include "targets/Horus/board_horus.h"
|
||||
#elif defined(PCBFLAMENCO)
|
||||
#include "targets/Flamenco/board_flamenco.h"
|
||||
#elif defined(PCBTARANIS)
|
||||
#include "targets/taranis/board_taranis.h"
|
||||
#elif defined(PCBSKY9X)
|
||||
#include "targets/sky9x/board_sky9x.h"
|
||||
@@ -333,7 +337,25 @@
|
||||
#include <avr/wdt.h>
|
||||
#endif
|
||||
|
||||
#if defined(PCBTARANIS)
|
||||
#if defined(PCBHORUS)
|
||||
#define NUM_SWITCHES 5 // 8 physical switches + 6 possible from 3POS
|
||||
#define NUM_SW_SRCRAW 8
|
||||
// #define SWSRC_THR SWSRC_SF2
|
||||
// #define SWSRC_GEA SWSRC_SG2
|
||||
// #define SWSRC_ID0 SWSRC_SA0
|
||||
// #define SWSRC_ID1 SWSRC_SA1
|
||||
// #define SWSRC_ID2 SWSRC_SA2
|
||||
// #define SW_DSM2_BIND SW_SH2
|
||||
#elif defined(PCBFLAMENCO)
|
||||
#define NUM_SWITCHES 5 // 8 physical switches + 6 possible from 3POS
|
||||
#define NUM_SW_SRCRAW 8
|
||||
// #define SWSRC_THR SWSRC_SF2
|
||||
// #define SWSRC_GEA SWSRC_SG2
|
||||
// #define SWSRC_ID0 SWSRC_SA0
|
||||
// #define SWSRC_ID1 SWSRC_SA1
|
||||
// #define SWSRC_ID2 SWSRC_SA2
|
||||
// #define SW_DSM2_BIND SW_SH2
|
||||
#elif defined(PCBTARANIS)
|
||||
#if defined(REV9E)
|
||||
#define NUM_SWITCHES 18 // yes, it's a lot!
|
||||
#else
|
||||
@@ -357,7 +379,11 @@
|
||||
#define NUM_PSWITCH (SWSRC_LAST_SWITCH-SWSRC_FIRST_SWITCH+1)
|
||||
#define NUM_POTSSW (NUM_XPOTS*6)
|
||||
|
||||
#if defined(PCBTARANIS)
|
||||
// TODO in keys.h!
|
||||
#if defined(PCBHORUS)
|
||||
#define KEY_PLUS KEY_RIGHT
|
||||
#define KEY_MINUS KEY_LEFT
|
||||
#elif defined(PCBTARANIS) || defined(PCBFLAMENCO)
|
||||
#define KEY_RIGHT KEY_PLUS
|
||||
#define KEY_LEFT KEY_MINUS
|
||||
#define KEY_UP KEY_PLUS
|
||||
@@ -376,7 +402,15 @@
|
||||
#define memclear(p, s) memset(p, 0, s)
|
||||
#endif
|
||||
|
||||
#if defined(PCBTARANIS) && defined(REV9E)
|
||||
#if defined(PCBHORUS)
|
||||
#define IS_POT_AVAILABLE(x) (true)
|
||||
#define IS_POT_MULTIPOS(x) (x==0)
|
||||
#define IS_POT_WITHOUT_DETENT(x) (x==0)
|
||||
#elif defined(PCBFLAMENCO)
|
||||
#define IS_POT_AVAILABLE(x) (true)
|
||||
#define IS_POT_MULTIPOS(x) (x==0)
|
||||
#define IS_POT_WITHOUT_DETENT(x) (x==0)
|
||||
#elif defined(PCBTARANIS) && defined(REV9E)
|
||||
#define IS_SLIDER_AVAILABLE(x) ((x)==SLIDER1 || (x)==SLIDER2 || (g_eeGeneral.slidersConfig & (0x01 << ((x)-SLIDER3))))
|
||||
#define IS_POT_AVAILABLE(x) ((x)<POT1 || ((x)<=POT_LAST && ((g_eeGeneral.potsConfig & (0x03 << (2*((x)-POT1))))!=0)) || ((x)>=SLIDER1 && IS_SLIDER_AVAILABLE(x)))
|
||||
#define IS_POT_MULTIPOS(x) ((x)>=POT1 && (x)<=POT_LAST && ((g_eeGeneral.potsConfig>>(2*((x)-POT1)))&0x03)==POT_MULTIPOS_SWITCH)
|
||||
@@ -450,6 +484,10 @@
|
||||
#define STICK_SCROLL_DISABLE()
|
||||
#endif
|
||||
|
||||
#if defined(CLI)
|
||||
#include "cli.h"
|
||||
#endif
|
||||
|
||||
#include "eeprom_common.h"
|
||||
|
||||
#if defined(EEPROM_RLC)
|
||||
@@ -486,7 +524,17 @@
|
||||
#define MAX_TRAINER_CHANNELS() (8)
|
||||
#endif
|
||||
|
||||
#if defined(PCBTARANIS)
|
||||
#if defined(PCBFLAMENCO)
|
||||
#define IS_MODULE_PPM(idx) (idx==TRAINER_MODULE || (idx==EXTERNAL_MODULE && g_model.externalModule==MODULE_TYPE_PPM))
|
||||
#define IS_MODULE_XJT(idx) ((g_model.externalModule==MODULE_TYPE_XJT) && (g_model.moduleData[idx].rfProtocol != RF_PROTO_OFF))
|
||||
#if defined(DSM2)
|
||||
#define IS_MODULE_DSM2(idx) (idx==EXTERNAL_MODULE && g_model.externalModule==MODULE_TYPE_DSM2)
|
||||
#else
|
||||
#define IS_MODULE_DSM2(idx) (false)
|
||||
#endif
|
||||
#define MAX_EXTERNAL_MODULE_CHANNELS() ((g_model.externalModule == MODULE_TYPE_XJT) ? maxChannelsXJT[1+g_model.moduleData[1].rfProtocol] : maxChannelsModules[g_model.externalModule])
|
||||
#define MAX_CHANNELS(idx) (idx==EXTERNAL_MODULE ? MAX_EXTERNAL_MODULE_CHANNELS() : MAX_TRAINER_CHANNELS())
|
||||
#elif defined(PCBTARANIS)
|
||||
#if defined(TARANIS_INTERNAL_PPM)
|
||||
#define IS_MODULE_PPM(idx) (idx==TRAINER_MODULE || (idx==INTERNAL_MODULE && g_model.moduleData[INTERNAL_MODULE].type==MODULE_TYPE_PPM)|| (idx==EXTERNAL_MODULE && g_model.moduleData[EXTERNAL_MODULE].type==MODULE_TYPE_PPM))
|
||||
#define IS_MODULE_XJT(idx) (((idx==INTERNAL_MODULE && g_model.moduleData[INTERNAL_MODULE].type==MODULE_TYPE_XJT)|| (idx==EXTERNAL_MODULE && g_model.moduleData[EXTERNAL_MODULE].type==MODULE_TYPE_XJT)) && (g_model.moduleData[idx].rfProtocol != RF_PROTO_OFF))
|
||||
@@ -589,7 +637,9 @@ enum BaseCurves {
|
||||
|
||||
#define THRCHK_DEADBAND 16
|
||||
|
||||
#if defined(PCBTARANIS)
|
||||
#if defined(PCBFLAMENCO)
|
||||
#define SPLASH_NEEDED() (true)
|
||||
#elif defined(PCBTARANIS)
|
||||
#define SPLASH_NEEDED() (g_eeGeneral.splashMode != 3)
|
||||
#elif defined(CPUARM)
|
||||
#define SPLASH_NEEDED() (g_model.moduleData[EXTERNAL_MODULE].type != MODULE_TYPE_DSM2 && !g_eeGeneral.splashMode)
|
||||
@@ -599,13 +649,13 @@ enum BaseCurves {
|
||||
|
||||
#if defined(FSPLASH)
|
||||
#define SPLASH_TIMEOUT (g_eeGeneral.splashMode == 0 ? 60000/*infinite=10mn*/ : ((4*100) * (g_eeGeneral.splashMode & 0x03)))
|
||||
#elif defined(PCBTARANIS)
|
||||
#elif defined(PCBTARANIS) || defined(PCBFLAMENCO) || defined(PCBHORUS)
|
||||
#define SPLASH_TIMEOUT (g_eeGeneral.splashMode==-4 ? 1500 : (g_eeGeneral.splashMode<=0 ? (400-g_eeGeneral.splashMode*200) : (400-g_eeGeneral.splashMode*100)))
|
||||
#else
|
||||
#define SPLASH_TIMEOUT (4*100) // 4 seconds
|
||||
#endif
|
||||
|
||||
#if defined(PCBTARANIS)
|
||||
#if defined(PCBTARANIS) || defined(PCBFLAMENCO) || defined(PCBHORUS)
|
||||
#define IS_RE_NAVIGATION_ENABLE() true
|
||||
#define NAVIGATION_RE_IDX() 0
|
||||
#elif defined(ROTARY_ENCODERS)
|
||||
@@ -618,7 +668,7 @@ enum BaseCurves {
|
||||
|
||||
#define HEART_TIMER_10MS 1
|
||||
#define HEART_TIMER_PULSES 2 // when multiple modules this is the first one
|
||||
#if defined(PCBTARANIS)
|
||||
#if defined(PCBTARANIS) || defined(PCBFLAMENCO) || defined(PCBHORUS)
|
||||
#define HEART_WDT_CHECK (HEART_TIMER_10MS + (HEART_TIMER_PULSES << 0) + (HEART_TIMER_PULSES << 1))
|
||||
#else
|
||||
#define HEART_WDT_CHECK (HEART_TIMER_10MS + HEART_TIMER_PULSES)
|
||||
@@ -658,7 +708,7 @@ int zchar2str(char *dest, const char *src, int size);
|
||||
#include "keys.h"
|
||||
#include "pwr.h"
|
||||
|
||||
#if defined(PCBTARANIS)
|
||||
#if defined(PCBTARANIS) || defined(PCBFLAMENCO) || defined(PCBHORUS)
|
||||
div_t switchInfo(int switchPosition);
|
||||
#endif
|
||||
|
||||
@@ -768,7 +818,7 @@ void logicalSwitchesReset();
|
||||
#define LS_RECURSIVE_EVALUATION_RESET() s_last_switch_used = 0
|
||||
#endif
|
||||
|
||||
#if defined(PCBTARANIS)
|
||||
#if defined(PCBTARANIS) || defined(PCBFLAMENCO) || defined(PCBHORUS)
|
||||
void getSwitchesPosition(bool startup);
|
||||
#else
|
||||
#define getSwitchesPosition(...)
|
||||
@@ -777,7 +827,7 @@ void logicalSwitchesReset();
|
||||
extern swarnstate_t switches_states;
|
||||
swsrc_t getMovedSwitch();
|
||||
|
||||
#if defined(PCBTARANIS)
|
||||
#if defined(VIRTUALINPUTS)
|
||||
#define GET_MOVED_SOURCE_PARAMS uint8_t min
|
||||
int8_t getMovedSource(GET_MOVED_SOURCE_PARAMS);
|
||||
#define GET_MOVED_SOURCE(min, max) getMovedSource(min)
|
||||
@@ -793,7 +843,7 @@ swsrc_t getMovedSwitch();
|
||||
#define getFlightMode() 0
|
||||
#endif
|
||||
|
||||
#if !defined(PCBTARANIS)
|
||||
#if !defined(VIRTUALINPUTS)
|
||||
uint8_t getTrimFlightPhase(uint8_t phase, uint8_t idx);
|
||||
#else
|
||||
#define getTrimFlightPhase(phase, idx) (phase)
|
||||
@@ -809,7 +859,7 @@ swsrc_t getMovedSwitch();
|
||||
trim_t getRawTrimValue(uint8_t phase, uint8_t idx);
|
||||
int getTrimValue(uint8_t phase, uint8_t idx);
|
||||
|
||||
#if defined(PCBTARANIS)
|
||||
#if defined(PCBTARANIS) || defined(PCBFLAMENCO) || defined(PCBHORUS)
|
||||
bool setTrimValue(uint8_t phase, uint8_t idx, int trim);
|
||||
#else
|
||||
void setTrimValue(uint8_t phase, uint8_t idx, int trim);
|
||||
@@ -988,7 +1038,17 @@ enum Analogs {
|
||||
STICK2,
|
||||
STICK3,
|
||||
STICK4,
|
||||
#if defined(PCBTARANIS)
|
||||
#if defined(PCBFLAMENCO)
|
||||
POT1,
|
||||
POT2,
|
||||
POT_LAST = POT2,
|
||||
SLIDER1,
|
||||
SLIDER2,
|
||||
SWITCHES1,
|
||||
SWITCHES2,
|
||||
SWITCHES3,
|
||||
SWITCHES4,
|
||||
#elif defined(PCBTARANIS)
|
||||
POT1,
|
||||
POT2,
|
||||
POT3,
|
||||
@@ -1027,6 +1087,7 @@ enum Analogs {
|
||||
};
|
||||
|
||||
void checkBacklight();
|
||||
void doLoopCommonActions();
|
||||
|
||||
#if defined(PCBSTD) && defined(VOICE) && !defined(SIMU)
|
||||
#define BACKLIGHT_ON() (Voice.Backlight = 1)
|
||||
@@ -1427,7 +1488,7 @@ enum AUDIO_SOUNDS {
|
||||
#if defined(CPUARM)
|
||||
AU_TRIM_END,
|
||||
#endif
|
||||
#if defined(PCBTARANIS)
|
||||
#if defined(PCBTARANIS) || defined(PCBFLAMENCO) || defined(PCBHORUS)
|
||||
AU_STICK1_MIDDLE,
|
||||
AU_STICK2_MIDDLE,
|
||||
AU_STICK3_MIDDLE,
|
||||
@@ -1549,7 +1610,7 @@ union ReusableBuffer
|
||||
int16_t loVals[NUM_STICKS+NUM_POTS];
|
||||
int16_t hiVals[NUM_STICKS+NUM_POTS];
|
||||
uint8_t state;
|
||||
#if defined(PCBTARANIS)
|
||||
#if defined(PCBTARANIS) || defined(PCBFLAMENCO) || defined(PCBHORUS)
|
||||
struct {
|
||||
uint8_t stepsCount;
|
||||
int16_t steps[XPOTS_MULTIPOS_COUNT];
|
||||
@@ -1698,7 +1759,7 @@ extern uint8_t s_frsky_view;
|
||||
#define EARTH_RADIUSKM ((uint32_t)6371)
|
||||
#define EARTH_RADIUS ((uint32_t)111194)
|
||||
|
||||
#if defined(PCBTARANIS)
|
||||
#if defined(PCBTARANIS) || defined(PCBFLAMENCO) || defined(PCBHORUS)
|
||||
double gpsToDouble(bool neg, int16_t bp, int16_t ap);
|
||||
#endif
|
||||
void getGpsPilotPosition();
|
||||
|
||||
@@ -51,7 +51,7 @@ uint8_t dsm2BindTimer = DSM2_BIND_TIMEOUT;
|
||||
|
||||
#define BITLEN_DSM2 (8*2) //125000 Baud => 8uS per bit
|
||||
|
||||
#if defined(PCBTARANIS)
|
||||
#if !defined(PPM_PIN_HW_SERIAL)
|
||||
void _send_1(uint8_t v)
|
||||
{
|
||||
if (modulePulsesData[EXTERNAL_MODULE].dsm2.index == 0)
|
||||
@@ -129,7 +129,7 @@ void setupPulsesDSM2(unsigned int port)
|
||||
{
|
||||
static uint8_t dsmDat[2+6*2]={0xFF,0x00, 0x00,0xAA, 0x05,0xFF, 0x09,0xFF, 0x0D,0xFF, 0x13,0x54, 0x14,0xAA};
|
||||
|
||||
#if defined(PCBSKY9X)
|
||||
#if defined(PPM_PIN_HW_SERIAL)
|
||||
modulePulsesData[EXTERNAL_MODULE].dsm2.serialByte = 0 ;
|
||||
modulePulsesData[EXTERNAL_MODULE].dsm2.serialBitCount = 0 ;
|
||||
#else
|
||||
@@ -139,7 +139,7 @@ void setupPulsesDSM2(unsigned int port)
|
||||
|
||||
modulePulsesData[EXTERNAL_MODULE].dsm2.ptr = modulePulsesData[EXTERNAL_MODULE].dsm2.pulses;
|
||||
|
||||
#if defined(PCBTARANIS)
|
||||
#if !defined(PPM_PIN_HW_SERIAL)
|
||||
modulePulsesData[EXTERNAL_MODULE].dsm2.value = 100;
|
||||
*modulePulsesData[EXTERNAL_MODULE].dsm2.ptr++ = modulePulsesData[EXTERNAL_MODULE].dsm2.value;
|
||||
#endif
|
||||
@@ -156,7 +156,7 @@ void setupPulsesDSM2(unsigned int port)
|
||||
break;
|
||||
}
|
||||
|
||||
#if defined(PCBTARANIS)
|
||||
#if !defined(PPM_PIN_HW_SERIAL)
|
||||
if (moduleFlag[port] == MODULE_BIND)
|
||||
dsmDat[0] |= DSM2_SEND_BIND;
|
||||
else if (moduleFlag[port] == MODULE_RANGECHECK)
|
||||
|
||||
@@ -55,7 +55,7 @@ enum ModuleFlag
|
||||
#define IS_RANGECHECK_ENABLE() (moduleFlag[0] == MODULE_RANGECHECK)
|
||||
#endif
|
||||
|
||||
#if defined(DSM2) && !defined(PCBTARANIS)
|
||||
#if defined(DSM2) && !defined(PCBTARANIS) && !defined(PCBFLAMENCO)
|
||||
#define DSM2_BIND_TIMEOUT 255 // 255*11ms
|
||||
extern uint8_t dsm2BindTimer;
|
||||
#endif
|
||||
|
||||
@@ -81,7 +81,7 @@ void crc(uint8_t data, unsigned int port)
|
||||
modulePulsesData[port].pxx.pcmCrc = (modulePulsesData[port].pxx.pcmCrc<<8) ^ (CRCTable[((modulePulsesData[port].pxx.pcmCrc>>8)^data) & 0xFF]);
|
||||
}
|
||||
|
||||
#if defined(PCBTARANIS)
|
||||
#if !defined(PPM_PIN_HW_SERIAL)
|
||||
|
||||
void putPcmPart(uint8_t value, unsigned int port)
|
||||
{
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define PRINTF_BUFFER_SIZE 256
|
||||
#define PRINTF_BUFFER_SIZE 128
|
||||
|
||||
void serialPutc(char c)
|
||||
{
|
||||
|
||||
+161
-58
@@ -63,8 +63,10 @@ class Open9xSim: public FXMainWindow
|
||||
Open9xSim(){};
|
||||
Open9xSim(FXApp* a);
|
||||
~Open9xSim();
|
||||
void updateKeysAndSwitches(bool start=false);
|
||||
long onKeypress(FXObject*,FXSelector,void*);
|
||||
long onTimeout(FXObject*,FXSelector,void*);
|
||||
void createBitmap(int index, uint16_t *data, int x, int y, int w, int h);
|
||||
void makeSnapshot(const FXDrawable* drawable);
|
||||
void doEvents();
|
||||
void refreshDisplay();
|
||||
@@ -93,7 +95,7 @@ Open9xSim::Open9xSim(FXApp* a):
|
||||
FXMainWindow(a, "OpenTX Simu", NULL, NULL, DECOR_ALL, 20, 90, 0, 0)
|
||||
{
|
||||
firstTime = true;
|
||||
memset(displayBuf, 0, DISPLAY_BUFER_SIZE);
|
||||
memset(displayBuf, 0, DISPLAY_BUFFER_SIZE);
|
||||
bmp = new FXPPMImage(getApp(),NULL,IMAGE_OWNED|IMAGE_KEEP|IMAGE_SHMI|IMAGE_SHMP, W2, H2);
|
||||
|
||||
#if defined(SIMU_AUDIO)
|
||||
@@ -137,7 +139,9 @@ Open9xSim::Open9xSim(FXApp* a):
|
||||
|
||||
bmf = new FXImageFrame(this,bmp);
|
||||
|
||||
getApp()->addTimeout(this,2,100);
|
||||
updateKeysAndSwitches(true);
|
||||
|
||||
getApp()->addTimeout(this, 2, 100);
|
||||
}
|
||||
|
||||
Open9xSim::~Open9xSim()
|
||||
@@ -163,6 +167,31 @@ Open9xSim::~Open9xSim()
|
||||
#endif
|
||||
}
|
||||
|
||||
void Open9xSim::createBitmap(int index, uint16_t *data, int x, int y, int w, int h)
|
||||
{
|
||||
FXPNGImage snapshot(getApp(), NULL, IMAGE_OWNED, w, h);
|
||||
|
||||
for (int i=0; i<w; i++) {
|
||||
for (int j=0; j<h; j++) {
|
||||
display_t z = data[(y+j) * LCD_W + (x+i)];
|
||||
FXColor color = FXRGB(255*((z&0xF00)>>8)/0x0f, 255*((z&0x0F0)>>4)/0x0f, 255*(z&0x00F)/0x0f);
|
||||
snapshot.setPixel(i, j, color);
|
||||
}
|
||||
}
|
||||
|
||||
FXFileStream stream;
|
||||
char buf[32];
|
||||
sprintf(buf,"%02d.png", index);
|
||||
if (stream.open(buf, FXStreamSave)) {
|
||||
snapshot.savePixels(stream);
|
||||
stream.close();
|
||||
TRACE("Bitmap %d (w=%d, h=%d) created", index, w, h);
|
||||
}
|
||||
else {
|
||||
TRACE("Bitmap %d (w=%d, h=%d) error", index, w, h);
|
||||
}
|
||||
}
|
||||
|
||||
void Open9xSim::makeSnapshot(const FXDrawable* drawable)
|
||||
{
|
||||
// Construct and create an FXImage object
|
||||
@@ -215,30 +244,120 @@ long Open9xSim::onKeypress(FXObject*,FXSelector,void*v)
|
||||
return 0;
|
||||
}
|
||||
|
||||
long Open9xSim::onTimeout(FXObject*, FXSelector, void*)
|
||||
void Open9xSim::updateKeysAndSwitches(bool start)
|
||||
{
|
||||
if(hasFocus()) {
|
||||
static int keys1[]={
|
||||
#if defined(PCBTARANIS)
|
||||
KEY_Page_Up, KEY_MENU,
|
||||
KEY_Page_Down, KEY_PAGE,
|
||||
KEY_Return, KEY_ENTER,
|
||||
KEY_BackSpace, KEY_EXIT,
|
||||
KEY_Up, KEY_PLUS,
|
||||
KEY_Down, KEY_MINUS,
|
||||
static int keys1[] = {
|
||||
#if defined(PCBHORUS)
|
||||
KEY_Page_Up, KEY_MENU,
|
||||
KEY_Return, KEY_ENTER,
|
||||
KEY_BackSpace, KEY_EXIT,
|
||||
KEY_Up, KEY_UP,
|
||||
KEY_Down, KEY_DOWN,
|
||||
KEY_Right, KEY_RIGHT,
|
||||
KEY_Left, KEY_LEFT,
|
||||
#elif defined(PCBTARANIS) || defined(PCBFLAMENCO)
|
||||
KEY_Page_Up, KEY_MENU,
|
||||
KEY_Page_Down, KEY_PAGE,
|
||||
KEY_Return, KEY_ENTER,
|
||||
KEY_BackSpace, KEY_EXIT,
|
||||
KEY_Up, KEY_PLUS,
|
||||
KEY_Down, KEY_MINUS,
|
||||
#else
|
||||
KEY_Return, KEY_MENU,
|
||||
KEY_BackSpace, KEY_EXIT,
|
||||
KEY_Right, KEY_RIGHT,
|
||||
KEY_Left, KEY_LEFT,
|
||||
KEY_Up, KEY_UP,
|
||||
KEY_Down, KEY_DOWN,
|
||||
KEY_Return, KEY_MENU,
|
||||
KEY_BackSpace, KEY_EXIT,
|
||||
KEY_Right, KEY_RIGHT,
|
||||
KEY_Left, KEY_LEFT,
|
||||
KEY_Up, KEY_UP,
|
||||
KEY_Down, KEY_DOWN,
|
||||
#endif
|
||||
#if defined(ROTARY_ENCODER_NAVIGATION)
|
||||
KEY_F, BTN_REa,
|
||||
KEY_F, BTN_REa,
|
||||
#endif
|
||||
};
|
||||
};
|
||||
|
||||
for (unsigned int i=0; i<DIM(keys1); i+=2) {
|
||||
simuSetKey(keys1[i+1], start ? false : getApp()->getKeyState(keys1[i]));
|
||||
}
|
||||
|
||||
#ifdef __APPLE__
|
||||
// gruvin: Can't use Function keys on the Mac -- too many other app conflicts.
|
||||
// The ordering of these keys, Q/W,E/R,T/Y,U/I matches the on screen
|
||||
// order of trim sliders
|
||||
static FXuint trimKeys[] = { KEY_E, KEY_R, KEY_U, KEY_I, KEY_R, KEY_E, KEY_Y, KEY_T, KEY_Q, KEY_W };
|
||||
#else
|
||||
static FXuint trimKeys[] = { KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, KEY_F6, KEY_F7, KEY_F8 };
|
||||
#endif
|
||||
|
||||
for (unsigned i=0; i<DIM(trimKeys); i++) {
|
||||
simuSetTrim(i, getApp()->getKeyState(trimKeys[i]));
|
||||
}
|
||||
|
||||
#define SWITCH_KEY(key, swtch, states) \
|
||||
static bool state##key = 0; \
|
||||
static int8_t state_##swtch = 2; \
|
||||
static int8_t inc_##swtch = 1; \
|
||||
if (getApp()->getKeyState(KEY_##key)) { \
|
||||
if (!state##key) { \
|
||||
state_##swtch = (state_##swtch+inc_##swtch); \
|
||||
if (state_##swtch == 1+states) inc_##swtch = -1; \
|
||||
else if (state_##swtch == 2) inc_##swtch = 1; \
|
||||
state##key = true; \
|
||||
} \
|
||||
} \
|
||||
else { \
|
||||
state##key = false; \
|
||||
} \
|
||||
simuSetSwitch(swtch, state_##swtch-states);
|
||||
|
||||
#if defined(PCBFLAMENCO)
|
||||
SWITCH_KEY(A, 0, 3);
|
||||
SWITCH_KEY(B, 1, 2);
|
||||
// SWITCH_KEY(C, 2, 3);
|
||||
// SWITCH_KEY(D, 3, 3);
|
||||
SWITCH_KEY(E, 4, 2);
|
||||
SWITCH_KEY(F, 5, 3);
|
||||
#elif defined(PCBTARANIS) && defined(REV9E)
|
||||
SWITCH_KEY(A, 0, 3);
|
||||
SWITCH_KEY(B, 1, 3);
|
||||
SWITCH_KEY(C, 2, 3);
|
||||
SWITCH_KEY(D, 3, 3);
|
||||
SWITCH_KEY(E, 4, 3);
|
||||
SWITCH_KEY(F, 5, 3);
|
||||
SWITCH_KEY(G, 6, 3);
|
||||
SWITCH_KEY(H, 7, 3);
|
||||
SWITCH_KEY(I, 8, 3);
|
||||
SWITCH_KEY(J, 9, 3);
|
||||
SWITCH_KEY(K, 10, 3);
|
||||
SWITCH_KEY(L, 11, 3);
|
||||
SWITCH_KEY(M, 12, 3);
|
||||
SWITCH_KEY(N, 13, 3);
|
||||
SWITCH_KEY(O, 14, 3);
|
||||
SWITCH_KEY(P, 15, 3);
|
||||
SWITCH_KEY(Q, 16, 3);
|
||||
SWITCH_KEY(R, 17, 3);
|
||||
#elif defined(PCBTARANIS)
|
||||
SWITCH_KEY(A, 0, 3);
|
||||
SWITCH_KEY(B, 1, 3);
|
||||
SWITCH_KEY(C, 2, 3);
|
||||
SWITCH_KEY(D, 3, 3);
|
||||
SWITCH_KEY(E, 4, 3);
|
||||
SWITCH_KEY(F, 5, 2);
|
||||
SWITCH_KEY(G, 6, 3);
|
||||
SWITCH_KEY(H, 7, 2);
|
||||
#else
|
||||
SWITCH_KEY(1, 0, 2);
|
||||
SWITCH_KEY(2, 1, 2);
|
||||
SWITCH_KEY(3, 2, 2);
|
||||
SWITCH_KEY(4, 3, 3);
|
||||
SWITCH_KEY(5, 4, 2);
|
||||
SWITCH_KEY(6, 5, 2);
|
||||
SWITCH_KEY(7, 6, 2);
|
||||
#endif
|
||||
}
|
||||
|
||||
long Open9xSim::onTimeout(FXObject*, FXSelector, void*)
|
||||
{
|
||||
if (hasFocus()) {
|
||||
#if defined(PCBSKY9X) && !defined(REVX)
|
||||
Coproc_temp = 23;
|
||||
Coproc_maxtemp = 28;
|
||||
@@ -249,23 +368,8 @@ long Open9xSim::onTimeout(FXObject*, FXSelector, void*)
|
||||
maxTemperature = 42;
|
||||
#endif
|
||||
|
||||
for (unsigned int i=0; i<DIM(keys1); i+=2) {
|
||||
simuSetKey(keys1[i+1], getApp()->getKeyState(keys1[i]));
|
||||
}
|
||||
|
||||
#ifdef __APPLE__
|
||||
// gruvin: Can't use Function keys on the Mac -- too many other app conflicts.
|
||||
// The ordering of these keys, Q/W,E/R,T/Y,U/I matches the on screen
|
||||
// order of trim sliders
|
||||
static FXuint trimKeys[] = { KEY_E, KEY_R, KEY_U, KEY_I, KEY_R, KEY_E, KEY_Y, KEY_T, KEY_Q, KEY_W };
|
||||
#else
|
||||
static FXuint trimKeys[] = { KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, KEY_F6, KEY_F7, KEY_F8 };
|
||||
#endif
|
||||
|
||||
for (unsigned i=0; i<DIM(trimKeys); i++) {
|
||||
simuSetTrim(i, getApp()->getKeyState(trimKeys[i]));
|
||||
}
|
||||
|
||||
updateKeysAndSwitches();
|
||||
|
||||
#if defined(ROTARY_ENCODER_NAVIGATION)
|
||||
static bool rotencAction = false;
|
||||
if (getApp()->getKeyState(KEY_G)) {
|
||||
@@ -281,24 +385,6 @@ long Open9xSim::onTimeout(FXObject*, FXSelector, void*)
|
||||
}
|
||||
#endif
|
||||
|
||||
#define SWITCH_KEY(key, swtch, states) \
|
||||
static bool state##key = 0; \
|
||||
static int8_t state_##swtch = 2; \
|
||||
static int8_t inc_##swtch = 1; \
|
||||
if (getApp()->getKeyState(KEY_##key)) { \
|
||||
if (!state##key) { \
|
||||
state_##swtch = (state_##swtch+inc_##swtch); \
|
||||
if (state_##swtch >= 1+states) inc_##swtch = -1; \
|
||||
else if (state_##swtch <= 2) inc_##swtch = 1; \
|
||||
/* TRACE("switch " #swtch ": state: %d, inc: %d", state_##swtch, inc_##swtch); */ \
|
||||
state##key = true; \
|
||||
} \
|
||||
} \
|
||||
else { \
|
||||
state##key = false; \
|
||||
} \
|
||||
simuSetSwitch(swtch, state_##swtch-states);
|
||||
|
||||
#if defined(PCBTARANIS) && defined(REV9E)
|
||||
SWITCH_KEY(A, 0, 3);
|
||||
SWITCH_KEY(B, 1, 3);
|
||||
@@ -337,7 +423,7 @@ long Open9xSim::onTimeout(FXObject*, FXSelector, void*)
|
||||
SWITCH_KEY(7, 6, 2);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
per10ms();
|
||||
refreshDisplay();
|
||||
getApp()->addTimeout(this, 2, 10);
|
||||
@@ -369,7 +455,19 @@ void Open9xSim::refreshDisplay()
|
||||
#endif
|
||||
for (int x=0; x<LCD_W; x++) {
|
||||
for (int y=0; y<LCD_H; y++) {
|
||||
#if defined(PCBTARANIS)
|
||||
#if defined(PCBHORUS)
|
||||
display_t z = lcd_buf[y * LCD_W + x];
|
||||
if (1) {
|
||||
FXColor color = FXRGB(255*((z&0xF800)>>11)/0x1f, 255*((z&0x07E0)>>5)/0x3F, 255*(z&0x001F)/0x01F);
|
||||
setPixel(x, y, color);
|
||||
}
|
||||
#elif defined(PCBFLAMENCO)
|
||||
display_t z = lcd_buf[y * LCD_W + x];
|
||||
if (1) {
|
||||
FXColor color = FXRGB(255*((z&0xF00)>>8)/0x0f, 255*((z&0x0F0)>>4)/0x0f, 255*(z&0x00F)/0x0f);
|
||||
setPixel(x, y, color);
|
||||
}
|
||||
#elif defined(PCBTARANIS)
|
||||
display_t * p = &lcd_buf[y / 2 * LCD_W + x];
|
||||
uint8_t z = (y & 1) ? (*p >> 4) : (*p & 0x0F);
|
||||
if (z) {
|
||||
@@ -459,7 +557,7 @@ uint16_t anaIn(uint8_t chan)
|
||||
return th9xSim->sliders[chan]->getValue();
|
||||
else if (chan<NUM_STICKS+NUM_POTS)
|
||||
return th9xSim->knobs[chan-NUM_STICKS]->getValue();
|
||||
#if defined(PCBTARANIS)
|
||||
#if defined(PCBTARANIS) || defined(PCBFLAMENCO)
|
||||
else if (chan == TX_VOLTAGE)
|
||||
return 1000;
|
||||
#elif defined(PCBSKY9X)
|
||||
@@ -477,3 +575,8 @@ uint16_t anaIn(uint8_t chan)
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
void createBitmap(int index, uint16_t *data, int x, int y, int w, int h)
|
||||
{
|
||||
th9xSim->createBitmap(index, data, x, y, w, h);
|
||||
}
|
||||
|
||||
+186
-46
@@ -71,6 +71,113 @@ volatile GETSWITCH_RECURSIVE_TYPE s_last_switch_value = 0;
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(PCBFLAMENCO) || defined(PCBHORUS)
|
||||
tmr10ms_t potsLastposStart[1];
|
||||
uint8_t potsPos[1];
|
||||
tmr10ms_t switchesMidposStart[2];
|
||||
uint64_t switchesPos = 0;
|
||||
div_t switchInfo(int switchPosition)
|
||||
{
|
||||
const div_t infos[] = {
|
||||
{ 0, 0 }, { 0, 1 }, { 0, 2 },
|
||||
{ 1, 0 }, { 1, 1 },
|
||||
{ 2, 0 }, { 2, 1 }, { 2, 2 }, { 2, 3 }, { 2, 4 }, { 2, 5 },
|
||||
{ 4, 0 }, { 4, 1 },
|
||||
{ 5, 0 }, { 5, 1 }, { 5, 2 },
|
||||
};
|
||||
return infos[switchPosition-SWSRC_FIRST_SWITCH];
|
||||
}
|
||||
|
||||
uint32_t check2PosSwitchPosition(EnumKeys sw)
|
||||
{
|
||||
uint32_t result;
|
||||
uint32_t index;
|
||||
|
||||
if (switchState(sw))
|
||||
index = sw - SW_SA0;
|
||||
else
|
||||
index = sw - SW_SA0 + 1;
|
||||
|
||||
result = ((uint32_t)1 << index);
|
||||
|
||||
if (!(switchesPos & result)) {
|
||||
PLAY_SWITCH_MOVED(index);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
uint32_t check3PosSwitchPosition(int idx, EnumKeys sw, bool startup)
|
||||
{
|
||||
uint32_t result;
|
||||
uint32_t index;
|
||||
|
||||
if (switchState(sw)) {
|
||||
index = sw - SW_SA0;
|
||||
result = (1 << index);
|
||||
switchesMidposStart[idx] = 0;
|
||||
}
|
||||
else if (switchState(EnumKeys(sw+2))) {
|
||||
index = sw - SW_SA0 + 2;
|
||||
result = (1 << index);
|
||||
switchesMidposStart[idx] = 0;
|
||||
}
|
||||
else if (startup || (switchesPos & (1 << (sw - SW_SA0 + 1))) || g_eeGeneral.switchesDelay==SWITCHES_DELAY_NONE || (switchesMidposStart[idx] && (tmr10ms_t)(get_tmr10ms() - switchesMidposStart[idx]) > SWITCHES_DELAY())) {
|
||||
index = sw - SW_SA0 + 1;
|
||||
result = (1 << index);
|
||||
switchesMidposStart[idx] = 0;
|
||||
}
|
||||
else {
|
||||
index = sw - SW_SA0 + 1;
|
||||
if (!switchesMidposStart[idx]) {
|
||||
switchesMidposStart[idx] = get_tmr10ms();
|
||||
}
|
||||
result = (switchesPos & (0x7 << (sw - SW_SA0)));
|
||||
}
|
||||
|
||||
if (!(switchesPos & result)) {
|
||||
PLAY_SWITCH_MOVED(index);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#define CHECK_2POS(sw) newPos |= check2PosSwitchPosition(sw ## 0)
|
||||
#define CHECK_3POS(idx, sw) newPos |= check3PosSwitchPosition(idx, sw ## 0, startup)
|
||||
|
||||
void getSwitchesPosition(bool startup)
|
||||
{
|
||||
uint64_t newPos = 0;
|
||||
CHECK_3POS(0, SW_SA);
|
||||
CHECK_2POS(SW_SB);
|
||||
CHECK_2POS(SW_SE);
|
||||
CHECK_3POS(1, SW_SF);
|
||||
switchesPos = newPos;
|
||||
|
||||
int i = 0;
|
||||
StepsCalibData * calib = (StepsCalibData *) &g_eeGeneral.calib[POT1+i];
|
||||
if (calib->count>0 && calib->count<XPOTS_MULTIPOS_COUNT) {
|
||||
uint8_t pos = anaIn(POT1+i) / (2*RESX/calib->count);
|
||||
uint8_t previousPos = potsPos[i] >> 4;
|
||||
uint8_t previousStoredPos = potsPos[i] & 0x0F;
|
||||
if (startup) {
|
||||
potsPos[i] = (pos << 4) | pos;
|
||||
}
|
||||
else if (pos != previousPos) {
|
||||
potsLastposStart[i] = get_tmr10ms();
|
||||
potsPos[i] = (pos << 4) | previousStoredPos;
|
||||
}
|
||||
else if (g_eeGeneral.switchesDelay==SWITCHES_DELAY_NONE || (tmr10ms_t)(get_tmr10ms() - potsLastposStart[i]) > SWITCHES_DELAY()) {
|
||||
potsLastposStart[i] = 0;
|
||||
potsPos[i] = (pos << 4) | pos;
|
||||
if (previousStoredPos != pos) {
|
||||
PLAY_SWITCH_MOVED(SWSRC_LAST_SWITCH+i*XPOTS_MULTIPOS_COUNT+pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(PCBTARANIS)
|
||||
#if defined(REV9E)
|
||||
tmr10ms_t switchesMidposStart[16];
|
||||
@@ -200,6 +307,7 @@ void getSwitchesPosition(bool startup)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
getvalue_t getValueForLogicalSwitch(mixsrc_t i)
|
||||
{
|
||||
getvalue_t result = getValue(i);
|
||||
@@ -462,7 +570,7 @@ bool getSwitch(swsrc_t swtch)
|
||||
result = true;
|
||||
}
|
||||
else if (cs_idx <= SWSRC_LAST_SWITCH) {
|
||||
#if defined(PCBTARANIS)
|
||||
#if defined(PCBTARANIS) // TODO || defined(PCBFLAMENCO)
|
||||
if (flags & GETSWITCH_MIDPOS_DELAY)
|
||||
result = SWITCH_POSITION(cs_idx-SWSRC_FIRST_SWITCH);
|
||||
else
|
||||
@@ -486,7 +594,7 @@ bool getSwitch(swsrc_t swtch)
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#if defined(PCBTARANIS)
|
||||
#if NUM_XPOTS > 0
|
||||
else if (cs_idx <= SWSRC_LAST_MULTIPOS_SWITCH) {
|
||||
result = POT_POSITION(cs_idx-SWSRC_FIRST_MULTIPOS_SWITCH);
|
||||
}
|
||||
@@ -568,7 +676,28 @@ swsrc_t getMovedSwitch()
|
||||
static tmr10ms_t s_move_last_time = 0;
|
||||
swsrc_t result = 0;
|
||||
|
||||
#if defined(PCBTARANIS)
|
||||
#if defined(PCBFLAMENCO)
|
||||
#if 0
|
||||
for (int i=0; i<NUM_SWITCHES; i++) {
|
||||
swarnstate_t mask = ((swarnstate_t)0x07 << (i*3));
|
||||
uint8_t prev = (switches_states & mask) >> (i*3);
|
||||
uint8_t next = (1024+getValue(MIXSRC_SA+i)) / 1024;
|
||||
if (prev != next) {
|
||||
switches_states = (switches_states & (~mask)) | ((swarnstate_t)next << (i*3));
|
||||
if (i == 0)
|
||||
result = 1+next;
|
||||
else if (i == 1)
|
||||
result = 1+(3*1)+(next!=0);
|
||||
else if (i == 3)
|
||||
result = 12+(next!=0);
|
||||
else if (i == 4)
|
||||
result = 14+next;
|
||||
else
|
||||
result = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#elif defined(PCBTARANIS)
|
||||
for (int i=0; i<NUM_SWITCHES; i++) {
|
||||
if (SWITCH_EXISTS(i)) {
|
||||
swarnstate_t mask = ((swarnstate_t)0x03 << (i*2));
|
||||
@@ -618,27 +747,22 @@ void checkSwitches()
|
||||
#endif
|
||||
swarnstate_t states = g_model.switchWarningState;
|
||||
|
||||
#if defined(PCBTARANIS)
|
||||
#if defined(PCBTARANIS) || defined(PCBFLAMENCO) || defined(PCBHORUS)
|
||||
uint8_t bad_pots = 0, last_bad_pots = 0xff;
|
||||
#endif
|
||||
|
||||
#if defined(PCBTARANIS) && defined(REV9E)
|
||||
bool refresh = false;
|
||||
#endif
|
||||
|
||||
#if !defined(MODULE_ALWAYS_SEND_PULSES)
|
||||
while (1) {
|
||||
|
||||
#if defined(TELEMETRY_MOD_14051) || defined(TELEMETRY_MOD_14051_SWAPPED)
|
||||
// FIXME: One getADC() call only reads one 14051 MUX input. To have all switch states updated, we need to call it MUX_MAX+1 times.
|
||||
#define GETADC_COUNT (MUX_MAX+1)
|
||||
#elif defined(PCBTARANIS)
|
||||
#elif defined(PCBTARANIS) || defined(PCBFLAMENCO)
|
||||
#define GETADC_COUNT 1
|
||||
#endif
|
||||
#ifdef GETADC_COUNT
|
||||
for (int i=0; i<GETADC_COUNT; i++) {
|
||||
for (int i=0; i<GETADC_COUNT; i++)
|
||||
getADC();
|
||||
}
|
||||
#undef GETADC_COUNT
|
||||
#endif
|
||||
#endif // !defined(MODULE_ALWAYS_SEND_PULSES)
|
||||
@@ -646,7 +770,8 @@ void checkSwitches()
|
||||
getMovedSwitch();
|
||||
|
||||
bool warn = false;
|
||||
#if defined(PCBTARANIS)
|
||||
#if defined(PCBFLAMENCO)
|
||||
#elif defined(PCBTARANIS)
|
||||
for (int i=0; i<NUM_SWITCHES; i++) {
|
||||
if (SWITCH_WARNING_ALLOWED(i) && !(g_model.switchWarningEnable & (1<<i))) {
|
||||
swarnstate_t mask = ((swarnstate_t)0x03 << (i*2));
|
||||
@@ -659,7 +784,7 @@ void checkSwitches()
|
||||
evalFlightModeMixes(e_perout_mode_normal, 0);
|
||||
bad_pots = 0;
|
||||
for (int i=0; i<NUM_POTS; i++) {
|
||||
if (!IS_POT_AVAILABLE(POT1+i)) {
|
||||
if (!IS_POT_AVAILABLE(i)) {
|
||||
continue;
|
||||
}
|
||||
if (!(g_model.potsWarnEnabled & (1 << i)) && (abs(g_model.potsWarnPosition[i] - GET_LOWRES_POT_POSITION(i)) > 1)) {
|
||||
@@ -692,25 +817,44 @@ void checkSwitches()
|
||||
}
|
||||
|
||||
// first - display warning
|
||||
#if defined(PCBTARANIS)
|
||||
#if defined(PCBTARANIS) || defined(PCBFLAMENCO) || defined(PCBHORUS)
|
||||
#if defined(COLORLCD)
|
||||
if ((last_bad_switches != switches_states) || (last_bad_pots != bad_pots)) {
|
||||
int x = WARNING_LINE_X, y = WARNING_INFOLINE_Y-5;
|
||||
#elif defined(PCBTARANIS)
|
||||
if ((last_bad_switches != switches_states) || (last_bad_pots != bad_pots)) {
|
||||
MESSAGE(STR_SWITCHWARN, NULL, STR_PRESSANYKEYTOSKIP, ((last_bad_switches == 0xff) || (last_bad_pots == 0xff)) ? AU_SWITCH_ALERT : AU_NONE);
|
||||
int x = 60, y = 4*FH+3;
|
||||
#endif
|
||||
int numWarnings = 0;
|
||||
for (int i=0; i<NUM_SWITCHES; ++i) {
|
||||
if (SWITCH_WARNING_ALLOWED(i) && !(g_model.switchWarningEnable & (1<<i))) {
|
||||
swarnstate_t mask = ((swarnstate_t)0x03 << (i*2));
|
||||
uint8_t attr = ((states & mask) == (switches_states & mask)) ? 0 : INVERS;
|
||||
#if defined(COLORLCD)
|
||||
LcdFlags attr = ((states & mask) == (switches_states & mask)) ? TEXT_COLOR : ALARM_COLOR;
|
||||
if (attr) {
|
||||
if (++numWarnings > 5) {
|
||||
lcd_putsAtt(x, y, "...", 0);
|
||||
break;
|
||||
if (++numWarnings < 6) {
|
||||
putsSwitches(x, y, SWSRC_FIRST_SWITCH+i*3, attr);
|
||||
x += 20;
|
||||
}
|
||||
else if (numWarnings == 6) {
|
||||
lcd_putsAtt(x, y, "...", ALARM_COLOR);
|
||||
}
|
||||
char c = "\300-\301"[(states & mask) >> (i*2)];
|
||||
putsMixerSource(x, y, MIXSRC_FIRST_SWITCH+i, attr);
|
||||
lcd_putcAtt(lcdNextPos, y, c, attr);
|
||||
x = lcdNextPos + 3;
|
||||
}
|
||||
#else
|
||||
LcdFlags attr = ((states & mask) == (switches_states & mask)) ? 0 : INVERS;
|
||||
if (attr) {
|
||||
if (++numWarnings < 7) {
|
||||
char c = "\300-\301"[(states & mask) >> (i*2)];
|
||||
putsMixerSource(x, y, MIXSRC_FIRST_SWITCH+i, attr);
|
||||
lcd_putcAtt(lcdNextPos, y, c, attr);
|
||||
x = lcdNextPos + 3;
|
||||
}
|
||||
else if (numWarnings == 7) {
|
||||
lcd_putsAtt(x, y, "...", 0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
if (g_model.potsWarnMode) {
|
||||
@@ -719,17 +863,34 @@ void checkSwitches()
|
||||
x = 60;
|
||||
}
|
||||
for (int i=0; i<NUM_POTS; i++) {
|
||||
if (!IS_POT_AVAILABLE(POT1+i)) {
|
||||
if (!IS_POT_AVAILABLE(i)) {
|
||||
continue;
|
||||
}
|
||||
if (!(g_model.potsWarnEnabled & (1 << i))) {
|
||||
if (abs(g_model.potsWarnPosition[i] - GET_LOWRES_POT_POSITION(i)) > 1) {
|
||||
#if defined(COLORLCD)
|
||||
char s[8];
|
||||
// TODO add an helper
|
||||
strncpy(s, &STR_VSRCRAW[1+(NUM_STICKS+1+i)*STR_VSRCRAW[0]], STR_VSRCRAW[0]);
|
||||
s[int(STR_VSRCRAW[0])] = '\0';
|
||||
#else
|
||||
lcd_putsiAtt(x, y, STR_VSRCRAW, NUM_STICKS+1+i, INVERS);
|
||||
if (IS_POT(POT1+i))
|
||||
lcd_putcAtt(lcdNextPos, y, g_model.potsWarnPosition[i] > GET_LOWRES_POT_POSITION(i) ? 126 : 127, INVERS);
|
||||
else
|
||||
lcd_putcAtt(lcdNextPos, y, g_model.potsWarnPosition[i] > GET_LOWRES_POT_POSITION(i) ? '\300' : '\301', INVERS);
|
||||
#endif
|
||||
#if defined(COLORLCD)
|
||||
if (++numWarnings < 6) {
|
||||
lcd_putsAtt(x, y, s, ALARM_COLOR);
|
||||
}
|
||||
else if (numWarnings == 6) {
|
||||
lcd_putsAtt(x, y, "...", ALARM_COLOR);
|
||||
}
|
||||
x += 20;
|
||||
#else
|
||||
x = lcdNextPos + 3;
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
@@ -761,30 +922,9 @@ void checkSwitches()
|
||||
last_bad_switches = 0xff;
|
||||
}
|
||||
#else
|
||||
if (pwrCheck()==e_power_off || keyDown()) return;
|
||||
|
||||
if (keyDown()) {
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined(PCBTARANIS) && defined(REV9E)
|
||||
uint32_t pwr_check = pwrCheck();
|
||||
if (pwr_check == e_power_off) {
|
||||
return;
|
||||
}
|
||||
else if (pwr_check == e_power_press) {
|
||||
refresh = true;
|
||||
}
|
||||
else if (pwr_check == e_power_on && refresh) {
|
||||
last_bad_switches = 0xff;
|
||||
refresh = false;
|
||||
}
|
||||
#else
|
||||
if (pwrCheck() == e_power_off) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
checkBacklight();
|
||||
doLoopCommonActions();
|
||||
|
||||
wdt_reset();
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ int g_snapshot_idx = 0;
|
||||
|
||||
#if defined(CPUSTM32)
|
||||
uint32_t Peri1_frequency, Peri2_frequency;
|
||||
GPIO_TypeDef gpioa, gpiob, gpioc, gpiod, gpioe, gpiof, gpiog;
|
||||
GPIO_TypeDef gpioa, gpiob, gpioc, gpiod, gpioe, gpiof, gpiog, gpioh, gpioi, gpioj;
|
||||
TIM_TypeDef tim1, tim2, tim3, tim4, tim5, tim6, tim7, tim8, tim9, tim10;
|
||||
RCC_TypeDef rcc;
|
||||
DMA_Stream_TypeDef dma2_stream2, dma2_stream6;
|
||||
@@ -152,7 +152,13 @@ void simuSetKey(uint8_t key, bool state)
|
||||
switch (key) {
|
||||
KEY_CASE(KEY_MENU, KEYS_GPIO_REG_MENU, KEYS_GPIO_PIN_MENU)
|
||||
KEY_CASE(KEY_EXIT, KEYS_GPIO_REG_EXIT, KEYS_GPIO_PIN_EXIT)
|
||||
#if defined(PCBTARANIS)
|
||||
#if defined(PCBHORUS)
|
||||
KEY_CASE(KEY_ENTER, KEYS_GPIO_REG_ENTER, KEYS_GPIO_PIN_ENTER)
|
||||
KEY_CASE(KEY_RIGHT, KEYS_GPIO_REG_RIGHT, KEYS_GPIO_PIN_RIGHT)
|
||||
KEY_CASE(KEY_LEFT, KEYS_GPIO_REG_LEFT, KEYS_GPIO_PIN_LEFT)
|
||||
KEY_CASE(KEY_UP, KEYS_GPIO_REG_UP, KEYS_GPIO_PIN_UP)
|
||||
KEY_CASE(KEY_DOWN, KEYS_GPIO_REG_DOWN, KEYS_GPIO_PIN_DOWN)
|
||||
#elif defined(PCBTARANIS) || defined(PCBFLAMENCO)
|
||||
KEY_CASE(KEY_ENTER, KEYS_GPIO_REG_ENTER, KEYS_GPIO_PIN_ENTER)
|
||||
KEY_CASE(KEY_PAGE, KEYS_GPIO_REG_PAGE, KEYS_GPIO_PIN_PAGE)
|
||||
KEY_CASE(KEY_MINUS, KEYS_GPIO_REG_MINUS, KEYS_GPIO_PIN_MINUS)
|
||||
@@ -186,6 +192,12 @@ void simuSetTrim(uint8_t trim, bool state)
|
||||
TRIM_CASE(5, TRIMS_GPIO_REG_RVU, TRIMS_GPIO_PIN_RVU)
|
||||
TRIM_CASE(6, TRIMS_GPIO_REG_RHL, TRIMS_GPIO_PIN_RHL)
|
||||
TRIM_CASE(7, TRIMS_GPIO_REG_RHR, TRIMS_GPIO_PIN_RHR)
|
||||
#if defined(HORUS)
|
||||
TRIM_CASE(8, TRIMS_GPIO_REG_LSU, TRIMS_GPIO_PIN_LSU)
|
||||
TRIM_CASE(9, TRIMS_GPIO_REG_LSD, TRIMS_GPIO_PIN_RVU)
|
||||
TRIM_CASE(10, TRIMS_GPIO_REG_RSU, TRIMS_GPIO_PIN_RHL)
|
||||
TRIM_CASE(11, TRIMS_GPIO_REG_RSD, TRIMS_GPIO_PIN_RHR)
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -194,7 +206,14 @@ void simuSetSwitch(uint8_t swtch, int8_t state)
|
||||
{
|
||||
// TRACE("simuSetSwitch(%d, %d)", swtch, state);
|
||||
switch (swtch) {
|
||||
#if defined(PCBTARANIS) && defined(REV9E)
|
||||
#if defined(PCBFLAMENCO)
|
||||
// SWITCH_3_CASE(0, SWITCHES_GPIO_REG_A_L, SWITCHES_GPIO_REG_A_H, SWITCHES_GPIO_PIN_A_L, SWITCHES_GPIO_PIN_A_H)
|
||||
// SWITCH_CASE(1, SWITCHES_GPIO_REG_B, SWITCHES_GPIO_PIN_B)
|
||||
// SWITCH_3_CASE(2, SWITCHES_GPIO_REG_C_L, SWITCHES_GPIO_REG_C_H, SWITCHES_GPIO_PIN_C_L, SWITCHES_GPIO_PIN_C_H)
|
||||
// SWITCH_3_CASE(3, SWITCHES_GPIO_REG_D_L, SWITCHES_GPIO_REG_D_H, SWITCHES_GPIO_PIN_D_L, SWITCHES_GPIO_PIN_D_H)
|
||||
// SWITCH_CASE(4, SWITCHES_GPIO_REG_E, SWITCHES_GPIO_PIN_E)
|
||||
// SWITCH_3_CASE(5, SWITCHES_GPIO_REG_F_H, SWITCHES_GPIO_REG_F_L, SWITCHES_GPIO_PIN_F_H, SWITCHES_GPIO_PIN_F_L)
|
||||
#elif defined(PCBTARANIS) && defined(REV9E)
|
||||
SWITCH_3_CASE(0, SWITCHES_GPIO_REG_A_L, SWITCHES_GPIO_REG_A_H, SWITCHES_GPIO_PIN_A_L, SWITCHES_GPIO_PIN_A_H)
|
||||
SWITCH_3_CASE(1, SWITCHES_GPIO_REG_B_L, SWITCHES_GPIO_REG_B_H, SWITCHES_GPIO_PIN_B_L, SWITCHES_GPIO_PIN_B_H)
|
||||
SWITCH_3_CASE(2, SWITCHES_GPIO_REG_C_L, SWITCHES_GPIO_REG_C_H, SWITCHES_GPIO_PIN_C_L, SWITCHES_GPIO_PIN_C_H)
|
||||
@@ -213,7 +232,7 @@ void simuSetSwitch(uint8_t swtch, int8_t state)
|
||||
SWITCH_3_CASE(15, SWITCHES_GPIO_REG_P_L, SWITCHES_GPIO_REG_P_H, SWITCHES_GPIO_PIN_P_L, SWITCHES_GPIO_PIN_P_H)
|
||||
SWITCH_3_CASE(16, SWITCHES_GPIO_REG_Q_L, SWITCHES_GPIO_REG_Q_H, SWITCHES_GPIO_PIN_Q_L, SWITCHES_GPIO_PIN_Q_H)
|
||||
SWITCH_3_CASE(17, SWITCHES_GPIO_REG_R_L, SWITCHES_GPIO_REG_R_H, SWITCHES_GPIO_PIN_R_L, SWITCHES_GPIO_PIN_R_H)
|
||||
#elif defined(PCBTARANIS)
|
||||
#elif defined(PCBTARANIS) || defined(PCBHORUS)
|
||||
SWITCH_3_CASE(0, SWITCHES_GPIO_REG_A_L, SWITCHES_GPIO_REG_A_H, SWITCHES_GPIO_PIN_A_L, SWITCHES_GPIO_PIN_A_H)
|
||||
SWITCH_3_CASE(1, SWITCHES_GPIO_REG_B_L, SWITCHES_GPIO_REG_B_H, SWITCHES_GPIO_PIN_B_L, SWITCHES_GPIO_PIN_B_H)
|
||||
SWITCH_3_CASE(2, SWITCHES_GPIO_REG_C_L, SWITCHES_GPIO_REG_C_H, SWITCHES_GPIO_PIN_C_L, SWITCHES_GPIO_PIN_C_H)
|
||||
@@ -271,7 +290,7 @@ uint16_t getTmr16KHz()
|
||||
return get_tmr10ms() * 160;
|
||||
}
|
||||
|
||||
#if !defined(PCBTARANIS)
|
||||
#if !defined(PCBTARANIS) && !defined(PCBHORUS)
|
||||
bool eeprom_thread_running = true;
|
||||
void *eeprom_write_function(void *)
|
||||
{
|
||||
@@ -329,6 +348,10 @@ void *main_thread(void *)
|
||||
try {
|
||||
#endif
|
||||
|
||||
#if defined(COLORLCD)
|
||||
lcdColorsInit();
|
||||
#endif
|
||||
|
||||
#if defined(CPUARM)
|
||||
stackPaint();
|
||||
#endif
|
||||
@@ -339,7 +362,9 @@ void *main_thread(void *)
|
||||
g_menuStack[0] = menuMainView;
|
||||
g_menuStack[1] = menuModelSelect;
|
||||
|
||||
#if defined(EEPROM)
|
||||
eeReadAll(); // load general setup and selected model
|
||||
#endif
|
||||
|
||||
#if defined(SIMU_DISKIO)
|
||||
f_mount(&g_FATFS_Obj, "", 1);
|
||||
@@ -364,6 +389,10 @@ void *main_thread(void *)
|
||||
|
||||
s_current_protocol[0] = 0;
|
||||
|
||||
#if defined(PCBFLAMENCO)
|
||||
menuEntryTime = get_tmr10ms() - 200;
|
||||
#endif
|
||||
|
||||
while (main_thread_running) {
|
||||
#if defined(CPUARM)
|
||||
doMixerCalculations();
|
||||
@@ -603,7 +632,7 @@ void StartEepromThread(const char *filename)
|
||||
sem_init(eeprom_write_sem, 0, 0);
|
||||
#endif
|
||||
|
||||
#if !defined(PCBTARANIS)
|
||||
#if !defined(PCBTARANIS) && !defined(PCBHORUS)
|
||||
eeprom_thread_running = true;
|
||||
assert(!pthread_create(&eeprom_thread_pid, NULL, &eeprom_write_function, NULL));
|
||||
#endif
|
||||
@@ -611,7 +640,7 @@ void StartEepromThread(const char *filename)
|
||||
|
||||
void StopEepromThread()
|
||||
{
|
||||
#if !defined(PCBTARANIS)
|
||||
#if !defined(PCBTARANIS) && !defined(PCBFLAMENCO) && !defined(PCBHORUS)
|
||||
eeprom_thread_running = false;
|
||||
sem_post(eeprom_write_sem);
|
||||
pthread_join(eeprom_thread_pid, NULL);
|
||||
@@ -640,7 +669,7 @@ void eepromReadBlock (uint8_t * pointer_ram, uint32_t pointer_eeprom, uint32_t s
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(PCBTARANIS)
|
||||
#if defined(PCBTARANIS) || defined(PCBFLAMENCO)
|
||||
void eepromWriteBlock(uint8_t * pointer_ram, uint32_t pointer_eeprom, uint32_t size)
|
||||
{
|
||||
assert(size);
|
||||
@@ -1198,9 +1227,11 @@ uint32_t sdGetSpeed()
|
||||
bool lcd_refresh = true;
|
||||
display_t lcd_buf[DISPLAY_BUF_SIZE];
|
||||
|
||||
#if !defined(PCBFLAMENCO) && !defined(PCBHORUS)
|
||||
void lcdSetRefVolt(uint8_t val)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
void adcPrepareBandgap()
|
||||
{
|
||||
@@ -1214,11 +1245,15 @@ void lcdOff()
|
||||
|
||||
void lcdRefresh()
|
||||
{
|
||||
#if defined(PCBFLAMENCO)
|
||||
TW8823_SendScreen();
|
||||
#endif
|
||||
|
||||
memcpy(lcd_buf, displayBuf, sizeof(lcd_buf));
|
||||
lcd_refresh = true;
|
||||
}
|
||||
|
||||
#if defined(PCBTARANIS)
|
||||
#if defined(PCBTARANIS) || defined(PCBFLAMENCO) || defined(PCBHORUS)
|
||||
void pwrInit() { }
|
||||
void pwrOff() { }
|
||||
#if defined(REV9E)
|
||||
@@ -1275,3 +1310,8 @@ void turnBacklightOff(void)
|
||||
|
||||
#endif // #if defined(PCBTARANIS)
|
||||
|
||||
#if defined(PCBFLAMENCO)
|
||||
void i2cWriteTW8823(unsigned char, unsigned char) { }
|
||||
uint8_t i2cReadBQ24195(uint8_t) { return 0; }
|
||||
void i2cWriteBQ24195(uint8_t, uint8_t) { }
|
||||
#endif
|
||||
|
||||
@@ -101,7 +101,7 @@ typedef const int16_t pm_int16_t;
|
||||
typedef const int8_t pm_int8_t;
|
||||
|
||||
#if defined(CPUSTM32)
|
||||
extern GPIO_TypeDef gpioa, gpiob, gpioc, gpiod, gpioe, gpiof, gpiog;
|
||||
extern GPIO_TypeDef gpioa, gpiob, gpioc, gpiod, gpioe, gpiof, gpiog, gpioh, gpioi, gpioj;
|
||||
extern TIM_TypeDef tim1, tim2, tim3, tim4, tim5, tim6, tim7, tim8, tim9, tim10;
|
||||
extern USART_TypeDef Usart0, Usart1, Usart2, Usart3, Usart4;
|
||||
extern RCC_TypeDef rcc;
|
||||
@@ -114,6 +114,9 @@ extern DMA_TypeDef dma2;
|
||||
#undef GPIOE
|
||||
#undef GPIOF
|
||||
#undef GPIOG
|
||||
#undef GPIOH
|
||||
#undef GPIOI
|
||||
#undef GPIOJ
|
||||
#define GPIOA (&gpioa)
|
||||
#define GPIOB (&gpiob)
|
||||
#define GPIOC (&gpioc)
|
||||
@@ -121,6 +124,9 @@ extern DMA_TypeDef dma2;
|
||||
#define GPIOE (&gpioe)
|
||||
#define GPIOF (&gpiof)
|
||||
#define GPIOG (&gpiog)
|
||||
#define GPIOH (&gpioh)
|
||||
#define GPIOI (&gpioi)
|
||||
#define GPIOJ (&gpioj)
|
||||
#undef TIM1
|
||||
#undef TIM2
|
||||
#undef TIM3
|
||||
@@ -392,23 +398,24 @@ extern OS_MutexID audioMutex;
|
||||
|
||||
#define CoInitOS(...)
|
||||
#define CoStartOS(...)
|
||||
#define CoCreateTask(...) (0)
|
||||
#define CoCreateMutex(...) PTHREAD_MUTEX_INITIALIZER
|
||||
#define CoCreateTask(...) 0
|
||||
#define CoCreateTaskEx(...) 0
|
||||
#define CoCreateMutex(...) PTHREAD_MUTEX_INITIALIZER
|
||||
#define CoSetFlag(...)
|
||||
#define CoClearFlag(...)
|
||||
#define CoSetTmrCnt(...)
|
||||
#define CoEnterISR(...)
|
||||
#define CoExitISR(...)
|
||||
#define CoStartTmr(...)
|
||||
#define CoWaitForSingleFlag(...) 0
|
||||
#define CoEnterMutexSection(m) pthread_mutex_lock(&(m))
|
||||
#define CoLeaveMutexSection(m) pthread_mutex_unlock(&(m))
|
||||
#define CoWaitForSingleFlag(...) 0
|
||||
#define CoEnterMutexSection(m) pthread_mutex_lock(&(m))
|
||||
#define CoLeaveMutexSection(m) pthread_mutex_unlock(&(m))
|
||||
#define CoTickDelay(...)
|
||||
#define CoCreateFlag(...) 0
|
||||
#define CoGetOSTime(...) 0
|
||||
#define CoCreateFlag(...) 0
|
||||
#define CoGetOSTime(...) 0
|
||||
#define UART_Stop(...)
|
||||
#define UART3_Stop(...)
|
||||
#define USART_GetITStatus(...) 0
|
||||
#define USART_GetITStatus(...) 0
|
||||
|
||||
#if defined(CPUSTM32)
|
||||
inline void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct) { }
|
||||
|
||||
@@ -97,6 +97,9 @@ uint16_t getStackAvailable(void * address, uint16_t size)
|
||||
i++;
|
||||
}
|
||||
return i*4;
|
||||
#if defined(CLI)
|
||||
cliStackPaint();
|
||||
#endif
|
||||
}
|
||||
|
||||
template<int SIZE>
|
||||
|
||||
@@ -47,7 +47,7 @@ uint8_t link_counter = 0;
|
||||
#define FRSKY_RX_PACKET_SIZE 19
|
||||
uint8_t frskyRxBuffer[FRSKY_RX_PACKET_SIZE]; // Receive buffer. 9 bytes (full packet), worst case 18 bytes with byte-stuffing (+1)
|
||||
|
||||
#if !defined(CPUARM)
|
||||
#if !defined(CPUARM) && !defined(PCBFLAMENCO)
|
||||
uint8_t frskyTxBuffer[FRSKY_TX_PACKET_SIZE];
|
||||
#endif
|
||||
|
||||
@@ -59,7 +59,7 @@ uint8_t frskyTxBufferCount = 0;
|
||||
uint8_t telemetryState = TELEMETRY_INIT;
|
||||
#endif
|
||||
|
||||
#if defined(PCBTARANIS)
|
||||
#if defined(PCBTARANIS) || defined(PCBFLAMENCO) || defined(PCBHORUS)
|
||||
Fifo<512> telemetryFifo; // TODO should be in the driver
|
||||
#endif
|
||||
|
||||
@@ -323,7 +323,7 @@ void telemetryWakeup()
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(CPUARM)
|
||||
#if !defined(CPUARM) && !defined(PCBFLAMENCO)
|
||||
if (IS_FRSKY_D_PROTOCOL()) {
|
||||
// Attempt to transmit any waiting Fr-Sky alarm set packets every 50ms (subject to packet buffer availability)
|
||||
static uint8_t frskyTxDelay = 5;
|
||||
|
||||
@@ -491,7 +491,7 @@ enum FrSkyDataState {
|
||||
#endif
|
||||
};
|
||||
|
||||
#if defined(CPUARM)
|
||||
#if defined(CPUARM) || defined(PCBFLAMENCO)
|
||||
#define frskySendAlarms()
|
||||
#else
|
||||
#define SEND_RSSI_ALARMS 6
|
||||
|
||||
Vendored
+2
-2
@@ -69,9 +69,9 @@ Idle task stack size(word).
|
||||
/*!<
|
||||
System frequency (Hz).
|
||||
*/
|
||||
#if defined(PCBTARANIS) && defined(REV9E)
|
||||
#if defined(PCBFLAMENCO) || (defined(PCBTARANIS) && defined(REV9E))
|
||||
#define CFG_CPU_FREQ (168000000)
|
||||
#elif defined(PCBTARANIS)
|
||||
#elif defined(PCBTARANIS) || defined(PCBHORUS)
|
||||
#define CFG_CPU_FREQ (120000000)
|
||||
#else
|
||||
#define CFG_CPU_FREQ (36000000) // TODO check if really correct for sky9x?
|
||||
|
||||
@@ -178,7 +178,7 @@
|
||||
<field type="int16_t" name="sue_waypoint_goal_x">Serial UDB Extra Current Waypoint Goal X</field>
|
||||
<field type="int16_t" name="sue_waypoint_goal_y">Serial UDB Extra Current Waypoint Goal Y</field>
|
||||
<field type="int16_t" name="sue_waypoint_goal_z">Serial UDB Extra Current Waypoint Goal Z</field>
|
||||
<field type="int16_t" name="sue_memory_stack_free">Serial UDB Extra Stack Memory Free</field>
|
||||
<field type="int16_t" name="sue_memory_taskStackFree">Serial UDB Extra Stack Memory Free</field>
|
||||
</message>
|
||||
<message id="172" name="SERIAL_UDB_EXTRA_F4">
|
||||
<description>Backwards compatible version of SERIAL_UDB_EXTRA F4: format</description>
|
||||
|
||||
+1
-1
@@ -30,9 +30,9 @@
|
||||
#ifndef __USB_AUDIO_CORE_H_
|
||||
#define __USB_AUDIO_CORE_H_
|
||||
|
||||
#include "../../../../../../../targets/Flamenco/usbd_desc.h"
|
||||
#include "usbd_ioreq.h"
|
||||
#include "usbd_req.h"
|
||||
#include "usbd_desc.h"
|
||||
|
||||
|
||||
|
||||
|
||||
+2
-2
@@ -30,8 +30,8 @@
|
||||
#define __USBD_CDC_IF_TEMPLATE_H
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "usb_conf.h"
|
||||
#include "usbd_conf.h"
|
||||
#include "../../../../../../../targets/Flamenco/usb_conf.h"
|
||||
#include "../../../../../../../targets/Flamenco/usbd_conf.h"
|
||||
#include "usbd_cdc_core.h"
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
|
||||
+2
-1
@@ -64,7 +64,8 @@
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "usbd_cdc_core.h"
|
||||
#include "../inc/usbd_cdc_core.h"
|
||||
|
||||
#include "usbd_desc.h"
|
||||
#include "usbd_req.h"
|
||||
|
||||
|
||||
+2
-2
@@ -30,8 +30,8 @@
|
||||
#define __DFU_MAL_H
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "usb_conf.h"
|
||||
|
||||
#include "../../../../../../../targets/Flamenco/usb_conf.h"
|
||||
#include "../../../../../../../targets/Flamenco/usbd_conf.h"
|
||||
#include "usbd_conf.h"
|
||||
#include "usbd_dfu_core.h"
|
||||
|
||||
|
||||
+1
-2
@@ -30,8 +30,7 @@
|
||||
#define __MEM_IF_MAL_H
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "usb_conf.h"
|
||||
|
||||
#include "../../../../../../../targets/Flamenco/usb_conf.h"
|
||||
#include "usbd_dfu_mal.h"
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
|
||||
+2
-1
@@ -63,7 +63,8 @@
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "usbd_dfu_core.h"
|
||||
#include "usbd_desc.h"
|
||||
|
||||
#include "../../../../../../../targets/Flamenco/usbd_desc.h"
|
||||
#include "usbd_req.h"
|
||||
#include "usb_bsp.h"
|
||||
|
||||
|
||||
+2
-1
@@ -48,7 +48,8 @@
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "usbd_hid_core.h"
|
||||
#include "../../../../../usbd_desc.h"
|
||||
|
||||
#include "../../../../../../../targets/Flamenco/usbd_desc.h"
|
||||
#include "usbd_req.h"
|
||||
|
||||
|
||||
|
||||
+1
-1
@@ -31,7 +31,7 @@
|
||||
#define _USBD_MSC_DATA_H_
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "usbd_conf.h"
|
||||
#include "../../../../../../../targets/Flamenco/usbd_conf.h"
|
||||
|
||||
/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
|
||||
* @{
|
||||
|
||||
+1
-1
@@ -30,7 +30,7 @@
|
||||
#define __USBD_CONF__H__
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "usb_conf.h"
|
||||
#include "../../../../../../targets/Flamenco/usb_conf.h"
|
||||
|
||||
/** @defgroup USB_CONF_Exported_Defines
|
||||
* @{
|
||||
|
||||
+1
-1
@@ -30,9 +30,9 @@
|
||||
#define __USBD_CORE_H
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "../../../../../../targets/Flamenco/usbd_conf.h"
|
||||
#include "../../../STM32_USB_OTG_Driver/inc/usb_dcd.h"
|
||||
#include "usbd_def.h"
|
||||
#include "usbd_conf.h"
|
||||
|
||||
/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
|
||||
* @{
|
||||
|
||||
+1
-1
@@ -31,9 +31,9 @@
|
||||
#define __USB_REQUEST_H_
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "../../../../../../targets/Flamenco/usbd_conf.h"
|
||||
#include "usbd_def.h"
|
||||
#include "usbd_core.h"
|
||||
#include "usbd_conf.h"
|
||||
|
||||
|
||||
/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
|
||||
|
||||
+2
-1
@@ -27,8 +27,9 @@
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "usbd_req.h"
|
||||
|
||||
#include "../../../../../../targets/Flamenco/usbd_desc.h"
|
||||
#include "usbd_ioreq.h"
|
||||
#include "usbd_desc.h"
|
||||
|
||||
|
||||
/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
|
||||
|
||||
+1
-1
@@ -30,7 +30,7 @@
|
||||
#define __USB_CONF__H__
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "usb_conf.h"
|
||||
#include "../../../../../targets/Flamenco/usb_conf.h"
|
||||
|
||||
/** @addtogroup USB_OTG_DRIVER
|
||||
* @{
|
||||
|
||||
+1
-1
@@ -30,7 +30,7 @@
|
||||
#define __USB_DEF_H__
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "usb_conf.h"
|
||||
#include "../../../../../targets/Flamenco/usb_conf.h"
|
||||
|
||||
/** @addtogroup USB_OTG_DRIVER
|
||||
* @{
|
||||
|
||||
Vendored
+1
-1
@@ -30,7 +30,7 @@
|
||||
#define __USB_OTG_REGS_H__
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "usb_conf.h"
|
||||
#include "../../../../../targets/Flamenco/usb_conf.h"
|
||||
|
||||
|
||||
/** @addtogroup USB_OTG_DRIVER
|
||||
|
||||
Vendored
+2
-1
@@ -28,7 +28,8 @@
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "usb_core.h"
|
||||
#include "usb_hcd.h"
|
||||
#include "usb_conf.h"
|
||||
|
||||
#include "../../../../../targets/Flamenco/usb_conf.h"
|
||||
#include "usb_bsp.h"
|
||||
|
||||
|
||||
|
||||
@@ -581,7 +581,7 @@ const pm_char STR_BLCOLOR[] PROGMEM = TR_BLCOLOR;
|
||||
const pm_char STR_CONFIRMDELETE[] PROGMEM = TR_CONFIRMDELETE;
|
||||
#endif
|
||||
|
||||
#if defined(PCBTARANIS)
|
||||
#if defined(PCBTARANIS) || defined(PCBFLAMENCO) || defined(PCBHORUS)
|
||||
const pm_char STR_BYTES[] PROGMEM = TR_BYTES;
|
||||
const pm_char STR_ANTENNAPROBLEM[] PROGMEM = TR_ANTENNAPROBLEM;
|
||||
const pm_char STR_MODULE[] PROGMEM = TR_MODULE;
|
||||
|
||||
@@ -800,7 +800,7 @@ extern const pm_char STR_BLCOLOR[];
|
||||
extern const pm_char STR_CONFIRMDELETE[];
|
||||
#endif
|
||||
|
||||
#if defined(PCBTARANIS)
|
||||
#if defined(PCBTARANIS) || defined(PCBFLAMENCO) || defined(PCBHORUS)
|
||||
extern const pm_char STR_BYTES[];
|
||||
extern const pm_char STR_ANTENNAPROBLEM[];
|
||||
extern const pm_char STR_MODULE[];
|
||||
|
||||
@@ -129,7 +129,9 @@
|
||||
|
||||
#define LEN_RETA123 "\001"
|
||||
|
||||
#if defined(PCBTARANIS) && defined(REV9E)
|
||||
#if defined(PCBFLAMENCO)
|
||||
#define TR_RETA123 "RETA123LR"
|
||||
#elif defined(PCBTARANIS) && defined(REV9E)
|
||||
#define TR_RETA123 "RETA1234LRLR"
|
||||
#elif defined(PCBTARANIS) || defined(REVX)
|
||||
#define TR_RETA123 "RETA123LR"
|
||||
@@ -443,8 +445,16 @@
|
||||
#define LEN_VSWASHTYPE "\004"
|
||||
#define TR_VSWASHTYPE "---\0""120\0""120X""140\0""90\0"
|
||||
|
||||
#if defined(PCBHORUS)
|
||||
#define LEN_VKEYS "\006"
|
||||
#define TR_VKEYS "Menu\0 ""Exit\0 ""Enter\0""Up\0 ""Down\0 ""Right\0""Left"
|
||||
#elif defined(PCBTARANIS)
|
||||
#define LEN_VKEYS "\005"
|
||||
#define TR_VKEYS TR("Menu\0""Exit\0""Down\0""Up\0 ""Right""Left\0", "Menu\0""Exit\0""Enter""Page\0""Plus\0""Minus")
|
||||
#define TR_VKEYS "Menu\0""Exit\0""Enter""Page\0""Plus\0""Minus"
|
||||
#else
|
||||
#define LEN_VKEYS "\005"
|
||||
#define TR_VKEYS "Menu\0""Exit\0""Down\0""Up\0 ""Right""Left\0"
|
||||
#endif
|
||||
|
||||
#define LEN_VRENCODERS "\003"
|
||||
#define TR_VRENCODERS "REa""REb"
|
||||
@@ -455,7 +465,10 @@
|
||||
#define TR_STICKS_VSRCRAW TR("Rud\0""Ele\0""Thr\0""Ail\0", "\307Rud""\307Ele""\307Thr""\307Ail")
|
||||
#define TR_TRIMS_VSRCRAW TR("TrmR""TrmE""TrmT""TrmA", "\313Rud""\313Ele""\313Thr""\313Ail")
|
||||
|
||||
#if defined(PCBTARANIS) && defined(REV9E)
|
||||
#if defined(PCBFLAMENCO)
|
||||
#define TR_POTS_VSRCRAW "SD\0 ""LS\0 ""RS\0 "
|
||||
#define TR_SW_VSRCRAW "SA\0 ""SB\0 ""SC\0 ""SE\0 ""SF\0 "
|
||||
#elif defined(PCBTARANIS) && defined(REV9E)
|
||||
#define TR_POTS_VSRCRAW "\310F1\0""\310F2\0""\310F3\0""\310F4\0""\311S1\0""\311S2\0""\311LS\0""\311RS\0"
|
||||
#define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0""\312SE\0""\312SF\0""\312SG\0""\312SH\0""\312SI\0""\312SJ\0""\312SK\0""\312SL\0""\312SM\0""\312SN\0""\312SO\0""\312SP\0""\312SQ\0""\312SR\0"
|
||||
#elif defined(PCBTARANIS)
|
||||
@@ -486,13 +499,17 @@
|
||||
#define TR_ROTENC_SWITCHES
|
||||
#endif
|
||||
|
||||
#if !defined(PCBTARANIS)
|
||||
#if defined(PCBFLAMENCO)
|
||||
#define TR_PHYS_SWITCHES "SA\300""SA-""SA\301""SB\300""SB\301""SC1""SC2""SC3""SC4""SC5""SC6""SE\300""SE\301""SF\300""SF-""SF\301"
|
||||
#elif !defined(PCBTARANIS)
|
||||
#define TR_PHYS_SWITCHES "THR""RUD""ELE""AIL""GEA""TRN"
|
||||
#endif
|
||||
|
||||
#define TR_ON_ONE_SWITCHES "ON\0""One"
|
||||
|
||||
#if defined(PCBTARANIS)
|
||||
#if defined(PCBFLAMENCO)
|
||||
#define TR_VSWITCHES "---" TR_PHYS_SWITCHES TR_TRIMS_SWITCHES TR_ROTENC_SWITCHES TR_LOGICALSW "ON\0""One"
|
||||
#elif defined(PCBTARANIS)
|
||||
// only special switches here
|
||||
#define TR_VSWITCHES "---" TR_TRIMS_SWITCHES TR_ON_ONE_SWITCHES
|
||||
#else
|
||||
@@ -546,8 +563,8 @@
|
||||
|
||||
// ZERO TERMINATED STRINGS
|
||||
#if defined(COLORLCD)
|
||||
#define INDENT "\007"
|
||||
#define LEN_INDENT 1
|
||||
#define INDENT " "
|
||||
#define LEN_INDENT 3
|
||||
#define INDENT_WIDTH 12
|
||||
#define BREAKSPACE "\036"
|
||||
#else
|
||||
@@ -557,7 +574,7 @@
|
||||
#define BREAKSPACE " "
|
||||
#endif
|
||||
|
||||
#if defined(PCBTARANIS)
|
||||
#if defined(PCBTARANIS) || defined(PCBFLAMENCO)
|
||||
#define TR_ENTER "[ENTER]"
|
||||
#else
|
||||
#define TR_ENTER "[MENU]"
|
||||
@@ -565,7 +582,9 @@
|
||||
|
||||
#define TR_EXIT "[EXIT]"
|
||||
|
||||
#if defined(PCBTARANIS)
|
||||
#if defined(PCBFLAMENCO)
|
||||
#define TR_POPUPS TR_EXIT "\010" TR_ENTER
|
||||
#elif defined(PCBTARANIS)
|
||||
#define TR_POPUPS TR_EXIT "\010" "\010" "\010" "\010" TR_ENTER
|
||||
#else
|
||||
#define TR_POPUPS TR_ENTER "\010" TR_EXIT
|
||||
@@ -1031,7 +1050,11 @@
|
||||
#define TR_ABOUT_MARTIN_1 "Martin Hotar"
|
||||
#define TR_ABOUT_MARTIN_2 "Graphics designer"
|
||||
|
||||
#if defined(PCBTARANIS)
|
||||
#if defined(PCBFLAMENCO)
|
||||
#define TR_ABOUT_HARDWARE_1 "XXX"
|
||||
#define TR_ABOUT_HARDWARE_2 "Hardware designer/producer"
|
||||
#define TR_ABOUT_HARDWARE_3 ""
|
||||
#elif defined(PCBTARANIS) || defined(PCBHORUS)
|
||||
#define TR_ABOUT_HARDWARE_1 "FrSky"
|
||||
#define TR_ABOUT_HARDWARE_2 "Hardware designer/producer"
|
||||
#define TR_ABOUT_HARDWARE_3 "Firmware contributor"
|
||||
|
||||
Reference in New Issue
Block a user