avr-size -C --mcu=$(MCU) $(TARGET)
# Program
+reset:
+ avrdude $(AVRDUDE_OPTS)
+
erase:
avrdude $(AVRDUDE_OPTS) -e
rm -rf $(PROJECT).elf $(PROJECT).hex $(PROJECT).eep $(PROJECT).lss \
$(PROJECT).map build fuse?.hex
-.PHONY: tidy clean size all erase program fuses read_fuses
+.PHONY: tidy clean size all reset erase program fuses read_fuses
# Dependencies
-include $(shell mkdir -p build/dep) $(wildcard build/dep/*)
#ifndef CONFIG_H_ONCE
#define CONFIG_H_ONCE
-/***** PLEASE NOTE *****
-#include "config_app.h" // is present at the end of this file
-*/
+// Please note config_app.h in included at the end of this file
/**** Config System Overview and Usage ***
*
* This way the internals don't care about how the variable is represented or communicated
* externally as all internal operations occur on the nvObjs, not the wire form (text or JSON).
*/
+
/* --- Config variables, tables and strings ---
*
* Each configuration value is identified by a short mnemonic string (token). The token
* with: xyzabcuvw0123456789 (but there can be exceptions)
*
* "Groups" are collections of values that mimic REST resources. Groups include:
- * - axis groups prefixed by "xyzabc" ("uvw" are reserved)
+ * - axis groups prefixed by "xyzabc" ("uvw" are reserved)
* - motor groups prefixed by "1234" ("56789" are reserved)
- * - PWM groups prefixed by p1, p2 (p3 - p9 are reserved)
+ * - PWM groups prefixed by p1, p2 (p3 - p9 are reserved)
* - coordinate system groups prefixed by g54, g55, g56, g57, g59, g92
* - a system group is identified by "sys" and contains a collection of otherwise unrelated values
*
* - group of all offset groups
* - group of all groups
*/
+
/* --- Making changes and adding new values
*
* Adding a new value to config (or changing an existing one) involves touching the following places:
/**** nvObj lists ****
*
- * Commands and groups of commands are processed internally a doubly linked list of nvObj_t
+ * Commands and groups of commands are processed internally a doubly linked list of nvObj_t
* structures. This isolates the command and config internals from the details of communications,
* parsing and display in text mode and JSON mode.
*
* When you use the list you can terminate your own last element, or just leave the EMPTY elements
* to be skipped over during output serialization.
*
- * We don't use recursion so parent/child nesting relationships are captured in a 'depth' variable,
+ * We don't use recursion so parent/child nesting relationships are captured in a 'depth' variable,
* This must remain consistent if the curlies are to work out. You should not have to track depth
* explicitly if you use nv_reset_nv_list() or the accessor functions like nv_add_integer() or
* nv_add_message(). If you see problems with curlies check the depth values in the lists.
*
* Use the nv_print_list() dispatcher for all JSON and text output. Do not simply run through printf.
*/
+
/* Token and Group Fields
*
* The nvObject struct (nvObj_t) has strict rules on the use of the token and group fields.
* - JSON-mode display for single - element value e.g. xvm. Concatenate as above
* - JSON-mode display of a parent/child group. Parent is named grp, children nems are tokens
*/
+
/* --- nv object string handling ---
*
* It's very expensive to allocate sufficient string space to each nvObj, so nv uses a cheater's
* the output buffer (typ 256 bytes), So some number less than that is sufficient for shared strings.
* This is all mediated through nv_copy_string(), nv_copy_string_P(), and nv_reset_nv_list().
*/
+
/* --- Setting nvObj indexes ---
*
* It's the responsibility of the object creator to set the index. Downstream functions
* (linear table scan), so there are some exceptions where the index does not need to be set.
* These cases are put in the code, commented out, and explained.
*/
+
/* --- Other Notes:---
*
* NV_BODY_LEN needs to allow for one parent JSON object and enough children to complete the
#include <stdint.h>
-// Sizing and footprints // chose one based on # of elements in cfgArray
-//typedef uint8_t index_t; // use this if there are < 256 indexed objects
-typedef uint16_t index_t; // use this if there are > 255 indexed objects
+// Sizing and footprints // chose one based on # of elements in cfgArray
+typedef uint16_t index_t; // use this if there are > 255 indexed objects
- // defines allocated from stack (not-pre-allocated)
-#define NV_FORMAT_LEN 128 // print formatting string max length
-#define NV_MESSAGE_LEN 128 // sufficient space to contain end-user messages
+ // defines allocated from stack (not-pre-allocated)
+#define NV_FORMAT_LEN 128 // print formatting string max length
+#define NV_MESSAGE_LEN 128 // sufficient space to contain end-user messages
- // pre-allocated defines (take RAM permanently)
-#define NV_SHARED_STRING_LEN 512 // shared string for string values
-#define NV_BODY_LEN 30 // body elements - allow for 1 parent + N children
- // (each body element takes about 30 bytes of RAM)
+ // pre-allocated defines (take RAM permanently)
+#define NV_SHARED_STRING_LEN 512 // shared string for string values
+#define NV_BODY_LEN 30 // body elements - allow for 1 parent + N children
+ // (each body element takes about 30 bytes of RAM)
-// Stuff you probably don't want to change
+// Stuff you probably don't want to change
#define GROUP_LEN 3 // max length of group prefix
#define TOKEN_LEN 5 // mnemonic token string: group prefix + short token
#define NV_FOOTER_LEN 18 // sufficient space to contain a JSON footer array
-#define NV_LIST_LEN (NV_BODY_LEN+2) // +2 allows for a header and a footer
-#define NV_MAX_OBJECTS (NV_BODY_LEN-1) // maximum number of objects in a body string
+#define NV_LIST_LEN (NV_BODY_LEN + 2) // +2 allows for a header and a footer
+#define NV_MAX_OBJECTS (NV_BODY_LEN - 1) // maximum number of objects in a body string
#define NO_MATCH (index_t)0xFFFF
#define NV_STATUS_REPORT_LEN NV_MAX_OBJECTS // max number of status report elements - see cfgArray
// **** must also line up in cfgArray, se00 - seXX ****
enum tgCommunicationsMode {
- TEXT_MODE = 0, // text command line mode
- JSON_MODE, // strict JSON construction
- JSON_MODE_RELAXED // relaxed JSON construction (future)
+ TEXT_MODE = 0, // text command line mode
+ JSON_MODE, // strict JSON construction
+ JSON_MODE_RELAXED // relaxed JSON construction (future)
};
+
enum flowControl {
- FLOW_CONTROL_OFF = 0, // flow control disabled
- FLOW_CONTROL_XON, // flow control uses XON/XOFF
- FLOW_CONTROL_RTS // flow control uses RTS/CTS
+ FLOW_CONTROL_OFF = 0, // flow control disabled
+ FLOW_CONTROL_XON, // flow control uses XON/XOFF
+ FLOW_CONTROL_RTS // flow control uses RTS/CTS
};
-enum valueType { // value typing for config and JSON
- TYPE_EMPTY = -1, // value struct is empty (which is not the same as "0")
- TYPE_0 = 0, // value is 'null' (meaning the JSON null value)
- TYPE_BOOL, // value is "true" (1) or "false"(0)
- TYPE_INTEGER, // value is a uint32_t
- TYPE_DATA, // value is blind cast to uint32_t
- TYPE_FLOAT, // value is a floating point number
- TYPE_STRING, // value is in string field
- TYPE_ARRAY, // value is array element count, values are CSV ASCII in string field
- TYPE_PARENT // object is a parent to a sub-object
+
+enum valueType { // value typing for config and JSON
+ TYPE_EMPTY = -1, // value struct is empty (which is not the same as "0")
+ TYPE_0 = 0, // value is 'null' (meaning the JSON null value)
+ TYPE_BOOL, // value is "true" (1) or "false"(0)
+ TYPE_INTEGER, // value is a uint32_t
+ TYPE_DATA, // value is blind cast to uint32_t
+ TYPE_FLOAT, // value is a floating point number
+ TYPE_STRING, // value is in string field
+ TYPE_ARRAY, // value is array element count, values are CSV ASCII in string field
+ TYPE_PARENT // object is a parent to a sub-object
};
-/**** operations flags and shorthand ****/
-#define F_INITIALIZE 0x01 // initialize this item (run set during initialization)
-#define F_PERSIST 0x02 // persist this item when set is run
-#define F_NOSTRIP 0x04 // do not strip the group prefix from the token
-#define F_CONVERT 0x08 // set if unit conversion is required
+// Operations flags and shorthand
+#define F_INITIALIZE 0x01 // initialize this item (run set during initialization)
+#define F_PERSIST 0x02 // persist this item when set is run
+#define F_NOSTRIP 0x04 // do not strip the group prefix from the token
+#define F_CONVERT 0x08 // set if unit conversion is required
#define _f0 0x00
#define _fi (F_INITIALIZE)
#define _fipn (F_INITIALIZE | F_PERSIST | F_NOSTRIP)
#define _fipnc (F_INITIALIZE | F_PERSIST | F_NOSTRIP | F_CONVERT)
-/**** Structures ****/
-
-typedef struct nvString { // shared string object
- uint16_t magic_start;
- #if (NV_SHARED_STRING_LEN < 256)
- uint8_t wp; // use this string array index value if string len < 256 bytes
- #else
- uint16_t wp; // use this string array index value is string len > 255 bytes
- #endif
- char_t string[NV_SHARED_STRING_LEN];
- uint16_t magic_end; // guard to detect string buffer underruns
+
+typedef struct nvString { // shared string object
+ uint16_t magic_start;
+#if (NV_SHARED_STRING_LEN < 256)
+ uint8_t wp; // use this string array index value if string len < 256 bytes
+#else
+ uint16_t wp; // use this string array index value is string len > 255 bytes
+#endif
+ char_t string[NV_SHARED_STRING_LEN];
+ uint16_t magic_end; // guard to detect string buffer underruns
} nvStr_t;
-typedef struct nvObject { // depending on use, not all elements may be populated
- struct nvObject *pv; // pointer to previous object or 0 if first object
- struct nvObject *nx; // pointer to next object or 0 if last object
- index_t index; // index of tokenized name, or -1 if no token (optional)
- int8_t depth; // depth of object in the tree. 0 is root (-1 is invalid)
- int8_t valuetype; // see valueType enum
- int8_t precision; // decimal precision for reporting (JSON)
- float value; // numeric value
- char_t group[GROUP_LEN+1]; // group prefix or 0 if not in a group
- char_t token[TOKEN_LEN+1]; // full mnemonic token for lookup
- char_t (*stringp)[]; // pointer to array of characters from shared character array
-} nvObj_t; // OK, so it's not REALLY an object
-
-typedef uint8_t (*fptrCmd)(nvObj_t *nv);// required for cfg table access
-typedef void (*fptrPrint)(nvObj_t *nv); // required for PROGMEM access
+
+typedef struct nvObject { // depending on use, not all elements may be populated
+ struct nvObject *pv; // pointer to previous object or 0 if first object
+ struct nvObject *nx; // pointer to next object or 0 if last object
+ index_t index; // index of tokenized name, or -1 if no token (optional)
+ int8_t depth; // depth of object in the tree. 0 is root (-1 is invalid)
+ int8_t valuetype; // see valueType enum
+ int8_t precision; // decimal precision for reporting (JSON)
+ float value; // numeric value
+ char_t group[GROUP_LEN + 1]; // group prefix or 0 if not in a group
+ char_t token[TOKEN_LEN + 1]; // full mnemonic token for lookup
+ char_t (*stringp)[]; // pointer to array of characters from shared character array
+} nvObj_t;
+
+
+typedef uint8_t (*fptrCmd)(nvObj_t *nv); // required for cfg table access
+typedef void (*fptrPrint)(nvObj_t *nv); // required for PROGMEM access
+
typedef struct nvList {
- uint16_t magic_start;
- nvObj_t list[NV_LIST_LEN]; // list of nv objects, including space for a JSON header element
- uint16_t magic_end;
+ uint16_t magic_start;
+ nvObj_t list[NV_LIST_LEN]; // list of nv objects, including space for a JSON header element
+ uint16_t magic_end;
} nvList_t;
+
typedef struct cfgItem {
- char_t group[GROUP_LEN+1]; // group prefix (with 0 termination)
- char_t token[TOKEN_LEN+1]; // token - stripped of group prefix (w/0 termination)
- uint8_t flags; // operations flags - see defines below
- int8_t precision; // decimal precision for display (JSON)
- fptrPrint print; // print binding: aka void (*print)(nvObj_t *nv);
- fptrCmd get; // GET binding aka uint8_t (*get)(nvObj_t *nv)
- fptrCmd set; // SET binding aka uint8_t (*set)(nvObj_t *nv)
- float *target; // target for writing config value
- float def_value; // default value for config item
+ char_t group[GROUP_LEN + 1]; // group prefix (with 0 termination)
+ char_t token[TOKEN_LEN + 1]; // token - stripped of group prefix (w/0 termination)
+ uint8_t flags; // operations flags - see defines below
+ int8_t precision; // decimal precision for display (JSON)
+ fptrPrint print; // print binding: aka void (*print)(nvObj_t *nv);
+ fptrCmd get; // GET binding aka uint8_t (*get)(nvObj_t *nv)
+ fptrCmd set; // SET binding aka uint8_t (*set)(nvObj_t *nv)
+ float *target; // target for writing config value
+ float def_value; // default value for config item
} cfgItem_t;
-/**** static allocation and definitions ****/
extern nvStr_t nvStr;
extern nvList_t nvl;
extern const cfgItem_t cfgArray[];
-//#define nv_header nv.list
+
#define nv_header (&nvl.list[0])
#define nv_body (&nvl.list[1])
-/**** Prototypes for generic config functions - see individual modules for application-specific functions ****/
void config_init();
-stat_t set_defaults(nvObj_t *nv); // reset config to default values
+stat_t set_defaults(nvObj_t *nv); // reset config to default values
void config_init_assertions();
stat_t config_test_assertions();
+
// main entry points for core access functions
-stat_t nv_get(nvObj_t *nv); // main entry point for get value
-stat_t nv_set(nvObj_t *nv); // main entry point for set value
-void nv_print(nvObj_t *nv); // main entry point for print value
-stat_t nv_persist(nvObj_t *nv); // main entry point for persistence
+stat_t nv_get(nvObj_t *nv); // main entry point for get value
+stat_t nv_set(nvObj_t *nv); // main entry point for set value
+void nv_print(nvObj_t *nv); // main entry point for print value
+stat_t nv_persist(nvObj_t *nv); // main entry point for persistence
-// helpers
+
+// Helpers
uint8_t nv_get_type(nvObj_t *nv);
index_t nv_get_index(const char_t *group, const char_t *token);
-index_t nv_index_max(); // (see config_app.c)
-uint8_t nv_index_is_single(index_t index); // (see config_app.c)
+index_t nv_index_max(); // (see config_app.c)
+uint8_t nv_index_is_single(index_t index); // (see config_app.c)
uint8_t nv_index_is_group(index_t index); // (see config_app.c)
-uint8_t nv_index_lt_groups(index_t index); // (see config_app.c)
+uint8_t nv_index_lt_groups(index_t index); // (see config_app.c)
uint8_t nv_group_is_prefixed(char_t *group);
-// generic internal functions and accessors
-stat_t set_nul(nvObj_t *nv); // set nothing (no operation)
-stat_t set_ui8(nvObj_t *nv); // set uint8_t value
-stat_t set_01(nvObj_t *nv); // set a 0 or 1 value with validation
-stat_t set_012(nvObj_t *nv); // set a 0, 1 or 2 value with validation
+
+// Generic internal functions and accessors
+stat_t set_nul(nvObj_t *nv); // set nothing (no operation)
+stat_t set_ui8(nvObj_t *nv); // set uint8_t value
+stat_t set_01(nvObj_t *nv); // set a 0 or 1 value with validation
+stat_t set_012(nvObj_t *nv); // set a 0, 1 or 2 value with validation
stat_t set_0123(nvObj_t *nv); // set a 0, 1, 2 or 3 value with validation
-stat_t set_int(nvObj_t *nv); // set uint32_t integer value
+stat_t set_int(nvObj_t *nv); // set uint32_t integer value
stat_t set_data(nvObj_t *nv); // set uint32_t integer value blind cast
-stat_t set_flt(nvObj_t *nv); // set floating point value
+stat_t set_flt(nvObj_t *nv); // set floating point value
-stat_t get_nul(nvObj_t *nv); // get null value type
-stat_t get_ui8(nvObj_t *nv); // get uint8_t value
-stat_t get_int(nvObj_t *nv); // get uint32_t integer value
+stat_t get_nul(nvObj_t *nv); // get null value type
+stat_t get_ui8(nvObj_t *nv); // get uint8_t value
+stat_t get_int(nvObj_t *nv); // get uint32_t integer value
stat_t get_data(nvObj_t *nv); // get uint32_t integer value blind cast
-stat_t get_flt(nvObj_t *nv); // get floating point value
+stat_t get_flt(nvObj_t *nv); // get floating point value
+
+stat_t set_grp(nvObj_t *nv); // set data for a group
+stat_t get_grp(nvObj_t *nv); // get data for a group
-stat_t set_grp(nvObj_t *nv); // set data for a group
-stat_t get_grp(nvObj_t *nv); // get data for a group
// nvObj and list functions
void nv_get_nvObj(nvObj_t *nv);
nvObj_t *nv_add_conditional_message(const char_t *string);
void nv_print_list(stat_t status, uint8_t text_flags, uint8_t json_flags);
-// application specific helpers and functions (config_app.c)
+
+// Application specific helpers and functions (config_app.c)
stat_t set_flu(nvObj_t *nv); // set floating point number with G20/G21 units conversion
-void preprocess_float(nvObj_t *nv); // pre-process float values for units and illegal values
+void preprocess_float(nvObj_t *nv); // pre-process float values for units and illegal values
+
-// diagnostics
+// Diagnostics
void nv_dump_nv(nvObj_t *nv);
-/*********************************************************************************************
- **** PLEASE NOTICE THAT CONFIG_APP.H IS HERE ************************************************
- *********************************************************************************************/
+
+// Please notice that config_app.h is here
#include "config_app.h"
-#endif // End of include guard: CONFIG_H_ONCE
+#endif // CONFIG_H_ONCE
#include "util.h"
#include "help.h"
#include "usart.h"
+#include "tmc2660.h"
-cfgParameters_t cfg; // application specific configuration parameters
+cfgParameters_t cfg; // Application specific configuration parameters
// See config.cpp/.h for generic variables and functions that are not specific to
// TinyG or the motion control application domain
// helpers (most helpers are defined immediately above their usage so they don't need prototypes here)
-
static stat_t _do_motors(nvObj_t *nv); // print parameters for all motor groups
-static stat_t _do_axes(nvObj_t *nv); // print parameters for all axis groups
-static stat_t _do_offsets(nvObj_t *nv); // print offset parameters for G54-G59,G92, G28, G30
-static stat_t _do_all(nvObj_t *nv); // print all parameters
+static stat_t _do_axes(nvObj_t *nv); // print parameters for all axis groups
+static stat_t _do_offsets(nvObj_t *nv); // print offset parameters for G54-G59,G92, G28, G30
+static stat_t _do_all(nvObj_t *nv); // print all parameters
// communications settings and functions
-
static stat_t set_ec(nvObj_t *nv); // expand CRLF on TX output
static stat_t set_ee(nvObj_t *nv); // enable character echo
static stat_t set_ex(nvObj_t *nv); // enable XON/XOFF and RTS/CTS flow control
* uint16_t in the config.h file.
*/
const cfgItem_t cfgArray[] PROGMEM = {
- // group token flags p, print_func, get_func, set_func, target for get/set, default value
+ // group, token, flags, p, print_func, get_func, set_func, target for get/set, default value
{"sys", "fb", _fipn,2, hw_print_fb, get_flt, set_nul, (float *)&cs.fw_build, TINYG_FIRMWARE_BUILD}, // MUST BE FIRST!
{"sys", "fv", _fipn,3, hw_print_fv, get_flt, set_nul, (float *)&cs.fw_version, TINYG_FIRMWARE_VERSION},
{"sys", "hp", _fipn,0, hw_print_hp, get_flt, set_flt, (float *)&cs.hw_platform,TINYG_HARDWARE_PLATFORM},
{"sys", "hv", _fipn,0, hw_print_hv, get_flt, hw_set_hv,(float *)&cs.hw_version, TINYG_HARDWARE_VERSION},
- {"sys", "id", _fn, 0, hw_print_id, hw_get_id, set_nul, (float *)&cs.null, 0}, // device ID (ASCII signature)
-
- // dynamic model attributes for reporting purposes (up front for speed)
- {"", "n", _fi, 0, cm_print_line, cm_get_mline,set_int,(float *)&cm.gm.linenum,0}, // Model line number
- {"", "line",_fi, 0, cm_print_line, cm_get_line, set_int,(float *)&cm.gm.linenum,0}, // Active line number - model or runtime line number
- {"", "vel", _f0, 2, cm_print_vel, cm_get_vel, set_nul,(float *)&cs.null, 0}, // current velocity
- {"", "feed",_f0, 2, cm_print_feed, cm_get_feed, set_nul,(float *)&cs.null, 0}, // feed rate
- {"", "stat",_f0, 0, cm_print_stat, cm_get_stat, set_nul,(float *)&cs.null, 0}, // combined machine state
- {"", "macs",_f0, 0, cm_print_macs, cm_get_macs, set_nul,(float *)&cs.null, 0}, // raw machine state
- {"", "cycs",_f0, 0, cm_print_cycs, cm_get_cycs, set_nul,(float *)&cs.null, 0}, // cycle state
- {"", "mots",_f0, 0, cm_print_mots, cm_get_mots, set_nul,(float *)&cs.null, 0}, // motion state
- {"", "hold",_f0, 0, cm_print_hold, cm_get_hold, set_nul,(float *)&cs.null, 0}, // feedhold state
- {"", "unit",_f0, 0, cm_print_unit, cm_get_unit, set_nul,(float *)&cs.null, 0}, // units mode
- {"", "coor",_f0, 0, cm_print_coor, cm_get_coor, set_nul,(float *)&cs.null, 0}, // coordinate system
- {"", "momo",_f0, 0, cm_print_momo, cm_get_momo, set_nul,(float *)&cs.null, 0}, // motion mode
- {"", "plan",_f0, 0, cm_print_plan, cm_get_plan, set_nul,(float *)&cs.null, 0}, // plane select
- {"", "path",_f0, 0, cm_print_path, cm_get_path, set_nul,(float *)&cs.null, 0}, // path control mode
- {"", "dist",_f0, 0, cm_print_dist, cm_get_dist, set_nul,(float *)&cs.null, 0}, // distance mode
- {"", "frmo",_f0, 0, cm_print_frmo, cm_get_frmo, set_nul,(float *)&cs.null, 0}, // feed rate mode
- {"", "tool",_f0, 0, cm_print_tool, cm_get_toolv,set_nul,(float *)&cs.null, 0}, // active tool
+ {"sys", "id", _fn, 0, hw_print_id, hw_get_id, set_nul, (float *)&cs.null, 0}, // device ID (ASCII signature)
+
+ {"mst", "mst1", _f0, 0, tmc2660_print_motor_step, tmc2660_get_motor_step, set_nul, (float *)&cs.null, 0},
+ {"mst", "mst2", _f0, 0, tmc2660_print_motor_step, tmc2660_get_motor_step, set_nul, (float *)&cs.null, 0},
+ {"mst", "mst3", _f0, 0, tmc2660_print_motor_step, tmc2660_get_motor_step, set_nul, (float *)&cs.null, 0},
+ {"mst", "mst4", _f0, 0, tmc2660_print_motor_step, tmc2660_get_motor_step, set_nul, (float *)&cs.null, 0},
+ {"mfl", "mfl1", _f0, 0, tmc2660_print_motor_flags, tmc2660_get_motor_flags, set_nul, (float *)&cs.null, 0},
+ {"mfl", "mfl2", _f0, 0, tmc2660_print_motor_flags, tmc2660_get_motor_flags, set_nul, (float *)&cs.null, 0},
+ {"mfl", "mfl3", _f0, 0, tmc2660_print_motor_flags, tmc2660_get_motor_flags, set_nul, (float *)&cs.null, 0},
+ {"mfl", "mfl4", _f0, 0, tmc2660_print_motor_flags, tmc2660_get_motor_flags, set_nul, (float *)&cs.null, 0},
+
+ // Dynamic model attributes for reporting purposes (up front for speed)
+ {"", "n", _fi, 0, cm_print_line, cm_get_mline,set_int,(float *)&cm.gm.linenum,0}, // Model line number
+ {"", "line",_fi, 0, cm_print_line, cm_get_line, set_int,(float *)&cm.gm.linenum,0}, // Active model or runtime line number
+ {"", "vel", _f0, 2, cm_print_vel, cm_get_vel, set_nul,(float *)&cs.null, 0}, // current velocity
+ {"", "feed",_f0, 2, cm_print_feed, cm_get_feed, set_nul,(float *)&cs.null, 0}, // feed rate
+ {"", "stat",_f0, 0, cm_print_stat, cm_get_stat, set_nul,(float *)&cs.null, 0}, // combined machine state
+ {"", "macs",_f0, 0, cm_print_macs, cm_get_macs, set_nul,(float *)&cs.null, 0}, // raw machine state
+ {"", "cycs",_f0, 0, cm_print_cycs, cm_get_cycs, set_nul,(float *)&cs.null, 0}, // cycle state
+ {"", "mots",_f0, 0, cm_print_mots, cm_get_mots, set_nul,(float *)&cs.null, 0}, // motion state
+ {"", "hold",_f0, 0, cm_print_hold, cm_get_hold, set_nul,(float *)&cs.null, 0}, // feedhold state
+ {"", "unit",_f0, 0, cm_print_unit, cm_get_unit, set_nul,(float *)&cs.null, 0}, // units mode
+ {"", "coor",_f0, 0, cm_print_coor, cm_get_coor, set_nul,(float *)&cs.null, 0}, // coordinate system
+ {"", "momo",_f0, 0, cm_print_momo, cm_get_momo, set_nul,(float *)&cs.null, 0}, // motion mode
+ {"", "plan",_f0, 0, cm_print_plan, cm_get_plan, set_nul,(float *)&cs.null, 0}, // plane select
+ {"", "path",_f0, 0, cm_print_path, cm_get_path, set_nul,(float *)&cs.null, 0}, // path control mode
+ {"", "dist",_f0, 0, cm_print_dist, cm_get_dist, set_nul,(float *)&cs.null, 0}, // distance mode
+ {"", "frmo",_f0, 0, cm_print_frmo, cm_get_frmo, set_nul,(float *)&cs.null, 0}, // feed rate mode
+ {"", "tool",_f0, 0, cm_print_tool, cm_get_toolv,set_nul,(float *)&cs.null, 0}, // active tool
{"mpo","mpox",_f0, 3, cm_print_mpo, cm_get_mpo, set_nul,(float *)&cs.null, 0}, // X machine position
{"mpo","mpoy",_f0, 3, cm_print_mpo, cm_get_mpo, set_nul,(float *)&cs.null, 0}, // Y machine position
{"ofs","ofsb",_f0, 3, cm_print_ofs, cm_get_ofs, set_nul,(float *)&cs.null, 0}, // B work offset
{"ofs","ofsc",_f0, 3, cm_print_ofs, cm_get_ofs, set_nul,(float *)&cs.null, 0}, // C work offset
- {"hom","home",_f0, 0, cm_print_home, cm_get_home, cm_run_home,(float *)&cs.null, 0}, // homing state, invoke homing cycle
- {"hom","homx",_f0, 0, cm_print_pos, get_ui8, set_nul,(float *)&cm.homed[AXIS_X], false}, // X homed - Homing status group
- {"hom","homy",_f0, 0, cm_print_pos, get_ui8, set_nul,(float *)&cm.homed[AXIS_Y], false}, // Y homed
- {"hom","homz",_f0, 0, cm_print_pos, get_ui8, set_nul,(float *)&cm.homed[AXIS_Z], false}, // Z homed
- {"hom","homa",_f0, 0, cm_print_pos, get_ui8, set_nul,(float *)&cm.homed[AXIS_A], false}, // A homed
- {"hom","homb",_f0, 0, cm_print_pos, get_ui8, set_nul,(float *)&cm.homed[AXIS_B], false}, // B homed
- {"hom","homc",_f0, 0, cm_print_pos, get_ui8, set_nul,(float *)&cm.homed[AXIS_C], false}, // C homed
+ {"hom","home",_f0, 0, cm_print_home, cm_get_home, cm_run_home,(float *)&cs.null, 0}, // homing state, invoke homing cycle
+ {"hom","homx",_f0, 0, cm_print_pos, get_ui8, set_nul,(float *)&cm.homed[AXIS_X], false}, // X homed - Homing status group
+ {"hom","homy",_f0, 0, cm_print_pos, get_ui8, set_nul,(float *)&cm.homed[AXIS_Y], false}, // Y homed
+ {"hom","homz",_f0, 0, cm_print_pos, get_ui8, set_nul,(float *)&cm.homed[AXIS_Z], false}, // Z homed
+ {"hom","homa",_f0, 0, cm_print_pos, get_ui8, set_nul,(float *)&cm.homed[AXIS_A], false}, // A homed
+ {"hom","homb",_f0, 0, cm_print_pos, get_ui8, set_nul,(float *)&cm.homed[AXIS_B], false}, // B homed
+ {"hom","homc",_f0, 0, cm_print_pos, get_ui8, set_nul,(float *)&cm.homed[AXIS_C], false}, // C homed
{"prb","prbe",_f0, 0, tx_print_nul, get_ui8, set_nul,(float *)&cm.probe_state, 0}, // probing state
{"prb","prbx",_f0, 3, tx_print_nul, get_flt, set_nul,(float *)&cm.probe_results[AXIS_X], 0},
{"jog","jogz",_f0, 0, tx_print_nul, get_nul, cm_run_jogz, (float *)&cm.jogging_dest, 0},
{"jog","joga",_f0, 0, tx_print_nul, get_nul, cm_run_joga, (float *)&cm.jogging_dest, 0},
- {"pwr","pwr1",_f0, 0, st_print_pwr, st_get_pwr, set_nul, (float *)&cs.null, 0}, // motor power enable readouts
+ {"pwr","pwr1",_f0, 0, st_print_pwr, st_get_pwr, set_nul, (float *)&cs.null, 0}, // motor power enable readouts
{"pwr","pwr2",_f0, 0, st_print_pwr, st_get_pwr, set_nul, (float *)&cs.null, 0},
{"pwr","pwr3",_f0, 0, st_print_pwr, st_get_pwr, set_nul, (float *)&cs.null, 0},
{"pwr","pwr4",_f0, 0, st_print_pwr, st_get_pwr, set_nul, (float *)&cs.null, 0},
#endif
// Reports, tests, help, and messages
- {"", "sr", _f0, 0, sr_print_sr, sr_get, sr_set, (float *)&cs.null, 0}, // status report object
- {"", "qr", _f0, 0, qr_print_qr, qr_get, set_nul, (float *)&cs.null, 0}, // queue report - planner buffers available
- {"", "qi", _f0, 0, qr_print_qi, qi_get, set_nul, (float *)&cs.null, 0}, // queue report - buffers added to queue
- {"", "qo", _f0, 0, qr_print_qo, qo_get, set_nul, (float *)&cs.null, 0}, // queue report - buffers removed from queue
- {"", "er", _f0, 0, tx_print_nul, rpt_er, set_nul, (float *)&cs.null, 0}, // invoke bogus exception report for testing
- {"", "qf", _f0, 0, tx_print_nul, get_nul, cm_run_qf,(float *)&cs.null, 0}, // queue flush
- {"", "rx", _f0, 0, tx_print_int, get_rx, set_nul, (float *)&cs.null, 0}, // space in RX buffer
- {"", "msg", _f0, 0, tx_print_str, get_nul, set_nul, (float *)&cs.null, 0}, // string for generic messages
- {"", "clear",_f0,0, tx_print_nul, cm_clear,cm_clear, (float *)&cs.null, 0}, // GET a clear to clear soft alarm
+ {"", "sr", _f0, 0, sr_print_sr, sr_get, sr_set, (float *)&cs.null, 0}, // status report object
+ {"", "qr", _f0, 0, qr_print_qr, qr_get, set_nul, (float *)&cs.null, 0}, // queue report - planner buffers available
+ {"", "qi", _f0, 0, qr_print_qi, qi_get, set_nul, (float *)&cs.null, 0}, // queue report - buffers added to queue
+ {"", "qo", _f0, 0, qr_print_qo, qo_get, set_nul, (float *)&cs.null, 0}, // queue report - buffers removed from queue
+ {"", "er", _f0, 0, tx_print_nul, rpt_er, set_nul, (float *)&cs.null, 0}, // invoke bogus exception report for testing
+ {"", "qf", _f0, 0, tx_print_nul, get_nul, cm_run_qf,(float *)&cs.null, 0}, // queue flush
+ {"", "rx", _f0, 0, tx_print_int, get_rx, set_nul, (float *)&cs.null, 0}, // space in RX buffer
+ {"", "msg", _f0, 0, tx_print_str, get_nul, set_nul, (float *)&cs.null, 0}, // string for generic messages
+ {"", "clear",_f0,0, tx_print_nul, cm_clear,cm_clear, (float *)&cs.null, 0}, // GET a clear to clear soft alarm
{"", "test",_f0, 0, tx_print_nul, help_test, run_test, (float *)&cs.null,0}, // run tests, print test help screen
- {"", "defa",_f0, 0, tx_print_nul, help_defa, set_defaults,(float *)&cs.null,0}, // set/print defaults / help screen
+ {"", "defa",_f0, 0, tx_print_nul, help_defa, set_defaults,(float *)&cs.null,0}, // set/print defaults / help screen
{"", "boot",_f0, 0, tx_print_nul, help_boot_loader,hw_run_boot, (float *)&cs.null,0},
#ifdef __HELP_SCREENS
- {"", "help",_f0, 0, tx_print_nul, help_config, set_nul, (float *)&cs.null,0}, // prints config help screen
- {"", "h", _f0, 0, tx_print_nul, help_config, set_nul, (float *)&cs.null,0}, // alias for "help"
+ {"", "help",_f0, 0, tx_print_nul, help_config, set_nul, (float *)&cs.null,0}, // prints config help screen
+ {"", "h", _f0, 0, tx_print_nul, help_config, set_nul, (float *)&cs.null,0}, // alias for "help"
#endif
// Motor parameters
{"g59","g59b",_fipc, 3, cm_print_cofs, get_flt, set_flu,(float *)&cm.offset[G59][AXIS_B], G59_B_OFFSET},
{"g59","g59c",_fipc, 3, cm_print_cofs, get_flt, set_flu,(float *)&cm.offset[G59][AXIS_C], G59_C_OFFSET},
- {"g92","g92x",_fi, 3, cm_print_cofs, get_flt, set_nul,(float *)&cm.gmx.origin_offset[AXIS_X], 0},// G92 handled differently
+ {"g92","g92x",_fi, 3, cm_print_cofs, get_flt, set_nul,(float *)&cm.gmx.origin_offset[AXIS_X], 0}, // G92 handled differently
{"g92","g92y",_fi, 3, cm_print_cofs, get_flt, set_nul,(float *)&cm.gmx.origin_offset[AXIS_Y], 0},
{"g92","g92z",_fi, 3, cm_print_cofs, get_flt, set_nul,(float *)&cm.gmx.origin_offset[AXIS_Z], 0},
{"g92","g92a",_fi, 3, cm_print_cofs, get_flt, set_nul,(float *)&cm.gmx.origin_offset[AXIS_A], 0},
{"g92","g92c",_fi, 3, cm_print_cofs, get_flt, set_nul,(float *)&cm.gmx.origin_offset[AXIS_C], 0},
// Coordinate positions (G28, G30)
- {"g28","g28x",_fi, 3, cm_print_cpos, get_flt, set_nul,(float *)&cm.gmx.g28_position[AXIS_X], 0},// g28 handled differently
+ {"g28","g28x",_fi, 3, cm_print_cpos, get_flt, set_nul,(float *)&cm.gmx.g28_position[AXIS_X], 0}, // g28 handled differently
{"g28","g28y",_fi, 3, cm_print_cpos, get_flt, set_nul,(float *)&cm.gmx.g28_position[AXIS_Y], 0},
{"g28","g28z",_fi, 3, cm_print_cpos, get_flt, set_nul,(float *)&cm.gmx.g28_position[AXIS_Z], 0},
{"g28","g28a",_fi, 3, cm_print_cpos, get_flt, set_nul,(float *)&cm.gmx.g28_position[AXIS_A], 0},
{"g28","g28b",_fi, 3, cm_print_cpos, get_flt, set_nul,(float *)&cm.gmx.g28_position[AXIS_B], 0},
{"g28","g28c",_fi, 3, cm_print_cpos, get_flt, set_nul,(float *)&cm.gmx.g28_position[AXIS_C], 0},
- {"g30","g30x",_fi, 3, cm_print_cpos, get_flt, set_nul,(float *)&cm.gmx.g30_position[AXIS_X], 0},// g30 handled differently
+ {"g30","g30x",_fi, 3, cm_print_cpos, get_flt, set_nul,(float *)&cm.gmx.g30_position[AXIS_X], 0}, // g30 handled differently
{"g30","g30y",_fi, 3, cm_print_cpos, get_flt, set_nul,(float *)&cm.gmx.g30_position[AXIS_Y], 0},
{"g30","g30z",_fi, 3, cm_print_cpos, get_flt, set_nul,(float *)&cm.gmx.g30_position[AXIS_Z], 0},
{"g30","g30a",_fi, 3, cm_print_cpos, get_flt, set_nul,(float *)&cm.gmx.g30_position[AXIS_A], 0},
// Diagnostic parameters
#ifdef __DIAGNOSTIC_PARAMETERS
- {"_te","_tex",_f0, 2, tx_print_flt, get_flt, set_nul,(float *)&mr.target[AXIS_X], 0}, // X target endpoint
+ {"_te","_tex",_f0, 2, tx_print_flt, get_flt, set_nul,(float *)&mr.target[AXIS_X], 0}, // X target endpoint
{"_te","_tey",_f0, 2, tx_print_flt, get_flt, set_nul,(float *)&mr.target[AXIS_Y], 0},
{"_te","_tez",_f0, 2, tx_print_flt, get_flt, set_nul,(float *)&mr.target[AXIS_Z], 0},
{"_te","_tea",_f0, 2, tx_print_flt, get_flt, set_nul,(float *)&mr.target[AXIS_A], 0},
{"_te","_teb",_f0, 2, tx_print_flt, get_flt, set_nul,(float *)&mr.target[AXIS_B], 0},
{"_te","_tec",_f0, 2, tx_print_flt, get_flt, set_nul,(float *)&mr.target[AXIS_C], 0},
- {"_tr","_trx",_f0, 2, tx_print_flt, get_flt, set_nul,(float *)&mr.gm.target[AXIS_X], 0}, // X target runtime
+ {"_tr","_trx",_f0, 2, tx_print_flt, get_flt, set_nul,(float *)&mr.gm.target[AXIS_X], 0}, // X target runtime
{"_tr","_try",_f0, 2, tx_print_flt, get_flt, set_nul,(float *)&mr.gm.target[AXIS_Y], 0},
{"_tr","_trz",_f0, 2, tx_print_flt, get_flt, set_nul,(float *)&mr.gm.target[AXIS_Z], 0},
{"_tr","_tra",_f0, 2, tx_print_flt, get_flt, set_nul,(float *)&mr.gm.target[AXIS_A], 0},
{"","jog",_f0, 0, tx_print_nul, get_grp, set_grp,(float *)&cs.null,0}, // axis jogging state group
{"","jid",_f0, 0, tx_print_nul, get_grp, set_grp,(float *)&cs.null,0}, // job ID group
- {"","uda", _f0, 0, tx_print_nul, get_grp, set_grp,(float *)&cs.null,0}, // user data group
- {"","udb", _f0, 0, tx_print_nul, get_grp, set_grp,(float *)&cs.null,0}, // user data group
- {"","udc", _f0, 0, tx_print_nul, get_grp, set_grp,(float *)&cs.null,0}, // user data group
- {"","udd", _f0, 0, tx_print_nul, get_grp, set_grp,(float *)&cs.null,0}, // user data group
+ {"","uda", _f0, 0, tx_print_nul, get_grp, set_grp,(float *)&cs.null,0}, // user data group
+ {"","udb", _f0, 0, tx_print_nul, get_grp, set_grp,(float *)&cs.null,0}, // user data group
+ {"","udc", _f0, 0, tx_print_nul, get_grp, set_grp,(float *)&cs.null,0}, // user data group
+ {"","udd", _f0, 0, tx_print_nul, get_grp, set_grp,(float *)&cs.null,0}, // user data group
#ifdef __DIAGNOSTIC_PARAMETERS
{"","_te",_f0, 0, tx_print_nul, get_grp, set_grp,(float *)&cs.null,0}, // target axis endpoint group
{"", "$", _f0, 0, tx_print_nul, _do_all, set_nul,(float *)&cs.null,0}
};
-/***** Make sure these defines line up with any changes in the above table *****/
-#define NV_COUNT_UBER_GROUPS 4 // count of uber-groups, above
+// Make sure these defines line up with any changes in the above table
+#define NV_COUNT_UBER_GROUPS 4 // count of uber-groups, above
#define STANDARD_GROUPS 33 // count of standard groups, excluding diagnostic parameter groups
#if (MOTORS >= 5)
index_t nv_index_max() {return NV_INDEX_MAX;}
uint8_t nv_index_is_single(index_t index) {return (index <= NV_INDEX_END_SINGLES ? true : false);}
-uint8_t nv_index_is_group(index_t index) {return ((index >= NV_INDEX_START_GROUPS && (index < NV_INDEX_START_UBER_GROUPS)) ? true : false);}
+
+uint8_t nv_index_is_group(index_t index) {
+ return ((index >= NV_INDEX_START_GROUPS && (index < NV_INDEX_START_UBER_GROUPS)) ? true : false);
+}
+
uint8_t nv_index_lt_groups(index_t index) {return (index <= NV_INDEX_START_GROUPS ? true : false);}
-/***** APPLICATION SPECIFIC CONFIGS AND EXTENSIONS TO GENERIC FUNCTIONS *****/
/*
- * set_flu() - set floating point number with G20/G21 units conversion
+ * Det floating point number with G20/G21 units conversion
*
* The number 'setted' will have been delivered in external units (inches or mm).
* It is written to the target memory location in internal canonical units (mm).
* The original nv->value is also changed so persistence works correctly.
* Displays should convert back from internal canonical form to external form.
*/
-
stat_t set_flu(nvObj_t *nv) {
if (cm_get_units_mode(MODEL) == INCHES) // if in inches...
nv->value *= MM_PER_INCH; // convert to canonical millimeter units
return STAT_OK;
}
-/*
- * preprocess_float() - pre-process floating point number for units display
- */
+/// Pre-process floating point number for units display
void preprocess_float(nvObj_t *nv) {
if (isnan((double)nv->value) || isinf((double)nv->value)) return; // illegal float values
/**** TinyG UberGroup Operations ****************************************************
* Uber groups are groups of groups organized for convenience:
- * - motors - group of all motor groups
- * - axes - group of all axis groups
+ * - motors - group of all motor groups
+ * - axes - group of all axis groups
* - offsets - group of all offsets and stored positions
* - all - group of all groups
*
* _do_group_list() - get and print all groups in the list (iteration)
* _do_motors() - get and print motor uber group 1-N
- * _do_axes() - get and print axis uber group XYZABC
- * _do_offsets() - get and print offset uber group G54-G59, G28, G30, G92
- * _do_all() - get and print all groups uber group
+ * _do_axes() - get and print axis uber group XYZABC
+ * _do_offsets() - get and print offset uber group G54-G59, G28, G30, G92
+ * _do_all() - get and print all groups uber group
*/
static stat_t _do_group_list(nvObj_t *nv, char list[][TOKEN_LEN + 1]) { // helper to print multiple groups in a list
for (uint8_t i = 0; i < NV_MAX_OBJECTS; i++) {
}
-static stat_t _do_all(nvObj_t *nv) { // print all parameters
- strcpy(nv->token,"sys"); // print system group
+static stat_t _do_all(nvObj_t *nv) { // print all parameters
+ strcpy(nv->token,"sys"); // print system group
get_grp(nv);
nv_print_list(STAT_OK, TEXT_MULTILINE_FORMATTED, JSON_RESPONSE_FORMAT);
_do_motors(nv); // print all motor groups
- _do_axes(nv); // print all axis groups
+ _do_axes(nv); // print all axis groups
strcpy(nv->token,"p1"); // print PWM group
get_grp(nv);
}
-static stat_t set_ec(nvObj_t *nv) { // expand CR to CRLF on TX
+static stat_t set_ec(nvObj_t *nv) { // expand CR to CRLF on TX
if (nv->value > true) return STAT_INPUT_VALUE_RANGE_ERROR;
cfg.enable_cr = (uint8_t)nv->value;
return _set_comm_helper(nv, USART_CRLF);
}
-static stat_t set_ee(nvObj_t *nv) { // enable character echo
+static stat_t set_ee(nvObj_t *nv) { // enable character echo
if (nv->value > true) return STAT_INPUT_VALUE_RANGE_ERROR;
cfg.enable_echo = (uint8_t)nv->value;
return _set_comm_helper(nv, USART_ECHO);
}
-/***********************************************************************************
- * TEXT MODE SUPPORT
- * Functions to print variables from the cfgArray table
- ***********************************************************************************/
-
#ifdef __TEXT_MODE
static const char fmt_ec[] PROGMEM = "[ec] expand LF to CRLF on TX%6d [0=off,1=on]\n";
static const char fmt_ee[] PROGMEM = "[ee] enable echo%18d [0=off,1=on]\n";
void cfg_print_ex(nvObj_t *nv) {text_print_ui8(nv, fmt_ex);}
void cfg_print_baud(nvObj_t *nv) {text_print_ui8(nv, fmt_baud);}
void cfg_print_rx(nvObj_t *nv) {text_print_ui8(nv, fmt_rx);}
-
#endif // __TEXT_MODE
#ifndef CONFIG_APP_H_ONCE
#define CONFIG_APP_H_ONCE
-/***********************************************************************************
- **** APPLICATION_SPECIFIC DEFINITIONS AND SETTINGS ********************************
- ***********************************************************************************/
-
-enum nvType { // classification of commands
- NV_TYPE_0 = 0,
- NV_TYPE_CONFIG, // configuration commands
- NV_TYPE_GCODE, // gcode
- NV_TYPE_REPORT, // SR, QR and any other report
- NV_TYPE_MESSAGE, // nv object carries a message
- NV_TYPE_LINENUM // nv object carries a gcode line number
+enum nvType { // classification of commands
+ NV_TYPE_0 = 0,
+ NV_TYPE_CONFIG, // configuration commands
+ NV_TYPE_GCODE, // gcode
+ NV_TYPE_REPORT, // SR, QR and any other report
+ NV_TYPE_MESSAGE, // nv object carries a message
+ NV_TYPE_LINENUM // nv object carries a gcode line number
};
-/***********************************************************************************
- **** APPLICATION_SPECIFIC CONFIG STRUCTURE(S) *************************************
- ***********************************************************************************/
-typedef struct cfgParameters { // mostly communications variables at this point
- uint16_t magic_start; // magic number to test memory integrity
+typedef struct cfgParameters { // mostly communications variables
+ uint16_t magic_start; // magic number to test memory integrity
- // communications settings
- uint8_t comm_mode; // TG_TEXT_MODE or TG_JSON_MODE
- uint8_t enable_cr; // enable CR in CRFL expansion on TX
- uint8_t enable_echo; // enable text-mode echo
- uint8_t enable_flow_control; // enable XON/XOFF or RTS/CTS flow control
+ // Communications settings
+ uint8_t comm_mode; // TG_TEXT_MODE or TG_JSON_MODE
+ uint8_t enable_cr; // enable CR in CRFL expansion on TX
+ uint8_t enable_echo; // enable text-mode echo
+ uint8_t enable_flow_control; // enable XON/XOFF or RTS/CTS flow control
- uint8_t baud_rate; // see usart.h for BAUD values
- uint8_t baud_flag; // technically this belongs in the controller singleton
+ uint8_t baud_rate; // see usart.h for BAUD values
+ uint8_t baud_flag; // should be in controller singleton
- // user-defined data groups
- uint32_t user_data_a[4];
- uint32_t user_data_b[4];
- uint32_t user_data_c[4];
- uint32_t user_data_d[4];
+ // User defined data groups
+ uint32_t user_data_a[4];
+ uint32_t user_data_b[4];
+ uint32_t user_data_c[4];
+ uint32_t user_data_d[4];
- uint16_t magic_end;
+ uint16_t magic_end;
} cfgParameters_t;
extern cfgParameters_t cfg;
-/***********************************************************************************
- * CONFIGURATION AND INTERFACE FUNCTIONS
- * Functions to get and set variables from the cfgArray table
- ***********************************************************************************/
stat_t set_baud_callback();
-// job config
+
+// Job config
void job_print_job(nvObj_t *nv);
stat_t job_get(nvObj_t *nv);
stat_t job_set(nvObj_t *nv);
uint8_t job_report_callback();
-/***********************************************************************************
- * TEXT MODE SUPPORT
- * Functions to print variables from the cfgArray table
- ***********************************************************************************/
#ifdef __TEXT_MODE
-
- void cfg_print_ec(nvObj_t *nv);
- void cfg_print_ee(nvObj_t *nv);
- void cfg_print_ex(nvObj_t *nv);
- void cfg_print_baud(nvObj_t *nv);
- void cfg_print_net(nvObj_t *nv);
- void cfg_print_rx(nvObj_t *nv);
-
+void cfg_print_ec(nvObj_t *nv);
+void cfg_print_ee(nvObj_t *nv);
+void cfg_print_ex(nvObj_t *nv);
+void cfg_print_baud(nvObj_t *nv);
+void cfg_print_net(nvObj_t *nv);
+void cfg_print_rx(nvObj_t *nv);
#else
-
- #define cfg_print_ec tx_print_stub
- #define cfg_print_ee tx_print_stub
- #define cfg_print_ex tx_print_stub
- #define cfg_print_baud tx_print_stub
- #define cfg_print_net tx_print_stub
- #define cfg_print_rx tx_print_stub
-
+#define cfg_print_ec tx_print_stub
+#define cfg_print_ee tx_print_stub
+#define cfg_print_ex tx_print_stub
+#define cfg_print_baud tx_print_stub
+#define cfg_print_net tx_print_stub
+#define cfg_print_rx tx_print_stub
#endif // __TEXT_MODE
-#endif //End of include guard: CONFIG_APP_H_ONCE
+#endif // CONFIG_APP_H_ONCE
#include "util.h"
#include "usart.h"
+
controller_t cs; // controller state structure
+
static stat_t _shutdown_idler();
static stat_t _normal_idler();
static stat_t _limit_switch_handler();
static stat_t _sync_to_tx_buffer();
static stat_t _command_dispatch();
+
// prep for export to other modules:
stat_t hardware_hard_reset_handler();
stat_t hardware_bootloader_handler();
cs.fw_build = TINYG_FIRMWARE_BUILD;
cs.fw_version = TINYG_FIRMWARE_VERSION;
- cs.hw_platform = TINYG_HARDWARE_PLATFORM; // NB: HW version is set from EEPROM
+ cs.hw_platform = TINYG_HARDWARE_PLATFORM; // NB: HW version is set from EEPROM
- cs.state = CONTROLLER_STARTUP; // ready to run startup lines
+ cs.state = CONTROLLER_STARTUP; // ready to run startup lines
}
-/// controller_test_assertions() - check memory integrity of controller
+/// Check memory integrity of controller
void controller_init_assertions() {
cs.magic_start = MAGICNUM;
cs.magic_end = MAGICNUM;
/*
- * controller_run() - MAIN LOOP - top-level controller
+ * Main loop - top-level controller
*
* The order of the dispatched tasks is very important.
* Tasks are ordered by increasing dependency (blocking hierarchy).
// See hardware.h for a list of ISRs and their priorities.
// Kernel level ISR handlers, flags are set in ISRs, order is important
- DISPATCH(hw_hard_reset_handler()); // 1. handle hard reset requests
- DISPATCH(hw_bootloader_handler()); // 2. handle requests to enter bootloader
- DISPATCH(_shutdown_idler()); // 3. idle in shutdown state
- DISPATCH(_limit_switch_handler()); // 4. limit switch has been thrown
- DISPATCH(cm_feedhold_sequencing_callback()); // 5a. feedhold state machine runner
- DISPATCH(mp_plan_hold_callback()); // 5b. plan a feedhold from line runtime
- DISPATCH(_system_assertions()); // 6. system integrity assertions
+ DISPATCH(hw_hard_reset_handler()); // 1. handle hard reset requests
+ DISPATCH(hw_bootloader_handler()); // 2. handle requests to enter bootloader
+ DISPATCH(_shutdown_idler()); // 3. idle in shutdown state
+ DISPATCH(_limit_switch_handler()); // 4. limit switch has been thrown
+ DISPATCH(cm_feedhold_sequencing_callback()); // 5a. feedhold state machine runner
+ DISPATCH(mp_plan_hold_callback()); // 5b. plan a feedhold from line runtime
+ DISPATCH(_system_assertions()); // 6. system integrity assertions
// Planner hierarchy for gcode and cycles
- DISPATCH(st_motor_power_callback()); // stepper motor power sequencing
- DISPATCH(sr_status_report_callback()); // conditionally send status report
- DISPATCH(qr_queue_report_callback()); // conditionally send queue report
- DISPATCH(rx_report_callback()); // conditionally send rx report
- DISPATCH(cm_arc_callback()); // arc generation runs behind lines
- DISPATCH(cm_homing_callback()); // G28.2 continuation
- DISPATCH(cm_jogging_callback()); // jog function
- DISPATCH(cm_probe_callback()); // G38.2 continuation
- DISPATCH(cm_deferred_write_callback()); // persist G10 changes when not in machining cycle
+ DISPATCH(st_motor_power_callback()); // stepper motor power sequencing
+ DISPATCH(sr_status_report_callback()); // conditionally send status report
+ DISPATCH(qr_queue_report_callback()); // conditionally send queue report
+ DISPATCH(rx_report_callback()); // conditionally send rx report
+ DISPATCH(cm_arc_callback()); // arc generation runs behind lines
+ DISPATCH(cm_homing_callback()); // G28.2 continuation
+ DISPATCH(cm_jogging_callback()); // jog function
+ DISPATCH(cm_probe_callback()); // G38.2 continuation
+ DISPATCH(cm_deferred_write_callback()); // persist G10 changes when not in machining cycle
// Command readers and parsers
DISPATCH(_sync_to_planner()); // ensure there is at least one free buffer in planning queue
/*****************************************************************************
- * _command_dispatch() - dispatch line received from active input device
+ * Dispatch line received from active input device
*
* Reads next command line and dispatches to relevant parser or action
* Accepts commands if the move queue has room - EAGAINS if it doesn't
strncpy(cs.saved_buf, cs.bufp, SAVED_BUFFER_LEN - 1); // save input buffer for reporting
// dispatch the new text line
- switch (toupper(*cs.bufp)) { // first char
- case '!': cm_request_feedhold(); break; // include for diagnostics
+ switch (toupper(*cs.bufp)) { // first char
+ case '!': cm_request_feedhold(); break; // include for diagnostics
case '%': cm_request_queue_flush(); break;
case '~': cm_request_cycle_start(); break;
- case 0: // blank line (just a CR)
+ case 0: // blank line (just a CR)
if (cfg.comm_mode != JSON_MODE)
text_response(STAT_OK, cs.saved_buf);
break;
- case '$': case '?': case 'H': // text mode input
+ case '$': case '?': case 'H': // text mode input
cfg.comm_mode = TEXT_MODE;
text_response(text_parser(cs.bufp), cs.saved_buf);
break;
- case '{': // JSON input
+ case '{': // JSON input
cfg.comm_mode = JSON_MODE;
json_parser(cs.bufp);
break;
- default: // anything else must be Gcode
+ default: // anything else must be Gcode
if (cfg.comm_mode == JSON_MODE) { // run it as JSON...
- strncpy(cs.out_buf, cs.bufp, INPUT_BUFFER_LEN -8); // use out_buf as temp
- sprintf((char *)cs.bufp,"{\"gc\":\"%s\"}\n", (char *)cs.out_buf); // '-8' is used for JSON chars
+ strncpy(cs.out_buf, cs.bufp, INPUT_BUFFER_LEN -8); // use out_buf as temp
+ sprintf((char *)cs.bufp,"{\"gc\":\"%s\"}\n", (char *)cs.out_buf); // '-8' is used for JSON chars
json_parser(cs.bufp);
- } else text_response(gc_gcode_parser(cs.bufp), cs.saved_buf); //...or run it as text
+ } else text_response(gc_gcode_parser(cs.bufp), cs.saved_buf); //...or run it as text
}
return STAT_OK;
}
-/**** Local Utilities ********************************************************/
-/*
- * _shutdown_idler() - blink rapidly and prevent further activity from occurring
- * _normal_idler() - blink Indicator LED slowly to show everything is OK
- *
- * Shutdown idler flashes indicator LED rapidly to show everything is not OK.
- * Shutdown idler returns EAGAIN causing the control loop to never advance beyond
- * this point. It's important that the reset handler is still called so a SW reset
- * (ctrl-x) or bootloader request can be processed.
- */
-
+/// Blink rapidly and prevent further activity from occurring
+/// Shutdown idler flashes indicator LED rapidly to show everything is not OK.
+/// Shutdown idler returns EAGAIN causing the control loop to never advance beyond
+/// this point. It's important that the reset handler is still called so a SW reset
+/// (ctrl-x) or bootloader request can be processed.
static stat_t _shutdown_idler() {
if (cm_get_machine_state() != MACHINE_SHUTDOWN) return STAT_OK;
return STAT_OK;
}
-/*
- * _sync_to_tx_buffer() - return eagain if TX queue is backed up
- * _sync_to_planner() - return eagain if planner is not ready for a new command
- * _sync_to_time() - return eagain if planner is not ready for a new command
- */
+
+/// Return eagain if TX queue is backed up
static stat_t _sync_to_tx_buffer() {
if (usart_tx_full()) return STAT_EAGAIN;
}
+/// Return eagain if planner is not ready for a new command
static stat_t _sync_to_planner() {
if (mp_get_planner_buffers_available() < PLANNER_BUFFER_HEADROOM) // allow up to N planner buffers for this line
return STAT_EAGAIN;
#include "util.h"
#include "usart.h"
-/**** Allocation ****/
srSingleton_t sr;
qrSingleton_t qr;
rxSingleton_t rx;
-/**** Exception Reports ************************************************************
- * rpt_exception() - generate an exception message - always in JSON format
+
+/*
+ * Generate an exception message - always in JSON format
*
* Returns incoming status value
*
* WARNING: Do not call this function from MED or HI interrupts (LO is OK)
- * or there is a potential for deadlock in the TX buffer.
+ * or there is a potential for deadlock in the TX buffer.
*/
-stat_t rpt_exception(uint8_t status)
-{
- if (status != STAT_OK) { // makes it possible to call exception reports w/o checking status value
- if (js.json_syntax == JSON_SYNTAX_RELAXED) {
+stat_t rpt_exception(uint8_t status) {
+ if (status != STAT_OK) { // makes it possible to call exception reports w/o checking status value
+ if (js.json_syntax == JSON_SYNTAX_RELAXED)
printf_P(PSTR("{er:{fb:%0.2f,st:%d,msg:\"%s\"}}\n"),
TINYG_FIRMWARE_BUILD, status, get_status_message(status));
- } else {
- printf_P(PSTR("{\"er\":{\"fb\":%0.2f,\"st\":%d,\"msg\":\"%s\"}}\n"),
+ else printf_P(PSTR("{\"er\":{\"fb\":%0.2f,\"st\":%d,\"msg\":\"%s\"}}\n"),
TINYG_FIRMWARE_BUILD, status, get_status_message(status));
- }
}
- return status; // makes it possible to inline, e.g: return rpt_exception(status);
+
+ return status;
}
-/*
- * rpt_er() - send a bogus exception report for testing purposes (it's not real)
- */
-stat_t rpt_er(nvObj_t *nv)
-{
+
+/// Send a bogus exception report for testing purposes (it's not real)
+stat_t rpt_er(nvObj_t *nv) {
return rpt_exception(STAT_GENERIC_EXCEPTION_REPORT); // bogus exception report for testing
}
-/**** Application Messages *********************************************************
- * rpt_print_initializing_message() - initializing configs from hard-coded profile
- * rpt_print_loading_configs_message() - loading configs from EEPROM
- * rpt_print_system_ready_message() - system ready message
- *
- * These messages are always in JSON format to allow UIs to sync
- */
-//void _startup_helper(stat_t status, const char_t *msg)
-void _startup_helper(stat_t status, const char *msg)
-{
+
+// These messages are always in JSON format to allow UIs to sync
+void _startup_helper(stat_t status, const char *msg) {
#ifndef __SUPPRESS_STARTUP_MESSAGES
- js.json_footer_depth = JSON_FOOTER_DEPTH; //++++ temporary until changeover is complete
+ js.json_footer_depth = JSON_FOOTER_DEPTH;
nv_reset_nv_list();
- nv_add_object((const char_t *)"fv"); // firmware version
- nv_add_object((const char_t *)"fb"); // firmware build
- nv_add_object((const char_t *)"hp"); // hardware platform
- nv_add_object((const char_t *)"hv"); // hardware version
- nv_add_object((const char_t *)"id"); // hardware ID
- nv_add_string((const char_t *)"msg", pstr2str(msg)); // startup message
+
+ nv_add_object((const char_t *)"fv"); // firmware version
+ nv_add_object((const char_t *)"fb"); // firmware build
+ nv_add_object((const char_t *)"hp"); // hardware platform
+ nv_add_object((const char_t *)"hv"); // hardware version
+ nv_add_object((const char_t *)"id"); // hardware ID
+ nv_add_string((const char_t *)"msg", pstr2str(msg)); // startup message
+
json_print_response(status);
#endif
}
-void rpt_print_initializing_message()
-{
+
+/// Initializing configs from hard-coded profile
+void rpt_print_initializing_message() {
_startup_helper(STAT_INITIALIZING, PSTR(INIT_MESSAGE));
}
-void rpt_print_loading_configs_message()
-{
+
+/// Loading configs from EEPROM
+void rpt_print_loading_configs_message() {
_startup_helper(STAT_INITIALIZING, PSTR("Loading configs from EEPROM"));
}
-void rpt_print_system_ready_message()
-{
+
+/// System ready message
+void rpt_print_system_ready_message() {
_startup_helper(STAT_OK, PSTR("SYSTEM READY"));
if (cfg.comm_mode == TEXT_MODE)
text_response(STAT_OK, (char_t *)""); // prompt
}
+
/*****************************************************************************
* Status Reports
*
*
* Status report formats: The following formats exist for status reports:
*
- * - JSON format: Returns a JSON object as above, but with the values filled in.
+ * - JSON format: Returns a JSON object as above, but with the values filled in.
* In JSON form all values are returned as numeric values or enumerations.
* E.g. "posx" is returned as 124.523 and "unit" is returned as 0 for
* inches (G20) and 1 for mm (G21).
static stat_t _populate_unfiltered_status_report();
static uint8_t _populate_filtered_status_report();
-uint8_t _is_stat(nvObj_t *nv)
-{
- char_t tok[TOKEN_LEN+1];
+
+uint8_t _is_stat(nvObj_t *nv) {
+ char_t tok[TOKEN_LEN + 1];
GET_TOKEN_STRING(nv->value, tok);
- if (strcmp(tok, "stat") == 0) { return true;}
- return false;
+
+ return strcmp(tok, "stat") == 0;
}
-/*
- * sr_init_status_report()
- *
- * Call this function to completely re-initialize the status report
- * Sets SR list to hard-coded defaults and re-initializes SR values in NVM
- */
-void sr_init_status_report()
-{
- nvObj_t *nv = nv_reset_nv_list(); // used for status report persistence locations
+
+/// Call this function to completely re-initialize the status report
+/// Sets SR list to hard-coded defaults and re-initializes SR values in NVM
+void sr_init_status_report() {
+ nvObj_t *nv = nv_reset_nv_list(); // used for status report persistence locations
sr.status_report_requested = false;
- char_t sr_defaults[NV_STATUS_REPORT_LEN][TOKEN_LEN+1] = { STATUS_REPORT_DEFAULTS }; // see settings.h
+ char_t sr_defaults[NV_STATUS_REPORT_LEN][TOKEN_LEN+1] = {STATUS_REPORT_DEFAULTS}; // see settings.h
nv->index = nv_get_index((const char_t *)"", (const char_t *)"se00"); // set first SR persistence index
sr.stat_index = 0;
- for (uint8_t i=0; i < NV_STATUS_REPORT_LEN ; i++) {
- if (sr_defaults[i][0] == 0) break; // quit on first blank array entry
- sr.status_report_value[i] = -1234567; // pre-load values with an unlikely number
- nv->value = nv_get_index((const char_t *)"", sr_defaults[i]);// load the index for the SR element
+ for (uint8_t i = 0; i < NV_STATUS_REPORT_LEN; i++) {
+ if (sr_defaults[i][0] == 0) break; // quit on first blank array entry
+
+ sr.status_report_value[i] = -1234567; // pre-load values with an unlikely number
+ nv->value = nv_get_index((const char_t *)"", sr_defaults[i]); // load the index for the SR element
+
if (nv->value == NO_MATCH) {
- rpt_exception(STAT_BAD_STATUS_REPORT_SETTING); // trap mis-configured profile settings
+ rpt_exception(STAT_BAD_STATUS_REPORT_SETTING); // trap mis-configured profile settings
return;
}
- if (_is_stat(nv) == true)
- sr.stat_index = nv->value; // identify index for 'stat' if status is in the report
+
+ if (_is_stat(nv)) sr.stat_index = nv->value; // identify index for 'stat' if status is in the report
+
nv_set(nv);
- nv_persist(nv); // conditionally persist - automatic by nv_persist()
- nv->index++; // increment SR NVM index
+ nv_persist(nv); // conditionally persist - automatic by nv_persist()
+ nv->index++; // increment SR NVM index
}
}
+
/*
- * sr_set_status_report() - interpret an SR setup string and return current report
+ * Interpret an SR setup string and return current report
*
* Note: By the time this function is called any unrecognized tokens have been detected and
* rejected by the JSON or text parser. In other words, it should never get to here if
* there is an unrecognized token in the SR string.
*/
-stat_t sr_set_status_report(nvObj_t *nv)
-{
+stat_t sr_set_status_report(nvObj_t *nv) {
uint8_t elements = 0;
index_t status_report_list[NV_STATUS_REPORT_LEN];
memset(status_report_list, 0, sizeof(status_report_list));
- index_t sr_start = nv_get_index((const char_t *)"",(const char_t *)"se00");// set first SR persistence index
+ index_t sr_start = nv_get_index((const char_t *)"", (const char_t *)"se00"); // set first SR persistence index
- for (uint8_t i=0; i<NV_STATUS_REPORT_LEN; i++) {
+ for (uint8_t i = 0; i < NV_STATUS_REPORT_LEN; i++) {
if (((nv = nv->nx) == 0) || (nv->valuetype == TYPE_EMPTY)) break;
+
if ((nv->valuetype == TYPE_BOOL) && (fp_TRUE(nv->value))) {
status_report_list[i] = nv->index;
nv->value = nv->index; // persist the index as the value
- nv->index = sr_start + i; // index of the SR persistence location
+ nv->index = sr_start + i; // index of the SR persistence location
nv_persist(nv);
elements++;
- } else {
- return STAT_UNRECOGNIZED_NAME;
- }
+
+ } else return STAT_UNRECOGNIZED_NAME;
}
+
if (elements == 0)
return STAT_INVALID_OR_MALFORMED_COMMAND;
+
memcpy(sr.status_report_list, status_report_list, sizeof(status_report_list));
+
return _populate_unfiltered_status_report(); // return current values
}
+
/*
- * sr_request_status_report() - request a status report to run after minimum interval
- * sr_status_report_callback() - main loop callback to send a report if one is ready
+ * Request a status report to run after minimum interval
*
* Status reports can be request from a number of sources including:
* - direct request from command line in the form of ? or {"sr:""}
* Status reports are generally returned with minimal delay (from the controller callback),
* but will not be provided more frequently than the status report interval
*/
-stat_t sr_request_status_report(uint8_t request_type)
-{
- if (request_type == SR_IMMEDIATE_REQUEST) {
+stat_t sr_request_status_report(uint8_t request_type) {
+ if (request_type == SR_IMMEDIATE_REQUEST)
sr.status_report_systick = SysTickTimer_getValue();
- }
- if ((request_type == SR_TIMED_REQUEST) && (sr.status_report_requested == false)) {
+
+ if ((request_type == SR_TIMED_REQUEST) && (sr.status_report_requested == false))
sr.status_report_systick = SysTickTimer_getValue() + sr.status_report_interval;
- }
+
sr.status_report_requested = true;
+
return STAT_OK;
}
-stat_t sr_status_report_callback() // called by controller dispatcher
-{
+
+/// Main loop callback to send a report if one is ready
+stat_t sr_status_report_callback() { // called by controller dispatcher
#ifdef __SUPPRESS_STATUS_REPORTS
return STAT_NOOP;
#endif
- if (sr.status_report_verbosity == SR_OFF)
- return STAT_NOOP;
-
- if (sr.status_report_requested == false)
- return STAT_NOOP;
-
- if (SysTickTimer_getValue() < sr.status_report_systick)
- return STAT_NOOP;
+ if (sr.status_report_verbosity == SR_OFF) return STAT_NOOP;
+ if (sr.status_report_requested == false) return STAT_NOOP;
+ if (SysTickTimer_getValue() < sr.status_report_systick) return STAT_NOOP;
sr.status_report_requested = false; // disable reports until requested again
- if (sr.status_report_verbosity == SR_VERBOSE) {
+ if (sr.status_report_verbosity == SR_VERBOSE)
_populate_unfiltered_status_report();
- } else {
- if (_populate_filtered_status_report() == false) { // no new data
- return STAT_OK;
- }
- }
+ else if (_populate_filtered_status_report() == false) return STAT_OK; // no new data
+
nv_print_list(STAT_OK, TEXT_INLINE_PAIRS, JSON_OBJECT_FORMAT);
+
return STAT_OK;
}
-/*
- * sr_run_text_status_report() - generate a text mode status report in multiline format
- */
-stat_t sr_run_text_status_report()
-{
+
+/// Generate a text mode status report in multiline format
+stat_t sr_run_text_status_report() {
_populate_unfiltered_status_report();
nv_print_list(STAT_OK, TEXT_MULTILINE_FORMATTED, JSON_RESPONSE_FORMAT);
return STAT_OK;
}
-/*
- * _populate_unfiltered_status_report() - populate nvObj body with status values
- *
- * Designed to be run as a response; i.e. have a "r" header and a footer.
- */
-static stat_t _populate_unfiltered_status_report()
-{
+
+/// Populate nvObj body with status values
+/// Designed to be run as a response; i.e. have a "r" header and a footer.
+static stat_t _populate_unfiltered_status_report() {
const char_t sr_str[] = "sr";
- char_t tmp[TOKEN_LEN+1];
+ char_t tmp[TOKEN_LEN + 1];
nvObj_t *nv = nv_reset_nv_list(); // sets *nv to the start of the body
nv->valuetype = TYPE_PARENT; // setup the parent object (no length checking required)
strcpy(nv->token, sr_str);
nv->index = nv_get_index((const char_t *)"", sr_str);// set the index - may be needed by calling function
- nv = nv->nx; // no need to check for 0 as list has just been reset
+ nv = nv->nx; // no need to check for 0 as list has just been reset
- for (uint8_t i=0; i<NV_STATUS_REPORT_LEN; i++) {
- if ((nv->index = sr.status_report_list[i]) == 0) { break;}
+ for (uint8_t i = 0; i < NV_STATUS_REPORT_LEN; i++) {
+ if ((nv->index = sr.status_report_list[i]) == 0) break;
nv_get_nvObj(nv);
- strcpy(tmp, nv->group); // flatten out groups - WARNING - you cannot use strncpy here...
+ strcpy(tmp, nv->group); // flatten out groups - WARNING - you cannot use strncpy here...
strcat(tmp, nv->token);
- strcpy(nv->token, tmp); //...or here.
+ strcpy(nv->token, tmp); //...or here.
- if ((nv = nv->nx) == 0)
- return cm_hard_alarm(STAT_BUFFER_FULL_FATAL); // should never be 0 unless SR length exceeds available buffer array
+ if (!(nv = nv->nx))
+ return cm_hard_alarm(STAT_BUFFER_FULL_FATAL); // should never be 0 unless SR length exceeds available buffer array
}
+
return STAT_OK;
}
+
/*
- * _populate_filtered_status_report() - populate nvObj body with status values
+ * Populate nvObj body with status values
*
* Designed to be displayed as a JSON object; i;e; no footer or header
* Returns 'true' if the report has new data, 'false' if there is nothing to report.
* NOTE: Room for improvement - look up the SR index initially and cache it, use the
* cached value for all remaining reports.
*/
-static uint8_t _populate_filtered_status_report()
-{
+static uint8_t _populate_filtered_status_report() {
const char_t sr_str[] = "sr";
uint8_t has_data = false;
- char_t tmp[TOKEN_LEN+1];
+ char_t tmp[TOKEN_LEN + 1];
nvObj_t *nv = nv_reset_nv_list(); // sets nv to the start of the body
nv->valuetype = TYPE_PARENT; // setup the parent object (no need to length check the copy)
strcpy(nv->token, sr_str);
- // nv->index = nv_get_index((const char_t *)"", sr_str);// OMITTED - set the index - may be needed by calling function
- nv = nv->nx; // no need to check for 0 as list has just been reset
+ nv = nv->nx; // no need to check for 0 as list has just been reset
- for (uint8_t i=0; i<NV_STATUS_REPORT_LEN; i++) {
- if ((nv->index = sr.status_report_list[i]) == 0) { break;}
+ for (uint8_t i = 0; i < NV_STATUS_REPORT_LEN; i++) {
+ if ((nv->index = sr.status_report_list[i]) == 0) break;
nv_get_nvObj(nv);
// do not report values that have not changed...
// ...except for stat=3 (STOP), which is an exception
if (fp_EQ(nv->value, sr.status_report_value[i])) {
- // if (nv->index != sr.stat_index) {
- // if (fp_EQ(nv->value, COMBINED_PROGRAM_STOP)) {
nv->valuetype = TYPE_EMPTY;
continue;
- // }
- // }
- // report anything that has changed
+
} else {
+ // report anything that has changed
strcpy(tmp, nv->group); // flatten out groups - WARNING - you cannot use strncpy here...
strcat(tmp, nv->token);
strcpy(nv->token, tmp); //...or here.
sr.status_report_value[i] = nv->value;
- if ((nv = nv->nx) == 0) return false; // should never be 0 unless SR length exceeds available buffer array
+ if (!(nv = nv->nx)) return false; // should never be 0 unless SR length exceeds available buffer array
has_data = true;
}
}
+
return has_data;
}
-/*
- * Wrappers and Setters - for calling from nvArray table
- *
- * sr_get() - run status report
- * sr_set() - set status report elements
- * sr_set_si() - set status report interval
- */
-stat_t sr_get(nvObj_t *nv) { return _populate_unfiltered_status_report();}
-stat_t sr_set(nvObj_t *nv) { return sr_set_status_report(nv);}
-stat_t sr_set_si(nvObj_t *nv)
-{
+/// Run status report
+stat_t sr_get(nvObj_t *nv) {return _populate_unfiltered_status_report();}
+
+
+/// Set status report elements
+stat_t sr_set(nvObj_t *nv) {return sr_set_status_report(nv);}
+
+
+/// Set status report interval
+stat_t sr_set_si(nvObj_t *nv) {
if (nv->value < STATUS_REPORT_MIN_MS) { nv->value = STATUS_REPORT_MIN_MS;}
sr.status_report_interval = (uint32_t)nv->value;
return STAT_OK;
}
-/*********************
- * TEXT MODE SUPPORT *
- *********************/
+
#ifdef __TEXT_MODE
static const char fmt_si[] PROGMEM = "[si] status interval%14.0f ms\n";
static const char fmt_sv[] PROGMEM = "[sv] status report verbosity%6d [0=off,1=filtered,2=verbose]\n";
-void sr_print_sr(nvObj_t *nv) { _populate_unfiltered_status_report();}
-void sr_print_si(nvObj_t *nv) { text_print_flt(nv, fmt_si);}
-void sr_print_sv(nvObj_t *nv) { text_print_ui8(nv, fmt_sv);}
+void sr_print_sr(nvObj_t *nv) {_populate_unfiltered_status_report();}
+void sr_print_si(nvObj_t *nv) {text_print_flt(nv, fmt_si);}
+void sr_print_sv(nvObj_t *nv) {text_print_ui8(nv, fmt_sv);}
#endif // __TEXT_MODE
* 2. Add qr, qi and qo (or some combination) to the status report. This will
* return queue report data when status reports are generated.
*/
-/*
- * qr_init_queue_report() - initialize or clear queue report values
- */
-void qr_init_queue_report()
-{
+
+
+/// Initialize or clear queue report values
+void qr_init_queue_report() {
qr.queue_report_requested = false;
qr.buffers_added = 0;
qr.buffers_removed = 0;
qr.init_tick = SysTickTimer_getValue();
}
+
/*
- * qr_request_queue_report() - request a queue report
+ * Request a queue report
*
- * Requests a queue report and also records the buffers added and removed
- * since the last init (usually re-initted when a report is generated).
+ * Requests a queue report and also records the buffers added and removed
+ * since the last init (usually re-initted when a report is generated).
*/
-void qr_request_queue_report(int8_t buffers)
-{
+void qr_request_queue_report(int8_t buffers) {
// get buffer depth and added/removed count
qr.buffers_available = mp_get_planner_buffers_available();
- if (buffers > 0) {
- qr.buffers_added += buffers;
- } else {
- qr.buffers_removed -= buffers;
- }
+ if (buffers > 0) qr.buffers_added += buffers;
+ else qr.buffers_removed -= buffers;
// time-throttle requests while generating arcs
qr.motion_mode = cm_get_motion_mode(ACTIVE_MODEL);
if ((qr.motion_mode == MOTION_MODE_CW_ARC) || (qr.motion_mode == MOTION_MODE_CCW_ARC)) {
uint32_t tick = SysTickTimer_getValue();
+
if (tick - qr.init_tick < MIN_ARC_QR_INTERVAL) {
qr.queue_report_requested = false;
return;
}
// either return or request a report
- if (qr.queue_report_verbosity != QR_OFF) {
+ if (qr.queue_report_verbosity != QR_OFF)
qr.queue_report_requested = true;
- }
}
-/*
- * qr_queue_report_callback() - generate a queue report if one has been requested
- */
-stat_t qr_queue_report_callback() // called by controller dispatcher
-{
+
+/// generate a queue report if one has been requested
+stat_t qr_queue_report_callback() { // called by controller dispatcher
#ifdef __SUPPRESS_QUEUE_REPORTS
return STAT_NOOP;
#endif
- if (qr.queue_report_verbosity == QR_OFF)
- return STAT_NOOP;
-
- if (qr.queue_report_requested == false)
- return STAT_NOOP;
+ if (qr.queue_report_verbosity == QR_OFF) return STAT_NOOP;
+ if (qr.queue_report_requested == false) return STAT_NOOP;
qr.queue_report_requested = false;
if (cfg.comm_mode == TEXT_MODE) {
- if (qr.queue_report_verbosity == QR_SINGLE) {
+ if (qr.queue_report_verbosity == QR_SINGLE)
fprintf(stderr, "qr:%d\n", qr.buffers_available);
- } else {
- fprintf(stderr, "qr:%d, qi:%d, qo:%d\n", qr.buffers_available,qr.buffers_added,qr.buffers_removed);
- }
+ else fprintf(stderr, "qr:%d, qi:%d, qo:%d\n", qr.buffers_available,qr.buffers_added,qr.buffers_removed);
} else if (js.json_syntax == JSON_SYNTAX_RELAXED) {
- if (qr.queue_report_verbosity == QR_SINGLE) {
+ if (qr.queue_report_verbosity == QR_SINGLE)
fprintf(stderr, "{qr:%d}\n", qr.buffers_available);
- } else {
- fprintf(stderr, "{qr:%d,qi:%d,qo:%d}\n", qr.buffers_available, qr.buffers_added,qr.buffers_removed);
- }
+ else fprintf(stderr, "{qr:%d,qi:%d,qo:%d}\n", qr.buffers_available, qr.buffers_added,qr.buffers_removed);
} else {
- if (qr.queue_report_verbosity == QR_SINGLE) {
+ if (qr.queue_report_verbosity == QR_SINGLE)
fprintf(stderr, "{\"qr\":%d}\n", qr.buffers_available);
- } else {
- fprintf(stderr, "{\"qr\":%d,\"qi\":%d,\"qo\":%d}\n", qr.buffers_available, qr.buffers_added,qr.buffers_removed);
- }
+ else fprintf(stderr, "{\"qr\":%d,\"qi\":%d,\"qo\":%d}\n", qr.buffers_available, qr.buffers_added,qr.buffers_removed);
}
+
qr_init_queue_report();
return STAT_OK;
}
-/*
- * rx_request_rx_report() - request an update on serial buffer space available
- */
+/// Request an update on serial buffer space available
void rx_request_rx_report() {
rx.rx_report_requested = true;
rx.space_available = usart_rx_space();
}
-/*
- * rx_report_callback() - send rx report if one has been requested
- */
+/// Send rx report if one has been requested
stat_t rx_report_callback() {
- if (!rx.rx_report_requested)
- return STAT_NOOP;
+ if (!rx.rx_report_requested) return STAT_NOOP;
rx.rx_report_requested = false;
}
-/*
- * Wrappers and Setters - for calling from cfgArray table
- *
- * qr_get() - run a queue report (as data)
- * qi_get() - run a queue report - buffers in
- * qo_get() - run a queue report - buffers out
- */
+/// Run a queue report (as data)
stat_t qr_get(nvObj_t *nv) {
nv->value = (float)mp_get_planner_buffers_available(); // ensure that manually requested QR count is always up to date
nv->valuetype = TYPE_INTEGER;
}
+/// Run a queue report - buffers in
stat_t qi_get(nvObj_t *nv) {
nv->value = (float)qr.buffers_added;
nv->valuetype = TYPE_INTEGER;
- qr.buffers_added = 0; // reset it
+ qr.buffers_added = 0; // reset it
return STAT_OK;
}
+/// Run a queue report - buffers out
stat_t qo_get(nvObj_t *nv) {
nv->value = (float)qr.buffers_removed;
nv->valuetype = TYPE_INTEGER;
- qr.buffers_removed = 0; // reset it
+ qr.buffers_removed = 0; // reset it
return STAT_OK;
}
-/*****************************************************************************
- * JOB ID REPORTS
- *
- * job_populate_job_report()
- * job_set_job_report()
- * job_report_callback()
- * job_get()
- * job_set()
- * job_print_job()
- */
+// Job ID reports
stat_t job_populate_job_report() {
const char_t job_str[] = "job";
char_t tmp[TOKEN_LEN+1];
nv->valuetype = TYPE_PARENT; // setup the parent object
strcpy(nv->token, job_str);
- //nv->index = nv_get_index((const char_t *)"", job_str);// set the index - may be needed by calling function
- nv = nv->nx; // no need to check for 0 as list has just been reset
+ nv = nv->nx; // no need to check for 0 as list has just been reset
- index_t job_start = nv_get_index((const char_t *)"",(const char_t *)"job1");// set first job persistence index
- for (uint8_t i=0; i<4; i++) {
+ index_t job_start = nv_get_index((const char_t *)"",(const char_t *)"job1"); // set first job persistence index
+ for (uint8_t i = 0; i < 4; i++) {
nv->index = job_start + i;
nv_get_nvObj(nv);
strcat(tmp, nv->token);
strcpy(nv->token, tmp);
- if ((nv = nv->nx) == 0)
- return STAT_OK; // should never be 0 unless SR length exceeds available buffer array
+ if ((nv = nv->nx) == 0) return STAT_OK; // should never be 0 unless SR length exceeds available buffer array
}
+
return STAT_OK;
}
-stat_t job_set_job_report(nvObj_t *nv)
-{
- index_t job_start = nv_get_index((const char_t *)"",(const char_t *)"job1");// set first job persistence index
+
+stat_t job_set_job_report(nvObj_t *nv) {
+ index_t job_start = nv_get_index((const char_t *)"",(const char_t *)"job1"); // set first job persistence index
for (uint8_t i=0; i<4; i++) {
- if (((nv = nv->nx) == 0) || (nv->valuetype == TYPE_EMPTY)) { break;}
+ if (((nv = nv->nx) == 0) || (nv->valuetype == TYPE_EMPTY)) break;
+
if (nv->valuetype == TYPE_INTEGER) {
cs.job_id[i] = nv->value;
nv->index = job_start + i; // index of the SR persistence location
nv_persist(nv);
- } else {
- return STAT_UNSUPPORTED_TYPE;
- }
+
+ } else return STAT_UNSUPPORTED_TYPE;
}
- job_populate_job_report(); // return current values
+
+ job_populate_job_report(); // return current values
+
return STAT_OK;
}
-uint8_t job_report_callback()
-{
- if (cfg.comm_mode == TEXT_MODE) {
- // no-op, job_ids are client app state
- } else if (js.json_syntax == JSON_SYNTAX_RELAXED) {
- fprintf(stderr, "{job:[%lu,%lu,%lu,%lu]}\n", cs.job_id[0], cs.job_id[1], cs.job_id[2], cs.job_id[3] );
- } else {
- fprintf(stderr, "{\"job\":[%lu,%lu,%lu,%lu]}\n", cs.job_id[0], cs.job_id[1], cs.job_id[2], cs.job_id[3] );
- //job_clear_report();
- }
+
+uint8_t job_report_callback() {
+ if (cfg.comm_mode == TEXT_MODE) ; // no-op, job_ids are client app state
+
+ else if (js.json_syntax == JSON_SYNTAX_RELAXED)
+ fprintf(stderr, "{job:[%lu,%lu,%lu,%lu]}\n",
+ cs.job_id[0], cs.job_id[1], cs.job_id[2], cs.job_id[3]);
+
+ else fprintf(stderr, "{\"job\":[%lu,%lu,%lu,%lu]}\n",
+ cs.job_id[0], cs.job_id[1], cs.job_id[2], cs.job_id[3]);
+
return STAT_OK;
}
-stat_t job_get(nvObj_t *nv) { return job_populate_job_report();}
-stat_t job_set(nvObj_t *nv) { return job_set_job_report(nv);}
-void job_print_job(nvObj_t *nv) { job_populate_job_report();}
+stat_t job_get(nvObj_t *nv) {return job_populate_job_report();}
+stat_t job_set(nvObj_t *nv) {return job_set_job_report(nv);}
+void job_print_job(nvObj_t *nv) {job_populate_job_report();}
+
-/*********************
- * TEXT MODE SUPPORT *
- *********************/
#ifdef __TEXT_MODE
static const char fmt_qr[] PROGMEM = "qr:%d\n";
static const char fmt_qo[] PROGMEM = "qo:%d\n";
static const char fmt_qv[] PROGMEM = "[qv] queue report verbosity%7d [0=off,1=single,2=triple]\n";
-void qr_print_qr(nvObj_t *nv) { text_print_int(nv, fmt_qr);}
-void qr_print_qi(nvObj_t *nv) { text_print_int(nv, fmt_qi);}
-void qr_print_qo(nvObj_t *nv) { text_print_int(nv, fmt_qo);}
-void qr_print_qv(nvObj_t *nv) { text_print_ui8(nv, fmt_qv);}
+void qr_print_qr(nvObj_t *nv) {text_print_int(nv, fmt_qr);}
+void qr_print_qi(nvObj_t *nv) {text_print_int(nv, fmt_qi);}
+void qr_print_qo(nvObj_t *nv) {text_print_int(nv, fmt_qo);}
+void qr_print_qv(nvObj_t *nv) {text_print_ui8(nv, fmt_qv);}
#endif // __TEXT_MODE
#ifndef REPORT_H_ONCE
#define REPORT_H_ONCE
-/**** Configs, Definitions and Structures ****/
-//
// Notes:
-// - The NV_STATUS_REPORT_LEN define is in config.h
-// - The status report defaults can be found in settings.h
+// - The NV_STATUS_REPORT_LEN define is in config.h
+// - The status report defaults can be found in settings.h
#define MIN_ARC_QR_INTERVAL 200 // minimum interval between QRs during arc generation (in system ticks)
-enum srVerbosity { // status report enable and verbosity
- SR_OFF = 0, // no reports
- SR_FILTERED, // reports only values that have changed from the last report
- SR_VERBOSE // reports all values specified
+
+enum srVerbosity { // status report enable and verbosity
+ SR_OFF = 0, // no reports
+ SR_FILTERED, // reports only values that have changed from the last report
+ SR_VERBOSE // reports all values specified
};
+
enum cmStatusReportRequest {
- SR_TIMED_REQUEST = 0, // request a status report at next timer interval
- SR_IMMEDIATE_REQUEST // request a status report ASAP
+ SR_TIMED_REQUEST = 0, // request a status report at next timer interval
+ SR_IMMEDIATE_REQUEST // request a status report ASAP
};
-enum qrVerbosity { // planner queue enable and verbosity
- QR_OFF = 0, // no response is provided
- QR_SINGLE, // queue depth reported
- QR_TRIPLE // queue depth reported for buffers, buffers added, buffered removed
+
+enum qrVerbosity { // planner queue enable and verbosity
+ QR_OFF = 0, // no response is provided
+ QR_SINGLE, // queue depth reported
+ QR_TRIPLE // queue depth reported for buffers, buffers added, buffered removed
};
-typedef struct srSingleton {
- /*** config values (PUBLIC) ***/
+typedef struct srSingleton {
+ // Public
uint8_t status_report_verbosity;
- uint32_t status_report_interval; // in milliseconds
-
- /*** runtime values (PRIVATE) ***/
- uint8_t status_report_requested; // flag that SR has been requested
- uint32_t status_report_systick; // SysTick value for next status report
- index_t stat_index; // table index value for stat - determined during initialization
- index_t status_report_list[NV_STATUS_REPORT_LEN]; // status report elements to report
- float status_report_value[NV_STATUS_REPORT_LEN]; // previous values for filtered reporting
-
+ uint32_t status_report_interval; // in milliseconds
+
+ // Private
+ uint8_t status_report_requested; // flag that SR has been requested
+ uint32_t status_report_systick; // SysTick value for next status report
+ index_t stat_index; // table index value for stat - determined during initialization
+ index_t status_report_list[NV_STATUS_REPORT_LEN]; // status report elements to report
+ float status_report_value[NV_STATUS_REPORT_LEN]; // previous values for filtered reporting
} srSingleton_t;
-typedef struct qrSingleton { // data for queue reports
- /*** config values (PUBLIC) ***/
- uint8_t queue_report_verbosity; // queue reports enabled and verbosity level
-
- /*** runtime values (PRIVATE) ***/
- uint8_t queue_report_requested; // set to true to request a report
- uint8_t buffers_available; // stored buffer depth passed to by callback
- uint8_t prev_available; // buffers available at last count
- uint16_t buffers_added; // buffers added since last count
- uint16_t buffers_removed; // buffers removed since last report
- uint8_t motion_mode; // used to detect arc movement
- uint32_t init_tick; // time when values were last initialized or cleared
+typedef struct qrSingleton { // data for queue reports
+ // Public
+ uint8_t queue_report_verbosity; // queue reports enabled and verbosity level
+ // Private
+ uint8_t queue_report_requested; // set to true to request a report
+ uint8_t buffers_available; // stored buffer depth passed to by callback
+ uint8_t prev_available; // buffers available at last count
+ uint16_t buffers_added; // buffers added since last count
+ uint16_t buffers_removed; // buffers removed since last report
+ uint8_t motion_mode; // used to detect arc movement
+ uint32_t init_tick; // time when values were last initialized or cleared
} qrSingleton_t;
+
typedef struct rxSingleton {
uint8_t rx_report_requested;
- uint16_t space_available; // space available in rx buffer at time of request
+ uint16_t space_available; // space available in rx buffer at time of request
} rxSingleton_t;
-/**** Externs - See report.c for allocation ****/
extern srSingleton_t sr;
extern qrSingleton_t qr;
extern rxSingleton_t rx;
-/**** Function Prototypes ****/
void rpt_print_message(char *msg);
stat_t rpt_exception(uint8_t status);
#endif // __TEXT_MODE
-#endif // End of include guard: REPORT_H_ONCE
+#endif // REPORT_H_ONCE
#define STATUS_REPORT_VERBOSITY SR_FILTERED // one of: SR_OFF, SR_FILTERED, SR_VERBOSE=
#define STATUS_REPORT_MIN_MS 100 // milliseconds - enforces a viable minimum
#define STATUS_REPORT_INTERVAL_MS 500 // milliseconds - set $SV=0 to disable
-#define STATUS_REPORT_DEFAULTS "posx","posy","posz","posa","feed","vel","unit","coor","dist","frmo","stat"
+#define STATUS_REPORT_DEFAULTS "posx","posy","posz","posa","feed","vel","unit","coor","dist","frmo","stat","mst1","mfl1"
#define QUEUE_REPORT_VERBOSITY QR_OFF // one of: QR_OFF, QR_SINGLE, QR_TRIPLE
#define M1_MOTOR_MAP AXIS_X // 1ma
#define M1_STEP_ANGLE 1.8 // 1sa
#define M1_TRAVEL_PER_REV 1.25 // 1tr
-#define M1_MICROSTEPS 256 // 1mi 1,2,4,8
+#define M1_MICROSTEPS 8 // 1mi 1,2,4,8
#define M1_POLARITY 0 // 1po 0=normal, 1=reversed
#define M1_POWER_MODE MOTOR_POWER_MODE // 1pm standard
#define M1_POWER_LEVEL MOTOR_POWER_LEVEL // 1mp
*/
ISR(TIMER_DDA_ISR_vect) {
if ((st_run.mot[MOTOR_1].substep_accumulator += st_run.mot[MOTOR_1].substep_increment) > 0) {
- PORT_MOTOR_1_VPORT.OUT |= STEP_BIT_bm; // turn step bit on
+ PORT_MOTOR_1_VPORT.OUT ^= STEP_BIT_bm; // turn step bit on
st_run.mot[MOTOR_1].substep_accumulator -= st_run.dda_ticks_X_substeps;
INCREMENT_ENCODER(MOTOR_1);
}
INCREMENT_ENCODER(MOTOR_4);
}
- // pulse stretching for using external drivers.- turn step bits off
- PORT_MOTOR_1_VPORT.OUT &= ~STEP_BIT_bm; // ~ 5 uSec pulse width
+ // Turn step bits off - pulse stretching for using external drivers.
+ //PORT_MOTOR_1_VPORT.OUT &= ~STEP_BIT_bm; // ~ 5 uSec pulse width
PORT_MOTOR_2_VPORT.OUT &= ~STEP_BIT_bm; // ~ 4 uSec
PORT_MOTOR_3_VPORT.OUT &= ~STEP_BIT_bm; // ~ 3 uSec
PORT_MOTOR_4_VPORT.OUT &= ~STEP_BIT_bm; // ~ 2 uSec
\******************************************************************************/
+#include "tinyg.h"
+#include "config.h"
#include "tmc2660.h"
#include <avr/io.h>
uint8_t reset;
uint8_t reg;
- uint16_t mstep;
+ int16_t mstep;
uint8_t status;
uint32_t regs[5];
} tmc2660_driver_t;
case TMC2660_STATE_MONITOR:
// Read response
- drv->mstep = (spi_in >> 14) & 0x3ff;
+ drv->mstep = (int16_t)((spi_in >> 14) & 0x1ff);
+ if (spi_in & (1UL << 19)) drv->mstep = -drv->mstep;
drv->status = spi_in >> 4;
if (drv->reset) {
drivers[i].state = TMC2660_STATE_CONFIG;
drivers[i].reg = 0;
- drivers[i].regs[TMC2660_DRVCTRL] = TMC2660_DRVCTRL_MRES_256;
- //drivers[i].regs[TMC2660_CHOPCONF] = TMC2660_CHOPCONF_TBL_36 | TMC2660_CHOPCONF_HEND(0) | TMC2660_CHOPCONF_HSTART(4) |
+ drivers[i].regs[TMC2660_DRVCTRL] = TMC2660_DRVCTRL_MRES_8;
+ //drivers[i].regs[TMC2660_CHOPCONF] = TMC2660_CHOPCONF_TBL_36 |
+ // TMC2660_CHOPCONF_HEND(0) | TMC2660_CHOPCONF_HSTART(4) |
// TMC2660_CHOPCONF_TOFF(4);
- drivers[i].regs[TMC2660_CHOPCONF] = TMC2660_CHOPCONF_TBL_36 | TMC2660_CHOPCONF_CHM | TMC2660_CHOPCONF_HEND(7) |
+ drivers[i].regs[TMC2660_CHOPCONF] = TMC2660_CHOPCONF_TBL_36 |
+ TMC2660_CHOPCONF_CHM | TMC2660_CHOPCONF_HEND(7) |
TMC2660_CHOPCONF_HSTART(6) | TMC2660_CHOPCONF_TOFF(7);
- drivers[i].regs[TMC2660_SMARTEN] = TMC2660_SMARTEN_SEIMIN | TMC2660_SMARTEN_MAX(2) | TMC2660_SMARTEN_MIN(2);
- drivers[i].regs[TMC2660_SGCSCONF] = TMC2660_SGCSCONF_SFILT | TMC2660_SGCSCONF_CS_NONE;
+ //drivers[i].regs[TMC2660_SMARTEN] = TMC2660_SMARTEN_SEIMIN |
+ // TMC2660_SMARTEN_MAX(2) | TMC2660_SMARTEN_MIN(2);
+ drivers[i].regs[TMC2660_SGCSCONF] = TMC2660_SGCSCONF_SFILT |
+ TMC2660_SGCSCONF_THRESH(63) | TMC2660_SGCSCONF_CS_NONE;
drivers[i].regs[TMC2660_DRVCONF] = TMC2660_DRVCONF_RDSEL_MSTEP;
}
// Setup pins
+ // Why is it necessary to set the SS pin for master mode to work?
TMC2660_SPI_PORT.OUTSET = 1 << TMC2660_SPI_SS_PIN; // High
- TMC2660_SPI_PORT.DIRSET = 1 << TMC2660_SPI_SS_PIN; // Output (Why is it necessary to set the SS pin?)
+ TMC2660_SPI_PORT.DIRSET = 1 << TMC2660_SPI_SS_PIN; // Output
TMC2660_SPI_PORT.OUTSET = 1 << TMC2660_SPI_SCK_PIN; // High
TMC2660_SPI_PORT.DIRSET = 1 << TMC2660_SPI_SCK_PIN; // Output
TMC2660_SPI_PORT.DIRCLR = 1 << TMC2660_SPI_MISO_PIN; // Input
return 1;
}
+
+
+static void tmc2660_get_status_flags(uint8_t status, char buf[35]) {
+ buf[0] = 0;
+
+ if (TMC2660_DRVSTATUS_STST & status) strcat(buf, "stst,");
+ if (TMC2660_DRVSTATUS_OLB & status) strcat(buf, "olb,");
+ if (TMC2660_DRVSTATUS_OLA & status) strcat(buf, "ola,");
+ if (TMC2660_DRVSTATUS_S2GB & status) strcat(buf, "s2gb,");
+ if (TMC2660_DRVSTATUS_S2GA & status) strcat(buf, "s2ga,");
+ if (TMC2660_DRVSTATUS_OTPW & status) strcat(buf, "otpw,");
+ if (TMC2660_DRVSTATUS_OT & status) strcat(buf, "ot,");
+ if (TMC2660_DRVSTATUS_SG & status) strcat(buf, "sg,");
+
+ if (buf[0] != 0) buf[strlen(buf) - 1] = 0; // Remove last comma
+}
+
+
+static const char mst_fmt[] PROGMEM = "Motor %i step: %i\n";
+static const char mfl_fmt[] PROGMEM = "Motor %i flags: %s\n";
+
+
+void tmc2660_print_motor_step(nvObj_t *nv) {
+ int driver = nv->token[3] - '1';
+ fprintf_P(stderr, mst_fmt, driver + 1, drivers[driver].mstep);
+}
+
+
+void tmc2660_print_motor_flags(nvObj_t *nv) {
+ int driver = nv->token[3] - '1';
+
+ char buf[35];
+ tmc2660_get_status_flags(drivers[driver].status, buf);
+
+ fprintf_P(stderr, mfl_fmt, driver + 1, buf);
+}
+
+
+stat_t tmc2660_get_motor_step(nvObj_t *nv) {
+ int driver = nv->token[3] - '1';
+
+ nv->value = drivers[driver].mstep;
+ nv->valuetype = TYPE_INTEGER;
+
+ return STAT_OK;
+}
+
+
+stat_t tmc2660_get_motor_flags(nvObj_t *nv) {
+ int driver = nv->token[3] - '1';
+ char buf[35];
+
+ tmc2660_get_status_flags(drivers[driver].status, buf);
+ nv_copy_string(nv, buf);
+ nv->valuetype = TYPE_STRING;
+
+ return STAT_OK;
+}
#define TMC2660_SPI_SSB_PORT PORTB
#define TMC2660_SPI_SSB_PIN 3
-#define TMC2660_NUM_DRIVERS 4
+#define TMC2660_NUM_DRIVERS 3
#define TMC2660_TIMER TCC1
int tmc2660_ready(int driver);
int tmc2660_all_ready();
+void tmc2660_print_motor_step(nvObj_t *nv);
+void tmc2660_print_motor_flags(nvObj_t *nv);
+stat_t tmc2660_get_motor_step(nvObj_t *nv);
+stat_t tmc2660_get_motor_flags(nvObj_t *nv);
+
#define TMC2660_DRVCTRL 0
#define TMC2660_DRVCTRL_ADDR (0UL << 18)
#define TMC2660_DRVCTRL_PHA (1UL << 17)