/** \file \brief I/O primitives - step, enable, direction, endstops etc */ #ifndef _PINIO_H #define _PINIO_H #include "config_wrapper.h" #ifndef MASK /// MASKING- returns \f$2^PIN\f$ #define MASK(PIN) (1 << PIN) #endif /** Magic I/O routines, also known as "FastIO". Now you can simply SET_OUTPUT(STEP); WRITE(STEP, 1); WRITE(STEP, 0);. The point here is to move any pin/port mapping calculations into the preprocessor. This way there is no longer math at runtime neccessary, all instructions melt into a single one with fixed numbers. This makes code for setting a pin small, smaller than calling a subroutine. It also make code fast, on AVR a pin can be turned on and off in just two clock cycles. */ #if defined __AVR__ #include /// Read a pin. #define _READ(IO) (IO ## _RPORT & MASK(IO ## _PIN)) /// Write to a pin. #define _WRITE(IO, v) do { if (v) { IO ## _WPORT |= MASK(IO ## _PIN); } \ else { IO ## _WPORT &= ~MASK(IO ## _PIN); }; } \ while (0) /// Toggle a pin. #define _TOGGLE(IO) do { IO ## _RPORT = MASK(IO ## _PIN); } while (0) /// Set pin as input. #define _SET_INPUT(IO) do { IO ## _DDR &= ~MASK(IO ## _PIN); } while (0) /// Set pin as output. #define _SET_OUTPUT(IO) do { IO ## _DDR |= MASK(IO ## _PIN); } while (0) /// Check if pin is an input. #define _GET_INPUT(IO) ((IO ## _DDR & MASK(IO ## _PIN)) == 0) /// Check if pin is an output. #define _GET_OUTPUT(IO) ((IO ## _DDR & MASK(IO ## _PIN)) != 0) #elif defined SIMULATOR #include "simulator.h" bool _READ(pin_t pin); void _WRITE(pin_t pin, bool on); void _TOGGLE(pin_t pin); void _SET_OUTPUT(pin_t pin); void _SET_INPUT(pin_t pin); #endif /* __AVR__, SIMULATOR */ /** Why double up on these macros? See http://gcc.gnu.org/onlinedocs/cpp/Stringification.html */ /// Read a pin wrapper. #define READ(IO) _READ(IO) /// Write to a pin wrapper. #define WRITE(IO, v) _WRITE(IO, v) /// Toggle a pin wrapper. #define TOGGLE(IO) _TOGGLE(IO) /// Set pin as input wrapper. #define SET_INPUT(IO) _SET_INPUT(IO) /// Set pin as output wrapper. #define SET_OUTPUT(IO) _SET_OUTPUT(IO) /// Check if pin is an input wrapper. #define GET_INPUT(IO) _GET_INPUT(IO) /// Check if pin is an output wrapper. #define GET_OUTPUT(IO) _GET_OUTPUT(IO) /* Power */ /// psu_timeout is set to zero when we step, and increases over time so we can /// turn the motors off when they've been idle for a while. /// A second function is to guarantee a minimum on time of the PSU. /// Timeout counting is done in clock.c. /// It is used inside and outside of interrupts, which is why it has been made volatile extern volatile uint8_t psu_timeout; static void power_init(void); inline void power_init(void) { #ifdef PS_MOSFET_PIN WRITE(PS_MOSFET_PIN, 0); SET_OUTPUT(PS_MOSFET_PIN); #endif } void power_on(void); void power_off(void); /* X Stepper */ #define _x_step(st) WRITE(X_STEP_PIN, st) #define x_step() _x_step(1) #ifndef X_INVERT_DIR #define x_direction(dir) WRITE(X_DIR_PIN, dir) #else #define x_direction(dir) WRITE(X_DIR_PIN, (dir)^1) #endif #ifdef X_MIN_PIN #ifndef X_INVERT_MIN #define x_min() (READ(X_MIN_PIN)?1:0) #else #define x_min() (READ(X_MIN_PIN)?0:1) #endif #else #define x_min() (0) #endif #ifdef X_MAX_PIN #ifndef X_INVERT_MAX #define x_max() (READ(X_MAX_PIN)?1:0) #else #define x_max() (READ(X_MAX_PIN)?0:1) #endif #else #define x_max() (0) #endif /* Y Stepper */ #define _y_step(st) WRITE(Y_STEP_PIN, st) #define y_step() _y_step(1) #ifndef Y_INVERT_DIR #define y_direction(dir) WRITE(Y_DIR_PIN, dir) #else #define y_direction(dir) WRITE(Y_DIR_PIN, (dir)^1) #endif #ifdef Y_MIN_PIN #ifndef Y_INVERT_MIN #define y_min() (READ(Y_MIN_PIN)?1:0) #else #define y_min() (READ(Y_MIN_PIN)?0:1) #endif #else #define y_min() (0) #endif #ifdef Y_MAX_PIN #ifndef Y_INVERT_MAX #define y_max() (READ(Y_MAX_PIN)?1:0) #else #define y_max() (READ(Y_MAX_PIN)?0:1) #endif #else #define y_max() (0) #endif /* Z Stepper */ #if defined Z_STEP_PIN && defined Z_DIR_PIN #define _z_step(st) WRITE(Z_STEP_PIN, st) #define z_step() _z_step(1) #ifndef Z_INVERT_DIR #define z_direction(dir) WRITE(Z_DIR_PIN, dir) #else #define z_direction(dir) WRITE(Z_DIR_PIN, (dir)^1) #endif #else #define _z_step(x) do { } while (0) #define z_step() do { } while (0) #define z_direction(x) do { } while (0) #endif #ifdef Z_MIN_PIN #ifndef Z_INVERT_MIN #define z_min() (READ(Z_MIN_PIN)?1:0) #else #define z_min() (READ(Z_MIN_PIN)?0:1) #endif #else #define z_min() (0) #endif #ifdef Z_MAX_PIN #ifndef Z_INVERT_MAX #define z_max() (READ(Z_MAX_PIN)?1:0) #else #define z_max() (READ(Z_MAX_PIN)?0:1) #endif #else #define z_max() (0) #endif /* Extruder */ #if defined E_STEP_PIN && defined E_DIR_PIN #define _e_step(st) WRITE(E_STEP_PIN, st) #define e_step() _e_step(1) #ifndef E_INVERT_DIR #define e_direction(dir) WRITE(E_DIR_PIN, dir) #else #define e_direction(dir) WRITE(E_DIR_PIN, (dir)^1) #endif #else #define _e_step(st) do { } while (0) #define e_step() do { } while (0) #define e_direction(dir) do { } while (0) #endif /* End Step - All Steppers (so we don't have to delay in interrupt context) */ #define unstep() do { _x_step(0); _y_step(0); _z_step(0); _e_step(0); } while (0) /* Stepper Enable Pins */ #ifdef STEPPER_ENABLE_PIN #ifdef STEPPER_INVERT_ENABLE #define stepper_enable() do { WRITE(STEPPER_ENABLE_PIN, 0); } while (0) #define stepper_disable() do { WRITE(STEPPER_ENABLE_PIN, 1); } while (0) #else #define stepper_enable() do { WRITE(STEPPER_ENABLE_PIN, 1); } while (0) #define stepper_disable() do { WRITE(STEPPER_ENABLE_PIN, 0); } while (0) #endif #else #define stepper_enable() do { } while (0) #define stepper_disable() do { } while (0) #endif #ifdef X_ENABLE_PIN #ifdef X_INVERT_ENABLE #define x_enable() do { WRITE(X_ENABLE_PIN, 0); } while (0) #define x_disable() do { WRITE(X_ENABLE_PIN, 1); } while (0) #else #define x_enable() do { WRITE(X_ENABLE_PIN, 1); } while (0) #define x_disable() do { WRITE(X_ENABLE_PIN, 0); } while (0) #endif #else #define x_enable() do { } while (0) #define x_disable() do { } while (0) #endif #ifdef Y_ENABLE_PIN #ifdef Y_INVERT_ENABLE #define y_enable() do { WRITE(Y_ENABLE_PIN, 0); } while (0) #define y_disable() do { WRITE(Y_ENABLE_PIN, 1); } while (0) #else #define y_enable() do { WRITE(Y_ENABLE_PIN, 1); } while (0) #define y_disable() do { WRITE(Y_ENABLE_PIN, 0); } while (0) #endif #else #define y_enable() do { } while (0) #define y_disable() do { } while (0) #endif #ifdef Z_ENABLE_PIN #ifdef Z_INVERT_ENABLE #define z_enable() do { WRITE(Z_ENABLE_PIN, 0); } while (0) #define z_disable() do { WRITE(Z_ENABLE_PIN, 1); } while (0) #else #define z_enable() do { WRITE(Z_ENABLE_PIN, 1); } while (0) #define z_disable() do { WRITE(Z_ENABLE_PIN, 0); } while (0) #endif #else #define z_enable() do { } while (0) #define z_disable() do { } while (0) #endif #ifdef E_ENABLE_PIN #ifdef E_INVERT_ENABLE #define e_enable() do { WRITE(E_ENABLE_PIN, 0); } while (0) #define e_disable() do { WRITE(E_ENABLE_PIN, 1); } while (0) #else #define e_enable() do { WRITE(E_ENABLE_PIN, 1); } while (0) #define e_disable() do { WRITE(E_ENABLE_PIN, 0); } while (0) #endif #else #define e_enable() do { } while (0) #define e_disable() do { } while (0) #endif /* Internal pullup resistors for endstops */ static void endstops_on(void) __attribute__ ((always_inline)); inline void endstops_on(void) { #ifdef USE_INTERNAL_PULLUPS #ifdef X_MIN_PIN WRITE(X_MIN_PIN, 1); #endif #ifdef X_MAX_PIN WRITE(X_MAX_PIN, 1); #endif #ifdef Y_MIN_PIN WRITE(Y_MIN_PIN, 1); #endif #ifdef Y_MAX_PIN WRITE(Y_MAX_PIN, 1); #endif #ifdef Z_MIN_PIN WRITE(Z_MIN_PIN, 1); #endif #ifdef Z_MAX_PIN WRITE(Z_MAX_PIN, 1); #endif #endif } static void endstops_off(void) __attribute__ ((always_inline)); inline void endstops_off(void) { #ifdef USE_INTERNAL_PULLUPS #ifdef X_MIN_PIN WRITE(X_MIN_PIN, 0); #endif #ifdef X_MAX_PIN WRITE(X_MAX_PIN, 0); #endif #ifdef Y_MIN_PIN WRITE(Y_MIN_PIN, 0); #endif #ifdef Y_MAX_PIN WRITE(Y_MAX_PIN, 0); #endif #ifdef Z_MIN_PIN WRITE(Z_MIN_PIN, 0); #endif #ifdef Z_MAX_PIN WRITE(Z_MAX_PIN, 0); #endif #endif } #endif /* _PINIO_H */