337 lines
6.9 KiB
C++
337 lines
6.9 KiB
C++
|
|
static char result[16];
|
|
static word eeAdr = 0;
|
|
|
|
char getCharFromC40(ulong *c40) {
|
|
char result = *c40 % 40;
|
|
*c40 /= 40;
|
|
if (result < 12) {
|
|
if (result == 0) return '\0';
|
|
return result + ('0' - 1);
|
|
}
|
|
if (result <= 36) return result + ('a' - 12);
|
|
if (result == 37) return '.';
|
|
if (result == 38) return '-';
|
|
return '_';
|
|
}
|
|
|
|
void c40toString(ulong c40, char *str, byte maxlen) {
|
|
byte i = 0;
|
|
|
|
for (i = 0; i < maxlen; i++) {
|
|
if ((str[i] = getCharFromC40(&c40)) == 0) return;
|
|
}
|
|
str[maxlen - 1] = 0;
|
|
}
|
|
|
|
char *c40(ulong c40) {
|
|
c40toString(c40, result, sizeof result);
|
|
return result;
|
|
}
|
|
|
|
ulong addCharToC40(ulong in, char chr) {
|
|
ulong pos = 1;
|
|
if (in >= 40UL*40UL*40UL*40UL*40UL) return in; // throw away superflous chars
|
|
while (pos < in) {
|
|
pos *= 40;
|
|
}
|
|
return in + pos * CHAR_TO_C40(chr);
|
|
}
|
|
|
|
ulong addNumToC40(ulong in, byte num) {
|
|
// add number in the range 0..99
|
|
if (num >= 10) {
|
|
in = addCharToC40(in, '0' + num / 10);
|
|
}
|
|
return addCharToC40(in, '0' + num % 10);
|
|
}
|
|
|
|
boolean expired(ulong *last, long ms) {
|
|
if (now - *last > ms) {
|
|
*last = now;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
byte textcopyuntil(char *dst, byte maxlen, const char *src, char endchar) {
|
|
byte reslen = 0;
|
|
char ch;
|
|
|
|
if (maxlen == 0) return 0;
|
|
maxlen--;
|
|
for (reslen = 0; reslen < maxlen; reslen++, src++, dst++) {
|
|
ch = *src;
|
|
if (ch == endchar || ch == 0) {
|
|
*dst = 0;
|
|
return reslen;
|
|
}
|
|
*dst = ch;
|
|
}
|
|
*dst = 0;
|
|
return maxlen + 1; // indicates overflow
|
|
}
|
|
|
|
byte textcopy(char *dst, byte maxlen, const char *src) {
|
|
return textcopyuntil(dst, maxlen, src, 0);
|
|
}
|
|
|
|
boolean textcmpcopy(char *dst, byte maxlen, const char *src) {
|
|
byte reslen = 0;
|
|
boolean equal = true;
|
|
|
|
if (maxlen == 0) return true;
|
|
maxlen--;
|
|
// first compare
|
|
dst[maxlen] = 0; // save reslen < maxlen comparison
|
|
for (reslen = 0; *src == *dst; reslen++, src++, dst++) {
|
|
if (*src == 0) return true;
|
|
}
|
|
// then copy
|
|
for (; reslen < maxlen; reslen++, src++, dst++) {
|
|
if ((*dst = *src) == 0) {
|
|
return false;
|
|
}
|
|
}
|
|
*dst = 0;
|
|
return false;
|
|
}
|
|
|
|
byte textappend(char *dst, byte maxlen, const char *src) {
|
|
byte len = strlen(dst);
|
|
return len + textcopyuntil(dst + len, maxlen - len, src, 0);
|
|
}
|
|
|
|
byte textequal(const char *a, const char *b) {
|
|
if (a == b) return 1;
|
|
if (a == 0) {
|
|
if (*b == 0) return 1;
|
|
return 0;
|
|
}
|
|
if (b == 0) {
|
|
if (*a == 0) return 1;
|
|
return 0;
|
|
}
|
|
for (; *a == *b; a++, b++) {
|
|
if (*a == 0) return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
boolean textContainsBlanks(const char *text) {
|
|
for (; (signed char)*text > ' '; text++);
|
|
return (*text != 0);
|
|
}
|
|
|
|
void DummyHandler() {
|
|
}
|
|
|
|
size_t array_out_of_bounds(const char *func, long line, size_t index) {
|
|
Serial.println();
|
|
Serial.print(F("error in "));
|
|
Serial.print(func);
|
|
Serial.print(':');
|
|
Serial.print(line);
|
|
Serial.print('[');
|
|
Serial.print(index);
|
|
Serial.print(F("] invalid"));
|
|
SerialD.handler = DummyHandler;
|
|
SerialD.print("\033DL\033TE\014"); // clear display, terminal mode, clear terminal
|
|
SerialD.print("index\r\nerror:\r\n");
|
|
SerialD.print(func);
|
|
SerialD.print(':');
|
|
SerialD.print(line);
|
|
SerialD.print("\r\n[");
|
|
SerialD.print(index);
|
|
SerialD.print("]\r\n");
|
|
SerialD.send();
|
|
while (1);
|
|
//DispError("array out","of bounds");
|
|
return 0;
|
|
}
|
|
|
|
char *fix2str(long num, char dig, char *buffer, char maxlen) {
|
|
long divisor;
|
|
long n;
|
|
int i=0;
|
|
|
|
if (buffer == 0) {
|
|
buffer = result;
|
|
if (maxlen == 0 || maxlen > sizeof result) {
|
|
maxlen = sizeof result;
|
|
}
|
|
}
|
|
if (maxlen < 2) {
|
|
buffer[0] = 0;
|
|
return 0;
|
|
}
|
|
maxlen--;
|
|
if (dig >= 0) {
|
|
if (num < 0) {
|
|
buffer[i] = '-'; i++;
|
|
num = -num;
|
|
}
|
|
divisor = 1; n = num / 10;
|
|
while (n != 0 || dig > 0) {
|
|
n /= 10;
|
|
divisor *= 10;
|
|
dig--;
|
|
}
|
|
n = num;
|
|
while (divisor > 0 && i < maxlen) {
|
|
if (dig == 1) {
|
|
buffer[i] = '.'; i++;
|
|
}
|
|
buffer[i] = '0' + (n / divisor) % 10; i++;
|
|
divisor /= 10;
|
|
dig++;
|
|
}
|
|
}
|
|
if (i > maxlen) {
|
|
buffer[maxlen] = 0;
|
|
return 0;
|
|
}
|
|
buffer[i] = 0;
|
|
return buffer;
|
|
}
|
|
|
|
char *enum2str(byte value, flash_str flashList, char *buffer, byte maxlen) {
|
|
const char *list PROGMEM = (const char PROGMEM *)flashList;
|
|
byte len;
|
|
byte val = value;
|
|
char ch;
|
|
|
|
if (buffer == 0) {
|
|
buffer = result;
|
|
if (maxlen == 0 || maxlen > sizeof result) {
|
|
maxlen = sizeof result;
|
|
}
|
|
}
|
|
if (maxlen < 2) {
|
|
buffer[0] = 0;
|
|
return 0;
|
|
}
|
|
if (list == 0) {
|
|
buffer[0] = 0;
|
|
return buffer;
|
|
}
|
|
len = 0;
|
|
while (1) {
|
|
ch = pgm_read_byte(list);
|
|
if (ch == 0) break;
|
|
if (ch == '|') {
|
|
if (val == 0) break;
|
|
val--;
|
|
len = -1;
|
|
}
|
|
list++;
|
|
len++;
|
|
}
|
|
if (val != 0) {
|
|
return fix2str(value, 0, buffer, maxlen);
|
|
}
|
|
while (len >= maxlen) {
|
|
len--;
|
|
list--;
|
|
}
|
|
buffer[len] = 0;
|
|
while (len > 0) {
|
|
len--;
|
|
list--;
|
|
buffer[len] = pgm_read_byte(list);;
|
|
}
|
|
return buffer;
|
|
}
|
|
|
|
void eeSetAdr(word adr) {
|
|
eeAdr = adr;
|
|
}
|
|
|
|
word eeGetAdr() {
|
|
return eeAdr;
|
|
}
|
|
|
|
void eeStore(const void *data, word length, byte mode) {
|
|
byte *p;
|
|
if (mode == ee_write) {
|
|
for (p = (byte *)data; length > 0; length--, p++, eeAdr++) {
|
|
//Serial.print(eeAdr); Serial.print(":"); if(*p > ' ' && *p <= 'z') Serial.print((char)*p); Serial.println(*p);
|
|
EEPROM.write(eeAdr, *p);
|
|
}
|
|
} else {
|
|
for (p = (byte *)data; length > 0; length--, p++, eeAdr++) {
|
|
*p = EEPROM.read(eeAdr);
|
|
//Serial.print(eeAdr); Serial.print(":"); if(*p > ' ' && *p <= 'z') Serial.print((char)*p); Serial.println(*p);
|
|
}
|
|
}
|
|
}
|
|
|
|
void eeStoreText(char *p, word length, byte mode) {
|
|
char ch;
|
|
char *fini = p + length;
|
|
if (mode == ee_write) {
|
|
while (p < fini) {
|
|
ch = *p;
|
|
EEPROM.write(eeAdr, ch);
|
|
eeAdr++;
|
|
if (ch == 0) break;
|
|
p++;
|
|
}
|
|
} else {
|
|
while (p < fini) {
|
|
ch = EEPROM.read(eeAdr);
|
|
eeAdr++;
|
|
if (ch == -1) { // empty EEPROM location
|
|
ch = 0;
|
|
}
|
|
*p = ch;
|
|
if (ch == 0) break;
|
|
p++;
|
|
//Serial.print(eeAdr); Serial.print(":"); if(*p > ' ' && *p <= 'z') Serial.print((char)*p); Serial.println(*p);
|
|
}
|
|
}
|
|
}
|
|
|
|
long text2fix(const char *str, byte dig, byte *len) {
|
|
boolean neg;
|
|
long res = 0;
|
|
char ch;
|
|
const char *p = str;
|
|
|
|
if (len) *len = 0;
|
|
if (*p == '-') {
|
|
neg = true;
|
|
p++;
|
|
} else {
|
|
neg = false;
|
|
}
|
|
for (ch = *p; ch >= '0' && ch <='9'; p++, ch = *p) {
|
|
if (res >= 214748364) return 0;
|
|
res *= 10;
|
|
res += ch - '0';
|
|
}
|
|
if (ch == '.') {
|
|
p++;
|
|
for (ch = *p; ch >= '0' && ch <='9'; p++, ch = *p) {
|
|
if (dig == 0) {
|
|
if (ch >= '5') res++; // round up;
|
|
for (; ch >= '0' && ch <='9'; p++, ch = *p);
|
|
break;
|
|
}
|
|
res *= 10;
|
|
res += ch - '0';
|
|
dig --;
|
|
}
|
|
}
|
|
while (dig > 0) {
|
|
if (res >= 214748364) return 0;
|
|
res *= 10;
|
|
dig--;
|
|
}
|
|
if (len) {
|
|
*len = p - str;
|
|
}
|
|
if (neg) res = -res;
|
|
return res;
|
|
}
|