Merge remote-tracking branch 'upstream/edge' into upstream-master
[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
219fd4ba 19using std::string;
4eb9c745 20
219fd4ba
JM
21uint16_t get_checksum(const string &to_check)
22{
d5d3d675
JM
23 return get_checksum(to_check.c_str());
24}
25
219fd4ba
JM
26uint16_t get_checksum(const char *to_check)
27{
28 // From: http://en.wikipedia.org/wiki/Fletcher%27s_checksum
29 uint16_t sum1 = 0;
30 uint16_t sum2 = 0;
31 const char *p = to_check;
32 char c;
33 while((c = *p++) != 0) {
34 sum1 = (sum1 + c) % 255;
35 sum2 = (sum2 + sum1) % 255;
36 }
37 return (sum2 << 8) | sum1;
4eb9c745
AW
38}
39
219fd4ba
JM
40void get_checksums(uint16_t check_sums[], const string &key)
41{
4464301d
AW
42 check_sums[0] = 0x0000;
43 check_sums[1] = 0x0000;
44 check_sums[2] = 0x0000;
5efaa1b1 45 size_t begin_key = 0;
df27a6a3 46 unsigned int counter = 0;
219fd4ba 47 while( begin_key < key.size() && counter < 3 ) {
d8cff5af
JM
48 size_t end_key = key.find_first_of(".", begin_key);
49 string key_node;
50 if(end_key == string::npos) {
219fd4ba
JM
51 key_node = key.substr(begin_key);
52 } else {
53 key_node = key.substr(begin_key, end_key - begin_key);
d8cff5af
JM
54 }
55
4464301d 56 check_sums[counter] = get_checksum(key_node);
d8cff5af 57 if(end_key == string::npos) break;
5efaa1b1 58 begin_key = end_key + 1;
4464301d 59 counter++;
5efaa1b1 60 }
5efaa1b1
L
61}
62
a2970685
MM
63bool is_alpha(int c)
64{
65 if ((c >= 'a') && (c <= 'z')) return true;
66 if ((c >= 'A') && (c <= 'Z')) return true;
67 if ((c == '_')) return true;
68 return false;
69}
70
71bool is_digit(int c)
72{
73 if ((c >= '0') && (c <= '9')) return true;
74 return false;
75}
76
77bool is_numeric(int c)
78{
79 if (is_digit(c)) return true;
80 if ((c == '.') || (c == '-')) return true;
81 if ((c == 'e')) return true;
82 return false;
83}
84
85bool is_alphanum(int c)
86{
87 return is_alpha(c) || is_numeric(c);
88}
89
90bool is_whitespace(int c)
91{
92 if ((c == ' ') || (c == '\t')) return true;
93 return false;
94}
95
4eb9c745 96// Convert to lowercase
219fd4ba
JM
97string lc(const string &str)
98{
99 string lcstr;
100 for (auto c : str) {
101 lcstr.append(1, ::tolower(c));
102 }
103 return lcstr;
4eb9c745
AW
104}
105
a699b669 106// Remove non-number characters
219fd4ba
JM
107string remove_non_number( string str )
108{
dfb53c73 109 string number_mask = "0123456789-.abcdefpxABCDEFPX";
219fd4ba
JM
110 size_t found = str.find_first_not_of(number_mask);
111 while (found != string::npos) {
a699b669 112 //str[found]='*';
219fd4ba
JM
113 str.replace(found, 1, "");
114 found = str.find_first_not_of(number_mask);
a699b669
AW
115 }
116 return str;
117}
118
4eb9c745 119// Get the first parameter, and remove it from the original string
219fd4ba
JM
120string shift_parameter( string &parameters )
121{
4eb9c745 122 size_t beginning = parameters.find_first_of(" ");
219fd4ba
JM
123 if( beginning == string::npos ) {
124 string temp = parameters;
125 parameters = "";
126 return temp;
127 }
4eb9c745 128 string temp = parameters.substr( 0, beginning );
219fd4ba 129 parameters = parameters.substr(beginning + 1, parameters.size());
4eb9c745
AW
130 return temp;
131}
cebe90b6
AW
132
133// Separate command from arguments
219fd4ba
JM
134string get_arguments( string possible_command )
135{
cebe90b6 136 size_t beginning = possible_command.find_first_of(" ");
219fd4ba
JM
137 if( beginning == string::npos ) {
138 return "";
139 }
5b81ce13 140 return possible_command.substr( beginning + 1, possible_command.size() - beginning + 1);
cebe90b6
AW
141}
142
8d857d2e 143// Returns true if the file exists
219fd4ba
JM
144bool file_exists( const string file_name )
145{
8d857d2e
L
146 bool exists = false;
147 FILE *lp = fopen(file_name.c_str(), "r");
219fd4ba
JM
148 if(lp) {
149 exists = true;
150 }
8d857d2e
L
151 fclose(lp);
152 return exists;
153}
154
2742fca9 155// Prepares and executes a watchdog reset for dfu or reboot
219fd4ba
JM
156void system_reset( bool dfu )
157{
ed7c5844
JM
158 if(dfu) {
159 LPC_WDT->WDCLKSEL = 0x1; // Set CLK src to PCLK
160 uint32_t clk = SystemCoreClock / 16; // WD has a fixed /4 prescaler, PCLK default is /4
161 LPC_WDT->WDTC = 1 * (float)clk; // Reset in 1 second
162 LPC_WDT->WDMOD = 0x3; // Enabled and Reset
163 LPC_WDT->WDFEED = 0xAA; // Kick the dog!
164 LPC_WDT->WDFEED = 0x55;
219fd4ba 165 } else {
ed7c5844
JM
166 NVIC_SystemReset();
167 }
4de76b51 168}
cebe90b6 169
75f4581c 170// Convert a path indication ( absolute or relative ) into a path ( absolute )
7027d199 171// TODO: Combine with plan9 absolute_path, current_path as argument?
75f4581c
JM
172string absolute_from_relative( string path )
173{
174 string cwd = THEKERNEL->current_path;
175
176 if ( path.empty() ) {
177 return THEKERNEL->current_path;
178 }
179
180 if ( path[0] == '/' ) {
181 return path;
182 }
183
782b3e0d 184 while ( path.substr(0, 3) == "../" ) {
75f4581c
JM
185 path = path.substr(3);
186 unsigned found = cwd.find_last_of("/");
219fd4ba 187 cwd = cwd.substr(0, found);
75f4581c
JM
188 }
189
782b3e0d 190 if ( path.substr(0, 2) == ".." ) {
75f4581c
JM
191 path = path.substr(2);
192 unsigned found = cwd.find_last_of("/");
219fd4ba 193 cwd = cwd.substr(0, found);
75f4581c
JM
194 }
195
196 if ( cwd[cwd.length() - 1] == '/' ) {
219fd4ba 197 return cwd + path;
75f4581c
JM
198 }
199
200 return cwd + '/' + path;
201}
f6fc8c0d 202
7f3e6350 203// FIXME this does not handle empty strings correctly
f6fc8c0d
JM
204//split a string on a delimiter, return a vector of the split tokens
205vector<string> split(const char *str, char c)
206{
207 vector<string> result;
208
209 do {
210 const char *begin = str;
211
212 while(*str != c && *str)
213 str++;
214
215 result.push_back(string(begin, str));
216 } while (0 != *str++);
217
218 return result;
219}
220
7f3e6350 221// FIXME this does not handle empty strings correctly
f6fc8c0d
JM
222// parse a number list "1.1,2.2,3.3" and return the numbers in a vector of floats
223vector<float> parse_number_list(const char *str)
224{
225 vector<string> l= split(str, ',');
226 vector<float> r;
7b35a4c8 227 for(auto& s : l){
f6fc8c0d
JM
228 float x = strtof(s.c_str(), nullptr);
229 r.push_back(x);
230 }
231 return r;
232}
7f3e6350 233
7b35a4c8
JM
234vector<uint32_t> parse_number_list(const char *str, uint8_t radix)
235{
236 vector<string> l= split(str, ',');
237 vector<uint32_t> r;
238 for(auto& s : l){
239 uint32_t x = strtol(s.c_str(), nullptr, radix);
240 r.push_back(x);
241 }
242 return r;
243}
244
7c801094 245int append_parameters(char *buf, std::vector<std::pair<char,float>> params, size_t bufsize)
7f3e6350 246{
7c801094 247 size_t n= 0;
7f3e6350 248 for(auto &i : params) {
7c801094
JM
249 if(n >= bufsize) break;
250 buf[n++]= i.first;
251 n += snprintf(&buf[n], bufsize-n, "%1.4f ", i.second);
7f3e6350 252 }
7c801094 253 return n;
7f3e6350 254}