Files
edgetx-gx12/radio/src/opentx.h
T
Raphael CoefficandMalte Langermann 2b100e0eb5 refact: ADC, switches and keys
Add "hardware_defs" target to dump hardware defines from hal.h per target

Fixed hal.h definitions for switches & ADC inputs

Tools to generate hardware definitions from current hal.h

generator: add support for EXTx and analog switches

WiP

Add generated header to hardware_defs target

Add support for ADC input direction and index per GPIO port

Incredible: it compiles

Removed StdPeriph ADC driver

Works on QX7

Works on TX16S (VBat missing)

Switch driver using generated switches for stm32 targets

Switch driver with generated switches for simu

Use switch names from switch driver

Fixed single conversion handling

Fixed horus VBat reading

Added switch name

Fix warnings about bitfield offsets and GCC 4.4

This is caused by bitfields that cross type boundaries. In this particular case, it happens as the bitfield is not defined the same in `rtc_backup.cpp`.

Switches has already been moved to generic driver

Jitter measurement for each sample, not just for oversampled values

Moved periph clock init to the ADC driver

ADC & GPIOs.

Add switchInit() to init pins

Fix NV14 CMake

Fix taranis target

Fix NV14 (again)

Model audio files: use new interface for switch index

Fix X9-lite

Fix simu headers

Fix getSwitchName()

Add support for ADC switches

Fix switch warning YAML

Test only switches which are defined

Conversions tests for QX7 only on QX7

Fix X12S

Fix function switch names

Enable ADC periph clock before initialising channels

NV14: offset inputs for the sticks & fix switches

WiP: get rid of VSRCRAW and some more

Simu shall use normal ADC driver

fix x7

fix nv14

Fix 9x nav

fix 212x64

fix xlite

fix x9e

fix simu lib

fix unit tests

fix x7 tests

PWM stick values should be written directly into adcValues

... just like FlySky sticks.

fix x12s

fix nv14

Add some support for SPI ADC (only unit tests)

Remove `jq` usage

fix generate_yaml.py for newer libclang

fix pot config

fix stick names

Some YAML generator improvements

Max 16 Pots on COLORLCD

Fix some source names

Use 10 bits for switches to prevent overflow

Removed horus constants for switches & ADC inputs

Fix unit tests

Fix curve edit

Fix libsimulator

Fix function switches (tpro)

Refine ADC & analog API

Moved hardware definitions scripts and templates into own dir

cleanup API refine

Fix unit tests

Mixer: apply calibration only on required inputs

Place ADC switches after all other ADC inputs

Fix X12S

Remove useless TR_POTS_VSRCRAW, TR_SW_VSRCRAW, and TR_VSRCRAW

Cleanup redundant generated YAML parsers

Fixes Boxer rebase

Add boxer to generate-hw-defs.sh

Obsolete LUA exports

Add boxer ADC_DIRECTION

Split generate_hw_defs.py into multiple files

Some cleanup (+ LUA switches)

Fix AXIS definitions

Fixed translation strings declarations

Some rebase fixes

Remove some useless StdPeriph drivers

fix: set pin mode to reset state on usart deinit

fix: use canonical names for calibration data

fix: ADC driver does not care about unconfigured inputs

fix X12S ADC

Add support for ADC conversion chaining

Better X12S ADC implem

Moved X12S ADC driver to HAL/LL

Improve ADC driver separation

Fixed taranis & nv14

Moved PWM gimbals to HAL/LL

Removed useless TR_EXTRA_VSRCRAW

Fixed include guards

Small fixes

Renamed control inputs

Moved internal and external module pulse driver def to boards

Move more things to the generic_stm32 board

Remove STR_VMIXTRIMS

Added analog labels

Generate main control names

Misuse labels / short labels for main controls

Backward compatibility: sliders and legacy names

New keys driver

Let's get rid of StdPeriph headers in simu

Add jinja2 to CI workflows

Use `grep` instead of `sed`

chore: add python jinja2 oto msys setup script

Removed more static definitions and use dynamic ones instead

Fixes X9E

Fix x7 nav too

212 switch display

Fix default sliders

Removed NUM_STICKS

212 switch display working nicely

Surface radio 'stick' replacements

fix: switch, trim & rotary pin init

Remove old key drivers

Removed VKEYS

Removed ETX_FOURCC

Fixed SURFACE_NAME

Removed TR_VSWITCHES & TR_TRIMS_SWITCHES

Fix xpot switches

Store calibrated analogs in physical order

Use getSourceString in drawSource

Implement missing YAML read/write

Fix isSourceAvailableInInputs()

Fix isSourceAvailable()

Some surface fixes

Fix CLI debug

Ported colour UI of analog diagnostics to new ADC API

Small fixes

Better input mapping

Minor tpro fixes

Fix trims available

Remove TX mode choice on surface radio

Rename surface controls

Channel order alignement

Fix throttle warning

Fix checkTrims()

Fix pot config casting issue

Fix IS_SWITCH_FS()

Fixed input mapping

Fix fswitch auto-switch

Fixed storing / reading function switches in YAML

Fix enableVBatBridge() / disableVBatBridge()

Fix interesting mode conversion

Fix sources issues

Fix special funnction list

Proper function switch handling

