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