From 220936e0341761845afaae250950120b430ddbae Mon Sep 17 00:00:00 2001 From: "alden.hart" Date: Sun, 21 Apr 2013 08:16:03 -0400 Subject: [PATCH] 005.03 Added Rob's Makefile and Motate changes; Got ported code to compile --- TinyG2/Makefile | 9 +- TinyG2/canonical_machine.cpp | 18 +- TinyG2/canonical_machine.h | 10 +- TinyG2/config.cpp | 114 ++++++-- TinyG2/config_app.cpp | 22 +- TinyG2/main.cpp | 4 +- TinyG2/motate/utility/SamPins.h | 11 +- TinyG2/motate/utility/SamTimers.h | 94 ++++++- TinyG2/tinyg2.h | 450 +++++++++++++++--------------- TinyG2/util.cpp | 37 ++- 10 files changed, 460 insertions(+), 309 deletions(-) diff --git a/TinyG2/Makefile b/TinyG2/Makefile index b03d1a9e..c9fb2156 100644 --- a/TinyG2/Makefile +++ b/TinyG2/Makefile @@ -68,7 +68,7 @@ CFLAGS += -Wunreachable-code #CFLAGS += -Wmissing-noreturn #CFLAGS += -Wconversion -# Stop warnings about late-bound printf() format strings. We use these. +# Turn off printf() format strings. We use late bound FLASH and RAM format strings and this causes warnings CFLAGS += -Wno-format-nonliteral -Wno-format-security # To reduce application size use only integer printf function. @@ -89,7 +89,7 @@ CPPFLAGS += -Wredundant-decls -Winline -Wlong-long #CPPFLAGS += -Wmissing-noreturn -Wpacked #CPPFLAGS += -Wconversion -# Stop warnings about late-bound printf() format strings. We use these. +# Turn off printf() format strings. We use late bound FLASH and RAM format strings and this causes warnings CPPFLAGS += -Wno-format-nonliteral -Wno-format-security # To reduce application size use only integer printf function. @@ -305,9 +305,8 @@ $(OUTPUT_BIN)_$(1).elf: $$(OUTDIR)/core.a $$(DEVICE_OBJECTS_$(1)) $(QUIET)$(NM) "$(OUTPUT_BIN)_$(1).elf" >"$(OUTPUT_BIN)_$(1).elf.txt" @echo $(START_BOLD)"Making binary $(OUTPUT_BIN)_$(1).bin" $(END_BOLD) $(QUIET)$(OBJCOPY) -O binary "$(OUTPUT_BIN)_$(1).elf" "$(OUTPUT_BIN)_$(1).bin" -# @echo "--- SIZE INFO ---" -# $(QUIET)$(SIZE) $$^ "$(OUTPUT_BIN)_$$@" -# $(QUIET)$(SIZE) $$^ "$(OUTPUT_BIN)_$$@.elf" + @echo "--- SIZE INFO ---" + $(QUIET)$(SIZE) "$(OUTPUT_BIN)_$(1).elf" $$(ALL_CXX_OBJECTS_$(1)): $$(OUTDIR)/%.o: %.cpp | $(MK_DIRS) $(QUIET)if [[ ! -d `dirname $$@` ]]; then mkdir -p `dirname $$@`; fi diff --git a/TinyG2/canonical_machine.cpp b/TinyG2/canonical_machine.cpp index bb6c1043..32114f7a 100755 --- a/TinyG2/canonical_machine.cpp +++ b/TinyG2/canonical_machine.cpp @@ -96,9 +96,21 @@ extern "C"{ #endif -// NOTE: The canonical machine singleton "cm" would normally be declared here +/*********************************************************************************** + **** STRUCTURE ALLOCATIONS ********************************************************* + ***********************************************************************************/ +// NOTE: The canonical machine singleton "cm" would normally be declared here // but it's also used by cycles so it's in canonical_machine.h instead. +cmSingleton_t cm; // canonical machine control structure +GCodeModel_t gm; // active gcode model +GCodeInput_t gn; // gcode input values +GCodeInput_t gf; // gcode input flags + +/*********************************************************************************** + **** GENERIC STATIC FUNCTIONS AND VARIABLES *************************************** + ***********************************************************************************/ + static float _get_move_times(float *min_time); // planner queue callbacks @@ -112,6 +124,10 @@ static void _exec_program_finalize(uint8_t machine_state, float float_val); #define _to_millimeters(a) ((gm.units_mode == INCHES) ? (a * MM_PER_INCH) : a) +/*********************************************************************************** + **** CODE ************************************************************************* + ***********************************************************************************/ + /************************************************************************* * * HELPERS AND UTILITY FUNCTIONS diff --git a/TinyG2/canonical_machine.h b/TinyG2/canonical_machine.h index c72091dd..970fd336 100755 --- a/TinyG2/canonical_machine.h +++ b/TinyG2/canonical_machine.h @@ -56,7 +56,7 @@ typedef struct cmSingleton { // struct to manage cm globals and cycles uint8_t g10_persist_flag; //.G10 changed offsets - persist them uint16_t magic_end; } cmSingleton_t; -cmSingleton_t cm; +extern cmSingleton_t cm; /* GCODE MODEL - The following GCodeModel/GCodeInput structs are used: * @@ -187,10 +187,10 @@ typedef struct GCodeInput { // Gcode model inputs - meaning depends on contex float arc_offset[3]; // IJK - used by arc commands } GCodeInput_t; -// Allocation -GCodeModel_t gm; // active gcode model -GCodeInput_t gn; // gcode input values -GCodeInput_t gf; // gcode input flags +// Externs +extern GCodeModel_t gm; // active gcode model +extern GCodeInput_t gn; // gcode input values +extern GCodeInput_t gf; // gcode input flags /***************************************************************************** * diff --git a/TinyG2/config.cpp b/TinyG2/config.cpp index eeb7e56d..13f1a0d3 100755 --- a/TinyG2/config.cpp +++ b/TinyG2/config.cpp @@ -30,6 +30,7 @@ #include "json_parser.h" #include "text_parser.h" #include "controller.h" +#include "canonical_machine.h" #include "util.h" #include "xio.h" @@ -38,7 +39,7 @@ extern "C"{ #endif /*********************************************************************************** - **** STUCTURE ALLOCATIONS ********************************************************* + **** STRUCTURE ALLOCATIONS ******************************************************** ***********************************************************************************/ cmdStr_t cmdStr; @@ -128,20 +129,16 @@ static stat_t set_defa(cmdObj_t *cmd) return (STAT_OK); } -/***** Generic Internal Functions ******************************************* - * Generic gets() - * get_nul() - get nothing (returns STAT_NOOP) - * get_ui8() - get value as 8 bit uint8_t w/o unit conversion - * get_int() - get value as 32 bit integer w/o unit conversion - * get_flt() - get value as float w/o unit conversion - * - * Generic sets() - * set_nul() - set nothing (returns STAT_NOOP) - * set_ui8() - set value as 8 bit uint8_t value w/o unit conversion - * set_int() - set value as 32 bit integer w/o unit conversion - * set_flt() - set value as float w/o unit conversion +/***** Generic Internal Functions *********************************************/ + +/* Generic gets() + * get_nul() - get nothing (returns STAT_NOOP) + * get_ui8() - get value as 8 bit uint8_t w/o unit conversion + * get_int() - get value as 32 bit integer w/o unit conversion + * get_flt() - get value as float w/o unit conversion + * get_flu() - get value as double w/unit conversion + * get_format() - internal accessor for printf() format string */ -stat_t set_nul(cmdObj_t *cmd) { return (STAT_NOOP);} stat_t get_nul(cmdObj_t *cmd) { cmd->type = TYPE_NULL; @@ -154,43 +151,98 @@ stat_t get_ui8(cmdObj_t *cmd) cmd->type = TYPE_INTEGER; return (STAT_OK); } -stat_t set_ui8(cmdObj_t *cmd) -{ - *((uint8_t *)cfgArray[cmd->index].target) = cmd->value; - cmd->type = TYPE_INTEGER; - return(STAT_OK); -} + stat_t get_int(cmdObj_t *cmd) { cmd->value = (float)*((uint32_t *)cfgArray[cmd->index].target); cmd->type = TYPE_INTEGER; return (STAT_OK); } + +stat_t get_flt(cmdObj_t *cmd) +{ + cmd->value = *((float *)cfgArray[cmd->index].target); + cmd->precision = cfgArray[cmd->index].precision; + cmd->type = TYPE_FLOAT; + return (STAT_OK); +} + +stat_t get_flu(cmdObj_t *cmd) +{ + get_flt(cmd); + if (cm_get_units_mode() == INCHES) { + cmd->value *= INCH_PER_MM; + } + cmd->precision = cfgArray[cmd->index].precision; + cmd->type = TYPE_FLOAT; + return (STAT_OK); +} +/* REPLACED BY A MACRO - See config.h +char *get_format(const index_t index) +{ + return ((char *)cfgArray[index].format); +} +*/ + +/* Generic sets() + * set_nul() - set nothing (returns STAT_NOOP) + * set_ui8() - set value as 8 bit uint8_t value w/o unit conversion + * set_01() - set a 0 or 1 uint8_t value with validation + * set_012() - set a 0, 1 or 2 uint8_t value with validation + * set_int() - set value as 32 bit integer w/o unit conversion + * set_flt() - set value as float w/o unit conversion + * set_flu() - set value as float w/unit conversion + */ +stat_t set_nul(cmdObj_t *cmd) { return (STAT_NOOP);} + +stat_t set_ui8(cmdObj_t *cmd) +{ + *((uint8_t *)cfgArray[cmd->index].target) = cmd->value; + cmd->type = TYPE_INTEGER; + return(STAT_OK); +} + +stat_t set_01(cmdObj_t *cmd) +{ + if (cmd->value > 1) { + return (STAT_INPUT_VALUE_UNSUPPORTED); + } else { + return (set_ui8(cmd)); + } +} + +stat_t set_012(cmdObj_t *cmd) +{ + if (cmd->value > 2) { + return (STAT_INPUT_VALUE_UNSUPPORTED); + } else { + return (set_ui8(cmd)); + } +} + stat_t set_int(cmdObj_t *cmd) { *((uint32_t *)cfgArray[cmd->index].target) = cmd->value; cmd->type = TYPE_INTEGER; return(STAT_OK); } -stat_t get_flt(cmdObj_t *cmd) -{ - cmd->value = *((float *)cfgArray[cmd->index].target); - cmd->type = TYPE_FLOAT; - return (STAT_OK); -} + stat_t set_flt(cmdObj_t *cmd) { *((float *)cfgArray[cmd->index].target) = cmd->value; + cmd->precision = cfgArray[cmd->index].precision; cmd->type = TYPE_FLOAT; return(STAT_OK); } -/* -char *get_format(const index_t index) +stat_t set_flu(cmdObj_t *cmd) { - return ((char *)cfgArray[index].format); + if (cm_get_units_mode() == INCHES) { cmd->value *= MM_PER_INCH;} + *((float *)cfgArray[cmd->index].target) = cmd->value; + cmd->precision = cfgArray[cmd->index].precision; + cmd->type = TYPE_FLOAT_UNITS; + return(STAT_OK); } -*/ /* Generic prints() * print_nul() - print nothing @@ -201,7 +253,6 @@ char *get_format(const index_t index) * print_lin() - print linear value with units and in/mm unit conversion * print_rot() - print rotary value with units */ - void print_nul(cmdObj_t *cmd) {} void print_str(cmdObj_t *cmd) @@ -403,6 +454,7 @@ cmdObj_t *cmd_reset_obj(cmdObj_t *cmd) // clear a single cmdObj structure cmd->type = TYPE_EMPTY; // selective clear is much faster than calling memset cmd->index = 0; cmd->value = 0; + cmd->precision = 0; cmd->token[0] = NUL; cmd->group[0] = NUL; cmd->stringp = NULL; diff --git a/TinyG2/config_app.cpp b/TinyG2/config_app.cpp index 4246ac7f..7a72b5ee 100755 --- a/TinyG2/config_app.cpp +++ b/TinyG2/config_app.cpp @@ -34,7 +34,6 @@ */ #include "tinyg2.h" #include "config.h" -//#include "config_app.h" #include "controller.h" #include "canonical_machine.h" #include "settings.h" @@ -108,7 +107,7 @@ static stat_t set_defa(cmdObj_t *cmd); // reset config to default values static stat_t get_am(cmdObj_t *cmd); // get axis mode static stat_t set_am(cmdObj_t *cmd); // set axis mode -static void print_am(cmdObj_t *cmd); // print axis mode +static void print_am(cmdObj_t *cmd); // print axis mode with enumeration string static stat_t set_sw(cmdObj_t *cmd); // must run any time you change a switch setting static stat_t set_sa(cmdObj_t *cmd); // set motor step angle static stat_t set_tr(cmdObj_t *cmd); // set motor travel per revolution @@ -118,7 +117,6 @@ static stat_t set_po(cmdObj_t *cmd); // set motor polarity static void pr_ma_ui8(cmdObj_t *cmd); // print uint8_t value static void pr_ma_lin(cmdObj_t *cmd); // print a linear value in prevailing units static void pr_ma_rot(cmdObj_t *cmd); // print a rotary value in degrees units -static void print_am(cmdObj_t *cmd); // print axis mode with enumeration string static void print_coor(cmdObj_t *cmd); // print coordinate offsets with linear units static void print_corr(cmdObj_t *cmd); // print coordinate offsets with rotary units @@ -541,7 +539,7 @@ const cfgItem_t cfgArray[] = { { "c","cjm",_fip, 0, fmt_Xjm, pr_ma_rot, get_flt, set_flt,(float *)&cfg.a[AXIS_C].jerk_max, C_JERK_MAX }, { "c","cjd",_fip, 0, fmt_Xjd, pr_ma_rot, get_flt, set_flt,(float *)&cfg.a[AXIS_C].junction_dev, C_JUNCTION_DEVIATION }, { "c","cra",_fip, 3, fmt_Xra, pr_ma_rot, get_flt, set_flt,(float *)&cfg.a[AXIS_C].radius, C_RADIUS }, -/* + // PWM settings { "p1","p1frq",_fip, 0, fmt_p1frq, print_flt, get_flt, set_flt,(float *)&cfg.p.frequency, P1_PWM_FREQUENCY }, { "p1","p1csl",_fip, 0, fmt_p1csl, print_flt, get_flt, set_flt,(float *)&cfg.p.cw_speed_lo, P1_CW_SPEED_LO }, @@ -553,7 +551,7 @@ const cfgItem_t cfgArray[] = { { "p1","p1wpl",_fip, 3, fmt_p1wpl, print_flt, get_flt, set_flt,(float *)&cfg.p.ccw_phase_lo, P1_CCW_PHASE_LO }, { "p1","p1wph",_fip, 3, fmt_p1wph, print_flt, get_flt, set_flt,(float *)&cfg.p.ccw_phase_hi, P1_CCW_PHASE_HI }, { "p1","p1pof",_fip, 3, fmt_p1pof, print_rot, get_flt, set_flt,(float *)&cfg.p.phase_off, P1_PWM_PHASE_OFF }, - +/* // Coordinate system offsets (G54-G59 and G92) { "g54","g54x",_fip, 3, fmt_cofs, print_coor,get_flu, set_flu,(float *)&cfg.offset[G54][AXIS_X], G54_X_OFFSET }, { "g54","g54y",_fip, 3, fmt_cofs, print_coor,get_flu, set_flu,(float *)&cfg.offset[G54][AXIS_Y], G54_Y_OFFSET }, @@ -978,8 +976,9 @@ static stat_t get_vel(cmdObj_t *cmd) { //+++++ cmd->value = mp_get_runtime_velocity(); if (cm_get_units_mode() == INCHES) cmd->value *= INCH_PER_MM; - cmd->type = TYPE_FLOAT; cmd->precision = cfgArray[cmd->index].precision; +// cmd->type = TYPE_FLOAT_UNITS; + cmd->type = TYPE_FLOAT; return (STAT_OK); } @@ -1013,24 +1012,27 @@ int8_t _get_pos_axis(const index_t index) // index into configArray static stat_t get_pos(cmdObj_t *cmd) { cmd->value = cm_get_runtime_work_position(_get_pos_axis(cmd->index)); - cmd->type = TYPE_FLOAT; cmd->precision = cfgArray[cmd->index].precision; +// cmd->type = TYPE_FLOAT_UNITS; //++++ UNTESTED + cmd->type = TYPE_FLOAT; return (STAT_OK); } static stat_t get_mpos(cmdObj_t *cmd) { cmd->value = cm_get_runtime_machine_position(_get_pos_axis(cmd->index)); - cmd->type = TYPE_FLOAT; cmd->precision = cfgArray[cmd->index].precision; +// cmd->type = TYPE_FLOAT_UNITS; //++++ UNTESTED + cmd->type = TYPE_FLOAT; return (STAT_OK); } static stat_t get_ofs(cmdObj_t *cmd) { cmd->value = cm_get_runtime_work_offset(_get_pos_axis(cmd->index)); - cmd->type = TYPE_FLOAT; cmd->precision = cfgArray[cmd->index].precision; +// cmd->type = TYPE_FLOAT_UNITS; //++++ UNTESTED + cmd->type = TYPE_FLOAT; return (STAT_OK); } @@ -1073,7 +1075,7 @@ static stat_t run_gc(cmdObj_t *cmd) static stat_t run_home(cmdObj_t *cmd) { - if (fp_TRUE(cmd->value)) { cm_homing_cycle_start();} +//+++++ if (fp_TRUE(cmd->value)) { cm_homing_cycle_start();} return (STAT_OK); } diff --git a/TinyG2/main.cpp b/TinyG2/main.cpp index 1b15de0a..f1bcb83b 100755 --- a/TinyG2/main.cpp +++ b/TinyG2/main.cpp @@ -73,9 +73,9 @@ extern void SysTick_Handler( void ) static void _application_init(void); -//globals +// collect all weird little globals here stat_t status_code; // declared for ritorno, see tinyg2.h - + /******************** Application Code ************************/ void setup( void ) diff --git a/TinyG2/motate/utility/SamPins.h b/TinyG2/motate/utility/SamPins.h index 30316d90..c5fea0b6 100755 --- a/TinyG2/motate/utility/SamPins.h +++ b/TinyG2/motate/utility/SamPins.h @@ -179,7 +179,6 @@ namespace Motate { static const int8_t number = pinNum;\ static const uint8_t portLetter = (uint8_t) registerChar;\ static const uint32_t mask = (1u << registerPin);\ - static Port32 port;\ \ Pin() {};\ Pin(const PinMode type, const PinOptions options = kNormal) {\ @@ -201,12 +200,12 @@ namespace Motate { if (!fromConstructor) {\ if ( (*PIO ## registerLetter).PIO_OSR == 0xffffffff )\ {\ - port.disablePeripheralClock();\ + Port32::disablePeripheralClock();\ }\ }\ break;\ case kInput:\ - port.enablePeripheralClock();\ + Port32::enablePeripheralClock();\ (*PIO ## registerLetter).PIO_ODR = mask ;\ (*PIO ## registerLetter).PIO_PER = mask ;\ break;\ @@ -295,7 +294,7 @@ namespace Motate { template <>\ struct Port32 {\ static const uint8_t letter = (uint8_t) registerChar;\ - void enablePeripheralClock() {\ + static void enablePeripheralClock() {\ if (pmcId() < 32) {\ uint32_t id_mask = 1u << ( pmcId() );\ if ((PMC->PMC_PCSR0 & id_mask) != id_mask) {\ @@ -308,7 +307,7 @@ namespace Motate { }\ }\ };\ - void disablePeripheralClock() {\ + static void disablePeripheralClock() {\ if (pmcId() < 32) {\ uint32_t id_mask = 1u << ( pmcId() );\ if ((PMC->PMC_PCSR0 & id_mask) == id_mask) {\ @@ -393,7 +392,7 @@ namespace Motate { Pio* portPtr() {\ return (PIO ## registerLetter);\ };\ - const uint32_t pmcId() {\ + static const uint32_t pmcId() {\ return ID_PIO ## registerLetter;\ };\ };\ diff --git a/TinyG2/motate/utility/SamTimers.h b/TinyG2/motate/utility/SamTimers.h index 08b46ece..b099181d 100644 --- a/TinyG2/motate/utility/SamTimers.h +++ b/TinyG2/motate/utility/SamTimers.h @@ -66,7 +66,6 @@ namespace Motate { kInterruptsOff = 0, kInterruptOnMatch = 1<<1, kInterruptOnOverflow = 1<<2, - kSetOnMatch = 1<<3, // ??? }; enum TimerErrorCodes { @@ -75,18 +74,18 @@ namespace Motate { template struct Timer { - // NOTE: Read carefully! The *pointers* are const, not the *values*. + // NOTE: Notice! The *pointers* are const, not the *values*. static Tc * const tc; static TcChannel * const tcChan; static const uint32_t peripheralId; // ID_TC0 .. ID_TC8 /* ################################################################### * - /* # WARNING # * - /* # WARNING: Sam channels (tcChan) DO NOT map to Motate Channels!?! # * - /* # WARNING (u been warned) # * - /* ################################################################### */ + * # WARNING # * + * # WARNING: Sam channels (tcChan) DO NOT map to Motate Channels!?! # * + * # WARNING (u been warned) # * + * ################################################################### */ - Timer() : init() {}; + Timer() { init(); }; void init() { /* Unlock this thing */ @@ -133,7 +132,7 @@ namespace Motate { // Set the mode and frequency. // Returns: The actual frequency that was used, or kFrequencyUnattainable int32_t setModeAndFrequency(const TimerMode mode, const uint32_t freq) { - /* Prepare to be able to make changes: *? + /* Prepare to be able to make changes: */ /* Disable TC clock */ tcChan->TC_CCR = TC_CCR_CLKDIS ; /* Disable interrupts */ @@ -196,11 +195,16 @@ namespace Motate { int32_t newTop = masterClock/(divisor*freq); setTop(newTop); - // determine and return the new frequency + // Determine and return the new frequency. return masterClock/(divisor*newTop); } - // determine and return the new frequency + // Optimization -- we can't use RC for much when we're not using it, + // so, instead of looking up if we're using it or not, just set it to + // 0xFFFF when we're not using it. + setTop(0xFFFF); + + // Determine and return the new frequency. return masterClock/(divisor*0xFFFF); }; @@ -212,9 +216,79 @@ namespace Motate { return 0; }; + // Here we want to get what the TOP value is. Is the mode is one that resets on RC, then RC is the TOP. + // Otherwise, TOP is 0xFFFF. In order to see if TOP is RC, we need to look at the CPCTRG (RC Compare + // Trigger Enable) bit of the CMR (Channel Mode Register). Note that this bit position is the same for + // waveform or Capture mode, even though the Datasheet seems to obfuscate this fact. + uint32_t getTopValue() { + return tcChan->TC_CMR & TC_CMR_CPCTRG ? tcChan->TC_RC : 0xFFFF; + }; + // Return the current value of the counter. This is a fleeting thing... + uint32_t getValue() { + return tcChan->TC_CV; + } + + void start() { + tcChan->TC_CCR = TC_CCR_CLKEN | TC_CCR_SWTRG; + }; + + void stop() { + tcChan->TC_CCR = TC_CCR_CLKDIS; + }; + + // Channel-specific functions. These are Motate channels. + // Motate channel 0 = Sam channel A. + // Motate channel 1 = Sam channel B. + + // Specify the duty cycle as a value from 0.0 .. 1.0; + void setDutyCycle(const uint8_t channel, const float ratio) { + if (channel == 0) + tcChan->TC_RA = getTopValue() * ratio; + else if (channel == 1) + tcChan->TC_RB = getTopValue() * ratio; + }; + + // Specify channel A/B duty cycle as a integer value from 0 .. TOP. + // TOP in this case is either RC_RC or 0xFFFF. + void setDutyCycle(const uint8_t channel, const uint32_t absolute) { + if (channel == 0) + tcChan->TC_RA = absolute; + else if (channel == 1) + tcChan->TC_RB = absolute; + }; }; + + template<> Tc * const Timer<0>::tc = TC0; + template<> TcChannel * const Timer<0>::tcChan = TC0->TC_CHANNEL + 0; + template<> const uint32_t Timer<0>::peripheralId = ID_TC0; + template<> Tc * const Timer<1>::tc = TC0; + template<> TcChannel * const Timer<1>::tcChan = TC0->TC_CHANNEL + 1; + template<> const uint32_t Timer<1>::peripheralId = ID_TC1; + template<> Tc * const Timer<2>::tc = TC0; + template<> TcChannel * const Timer<2>::tcChan = TC0->TC_CHANNEL + 2; + template<> const uint32_t Timer<2>::peripheralId = ID_TC2; + + template<> Tc * const Timer<3>::tc = TC1; + template<> TcChannel * const Timer<3>::tcChan = TC1->TC_CHANNEL + 0; + template<> const uint32_t Timer<3>::peripheralId = ID_TC3; + template<> Tc * const Timer<4>::tc = TC1; + template<> TcChannel * const Timer<4>::tcChan = TC1->TC_CHANNEL + 1; + template<> const uint32_t Timer<4>::peripheralId = ID_TC4; + template<> Tc * const Timer<5>::tc = TC1; + template<> TcChannel * const Timer<5>::tcChan = TC1->TC_CHANNEL + 2; + template<> const uint32_t Timer<5>::peripheralId = ID_TC5; + + template<> Tc * const Timer<6>::tc = TC2; + template<> TcChannel * const Timer<6>::tcChan = TC2->TC_CHANNEL + 0; + template<> const uint32_t Timer<6>::peripheralId = ID_TC6; + template<> Tc * const Timer<7>::tc = TC2; + template<> TcChannel * const Timer<7>::tcChan = TC2->TC_CHANNEL + 1; + template<> const uint32_t Timer<7>::peripheralId = ID_TC7; + template<> Tc * const Timer<8>::tc = TC2; + template<> TcChannel * const Timer<8>::tcChan = TC2->TC_CHANNEL + 2; + template<> const uint32_t Timer<8>::peripheralId = ID_TC8; } #endif /* end of include guard: AVRTIMERS_H_ONCE */ \ No newline at end of file diff --git a/TinyG2/tinyg2.h b/TinyG2/tinyg2.h index 59a67770..e852b4db 100755 --- a/TinyG2/tinyg2.h +++ b/TinyG2/tinyg2.h @@ -1,225 +1,225 @@ -/* - * tinyg2.h - tinyg2 main header - Application GLOBALS - * Part of TinyG2 project - * - * Copyright (c) 2013 Alden S. Hart Jr. - * Copyright (c) 2013 Robert Giseburt - * - * This file ("the software") is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License, version 2 as published by the - * Free Software Foundation. You should have received a copy of the GNU General Public - * License, version 2 along with the software. If not, see . - * - * As a special exception, you may use this file as part of a software library without - * restriction. Specifically, if other files instantiate templates or use macros or - * inline functions from this file, or you compile this file and link it with other - * files to produce an executable, this file does not by itself cause the resulting - * executable to be covered by the GNU General Public License. This exception does not - * however invalidate any other reasons why the executable file might be covered by the - * GNU General Public License. - * - * THE SOFTWARE IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT WITHOUT ANY - * WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT - * SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF - * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ -/* Is this code over documented? Possibly. - * We try to follow this (at least we are evolving to it). It's worth a read. - * ftp://ftp.idsoftware.com/idstuff/doom3/source/CodeStyleConventions.doc - */ -#ifndef _TINYG2_H_ -#define _TINYG2_H_ - -// common system includes -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "Arduino.h" - -#ifdef __cplusplus -extern "C"{ -#endif // __cplusplus - -// NOTE: This header requires be included previously - -#define TINYG_FIRMWARE_BUILD 005.02 // -#define TINYG_FIRMWARE_VERSION 0.01 // firmware major version -#define TINYG_HARDWARE_PLATFORM 2.00 // hardware platform indicator (Native Arduino Due) -#define TINYG_HARDWARE_VERSION 1.00 // hardware platform revision number - -#define TINYG2_HARDWARE_VERSION_MAX (TINYG_HARDWARE_VERSION) - -/****** DEVELOPMENT SETTINGS ******/ - -//#define __CANNED_STARTUP // run any canned startup moves -//#define __DISABLE_PERSISTENCE // disable EEPROM writes for faster simulation -//#define __SUPPRESS_STARTUP_MESSAGES // what it says -//#define __UNIT_TESTS // master enable for unit tests; uncomment modules in .h files -//#define __DEBUG // complies debug functions found in test.c - -// UNIT_TESTS exist for various modules are can be enabled at the end of their .h files - -/****** OPERATING SETTINGS *******/ - -void tg_setup(void); - -/************************************************************************* - * String handling help - strings are handled as uint8_t's typedef'd to char_t - */ -typedef uint8_t char_t; -#define strncpy(d,s,l) (char_t *)strncpy((char *)d, (char *)s, l) -#define strpbrk(d,s) (char_t* )strpbrk((char *)d, (char *)s) -#define strcpy(d,s) (char_t *)strcpy((char *)d, (char *)s) -#define strcat(d,s) (char_t *)strcat((char *)d, (char *)s) -#define strstr(d,s) (char_t *)strstr((char *)d, (char *)s) -#define strchr(d,s) (char_t *)strchr((char *)d, (char)s) -#define strcmp(d,s) strcmp((char *)d, (char *)s) -#define strtod(d,s) strtod((char *)d, (char **)s) -#define strlen(s) strlen((char *)s) - -//#define sprintf(a,b) sprintf(char *)a, (char *)b) - -/************************************************************************* - * TinyG application-specific prototypes, defines and globals - */ -#define MAGICNUM 0x12EF // used for memory integrity assertions - -Motate::pin_number indicator_led_pin_num = 13; -static Motate::OutputPin IndicatorLed; - -#define AXES 6 // number of axes supported in this version -#define MOTORS 4 // number of motors on the board -#define COORDS 6 // number of supported coordinate systems (1-6) -#define PWMS 2 // number of supported PWM channels - -// If you change COORDS you must adjust the entries in cfgArray table in config.c - -/* Axes, motors & PWM channels must be defines (not enums) so #ifdef can be used - * NB: Using defines can have side effects if anythign else in the code uses A, B, X... etc. - * The "side effect safe" min and max routines had this side effect. - * Alternate enum is: enum tgAxes { X=0, Y, Z, A, B, C }; - */ - -#define AXIS_X 0 -#define AXIS_Y 1 -#define AXIS_Z 2 -#define AXIS_A 3 -#define AXIS_B 4 -#define AXIS_C 5 -#define AXIS_U 6 // reserved -#define AXIS_V 7 // reserved -#define AXIS_W 8 // reserved - -#define MOTOR_1 0 // define motor numbers and array indexes -#define MOTOR_2 1 // must be defines. enums don't work -#define MOTOR_3 2 -#define MOTOR_4 3 - -#define PWM_1 0 -#define PWM_2 1 - -/* - * STATUS CODES - * - * Any changes to the ranges also require changing the message strings and - * string array in controller.c - * - * ritorno is a handy way to provide exception returns - * It returns only if an error occurred. (ritorno is Italian for return) - */ -typedef uint8_t stat_t; -extern stat_t status_code; // declared in main.cpp -#define ritorno(a) if((status_code=a) != STAT_OK) { return(status_code); } - -// OS, communications and low-level status (must align with XIO_xxxx codes in xio.h) -#define STAT_OK 0 // function completed OK -#define STAT_ERROR 1 // generic error return (EPERM) -#define STAT_EAGAIN 2 // function would block here (call again) -#define STAT_NOOP 3 // function had no-operation -#define STAT_COMPLETE 4 // operation is complete -#define STAT_TERMINATE 5 // operation terminated (gracefully) -#define STAT_RESET 6 // operation was hard reset (sig kill) -#define STAT_EOL 7 // function returned end-of-line -#define STAT_EOF 8 // function returned end-of-file -#define STAT_FILE_NOT_OPEN 9 -#define STAT_FILE_SIZE_EXCEEDED 10 -#define STAT_NO_SUCH_DEVICE 11 -#define STAT_BUFFER_EMPTY 12 -#define STAT_BUFFER_FULL 13 -#define STAT_BUFFER_FULL_FATAL 14 -#define STAT_INITIALIZING 15 // initializing - not ready for use -#define STAT_STUBBED_16 16 // function is stubbed -#define STAT_ERROR_17 17 -#define STAT_ERROR_18 18 -#define STAT_ERROR_19 19 // NOTE: XIO codes align to here - -// Internal errors and startup messages -#define STAT_INTERNAL_ERROR 20 // unrecoverable internal error -#define STAT_INTERNAL_RANGE_ERROR 21 // number range other than by user input -#define STAT_FLOATING_POINT_ERROR 22 // number conversion error -#define STAT_DIVIDE_BY_ZERO 23 -#define STAT_INVALID_ADDRESS 24 -#define STAT_READ_ONLY_ADDRESS 25 -#define STAT_INIT_FAIL 26 -#define STAT_SHUTDOWN 27 -#define STAT_MEMORY_CORRUPTION 28 -#define STAT_ERROR_29 29 -#define STAT_ERROR_30 30 -#define STAT_ERROR_31 31 -#define STAT_ERROR_32 32 -#define STAT_ERROR_33 33 -#define STAT_ERROR_34 34 -#define STAT_ERROR_35 35 -#define STAT_ERROR_36 36 -#define STAT_ERROR_37 37 -#define STAT_ERROR_38 38 -#define STAT_ERROR_39 39 - -// Input errors (400's, if you will) -#define STAT_UNRECOGNIZED_COMMAND 40 // parser didn't recognize the command -#define STAT_EXPECTED_COMMAND_LETTER 41 // malformed line to parser -#define STAT_BAD_NUMBER_FORMAT 42 // number format error -#define STAT_INPUT_EXCEEDS_MAX_LENGTH 43// input string is too long -#define STAT_INPUT_VALUE_TOO_SMALL 44 // input error: value is under minimum -#define STAT_INPUT_VALUE_TOO_LARGE 45 // input error: value is over maximum -#define STAT_INPUT_VALUE_RANGE_ERROR 46 // input error: value is out-of-range -#define STAT_INPUT_VALUE_UNSUPPORTED 47 // input error: value is not supported -#define STAT_JSON_SYNTAX_ERROR 48 // JSON input string is not well formed -#define STAT_JSON_TOO_MANY_PAIRS 49 // JSON input string has too many JSON pairs -#define STAT_JSON_TOO_LONG 50 // JSON output exceeds buffer size -#define STAT_NO_BUFFER_SPACE 51 // Buffer pool is full and cannot perform this operation -#define STAT_ERROR_52 52 -#define STAT_ERROR_53 53 -#define STAT_ERROR_54 54 -#define STAT_ERROR_55 55 -#define STAT_ERROR_56 56 -#define STAT_ERROR_57 57 -#define STAT_ERROR_58 58 -#define STAT_ERROR_59 59 - -// Gcode and machining errors -#define STAT_ZERO_LENGTH_MOVE 60 // move is zero length -#define STAT_GCODE_BLOCK_SKIPPED 61 // block is too short - was skipped -#define STAT_GCODE_INPUT_ERROR 62 // general error for gcode input -#define STAT_GCODE_FEEDRATE_ERROR 63 // move has no feedrate -#define STAT_GCODE_AXIS_WORD_MISSING 64 // command requires at least one axis present -#define STAT_MODAL_GROUP_VIOLATION 65 // gcode modal group error -#define STAT_HOMING_CYCLE_FAILED 66 // homing cycle did not complete -#define STAT_MAX_TRAVEL_EXCEEDED 67 -#define STAT_MAX_SPINDLE_SPEED_EXCEEDED 68 -#define STAT_ARC_SPECIFICATION_ERROR 69 // arc specification error - -#ifdef __cplusplus -} -#endif // __cplusplus - -#endif // _TINYG2_H_ +/* + * tinyg2.h - tinyg2 main header - Application GLOBALS + * Part of TinyG2 project + * + * Copyright (c) 2013 Alden S. Hart Jr. + * Copyright (c) 2013 Robert Giseburt + * + * This file ("the software") is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2 as published by the + * Free Software Foundation. You should have received a copy of the GNU General Public + * License, version 2 along with the software. If not, see . + * + * As a special exception, you may use this file as part of a software library without + * restriction. Specifically, if other files instantiate templates or use macros or + * inline functions from this file, or you compile this file and link it with other + * files to produce an executable, this file does not by itself cause the resulting + * executable to be covered by the GNU General Public License. This exception does not + * however invalidate any other reasons why the executable file might be covered by the + * GNU General Public License. + * + * THE SOFTWARE IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT WITHOUT ANY + * WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT + * SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +/* Is this code over documented? Possibly. + * We try to follow this (at least we are evolving to it). It's worth a read. + * ftp://ftp.idsoftware.com/idstuff/doom3/source/CodeStyleConventions.doc + */ +#ifndef _TINYG2_H_ +#define _TINYG2_H_ + +// common system includes +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "Arduino.h" + +#ifdef __cplusplus +extern "C"{ +#endif // __cplusplus + +// NOTE: This header requires be included previously + +#define TINYG_FIRMWARE_BUILD 005.03 // +#define TINYG_FIRMWARE_VERSION 0.01 // firmware major version +#define TINYG_HARDWARE_PLATFORM 2.00 // hardware platform indicator (Native Arduino Due) +#define TINYG_HARDWARE_VERSION 1.00 // hardware platform revision number + +#define TINYG2_HARDWARE_VERSION_MAX (TINYG_HARDWARE_VERSION) + +/****** DEVELOPMENT SETTINGS ******/ + +//#define __CANNED_STARTUP // run any canned startup moves +//#define __DISABLE_PERSISTENCE // disable EEPROM writes for faster simulation +//#define __SUPPRESS_STARTUP_MESSAGES // what it says +//#define __UNIT_TESTS // master enable for unit tests; uncomment modules in .h files +//#define __DEBUG // complies debug functions found in test.c + +// UNIT_TESTS exist for various modules are can be enabled at the end of their .h files + +/****** OPERATING SETTINGS *******/ + +void tg_setup(void); + +/************************************************************************* + * String handling help - strings are handled as uint8_t's typedef'd to char_t + */ +typedef uint8_t char_t; +#define strncpy(d,s,l) (char_t *)strncpy((char *)d, (char *)s, l) +#define strpbrk(d,s) (char_t* )strpbrk((char *)d, (char *)s) +#define strcpy(d,s) (char_t *)strcpy((char *)d, (char *)s) +#define strcat(d,s) (char_t *)strcat((char *)d, (char *)s) +#define strstr(d,s) (char_t *)strstr((char *)d, (char *)s) +#define strchr(d,s) (char_t *)strchr((char *)d, (char)s) +#define strcmp(d,s) strcmp((char *)d, (char *)s) +#define strtod(d,s) strtod((char *)d, (char **)s) +#define strlen(s) strlen((char *)s) + +//#define sprintf(a,b) sprintf(char *)a, (char *)b) + +/************************************************************************* + * TinyG application-specific prototypes, defines and globals + */ +Motate::pin_number indicator_led_pin_num = 13; +static Motate::OutputPin IndicatorLed; + +#define MAGICNUM 0x12EF // used for memory integrity assertions + +#define AXES 6 // number of axes supported in this version +#define MOTORS 4 // number of motors on the board +#define COORDS 6 // number of supported coordinate systems (1-6) +#define PWMS 2 // number of supported PWM channels + +// If you change COORDS you must adjust the entries in cfgArray table in config.c + +/* Axes, motors & PWM channels must be defines (not enums) so #ifdef can be used + * NB: Using defines can have side effects if anythign else in the code uses A, B, X... etc. + * The "side effect safe" min and max routines had this side effect. + * Alternate enum is: enum tgAxes { X=0, Y, Z, A, B, C }; + */ + +#define AXIS_X 0 +#define AXIS_Y 1 +#define AXIS_Z 2 +#define AXIS_A 3 +#define AXIS_B 4 +#define AXIS_C 5 +#define AXIS_U 6 // reserved +#define AXIS_V 7 // reserved +#define AXIS_W 8 // reserved + +#define MOTOR_1 0 // define motor numbers and array indexes +#define MOTOR_2 1 // must be defines. enums don't work +#define MOTOR_3 2 +#define MOTOR_4 3 + +#define PWM_1 0 +#define PWM_2 1 + +/* + * STATUS CODES + * + * Any changes to the ranges also require changing the message strings and + * string array in controller.c + * + * ritorno is a handy way to provide exception returns + * It returns only if an error occurred. (ritorno is Italian for return) + */ +typedef uint8_t stat_t; +extern stat_t status_code; // declared in main.cpp +#define ritorno(a) if((status_code=a) != STAT_OK) { return(status_code); } + +// OS, communications and low-level status (must align with XIO_xxxx codes in xio.h) +#define STAT_OK 0 // function completed OK +#define STAT_ERROR 1 // generic error return (EPERM) +#define STAT_EAGAIN 2 // function would block here (call again) +#define STAT_NOOP 3 // function had no-operation +#define STAT_COMPLETE 4 // operation is complete +#define STAT_TERMINATE 5 // operation terminated (gracefully) +#define STAT_RESET 6 // operation was hard reset (sig kill) +#define STAT_EOL 7 // function returned end-of-line +#define STAT_EOF 8 // function returned end-of-file +#define STAT_FILE_NOT_OPEN 9 +#define STAT_FILE_SIZE_EXCEEDED 10 +#define STAT_NO_SUCH_DEVICE 11 +#define STAT_BUFFER_EMPTY 12 +#define STAT_BUFFER_FULL 13 +#define STAT_BUFFER_FULL_FATAL 14 +#define STAT_INITIALIZING 15 // initializing - not ready for use +#define STAT_STUBBED_16 16 // function is stubbed +#define STAT_ERROR_17 17 +#define STAT_ERROR_18 18 +#define STAT_ERROR_19 19 // NOTE: XIO codes align to here + +// Internal errors and startup messages +#define STAT_INTERNAL_ERROR 20 // unrecoverable internal error +#define STAT_INTERNAL_RANGE_ERROR 21 // number range other than by user input +#define STAT_FLOATING_POINT_ERROR 22 // number conversion error +#define STAT_DIVIDE_BY_ZERO 23 +#define STAT_INVALID_ADDRESS 24 +#define STAT_READ_ONLY_ADDRESS 25 +#define STAT_INIT_FAIL 26 +#define STAT_SHUTDOWN 27 +#define STAT_MEMORY_CORRUPTION 28 +#define STAT_ERROR_29 29 +#define STAT_ERROR_30 30 +#define STAT_ERROR_31 31 +#define STAT_ERROR_32 32 +#define STAT_ERROR_33 33 +#define STAT_ERROR_34 34 +#define STAT_ERROR_35 35 +#define STAT_ERROR_36 36 +#define STAT_ERROR_37 37 +#define STAT_ERROR_38 38 +#define STAT_ERROR_39 39 + +// Input errors (400's, if you will) +#define STAT_UNRECOGNIZED_COMMAND 40 // parser didn't recognize the command +#define STAT_EXPECTED_COMMAND_LETTER 41 // malformed line to parser +#define STAT_BAD_NUMBER_FORMAT 42 // number format error +#define STAT_INPUT_EXCEEDS_MAX_LENGTH 43// input string is too long +#define STAT_INPUT_VALUE_TOO_SMALL 44 // input error: value is under minimum +#define STAT_INPUT_VALUE_TOO_LARGE 45 // input error: value is over maximum +#define STAT_INPUT_VALUE_RANGE_ERROR 46 // input error: value is out-of-range +#define STAT_INPUT_VALUE_UNSUPPORTED 47 // input error: value is not supported +#define STAT_JSON_SYNTAX_ERROR 48 // JSON input string is not well formed +#define STAT_JSON_TOO_MANY_PAIRS 49 // JSON input string has too many JSON pairs +#define STAT_JSON_TOO_LONG 50 // JSON output exceeds buffer size +#define STAT_NO_BUFFER_SPACE 51 // Buffer pool is full and cannot perform this operation +#define STAT_ERROR_52 52 +#define STAT_ERROR_53 53 +#define STAT_ERROR_54 54 +#define STAT_ERROR_55 55 +#define STAT_ERROR_56 56 +#define STAT_ERROR_57 57 +#define STAT_ERROR_58 58 +#define STAT_ERROR_59 59 + +// Gcode and machining errors +#define STAT_ZERO_LENGTH_MOVE 60 // move is zero length +#define STAT_GCODE_BLOCK_SKIPPED 61 // block is too short - was skipped +#define STAT_GCODE_INPUT_ERROR 62 // general error for gcode input +#define STAT_GCODE_FEEDRATE_ERROR 63 // move has no feedrate +#define STAT_GCODE_AXIS_WORD_MISSING 64 // command requires at least one axis present +#define STAT_MODAL_GROUP_VIOLATION 65 // gcode modal group error +#define STAT_HOMING_CYCLE_FAILED 66 // homing cycle did not complete +#define STAT_MAX_TRAVEL_EXCEEDED 67 +#define STAT_MAX_SPINDLE_SPEED_EXCEEDED 68 +#define STAT_ARC_SPECIFICATION_ERROR 69 // arc specification error + +#ifdef __cplusplus +} +#endif // __cplusplus + +#endif // _TINYG2_H_ diff --git a/TinyG2/util.cpp b/TinyG2/util.cpp index 2dd990cf..1f8a048a 100755 --- a/TinyG2/util.cpp +++ b/TinyG2/util.cpp @@ -9,6 +9,8 @@ * - vector manipulation utilities * - support for debugging routines */ + +#include "tinyg2.h" #include "util.h" /* @@ -28,10 +30,17 @@ #include "stepper.h" #include "report.h" */ + #ifdef __cplusplus extern "C"{ #endif +/*** statically allocated global for vector operations ***/ +float vector[AXES]; // vector used by util.cpp and other functions + +/* + * strcpy_U() - strcpy workalike to get around initial NUL for blank string - possibly wrong + */ uint8_t * strcpy_U( uint8_t * dst, const uint8_t * src ) { uint16_t index = 0; @@ -56,14 +65,14 @@ uint8_t * strcpy_U( uint8_t * dst, const uint8_t * src ) * set_vector_by_axis() - load a single value into a zero vector */ -inline void copy_vector(float dest[], const float src[], uint8_t length) +void copy_vector(float dest[], const float src[], uint8_t length) { for (uint8_t i=0; i