#include "libs/StreamOutput.h"
#include "Gcode.h"
#include "checksumm.h"
-#include "Pauser.h"
#include "Config.h"
#include "ConfigValue.h"
#include "SDFAT.h"
this->booted = false;
this->elapsed_secs = 0;
this->reply_stream = nullptr;
- this->halted= false;
this->suspended= false;
this->suspend_loops= 0;
}
this->register_for_event(ON_GET_PUBLIC_DATA);
this->register_for_event(ON_SET_PUBLIC_DATA);
this->register_for_event(ON_GCODE_RECEIVED);
- this->register_for_event(ON_HALT);
this->on_boot_gcode = THEKERNEL->config->value(on_boot_gcode_checksum)->by_default("/sd/on_boot.gcode")->as_string();
this->on_boot_gcode_enable = THEKERNEL->config->value(on_boot_gcode_enable_checksum)->by_default(true)->as_bool();
this->leave_heaters_on = THEKERNEL->config->value(leave_heaters_on_suspend_checksum)->by_default(false)->as_bool();
}
-void Player::on_halt(void *arg)
-{
- halted= (arg == nullptr);
-}
-
void Player::on_second_tick(void *)
{
if(this->playing_file) this->elapsed_secs++;
this->played_cnt = 0;
this->elapsed_secs = 0;
- } else if (gcode->m == 600) { // suspend print, Not entirely Marlin compliant
- this->suspend_command("", &(StreamOutput::NullStream));
+ } else if (gcode->m == 600) { // suspend print, Not entirely Marlin compliant, M600.1 will leave the heaters on
+ this->suspend_command((gcode->subcode == 1)?"h":"", gcode->stream);
} else if (gcode->m == 601) { // resume print
- this->resume_command("", &(StreamOutput::NullStream));
+ this->resume_command("", gcode->stream);
}
}
}
// When a new line is received, check if it is a command, and if it is, act upon it
void Player::on_console_line_received( void *argument )
{
- if(halted) return; // if in halted state ignore any commands
+ if(THEKERNEL->is_halted()) return; // if in halted state ignore any commands
SerialMessage new_message = *static_cast<SerialMessage *>(argument);
// now the position will think it is at the last received pos, so we need to do FK to get the actuator position and reset the current position
THEKERNEL->robot->reset_position_from_current_actuator_position();
}
- stream->printf("Aborted playing or paused file\r\n");
+ stream->printf("Aborted playing or paused file. Please turn any heaters off manually\r\n");
}
void Player::on_main_loop(void *argument)
}
if( this->playing_file ) {
- if(halted) {
+ if(THEKERNEL->is_halted()) {
abort_command("1", &(StreamOutput::NullStream));
return;
}
return;
}
- stream->printf("ok Suspending print, waiting for queue to empty...\n");
+ stream->printf("Suspending print, waiting for queue to empty...\n");
+
+ // override the leave_heaters_on setting
+ this->override_leave_heaters_on= (parameters == "h");
suspended= true;
if( this->playing_file ) {
// we need to allow main loop to cycle a few times to clear any buffered commands in the serial streams etc
suspend_loops= 10;
- suspend_stream= stream;
}
// this completes the suspend
void Player::suspend_part2()
{
+ // need to use streams here as the original stream may have changed
+ THEKERNEL->streams->printf("// Waiting for queue to empty (Host must stop sending)...\n");
// wait for queue to empty
THEKERNEL->conveyor->wait_for_empty_queue();
- suspend_stream->printf("Saving current state...\n");
+ THEKERNEL->streams->printf("// Saving current state...\n");
// save current XYZ position
THEKERNEL->robot->get_axis_position(this->saved_position);
// save current extruder state
PublicData::set_value( extruder_checksum, save_state_checksum, nullptr );
- // save state
- this->saved_inch_mode= THEKERNEL->robot->inch_mode;
- this->saved_absolute_mode= THEKERNEL->robot->absolute_mode;
- this->saved_feed_rate= THEKERNEL->robot->get_feed_rate() * 60; // save in mm/min
+ // save state use M120
+ THEKERNEL->robot->push_state();
// TODO retract by optional amount...
this->saved_temperatures.clear();
- if(!this->leave_heaters_on) {
+ if(!this->leave_heaters_on && !this->override_leave_heaters_on) {
// save current temperatures, get a vector of all the controllers data
- std::vector<struct pad_temperature*> *controllers;
- bool ok = PublicData::get_value(temperature_control_checksum, poll_controls_checksum, (void**)&controllers);
+ std::vector<struct pad_temperature> controllers;
+ bool ok = PublicData::get_value(temperature_control_checksum, poll_controls_checksum, &controllers);
if (ok) {
// query each heater and save the target temperature if on
- for (auto &c : *controllers) {
+ for (auto &c : controllers) {
// TODO see if in exclude list
- if(c->target_temperature > 0) {
- this->saved_temperatures[c->id]= c->target_temperature;
+ if(c.target_temperature > 0) {
+ this->saved_temperatures[c.id]= c.target_temperature;
}
}
}
THEKERNEL->call_event(ON_CONSOLE_LINE_RECEIVED, &message );
}
- suspend_stream->printf("Print Suspended, enter resume to continue printing\n");
+ THEKERNEL->streams->printf("// Print Suspended, enter resume to continue printing\n");
}
/**
return;
}
- stream->printf("ok resuming print...\n");
-
- // set heaters to saved temps
- for(auto& h : this->saved_temperatures) {
- float t= h.second;
- PublicData::set_value( temperature_control_checksum, h.first, &t );
- }
+ stream->printf("resuming print...\n");
// wait for them to reach temp
if(!this->saved_temperatures.empty()) {
+ // set heaters to saved temps
+ for(auto& h : this->saved_temperatures) {
+ float t= h.second;
+ PublicData::set_value( temperature_control_checksum, h.first, &t );
+ }
stream->printf("Waiting for heaters...\n");
bool wait= true;
uint32_t tus= us_ticker_read(); // mbed call
}
for(auto& h : this->saved_temperatures) {
- void *p;
- if(PublicData::get_value( temperature_control_checksum, h.first, current_temperature_checksum, &p )) {
- struct pad_temperature *temp= static_cast<struct pad_temperature *>(p);
- if(timeup) stream->printf("%s:%3.1f /%3.1f @%d ", temp->designator.c_str(), temp->current_temperature, ((temp->target_temperature == -1) ? 0.0 : temp->target_temperature), temp->pwm);
- wait= wait || (temp->current_temperature < h.second);
+ struct pad_temperature temp;
+ if(PublicData::get_value( temperature_control_checksum, current_temperature_checksum, h.first, &temp )) {
+ if(timeup)
+ stream->printf("%s:%3.1f /%3.1f @%d ", temp.designator.c_str(), temp.current_temperature, ((temp.target_temperature == -1) ? 0.0 : temp.target_temperature), temp.pwm);
+ wait= wait || (temp.current_temperature < h.second);
}
}
if(timeup) stream->printf("\n");
if(wait)
THEKERNEL->call_event(ON_IDLE, this);
+
+ if(THEKERNEL->is_halted()) {
+ // abort temp wait and rest of resume
+ THEKERNEL->streams->printf("Resume aborted by kill\n");
+ THEKERNEL->robot->pop_state();
+ this->saved_temperatures.clear();
+ suspended= false;
+ return;
+ }
}
}
// Restore position
stream->printf("Restoring saved XYZ positions and state...\n");
- THEKERNEL->robot->inch_mode= saved_inch_mode;
- THEKERNEL->robot->absolute_mode= saved_absolute_mode;
- char buf[128];
+ THEKERNEL->robot->pop_state();
+ bool abs_mode= THEKERNEL->robot->absolute_mode; // what mode we were in
+ // force absolute mode for restoring position, then set to the saved relative/absolute mode
+ THEKERNEL->robot->absolute_mode= true;
{
- int n = snprintf(buf, sizeof(buf), "G1 X%f Y%f Z%f F%f", saved_position[0], saved_position[1], saved_position[2], saved_feed_rate);
+ char buf[128];
+ int n = snprintf(buf, sizeof(buf), "G1 X%f Y%f Z%f", saved_position[0], saved_position[1], saved_position[2]);
string g(buf, n);
Gcode gcode(g, &(StreamOutput::NullStream));
THEKERNEL->call_event(ON_GCODE_RECEIVED, &gcode );
}
+ THEKERNEL->robot->absolute_mode= abs_mode;
// restore extruder state
PublicData::set_value( extruder_checksum, restore_state_checksum, nullptr );
if(this->was_playing_file) {
this->playing_file = true;
+ this->was_playing_file= false;
}else{
// Send resume to host
THEKERNEL->streams->printf("// action:resume\r\n");