5 * th9x - http://code.google.com/p/th9x
6 * er9x - http://code.google.com/p/er9x
7 * gruvin9x - http://code.google.com/p/gruvin9x
9 * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
28 #include "definitions.h"
29 #include "opentx_types.h"
32 #define SWITCH_SIMU(a, b) (a)
34 #define SWITCH_SIMU(a, b) (b)
38 #define IS_PCBSKY9X true
39 #define CASE_PCBSKY9X(x) x,
41 #define IS_PCBSKY9X false
42 #define CASE_PCBSKY9X(x)
46 #define CASE_CPUARM(x) x,
47 #define IF_CPUARM(x) x
49 #define CASE_CPUARM(x)
54 #define CASE_STM32(x) x,
59 #if defined(VARIO) && defined(CPUARM)
60 #define CASE_VARIO_CPUARM(x) x,
62 #define CASE_VARIO_CPUARM(x)
66 #define CASE_LUA(x) x,
71 #if defined(CPUARM) || defined(CPUM2560)
72 #define CASE_PERSISTENT_TIMERS(x) x,
74 #define CASE_PERSISTENT_TIMERS(x)
78 #define CASE_RTCLOCK(x) x,
80 #define CASE_RTCLOCK(x)
84 #define CASE_BUZZER(x) x,
86 #define CASE_BUZZER(x)
90 #define CASE_AUDIO(x) x,
96 #define CASE_VOICE(x) x,
101 #if defined(PWM_BACKLIGHT)
102 #define CASE_PWM_BACKLIGHT(x) x,
104 #define CASE_PWM_BACKLIGHT(x)
107 #if defined(TELEMETRY_FRSKY) && defined(FRSKY_HUB) && defined(GPS)
108 #define CASE_GPS(x) x,
114 #define CASE_VARIO(x) x,
116 #define CASE_VARIO(x)
120 #define CASE_HAPTIC(x) x,
122 #define CASE_HAPTIC(x)
126 #define CASE_SPLASH(x) x,
128 #define CASE_SPLASH(x)
131 #if defined(TELEMETRY_FRSKY)
132 #define CASE_FRSKY(x) x,
134 #define CASE_FRSKY(x)
137 #if defined(TELEMETRY_MAVLINK)
138 #define CASE_MAVLINK(x) x,
140 #define CASE_MAVLINK(x)
144 #define CASE_PXX(x) x,
150 #define CASE_SDCARD(x) x,
152 #define CASE_SDCARD(x)
155 #if defined(BLUETOOTH) && !(defined(PCBX9E) && !defined(USEHORUSBT))
156 #define CASE_BLUETOOTH(x) x,
158 #define CASE_BLUETOOTH(x)
162 #define CASE_HELI(x) x,
167 #if defined(TEMPLATES)
168 #define CASE_TEMPLATES(x) x,
170 #define CASE_TEMPLATES(x)
173 #if defined(FLIGHT_MODES)
174 #define CASE_FLIGHT_MODES(x) x,
176 #define CASE_FLIGHT_MODES(x)
180 #define CASE_CURVES(x) x,
182 #define CASE_CURVES(x)
186 #define CASE_GVARS(x) x,
188 #define CASE_GVARS(x)
191 #if defined(PCBX9DP) || defined(PCBX9E)
192 #define CASE_PCBX9E_PCBX9DP(x) x,
194 #define CASE_PCBX9E_PCBX9DP(x)
198 #define CASE_PCBX9E(x) x,
200 #define CASE_PCBX9E(x)
203 #if defined(BLUETOOTH) && !(defined(PCBX9E) && !defined(USEHORUSBT))
204 #define CASE_BLUETOOTH(x) x,
206 #define CASE_BLUETOOTH(x)
209 #if defined(PCBSKY9X) && !defined(AR9X) && !defined(REVA)
210 #define TX_CAPACITY_MEASUREMENT
211 #define CASE_CAPACITY(x) x,
213 #define CASE_CAPACITY(x)
216 #if ROTARY_ENCODERS > 0
217 #define ROTARY_ENCODER_NAVIGATION
221 #define IS_FAI_ENABLED() true
222 #define IF_FAI_CHOICE(x)
223 #elif defined(FAI_CHOICE)
224 #define IS_FAI_ENABLED() g_eeGeneral.fai
225 #define IF_FAI_CHOICE(x) x,
227 #define IS_FAI_ENABLED() false
228 #define IF_FAI_CHOICE(x)
231 #define IS_FAI_FORBIDDEN(idx) (IS_FAI_ENABLED() && idx >= MIXSRC_FIRST_TELEM)
233 #if defined(BLUETOOTH)
234 #if defined(X9E) && !defined(USEHORUSBT)
235 #define IS_BLUETOOTH_TRAINER() (g_model.trainerMode == TRAINER_MODE_SLAVE_BLUETOOTH)
236 #define IS_SLAVE_TRAINER() (g_model.trainerMode == TRAINER_MODE_SLAVE)
238 #define IS_BLUETOOTH_TRAINER() (g_model.trainerMode == TRAINER_MODE_MASTER_BLUETOOTH || g_model.trainerMode == TRAINER_MODE_SLAVE_BLUETOOTH)
239 #define IS_SLAVE_TRAINER() (g_model.trainerMode == TRAINER_MODE_SLAVE || g_model.trainerMode == TRAINER_MODE_SLAVE_BLUETOOTH)
242 #define IS_BLUETOOTH_TRAINER() false
243 #define IS_SLAVE_TRAINER() (g_model.trainerMode == TRAINER_MODE_SLAVE)
247 #define MASTER_VOLUME
250 #if !defined(CPUM64) && !defined(ACCURAT_THROTTLE_TIMER)
251 // code cost is about 16 bytes for higher throttle accuracy for timer
252 // would not be noticable anyway, because all version up to this change had only 16 steps;
253 // now it has already 32 steps; this define would increase to 128 steps
254 #if !defined(ACCURAT_THROTTLE_TIMER)
255 #define ACCURAT_THROTTLE_TIMER
259 // 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
260 #define RESX_SHIFT 10
263 #define RESXul 1024ul
268 #if defined(DISK_CACHE)
269 #include "disk_cache.h"
273 #include "targets/simu/simpgmspace.h"
274 #elif defined(CPUARM)
275 typedef const unsigned char pm_uchar
;
276 typedef const char pm_char
;
277 typedef const uint16_t pm_uint16_t
;
278 typedef const uint8_t pm_uint8_t
;
279 typedef const int16_t pm_int16_t
;
280 typedef const int8_t pm_int8_t
;
281 #define pgm_read_byte(address_short) (*(uint8_t*)(address_short))
282 #define PSTR(adr) adr
284 #define pgm_read_adr(x) *(x)
291 #if defined(PCBFLAMENCO)
292 #elif defined(PCBTARANIS) || defined(PCBHORUS)
293 #define SWSRC_THR SWSRC_SF2
294 #define SWSRC_GEA SWSRC_SG2
295 #define SWSRC_ID0 SWSRC_SA0
296 #define SWSRC_ID1 SWSRC_SA1
297 #define SWSRC_ID2 SWSRC_SA2
298 #define IS_MOMENTARY(sw) false // TODO
300 #define SW_DSM2_BIND SW_TRN
303 #define NUM_PSWITCH (SWSRC_LAST_SWITCH-SWSRC_FIRST_SWITCH+1)
305 #include "myeeprom.h"
308 void memclear(void * ptr
, uint8_t size
);
310 #define memclear(p, s) memset(p, 0, s)
313 void memswap(void * a
, void * b
, uint8_t size
);
315 #if defined(PCBX9D) || defined(PCBX9DP) || defined(PCBX9E) || defined(PCBHORUS)
316 #define POT_CONFIG(x) ((g_eeGeneral.potsConfig >> (2*((x)-POT1)))&0x03)
317 #define IS_POT_MULTIPOS(x) (IS_POT(x) && POT_CONFIG(x)==POT_MULTIPOS_SWITCH)
318 #define IS_POT_WITHOUT_DETENT(x) (IS_POT(x) && POT_CONFIG(x)==POT_WITHOUT_DETENT)
319 #define IS_SLIDER_AVAILABLE(x) ((x) == SLIDER1 || (x) == SLIDER2 || (IS_SLIDER(x) && (g_eeGeneral.slidersConfig & (0x01 << ((x)-SLIDER1)))))
320 #define IS_POT_AVAILABLE(x) (IS_POT(x) && POT_CONFIG(x)!=POT_NONE)
321 #define IS_POT_SLIDER_AVAILABLE(x) (IS_POT_AVAILABLE(x) || IS_SLIDER_AVAILABLE(x))
322 #define IS_MULTIPOS_CALIBRATED(cal) (cal->count>0 && cal->count<XPOTS_MULTIPOS_COUNT)
324 #define IS_POT_MULTIPOS(x) (false)
325 #define IS_POT_WITHOUT_DETENT(x) (false)
326 #define IS_POT_SLIDER_AVAILABLE(x) (true)
327 #define IS_MULTIPOS_CALIBRATED(cal) (false)
328 #elif defined(PCBFLAMENCO)
329 #define IS_POT_MULTIPOS(x) (false)
330 #define IS_POT_WITHOUT_DETENT(x) (false)
331 #define IS_POT_SLIDER_AVAILABLE(x) (true)
332 #define IS_MULTIPOS_CALIBRATED(cal) (false)
334 #define IS_POT_MULTIPOS(x) (false)
335 #define IS_POT_WITHOUT_DETENT(x) (true)
336 #define IS_POT_SLIDER_AVAILABLE(x) (true)
337 #define IS_MULTIPOS_CALIBRATED(cal) (false)
340 #if defined(PWR_BUTTON_PRESS)
341 #define pwrOffPressed() pwrPressed()
343 #define pwrOffPressed() (!pwrPressed())
346 #define PWR_PRESS_SHUTDOWN_DELAY 300 // 3s
348 #define GET_LOWRES_POT_POSITION(i) (getValue(MIXSRC_FIRST_POT+(i)) >> 4)
349 #define SAVE_POT_POSITION(i) g_model.potsWarnPosition[i] = GET_LOWRES_POT_POSITION(i)
351 #if ROTARY_ENCODERS > 0
352 #define IF_ROTARY_ENCODERS(x) x,
354 #define IF_ROTARY_ENCODERS(x)
357 #define PPM_CENTER 1500
359 #if defined(PPM_CENTER_ADJUSTABLE)
360 #define PPM_CH_CENTER(ch) (PPM_CENTER + limitAddress(ch)->ppmCenter)
362 #define PPM_CH_CENTER(ch) (PPM_CENTER)
367 #include "io/io_arm.h"
368 // This doesn't need protection on this processor
369 extern volatile tmr10ms_t g_tmr10ms
;
370 #define get_tmr10ms() g_tmr10ms
372 extern volatile tmr10ms_t g_tmr10ms
;
373 extern inline uint16_t get_tmr10ms()
383 #if defined(NAVIGATION_STICKS)
384 extern uint8_t StickScrollAllowed
;
385 extern uint8_t StickScrollTimer
;
386 #define STICK_SCROLL_TIMEOUT 9
387 #define STICK_SCROLL_DISABLE() StickScrollAllowed = 0
389 #define STICK_SCROLL_DISABLE()
397 #include "storage/storage.h"
398 #include "pulses/pulses.h"
401 // Order is the same as in enum Protocols in myeeprom.h (none, ppm, xjt, dsm, crossfire, multi, r9m)
402 static const int8_t maxChannelsModules
[] = { 0, 8, 8, -2, 8, 4, 8}; // relative to 8!
403 static const int8_t maxChannelsXJT
[] = { 0, 8, 0, 4 }; // relative to 8!
404 #define MAX_TRAINER_CHANNELS_M8() (MAX_TRAINER_CHANNELS-8)
407 #if defined(MULTIMODULE)
408 #define IS_MODULE_MULTIMODULE(idx) (idx==EXTERNAL_MODULE && g_model.moduleData[EXTERNAL_MODULE].type==MODULE_TYPE_MULTIMODULE)
410 #define IS_MODULE_MULTIMODULE(idx) (false)
413 #if defined(PCBTARANIS) || defined(PCBHORUS)
414 #if defined(TARANIS_INTERNAL_PPM)
415 #define IS_MODULE_PPM(idx) (idx==TRAINER_MODULE || (idx==INTERNAL_MODULE && g_model.moduleData[INTERNAL_MODULE].type==MODULE_TYPE_PPM)|| (idx==EXTERNAL_MODULE && g_model.moduleData[EXTERNAL_MODULE].type==MODULE_TYPE_PPM))
417 #define IS_MODULE_PPM(idx) (idx==TRAINER_MODULE || (idx==EXTERNAL_MODULE && g_model.moduleData[EXTERNAL_MODULE].type==MODULE_TYPE_PPM))
419 #define IS_MODULE_XJT(idx) (g_model.moduleData[idx].type==MODULE_TYPE_XJT)
421 #define IS_MODULE_DSM2(idx) (idx==EXTERNAL_MODULE && g_model.moduleData[EXTERNAL_MODULE].type==MODULE_TYPE_DSM2)
423 #define IS_MODULE_DSM2(idx) (false)
425 #if defined(CROSSFIRE)
426 #define IS_MODULE_CROSSFIRE(idx) (idx==EXTERNAL_MODULE && g_model.moduleData[EXTERNAL_MODULE].type==MODULE_TYPE_CROSSFIRE)
428 #define IS_MODULE_CROSSFIRE(idx) (false)
430 #if defined(TARANIS_INTERNAL_PPM)
431 #define MAX_INTERNAL_MODULE_CHANNELS() ((g_model.moduleData[INTERNAL_MODULE].type == MODULE_TYPE_XJT) ? maxChannelsXJT[1+g_model.moduleData[0].rfProtocol] : maxChannelsModules[g_model.moduleData[INTERNAL_MODULE].type])
433 #define MAX_INTERNAL_MODULE_CHANNELS() (maxChannelsXJT[1+g_model.moduleData[INTERNAL_MODULE].rfProtocol])
435 #define MAX_EXTERNAL_MODULE_CHANNELS() ((g_model.moduleData[EXTERNAL_MODULE].type == MODULE_TYPE_XJT) ? maxChannelsXJT[1+g_model.moduleData[1].rfProtocol] : maxChannelsModules[g_model.moduleData[EXTERNAL_MODULE].type])
436 #define MAX_CHANNELS(idx) (idx==INTERNAL_MODULE ? MAX_INTERNAL_MODULE_CHANNELS() : (idx==EXTERNAL_MODULE ? MAX_EXTERNAL_MODULE_CHANNELS() : MAX_TRAINER_CHANNELS_M8()))
437 #define NUM_CHANNELS(idx) ((IS_MODULE_CROSSFIRE(idx) || (IS_MODULE_MULTIMODULE(idx) && (g_model.moduleData[idx].getMultiProtocol(true) != MM_RF_PROTO_DSM2))) ? CROSSFIRE_CHANNELS_COUNT : (8+g_model.moduleData[idx].channelsCount))
438 #elif defined(PCBSKY9X) && !defined(REVA)
439 #define IS_MODULE_PPM(idx) (idx==TRAINER_MODULE || idx==EXTRA_MODULE || (idx==EXTERNAL_MODULE && g_model.moduleData[EXTERNAL_MODULE].type==MODULE_TYPE_PPM))
440 #define IS_MODULE_XJT(idx) (idx==EXTERNAL_MODULE && g_model.moduleData[EXTERNAL_MODULE].type==MODULE_TYPE_XJT)
441 #define IS_MODULE_DSM2(idx) (idx==EXTERNAL_MODULE && g_model.moduleData[EXTERNAL_MODULE].type==MODULE_TYPE_DSM2)
442 #define MAX_EXTERNAL_MODULE_CHANNELS() ((g_model.moduleData[EXTERNAL_MODULE].type == MODULE_TYPE_XJT) ? maxChannelsXJT[1+g_model.moduleData[0].rfProtocol] : maxChannelsModules[g_model.moduleData[EXTERNAL_MODULE].type])
443 #define MAX_EXTRA_MODULE_CHANNELS() (8) // Only PPM (16ch PPM)
444 #define MAX_CHANNELS(idx) (idx==EXTERNAL_MODULE ? MAX_EXTERNAL_MODULE_CHANNELS() : (idx==EXTRA_MODULE ? MAX_EXTRA_MODULE_CHANNELS() : MAX_TRAINER_CHANNELS_M8()))
445 #define NUM_CHANNELS(idx) (8+g_model.moduleData[idx].channelsCount)
446 #define IS_MODULE_CROSSFIRE(idx) (false)
448 #define IS_MODULE_PPM(idx) (idx==TRAINER_MODULE || (idx==EXTERNAL_MODULE && g_model.moduleData[EXTERNAL_MODULE].type==MODULE_TYPE_PPM))
449 #define IS_MODULE_XJT(idx) (idx==EXTERNAL_MODULE && g_model.moduleData[EXTERNAL_MODULE].type==MODULE_TYPE_XJT)
450 #define IS_MODULE_DSM2(idx) (idx==EXTERNAL_MODULE && g_model.moduleData[EXTERNAL_MODULE].type==MODULE_TYPE_DSM2)
451 #define MAX_EXTERNAL_MODULE_CHANNELS() ((g_model.moduleData[EXTERNAL_MODULE].type == MODULE_TYPE_XJT) ? maxChannelsXJT[1+g_model.moduleData[EXTERNAL_MODULE].rfProtocol] : maxChannelsModules[g_model.moduleData[EXTERNAL_MODULE].type])
452 #define MAX_CHANNELS(idx) (idx==EXTERNAL_MODULE ? MAX_EXTERNAL_MODULE_CHANNELS() : MAX_TRAINER_CHANNELS_M8())
453 #define NUM_CHANNELS(idx) (8+g_model.moduleData[idx].channelsCount)
455 #define IS_MODULE_R9M(idx) (g_model.moduleData[idx].type==MODULE_TYPE_R9M)
456 #define IS_MODULE_PXX(idx) (IS_MODULE_XJT(idx) || IS_MODULE_R9M(idx))
459 #if defined(MULTIMODULE)
460 #define IS_MULTIMODULE_DSM(idx) (IS_MODULE_MULTIMODULE(idx) && g_model.moduleData[idx].getMultiProtocol(true) == MM_RF_PROTO_DSM2)
461 #define DEFAULT_CHANNELS(idx) (IS_MODULE_PPM(idx) ? 0 : IS_MULTIMODULE_DSM(idx) ? -1 : MAX_CHANNELS(idx))
463 #define DEFAULT_CHANNELS(idx) (IS_MODULE_PPM(idx) ? 0 : MAX_CHANNELS(idx))
467 #define MASK_CFN_TYPE uint64_t // current max = 64 function switches
468 #define MASK_FUNC_TYPE uint32_t // current max = 32 functions
469 #elif defined(CPUM64)
470 #define MASK_CFN_TYPE uint16_t // current max = 16 function switches
471 #define MASK_FUNC_TYPE uint8_t // current max = 8 functions
473 #define MASK_CFN_TYPE uint32_t // current max = 32 function switches
474 #define MASK_FUNC_TYPE uint8_t // current max = 8 functions
478 MASK_FUNC_TYPE activeFunctions
;
479 MASK_CFN_TYPE activeSwitches
;
480 tmr10ms_t lastFunctionTime
[MAX_SPECIAL_FUNCTIONS
];
482 inline bool isFunctionActive(uint8_t func
)
484 return activeFunctions
& ((MASK_FUNC_TYPE
)1 << func
);
489 memclear(this, sizeof(*this));
491 } CustomFunctionsContext
;
493 #include "strhelpers.h"
496 #if defined(TEMPLATES)
497 #include "templates.h"
502 #if !defined(CPUARM) || !defined(DEBUG)
503 #define printf printf_not_allowed
507 extern const pm_uint8_t bchout_ar
[];
508 extern const pm_uint8_t modn12x3
[];
510 //convert from mode 1 to mode stickMode
511 //NOTICE! => 0..3 -> 0..3
516 #define CONVERT_MODE(x) (((x)<=AIL_STICK) ? pgm_read_byte(modn12x3 + 4*g_eeGeneral.stickMode + (x)) : (x) )
518 extern uint8_t channel_order(uint8_t x
);
520 #define THRCHK_DEADBAND 16
522 #if defined(COLORLCD)
523 #define SPLASH_NEEDED() (false)
524 #elif defined(PCBTARANIS)
525 #define SPLASH_NEEDED() (g_eeGeneral.splashMode != 3)
526 #elif defined(CPUARM)
527 #define SPLASH_NEEDED() (g_model.moduleData[EXTERNAL_MODULE].type != MODULE_TYPE_DSM2 && !g_eeGeneral.splashMode)
529 #define SPLASH_NEEDED() (!IS_DSM2_PROTOCOL(g_model.protocol) && !g_eeGeneral.splashMode)
532 #if defined(PCBHORUS)
533 #define SPLASH_TIMEOUT 0 /* we use the splash duration to load stuff from the SD */
534 #elif defined(FSPLASH)
535 #define SPLASH_TIMEOUT (g_eeGeneral.splashMode == 0 ? 60000/*infinite=10mn*/ : ((4*100) * (g_eeGeneral.splashMode & 0x03)))
536 #elif defined(PCBTARANIS) || defined(PCBFLAMENCO)
537 #define SPLASH_TIMEOUT (g_eeGeneral.splashMode==-4 ? 1500 : (g_eeGeneral.splashMode<=0 ? (400-g_eeGeneral.splashMode*200) : (400-g_eeGeneral.splashMode*100)))
539 #define SPLASH_TIMEOUT (4*100) // 4 seconds
542 #if defined(ROTARY_ENCODERS)
543 #define IS_ROTARY_ENCODER_NAVIGATION_ENABLE() g_eeGeneral.reNavigation
544 extern volatile rotenc_t rotencValue
[ROTARY_ENCODERS
];
545 #define ROTARY_ENCODER_NAVIGATION_VALUE rotencValue[g_eeGeneral.reNavigation - 1]
546 #elif defined(ROTARY_ENCODER_NAVIGATION)
547 #define IS_ROTARY_ENCODER_NAVIGATION_ENABLE() true
548 extern volatile rotenc_t rotencValue
[1];
549 #define ROTARY_ENCODER_NAVIGATION_VALUE rotencValue[0]
552 #if defined(CPUARM) && defined(ROTARY_ENCODER_NAVIGATION)
553 extern uint8_t rotencSpeed
;
554 #define ROTENC_LOWSPEED 1
555 #define ROTENC_MIDSPEED 5
556 #define ROTENC_HIGHSPEED 50
557 #define ROTENC_DELAY_MIDSPEED 32
558 #define ROTENC_DELAY_HIGHSPEED 16
561 #define HEART_TIMER_10MS 1
562 #define HEART_TIMER_PULSES 2 // when multiple modules this is the first one
563 #if defined(PCBTARANIS) || defined(PCBFLAMENCO) || defined(PCBHORUS)
564 #define HEART_WDT_CHECK (HEART_TIMER_10MS + (HEART_TIMER_PULSES << 0) + (HEART_TIMER_PULSES << 1))
566 #define HEART_WDT_CHECK (HEART_TIMER_10MS + HEART_TIMER_PULSES)
568 extern uint8_t heartbeat
;
570 #if defined(CPUARM) && !defined(BOOT)
571 void watchdogSuspend(uint32_t timeout
);
572 #define WATCHDOG_SUSPEND(x) watchdogSuspend(x)
574 #define WATCHDOG_SUSPEND(...)
577 #define MAX_ALERT_TIME 60
585 extern struct t_inactivity inactivity
;
587 #define LEN_STD_CHARS 40
589 #if defined(TRANSLATIONS_CZ)
590 #define ZCHAR_MAX (LEN_STD_CHARS)
592 #define ZCHAR_MAX (LEN_STD_CHARS + LEN_SPECIAL_CHARS)
595 char hex2zchar(uint8_t hex
);
596 char idx2char(int8_t idx
);
597 #if defined(CPUARM) || defined(SIMU)
598 int8_t char2idx(char c
);
599 void str2zchar(char *dest
, const char *src
, int size
);
600 int zchar2str(char *dest
, const char *src
, int size
);
606 #if defined(PCBTARANIS) || defined(PCBFLAMENCO) || defined(PCBHORUS)
607 div_t switchInfo(int switchPosition
);
608 extern uint8_t potsPos
[NUM_XPOTS
];
611 #if defined(PCBHORUS)
612 uint16_t trimDown(uint16_t idx
); // TODO why?
614 uint8_t trimDown(uint8_t idx
);
616 void readKeysAndTrims();
618 uint16_t evalChkSum();
621 #define RAISE_ALERT(...)
624 #define RAISE_ALERT(title, msg, info, sound) showAlertBox(title, msg, info, sound)
625 #define ALERT(title, msg, sound) alert(title, msg, sound)
627 #define RAISE_ALERT(title, msg, info, sound) showAlertBox(title, msg, info)
628 #define ALERT(title, msg, sound) alert(title, msg)
631 void alert(const pm_char
* t
, const pm_char
* s ALERT_SOUND_ARG
);
634 e_perout_mode_normal
= 0,
635 e_perout_mode_inactive_flight_mode
= 1,
636 e_perout_mode_notrainer
= 2,
637 e_perout_mode_notrims
= 4,
638 e_perout_mode_nosticks
= 8,
639 e_perout_mode_noinput
= e_perout_mode_notrainer
+e_perout_mode_notrims
+e_perout_mode_nosticks
643 #if defined(MODULE_ALWAYS_SEND_PULSES)
644 extern uint8_t startupWarningState
;
646 enum StartupWarningStates
{
647 STARTUP_WARNING_THROTTLE
,
648 STARTUP_WARNING_SWITCHES
,
649 STARTUP_WARNING_DONE
,
654 // Fiddle to force compiler to use a pointer
655 #if defined(CPUARM) || defined(SIMU)
656 #define FORCE_INDIRECT(ptr)
658 #define FORCE_INDIRECT(ptr) __asm__ __volatile__ ("" : "=e" (ptr) : "0" (ptr))
661 extern uint8_t mixerCurrentFlightMode
;
662 extern uint8_t lastFlightMode
;
663 extern uint8_t flightModeTransitionLast
;
666 #define bitfield_channels_t uint32_t
668 #define bitfield_channels_t uint16_t
672 inline int availableMemory() { return 1000; }
673 #elif defined(CPUARM) && !defined(SIMU)
674 extern unsigned char *heap
;
677 extern int _main_stack_start
;
678 extern int _heap_end
;
679 #define availableMemory() ((unsigned int)((unsigned char *)&_heap_end - heap))
682 void evalFlightModeMixes(uint8_t mode
, uint8_t tick10ms
);
683 void evalMixes(uint8_t tick10ms
);
684 void doMixerCalculations();
685 void scheduleNextMixerCalculation(uint8_t module
, uint16_t delay
);
691 NOINLINE
void per10ms();
693 getvalue_t
getValue(mixsrc_t i
);
696 #define GETSWITCH_MIDPOS_DELAY 1
697 bool getSwitch(swsrc_t swtch
, uint8_t flags
=0);
699 bool getSwitch(swsrc_t swtch
);
702 void logicalSwitchesTimerTick();
703 void logicalSwitchesReset();
706 void evalLogicalSwitches(bool isCurrentPhase
=true);
707 void logicalSwitchesCopyState(uint8_t src
, uint8_t dst
);
708 #define LS_RECURSIVE_EVALUATION_RESET()
710 #define evalLogicalSwitches(xxx)
711 #define GETSWITCH_RECURSIVE_TYPE uint16_t
712 extern volatile GETSWITCH_RECURSIVE_TYPE s_last_switch_used
;
713 extern volatile GETSWITCH_RECURSIVE_TYPE s_last_switch_value
;
714 #define LS_RECURSIVE_EVALUATION_RESET() s_last_switch_used = 0
717 #if defined(PCBTARANIS) || defined(PCBFLAMENCO) || defined(PCBHORUS)
718 void getSwitchesPosition(bool startup
);
720 #define getSwitchesPosition(...)
723 extern swarnstate_t switches_states
;
724 swsrc_t
getMovedSwitch();
727 #define GET_MOVED_SOURCE_PARAMS uint8_t min
728 int8_t getMovedSource(GET_MOVED_SOURCE_PARAMS
);
729 #define GET_MOVED_SOURCE(min, max) getMovedSource(min)
731 #define GET_MOVED_SOURCE_PARAMS
732 int8_t getMovedSource();
733 #define GET_MOVED_SOURCE(min, max) getMovedSource()
736 #if defined(FLIGHT_MODES)
737 extern uint8_t getFlightMode();
739 #define getFlightMode() 0
743 uint8_t getTrimFlightMode(uint8_t phase
, uint8_t idx
);
745 #define getTrimFlightMode(phase, idx) (phase)
749 extern int8_t trimGvar
[NUM_STICKS
+NUM_AUX_TRIMS
];
750 #define TRIM_REUSED(idx) trimGvar[idx] >= 0
752 #define TRIM_REUSED(idx) 0
755 trim_t
getRawTrimValue(uint8_t phase
, uint8_t idx
);
756 int getTrimValue(uint8_t phase
, uint8_t idx
);
759 bool setTrimValue(uint8_t phase
, uint8_t idx
, int trim
);
761 void setTrimValue(uint8_t phase
, uint8_t idx
, int trim
);
764 #if defined(ROTARY_ENCODERS)
765 int16_t getRotaryEncoder(uint8_t idx
);
766 void incRotaryEncoder(uint8_t idx
, int8_t inc
);
769 #if defined(PCBGRUVIN9X) || defined(PCBMEGA2560)
770 #define ROTARY_ENCODER_GRANULARITY (1)
771 #elif defined(PCBSKY9X)
772 #define ROTARY_ENCODER_GRANULARITY (2 << g_eeGeneral.rotarySteps)
774 #define ROTARY_ENCODER_GRANULARITY (2)
779 extern uint16_t sessionTimer
;
780 extern uint16_t s_timeCumThr
;
781 extern uint16_t s_timeCum16ThrP
;
783 #if defined(OVERRIDE_CHANNEL_FUNCTION)
785 #define OVERRIDE_CHANNEL_UNDEFINED -4096
787 #define OVERRIDE_CHANNEL_UNDEFINED -128
789 extern safetych_t safetyCh
[MAX_OUTPUT_CHANNELS
];
792 extern uint8_t trimsCheckTimer
;
795 extern uint8_t trimsDisplayTimer
;
796 extern uint8_t trimsDisplayMask
;
799 void flightReset(uint8_t check
=true);
801 extern uint8_t unexpectedShutdown
;
803 extern uint16_t maxMixerDuration
;
806 extern uint8_t g_tmr1Latency_max
;
807 extern uint8_t g_tmr1Latency_min
;
808 extern uint16_t lastMixerDuration
;
812 #define DURATION_MS_PREC2(x) ((x)/20)
814 #define DURATION_MS_PREC2(x) ((x)*100)/16
817 #if defined(THRTRACE)
818 #if defined(COLORLCD)
819 #define MAXTRACE (LCD_W-2*10)
821 #define MAXTRACE (LCD_W - 8)
823 extern uint8_t s_traceBuf
[MAXTRACE
];
824 extern uint16_t s_traceWr
;
825 extern uint8_t s_cnt_10s
;
826 extern uint16_t s_cnt_samples_thr_10s
;
827 extern uint16_t s_sum_samples_thr_10s
;
828 #define RESET_THR_TRACE() s_traceWr = s_cnt_10s = s_cnt_samples_thr_10s = s_sum_samples_thr_10s = s_timeCum16ThrP = s_timeCumThr = 0
830 #define RESET_THR_TRACE() s_timeCum16ThrP = s_timeCumThr = 0
834 uint16_t getTmr2MHz();
835 uint16_t getTmr16KHz();
837 static inline uint16_t getTmr2MHz() { return TIMER_2MHz_TIMER
->CNT
; }
838 #elif defined(PCBSKY9X)
839 static inline uint16_t getTmr2MHz() { return TC1
->TC_CHANNEL
[0].TC_CV
; }
841 uint16_t getTmr16KHz();
845 uint16_t stackAvailable();
853 extern bool readonly
;
854 extern bool readonlyUnlocked();
855 #define READ_ONLY() readonly
856 #define READ_ONLY_UNLOCKED() readonlyUnlocked()
858 #define READ_ONLY() false
859 #define READ_ONLY_UNLOCKED() true
862 void checkLowEEPROM();
864 void checkSwitches();
871 #define GET_ADC_IF_MIXER_NOT_RUNNING() do { if (s_pulses_paused) getADC(); } while(0)
873 #define GET_ADC_IF_MIXER_NOT_RUNNING() getADC()
882 void checkBacklight();
883 void doLoopCommonActions();
885 #define BITMASK(bit) (1<<(bit))
888 #define UNUSED(x) ((void)(x)) /* to avoid warnings */
891 /// returns the number of elements of an array
892 #define DIM(arr) (sizeof((arr))/sizeof((arr)[0]))
894 template<class t
> FORCEINLINE t
min(t a
, t b
) { return a
<b
?a
:b
; }
895 template<class t
> FORCEINLINE t
max(t a
, t b
) { return a
>b
?a
:b
; }
896 template<class t
> FORCEINLINE t
sgn(t a
) { return a
>0 ? 1 : (a
< 0 ? -1 : 0); }
897 template<class t
> FORCEINLINE t
limit(t mi
, t x
, t ma
) { return min(max(mi
,x
),ma
); }
898 template<class t
> void SWAP(t
& a
, t
& b
) { t tmp
= b
; b
= a
; a
= tmp
; }
900 uint16_t isqrt32(uint32_t n
);
902 #if defined(CPUARM) && !defined(BOOT)
903 #include "tasks_arm.h"
904 extern OS_MutexID mixerMutex
;
905 inline void pauseMixerCalculations()
907 CoEnterMutexSection(mixerMutex
);
910 inline void resumeMixerCalculations()
912 CoLeaveMutexSection(mixerMutex
);
915 #define pauseMixerCalculations()
916 #define resumeMixerCalculations()
919 void generalDefault();
920 void modelDefault(uint8_t id
);
923 void checkModelIdUnique(uint8_t index
, uint8_t module
);
927 uint32_t hash(const void * ptr
, uint32_t size
);
928 inline int divRoundClosest(const int n
, const int d
)
933 return ((n
< 0) ^ (d
< 0)) ? ((n
- d
/2)/d
) : ((n
+ d
/2)/d
);
936 #define calc100to256_16Bits(x) calc100to256(x)
937 #define calc100toRESX_16Bits(x) calc100toRESX(x)
939 inline int calc100to256(int x
)
941 return divRoundClosest(x
*256, 100);
944 inline int calc100toRESX(int x
)
946 return divRoundClosest(x
*RESX
, 100);
949 inline int calc1000toRESX(int x
)
951 return divRoundClosest(x
*RESX
, 1000);
954 inline int calcRESXto1000(int x
)
956 return divRoundClosest(x
*1000, RESX
);
959 inline int calcRESXto100(int x
)
961 return divRoundClosest(x
*100, RESX
);
965 extern int16_t calc100to256_16Bits(int16_t x
); // @@@2 open.20.fsguruh: return x*2.56
966 extern int16_t calc100to256(int8_t x
); // @@@2 open.20.fsguruh: return x*2.56
967 extern int16_t calc100toRESX_16Bits(int16_t x
); // @@@ open.20.fsguruh
968 extern int16_t calc100toRESX(int8_t x
);
969 extern int16_t calc1000toRESX(int16_t x
);
970 extern int16_t calcRESXto1000(int16_t x
);
971 extern int8_t calcRESXto100(int16_t x
);
974 #if defined(COLORLCD)
975 extern const char vers_stamp
[];
976 extern const char date_stamp
[];
977 extern const char time_stamp
[];
978 extern const char eeprom_stamp
[];
980 extern const char vers_stamp
[];
983 extern uint8_t g_vbat100mV
;
985 #define GET_TXBATT_BARS() (limit<int8_t>(0, div_and_round(10 * (g_vbat100mV - g_eeGeneral.vBatMin - 90), 30 + g_eeGeneral.vBatMax - g_eeGeneral.vBatMin), 10))
987 #define GET_TXBATT_BARS() (limit<int8_t>(2, 20 * (g_vbat100mV - g_eeGeneral.vBatMin - 90) / (30 + g_eeGeneral.vBatMax - g_eeGeneral.vBatMin), 20))
989 #define IS_TXBATT_WARNING() (g_vbat100mV <= g_eeGeneral.vBatWarn)
992 #define g_blinkTmr10ms (*(uint8_t*)&g_tmr10ms)
993 extern uint8_t g_beepCnt
;
994 extern uint8_t g_beepVal
[5];
996 #include "trainer_input.h"
998 extern int32_t chans
[MAX_OUTPUT_CHANNELS
];
999 extern int16_t ex_chans
[MAX_OUTPUT_CHANNELS
]; // Outputs (before LIMITS) of the last perMain
1000 extern int16_t channelOutputs
[MAX_OUTPUT_CHANNELS
];
1001 extern uint16_t BandGap
;
1004 #define NUM_INPUTS (MAX_INPUTS)
1006 #define NUM_INPUTS (NUM_STICKS)
1009 int expo(int x
, int k
);
1012 inline int getMaximumValue(int source
)
1014 if (source
< MIXSRC_FIRST_CH
)
1016 else if (source
<= MIXSRC_LAST_CH
)
1017 return g_model
.extendedLimits
? 150 : 100;
1018 else if (source
>= MIXSRC_FIRST_TIMER
&& source
<= MIXSRC_LAST_TIMER
)
1036 int8_t * curveAddress(uint8_t idx
);
1042 point_t
getPoint(uint8_t i
);
1043 #if !defined(CURVES)
1044 #define LOAD_MODEL_CURVES()
1045 #define applyCurve(x, idx) (x)
1046 #elif defined(CPUARM)
1047 typedef CurveData CurveInfo
;
1049 #define LOAD_MODEL_CURVES() loadCurves()
1050 int intpol(int x
, uint8_t idx
);
1051 int applyCurve(int x
, CurveRef
& curve
);
1052 int applyCustomCurve(int x
, uint8_t idx
);
1053 int applyCurrentCurve(int x
);
1054 int8_t getCurveX(int noPoints
, int point
);
1055 void resetCustomCurveX(int8_t * points
, int noPoints
);
1056 bool moveCurve(uint8_t index
, int8_t shift
); // TODO bool?
1063 CurveInfo
curveInfo(uint8_t idx
);
1064 int intpol(int x
, uint8_t idx
);
1065 int applyCurve(int x
, int8_t idx
);
1066 #define LOAD_MODEL_CURVES()
1067 #define applyCustomCurve(x, idx) intpol(x, idx)
1068 int applyCurrentCurve(int x
);
1069 bool moveCurve(uint8_t index
, int8_t shift
, int8_t custom
=0);
1073 #define APPLY_EXPOS_EXTRA_PARAMS_INC , uint8_t ovwrIdx=0, int16_t ovwrValue=0
1074 #define APPLY_EXPOS_EXTRA_PARAMS , uint8_t ovwrIdx, int16_t ovwrValue
1076 #define APPLY_EXPOS_EXTRA_PARAMS_INC
1077 #define APPLY_EXPOS_EXTRA_PARAMS
1082 void defaultInputs();
1085 void applyExpos(int16_t * anas
, uint8_t mode APPLY_EXPOS_EXTRA_PARAMS_INC
);
1086 int16_t applyLimits(uint8_t channel
, int32_t value
);
1088 void evalInputs(uint8_t mode
);
1089 uint16_t anaIn(uint8_t chan
);
1091 extern int16_t calibratedAnalogs
[NUM_CALIBRATED_ANALOGS
];
1093 #define FLASH_DURATION 20 /*200ms*/
1095 extern uint8_t beepAgain
;
1096 extern uint16_t lightOffCounter
;
1097 extern uint8_t flashCounter
;
1098 extern uint8_t mixWarning
;
1100 FlightModeData
* flightModeAddress(uint8_t idx
);
1101 ExpoData
* expoAddress(uint8_t idx
);
1102 MixData
* mixAddress(uint8_t idx
);
1103 LimitData
* limitAddress(uint8_t idx
);
1104 LogicalSwitchData
* lswAddress(uint8_t idx
);
1106 // static variables used in evalFlightModeMixes - moved here so they don't interfere with the stack
1107 // It's also easier to initialize them here.
1109 extern int8_t virtualInputsTrims
[NUM_INPUTS
];
1111 extern int16_t rawAnas
[NUM_INPUTS
];
1114 extern int16_t anas
[NUM_INPUTS
];
1115 extern int16_t trims
[NUM_STICKS
+NUM_AUX_TRIMS
];
1116 extern BeepANACenter bpanaCenter
;
1118 extern uint8_t s_mixer_first_run_done
;
1120 void applyDefaultTemplate();
1122 void incSubtrim(uint8_t idx
, int16_t inc
);
1125 void copyTrimsToOffset(uint8_t ch
);
1126 void copySticksToOffset(uint8_t ch
);
1127 void moveTrimsToOffsets();
1130 #define ACTIVE_PHASES_TYPE uint16_t
1131 #define DELAY_POS_SHIFT 0
1132 #define DELAY_POS_MARGIN 3
1133 #define delayval_t int16_t
1134 PACK(typedef struct {
1136 int16_t now
; // timer trigger source -> off, abs, stk, stk%, sw/!sw, !m_sw/!m_sw
1142 #define ACTIVE_PHASES_TYPE uint8_t
1143 #define DELAY_POS_SHIFT 10
1144 #define DELAY_POS_MARGIN 0
1145 #define delayval_t int8_t
1146 PACK(typedef struct {
1148 int16_t now
:2; // timer trigger source -> off, abs, stk, stk%, sw/!sw, !m_sw/!m_sw
1150 int16_t activeMix
:1;
1151 int16_t activeExpo
:1;
1155 extern SwOn swOn
[MAX_MIXERS
];
1156 extern int24_t act
[MAX_MIXERS
];
1158 #if defined(BOLD_FONT)
1159 inline bool isExpoActive(uint8_t expo
)
1161 return swOn
[expo
].activeExpo
;
1164 inline bool isMixActive(uint8_t mix
)
1166 return swOn
[mix
].activeMix
;
1169 #define isExpoActive(x) false
1170 #define isMixActive(x) false
1173 enum LogicalSwitchFamilies
{
1184 uint8_t lswFamily(uint8_t func
);
1185 int16_t lswTimerValue(delayval_t val
);
1187 enum FunctionsActive
{
1189 FUNCTION_INSTANT_TRIM
= FUNCTION_TRAINER
+4,
1196 FUNCTION_BACKGND_MUSIC
,
1197 FUNCTION_BACKGND_MUSIC_PAUSE
,
1201 #define VARIO_FREQUENCY_ZERO 700/*Hz*/
1202 #define VARIO_FREQUENCY_RANGE 1000/*Hz*/
1203 #define VARIO_REPEAT_ZERO 500/*ms*/
1204 #define VARIO_REPEAT_MAX 80/*ms*/
1207 extern CustomFunctionsContext modelFunctionsContext
;
1208 extern CustomFunctionsContext globalFunctionsContext
;
1209 inline bool isFunctionActive(uint8_t func
)
1211 return globalFunctionsContext
.isFunctionActive(func
) || modelFunctionsContext
.isFunctionActive(func
);
1213 void evalFunctions(const CustomFunctionData
* functions
, CustomFunctionsContext
& functionsContext
);
1214 inline void customFunctionsReset()
1216 globalFunctionsContext
.reset();
1217 modelFunctionsContext
.reset();
1220 extern CustomFunctionsContext modelFunctionsContext
;
1221 #define isFunctionActive(func) modelFunctionsContext.isFunctionActive(func)
1222 void evalFunctions();
1223 #define customFunctionsReset() modelFunctionsContext.reset()
1226 #include "telemetry/telemetry.h"
1229 uint8_t crc8(const uint8_t * ptr
, uint32_t len
);
1230 uint16_t crc16(const uint8_t * ptr
, uint32_t len
);
1233 #define PLAY_REPEAT(x) (x) /* Range 0 to 15 */
1234 #define PLAY_NOW 0x10
1235 #define PLAY_BACKGROUND 0x20
1236 #define PLAY_INCREMENT(x) ((uint8_t)(((uint8_t)x) << 6)) /* -1, 0, 1, 2 */
1261 AU_MODEL_STILL_POWERED
,
1263 #if defined(PCBSKY9X)
1282 #if defined(PCBTARANIS) || defined(PCBFLAMENCO) || defined(PCBHORUS)
1291 #elif defined(CPUARM)
1307 AU_SPECIAL_SOUND_FIRST
,
1308 AU_SPECIAL_SOUND_BEEP1
= AU_SPECIAL_SOUND_FIRST
,
1309 AU_SPECIAL_SOUND_BEEP2
,
1310 AU_SPECIAL_SOUND_BEEP3
,
1311 AU_SPECIAL_SOUND_WARN1
,
1312 AU_SPECIAL_SOUND_WARN2
,
1313 AU_SPECIAL_SOUND_CHEEP
,
1314 AU_SPECIAL_SOUND_RATATA
,
1315 AU_SPECIAL_SOUND_TICK
,
1316 AU_SPECIAL_SOUND_SIREN
,
1317 AU_SPECIAL_SOUND_RING
,
1318 AU_SPECIAL_SOUND_SCIFI
,
1319 AU_SPECIAL_SOUND_ROBOT
,
1320 AU_SPECIAL_SOUND_CHIRP
,
1321 AU_SPECIAL_SOUND_TADA
,
1322 AU_SPECIAL_SOUND_CRICKET
,
1323 AU_SPECIAL_SOUND_ALARMC
,
1324 AU_SPECIAL_SOUND_LAST
,
1331 #include "audio_arm.h"
1333 #include "audio_avr.h"
1339 #if defined(PCBSTD) && defined(VOICE)
1340 #include "targets/9x/voice.h"
1343 #if defined(PCBGRUVIN9X) && defined(VOICE)
1344 #include "targets/gruvin9x/voice.h"
1347 #if defined(PCBMEGA2560) && defined(VOICE)
1348 #include "targets/mega2560/voice.h"
1351 #include "translations.h"
1362 #if defined(RTCLOCK)
1372 extern uint8_t requiredSpeakerVolume
;
1378 REQUEST_FLIGHT_RESET
,
1381 extern uint8_t mainRequestFlags
;
1384 void checkBattery();
1385 void opentxClose(uint8_t shutdown
=true);
1387 void opentxResume();
1389 #if defined(PCBHORUS) || defined(PCBX7)
1390 #define LED_ERROR_BEGIN() ledRed()
1391 #define LED_ERROR_END() ledBlue()
1393 #define LED_ERROR_BEGIN()
1394 #define LED_ERROR_END()
1397 // Re-useable byte array to save having multiple buffers
1399 #define SD_SCREEN_FILE_LENGTH 32
1401 #define SD_SCREEN_FILE_LENGTH 64
1403 union ReusableBuffer
1408 #if !defined(CPUARM)
1409 char listnames
[NUM_BODY_LINES
][LEN_MODEL_NAME
];
1411 #if defined(EEPROM_RLC) && LCD_W < 212
1412 uint16_t eepromfree
;
1415 char menu_bss
[POPUP_MENU_MAX_LINES
][MENU_LINE_LENGTH
];
1416 char mainname
[45]; // because reused for SD backup / restore, max backup filename 44 chars: "/MODELS/MODEL0134353-2014-06-19-04-51-27.bin"
1418 char mainname
[LEN_MODEL_NAME
];
1424 } msgbuf
; // used in modelsel and modelsetup (only in a warning message)
1429 int16_t midVals
[NUM_STICKS
+NUM_POTS
+NUM_SLIDERS
+NUM_MOUSE_ANALOGS
];
1430 int16_t loVals
[NUM_STICKS
+NUM_POTS
+NUM_SLIDERS
+NUM_MOUSE_ANALOGS
];
1431 int16_t hiVals
[NUM_STICKS
+NUM_POTS
+NUM_SLIDERS
+NUM_MOUSE_ANALOGS
];
1433 #if defined(PCBTARANIS) || defined(PCBFLAMENCO) || defined(PCBHORUS)
1436 int16_t steps
[XPOTS_MULTIPOS_COUNT
];
1438 int16_t lastPosition
;
1439 } xpotsCalib
[NUM_XPOTS
];
1447 char lines
[NUM_BODY_LINES
][SD_SCREEN_FILE_LENGTH
+1+1]; // the last char is used to store the flags (directory) of the line
1451 char originalName
[SD_SCREEN_FILE_LENGTH
+1];
1467 extern union ReusableBuffer reusableBuffer
;
1469 void checkFlashOnBeep();
1472 uint8_t zlen(const char *str
, uint8_t size
);
1473 bool zexist(const char *str
, uint8_t size
);
1474 unsigned int effectiveLen(const char * str
, unsigned int size
);
1475 char * strcat_zchar(char *dest
, const char *name
, uint8_t size
, const char *defaultName
=NULL
, uint8_t defaultNameSize
=0, uint8_t defaultIdx
=0);
1476 #define strcat_phasename(dest, idx) strcat_zchar(dest, g_model.flightModeData[idx].name, LEN_FLIGHT_MODE_NAME, STR_FP, PSIZE(TR_FP), idx+1)
1478 #define strcat_modelname(dest, idx) strcat_zchar(dest, modelHeaders[idx].name, LEN_MODEL_NAME, STR_MODEL, PSIZE(TR_MODEL), idx+1)
1479 #define strcat_currentmodelname(dest) strcat_modelname(dest, g_eeGeneral.currModel)
1481 #define strcat_currentmodelname(dest) strcat_zchar(dest, g_model.header.name, LEN_MODEL_NAME)
1483 #define ZLEN(s) zlen(s, sizeof(s))
1484 #define ZEXIST(s) zexist(s, sizeof(s))
1487 // Stick tolerance varies between transmitters, Higher is better
1488 #if defined (PCB9XR) || defined (PCB9XR128)
1489 #define STICK_TOLERANCE 16
1491 #define STICK_TOLERANCE 64
1494 #if defined(FRSKY_HUB) && defined(GAUGES)
1495 enum BarThresholdIdx
{
1513 #define FILL_THRESHOLD(idx, val) barsThresholds[idx] = (val)
1515 #define FILL_THRESHOLD(idx, val) barsThresholds[idx] = 128 + (val)
1518 extern bar_threshold_t barsThresholds
[THLD_MAX
];
1520 #define FILL_THRESHOLD(idx, val)
1523 #if defined(TELEMETRY_FRSKY)
1524 ls_telemetry_value_t
minTelemValue(source_t channel
);
1525 ls_telemetry_value_t
maxTelemValue(source_t channel
);
1527 #define minTelemValue(channel) 255
1528 #define maxTelemValue(channel) 255
1532 getvalue_t
convert16bitsTelemValue(source_t channel
, ls_telemetry_value_t value
);
1533 ls_telemetry_value_t
max8bitsTelemValue(source_t channel
);
1536 getvalue_t
convert8bitsTelemValue(source_t channel
, ls_telemetry_value_t value
);
1537 getvalue_t
convertLswTelemValue(LogicalSwitchData
* cs
);
1540 #define convertTelemValue(channel, value) convert16bitsTelemValue(channel, value)
1541 #define convertBarTelemValue(channel, value) convert8bitsTelemValue(channel, value)
1542 #define maxBarTelemValue(channel) max8bitsTelemValue(channel)
1544 #define convertTelemValue(channel, value) convert8bitsTelemValue(channel, value)
1545 #define convertBarTelemValue(channel, value) convert8bitsTelemValue(channel, value)
1546 #define maxBarTelemValue(channel) maxTelemValue(channel)
1549 #if defined(TELEMETRY_FRSKY) || defined(CPUARM)
1550 lcdint_t
applyChannelRatio(source_t channel
, lcdint_t val
);
1551 #define ANA_CHANNEL_UNIT(channel) g_model.frsky.channels[channel].type
1554 inline int div_and_round(int num
, int den
)
1559 else if (num
>= 0) {
1568 #if defined(TELEMETRY_FRSKY)
1569 #if !defined(CPUARM)
1570 NOINLINE
uint8_t getRssiAlarmValue(uint8_t alarm
);
1573 extern const pm_uint8_t bchunit_ar
[];
1576 #define FRSKY_MULTIPLIER_MAX 5
1578 #define FRSKY_MULTIPLIER_MAX 3
1581 enum TelemetryViews
{
1582 TELEMETRY_CUSTOM_SCREEN_1
,
1583 TELEMETRY_CUSTOM_SCREEN_2
,
1585 TELEMETRY_CUSTOM_SCREEN_3
,
1586 TELEMETRY_CUSTOM_SCREEN_4
,
1587 TELEMETRY_VIEW_MAX
= TELEMETRY_CUSTOM_SCREEN_4
1589 TELEMETRY_VOLTAGES_SCREEN
,
1590 TELEMETRY_AFTER_FLIGHT_SCREEN
,
1591 TELEMETRY_VIEW_MAX
= TELEMETRY_AFTER_FLIGHT_SCREEN
1595 extern uint8_t s_frsky_view
;
1599 #define EARTH_RADIUSKM ((uint32_t)6371)
1600 #define EARTH_RADIUS ((uint32_t)111194) // meters * pi / 180°
1602 void getGpsPilotPosition();
1603 void getGpsDistance();
1606 #if defined(AUDIO) && defined(BUZZER)
1607 #define IS_SOUND_OFF() (g_eeGeneral.buzzerMode==e_mode_quiet && g_eeGeneral.beepMode==e_mode_quiet)
1609 #define IS_SOUND_OFF() (g_eeGeneral.beepMode == e_mode_quiet)
1613 #define IS_IMPERIAL_ENABLE() (g_eeGeneral.imperial)
1614 #elif defined(IMPERIAL_UNITS)
1615 #define IS_IMPERIAL_ENABLE() (1)
1617 #define IS_IMPERIAL_ENABLE() (0)
1621 #elif defined(TELEMETRY_FRSKY)
1622 FORCEINLINE
void convertUnit(getvalue_t
& val
, uint8_t & unit
)
1624 if (IS_IMPERIAL_ENABLE()) {
1625 if (unit
== UNIT_TEMPERATURE
) {
1630 if (unit
== UNIT_DIST
) {
1632 val
= val
* 3 + (val
>> 2) + (val
>> 5);
1634 if (unit
== UNIT_FEET
) {
1637 if (unit
== UNIT_KTS
) {
1640 val
= (val
* 23) / 20;
1644 if (unit
== UNIT_KTS
) {
1647 val
= (val
* 50) / 27;
1651 if (unit
== UNIT_HDG
) {
1652 unit
= UNIT_TEMPERATURE
;
1656 #define convertUnit(...)
1659 #if !defined(CPUARM)
1660 #define IS_USR_PROTO_FRSKY_HUB() (g_model.frsky.usrProto == USR_PROTO_FRSKY)
1661 #define IS_USR_PROTO_WS_HOW_HIGH() (g_model.frsky.usrProto == USR_PROTO_WS_HOW_HIGH)
1664 #if defined(TELEMETRY_FRSKY) && defined(FRSKY_HUB) && defined(GPS)
1665 #define IS_GPS_AVAILABLE() IS_USR_PROTO_FRSKY_HUB()
1667 #define IS_GPS_AVAILABLE() (0)
1670 #if defined(PCBTARANIS)
1671 extern const pm_uchar logo_taranis
[];
1674 #if defined(USB_MASS_STORAGE)
1675 void usbPluggedIn();
1678 #include "lua/lua_api.h"
1681 enum ClipboardType
{
1682 CLIPBOARD_TYPE_NONE
,
1683 CLIPBOARD_TYPE_CUSTOM_SWITCH
,
1684 CLIPBOARD_TYPE_CUSTOM_FUNCTION
,
1685 CLIPBOARD_TYPE_SD_FILE
,
1689 #define CLIPBOARD_PATH_LEN 1024
1691 #define CLIPBOARD_PATH_LEN 32
1697 LogicalSwitchData csw
;
1698 CustomFunctionData cfn
;
1700 char directory
[CLIPBOARD_PATH_LEN
];
1701 char filename
[CLIPBOARD_PATH_LEN
];
1706 extern Clipboard clipboard
;
1710 extern uint16_t s_anaFilt
[NUM_ANALOGS
];
1713 #if defined(JITTER_MEASURE)
1714 extern JitterMeter
<uint16_t> rawJitter
[NUM_ANALOGS
];
1715 extern JitterMeter
<uint16_t> avgJitter
[NUM_ANALOGS
];
1716 #if defined(PCBHORUS)
1717 #define JITTER_MEASURE_ACTIVE() (menuHandlers[menuLevel] == menuStatsAnalogs)
1718 #elif defined(PCBTARANIS)
1719 #define JITTER_MEASURE_ACTIVE() (menuHandlers[menuLevel] == menuRadioDiagAnalogs)
1721 #define JITTER_MEASURE_ACTIVE() (1)
1723 #define JITTER_MEASURE_ACTIVE() (0)
1727 #if defined(INTERNAL_GPS)
1731 #if defined(BLUETOOTH)
1732 #include "bluetooth.h"
1735 #endif // _OPENTX_H_