Updated to use encapsulated stream code and stadardized motor allocations.

Added support for Bluetooth plugin.
This commit is contained in:
Terje Io 2021-06-27 21:02:38 +02:00
parent 0d7d05c656
commit f0e1c4dd1b
18 changed files with 824 additions and 837 deletions

View File

@ -23,81 +23,49 @@
#define BOARD_NAME "T40X101" #define BOARD_NAME "T40X101"
#if N_AXIS > 4 #if N_ABC_MOTORS > 2
#error Max number of axes is 4 for T40X101 #error "Axis configuration is not supported!"
#endif #endif
#if QEI_ENABLE #if QEI_ENABLE
#error No pins available for encoder input! #error "No pins available for encoder input!"
#endif #endif
#if SPINDLE_SYNC_ENABLE #if SPINDLE_SYNC_ENABLE
#error Spindle sync is not supported for T40X101 #error "Spindle sync is not supported for T40X101!"
#endif #endif
// Default pin assignments allow only one axis to be ganged or auto squared. #define X_STEP_PIN (2u)
// A axis pin numbers are used for the ganged/auto squared axis. #define X_DIRECTION_PIN (3u)
// If a second axis is to be ganged/auto squared pin assignments needs to be changed! #define X_LIMIT_PIN (20u)
// 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 Y_STEP_PIN (4u)
#define X_DIRECTION_PIN (3u) #define Y_DIRECTION_PIN (5u)
#define X_LIMIT_PIN (20u) #define Y_LIMIT_PIN (21u)
#if X_GANGED || X_AUTO_SQUARE #define Z_STEP_PIN (6u)
#define X2_STEP_PIN (8u) #define Z_DIRECTION_PIN (7u)
#define X2_DIRECTION_PIN (9u) #define Z_LIMIT_PIN (22u)
#if X_AUTO_SQUARE
#define X2_LIMIT_PIN (23u) // Define ganged axis or A axis step pulse and step direction output pins.
#endif #if N_ABC_MOTORS > 0
#define M3_AVAILABLE
#define M3_STEP_PIN (8u)
#define M3_DIRECTION_PIN (9u)
#define M3_LIMIT_PIN (23u)
#endif #endif
#define Y_STEP_PIN (4u) // Define ganged axis or B axis step pulse and step direction output pins.
#define Y_DIRECTION_PIN (5u) #if N_ABC_MOTORS == 2
#define Y_LIMIT_PIN (21u) #define M4_AVAILABLE
#define M4_STEP_PIN (26u)
#if Y_GANGED || Y_AUTO_SQUARE #define M4_DIRECTION_PIN (27u)
#define Y2_STEP_PIN (8u) #define M4_LIMIT_PIN (28u)
#define Y2_DIRECTION_PIN (9u) #define M4_ENABLE_PIN (37u)
#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)
#endif #endif
// Define stepper driver enable/disable output pin(s). // 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 and spindle direction output pins.
#define SPINDLE_ENABLE_PIN (12u) #define SPINDLE_ENABLE_PIN (12u)

View File

@ -21,8 +21,12 @@
along with Grbl. If not, see <http://www.gnu.org/licenses/>. along with Grbl. If not, see <http://www.gnu.org/licenses/>.
*/ */
#if N_ABC_MOTORS > 2
#error "Axis configuration is not supported!"
#endif
#define BOARD_NAME "T41BB5X Pro" #define BOARD_NAME "T41BB5X Pro"
#define HAS_BOARD_INIT #define HAS_IOPORTS
#if N_AXIS > 5 #if N_AXIS > 5
#error Max number of axes is 5 for T41U5XBB #error Max number of axes is 5 for T41U5XBB
@ -38,72 +42,37 @@
#define EEPROM_ENABLE 1 #define EEPROM_ENABLE 1
#define EEPROM_IS_FRAM 1 #define EEPROM_IS_FRAM 1
// Default pin assignments allow only one axis to be ganged or auto squared. #define X_STEP_PIN (2u)
// B axis pin numbers are used for the ganged/auto squared axis. #define X_DIRECTION_PIN (3u)
// If a second axis is to be ganged/auto squared pin assignments needs to be changed! #define X_ENABLE_PIN (10u)
// Set to 1 to enable, 0 to disable. #define X_LIMIT_PIN (20u)
#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 Y_STEP_PIN (4u)
#define X_DIRECTION_PIN (3u) #define Y_DIRECTION_PIN (5u)
#define X_ENABLE_PIN (10u) #define Y_ENABLE_PIN (35u)
#define X_LIMIT_PIN (20u) #define Y_LIMIT_PIN (21u)
#if X_GANGED || X_AUTO_SQUARE #define Z_STEP_PIN (6u)
#define X2_STEP_PIN (26u) #define Z_DIRECTION_PIN (7u)
#define X2_DIRECTION_PIN (27u) #define Z_ENABLE_PIN (39u)
#define X2_ENABLE_PIN (37u) #define Z_LIMIT_PIN (22u)
#if X_AUTO_SQUARE
#define X2_LIMIT_PIN (28u) // Define ganged axis or A axis step pulse and step direction output pins.
#endif #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 #endif
#define Y_STEP_PIN (4u) // Define ganged axis or B axis step pulse and step direction output pins.
#define Y_DIRECTION_PIN (5u) #if N_ABC_MOTORS == 2
#define Y_ENABLE_PIN (35u) #define M4_AVAILABLE
#define Y_LIMIT_PIN (21u) #define M4_STEP_PIN (26u)
#define M4_DIRECTION_PIN (27u)
#if Y_GANGED || Y_AUTO_SQUARE #define M4_LIMIT_PIN (28u)
#define Y2_STEP_PIN (26u) #define M4_ENABLE_PIN (37u)
#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)
#endif #endif
// Define spindle enable and spindle direction output pins. // Define spindle enable and spindle direction output pins.

View File

