Commit | Line | Data |
---|---|---|
df27a6a3 | 1 | /* |
cd011f58 AW |
2 | This file is part of Smoothie (http://smoothieware.org/). The motion control part is heavily based on Grbl (https://github.com/simen/grbl). |
3 | Smoothie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. | |
4 | Smoothie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. | |
df27a6a3 | 5 | You should have received a copy of the GNU General Public License along with Smoothie. If not, see <http://www.gnu.org/licenses/>. |
cd011f58 AW |
6 | */ |
7 | ||
4de76b51 | 8 | #include "libs/Kernel.h" |
4eb9c745 | 9 | #include "libs/utils.h" |
4de76b51 | 10 | #include "system_LPC17xx.h" |
61134a65 JM |
11 | #include "LPC17xx.h" |
12 | #include "utils.h" | |
219fd4ba | 13 | |
4eb9c745 | 14 | #include <string> |
423df6df | 15 | #include <cstring> |
61134a65 | 16 | #include <stdio.h> |
f6fc8c0d | 17 | #include <cstdlib> |
7f3e6350 | 18 | |
37102904 JM |
19 | #include "mbed.h" |
20 | ||
219fd4ba | 21 | using std::string; |
4eb9c745 | 22 | |
219fd4ba JM |
23 | uint16_t get_checksum(const string &to_check) |
24 | { | |
d5d3d675 JM |
25 | return get_checksum(to_check.c_str()); |
26 | } | |
27 | ||
219fd4ba JM |
28 | uint16_t get_checksum(const char *to_check) |
29 | { | |
30 | // From: http://en.wikipedia.org/wiki/Fletcher%27s_checksum | |
31 | uint16_t sum1 = 0; | |
32 | uint16_t sum2 = 0; | |
33 | const char *p = to_check; | |
34 | char c; | |
35 | while((c = *p++) != 0) { | |
36 | sum1 = (sum1 + c) % 255; | |
37 | sum2 = (sum2 + sum1) % 255; | |
38 | } | |
39 | return (sum2 << 8) | sum1; | |
4eb9c745 AW |
40 | } |
41 | ||
219fd4ba JM |
42 | void get_checksums(uint16_t check_sums[], const string &key) |
43 | { | |
4464301d AW |
44 | check_sums[0] = 0x0000; |
45 | check_sums[1] = 0x0000; | |
46 | check_sums[2] = 0x0000; | |
5efaa1b1 | 47 | size_t begin_key = 0; |
df27a6a3 | 48 | unsigned int counter = 0; |
219fd4ba | 49 | while( begin_key < key.size() && counter < 3 ) { |
d8cff5af JM |
50 | size_t end_key = key.find_first_of(".", begin_key); |
51 | string key_node; | |
52 | if(end_key == string::npos) { | |
219fd4ba JM |
53 | key_node = key.substr(begin_key); |
54 | } else { | |
55 | key_node = key.substr(begin_key, end_key - begin_key); | |
d8cff5af JM |
56 | } |
57 | ||
4464301d | 58 | check_sums[counter] = get_checksum(key_node); |
d8cff5af | 59 | if(end_key == string::npos) break; |
5efaa1b1 | 60 | begin_key = end_key + 1; |
4464301d | 61 | counter++; |
5efaa1b1 | 62 | } |
5efaa1b1 L |
63 | } |
64 | ||
a2970685 MM |
65 | bool is_alpha(int c) |
66 | { | |
67 | if ((c >= 'a') && (c <= 'z')) return true; | |
68 | if ((c >= 'A') && (c <= 'Z')) return true; | |
69 | if ((c == '_')) return true; | |
70 | return false; | |
71 | } | |
72 | ||
73 | bool is_digit(int c) | |
74 | { | |
75 | if ((c >= '0') && (c <= '9')) return true; | |
76 | return false; | |
77 | } | |
78 | ||
79 | bool is_numeric(int c) | |
80 | { | |
81 | if (is_digit(c)) return true; | |
82 | if ((c == '.') || (c == '-')) return true; | |
83 | if ((c == 'e')) return true; | |
84 | return false; | |
85 | } | |
86 | ||
87 | bool is_alphanum(int c) | |
88 | { | |
89 | return is_alpha(c) || is_numeric(c); | |
90 | } | |
91 | ||
92 | bool is_whitespace(int c) | |
93 | { | |
94 | if ((c == ' ') || (c == '\t')) return true; | |
95 | return false; | |
96 | } | |
97 | ||
4eb9c745 | 98 | // Convert to lowercase |
219fd4ba JM |
99 | string lc(const string &str) |
100 | { | |
101 | string lcstr; | |
102 | for (auto c : str) { | |
103 | lcstr.append(1, ::tolower(c)); | |
104 | } | |
105 | return lcstr; | |
4eb9c745 AW |
106 | } |
107 | ||
a699b669 | 108 | // Remove non-number characters |
219fd4ba JM |
109 | string remove_non_number( string str ) |
110 | { | |
dfb53c73 | 111 | string number_mask = "0123456789-.abcdefpxABCDEFPX"; |
219fd4ba JM |
112 | size_t found = str.find_first_not_of(number_mask); |
113 | while (found != string::npos) { | |
a699b669 | 114 | //str[found]='*'; |
219fd4ba JM |
115 | str.replace(found, 1, ""); |
116 | found = str.find_first_not_of(number_mask); | |
a699b669 AW |
117 | } |
118 | return str; | |
119 | } | |
120 | ||
4eb9c745 | 121 | // Get the first parameter, and remove it from the original string |
219fd4ba JM |
122 | string shift_parameter( string ¶meters ) |
123 | { | |
4eb9c745 | 124 | size_t beginning = parameters.find_first_of(" "); |
219fd4ba JM |
125 | if( beginning == string::npos ) { |
126 | string temp = parameters; | |
127 | parameters = ""; | |
128 | return temp; | |
129 | } | |
4eb9c745 | 130 | string temp = parameters.substr( 0, beginning ); |
219fd4ba | 131 | parameters = parameters.substr(beginning + 1, parameters.size()); |
4eb9c745 AW |
132 | return temp; |
133 | } | |
cebe90b6 AW |
134 | |
135 | // Separate command from arguments | |
c0b50fa8 | 136 | string get_arguments( const string& possible_command ) |
219fd4ba | 137 | { |
cebe90b6 | 138 | size_t beginning = possible_command.find_first_of(" "); |
219fd4ba JM |
139 | if( beginning == string::npos ) { |
140 | return ""; | |
141 | } | |
5b81ce13 | 142 | return possible_command.substr( beginning + 1, possible_command.size() - beginning + 1); |
cebe90b6 AW |
143 | } |
144 | ||
8d857d2e | 145 | // Returns true if the file exists |
219fd4ba JM |
146 | bool file_exists( const string file_name ) |
147 | { | |
8d857d2e L |
148 | bool exists = false; |
149 | FILE *lp = fopen(file_name.c_str(), "r"); | |
219fd4ba JM |
150 | if(lp) { |
151 | exists = true; | |
152 | } | |
8d857d2e L |
153 | fclose(lp); |
154 | return exists; | |
155 | } | |
156 | ||
2742fca9 | 157 | // Prepares and executes a watchdog reset for dfu or reboot |
219fd4ba JM |
158 | void system_reset( bool dfu ) |
159 | { | |
ed7c5844 JM |
160 | if(dfu) { |
161 | LPC_WDT->WDCLKSEL = 0x1; // Set CLK src to PCLK | |
162 | uint32_t clk = SystemCoreClock / 16; // WD has a fixed /4 prescaler, PCLK default is /4 | |
163 | LPC_WDT->WDTC = 1 * (float)clk; // Reset in 1 second | |
164 | LPC_WDT->WDMOD = 0x3; // Enabled and Reset | |
165 | LPC_WDT->WDFEED = 0xAA; // Kick the dog! | |
166 | LPC_WDT->WDFEED = 0x55; | |
219fd4ba | 167 | } else { |
ed7c5844 JM |
168 | NVIC_SystemReset(); |
169 | } | |
4de76b51 | 170 | } |
cebe90b6 | 171 | |
75f4581c JM |
172 | // Convert a path indication ( absolute or relative ) into a path ( absolute ) |
173 | string absolute_from_relative( string path ) | |
174 | { | |
175 | string cwd = THEKERNEL->current_path; | |
176 | ||
177 | if ( path.empty() ) { | |
178 | return THEKERNEL->current_path; | |
179 | } | |
180 | ||
181 | if ( path[0] == '/' ) { | |
182 | return path; | |
183 | } | |
184 | ||
782b3e0d | 185 | while ( path.substr(0, 3) == "../" ) { |
75f4581c JM |
186 | path = path.substr(3); |
187 | unsigned found = cwd.find_last_of("/"); | |
219fd4ba | 188 | cwd = cwd.substr(0, found); |
75f4581c JM |
189 | } |
190 | ||
782b3e0d | 191 | if ( path.substr(0, 2) == ".." ) { |
75f4581c JM |
192 | path = path.substr(2); |
193 | unsigned found = cwd.find_last_of("/"); | |
219fd4ba | 194 | cwd = cwd.substr(0, found); |
75f4581c JM |
195 | } |
196 | ||
197 | if ( cwd[cwd.length() - 1] == '/' ) { | |
219fd4ba | 198 | return cwd + path; |
75f4581c JM |
199 | } |
200 | ||
201 | return cwd + '/' + path; | |
202 | } | |
f6fc8c0d | 203 | |
7f3e6350 | 204 | // FIXME this does not handle empty strings correctly |
f6fc8c0d JM |
205 | //split a string on a delimiter, return a vector of the split tokens |
206 | vector<string> split(const char *str, char c) | |
207 | { | |
208 | vector<string> result; | |
209 | ||
210 | do { | |
211 | const char *begin = str; | |
212 | ||
213 | while(*str != c && *str) | |
214 | str++; | |
215 | ||
216 | result.push_back(string(begin, str)); | |
217 | } while (0 != *str++); | |
218 | ||
219 | return result; | |
220 | } | |
221 | ||
7f3e6350 | 222 | // FIXME this does not handle empty strings correctly |
f6fc8c0d JM |
223 | // parse a number list "1.1,2.2,3.3" and return the numbers in a vector of floats |
224 | vector<float> parse_number_list(const char *str) | |
225 | { | |
226 | vector<string> l= split(str, ','); | |
227 | vector<float> r; | |
7b35a4c8 | 228 | for(auto& s : l){ |
f6fc8c0d JM |
229 | float x = strtof(s.c_str(), nullptr); |
230 | r.push_back(x); | |
231 | } | |
232 | return r; | |
233 | } | |
7f3e6350 | 234 | |
7b35a4c8 JM |
235 | vector<uint32_t> parse_number_list(const char *str, uint8_t radix) |
236 | { | |
237 | vector<string> l= split(str, ','); | |
238 | vector<uint32_t> r; | |
239 | for(auto& s : l){ | |
240 | uint32_t x = strtol(s.c_str(), nullptr, radix); | |
241 | r.push_back(x); | |
242 | } | |
243 | return r; | |
244 | } | |
245 | ||
7c801094 | 246 | int append_parameters(char *buf, std::vector<std::pair<char,float>> params, size_t bufsize) |
7f3e6350 | 247 | { |
7c801094 | 248 | size_t n= 0; |
7f3e6350 | 249 | for(auto &i : params) { |
7c801094 JM |
250 | if(n >= bufsize) break; |
251 | buf[n++]= i.first; | |
252 | n += snprintf(&buf[n], bufsize-n, "%1.4f ", i.second); | |
7f3e6350 | 253 | } |
7c801094 | 254 | return n; |
7f3e6350 | 255 | } |
40fd5d98 JM |
256 | |
257 | string wcs2gcode(int wcs) { | |
258 | string str= "G5"; | |
259 | str.append(1, std::min(wcs, 5) + '4'); | |
260 | if(wcs >= 6) { | |
261 | str.append(".").append(1, '1' + (wcs - 6)); | |
262 | } | |
263 | return str; | |
264 | } | |
37102904 | 265 | |
be7f67cd JM |
266 | void safe_delay_ms(uint32_t delay) |
267 | { | |
268 | safe_delay_us(delay*1000); | |
269 | } | |
270 | ||
271 | void safe_delay_us(uint32_t dus) | |
37102904 | 272 | { |
37102904 JM |
273 | uint32_t start = us_ticker_read(); |
274 | while ((us_ticker_read() - start) < dus) { | |
275 | THEKERNEL->call_event(ON_IDLE); | |
276 | } | |
277 | } |