switch_set_callback(SW_ESTOP, _switch_callback);
- if (estop.triggered) mach_set_state(STATE_ESTOP);
+ if (estop.triggered) mach_set_state(STATE_ESTOPPED);
// Fault signal
if (estop.triggered) OUTSET_PIN(FAULT_PIN); // High
mach_spindle_estop();
// Set machine state
- mach_set_state(STATE_ESTOP);
+ mach_set_state(STATE_ESTOPPED);
// Set axes not homed
mach_set_not_homed();
mach.gm.feed_rate = hm.saved_feed_rate;
mach_set_motion_mode(MOTION_MODE_CANCEL_MOTION_MODE);
mach_cycle_end();
+ mach_set_cycle(CYCLE_MACHINING);
}
bool mach_is_homing() {
- return mach_get_state() == STATE_HOMING;
+ return mach_get_cycle() == CYCLE_HOMING;
}
hm.axis = -1; // set to retrieve initial axis
hm.func = _homing_axis_start; // bind initial processing function
- mach_set_state(STATE_HOMING);
+ mach_set_cycle(CYCLE_HOMING);
mach.homing_state = HOMING_NOT_HOMED;
}
/// Main loop callback for running the homing cycle
void mach_homing_callback() {
- if (mach_get_state() != STATE_HOMING || mach_get_runtime_busy()) return;
+ if (mach_get_cycle() != CYCLE_HOMING || mach_get_runtime_busy()) return;
hm.func(hm.axis); // execute the current homing move
}
},
._state = STATE_IDLE,
+ ._cycle = CYCLE_MACHINING,
// State
.gm = {.motion_mode = MOTION_MODE_CANCEL_MOTION_MODE},
uint32_t mach_get_line() {return mach.gm.line;}
-bool mach_is_running() {
- switch (mach_get_state()) {
- case STATE_RUNNING:
- case STATE_HOMING:
- case STATE_PROBING:
- return true;
- default: return false;
+PGM_P mach_get_state_pgmstr(machState_t state) {
+ switch (state) {
+ case STATE_IDLE: return PSTR("idle");
+ case STATE_ESTOPPED: return PSTR("estopped");
+ case STATE_RUNNING: return PSTR("running");
+ case STATE_STOPPING: return PSTR("stopping");
+ case STATE_HOLDING: return PSTR("holding");
}
+
+ return PSTR("invalid");
+}
+
+
+PGM_P mach_get_cycle_pgmstr(machCycle_t cycle) {
+ switch (cycle) {
+ case CYCLE_MACHINING: return PSTR("machining");
+ case CYCLE_HOMING: return PSTR("homing");
+ case CYCLE_PROBING: return PSTR("probing");
+ case CYCLE_CALIBRATING: return PSTR("calibrating");
+ case CYCLE_JOGGING: return PSTR("jogging");
+ }
+
+ return PSTR("invalid");
}
void mach_set_state(machState_t state) {
if (mach._state == state) return; // No change
- if (mach._state == STATE_ESTOP) return; // Can't leave EStop state
+ if (mach._state == STATE_ESTOPPED) return; // Can't leave EStop state
mach._state = state;
report_request();
}
+void mach_set_cycle(machCycle_t cycle) {
+ if (mach._cycle == cycle) return; // No change
+
+ if (mach._state != STATE_IDLE) {
+ STATUS_ERROR(STAT_INTERNAL_ERROR, "Cannot transition to %S while %S",
+ mach_get_cycle_pgmstr(cycle),
+ mach_get_state_pgmstr(mach._state));
+ return;
+ }
+
+ if (mach._cycle != CYCLE_MACHINING && cycle != CYCLE_MACHINING) {
+ STATUS_ERROR(STAT_INTERNAL_ERROR,
+ "Cannot transition to cycle %S while in %S",
+ mach_get_cycle_pgmstr(cycle),
+ mach_get_cycle_pgmstr(mach._cycle));
+ return;
+ }
+
+ mach._cycle = cycle;
+ report_request();
+}
+
+
void mach_set_motion_mode(machMotionMode_t motion_mode) {
mach.gm.motion_mode = motion_mode;
}
if (mach.feedhold_requested) {
mach.feedhold_requested = false;
- if (mach_is_running()) {
+ if (mach_get_state() == STATE_RUNNING) {
mach_set_state(STATE_STOPPING);
mach.hold_state = FEEDHOLD_SYNC; // invokes hold from aline execution
}
/// Do a cycle start right now
void mach_cycle_start() {
- // don't (re)start homing, probe or other canned cycles
if (mach_get_state() == STATE_IDLE) mach_set_state(STATE_RUNNING);
}
#include "config.h"
#include "status.h"
+#include <avr/pgmspace.h>
+
#include <stdint.h>
#include <stdbool.h>
typedef enum {
STATE_IDLE,
- STATE_ESTOP,
+ STATE_ESTOPPED,
STATE_RUNNING,
- STATE_HOMING,
- STATE_PROBING,
STATE_STOPPING,
STATE_HOLDING,
} machState_t;
+typedef enum {
+ CYCLE_MACHINING,
+ CYCLE_HOMING,
+ CYCLE_PROBING,
+ CYCLE_CALIBRATING,
+ CYCLE_JOGGING,
+} machCycle_t;
+
+
typedef enum { // feedhold_state machine
FEEDHOLD_OFF, // no feedhold in effect
FEEDHOLD_SYNC, // start hold - sync to latest aline segment
AxisConfig_t a[AXES];
machState_t _state;
+ machCycle_t _cycle;
machFeedholdState_t hold_state; // hold: feedhold sub-state machine
machHomingState_t homing_state; // home: homing cycle sub-state machine
bool homed[AXES]; // individual axis homing flags
// Model state getters and setters
uint32_t mach_get_line();
inline machState_t mach_get_state() {return mach._state;}
-bool mach_is_running();
+inline machCycle_t mach_get_cycle() {return mach._cycle;}
machFeedholdState_t mach_get_hold_state();
machHomingState_t mach_get_homing_state();
machMotionMode_t mach_get_motion_mode();
float mach_get_feed_rate();
void mach_set_state(machState_t state);
+void mach_set_cycle(machCycle_t cycle);
+PGM_P mach_get_state_pgmstr(machState_t state);
+PGM_P mach_get_cycle_pgmstr(machCycle_t cycle);
void mach_set_motion_mode(machMotionMode_t motion_mode);
void mach_set_spindle_mode(machSpindleMode_t spindle_mode);
void mach_set_spindle_speed_parameter(float speed);
typedef struct {
- bool busy;
bool stall_valid;
bool stalled;
bool reverse;
tmc2660_set_stallguard_threshold(cal.motor, 63);
mp_free_run_buffer(); // Release buffer
- cal.busy = false;
+ mach_set_cycle(CYCLE_MACHINING);
return STAT_OK;
} else {
}
-bool calibrate_busy() {return cal.busy;}
+bool calibrate_busy() {return mach_get_cycle() == CYCLE_CALIBRATING;}
void calibrate_set_stallguard(int motor, uint16_t sg) {
uint8_t command_calibrate(int argc, char *argv[]) {
- if (cal.busy) return 0;
+ if (mach_get_cycle() != CYCLE_MACHINING || mach_get_state() != STATE_IDLE)
+ return 0;
mpBuf_t *bf = mp_get_write_buffer();
if (!bf) {
// Start
memset(&cal, 0, sizeof(cal));
- cal.busy = true;
+ mach_set_cycle(CYCLE_CALIBRATING);
cal.motor = 1;
bf->bf_func = _exec_calibrate; // register callback
}
-/// Dequeues buffer, executes move continuations and manages run buffers.
+/// Dequeues buffer, executes move callback and enters RUNNING state
stat_t mp_exec_move() {
- mpBuf_t *bf = mp_get_run_buffer();
-
- if (!bf) return STAT_NOOP; // nothing's running
if (estop_triggered()) return STAT_MACHINE_ALARMED;
- // Manage state transitions
- // Cycle auto-start for lines only
- if (bf->move_type == MOVE_TYPE_ALINE && mach_get_state() == STATE_IDLE)
- mach_set_state(STATE_RUNNING);
+ mpBuf_t *bf = mp_get_run_buffer();
+ if (!bf) return STAT_NOOP; // nothing running
+ if (!bf->bf_func) return CM_ALARM(STAT_INTERNAL_ERROR);
- if (!bf->bf_func)
- return CM_ALARM(STAT_INTERNAL_ERROR); // never supposed to get here
+ if (mach_get_state() == STATE_IDLE) mach_set_state(STATE_RUNNING);
- return bf->bf_func(bf); // run the move callback on the planner buffer
+ return bf->bf_func(bf); // move callback
}
typedef struct {
- bool running;
bool writing;
float next_velocity[AXES];
float target_velocity[AXES];
// Release buffer
mp_free_run_buffer();
- jr.running = false;
+ mach_set_cycle(CYCLE_MACHINING);
return STAT_NOOP;
}
}
-bool mp_jog_busy() {return jr.running;}
+bool mp_jog_busy() {return mach_get_cycle() == CYCLE_JOGGING;}
uint8_t command_jog(int argc, char *argv[]) {
+ if (!mp_jog_busy() &&
+ (mach_get_state() != STATE_IDLE || mach_get_cycle() != CYCLE_MACHINING))
+ return STAT_NOOP;
+
float velocity[AXES];
for (int axis = 0; axis < AXES; axis++)
else velocity[axis] = 0;
// Reset
- if (!jr.running) memset(&jr, 0, sizeof(jr));
+ if (mp_jog_busy()) memset(&jr, 0, sizeof(jr));
jr.writing = true;
for (int axis = 0; axis < AXES; axis++)
jr.next_velocity[axis] = velocity[axis];
jr.writing = false;
- if (!jr.running) {
+ if (!mp_jog_busy()) {
// Should always be at least one free buffer
mpBuf_t *bf = mp_get_write_buffer();
if (!bf) {
}
// Start
- jr.running = true;
+ mach_set_cycle(CYCLE_JOGGING);
bf->bf_func = _exec_jog; // register callback
mp_commit_write_buffer(-1, MOVE_TYPE_COMMAND);
}
// update the model with actual position
mach_set_motion_mode(MOTION_MODE_CANCEL_MOTION_MODE);
mach_cycle_end();
+ mach_set_cycle(CYCLE_MACHINING);
}
// it is an error for the limit or homing switches to fire, or for some other
// configuration error.
mach.probe_state = PROBE_FAILED;
- mach_set_state(STATE_PROBING);
+ mach_set_cycle(CYCLE_PROBING);
// initialize the axes - save the jerk settings & switch to the jerk_homing
// settings
bool mach_is_probing() {
- return mach_get_state() == STATE_PROBING || mach.probe_state == PROBE_WAITING;
+ return mach_get_cycle() == CYCLE_PROBING || mach.probe_state == PROBE_WAITING;
}
#define STATUS_WARNING(MSG, ...) \
STATUS_MESSAGE(STAT_LEVEL_WARNING, STAT_OK, MSG, ##__VA_ARGS__)
-#define STATUS_ERROR(MSG, CODE, ...) \
+#define STATUS_ERROR(CODE, MSG, ...) \
STATUS_MESSAGE(STAT_LEVEL_ERROR, CODE, MSG, ##__VA_ARGS__)
\******************************************************************************/
#include "usart.h"
+#include "machine.h"
#include "plan/planner.h"
#include "plan/buffer.h"
-#include <avr/pgmspace.h>
-
float get_position(int index) {return mp_get_runtime_absolute_position(index);}
float get_velocity() {return mp_get_runtime_velocity();}
void set_echo(bool value) {return usart_set(USART_ECHO, value);}
uint16_t get_queue() {return mp_get_planner_buffer_room();}
int32_t get_line() {return mr.ms.line;}
-
-
-PGM_P get_state() {
- switch (mach_get_state()) {
- case STATE_IDLE: return PSTR("idle");
- case STATE_ESTOP: return PSTR("estop");
- case STATE_RUNNING: return PSTR("running");
- case STATE_HOMING: return PSTR("homing");
- case STATE_PROBING: return PSTR("probing");
- case STATE_STOPPING: return PSTR("stopping");
- case STATE_HOLDING: return PSTR("holding");
- }
-
- return PSTR("invalid");
-}
+PGM_P get_state() {return mach_get_state_pgmstr(mach_get_state());}
+PGM_P get_cycle() {return mach_get_cycle_pgmstr(mach_get_cycle());}
VAR(line, "ln", int32_t, 0, 0, 0, "Last GCode line executed")
VAR(queue, "q", uint16_t, 0, 0, 0, "Space in planner queue")
VAR(state, "s", pstring, 0, 0, 0, "Machine state")
+VAR(cycle, "c", pstring, 0, 0, 0, "Current machine cycle")