potentiall fix issue when filemant diamted or flow rate are changed during a print
[clinton/Smoothieware.git] / src / modules / utils / panel / screens / cnc / WatchScreen.cpp
CommitLineData
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
33using namespace std;
34
862fc625
JM
35WatchScreen::WatchScreen()
36{
37 speed_changed = false;
38 issue_change_speed = false;
383c9c1c 39 ipstr = nullptr;
c77d6dae 40 update_counts= 0;
383c9c1c
JM
41}
42
43WatchScreen::~WatchScreen()
44{
45 delete[] ipstr;
dcf86322 46}
35089dc7 47
862fc625
JM
48void 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
61void 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
104void 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
131void 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
141void 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 155float 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
161void 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
177void 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
194const 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
219void WatchScreen::set_speed()
220{
2fa50ca0 221 send_gcode("M220", 'S', this->current_speed);
dcf86322 222}
d4ee6ee2
JM
223
224const 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}