Files
edgetx-gx12/radio/src/strhelpers.cpp
T

809 lines
19 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.
*/
#include "strhelpers.h"
#include "opentx.h"
#if !defined(BOOT)
const char s_charTab[] = "_-.,";
char hex2zchar(uint8_t hex) { return (hex >= 10 ? hex - 9 : 27 + hex); }
char hex2char(uint8_t hex) { return (hex >= 10 ? hex - 9 + 'A' : hex + '0'); }
char zchar2char(int8_t idx)
{
if (idx == 0) return ' ';
if (idx < 0) {
if (idx > -27) return 'a' - idx - 1;
idx = -idx;
}
if (idx < 27) return 'A' + idx - 1;
if (idx < 37) return '0' + idx - 27;
if (idx <= 40) return *(s_charTab + idx - 37);
#if LEN_SPECIAL_CHARS > 0
if (idx <= (LEN_STD_CHARS + LEN_SPECIAL_CHARS)) return 'z' + 5 + idx - 40;
#endif
return ' ';
}
char char2lower(char c) { return (c >= 'A' && c <= 'Z') ? c + 32 : c; }
int8_t char2zchar(char c)
{
if (c == '_') return 37;
#if LEN_SPECIAL_CHARS > 0
if ((int8_t)c < 0 && c + 128 <= LEN_SPECIAL_CHARS) return 41 + (c + 128);
#endif
if (c >= 'a') return 'a' - c - 1;
if (c >= 'A') return c - 'A' + 1;
if (c >= '0') return c - '0' + 27;
if (c == '-') return 38;
if (c == '.') return 39;
if (c == ',') return 40;
return 0;
}
void str2zchar(char *dest, const char *src, int size)
{
memset(dest, 0, size);
for (int c = 0; c < size && src[c]; c++) {
dest[c] = char2zchar(src[c]);
}
}
int zchar2str(char *dest, const char *src, int size)
{
for (int c = 0; c < size; c++) {
dest[c] = zchar2char(src[c]);
}
do {
dest[size--] = '\0';
} while (size >= 0 && dest[size] == ' ');
return size + 1;
}
int strnlen(const char *src, int max_size)
{
for (int i = 0; i < max_size; i++) {
if (src[i] == '\0') return i;
}
return max_size;
}
unsigned int effectiveLen(const char *str, unsigned int size)
{
while (size > 0) {
if (str[size - 1] != ' ' && str[size - 1] != '\0') return size;
size--;
}
return 0;
}
bool zexist(const char *str, uint8_t size)
{
for (int i = 0; i < size; i++) {
if (str[i] != 0) return true;
}
return false;
}
uint8_t zlen(const char *str, uint8_t size)
{
while (size > 0) {
if (str[size - 1] != 0) return size;
size--;
}
return 0;
}
char *strcat_zchar(char *dest, const char *name, uint8_t size,
const char spaceSym, const char *defaultName,
uint8_t defaultNameSize, uint8_t defaultIdx)
{
int8_t len = 0;
if (name) {
memcpy(dest, name, size);
dest[size] = '\0';
int8_t i = size - 1;
while (i >= 0) {
if (!len && dest[i]) len = i + 1;
if (len) {
if (dest[i] == spaceSym) dest[i] = '_';
}
i--;
}
}
if (len == 0 && defaultName) {
strcpy(dest, defaultName);
dest[defaultNameSize] = (char)((defaultIdx / 10) + '0');
dest[defaultNameSize + 1] = (char)((defaultIdx % 10) + '0');
len = defaultNameSize + 2;
}
return &dest[len];
}
#endif
#if !defined(BOOT)
char *getStringAtIndex(char *dest, const char *s, int idx)
{
uint8_t len = s[0];
strncpy(dest, s + 1 + len * idx, len);
dest[len] = '\0';
return dest;
}
char *strAppendStringWithIndex(char *dest, const char *s, int idx)
{
return strAppendUnsigned(strAppend(dest, s), abs(idx));
}
#define SECONDSPERMIN 60
#define SECONDSPERHOUR (60 * SECONDSPERMIN)
#define SECONDSPERDAY (24 * SECONDSPERHOUR)
#define SECONDSPERYEAR (365 * SECONDSPERDAY)
char *getFormattedTimerString(char *dest, int32_t tme, TimerOptions timerOptions)
{
char *s = dest;
div_t qr;
int val = abs(tme);
uint8_t digit_group = 0;
const bool bLowerCase = !(timerOptions.options & SHOW_TIMER_UPPER_CASE);
const bool showTime = timerOptions.options & SHOW_TIME;
uint8_t numDigitGroupRequired = (timerOptions.options >> 2) & 0x7;
const bool hmFormat = timerOptions.options & SHOW_TIMER_HM_FORMAT;
if(!numDigitGroupRequired) numDigitGroupRequired = 3;
if (tme < 0) {
tme = -tme;
*s++ = '-';
}
// years
qr = div((int)val, SECONDSPERYEAR);
if (qr.quot != 0) {
qr = div((int)val, SECONDSPERYEAR);
*s++ = '0' + (qr.quot / 10);
*s++ = '0' + (qr.quot % 10);
*s++ = bLowerCase ? 'y' : 'Y';
val = qr.rem;
digit_group++;
}
if (digit_group == numDigitGroupRequired) {
*s = 0;
return dest;
}
// days
qr = div((int)val, SECONDSPERDAY);
if (qr.quot != 0 || digit_group != 0) {
qr = div((int)val, SECONDSPERDAY);
*s++ = '0' + (qr.quot / 10);
*s++ = '0' + (qr.quot % 10);
*s++ = bLowerCase ? 'd' : 'D';
val = qr.rem;
digit_group++;
}
if (digit_group == numDigitGroupRequired) {
*s = 0;
return dest;
}
// hours
qr = div((int)val, SECONDSPERHOUR);
if (qr.quot != 0 || digit_group != 0) {
qr = div((int)val, SECONDSPERHOUR);
*s++ = '0' + (qr.quot / 10);
*s++ = '0' + (qr.quot % 10);
digit_group++;
// if format hm is selected h should be always printed
if (digit_group == numDigitGroupRequired && !hmFormat) {
*s = 0;
return dest;
}
if(numDigitGroupRequired < 3 || hmFormat)
*s++ = bLowerCase ? 'h' : 'H';
else
*s++ = ':';
val = qr.rem;
}
if (digit_group == numDigitGroupRequired) {
*s = 0;
return dest;
}
// minutes
qr = div((int)val, SECONDSPERMIN);
*s++ = '0' + (qr.quot / 10);
*s++ = '0' + (qr.quot % 10);
digit_group++;
if (digit_group == numDigitGroupRequired) {
*s = 0;
return dest;
}
if(!showTime && hmFormat)
*s++ = bLowerCase ? 'm' : 'M';
else
*s++ = ':';
// seconds
*s++ = '0' + (qr.rem / 10);
*s++ = '0' + (qr.rem % 10);
*s = 0;
return dest;
}
void splitTimer(char *sDb0, char *sDb1, char *sUnit0, char *sUnit1, int tme,
bool bLowerCase)
{
char *s0 = sDb0;
char *s1 = sDb1;
char *s2 = sUnit0;
char *s3 = sUnit1;
s0[0] = s1[0] = s0[1] = s1[1] = '0';
div_t qr;
int val = tme;
uint8_t digit_group = 0;
/*
if (tme < 0) {
tme = -tme;
*s++ = '-';
}
*/
// years
qr = div((int)val, SECONDSPERYEAR);
if (qr.quot != 0) {
qr = div((int)val, SECONDSPERYEAR);
*s0++ += (qr.quot / 10);
*s0++ += (qr.quot % 10);
*s0 = 0;
;
*s2++ = bLowerCase ? 'y' : 'Y';
*s2 = 0;
digit_group++;
val = qr.rem;
}
// days
qr = div((int)val, SECONDSPERDAY);
if (digit_group == 1) {
*s1++ += (qr.quot / 10);
*s1++ += (qr.quot % 10);
*s1 = 0;
*s3++ = bLowerCase ? 'd' : 'D';
*s3 = 0;
return;
}
if (qr.quot != 0) {
*s0++ += (qr.quot / 10);
*s0++ += (qr.quot % 10);
*s0 = 0;
;
*s2++ = bLowerCase ? 'd' : 'D';
*s2 = 0;
digit_group++;
val = qr.rem;
}
// hours
qr = div((int)val, SECONDSPERHOUR);
if (digit_group == 1) {
*s1++ += (qr.quot / 10);
*s1++ += (qr.quot % 10);
*s1 = 0;
*s3++ = bLowerCase ? 'h' : 'H';
*s3 = 0;
return;
}
if (qr.quot != 0) {
*s0++ += (qr.quot / 10);
*s0++ += (qr.quot % 10);
*s0 = 0;
*s2++ = bLowerCase ? 'h' : 'H';
*s2 = 0;
digit_group++;
val = qr.rem;
}
// minutes
qr = div((int)val, SECONDSPERMIN);
if (digit_group == 1) {
*s1++ += (qr.quot / 10);
*s1++ += (qr.quot % 10);
*s1 = 0;
*s3++ = bLowerCase ? 'm' : 'M';
*s3 = 0;
return;
}
*s0++ += (qr.quot / 10);
*s0++ += (qr.quot % 10);
*s0 = 0;
*s2++ = bLowerCase ? 'm' : 'M';
*s2 = 0;
// seconds
*s1++ += (qr.rem / 10);
*s1++ += (qr.rem % 10);
*s1 = 0;
*s3++ = bLowerCase ? 's' : 'S';
*s3 = 0;
}
char *getCurveString(char *dest, int idx)
{
if (idx == 0) {
return getStringAtIndex(dest, STR_MMMINV, 0);
}
char *s = dest;
if (idx < 0) {
*s++ = '!';
idx = -idx;
}
if (g_model.curves[idx - 1].name[0])
strAppend(s, g_model.curves[idx - 1].name, LEN_CURVE_NAME);
else
strAppendStringWithIndex(s, STR_CV, idx);
return dest;
}
char *getGVarString(char *dest, int idx)
{
char *s = dest;
if (idx < 0) {
*s++ = '-';
idx = -idx - 1;
}
if (g_model.gvars[idx].name[0])
strAppend(s, g_model.gvars[idx].name, LEN_GVAR_NAME);
else
strAppendStringWithIndex(s, STR_GV, idx + 1);
return dest;
}
char *getFlightModeString(char *dest, int8_t idx)
{
char *s = dest;
if (idx == 0) {
strcpy(s, "---");
return dest;
}
if (idx < 0) {
*s++ = '!';
idx = -idx;
}
s = strAppend(s, STR_FM);
strAppendUnsigned(s, idx - 1);
return dest;
}
// char * getSwitchWarningString(char * dest, swsrc_t idx)
// {
// char * s = dest;
// uint8_t state = g_model.switchWarningState >> (3*idx) & 0x07;
// *s++ = 'A' + idx;
// if (state == 0)
// *s = '\0';
// else {
// *s++ = "x\300-\301"[state];
// *s = '\0';
// }
// return dest;
// }
#if !defined(PCBSKY9X)
int getRawSwitchIdx(char sw)
{
if (sw < 'A' || sw > 'Z')
return -1;
#if defined(PCBX7) && !defined(RADIO_TX12)
if (sw >= 'H')
return sw - 'H' + 5;
#if defined(RADIO_T12)
else if (sw == 'G')
#else
else if (sw == 'F')
#endif
return 4;
else
return sw - 'A';
#else
return sw - 'A';
#endif
}
char getRawSwitchFromIdx(int idx)
{
#if defined(PCBX7) && !defined(RADIO_TX12)
if (idx >= 5)
return 'H' + idx - 5;
else if (idx == 4)
#if defined(RADIO_T12)
return 'G';
#else
return 'F';
#endif
else
return 'A' + idx;
#else
return 'A' + idx;
#endif
}
char *getSwitchName(char *dest, swsrc_t idx)
{
div_t swinfo = switchInfo(idx);
if (g_eeGeneral.switchNames[swinfo.quot][0] != '\0') {
dest =
strAppend(dest, g_eeGeneral.switchNames[swinfo.quot], LEN_SWITCH_NAME);
} else {
*dest++ = 'S';
*dest++ = getRawSwitchFromIdx(swinfo.quot);
}
return dest;
}
#endif
char *getSwitchPositionName(char *dest, swsrc_t idx)
{
if (idx == SWSRC_NONE) {
return getStringAtIndex(dest, STR_VSWITCHES, 0);
} else if (idx == SWSRC_OFF) {
return getStringAtIndex(dest, STR_OFFON, 0);
}
char *s = dest;
if (idx < 0) {
*s++ = '!';
idx = -idx;
}
#if defined(PCBSKY9X)
#define IDX_TRIMS_IN_STR_VSWITCHES (1 + SWSRC_LAST_SWITCH)
#define IDX_ON_IN_STR_VSWITCHES \
(IDX_TRIMS_IN_STR_VSWITCHES + SWSRC_LAST_TRIM - SWSRC_FIRST_TRIM + 2)
if (idx <= SWSRC_LAST_SWITCH) {
getStringAtIndex(s, STR_VSWITCHES, idx);
}
#else
#define IDX_TRIMS_IN_STR_VSWITCHES (1)
#define IDX_ON_IN_STR_VSWITCHES \
(IDX_TRIMS_IN_STR_VSWITCHES + SWSRC_LAST_TRIM - SWSRC_FIRST_TRIM + 1)
if (idx <= SWSRC_LAST_SWITCH) {
div_t swinfo = switchInfo(idx);
s = getSwitchName(s, idx);
*s++ = (STR_CHAR_UP "-" STR_CHAR_DOWN)[swinfo.rem];
*s = '\0';
}
#endif // PCBSKY9X
#if NUM_XPOTS > 0
else if (idx <= SWSRC_LAST_MULTIPOS_SWITCH) {
div_t swinfo =
div(int(idx - SWSRC_FIRST_MULTIPOS_SWITCH), XPOTS_MULTIPOS_COUNT);
char temp[LEN_ANA_NAME + 1];
getSourceString(temp, MIXSRC_FIRST_POT + swinfo.quot);
temp[LEN_ANA_NAME] = '\0';
strAppendStringWithIndex(s, temp, swinfo.rem + 1);
}
#endif
else if (idx <= SWSRC_LAST_TRIM) {
getStringAtIndex(s, STR_VSWITCHES,
IDX_TRIMS_IN_STR_VSWITCHES + idx - SWSRC_FIRST_TRIM);
} else if (idx <= SWSRC_LAST_LOGICAL_SWITCH) {
*s++ = 'L';
strAppendUnsigned(s, idx - SWSRC_FIRST_LOGICAL_SWITCH + 1, 2);
} else if (idx <= SWSRC_ONE) {
getStringAtIndex(s, STR_VSWITCHES,
IDX_ON_IN_STR_VSWITCHES + idx - SWSRC_ON);
} else if (idx <= SWSRC_LAST_FLIGHT_MODE) {
strAppendStringWithIndex(s, STR_FM, idx - SWSRC_FIRST_FLIGHT_MODE);
} else if (idx == SWSRC_TELEMETRY_STREAMING) {
strcpy(s, "Tele");
} else if (idx == SWSRC_RADIO_ACTIVITY) {
strcpy(s, "Act");
}
#if defined(DEBUG_LATENCY)
else if (idx == SWSRC_LATENCY_TOGGLE) {
strcpy(s, "Ltc");
}
#endif
else {
strncpy(s, g_model.telemetrySensors[idx - SWSRC_FIRST_SENSOR].label,
TELEM_LABEL_LEN);
s[TELEM_LABEL_LEN] = '\0';
}
return dest;
}
char *getSourceString(char *dest, mixsrc_t idx)
{
if (idx == MIXSRC_NONE) {
return getStringAtIndex(dest, STR_VSRCRAW, 0);
} else if (idx <= MIXSRC_LAST_INPUT) {
idx -= MIXSRC_FIRST_INPUT;
*dest = CHAR_INPUT;
if (strlen(g_model.inputNames[idx])) {
memset(dest + 1, 0, LEN_INPUT_NAME + 1);
strncpy(dest + 1, g_model.inputNames[idx], LEN_INPUT_NAME);
} else {
strAppendUnsigned(dest + 1, idx + 1, 2);
}
}
#if defined(LUA_INPUTS)
else if (idx <= MIXSRC_LAST_LUA) {
#if defined(LUA_MODEL_SCRIPTS)
div_t qr = div(idx - MIXSRC_FIRST_LUA, MAX_SCRIPT_OUTPUTS);
if (qr.quot < MAX_SCRIPTS &&
qr.rem < scriptInputsOutputs[qr.quot].outputsCount) {
*dest++ = CHAR_LUA;
// temporary string
#define MAX_CHAR 16
char temp[MAX_CHAR];
strncpy(temp, g_model.scriptsData[qr.quot].name, MAX_CHAR);
// instance Name is empty : dest = n-ScriptFileName/OutputName
if (temp[0] == 0) {
snprintf(temp, MAX_CHAR, "%d-%s/%s", qr.quot + 1,
g_model.scriptsData[qr.quot].file,
scriptInputsOutputs[qr.quot].outputs[qr.rem].name);
// instance Name is not empty : dest = InstanceName/OutputName
} else {
snprintf(temp, MAX_CHAR, "%s/%s", g_model.scriptsData[qr.quot].name,
scriptInputsOutputs[qr.quot].outputs[qr.rem].name);
}
strcpy(dest, temp);
}
#else
strcpy(dest, "N/A");
#endif
}
#endif
else if (idx <= MIXSRC_LAST_POT) {
if (g_eeGeneral.anaNames[idx - MIXSRC_Rud][0]) {
// TODO: add correct symbol
if (idx <= MIXSRC_LAST_STICK) {
dest[0] = CHAR_STICK;
#if NUM_SLIDERS > 0
} else if (idx < MIXSRC_FIRST_SLIDER) {
dest[0] = CHAR_POT;
} else {
dest[0] = CHAR_SLIDER;
#else
} else {
dest[0] = CHAR_POT;
#endif
}
idx -= MIXSRC_Rud;
memcpy(dest + 1, g_eeGeneral.anaNames[idx], LEN_ANA_NAME);
dest[LEN_ANA_NAME + 1] = '\0';
} else {
idx -= MIXSRC_Rud;
getStringAtIndex(dest, STR_VSRCRAW, idx + 1);
}
} else if (idx <= MIXSRC_LAST_TRIM) {
idx -= MIXSRC_Rud;
getStringAtIndex(dest, STR_VSRCRAW, idx + 1);
} else if (idx <= MIXSRC_LAST_SWITCH) {
idx -= MIXSRC_FIRST_SWITCH;
if (g_eeGeneral.switchNames[idx][0] != '\0') {
strncpy(dest, g_eeGeneral.switchNames[idx], LEN_SWITCH_NAME);
dest[LEN_SWITCH_NAME] = '\0';
} else {
getStringAtIndex(dest, STR_VSRCRAW,
idx + MIXSRC_FIRST_SWITCH - MIXSRC_Rud + 1);
}
} else if (idx <= MIXSRC_LAST_LOGICAL_SWITCH) {
getSwitchPositionName(dest, SWSRC_SW1 + idx - MIXSRC_SW1);
} else if (idx <= MIXSRC_LAST_TRAINER) {
strAppendStringWithIndex(dest, STR_PPM_TRAINER,
idx - MIXSRC_FIRST_TRAINER + 1);
} else if (idx <= MIXSRC_LAST_CH) {
strAppendStringWithIndex(dest, STR_CH, idx - MIXSRC_CH1 + 1);
} else if (idx <= MIXSRC_LAST_GVAR) {
strAppendStringWithIndex(dest, STR_GV, idx - MIXSRC_GVAR1 + 1);
} else if (idx < MIXSRC_FIRST_TIMER) {
getStringAtIndex(dest, STR_VSRCRAW,
idx - MIXSRC_Rud + 1 - MAX_LOGICAL_SWITCHES -
MAX_TRAINER_CHANNELS - MAX_OUTPUT_CHANNELS -
MAX_GVARS);
} else if (idx <= MIXSRC_LAST_TIMER) {
if (g_model.timers[idx - MIXSRC_FIRST_TIMER].name[0] != '\0') {
strncpy(dest, g_model.timers[idx - MIXSRC_FIRST_TIMER].name,
LEN_TIMER_NAME);
dest[LEN_TIMER_NAME] = '\0';
} else {
getStringAtIndex(dest, STR_VSRCRAW,
idx - MIXSRC_Rud + 1 - MAX_LOGICAL_SWITCHES -
MAX_TRAINER_CHANNELS - MAX_OUTPUT_CHANNELS -
MAX_GVARS);
}
} else {
idx -= MIXSRC_FIRST_TELEM;
div_t qr = div(idx, 3);
dest[0] = CHAR_TELEMETRY;
char *pos = strAppend(&dest[1], g_model.telemetrySensors[qr.quot].label,
sizeof(g_model.telemetrySensors[qr.quot].label));
if (qr.rem) *pos = (qr.rem == 2 ? '+' : '-');
*++pos = '\0';
}
return dest;
}
#endif
char *strAppendUnsigned(char *dest, uint32_t value, uint8_t digits,
uint8_t radix)
{
if (digits == 0) {
unsigned int tmp = value;
digits = 1;
while (tmp >= radix) {
++digits;
tmp /= radix;
}
}
uint8_t idx = digits;
while (idx > 0) {
div_t qr = div(value, radix);
dest[--idx] = (qr.rem >= 10 ? 'A' - 10 : '0') + qr.rem;
value = qr.quot;
}
dest[digits] = '\0';
return &dest[digits];
}
char *strAppendSigned(char *dest, int32_t value, uint8_t digits, uint8_t radix)
{
if (value < 0) {
*dest++ = '-';
value = -value;
}
return strAppendUnsigned(dest, (uint32_t)value, digits, radix);
}
char *strAppend(char *dest, const char *source, int len)
{
while ((*dest++ = *source++)) {
if (--len == 0) {
*dest = '\0';
return dest;
}
}
return dest - 1;
}
char *strSetCursor(char *dest, int position)
{
*dest++ = 0x1F;
*dest++ = position;
*dest = '\0';
return dest;
}
char *strAppendFilename(char *dest, const char *filename, const int size)
{
memset(dest, 0, size);
for (int i = 0; i < size; i++) {
char c = *filename++;
if (c == '\0' || c == '.') {
*dest = 0;
break;
}
*dest++ = c;
}
return dest;
}
#if defined(RTCLOCK)
#include "rtc.h"
char *strAppendDate(char *str, bool time)
{
str[0] = '-';
struct gtm utm;
gettime(&utm);
div_t qr = div(utm.tm_year + TM_YEAR_BASE, 10);
str[4] = '0' + qr.rem;
qr = div(qr.quot, 10);
str[3] = '0' + qr.rem;
qr = div(qr.quot, 10);
str[2] = '0' + qr.rem;
str[1] = '0' + qr.quot;
str[5] = '-';
qr = div(utm.tm_mon + 1, 10);
str[7] = '0' + qr.rem;
str[6] = '0' + qr.quot;
str[8] = '-';
qr = div(utm.tm_mday, 10);
str[10] = '0' + qr.rem;
str[9] = '0' + qr.quot;
if (time) {
str[11] = '-';
div_t qr = div(utm.tm_hour, 10);
str[13] = '0' + qr.rem;
str[12] = '0' + qr.quot;
qr = div(utm.tm_min, 10);
str[15] = '0' + qr.rem;
str[14] = '0' + qr.quot;
qr = div(utm.tm_sec, 10);
str[17] = '0' + qr.rem;
str[16] = '0' + qr.quot;
str[18] = '\0';
return &str[18];
} else {
str[11] = '\0';
return &str[11];
}
}
#endif
#if !defined(BOOT)
static char tmpHelpersString[32];
// char * getSwitchWarningString(swsrc_t idx)
// {
// return getSwitchWarningString(tmpHelpersString, idx);
// }
char *getSourceString(mixsrc_t idx)
{
return getSourceString(tmpHelpersString, idx);
}
char *getCurveString(int idx) { return getCurveString(tmpHelpersString, idx); }
char *getTimerString(int32_t tme, TimerOptions timerOptions)
{
return getFormattedTimerString(tmpHelpersString, tme, timerOptions);
}
char *getTimerString(char *dest, int32_t tme, TimerOptions timerOptions)
{
return getFormattedTimerString(dest, tme, timerOptions);
}
char *getSwitchPositionName(swsrc_t idx)
{
return getSwitchPositionName(tmpHelpersString, idx);
}
char *getGVarString(int idx) { return getGVarString(tmpHelpersString, idx); }
#endif