@ -21,84 +21,48 @@
along with Grbl. If not, see <http://www.gnu.org/licenses/>. along with Grbl. If not, see <http://www.gnu.org/licenses/>.
*/ */
#define BOARD_NAME "T41U5XBB" #if N_ABC_MOTORS > 2
#define HAS_BOARD_INIT #error "Axis configuration is not supported!"
#if N_AXIS > 5
#error Max number of axes is 5 for T41U5XBB
#endif #endif
#if SPINDLE_SYNC_ENABLE #if SPINDLE_SYNC_ENABLE
#error Spindle sync is not supported for T41U5XBB #error "Spindle sync is not supported for T41U5XBB!"
#endif #endif
// Default pin assignments allow only one axis to be ganged or auto squared. #define BOARD_NAME "T41U5XBB"
// B axis pin numbers are used for the ganged/auto squared axis. #define HAS_IOPORTS
// 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_STEP_PIN (2u)
#define X_DIRECTION_PIN (3u) #define X_DIRECTION_PIN (3u)
#define X_ENABLE_PIN (10u) #define X_ENABLE_PIN (10u)
#define X_LIMIT_PIN (20u) #define X_LIMIT_PIN (20u)
#if X_GANGED || X_AUTO_SQUARE #define Y_STEP_PIN (4u)
#define X2_STEP_PIN (26u) #define Y_DIRECTION_PIN (5u)
#define X2_DIRECTION_PIN (27u) #define Y_ENABLE_PIN (40u)
#define X2_ENABLE_PIN (37u) #define Y_LIMIT_PIN (21u)
#if X_AUTO_SQUARE
#define X2_LIMIT_PIN (28u) #define Z_STEP_PIN (6u)
#endif #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 #endif
#define Y_STEP_PIN (4u) // Define ganged axis or B axis step pulse and step direction output pins.
#define Y_DIRECTION_PIN (5u) #if N_ABC_MOTORS == 2
#define Y_ENABLE_PIN (40u) #define M4_AVAILABLE
#define Y_LIMIT_PIN (21u) #define M4_STEP_PIN (26u)
#define M4_DIRECTION_PIN (27u)
// Changed to use A pins rather than B pins #define M4_LIMIT_PIN (28u)
#if Y_GANGED || Y_AUTO_SQUARE #define M4_ENABLE_PIN (37u)
#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)
#endif #endif
// Define spindle enable and spindle direction output pins. // Define spindle enable and spindle direction output pins.

View File

@ -23,84 +23,48 @@
along with Grbl. If not, see <http://www.gnu.org/licenses/>. along with Grbl. If not, see <http://www.gnu.org/licenses/>.
*/ */
#define BOARD_NAME "T41U5XBB" #if N_ABC_MOTORS > 2
#define HAS_BOARD_INIT #error "Axis configuration is not supported!"
#if N_AXIS > 5
#error Max number of axes is 5 for T41U5XBB
#endif #endif
#if QEI_ENABLE && SPINDLE_SYNC_ENABLE #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 #endif
// Default pin assignments allow only one axis to be ganged or auto squared. #define BOARD_NAME "T41U5XBB"
// B axis pin numbers are used for the ganged/auto squared axis. #define HAS_IOPORTS
// 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_STEP_PIN (2u)
#define X_DIRECTION_PIN (3u) #define X_DIRECTION_PIN (3u)
#define X_ENABLE_PIN (10u) #define X_ENABLE_PIN (10u)
#define X_LIMIT_PIN (20u) #define X_LIMIT_PIN (20u)
#if X_GANGED || X_AUTO_SQUARE #define Y_STEP_PIN (4u)
#define X2_STEP_PIN (26u) #define Y_DIRECTION_PIN (5u)
#define X2_DIRECTION_PIN (27u) #define Y_ENABLE_PIN (40u)
#define X2_ENABLE_PIN (37u) #define Y_LIMIT_PIN (21u)
#if X_AUTO_SQUARE
#define X2_LIMIT_PIN (28u) #define Z_STEP_PIN (6u)
#endif #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 #endif
#define Y_STEP_PIN (4u) // Define ganged axis or B axis step pulse and step direction output pins.
#define Y_DIRECTION_PIN (5u) #if N_ABC_MOTORS == 2
#define Y_ENABLE_PIN (40u) #define M4_AVAILABLE
#define Y_LIMIT_PIN (21u) #define M4_STEP_PIN (26u)
#define M4_DIRECTION_PIN (27u)
// Changed to use A pins rather than B pins #define M4_LIMIT_PIN (28u)
#if Y_GANGED || Y_AUTO_SQUARE #define M4_ENABLE_PIN (37u)
#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)
#endif #endif
// Define spindle enable and spindle direction output pins. // Define spindle enable and spindle direction output pins.

View File

@ -21,12 +21,12 @@
#define BOARD_NAME "CNC BoosterPack" #define BOARD_NAME "CNC BoosterPack"
#if N_AXIS > 3 #if N_ABC_MOTORS
#error Max number of axes is 3 for CNC BoosterPack #error "Axis configuration is not supported!"
#endif #endif
#if SPINDLE_SYNC_ENABLE #if SPINDLE_SYNC_ENABLE
#error Spindle sync is not supported for CNC BoosterPack #error "Spindle sync is not supported for CNC BoosterPack"
#endif #endif
#ifdef EEPROM_ENABLE #ifdef EEPROM_ENABLE

View File

