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