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.
5 You should have received a copy of the GNU General Public License along with Smoothie. If not, see <http://www.gnu.org/licenses/>.
8 #include "libs/Kernel.h"
9 #include "libs/utils.h"
10 #include "system_LPC17xx.h"
23 uint16_t get_checksum(const string
&to_check
)
25 return get_checksum(to_check
.c_str());
28 uint16_t get_checksum(const char *to_check
)
30 // From: http://en.wikipedia.org/wiki/Fletcher%27s_checksum
33 const char *p
= to_check
;
35 while((c
= *p
++) != 0) {
36 sum1
= (sum1
+ c
) % 255;
37 sum2
= (sum2
+ sum1
) % 255;
39 return (sum2
<< 8) | sum1
;
42 void get_checksums(uint16_t check_sums
[], const string
&key
)
44 check_sums
[0] = 0x0000;
45 check_sums
[1] = 0x0000;
46 check_sums
[2] = 0x0000;
48 unsigned int counter
= 0;
49 while( begin_key
< key
.size() && counter
< 3 ) {
50 size_t end_key
= key
.find_first_of(".", begin_key
);
52 if(end_key
== string::npos
) {
53 key_node
= key
.substr(begin_key
);
55 key_node
= key
.substr(begin_key
, end_key
- begin_key
);
58 check_sums
[counter
] = get_checksum(key_node
);
59 if(end_key
== string::npos
) break;
60 begin_key
= end_key
+ 1;
67 if ((c
>= 'a') && (c
<= 'z')) return true;
68 if ((c
>= 'A') && (c
<= 'Z')) return true;
69 if ((c
== '_')) return true;
75 if ((c
>= '0') && (c
<= '9')) return true;
79 bool is_numeric(int c
)
81 if (is_digit(c
)) return true;
82 if ((c
== '.') || (c
== '-')) return true;
83 if ((c
== 'e')) return true;
87 bool is_alphanum(int c
)
89 return is_alpha(c
) || is_numeric(c
);
92 bool is_whitespace(int c
)
94 if ((c
== ' ') || (c
== '\t')) return true;
98 // Convert to lowercase
99 string
lc(const string
&str
)
103 lcstr
.append(1, ::tolower(c
));
108 // Remove non-number characters
109 string
remove_non_number( string str
)
111 string number_mask
= "0123456789-.abcdefpxABCDEFPX";
112 size_t found
= str
.find_first_not_of(number_mask
);
113 while (found
!= string::npos
) {
115 str
.replace(found
, 1, "");
116 found
= str
.find_first_not_of(number_mask
);
121 // Get the first parameter, and remove it from the original string
122 string
shift_parameter( string
¶meters
)
124 size_t beginning
= parameters
.find_first_of(" ");
125 if( beginning
== string::npos
) {
126 string temp
= parameters
;
130 string temp
= parameters
.substr( 0, beginning
);
131 parameters
= parameters
.substr(beginning
+ 1, parameters
.size());
135 // Separate command from arguments
136 string
get_arguments( const string
& possible_command
)
138 size_t beginning
= possible_command
.find_first_of(" ");
139 if( beginning
== string::npos
) {
142 return possible_command
.substr( beginning
+ 1, possible_command
.size() - beginning
+ 1);
145 // Returns true if the file exists
146 bool file_exists( const string file_name
)
149 FILE *lp
= fopen(file_name
.c_str(), "r");
157 // Prepares and executes a watchdog reset for dfu or reboot
158 void system_reset( bool 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;
172 // Convert a path indication ( absolute or relative ) into a path ( absolute )
173 string
absolute_from_relative( string path
)
175 string cwd
= THEKERNEL
->current_path
;
177 if ( path
.empty() ) {
178 return THEKERNEL
->current_path
;
181 if ( path
[0] == '/' ) {
185 while ( path
.substr(0, 3) == "../" ) {
186 path
= path
.substr(3);
187 unsigned found
= cwd
.find_last_of("/");
188 cwd
= cwd
.substr(0, found
);
191 if ( path
.substr(0, 2) == ".." ) {
192 path
= path
.substr(2);
193 unsigned found
= cwd
.find_last_of("/");
194 cwd
= cwd
.substr(0, found
);
197 if ( cwd
[cwd
.length() - 1] == '/' ) {
201 return cwd
+ '/' + path
;
204 // FIXME this does not handle empty strings correctly
205 //split a string on a delimiter, return a vector of the split tokens
206 vector
<string
> split(const char *str
, char c
)
208 vector
<string
> result
;
211 const char *begin
= str
;
213 while(*str
!= c
&& *str
)
216 result
.push_back(string(begin
, str
));
217 } while (0 != *str
++);
222 // FIXME this does not handle empty strings correctly
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
)
226 vector
<string
> l
= split(str
, ',');
229 float x
= strtof(s
.c_str(), nullptr);
235 vector
<uint32_t> parse_number_list(const char *str
, uint8_t radix
)
237 vector
<string
> l
= split(str
, ',');
240 uint32_t x
= strtol(s
.c_str(), nullptr, radix
);
246 int append_parameters(char *buf
, std::vector
<std::pair
<char,float>> params
, size_t bufsize
)
249 for(auto &i
: params
) {
250 if(n
>= bufsize
) break;
252 n
+= snprintf(&buf
[n
], bufsize
-n
, "%1.4f ", i
.second
);
257 string
wcs2gcode(int wcs
) {
259 str
.append(1, std::min(wcs
, 5) + '4');
261 str
.append(".").append(1, '1' + (wcs
- 6));
266 void safe_delay_ms(uint32_t delay
)
268 safe_delay_us(delay
*1000);
271 void safe_delay_us(uint32_t dus
)
273 uint32_t start
= us_ticker_read();
274 while ((us_ticker_read() - start
) < dus
) {
275 THEKERNEL
->call_event(ON_IDLE
);