@ -67,6 +67,10 @@ static void ppi_timeout_isr (void);
#include "openpnp/openpnp.h" #include "openpnp/openpnp.h"
#endif #endif
#if BLUETOOTH_ENABLE
#include "bluetooth/bluetooth.h"
#endif
#if ETHERNET_ENABLE #if ETHERNET_ENABLE
#include "enet.h" #include "enet.h"
#if TELNET_ENABLE #if TELNET_ENABLE
@ -96,17 +100,7 @@ static void ppi_timeout_isr (void);
#define F_BUS_MHZ (F_BUS_ACTUAL / 1000000) #define F_BUS_MHZ (F_BUS_ACTUAL / 1000000)
#if X_AUTO_SQUARE || Y_AUTO_SQUARE || Z_AUTO_SQUARE #include "grbl/motor_pins.h"
#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
typedef struct { typedef struct {
volatile uint_fast8_t head; volatile uint_fast8_t head;
@ -224,6 +218,9 @@ static gpio_t QEI_A, QEI_B;
#ifdef X2_LIMIT_PIN #ifdef X2_LIMIT_PIN
static gpio_t LimitX2; static gpio_t LimitX2;
#endif #endif
#ifdef X_LIMIT_PIN_MAX
static gpio_t LimitXMax;
#endif
#ifdef Y2_STEP_PIN #ifdef Y2_STEP_PIN
static gpio_t stepY2; static gpio_t stepY2;
@ -237,6 +234,9 @@ static gpio_t QEI_A, QEI_B;
#ifdef Y2_LIMIT_PIN #ifdef Y2_LIMIT_PIN
static gpio_t LimitY2; static gpio_t LimitY2;
#endif #endif
#ifdef Y_LIMIT_PIN_MAX
static gpio_t LimitYMax;
#endif
#ifdef Z2_STEP_PIN #ifdef Z2_STEP_PIN
static gpio_t stepZ2; static gpio_t stepZ2;
@ -250,6 +250,10 @@ static gpio_t QEI_A, QEI_B;
#ifdef Z2_LIMIT_PIN #ifdef Z2_LIMIT_PIN
static gpio_t LimitZ2; static gpio_t LimitZ2;
#endif #endif
#ifdef Z_LIMIT_PIN_MAX
static gpio_t LimitZMax;
#endif
#ifdef SPINDLE_INDEX_PIN #ifdef SPINDLE_INDEX_PIN
static gpio_t SpindleIndex; static gpio_t SpindleIndex;
#endif #endif
@ -295,15 +299,24 @@ input_signal_t inputpin[] = {
// Limit input pins must be consecutive // Limit input pins must be consecutive
{ .id = Input_LimitX, .port = &LimitX, .pin = X_LIMIT_PIN, .group = PinGroup_Limit }, { .id = Input_LimitX, .port = &LimitX, .pin = X_LIMIT_PIN, .group = PinGroup_Limit },
#ifdef X2_LIMIT_PIN #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 #endif
{ .id = Input_LimitY, .port = &LimitY, .pin = Y_LIMIT_PIN, .group = PinGroup_Limit }, { .id = Input_LimitY, .port = &LimitY, .pin = Y_LIMIT_PIN, .group = PinGroup_Limit },
#ifdef Y2_LIMIT_PIN #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 #endif
{ .id = Input_LimitZ, .port = &LimitZ, .pin = Z_LIMIT_PIN, .group = PinGroup_Limit } { .id = Input_LimitZ, .port = &LimitZ, .pin = Z_LIMIT_PIN, .group = PinGroup_Limit }
#ifdef Z2_LIMIT_PIN #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 #endif
#ifdef A_LIMIT_PIN #ifdef A_LIMIT_PIN
, { .id = Input_LimitA, .port = &LimitA, .pin = A_LIMIT_PIN, .group = PinGroup_Limit } , { .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); static void spindle_set_speed (uint_fast16_t pwm_value);
#endif #endif
#if MODBUS_ENABLE
static modbus_stream_t modbus_stream = {0};
#endif
#if SPINDLE_SYNC_ENABLE #if SPINDLE_SYNC_ENABLE
#include "grbl/spindle_sync.h" #include "grbl/spindle_sync.h"
@ -493,8 +502,11 @@ static void spindle_pulse_isr (void);
#endif #endif
static const io_stream_t *serial_stream;
#if ETHERNET_ENABLE #if ETHERNET_ENABLE
static network_services_t services = {0}; static network_services_t services = {0};
static stream_write_ptr write_serial;
static void enetStreamWriteS (const char *data) static void enetStreamWriteS (const char *data)
{ {
@ -506,50 +518,11 @@ static void enetStreamWriteS (const char *data)
if(services.websocket) if(services.websocket)
WsStreamWriteS(data); WsStreamWriteS(data);
#endif #endif
#if USB_SERIAL_CDC if(write_serial)
usb_serialWriteS(data); write_serial(data);
#else
serialWriteS(data);
#endif
} }
#endif // ETHERNET_ENABLE #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 handler prototypes
// Interrupt handlers needs to be registered, possibly by modifying a system specific startup file. // 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. // 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 bool serial_connected = false;
static stream_type_t active_stream = StreamType_Serial; 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; serial_connected = hal.stream.connected;
if(!stream) if(!stream)
stream = &serial_stream; stream = active_stream == StreamType_Bluetooth ? serial_stream : last_serial_stream;
memcpy(&hal.stream, stream, sizeof(io_stream_t)); 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) if(!hal.stream.enqueue_realtime_command)
hal.stream.enqueue_realtime_command = protocol_enqueue_realtime_command; hal.stream.enqueue_realtime_command = protocol_enqueue_realtime_command;
if(hal.stream.disable)
hal.stream.disable(false);
switch(stream->type) { switch(stream->type) {
#if TELNET_ENABLE #if TELNET_ENABLE
@ -624,12 +601,21 @@ static bool selectStream (const io_stream_t *stream)
case StreamType_Serial: case StreamType_Serial:
#if ETHERNET_ENABLE #if ETHERNET_ENABLE
services.mask = 0; services.mask = 0;
write_serial = serial_connected ? hal.stream.write : NULL;
#endif #endif
hal.stream.connected = serial_connected; hal.stream.connected = serial_connected;
last_serial_stream = stream;
if(active_stream != StreamType_Serial && hal.stream.connected) if(active_stream != StreamType_Serial && hal.stream.connected)
hal.stream.write_all("[MSG:SERIAL STREAM ACTIVE]" ASCII_EOL); hal.stream.write_all("[MSG:SERIAL STREAM ACTIVE]" ASCII_EOL);
break; break;
case StreamType_Bluetooth:
#if ETHERNET_ENABLE
services.mask = 0;
write_serial = hal.stream.write;
#endif
last_serial_stream = stream;
break;
default: default:
break; 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... // 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, ... // Individual step bits can be accessed by step_outbits.x, step_outbits.y, ...
#ifdef SQUARING_ENABLED #ifdef SQUARING_ENABLED
inline static __attribute__((always_inline)) void set_step_outputs (axes_signals_t step_outbits_1) inline static __attribute__((always_inline)) void set_step_outputs (axes_signals_t step_outbits_1)
{ {
axes_signals_t step_outbits_2; 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); DIGITAL_OUT(stepB, step_outbits_1.b);
#endif #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 #else
inline static __attribute__((always_inline)) void set_step_outputs (axes_signals_t step_outbits) inline static __attribute__((always_inline)) void set_step_outputs (axes_signals_t step_outbits)
{ {
step_outbits.value ^= settings.steppers.step_invert.mask; 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); DIGITAL_OUT(stepC, step_outbits.c);
#endif #endif
} }
#endif
#endif // SQUARING_ENABLED
// Set stepper direction ouput pins. // Set stepper direction ouput pins.
// dir_outbits.value (or dir_outbits.mask) are: bit0 -> X, bit1 -> Y... // 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 #endif
#ifdef DUAL_LIMIT_SWITCHES
// Returns limit state as an axes_signals_t variable. // 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. // 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! // 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}; limit_signals_t signals = {0};
signals.min.mask = signals.min2.mask = settings.limits.invert.mask; 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 #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 #endif
signals.min.y = (LimitY.reg->DR & LimitY.bit) != 0; signals.min.y = DIGITAL_IN(LimitY);
#ifdef Y2_LIMIT_PIN #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 #endif
signals.min.z = (LimitZ.reg->DR & LimitZ.bit) != 0; signals.min.z = DIGITAL_IN(LimitZ);
#ifdef Z2_LIMIT_PIN #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 #endif
#ifdef A_LIMIT_PIN #ifdef A_LIMIT_PIN
signals.min.a = (LimitA.reg->DR & LimitA.bit) != 0; signals.min.a = DIGITAL_IN(LimitA);
#endif #endif
#ifdef B_LIMIT_PIN #ifdef B_LIMIT_PIN
signals.min.b = (LimitB.reg->DR & LimitB.bit) != 0; signals.min.b = DIGITAL_IN(LimitB);
#endif #endif
#ifdef C_LIMIT_PIN #ifdef C_LIMIT_PIN
signals.min.c = (LimitC.reg->DR & LimitC.bit) != 0; signals.min.c = DIGITAL_IN(LimitC);
#endif #endif
if(settings.limits.invert.mask) { if(settings.limits.invert.mask) {
signals.min.value ^= 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; 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. // Enable/disable limit pins interrupt.
// NOTE: the homing parameter is indended for configuring advanced // NOTE: the homing parameter is indended for configuring advanced
@ -1633,6 +1604,7 @@ static void settings_changed (settings_t *settings)
break; break;
case Input_LimitX: case Input_LimitX:
case Input_LimitX_2:
case Input_LimitX_Max: case Input_LimitX_Max:
pullup = !settings->limits.disable_pullup.x; pullup = !settings->limits.disable_pullup.x;
signal->debounce = hal.driver_cap.software_debounce; signal->debounce = hal.driver_cap.software_debounce;
@ -1640,12 +1612,14 @@ static void settings_changed (settings_t *settings)
break; break;
case Input_LimitY: case Input_LimitY:
case Input_LimitY_2:
case Input_LimitY_Max: case Input_LimitY_Max:
pullup = !settings->limits.disable_pullup.y; pullup = !settings->limits.disable_pullup.y;
signal->irq_mode = limit_fei.y ? IRQ_Mode_Falling : IRQ_Mode_Rising; signal->irq_mode = limit_fei.y ? IRQ_Mode_Falling : IRQ_Mode_Rising;
break; break;
case Input_LimitZ: case Input_LimitZ:
case Input_LimitZ_2:
case Input_LimitZ_Max: case Input_LimitZ_Max:
pullup = !settings->limits.disable_pullup.z; pullup = !settings->limits.disable_pullup.z;
signal->irq_mode = limit_fei.z ? IRQ_Mode_Falling : IRQ_Mode_Rising; signal->irq_mode = limit_fei.z ? IRQ_Mode_Falling : IRQ_Mode_Rising;
@ -1718,42 +1692,30 @@ static void settings_changed (settings_t *settings)
break; 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); pinMode(signal->pin, pullup ? INPUT_PULLUP : INPUT_PULLDOWN);
signal->gpio.reg = (gpio_reg_t *)digital_pin_to_info_PGM[signal->pin].reg; 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; 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) if(signal->port != NULL)
memcpy(signal->port, &signal->gpio, sizeof(gpio_t)); memcpy(signal->port, &signal->gpio, sizeof(gpio_t));
if(signal->irq_mode != IRQ_Mode_None) { if(signal->irq_mode != IRQ_Mode_None) {
if(signal->gpio.reg == (gpio_reg_t *)&GPIO6_DR) pinEnableIRQ(signal, signal->irq_mode);
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
signal->active = (signal->gpio.reg->DR & signal->gpio.bit) != 0; 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; 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 #if QEI_ENABLE
static void qei_update (void) static void qei_update (void)
@ -2165,7 +2166,7 @@ bool driver_init (void)
options[strlen(options) - 1] = '\0'; options[strlen(options) - 1] = '\0';
hal.info = "iMXRT1062"; hal.info = "iMXRT1062";
hal.driver_version = "210605"; hal.driver_version = "210617";
#ifdef BOARD_NAME #ifdef BOARD_NAME
hal.board = BOARD_NAME; hal.board = BOARD_NAME;
#endif #endif
@ -2219,15 +2220,15 @@ bool driver_init (void)
grbl.on_report_options = reportIP; grbl.on_report_options = reportIP;
#endif #endif
hal.stream_select = selectStream;
hal.stream_select(&serial_stream);
#if USB_SERIAL_CDC #if USB_SERIAL_CDC
usb_serialInit(); serial_stream = usb_serialInit();
#else #else
serialInit(115200); serial_stream = serialInit(115200);
#endif #endif
hal.stream_select = selectStream;
hal.stream_select(serial_stream);
#ifdef I2C_PORT #ifdef I2C_PORT
i2c_init(); i2c_init();
#endif #endif
@ -2257,30 +2258,13 @@ bool driver_init (void)
#if QEI_ENABLE #if QEI_ENABLE
hal.encoder.reset = qei_reset; hal.encoder.reset = qei_reset;
hal.encoder.on_event = encoder_event; 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 #endif
// Driver capabilities, used for announcing and negotiating (with Grbl) driver functionality. // Driver capabilities, used for announcing and negotiating (with Grbl) driver functionality.
// See driver_cap_t union i grbl/hal.h for available flags. // See driver_cap_t union i grbl/hal.h for available flags.
#if ESTOP_ENABLE #if ESTOP_ENABLE
hal.signals_cap.reset = Off;
hal.signals_cap.e_stop = On; hal.signals_cap.e_stop = On;
#endif #endif
#if SAFETY_DOOR_ENABLE #if SAFETY_DOOR_ENABLE
@ -2321,13 +2305,13 @@ bool driver_init (void)
for(i = 0 ; i < sizeof(inputpin) / sizeof(input_signal_t); i++) { for(i = 0 ; i < sizeof(inputpin) / sizeof(input_signal_t); i++) {
signal = &inputpin[i]; signal = &inputpin[i];
#ifdef HAS_IOPORTS
if(signal->group == PinGroup_AuxInput) { if(signal->group == PinGroup_AuxInput) {
if(aux_inputs.pins.inputs == NULL) if(aux_inputs.pins.inputs == NULL)
aux_inputs.pins.inputs = signal; aux_inputs.pins.inputs = signal;
aux_inputs.n_pins++; aux_inputs.n_pins++;
} }
#endif
if(signal->group == PinGroup_Limit) { if(signal->group == PinGroup_Limit) {
if(limit_inputs.pins.inputs == NULL) if(limit_inputs.pins.inputs == NULL)
limit_inputs.pins.inputs = signal; limit_inputs.pins.inputs = signal;
@ -2335,6 +2319,7 @@ bool driver_init (void)
} }
} }
#ifdef HAS_IOPORTS
output_signal_t *output; output_signal_t *output;
for(i = 0 ; i < sizeof(outputpin) / sizeof(output_signal_t); i++) { for(i = 0 ; i < sizeof(outputpin) / sizeof(output_signal_t); i++) {
output = &outputpin[i]; output = &outputpin[i];
@ -2345,14 +2330,17 @@ bool driver_init (void)
} }
} }
#ifdef HAS_BOARD_INIT ioports_init(&aux_inputs, &aux_outputs);
board_init(&aux_inputs, &aux_outputs);
#endif #endif
#if ETHERNET_ENABLE #if ETHERNET_ENABLE
grbl_enet_init(); grbl_enet_init();
#endif #endif
#if SPINDLE_HUANYANG
huanyang_init(modbus_init(serialInit(115200), NULL));
#endif
#if KEYPAD_ENABLE #if KEYPAD_ENABLE
keypad_init(); keypad_init();
#endif #endif
@ -2370,6 +2358,10 @@ bool driver_init (void)
openpnp_init(); openpnp_init();
#endif #endif
#if BLUETOOTH_ENABLE
bluetooth_init(serialInit(115200));
#endif
#if ODOMETER_ENABLE #if ODOMETER_ENABLE
odometer_init(); // NOTE: this *must* be last plugin to be initialized as it claims storage at the end of NVS. odometer_init(); // NOTE: this *must* be last plugin to be initialized as it claims storage at the end of NVS.
#endif #endif
@ -2548,16 +2540,17 @@ static void gpio_isr (void)
uint32_t i = sizeof(inputpin) / sizeof(input_signal_t); uint32_t i = sizeof(inputpin) / sizeof(input_signal_t);
do { 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) { if(intr_status[inputpin[i].offset] & inputpin[i].gpio.bit) {
inputpin[i].active = true; inputpin[i].active = true;
if(inputpin[i].debounce && enqueue_debounce(&inputpin[i])) { if(inputpin[i].debounce && enqueue_debounce(&inputpin[i])) {
inputpin[i].gpio.reg->IMR &= ~inputpin[i].gpio.bit; inputpin[i].gpio.reg->IMR &= ~inputpin[i].gpio.bit;
debounce = true; debounce = true;
} else { } else switch(inputpin[i].group) {
#if QEI_ENABLE #if QEI_ENABLE
if(inputpin[i].group & PinGroup_QEI) { casePinGroup_QEI:
qei_update(); qei_update();
/* /*
QEI_A.reg->IMR &= ~QEI_A.bit; // Switch off QEI_A.reg->IMR &= ~QEI_A.bit; // Switch off
@ -2567,19 +2560,33 @@ static void gpio_isr (void)
qei.debounce = QEI_DEBOUNCE; qei.debounce = QEI_DEBOUNCE;
qei.initial_debounce = true; qei.initial_debounce = true;
*/ */
} else break;
#endif #endif
#if SPINDLE_SYNC_ENABLE && defined(SPINDLE_INDEX_PIN) #if SPINDLE_SYNC_ENABLE && defined(SPINDLE_INDEX_PIN)
if(inputpin[i].group & PinGroup_SpindleIndex) { case PinGroup_SpindleIndex:
spindleLock = true; spindleLock = true;
spindle_encoder.counter.index_count++; spindle_encoder.counter.index_count++;
spindle_encoder.counter.last_index = GPT2_CNT; spindle_encoder.counter.last_index = GPT2_CNT;
spindle_encoder.timer.last_index = GPT1_CNT; spindle_encoder.timer.last_index = GPT1_CNT;
spindleLock = false; spindleLock = false;
} else break;
#endif #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; grp |= inputpin[i].group;
break;
} }
} }
} }
@ -2622,11 +2629,6 @@ static void gpio_isr (void)
mpg_mutex = false; mpg_mutex = false;
} }
#endif #endif
#if KEYPAD_ENABLE
if(grp & PinGroup_Keypad)
keypad_keyclick_handler(!(KeypadStrobe.reg->DR & KeypadStrobe.bit));
#endif
} }
// Interrupt handler for 1 ms interval timer // Interrupt handler for 1 ms interval timer

