Merge branch 'feature/e-endstop' into merge-abc-with-homing
[clinton/Smoothieware.git] / src / libs / utils.cpp
CommitLineData
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 21using std::string;
4eb9c745 22
219fd4ba
JM
23uint16_t get_checksum(const string &to_check)
24{
d5d3d675
JM
25 return get_checksum(to_check.c_str());
26}
27
219fd4ba
JM
28uint16_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
42void 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
65bool 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
73bool is_digit(int c)
74{
75 if ((c >= '0') && (c <= '9')) return true;
76 return false;
77}
78
79bool 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
87bool is_alphanum(int c)
88{
89 return is_alpha(c) || is_numeric(c);
90}
91
92bool is_whitespace(int c)
93{
94 if ((c == ' ') || (c == '\t')) return true;
95 return false;
96}
97
4eb9c745 98// Convert to lowercase
219fd4ba
JM
99string 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
109string 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
122string shift_parameter( string &parameters )
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 136string 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
146bool 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
158void 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 )
173string 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
206vector<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
224vector<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
235vector<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 246int 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
257string 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
266void safe_delay_ms(uint32_t delay)
267{
268 safe_delay_us(delay*1000);
269}
270
271void 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}