From 10819db219b1ea9406fa2c20e8add24f0b2a569f Mon Sep 17 00:00:00 2001 From: Terje Io Date: Sun, 7 Jun 2020 23:15:21 +0200 Subject: [PATCH] Updated for missing commit for Arduino based drivers for issue #56 and board name fix for STM32F1xx driver in issue #55. Initial version of encoder handling added to IMXRT1062 driver. --- drivers/IMXRT1062/main/cnc_boosterpack_map.h | 11 + drivers/IMXRT1062/main/driver.c | 210 +++++++++++++++++-- drivers/IMXRT1062/main/driver.h | 6 + drivers/SAM3X8E/main/cmcgrath_rev3_map.h | 2 + drivers/SAM3X8E/main/driver.c | 27 ++- drivers/SAM3X8E/main/ramps_1.6_map.h | 2 + drivers/SAMD21/main/driver.c | 31 ++- drivers/SAMD21/main/driver.h | 2 + drivers/STM32F1xx/Inc/cnc3040_map.h | 3 +- 9 files changed, 253 insertions(+), 41 deletions(-) diff --git a/drivers/IMXRT1062/main/cnc_boosterpack_map.h b/drivers/IMXRT1062/main/cnc_boosterpack_map.h index ca1668d6..64ccb6aa 100644 --- a/drivers/IMXRT1062/main/cnc_boosterpack_map.h +++ b/drivers/IMXRT1062/main/cnc_boosterpack_map.h @@ -19,6 +19,10 @@ along with Grbl. If not, see . */ +#include "driver.h" + +#define BOARD_NAME "CNC BoosterPack" + // Define step pulse output pins. #define X_STEP_PIN (32u) #define Y_STEP_PIN (30u) @@ -71,4 +75,11 @@ #define GPIO2_PIN (27u) #define GPIO3_PIN (2u) +#if QEI_ENABLE + #define QEI_A_PIN GPIO0_PIN + #define QEI_B_PIN GPIO3_PIN +// #define QEI_INDEX_PIN GPIO2_PIN + #define QEI_SELECT_PIN GPIO1_PIN +#endif + /* EOF */ diff --git a/drivers/IMXRT1062/main/driver.c b/drivers/IMXRT1062/main/driver.c index 56846aa5..787a59dd 100644 --- a/drivers/IMXRT1062/main/driver.c +++ b/drivers/IMXRT1062/main/driver.c @@ -33,6 +33,10 @@ #include "ioports.h" #endif +#if QEI_ENABLE +#include "src/encoder/encoder.h" +#endif + #if USB_SERIAL_GRBL == 1 #include "usb_serial_ard.h" #elif USB_SERIAL_GRBL == 2 @@ -83,14 +87,20 @@ typedef enum { Input_LimitB_Max, Input_LimitC, Input_LimitC_Max, - Input_KeypadStrobe + Input_KeypadStrobe, + Input_QEI_A, + Input_QEI_B, + Input_QEI_Select, + Input_QEI_Index, } input_t; -#define INPUT_GROUP_CONTROL (1 << 0) -#define INPUT_GROUP_PROBE (1 << 1) -#define INPUT_GROUP_LIMIT (1 << 2) -#define INPUT_GROUP_KEYPAD (1 << 3) -#define INPUT_GROUP_MPG (1 << 4) +#define INPUT_GROUP_CONTROL (1 << 0) +#define INPUT_GROUP_PROBE (1 << 1) +#define INPUT_GROUP_LIMIT (1 << 2) +#define INPUT_GROUP_KEYPAD (1 << 3) +#define INPUT_GROUP_MPG (1 << 4) +#define INPUT_GROUP_QEI (1 << 5) +#define INPUT_GROUP_QEI_SELECT (1 << 6) typedef enum { IRQ_Mode_None = 0b00, @@ -117,6 +127,23 @@ typedef struct { input_signal_t *signal[DEBOUNCE_QUEUE]; } debounce_queue_t; +typedef union { + uint_fast8_t pins; + struct { + uint_fast8_t a :1, + b :1; + }; +} qei_state_t; + +typedef struct { + encoder_t encoder; + qei_state_t state; + qei_state_t iflags; + bool initial_debounce; + volatile uint32_t debounce; +} qei_t; + +static qei_t qei = {0}; static debounce_queue_t debounce_queue = {0}; // Standard inputs @@ -153,6 +180,17 @@ static gpio_t KeypadStrobe; #if MPG_MODE_ENABLE static gpio_t ModeSelect; #endif +#if QEI_ENABLE +static gpio_t QEI_A, QEI_B; + #ifdef QEI_SELECT_PIN + #define QEI_SELECT_ENABLED 1 + static gpio_t QEI_Select; + #endif + #ifdef QEI_INDEX_PIN + #define QEI_INDEX_ENABLED 1 + static gpio_t QEI_Index; + #endif +#endif static input_signal_t inputpin[] = { #if ESTOP_ENABLE @@ -181,6 +219,16 @@ static input_signal_t inputpin[] = { #if KEYPAD_ENABLE , { .id = Input_KeypadStrobe, .port = &KeypadStrobe, .pin = KEYPAD_PIN, .group = INPUT_GROUP_KEYPAD } #endif +#if QEI_ENABLE + , { .id = Input_QEI_A, .port = &QEI_A, .pin = QEI_A_PIN, .group = INPUT_GROUP_QEI } + , { .id = Input_QEI_B, .port = &QEI_B, .pin = QEI_B_PIN, .group = INPUT_GROUP_QEI } + #if QEI_SELECT_ENABLED + , { .id = Input_QEI_Select, .port = &QEI_Select, .pin = QEI_SELECT_PIN, .group = INPUT_GROUP_QEI_SELECT } + #endif + #if QEI_INDEX_ENABLED + , { .id = Input_QEI_Index, .port = &QEI_Index, .pin = QEI_INDEX_PIN, .group = INPUT_GROUP_QEI } + #endif +#endif }; #define DIGITAL_OUT(gpio, on) { if(on) gpio.reg->DR_SET = gpio.bit; else gpio.reg->DR_CLEAR = gpio.bit; } @@ -432,10 +480,16 @@ static void probeConfigure (bool is_probe_away) probe_invert = !probe_invert; } -// Returns the probe pin state. Triggered = true. -bool probeGetState (void) +// Returns the probe connected and triggered pin states. +probe_state_t probeGetState (void) { - return ((Probe.reg->DR & Probe.bit) != 0) ^ probe_invert; + probe_state_t state = { + .connected = On + }; + + state.triggered = ((Probe.reg->DR & Probe.bit) != 0) ^ probe_invert; + + return state; } // Static spindle (off, on cw & on ccw) @@ -745,13 +799,35 @@ static void settings_changed (settings_t *settings) #endif #if MPG_MODE_ENABLE case Input_ModeSelect: - irq_mode = IRQ_Mode_Change; + signal->irq_mode = IRQ_Mode_Change; break; #endif #if KEYPAD_ENABLE case Input_KeypadStrobe: - irq_mode = IRQ_Mode_Change; + signal->irq_mode = IRQ_Mode_Change; + break; +#endif +#if QEI_ENABLE + case Input_QEI_A: + signal->irq_mode = IRQ_Mode_Change; + break; + + case Input_QEI_B: + signal->irq_mode = IRQ_Mode_Change; + break; + + #if QEI_INDEX_ENABLED + case Input_QEI_Index: + signal->irq_mode = IRQ_Mode_None; break; + #endif + + #if QEI_SELECT_ENABLED + case Input_QEI_Select: + signal->debounce = hal.driver_cap.software_debounce; + signal->irq_mode = IRQ_Mode_Falling; + break; + #endif #endif default: break; @@ -936,7 +1012,7 @@ static bool driver_setup (settings_t *settings) // Set defaults - IOInitDone = settings->version == 15; + IOInitDone = settings->version == 16; settings_changed(settings); @@ -975,7 +1051,7 @@ bool nvsWrite (uint8_t *source) #endif -#if KEYPAD_ENABLE || USB_SERIAL_GRBL > 0 +#if QEI_SELECT_ENABLED || KEYPAD_ENABLE || USB_SERIAL_GRBL > 0 static void execute_realtime (uint_fast16_t state) { #if USB_SERIAL_GRBL > 0 @@ -984,6 +1060,9 @@ static void execute_realtime (uint_fast16_t state) #if KEYPAD_ENABLE keypad_process_keypress(state); #endif +#if QEI_SELECT_ENABLED + encoder_execute_realtime(state); +#endif } #endif @@ -1027,8 +1106,11 @@ bool driver_init (void) if(*options != '\0') options[strlen(options) - 1] = '\0'; - hal.info = "Teensy 4.0"; // Typically set to MCU or board name - hal.driver_version = "200518"; + hal.info = "IMXRT1062"; + hal.driver_version = "200606"; +#ifdef BOARD_NAME + hal.board = BOARD_NAME; +#endif hal.driver_options = *options == '\0' ? NULL : options; hal.driver_setup = driver_setup; hal.f_step_timer = 24000000; @@ -1100,10 +1182,14 @@ bool driver_init (void) hal.clear_bits_atomic = bitsClearAtomic; hal.set_value_atomic = valueSetAtomic; -#if KEYPAD_ENABLE || USB_SERIAL_GRBL > 0 +#if QEI_SELECT_ENABLED || KEYPAD_ENABLE || USB_SERIAL_GRBL > 0 hal.execute_realtime = execute_realtime; #endif +#if QEI_ENABLE + hal.encoder_state_changed = encoder_changed; +#endif + #ifdef DEBUGOUT hal.debug_out = debugOut; #endif @@ -1223,6 +1309,16 @@ static void debounce_isr (void) if(grp & INPUT_GROUP_CONTROL) hal.control_interrupt_callback(systemGetState()); + +#if QEI_SELECT_ENABLED + + if(grp & INPUT_GROUP_QEI_SELECT) { + qei.encoder.changed.select = On; + hal.encoder_state_changed(&qei.encoder); + } + +#endif + } //GPIO intr process @@ -1253,8 +1349,19 @@ static void gpio_isr (void) if(inputpin[i].debounce && enqueue_debounce(&inputpin[i])) { inputpin[i].gpio.reg->IMR &= ~inputpin[i].gpio.bit; debounce = true; - } else + } else { +#if QEI_ENABLE + if(inputpin[i].group & INPUT_GROUP_QEI) { + QEI_A.reg->IMR &= ~QEI_A.bit; // Switch off + QEI_B.reg->IMR &= ~QEI_B.bit; // encoder interrupts. + qei.iflags.a = inputpin[i].port == &QEI_A; + qei.iflags.b = inputpin[i].port == &QEI_B; + qei.debounce = 1; + qei.initial_debounce = true; + } else +#endif grp |= inputpin[i].group; + } } } } while(i); @@ -1269,6 +1376,15 @@ static void gpio_isr (void) if(grp & INPUT_GROUP_CONTROL) hal.control_interrupt_callback(systemGetState()); +#if QEI_SELECT_ENABLED + + if(grp & INPUT_GROUP_QEI_SELECT) { + qei.encoder.changed.select = On; + hal.encoder_state_changed(&qei.encoder); + } + +#endif + #if MPG_MODE_ENABLE static bool mpg_mutex = false; @@ -1287,6 +1403,57 @@ static void gpio_isr (void) #endif } +#if QEI_ENABLE + +void encoder_debounce (void) +{ + qei.debounce = 1; + qei.initial_debounce = false; + qei.state.a = (QEI_A.reg->DR & QEI_A.bit) != 0; + qei.state.b = (QEI_B.reg->DR & QEI_B.bit) != 0; +} + +void encoder_update (void) +{ + qei_state_t state = {0}; + + state.a = (QEI_A.reg->DR & QEI_A.bit) != 0; + state.b = (QEI_B.reg->DR & QEI_B.bit) != 0; + + if(state.pins == qei.state.pins) { + + if(qei.iflags.a) { + + if(qei.state.a) + qei.encoder.position = qei.encoder.position + (qei.state.b ? 1 : -1); + else + qei.encoder.position = qei.encoder.position + (qei.state.b ? -1 : 1); + + qei.encoder.changed.position = hal.encoder_state_changed != NULL; + } + + if(qei.iflags.b) { + + if(qei.state.b) + qei.encoder.position = qei.encoder.position + (qei.state.a ? -1 : 1); + else + qei.encoder.position = qei.encoder.position + (qei.state.a ? 1 : -1); + + qei.encoder.changed.position = hal.encoder_state_changed != NULL; + } + + if(qei.encoder.changed.position) + hal.encoder_state_changed(&qei.encoder); + } + + // Clear and reenable encoder interrupts + QEI_A.reg->ISR = QEI_A.bit; + QEI_B.reg->ISR = QEI_B.bit; + QEI_A.reg->IMR |= QEI_A.bit; + QEI_B.reg->IMR |= QEI_B.bit; +} +#endif + // Interrupt handler for 1 ms interval timer static void systick_isr (void) { @@ -1295,6 +1462,15 @@ static void systick_isr (void) // usb_serial_poll(); #endif +#if QEI_ENABLE + if(qei.debounce && !(--qei.debounce)) { + if(qei.initial_debounce) + encoder_debounce(); + else + encoder_update(); + } +#endif + if(grbl_delay.ms && !(--grbl_delay.ms)) { if(grbl_delay.callback) { grbl_delay.callback(); diff --git a/drivers/IMXRT1062/main/driver.h b/drivers/IMXRT1062/main/driver.h index 26629275..d1edfccc 100644 --- a/drivers/IMXRT1062/main/driver.h +++ b/drivers/IMXRT1062/main/driver.h @@ -36,6 +36,8 @@ #define USB_SERIAL_GRBL 2 // Set to 1 for Arduino class library, 2 for PJRC C library. #define USB_SERIAL_WAIT 0 // Wait for USB connection before starting grblHAL. +#define QEI_ENABLE 0 // Enable quadrature encoder interface. NOTE: requires encoder plugin. + #if COMPATIBILITY_LEVEL <= 1 #define ESTOP_ENABLE 1 // When enabled only real-time report requests will be executed when the reset pin is asserted. #else @@ -157,6 +159,10 @@ extern driver_settings_t driver_settings; #error "SPINDLEPWMPIN can only be routed to pin 12 or 13!" #endif +#if QEI_ENABLE && !(defined(QEI_A_PIN) && defined(QEI_B_PIN)) + #error "QEI_ENABLE requires encoder input pins A and B to be defined!" +#endif + // The following struct is pulled from the Teensy Library core, Copyright (c) 2019 PJRC.COM, LLC. typedef struct { diff --git a/drivers/SAM3X8E/main/cmcgrath_rev3_map.h b/drivers/SAM3X8E/main/cmcgrath_rev3_map.h index ed92851f..1d2fc341 100644 --- a/drivers/SAM3X8E/main/cmcgrath_rev3_map.h +++ b/drivers/SAM3X8E/main/cmcgrath_rev3_map.h @@ -21,6 +21,8 @@ along with Grbl. If not, see . */ +#define BOARD_NAME "cmcgrath v3" + // Uncomment ONE line below to enable dual motors with auto squaring for axis // NOTE: if more than one is uncommented only the first will be honored. // NOTE: the max limit definitions for the enabled axis will be used as input for the second motor when homing. diff --git a/drivers/SAM3X8E/main/driver.c b/drivers/SAM3X8E/main/driver.c index 100f688b..bb17fc3f 100644 --- a/drivers/SAM3X8E/main/driver.c +++ b/drivers/SAM3X8E/main/driver.c @@ -607,18 +607,20 @@ static void probeConfigureInvertMask (bool is_probe_away) probe_invert = !probe_invert; } -// Returns the probe pin state. Triggered = true. -#ifdef PROBE_PIN -bool probeGetState (void) +// Returns the probe connected and triggered pin states. +probe_state_t probeGetState (void) { - return BITBAND_PERI(PROBE_PORT->PIO_PDSR, PROBE_PIN) ^ probe_invert; -} + probe_state_t state = { + .connected = On + }; + +#ifdef PROBE_PIN + state.triggered = BITBAND_PERI(PROBE_PORT->PIO_PDSR, PROBE_PIN) ^ probe_invert; #else -bool probeGetState (void) -{ - return false; -} + state.triggered = false; #endif + return state; +} // Static spindle (off, on cw & on ccw) @@ -1300,7 +1302,7 @@ static bool driver_setup (settings_t *settings) // Set defaults - IOInitDone = settings->version == 15; + IOInitDone = settings->version == 16; settings_changed(settings); @@ -1480,7 +1482,10 @@ bool driver_init (void) NVIC_EnableIRQ(SysTick_IRQn); hal.info = "SAM3X8E"; - hal.driver_version = "200411"; + hal.driver_version = "200528"; +#ifdef BOARD_NAME + hal.board = BOARD_NAME; +#endif hal.driver_setup = driver_setup; hal.f_step_timer = SystemCoreClock / 2; // 42 MHz hal.rx_buffer_size = RX_BUFFER_SIZE; diff --git a/drivers/SAM3X8E/main/ramps_1.6_map.h b/drivers/SAM3X8E/main/ramps_1.6_map.h index f4c449a6..06302f75 100644 --- a/drivers/SAM3X8E/main/ramps_1.6_map.h +++ b/drivers/SAM3X8E/main/ramps_1.6_map.h @@ -23,6 +23,8 @@ along with Grbl. If not, see . */ +#define BOARD_NAME "Ramps 1.6" + // Define step pulse output pins. #define X_STEP_PORT PIOA #define X_STEP_PIN 16 // Due Analog Pin 0 diff --git a/drivers/SAMD21/main/driver.c b/drivers/SAMD21/main/driver.c index d9ca81b1..e0d27684 100644 --- a/drivers/SAMD21/main/driver.c +++ b/drivers/SAMD21/main/driver.c @@ -289,19 +289,22 @@ static void probeConfigureInvertMask (bool is_probe_away) probe_invert = !probe_invert; } -// Returns the probe pin state. Triggered = true. -#ifdef PROBE_PIN -bool probeGetState (void) +// Returns the probe connected and triggered pin states. +probe_state_t probeGetState (void) { - return pinIn(PROBE_PIN) ^ probe_invert; -} + probe_state_t state = { + .connected = On + }; + +#ifdef PROBE_PIN + state.triggered = pinIn(PROBE_PIN) ^ probe_invert; #else -bool probeGetState (void) -{ - return false; -} + state.triggered = false; #endif + return state; +} + // Static spindle (off, on cw & on ccw) inline static void spindle_off (void) @@ -822,7 +825,7 @@ static bool driver_setup (settings_t *settings) // Set defaults - IOInitDone = settings->version == 15; + IOInitDone = settings->version == 16; settings_changed(settings); @@ -1006,7 +1009,10 @@ bool driver_init (void) { IRQRegister(SysTick_IRQn, SysTick_IRQHandler); hal.info = "SAMD21"; - hal.driver_version = "200307"; + hal.driver_version = "200528"; +#ifdef BOARD_NAME + hal.board = BOARD_NAME; +#endif hal.driver_setup = driver_setup; hal.f_step_timer = SystemCoreClock / 3; hal.rx_buffer_size = RX_BUFFER_SIZE; @@ -1116,6 +1122,9 @@ bool driver_init (void) { #endif // driver capabilities, used for announcing and negotiating (with Grbl) driver functionality +#ifdef SAFETY_DOOR_PIN + hal.driver_cap.safety_door = On; +#endif #ifdef SPINDLE_DIRECTION_PIN hal.driver_cap.spindle_dir = On; #endif diff --git a/drivers/SAMD21/main/driver.h b/drivers/SAMD21/main/driver.h index 17c29801..d5ad7deb 100644 --- a/drivers/SAMD21/main/driver.h +++ b/drivers/SAMD21/main/driver.h @@ -130,6 +130,8 @@ extern driver_settings_t driver_settings; #else // CNC Boosterpack pin assignments +#define BOARD_NAME "CNC BoosterPack" + // Define step pulse output pins. #define X_STEP_PIN (19u) #define Y_STEP_PIN (20u) diff --git a/drivers/STM32F1xx/Inc/cnc3040_map.h b/drivers/STM32F1xx/Inc/cnc3040_map.h index e53f26ff..a71f1ad7 100644 --- a/drivers/STM32F1xx/Inc/cnc3040_map.h +++ b/drivers/STM32F1xx/Inc/cnc3040_map.h @@ -19,8 +19,7 @@ #if N_AXIS == 5 #define BOARD_NAME "CNC 3040 5-axis" -#endif -#if N_AXIS == 4 +#elif N_AXIS == 4 #define BOARD_NAME "CNC 3040 4-axis" #else #define BOARD_NAME "CNC 3040"