View File

@ -34,9 +34,7 @@
#include "my_machine.h" #include "my_machine.h"
#endif #endif
#include "grbl/hal.h" #include "grbl/driver_opts.h"
#include "grbl/nuts_bolts.h"
#include "grbl/crossbar.h"
#define DIGITAL_IN(gpio) (!!(gpio.reg->DR & gpio.bit)) #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; } #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 //#define UART_DEBUG // For development only - enable only with USB_SERIAL_CDC enabled and SPINDLE_HUANYANG disabled
#endif #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...) // Timer assignments (for reference, Arduino libs does not follow the CMSIS style...)
//#define STEPPER_TIMER PIT0 (32 bit) //#define STEPPER_TIMER PIT0 (32 bit)
@ -163,8 +56,6 @@
//#define RPM_TIMER GPT1 //#define RPM_TIMER GPT1
//#define RPM_COUNTER GPT2 //#define RPM_COUNTER GPT2
// End configuration
#ifdef BOARD_CNC_BOOSTERPACK #ifdef BOARD_CNC_BOOSTERPACK
#include "cnc_boosterpack_map.h" #include "cnc_boosterpack_map.h"
#elif defined(BOARD_T40X101) #elif defined(BOARD_T40X101)
@ -212,6 +103,10 @@
#include "encoder/encoder.h" #include "encoder/encoder.h"
#endif #endif
#if BLUETOOTH_ENABLE && USB_SERIAL_CDC == 0
#error "Bluetooth cannot be used with UART communications enabled!"
#endif
#if SPINDLE_HUANYANG #if SPINDLE_HUANYANG
#if USB_SERIAL_CDC == 0 #if USB_SERIAL_CDC == 0
#error "Huanyang VFD cannot be used with UART communications enabled!" #error "Huanyang VFD cannot be used with UART communications enabled!"
@ -286,6 +181,8 @@ typedef struct {
uint8_t offset; uint8_t offset;
volatile bool active; volatile bool active;
volatile bool debounce; volatile bool debounce;
pin_mode_t cap;
ioport_interrupt_callback_ptr interrupt_callback;
} input_signal_t; } input_signal_t;
typedef struct { typedef struct {
@ -312,13 +209,13 @@ typedef struct {
const uint32_t select_val; // Value for that selection const uint32_t select_val; // Value for that selection
} pin_info_t; } pin_info_t;
//
void pinModeOutput (gpio_t *gpio, uint8_t pin); void pinModeOutput (gpio_t *gpio, uint8_t pin);
void pinEnableIRQ (const input_signal_t *signal, pin_irq_mode_t irq_mode);
uint32_t xTaskGetTickCount(); uint32_t xTaskGetTickCount();
#ifdef HAS_BOARD_INIT #ifdef HAS_IOPORTS
void board_init(pin_group_pins_t *aux_inputs, pin_group_pins_t *aux_outputs); void ioports_init (pin_group_pins_t *aux_inputs, pin_group_pins_t *aux_outputs);
void ioports_event (input_signal_t *input);
#endif #endif
#ifdef UART_DEBUG #ifdef UART_DEBUG

View File

@ -38,13 +38,14 @@
#include "networking/networking.h" #include "networking/networking.h"
static bool enet_started = false;
static volatile bool linkUp = false; static volatile bool linkUp = false;
static char IPAddress[IP4ADDR_STRLEN_MAX]; static char IPAddress[IP4ADDR_STRLEN_MAX];
static network_services_t services = {0}, allowed_services; static network_services_t services = {0}, allowed_services;
static nvs_address_t nvs_address; static nvs_address_t nvs_address;
static network_settings_t ethernet, network; static network_settings_t ethernet, network;
static on_report_options_ptr on_report_options;; 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) static void report_options (bool newopt)
{ {
@ -105,6 +106,9 @@ void grbl_enet_poll (void)
static uint32_t last_ms0, last_ms1; static uint32_t last_ms0, last_ms1;
uint32_t ms; uint32_t ms;
if(!enet_started)
return;
enet_proc_input(); enet_proc_input();
ms = millis(); ms = millis();
@ -154,6 +158,8 @@ bool grbl_enet_start (void)
#endif #endif
if(network.ip_mode == IpMode_DHCP) if(network.ip_mode == IpMode_DHCP)
dhcp_start(netif_default); dhcp_start(netif_default);
enet_started = true;
} }
return nvs_address != 0; return nvs_address != 0;

