Fork of Smoothie to port to mbed non-LPC targets.
Fork of Smoothie by
WatchScreen.cpp
00001 /* 00002 This file is part of Smoothie (http://smoothieware.org/). The motion control part is heavily based on Grbl (https://github.com/simen/grbl). 00003 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. 00004 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. 00005 You should have received a copy of the GNU General Public License along with Smoothie. If not, see <http://www.gnu.org/licenses/>. 00006 */ 00007 00008 #include "libs/Kernel.h" 00009 #include "Panel.h" 00010 #include "PanelScreen.h" 00011 #include "MainMenuScreen.h" 00012 #include "WatchScreen.h" 00013 #include "libs/nuts_bolts.h" 00014 #include "libs/utils.h" 00015 #include "modules/tools/temperaturecontrol/TemperatureControlPublicAccess.h" 00016 #include "modules/robot/RobotPublicAccess.h" 00017 #include "modules/robot/Conveyor.h" 00018 #include "modules/utils/player/PlayerPublicAccess.h" 00019 #include "NetworkPublicAccess.h" 00020 00021 #include <string> 00022 using namespace std; 00023 static const uint8_t icons[] = { // 115x19 - 3 bytes each: he1, he2, he3, bed, fan 00024 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xE0, 00025 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0xE0, 00026 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x0C, 0x60, 00027 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x0E, 0x20, 00028 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4F, 0x0F, 0x20, 00029 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5F, 0x0F, 0xA0, 00030 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5E, 0x07, 0xA0, 00031 0x7F, 0x80, 0x00, 0x3F, 0xC0, 0x00, 0x3F, 0xC0, 0x00, 0x41, 0x04, 0x00, 0x40, 0x60, 0x20, 00032 0xFB, 0xC0, 0x00, 0x79, 0xE0, 0x00, 0x79, 0xE0, 0x00, 0x20, 0x82, 0x00, 0x40, 0xF0, 0x20, 00033 0xF3, 0xC0, 0x00, 0x76, 0xE0, 0x00, 0x76, 0xE0, 0x00, 0x20, 0x82, 0x00, 0x40, 0xF0, 0x20, 00034 0xEB, 0xC0, 0x00, 0x7E, 0xE0, 0x00, 0x7E, 0xE0, 0x00, 0x41, 0x04, 0x00, 0x40, 0x60, 0x20, 00035 0x7B, 0x80, 0x00, 0x3D, 0xC0, 0x00, 0x39, 0xC0, 0x00, 0x82, 0x08, 0x00, 0x5E, 0x07, 0xA0, 00036 0x7B, 0x80, 0x00, 0x3B, 0xC0, 0x00, 0x3E, 0xC0, 0x01, 0x04, 0x10, 0x00, 0x5F, 0x0F, 0xA0, 00037 0xFB, 0xC0, 0x00, 0x77, 0xE0, 0x00, 0x76, 0xE0, 0x01, 0x04, 0x10, 0x00, 0x4F, 0x0F, 0x20, 00038 0xFB, 0xC0, 0x00, 0x70, 0xE0, 0x00, 0x79, 0xE0, 0x00, 0x82, 0x08, 0x00, 0x47, 0x0E, 0x20, 00039 0xFF, 0xC0, 0x00, 0x7F, 0xE0, 0x00, 0x7F, 0xE0, 0x00, 0x41, 0x04, 0x00, 0x63, 0x0C, 0x60, 00040 0x3F, 0x00, 0x00, 0x1F, 0x80, 0x00, 0x1F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0xE0, 00041 0x1E, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x0F, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x7F, 0xFF, 0xE0, 00042 0x0C, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x00 00043 }; 00044 00045 00046 00047 WatchScreen::WatchScreen() 00048 { 00049 speed_changed = false; 00050 issue_change_speed = false; 00051 ipstr = NULL; 00052 } 00053 00054 void WatchScreen::on_enter() 00055 { 00056 this->panel->lcd->clear(); 00057 this->panel->setup_menu(4); 00058 get_temp_data(); 00059 get_current_pos(this->pos); 00060 get_sd_play_info(); 00061 this->current_speed = lround(get_current_speed()); 00062 this->refresh_screen(false); 00063 this->panel->enter_control_mode(1, 0.5); 00064 this->panel->set_control_value(this->current_speed); 00065 } 00066 00067 void WatchScreen::on_refresh() 00068 { 00069 // Exit if the button is clicked 00070 if ( this->panel->click() ) { 00071 this->panel->enter_screen(this->parent); 00072 return; 00073 } 00074 00075 // see if speed is being changed 00076 if (this->panel->control_value_change()) { 00077 this->current_speed = this->panel->get_control_value(); 00078 if (this->current_speed < 10) { 00079 this->current_speed = 10; 00080 this->panel->set_control_value(this->current_speed); 00081 this->panel->reset_counter(); 00082 } else { 00083 // flag the update to change the speed, we don't want to issue hundreds of M220s 00084 // but we do want to display the change we are going to make 00085 this->speed_changed = true; // flag indicating speed changed 00086 this->refresh_screen(false); 00087 } 00088 } 00089 00090 // Update Only every 20 refreshes, 1 a second 00091 static int update_counts = 0; 00092 update_counts++; 00093 if ( update_counts % 20 == 0 ) { 00094 get_sd_play_info(); 00095 get_current_pos(this->pos); 00096 get_temp_data(); 00097 if (this->speed_changed) { 00098 this->issue_change_speed = true; // trigger actual command to change speed 00099 this->speed_changed = false; 00100 } else if (!this->issue_change_speed) { // change still queued 00101 // read it in case it was changed via M220 00102 this->current_speed = lround(get_current_speed()); 00103 this->panel->set_control_value(this->current_speed); 00104 this->panel->reset_counter(); 00105 } 00106 00107 this->refresh_screen(this->panel->lcd->hasGraphics() ? true : false); // graphics screens should be cleared 00108 00109 // for LCDs with leds set them according to heater status 00110 // TODO should be enabled and disabled and settable from config 00111 this->panel->lcd->setLed(LED_BED_ON, this->bedtarget > 0); 00112 this->panel->lcd->setLed(LED_HOTEND_ON, this->hotendtarget > 0); 00113 //this->panel->lcd->setLed(LED_FAN_ON, this->fanon); 00114 00115 if (this->panel->lcd->hasGraphics()) { 00116 // display the graphical icons below the status are 00117 //this->panel->lcd->bltGlyph(0, 34, 115, 19, icons); 00118 // for (int i = 0; i < 5; ++i) { 00119 // this->panel->lcd->bltGlyph(i*24, 38, 23, 19, icons, 15, i*24, 0); 00120 // } 00121 if (this->hotendtarget > 0) 00122 this->panel->lcd->bltGlyph(8, 38, 20, 19, icons, 15, 0, 0); 00123 00124 if (this->bedtarget > 0) 00125 this->panel->lcd->bltGlyph(32, 38, 23, 19, icons, 15, 64, 0); 00126 00127 // fan appears always on for now 00128 this->panel->lcd->bltGlyph(96, 38, 23, 19, icons, 15, 96, 0); 00129 } 00130 } 00131 } 00132 00133 // queuing gcodes needs to be done from main loop 00134 void WatchScreen::on_main_loop() 00135 { 00136 if (this->issue_change_speed) { 00137 this->issue_change_speed = false; 00138 set_speed(); 00139 } 00140 } 00141 00142 // fetch the data we are displaying 00143 void WatchScreen::get_temp_data() 00144 { 00145 void *returned_data; 00146 bool ok; 00147 00148 ok = THEKERNEL->public_data->get_value( temperature_control_checksum, bed_checksum, current_temperature_checksum, &returned_data ); 00149 if (ok) { 00150 struct pad_temperature temp = *static_cast<struct pad_temperature *>(returned_data); 00151 this->bedtemp = round(temp.current_temperature); 00152 if (this->bedtemp > 100000) this->bedtemp = -2; 00153 this->bedtarget = round(temp.target_temperature); 00154 //this->bedpwm= temp.pwm; 00155 } else { 00156 // temp probably disabled 00157 this->bedtemp = -1; 00158 this->bedtarget = -1; 00159 } 00160 00161 00162 ok = THEKERNEL->public_data->get_value( temperature_control_checksum, hotend_checksum, current_temperature_checksum, &returned_data ); 00163 if (ok) { 00164 struct pad_temperature temp = *static_cast<struct pad_temperature *>(returned_data); 00165 this->hotendtemp = round(temp.current_temperature); 00166 if (this->hotendtemp > 100000) this->hotendtemp = -2; 00167 this->hotendtarget = round(temp.target_temperature); 00168 //this->hotendpwm= temp.pwm; 00169 } else { 00170 // temp probably disabled 00171 this->hotendtemp = -1; 00172 this->hotendtarget = -1; 00173 } 00174 } 00175 00176 // fetch the data we are displaying 00177 float WatchScreen::get_current_speed() 00178 { 00179 void *returned_data; 00180 00181 bool ok = THEKERNEL->public_data->get_value( robot_checksum, speed_override_percent_checksum, &returned_data ); 00182 if (ok) { 00183 float cs = *static_cast<float *>(returned_data); 00184 return cs; 00185 } 00186 return 0.0; 00187 } 00188 00189 void WatchScreen::get_current_pos(float *cp) 00190 { 00191 void *returned_data; 00192 00193 bool ok = THEKERNEL->public_data->get_value( robot_checksum, current_position_checksum, &returned_data ); 00194 if (ok) { 00195 float *p = static_cast<float *>(returned_data); 00196 cp[0] = p[0]; 00197 cp[1] = p[1]; 00198 cp[2] = p[2]; 00199 } 00200 } 00201 00202 void WatchScreen::get_sd_play_info() 00203 { 00204 void *returned_data; 00205 bool ok = THEKERNEL->public_data->get_value( player_checksum, get_progress_checksum, &returned_data ); 00206 if (ok) { 00207 struct pad_progress p = *static_cast<struct pad_progress *>(returned_data); 00208 this->elapsed_time = p.elapsed_secs; 00209 this->sd_pcnt_played = p.percent_complete; 00210 this->panel->set_playing_file(p.filename); 00211 00212 } else { 00213 this->elapsed_time = 0; 00214 this->sd_pcnt_played = 0; 00215 } 00216 } 00217 00218 void WatchScreen::display_menu_line(uint16_t line) 00219 { 00220 // in menu mode 00221 switch ( line ) { 00222 case 0: this->panel->lcd->printf("H%03d/%03dc B%03d/%03dc", this->hotendtemp, this->hotendtarget, this->bedtemp, this->bedtarget); break; 00223 case 1: this->panel->lcd->printf("X%4d Y%4d Z%7.2f", (int)round(this->pos[0]), (int)round(this->pos[1]), this->pos[2]); break; 00224 case 2: this->panel->lcd->printf("%3d%% %2lu:%02lu %3u%% sd", this->current_speed, this->elapsed_time / 60, this->elapsed_time % 60, this->sd_pcnt_played); break; 00225 case 3: this->panel->lcd->printf("%19s", this->get_status()); break; 00226 } 00227 } 00228 00229 const char *WatchScreen::get_status() 00230 { 00231 if (panel->hasMessage()) { 00232 return panel->getMessage().c_str(); 00233 } 00234 00235 if (THEKERNEL->pauser->paused()) 00236 return "Paused"; 00237 00238 if (panel->is_playing()) 00239 return panel->get_playing_file(); 00240 00241 if (!THEKERNEL->conveyor->queue.is_empty()) { 00242 return "Printing"; 00243 } 00244 00245 const char *ip = get_network(); 00246 if (ip == NULL) { 00247 return "Smoothie ready"; 00248 } else { 00249 return ip; 00250 } 00251 } 00252 00253 void WatchScreen::set_speed() 00254 { 00255 // change pos by issuing a M220 Snnn 00256 char buf[32]; 00257 int n = snprintf(buf, sizeof(buf), "M220 S%d", this->current_speed); 00258 string g(buf, n); 00259 send_gcode(g); 00260 } 00261 00262 const char *WatchScreen::get_network() 00263 { 00264 void *returned_data; 00265 00266 bool ok = THEKERNEL->public_data->get_value( network_checksum, get_ip_checksum, &returned_data ); 00267 if (ok) { 00268 uint8_t *ipaddr = (uint8_t *)returned_data; 00269 char buf[20]; 00270 int n = snprintf(buf, sizeof(buf), "IP %d.%d.%d.%d", ipaddr[0], ipaddr[1], ipaddr[2], ipaddr[3]); 00271 buf[n] = 0; 00272 if (this->ipstr == NULL) { 00273 this->ipstr = (char *)malloc(n + 1); 00274 } 00275 strcpy(this->ipstr, buf); 00276 00277 return this->ipstr; 00278 } 00279 00280 return NULL; 00281 }
Generated on Tue Jul 12 2022 20:09:03 by 1.7.2