Commit | Line | Data |
---|---|---|
3105a7be | 1 | /* |
35089dc7 JM |
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. | |
3105a7be | 5 | You should have received a copy of the GNU General Public License along with Smoothie. If not, see <http://www.gnu.org/licenses/>. |
35089dc7 JM |
6 | */ |
7 | ||
8 | #include "libs/Kernel.h" | |
383c9c1c | 9 | #include "LcdBase.h" |
35089dc7 JM |
10 | #include "Panel.h" |
11 | #include "PanelScreen.h" | |
12 | #include "MainMenuScreen.h" | |
13 | #include "WatchScreen.h" | |
14 | #include "libs/nuts_bolts.h" | |
15 | #include "libs/utils.h" | |
564cf1f0 | 16 | #include "Robot.h" |
c7f4902c | 17 | #include "Conveyor.h" |
691dcad3 | 18 | #include "modules/robot/Conveyor.h" |
35089dc7 | 19 | #include "modules/utils/player/PlayerPublicAccess.h" |
d4ee6ee2 | 20 | #include "NetworkPublicAccess.h" |
61134a65 | 21 | #include "PublicData.h" |
f1aac8df | 22 | #include "SwitchPublicAccess.h" |
61134a65 | 23 | #include "checksumm.h" |
8a75ef4a JM |
24 | #include "StepperMotor.h" |
25 | #include "BaseSolution.h" | |
02e4b295 | 26 | |
646d62d0 JM |
27 | #ifndef NO_TOOLS_LASER |
28 | #include "Laser.h" | |
29 | #endif | |
30 | ||
61134a65 JM |
31 | #include <math.h> |
32 | #include <string.h> | |
35089dc7 | 33 | #include <string> |
383c9c1c | 34 | #include <stdio.h> |
373d0bf1 | 35 | #include <algorithm> |
61134a65 | 36 | |
35089dc7 JM |
37 | using namespace std; |
38 | ||
646d62d0 JM |
39 | #define laser_checksum CHECKSUM("laser") |
40 | ||
862fc625 JM |
41 | WatchScreen::WatchScreen() |
42 | { | |
43 | speed_changed = false; | |
44 | issue_change_speed = false; | |
383c9c1c | 45 | ipstr = nullptr; |
c77d6dae | 46 | update_counts= 0; |
383c9c1c JM |
47 | } |
48 | ||
49 | WatchScreen::~WatchScreen() | |
50 | { | |
51 | delete[] ipstr; | |
dcf86322 | 52 | } |
35089dc7 | 53 | |
862fc625 JM |
54 | void WatchScreen::on_enter() |
55 | { | |
cee1bb2d | 56 | THEPANEL->lcd->clear(); |
289380f2 | 57 | THEPANEL->setup_menu(8); |
c77d6dae | 58 | get_current_status(); |
8a75ef4a | 59 | get_wpos(); |
58d6d841 | 60 | get_sd_play_info(); |
586cc733 | 61 | this->current_speed = lroundf(get_current_speed()); |
58d6d841 | 62 | this->refresh_screen(false); |
cee1bb2d JM |
63 | THEPANEL->enter_control_mode(1, 0.5); |
64 | THEPANEL->set_control_value(this->current_speed); | |
35089dc7 JM |
65 | } |
66 | ||
862fc625 JM |
67 | void WatchScreen::on_refresh() |
68 | { | |
3105a7be | 69 | // Exit if the button is clicked |
cee1bb2d JM |
70 | if ( THEPANEL->click() ) { |
71 | THEPANEL->enter_screen(this->parent); | |
35089dc7 | 72 | return; |
58d6d841 JM |
73 | } |
74 | ||
75 | // see if speed is being changed | |
cee1bb2d JM |
76 | if (THEPANEL->control_value_change()) { |
77 | this->current_speed = THEPANEL->get_control_value(); | |
862fc625 JM |
78 | if (this->current_speed < 10) { |
79 | this->current_speed = 10; | |
cee1bb2d JM |
80 | THEPANEL->set_control_value(this->current_speed); |
81 | THEPANEL->reset_counter(); | |
862fc625 | 82 | } else { |
3f038f58 JM |
83 | // flag the update to change the speed, we don't want to issue hundreds of M220s |
84 | // but we do want to display the change we are going to make | |
862fc625 | 85 | this->speed_changed = true; // flag indicating speed changed |
7a522ccc JM |
86 | this->refresh_screen(false); |
87 | } | |
58d6d841 | 88 | } |
3105a7be | 89 | |
35089dc7 | 90 | // Update Only every 20 refreshes, 1 a second |
35089dc7 | 91 | update_counts++; |
862fc625 | 92 | if ( update_counts % 20 == 0 ) { |
58d6d841 | 93 | get_sd_play_info(); |
8a75ef4a | 94 | get_wpos(); |
c77d6dae | 95 | get_current_status(); |
862fc625 JM |
96 | if (this->speed_changed) { |
97 | this->issue_change_speed = true; // trigger actual command to change speed | |
98 | this->speed_changed = false; | |
99 | } else if (!this->issue_change_speed) { // change still queued | |
3f038f58 | 100 | // read it in case it was changed via M220 |
586cc733 | 101 | this->current_speed = lroundf(get_current_speed()); |
cee1bb2d JM |
102 | THEPANEL->set_control_value(this->current_speed); |
103 | THEPANEL->reset_counter(); | |
3f038f58 | 104 | } |
7a522ccc | 105 | |
cee1bb2d | 106 | this->refresh_screen(THEPANEL->lcd->hasGraphics() ? true : false); // graphics screens should be cleared |
35089dc7 JM |
107 | } |
108 | } | |
109 | ||
8a75ef4a JM |
110 | void WatchScreen::get_wpos() |
111 | { | |
112 | // get real time positions | |
8a75ef4a | 113 | float mpos[3]; |
fdfa00d2 | 114 | THEROBOT->get_current_machine_position(mpos); |
c8bac202 JM |
115 | Robot::wcs_t wpos= THEROBOT->mcs2wcs(mpos); |
116 | this->wpos[0]= THEROBOT->from_millimeters(std::get<X_AXIS>(wpos)); | |
117 | this->wpos[1]= THEROBOT->from_millimeters(std::get<Y_AXIS>(wpos)); | |
118 | this->wpos[2]= THEROBOT->from_millimeters(std::get<Z_AXIS>(wpos)); | |
119 | this->mpos[0]= THEROBOT->from_millimeters(mpos[0]); | |
120 | this->mpos[1]= THEROBOT->from_millimeters(mpos[1]); | |
121 | this->mpos[2]= THEROBOT->from_millimeters(mpos[2]); | |
122 | ||
123 | std::vector<Robot::wcs_t> v= THEROBOT->get_wcs_state(); | |
381fbb3b JM |
124 | char current_wcs= std::get<0>(v[0]); |
125 | this->wcs= wcs2gcode(current_wcs); | |
8a75ef4a JM |
126 | } |
127 | ||
dcf86322 | 128 | // queuing gcodes needs to be done from main loop |
862fc625 JM |
129 | void WatchScreen::on_main_loop() |
130 | { | |
131 | if (this->issue_change_speed) { | |
132 | this->issue_change_speed = false; | |
3f038f58 JM |
133 | set_speed(); |
134 | } | |
f15e6f4b | 135 | PanelScreen::on_main_loop(); // in case any queued commands left |
dcf86322 JM |
136 | } |
137 | ||
c77d6dae JM |
138 | // fetch the data we are displaying |
139 | void WatchScreen::get_current_status() | |
140 | { | |
8a75ef4a | 141 | // get spindle status |
1ae7e276 JM |
142 | struct pad_switch s; |
143 | bool ok = PublicData::get_value( switch_checksum, fan_checksum, 0, &s ); | |
f1aac8df | 144 | if (ok) { |
8a75ef4a | 145 | this->spindle_state = s.state; |
f1aac8df | 146 | } else { |
8a75ef4a JM |
147 | // spindle probably disabled |
148 | this->spindle_state = false; | |
f1aac8df | 149 | } |
35089dc7 JM |
150 | } |
151 | ||
152 | // fetch the data we are displaying | |
1ad23cd3 | 153 | float WatchScreen::get_current_speed() |
862fc625 | 154 | { |
564cf1f0 | 155 | // in percent |
c8bac202 | 156 | return 6000.0F / THEROBOT->get_seconds_per_minute(); |
35089dc7 JM |
157 | } |
158 | ||
862fc625 JM |
159 | void WatchScreen::get_sd_play_info() |
160 | { | |
58d6d841 | 161 | void *returned_data; |
75e6428d | 162 | bool ok = PublicData::get_value( player_checksum, get_progress_checksum, &returned_data ); |
862fc625 JM |
163 | if (ok) { |
164 | struct pad_progress p = *static_cast<struct pad_progress *>(returned_data); | |
165 | this->elapsed_time = p.elapsed_secs; | |
166 | this->sd_pcnt_played = p.percent_complete; | |
cee1bb2d | 167 | THEPANEL->set_playing_file(p.filename); |
4c8afa75 | 168 | |
862fc625 JM |
169 | } else { |
170 | this->elapsed_time = 0; | |
171 | this->sd_pcnt_played = 0; | |
58d6d841 | 172 | } |
35089dc7 JM |
173 | } |
174 | ||
862fc625 JM |
175 | void WatchScreen::display_menu_line(uint16_t line) |
176 | { | |
58d6d841 | 177 | // in menu mode |
862fc625 | 178 | switch ( line ) { |
c8bac202 | 179 | case 0: THEPANEL->lcd->printf(" WCS MCS %s", THEROBOT->inch_mode ? "in" : "mm"); break; |
8a75ef4a JM |
180 | case 1: THEPANEL->lcd->printf("X %8.3f %8.3f", wpos[0], mpos[0]); break; |
181 | case 2: THEPANEL->lcd->printf("Y %8.3f %8.3f", wpos[1], mpos[1]); break; | |
182 | case 3: THEPANEL->lcd->printf("Z %8.3f %8.3f", wpos[2], mpos[2]); break; | |
c7f4902c | 183 | case 4: THEPANEL->lcd->printf("%s F%6.1f/%6.1f", this->wcs.c_str(), // display requested feedrate and actual feedrate |
c8bac202 JM |
184 | THEROBOT->from_millimeters(THEROBOT->get_feed_rate()), |
185 | THEROBOT->from_millimeters(THEKERNEL->conveyor->get_current_feedrate()*60.0F)); | |
c7f4902c | 186 | break; |
381fbb3b | 187 | case 5: THEPANEL->lcd->printf("%3d%% %2lu:%02lu %3u%% sd", this->current_speed, this->elapsed_time / 60, this->elapsed_time % 60, this->sd_pcnt_played); break; |
646d62d0 JM |
188 | case 6: |
189 | if(THEPANEL->has_laser()){ | |
190 | #ifndef NO_TOOLS_LASER | |
191 | Laser *plaser= nullptr; | |
192 | if(PublicData::get_value(laser_checksum, (void *)&plaser) && plaser != nullptr) { | |
1fa0f55a | 193 | THEPANEL->lcd->printf("Laser S%1.4f/%1.2f%%", THEROBOT->get_s_value(), plaser->get_current_power()); |
646d62d0 JM |
194 | } |
195 | #endif | |
646d62d0 | 196 | } |
611fc309 | 197 | break; |
289380f2 | 198 | case 7: THEPANEL->lcd->printf("%19s", this->get_status()); break; |
58d6d841 | 199 | } |
35089dc7 | 200 | } |
84267f43 | 201 | |
862fc625 JM |
202 | const char *WatchScreen::get_status() |
203 | { | |
5f1a896b | 204 | if (THEPANEL->hasMessage()) |
cee1bb2d | 205 | return THEPANEL->getMessage().c_str(); |
399cb110 | 206 | |
73706276 | 207 | if (THEKERNEL->is_halted()) |
8a75ef4a | 208 | return "ALARM"; |
76217df5 | 209 | |
cc7ea0e1 JM |
210 | if (THEKERNEL->get_feed_hold()) |
211 | return "Hold"; | |
212 | ||
213 | if (THEPANEL->is_suspended()) | |
716c7597 | 214 | return "Suspended"; |
5f1a896b | 215 | |
cee1bb2d JM |
216 | if (THEPANEL->is_playing()) |
217 | return THEPANEL->get_playing_file(); | |
84267f43 | 218 | |
7baa50df | 219 | if (!THECONVEYOR->is_idle()) |
8a75ef4a | 220 | return "Running"; |
691dcad3 | 221 | |
d4ee6ee2 JM |
222 | const char *ip = get_network(); |
223 | if (ip == NULL) { | |
8a75ef4a | 224 | return "Idle"; |
d4ee6ee2 JM |
225 | } else { |
226 | return ip; | |
227 | } | |
84267f43 | 228 | } |
dcf86322 | 229 | |
862fc625 JM |
230 | void WatchScreen::set_speed() |
231 | { | |
2fa50ca0 | 232 | send_gcode("M220", 'S', this->current_speed); |
dcf86322 | 233 | } |
d4ee6ee2 JM |
234 | |
235 | const char *WatchScreen::get_network() | |
236 | { | |
237 | void *returned_data; | |
238 | ||
75e6428d | 239 | bool ok = PublicData::get_value( network_checksum, get_ip_checksum, &returned_data ); |
d4ee6ee2 JM |
240 | if (ok) { |
241 | uint8_t *ipaddr = (uint8_t *)returned_data; | |
242 | char buf[20]; | |
243 | int n = snprintf(buf, sizeof(buf), "IP %d.%d.%d.%d", ipaddr[0], ipaddr[1], ipaddr[2], ipaddr[3]); | |
244 | buf[n] = 0; | |
383c9c1c JM |
245 | if (this->ipstr == nullptr) { |
246 | this->ipstr = new char[n + 1]; | |
d4ee6ee2 JM |
247 | } |
248 | strcpy(this->ipstr, buf); | |
249 | ||
250 | return this->ipstr; | |
251 | } | |
252 | ||
253 | return NULL; | |
254 | } |