128 GUI improvements

Fix compilation

Boxer cosmetics

128 hardware screen cosmetic

Fix TX12 switches

More switches fixes

Simplify CPU type handling

Fix flash size

Fixed page-up / page-down in libopenui
2023-06-25 14:32:39 +02:00

1161 lines
26 KiB
C++

/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* 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.
*/
#pragma once
#include <stdlib.h>
#include "definitions.h"
#include "opentx_types.h"
#include "opentx_helpers.h"
#include "touch.h"
#if defined(SIMU)
#include "targets/simu/simpgmspace.h"
#endif
#include "board.h"
#include "usbd_conf.h"
#if defined(LIBOPENUI)
#include "libopenui.h"
#else
#include "libopenui/src/libopenui_file.h"
#endif
#if defined(SIMU)
#define SWITCH_SIMU(a, b) (a)
#else
#define SWITCH_SIMU(a, b) (b)
#endif
#if defined(VARIO)
#define CASE_VARIO(x) x,
#else
#define CASE_VARIO(x)
#endif
#if defined(IMU)
#define CASE_IMU(x) x,
#else
#define CASE_IMU(x)
#endif
#if defined(BACKLIGHT_GPIO)
#define CASE_BACKLIGHT(x) x,
#else
#define CASE_BACKLIGHT(x)
#endif
#if defined(LUA)
#define CASE_LUA(x) x,
#else
#define CASE_LUA(x)
#endif
#if defined(RTCLOCK)
#define CASE_RTCLOCK(x) x,
#else
#define CASE_RTCLOCK(x)
#endif
#if defined(BUZZER)
#define CASE_BUZZER(x) x,
#else
#define CASE_BUZZER(x)
#endif
#if defined(AUDIO)
#define CASE_AUDIO(x) x,
#else
#define CASE_AUDIO(x)
#endif
#if defined(PWM_BACKLIGHT)
#define CASE_PWM_BACKLIGHT(x) x,
#else
#define CASE_PWM_BACKLIGHT(x)
#endif
#if defined(GPS)
#define CASE_GPS(x) x,
#else
#define CASE_GPS(x)
#endif
#if defined(VARIO)
#define CASE_VARIO(x) x,
#else
#define CASE_VARIO(x)
#endif
#if defined(HAPTIC)
#define CASE_HAPTIC(x) x,
#else
#define CASE_HAPTIC(x)
#endif
#if defined(SPLASH)
#define CASE_SPLASH(x) x,
#else
#define CASE_SPLASH(x)
#endif
#if defined(PWR_BUTTON_PRESS)
#define CASE_PWR_BUTTON_PRESS(x) x,
#else
#define CASE_PWR_BUTTON_PRESS(x)
#endif
#if defined(PXX1)
#define CASE_PXX1(x) x,
#else
#define CASE_PXX1(x)
#endif
#if defined(PXX2)
#define CASE_PXX2(x) x,
#else
#define CASE_PXX2(x)
#endif
#if defined(SDCARD)
#define CASE_SDCARD(x) x,
#else
#define CASE_SDCARD(x)
#endif
#if defined(BLUETOOTH)
#define CASE_BLUETOOTH(x) x,
#else
#define CASE_BLUETOOTH(x)
#endif
#if defined(HELI)
#define CASE_HELI(x) x,
#else
#define CASE_HELI(x)
#endif
#if defined(FLIGHT_MODES)
#define CASE_FLIGHT_MODES(x) x,
#else
#define CASE_FLIGHT_MODES(x)
#endif
#if defined(GVARS)
#define CASE_GVARS(x) x,
#else
#define CASE_GVARS(x)
#endif
#if defined(LUA_MODEL_SCRIPTS)
#define CASE_LUA_MODEL_SCRIPTS(x) x,
#else
#define CASE_LUA_MODEL_SCRIPTS(x)
#endif
#if defined(PCBX9DP) || defined(PCBX9E)
#define CASE_PCBX9E_PCBX9DP(x) x,
#else
#define CASE_PCBX9E_PCBX9DP(x)
#endif
#if defined(PCBX9E)
#define CASE_PCBX9E(x) x,
#else
#define CASE_PCBX9E(x)
#endif
#define CASE_CAPACITY(x)
#if defined(FAI)
#define IS_FAI_ENABLED() true
#define IF_FAI_CHOICE(x)
#elif defined(FAI_CHOICE)
#define IS_FAI_ENABLED() g_eeGeneral.fai
#define IF_FAI_CHOICE(x) x,
#else
#define IS_FAI_ENABLED() false
#define IF_FAI_CHOICE(x)
#endif
#define IS_FAI_FORBIDDEN(idx) (IS_FAI_ENABLED() && isFaiForbidden(idx))
#if defined(BLUETOOTH)
#if defined(X9E)
#define IS_BLUETOOTH_TRAINER() (g_model.trainerData.mode == TRAINER_MODE_SLAVE_BLUETOOTH)
#define IS_SLAVE_TRAINER() (g_model.trainerData.mode == TRAINER_MODE_SLAVE)
#else
#define IS_BLUETOOTH_TRAINER() (g_model.trainerData.mode == TRAINER_MODE_MASTER_BLUETOOTH || g_model.trainerData.mode == TRAINER_MODE_SLAVE_BLUETOOTH)
#define IS_SLAVE_TRAINER() (g_model.trainerData.mode == TRAINER_MODE_SLAVE || g_model.trainerData.mode == TRAINER_MODE_SLAVE_BLUETOOTH)
#endif
#else
#define IS_BLUETOOTH_TRAINER() false
#define IS_SLAVE_TRAINER() (g_model.trainerData.mode == TRAINER_MODE_SLAVE)
#endif
#if defined(LUA) || defined(PXX2) || defined(MULTIMODULE)
#define RADIO_TOOLS
#endif
#if defined(ROTARY_ENCODER_NAVIGATION)
enum RotaryEncoderMode {
ROTARY_ENCODER_MODE_NORMAL,
ROTARY_ENCODER_MODE_INVERT_BOTH,
ROTARY_ENCODER_MODE_INVERT_VERT_HORZ_NORM,
ROTARY_ENCODER_MODE_INVERT_VERT_HORZ_ALT
};
#endif
// RESX range is used for internal calculation; The menu says -100.0 to 100.0; internally it is -1024 to 1024 to allow some optimizations
#define RESX_SHIFT 10
#define RESX 1024
#define RESXu 1024u
#define RESXul 1024ul
#define RESXl 1024l
#if defined(JACK_DETECT_GPIO)
#define CASE_JACK_DETECT(x) x,
#else
#define CASE_JACK_DETECT(x)
#endif
#if defined(DISK_CACHE)
#include "disk_cache.h"
#endif
#include "debug.h"
#include "myeeprom.h"
#include "curves.h"
void memswap(void * a, void * b, uint8_t size);
// TODO: move these config check macros somewhere else
#define POT_CONFIG(x) \
((g_eeGeneral.potsConfig >> POT_CONFIG_POS(x)) & POT_CFG_MASK)
#define IS_POT_MULTIPOS(x) (POT_CONFIG(x) == POT_MULTIPOS_SWITCH)
#define IS_POT_WITHOUT_DETENT(x) (POT_CONFIG(x) == POT_WITHOUT_DETENT)
#define IS_SLIDER(x) (POT_CONFIG(x) == POT_SLIDER_WITH_DETENT)
#define IS_POT_AVAILABLE(x) (POT_CONFIG(x) != POT_NONE)
#define IS_POT_SLIDER_AVAILABLE(x) (IS_POT_AVAILABLE(x))
#define IS_MULTIPOS_CALIBRATED(cal) (cal->count > 0 && cal->count < XPOTS_MULTIPOS_COUNT)
#define IS_SWITCH_MULTIPOS(x) \
(SWSRC_FIRST_MULTIPOS_SWITCH <= (x) && (x) <= SWSRC_LAST_MULTIPOS_SWITCH)
#define GET_LOWRES_POT_POSITION(i) (getValue(MIXSRC_FIRST_POT + (i)) >> 4)
#define SAVE_POT_POSITION(i) \
g_model.potsWarnPosition[i] = GET_LOWRES_POT_POSITION(i)
#define ANALOG_CENTER_BEEP(x) \
(g_model.beepANACenter & ((BeepANACenter)1 << (x)))
#define PPM_CENTER 1500
#if defined(PPM_CENTER_ADJUSTABLE)
#define PPM_CH_CENTER(ch) (PPM_CENTER + limitAddress(ch)->ppmCenter)
#else
#define PPM_CH_CENTER(ch) (PPM_CENTER)
#endif
#include "fifo.h"
#include "io/frsky_sport.h"
#if defined(CLI)
#include "cli.h"
#endif
#include "timers.h"
#include "storage/storage.h"
#include "pulses/pulses.h"
#include "pulses/modules_helpers.h"
#define MASK_CFN_TYPE uint64_t // current max = 64 function switches
#define MASK_FUNC_TYPE uint32_t // current max = 32 functions
struct CustomFunctionsContext {
MASK_FUNC_TYPE activeFunctions;
MASK_CFN_TYPE activeSwitches;
tmr10ms_t lastFunctionTime[MAX_SPECIAL_FUNCTIONS];
inline bool isFunctionActive(uint8_t func)
{
return activeFunctions & ((MASK_FUNC_TYPE)1 << func);
}
void reset()
{
memclear(this, sizeof(*this));
}
};
#include "strhelpers.h"
#include "gui.h"
#if !defined(SIMU)
#define assert(x)
#if !defined(DEBUG)
#define printf printf_not_allowed
#endif
#endif
#define THRCHK_DEADBAND 16
inline bool SPLASH_NEEDED()
{
#if defined(COLORLCD)
return false;
#else
return g_eeGeneral.splashMode != 3;
#endif
}
#if defined(PCBHORUS)
#define SPLASH_TIMEOUT 0 /* we use the splash duration to load stuff from the SD */
#elif defined(PCBTARANIS)
#define SPLASH_TIMEOUT (g_eeGeneral.splashMode == -4 ? 1500 : (g_eeGeneral.splashMode <= 0 ? (400-g_eeGeneral.splashMode * 200) : (400 - g_eeGeneral.splashMode * 100)))
#else
#define SPLASH_TIMEOUT (4 * 100) // 4 seconds
#endif
constexpr uint8_t HEART_TIMER_10MS = 0x01;
constexpr uint8_t HEART_TIMER_PULSES = 0x02; // when multiple modules this is the first one
constexpr uint8_t HEART_WDT_CHECK = HEART_TIMER_10MS
#if defined(HARDWARE_INTERNAL_MODULE)
+ (HEART_TIMER_PULSES << INTERNAL_MODULE)
#endif
#if defined(HARDWARE_EXTERNAL_MODULE)
+ (HEART_TIMER_PULSES << EXTERNAL_MODULE)
#endif
; // end of HEART_WDT_CHECK
extern uint8_t heartbeat;
#define MAX_ALERT_TIME 60
#define LEN_STD_CHARS 40
#if defined(TRANSLATIONS_CZ)
#define ZCHAR_MAX (LEN_STD_CHARS)
#else
#define ZCHAR_MAX (LEN_STD_CHARS + LEN_SPECIAL_CHARS)
#endif
#include "keys.h"
#include "pwr.h"
// #if defined(PCBFRSKY) || defined(PCBNV14)
// extern uint8_t potsPos[NUM_XPOTS];
// #endif
bool trimDown(uint8_t idx);
#if defined(KEYS_GPIO_REG_BIND)
void bindButtonHandler(event_t event);
#endif
uint16_t evalChkSum();
void alert(const char * title, const char * msg, uint8_t sound);
#if !defined(GUI)
#define RAISE_ALERT(...)
#define ALERT(...)
#elif defined(COLORLCD)
#define TELEMETRY_CHECK_DELAY10ms 150
bool confirmationDialog(const char *title, const char *msg, bool checkPwr = true, const std::function<bool(void)>& closeCondition = nullptr);
void raiseAlert(const char *title, const char *msg, const char *info,
uint8_t sound);
inline void RAISE_ALERT(const char *title, const char *msg, const char *info,
uint8_t sound)
{
raiseAlert(title, msg, info, sound);
}
inline void ALERT(const char *title, const char *msg, uint8_t sound)
{
raiseAlert(title, msg, STR_PRESS_ANY_KEY_TO_SKIP, sound);
}
#else // !COLORLCD && GUI
inline void RAISE_ALERT(const char *title, const char *msg, const char *info,
uint8_t sound)
{
showAlertBox(title, msg, info, sound);
}
inline void ALERT(const char *title, const char *msg, uint8_t sound)
{
alert(title, msg, sound);
}
#endif // !COLORLCD && GUI
enum PerOutMode {
e_perout_mode_normal = 0,
e_perout_mode_inactive_flight_mode = 1,
e_perout_mode_notrainer = 2,
e_perout_mode_notrims = 4,
e_perout_mode_nosticks = 8,
e_perout_mode_noinput = e_perout_mode_notrainer+e_perout_mode_notrims+e_perout_mode_nosticks
};
extern uint8_t mixerCurrentFlightMode;
extern uint8_t lastFlightMode;
extern uint8_t flightModeTransitionLast;
extern uint32_t availableMemory();
void evalFlightModeMixes(uint8_t mode, uint8_t tick10ms);
void evalMixes(uint8_t tick10ms);
void doMixerCalculations();
void doMixerPeriodicUpdates();
void checkTrims();
extern uint8_t currentBacklightBright;
void perMain();
void per10ms();
getvalue_t getValue(mixsrc_t i, bool* valid = nullptr);
int8_t getMovedSource(uint8_t min);
#define GET_MOVED_SOURCE(min, max) getMovedSource(min)
#if defined(FLIGHT_MODES)
extern uint8_t getFlightMode();
#else
#define getFlightMode() 0
#endif
#define getTrimFlightMode(phase, idx) (phase)
#if defined(GVARS)
extern int8_t trimGvar[MAX_TRIMS];
#define TRIM_REUSED(idx) trimGvar[idx] >= 0
#else
#define TRIM_REUSED(idx) 0
#endif
trim_t getRawTrimValue(uint8_t phase, uint8_t idx);
int getTrimValue(uint8_t phase, uint8_t idx);
bool setTrimValue(uint8_t phase, uint8_t idx, int trim);
#include "gvars.h"
void flightReset(uint8_t check=true);
#define DURATION_MS_PREC2(x) ((x)/20)
#if defined(THRTRACE)
#if defined(COLORLCD)
#define MAXTRACE (LCD_W-2*10)
#else
#define MAXTRACE (LCD_W - 8)
#endif
extern uint8_t s_traceBuf[MAXTRACE];
extern uint16_t s_traceWr;
extern uint8_t s_cnt_10s;
extern uint16_t s_cnt_samples_thr_10s;
extern uint16_t s_sum_samples_thr_10s;
#define RESET_THR_TRACE() s_traceWr = s_cnt_10s = s_cnt_samples_thr_10s = s_sum_samples_thr_10s = s_timeCum16ThrP = s_timeCumThr = 0
#else
#define RESET_THR_TRACE() s_timeCum16ThrP = s_timeCumThr = 0
#endif
#if defined(SPLASH)
void doSplash();
#endif
// disabled function (not used anywhere)
#define READ_ONLY() false
#define READ_ONLY_UNLOCKED() true
void checkLowEEPROM();
void checkThrottleStick();
void checkSwitches();
void checkAlarm();
void checkAll();
void getADC();
#include "sbus.h"
void resetBacklightTimeout();
void checkBacklight();
uint16_t isqrt32(uint32_t n);
void setDefaultOwnerId();
void generalDefault();
uint32_t hash(const void * ptr, uint32_t size);
#define calc100to256_16Bits(x) calc100to256(x)
#define calc100toRESX_16Bits(x) calc100toRESX(x)
#define calc100to256_16Bits(x) calc100to256(x)
#define calc100toRESX_16Bits(x) calc100toRESX(x)
inline int calc100to256(int x)
{
return divRoundClosest(x*256, 100);
}
inline int calc100toRESX(int x)
{
return divRoundClosest(x*RESX, 100);
}
inline int calc1000toRESX(int x)
{
return divRoundClosest(x*RESX, 1000);
}
inline int calcRESXto1000(int x)
{
return divRoundClosest(x*1000, RESX);
}
inline int calcRESXto100(int x)
{
return divRoundClosest(x*100, RESX);
}
#define g_blinkTmr10ms (*(uint8_t*)&g_tmr10ms)
#include "trainer.h"
int expo(int x, int k);
inline void getMixSrcRange(const int source, int16_t & valMin, int16_t & valMax, LcdFlags * flags = 0)
{
if (source >= MIXSRC_FIRST_TRIM && source <= MIXSRC_LAST_TRIM) {
valMax = g_model.extendedTrims ? TRIM_EXTENDED_MAX : TRIM_MAX;
valMin = -valMax;
}
#if defined(LUA_INPUTS)
else if (source >= MIXSRC_FIRST_LUA && source <= MIXSRC_LAST_LUA) {
valMax = 30000;
valMin = -valMax;
}
#endif
else if (source < MIXSRC_FIRST_CH) {
valMax = 100;
valMin = -valMax;
}
else if (source <= MIXSRC_LAST_CH) {
valMax = g_model.extendedLimits ? LIMIT_EXT_PERCENT : 100;
valMin = -valMax;
}
#if defined(GVARS)
else if (source >= MIXSRC_FIRST_GVAR && source <= MIXSRC_LAST_GVAR) {
valMax = min<int>(CFN_GVAR_CST_MAX, MODEL_GVAR_MAX(source-MIXSRC_FIRST_GVAR));
valMin = max<int>(CFN_GVAR_CST_MIN, MODEL_GVAR_MIN(source-MIXSRC_FIRST_GVAR));
if (flags && g_model.gvars[source-MIXSRC_FIRST_GVAR].prec)
*flags |= PREC1;
}
#endif
else if (source == MIXSRC_TX_VOLTAGE) {
valMax = 255;
valMin = 0;
if (flags)
*flags |= PREC1;
}
else if (source == MIXSRC_TX_TIME) {
valMax = 23 * 60 + 59;
valMin = 0;
}
else if (source >= MIXSRC_FIRST_TIMER && source <= MIXSRC_LAST_TIMER) {
valMax = 9 * 60 * 60 - 1;
valMin = -valMax;
if (flags)
*flags |= TIMEHOUR;
}
else {
valMax = 30000;
valMin = -valMax;
}
}
#if defined(GVAR_MAX)
inline void getGVarIncDecRange(int16_t & valMin, int16_t & valMax)
{
int16_t rng = abs(valMax - valMin);
valMin = -rng;
valMax = rng;
}
#endif
void applyExpos(int16_t * anas, uint8_t mode, uint8_t ovwrIdx=0, int16_t ovwrValue=0);
int16_t applyLimits(uint8_t channel, int32_t value);
void evalInputs(uint8_t mode);
uint16_t anaIn(uint8_t chan);
#define FLASH_DURATION 20 /*200ms*/
FlightModeData * flightModeAddress(uint8_t idx);
ExpoData * expoAddress(uint8_t idx);
MixData * mixAddress(uint8_t idx);
LimitData * limitAddress(uint8_t idx);
LogicalSwitchData * lswAddress(uint8_t idx);
USBJoystickChData * usbJChAddress(uint8_t idx);
void applyDefaultTemplate();
void instantTrim();
void evalTrims();
void copyTrimsToOffset(uint8_t ch);
void copySticksToOffset(uint8_t ch);
void copyMinMaxToOutputs(uint8_t ch);
void moveTrimsToOffsets();
inline bool isExpoActive(uint8_t expo)
{
return swOn[expo].activeExpo;
}
inline bool isMixActive(uint8_t mix)
{
return swOn[mix].activeMix;
}
enum FunctionsActive {
FUNCTION_TRAINER_STICK1,
FUNCTION_TRAINER_CHANNELS = FUNCTION_TRAINER_STICK1 + MAX_STICKS,
FUNCTION_INSTANT_TRIM,
FUNCTION_VARIO,
#if defined(SDCARD)
FUNCTION_LOGS,
#endif
FUNCTION_BACKGND_MUSIC,
FUNCTION_BACKGND_MUSIC_PAUSE,
FUNCTION_BACKLIGHT,
FUNCTION_RACING_MODE,
#if defined(HARDWARE_TOUCH)
FUNCTION_DISABLE_TOUCH,
#endif
};
#define VARIO_FREQUENCY_ZERO 700/*Hz*/
#define VARIO_FREQUENCY_RANGE 1000/*Hz*/
#define VARIO_REPEAT_ZERO 500/*ms*/
#define VARIO_REPEAT_MAX 80/*ms*/
extern CustomFunctionsContext modelFunctionsContext;
extern CustomFunctionsContext globalFunctionsContext;
inline bool isFunctionActive(uint8_t func)
{
return globalFunctionsContext.isFunctionActive(func) || modelFunctionsContext.isFunctionActive(func);
}
void evalFunctions(const CustomFunctionData * functions, CustomFunctionsContext & functionsContext);
inline void customFunctionsReset()
{
globalFunctionsContext.reset();
modelFunctionsContext.reset();
}
const char* funcGetLabel(uint8_t func);
#include "telemetry/telemetry.h"
#include "crc.h"
#define PLAY_REPEAT(x) (x) /* Range 0 to 15 */
#define PLAY_NOW 0x10
#define PLAY_BACKGROUND 0x20
enum AUDIO_SOUNDS {
AUDIO_HELLO,
AU_BYE,
AU_THROTTLE_ALERT,
AU_SWITCH_ALERT,
AU_BAD_RADIODATA,
AU_TX_BATTERY_LOW,
AU_INACTIVITY,
AU_RSSI_ORANGE,
AU_RSSI_RED,
AU_RAS_RED,
AU_TELEMETRY_LOST,
AU_TELEMETRY_BACK,
AU_TRAINER_CONNECTED,
AU_TRAINER_LOST,
AU_TRAINER_BACK,
AU_SENSOR_LOST,
AU_SERVO_KO,
AU_RX_OVERLOAD,
AU_MODEL_STILL_POWERED,
AU_ERROR,
AU_WARNING1,
AU_WARNING2,
AU_WARNING3,
AU_TRIM_MIDDLE,
AU_TRIM_MIN,
AU_TRIM_MAX,
AU_STICK1_MIDDLE,
AU_STICK2_MIDDLE,
AU_STICK3_MIDDLE,
AU_STICK4_MIDDLE,
#if defined(PCBFRSKY)
AU_POT1_MIDDLE,
AU_POT2_MIDDLE,
#if defined(PCBX9E)
AU_POT3_MIDDLE,
AU_POT4_MIDDLE,
#endif
#if defined(PCBX10)
AU_POT4_MIDDLE,
AU_POT5_MIDDLE,
AU_POT6_MIDDLE,
AU_POT7_MIDDLE,
#endif
AU_SLIDER1_MIDDLE,
AU_SLIDER2_MIDDLE,
#if defined(PCBX9E)
AU_SLIDER3_MIDDLE,
AU_SLIDER4_MIDDLE,
#endif
#else
AU_POT1_MIDDLE,
AU_POT2_MIDDLE,
AU_POT3_MIDDLE,
#endif
AU_MIX_WARNING_1,
AU_MIX_WARNING_2,
AU_MIX_WARNING_3,
AU_TIMER1_ELAPSED,
AU_TIMER2_ELAPSED,
AU_TIMER3_ELAPSED,
AU_SPECIAL_SOUND_FIRST,
AU_SPECIAL_SOUND_BEEP1 = AU_SPECIAL_SOUND_FIRST,
AU_SPECIAL_SOUND_BEEP2,
AU_SPECIAL_SOUND_BEEP3,
AU_SPECIAL_SOUND_WARN1,
AU_SPECIAL_SOUND_WARN2,
AU_SPECIAL_SOUND_CHEEP,
AU_SPECIAL_SOUND_RATATA,
AU_SPECIAL_SOUND_TICK,
AU_SPECIAL_SOUND_SIREN,
AU_SPECIAL_SOUND_RING,
AU_SPECIAL_SOUND_SCIFI,
AU_SPECIAL_SOUND_ROBOT,
AU_SPECIAL_SOUND_CHIRP,
AU_SPECIAL_SOUND_TADA,
AU_SPECIAL_SOUND_CRICKET,
AU_SPECIAL_SOUND_ALARMC,
AU_SPECIAL_SOUND_LAST,
AU_NONE = 0xff
};
#if defined(AUDIO)
#include "audio.h"
#endif
#include "buzzer.h"
#include "translations.h"
#if defined(HAPTIC)
#include "haptic.h"
#endif
#if defined(SDCARD)
#include "sdcard.h"
#endif
#if defined(RTCLOCK)
#include "rtc.h"
#endif
void checkBattery();
void opentxClose(uint8_t shutdown=true);
void opentxInit();
void opentxResume();
constexpr uint8_t OPENTX_START_NO_SPLASH = 0x01;
constexpr uint8_t OPENTX_START_NO_CALIBRATION = 0x02;
constexpr uint8_t OPENTX_START_NO_CHECKS = 0x04;
#if defined(STATUS_LEDS)
#define LED_ERROR_BEGIN() ledRed()
// Green is preferred "ready to use" color for these radios
#if defined(MANUFACTURER_RADIOMASTER) || defined(MANUFACTURER_JUMPER) || defined(RADIO_COMMANDO8)
#define LED_ERROR_END() ledGreen()
#define LED_BIND() ledBlue()
#else
// Either green is not an option, or blue is preferred "ready to use" color
#define LED_ERROR_END() ledBlue()
#endif
#else
#define LED_ERROR_BEGIN()
#define LED_ERROR_END()
#endif
// Re-useable byte array to save having multiple buffers
#if LCD_W <= 212
constexpr uint8_t SD_SCREEN_FILE_LENGTH = 32;
#else
constexpr uint8_t SD_SCREEN_FILE_LENGTH = 64;
#endif
#if defined(BLUETOOTH)
#include "bluetooth.h"
#endif
constexpr uint8_t TEXT_FILENAME_MAXLEN = 40;
#if defined(GHOST)
#include "telemetry/ghost_menu.h"
#endif
union ReusableBuffer
{
struct {
#if defined(EEPROM_RLC) && LCD_W < 212
uint16_t eepromfree;
#endif
#if defined(SDCARD) && !defined(COLORLCD)
char menu_bss[POPUP_MENU_MAX_LINES][MENU_LINE_LENGTH];
char mainname[45]; // because reused for SD backup / restore, max backup filename 44 chars: "/MODELS/MODEL0134353-2014-06-19-04-51-27.bin"
#elif !defined(COLORLCD)
char mainname[LEN_MODEL_NAME];
#endif
} modelsel;
struct {
char msg[64];
uint8_t r9mPower;
int8_t antennaMode;
uint8_t previousType;
uint8_t newType;
#if defined(PXX2)
BindInformation bindInformation;
PXX2ModuleSetup pxx2;
#endif
#if defined(BLUETOOTH)
struct {
char devices[MAX_BLUETOOTH_DISTANT_ADDR][LEN_BLUETOOTH_ADDR+1];
uint8_t devicesCount;
} bt;
#endif
} moduleSetup;
struct {
uint8_t state;
union {
struct {
int16_t midVal;
int16_t loVal;
int16_t hiVal;
} input;
struct {
uint8_t stepsCount;
int16_t steps[XPOTS_MULTIPOS_COUNT];
uint8_t lastCount;
int16_t lastPosition;
} xpot;
} inputs[MAX_ANALOG_INPUTS];
} calib;
#if defined(SDCARD)
struct {
char lines[NUM_BODY_LINES][SD_SCREEN_FILE_LENGTH+1+1]; // the last char is used to store the flags (directory) of the line
uint32_t available;
uint16_t offset;
uint16_t count;
char originalName[SD_SCREEN_FILE_LENGTH+1];
#if defined(PXX2)
OtaUpdateInformation otaUpdateInformation;
char otaReceiverVersion[sizeof(TR_CURRENT_VERSION) + 12];
#endif
} sdManager;
#endif
struct
{
char id[27];
} version;
#if defined(PXX2)
PXX2HardwareAndSettings hardwareAndSettings; // radio_version
#endif
struct {
#if defined(PXX2)
ModuleInformation modules[NUM_MODULES];
#endif
char msg[64];
#if !defined(COLORLCD)
uint8_t linesCount;
#endif
} radioTools;
struct {
int8_t antennaMode;
} radioHardware;
struct {
uint8_t stickMode;
#if defined(ROTARY_ENCODER_NAVIGATION)
uint8_t rotaryEncoderMode;
#endif
} generalSettings;
struct {
uint8_t bars[LCD_W];
uint8_t max[LCD_W];
uint32_t freq;
uint32_t span;
uint32_t step;
uint32_t track;
uint8_t spanDefault;
uint8_t spanMax;
uint16_t freqDefault;
uint16_t freqMax;
uint16_t freqMin;
uint8_t dirty;
uint8_t moduleOFF;
} spectrumAnalyser;
#if defined(GHOST)
struct {
GhostMenuData line[GHST_MENU_LINES + 1];
uint8_t menuStatus;
uint8_t menuAction;
uint8_t buttonAction;
} ghostMenu;
#endif
struct {
uint32_t freq;
int16_t power;
int16_t peak;
uint8_t attn;
uint8_t dirty;
} powerMeter;
struct {
int8_t preset;
} curveEdit;
#if !defined(COLORLCD)
struct {
char filename[TEXT_FILENAME_MAXLEN];
char lines[NUM_BODY_LINES][LCD_COLS + 1];
int linesCount;
} viewText;
#endif
struct {
bool longNames;
bool secondPage;
bool mixersView;
} viewChannels;
struct {
uint8_t maxNameLen;
} modelFailsafe;
struct {
#if defined(PXX2)
ModuleInformation internalModule;
#endif
} viewMain;
// Data for the USB mass storage driver. If USB mass storage runs no menu is not allowed to be displayed
uint8_t MSC_BOT_Data[MSC_MEDIA_PACKET];
};
extern ReusableBuffer reusableBuffer;
uint8_t zlen(const char *str, uint8_t size);
bool zexist(const char *str, uint8_t size);
char * strcat_zchar(char *dest, const char *name, uint8_t size, const char spaceSym = 0, const char *defaultName=nullptr, uint8_t defaultNameSize=0, uint8_t defaultIdx=0);
#define strcatFlightmodeName(dest, idx) strcat_zchar(dest, g_model.flightModeData[idx].name, LEN_FLIGHT_MODE_NAME, 0, STR_FM, PSIZE(TR_FM), idx+1)
#if !defined(STORAGE_MODELSLIST)
#define strcat_modelname(dest, idx, spaceSym) \
strcat_zchar(dest, modelHeaders[idx].name, LEN_MODEL_NAME, spaceSym, STR_MODEL, \
PSIZE(TR_MODEL), idx + 1)
#define strcat_currentmodelname(dest, spaceSym) \
strcat_modelname(dest, g_eeGeneral.currModel, spaceSym)
#else
#define strcat_currentmodelname(dest, spaceSym) \
strcat_zchar(dest, g_model.header.name, LEN_MODEL_NAME, spaceSym)
#endif
#define ZLEN(s) zlen(s, sizeof(s))
#define ZEXIST(s) zexist(s, sizeof(s))
// Stick tolerance varies between transmitters, Higher is better
#define STICK_TOLERANCE 64
ls_telemetry_value_t maxTelemValue(source_t channel);
getvalue_t convert16bitsTelemValue(source_t channel, ls_telemetry_value_t value);
getvalue_t convertLswTelemValue(LogicalSwitchData * cs);
inline getvalue_t convertTelemValue(source_t channel, ls_telemetry_value_t value)
{
return convert16bitsTelemValue(channel, value);
}
extern uint8_t g_vbat100mV;
inline uint8_t GET_TXBATT_BARS(uint8_t barsMax)
{
return limit<int8_t>(0, divRoundClosest(barsMax * (g_vbat100mV - g_eeGeneral.vBatMin - 90), 30 + g_eeGeneral.vBatMax - g_eeGeneral.vBatMin), barsMax);
}
inline bool IS_TXBATT_WARNING()
{
return g_vbat100mV <= g_eeGeneral.vBatWarn;
}
enum TelemetryViews {
TELEMETRY_CUSTOM_SCREEN_1,
TELEMETRY_CUSTOM_SCREEN_2,
TELEMETRY_CUSTOM_SCREEN_3,
TELEMETRY_CUSTOM_SCREEN_4,
TELEMETRY_VIEW_MAX = TELEMETRY_CUSTOM_SCREEN_4
};
extern uint8_t s_frsky_view;
constexpr uint32_t EARTH_RADIUS = 6371009;
void varioWakeup();
#if defined(AUDIO) && defined(BUZZER)
#define IS_SOUND_OFF() (g_eeGeneral.buzzerMode==e_mode_quiet && g_eeGeneral.beepMode==e_mode_quiet)
#else
#define IS_SOUND_OFF() (g_eeGeneral.beepMode == e_mode_quiet)
#endif
#define IS_IMPERIAL_ENABLE() (g_eeGeneral.imperial)
#if defined(PCBTARANIS)
extern const unsigned char logo_taranis[];
#endif
#include "lua/lua_api.h"
#if defined(SDCARD)
enum ClipboardType {
CLIPBOARD_TYPE_NONE,
CLIPBOARD_TYPE_CUSTOM_SWITCH,
CLIPBOARD_TYPE_CUSTOM_FUNCTION,
CLIPBOARD_TYPE_SD_FILE,
};
#if defined(SIMU)
#define CLIPBOARD_PATH_LEN 1024
#else
#define CLIPBOARD_PATH_LEN 32
#endif
struct Clipboard {
ClipboardType type;
union {
LogicalSwitchData csw;
CustomFunctionData cfn;
struct {
char directory[CLIPBOARD_PATH_LEN];
char filename[CLIPBOARD_PATH_LEN];
} sd;
} data;
};
extern Clipboard clipboard;
#endif
#if defined(INTERNAL_GPS)
#include "gps.h"
#endif
#if defined(SPACEMOUSE)
#include "spacemouse.h"
#endif
#if defined(JACK_DETECT_GPIO)
enum JackMode {
JACK_UNSELECTED_MODE,
JACK_HEADPHONE_MODE,
JACK_TRAINER_MODE,
JACK_MAX_MODE = JACK_TRAINER_MODE
};
#endif
#if defined(IMU)
#include "gyro.h"
#endif
#if defined(DEBUG_LATENCY)
extern uint8_t latencyToggleSwitch;
#endif
inline bool isAsteriskDisplayed()
{
#if defined(ASTERISK) || !defined(WATCHDOG) || defined(LOG_TELEMETRY) || defined(LOG_BLUETOOTH) || defined(DEBUG_LATENCY)
return true;
#endif
return globalData.unexpectedShutdown;
}
#include "module.h"
extern CircularBuffer<uint8_t, 8> luaSetStickySwitchBuffer;
// Radio menu tab state
#if defined(COLORLCD)
extern bool radioThemesEnabled();
#endif
extern bool radioGFEnabled();
extern bool radioTrainerEnabled();
extern bool modelHeliEnabled();
extern bool modelFMEnabled();
extern bool modelCurvesEnabled();
extern bool modelGVEnabled();
extern bool modelLSEnabled();
extern bool modelSFEnabled();
extern bool modelCustomScriptsEnabled();
extern bool modelTelemetryEnabled();