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 ((int8_t)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 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);
190 *s
++ = '0' + (qr
.rem
/ 10);
191 *s
++ = '0' + (qr
.rem
% 10);
197 char * getCurveString(char * dest
, int idx
)
200 return getStringAtIndex(dest
, STR_MMMINV
, 0);
209 if (ZEXIST(g_model
.curves
[idx
- 1].name
))
210 zchar2str(s
, g_model
.curves
[idx
- 1].name
, LEN_CURVE_NAME
);
212 strAppendStringWithIndex(s
, STR_CV
, idx
);
217 char * getGVarString(char * dest
, int idx
)
225 if (ZEXIST(g_model
.gvars
[idx
].name
))
226 zchar2str(s
, g_model
.gvars
[idx
].name
, LEN_GVAR_NAME
);
228 strAppendStringWithIndex(s
, STR_GV
, idx
+1);
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);
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
);
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
266 if (swinfo
.quot
== 5)
268 else if (swinfo
.quot
== 4)
271 *s
++ = 'A'+swinfo
.quot
;
273 *s
++ = 'A'+swinfo
.quot
;
276 *s
++ = "\300-\301"[swinfo
.rem
];
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);
291 #if defined(PCBSKY9X)
292 else if (idx
<= SWSRC_REa
) {
293 getStringAtIndex(s
, STR_VSWITCHES
, IDX_TRIMS_IN_STR_VSWITCHES
+idx
-SWSRC_FIRST_TRIM
);
296 else if (idx
<= SWSRC_LAST_TRIM
) {
297 getStringAtIndex(s
, STR_VSWITCHES
, IDX_TRIMS_IN_STR_VSWITCHES
+idx
-SWSRC_FIRST_TRIM
);
301 else if (idx
<= SWSRC_LAST_LOGICAL_SWITCH
) {
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
) {
315 zchar2str(s
, g_model
.telemetrySensors
[idx
-SWSRC_FIRST_SENSOR
].label
, TELEM_LABEL_LEN
);
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
;
329 if (ZEXIST(g_model
.inputNames
[idx
])) {
330 zchar2str(dest
, g_model
.inputNames
[idx
], LEN_INPUT_NAME
);
331 dest
[LEN_INPUT_NAME
] = '\0';
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
) {
343 // *dest++ = '1'+qr.quot;
344 strcpy(dest
, scriptInputsOutputs
[qr
.quot
].outputs
[qr
.rem
].name
);
351 else if (idx
<= MIXSRC_LAST_POT
) {
353 if (ZEXIST(g_eeGeneral
.anaNames
[idx
])) {
354 zchar2str(dest
, g_eeGeneral
.anaNames
[idx
], LEN_ANA_NAME
);
355 dest
[LEN_ANA_NAME
] = '\0';
358 getStringAtIndex(dest
, STR_VSRCRAW
, idx
+ 1);
361 else if (idx
<= MIXSRC_LAST_TRIM
) {
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';
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';
396 getStringAtIndex(dest
, STR_VSRCRAW
, idx
-MIXSRC_Rud
+1-MAX_LOGICAL_SWITCHES
-MAX_TRAINER_CHANNELS
-MAX_OUTPUT_CHANNELS
-MAX_GVARS
);
400 idx
-= MIXSRC_FIRST_TELEM
;
401 div_t qr
= div(idx
, 3);
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 ? '+' : '-');
412 char * strAppendUnsigned(char * dest
, uint32_t value
, uint8_t digits
, uint8_t radix
)
415 unsigned int tmp
= value
;
417 while (tmp
>= radix
) {
422 uint8_t idx
= digits
;
424 uint32_t rem
= value
% radix
;
425 dest
[--idx
] = (rem
>= 10 ? 'A'-10 : '0') + rem
;
429 return &dest
[digits
];
432 char * strAppendSigned(char * dest
, int32_t value
, uint8_t digits
, uint8_t radix
)
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
++)) {
453 char * strSetCursor(char * dest
, int position
)
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
== '.') {
478 char * strAppendDate(char * str
, bool time
)
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
;
491 qr
= div(utm
.tm_mon
+1, 10);
492 str
[7] = '0' + qr
.rem
;
493 str
[6] = '0' + qr
.quot
;
495 qr
= div(utm
.tm_mday
, 10);
496 str
[10] = '0' + qr
.rem
;
497 str
[9] = '0' + qr
.quot
;
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
;