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.
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 ' ';
35 if (idx
> -27) return 'a' - idx
- 1;
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;
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 (c
< 0 && c
+128 <= LEN_SPECIAL_CHARS
) return 41 + (c
+128);
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;
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
]);
78 } while (size
>= 0 && dest
[size
] == ' ');
84 unsigned int effectiveLen(const char * str
, unsigned int size
)
87 if (str
[size
-1] != ' ')
94 bool zexist(const char * str
, uint8_t size
)
96 for (int i
=0; i
<size
; i
++) {
103 uint8_t zlen(const char * str
, uint8_t size
)
106 if (str
[size
-1] != 0)
113 char * strcat_zchar(char * dest
, const char * name
, uint8_t size
, const char * defaultName
, uint8_t defaultNameSize
, uint8_t defaultIdx
)
118 memcpy(dest
, name
, size
);
128 dest
[i
] = idx2char(dest
[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;
148 #if defined(CPUARM) && !defined(BOOT)
149 char * getStringAtIndex(char * dest
, const char * s
, int idx
)
152 strncpy(dest
, s
+1+len
*idx
, len
);
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
)
172 qr
= div((int)tme
, 60);
175 div_t qr2
= div(qr
.quot
, 60);
176 *s
++ = '0' + (qr2
.quot
/ 10);
177 *s
++ = '0' + (qr2
.quot
% 10);
182 *s
++ = '0' + (qr
.quot
/ 10);
183 *s
++ = '0' + (qr
.quot
% 10);
185 *s
++ = '0' + (qr
.rem
/ 10);
186 *s
++ = '0' + (qr
.rem
% 10);
192 char * getCurveString(char * dest
, int idx
)
195 return getStringAtIndex(dest
, STR_MMMINV
, 0);
204 if (ZEXIST(g_model
.curves
[idx
- 1].name
))
205 zchar2str(s
, g_model
.curves
[idx
- 1].name
, LEN_CURVE_NAME
);
207 strAppendStringWithIndex(s
, STR_CV
, idx
);
212 char * getGVarString(char * dest
, int idx
)
220 if (ZEXIST(g_model
.gvars
[idx
].name
))
221 zchar2str(s
, g_model
.gvars
[idx
].name
, LEN_GVAR_NAME
);
223 strAppendStringWithIndex(s
, STR_GV
, idx
+1);
228 char * getSwitchString(char * dest
, swsrc_t idx
)
230 if (idx
== SWSRC_NONE
) {
231 return getStringAtIndex(dest
, STR_VSWITCHES
, 0);
233 else if (idx
== SWSRC_OFF
) {
234 return getStringAtIndex(dest
, STR_OFFON
, 0);
243 #if defined(PCBSKY9X)
244 #define IDX_TRIMS_IN_STR_VSWITCHES (1+SWSRC_LAST_SWITCH)
245 #define IDX_ON_IN_STR_VSWITCHES (IDX_TRIMS_IN_STR_VSWITCHES+SWSRC_LAST_TRIM-SWSRC_FIRST_TRIM+2)
246 if (idx
<= SWSRC_LAST_SWITCH
) {
247 getStringAtIndex(s
, STR_VSWITCHES
, idx
);
250 #define IDX_TRIMS_IN_STR_VSWITCHES (1)
251 #define IDX_ON_IN_STR_VSWITCHES (IDX_TRIMS_IN_STR_VSWITCHES+SWSRC_LAST_TRIM-SWSRC_FIRST_TRIM+1)
252 if (idx
<= SWSRC_LAST_SWITCH
) {
253 div_t swinfo
= switchInfo(idx
);
254 if (ZEXIST(g_eeGeneral
.switchNames
[swinfo
.quot
])) {
255 s
+= zchar2str(s
, g_eeGeneral
.switchNames
[swinfo
.quot
], LEN_SWITCH_NAME
);
256 // TODO tous zchar2str
261 if (swinfo
.quot
== 5)
263 else if (swinfo
.quot
== 4)
266 *s
++ = 'A'+swinfo
.quot
;
268 *s
++ = 'A'+swinfo
.quot
;
271 *s
++ = "\300-\301"[swinfo
.rem
];
277 else if (idx
<= SWSRC_LAST_MULTIPOS_SWITCH
) {
278 div_t swinfo
= div(int(idx
- SWSRC_FIRST_MULTIPOS_SWITCH
), XPOTS_MULTIPOS_COUNT
);
279 char temp
[LEN_ANA_NAME
+1];
280 getSourceString(temp
, MIXSRC_FIRST_POT
+swinfo
.quot
);
281 temp
[LEN_ANA_NAME
]= '\0';
282 strAppendStringWithIndex(s
, temp
, swinfo
.rem
+1);
286 #if defined(PCBSKY9X)
287 else if (idx
<= SWSRC_REa
) {
288 getStringAtIndex(s
, STR_VSWITCHES
, IDX_TRIMS_IN_STR_VSWITCHES
+idx
-SWSRC_FIRST_TRIM
);
291 else if (idx
<= SWSRC_LAST_TRIM
) {
292 getStringAtIndex(s
, STR_VSWITCHES
, IDX_TRIMS_IN_STR_VSWITCHES
+idx
-SWSRC_FIRST_TRIM
);
296 else if (idx
<= SWSRC_LAST_LOGICAL_SWITCH
) {
297 strAppendStringWithIndex(s
, "L", idx
-SWSRC_FIRST_LOGICAL_SWITCH
+1);
299 else if (idx
<= SWSRC_ONE
) {
300 getStringAtIndex(s
, STR_VSWITCHES
, IDX_ON_IN_STR_VSWITCHES
+ idx
- SWSRC_ON
);
302 else if (idx
<= SWSRC_LAST_FLIGHT_MODE
) {
303 strAppendStringWithIndex(s
, STR_FP
, idx
-SWSRC_FIRST_FLIGHT_MODE
);
305 else if (idx
== SWSRC_TELEMETRY_STREAMING
) {
309 zchar2str(s
, g_model
.telemetrySensors
[idx
-SWSRC_FIRST_SENSOR
].label
, TELEM_LABEL_LEN
);
315 char * getSourceString(char * dest
, mixsrc_t idx
)
317 if (idx
== MIXSRC_NONE
) {
318 return getStringAtIndex(dest
, STR_VSRCRAW
, 0);
320 else if (idx
<= MIXSRC_LAST_INPUT
) {
321 idx
-= MIXSRC_FIRST_INPUT
;
323 if (ZEXIST(g_model
.inputNames
[idx
])) {
324 zchar2str(dest
, g_model
.inputNames
[idx
], LEN_INPUT_NAME
);
325 dest
[LEN_INPUT_NAME
] = '\0';
328 strAppendUnsigned(dest
, idx
, 2);
331 #if defined(LUA_INPUTS)
332 else if (idx
<= MIXSRC_LAST_LUA
) {
333 #if defined(LUA_MODEL_SCRIPTS)
334 div_t qr
= div(idx
-MIXSRC_FIRST_LUA
, MAX_SCRIPT_OUTPUTS
);
335 if (qr
.quot
< MAX_SCRIPTS
&& qr
.rem
< scriptInputsOutputs
[qr
.quot
].outputsCount
) {
337 // *dest++ = '1'+qr.quot;
338 strcpy(dest
, scriptInputsOutputs
[qr
.quot
].outputs
[qr
.rem
].name
);
345 else if (idx
<= MIXSRC_LAST_POT
) {
347 if (ZEXIST(g_eeGeneral
.anaNames
[idx
])) {
348 zchar2str(dest
, g_eeGeneral
.anaNames
[idx
], LEN_ANA_NAME
);
349 dest
[LEN_ANA_NAME
] = '\0';
352 getStringAtIndex(dest
, STR_VSRCRAW
, idx
+ 1);
355 else if (idx
<= MIXSRC_LAST_TRIM
) {
357 getStringAtIndex(dest
, STR_VSRCRAW
, idx
+ 1);
359 else if (idx
<= MIXSRC_LAST_SWITCH
) {
360 idx
-= MIXSRC_FIRST_SWITCH
;
361 if (ZEXIST(g_eeGeneral
.switchNames
[idx
])) {
362 zchar2str(dest
, g_eeGeneral
.switchNames
[idx
], LEN_SWITCH_NAME
);
363 dest
[LEN_SWITCH_NAME
] = '\0';
366 getStringAtIndex(dest
, STR_VSRCRAW
, idx
+ MIXSRC_FIRST_SWITCH
- MIXSRC_Rud
+ 1);
369 else if (idx
<= MIXSRC_LAST_LOGICAL_SWITCH
) {
370 getSwitchString(dest
, SWSRC_SW1
+ idx
- MIXSRC_SW1
);
372 else if (idx
<= MIXSRC_LAST_TRAINER
) {
373 strAppendStringWithIndex(dest
, STR_PPM_TRAINER
, idx
- MIXSRC_FIRST_TRAINER
+ 1);
375 else if (idx
<= MIXSRC_LAST_CH
) {
376 strAppendStringWithIndex(dest
, STR_CH
, idx
- MIXSRC_CH1
+ 1);
378 else if (idx
<= MIXSRC_LAST_GVAR
) {
379 strAppendStringWithIndex(dest
, STR_GV
, idx
- MIXSRC_GVAR1
+ 1);
381 else if (idx
< MIXSRC_FIRST_TELEM
) {
382 getStringAtIndex(dest
, STR_VSRCRAW
, idx
-MIXSRC_Rud
+1-MAX_LOGICAL_SWITCHES
-MAX_TRAINER_CHANNELS
-MAX_OUTPUT_CHANNELS
-MAX_GVARS
);
385 idx
-= MIXSRC_FIRST_TELEM
;
386 div_t qr
= div(idx
, 3);
388 int pos
= 1 + zchar2str(&dest
[1], g_model
.telemetrySensors
[qr
.quot
].label
, sizeof(g_model
.telemetrySensors
[qr
.quot
].label
));
389 if (qr
.rem
) dest
[pos
++] = (qr
.rem
==2 ? '+' : '-');
397 char * strAppendUnsigned(char * dest
, uint32_t value
, uint8_t digits
, uint8_t radix
)
400 unsigned int tmp
= value
;
407 uint8_t idx
= digits
;
409 uint32_t rem
= value
% radix
;
410 dest
[--idx
] = (rem
>= 10 ? 'A'-10 : '0') + rem
;
414 return &dest
[digits
];
417 char * strAppendSigned(char * dest
, int32_t value
, uint8_t digits
, uint8_t radix
)
423 return strAppendUnsigned(dest
, (uint32_t)value
, digits
, radix
);
426 #if defined(CPUARM) || defined(SDCARD)
427 char * strAppend(char * dest
, const char * source
, int len
)
429 while ((*dest
++ = *source
++)) {
438 char * strSetCursor(char * dest
, int position
)
446 char * strAppendFilename(char * dest
, const char * filename
, const int size
)
448 memset(dest
, 0, size
);
449 for (int i
=0; i
<size
; i
++) {
450 char c
= *filename
++;
451 if (c
== '\0' || c
== '.')
461 char * strAppendDate(char * str
, bool time
)
466 div_t qr
= div(utm
.tm_year
+TM_YEAR_BASE
, 10);
467 str
[4] = '0' + qr
.rem
;
468 qr
= div(qr
.quot
, 10);
469 str
[3] = '0' + qr
.rem
;
470 qr
= div(qr
.quot
, 10);
471 str
[2] = '0' + qr
.rem
;
472 str
[1] = '0' + qr
.quot
;
474 qr
= div(utm
.tm_mon
+1, 10);
475 str
[7] = '0' + qr
.rem
;
476 str
[6] = '0' + qr
.quot
;
478 qr
= div(utm
.tm_mday
, 10);
479 str
[10] = '0' + qr
.rem
;
480 str
[9] = '0' + qr
.quot
;
484 div_t qr
= div(utm
.tm_hour
, 10);
485 str
[13] = '0' + qr
.rem
;
486 str
[12] = '0' + qr
.quot
;
487 qr
= div(utm
.tm_min
, 10);
488 str
[15] = '0' + qr
.rem
;
489 str
[14] = '0' + qr
.quot
;
490 qr
= div(utm
.tm_sec
, 10);
491 str
[17] = '0' + qr
.rem
;
492 str
[16] = '0' + qr
.quot
;