From 860f9894862bd2a0b307cad20695bc18f025db0d Mon Sep 17 00:00:00 2001 From: Joseph Coffland Date: Mon, 4 Jan 2016 13:08:22 -0800 Subject: [PATCH] Motor status reporting --- Makefile | 5 +- src/config.h | 233 +++++++++-------- src/config_app.c | 164 ++++++------ src/config_app.h | 92 +++---- src/controller.c | 87 +++---- src/report.c | 447 ++++++++++++++------------------ src/report.h | 80 +++--- src/settings.h | 2 +- src/settings/settings_default.h | 2 +- src/stepper.c | 6 +- src/tmc2660.c | 82 +++++- src/tmc2660.h | 7 +- 12 files changed, 609 insertions(+), 598 deletions(-) diff --git a/Makefile b/Makefile index 1db20ee..60c8120 100755 --- a/Makefile +++ b/Makefile @@ -66,6 +66,9 @@ size: $(TARGET) avr-size -C --mcu=$(MCU) $(TARGET) # Program +reset: + avrdude $(AVRDUDE_OPTS) + erase: avrdude $(AVRDUDE_OPTS) -e @@ -89,7 +92,7 @@ clean: tidy 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/*) diff --git a/src/config.h b/src/config.h index 078f5a0..a51936c 100644 --- a/src/config.h +++ b/src/config.h @@ -28,9 +28,7 @@ #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 *** * @@ -44,6 +42,7 @@ * 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 @@ -72,9 +71,9 @@ * 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 * @@ -84,6 +83,7 @@ * - 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: @@ -104,7 +104,7 @@ /**** 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. * @@ -119,13 +119,14 @@ * 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. @@ -142,6 +143,7 @@ * - 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 @@ -150,6 +152,7 @@ * 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 @@ -158,6 +161,7 @@ * (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 @@ -166,60 +170,61 @@ #include -// 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) @@ -231,103 +236,108 @@ enum valueType { // value typing for config and JSON #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); @@ -341,16 +351,17 @@ nvObj_t *nv_add_string(const char_t *token, const char_t *string); 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 diff --git a/src/config_app.c b/src/config_app.c index 87a110f..3c4e8ee 100644 --- a/src/config_app.c +++ b/src/config_app.c @@ -43,21 +43,20 @@ #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 @@ -90,31 +89,40 @@ static stat_t get_rx(nvObj_t *nv); // get bytes in RX buffer * 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 @@ -137,13 +145,13 @@ const cfgItem_t cfgArray[] PROGMEM = { {"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}, @@ -158,7 +166,7 @@ const cfgItem_t cfgArray[] PROGMEM = { {"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}, @@ -170,23 +178,23 @@ const cfgItem_t cfgArray[] PROGMEM = { #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 @@ -371,7 +379,7 @@ const cfgItem_t cfgArray[] PROGMEM = { {"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}, @@ -379,14 +387,14 @@ const cfgItem_t cfgArray[] PROGMEM = { {"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}, @@ -456,14 +464,14 @@ const cfgItem_t cfgArray[] PROGMEM = { // 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}, @@ -598,10 +606,10 @@ const cfgItem_t cfgArray[] PROGMEM = { {"","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 @@ -622,9 +630,9 @@ const cfgItem_t cfgArray[] PROGMEM = { {"", "$", _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) @@ -655,20 +663,22 @@ const cfgItem_t cfgArray[] PROGMEM = { 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 @@ -680,10 +690,8 @@ stat_t set_flu(nvObj_t *nv) { 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 @@ -695,16 +703,16 @@ void preprocess_float(nvObj_t *nv) { /**** 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++) { @@ -754,13 +762,13 @@ static stat_t _do_offsets(nvObj_t *nv) { // print offset parameters for G54-G5 } -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); @@ -783,14 +791,14 @@ static stat_t _set_comm_helper(nvObj_t *nv, int cmd) { } -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); @@ -856,11 +864,6 @@ stat_t set_baud_callback() { } -/*********************************************************************************** - * 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"; @@ -873,5 +876,4 @@ void cfg_print_ee(nvObj_t *nv) {text_print_ui8(nv, fmt_ee);} 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 diff --git a/src/config_app.h b/src/config_app.h index 275f0b4..39ba52a 100644 --- a/src/config_app.h +++ b/src/config_app.h @@ -21,81 +21,63 @@ #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 diff --git a/src/controller.c b/src/controller.c index 33cec6f..44a2a05 100644 --- a/src/controller.c +++ b/src/controller.c @@ -46,8 +46,10 @@ #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(); @@ -56,6 +58,7 @@ static stat_t _sync_to_planner(); 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(); @@ -67,13 +70,13 @@ void controller_init() { 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; @@ -89,7 +92,7 @@ stat_t controller_test_assertions() { /* - * 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). @@ -113,24 +116,24 @@ void controller_run() { // 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 @@ -142,7 +145,7 @@ void controller_run() { /***************************************************************************** - * _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 @@ -167,50 +170,44 @@ static stat_t _command_dispatch() { 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; @@ -227,11 +224,8 @@ static stat_t _normal_idler() { 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; @@ -239,6 +233,7 @@ static stat_t _sync_to_tx_buffer() { } +/// 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; diff --git a/src/report.c b/src/report.c index bd2e842..ecd50f7 100644 --- a/src/report.c +++ b/src/report.c @@ -36,83 +36,78 @@ #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 * @@ -127,7 +122,7 @@ void rpt_print_system_ready_message() * * 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). @@ -158,80 +153,82 @@ void rpt_print_system_ready_message() 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; inx) == 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:""} @@ -241,88 +238,79 @@ stat_t sr_set_status_report(nvObj_t *nv) * 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; iindex = 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. @@ -334,72 +322,65 @@ static stat_t _populate_unfiltered_status_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; iindex = 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 @@ -422,37 +403,34 @@ void sr_print_sv(nvObj_t *nv) { text_print_ui8(nv, fmt_sv);} * 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; @@ -460,70 +438,54 @@ void qr_request_queue_report(int8_t buffers) } // 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; @@ -532,13 +494,7 @@ stat_t rx_report_callback() { } -/* - * 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; @@ -546,32 +502,25 @@ stat_t qr_get(nvObj_t *nv) { } +/// 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]; @@ -580,12 +529,11 @@ stat_t job_populate_job_report() { 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); @@ -593,50 +541,51 @@ stat_t job_populate_job_report() { 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"; @@ -644,9 +593,9 @@ static const char fmt_qi[] PROGMEM = "qi:%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 diff --git a/src/report.h b/src/report.h index da41d0d..1163a76 100644 --- a/src/report.h +++ b/src/report.h @@ -28,74 +28,72 @@ #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); @@ -148,4 +146,4 @@ void qr_print_qo(nvObj_t *nv); #endif // __TEXT_MODE -#endif // End of include guard: REPORT_H_ONCE +#endif // REPORT_H_ONCE diff --git a/src/settings.h b/src/settings.h index 717f6d6..4866a28 100644 --- a/src/settings.h +++ b/src/settings.h @@ -64,7 +64,7 @@ #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 diff --git a/src/settings/settings_default.h b/src/settings/settings_default.h index 1f6ef74..32cbd0c 100644 --- a/src/settings/settings_default.h +++ b/src/settings/settings_default.h @@ -49,7 +49,7 @@ #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 diff --git a/src/stepper.c b/src/stepper.c index 4d8ddbb..44075e9 100644 --- a/src/stepper.c +++ b/src/stepper.c @@ -278,7 +278,7 @@ stat_t st_motor_power_callback() { // called by controller */ 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); } @@ -301,8 +301,8 @@ ISR(TIMER_DDA_ISR_vect) { 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 diff --git a/src/tmc2660.c b/src/tmc2660.c index 21b8c75..278bc5f 100644 --- a/src/tmc2660.c +++ b/src/tmc2660.c @@ -29,6 +29,8 @@ \******************************************************************************/ +#include "tinyg.h" +#include "config.h" #include "tmc2660.h" #include @@ -53,7 +55,7 @@ typedef struct { uint8_t reset; uint8_t reg; - uint16_t mstep; + int16_t mstep; uint8_t status; uint32_t regs[5]; } tmc2660_driver_t; @@ -164,7 +166,8 @@ void spi_next() { 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) { @@ -213,19 +216,24 @@ void tmc2660_init() { 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 @@ -285,3 +293,61 @@ int tmc2660_all_ready() { 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; +} diff --git a/src/tmc2660.h b/src/tmc2660.h index 07212a2..ec99b80 100644 --- a/src/tmc2660.h +++ b/src/tmc2660.h @@ -51,7 +51,7 @@ #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 @@ -62,6 +62,11 @@ void tmc2660_reset(int driver); 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) -- 2.27.0