Fix 2.2.2RC1 no gvar compile (#5961)
[opentx.git] / radio / src / strhelpers.cpp
blob4e2c0f2ebdfacd8748732c78008c8b931f9e7e42
1 /*
2 * Copyright (C) OpenTX
4 * Based on code named
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.
21 #include "opentx.h"
23 #if !defined(BOOT)
24 const pm_char s_charTab[] PROGMEM = "_-.,";
26 char hex2zchar(uint8_t hex)
28 return (hex >= 10 ? hex-9 : 27+hex);
31 char idx2char(int8_t idx)
33 if (idx == 0) return ' ';
34 if (idx < 0) {
35 if (idx > -27) return 'a' - idx - 1;
36 idx = -idx;
38 if (idx < 27) return 'A' + idx - 1;
39 if (idx < 37) return '0' + idx - 27;
40 if (idx <= 40) return pgm_read_byte(s_charTab+idx-37);
41 #if LEN_SPECIAL_CHARS > 0
42 if (idx <= (LEN_STD_CHARS + LEN_SPECIAL_CHARS)) return 'z' + 5 + idx - 40;
43 #endif
44 return ' ';
47 #if defined(CPUARM) || defined(SIMU)
48 int8_t char2idx(char c)
50 if (c == '_') return 37;
51 #if LEN_SPECIAL_CHARS > 0
52 if ((int8_t)c < 0 && c+128 <= LEN_SPECIAL_CHARS) return 41 + (c+128);
53 #endif
54 if (c >= 'a') return 'a' - c - 1;
55 if (c >= 'A') return c - 'A' + 1;
56 if (c >= '0') return c - '0' + 27;
57 if (c == '-') return 38;
58 if (c == '.') return 39;
59 if (c == ',') return 40;
60 return 0;
63 void str2zchar(char * dest, const char * src, int size)
65 memset(dest, 0, size);
66 for (int c=0; c<size && src[c]; c++) {
67 dest[c] = char2idx(src[c]);
71 int zchar2str(char * dest, const char * src, int size)
73 for (int c=0; c<size; c++) {
74 dest[c] = idx2char(src[c]);
76 do {
77 dest[size--] = '\0';
78 } while (size >= 0 && dest[size] == ' ');
79 return size+1;
81 #endif
83 #if defined(CPUARM)
84 unsigned int effectiveLen(const char * str, unsigned int size)
86 while (size > 0) {
87 if (str[size-1] != ' ')
88 return size;
89 size--;
91 return 0;
94 bool zexist(const char * str, uint8_t size)
96 for (int i=0; i<size; i++) {
97 if (str[i] != 0)
98 return true;
100 return false;
103 uint8_t zlen(const char * str, uint8_t size)
105 while (size > 0) {
106 if (str[size-1] != 0)
107 return size;
108 size--;
110 return 0;
113 char * strcat_zchar(char * dest, const char * name, uint8_t size, const char * defaultName, uint8_t defaultNameSize, uint8_t defaultIdx)
115 int8_t len = 0;
117 if (name) {
118 memcpy(dest, name, size);
119 dest[size] = '\0';
121 int8_t i = size-1;
123 while (i>=0) {
124 if (!len && dest[i])
125 len = i+1;
126 if (len) {
127 if (dest[i])
128 dest[i] = idx2char(dest[i]);
129 else
130 dest[i] = '_';
132 i--;
136 if (len == 0 && defaultName) {
137 strcpy(dest, defaultName);
138 dest[defaultNameSize] = (char)((defaultIdx / 10) + '0');
139 dest[defaultNameSize + 1] = (char)((defaultIdx % 10) + '0');
140 len = defaultNameSize + 2;
143 return &dest[len];
145 #endif
146 #endif
148 #if defined(CPUARM) && !defined(BOOT)
149 char * getStringAtIndex(char * dest, const char * s, int idx)
151 uint8_t len = s[0];
152 strncpy(dest, s+1+len*idx, len);
153 dest[len] = '\0';
154 return dest;
157 char * strAppendStringWithIndex(char * dest, const char * s, int idx)
159 return strAppendUnsigned(strAppend(dest, s), abs(idx));
162 char * getTimerString(char * dest, putstime_t tme, uint8_t hours)
164 char * s = dest;
165 div_t qr;
167 if (tme < 0) {
168 tme = -tme;
169 *s++ = '-';
172 qr = div((int)tme, 60);
174 if (hours) {
175 div_t qr2 = div(qr.quot, 60);
176 *s++ = '0' + (qr2.quot / 10);
177 *s++ = '0' + (qr2.quot % 10);
178 *s++ = ':';
179 qr.quot = qr2.rem;
182 if (!hours && qr.quot > 99) {
183 *s++ = '0' + (qr.quot / 100);
184 qr.quot = qr.quot % 100;
187 *s++ = '0' + (qr.quot / 10);
188 *s++ = '0' + (qr.quot % 10);
189 *s++ = ':';
190 *s++ = '0' + (qr.rem / 10);
191 *s++ = '0' + (qr.rem % 10);
192 *s = '\0';
194 return dest;
197 char * getCurveString(char * dest, int idx)
199 if (idx == 0) {
200 return getStringAtIndex(dest, STR_MMMINV, 0);
203 char * s = dest;
204 if (idx < 0) {
205 *s++ = '!';
206 idx = -idx;
209 if (ZEXIST(g_model.curves[idx - 1].name))
210 zchar2str(s, g_model.curves[idx - 1].name, LEN_CURVE_NAME);
211 else
212 strAppendStringWithIndex(s, STR_CV, idx);
214 return dest;
217 char * getGVarString(char * dest, int idx)
219 char * s = dest;
220 if (idx < 0) {
221 *s++ = '-';
222 idx = -idx-1;
225 if (ZEXIST(g_model.gvars[idx].name))
226 zchar2str(s, g_model.gvars[idx].name, LEN_GVAR_NAME);
227 else
228 strAppendStringWithIndex(s, STR_GV, idx+1);
230 return dest;
233 char * getSwitchString(char * dest, swsrc_t idx)
235 if (idx == SWSRC_NONE) {
236 return getStringAtIndex(dest, STR_VSWITCHES, 0);
238 else if (idx == SWSRC_OFF) {
239 return getStringAtIndex(dest, STR_OFFON, 0);
242 char * s = dest;
243 if (idx < 0) {
244 *s++ = '!';
245 idx = -idx;
248 #if defined(PCBSKY9X)
249 #define IDX_TRIMS_IN_STR_VSWITCHES (1+SWSRC_LAST_SWITCH)
250 #define IDX_ON_IN_STR_VSWITCHES (IDX_TRIMS_IN_STR_VSWITCHES+SWSRC_LAST_TRIM-SWSRC_FIRST_TRIM+2)
251 if (idx <= SWSRC_LAST_SWITCH) {
252 getStringAtIndex(s, STR_VSWITCHES, idx);
254 #else
255 #define IDX_TRIMS_IN_STR_VSWITCHES (1)
256 #define IDX_ON_IN_STR_VSWITCHES (IDX_TRIMS_IN_STR_VSWITCHES+SWSRC_LAST_TRIM-SWSRC_FIRST_TRIM+1)
257 if (idx <= SWSRC_LAST_SWITCH) {
258 div_t swinfo = switchInfo(idx);
259 if (ZEXIST(g_eeGeneral.switchNames[swinfo.quot])) {
260 s += zchar2str(s, g_eeGeneral.switchNames[swinfo.quot], LEN_SWITCH_NAME);
261 // TODO tous zchar2str
263 else {
264 *s++ = 'S';
265 #if defined(PCBX7)
266 if (swinfo.quot == 5)
267 *s++ = 'H';
268 else if (swinfo.quot == 4)
269 *s++ = 'F';
270 else
271 *s++ = 'A'+swinfo.quot;
272 #else
273 *s++ = 'A'+swinfo.quot;
274 #endif
276 *s++ = "\300-\301"[swinfo.rem];
277 *s = '\0';
279 #endif // PCBSKY9X
281 #if NUM_XPOTS > 0
282 else if (idx <= SWSRC_LAST_MULTIPOS_SWITCH) {
283 div_t swinfo = div(int(idx - SWSRC_FIRST_MULTIPOS_SWITCH), XPOTS_MULTIPOS_COUNT);
284 char temp[LEN_ANA_NAME+1];
285 getSourceString(temp, MIXSRC_FIRST_POT+swinfo.quot);
286 temp[LEN_ANA_NAME]= '\0';
287 strAppendStringWithIndex(s, temp, swinfo.rem+1);
289 #endif
291 #if defined(PCBSKY9X)
292 else if (idx <= SWSRC_REa) {
293 getStringAtIndex(s, STR_VSWITCHES, IDX_TRIMS_IN_STR_VSWITCHES+idx-SWSRC_FIRST_TRIM);
295 #else
296 else if (idx <= SWSRC_LAST_TRIM) {
297 getStringAtIndex(s, STR_VSWITCHES, IDX_TRIMS_IN_STR_VSWITCHES+idx-SWSRC_FIRST_TRIM);
299 #endif
301 else if (idx <= SWSRC_LAST_LOGICAL_SWITCH) {
302 *s++ = 'L';
303 strAppendUnsigned(s, idx-SWSRC_FIRST_LOGICAL_SWITCH+1, 2);
305 else if (idx <= SWSRC_ONE) {
306 getStringAtIndex(s, STR_VSWITCHES, IDX_ON_IN_STR_VSWITCHES + idx - SWSRC_ON);
308 else if (idx <= SWSRC_LAST_FLIGHT_MODE) {
309 strAppendStringWithIndex(s, STR_FP, idx-SWSRC_FIRST_FLIGHT_MODE);
311 else if (idx == SWSRC_TELEMETRY_STREAMING) {
312 strcpy(s, "Tele");
314 else {
315 zchar2str(s, g_model.telemetrySensors[idx-SWSRC_FIRST_SENSOR].label, TELEM_LABEL_LEN);
318 return dest;
321 char * getSourceString(char * dest, mixsrc_t idx)
323 if (idx == MIXSRC_NONE) {
324 return getStringAtIndex(dest, STR_VSRCRAW, 0);
326 else if (idx <= MIXSRC_LAST_INPUT) {
327 idx -= MIXSRC_FIRST_INPUT;
328 *dest++ = '\314';
329 if (ZEXIST(g_model.inputNames[idx])) {
330 zchar2str(dest, g_model.inputNames[idx], LEN_INPUT_NAME);
331 dest[LEN_INPUT_NAME] = '\0';
333 else {
334 strAppendUnsigned(dest, idx+1, 2);
337 #if defined(LUA_INPUTS)
338 else if (idx <= MIXSRC_LAST_LUA) {
339 #if defined(LUA_MODEL_SCRIPTS)
340 div_t qr = div(idx-MIXSRC_FIRST_LUA, MAX_SCRIPT_OUTPUTS);
341 if (qr.quot < MAX_SCRIPTS && qr.rem < scriptInputsOutputs[qr.quot].outputsCount) {
342 *dest++ = '\322';
343 // *dest++ = '1'+qr.quot;
344 strcpy(dest, scriptInputsOutputs[qr.quot].outputs[qr.rem].name);
346 #else
347 strcpy(dest, "N/A");
348 #endif
350 #endif
351 else if (idx <= MIXSRC_LAST_POT) {
352 idx -= MIXSRC_Rud;
353 if (ZEXIST(g_eeGeneral.anaNames[idx])) {
354 zchar2str(dest, g_eeGeneral.anaNames[idx], LEN_ANA_NAME);
355 dest[LEN_ANA_NAME] = '\0';
357 else {
358 getStringAtIndex(dest, STR_VSRCRAW, idx + 1);
361 else if (idx <= MIXSRC_LAST_TRIM) {
362 idx -= MIXSRC_Rud;
363 getStringAtIndex(dest, STR_VSRCRAW, idx + 1);
365 else if (idx <= MIXSRC_LAST_SWITCH) {
366 idx -= MIXSRC_FIRST_SWITCH;
367 if (ZEXIST(g_eeGeneral.switchNames[idx])) {
368 zchar2str(dest, g_eeGeneral.switchNames[idx], LEN_SWITCH_NAME);
369 dest[LEN_SWITCH_NAME] = '\0';
371 else {
372 getStringAtIndex(dest, STR_VSRCRAW, idx + MIXSRC_FIRST_SWITCH - MIXSRC_Rud + 1);
375 else if (idx <= MIXSRC_LAST_LOGICAL_SWITCH) {
376 getSwitchString(dest, SWSRC_SW1 + idx - MIXSRC_SW1);
378 else if (idx <= MIXSRC_LAST_TRAINER) {
379 strAppendStringWithIndex(dest, STR_PPM_TRAINER, idx - MIXSRC_FIRST_TRAINER + 1);
381 else if (idx <= MIXSRC_LAST_CH) {
382 strAppendStringWithIndex(dest, STR_CH, idx - MIXSRC_CH1 + 1);
384 else if (idx <= MIXSRC_LAST_GVAR) {
385 strAppendStringWithIndex(dest, STR_GV, idx - MIXSRC_GVAR1 + 1);
387 else if (idx < MIXSRC_FIRST_TIMER) {
388 getStringAtIndex(dest, STR_VSRCRAW, idx-MIXSRC_Rud+1-MAX_LOGICAL_SWITCHES-MAX_TRAINER_CHANNELS-MAX_OUTPUT_CHANNELS-MAX_GVARS);
390 else if (idx <= MIXSRC_LAST_TIMER) {
391 if(ZEXIST(g_model.timers[idx-MIXSRC_FIRST_TIMER].name)) {
392 zchar2str(dest,g_model.timers[idx-MIXSRC_FIRST_TIMER].name, LEN_TIMER_NAME);
393 dest[LEN_TIMER_NAME] = '\0';
395 else {
396 getStringAtIndex(dest, STR_VSRCRAW, idx-MIXSRC_Rud+1-MAX_LOGICAL_SWITCHES-MAX_TRAINER_CHANNELS-MAX_OUTPUT_CHANNELS-MAX_GVARS);
399 else {
400 idx -= MIXSRC_FIRST_TELEM;
401 div_t qr = div(idx, 3);
402 dest[0] = '\321';
403 int pos = 1 + zchar2str(&dest[1], g_model.telemetrySensors[qr.quot].label, sizeof(g_model.telemetrySensors[qr.quot].label));
404 if (qr.rem) dest[pos++] = (qr.rem==2 ? '+' : '-');
405 dest[pos] = '\0';
408 return dest;
410 #endif
412 char * strAppendUnsigned(char * dest, uint32_t value, uint8_t digits, uint8_t radix)
414 if (digits == 0) {
415 unsigned int tmp = value;
416 digits = 1;
417 while (tmp >= radix) {
418 ++digits;
419 tmp /= radix;
422 uint8_t idx = digits;
423 while(idx > 0) {
424 uint32_t rem = value % radix;
425 dest[--idx] = (rem >= 10 ? 'A'-10 : '0') + rem;
426 value /= radix;
428 dest[digits] = '\0';
429 return &dest[digits];
432 char * strAppendSigned(char * dest, int32_t value, uint8_t digits, uint8_t radix)
434 if (value < 0) {
435 *dest++ = '-';
436 value = -value;
438 return strAppendUnsigned(dest, (uint32_t)value, digits, radix);
441 #if defined(CPUARM) || defined(SDCARD)
442 char * strAppend(char * dest, const char * source, int len)
444 while ((*dest++ = *source++)) {
445 if (--len == 0) {
446 *dest = '\0';
447 return dest;
450 return dest - 1;
453 char * strSetCursor(char * dest, int position)
455 *dest++ = 0x1F;
456 *dest++ = position;
457 *dest = '\0';
458 return dest;
461 char * strAppendFilename(char * dest, const char * filename, const int size)
463 memset(dest, 0, size);
464 for (int i=0; i<size; i++) {
465 char c = *filename++;
466 if (c == '\0' || c == '.') {
467 *dest = 0;
468 break;
470 *dest++ = c;
472 return dest;
475 #if defined(RTCLOCK)
476 #include "rtc.h"
478 char * strAppendDate(char * str, bool time)
480 str[0] = '-';
481 struct gtm utm;
482 gettime(&utm);
483 div_t qr = div(utm.tm_year+TM_YEAR_BASE, 10);
484 str[4] = '0' + qr.rem;
485 qr = div(qr.quot, 10);
486 str[3] = '0' + qr.rem;
487 qr = div(qr.quot, 10);
488 str[2] = '0' + qr.rem;
489 str[1] = '0' + qr.quot;
490 str[5] = '-';
491 qr = div(utm.tm_mon+1, 10);
492 str[7] = '0' + qr.rem;
493 str[6] = '0' + qr.quot;
494 str[8] = '-';
495 qr = div(utm.tm_mday, 10);
496 str[10] = '0' + qr.rem;
497 str[9] = '0' + qr.quot;
499 if (time) {
500 str[11] = '-';
501 div_t qr = div(utm.tm_hour, 10);
502 str[13] = '0' + qr.rem;
503 str[12] = '0' + qr.quot;
504 qr = div(utm.tm_min, 10);
505 str[15] = '0' + qr.rem;
506 str[14] = '0' + qr.quot;
507 qr = div(utm.tm_sec, 10);
508 str[17] = '0' + qr.rem;
509 str[16] = '0' + qr.quot;
510 str[18] = '\0';
511 return &str[18];
513 else {
514 str[11] = '\0';
515 return &str[11];
518 #endif
519 #endif