mirror of
https://github.com/opentx/opentx.git
synced 2025-07-25 17:25:13 +03:00
parent
bb2ca31dad
commit
8b4d2b698d
69 changed files with 5577 additions and 425 deletions
|
@ -129,27 +129,45 @@ endforeach()
|
|||
|
||||
set(SRC ${SRC} debug.cpp)
|
||||
|
||||
if(${EEPROM} STREQUAL SDCARD)
|
||||
set(SRC ${SRC} storage/storage_common.cpp storage/sdcard_raw.cpp)
|
||||
elseif(${EEPROM} STREQUAL EEPROM_RLC)
|
||||
set(SRC ${SRC} storage/storage_common.cpp storage/eeprom_common.cpp storage/eeprom_rlc.cpp)
|
||||
add_definitions(-DEEPROM -DEEPROM_RLC)
|
||||
else()
|
||||
set(SRC ${SRC} storage/storage_common.cpp storage/eeprom_common.cpp storage/eeprom_raw.cpp)
|
||||
add_definitions(-DEEPROM -DEEPROM_RAW)
|
||||
endif()
|
||||
|
||||
include(storage/conversions/CMakeLists.txt)
|
||||
|
||||
add_definitions(-DFLAVOUR="${FLAVOUR}")
|
||||
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
|
||||
include_directories(${CMAKE_CURRENT_BINARY_DIR})
|
||||
include_directories(${CMAKE_CURRENT_BINARY_DIR}/bitmaps/${GUI_DIR})
|
||||
|
||||
add_subdirectory(lua)
|
||||
include(gui/CMakeLists.txt)
|
||||
|
||||
set(SRC ${SRC} storage/storage_common.cpp)
|
||||
if(${STORAGE} STREQUAL SDCARD)
|
||||
set(SRC ${SRC} storage/modelslist.cpp storage/sdcard_common.cpp)
|
||||
if(${STORAGE_FORMAT} STREQUAL BIN)
|
||||
set(SRC ${SRC} storage/sdcard_raw.cpp)
|
||||
add_definitions(-DSDCARD_RAW)
|
||||
elseif(${STORAGE_FORMAT} STREQUAL YAML)
|
||||
set(SRC ${SRC} storage/sdcard_yaml.cpp)
|
||||
add_definitions(-DSDCARD_YAML)
|
||||
include(storage/yaml/CMakeLists.txt)
|
||||
#add_subdirectory(storage/yaml)
|
||||
endif()
|
||||
elseif(${STORAGE} STREQUAL EEPROM)
|
||||
set(SRC ${SRC} storage/eeprom_common.cpp)
|
||||
add_definitions(-DEEPROM)
|
||||
if(${STORAGE_FORMAT} STREQUAL RLC)
|
||||
set(SRC ${SRC} storage/eeprom_rlc.cpp)
|
||||
add_definitions(-DEEPROM_RLC)
|
||||
elseif(${STORAGE_FORMAT} STREQUAL RAW)
|
||||
set(SRC ${SRC} storage/eeprom_raw.cpp)
|
||||
add_definitions(-DEEPROM_RAW)
|
||||
else()
|
||||
set(SRC ${SRC} storage/eeprom_none.cpp)
|
||||
add_definitions(-DEEPROM_NONE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
include(storage/conversions/CMakeLists.txt)
|
||||
|
||||
add_subdirectory(lua)
|
||||
|
||||
if(RAMBACKUP)
|
||||
add_definitions(-DRAMBACKUP)
|
||||
set(SRC ${SRC} storage/rambackup.cpp storage/rlc.cpp)
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#define _DATACONSTANTS_H_
|
||||
|
||||
#include "board.h"
|
||||
#include "storage/yaml/yaml_defs.h"
|
||||
|
||||
#define NUM_STICKS 4
|
||||
|
||||
|
@ -384,7 +385,7 @@ enum PotsWarnMode {
|
|||
enum SwitchSources {
|
||||
SWSRC_NONE = 0,
|
||||
|
||||
SWSRC_FIRST_SWITCH,
|
||||
SWSRC_FIRST_SWITCH SKIP,
|
||||
|
||||
#if defined(STORAGE_SWITCH_A)
|
||||
SWSRC_SA0 = SWSRC_FIRST_SWITCH,
|
||||
|
@ -504,18 +505,18 @@ enum SwitchSources {
|
|||
SWSRC_AIL,
|
||||
SWSRC_GEA,
|
||||
SWSRC_TRN,
|
||||
SWSRC_TRAINER = SWSRC_TRN,
|
||||
SWSRC_LAST_SWITCH = SWSRC_TRN,
|
||||
SWSRC_TRAINER SKIP = SWSRC_TRN,
|
||||
SWSRC_LAST_SWITCH SKIP = SWSRC_TRN,
|
||||
#else
|
||||
SWSRC_LAST_SWITCH = SWSRC_FIRST_SWITCH + STORAGE_NUM_SWITCHES_POSITIONS - 1,
|
||||
SWSRC_LAST_SWITCH SKIP = SWSRC_FIRST_SWITCH + STORAGE_NUM_SWITCHES_POSITIONS - 1,
|
||||
#endif
|
||||
|
||||
#if NUM_XPOTS > 0
|
||||
SWSRC_FIRST_MULTIPOS_SWITCH,
|
||||
SWSRC_LAST_MULTIPOS_SWITCH = SWSRC_FIRST_MULTIPOS_SWITCH + (NUM_XPOTS * XPOTS_MULTIPOS_COUNT) - 1,
|
||||
SWSRC_FIRST_MULTIPOS_SWITCH SKIP,
|
||||
SWSRC_LAST_MULTIPOS_SWITCH SKIP = SWSRC_FIRST_MULTIPOS_SWITCH + (NUM_XPOTS * XPOTS_MULTIPOS_COUNT) - 1,
|
||||
#endif
|
||||
|
||||
SWSRC_FIRST_TRIM,
|
||||
SWSRC_FIRST_TRIM SKIP,
|
||||
SWSRC_TrimRudLeft = SWSRC_FIRST_TRIM,
|
||||
SWSRC_TrimRudRight,
|
||||
SWSRC_TrimEleDown,
|
||||
|
@ -539,22 +540,22 @@ enum SwitchSources {
|
|||
SWSRC_REa,
|
||||
#endif
|
||||
|
||||
SWSRC_FIRST_LOGICAL_SWITCH,
|
||||
SWSRC_FIRST_LOGICAL_SWITCH SKIP,
|
||||
SWSRC_SW1 = SWSRC_FIRST_LOGICAL_SWITCH,
|
||||
SWSRC_SW2,
|
||||
// ...
|
||||
SWSRC_LAST_LOGICAL_SWITCH = SWSRC_FIRST_LOGICAL_SWITCH+MAX_LOGICAL_SWITCHES-1,
|
||||
SWSRC_LAST_LOGICAL_SWITCH SKIP = SWSRC_FIRST_LOGICAL_SWITCH+MAX_LOGICAL_SWITCHES-1,
|
||||
|
||||
SWSRC_ON,
|
||||
SWSRC_ONE,
|
||||
|
||||
SWSRC_FIRST_FLIGHT_MODE,
|
||||
SWSRC_LAST_FLIGHT_MODE = SWSRC_FIRST_FLIGHT_MODE+MAX_FLIGHT_MODES-1,
|
||||
SWSRC_FIRST_FLIGHT_MODE SKIP,
|
||||
SWSRC_LAST_FLIGHT_MODE SKIP = SWSRC_FIRST_FLIGHT_MODE+MAX_FLIGHT_MODES-1,
|
||||
|
||||
SWSRC_TELEMETRY_STREAMING,
|
||||
|
||||
SWSRC_FIRST_SENSOR,
|
||||
SWSRC_LAST_SENSOR = SWSRC_FIRST_SENSOR+MAX_TELEMETRY_SENSORS-1,
|
||||
SWSRC_FIRST_SENSOR SKIP,
|
||||
SWSRC_LAST_SENSOR SKIP = SWSRC_FIRST_SENSOR+MAX_TELEMETRY_SENSORS-1,
|
||||
|
||||
SWSRC_RADIO_ACTIVITY,
|
||||
|
||||
|
@ -562,20 +563,20 @@ enum SwitchSources {
|
|||
SWSRC_LATENCY_TOGGLE,
|
||||
#endif
|
||||
|
||||
SWSRC_COUNT,
|
||||
SWSRC_COUNT SKIP,
|
||||
|
||||
SWSRC_OFF = -SWSRC_ON,
|
||||
|
||||
SWSRC_LAST = SWSRC_COUNT-1,
|
||||
SWSRC_FIRST = -SWSRC_LAST,
|
||||
SWSRC_LAST SKIP = SWSRC_COUNT-1,
|
||||
SWSRC_FIRST SKIP = -SWSRC_LAST,
|
||||
|
||||
SWSRC_LAST_IN_LOGICAL_SWITCHES = SWSRC_COUNT-1,
|
||||
SWSRC_LAST_IN_MIXES = SWSRC_COUNT-1,
|
||||
SWSRC_LAST_IN_LOGICAL_SWITCHES SKIP = SWSRC_COUNT-1,
|
||||
SWSRC_LAST_IN_MIXES SKIP = SWSRC_COUNT-1,
|
||||
|
||||
SWSRC_FIRST_IN_LOGICAL_SWITCHES = -SWSRC_LAST_IN_LOGICAL_SWITCHES,
|
||||
SWSRC_FIRST_IN_MIXES = -SWSRC_LAST_IN_MIXES,
|
||||
SWSRC_FIRST_IN_LOGICAL_SWITCHES SKIP = -SWSRC_LAST_IN_LOGICAL_SWITCHES,
|
||||
SWSRC_FIRST_IN_MIXES SKIP = -SWSRC_LAST_IN_MIXES,
|
||||
|
||||
SWSRC_INVERT = SWSRC_COUNT+1,
|
||||
SWSRC_INVERT SKIP = SWSRC_COUNT+1,
|
||||
};
|
||||
|
||||
#if NUM_SWITCHES >= 8
|
||||
|
@ -589,22 +590,22 @@ enum SwitchSources {
|
|||
enum MixSources {
|
||||
MIXSRC_NONE,
|
||||
|
||||
MIXSRC_FIRST_INPUT, LUA_EXPORT_MULTIPLE("input", "Input [I%d]", MAX_INPUTS)
|
||||
MIXSRC_LAST_INPUT = MIXSRC_FIRST_INPUT+MAX_INPUTS-1,
|
||||
MIXSRC_FIRST_INPUT SKIP, LUA_EXPORT_MULTIPLE("input", "Input [I%d]", MAX_INPUTS)
|
||||
MIXSRC_LAST_INPUT SKIP = MIXSRC_FIRST_INPUT+MAX_INPUTS-1,
|
||||
|
||||
#if defined(LUA_INPUTS)
|
||||
MIXSRC_FIRST_LUA, LUA_EXPORT_MULTIPLE("lua", "Lua mix output %d", MAX_SCRIPTS*MAX_SCRIPT_OUTPUTS)
|
||||
MIXSRC_LAST_LUA = MIXSRC_FIRST_LUA+(MAX_SCRIPTS*MAX_SCRIPT_OUTPUTS)-1,
|
||||
MIXSRC_FIRST_LUA SKIP, LUA_EXPORT_MULTIPLE("lua", "Lua mix output %d", MAX_SCRIPTS*MAX_SCRIPT_OUTPUTS)
|
||||
MIXSRC_LAST_LUA SKIP = MIXSRC_FIRST_LUA+(MAX_SCRIPTS*MAX_SCRIPT_OUTPUTS)-1,
|
||||
#endif
|
||||
|
||||
MIXSRC_FIRST_STICK,
|
||||
MIXSRC_FIRST_STICK SKIP,
|
||||
MIXSRC_Rud = MIXSRC_FIRST_STICK, LUA_EXPORT("rud", "Rudder")
|
||||
MIXSRC_Ele, LUA_EXPORT("ele", "Elevator")
|
||||
MIXSRC_Thr, LUA_EXPORT("thr", "Throttle")
|
||||
MIXSRC_Ail, LUA_EXPORT("ail", "Aileron")
|
||||
|
||||
MIXSRC_LAST_STICK = MIXSRC_Ail,
|
||||
MIXSRC_FIRST_POT,
|
||||
MIXSRC_LAST_STICK SKIP = MIXSRC_Ail,
|
||||
MIXSRC_FIRST_POT SKIP,
|
||||
#if defined(PCBHORUS)
|
||||
MIXSRC_S1 = MIXSRC_FIRST_POT, LUA_EXPORT("s1", "Potentiometer S1")
|
||||
MIXSRC_6POS, LUA_EXPORT("6pos", "Multipos Switch")
|
||||
|
@ -613,7 +614,7 @@ enum MixSources {
|
|||
MIXSRC_EXT1, LUA_EXPORT("ext1", "Ext 1")
|
||||
MIXSRC_EXT2, LUA_EXPORT("ext2", "Ext 2")
|
||||
#endif
|
||||
MIXSRC_FIRST_SLIDER,
|
||||
MIXSRC_FIRST_SLIDER SKIP,
|
||||
#if defined(PCBX12S)
|
||||
MIXSRC_S3 = MIXSRC_FIRST_SLIDER, LUA_EXPORT("s3", "Slider S3")
|
||||
MIXSRC_S4, LUA_EXPORT("s4", "Slider S4")
|
||||
|
@ -623,7 +624,7 @@ enum MixSources {
|
|||
MIXSRC_LS = MIXSRC_FIRST_SLIDER, LUA_EXPORT("ls", "Left slider")
|
||||
MIXSRC_RS, LUA_EXPORT("rs", "Right slider")
|
||||
#endif
|
||||
MIXSRC_LAST_POT = MIXSRC_RS,
|
||||
MIXSRC_LAST_POT SKIP = MIXSRC_RS,
|
||||
#elif defined(PCBX9E)
|
||||
MIXSRC_POT1 = MIXSRC_FIRST_POT, LUA_EXPORT("s1", "Potentiometer 1")
|
||||
MIXSRC_POT2, LUA_EXPORT("s2", "Potentiometer 2")
|
||||
|
@ -634,27 +635,27 @@ enum MixSources {
|
|||
MIXSRC_SLIDER2, LUA_EXPORT("rs", "Right slider")
|
||||
MIXSRC_SLIDER3, LUA_EXPORT("lcs", "Left center slider (X9E only)")
|
||||
MIXSRC_SLIDER4, LUA_EXPORT("rcs", "Right center slider (X9E only)")
|
||||
MIXSRC_LAST_POT = MIXSRC_SLIDER4,
|
||||
MIXSRC_LAST_POT SKIP = MIXSRC_SLIDER4,
|
||||
#elif defined(PCBX7) || defined(PCBXLITE) || defined(PCBNV14)
|
||||
MIXSRC_POT1 = MIXSRC_FIRST_POT, LUA_EXPORT("s1", "Potentiometer 1")
|
||||
MIXSRC_POT2, LUA_EXPORT("s2", "Potentiometer 2")
|
||||
MIXSRC_LAST_POT = MIXSRC_POT2,
|
||||
MIXSRC_LAST_POT SKIP = MIXSRC_POT2,
|
||||
#elif defined(PCBX9LITE)
|
||||
MIXSRC_POT1 = MIXSRC_FIRST_POT, LUA_EXPORT("s1", "Potentiometer 1")
|
||||
MIXSRC_LAST_POT = MIXSRC_POT1,
|
||||
MIXSRC_LAST_POT SKIP = MIXSRC_POT1,
|
||||
#elif defined(PCBTARANIS)
|
||||
MIXSRC_POT1 = MIXSRC_FIRST_POT, LUA_EXPORT("s1", "Potentiometer 1")
|
||||
MIXSRC_POT2, LUA_EXPORT("s2", "Potentiometer 2")
|
||||
MIXSRC_POT3, LUA_EXPORT("s3", "Potentiometer 3")
|
||||
MIXSRC_FIRST_SLIDER,
|
||||
MIXSRC_FIRST_SLIDER SKIP,
|
||||
MIXSRC_SLIDER1 = MIXSRC_FIRST_SLIDER, LUA_EXPORT("ls", "Left slider")
|
||||
MIXSRC_SLIDER2, LUA_EXPORT("rs", "Right slider")
|
||||
MIXSRC_LAST_POT = MIXSRC_SLIDER2,
|
||||
MIXSRC_LAST_POT SKIP = MIXSRC_SLIDER2,
|
||||
#else
|
||||
MIXSRC_P1 = MIXSRC_FIRST_POT,
|
||||
MIXSRC_P2,
|
||||
MIXSRC_P3,
|
||||
MIXSRC_LAST_POT = MIXSRC_P3,
|
||||
MIXSRC_LAST_POT SKIP = MIXSRC_P3,
|
||||
#endif
|
||||
|
||||
#if defined(PCBHORUS)
|
||||
|
@ -669,13 +670,13 @@ enum MixSources {
|
|||
|
||||
MIXSRC_MAX,
|
||||
|
||||
MIXSRC_FIRST_HELI,
|
||||
MIXSRC_FIRST_HELI SKIP,
|
||||
MIXSRC_CYC1 = MIXSRC_FIRST_HELI, LUA_EXPORT("cyc1", "Cyclic 1")
|
||||
MIXSRC_CYC2, LUA_EXPORT("cyc2", "Cyclic 2")
|
||||
MIXSRC_CYC3, LUA_EXPORT("cyc3", "Cyclic 3")
|
||||
MIXSRC_LAST_HELI = MIXSRC_CYC3,
|
||||
MIXSRC_LAST_HELI SKIP = MIXSRC_CYC3,
|
||||
|
||||
MIXSRC_FIRST_TRIM,
|
||||
MIXSRC_FIRST_TRIM SKIP,
|
||||
MIXSRC_TrimRud = MIXSRC_FIRST_TRIM, LUA_EXPORT("trim-rud", "Rudder trim")
|
||||
MIXSRC_TrimEle, LUA_EXPORT("trim-ele", "Elevator trim")
|
||||
MIXSRC_TrimThr, LUA_EXPORT("trim-thr", "Throttle trim")
|
||||
|
@ -683,12 +684,12 @@ enum MixSources {
|
|||
#if defined(PCBHORUS)
|
||||
MIXSRC_TrimT5, LUA_EXPORT("trim-t5", "Aux trim T5")
|
||||
MIXSRC_TrimT6, LUA_EXPORT("trim-t6", "Aux trim T6")
|
||||
MIXSRC_LAST_TRIM = MIXSRC_TrimT6,
|
||||
MIXSRC_LAST_TRIM SKIP = MIXSRC_TrimT6,
|
||||
#else
|
||||
MIXSRC_LAST_TRIM = MIXSRC_TrimAil,
|
||||
MIXSRC_LAST_TRIM SKIP = MIXSRC_TrimAil,
|
||||
#endif
|
||||
|
||||
MIXSRC_FIRST_SWITCH,
|
||||
MIXSRC_FIRST_SWITCH SKIP,
|
||||
|
||||
#if defined(HARDWARE_SWITCH_A)
|
||||
MIXSRC_SA = MIXSRC_FIRST_SWITCH, LUA_EXPORT("sa", "Switch A")
|
||||
|
@ -749,14 +750,14 @@ enum MixSources {
|
|||
MIXSRC_GEA,
|
||||
MIXSRC_TRN,
|
||||
#endif
|
||||
MIXSRC_FIRST_LOGICAL_SWITCH,
|
||||
MIXSRC_FIRST_LOGICAL_SWITCH SKIP,
|
||||
MIXSRC_SW1 = MIXSRC_FIRST_LOGICAL_SWITCH, LUA_EXPORT_MULTIPLE("ls", "Logical switch L%d", MAX_LOGICAL_SWITCHES)
|
||||
MIXSRC_LAST_LOGICAL_SWITCH = MIXSRC_FIRST_LOGICAL_SWITCH+MAX_LOGICAL_SWITCHES-1,
|
||||
MIXSRC_LAST_LOGICAL_SWITCH SKIP = MIXSRC_FIRST_LOGICAL_SWITCH+MAX_LOGICAL_SWITCHES-1,
|
||||
|
||||
MIXSRC_FIRST_TRAINER, LUA_EXPORT_MULTIPLE("trn", "Trainer input %d", MAX_TRAINER_CHANNELS)
|
||||
MIXSRC_LAST_TRAINER = MIXSRC_FIRST_TRAINER+MAX_TRAINER_CHANNELS-1,
|
||||
MIXSRC_FIRST_TRAINER SKIP, LUA_EXPORT_MULTIPLE("trn", "Trainer input %d", MAX_TRAINER_CHANNELS)
|
||||
MIXSRC_LAST_TRAINER SKIP = MIXSRC_FIRST_TRAINER+MAX_TRAINER_CHANNELS-1,
|
||||
|
||||
MIXSRC_FIRST_CH,
|
||||
MIXSRC_FIRST_CH SKIP,
|
||||
MIXSRC_CH1 = MIXSRC_FIRST_CH, LUA_EXPORT_MULTIPLE("ch", "Channel CH%d", MAX_OUTPUT_CHANNELS)
|
||||
MIXSRC_CH2,
|
||||
MIXSRC_CH3,
|
||||
|
@ -773,32 +774,32 @@ enum MixSources {
|
|||
MIXSRC_CH14,
|
||||
MIXSRC_CH15,
|
||||
MIXSRC_CH16,
|
||||
MIXSRC_LAST_CH = MIXSRC_CH1+MAX_OUTPUT_CHANNELS-1,
|
||||
MIXSRC_LAST_CH SKIP = MIXSRC_CH1+MAX_OUTPUT_CHANNELS-1,
|
||||
|
||||
MIXSRC_FIRST_GVAR,
|
||||
MIXSRC_FIRST_GVAR SKIP,
|
||||
MIXSRC_GVAR1 = MIXSRC_FIRST_GVAR, LUA_EXPORT_MULTIPLE("gvar", "Global variable %d", MAX_GVARS)
|
||||
MIXSRC_LAST_GVAR = MIXSRC_FIRST_GVAR+MAX_GVARS-1,
|
||||
MIXSRC_LAST_GVAR SKIP = MIXSRC_FIRST_GVAR+MAX_GVARS-1,
|
||||
|
||||
MIXSRC_TX_VOLTAGE, LUA_EXPORT("tx-voltage", "Transmitter battery voltage [volts]")
|
||||
MIXSRC_TX_TIME, LUA_EXPORT("clock", "RTC clock [minutes from midnight]")
|
||||
#if defined(INTERNAL_GPS)
|
||||
MIXSRC_TX_GPS,
|
||||
MIXSRC_FIRST_RESERVE,
|
||||
MIXSRC_FIRST_RESERVE SKIP,
|
||||
#else
|
||||
MIXSRC_FIRST_RESERVE,
|
||||
MIXSRC_RESERVE2,
|
||||
MIXSRC_FIRST_RESERVE SKIP,
|
||||
MIXSRC_RESERVE2 SKIP,
|
||||
#endif
|
||||
MIXSRC_RESERVE3,
|
||||
MIXSRC_RESERVE4,
|
||||
MIXSRC_LAST_RESERVE,
|
||||
MIXSRC_FIRST_TIMER,
|
||||
MIXSRC_RESERVE3 SKIP,
|
||||
MIXSRC_RESERVE4 SKIP,
|
||||
MIXSRC_LAST_RESERVE SKIP,
|
||||
MIXSRC_FIRST_TIMER SKIP,
|
||||
MIXSRC_TIMER1 = MIXSRC_FIRST_TIMER, LUA_EXPORT("timer1", "Timer 1 value [seconds]")
|
||||
MIXSRC_TIMER2, LUA_EXPORT("timer2", "Timer 2 value [seconds]")
|
||||
MIXSRC_TIMER3, LUA_EXPORT("timer3", "Timer 3 value [seconds]")
|
||||
MIXSRC_LAST_TIMER = MIXSRC_TIMER3,
|
||||
MIXSRC_LAST_TIMER SKIP = MIXSRC_TIMER3,
|
||||
|
||||
MIXSRC_FIRST_TELEM, LUA_EXPORT_MULTIPLE("telem", "Telemetry sensor %d", MAX_TELEMETRY_SENSORS)
|
||||
MIXSRC_LAST_TELEM = MIXSRC_FIRST_TELEM+3*MAX_TELEMETRY_SENSORS-1
|
||||
MIXSRC_FIRST_TELEM SKIP, LUA_EXPORT_MULTIPLE("telem", "Telemetry sensor %d", MAX_TELEMETRY_SENSORS)
|
||||
MIXSRC_LAST_TELEM SKIP = MIXSRC_FIRST_TELEM+3*MAX_TELEMETRY_SENSORS-1
|
||||
};
|
||||
|
||||
#if defined(__cplusplus)
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "board.h"
|
||||
#include "dataconstants.h"
|
||||
#include "definitions.h"
|
||||
#include "opentx_types.h"
|
||||
|
||||
#if defined(PCBTARANIS)
|
||||
#define N_TARANIS_FIELD(x)
|
||||
|
@ -54,6 +55,8 @@
|
|||
#define NOBACKUP(...) __VA_ARGS__
|
||||
#endif
|
||||
|
||||
#include "storage/yaml/yaml_defs.h"
|
||||
|
||||
/*
|
||||
* Mixer structure
|
||||
*/
|
||||
|
@ -64,15 +67,15 @@ PACK(struct CurveRef {
|
|||
});
|
||||
|
||||
PACK(struct MixData {
|
||||
int16_t weight:11; // GV1=-1024, -GV1=1023
|
||||
int16_t weight:11 CUST(in_read_weight,in_write_weight); // GV1=-1024, -GV1=1023
|
||||
uint16_t destCh:5;
|
||||
uint16_t srcRaw:10; // srcRaw=0 means not used
|
||||
uint16_t srcRaw:10 CUST(r_mixSrcRaw,w_mixSrcRaw); // srcRaw=0 means not used
|
||||
uint16_t carryTrim:1;
|
||||
uint16_t mixWarn:2; // mixer warning
|
||||
uint16_t mltpx:2; // multiplex method: 0 means +=, 1 means *=, 2 means :=
|
||||
uint16_t spare:1;
|
||||
uint16_t spare:1 SKIP;
|
||||
int32_t offset:14;
|
||||
int32_t swtch:9;
|
||||
int32_t swtch:9 CUST(r_swtchSrc,w_swtchSrc);
|
||||
uint32_t flightModes:9;
|
||||
CurveRef curve;
|
||||
uint8_t delayUp;
|
||||
|
@ -89,13 +92,13 @@ PACK(struct MixData {
|
|||
PACK(struct ExpoData {
|
||||
uint16_t mode:2;
|
||||
uint16_t scale:14;
|
||||
uint16_t srcRaw:10;
|
||||
uint16_t srcRaw:10 ENUM(MixSources);
|
||||
int16_t carryTrim:6;
|
||||
uint32_t chn:5;
|
||||
int32_t swtch:9;
|
||||
int32_t swtch:9 CUST(r_swtchSrc,w_swtchSrc);
|
||||
uint32_t flightModes:9;
|
||||
int32_t weight:8;
|
||||
int32_t spare:1;
|
||||
int32_t weight:8 CUST(in_read_weight,in_write_weight);
|
||||
int32_t spare:1 SKIP;
|
||||
NOBACKUP(char name[LEN_EXPOMIX_NAME]);
|
||||
int8_t offset;
|
||||
CurveRef curve;
|
||||
|
@ -112,7 +115,7 @@ PACK(struct LimitData {
|
|||
int16_t offset:11;
|
||||
uint16_t symetrical:1;
|
||||
uint16_t revert:1;
|
||||
uint16_t spare:3;
|
||||
uint16_t spare:3 SKIP;
|
||||
int8_t curve;
|
||||
NOBACKUP(char name[LEN_CHANNEL_NAME]);
|
||||
});
|
||||
|
@ -122,12 +125,12 @@ PACK(struct LimitData {
|
|||
*/
|
||||
|
||||
PACK(struct LogicalSwitchData {
|
||||
uint8_t func;
|
||||
uint8_t func ENUM(LogicalSwitchesFunctions);
|
||||
int32_t v1:10;
|
||||
int32_t v3:10;
|
||||
int32_t andsw:9; // TODO rename to xswtch
|
||||
uint32_t andswtype:1; // TODO rename to xswtchType (AND / OR)
|
||||
uint32_t spare:2; // anything else needed?
|
||||
uint32_t spare:2 SKIP; // anything else needed?
|
||||
int16_t v2;
|
||||
uint8_t delay;
|
||||
uint8_t duration;
|
||||
|
@ -145,8 +148,8 @@ PACK(struct LogicalSwitchData {
|
|||
#endif
|
||||
|
||||
PACK(struct CustomFunctionData {
|
||||
int16_t swtch:9;
|
||||
uint16_t func:7;
|
||||
int16_t swtch:9 CUST(r_swtchSrc,w_swtchSrc);
|
||||
uint16_t func:7 ENUM(Functions);
|
||||
PACK(union {
|
||||
NOBACKUP(PACK(struct {
|
||||
char name[LEN_FUNCTION_NAME];
|
||||
|
@ -156,14 +159,14 @@ PACK(struct CustomFunctionData {
|
|||
int16_t val;
|
||||
uint8_t mode;
|
||||
uint8_t param;
|
||||
NOBACKUP(CFN_SPARE_TYPE spare);
|
||||
NOBACKUP(CFN_SPARE_TYPE spare SKIP);
|
||||
}) all;
|
||||
|
||||
NOBACKUP(PACK(struct {
|
||||
int32_t val1;
|
||||
NOBACKUP(CFN_SPARE_TYPE val2);
|
||||
NOBACKUP(CFN_SPARE_TYPE val2 SKIP);
|
||||
}) clear);
|
||||
});
|
||||
}) NAME(fp) FUNC(select_custom_fn);
|
||||
uint8_t active;
|
||||
|
||||
bool isEmpty() const
|
||||
|
@ -184,11 +187,11 @@ PACK(struct trim_t {
|
|||
PACK(struct FlightModeData {
|
||||
trim_t trim[NUM_TRIMS];
|
||||
NOBACKUP(char name[LEN_FLIGHT_MODE_NAME]);
|
||||
int16_t swtch:9; // swtch of phase[0] is not used
|
||||
int16_t spare:7;
|
||||
int16_t swtch:9 ENUM(SwitchSources) CUST(r_swtchSrc,w_swtchSrc); // swtch of phase[0] is not used
|
||||
int16_t spare:7 SKIP;
|
||||
uint8_t fadeIn;
|
||||
uint8_t fadeOut;
|
||||
gvar_t gvars[MAX_GVARS];
|
||||
gvar_t gvars[MAX_GVARS] FUNC(gvar_is_active);
|
||||
});
|
||||
|
||||
/*
|
||||
|
@ -213,7 +216,7 @@ PACK(struct GVarData {
|
|||
uint32_t popup:1;
|
||||
uint32_t prec:1;
|
||||
uint32_t unit:2;
|
||||
uint32_t spare:4;
|
||||
uint32_t spare:4 SKIP;
|
||||
});
|
||||
|
||||
/*
|
||||
|
@ -251,7 +254,7 @@ PACK(struct SwashRingData {
|
|||
union ScriptDataInput {
|
||||
int16_t value;
|
||||
source_t source;
|
||||
};
|
||||
} FUNC(select_script_input);
|
||||
|
||||
PACK(struct ScriptData {
|
||||
char file[LEN_SCRIPT_FILENAME];
|
||||
|
@ -266,12 +269,12 @@ PACK(struct ScriptData {
|
|||
PACK(struct RssiAlarmData {
|
||||
int8_t disabled:1;
|
||||
#if defined (PCBNV14)
|
||||
uint8_t flysky_telemetry:1; // if set for FlySky receivers use native RSSI values instead of rescaled ones
|
||||
uint8_t flysky_telemetry:1; // if set for FlySky receivers use native RSSI values instead of rescaled ones
|
||||
#else
|
||||
int8_t spare:1;
|
||||
int8_t spare:1 SKIP;
|
||||
#endif
|
||||
int8_t warning:6;
|
||||
int8_t spare2:2;
|
||||
int8_t spare2:2 SKIP;
|
||||
int8_t critical:6;
|
||||
inline int8_t getWarningRssi() {return 45 + warning;}
|
||||
inline int8_t getCriticalRssi() {return 42 + critical;}
|
||||
|
@ -326,7 +329,7 @@ PACK(struct TelemetrySensor {
|
|||
union {
|
||||
uint16_t id; // data identifier, for FrSky we can reuse existing ones. Source unit is derived from type.
|
||||
NOBACKUP(uint16_t persistentValue);
|
||||
};
|
||||
} NAME(id1) FUNC(select_id1);
|
||||
union {
|
||||
PACK(struct {
|
||||
uint8_t physID:5;
|
||||
|
@ -334,11 +337,11 @@ PACK(struct TelemetrySensor {
|
|||
}) frskyInstance;
|
||||
uint8_t instance;
|
||||
NOBACKUP(uint8_t formula);
|
||||
};
|
||||
} NAME(id2) FUNC(select_id2);
|
||||
char label[TELEM_LABEL_LEN]; // user defined label
|
||||
uint8_t subId;
|
||||
uint8_t type:1; // 0=custom / 1=calculated // user can choose what unit to display each value in
|
||||
uint8_t spare1:1;
|
||||
uint8_t spare1:1 SKIP;
|
||||
uint8_t unit:6;
|
||||
uint8_t prec:2;
|
||||
uint8_t autoOffset:1;
|
||||
|
@ -346,7 +349,7 @@ PACK(struct TelemetrySensor {
|
|||
uint8_t logs:1;
|
||||
uint8_t persistent:1;
|
||||
uint8_t onlyPositive:1;
|
||||
uint8_t spare2:1;
|
||||
uint8_t spare2:1 SKIP;
|
||||
union {
|
||||
NOBACKUP(PACK(struct {
|
||||
uint16_t ratio;
|
||||
|
@ -355,22 +358,22 @@ PACK(struct TelemetrySensor {
|
|||
NOBACKUP(PACK(struct {
|
||||
uint8_t source;
|
||||
uint8_t index;
|
||||
uint16_t spare;
|
||||
uint16_t spare SKIP;
|
||||
}) cell);
|
||||
NOBACKUP(PACK(struct {
|
||||
int8_t sources[4];
|
||||
}) calc);
|
||||
NOBACKUP(PACK(struct {
|
||||
uint8_t source;
|
||||
uint8_t spare[3];
|
||||
uint8_t spare[3] SKIP;
|
||||
}) consumption);
|
||||
NOBACKUP(PACK(struct {
|
||||
uint8_t gps;
|
||||
uint8_t alt;
|
||||
uint16_t spare;
|
||||
uint16_t spare SKIP;
|
||||
}) dist);
|
||||
uint32_t param;
|
||||
};
|
||||
} NAME(cfg) FUNC(select_sensor_cfg);
|
||||
NOBACKUP(
|
||||
void init(const char *label, uint8_t unit=UNIT_RAW, uint8_t prec=0);
|
||||
void init(uint16_t id);
|
||||
|
@ -403,13 +406,13 @@ PACK(struct TelemetrySensor {
|
|||
|
||||
PACK(struct TrainerModuleData {
|
||||
uint8_t mode:3;
|
||||
uint8_t spare1:5;
|
||||
uint8_t spare1:5 SKIP;
|
||||
uint8_t channelsStart;
|
||||
int8_t channelsCount; // 0=8 channels
|
||||
int8_t frameLength;
|
||||
int8_t delay:6;
|
||||
uint8_t pulsePol:1;
|
||||
uint8_t spare2:1;
|
||||
uint8_t spare2:1 SKIP;
|
||||
});
|
||||
|
||||
/*
|
||||
|
@ -419,7 +422,7 @@ PACK(struct TrainerModuleData {
|
|||
// Only used in case switch and if statements as "virtual" protocol
|
||||
#define MM_RF_CUSTOM_SELECTED 0xff
|
||||
PACK(struct ModuleData {
|
||||
uint8_t type:4;
|
||||
uint8_t type:4 ENUM(ModuleType);
|
||||
// TODO some refactoring is needed, rfProtocol is only used by DSM2 and MULTI, it could be merged with subType
|
||||
int8_t rfProtocol:4;
|
||||
uint8_t channelsStart;
|
||||
|
@ -438,7 +441,7 @@ PACK(struct ModuleData {
|
|||
} ppm);
|
||||
NOBACKUP(struct {
|
||||
uint8_t rfProtocolExtra:2;
|
||||
uint8_t spare1:3;
|
||||
uint8_t spare1:3 SKIP;
|
||||
uint8_t customProto:1;
|
||||
uint8_t autoBindMode:1;
|
||||
uint8_t lowPowerMode:1;
|
||||
|
@ -446,16 +449,16 @@ PACK(struct ModuleData {
|
|||
} multi);
|
||||
NOBACKUP(struct {
|
||||
uint8_t power:2; // 0=10 mW, 1=100 mW, 2=500 mW, 3=1W
|
||||
uint8_t spare1:2;
|
||||
uint8_t spare1:2 SKIP;
|
||||
uint8_t receiverTelemetryOff:1; // false = receiver telem enabled
|
||||
uint8_t receiverHigherChannels:1; // false = pwm out 1-8, true 9-16
|
||||
int8_t antennaMode:2;
|
||||
uint8_t spare2;
|
||||
uint8_t spare2 SKIP;
|
||||
} pxx);
|
||||
NOBACKUP(struct {
|
||||
uint8_t spare1:6;
|
||||
uint8_t spare1:6 SKIP;
|
||||
uint8_t noninverted:1;
|
||||
uint8_t spare2:1;
|
||||
uint8_t spare2:1 SKIP;
|
||||
int8_t refreshRate; // definition as framelength for ppm (* 5 + 225 = time in 1/10 ms)
|
||||
} sbus);
|
||||
NOBACKUP(PACK(struct {
|
||||
|
@ -469,7 +472,7 @@ PACK(struct ModuleData {
|
|||
uint8_t rx_freq[2];
|
||||
} flysky);
|
||||
#endif
|
||||
};
|
||||
} NAME(mod) FUNC(select_mod_type);
|
||||
|
||||
// Helper functions to set both of the rfProto protocol at the same time
|
||||
NOBACKUP(inline uint8_t getMultiProtocol(bool returnCustom) {
|
||||
|
@ -589,9 +592,9 @@ PACK(struct ModelData {
|
|||
int8_t points[MAX_CURVE_POINTS];
|
||||
|
||||
LogicalSwitchData logicalSw[MAX_LOGICAL_SWITCHES];
|
||||
CustomFunctionData customFn[MAX_SPECIAL_FUNCTIONS];
|
||||
CustomFunctionData customFn[MAX_SPECIAL_FUNCTIONS] FUNC(cfn_is_active);
|
||||
SwashRingData swashR;
|
||||
FlightModeData flightModeData[MAX_FLIGHT_MODES];
|
||||
FlightModeData flightModeData[MAX_FLIGHT_MODES] FUNC(fmd_is_active);
|
||||
|
||||
NOBACKUP(uint8_t thrTraceSrc);
|
||||
|
||||
|
@ -606,7 +609,7 @@ PACK(struct ModelData {
|
|||
|
||||
NOBACKUP(RssiAlarmData rssiAlarms);
|
||||
|
||||
NOBACKUP(uint8_t spare1:6);
|
||||
NOBACKUP(uint8_t spare1:6 SKIP);
|
||||
NOBACKUP(uint8_t potsWarnMode:2);
|
||||
|
||||
ModuleData moduleData[NUM_MODULES];
|
||||
|
@ -673,37 +676,37 @@ PACK(struct TrainerData {
|
|||
#if defined(PCBHORUS) || defined(PCBNV14)
|
||||
#define EXTRA_GENERAL_FIELDS \
|
||||
NOBACKUP(uint8_t auxSerialMode); \
|
||||
swconfig_t switchConfig; \
|
||||
uint16_t potsConfig; /* two bits per pot */ \
|
||||
uint8_t slidersConfig; /* 1 bit per slider */ \
|
||||
swconfig_t switchConfig ARRAY(2,struct_switchConfig,nullptr); \
|
||||
uint16_t potsConfig ARRAY(2,struct_potConfig,nullptr); /* two bits per pot */ \
|
||||
uint8_t slidersConfig ARRAY(1,struct_sliderConfig,nullptr); /* 1 bit per slider */ \
|
||||
NOBACKUP(char switchNames[STORAGE_NUM_SWITCHES][LEN_SWITCH_NAME]); \
|
||||
NOBACKUP(char anaNames[NUM_STICKS + STORAGE_NUM_POTS + STORAGE_NUM_SLIDERS][LEN_ANA_NAME]); \
|
||||
NOBACKUP(char currModelFilename[LEN_MODEL_FILENAME+1]); \
|
||||
NOBACKUP(uint8_t spare5:1); \
|
||||
NOBACKUP(uint8_t spare5:1 SKIP); \
|
||||
NOBACKUP(uint8_t blOffBright:7); \
|
||||
NOBACKUP(char bluetoothName[LEN_BLUETOOTH_NAME]);
|
||||
#elif defined(PCBTARANIS) || defined(PCBNV14)
|
||||
#if defined(STORAGE_BLUETOOTH)
|
||||
#define BLUETOOTH_FIELDS \
|
||||
uint8_t spare5; \
|
||||
uint8_t spare5 SKIP; \
|
||||
char bluetoothName[LEN_BLUETOOTH_NAME];
|
||||
#else
|
||||
#define BLUETOOTH_FIELDS
|
||||
#endif
|
||||
#define EXTRA_GENERAL_FIELDS \
|
||||
uint8_t auxSerialMode:4; \
|
||||
uint8_t slidersConfig:4; \
|
||||
uint8_t potsConfig; /* two bits per pot */\
|
||||
uint8_t slidersConfig:4 ARRAY(1,struct_sliderConfig,nullptr); \
|
||||
uint8_t potsConfig ARRAY(2,struct_potConfig,nullptr); /* two bits per pot */\
|
||||
uint8_t backlightColor; \
|
||||
swarnstate_t switchUnlockStates; \
|
||||
swconfig_t switchConfig; \
|
||||
swconfig_t switchConfig ARRAY(2,struct_switchConfig,nullptr); \
|
||||
char switchNames[STORAGE_NUM_SWITCHES][LEN_SWITCH_NAME]; \
|
||||
char anaNames[NUM_STICKS+STORAGE_NUM_POTS+STORAGE_NUM_SLIDERS][LEN_ANA_NAME]; \
|
||||
BLUETOOTH_FIELDS
|
||||
#elif defined(PCBSKY9X)
|
||||
#define EXTRA_GENERAL_FIELDS \
|
||||
int8_t txCurrentCalibration; \
|
||||
int8_t spare5; \
|
||||
int8_t spare5 SKIP; \
|
||||
uint8_t mAhWarn; \
|
||||
uint16_t mAhUsed; \
|
||||
int8_t temperatureCalib; \
|
||||
|
@ -729,7 +732,7 @@ PACK(struct TrainerData {
|
|||
#if defined(BUZZER)
|
||||
#define BUZZER_FIELD int8_t buzzerMode:2 // -2=quiet, -1=only alarms, 0=no keys, 1=all (only used on AVR radios without audio hardware)
|
||||
#else
|
||||
#define BUZZER_FIELD int8_t spare4:2
|
||||
#define BUZZER_FIELD int8_t spare4:2 SKIP
|
||||
#endif
|
||||
|
||||
PACK(struct RadioData {
|
||||
|
@ -744,7 +747,7 @@ PACK(struct RadioData {
|
|||
uint8_t backlightMode:3;
|
||||
int8_t antennaMode:2;
|
||||
uint8_t disableRtcWarning:1;
|
||||
int8_t spare1:2;
|
||||
int8_t spare1:2 SKIP;
|
||||
NOBACKUP(TrainerData trainer);
|
||||
NOBACKUP(uint8_t view); // index of view in main screen
|
||||
NOBACKUP(BUZZER_FIELD); /* 2bits */
|
||||
|
@ -765,7 +768,7 @@ PACK(struct RadioData {
|
|||
NOBACKUP(uint8_t templateSetup); // RETA order for receiver channels
|
||||
NOBACKUP(int8_t PPM_Multiplier);
|
||||
NOBACKUP(int8_t hapticLength);
|
||||
N_HORUS_FIELD(N_TARANIS_FIELD(uint8_t spare2));
|
||||
N_HORUS_FIELD(N_TARANIS_FIELD(uint8_t spare2 SKIP));
|
||||
N_HORUS_FIELD(N_TARANIS_FIELD(uint8_t stickReverse));
|
||||
NOBACKUP(int8_t beepLength:3);
|
||||
NOBACKUP(int8_t hapticStrength:3);
|
||||
|
@ -773,8 +776,8 @@ PACK(struct RadioData {
|
|||
NOBACKUP(uint8_t unexpectedShutdown:1);
|
||||
NOBACKUP(uint8_t speakerPitch);
|
||||
NOBACKUP(int8_t speakerVolume);
|
||||
NOBACKUP(int8_t vBatMin);
|
||||
NOBACKUP(int8_t vBatMax);
|
||||
NOBACKUP(int8_t vBatMin CUST(r_vbat_min,w_vbat_min));
|
||||
NOBACKUP(int8_t vBatMax CUST(r_vbat_max,w_vbat_max));
|
||||
|
||||
NOBACKUP(uint8_t backlightBright);
|
||||
NOBACKUP(uint32_t globalTimer);
|
||||
|
@ -788,7 +791,7 @@ PACK(struct RadioData {
|
|||
NOBACKUP(uint8_t disableRssiPoweroffAlarm:1);
|
||||
NOBACKUP(uint8_t USBMode:2);
|
||||
NOBACKUP(uint8_t jackMode:2);
|
||||
NOBACKUP(uint8_t spare3:1);
|
||||
NOBACKUP(uint8_t spare3:1 SKIP);
|
||||
NOBACKUP(char ttsLanguage[2]);
|
||||
NOBACKUP(int8_t beepVolume:4);
|
||||
NOBACKUP(int8_t wavVolume:4);
|
||||
|
@ -797,7 +800,7 @@ PACK(struct RadioData {
|
|||
NOBACKUP(int8_t varioPitch);
|
||||
NOBACKUP(int8_t varioRange);
|
||||
NOBACKUP(int8_t varioRepeat);
|
||||
CustomFunctionData customFn[MAX_SPECIAL_FUNCTIONS];
|
||||
CustomFunctionData customFn[MAX_SPECIAL_FUNCTIONS] FUNC(cfn_is_active);
|
||||
|
||||
EXTRA_GENERAL_FIELDS
|
||||
|
||||
|
@ -880,8 +883,8 @@ static inline void check_struct()
|
|||
CHKSIZE(SwashRingData, 8);
|
||||
CHKSIZE(ModelHeader, 31);
|
||||
CHKSIZE(CurveHeader, 4);
|
||||
CHKSIZE(CustomScreenData, 610);
|
||||
CHKSIZE(Topbar::PersistentData, 216);
|
||||
CHKSIZE(CustomScreenData, 850);
|
||||
CHKSIZE(Topbar::PersistentData, 300);
|
||||
#elif defined(PCBNV14)
|
||||
// TODO
|
||||
#elif defined(PCBSKY9X)
|
||||
|
@ -942,8 +945,8 @@ static inline void check_struct()
|
|||
CHKSIZE(RadioData, 735);
|
||||
CHKSIZE(ModelData, 5301);
|
||||
#elif defined(PCBHORUS)
|
||||
CHKSIZE(RadioData, 881);
|
||||
CHKSIZE(ModelData, 9736);
|
||||
CHKSIZE(RadioData, 901);
|
||||
CHKSIZE(ModelData, 11020);
|
||||
#endif
|
||||
|
||||
#undef CHKSIZE
|
||||
|
|
|
@ -41,8 +41,8 @@ class Layout1x1: public Layout
|
|||
void create() override
|
||||
{
|
||||
Layout::create();
|
||||
persistentData->options[0].boolValue = true;
|
||||
persistentData->options[1].boolValue = true;
|
||||
persistentData->options[0] = ZoneOptionValueTyped { ZOV_Bool, OPTION_VALUE_BOOL(true) };
|
||||
persistentData->options[1] = ZoneOptionValueTyped { ZOV_Bool, OPTION_VALUE_BOOL(true) };
|
||||
}
|
||||
|
||||
unsigned int getZonesCount() const override
|
||||
|
@ -53,11 +53,11 @@ class Layout1x1: public Layout
|
|||
Zone getZone(unsigned int index) const override
|
||||
{
|
||||
Zone zone = { 10, 10, LCD_W - 2*10, LCD_H - 2*10 };
|
||||
if (persistentData->options[0].boolValue) {
|
||||
if (persistentData->options[0].value.boolValue) {
|
||||
zone.y += MENU_HEADER_HEIGHT;
|
||||
zone.h -= MENU_HEADER_HEIGHT;
|
||||
}
|
||||
if (persistentData->options[1].boolValue) {
|
||||
if (persistentData->options[1].value.boolValue) {
|
||||
zone.x += 35;
|
||||
zone.w -= 2*35;
|
||||
zone.h -= 35;
|
||||
|
@ -72,11 +72,11 @@ class Layout1x1: public Layout
|
|||
//{
|
||||
// theme->drawBackground();
|
||||
//
|
||||
// if (persistentData->options[0].boolValue) {
|
||||
// if (persistentData->options[0].value.boolValue) {
|
||||
// drawTopBar();
|
||||
// }
|
||||
//
|
||||
// if (persistentData->options[1].boolValue) {
|
||||
// if (persistentData->options[1].value.boolValue) {
|
||||
// // Sliders + Trims + Flight mode
|
||||
// lcdDrawSizedText(LCD_W / 2 - getTextWidth(g_model.flightModeData[mixerCurrentFlightMode].name, sizeof(g_model.flightModeData[mixerCurrentFlightMode].name), ZCHAR | FONT(XS)) / 2,
|
||||
// 232,
|
||||
|
|
|
@ -49,10 +49,10 @@ class Layout2P1: public Layout
|
|||
void create() override
|
||||
{
|
||||
Layout::create();
|
||||
persistentData->options[0].boolValue = true;
|
||||
persistentData->options[1].boolValue = true;
|
||||
persistentData->options[2].boolValue = true;
|
||||
persistentData->options[3].boolValue = true;
|
||||
persistentData->options[0] = ZoneOptionValueTyped { ZOV_Bool, OPTION_VALUE_BOOL(true) };
|
||||
persistentData->options[1] = ZoneOptionValueTyped { ZOV_Bool, OPTION_VALUE_BOOL(true) };
|
||||
persistentData->options[2] = ZoneOptionValueTyped { ZOV_Bool, OPTION_VALUE_BOOL(true) };
|
||||
persistentData->options[3] = ZoneOptionValueTyped { ZOV_Bool, OPTION_VALUE_BOOL(true) };
|
||||
}
|
||||
|
||||
unsigned int getZonesCount() const override
|
||||
|
@ -72,11 +72,11 @@ class Layout2P1: public Layout
|
|||
//{
|
||||
// theme->drawBackground();
|
||||
//
|
||||
// if (persistentData->options[0].boolValue) {
|
||||
// if (persistentData->options[0].value.boolValue) {
|
||||
// drawTopBar();
|
||||
// }
|
||||
//
|
||||
// if (persistentData->options[1].boolValue) {
|
||||
// if (persistentData->options[1].value.boolValue) {
|
||||
// // Flight mode
|
||||
// lcdDrawSizedText(LCD_W / 2 - getTextWidth(g_model.flightModeData[mixerCurrentFlightMode].name,
|
||||
// sizeof(g_model.flightModeData[mixerCurrentFlightMode].name),
|
||||
|
@ -86,12 +86,12 @@ class Layout2P1: public Layout
|
|||
// sizeof(g_model.flightModeData[mixerCurrentFlightMode].name), ZCHAR | FONT(XS));
|
||||
// }
|
||||
//
|
||||
// if (persistentData->options[2].boolValue) {
|
||||
// if (persistentData->options[2].value.boolValue) {
|
||||
// // Pots and rear sliders positions
|
||||
// drawMainPots();
|
||||
// }
|
||||
//
|
||||
// if (persistentData->options[3].boolValue) {
|
||||
// if (persistentData->options[3].value.boolValue) {
|
||||
// // Trims
|
||||
// drawTrims(mixerCurrentFlightMode);
|
||||
// }
|
||||
|
|
|
@ -40,7 +40,7 @@ class Layout2x1: public Layout
|
|||
void create() override
|
||||
{
|
||||
Layout::create();
|
||||
persistentData->options[0].boolValue = true;
|
||||
persistentData->options[0] = ZoneOptionValueTyped { ZOV_Bool, OPTION_VALUE_BOOL(true) };
|
||||
}
|
||||
|
||||
unsigned int getZonesCount() const override
|
||||
|
@ -53,7 +53,7 @@ class Layout2x1: public Layout
|
|||
Zone zone;
|
||||
zone.w = (LCD_W-3*10) / 2;
|
||||
zone.x = (index & 1) ? 20 + zone.w : 10;
|
||||
if (persistentData->options[0].boolValue) {
|
||||
if (persistentData->options[0].value.boolValue) {
|
||||
zone.h = (LCD_H-MENU_HEADER_HEIGHT-2*10);
|
||||
zone.y = MENU_HEADER_HEIGHT + 10;
|
||||
}
|
||||
|
@ -71,7 +71,7 @@ class Layout2x1: public Layout
|
|||
//{
|
||||
// theme->drawBackground();
|
||||
//
|
||||
// if (persistentData->options[0].boolValue) {
|
||||
// if (persistentData->options[0].value.boolValue) {
|
||||
// drawTopBar();
|
||||
// }
|
||||
//
|
||||
|
|
|
@ -40,7 +40,7 @@ class Layout2x2: public Layout
|
|||
void create() override
|
||||
{
|
||||
Layout::create();
|
||||
persistentData->options[0].boolValue = true;
|
||||
persistentData->options[0] = ZoneOptionValueTyped { ZOV_Bool, OPTION_VALUE_BOOL(true) };
|
||||
}
|
||||
|
||||
unsigned int getZonesCount() const override
|
||||
|
@ -53,7 +53,7 @@ class Layout2x2: public Layout
|
|||
Zone zone;
|
||||
zone.w = (LCD_W-3*10) / 2;
|
||||
zone.x = (index & 1) ? 20 + zone.w : 10;
|
||||
if (persistentData->options[0].boolValue) {
|
||||
if (persistentData->options[0].value.boolValue) {
|
||||
zone.h = (LCD_H-MENU_HEADER_HEIGHT-3*10) / 2;
|
||||
zone.y = MENU_HEADER_HEIGHT + 10;
|
||||
}
|
||||
|
@ -74,7 +74,7 @@ class Layout2x2: public Layout
|
|||
//{
|
||||
// theme->drawBackground();
|
||||
//
|
||||
// if (persistentData->options[0].boolValue) {
|
||||
// if (persistentData->options[0].value.boolValue) {
|
||||
// drawTopBar();
|
||||
// }
|
||||
//
|
||||
|
|
|
@ -47,14 +47,14 @@ class Layout2x4: public Layout
|
|||
void create() override
|
||||
{
|
||||
Layout::create();
|
||||
persistentData->options[0].boolValue = true;
|
||||
persistentData->options[1].boolValue = true;
|
||||
persistentData->options[2].boolValue = true;
|
||||
persistentData->options[3].boolValue = true;
|
||||
persistentData->options[4].boolValue = true;
|
||||
persistentData->options[5].unsignedValue = RGB(77, 112, 203);
|
||||
persistentData->options[6].boolValue = false;
|
||||
persistentData->options[7].unsignedValue = RGB(77, 112, 203);
|
||||
persistentData->options[0] = ZoneOptionValueTyped { ZOV_Bool, OPTION_VALUE_BOOL(true) };
|
||||
persistentData->options[1] = ZoneOptionValueTyped { ZOV_Bool, OPTION_VALUE_BOOL(true) };
|
||||
persistentData->options[2] = ZoneOptionValueTyped { ZOV_Bool, OPTION_VALUE_BOOL(true) };
|
||||
persistentData->options[3] = ZoneOptionValueTyped { ZOV_Bool, OPTION_VALUE_BOOL(true) };
|
||||
persistentData->options[4] = ZoneOptionValueTyped { ZOV_Bool, OPTION_VALUE_BOOL(true) };
|
||||
persistentData->options[5] = ZoneOptionValueTyped { ZOV_Unsigned, OPTION_VALUE_UNSIGNED( RGB(77,112,203)) };
|
||||
persistentData->options[6] = ZoneOptionValueTyped { ZOV_Bool, OPTION_VALUE_BOOL(true) };
|
||||
persistentData->options[7] = ZoneOptionValueTyped { ZOV_Unsigned, OPTION_VALUE_UNSIGNED( RGB(77,112,203)) };
|
||||
}
|
||||
|
||||
unsigned int getZonesCount() const override
|
||||
|
@ -79,11 +79,11 @@ class Layout2x4: public Layout
|
|||
//{
|
||||
// theme->drawBackground();
|
||||
//
|
||||
// if (persistentData->options[0].boolValue) {
|
||||
// if (persistentData->options[0].value.boolValue) {
|
||||
// drawTopBar();
|
||||
// }
|
||||
//
|
||||
// if (persistentData->options[1].boolValue) {
|
||||
// if (persistentData->options[1].value.boolValue) {
|
||||
// // Flight mode
|
||||
// lcdDrawSizedText(LCD_W / 2 - getTextWidth(g_model.flightModeData[mixerCurrentFlightMode].name,
|
||||
// sizeof(g_model.flightModeData[mixerCurrentFlightMode].name),
|
||||
|
@ -93,23 +93,23 @@ class Layout2x4: public Layout
|
|||
// sizeof(g_model.flightModeData[mixerCurrentFlightMode].name), ZCHAR | FONT(XS));
|
||||
// }
|
||||
//
|
||||
// if (persistentData->options[2].boolValue) {
|
||||
// if (persistentData->options[2].value.boolValue) {
|
||||
// // Pots and rear sliders positions
|
||||
// drawMainPots();
|
||||
// }
|
||||
//
|
||||
// if (persistentData->options[3].boolValue) {
|
||||
// if (persistentData->options[3].value.boolValue) {
|
||||
// // Trims
|
||||
// drawTrims(mixerCurrentFlightMode);
|
||||
// }
|
||||
//
|
||||
// if (persistentData->options[4].boolValue) {
|
||||
// lcdSetColor(persistentData->options[5].unsignedValue);
|
||||
// if (persistentData->options[4].value.boolValue) {
|
||||
// lcdSetColor(persistentData->options[5].value.unsignedValue);
|
||||
// lcdDrawSolidFilledRect(50, 50, 180, 170, CUSTOM_COLOR);
|
||||
// }
|
||||
//
|
||||
// if (persistentData->options[6].boolValue) {
|
||||
// lcdSetColor(persistentData->options[7].unsignedValue);
|
||||
// if (persistentData->options[6].value.boolValue) {
|
||||
// lcdSetColor(persistentData->options[7].value.unsignedValue);
|
||||
// lcdDrawSolidFilledRect(250, 50, 180, 170, CUSTOM_COLOR);
|
||||
// }
|
||||
//
|
||||
|
|
|
@ -53,7 +53,8 @@ void ThemeBase::init() const
|
|||
int i = 0;
|
||||
for (const ZoneOption * option = options; option->name; option++, i++) {
|
||||
// TODO compiler bug? The CPU freezes ... g_eeGeneral.themeData.options[i] = &option->deflt;
|
||||
memcpy(&g_eeGeneral.themeData.options[i], &option->deflt, sizeof(ZoneOptionValue));
|
||||
memcpy(&g_eeGeneral.themeData.options[i].value, &option->deflt, sizeof(ZoneOptionValue));
|
||||
g_eeGeneral.themeData.options[i].type = zoneValueEnumFromType(option->type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -70,7 +71,7 @@ void ThemeBase::load() const
|
|||
|
||||
ZoneOptionValue * ThemeBase::getOptionValue(unsigned int index) const
|
||||
{
|
||||
return &g_eeGeneral.themeData.options[index];
|
||||
return &g_eeGeneral.themeData.options[index].value;
|
||||
}
|
||||
|
||||
const char * ThemeBase::getFilePath(const char * filename) const
|
||||
|
|
|
@ -34,11 +34,16 @@ class PageTab;
|
|||
class ThemeBase;
|
||||
void registerTheme(ThemeBase * theme);
|
||||
|
||||
// YAML_GENERATOR defs
|
||||
#if !defined(USE_IDX)
|
||||
#define USE_IDX
|
||||
#endif
|
||||
|
||||
class ThemeBase: public Theme
|
||||
{
|
||||
public:
|
||||
struct PersistentData {
|
||||
ZoneOptionValue options[MAX_THEME_OPTIONS];
|
||||
ZoneOptionValueTyped options[MAX_THEME_OPTIONS] USE_IDX;
|
||||
};
|
||||
|
||||
ThemeBase(const char * name, const ZoneOption * options = nullptr):
|
||||
|
@ -79,7 +84,7 @@ class ThemeBase: public Theme
|
|||
|
||||
virtual void drawMenuHeader(BitmapBuffer * dc, std::vector<PageTab *> & tabs, uint8_t currentIndex) const = 0;
|
||||
|
||||
virtual void drawMessageBox(const char * title, const char * text, const char * action, uint32_t flags) const;
|
||||
virtual void drawMessageBox(const char * title, const char * text, const char * action, uint32_t flags) const override;
|
||||
// virtual void drawProgressBar(BitmapBuffer * dc, coord_t x, coord_t y, coord_t w, coord_t h, int value) const = 0;
|
||||
|
||||
void drawCheckBox(BitmapBuffer * dc, bool checked, coord_t x, coord_t y, bool focus) const override;
|
||||
|
|
|
@ -337,7 +337,7 @@ class FlyskyTheme: public ThemeBase
|
|||
dc->drawBitmap(0, 0, backgroundBitmap);
|
||||
}
|
||||
else {
|
||||
lcdSetColor(g_eeGeneral.themeData.options[0].unsignedValue);
|
||||
lcdSetColor(g_eeGeneral.themeData.options[0].value.unsignedValue);
|
||||
dc->drawSolidFilledRect(0, 0, LCD_W, LCD_H, CUSTOM_COLOR);
|
||||
}
|
||||
}
|
||||
|
@ -441,4 +441,4 @@ FlyskyTheme flyskyTheme;
|
|||
#if defined(PCBFLYSKY)
|
||||
ThemeBase * defaultTheme = &flyskyTheme;
|
||||
Theme * theme = &flyskyTheme;
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -287,8 +287,8 @@ class FrskyTheme: public ThemeBase
|
|||
{
|
||||
TRACE("TODO THEME::UPDATE()");
|
||||
#if 0
|
||||
uint32_t color = g_eeGeneral.themeData.options[1].unsignedValue;
|
||||
uint32_t bg_color = UNEXPECTED_SHUTDOWN() ? WHITE : g_eeGeneral.themeData.options[0].unsignedValue;
|
||||
uint32_t color = g_eeGeneral.themeData.options[1].value.unsignedValue;
|
||||
uint32_t bg_color = UNEXPECTED_SHUTDOWN() ? WHITE : g_eeGeneral.themeData.options[0].value.unsignedValue;
|
||||
|
||||
lcdColorTable[DEFAULT_BGCOLOR_INDEX] = bg_color;
|
||||
lcdColorTable[FOCUS_BGCOLOR_INDEX] = color;
|
||||
|
@ -316,7 +316,7 @@ class FrskyTheme: public ThemeBase
|
|||
dc->drawBitmap(0, 0, backgroundBitmap);
|
||||
}
|
||||
else {
|
||||
lcdSetColor(g_eeGeneral.themeData.options[0].unsignedValue);
|
||||
lcdSetColor(g_eeGeneral.themeData.options[0].value.unsignedValue);
|
||||
dc->drawSolidFilledRect(0, 0, LCD_W, LCD_H, CUSTOM_COLOR);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,15 +24,21 @@
|
|||
#include <list>
|
||||
#include <string.h>
|
||||
#include "zone.h"
|
||||
#include "debug.h"
|
||||
|
||||
#define MAX_WIDGET_OPTIONS 5
|
||||
|
||||
// YAML_GENERATOR defs
|
||||
#if !defined(USE_IDX)
|
||||
#define USE_IDX
|
||||
#endif
|
||||
|
||||
class WidgetFactory;
|
||||
class Widget
|
||||
{
|
||||
public:
|
||||
struct PersistentData {
|
||||
ZoneOptionValue options[MAX_WIDGET_OPTIONS];
|
||||
ZoneOptionValueTyped options[MAX_WIDGET_OPTIONS] USE_IDX;
|
||||
};
|
||||
|
||||
Widget(const WidgetFactory * factory, const Zone & zone, PersistentData * persistentData):
|
||||
|
@ -64,7 +70,7 @@ class Widget
|
|||
|
||||
inline ZoneOptionValue * getOptionValue(unsigned int index) const
|
||||
{
|
||||
return &persistentData->options[index];
|
||||
return &persistentData->options[index].value;
|
||||
}
|
||||
|
||||
virtual void refresh() = 0;
|
||||
|
@ -109,7 +115,8 @@ class WidgetFactory
|
|||
for (const ZoneOption * option = options; option->name; option++) {
|
||||
TRACE("WidgetFactory::initPersistentData() setting option '%s'", option->name);
|
||||
// TODO compiler bug? The CPU freezes ... persistentData->options[i++] = option->deflt;
|
||||
memcpy(&persistentData->options[i++], &option->deflt, sizeof(ZoneOptionValue));
|
||||
memcpy(&persistentData->options[i++].value, &option->deflt, sizeof(ZoneOptionValue));
|
||||
persistentData->options[i++].type = zoneValueEnumFromType(option->type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,10 +43,10 @@ const ZoneOption GaugeWidget::options[] = {
|
|||
|
||||
void GaugeWidget::refresh()
|
||||
{
|
||||
mixsrc_t index = persistentData->options[0].unsignedValue;
|
||||
int32_t min = persistentData->options[1].signedValue;
|
||||
int32_t max = persistentData->options[2].signedValue;
|
||||
uint16_t color = persistentData->options[3].unsignedValue;
|
||||
mixsrc_t index = persistentData->options[0].value.unsignedValue;
|
||||
int32_t min = persistentData->options[1].value.signedValue;
|
||||
int32_t max = persistentData->options[2].value.signedValue;
|
||||
uint16_t color = persistentData->options[3].value.unsignedValue;
|
||||
|
||||
int32_t value = getValue(index);
|
||||
int32_t value_in_range = value;
|
||||
|
|
|
@ -73,13 +73,22 @@ class OutputsWidget: public Widget
|
|||
|
||||
void twoColumns()
|
||||
{
|
||||
uint8_t endColumn = drawChannels(zone.x, zone.y, zone.w / 2, zone.h, persistentData->options[0].unsignedValue, persistentData->options[1].boolValue, persistentData->options[2].unsignedValue);
|
||||
drawChannels(zone.x + zone.w / 2 + 2, zone.y, zone.w / 2, zone.h, endColumn + 1, persistentData->options[1].boolValue, persistentData->options[2].unsignedValue);
|
||||
uint8_t endColumn = drawChannels(zone.x, zone.y, zone.w / 2, zone.h,
|
||||
persistentData->options[0].value.unsignedValue,
|
||||
persistentData->options[1].value.boolValue,
|
||||
persistentData->options[2].value.unsignedValue);
|
||||
|
||||
drawChannels(zone.x + zone.w / 2 + 2, zone.y, zone.w / 2, zone.h, endColumn + 1,
|
||||
persistentData->options[1].value.boolValue,
|
||||
persistentData->options[2].value.unsignedValue);
|
||||
}
|
||||
|
||||
void oneColumn()
|
||||
{
|
||||
drawChannels(zone.x, zone.y, zone.w, zone.h, persistentData->options[0].unsignedValue, persistentData->options[1].boolValue, persistentData->options[2].unsignedValue);
|
||||
drawChannels(zone.x, zone.y, zone.w, zone.h,
|
||||
persistentData->options[0].value.unsignedValue,
|
||||
persistentData->options[1].value.boolValue,
|
||||
persistentData->options[2].value.unsignedValue);
|
||||
}
|
||||
|
||||
static const ZoneOption options[];
|
||||
|
|
|
@ -45,12 +45,18 @@ const ZoneOption TextWidget::options[] = {
|
|||
|
||||
void TextWidget::refresh()
|
||||
{
|
||||
lcdSetColor(persistentData->options[1].unsignedValue);
|
||||
LcdFlags fontsize = FONTSIZE(persistentData->options[2].unsignedValue << 8);
|
||||
if(persistentData->options[3].boolValue) {
|
||||
lcdDrawSizedText(zone.x+1, zone.y+1, persistentData->options[0].stringValue, sizeof(persistentData->options[0].stringValue), ZCHAR|fontsize|BLACK);
|
||||
lcdSetColor(persistentData->options[1].value.unsignedValue);
|
||||
LcdFlags fontsize = FONTSIZE(persistentData->options[2].value.unsignedValue << 8);
|
||||
if(persistentData->options[3].value.boolValue) {
|
||||
lcdDrawSizedText(zone.x+1, zone.y+1,
|
||||
persistentData->options[0].value.stringValue,
|
||||
sizeof(persistentData->options[0].value.stringValue),
|
||||
ZCHAR|fontsize|BLACK);
|
||||
}
|
||||
lcdDrawSizedText(zone.x, zone.y, persistentData->options[0].stringValue, sizeof(persistentData->options[0].stringValue), ZCHAR|fontsize|CUSTOM_COLOR);
|
||||
lcdDrawSizedText(zone.x, zone.y,
|
||||
persistentData->options[0].value.stringValue,
|
||||
sizeof(persistentData->options[0].value.stringValue),
|
||||
ZCHAR|fontsize|CUSTOM_COLOR);
|
||||
}
|
||||
|
||||
BaseWidgetFactory<TextWidget> textWidget("Text", TextWidget::options);
|
||||
|
|
|
@ -40,7 +40,7 @@ const ZoneOption TimerWidget::options[] = {
|
|||
|
||||
void TimerWidget::refresh()
|
||||
{
|
||||
uint32_t index = persistentData->options[0].unsignedValue;
|
||||
uint32_t index = persistentData->options[0].value.unsignedValue;
|
||||
TimerData & timerData = g_model.timers[index];
|
||||
TimerState & timerState = timersStates[index];
|
||||
|
||||
|
|
|
@ -44,8 +44,8 @@ void ValueWidget::refresh()
|
|||
{
|
||||
const int NUMBERS_PADDING = 4;
|
||||
|
||||
mixsrc_t field = persistentData->options[0].unsignedValue;
|
||||
lcdSetColor(persistentData->options[1].unsignedValue);
|
||||
mixsrc_t field = persistentData->options[0].value.unsignedValue;
|
||||
lcdSetColor(persistentData->options[1].value.unsignedValue);
|
||||
|
||||
int x = zone.x;
|
||||
int y = zone.y;
|
||||
|
@ -112,7 +112,7 @@ void ValueWidget::refresh()
|
|||
}
|
||||
}
|
||||
|
||||
if(persistentData->options[2].boolValue) {
|
||||
if(persistentData->options[2].value.boolValue) {
|
||||
drawSource(xLabel + 1, yLabel + 1, field, attrLabel|BLACK);
|
||||
drawSourceValue(xValue + 1, yValue + 1, field, attrValue|BLACK);
|
||||
}
|
||||
|
|
|
@ -59,8 +59,8 @@ class WidgetsContainer: public WidgetsContainerInterface
|
|||
};
|
||||
|
||||
struct PersistentData {
|
||||
ZonePersistentData zones[N];
|
||||
ZoneOptionValue options[O];
|
||||
ZonePersistentData zones[N];
|
||||
ZoneOptionValueTyped options[O];
|
||||
};
|
||||
|
||||
public:
|
||||
|
@ -120,7 +120,7 @@ class WidgetsContainer: public WidgetsContainerInterface
|
|||
|
||||
inline ZoneOptionValue * getOptionValue(unsigned int index) const
|
||||
{
|
||||
return &persistentData->options[index];
|
||||
return &persistentData->options[index].value;
|
||||
}
|
||||
|
||||
virtual unsigned int getZonesCount() const = 0;
|
||||
|
|
|
@ -3,19 +3,20 @@
|
|||
#define _ZONE_H_
|
||||
|
||||
#include <inttypes.h>
|
||||
#include "storage/yaml/yaml_defs.h"
|
||||
|
||||
#define LEN_ZONE_OPTION_STRING 8
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#define OPTION_VALUE_UNSIGNED(x) uint32_t(x)
|
||||
#define OPTION_VALUE_SIGNED(x) uint32_t(x)
|
||||
#define OPTION_VALUE_BOOL(x) bool(x)
|
||||
#define OPTION_VALUE_STRING(...) *(ZoneOptionValue *)(const char *) #__VA_ARGS__
|
||||
#define OPTION_VALUE_UNSIGNED(x) { uint32_t(x) }
|
||||
#define OPTION_VALUE_SIGNED(x) { uint32_t(x) }
|
||||
#define OPTION_VALUE_BOOL(x) { bool(x) }
|
||||
#define OPTION_VALUE_STRING(...) { *(ZoneOptionValue *)(const char *) #__VA_ARGS__ }
|
||||
#else
|
||||
#define OPTION_VALUE_UNSIGNED(x) { .unsignedValue = (x) }
|
||||
#define OPTION_VALUE_SIGNED(x) { .signedValue = (x) }
|
||||
#define OPTION_VALUE_BOOL(x) { .boolValue = (x) }
|
||||
#define OPTION_VALUE_STRING(...) { .stringValue = {__VA_ARGS__} }
|
||||
#define OPTION_VALUE_UNSIGNED(x) { .unsignedValue = (x) }
|
||||
#define OPTION_VALUE_SIGNED(x) { .signedValue = (x) }
|
||||
#define OPTION_VALUE_BOOL(x) { .boolValue = (x) }
|
||||
#define OPTION_VALUE_STRING(...) { .stringValue = { __VA_ARGS__ } }
|
||||
#endif
|
||||
|
||||
struct Zone
|
||||
|
@ -31,6 +32,13 @@ union ZoneOptionValue
|
|||
char stringValue[LEN_ZONE_OPTION_STRING];
|
||||
};
|
||||
|
||||
enum ZoneOptionValueEnum {
|
||||
ZOV_Unsigned=0,
|
||||
ZOV_Signed,
|
||||
ZOV_Bool,
|
||||
ZOV_String
|
||||
};
|
||||
|
||||
struct ZoneOption
|
||||
{
|
||||
enum Type {
|
||||
|
@ -52,4 +60,34 @@ struct ZoneOption
|
|||
ZoneOptionValue max;
|
||||
};
|
||||
|
||||
struct ZoneOptionValueTyped
|
||||
{
|
||||
ZoneOptionValueEnum type;
|
||||
ZoneOptionValue value FUNC(select_zov);
|
||||
};
|
||||
|
||||
|
||||
inline ZoneOptionValueEnum zoneValueEnumFromType(ZoneOption::Type type)
|
||||
{
|
||||
switch(type) {
|
||||
case ZoneOption::File:
|
||||
case ZoneOption::String:
|
||||
return ZOV_String;
|
||||
|
||||
case ZoneOption::Integer:
|
||||
return ZOV_Signed;
|
||||
|
||||
case ZoneOption::Bool:
|
||||
return ZOV_Bool;
|
||||
|
||||
case ZoneOption::Color:
|
||||
case ZoneOption::Timer:
|
||||
case ZoneOption::Switch:
|
||||
case ZoneOption::Source:
|
||||
case ZoneOption::TextSize:
|
||||
default:
|
||||
return ZOV_Unsigned;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -319,7 +319,7 @@ class LuaWidgetFactory: public WidgetFactory
|
|||
lua_newtable(lsWidgets);
|
||||
int i = 0;
|
||||
for (const ZoneOption * option = options; option->name; option++, i++) {
|
||||
l_pushtableint(option->name, persistentData->options[i].signedValue);
|
||||
l_pushtableint(option->name, persistentData->options[i].value.signedValue);
|
||||
}
|
||||
|
||||
if (lua_pcall(lsWidgets, 2, 1, 0) != 0) {
|
||||
|
@ -349,7 +349,7 @@ void LuaWidget::update()
|
|||
lua_newtable(lsWidgets);
|
||||
int i = 0;
|
||||
for (const ZoneOption * option = getOptions(); option->name; option++, i++) {
|
||||
l_pushtableint(option->name, persistentData->options[i].signedValue);
|
||||
l_pushtableint(option->name, persistentData->options[i].value.signedValue);
|
||||
}
|
||||
|
||||
if (lua_pcall(lsWidgets, 2, 0, 0) != 0) {
|
||||
|
|
|
@ -1952,6 +1952,18 @@ void opentxInit()
|
|||
// TODO topbar removed from new UI for now
|
||||
// topbar = new Topbar(&g_model.topbarData);
|
||||
|
||||
// #if __clang__
|
||||
// // clang does not like this at all, turn into a warning so that -Werror does not stop here
|
||||
// // taking address of packed member 'topbarData' of class or structure 'ModelData' may result in an unaligned pointer value [-Werror,-Waddress-of-packed-member]
|
||||
// #pragma clang diagnostic push
|
||||
// #pragma clang diagnostic warning "-Waddress-of-packed-member"
|
||||
// #endif
|
||||
// topbar = new Topbar((Topbar::PersistentData*)(((uint8_t*)&g_model) + offsetof(ModelData,topbarData)));
|
||||
// #if __clang__
|
||||
// // Restore warnings
|
||||
// #pragma clang diagnostic pop
|
||||
// #endif
|
||||
|
||||
// lua widget state must also be prepared before the call to storageReadAll()
|
||||
LUA_INIT_THEMES_AND_WIDGETS();
|
||||
}
|
||||
|
|
|
@ -55,6 +55,10 @@
|
|||
#if defined(COLORLCD)
|
||||
const char RADIO_MODELSLIST_PATH[] = RADIO_PATH "/models.txt";
|
||||
const char RADIO_SETTINGS_PATH[] = RADIO_PATH "/radio.bin";
|
||||
#if defined(SDCARD_YAML)
|
||||
const char RADIO_MODELSLIST_YAML_PATH[] = RADIO_PATH "/models.yml";
|
||||
const char RADIO_SETTINGS_YAML_PATH[] = RADIO_PATH "/radio.yml";
|
||||
#endif
|
||||
#define SPLASH_FILE "splash.png"
|
||||
#endif
|
||||
|
||||
|
@ -72,6 +76,9 @@ const char RADIO_SETTINGS_PATH[] = RADIO_PATH "/radio.bin";
|
|||
#define SPORT_FIRMWARE_EXT ".frk"
|
||||
#define FRSKY_FIRMWARE_EXT ".frsk"
|
||||
#define MULTI_FIRMWARE_EXT ".bin"
|
||||
#define YAML_EXT ".yml"
|
||||
|
||||
#define LEN_FILE_EXTENSION_MAX 5 // longest used, including the dot, excluding null term.
|
||||
|
||||
#if defined(COLORLCD)
|
||||
#define BITMAPS_EXT BMP_EXT JPG_EXT PNG_EXT
|
||||
|
|
|
@ -355,7 +355,7 @@ void OpenTxSim::updateKeysAndSwitches(bool start)
|
|||
// gruvin: Can't use Function keys on the Mac -- too many other app conflicts.
|
||||
// The ordering of these keys, Q/W,E/R,T/Y,U/I matches the on screen
|
||||
// order of trim sliders
|
||||
static FXuint trimKeys[] = { KEY_E, KEY_R, KEY_U, KEY_I, KEY_R, KEY_E, KEY_Y, KEY_T, KEY_Q, KEY_W };
|
||||
static FXuint trimKeys[] = { KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6, KEY_7, KEY_8, KEY_9, KEY_0 };
|
||||
#else
|
||||
static FXuint trimKeys[] = { KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, KEY_F6, KEY_F7, KEY_F8, KEY_F9, KEY_F10, KEY_F11, KEY_F12 };
|
||||
#endif
|
||||
|
@ -432,11 +432,11 @@ long OpenTxSim::onTimeout(FXObject*, FXSelector, void*)
|
|||
|
||||
#if defined(ROTARY_ENCODER_NAVIGATION)
|
||||
static bool rotencAction = false;
|
||||
if (getApp()->getKeyState(KEY_X)) {
|
||||
if (getApp()->getKeyState(KEY_X) || getApp()->getKeyState(KEY_plus)) {
|
||||
if (!rotencAction) ROTARY_ENCODER_NAVIGATION_VALUE += ROTARY_ENCODER_GRANULARITY;
|
||||
rotencAction = true;
|
||||
}
|
||||
else if (getApp()->getKeyState(KEY_W)) {
|
||||
else if (getApp()->getKeyState(KEY_W) || getApp()->getKeyState(KEY_minus)) {
|
||||
if (!rotencAction) ROTARY_ENCODER_NAVIGATION_VALUE -= ROTARY_ENCODER_GRANULARITY;
|
||||
rotencAction = true;
|
||||
}
|
||||
|
|
|
@ -316,6 +316,7 @@ void convertModelData_218_to_219(ModelData &model)
|
|||
#endif
|
||||
|
||||
#if defined(PCBHORUS)
|
||||
#if defined(FIXME) //TODO
|
||||
memcpy(newModel.screenData, oldModel.screenData,
|
||||
sizeof(newModel.screenData) +
|
||||
sizeof(newModel.topbarData));
|
||||
|
@ -342,7 +343,7 @@ void convertModelData_218_to_219(ModelData &model)
|
|||
ZoneOptionValue & option = zoneData->widgetData.options[0];
|
||||
option.unsignedValue = convertSource_218_to_219(option.unsignedValue);
|
||||
}
|
||||
|
||||
#endif
|
||||
#else
|
||||
newModel.screensType = oldModel.frsky.screensType;
|
||||
memmove(&newModel.screens, &oldModel.frsky.screens, sizeof(newModel.screens));
|
||||
|
|
|
@ -611,7 +611,8 @@ PACK(struct RadioData_v218 {
|
|||
static inline void check_struct_218()
|
||||
{
|
||||
#if defined(PCBHORUS)
|
||||
CHKSIZE(ModelData_v218, 9380);
|
||||
// FIXME !!!
|
||||
CHKSIZE(ModelData_v218, 10664);
|
||||
#elif defined(PCBX9E)
|
||||
CHKSIZE(ModelData_v218, 6520);
|
||||
#elif defined(PCBX9D)
|
||||
|
|
|
@ -18,6 +18,9 @@
|
|||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef _EEPROM_COMMON_H_
|
||||
#define _EEPROM_COMMON_H_
|
||||
|
||||
#define EEPROM_MIN_MODEL_SIZE 256
|
||||
|
||||
uint16_t eeLoadModelData(uint8_t id);
|
||||
|
@ -36,3 +39,10 @@ void storageClearRadioSettings();
|
|||
bool storageReadRadioSettings(bool allowFixes = true);
|
||||
void storageReadCurrentModel();
|
||||
|
||||
#if defined(EEPROM_RLC)
|
||||
#include "eeprom_rlc.h"
|
||||
#else
|
||||
#include "eeprom_raw.h"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
79
radio/src/storage/eeprom_none.cpp
Normal file
79
radio/src/storage/eeprom_none.cpp
Normal file
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include "opentx.h"
|
||||
//#include "eeprom_common.h"
|
||||
|
||||
void eepromCheck()
|
||||
{
|
||||
}
|
||||
|
||||
void storageFormat()
|
||||
{
|
||||
}
|
||||
|
||||
bool eepromOpen()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
uint16_t eeLoadModelData(uint8_t index)
|
||||
{
|
||||
modelDefault(index);
|
||||
return sizeof(g_model);
|
||||
}
|
||||
|
||||
bool eeLoadGeneral()
|
||||
{
|
||||
generalDefault();
|
||||
return true;
|
||||
}
|
||||
|
||||
void eeLoadModelName(uint8_t id, char *name)
|
||||
{
|
||||
memclear(name, sizeof(g_model.header.name));
|
||||
}
|
||||
|
||||
bool eeModelExists(uint8_t id)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void storageCheck(bool immediately)
|
||||
{
|
||||
}
|
||||
|
||||
void eeLoadModelHeader(uint8_t id, ModelHeader * header)
|
||||
{
|
||||
memclear(header, sizeof(ModelHeader));
|
||||
}
|
||||
|
||||
bool eeCopyModel(uint8_t dst, uint8_t src)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void eeSwapModels(uint8_t id1, uint8_t id2)
|
||||
{
|
||||
}
|
||||
|
||||
void eeDeleteModel(uint8_t idx)
|
||||
{
|
||||
}
|
|
@ -21,6 +21,11 @@
|
|||
#include "modelslist.h"
|
||||
using std::list;
|
||||
|
||||
#if defined(SDCARD_YAML)
|
||||
#include "yaml/yaml_parser.h"
|
||||
#include "yaml/yaml_modelslist.h"
|
||||
#endif
|
||||
|
||||
ModelsList modelslist;
|
||||
|
||||
ModelCell::ModelCell(const char * name):
|
||||
|
@ -29,6 +34,16 @@ ModelCell::ModelCell(const char * name):
|
|||
strncpy(modelFilename, name, sizeof(modelFilename));
|
||||
}
|
||||
|
||||
ModelCell::ModelCell(const char * name, uint8_t len)
|
||||
: valid_rfData(false)
|
||||
{
|
||||
if (len > sizeof(modelFilename)-1)
|
||||
len = sizeof(modelFilename)-1;
|
||||
|
||||
memcpy(modelFilename, name, len);
|
||||
modelFilename[len] = '\0';
|
||||
}
|
||||
|
||||
ModelCell::~ModelCell()
|
||||
{
|
||||
}
|
||||
|
@ -45,15 +60,132 @@ void ModelCell::setModelName(char * name)
|
|||
}
|
||||
}
|
||||
|
||||
void ModelCell::setModelName(char* name, uint8_t len)
|
||||
{
|
||||
if (len > LEN_MODEL_NAME-1)
|
||||
len = LEN_MODEL_NAME-1;
|
||||
|
||||
memcpy(modelName, name, len);
|
||||
modelName[len] = '\0';
|
||||
|
||||
if (modelName[0] == 0) {
|
||||
char * tmp;
|
||||
strncpy(modelName, modelFilename, LEN_MODEL_NAME);
|
||||
tmp = (char *) memchr(modelName, '.', LEN_MODEL_NAME);
|
||||
if (tmp != NULL)
|
||||
*tmp = 0;
|
||||
}
|
||||
|
||||
//resetBuffer();
|
||||
}
|
||||
|
||||
void ModelCell::setModelId(uint8_t moduleIdx, uint8_t id)
|
||||
{
|
||||
modelId[moduleIdx] = id;
|
||||
}
|
||||
|
||||
// void ModelCell::resetBuffer()
|
||||
// {
|
||||
// if (buffer) {
|
||||
// delete buffer;
|
||||
// buffer = NULL;
|
||||
// }
|
||||
// }
|
||||
|
||||
// const BitmapBuffer * ModelCell::getBuffer()
|
||||
// {
|
||||
// if (!buffer) {
|
||||
// loadBitmap();
|
||||
// }
|
||||
// return buffer;
|
||||
// }
|
||||
|
||||
// void ModelCell::loadBitmap()
|
||||
// {
|
||||
// uint8_t version;
|
||||
|
||||
// PACK(struct {
|
||||
// ModelHeader header;
|
||||
// TimerData timers[MAX_TIMERS];
|
||||
// }) partialmodel;
|
||||
|
||||
// const char * error = NULL;
|
||||
// BitmapBuffer * tmp_buffer;
|
||||
|
||||
// if (strncmp(modelFilename, g_eeGeneral.currModelFilename, LEN_MODEL_FILENAME) == 0) {
|
||||
// memcpy(&partialmodel.header, &g_model.header, sizeof(partialmodel));
|
||||
// }
|
||||
// else {
|
||||
// #if !defined (SDCARD_YAML)
|
||||
// error = readModel(modelFilename, (uint8_t *)&partialmodel.header, sizeof(partialmodel), &version);
|
||||
// // LEN_BITMAP_NAME has now 4 bytes more
|
||||
// if (version <= 218) {
|
||||
// memmove(partialmodel.timers, &(partialmodel.header.bitmap[10]), sizeof(TimerData)*MAX_TIMERS);
|
||||
// memclear(&(partialmodel.header.bitmap[10]), 4);
|
||||
// }
|
||||
// #else
|
||||
// memset(&partialmodel.header,0,sizeof(partialmodel));
|
||||
// #endif
|
||||
// }
|
||||
|
||||
// if ((modelName[0] == 0) && ! error)
|
||||
// setModelName(partialmodel.header.name); // resets buffer!!!
|
||||
|
||||
// tmp_buffer = new BitmapBuffer(BMP_RGB565, MODELCELL_WIDTH, MODELCELL_HEIGHT);
|
||||
// if (tmp_buffer == NULL) {
|
||||
// return;
|
||||
// }
|
||||
// tmp_buffer->clear(TEXT_BGCOLOR);
|
||||
|
||||
// if (error) {
|
||||
// tmp_buffer->drawText(5, 2, "(Invalid Model)", TEXT_COLOR);
|
||||
// tmp_buffer->drawBitmapPattern(5, 23, LBM_LIBRARY_SLOT, TEXT_COLOR);
|
||||
// }
|
||||
// else {
|
||||
// char timer[LEN_TIMER_STRING];
|
||||
// tmp_buffer->drawSizedText(5, 2, modelName, /*LEN_MODEL_NAME*/strlen(modelName),
|
||||
// SMLSIZE|TEXT_COLOR);
|
||||
|
||||
// getTimerString(timer, 0);
|
||||
// for (uint8_t i = 0; i < MAX_TIMERS; i++) {
|
||||
// if (partialmodel.timers[i].mode > 0 && partialmodel.timers[i].persistent) {
|
||||
// getTimerString(timer, partialmodel.timers[i].value);
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// tmp_buffer->drawText(101, 40, timer, TEXT_COLOR);
|
||||
// for (int i=0; i<4; i++) {
|
||||
// tmp_buffer->drawBitmapPattern(104+i*11, 25, LBM_SCORE0, TITLE_BGCOLOR);
|
||||
// }
|
||||
// GET_FILENAME(filename, BITMAPS_PATH, partialmodel.header.bitmap, "");
|
||||
// const BitmapBuffer * bitmap = BitmapBuffer::load(filename);
|
||||
// if (bitmap) {
|
||||
// tmp_buffer->drawScaledBitmap(bitmap, 5, 24, 56, 32);
|
||||
// delete bitmap;
|
||||
// }
|
||||
// else {
|
||||
// tmp_buffer->drawBitmapPattern(5, 23, LBM_LIBRARY_SLOT, TEXT_COLOR);
|
||||
// }
|
||||
// }
|
||||
// tmp_buffer->drawSolidHorizontalLine(5, 19, 143, LINE_COLOR);
|
||||
|
||||
// buffer = tmp_buffer;
|
||||
// }
|
||||
|
||||
void ModelCell::save(FIL* file)
|
||||
{
|
||||
#if !defined(SDCARD_YAML)
|
||||
f_puts(modelFilename, file);
|
||||
f_putc('\n', file);
|
||||
#else
|
||||
f_puts(" - filename: ", file);
|
||||
f_puts(modelFilename, file);
|
||||
f_putc('\n', file);
|
||||
|
||||
f_puts(" name: ", file);
|
||||
f_puts(modelName, file);
|
||||
f_putc('\n', file);
|
||||
#endif
|
||||
}
|
||||
|
||||
void ModelCell::setRfData(ModelData* model)
|
||||
|
@ -82,6 +214,7 @@ void ModelCell::setRfModuleData(uint8_t moduleIdx, ModuleData* modData)
|
|||
|
||||
bool ModelCell::fetchRfData()
|
||||
{
|
||||
#if !defined(SDCARD_YAML)
|
||||
//TODO: use g_model in case fetching data for current model
|
||||
//
|
||||
char buf[256];
|
||||
|
@ -126,7 +259,11 @@ bool ModelCell::fetchRfData()
|
|||
|
||||
error:
|
||||
f_close(&file);
|
||||
return false;
|
||||
return false;
|
||||
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
ModelsCategory::ModelsCategory(const char * name)
|
||||
|
@ -134,6 +271,15 @@ ModelsCategory::ModelsCategory(const char * name)
|
|||
strncpy(this->name, name, sizeof(this->name));
|
||||
}
|
||||
|
||||
ModelsCategory::ModelsCategory(const char * name, uint8_t len)
|
||||
{
|
||||
if (len > sizeof(this->name)-1)
|
||||
len = sizeof(this->name)-1;
|
||||
|
||||
memcpy(this->name, name, len);
|
||||
this->name[len] = '\0';
|
||||
}
|
||||
|
||||
ModelsCategory::~ModelsCategory()
|
||||
{
|
||||
for (auto * model: *this) {
|
||||
|
@ -143,6 +289,8 @@ ModelsCategory::~ModelsCategory()
|
|||
|
||||
ModelCell * ModelsCategory::addModel(const char * name)
|
||||
{
|
||||
if (!name) return NULL;
|
||||
|
||||
ModelCell * result = new ModelCell(name);
|
||||
push_back(result);
|
||||
return result;
|
||||
|
@ -183,10 +331,16 @@ void ModelsCategory::moveModel(ModelCell * model, int8_t step)
|
|||
|
||||
void ModelsCategory::save(FIL * file)
|
||||
{
|
||||
#if !defined(SDCARD_YAML)
|
||||
f_puts("[", file);
|
||||
f_puts(name, file);
|
||||
f_puts("]", file);
|
||||
f_putc('\n', file);
|
||||
#else
|
||||
f_puts("- name: ", file);
|
||||
f_puts(name, file);
|
||||
f_putc('\n', file);
|
||||
#endif
|
||||
for (list<ModelCell *>::iterator it = begin(); it != end(); ++it) {
|
||||
(*it)->save(file);
|
||||
}
|
||||
|
@ -228,8 +382,15 @@ bool ModelsList::load()
|
|||
if (loaded)
|
||||
return true;
|
||||
|
||||
#if !defined(SDCARD_YAML)
|
||||
FRESULT result = f_open(&file, RADIO_MODELSLIST_PATH, FA_OPEN_EXISTING | FA_READ);
|
||||
#else
|
||||
FRESULT result = f_open(&file, RADIO_MODELSLIST_YAML_PATH, FA_OPEN_EXISTING | FA_READ);
|
||||
#endif
|
||||
if (result == FR_OK) {
|
||||
|
||||
#if !defined(SDCARD_YAML)
|
||||
// TXT reader
|
||||
while (readNextLine(line, LEN_MODELS_IDX_LINE)) {
|
||||
int len = strlen(line); // TODO could be returned by readNextLine
|
||||
if (len > 2 && line[0] == '[' && line[len-1] == ']') {
|
||||
|
@ -248,12 +409,32 @@ bool ModelsList::load()
|
|||
currentCategory = category;
|
||||
currentModel = model;
|
||||
}
|
||||
//parseModulesData(model, rf_data_str);
|
||||
//TRACE("model=<%s>, valid_rfData=<%i>",model->modelFilename,model->valid_rfData);
|
||||
model->fetchRfData();
|
||||
modelsCount += 1;
|
||||
}
|
||||
}
|
||||
#else
|
||||
// YAML reader
|
||||
TRACE("YAML modelslist reader");
|
||||
|
||||
YamlParser yp; //TODO: move to re-usable buffer
|
||||
yp.init(get_modelslist_parser_calls(), get_modelslist_iter());
|
||||
|
||||
UINT bytes_read=0;
|
||||
while (f_read(&file, line, sizeof(line), &bytes_read) == FR_OK) {
|
||||
|
||||
// reached EOF?
|
||||
if (bytes_read == 0)
|
||||
break;
|
||||
|
||||
if (yp.parse(line, bytes_read) != YamlParser::CONTINUE_PARSING)
|
||||
break;
|
||||
}
|
||||
|
||||
// debug output
|
||||
//modelslist.dump();
|
||||
#endif
|
||||
|
||||
f_close(&file);
|
||||
}
|
||||
|
||||
|
@ -276,12 +457,18 @@ bool ModelsList::load()
|
|||
|
||||
void ModelsList::save()
|
||||
{
|
||||
#if !defined(SDCARD_YAML)
|
||||
FRESULT result = f_open(&file, RADIO_MODELSLIST_PATH, FA_CREATE_ALWAYS | FA_WRITE);
|
||||
#else
|
||||
FRESULT result = f_open(&file, RADIO_MODELSLIST_YAML_PATH, FA_CREATE_ALWAYS | FA_WRITE);
|
||||
#endif
|
||||
|
||||
if (result != FR_OK) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (list<ModelsCategory *>::iterator it = categories.begin(); it != categories.end(); ++it) {
|
||||
for (list<ModelsCategory *>::iterator it = categories.begin();
|
||||
it != categories.end(); ++it) {
|
||||
(*it)->save(&file);
|
||||
}
|
||||
|
||||
|
@ -317,11 +504,16 @@ bool ModelsList::readNextLine(char * line, int maxlen)
|
|||
return false;
|
||||
}
|
||||
|
||||
ModelsCategory * ModelsList::createCategory()
|
||||
ModelsCategory * ModelsList::createCategory(bool save)
|
||||
{
|
||||
ModelsCategory * result = new ModelsCategory("Category");
|
||||
return createCategory("Category", save);
|
||||
}
|
||||
|
||||
ModelsCategory * ModelsList::createCategory(const char* name, bool save)
|
||||
{
|
||||
ModelsCategory * result = new ModelsCategory(name);
|
||||
categories.push_back(result);
|
||||
save();
|
||||
if (save) this->save();
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -23,7 +23,11 @@
|
|||
|
||||
#include <stdint.h>
|
||||
#include <list>
|
||||
|
||||
#include "sdcard.h"
|
||||
#if !defined(SDCARD_YAML)
|
||||
#include "sdcard_raw.h"
|
||||
#endif
|
||||
|
||||
#define MODELCELL_WIDTH 172
|
||||
#define MODELCELL_HEIGHT 59
|
||||
|
@ -48,11 +52,13 @@ class ModelCell
|
|||
SimpleModuleData moduleData[NUM_MODULES];
|
||||
|
||||
explicit ModelCell(const char * name);
|
||||
explicit ModelCell(const char * name, uint8_t len);
|
||||
~ModelCell();
|
||||
|
||||
void save(FIL* file);
|
||||
|
||||
void setModelName(char* name);
|
||||
void setModelName(char* name, uint8_t len);
|
||||
void setRfData(ModelData* model);
|
||||
|
||||
void setModelId(uint8_t moduleIdx, uint8_t id);
|
||||
|
@ -69,11 +75,13 @@ public:
|
|||
char name[LEN_MODEL_FILENAME+1];
|
||||
|
||||
explicit ModelsCategory(const char * name);
|
||||
explicit ModelsCategory(const char * name, uint8_t len);
|
||||
~ModelsCategory();
|
||||
|
||||
ModelCell * addModel(const char * name);
|
||||
void removeModel(ModelCell * model);
|
||||
void moveModel(ModelCell * model, int8_t step);
|
||||
|
||||
void save(FIL * file);
|
||||
};
|
||||
|
||||
|
@ -100,6 +108,11 @@ public:
|
|||
{
|
||||
return categories;
|
||||
}
|
||||
|
||||
std::list<ModelsCategory *>& getCategories()
|
||||
{
|
||||
return categories;
|
||||
}
|
||||
|
||||
void setCurrentCategorie(ModelsCategory * cat);
|
||||
|
||||
|
@ -115,6 +128,10 @@ public:
|
|||
return currentModel;
|
||||
}
|
||||
|
||||
void incModelsCount() {
|
||||
modelsCount++;
|
||||
}
|
||||
|
||||
unsigned int getModelsCount() const
|
||||
{
|
||||
return modelsCount;
|
||||
|
@ -122,7 +139,8 @@ public:
|
|||
|
||||
bool readNextLine(char * line, int maxlen);
|
||||
|
||||
ModelsCategory * createCategory();
|
||||
ModelsCategory * createCategory(bool save=true);
|
||||
ModelsCategory * createCategory(const char * name, bool save=true);
|
||||
void removeCategory(ModelsCategory * category);
|
||||
|
||||
ModelCell * addModel(ModelsCategory * category, const char * name);
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
*/
|
||||
|
||||
#include "opentx.h"
|
||||
#include "rambackup.h"
|
||||
|
||||
namespace Backup {
|
||||
#define BACKUP
|
||||
|
|
36
radio/src/storage/rambackup.h
Normal file
36
radio/src/storage/rambackup.h
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef _RAMBACKUP_H_
|
||||
#define _RAMBACKUP_H_
|
||||
|
||||
#include "rlc.h"
|
||||
|
||||
PACK(struct RamBackup {
|
||||
uint16_t size;
|
||||
uint8_t data[4094];
|
||||
});
|
||||
|
||||
extern RamBackup * ramBackup;
|
||||
|
||||
void rambackupWrite();
|
||||
bool rambackupRestore();
|
||||
|
||||
#endif
|
|
@ -22,6 +22,8 @@
|
|||
#include <assert.h>
|
||||
#include "debug.h"
|
||||
|
||||
#include "rlc.h"
|
||||
|
||||
#define CHECK_DST_SIZE() \
|
||||
if (cur-dst >= (int)dstsize) { \
|
||||
TRACE("RLC encoding size too big"); \
|
||||
|
|
27
radio/src/storage/rlc.h
Normal file
27
radio/src/storage/rlc.h
Normal file
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef _RLC_H_
|
||||
#define _RLC_H_
|
||||
|
||||
unsigned int compress(uint8_t * dst, unsigned int dstsize, const uint8_t * src, unsigned int len);
|
||||
unsigned int uncompress(uint8_t * dst, unsigned int dstsize, const uint8_t * src, unsigned int len);
|
||||
|
||||
#endif
|
161
radio/src/storage/sdcard_common.cpp
Normal file
161
radio/src/storage/sdcard_common.cpp
Normal file
|
@ -0,0 +1,161 @@
|
|||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include "opentx.h"
|
||||
#include "storage.h"
|
||||
#include "sdcard_common.h"
|
||||
#include "modelslist.h"
|
||||
#include "conversions/conversions.h"
|
||||
|
||||
// defined either in sdcard_raw.cpp or sdcard_yaml.cpp
|
||||
void storageCreateModelsList();
|
||||
|
||||
void getModelPath(char * path, const char * filename)
|
||||
{
|
||||
strcpy(path, STR_MODELS_PATH);
|
||||
path[sizeof(MODELS_PATH)-1] = '/';
|
||||
strcpy(&path[sizeof(MODELS_PATH)], filename);
|
||||
}
|
||||
|
||||
void storageEraseAll(bool warn)
|
||||
{
|
||||
TRACE("storageEraseAll");
|
||||
|
||||
#if defined(LIBOPENUI)
|
||||
// the theme has not been loaded before
|
||||
static_cast<ThemeBase*>(theme)->load();
|
||||
#endif
|
||||
|
||||
generalDefault();
|
||||
modelDefault(1);
|
||||
|
||||
if (warn) {
|
||||
ALERT(STR_STORAGE_WARNING, STR_BAD_RADIO_DATA, AU_BAD_RADIODATA);
|
||||
}
|
||||
|
||||
RAISE_ALERT(STR_STORAGE_WARNING, STR_STORAGE_FORMAT, NULL, AU_NONE);
|
||||
|
||||
storageFormat();
|
||||
storageDirty(EE_GENERAL|EE_MODEL);
|
||||
storageCheck(true);
|
||||
}
|
||||
|
||||
void storageFormat()
|
||||
{
|
||||
sdCheckAndCreateDirectory(RADIO_PATH);
|
||||
sdCheckAndCreateDirectory(MODELS_PATH);
|
||||
storageCreateModelsList();
|
||||
}
|
||||
|
||||
void storageCheck(bool immediately)
|
||||
{
|
||||
if (storageDirtyMsk & EE_GENERAL) {
|
||||
TRACE("eeprom write general");
|
||||
storageDirtyMsk -= EE_GENERAL;
|
||||
const char * error = writeGeneralSettings();
|
||||
if (error) {
|
||||
TRACE("writeGeneralSettings error=%s", error);
|
||||
}
|
||||
}
|
||||
|
||||
if (storageDirtyMsk & EE_MODEL) {
|
||||
TRACE("eeprom write model");
|
||||
storageDirtyMsk -= EE_MODEL;
|
||||
const char * error = writeModel();
|
||||
if (error) {
|
||||
TRACE("writeModel error=%s", error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const char * createModel()
|
||||
{
|
||||
preModelLoad();
|
||||
|
||||
char filename[LEN_MODEL_FILENAME+1];
|
||||
memset(filename, 0, sizeof(filename));
|
||||
strcpy(filename, MODEL_FILENAME_PATTERN);
|
||||
|
||||
int index = findNextFileIndex(filename, LEN_MODEL_FILENAME, MODELS_PATH);
|
||||
if (index > 0) {
|
||||
modelDefault(index);
|
||||
memcpy(g_eeGeneral.currModelFilename, filename, sizeof(g_eeGeneral.currModelFilename));
|
||||
storageDirty(EE_GENERAL);
|
||||
storageDirty(EE_MODEL);
|
||||
storageCheck(true);
|
||||
}
|
||||
postModelLoad(false);
|
||||
|
||||
return g_eeGeneral.currModelFilename;
|
||||
}
|
||||
|
||||
const char * loadModel(const char * filename, bool alarms)
|
||||
{
|
||||
uint8_t version;
|
||||
|
||||
preModelLoad();
|
||||
|
||||
const char * error = readModel(filename, (uint8_t *)&g_model, sizeof(g_model), &version);
|
||||
if (error) {
|
||||
TRACE("loadModel error=%s", error);
|
||||
}
|
||||
|
||||
if (error) {
|
||||
modelDefault(0) ;
|
||||
storageCheck(true);
|
||||
alarms = false;
|
||||
}
|
||||
else if (version < EEPROM_VER) {
|
||||
convertModelData(version);
|
||||
}
|
||||
|
||||
postModelLoad(alarms);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
void storageReadAll()
|
||||
{
|
||||
TRACE("storageReadAll");
|
||||
|
||||
if (loadRadioSettings() != nullptr) {
|
||||
storageEraseAll(true);
|
||||
}
|
||||
|
||||
for (uint8_t i = 0; languagePacks[i] != nullptr; i++) {
|
||||
if (!strncmp(g_eeGeneral.ttsLanguage, languagePacks[i]->id, 2)) {
|
||||
currentLanguagePackIdx = i;
|
||||
currentLanguagePack = languagePacks[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (loadModel(g_eeGeneral.currModelFilename, false) != nullptr) {
|
||||
sdCheckAndCreateDirectory(MODELS_PATH);
|
||||
createModel();
|
||||
}
|
||||
|
||||
// Wipe models list in case
|
||||
// it's being reloaded after USB connection
|
||||
modelslist.clear();
|
||||
|
||||
// and reload the list
|
||||
modelslist.load();
|
||||
}
|
||||
|
51
radio/src/storage/sdcard_common.h
Normal file
51
radio/src/storage/sdcard_common.h
Normal file
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef _SDCARD_COMMON_H_
|
||||
#define _SDCARD_COMMON_H_
|
||||
|
||||
#include "ff.h"
|
||||
|
||||
#define DEFAULT_CATEGORY "Models"
|
||||
|
||||
#if defined(SDCARD_RAW)
|
||||
#define DEFAULT_MODEL_FILENAME "model1.bin"
|
||||
#define MODEL_FILENAME_PATTERN "model.bin"
|
||||
#elif defined(SDCARD_YAML)
|
||||
#define DEFAULT_MODEL_FILENAME "model1.yml"
|
||||
#define MODEL_FILENAME_PATTERN "model.yml"
|
||||
#endif
|
||||
|
||||
// opens radio.bin or model file
|
||||
const char * openFile(const char * fullpath, FIL * file, uint16_t * size, uint8_t * version);
|
||||
|
||||
void getModelPath(char * path, const char * filename);
|
||||
|
||||
const char * readModel(const char * filename, uint8_t * buffer, uint32_t size, uint8_t * version);
|
||||
const char * loadModel(const char * filename, bool alarms=true);
|
||||
const char * createModel();
|
||||
const char * writeModel();
|
||||
|
||||
const char * loadRadioSettings();
|
||||
const char * writeGeneralSettings();
|
||||
|
||||
const char * loadRadioSettings(const char * path);
|
||||
const char * loadRadioSettings();
|
||||
#endif // _SDCARD_RAW_H_
|
|
@ -22,13 +22,6 @@
|
|||
#include "modelslist.h"
|
||||
#include "conversions/conversions.h"
|
||||
|
||||
void getModelPath(char * path, const char * filename)
|
||||
{
|
||||
strcpy(path, STR_MODELS_PATH);
|
||||
path[sizeof(MODELS_PATH)-1] = '/';
|
||||
strcpy(&path[sizeof(MODELS_PATH)], filename);
|
||||
}
|
||||
|
||||
const char * writeFile(const char * filename, const uint8_t * data, uint16_t size)
|
||||
{
|
||||
TRACE("writeFile(%s)", filename);
|
||||
|
@ -91,6 +84,8 @@ const char * openFile(const char * fullpath, FIL * file, uint16_t * size, uint8_
|
|||
return SDCARD_ERROR(result);
|
||||
}
|
||||
|
||||
//TODO: move this code into some checkCompatibleFormat()
|
||||
|
||||
*version = (uint8_t)buf[4];
|
||||
if (*(uint32_t*)&buf[0] != OTX_FOURCC || *version < FIRST_CONV_EEPROM_VER || *version > EEPROM_VER || buf[5] != 'M') {
|
||||
f_close(file);
|
||||
|
@ -131,32 +126,6 @@ const char * readModel(const char * filename, uint8_t * buffer, uint32_t size, u
|
|||
return loadFile(path, buffer, size, version);
|
||||
}
|
||||
|
||||
const char * loadModel(const char * filename, bool alarms)
|
||||
{
|
||||
uint8_t version;
|
||||
|
||||
preModelLoad();
|
||||
|
||||
const char * error = readModel(filename, (uint8_t *)&g_model, sizeof(g_model), &version);
|
||||
if (error) {
|
||||
TRACE("loadModel error=%s", error);
|
||||
}
|
||||
|
||||
if (error) {
|
||||
modelDefault(0) ;
|
||||
storageCheck(true);
|
||||
alarms = false;
|
||||
}
|
||||
#if defined(EEPROM_CONVERSIONS)
|
||||
else if (version < EEPROM_VER) {
|
||||
convertModelData(version);
|
||||
}
|
||||
#endif
|
||||
|
||||
postModelLoad(alarms);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
const char * loadRadioSettings(const char * path)
|
||||
{
|
||||
|
@ -188,55 +157,6 @@ const char * writeGeneralSettings()
|
|||
return writeFile(RADIO_SETTINGS_PATH, (uint8_t *)&g_eeGeneral, sizeof(g_eeGeneral));
|
||||
}
|
||||
|
||||
void storageCheck(bool immediately)
|
||||
{
|
||||
if (storageDirtyMsk & EE_GENERAL) {
|
||||
TRACE("Storage write general");
|
||||
storageDirtyMsk -= EE_GENERAL;
|
||||
const char * error = writeGeneralSettings();
|
||||
if (error) {
|
||||
TRACE("writeGeneralSettings error=%s", error);
|
||||
}
|
||||
}
|
||||
|
||||
if (storageDirtyMsk & EE_MODEL) {
|
||||
TRACE("Storage write current model");
|
||||
storageDirtyMsk -= EE_MODEL;
|
||||
const char * error = writeModel();
|
||||
if (error) {
|
||||
TRACE("writeModel error=%s", error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void storageReadAll()
|
||||
{
|
||||
TRACE("storageReadAll");
|
||||
|
||||
if (loadRadioSettings() != nullptr) {
|
||||
storageEraseAll(true);
|
||||
}
|
||||
|
||||
for (uint8_t i = 0; languagePacks[i] != nullptr; i++) {
|
||||
if (!strncmp(g_eeGeneral.ttsLanguage, languagePacks[i]->id, 2)) {
|
||||
currentLanguagePackIdx = i;
|
||||
currentLanguagePack = languagePacks[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (loadModel(g_eeGeneral.currModelFilename, false) != nullptr) {
|
||||
sdCheckAndCreateDirectory(MODELS_PATH);
|
||||
createModel();
|
||||
}
|
||||
|
||||
// Wipe models list in case
|
||||
// it's being reloaded after USB connection
|
||||
modelslist.clear();
|
||||
|
||||
// and reload the list
|
||||
modelslist.load();
|
||||
}
|
||||
|
||||
void storageCreateModelsList()
|
||||
{
|
||||
FIL file;
|
||||
|
@ -247,54 +167,3 @@ void storageCreateModelsList()
|
|||
f_close(&file);
|
||||
}
|
||||
}
|
||||
|
||||
void storageFormat()
|
||||
{
|
||||
sdCheckAndCreateDirectory(RADIO_PATH);
|
||||
sdCheckAndCreateDirectory(MODELS_PATH);
|
||||
storageCreateModelsList();
|
||||
}
|
||||
|
||||
const char * createModel()
|
||||
{
|
||||
preModelLoad();
|
||||
|
||||
char filename[LEN_MODEL_FILENAME+1];
|
||||
memset(filename, 0, sizeof(filename));
|
||||
strcpy(filename, "model.bin");
|
||||
|
||||
unsigned int index = findNextFileIndex(filename, LEN_MODEL_FILENAME, MODELS_PATH);
|
||||
if (index > 0) {
|
||||
modelDefault(index);
|
||||
memcpy(g_eeGeneral.currModelFilename, filename, sizeof(g_eeGeneral.currModelFilename));
|
||||
storageDirty(EE_GENERAL);
|
||||
storageDirty(EE_MODEL);
|
||||
storageCheck(true);
|
||||
}
|
||||
postModelLoad(false);
|
||||
|
||||
return g_eeGeneral.currModelFilename;
|
||||
}
|
||||
|
||||
void storageEraseAll(bool warn)
|
||||
{
|
||||
TRACE("storageEraseAll");
|
||||
|
||||
#if defined(LIBOPENUI)
|
||||
// the theme has not been loaded before
|
||||
static_cast<ThemeBase*>(theme)->load();
|
||||
#endif
|
||||
|
||||
generalDefault();
|
||||
modelDefault(1);
|
||||
|
||||
if (warn) {
|
||||
ALERT(STR_STORAGE_WARNING, STR_BAD_RADIO_DATA, AU_BAD_RADIODATA);
|
||||
}
|
||||
|
||||
RAISE_ALERT(STR_STORAGE_WARNING, STR_STORAGE_FORMAT, NULL, AU_NONE);
|
||||
|
||||
storageFormat();
|
||||
storageDirty(EE_GENERAL|EE_MODEL);
|
||||
storageCheck(true);
|
||||
}
|
||||
|
|
|
@ -1,48 +1,8 @@
|
|||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef _SDCARD_RAW_H_
|
||||
#define _SDCARD_RAW_H_
|
||||
|
||||
#include "ff.h"
|
||||
#include "FatFs/ff.h"
|
||||
|
||||
#define DEFAULT_CATEGORY "Models"
|
||||
#define DEFAULT_MODEL_FILENAME "model1.bin"
|
||||
const char * openFile(const char * fullpath, FIL* file, uint16_t* size);
|
||||
|
||||
// opens radio.bin or model file
|
||||
const char * openFile(const char * fullpath, FIL * file, uint16_t * size, uint8_t * version);
|
||||
|
||||
void getModelPath(char * path, const char * filename);
|
||||
|
||||
const char * readModel(const char * filename, uint8_t * buffer, uint32_t size, uint8_t * version);
|
||||
const char * loadModel(const char * filename, bool alarms=true);
|
||||
const char * createModel();
|
||||
|
||||
const char * loadRadioSettings(const char * path);
|
||||
const char * loadRadioSettings();
|
||||
|
||||
PACK(struct RamBackup {
|
||||
uint16_t size;
|
||||
uint8_t data[4094];
|
||||
});
|
||||
|
||||
extern RamBackup * ramBackup;
|
||||
|
||||
#endif // _SDCARD_RAW_H_
|
||||
#endif
|
||||
|
|
194
radio/src/storage/sdcard_yaml.cpp
Normal file
194
radio/src/storage/sdcard_yaml.cpp
Normal file
|
@ -0,0 +1,194 @@
|
|||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include "opentx.h"
|
||||
#include "storage.h"
|
||||
#include "sdcard_common.h"
|
||||
|
||||
#include "modelslist.h"
|
||||
|
||||
#include "yaml/yaml_tree_walker.h"
|
||||
#include "yaml/yaml_parser.h"
|
||||
#include "yaml/yaml_datastructs.h"
|
||||
|
||||
const char * readYamlFile(const char* fullpath, const YamlParserCalls* calls, void* parser_ctx)
|
||||
{
|
||||
FIL file;
|
||||
UINT bytes_read;
|
||||
|
||||
FRESULT result = f_open(&file, fullpath, FA_OPEN_EXISTING | FA_READ);
|
||||
if (result != FR_OK) {
|
||||
return SDCARD_ERROR(result);
|
||||
}
|
||||
|
||||
YamlParser yp; //TODO: move to re-usable buffer
|
||||
yp.init(calls, parser_ctx);
|
||||
|
||||
char buffer[32];
|
||||
while (f_read(&file, buffer, sizeof(buffer), &bytes_read) == FR_OK) {
|
||||
|
||||
// reached EOF?
|
||||
if (bytes_read == 0)
|
||||
break;
|
||||
|
||||
if (yp.parse(buffer, bytes_read) != YamlParser::CONTINUE_PARSING)
|
||||
break;
|
||||
}
|
||||
|
||||
f_close(&file);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Generic storage interface
|
||||
//
|
||||
|
||||
void storageCreateModelsList()
|
||||
{
|
||||
modelslist.clear();
|
||||
ModelsCategory* cat = modelslist.createCategory(DEFAULT_CATEGORY, false);
|
||||
cat->addModel(DEFAULT_MODEL_FILENAME);
|
||||
modelslist.save();
|
||||
}
|
||||
|
||||
//
|
||||
// SDCARD storage interface
|
||||
//
|
||||
|
||||
|
||||
const char * loadRadioSettings()
|
||||
{
|
||||
// YAML reader
|
||||
TRACE("YAML radio settings reader");
|
||||
|
||||
YamlTreeWalker tree;
|
||||
tree.reset(get_radiodata_nodes(), (uint8_t*)&g_eeGeneral);
|
||||
|
||||
return readYamlFile(RADIO_SETTINGS_YAML_PATH, YamlTreeWalker::get_parser_calls(), &tree);
|
||||
}
|
||||
|
||||
struct yaml_writer_ctx {
|
||||
FIL* file;
|
||||
FRESULT result;
|
||||
};
|
||||
|
||||
static bool yaml_writer(void* opaque, const char* str, size_t len)
|
||||
{
|
||||
UINT bytes_written;
|
||||
yaml_writer_ctx* ctx = (yaml_writer_ctx*)opaque;
|
||||
|
||||
TRACE_NOCRLF("%.*s",len,str);
|
||||
|
||||
ctx->result = f_write(ctx->file, str, len, &bytes_written);
|
||||
return (ctx->result == FR_OK) && (bytes_written == len);
|
||||
}
|
||||
|
||||
const char * writeGeneralSettings()
|
||||
{
|
||||
// YAML reader
|
||||
TRACE("YAML radio settings writer");
|
||||
|
||||
FIL file;
|
||||
|
||||
FRESULT result = f_open(&file, RADIO_SETTINGS_YAML_PATH, FA_CREATE_ALWAYS | FA_WRITE);
|
||||
if (result != FR_OK) {
|
||||
return SDCARD_ERROR(result);
|
||||
}
|
||||
|
||||
YamlTreeWalker tree;
|
||||
tree.reset(get_radiodata_nodes(), (uint8_t*)&g_eeGeneral);
|
||||
|
||||
yaml_writer_ctx ctx;
|
||||
ctx.file = &file;
|
||||
ctx.result = FR_OK;
|
||||
|
||||
if (!tree.generate(yaml_writer, &ctx)) {
|
||||
if (ctx.result != FR_OK) {
|
||||
f_close(&file);
|
||||
return SDCARD_ERROR(ctx.result);
|
||||
}
|
||||
}
|
||||
|
||||
f_close(&file);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
const char * readModel(const char * filename, uint8_t * buffer, uint32_t size, uint8_t * version)
|
||||
{
|
||||
// YAML reader
|
||||
TRACE("YAML model reader");
|
||||
|
||||
char path[256];
|
||||
getModelPath(path, filename);
|
||||
|
||||
YamlTreeWalker tree;
|
||||
tree.reset(get_modeldata_nodes(), buffer);
|
||||
|
||||
// wipe memory before reading YAML
|
||||
memset(buffer,0,size);
|
||||
|
||||
//#if defined(FLIGHT_MODES) && defined(GVARS)
|
||||
// reset GVars to default values
|
||||
// Note: taken from opentx.cpp::modelDefault()
|
||||
//TODO: new func in gvars
|
||||
for (int p=1; p<MAX_FLIGHT_MODES; p++) {
|
||||
for (int i=0; i<MAX_GVARS; i++) {
|
||||
g_model.flightModeData[p].gvars[i] = GVAR_MAX+1;
|
||||
}
|
||||
}
|
||||
//#endif
|
||||
|
||||
return readYamlFile(path, YamlTreeWalker::get_parser_calls(), &tree);
|
||||
}
|
||||
|
||||
const char * writeModel()
|
||||
{
|
||||
// YAML reader
|
||||
TRACE("YAML model writer");
|
||||
|
||||
char path[256];
|
||||
getModelPath(path, g_eeGeneral.currModelFilename);
|
||||
|
||||
FIL file;
|
||||
|
||||
FRESULT result = f_open(&file, path, FA_CREATE_ALWAYS | FA_WRITE);
|
||||
if (result != FR_OK) {
|
||||
return SDCARD_ERROR(result);
|
||||
}
|
||||
|
||||
YamlTreeWalker tree;
|
||||
tree.reset(get_modeldata_nodes(), (uint8_t*)&g_model);
|
||||
|
||||
yaml_writer_ctx ctx;
|
||||
ctx.file = &file;
|
||||
ctx.result = FR_OK;
|
||||
|
||||
if (!tree.generate(yaml_writer, &ctx)) {
|
||||
if (ctx.result != FR_OK) {
|
||||
f_close(&file);
|
||||
return SDCARD_ERROR(ctx.result);
|
||||
}
|
||||
}
|
||||
|
||||
f_close(&file);
|
||||
return NULL;
|
||||
}
|
|
@ -43,32 +43,34 @@ extern tmr10ms_t rambackupDirtyTime10ms;
|
|||
#define TIME_TO_RAMBACKUP() (rambackupDirtyMsk && (tmr10ms_t)(get_tmr10ms() - rambackupDirtyTime10ms) >= (tmr10ms_t)100)
|
||||
#endif
|
||||
|
||||
//
|
||||
// Generic storage interface
|
||||
//
|
||||
void storageEraseAll(bool warn);
|
||||
void storageFormat();
|
||||
void storageReadAll();
|
||||
void storageDirty(uint8_t msk);
|
||||
void storageCheck(bool immediately);
|
||||
|
||||
//
|
||||
// Generic storage functions (implemented in storage_common.cpp)
|
||||
//
|
||||
void storageDirty(uint8_t msk);
|
||||
void storageFlushCurrentModel();
|
||||
void postRadioSettingsLoad();
|
||||
void preModelLoad();
|
||||
void postModelLoad(bool alarms);
|
||||
void checkExternalAntenna();
|
||||
|
||||
#if defined(EEPROM_RLC)
|
||||
#if defined(EEPROM)
|
||||
#include "eeprom_common.h"
|
||||
#include "eeprom_rlc.h"
|
||||
#elif defined(EEPROM)
|
||||
#include "eeprom_common.h"
|
||||
#include "eeprom_raw.h"
|
||||
#elif defined(SDCARD)
|
||||
#include "sdcard_raw.h"
|
||||
#endif
|
||||
|
||||
#if defined(SDCARD_RAW) || defined(SDCARD_YAML)
|
||||
#include "sdcard_common.h"
|
||||
#endif
|
||||
|
||||
#if defined(RAMBACKUP)
|
||||
void rambackupWrite();
|
||||
bool rambackupRestore();
|
||||
unsigned int compress(uint8_t * dst, unsigned int dstsize, const uint8_t * src, unsigned int len);
|
||||
unsigned int uncompress(uint8_t * dst, unsigned int dstsize, const uint8_t * src, unsigned int len);
|
||||
#include "rambackup.h"
|
||||
#endif
|
||||
|
||||
#endif // _STORAGE_H_
|
||||
|
|
46
radio/src/storage/yaml/CMakeLists.txt
Normal file
46
radio/src/storage/yaml/CMakeLists.txt
Normal file
|
@ -0,0 +1,46 @@
|
|||
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
set(SRC ${SRC} storage/yaml/yaml_tree_walker.cpp
|
||||
storage/yaml/yaml_parser.cpp
|
||||
storage/yaml/yaml_bits.cpp
|
||||
storage/yaml/yaml_modelslist.cpp
|
||||
storage/yaml/yaml_datastructs.cpp)
|
||||
|
||||
if(PCB STREQUAL X12S)
|
||||
set(YAML_GEN_OUTPUT storage/yaml/yaml_datastructs_x12s.cpp)
|
||||
elseif(PCB STREQUAL X10)
|
||||
set(YAML_GEN_OUTPUT storage/yaml/yaml_datastructs_x10.cpp)
|
||||
else()
|
||||
message(FATAL_ERROR "PCB '${PCB}' is not supported by YAML storage")
|
||||
endif()
|
||||
|
||||
set(YAML_GEN ${RADIO_DIRECTORY}/util/generate_yaml.py)
|
||||
set(YAML_GEN_TEMPLATE ${RADIO_DIRECTORY}/util/yaml_parser.tmpl)
|
||||
|
||||
SET(YAML_NODES "\"RadioData,ModelData\"")
|
||||
set(YAML_GEN_ARGS myeeprom.h ${YAML_GEN_TEMPLATE} ${YAML_NODES} -DYAML_GENERATOR)
|
||||
|
||||
get_property(flags DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY COMPILE_DEFINITIONS)
|
||||
foreach(flag ${flags})
|
||||
#message(STATUS "dir='${dir}'")
|
||||
set(YAML_GEN_ARGS ${YAML_GEN_ARGS} -D${flag})
|
||||
endforeach()
|
||||
|
||||
get_property(dirs DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY INCLUDE_DIRECTORIES)
|
||||
foreach(dir ${dirs})
|
||||
#message(STATUS "dir='${dir}'")
|
||||
set(YAML_GEN_ARGS ${YAML_GEN_ARGS} -I${dir})
|
||||
endforeach()
|
||||
|
||||
set(YAML_GEN_ARGS ${YAML_GEN_ARGS} -DRTOS_COOS -Wno-inconsistent-missing-override)
|
||||
|
||||
#message(STATUS "YAML_GEN_ARGS=${YAML_GEN_ARGS}")
|
||||
|
||||
add_custom_target(yaml_data
|
||||
WORKING_DIRECTORY ${RADIO_DIRECTORY}/src
|
||||
COMMAND ${PYTHON_EXECUTABLE} ${YAML_GEN} ${YAML_GEN_ARGS} > ${YAML_GEN_OUTPUT}
|
||||
DEPENDS ${RADIO_DIRECTORY}/src/datastructs.h
|
||||
${RADIO_DIRECTORY}/src/dataconstants.h
|
||||
${RADIO_DIRECTORY}/src/myeeprom.h
|
||||
${RADIO_DIRECTORY}/util/generate_yaml.py
|
||||
)
|
137
radio/src/storage/yaml/yaml_bits.cpp
Normal file
137
radio/src/storage/yaml/yaml_bits.cpp
Normal file
|
@ -0,0 +1,137 @@
|
|||
#include <stdio.h>
|
||||
#include "yaml_bits.h"
|
||||
#include "yaml_parser.h"
|
||||
|
||||
#define MASK_LOWER(bits) ((1 << (bits)) - 1)
|
||||
#define MASK_UPPER(bits) (0xFF << bits)
|
||||
|
||||
void yaml_put_bits(uint8_t* dst, uint32_t i, uint32_t bit_ofs, uint32_t bits)
|
||||
{
|
||||
i &= ((1UL << bits) - 1);
|
||||
|
||||
if (bit_ofs) {
|
||||
|
||||
*dst &= MASK_LOWER(bit_ofs);
|
||||
*(dst++) |= (i << bit_ofs) & 0xFF;
|
||||
|
||||
if (bits <= 8 - bit_ofs)
|
||||
return;
|
||||
|
||||
bits -= 8 - bit_ofs;
|
||||
i = i >> (8 - bit_ofs);
|
||||
}
|
||||
|
||||
while(bits >= 8) {
|
||||
*(dst++) = i & 0xFF;
|
||||
bits -= 8;
|
||||
i = i >> 8;
|
||||
}
|
||||
|
||||
if (bits) {
|
||||
uint8_t mask = MASK_UPPER(bits);
|
||||
*dst &= mask;
|
||||
*dst |= i & ~mask;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uint32_t yaml_get_bits(uint8_t* src, uint32_t bit_ofs, uint32_t bits)
|
||||
{
|
||||
uint32_t i = 0;
|
||||
uint32_t bit_shift = 0;
|
||||
|
||||
if (bit_ofs) {
|
||||
i = (*(src++) & MASK_UPPER(bit_ofs)) >> bit_ofs;
|
||||
|
||||
if (bits <= 8 - bit_ofs) {
|
||||
i &= MASK_LOWER(bits);
|
||||
return i;
|
||||
}
|
||||
|
||||
bit_shift = 8 - bit_ofs;
|
||||
bits -= bit_shift;
|
||||
}
|
||||
|
||||
while(bits >= 8) {
|
||||
|
||||
i |= (uint32_t)*(src++) << bit_shift;
|
||||
|
||||
bits -= 8;
|
||||
bit_shift += 8;
|
||||
}
|
||||
|
||||
if (bits) {
|
||||
i |= ((uint32_t)*src & MASK_LOWER(bits)) << bit_shift;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
bool yaml_is_zero(uint8_t* data, uint32_t bitoffs, uint32_t bits)
|
||||
{
|
||||
return !yaml_get_bits(data + (bitoffs>>3UL), bitoffs & 0x7, bits);
|
||||
}
|
||||
|
||||
int32_t yaml_str2int(const char* val, uint8_t val_len)
|
||||
{
|
||||
bool neg = false;
|
||||
int i_val = 0;
|
||||
|
||||
for(uint8_t i=0; i < val_len; i++) {
|
||||
if (val[i] == '-')
|
||||
neg = true;
|
||||
else if (val[i] >= '0' && val[i] <= '9') {
|
||||
i_val = i_val * 10 + (val[i] - '0');
|
||||
}
|
||||
}
|
||||
|
||||
return neg ? -i_val : i_val;
|
||||
}
|
||||
|
||||
uint32_t yaml_str2uint(const char* val, uint8_t val_len)
|
||||
{
|
||||
uint32_t i_val = 0;
|
||||
|
||||
for(uint8_t i=0; i < val_len; i++) {
|
||||
if (val[i] >= '0' && val[i] <= '9') {
|
||||
i_val = i_val * 10 + (val[i] - '0');
|
||||
}
|
||||
}
|
||||
|
||||
return i_val;
|
||||
}
|
||||
|
||||
static char int2str_buffer[MAX_STR] = {0};
|
||||
static const char _int2str_lookup[] = { '0', '1', '2', '3', '4', '5', '6' , '7', '8', '9' };
|
||||
|
||||
char* yaml_unsigned2str(uint32_t i)
|
||||
{
|
||||
char* c = &(int2str_buffer[MAX_STR-2]);
|
||||
do {
|
||||
*(c--) = _int2str_lookup[i % 10];
|
||||
i = i / 10;
|
||||
} while((c > int2str_buffer) && i);
|
||||
|
||||
return (c + 1);
|
||||
}
|
||||
|
||||
char* yaml_signed2str(int32_t i)
|
||||
{
|
||||
if (i < 0) {
|
||||
char* c = yaml_unsigned2str(-i);
|
||||
*(--c) = '-';
|
||||
return c;
|
||||
}
|
||||
|
||||
return yaml_unsigned2str((uint32_t)i);
|
||||
}
|
||||
|
||||
int32_t yaml_to_signed(uint32_t i, uint32_t bits)
|
||||
{
|
||||
if (i & (1 << (bits-1))) {
|
||||
i |= 0xFFFFFFFF << bits;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
20
radio/src/storage/yaml/yaml_bits.h
Normal file
20
radio/src/storage/yaml/yaml_bits.h
Normal file
|
@ -0,0 +1,20 @@
|
|||
#ifndef _yaml_bits_h_
|
||||
#define _yaml_bits_h_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void yaml_put_bits(uint8_t* dst, uint32_t i, uint32_t bit_ofs, uint32_t bits);
|
||||
uint32_t yaml_get_bits(uint8_t* src, uint32_t bit_ofs, uint32_t bits);
|
||||
|
||||
// assumes bits is a multiple of 8
|
||||
bool yaml_is_zero(uint8_t* data, uint32_t bitoffs, uint32_t bits);
|
||||
|
||||
int32_t yaml_str2int(const char* val, uint8_t val_len);
|
||||
uint32_t yaml_str2uint(const char* val, uint8_t val_len);
|
||||
|
||||
char* yaml_unsigned2str(uint32_t i);
|
||||
char* yaml_signed2str(int32_t i);
|
||||
|
||||
int32_t yaml_to_signed(uint32_t i, uint32_t bits);
|
||||
|
||||
#endif
|
13
radio/src/storage/yaml/yaml_datastructs.cpp
Normal file
13
radio/src/storage/yaml/yaml_datastructs.cpp
Normal file
|
@ -0,0 +1,13 @@
|
|||
|
||||
#include "opentx.h"
|
||||
#include "yaml_node.h"
|
||||
|
||||
#include "yaml_datastructs_funcs.cpp"
|
||||
|
||||
#if defined(PCBX10)
|
||||
#include "yaml_datastructs_x10.cpp"
|
||||
#elif defined(PCBX12S)
|
||||
#include "yaml_datastructs_x12s.cpp"
|
||||
#else
|
||||
#error "Board not supported by YAML storage"
|
||||
#endif
|
9
radio/src/storage/yaml/yaml_datastructs.h
Normal file
9
radio/src/storage/yaml/yaml_datastructs.h
Normal file
|
@ -0,0 +1,9 @@
|
|||
#ifndef _YAML_DATASTRUCTS_H_
|
||||
#define _YAML_DATASTRUCTS_H_
|
||||
|
||||
struct YamlNode;
|
||||
|
||||
const YamlNode* get_radiodata_nodes();
|
||||
const YamlNode* get_modeldata_nodes();
|
||||
|
||||
#endif
|
361
radio/src/storage/yaml/yaml_datastructs_funcs.cpp
Normal file
361
radio/src/storage/yaml/yaml_datastructs_funcs.cpp
Normal file
|
@ -0,0 +1,361 @@
|
|||
#include "opentx.h"
|
||||
#include "yaml_bits.h"
|
||||
#include "yaml_tree_walker.h"
|
||||
|
||||
#define GVAR_SMALL 128
|
||||
|
||||
static uint32_t in_read_weight(const YamlNode* node, const char* val, uint8_t val_len)
|
||||
{
|
||||
if ((val_len == 4)
|
||||
&& (val[0] == '-')
|
||||
&& (val[1] == 'G')
|
||||
&& (val[2] == 'V')
|
||||
&& (val[3] >= '1')
|
||||
&& (val[3] <= '9')) {
|
||||
|
||||
TRACE("%.*s -> %i\n", val_len, val, GVAR_SMALL - (val[3] - '0'));
|
||||
return GVAR_SMALL - (val[3] - '0'); // -GVx => 128 - x
|
||||
}
|
||||
|
||||
if ((val_len == 3)
|
||||
&& (val[0] == 'G')
|
||||
&& (val[1] == 'V')
|
||||
&& (val[2] >= '1')
|
||||
&& (val[2] <= '9')) {
|
||||
|
||||
TRACE("%.*s -> %i\n", val_len, val, -GVAR_SMALL + (val[2] - '1'));
|
||||
return -GVAR_SMALL + (val[2] - '1'); // GVx => -128 + (x-1)
|
||||
}
|
||||
|
||||
return (uint32_t)yaml_str2int(val, val_len);
|
||||
}
|
||||
|
||||
static bool in_write_weight(const YamlNode* node, uint32_t val, yaml_writer_func wf, void* opaque)
|
||||
{
|
||||
int32_t sval = yaml_to_signed(val,node->size);
|
||||
|
||||
if (sval > GVAR_SMALL-11 && sval < GVAR_SMALL-1) {
|
||||
char n = GVAR_SMALL - sval + '0';
|
||||
return wf(opaque, "-GV", 3) && wf(opaque, &n, 1);
|
||||
}
|
||||
else if (sval < -GVAR_SMALL+11 && sval > -GVAR_SMALL+1) {
|
||||
char n = val - GVAR_SMALL + '1';
|
||||
return wf(opaque, "GV", 2) && wf(opaque, &n, 1);
|
||||
}
|
||||
|
||||
char* s = yaml_signed2str(sval);
|
||||
return wf(opaque, s, strlen(s));
|
||||
}
|
||||
|
||||
extern const struct YamlIdStr enum_MixSources[];
|
||||
|
||||
static uint32_t r_mixSrcRaw(const YamlNode* node, const char* val, uint8_t val_len)
|
||||
{
|
||||
if (val_len > 0 && val[0] == 'I') {
|
||||
return yaml_str2uint(val+1, val_len-1) + MIXSRC_FIRST_INPUT;
|
||||
}
|
||||
|
||||
return yaml_parse_enum(enum_MixSources, val, val_len);
|
||||
}
|
||||
|
||||
static bool w_mixSrcRaw(const YamlNode* node, uint32_t val, yaml_writer_func wf, void* opaque)
|
||||
{
|
||||
const char* str = nullptr;
|
||||
|
||||
if (val >= MIXSRC_FIRST_INPUT
|
||||
&& val <= MIXSRC_LAST_INPUT) {
|
||||
|
||||
if (!wf(opaque, "I", 1))
|
||||
return false;
|
||||
|
||||
str = yaml_unsigned2str(val - MIXSRC_FIRST_INPUT);
|
||||
}
|
||||
else {
|
||||
str = yaml_output_enum(val, enum_MixSources);
|
||||
}
|
||||
|
||||
if (str) {
|
||||
return wf(opaque, str, strlen(str));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static uint32_t r_vbat_min(const YamlNode* node, const char* val, uint8_t val_len)
|
||||
{
|
||||
int32_t v = yaml_str2int(val, val_len);
|
||||
return (uint32_t)(v - 90);
|
||||
}
|
||||
|
||||
static bool w_vbat_min(const YamlNode* node, uint32_t val, yaml_writer_func wf, void* opaque)
|
||||
{
|
||||
char* s = yaml_signed2str(yaml_to_signed(val,node->size) + 90);
|
||||
return wf(opaque, s, strlen(s));
|
||||
}
|
||||
|
||||
static uint32_t r_vbat_max(const YamlNode* node, const char* val, uint8_t val_len)
|
||||
{
|
||||
int32_t v = yaml_str2int(val, val_len);
|
||||
return (uint32_t)(v - 120);
|
||||
}
|
||||
|
||||
static bool w_vbat_max(const YamlNode* node, uint32_t val, yaml_writer_func wf, void* opaque)
|
||||
{
|
||||
char* s = yaml_signed2str(yaml_to_signed(val,node->size) + 120);
|
||||
return wf(opaque, s, strlen(s));
|
||||
}
|
||||
|
||||
static uint8_t select_zov(uint8_t* data, uint32_t bitoffs)
|
||||
{
|
||||
data += bitoffs >> 3UL;
|
||||
data -= sizeof(ZoneOptionValueEnum);
|
||||
ZoneOptionValueEnum* p_zovt = (ZoneOptionValueEnum*)data;
|
||||
return *p_zovt;
|
||||
}
|
||||
|
||||
static uint8_t select_mod_type(uint8_t* data, uint32_t bitoffs)
|
||||
{
|
||||
data += bitoffs >> 3UL;
|
||||
data -= offsetof(ModuleData, ppm);
|
||||
|
||||
switch(((ModuleData*)data)->type) {
|
||||
case MODULE_TYPE_NONE:
|
||||
case MODULE_TYPE_PPM:
|
||||
case MODULE_TYPE_DSM2:
|
||||
case MODULE_TYPE_CROSSFIRE:
|
||||
return 1;
|
||||
case MODULE_TYPE_MULTIMODULE:
|
||||
return 2;
|
||||
case MODULE_TYPE_XJT_PXX1:
|
||||
case MODULE_TYPE_R9M_PXX1:
|
||||
case MODULE_TYPE_R9M_LITE_PXX1:
|
||||
case MODULE_TYPE_R9M_LITE_PRO_PXX1:
|
||||
return 3;
|
||||
case MODULE_TYPE_SBUS:
|
||||
return 4;
|
||||
case MODULE_TYPE_ISRM_PXX2:
|
||||
case MODULE_TYPE_R9M_PXX2:
|
||||
case MODULE_TYPE_R9M_LITE_PXX2:
|
||||
case MODULE_TYPE_R9M_LITE_PRO_PXX2:
|
||||
case MODULE_TYPE_XJT_LITE_PXX2:
|
||||
return 5;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint8_t select_custom_fn(uint8_t* data, uint32_t bitoffs)
|
||||
{
|
||||
// always use 'all'
|
||||
return 1;
|
||||
}
|
||||
|
||||
static uint8_t select_script_input(uint8_t* data, uint32_t bitoffs)
|
||||
{
|
||||
// always use 'value'
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint8_t select_id1(uint8_t* data, uint32_t bitoffs)
|
||||
{
|
||||
// always use 'id'
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint8_t select_id2(uint8_t* data, uint32_t bitoffs)
|
||||
{
|
||||
// always use 'instance'
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint8_t select_sensor_cfg(uint8_t* data, uint32_t bitoffs)
|
||||
{
|
||||
// always use 'param'
|
||||
return 5;
|
||||
}
|
||||
|
||||
static uint32_t sw_read(const char* val, uint8_t val_len)
|
||||
{
|
||||
return yaml_parse_enum(enum_MixSources, val, val_len) - MIXSRC_FIRST_SWITCH;
|
||||
}
|
||||
|
||||
static bool sw_write(uint32_t idx, yaml_writer_func wf, void* opaque)
|
||||
{
|
||||
const char* str = yaml_output_enum(idx + MIXSRC_FIRST_SWITCH, enum_MixSources);
|
||||
return wf(opaque, str, strlen(str));
|
||||
}
|
||||
|
||||
static const struct YamlIdStr enum_SwitchConfig[] = {
|
||||
{ SWITCH_NONE, "none" },
|
||||
{ SWITCH_TOGGLE, "toggle" },
|
||||
{ SWITCH_2POS, "2pos" },
|
||||
{ SWITCH_3POS, "3pos" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
static const struct YamlNode struct_switchConfig[] = {
|
||||
YAML_IDX_CUST( "sw", sw_read, sw_write ),
|
||||
YAML_ENUM( "type", 2, enum_SwitchConfig),
|
||||
YAML_END
|
||||
};
|
||||
|
||||
static uint32_t pot_read(const char* val, uint8_t val_len)
|
||||
{
|
||||
return yaml_parse_enum(enum_MixSources, val, val_len) - MIXSRC_FIRST_POT;
|
||||
}
|
||||
|
||||
static bool pot_write(uint32_t idx, yaml_writer_func wf, void* opaque)
|
||||
{
|
||||
const char* str = yaml_output_enum(idx + MIXSRC_FIRST_POT, enum_MixSources);
|
||||
return wf(opaque, str, strlen(str));
|
||||
}
|
||||
|
||||
static const struct YamlIdStr enum_PotConfig[] = {
|
||||
{ POT_NONE, "none" },
|
||||
{ POT_WITH_DETENT, "with_detent" },
|
||||
{ POT_MULTIPOS_SWITCH, "multipos_switch" },
|
||||
{ POT_WITHOUT_DETENT, "without_detent" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
static const struct YamlNode struct_potConfig[] = {
|
||||
YAML_IDX_CUST( "pot", pot_read, pot_write ),
|
||||
YAML_ENUM( "type", 2, enum_PotConfig),
|
||||
YAML_END
|
||||
};
|
||||
|
||||
static uint32_t slider_read(const char* val, uint8_t val_len)
|
||||
{
|
||||
return yaml_parse_enum(enum_MixSources, val, val_len) - MIXSRC_FIRST_SLIDER;
|
||||
}
|
||||
|
||||
static bool slider_write(uint32_t idx, yaml_writer_func wf, void* opaque)
|
||||
{
|
||||
const char* str = yaml_output_enum(idx + MIXSRC_FIRST_SLIDER, enum_MixSources);
|
||||
return wf(opaque, str, strlen(str));
|
||||
}
|
||||
|
||||
static const struct YamlIdStr enum_SliderConfig[] = {
|
||||
{ SLIDER_NONE, "none" },
|
||||
{ SLIDER_WITH_DETENT, "with_detent" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
static const struct YamlNode struct_sliderConfig[] = {
|
||||
YAML_IDX_CUST( "sl", slider_read, slider_write ),
|
||||
YAML_ENUM( "type", 1, enum_SliderConfig),
|
||||
YAML_END
|
||||
};
|
||||
|
||||
extern const struct YamlIdStr enum_SwitchSources[];
|
||||
|
||||
static uint32_t r_swtchSrc(const YamlNode* node, const char* val, uint8_t val_len)
|
||||
{
|
||||
int32_t ival=0;
|
||||
bool neg = false;
|
||||
if (val_len > 0 && val[0] == '!') {
|
||||
neg = true;
|
||||
val++;
|
||||
val_len--;
|
||||
}
|
||||
|
||||
if (val_len > 3
|
||||
&& val[0] == '6'
|
||||
&& val[1] == 'P'
|
||||
&& (val[2] >= '0' && val[2] <= '9')
|
||||
&& (val[3] >= '0' && val[3] < (XPOTS_MULTIPOS_COUNT + '0'))) {
|
||||
|
||||
ival = (val[2] - '0') * XPOTS_MULTIPOS_COUNT + (val[3] - '0')
|
||||
+ SWSRC_FIRST_MULTIPOS_SWITCH;
|
||||
}
|
||||
else if (val_len >= 2
|
||||
&& val[0] == 'L'
|
||||
&& (val[1] >= '0' && val[1] <= '9')) {
|
||||
|
||||
ival = SWSRC_FIRST_LOGICAL_SWITCH + yaml_str2int(val+1, val_len-1) - 1;
|
||||
}
|
||||
//TODO: Flight modes ('FM[0-9]')
|
||||
//TODO: Sensors ('Sensor[0-9]')
|
||||
else {
|
||||
ival = yaml_parse_enum(enum_SwitchSources, val, val_len);
|
||||
}
|
||||
|
||||
return neg ? -ival : ival;
|
||||
}
|
||||
|
||||
static bool w_swtchSrc(const YamlNode* node, uint32_t val, yaml_writer_func wf, void* opaque)
|
||||
{
|
||||
int32_t sval = yaml_to_signed(val, node->size);
|
||||
if (sval < 0) {
|
||||
wf(opaque, "!", 1);
|
||||
sval = abs(sval);
|
||||
}
|
||||
|
||||
const char* str = NULL;
|
||||
if (sval >= SWSRC_FIRST_MULTIPOS_SWITCH
|
||||
&& sval <= SWSRC_LAST_MULTIPOS_SWITCH) {
|
||||
|
||||
wf(opaque, "6P", 2);
|
||||
|
||||
// pot #: start with 6P1
|
||||
sval -= SWSRC_FIRST_MULTIPOS_SWITCH;
|
||||
str = yaml_unsigned2str(sval / XPOTS_MULTIPOS_COUNT);
|
||||
wf(opaque,str, strlen(str));
|
||||
|
||||
// position
|
||||
str = yaml_unsigned2str(sval % XPOTS_MULTIPOS_COUNT);
|
||||
return wf(opaque,str, strlen(str));
|
||||
}
|
||||
else if (sval >= SWSRC_FIRST_LOGICAL_SWITCH
|
||||
&& sval <= SWSRC_LAST_LOGICAL_SWITCH) {
|
||||
|
||||
wf(opaque, "L", 1);
|
||||
str = yaml_unsigned2str(sval - SWSRC_FIRST_LOGICAL_SWITCH + 1);
|
||||
return wf(opaque,str, strlen(str));
|
||||
}
|
||||
else if (sval >= SWSRC_FIRST_FLIGHT_MODE
|
||||
&& sval <= SWSRC_LAST_FLIGHT_MODE) {
|
||||
|
||||
//TODO
|
||||
return true;
|
||||
}
|
||||
else if (sval >= SWSRC_FIRST_SENSOR
|
||||
&& sval <= SWSRC_LAST_SENSOR) {
|
||||
|
||||
//TODO
|
||||
return true;
|
||||
}
|
||||
|
||||
str = yaml_output_enum(sval, enum_SwitchSources);
|
||||
return wf(opaque, str, strlen(str));
|
||||
}
|
||||
|
||||
static bool cfn_is_active(uint8_t* data, uint32_t bitoffs)
|
||||
{
|
||||
data += bitoffs >> 3UL;
|
||||
return ((CustomFunctionData*)data)->swtch;
|
||||
}
|
||||
|
||||
static bool gvar_is_active(uint8_t* data, uint32_t bitoffs)
|
||||
{
|
||||
gvar_t* gvar = (gvar_t*)(data + (bitoffs>>3UL));
|
||||
return *gvar != GVAR_MAX+1;
|
||||
}
|
||||
|
||||
static bool fmd_is_active(uint8_t* data, uint32_t bitoffs)
|
||||
{
|
||||
uint32_t data_ofs = bitoffs >> 3UL;
|
||||
if (data_ofs == offsetof(ModelData, flightModeData)) {
|
||||
return !yaml_is_zero(data, bitoffs, sizeof(FlightModeData)*8);
|
||||
}
|
||||
|
||||
bool is_active = !yaml_is_zero(data, bitoffs,
|
||||
(sizeof(FlightModeData)
|
||||
- sizeof(FlightModeData::gvars))*8);
|
||||
|
||||
FlightModeData* fmd = (FlightModeData*)(data + data_ofs);
|
||||
for (uint8_t i=0; i<MAX_GVARS; i++) {
|
||||
is_active |= fmd->gvars[i] != GVAR_MAX+1;
|
||||
}
|
||||
|
||||
return is_active;
|
||||
}
|
770
radio/src/storage/yaml/yaml_datastructs_x10.cpp
Normal file
770
radio/src/storage/yaml/yaml_datastructs_x10.cpp
Normal file
|
@ -0,0 +1,770 @@
|
|||
// generated by generate_yaml.py
|
||||
|
||||
//
|
||||
// Enums first
|
||||
//
|
||||
|
||||
const struct YamlIdStr enum_Functions[] = {
|
||||
{ FUNC_OVERRIDE_CHANNEL, "OVERRIDE_CHANNEL" },
|
||||
{ FUNC_TRAINER, "TRAINER" },
|
||||
{ FUNC_INSTANT_TRIM, "INSTANT_TRIM" },
|
||||
{ FUNC_RESET, "RESET" },
|
||||
{ FUNC_SET_TIMER, "SET_TIMER" },
|
||||
{ FUNC_ADJUST_GVAR, "ADJUST_GVAR" },
|
||||
{ FUNC_VOLUME, "VOLUME" },
|
||||
{ FUNC_SET_FAILSAFE, "SET_FAILSAFE" },
|
||||
{ FUNC_RANGECHECK, "RANGECHECK" },
|
||||
{ FUNC_BIND, "BIND" },
|
||||
{ FUNC_FIRST_WITHOUT_ENABLE, "FIRST_WITHOUT_ENABLE" },
|
||||
{ FUNC_PLAY_SOUND, "PLAY_SOUND" },
|
||||
{ FUNC_PLAY_TRACK, "PLAY_TRACK" },
|
||||
{ FUNC_PLAY_VALUE, "PLAY_VALUE" },
|
||||
{ FUNC_RESERVE4, "RESERVE4" },
|
||||
{ FUNC_PLAY_SCRIPT, "PLAY_SCRIPT" },
|
||||
{ FUNC_RESERVE5, "RESERVE5" },
|
||||
{ FUNC_BACKGND_MUSIC, "BACKGND_MUSIC" },
|
||||
{ FUNC_BACKGND_MUSIC_PAUSE, "BACKGND_MUSIC_PAUSE" },
|
||||
{ FUNC_VARIO, "VARIO" },
|
||||
{ FUNC_HAPTIC, "HAPTIC" },
|
||||
{ FUNC_LOGS, "LOGS" },
|
||||
{ FUNC_BACKLIGHT, "BACKLIGHT" },
|
||||
{ FUNC_SCREENSHOT, "SCREENSHOT" },
|
||||
{ FUNC_MAX, "MAX" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
const struct YamlIdStr enum_ZoneOptionValueEnum[] = {
|
||||
{ ZOV_Unsigned, "Unsigned" },
|
||||
{ ZOV_Signed, "Signed" },
|
||||
{ ZOV_Bool, "Bool" },
|
||||
{ ZOV_String, "String" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
const struct YamlIdStr enum_MixSources[] = {
|
||||
{ MIXSRC_NONE, "NONE" },
|
||||
{ MIXSRC_Rud, "Rud" },
|
||||
{ MIXSRC_Ele, "Ele" },
|
||||
{ MIXSRC_Thr, "Thr" },
|
||||
{ MIXSRC_Ail, "Ail" },
|
||||
{ MIXSRC_S1, "S1" },
|
||||
{ MIXSRC_6POS, "6POS" },
|
||||
{ MIXSRC_S2, "S2" },
|
||||
{ MIXSRC_EXT1, "EXT1" },
|
||||
{ MIXSRC_EXT2, "EXT2" },
|
||||
{ MIXSRC_LS, "LS" },
|
||||
{ MIXSRC_RS, "RS" },
|
||||
{ MIXSRC_MOUSE1, "MOUSE1" },
|
||||
{ MIXSRC_MOUSE2, "MOUSE2" },
|
||||
{ MIXSRC_MAX, "MAX" },
|
||||
{ MIXSRC_CYC1, "CYC1" },
|
||||
{ MIXSRC_CYC2, "CYC2" },
|
||||
{ MIXSRC_CYC3, "CYC3" },
|
||||
{ MIXSRC_TrimRud, "TrimRud" },
|
||||
{ MIXSRC_TrimEle, "TrimEle" },
|
||||
{ MIXSRC_TrimThr, "TrimThr" },
|
||||
{ MIXSRC_TrimAil, "TrimAil" },
|
||||
{ MIXSRC_TrimT5, "TrimT5" },
|
||||
{ MIXSRC_TrimT6, "TrimT6" },
|
||||
{ MIXSRC_SA, "SA" },
|
||||
{ MIXSRC_SB, "SB" },
|
||||
{ MIXSRC_SC, "SC" },
|
||||
{ MIXSRC_SD, "SD" },
|
||||
{ MIXSRC_SE, "SE" },
|
||||
{ MIXSRC_SF, "SF" },
|
||||
{ MIXSRC_SG, "SG" },
|
||||
{ MIXSRC_SH, "SH" },
|
||||
{ MIXSRC_SI, "SI" },
|
||||
{ MIXSRC_SJ, "SJ" },
|
||||
{ MIXSRC_SW1, "SW1" },
|
||||
{ MIXSRC_CH1, "CH1" },
|
||||
{ MIXSRC_CH2, "CH2" },
|
||||
{ MIXSRC_CH3, "CH3" },
|
||||
{ MIXSRC_CH4, "CH4" },
|
||||
{ MIXSRC_CH5, "CH5" },
|
||||
{ MIXSRC_CH6, "CH6" },
|
||||
{ MIXSRC_CH7, "CH7" },
|
||||
{ MIXSRC_CH8, "CH8" },
|
||||
{ MIXSRC_CH9, "CH9" },
|
||||
{ MIXSRC_CH10, "CH10" },
|
||||
{ MIXSRC_CH11, "CH11" },
|
||||
{ MIXSRC_CH12, "CH12" },
|
||||
{ MIXSRC_CH13, "CH13" },
|
||||
{ MIXSRC_CH14, "CH14" },
|
||||
{ MIXSRC_CH15, "CH15" },
|
||||
{ MIXSRC_CH16, "CH16" },
|
||||
{ MIXSRC_GVAR1, "GVAR1" },
|
||||
{ MIXSRC_TX_VOLTAGE, "TX_VOLTAGE" },
|
||||
{ MIXSRC_TX_TIME, "TX_TIME" },
|
||||
{ MIXSRC_TIMER1, "TIMER1" },
|
||||
{ MIXSRC_TIMER2, "TIMER2" },
|
||||
{ MIXSRC_TIMER3, "TIMER3" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
const struct YamlIdStr enum_LogicalSwitchesFunctions[] = {
|
||||
{ LS_FUNC_NONE, "FUNC_NONE" },
|
||||
{ LS_FUNC_VEQUAL, "FUNC_VEQUAL" },
|
||||
{ LS_FUNC_VALMOSTEQUAL, "FUNC_VALMOSTEQUAL" },
|
||||
{ LS_FUNC_VPOS, "FUNC_VPOS" },
|
||||
{ LS_FUNC_VNEG, "FUNC_VNEG" },
|
||||
{ LS_FUNC_RANGE, "FUNC_RANGE" },
|
||||
{ LS_FUNC_APOS, "FUNC_APOS" },
|
||||
{ LS_FUNC_ANEG, "FUNC_ANEG" },
|
||||
{ LS_FUNC_AND, "FUNC_AND" },
|
||||
{ LS_FUNC_OR, "FUNC_OR" },
|
||||
{ LS_FUNC_XOR, "FUNC_XOR" },
|
||||
{ LS_FUNC_EDGE, "FUNC_EDGE" },
|
||||
{ LS_FUNC_EQUAL, "FUNC_EQUAL" },
|
||||
{ LS_FUNC_GREATER, "FUNC_GREATER" },
|
||||
{ LS_FUNC_LESS, "FUNC_LESS" },
|
||||
{ LS_FUNC_DIFFEGREATER, "FUNC_DIFFEGREATER" },
|
||||
{ LS_FUNC_ADIFFEGREATER, "FUNC_ADIFFEGREATER" },
|
||||
{ LS_FUNC_TIMER, "FUNC_TIMER" },
|
||||
{ LS_FUNC_STICKY, "FUNC_STICKY" },
|
||||
{ LS_FUNC_COUNT, "FUNC_COUNT" },
|
||||
{ LS_FUNC_MAX, "FUNC_MAX" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
const struct YamlIdStr enum_SwitchSources[] = {
|
||||
{ SWSRC_NONE, "NONE" },
|
||||
{ SWSRC_SA0, "SA0" },
|
||||
{ SWSRC_SA1, "SA1" },
|
||||
{ SWSRC_SA2, "SA2" },
|
||||
{ SWSRC_SB0, "SB0" },
|
||||
{ SWSRC_SB1, "SB1" },
|
||||
{ SWSRC_SB2, "SB2" },
|
||||
{ SWSRC_SC0, "SC0" },
|
||||
{ SWSRC_SC1, "SC1" },
|
||||
{ SWSRC_SC2, "SC2" },
|
||||
{ SWSRC_SD0, "SD0" },
|
||||
{ SWSRC_SD1, "SD1" },
|
||||
{ SWSRC_SD2, "SD2" },
|
||||
{ SWSRC_SE0, "SE0" },
|
||||
{ SWSRC_SE1, "SE1" },
|
||||
{ SWSRC_SE2, "SE2" },
|
||||
{ SWSRC_SF0, "SF0" },
|
||||
{ SWSRC_SF1, "SF1" },
|
||||
{ SWSRC_SF2, "SF2" },
|
||||
{ SWSRC_SG0, "SG0" },
|
||||
{ SWSRC_SG1, "SG1" },
|
||||
{ SWSRC_SG2, "SG2" },
|
||||
{ SWSRC_SH0, "SH0" },
|
||||
{ SWSRC_SH1, "SH1" },
|
||||
{ SWSRC_SH2, "SH2" },
|
||||
{ SWSRC_SI0, "SI0" },
|
||||
{ SWSRC_SI1, "SI1" },
|
||||
{ SWSRC_SI2, "SI2" },
|
||||
{ SWSRC_SJ0, "SJ0" },
|
||||
{ SWSRC_SJ1, "SJ1" },
|
||||
{ SWSRC_SJ2, "SJ2" },
|
||||
{ SWSRC_TrimRudLeft, "TrimRudLeft" },
|
||||
{ SWSRC_TrimRudRight, "TrimRudRight" },
|
||||
{ SWSRC_TrimEleDown, "TrimEleDown" },
|
||||
{ SWSRC_TrimEleUp, "TrimEleUp" },
|
||||
{ SWSRC_TrimThrDown, "TrimThrDown" },
|
||||
{ SWSRC_TrimThrUp, "TrimThrUp" },
|
||||
{ SWSRC_TrimAilLeft, "TrimAilLeft" },
|
||||
{ SWSRC_TrimAilRight, "TrimAilRight" },
|
||||
{ SWSRC_TrimT5Down, "TrimT5Down" },
|
||||
{ SWSRC_TrimT5Up, "TrimT5Up" },
|
||||
{ SWSRC_TrimT6Down, "TrimT6Down" },
|
||||
{ SWSRC_TrimT6Up, "TrimT6Up" },
|
||||
{ SWSRC_SW1, "SW1" },
|
||||
{ SWSRC_SW2, "SW2" },
|
||||
{ SWSRC_ON, "ON" },
|
||||
{ SWSRC_ONE, "ONE" },
|
||||
{ SWSRC_TELEMETRY_STREAMING, "TELEMETRY_STREAMING" },
|
||||
{ SWSRC_RADIO_ACTIVITY, "RADIO_ACTIVITY" },
|
||||
{ SWSRC_OFF, "OFF" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
const struct YamlIdStr enum_ModuleType[] = {
|
||||
{ MODULE_TYPE_NONE, "TYPE_NONE" },
|
||||
{ MODULE_TYPE_PPM, "TYPE_PPM" },
|
||||
{ MODULE_TYPE_XJT_PXX1, "TYPE_XJT_PXX1" },
|
||||
{ MODULE_TYPE_ISRM_PXX2, "TYPE_ISRM_PXX2" },
|
||||
{ MODULE_TYPE_DSM2, "TYPE_DSM2" },
|
||||
{ MODULE_TYPE_CROSSFIRE, "TYPE_CROSSFIRE" },
|
||||
{ MODULE_TYPE_MULTIMODULE, "TYPE_MULTIMODULE" },
|
||||
{ MODULE_TYPE_R9M_PXX1, "TYPE_R9M_PXX1" },
|
||||
{ MODULE_TYPE_R9M_PXX2, "TYPE_R9M_PXX2" },
|
||||
{ MODULE_TYPE_R9M_LITE_PXX1, "TYPE_R9M_LITE_PXX1" },
|
||||
{ MODULE_TYPE_R9M_LITE_PXX2, "TYPE_R9M_LITE_PXX2" },
|
||||
{ MODULE_TYPE_R9M_LITE_PRO_PXX1, "TYPE_R9M_LITE_PRO_PXX1" },
|
||||
{ MODULE_TYPE_R9M_LITE_PRO_PXX2, "TYPE_R9M_LITE_PRO_PXX2" },
|
||||
{ MODULE_TYPE_SBUS, "TYPE_SBUS" },
|
||||
{ MODULE_TYPE_XJT_LITE_PXX2, "TYPE_XJT_LITE_PXX2" },
|
||||
{ MODULE_TYPE_FLYSKY, "TYPE_FLYSKY" },
|
||||
{ MODULE_TYPE_COUNT, "TYPE_COUNT" },
|
||||
{ MODULE_TYPE_MAX, "TYPE_MAX" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
//
|
||||
// Structs last
|
||||
//
|
||||
|
||||
static const struct YamlNode struct_CalibData[] = {
|
||||
YAML_IDX,
|
||||
YAML_SIGNED( "mid", 16 ),
|
||||
YAML_SIGNED( "spanNeg", 16 ),
|
||||
YAML_SIGNED( "spanPos", 16 ),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_signed_16[] = {
|
||||
YAML_IDX,
|
||||
YAML_SIGNED( "val", 16 ),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_TrainerMix[] = {
|
||||
YAML_IDX,
|
||||
YAML_UNSIGNED( "srcChn", 6 ),
|
||||
YAML_UNSIGNED( "mode", 2 ),
|
||||
YAML_SIGNED( "studWeight", 8 ),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_TrainerData[] = {
|
||||
YAML_ARRAY("calib", 16, 4, struct_signed_16, NULL),
|
||||
YAML_ARRAY("mix", 16, 4, struct_TrainerMix, NULL),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_anonymous_1[] = {
|
||||
YAML_STRING("name", 6),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_anonymous_2[] = {
|
||||
YAML_SIGNED( "val", 16 ),
|
||||
YAML_UNSIGNED( "mode", 8 ),
|
||||
YAML_UNSIGNED( "param", 8 ),
|
||||
YAML_PADDING( 16 ),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_anonymous_3[] = {
|
||||
YAML_SIGNED( "val1", 32 ),
|
||||
YAML_PADDING( 16 ),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode union_anonymous_0_elmts[] = {
|
||||
YAML_STRUCT("play", 48, struct_anonymous_1, NULL),
|
||||
YAML_STRUCT("all", 48, struct_anonymous_2, NULL),
|
||||
YAML_STRUCT("clear", 48, struct_anonymous_3, NULL),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_CustomFunctionData[] = {
|
||||
YAML_IDX,
|
||||
YAML_SIGNED_CUST( "swtch", 9, r_swtchSrc, w_swtchSrc ),
|
||||
YAML_ENUM("func", 7, enum_Functions),
|
||||
YAML_UNION("fp", 48, union_anonymous_0_elmts, select_custom_fn),
|
||||
YAML_UNSIGNED( "active", 8 ),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_string_24[] = {
|
||||
YAML_IDX,
|
||||
YAML_STRING("val", 3),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode union_ZoneOptionValue_elmts[] = {
|
||||
YAML_UNSIGNED( "unsignedValue", 32 ),
|
||||
YAML_SIGNED( "signedValue", 32 ),
|
||||
YAML_UNSIGNED( "boolValue", 32 ),
|
||||
YAML_STRING("stringValue", 8),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_ZoneOptionValueTyped[] = {
|
||||
YAML_IDX,
|
||||
YAML_ENUM("type", 32, enum_ZoneOptionValueEnum),
|
||||
YAML_UNION("value", 64, union_ZoneOptionValue_elmts, select_zov),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_ThemeBase__PersistentData[] = {
|
||||
YAML_ARRAY("options", 96, 5, struct_ZoneOptionValueTyped, NULL),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_RadioData[] = {
|
||||
YAML_UNSIGNED( "version", 8 ),
|
||||
YAML_UNSIGNED( "variant", 16 ),
|
||||
YAML_ARRAY("calib", 48, 15, struct_CalibData, NULL),
|
||||
YAML_UNSIGNED( "chkSum", 16 ),
|
||||
YAML_UNSIGNED( "vBatWarn", 8 ),
|
||||
YAML_SIGNED( "txVoltageCalibration", 8 ),
|
||||
YAML_UNSIGNED( "backlightMode", 3 ),
|
||||
YAML_SIGNED( "antennaMode", 2 ),
|
||||
YAML_UNSIGNED( "disableRtcWarning", 1 ),
|
||||
YAML_PADDING( 2 ),
|
||||
YAML_STRUCT("trainer", 128, struct_TrainerData, NULL),
|
||||
YAML_UNSIGNED( "view", 8 ),
|
||||
YAML_PADDING( 2 ),
|
||||
YAML_UNSIGNED( "fai", 1 ),
|
||||
YAML_SIGNED( "beepMode", 2 ),
|
||||
YAML_UNSIGNED( "alarmsFlash", 1 ),
|
||||
YAML_UNSIGNED( "disableMemoryWarning", 1 ),
|
||||
YAML_UNSIGNED( "disableAlarmWarning", 1 ),
|
||||
YAML_UNSIGNED( "stickMode", 2 ),
|
||||
YAML_SIGNED( "timezone", 5 ),
|
||||
YAML_UNSIGNED( "adjustRTC", 1 ),
|
||||
YAML_UNSIGNED( "inactivityTimer", 8 ),
|
||||
YAML_UNSIGNED( "telemetryBaudrate", 3 ),
|
||||
YAML_UNSIGNED( "splashSpares", 3 ),
|
||||
YAML_SIGNED( "hapticMode", 2 ),
|
||||
YAML_SIGNED( "switchesDelay", 8 ),
|
||||
YAML_UNSIGNED( "lightAutoOff", 8 ),
|
||||
YAML_UNSIGNED( "templateSetup", 8 ),
|
||||
YAML_SIGNED( "PPM_Multiplier", 8 ),
|
||||
YAML_SIGNED( "hapticLength", 8 ),
|
||||
YAML_SIGNED( "beepLength", 3 ),
|
||||
YAML_SIGNED( "hapticStrength", 3 ),
|
||||
YAML_UNSIGNED( "gpsFormat", 1 ),
|
||||
YAML_UNSIGNED( "unexpectedShutdown", 1 ),
|
||||
YAML_UNSIGNED( "speakerPitch", 8 ),
|
||||
YAML_SIGNED( "speakerVolume", 8 ),
|
||||
YAML_SIGNED_CUST( "vBatMin", 8, r_vbat_min, w_vbat_min ),
|
||||
YAML_SIGNED_CUST( "vBatMax", 8, r_vbat_max, w_vbat_max ),
|
||||
YAML_UNSIGNED( "backlightBright", 8 ),
|
||||
YAML_UNSIGNED( "globalTimer", 32 ),
|
||||
YAML_UNSIGNED( "bluetoothBaudrate", 4 ),
|
||||
YAML_UNSIGNED( "bluetoothMode", 4 ),
|
||||
YAML_UNSIGNED( "countryCode", 2 ),
|
||||
YAML_SIGNED( "pwrOnSpeed", 3 ),
|
||||
YAML_SIGNED( "pwrOffSpeed", 3 ),
|
||||
YAML_UNSIGNED( "imperial", 1 ),
|
||||
YAML_UNSIGNED( "jitterFilter", 1 ),
|
||||
YAML_UNSIGNED( "disableRssiPoweroffAlarm", 1 ),
|
||||
YAML_UNSIGNED( "USBMode", 2 ),
|
||||
YAML_UNSIGNED( "jackMode", 2 ),
|
||||
YAML_PADDING( 1 ),
|
||||
YAML_STRING("ttsLanguage", 2),
|
||||
YAML_SIGNED( "beepVolume", 4 ),
|
||||
YAML_SIGNED( "wavVolume", 4 ),
|
||||
YAML_SIGNED( "varioVolume", 4 ),
|
||||
YAML_SIGNED( "backgroundVolume", 4 ),
|
||||
YAML_SIGNED( "varioPitch", 8 ),
|
||||
YAML_SIGNED( "varioRange", 8 ),
|
||||
YAML_SIGNED( "varioRepeat", 8 ),
|
||||
YAML_ARRAY("customFn", 72, 64, struct_CustomFunctionData, cfn_is_active),
|
||||
YAML_UNSIGNED( "auxSerialMode", 8 ),
|
||||
YAML_ARRAY("switchConfig", 2, 16, struct_switchConfig, nullptr),
|
||||
YAML_ARRAY("potsConfig", 2, 8, struct_potConfig, nullptr),
|
||||
YAML_ARRAY("slidersConfig", 1, 8, struct_sliderConfig, nullptr),
|
||||
YAML_ARRAY("switchNames", 24, 10, struct_string_24, NULL),
|
||||
YAML_ARRAY("anaNames", 24, 13, struct_string_24, NULL),
|
||||
YAML_STRING("currModelFilename", 17),
|
||||
YAML_PADDING( 1 ),
|
||||
YAML_UNSIGNED( "blOffBright", 7 ),
|
||||
YAML_STRING("bluetoothName", 10),
|
||||
YAML_STRING("themeName", 8),
|
||||
YAML_STRUCT("themeData", 480, struct_ThemeBase__PersistentData, NULL),
|
||||
YAML_STRING("ownerRegistrationID", 8),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_unsigned_8[] = {
|
||||
YAML_IDX,
|
||||
YAML_UNSIGNED( "val", 8 ),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_ModelHeader[] = {
|
||||
YAML_STRING("name", 15),
|
||||
YAML_ARRAY("modelId", 8, 2, struct_unsigned_8, NULL),
|
||||
YAML_STRING("bitmap", 14),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_TimerData[] = {
|
||||
YAML_IDX,
|
||||
YAML_UNSIGNED( "start", 22 ),
|
||||
YAML_SIGNED( "swtch", 10 ),
|
||||
YAML_SIGNED( "value", 22 ),
|
||||
YAML_UNSIGNED( "mode", 3 ),
|
||||
YAML_UNSIGNED( "countdownBeep", 2 ),
|
||||
YAML_UNSIGNED( "minuteBeep", 1 ),
|
||||
YAML_UNSIGNED( "persistent", 2 ),
|
||||
YAML_SIGNED( "countdownStart", 2 ),
|
||||
YAML_STRING("name", 8),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_CurveRef[] = {
|
||||
YAML_UNSIGNED( "type", 8 ),
|
||||
YAML_SIGNED( "value", 8 ),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_MixData[] = {
|
||||
YAML_IDX,
|
||||
YAML_SIGNED_CUST( "weight", 11, in_read_weight, in_write_weight ),
|
||||
YAML_UNSIGNED( "destCh", 5 ),
|
||||
YAML_UNSIGNED_CUST( "srcRaw", 10, r_mixSrcRaw, w_mixSrcRaw ),
|
||||
YAML_UNSIGNED( "carryTrim", 1 ),
|
||||
YAML_UNSIGNED( "mixWarn", 2 ),
|
||||
YAML_UNSIGNED( "mltpx", 2 ),
|
||||
YAML_PADDING( 1 ),
|
||||
YAML_SIGNED( "offset", 14 ),
|
||||
YAML_SIGNED_CUST( "swtch", 9, r_swtchSrc, w_swtchSrc ),
|
||||
YAML_UNSIGNED( "flightModes", 9 ),
|
||||
YAML_STRUCT("curve", 16, struct_CurveRef, NULL),
|
||||
YAML_UNSIGNED( "delayUp", 8 ),
|
||||
YAML_UNSIGNED( "delayDown", 8 ),
|
||||
YAML_UNSIGNED( "speedUp", 8 ),
|
||||
YAML_UNSIGNED( "speedDown", 8 ),
|
||||
YAML_STRING("name", 6),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_LimitData[] = {
|
||||
YAML_IDX,
|
||||
YAML_SIGNED( "min", 11 ),
|
||||
YAML_SIGNED( "max", 11 ),
|
||||
YAML_SIGNED( "ppmCenter", 10 ),
|
||||
YAML_SIGNED( "offset", 11 ),
|
||||
YAML_UNSIGNED( "symetrical", 1 ),
|
||||
YAML_UNSIGNED( "revert", 1 ),
|
||||
YAML_PADDING( 3 ),
|
||||
YAML_SIGNED( "curve", 8 ),
|
||||
YAML_STRING("name", 6),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_ExpoData[] = {
|
||||
YAML_IDX,
|
||||
YAML_UNSIGNED( "mode", 2 ),
|
||||
YAML_UNSIGNED( "scale", 14 ),
|
||||
YAML_ENUM("srcRaw", 10, enum_MixSources),
|
||||
YAML_SIGNED( "carryTrim", 6 ),
|
||||
YAML_UNSIGNED( "chn", 5 ),
|
||||
YAML_SIGNED_CUST( "swtch", 9, r_swtchSrc, w_swtchSrc ),
|
||||
YAML_UNSIGNED( "flightModes", 9 ),
|
||||
YAML_SIGNED_CUST( "weight", 8, in_read_weight, in_write_weight ),
|
||||
YAML_PADDING( 1 ),
|
||||
YAML_STRING("name", 6),
|
||||
YAML_SIGNED( "offset", 8 ),
|
||||
YAML_STRUCT("curve", 16, struct_CurveRef, NULL),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_CurveHeader[] = {
|
||||
YAML_IDX,
|
||||
YAML_UNSIGNED( "type", 1 ),
|
||||
YAML_UNSIGNED( "smooth", 1 ),
|
||||
YAML_SIGNED( "points", 6 ),
|
||||
YAML_STRING("name", 3),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_signed_8[] = {
|
||||
YAML_IDX,
|
||||
YAML_SIGNED( "val", 8 ),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_LogicalSwitchData[] = {
|
||||
YAML_IDX,
|
||||
YAML_ENUM("func", 8, enum_LogicalSwitchesFunctions),
|
||||
YAML_SIGNED( "v1", 10 ),
|
||||
YAML_SIGNED( "v3", 10 ),
|
||||
YAML_SIGNED( "andsw", 9 ),
|
||||
YAML_UNSIGNED( "andswtype", 1 ),
|
||||
YAML_PADDING( 2 ),
|
||||
YAML_SIGNED( "v2", 16 ),
|
||||
YAML_UNSIGNED( "delay", 8 ),
|
||||
YAML_UNSIGNED( "duration", 8 ),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_SwashRingData[] = {
|
||||
YAML_UNSIGNED( "type", 8 ),
|
||||
YAML_UNSIGNED( "value", 8 ),
|
||||
YAML_UNSIGNED( "collectiveSource", 8 ),
|
||||
YAML_UNSIGNED( "aileronSource", 8 ),
|
||||
YAML_UNSIGNED( "elevatorSource", 8 ),
|
||||
YAML_SIGNED( "collectiveWeight", 8 ),
|
||||
YAML_SIGNED( "aileronWeight", 8 ),
|
||||
YAML_SIGNED( "elevatorWeight", 8 ),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_trim_t[] = {
|
||||
YAML_IDX,
|
||||
YAML_SIGNED( "value", 11 ),
|
||||
YAML_UNSIGNED( "mode", 5 ),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_FlightModeData[] = {
|
||||
YAML_IDX,
|
||||
YAML_ARRAY("trim", 16, 6, struct_trim_t, NULL),
|
||||
YAML_STRING("name", 10),
|
||||
YAML_SIGNED_CUST( "swtch", 9, r_swtchSrc, w_swtchSrc ),
|
||||
YAML_PADDING( 7 ),
|
||||
YAML_UNSIGNED( "fadeIn", 8 ),
|
||||
YAML_UNSIGNED( "fadeOut", 8 ),
|
||||
YAML_ARRAY("gvars", 16, 9, struct_signed_16, gvar_is_active),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_GVarData[] = {
|
||||
YAML_IDX,
|
||||
YAML_STRING("name", 3),
|
||||
YAML_UNSIGNED( "min", 12 ),
|
||||
YAML_UNSIGNED( "max", 12 ),
|
||||
YAML_UNSIGNED( "popup", 1 ),
|
||||
YAML_UNSIGNED( "prec", 1 ),
|
||||
YAML_UNSIGNED( "unit", 2 ),
|
||||
YAML_PADDING( 4 ),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_VarioData[] = {
|
||||
YAML_UNSIGNED( "source", 7 ),
|
||||
YAML_UNSIGNED( "centerSilent", 1 ),
|
||||
YAML_SIGNED( "centerMax", 8 ),
|
||||
YAML_SIGNED( "centerMin", 8 ),
|
||||
YAML_SIGNED( "min", 8 ),
|
||||
YAML_SIGNED( "max", 8 ),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_RssiAlarmData[] = {
|
||||
YAML_SIGNED( "disabled", 1 ),
|
||||
YAML_PADDING( 1 ),
|
||||
YAML_SIGNED( "warning", 6 ),
|
||||
YAML_PADDING( 2 ),
|
||||
YAML_SIGNED( "critical", 6 ),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_anonymous_5[] = {
|
||||
YAML_SIGNED( "delay", 6 ),
|
||||
YAML_UNSIGNED( "pulsePol", 1 ),
|
||||
YAML_UNSIGNED( "outputType", 1 ),
|
||||
YAML_SIGNED( "frameLength", 8 ),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_anonymous_6[] = {
|
||||
YAML_UNSIGNED( "rfProtocolExtra", 2 ),
|
||||
YAML_PADDING( 3 ),
|
||||
YAML_UNSIGNED( "customProto", 1 ),
|
||||
YAML_UNSIGNED( "autoBindMode", 1 ),
|
||||
YAML_UNSIGNED( "lowPowerMode", 1 ),
|
||||
YAML_SIGNED( "optionValue", 8 ),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_anonymous_7[] = {
|
||||
YAML_UNSIGNED( "power", 2 ),
|
||||
YAML_PADDING( 2 ),
|
||||
YAML_UNSIGNED( "receiverTelemetryOff", 1 ),
|
||||
YAML_UNSIGNED( "receiverHigherChannels", 1 ),
|
||||
YAML_SIGNED( "antennaMode", 2 ),
|
||||
YAML_PADDING( 8 ),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_anonymous_8[] = {
|
||||
YAML_PADDING( 6 ),
|
||||
YAML_UNSIGNED( "noninverted", 1 ),
|
||||
YAML_PADDING( 1 ),
|
||||
YAML_SIGNED( "refreshRate", 8 ),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_string_64[] = {
|
||||
YAML_IDX,
|
||||
YAML_STRING("val", 8),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_anonymous_9[] = {
|
||||
YAML_UNSIGNED( "receivers", 8 ),
|
||||
YAML_ARRAY("receiverName", 64, 3, struct_string_64, NULL),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode union_anonymous_4_elmts[] = {
|
||||
YAML_ARRAY("raw", 8, 25, struct_unsigned_8, NULL),
|
||||
YAML_STRUCT("ppm", 16, struct_anonymous_5, NULL),
|
||||
YAML_STRUCT("multi", 16, struct_anonymous_6, NULL),
|
||||
YAML_STRUCT("pxx", 16, struct_anonymous_7, NULL),
|
||||
YAML_STRUCT("sbus", 16, struct_anonymous_8, NULL),
|
||||
YAML_STRUCT("pxx2", 200, struct_anonymous_9, NULL),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_ModuleData[] = {
|
||||
YAML_IDX,
|
||||
YAML_ENUM("type", 4, enum_ModuleType),
|
||||
YAML_SIGNED( "rfProtocol", 4 ),
|
||||
YAML_UNSIGNED( "channelsStart", 8 ),
|
||||
YAML_SIGNED( "channelsCount", 8 ),
|
||||
YAML_UNSIGNED( "failsafeMode", 4 ),
|
||||
YAML_UNSIGNED( "subType", 3 ),
|
||||
YAML_UNSIGNED( "invertedSerial", 1 ),
|
||||
YAML_UNION("mod", 200, union_anonymous_4_elmts, select_mod_type),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_TrainerModuleData[] = {
|
||||
YAML_UNSIGNED( "mode", 3 ),
|
||||
YAML_PADDING( 5 ),
|
||||
YAML_UNSIGNED( "channelsStart", 8 ),
|
||||
YAML_SIGNED( "channelsCount", 8 ),
|
||||
YAML_SIGNED( "frameLength", 8 ),
|
||||
YAML_SIGNED( "delay", 6 ),
|
||||
YAML_UNSIGNED( "pulsePol", 1 ),
|
||||
YAML_PADDING( 1 ),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode union_ScriptDataInput_elmts[] = {
|
||||
YAML_SIGNED( "value", 16 ),
|
||||
YAML_UNSIGNED( "source", 16 ),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode union_ScriptDataInput[] = {
|
||||
YAML_IDX,
|
||||
YAML_UNION("u", 16, union_ScriptDataInput_elmts, select_script_input),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_ScriptData[] = {
|
||||
YAML_IDX,
|
||||
YAML_STRING("file", 6),
|
||||
YAML_STRING("name", 6),
|
||||
YAML_ARRAY("inputs", 16, 6, union_ScriptDataInput, NULL),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_string_32[] = {
|
||||
YAML_IDX,
|
||||
YAML_STRING("val", 4),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode union_anonymous_10_elmts[] = {
|
||||
YAML_UNSIGNED( "id", 16 ),
|
||||
YAML_UNSIGNED( "persistentValue", 16 ),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_anonymous_12[] = {
|
||||
YAML_UNSIGNED( "physID", 5 ),
|
||||
YAML_UNSIGNED( "rxIndex", 3 ),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode union_anonymous_11_elmts[] = {
|
||||
YAML_STRUCT("frskyInstance", 8, struct_anonymous_12, NULL),
|
||||
YAML_UNSIGNED( "instance", 8 ),
|
||||
YAML_UNSIGNED( "formula", 8 ),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_anonymous_14[] = {
|
||||
YAML_UNSIGNED( "ratio", 16 ),
|
||||
YAML_SIGNED( "offset", 16 ),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_anonymous_15[] = {
|
||||
YAML_UNSIGNED( "source", 8 ),
|
||||
YAML_UNSIGNED( "index", 8 ),
|
||||
YAML_PADDING( 16 ),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_anonymous_16[] = {
|
||||
YAML_ARRAY("sources", 8, 4, struct_signed_8, NULL),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_anonymous_17[] = {
|
||||
YAML_UNSIGNED( "source", 8 ),
|
||||
YAML_PADDING( 24 ),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_anonymous_18[] = {
|
||||
YAML_UNSIGNED( "gps", 8 ),
|
||||
YAML_UNSIGNED( "alt", 8 ),
|
||||
YAML_PADDING( 16 ),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode union_anonymous_13_elmts[] = {
|
||||
YAML_STRUCT("custom", 32, struct_anonymous_14, NULL),
|
||||
YAML_STRUCT("cell", 32, struct_anonymous_15, NULL),
|
||||
YAML_STRUCT("calc", 32, struct_anonymous_16, NULL),
|
||||
YAML_STRUCT("consumption", 32, struct_anonymous_17, NULL),
|
||||
YAML_STRUCT("dist", 32, struct_anonymous_18, NULL),
|
||||
YAML_UNSIGNED( "param", 32 ),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_TelemetrySensor[] = {
|
||||
YAML_IDX,
|
||||
YAML_UNION("id1", 16, union_anonymous_10_elmts, select_id1),
|
||||
YAML_UNION("id2", 8, union_anonymous_11_elmts, select_id2),
|
||||
YAML_STRING("label", 4),
|
||||
YAML_UNSIGNED( "subId", 8 ),
|
||||
YAML_UNSIGNED( "type", 1 ),
|
||||
YAML_PADDING( 1 ),
|
||||
YAML_UNSIGNED( "unit", 6 ),
|
||||
YAML_UNSIGNED( "prec", 2 ),
|
||||
YAML_UNSIGNED( "autoOffset", 1 ),
|
||||
YAML_UNSIGNED( "filter", 1 ),
|
||||
YAML_UNSIGNED( "logs", 1 ),
|
||||
YAML_UNSIGNED( "persistent", 1 ),
|
||||
YAML_UNSIGNED( "onlyPositive", 1 ),
|
||||
YAML_PADDING( 1 ),
|
||||
YAML_UNION("cfg", 32, union_anonymous_13_elmts, select_sensor_cfg),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_Widget__PersistentData[] = {
|
||||
YAML_ARRAY("options", 96, 5, struct_ZoneOptionValueTyped, NULL),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_ZonePersistentData[] = {
|
||||
YAML_IDX,
|
||||
YAML_STRING("widgetName", 10),
|
||||
YAML_STRUCT("widgetData", 480, struct_Widget__PersistentData, NULL),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_Layout__PersistentData[] = {
|
||||
YAML_ARRAY("zones", 576, 10, struct_ZonePersistentData, NULL),
|
||||
YAML_ARRAY("options", 96, 10, struct_ZoneOptionValueTyped, NULL),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_CustomScreenData[] = {
|
||||
YAML_IDX,
|
||||
YAML_STRING("layoutName", 10),
|
||||
YAML_STRUCT("layoutData", 6720, struct_Layout__PersistentData, NULL),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_Topbar__PersistentData[] = {
|
||||
YAML_ARRAY("zones", 576, 4, struct_ZonePersistentData, NULL),
|
||||
YAML_ARRAY("options", 96, 1, struct_ZoneOptionValueTyped, NULL),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_ModelData[] = {
|
||||
YAML_STRUCT("header", 248, struct_ModelHeader, NULL),
|
||||
YAML_ARRAY("timers", 128, 3, struct_TimerData, NULL),
|
||||
YAML_UNSIGNED( "telemetryProtocol", 3 ),
|
||||
YAML_UNSIGNED( "thrTrim", 1 ),
|
||||
YAML_UNSIGNED( "noGlobalFunctions", 1 ),
|
||||
YAML_UNSIGNED( "displayTrims", 2 ),
|
||||
YAML_UNSIGNED( "ignoreSensorIds", 1 ),
|
||||
YAML_SIGNED( "trimInc", 3 ),
|
||||
YAML_UNSIGNED( "disableThrottleWarning", 1 ),
|
||||
YAML_UNSIGNED( "displayChecklist", 1 ),
|
||||
YAML_UNSIGNED( "extendedLimits", 1 ),
|
||||
YAML_UNSIGNED( "extendedTrims", 1 ),
|
||||
YAML_UNSIGNED( "throttleReversed", 1 ),
|
||||
YAML_UNSIGNED( "beepANACenter", 16 ),
|
||||
YAML_ARRAY("mixData", 160, 64, struct_MixData, NULL),
|
||||
YAML_ARRAY("limitData", 104, 32, struct_LimitData, NULL),
|
||||
YAML_ARRAY("expoData", 136, 64, struct_ExpoData, NULL),
|
||||
YAML_ARRAY("curves", 32, 32, struct_CurveHeader, NULL),
|
||||
YAML_ARRAY("points", 8, 512, struct_signed_8, NULL),
|
||||
YAML_ARRAY("logicalSw", 72, 64, struct_LogicalSwitchData, NULL),
|
||||
YAML_ARRAY("customFn", 72, 64, struct_CustomFunctionData, cfn_is_active),
|
||||
YAML_STRUCT("swashR", 64, struct_SwashRingData, NULL),
|
||||
YAML_ARRAY("flightModeData", 352, 9, struct_FlightModeData, fmd_is_active),
|
||||
YAML_UNSIGNED( "thrTraceSrc", 8 ),
|
||||
YAML_UNSIGNED( "switchWarningState", 32 ),
|
||||
YAML_ARRAY("gvars", 56, 9, struct_GVarData, NULL),
|
||||
YAML_STRUCT("varioData", 40, struct_VarioData, NULL),
|
||||
YAML_UNSIGNED( "rssiSource", 8 ),
|
||||
YAML_STRUCT("rssiAlarms", 16, struct_RssiAlarmData, NULL),
|
||||
YAML_PADDING( 6 ),
|
||||
YAML_UNSIGNED( "potsWarnMode", 2 ),
|
||||
YAML_ARRAY("moduleData", 232, 2, struct_ModuleData, NULL),
|
||||
YAML_ARRAY("failsafeChannels", 16, 32, struct_signed_16, NULL),
|
||||
YAML_STRUCT("trainerData", 40, struct_TrainerModuleData, NULL),
|
||||
YAML_ARRAY("scriptsData", 192, 9, struct_ScriptData, NULL),
|
||||
YAML_ARRAY("inputNames", 32, 32, struct_string_32, NULL),
|
||||
YAML_UNSIGNED( "potsWarnEnabled", 8 ),
|
||||
YAML_ARRAY("potsWarnPosition", 8, 9, struct_signed_8, NULL),
|
||||
YAML_ARRAY("telemetrySensors", 112, 60, struct_TelemetrySensor, NULL),
|
||||
YAML_ARRAY("screenData", 6800, 5, struct_CustomScreenData, NULL),
|
||||
YAML_STRUCT("topbarData", 2400, struct_Topbar__PersistentData, NULL),
|
||||
YAML_UNSIGNED( "view", 8 ),
|
||||
YAML_STRING("modelRegistrationID", 8),
|
||||
YAML_END
|
||||
};
|
||||
|
||||
#define MAX_RADIODATA_MODELDATA_STR_LEN 24
|
||||
|
||||
static const struct YamlNode __RadioData_root_node = YAML_ROOT( struct_RadioData );
|
||||
|
||||
const YamlNode* get_radiodata_nodes()
|
||||
{
|
||||
return &__RadioData_root_node;
|
||||
}
|
||||
static const struct YamlNode __ModelData_root_node = YAML_ROOT( struct_ModelData );
|
||||
|
||||
const YamlNode* get_modeldata_nodes()
|
||||
{
|
||||
return &__ModelData_root_node;
|
||||
}
|
||||
|
771
radio/src/storage/yaml/yaml_datastructs_x12s.cpp
Normal file
771
radio/src/storage/yaml/yaml_datastructs_x12s.cpp
Normal file
|
@ -0,0 +1,771 @@
|
|||
// generated by generate_yaml.py
|
||||
|
||||
//
|
||||
// Enums first
|
||||
//
|
||||
|
||||
const struct YamlIdStr enum_Functions[] = {
|
||||
{ FUNC_OVERRIDE_CHANNEL, "OVERRIDE_CHANNEL" },
|
||||
{ FUNC_TRAINER, "TRAINER" },
|
||||
{ FUNC_INSTANT_TRIM, "INSTANT_TRIM" },
|
||||
{ FUNC_RESET, "RESET" },
|
||||
{ FUNC_SET_TIMER, "SET_TIMER" },
|
||||
{ FUNC_ADJUST_GVAR, "ADJUST_GVAR" },
|
||||
{ FUNC_VOLUME, "VOLUME" },
|
||||
{ FUNC_SET_FAILSAFE, "SET_FAILSAFE" },
|
||||
{ FUNC_RANGECHECK, "RANGECHECK" },
|
||||
{ FUNC_BIND, "BIND" },
|
||||
{ FUNC_FIRST_WITHOUT_ENABLE, "FIRST_WITHOUT_ENABLE" },
|
||||
{ FUNC_PLAY_SOUND, "PLAY_SOUND" },
|
||||
{ FUNC_PLAY_TRACK, "PLAY_TRACK" },
|
||||
{ FUNC_PLAY_VALUE, "PLAY_VALUE" },
|
||||
{ FUNC_RESERVE4, "RESERVE4" },
|
||||
{ FUNC_PLAY_SCRIPT, "PLAY_SCRIPT" },
|
||||
{ FUNC_RESERVE5, "RESERVE5" },
|
||||
{ FUNC_BACKGND_MUSIC, "BACKGND_MUSIC" },
|
||||
{ FUNC_BACKGND_MUSIC_PAUSE, "BACKGND_MUSIC_PAUSE" },
|
||||
{ FUNC_VARIO, "VARIO" },
|
||||
{ FUNC_HAPTIC, "HAPTIC" },
|
||||
{ FUNC_LOGS, "LOGS" },
|
||||
{ FUNC_BACKLIGHT, "BACKLIGHT" },
|
||||
{ FUNC_SCREENSHOT, "SCREENSHOT" },
|
||||
{ FUNC_MAX, "MAX" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
const struct YamlIdStr enum_ZoneOptionValueEnum[] = {
|
||||
{ ZOV_Unsigned, "Unsigned" },
|
||||
{ ZOV_Signed, "Signed" },
|
||||
{ ZOV_Bool, "Bool" },
|
||||
{ ZOV_String, "String" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
const struct YamlIdStr enum_MixSources[] = {
|
||||
{ MIXSRC_NONE, "NONE" },
|
||||
{ MIXSRC_Rud, "Rud" },
|
||||
{ MIXSRC_Ele, "Ele" },
|
||||
{ MIXSRC_Thr, "Thr" },
|
||||
{ MIXSRC_Ail, "Ail" },
|
||||
{ MIXSRC_S1, "S1" },
|
||||
{ MIXSRC_6POS, "6POS" },
|
||||
{ MIXSRC_S2, "S2" },
|
||||
{ MIXSRC_S3, "S3" },
|
||||
{ MIXSRC_S4, "S4" },
|
||||
{ MIXSRC_LS, "LS" },
|
||||
{ MIXSRC_RS, "RS" },
|
||||
{ MIXSRC_MOUSE1, "MOUSE1" },
|
||||
{ MIXSRC_MOUSE2, "MOUSE2" },
|
||||
{ MIXSRC_MAX, "MAX" },
|
||||
{ MIXSRC_CYC1, "CYC1" },
|
||||
{ MIXSRC_CYC2, "CYC2" },
|
||||
{ MIXSRC_CYC3, "CYC3" },
|
||||
{ MIXSRC_TrimRud, "TrimRud" },
|
||||
{ MIXSRC_TrimEle, "TrimEle" },
|
||||
{ MIXSRC_TrimThr, "TrimThr" },
|
||||
{ MIXSRC_TrimAil, "TrimAil" },
|
||||
{ MIXSRC_TrimT5, "TrimT5" },
|
||||
{ MIXSRC_TrimT6, "TrimT6" },
|
||||
{ MIXSRC_SA, "SA" },
|
||||
{ MIXSRC_SB, "SB" },
|
||||
{ MIXSRC_SC, "SC" },
|
||||
{ MIXSRC_SD, "SD" },
|
||||
{ MIXSRC_SE, "SE" },
|
||||
{ MIXSRC_SF, "SF" },
|
||||
{ MIXSRC_SG, "SG" },
|
||||
{ MIXSRC_SH, "SH" },
|
||||
{ MIXSRC_SI, "SI" },
|
||||
{ MIXSRC_SJ, "SJ" },
|
||||
{ MIXSRC_SW1, "SW1" },
|
||||
{ MIXSRC_CH1, "CH1" },
|
||||
{ MIXSRC_CH2, "CH2" },
|
||||
{ MIXSRC_CH3, "CH3" },
|
||||
{ MIXSRC_CH4, "CH4" },
|
||||
{ MIXSRC_CH5, "CH5" },
|
||||
{ MIXSRC_CH6, "CH6" },
|
||||
{ MIXSRC_CH7, "CH7" },
|
||||
{ MIXSRC_CH8, "CH8" },
|
||||
{ MIXSRC_CH9, "CH9" },
|
||||
{ MIXSRC_CH10, "CH10" },
|
||||
{ MIXSRC_CH11, "CH11" },
|
||||
{ MIXSRC_CH12, "CH12" },
|
||||
{ MIXSRC_CH13, "CH13" },
|
||||
{ MIXSRC_CH14, "CH14" },
|
||||
{ MIXSRC_CH15, "CH15" },
|
||||
{ MIXSRC_CH16, "CH16" },
|
||||
{ MIXSRC_GVAR1, "GVAR1" },
|
||||
{ MIXSRC_TX_VOLTAGE, "TX_VOLTAGE" },
|
||||
{ MIXSRC_TX_TIME, "TX_TIME" },
|
||||
{ MIXSRC_TX_GPS, "TX_GPS" },
|
||||
{ MIXSRC_TIMER1, "TIMER1" },
|
||||
{ MIXSRC_TIMER2, "TIMER2" },
|
||||
{ MIXSRC_TIMER3, "TIMER3" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
const struct YamlIdStr enum_LogicalSwitchesFunctions[] = {
|
||||
{ LS_FUNC_NONE, "FUNC_NONE" },
|
||||
{ LS_FUNC_VEQUAL, "FUNC_VEQUAL" },
|
||||
{ LS_FUNC_VALMOSTEQUAL, "FUNC_VALMOSTEQUAL" },
|
||||
{ LS_FUNC_VPOS, "FUNC_VPOS" },
|
||||
{ LS_FUNC_VNEG, "FUNC_VNEG" },
|
||||
{ LS_FUNC_RANGE, "FUNC_RANGE" },
|
||||
{ LS_FUNC_APOS, "FUNC_APOS" },
|
||||
{ LS_FUNC_ANEG, "FUNC_ANEG" },
|
||||
{ LS_FUNC_AND, "FUNC_AND" },
|
||||
{ LS_FUNC_OR, "FUNC_OR" },
|
||||
{ LS_FUNC_XOR, "FUNC_XOR" },
|
||||
{ LS_FUNC_EDGE, "FUNC_EDGE" },
|
||||
{ LS_FUNC_EQUAL, "FUNC_EQUAL" },
|
||||
{ LS_FUNC_GREATER, "FUNC_GREATER" },
|
||||
{ LS_FUNC_LESS, "FUNC_LESS" },
|
||||
{ LS_FUNC_DIFFEGREATER, "FUNC_DIFFEGREATER" },
|
||||
{ LS_FUNC_ADIFFEGREATER, "FUNC_ADIFFEGREATER" },
|
||||
{ LS_FUNC_TIMER, "FUNC_TIMER" },
|
||||
{ LS_FUNC_STICKY, "FUNC_STICKY" },
|
||||
{ LS_FUNC_COUNT, "FUNC_COUNT" },
|
||||
{ LS_FUNC_MAX, "FUNC_MAX" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
const struct YamlIdStr enum_SwitchSources[] = {
|
||||
{ SWSRC_NONE, "NONE" },
|
||||
{ SWSRC_SA0, "SA0" },
|
||||
{ SWSRC_SA1, "SA1" },
|
||||
{ SWSRC_SA2, "SA2" },
|
||||
{ SWSRC_SB0, "SB0" },
|
||||
{ SWSRC_SB1, "SB1" },
|
||||
{ SWSRC_SB2, "SB2" },
|
||||
{ SWSRC_SC0, "SC0" },
|
||||
{ SWSRC_SC1, "SC1" },
|
||||
{ SWSRC_SC2, "SC2" },
|
||||
{ SWSRC_SD0, "SD0" },
|
||||
{ SWSRC_SD1, "SD1" },
|
||||
{ SWSRC_SD2, "SD2" },
|
||||
{ SWSRC_SE0, "SE0" },
|
||||
{ SWSRC_SE1, "SE1" },
|
||||
{ SWSRC_SE2, "SE2" },
|
||||
{ SWSRC_SF0, "SF0" },
|
||||
{ SWSRC_SF1, "SF1" },
|
||||
{ SWSRC_SF2, "SF2" },
|
||||
{ SWSRC_SG0, "SG0" },
|
||||
{ SWSRC_SG1, "SG1" },
|
||||
{ SWSRC_SG2, "SG2" },
|
||||
{ SWSRC_SH0, "SH0" },
|
||||
{ SWSRC_SH1, "SH1" },
|
||||
{ SWSRC_SH2, "SH2" },
|
||||
{ SWSRC_SI0, "SI0" },
|
||||
{ SWSRC_SI1, "SI1" },
|
||||
{ SWSRC_SI2, "SI2" },
|
||||
{ SWSRC_SJ0, "SJ0" },
|
||||
{ SWSRC_SJ1, "SJ1" },
|
||||
{ SWSRC_SJ2, "SJ2" },
|
||||
{ SWSRC_TrimRudLeft, "TrimRudLeft" },
|
||||
{ SWSRC_TrimRudRight, "TrimRudRight" },
|
||||
{ SWSRC_TrimEleDown, "TrimEleDown" },
|
||||
{ SWSRC_TrimEleUp, "TrimEleUp" },
|
||||
{ SWSRC_TrimThrDown, "TrimThrDown" },
|
||||
{ SWSRC_TrimThrUp, "TrimThrUp" },
|
||||
{ SWSRC_TrimAilLeft, "TrimAilLeft" },
|
||||
{ SWSRC_TrimAilRight, "TrimAilRight" },
|
||||
{ SWSRC_TrimT5Down, "TrimT5Down" },
|
||||
{ SWSRC_TrimT5Up, "TrimT5Up" },
|
||||
{ SWSRC_TrimT6Down, "TrimT6Down" },
|
||||
{ SWSRC_TrimT6Up, "TrimT6Up" },
|
||||
{ SWSRC_SW1, "SW1" },
|
||||
{ SWSRC_SW2, "SW2" },
|
||||
{ SWSRC_ON, "ON" },
|
||||
{ SWSRC_ONE, "ONE" },
|
||||
{ SWSRC_TELEMETRY_STREAMING, "TELEMETRY_STREAMING" },
|
||||
{ SWSRC_RADIO_ACTIVITY, "RADIO_ACTIVITY" },
|
||||
{ SWSRC_OFF, "OFF" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
const struct YamlIdStr enum_ModuleType[] = {
|
||||
{ MODULE_TYPE_NONE, "TYPE_NONE" },
|
||||
{ MODULE_TYPE_PPM, "TYPE_PPM" },
|
||||
{ MODULE_TYPE_XJT_PXX1, "TYPE_XJT_PXX1" },
|
||||
{ MODULE_TYPE_ISRM_PXX2, "TYPE_ISRM_PXX2" },
|
||||
{ MODULE_TYPE_DSM2, "TYPE_DSM2" },
|
||||
{ MODULE_TYPE_CROSSFIRE, "TYPE_CROSSFIRE" },
|
||||
{ MODULE_TYPE_MULTIMODULE, "TYPE_MULTIMODULE" },
|
||||
{ MODULE_TYPE_R9M_PXX1, "TYPE_R9M_PXX1" },
|
||||
{ MODULE_TYPE_R9M_PXX2, "TYPE_R9M_PXX2" },
|
||||
{ MODULE_TYPE_R9M_LITE_PXX1, "TYPE_R9M_LITE_PXX1" },
|
||||
{ MODULE_TYPE_R9M_LITE_PXX2, "TYPE_R9M_LITE_PXX2" },
|
||||
{ MODULE_TYPE_R9M_LITE_PRO_PXX1, "TYPE_R9M_LITE_PRO_PXX1" },
|
||||
{ MODULE_TYPE_R9M_LITE_PRO_PXX2, "TYPE_R9M_LITE_PRO_PXX2" },
|
||||
{ MODULE_TYPE_SBUS, "TYPE_SBUS" },
|
||||
{ MODULE_TYPE_XJT_LITE_PXX2, "TYPE_XJT_LITE_PXX2" },
|
||||
{ MODULE_TYPE_FLYSKY, "TYPE_FLYSKY" },
|
||||
{ MODULE_TYPE_COUNT, "TYPE_COUNT" },
|
||||
{ MODULE_TYPE_MAX, "TYPE_MAX" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
//
|
||||
// Structs last
|
||||
//
|
||||
|
||||
static const struct YamlNode struct_CalibData[] = {
|
||||
YAML_IDX,
|
||||
YAML_SIGNED( "mid", 16 ),
|
||||
YAML_SIGNED( "spanNeg", 16 ),
|
||||
YAML_SIGNED( "spanPos", 16 ),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_signed_16[] = {
|
||||
YAML_IDX,
|
||||
YAML_SIGNED( "val", 16 ),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_TrainerMix[] = {
|
||||
YAML_IDX,
|
||||
YAML_UNSIGNED( "srcChn", 6 ),
|
||||
YAML_UNSIGNED( "mode", 2 ),
|
||||
YAML_SIGNED( "studWeight", 8 ),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_TrainerData[] = {
|
||||
YAML_ARRAY("calib", 16, 4, struct_signed_16, NULL),
|
||||
YAML_ARRAY("mix", 16, 4, struct_TrainerMix, NULL),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_anonymous_1[] = {
|
||||
YAML_STRING("name", 6),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_anonymous_2[] = {
|
||||
YAML_SIGNED( "val", 16 ),
|
||||
YAML_UNSIGNED( "mode", 8 ),
|
||||
YAML_UNSIGNED( "param", 8 ),
|
||||
YAML_PADDING( 16 ),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_anonymous_3[] = {
|
||||
YAML_SIGNED( "val1", 32 ),
|
||||
YAML_PADDING( 16 ),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode union_anonymous_0_elmts[] = {
|
||||
YAML_STRUCT("play", 48, struct_anonymous_1, NULL),
|
||||
YAML_STRUCT("all", 48, struct_anonymous_2, NULL),
|
||||
YAML_STRUCT("clear", 48, struct_anonymous_3, NULL),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_CustomFunctionData[] = {
|
||||
YAML_IDX,
|
||||
YAML_SIGNED_CUST( "swtch", 9, r_swtchSrc, w_swtchSrc ),
|
||||
YAML_ENUM("func", 7, enum_Functions),
|
||||
YAML_UNION("fp", 48, union_anonymous_0_elmts, select_custom_fn),
|
||||
YAML_UNSIGNED( "active", 8 ),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_string_24[] = {
|
||||
YAML_IDX,
|
||||
YAML_STRING("val", 3),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode union_ZoneOptionValue_elmts[] = {
|
||||
YAML_UNSIGNED( "unsignedValue", 32 ),
|
||||
YAML_SIGNED( "signedValue", 32 ),
|
||||
YAML_UNSIGNED( "boolValue", 32 ),
|
||||
YAML_STRING("stringValue", 8),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_ZoneOptionValueTyped[] = {
|
||||
YAML_IDX,
|
||||
YAML_ENUM("type", 32, enum_ZoneOptionValueEnum),
|
||||
YAML_UNION("value", 64, union_ZoneOptionValue_elmts, select_zov),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_ThemeBase__PersistentData[] = {
|
||||
YAML_ARRAY("options", 96, 5, struct_ZoneOptionValueTyped, NULL),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_RadioData[] = {
|
||||
YAML_UNSIGNED( "version", 8 ),
|
||||
YAML_UNSIGNED( "variant", 16 ),
|
||||
YAML_ARRAY("calib", 48, 15, struct_CalibData, NULL),
|
||||
YAML_UNSIGNED( "chkSum", 16 ),
|
||||
YAML_UNSIGNED( "vBatWarn", 8 ),
|
||||
YAML_SIGNED( "txVoltageCalibration", 8 ),
|
||||
YAML_UNSIGNED( "backlightMode", 3 ),
|
||||
YAML_SIGNED( "antennaMode", 2 ),
|
||||
YAML_UNSIGNED( "disableRtcWarning", 1 ),
|
||||
YAML_PADDING( 2 ),
|
||||
YAML_STRUCT("trainer", 128, struct_TrainerData, NULL),
|
||||
YAML_UNSIGNED( "view", 8 ),
|
||||
YAML_PADDING( 2 ),
|
||||
YAML_UNSIGNED( "fai", 1 ),
|
||||
YAML_SIGNED( "beepMode", 2 ),
|
||||
YAML_UNSIGNED( "alarmsFlash", 1 ),
|
||||
YAML_UNSIGNED( "disableMemoryWarning", 1 ),
|
||||
YAML_UNSIGNED( "disableAlarmWarning", 1 ),
|
||||
YAML_UNSIGNED( "stickMode", 2 ),
|
||||
YAML_SIGNED( "timezone", 5 ),
|
||||
YAML_UNSIGNED( "adjustRTC", 1 ),
|
||||
YAML_UNSIGNED( "inactivityTimer", 8 ),
|
||||
YAML_UNSIGNED( "telemetryBaudrate", 3 ),
|
||||
YAML_UNSIGNED( "splashSpares", 3 ),
|
||||
YAML_SIGNED( "hapticMode", 2 ),
|
||||
YAML_SIGNED( "switchesDelay", 8 ),
|
||||
YAML_UNSIGNED( "lightAutoOff", 8 ),
|
||||
YAML_UNSIGNED( "templateSetup", 8 ),
|
||||
YAML_SIGNED( "PPM_Multiplier", 8 ),
|
||||
YAML_SIGNED( "hapticLength", 8 ),
|
||||
YAML_SIGNED( "beepLength", 3 ),
|
||||
YAML_SIGNED( "hapticStrength", 3 ),
|
||||
YAML_UNSIGNED( "gpsFormat", 1 ),
|
||||
YAML_UNSIGNED( "unexpectedShutdown", 1 ),
|
||||
YAML_UNSIGNED( "speakerPitch", 8 ),
|
||||
YAML_SIGNED( "speakerVolume", 8 ),
|
||||
YAML_SIGNED_CUST( "vBatMin", 8, r_vbat_min, w_vbat_min ),
|
||||
YAML_SIGNED_CUST( "vBatMax", 8, r_vbat_max, w_vbat_max ),
|
||||
YAML_UNSIGNED( "backlightBright", 8 ),
|
||||
YAML_UNSIGNED( "globalTimer", 32 ),
|
||||
YAML_UNSIGNED( "bluetoothBaudrate", 4 ),
|
||||
YAML_UNSIGNED( "bluetoothMode", 4 ),
|
||||
YAML_UNSIGNED( "countryCode", 2 ),
|
||||
YAML_SIGNED( "pwrOnSpeed", 3 ),
|
||||
YAML_SIGNED( "pwrOffSpeed", 3 ),
|
||||
YAML_UNSIGNED( "imperial", 1 ),
|
||||
YAML_UNSIGNED( "jitterFilter", 1 ),
|
||||
YAML_UNSIGNED( "disableRssiPoweroffAlarm", 1 ),
|
||||
YAML_UNSIGNED( "USBMode", 2 ),
|
||||
YAML_UNSIGNED( "jackMode", 2 ),
|
||||
YAML_PADDING( 1 ),
|
||||
YAML_STRING("ttsLanguage", 2),
|
||||
YAML_SIGNED( "beepVolume", 4 ),
|
||||
YAML_SIGNED( "wavVolume", 4 ),
|
||||
YAML_SIGNED( "varioVolume", 4 ),
|
||||
YAML_SIGNED( "backgroundVolume", 4 ),
|
||||
YAML_SIGNED( "varioPitch", 8 ),
|
||||
YAML_SIGNED( "varioRange", 8 ),
|
||||
YAML_SIGNED( "varioRepeat", 8 ),
|
||||
YAML_ARRAY("customFn", 72, 64, struct_CustomFunctionData, cfn_is_active),
|
||||
YAML_UNSIGNED( "auxSerialMode", 8 ),
|
||||
YAML_ARRAY("switchConfig", 2, 16, struct_switchConfig, nullptr),
|
||||
YAML_ARRAY("potsConfig", 2, 8, struct_potConfig, nullptr),
|
||||
YAML_ARRAY("slidersConfig", 1, 8, struct_sliderConfig, nullptr),
|
||||
YAML_ARRAY("switchNames", 24, 10, struct_string_24, NULL),
|
||||
YAML_ARRAY("anaNames", 24, 13, struct_string_24, NULL),
|
||||
YAML_STRING("currModelFilename", 17),
|
||||
YAML_PADDING( 1 ),
|
||||
YAML_UNSIGNED( "blOffBright", 7 ),
|
||||
YAML_STRING("bluetoothName", 10),
|
||||
YAML_STRING("themeName", 8),
|
||||
YAML_STRUCT("themeData", 480, struct_ThemeBase__PersistentData, NULL),
|
||||
YAML_STRING("ownerRegistrationID", 8),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_unsigned_8[] = {
|
||||
YAML_IDX,
|
||||
YAML_UNSIGNED( "val", 8 ),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_ModelHeader[] = {
|
||||
YAML_STRING("name", 15),
|
||||
YAML_ARRAY("modelId", 8, 2, struct_unsigned_8, NULL),
|
||||
YAML_STRING("bitmap", 14),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_TimerData[] = {
|
||||
YAML_IDX,
|
||||
YAML_UNSIGNED( "start", 22 ),
|
||||
YAML_SIGNED( "swtch", 10 ),
|
||||
YAML_SIGNED( "value", 22 ),
|
||||
YAML_UNSIGNED( "mode", 3 ),
|
||||
YAML_UNSIGNED( "countdownBeep", 2 ),
|
||||
YAML_UNSIGNED( "minuteBeep", 1 ),
|
||||
YAML_UNSIGNED( "persistent", 2 ),
|
||||
YAML_SIGNED( "countdownStart", 2 ),
|
||||
YAML_STRING("name", 8),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_CurveRef[] = {
|
||||
YAML_UNSIGNED( "type", 8 ),
|
||||
YAML_SIGNED( "value", 8 ),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_MixData[] = {
|
||||
YAML_IDX,
|
||||
YAML_SIGNED_CUST( "weight", 11, in_read_weight, in_write_weight ),
|
||||
YAML_UNSIGNED( "destCh", 5 ),
|
||||
YAML_UNSIGNED_CUST( "srcRaw", 10, r_mixSrcRaw, w_mixSrcRaw ),
|
||||
YAML_UNSIGNED( "carryTrim", 1 ),
|
||||
YAML_UNSIGNED( "mixWarn", 2 ),
|
||||
YAML_UNSIGNED( "mltpx", 2 ),
|
||||
YAML_PADDING( 1 ),
|
||||
YAML_SIGNED( "offset", 14 ),
|
||||
YAML_SIGNED_CUST( "swtch", 9, r_swtchSrc, w_swtchSrc ),
|
||||
YAML_UNSIGNED( "flightModes", 9 ),
|
||||
YAML_STRUCT("curve", 16, struct_CurveRef, NULL),
|
||||
YAML_UNSIGNED( "delayUp", 8 ),
|
||||
YAML_UNSIGNED( "delayDown", 8 ),
|
||||
YAML_UNSIGNED( "speedUp", 8 ),
|
||||
YAML_UNSIGNED( "speedDown", 8 ),
|
||||
YAML_STRING("name", 6),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_LimitData[] = {
|
||||
YAML_IDX,
|
||||
YAML_SIGNED( "min", 11 ),
|
||||
YAML_SIGNED( "max", 11 ),
|
||||
YAML_SIGNED( "ppmCenter", 10 ),
|
||||
YAML_SIGNED( "offset", 11 ),
|
||||
YAML_UNSIGNED( "symetrical", 1 ),
|
||||
YAML_UNSIGNED( "revert", 1 ),
|
||||
YAML_PADDING( 3 ),
|
||||
YAML_SIGNED( "curve", 8 ),
|
||||
YAML_STRING("name", 6),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_ExpoData[] = {
|
||||
YAML_IDX,
|
||||
YAML_UNSIGNED( "mode", 2 ),
|
||||
YAML_UNSIGNED( "scale", 14 ),
|
||||
YAML_ENUM("srcRaw", 10, enum_MixSources),
|
||||
YAML_SIGNED( "carryTrim", 6 ),
|
||||
YAML_UNSIGNED( "chn", 5 ),
|
||||
YAML_SIGNED_CUST( "swtch", 9, r_swtchSrc, w_swtchSrc ),
|
||||
YAML_UNSIGNED( "flightModes", 9 ),
|
||||
YAML_SIGNED_CUST( "weight", 8, in_read_weight, in_write_weight ),
|
||||
YAML_PADDING( 1 ),
|
||||
YAML_STRING("name", 6),
|
||||
YAML_SIGNED( "offset", 8 ),
|
||||
YAML_STRUCT("curve", 16, struct_CurveRef, NULL),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_CurveHeader[] = {
|
||||
YAML_IDX,
|
||||
YAML_UNSIGNED( "type", 1 ),
|
||||
YAML_UNSIGNED( "smooth", 1 ),
|
||||
YAML_SIGNED( "points", 6 ),
|
||||
YAML_STRING("name", 3),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_signed_8[] = {
|
||||
YAML_IDX,
|
||||
YAML_SIGNED( "val", 8 ),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_LogicalSwitchData[] = {
|
||||
YAML_IDX,
|
||||
YAML_ENUM("func", 8, enum_LogicalSwitchesFunctions),
|
||||
YAML_SIGNED( "v1", 10 ),
|
||||
YAML_SIGNED( "v3", 10 ),
|
||||
YAML_SIGNED( "andsw", 9 ),
|
||||
YAML_UNSIGNED( "andswtype", 1 ),
|
||||
YAML_PADDING( 2 ),
|
||||
YAML_SIGNED( "v2", 16 ),
|
||||
YAML_UNSIGNED( "delay", 8 ),
|
||||
YAML_UNSIGNED( "duration", 8 ),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_SwashRingData[] = {
|
||||
YAML_UNSIGNED( "type", 8 ),
|
||||
YAML_UNSIGNED( "value", 8 ),
|
||||
YAML_UNSIGNED( "collectiveSource", 8 ),
|
||||
YAML_UNSIGNED( "aileronSource", 8 ),
|
||||
YAML_UNSIGNED( "elevatorSource", 8 ),
|
||||
YAML_SIGNED( "collectiveWeight", 8 ),
|
||||
YAML_SIGNED( "aileronWeight", 8 ),
|
||||
YAML_SIGNED( "elevatorWeight", 8 ),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_trim_t[] = {
|
||||
YAML_IDX,
|
||||
YAML_SIGNED( "value", 11 ),
|
||||
YAML_UNSIGNED( "mode", 5 ),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_FlightModeData[] = {
|
||||
YAML_IDX,
|
||||
YAML_ARRAY("trim", 16, 6, struct_trim_t, NULL),
|
||||
YAML_STRING("name", 10),
|
||||
YAML_SIGNED_CUST( "swtch", 9, r_swtchSrc, w_swtchSrc ),
|
||||
YAML_PADDING( 7 ),
|
||||
YAML_UNSIGNED( "fadeIn", 8 ),
|
||||
YAML_UNSIGNED( "fadeOut", 8 ),
|
||||
YAML_ARRAY("gvars", 16, 9, struct_signed_16, gvar_is_active),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_GVarData[] = {
|
||||
YAML_IDX,
|
||||
YAML_STRING("name", 3),
|
||||
YAML_UNSIGNED( "min", 12 ),
|
||||
YAML_UNSIGNED( "max", 12 ),
|
||||
YAML_UNSIGNED( "popup", 1 ),
|
||||
YAML_UNSIGNED( "prec", 1 ),
|
||||
YAML_UNSIGNED( "unit", 2 ),
|
||||
YAML_PADDING( 4 ),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_VarioData[] = {
|
||||
YAML_UNSIGNED( "source", 7 ),
|
||||
YAML_UNSIGNED( "centerSilent", 1 ),
|
||||
YAML_SIGNED( "centerMax", 8 ),
|
||||
YAML_SIGNED( "centerMin", 8 ),
|
||||
YAML_SIGNED( "min", 8 ),
|
||||
YAML_SIGNED( "max", 8 ),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_RssiAlarmData[] = {
|
||||
YAML_SIGNED( "disabled", 1 ),
|
||||
YAML_PADDING( 1 ),
|
||||
YAML_SIGNED( "warning", 6 ),
|
||||
YAML_PADDING( 2 ),
|
||||
YAML_SIGNED( "critical", 6 ),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_anonymous_5[] = {
|
||||
YAML_SIGNED( "delay", 6 ),
|
||||
YAML_UNSIGNED( "pulsePol", 1 ),
|
||||
YAML_UNSIGNED( "outputType", 1 ),
|
||||
YAML_SIGNED( "frameLength", 8 ),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_anonymous_6[] = {
|
||||
YAML_UNSIGNED( "rfProtocolExtra", 2 ),
|
||||
YAML_PADDING( 3 ),
|
||||
YAML_UNSIGNED( "customProto", 1 ),
|
||||
YAML_UNSIGNED( "autoBindMode", 1 ),
|
||||
YAML_UNSIGNED( "lowPowerMode", 1 ),
|
||||
YAML_SIGNED( "optionValue", 8 ),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_anonymous_7[] = {
|
||||
YAML_UNSIGNED( "power", 2 ),
|
||||
YAML_PADDING( 2 ),
|
||||
YAML_UNSIGNED( "receiverTelemetryOff", 1 ),
|
||||
YAML_UNSIGNED( "receiverHigherChannels", 1 ),
|
||||
YAML_SIGNED( "antennaMode", 2 ),
|
||||
YAML_PADDING( 8 ),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_anonymous_8[] = {
|
||||
YAML_PADDING( 6 ),
|
||||
YAML_UNSIGNED( "noninverted", 1 ),
|
||||
YAML_PADDING( 1 ),
|
||||
YAML_SIGNED( "refreshRate", 8 ),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_string_64[] = {
|
||||
YAML_IDX,
|
||||
YAML_STRING("val", 8),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_anonymous_9[] = {
|
||||
YAML_UNSIGNED( "receivers", 8 ),
|
||||
YAML_ARRAY("receiverName", 64, 3, struct_string_64, NULL),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode union_anonymous_4_elmts[] = {
|
||||
YAML_ARRAY("raw", 8, 25, struct_unsigned_8, NULL),
|
||||
YAML_STRUCT("ppm", 16, struct_anonymous_5, NULL),
|
||||
YAML_STRUCT("multi", 16, struct_anonymous_6, NULL),
|
||||
YAML_STRUCT("pxx", 16, struct_anonymous_7, NULL),
|
||||
YAML_STRUCT("sbus", 16, struct_anonymous_8, NULL),
|
||||
YAML_STRUCT("pxx2", 200, struct_anonymous_9, NULL),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_ModuleData[] = {
|
||||
YAML_IDX,
|
||||
YAML_ENUM("type", 4, enum_ModuleType),
|
||||
YAML_SIGNED( "rfProtocol", 4 ),
|
||||
YAML_UNSIGNED( "channelsStart", 8 ),
|
||||
YAML_SIGNED( "channelsCount", 8 ),
|
||||
YAML_UNSIGNED( "failsafeMode", 4 ),
|
||||
YAML_UNSIGNED( "subType", 3 ),
|
||||
YAML_UNSIGNED( "invertedSerial", 1 ),
|
||||
YAML_UNION("mod", 200, union_anonymous_4_elmts, select_mod_type),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_TrainerModuleData[] = {
|
||||
YAML_UNSIGNED( "mode", 3 ),
|
||||
YAML_PADDING( 5 ),
|
||||
YAML_UNSIGNED( "channelsStart", 8 ),
|
||||
YAML_SIGNED( "channelsCount", 8 ),
|
||||
YAML_SIGNED( "frameLength", 8 ),
|
||||
YAML_SIGNED( "delay", 6 ),
|
||||
YAML_UNSIGNED( "pulsePol", 1 ),
|
||||
YAML_PADDING( 1 ),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode union_ScriptDataInput_elmts[] = {
|
||||
YAML_SIGNED( "value", 16 ),
|
||||
YAML_UNSIGNED( "source", 16 ),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode union_ScriptDataInput[] = {
|
||||
YAML_IDX,
|
||||
YAML_UNION("u", 16, union_ScriptDataInput_elmts, select_script_input),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_ScriptData[] = {
|
||||
YAML_IDX,
|
||||
YAML_STRING("file", 6),
|
||||
YAML_STRING("name", 6),
|
||||
YAML_ARRAY("inputs", 16, 6, union_ScriptDataInput, NULL),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_string_32[] = {
|
||||
YAML_IDX,
|
||||
YAML_STRING("val", 4),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode union_anonymous_10_elmts[] = {
|
||||
YAML_UNSIGNED( "id", 16 ),
|
||||
YAML_UNSIGNED( "persistentValue", 16 ),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_anonymous_12[] = {
|
||||
YAML_UNSIGNED( "physID", 5 ),
|
||||
YAML_UNSIGNED( "rxIndex", 3 ),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode union_anonymous_11_elmts[] = {
|
||||
YAML_STRUCT("frskyInstance", 8, struct_anonymous_12, NULL),
|
||||
YAML_UNSIGNED( "instance", 8 ),
|
||||
YAML_UNSIGNED( "formula", 8 ),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_anonymous_14[] = {
|
||||
YAML_UNSIGNED( "ratio", 16 ),
|
||||
YAML_SIGNED( "offset", 16 ),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_anonymous_15[] = {
|
||||
YAML_UNSIGNED( "source", 8 ),
|
||||
YAML_UNSIGNED( "index", 8 ),
|
||||
YAML_PADDING( 16 ),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_anonymous_16[] = {
|
||||
YAML_ARRAY("sources", 8, 4, struct_signed_8, NULL),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_anonymous_17[] = {
|
||||
YAML_UNSIGNED( "source", 8 ),
|
||||
YAML_PADDING( 24 ),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_anonymous_18[] = {
|
||||
YAML_UNSIGNED( "gps", 8 ),
|
||||
YAML_UNSIGNED( "alt", 8 ),
|
||||
YAML_PADDING( 16 ),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode union_anonymous_13_elmts[] = {
|
||||
YAML_STRUCT("custom", 32, struct_anonymous_14, NULL),
|
||||
YAML_STRUCT("cell", 32, struct_anonymous_15, NULL),
|
||||
YAML_STRUCT("calc", 32, struct_anonymous_16, NULL),
|
||||
YAML_STRUCT("consumption", 32, struct_anonymous_17, NULL),
|
||||
YAML_STRUCT("dist", 32, struct_anonymous_18, NULL),
|
||||
YAML_UNSIGNED( "param", 32 ),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_TelemetrySensor[] = {
|
||||
YAML_IDX,
|
||||
YAML_UNION("id1", 16, union_anonymous_10_elmts, select_id1),
|
||||
YAML_UNION("id2", 8, union_anonymous_11_elmts, select_id2),
|
||||
YAML_STRING("label", 4),
|
||||
YAML_UNSIGNED( "subId", 8 ),
|
||||
YAML_UNSIGNED( "type", 1 ),
|
||||
YAML_PADDING( 1 ),
|
||||
YAML_UNSIGNED( "unit", 6 ),
|
||||
YAML_UNSIGNED( "prec", 2 ),
|
||||
YAML_UNSIGNED( "autoOffset", 1 ),
|
||||
YAML_UNSIGNED( "filter", 1 ),
|
||||
YAML_UNSIGNED( "logs", 1 ),
|
||||
YAML_UNSIGNED( "persistent", 1 ),
|
||||
YAML_UNSIGNED( "onlyPositive", 1 ),
|
||||
YAML_PADDING( 1 ),
|
||||
YAML_UNION("cfg", 32, union_anonymous_13_elmts, select_sensor_cfg),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_Widget__PersistentData[] = {
|
||||
YAML_ARRAY("options", 96, 5, struct_ZoneOptionValueTyped, NULL),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_ZonePersistentData[] = {
|
||||
YAML_IDX,
|
||||
YAML_STRING("widgetName", 10),
|
||||
YAML_STRUCT("widgetData", 480, struct_Widget__PersistentData, NULL),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_Layout__PersistentData[] = {
|
||||
YAML_ARRAY("zones", 576, 10, struct_ZonePersistentData, NULL),
|
||||
YAML_ARRAY("options", 96, 10, struct_ZoneOptionValueTyped, NULL),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_CustomScreenData[] = {
|
||||
YAML_IDX,
|
||||
YAML_STRING("layoutName", 10),
|
||||
YAML_STRUCT("layoutData", 6720, struct_Layout__PersistentData, NULL),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_Topbar__PersistentData[] = {
|
||||
YAML_ARRAY("zones", 576, 4, struct_ZonePersistentData, NULL),
|
||||
YAML_ARRAY("options", 96, 1, struct_ZoneOptionValueTyped, NULL),
|
||||
YAML_END
|
||||
};
|
||||
static const struct YamlNode struct_ModelData[] = {
|
||||
YAML_STRUCT("header", 248, struct_ModelHeader, NULL),
|
||||
YAML_ARRAY("timers", 128, 3, struct_TimerData, NULL),
|
||||
YAML_UNSIGNED( "telemetryProtocol", 3 ),
|
||||
YAML_UNSIGNED( "thrTrim", 1 ),
|
||||
YAML_UNSIGNED( "noGlobalFunctions", 1 ),
|
||||
YAML_UNSIGNED( "displayTrims", 2 ),
|
||||
YAML_UNSIGNED( "ignoreSensorIds", 1 ),
|
||||
YAML_SIGNED( "trimInc", 3 ),
|
||||
YAML_UNSIGNED( "disableThrottleWarning", 1 ),
|
||||
YAML_UNSIGNED( "displayChecklist", 1 ),
|
||||
YAML_UNSIGNED( "extendedLimits", 1 ),
|
||||
YAML_UNSIGNED( "extendedTrims", 1 ),
|
||||
YAML_UNSIGNED( "throttleReversed", 1 ),
|
||||
YAML_UNSIGNED( "beepANACenter", 16 ),
|
||||
YAML_ARRAY("mixData", 160, 64, struct_MixData, NULL),
|
||||
YAML_ARRAY("limitData", 104, 32, struct_LimitData, NULL),
|
||||
YAML_ARRAY("expoData", 136, 64, struct_ExpoData, NULL),
|
||||
YAML_ARRAY("curves", 32, 32, struct_CurveHeader, NULL),
|
||||
YAML_ARRAY("points", 8, 512, struct_signed_8, NULL),
|
||||
YAML_ARRAY("logicalSw", 72, 64, struct_LogicalSwitchData, NULL),
|
||||
YAML_ARRAY("customFn", 72, 64, struct_CustomFunctionData, cfn_is_active),
|
||||
YAML_STRUCT("swashR", 64, struct_SwashRingData, NULL),
|
||||
YAML_ARRAY("flightModeData", 352, 9, struct_FlightModeData, fmd_is_active),
|
||||
YAML_UNSIGNED( "thrTraceSrc", 8 ),
|
||||
YAML_UNSIGNED( "switchWarningState", 32 ),
|
||||
YAML_ARRAY("gvars", 56, 9, struct_GVarData, NULL),
|
||||
YAML_STRUCT("varioData", 40, struct_VarioData, NULL),
|
||||
YAML_UNSIGNED( "rssiSource", 8 ),
|
||||
YAML_STRUCT("rssiAlarms", 16, struct_RssiAlarmData, NULL),
|
||||
YAML_PADDING( 6 ),
|
||||
YAML_UNSIGNED( "potsWarnMode", 2 ),
|
||||
YAML_ARRAY("moduleData", 232, 2, struct_ModuleData, NULL),
|
||||
YAML_ARRAY("failsafeChannels", 16, 32, struct_signed_16, NULL),
|
||||
YAML_STRUCT("trainerData", 40, struct_TrainerModuleData, NULL),
|
||||
YAML_ARRAY("scriptsData", 192, 9, struct_ScriptData, NULL),
|
||||
YAML_ARRAY("inputNames", 32, 32, struct_string_32, NULL),
|
||||
YAML_UNSIGNED( "potsWarnEnabled", 8 ),
|
||||
YAML_ARRAY("potsWarnPosition", 8, 9, struct_signed_8, NULL),
|
||||
YAML_ARRAY("telemetrySensors", 112, 60, struct_TelemetrySensor, NULL),
|
||||
YAML_ARRAY("screenData", 6800, 5, struct_CustomScreenData, NULL),
|
||||
YAML_STRUCT("topbarData", 2400, struct_Topbar__PersistentData, NULL),
|
||||
YAML_UNSIGNED( "view", 8 ),
|
||||
YAML_STRING("modelRegistrationID", 8),
|
||||
YAML_END
|
||||
};
|
||||
|
||||
#define MAX_RADIODATA_MODELDATA_STR_LEN 24
|
||||
|
||||
static const struct YamlNode __RadioData_root_node = YAML_ROOT( struct_RadioData );
|
||||
|
||||
const YamlNode* get_radiodata_nodes()
|
||||
{
|
||||
return &__RadioData_root_node;
|
||||
}
|
||||
static const struct YamlNode __ModelData_root_node = YAML_ROOT( struct_ModelData );
|
||||
|
||||
const YamlNode* get_modeldata_nodes()
|
||||
{
|
||||
return &__ModelData_root_node;
|
||||
}
|
||||
|
37
radio/src/storage/yaml/yaml_defs.h
Normal file
37
radio/src/storage/yaml/yaml_defs.h
Normal file
|
@ -0,0 +1,37 @@
|
|||
#ifndef _YAML_DEFS_H_
|
||||
#define _YAML_DEFS_H_
|
||||
|
||||
#if defined(YAML_GENERATOR)
|
||||
|
||||
/* private definitions */
|
||||
#define _yaml_note(label) #label
|
||||
#define _yaml_attribute(attr) __attribute__((annotate(attr)))
|
||||
|
||||
/* public definitions */
|
||||
#define ENUM(label) _yaml_attribute("enum:" _yaml_note(label))
|
||||
#define SKIP _yaml_attribute("skip:true")
|
||||
#define USE_IDX _yaml_attribute("idx:true")
|
||||
#define FUNC(name) _yaml_attribute("func:" _yaml_note(name))
|
||||
#define NAME(label) _yaml_attribute("name:" _yaml_note(label))
|
||||
|
||||
#define CUST(read,write) \
|
||||
_yaml_attribute("read:" _yaml_note(read)) \
|
||||
_yaml_attribute("write:" _yaml_note(write))
|
||||
|
||||
#define ARRAY(elmt_size,elmt_type,fcn) \
|
||||
_yaml_attribute("array:" _yaml_note(elmt_size) "|" \
|
||||
_yaml_note(elmt_type) "|" _yaml_note(fcn))
|
||||
|
||||
#else
|
||||
|
||||
#define ENUM(label)
|
||||
#define SKIP
|
||||
#define USE_IDX
|
||||
#define FUNC(name)
|
||||
#define NAME(label)
|
||||
#define CUST(read,write)
|
||||
#define ARRAY(elmt_size,elmt_type,fcn)
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
136
radio/src/storage/yaml/yaml_modelslist.cpp
Normal file
136
radio/src/storage/yaml/yaml_modelslist.cpp
Normal file
|
@ -0,0 +1,136 @@
|
|||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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 "yaml_modelslist.h"
|
||||
#include "yaml_parser.h"
|
||||
|
||||
#include "storage/modelslist.h"
|
||||
|
||||
using std::list;
|
||||
|
||||
struct modelslist_iter
|
||||
{
|
||||
enum Level {
|
||||
Root=0,
|
||||
Category=1,
|
||||
Model=2
|
||||
};
|
||||
|
||||
ModelsList* root;
|
||||
uint8_t level;
|
||||
char current_attr[16]; // set after find_node()
|
||||
};
|
||||
|
||||
static modelslist_iter __modelslist_iter_inst;
|
||||
|
||||
void* get_modelslist_iter()
|
||||
{
|
||||
__modelslist_iter_inst.root = &modelslist;
|
||||
__modelslist_iter_inst.level = 0;
|
||||
return &__modelslist_iter_inst;
|
||||
}
|
||||
|
||||
static bool to_parent(void* ctx)
|
||||
{
|
||||
modelslist_iter* mi = (modelslist_iter*)ctx;
|
||||
if (mi->level == modelslist_iter::Root) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mi->level--;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool to_child(void* ctx)
|
||||
{
|
||||
modelslist_iter* mi = (modelslist_iter*)ctx;
|
||||
if (mi->level == modelslist_iter::Model) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mi->level++;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool to_next_elmt(void* ctx)
|
||||
{
|
||||
modelslist_iter* mi = (modelslist_iter*)ctx;
|
||||
if (mi->level == modelslist_iter::Root) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool find_node(void* ctx, char* buf, uint8_t len)
|
||||
{
|
||||
modelslist_iter* mi = (modelslist_iter*)ctx;
|
||||
|
||||
if (len > sizeof(modelslist_iter::current_attr)-1)
|
||||
len = sizeof(modelslist_iter::current_attr)-1;
|
||||
|
||||
memcpy(mi->current_attr, buf, len);
|
||||
mi->current_attr[len] = '\0';
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void set_attr(void* ctx, char* buf, uint8_t len)
|
||||
{
|
||||
modelslist_iter* mi = (modelslist_iter*)ctx;
|
||||
list<ModelsCategory *>& cats = mi->root->getCategories();
|
||||
switch(mi->level) {
|
||||
case modelslist_iter::Category: {
|
||||
ModelsCategory* cat = new ModelsCategory(buf,len);
|
||||
cats.push_back(cat);
|
||||
} break;
|
||||
|
||||
case modelslist_iter::Model:
|
||||
if (!strcmp(mi->current_attr,"filename")) {
|
||||
if (!cats.empty()) {
|
||||
ModelCell* model = new ModelCell(buf, len);
|
||||
cats.back()->push_back(model);
|
||||
mi->root->incModelsCount();
|
||||
}
|
||||
}
|
||||
else if (!strcmp(mi->current_attr,"name")) {
|
||||
if (!cats.empty()) {
|
||||
ModelsCategory* cat = cats.back();
|
||||
if (!cat->empty()) {
|
||||
ModelCell* model = cat->back();
|
||||
model->setModelName(buf,len);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static const YamlParserCalls modelslistCalls = {
|
||||
to_parent,
|
||||
to_child,
|
||||
to_next_elmt,
|
||||
find_node,
|
||||
set_attr
|
||||
};
|
||||
|
||||
const YamlParserCalls* get_modelslist_parser_calls()
|
||||
{
|
||||
return &modelslistCalls;
|
||||
}
|
29
radio/src/storage/yaml/yaml_modelslist.h
Normal file
29
radio/src/storage/yaml/yaml_modelslist.h
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef _YAML_MODELSLIST_H_
|
||||
#define _YAML_MODELSLIST_H_
|
||||
|
||||
struct YamlParserCalls;
|
||||
|
||||
void* get_modelslist_iter();
|
||||
const YamlParserCalls* get_modelslist_parser_calls();
|
||||
|
||||
#endif
|
174
radio/src/storage/yaml/yaml_node.h
Normal file
174
radio/src/storage/yaml/yaml_node.h
Normal file
|
@ -0,0 +1,174 @@
|
|||
#ifndef _node_h_
|
||||
#define _node_h_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include "yaml_parser.h"
|
||||
|
||||
#define NODE_STACK_DEPTH 12
|
||||
|
||||
enum YamlDataType {
|
||||
YDT_NONE=0,
|
||||
YDT_IDX,
|
||||
YDT_SIGNED,
|
||||
YDT_UNSIGNED,
|
||||
YDT_STRING,
|
||||
YDT_ARRAY,
|
||||
YDT_ENUM,
|
||||
YDT_UNION,
|
||||
YDT_PADDING
|
||||
};
|
||||
|
||||
struct YamlIdStr
|
||||
{
|
||||
int id;
|
||||
const char* str;
|
||||
};
|
||||
|
||||
// return false if error
|
||||
typedef bool (*yaml_writer_func)(void* opaque, const char* str, size_t len);
|
||||
|
||||
struct YamlNode
|
||||
{
|
||||
typedef bool (*is_active_func)(uint8_t* data, uint32_t bitoffs);
|
||||
|
||||
typedef uint32_t (*cust_to_uint_func)(const YamlNode* node, const char* val, uint8_t val_len);
|
||||
|
||||
typedef bool (*uint_to_cust_func)(const YamlNode* node, uint32_t val, yaml_writer_func wf, void* opaque);
|
||||
|
||||
typedef uint8_t (*select_member_func)(uint8_t* data, uint32_t bitoffs);
|
||||
|
||||
typedef uint32_t (*cust_idx_read_func)(const char* val, uint8_t val_len);
|
||||
typedef bool (*cust_idx_write_func)(uint32_t idx, yaml_writer_func wf, void* opaque);
|
||||
|
||||
uint8_t type;
|
||||
uint32_t size; // bits
|
||||
uint8_t tag_len;
|
||||
const char* tag;
|
||||
union {
|
||||
struct {
|
||||
const YamlNode* child;
|
||||
union {
|
||||
struct {
|
||||
is_active_func is_active;
|
||||
uint16_t elmts; // maximum number of elements
|
||||
} _a;
|
||||
select_member_func select_member;
|
||||
} u;
|
||||
} _array;
|
||||
|
||||
struct {
|
||||
const YamlIdStr* choices;
|
||||
} _enum;
|
||||
|
||||
struct {
|
||||
cust_to_uint_func cust_to_uint;
|
||||
uint_to_cust_func uint_to_cust;
|
||||
} _cust;
|
||||
|
||||
struct {
|
||||
cust_idx_read_func read;
|
||||
cust_idx_write_func write;
|
||||
} _cust_idx;
|
||||
} u;
|
||||
};
|
||||
|
||||
#if !defined(_MSC_VER)
|
||||
#define YAML_TAG(str) \
|
||||
.tag_len=(sizeof(str)-1), .tag=(str)
|
||||
|
||||
#define YAML_IDX \
|
||||
{ .type=YDT_IDX, .size=0, YAML_TAG("idx") }
|
||||
|
||||
#define YAML_IDX_CUST(tag, f_read, f_write) \
|
||||
{ .type=YDT_IDX, .size=0, YAML_TAG(tag), .u={._cust_idx={.read=(f_read), .write=(f_write) }} }
|
||||
|
||||
#define YAML_SIGNED(tag, bits) \
|
||||
{ .type=YDT_SIGNED, .size=(bits), YAML_TAG(tag) }
|
||||
|
||||
#define YAML_UNSIGNED(tag, bits) \
|
||||
{ .type=YDT_UNSIGNED, .size=(bits), YAML_TAG(tag) }
|
||||
|
||||
#define YAML_SIGNED_CUST(tag, bits, f_cust_to_uint, f_uint_to_cust) \
|
||||
{ .type=YDT_SIGNED, .size=(bits), YAML_TAG(tag), .u={._cust={ .cust_to_uint=f_cust_to_uint, .uint_to_cust=f_uint_to_cust }} }
|
||||
|
||||
#define YAML_UNSIGNED_CUST(tag, bits, f_cust_to_uint, f_uint_to_cust) \
|
||||
{ .type=YDT_UNSIGNED, .size=(bits), YAML_TAG(tag), .u={._cust={ .cust_to_uint=f_cust_to_uint, .uint_to_cust=f_uint_to_cust }} }
|
||||
|
||||
#define YAML_STRING(tag, max_len) \
|
||||
{ .type=YDT_STRING, .size=((max_len)<<3), YAML_TAG(tag) }
|
||||
|
||||
#define YAML_STRUCT(tag, bits, nodes, f_is_active) \
|
||||
{ .type=YDT_ARRAY, .size=(bits), YAML_TAG(tag), .u={._array={ .child=(nodes), .u={ ._a={.is_active=(f_is_active), .elmts=1 }}}} }
|
||||
|
||||
#define YAML_ARRAY(tag, bits, max_elmts, nodes, f_is_active) \
|
||||
{ .type=YDT_ARRAY, .size=(bits), YAML_TAG(tag), .u={._array={ .child=(nodes), .u={ ._a={.is_active=(f_is_active), .elmts=(max_elmts) }}}} }
|
||||
|
||||
#define YAML_ENUM(tag, bits, id_strs) \
|
||||
{ .type=YDT_ENUM, .size=(bits), YAML_TAG(tag), .u={._enum={ .choices=(id_strs) }} }
|
||||
|
||||
#define YAML_UNION(tag, bits, nodes, f_sel_m) \
|
||||
{ .type=YDT_UNION, .size=(bits), YAML_TAG(tag), .u={._array={ .child=(nodes), .u={.select_member=(f_sel_m) }}} }
|
||||
|
||||
#define YAML_PADDING(bits) \
|
||||
{ .type=YDT_PADDING, .size=(bits) }
|
||||
|
||||
#define YAML_END \
|
||||
{ .type=YDT_NONE }
|
||||
|
||||
#define YAML_ROOT(nodes) \
|
||||
{ .type=YDT_ARRAY, .size=0, .tag_len=0, .tag=NULL, \
|
||||
.u={ \
|
||||
._array={ .child=(nodes), \
|
||||
.u={._a={.is_active=NULL, .elmts=1 }} \
|
||||
}} \
|
||||
}
|
||||
|
||||
#else // MSVC++ compat
|
||||
|
||||
#define YAML_TAG(str) \
|
||||
(sizeof(str)-1), (str)
|
||||
|
||||
#define YAML_IDX \
|
||||
{ YDT_IDX , 0, YAML_TAG("idx") }
|
||||
|
||||
#define YAML_SIGNED(tag, bits) \
|
||||
{ YDT_SIGNED, (bits), YAML_TAG(tag) }
|
||||
|
||||
#define YAML_UNSIGNED(tag, bits) \
|
||||
{ YDT_UNSIGNED, (bits), YAML_TAG(tag) }
|
||||
|
||||
#define YAML_SIGNED_CUST(tag, bits, f_cust_to_uint, f_uint_to_cust) \
|
||||
{ YDT_SIGNED, (bits), YAML_TAG(tag), {{ (const YamlNode*)f_cust_to_uint, {{ (YamlNode::is_active_func)f_uint_to_cust, 0 }}}} }
|
||||
|
||||
#define YAML_UNSIGNED_CUST(tag, bits, f_cust_to_uint, f_uint_to_cust) \
|
||||
{ YDT_UNSIGNED, (bits), YAML_TAG(tag), {{ (const YamlNode*)f_cust_to_uint, {{ (YamlNode::is_active_func)f_uint_to_cust, 0}}}} }
|
||||
|
||||
#define YAML_STRING(tag, max_len) \
|
||||
{ YDT_STRING, ((max_len)<<3), YAML_TAG(tag) }
|
||||
|
||||
#define YAML_STRUCT(tag, bits, nodes, f_is_active) \
|
||||
{ YDT_ARRAY, (bits), YAML_TAG(tag), {{ (nodes), {{ (f_is_active), 1 }}}} }
|
||||
|
||||
#define YAML_ARRAY(tag, bits, max_elmts, nodes, f_is_active) \
|
||||
{ YDT_ARRAY, (bits), YAML_TAG(tag), {{ (nodes), {{ (f_is_active), (max_elmts) }}}} }
|
||||
|
||||
#define YAML_ENUM(tag, bits, id_strs) \
|
||||
{ YDT_ENUM, (bits), YAML_TAG(tag), {{ (const YamlNode*)(id_strs) }} }
|
||||
|
||||
#define YAML_UNION(tag, bits, nodes, f_sel_m) \
|
||||
{ YDT_UNION, (bits), YAML_TAG(tag), {{ (nodes), {{ (YamlNode::is_active_func)(f_sel_m), 0 }}}} }
|
||||
|
||||
#define YAML_PADDING(bits) \
|
||||
{ YDT_PADDING, (bits) }
|
||||
|
||||
#define YAML_END \
|
||||
{ YDT_NONE }
|
||||
|
||||
#define YAML_ROOT(nodes) \
|
||||
{ YDT_ARRAY, 0, 0, NULL, {{ (nodes), {{ NULL, 1 }}}} }
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
256
radio/src/storage/yaml/yaml_parser.cpp
Normal file
256
radio/src/storage/yaml/yaml_parser.cpp
Normal file
|
@ -0,0 +1,256 @@
|
|||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "yaml_parser.h"
|
||||
#include "debug.h"
|
||||
|
||||
YamlParser::YamlParser()
|
||||
{
|
||||
}
|
||||
|
||||
void YamlParser::init(const YamlParserCalls* parser_calls, void* parser_ctx)
|
||||
{
|
||||
indent = 0;
|
||||
level = 0;
|
||||
memset(indents, 0, sizeof(indents));
|
||||
|
||||
calls = parser_calls;
|
||||
ctx = parser_ctx;
|
||||
reset();
|
||||
}
|
||||
|
||||
void YamlParser::reset()
|
||||
{
|
||||
state = ps_Indent;
|
||||
indents[level] = indent;
|
||||
indent = scratch_len = 0;
|
||||
node_found = false;
|
||||
}
|
||||
|
||||
bool YamlParser::toChild()
|
||||
{
|
||||
bool ret = calls->to_child(ctx);
|
||||
if (ret) level++;
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool YamlParser::toParent()
|
||||
{
|
||||
if (!level)
|
||||
return false;
|
||||
|
||||
bool ret = calls->to_parent(ctx);
|
||||
if (ret) level--;
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint8_t YamlParser::getLastIndent()
|
||||
{
|
||||
return indents[level];
|
||||
}
|
||||
|
||||
YamlParser::YamlResult
|
||||
YamlParser::parse(const char* buffer, unsigned int size)
|
||||
{
|
||||
|
||||
#define CONCAT_STR(s,s_len,c) \
|
||||
{ \
|
||||
if(s_len < MAX_STR) \
|
||||
s[s_len++] = c; \
|
||||
else { \
|
||||
TRACE("STRING_OVERFLOW"); \
|
||||
return STRING_OVERFLOW; \
|
||||
} \
|
||||
}
|
||||
|
||||
const char* c = buffer;
|
||||
const char* end = c + size;
|
||||
|
||||
while(c < end) {
|
||||
|
||||
switch(state) {
|
||||
|
||||
case ps_Indent:
|
||||
if (*c == '-') {
|
||||
state = ps_Dash;
|
||||
++indent;
|
||||
break;
|
||||
}
|
||||
// trap
|
||||
case ps_Dash:
|
||||
if (*c == ' ') { // skip space(s), should be only one??
|
||||
++indent;
|
||||
break;
|
||||
}
|
||||
|
||||
if (indent < getLastIndent()) {
|
||||
// go up as many levels as necessary
|
||||
do {
|
||||
if (!toParent()) {
|
||||
TRACE("STOP (no parent)!\n");
|
||||
return DONE_PARSING;
|
||||
}
|
||||
} while (indent < getLastIndent());
|
||||
|
||||
if (state == ps_Dash) {
|
||||
if (!calls->to_next_elmt(ctx)) {
|
||||
return DONE_PARSING;
|
||||
}
|
||||
}
|
||||
}
|
||||
// go down one level
|
||||
else if (indent > getLastIndent()) {
|
||||
if (!toChild()) {
|
||||
TRACE("STOP (stack full)!\n");
|
||||
return DONE_PARSING; // ERROR
|
||||
}
|
||||
}
|
||||
// same level, next element
|
||||
else if (state == ps_Dash) {
|
||||
if (!calls->to_next_elmt(ctx)) {
|
||||
return DONE_PARSING;
|
||||
}
|
||||
}
|
||||
|
||||
state = ps_Attr;
|
||||
CONCAT_STR(scratch_buf, scratch_len, *c);
|
||||
break;
|
||||
|
||||
case ps_Attr:
|
||||
if (*c == ' ') {// assumes nothing else comes after spaces start
|
||||
node_found = calls->find_node(ctx, scratch_buf, scratch_len);
|
||||
if (!node_found) {
|
||||
TRACE("YAML_PARSER: Could not find node '%.*s' (1)\n",
|
||||
scratch_len, scratch_buf);
|
||||
}
|
||||
state = ps_AttrSP;
|
||||
break;
|
||||
}
|
||||
if (*c != ':')
|
||||
CONCAT_STR(scratch_buf, scratch_len, *c);
|
||||
// trap
|
||||
case ps_AttrSP:
|
||||
if (*c == '\r' || *c == '\n') {
|
||||
if (state == ps_Attr) {
|
||||
node_found = calls->find_node(ctx, scratch_buf, scratch_len);
|
||||
if (!node_found) {
|
||||
TRACE("YAML_PARSER: Could not find node '%.*s' (2)\n",
|
||||
scratch_len, scratch_buf);
|
||||
}
|
||||
}
|
||||
state = ps_CRLF;
|
||||
continue;
|
||||
}
|
||||
if (*c == ':') {
|
||||
if (state == ps_Attr) {
|
||||
node_found = calls->find_node(ctx, scratch_buf, scratch_len);
|
||||
if (!node_found) {
|
||||
TRACE("YAML_PARSER: Could not find node '%.*s' (3)\n",
|
||||
scratch_len, scratch_buf);
|
||||
}
|
||||
}
|
||||
state = ps_Sep;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case ps_Sep:
|
||||
if (*c == ' ')
|
||||
break;
|
||||
if (*c == '\r' || *c == '\n'){
|
||||
state = ps_CRLF;
|
||||
continue;
|
||||
}
|
||||
state = ps_Val;
|
||||
scratch_len = 0;
|
||||
if (*c == '\"') {
|
||||
state = ps_ValQuo;
|
||||
break;
|
||||
}
|
||||
CONCAT_STR(scratch_buf, scratch_len, *c);
|
||||
break;
|
||||
|
||||
case ps_ValQuo:
|
||||
if (*c == '\"') {
|
||||
state = ps_Val;
|
||||
break;
|
||||
}
|
||||
if (*c == '\\') {
|
||||
state = ps_ValEsc1;
|
||||
break;
|
||||
}
|
||||
CONCAT_STR(scratch_buf, scratch_len, *c);
|
||||
break;
|
||||
|
||||
case ps_ValEsc1:
|
||||
if (*c == 'x') {
|
||||
state = ps_ValEsc2;
|
||||
break;
|
||||
}
|
||||
//TODO: more escapes needed???
|
||||
TRACE("unknown escape char '%c'",*c);
|
||||
return DONE_PARSING;
|
||||
|
||||
case ps_ValEsc2:
|
||||
if(scratch_len >= MAX_STR) {
|
||||
TRACE("STRING_OVERFLOW");
|
||||
return STRING_OVERFLOW;
|
||||
}
|
||||
else if (*c >= '0' && *c <= '9') {
|
||||
scratch_buf[scratch_len] = (*c - '0') << 4;
|
||||
state = ps_ValEsc3;
|
||||
break;
|
||||
}
|
||||
else if (*c >= 'A' && *c <= 'F') {
|
||||
scratch_buf[scratch_len] = (*c - 'A' + 10) << 4;
|
||||
state = ps_ValEsc3;
|
||||
break;
|
||||
}
|
||||
TRACE("wrong hex digit '%c'",*c);
|
||||
return DONE_PARSING;
|
||||
|
||||
case ps_ValEsc3:
|
||||
if (*c >= '0' && *c <= '9') {
|
||||
scratch_buf[scratch_len++] |= (*c - '0');
|
||||
state = ps_ValQuo;
|
||||
break;
|
||||
}
|
||||
else if (*c >= 'A' && *c <= 'F') {
|
||||
scratch_buf[scratch_len++] |= (*c - 'A' + 10);
|
||||
state = ps_ValQuo;
|
||||
break;
|
||||
}
|
||||
TRACE("wrong hex digit '%c'",*c);
|
||||
return DONE_PARSING;
|
||||
|
||||
case ps_Val:
|
||||
if (*c == ' ' || *c == '\r' || *c == '\n') {
|
||||
// set attribute
|
||||
if (node_found) {
|
||||
calls->set_attr(ctx, scratch_buf, scratch_len);
|
||||
}
|
||||
state = ps_CRLF;
|
||||
continue;
|
||||
}
|
||||
if (*c == '\"') {
|
||||
state = ps_ValQuo;
|
||||
break;
|
||||
}
|
||||
CONCAT_STR(scratch_buf, scratch_len, *c);
|
||||
break;
|
||||
|
||||
case ps_CRLF:
|
||||
if (*c == '\n') {
|
||||
// reset state at EOL
|
||||
reset();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
c++;
|
||||
} // for each char
|
||||
|
||||
return CONTINUE_PARSING;
|
||||
}
|
||||
|
79
radio/src/storage/yaml/yaml_parser.h
Normal file
79
radio/src/storage/yaml/yaml_parser.h
Normal file
|
@ -0,0 +1,79 @@
|
|||
#ifndef _yaml_parser_h_
|
||||
#define _yaml_parser_h_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define MAX_STR 40
|
||||
#define MAX_DEPTH 16 // 12 real + 4 virtual
|
||||
|
||||
struct YamlParserCalls
|
||||
{
|
||||
bool (*to_parent) (void* ctx);
|
||||
bool (*to_child) (void* ctx);
|
||||
bool (*to_next_elmt) (void* ctx);
|
||||
bool (*find_node) (void* ctx, char* buf, uint8_t len);
|
||||
void (*set_attr) (void* ctx, char* buf, uint8_t len);
|
||||
};
|
||||
|
||||
class YamlParser
|
||||
{
|
||||
enum ParserState {
|
||||
ps_Indent=0,
|
||||
ps_Dash,
|
||||
ps_Attr,
|
||||
ps_AttrSP,
|
||||
ps_Sep,
|
||||
ps_Val,
|
||||
ps_ValQuo,
|
||||
ps_ValEsc1,
|
||||
ps_ValEsc2,
|
||||
ps_ValEsc3,
|
||||
ps_CRLF
|
||||
};
|
||||
|
||||
// last indents for each level
|
||||
uint8_t indents[MAX_DEPTH];
|
||||
|
||||
// current indent
|
||||
uint8_t indent;
|
||||
|
||||
// current level
|
||||
uint8_t level;
|
||||
|
||||
// parser state
|
||||
uint8_t state;
|
||||
|
||||
// scratch buffer w/ 16 bytes
|
||||
// used for attribute and values
|
||||
char scratch_buf[MAX_STR];
|
||||
uint8_t scratch_len;
|
||||
|
||||
bool node_found;
|
||||
|
||||
// tree iterator state
|
||||
const YamlParserCalls* calls;
|
||||
void* ctx;
|
||||
|
||||
// Reset parser state for next line
|
||||
void reset();
|
||||
|
||||
bool toChild();
|
||||
bool toParent();
|
||||
uint8_t getLastIndent();
|
||||
|
||||
public:
|
||||
|
||||
enum YamlResult {
|
||||
DONE_PARSING,
|
||||
CONTINUE_PARSING,
|
||||
STRING_OVERFLOW
|
||||
};
|
||||
|
||||
YamlParser();
|
||||
|
||||
void init(const YamlParserCalls* parser_calls, void* parser_ctx);
|
||||
|
||||
YamlResult parse(const char* buffer, unsigned int size);
|
||||
};
|
||||
|
||||
#endif
|
620
radio/src/storage/yaml/yaml_tree_walker.cpp
Normal file
620
radio/src/storage/yaml/yaml_tree_walker.cpp
Normal file
|
@ -0,0 +1,620 @@
|
|||
|
||||
#include "debug.h"
|
||||
#include "yaml_node.h"
|
||||
#include "yaml_bits.h"
|
||||
#include "yaml_tree_walker.h"
|
||||
#include "yaml_parser.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#define MIN(a,b) (a < b ? a : b)
|
||||
|
||||
static void copy_string(char* dst, const char* src, uint8_t len)
|
||||
{
|
||||
memcpy(dst,src,len);
|
||||
dst[len] = '\0';
|
||||
}
|
||||
|
||||
uint32_t yaml_parse_enum(const struct YamlIdStr* choices, const char* val, uint8_t val_len)
|
||||
{
|
||||
while (choices->str) {
|
||||
|
||||
// we have a match!
|
||||
if (!strncmp(val, choices->str, val_len))
|
||||
break;
|
||||
|
||||
choices++;
|
||||
}
|
||||
|
||||
return choices->id;
|
||||
}
|
||||
|
||||
static void yaml_set_attr(uint8_t* ptr, uint32_t bit_ofs, const YamlNode* node,
|
||||
const char* val, uint8_t val_len)
|
||||
{
|
||||
uint32_t i = 0;
|
||||
|
||||
//TRACE("set(%s, %.*s, bit-ofs=%u, bits=%u)\n",
|
||||
// node->tag, val_len, val, bit_ofs, node->size);
|
||||
|
||||
ptr += bit_ofs >> 3UL;
|
||||
bit_ofs &= 0x07;
|
||||
|
||||
if (node->type == YDT_STRING) {
|
||||
//assert(!bit_ofs);
|
||||
copy_string((char*)ptr, val, MIN(val_len, node->size - 1));
|
||||
return;
|
||||
}
|
||||
|
||||
switch(node->type) {
|
||||
case YDT_SIGNED:
|
||||
i = node->u._cust.cust_to_uint ? node->u._cust.cust_to_uint(node, val, val_len)
|
||||
: (uint32_t)yaml_str2int(val, val_len);
|
||||
break;
|
||||
case YDT_UNSIGNED:
|
||||
i = node->u._cust.cust_to_uint ? node->u._cust.cust_to_uint(node, val, val_len)
|
||||
: yaml_str2uint(val, val_len);
|
||||
break;
|
||||
case YDT_ENUM:
|
||||
i = yaml_parse_enum(node->u._enum.choices, val, val_len);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
yaml_put_bits(ptr, i, bit_ofs, node->size);
|
||||
}
|
||||
|
||||
const char* yaml_output_enum(int32_t i, const struct YamlIdStr* choices)
|
||||
{
|
||||
//TRACE("<choice = %d>", i);
|
||||
while(choices->str) {
|
||||
if (i == choices->id)
|
||||
break;
|
||||
choices++;
|
||||
}
|
||||
|
||||
return choices->str;
|
||||
}
|
||||
|
||||
static const char hex_digits[] {
|
||||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
|
||||
};
|
||||
|
||||
static bool yaml_output_string(const char* str, uint32_t max_len,
|
||||
yaml_writer_func wf, void* opaque)
|
||||
{
|
||||
if (!wf(opaque, "\"", 1))
|
||||
return false;
|
||||
|
||||
while(*str && max_len > 0) {
|
||||
if (*str >= 0x20 && *str <= 0x7E) {
|
||||
if (!wf(opaque, str++, 1)) return false;
|
||||
max_len--;
|
||||
}
|
||||
else {
|
||||
if (!wf(opaque, "\\x", 2)) return false;
|
||||
if (!wf(opaque, &(hex_digits[((uint8_t)*str) >> 4]), 1)) return false;
|
||||
if (!wf(opaque, &(hex_digits[((uint8_t)*str) & 0x0F]), 1)) return false;
|
||||
str++; max_len--;
|
||||
}
|
||||
}
|
||||
|
||||
if (!wf(opaque, "\"", 1))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool yaml_output_attr(uint8_t* ptr, uint32_t bit_ofs, const YamlNode* node,
|
||||
yaml_writer_func wf, void* opaque)
|
||||
{
|
||||
if (node->type == YDT_NONE)
|
||||
return false;
|
||||
|
||||
if (node->type == YDT_PADDING)
|
||||
return true;
|
||||
|
||||
// output tag
|
||||
if (!wf(opaque, node->tag, node->tag_len))
|
||||
return false;
|
||||
|
||||
if (!wf(opaque, ": ", 2))
|
||||
return false;
|
||||
|
||||
if (ptr) {
|
||||
|
||||
ptr += bit_ofs >> 3UL;
|
||||
bit_ofs &= 0x07;
|
||||
|
||||
const char* p_out = NULL;
|
||||
if (node->type == YDT_STRING) {
|
||||
//assert(!bit_ofs);
|
||||
if (!yaml_output_string((const char*)ptr, (node->size)>>3UL, wf, opaque))
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
unsigned int i = yaml_get_bits(ptr, bit_ofs, node->size);
|
||||
|
||||
if ((node->type == YDT_SIGNED || node->type == YDT_UNSIGNED)
|
||||
&& node->u._cust.uint_to_cust) {
|
||||
return node->u._cust.uint_to_cust(node, i, wf, opaque)
|
||||
&& wf(opaque, "\r\n", 2);
|
||||
}
|
||||
else {
|
||||
switch(node->type) {
|
||||
case YDT_SIGNED:
|
||||
p_out = yaml_signed2str((int)yaml_to_signed(i, node->size));
|
||||
break;
|
||||
case YDT_UNSIGNED:
|
||||
p_out = yaml_unsigned2str(i);
|
||||
break;
|
||||
case YDT_ENUM:
|
||||
p_out = yaml_output_enum(i, node->u._enum.choices);
|
||||
break;
|
||||
|
||||
case YDT_ARRAY:
|
||||
case YDT_UNION:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (p_out && !wf(opaque, p_out, strlen(p_out)))
|
||||
return false;
|
||||
}
|
||||
|
||||
return wf(opaque, "\r\n", 2);
|
||||
}
|
||||
|
||||
YamlTreeWalker::YamlTreeWalker()
|
||||
: stack_level(NODE_STACK_DEPTH),
|
||||
virt_level(0),
|
||||
anon_union(0)
|
||||
{
|
||||
memset(stack,0,sizeof(stack));
|
||||
}
|
||||
|
||||
void YamlTreeWalker::reset(const YamlNode* node, uint8_t* data)
|
||||
{
|
||||
this->data = data;
|
||||
stack_level = NODE_STACK_DEPTH;
|
||||
virt_level = 0;
|
||||
|
||||
push();
|
||||
setNode(node);
|
||||
rewind();
|
||||
}
|
||||
|
||||
bool YamlTreeWalker::push()
|
||||
{
|
||||
if (full())
|
||||
return false;
|
||||
|
||||
stack_level--;
|
||||
memset(&(stack[stack_level]), 0, sizeof(State));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool YamlTreeWalker::pop()
|
||||
{
|
||||
if (empty())
|
||||
return false;
|
||||
|
||||
memset(&(stack[stack_level]), 0, sizeof(State));
|
||||
stack_level++;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Rewind to the current node's first attribute
|
||||
// (and reset the bit offset)
|
||||
void YamlTreeWalker::rewind()
|
||||
{
|
||||
if (getNode()->type == YDT_ARRAY
|
||||
|| getNode()->type == YDT_UNION) {
|
||||
setAttrIdx(0);
|
||||
setAttrOfs(getLevelOfs());
|
||||
}
|
||||
}
|
||||
|
||||
// Increment the cursor until a match is found or the end of
|
||||
// the current collection (node of type YDT_NONE) is reached.
|
||||
//
|
||||
// return true if a match has been found.
|
||||
bool YamlTreeWalker::findNode(const char* tag, uint8_t tag_len)
|
||||
{
|
||||
if (virt_level)
|
||||
return false;
|
||||
|
||||
rewind();
|
||||
|
||||
const struct YamlNode* attr = getAttr();
|
||||
while(attr && attr->type != YDT_NONE) {
|
||||
|
||||
if ((tag_len == attr->tag_len)
|
||||
&& !strncmp(tag, attr->tag, tag_len)) {
|
||||
return true; // attribute found!
|
||||
}
|
||||
|
||||
toNextAttr();
|
||||
attr = getAttr();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get the current bit offset
|
||||
unsigned int YamlTreeWalker::getBitOffset()
|
||||
{
|
||||
return stack[stack_level].getOfs();
|
||||
}
|
||||
|
||||
bool YamlTreeWalker::toParent()
|
||||
{
|
||||
if(virt_level) {
|
||||
virt_level--;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!pop())
|
||||
return false;
|
||||
|
||||
return !empty();
|
||||
}
|
||||
|
||||
bool YamlTreeWalker::toChild()
|
||||
{
|
||||
const struct YamlNode* attr = getAttr();
|
||||
if (!attr
|
||||
|| (attr->type != YDT_ARRAY
|
||||
&& attr->type != YDT_UNION)) {
|
||||
virt_level++;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!push()) {
|
||||
virt_level++;
|
||||
return false;
|
||||
}
|
||||
|
||||
setNode(attr);
|
||||
setAttrOfs(getLevelOfs());
|
||||
|
||||
attr = getAttr();
|
||||
if ((attr->type == YDT_UNION) && (attr->tag_len == 0)) {
|
||||
toChild();
|
||||
anon_union++;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool YamlTreeWalker::toNextElmt()
|
||||
{
|
||||
const struct YamlNode* node = getNode();
|
||||
if (!virt_level && (node->type == YDT_ARRAY
|
||||
|| node->type == YDT_UNION)) {
|
||||
|
||||
if (node->type == YDT_UNION) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (getElmts() >= node->u._array.u._a.elmts - 1)
|
||||
return false;
|
||||
|
||||
incElmts();
|
||||
rewind();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool YamlTreeWalker::isElmtEmpty(uint8_t* data)
|
||||
{
|
||||
if (virt_level)
|
||||
return true;
|
||||
|
||||
if (!data)
|
||||
return false;
|
||||
|
||||
const struct YamlNode* node = getNode();
|
||||
uint32_t bit_ofs = 0;
|
||||
|
||||
if (node->type == YDT_ARRAY) {
|
||||
|
||||
bit_ofs = ((uint32_t)getElmts())
|
||||
* getNode()->size
|
||||
+ getLevelOfs();
|
||||
|
||||
// assume structs aligned on 8bit boundaries
|
||||
if (node->u._array.u._a.is_active)
|
||||
return !node->u._array.u._a.is_active(data, bit_ofs);
|
||||
|
||||
return yaml_is_zero(data, bit_ofs, node->size);
|
||||
}
|
||||
else if ((node->type == YDT_UNION) && hasParent()) {
|
||||
|
||||
bit_ofs = getLevelOfs();
|
||||
|
||||
TRACE("<not empty>");
|
||||
return false;//node->u._array.u.select_member; //TODO!
|
||||
// // assume structs aligned on 8bit boundaries
|
||||
// && !node->_array.is_active(data + (bit_ofs >> 3));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void YamlTreeWalker::toNextAttr()
|
||||
{
|
||||
const struct YamlNode* node = getNode();
|
||||
const struct YamlNode* attr = NULL;
|
||||
|
||||
if (node->type != YDT_UNION) {
|
||||
|
||||
attr = getAttr();
|
||||
uint32_t attr_bit_ofs = getAttrOfs();
|
||||
|
||||
if (attr->type == YDT_ARRAY)
|
||||
attr_bit_ofs += ((uint32_t)attr->u._array.u._a.elmts * attr->size);
|
||||
else
|
||||
attr_bit_ofs += attr->size;
|
||||
|
||||
setAttrOfs(attr_bit_ofs);
|
||||
}
|
||||
|
||||
incAttr();
|
||||
|
||||
// anonymous union handling
|
||||
attr = getAttr();
|
||||
if ((attr->type == YDT_UNION) && (attr->tag_len == 0)) {
|
||||
toChild();
|
||||
anon_union++;
|
||||
}
|
||||
else if ((attr->type == YDT_NONE)
|
||||
&& (getNode()->type == YDT_UNION)
|
||||
&& anon_union) {
|
||||
|
||||
anon_union--;
|
||||
toParent();
|
||||
toNextAttr();
|
||||
}
|
||||
}
|
||||
|
||||
void YamlTreeWalker::setAttrValue(char* buf, uint8_t len)
|
||||
{
|
||||
if (!buf || !len)
|
||||
return;
|
||||
|
||||
const YamlNode* attr = getAttr();
|
||||
if (attr->type == YDT_IDX) {
|
||||
|
||||
uint32_t i = 0;
|
||||
if (attr->u._cust_idx.read)
|
||||
i = attr->u._cust_idx.read(buf, len);
|
||||
else
|
||||
i = yaml_str2uint(buf, len);
|
||||
|
||||
while ((i > getElmts()) && toNextElmt());
|
||||
}
|
||||
else {
|
||||
yaml_set_attr(data, getBitOffset(), attr, buf, len);
|
||||
//walker.dump_stack();
|
||||
}
|
||||
}
|
||||
|
||||
bool YamlTreeWalker::generate(yaml_writer_func wf, void* opaque)
|
||||
{
|
||||
bool new_elmt = false;
|
||||
|
||||
while (true) {
|
||||
const struct YamlNode* attr = getAttr();
|
||||
|
||||
if (attr->type == YDT_PADDING) {
|
||||
toNextAttr();
|
||||
continue;
|
||||
}
|
||||
|
||||
// end of this level, go up or die
|
||||
if (attr->type == YDT_NONE) {
|
||||
|
||||
const struct YamlNode* node = getNode();
|
||||
if (node->type != YDT_ARRAY && node->type != YDT_UNION)
|
||||
return false; // Error in the structure (probably)
|
||||
|
||||
// if parent is a union, no need to output the other elements...
|
||||
const YamlNode* parent = getParent();
|
||||
if (parent && (parent->type == YDT_UNION)) {
|
||||
|
||||
if (!toParent())
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
// walk to next non-empty element
|
||||
while (toNextElmt()) {
|
||||
if (!isElmtEmpty(data)) {
|
||||
new_elmt = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (new_elmt)
|
||||
continue;
|
||||
}
|
||||
|
||||
// no next element, go up
|
||||
if (!toParent())
|
||||
return true;
|
||||
|
||||
toNextAttr();
|
||||
continue;
|
||||
}
|
||||
else if (attr->type == YDT_ARRAY || attr->type == YDT_UNION) {
|
||||
|
||||
if (!toChild())
|
||||
return false; // TODO: error handling???
|
||||
|
||||
const struct YamlNode* node = getNode();
|
||||
if (node->type == YDT_UNION && node->u._array.u.select_member) {
|
||||
|
||||
// output union tag, select member and go up one level
|
||||
|
||||
// output union tag
|
||||
for(int i=2; i < getLevel(); i++)
|
||||
if (!wf(opaque, " ", 3))
|
||||
return false;
|
||||
if (!yaml_output_attr(NULL, 0, node, wf, opaque))
|
||||
return false; // TODO: error handling???
|
||||
|
||||
// grab attr idx...
|
||||
uint8_t idx = node->u._array.u.select_member(data, getBitOffset());
|
||||
//TRACE("<idx = %d>", idx);
|
||||
setAttrIdx(idx);
|
||||
|
||||
attr = getAttr();
|
||||
for(int i=1; i < getLevel(); i++)
|
||||
if (!wf(opaque, " ", 3))
|
||||
return false;
|
||||
if (!yaml_output_attr(data, getBitOffset(), attr, wf, opaque))
|
||||
return false; // TODO: error handling???
|
||||
|
||||
if (attr->type != YDT_ARRAY
|
||||
&& attr->type != YDT_UNION) {
|
||||
|
||||
if (!toParent())
|
||||
return false;
|
||||
|
||||
toNextAttr();
|
||||
}
|
||||
else {
|
||||
if (!toChild() && !toParent())
|
||||
return false;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// walk to next non-empty element
|
||||
do {
|
||||
if (!isElmtEmpty(data)) {
|
||||
new_elmt = true;
|
||||
break;
|
||||
}
|
||||
new_elmt = false;
|
||||
} while (toNextElmt());
|
||||
|
||||
if (new_elmt) {
|
||||
// non-empty element present in a new structure/array
|
||||
// let's output the attribute
|
||||
for(int i=2; i < getLevel(); i++)
|
||||
if (!wf(opaque, " ", 3))
|
||||
return false;
|
||||
if (!yaml_output_attr(NULL, 0, getNode(), wf, opaque))
|
||||
return false; // TODO: error handling???
|
||||
continue;
|
||||
}
|
||||
|
||||
// no next element, go up
|
||||
if (!toParent())
|
||||
return true;
|
||||
|
||||
toNextAttr();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (new_elmt) {
|
||||
|
||||
for(int i=2; i < getLevel(); i++)
|
||||
if (!wf(opaque, " ", 3))
|
||||
return false;
|
||||
|
||||
if (!wf(opaque, " - ", 3))
|
||||
return false;
|
||||
|
||||
new_elmt = false;
|
||||
}
|
||||
else {
|
||||
for(int i=1; i < getLevel(); i++)
|
||||
if (!wf(opaque, " ", 3))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (attr->type == YDT_IDX) {
|
||||
|
||||
if (!wf(opaque, attr->tag, attr->tag_len))
|
||||
return false;
|
||||
|
||||
if (!wf(opaque, ": ", 2))
|
||||
return false;
|
||||
|
||||
if (attr->u._cust_idx.write) {
|
||||
if (!attr->u._cust_idx.write(getElmts(),wf,opaque))
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
char* idx = yaml_unsigned2str(getElmts());
|
||||
if (!wf(opaque, idx, strlen(idx)))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!wf(opaque, "\r\n", 2))
|
||||
return false;
|
||||
}
|
||||
else if (!yaml_output_attr(data, getBitOffset(), attr, wf, opaque))
|
||||
return false; // TODO: error handling???
|
||||
|
||||
toNextAttr();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void YamlTreeWalker::dump_stack()
|
||||
{
|
||||
for (int i=0; i<NODE_STACK_DEPTH; i++) {
|
||||
TRACE(" [%p|%u|%i|%i]",
|
||||
stack[i].node,stack[i].bit_ofs,
|
||||
stack[i].attr_idx,stack[i].elmts);
|
||||
}
|
||||
TRACE("\n");
|
||||
}
|
||||
|
||||
static bool to_parent(void* ctx)
|
||||
{
|
||||
return ((YamlTreeWalker*)ctx)->toParent();
|
||||
}
|
||||
|
||||
static bool to_child(void* ctx)
|
||||
{
|
||||
return ((YamlTreeWalker*)ctx)->toChild();
|
||||
}
|
||||
|
||||
static bool to_next_elmt(void* ctx)
|
||||
{
|
||||
return ((YamlTreeWalker*)ctx)->toNextElmt();
|
||||
}
|
||||
|
||||
static bool find_node(void* ctx, char* buf, uint8_t len)
|
||||
{
|
||||
return ((YamlTreeWalker*)ctx)->findNode(buf,len);
|
||||
}
|
||||
|
||||
static void set_attr(void* ctx, char* buf, uint8_t len)
|
||||
{
|
||||
return ((YamlTreeWalker*)ctx)->setAttrValue(buf,len);
|
||||
}
|
||||
|
||||
const YamlParserCalls YamlTreeWalkerCalls = {
|
||||
to_parent,
|
||||
to_child,
|
||||
to_next_elmt,
|
||||
find_node,
|
||||
set_attr
|
||||
};
|
||||
|
||||
const YamlParserCalls* YamlTreeWalker::get_parser_calls()
|
||||
{
|
||||
return &YamlTreeWalkerCalls;
|
||||
}
|
||||
|
122
radio/src/storage/yaml/yaml_tree_walker.h
Normal file
122
radio/src/storage/yaml/yaml_tree_walker.h
Normal file
|
@ -0,0 +1,122 @@
|
|||
#ifndef _YAML_TREE_WALKER_H_
|
||||
#define _YAML_TREE_WALKER_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include "yaml_node.h"
|
||||
|
||||
struct YamlParserCalls;
|
||||
|
||||
class YamlTreeWalker
|
||||
{
|
||||
struct State {
|
||||
const YamlNode* node;
|
||||
uint32_t bit_ofs;
|
||||
int8_t attr_idx;
|
||||
uint16_t elmts;
|
||||
|
||||
inline uint32_t getOfs() {
|
||||
return bit_ofs + node->size * elmts;
|
||||
}
|
||||
};
|
||||
|
||||
State stack[NODE_STACK_DEPTH];
|
||||
uint8_t stack_level;
|
||||
uint8_t virt_level;
|
||||
uint8_t anon_union;
|
||||
|
||||
uint8_t* data;
|
||||
|
||||
uint32_t getAttrOfs() { return stack[stack_level].bit_ofs; }
|
||||
uint32_t getLevelOfs() {
|
||||
if (hasParent()) {
|
||||
return stack[stack_level + 1].getOfs();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
const YamlNode* getParent() {
|
||||
if (hasParent())
|
||||
return stack[stack_level + 1].node;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void setNode(const YamlNode* node) { stack[stack_level].node = node; }
|
||||
void setAttrIdx(uint8_t idx) { stack[stack_level].attr_idx = idx; }
|
||||
|
||||
void setAttrOfs(unsigned int ofs) { stack[stack_level].bit_ofs = ofs; }
|
||||
|
||||
void incAttr() { stack[stack_level].attr_idx++; }
|
||||
void incElmts() { stack[stack_level].elmts++; }
|
||||
|
||||
bool empty() { return stack_level == NODE_STACK_DEPTH; }
|
||||
bool full() { return stack_level == 0; }
|
||||
|
||||
bool hasParent() { return stack_level < NODE_STACK_DEPTH -1; }
|
||||
|
||||
// return true on success
|
||||
bool push();
|
||||
bool pop();
|
||||
|
||||
// Rewind to the current node's first attribute
|
||||
// (and reset the bit offset)
|
||||
void rewind();
|
||||
|
||||
public:
|
||||
YamlTreeWalker();
|
||||
|
||||
void reset(const YamlNode* node, uint8_t* data);
|
||||
|
||||
int getLevel() {
|
||||
return NODE_STACK_DEPTH - stack_level
|
||||
+ virt_level - anon_union;
|
||||
}
|
||||
|
||||
const YamlNode* getNode() {
|
||||
return stack[stack_level].node;
|
||||
}
|
||||
|
||||
const YamlNode* getAttr() {
|
||||
int8_t idx = stack[stack_level].attr_idx;
|
||||
if (idx >= 0)
|
||||
return &(stack[stack_level].node->u._array.child[idx]);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint16_t getElmts() {
|
||||
return stack[stack_level].elmts;
|
||||
}
|
||||
|
||||
// Increment the cursor until a match is found or the end of
|
||||
// the current collection (node of type YDT_NONE) is reached.
|
||||
//
|
||||
// return true if a match has been found.
|
||||
bool findNode(const char* tag, uint8_t tag_len);
|
||||
|
||||
// Get the current bit offset
|
||||
unsigned int getBitOffset();
|
||||
|
||||
bool toParent();
|
||||
bool toChild();
|
||||
|
||||
bool toNextElmt();
|
||||
void toNextAttr();
|
||||
|
||||
bool isElmtEmpty(uint8_t* data);
|
||||
|
||||
void setAttrValue(char* buf, uint8_t len);
|
||||
|
||||
bool generate(yaml_writer_func wf, void* opaque);
|
||||
|
||||
void dump_stack();
|
||||
|
||||
static const YamlParserCalls* get_parser_calls();
|
||||
};
|
||||
|
||||
// utils
|
||||
uint32_t yaml_parse_enum(const struct YamlIdStr* choices, const char* val, uint8_t val_len);
|
||||
const char* yaml_output_enum(int32_t i, const struct YamlIdStr* choices);
|
||||
|
||||
|
||||
#endif
|
|
@ -8,7 +8,8 @@ set(PWR_BUTTON "PRESS" CACHE STRING "Pwr button type (PRESS/SWITCH)")
|
|||
set(CPU_TYPE STM32F4)
|
||||
set(HSE_VALUE 12000000)
|
||||
set(SDCARD YES)
|
||||
set(EEPROM SDCARD)
|
||||
set(STORAGE SDCARD)
|
||||
set(STORAGE_FORMAT BIN)
|
||||
set(HAPTIC YES)
|
||||
set(GUI_DIR colorlcd)
|
||||
set(NAVIGATION_TYPE horus)
|
||||
|
@ -24,6 +25,11 @@ set(RAMBACKUP YES)
|
|||
set(PPM_LIMITS_SYMETRICAL YES)
|
||||
set(USB_SERIAL ON CACHE BOOL "Enable USB serial (CDC)")
|
||||
|
||||
option(YAML_STORAGE "Enable YAML storage" NO)
|
||||
if(YAML_STORAGE)
|
||||
set(STORAGE_FORMAT YAML)
|
||||
endif()
|
||||
|
||||
# for size report script
|
||||
set(CPU_TYPE_FULL STM32F429xI)
|
||||
set(SIZE_TARGET_MEM_DEFINE "MEM_SIZE_SDRAM2=8192")
|
||||
|
|
|
@ -124,7 +124,7 @@ uint32_t sdMounted();
|
|||
#endif
|
||||
|
||||
#if defined(DISK_CACHE)
|
||||
#include "diskio.h"
|
||||
#include "FatFs/diskio.h"
|
||||
DRESULT __disk_read(BYTE drv, BYTE * buff, DWORD sector, UINT count);
|
||||
DRESULT __disk_write(BYTE drv, const BYTE * buff, DWORD sector, UINT count);
|
||||
#else
|
||||
|
|
|
@ -124,11 +124,20 @@ bool redirectToSettingsDirectory(const std::string & path)
|
|||
*/
|
||||
if (!simuSettingsDirectory.empty()) {
|
||||
#if defined(COLORLCD)
|
||||
if (path == RADIO_MODELSLIST_PATH || path == RADIO_SETTINGS_PATH) {
|
||||
if (path == RADIO_MODELSLIST_PATH || path == RADIO_SETTINGS_PATH
|
||||
#if defined(SDCARD_YAML)
|
||||
|| path == RADIO_MODELSLIST_YAML_PATH || path == RADIO_SETTINGS_YAML_PATH
|
||||
#endif
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
if (startsWith(path, "/MODELS") && endsWith(path, MODELS_EXT)) {
|
||||
if (startsWith(path, "/MODELS")
|
||||
&& (endsWith(path, MODELS_EXT)
|
||||
#if defined(SDCARD_YAML)
|
||||
|| endsWith(path, YAML_EXT)
|
||||
#endif
|
||||
)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,8 @@ set(LUA NO)
|
|||
set(MCU cortex-m3)
|
||||
set(SDCARD YES)
|
||||
set(HAPTIC YES)
|
||||
set(EEPROM EEPROM_RAW)
|
||||
set(STORAGE EEPROM)
|
||||
set(STORAGE_FORMAT RAW)
|
||||
set(GUI_DIR 128x64)
|
||||
set(NAVIGATION_TYPE 9x)
|
||||
set(TARGET_DIR sky9x)
|
||||
|
|
|
@ -271,7 +271,8 @@ endif()
|
|||
|
||||
set(HSE_VALUE 12000000)
|
||||
set(SDCARD YES)
|
||||
set(EEPROM EEPROM_RLC)
|
||||
set(STORAGE EEPROM)
|
||||
set(STORAGE_FORMAT RLC)
|
||||
set(TARGET_DIR taranis)
|
||||
set(PPM_LIMITS_SYMETRICAL YES)
|
||||
|
||||
|
|
|
@ -223,7 +223,7 @@ void processTelemetryFrame(uint8_t module, uint8_t * frame)
|
|||
}
|
||||
}
|
||||
|
||||
#if defined(ACCESS_LIB)
|
||||
#if defined(ACCESS_LIB) && !defined(SIMU)
|
||||
void processAuthenticationFrame(uint8_t module, uint8_t * frame)
|
||||
{
|
||||
uint8_t cryptoType = frame[3];
|
||||
|
|
|
@ -84,7 +84,7 @@ PACK(struct CellValue
|
|||
void set(uint16_t newValue)
|
||||
{
|
||||
if (newValue > 50) {
|
||||
value = value;
|
||||
value = newValue;
|
||||
state = 1;
|
||||
}
|
||||
}
|
||||
|
|
2
radio/src/thirdparty/libACCESS
vendored
2
radio/src/thirdparty/libACCESS
vendored
|
@ -1 +1 @@
|
|||
Subproject commit 79a6921d2386236a44e87554195bf41dc412b445
|
||||
Subproject commit 1bae467262bbe8232111a6baee7195850cef2531
|
2
radio/src/thirdparty/libopenui
vendored
2
radio/src/thirdparty/libopenui
vendored
|
@ -1 +1 @@
|
|||
Subproject commit 24ef5848392ac2a6196f97d277ba54ded8965e4c
|
||||
Subproject commit 385c511755dd9ba5814a9bf46ceb0ce499efd162
|
26
radio/util/dump_ast.py
Normal file
26
radio/util/dump_ast.py
Normal file
|
@ -0,0 +1,26 @@
|
|||
#!/usr/bin/python
|
||||
# vim: set fileencoding=utf-8
|
||||
import clang.cindex
|
||||
import asciitree # must be version 0.2
|
||||
import sys
|
||||
|
||||
def node_children(node):
|
||||
return list(c for c in node.get_children() if c is not None and c.location is not None and c.location.file is not None and c.location.file.name == sys.argv[1])
|
||||
|
||||
def print_node(node):
|
||||
text = node.spelling or node.displayname
|
||||
kind = str(node.kind)[str(node.kind).index('.')+1:]
|
||||
if clang.cindex.CursorKind.FIELD_DECL == node.kind:
|
||||
size = node.type.get_size()
|
||||
return '{} {} {}'.format(kind, text, size)
|
||||
return '{} {}'.format(kind, text)
|
||||
|
||||
if len(sys.argv) < 2:
|
||||
print("Usage: dump_ast.py [header file name] [additional compile args]")
|
||||
sys.exit()
|
||||
|
||||
clang.cindex.Config.set_library_file('/usr/local/Cellar/llvm/6.0.0/lib/libclang.dylib')
|
||||
index = clang.cindex.Index.create()
|
||||
translation_unit = index.parse(sys.argv[1], ['-x', 'c++', '-std=c++11'] + sys.argv[2:])
|
||||
|
||||
print(asciitree.draw_tree(translation_unit.cursor, node_children, print_node))
|
182
radio/util/dump_ast_yaml.py
Normal file
182
radio/util/dump_ast_yaml.py
Normal file
|
@ -0,0 +1,182 @@
|
|||
#!/usr/bin/python
|
||||
# vim: set fileencoding=utf-8
|
||||
|
||||
from clang.cindex import *
|
||||
import asciitree # must be version 0.2
|
||||
import sys
|
||||
|
||||
TOP_NODE_TYPES = [
|
||||
CursorKind.ENUM_DECL,
|
||||
CursorKind.STRUCT_DECL ]
|
||||
|
||||
CHILD_NODE_TYPES = [
|
||||
CursorKind.FIELD_DECL,
|
||||
CursorKind.UNION_DECL,
|
||||
#CursorKind.STRUCT_DECL,
|
||||
CursorKind.ENUM_CONSTANT_DECL ]
|
||||
|
||||
def filter_node(node):
|
||||
if node is None:
|
||||
return False
|
||||
|
||||
# # no node or no location
|
||||
# if node is None or node.location is None or node.location.file is None:
|
||||
# return False
|
||||
|
||||
# # not the main source file
|
||||
# if node.location.file.name != sys.argv[1]:
|
||||
# return False
|
||||
|
||||
if node.kind in CHILD_NODE_TYPES:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def get_struct_decl(node):
|
||||
for c in node.get_children():
|
||||
if c is not None and c.kind == CursorKind.STRUCT_DECL:
|
||||
return c
|
||||
return None
|
||||
|
||||
def node_children(node):
|
||||
|
||||
if node is None:
|
||||
return []
|
||||
|
||||
if isinstance(node,list):
|
||||
return node
|
||||
|
||||
if node.kind == CursorKind.FIELD_DECL:
|
||||
if node.type.kind == TypeKind.ELABORATED:
|
||||
return node_children(node.type.get_declaration())
|
||||
elif node.type.kind == TypeKind.RECORD:
|
||||
return list(c for c in node.type.get_fields())
|
||||
elif node.type.kind == TypeKind.CONSTANTARRAY:
|
||||
et = node.type.element_type
|
||||
if et.kind == TypeKind.RECORD:
|
||||
return list(c for c in et.get_fields())
|
||||
elif node.type.kind == TypeKind.ENUM:
|
||||
return node_children(node.type.get_declaration())
|
||||
else:
|
||||
print("{} {}".format(str(node.type.kind),node.spelling))
|
||||
|
||||
return list(c for c in node.get_children() if filter_node(c))
|
||||
|
||||
def get_array_size(f):
|
||||
et = f.type.element_type
|
||||
ec = f.type.element_count
|
||||
if et.spelling == 'char':
|
||||
return 'string({})'.format(ec)
|
||||
else:
|
||||
return '{} x {} bytes'.format(ec,et.get_size())
|
||||
|
||||
def get_field_size(f):
|
||||
if f.is_bitfield():
|
||||
return '{} bits'.format(f.get_bitfield_width())
|
||||
elif f.type.kind == TypeKind.CONSTANTARRAY:
|
||||
return get_array_size(f)
|
||||
return '{} bytes'.format(f.type.get_size())
|
||||
|
||||
def print_field_decl(kind, text, f):
|
||||
ft = ''
|
||||
is_anon = f.is_anonymous()
|
||||
if f.type.kind == TypeKind.RECORD:
|
||||
decl = f.type.get_declaration()
|
||||
if decl.kind == CursorKind.UNION_DECL:
|
||||
if is_anon:
|
||||
ft = 'anonymous union ({})'.format(decl.mangled_name)
|
||||
else:
|
||||
ft = 'union {}'.format(f.type.spelling)
|
||||
elif decl.kind == CursorKind.STRUCT_DECL:
|
||||
if is_anon:
|
||||
ft = '{} anonymous struct'.format(f.kind)
|
||||
else:
|
||||
ft = 'struct {}'.format(f.type.spelling)
|
||||
elif f.type.kind == TypeKind.TYPEDEF:
|
||||
decl = f.type.get_canonical()
|
||||
ft = decl.spelling
|
||||
elif get_struct_decl(f) is not None:
|
||||
ft = 'anon struct'
|
||||
elif f.type.kind == TypeKind.CONSTANTARRAY:
|
||||
et = f.type.element_type
|
||||
ft = et.spelling
|
||||
else:
|
||||
ft = f.type.spelling
|
||||
|
||||
return '{} {} ({})'.format(ft, text, get_field_size(f))
|
||||
|
||||
def print_enum_decl(kind, text, e):
|
||||
return '{} {} ({})'.format(kind, text, e.enum_value)
|
||||
|
||||
def print_union_decl(kind, text, f):
|
||||
return '{} {} ({})'.format(kind, text, get_field_size(f))
|
||||
|
||||
def print_node(node):
|
||||
|
||||
if isinstance(node,list):
|
||||
return 'ROOT'
|
||||
|
||||
text = node.spelling or node.displayname
|
||||
kind = str(node.kind)[str(node.kind).index('.')+1:]
|
||||
|
||||
if CursorKind.FIELD_DECL == node.kind:
|
||||
return print_field_decl(kind, text, node)
|
||||
|
||||
if CursorKind.ENUM_CONSTANT_DECL == node.kind:
|
||||
return print_enum_decl(kind, text, node)
|
||||
|
||||
if CursorKind.UNION_DECL == node.kind:
|
||||
return print_union_decl(kind, text, node)
|
||||
|
||||
return '{} {}'.format(kind, text)
|
||||
|
||||
def get_top_node(name, node):
|
||||
for c in node.get_children():
|
||||
if c.spelling == name:
|
||||
# struct found
|
||||
return c
|
||||
|
||||
print("get_top_node: '{}' not found!".format(name))
|
||||
return None
|
||||
|
||||
def get_top_nodes(node):
|
||||
l = list()
|
||||
for c in node.get_children():
|
||||
# no node or no location
|
||||
if c is None or c.location is None or c.location.file is None:
|
||||
continue
|
||||
|
||||
# not the main source file
|
||||
if c.location.file.name != sys.argv[1]:
|
||||
continue
|
||||
|
||||
if c.kind in TOP_NODE_TYPES:
|
||||
# struct found
|
||||
l.append(c)
|
||||
|
||||
return l
|
||||
|
||||
def print_top_node(name):
|
||||
s = get_top_node(name, translation_unit.cursor)
|
||||
if s is None:
|
||||
return
|
||||
print(asciitree.draw_tree(s, node_children, print_node))
|
||||
|
||||
def print_all():
|
||||
s = get_top_nodes(translation_unit.cursor)
|
||||
print(asciitree.draw_tree(s, node_children, print_node))
|
||||
|
||||
|
||||
### Main ###
|
||||
|
||||
if len(sys.argv) < 3:
|
||||
print("Usage: dump_ast_yaml.py [header file name] [top node] [additional compile args]")
|
||||
sys.exit()
|
||||
|
||||
Config.set_library_file('/usr/local/Cellar/llvm/6.0.0/lib/libclang.dylib')
|
||||
index = Index.create()
|
||||
translation_unit = index.parse(sys.argv[1], ['-x', 'c++', '-std=c++11'] + sys.argv[3:])
|
||||
|
||||
print_top_node(sys.argv[2])
|
||||
#print_top_node('CustomFunctionData')
|
||||
#print_all()
|
564
radio/util/generate_yaml.py
Normal file
564
radio/util/generate_yaml.py
Normal file
|
@ -0,0 +1,564 @@
|
|||
#!/usr/bin/python
|
||||
import os
|
||||
import sys
|
||||
from clang.cindex import *
|
||||
|
||||
# debug
|
||||
import asciitree # must be version 0.2
|
||||
|
||||
# output
|
||||
import jinja2
|
||||
|
||||
DEBUG_ATTRS = ['layoutData','topbarData','widgetData']
|
||||
|
||||
#USE_FAKE_STRUCT = False
|
||||
USE_FAKE_STRUCT = True
|
||||
|
||||
def node_children(node):
|
||||
l = list(c for c in node.get_children() if c is not None)
|
||||
if len(l) > 0:
|
||||
return l
|
||||
|
||||
return []
|
||||
#decl = node.type.get_declaration()
|
||||
#return list(c for c in decl.get_children() if c is not None)
|
||||
|
||||
def print_node(node):
|
||||
text = node.spelling or node.displayname
|
||||
kind = str(node.kind)[str(node.kind).index('.')+1:]
|
||||
if CursorKind.FIELD_DECL == node.kind:
|
||||
size = node.type.get_size()
|
||||
return '{} {} {}'.format(kind, text, size)
|
||||
return '{} {}'.format(kind, text)
|
||||
|
||||
def dump_node(node):
|
||||
print(asciitree.draw_tree(node, node_children, print_node))
|
||||
|
||||
has_errors = False
|
||||
|
||||
def print_error(*args):
|
||||
print("ERROR:",*args,file=sys.stderr)
|
||||
has_errors = True
|
||||
|
||||
def print_debug(*args):
|
||||
print("DBG:",*args,file=sys.stderr)
|
||||
|
||||
def bail_out(*args):
|
||||
print_error(*args)
|
||||
sys.exit(-1)
|
||||
|
||||
_anon_cnt = 0
|
||||
|
||||
def get_next_anon():
|
||||
global _anon_cnt
|
||||
label = str(_anon_cnt)
|
||||
_anon_cnt = _anon_cnt + 1
|
||||
return label
|
||||
|
||||
SIGNED_TYPES = ['bool', 'char', 'short', 'int', 'long' ]
|
||||
|
||||
def map_type(type_name):
|
||||
if 'unsigned' in type_name:
|
||||
return 'unsigned'
|
||||
elif ('signed' in type_name) or (type_name in SIGNED_TYPES):
|
||||
return 'signed'
|
||||
|
||||
return type_name
|
||||
|
||||
def mangle_type(type_name):
|
||||
return type_name.replace(':','_')
|
||||
|
||||
# Cursor or Type
|
||||
def get_type(obj):
|
||||
if isinstance(obj,Cursor):
|
||||
return obj.type
|
||||
else:
|
||||
return obj
|
||||
|
||||
def is_string(type):
|
||||
if type.kind == TypeKind.CONSTANTARRAY:
|
||||
if type.element_type.spelling == 'char':
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
class AST_Element:
|
||||
def __init__(self, name, cursor):
|
||||
self.name = name
|
||||
self.cursor = cursor
|
||||
self.elmts = []
|
||||
|
||||
def get_children(self):
|
||||
return self.cursor.get_children()
|
||||
|
||||
def get_elmts(self):
|
||||
return self.elmts
|
||||
|
||||
def append(self,elmt):
|
||||
if isinstance(elmt, list):
|
||||
self.elmts.extend(elmt)
|
||||
else:
|
||||
self.elmts.append(elmt)
|
||||
|
||||
def str(self):
|
||||
if hasattr(self,'value'):
|
||||
if hasattr(self,'ann'):
|
||||
return '{}:\t{} ({})'.format(self.name,self.value,self.ann)
|
||||
return '{}:\t{}'.format(self.name,self.value)
|
||||
elif hasattr(self,'type'):
|
||||
if hasattr(self,'var_type'):
|
||||
return '{} {}\t{}'.format(self.type, self.var_type, self.name)
|
||||
else:
|
||||
return '{}\t{}'.format(self.type, self.name)
|
||||
return self.name
|
||||
|
||||
class FieldAST(AST_Element):
|
||||
def __init__(self, name, cursor):
|
||||
super(FieldAST, self).__init__(name, cursor)
|
||||
|
||||
self.is_array = False
|
||||
self.func = 'NULL'
|
||||
|
||||
if self.name in DEBUG_ATTRS:
|
||||
#print("# field name={} type={} canon={} decl={}".format(self.name,cursor.type.spelling,cursor.type.get_canonical().spelling,str(cursor.type.kind)))
|
||||
#dump_node(cursor)
|
||||
pass
|
||||
|
||||
if isinstance(cursor,Cursor):
|
||||
t = cursor.type
|
||||
if cursor.is_bitfield():
|
||||
self.bits = cursor.get_bitfield_width()
|
||||
else:
|
||||
# cursor is a type...
|
||||
t = cursor
|
||||
|
||||
if not hasattr(self,'bits'):
|
||||
self.bits = t.get_size() * 8
|
||||
|
||||
if t.kind == TypeKind.TYPEDEF:
|
||||
self.type = map_type(t.get_canonical().spelling)
|
||||
elif t.kind == TypeKind.CONSTANTARRAY:
|
||||
self.type = t.element_type.spelling
|
||||
self.is_array = True
|
||||
self.length = t.element_count
|
||||
|
||||
if self.type == 'char':
|
||||
self.type = 'string'
|
||||
else:
|
||||
self.type = map_type(t.spelling)
|
||||
|
||||
|
||||
class StructAST(AST_Element):
|
||||
type = 'struct'
|
||||
|
||||
def __init__(self, name, cursor, alt_name=''):
|
||||
|
||||
self.var_name = name
|
||||
|
||||
if len(alt_name) > 0:
|
||||
name = alt_name
|
||||
|
||||
if name == '':
|
||||
name = self.name_prefix() + 'anonymous_' + get_next_anon()
|
||||
else:
|
||||
name = self.name_prefix() + name
|
||||
|
||||
self.func = 'NULL'
|
||||
super(StructAST, self).__init__(name, cursor)
|
||||
|
||||
def name_prefix(self):
|
||||
return self.type + '_'
|
||||
|
||||
class UnionAST(StructAST):
|
||||
type = 'union'
|
||||
|
||||
class EnumAST(AST_Element):
|
||||
type = 'enum'
|
||||
|
||||
def __init__(self, name, cursor):
|
||||
self.var_name = name
|
||||
super(EnumAST, self).__init__('enum_' + name, cursor)
|
||||
|
||||
class AST:
|
||||
name = 'ROOT'
|
||||
|
||||
def __init__(self):
|
||||
self.structs = []
|
||||
self.enums = []
|
||||
|
||||
def has_enum(self,name):
|
||||
for e in self.enums:
|
||||
if e.name == name:
|
||||
return True
|
||||
return False
|
||||
|
||||
def get_enums(self):
|
||||
return self.enums
|
||||
|
||||
def get_structs(self):
|
||||
return self.structs
|
||||
|
||||
def has_struct(self,name):
|
||||
for s in self.structs:
|
||||
if s.name == name:
|
||||
return True
|
||||
return False
|
||||
|
||||
def get_struct(self,name):
|
||||
for s in self.structs:
|
||||
if s.name == name:
|
||||
return s
|
||||
return None
|
||||
|
||||
def get_elmts(self):
|
||||
return self.enums + self.structs
|
||||
|
||||
def append(self, elmt):
|
||||
if isinstance(elmt, StructAST):
|
||||
self.structs.append(elmt)
|
||||
elif isinstance(elmt, EnumAST):
|
||||
self.enums.append(elmt)
|
||||
|
||||
def str(self):
|
||||
return self.name
|
||||
|
||||
def parse_struct(ast, node, alt_name):
|
||||
st = None
|
||||
|
||||
if ast is not RootAST:
|
||||
ast.var_type = ast.type
|
||||
ast.type = 'struct'
|
||||
|
||||
st = StructAST(node.spelling, node, alt_name)
|
||||
if (ast is RootAST):
|
||||
old_st = RootAST.get_struct(st.name)
|
||||
if old_st is not None:
|
||||
return old_st
|
||||
|
||||
st.use_idx = False
|
||||
ann = get_annotations(node)
|
||||
if len(ann) > 0:
|
||||
#print(ann)
|
||||
for a in ann:
|
||||
if a['type'] == 'idx' and a['val'] == 'true':
|
||||
st.use_idx = True
|
||||
break
|
||||
|
||||
for c in node.get_children():
|
||||
parse_field(st,c)
|
||||
|
||||
if st is not ast:
|
||||
ast.append(st)
|
||||
|
||||
#print_debug("IDX ",st.name, " ", st.use_idx)
|
||||
return st
|
||||
|
||||
def parse_union(ast, node):
|
||||
st = None
|
||||
|
||||
if ast is not RootAST:
|
||||
ast.var_type = ast.type
|
||||
ast.type = 'union'
|
||||
|
||||
st = UnionAST(node.spelling, node)
|
||||
if (ast is RootAST):
|
||||
old_st = RootAST.get_struct(st.name)
|
||||
if old_st is not None:
|
||||
return old_st
|
||||
|
||||
for c in node.get_children():
|
||||
parse_field(st,c)
|
||||
|
||||
|
||||
ann = get_annotations(node)
|
||||
if len(ann) > 0:
|
||||
for a in ann:
|
||||
if a['type'] == 'func':
|
||||
st.func = a['val']
|
||||
|
||||
if st is not ast:
|
||||
ast.append(st)
|
||||
|
||||
return st
|
||||
|
||||
def get_annotations(node):
|
||||
l = list()
|
||||
for c in node.get_children():
|
||||
if c.kind == CursorKind.ANNOTATE_ATTR:
|
||||
ann = c.displayname.split(':')
|
||||
l.append({'type':ann[0], 'val':ann[1]})
|
||||
return l
|
||||
|
||||
def parse_field_record(f, node):
|
||||
alt_name = ''
|
||||
decl = node.type.get_declaration()
|
||||
|
||||
if not decl.spelling == '':
|
||||
alt_name = mangle_type(node.type.spelling)
|
||||
#print("alt_name = " + alt_name)
|
||||
|
||||
st = parse_node(RootAST,decl,alt_name)
|
||||
if st is not None:
|
||||
f.var_type = st.name
|
||||
f.var_name = alt_name
|
||||
f.type = st.type
|
||||
|
||||
def make_fake_array_struct(f, node_type, use_idx):
|
||||
|
||||
# if not USE_FAKE_STRUCT:
|
||||
# f.var_type = node_type.spelling
|
||||
# # if is_string(get_type(node_type)):
|
||||
# # f.type = 'array'
|
||||
# # f.length = get_type(node_type).element_count
|
||||
# return
|
||||
|
||||
field = FieldAST('val', node_type)
|
||||
#field.is_fake = True
|
||||
type_name = field.type + '_' + str(field.bits)
|
||||
struct_name = 'struct_' + type_name
|
||||
|
||||
if USE_FAKE_STRUCT and not RootAST.has_struct(struct_name):
|
||||
#print("# field created " + struct_name)
|
||||
st = StructAST(type_name, node_type)
|
||||
st.append(field)
|
||||
st.used_in_arrays = True
|
||||
st.use_idx = use_idx
|
||||
RootAST.append(st)
|
||||
|
||||
f.var_name = f.type
|
||||
f.type = 'array'
|
||||
f.var_type = struct_name
|
||||
#f.var_name = field.type
|
||||
|
||||
|
||||
def parse_field_array(f, node):
|
||||
et = node.type.element_type
|
||||
if f.type != 'string':
|
||||
elmt_decl = et.get_declaration()
|
||||
|
||||
use_idx = False
|
||||
ann = get_annotations(node)
|
||||
if len(ann) > 0:
|
||||
for a in ann:
|
||||
if a['type'] == 'idx':
|
||||
use_idx = True
|
||||
|
||||
# let's see first if it's some kind of struct/union/enum
|
||||
elmt_st = parse_node(RootAST, elmt_decl)
|
||||
if elmt_st is not None:
|
||||
f.type = 'array'
|
||||
f.var_type = elmt_st.name
|
||||
f.var_name = elmt_st.var_name
|
||||
# mark array usage for unions
|
||||
elmt_st.used_in_arrays = True
|
||||
elif elmt_decl.kind == CursorKind.TYPEDEF_DECL:
|
||||
# it's some typedef
|
||||
#print_error("TYPEDEF {} {}".format(f.name, elmt_decl.spelling));
|
||||
make_fake_array_struct(f, elmt_decl, use_idx)
|
||||
elif et.kind == TypeKind.CONSTANTARRAY:
|
||||
# it's an array:
|
||||
# let's create a fake struct with the element type
|
||||
#print_error("ARRAY {} {}".format(f.name, elmt_decl.spelling));
|
||||
make_fake_array_struct(f, et, use_idx)
|
||||
else:
|
||||
pass
|
||||
#print("# unknown array attr: {} {}".format(str(elmt_decl.kind), f.name))
|
||||
|
||||
|
||||
def parse_field(ast,node):
|
||||
|
||||
if (not node.is_anonymous()) and (node.kind != CursorKind.FIELD_DECL):
|
||||
return
|
||||
|
||||
f = FieldAST(node.spelling, node)
|
||||
|
||||
if node.type.kind in [TypeKind.ELABORATED, TypeKind.RECORD, TypeKind.ENUM]:
|
||||
parse_field_record(f, node)
|
||||
|
||||
elif node.type.kind == TypeKind.CONSTANTARRAY:
|
||||
parse_field_array(f, node)
|
||||
|
||||
ann = get_annotations(node)
|
||||
if len(ann) > 0:
|
||||
for a in ann:
|
||||
if a['type'] == 'enum':
|
||||
if not hasattr(f,'f_read'):
|
||||
f.type = 'enum'
|
||||
enum_name = 'enum_' + a['val']
|
||||
f.var_type = enum_name
|
||||
if not RootAST.has_enum(enum_name):
|
||||
parse_node(RootAST,get_top_node(a['val']))
|
||||
elif a['type'] == 'func':
|
||||
f.func = a['val']
|
||||
elif a['type'] == 'name':
|
||||
f.name = a['val']
|
||||
elif a['type'] == 'read':
|
||||
f.f_read = a['val']
|
||||
elif a['type'] == 'write':
|
||||
f.f_write = a['val']
|
||||
elif a['type'] == 'array':
|
||||
array_attrs = a['val'].split('|')
|
||||
elmt_size = int(array_attrs[0])
|
||||
f.var_type = array_attrs[1]
|
||||
f.type = 'array'
|
||||
f.length = int(f.bits / elmt_size)
|
||||
f.func = array_attrs[2]
|
||||
elif a['type'] == 'skip':
|
||||
f.skip = True
|
||||
|
||||
if len(f.name) == 0:
|
||||
print_error("in '{}', field of type '{}' does not have a name".format(ast.name,f.var_type))
|
||||
|
||||
ast.append(f)
|
||||
|
||||
|
||||
def parse_enum_field(ast,node):
|
||||
|
||||
ann = get_annotations(node)
|
||||
if len(ann) > 0:
|
||||
for a in ann:
|
||||
if a['type'] == 'skip':
|
||||
return
|
||||
|
||||
enum_value = node.spelling
|
||||
if '_' in enum_value:
|
||||
enum_value = enum_value[enum_value.index('_')+1:]
|
||||
|
||||
st = AST_Element(enum_value, node)
|
||||
st.value = node.spelling #node.enum_value
|
||||
ast.append(st)
|
||||
# debug
|
||||
if len(ann) > 0:
|
||||
#print(ann)
|
||||
st.ann = ann
|
||||
|
||||
def parse_enum(ast,node):
|
||||
st = EnumAST(node.spelling or node.displayname, node)
|
||||
for c in node.get_children():
|
||||
parse_enum_field(st,c)
|
||||
|
||||
ast.append(st)
|
||||
return st
|
||||
|
||||
def parse_node(ast,node,alt_name=''):
|
||||
st = None
|
||||
|
||||
if node.kind in [CursorKind.STRUCT_DECL,CursorKind.CLASS_DECL]:
|
||||
st = parse_struct(ast,node,alt_name)
|
||||
elif node.kind == CursorKind.UNION_DECL:
|
||||
st = parse_union(ast,node)
|
||||
elif node.kind == CursorKind.FIELD_DECL:
|
||||
parse_field(ast,node)
|
||||
elif node.kind == CursorKind.ENUM_DECL:
|
||||
st = parse_enum(ast,node)
|
||||
else:
|
||||
pass
|
||||
|
||||
return st
|
||||
|
||||
### main ###
|
||||
|
||||
def get_top_node(name):
|
||||
node = translation_unit.cursor
|
||||
for c in node.get_children():
|
||||
if c.spelling == name:
|
||||
# struct found
|
||||
return c.get_definition()
|
||||
|
||||
bail_out(f"'{name}' not found")
|
||||
|
||||
def ast_children(ast_node):
|
||||
if ast_node is not None:
|
||||
return ast_node.get_elmts()
|
||||
return []
|
||||
|
||||
def print_ast_node(ast_node):
|
||||
#if isinstance(ast_node,dict):
|
||||
# return str(ast_node)
|
||||
return ast_node.str()
|
||||
|
||||
if len(sys.argv) < 2:
|
||||
bail_out(f"usage: {sys.argv[0]} [header file name] [template] [node name] [additional compile args]")
|
||||
|
||||
CLANG_LIB_LOCATIONS = [
|
||||
'/usr/local/Cellar/llvm/6.0.0/lib/libclang.dylib',
|
||||
'/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/libclang.dylib',
|
||||
'/Library/Developer/CommandLineTools/usr/lib/libclang.dylib',
|
||||
'/usr/lib/x86_64-linux-gnu/libclang-3.8.so.1'
|
||||
]
|
||||
|
||||
# set clang lib file
|
||||
for lib in CLANG_LIB_LOCATIONS:
|
||||
if os.path.exists(lib):
|
||||
Config.set_library_file(lib)
|
||||
break
|
||||
|
||||
# compile source file
|
||||
index = Index.create()
|
||||
translation_unit = index.parse(sys.argv[1], ['-x', 'c++', '-std=c++11', '-Wno-deprecated-register'] + sys.argv[4:])
|
||||
|
||||
def show_tu_diags(diags, prefix=''):
|
||||
tu_errors = 0
|
||||
for diag in diags:
|
||||
tu_errors = tu_errors + 1
|
||||
print_error(prefix + str(diag))
|
||||
show_tu_diags(diag.children, ' ' + prefix)
|
||||
return tu_errors
|
||||
|
||||
tu_errors = show_tu_diags(translation_unit.diagnostics)
|
||||
if tu_errors > 0:
|
||||
bail_out("{} error(s) while compiling '{}'".format(tu_errors, sys.argv[1]))
|
||||
|
||||
RootAST = AST()
|
||||
|
||||
root_nodes_name = ''
|
||||
top_node_names = sys.argv[3].split(',')
|
||||
# cycle on top nodes:
|
||||
for tn in top_node_names:
|
||||
top_node = get_top_node(tn)
|
||||
#dump_node(top_node)
|
||||
parse_node(RootAST, top_node)
|
||||
if len(root_nodes_name) > 0:
|
||||
root_nodes_name = root_nodes_name + '_' + tn
|
||||
else:
|
||||
root_nodes_name = tn
|
||||
|
||||
# Do not generate anything we had some errors
|
||||
if has_errors:
|
||||
sys.exit(-1)
|
||||
|
||||
#print("Enums:", RootAST.get_enums())
|
||||
#print("Structs:", RootAST.get_structs())
|
||||
#print(asciitree.draw_tree(RootAST, ast_children, print_ast_node))
|
||||
|
||||
#
|
||||
# Template rendering
|
||||
#
|
||||
|
||||
__max_str_len = 0
|
||||
|
||||
def max_len(str):
|
||||
global __max_str_len
|
||||
if len(str) > __max_str_len:
|
||||
__max_str_len = len(str)
|
||||
return str
|
||||
|
||||
def get_max_len():
|
||||
global __max_str_len
|
||||
return __max_str_len
|
||||
|
||||
def max_bits(struct):
|
||||
bits = 0
|
||||
for s in struct.get_elmts():
|
||||
if s.bits > bits:
|
||||
bits = s.bits
|
||||
return bits
|
||||
|
||||
template = jinja2.Template(open(sys.argv[2]).read(), lstrip_blocks=True, trim_blocks=True)
|
||||
|
||||
template.globals['max_len'] = max_len
|
||||
template.globals['get_max_len'] = get_max_len
|
||||
template.globals['max_bits'] = max_bits
|
||||
|
||||
## fixme: root_node_name needs to be mangled (contains ',')
|
||||
print(template.render(root=RootAST,root_nodes=top_node_names,root_node_name=root_nodes_name))
|
72
radio/util/yaml_parser.tmpl
Normal file
72
radio/util/yaml_parser.tmpl
Normal file
|
@ -0,0 +1,72 @@
|
|||
// generated by generate_yaml.py
|
||||
|
||||
//
|
||||
// Enums first
|
||||
//
|
||||
|
||||
{% for enum in root.get_enums() %}
|
||||
const struct YamlIdStr {{ enum.name }}[] = {
|
||||
{% for elmt in enum.get_elmts() %}
|
||||
{ {{ elmt.value }}, "{{ max_len(elmt.name) }}" },
|
||||
{% endfor %}
|
||||
{ 0, NULL }
|
||||
};
|
||||
{% endfor %}
|
||||
|
||||
//
|
||||
// Structs last
|
||||
//
|
||||
|
||||
{% for struct in root.get_structs() %}
|
||||
{% if struct.name.startswith('union_') %}
|
||||
static const struct YamlNode {{ struct.name }}_elmts[] = {
|
||||
{% else %}
|
||||
static const struct YamlNode {{ struct.name }}[] = {
|
||||
{% if struct.used_in_arrays %}
|
||||
YAML_IDX,
|
||||
{% endif%}
|
||||
{% endif %}
|
||||
{% for elmt in struct.get_elmts() %}
|
||||
{% if elmt.skip %}
|
||||
YAML_PADDING( {{ elmt.bits }} ),
|
||||
{% elif elmt.type == 'string' %}
|
||||
YAML_STRING("{{ max_len(elmt.name) }}", {{elmt.length}}),
|
||||
{% elif elmt.type in ['signed','unsigned'] %}
|
||||
{% if elmt.f_read and elmt.f_write %}
|
||||
YAML_{{elmt.type|upper}}_CUST( "{{ max_len(elmt.name) }}", {{ elmt.bits }}, {{ elmt.f_read}}, {{ elmt.f_write}} ),
|
||||
{% else %}
|
||||
YAML_{{elmt.type|upper}}( "{{ max_len(elmt.name) }}", {{ elmt.bits }} ),
|
||||
{% endif %}
|
||||
{% elif elmt.type == 'enum' %}
|
||||
YAML_ENUM("{{ max_len(elmt.name) }}", {{elmt.bits}}, {{elmt.var_type}}),
|
||||
{% elif elmt.type == 'struct' %}
|
||||
YAML_STRUCT("{{ max_len(elmt.name) }}", {{elmt.bits}}, {{elmt.var_type}}, {{ elmt.func }}),
|
||||
{% elif elmt.type == 'union' %}
|
||||
YAML_UNION("{{ max_len(elmt.name) }}", {{elmt.bits}}, {{elmt.var_type}}_elmts, {{ elmt.func}}),
|
||||
{% elif elmt.type == 'array' %}
|
||||
YAML_ARRAY("{{ max_len(elmt.name) }}", {{elmt.bits // elmt.length}}, {{elmt.length}}, {{elmt.var_type}}, {{ elmt.func }}),
|
||||
{% else %}
|
||||
// name='{{elmt.name}}', type='{{elmt.type}}', bits='{{elmt.bits}}', is_array='{{elmt.is_array}}', var_type='{{elmt.var_type}}', kind='{{elmt.cursor.kind}}' , type.kind='{{elmt.cursor.type.kind}}'
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
YAML_END
|
||||
};
|
||||
{% if struct.name.startswith('union_') and struct.used_in_arrays %}
|
||||
static const struct YamlNode {{ struct.name }}[] = {
|
||||
YAML_IDX,
|
||||
YAML_UNION("u", {{ max_bits(struct) }}, {{ struct.name }}_elmts, {{ struct.func }}),
|
||||
YAML_END
|
||||
};
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
#define MAX_{{ root_node_name | upper }}_STR_LEN {{ get_max_len() }}
|
||||
|
||||
{% for tn in root_nodes %}
|
||||
static const struct YamlNode __{{ tn }}_root_node = YAML_ROOT( struct_{{ tn }} );
|
||||
|
||||
const YamlNode* get_{{ tn | lower }}_nodes()
|
||||
{
|
||||
return &__{{ tn }}_root_node;
|
||||
}
|
||||
{% endfor %}
|
Loading…
Add table
Add a link
Reference in a new issue