From 4b9270182e6faa098c5251e6c54360c67a9cc1c2 Mon Sep 17 00:00:00 2001 From: bsongis Date: Sat, 30 Nov 2013 11:11:14 +0100 Subject: [PATCH] [Taranis] A lot of new features, >100 hours work in one commit... --- src/Makefile | 101 +-- src/audio_arm.cpp | 45 +- src/audio_arm.h | 5 +- src/audio_avr.cpp | 1 + src/audio_avr.h | 9 +- src/bitmaps/icons.lbm | 4 +- src/bitmaps/icons.png | Bin 3181 -> 502 bytes src/bmp.cpp | 10 +- src/buzzer.h | 5 +- src/eeprom_common.h | 1 + src/eeprom_conversions.cpp | 574 +++++++++---- src/eeprom_raw.cpp | 10 +- src/eeprom_raw.h | 1 - src/eeprom_rlc.cpp | 27 +- src/fonts/std/font_03x05.lbm | 2 +- src/fonts/std/font_03x05.png | Bin 154 -> 222 bytes src/gtests.cpp | 8 +- src/gui/menu_general.cpp | 81 +- src/gui/menu_model.cpp | 1099 ++++++++++++++++++------ src/gui/menus.cpp | 174 +++- src/gui/menus.h | 29 +- src/gui/view_main.cpp | 94 +- src/gui/view_statistics.cpp | 22 +- src/gui/view_telemetry.cpp | 6 +- src/gui/view_text.cpp | 153 ++++ src/lcd.cpp | 163 +++- src/lcd.h | 34 +- src/logs.cpp | 2 +- src/maths.cpp | 21 + src/myeeprom.h | 384 ++++++--- src/opentx.cpp | 1131 ++++++++++++++++++------- src/opentx.h | 273 ++++-- src/sdcard.h | 4 + src/simpgmspace.cpp | 24 +- src/simpgmspace.h | 6 +- src/targets/gruvin9x/board_gruvin9x.h | 3 +- src/targets/mega2560/board_mega2560.h | 3 +- src/targets/sky9x/board_sky9x.h | 4 +- src/targets/sky9x/syscalls.c | 49 +- src/targets/stock/board_stock.h | 3 +- src/targets/taranis/adc_driver.cpp | 2 +- src/targets/taranis/board_taranis.h | 4 +- src/targets/taranis/delays.cpp | 2 +- src/targets/taranis/sport_driver.cpp | 2 +- src/targets/taranis/stm32_flash.ld | 5 +- src/targets/taranis/uart_driver.cpp | 2 +- src/telemetry/frsky_sport.cpp | 8 +- src/templates.cpp | 104 ++- src/templates.h | 16 +- src/translations.cpp | 36 +- src/translations.h | 37 +- src/translations/cz.h | 4 +- src/translations/cz.h.txt | 4 +- src/translations/de.h | 2 +- src/translations/de.h.txt | 2 +- src/translations/en.h | 35 +- src/translations/es.h | 16 +- src/translations/es.h.txt | 8 +- src/translations/fr.h | 8 +- src/translations/fr.h.txt | 8 +- src/translations/it.h | 8 +- src/translations/it.h.txt | 8 +- src/translations/pt.h | 8 +- src/translations/pt.h.txt | 8 +- src/translations/se.h | 2 +- src/translations/se.h.txt | 2 +- 66 files changed, 3611 insertions(+), 1295 deletions(-) create mode 100644 src/gui/view_text.cpp diff --git a/src/Makefile b/src/Makefile index 477d0fb4a..5cb2eccfb 100644 --- a/src/Makefile +++ b/src/Makefile @@ -246,6 +246,10 @@ GVARS = NO # Values = NO, POT1, POT2, POT3, 3POS = NO +# Menu Lock modes +# Values = NO, READONLY, NOMENUS +MENUS_LOCK == NO + #------- END BUILD OPTIONS --------------------------- # Define programs and commands. @@ -256,19 +260,21 @@ SVNREV = $(shell sh -c "svnversion | egrep -o '[[:digit:]]+[[:alpha:]]*$$'") SRC = CPPSRC = +INCDIRS = . translations +EXTRAINCDIRS = # MCU name ifneq ($(PCB), $(filter $(PCB), STD 9X 9XR STD128 9X128 9XR128 9X2561 9XR2561 GRUVIN9X MEGA2560 SKY9X TARANIS)) $(error Sorry, the PCB $(PCB) is not supported yet in openTx) endif -GVARS_VARIANT = +1 -FRSKY_VARIANT = +2 -3POS_VARIANT = +4 -MAVLINK_VARIANT = +8 -M128_VARIANT = +32768 -M2561_VARIANT = +16384 -EEPROM_VARIANT = 0 +GVARS_VARIANT = +1 +FRSKY_VARIANT = +2 +3POS_VARIANT = +4 +MAVLINK_VARIANT = +8 +M128_VARIANT = +32768 +M2561_VARIANT = +16384 +EEPROM_VARIANT = 0 ifeq ($(PCB), $(filter $(PCB), STD 9X 9XR)) # 9x/9xr radio @@ -278,7 +284,7 @@ ifeq ($(PCB), $(filter $(PCB), STD 9X 9XR)) OPT = s SDCARD = NO THR_TRACE = NO - EXTRAINCDIRS = targets/stock + INCDIRS += targets/stock CPPDEFS = -DF_CPU=$(F_CPU)UL -DPCBSTD -DCPUM64 -DEEPROM_VARIANT=$(shell echo ${EEPROM_VARIANT} | bc) BOARDSRC = targets/stock/board_stock.cpp EXTRABOARDSRC = targets/stock/lcd_driver.cpp @@ -338,7 +344,7 @@ ifeq ($(PCB), $(filter $(PCB), STD128 9X128 9XR128)) THR_TRACE = NO EEPROM_VARIANT += ${M128_VARIANT} CPPDEFS = -DF_CPU=$(F_CPU)UL -DPCBSTD -DCPUM128 -DEEPROM_VARIANT=$(shell echo ${EEPROM_VARIANT} | bc) - EXTRAINCDIRS = targets/stock + INCDIRS += targets/stock BOARDSRC = targets/stock/board_stock.cpp EXTRABOARDSRC = targets/stock/lcd_driver.cpp EEPROMSRC = eeprom_common.cpp eeprom_rlc.cpp @@ -397,7 +403,7 @@ ifeq ($(PCB), $(filter $(PCB), 9X2561)) THR_TRACE = YES EEPROM_VARIANT += ${M2561_VARIANT} CPPDEFS = -DF_CPU=$(F_CPU)UL -DPCBSTD -DCPUM2561 -DEEPROM_VARIANT=$(shell echo ${EEPROM_VARIANT} | bc) - EXTRAINCDIRS = targets/stock + INCDIRS += targets/stock BOARDSRC = targets/stock/board_stock.cpp EXTRABOARDSRC = targets/stock/lcd_driver.cpp EEPROMSRC = eeprom_common.cpp eeprom_rlc.cpp @@ -457,7 +463,7 @@ ifeq ($(PCB), GRUVIN9X) SDCARD = NO BUZZER = NO THR_TRACE = YES - EXTRAINCDIRS = targets/gruvin9x targets/stock FatFs FatFs/option + INCDIRS += targets/gruvin9x targets/stock FatFs FatFs/option BOARDSRC = targets/gruvin9x/board_gruvin9x.cpp EXTRABOARDSRC = targets/stock/lcd_driver.cpp EEPROMSRC = eeprom_common.cpp eeprom_rlc.cpp @@ -495,7 +501,7 @@ ifeq ($(PCB), MEGA2560) CPPDEFS = -DF_CPU=$(F_CPU)UL -DPCBMEGA2560 -DCPUM2560 -DEEPROM_VARIANT=0 -DAUDIO -DRTCLOCK SDCARD = YES THR_TRACE = YES - EXTRAINCDIRS = targets/mega2560 targets/stock FatFs FatFs/option + INCDIRS += targets/mega2560 targets/stock FatFs FatFs/option BOARDSRC = targets/mega2560/board_mega2560.cpp EXTRABOARDSRC = targets/mega2560/lcd_driver_ST7565R.cpp EEPROMSRC = eeprom_common.cpp eeprom_rlc.cpp @@ -535,7 +541,7 @@ ifeq ($(PCB), SKY9X) BUZZER = NO THR_TRACE = YES CPPDEFS += -DPCBSKY9X -DCPUARM -DEEPROM_VARIANT=0 -DAUDIO -DHAPTIC -DPXX -DDSM2 -DDSM2_PPM -DROTARY_ENCODERS=1 - EXTRAINCDIRS = targets/sky9x CoOS/kernel CoOS/portable + INCDIRS += targets/sky9x CoOS/kernel CoOS/portable BOARDSRC = targets/sky9x/board_sky9x.cpp EXTRABOARDSRC = targets/sky9x/lcd_driver.cpp SRC += targets/sky9x/core_cm3.c targets/sky9x/board_lowlevel.c targets/sky9x/crt.c targets/sky9x/vectors_sam3s.c @@ -551,7 +557,7 @@ ifeq ($(PCB), SKY9X) ifeq ($(SDCARD), YES) CPPDEFS += -DVOICE - EXTRAINCDIRS += FatFs FatFs/option + INCDIRS += FatFs FatFs/option EXTRABOARDSRC += FatFs/ff.c FatFs/fattime.c FatFs/option/ccsbcs.c targets/sky9x/diskio.cpp endif @@ -596,18 +602,18 @@ ifeq ($(PCB), TARANIS) THR_TRACE = YES EXT = FRSKY CPPDEFS += -DPCBTARANIS -DCPUARM -DEEPROM_VARIANT=0 -DAUDIO -DPXX - EXTRAINCDIRS = targets/taranis CoOS/kernel CoOS/portable + INCDIRS += targets/taranis CoOS/kernel CoOS/portable EXTRAINCDIRS += targets/taranis/STM32F2xx_StdPeriph_Lib_V1.1.0/Libraries/STM32F2xx_StdPeriph_Driver/inc targets/taranis/STM32F2xx_StdPeriph_Lib_V1.1.0/Libraries/CMSIS/Device/ST/STM32F2xx/Include targets/taranis/STM32F2xx_StdPeriph_Lib_V1.1.0/Libraries/CMSIS/include EXTRAINCDIRS += targets/taranis/STM32_USB-Host-Device_Lib_V2.1.0/Libraries/STM32_USB_OTG_Driver/inc targets/taranis/STM32_USB-Host-Device_Lib_V2.1.0/Libraries/STM32_USB_Device_Library/Core/inc EXTRAINCDIRS += targets/taranis/STM32_USB-Host-Device_Lib_V2.1.0/Libraries/STM32_USB_Device_Library/Class/msc/inc targets/taranis/STM32_USB-Host-Device_Lib_V2.1.0/Libraries/STM32_USB_Device_Library/Class/hid/inc BOARDSRC = targets/taranis/board_taranis.cpp EXTRABOARDSRC += targets/taranis/lcd_driver.cpp targets/taranis/aspi.cpp targets/taranis/i2c.c SRC += CoOS/kernel/core.c CoOS/kernel/hook.c CoOS/kernel/task.c CoOS/kernel/event.c CoOS/kernel/time.c CoOS/kernel/timer.c CoOS/kernel/flag.c CoOS/kernel/mutex.c CoOS/kernel/serviceReq.c CoOS/portable/GCC/port.c CoOS/portable/arch.c - EEPROMSRC = eeprom_common.cpp eeprom_rlc.cpp # TODO later eeprom_conversions.cpp + EEPROMSRC = eeprom_common.cpp eeprom_rlc.cpp eeprom_conversions.cpp PULSESSRC = protocols/pulses_arm.cpp protocols/ppm_arm.cpp protocols/pxx_arm.cpp CPPSRC += audio_arm.cpp CPPSRC += targets/taranis/pwr_driver.cpp targets/taranis/pulses_driver.cpp targets/taranis/keys_driver.cpp targets/taranis/adc_driver.cpp targets/taranis/trainer_driver.cpp targets/taranis/audio_driver.cpp targets/taranis/delays.cpp targets/taranis/uart_driver.cpp targets/taranis/sport_driver.cpp - CPPSRC += bmp.cpp gui/view_channels.cpp gui/view_about.cpp + CPPSRC += bmp.cpp gui/view_channels.cpp gui/view_about.cpp gui/view_text.cpp SRC += targets/taranis/STM32F2xx_StdPeriph_Lib_V1.1.0/Libraries/CMSIS/Device/ST/STM32F2xx/Source/Templates/system_stm32f2xx.c SRC += targets/taranis/STM32F2xx_StdPeriph_Lib_V1.1.0/Libraries/STM32F2xx_StdPeriph_Driver/src/misc.c SRC += targets/taranis/STM32F2xx_StdPeriph_Lib_V1.1.0/Libraries/STM32F2xx_StdPeriph_Driver/src/stm32f2xx_gpio.c @@ -631,11 +637,12 @@ ifeq ($(PCB), TARANIS) SRC += targets/taranis/STM32_USB-Host-Device_Lib_V2.1.0/Libraries/STM32_USB_Device_Library/Class/msc/src/usbd_msc_bot.c SRC += targets/taranis/STM32_USB-Host-Device_Lib_V2.1.0/Libraries/STM32_USB_Device_Library/Class/msc/src/usbd_msc_core.c EXTRABOARDSRC += targets/taranis/usbd_usr.cpp targets/taranis/usbd_storage_msd.cpp + SRC += targets/sky9x/syscalls.c ifeq ($(SDCARD), YES) EXTRABOARDSRC += FatFs/ff.c FatFs/fattime.c FatFs/option/ccsbcs.c targets/taranis/diskio.cpp CPPDEFS += -DVOICE - EXTRAINCDIRS += FatFs FatFs/option + INCDIRS += FatFs FatFs/option endif ifeq ($(RTCLOCK), YES) @@ -645,7 +652,6 @@ ifeq ($(PCB), TARANIS) ifeq ($(DEBUG), YES) CPPSRC += debug.cpp - SRC += targets/sky9x/syscalls.c endif ifeq ($(DSM2), PPM) @@ -696,12 +702,6 @@ CPPSRC += opentx.cpp $(PULSESSRC) stamp.cpp gui/menus.cpp gui/menu_model.cpp gui # AVR [Extended] COFF format requires stabs, plus an avr-objcopy run. DBGFMT = dwarf-2 -# List any extra directories to look for include files here. -# Each directory must be seperated by a space. -# Use forward slashes for directory separators. -# For a directory that has spaces, enclose it in quotes. -EXTRAINCDIRS += . translations - CPPDEFS += -DTRANSLATIONS_$(TRANSLATIONS) # TTS language @@ -780,8 +780,10 @@ endif ifneq ($(FONT), STD) CPPDEFS += -DFONT_$(FONT) - EXTRAINCDIRS += fonts/$(shell sh -c "echo $(FONT) | tr '[:upper:]' '[:lower:]'") + INCDIRS += fonts/$(shell sh -c "echo $(FONT) | tr '[:upper:]' '[:lower:]'") endif + +INCDIRS += fonts/std ifeq ($(THR_TRACE), YES) CPPDEFS += -DTHRTRACE @@ -800,6 +802,14 @@ ifeq ($(GVARS), YES) EEPROM_VARIANT += ${GVARS_VARIANT} endif +ifeq ($(MENUS_LOCK), READONLY) + CPPDEFS += -DMENUS_LOCK=1 +endif + +ifeq ($(MENUS_LOCK), NOMENUS) + CPPDEFS += -DMENUS_LOCK=2 +endif + ifeq ($(CORRECT_NEGATIVE_VALUES), YES) CPPDEFS += -DCORRECT_NEGATIVE_SHIFTS endif @@ -978,33 +988,17 @@ CPPFLAGS += $(CPPDEFS) CPPFLAGS += -Wall CPPFLAGS += -fno-exceptions CPPFLAGS += -Wno-strict-aliasing -EXTRAINCDIRS += fonts/std -CPPFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS)) +INCFLAGS = $(patsubst %,-I%,$(INCDIRS)) +EXTRAINCFLAGS = $(patsubst %,-I%,$(EXTRAINCDIRS)) MATH_LIB = -lm -#---------------- External Memory Options ---------------- - -# 64 KB of external RAM, starting after internal RAM (ATmega128!), -# used for variables (.data/.bss) and heap (malloc()). -#EXTMEMOPTS = -Wl,-Tdata=0x801100,--defsym=__heap_end=0x80ffff - -# 64 KB of external RAM, starting after internal RAM (ATmega128!), -# only used for heap (malloc()). -#EXTMEMOPTS = -Wl,--defsym=__heap_start=0x801100,--defsym=__heap_end=0x80ffff - -EXTMEMOPTS = - - - #---------------- Linker Options ---------------- # -Wl,...: tell GCC to pass this to linker. # -Map: create map file # --cref: add cross reference to map file LDFLAGS = -Wl,-Map=$(TARGET).map,--cref -LDFLAGS += $(EXTMEMOPTS) LDFLAGS += $(MATH_LIB) -#LDFLAGS += -T linker_script.x # Define Messages # English @@ -1022,8 +1016,8 @@ MSG_CLEANING = Cleaning project: # Combine all necessary flags and optional flags. # Add target processor to flags. -ARMCPPFLAGS = -c -mcpu=$(MCU) -mthumb -fomit-frame-pointer -fverbose-asm -Wa,-ahlms=opentx.lst -DRUN_FROM_FLASH=1 -O$(OPT) $(CPPFLAGS) $(GENDEPFLAGS) -AVRCPPFLAGS = -mmcu=$(MCU) -I. -x c++ -O$(OPT) $(CPPFLAGS) $(GENDEPFLAGS) -fwhole-program +ARMCPPFLAGS = -c -mcpu=$(MCU) -mthumb -fomit-frame-pointer -fverbose-asm -Wa,-ahlms=opentx.lst -DRUN_FROM_FLASH=1 -O$(OPT) $(CPPFLAGS) $(INCFLAGS) $(EXTRAINCFLAGS) $(GENDEPFLAGS) +AVRCPPFLAGS = -mmcu=$(MCU) -I. -x c++ -O$(OPT) $(CPPFLAGS) $(INCFLAGS) $(EXTRAINCFLAGS) $(GENDEPFLAGS) -fwhole-program ifeq ($(ARCH), AVR) GCCVERSIONGTE462 := $(shell expr 4.6.2 \<= `$(CC) -dumpversion`) @@ -1047,7 +1041,7 @@ all: begin gccversion sizebefore build sizeafter end # Change the build target to build a HEX file or a library. ifeq ($(ARCH), AVR) - build: stamp_header tra lbm allsrc.cpp elf remallsrc hex + build: stamp_header tra lbm allsrc.cpp elf remallsrc hex else build: stamp_header tra lbm allsrc.cpp elf remallsrc bin endif @@ -1176,7 +1170,6 @@ sizeafter: gccversion : @$(CC) --version -# gruvin: added extra include and lib paths to get simu working on my Mac FOXINC=-I/usr/local/include/fox-1.6 -I/usr/include/fox-1.6 \ -I$(FOXPATH)/include \ -I/opt/local/include/fox-1.6 @@ -1187,7 +1180,7 @@ FOXLIB=-L/usr/local/lib \ -Wl,-rpath,$(FOXPATH)/src/.libs simu: stamp_header $(BOARDSRC) $(CPPSRC) Makefile simu.cpp simpgmspace.cpp *.h tra lbm eeprom.bin - g++ $(CPPFLAGS) simu.cpp $(BOARDSRC) $(CPPSRC) simpgmspace.cpp -MD -DSIMU -O0 -o simu $(FOXINC) $(FOXLIB) -pthread + g++ $(CPPFLAGS) $(INCFLAGS) simu.cpp $(BOARDSRC) $(CPPSRC) simpgmspace.cpp -MD -DSIMU -O0 -o simu $(FOXINC) $(FOXLIB) -pthread -fexceptions eeprom.bin: dd if=/dev/zero of=$@ bs=1 count=2048 @@ -1327,12 +1320,6 @@ GTEST_DIR = ../gtest-1.6.0 # Where to find user code. USER_DIR = ./ -# Flags passed to the preprocessor. -CPPFLAGS += -I$(GTEST_DIR)/include - -# Flags passed to the C++ compiler. -CXXFLAGS += -g -Wall -Wextra - # All Google Test headers. Usually you shouldn't change this # definition. GTEST_HEADERS = $(GTEST_DIR)/include/gtest/*.h \ @@ -1351,11 +1338,11 @@ GTEST_SRCS_ = $(GTEST_DIR)/src/*.cc $(GTEST_DIR)/src/*.h $(GTEST_HEADERS) # conservative and not optimized. This is fine as Google Test # compiles fast and for ordinary users its source rarely changes. gtest-all.o : $(GTEST_SRCS_) - $(CXX) $(CPPFLAGS) -I$(GTEST_DIR) $(CXXFLAGS) -c \ + $(CXX) $(CPPFLAGS) -I$(GTEST_DIR) -c \ $(GTEST_DIR)/src/gtest-all.cc gtest_main.o : $(GTEST_SRCS_) - $(CXX) $(CPPFLAGS) -I$(GTEST_DIR) $(CXXFLAGS) -c \ + $(CXX) $(CPPFLAGS) -I$(GTEST_DIR) -c \ $(GTEST_DIR)/src/gtest_main.cc gtest.a : gtest-all.o diff --git a/src/audio_arm.cpp b/src/audio_arm.cpp index 8b6bf9b44..83988b215 100644 --- a/src/audio_arm.cpp +++ b/src/audio_arm.cpp @@ -82,10 +82,24 @@ const char * audioFilenames[] = { "warning3", "midtrim", "endtrim", - "midpot", + "midstck1", + "midstck2", + "midstck3", + "midstck4", +#if defined(PCBTARANIS) + "midpot1", + "midpot2", + "midslid1", + "midslid2", +#else + "midpot1", + "midpot2", + "midpot3", +#endif "mixwarn1", "mixwarn2", "mixwarn3", + "timer00", "timer10", "timer20", "timer30", @@ -152,11 +166,9 @@ inline uint8_t getAvailableFiles(char *prefix, FILINFO &info, char *filename) void refreshModelAudioFiles() { FILINFO info; -#if _USE_LFN TCHAR lfn[_MAX_LFN + 1]; info.lfname = lfn; info.lfsize = sizeof(lfn); -#endif char filename[AUDIO_FILENAME_MAXLEN+1] = SOUNDS_PATH "/"; strncpy(filename+SOUNDS_PATH_LNG_OFS, currentLanguagePack->id, 2); @@ -822,7 +834,18 @@ void audioEvent(uint8_t e, uint16_t f) audioQueue.play(BEEP_DEFAULT_FREQ, 200, 20, PLAY_NOW); break; // pot/stick center - case AU_POT_STICK_MIDDLE: + case AU_STICK1_MIDDLE: + case AU_STICK2_MIDDLE: + case AU_STICK3_MIDDLE: + case AU_STICK4_MIDDLE: + case AU_POT1_MIDDLE: + case AU_POT2_MIDDLE: +#if defined(PCBTARANIS) + case AU_SLIDER1_MIDDLE: + case AU_SLIDER2_MIDDLE: +#else + case AU_POT3_MIDDLE: +#endif audioQueue.play(BEEP_DEFAULT_FREQ+1500, 80, 20, PLAY_NOW); break; // mix warning 1 @@ -837,17 +860,21 @@ void audioEvent(uint8_t e, uint16_t f) case AU_MIX_WARNING_3: audioQueue.play(BEEP_DEFAULT_FREQ+1680, 48, 32, PLAY_REPEAT(2)); break; - // time <= 10 seconds left + // timer == 0 + case AU_TIMER_00: + audioQueue.play(BEEP_DEFAULT_FREQ+150, 240, 20, PLAY_NOW); + break; + // timer <= 10 seconds left case AU_TIMER_LT10: audioQueue.play(BEEP_DEFAULT_FREQ+150, 120, 20, PLAY_NOW); break; - // time 20 seconds left + // timer 20 seconds left case AU_TIMER_20: - audioQueue.play(BEEP_DEFAULT_FREQ, 120, 20, PLAY_REPEAT(1)|PLAY_NOW); + audioQueue.play(BEEP_DEFAULT_FREQ+150, 120, 20, PLAY_REPEAT(1)|PLAY_NOW); break; - // time 30 seconds left + // timer 30 seconds left case AU_TIMER_30: - audioQueue.play(BEEP_DEFAULT_FREQ, 120, 20, PLAY_REPEAT(2)|PLAY_NOW); + audioQueue.play(BEEP_DEFAULT_FREQ+150, 120, 20, PLAY_REPEAT(2)|PLAY_NOW); break; #if defined(PCBTARANIS) case AU_A1_ORANGE: diff --git a/src/audio_arm.h b/src/audio_arm.h index fd403222f..9b45187b0 100644 --- a/src/audio_arm.h +++ b/src/audio_arm.h @@ -249,10 +249,11 @@ void audioStart(); #define AUDIO_ERROR() AUDIO_BUZZER(audioEvent(AU_ERROR), beep(4)) #define AUDIO_TIMER_30() AUDIO_BUZZER(audioEvent(AU_TIMER_30), { beepAgain=2; beep(2); }) #define AUDIO_TIMER_20() AUDIO_BUZZER(audioEvent(AU_TIMER_20), { beepAgain=1; beep(2); }) -#define AUDIO_TIMER_LT10(x) AUDIO_BUZZER(audioEvent(AU_TIMER_LT10), beep(2)) +#define AUDIO_TIMER_LT10(m, x) do { if (m==COUNTDOWN_VOICE) playNumber(x, 0, 0, 0); else AUDIO_BUZZER(audioEvent(AU_TIMER_LT10), beep(2)); } while(0) +#define AUDIO_TIMER_00(m) do { if (m==COUNTDOWN_VOICE) playNumber(0, 0, 0, 0); else AUDIO_BUZZER(audioEvent(AU_TIMER_00), beep(3)); } while(0) #define AUDIO_INACTIVITY() AUDIO_BUZZER(audioEvent(AU_INACTIVITY), beep(3)) #define AUDIO_MIX_WARNING(x) AUDIO_BUZZER(audioEvent(AU_MIX_WARNING_1+x-1), beep(1)) -#define AUDIO_POT_STICK_MIDDLE() AUDIO_BUZZER(audioEvent(AU_POT_STICK_MIDDLE), beep(2)) +#define AUDIO_POT_MIDDLE(x) AUDIO_BUZZER(audioEvent(AU_STICK1_MIDDLE+x), beep(2)) #define AUDIO_VARIO_UP() audioEvent(AU_KEYPAD_UP) #define AUDIO_VARIO_DOWN() audioEvent(AU_KEYPAD_DOWN) #define AUDIO_TRIM_MIDDLE(f) AUDIO_BUZZER(audioEvent(AU_TRIM_MIDDLE, f), beep(2)) diff --git a/src/audio_avr.cpp b/src/audio_avr.cpp index f57816d38..356e9051d 100644 --- a/src/audio_avr.cpp +++ b/src/audio_avr.cpp @@ -242,6 +242,7 @@ void audioQueue::event(uint8_t e, uint8_t f) BEEP_DEFAULT_FREQ + 50, 6, 0, 0, // MIX_WARNING_1 BEEP_DEFAULT_FREQ + 52, 6, 3, PLAY_REPEAT(1), // MIX_WARNING_2 BEEP_DEFAULT_FREQ + 54, 6, 3, PLAY_REPEAT(2), // MIX_WARNING_3 + BEEP_DEFAULT_FREQ + 50, 30, 3, PLAY_NOW, // TIMER_00 BEEP_DEFAULT_FREQ + 50, 15, 3, PLAY_NOW, // TIMER_LT10 BEEP_DEFAULT_FREQ + 50, 15, 3, PLAY_REPEAT(1)|PLAY_NOW, // TIMER_20 BEEP_DEFAULT_FREQ + 50, 15, 3, PLAY_REPEAT(2)|PLAY_NOW, // TIMER_30 diff --git a/src/audio_avr.h b/src/audio_avr.h index 6290ac4b7..ba5e9653a 100644 --- a/src/audio_avr.h +++ b/src/audio_avr.h @@ -136,11 +136,12 @@ void audioDefevent(uint8_t e); #define AUDIO_INACTIVITY() VOICE_AUDIO_BUZZER(PUSH_SYSTEM_PROMPT(AU_INACTIVITY), audioDefevent(AU_INACTIVITY), beep(3)) #define AUDIO_ERROR_MESSAGE(e) VOICE_AUDIO_BUZZER(PUSH_SYSTEM_PROMPT((e)), audioDefevent(AU_ERROR), beep(4)) #define AUDIO_TIMER_MINUTE(t) VOICE_AUDIO_BUZZER(playDuration(t), audioDefevent(AU_WARNING1), beep(2)) -#define AUDIO_TIMER_30() VOICE_AUDIO_BUZZER(PUSH_SYSTEM_PROMPT(AU_TIMER_30+1/*to avoid renumbering*/), audioDefevent(AU_TIMER_30), { beepAgain=2; beep(2); }) -#define AUDIO_TIMER_20() VOICE_AUDIO_BUZZER(PUSH_SYSTEM_PROMPT(AU_TIMER_20+1/*to avoid renumbering*/), audioDefevent(AU_TIMER_20), { beepAgain=1; beep(2); }) -#define AUDIO_TIMER_LT10(x) AUDIO_BUZZER(audioDefevent(AU_TIMER_LT10), beep(2)) +#define AUDIO_TIMER_30() VOICE_AUDIO_BUZZER(PUSH_SYSTEM_PROMPT(AU_TIMER_30), audioDefevent(AU_TIMER_30), { beepAgain=2; beep(2); }) +#define AUDIO_TIMER_20() VOICE_AUDIO_BUZZER(PUSH_SYSTEM_PROMPT(AU_TIMER_20), audioDefevent(AU_TIMER_20), { beepAgain=1; beep(2); }) +#define AUDIO_TIMER_LT10(m, x) AUDIO_BUZZER(audioDefevent(AU_TIMER_LT10), beep(2)) +#define AUDIO_TIMER_00(m) AUDIO_BUZZER(audioDefevent(AU_TIMER_00), beep(3)) #define AUDIO_MIX_WARNING(x) AUDIO_BUZZER(audioDefevent(AU_MIX_WARNING_1+x-1), beep(1)) -#define AUDIO_POT_STICK_MIDDLE() AUDIO_BUZZER(audioDefevent(AU_POT_STICK_MIDDLE), beep(2)) +#define AUDIO_POT_MIDDLE(x) AUDIO_BUZZER(audioDefevent(AU_POT_MIDDLE), beep(2)) #define AUDIO_VARIO_UP() audioDefevent(AU_KEYPAD_UP) #define AUDIO_VARIO_DOWN() audioDefevent(AU_KEYPAD_DOWN) #define AUDIO_TRIM_MIDDLE(f) AUDIO_BUZZER(audio.event(AU_TRIM_MIDDLE, f), beep(2)) diff --git a/src/bitmaps/icons.lbm b/src/bitmaps/icons.lbm index 3f159efd6..b111790e1 100644 --- a/src/bitmaps/icons.lbm +++ b/src/bitmaps/icons.lbm @@ -1,2 +1,2 @@ -102,8, -0xff,0xff,0x00,0x00,0xff,0xff,0x1c,0x1c,0x6b,0xff,0xb6,0x22,0xbf,0xff,0xc0,0x80,0xff,0xff,0xe8,0xe8,0xbf,0xff,0xc0,0x80,0x6b,0xff,0xb6,0x22,0xff,0xff,0x1c,0x1c,0xff,0xff,0x00,0x00,0xff,0xff,0x38,0x38,0xbb,0xff,0x7c,0x38,0x7d,0xff,0xfe,0x7c,0xff,0xff,0xfe,0xfe,0xff,0xff,0x00,0x00,0xff,0xff,0x50,0x50,0xff,0xff,0x20,0x20,0xff,0xff,0x50,0x50,0xff,0xff,0x38,0x38,0xbb,0xff,0x7c,0x38,0x7d,0xff,0xfe,0x7c,0xff,0xff,0xfe,0xfe,0xff,0xff,0x00,0x00,0xff,0xff,0x40,0x40,0xff,0xff,0x40,0x40,0xff,0xff,0x40,0x40,0xff,0xff,0x38,0x38,0xbb,0xff,0x7c,0x38,0x7d,0xff,0xfe,0x7c,0xff,0xff,0xfe,0xfe,0xff,0xff,0x00,0x00,0xff,0xff,0x50,0x50,0xff,0xff,0x50,0x50,0xff,0xff,0x50,0x50,0xff,0xff,0x38,0x38,0xbb,0xff,0x7c,0x38,0x7d,0xff,0xfe,0x7c,0xff,0xff,0xfe,0xfe,0xff,0xff,0x00,0x00,0xff,0xff,0x54,0x54,0xff,0xff,0x54,0x54,0xff,0xff,0x54,0x54,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x7f,0xff,0xc1,0x41,0x41,0xff,0xfd,0x7d,0x7d,0xff,0xfd,0x7d,0x7d,0xff,0xfd,0x7d,0x7d,0xff,0xfd,0x7d,0x7d,0xfd,0xfb,0x7b,0x79,0xfb,0xc7,0x47,0x43,0xff,0xff,0x7f,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x7f,0xff,0xff,0x7f,0x7f,0xe3,0xff,0x77,0x63,0xdd,0xff,0x63,0x41,0xdd,0xff,0x41,0x41,0xdd,0xff,0x63,0x41,0xe3,0xff,0x77,0x63,0xff,0xff,0x7f,0x7f,0xff,0xff,0x7f,0x7f,0xff,0xff,0xff,0xff,0xfd,0xff,0x43,0x41,0xff,0xff,0x7d,0x7d,0xff,0xff,0x73,0x73,0xff,0xff,0x7d,0x7d,0xdd,0xff,0x63,0x41,0xff,0xff,0x5f,0x5f,0xff,0xff,0x59,0x59,0xdd,0xff,0x63,0x41,0xff,0xff,0x79,0x79,0xff,0xff,0xff,0xff,0xff,0xff,0x79,0x79,0xdd,0xff,0x63,0x41,0xff,0xff,0x59,0x59,0xff,0xff,0x5f,0x5f,0xf5,0xff,0x5b,0x51,0xff,0xff,0x55,0x55,0xff,0xff,0x55,0x55,0xff,0xff,0x55,0x55,0xd7,0xff,0x6d,0x45,0xff,0xff,0xff,0xff,0xff,0xff,0x63,0x63,0xff,0xff,0x63,0x63,0xff,0xff,0x77,0x77,0xff,0xff,0x73,0x73,0xff,0xff,0x65,0x65,0xfd,0xff,0x57,0x55,0xff,0xff,0x77,0x77,0xff,0xff,0x63,0x63,0xeb,0xff,0x77,0x63,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x7f,0xff,0xff,0x7f,0x7f,0xff,0xff,0x7f,0x7f,0xff,0xff,0x7f,0x7f,0xff,0xff,0x51,0x51,0xff,0xff,0x7f,0x7f,0xff,0xff,0x7f,0x7f,0xff,0xff,0x7f,0x7f,0xff,0xff,0x7f,0x7f,0xff,0xff,0xff,0xff, +111,8, +0xff,0xff,0x00,0x00,0xff,0xff,0x1c,0x1c,0x6b,0xff,0xb6,0x22,0xbf,0xff,0xc0,0x80,0xff,0xff,0xe8,0xe8,0xbf,0xff,0xc0,0x80,0x6b,0xff,0xb6,0x22,0xff,0xff,0x1c,0x1c,0xff,0xff,0x00,0x00,0xff,0xff,0x38,0x38,0xbb,0xff,0x7c,0x38,0x7d,0xff,0xfe,0x7c,0xff,0xff,0xfe,0xfe,0xff,0xff,0x00,0x00,0xff,0xff,0x50,0x50,0xff,0xff,0x20,0x20,0xff,0xff,0x50,0x50,0xff,0xff,0x38,0x38,0xbb,0xff,0x7c,0x38,0x7d,0xff,0xfe,0x7c,0xff,0xff,0xfe,0xfe,0xff,0xff,0x00,0x00,0xff,0xff,0x40,0x40,0xff,0xff,0x40,0x40,0xff,0xff,0x40,0x40,0xff,0xff,0x38,0x38,0xbb,0xff,0x7c,0x38,0x7d,0xff,0xfe,0x7c,0xff,0xff,0xfe,0xfe,0xff,0xff,0x00,0x00,0xff,0xff,0x50,0x50,0xff,0xff,0x50,0x50,0xff,0xff,0x50,0x50,0xff,0xff,0x38,0x38,0xbb,0xff,0x7c,0x38,0x7d,0xff,0xfe,0x7c,0xff,0xff,0xfe,0xfe,0xff,0xff,0x00,0x00,0xff,0xff,0x54,0x54,0xff,0xff,0x54,0x54,0xff,0xff,0x54,0x54,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x7f,0xff,0xc1,0x41,0x41,0xff,0xfd,0x7d,0x7d,0xff,0xfd,0x7d,0x7d,0xff,0xfd,0x7d,0x7d,0xff,0xfd,0x7d,0x7d,0xfd,0xfb,0x7b,0x79,0xfb,0xc7,0x47,0x43,0xff,0xff,0x7f,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x7f,0xff,0xff,0x7f,0x7f,0xe3,0xff,0x77,0x63,0xdd,0xff,0x63,0x41,0xdd,0xff,0x41,0x41,0xdd,0xff,0x63,0x41,0xe3,0xff,0x77,0x63,0xff,0xff,0x7f,0x7f,0xff,0xff,0x7f,0x7f,0xff,0xff,0xff,0xff,0xfd,0xff,0x43,0x41,0xff,0xff,0x7d,0x7d,0xff,0xff,0x73,0x73,0xff,0xff,0x7d,0x7d,0xdd,0xff,0x63,0x41,0xff,0xff,0x5f,0x5f,0xff,0xff,0x59,0x59,0xdd,0xff,0x63,0x41,0xff,0xff,0x79,0x79,0xff,0xff,0xff,0xff,0xff,0xff,0x79,0x79,0xdd,0xff,0x63,0x41,0xff,0xff,0x59,0x59,0xff,0xff,0x5f,0x5f,0xf5,0xff,0x5b,0x51,0xff,0xff,0x55,0x55,0xff,0xff,0x55,0x55,0xff,0xff,0x55,0x55,0xd7,0xff,0x6d,0x45,0xff,0xff,0xff,0xff,0xff,0xff,0x63,0x63,0xff,0xff,0x63,0x63,0xff,0xff,0x77,0x77,0xff,0xff,0x73,0x73,0xff,0xff,0x65,0x65,0xfd,0xff,0x57,0x55,0xff,0xff,0x77,0x77,0xff,0xff,0x63,0x63,0xeb,0xff,0x77,0x63,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x7f,0xff,0xff,0x7f,0x7f,0xff,0xff,0x7f,0x7f,0xff,0xff,0x7f,0x7f,0xff,0xff,0x51,0x51,0xff,0xff,0x7f,0x7f,0xff,0xff,0x7f,0x7f,0xff,0xff,0x7f,0x7f,0xff,0xff,0x7f,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0x40,0x40,0xff,0xff,0x20,0x20,0xff,0xff,0x10,0x10,0xff,0xff,0x08,0x08,0xff,0xff,0x10,0x10,0xff,0xff,0x08,0x08,0xff,0xff,0x06,0x06,0xff,0xff,0x18,0x18,0xff,0xff,0xe0,0xe0, diff --git a/src/bitmaps/icons.png b/src/bitmaps/icons.png index 8b08f8a691beff81b66c6a1b804241f72b326ca4..dcd4e5a98e92db5b34b3e59ae73fdb8e89bc08d4 100644 GIT binary patch delta 491 zcmVK00J6JGlH^?o!4|eBs*}W2BV0O9(-0ou%euJms`)Tk_|5w$={Az^N2MEXyK< z0D!*l5%0PV^Q3GMq=n>TWXcgOCvY$SlUDMBad%2$uM;ogRCzYOX_{%8IHHtVmZd0) zbzPNG#~LAaxF15GLpfih;`9PePAa;8OMI4eM%Q(u$CtTY8H+D>*tU(oI_HEC>$+A| z<(&Iq_;R^%?r<#?h1xt{Mbs9*+KdR+T4#p^4|{7`A8WI&>u6zw^nDKiN-5_YwRt*8 zQYmmraxnc*U{Tq+vh@;)v_FOwQ41JjxZ0^NBE};;ojYgn`&w3QPd529$r73(z2u8{ h)FylPf0wUP${*A_ioik9LS6s>002ovPDHLkV1gU3(Ru&? literal 3181 zcmV-z43hJSP)KLZ*U+IBfRsybQWXdwQbLP>6pAqfylh#{fb6;Z(vMMVS~$e@S=j*ftg6;Uhf59&ghTmgWD0l;*T zI709Y^p6lP1rIRMx#05C~cW=H_Aw*bJ-5DT&Z2n+x)QHX^p z00esgV8|mQcmRZ%02D^@S3L16t`O%c004NIvOKvYIYoh62rY33S640`D9%Y2D-rV&neh&#Q1i z007~1e$oCcFS8neI|hJl{-P!B1ZZ9hpmq0)X0i`JwE&>$+E?>%_LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxW zizFb)h!jyGOOZ85F;a?DAXP{m@;!0_IfqH8(HlgRxt7s3}k3K`kFu>>-2Q$QMFfPW!La{h336o>X zu_CMttHv6zR;&ZNiS=X8v3CR#fknUxHUxJ0uoBa_M6WNWeqIg~6QE69c9o#eyhGvpiOA@W-aonk<7r1(?fC{oI5N*U!4 zfg=2N-7=cNnjjOr{yriy6mMFgG#l znCF=fnQv8CDz++o6_Lscl}eQ+l^ZHARH>?_s@|##Rr6KLRFA1%Q+=*RRWnoLsR`7U zt5vFIcfW3@?wFpwUVxrVZ>QdQz32KIeJ}k~{cZZE^+ya? z2D1z#2HOnI7(B%_ac?{wFUQ;QQA1tBKtrWrm0_3Rgps+?Jfqb{jYbcQX~taRB;#$y zZN{S}1|}gUOHJxc?wV3fxuz+mJ4`!F$IZ;mqRrNsHJd##*D~ju=bP7?-?v~|cv>vB zsJ6IeNwVZxrdjT`yl#bBIa#GxRa#xMMy;K#CDyyGyQdMSxlWT#tDe?p!?5wT$+oGt z8L;Kp2HUQ-ZMJ=3XJQv;x5ci*?vuTfeY$;({XGW_huIFR9a(?@3)XSs8O^N5RyOM=TTmp(3=8^+zpz2r)C z^>JO{deZfso3oq3?Wo(Y?l$ge?uXo;%ru`Vo>?<<(8I_>;8Eq#KMS9gFl*neeosSB zfoHYnBQIkwkyowPu(zdms`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMe zBmZRodjHV?r+_5^X9J0WL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0 z?2xS?_ve_-kiKB_KiJlZ$9G`c^=E@oNG)mWWaNo-3TIW8)$Hg0Ub-~8?KhvJ>$ z3*&nim@mj(aCxE5!t{lw7O5^0EIO7zOo&c6l<+|iDySBWCGrz@C5{St!X3hAA}`T4 z(TLbXTq+(;@<=L8dXnssyft|w#WSTW<++3>sgS%(4NTpeI-VAqb|7ssJvzNHgOZVu zaYCvgO_R1~>SyL=cFU|~g|hy|Zi}}s9+d~lYqOB71z9Z$wnC=pR9Yz4DhIM>Wmjgu z&56o6maCpC&F##y%G;1PobR9i?GnNg;gYtchD%p19a!eQtZF&3JaKv33gZ<8D~47E ztUS1iwkmDaPpj=$m#%)jCVEY4fnLGNg2A-`YwHVD3gv};>)hAvT~AmqS>Lr``i7kw zJ{5_It`yrBmlc25DBO7E8;5VoznR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX z4c}I@?e+FW+b@^RDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i& z_B8C(+grT%{XWUQ+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?Z*Ss1N{dh4z}01 z)YTo*JycSU)+_5r4#yw9{+;i4Ee$peRgIj+;v;ZGdF1K$3E%e~4LaI(jC-u%2h$&R z9cLXcYC@Xwnns&bn)_Q~Te?roKGD|d-g^8;+aC{{G(1^(O7m37Y1-+6)01cN&y1aw zoqc{T`P^XJqPBbIW6s}d4{z_f5Om?vMgNQEJG?v2T=KYd^0M3I6IZxbny)%vZR&LD zJpPl@Psh8QyPB@KTx+@RdcC!KX7}kEo;S|j^u2lU7XQ}Oo;f|;z4Ll+_r>@1-xl3| zawq-H%e&ckC+@AhPrP6BKT#_XdT7&;F71j}Joy zkC~6lh7E@6o;W@^IpRNZ{ptLtL(gQ-CY~4mqW;US7Zxvm_|@yz&e53Bp_lTPlfP|z zrTyx_>lv@x#=^!PzR7qqF<$gm`|ZJZ+;<)Cqu&ot2z=0000WV@Og>004R=004l4008;_004mL004C`008P>0026e000+nl3&F} z0004)Nkl@2tS2&n{%T*mD^&GhCnDFQjdR$JJJ7Z4Ww&5ulC zqAP!e&){E_Gew)8s1^e2ffh?IuZQ$>EAr4;V> zJCsr@jEG>20RR|dKt$d=#GLNte8hzN+>(_2#U&whLPV(RdNH)tqHWtvQs0TE5>%F@ zrw_w`uIq5S-Bw8vLSP(62qB=9Len%0URBi+ACJ>vT)6J+QUr6K9NUXOni&3a=a_%Y zUMo2R=R|GUU$0m6eZN|lQeqrOWLbu3njocoxovV{L)}{IeOpL4ue4Nh4<*K0i>j); z3ON$MyYG!7exJ|hYE5emAq1vrLZ0W)TEFG~3Qv8Q0OyZ$<0|IJ`!C!Hf3|I#?0+$v zqq0{KF}x^>sIS<1(=<>@K}rd&wb#Z{tu%Eg!zu}})E(`(+2SY3pD|{3gNSATGZD>v zonrvzpFcV88N<2$8~hVT=6;vMUP(l&zUcOBot`uB@N(X3um54+Hvj+t|NjF3e`L~q Tcm?r<00000NkvXXu0mjfOS|p} diff --git a/src/bmp.cpp b/src/bmp.cpp index fd8f098fd..729273134 100644 --- a/src/bmp.cpp +++ b/src/bmp.cpp @@ -36,7 +36,7 @@ #include "opentx.h" -const pm_char * bmpLoad(uint8_t *dest, const char *filename, const xcoord_t width, const uint8_t height) +const pm_char * bmpLoad(bmp_ptr_t &bmp, const char *filename, const xcoord_t width, const uint8_t height) { FIL bmpFile; UINT read; @@ -147,10 +147,16 @@ const pm_char * bmpLoad(uint8_t *dest, const char *filename, const xcoord_t widt } } + if (bmp == NULL) { + bmp = (uint8_t *)malloc(2+w*((h+7)/8)*4); + } + + uint8_t *dest = bmp; + *dest++ = w; *dest++ = h; - memset(dest, 0, w*(h/8)*4); + memset(dest, 0, w*((h+7)/8)*4); uint32_t n; diff --git a/src/buzzer.h b/src/buzzer.h index 71c8dafc4..4f89e78cb 100644 --- a/src/buzzer.h +++ b/src/buzzer.h @@ -87,8 +87,9 @@ void beep(uint8_t val); #define AUDIO_WARNING1() beep(3) #define AUDIO_ERROR() beep(4) #define AUDIO_MIX_WARNING(x) beep(1) - #define AUDIO_POT_STICK_MIDDLE() beep(2) - #define AUDIO_TIMER_LT10(x) beep(2) + #define AUDIO_POT_MIDDLE(x) beep(2) + #define AUDIO_TIMER_LT10(m, x) beep(2) + #define AUDIO_TIMER_00(m) beep(3) #define AUDIO_VARIO_UP() _beep(1) #define AUDIO_VARIO_DOWN() _beep(1) #define AUDIO_TRIM(event, f) { if (!IS_KEY_FIRST(event)) warble = true; beep(1); } diff --git a/src/eeprom_common.h b/src/eeprom_common.h index 68b3910c0..8e9243f79 100644 --- a/src/eeprom_common.h +++ b/src/eeprom_common.h @@ -55,6 +55,7 @@ void eeReadAll(); bool eeModelExists(uint8_t id); void eeLoadModelName(uint8_t id, char *name); void eeLoadModel(uint8_t id); +bool eeConvert(); #if defined(CPUARM) extern ModelHeader modelHeaders[MAX_MODELS]; diff --git a/src/eeprom_conversions.cpp b/src/eeprom_conversions.cpp index 658955988..6107d3e51 100644 --- a/src/eeprom_conversions.cpp +++ b/src/eeprom_conversions.cpp @@ -36,55 +36,100 @@ #include "opentx.h" +PACK(typedef struct { + uint8_t mode; // 0=end, 1=pos, 2=neg, 3=both + uint8_t chn; + int8_t swtch; + uint16_t phases; + int8_t weight; + uint8_t curveMode; + char name[LEN_EXPOMIX_NAME]; + uint8_t spare[2]; + int8_t curveParam; +}) ExpoData_v215; + +PACK(typedef struct { + int8_t min; + int8_t max; + int8_t ppmCenter; + int16_t offset:14; + uint16_t symetrical:1; + uint16_t revert:1; +#if defined(PCBTARANIS) + char name[LEN_CHANNEL_NAME]; +#endif +}) LimitData_v215; + +#if defined(PCBTARANIS) PACK(typedef struct { uint8_t destCh; uint16_t phases; - uint8_t curveMode:1; // O=curve, 1=differential - uint8_t noExpo:1; - int8_t carryTrim:3; - uint8_t mltpx:2; // multiplex method: 0 means +=, 1 means *=, 2 means := - uint8_t spare:1; - int8_t weight; - int8_t swtch; - int8_t curveParam; - uint8_t mixWarn; // mixer warning - uint8_t delayUp; - uint8_t delayDown; - uint8_t speedUp; - uint8_t speedDown; - uint8_t srcRaw; - int8_t sOffset; - char name[LEN_EXPOMIX_NAME]; -}) MixData_v212; + uint8_t curveMode:1; // O=curve, 1=differential + uint8_t noExpo:1; + int8_t carryTrim:3; + uint8_t mltpx:2; // multiplex method: 0 means +=, 1 means *=, 2 means := + uint8_t spare1:1; + int16_t weight; + int8_t swtch; + int8_t curveParam; + uint8_t mixWarn:4; // mixer warning + uint8_t srcVariant:4; + uint8_t delayUp; + uint8_t delayDown; + uint8_t speedUp; + uint8_t speedDown; + uint8_t srcRaw; + int16_t offset; + char name[LEN_EXPOMIX_NAME]; + uint8_t spare2[2]; +}) MixData_v215; +#else +PACK(typedef struct { + uint8_t destCh; + uint16_t phases; + uint8_t curveMode:1; // O=curve, 1=differential + uint8_t noExpo:1; + int8_t carryTrim:3; + uint8_t mltpx:2; // multiplex method: 0 means +=, 1 means *=, 2 means := + uint8_t spare:1; + int16_t weight; + int8_t swtch; + int8_t curveParam; + uint8_t mixWarn:4; // mixer warning + uint8_t srcVariant:4; + uint8_t delayUp; + uint8_t delayDown; + uint8_t speedUp; + uint8_t speedDown; + uint8_t srcRaw; + int16_t offset; + char name[LEN_EXPOMIX_NAME]; +}) MixData_v215; +#endif PACK(typedef struct { int8_t mode; // timer trigger source -> off, abs, stk, stk%, sw/!sw, !m_sw/!m_sw - uint16_t val; -}) TimerData_v212; + uint16_t start:12; + uint16_t countdownBeep:1; + uint16_t minuteBeep:1; + uint16_t persistent:1; + uint16_t spare:1; + uint16_t value; +}) TimerData_v215; PACK(typedef struct { - uint16_t persistent:1; - uint16_t value:15; -}) TimerDataExtra_v212; + TRIMS_ARRAY; + int8_t swtch; // swtch of phase[0] is not used + char name[LEN_FP_NAME]; + uint8_t fadeIn; + uint8_t fadeOut; + ROTARY_ENCODER_ARRAY; + gvar_t gvars[5]; +}) PhaseData_v215; PACK(typedef struct { - FrSkyChannelData channels[2]; - FrSkyRSSIAlarm rssiAlarms[2]; - uint8_t usrProto; // Protocol in FrSky user data, 0=None, 1=FrSky hub, 2=WS HowHigh - uint8_t voltsSource; - uint8_t blades; // How many blades for RPMs, 0=2 blades, 1=3 blades - uint8_t currentSource; - FrSkyBarData bars[4]; - uint8_t lines[4*2*2]; - uint8_t varioSource; - uint8_t varioCenterMin; - uint8_t varioCenterMax; - uint8_t spare[4]; -}) FrSkyData_v212; - -PACK(typedef struct { - char name[LEN_MODEL_NAME]; // must be first for eeLoadModelName - TimerData_v212 timers[MAX_TIMERS]; + ModelHeader header; + TimerData_v215 timers[MAX_TIMERS]; uint8_t protocol:3; uint8_t thrTrim:1; // Enable Throttle Trim int8_t ppmNCH:4; @@ -93,157 +138,364 @@ PACK(typedef struct { uint8_t pulsePol:1; uint8_t extendedLimits:1; uint8_t extendedTrims:1; - uint8_t spare1:1; + uint8_t throttleReversed:1; int8_t ppmDelay; - BeepANACenter beepANACenter; // 1<<0->A1.. 1<<6->A7 - MixData_v212 mixData[MAX_MIXERS]; - LimitData limitData[NUM_CHNOUT]; - ExpoData expoData[MAX_EXPOS]; + BeepANACenter beepANACenter; // 1<<0->A1.. 1<<6->A7 + MixData_v215 mixData[MAX_MIXERS]; + LimitData_v215 limitData[NUM_CHNOUT]; + ExpoData_v215 expoData[32]; - CURVTYPE curves[MAX_CURVES]; + int16_t curves[16]; int8_t points[NUM_POINTS]; CustomSwData customSw[NUM_CSW]; - CustomFnData funcSw[NUM_CFN]; + CustomFnData funcSw[NUM_CFN]; SwashRingData swashR; - PhaseData phaseData[MAX_PHASES]; + PhaseData_v215 phaseData[MAX_PHASES]; int8_t ppmFrameLength; // 0=22.5ms (10ms-30ms) 0.5ms increments uint8_t thrTraceSrc; - uint8_t modelId; - uint8_t switchWarningStates; + swstate_t switchWarningStates; - FrSkyData_v212 frsky; + char gvar_names[5][LEN_GVAR_NAME]; - TimerDataExtra_v212 timersXtra[MAX_TIMERS]; + TELEMETRY_DATA -}) ModelData_v212; + ROTARY_ENCODER_ARRAY_EXTRA + + MODELDATA_EXTRA + +}) ModelData_v215; + +void ConvertGeneralSettings_215_to_216(EEGeneral &settings) +{ + settings.version = 216; +} + +void ConvertModel_215_to_216(ModelData &model) +{ + // Virtual inputs added instead of Expo/DR + // LUA scripts added + // GVARS: now 9 GVARS, popup param added + // Curves: structure changed, 32 curves + // Limits: min and max with PREC1 + // Custom Functions: play repeat * 5 + // Custom Switches: better precision for x when A comes from telemetry + // Main View: altitude in top bar + // Mixes: GVARS in weight moved from 512 to 4096 and -512 to -4096, because GVARS may be used in limits [-1250:1250] + + TRACE("Model conversion from v215 to v216"); + + assert(sizeof(ModelData_v215) <= sizeof(ModelData)); + + ModelData_v215 oldModel; + memcpy(&oldModel, &model, sizeof(oldModel)); + memset(&model, 0, sizeof(ModelData)); + + memcpy(&g_model.header, &oldModel.header, sizeof(g_model.header)); + for (uint8_t i=0; i<2; i++) { + g_model.timers[i].mode = oldModel.timers[i].mode; + g_model.timers[i].start = oldModel.timers[i].start; + g_model.timers[i].minuteBeep = oldModel.timers[i].minuteBeep; + g_model.timers[i].persistent = oldModel.timers[i].persistent; + g_model.timers[i].countdownBeep = oldModel.timers[i].countdownBeep; + g_model.timers[i].value = oldModel.timers[i].value; + } + g_model.protocol = oldModel.protocol; + g_model.thrTrim = oldModel.thrTrim; + g_model.trimInc = oldModel.trimInc; + g_model.disableThrottleWarning = oldModel.disableThrottleWarning; + g_model.extendedLimits = oldModel.extendedLimits; + g_model.extendedTrims = oldModel.extendedTrims; + g_model.throttleReversed = oldModel.throttleReversed; + g_model.beepANACenter = oldModel.beepANACenter; + + for (uint8_t i=0; i<64; i++) { +#if defined(PCBTARANIS) + g_model.mixData[i].destCh = oldModel.mixData[i].destCh; + g_model.mixData[i].phases = oldModel.mixData[i].phases; + g_model.mixData[i].mltpx = oldModel.mixData[i].mltpx; + g_model.mixData[i].weight = oldModel.mixData[i].weight; + g_model.mixData[i].swtch = oldModel.mixData[i].swtch; + if (oldModel.mixData[i].curveMode==0/*differential*/) { + g_model.mixData[i].curve.type = CURVE_REF_DIFF; + g_model.mixData[i].curve.value = oldModel.mixData[i].curveParam; + } + else if (oldModel.mixData[i].curveParam <= 6) { + g_model.mixData[i].curve.type = CURVE_REF_FUNC; + g_model.mixData[i].curve.value = oldModel.mixData[i].curveParam; + } + else { + g_model.mixData[i].curve.type = CURVE_REF_CUSTOM; + g_model.mixData[i].curve.value = oldModel.mixData[i].curveParam - 6; + } + g_model.mixData[i].mixWarn = oldModel.mixData[i].mixWarn; + g_model.mixData[i].delayUp = oldModel.mixData[i].delayUp; + g_model.mixData[i].delayDown = oldModel.mixData[i].delayDown; + g_model.mixData[i].speedUp = oldModel.mixData[i].speedUp; + g_model.mixData[i].speedDown = oldModel.mixData[i].speedDown; + g_model.mixData[i].srcRaw = oldModel.mixData[i].srcRaw; + if (g_model.mixData[i].srcRaw > 4 || oldModel.mixData[i].noExpo) + g_model.mixData[i].srcRaw += MAX_INPUTS + MAX_SCRIPTS*MAX_SCRIPT_OUTPUTS; + g_model.mixData[i].offset = oldModel.mixData[i].offset; + memcpy(g_model.mixData[i].name, oldModel.mixData[i].name, LEN_EXPOMIX_NAME); +#else + memcpy(&g_model.mixData[i], &oldModel.mixData[i], sizeof(g_model.mixData[i])); +#endif + if (g_model.mixData[i].weight <= -508) + g_model.mixData[i].weight = g_model.mixData[i].weight + 512 - 4096; + else if (g_model.mixData[i].weight >= 507) + g_model.mixData[i].weight = g_model.mixData[i].weight - 512 + 4096; + else + g_model.mixData[i].offset = g_model.mixData[i].offset * g_model.mixData[i].weight / 100; + } + for (uint8_t i=0; i<32; i++) { + g_model.limitData[i].min = 10 * oldModel.limitData[i].min; + g_model.limitData[i].max = 10 * oldModel.limitData[i].max; + g_model.limitData[i].ppmCenter = oldModel.limitData[i].ppmCenter; + g_model.limitData[i].offset = oldModel.limitData[i].offset; + g_model.limitData[i].symetrical = oldModel.limitData[i].symetrical; + g_model.limitData[i].revert = oldModel.limitData[i].revert; +#if defined(PCBTARANIS) + memcpy(&g_model.limitData[i].name, &oldModel.limitData[i].name, LEN_CHANNEL_NAME); +#endif + } + int indexes[NUM_STICKS] = { 0, 0, 0, 0 }; + for (uint8_t i=0; i<32; i++) { + if (oldModel.expoData[i].mode) { +#if defined(PCBTARANIS) + uint8_t chn = oldModel.expoData[i].chn; + if (!oldModel.expoData[i].swtch && !oldModel.expoData[i].phases) { + indexes[chn] = -1; + } + else if (indexes[chn] != -1) { + indexes[chn] = i+1; + } + for (uint8_t j=chn+1; j=0; i--) { + int idx = indexes[i]; + if (idx >= 0) { + ExpoData *expo = expoAddress(idx); + memmove(expo+1, expo, (MAX_EXPOS-(idx+1))*sizeof(ExpoData)); + memclear(expo, sizeof(ExpoData)); + expo->srcRaw = MIXSRC_Rud + i; + expo->chn = i; + expo->weight = 100; + expo->curve.type = CURVE_REF_EXPO; + } + for (int c=0; c<4; c++) { + g_model.inputNames[i][c] = char2idx(STR_VSRCRAW[1+STR_VSRCRAW[0]*(i+1)+c]); + } + } +#endif + for (uint8_t i=0; i<16; i++) { +#if defined(PCBTARANIS) + int8_t *cur = &oldModel.points[i==0 ? 0 : 5*i+oldModel.curves[i-1]]; + int8_t *nxt = &oldModel.points[5+5*i+oldModel.curves[i]]; + uint8_t size = nxt - cur; + if ((size & 1) == 0) { + g_model.curves[i].type = CURVE_TYPE_CUSTOM; + g_model.curves[i].points = (size / 2) - 4; + } + else { + g_model.curves[i].points = size-5; + } +#else + g_model.curves[i] = oldModel.curves[i]; +#endif + } + for (uint16_t i=0; i<512; i++) { + g_model.points[i] = oldModel.points[i]; + } + for (uint8_t i=0; i<32; i++) { + g_model.customSw[i] = oldModel.customSw[i]; +#if defined(PCBTARANIS) + CustomSwData * cs = &g_model.customSw[i]; + uint8_t cstate = cswFamily(cs->func); + if (cstate == CS_VOFS || cstate == CS_VCOMP || cstate == CS_VDIFF) { + if (cs->v1 > 0) cs->v1 += MAX_INPUTS + MAX_SCRIPTS*MAX_SCRIPT_OUTPUTS; + if (cs->v1 > MIXSRC_GVAR1+4) cs->v1 += 4; + } + if (cstate == CS_VOFS || cstate == CS_VDIFF) { + if (cs->v1 >= MIXSRC_FIRST_TELEM) { + switch (cs->v1) { + case MIXSRC_FIRST_TELEM + TELEM_TM1-1: + case MIXSRC_FIRST_TELEM + TELEM_TM2-1: + cs->v2 = (cs->v2+128) * 3; + break; + case MIXSRC_FIRST_TELEM + TELEM_ALT-1: + case MIXSRC_FIRST_TELEM + TELEM_GPSALT-1: + case MIXSRC_FIRST_TELEM + TELEM_MIN_ALT-1: + case MIXSRC_FIRST_TELEM + TELEM_MAX_ALT-1: + cs->v2 = (cs->v2+128) * 8 - 500; + break; + case MIXSRC_FIRST_TELEM + TELEM_RPM-1: + case MIXSRC_FIRST_TELEM + TELEM_MAX_RPM-1: + cs->v2 = (cs->v2+128) * 50; + break; + case MIXSRC_FIRST_TELEM + TELEM_T1-1: + case MIXSRC_FIRST_TELEM + TELEM_T2-1: + case MIXSRC_FIRST_TELEM + TELEM_MAX_T1-1: + case MIXSRC_FIRST_TELEM + TELEM_MAX_T2-1: + cs->v2 = (cs->v2+128) + 30; + break; + case MIXSRC_FIRST_TELEM + TELEM_CELL-1: + case MIXSRC_FIRST_TELEM + TELEM_HDG-1: + cs->v2 = (cs->v2+128) * 2; + break; + case MIXSRC_FIRST_TELEM + TELEM_DIST-1: + case MIXSRC_FIRST_TELEM + TELEM_MAX_DIST-1: + cs->v2 = (cs->v2+128) * 8; + break; + case MIXSRC_FIRST_TELEM + TELEM_CURRENT-1: + case MIXSRC_FIRST_TELEM + TELEM_POWER-1: + cs->v2 = (cs->v2+128) * 5; + break; + case MIXSRC_FIRST_TELEM + TELEM_CONSUMPTION-1: + cs->v2 = (cs->v2+128) * 20; + break; + default: + cs->v2 += 128; + break; + } + } + } + if (cstate == CS_VCOMP) { + if (cs->v2 > 0) cs->v2 += MAX_INPUTS + MAX_SCRIPTS*MAX_SCRIPT_OUTPUTS; + if (cs->v2 > MIXSRC_GVAR1+4) cs->v2 += 4; + } +#endif + } + for (uint8_t i=0; i<32; i++) { + g_model.funcSw[i] = oldModel.funcSw[i]; + CustomFnData *sd = &g_model.funcSw[i]; + if (CFN_FUNC(sd) == FUNC_PLAY_VALUE || CFN_FUNC(sd) == FUNC_VOLUME || (CFN_FUNC(sd) >= FUNC_ADJUST_GV1 && CFN_FUNC(sd) <= FUNC_ADJUST_GVLAST && CFN_GVAR_MODE(sd) == FUNC_ADJUST_GVAR_SOURCE)) { +#if defined(PCBTARANIS) + CFN_PARAM(sd) += 1 + MAX_INPUTS + MAX_SCRIPTS*MAX_SCRIPT_OUTPUTS; +#endif + if (CFN_PARAM(sd) > MIXSRC_GVAR1+4) CFN_PARAM(sd) += 4; + } + if (HAS_REPEAT_PARAM(sd)) + CFN_PLAY_REPEAT(sd) *= 5; + } + + g_model.swashR = oldModel.swashR; +#if defined(PCBTARANIS) + if (g_model.swashR.collectiveSource > 0) g_model.swashR.collectiveSource += MAX_INPUTS + MAX_SCRIPTS*MAX_SCRIPT_OUTPUTS; + if (g_model.swashR.collectiveSource > MIXSRC_GVAR1+4) g_model.swashR.collectiveSource += 4; +#endif + + for (uint8_t i=0; i<9; i++) { + memcpy(&g_model.phaseData[i], &oldModel.phaseData[i], sizeof(oldModel.phaseData[i])); // the last 4 gvars will remain blank + } + g_model.thrTraceSrc = oldModel.thrTraceSrc; + g_model.switchWarningStates = oldModel.switchWarningStates; + for (uint8_t i=0; i<5; i++) { + memcpy(g_model.gvars[i].name, oldModel.gvar_names[i], LEN_GVAR_NAME); + } + g_model.frsky = oldModel.frsky; + +#if defined(PCBTARANIS) + g_model.externalModule = oldModel.externalModule; + g_model.trainerMode = oldModel.trainerMode; + memcpy(g_model.curveNames, oldModel.curveNames, sizeof(g_model.curveNames)); +#endif + + memcpy(g_model.moduleData, oldModel.moduleData, sizeof(g_model.moduleData)); +} bool eeConvert() { - return false; + const char *msg = NULL; - if (g_eeGeneral.version == 212) { - g_eeGeneral.optrexDisplay = 0; - g_eeGeneral.backlightBright = 0; - g_eeGeneral.contrast = 25; - ALERT(STR_EEPROMWARN, PSTR("EEprom Data v212"), AU_BAD_EEPROM); + if (g_eeGeneral.version == 215) { + msg = PSTR("EEprom Data v215"); } else { return false; } + int conversionVersionStart = g_eeGeneral.version; + + // Information to the user and wait for key press + g_eeGeneral.optrexDisplay = 0; + g_eeGeneral.backlightMode = e_backlight_mode_on; + g_eeGeneral.backlightBright = 0; + g_eeGeneral.contrast = 25; + ALERT(STR_EEPROMWARN, msg, AU_BAD_EEPROM); + + // Message MESSAGE(STR_EEPROMWARN, PSTR("EEPROM Converting"), NULL, AU_EEPROM_FORMATTING); // TODO translations - if (g_eeGeneral.version == 212) { - memmove(((uint8_t*)&g_eeGeneral)+3, ((uint8_t*)&g_eeGeneral)+1, 81); - g_eeGeneral.variant = 0; - g_eeGeneral.version = 213; + // General Settings conversion +#if defined(PCBTARANIS) + theFile.openRlc(0); + theFile.readRlc((uint8_t*)&g_eeGeneral, sizeof(g_eeGeneral)); +#else + #warning "TODO openRlc for sky9x" +#endif + if (g_eeGeneral.version == 215) ConvertGeneralSettings_215_to_216(g_eeGeneral); + s_eeDirtyMsk = EE_GENERAL; + eeCheck(true); - Eeprom32_source_address = (uint8_t *)&g_eeGeneral ; // Get data from here - Eeprom32_data_size = sizeof(g_eeGeneral) ; // This much - Eeprom32_file_index = 0 ; // This file system entry - Eeprom32_process_state = E32_BLANKCHECK ; - eeWaitFinished(); + lcd_rect(60, 6*FH+4, 132, 3); - for (uint8_t id=0; id= 256) { - ModelData_v212 oldModel; - memset(&oldModel, 0, sizeof(oldModel)); - if (size > sizeof(oldModel)) { - size = sizeof(oldModel) ; - } - read32_eeprom_data((File_system[id+1].block_no << 12) + sizeof(struct t_eeprom_header), (uint8_t *)&oldModel, size); - - memcpy(g_model.header.name, oldModel.name, 10); - for (uint8_t i=0; i<2; i++) { - g_model.timers[i].mode = oldModel.timers[i].mode; - g_model.timers[i].start = oldModel.timers[i].val; - g_model.timers[i].persistent = oldModel.timersXtra[i].persistent; - g_model.timers[i].value = oldModel.timersXtra[i].value; - } - g_model.protocol = oldModel.protocol; - g_model.thrTrim = oldModel.thrTrim; - g_model.moduleData[0].channelsCount = oldModel.ppmNCH*2; - g_model.trimInc = oldModel.trimInc; - g_model.disableThrottleWarning = oldModel.disableThrottleWarning; - g_model.moduleData[0].ppmPulsePol = oldModel.pulsePol; - g_model.extendedLimits = oldModel.extendedLimits; - g_model.extendedTrims = oldModel.extendedTrims; - g_model.moduleData[0].ppmDelay = oldModel.ppmDelay; - g_model.beepANACenter = oldModel.beepANACenter; - for (uint8_t i=0; i<64; i++) { - g_model.mixData[i].destCh = oldModel.mixData[i].destCh; - g_model.mixData[i].phases = oldModel.mixData[i].phases; - g_model.mixData[i].curveMode = oldModel.mixData[i].curveMode; - g_model.mixData[i].noExpo = oldModel.mixData[i].noExpo; - g_model.mixData[i].carryTrim = oldModel.mixData[i].carryTrim; - g_model.mixData[i].mltpx = oldModel.mixData[i].mltpx; - g_model.mixData[i].weight = oldModel.mixData[i].weight; - g_model.mixData[i].swtch = oldModel.mixData[i].swtch; - g_model.mixData[i].curveParam = oldModel.mixData[i].curveParam; - g_model.mixData[i].mixWarn = oldModel.mixData[i].mixWarn; - g_model.mixData[i].delayUp = oldModel.mixData[i].delayUp; - g_model.mixData[i].delayDown = oldModel.mixData[i].delayDown; - g_model.mixData[i].speedUp = oldModel.mixData[i].speedUp; - g_model.mixData[i].speedDown = oldModel.mixData[i].speedDown; - g_model.mixData[i].srcRaw = oldModel.mixData[i].srcRaw; - g_model.mixData[i].offset = oldModel.mixData[i].sOffset; - memcpy(g_model.mixData[i].name, oldModel.mixData[i].name, 6); - } - for (uint8_t i=0; i<32; i++) { - g_model.limitData[i] = oldModel.limitData[i]; - } - for (uint8_t i=0; i<32; i++) { - g_model.expoData[i] = oldModel.expoData[i]; - } - for (uint8_t i=0; i<16; i++) { - g_model.curves[i] = oldModel.curves[i]; - } - for (uint16_t i=0; i<512; i++) { - g_model.points[i] = oldModel.points[i]; - } - for (uint8_t i=0; i<32; i++) { - g_model.customSw[i] = oldModel.customSw[i]; - } - for (uint8_t i=0; i<32; i++) { - g_model.funcSw[i] = oldModel.funcSw[i]; - } - g_model.swashR = oldModel.swashR; - for (uint8_t i=0; i<9; i++) { - g_model.phaseData[i].swtch = oldModel.phaseData[i].swtch; - g_model.phaseData[i].fadeIn = oldModel.phaseData[i].fadeIn; - g_model.phaseData[i].fadeOut = oldModel.phaseData[i].fadeOut; - memcpy(g_model.phaseData[i].name, oldModel.phaseData[i].name, 6); - memcpy(g_model.phaseData[i].trim, oldModel.phaseData[i].trim, 4*sizeof(int16_t)); - memcpy(g_model.phaseData[i].rotaryEncoders, oldModel.phaseData[i].rotaryEncoders, 1*sizeof(int16_t)); - } - g_model.moduleData[0].ppmFrameLength = oldModel.ppmFrameLength; - g_model.thrTraceSrc = oldModel.thrTraceSrc; - g_model.header.modelId = oldModel.modelId; - g_model.switchWarningStates = oldModel.switchWarningStates; - g_model.frsky.usrProto = oldModel.frsky.usrProto; - g_model.frsky.voltsSource = oldModel.frsky.voltsSource; - g_model.frsky.blades = oldModel.frsky.blades; - g_model.frsky.currentSource = oldModel.frsky.currentSource; - g_model.frsky.varioSource = oldModel.frsky.varioSource; - g_model.frsky.varioCenterMax = oldModel.frsky.varioCenterMax; - g_model.frsky.varioCenterMin = oldModel.frsky.varioCenterMin; - for (uint8_t i=0; i<2; i++) { - g_model.frsky.channels[i] = oldModel.frsky.channels[i]; - g_model.frsky.rssiAlarms[i] = oldModel.frsky.rssiAlarms[i]; - } - - Eeprom32_source_address = (uint8_t *)&g_model ; // Get data from here - Eeprom32_data_size = sizeof(g_model) ; // This much - Eeprom32_file_index = g_eeGeneral.currModel + 1 ; // This file system entry - Eeprom32_process_state = E32_BLANKCHECK ; - eeWaitFinished(); + // Models conversion + uint8_t currModel = g_eeGeneral.currModel; + for (uint8_t id=0; id0^^Wy!4%+niL8G3w!xHl+Vc~)+#&MuvBlglo~ z>-k+ltE}%o7AUW8V!7BS#Ygr+Asp9}f7Ew(Ha0%||H${J7SE^E!ZV~K{;mI2mc@Jc eKX;A~FT<|iJhwFrcl!XfFnGH9xvX0) { CHECK_INCDEC_GENVAR(event, g_eeGeneral.stickMode, 0, 3); } @@ -651,7 +651,7 @@ inline bool isFilenameLower(bool isfile, const char * fn, const char * line) void onSdManagerMenu(const char *result) { - char lfn[SD_SCREEN_FILE_LENGTH]; + TCHAR lfn[_MAX_LFN + 1]; uint8_t index = m_posVert-1-s_pgOfs; if (result == STR_SD_INFO) { @@ -661,7 +661,7 @@ void onSdManagerMenu(const char *result) POPUP_CONFIRMATION(PSTR("Confirm Format?")); } else if (result == STR_DELETE_FILE) { - f_getcwd(lfn, SD_SCREEN_FILE_LENGTH); + f_getcwd(lfn, _MAX_LFN); strcat_P(lfn, PSTR("/")); strcat(lfn, reusableBuffer.sdmanager.lines[index]); f_unlink(lfn); @@ -673,13 +673,13 @@ void onSdManagerMenu(const char *result) } #if defined(CPUARM) /* TODO else if (result == STR_LOAD_FILE) { - f_getcwd(lfn, SD_SCREEN_FILE_LENGTH); + f_getcwd(lfn, _MAX_LFN); strcat(lfn, "/"); strcat(lfn, reusableBuffer.sdmanager.lines[index]); POPUP_WARNING(eeLoadModelSD(lfn)); } */ else if (result == STR_PLAY_FILE) { - f_getcwd(lfn, SD_SCREEN_FILE_LENGTH); + f_getcwd(lfn, _MAX_LFN); strcat(lfn, "/"); strcat(lfn, reusableBuffer.sdmanager.lines[index]); audioQueue.playFile(lfn, PLAY_BACKGROUND, 255); @@ -697,21 +697,31 @@ void onSdManagerMenu(const char *result) memcpy(modelHeaders[g_eeGeneral.currModel].bitmap, g_model.header.bitmap, sizeof(g_model.header.bitmap)); eeDirty(EE_MODEL); } +#if defined(LUA) + else if (result == STR_EXECUTE_FILE) { + f_getcwd(lfn, _MAX_LFN); + strcat(lfn, "/"); + strcat(lfn, reusableBuffer.sdmanager.lines[index]); + luaExec(lfn); + } + else if (result == STR_VIEW_TEXT) { + f_getcwd(lfn, _MAX_LFN); + strcat(lfn, "/"); + strcat(lfn, reusableBuffer.sdmanager.lines[index]); + pushMenuTextView(lfn); + } +#endif #endif } -void menuGeneralSdManager(uint8_t event) +void menuGeneralSdManager(uint8_t _event) { FILINFO fno; DIR dir; char *fn; /* This function is assuming non-Unicode cfg. */ -#if _USE_LFN TCHAR lfn[_MAX_LFN + 1]; fno.lfname = lfn; fno.lfsize = sizeof(lfn); -#else - char lfn[SD_SCREEN_FILE_LENGTH]; -#endif #if defined(SDCARD) if (s_warning_result) { @@ -734,12 +744,13 @@ void menuGeneralSdManager(uint8_t event) } #endif + uint8_t event = ((READ_ONLY() && EVT_KEY_MASK(_event) == KEY_ENTER) ? 0 : _event); SIMPLE_MENU(SD_IS_HC() ? STR_SDHC_CARD : STR_SD_CARD, menuTabDiag, e_Sd, 1+reusableBuffer.sdmanager.count); if (s_editMode > 0) s_editMode = 0; - switch(event) { + switch(_event) { case EVT_ENTRY: f_chdir(ROOT_PATH); reusableBuffer.sdmanager.offset = 65535; @@ -747,10 +758,12 @@ void menuGeneralSdManager(uint8_t event) #if defined(PCBTARANIS) case EVT_KEY_LONG(KEY_MENU): - killEvents(event); -// MENU_ADD_ITEM(STR_SD_INFO); TODO: Implement - MENU_ADD_ITEM(STR_SD_FORMAT); - menuHandler = onSdManagerMenu; + if (!READ_ONLY()) { + killEvents(_event); + // MENU_ADD_ITEM(STR_SD_INFO); TODO: Implement + MENU_ADD_ITEM(STR_SD_FORMAT); + menuHandler = onSdManagerMenu; + } break; #endif @@ -772,13 +785,13 @@ void menuGeneralSdManager(uint8_t event) break; } } - if (!IS_ROTARY_BREAK(event) || m_posVert==0) + if (!IS_ROTARY_BREAK(_event) || m_posVert==0) break; // no break; } case EVT_KEY_LONG(KEY_ENTER): - killEvents(event); + killEvents(_event); #if !defined(PCBTARANIS) if (m_posVert == 0) { MENU_ADD_ITEM(STR_SD_INFO); @@ -799,14 +812,24 @@ void menuGeneralSdManager(uint8_t event) MENU_ADD_ITEM(STR_PLAY_FILE); } #if defined(PCBTARANIS) - else if (!strcasecmp(ext, BITMAPS_EXT)) { + else if (!strcasecmp(ext, BITMAPS_EXT) && !READ_ONLY()) { MENU_ADD_ITEM(STR_ASSIGN_BITMAP); } + else if (!strcasecmp(ext, TEXT_EXT)) { + MENU_ADD_ITEM(STR_VIEW_TEXT); + } +#endif +#if defined(LUA) + else if (!strcasecmp(ext, SCRIPTS_EXT)) { + MENU_ADD_ITEM(STR_EXECUTE_FILE); + } #endif #endif - MENU_ADD_ITEM(STR_DELETE_FILE); -// MENU_ADD_ITEM(STR_RENAME_FILE); TODO: Implement -// MENU_ADD_ITEM(STR_COPY_FILE); TODO: Implement + if (!READ_ONLY()) { + MENU_ADD_ITEM(STR_DELETE_FILE); + // MENU_ADD_ITEM(STR_RENAME_FILE); TODO: Implement + // MENU_ADD_ITEM(STR_COPY_FILE); TODO: Implement + } } menuHandler = onSdManagerMenu; break; @@ -915,8 +938,10 @@ void menuGeneralSdManager(uint8_t event) if (!strcasecmp(ext, BITMAPS_EXT)) { if (sdBitmapIdx != m_posVert) { sdBitmapIdx = m_posVert; - if (bmpLoad(sdBitmap, reusableBuffer.sdmanager.lines[index], MODEL_BITMAP_WIDTH, MODEL_BITMAP_HEIGHT)) + uint8_t *dest = sdBitmap; + if (bmpLoad(dest, reusableBuffer.sdmanager.lines[index], MODEL_BITMAP_WIDTH, MODEL_BITMAP_HEIGHT)) { memcpy(sdBitmap, logo_taranis, MODEL_BITMAP_SIZE); + } } lcd_bmp(22*FW+2, 2*FH+FH/2, sdBitmap); } @@ -953,7 +978,7 @@ void menuGeneralTrainer(uint8_t event) uint8_t chan = channel_order(i); volatile TrainerMix *td = &g_eeGeneral.trainer.mix[chan-1]; - putsMixerSource(0, y, chan, (m_posVert==i && m_posHorz<0) ? INVERS : 0); + putsMixerSource(0, y, MIXSRC_Rud-1+chan, (m_posVert==i && m_posHorz<0) ? INVERS : 0); for (uint8_t j=0; j<3; j++) { @@ -1088,7 +1113,7 @@ void menuGeneralDiagAna(uint8_t event) putsStrIdx(x, y, PSTR("A"), i+1); lcd_putc(x+2*FWNUM, y, ':'); lcd_outhex4(x+3*FW-1, y, anaIn(i)); - lcd_outdez8(x+10*FW-1, y, (int16_t)calibratedStick[CONVERT_MODE(i+1)-1]*25/256); + lcd_outdez8(x+10*FW-1, y, (int16_t)calibratedStick[CONVERT_MODE(i)]*25/256); } #if !defined(CPUARM) @@ -1243,7 +1268,9 @@ void menuCommonCalib(uint8_t event) switch (reusableBuffer.calib.state) { case 0: // START CALIBRATION - lcd_putsLeft(3*FH, STR_MENUTOSTART); + if (!READ_ONLY()) { + lcd_putsLeft(3*FH, STR_MENUTOSTART); + } break; case 1: @@ -1296,7 +1323,7 @@ void menuGeneralCalib(uint8_t event) { SIMPLE_MENU(STR_MENUCALIBRATION, menuTabDiag, e_Calib, 1); - menuCommonCalib(event); + menuCommonCalib(READ_ONLY() ? 0 : event); } void menuFirstCalib(uint8_t event) diff --git a/src/gui/menu_model.cpp b/src/gui/menu_model.cpp index 2d4e767db..19baed385 100644 --- a/src/gui/menu_model.cpp +++ b/src/gui/menu_model.cpp @@ -48,7 +48,7 @@ enum EnumTabModel { e_ModelSetup, IF_HELI(e_Heli) IF_FLIGHT_MODES(e_FlightModesAll) - e_ExposAll, + e_InputsAll, e_MixAll, e_Limits, IF_CURVES(e_CurvesAll) @@ -57,6 +57,9 @@ enum EnumTabModel { #endif e_CustomSwitches, e_CustomFunctions, +#if defined(LUA_MODEL_SCRIPTS) + e_CustomScripts, +#endif IF_FRSKY(e_Telemetry) IF_MAVLINK(e_MavSetup) IF_TEMPLATES(e_Templates) @@ -73,6 +76,7 @@ void menuModelCurvesAll(uint8_t event); void menuModelGVars(uint8_t event); void menuModelCustomSwitches(uint8_t event); void menuModelCustomFunctions(uint8_t event); +void menuModelCustomScripts(uint8_t event); void menuModelTelemetry(uint8_t event); void menuModelTemplates(uint8_t event); void menuModelExpoOne(uint8_t event); @@ -91,6 +95,9 @@ const MenuFuncP_PROGMEM menuTabModel[] PROGMEM = { #endif menuModelCustomSwitches, menuModelCustomFunctions, +#if defined(LUA_MODEL_SCRIPTS) + menuModelCustomScripts, +#endif IF_FRSKY(menuModelTelemetry) IF_MAVLINK(menuTelemetryMavlinkSetup) IF_TEMPLATES(menuModelTemplates) @@ -439,7 +446,12 @@ void menuModelSelect(uint8_t event) case EVT_KEY_LONG(KEY_ENTER): case EVT_KEY_BREAK(KEY_ENTER): s_editMode = 0; - if (s_copyMode && (s_copyTgtOfs || s_copySrcRow>=0)) { + if (READ_ONLY()) { + if (g_eeGeneral.currModel != sub && eeModelExists(sub)) { + selectModel(sub); + } + } + else if (s_copyMode && (s_copyTgtOfs || s_copySrcRow>=0)) { displayPopup(s_copyMode==COPY_MODE ? STR_COPYINGMODEL : STR_MOVINGMODEL); eeCheck(true); // force writing of current model data before this is changed @@ -898,6 +910,14 @@ enum menuModelSetupItems { #endif #if defined(PCBTARANIS) && defined(SDCARD) +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 onModelSetupBitmapMenu(const char *result) { if (result == STR_UPDATE_LIST) { @@ -908,10 +928,7 @@ void onModelSetupBitmapMenu(const char *result) } else { // The user choosed a bmp file in the list - if (memcmp(result, "---", 3) == 0) - memset(g_model.header.bitmap, 0, sizeof(g_model.header.bitmap)); - else - memcpy(g_model.header.bitmap, result, sizeof(g_model.header.bitmap)); + copySelection(g_model.header.bitmap, result, sizeof(g_model.header.bitmap)); LOAD_MODEL_BITMAP(); memcpy(modelHeaders[g_eeGeneral.currModel].bitmap, g_model.header.bitmap, sizeof(g_model.header.bitmap)); eeDirty(EE_MODEL); @@ -996,7 +1013,7 @@ void menuModelSetup(uint8_t event) lcd_putsnAtt(MODEL_SETUP_2ND_COLUMN, y, g_model.header.bitmap, sizeof(g_model.header.bitmap), attr); else lcd_putsiAtt(MODEL_SETUP_2ND_COLUMN, y, STR_VCSWFUNC, 0, attr); - if (attr && event==EVT_KEY_BREAK(KEY_ENTER)) { + if (attr && event==EVT_KEY_BREAK(KEY_ENTER) && READ_ONLY_UNLOCKED()) { s_editMode = 0; if (listSdFiles(BITMAPS_PATH, BITMAPS_EXT, sizeof(g_model.header.bitmap), g_model.header.bitmap, LIST_NONE_SD_FILE)) { menuHandler = onModelSetupBitmapMenu; @@ -1021,7 +1038,11 @@ void menuModelSetup(uint8_t event) timer->minuteBeep = onoffMenuItem(timer->minuteBeep, MODEL_SETUP_2ND_COLUMN, y, STR_MINUTEBEEP, attr, event); } else if (k==ITEM_MODEL_TIMER1_COUNTDOWN_BEEP || k==ITEM_MODEL_TIMER2_COUNTDOWN_BEEP) { - timer->countdownBeep = onoffMenuItem(timer->countdownBeep, MODEL_SETUP_2ND_COLUMN, y, STR_BEEPCOUNTDOWN, attr, event); +#if defined(CPUARM) + timer->countdownBeep = selectMenuItem(MODEL_SETUP_2ND_COLUMN, y, STR_BEEPCOUNTDOWN, STR_VBEEPCOUNTDOWN, timer->countdownBeep, 0, 2, attr, event); +#else + timer->countdownBeep = onoffMenuItem(timer->countdownBeep, MODEL_SETUP_2ND_COLUMN, y, STR_BEEPCOUNTDOWN, attr, event); +#endif } else { putsStrIdx(0*FW, y, STR_TIMER, k>=ITEM_MODEL_TIMER2 ? 2 : 1); @@ -1070,7 +1091,7 @@ void menuModelSetup(uint8_t event) g_model.extendedTrims = onoffMenuItem(g_model.extendedTrims, MODEL_SETUP_2ND_COLUMN, y, STR_ETRIMS, attr, event); #else g_model.extendedTrims = onoffMenuItem(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+3*FW, y, STR_RESET, m_posHorz>0 ? attr : 0); + lcd_putsAtt(MODEL_SETUP_2ND_COLUMN+3*FW, y, STR_RESET_BTN, m_posHorz>0 ? attr : 0); if (attr && m_posHorz>0) { s_editMode = 0; if (event==EVT_KEY_LONG(KEY_ENTER)) { @@ -1099,8 +1120,8 @@ void menuModelSetup(uint8_t event) uint8_t idx = g_model.thrTraceSrc + MIXSRC_Thr; if (idx > MIXSRC_Thr) idx += 1; - if (idx >= MIXSRC_Pot1+NUM_POTS) - idx += MIXSRC_CH1 - MIXSRC_Pot1 - NUM_POTS; + if (idx >= MIXSRC_FIRST_POT+NUM_POTS) + idx += MIXSRC_CH1 - MIXSRC_FIRST_POT - NUM_POTS; putsMixerSource(MODEL_SETUP_2ND_COLUMN, y, idx, attr); break; } @@ -1123,9 +1144,11 @@ void menuModelSetup(uint8_t event) s_editMode = 0; switch(event) { case EVT_KEY_LONG(KEY_ENTER): - killEvents(event); - getMovedSwitch(); - g_model.switchWarningStates = 0x01 + (switches_states << 1); + if (!READ_ONLY()) { + killEvents(event); + getMovedSwitch(); + g_model.switchWarningStates = 0x01 + (switches_states << 1); + } // no break CASE_EVT_ROTARY_BREAK case EVT_KEY_BREAK(KEY_ENTER): @@ -1133,8 +1156,10 @@ void menuModelSetup(uint8_t event) case EVT_KEY_BREAK(KEY_LEFT): case EVT_KEY_BREAK(KEY_RIGHT): #endif - g_model.switchWarningStates ^= 0x01; - eeDirty(EE_MODEL); + if (!READ_ONLY()) { + g_model.switchWarningStates ^= 0x01; + eeDirty(EE_MODEL); + } break; } } @@ -1170,10 +1195,12 @@ void menuModelSetup(uint8_t event) for (uint8_t i=0; i= 212 -#define EXPO_ONE_2ND_COLUMN (LCD_W - 88) -#define EXPO_ONE_FP_WIDTH (9*FW) + #define EXPO_ONE_2ND_COLUMN (LCD_W-8*FW-90) + #define EXPO_ONE_FP_WIDTH (9*FW) #else -#define EXPO_ONE_2ND_COLUMN (7*FW+2) -#define EXPO_ONE_FP_WIDTH (5*FW) + #define EXPO_ONE_2ND_COLUMN (7*FW+3*FW+2) + #define EXPO_ONE_FP_WIDTH (5*FW) #endif #if MENU_COLUMNS > 1 @@ -1653,19 +1680,24 @@ FlightModesType editFlightModes(uint8_t x, uint8_t y, uint8_t event, FlightModes uint8_t posHorz = m_posHorz; #if defined(CPUARM) && LCD_W < 212 - bool expoMenu = (x==EXPO_ONE_2ND_COLUMN-2*FW); + bool expoMenu = (x==EXPO_ONE_2ND_COLUMN-5*FW); #endif for (uint8_t p=0; p EXPO_ONE_2ND_COLUMN+2*FW))) + if (expoMenu && ((attr && p < posHorz-4) || (x > EXPO_ONE_2ND_COLUMN-FW))) continue; #endif #if defined(PCBTARANIS) - LcdFlags flags = (attr && (posHorz==p)) ? BLINK|INVERS : ((value & (1<gvars[idx]; if (v > GVAR_MAX) { @@ -1980,8 +2012,9 @@ void menuModelPhaseOne(uint8_t event) uint8_t p = getGVarFlightPhase(s_currIdx, idx); lcd_outdezAtt(21*FW, y, GVAR_VALUE(idx, p), posHorz==2 ? attr : 0); - if (attr && posHorz==2 && ((editMode>0) || p1valdiff)) - GVAR_VALUE(idx, p) = checkIncDec(event, GVAR_VALUE(idx, p), -GVAR_MAX, GVAR_MAX, EE_MODEL); + if (attr && posHorz==2 && ((editMode>0) || p1valdiff)) { + GVAR_VALUE(idx, p) = checkIncDec(event, GVAR_VALUE(idx, p), -GVAR_LIMIT, GVAR_LIMIT, EE_MODEL); + } break; } @@ -2118,7 +2151,12 @@ void menuModelHeli(uint8_t event) break; case ITEM_HELI_COLLECTIVE: +#if defined(PCBTARANIS) + lcd_putsLeft(y, STR_COLLECTIVE); + if (attr) CHECK_INCDEC_MODELSOURCE(event, g_model.swashR.collectiveSource, 0, MIXSRC_LAST_CH); +#else g_model.swashR.collectiveSource = selectMenuItem(HELI_PARAM_OFS, y, STR_COLLECTIVE, NULL, g_model.swashR.collectiveSource, 0, MIXSRC_LAST_CH, attr, event); +#endif putsMixerSource(HELI_PARAM_OFS, y, g_model.swashR.collectiveSource, attr); break; @@ -2150,8 +2188,12 @@ int16_t expoFn(int16_t x) { ExpoData *ed = expoAddress(s_currIdx); int16_t anas[NUM_INPUTS] = {0}; +#if defined(PCBTARANIS) + applyExpos(anas, e_perout_mode_inactive_phase, ed->srcRaw, x); +#else anas[ed->chn] = x; applyExpos(anas, e_perout_mode_inactive_phase); +#endif return anas[ed->chn]; } @@ -2181,7 +2223,7 @@ void DrawFunction(FnFuncP fn, uint8_t offset=0) static uint8_t s_curveChan; int16_t curveFn(int16_t x) { - return intpol(x, s_curveChan); + return applyCustomCurve(x, s_curveChan); } struct point_t { @@ -2192,12 +2234,26 @@ struct point_t { point_t getPoint(uint8_t i) { point_t result = {0, 0}; +#if defined(PCBTARANIS) + 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; +#else CurveInfo crv = curveInfo(s_curveChan); - if (i < crv.points) { - result.x = X0-1-WCHART+i*WCHART/(crv.points/2); - result.y = (LCD_H-1) - (100 + crv.crv[i]) * (LCD_H-1) / 200; - if (crv.custom && i>0 && i0 && i 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 NUM_POINTS-5*MAX_CURVES) { @@ -2241,27 +2317,24 @@ bool moveCurve(uint8_t index, int8_t shift, int8_t custom=0) eeDirty(EE_MODEL); return true; } +#endif #if defined(PCBTARANIS) -const pm_char STR_CURVE_PRESET[] PROGMEM = "Preset..."; -const pm_char STR_PRESET[] PROGMEM = "Preset"; -const pm_char STR_CURVE_MIRROR[] PROGMEM = "Mirror"; -const pm_char STR_CURVE_CLEAR[] PROGMEM = "Clear"; - void displayPresetChoice(uint8_t event) { displayWarning(event); - lcd_outdezAtt(WARNING_LINE_X+FW*sizeof(STR_PRESET), WARNING_LINE_Y, 45*s_warning_input_value/4, LEFT|INVERS); + lcd_outdezAtt(WARNING_LINE_X+FW*7, WARNING_LINE_Y, 45*s_warning_input_value/4, LEFT|INVERS); lcd_putcAtt(lcdLastPos, WARNING_LINE_Y, '@', INVERS); if (s_warning_result) { s_warning_result = 0; - CurveInfo crv = curveInfo(s_curveChan); - for (uint8_t i=0; i0 ? INVERS|BLINK : INVERS) : 0); - lcd_putsLeft(3*FH+3, STR_TYPE); - lcd_outdezAtt(INDENT_WIDTH, 4*FH+3, crv.points, LEFT|attr); - lcd_putsAtt(lcdLastPos, 4*FH+3, crv.custom ? PSTR("pt'") : PSTR("pt"), attr); - if (attr==(INVERS|BLINK)) { - switch(event) { - case EVT_KEY_REPT(KEY_LEFT): - case EVT_KEY_FIRST(KEY_LEFT): - if (crv.custom) { - moveCurve(s_curveChan, -crv.points+2); - } - else if (crv.points > MIN_POINTS) { - moveCurve(s_curveChan, -1, (crv.points+1)/2); - } - else { - AUDIO_WARNING2(); - } - break; - - case EVT_KEY_REPT(KEY_RIGHT): - case EVT_KEY_FIRST(KEY_RIGHT): - if (!crv.custom) { - moveCurve(s_curveChan, crv.points-2, crv.points); - } - else if (crv.points < MAX_POINTS) { - if (moveCurve(s_curveChan, 1)) { - for (int8_t i=crv.points+crv.points-2; i>=0; i--) { - if (i%2) - crv.crv[i] = (crv.crv[i/2] + crv.crv[1+i/2]) / 2; - else - crv.crv[i] = crv.crv[i/2]; - } - } - } - else { - AUDIO_WARNING2(); - } - break; + lcd_putsLeft(3*FH+1, STR_TYPE); + lcd_putsiAtt(INDENT_WIDTH, 4*FH+1, "\010StandardCustom\0", 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; } - crv = curveInfo(s_curveChan); } + attr = (m_posVert==2 ? (s_editMode>0 ? INVERS|BLINK : INVERS) : 0); + lcd_putsLeft(5*FH+1, "Count"); + lcd_outdezAtt(INDENT_WIDTH, 6*FH+1, 5+crv.points, LEFT|attr); + lcd_putsAtt(lcdLastPos, 6*FH+1, PSTR("pts"), attr); + if (attr) { + int8_t count = checkIncDecModel(event, crv.points, -3, 12); // 2pts - 17pts + if (checkIncDec_Ret) { + int8_t 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(7*FH+1, PSTR("Smooth")); + menu_lcd_onoff(7*FW, 7*FH+1, 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; + SET_SCROLLBAR_X(0); break; case EVT_KEY_LONG(KEY_ENTER): if (m_posVert > 1) { killEvents(event); MENU_ADD_ITEM(STR_CURVE_PRESET); - MENU_ADD_ITEM(STR_CURVE_MIRROR); - MENU_ADD_ITEM(STR_CURVE_CLEAR); + MENU_ADD_ITEM(STR_MIRROR); + MENU_ADD_ITEM(STR_CLEAR); menuHandler = onCurveOneMenu; } break; @@ -2366,25 +2444,25 @@ void menuModelCurveOne(uint8_t event) uint8_t posY = FH+1; attr = (s_editMode > 0 ? INVERS|BLINK : INVERS); - for (uint8_t i=0; i0 && m_posVert==1+2*i) + else if (i>0 && m_posVert==3+2*i) selectionMode = 1; } - else if (m_posVert == 2+i) { + else if (m_posVert == 4+i) { selectionMode = 2; } if (i>=pointsOfs && i0 && i0 && i<5+crv.points-1) x = points[5+crv.points+i-1]; lcd_outdezAtt(6+8*FW, posY, i+1, LEFT); lcd_outdezAtt(3+12*FW, posY, x, LEFT|(selectionMode==1?attr:0)); - lcd_outdezAtt(3+16*FW, posY, crv.crv[i], LEFT|(selectionMode==2?attr:0)); + lcd_outdezAtt(3+16*FW, posY, points[i], LEFT|(selectionMode==2?attr:0)); posY += FH; } @@ -2394,9 +2472,9 @@ void menuModelCurveOne(uint8_t event) lcd_filled_rect(point.x-FW, point.y-1, 3, 3, SOLID); if (s_editMode > 0) { if (selectionMode == 1) - CHECK_INCDEC_MODELVAR(event, crv.crv[crv.points+i-1], i==1 ? -99 : crv.crv[crv.points+i-2], i==crv.points-2 ? 99 : crv.crv[crv.points+i]); // edit X + 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, crv.crv[i], -100, 100); + CHECK_INCDEC_MODELVAR(event, points[i], -100, 100); } if (i < pointsOfs) pointsOfs = i; @@ -2523,13 +2601,46 @@ void menuModelCurveOne(uint8_t event) #endif #endif +#if defined(PCBTARANIS) && defined(CURVES) +void editCurveRef(uint8_t x, uint8_t y, CurveRef & curve, uint8_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 = gvarMenuItem(x+5*FW, y, curve.value, -100, 100, m_posHorz==1 ? LEFT|attr : LEFT, event); + break; + case CURVE_REF_FUNC: + lcd_putsiAtt(x+5*FW, 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+5*FW+2, 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; + } +} +#endif + 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 ? expoAddress(i)->mode : mixAddress(i)->srcRaw); + ch = (expo ? EXPO_VALID(expoAddress(i)) : mixAddress(i)->srcRaw); if (ch != 0) { count++; } @@ -2564,7 +2675,8 @@ void deleteExpoMix(uint8_t expo, uint8_t idx) eeDirty(EE_MODEL); } -static int8_t s_currCh; +// TODO avoid this global s_currCh on ARM boards ... +int8_t s_currCh; void insertExpoMix(uint8_t expo, uint8_t idx) { pauseMixerCalculations(); @@ -2572,7 +2684,12 @@ void insertExpoMix(uint8_t expo, uint8_t idx) ExpoData *expo = expoAddress(idx); memmove(expo+1, expo, (MAX_EXPOS-(idx+1))*sizeof(ExpoData)); memclear(expo, sizeof(ExpoData)); +#if defined(PCBTARANIS) + expo->srcRaw = (s_currCh > 4 ? MIXSRC_Rud - 1 + s_currCh : MIXSRC_Rud - 1 + channel_order(s_currCh)); + expo->curve.type = CURVE_REF_EXPO; +#else expo->mode = 3; // pos&neg +#endif expo->chn = s_currCh - 1; expo->weight = 100; } @@ -2581,7 +2698,13 @@ void insertExpoMix(uint8_t expo, uint8_t idx) memmove(mix+1, mix, (MAX_MIXERS-(idx+1))*sizeof(MixData)); memclear(mix, sizeof(MixData)); mix->destCh = s_currCh-1; - mix->srcRaw = (s_currCh > 4 ? s_currCh : channel_order(s_currCh)); +#if defined(PCBTARANIS) + 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)); +#else + mix->srcRaw = (s_currCh > 4 ? MIXSRC_Rud - 1 + s_currCh : MIXSRC_Rud - 1 + channel_order(s_currCh)); +#endif mix->weight = 100; } resumeMixerCalculations(); @@ -2640,7 +2763,7 @@ bool swapExpoMix(uint8_t expo, uint8_t &idx, uint8_t up) } y = (ExpoData *)expoAddress(tgt_idx); - if(((ExpoData *)x)->chn != ((ExpoData *)y)->chn || !((ExpoData *)y)->mode) { + if(((ExpoData *)x)->chn != ((ExpoData *)y)->chn || !EXPO_VALID((ExpoData *)y)) { if (up) { if (((ExpoData *)x)->chn>0) ((ExpoData *)x)->chn--; else return false; @@ -2697,16 +2820,27 @@ bool swapExpoMix(uint8_t expo, uint8_t &idx, uint8_t up) } enum ExposFields { + CASE_PCBTARANIS(EXPO_FIELD_INPUT_NAME) IF_CPUARM(EXPO_FIELD_NAME) + CASE_PCBTARANIS(EXPO_FIELD_SOURCE) + CASE_PCBTARANIS(EXPO_FIELD_SCALE) EXPO_FIELD_WEIGHT, - EXPO_FIELD_EXPO, + CASE_PCBTARANIS(EXPO_FIELD_OFFSET) + CASE_9X(EXPO_FIELD_EXPO) IF_CURVES(EXPO_FIELD_CURVE) IF_FLIGHT_MODES(EXPO_FIELD_FLIGHT_PHASE) EXPO_FIELD_SWITCH, - EXPO_FIELD_SIDE, + CASE_9X(EXPO_FIELD_SIDE) + CASE_PCBTARANIS(EXPO_FIELD_TRIM) EXPO_FIELD_MAX }; +#if defined(PCBTARANIS) + #define CURVE_ROWS 1 +#else + #define CURVE_ROWS 0 +#endif + void menuModelExpoOne(uint8_t event) { #if defined(PCBTARANIS) @@ -2718,42 +2852,92 @@ void menuModelExpoOne(uint8_t event) #endif ExpoData *ed = expoAddress(s_currIdx); - putsMixerSource(7*FW+FW/2, 0, ed->chn+1, 0); +#if defined(PCBTARANIS) + putsMixerSource(7*FW+FW/2, 0, MIXSRC_FIRST_INPUT+ed->chn, 0); +#else + putsMixerSource(7*FW+FW/2, 0, MIXSRC_Rud+ed->chn, 0); +#endif - SUBMENU(STR_MENUDREXPO, EXPO_FIELD_MAX, {IF_CPUARM(0) 0, 0, IF_CURVES(0) IF_FLIGHT_MODES((MAX_PHASES-1) | NAVIGATION_LINE_BY_LINE) 0 /*, ...*/}); + SUBMENU(STR_MENUINPUTS, EXPO_FIELD_MAX, {CASE_PCBTARANIS(0) IF_CPUARM(0) CASE_PCBTARANIS(0) CASE_PCBTARANIS((ed->srcRaw >= MIXSRC_FIRST_TELEM ? (uint8_t)0 : (uint8_t)HIDDEN_ROW)) 0, CASE_PCBTARANIS(0) CASE_9X(0) IF_CURVES(CURVE_ROWS) IF_FLIGHT_MODES((MAX_PHASES-1) | NAVIGATION_LINE_BY_LINE) 0 /*, ...*/}); + + SET_SCROLLBAR_X(EXPO_ONE_2ND_COLUMN+10*FW); int8_t sub = m_posVert; uint8_t y = FH+1; +#if defined(PCBTARANIS) + for (uint8_t k=0; k0 ? BLINK|INVERS : INVERS) : 0); switch(i) { -#if defined(CPUARM) - case EXPO_FIELD_NAME: - editSingleName(EXPO_ONE_2ND_COLUMN+3*FW-sizeof(ed->name)*FW, y, STR_EXPONAME, ed->name, sizeof(ed->name), event, attr); +#if defined(PCBTARANIS) + case EXPO_FIELD_INPUT_NAME: + editSingleName(EXPO_ONE_2ND_COLUMN, y, "Input Name", g_model.inputNames[ed->chn], sizeof(g_model.inputNames[ed->chn]), event, attr); break; #endif + +#if defined(CPUARM) + case EXPO_FIELD_NAME: + editSingleName(EXPO_ONE_2ND_COLUMN-IF_9X(sizeof(ed->name)*FW), y, STR_EXPONAME, ed->name, sizeof(ed->name), event, attr); + break; +#endif + +#if defined(PCBTARANIS) + 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); + putsTelemetryChannel(EXPO_ONE_2ND_COLUMN, y, ed->srcRaw - MIXSRC_FIRST_TELEM, 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, NULL); + break; +#endif + case EXPO_FIELD_WEIGHT: lcd_putsLeft(y, STR_WEIGHT); - ed->weight = gvarMenuItem(EXPO_ONE_2ND_COLUMN+3*FW, y, ed->weight, 0, 100, attr, event); + ed->weight = gvarMenuItem(EXPO_ONE_2ND_COLUMN, y, ed->weight, MIN_EXPO_WEIGHT, 100, IF_PCBTARANIS(LEFT)|attr, event); break; + +#if defined(PCBTARANIS) + case EXPO_FIELD_OFFSET: + lcd_putsLeft(y, NO_INDENT(STR_OFFSET)); + ed->offset = gvarMenuItem(EXPO_ONE_2ND_COLUMN, y, ed->offset, -100, 100, LEFT|attr, event); + break; +#endif + +#if !defined(PCBTARANIS) case EXPO_FIELD_EXPO: lcd_putsLeft(y, STR_EXPO); if (ed->curveMode==MODE_EXPO || ed->curveParam==0) { ed->curveMode = MODE_EXPO; - ed->curveParam = gvarMenuItem(EXPO_ONE_2ND_COLUMN+3*FW, y, ed->curveParam, -100, 100, attr, event); + ed->curveParam = gvarMenuItem(EXPO_ONE_2ND_COLUMN, y, ed->curveParam, -100, 100, attr, event); } else { - lcd_putsAtt(EXPO_ONE_2ND_COLUMN, y, STR_NA, attr); + lcd_putsAtt(EXPO_ONE_2ND_COLUMN-3*FW, y, STR_NA, attr); } break; +#endif + #if defined(CURVES) case EXPO_FIELD_CURVE: lcd_putsLeft(y, STR_CURVE); +#if defined(PCBTARANIS) + editCurveRef(EXPO_ONE_2ND_COLUMN, y, ed->curve, event, attr); +#else if (ed->curveMode!=MODE_EXPO || ed->curveParam==0) { - putsCurve(EXPO_ONE_2ND_COLUMN, y, ed->curveParam, attr); + putsCurve(EXPO_ONE_2ND_COLUMN-3*FW, y, ed->curveParam, attr); if (attr) { CHECK_INCDEC_MODELVAR_ZERO(event, ed->curveParam, CURVE_BASE+MAX_CURVES-1); if (ed->curveParam) ed->curveMode = MODE_CURVE; @@ -2764,38 +2948,71 @@ void menuModelExpoOne(uint8_t event) } } else { - lcd_putsAtt(EXPO_ONE_2ND_COLUMN, y, STR_NA, attr); + lcd_putsAtt(EXPO_ONE_2ND_COLUMN-3*FW, y, STR_NA, attr); } +#endif break; #endif + #if defined(FLIGHT_MODES) case EXPO_FIELD_FLIGHT_PHASE: - ed->phases = editFlightModes(EXPO_ONE_2ND_COLUMN+3*FW-EXPO_ONE_FP_WIDTH, y, event, ed->phases, attr); + ed->phases = editFlightModes(EXPO_ONE_2ND_COLUMN-IF_9X(EXPO_ONE_FP_WIDTH), y, event, ed->phases, attr); break; #endif + case EXPO_FIELD_SWITCH: - ed->swtch = switchMenuItem(EXPO_ONE_2ND_COLUMN, y, ed->swtch, attr, event); + ed->swtch = switchMenuItem(EXPO_ONE_2ND_COLUMN-IF_9X(3*FW), y, ed->swtch, attr, event); break; + +#if !defined(PCBTARANIS) case EXPO_FIELD_SIDE: - ed->mode = 4 - selectMenuItem(EXPO_ONE_2ND_COLUMN, y, STR_SIDE, STR_VSIDE, 4-ed->mode, 1, 3, attr, event); + ed->mode = 4 - selectMenuItem(EXPO_ONE_2ND_COLUMN-3*FW, y, STR_SIDE, STR_VSIDE, 4-ed->mode, 1, 3, attr, event); break; +#endif + +#if defined(PCBTARANIS) + 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; +#endif } - y+=FH; + y += FH; } DrawFunction(expoFn); +#if defined(PCBTARANIS) + int x512 = getValue(ed->srcRaw); + if (ed->srcRaw >= MIXSRC_FIRST_TELEM) { + putsTelemetryChannel(LCD_W-8, 6*FH, ed->srcRaw - MIXSRC_FIRST_TELEM, x512, 0); + if (ed->scale > 0) x512 = (x512 * 1024) / convertTelemValue(ed->srcRaw - MIXSRC_FIRST_TELEM + 1, ed->scale); + x512 = limit(-1024, x512, 1024); + } + else { + lcd_outdezAtt(LCD_W-8, 6*FH, calcRESXto1000(x512), PREC1); + } + int y512 = expoFn(x512); + lcd_outdezAtt(LCD_W-8-6*FW, 1*FH, calcRESXto1000(y512), PREC1); +#else int16_t x512 = calibratedStick[ed->chn]; - int16_t y512 = expoFn(x512); - lcd_outdezAtt(LCD_W-8, 6*FH, calcRESXto100(x512), 0); + int16_t y512 = expoFn(x512); lcd_outdezAtt(LCD_W-8-6*FW, 1*FH, calcRESXto100(y512), 0); +#endif x512 = X0+x512/(RESXu/WCHART); +#if defined(CPUARM) + y512 = (LCD_H-1) - ((y512+RESX)/2) * (LCD_H-1) / RESX; +#else y512 = (LCD_H-1) - (uint16_t)((y512+RESX)/2) * (LCD_H-1) / RESX; +#endif - lcd_vline(x512, y512-3,3*2+1); - lcd_hline(x512-3, y512,3*2+1); + lcd_vline(x512, y512-3, 3*2+1); + lcd_hline(x512-3, y512, 3*2+1); } enum MixFields { @@ -2803,7 +3020,7 @@ enum MixFields { MIX_FIELD_SOURCE, MIX_FIELD_WEIGHT, MIX_FIELD_OFFSET, - MIX_FIELD_TRIM, + CASE_9X(MIX_FIELD_TRIM) IF_CURVES(MIX_FIELD_CURVE) IF_FLIGHT_MODES(MIX_FIELD_FLIGHT_PHASE) MIX_FIELD_SWITCH, @@ -2820,7 +3037,7 @@ void gvarWeightItem(xcoord_t x, uint8_t y, MixData *md, uint8_t attr, uint8_t ev { u_int8int16_t weight; MD_WEIGHT_TO_UNION(md, weight); - weight.word = gvarMenuItem(x, y, weight.word, GV_RANGELARGE_NEG, GV_RANGELARGE, attr, event); + weight.word = gvarMenuItem(x, y, weight.word, -500, 500, attr, event); MD_UNION_TO_WEIGHT(weight, md); } @@ -2844,11 +3061,11 @@ void menuModelMixOne(uint8_t event) #else if (m_posVert == MIX_FIELD_TRIM && md2->srcRaw > NUM_STICKS) #endif - SUBMENU_NOTITLE(MIX_FIELD_COUNT, {IF_CPUARM(0) 0, 0, 0, 0, IF_CURVES(0) IF_FLIGHT_MODES((MAX_PHASES-1) | NAVIGATION_LINE_BY_LINE) 0, 0 /*, ...*/}) + SUBMENU_NOTITLE(MIX_FIELD_COUNT, {IF_CPUARM(0) 0, 0, 0, CASE_9X(0) IF_CURVES(0) IF_FLIGHT_MODES((MAX_PHASES-1) | NAVIGATION_LINE_BY_LINE) 0, 0 /*, ...*/}) else - SUBMENU_NOTITLE(MIX_FIELD_COUNT, {IF_CPUARM(0) 0, 0, 0, 1, IF_CURVES(1) IF_FLIGHT_MODES((MAX_PHASES-1) | NAVIGATION_LINE_BY_LINE) 0, 0 /*, ...*/}); + SUBMENU_NOTITLE(MIX_FIELD_COUNT, {IF_CPUARM(0) 0, 0, 0, CASE_9X(1) IF_CURVES(1) IF_FLIGHT_MODES((MAX_PHASES-1) | NAVIGATION_LINE_BY_LINE) 0, 0 /*, ...*/}); #else - SUBMENU_NOTITLE(MIX_FIELD_COUNT, {IF_CPUARM(0) 0, 0, 0, 1, IF_CURVES(1) IF_FLIGHT_MODES((MAX_PHASES-1) | NAVIGATION_LINE_BY_LINE) 0, 0 /*, ...*/}); + SUBMENU_NOTITLE(MIX_FIELD_COUNT, {IF_CPUARM(0) 0, 0, 0, CASE_9X(1) IF_CURVES(1) IF_FLIGHT_MODES((MAX_PHASES-1) | NAVIGATION_LINE_BY_LINE) 0, 0 /*, ...*/}); #endif #if MENU_COLUMNS > 1 @@ -2902,6 +3119,8 @@ void menuModelMixOne(uint8_t event) MD_UNION_TO_OFFSET(offset, md2); break; } + +#if !defined(PCBTARANIS) case MIX_FIELD_TRIM: { uint8_t not_stick = (md2->srcRaw > NUM_STICKS); @@ -2923,11 +3142,16 @@ void menuModelMixOne(uint8_t event) } break; } +#endif + #if defined(CURVES) case MIX_FIELD_CURVE: { - int8_t curveParam = md2->curveParam; lcd_putsColumnLeft(COLUMN_X, y, STR_CURVE); +#if defined(PCBTARANIS) + editCurveRef(COLUMN_X+MIXES_2ND_COLUMN, y, md2->curve, event, attr); +#else + int8_t curveParam = md2->curveParam; if (md2->curveMode == MODE_CURVE) { putsCurve(COLUMN_X+MIXES_2ND_COLUMN, y, curveParam, attr); if (attr) { @@ -2959,6 +3183,7 @@ void menuModelMixOne(uint8_t event) } } } +#endif break; } #endif @@ -3007,11 +3232,11 @@ static uint8_t s_copySrcCh; #define MIX_LINE_SRC_POS 4*FW-1 #if LCD_W >= 212 - #define EXPO_LINE_WEIGHT_POS 7*FW+1 - #define EXPO_LINE_EXPO_POS 11*FW+5 - #define EXPO_LINE_SWITCH_POS 13*FW+3 - #define EXPO_LINE_SIDE_POS 17*FW+4 - #define EXPO_LINE_SELECT_POS 18 + #define EXPO_LINE_WEIGHT_POS 8*FW+1 + #define EXPO_LINE_SRC_POS 9*FW-2 + #define EXPO_LINE_CURVE_POS 12*FW+4 + #define EXPO_LINE_SWITCH_POS 17*FW-1 + #define EXPO_LINE_SELECT_POS 5*FW+2 #define EXPO_LINE_FM_POS LCD_W-LEN_EXPOMIX_NAME*FW-MENUS_SCROLLBAR_WIDTH-FW-1 #define EXPO_LINE_NAME_POS LCD_W-LEN_EXPOMIX_NAME*FW-MENUS_SCROLLBAR_WIDTH #define MIX_LINE_WEIGHT_POS 11*FW+5 @@ -3139,7 +3364,7 @@ void menuModelExpoMix(uint8_t expo, uint8_t event) } break; case EVT_KEY_BREAK(KEY_ENTER): - if (sub != 0 && (!s_currCh || (s_copyMode && !s_copyTgtOfs))) { + if (sub != 0 && (!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; @@ -3156,35 +3381,43 @@ void menuModelExpoMix(uint8_t expo, uint8_t event) s_copyTgtOfs = 0; } else if (sub != 0) { - if (s_copyMode) s_currCh = 0; + if (READ_ONLY()) { + if (!s_currCh) { + pushMenu(expo ? menuModelExpoOne : menuModelMixOne); + return; + } + } + else { + if (s_copyMode) s_currCh = 0; #if defined(NAVIGATION_MENUS) - if (s_currCh) { - if (reachExpoMixCountLimit(expo)) break; - insertExpoMix(expo, s_currIdx); + if (s_currCh) { + if (reachExpoMixCountLimit(expo)) break; + insertExpoMix(expo, s_currIdx); + pushMenu(expo ? menuModelExpoOne : menuModelMixOne); + s_copyMode = 0; + return; + } + 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; + } +#else + if (s_currCh) { + if (reachExpoMixCountLimit(expo)) break; + insertExpoMix(expo, s_currIdx); + } pushMenu(expo ? menuModelExpoOne : menuModelMixOne); s_copyMode = 0; return; - } - 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; - } -#else - if (s_currCh) { - if (reachExpoMixCountLimit(expo)) break; - insertExpoMix(expo, s_currIdx); - } - pushMenu(expo ? menuModelExpoOne : menuModelMixOne); - s_copyMode = 0; - return; #endif + } } break; case EVT_KEY_LONG(KEY_LEFT): @@ -3235,9 +3468,9 @@ void menuModelExpoMix(uint8_t expo, uint8_t event) break; } - lcd_outdezAtt(FW*max(sizeof(TR_MENUDREXPO), sizeof(TR_MIXER))+FW+FW/2, 0, getExpoMixCount(expo)); - lcd_puts(FW*max(sizeof(TR_MENUDREXPO), sizeof(TR_MIXER))+FW+FW/2, 0, expo ? STR_MAX(MAX_EXPOS) : STR_MAX(MAX_MIXERS)); - SIMPLE_MENU(expo ? STR_MENUDREXPO : STR_MIXER, menuTabModel, expo ? e_ExposAll : e_MixAll, s_maxLines); + lcd_outdezAtt(FW*max(sizeof(TR_MENUINPUTS), sizeof(TR_MIXER))+FW+FW/2, 0, getExpoMixCount(expo)); + lcd_puts(FW*max(sizeof(TR_MENUINPUTS), sizeof(TR_MIXER))+FW+FW/2, 0, expo ? STR_MAX(MAX_EXPOS) : STR_MAX(MAX_MIXERS)); + SIMPLE_MENU(expo ? STR_MENUINPUTS : STR_MIXER, menuTabModel, expo ? e_InputsAll : e_MixAll, s_maxLines); sub = m_posVert; s_currCh = 0; @@ -3247,10 +3480,14 @@ void menuModelExpoMix(uint8_t expo, uint8_t event) for (uint8_t ch=1; ch<=(expo ? NUM_INPUTS : NUM_CHNOUT); ch++) { void *pointer = NULL; MixData * &md = (MixData * &)pointer; ExpoData * &ed = (ExpoData * &)pointer; uint8_t y = 1+(cur-s_pgOfs)*FH; - if (expo ? (ichn+1 == ch && ed->mode) : (isrcRaw && md->destCh+1 == ch)) { + if (expo ? (ichn+1 == ch && EXPO_VALID(ed)) : (isrcRaw && md->destCh+1 == ch)) { if (s_pgOfs < cur && cur-s_pgOfs < LCD_LINES) { if (expo) { +#if defined(PCBTARANIS) putsMixerSource(0, y, ch, 0); +#else + putsMixerSource(0, y, MIXSRC_Rud+ch-1, 0); +#endif } else { putsChn(0, y, ch, 0); // show CHx @@ -3274,16 +3511,26 @@ void menuModelExpoMix(uint8_t expo, uint8_t event) if (s_pgOfs < cur && cur-s_pgOfs < 8) { uint8_t attr = ((s_copyMode || sub != cur) ? 0 : INVERS); if (expo) { - ed->weight = gvarMenuItem(EXPO_LINE_WEIGHT_POS, y, ed->weight, 0, 100, attr | (isExpoActive(i) ? BOLD : 0), event); + ed->weight = gvarMenuItem(EXPO_LINE_WEIGHT_POS, y, ed->weight, MIN_EXPO_WEIGHT, 100, attr | (isExpoActive(i) ? BOLD : 0), event); +#if defined(PCBTARANIS) + putsMixerSource(EXPO_LINE_SRC_POS, y, ed->srcRaw, 0); +#endif + +#if defined(PCBTARANIS) + putsCurveRef(EXPO_LINE_CURVE_POS, y, ed->curve, 0); +#else if (ed->curveMode == MODE_CURVE) putsCurve(EXPO_LINE_EXPO_POS-3*FW, y, ed->curveParam); else displayGVar(EXPO_LINE_EXPO_POS, y, ed->curveParam, -100, 100); +#endif putsSwitches(EXPO_LINE_SWITCH_POS, y, ed->swtch, 0); +#if !defined(PCBTARANIS) if (ed->mode!=3) lcd_putc(EXPO_LINE_SIDE_POS, y, ed->mode == 2 ? 126 : 127); +#endif #if defined(CPUARM) && LCD_W >= 212 displayFlightModes(EXPO_LINE_FM_POS, y, ed->phases); @@ -3320,13 +3567,15 @@ void menuModelExpoMix(uint8_t expo, uint8_t event) #endif #endif { +#if defined(PCBTARANIS) +#else if (md->curveParam) { if (md->curveMode == MODE_CURVE) putsCurve(MIX_LINE_CURVE_POS, y, md->curveParam); else displayGVar(MIX_LINE_CURVE_POS+3*FW, y, md->curveParam, -100, 100); } - +#endif if (md->swtch) putsSwitches(MIX_LINE_SWITCH_POS, y, md->swtch); char cs = ' '; @@ -3349,7 +3598,7 @@ void menuModelExpoMix(uint8_t expo, uint8_t event) } } cur++; y+=FH; mixCnt++; i++; if (expo) ed++; else md++; - } while (expo ? (ichn+1 == ch && ed->mode) : (isrcRaw && md->destCh+1 == ch)); + } while (expo ? (ichn+1 == ch && EXPO_VALID(ed)) : (isrcRaw && md->destCh+1 == ch)); if (s_copyMode == MOVE_MODE && s_pgOfs < cur && cur-s_pgOfs < LCD_LINES && s_copySrcCh == ch && i == (s_copySrcIdx + (s_copyTgtOfs<0))) { lcd_rect(expo ? EXPO_LINE_SELECT_POS : 22, y-1, expo ? LCD_W-EXPO_LINE_SELECT_POS : LCD_W-22, 9, DOTTED); cur++; y+=FH; @@ -3366,7 +3615,11 @@ void menuModelExpoMix(uint8_t expo, uint8_t event) } if (s_pgOfs < cur && cur-s_pgOfs < LCD_LINES) { if (expo) { +#if defined(PCBTARANIS) putsMixerSource(0, y, ch, attr); +#else + putsMixerSource(0, y, MIXSRC_Rud+ch-1, attr); +#endif } else { putsChn(0, y, ch, attr); // show CHx @@ -3415,6 +3668,9 @@ enum LimitsItems { ITEM_LIMITS_MIN, ITEM_LIMITS_MAX, ITEM_LIMITS_DIRECTION, +#if defined(PCBTARANIS) && defined(CURVES) + ITEM_LIMITS_CURVE, +#endif #if defined(PPM_CENTER_ADJUSTABLE) ITEM_LIMITS_PPM_CENTER, #endif @@ -3427,16 +3683,13 @@ enum LimitsItems { #if defined(PCBTARANIS) #define LIMITS_NAME_POS 4*FW - #define LIMITS_OFFSET_POS 14*FW - #define LIMITS_DIRECTION_POS 19*FW+4 - #define LIMITS_MIN_POS 19*FW - #define LIMITS_MAX_POS 23*FW+4 - #define LIMITS_REVERT_POS 26*FW - #ifdef PPM_CENTER_ADJUSTABLE - #define LIMITS_PPM_CENTER_POS 34*FW - #else - #define LIMITS_PPM_CENTER_POS 32*FW - #endif + #define LIMITS_OFFSET_POS 14*FW+4 + #define LIMITS_MIN_POS 20*FW-3 + #define LIMITS_DIRECTION_POS 20*FW-3 + #define LIMITS_MAX_POS 24*FW+2 + #define LIMITS_REVERT_POS 25*FW-1 + #define LIMITS_CURVE_POS 27*FW-1 + #define LIMITS_PPM_CENTER_POS 34*FW #else #if defined(PPM_UNIT_US) #define LIMITS_MIN_POS 12*FW+1 @@ -3467,6 +3720,46 @@ enum LimitsItems { #endif #endif +#if defined(CPUARM) + #define LIMITS_MIN_MAX_OFFSET 1000 + #define CONVERT_US_MIN_MAX(x) (((x)*128)/250) + #define MIN_MAX_LIMIT (10*limit) + #define MIN_MAX_ATTR attr|PREC1 +#else + #define LIMITS_MIN_MAX_OFFSET 100 + #define CONVERT_US_MIN_MAX(x) ((int16_t(x)*128)/25) + #define MIN_MAX_LIMIT (limit) + #define MIN_MAX_ATTR attr +#endif + +#if defined(PPM_UNIT_US) + #define MIN_MAX_DISPLAY(x) CONVERT_US_MIN_MAX(x) + #undef MIN_MAX_ATTR + #define MIN_MAX_ATTR attr +#else + #define MIN_MAX_DISPLAY(x) (x) +#endif + +#if defined(PCBTARANIS) +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_TRIMS_TO_OFFSET) { + copyTrimsToOffset(ch); + } +} +#endif + void menuModelLimits(uint8_t event) { uint8_t sub = m_posVert - 1; @@ -3518,7 +3811,7 @@ void menuModelLimits(uint8_t event) return; } - LimitData *ld = limitAddress(k) ; + LimitData *ld = limitAddress(k); #if LCD_W >= 212 || !defined(PPM_CENTER_ADJUSTABLE) int16_t v = (ld->revert) ? -ld->offset : ld->offset; @@ -3537,6 +3830,12 @@ void menuModelLimits(uint8_t event) #if defined(PCBTARANIS) putsChn(0, y, k+1, (sub==k && m_posHorz < 0) ? INVERS : 0); + if (sub==k && m_posHorz < 0 && event==EVT_KEY_LONG(KEY_ENTER)) { + killEvents(event); + MENU_ADD_ITEM(STR_RESET); + MENU_ADD_ITEM(STR_COPY_TRIMS_TO_OFFSET); + menuHandler = onLimitsMenu; + } #else putsChn(0, y, k+1, 0); #endif @@ -3554,51 +3853,46 @@ void menuModelLimits(uint8_t event) #endif case ITEM_LIMITS_OFFSET: -#if defined(PPM_UNIT_US) - lcd_outdezAtt(LIMITS_OFFSET_POS, y, ((int32_t)ld->offset*128) / 25, attr|PREC1); +#if defined(PCBTARANIS) + ld->offset = gvarMenuItem(LIMITS_OFFSET_POS, y, MIN_MAX_DISPLAY(ld->offset), -1000, 1000, attr|PREC1, event); #else + #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 + #endif if (active) { ld->offset = checkIncDec(event, ld->offset, -1000, 1000, EE_MODEL|NO_INCDEC_MARKS); } else if (attr && event==EVT_KEY_LONG(KEY_MENU)) { - pauseMixerCalculations(); - int32_t zero = (int32_t)channelOutputs[k]; - perOut(e_perout_mode_nosticks+e_perout_mode_notrainer, 0); - int32_t chan = chans[k]; - int8_t lim = ld->max+100; - if (chan < 0) { - chan = -chan; - lim = ld->min-100; - } - zero = (zero*100000 - 10*chan*lim) / (102400 - chan); - ld->offset = (ld->revert) ? -zero : zero; - resumeMixerCalculations(); + copyTrimsToOffset(k); s_editMode = 0; - eeDirty(EE_MODEL); } +#endif break; + case ITEM_LIMITS_MIN: -#if defined(PPM_UNIT_US) - lcd_outdezAtt(LIMITS_MIN_POS, y, (((int16_t)ld->min-100)*128) / 25, attr); +#if defined(CPUARM) + ld->min = LIMITS_MIN_MAX_OFFSET + gvarMenuItem(LIMITS_MIN_POS, y, MIN_MAX_DISPLAY(ld->min-LIMITS_MIN_MAX_OFFSET), -MIN_MAX_LIMIT, 0, MIN_MAX_ATTR, event); #else - lcd_outdezAtt(LIMITS_MIN_POS, y, (int8_t)(ld->min-100), attr); + lcd_outdezAtt(LIMITS_MIN_POS, y, MIN_MAX_DISPLAY(ld->min-LIMITS_MIN_MAX_OFFSET), MIN_MAX_ATTR); + if (active) ld->min = LIMITS_MIN_MAX_OFFSET + checkIncDecModel(event, ld->min-LIMITS_MIN_MAX_OFFSET, -MIN_MAX_LIMIT, 0); #endif - if (active) ld->min = 100 + checkIncDecModel(event, ld->min-100, -limit, 0); break; + case ITEM_LIMITS_MAX: -#if defined(PPM_UNIT_US) - lcd_outdezAtt(LIMITS_MAX_POS, y, (((int16_t)ld->max+100)*128) / 25, attr); +#if defined(CPUARM) + ld->max = -LIMITS_MIN_MAX_OFFSET + gvarMenuItem(LIMITS_MAX_POS, y, MIN_MAX_DISPLAY(ld->max+LIMITS_MIN_MAX_OFFSET), 0, MIN_MAX_LIMIT, MIN_MAX_ATTR, event); #else - lcd_outdezAtt(LIMITS_MAX_POS, y, (int8_t)(ld->max+100), attr); + lcd_outdezAtt(LIMITS_MAX_POS, y, MIN_MAX_DISPLAY(ld->max+LIMITS_MIN_MAX_OFFSET), MIN_MAX_ATTR); + if (active) ld->max = -LIMITS_MIN_MAX_OFFSET + checkIncDecModelZero(event, ld->max+LIMITS_MIN_MAX_OFFSET, +MIN_MAX_LIMIT); #endif - if (active) ld->max = -100 + checkIncDecModelZero(event, ld->max+100, limit); break; + case ITEM_LIMITS_DIRECTION: { uint8_t revert = ld->revert; -#if defined(PPM_CENTER_ADJUSTABLE) && LCD_W < 212 +#if defined(PPM_CENTER_ADJUSTABLE) lcd_putcAtt(LIMITS_REVERT_POS, y, revert ? 127 : 126, attr); #else lcd_putsiAtt(LIMITS_REVERT_POS, y, STR_MMMINV, revert, attr); @@ -3614,14 +3908,30 @@ void menuModelLimits(uint8_t event) } break; } + +#if defined(PCBTARANIS) && 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); +#warning "could be less restrictive!" if (active && ld->max <= 0 && ld->min >= 0) { CHECK_INCDEC_MODELVAR(event, ld->ppmCenter, -125, +125); } break; #endif + #if defined(PPM_LIMITS_SYMETRICAL) case ITEM_LIMITS_SYMETRICAL: lcd_putcAtt(LCD_W-FW-MENUS_SCROLLBAR_WIDTH, y, ld->symetrical ? '=' : '^', attr); @@ -3664,7 +3974,7 @@ void menuModelCurvesAll(uint8_t event) case EVT_KEY_FIRST(KEY_RIGHT): case EVT_KEY_FIRST(KEY_ENTER): #endif - if (CURVE_SELECTED()) { + if (CURVE_SELECTED() && !READ_ONLY()) { s_curveChan = sub; pushMenu(menuModelCurveOne); } @@ -3690,9 +4000,9 @@ void menuModelCurvesAll(uint8_t event) putsStrIdx(0, y, STR_CV, k+1, attr); #if defined(PCBTARANIS) editName(4*FW, y, g_model.curveNames[k], sizeof(g_model.curveNames[k]), 0, 0); - CurveInfo crv = curveInfo(k); - lcd_outdezAtt(11*FW, y, crv.points, LEFT); - lcd_putsAtt(lcdLastPos, y, crv.custom ? PSTR("pt'") : PSTR("pt"), 0); + CurveInfo & crv = g_model.curves[k]; + lcd_outdezAtt(11*FW, y, 5+crv.points, LEFT); + lcd_putsAtt(lcdLastPos, y, PSTR("pts"), 0); #endif } } @@ -3705,6 +4015,27 @@ void menuModelCurvesAll(uint8_t event) #endif #if LCD_W >= 212 && defined(GVARS) && defined(FLIGHT_MODES) + +void onGVARSMenu(const char *result) +{ + int8_t sub = m_posVert - 1; + + 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; i0) ? BLINK|INVERS : INVERS) : 0); - xcoord_t x = 12*FW + FWNUM + (j-1)*(2+3*FWNUM) - 1; + xcoord_t x = 12*FW + FWNUM + (j-1)*(2+3*FWNUM) - 3; #if MAX_GVARS == 6 if (i==0 && j!=9) putsStrIdx(x+2, FH+1, STR_FP, j, SMLSIZE); @@ -3738,7 +4070,7 @@ void menuModelGVars(uint8_t event) switch(j) { case 0: - editName(4*FW-3, y, g_model.gvarsNames[i], sizeof(gvar_name_t), event, attr); + editName(4*FW-3, y, g_model.gvars[i].name, LEN_GVAR_NAME, event, attr); break; default: @@ -3774,6 +4106,33 @@ void menuModelGVars(uint8_t event) } } } + +#if defined(CPUARM) + #define INCDEC_DECLARE_VARS() uint8_t incdecFlag = EE_MODEL; IsValueAvailable isValueAvailable = NULL + #define INCDEC_SET_FLAG(f) incdecFlag = (EE_MODEL|(f)) + #define INCDEC_ENABLE_CHECK(fn) isValueAvailable = fn + #define CHECK_INCDEC_PARAM(event, var, min, max) checkIncDec(event, var, min, max, incdecFlag, isValueAvailable) +#elif defined(CPUM64) + #define INCDEC_DECLARE_VARS() + #define INCDEC_SET_FLAG(f) + #define INCDEC_ENABLE_CHECK(fn) + #define CHECK_INCDEC_PARAM(event, var, min, max) checkIncDec(event, var, min, max, EE_MODEL) +#else + #define INCDEC_DECLARE_VARS() uint8_t incdecFlag = EE_MODEL + #define INCDEC_SET_FLAG(f) incdecFlag = (EE_MODEL|(f)) + #define INCDEC_ENABLE_CHECK(fn) + #define CHECK_INCDEC_PARAM(event, var, min, max) checkIncDec(event, var, min, max, incdecFlag) +#endif + + if (m_posVert > 0 && 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; + } } #endif @@ -4067,7 +4426,7 @@ void menuModelCustomSwitches(uint8_t event) #endif #if defined(PCBTARANIS) - if (sub>=0 && horz<0 && event==EVT_KEY_LONG(KEY_ENTER)) { + if (sub>=0 && horz<0 && event==EVT_KEY_LONG(KEY_ENTER) && !READ_ONLY()) { killEvents(event); CustomSwData * cs = cswAddress(sub); if (cs->func) MENU_ADD_ITEM(STR_COPY); @@ -4137,6 +4496,13 @@ void menuModelCustomSwitches(uint8_t event) if (cs->v1 >= MIXSRC_FIRST_TELEM) { putsTelemetryChannel(CSW_3RD_COLUMN, y, cs->v1 - MIXSRC_FIRST_TELEM, convertCswTelemValue(cs), LEFT|attr2); v2_max = maxTelemValue(cs->v1 - MIXSRC_FIRST_TELEM + 1); +#if defined(CPUARM) + v2_min = minTelemValue(cs->v1 - MIXSRC_FIRST_TELEM + 1); + if (cs->v2 < v2_min || cs->v2 > v2_max) { + cs->v2 = 0; + eeDirty(EE_MODEL); + } +#else if (cstate == CS_VOFS) { v2_min = -128; v2_max -= 128; @@ -4149,6 +4515,7 @@ void menuModelCustomSwitches(uint8_t event) cs->v2 = v2_max; eeDirty(EE_MODEL); } +#endif } else { lcd_outdezAtt(CSW_3RD_COLUMN, y, cs->v2, LEFT|attr2); @@ -4198,6 +4565,18 @@ void menuModelCustomSwitches(uint8_t event) break; case CSW_FIELD_V2: cs->v2 = CHECK_INCDEC_PARAM(event, cs->v2, v2_min, v2_max); +#if defined(PCBTARANIS) + if (cstate==CS_VOFS && cs->v1!=0 && event==EVT_KEY_LONG(KEY_ENTER)) { + killEvents(event); + getvalue_t x = getValue(cs->v1); + TRACE("AUTO x=%d", x); + if (cs->v1 < MIXSRC_GVAR1) + cs->v2 = calcRESXto100(x); + else if (cs->v1 - MIXSRC_FIRST_TELEM + 1 == TELEM_ALT) + cs->v2 *= 100; + eeDirty(EE_MODEL); + } +#endif break; case CSW_FIELD_ANDSW: #if defined(CPUARM) @@ -4224,15 +4603,15 @@ void menuModelCustomSwitches(uint8_t event) #define MODEL_CUSTOM_FUNC_1ST_COLUMN (5+4*FW) #define MODEL_CUSTOM_FUNC_2ND_COLUMN (9*FW) #define MODEL_CUSTOM_FUNC_3RD_COLUMN (21*FW) - #define MODEL_CUSTOM_FUNC_4TH_COLUMN (34*FW-3) - #define MODEL_CUSTOM_FUNC_4TH_COLUMN_ONOFF MODEL_CUSTOM_FUNC_4TH_COLUMN + #define MODEL_CUSTOM_FUNC_4TH_COLUMN (33*FW-3) + #define MODEL_CUSTOM_FUNC_4TH_COLUMN_ONOFF (34*FW-3) #else #define MODEL_CUSTOM_FUNC_1ST_COLUMN (3) #define MODEL_CUSTOM_FUNC_2ND_COLUMN (5*FW-2) #define MODEL_CUSTOM_FUNC_3RD_COLUMN (15*FW+2) #define MODEL_CUSTOM_FUNC_4TH_COLUMN (20*FW) #if defined(GRAPHICS) - #define MODEL_CUSTOM_FUNC_4TH_COLUMN_ONOFF MODEL_CUSTOM_FUNC_4TH_COLUMN + #define MODEL_CUSTOM_FUNC_4TH_COLUMN_ONOFF (20*FW) #else #define MODEL_CUSTOM_FUNC_4TH_COLUMN_ONOFF (18*FW+2) #endif @@ -4273,10 +4652,20 @@ void onCustomFunctionsMenu(const char *result) *cfn = clipboard.data.cfn; eeDirty(EE_MODEL); } - else if (result == STR_DELETE) { + else if (result == STR_CLEAR) { memset(cfn, 0, sizeof(CustomFnData)); eeDirty(EE_MODEL); } + else if (result == STR_INSERT) { + memmove(cfn+1, cfn, (NUM_CFN-sub-1)*sizeof(CustomFnData)); + memset(cfn, 0, sizeof(CustomFnData)); + eeDirty(EE_MODEL); + } + else if (result == STR_DELETE) { + memmove(cfn, cfn+1, (NUM_CFN-sub-1)*sizeof(CustomFnData)); + memset(&g_model.funcSw[NUM_CFN-1], 0, sizeof(CustomFnData)); + eeDirty(EE_MODEL); + } } #endif @@ -4290,13 +4679,19 @@ void menuModelCustomFunctions(uint8_t event) int8_t sub = m_posVert - 1; #if defined(PCBTARANIS) - if (sub>=0 && m_posHorz<0 && event==EVT_KEY_LONG(KEY_ENTER)) { + if (sub>=0 && m_posHorz<0 && event==EVT_KEY_LONG(KEY_ENTER) && !READ_ONLY()) { killEvents(event); CustomFnData *sd = &g_model.funcSw[sub]; - if (sd->swtch && sd->func) MENU_ADD_ITEM(STR_COPY); + if (!CFN_EMPTY(sd)) + MENU_ADD_ITEM(STR_COPY); if (clipboard.type == CLIPBOARD_TYPE_CUSTOM_FUNCTION) MENU_ADD_ITEM(STR_PASTE); - if (sd->swtch || sd->func) MENU_ADD_ITEM(STR_DELETE); + if (!CFN_EMPTY(sd) && CFN_EMPTY(&g_model.funcSw[NUM_CFN-1])) + MENU_ADD_ITEM(STR_INSERT); + if (CFN_EMPTY(sd)) + MENU_ADD_ITEM(STR_DELETE); + else + MENU_ADD_ITEM(STR_CLEAR); menuHandler = onCustomFunctionsMenu; } #endif @@ -4329,7 +4724,7 @@ void menuModelCustomFunctions(uint8_t event) else if (CFN_FUNC(sd) <= FUNC_TRAINER + NUM_STICKS) { func_displayed = 1; if (CFN_FUNC(sd) != FUNC_TRAINER) - putsMixerSource(MODEL_CUSTOM_FUNC_2ND_COLUMN+7*FW, y, CFN_FUNC(sd)-FUNC_TRAINER, attr); + putsMixerSource(MODEL_CUSTOM_FUNC_2ND_COLUMN+7*FW, y, MIXSRC_Rud+CFN_FUNC(sd)-FUNC_TRAINER-1, attr); } #if defined(DEBUG) else if (CFN_FUNC(sd) == FUNC_TEST) { @@ -4417,16 +4812,16 @@ void menuModelCustomFunctions(uint8_t event) break; } else if (CFN_FUNC(sd) == FUNC_PLAY_VALUE) { - val_max = MIXSRC_FIRST_TELEM + TELEM_DISPLAY_MAX - 2; - putsMixerSource(MODEL_CUSTOM_FUNC_3RD_COLUMN, y, val_displayed+1, attr); - INCDEC_ENABLE_CHECK(isSourceP1Available); + val_max = MIXSRC_FIRST_TELEM + TELEM_DISPLAY_MAX - 1; + putsMixerSource(MODEL_CUSTOM_FUNC_3RD_COLUMN, y, val_displayed, attr); + INCDEC_ENABLE_CHECK(isSourceAvailable); } #endif #if defined(CPUARM) else if (CFN_FUNC(sd) == FUNC_VOLUME) { - val_max = MIXSRC_LAST_CH-1; - putsMixerSource(MODEL_CUSTOM_FUNC_3RD_COLUMN, y, val_displayed+1, attr); - INCDEC_ENABLE_CHECK(isSourceP1Available); + val_max = MIXSRC_LAST_CH; + putsMixerSource(MODEL_CUSTOM_FUNC_3RD_COLUMN, y, val_displayed, attr); + INCDEC_ENABLE_CHECK(isSourceAvailable); } #elif defined(VOICE) else if (CFN_FUNC(sd) == FUNC_PLAY_TRACK) { @@ -4453,9 +4848,9 @@ void menuModelCustomFunctions(uint8_t event) lcd_outdezAtt(MODEL_CUSTOM_FUNC_3RD_COLUMN+2+3*FWNUM, y, (val_displayed+PROMPT_CUSTOM_BASE+1)%10, attr|LEFT); } else if (CFN_FUNC(sd) == FUNC_PLAY_VALUE) { - val_max = MIXSRC_FIRST_TELEM + TELEM_DISPLAY_MAX - 2; - putsMixerSource(MODEL_CUSTOM_FUNC_3RD_COLUMN, y, val_displayed+1, attr); - INCDEC_ENABLE_CHECK(isSourceP1Available); + val_max = MIXSRC_FIRST_TELEM + TELEM_DISPLAY_MAX - 1; + putsMixerSource(MODEL_CUSTOM_FUNC_3RD_COLUMN, y, val_displayed, attr); + INCDEC_ENABLE_CHECK(isSourceAvailable); } #endif #if defined(SDCARD) @@ -4491,9 +4886,9 @@ void menuModelCustomFunctions(uint8_t event) lcd_outdezAtt(MODEL_CUSTOM_FUNC_3RD_COLUMN, y, val_displayed, attr|LEFT); break; case FUNC_ADJUST_GVAR_SOURCE: - val_max = MIXSRC_LAST_CH-1; - putsMixerSource(MODEL_CUSTOM_FUNC_3RD_COLUMN, y, val_displayed+1, attr); - INCDEC_ENABLE_CHECK(isSourceP1Available); + val_max = MIXSRC_LAST_CH; + putsMixerSource(MODEL_CUSTOM_FUNC_3RD_COLUMN, y, val_displayed, attr); + INCDEC_ENABLE_CHECK(isSourceAvailable); break; case FUNC_ADJUST_GVAR_GVAR: val_max = MAX_GVARS-1; @@ -4540,19 +4935,34 @@ void menuModelCustomFunctions(uint8_t event) menu_lcd_onoff(MODEL_CUSTOM_FUNC_4TH_COLUMN_ONOFF, y, CFN_ACTIVE(sd), attr); if (active) CHECK_INCDEC_MODELVAR_ZERO(event, CFN_ACTIVE(sd), 1); } - else if (sd->swtch && HAS_REPEAT_PARAM()) { -#if defined(CPUARM) - if (CFN_PLAY_REPEAT(sd)) - lcd_outdezAtt(MODEL_CUSTOM_FUNC_4TH_COLUMN+2+FW, y, CFN_PLAY_REPEAT(sd)*5, attr); - else - lcd_putcAtt(MODEL_CUSTOM_FUNC_4TH_COLUMN+1, y, '-', attr); - if (active) CHECK_INCDEC_MODELVAR_ZERO(event, CFN_PLAY_REPEAT(sd), 12); + else if (sd->swtch && HAS_REPEAT_PARAM(sd)) { + if (CFN_PLAY_REPEAT(sd) == 0) { +#if LCD_W >= 212 + lcd_putsAtt(MODEL_CUSTOM_FUNC_4TH_COLUMN+2, y, "1x", attr); #else - if (CFN_PLAY_REPEAT(sd)) - lcd_outdezAtt(MODEL_CUSTOM_FUNC_4TH_COLUMN+2+FW, y, CFN_PLAY_REPEAT(sd)*10, attr); - else - lcd_putcAtt(MODEL_CUSTOM_FUNC_4TH_COLUMN+1, y, '-', attr); - if (active) CHECK_INCDEC_MODELVAR_ZERO(event, CFN_PLAY_REPEAT(sd), 6); + lcd_putcAtt(MODEL_CUSTOM_FUNC_4TH_COLUMN_ONOFF+1, y, '-', attr); +#endif + } +#if defined(CPUARM) + else if (CFN_PLAY_REPEAT(sd) == CFN_PLAY_REPEAT_NOSTART) { +#if LCD_W >= 212 + lcd_putcAtt(MODEL_CUSTOM_FUNC_4TH_COLUMN-2, y, '!', attr); + lcd_putsAtt(MODEL_CUSTOM_FUNC_4TH_COLUMN+2, y, "1x", attr); +#else + lcd_putcAtt(MODEL_CUSTOM_FUNC_4TH_COLUMN_ONOFF+1, y, '!', attr); +#endif + } +#endif + else { + lcd_outdezAtt(MODEL_CUSTOM_FUNC_4TH_COLUMN+2+FW, y, CFN_PLAY_REPEAT(sd)*CFN_PLAY_REPEAT_MUL, attr); +#if LCD_W >= 212 + lcd_putcAtt(MODEL_CUSTOM_FUNC_4TH_COLUMN+2+FW, y, 's', attr); +#endif + } +#if defined(CPUARM) + if (active) CFN_PLAY_REPEAT(sd) = checkIncDecModel(event, CFN_PLAY_REPEAT(sd)==CFN_PLAY_REPEAT_NOSTART?-1:CFN_PLAY_REPEAT(sd), -1, 60/CFN_PLAY_REPEAT_MUL); +#else + if (active) CHECK_INCDEC_MODELVAR_ZERO(event, CFN_PLAY_REPEAT(sd), 60/CFN_PLAY_REPEAT_MUL); #endif } else if (attr) { @@ -4564,6 +4974,167 @@ void menuModelCustomFunctions(uint8_t event) } } +#if defined(LUA_MODEL_SCRIPTS) +void onModelCustomScriptMenu(const char *result) +{ + ScriptData &sd = g_model.scriptsData[s_currIdx]; + + if (result == STR_UPDATE_LIST) { + if (!listSdFiles(SCRIPTS_PATH, MIXES_EXT, sizeof(sd.file), NULL)) { + POPUP_WARNING(STR_NO_BITMAPS_ON_SD); + s_menu_flags = 0; + } + } + else { + // The user choosed a lua file in the list + copySelection(sd.file, result, sizeof(sd.file)); + memset(sd.inputs, 0, sizeof(sd.inputs)); + eeDirty(EE_MODEL); + LUA_LOAD_MODEL_SCRIPT(s_currIdx); + } +} + +enum menuModelCustomScriptItems { + ITEM_MODEL_CUSTOMSCRIPT_FILE, + ITEM_MODEL_CUSTOMSCRIPT_NAME, + ITEM_MODEL_CUSTOMSCRIPT_PARAMS_LABEL, +}; + +#define SCRIPT_ONE_2ND_COLUMN_POS (12*FW) +#define SCRIPT_ONE_3RD_COLUMN_POS (23*FW) + +void menuModelCustomScriptOne(uint8_t event) +{ + TITLE(STR_MENUCUSTOMSCRIPT); + + ScriptData &sd = g_model.scriptsData[s_currIdx]; + + putsStrIdx(lcdLastPos+FW, 0, "LUA", s_currIdx+1, 0); + + SUBMENU_NOTITLE(3+scriptInternalData[s_currIdx].inputsCount, { 0, 0, LABEL(inputs), 0/*repeated*/ }); + + int8_t sub = m_posVert; + + for (uint8_t k=0; k0 ? BLINK|INVERS : INVERS) : 0); + + if (i == ITEM_MODEL_CUSTOMSCRIPT_FILE) { + lcd_putsLeft(y, "Script"); + if (ZEXIST(sd.file) > 0) + lcd_putsnAtt(SCRIPT_ONE_2ND_COLUMN_POS, y, sd.file, sizeof(sd.file), attr); + else + lcd_putsiAtt(SCRIPT_ONE_2ND_COLUMN_POS, y, STR_VCSWFUNC, 0, attr); + if (attr && event==EVT_KEY_BREAK(KEY_ENTER) && !READ_ONLY()) { + s_editMode = 0; + if (listSdFiles(SCRIPTS_PATH, MIXES_EXT, sizeof(sd.file), sd.file, LIST_NONE_SD_FILE)) { + menuHandler = onModelCustomScriptMenu; + } + else { + POPUP_WARNING(STR_NO_SCRIPTS_ON_SD); + s_menu_flags = 0; + } + } + } + else if (i == ITEM_MODEL_CUSTOMSCRIPT_NAME) { + lcd_putsLeft(y, "Name"); + editName(SCRIPT_ONE_2ND_COLUMN_POS, y, sd.name, sizeof(sd.name), event, attr); + } + else if (i == ITEM_MODEL_CUSTOMSCRIPT_PARAMS_LABEL) { + lcd_putsLeft(y, "Inputs"); + } + else if (i <= ITEM_MODEL_CUSTOMSCRIPT_PARAMS_LABEL+scriptInternalData[s_currIdx].inputsCount) { + int inputIdx = i-ITEM_MODEL_CUSTOMSCRIPT_PARAMS_LABEL-1; + lcd_putsnAtt(INDENT_WIDTH, y, scriptInternalData[s_currIdx].inputs[inputIdx].name, 10, 0); + if (scriptInternalData[s_currIdx].inputs[inputIdx].type == 0) { + lcd_outdezAtt(SCRIPT_ONE_2ND_COLUMN_POS, y, g_model.scriptsData[s_currIdx].inputs[inputIdx]+scriptInternalData[s_currIdx].inputs[inputIdx].def, attr|LEFT); + if (attr) { + CHECK_INCDEC_MODELVAR(event, g_model.scriptsData[s_currIdx].inputs[inputIdx], scriptInternalData[s_currIdx].inputs[inputIdx].min-scriptInternalData[s_currIdx].inputs[inputIdx].def, scriptInternalData[s_currIdx].inputs[inputIdx].max-scriptInternalData[s_currIdx].inputs[inputIdx].def); + } + } + else { + putsMixerSource(SCRIPT_ONE_2ND_COLUMN_POS, y, g_model.scriptsData[s_currIdx].inputs[inputIdx]+scriptInternalData[s_currIdx].inputs[inputIdx].def, attr); + if (attr) { + uint8_t *source = (uint8_t *)&g_model.scriptsData[s_currIdx].inputs[inputIdx]; + CHECK_INCDEC_MODELSOURCE(event, *source, scriptInternalData[s_currIdx].inputs[inputIdx].min-scriptInternalData[s_currIdx].inputs[inputIdx].def, scriptInternalData[s_currIdx].inputs[inputIdx].max-scriptInternalData[s_currIdx].inputs[inputIdx].def); + } + } + } + } + + if (scriptInternalData[s_currIdx].outputsCount > 0) { + lcd_vline(SCRIPT_ONE_3RD_COLUMN_POS-4, FH+1, LCD_H-FH-1); + lcd_puts(SCRIPT_ONE_3RD_COLUMN_POS, FH+1, "Outputs"); + + for (int i=0; i= 0) { + s_currIdx = sub; + pushMenu(menuModelCustomScriptOne); + } + break; + } + + for (int i=0; i9 ? 3 : 2); - lcd_putcAtt(x,0,'/',attr); - lcd_outdezAtt(x,0,index+1,attr); + lcd_putcAtt(x, 0, '/', attr); + lcd_outdezAtt(x, 0, index+1, attr); } #if !defined(CPUM64) @@ -85,6 +85,25 @@ int16_t p1valdiff; int8_t p2valdiff; #endif +uint8_t switchToMix(uint8_t source) +{ +#if defined(PCBTARANIS) + if (source <= 5*3) + return MIXSRC_FIRST_SWITCH + (source-1) / 3; + else if (source <= 17) + return MIXSRC_SF; + else if (source <= 20) + return MIXSRC_SG; + else + return MIXSRC_SH; +#else + if (source <= 3) + return MIXSRC_3POS; + else + return MIXSRC_FIRST_SWITCH - 3 + source; +#endif +} + int8_t checkIncDec_Ret; #if defined(CPUARM) @@ -167,7 +186,7 @@ int16_t checkIncDec(uint8_t event, int16_t val, int16_t i_min, int16_t i_max, ui AUDIO_KEYPAD_DOWN(); } - if (i_min==0 && i_max==1 && (event==EVT_KEY_BREAK(KEY_ENTER) || IS_ROTARY_BREAK(event))) { + if (!READ_ONLY() && i_min==0 && i_max==1 && (event==EVT_KEY_BREAK(KEY_ENTER) || IS_ROTARY_BREAK(event))) { s_editMode = 0; newval = !val; } @@ -214,28 +233,16 @@ int16_t checkIncDec(uint8_t event, int16_t val, int16_t i_min, int16_t i_max, ui #if defined(AUTOSOURCE) if (i_flags & INCDEC_SOURCE) { if (s_editMode>0) { - int8_t source = getMovedSource(); + int8_t source = GET_MOVED_SOURCE(i_min, i_max); if (source) { - newval = MIXSRC_Rud - 1 + source; + newval = source; } #if defined(AUTOSWITCH) - source = abs(getMovedSwitch()); - if (source) { -#if defined(PCBTARANIS) - if (source <= 5*3) - newval = MIXSRC_FIRST_SWITCH + (source-1) / 3; - else if (source <= 17) - newval = MIXSRC_SF; - else if (source <= 20) - newval = MIXSRC_SG; - else - newval = MIXSRC_SH; -#else - if (source <= 3) - newval = MIXSRC_3POS; - else - newval = MIXSRC_FIRST_SWITCH - 3 + source; -#endif + else { + uint8_t swtch = abs(getMovedSwitch()); + if (swtch) { + newval = switchToMix(swtch); + } } #endif } @@ -321,6 +328,35 @@ void title(const pm_char * s) uint8_t scrollbar_X = LCD_W-1; #endif +#if defined(PCBTARANIS) +bool modelHasNotes() +{ + FILINFO info; + TCHAR lfn[_MAX_LFN + 1]; + info.lfname = lfn; + info.lfsize = sizeof(lfn); + + 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 (f_stat(filename, &info) == FR_OK); +} + +void onLongMenuPress(const char *result) +{ + if (result == STR_VIEW_CHANNELS) { + pushMenu(menuChannelsView); + } + else if (result == STR_VIEW_NOTES) { + char filename[sizeof(MODELS_PATH)+1+sizeof(g_model.header.name)+sizeof(TEXT_EXT)] = MODELS_PATH "/"; + char *buf = strcat_modelname(&filename[sizeof(MODELS_PATH)], g_eeGeneral.currModel); + strcpy(buf, TEXT_EXT); + pushMenuTextView(filename); + } +} +#endif + bool check(check_event_t event, uint8_t curr, const MenuFuncP *menuTab, uint8_t menuTabSize, const pm_uint8_t *horTab, uint8_t horTabMax, vertpos_t maxrow) { vertpos_t l_posVert = m_posVert; @@ -366,9 +402,16 @@ bool check(check_event_t event, uint8_t curr, const MenuFuncP *menuTab, uint8_t switch(event) { case EVT_KEY_LONG(KEY_MENU): if (menuTab == menuTabModel) { - pushMenu(menuChannelsView); killEvents(event); - return false; + if (modelHasNotes()) { + MENU_ADD_SD_ITEM(STR_VIEW_CHANNELS); + MENU_ADD_ITEM(STR_VIEW_NOTES); + menuHandler = onLongMenuPress; + } + else { + pushMenu(menuChannelsView); + return false; + } } break; @@ -501,7 +544,7 @@ bool check(check_event_t event, uint8_t curr, const MenuFuncP *menuTab, uint8_t case EVT_ROTARY_BREAK: if (s_editMode > 1) break; - if (m_posHorz < 0 && maxcol > 0) { + if (m_posHorz < 0 && maxcol > 0 && READ_ONLY_UNLOCKED()) { l_posHorz = 0; break; } @@ -518,8 +561,11 @@ bool check(check_event_t event, uint8_t curr, const MenuFuncP *menuTab, uint8_t #if !defined(PCBTARANIS) case EVT_KEY_FIRST(KEY_ENTER): #endif - if (!menuTab || l_posVert>0) - s_editMode = (s_editMode<=0); + if (!menuTab || l_posVert>0) { + if (READ_ONLY_UNLOCKED()) { + s_editMode = (s_editMode<=0); + } + } break; #if defined(ROTARY_ENCODER_NAVIGATION) @@ -757,7 +803,7 @@ bool check(check_event_t event, uint8_t curr, const MenuFuncP *menuTab, uint8_t #if LCD_W >= 212 if (maxrow > LCD_LINES-1 && scrollbar_X) - displayScrollbar(scrollbar_X, FH, LCD_H-FH, s_pgOfs, maxrow, LCD_LINES-1); + displayScrollbar(scrollbar_X, FH, LCD_H-FH, s_pgOfs, menuTab ? maxrow : maxrow+1, LCD_LINES-1); #endif #else @@ -844,7 +890,11 @@ void displayBox() { lcd_filled_rect(10, 16, LCD_W-20, 40, SOLID, ERASE); lcd_rect(10, 16, LCD_W-20, 40); +#if defined(CPUARM) + lcd_putsn(WARNING_LINE_X, WARNING_LINE_Y, s_warning, WARNING_LINE_LEN); +#else lcd_puts(WARNING_LINE_X, WARNING_LINE_Y, s_warning); +#endif // could be a place for a s_warning_info } @@ -891,7 +941,7 @@ void displayWarning(uint8_t event) } } -int8_t selectMenuItem(uint8_t x, uint8_t y, const pm_char *label, const pm_char *values, int8_t value, int8_t min, int8_t max, LcdFlags attr, uint8_t event) +select_menu_value_t selectMenuItem(uint8_t x, uint8_t y, const pm_char *label, const pm_char *values, select_menu_value_t value, select_menu_value_t min, select_menu_value_t max, LcdFlags attr, uint8_t event) { lcd_putsColumnLeft(x, y, label); if (values) lcd_putsiAtt(x, y, values, value-min, attr); @@ -924,7 +974,14 @@ int16_t gvarMenuItem(uint8_t x, uint8_t y, int16_t value, int16_t min, int16_t m bool invers = (attr & INVERS); if (invers && event == EVT_KEY_LONG(KEY_ENTER)) { s_editMode = !s_editMode; +#if defined(CPUARM) + if (attr & PREC1) + value = (GV_IS_GV_VALUE(value, min, max) ? GET_GVAR(value, min, max, s_perout_flight_phase)*10 : delta); + else + value = (GV_IS_GV_VALUE(value, min, max) ? GET_GVAR(value, min, max, s_perout_flight_phase) : delta); +#else value = (GV_IS_GV_VALUE(value, min, max) ? GET_GVAR(value, min, max, s_perout_flight_phase) : delta); +#endif eeDirty(EE_MODEL); } if (GV_IS_GV_VALUE(value, min, max)) { @@ -933,6 +990,10 @@ int16_t gvarMenuItem(uint8_t x, uint8_t y, int16_t value, int16_t min, int16_t m else x -= 2*FW+FWNUM; +#if defined(CPUARM) + attr &= ~PREC1; +#endif + int8_t idx = (int16_t) GV_INDEX_CALC_DELTA(value, delta); if (invers) { CHECK_INCDEC_MODELVAR(event, idx, -MAX_GVARS, MAX_GVARS-1); @@ -1107,6 +1168,22 @@ void drawStatusLine() #if defined(CPUARM) bool isSourceAvailable(int16_t source) { +#if defined(PCBTARANIS) + if (source>=MIXSRC_FIRST_INPUT && source<=MIXSRC_LAST_INPUT) { + return ZEXIST(g_model.inputNames[source-MIXSRC_FIRST_INPUT]); + } +#endif + +#if defined(LUA_MODEL_SCRIPTS) + if (source>=MIXSRC_FIRST_LUA && source<=MIXSRC_LAST_LUA) { + div_t qr = div(source-MIXSRC_FIRST_LUA, MAX_SCRIPT_OUTPUTS); + return (scriptInternalData[qr.quot].state==SCRIPT_OK && qr.rem=MIXSRC_FIRST_LUA && source<=MIXSRC_LAST_LUA) + return false; +#endif + #if !defined(HELI) if (source>=MIXSRC_CYC1 && source<=MIXSRC_CYC3) return false; @@ -1135,8 +1212,41 @@ bool isSourceAvailable(int16_t source) return true; } -bool isSourceP1Available(int16_t source) +bool isInputSourceAvailable(int16_t source) { - return isSourceAvailable(source+1); + if (source>=MIXSRC_Rud && source<=MIXSRC_MAX) + return true; + + if (source>=MIXSRC_TrimRud && source=MIXSRC_FIRST_CH && source<=MIXSRC_LAST_CH) + return true; + + if (source>=MIXSRC_FIRST_TELEM && source<=MIXSRC_LAST_TELEM) + return true; + + return false; +} + +bool isSwitchAvailable(int16_t swtch) +{ + if (swtch < 0) { + if (swtch <= -SWSRC_ON) + return false; +#if defined(PCBTARANIS) + else if (swtch == -SWSRC_SF0 || swtch == -SWSRC_SF2 || swtch == -SWSRC_SH0 || swtch == -SWSRC_SH2) + return false; +#endif + else + swtch = -swtch; + } + + if (swtch>=SWSRC_FIRST_CSW && swtch<=SWSRC_LAST_CSW) { + CustomSwData * cs = cswAddress(swtch-SWSRC_FIRST_CSW); + return (cs->func != CS_OFF); + } + + return true; } #endif diff --git a/src/gui/menus.h b/src/gui/menus.h index 03b53f924..0265076e3 100644 --- a/src/gui/menus.h +++ b/src/gui/menus.h @@ -188,7 +188,12 @@ int8_t checkIncDecGen(uint8_t event, int8_t i_val, int8_t i_min, int8_t i_max); #define CHECK_INCDEC_MODELVAR_ZERO(event, var, max) \ var = checkIncDecModelZero(event,var,max) -#if defined(AUTOSWITCH) +#if defined(CPUARM) + bool isSwitchAvailable(int16_t swtch); + #define AUTOSWITCH_ENTER_LONG() (attr && event==EVT_KEY_LONG(KEY_ENTER)) + #define CHECK_INCDEC_MODELSWITCH(event, var, min, max) \ + var = checkIncDec(event,var,min,max,EE_MODEL|INCDEC_SWITCH|NO_INCDEC_MARKS, isSwitchAvailable) +#elif defined(AUTOSWITCH) #define AUTOSWITCH_ENTER_LONG() (attr && event==EVT_KEY_LONG(KEY_ENTER)) #define CHECK_INCDEC_MODELSWITCH(event, var, min, max) \ var = checkIncDec(event,var,min,max,EE_MODEL|INCDEC_SWITCH) @@ -199,7 +204,7 @@ int8_t checkIncDecGen(uint8_t event, int8_t i_val, int8_t i_min, int8_t i_max); #if defined(CPUARM) bool isSourceAvailable(int16_t source); - bool isSourceP1Available(int16_t source); + bool isInputSourceAvailable(int16_t source); #define CHECK_INCDEC_MODELSOURCE(event, var, min, max) \ var = checkIncDec(event,var,min,max,EE_MODEL|INCDEC_SOURCE|NO_INCDEC_MARKS, isSourceAvailable) #elif defined(AUTOSOURCE) @@ -246,11 +251,11 @@ void title(const pm_char * s); TITLE(title) #define SUBMENU_NOTITLE(lines_count, ...) { \ - static const pm_uint8_t mstate_tab[] PROGMEM = __VA_ARGS__; \ + MENU_TAB(__VA_ARGS__); \ if (!check(event,0,NULL,0,mstate_tab,DIM(mstate_tab)-1,(lines_count)-1)) return; } #define SUBMENU(title, lines_count, ...) \ - static const pm_uint8_t mstate_tab[] PROGMEM = __VA_ARGS__; \ + MENU_TAB(__VA_ARGS__); \ if (!check(event,0,NULL,0,mstate_tab,DIM(mstate_tab)-1,(lines_count)-1)) return; \ TITLE(title) @@ -261,7 +266,13 @@ void title(const pm_char * s); SIMPLE_SUBMENU_NOTITLE(lines_count); \ TITLE(title) -int8_t selectMenuItem(uint8_t x, uint8_t y, const pm_char *label, const pm_char *values, int8_t value, int8_t min, int8_t max, LcdFlags attr, uint8_t event); +#if defined(CPUARM) + typedef int select_menu_value_t; +#else + typedef int8_t select_menu_value_t; +#endif + +select_menu_value_t selectMenuItem(uint8_t x, uint8_t y, const pm_char *label, const pm_char *values, select_menu_value_t value, select_menu_value_t min, select_menu_value_t max, LcdFlags attr, uint8_t event); uint8_t onoffMenuItem(uint8_t value, uint8_t x, uint8_t y, const pm_char *label, LcdFlags attr, uint8_t event ); int8_t switchMenuItem(uint8_t x, uint8_t y, int8_t value, LcdFlags attr, uint8_t event); @@ -287,6 +298,11 @@ extern const pm_char * s_global_warning; #define WARNING_LINE_X 16 #define WARNING_LINE_Y 3*FH +#if LCD_W >= 212 + #define WARNING_LINE_LEN 30 +#else + #define WARNING_LINE_LEN 20 +#endif void displayBox(); void displayPopup(const pm_char * pstr); @@ -339,7 +355,10 @@ void displayWarning(uint8_t event); #define drawStatusLine() #endif +#if defined(PCBTARANIS) void menuChannelsView(uint8_t event); +void pushMenuTextView(const char *filename); +#endif #define LABEL(...) (uint8_t)-1 diff --git a/src/gui/view_main.cpp b/src/gui/view_main.cpp index f1b825ac4..8bf5ea6b7 100644 --- a/src/gui/view_main.cpp +++ b/src/gui/view_main.cpp @@ -114,6 +114,7 @@ #define ICON_TRAINEE 71, 11 #define ICON_USB 81, 11 #define ICON_REBOOT 91, 11 + #define ICON_ALTITUDE 102, 9 #endif void drawPotsBars() @@ -135,15 +136,15 @@ void drawStick(uint8_t centrex, int16_t xval, int16_t yval) void doMainScreenGraphics() { - int16_t calibStickVert = calibratedStick[CONVERT_MODE(1+1)-1]; - if (g_model.throttleReversed && CONVERT_MODE(1+1)-1 == THR_STICK) + 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+1)-1], calibStickVert); + drawStick(LBOX_CENTERX, calibratedStick[CONVERT_MODE(0)], calibStickVert); - calibStickVert = calibratedStick[CONVERT_MODE(2+1)-1]; - if (g_model.throttleReversed && CONVERT_MODE(2+1)-1 == THR_STICK) + calibStickVert = calibratedStick[CONVERT_MODE(2)]; + if (g_model.throttleReversed && CONVERT_MODE(2) == THR_STICK) calibStickVert = -calibStickVert; - drawStick(RBOX_CENTERX, calibratedStick[CONVERT_MODE(3+1)-1], calibStickVert); + drawStick(RBOX_CENTERX, calibratedStick[CONVERT_MODE(3)], calibStickVert); #if !defined(PCBTARANIS) drawPotsBars(); @@ -156,7 +157,7 @@ void displayTrims(uint8_t phase) static xcoord_t x[4] = {TRIM_LH_X, TRIM_LV_X, TRIM_RV_X, TRIM_RH_X}; static uint8_t vert[4] = {0,1,1,0}; uint8_t xm, ym; - xm = x[CONVERT_MODE(i+1)-1]; + xm = x[CONVERT_MODE(i)]; uint8_t att = ROUND; int16_t val = getTrimValue(phase, i); @@ -210,9 +211,6 @@ void displaySliders() #define BAR_Y 1 #define BAR_W 184 #define BAR_H 9 -#define BAR_BATT_X BAR_X+18 -#define BAR_RSSI_X BAR_X+42 -#define BAR_A1_X BAR_X+69 #define BAR_NOTIFS_X BAR_X+133 #define BAR_VOLUME_X BAR_X+147 #define BAR_TIME_X BAR_X+168 @@ -232,15 +230,19 @@ void displayTopBarGauge(xcoord_t x, int count, bool blinking=false) void displayTopBar() { + uint8_t batt_icon_x; + uint8_t altitude_icon_x; + /* Tx voltage */ - putsVBat(BAR_BATT_X, BAR_Y+1, 0); - lcd_rect(BAR_BATT_X+FW, BAR_Y+1, 13, 7); - lcd_vline(BAR_BATT_X+FW+13, BAR_Y+2, 5); + putsVBat(BAR_X+2, BAR_Y+1, LEFT); + batt_icon_x = lcdLastPos; + lcd_rect(batt_icon_x+FW, BAR_Y+1, 13, 7); + lcd_vline(batt_icon_x+FW+13, BAR_Y+2, 5); if (frskyData.rssi[0].value > 0) { /* RSSI */ - LCD_ICON(BAR_RSSI_X, BAR_Y, ICON_RSSI); - lcd_rect(BAR_RSSI_X+10, BAR_Y+1, 13, 7); + LCD_ICON(batt_icon_x+3*FW+3, BAR_Y, ICON_RSSI); + lcd_rect(batt_icon_x+5*FW, BAR_Y+1, 13, 7); /* Rx voltage */ lcdint_t voltage = 0; @@ -258,7 +260,17 @@ void displayTopBar() voltage = frskyData.hub.cellsSum; } if (voltage > 0) { - putsTelemetryChannel(BAR_A1_X, BAR_Y+1, channel, voltage, LEFT); + putsTelemetryChannel(batt_icon_x+7*FW+2, BAR_Y+1, channel, voltage, LEFT); + altitude_icon_x = lcdLastPos+1; + } + else { + altitude_icon_x = batt_icon_x+7*FW+3; + } + + /* Altitude */ + if (g_model.frsky.altitudeDisplayed && frskyData.hub.baroAltitudeOffset) { + LCD_ICON(altitude_icon_x, BAR_Y, ICON_ALTITUDE); + putsTelemetryValue(altitude_icon_x+2*FW-1, BAR_Y+1, TELEMETRY_ALT_BP, UNIT_METERS, LEFT); } } @@ -288,9 +300,10 @@ void displayTopBar() x -= 12; } + /* SD ICON, not really needed if (sdMounted()) { LCD_NOTIF_ICON(x, ICON_SD); - } + } */ /* Audio volume */ if (requiredSpeakerVolume == 0) @@ -314,11 +327,11 @@ void displayTopBar() /* The inside of the Batt gauge */ int count = 10 * (g_vbat100mV - g_eeGeneral.vBatMin - 90) / (30 + g_eeGeneral.vBatMax - g_eeGeneral.vBatMin); - displayTopBarGauge(BAR_BATT_X+FW, count, g_vbat100mV <= g_eeGeneral.vBatWarn); + displayTopBarGauge(batt_icon_x+FW, count, g_vbat100mV <= g_eeGeneral.vBatWarn); /* The inside of the RSSI gauge */ if (frskyData.rssi[0].value > 0) { - displayTopBarGauge(BAR_RSSI_X+10, frskyData.rssi[0].value / 10, frskyData.rssi[0].value < getRssiAlarmValue(0)); + displayTopBarGauge(batt_icon_x+5*FW, frskyData.rssi[0].value / 10, frskyData.rssi[0].value < getRssiAlarmValue(0)); } } #endif @@ -358,7 +371,7 @@ void displayTimers() // Main timer if (g_model.timers[0].mode) { TimerState & timerState = timersStates[0]; - uint8_t att = DBLSIZE | (timerState.state==TMR_BEEPING ? BLINK|INVERS : 0); + uint8_t att = DBLSIZE | (timerState.val<0 ? BLINK|INVERS : 0); putsTime(12*FW+2+10*FWNUM-4, FH*2, timerState.val, att, att); putsTmrMode(timerState.val >= 0 ? 9*FW-FW/2+3 : 9*FW-FW/2-4, FH*3, g_model.timers[0].mode, STRCONDENSED); } @@ -525,7 +538,7 @@ void menuMainView(uint8_t event) break; #endif -#if !defined(READONLY) +#if MENUS_LOCK != 2/*no menus*/ #if !defined(PCBTARANIS) case EVT_KEY_LONG(KEY_MENU):// go to last menu pushMenu(lastPopMenu()); @@ -594,12 +607,14 @@ void menuMainView(uint8_t event) return; case EVT_KEY_FIRST(KEY_EXIT): - if (timersStates[0].state==TMR_BEEPING) { - timersStates[0].state = TMR_STOPPED; - } - else if (s_global_warning) { + if (s_global_warning) { s_global_warning = NULL; } +#if defined(GVARS) && !defined(PCBSTD) + else if (s_gvar_timer > 0) { + s_gvar_timer = 0; + } +#endif #if !defined(PCBTARANIS) else if (view == VIEW_TIMER2) { resetTimer(1); @@ -652,18 +667,18 @@ void menuMainView(uint8_t event) // TODO simplify this + reuse code in checkSwitches() + Menu MODELSETUP switch(i) { case 5: - sw = getValue(MIXSRC_SF-1) > 0 ? 3*i+2 : 3*i+1; + sw = getValue(MIXSRC_SF) > 0 ? 3*i+2 : 3*i+1; break; case 6: - val = getValue(MIXSRC_SG-1); + val = getValue(MIXSRC_SG); sw = ((val < 0) ? 3*i : ((val == 0) ? 3*i+1 : 3*i+2)); break; case 7: - sw = getValue(MIXSRC_SH-1) > 0 ? 3*i+1 : 3*i; + sw = getValue(MIXSRC_SH) > 0 ? 3*i+1 : 3*i; break; default: { - val = getValue(MIXSRC_SA+i-1); + val = getValue(MIXSRC_SA+i); sw = ((val < 0) ? 3*i+1 : ((val == 0) ? 3*i+2 : 3*i+3)); break; } @@ -822,6 +837,27 @@ void menuMainView(uint8_t event) s_warning = NULL; } +#if defined(GVARS) && !defined(PCBSTD) + else if (s_gvar_timer > 0) { + s_gvar_timer--; +#if LCD_W >= 212 + lcd_filled_rect(BITMAP_X, BITMAP_Y, 64, 32, SOLID, ERASE); + lcd_rect(BITMAP_X, BITMAP_Y, 64, 32); + putsStrIdx(BITMAP_X+FW, BITMAP_Y+FH-1, STR_GV, s_gvar_last+1); + lcd_putsnAtt(BITMAP_X+4*FW+FW/2, BITMAP_Y+FH-1, g_model.gvars[s_gvar_last].name, LEN_GVAR_NAME, ZCHAR); + lcd_putsAtt(BITMAP_X+FW, BITMAP_Y+2*FH+3, PSTR("[\010]"), BOLD); + lcd_outdezAtt(BITMAP_X+5*FW+FW/2, BITMAP_Y+2*FH+3, GVAR_VALUE(s_gvar_last, s_perout_flight_phase), BOLD); +#else + s_warning = STR_GLOBAL_VAR; + displayBox(); + lcd_putsnAtt(16, 5*FH, g_model.gvars[s_gvar_last].name, LEN_GVAR_NAME, ZCHAR); + lcd_putsAtt(16+7*FW, 5*FH, PSTR("[\010]"), BOLD); + lcd_outdezAtt(16+7*FW+4*FW+FW/2, 5*FH, GVAR_VALUE(s_gvar_last, s_perout_flight_phase), BOLD); + s_warning = NULL; +#endif + } +#endif + #if defined(DSM2) if (dsm2Flag == DSM2_BIND_FLAG) // Issue 98 lcd_putsAtt(15*FW, 0, PSTR("BIND"), 0); diff --git a/src/gui/view_statistics.cpp b/src/gui/view_statistics.cpp index 5d13bdc56..be02ac464 100644 --- a/src/gui/view_statistics.cpp +++ b/src/gui/view_statistics.cpp @@ -84,9 +84,9 @@ void menuStatisticsView(uint8_t event) } #if defined(CPUARM) -#define MENU_DEBUG_COL_OFS (13*FW) + #define MENU_DEBUG_COL_OFS (11*FW-2) #else -#define MENU_DEBUG_COL_OFS (14*FW) + #define MENU_DEBUG_COL_OFS (14*FW) #endif void menuStatisticsDebug(uint8_t event) @@ -167,18 +167,22 @@ void menuStatisticsDebug(uint8_t event) putsTelemetryValue(MENU_DEBUG_COL_OFS, 4*FH, Coproc_temp, UNIT_DEGREES, 0); putsTelemetryValue(20*FW+2, 4*FH, Coproc_maxtemp, UNIT_DEGREES, 0); } +#elif defined(PCBTARANIS) && !defined(SIMU) + lcd_putsLeft(4*FH, "Free Mem"); + lcd_outdezAtt(MENU_DEBUG_COL_OFS, 4*FH, 0x20020000 - (unsigned int)heap, LEFT); #endif #if defined(CPUARM) lcd_putsLeft(5*FH, STR_TMIXMAXMS); - lcd_outdezAtt(MENU_DEBUG_COL_OFS, 5*FH, (maxMixerDuration)/20, PREC2); - + lcd_outdezAtt(MENU_DEBUG_COL_OFS, 5*FH, (maxMixerDuration)/20, PREC2|LEFT); + lcd_puts(lcdLastPos, 5*FH, "ms"); lcd_putsLeft(6*FH, STR_FREESTACKMINB); - lcd_outdezAtt(13*FW, 6*FH, stack_free(0), UNSIGN); - lcd_putc(13*FW, 6*FH, '/'); - lcd_outdezAtt(13*FW+FWNUM, 6*FH, stack_free(1), UNSIGN|LEFT); - lcd_putc(lcdLastPos, 6*FH, '/'); - lcd_outdezAtt(lcdLastPos+FWNUM, 6*FH, stack_free(2), UNSIGN|LEFT); + lcd_putsAtt(MENU_DEBUG_COL_OFS-1, 6*FH+1, "[Main]", SMLSIZE); + lcd_outdezAtt(lcdLastPos, 6*FH, stack_free(0), UNSIGN|LEFT); + lcd_putsAtt(lcdLastPos+2, 6*FH+1, "[Mix]", SMLSIZE); + lcd_outdezAtt(lcdLastPos, 6*FH, stack_free(1), UNSIGN|LEFT); + lcd_putsAtt(lcdLastPos+2, 6*FH+1, "[Audio]", SMLSIZE); + lcd_outdezAtt(lcdLastPos, 6*FH, stack_free(2), UNSIGN|LEFT); #else lcd_putsLeft(1*FH, STR_TMR1LATMAXUS); lcd_outdez8(MENU_DEBUG_COL_OFS , 1*FH, g_tmr1Latency_max/2 ); diff --git a/src/gui/view_telemetry.cpp b/src/gui/view_telemetry.cpp index 2adf3eb0a..ff06cd142 100644 --- a/src/gui/view_telemetry.cpp +++ b/src/gui/view_telemetry.cpp @@ -113,7 +113,7 @@ void displayGpsCoord(uint8_t y, char direction, int16_t bp, int16_t ap) if (!direction) direction = '-'; lcd_outdezAtt(TELEM_2ND_COLUMN, y, bp / 100, LEFT); // ddd before '.' lcd_putc(lcdLastPos, y, '@'); - uint8_t mn = bp % 100; + uint8_t mn = bp % 100; // TODO div_t if (g_eeGeneral.gpsFormat == 0) { lcd_putc(lcdLastPos+FWNUM, y, direction); lcd_outdezNAtt(lcdLastPos+FW+FW+1, y, mn, LEFT|LEADING0, 2); // mm before '.' @@ -220,7 +220,7 @@ void menuTelemetryFrsky(uint8_t event) uint8_t y = barHeight+6+i*(barHeight+6); lcd_putsiAtt(0, y+barHeight-5, STR_VTELEMCHNS, source, 0); lcd_rect(25, y, BAR_WIDTH+1, barHeight+2); - getvalue_t value = getValue(MIXSRC_FIRST_TELEM+source-2); + getvalue_t value = getValue(MIXSRC_FIRST_TELEM+source-1); #if LCD_W >= 212 putsTelemetryChannel(27+BAR_WIDTH, y+barHeight-6, source-1, value, LEFT); #endif @@ -305,7 +305,7 @@ void menuTelemetryFrsky(uint8_t event) } if (field) { fields_count++; - getvalue_t value = getValue(MIXSRC_FIRST_TELEM+field-2); + getvalue_t value = getValue(MIXSRC_FIRST_TELEM+field-1); uint8_t att = (i==3 ? NO_UNIT : DBLSIZE|NO_UNIT); #if LCD_W >= 212 xcoord_t pos[] = {0, 71, 143, 214}; diff --git a/src/gui/view_text.cpp b/src/gui/view_text.cpp new file mode 100644 index 000000000..66d500c78 --- /dev/null +++ b/src/gui/view_text.cpp @@ -0,0 +1,153 @@ +/* + * Authors (alphabetical order) + * - Andre Bernet + * - Andreas Weitl + * - Bertrand Songis + * - Bryan J. Rentoul (Gruvin) + * - Cameron Weeks + * - Erez Raviv + * - Gabriel Birkus + * - Jean-Pierre Parisy + * - Karl Szmutny + * - Michael Blandford + * - Michal Hlavinka + * - Pat Mackenzie + * - Philip Moss + * - Rob Thomson + * - Romolo Manfredini + * - Thomas Husterer + * + * opentx is based on code named + * gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/, + * er9x by Erez Raviv: http://code.google.com/p/er9x/, + * and the original (and ongoing) project by + * Thomas Husterer, th9x: http://code.google.com/p/th9x/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include "../opentx.h" + +#define TEXT_FILENAME_MAXLEN 40 +#define TEXT_FILE_MAXSIZE 1000 + +char s_text_file[TEXT_FILENAME_MAXLEN]; +char s_text_screen[LCD_LINES-1][LCD_COLS+1]; + +void readTextFile(int & lines_count) +{ + FIL file; + int result; + char c; + unsigned int sz; + int line_length = 0; + int escape = 0; + char escape_chars[2]; + int current_line = 0; + + memset(s_text_screen, 0, sizeof(s_text_screen)); + + result = f_open(&file, s_text_file, FA_OPEN_EXISTING | FA_READ); + if (result == FR_OK) { + for (int i=0; i=s_pgOfs && current_line-s_pgOfs0 && escape<3) { + escape_chars[escape-1] = c; + if (escape == 2 && !strncmp(escape_chars, "up", 2)) { + c = '\300'; + } + else if (escape == 2 && !strncmp(escape_chars, "dn", 2)) { + c = '\301'; + } + else { + escape++; + continue; + } + } + escape = 0; + s_text_screen[current_line-s_pgOfs][line_length++] = c; + } + } + f_close(&file); + } + + if (lines_count == 0) { + lines_count = current_line; + } +} + +void menuTextView(uint8_t event) +{ + static int lines_count; + + switch (event) { + case EVT_ENTRY: + s_pgOfs = 0; + lines_count = 0; + readTextFile(lines_count); + break; + + case EVT_KEY_BREAK(KEY_UP): + if (s_pgOfs == 0) + break; + else + s_pgOfs--; + // no break; + + case EVT_KEY_BREAK(KEY_DOWN): + if (event == EVT_KEY_BREAK(KEY_DOWN)) { + if (s_pgOfs+LCD_LINES-1 >= lines_count) + break; + else + ++s_pgOfs; + } + readTextFile(lines_count); + break; + + case EVT_KEY_BREAK(KEY_EXIT): + popMenu(); + return; + } + + for (int i=0; i LCD_LINES-1) { + displayScrollbar(LCD_W-1, FH, LCD_H-FH, s_pgOfs, lines_count, LCD_LINES-1); + } +} + +void pushMenuTextView(const char *filename) +{ + if (strlen(filename) < TEXT_FILENAME_MAXLEN) { + strcpy(s_text_file, filename); + pushMenu(menuTextView); + } +} diff --git a/src/lcd.cpp b/src/lcd.cpp index c74f4cb44..b8702878d 100644 --- a/src/lcd.cpp +++ b/src/lcd.cpp @@ -40,6 +40,10 @@ uint8_t displayBuf[DISPLAY_BUF_SIZE]; #define DISPLAY_END (displayBuf+DISPLAY_PLAN_SIZE) #define ASSERT_IN_DISPLAY(p) assert((p) >= displayBuf && (p) < DISPLAY_END) +#if defined(LUA) +bool lcd_locked = false; +#endif + void lcd_clear() { memset(displayBuf, 0, sizeof(displayBuf)); @@ -251,6 +255,17 @@ void lcd_putcAtt(xcoord_t x, uint8_t y, const unsigned char c, LcdFlags flags) LCD_BYTE_FILTER(p+1, b << ym8, 0); else LCD_BYTE_FILTER(p+1, 0xff, b << ym8); +#if defined(CPUARM) + if (ym8) { + uint8_t *r = p+1 + LCD_W; + if (r> (8-ym8), 0); + else + LCD_BYTE_FILTER(r, 0xff, b >> (8-ym8)); + } + } +#endif } #endif } @@ -458,8 +473,9 @@ void lcd_outdezNAtt(xcoord_t x, uint8_t y, lcdint_t val, LcdFlags flags, uint8_t else { x--; lcd_plot(x, y+6); - if ((flags&INVERS) && ((~flags & BLINK) || BLINK_ON_PHASE)) + if ((flags&INVERS) && ((~flags & BLINK) || BLINK_ON_PHASE)) { lcd_vline(x, y, 8); + } x--; } } @@ -583,6 +599,55 @@ void lcd_hline(xcoord_t x, uint8_t y, xcoord_t w, LcdFlags att) lcd_hlineStip(x, y, w, 0xff, att); } +#if defined(CPUARM) +void lcd_line(int x1, int y1, int x2, int y2, LcdFlags att) +{ + int i,dx,dy,sdx,sdy,dxabs,dyabs,x,y,px,py; + + dx=x2-x1; /* the horizontal distance of the line */ + dy=y2-y1; /* the vertical distance of the line */ + dxabs=abs(dx); + dyabs=abs(dy); + sdx=sgn(dx); + sdy=sgn(dy); + x=dyabs>>1; + y=dxabs>>1; + px=x1; + py=y1; + + // VGA[(py<<8)+(py<<6)+px]=color; + + if (dxabs>=dyabs) /* the line is more horizontal than vertical */ + { + for(i=0;i=dxabs) + { + y-=dxabs; + py+=sdy; + } + px+=sdx; + lcd_plot(px,py,att); + } + } + else /* the line is more vertical than horizontal */ + { + for(i=0;i=dyabs) + { + x-=dyabs; + px+=sdx; + } + py+=sdy; + lcd_plot(px,py,att); + } + } +} +#endif + #if defined(CPUM64) void lcd_vlineStip(xcoord_t x, int8_t y, int8_t h, uint8_t pat) { @@ -620,6 +685,11 @@ void lcd_vlineStip(xcoord_t x, int8_t y, int8_t h, uint8_t pat) void lcd_vlineStip(xcoord_t x, int8_t y, int8_t h, uint8_t pat, LcdFlags att) { if (x >= LCD_W) return; +#if defined(CPUARM) + // should never happen on 9X + if (y >= LCD_H) return; +#endif + if (h<0) { y+=h; h=-h; } if (y<0) { h+=y; y=0; } if (y+h > LCD_H) { h = LCD_H - y; } @@ -704,12 +774,12 @@ void lcdDrawTelemetryTopBar() uint8_t att = (g_vbat100mV < g_eeGeneral.vBatWarn ? BLINK : 0); putsVBat(16*FW+2,0,att); if (g_model.timers[0].mode) { - att = (timersStates[0].state==TMR_BEEPING ? BLINK : 0); + att = (timersStates[0].val<0 ? BLINK : 0); putsTime(22*FW+5*FWNUM+1, 0, timersStates[0].val, att, att); lcd_putsiAtt(18*FW+2, 1, STR_VTELEMCHNS, TELEM_TM1, SMLSIZE); } if (g_model.timers[1].mode) { - att = (timersStates[1].state==TMR_BEEPING ? BLINK : 0); + att = (timersStates[1].val<0 ? BLINK : 0); putsTime(31*FW+5*FWNUM+1, 0, timersStates[1].val, att, att); lcd_putsiAtt(27*FW+2, 1, STR_VTELEMCHNS, TELEM_TM2, SMLSIZE); } @@ -722,7 +792,7 @@ void lcdDrawTelemetryTopBar() uint8_t att = (g_vbat100mV < g_eeGeneral.vBatWarn ? BLINK : 0); putsVBat(14*FW,0,att); if (g_model.timers[0].mode) { - att = (timersStates[0].state==TMR_BEEPING ? BLINK : 0); + att = (timersStates[0].val<0 ? BLINK : 0); putsTime(17*FW+5*FWNUM+1, 0, timersStates[0].val, att, att); } lcd_invert_line(0); @@ -828,18 +898,50 @@ void putsStrIdx(xcoord_t x, uint8_t y, const pm_char *str, uint8_t idx, LcdFlags void putsMixerSource(xcoord_t x, uint8_t y, uint8_t idx, LcdFlags att) { #if defined(PCBTARANIS) - if (idx < MIXSRC_SW1) - lcd_putsiAtt(x, y, STR_VSRCRAW, idx, att); - else if (idx < MIXSRC_PPM1) + if (idx == 0) { + lcd_putsiAtt(x, y, STR_VSRCRAW, 0, att); + } + else if (idx <= MIXSRC_LAST_INPUT) { + lcd_putcAtt(x+2, y+1, 'I', TINSIZE); + lcd_filled_rect(x, y, 7, 7); + if (ZEXIST(g_model.inputNames[idx-MIXSRC_FIRST_INPUT])) + lcd_putsnAtt(x+8, y, g_model.inputNames[idx-MIXSRC_FIRST_INPUT], 4, ZCHAR|att); + else + lcd_outdezNAtt(x+8, y, idx, att|LEADING0|LEFT, 2); + } +#endif + +#if defined(PCBTARANIS) + 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 < scriptInternalData[qr.quot].outputsCount) { + lcd_putcAtt(x+2, y+1, '1'+qr.quot, TINSIZE); + lcd_filled_rect(x, y, 7, 7); + lcd_putsnAtt(x+8, y, scriptInternalData[qr.quot].outputs[qr.rem].name, att & STREXPANDED ? 9 : 4, att); + } + else +#endif + { + putsStrIdx(x, y, "LUA", qr.quot+1, att); + lcd_putcAtt(lcdLastPos, y, 'a'+qr.rem, att); + } + } +#endif + +#if defined(PCBTARANIS) + else if (idx < MIXSRC_SW1) + lcd_putsiAtt(x, y, STR_VSRCRAW, idx-MIXSRC_Rud+1, att); + else if (idx <= MIXSRC_LAST_CSW) putsSwitches(x, y, SWSRC_SW1+idx-MIXSRC_SW1, att); #else if (idx < MIXSRC_THR) lcd_putsiAtt(x, y, STR_VSRCRAW, idx, att); - else if (idx < MIXSRC_PPM1) + else if (idx < MIXSRC_FIRST_PPM) putsSwitches(x, y, idx-MIXSRC_THR+1+3*(1/*+EXTRA_3POS*/), att); #endif else if (idx < MIXSRC_CH1) - putsStrIdx(x, y, STR_PPM, idx-MIXSRC_PPM1+1, att); + putsStrIdx(x, y, STR_PPM, idx-MIXSRC_FIRST_PPM+1, att); else if (idx <= MIXSRC_LAST_CH) { putsStrIdx(x, y, STR_CH, idx-MIXSRC_CH1+1, att); #if defined(PCBTARANIS) @@ -857,9 +959,9 @@ void putsMixerSource(xcoord_t x, uint8_t y, uint8_t idx, LcdFlags att) lcd_putsiAtt(x, y, STR_VTELEMCHNS, idx-MIXSRC_FIRST_TELEM+1, att); } -void putsChnLetter(xcoord_t x, uint8_t y, uint8_t idx, LcdFlags attr) +void putsChnLetter(xcoord_t x, uint8_t y, uint8_t idx, LcdFlags att) { - lcd_putsiAtt(x, y, STR_RETA123, idx-1, attr); + lcd_putsiAtt(x, y, STR_RETA123, idx-1, att); } void putsModelName(xcoord_t x, uint8_t y, char *name, uint8_t id, LcdFlags att) @@ -933,6 +1035,44 @@ void putsFlightPhase(xcoord_t x, uint8_t y, int8_t idx, LcdFlags att) } #endif +#if defined(PCBTARANIS) +void putsCurveRef(xcoord_t x, uint8_t y, CurveRef &curve, LcdFlags att) +{ + if (curve.value != 0) { + switch (curve.type) { + case CURVE_REF_DIFF: + lcd_putcAtt(x, y, 'D', att); + lcd_outdezAtt(x+FW, y, curve.value, LEFT|att); + break; + + case CURVE_REF_EXPO: + lcd_putcAtt(x, y, 'E', att); + lcd_outdezAtt(x+FW, y, curve.value, LEFT|att); + 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(xcoord_t x, uint8_t y, int8_t idx, LcdFlags att) +{ + if (idx == 0) return lcd_putsiAtt(x, y, STR_MMMINV, 0, att); + + if (idx < 0) { + lcd_putcAtt(x-1*FW, y, '!', att); + idx = -idx; + } + + putsStrIdx(x, y, STR_CV, idx, att); +} +#else void putsCurve(xcoord_t x, uint8_t y, int8_t idx, LcdFlags att) { if (idx < 0) { @@ -944,6 +1084,7 @@ void putsCurve(xcoord_t x, uint8_t y, int8_t idx, LcdFlags att) else putsStrIdx(x, y, STR_CV, idx-CURVE_BASE+1, att); } +#endif void putsTmrMode(xcoord_t x, uint8_t y, int8_t mode, LcdFlags att) { diff --git a/src/lcd.h b/src/lcd.h index a826df7f4..52a9ae8ce 100644 --- a/src/lcd.h +++ b/src/lcd.h @@ -57,16 +57,13 @@ #define lcdint_t int16_t #endif -#if LCD_H > 64 - #define LCD_LINES 9 -#else - #define LCD_LINES 8 -#endif - #define FW 6 #define FWNUM 5 #define FH 8 +#define LCD_LINES (LCD_H/FH) +#define LCD_COLS (LCD_W/FW) + /* lcd common flags */ #define BLINK 0x01 @@ -85,8 +82,8 @@ /* lcd puts flags */ /* no 0x80 here because of "GV"1 which is aligned LEFT */ /* no 0x10 here because of "MODEL"01 which uses LEADING0 */ -#define STRCONDENSED 0x10 /* means that THRm will be displayed as THR */ #define BSS 0x20 +#define STRCONDENSED 0x40 /* means that THRm will be displayed as THR */ #define ZCHAR 0x80 /* lcd outdez flags */ @@ -121,9 +118,9 @@ #endif #if defined(PCBTARANIS) -#define GREY(x) ((x) * 0x1000) -#define GREY_DEFAULT GREY(11) -#define GREY_MASK(x) ((x) & 0xF000) + #define GREY(x) ((x) * 0x1000) + #define GREY_DEFAULT GREY(11) + #define GREY_MASK(x) ((x) & 0xF000) #endif #if defined(CPUARM) @@ -172,6 +169,9 @@ void putsModelName(xcoord_t x, uint8_t y, char *name, uint8_t id, LcdFlags att); void putsSwitches(xcoord_t x, uint8_t y, int8_t swtch, LcdFlags att=0); void putsMixerSource(xcoord_t x, uint8_t y, uint8_t idx, LcdFlags att=0); void putsFlightPhase(xcoord_t x, uint8_t y, int8_t idx, LcdFlags att=0); +#if defined(PCBTARANIS) +void putsCurveRef(xcoord_t x, uint8_t y, CurveRef &curve, LcdFlags att); +#endif void putsCurve(xcoord_t x, uint8_t y, int8_t idx, LcdFlags att=0); void putsTmrMode(xcoord_t x, uint8_t y, int8_t mode, LcdFlags att); void putsTrimMode(xcoord_t x, uint8_t y, uint8_t phase, uint8_t idx, LcdFlags att); @@ -206,6 +206,9 @@ void lcd_vline(xcoord_t x, int8_t y, int8_t h); #else void lcd_vlineStip(xcoord_t x, int8_t y, int8_t h, uint8_t pat, LcdFlags att=0); #endif +#if defined(CPUARM) + void lcd_line(int x1, int y1, int x2, int y2, LcdFlags att=0); +#endif void lcd_rect(xcoord_t x, uint8_t y, xcoord_t w, uint8_t h, uint8_t pat=SOLID, LcdFlags att=0); void lcd_filled_rect(xcoord_t x, int8_t y, xcoord_t w, uint8_t h, uint8_t pat=SOLID, LcdFlags att=0); @@ -238,11 +241,11 @@ void lcdSetRefVolt(unsigned char val); void lcdInit(); void lcd_clear(); void lcdSetContrast(); - void lcdRefresh(); #if defined(PCBTARANIS) - const pm_char * bmpLoad(uint8_t *dest, const char *filename, const xcoord_t width, const uint8_t height); + typedef uint8_t * bmp_ptr_t; + const pm_char * bmpLoad(bmp_ptr_t &dest, const char *filename, const xcoord_t width, const uint8_t height); #endif #define BLINK_ON_PHASE (g_blinkTmr10ms & (1<<6)) @@ -252,6 +255,13 @@ void lcdRefresh(); extern uint8_t lcd_buf[DISPLAY_BUF_SIZE]; #endif +#if defined(LUA) + extern bool lcd_locked; + #define LCD_LOCKED() lcd_locked +#else + #define LCD_LOCKED() 0 +#endif + #define LCD_BYTE_FILTER_PLAN(p, keep, add) *(p) = (*(p) & (keep)) | (add) #if defined(PCBTARANIS) diff --git a/src/logs.cpp b/src/logs.cpp index 0c2ae7865..58c47eacc 100644 --- a/src/logs.cpp +++ b/src/logs.cpp @@ -149,7 +149,7 @@ const pm_char * openLogs() #if defined(PCBTARANIS) f_puts("Rud,Ele,Thr,Ail,S1,S2,LS,RS,SA,SB,SC,SD,SE,SF,SG,SH\n", &g_oLogFile); #else - f_puts("Rud,Ele,Thr,Ail,P1,P2,P3,THR,RUD,ELE,3POS,AIL,GEA,TRN\n", &g_oLogFile); + f_puts("Rud,Ele,Thr,Ail,P1,P2,P3,THR,RUD,ELE,ID0,ID1,ID2,AIL,GEA,TRN\n", &g_oLogFile); #endif } else { diff --git a/src/maths.cpp b/src/maths.cpp index 6202255db..6cee8d2d7 100644 --- a/src/maths.cpp +++ b/src/maths.cpp @@ -48,6 +48,18 @@ lcdint_t applyChannelRatio(uint8_t channel, lcdint_t val) } #endif +#if defined(PCBTARANIS) +double gpsToDouble(bool neg, int16_t bp, int16_t ap) +{ + double result = ap; + result /= 10000; + result += (bp % 100); + result /= 60; + result += (bp / 100); + return neg?-result:result; +} +#endif + #if defined(FRSKY_HUB) void extractLatitudeLongitude(uint32_t * latitude, uint32_t * longitude) { @@ -58,8 +70,17 @@ void extractLatitudeLongitude(uint32_t * latitude, uint32_t * longitude) *longitude = ((uint32_t)(qr.quot) * 1000000) + (((uint32_t)(qr.rem) * 10000 + frskyData.hub.gpsLongitude_ap) * 5) / 3; } +#if defined(PCBTARANIS) +double pilotLatitude; +double pilotLongitude; +#endif + void getGpsPilotPosition() { +#if defined(PCBTARANIS) + pilotLatitude = gpsToDouble(frskyData.hub.gpsLatitudeNS=='S', frskyData.hub.gpsLatitude_bp, frskyData.hub.gpsLatitude_ap); + pilotLongitude = gpsToDouble(frskyData.hub.gpsLongitudeEW=='W', frskyData.hub.gpsLongitude_bp, frskyData.hub.gpsLongitude_ap); +#endif extractLatitudeLongitude(&frskyData.hub.pilotLatitude, &frskyData.hub.pilotLongitude); uint32_t lat = frskyData.hub.pilotLatitude / 10000; uint32_t angle2 = (lat*lat) / 10000; diff --git a/src/myeeprom.h b/src/myeeprom.h index d99c4af33..3ddb63d69 100644 --- a/src/myeeprom.h +++ b/src/myeeprom.h @@ -52,65 +52,90 @@ #define BEEP_VAL ( (g_eeGeneral.warnOpts & WARN_BVAL_BIT) >>3 ) #if defined(PCBTARANIS) - #define EEPROM_VER 215 + #define EEPROM_VER 216 #elif defined(PCBSKY9X) - #define EEPROM_VER 215 + #define EEPROM_VER 216 #elif defined(CPUM2560) || defined(CPUM2561) - #define EEPROM_VER 214 -#elif defined(CPUM128) #define EEPROM_VER 215 +#elif defined(CPUM128) + #define EEPROM_VER 216 #else - #define EEPROM_VER 213 + #define EEPROM_VER 214 #endif #ifndef PACK #define PACK( __Declaration__ ) __Declaration__ __attribute__((__packed__)) #endif -#if defined(CPUARM) - #define MAX_MODELS 60 - #define NUM_CHNOUT 32 // number of real output channels CH1-CH32 - #define MAX_PHASES 9 - #define MAX_MIXERS 64 - #define MAX_EXPOS 32 - #define NUM_CSW 32 // number of custom switches - #define NUM_CFN 32 // number of functions assigned to switches +#if defined(PCBTARANIS) + #define MAX_MODELS 60 + #define NUM_CHNOUT 32 // number of real output channels CH1-CH32 + #define MAX_PHASES 9 + #define MAX_MIXERS 64 + #define MAX_EXPOS 64 + #define NUM_CSW 32 // number of custom switches + #define NUM_CFN 32 // number of functions assigned to switches + #define MAX_SCRIPTS 3 + #define MAX_INPUTS 32 +#elif defined(CPUARM) + #define MAX_MODELS 60 + #define NUM_CHNOUT 32 // number of real output channels CH1-CH32 + #define MAX_PHASES 9 + #define MAX_MIXERS 64 + #define MAX_EXPOS 32 + #define NUM_CSW 32 // number of custom switches + #define NUM_CFN 32 // number of functions assigned to switches #elif defined(CPUM2560) || defined(CPUM2561) - #define MAX_MODELS 30 - #define NUM_CHNOUT 16 // number of real output channels CH1-CH16 - #define MAX_PHASES 6 - #define MAX_MIXERS 32 - #define MAX_EXPOS 16 - #define NUM_CSW 15 // number of custom switches - #define NUM_CFN 24 // number of functions assigned to switches + #define MAX_MODELS 30 + #define NUM_CHNOUT 16 // number of real output channels CH1-CH16 + #define MAX_PHASES 6 + #define MAX_MIXERS 32 + #define MAX_EXPOS 16 + #define NUM_CSW 15 // number of custom switches + #define NUM_CFN 24 // number of functions assigned to switches #elif defined(CPUM128) - #define MAX_MODELS 30 - #define NUM_CHNOUT 16 // number of real output channels CH1-CH16 - #define MAX_PHASES 5 - #define MAX_MIXERS 32 - #define MAX_EXPOS 14 - #define NUM_CSW 15 // number of custom switches - #define NUM_CFN 24 // number of functions assigned to switches + #define MAX_MODELS 30 + #define NUM_CHNOUT 16 // number of real output channels CH1-CH16 + #define MAX_PHASES 5 + #define MAX_MIXERS 32 + #define MAX_EXPOS 14 + #define NUM_CSW 15 // number of custom switches + #define NUM_CFN 24 // number of functions assigned to switches #else - #define MAX_MODELS 16 - #define NUM_CHNOUT 16 // number of real output channels CH1-CH16 - #define MAX_PHASES 5 - #define MAX_MIXERS 32 - #define MAX_EXPOS 14 - #define NUM_CSW 12 // number of custom switches - #define NUM_CFN 16 // number of functions assigned to switches + #define MAX_MODELS 16 + #define NUM_CHNOUT 16 // number of real output channels CH1-CH16 + #define MAX_PHASES 5 + #define MAX_MIXERS 32 + #define MAX_EXPOS 14 + #define NUM_CSW 12 // number of custom switches + #define NUM_CFN 16 // number of functions assigned to switches #endif -#define MAX_TIMERS 2 +#define MAX_TIMERS 2 -#if defined(CPUARM) +#if defined(PCBTARANIS) + enum CurveType { + CURVE_TYPE_STANDARD, + CURVE_TYPE_CUSTOM, + CURVE_TYPE_LAST = CURVE_TYPE_CUSTOM + }; +PACK(typedef struct t_CurveInfo { + uint8_t type:3; + uint8_t smooth:1; + uint8_t spare:4; + int8_t points; +}) CurveInfo; + #define MAX_CURVES 32 + #define NUM_POINTS 512 + #define CURVDATA CurveInfo +#elif defined(CPUARM) #define MAX_CURVES 16 #define NUM_POINTS 512 - #define CURVTYPE int16_t + #define CURVDATA int16_t #else #define MAX_CURVES 8 #define NUM_POINTS (112-MAX_CURVES) - #define CURVTYPE int8_t + #define CURVDATA int8_t #endif #if defined(PCBTARANIS) || defined(PCBSKY9X) @@ -122,8 +147,14 @@ typedef int16_t gvar_t; #if !defined(PCBSTD) - typedef char gvar_name_t[6]; - #define GVAR_MAX 1024 + #define LEN_GVAR_NAME 6 + #define GVAR_MAX 1024 + #define GVAR_LIMIT 500 + PACK(typedef struct { + char name[LEN_GVAR_NAME]; + uint8_t popup:1; + uint8_t spare:7; + }) global_gvar_t; #endif #define RESERVE_RANGE_FOR_GVARS 10 @@ -139,8 +170,12 @@ typedef int16_t gvar_t; #define MODEL_GVARS_DATA #define PHASE_GVARS_DATA #else - #define MAX_GVARS 5 - #define MODEL_GVARS_DATA gvar_name_t gvarsNames[MAX_GVARS]; + #if defined(CPUARM) + #define MAX_GVARS 9 + #else + #define MAX_GVARS 5 + #endif + #define MODEL_GVARS_DATA global_gvar_t gvars[MAX_GVARS]; #define PHASE_GVARS_DATA gvar_t gvars[MAX_GVARS] #define GVAR_VALUE(x, p) g_model.phaseData[p].gvars[x] #endif @@ -224,26 +259,34 @@ PACK(typedef struct t_ModuleData { #define SET_DEFAULT_PPM_FRAME_LENGTH(idx) g_model.moduleData[idx].ppmFrameLength = 4 * max((int8_t)0, g_model.moduleData[idx].channelsCount) +#define MAX_SCRIPT_INPUTS 10 +#define MAX_SCRIPT_OUTPUTS 6 +PACK(typedef struct t_ScriptData { + char file[10]; + char name[10]; + int8_t inputs[MAX_SCRIPT_INPUTS]; +}) ScriptData; + #if defined(PCBTARANIS) -enum ModuleIndex { - INTERNAL_MODULE, - EXTERNAL_MODULE, - TRAINER_MODULE -}; -#define MODELDATA_BITMAP char bitmap[LEN_BITMAP_NAME]; -#define MODELDATA_EXTRA uint8_t externalModule; uint8_t trainerMode; ModuleData moduleData[NUM_MODULES+1]; char curveNames[MAX_CURVES][6]; -#define LIMITDATA_EXTRA char name[LEN_CHANNEL_NAME]; -#define swstate_t uint16_t + enum ModuleIndex { + INTERNAL_MODULE, + EXTERNAL_MODULE, + TRAINER_MODULE + }; + #define MODELDATA_BITMAP char bitmap[LEN_BITMAP_NAME]; + #define MODELDATA_EXTRA uint8_t externalModule; uint8_t trainerMode; ModuleData moduleData[NUM_MODULES+1]; char curveNames[MAX_CURVES][6]; ScriptData scriptsData[MAX_SCRIPTS]; char inputNames[MAX_INPUTS][4]; + #define LIMITDATA_EXTRA char name[LEN_CHANNEL_NAME]; int8_t curve; + #define swstate_t uint16_t #elif defined(PCBSKY9X) -#define MODELDATA_BITMAP -#define MODELDATA_EXTRA ModuleData moduleData[NUM_MODULES]; -#define LIMITDATA_EXTRA -#define swstate_t uint8_t + #define MODELDATA_BITMAP + #define MODELDATA_EXTRA ModuleData moduleData[NUM_MODULES]; + #define LIMITDATA_EXTRA + #define swstate_t uint8_t #else -#define MODELDATA_BITMAP -#define MODELDATA_EXTRA -#define LIMITDATA_EXTRA -#define swstate_t uint8_t + #define MODELDATA_BITMAP + #define MODELDATA_EXTRA + #define LIMITDATA_EXTRA + #define swstate_t uint8_t #endif enum BacklightMode { @@ -255,9 +298,9 @@ enum BacklightMode { }; #if defined(FSPLASH) || defined(XSPLASH) -#define SPLASH_MODE uint8_t splashMode:3 + #define SPLASH_MODE uint8_t splashMode:3 #else -#define SPLASH_MODE uint8_t splashMode:1; uint8_t spare4:2 + #define SPLASH_MODE uint8_t splashMode:1; uint8_t spare4:2 #endif #define ALTERNATE_VIEW 0x10 @@ -306,35 +349,59 @@ PACK(typedef struct t_EEGeneral { EXTRA_GENERAL_FIELDS + swstate_t switchUnlockStates; + }) EEGeneral; #if defined(PCBTARANIS) -#define LEN_MODEL_NAME 12 -#define LEN_BITMAP_NAME 10 -#define LEN_EXPOMIX_NAME 8 -#define LEN_FP_NAME 10 -#define LEN_CHANNEL_NAME 6 + #define LEN_MODEL_NAME 12 + #define LEN_BITMAP_NAME 10 + #define LEN_EXPOMIX_NAME 8 + #define LEN_FP_NAME 10 + #define LEN_CHANNEL_NAME 6 #elif defined(PCBSKY9X) -#define LEN_MODEL_NAME 10 -#define LEN_EXPOMIX_NAME 6 -#define LEN_FP_NAME 6 + #define LEN_MODEL_NAME 10 + #define LEN_EXPOMIX_NAME 6 + #define LEN_FP_NAME 6 #else -#define LEN_MODEL_NAME 10 -#define LEN_FP_NAME 6 + #define LEN_MODEL_NAME 10 + #define LEN_FP_NAME 6 +#endif + +#if defined(PCBTARANIS) +enum CurveRefType { + CURVE_REF_DIFF, + CURVE_REF_EXPO, + CURVE_REF_FUNC, + CURVE_REF_CUSTOM +}; +PACK(typedef struct t_CurveRef { + uint8_t type; + int8_t value; +}) CurveRef; +#else + #define MODE_DIFFERENTIAL 0 + #define MODE_EXPO 0 + #define MODE_CURVE 1 #endif #if defined(PCBTARANIS) PACK(typedef struct t_ExpoData { - uint8_t mode; // 0=end, 1=pos, 2=neg, 3=both + uint8_t srcRaw; + uint16_t scale; uint8_t chn; int8_t swtch; uint16_t phases; int8_t weight; - uint8_t curveMode; + int8_t carryTrim; char name[LEN_EXPOMIX_NAME]; + int8_t offset; + CurveRef curve; uint8_t spare[2]; - int8_t curveParam; }) ExpoData; +#define MIN_EXPO_WEIGHT -100 +#define EXPO_VALID(ed) ((ed)->srcRaw) +#define EXPO_MODE_ENABLE(ed, v) (true) #elif defined(CPUARM) PACK(typedef struct t_ExpoData { uint8_t mode; // 0=end, 1=pos, 2=neg, 3=both @@ -346,6 +413,9 @@ PACK(typedef struct t_ExpoData { char name[LEN_EXPOMIX_NAME]; int8_t curveParam; }) ExpoData; +#define MIN_EXPO_WEIGHT 0 +#define EXPO_VALID(ed) ((ed)->mode) +#define EXPO_MODE_ENABLE(ed, v) ((v<0 && (ed->mode&1)) || (v>=0 && (ed->mode&2))) #elif defined(CPUM2560) || defined(CPUM2561) PACK(typedef struct t_ExpoData { uint8_t mode:2; // 0=end, 1=pos, 2=neg, 3=both @@ -357,6 +427,9 @@ PACK(typedef struct t_ExpoData { uint8_t weight; int8_t curveParam; }) ExpoData; +#define MIN_EXPO_WEIGHT 0 +#define EXPO_VALID(ed) ((ed)->mode) +#define EXPO_MODE_ENABLE(ed, v) ((v<0 && (ed->mode&1)) || (v>=0 && (ed->mode&2))) #else PACK(typedef struct t_ExpoData { uint8_t mode:2; // 0=end, 1=pos, 2=neg, 3=both @@ -367,11 +440,32 @@ PACK(typedef struct t_ExpoData { uint8_t weight; // One spare bit here (used for GVARS) int8_t curveParam; }) ExpoData; +#define MIN_EXPO_WEIGHT 0 +#define EXPO_VALID(ed) ((ed)->mode) +#define EXPO_MODE_ENABLE(ed, v) ((v<0 && (ed->mode&1)) || (v>=0 && (ed->mode&2))) +#endif + +#if defined(CPUARM) + #define limit_min_max_t int16_t + #define LIMIT_MAX(lim) (GV_IS_GV_VALUE(lim->max+1000, 0, 1250) ? GET_GVAR(lim->max+1000, 0, 125, s_perout_flight_phase)*10 : lim->max+1000) + #define LIMIT_MIN(lim) (GV_IS_GV_VALUE(lim->min-1000, -1250, 0) ? GET_GVAR(lim->min-1000, -125, 0, s_perout_flight_phase)*10 : lim->min-1000) + #define LIMIT_OFS(lim) (GV_IS_GV_VALUE(lim->offset, -1000, 1000) ? GET_GVAR(lim->offset, -100, 100, s_perout_flight_phase)*10 : lim->offset) + #define LIMIT_MAX_RESX(lim) calc1000toRESX(LIMIT_MAX(lim)) + #define LIMIT_MIN_RESX(lim) calc1000toRESX(LIMIT_MIN(lim)) + #define LIMIT_OFS_RESX(lim) calc1000toRESX(LIMIT_OFS(lim)) +#else + #define limit_min_max_t int8_t + #define LIMIT_MAX(lim) (lim->max+100) + #define LIMIT_MIN(lim) (lim->min-100) + #define LIMIT_OFS(lim) (lim->offset) + #define LIMIT_MAX_RESX(lim) calc100toRESX(LIMIT_MAX(lim)) + #define LIMIT_MIN_RESX(lim) calc100toRESX(LIMIT_MIN(lim)) + #define LIMIT_OFS_RESX(lim) calc1000toRESX(LIMIT_OFS(lim)) #endif PACK(typedef struct t_LimitData { - int8_t min; - int8_t max; + limit_min_max_t min; + limit_min_max_t max; int8_t ppmCenter; int16_t offset:14; uint16_t symetrical:1; @@ -392,10 +486,6 @@ PACK(typedef struct t_LimitData { #define MLTPX_MUL 1 #define MLTPX_REP 2 -#define MODE_DIFFERENTIAL 0 -#define MODE_EXPO 0 -#define MODE_CURVE 1 - #if defined(CPUARM) #define DELAY_STEP 10 #define SLOW_STEP 10 @@ -405,14 +495,10 @@ PACK(typedef struct t_LimitData { PACK(typedef struct t_MixData { uint8_t destCh; uint16_t phases; - uint8_t curveMode:1; // O=curve, 1=differential - uint8_t noExpo:1; - int8_t carryTrim:3; - uint8_t mltpx:2; // multiplex method: 0 means +=, 1 means *=, 2 means := - uint8_t spare1:1; + uint8_t mltpx; // multiplex method: 0 means +=, 1 means *=, 2 means := int16_t weight; int8_t swtch; - int8_t curveParam; + CurveRef curve; uint8_t mixWarn:4; // mixer warning uint8_t srcVariant:4; uint8_t delayUp; @@ -422,13 +508,13 @@ PACK(typedef struct t_MixData { uint8_t srcRaw; int16_t offset; char name[LEN_EXPOMIX_NAME]; - uint8_t spare2[2]; + uint8_t spare[2]; }) MixData; #else PACK(typedef struct t_MixData { uint8_t destCh; uint16_t phases; - uint8_t curveMode:1; // O=curve, 1=differential + uint8_t curveMode:1; uint8_t noExpo:1; int8_t carryTrim:3; uint8_t mltpx:2; // multiplex method: 0 means +=, 1 means *=, 2 means := @@ -554,6 +640,7 @@ PACK( union u_int8int16_t { #define MAX_CSW_DURATION 120 /*60s*/ #define MAX_CSW_DELAY 120 /*60s*/ #define MAX_CSW_ANDSW MAX_SWITCH +typedef int16_t csw_telemetry_value_t; PACK(typedef struct t_CustomSwData { // Custom Switches data int16_t v1; int16_t v2; @@ -563,6 +650,7 @@ PACK(typedef struct t_CustomSwData { // Custom Switches data int8_t andsw; }) CustomSwData; #else +typedef uint8_t csw_telemetry_value_t; #define MAX_CSW_ANDSW 15 PACK(typedef struct t_CustomSwData { // Custom Switches data int8_t v1; //input @@ -621,9 +709,9 @@ enum Functions { }; #if defined(VOICE) - #define HAS_REPEAT_PARAM() (CFN_FUNC(sd) == FUNC_PLAY_SOUND || (CFN_FUNC(sd) >= FUNC_PLAY_TRACK && CFN_FUNC(sd) <= FUNC_PLAY_VALUE)) + #define HAS_REPEAT_PARAM(sd) (CFN_FUNC(sd) == FUNC_PLAY_SOUND || (CFN_FUNC(sd) >= FUNC_PLAY_TRACK && CFN_FUNC(sd) <= FUNC_PLAY_VALUE)) #else - #define HAS_REPEAT_PARAM() (CFN_FUNC(sd) == FUNC_PLAY_SOUND) + #define HAS_REPEAT_PARAM(sd) (CFN_FUNC(sd) == FUNC_PLAY_SOUND) #endif enum ResetFunctionParam { @@ -670,15 +758,18 @@ PACK(typedef struct t_CustomFnData { // Function Switches data uint8_t mode:2; uint8_t active:6; }) CustomFnData; -#define CFN_FUNC(p) ((p)->func) -#define CFN_ACTIVE(p) ((p)->active) -#define CFN_CH_NUMBER(p) (CFN_FUNC(p)) -#define CFN_PLAY_REPEAT(p) ((p)->active) -#define CFN_GVAR_MODE(p) ((p)->mode) -#define CFN_PARAM(p) ((p)->param.composite.val) -#define CFN_RESET(p) { p->active = 0; memset(&(p)->param, 0, sizeof((p)->param)); } +#define CFN_EMPTY(p) (!(p)->swtch) +#define CFN_FUNC(p) ((p)->func) +#define CFN_ACTIVE(p) ((p)->active) +#define CFN_CH_NUMBER(p) (CFN_FUNC(p)) +#define CFN_PLAY_REPEAT(p) ((p)->active) +#define CFN_PLAY_REPEAT_MUL 1 +#define CFN_PLAY_REPEAT_NOSTART 0b111111 +#define CFN_GVAR_MODE(p) ((p)->mode) +#define CFN_PARAM(p) ((p)->param.composite.val) +#define CFN_RESET(p) (p->active = 0, memset(&(p)->param, 0, sizeof((p)->param))) #else -PACK(typedef struct t_CustomFnData { // Function Switches data +PACK(typedef struct t_CustomFnData { int8_t swtch; // input union { struct { @@ -699,13 +790,14 @@ PACK(typedef struct t_CustomFnData { // Function Switches data } internal; uint8_t param; }) CustomFnData; -#define CFN_FUNC(p) ((p)->internal.func_param.func) -#define CFN_ACTIVE(p) ((p)->internal.func_param_enable.active) -#define CFN_CH_NUMBER(p) ((p)->internal.func_safety.func) -#define CFN_PLAY_REPEAT(p) ((p)->internal.func_param.param) -#define CFN_GVAR_MODE(p) ((p)->internal.func_param_enable.param) -#define CFN_PARAM(p) ((p)->param) -#define CFN_RESET(p) {(p)->internal.func_param_enable.active = 0; CFN_PARAM(p) = 0;} +#define CFN_FUNC(p) ((p)->internal.func_param.func) +#define CFN_ACTIVE(p) ((p)->internal.func_param_enable.active) +#define CFN_CH_NUMBER(p) ((p)->internal.func_safety.func) +#define CFN_PLAY_REPEAT(p) ((p)->internal.func_param.param) +#define CFN_PLAY_REPEAT_MUL 10 +#define CFN_GVAR_MODE(p) ((p)->internal.func_param_enable.param) +#define CFN_PARAM(p) ((p)->param) +#define CFN_RESET(p) ((p)->internal.func_param_enable.active = 0, CFN_PARAM(p) = 0) #endif enum TelemetryUnit { @@ -791,6 +883,8 @@ enum TelemetrySource { TELEM_MAX_T2, TELEM_MAX_SPEED, TELEM_MAX_DIST, + // TODO TELEM_MIN_CELL, + // TODO TELEM_MIN_VFAS, TELEM_MAX_CURRENT, TELEM_MAX_POWER, TELEM_ACC, @@ -874,7 +968,8 @@ enum FrskySource { PACK(typedef struct t_FrSkyData { FrSkyChannelData channels[2]; uint8_t usrProto; // Protocol in FrSky user data, 0=None, 1=FrSky hub, 2=WS HowHigh, 3=Halcyon - uint8_t voltsSource; + uint8_t voltsSource:7; + uint8_t altitudeDisplayed:1; uint8_t blades; // How many blades for RPMs, 0=2 blades, 1=3 blades uint8_t currentSource; uint8_t screensType; @@ -1032,7 +1127,8 @@ enum SwitchSources { SWSRC_TRN, #endif - SWSRC_SW1, + SWSRC_FIRST_CSW, + SWSRC_SW1 = SWSRC_FIRST_CSW, SWSRC_SW2, SWSRC_SW3, SWSRC_SW4, @@ -1071,33 +1167,50 @@ enum SwitchSources { enum MixSources { MIXSRC_NONE, + +#if defined(PCBTARANIS) + MIXSRC_FIRST_INPUT, + MIXSRC_LAST_INPUT = MIXSRC_FIRST_INPUT+MAX_INPUTS-1, + + MIXSRC_FIRST_LUA, + MIXSRC_LAST_LUA = MIXSRC_FIRST_LUA+(MAX_SCRIPTS*MAX_SCRIPT_OUTPUTS)-1, +#endif + MIXSRC_Rud, MIXSRC_Ele, MIXSRC_Thr, MIXSRC_Ail, - MIXSRC_Pot1, + MIXSRC_FIRST_POT, #if defined(PCBTARANIS) - MIXSRC_S1 = MIXSRC_Pot1, + MIXSRC_S1 = MIXSRC_FIRST_POT, MIXSRC_S2, MIXSRC_S3, MIXSRC_S4, + MIXSRC_LAST_POT = MIXSRC_S4, #else - MIXSRC_P1 = MIXSRC_Pot1, + MIXSRC_P1 = MIXSRC_FIRST_POT, MIXSRC_P2, - #if !defined(EXTRA_3POS) + #if defined(EXTRA_3POS) + MIXSRC_LAST_POT = MIXSRC_P2, + #else MIXSRC_P3, + MIXSRC_LAST_POT = MIXSRC_P3, #endif #endif #if defined(PCBSKY9X) MIXSRC_REa, + MIXSRC_LAST_ROTARY_ENCODER = MIXSRC_REa, #elif defined(PCBGRUVIN9X) || defined(PCBMEGA2560) MIXSRC_REa, MIXSRC_REb, #if ROTARY_ENCODERS > 2 MIXSRC_REc, MIXSRC_REd, + MIXSRC_LAST_ROTARY_ENCODER = MIXSRC_REd, + #else + MIXSRC_LAST_ROTARY_ENCODER = MIXSRC_REb, #endif #endif @@ -1135,17 +1248,19 @@ enum MixSources { MIXSRC_GEA, MIXSRC_TRN, #endif - MIXSRC_SW1, + MIXSRC_FIRST_CSW, + MIXSRC_SW1 = MIXSRC_FIRST_CSW, MIXSRC_SW9 = MIXSRC_SW1 + 8, MIXSRC_SWA, MIXSRC_SWB, MIXSRC_SWC, - MIXSRC_LAST_CSW = MIXSRC_SW1+NUM_CSW-1, + MIXSRC_LAST_CSW = MIXSRC_FIRST_CSW+NUM_CSW-1, - MIXSRC_PPM1, - MIXSRC_LAST_PPM = MIXSRC_PPM1 + 7, + MIXSRC_FIRST_PPM, + MIXSRC_LAST_PPM = MIXSRC_FIRST_PPM + 7, - MIXSRC_CH1, + MIXSRC_FIRST_CH, + MIXSRC_CH1 = MIXSRC_FIRST_CH, MIXSRC_CH2, MIXSRC_CH3, MIXSRC_CH4, @@ -1170,7 +1285,10 @@ enum MixSources { MIXSRC_LAST_TELEM = MIXSRC_FIRST_TELEM+NUM_TELEMETRY-1 }; -#define MIXSRC_LAST MIXSRC_LAST_CH +#define MIXSRC_FIRST (MIXSRC_NONE+1) +#define MIXSRC_LAST MIXSRC_LAST_CH +#define INPUTSRC_FIRST MIXSRC_Rud +#define INPUTSRC_LAST MIXSRC_LAST_TELEM #define MIN_POINTS 3 #define MAX_POINTS 17 @@ -1181,15 +1299,19 @@ enum MixSources { #define TMRMODE_THR_REL 3 #define TMRMODE_THR_TRG 4 +#define COUNTDOWN_SILENT 0 +#define COUNTDOWN_BEEPS 1 +#define COUNTDOWN_VOICE 2 + #if defined(CPUARM) || defined(CPUM2560) PACK(typedef struct t_TimerData { - int8_t mode; // timer trigger source -> off, abs, stk, stk%, sw/!sw, !m_sw/!m_sw - uint16_t start:12; - uint16_t countdownBeep:1; - uint16_t minuteBeep:1; - uint16_t persistent:1; - uint16_t spare:1; - uint16_t value; + int8_t mode; // timer trigger source -> off, abs, stk, stk%, sw/!sw, !m_sw/!m_sw + uint16_t start; + uint8_t countdownBeep:2; + uint8_t minuteBeep:1; + uint8_t persistent:1; + uint8_t spare:4; + uint16_t value; }) TimerData; #else PACK(typedef struct t_TimerData { @@ -1258,11 +1380,11 @@ enum FailsafeModes { }; #if defined(FRSKY) || !defined(PCBSTD) -#define TELEMETRY_DATA FrSkyData frsky; + #define TELEMETRY_DATA FrSkyData frsky; #elif defined(MAVLINK) -#define TELEMETRY_DATA MavlinkData mavlink; + #define TELEMETRY_DATA MavlinkData mavlink; #else -#define TELEMETRY_DATA + #define TELEMETRY_DATA #endif #if defined(CPUARM) || defined(PCBGRUVIN9X) || defined(PCBMEGA2560) @@ -1282,20 +1404,20 @@ PACK(typedef struct t_ModelData { TimerData timers[MAX_TIMERS]; uint8_t protocol:3; uint8_t thrTrim:1; // Enable Throttle Trim - int8_t ppmNCH:4; + int8_t ppmNCH:4; /* spare on ARM */ uint8_t trimInc:3; // Trim Increments uint8_t disableThrottleWarning:1; - uint8_t pulsePol:1; + uint8_t pulsePol:1; /* spare on ARM */ uint8_t extendedLimits:1; uint8_t extendedTrims:1; uint8_t throttleReversed:1; - int8_t ppmDelay; + int8_t ppmDelay; /* spare on ARM */ BeepANACenter beepANACenter; // 1<<0->A1.. 1<<6->A7 MixData mixData[MAX_MIXERS]; LimitData limitData[NUM_CHNOUT]; ExpoData expoData[MAX_EXPOS]; - CURVTYPE curves[MAX_CURVES]; + CURVDATA curves[MAX_CURVES]; int8_t points[NUM_POINTS]; CustomSwData customSw[NUM_CSW]; diff --git a/src/opentx.cpp b/src/opentx.cpp index 6f02ebd2f..af3e7dd27 100644 --- a/src/opentx.cpp +++ b/src/opentx.cpp @@ -36,19 +36,35 @@ #include "opentx.h" +// static variables used in perOut - moved here so they don't interfere with the stack +// It's also easier to initialize them here. +#if !defined(PCBTARANIS) +int16_t rawAnas[NUM_INPUTS] = {0}; +#endif +int16_t anas [NUM_INPUTS] = {0}; +int16_t trims[NUM_STICKS] = {0}; +int32_t chans[NUM_CHNOUT] = {0}; +BeepANACenter bpanaCenter = 0; +struct t_inactivity inactivity = {0}; + +int24_t act [MAX_MIXERS] = {0}; +SwOn swOn [MAX_MIXERS]; // TODO better name later... + +uint8_t mixWarning; + #if defined(CPUARM) +#define MENUS_STACK_SIZE 2000 #define MIXER_STACK_SIZE 500 -#define MENUS_STACK_SIZE 1000 #define AUDIO_STACK_SIZE 500 #define BT_STACK_SIZE 500 #define DEBUG_STACK_SIZE 500 -OS_TID mixerTaskId; -OS_STK mixerStack[MIXER_STACK_SIZE]; - OS_TID menusTaskId; OS_STK menusStack[MENUS_STACK_SIZE]; +OS_TID mixerTaskId; +OS_STK mixerStack[MIXER_STACK_SIZE]; + OS_TID audioTaskId; OS_STK audioStack[AUDIO_STACK_SIZE]; @@ -163,10 +179,10 @@ mode3 ail ele thr rud mode4 ail thr ele rud */ const pm_uint8_t modn12x3[] PROGMEM = { - 1, 2, 3, 4, - 1, 3, 2, 4, - 4, 2, 3, 1, - 4, 3, 2, 1 }; + 0, 1, 2, 3, + 0, 2, 1, 3, + 3, 1, 2, 0, + 3, 2, 1, 0 }; char idx2char(int8_t idx) { @@ -182,6 +198,38 @@ char idx2char(int8_t idx) return ' '; } +#if defined(PCBTARANIS) +int8_t char2idx(char c) +{ + if (c == '_') return 37; + if (c >= 'a') return 'a' - c - 1; + if (c >= 'A') return c - 'A' + 1; + if (c >= '0') return c - '0' + 27; + if (c == '-') return 38; + if (c == '.') return 39; + if (c == ',') return 40; + return 0; +} + +void str2zchar(char *dest, const char *src, int size) +{ + memset(dest, 0, size); + for (int c=0; c= 0 && dest[size] == ' '); +} +#endif + #if defined(CPUARM) bool zexist(const char *str, uint8_t size) { @@ -348,6 +396,28 @@ LimitData *limitAddress(uint8_t idx) return &g_model.limitData[idx]; } +#if defined(PCBTARANIS) +int8_t *curveEnd[MAX_CURVES]; +void loadCurves() +{ + int8_t * tmp = g_model.points; + for (int i=0; idestCh = i; - md->weight = 100; - md->srcRaw = channel_order(i+1); - } +#if defined(PCBTARANIS) + uint8_t stick_index = channel_order(i+1); + ExpoData *expo = expoAddress(i); + expo->srcRaw = MIXSRC_Rud - 1 + stick_index; + expo->curve.type = CURVE_REF_EXPO; + expo->chn = i; + expo->weight = 100; + for (int c=0; c<4; c++) { + g_model.inputNames[i][c] = char2idx(STR_VSRCRAW[1+STR_VSRCRAW[0]*stick_index+c]); + } +#endif + MixData *mix = mixAddress(i); + mix->destCh = i; + mix->weight = 100; + +#if defined(PCBTARANIS) + mix->srcRaw = i+1; + if (!isSourceAvailable(mix->srcRaw)) { + mix->srcRaw = MIXSRC_Rud - 1 + stick_index; + } +#else + mix->srcRaw = MIXSRC_Rud - 1 + channel_order(i+1); +#endif + } eeDirty(EE_MODEL); } -#endif #if defined(PXX) && defined(CPUARM) void checkModelIdUnique(uint8_t id) @@ -458,6 +546,7 @@ void checkModelIdUnique(uint8_t id) for (uint8_t i=0; ipoints + 5; + #define MMULT 1024 + if (i == 0) { + //linear interpolation between 1st 2 points + //keep 3 decimal-places for m + if (crv->type == CURVE_TYPE_CUSTOM) { + int8_t x0 = CUSTOM_POINT_X(points, num_points, 0); + int8_t x1 = CUSTOM_POINT_X(points, num_points, 1); + if (x1 > x0) m = (MMULT * (points[1] - points[0])) / (x1 - x0); + } + else { + s32 delta = (2 * 100) / (num_points - 1); + m = (MMULT * (points[1] - points[0])) / delta; + } + } + else if (i == num_points - 1) { + //linear interpolation between last 2 points + //keep 3 decimal-places for m + if (crv->type == CURVE_TYPE_CUSTOM) { + int8_t x0 = CUSTOM_POINT_X(points, num_points, num_points-2); + int8_t x1 = CUSTOM_POINT_X(points, num_points, num_points-1); + if (x1 > x0) m = (MMULT * (points[num_points-1] - points[num_points-2])) / (x1 - x0); + } + else { + s32 delta = (2 * 100) / (num_points - 1); + m = (MMULT * (points[num_points-1] - points[num_points-2])) / delta; + } + } + else { + //apply monotone rules from + //http://en.wikipedia.org/wiki/Monotone_cubic_interpolation + //1) compute slopes of secant lines + s32 d0=0, d1=0; + if (crv->type == CURVE_TYPE_CUSTOM) { + int8_t x0 = CUSTOM_POINT_X(points, num_points, i-1); + int8_t x1 = CUSTOM_POINT_X(points, num_points, i); + int8_t x2 = CUSTOM_POINT_X(points, num_points, i+1); + if (x1 > x0) d0 = (MMULT * (points[i] - points[i-1])) / (x1 - x0); + if (x2 > x1) d1 = (MMULT * (points[i+1] - points[i])) / (x2 - x1); + } + else { + s32 delta = (2 * 100) / (num_points - 1); + d0 = (MMULT * (points[i] - points[i-1])) / (delta); + d1 = (MMULT * (points[i+1] - points[i])) / (delta); + } + //2) compute initial average tangent + m = (d0 + d1) / 2; + //3 check for horizontal lines + if (d0 == 0 || d1 == 0 || (d0 > 0 && d1 < 0) || (d0 < 0 && d1 > 0)) { + m = 0; + } + else if (MMULT * m / d0 > 3 * MMULT) { + m = 3 * d0; + } + else if (MMULT * m / d1 > 3 * MMULT) { + m = 3 * d1; + } + } + return m; +} + +/* The following is a hermite cubic spline. + The basis functions can be found here: + http://en.wikipedia.org/wiki/Cubic_Hermite_spline + The tangents are computed via the 'cubic monotone' rules (allowing for local-maxima) +*/ +int16_t hermite_spline(int16_t x, uint8_t idx) +{ + CurveInfo &crv = g_model.curves[idx]; + int8_t *points = curveAddress(idx); + uint8_t count = crv.points+5; + bool custom = (crv.type == CURVE_TYPE_CUSTOM); + + if (x < -RESX) + x = -RESX; + else if (x > RESX) + x = RESX; + + for (int i=0; i0 ? calc100toRESX(points[count+i-1]) : -RESX); + p3x = (i= p0x && x <= p3x) { + s32 p0y = calc100toRESX(points[i]); + s32 p3y = calc100toRESX(points[i+1]); + s32 m0 = compute_tangent(&crv, points, i); + s32 m3 = compute_tangent(&crv, points, i+1); + s32 y; + s32 h = p3x - p0x; + s32 t = (h > 0 ? (MMULT * (x - p0x)) / h : 0); + s32 t2 = t * t / MMULT; + s32 t3 = t2 * t / MMULT; + s32 h00 = 2*t3 - 3*t2 + MMULT; + s32 h10 = t3 - 2*t2 + t; + s32 h01 = -2*t3 + 3*t2; + s32 h11 = t3 - t2; + y = p0y * h00 + h * (m0 * h10 / MMULT) + p3y * h01 + h * (m3 * h11 / MMULT); + y /= MMULT; + return y; + } + } + return 0; +} +#endif + +int intpol(int x, uint8_t idx) // -100, -75, -50, -25, 0 ,25 ,50, 75, 100 +{ +#if defined(PCBTARANIS) + CurveInfo &crv = g_model.curves[idx]; + int8_t *points = curveAddress(idx); + uint8_t count = crv.points+5; + bool custom = (crv.type == CURVE_TYPE_CUSTOM); +#else CurveInfo crv = curveInfo(idx); + int8_t *points = crv.crv; + uint8_t count = crv.points; + bool custom = crv.custom; +#endif int16_t erg = 0; - x+=RESXu; - if (x < 0) { - erg = (int16_t)crv.crv[0] * (RESX/4); + x += RESXu; + + if (x <= 0) { + erg = (int16_t)points[0] * (RESX/4); } else if (x >= (RESX*2)) { - erg = (int16_t)crv.crv[crv.points-1] * (RESX/4); + erg = (int16_t)points[count-1] * (RESX/4); } else { uint16_t a=0, b=0; uint8_t i; - if (crv.custom) { - for (i=0; i 0 && x < 0) + x = (x * (256 - curveParam)) >> 8; + else if (curveParam < 0 && x > 0) + x = (x * (256 + curveParam)) >> 8; + return x; + } + + case CURVE_REF_EXPO: + return expo(x, GET_GVAR(curve.value, -100, 100, s_perout_flight_phase)); + + case CURVE_REF_FUNC: + switch(curve.value) { + case CURVE_X_GT0: + if (x < 0) x = 0; //x|x>0 + return x; + case CURVE_X_LT0: + if (x > 0) x = 0; //x|x<0 + return x; + case CURVE_ABS_X: // x|abs(x) + return abs(x); + case CURVE_F_GT0: //f|f>0 + return x > 0 ? RESX : 0; + case CURVE_F_LT0: //f|f<0 + return x < 0 ? -RESX : 0; + case CURVE_ABS_F: //f|abs(f) + return x > 0 ? RESX : -RESX; + } + break; + + case CURVE_REF_CUSTOM: + { + int curveParam = curve.value; + if (curveParam < 0) { + x = -x; + curveParam = -curveParam; + } + if (curveParam > 0 && curveParam <= MAX_CURVES) { + return applyCustomCurve(x, curveParam - 1); + } + break; + } + } + + return x; +} + +int applyCustomCurve(int x, uint8_t idx) +{ + CurveInfo &crv = g_model.curves[idx]; + if (crv.smooth) + return hermite_spline(x, idx); + else + return intpol(x, idx); +} + +#else +int applyCurve(int x, int8_t idx) { /* already tried to have only one return at the end */ switch(idx) { @@ -543,8 +823,9 @@ int16_t applyCurve(int16_t x, int8_t idx) x = -x; idx = -idx + CURVE_BASE - 1; } - return intpol(x, idx - CURVE_BASE); + return applyCustomCurve(x, idx - CURVE_BASE); } +#endif #else #define applyCurve(x, idx) (x) #endif @@ -592,7 +873,7 @@ int16_t applyCurve(int16_t x, int8_t idx) // x 0 to 1024; // k 0 to 100; // output between 0 and 1024 -uint16_t expou(uint16_t x, uint16_t k) +unsigned int expou(unsigned int x, unsigned int k) { #if defined(EXTENDED_EXPO) bool extended; @@ -627,11 +908,11 @@ uint16_t expou(uint16_t x, uint16_t k) return value>>8; } -int16_t expo(int16_t x, int16_t k) +int expo(int x, int k) { if (k == 0) return x; - int16_t y; - bool neg = x < 0; + int y; + bool neg = (x < 0); if (neg) x = -x; if (k<0) { @@ -643,10 +924,12 @@ int16_t expo(int16_t x, int16_t k) return neg? -y : y; } -void applyExpos(int16_t *anas, uint8_t mode) +void applyExpos(int16_t *anas, uint8_t mode APPLY_EXPOS_EXTRA_PARAMS) { +#if !defined(PCBTARANIS) int16_t anas2[NUM_INPUTS]; // values before expo, to ensure same expo base when multiple expo lines are used memcpy(anas2, anas, sizeof(anas2)); +#endif int8_t cur_chn = -1; @@ -654,29 +937,65 @@ void applyExpos(int16_t *anas, uint8_t mode) #if defined(BOLD_FONT) if (mode==e_perout_mode_normal) swOn[i].activeExpo = false; #endif - ExpoData &ed = g_model.expoData[i]; - if (ed.mode==0) break; // end of list - if (ed.chn == cur_chn) + ExpoData * ed = expoAddress(i); + if (!EXPO_VALID(ed)) break; // end of list + if (ed->chn == cur_chn) continue; - if (ed.phases & (1<phases & (1<=0 && (ed.mode&2))) { + if (getSwitch(ed->swtch)) { +#if defined(PCBTARANIS) + int v = (ed->srcRaw == ovwrIdx ? ovwrValue : getValue(ed->srcRaw)); + if (ed->srcRaw != ovwrIdx && ed->srcRaw >= MIXSRC_FIRST_TELEM && ed->scale > 0) { + v = limit(-1024, int((v * 1024) / convertTelemValue(ed->srcRaw-MIXSRC_FIRST_TELEM+1, ed->scale)), 1024); + } +#else + int16_t v = anas2[ed->chn]; +#endif + if (EXPO_MODE_ENABLE(ed, v)) { #if defined(BOLD_FONT) if (mode==e_perout_mode_normal) swOn[i].activeExpo = true; #endif - cur_chn = ed.chn; - int8_t curveParam = ed.curveParam; + cur_chn = ed->chn; + + //========== CURVE================= +#if defined(PCBTARANIS) + if (ed->curve.value) { + v = applyCurve(v, ed->curve); + } +#else + int8_t curveParam = ed->curveParam; if (curveParam) { - if (ed.curveMode == MODE_CURVE) + if (ed->curveMode == MODE_CURVE) v = applyCurve(v, curveParam); else v = expo(v, GET_GVAR(curveParam, -100, 100, s_perout_flight_phase)); } - int16_t weight = GET_GVAR(ed.weight, 0, 100, s_perout_flight_phase); +#endif + + //========== WEIGHT =============== + int16_t weight = GET_GVAR(ed->weight, MIN_EXPO_WEIGHT, 100, s_perout_flight_phase); weight = calc100to256(weight); v = ((int32_t)v * weight) >> 8; + +#if defined(PCBTARANIS) + //========== OFFSET =============== + int16_t offset = GET_GVAR(ed->offset, -100, 100, s_perout_flight_phase); + if (offset) v += calc100toRESX(offset); + + //========== TRIMS =============== + if (!(mode & e_perout_mode_notrims)) { + int8_t input_trim = ed->carryTrim; + if (input_trim < TRIM_ON) + input_trim = -input_trim - 1; + else if (input_trim == TRIM_ON && ed->srcRaw >= MIXSRC_Rud && ed->srcRaw <= MIXSRC_Ail) + input_trim = ed->srcRaw - MIXSRC_Rud; + else + input_trim = -1; + if (input_trim >= 0) v += trims[input_trim]; + } +#endif + anas[cur_chn] = v; } } @@ -788,9 +1107,20 @@ int8_t calcRESXto100(int16_t x) int16_t applyLimits(uint8_t channel, int32_t value) { LimitData * lim = limitAddress(channel); - int16_t ofs = calc1000toRESX(lim->offset); // multiply to 1.24 to get range (-1024..1024) - int16_t lim_p = calc100toRESX(lim->max + 100); - int16_t lim_n = calc100toRESX(lim->min - 100); //multiply by 10.24 to get same range (-1024..1024) + +#if defined(PCBTARANIS) + if (lim->curve) { + // TODO we loose precision here, applyCustomCurve could work with int32_t on ARM boards... + if (lim->curve > 0) + value = 256 * applyCustomCurve(value/256, lim->curve-1); + else + value = 256 * applyCustomCurve(-value/256, -lim->curve-1); + } +#endif + + int16_t ofs = LIMIT_OFS_RESX(lim); + int16_t lim_p = LIMIT_MAX_RESX(lim); + int16_t lim_n = LIMIT_MIN_RESX(lim); if (ofs > lim_p) ofs = lim_p; if (ofs < lim_n) ofs = lim_n; @@ -853,80 +1183,111 @@ int16_t cyc_anas[3] = {0}; getvalue_t getValue(uint8_t i) { - /*srcRaw is shifted +1!*/ + if (i==MIXSRC_NONE) return 0; - if (i DELAY_SWITCH_3POS)) { \ + newPos |= (1 << (sw ## 0 - SW_SA0 + 1)); \ + switchesMidposStart[idx] = 0; \ + } \ + else { \ + if (!switchesMidposStart[idx]) { \ + switchesMidposStart[idx] = get_tmr10ms(); \ + } \ + newPos |= (switchesPos & (0x7 << (sw ## 0 - SW_SA0))); \ + } +#define SWITCH_POSITION(sw) (switchesPos & (1<<(sw))) +void get3POSSwitchesPosition() +{ + uint32_t newPos = 0; + CHECK_3POS(0, SW_SA); + CHECK_3POS(1, SW_SB); + CHECK_3POS(2, SW_SC); + CHECK_3POS(3, SW_SD); + CHECK_3POS(4, SW_SE); + CHECK_2POS(SW_SF); + CHECK_3POS(5, SW_SG); + CHECK_2POS(SW_SH); + switchesPos = newPos; +} +#else +#define get3POSSwitchesPosition() +#endif + int16_t csLastValue[NUM_CSW]; #define CS_LAST_VALUE_INIT -32768 bool getSwitch(int8_t swtch) { bool result; - if (swtch == 0) + if (swtch == SWSRC_NONE) return true; uint8_t cs_idx = abs(swtch); @@ -952,7 +1354,11 @@ bool getSwitch(int8_t swtch) result = true; } else if (cs_idx <= MAX_PSWITCH) { +#if defined(PCBTARANIS) + result = SWITCH_POSITION(cs_idx-SWSRC_SA0); +#else result = switchState((EnumKeys)(SW_BASE+cs_idx-1)); +#endif } else { cs_idx -= MAX_PSWITCH+1; @@ -990,10 +1396,10 @@ bool getSwitch(int8_t swtch) result = csLastValue[cs_idx] <= 0; } else { - getvalue_t x = getValue(cs->v1-1); + getvalue_t x = getValue(cs->v1); getvalue_t y; if (s == CS_VCOMP) { - y = getValue(cs->v2-1); + y = getValue(cs->v2); switch (cs->func) { case CS_EQUAL: @@ -1130,7 +1536,7 @@ int8_t getMovedSwitch() for (uint8_t i=0; i> (i*2); - uint8_t next = (1024+getValue(MIXSRC_SA+i-1)) / 1024; + uint8_t next = (1024+getValue(MIXSRC_SA+i)) / 1024; if (prev != next) { switches_states = (switches_states & (~mask)) | (next << (i*2)); if (i<5) @@ -1175,17 +1581,30 @@ int8_t getMovedSwitch() } #if defined(AUTOSOURCE) -int8_t getMovedSource() +int8_t getMovedSource(GET_MOVED_SOURCE_PARAMS) { - static tmr10ms_t s_move_last_time = 0; - static int16_t sourcesStates[NUM_STICKS+NUM_POTS]; - int8_t result = 0; + static tmr10ms_t s_move_last_time = 0; - for (uint8_t i=0; i 512) { - result = 1+i; - break; +#if defined(PCBTARANIS) + static int16_t inputsStates[MAX_INPUTS]; + if (min <= MIXSRC_FIRST_INPUT) { + for (uint8_t i=0; i 512) { + result = MIXSRC_FIRST_INPUT+i; + break; + } + } + } +#endif + + static int16_t sourcesStates[NUM_STICKS+NUM_POTS]; + if (result == 0) { + for (uint8_t i=0; i 512) { + result = MIXSRC_Rud+i; + break; + } } } @@ -1195,6 +1614,9 @@ int8_t getMovedSource() } if (result || recent) { +#if defined(PCBTARANIS) + memcpy(inputsStates, anas, sizeof(inputsStates)); +#endif memcpy(sourcesStates, calibratedStick, sizeof(sourcesStates)); } @@ -1306,6 +1728,20 @@ void incRotaryEncoder(uint8_t idx, int8_t inc) #endif #if defined(GVARS) + +#if defined(PCBSTD) + #define SET_GVAR_VALUE(idx, phase, value) \ + (GVAR_VALUE(idx, phase) = value, eeDirty(EE_MODEL)) +#else + #define SET_GVAR_VALUE(gvar, phase, value) \ + GVAR_VALUE(idx, phase) = value; \ + eeDirty(EE_MODEL); \ + if (g_model.gvars[idx].popup) { \ + s_gvar_last = idx; \ + s_gvar_timer = GVAR_DISPLAY_TIME; \ + } +#endif + #if defined(PCBSTD) int16_t getGVarValue(int16_t x, int16_t min, int16_t max) { @@ -1327,11 +1763,13 @@ int16_t getGVarValue(int16_t x, int16_t min, int16_t max) void setGVarValue(uint8_t idx, int8_t value) { if (GVAR_VALUE(idx, -1) != value) { - GVAR_VALUE(idx, -1) = value; - eeDirty(EE_MODEL); + SET_GVAR_VALUE(idx, -1, value); } } #else +uint8_t s_gvar_timer = 0; +uint8_t s_gvar_last = 0; + uint8_t getGVarFlightPhase(uint8_t phase, uint8_t idx) { for (uint8_t i=0; iv1 - MIXSRC_FIRST_TELEM + 1, cs->v2); +#else if (cswFamily(cs->func)==CS_VOFS) val = convertTelemValue(cs->v1 - MIXSRC_FIRST_TELEM + 1, 128+cs->v2); else val = convertTelemValue(cs->v1 - MIXSRC_FIRST_TELEM + 1, 128+cs->v2) - convertTelemValue(cs->v1 - MIXSRC_FIRST_TELEM + 1, 128); +#endif return val; } @@ -1495,16 +1959,22 @@ FORCEINLINE void convertUnit(getvalue_t & val, uint8_t & unit) } #endif -#define INAC_DEVISOR 512 // bypass splash screen with stick movement -#define INAC_DEV_SHIFT 9 // shift right value for stick movement -uint8_t inputsMoveValue() +#define INAC_DEV_SHIFT 6 // shift right value for stick movement +bool inputsMoved() { uint8_t sum = 0; for (uint8_t i=0; i> INAC_DEV_SHIFT; for (uint8_t i=0; i> 10; - return sum; + + if (abs((int8_t)(sum-inactivity.sum)) > 1) { + inactivity.sum = sum; + return true; + } + else { + return false; + } } void checkBacklight() @@ -1518,9 +1988,7 @@ void checkBacklight() uint8_t x = g_blinkTmr10ms; if (tmr10ms != x) { tmr10ms = x; - uint8_t tsum = inputsMoveValue(); - if (tsum != inactivity.sum) { - inactivity.sum = tsum; + if (inputsMoved()) { inactivity.counter = 0; if (g_eeGeneral.backlightMode & e_backlight_mode_sticks) backlightOn(); @@ -1544,6 +2012,20 @@ void backlightOn() lightOffCounter = ((uint16_t)g_eeGeneral.lightAutoOff*250) << 1; } +#if MENUS_LOCK == 1 +bool readonly = true; +bool readonlyUnlocked() +{ + if (readonly) { + POPUP_WARNING(STR_MODS_FORBIDDEN); + return false; + } + else { + return true; + } +} +#endif + #if defined(SPLASH) #define SPLASH_NEEDED() (!IS_DSM2_PROTOCOL(g_model.protocol) && !g_eeGeneral.splashMode) @@ -1556,6 +2038,14 @@ inline void Splash() #else lcd_img(0, 0, splash_lbm, 0, 0); #endif + +#if MENUS_LOCK == 1 + if (readonly == false) { + lcd_filled_rect((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(); } @@ -1578,7 +2068,7 @@ void doSplash() getADC(); // init ADC array - uint8_t inacSum = inputsMoveValue(); + inputsMoved(); tmr10ms_t tgtime = get_tmr10ms() + SPLASH_TIMEOUT; while (tgtime != get_tmr10ms()) { @@ -1590,12 +2080,10 @@ void doSplash() getADC(); - uint8_t tsum = inputsMoveValue(); - #if defined(FSPLASH) || defined(XSPLASH) if (!(g_eeGeneral.splashMode & 0x04)) #endif - if (keyDown() || tsum!=inacSum) return; // wait for key release + if (keyDown() || inputsMoved()) return; if (pwrCheck()==e_power_off) return; @@ -1744,7 +2232,10 @@ void alert(const pm_char * t, const pm_char *s MESSAGE_SOUND_ARG) { SIMU_SLEEP(1); - if (pwrCheck() == e_power_off) return; + if (pwrCheck() == e_power_off) { + // the radio has been powered off during the ALERT + pwrOff(); // turn power off now + } if (keyDown()) return; // wait for key release @@ -1816,7 +2307,7 @@ uint8_t checkTrim(uint8_t event) if (k>=0 && k<8 && !IS_KEY_BREAK(event)) { #endif // LH_DWN LH_UP LV_DWN LV_UP RV_DWN RV_UP RH_DWN RH_UP - uint8_t idx = CONVERT_MODE(1+(uint8_t)k/2) - 1; + uint8_t idx = CONVERT_MODE((uint8_t)k/2); uint8_t phase; int16_t before; bool thro; @@ -1871,8 +2362,7 @@ uint8_t checkTrim(uint8_t event) #if defined(GVARS) if (TRIM_REUSED()) { - GVAR_VALUE(trimGvar[idx], phase) = after; - eeDirty(EE_MODEL); + SET_GVAR_VALUE(trimGvar[idx], phase, after); } else { setTrimValue(phase, idx, after); @@ -2184,20 +2674,6 @@ uint16_t isqrt32(uint32_t n) } #endif -// static variables used in perOut - moved here so they don't interfere with the stack -// It's also easier to initialize them here. -int16_t rawAnas [NUM_INPUTS] = {0}; -int16_t anas [NUM_INPUTS] = {0}; -int16_t trims[NUM_STICKS] = {0}; -int32_t chans[NUM_CHNOUT] = {0}; -BeepANACenter bpanaCenter = 0; -struct t_inactivity inactivity = {0}; - -int24_t act [MAX_MIXERS] = {0}; -SwOn swOn [MAX_MIXERS]; // TODO better name later... - -uint8_t mixWarning; - FORCEINLINE void evalTrims() { uint8_t phase = s_perout_flight_phase; @@ -2219,26 +2695,26 @@ FORCEINLINE void evalTrims() } } -BeepANACenter evalSticks(uint8_t mode) +void evalInputs(uint8_t mode) { BeepANACenter anaCenter = 0; #if defined(HELI) uint16_t d = 0; if (g_model.swashR.value) { - uint32_t v = (int32_t(calibratedStick[ELE_STICK])*calibratedStick[ELE_STICK] + - int32_t(calibratedStick[AIL_STICK])*calibratedStick[AIL_STICK]); + uint32_t v = (int32_t(calibratedStick[ELE_STICK])*calibratedStick[ELE_STICK] + int32_t(calibratedStick[AIL_STICK])*calibratedStick[AIL_STICK]); uint32_t q = calc100toRESX(g_model.swashR.value); q *= q; - if (v>q) + if (v > q) { d = isqrt32(v); + } } #endif for (uint8_t i=0; i [-1024..1024] - uint8_t ch = (i < NUM_STICKS ? CONVERT_MODE(i+1) - 1 : i); + uint8_t ch = (i < NUM_STICKS ? CONVERT_MODE(i) : i); #if defined(ROTARY_ENCODERS) int16_t v = ((i < NUM_STICKS+NUM_POTS) ? anaIn(i) : getRotaryEncoder(i-(NUM_STICKS+NUM_POTS))); @@ -2255,11 +2731,11 @@ BeepANACenter evalSticks(uint8_t mode) } #endif - if(v < -RESX) v = -RESX; - if(v > RESX) v = RESX; + if (v < -RESX) v = -RESX; + if (v > RESX) v = RESX; #if defined(PCBTARANIS) - if (i == POT1 || i == SLIDER1) + if (i==POT1 || i==SLIDER1) v = -v; #endif @@ -2281,11 +2757,23 @@ BeepANACenter evalSticks(uint8_t mode) BeepANACenter mask = (BeepANACenter)1 << ch; if (i < NUM_STICKS+NUM_POTS) { + calibratedStick[ch] = v; //for show in expo // filtering for center beep uint8_t tmp = (uint16_t)abs(v) / 16; +#if defined(CPUARM) + if (mode == e_perout_mode_normal) { + if (tmp==0 || (tmp==1 && (bpanaCenter & mask))) { + anaCenter |= mask; + if ((g_model.beepANACenter & mask) && !(bpanaCenter & mask)) { + AUDIO_POT_MIDDLE(i); + } + } + } +#else if (tmp <= 1) anaCenter |= (tmp==0 ? mask : (bpanaCenter & mask)); +#endif } else { // rotary encoders @@ -2305,26 +2793,37 @@ BeepANACenter evalSticks(uint8_t mode) case 1: v += vStud; break; // add-mode case 2: v = vStud; break; // subst-mode } +#if defined(PCBTARANIS) + calibratedStick[ch] = v; +#endif } } -#ifdef HELI +#if defined(HELI) if (d && (ch==ELE_STICK || ch==AIL_STICK)) v = (int32_t(v)*calc100toRESX(g_model.swashR.value))/int32_t(d); #endif +#if !defined(PCBTARANIS) rawAnas[ch] = v; anas[ch] = v; //set values for mixer +#endif } } - /* EXPOs */ - applyExpos(anas, mode); - /* TRIMs */ evalTrims(); - return anaCenter; + /* EXPOs */ + applyExpos(anas, mode); + + if (mode == e_perout_mode_normal) { +#if !defined(CPUARM) + anaCenter &= g_model.beepANACenter; + if(((bpanaCenter ^ anaCenter) & anaCenter)) AUDIO_POT_MIDDLE(); +#endif + bpanaCenter = anaCenter; + } } #ifdef DEBUG @@ -2353,30 +2852,30 @@ PLAY_FUNCTION(playValue, uint8_t idx) getvalue_t val = getValue(idx); switch (idx) { - case MIXSRC_FIRST_TELEM-1+TELEM_TX_VOLTAGE-1: + case MIXSRC_FIRST_TELEM+TELEM_TX_VOLTAGE-1: PLAY_NUMBER(val, 1+UNIT_VOLTS, PREC1); break; - case MIXSRC_FIRST_TELEM-1+TELEM_TM1-1: - case MIXSRC_FIRST_TELEM-1+TELEM_TM2-1: + case MIXSRC_FIRST_TELEM+TELEM_TM1-1: + case MIXSRC_FIRST_TELEM+TELEM_TM2-1: PLAY_DURATION(val); break; #if defined(FRSKY) - case MIXSRC_FIRST_TELEM-1+TELEM_RSSI_TX-1: + case MIXSRC_FIRST_TELEM+TELEM_RSSI_TX-1: #if defined(PCBTARANIS) // On Taranis RSSI_TX is used for SWR PLAY_NUMBER(val, 0, 0); break; #endif - case MIXSRC_FIRST_TELEM-1+TELEM_RSSI_RX-1: + case MIXSRC_FIRST_TELEM+TELEM_RSSI_RX-1: PLAY_NUMBER(val, 1+UNIT_DBM, 0); break; - case MIXSRC_FIRST_TELEM-1+TELEM_MIN_A1-1: - case MIXSRC_FIRST_TELEM-1+TELEM_MIN_A2-1: + case MIXSRC_FIRST_TELEM+TELEM_MIN_A1-1: + case MIXSRC_FIRST_TELEM+TELEM_MIN_A2-1: idx -= TELEM_MIN_A1-TELEM_A1; // no break - case MIXSRC_FIRST_TELEM-1+TELEM_A1-1: - case MIXSRC_FIRST_TELEM-1+TELEM_A2-1: - idx -= (MIXSRC_FIRST_TELEM-1+TELEM_A1-1); + case MIXSRC_FIRST_TELEM+TELEM_A1-1: + case MIXSRC_FIRST_TELEM+TELEM_A2-1: + idx -= (MIXSRC_FIRST_TELEM+TELEM_A1-1); // A1 and A2 { if (TELEMETRY_STREAMING()) { @@ -2390,45 +2889,45 @@ PLAY_FUNCTION(playValue, uint8_t idx) break; } - case MIXSRC_FIRST_TELEM-1+TELEM_CELL-1: + case MIXSRC_FIRST_TELEM+TELEM_CELL-1: PLAY_NUMBER(val/10, 1+UNIT_VOLTS, PREC1); break; - case MIXSRC_FIRST_TELEM-1+TELEM_VFAS-1: - case MIXSRC_FIRST_TELEM-1+TELEM_CELLS_SUM-1: + case MIXSRC_FIRST_TELEM+TELEM_VFAS-1: + case MIXSRC_FIRST_TELEM+TELEM_CELLS_SUM-1: PLAY_NUMBER(val, 1+UNIT_VOLTS, PREC1); break; - case MIXSRC_FIRST_TELEM-1+TELEM_CURRENT-1: - case MIXSRC_FIRST_TELEM-1+TELEM_MAX_CURRENT-1: + case MIXSRC_FIRST_TELEM+TELEM_CURRENT-1: + case MIXSRC_FIRST_TELEM+TELEM_MAX_CURRENT-1: PLAY_NUMBER(val, 1+UNIT_AMPS, PREC1); break; - case MIXSRC_FIRST_TELEM-1+TELEM_ACCx-1: - case MIXSRC_FIRST_TELEM-1+TELEM_ACCy-1: - case MIXSRC_FIRST_TELEM-1+TELEM_ACCz-1: + case MIXSRC_FIRST_TELEM+TELEM_ACCx-1: + case MIXSRC_FIRST_TELEM+TELEM_ACCy-1: + case MIXSRC_FIRST_TELEM+TELEM_ACCz-1: PLAY_NUMBER(val/10, 1+UNIT_G, PREC1); break; - case MIXSRC_FIRST_TELEM-1+TELEM_VSPD-1: + case MIXSRC_FIRST_TELEM+TELEM_VSPD-1: PLAY_NUMBER(val/10, 1+UNIT_METERS_PER_SECOND, PREC1); break; - case MIXSRC_FIRST_TELEM-1+TELEM_CONSUMPTION-1: + case MIXSRC_FIRST_TELEM+TELEM_CONSUMPTION-1: PLAY_NUMBER(val, 1+UNIT_MAH, 0); break; - case MIXSRC_FIRST_TELEM-1+TELEM_POWER-1: + case MIXSRC_FIRST_TELEM+TELEM_POWER-1: PLAY_NUMBER(val, 1+UNIT_WATTS, 0); break; - case MIXSRC_FIRST_TELEM-1+TELEM_ALT-1: + case MIXSRC_FIRST_TELEM+TELEM_ALT-1: #if defined(PCBTARANIS) PLAY_NUMBER(val/10, 1+UNIT_METERS, PREC1); break; #endif - case MIXSRC_FIRST_TELEM-1+TELEM_MIN_ALT-1: - case MIXSRC_FIRST_TELEM-1+TELEM_MAX_ALT-1: + case MIXSRC_FIRST_TELEM+TELEM_MIN_ALT-1: + case MIXSRC_FIRST_TELEM+TELEM_MAX_ALT-1: #if defined(WS_HOW_HIGH) if (IS_IMPERIAL_ENABLE() && IS_USR_PROTO_WS_HOW_HIGH()) PLAY_NUMBER(val, 1+UNIT_FEET, 0); @@ -2437,24 +2936,24 @@ PLAY_FUNCTION(playValue, uint8_t idx) PLAY_NUMBER(val, 1+UNIT_METERS, 0); break; - case MIXSRC_FIRST_TELEM-1+TELEM_RPM-1: - case MIXSRC_FIRST_TELEM-1+TELEM_MAX_RPM-1: + case MIXSRC_FIRST_TELEM+TELEM_RPM-1: + case MIXSRC_FIRST_TELEM+TELEM_MAX_RPM-1: PLAY_NUMBER(val, 1+UNIT_RPMS, 0); break; - case MIXSRC_FIRST_TELEM-1+TELEM_HDG-1: + case MIXSRC_FIRST_TELEM+TELEM_HDG-1: PLAY_NUMBER(val, 1+UNIT_DEGREES, 0); break; default: { uint8_t unit = 1; - if (idx < MIXSRC_GVAR1-1) + if (idx < MIXSRC_GVAR1) val = calcRESXto100(val); - if (idx >= MIXSRC_FIRST_TELEM-1+TELEM_ALT-1 && idx <= MIXSRC_FIRST_TELEM-1+TELEM_GPSALT-1) - unit = idx - (MIXSRC_FIRST_TELEM-1+TELEM_ALT-1); - else if (idx >= MIXSRC_FIRST_TELEM-1+TELEM_MAX_T1-1 && idx <= MIXSRC_FIRST_TELEM-1+TELEM_MAX_DIST-1) - unit = 3 + idx - (MIXSRC_FIRST_TELEM-1+TELEM_MAX_T1-1); + if (idx >= MIXSRC_FIRST_TELEM+TELEM_ALT-1 && idx <= MIXSRC_FIRST_TELEM+TELEM_GPSALT-1) + unit = idx - (MIXSRC_FIRST_TELEM+TELEM_ALT-1); + else if (idx >= MIXSRC_FIRST_TELEM+TELEM_MAX_T1-1 && idx <= MIXSRC_FIRST_TELEM+TELEM_MAX_DIST-1) + unit = 3 + idx - (MIXSRC_FIRST_TELEM+TELEM_MAX_T1-1); unit = pgm_read_byte(bchunit_ar+unit); PLAY_NUMBER(val, unit == UNIT_RAW ? 0 : unit+1, 0); @@ -2492,6 +2991,10 @@ inline void playCustomFunctionFile(CustomFnData *sd, uint8_t id) } #endif +#if defined(CPUARM) +bool evalFunctionsFirstTime = true; +#endif + void evalFunctions() { MASK_FUNC_TYPE newActiveFunctions = 0; @@ -2676,7 +3179,9 @@ void evalFunctions() else if (CFN_FUNC(sd) == FUNC_PLAY_SOUND || CFN_FUNC(sd) == FUNC_PLAY_TRACK || CFN_FUNC(sd) == FUNC_PLAY_VALUE) { tmr10ms_t tmr10ms = get_tmr10ms(); uint8_t repeatParam = CFN_PLAY_REPEAT(sd); - if (!lastFunctionTime[i] || (repeatParam && (signed)(tmr10ms-lastFunctionTime[i])>=500*repeatParam)) { + if (evalFunctionsFirstTime && repeatParam == CFN_PLAY_REPEAT_NOSTART) + lastFunctionTime[i] = tmr10ms; + if (!lastFunctionTime[i] || (repeatParam && repeatParam!=CFN_PLAY_REPEAT_NOSTART && (signed)(tmr10ms-lastFunctionTime[i])>=100*repeatParam)) { if (!IS_PLAYING(i+1)) { lastFunctionTime[i] = tmr10ms; if (CFN_FUNC(sd) == FUNC_PLAY_SOUND) { @@ -2757,12 +3262,12 @@ void evalFunctions() SET_GVAR(CFN_FUNC(sd)-FUNC_ADJUST_GV1, GVAR_VALUE(CFN_FUNC(sd)-FUNC_ADJUST_GV1, getGVarFlightPhase(s_perout_flight_phase, CFN_FUNC(sd)-FUNC_ADJUST_GV1)) + (CFN_PARAM(sd) ? +1 : -1), s_perout_flight_phase); } } - else if (CFN_PARAM(sd) >= MIXSRC_TrimRud-1 && CFN_PARAM(sd) <= MIXSRC_TrimAil-1) { - trimGvar[CFN_PARAM(sd)-MIXSRC_TrimRud+1] = CFN_FUNC(sd)-FUNC_ADJUST_GV1; + else if (CFN_PARAM(sd) >= MIXSRC_TrimRud && CFN_PARAM(sd) <= MIXSRC_TrimAil) { + trimGvar[CFN_PARAM(sd)-MIXSRC_TrimRud] = CFN_FUNC(sd)-FUNC_ADJUST_GV1; } #if defined(ROTARY_ENCODERS) - else if (CFN_PARAM(sd) >= MIXSRC_REa-1 && CFN_PARAM(sd) < MIXSRC_TrimRud-1) { - int8_t scroll = rePreviousValues[CFN_PARAM(sd)-MIXSRC_REa+1] - (g_rotenc[CFN_PARAM(sd)-MIXSRC_REa+1] / ROTARY_ENCODER_GRANULARITY); + else if (CFN_PARAM(sd) >= MIXSRC_REa && CFN_PARAM(sd) < MIXSRC_TrimRud) { + int8_t scroll = rePreviousValues[CFN_PARAM(sd)-MIXSRC_REa] - (g_rotenc[CFN_PARAM(sd)-MIXSRC_REa] / ROTARY_ENCODER_GRANULARITY); if (scroll) { SET_GVAR(CFN_FUNC(sd)-FUNC_ADJUST_GV1, GVAR_VALUE(CFN_FUNC(sd)-FUNC_ADJUST_GV1, getGVarFlightPhase(s_perout_flight_phase, CFN_FUNC(sd)-FUNC_ADJUST_GV1)) + scroll, s_perout_flight_phase); } @@ -2805,20 +3310,17 @@ void evalFunctions() for (uint8_t i=0; isrcRaw == 0) break; - uint8_t k = md->srcRaw - 1; - if (!(dirtyChannels & ((bitfield_channels_t)1 << md->destCh))) continue; // if this is the first calculation for the destination channel, initialize it with 0 (otherwise would be random) @@ -2920,26 +3420,30 @@ void perOut(uint8_t mode, uint8_t tick10ms) delayval_t mixEnabled = !(md->phases & (1 << s_perout_flight_phase)) && getSwitch(md->swtch); //========== VALUE =============== + uint8_t stickIndex = md->srcRaw - MIXSRC_Rud; getvalue_t v = 0; if (mode > e_perout_mode_inactive_phase) { - if (!mixEnabled || k >= NUM_STICKS || (k == THR_STICK && g_model.thrTrim)) { + if (!mixEnabled || stickIndex >= NUM_STICKS || (stickIndex == THR_STICK && g_model.thrTrim)) { continue; } else { - if (!(mode & e_perout_mode_nosticks)) v = anas[k]; + if (!(mode & e_perout_mode_nosticks)) v = anas[stickIndex]; } } else { - if (k < NUM_STICKS) { - v = md->noExpo ? rawAnas[k] : anas[k]; +#if !defined(PCBTARANIS) + if (stickIndex < NUM_STICKS) { + v = md->noExpo ? rawAnas[stickIndex] : anas[stickIndex]; } - else { - v = getValue(k); - if (k>=MIXSRC_CH1-1 && k<=MIXSRC_LAST_CH-1 && md->destCh != k-MIXSRC_CH1+1) { - if (dirtyChannels & ((bitfield_channels_t)1 << (k-MIXSRC_CH1+1))) + else +#endif + { + v = getValue(md->srcRaw); + if (md->srcRaw>=MIXSRC_CH1 && md->srcRaw<=MIXSRC_LAST_CH && md->destCh != md->srcRaw-MIXSRC_CH1) { + if (dirtyChannels & ((bitfield_channels_t)1 << (md->srcRaw-MIXSRC_CH1)) & (passDirtyChannels|~(((bitfield_channels_t) 1 << md->destCh)-1))) passDirtyChannels |= (bitfield_channels_t) 1 << md->destCh; - if (k-MIXSRC_CH1+1 < md->destCh || pass > 0) - v = chans[k-MIXSRC_CH1+1] >> 8; + if (md->srcRaw-MIXSRC_CH1 < md->destCh || pass > 0) + v = chans[md->srcRaw-MIXSRC_CH1] >> 8; } } if (!mixCondition) { @@ -2985,23 +3489,25 @@ void perOut(uint8_t mode, uint8_t tick10ms) #endif } - //========== OFFSET =============== +#if !defined(PCBTARANIS) // (because trims are taken into account by INPUTS on Taranis) if (apply_offset_and_curve) { + //========== OFFSET / SOURCE =============== int16_t offset = GET_GVAR(MD_OFFSET(md), GV_RANGELARGE_NEG, GV_RANGELARGE, s_perout_flight_phase); if (offset) v += calc100toRESX_16Bits(offset); - //========== TRIMS ================ + //========== TRIMS ================ if (!(mode & e_perout_mode_notrims)) { int8_t mix_trim = md->carryTrim; if (mix_trim < TRIM_ON) mix_trim = -mix_trim - 1; - else if (mix_trim == TRIM_ON && k < NUM_STICKS) - mix_trim = k; + else if (mix_trim == TRIM_ON && stickIndex < NUM_STICKS) + mix_trim = stickIndex; else mix_trim = -1; if (mix_trim >= 0) v += trims[mix_trim]; } } +#endif // saves 12 bytes code if done here and not together with weight; unknown reason int16_t weight = GET_GVAR(MD_WEIGHT(md), GV_RANGELARGE_NEG, GV_RANGELARGE, s_perout_flight_phase); @@ -3048,13 +3554,29 @@ void perOut(uint8_t mode, uint8_t tick10ms) } //========== CURVES =============== +#if defined(PCBTARANIS) + // TODO something cleaner ... + if (apply_offset_and_curve && md->curve.value) { + v = applyCurve(v, md->curve); + } +#else if (apply_offset_and_curve && md->curveParam && md->curveMode == MODE_CURVE) { v = applyCurve(v, md->curveParam); } +#endif //========== WEIGHT =============== int32_t dv = (int32_t) v * weight; - + + //========== OFFSET / AFTER =============== +#if defined(PCBTARANIS) + if (apply_offset_and_curve) { + int16_t offset = GET_GVAR(MD_OFFSET(md), GV_RANGELARGE_NEG, GV_RANGELARGE, s_perout_flight_phase); + if (offset) dv += calc100toRESX_16Bits(offset) << 8; + } +#endif + +#if !defined(PCBTARANIS) // TODO move before WEIGHT for readability //========== DIFFERENTIAL ========= if (md->curveMode == MODE_DIFFERENTIAL) { // @@@2 also recalculate curveParam to a 256 basis which ease the calculation later a lot @@ -3064,6 +3586,7 @@ void perOut(uint8_t mode, uint8_t tick10ms) else if (curveParam < 0 && dv > 0) dv = (dv * (256 + curveParam)) >> 8; } +#endif int32_t *ptr = &chans[md->destCh]; // Save calculating address several times @@ -3161,6 +3684,8 @@ void doMixerCalculations() // therefore forget the exact calculation and use only 1 instead; good compromise lastTMR = tmr10ms; + get3POSSwitchesPosition(); + getADC(); #if defined(PCBSKY9X) && !defined(REVA) && !defined(SIMU) @@ -3278,17 +3803,18 @@ void doMixerCalculations() uint8_t ch = g_model.thrTraceSrc-NUM_POTS-1; val = channelOutputs[ch]; - int16_t gModelMax = calc100toRESX(limitAddress(ch)->max)+1024; - int16_t gModelMin = calc100toRESX(limitAddress(ch)->min)-1024; + LimitData *lim = limitAddress(ch); + int16_t gModelMax = LIMIT_MAX_RESX(lim); + int16_t gModelMin = LIMIT_MIN_RESX(lim); - if (limitAddress(ch)->revert) + if (lim->revert) val = -val + gModelMax; else val = val - gModelMin; #if defined(PPM_LIMITS_SYMETRICAL) - if (limitAddress(ch)->symetrical) - val -= calc1000toRESX(limitAddress(ch)->offset); + if (lim->symetrical) + val -= calc1000toRESX(lim->offset); #endif // @@@ open.20.fsguruh optimized calculation; now *8 /8 instead of 10 base; (*16/16 already cause a overrun; unsigned calculation also not possible, because v may be negative) gModelMax -= gModelMin; // we compare difference between Max and Mix for recaling needed; Max and Min are shifted to 0 by default @@ -3299,7 +3825,7 @@ void doMixerCalculations() val = (val << 3) / (gModelMax); // rescaling only needed if Min, Max differs // if (gModelMax!=2048) val = (int32_t) (val << 11) / (gModelMax); // recaling only needed if Min, Max differs - // val = val * 10 / (10+(limitAddress(ch)->max-limitAddress(ch)->min)/20); + // val = val * 10 / (10+(lim->max-lim->min)/20); if (val<0) val=0; // prevent val be negative, which would corrupt throttle trace and timers; could occur if safetyswitch is smaller than limits } else { @@ -3389,31 +3915,28 @@ void doMixerCalculations() switch(timerState->state) { case TMR_RUNNING: - if (tv && newTimerVal>=(int16_t)tv) timerState->state = TMR_BEEPING; + if (tv && newTimerVal>=(int16_t)tv) timerState->state = TMR_NEGATIVE; break; - case TMR_BEEPING: + case TMR_NEGATIVE: if (newTimerVal >= (int16_t)tv + MAX_ALERT_TIME) timerState->state = TMR_STOPPED; break; } - if (tv) newTimerVal = tv - newTimerVal; //if counting backwards - display backwards + if (tv) newTimerVal = tv - newTimerVal; // if counting backwards - display backwards - if (newTimerVal != timerState->val) { // beep only if seconds advance + if (newTimerVal != timerState->val) { timerState->val = newTimerVal; if (timerState->state == TMR_RUNNING) { - if (g_model.timers[i].countdownBeep && g_model.timers[i].start) { // beep when 30, 15, 10, 5,4,3,2,1 seconds remaining - if (newTimerVal==30) AUDIO_TIMER_30(); // beep three times - if (newTimerVal==20) AUDIO_TIMER_20(); // beep two times - if (newTimerVal<=10) AUDIO_TIMER_LT10(newTimerVal); + if (g_model.timers[i].countdownBeep && g_model.timers[i].start) { + if (newTimerVal==30) AUDIO_TIMER_30(); + if (newTimerVal==20) AUDIO_TIMER_20(); + if (newTimerVal==00) AUDIO_TIMER_00(g_model.timers[i].countdownBeep); + if (newTimerVal<=10) AUDIO_TIMER_LT10(g_model.timers[i].countdownBeep, newTimerVal); } - - if (g_model.timers[i].minuteBeep && (newTimerVal % 60)==0) { // short beep every minute + if (g_model.timers[i].minuteBeep && (newTimerVal % 60)==0) { AUDIO_TIMER_MINUTE(newTimerVal); } } - else if (timerState->state == TMR_BEEPING) { - AUDIO_WARNING1(); - } } } } @@ -3847,27 +4370,37 @@ void perMain() StickScrollAllowed = 1 ; #endif - lcd_clear(); const char *warn = s_warning; uint8_t menu = s_menu_count; if (usbPlugged()) { + lcd_clear(); menuMainView(0); } else { - g_menuStack[g_menuStackPtr]((warn || menu) ? 0 : evt); - if (warn) DISPLAY_WARNING(evt); + if (!LCD_LOCKED()) { + lcd_clear(); + g_menuStack[g_menuStackPtr]((warn || menu) ? 0 : evt); + if (warn) DISPLAY_WARNING(evt); #if defined(NAVIGATION_MENUS) - if (menu) { - const char * result = displayMenu(evt); - if (result) { - menuHandler(result); - putEvent(EVT_MENU_UP); + if (menu) { + const char * result = displayMenu(evt); + if (result) { + menuHandler(result); + putEvent(EVT_MENU_UP); + } } - } #endif +#if defined(LUA) + evt = 0; +#endif + } } +#if defined(LUA) + luaTask(evt); +#endif + drawStatusLine(); lcdRefresh(); @@ -4109,7 +4642,7 @@ ISR(USART0_UDRE_vect) void instantTrim() { - evalSticks(e_perout_mode_notrainer); + evalInputs(e_perout_mode_notrainer); for (uint8_t i=0; ioffset = (ld->revert) ? -zero : zero; + resumeMixerCalculations(); + eeDirty(EE_MODEL); +} + void moveTrimsToOffsets() // copy state of 3 primary to subtrim { int16_t zeros[NUM_CHNOUT]; @@ -4204,6 +4759,10 @@ uint16_t stack_free(uint8_t tid) uint16_t size; switch(tid) { + case 0: + stack = menusStack; + size = MENUS_STACK_SIZE; + break; case 1: stack = mixerStack; size = MIXER_STACK_SIZE; @@ -4213,26 +4772,15 @@ uint16_t stack_free(uint8_t tid) size = AUDIO_STACK_SIZE; break; default: - stack = menusStack; - size = MENUS_STACK_SIZE; - break; + return 0; } uint16_t i=0; for (; i #include -#if defined(PCBTARANIS) -#define IF_9X(x) -#else -#define IF_9X(x) x, -#endif +// TODO change all IF_xxx by CASE_xxx when used with a comma! #if defined(PCBSKY9X) #define IF_PCBSKY9X(x) x, @@ -55,11 +51,17 @@ #endif #if defined(PCBTARANIS) -#define IF_PCBTARANIS() true +#define IS_PCBTARANIS() true +#define IF_PCBTARANIS(x) (x) #define CASE_PCBTARANIS(x) x, +#define IF_9X(x) (0) +#define CASE_9X(x) #else -#define IF_PCBTARANIS() false +#define IS_PCBTARANIS() false +#define IF_PCBTARANIS(x) (0) #define CASE_PCBTARANIS(x) +#define IF_9X(x) (x) +#define CASE_9X(x) x, #endif #if defined(CPUARM) @@ -68,6 +70,12 @@ #define IF_CPUARM(x) #endif +#if defined(LUA) +#define IF_LUA(x) x, +#else +#define IF_LUA(x) +#endif + #if defined(BATTGRAPH) || defined(PCBTARANIS) #define IF_BATTGRAPH(x) x, #else @@ -474,6 +482,13 @@ enum EnumKeys { #define LOAD_MODEL_BITMAP() #endif +#if defined(PCBTARANIS) + void loadCurves(); + #define LOAD_MODEL_CURVES() loadCurves() +#else + #define LOAD_MODEL_CURVES() +#endif + // TODO elsewhere ... #if defined(DSM2) #define DSM2_BIND_FLAG 0x80 @@ -549,13 +564,12 @@ extern const pm_uint8_t modn12x3[]; extern uint8_t stickMode; //convert from mode 1 to mode stickMode -//NOTICE! => 1..4 -> 1..4 -#define CONVERT_MODE(x) (((x)<=4) ? pgm_read_byte(modn12x3 + 4*stickMode + (x)-1) : (x) ) - +//NOTICE! => 0..3 -> 0..3 #define RUD_STICK 0 #define ELE_STICK 1 #define THR_STICK 2 #define AIL_STICK 3 +#define CONVERT_MODE(x) (((x)<=AIL_STICK) ? pgm_read_byte(modn12x3 + 4*stickMode + (x)) : (x) ) extern uint8_t channel_order(uint8_t x); @@ -752,7 +766,12 @@ extern uint8_t pxxFlag[NUM_MODULES]; #define LEN_STD_CHARS 40 #define ZCHAR_MAX (LEN_STD_CHARS + LEN_SPECIAL_CHARS) -extern char idx2char(int8_t idx); +char idx2char(int8_t idx); +#if defined(PCBTARANIS) +int8_t char2idx(char c); +void str2zchar(char *dest, const char *src, int size); +void zchar2str(char *dest, const char *src, int size); +#endif extern uint8_t s_evt; #define putEvent(evt) s_evt = evt @@ -816,6 +835,12 @@ extern uint8_t s_perout_flight_phase; #define bitfield_channels_t uint16_t #endif +#if defined(CPUARM) && !defined(SIMU) + extern unsigned char *heap; + extern int _end; + extern unsigned char *_estack; +#endif + void perOut(uint8_t mode, uint8_t tick10ms); void perMain(); NOINLINE void per10ms(); @@ -825,8 +850,15 @@ bool getSwitch(int8_t swtch); extern swstate_t switches_states; int8_t getMovedSwitch(); -#if defined(AUTOSOURCE) -int8_t getMovedSource(); + +#if defined(PCBTARANIS) + #define GET_MOVED_SOURCE_PARAMS uint8_t min + int8_t getMovedSource(GET_MOVED_SOURCE_PARAMS); + #define GET_MOVED_SOURCE(min, max) getMovedSource(min) +#else + #define GET_MOVED_SOURCE_PARAMS + int8_t getMovedSource(); + #define GET_MOVED_SOURCE(min, max) getMovedSource() #endif #if defined(FLIGHT_MODES) @@ -865,6 +897,9 @@ extern void setTrimValue(uint8_t phase, uint8_t idx, int16_t trim); void setGVarValue(uint8_t x, int16_t value, int8_t phase); #define GET_GVAR(x, min, max, p) getGVarValue(x, min, max, p) #define SET_GVAR(idx, val, p) setGVarValue(idx, val, p) + #define GVAR_DISPLAY_TIME 100 /*1 second*/; + extern uint8_t s_gvar_timer; + extern uint8_t s_gvar_last; #endif #else #define GET_GVAR(x, ...) (x) @@ -872,17 +907,17 @@ extern void setTrimValue(uint8_t phase, uint8_t idx, int16_t trim); #if defined(CPUARM) #define GV1_SMALL 128 - // define here range for ARM based controllers; could be nearly unlimited, but could cause problems in mixer calculation (overflows) - #define GV1_LARGE 512 + #define GV1_LARGE 4096 + #define GV_GET_GV1_VALUE(max) ( (max<=GV_RANGESMALL && min>=GV_RANGESMALL_NEG) ? GV1_SMALL : GV1_LARGE ) + #define GV_INDEX_CALCULATION(x,max) ( (max<=GV_RANGESMALL && min>=GV_RANGESMALL_NEG) ? (uint8_t) x-GV1_SMALL : ((x&(GV1_LARGE*2-1))-GV1_LARGE) ) #else #define GV1_SMALL 128 #define GV1_LARGE 256 + #define GV_GET_GV1_VALUE(max) ( (max<=GV_RANGESMALL) ? GV1_SMALL : GV1_LARGE ) + #define GV_INDEX_CALCULATION(x,max) ( (max<=GV1_SMALL) ? (uint8_t) x-GV1_SMALL : ((x&(GV1_LARGE*2-1))-GV1_LARGE) ) #endif #define GV_IS_GV_VALUE(x,min,max) ( (x>max) || (xCNT; } #elif defined(PCBSKY9X) static inline uint16_t getTmr2MHz() { return TC1->TC_CHANNEL[0].TC_CV; } #else @@ -974,6 +1009,16 @@ extern uint16_t lastMixerDuration; void doSplash(); #endif +#if MENUS_LOCK == 1 + extern bool readonly; + extern bool readonlyUnlocked(); + #define READ_ONLY() readonly + #define READ_ONLY_UNLOCKED() readonlyUnlocked() +#else + #define READ_ONLY() false + #define READ_ONLY_UNLOCKED() true +#endif + void checkLowEEPROM(); void checkTHR(); void checkSwitches(); @@ -1090,39 +1135,38 @@ void checkModelIdUnique(uint8_t id); #endif #if defined(CPUARM) -inline int16_t calc100to256_16Bits(register int16_t x) // @@@2 open.20.fsguruh: return x*2.56 + +inline int divRoundClosest(const int n, const int d) { - return ((int16_t) x * 256) / 100; + return ((n < 0) ^ (d < 0)) ? ((n - d/2)/d) : ((n + d/2)/d); } -inline int16_t calc100to256(register int8_t x) // @@@2 open.20.fsguruh: return x*2.56 +#define calc100to256_16Bits(x) calc100to256(x) +#define calc100toRESX_16Bits(x) calc100toRESX(x) + +inline int calc100to256(register int x) { - return ((int16_t) x * 256) / 100; + return divRoundClosest(x*256, 100); } -inline int16_t calc100toRESX_16Bits(register int16_t x) // @@@ open.20.fsguruh +inline int calc100toRESX(register int x) { - return x * 1024 / 100; + return divRoundClosest(x*RESX, 100); } -inline int32_t calc100toRESX(register int8_t x) +inline int calc1000toRESX(register int x) { - return x * 1024 / 100; + return divRoundClosest(x*RESX, 1000); } -inline int16_t calc1000toRESX(register int32_t x) // improve calc time by Pat MacKenzie +inline int calcRESXto1000(register int x) { - return x * 1024 / 1000; + return divRoundClosest(x*1000, RESX); } -inline int16_t calcRESXto1000(register int32_t x) +inline int calcRESXto100(register int x) { - return x * 1000 / 1024; -} - -inline int16_t calcRESXto100(register int32_t x) -{ - return x * 100 / 1024; + return divRoundClosest(x*100, RESX); } #else @@ -1154,20 +1198,35 @@ extern int16_t ex_chans[NUM_CHNOUT]; // Outputs (before LIMITS) of th extern int16_t channelOutputs[NUM_CHNOUT]; extern uint16_t BandGap; -#if defined(CPUARM) - #define NUM_INPUTS (NUM_STICKS) +#if defined(PCBTARANIS) + #define NUM_INPUTS (MAX_INPUTS) #else #define NUM_INPUTS (NUM_STICKS) #endif -extern int16_t expo(int16_t x, int16_t k); -extern int16_t intpol(int16_t, uint8_t); -extern int16_t applyCurve(int16_t, int8_t); -extern void applyExpos(int16_t *anas, uint8_t mode); -extern int16_t applyLimits(uint8_t channel, int32_t value); +int intpol(int x, uint8_t idx); +int expo(int x, int k); +int applyCurve(int x, int8_t idx); -extern uint16_t anaIn(uint8_t chan); -extern int16_t thrAnaIn(uint8_t chan); +#if defined(PCBTARANIS) + int applyCustomCurve(int x, uint8_t idx); +#else + #define applyCustomCurve(x, idx) intpol(x, idx) +#endif + +#if defined(PCBTARANIS) + #define APPLY_EXPOS_EXTRA_PARAMS_INC , uint8_t ovwrIdx=0, int16_t ovwrValue=0 + #define APPLY_EXPOS_EXTRA_PARAMS , uint8_t ovwrIdx, int16_t ovwrValue +#else + #define APPLY_EXPOS_EXTRA_PARAMS_INC + #define APPLY_EXPOS_EXTRA_PARAMS +#endif + +void applyExpos(int16_t *anas, uint8_t mode APPLY_EXPOS_EXTRA_PARAMS_INC); +int16_t applyLimits(uint8_t channel, int32_t value); + +uint16_t anaIn(uint8_t chan); +int16_t thrAnaIn(uint8_t chan); extern int16_t calibratedStick[NUM_STICKS+NUM_POTS]; #define FLASH_DURATION 20 /*200ms*/ @@ -1177,25 +1236,32 @@ extern uint16_t lightOffCounter; extern uint8_t flashCounter; extern uint8_t mixWarning; -extern PhaseData *phaseAddress(uint8_t idx); -extern ExpoData *expoAddress(uint8_t idx); -extern MixData *mixAddress(uint8_t idx); -extern LimitData *limitAddress(uint8_t idx); -extern int8_t *curveAddress(uint8_t idx); -extern CustomSwData *cswAddress(uint8_t idx); +PhaseData *phaseAddress(uint8_t idx); +ExpoData *expoAddress(uint8_t idx); +MixData *mixAddress(uint8_t idx); +LimitData *limitAddress(uint8_t idx); +int8_t *curveAddress(uint8_t idx); +CustomSwData *cswAddress(uint8_t idx); +#if !defined(PCBTARANIS) struct CurveInfo { int8_t *crv; uint8_t points; bool custom; }; extern CurveInfo curveInfo(uint8_t idx); +#endif -extern void deleteExpoMix(uint8_t expo, uint8_t idx); +extern int8_t s_currCh; +uint8_t getExpoMixCount(uint8_t expo); +void deleteExpoMix(uint8_t expo, uint8_t idx); +void insertExpoMix(uint8_t expo, uint8_t idx); +void applyDefaultTemplate(); -extern void incSubtrim(uint8_t idx, int16_t inc); -extern void instantTrim(); -extern void moveTrimsToOffsets(); +void incSubtrim(uint8_t idx, int16_t inc); +void instantTrim(); +void copyTrimsToOffset(uint8_t ch); +void moveTrimsToOffsets(); #if defined(CPUARM) #define ACTIVE_PHASES_TYPE uint16_t @@ -1255,6 +1321,10 @@ extern MASK_CFN_TYPE activeFnSwitches; extern MASK_FUNC_TYPE activeFunctions; extern tmr10ms_t lastFunctionTime[NUM_CFN]; +#if defined(CPUARM) +extern bool evalFunctionsFirstTime; +#endif + inline bool isFunctionActive(uint8_t func) { return activeFunctions & ((MASK_FUNC_TYPE)1 << (func-FUNC_TRAINER)); @@ -1319,10 +1389,30 @@ enum AUDIO_SOUNDS { #if defined(CPUARM) AU_TRIM_END, #endif - AU_POT_STICK_MIDDLE, +#if defined(PCBTARANIS) + AU_STICK1_MIDDLE, + AU_STICK2_MIDDLE, + AU_STICK3_MIDDLE, + AU_STICK4_MIDDLE, + AU_POT1_MIDDLE, + AU_POT2_MIDDLE, + AU_SLIDER1_MIDDLE, + AU_SLIDER2_MIDDLE, +#elif defined(CPUARM) + AU_STICK1_MIDDLE, + AU_STICK2_MIDDLE, + AU_STICK3_MIDDLE, + AU_STICK4_MIDDLE, + AU_POT1_MIDDLE, + AU_POT2_MIDDLE, + AU_POT3_MIDDLE, +#else + AU_POT_MIDDLE, +#endif AU_MIX_WARNING_1, AU_MIX_WARNING_2, AU_MIX_WARNING_3, + AU_TIMER_00, AU_TIMER_LT10, AU_TIMER_20, AU_TIMER_30, @@ -1395,6 +1485,58 @@ enum AUDIO_SOUNDS { #include "rtc.h" #endif +#if defined(LUA) + struct ScriptInput { + const char *name; + uint8_t type; + int16_t min; + int16_t max; + int16_t def; + }; + struct ScriptOutput { + const char *name; + int16_t value; + }; + enum ScriptState { + SCRIPT_OK, + SCRIPT_NOFILE, + SCRIPT_SYNTAX_ERROR, + SCRIPT_KILLED, + SCRIPT_LEAK + }; + struct ScriptInternalData { + uint8_t state; + int run; + uint8_t instructions; + uint8_t memory; + uint8_t inputsCount; + ScriptInput inputs[MAX_SCRIPT_INPUTS]; + uint8_t outputsCount; + ScriptOutput outputs[MAX_SCRIPT_OUTPUTS]; + }; + #define LUASTATE_STANDALONE_SCRIPT_RUNNING 1 + #define LUASTATE_RELOAD_MODEL_SCRIPTS 2 + extern uint8_t luaState; + extern ScriptInternalData scriptInternalData[MAX_SCRIPTS]; + extern ScriptInternalData standaloneScript; + void luaInit(); + void luaTask(uint8_t evt); + void luaExec(const char *filename); + void luaLoadModelScript(uint8_t index); + void luaLoadModelScripts(); + #define luaGetMemUsed(idx) scriptInternalData[idx].memory + #define luaGetCpuUsed(idx) scriptInternalData[idx].instructions + #define LUA_INIT() + #define LUA_RESET() luaInit() + #define LUA_LOAD_MODEL_SCRIPTS() luaState |= LUASTATE_RELOAD_MODEL_SCRIPTS + #define LUA_LOAD_MODEL_SCRIPT(idx) luaState |= LUASTATE_RELOAD_MODEL_SCRIPTS +#else + #define LUA_INIT() + #define LUA_RESET() + #define LUA_LOAD_MODEL_SCRIPTS() + #define LUA_LOAD_MODEL_SCRIPT(idx) +#endif + #if defined(CPUARM) extern uint8_t requiredSpeakerVolume; #endif @@ -1483,12 +1625,14 @@ extern uint8_t barsThresholds[THLD_MAX]; #endif #if defined(FRSKY) - uint8_t maxTelemValue(uint8_t channel); + csw_telemetry_value_t minTelemValue(uint8_t channel); + csw_telemetry_value_t maxTelemValue(uint8_t channel); #else + #define minTelemValue(channel) 255 #define maxTelemValue(channel) 255 #endif -getvalue_t convertTelemValue(uint8_t channel, uint8_t value); +getvalue_t convertTelemValue(uint8_t channel, csw_telemetry_value_t value); getvalue_t convertCswTelemValue(CustomSwData * cs); #if defined(FRSKY) || defined(CPUARM) @@ -1512,6 +1656,11 @@ extern const pm_uint8_t bchunit_ar[]; #define EARTH_RADIUSKM ((uint32_t)6371) #define EARTH_RADIUS ((uint32_t)111194) +#if defined(PCBTARANIS) +double gpsToDouble(bool neg, int16_t bp, int16_t ap); +extern double pilotLatitude; +extern double pilotLongitude; +#endif void getGpsPilotPosition(); void getGpsDistance(); void varioWakeup(); diff --git a/src/sdcard.h b/src/sdcard.h index f9da8ffd0..4e6c446d7 100644 --- a/src/sdcard.h +++ b/src/sdcard.h @@ -46,11 +46,15 @@ #define SOUNDS_PATH_LNG_OFS (sizeof(SOUNDS_PATH)-3) #define SYSTEM_SOUNDS_PATH SOUNDS_PATH "/SYSTEM" // no trailing slash = important #define BITMAPS_PATH ROOT_PATH "BMP" +#define SCRIPTS_PATH ROOT_PATH "SCRIPTS" #define MODELS_EXT ".bin" #define LOGS_EXT ".csv" #define SOUNDS_EXT ".wav" #define BITMAPS_EXT ".bmp" +#define SCRIPTS_EXT ".lua" +#define MIXES_EXT ".mix" +#define TEXT_EXT ".txt" extern FATFS g_FATFS_Obj; diff --git a/src/simpgmspace.cpp b/src/simpgmspace.cpp index 75e7b91d6..48aecb6c7 100644 --- a/src/simpgmspace.cpp +++ b/src/simpgmspace.cpp @@ -297,14 +297,16 @@ void *main_thread(void *) g_menuStack[0] = menuMainView; g_menuStack[1] = menuModelSelect; + eeReadAll(); // load general setup and selected model + #if defined(CPUARM) && defined(SDCARD) refreshSystemAudioFiles(); #endif - eeReadAll(); // load general setup and selected model - if (g_eeGeneral.backlightMode != e_backlight_mode_off) backlightOn(); // on Tx start turn the light on + LUA_INIT(); + if (main_thread_running == 1) { opentxStart(); } @@ -335,16 +337,6 @@ void *main_thread(void *) #define getcwd _getcwd #endif -#if defined(LUA) -extern void luaTask(void * pdata); -void *lua_thread(void *) -{ - luaTask(NULL); - return NULL; -} -pthread_t lua_thread_pid; -#endif - pthread_t main_thread_pid; void StartMainThread(bool tests) { @@ -355,20 +347,12 @@ void StartMainThread(bool tests) main_thread_running = (tests ? 1 : 2); pthread_create(&main_thread_pid, NULL, &main_thread, NULL); - -#if defined(LUA) - pthread_create(&lua_thread_pid, NULL, &lua_thread, NULL); -#endif } void StopMainThread() { main_thread_running = 0; pthread_join(main_thread_pid, NULL); - -#if defined(LUA) - pthread_join(lua_thread_pid, NULL); -#endif } pthread_t eeprom_thread_pid; diff --git a/src/simpgmspace.h b/src/simpgmspace.h index 14f3603fb..1b2e8b0c2 100644 --- a/src/simpgmspace.h +++ b/src/simpgmspace.h @@ -357,7 +357,7 @@ void eeprom_read_block (void *pointer_ram, const void *pointer_eeprom, size_t si #define wdt_reset() sleep(1/*ms*/) #define boardInit() -#define OS_MutexID int +#define OS_MutexID pthread_mutex_t #define OS_FlagID int #define OS_TID int #define OS_TCID int @@ -372,8 +372,8 @@ void eeprom_read_block (void *pointer_ram, const void *pointer_eeprom, size_t si #define CoExitISR(...) #define CoStartTmr(...) #define CoWaitForSingleFlag(...) 0 -#define CoEnterMutexSection(...) -#define CoLeaveMutexSection(...) +#define CoEnterMutexSection(m) pthread_mutex_lock(&(m)) +#define CoLeaveMutexSection(m) pthread_mutex_unlock(&(m)) #define CoTickDelay(...) #define CoCreateFlag(...) 0 #define UART3_Configure(...) diff --git a/src/targets/gruvin9x/board_gruvin9x.h b/src/targets/gruvin9x/board_gruvin9x.h index 65c5e2f04..fb87c5944 100644 --- a/src/targets/gruvin9x/board_gruvin9x.h +++ b/src/targets/gruvin9x/board_gruvin9x.h @@ -160,7 +160,8 @@ void sdPoll10ms(); #endif // Keys driver -#define KEYS_PRESSED() (~PINL) // used only for DBLKEYS code. +#define TRIMS_PRESSED() (~PINJ) +#define KEYS_PRESSED() (~PINL) // used only for DBLKEYS code. #define DBLKEYS_PRESSED_RGT_LFT(i) ((in & ((1< #include #include +#include /*---------------------------------------------------------------------------- * Exported variables *----------------------------------------------------------------------------*/ #undef errno -extern int errno ; -extern int _end ; +extern int errno; +extern int _end; +extern int _estack; + +#define RAM_END (unsigned char *)&_estack /*---------------------------------------------------------------------------- * Exported functions @@ -61,23 +65,36 @@ extern void _exit( int status ) ; extern void _kill( int pid, int sig ) ; extern int _getpid ( void ) ; -extern caddr_t _sbrk ( int incr ) +unsigned char *heap = (unsigned char *)&_end; +extern caddr_t _sbrk(int nbytes) { - static unsigned char *heap = NULL ; - unsigned char *prev_heap ; - - if ( heap == NULL ) - { - heap = (unsigned char *)&_end ; - } - prev_heap = heap; - - heap += incr ; - - return (caddr_t) prev_heap ; + if (heap + nbytes < RAM_END-4096) { + unsigned char *prev_heap = heap; + heap += nbytes; + return (caddr_t) prev_heap; + } + else { + errno = ENOMEM; + return ((void*)-1); + } } -extern int link( char *old, char *nw ) +extern int _gettimeofday(void *p1, void *p2) +{ + return 0 ; +} + +extern int _link( char *old, char *nw ) +{ + return -1 ; +} + +extern int _unlink (const char *path) +{ + return -1 ; +} + +extern int _open(const char *name, int flags, int mode) { return -1 ; } diff --git a/src/targets/stock/board_stock.h b/src/targets/stock/board_stock.h index 3430f3d87..53c99012f 100644 --- a/src/targets/stock/board_stock.h +++ b/src/targets/stock/board_stock.h @@ -208,7 +208,8 @@ void backlightFade(); #define INP_G_RuddDR 0 // Keys driver -#define KEYS_PRESSED() (~PINB) +#define TRIMS_PRESSED() (~PIND) +#define KEYS_PRESSED() (~PINB) #define DBLKEYS_PRESSED_RGT_LFT(i) ((in & ((1< telemetryFifo; diff --git a/src/targets/taranis/stm32_flash.ld b/src/targets/taranis/stm32_flash.ld index 647b9a192..a3279e20a 100644 --- a/src/targets/taranis/stm32_flash.ld +++ b/src/targets/taranis/stm32_flash.ld @@ -32,9 +32,6 @@ /* Entry Point */ ENTRY(Reset_Handler) -/* Highest address of the user mode stack */ -_estack = 0x20020000; /* end of 128K SRAM */ - /* Generate a link error if heap and stack don't fit into RAM */ _Min_Heap_Size = 0; /* required amount of heap */ _Min_Stack_Size = 0x200; /* required amount of stack */ @@ -144,6 +141,8 @@ SECTIONS . = ALIGN(4); } >RAM + PROVIDE ( _estack = ORIGIN(RAM) + LENGTH(RAM) ); + /* MEMORY_bank1 section, code must be located here explicitly */ /* Example: extern int foo(void) __attribute__ ((section (".mb1text"))); */ .memory_b1_text : diff --git a/src/targets/taranis/uart_driver.cpp b/src/targets/taranis/uart_driver.cpp index 8c1ec1de6..b68042bb7 100644 --- a/src/targets/taranis/uart_driver.cpp +++ b/src/targets/taranis/uart_driver.cpp @@ -34,7 +34,7 @@ * */ -#include "../opentx.h" +#include "../../opentx.h" void uartInit(uint32_t baudrate) { diff --git a/src/telemetry/frsky_sport.cpp b/src/telemetry/frsky_sport.cpp index 5ea7a2846..4794940b5 100644 --- a/src/telemetry/frsky_sport.cpp +++ b/src/telemetry/frsky_sport.cpp @@ -646,7 +646,7 @@ void resetTelemetry() frskyData.hub.gpsFix = -1; #endif -#ifdef SIMU +#if defined(SIMU) frskyData.analog[0].set(120); frskyData.analog[1].set(240); frskyData.rssi[0].value = 75; @@ -669,12 +669,8 @@ void resetTelemetry() frskyData.hub.cellsCount = 6; -#if 0 // defined(FRSKY_SPORT) + frskyData.hub.baroAltitudeOffset = 500 * 100; frskyData.hub.baroAltitude = 50 * 100; -#else - frskyData.hub.baroAltitude_bp = 50; -#endif - frskyData.hub.gpsAltitude_bp = 50; frskyData.hub.minAltitude = 10; diff --git a/src/templates.cpp b/src/templates.cpp index 14bf1d4a3..33e4ca7b2 100644 --- a/src/templates.cpp +++ b/src/templates.cpp @@ -87,7 +87,7 @@ MixData* setDest(uint8_t dch, uint8_t src, bool clear=false) return mix; } -void md_SetWeight(MixData* md, int8_t weight) +void mixSetWeight(MixData* md, int8_t weight) { u_int8int16_t tmp; tmp.word=weight; @@ -95,10 +95,35 @@ void md_SetWeight(MixData* md, int8_t weight) // MD_SETWEIGHT(md,weight); doesn't matter here in code cost compiler optimizes this anyway } +#if defined(PCBTARANIS) +void clearInputs() +{ + memset(g_model.expoData, 0, sizeof(g_model.expoData)); // clear all expos +} + +void defaultInputs() +{ + clearInputs(); + + for (int i=0; isrcRaw-MIXSRC_Rud+1)+c]); + } + } + eeDirty(EE_MODEL); +} +#define TMPL_INPUT(x) (MIXSRC_FIRST_INPUT+channel_order(x)-1) +#else +#define clearInputs() +#define defaultInputs() +#define TMPL_INPUT(x) (MIXSRC_Rud+x-1) +#endif + void clearMixes() { memset(g_model.mixData, 0, sizeof(g_model.mixData)); // clear all mixes - eeDirty(EE_MODEL); } void clearCurves() @@ -136,8 +161,10 @@ void applyTemplate(uint8_t idx) //ICC(vSTK) -> STK #define ICC(x) icc[(x)-1] uint8_t icc[4] = {0}; - for (uint8_t i=0; i<4; i++) //generate inverse array - for(uint8_t j=0; j<4; j++) if(CC(i+1)==j+1) icc[j]=i; + for (uint8_t i=0; i<4; i++) { //generate inverse array + for(uint8_t j=0; j<4; j++) + if(CC(i+1)==j+1) icc[j]=i; + } switch (idx) { case TMPL_CLEAR_MIXES: @@ -150,17 +177,15 @@ void applyTemplate(uint8_t idx) switch (idx) { // Simple 4-Ch case TMPL_SIMPLE_4CH: - setDest(ICC(STK_RUD), MIXSRC_Rud); - setDest(ICC(STK_ELE), MIXSRC_Ele); - setDest(ICC(STK_THR), MIXSRC_Thr); - setDest(ICC(STK_AIL), MIXSRC_Ail); + clearInputs(); + applyDefaultTemplate(); break; // Sticky-T-Cut case TMPL_STI_THR_CUT: - md=setDest(ICC(STK_THR), MIXSRC_MAX); md_SetWeight(md, -100); md->swtch=SWSRC_SWC; md->mltpx=MLTPX_REP; + md=setDest(ICC(STK_THR), MIXSRC_MAX); mixSetWeight(md, -100); md->swtch=SWSRC_SWC; md->mltpx=MLTPX_REP; md=setDest(13, MIXSRC_CH14); // md->weight= 100; done by setDest anyway - md=setDest(13, MIXSRC_MAX); md_SetWeight(md, -100); md->swtch=SWSRC_SWB; md->mltpx=MLTPX_REP; + md=setDest(13, MIXSRC_MAX); mixSetWeight(md, -100); md->swtch=SWSRC_SWB; md->mltpx=MLTPX_REP; md=setDest(13, MIXSRC_MAX); /* md->weight= 100;*/ md->swtch=SWSRC_THR; md->mltpx=MLTPX_REP; setSwitch(11, CS_VNEG, STK_THR, -99); setSwitch(12, CS_VPOS, MIXSRC_CH14, 0); @@ -168,29 +193,34 @@ void applyTemplate(uint8_t idx) // V-Tail case TMPL_V_TAIL: - setDest(ICC(STK_RUD), MIXSRC_Rud, true); - md=setDest(ICC(STK_RUD), MIXSRC_Ele); md_SetWeight(md, -100); - setDest(ICC(STK_ELE), MIXSRC_Rud, true); - setDest(ICC(STK_ELE), MIXSRC_Ele); + defaultInputs(); + setDest(ICC(STK_RUD), TMPL_INPUT(STK_RUD), true); + md=setDest(ICC(STK_RUD), TMPL_INPUT(STK_ELE)); mixSetWeight(md, -100); + setDest(ICC(STK_ELE), TMPL_INPUT(STK_RUD), true); + setDest(ICC(STK_ELE), TMPL_INPUT(STK_ELE)); break; // Elevon\\Delta case TMPL_ELEVON_DELTA: + defaultInputs(); +#if defined(PCBTARANIS) +#warning "Templates below are not implemented (only V-TAIL has been done). Feel free to help!" +#endif setDest(ICC(STK_ELE), MIXSRC_Ele, true); setDest(ICC(STK_ELE), MIXSRC_Ail); setDest(ICC(STK_AIL), MIXSRC_Ele, true); - md=setDest(ICC(STK_AIL), MIXSRC_Ail); md_SetWeight(md, -100); + md=setDest(ICC(STK_AIL), MIXSRC_Ail); mixSetWeight(md, -100); break; // eCCPM case TMPL_ECCPM: md=setDest(ICC(STK_ELE), MIXSRC_Ele, true); md->weight= 72; md=setDest(ICC(STK_ELE), MIXSRC_Thr); md->weight= 55; - md=setDest(ICC(STK_AIL), MIXSRC_Ele, true); md_SetWeight(md, -36); + md=setDest(ICC(STK_AIL), MIXSRC_Ele, true); mixSetWeight(md, -36); md=setDest(ICC(STK_AIL), MIXSRC_Ail); md->weight= 62; md=setDest(ICC(STK_AIL), MIXSRC_Thr); md->weight= 55; - md=setDest(5, MIXSRC_Ele, true); md_SetWeight(md, -36); - md=setDest(5, MIXSRC_Ail); md_SetWeight(md, -62); + md=setDest(5, MIXSRC_Ele, true); mixSetWeight(md, -36); + md=setDest(5, MIXSRC_Ail); mixSetWeight(md, -62); md=setDest(5, MIXSRC_Thr); md->weight= 55; break; @@ -208,30 +238,38 @@ void applyTemplate(uint8_t idx) md=setDest(3, MIXSRC_Rud); // md->weight=100; // throttle - md=setDest(4, MIXSRC_Thr); md->swtch=SWSRC_ID0; md->curveMode=MODE_CURVE; md->curveParam=CV(1); md->carryTrim=TRIM_OFF; - md=setDest(4, MIXSRC_Thr); md->swtch=SWSRC_ID1; md->curveMode=MODE_CURVE; md->curveParam=CV(2); md->carryTrim=TRIM_OFF; - md=setDest(4, MIXSRC_Thr); md->swtch=SWSRC_ID2; md->curveMode=MODE_CURVE; md->curveParam=CV(3); md->carryTrim=TRIM_OFF; - md=setDest(4, MIXSRC_MAX); md_SetWeight(md, -100); md->swtch=SWSRC_THR; md->mltpx=MLTPX_REP; +#if defined(PCBTARANIS) + // TODO +#else + md=setDest(4, MIXSRC_Thr); md->swtch=SWSRC_ID0; mixSetCurve(md, 0); md->carryTrim=TRIM_OFF; + md=setDest(4, MIXSRC_Thr); md->swtch=SWSRC_ID1; mixSetCurve(md, 1); md->carryTrim=TRIM_OFF; + md=setDest(4, MIXSRC_Thr); md->swtch=SWSRC_ID2; mixSetCurve(md, 2); md->carryTrim=TRIM_OFF; +#endif + md=setDest(4, MIXSRC_MAX); mixSetWeight(md, -100); md->swtch=SWSRC_THR; md->mltpx=MLTPX_REP; // gyro gain md=setDest(5, MIXSRC_MAX); md->weight= 30; md->swtch=-SWSRC_GEA; - md=setDest(5, MIXSRC_MAX); md_SetWeight(md, -30); md->swtch= SWSRC_GEA; + md=setDest(5, MIXSRC_MAX); mixSetWeight(md, -30); md->swtch= SWSRC_GEA; // collective - md=setDest(10, MIXSRC_Thr); /*md->weight= 100;*/ md->swtch=SWSRC_ID0; md->curveMode=MODE_CURVE; md->curveParam=CV(4); md->carryTrim=TRIM_OFF; - md=setDest(10, MIXSRC_Thr); /*md->weight= 100;*/ md->swtch=SWSRC_ID1; md->curveMode=MODE_CURVE; md->curveParam=CV(5); md->carryTrim=TRIM_OFF; - md=setDest(10, MIXSRC_Thr); /*md->weight= 100;*/ md->swtch=SWSRC_ID2; md->curveMode=MODE_CURVE; md->curveParam=CV(6); md->carryTrim=TRIM_OFF; +#if defined(PCBTARANIS) + // TODO +#else + md=setDest(10, MIXSRC_Thr); /*md->weight= 100;*/ md->swtch=SWSRC_ID0; mixSetCurve(md, 3); md->carryTrim=TRIM_OFF; + md=setDest(10, MIXSRC_Thr); /*md->weight= 100;*/ md->swtch=SWSRC_ID1; mixSetCurve(md, 4); md->carryTrim=TRIM_OFF; + md=setDest(10, MIXSRC_Thr); /*md->weight= 100;*/ md->swtch=SWSRC_ID2; mixSetCurve(md, 5); md->carryTrim=TRIM_OFF; +#endif g_model.swashR.collectiveSource = MIXSRC_CH11; g_model.swashR.type = SWASH_TYPE_120; - //Set up Curves - setCurve(CURVE5(1), heli_ar1); - setCurve(CURVE5(2), heli_ar2); - setCurve(CURVE5(3), heli_ar3); - setCurve(CURVE5(4), heli_ar4); - setCurve(CURVE5(5), heli_ar5); - setCurve(CURVE5(6), heli_ar5); + // curves + setCurve(0, heli_ar1); + setCurve(1, heli_ar2); + setCurve(2, heli_ar3); + setCurve(3, heli_ar4); + setCurve(4, heli_ar5); + setCurve(5, heli_ar5); break; // Servo Test diff --git a/src/templates.h b/src/templates.h index 3accc39df..2ac2cac71 100644 --- a/src/templates.h +++ b/src/templates.h @@ -68,10 +68,13 @@ #define STK_P3 7 #define CV(x) (CURVE_BASE+(x)-1) -#define CC(x) (channel_order(x)) //need to invert this to work with dest +#define CC(x) (MIXSRC_Rud - 1 + channel_order(x)) // need to invert this to work with dest -#define CURVE5(x) ((x)-1) -#define CURVE9(x) (MAX_CURVE5+(x)-1) +#if defined(PCBTARANIS) + #define mixSetCurve(mix, idx) mix->curve.type=CURVE_REF_CUSTOM; mix->curve.value=idx +#else + #define mixSetCurve(mix, idx) mix->curveMode=MODE_CURVE; mix->curveParam=CURVE_BASE+idx +#endif enum Templates { TMPL_CLEAR_MIXES, @@ -89,13 +92,6 @@ void clearMixes(); void clearCurves(); void applyTemplate(uint8_t idx); -#ifdef TEMPLATES -inline void applyDefaultTemplate() -{ - applyTemplate(TMPL_SIMPLE_4CH); -} -#endif - #endif //TEMPLATES_H diff --git a/src/translations.cpp b/src/translations.cpp index 90d6032ad..05df2e4dd 100644 --- a/src/translations.cpp +++ b/src/translations.cpp @@ -100,6 +100,7 @@ const pm_char STR_OPEN9X[] PROGMEM = #if defined(CPUARM) ISTR(VLCD) ISTR(VUNITSSYSTEM) + ISTR(VBEEPCOUNTDOWN) #endif #if defined(PXX) ISTR(COUNTRYCODES) @@ -247,9 +248,6 @@ const pm_char STR_TMR1LATMAXUS[] PROGMEM = TR_TMR1LATMAXUS; const pm_char STR_TMR1LATMINUS[] PROGMEM = TR_TMR1LATMINUS; const pm_char STR_TMR1JITTERUS[] PROGMEM = TR_TMR1JITTERUS; const pm_char STR_TMIXMAXMS[] PROGMEM = TR_TMIXMAXMS; -#ifdef DEBUG -const pm_char STR_T10MSUS[] PROGMEM = TR_T10MSUS; -#endif const pm_char STR_FREESTACKMINB[] PROGMEM = TR_FREESTACKMINB; const pm_char STR_MENUTORESET[] PROGMEM = TR_MENUTORESET; const pm_char STR_PPM[] PROGMEM = TR_PPM; @@ -288,7 +286,7 @@ const pm_char STR_MENUFLIGHTPHASES[] PROGMEM = TR_MENUFLIGHTPHASES; const pm_char STR_MENUHELISETUP[] PROGMEM = TR_MENUHELISETUP; #endif -const pm_char STR_MENUDREXPO[] PROGMEM = TR_MENUDREXPO; +const pm_char STR_MENUINPUTS[] PROGMEM = TR_MENUINPUTS; const pm_char STR_MENULIMITS[] PROGMEM = TR_MENULIMITS; const pm_char STR_MENUCURVES[] PROGMEM = TR_MENUCURVES; const pm_char STR_MENUCURVE[] PROGMEM = TR_MENUCURVE; @@ -296,6 +294,11 @@ const pm_char STR_MENUCUSTOMSWITCH[] PROGMEM = TR_MENUCUSTOMSWITCH; const pm_char STR_MENUCUSTOMSWITCHES[] PROGMEM = TR_MENUCUSTOMSWITCHES; const pm_char STR_MENUCUSTOMFUNC[] PROGMEM = TR_MENUCUSTOMFUNC; +#if defined(LUA) +const pm_char STR_MENUCUSTOMSCRIPTS[] PROGMEM = "CUSTOM SCRIPTS"; +const pm_char STR_MENUCUSTOMSCRIPT[] PROGMEM = "CUSTOM SCRIPT"; +#endif + #if defined(FRSKY) const pm_char STR_MENUTELEMETRY[] PROGMEM = TR_MENUTELEMETRY; const pm_char STR_LIMIT[] PROGMEM = TR_LIMIT; @@ -366,6 +369,7 @@ const pm_char STR_INSERT_AFTER[] PROGMEM = TR_INSERT_AFTER; const pm_char STR_COPY[] PROGMEM = TR_COPY; const pm_char STR_MOVE[] PROGMEM = TR_MOVE; const pm_char STR_PASTE[] PROGMEM = TR_PASTE; +const pm_char STR_INSERT[] PROGMEM = TR_INSERT; const pm_char STR_DELETE[] PROGMEM = TR_DELETE; const pm_char STR_RESET_FLIGHT[] PROGMEM = TR_RESET_FLIGHT; const pm_char STR_RESET_TIMER1[] PROGMEM = TR_RESET_TIMER1; @@ -375,7 +379,7 @@ const pm_char STR_STATISTICS[] PROGMEM = TR_STATISTICS; const pm_char STR_ABOUT_US[] PROGMEM = TR_ABOUT_US; #endif -const pm_char STR_RESET[] PROGMEM = TR_RESET; +const pm_char STR_RESET_BTN[] PROGMEM = TR_RESET_BTN; #if defined(SDCARD) const pm_char STR_BACKUP_MODEL[] PROGMEM = TR_BACKUP_MODEL; @@ -415,8 +419,10 @@ const pm_char STR_SDHC_CARD[] PROGMEM = TR_SDHC_CARD; const pm_char STR_NO_SOUNDS_ON_SD[] PROGMEM = TR_NO_SOUNDS_ON_SD; const pm_char STR_NO_MODELS_ON_SD[] PROGMEM = TR_NO_MODELS_ON_SD; const pm_char STR_NO_BITMAPS_ON_SD[] PROGMEM = TR_NO_BITMAPS_ON_SD; +const pm_char STR_NO_SCRIPTS_ON_SD[] PROGMEM = "No Scripts on SD"; // TODO TR_NO_BITMAPS_ON_SD; const pm_char STR_PLAY_FILE[] PROGMEM = TR_PLAY_FILE; const pm_char STR_ASSIGN_BITMAP[] PROGMEM = TR_ASSIGN_BITMAP; +const pm_char STR_EXECUTE_FILE[] PROGMEM = "Execute"; const pm_char STR_DELETE_FILE[] PROGMEM = TR_DELETE_FILE; const pm_char STR_COPY_FILE[] PROGMEM = TR_COPY_FILE; const pm_char STR_RENAME_FILE[] PROGMEM = TR_RENAME_FILE; @@ -442,6 +448,7 @@ const pm_char STR_ROTARY_ENCODER[] PROGMEM = TR_ROTARY_ENCODER; const pm_char STR_DATE[] PROGMEM = TR_DATE; const pm_char STR_CHANNELS_MONITOR[] PROGMEM = TR_CHANNELS_MONITOR; const pm_char STR_PATH_TOO_LONG[] PROGMEM = "Path too long"; +const pm_char STR_VIEW_TEXT[] PROGMEM = "View text"; #if LCD_W >= 212 const pm_char STR_MODELNAME[] PROGMEM = TR_MODELNAME; @@ -466,6 +473,24 @@ const pm_char STR_PATH_TOO_LONG[] PROGMEM = "Path too long"; const pm_char STR_CHANNELRANGE[] PROGMEM = TR_CHANNELRANGE; const pm_char STR_LOWALARM[] PROGMEM = TR_LOWALARM; const pm_char STR_CRITICALALARM[] PROGMEM = TR_CRITICALALARM; + const pm_char STR_ENABLE_POPUP[] PROGMEM = "Enable Popup"; + const pm_char STR_DISABLE_POPUP[] PROGMEM = "Disable Popup"; + const pm_char STR_CURVE_PRESET[] PROGMEM = "Preset..."; + const pm_char STR_PRESET[] PROGMEM = "Preset"; + const pm_char STR_MIRROR[] PROGMEM = "Mirror"; + const pm_char STR_CLEAR[] PROGMEM = "Clear"; + const pm_char STR_RESET[] PROGMEM = "Reset"; + const pm_char STR_COPY_TRIMS_TO_OFFSET[] = "Copy Trims To Offset"; + const pm_char STR_TOP_BAR[] PROGMEM = "Top Bar"; + const pm_char STR_ALTITUDE[] PROGMEM = INDENT "Altitude"; + const pm_char STR_SCALE[] PROGMEM = "Scale"; + const pm_char STR_VIEW_CHANNELS[] PROGMEM = "View Channels"; + const pm_char STR_VIEW_NOTES[] PROGMEM = "View Notes"; +#endif + +#if MENUS_LOCK == 1 + const pm_char STR_UNLOCKED[] PROGMEM = TR_UNLOCKED; + const pm_char STR_MODS_FORBIDDEN[] PROGMEM = TR_MODS_FORBIDDEN; #endif #if defined(PCBTARANIS) || defined(DSM2) @@ -636,4 +661,3 @@ const pm_uchar font_10x14_extra[] PROGMEM = { #endif - diff --git a/src/translations.h b/src/translations.h index f8e4bc79c..e1e6e624a 100644 --- a/src/translations.h +++ b/src/translations.h @@ -150,11 +150,8 @@ extern const pm_char STR_OPEN9X[]; #endif #if defined(CPUARM) #define OFS_VUNITSSYSTEM (OFS_VLCD + sizeof(TR_VLCD)) -#else - #define OFS_VUNITSSYSTEM (OFS_VLCD) -#endif -#if defined(CPUARM) - #define OFS_COUNTRYCODES (OFS_VUNITSSYSTEM + sizeof(TR_VUNITSSYSTEM)) + #define OFS_VBEEPCOUNTDOWN (OFS_VUNITSSYSTEM + sizeof(TR_VUNITSSYSTEM)) + #define OFS_COUNTRYCODES (OFS_VBEEPCOUNTDOWN + sizeof(TR_VBEEPCOUNTDOWN)) #else #define OFS_COUNTRYCODES (OFS_VUNITSSYSTEM) #endif @@ -251,6 +248,7 @@ extern const pm_char STR_OPEN9X[]; #if defined(CPUARM) #define STR_VLCD (STR_OPEN9X + OFS_VLCD) #define STR_VUNITSSYSTEM (STR_OPEN9X + OFS_VUNITSSYSTEM) + #define STR_VBEEPCOUNTDOWN (STR_OPEN9X + OFS_VBEEPCOUNTDOWN) #endif #if defined(PXX) @@ -397,7 +395,6 @@ extern const pm_char STR_TMR1LATMAXUS[]; extern const pm_char STR_TMR1LATMINUS[]; extern const pm_char STR_TMR1JITTERUS[]; extern const pm_char STR_TMIXMAXMS[]; -extern const pm_char STR_T10MSUS[]; extern const pm_char STR_FREESTACKMINB[]; extern const pm_char STR_MENUTORESET[]; extern const pm_char STR_PPM[]; @@ -430,13 +427,15 @@ extern const pm_char STR_MENUSETUP[]; extern const pm_char STR_MENUFLIGHTPHASE[]; extern const pm_char STR_MENUFLIGHTPHASES[]; extern const pm_char STR_MENUHELISETUP[]; -extern const pm_char STR_MENUDREXPO[]; +extern const pm_char STR_MENUINPUTS[]; extern const pm_char STR_MENULIMITS[]; extern const pm_char STR_MENUCURVES[]; extern const pm_char STR_MENUCURVE[]; extern const pm_char STR_MENUCUSTOMSWITCH[]; extern const pm_char STR_MENUCUSTOMSWITCHES[]; extern const pm_char STR_MENUCUSTOMFUNC[]; +extern const pm_char STR_MENUCUSTOMSCRIPTS[]; +extern const pm_char STR_MENUCUSTOMSCRIPT[]; extern const pm_char STR_MENUTELEMETRY[]; extern const pm_char STR_MENUTEMPLATES[]; extern const pm_char STR_MENUSTAT[]; @@ -506,6 +505,7 @@ extern const pm_char STR_CURRENT[]; extern const pm_char STR_COPY[]; extern const pm_char STR_MOVE[]; extern const pm_char STR_PASTE[]; + extern const pm_char STR_INSERT[]; extern const pm_char STR_DELETE[]; extern const pm_char STR_RESET_FLIGHT[]; extern const pm_char STR_RESET_TIMER1[]; @@ -515,7 +515,7 @@ extern const pm_char STR_CURRENT[]; extern const pm_char STR_ABOUT_US[]; #endif -extern const pm_char STR_RESET[]; +extern const pm_char STR_RESET_BTN[]; #if defined(SDCARD) extern const pm_char STR_BACKUP_MODEL[]; @@ -568,8 +568,10 @@ extern const pm_char STR_SDHC_CARD[]; extern const pm_char STR_NO_SOUNDS_ON_SD[]; extern const pm_char STR_NO_MODELS_ON_SD[]; extern const pm_char STR_NO_BITMAPS_ON_SD[]; +extern const pm_char STR_NO_SCRIPTS_ON_SD[]; extern const pm_char STR_PLAY_FILE[]; extern const pm_char STR_ASSIGN_BITMAP[]; +extern const pm_char STR_EXECUTE_FILE[]; extern const pm_char STR_DELETE_FILE[]; extern const pm_char STR_COPY_FILE[]; extern const pm_char STR_RENAME_FILE[]; @@ -595,6 +597,7 @@ extern const pm_char STR_ROTARY_ENCODER[]; extern const pm_char STR_DATE[]; extern const pm_char STR_CHANNELS_MONITOR[]; extern const pm_char STR_PATH_TOO_LONG[]; +extern const pm_char STR_VIEW_TEXT[]; #if defined(VOICE) && defined(CPUARM) struct LanguagePack { @@ -648,6 +651,24 @@ extern const pm_char STR_PATH_TOO_LONG[]; extern const pm_char STR_CHANNELRANGE[]; extern const pm_char STR_LOWALARM[]; extern const pm_char STR_CRITICALALARM[]; + extern const pm_char STR_ENABLE_POPUP[]; + extern const pm_char STR_DISABLE_POPUP[]; + extern const pm_char STR_CURVE_PRESET[]; + extern const pm_char STR_PRESET[]; + extern const pm_char STR_MIRROR[]; + extern const pm_char STR_CLEAR[]; + extern const pm_char STR_RESET[]; + extern const pm_char STR_COPY_TRIMS_TO_OFFSET[]; + extern const pm_char STR_TOP_BAR[]; + extern const pm_char STR_ALTITUDE[]; + extern const pm_char STR_SCALE[]; + extern const pm_char STR_VIEW_CHANNELS[]; + extern const pm_char STR_VIEW_NOTES[]; +#endif + +#if MENUS_LOCK == 1 + extern const pm_char STR_UNLOCKED[]; + extern const pm_char STR_MODS_FORBIDDEN[]; #endif #if defined(PCBTARANIS) || defined(DSM2) diff --git a/src/translations/cz.h b/src/translations/cz.h index 84387d2fa..c31e89081 100644 --- a/src/translations/cz.h +++ b/src/translations/cz.h @@ -530,7 +530,7 @@ // Alignment -#define TR_MENUDREXPO "DR/EXPO" +#define TR_MENUINPUTS "DR/EXPO" #define TR_MENULIMITS "LIMITY" @@ -684,7 +684,7 @@ // Taranis column headers #define TR_PHASES_HEADERS { " Jm\202no ", " Sp\204na\201 ", " Trimy ", " P\206echod Zap ", " P\206echod Vyp " } -#define TR_LIMITS_HEADERS { " Jm\202no ", " Subtrim ", " Min ", " Max ", " Sm\203r ", " St\206ed PPM ", " Symetrick\202 " } +#define TR_LIMITS_HEADERS { " Jm\202no ", " Subtrim ", " Min ", " Max ", " Sm\203r ", " Curve ", " St\206ed PPM ", " Symetrick\202 " } #define TR_CSW_HEADERS { " Funkce ", " Hodnota 1 ", " Hodnota 2 ", " AND Sp\204na\201 ", " Trv\200n\204 ", " Zpo\217d\203n\204 " } //Taranis About screen diff --git a/src/translations/cz.h.txt b/src/translations/cz.h.txt index 6a424d209..c4f7ff837 100644 --- a/src/translations/cz.h.txt +++ b/src/translations/cz.h.txt @@ -530,7 +530,7 @@ // Alignment -#define TR_MENUDREXPO "DR/EXPO" +#define TR_MENUINPUTS "DR/EXPO" #define TR_MENULIMITS "LIMITY" @@ -684,7 +684,7 @@ // Taranis column headers #define TR_PHASES_HEADERS { " Jméno ", " Spínač ", " Trimy ", " Přechod Zap ", " Přechod Vyp " } -#define TR_LIMITS_HEADERS { " Jméno ", " Subtrim ", " Min ", " Max ", " Směr ", " Střed PPM ", " Symetrické " } +#define TR_LIMITS_HEADERS { " Jméno ", " Subtrim ", " Min ", " Max ", " Směr ", " Curve ", " Střed PPM ", " Symetrické " } #define TR_CSW_HEADERS { " Funkce ", " Hodnota 1 ", " Hodnota 2 ", " AND Spínač ", " Trvání ", " Zpoždění " } //Taranis About screen diff --git a/src/translations/de.h b/src/translations/de.h index 75fedb65f..39707422d 100644 --- a/src/translations/de.h +++ b/src/translations/de.h @@ -646,7 +646,7 @@ #define TR_BYTES "bytes" #define TR_MODULE_BIND "[Bind]" #define TR_MODULE_RANGE "[Range]" -#define TR_RESET "[Reset]" +#define TR_RESET_BTN "[Reset]" #define TR_SET "[Set]" #define TR_TRAINER "----Trainer Buchse Einst.------" //DSC Buchse Funktion #define TR_ANTENNAPROBLEM CENTER "TX Antennen Problem!" diff --git a/src/translations/de.h.txt b/src/translations/de.h.txt index 6f88db196..e6d03ca4b 100644 --- a/src/translations/de.h.txt +++ b/src/translations/de.h.txt @@ -646,7 +646,7 @@ #define TR_BYTES "bytes" #define TR_MODULE_BIND "[Bind]" #define TR_MODULE_RANGE "[Range]" -#define TR_RESET "[Reset]" +#define TR_RESET_BTN "[Reset]" #define TR_SET "[Set]" #define TR_TRAINER "----Trainer Buchse Einst.------" //DSC Buchse Funktion #define TR_ANTENNAPROBLEM CENTER "TX Antennen Problem!" diff --git a/src/translations/en.h b/src/translations/en.h index e4c340c4f..b82468e9c 100644 --- a/src/translations/en.h +++ b/src/translations/en.h @@ -74,6 +74,9 @@ #define LEN_VTRIMINC TR("\006","\013") #define TR_VTRIMINC TR("Expo ""ExFine""Fine ""Medium""Coarse","Exponential""Extra Fine ""Fine ""Medium ""Coarse ") +#define LEN_VBEEPCOUNTDOWN "\006" +#define TR_VBEEPCOUNTDOWN "SilentBeeps\0Voice\0" + #define LEN_RETA123 "\001" #if defined(PCBGRUVIN9X) @@ -384,7 +387,11 @@ #define TR_MODELNAME "Model Name" #define TR_PHASENAME "Mode Name" #define TR_MIXNAME "Mix Name" -#define TR_EXPONAME "Expo Name" +#if defined(PCBTARANIS) + #define TR_EXPONAME "Line Name" +#else + #define TR_EXPONAME "Expo Name" +#endif #define TR_BITMAP "Model Image" #define TR_TIMER TR("Timer","Timer ") #define TR_ELIMITS TR("E.Limits","Extended Limits") @@ -490,13 +497,13 @@ #define TR_TMR1JITTERUS "Tmr1 Jitter\006us" #if defined(CPUARM) - #define TR_TMIXMAXMS "Tmix max\012ms" + #define TR_TMIXMAXMS "Tmix max" + #define TR_FREESTACKMINB "Free Stack" #else #define TR_TMIXMAXMS "Tmix max\014ms" + #define TR_FREESTACKMINB "Free Stack\010b" #endif -#define TR_T10MSUS "T10ms\016us" -#define TR_FREESTACKMINB "Free Stack\010b" #define TR_MENUTORESET CENTER TR_ENTER " to reset" #define TR_PPM "PPM" #define TR_CH "CH" @@ -526,11 +533,14 @@ #define TR_MENUFLIGHTPHASES "FLIGHT MODES" #define TR_MENUHELISETUP "HELI SETUP" -#if defined(PPM_CENTER_ADJUSTABLE) || defined(PPM_LIMITS_SYMETRICAL) // The right menu titles for the gurus ... - #define TR_MENUDREXPO "STICKS" +#if defined(PCBTARANIS) + #define TR_MENUINPUTS "INPUTS" + #define TR_MENULIMITS "SERVOS" +#elif defined(PPM_CENTER_ADJUSTABLE) || defined(PPM_LIMITS_SYMETRICAL) // The right menu titles for the gurus ... + #define TR_MENUINPUTS "STICKS" #define TR_MENULIMITS "SERVOS" #else - #define TR_MENUDREXPO "DR/EXPO" + #define TR_MENUINPUTS "DR/EXPO" #define TR_MENULIMITS "LIMITS" #endif @@ -633,6 +643,7 @@ #define TR_MOVE "Move" #define TR_PASTE "Paste" #define TR_DELETE "Delete" +#define TR_INSERT "Insert" #define TR_RESET_FLIGHT "Reset Flight" #define TR_RESET_TIMER1 "Reset Timer1" #define TR_RESET_TIMER2 "Reset Timer2" @@ -646,7 +657,7 @@ #define TR_BYTES "bytes" #define TR_MODULE_BIND "[Bind]" #define TR_MODULE_RANGE "[Range]" -#define TR_RESET "[Reset]" +#define TR_RESET_BTN "[Reset]" #define TR_SET "[Set]" #define TR_TRAINER "Trainer" #define TR_ANTENNAPROBLEM CENTER "TX Antenna problem!" @@ -686,7 +697,7 @@ // Taranis column headers #define TR_PHASES_HEADERS { " Name ", " Switch ", " Trims ", " Fade In ", " Fade Out " } -#define TR_LIMITS_HEADERS { " Name ", " Subtrim ", " Min ", " Max ", " Direction ", " PPM Center ", " Subtrim mode " } +#define TR_LIMITS_HEADERS { " Name ", " Subtrim ", " Min ", " Max ", " Direction ", " Curve ", " PPM Center ", " Subtrim mode " } #define TR_CSW_HEADERS { " Function ", " V1 ", " V2 ", " AND Switch ", " Duration ", " Delay " } // About screen @@ -745,3 +756,9 @@ #define TR_WAV_VOLUME "Wav Volume" #define TR_VARIO_VOLUME "Vario Volume" #define TR_BG_VOLUME "Bg Volume" + +#define TR_TOP_BAR "Top Bar" +#define TR_ALTITUDE INDENT "Altitude" +#define TR_MODS_FORBIDDEN "Modifications forbidden!" +#define TR_UNLOCKED "Unlocked" + diff --git a/src/translations/es.h b/src/translations/es.h index 3fe1d6de5..5bedd91fe 100644 --- a/src/translations/es.h +++ b/src/translations/es.h @@ -1,4 +1,4 @@ -/* +/* * Authors (alphabetical order) * - Bertrand Songis * - Bernet Andre @@ -527,10 +527,10 @@ #define TR_MENUHELISETUP "CONF. HELI" #if defined(PPM_CENTER_ADJUSTABLE) || defined(PPM_LIMITS_SYMETRICAL) // The right menu titles for the gurus ... - #define TR_MENUDREXPO "STICKS" + #define TR_MENUINPUTS "STICKS" #define TR_MENULIMITS "SERVOS" #else - #define TR_MENUDREXPO "DR/EXPO" + #define TR_MENUINPUTS "DR/EXPO" #define TR_MENULIMITS "LIMITES" #endif @@ -610,7 +610,7 @@ #define TR_SD_TYPE "Tipo:" #define TR_SD_SPEED "Velocidad:" #define TR_SD_SECTORS "Sectores:" -#define TR_SD_SIZE "Tamaño:" +#define TR_SD_SIZE "Tama\201o:" #define TR_TYPE "Tipo" #define TR_GLOBAL_VARS "Global Variables" #define TR_GLOBAL_VAR "Global Variable" @@ -646,10 +646,10 @@ #define TR_BYTES "bytes" #define TR_MODULE_BIND "[Enlace]" #define TR_MODULE_RANGE "[Limites]" -#define TR_RESET "[Reset]" +#define TR_RESET_BTN "[Reset]" #define TR_SET "[Ajuste]" #define TR_TRAINER "Aprendiz" -#define TR_ANTENNAPROBLEM CENTER "¡Problema antena TX!" +#define TR_ANTENNAPROBLEM CENTER "¡Problema antena TX!" #define TR_MODELIDUSED TR("ID en uso", "ID modelo en uso") #define TR_MODULE INDENT "Modulo" #define TR_CHANNELRANGE INDENT "Gama de canales" @@ -684,7 +684,7 @@ // Taranis column headers #define TR_PHASES_HEADERS { " Nombre ", " Interrup.", " Trims ", " Aparecer ", " Desparecer " } -#define TR_LIMITS_HEADERS { " Nombre ", " Compensacion", " Min ", " Max ", " Direccion ", " Centrado PPM ", " Simetrica " } +#define TR_LIMITS_HEADERS { " Nombre ", " Compensacion", " Min ", " Max ", " Direccion ", " Curve ", " Centrado PPM ", " Simetrica " } #define TR_CSW_HEADERS { " Funcion ", " V1 ", " V2 ", " AND Interrup. ", " Duracion ", " Retardo " } //Taranis About screen @@ -742,4 +742,4 @@ #define TR_BEEP_VOLUME "Volumen Beep" #define TR_WAV_VOLUME "Volumen Wav" #define TR_VARIO_VOLUME "Volumen Vario" -#define TR_BG_VOLUME "Volumen Bg" \ No newline at end of file +#define TR_BG_VOLUME "Volumen Bg" diff --git a/src/translations/es.h.txt b/src/translations/es.h.txt index b777a37d1..58e6496e6 100644 --- a/src/translations/es.h.txt +++ b/src/translations/es.h.txt @@ -527,10 +527,10 @@ #define TR_MENUHELISETUP "CONF. HELI" #if defined(PPM_CENTER_ADJUSTABLE) || defined(PPM_LIMITS_SYMETRICAL) // The right menu titles for the gurus ... - #define TR_MENUDREXPO "STICKS" + #define TR_MENUINPUTS "STICKS" #define TR_MENULIMITS "SERVOS" #else - #define TR_MENUDREXPO "DR/EXPO" + #define TR_MENUINPUTS "DR/EXPO" #define TR_MENULIMITS "LIMITES" #endif @@ -646,7 +646,7 @@ #define TR_BYTES "bytes" #define TR_MODULE_BIND "[Enlace]" #define TR_MODULE_RANGE "[Limites]" -#define TR_RESET "[Reset]" +#define TR_RESET_BTN "[Reset]" #define TR_SET "[Ajuste]" #define TR_TRAINER "Aprendiz" #define TR_ANTENNAPROBLEM CENTER "¡Problema antena TX!" @@ -684,7 +684,7 @@ // Taranis column headers #define TR_PHASES_HEADERS { " Nombre ", " Interrup.", " Trims ", " Aparecer ", " Desparecer " } -#define TR_LIMITS_HEADERS { " Nombre ", " Compensacion", " Min ", " Max ", " Direccion ", " Centrado PPM ", " Simetrica " } +#define TR_LIMITS_HEADERS { " Nombre ", " Compensacion", " Min ", " Max ", " Direccion ", " Curve ", " Centrado PPM ", " Simetrica " } #define TR_CSW_HEADERS { " Funcion ", " V1 ", " V2 ", " AND Interrup. ", " Duracion ", " Retardo " } //Taranis About screen diff --git a/src/translations/fr.h b/src/translations/fr.h index f9a022840..923ff8889 100644 --- a/src/translations/fr.h +++ b/src/translations/fr.h @@ -527,10 +527,10 @@ #define TR_MENUHELISETUP TR("CONF.HELI","CONFIGURATION HELICO") #if defined(PPM_CENTER_ADJUSTABLE) || defined(PPM_LIMITS_SYMETRICAL) // The right menu titles for the gurus ... - #define TR_MENUDREXPO "MANCHES" + #define TR_MENUINPUTS "MANCHES" #define TR_MENULIMITS "SORTIES" #else - #define TR_MENUDREXPO "DR/EXPO" + #define TR_MENUINPUTS "DR/EXPO" #define TR_MENULIMITS "LIMITES" #endif @@ -646,7 +646,7 @@ #define TR_BYTES "bytes" #define TR_MODULE_BIND "[Bind]" #define TR_MODULE_RANGE "[Port.]" -#define TR_RESET "[RAZ]" +#define TR_RESET_BTN "[RAZ]" #define TR_SET "[D\200f.]" #define TR_TRAINER "Ecolage" #define TR_ANTENNAPROBLEM CENTER "Antenne radio d\200fectueuse!" @@ -684,7 +684,7 @@ // Taranis column headers #define TR_PHASES_HEADERS { " Nom ", " Inter ", " Trims ", " Fondu ON ", " Fondu OFF " } -#define TR_LIMITS_HEADERS { " Nom ", " Subtrim ", " Min ", " Max ", " Direction ", " Neutre PPM ", " Mode subtrim " } +#define TR_LIMITS_HEADERS { " Nom ", " Subtrim ", " Min ", " Max ", " Direction ", " Curve ", " Neutre PPM ", " Mode subtrim " } #define TR_CSW_HEADERS { " Fonction ", " V1 ", " V2 ", " ET suppl. ", " Dur\200e ", " D\200lai " } //Taranis About screen diff --git a/src/translations/fr.h.txt b/src/translations/fr.h.txt index ec3d01669..8850301f8 100644 --- a/src/translations/fr.h.txt +++ b/src/translations/fr.h.txt @@ -527,10 +527,10 @@ #define TR_MENUHELISETUP TR("CONF.HELI","CONFIGURATION HELICO") #if defined(PPM_CENTER_ADJUSTABLE) || defined(PPM_LIMITS_SYMETRICAL) // The right menu titles for the gurus ... - #define TR_MENUDREXPO "MANCHES" + #define TR_MENUINPUTS "MANCHES" #define TR_MENULIMITS "SORTIES" #else - #define TR_MENUDREXPO "DR/EXPO" + #define TR_MENUINPUTS "DR/EXPO" #define TR_MENULIMITS "LIMITES" #endif @@ -646,7 +646,7 @@ #define TR_BYTES "bytes" #define TR_MODULE_BIND "[Bind]" #define TR_MODULE_RANGE "[Port.]" -#define TR_RESET "[RAZ]" +#define TR_RESET_BTN "[RAZ]" #define TR_SET "[Déf.]" #define TR_TRAINER "Ecolage" #define TR_ANTENNAPROBLEM CENTER "Antenne radio défectueuse!" @@ -684,7 +684,7 @@ // Taranis column headers #define TR_PHASES_HEADERS { " Nom ", " Inter ", " Trims ", " Fondu ON ", " Fondu OFF " } -#define TR_LIMITS_HEADERS { " Nom ", " Subtrim ", " Min ", " Max ", " Direction ", " Neutre PPM ", " Mode subtrim " } +#define TR_LIMITS_HEADERS { " Nom ", " Subtrim ", " Min ", " Max ", " Direction ", " Curve ", " Neutre PPM ", " Mode subtrim " } #define TR_CSW_HEADERS { " Fonction ", " V1 ", " V2 ", " ET suppl. ", " Durée ", " Délai " } //Taranis About screen diff --git a/src/translations/it.h b/src/translations/it.h index 16b309383..72f53001d 100644 --- a/src/translations/it.h +++ b/src/translations/it.h @@ -527,10 +527,10 @@ #define TR_MENUHELISETUP "SETUP ELI" #if defined(PPM_CENTER_ADJUSTABLE) || defined(PPM_LIMITS_SYMETRICAL) // The right menu titles for the gurus ... - #define TR_MENUDREXPO "STICK" + #define TR_MENUINPUTS "STICK" #define TR_MENULIMITS "USCITE" #else - #define TR_MENUDREXPO "DR/ESPO" + #define TR_MENUINPUTS "DR/ESPO" #define TR_MENULIMITS "LIMITI" #endif @@ -646,7 +646,7 @@ #define TR_BYTES "bytes" #define TR_MODULE_BIND "[Bind]" #define TR_MODULE_RANGE "[Range]" -#define TR_RESET "[Reset]" +#define TR_RESET_BTN "[Reset]" #define TR_SET "[Set]" #define TR_TRAINER TR("Trainer","Maestro/Allievo") #define TR_ANTENNAPROBLEM CENTER "Problemi antenna TX!" @@ -684,7 +684,7 @@ // Taranis column headers #define TR_PHASES_HEADERS { " Nome ", " Switch ", " Trims ", " Fade In ", " Fade Out " } -#define TR_LIMITS_HEADERS { " Nome ", " Offset ", " Min ", " Max ", " Direzione ", " Centro PPM ", " Simmetria " } +#define TR_LIMITS_HEADERS { " Nome ", " Offset ", " Min ", " Max ", " Direzione ", " Curve ", " Centro PPM ", " Simmetria " } #define TR_CSW_HEADERS { " Funzione ", " V1 ", " V2 ", " AND Switch ", " Durata ", " Ritardo " } //Taranis About screen diff --git a/src/translations/it.h.txt b/src/translations/it.h.txt index 56a2d714a..43943cfcb 100644 --- a/src/translations/it.h.txt +++ b/src/translations/it.h.txt @@ -527,10 +527,10 @@ #define TR_MENUHELISETUP "SETUP ELI" #if defined(PPM_CENTER_ADJUSTABLE) || defined(PPM_LIMITS_SYMETRICAL) // The right menu titles for the gurus ... - #define TR_MENUDREXPO "STICK" + #define TR_MENUINPUTS "STICK" #define TR_MENULIMITS "USCITE" #else - #define TR_MENUDREXPO "DR/ESPO" + #define TR_MENUINPUTS "DR/ESPO" #define TR_MENULIMITS "LIMITI" #endif @@ -646,7 +646,7 @@ #define TR_BYTES "bytes" #define TR_MODULE_BIND "[Bind]" #define TR_MODULE_RANGE "[Range]" -#define TR_RESET "[Reset]" +#define TR_RESET_BTN "[Reset]" #define TR_SET "[Set]" #define TR_TRAINER TR("Trainer","Maestro/Allievo") #define TR_ANTENNAPROBLEM CENTER "Problemi antenna TX!" @@ -684,7 +684,7 @@ // Taranis column headers #define TR_PHASES_HEADERS { " Nome ", " Switch ", " Trims ", " Fade In ", " Fade Out " } -#define TR_LIMITS_HEADERS { " Nome ", " Offset ", " Min ", " Max ", " Direzione ", " Centro PPM ", " Simmetria " } +#define TR_LIMITS_HEADERS { " Nome ", " Offset ", " Min ", " Max ", " Direzione ", " Curve ", " Centro PPM ", " Simmetria " } #define TR_CSW_HEADERS { " Funzione ", " V1 ", " V2 ", " AND Switch ", " Durata ", " Ritardo " } //Taranis About screen diff --git a/src/translations/pt.h b/src/translations/pt.h index ab8eb844e..86bbeaa8e 100644 --- a/src/translations/pt.h +++ b/src/translations/pt.h @@ -527,10 +527,10 @@ #define TR_MENUHELISETUP "HELI SETUP" #if defined(PPM_CENTER_ADJUSTABLE) || defined(PPM_LIMITS_SYMETRICAL) // The right menu titles for the gurus ... - #define TR_MENUDREXPO "STICKS" + #define TR_MENUINPUTS "STICKS" #define TR_MENULIMITS "SAIDAS" #else - #define TR_MENUDREXPO "DR/EXPO" + #define TR_MENUINPUTS "DR/EXPO" #define TR_MENULIMITS "LIMITES" #endif @@ -646,7 +646,7 @@ #define TR_BYTES "bytes" #define TR_MODULE_BIND "[Bind]" #define TR_MODULE_RANGE "[Range]" -#define TR_RESET "[Reset]" +#define TR_RESET_BTN "[Reset]" #define TR_SET "[Set]" #define TR_TRAINER "Trainer" #define TR_ANTENNAPROBLEM CENTER "TX Antenna problem!" @@ -684,7 +684,7 @@ // Taranis column headers #define TR_PHASES_HEADERS { " Name ", " Switch ", " Trims ", " Fade In ", " Fade Out " } -#define TR_LIMITS_HEADERS { " Name ", " Offset ", " Min ", " Max ", " Direction ", " PPM Center ", " Symmetrical " } +#define TR_LIMITS_HEADERS { " Name ", " Offset ", " Min ", " Max ", " Direction ", " Curve ", " PPM Center ", " Symmetrical " } #define TR_CSW_HEADERS { " Function ", " V1 ", " V2 ", " AND Switch ", " Duration ", " Delay " } //Taranis About screen diff --git a/src/translations/pt.h.txt b/src/translations/pt.h.txt index ab8eb844e..86bbeaa8e 100644 --- a/src/translations/pt.h.txt +++ b/src/translations/pt.h.txt @@ -527,10 +527,10 @@ #define TR_MENUHELISETUP "HELI SETUP" #if defined(PPM_CENTER_ADJUSTABLE) || defined(PPM_LIMITS_SYMETRICAL) // The right menu titles for the gurus ... - #define TR_MENUDREXPO "STICKS" + #define TR_MENUINPUTS "STICKS" #define TR_MENULIMITS "SAIDAS" #else - #define TR_MENUDREXPO "DR/EXPO" + #define TR_MENUINPUTS "DR/EXPO" #define TR_MENULIMITS "LIMITES" #endif @@ -646,7 +646,7 @@ #define TR_BYTES "bytes" #define TR_MODULE_BIND "[Bind]" #define TR_MODULE_RANGE "[Range]" -#define TR_RESET "[Reset]" +#define TR_RESET_BTN "[Reset]" #define TR_SET "[Set]" #define TR_TRAINER "Trainer" #define TR_ANTENNAPROBLEM CENTER "TX Antenna problem!" @@ -684,7 +684,7 @@ // Taranis column headers #define TR_PHASES_HEADERS { " Name ", " Switch ", " Trims ", " Fade In ", " Fade Out " } -#define TR_LIMITS_HEADERS { " Name ", " Offset ", " Min ", " Max ", " Direction ", " PPM Center ", " Symmetrical " } +#define TR_LIMITS_HEADERS { " Name ", " Offset ", " Min ", " Max ", " Direction ", " Curve ", " PPM Center ", " Symmetrical " } #define TR_CSW_HEADERS { " Function ", " V1 ", " V2 ", " AND Switch ", " Duration ", " Delay " } //Taranis About screen diff --git a/src/translations/se.h b/src/translations/se.h index 266806bcc..3ea4957c3 100644 --- a/src/translations/se.h +++ b/src/translations/se.h @@ -646,7 +646,7 @@ #define TR_BYTES "bytes" #define TR_MODULE_BIND "[Bind]" #define TR_MODULE_RANGE "[Testa]" -#define TR_RESET "[Nollst\201ll]" +#define TR_RESET_BTN "[Nollst\201ll]" #define TR_SET "[Spara]" #define TR_TRAINER "Trainer" #define TR_ANTENNAPROBLEM CENTER "Fel p\200 TX-antennen" diff --git a/src/translations/se.h.txt b/src/translations/se.h.txt index a06ad3bf5..b98b8b4e8 100644 --- a/src/translations/se.h.txt +++ b/src/translations/se.h.txt @@ -646,7 +646,7 @@ #define TR_BYTES "bytes" #define TR_MODULE_BIND "[Bind]" #define TR_MODULE_RANGE "[Testa]" -#define TR_RESET "[Nollställ]" +#define TR_RESET_BTN "[Nollställ]" #define TR_SET "[Spara]" #define TR_TRAINER "Trainer" #define TR_ANTENNAPROBLEM CENTER "Fel på TX-antennen"