Use only 2 char var codes, Enabled serial hardware flow control, Reorder command...
authorJoseph Coffland <joseph@cauldrondevelopment.com>
Sun, 26 Jun 2016 19:15:37 +0000 (12:15 -0700)
committerJoseph Coffland <joseph@cauldrondevelopment.com>
Sun, 26 Jun 2016 19:15:37 +0000 (12:15 -0700)
src/command.c
src/command.h
src/main.c
src/messages.def
src/plan/arc.c
src/report.c
src/tmc2660.c
src/usart.c
src/vars.c
src/vars.def

index 37cf3be0a0200cf32e1f0bcea379a3e1cdbe68e7..80818cc3911b7f06a46b6008c75ff110b55be415 100644 (file)
@@ -35,6 +35,7 @@
 #include "estop.h"
 #include "plan/jog.h"
 #include "plan/calibrate.h"
+#include "plan/buffer.h"
 #include "config.h"
 
 #include <avr/pgmspace.h>
@@ -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);
 
index a110f622f67eb991780be8fa5eec4adafb0a3524..7c92c6a98b553a0265d015faf3321c5964a4f4d1 100644 (file)
@@ -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();
index 0d3882bea1343e410dbee791b4553db4a6d801ef..2e176a6a1cd6f8ace5150996cf3a481e2adcaace 100644 (file)
 #include <stdbool.h>
 
 
-/// 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);
 }
 
 
index ea0973b471a0365692f79f2bfec6044bf7f84202..1aa07cbb372babca1392d488ea77ec6b23418bf8 100644 (file)
@@ -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")
index 8b01e40a0a65c31be10418715f11baf9eea1d365..d62d18b14921465b4bfd17187077143d1d3163fc 100644 (file)
@@ -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;
 
index 5614f157878ae29017ef2d8739a61b1be7ee6d44..417ae6d7f3d62b0410b1006d83ae02f35137bde9 100644 (file)
@@ -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;
index ce7c7afcdbbd3512c6c4c10fa0d25525e2b19fb9..ba761b2c6f760ba08054863d3cdaf266be8c1edf 100644 (file)
@@ -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
index 7f4369d5003713e64b816790a9287f34ef67fa91..359b8fc5eab78e360b7192faea1a997e2dfb6cf0 100644 (file)
@@ -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);
 }
 
 
index 4c12de8bbe815b2e9d5dcfd929d586d255e85ecf..ba7dbcc0f44bb8f9ad1dc817b47e2bdcca146c77 100644 (file)
@@ -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();
index 072f1b0eb5b74a2d471cf54487caa4543b63b23f..80feee0633aade4df6e237ff27e9817b2ce42a58 100644 (file)
@@ -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")