View File

@ -19,38 +19,46 @@
along with Grbl. If not, see <http://www.gnu.org/licenses/>. along with Grbl. If not, see <http://www.gnu.org/licenses/>.
*/ */
#if N_ABC_MOTORS > 2
#error "Axis configuration is not supported!"
#endif
#if SPINDLE_SYNC_ENABLE #if SPINDLE_SYNC_ENABLE
#error Spindle sync is not supported #error "Spindle sync is not supported"
#endif #endif
// Define step pulse output pins. // Define step pulse output pins.
#define X_STEP_PIN (2u) #define X_STEP_PIN (2u)
#define Y_STEP_PIN (4u) #define Y_STEP_PIN (4u)
#define Z_STEP_PIN (6u) #define Z_STEP_PIN (6u)
// Define step direction output pins. // Define step direction output pins.
#define X_DIRECTION_PIN (3u) #define X_DIRECTION_PIN (3u)
#define Y_DIRECTION_PIN (5u) #define Y_DIRECTION_PIN (5u)
#define Z_DIRECTION_PIN (7u) #define Z_DIRECTION_PIN (7u)
// Define stepper driver enable/disable output pin(s). // Define stepper driver enable/disable output pin(s).
#define STEPPERS_ENABLE_PIN (10u) #define STEPPERS_ENABLE_PIN (10u)
// Define homing/hard limit switch input pins. // Define homing/hard limit switch input pins.
#define X_LIMIT_PIN (20u) #define X_LIMIT_PIN (20u)
#define Y_LIMIT_PIN (21u) #define Y_LIMIT_PIN (21u)
#define Z_LIMIT_PIN (22u) #define Z_LIMIT_PIN (22u)
#if N_AXIS > 3 // Define ganged axis or A axis step pulse and step direction output pins.
#define A_STEP_PIN (8u) #if N_ABC_MOTORS > 0
#define A_DIRECTION_PIN (9u) #define M3_AVAILABLE
#define A_LIMIT_PIN (23u) #define M3_STEP_PIN (8u)
#define M3_DIRECTION_PIN (9u)
#define M3_LIMIT_PIN (23u)
#endif #endif
#if N_AXIS > 4 // Define ganged axis or B axis step pulse and step direction output pins.
#define B_STEP_PIN (26u) #if N_ABC_MOTORS == 2
#define B_DIRECTION_PIN (27u) #define M4_AVAILABLE
#define B_LIMIT_PIN (28u) #define M4_STEP_PIN (26u)
#define M4_DIRECTION_PIN (27u)
#define M4_LIMIT_PIN (28u)
#endif #endif
// Define spindle enable and spindle direction output pins. // Define spindle enable and spindle direction output pins.

