From f0e1c4dd1bafea294fc991f3b60ff50b4d5274bd Mon Sep 17 00:00:00 2001 From: Terje Io Date: Sun, 27 Jun 2021 21:02:38 +0200 Subject: [PATCH] Updated to use encapsulated stream code and stadardized motor allocations. Added support for Bluetooth plugin. --- grblHAL_Teensy4/src/T40X101_map.h | 88 ++-- grblHAL_Teensy4/src/T41BB5X_Pro_map.h | 95 ++-- grblHAL_Teensy4/src/T41U5XBB_map.h | 102 ++--- grblHAL_Teensy4/src/T41U5XBB_ss_map.h | 102 ++--- grblHAL_Teensy4/src/cnc_boosterpack_map.h | 6 +- grblHAL_Teensy4/src/driver.c | 404 +++++++++--------- grblHAL_Teensy4/src/driver.h | 125 +----- grblHAL_Teensy4/src/enet.c | 8 +- grblHAL_Teensy4/src/generic_map.h | 44 +- grblHAL_Teensy4/src/{T41U5XBB.c => ioports.c} | 149 +++++-- grblHAL_Teensy4/src/my_machine.h | 20 +- grblHAL_Teensy4/src/my_plugin.c | 75 ++++ grblHAL_Teensy4/src/uart.c | 257 ++++++----- grblHAL_Teensy4/src/uart.h | 18 +- grblHAL_Teensy4/src/usb_serial_ard.cpp | 74 ++-- grblHAL_Teensy4/src/usb_serial_ard.h | 18 +- grblHAL_Teensy4/src/usb_serial_pjrc.c | 58 ++- grblHAL_Teensy4/src/usb_serial_pjrc.h | 18 +- 18 files changed, 824 insertions(+), 837 deletions(-) rename grblHAL_Teensy4/src/{T41U5XBB.c => ioports.c} (52%) create mode 100644 grblHAL_Teensy4/src/my_plugin.c diff --git a/grblHAL_Teensy4/src/T40X101_map.h b/grblHAL_Teensy4/src/T40X101_map.h index 45a0320..fa5faa9 100644 --- a/grblHAL_Teensy4/src/T40X101_map.h +++ b/grblHAL_Teensy4/src/T40X101_map.h @@ -23,81 +23,49 @@ #define BOARD_NAME "T40X101" -#if N_AXIS > 4 -#error Max number of axes is 4 for T40X101 +#if N_ABC_MOTORS > 2 +#error "Axis configuration is not supported!" #endif #if QEI_ENABLE -#error No pins available for encoder input! +#error "No pins available for encoder input!" #endif #if SPINDLE_SYNC_ENABLE -#error Spindle sync is not supported for T40X101 +#error "Spindle sync is not supported for T40X101!" #endif -// Default pin assignments allow only one axis to be ganged or auto squared. -// A axis pin numbers are used for the ganged/auto squared axis. -// If a second axis is to be ganged/auto squared pin assignments needs to be changed! -// Set to 1 to enable, 0 to disable. -#define X_GANGED 0 -#define X_AUTO_SQUARE 0 -#define Y_GANGED 0 -#define Y_AUTO_SQUARE 0 -#define Z_GANGED 0 -#define Z_AUTO_SQUARE 0 -// +#define X_STEP_PIN (2u) +#define X_DIRECTION_PIN (3u) +#define X_LIMIT_PIN (20u) -#define X_STEP_PIN (2u) -#define X_DIRECTION_PIN (3u) -#define X_LIMIT_PIN (20u) +#define Y_STEP_PIN (4u) +#define Y_DIRECTION_PIN (5u) +#define Y_LIMIT_PIN (21u) -#if X_GANGED || X_AUTO_SQUARE -#define X2_STEP_PIN (8u) -#define X2_DIRECTION_PIN (9u) -#if X_AUTO_SQUARE - #define X2_LIMIT_PIN (23u) -#endif +#define Z_STEP_PIN (6u) +#define Z_DIRECTION_PIN (7u) +#define Z_LIMIT_PIN (22u) + +// Define ganged axis or A axis step pulse and step direction output pins. +#if N_ABC_MOTORS > 0 +#define M3_AVAILABLE +#define M3_STEP_PIN (8u) +#define M3_DIRECTION_PIN (9u) +#define M3_LIMIT_PIN (23u) #endif -#define Y_STEP_PIN (4u) -#define Y_DIRECTION_PIN (5u) -#define Y_LIMIT_PIN (21u) - -#if Y_GANGED || Y_AUTO_SQUARE -#define Y2_STEP_PIN (8u) -#define Y2_DIRECTION_PIN (9u) -#if Y_AUTO_SQUARE - #define Y2_LIMIT_PIN (23u) -#endif -#endif - -#define Z_STEP_PIN (6u) -#define Z_DIRECTION_PIN (7u) -#define Z_LIMIT_PIN (22u) - -#if Z_GANGED || Z_AUTO_SQUARE -#define Z2_STEP_PIN (8u) -#define Z2_DIRECTION_PIN (9u) -#if Z_AUTO_SQUARE - #define Z2_LIMIT_PIN (23u) -#endif -#endif - -#if N_AXIS > 3 -#define A_STEP_PIN (8u) -#define A_DIRECTION_PIN (9u) -#define A_LIMIT_PIN (23u) -#endif - -#if N_AXIS > 4 -#define B_STEP_PIN (26u) -#define B_DIRECTION_PIN (27u) -#define B_ENABLE_PIN (37u) -#define B_LIMIT_PIN (28u) +// Define ganged axis or B axis step pulse and step direction output pins. +#if N_ABC_MOTORS == 2 +#define M4_AVAILABLE +#define M4_STEP_PIN (26u) +#define M4_DIRECTION_PIN (27u) +#define M4_LIMIT_PIN (28u) +#define M4_ENABLE_PIN (37u) #endif // Define stepper driver enable/disable output pin(s). -#define STEPPERS_ENABLE_PIN (10u) +#define STEPPERS_ENABLE_PIN (10u) // Define spindle enable and spindle direction output pins. #define SPINDLE_ENABLE_PIN (12u) diff --git a/grblHAL_Teensy4/src/T41BB5X_Pro_map.h b/grblHAL_Teensy4/src/T41BB5X_Pro_map.h index b528197..8d2bae5 100644 --- a/grblHAL_Teensy4/src/T41BB5X_Pro_map.h +++ b/grblHAL_Teensy4/src/T41BB5X_Pro_map.h @@ -21,8 +21,12 @@ along with Grbl. If not, see . */ +#if N_ABC_MOTORS > 2 +#error "Axis configuration is not supported!" +#endif + #define BOARD_NAME "T41BB5X Pro" -#define HAS_BOARD_INIT +#define HAS_IOPORTS #if N_AXIS > 5 #error Max number of axes is 5 for T41U5XBB @@ -38,72 +42,37 @@ #define EEPROM_ENABLE 1 #define EEPROM_IS_FRAM 1 -// Default pin assignments allow only one axis to be ganged or auto squared. -// B axis pin numbers are used for the ganged/auto squared axis. -// If a second axis is to be ganged/auto squared pin assignments needs to be changed! -// Set to 1 to enable, 0 to disable. -#define X_GANGED 1 -#define X_AUTO_SQUARE 1 -#define Y_GANGED 0 -#define Y_AUTO_SQUARE 0 -#define Z_GANGED 0 -#define Z_AUTO_SQUARE 0 -// +#define X_STEP_PIN (2u) +#define X_DIRECTION_PIN (3u) +#define X_ENABLE_PIN (10u) +#define X_LIMIT_PIN (20u) -#define X_STEP_PIN (2u) -#define X_DIRECTION_PIN (3u) -#define X_ENABLE_PIN (10u) -#define X_LIMIT_PIN (20u) +#define Y_STEP_PIN (4u) +#define Y_DIRECTION_PIN (5u) +#define Y_ENABLE_PIN (35u) +#define Y_LIMIT_PIN (21u) -#if X_GANGED || X_AUTO_SQUARE -#define X2_STEP_PIN (26u) -#define X2_DIRECTION_PIN (27u) -#define X2_ENABLE_PIN (37u) -#if X_AUTO_SQUARE - #define X2_LIMIT_PIN (28u) -#endif +#define Z_STEP_PIN (6u) +#define Z_DIRECTION_PIN (7u) +#define Z_ENABLE_PIN (39u) +#define Z_LIMIT_PIN (22u) + +// Define ganged axis or A axis step pulse and step direction output pins. +#if N_ABC_MOTORS > 0 +#define M3_AVAILABLE +#define M3_STEP_PIN (8u) +#define M3_DIRECTION_PIN (9u) +#define M3_LIMIT_PIN (23u) +#define M3_ENABLE_PIN (38u) #endif -#define Y_STEP_PIN (4u) -#define Y_DIRECTION_PIN (5u) -#define Y_ENABLE_PIN (35u) -#define Y_LIMIT_PIN (21u) - -#if Y_GANGED || Y_AUTO_SQUARE -#define Y2_STEP_PIN (26u) -#define Y2_DIRECTION_PIN (27u) -#define Y2_ENABLE_PIN (37u) -#if Y_AUTO_SQUARE - #define Y2_LIMIT_PIN (28u) -#endif -#endif - -#define Z_STEP_PIN (6u) -#define Z_DIRECTION_PIN (7u) -#define Z_ENABLE_PIN (39u) -#define Z_LIMIT_PIN (22u) - -#if Z_GANGED || Z_AUTO_SQUARE -#define Z2_STEP_PIN (26u) -#define Z2_DIRECTION_PIN (27u) -#define Z2_ENABLE_PIN (37u) -#if Z_AUTO_SQUARE - #define Z2_LIMIT_PIN (28u) -#endif -#endif - -#if N_AXIS > 3 -#define A_STEP_PIN (8u) -#define A_DIRECTION_PIN (9u) -#define A_ENABLE_PIN (38u) -#define A_LIMIT_PIN (23u) -#endif - -#if N_AXIS > 4 -#define B_STEP_PIN (26u) -#define B_DIRECTION_PIN (27u) -#define B_ENABLE_PIN (37u) -#define B_LIMIT_PIN (28u) +// Define ganged axis or B axis step pulse and step direction output pins. +#if N_ABC_MOTORS == 2 +#define M4_AVAILABLE +#define M4_STEP_PIN (26u) +#define M4_DIRECTION_PIN (27u) +#define M4_LIMIT_PIN (28u) +#define M4_ENABLE_PIN (37u) #endif // Define spindle enable and spindle direction output pins. diff --git a/grblHAL_Teensy4/src/T41U5XBB_map.h b/grblHAL_Teensy4/src/T41U5XBB_map.h index f16a2c2..5014a3a 100644 --- a/grblHAL_Teensy4/src/T41U5XBB_map.h +++ b/grblHAL_Teensy4/src/T41U5XBB_map.h @@ -21,84 +21,48 @@ along with Grbl. If not, see . */ -#define BOARD_NAME "T41U5XBB" -#define HAS_BOARD_INIT - -#if N_AXIS > 5 -#error Max number of axes is 5 for T41U5XBB +#if N_ABC_MOTORS > 2 +#error "Axis configuration is not supported!" #endif #if SPINDLE_SYNC_ENABLE -#error Spindle sync is not supported for T41U5XBB +#error "Spindle sync is not supported for T41U5XBB!" #endif -// Default pin assignments allow only one axis to be ganged or auto squared. -// B axis pin numbers are used for the ganged/auto squared axis. -// If a second axis is to be ganged/auto squared pin assignments needs to be changed! -// Set to 1 to enable, 0 to disable. -#define X_GANGED 0 -#define X_AUTO_SQUARE 0 -#define Y_GANGED 0 -#define Y_AUTO_SQUARE 0 -#define Z_GANGED 0 -#define Z_AUTO_SQUARE 0 -// +#define BOARD_NAME "T41U5XBB" +#define HAS_IOPORTS -#define X_STEP_PIN (2u) -#define X_DIRECTION_PIN (3u) -#define X_ENABLE_PIN (10u) -#define X_LIMIT_PIN (20u) +#define X_STEP_PIN (2u) +#define X_DIRECTION_PIN (3u) +#define X_ENABLE_PIN (10u) +#define X_LIMIT_PIN (20u) -#if X_GANGED || X_AUTO_SQUARE -#define X2_STEP_PIN (26u) -#define X2_DIRECTION_PIN (27u) -#define X2_ENABLE_PIN (37u) -#if X_AUTO_SQUARE - #define X2_LIMIT_PIN (28u) -#endif +#define Y_STEP_PIN (4u) +#define Y_DIRECTION_PIN (5u) +#define Y_ENABLE_PIN (40u) +#define Y_LIMIT_PIN (21u) + +#define Z_STEP_PIN (6u) +#define Z_DIRECTION_PIN (7u) +#define Z_ENABLE_PIN (39u) +#define Z_LIMIT_PIN (22u) + +// Define ganged axis or A axis step pulse and step direction output pins. +#if N_ABC_MOTORS > 0 +#define M3_AVAILABLE +#define M3_STEP_PIN (8u) +#define M3_DIRECTION_PIN (9u) +#define M3_LIMIT_PIN (23u) +#define M3_ENABLE_PIN (38u) #endif -#define Y_STEP_PIN (4u) -#define Y_DIRECTION_PIN (5u) -#define Y_ENABLE_PIN (40u) -#define Y_LIMIT_PIN (21u) - -// Changed to use A pins rather than B pins -#if Y_GANGED || Y_AUTO_SQUARE -#define Y2_STEP_PIN (8u) -#define Y2_DIRECTION_PIN (9u) -#define Y2_ENABLE_PIN (38u) -#if Y_AUTO_SQUARE - #define Y2_LIMIT_PIN (23u) -#endif -#endif - -#define Z_STEP_PIN (6u) -#define Z_DIRECTION_PIN (7u) -#define Z_ENABLE_PIN (39u) -#define Z_LIMIT_PIN (22u) - -#if Z_GANGED || Z_AUTO_SQUARE -#define Z2_STEP_PIN (26u) -#define Z2_DIRECTION_PIN (27u) -#define Z2_ENABLE_PIN (37u) -#if Z_AUTO_SQUARE - #define Z2_LIMIT_PIN (28u) -#endif -#endif - -#if N_AXIS > 3 -#define A_STEP_PIN (8u) -#define A_DIRECTION_PIN (9u) -#define A_ENABLE_PIN (38u) -#define A_LIMIT_PIN (23u) -#endif - -#if N_AXIS > 4 -#define B_STEP_PIN (26u) -#define B_DIRECTION_PIN (27u) -#define B_ENABLE_PIN (37u) -#define B_LIMIT_PIN (28u) +// Define ganged axis or B axis step pulse and step direction output pins. +#if N_ABC_MOTORS == 2 +#define M4_AVAILABLE +#define M4_STEP_PIN (26u) +#define M4_DIRECTION_PIN (27u) +#define M4_LIMIT_PIN (28u) +#define M4_ENABLE_PIN (37u) #endif // Define spindle enable and spindle direction output pins. diff --git a/grblHAL_Teensy4/src/T41U5XBB_ss_map.h b/grblHAL_Teensy4/src/T41U5XBB_ss_map.h index 3fd2506..5c62312 100644 --- a/grblHAL_Teensy4/src/T41U5XBB_ss_map.h +++ b/grblHAL_Teensy4/src/T41U5XBB_ss_map.h @@ -23,84 +23,48 @@ along with Grbl. If not, see . */ -#define BOARD_NAME "T41U5XBB" -#define HAS_BOARD_INIT - -#if N_AXIS > 5 -#error Max number of axes is 5 for T41U5XBB +#if N_ABC_MOTORS > 2 +#error "Axis configuration is not supported!" #endif #if QEI_ENABLE && SPINDLE_SYNC_ENABLE -#error Quadrature encoder and spindle sync cannot be enabled at the same time +#error "Quadrature encoder and spindle sync cannot be enabled at the same time!" #endif -// Default pin assignments allow only one axis to be ganged or auto squared. -// B axis pin numbers are used for the ganged/auto squared axis. -// If a second axis is to be ganged/auto squared pin assignments needs to be changed! -// Set to 1 to enable, 0 to disable. -#define X_GANGED 0 -#define X_AUTO_SQUARE 0 -#define Y_GANGED 0 -#define Y_AUTO_SQUARE 0 -#define Z_GANGED 0 -#define Z_AUTO_SQUARE 0 -// +#define BOARD_NAME "T41U5XBB" +#define HAS_IOPORTS -#define X_STEP_PIN (2u) -#define X_DIRECTION_PIN (3u) -#define X_ENABLE_PIN (10u) -#define X_LIMIT_PIN (20u) +#define X_STEP_PIN (2u) +#define X_DIRECTION_PIN (3u) +#define X_ENABLE_PIN (10u) +#define X_LIMIT_PIN (20u) -#if X_GANGED || X_AUTO_SQUARE -#define X2_STEP_PIN (26u) -#define X2_DIRECTION_PIN (27u) -#define X2_ENABLE_PIN (37u) -#if X_AUTO_SQUARE - #define X2_LIMIT_PIN (28u) -#endif +#define Y_STEP_PIN (4u) +#define Y_DIRECTION_PIN (5u) +#define Y_ENABLE_PIN (40u) +#define Y_LIMIT_PIN (21u) + +#define Z_STEP_PIN (6u) +#define Z_DIRECTION_PIN (7u) +#define Z_ENABLE_PIN (39u) +#define Z_LIMIT_PIN (22u) + +// Define ganged axis or A axis step pulse and step direction output pins. +#if N_ABC_MOTORS > 0 +#define M3_AVAILABLE +#define M3_STEP_PIN (8u) +#define M3_DIRECTION_PIN (9u) +#define M3_LIMIT_PIN (23u) +#define M3_ENABLE_PIN (38u) #endif -#define Y_STEP_PIN (4u) -#define Y_DIRECTION_PIN (5u) -#define Y_ENABLE_PIN (40u) -#define Y_LIMIT_PIN (21u) - -// Changed to use A pins rather than B pins -#if Y_GANGED || Y_AUTO_SQUARE -#define Y2_STEP_PIN (8u) -#define Y2_DIRECTION_PIN (9u) -#define Y2_ENABLE_PIN (38u) -#if Y_AUTO_SQUARE - #define Y2_LIMIT_PIN (23u) -#endif -#endif - -#define Z_STEP_PIN (6u) -#define Z_DIRECTION_PIN (7u) -#define Z_ENABLE_PIN (39u) -#define Z_LIMIT_PIN (22u) - -#if Z_GANGED || Z_AUTO_SQUARE -#define Z2_STEP_PIN (26u) -#define Z2_DIRECTION_PIN (27u) -#define Z2_ENABLE_PIN (37u) -#if Z_AUTO_SQUARE - #define Z2_LIMIT_PIN (28u) -#endif -#endif - -#if N_AXIS > 3 -#define A_STEP_PIN (8u) -#define A_DIRECTION_PIN (9u) -#define A_ENABLE_PIN (38u) -#define A_LIMIT_PIN (23u) -#endif - -#if N_AXIS > 4 -#define B_STEP_PIN (26u) -#define B_DIRECTION_PIN (27u) -#define B_ENABLE_PIN (37u) -#define B_LIMIT_PIN (28u) +// Define ganged axis or B axis step pulse and step direction output pins. +#if N_ABC_MOTORS == 2 +#define M4_AVAILABLE +#define M4_STEP_PIN (26u) +#define M4_DIRECTION_PIN (27u) +#define M4_LIMIT_PIN (28u) +#define M4_ENABLE_PIN (37u) #endif // Define spindle enable and spindle direction output pins. diff --git a/grblHAL_Teensy4/src/cnc_boosterpack_map.h b/grblHAL_Teensy4/src/cnc_boosterpack_map.h index c94254a..31a6854 100644 --- a/grblHAL_Teensy4/src/cnc_boosterpack_map.h +++ b/grblHAL_Teensy4/src/cnc_boosterpack_map.h @@ -21,12 +21,12 @@ #define BOARD_NAME "CNC BoosterPack" -#if N_AXIS > 3 -#error Max number of axes is 3 for CNC BoosterPack +#if N_ABC_MOTORS +#error "Axis configuration is not supported!" #endif #if SPINDLE_SYNC_ENABLE -#error Spindle sync is not supported for CNC BoosterPack +#error "Spindle sync is not supported for CNC BoosterPack" #endif #ifdef EEPROM_ENABLE diff --git a/grblHAL_Teensy4/src/driver.c b/grblHAL_Teensy4/src/driver.c index b88f1c1..ff041f8 100644 --- a/grblHAL_Teensy4/src/driver.c +++ b/grblHAL_Teensy4/src/driver.c @@ -67,6 +67,10 @@ static void ppi_timeout_isr (void); #include "openpnp/openpnp.h" #endif +#if BLUETOOTH_ENABLE +#include "bluetooth/bluetooth.h" +#endif + #if ETHERNET_ENABLE #include "enet.h" #if TELNET_ENABLE @@ -96,17 +100,7 @@ static void ppi_timeout_isr (void); #define F_BUS_MHZ (F_BUS_ACTUAL / 1000000) -#if X_AUTO_SQUARE || Y_AUTO_SQUARE || Z_AUTO_SQUARE -#define SQUARING_ENABLED -#endif - -#if defined(X2_LIMIT_PIN) || defined(Y2_LIMIT_PIN) || defined(Z2_LIMIT_PIN) || defined(A2_LIMIT_PIN) || defined(B2_LIMIT_PIN) -#define DUAL_LIMIT_SWITCHES -#else - #ifdef SQUARING_ENABLED - #error "Squaring requires at least one axis with dual switch inputs!" - #endif -#endif +#include "grbl/motor_pins.h" typedef struct { volatile uint_fast8_t head; @@ -224,6 +218,9 @@ static gpio_t QEI_A, QEI_B; #ifdef X2_LIMIT_PIN static gpio_t LimitX2; #endif +#ifdef X_LIMIT_PIN_MAX + static gpio_t LimitXMax; +#endif #ifdef Y2_STEP_PIN static gpio_t stepY2; @@ -237,6 +234,9 @@ static gpio_t QEI_A, QEI_B; #ifdef Y2_LIMIT_PIN static gpio_t LimitY2; #endif +#ifdef Y_LIMIT_PIN_MAX + static gpio_t LimitYMax; +#endif #ifdef Z2_STEP_PIN static gpio_t stepZ2; @@ -250,6 +250,10 @@ static gpio_t QEI_A, QEI_B; #ifdef Z2_LIMIT_PIN static gpio_t LimitZ2; #endif +#ifdef Z_LIMIT_PIN_MAX + static gpio_t LimitZMax; +#endif + #ifdef SPINDLE_INDEX_PIN static gpio_t SpindleIndex; #endif @@ -295,15 +299,24 @@ input_signal_t inputpin[] = { // Limit input pins must be consecutive { .id = Input_LimitX, .port = &LimitX, .pin = X_LIMIT_PIN, .group = PinGroup_Limit }, #ifdef X2_LIMIT_PIN - { .id = Input_LimitX_Max, .port = &LimitX2, .pin = X2_LIMIT_PIN, .group = PinGroup_Limit }, + { .id = Input_LimitX_2, .port = &LimitX2, .pin = X2_LIMIT_PIN, .group = PinGroup_Limit }, +#endif +#ifdef X_LIMIT_PIN_MAX + { .id = Input_LimitX_Max, .port = &LimitXMax, .pin = X_LIMIT_PIN_MAX, .group = PinGroup_Limit }, #endif { .id = Input_LimitY, .port = &LimitY, .pin = Y_LIMIT_PIN, .group = PinGroup_Limit }, #ifdef Y2_LIMIT_PIN - { .id = Input_LimitY_Max, .port = &LimitY2, .pin = Y2_LIMIT_PIN, .group = PinGroup_Limit }, + { .id = Input_LimitY_2, .port = &LimitY2, .pin = Y2_LIMIT_PIN, .group = PinGroup_Limit }, +#endif +#ifdef Y_LIMIT_PIN_MAX + { .id = Input_LimitY_Max, .port = &LimitYMax, .pin = Y_LIMIT_PIN_MAX, .group = PinGroup_Limit }, #endif { .id = Input_LimitZ, .port = &LimitZ, .pin = Z_LIMIT_PIN, .group = PinGroup_Limit } #ifdef Z2_LIMIT_PIN - , { .id = Input_LimitZ_Max, .port = &LimitZ2, .pin = Z2_LIMIT_PIN, .group = PinGroup_Limit } + , { .id = Input_LimitZ_2, .port = &LimitZ2, .pin = Z2_LIMIT_PIN, .group = PinGroup_Limit } +#endif +#ifdef Z_LIMIT_PIN_MAX + , { .id = Input_LimitZ_Max, .port = &LimitZMax, .pin = Z_LIMIT_PIN_MAX, .group = PinGroup_Limit } #endif #ifdef A_LIMIT_PIN , { .id = Input_LimitA, .port = &LimitA, .pin = A_LIMIT_PIN, .group = PinGroup_Limit } @@ -471,10 +484,6 @@ static spindle_pwm_t spindle_pwm; static void spindle_set_speed (uint_fast16_t pwm_value); #endif -#if MODBUS_ENABLE -static modbus_stream_t modbus_stream = {0}; -#endif - #if SPINDLE_SYNC_ENABLE #include "grbl/spindle_sync.h" @@ -493,8 +502,11 @@ static void spindle_pulse_isr (void); #endif +static const io_stream_t *serial_stream; + #if ETHERNET_ENABLE static network_services_t services = {0}; +static stream_write_ptr write_serial; static void enetStreamWriteS (const char *data) { @@ -506,50 +518,11 @@ static void enetStreamWriteS (const char *data) if(services.websocket) WsStreamWriteS(data); #endif -#if USB_SERIAL_CDC - usb_serialWriteS(data); -#else - serialWriteS(data); -#endif + if(write_serial) + write_serial(data); } #endif // ETHERNET_ENABLE -#if USB_SERIAL_CDC - const io_stream_t serial_stream = { - .type = StreamType_Serial, - .read = usb_serialGetC, - .write = usb_serialWriteS, - .write_char = usb_serialPutC, - #if ETHERNET_ENABLE - .write_all = enetStreamWriteS, - #else - .write_all = usb_serialWriteS, - #endif - .get_rx_buffer_available = usb_serialRxFree, - .reset_read_buffer = usb_serialRxFlush, - .cancel_read_buffer = usb_serialRxCancel, - .suspend_read = usb_serialSuspendInput, - .enqueue_realtime_command = protocol_enqueue_realtime_command - }; -#else -const io_stream_t serial_stream = { - .type = StreamType_Serial, - .read = serialGetC, - .write = serialWriteS, - .write_char = serialPutC, -#if ETHERNET_ENABLE - .write_all = enetStreamWriteS, -#else - .write_all = serialWriteS, -#endif - .get_rx_buffer_available = serialRxFree, - .reset_read_buffer = serialRxFlush, - .cancel_read_buffer = serialRxCancel, - .suspend_read = serialSuspendInput, - .enqueue_realtime_command = protocol_enqueue_realtime_command -}; -#endif - // Interrupt handler prototypes // Interrupt handlers needs to be registered, possibly by modifying a system specific startup file. // It is possible to relocate the interrupt dispatch table from flash to RAM and programatically attach handlers. @@ -587,12 +560,13 @@ static bool selectStream (const io_stream_t *stream) { static bool serial_connected = false; static stream_type_t active_stream = StreamType_Serial; + static const io_stream_t *last_serial_stream; - if(hal.stream.type == StreamType_Serial) + if(hal.stream.type == StreamType_Serial || hal.stream.type == StreamType_Bluetooth) serial_connected = hal.stream.connected; if(!stream) - stream = &serial_stream; + stream = active_stream == StreamType_Bluetooth ? serial_stream : last_serial_stream; memcpy(&hal.stream, stream, sizeof(io_stream_t)); @@ -607,6 +581,9 @@ static bool selectStream (const io_stream_t *stream) if(!hal.stream.enqueue_realtime_command) hal.stream.enqueue_realtime_command = protocol_enqueue_realtime_command; + if(hal.stream.disable) + hal.stream.disable(false); + switch(stream->type) { #if TELNET_ENABLE @@ -624,12 +601,21 @@ static bool selectStream (const io_stream_t *stream) case StreamType_Serial: #if ETHERNET_ENABLE services.mask = 0; + write_serial = serial_connected ? hal.stream.write : NULL; #endif hal.stream.connected = serial_connected; + last_serial_stream = stream; if(active_stream != StreamType_Serial && hal.stream.connected) hal.stream.write_all("[MSG:SERIAL STREAM ACTIVE]" ASCII_EOL); break; + case StreamType_Bluetooth: +#if ETHERNET_ENABLE + services.mask = 0; + write_serial = hal.stream.write; +#endif + last_serial_stream = stream; + break; default: break; } @@ -643,6 +629,7 @@ static bool selectStream (const io_stream_t *stream) // step_outbits.value (or step_outbits.mask) are: bit0 -> X, bit1 -> Y... // Individual step bits can be accessed by step_outbits.x, step_outbits.y, ... #ifdef SQUARING_ENABLED + inline static __attribute__((always_inline)) void set_step_outputs (axes_signals_t step_outbits_1) { axes_signals_t step_outbits_2; @@ -672,7 +659,33 @@ inline static __attribute__((always_inline)) void set_step_outputs (axes_signals DIGITAL_OUT(stepB, step_outbits_1.b); #endif } + +static axes_signals_t getAutoSquaredAxes (void) +{ + axes_signals_t ganged = {0}; + +#if X_AUTO_SQUARE + ganged.x = On; +#endif +#if Y_AUTO_SQUARE + ganged.y = On; +#endif +#if Z_AUTO_SQUARE + ganged.z = On; +#endif + + return ganged; +} + +// Enable/disable motors for auto squaring of ganged axes +static void StepperDisableMotors (axes_signals_t axes, squaring_mode_t mode) +{ + motors_1.mask = (mode == SquaringMode_A || mode == SquaringMode_Both ? axes.mask : 0) ^ AXES_BITMASK; + motors_2.mask = (mode == SquaringMode_B || mode == SquaringMode_Both ? axes.mask : 0) ^ AXES_BITMASK; +} + #else + inline static __attribute__((always_inline)) void set_step_outputs (axes_signals_t step_outbits) { step_outbits.value ^= settings.steppers.step_invert.mask; @@ -702,7 +715,8 @@ inline static __attribute__((always_inline)) void set_step_outputs (axes_signals DIGITAL_OUT(stepC, step_outbits.c); #endif } -#endif + +#endif // SQUARING_ENABLED // Set stepper direction ouput pins. // dir_outbits.value (or dir_outbits.mask) are: bit0 -> X, bit1 -> Y... @@ -988,8 +1002,6 @@ void stepperOutputStep (axes_signals_t step_outbits, axes_signals_t dir_outbits) #endif -#ifdef DUAL_LIMIT_SWITCHES - // Returns limit state as an axes_signals_t variable. // Each bitfield bit indicates an axis limit, where triggered is 1 and not triggered is 0. // Dual limit switch inputs per axis version. Only one needs to be dual input! @@ -998,100 +1010,59 @@ inline static limit_signals_t limitsGetState() limit_signals_t signals = {0}; signals.min.mask = signals.min2.mask = settings.limits.invert.mask; +#ifdef DUAL_LIMIT_SWITCHES + signals.min2.mask = settings.limits.invert.mask; +#endif +#ifdef MAX_LIMIT_SWITCHES + signals.max.mask = settings.limits.invert.mask; +#endif - signals.min.x = (LimitX.reg->DR & LimitX.bit) != 0; + signals.min.x = DIGITAL_IN(LimitX); #ifdef X2_LIMIT_PIN - signals.min2.x = (LimitX2.reg->DR & LimitX2.bit) != 0; + signals.min2.x = DIGITAL_IN(LimitX2); +#endif +#ifdef X_LIMIT_PIN_MAX + signals.max.x = DIGITAL_IN(LimitXMax); #endif - signals.min.y = (LimitY.reg->DR & LimitY.bit) != 0; + signals.min.y = DIGITAL_IN(LimitY); #ifdef Y2_LIMIT_PIN - signals.min2.y = (LimitY2.reg->DR & LimitY2.bit) != 0; + signals.min2.y = DIGITAL_IN(LimitY2); +#endif +#ifdef Y_LIMIT_PIN_MAX + signals.max.y = DIGITAL_IN(LimitYMax); #endif - signals.min.z = (LimitZ.reg->DR & LimitZ.bit) != 0; + signals.min.z = DIGITAL_IN(LimitZ); #ifdef Z2_LIMIT_PIN - signals.min2.z = (LimitZ2.reg->DR & LimitZ2.bit) != 0; + signals.min2.z = DIGITAL_IN(LimitZ2); +#endif +#ifdef Z_LIMIT_PIN_MAX + signals.max.z = DIGITAL_IN(LimitZMax); #endif #ifdef A_LIMIT_PIN - signals.min.a = (LimitA.reg->DR & LimitA.bit) != 0; + signals.min.a = DIGITAL_IN(LimitA); #endif #ifdef B_LIMIT_PIN - signals.min.b = (LimitB.reg->DR & LimitB.bit) != 0; + signals.min.b = DIGITAL_IN(LimitB); #endif #ifdef C_LIMIT_PIN - signals.min.c = (LimitC.reg->DR & LimitC.bit) != 0; + signals.min.c = DIGITAL_IN(LimitC); #endif if(settings.limits.invert.mask) { signals.min.value ^= settings.limits.invert.mask; - signals.min2.value ^= settings.limits.invert.mask; +#ifdef DUAL_LIMIT_SWITCHES + signals.min2.mask ^= settings.limits.invert.mask; +#endif +#ifdef MAX_LIMIT_SWITCHES + signals.max.value ^= settings.limits.invert.mask; +#endif } return signals; } -#else // SINGLE INPUT LIMIT SWITCHES - -// Returns limit state as an axes_signals_t bitmap variable. -// signals.value (or signals.mask) are: bit0 -> X, bit1 -> Y... -// Individual signals bits can be accessed by signals.x, signals.y, ... -// Each bit indicates a limit signal, where triggered is 1 and not triggered is 0. -// axes_signals_t is defined in grbl/nuts_bolts.h. -inline static limit_signals_t limitsGetState() -{ - limit_signals_t signals = {0}; - - signals.min.mask = settings.limits.invert.mask; - - signals.min.x = (LimitX.reg->DR & LimitX.bit) != 0; - signals.min.y = (LimitY.reg->DR & LimitY.bit) != 0; - signals.min.z = (LimitZ.reg->DR & LimitZ.bit) != 0; -#ifdef A_LIMIT_PIN - signals.min.a = (LimitA.reg->DR & LimitA.bit) != 0; -#endif -#ifdef B_LIMIT_PIN - signals.min.b = (LimitB.reg->DR & LimitB.bit) != 0; -#endif -#ifdef C_LIMIT_PIN - signals.min.c = (LimitC.reg->DR & LimitC.bit) != 0; -#endif - - if (settings.limits.invert.mask) - signals.min.value ^= settings.limits.invert.mask; - - return signals; -} - -#endif - -#ifdef SQUARING_ENABLED - -static axes_signals_t getAutoSquaredAxes (void) -{ - axes_signals_t ganged = {0}; - - #if X_AUTO_SQUARE - ganged.x = On; -#endif -#if Y_AUTO_SQUARE - ganged.y = On; -#endif -#if Z_AUTO_SQUARE - ganged.z = On; -#endif - - return ganged; -} - -// Enable/disable motors for auto squaring of ganged axes -static void StepperDisableMotors (axes_signals_t axes, squaring_mode_t mode) -{ - motors_1.mask = (mode == SquaringMode_A || mode == SquaringMode_Both ? axes.mask : 0) ^ AXES_BITMASK; - motors_2.mask = (mode == SquaringMode_B || mode == SquaringMode_Both ? axes.mask : 0) ^ AXES_BITMASK; -} - -#endif // Enable/disable limit pins interrupt. // NOTE: the homing parameter is indended for configuring advanced @@ -1633,6 +1604,7 @@ static void settings_changed (settings_t *settings) break; case Input_LimitX: + case Input_LimitX_2: case Input_LimitX_Max: pullup = !settings->limits.disable_pullup.x; signal->debounce = hal.driver_cap.software_debounce; @@ -1640,12 +1612,14 @@ static void settings_changed (settings_t *settings) break; case Input_LimitY: + case Input_LimitY_2: case Input_LimitY_Max: pullup = !settings->limits.disable_pullup.y; signal->irq_mode = limit_fei.y ? IRQ_Mode_Falling : IRQ_Mode_Rising; break; case Input_LimitZ: + case Input_LimitZ_2: case Input_LimitZ_Max: pullup = !settings->limits.disable_pullup.z; signal->irq_mode = limit_fei.z ? IRQ_Mode_Falling : IRQ_Mode_Rising; @@ -1718,42 +1692,30 @@ static void settings_changed (settings_t *settings) break; } + if(signal->group == PinGroup_AuxInput) { + signal->cap.pull_mode = (PullMode_Up|PullMode_Down); + signal->cap.irq_mode = (IRQ_Mode_Rising|IRQ_Mode_Falling); + } + pinMode(signal->pin, pullup ? INPUT_PULLUP : INPUT_PULLDOWN); signal->gpio.reg = (gpio_reg_t *)digital_pin_to_info_PGM[signal->pin].reg; signal->gpio.bit = digital_pin_to_info_PGM[signal->pin].mask; + if(signal->gpio.reg == (gpio_reg_t *)&GPIO6_DR) + signal->offset = 0; + else if(signal->gpio.reg == (gpio_reg_t *)&GPIO7_DR) + signal->offset = 1; + else if(signal->gpio.reg == (gpio_reg_t *)&GPIO8_DR) + signal->offset = 2; + else + signal->offset = 3; + if(signal->port != NULL) memcpy(signal->port, &signal->gpio, sizeof(gpio_t)); if(signal->irq_mode != IRQ_Mode_None) { - if(signal->gpio.reg == (gpio_reg_t *)&GPIO6_DR) - signal->offset = 0; - else if(signal->gpio.reg == (gpio_reg_t *)&GPIO7_DR) - signal->offset = 1; - else if(signal->gpio.reg == (gpio_reg_t *)&GPIO8_DR) - signal->offset = 2; - else - signal->offset = 3; - - if(signal->irq_mode == IRQ_Mode_Change) - signal->gpio.reg->EDGE_SEL |= signal->gpio.bit; - else { - signal->gpio.reg->EDGE_SEL &= ~signal->gpio.bit; - uint32_t iopin = __builtin_ctz(signal->gpio.bit); - if(iopin < 16) { - uint32_t shift = iopin << 1; - signal->gpio.reg->ICR1 = (signal->gpio.reg->ICR1 & ~(0b11 << shift)) | (signal->irq_mode << shift); - } else { - uint32_t shift = (iopin - 16) << 1; - signal->gpio.reg->ICR2 = (signal->gpio.reg->ICR2 & ~(0b11 << shift)) | (signal->irq_mode << shift); - } - } - - signal->gpio.reg->ISR = signal->gpio.bit; // Clear interrupt. - - if(signal->group != PinGroup_Limit) // If pin is not a limit pin - signal->gpio.reg->IMR |= signal->gpio.bit; // enable interrupt + pinEnableIRQ(signal, signal->irq_mode); signal->active = (signal->gpio.reg->DR & signal->gpio.bit) != 0; @@ -1803,6 +1765,45 @@ void pinModeOutput (gpio_t *gpio, uint8_t pin) gpio->bit = digital_pin_to_info_PGM[pin].mask; } +void pinEnableIRQ (const input_signal_t *signal, pin_irq_mode_t irq_mode) +{ + if(irq_mode == IRQ_Mode_None) + signal->gpio.reg->IMR &= ~signal->gpio.bit; // Disable interrupt + else if(irq_mode == IRQ_Mode_Change) + signal->gpio.reg->EDGE_SEL |= signal->gpio.bit; + else { + uint32_t iopin = __builtin_ctz(signal->gpio.bit), shift, mode = 0; + + switch(irq_mode) { + case IRQ_Mode_Rising: + mode = 0b10; + break; + case IRQ_Mode_Falling: + mode = 0b11; + break; + case IRQ_Mode_High: + mode = 0b10; + break; + default: // Low + mode = 0b00; + break; + } + signal->gpio.reg->EDGE_SEL &= ~signal->gpio.bit; + if(iopin < 16) { + shift = iopin << 1; + signal->gpio.reg->ICR1 = (signal->gpio.reg->ICR1 & ~(0b11 << shift)) | (mode << shift); + } else { + shift = (iopin - 16) << 1; + signal->gpio.reg->ICR2 = (signal->gpio.reg->ICR2 & ~(0b11 << shift)) | (mode << shift); + } + } + + signal->gpio.reg->ISR = signal->gpio.bit; // Clear interrupt. + + if(!(irq_mode == IRQ_Mode_None || signal->group == PinGroup_Limit)) // If pin is not a limit pin + signal->gpio.reg->IMR |= signal->gpio.bit; // enable interrupt +} + #if QEI_ENABLE static void qei_update (void) @@ -2165,7 +2166,7 @@ bool driver_init (void) options[strlen(options) - 1] = '\0'; hal.info = "iMXRT1062"; - hal.driver_version = "210605"; + hal.driver_version = "210617"; #ifdef BOARD_NAME hal.board = BOARD_NAME; #endif @@ -2219,15 +2220,15 @@ bool driver_init (void) grbl.on_report_options = reportIP; #endif - hal.stream_select = selectStream; - hal.stream_select(&serial_stream); - #if USB_SERIAL_CDC - usb_serialInit(); + serial_stream = usb_serialInit(); #else - serialInit(115200); + serial_stream = serialInit(115200); #endif + hal.stream_select = selectStream; + hal.stream_select(serial_stream); + #ifdef I2C_PORT i2c_init(); #endif @@ -2257,30 +2258,13 @@ bool driver_init (void) #if QEI_ENABLE hal.encoder.reset = qei_reset; hal.encoder.on_event = encoder_event; -#endif - -#if MODBUS_ENABLE - modbus_stream.write = serialWrite; - modbus_stream.read = serialGetC; - modbus_stream.flush_rx_buffer = serialRxFlush; - modbus_stream.flush_tx_buffer = serialTxFlush; - modbus_stream.get_rx_buffer_count = serialRxCount; - modbus_stream.get_tx_buffer_count = serialTxCount; - modbus_stream.set_baud_rate = serialSetBaudRate; - - bool modbus = modbus_init(&modbus_stream); - -#if SPINDLE_HUANYANG - if(modbus) - huanyang_init(&modbus_stream); -#endif - #endif // Driver capabilities, used for announcing and negotiating (with Grbl) driver functionality. // See driver_cap_t union i grbl/hal.h for available flags. #if ESTOP_ENABLE + hal.signals_cap.reset = Off; hal.signals_cap.e_stop = On; #endif #if SAFETY_DOOR_ENABLE @@ -2321,13 +2305,13 @@ bool driver_init (void) for(i = 0 ; i < sizeof(inputpin) / sizeof(input_signal_t); i++) { signal = &inputpin[i]; - +#ifdef HAS_IOPORTS if(signal->group == PinGroup_AuxInput) { if(aux_inputs.pins.inputs == NULL) aux_inputs.pins.inputs = signal; aux_inputs.n_pins++; } - +#endif if(signal->group == PinGroup_Limit) { if(limit_inputs.pins.inputs == NULL) limit_inputs.pins.inputs = signal; @@ -2335,6 +2319,7 @@ bool driver_init (void) } } +#ifdef HAS_IOPORTS output_signal_t *output; for(i = 0 ; i < sizeof(outputpin) / sizeof(output_signal_t); i++) { output = &outputpin[i]; @@ -2345,14 +2330,17 @@ bool driver_init (void) } } -#ifdef HAS_BOARD_INIT - board_init(&aux_inputs, &aux_outputs); + ioports_init(&aux_inputs, &aux_outputs); #endif #if ETHERNET_ENABLE grbl_enet_init(); #endif +#if SPINDLE_HUANYANG + huanyang_init(modbus_init(serialInit(115200), NULL)); +#endif + #if KEYPAD_ENABLE keypad_init(); #endif @@ -2370,6 +2358,10 @@ bool driver_init (void) openpnp_init(); #endif +#if BLUETOOTH_ENABLE + bluetooth_init(serialInit(115200)); +#endif + #if ODOMETER_ENABLE odometer_init(); // NOTE: this *must* be last plugin to be initialized as it claims storage at the end of NVS. #endif @@ -2548,16 +2540,17 @@ static void gpio_isr (void) uint32_t i = sizeof(inputpin) / sizeof(input_signal_t); do { - if(inputpin[--i].irq_mode != IRQ_Mode_None) { + if(inputpin[--i].irq_mode != IRQ_Mode_None || inputpin[i].group == PinGroup_AuxInput) { if(intr_status[inputpin[i].offset] & inputpin[i].gpio.bit) { inputpin[i].active = true; + if(inputpin[i].debounce && enqueue_debounce(&inputpin[i])) { inputpin[i].gpio.reg->IMR &= ~inputpin[i].gpio.bit; debounce = true; - } else { + } else switch(inputpin[i].group) { #if QEI_ENABLE - if(inputpin[i].group & PinGroup_QEI) { + casePinGroup_QEI: qei_update(); /* QEI_A.reg->IMR &= ~QEI_A.bit; // Switch off @@ -2567,19 +2560,33 @@ static void gpio_isr (void) qei.debounce = QEI_DEBOUNCE; qei.initial_debounce = true; */ - } else + break; #endif #if SPINDLE_SYNC_ENABLE && defined(SPINDLE_INDEX_PIN) - if(inputpin[i].group & PinGroup_SpindleIndex) { + case PinGroup_SpindleIndex: spindleLock = true; spindle_encoder.counter.index_count++; spindle_encoder.counter.last_index = GPT2_CNT; spindle_encoder.timer.last_index = GPT1_CNT; spindleLock = false; - } else + break; #endif + +#if KEYPAD_ENABLE + case PinGroup_Keypad: + keypad_keyclick_handler(!(KeypadStrobe.reg->DR & KeypadStrobe.bit)); + break; +#endif + +#ifdef HAS_IOPORTS + case PinGroup_AuxInput: + ioports_event(&inputpin[i]); + break; +#endif + default: grp |= inputpin[i].group; + break; } } } @@ -2622,11 +2629,6 @@ static void gpio_isr (void) mpg_mutex = false; } #endif - -#if KEYPAD_ENABLE - if(grp & PinGroup_Keypad) - keypad_keyclick_handler(!(KeypadStrobe.reg->DR & KeypadStrobe.bit)); -#endif } // Interrupt handler for 1 ms interval timer diff --git a/grblHAL_Teensy4/src/driver.h b/grblHAL_Teensy4/src/driver.h index ffac504..68b54e4 100644 --- a/grblHAL_Teensy4/src/driver.h +++ b/grblHAL_Teensy4/src/driver.h @@ -34,9 +34,7 @@ #include "my_machine.h" #endif -#include "grbl/hal.h" -#include "grbl/nuts_bolts.h" -#include "grbl/crossbar.h" +#include "grbl/driver_opts.h" #define DIGITAL_IN(gpio) (!!(gpio.reg->DR & gpio.bit)) #define DIGITAL_OUT(gpio, on) { if(on) gpio.reg->DR_SET = gpio.bit; else gpio.reg->DR_CLEAR = gpio.bit; } @@ -45,111 +43,6 @@ //#define UART_DEBUG // For development only - enable only with USB_SERIAL_CDC enabled and SPINDLE_HUANYANG disabled #endif -#ifndef USB_SERIAL_CDC -#define USB_SERIAL_CDC 0 // for UART comms -#endif -#ifndef USB_SERIAL_WAIT -#define USB_SERIAL_WAIT 0 -#endif -#ifndef SDCARD_ENABLE -#define SDCARD_ENABLE 0 -#endif -#ifndef KEYPAD_ENABLE -#define KEYPAD_ENABLE 0 -#endif -#ifndef EEPROM_ENABLE -#define EEPROM_ENABLE 0 -#endif -#ifndef EEPROM_IS_FRAM -#define EEPROM_IS_FRAM 0 -#endif -#ifndef SPINDLE_SYNC_ENABLE -#define SPINDLE_SYNC_ENABLE 0 -#endif -#ifndef TRINAMIC_ENABLE -#define TRINAMIC_ENABLE 0 -#endif -#ifndef TRINAMIC_I2C -#define TRINAMIC_I2C 0 -#endif -#ifndef TRINAMIC_DEV -#define TRINAMIC_DEV 0 -#endif -#ifndef PLASMA_ENABLE -#define PLASMA_ENABLE 0 -#endif -#ifndef PPI_ENABLE -#define PPI_ENABLE 0 -#endif -#ifndef SPINDLE_HUANYANG -#define SPINDLE_HUANYANG 0 -#endif -#ifndef QEI_ENABLE -#define QEI_ENABLE 0 -#endif -#ifndef ODOMETER_ENABLE -#define ODOMETER_ENABLE 0 -#endif -#ifndef OPENPNP_ENABLE -#define OPENPNP_ENABLE 0 -#endif - -#ifndef ESTOP_ENABLE - #if COMPATIBILITY_LEVEL <= 1 - #define ESTOP_ENABLE 1 - #else - #define ESTOP_ENABLE 0 - #endif -#elif ESTOP_ENABLE && COMPATIBILITY_LEVEL > 1 - #warning "Enabling ESTOP may not work with all senders!" -#endif - -#ifndef ETHERNET_ENABLE -#define ETHERNET_ENABLE 0 -#endif -#ifndef TELNET_ENABLE -#define TELNET_ENABLE 0 -#endif -#ifndef WEBSOCKET_ENABLE -#define WEBSOCKET_ENABLE 0 -#endif -#ifndef FTP_ENABLE -#define FTP_ENABLE 0 -#elif !SDCARD_ENABLE -#undef FTP_ENABLE -#define FTP_ENABLE 0 -#endif - -#if ETHERNET_ENABLE -#ifndef NETWORK_HOSTNAME -#define NETWORK_HOSTNAME "GRBL" -#endif -#ifndef NETWORK_IPMODE -#define NETWORK_IPMODE 1 // 0 = static, 1 = DHCP, 2 = AutoIP -#endif -#ifndef NETWORK_IP -#define NETWORK_IP "192.168.5.1" -#endif -#ifndef NETWORK_GATEWAY -#define NETWORK_GATEWAY "192.168.5.1" -#endif -#ifndef NETWORK_MASK -#define NETWORK_MASK "255.255.255.0" -#endif -#ifndef NETWORK_TELNET_PORT -#define NETWORK_TELNET_PORT 23 -#endif -#ifndef NETWORK_WEBSOCKET_PORT -#define NETWORK_WEBSOCKET_PORT 80 -#endif -#ifndef NETWORK_HTTP_PORT -#define NETWORK_HTTP_PORT 80 -#endif -#if NETWORK_IPMODE < 0 || NETWORK_IPMODE > 2 -#error "Invalid IP mode selected!" -#endif -#endif - // Timer assignments (for reference, Arduino libs does not follow the CMSIS style...) //#define STEPPER_TIMER PIT0 (32 bit) @@ -163,8 +56,6 @@ //#define RPM_TIMER GPT1 //#define RPM_COUNTER GPT2 -// End configuration - #ifdef BOARD_CNC_BOOSTERPACK #include "cnc_boosterpack_map.h" #elif defined(BOARD_T40X101) @@ -212,6 +103,10 @@ #include "encoder/encoder.h" #endif +#if BLUETOOTH_ENABLE && USB_SERIAL_CDC == 0 +#error "Bluetooth cannot be used with UART communications enabled!" +#endif + #if SPINDLE_HUANYANG #if USB_SERIAL_CDC == 0 #error "Huanyang VFD cannot be used with UART communications enabled!" @@ -286,6 +181,8 @@ typedef struct { uint8_t offset; volatile bool active; volatile bool debounce; + pin_mode_t cap; + ioport_interrupt_callback_ptr interrupt_callback; } input_signal_t; typedef struct { @@ -312,13 +209,13 @@ typedef struct { const uint32_t select_val; // Value for that selection } pin_info_t; -// - void pinModeOutput (gpio_t *gpio, uint8_t pin); +void pinEnableIRQ (const input_signal_t *signal, pin_irq_mode_t irq_mode); uint32_t xTaskGetTickCount(); -#ifdef HAS_BOARD_INIT -void board_init(pin_group_pins_t *aux_inputs, pin_group_pins_t *aux_outputs); +#ifdef HAS_IOPORTS +void ioports_init (pin_group_pins_t *aux_inputs, pin_group_pins_t *aux_outputs); +void ioports_event (input_signal_t *input); #endif #ifdef UART_DEBUG diff --git a/grblHAL_Teensy4/src/enet.c b/grblHAL_Teensy4/src/enet.c index e6ac89f..107adff 100644 --- a/grblHAL_Teensy4/src/enet.c +++ b/grblHAL_Teensy4/src/enet.c @@ -38,13 +38,14 @@ #include "networking/networking.h" +static bool enet_started = false; static volatile bool linkUp = false; static char IPAddress[IP4ADDR_STRLEN_MAX]; static network_services_t services = {0}, allowed_services; static nvs_address_t nvs_address; static network_settings_t ethernet, network; static on_report_options_ptr on_report_options;; -static char netservices[30] = ""; // must be large enough to hold all service names +static char netservices[40] = ""; // must be large enough to hold all service names static void report_options (bool newopt) { @@ -105,6 +106,9 @@ void grbl_enet_poll (void) static uint32_t last_ms0, last_ms1; uint32_t ms; + if(!enet_started) + return; + enet_proc_input(); ms = millis(); @@ -154,6 +158,8 @@ bool grbl_enet_start (void) #endif if(network.ip_mode == IpMode_DHCP) dhcp_start(netif_default); + + enet_started = true; } return nvs_address != 0; diff --git a/grblHAL_Teensy4/src/generic_map.h b/grblHAL_Teensy4/src/generic_map.h index ce6f844..ae22554 100644 --- a/grblHAL_Teensy4/src/generic_map.h +++ b/grblHAL_Teensy4/src/generic_map.h @@ -19,38 +19,46 @@ along with Grbl. If not, see . */ +#if N_ABC_MOTORS > 2 +#error "Axis configuration is not supported!" +#endif + #if SPINDLE_SYNC_ENABLE -#error Spindle sync is not supported +#error "Spindle sync is not supported" #endif // Define step pulse output pins. -#define X_STEP_PIN (2u) -#define Y_STEP_PIN (4u) -#define Z_STEP_PIN (6u) +#define X_STEP_PIN (2u) +#define Y_STEP_PIN (4u) +#define Z_STEP_PIN (6u) // Define step direction output pins. -#define X_DIRECTION_PIN (3u) -#define Y_DIRECTION_PIN (5u) -#define Z_DIRECTION_PIN (7u) +#define X_DIRECTION_PIN (3u) +#define Y_DIRECTION_PIN (5u) +#define Z_DIRECTION_PIN (7u) // Define stepper driver enable/disable output pin(s). #define STEPPERS_ENABLE_PIN (10u) // Define homing/hard limit switch input pins. -#define X_LIMIT_PIN (20u) -#define Y_LIMIT_PIN (21u) -#define Z_LIMIT_PIN (22u) +#define X_LIMIT_PIN (20u) +#define Y_LIMIT_PIN (21u) +#define Z_LIMIT_PIN (22u) -#if N_AXIS > 3 -#define A_STEP_PIN (8u) -#define A_DIRECTION_PIN (9u) -#define A_LIMIT_PIN (23u) +// Define ganged axis or A axis step pulse and step direction output pins. +#if N_ABC_MOTORS > 0 +#define M3_AVAILABLE +#define M3_STEP_PIN (8u) +#define M3_DIRECTION_PIN (9u) +#define M3_LIMIT_PIN (23u) #endif -#if N_AXIS > 4 -#define B_STEP_PIN (26u) -#define B_DIRECTION_PIN (27u) -#define B_LIMIT_PIN (28u) +// Define ganged axis or B axis step pulse and step direction output pins. +#if N_ABC_MOTORS == 2 +#define M4_AVAILABLE +#define M4_STEP_PIN (26u) +#define M4_DIRECTION_PIN (27u) +#define M4_LIMIT_PIN (28u) #endif // Define spindle enable and spindle direction output pins. diff --git a/grblHAL_Teensy4/src/T41U5XBB.c b/grblHAL_Teensy4/src/ioports.c similarity index 52% rename from grblHAL_Teensy4/src/T41U5XBB.c rename to grblHAL_Teensy4/src/ioports.c index 3a82951..938b418 100644 --- a/grblHAL_Teensy4/src/T41U5XBB.c +++ b/grblHAL_Teensy4/src/ioports.c @@ -1,5 +1,5 @@ /* - T41U5XBB.c - driver code for IMXRT1062 processor (on Teensy 4.1 board) + ioports.c - driver code for IMXRT1062 processor (on Teensy 4.1 board) Part of grblHAL @@ -23,7 +23,7 @@ #include "driver.h" -#if defined(BOARD_T41U5XBB) || defined(BOARD_T41U5XBB_SS) || defined(BOARD_T41BB5X_PRO) +#ifdef HAS_IOPORTS //#include "Arduino.h" #include @@ -32,6 +32,8 @@ #include "grbl/protocol.h" static uint_fast8_t aux_n_in, aux_n_out; +static volatile uint32_t event_bits; +static volatile bool spin_lock = false; static input_signal_t *aux_in; static output_signal_t *aux_out; static ioport_bus_t out = {0}; @@ -40,14 +42,15 @@ static char input_ports[56] = "", output_ports[56] = ""; static void aux_settings_load (void); static status_code_t aux_set_invert_out (setting_id_t id, uint_fast16_t int_value); static uint32_t aux_get_invert_out (setting_id_t setting); +static bool is_setting_available (const setting_detail_t *setting); static const setting_group_detail_t aux_groups[] = { { Group_Root, Group_AuxPorts, "Aux ports"} }; static const setting_detail_t aux_settings[] = { - { Settings_IoPort_InvertIn, Group_AuxPorts, "Invert I/O Port inputs", NULL, Format_Bitfield, input_ports, NULL, NULL, Setting_NonCore, &settings.ioport.invert_in.mask }, - { Settings_IoPort_InvertOut, Group_AuxPorts, "Invert I/O Port outputs", NULL, Format_Bitfield, output_ports, NULL, NULL, Setting_NonCoreFn, aux_set_invert_out, aux_get_invert_out }, + { Settings_IoPort_InvertIn, Group_AuxPorts, "Invert I/O Port inputs", NULL, Format_Bitfield, input_ports, NULL, NULL, Setting_NonCore, &settings.ioport.invert_in.mask, NULL, is_setting_available }, + { Settings_IoPort_InvertOut, Group_AuxPorts, "Invert I/O Port outputs", NULL, Format_Bitfield, output_ports, NULL, NULL, Setting_NonCoreFn, aux_set_invert_out, aux_get_invert_out, is_setting_available }, }; static setting_details_t details = { @@ -59,6 +62,29 @@ static setting_details_t details = { .save = settings_write_global }; +static bool is_setting_available (const setting_detail_t *setting) +{ + bool available = false; + + switch(setting->id) { + + case Settings_IoPort_InvertIn: + case Settings_IoPort_Pullup_Disable: + available = aux_n_in > 0; + break; + + case Settings_IoPort_InvertOut: + case Settings_IoPort_OD_Enable: + available = aux_n_out > 0; + break; + + default: + break; + } + + return available; +} + static setting_details_t *on_get_settings (void) { return &details; @@ -70,6 +96,7 @@ static void aux_settings_load (void) do { idx--; + pinModeOutput(aux_out[idx].port, aux_out[idx].pin); DIGITAL_OUT((*(aux_out[idx].port)), (settings.ioport.invert_out.mask >> idx) & 0x01); } while(idx); } @@ -104,27 +131,67 @@ static void digital_out (uint8_t port, bool on) DIGITAL_OUT((*(aux_out[port].port)), ((settings.ioport.invert_out.mask >> port) & 0x01) ? !on : on); } -inline static __attribute__((always_inline)) int32_t get_input (gpio_t *gpio, bool invert, wait_mode_t wait_mode, float timeout) +inline static __attribute__((always_inline)) int32_t get_input (const input_signal_t *input, bool invert, wait_mode_t wait_mode, float timeout) { if(wait_mode == WaitMode_Immediate) - return !!(gpio->reg->DR & gpio->bit) ^ invert; + return DIGITAL_IN(input->gpio) ^ invert; + int32_t value = -1; uint_fast16_t delay = (uint_fast16_t)ceilf((1000.0f / 50.0f) * timeout) + 1; - bool wait_for = wait_mode != WaitMode_Low; + if(wait_mode == WaitMode_Rise || wait_mode == WaitMode_Fall) { - do { - if((!!(gpio->reg->DR & gpio->bit) ^ invert) == wait_for) - return !!(gpio->reg->DR & gpio->bit); + pin_irq_mode_t irq_mode = wait_mode == WaitMode_Rise ? IRQ_Mode_Rising : IRQ_Mode_Falling; - if(delay) { - protocol_execute_realtime(); - hal.delay_ms(50, NULL); - } else - break; - } while(--delay && !sys.abort); + if(input->cap.irq_mode & irq_mode) { - return -1; + event_bits &= ~input->gpio.bit; + pinEnableIRQ(input, irq_mode); + + do { + if(event_bits & input->gpio.bit) { + value = DIGITAL_IN(input->gpio) ^ invert; + break; + } + if(delay) { + protocol_execute_realtime(); + hal.delay_ms(50, NULL); + } else + break; + } while(--delay && !sys.abort); + + pinEnableIRQ(input, IRQ_Mode_None); // Restore pin interrupt status + } + + } else { + + bool wait_for = wait_mode != WaitMode_Low; + + do { + if((DIGITAL_IN(input->gpio) ^ invert) == wait_for) { + value = DIGITAL_IN(input->gpio); + break; + } + if(delay) { + protocol_execute_realtime(); + hal.delay_ms(50, NULL); + } else + break; + } while(--delay && !sys.abort); + } + + return value; +} + +void ioports_event (input_signal_t *input) +{ + spin_lock = true; + event_bits |= input->gpio.bit; + + if(input->interrupt_callback) + input->interrupt_callback(input->id - Output_Aux0, !!(input->port->reg->DR & input->port->bit)); + + spin_lock = false; } static int32_t wait_on_input (bool digital, uint8_t port, wait_mode_t wait_mode, float timeout) @@ -133,29 +200,51 @@ static int32_t wait_on_input (bool digital, uint8_t port, wait_mode_t wait_mode, if(digital) { if(port < aux_n_in) - value = get_input(aux_in[port].port, (settings.ioport.invert_in.mask << port) & 0x01, wait_mode, timeout); + value = get_input(&aux_in[port], (settings.ioport.invert_in.mask << port) & 0x01, wait_mode, timeout); } // else if(port == 0) // value = analogRead(41); -/* - hal.stream.write("[MSG:AUX"); - hal.stream.write(uitoa(port)); - hal.stream.write("="); - hal.stream.write(value == -1 ? "fail" : uitoa(value)); - hal.stream.write("]" ASCII_EOL); -*/ + return value; } -void board_init (pin_group_pins_t *aux_inputs, pin_group_pins_t *aux_outputs) +static bool register_interrupt_handler (uint8_t port, pin_irq_mode_t irq_mode, ioport_interrupt_callback_ptr interrupt_callback) +{ + bool ok; + + if((ok = port < aux_n_in && aux_in[port].cap.irq_mode != IRQ_Mode_None)) { + + input_signal_t *input = &aux_in[port]; + + if(irq_mode != IRQ_Mode_None && (ok = interrupt_callback != NULL)) { + input->irq_mode = irq_mode; + input->interrupt_callback = interrupt_callback; + pinEnableIRQ(input, irq_mode); + } + + if(irq_mode == IRQ_Mode_None || !ok) { + while(spin_lock); + pinEnableIRQ(input, IRQ_Mode_None); + input->irq_mode = IRQ_Mode_None; + input->interrupt_callback = NULL; + } + } + + return ok; +} + +void ioports_init (pin_group_pins_t *aux_inputs, pin_group_pins_t *aux_outputs) { aux_in = aux_inputs->pins.inputs; aux_out = aux_outputs->pins.outputs; - hal.port.wait_on_input = wait_on_input; - hal.port.digital_out = digital_out; - hal.port.num_digital_in = aux_n_in = aux_inputs->n_pins; - hal.port.num_digital_out = aux_n_out = aux_outputs->n_pins; + if((hal.port.num_digital_in = aux_n_in = aux_inputs->n_pins)) { + hal.port.wait_on_input = wait_on_input; + hal.port.register_interrupt_handler = register_interrupt_handler; + } + + if((hal.port.num_digital_out = aux_n_out = aux_outputs->n_pins)) + hal.port.digital_out = digital_out; details.on_get_settings = grbl.on_get_settings; grbl.on_get_settings = on_get_settings; diff --git a/grblHAL_Teensy4/src/my_machine.h b/grblHAL_Teensy4/src/my_machine.h index ceb78e5..f46a475 100644 --- a/grblHAL_Teensy4/src/my_machine.h +++ b/grblHAL_Teensy4/src/my_machine.h @@ -51,10 +51,11 @@ N_AXIS has a default value of 3, edit grbl\config.h to increase. #define USB_SERIAL_CDC 2 // 1 for Arduino class library and 2 for PJRC C library. Comment out to use UART communication. //#define USB_SERIAL_WAIT 1 // Wait for USB connection before starting grblHAL. +//#define BLUETOOTH_ENABLE 1 // Set to 1 for HC-05 module. Requires Bluetooth plugin. //#define SPINDLE_HUANYANG 1 // Set to 1 or 2 for Huanyang VFD spindle. Requires spindle plugin. //#define QEI_ENABLE 1 // Enable quadrature encoder interfaces. Max value is 1. Requires encoder plugin. //#define ETHERNET_ENABLE 1 // Ethernet streaming. Requires networking plugin. -//#define SDCARD_ENABLE 2 // Run gcode programs from SD card, requires sdcard plugin. +//#define SDCARD_ENABLE 1 // Run gcode programs from SD card, requires sdcard plugin. //#define KEYPAD_ENABLE 1 // I2C keypad for jogging etc., requires keypad plugin. //#define PLASMA_ENABLE 1 // Plasma/THC plugin. To be completed. //#define PPI_ENABLE 1 // Laser PPI plugin. To be completed. @@ -67,9 +68,24 @@ N_AXIS has a default value of 3, edit grbl\config.h to increase. //#define ESTOP_ENABLE 0 // When enabled only real-time report requests will be executed when the reset pin is asserted. // Note: if left commented out the default setting is determined from COMPATIBILITY_LEVEL. +// If the selected board map supports more than three motors ganging and/or auto-squaring +// of axes can be enabled here. +//#define X_GANGED 1 +//#define X_AUTO_SQUARE 1 +//#define Y_GANGED 1 +//#define Y_AUTO_SQUARE 1 +//#define Z_GANGED 1 +//#define Z_AUTO_SQUARE 1 +// For ganged axes the limit switch input (if available) can be configured to act as a max travel limit switch. +// NOTE: If board map already has max limit inputs defined this configuration will be ignored. +//#define X_GANGED_LIM_MAX 1 +//#define Y_GANGED_LIM_MAX 1 +//#define Z_GANGED_LIM_MAX 1 +// + #if ETHERNET_ENABLE > 0 #define TELNET_ENABLE 1 // Telnet daemon - requires Ethernet streaming enabled. -#define FTP_ENABLE 0 // Ftp daemon - requires SD card enabled. !!DO NOT ENABLE - there is a bug in the FatFS library that has to be fixed first!! +#define FTP_ENABLE 1 // Ftp daemon - requires SD card enabled. #define WEBSOCKET_ENABLE 1 // Websocket daemon - requires Ethernet streaming enabled. #define NETWORK_HOSTNAME "GRBL" #define NETWORK_IPMODE 1 // 0 = static, 1 = DHCP, 2 = AutoIP diff --git a/grblHAL_Teensy4/src/my_plugin.c b/grblHAL_Teensy4/src/my_plugin.c new file mode 100644 index 0000000..d65987b --- /dev/null +++ b/grblHAL_Teensy4/src/my_plugin.c @@ -0,0 +1,75 @@ +/* + + my_plugin.c - plugin template for setting auxillary output on feed hold + + Part of grblHAL + + Public domain. + +*/ + +#include + +#include "driver.h" +#include "grbl/protocol.h" + +static uint8_t port; + +static on_state_change_ptr on_state_change; +static on_report_options_ptr on_report_options; + +static void onStateChanged (sys_state_t state) +{ + static sys_state_t last_state = STATE_IDLE; + + if(state != last_state) { + last_state = state; + hal.port.digital_out(port, state == STATE_HOLD); + } + + if(on_state_change) // Call previous function in the chain. + on_state_change(state); +} + +static void onReportOptions (bool newopt) +{ + on_report_options(newopt); // Call previous function in the chain. + + if(!newopt) // Add info about us to the $I report. + hal.stream.write("[PLUGIN:MY PLUGIN Template 2]" ASCII_EOL); +} + +static void output_warning (uint_fast16_t state) +{ + report_message("An output port is required for my_plugin!", Message_Warning); +} + +// Tell the user about which port is used for the output +static void output_port (uint_fast16_t state) +{ + char msg[30]; + + strcpy(msg, "My plugin port: "); + strcat(msg, uitoa(port)); + + report_message(msg, Message_Info); +} + +void xmy_plugin_init() +{ + if(hal.port.num_digital_out == 0) // This plugin requires one digital output port, + protocol_enqueue_rt_command(output_warning); // complain if not available. + + else { + port = hal.port.num_digital_out - 1; // Claim the + hal.port.num_digital_out--; // last free port. + + on_state_change = grbl.on_state_change; // Subscribe to the state changed event by saving away the original + grbl.on_state_change = onStateChanged; // function pointer and adding ours to the chain. + + on_report_options = grbl.on_report_options; // Add our plugin to to the options report chain + grbl.on_report_options = onReportOptions; // to tell the user we are active. + + protocol_enqueue_rt_command(output_port); // Tell the user about which port is used for the output after startup is complete. + } +} diff --git a/grblHAL_Teensy4/src/uart.c b/grblHAL_Teensy4/src/uart.c index 82f69d0..ecf9a93 100644 --- a/grblHAL_Teensy4/src/uart.c +++ b/grblHAL_Teensy4/src/uart.c @@ -143,113 +143,10 @@ static uint16_t tx_fifo_size; static stream_tx_buffer_t txbuffer = {0}; static stream_rx_buffer_t rxbuffer = {0}; -void serialInit (uint32_t baud_rate) -{ -// uart_hardware_t *hardware = &UART; - float base = (float)UART_CLOCK / (float)baud_rate; - float besterr = 1e20; - int bestdiv = 1; - int bestosr = 4; - for (int osr = 4; osr <= 32; osr++) { - float div = base / (float)osr; - int divint = (int)(div + 0.5f); - if (divint < 1) - divint = 1; - else if (divint > 8191) - divint = 8191; - float err = ((float)divint - div) / div; - if (err < 0.0f) - err = -err; - if (err <= besterr) { - besterr = err; - bestdiv = divint; - bestosr = osr; - } - } - - *UART.ccm_register |= UART.ccm_value; - - *(portControlRegister(UART.rx_pin.pin)) = IOMUXC_PAD_DSE(7) | IOMUXC_PAD_PKE | IOMUXC_PAD_PUE | IOMUXC_PAD_PUS(3) | IOMUXC_PAD_HYS; - *(portConfigRegister(UART.rx_pin.pin)) = UART.rx_pin.mux_val; - if (UART.rx_pin.select_reg) - *(UART.rx_pin.select_reg) = UART.rx_pin.select_val; - - *(portControlRegister(UART.tx_pin.pin)) = IOMUXC_PAD_SRE | IOMUXC_PAD_DSE(3) | IOMUXC_PAD_SPEED(3); - *(portConfigRegister(UART.tx_pin.pin)) = UART.tx_pin.mux_val; - if (UART.tx_pin.select_reg) - *(UART.tx_pin.select_reg) = UART.tx_pin.select_val; - - UART.port->BAUD = LPUART_BAUD_OSR(bestosr - 1) | LPUART_BAUD_SBR(bestdiv) | (bestosr <= 8 ? LPUART_BAUD_BOTHEDGE : 0); - UART.port->PINCFG = 0; - - // Enable the transmitter, receiver and enable receiver interrupt - NVIC_DISABLE_IRQ(UART.irq); - attachInterruptVector(UART.irq, UART.irq_handler); - NVIC_SET_PRIORITY(UART.irq, 0); - NVIC_ENABLE_IRQ(UART.irq); - - tx_fifo_size = (UART.port->FIFO >> 4) & 0x7; - tx_fifo_size = tx_fifo_size ? (2 << tx_fifo_size) : 1; - - uint8_t tx_water = (tx_fifo_size < 16) ? tx_fifo_size >> 1 : 7; - uint16_t rx_fifo_size = (((UART.port->FIFO >> 0) & 0x7) << 2); - uint8_t rx_water = (rx_fifo_size < 16) ? rx_fifo_size >> 1 : 7; - /* - Serial.printf("SerialX::begin stat:%x ctrl:%x fifo:%x water:%x\n", UART.port->STAT, UART.port->CTRL, UART.port->FIFO, UART.port->WATER ); - Serial.printf(" FIFO sizes: tx:%d rx:%d\n",tx_fifo_size, rx_fifo_size); - Serial.printf(" Watermark tx:%d, rx: %d\n", tx_water, rx_water); - */ - UART.port->WATER = LPUART_WATER_RXWATER(rx_water) | LPUART_WATER_TXWATER(tx_water); - UART.port->FIFO |= LPUART_FIFO_TXFE | LPUART_FIFO_RXFE; - // lets configure up our CTRL register value - uint32_t ctrl = CTRL_TX_INACTIVE; - -uint16_t format = 0; - - // Now process the bits in the Format value passed in - // Bits 0-2 - Parity plus 9 bit. - ctrl |= (format & (LPUART_CTRL_PT | LPUART_CTRL_PE) ); // configure parity - turn off PT, PE, M and configure PT, PE - if (format & 0x04) ctrl |= LPUART_CTRL_M; // 9 bits (might include parity) - if ((format & 0x0F) == 0x04) ctrl |= LPUART_CTRL_R9T8; // 8N2 is 9 bit with 9th bit always 1 - - // Bit 5 TXINVERT - if (format & 0x20) ctrl |= LPUART_CTRL_TXINV; // tx invert - - // write out computed CTRL - UART.port->CTRL = ctrl; - - // Bit 3 10 bit - Will assume that begin already cleared it. - // process some other bits which change other registers. - if (format & 0x08) UART.port->BAUD |= LPUART_BAUD_M10; - - // Bit 4 RXINVERT - uint32_t c = UART.port->STAT & ~LPUART_STAT_RXINV; - if (format & 0x10) c |= LPUART_STAT_RXINV; // rx invert - UART.port->STAT = c; - - // bit 8 can turn on 2 stop bit mote - if ( format & 0x100) UART.port->BAUD |= LPUART_BAUD_SBNS; - -//transmitterEnable(1); - hal.stream.connected = true; -} - -bool serialSetBaudRate (uint32_t baud_rate) -{ - static bool init_ok = false; - - if(!init_ok) { - serialInit(baud_rate); - init_ok = true; - } - - return true; -} - // // serialGetC - returns -1 if no data available // -int16_t serialGetC (void) +static int16_t serialGetC (void) { int16_t data; uint_fast16_t bptr = rxbuffer.tail; @@ -263,37 +160,37 @@ int16_t serialGetC (void) return data; } -void serialTxFlush (void) +static void serialTxFlush (void) { txbuffer.tail = txbuffer.head; } -uint16_t serialRxCount (void) +static uint16_t serialRxCount (void) { uint_fast16_t head = rxbuffer.head, tail = rxbuffer.tail; return BUFCOUNT(head, tail, RX_BUFFER_SIZE); } -uint16_t serialRxFree (void) +static uint16_t serialRxFree (void) { return (RX_BUFFER_SIZE - 1) - serialRxCount(); } -void serialRxFlush (void) +static void serialRxFlush (void) { rxbuffer.tail = rxbuffer.head; rxbuffer.overflow = false; } -void serialRxCancel (void) +static void serialRxCancel (void) { serialRxFlush(); rxbuffer.data[rxbuffer.head] = ASCII_CAN; rxbuffer.head = (rxbuffer.tail + 1) & (RX_BUFFER_SIZE - 1); } -bool serialPutC (const char c) +static bool serialPutC (const char c) { uint_fast16_t next_head; @@ -324,7 +221,7 @@ bool serialPutC (const char c) return true; } -void serialWriteS (const char *data) +static void serialWriteS (const char *data) { char c, *ptr = (char *)data; @@ -332,7 +229,7 @@ void serialWriteS (const char *data) serialPutC(c); } -void serialWrite(const char *s, uint16_t length) +static void serialWrite(const char *s, uint16_t length) { char *ptr = (char *)s; @@ -340,18 +237,150 @@ void serialWrite(const char *s, uint16_t length) serialPutC(*ptr++); } -bool serialSuspendInput (bool suspend) +static bool serialSuspendInput (bool suspend) { return stream_rx_suspend(&rxbuffer, suspend); } -uint16_t serialTxCount(void) { +static uint16_t serialTxCount(void) { uint_fast16_t head = txbuffer.head, tail = txbuffer.tail; return BUFCOUNT(head, tail, TX_BUFFER_SIZE) + ((UART.port->WATER >> 8) & 0x7) + ((UART.port->STAT & LPUART_STAT_TC) ? 0 : 1); } +static bool serialSetBaudRate (uint32_t baud_rate) +{ + float base = (float)UART_CLOCK / (float)baud_rate; + float besterr = 1e20; + int bestdiv = 1; + int bestosr = 4; + for (int osr = 4; osr <= 32; osr++) { + float div = base / (float)osr; + int divint = (int)(div + 0.5f); + if (divint < 1) + divint = 1; + else if (divint > 8191) + divint = 8191; + float err = ((float)divint - div) / div; + if (err < 0.0f) + err = -err; + if (err <= besterr) { + besterr = err; + bestdiv = divint; + bestosr = osr; + } + } + + UART.port->BAUD = LPUART_BAUD_OSR(bestosr - 1) | LPUART_BAUD_SBR(bestdiv) | (bestosr <= 8 ? LPUART_BAUD_BOTHEDGE : 0); + + return true; +} + +static bool serialDisable (bool disable) +{ + if(disable) + NVIC_DISABLE_IRQ(UART.irq); + else + NVIC_ENABLE_IRQ(UART.irq); + + return true; +} + +const io_stream_t *serialInit (uint32_t baud_rate) +{ + PROGMEM static const io_stream_t stream = { + .type = StreamType_Serial, + .connected = true, + .read = serialGetC, + .write = serialWriteS, + .write_n = serialWrite, + .write_char = serialPutC, + .write_all = serialWriteS, + .get_rx_buffer_free = serialRxFree, + .get_rx_buffer_count = serialRxCount, + .get_tx_buffer_count = serialTxCount, + .reset_write_buffer = serialTxFlush, + .reset_read_buffer = serialRxFlush, + .cancel_read_buffer = serialRxCancel, + .suspend_read = serialSuspendInput, + .disable = serialDisable, + .set_baud_rate = serialSetBaudRate + }; + + *UART.ccm_register |= UART.ccm_value; + + *(portControlRegister(UART.rx_pin.pin)) = IOMUXC_PAD_DSE(7) | IOMUXC_PAD_PKE | IOMUXC_PAD_PUE | IOMUXC_PAD_PUS(3) | IOMUXC_PAD_HYS; + *(portConfigRegister(UART.rx_pin.pin)) = UART.rx_pin.mux_val; + if (UART.rx_pin.select_reg) + *(UART.rx_pin.select_reg) = UART.rx_pin.select_val; + + *(portControlRegister(UART.tx_pin.pin)) = IOMUXC_PAD_SRE | IOMUXC_PAD_DSE(3) | IOMUXC_PAD_SPEED(3); + *(portConfigRegister(UART.tx_pin.pin)) = UART.tx_pin.mux_val; + if (UART.tx_pin.select_reg) + *(UART.tx_pin.select_reg) = UART.tx_pin.select_val; + + serialSetBaudRate(baud_rate); + + UART.port->PINCFG = 0; + + // Enable the transmitter, receiver and enable receiver interrupt + NVIC_DISABLE_IRQ(UART.irq); + attachInterruptVector(UART.irq, UART.irq_handler); + NVIC_SET_PRIORITY(UART.irq, 0); + NVIC_ENABLE_IRQ(UART.irq); + + tx_fifo_size = (UART.port->FIFO >> 4) & 0x7; + tx_fifo_size = tx_fifo_size ? (2 << tx_fifo_size) : 1; + + uint8_t tx_water = (tx_fifo_size < 16) ? tx_fifo_size >> 1 : 7; + uint16_t rx_fifo_size = (((UART.port->FIFO >> 0) & 0x7) << 2); + uint8_t rx_water = (rx_fifo_size < 16) ? rx_fifo_size >> 1 : 7; + /* + Serial.printf("SerialX::begin stat:%x ctrl:%x fifo:%x water:%x\n", UART.port->STAT, UART.port->CTRL, UART.port->FIFO, UART.port->WATER ); + Serial.printf(" FIFO sizes: tx:%d rx:%d\n",tx_fifo_size, rx_fifo_size); + Serial.printf(" Watermark tx:%d, rx: %d\n", tx_water, rx_water); + */ + UART.port->WATER = LPUART_WATER_RXWATER(rx_water) | LPUART_WATER_TXWATER(tx_water); + UART.port->FIFO |= LPUART_FIFO_TXFE | LPUART_FIFO_RXFE; + // lets configure up our CTRL register value + uint32_t ctrl = CTRL_TX_INACTIVE; + +uint16_t format = 0; + + // Now process the bits in the Format value passed in + // Bits 0-2 - Parity plus 9 bit. + ctrl |= (format & (LPUART_CTRL_PT | LPUART_CTRL_PE) ); // configure parity - turn off PT, PE, M and configure PT, PE + if (format & 0x04) + ctrl |= LPUART_CTRL_M; // 9 bits (might include parity) + if ((format & 0x0F) == 0x04) + ctrl |= LPUART_CTRL_R9T8; // 8N2 is 9 bit with 9th bit always 1 + + // Bit 5 TXINVERT + if (format & 0x20) + ctrl |= LPUART_CTRL_TXINV; // tx invert + + // write out computed CTRL + UART.port->CTRL = ctrl; + + // Bit 3 10 bit - Will assume that begin already cleared it. + // process some other bits which change other registers. + if (format & 0x08) UART.port->BAUD |= LPUART_BAUD_M10; + + // Bit 4 RXINVERT + uint32_t c = UART.port->STAT & ~LPUART_STAT_RXINV; + if (format & 0x10) c |= LPUART_STAT_RXINV; // rx invert + UART.port->STAT = c; + + // bit 8 can turn on 2 stop bit mode + if (format & 0x100) + UART.port->BAUD |= LPUART_BAUD_SBNS; + +//transmitterEnable(1); + + return &stream; +} + static void uart_interrupt_handler (void) { uint_fast16_t bptr; diff --git a/grblHAL_Teensy4/src/uart.h b/grblHAL_Teensy4/src/uart.h index 1847bf4..2bf05ca 100644 --- a/grblHAL_Teensy4/src/uart.h +++ b/grblHAL_Teensy4/src/uart.h @@ -4,7 +4,7 @@ Part of grblHAL - Copyright (c) 2020 Terje Io + Copyright (c) 2020-2021 Terje Io Grbl is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -26,18 +26,8 @@ #include #include -void serialInit (uint32_t baud_rate); -bool serialSetBaudRate (uint32_t baud_rate); -int16_t serialGetC (void); -bool serialPutC (const char c); -void serialWrite(const char *s, uint16_t length); -void serialWriteS (const char *data); -bool serialSuspendInput (bool suspend); -uint16_t serialRxFree (void); -uint16_t serialRxCount (void); -uint16_t serialTxCount (void); -void serialRxFlush (void); -void serialTxFlush (void); -void serialRxCancel (void); +#include "grbl/hal.h" + +const io_stream_t *serialInit (uint32_t baud_rate); #endif diff --git a/grblHAL_Teensy4/src/usb_serial_ard.cpp b/grblHAL_Teensy4/src/usb_serial_ard.cpp index 118222f..0749d7f 100644 --- a/grblHAL_Teensy4/src/usb_serial_ard.cpp +++ b/grblHAL_Teensy4/src/usb_serial_ard.cpp @@ -39,36 +39,20 @@ extern "C" { static stream_block_tx_buffer_t txbuf = {0}; static char rxbuf[BLOCK_RX_BUFFER_SIZE]; static stream_rx_buffer_t usb_rxbuffer; - -void usb_serialInit(void) -{ - txbuf.s = txbuf.data; - - SerialUSB.begin(BAUD_RATE); - -#if USB_SERIAL_WAIT - while(!SerialUSB); // Wait for connection - - hal.stream.connected = true; -#endif - - txbuf.max_length = SerialUSB.availableForWrite(); // 6144 bytes - txbuf.max_length = (txbuf.max_length > BLOCK_TX_BUFFER_SIZE ? BLOCK_TX_BUFFER_SIZE : txbuf.max_length) - 20; -} - +/* // // Returns number of characters in serial input buffer // -uint16_t usb_serialRxCount (void) +static uint16_t usb_serialRxCount (void) { uint_fast16_t tail = usb_rxbuffer.tail, head = usb_rxbuffer.head; return (uint16_t)BUFCOUNT(head, tail, RX_BUFFER_SIZE); } - +*/ // // Returns number of free characters in serial input buffer // -uint16_t usb_serialRxFree (void) +static uint16_t usb_serialRxFree (void) { uint_fast16_t tail = usb_rxbuffer.tail, head = usb_rxbuffer.head; return (uint16_t)((RX_BUFFER_SIZE - 1) - BUFCOUNT(head, tail, RX_BUFFER_SIZE)); @@ -86,7 +70,7 @@ void usb_serialRxFlush (void) // // Flushes and adds a CAN character to the serial input buffer // -void usb_serialRxCancel (void) +static void usb_serialRxCancel (void) { usb_rxbuffer.data[usb_rxbuffer.head] = CMD_RESET; usb_rxbuffer.tail = usb_rxbuffer.head; @@ -96,7 +80,7 @@ void usb_serialRxCancel (void) // // Writes a character to the serial output stream // -bool usb_serialPutC (const char c) +static bool usb_serialPutC (const char c) { SerialUSB.write(c); @@ -108,7 +92,7 @@ bool usb_serialPutC (const char c) // Buffers locally up to 40 characters or until the string is terminated with a ASCII_LF character. // NOTE: grbl always sends ASCII_LF terminated strings! // -void usb_serialWriteS (const char *s) +static void usb_serialWriteS (const char *s) { if(*s == '\0') return; @@ -148,11 +132,11 @@ void usb_serialWriteS (const char *s) } } } - +/* // // Writes a null terminated string to the serial output stream followed by EOL, blocks if buffer full // -void usb_serialWriteLn (const char *s) +static void usb_serialWriteLn (const char *s) { usb_serialWriteS(s); usb_serialWriteS(ASCII_EOL); @@ -161,18 +145,18 @@ void usb_serialWriteLn (const char *s) // // Writes a number of characters from string to the serial output stream followed by EOL, blocks if buffer full // -void usb_serialWrite (const char *s, uint16_t length) +static void usb_serialWrite (const char *s, uint16_t length) { char *ptr = (char *)s; while(length--) usb_serialPutC(*ptr++); } - +*/ // // serialGetC - returns -1 if no data available // -int16_t usb_serialGetC (void) +static int16_t usb_serialGetC (void) { uint16_t bptr = usb_rxbuffer.tail; @@ -185,11 +169,43 @@ int16_t usb_serialGetC (void) return (int16_t)data; } -bool usb_serialSuspendInput (bool suspend) +static bool usb_serialSuspendInput (bool suspend) { return stream_rx_suspend(&usb_rxbuffer, suspend); } +const io_stream_t *usb_serialInit (void) +{ + PROGMEM static const io_stream_t stream = { + .type = StreamType_Serial, + .connected = false, + .get_rx_buffer_free = usb_serialRxFree, + .write = usb_serialWriteS, + .write_all = usb_serialWriteS, + .write_char = usb_serialPutC, + .read = usb_serialGetC, + .reset_read_buffer = usb_serialRxFlush, + .cancel_read_buffer = usb_serialRxCancel, + .suspend_read = usb_serialSuspendInput + }; + + txbuf.s = txbuf.data; + + SerialUSB.begin(BAUD_RATE); + +#if USB_SERIAL_WAIT + while(!SerialUSB); // Wait for connection + + hal.stream.connected = true; +#endif + + txbuf.max_length = SerialUSB.availableForWrite(); // 6144 bytes + txbuf.max_length = (txbuf.max_length > BLOCK_TX_BUFFER_SIZE ? BLOCK_TX_BUFFER_SIZE : txbuf.max_length) - 20; + + return &stream; +} + + // // This function get called from the systick interrupt handler, // used here to get characters off the USB serial input stream and buffer diff --git a/grblHAL_Teensy4/src/usb_serial_ard.h b/grblHAL_Teensy4/src/usb_serial_ard.h index 71f6285..53b7766 100644 --- a/grblHAL_Teensy4/src/usb_serial_ard.h +++ b/grblHAL_Teensy4/src/usb_serial_ard.h @@ -4,7 +4,7 @@ Part of grblHAL - Copyright (c) 2018-2020 Terje Io + Copyright (c) 2018-2021 Terje Io Grbl is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -27,22 +27,12 @@ #include #include +#include "grbl/hal.h" + extern void usb_execute_realtime (uint_fast16_t state); #define usb_serial_poll() usb_execute_realtime(0) -void usb_serialInit(void); -int16_t usb_serialGetC(void); -bool usb_serialPutC(const char c); -void usb_serialWriteS(const char *s); -void usb_serialWriteLn(const char *s); -void usb_serialWrite(const char *s, uint16_t length); -bool usb_serialSuspendInput (bool suspend); - -uint16_t usb_serialTxCount(void); -uint16_t usb_serialRxCount(void); -uint16_t usb_serialRxFree(void); -void usb_serialRxFlush(void); -void usb_serialRxCancel(void); +const io_stream_t *usb_serialInit(void); #endif diff --git a/grblHAL_Teensy4/src/usb_serial_pjrc.c b/grblHAL_Teensy4/src/usb_serial_pjrc.c index 1ce4b74..e59c76d 100644 --- a/grblHAL_Teensy4/src/usb_serial_pjrc.c +++ b/grblHAL_Teensy4/src/usb_serial_pjrc.c @@ -35,28 +35,20 @@ static stream_block_tx_buffer_t txbuf = {0}; static char rxbuf[BLOCK_RX_BUFFER_SIZE]; static stream_rx_buffer_t usb_rxbuffer; - -void usb_serialInit(void) -{ -// usb_serial_configure(); // Done somewhere already - do not call again - txbuf.s = txbuf.data; - txbuf.max_length = usb_serial_write_buffer_free(); // 6144 - txbuf.max_length = (txbuf.max_length > BLOCK_TX_BUFFER_SIZE ? BLOCK_TX_BUFFER_SIZE : txbuf.max_length) - 20; -} - +/* // // Returns number of characters in serial input buffer // -uint16_t usb_serialRxCount (void) +static uint16_t usb_serialRxCount (void) { uint_fast16_t tail = usb_rxbuffer.tail, head = usb_rxbuffer.head; return (uint16_t)BUFCOUNT(head, tail, RX_BUFFER_SIZE); } - +*/ // // Returns number of free characters in serial input buffer // -uint16_t usb_serialRxFree (void) +static uint16_t usb_serialRxFree (void) { uint_fast16_t tail = usb_rxbuffer.tail, head = usb_rxbuffer.head; return (uint16_t)((RX_BUFFER_SIZE - 1) - BUFCOUNT(head, tail, RX_BUFFER_SIZE)); @@ -65,7 +57,7 @@ uint16_t usb_serialRxFree (void) // // Flushes the serial input buffer (including the USB buffer) // -void usb_serialRxFlush (void) +static void usb_serialRxFlush (void) { usb_serial_flush_input(); usb_rxbuffer.tail = usb_rxbuffer.head; @@ -74,7 +66,7 @@ void usb_serialRxFlush (void) // // Flushes and adds a CAN character to the serial input buffer // -void usb_serialRxCancel (void) +static void usb_serialRxCancel (void) { usb_rxbuffer.data[usb_rxbuffer.head] = CMD_RESET; usb_rxbuffer.tail = usb_rxbuffer.head; @@ -84,7 +76,7 @@ void usb_serialRxCancel (void) // // Writes a character to the serial output stream // -bool usb_serialPutC (const char c) +static bool usb_serialPutC (const char c) { usb_serial_putchar(c); @@ -94,7 +86,7 @@ bool usb_serialPutC (const char c) // // Writes a null terminated string to the serial output stream, blocks if buffer full // -void usb_serialWriteS (const char *s) +static void usb_serialWriteS (const char *s) { if(*s == '\0') return; @@ -134,11 +126,11 @@ void usb_serialWriteS (const char *s) } } } - +/* // // Writes a null terminated string to the serial output stream followed by EOL, blocks if buffer full // -void usb_serialWriteLn (const char *s) +static void usb_serialWriteLn (const char *s) { usb_serialWriteS(s); usb_serialWriteS(ASCII_EOL); @@ -147,18 +139,18 @@ void usb_serialWriteLn (const char *s) // // Writes a number of characters from string to the serial output stream followed by EOL, blocks if buffer full // -void usb_serialWrite (const char *s, uint16_t length) +static void usb_serialWrite (const char *s, uint16_t length) { char *ptr = (char *)s; while(length--) usb_serialPutC(*ptr++); } - +*/ // // serialGetC - returns -1 if no data available // -int16_t usb_serialGetC (void) +static int16_t usb_serialGetC (void) { uint16_t bptr = usb_rxbuffer.tail; @@ -171,11 +163,33 @@ int16_t usb_serialGetC (void) return (int16_t)data; } -bool usb_serialSuspendInput (bool suspend) +static bool usb_serialSuspendInput (bool suspend) { return stream_rx_suspend(&usb_rxbuffer, suspend); } +const io_stream_t *usb_serialInit(void) +{ + PROGMEM static const io_stream_t stream = { + .type = StreamType_Serial, + .read = usb_serialGetC, + .write = usb_serialWriteS, + .write_char = usb_serialPutC, + .write_all = usb_serialWriteS, + .get_rx_buffer_free = usb_serialRxFree, + .reset_read_buffer = usb_serialRxFlush, + .cancel_read_buffer = usb_serialRxCancel, + .suspend_read = usb_serialSuspendInput + }; + +// usb_serial_configure(); // Done somewhere already - do not call again + txbuf.s = txbuf.data; + txbuf.max_length = usb_serial_write_buffer_free(); // 6144 + txbuf.max_length = (txbuf.max_length > BLOCK_TX_BUFFER_SIZE ? BLOCK_TX_BUFFER_SIZE : txbuf.max_length) - 20; + + return &stream; +} + // // This function get called from the systick interrupt handler, // used here to get characters off the USB serial input stream and buffer diff --git a/grblHAL_Teensy4/src/usb_serial_pjrc.h b/grblHAL_Teensy4/src/usb_serial_pjrc.h index ea7d675..ec7b58e 100644 --- a/grblHAL_Teensy4/src/usb_serial_pjrc.h +++ b/grblHAL_Teensy4/src/usb_serial_pjrc.h @@ -4,7 +4,7 @@ Part of grblHAL - Copyright (c) 2018-2020 Terje Io + Copyright (c) 2020-2021 Terje Io Grbl is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -27,22 +27,12 @@ #include #include +#include "grbl/hal.h" + extern void usb_execute_realtime (uint_fast16_t state); #define usb_serial_poll() usb_execute_realtime(0) -void usb_serialInit(void); -int16_t usb_serialGetC(void); -bool usb_serialPutC(const char c); -void usb_serialWriteS(const char *s); -void usb_serialWriteLn(const char *s); -void usb_serialWrite(const char *s, uint16_t length); -bool usb_serialSuspendInput (bool suspend); - -uint16_t usb_serialTxCount(void); -uint16_t usb_serialRxCount(void); -uint16_t usb_serialRxFree(void); -void usb_serialRxFlush(void); -void usb_serialRxCancel(void); +const io_stream_t *usb_serialInit(void); #endif