From 46bc1c7e2109afa905a1dbfb791c75a2389697cf Mon Sep 17 00:00:00 2001 From: Joseph Coffland Date: Sun, 26 Jun 2016 12:15:37 -0700 Subject: [PATCH] Use only 2 char var codes, Enabled serial hardware flow control, Reorder command processing priority --- src/command.c | 60 ++++++++++++++++++++++++++++++++---------------- src/command.h | 4 ++-- src/main.c | 52 +++++++++-------------------------------- src/messages.def | 1 + src/plan/arc.c | 2 +- src/report.c | 2 ++ src/tmc2660.c | 2 +- src/usart.c | 20 +++++++++++----- src/vars.c | 2 +- src/vars.def | 10 ++++---- 10 files changed, 78 insertions(+), 77 deletions(-) diff --git a/src/command.c b/src/command.c index 37cf3be..80818cc 100644 --- a/src/command.c +++ b/src/command.c @@ -35,6 +35,7 @@ #include "estop.h" #include "plan/jog.h" #include "plan/calibrate.h" +#include "plan/buffer.h" #include "config.h" #include @@ -72,13 +73,7 @@ static const command_t commands[] PROGMEM = { }; -stat_t command_dispatch() { - // Read input line or return if incomplete, usart_gets() is non-blocking - char *input = usart_readline(); - if (!input) return STAT_EAGAIN; - - return command_eval(input); -} +static char *_cmd = 0; int command_find(const char *match) { @@ -150,26 +145,51 @@ int command_parser(char *cmd) { } -int command_eval(char *cmd) { - // Skip leading whitespace - while (*cmd && isspace(*cmd)) cmd++; +stat_t command_hi() { + // Get next command + if (!_cmd) { + // Read input line or return if incomplete, usart_readline() is non-blocking + _cmd = usart_readline(); + if (!_cmd) return STAT_OK; + + // Skip leading whitespace + while (*_cmd && isspace(*_cmd)) _cmd++; + } + + if (usart_tx_full()) return STAT_OK; + + stat_t status = STAT_OK; - switch (*cmd) { - case 0: report_request_full(); return STAT_OK; - case '{': return vars_parser(cmd); - case '$': return command_parser(cmd); - default: - if (estop_triggered()) return STAT_MACHINE_ALARMED; - if (calibrate_busy()) return STAT_OK; - if (mp_jog_busy()) return STAT_OK; - return gc_gcode_parser(cmd); + switch (*_cmd) { + case 0: report_request_full(); break; // Full report + case '{': status = vars_parser(_cmd); break; + case '$': status = command_parser(_cmd); break; + default: return STAT_OK; // Continue processing in command_lo() } + + _cmd = 0; // Command complete + return status; +} + + +stat_t command_lo() { + if (!_cmd || mp_get_planner_buffers_available() < PLANNER_BUFFER_HEADROOM || + usart_tx_full()) + return STAT_OK; // Wait + + if (estop_triggered()) return STAT_MACHINE_ALARMED; + if (calibrate_busy()) return STAT_BUSY; + if (mp_jog_busy()) return STAT_BUSY; + + stat_t status = gc_gcode_parser(_cmd); + _cmd = 0; + return status; } // Command functions void static print_command_help(int i) { - static const char fmt[] PROGMEM = " $%-8S %S\n"; + static const char fmt[] PROGMEM = " $%-12S %S\n"; const char *name = pgm_read_word(&commands[i].name); const char *help = pgm_read_word(&commands[i].help); diff --git a/src/command.h b/src/command.h index a110f62..7c92c6a 100644 --- a/src/command.h +++ b/src/command.h @@ -46,7 +46,7 @@ typedef struct { } command_t; -stat_t command_dispatch(); int command_find(const char *name); int command_exec(int argc, char *argv[]); -int command_eval(char *cmd); +stat_t command_hi(); +stat_t command_lo(); diff --git a/src/main.c b/src/main.c index 0d3882b..2e176a6 100644 --- a/src/main.c +++ b/src/main.c @@ -53,28 +53,6 @@ #include -/// Return eagain if TX queue is backed up -static stat_t _sync_to_tx_buffer() { - return usart_tx_full() ? STAT_EAGAIN : STAT_OK; -} - - -/// Return eagain if planner is not ready for a new command -static stat_t _sync_to_planner() { - return mp_get_planner_buffers_available() < PLANNER_BUFFER_HEADROOM ? - STAT_EAGAIN : STAT_OK; -} - - -/// Shut down system if limit switch fired -static stat_t _limit_switch_handler() { - if (cm_get_machine_state() == MACHINE_ALARM) return STAT_NOOP; - if (!switch_get_limit_thrown()) return STAT_NOOP; - - return CM_ALARM(STAT_LIMIT_SWITCH_HIT); -} - - static bool _dispatch(stat_t (*func)()) { stat_t err = func(); @@ -90,40 +68,32 @@ static bool _dispatch(stat_t (*func)()) { /* Main loop * - * The order of the dispatched tasks is very important. - * Tasks are ordered by increasing dependency (blocking hierarchy). - * Tasks that are dependent on completion of lower-level tasks must be - * later in the list than the task(s) they are dependent upon. - * - * Tasks must be written as continuations as they will be called repeatedly, - * and are called even if they are not currently active. - * - * The DISPATCH macro calls the function and returns to the caller - * if not finished (STAT_EAGAIN), preventing later routines from running - * (they remain blocked). Any other condition - OK or ERR - drops through - * and runs the next routine in the list. + * The task order is very important. Tasks are ordered by increasing dependency + * (blocking hierarchy). Tasks that are dependent on completion of lower-level + * tasks must be later in the list. Tasks are called repeatedly even if they + * are not currently active. * - * A routine that had no action (i.e. is OFF or idle) should return STAT_NOOP + * The DISPATCH macro calls a function and returns if not finished + * (STAT_EAGAIN). This prevents later routines from running. Any other + * condition - OK or ERR - drops through and runs the next routine in the list. */ static void _run() { #define DISPATCH(func) if (_dispatch(func)) return; DISPATCH(hw_reset_handler); // handle hard reset requests - DISPATCH(_limit_switch_handler); // limit switch thrown - DISPATCH(tmc2660_sync); // synchronize driver config DISPATCH(motor_power_callback); // stepper motor power sequencing + DISPATCH(command_hi); + DISPATCH(cm_feedhold_sequencing_callback); // feedhold state machine DISPATCH(mp_plan_hold_callback); // plan a feedhold DISPATCH(cm_arc_callback); // arc generation runs DISPATCH(cm_homing_callback); // G28.2 continuation DISPATCH(cm_probe_callback); // G38.2 continuation - - DISPATCH(_sync_to_planner); // ensure a free planning buffer - DISPATCH(_sync_to_tx_buffer); // sync with TX buffer DISPATCH(report_callback); // report changes - DISPATCH(command_dispatch); // read and execute next command + + DISPATCH(command_lo); } diff --git a/src/messages.def b/src/messages.def index ea0973b..1aa07cb 100644 --- a/src/messages.def +++ b/src/messages.def @@ -30,6 +30,7 @@ STAT_MSG(OK, "OK") STAT_MSG(EAGAIN, "Run command again") STAT_MSG(NOOP, "No op") STAT_MSG(COMPLETE, "Complete") +STAT_MSG(BUSY, "Busy") STAT_MSG(NO_SUCH_DEVICE, "No such device") STAT_MSG(BUFFER_FULL, "Buffer full") STAT_MSG(BUFFER_FULL_FATAL, "Buffer full - fatal") diff --git a/src/plan/arc.c b/src/plan/arc.c index 8b01e40..d62d18b 100644 --- a/src/plan/arc.c +++ b/src/plan/arc.c @@ -486,7 +486,7 @@ stat_t cm_arc_callback() { arc.ms.target[arc.plane_axis_1] = arc.center_1 + cos(arc.theta) * arc.radius; arc.ms.target[arc.linear_axis] += arc.arc_segment_linear_travel; mp_aline(&arc.ms); // run the line - copy_vector(arc.position, arc.ms.target); // update arc current pos + copy_vector(arc.position, arc.ms.target); // update arc current pos if (--arc.arc_segment_count > 0) return STAT_EAGAIN; diff --git a/src/report.c b/src/report.c index 5614f15..417ae6d 100644 --- a/src/report.c +++ b/src/report.c @@ -53,6 +53,8 @@ void report_request_full() { stat_t report_callback() { + if (usart_tx_full()) return STAT_OK; // Wait for buffer space + if (report_requested && usart_tx_empty()) { uint32_t now = rtc_get_time(); if (now - last_report < 100) return STAT_OK; diff --git a/src/tmc2660.c b/src/tmc2660.c index ce7c7af..ba761b2 100644 --- a/src/tmc2660.c +++ b/src/tmc2660.c @@ -295,7 +295,7 @@ void tmc2660_init() { // Setup pins // Must set the SS pin either in/high or any/output for master mode to work - TMC2660_SPI_PORT.OUTSET = 1 << TMC2660_SPI_SS_PIN; // High + // Note, this pin is also used by the USART as the CTS line TMC2660_SPI_PORT.DIRSET = 1 << TMC2660_SPI_SS_PIN; // Output TMC2660_SPI_PORT.OUTSET = 1 << TMC2660_SPI_SCK_PIN; // High diff --git a/src/usart.c b/src/usart.c index 7f4369d..359b8fc 100644 --- a/src/usart.c +++ b/src/usart.c @@ -57,8 +57,11 @@ static void _set_dre_interrupt(bool enable) { static void _set_rxc_interrupt(bool enable) { - if (enable) USARTC0.CTRLA |= USART_RXCINTLVL_HI_gc; - else USARTC0.CTRLA &= ~USART_RXCINTLVL_HI_gc; + if (enable) { + USARTC0.CTRLA |= USART_RXCINTLVL_HI_gc; + if (4 <= rx_buf_space()) PORTC.OUTCLR = 1 << 4; // CTS Lo (enable) + + } else USARTC0.CTRLA &= ~USART_RXCINTLVL_HI_gc; } @@ -96,6 +99,7 @@ ISR(USARTC0_RXC_vect) { uint8_t data = USARTC0.DATA; rx_buf_push(data); if (usart_flags & USART_ECHO) _echo_char(data); + if (rx_buf_space() < 4) PORTC.OUTSET = 1 << 4; // CTS Hi (disable) } } @@ -116,9 +120,11 @@ void usart_init(void) { PR.PRPC &= ~PR_USART0_bm; // Disable power reduction // Setup pins - PORTC.OUTSET = 1 << 3; // High - PORTC.DIRSET = 1 << 3; // Output - PORTC.DIRCLR = 1 << 2; // Input + PORTC.OUTSET = 1 << 4; // CTS Hi (disable) + PORTC.DIRSET = 1 << 4; // CTS Output + PORTC.OUTSET = 1 << 3; // Tx High + PORTC.DIRSET = 1 << 3; // Tx Output + PORTC.DIRCLR = 1 << 2; // Rx Input // Set baud rate usart_set_baud(USART_BAUD_115200); @@ -128,7 +134,6 @@ void usart_init(void) { USART_CHSIZE_8BIT_gc; // Configure receiver and transmitter - USARTC0.CTRLA = USART_RXCINTLVL_HI_gc; USARTC0.CTRLB = USART_RXEN_bm | USART_TXEN_bm | USART_CLK2X_bm; PMIC.CTRL |= PMIC_HILVLEN_bm; // Interrupt level on @@ -136,6 +141,9 @@ void usart_init(void) { // Connect IO stdout = &_stdout; stderr = &_stdout; + + // Enable Rx + _set_rxc_interrupt(true); } diff --git a/src/vars.c b/src/vars.c index 4c12de8..ba7dbcc 100644 --- a/src/vars.c +++ b/src/vars.c @@ -383,7 +383,7 @@ int vars_parser(char *vars) { void vars_print_help() { - static const char fmt[] PROGMEM = " $%-5s %-14S %-12S %S\n"; + static const char fmt[] PROGMEM = " $%-5s %-20S %-16S %S\n"; // Save and disable watchdog uint8_t wd_state = hw_disable_watchdog(); diff --git a/src/vars.def b/src/vars.def index 072f1b0..80feee0 100644 --- a/src/vars.def +++ b/src/vars.def @@ -42,10 +42,10 @@ VAR(power_mode, "pm", uint8_t, MOTORS, 1, 0, "Motor power mode") VAR(power_level, "pl", float, MOTORS, 1, 0, "Motor drive current") VAR(idle_level, "il", float, MOTORS, 1, 0, "Motor idle current") VAR(current_level, "cl", float, MOTORS, 1, 0, "Motor current now") -VAR(stallguard, "sg", int8_t, MOTORS, 1, 0, "StallGuard threshold") -VAR(sg_value, "sgv", uint16_t, MOTORS, 0, 0, "StallGuard reading") +VAR(stallguard, "th", int8_t, MOTORS, 1, 0, "StallGuard threshold") +VAR(sg_value, "sg", uint16_t, MOTORS, 0, 0, "StallGuard reading") VAR(status_flags, "mf", uint8_t, MOTORS, 0, 0, "Motor status flags") -VAR(status_strings,"mfs", flags_t, MOTORS, 0, 0, "Motor status strings") +VAR(status_strings, "ms", flags_t, MOTORS, 0, 0, "Motor status strings") // Axis VAR(position, "p", float, AXES, 0, 0, "Current axis position") @@ -96,5 +96,5 @@ VAR(switch_type, "sw", uint8_t, SWITCHES, 1, 0, "Normally open or closed") // System VAR(velocity, "v", float, 0, 0, 0, "Current velocity") VAR(hw_id, "id", string, 0, 0, 0, "Hardware ID") -VAR(echo, "echo", bool, 0, 1, 1, "Enable or disable echo") -VAR(estop, "estop", bool, 0, 1, 1, "Emergency stop") +VAR(echo, "ec", bool, 0, 1, 1, "Enable or disable echo") +VAR(estop, "es", bool, 0, 1, 1, "Emergency stop") -- 2.27.0