View File

@ -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 Part of grblHAL
@ -23,7 +23,7 @@
#include "driver.h" #include "driver.h"
#if defined(BOARD_T41U5XBB) || defined(BOARD_T41U5XBB_SS) || defined(BOARD_T41BB5X_PRO) #ifdef HAS_IOPORTS
//#include "Arduino.h" //#include "Arduino.h"
#include <math.h> #include <math.h>
@ -32,6 +32,8 @@
#include "grbl/protocol.h" #include "grbl/protocol.h"
static uint_fast8_t aux_n_in, aux_n_out; 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 input_signal_t *aux_in;
static output_signal_t *aux_out; static output_signal_t *aux_out;
static ioport_bus_t out = {0}; 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 void aux_settings_load (void);
static status_code_t aux_set_invert_out (setting_id_t id, uint_fast16_t int_value); 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 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[] = { static const setting_group_detail_t aux_groups[] = {
{ Group_Root, Group_AuxPorts, "Aux ports"} { Group_Root, Group_AuxPorts, "Aux ports"}
}; };
static const setting_detail_t aux_settings[] = { 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_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 }, { 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 = { static setting_details_t details = {
@ -59,6 +62,29 @@ static setting_details_t details = {
.save = settings_write_global .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) static setting_details_t *on_get_settings (void)
{ {
return &details; return &details;
@ -70,6 +96,7 @@ static void aux_settings_load (void)
do { do {
idx--; idx--;
pinModeOutput(aux_out[idx].port, aux_out[idx].pin);
DIGITAL_OUT((*(aux_out[idx].port)), (settings.ioport.invert_out.mask >> idx) & 0x01); DIGITAL_OUT((*(aux_out[idx].port)), (settings.ioport.invert_out.mask >> idx) & 0x01);
} while(idx); } 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); 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) 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; 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 { pin_irq_mode_t irq_mode = wait_mode == WaitMode_Rise ? IRQ_Mode_Rising : IRQ_Mode_Falling;
if((!!(gpio->reg->DR & gpio->bit) ^ invert) == wait_for)
return !!(gpio->reg->DR & gpio->bit);
if(delay) { if(input->cap.irq_mode & irq_mode) {
protocol_execute_realtime();
hal.delay_ms(50, NULL);
} else
break;
} while(--delay && !sys.abort);
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) 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(digital) {
if(port < aux_n_in) 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) // else if(port == 0)
// value = analogRead(41); // 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; 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_in = aux_inputs->pins.inputs;
aux_out = aux_outputs->pins.outputs; aux_out = aux_outputs->pins.outputs;
hal.port.wait_on_input = wait_on_input; if((hal.port.num_digital_in = aux_n_in = aux_inputs->n_pins)) {
hal.port.digital_out = digital_out; hal.port.wait_on_input = wait_on_input;
hal.port.num_digital_in = aux_n_in = aux_inputs->n_pins; hal.port.register_interrupt_handler = register_interrupt_handler;
hal.port.num_digital_out = aux_n_out = aux_outputs->n_pins; }
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; details.on_get_settings = grbl.on_get_settings;
grbl.on_get_settings = on_get_settings; grbl.on_get_settings = on_get_settings;

View File

@ -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_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 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 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 QEI_ENABLE 1 // Enable quadrature encoder interfaces. Max value is 1. Requires encoder plugin.
//#define ETHERNET_ENABLE 1 // Ethernet streaming. Requires networking 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 KEYPAD_ENABLE 1 // I2C keypad for jogging etc., requires keypad plugin.
//#define PLASMA_ENABLE 1 // Plasma/THC plugin. To be completed. //#define PLASMA_ENABLE 1 // Plasma/THC plugin. To be completed.
//#define PPI_ENABLE 1 // Laser PPI 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. //#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. // 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 #if ETHERNET_ENABLE > 0
#define TELNET_ENABLE 1 // Telnet daemon - requires Ethernet streaming enabled. #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 WEBSOCKET_ENABLE 1 // Websocket daemon - requires Ethernet streaming enabled.
#define NETWORK_HOSTNAME "GRBL" #define NETWORK_HOSTNAME "GRBL"
#define NETWORK_IPMODE 1 // 0 = static, 1 = DHCP, 2 = AutoIP #define NETWORK_IPMODE 1 // 0 = static, 1 = DHCP, 2 = AutoIP

View File

@ -0,0 +1,75 @@
/*
my_plugin.c - plugin template for setting auxillary output on feed hold
Part of grblHAL
Public domain.
*/
#include <string.h>
#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.
}
}

View File

@ -143,113 +143,10 @@ static uint16_t tx_fifo_size;
static stream_tx_buffer_t txbuffer = {0}; static stream_tx_buffer_t txbuffer = {0};
static stream_rx_buffer_t rxbuffer = {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 // serialGetC - returns -1 if no data available
// //
int16_t serialGetC (void) static int16_t serialGetC (void)
{ {
int16_t data; int16_t data;
uint_fast16_t bptr = rxbuffer.tail; uint_fast16_t bptr = rxbuffer.tail;
@ -263,37 +160,37 @@ int16_t serialGetC (void)
return data; return data;
} }
void serialTxFlush (void) static void serialTxFlush (void)
{ {
txbuffer.tail = txbuffer.head; txbuffer.tail = txbuffer.head;
} }
uint16_t serialRxCount (void) static uint16_t serialRxCount (void)
{ {
uint_fast16_t head = rxbuffer.head, tail = rxbuffer.tail; uint_fast16_t head = rxbuffer.head, tail = rxbuffer.tail;
return BUFCOUNT(head, tail, RX_BUFFER_SIZE); return BUFCOUNT(head, tail, RX_BUFFER_SIZE);
} }
uint16_t serialRxFree (void) static uint16_t serialRxFree (void)
{ {
return (RX_BUFFER_SIZE - 1) - serialRxCount(); return (RX_BUFFER_SIZE - 1) - serialRxCount();
} }
void serialRxFlush (void) static void serialRxFlush (void)
{ {
rxbuffer.tail = rxbuffer.head; rxbuffer.tail = rxbuffer.head;
rxbuffer.overflow = false; rxbuffer.overflow = false;
} }
void serialRxCancel (void) static void serialRxCancel (void)
{ {
serialRxFlush(); serialRxFlush();
rxbuffer.data[rxbuffer.head] = ASCII_CAN; rxbuffer.data[rxbuffer.head] = ASCII_CAN;
rxbuffer.head = (rxbuffer.tail + 1) & (RX_BUFFER_SIZE - 1); 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; uint_fast16_t next_head;
@ -324,7 +221,7 @@ bool serialPutC (const char c)
return true; return true;
} }
void serialWriteS (const char *data) static void serialWriteS (const char *data)
{ {
char c, *ptr = (char *)data; char c, *ptr = (char *)data;
@ -332,7 +229,7 @@ void serialWriteS (const char *data)
serialPutC(c); serialPutC(c);
} }
void serialWrite(const char *s, uint16_t length) static void serialWrite(const char *s, uint16_t length)
{ {
char *ptr = (char *)s; char *ptr = (char *)s;
@ -340,18 +237,150 @@ void serialWrite(const char *s, uint16_t length)
serialPutC(*ptr++); serialPutC(*ptr++);
} }
bool serialSuspendInput (bool suspend) static bool serialSuspendInput (bool suspend)
{ {
return stream_rx_suspend(&rxbuffer, 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; 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); 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) static void uart_interrupt_handler (void)
{ {
uint_fast16_t bptr; uint_fast16_t bptr;

View File

@ -4,7 +4,7 @@
Part of grblHAL 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 Grbl is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@ -26,18 +26,8 @@
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
void serialInit (uint32_t baud_rate); #include "grbl/hal.h"
bool serialSetBaudRate (uint32_t baud_rate);
int16_t serialGetC (void); const io_stream_t *serialInit (uint32_t baud_rate);
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);
#endif #endif

View File

@ -39,36 +39,20 @@ extern "C" {
static stream_block_tx_buffer_t txbuf = {0}; static stream_block_tx_buffer_t txbuf = {0};
static char rxbuf[BLOCK_RX_BUFFER_SIZE]; static char rxbuf[BLOCK_RX_BUFFER_SIZE];
static stream_rx_buffer_t usb_rxbuffer; 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 // 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; uint_fast16_t tail = usb_rxbuffer.tail, head = usb_rxbuffer.head;
return (uint16_t)BUFCOUNT(head, tail, RX_BUFFER_SIZE); return (uint16_t)BUFCOUNT(head, tail, RX_BUFFER_SIZE);
} }
*/
// //
// Returns number of free characters in serial input buffer // 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; uint_fast16_t tail = usb_rxbuffer.tail, head = usb_rxbuffer.head;
return (uint16_t)((RX_BUFFER_SIZE - 1) - BUFCOUNT(head, tail, RX_BUFFER_SIZE)); 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 // 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.data[usb_rxbuffer.head] = CMD_RESET;
usb_rxbuffer.tail = usb_rxbuffer.head; usb_rxbuffer.tail = usb_rxbuffer.head;
@ -96,7 +80,7 @@ void usb_serialRxCancel (void)
// //
// Writes a character to the serial output stream // Writes a character to the serial output stream
// //
bool usb_serialPutC (const char c) static bool usb_serialPutC (const char c)
{ {
SerialUSB.write(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. // 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! // NOTE: grbl always sends ASCII_LF terminated strings!
// //
void usb_serialWriteS (const char *s) static void usb_serialWriteS (const char *s)
{ {
if(*s == '\0') if(*s == '\0')
return; 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 // 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(s);
usb_serialWriteS(ASCII_EOL); 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 // 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; char *ptr = (char *)s;
while(length--) while(length--)
usb_serialPutC(*ptr++); usb_serialPutC(*ptr++);
} }
*/
// //
// serialGetC - returns -1 if no data available // serialGetC - returns -1 if no data available
// //
int16_t usb_serialGetC (void) static int16_t usb_serialGetC (void)
{ {
uint16_t bptr = usb_rxbuffer.tail; uint16_t bptr = usb_rxbuffer.tail;
@ -185,11 +169,43 @@ int16_t usb_serialGetC (void)
return (int16_t)data; return (int16_t)data;
} }
bool usb_serialSuspendInput (bool suspend) static bool usb_serialSuspendInput (bool suspend)
{ {
return stream_rx_suspend(&usb_rxbuffer, 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, // This function get called from the systick interrupt handler,
// used here to get characters off the USB serial input stream and buffer // used here to get characters off the USB serial input stream and buffer

View File

@ -4,7 +4,7 @@
Part of grblHAL 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 Grbl is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@ -27,22 +27,12 @@
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include "grbl/hal.h"
extern void usb_execute_realtime (uint_fast16_t state); extern void usb_execute_realtime (uint_fast16_t state);
#define usb_serial_poll() usb_execute_realtime(0) #define usb_serial_poll() usb_execute_realtime(0)
void usb_serialInit(void); const io_stream_t *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);
#endif #endif

View File

@ -35,28 +35,20 @@
static stream_block_tx_buffer_t txbuf = {0}; static stream_block_tx_buffer_t txbuf = {0};
static char rxbuf[BLOCK_RX_BUFFER_SIZE]; static char rxbuf[BLOCK_RX_BUFFER_SIZE];
static stream_rx_buffer_t usb_rxbuffer; 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 // 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; uint_fast16_t tail = usb_rxbuffer.tail, head = usb_rxbuffer.head;
return (uint16_t)BUFCOUNT(head, tail, RX_BUFFER_SIZE); return (uint16_t)BUFCOUNT(head, tail, RX_BUFFER_SIZE);
} }
*/
// //
// Returns number of free characters in serial input buffer // 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; uint_fast16_t tail = usb_rxbuffer.tail, head = usb_rxbuffer.head;
return (uint16_t)((RX_BUFFER_SIZE - 1) - BUFCOUNT(head, tail, RX_BUFFER_SIZE)); 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) // Flushes the serial input buffer (including the USB buffer)
// //
void usb_serialRxFlush (void) static void usb_serialRxFlush (void)
{ {
usb_serial_flush_input(); usb_serial_flush_input();
usb_rxbuffer.tail = usb_rxbuffer.head; 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 // 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.data[usb_rxbuffer.head] = CMD_RESET;
usb_rxbuffer.tail = usb_rxbuffer.head; usb_rxbuffer.tail = usb_rxbuffer.head;
@ -84,7 +76,7 @@ void usb_serialRxCancel (void)
// //
// Writes a character to the serial output stream // 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); 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 // 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') if(*s == '\0')
return; 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 // 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(s);
usb_serialWriteS(ASCII_EOL); 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 // 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; char *ptr = (char *)s;
while(length--) while(length--)
usb_serialPutC(*ptr++); usb_serialPutC(*ptr++);
} }
*/
// //
// serialGetC - returns -1 if no data available // serialGetC - returns -1 if no data available
// //
int16_t usb_serialGetC (void) static int16_t usb_serialGetC (void)
{ {
uint16_t bptr = usb_rxbuffer.tail; uint16_t bptr = usb_rxbuffer.tail;
@ -171,11 +163,33 @@ int16_t usb_serialGetC (void)
return (int16_t)data; return (int16_t)data;
} }
bool usb_serialSuspendInput (bool suspend) static bool usb_serialSuspendInput (bool suspend)
{ {
return stream_rx_suspend(&usb_rxbuffer, 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, // This function get called from the systick interrupt handler,
// used here to get characters off the USB serial input stream and buffer // used here to get characters off the USB serial input stream and buffer

View File

@ -4,7 +4,7 @@
Part of grblHAL 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 Grbl is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@ -27,22 +27,12 @@
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include "grbl/hal.h"
extern void usb_execute_realtime (uint_fast16_t state); extern void usb_execute_realtime (uint_fast16_t state);
#define usb_serial_poll() usb_execute_realtime(0) #define usb_serial_poll() usb_execute_realtime(0)
void usb_serialInit(void); const io_stream_t *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);
#endif #endif