|
@@ -28,6 +28,146 @@
|
28
|
28
|
|
29
|
29
|
#include "../MarlinCore.h"
|
30
|
30
|
|
|
31
|
+#ifdef __AVR__
|
|
32
|
+
|
|
33
|
+ static FORCE_INLINE uint32_t mult10(uint32_t val) {
|
|
34
|
+ uint32_t tmp = val;
|
|
35
|
+ __asm__ __volatile__ (
|
|
36
|
+ "add %A[tmp], %A[tmp]\n"
|
|
37
|
+ "adc %B[tmp], %B[tmp]\n"
|
|
38
|
+ "adc %C[tmp], %C[tmp]\n"
|
|
39
|
+ "adc %D[tmp], %D[tmp]\n"
|
|
40
|
+ "add %A[tmp], %A[tmp]\n"
|
|
41
|
+ "adc %B[tmp], %B[tmp]\n"
|
|
42
|
+ "adc %C[tmp], %C[tmp]\n"
|
|
43
|
+ "adc %D[tmp], %D[tmp]\n"
|
|
44
|
+ "add %A[val], %A[tmp]\n"
|
|
45
|
+ "adc %B[val], %B[tmp]\n"
|
|
46
|
+ "adc %C[val], %C[tmp]\n"
|
|
47
|
+ "adc %D[val], %D[tmp]\n"
|
|
48
|
+ "add %A[val], %A[val]\n"
|
|
49
|
+ "adc %B[val], %B[val]\n"
|
|
50
|
+ "adc %C[val], %C[val]\n"
|
|
51
|
+ "adc %D[val], %D[val]\n"
|
|
52
|
+ : [val] "+&r" (val),
|
|
53
|
+ [tmp] "+&r" (tmp)
|
|
54
|
+ );
|
|
55
|
+ return val;
|
|
56
|
+ }
|
|
57
|
+
|
|
58
|
+#else
|
|
59
|
+
|
|
60
|
+ static FORCE_INLINE uint32_t mult10(uint32_t val) { return val * 10; }
|
|
61
|
+
|
|
62
|
+#endif
|
|
63
|
+
|
|
64
|
+// cheap base-10 strto(u)l.
|
|
65
|
+// does not check for errors.
|
|
66
|
+int32_t parse_int32(const char *buf) {
|
|
67
|
+ char c;
|
|
68
|
+
|
|
69
|
+ // Get a char, skipping leading spaces
|
|
70
|
+ do { c = *buf++; } while (c == ' ');
|
|
71
|
+
|
|
72
|
+ // check for sign
|
|
73
|
+ bool is_negative = (c == '-');
|
|
74
|
+ if (is_negative || c == '+')
|
|
75
|
+ c = *buf++;
|
|
76
|
+
|
|
77
|
+ // optimization for first digit (no multiplication)
|
|
78
|
+ uint8_t uc = c - '0';
|
|
79
|
+ if (uc > 9) return 0;
|
|
80
|
+
|
|
81
|
+ // read unsigned value
|
|
82
|
+ uint32_t uval = uc;
|
|
83
|
+ while (true) {
|
|
84
|
+ c = *buf++;
|
|
85
|
+ uc = c - '0';
|
|
86
|
+ if (uc > 9) break;
|
|
87
|
+ uval = mult10(uval) + uc;
|
|
88
|
+ }
|
|
89
|
+
|
|
90
|
+ return is_negative ? -uval : uval;
|
|
91
|
+}
|
|
92
|
+
|
|
93
|
+// cheap strtof.
|
|
94
|
+// does not support nan/infinity or exponent notation.
|
|
95
|
+// does not check for errors.
|
|
96
|
+float parse_float(const char *buf) {
|
|
97
|
+ char c;
|
|
98
|
+
|
|
99
|
+ // Get a char, skipping leading spaces
|
|
100
|
+ do { c = *buf++; } while (c == ' ');
|
|
101
|
+
|
|
102
|
+ // check for sign
|
|
103
|
+ bool is_negative = (c == '-');
|
|
104
|
+ if (is_negative || c == '+')
|
|
105
|
+ c = *buf++;
|
|
106
|
+
|
|
107
|
+ // read unsigned value and decimal point
|
|
108
|
+ uint32_t uval;
|
|
109
|
+ uint8_t exp_dec;
|
|
110
|
+ uint8_t uc = c - '0';
|
|
111
|
+ if (uc <= 9) {
|
|
112
|
+ uval = uc;
|
|
113
|
+ exp_dec = 0;
|
|
114
|
+ }
|
|
115
|
+ else {
|
|
116
|
+ if (c != '.') return 0;
|
|
117
|
+ uval = 0;
|
|
118
|
+ exp_dec = 1;
|
|
119
|
+ }
|
|
120
|
+
|
|
121
|
+ int8_t exp = 0;
|
|
122
|
+ while (true) {
|
|
123
|
+ c = *buf++;
|
|
124
|
+ uc = c - '0';
|
|
125
|
+ if (uc <= 9) {
|
|
126
|
+ exp -= exp_dec;
|
|
127
|
+ uval = mult10(uval) + uc;
|
|
128
|
+ if (uval >= (UINT32_MAX - 9) / 10) {
|
|
129
|
+ // overflow. keep reading digits until decimal point.
|
|
130
|
+ while (exp_dec == 0) {
|
|
131
|
+ c = *buf++;
|
|
132
|
+ uc = c - '0';
|
|
133
|
+ if (uc > 9) break;
|
|
134
|
+ exp++;
|
|
135
|
+ }
|
|
136
|
+ goto overflow;
|
|
137
|
+ }
|
|
138
|
+ }
|
|
139
|
+ else {
|
|
140
|
+ if (c != '.' || exp_dec != 0) break;
|
|
141
|
+ exp_dec = 1;
|
|
142
|
+ }
|
|
143
|
+ }
|
|
144
|
+
|
|
145
|
+ // early return for 0
|
|
146
|
+ if (uval == 0) return 0;
|
|
147
|
+
|
|
148
|
+ overflow:
|
|
149
|
+
|
|
150
|
+ // convert to float and apply sign
|
|
151
|
+ float fval = uval;
|
|
152
|
+ if (is_negative) fval *= -1;
|
|
153
|
+
|
|
154
|
+ // apply exponent (up to 1e-15 / 1e+15)
|
|
155
|
+ if (exp < 0) {
|
|
156
|
+ if (exp <= -8) { fval *= 1e-8; exp += 8; }
|
|
157
|
+ if (exp <= -4) { fval *= 1e-4; exp += 4; }
|
|
158
|
+ if (exp <= -2) { fval *= 1e-2; exp += 2; }
|
|
159
|
+ if (exp <= -1) { fval *= 1e-1; exp += 1; }
|
|
160
|
+ }
|
|
161
|
+ else if (exp > 0) {
|
|
162
|
+ if (exp >= 8) { fval *= 1e+8; exp -= 8; }
|
|
163
|
+ if (exp >= 4) { fval *= 1e+4; exp -= 4; }
|
|
164
|
+ if (exp >= 2) { fval *= 1e+2; exp -= 2; }
|
|
165
|
+ if (exp >= 1) { fval *= 1e+1; exp -= 1; }
|
|
166
|
+ }
|
|
167
|
+
|
|
168
|
+ return fval;
|
|
169
|
+}
|
|
170
|
+
|
31
|
171
|
// Must be declared for allocation and to satisfy the linker
|
32
|
172
|
// Zero values need no initialization.
|
33
|
173
|
|