update firmware.bin
[clinton/Smoothieware.git] / src / modules / utils / pausebutton / PauseButton.cpp
CommitLineData
81b547a1
AW
1#include "libs/Kernel.h"
2#include "PauseButton.h"
3#include "libs/nuts_bolts.h"
4#include "libs/utils.h"
61134a65
JM
5#include "Config.h"
6#include "SlowTicker.h"
9bce85f9
L
7#include "libs/SerialMessage.h"
8#include "libs/StreamOutput.h"
61134a65 9#include "Pauser.h"
7af0714f 10#include "checksumm.h"
8d54c34c 11#include "ConfigValue.h"
e558f082 12#include "StreamOutputPool.h"
61134a65 13
81b547a1
AW
14using namespace std;
15
4e722c00 16#define pause_button_enable_checksum CHECKSUM("pause_button_enable")
e558f082 17#define kill_button_enable_checksum CHECKSUM("kill_button_enable")
4e722c00 18#define pause_button_pin_checksum CHECKSUM("pause_button_pin")
e558f082 19#define kill_button_pin_checksum CHECKSUM("kill_button_pin")
4e722c00 20
76217df5
JM
21PauseButton::PauseButton()
22{
e558f082 23 this->button_state = true;
76217df5 24 this->killed = false;
85bb9a93 25 this->do_kill= false;
e558f082 26}
81b547a1 27
76217df5
JM
28void PauseButton::on_module_loaded()
29{
e558f082 30 this->pause_enable = THEKERNEL->config->value( pause_button_enable_checksum )->by_default(false)->as_bool();
5dfe966f 31 this->kill_enable = THEKERNEL->config->value( kill_button_enable_checksum )->by_default(false)->as_bool();
e558f082 32 this->pause_button.from_string( THEKERNEL->config->value( pause_button_pin_checksum )->by_default("2.12")->as_string())->as_input();
5dfe966f 33 this->kill_button.from_string( THEKERNEL->config->value( kill_button_pin_checksum )->by_default("nc")->as_string())->as_input();
81b547a1 34
5dfe966f 35 if(this->kill_enable && this->kill_button.connected() && pause_button.equals(kill_button)) {
e558f082 36 // kill button takes priority
76217df5
JM
37 this->pause_enable = false;
38
39 } else if(this->kill_enable && !this->kill_button.connected() && !this->pause_enable && pause_button.connected()) {
85bb9a93 40 // use pause button for kill button if kill buttin not specifically defined
76217df5 41 this->kill_button = this->pause_button;
e558f082 42 }
81b547a1 43
9bce85f9 44 this->register_for_event(ON_CONSOLE_LINE_RECEIVED);
4e722c00 45
e558f082 46 if( (this->pause_enable && this->pause_button.connected()) || (this->kill_enable && this->kill_button.connected()) ) {
373d0bf1 47 THEKERNEL->slow_ticker->attach( 10, this, &PauseButton::button_tick );
85bb9a93
JM
48 this->register_for_event(ON_IDLE);
49 }
50}
51
52void PauseButton::on_idle(void *argument)
53{
54 if(do_kill) {
55 do_kill= false;
728477c4 56 THEKERNEL->call_event(ON_HALT, nullptr);
85bb9a93 57 THEKERNEL->streams->printf("Kill button pressed - reset or M999 to continue\r\n");
e558f082 58 }
81b547a1
AW
59}
60
7b49793d 61//TODO: Make this use InterruptIn
7dc903db 62//Check the state of the button and act accordingly based on current pause state
728477c4 63// Note this is ISR so don't do anything nasty in here
76217df5
JM
64uint32_t PauseButton::button_tick(uint32_t dummy)
65{
e558f082
JM
66 // If pause button changed
67 if(this->pause_enable && this->pause_button.connected()) {
68 bool newstate = this->pause_button.get();
76217df5 69 if(this->button_state != newstate) {
e558f082
JM
70 this->button_state = newstate;
71 // If button pressed
76217df5
JM
72 if( this->button_state ) {
73 if( THEKERNEL->pauser->paused() ) {
e558f082 74 THEKERNEL->pauser->release();
76217df5 75 } else {
e558f082
JM
76 THEKERNEL->pauser->take();
77 }
df27a6a3
MM
78 }
79 }
81b547a1 80 }
e558f082 81
76217df5
JM
82 if(!this->killed && this->kill_enable && this->kill_button.connected() && !this->kill_button.get()) {
83 this->killed = true;
85bb9a93
JM
84 // we can't call this in ISR, and we need to block on_main_loop so do it in on_idle
85 // THEKERNEL->call_event(ON_HALT);
86 this->do_kill= true;
e558f082
JM
87 }
88
f03d3c1c 89 return 0;
81b547a1 90}
9bce85f9
L
91
92// When a new line is received, check if it is a command, and if it is, act upon it
93void PauseButton::on_console_line_received( void *argument )
94{
95 SerialMessage new_message = *static_cast<SerialMessage *>(argument);
96
891910b6
JM
97 if(this->killed && new_message.message == "M999") {
98 this->killed= false;
99 return;
100 }
101
9bce85f9
L
102 // ignore comments and blank lines and if this is a G code then also ignore it
103 char first_char = new_message.message[0];
104 if(strchr(";( \n\rGMTN", first_char) != NULL) return;
105
76217df5 106 string cmd = shift_parameter(new_message.message);
9bce85f9 107
e558f082 108 if (cmd == "freeze") {
76217df5 109 if( !THEKERNEL->pauser->paused() ) {
9bce85f9
L
110 THEKERNEL->pauser->take();
111 }
7dc903db 112
76217df5
JM
113 } else if (cmd == "unfreeze") {
114 if( THEKERNEL->pauser->paused() ) {
9bce85f9
L
115 THEKERNEL->pauser->release();
116 }
117 }
118}
119