|
@ -28,6 +28,146 @@ |
|
|
|
|
|
|
|
|
#include "../MarlinCore.h" |
|
|
#include "../MarlinCore.h" |
|
|
|
|
|
|
|
|
|
|
|
#ifdef __AVR__ |
|
|
|
|
|
|
|
|
|
|
|
static FORCE_INLINE uint32_t mult10(uint32_t val) { |
|
|
|
|
|
uint32_t tmp = val; |
|
|
|
|
|
__asm__ __volatile__ ( |
|
|
|
|
|
"add %A[tmp], %A[tmp]\n" |
|
|
|
|
|
"adc %B[tmp], %B[tmp]\n" |
|
|
|
|
|
"adc %C[tmp], %C[tmp]\n" |
|
|
|
|
|
"adc %D[tmp], %D[tmp]\n" |
|
|
|
|
|
"add %A[tmp], %A[tmp]\n" |
|
|
|
|
|
"adc %B[tmp], %B[tmp]\n" |
|
|
|
|
|
"adc %C[tmp], %C[tmp]\n" |
|
|
|
|
|
"adc %D[tmp], %D[tmp]\n" |
|
|
|
|
|
"add %A[val], %A[tmp]\n" |
|
|
|
|
|
"adc %B[val], %B[tmp]\n" |
|
|
|
|
|
"adc %C[val], %C[tmp]\n" |
|
|
|
|
|
"adc %D[val], %D[tmp]\n" |
|
|
|
|
|
"add %A[val], %A[val]\n" |
|
|
|
|
|
"adc %B[val], %B[val]\n" |
|
|
|
|
|
"adc %C[val], %C[val]\n" |
|
|
|
|
|
"adc %D[val], %D[val]\n" |
|
|
|
|
|
: [val] "+&r" (val), |
|
|
|
|
|
[tmp] "+&r" (tmp) |
|
|
|
|
|
); |
|
|
|
|
|
return val; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
#else |
|
|
|
|
|
|
|
|
|
|
|
static FORCE_INLINE uint32_t mult10(uint32_t val) { return val * 10; } |
|
|
|
|
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
// cheap base-10 strto(u)l.
|
|
|
|
|
|
// does not check for errors.
|
|
|
|
|
|
int32_t parse_int32(const char *buf) { |
|
|
|
|
|
char c; |
|
|
|
|
|
|
|
|
|
|
|
// Get a char, skipping leading spaces
|
|
|
|
|
|
do { c = *buf++; } while (c == ' '); |
|
|
|
|
|
|
|
|
|
|
|
// check for sign
|
|
|
|
|
|
bool is_negative = (c == '-'); |
|
|
|
|
|
if (is_negative || c == '+') |
|
|
|
|
|
c = *buf++; |
|
|
|
|
|
|
|
|
|
|
|
// optimization for first digit (no multiplication)
|
|
|
|
|
|
uint8_t uc = c - '0'; |
|
|
|
|
|
if (uc > 9) return 0; |
|
|
|
|
|
|
|
|
|
|
|
// read unsigned value
|
|
|
|
|
|
uint32_t uval = uc; |
|
|
|
|
|
while (true) { |
|
|
|
|
|
c = *buf++; |
|
|
|
|
|
uc = c - '0'; |
|
|
|
|
|
if (uc > 9) break; |
|
|
|
|
|
uval = mult10(uval) + uc; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return is_negative ? -uval : uval; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// cheap strtof.
|
|
|
|
|
|
// does not support nan/infinity or exponent notation.
|
|
|
|
|
|
// does not check for errors.
|
|
|
|
|
|
float parse_float(const char *buf) { |
|
|
|
|
|
char c; |
|
|
|
|
|
|
|
|
|
|
|
// Get a char, skipping leading spaces
|
|
|
|
|
|
do { c = *buf++; } while (c == ' '); |
|
|
|
|
|
|
|
|
|
|
|
// check for sign
|
|
|
|
|
|
bool is_negative = (c == '-'); |
|
|
|
|
|
if (is_negative || c == '+') |
|
|
|
|
|
c = *buf++; |
|
|
|
|
|
|
|
|
|
|
|
// read unsigned value and decimal point
|
|
|
|
|
|
uint32_t uval; |
|
|
|
|
|
uint8_t exp_dec; |
|
|
|
|
|
uint8_t uc = c - '0'; |
|
|
|
|
|
if (uc <= 9) { |
|
|
|
|
|
uval = uc; |
|
|
|
|
|
exp_dec = 0; |
|
|
|
|
|
} |
|
|
|
|
|
else { |
|
|
|
|
|
if (c != '.') return 0; |
|
|
|
|
|
uval = 0; |
|
|
|
|
|
exp_dec = 1; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
int8_t exp = 0; |
|
|
|
|
|
while (true) { |
|
|
|
|
|
c = *buf++; |
|
|
|
|
|
uc = c - '0'; |
|
|
|
|
|
if (uc <= 9) { |
|
|
|
|
|
exp -= exp_dec; |
|
|
|
|
|
uval = mult10(uval) + uc; |
|
|
|
|
|
if (uval >= (UINT32_MAX - 9) / 10) { |
|
|
|
|
|
// overflow. keep reading digits until decimal point.
|
|
|
|
|
|
while (exp_dec == 0) { |
|
|
|
|
|
c = *buf++; |
|
|
|
|
|
uc = c - '0'; |
|
|
|
|
|
if (uc > 9) break; |
|
|
|
|
|
exp++; |
|
|
|
|
|
} |
|
|
|
|
|
goto overflow; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
else { |
|
|
|
|
|
if (c != '.' || exp_dec != 0) break; |
|
|
|
|
|
exp_dec = 1; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// early return for 0
|
|
|
|
|
|
if (uval == 0) return 0; |
|
|
|
|
|
|
|
|
|
|
|
overflow: |
|
|
|
|
|
|
|
|
|
|
|
// convert to float and apply sign
|
|
|
|
|
|
float fval = uval; |
|
|
|
|
|
if (is_negative) fval *= -1; |
|
|
|
|
|
|
|
|
|
|
|
// apply exponent (up to 1e-15 / 1e+15)
|
|
|
|
|
|
if (exp < 0) { |
|
|
|
|
|
if (exp <= -8) { fval *= 1e-8; exp += 8; } |
|
|
|
|
|
if (exp <= -4) { fval *= 1e-4; exp += 4; } |
|
|
|
|
|
if (exp <= -2) { fval *= 1e-2; exp += 2; } |
|
|
|
|
|
if (exp <= -1) { fval *= 1e-1; exp += 1; } |
|
|
|
|
|
} |
|
|
|
|
|
else if (exp > 0) { |
|
|
|
|
|
if (exp >= 8) { fval *= 1e+8; exp -= 8; } |
|
|
|
|
|
if (exp >= 4) { fval *= 1e+4; exp -= 4; } |
|
|
|
|
|
if (exp >= 2) { fval *= 1e+2; exp -= 2; } |
|
|
|
|
|
if (exp >= 1) { fval *= 1e+1; exp -= 1; } |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return fval; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
// Must be declared for allocation and to satisfy the linker
|
|
|
// Must be declared for allocation and to satisfy the linker
|
|
|
// Zero values need no initialization.
|
|
|
// Zero values need no initialization.
|
|
|
|
|
|
|
|
|