* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-#ifndef CANONICAL_MACHINE_H
-#define CANONICAL_MACHINE_H
+#pragma once
+
#include "config.h"
#include "status.h"
#define AXIS_MODE_MAX_LINEAR AXIS_INHIBITED
#define AXIS_MODE_MAX_ROTARY AXIS_RADIUS
+// Coordinate offsets
+#define G54_X_OFFSET 0 // G54 is traditionally set to all zeros
+#define G54_Y_OFFSET 0
+#define G54_Z_OFFSET 0
+#define G54_A_OFFSET 0
+#define G54_B_OFFSET 0
+#define G54_C_OFFSET 0
+
+#define G55_X_OFFSET (X_TRAVEL_MAX / 2) // set to middle of table
+#define G55_Y_OFFSET (Y_TRAVEL_MAX / 2)
+#define G55_Z_OFFSET 0
+#define G55_A_OFFSET 0
+#define G55_B_OFFSET 0
+#define G55_C_OFFSET 0
+
+#define G56_X_OFFSET 0
+#define G56_Y_OFFSET 0
+#define G56_Z_OFFSET 0
+#define G56_A_OFFSET 0
+#define G56_B_OFFSET 0
+#define G56_C_OFFSET 0
+
+#define G57_X_OFFSET 0
+#define G57_Y_OFFSET 0
+#define G57_Z_OFFSET 0
+#define G57_A_OFFSET 0
+#define G57_B_OFFSET 0
+#define G57_C_OFFSET 0
+
+#define G58_X_OFFSET 0
+#define G58_Y_OFFSET 0
+#define G58_Z_OFFSET 0
+#define G58_A_OFFSET 0
+#define G58_B_OFFSET 0
+#define G58_C_OFFSET 0
+
+#define G59_X_OFFSET 0
+#define G59_Y_OFFSET 0
+#define G59_Z_OFFSET 0
+#define G59_A_OFFSET 0
+#define G59_B_OFFSET 0
+#define G59_C_OFFSET 0
+
// Model state getters and setters
uint8_t cm_get_combined_state();
stat_t cm_straight_probe(float target[], float flags[]); // G38.2
stat_t cm_probe_callback(); // G38.2 main loop callback
-#endif // CANONICAL_MACHINE_H
+
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-#ifndef CLOCK_H
-#define CLOCK_H
+#pragma once
+
#include <stdint.h>
void clock_init();
void CCPWrite(volatile uint8_t *address, uint8_t value);
-#endif // CLOCK_H
+
\******************************************************************************/
-#ifndef COMMAND_H
-#define COMMAND_H
+#pragma once
+
#include "status.h"
int command_exec(int argc, char *argv[]);
int command_eval(char *cmd);
-#endif // COMMAND_H
+
-#ifndef CONFIG_H
-#define CONFIG_H
+#pragma once
+
+#include <avr/interrupt.h>
+
// Compile-time settings
#define __STEP_CORRECTION
//#define __JERK_EXEC // Use computed jerk (vs. forward difference)
//#define __KAHAN // Use Kahan summation in aline exec functions
+
#define INPUT_BUFFER_LEN 255 // text buffer size (255 max)
#define AXES 6 // number of axes
#define COORDS 6 // number of supported coordinate systems (1-6)
#define PWMS 2 // number of supported PWM channels
-#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
-
// Motor settings
+#define STEP_CLOCK_FREQ 25000
+#define MOTOR_CURRENT 0.8 // 1.0 is full power
#define MOTOR_MICROSTEPS 16
-/// One of:
-/// MOTOR_DISABLED
-/// MOTOR_ALWAYS_POWERED
-/// MOTOR_POWERED_IN_CYCLE
+/// One of: MOTOR_DISABLED, MOTOR_ALWAYS_POWERED, MOTOR_POWERED_IN_CYCLE,
/// MOTOR_POWERED_ONLY_WHEN_MOVING
#define MOTOR_POWER_MODE MOTOR_ALWAYS_POWERED
/// Seconds to maintain motor at full power before idling
#define MOTOR_IDLE_TIMEOUT 2.00
+#define MAX_VELOCITY(angle, travel, mstep) \
+ (0.98 * (angle) * (travel) * STEP_CLOCK_FREQ / (mstep) / 6.0)
#define M1_MOTOR_MAP AXIS_X
#define M1_STEP_ANGLE 1.8
#define SWITCH_TYPE SW_TYPE_NORMALLY_OPEN
/// SW_MODE_DISABLED, SW_MODE_HOMING, SW_MODE_LIMIT, SW_MODE_HOMING_LIMIT
#define X_SWITCH_MODE_MIN SW_MODE_HOMING
-/// SW_MODE_DISABLED, SW_MODE_HOMING, SW_MODE_LIMIT, SW_MODE_HOMING_LIMIT
#define X_SWITCH_MODE_MAX SW_MODE_DISABLED
#define Y_SWITCH_MODE_MIN SW_MODE_HOMING
#define Y_SWITCH_MODE_MAX SW_MODE_DISABLED
#define JOG_ACCELERATION 50000 // mm/min^2
// Machine settings
-#define MOTOR_CURRENT 1.0 // 1.0 is full power
#define CHORDAL_TOLERANCE 0.01 // chordal accuracy for arc drawing
#define SOFT_LIMIT_ENABLE 0 // 0 = off, 1 = on
#define JERK_MAX 10 // yes, that's "20,000,000" mm/min^3
// Axis settings
-#define VELOCITY_MAX 575
+#define VELOCITY_MAX \
+ MAX_VELOCITY(M1_STEP_ANGLE, M1_TRAVEL_PER_REV, MOTOR_MICROSTEPS)
#define FEEDRATE_MAX VELOCITY_MAX
// see canonical_machine.h cmAxisMode for valid values
#define Z_LATCH_BACKOFF 5
#define Z_ZERO_BACKOFF 1
-#if 0
-#define A_AXIS_MODE AXIS_STANDARD
-#define A_VELOCITY_MAX VELOCITY_MAX
-#define A_FEEDRATE_MAX FEEDRATE_MAX
-#define A_TRAVEL_MIN 0
-#define A_TRAVEL_MAX 75
-#define A_JERK_MAX JERK_MAX
-#define A_JERK_HOMING (A_JERK_MAX * 2)
-#define A_JUNCTION_DEVIATION JUNCTION_DEVIATION
-#define A_SEARCH_VELOCITY 400
-#define A_LATCH_VELOCITY 100
-#define A_LATCH_BACKOFF 5
-#define A_ZERO_BACKOFF 1
-#define A_RADIUS 0
-
// A values are chosen to make the A motor react the same as X for testing
-#else
-#define A_AXIS_MODE AXIS_RADIUS
// set to the same speed as X axis
+#define A_AXIS_MODE AXIS_RADIUS
#define A_VELOCITY_MAX ((X_VELOCITY_MAX / M1_TRAVEL_PER_REV) * 360)
#define A_FEEDRATE_MAX A_VELOCITY_MAX
#define A_TRAVEL_MIN -1
#define A_LATCH_VELOCITY 100
#define A_LATCH_BACKOFF 5
#define A_ZERO_BACKOFF 2
-#endif
#define B_AXIS_MODE AXIS_DISABLED
#define B_VELOCITY_MAX 3600
// PWM settings
-#define P1_PWM_FREQUENCY 100 // in Hz
-#define P1_CW_SPEED_LO 1000 // in RPM (arbitrary units)
+#define P1_PWM_FREQUENCY 100 // in Hz
+#define P1_CW_SPEED_LO 1000 // in RPM (arbitrary units)
#define P1_CW_SPEED_HI 2000
-#define P1_CW_PHASE_LO 0.125 // phase [0..1]
+#define P1_CW_PHASE_LO 0.125 // phase [0..1]
#define P1_CW_PHASE_HI 0.2
#define P1_CCW_SPEED_LO 1000
#define P1_CCW_SPEED_HI 2000
// Gcode defaults
-#define GCODE_DEFAULT_UNITS MILLIMETERS // MILLIMETERS or INCHES
+#define GCODE_DEFAULT_UNITS MILLIMETERS // MILLIMETERS or INCHES
// CANON_PLANE_XY, CANON_PLANE_XZ, or CANON_PLANE_YZ
#define GCODE_DEFAULT_PLANE CANON_PLANE_XY
#define GCODE_DEFAULT_COORD_SYSTEM G54 // G54, G55, G56, G57, G58 or G59
#define GCODE_DEFAULT_PATH_CONTROL PATH_CONTINUOUS
#define GCODE_DEFAULT_DISTANCE_MODE ABSOLUTE_MODE
+#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
+
-// Coordinate offsets
-#define G54_X_OFFSET 0 // G54 is traditionally set to all zeros
-#define G54_Y_OFFSET 0
-#define G54_Z_OFFSET 0
-#define G54_A_OFFSET 0
-#define G54_B_OFFSET 0
-#define G54_C_OFFSET 0
-
-#define G55_X_OFFSET (X_TRAVEL_MAX / 2) // set to middle of table
-#define G55_Y_OFFSET (Y_TRAVEL_MAX / 2)
-#define G55_Z_OFFSET 0
-#define G55_A_OFFSET 0
-#define G55_B_OFFSET 0
-#define G55_C_OFFSET 0
-
-#define G56_X_OFFSET 0
-#define G56_Y_OFFSET 0
-#define G56_Z_OFFSET 0
-#define G56_A_OFFSET 0
-#define G56_B_OFFSET 0
-#define G56_C_OFFSET 0
-
-#define G57_X_OFFSET 0
-#define G57_Y_OFFSET 0
-#define G57_Z_OFFSET 0
-#define G57_A_OFFSET 0
-#define G57_B_OFFSET 0
-#define G57_C_OFFSET 0
-
-#define G58_X_OFFSET 0
-#define G58_Y_OFFSET 0
-#define G58_Z_OFFSET 0
-#define G58_A_OFFSET 0
-#define G58_B_OFFSET 0
-#define G58_C_OFFSET 0
-
-#define G59_X_OFFSET 0
-#define G59_Y_OFFSET 0
-#define G59_Z_OFFSET 0
-#define G59_A_OFFSET 0
-#define G59_B_OFFSET 0
-#define G59_C_OFFSET 0
-
-#endif // CONFIG_H
+#define MILLISECONDS_PER_TICK 1 // MS for system tick (systick * N)
+#define SYS_ID_LEN 12 // length of system ID string from sys_get_id()
+
+// Clock Crystal Config. Pick one:
+//#define __CLOCK_INTERNAL_32MHZ TRUE // use internal oscillator
+//#define __CLOCK_EXTERNAL_8MHZ TRUE // uses PLL to provide 32 MHz system clock
+#define __CLOCK_EXTERNAL_16MHZ TRUE // uses PLL to provide 32 MHz system clock
+
+// Motor, output bit & switch port assignments
+// These are not all the same, and must line up in multiple places in gpio.h
+// Sorry if this is confusing - it's a board routing issue
+#define PORT_MOTOR_1 PORTA // motors mapped to ports
+#define PORT_MOTOR_2 PORTF
+#define PORT_MOTOR_3 PORTE
+#define PORT_MOTOR_4 PORTD
+
+#define PORT_SWITCH_X PORTA // Switch axes mapped to ports
+#define PORT_SWITCH_Y PORTD
+#define PORT_SWITCH_Z PORTE
+#define PORT_SWITCH_A PORTF
+
+#define PORT_OUT_V7_X PORTA // v7 mapping
+#define PORT_OUT_V7_Y PORTF
+#define PORT_OUT_V7_Z PORTD
+#define PORT_OUT_V7_A PORTE
+
+// These next four must be changed when the PORT_MOTOR_* definitions change!
+#define PORTCFG_VP0MAP_PORT_MOTOR_1_gc PORTCFG_VP02MAP_PORTA_gc
+#define PORTCFG_VP1MAP_PORT_MOTOR_2_gc PORTCFG_VP13MAP_PORTF_gc
+#define PORTCFG_VP2MAP_PORT_MOTOR_3_gc PORTCFG_VP02MAP_PORTE_gc
+#define PORTCFG_VP3MAP_PORT_MOTOR_4_gc PORTCFG_VP13MAP_PORTD_gc
+
+#define PORT_MOTOR_1_VPORT VPORT0
+#define PORT_MOTOR_2_VPORT VPORT1
+#define PORT_MOTOR_3_VPORT VPORT2
+#define PORT_MOTOR_4_VPORT VPORT3
+
+/*
+ * Port setup - Stepper / Switch Ports:
+ * b0 (out) step (SET is step, CLR is rest)
+ * b1 (out) direction (CLR = Clockwise)
+ * b2 (out) motor enable (CLR = Enabled)
+ * b3 (out) chip select
+ * b4 (in) fault
+ * b5 (out) output bit for GPIO port1
+ * b6 (in) min limit switch on GPIO 2 *
+ * b7 (in) max limit switch on GPIO 2 *
+ * * motor controls and GPIO2 port mappings are not the same
+ */
+#define MOTOR_PORT_DIR_gm 0x2f // pin dir settings
+
+enum cfgPortBits { // motor control port bit positions
+ STEP_BIT_bp = 0, // bit 0
+ DIRECTION_BIT_bp, // bit 1
+ MOTOR_ENABLE_BIT_bp, // bit 2
+ CHIP_SELECT_BIT_bp, // bit 3
+ FAULT_BIT_bp, // bit 4
+ GPIO1_OUT_BIT_bp, // bit 5 (4 gpio1 output bits; 1 from each axis)
+ SW_MIN_BIT_bp, // bit 6 (4 input bits for homing/limit switches)
+ SW_MAX_BIT_bp // bit 7 (4 input bits for homing/limit switches)
+};
+
+#define STEP_BIT_bm (1 << STEP_BIT_bp)
+#define DIRECTION_BIT_bm (1 << DIRECTION_BIT_bp)
+#define MOTOR_ENABLE_BIT_bm (1 << MOTOR_ENABLE_BIT_bp)
+#define CHIP_SELECT_BIT_bm (1 << CHIP_SELECT_BIT_bp)
+#define FAULT_BIT_bm (1 << FAULT_BIT_bp)
+#define GPIO1_OUT_BIT_bm (1 << GPIO1_OUT_BIT_bp) // spindle and coolant
+#define SW_MIN_BIT_bm (1 << SW_MIN_BIT_bp) // minimum switch inputs
+#define SW_MAX_BIT_bm (1 << SW_MAX_BIT_bp) // maximum switch inputs
+
+// Bit assignments for GPIO1_OUTs for spindle, PWM and coolant
+#define SPINDLE_BIT 8 // spindle on/off
+#define SPINDLE_DIR 4 // spindle direction, 1=CW, 0=CCW
+#define SPINDLE_PWM 2 // spindle PWMs output bit
+#define MIST_COOLANT_BIT 1 // coolant on/off (same as flood)
+#define FLOOD_COOLANT_BIT 1 // coolant on/off (same as mist)
+
+#define SPINDLE_LED 0
+#define SPINDLE_DIR_LED 1
+#define SPINDLE_PWM_LED 2
+#define COOLANT_LED 3
+
+// Can use the spindle direction as an indicator LED
+#define INDICATOR_LED SPINDLE_DIR_LED
+
+/*
+ * Interrupt usage - TinyG uses a lot of them all over the place
+ *
+ * HI Stepper DDA pulse generation (set in stepper.h)
+ * HI Stepper load routine SW interrupt (set in stepper.h)
+ * HI Dwell timer counter (set in stepper.h)
+ * LO Segment execution SW interrupt (set in stepper.h)
+ * MED GPIO1 switch port (set in gpio.h)
+ * MED Serial RX (set in usart.c)
+ * MED Serial TX (set in usart.c) (* see note)
+ * LO Real time clock interrupt (set in xmega_rtc.h)
+ *
+ * (*) The TX cannot run at LO level or exception reports and other prints
+ * called from a LO interrupt (as in prep_line()) will kill the system
+ * in a permanent sleep_mode() call in usart_putc() (usart.c) as no
+ * interrupt can release the sleep mode.
+ */
+
+// Timer assignments - see specific modules for details
+#define TIMER_DDA TCC0 // DDA timer (see stepper.h)
+#define TIMER_TMC2660 TCC1 // TMC2660 timer (see tmc2660.h)
+#define TIMER_PWM1 TCD1 // PWM timer #1 (see pwm.c)
+#define TIMER_PWM2 TCD1 // PWM timer #2 (see pwm.c)
+#define TIMER_MOTOR1 TCE1
+#define TIMER_MOTOR2 TCF0
+#define TIMER_MOTOR3 TCE0
+#define TIMER_MOTOR4 TCD0
+
+// Timer setup for stepper and dwells
+#define FREQUENCY_DDA STEP_CLOCK_FREQ // DDA frequency in hz.
+#define STEP_TIMER_DISABLE 0 // turn timer off
+#define STEP_TIMER_ENABLE 1 // turn timer clock on
+#define STEP_TIMER_WGMODE 0 // normal mode (count to TOP and rollover)
+#define TIMER_DDA_ISR_vect TCC0_OVF_vect
+#define TIMER_DDA_INTLVL 3 // Timer overflow HI
+
+#define PWM1_CTRLB (3 | TC1_CCBEN_bm) // single slope PWM channel B
+#define PWM1_ISR_vect TCD1_CCB_vect
+#define PWM2_CTRLA_CLKSEL TC_CLKSEL_DIV1_gc
+#define PWM2_CTRLB 3 // single slope PWM no output
+#define PWM2_ISR_vect TCE1_CCB_vect
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-#ifndef CONTROLLER_H
-#define CONTROLLER_H
+#pragma once
+
#include "status.h"
void controller_init();
void controller_run();
-#endif // CONTROLLER_H
+
* The majority of the magic tricks used in this file are based on those
* described by pfultz2 in his "Cloak" library:
*
- * https://github.com/pfultz2/Cloak/wiki/C-Preprocessor-tricks,-tips,-and-idioms
+ * https://github.com/pfultz2/Cloak/wiki/C-Preprocessor-tricks,-tips,-and-idioms
*
* Major differences are a greater level of detailed explanation in this
* implementation and also a refusal to include any macros which require a O(N)
* macro definitions to handle O(N) arguments (with the exception of DEFERn).
*/
-#ifndef CPP_MAGIC_H
-#define CPP_MAGIC_H
+#pragma once
/**
- * Force the pre-processor to expand the macro a large number of times. Usage:
+ * Force the pre-processor to expand the macro a large number of times.
+ * Usage:
*
* EVAL(expression)
*
- * This is useful when you have a macro which evaluates to a valid macro
- * expression which is not subsequently expanded in the same pass. A contrived,
- * but easy to understand, example of such a macro follows. Note that though
- * this example is contrived, this behaviour is abused to implement bounded
- * recursion in macros such as FOR.
+ * This is useful when you have a macro which evaluates to a valid
+ * macro expression which is not subsequently expanded in the same
+ * pass. A contrived, but easy to understand, example of such a macro
+ * follows. Note that though this example is contrived, this behaviour
+ * is abused to implement bounded recursion in macros such as FOR.
*
* #define A(x) x+1
* #define EMPTY
*
* Here's what happens inside the C preprocessor:
*
- * 1. It sees a macro "NOT_QUITE_RIGHT" and performs a single macro expansion
- * pass on its arguments. Since the argument is "999" and this isn't a macro,
- * this is a boring step resulting in no change.
- * 2. The NOT_QUITE_RIGHT macro is substituted for its definition giving "A
- * EMPTY() (x)".
- * 3. The expander moves from left-to-right trying to expand the macro:
- * The first token, A, cannot be expanded since there are no brackets
- * immediately following it. The second token EMPTY(), however, can be
- * expanded (recursively in this manner) and is replaced with "".
- * 4. Expansion continues from the start of the substituted test (which in this
- * case is just empty), and sees "(999)" but since no macro name is present,
- * nothing is done. This results in a final expansion of "A (999)".
- *
- * Unfortunately, this doesn't quite meet expectations since you may expect that
- * "A (999)" would have been expanded into "999+1". Unfortunately this requires
- * a second expansion pass but luckily we can force the macro processor to make
- * more passes by abusing the first step of macro expansion: the preprocessor
- * expands arguments in their own pass. If we define a macro which does nothing
- * except produce its arguments e.g.:
+ * 1. It sees a macro "NOT_QUITE_RIGHT" and performs a single macro
+ * expansion pass on its arguments. Since the argument is "999" and
+ * this isn't a macro, this is a boring step resulting in no
+ * change.
+ *
+ * 2. The NOT_QUITE_RIGHT macro is substituted for its definition
+ * giving "A EMPTY() (x)".
+ *
+ * 3. The expander moves from left-to-right trying to expand the
+ * macro: The first token, A, cannot be expanded since there are no
+ * brackets immediately following it. The second token EMPTY(),
+ * however, can be expanded (recursively in this manner) and is
+ * replaced with "".
+ *
+ * 4. Expansion continues from the start of the substituted test
+ * (which in this case is just empty), and sees "(999)" but since
+ * no macro name is present, nothing is done. This results in a
+ * final expansion of "A (999)".
+ *
+ * Unfortunately, this doesn't quite meet expectations since you may
+ * expect that "A (999)" would have been expanded into
+ * "999+1". Unfortunately this requires a second expansion pass but
+ * luckily we can force the macro processor to make more passes by
+ * abusing the first step of macro expansion: the preprocessor expands
+ * arguments in their own pass. If we define a macro which does
+ * nothing except produce its arguments e.g.:
*
* #define PASS_THROUGH(...) __VA_ARGS__
*
- * We can now do "PASS_THROUGH(NOT_QUITE_RIGHT(999))" causing "NOT_QUITE_RIGHT" to be
- * expanded to "A (999)", as described above, when the arguments are expanded.
- * Now when the body of PASS_THROUGH is expanded, "A (999)" gets expanded to
- * "999+1".
+ * We can now do "PASS_THROUGH(NOT_QUITE_RIGHT(999))" causing
+ * "NOT_QUITE_RIGHT" to be expanded to "A (999)", as described above,
+ * when the arguments are expanded. Now when the body of PASS_THROUGH
+ * is expanded, "A (999)" gets expanded to "999+1".
*
- * The EVAL defined below is essentially equivalent to a large nesting of
- * "PASS_THROUGH(PASS_THROUGH(PASS_THROUGH(..." which results in the
- * preprocessor making a large number of expansion passes over the given
- * expression.
+ * The EVAL defined below is essentially equivalent to a large nesting
+ * of "PASS_THROUGH(PASS_THROUGH(PASS_THROUGH(..." which results in
+ * the preprocessor making a large number of expansion passes over the
+ * given expression.
*/
#define EVAL(...) EVAL1024(__VA_ARGS__)
#define EVAL1024(...) EVAL512(EVAL512(__VA_ARGS__))
#define DEFER5(id) id EMPTY EMPTY EMPTY EMPTY EMPTY()()()()()
#define DEFER6(id) id EMPTY EMPTY EMPTY EMPTY EMPTY EMPTY()()()()()()
#define DEFER7(id) id EMPTY EMPTY EMPTY EMPTY EMPTY EMPTY EMPTY()()()()()()()
-#define DEFER8(id) id EMPTY EMPTY EMPTY EMPTY EMPTY EMPTY EMPTY EMPTY()()()()()()()()
+#define DEFER8(id) \
+ id EMPTY EMPTY EMPTY EMPTY EMPTY EMPTY EMPTY EMPTY()()()()()()()()
/**
/**
* Logical negation. 0 is defined as false and everything else as true.
*
- * When 0, _NOT_0 will be found which evaluates to the PROBE. When 1 (or any other
- * value) is given, an appropriately named macro won't be found and the
- * concatenated string will be produced. IS_PROBE then simply checks to see if
- * the PROBE was returned, cleanly converting the argument into a 1 or 0.
+ * When 0, _NOT_0 will be found which evaluates to the PROBE. When 1
+ * (or any other value) is given, an appropriately named macro won't
+ * be found and the concatenated string will be produced. IS_PROBE
+ * then simply checks to see if the PROBE was returned, cleanly
+ * converting the argument into a 1 or 0.
*/
#define NOT(x) IS_PROBE(CAT(_NOT_, x))
#define _NOT_0 PROBE()
*
* Important tricks used:
*
- * * If we directly produce "MAP_INNER" in an expansion of MAP_INNER, a special
- * case in the preprocessor will prevent it being expanded in the future, even
- * if we EVAL. As a result, the MAP_INNER macro carefully only expands to
- * something containing "_MAP_INNER()" which requires a further expansion step
- * to invoke MAP_INNER and thus implementing the recursion.
- * * To prevent _MAP_INNER being expanded within the macro we must first defer its
- * expansion during its initial pass as an argument to _IF_0 or _IF_1. We must
- * then defer its expansion a second time as part of the body of the _IF_0. As
- * a result hence the DEFER2.
- * * _MAP_INNER seemingly gets away with producing itself because it actually only
- * produces MAP_INNER. It just happens that when _MAP_INNER() is expanded in
- * this case it is followed by some arguments which get consumed by MAP_INNER
- * and produce a _MAP_INNER. As such, the macro expander never marks
- * _MAP_INNER as expanding to itself and thus it will still be expanded in
+ * * If we directly produce "MAP_INNER" in an expansion of MAP_INNER,
+ * a special case in the preprocessor will prevent it being expanded
+ * in the future, even if we EVAL. As a result, the MAP_INNER macro
+ * carefully only expands to something containing "_MAP_INNER()"
+ * which requires a further expansion step to invoke MAP_INNER and
+ * thus implementing the recursion.
+ *
+ * * To prevent _MAP_INNER being expanded within the macro we must
+ * first defer its expansion during its initial pass as an argument
+ * to _IF_0 or _IF_1. We must then defer its expansion a second time
+ * as part of the body of the _IF_0. As a result hence the DEFER2.
+ *
+ * * _MAP_INNER seemingly gets away with producing itself because it
+ * actually only produces MAP_INNER. It just happens that when
+ * _MAP_INNER() is expanded in this case it is followed by some
+ * arguments which get consumed by MAP_INNER and produce a
+ * _MAP_INNER. As such, the macro expander never marks _MAP_INNER
+ * as expanding to itself and thus it will still be expanded in
* future productions of itself.
*/
#define MAP(...) \
*
* Which expands to:
*
- * static int I; static int II; static int III; static bool IIII; static char IIIII;
+ * static int I; static int II; static int III; static bool IIII;
+ * static char IIIII;
*
* The mechanism is analogous to the MAP macro.
*/
* #define SIMON_SAYS_LAST_OP(val) last_but_not_least_##val
* #define SIMON_SAYS() 0
*
- * MAP_SLIDE(SIMON_SAYS_OP, SIMON_SAYS_LAST_OP, EMPTY, wiggle, SIMON_SAYS, dance, move, SIMON_SAYS, boogie, stop)
+ * MAP_SLIDE(SIMON_SAYS_OP, SIMON_SAYS_LAST_OP, EMPTY, wiggle, SIMON_SAYS,
+ * dance, move, SIMON_SAYS, boogie, stop)
*
* Which expands to:
*
#define _EMAP2_INNER() EMAP2_INNER
-
-#endif
* recompute the body of moveB, but it may not be worth the trouble).
*/
-#ifndef ENCODER_H
-#define ENCODER_H
+#pragma once
+
#include "config.h"
void en_set_encoder_steps(uint8_t motor, float steps);
float en_read_encoder(uint8_t motor);
-#endif // ENCODER_H
+
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-#ifndef GCODE_PARSER_H
-#define GCODE_PARSER_H
+#pragma once
+
#include "status.h"
stat_t gc_gcode_parser(char *block);
-#endif // GCODE_PARSER_H
+
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-#ifndef GPIO_H
-#define GPIO_H
+#pragma once
+
#include <stdint.h>
void gpio_set_bit_off(uint8_t b);
void gpio_set_bit_toggle(uint8_t b);
-#endif // GPIO_H
+
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-/*
- * Interrupt usage - TinyG uses a lot of them all over the place
- *
- * HI Stepper DDA pulse generation (set in stepper.h)
- * HI Stepper load routine SW interrupt (set in stepper.h)
- * HI Dwell timer counter (set in stepper.h)
- * LO Segment execution SW interrupt (set in stepper.h)
- * MED GPIO1 switch port (set in gpio.h)
- * MED Serial RX (set in usart.c)
- * MED Serial TX (set in usart.c) (* see note)
- * LO Real time clock interrupt (set in xmega_rtc.h)
- *
- * (*) The TX cannot run at LO level or exception reports and other prints
- * called from a LO interrupt (as in prep_line()) will kill the system
- * in a permanent sleep_mode() call in usart_putc() (usart.c) as no
- * interrupt can release the sleep mode.
- */
+#pragma once
-#ifndef HARDWARE_H
-#define HARDWARE_H
#include "status.h"
#include "config.h"
-#include <avr/interrupt.h>
-
-#define MILLISECONDS_PER_TICK 1 // MS for system tick (systick * N)
-#define SYS_ID_LEN 12 // length of system ID string from sys_get_id()
-
-
-// Clock Crystal Config. Pick one:
-//#define __CLOCK_INTERNAL_32MHZ TRUE // use internal oscillator
-//#define __CLOCK_EXTERNAL_8MHZ TRUE // uses PLL to provide 32 MHz system clock
-#define __CLOCK_EXTERNAL_16MHZ TRUE // uses PLL to provide 32 MHz system clock
-
-// Motor, output bit & switch port assignments
-// These are not all the same, and must line up in multiple places in gpio.h
-// Sorry if this is confusing - it's a board routing issue
-#define PORT_MOTOR_1 PORTA // motors mapped to ports
-#define PORT_MOTOR_2 PORTF
-#define PORT_MOTOR_3 PORTE
-#define PORT_MOTOR_4 PORTD
-
-#define PORT_SWITCH_X PORTA // Switch axes mapped to ports
-#define PORT_SWITCH_Y PORTD
-#define PORT_SWITCH_Z PORTE
-#define PORT_SWITCH_A PORTF
-
-#define PORT_OUT_V7_X PORTA // v7 mapping
-#define PORT_OUT_V7_Y PORTF
-#define PORT_OUT_V7_Z PORTD
-#define PORT_OUT_V7_A PORTE
-
-// These next four must be changed when the PORT_MOTOR_* definitions change!
-#define PORTCFG_VP0MAP_PORT_MOTOR_1_gc PORTCFG_VP02MAP_PORTA_gc
-#define PORTCFG_VP1MAP_PORT_MOTOR_2_gc PORTCFG_VP13MAP_PORTF_gc
-#define PORTCFG_VP2MAP_PORT_MOTOR_3_gc PORTCFG_VP02MAP_PORTE_gc
-#define PORTCFG_VP3MAP_PORT_MOTOR_4_gc PORTCFG_VP13MAP_PORTD_gc
-
-#define PORT_MOTOR_1_VPORT VPORT0
-#define PORT_MOTOR_2_VPORT VPORT1
-#define PORT_MOTOR_3_VPORT VPORT2
-#define PORT_MOTOR_4_VPORT VPORT3
-
-/*
- * Port setup - Stepper / Switch Ports:
- * b0 (out) step (SET is step, CLR is rest)
- * b1 (out) direction (CLR = Clockwise)
- * b2 (out) motor enable (CLR = Enabled)
- * b3 (out) chip select
- * b4 (in) fault
- * b5 (out) output bit for GPIO port1
- * b6 (in) min limit switch on GPIO 2 *
- * b7 (in) max limit switch on GPIO 2 *
- * * motor controls and GPIO2 port mappings are not the same
- */
-#define MOTOR_PORT_DIR_gm 0x2f // pin dir settings
-
-enum cfgPortBits { // motor control port bit positions
- STEP_BIT_bp = 0, // bit 0
- DIRECTION_BIT_bp, // bit 1
- MOTOR_ENABLE_BIT_bp, // bit 2
- CHIP_SELECT_BIT_bp, // bit 3
- FAULT_BIT_bp, // bit 4
- GPIO1_OUT_BIT_bp, // bit 5 (4 gpio1 output bits; 1 from each axis)
- SW_MIN_BIT_bp, // bit 6 (4 input bits for homing/limit switches)
- SW_MAX_BIT_bp // bit 7 (4 input bits for homing/limit switches)
-};
-
-#define STEP_BIT_bm (1 << STEP_BIT_bp)
-#define DIRECTION_BIT_bm (1 << DIRECTION_BIT_bp)
-#define MOTOR_ENABLE_BIT_bm (1 << MOTOR_ENABLE_BIT_bp)
-#define CHIP_SELECT_BIT_bm (1 << CHIP_SELECT_BIT_bp)
-#define FAULT_BIT_bm (1 << FAULT_BIT_bp)
-#define GPIO1_OUT_BIT_bm (1 << GPIO1_OUT_BIT_bp) // spindle and coolant
-#define SW_MIN_BIT_bm (1 << SW_MIN_BIT_bp) // minimum switch inputs
-#define SW_MAX_BIT_bm (1 << SW_MAX_BIT_bp) // maximum switch inputs
-
-// Bit assignments for GPIO1_OUTs for spindle, PWM and coolant
-#define SPINDLE_BIT 8 // spindle on/off
-#define SPINDLE_DIR 4 // spindle direction, 1=CW, 0=CCW
-#define SPINDLE_PWM 2 // spindle PWMs output bit
-#define MIST_COOLANT_BIT 1 // coolant on/off (same as flood)
-#define FLOOD_COOLANT_BIT 1 // coolant on/off (same as mist)
-
-#define SPINDLE_LED 0
-#define SPINDLE_DIR_LED 1
-#define SPINDLE_PWM_LED 2
-#define COOLANT_LED 3
-
-// Can use the spindle direction as an indicator LED
-#define INDICATOR_LED SPINDLE_DIR_LED
-
-// Timer assignments - see specific modules for details
-#define TIMER_DDA TCC0 // DDA timer (see stepper.h)
-#define TIMER_TMC2660 TCC1 // TMC2660 timer (see tmc2660.h)
-#define TIMER_PWM1 TCD1 // PWM timer #1 (see pwm.c)
-#define TIMER_PWM2 TCD1 // PWM timer #2 (see pwm.c)
-#define TIMER_MOTOR1 TCE1
-#define TIMER_MOTOR2 TCF0
-#define TIMER_MOTOR3 TCE0
-#define TIMER_MOTOR4 TCD0
-
-// Timer setup for stepper and dwells
-#define FREQUENCY_DDA 25000 // DDA frequency in hz.
-#define STEP_TIMER_DISABLE 0 // turn timer off
-#define STEP_TIMER_ENABLE 1 // turn timer clock on
-#define STEP_TIMER_WGMODE 0 // normal mode (count to TOP and rollover)
-#define TIMER_DDA_ISR_vect TCC0_OVF_vect
-#define TIMER_DDA_INTLVL 3 // Timer overflow HI
-
-#define PWM1_CTRLB (3 | TC1_CCBEN_bm) // single slope PWM channel B
-#define PWM1_ISR_vect TCD1_CCB_vect
-#define PWM2_CTRLA_CLKSEL TC_CLKSEL_DIV1_gc
-#define PWM2_CTRLB 3 // single slope PWM no output
-#define PWM2_ISR_vect TCE1_CCB_vect
-
/*
Device singleton - global structure to allow iteration through similar devices
void hw_request_bootloader();
stat_t hw_bootloader_handler();
-
-#endif // HARDWARE_H
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-#ifndef PLAN_ARC_H
-#define PLAN_ARC_H
+#pragma once
+
#include "canonical_machine.h"
stat_t cm_arc_callback();
void cm_abort_arc();
-#endif // PLAN_ARC_H
+
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-#ifndef KINEMATICS_H
-#define KINEMATICS_H
+#pragma once
+
void ik_kinematics(const float travel[], float steps[]);
-#endif // KINEMATICS_H
+
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-#ifndef PLANNER_H
-#define PLANNER_H
+#pragma once
+
#include "canonical_machine.h" // used for GCodeState_t
#include "util.h"
void mp_queue_command(cm_exec_t, float *value, float *flag);
void mp_runtime_command(mpBuf_t *bf);
-#endif // PLANNER_H
+
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-#ifndef PWM_H
-#define PWM_H
+#pragma once
+
#include "config.h"
#include "status.h"
stat_t pwm_set_freq(uint8_t channel, float freq);
stat_t pwm_set_duty(uint8_t channel, float duty);
-#endif // PWM_H
+
\******************************************************************************/
-#ifndef REPORT_H
-#define REPORT_H
+#pragma once
+
#include "status.h"
void report_request_full();
stat_t report_callback();
-#endif // REPORT_H
+
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-#ifndef RTC_H
-#define RTC_H
+#pragma once
+
#include <stdint.h>
void rtc_init(); // initialize and start general timer
uint32_t rtc_get_time();
-#endif // RTC_H
+
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-#ifndef SPINDLE_H
-#define SPINDLE_H
+#pragma once
+
#include "status.h"
stat_t cm_spindle_control(uint8_t spindle_mode); // M3, M4, M5
void cm_exec_spindle_control(uint8_t spindle_mode); // callback for above
-#endif // SPINDLE_H
+
\******************************************************************************/
-#ifndef STATUS_H
-#define STATUS_H
+#pragma once
+
/************************************************************************************
* STATUS CODES
// !!! Do not exceed 255 without also changing stat_t typedef
-#endif // STATUS_H
+
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-#ifndef STEPPER_H
-#define STEPPER_H
+#pragma once
+
/*
* Coordinated motion (line drawing) is performed using a classic
stat_t st_prep_line(float travel_steps[], float following_error[],
float segment_time);
-#endif // STEPPER_H
+
* Read switch contains the results of read pin and manages edges and
* debouncing.
*/
-#ifndef SWITCH_H
-#define SWITCH_H
+#pragma once
+
#include <stdint.h>
void set_switch_type(uint8_t switch_type);
uint8_t get_switch_type();
-#endif // SWITCH_H
+
\******************************************************************************/
-#ifndef TMC2660_H
-#define TMC2660_H
+#pragma once
+
#include "config.h"
#define TMC2660_DRVSTATUS_OT (1UL << 1)
#define TMC2660_DRVSTATUS_SG (1UL << 0)
-#endif // TMC2660_H
+
\******************************************************************************/
-#ifndef USART_H
-#define USART_H
+#pragma once
+
#include <stdint.h>
inline int usart_tx_empty() {return !usart_tx_fill();}
inline int usart_tx_full() {return !usart_tx_space();}
-#endif // USART_H
+
* - support for debugging routines
*/
-#ifndef UTIL_H
-#define UTIL_H
+#pragma once
+
#include "config.h"
#define M_SQRT3 (1.73205080756888)
#endif
-#endif // UTIL_H
+