allow for a default_excludes.mk file in src that will be used for the excluded midule...
[clinton/Smoothieware.git] / src / modules / robot / Stepper.cpp
1 /*
2 This file is part of Smoothie (http://smoothieware.org/). The motion control part is heavily based on Grbl (https://github.com/simen/grbl) with additions from Sungeun K. Jeon (https://github.com/chamnit/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.
5 You should have received a copy of the GNU General Public License along with Smoothie. If not, see <http://www.gnu.org/licenses/>.
6 */
7
8 #include "Stepper.h"
9
10 #include "libs/Module.h"
11 #include "libs/Kernel.h"
12 #include "Planner.h"
13 #include "Conveyor.h"
14 #include "StepperMotor.h"
15 #include "Robot.h"
16 #include "checksumm.h"
17 #include "SlowTicker.h"
18 #include "Config.h"
19 #include "ConfigValue.h"
20 #include "Gcode.h"
21 #include "Block.h"
22 #include "StepTicker.h"
23
24 #include <functional>
25
26 #include "libs/nuts_bolts.h"
27 #include "libs/Hook.h"
28
29 #include <mri.h>
30
31 // The stepper reacts to blocks that have XYZ movement to transform them into actual stepper motor moves
32 Stepper::Stepper()
33 {
34 this->current_block = NULL;
35 }
36
37 //Called when the module has just been loaded
38 void Stepper::on_module_loaded()
39 {
40 this->register_for_event(ON_BLOCK_BEGIN);
41 this->register_for_event(ON_BLOCK_END);
42 this->register_for_event(ON_GCODE_RECEIVED);
43 this->register_for_event(ON_HALT);
44
45 // Get onfiguration
46 this->on_config_reload(this);
47
48 // Attach to the end_of_move stepper event
49 THEKERNEL->step_ticker->finished_fnc= std::bind( &Stepper::stepper_motor_finished_move, this);
50 }
51
52 // Get configuration from the config file
53 void Stepper::on_config_reload(void *argument)
54 {
55 // Steppers start off by default
56 this->turn_enable_pins_off();
57 }
58
59 void Stepper::on_halt(void *argument)
60 {
61 if(argument == nullptr) {
62 this->turn_enable_pins_off();
63 }
64 }
65
66 void Stepper::on_gcode_received(void *argument)
67 {
68 Gcode *gcode = static_cast<Gcode *>(argument);
69
70 if( gcode->has_m) {
71 if( gcode->m == 17 ) {
72 this->turn_enable_pins_on();
73
74 }else if( (gcode->m == 84 || gcode->m == 18) && !gcode->has_letter('E') ) {
75 THEKERNEL->conveyor->wait_for_empty_queue();
76 this->turn_enable_pins_off();
77 }
78 }
79 }
80
81 // Enable steppers
82 void Stepper::turn_enable_pins_on()
83 {
84 for (auto a : THEKERNEL->robot->actuators)
85 a->enable(true);
86 this->enable_pins_status = true;
87 THEKERNEL->call_event(ON_ENABLE, (void*)1);
88 }
89
90 // Disable steppers
91 void Stepper::turn_enable_pins_off()
92 {
93 for (auto a : THEKERNEL->robot->actuators)
94 a->enable(false);
95 this->enable_pins_status = false;
96 THEKERNEL->call_event(ON_ENABLE, nullptr);
97 }
98
99 // A new block is popped from the queue
100 void Stepper::on_block_begin(void *argument)
101 {
102 Block *block = static_cast<Block *>(argument);
103
104 // Mark the new block as of interrest to us, handle blocks that have no axis moves properly (like Extrude blocks etc)
105 bool take = false;
106 if (block->millimeters > 0.0F) {
107 for (size_t s = 0; !take && s < THEKERNEL->robot->actuators.size(); s++) {
108 take = block->steps[s] > 0;
109 }
110 }
111 if(!take) return;
112
113 block->take();
114
115 // We can't move with the enable pins off
116 if( this->enable_pins_status == false ) {
117 this->turn_enable_pins_on();
118 }
119
120 this->current_block = block;
121
122 // setup stepticker to execute this block
123 THEKERNEL->step_ticker->add_job(block);
124 }
125
126 // Current block is discarded
127 void Stepper::on_block_end(void *argument)
128 {
129 this->current_block = NULL; //stfu !
130 }
131
132 // When all moves in a block have finished this is called by step ticker (in the pendsv ISR)
133 void Stepper::stepper_motor_finished_move()
134 {
135 // This block is finished, release it
136 if( this->current_block != NULL ) {
137 this->current_block->release();
138 }
139 }