From 44e4dc4ea37da85fd3a374ca49cf6c80708f8d64 Mon Sep 17 00:00:00 2001 From: Terje Io Date: Fri, 19 May 2023 19:17:32 +0200 Subject: [PATCH] Extended handling of legacy printable real-time commands due to ESP32 RTOS issue. Internal changes to crossbar definitions, improved stream handling and sleep handling. --- README.md | 6 +- changelog.md | 24 ++++ crossbar.h | 308 +++++++++++++++++++++++++++-------------------- grbl.h | 2 +- hal.h | 9 -- ioports.c | 4 +- pin_bits_masks.h | 4 + protocol.c | 5 + sleep.c | 1 + stream.c | 64 +++++++--- stream.h | 8 +- 11 files changed, 273 insertions(+), 162 deletions(-) diff --git a/README.md b/README.md index b699858..20f1b4d 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ It has been written to complement grblHAL and has features such as proper keyboa --- -Latest build date is 20230501 see the [changelog](changelog.md) for details. +Latest build date is 20230507 see the [changelog](changelog.md) for details. __NOTE:__ A settings reset will be performed on an update of builds earlier than 20230125. Backup and restore of settings is recommended. __IMPORTANT!__ A new setting has been introduced for ganged axes motors in build 20211121. I have only bench tested this for a couple of drivers, correct function should be verified after updating by those who have more than three motors configured. @@ -86,7 +86,9 @@ List of Supported G-Codes: ***** requires keypad macros plugin or SD card plugin. Nesting is not allowed. ``` +G/M-codes not supported by [legacy Grbl](https://github.com/gnea/grbl/wiki) are documented [here](https://github.com/grblHAL/core/wiki/Additional-G--and-M-codes). + Some [plugins](https://github.com/grblHAL/plugins) implements additional M-codes. --- -2023-05-07 +2023-05-11 diff --git a/changelog.md b/changelog.md index d0cf737..f36a5f7 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,29 @@ ## grblHAL changelog +20230519 + +Core: + +* Extended handling of legacy printable real-time commands due to ESP32 RTOS issue. +* Internal to changes for crossbar definitions, improved stream handling and sleep handling. + +Plugins: + +* Networking: added support for some WIZnet SPI based ethernet breakout boards, currently only W5100S and W5500 based. Updated for core changes. + +Drivers: + +* STM32F4xx: added low level driver support for WIZnet SPI based ethernet breakout boards, updated SPI interface for DMA transfer. + +* RP2040: added low level driver support for WIZnet SPI based ethernet breakout boards, updated SPI interface for DMA transfer. +__NOTE:__ Build support for ethernet is not yet ready! + +Web Builder: + +Added options for spindle sync and WIZnet networking for relevant drivers and boards. + +--- + 20230507 Core: diff --git a/crossbar.h b/crossbar.h index 00d07cc..6d1c750 100644 --- a/crossbar.h +++ b/crossbar.h @@ -58,6 +58,7 @@ typedef enum { Input_LimitV, Input_LimitV_Max, Input_MISO, + Input_SPIIRQ, Input_RX, Input_KeypadStrobe, // To be deprecated? Use Input_I2CStrobe instead. Input_I2CStrobe, @@ -75,6 +76,14 @@ typedef enum { Input_Aux5, Input_Aux6, Input_Aux7, + Input_Analog_Aux0, + Input_Analog_Aux1, + Input_Analog_Aux2, + Input_Analog_Aux3, + Input_Analog_Aux4, + Input_Analog_Aux5, + Input_Analog_Aux6, + Input_Analog_Aux7, Input_MotorWarning, Input_MotorFault, Outputs, @@ -130,6 +139,8 @@ typedef enum { Output_RTS, Output_SCK, Output_MOSI, + Output_SPIRST, + Output_SPICS, Output_SdCardCS, Output_Aux0, Output_Aux1, @@ -139,6 +150,14 @@ typedef enum { Output_Aux5, Output_Aux6, Output_Aux7, + Output_Analog_Aux0, + Output_Analog_Aux1, + Output_Analog_Aux2, + Output_Analog_Aux3, + Output_Analog_Aux4, + Output_Analog_Aux5, + Output_Analog_Aux6, + Output_Analog_Aux7, Bidirectional, Bidirectional_SDA = Bidirectional, Bidirectional_MotorUARTX, @@ -161,137 +180,156 @@ typedef struct { } pin_name_t; PROGMEM static const pin_name_t pin_names[] = { - { .function = Input_Probe, .name = "Probe" }, - { .function = Input_Reset, .name = "Reset" }, - { .function = Input_FeedHold, .name = "Feed hold" }, - { .function = Input_CycleStart, .name = "Cycle start" }, - { .function = Input_SafetyDoor, .name = "Safety door" }, - { .function = Input_LimitsOverride, .name = "Limits override" }, - { .function = Input_EStop, .name = "Emergency stop" }, - { .function = Input_BlockDelete, .name = "Block delete" }, - { .function = Input_SingleBlock, .name = "Single block" }, - { .function = Input_StopDisable, .name = "Stop disable" }, - { .function = Input_ProbeDisconnect, .name = "Probe disconnect" }, - { .function = Input_MPGSelect, .name = "MPG mode select" }, - { .function = Input_LimitX, .name = "X limit min" }, - { .function = Input_LimitX_2, .name = "X limit min 2" }, - { .function = Input_LimitX_Max, .name = "X limit max" }, - { .function = Input_LimitY, .name = "Y limit min" }, - { .function = Input_LimitY_2, .name = "Y limit min 2" }, - { .function = Input_LimitY_Max, .name = "Y limit max" }, - { .function = Input_LimitZ, .name = "Z limit min" }, - { .function = Input_LimitZ_2, .name = "Z limit min 2" }, - { .function = Input_LimitZ_Max, .name = "Z limit max" }, - { .function = Input_MISO, .name = "MISO" }, - { .function = Input_RX, .name = "RX" }, - { .function = Input_KeypadStrobe, .name = "Keypad strobe" }, - { .function = Input_I2CStrobe, .name = "I2C strobe" }, - { .function = Input_QEI_A, .name = "QEI A" }, - { .function = Input_QEI_B, .name = "QEI B" }, - { .function = Input_QEI_Select, .name = "QEI select" }, - { .function = Input_QEI_Index, .name = "QEI index" }, - { .function = Input_SpindleIndex, .name = "Spindle index" }, - { .function = Input_SpindlePulse, .name = "Spindle pulse" }, - { .function = Input_MotorWarning, .name = "Motor warning" }, - { .function = Input_MotorFault, .name = "Motor fault" }, - { .function = Input_Aux0, .name = "Aux input 0" }, - { .function = Input_Aux1, .name = "Aux input 1" }, - { .function = Input_Aux2, .name = "Aux input 2" }, - { .function = Input_Aux3, .name = "Aux input 3" }, - { .function = Input_Aux4, .name = "Aux input 4" }, - { .function = Input_Aux5, .name = "Aux input 5" }, - { .function = Input_Aux6, .name = "Aux input 6" }, - { .function = Input_Aux7, .name = "Aux input 7" }, - { .function = Output_StepX, .name = "X step" }, - { .function = Output_StepX_2, .name = "X2 step" }, - { .function = Output_StepY, .name = "Y step" }, - { .function = Output_StepY_2, .name = "Y2 step" }, - { .function = Output_StepZ, .name = "Z step" }, - { .function = Output_StepZ_2, .name = "Z2 step" }, - { .function = Output_DirX, .name = "X dir" }, - { .function = Output_DirX_2, .name = "X2 dir" }, - { .function = Output_DirY, .name = "Y dir" }, - { .function = Output_DirY_2, .name = "Y2 dir" }, - { .function = Output_DirZ, .name = "Z dir" }, - { .function = Output_DirZ_2, .name = "Z2 dir" }, - { .function = Output_StepperPower, .name = "Stepper power" }, - { .function = Output_StepperEnable, .name = "Steppers enable" }, - { .function = Output_StepperEnableX, .name = "X enable" }, - { .function = Output_StepperEnableY, .name = "Y enable" }, - { .function = Output_StepperEnableZ, .name = "Z enable" }, - { .function = Output_StepperEnableXY, .name = "XY enable" }, + { .function = Input_Probe, .name = "Probe" }, + { .function = Input_Reset, .name = "Reset" }, + { .function = Input_FeedHold, .name = "Feed hold" }, + { .function = Input_CycleStart, .name = "Cycle start" }, + { .function = Input_SafetyDoor, .name = "Safety door" }, + { .function = Input_LimitsOverride, .name = "Limits override" }, + { .function = Input_EStop, .name = "Emergency stop" }, + { .function = Input_BlockDelete, .name = "Block delete" }, + { .function = Input_SingleBlock, .name = "Single block" }, + { .function = Input_StopDisable, .name = "Stop disable" }, + { .function = Input_ProbeDisconnect, .name = "Probe disconnect" }, + { .function = Input_MPGSelect, .name = "MPG mode select" }, + { .function = Input_LimitX, .name = "X limit min" }, + { .function = Input_LimitX_2, .name = "X limit min 2" }, + { .function = Input_LimitX_Max, .name = "X limit max" }, + { .function = Input_LimitY, .name = "Y limit min" }, + { .function = Input_LimitY_2, .name = "Y limit min 2" }, + { .function = Input_LimitY_Max, .name = "Y limit max" }, + { .function = Input_LimitZ, .name = "Z limit min" }, + { .function = Input_LimitZ_2, .name = "Z limit min 2" }, + { .function = Input_LimitZ_Max, .name = "Z limit max" }, + { .function = Input_MISO, .name = "MISO" }, + { .function = Input_SPIIRQ, .name = "SPI IRQ" }, + { .function = Input_RX, .name = "RX" }, + { .function = Input_KeypadStrobe, .name = "Keypad strobe" }, + { .function = Input_I2CStrobe, .name = "I2C strobe" }, + { .function = Input_QEI_A, .name = "QEI A" }, + { .function = Input_QEI_B, .name = "QEI B" }, + { .function = Input_QEI_Select, .name = "QEI select" }, + { .function = Input_QEI_Index, .name = "QEI index" }, + { .function = Input_SpindleIndex, .name = "Spindle index" }, + { .function = Input_SpindlePulse, .name = "Spindle pulse" }, + { .function = Input_MotorWarning, .name = "Motor warning" }, + { .function = Input_MotorFault, .name = "Motor fault" }, + { .function = Input_Aux0, .name = "Aux input 0" }, + { .function = Input_Aux1, .name = "Aux input 1" }, + { .function = Input_Aux2, .name = "Aux input 2" }, + { .function = Input_Aux3, .name = "Aux input 3" }, + { .function = Input_Aux4, .name = "Aux input 4" }, + { .function = Input_Aux5, .name = "Aux input 5" }, + { .function = Input_Aux6, .name = "Aux input 6" }, + { .function = Input_Aux7, .name = "Aux input 7" }, + { .function = Input_Analog_Aux0, .name = "Aux analog input 0" }, + { .function = Input_Analog_Aux1, .name = "Aux analog input 1" }, + { .function = Input_Analog_Aux2, .name = "Aux analog input 2" }, + { .function = Input_Analog_Aux3, .name = "Aux analog input 3" }, + { .function = Input_Analog_Aux4, .name = "Aux analog input 4" }, + { .function = Input_Analog_Aux5, .name = "Aux analog input 5" }, + { .function = Input_Analog_Aux6, .name = "Aux analog input 6" }, + { .function = Input_Analog_Aux7, .name = "Aux analog input 7" }, + { .function = Output_StepX, .name = "X step" }, + { .function = Output_StepX_2, .name = "X2 step" }, + { .function = Output_StepY, .name = "Y step" }, + { .function = Output_StepY_2, .name = "Y2 step" }, + { .function = Output_StepZ, .name = "Z step" }, + { .function = Output_StepZ_2, .name = "Z2 step" }, + { .function = Output_DirX, .name = "X dir" }, + { .function = Output_DirX_2, .name = "X2 dir" }, + { .function = Output_DirY, .name = "Y dir" }, + { .function = Output_DirY_2, .name = "Y2 dir" }, + { .function = Output_DirZ, .name = "Z dir" }, + { .function = Output_DirZ_2, .name = "Z2 dir" }, + { .function = Output_StepperPower, .name = "Stepper power" }, + { .function = Output_StepperEnable, .name = "Steppers enable" }, + { .function = Output_StepperEnableX, .name = "X enable" }, + { .function = Output_StepperEnableY, .name = "Y enable" }, + { .function = Output_StepperEnableZ, .name = "Z enable" }, + { .function = Output_StepperEnableXY, .name = "XY enable" }, #ifdef A_AXIS - { .function = Output_StepA, .name = "A step" }, - { .function = Output_DirA, .name = "A dir" }, - { .function = Output_StepperEnableA, .name = "A enable" }, - { .function = Input_LimitA, .name = "A limit min" }, - { .function = Input_LimitA_Max, .name = "A limit max" }, + { .function = Output_StepA, .name = "A step" }, + { .function = Output_DirA, .name = "A dir" }, + { .function = Output_StepperEnableA, .name = "A enable" }, + { .function = Input_LimitA, .name = "A limit min" }, + { .function = Input_LimitA_Max, .name = "A limit max" }, #endif #ifdef B_AXIS - { .function = Output_StepB, .name = "B step" }, - { .function = Output_DirB, .name = "B dir" }, - { .function = Output_StepperEnableB, .name = "B enable" }, - { .function = Output_StepperEnableAB, .name = "AB enable" }, - { .function = Input_LimitB, .name = "B limit min" }, - { .function = Input_LimitB_Max, .name = "B limit max" }, + { .function = Output_StepB, .name = "B step" }, + { .function = Output_DirB, .name = "B dir" }, + { .function = Output_StepperEnableB, .name = "B enable" }, + { .function = Output_StepperEnableAB, .name = "AB enable" }, + { .function = Input_LimitB, .name = "B limit min" }, + { .function = Input_LimitB_Max, .name = "B limit max" }, #endif #ifdef C_AXIS - { .function = Output_StepC, .name = "C step" }, - { .function = Output_DirC, .name = "C dir" }, - { .function = Output_StepperEnableC, .name = "C enable" }, - { .function = Input_LimitC, .name = "C limit min" }, - { .function = Input_LimitC_Max, .name = "C limit max" }, + { .function = Output_StepC, .name = "C step" }, + { .function = Output_DirC, .name = "C dir" }, + { .function = Output_StepperEnableC, .name = "C enable" }, + { .function = Input_LimitC, .name = "C limit min" }, + { .function = Input_LimitC_Max, .name = "C limit max" }, #endif #ifdef U_AXIS - { .function = Output_StepU, .name = "U step" }, - { .function = Output_DirU, .name = "U dir" }, - { .function = Output_StepperEnableU, .name = "U enable" }, - { .function = Input_LimitU, .name = "U limit min" }, - { .function = Input_LimitU_Max, .name = "U limit max" }, + { .function = Output_StepU, .name = "U step" }, + { .function = Output_DirU, .name = "U dir" }, + { .function = Output_StepperEnableU, .name = "U enable" }, + { .function = Input_LimitU, .name = "U limit min" }, + { .function = Input_LimitU_Max, .name = "U limit max" }, #endif #ifdef V_AXIS - { .function = Output_StepV, .name = "V step" }, - { .function = Output_DirV, .name = "V dir" }, - { .function = Output_StepperEnableV, .name = "V enable" }, - { .function = Input_LimitV, .name = "V limit min" }, - { .function = Input_LimitV_Max, .name = "V limit max" }, + { .function = Output_StepV, .name = "V step" }, + { .function = Output_DirV, .name = "V dir" }, + { .function = Output_StepperEnableV, .name = "V enable" }, + { .function = Input_LimitV, .name = "V limit min" }, + { .function = Input_LimitV_Max, .name = "V limit max" }, #endif - { .function = Output_MotorChipSelect, .name = "Motor CS" }, - { .function = Output_MotorChipSelectX, .name = "Motor CSX" }, - { .function = Output_MotorChipSelectY, .name = "Motor CSY" }, - { .function = Output_MotorChipSelectZ, .name = "Motor CSZ" }, - { .function = Output_MotorChipSelectM3, .name = "Motor CSM3" }, - { .function = Output_MotorChipSelectM4, .name = "Motor CSM4" }, - { .function = Output_MotorChipSelectM5, .name = "Motor CSM5" }, - { .function = Output_MotorChipSelectM6, .name = "Motor CSM6" }, - { .function = Output_MotorChipSelectM7, .name = "Motor CSM7" }, - { .function = Output_SpindleOn, .name = "Spindle on" }, - { .function = Output_SpindleDir, .name = "Spindle direction" }, - { .function = Output_SpindlePWM, .name = "Spindle PWM" }, - { .function = Output_CoolantMist, .name = "Mist" }, - { .function = Output_CoolantFlood, .name = "Flood" }, - { .function = Output_TX, .name = "TX" }, - { .function = Output_RTS, .name = "RTS" }, - { .function = Output_SCK, .name = "SCK" }, - { .function = Output_MOSI, .name = "MOSI" }, - { .function = Output_SdCardCS, .name = "SD card CS" }, - { .function = Output_Aux0, .name = "Aux out 0" }, - { .function = Output_Aux1, .name = "Aux out 1" }, - { .function = Output_Aux2, .name = "Aux out 2" }, - { .function = Output_Aux3, .name = "Aux out 3" }, - { .function = Output_Aux4, .name = "Aux out 4" }, - { .function = Output_Aux5, .name = "Aux out 5" }, - { .function = Output_Aux6, .name = "Aux out 6" }, - { .function = Output_Aux7, .name = "Aux out 7" }, - { .function = Bidirectional_SDA, .name = "SDA" }, - { .function = Bidirectional_MotorUARTX, .name = "UART X" }, - { .function = Bidirectional_MotorUARTY, .name = "UART Y" }, - { .function = Bidirectional_MotorUARTZ, .name = "UART Z" }, - { .function = Bidirectional_MotorUARTM3, .name = "UART M3" }, - { .function = Bidirectional_MotorUARTM4, .name = "UART M4" }, - { .function = Bidirectional_MotorUARTM5, .name = "UART M5" }, - { .function = Bidirectional_MotorUARTM6, .name = "UART M6" }, - { .function = Bidirectional_MotorUARTM7, .name = "UART M7" } + { .function = Output_MotorChipSelect, .name = "Motor CS" }, + { .function = Output_MotorChipSelectX, .name = "Motor CSX" }, + { .function = Output_MotorChipSelectY, .name = "Motor CSY" }, + { .function = Output_MotorChipSelectZ, .name = "Motor CSZ" }, + { .function = Output_MotorChipSelectM3, .name = "Motor CSM3" }, + { .function = Output_MotorChipSelectM4, .name = "Motor CSM4" }, + { .function = Output_MotorChipSelectM5, .name = "Motor CSM5" }, + { .function = Output_MotorChipSelectM6, .name = "Motor CSM6" }, + { .function = Output_MotorChipSelectM7, .name = "Motor CSM7" }, + { .function = Output_SpindleOn, .name = "Spindle on" }, + { .function = Output_SpindleDir, .name = "Spindle direction" }, + { .function = Output_SpindlePWM, .name = "Spindle PWM" }, + { .function = Output_CoolantMist, .name = "Mist" }, + { .function = Output_CoolantFlood, .name = "Flood" }, + { .function = Output_TX, .name = "TX" }, + { .function = Output_RTS, .name = "RTS" }, + { .function = Output_SCK, .name = "SCK" }, + { .function = Output_MOSI, .name = "MOSI" }, + { .function = Output_SPIRST, .name = "SPI reset" }, + { .function = Output_SPICS, .name = "SPI CS" }, + { .function = Output_SdCardCS, .name = "SD card CS" }, + { .function = Output_Aux0, .name = "Aux out 0" }, + { .function = Output_Aux1, .name = "Aux out 1" }, + { .function = Output_Aux2, .name = "Aux out 2" }, + { .function = Output_Aux3, .name = "Aux out 3" }, + { .function = Output_Aux4, .name = "Aux out 4" }, + { .function = Output_Aux5, .name = "Aux out 5" }, + { .function = Output_Aux6, .name = "Aux out 6" }, + { .function = Output_Aux7, .name = "Aux out 7" }, + { .function = Output_Analog_Aux0, .name = "Aux analog out 0" }, + { .function = Output_Analog_Aux1, .name = "Aux analog out 1" }, + { .function = Output_Analog_Aux2, .name = "Aux analog out 2" }, + { .function = Output_Analog_Aux3, .name = "Aux analog out 3" }, + { .function = Output_Analog_Aux4, .name = "Aux analog out 4" }, + { .function = Output_Analog_Aux5, .name = "Aux analog out 5" }, + { .function = Output_Analog_Aux6, .name = "Aux analog out 6" }, + { .function = Output_Analog_Aux7, .name = "Aux analog out 7" }, + { .function = Bidirectional_SDA, .name = "SDA" }, + { .function = Bidirectional_MotorUARTX, .name = "UART X" }, + { .function = Bidirectional_MotorUARTY, .name = "UART Y" }, + { .function = Bidirectional_MotorUARTZ, .name = "UART Z" }, + { .function = Bidirectional_MotorUARTM3, .name = "UART M3" }, + { .function = Bidirectional_MotorUARTM4, .name = "UART M4" }, + { .function = Bidirectional_MotorUARTM5, .name = "UART M5" }, + { .function = Bidirectional_MotorUARTM6, .name = "UART M6" }, + { .function = Bidirectional_MotorUARTM7, .name = "UART M7" } }; typedef enum { @@ -344,7 +382,8 @@ typedef enum { } pin_irq_mode_t; typedef enum { - IRQ_I2C_Strobe = 0 + IRQ_I2C_Strobe = 0, + IRQ_SPI } irq_type_t; typedef bool (*irq_callback_ptr)(uint_fast8_t id, bool level); @@ -371,6 +410,8 @@ typedef enum { #define PINMODE_PULLUP (PullMode_Up<<3) #define PINMODE_PULLDOWN (PullMode_Down<<3) #define PINMODE_REMAP (1U<<10) +#define PINMODE_PWM (1U<<11) +#define PINMODE_ANALOG (1U<<12) typedef union { uint16_t mask; @@ -389,12 +430,23 @@ typedef union { }; } pin_mode_t; -typedef bool (*xbar_get_value_ptr)(void); -typedef void (*xbar_set_value_ptr)(bool on); -typedef void (*xbar_event_ptr)(bool on); -typedef void (*xbar_config_ptr)(void *cfg_data); - +//! /a cfg_data argument to /a xbar_config_ptr for PWM pins typedef struct { + float freq_hz; // + float off_value; // percent of period + float min_value; // percent of period + float max_value; // percent of period + bool invert; +} pwm_config_t; + +struct xbar; + +typedef float (*xbar_get_value_ptr)(struct xbar *pin); +typedef void (*xbar_set_value_ptr)(struct xbar *pin, float value); +typedef void (*xbar_event_ptr)(bool on); +typedef void (*xbar_config_ptr)(struct xbar *pin, void *cfg_data); + +typedef struct xbar { pin_function_t function; pin_group_t group; void *port; @@ -406,7 +458,7 @@ typedef struct { xbar_config_ptr config; xbar_get_value_ptr get_value; xbar_set_value_ptr set_value; - xbar_event_ptr on_event; + xbar_event_ptr on_event; // ?? - remove? } xbar_t; typedef struct { diff --git a/grbl.h b/grbl.h index d36dade..6c95f17 100644 --- a/grbl.h +++ b/grbl.h @@ -42,7 +42,7 @@ #else #define GRBL_VERSION "1.1f" #endif -#define GRBL_BUILD 20230507 +#define GRBL_BUILD 20230519 #define GRBL_URL "https://github.com/grblHAL" diff --git a/hal.h b/hal.h index 3d8a955..4d6978f 100644 --- a/hal.h +++ b/hal.h @@ -79,14 +79,6 @@ typedef void (*driver_reset_ptr)(void); /*! \brief Pointer to function for getting free memory (as sum of all free blocks in the heap). */ typedef uint32_t (*get_free_mem_ptr)(void); -/*! \brief Optional pointer to function for switching between I/O streams. -\param stream pointer to io_stream_t -\returns true if switch was successful - -__NOTE:__ required if the networking plugin is to be supported. -*/ -typedef bool (*stream_select_ptr)(const io_stream_t *stream); - /*! \brief Pointer to function for registering information about a peripheral pin. \param pin as periph_pin_t struct containing pin information. */ @@ -585,7 +577,6 @@ typedef struct { spindle_data_ptrs_t spindle_data; //!< Handlers for getting/resetting spindle data (RPM, angular position, ...). stepper_ptrs_t stepper; //!< Handlers for stepper motors. io_stream_t stream; //!< Handlers for stream I/O. - stream_select_ptr stream_select; //!< Optional handler for switching between I/O streams. settings_changed_ptr settings_changed; //!< Callback handler to be called on settings loaded or settings changed events. probe_ptrs_t probe; //!< Optional handlers for probe input(s). tool_ptrs_t tool; //!< Optional handlers for tool changes. diff --git a/ioports.c b/ioports.c index 21b0686..faea7af 100644 --- a/ioports.c +++ b/ioports.c @@ -3,7 +3,7 @@ Part of grblHAL - Copyright (c) 2021 Terje Io + Copyright (c) 2021-2023 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 @@ -90,7 +90,7 @@ bool ioport_claim (io_port_type_t type, io_port_direction_t dir, uint8_t *port, uint8_t n_ports = ioports_available(type, dir); uint8_t base = type == Port_Digital ? (dir == Port_Input ? Input_Aux0 : Output_Aux0) - : (dir == Port_Input ? Input_Aux0 : Output_Aux0); // TODO add analog ports? + : (dir == Port_Input ? Input_Analog_Aux0 : Output_Analog_Aux0); if(hal.port.claim != NULL) { diff --git a/pin_bits_masks.h b/pin_bits_masks.h index d6efe9d..e96d7bc 100644 --- a/pin_bits_masks.h +++ b/pin_bits_masks.h @@ -197,6 +197,10 @@ #define I2C_STROBE_BIT (1<is_connected) + return stream->is_connected(); + + stream_connection_t *connection = connections; + + while(connection) { + if(connection->stream->type == stream->type && + connection->stream->instance == stream->instance && + connection->stream->state.is_usb == stream->state.is_usb) + return connection->is_up(); + connection = connection->next; + } + + return false; +} + static void stream_write_all (const char *s) { stream_connection_t *connection = connections; while(connection) { - if(connection->flags.is_up) + if(connection->is_up()) connection->stream->write(s); connection = connection->next; } } +static bool is_connected (void) +{ + return true; +} + +static bool is_not_connected (void) +{ + return false; +} + static stream_connection_t *add_connection (const io_stream_t *stream) { stream_connection_t *connection, *last = connections; if(base.stream == NULL) { base.stream = stream; - base.flags.is_up = stream->state.connected == On; connection = &base; } else if((connection = malloc(sizeof(stream_connection_t)))) { connection->stream = stream; - connection->flags.is_up = stream->state.connected == On || stream->state.is_usb == On; // TODO: add connect/disconnect event to driver code connection->next = NULL; while(last->next) { last = last->next; @@ -195,6 +221,8 @@ static stream_connection_t *add_connection (const io_stream_t *stream) last->next = connection; } + connection->is_up = stream->is_connected ? stream->is_connected : (stream->state.is_usb ? is_not_connected : is_connected); + return connection; } @@ -203,7 +231,7 @@ static bool stream_select (const io_stream_t *stream, bool add) static const io_stream_t *active_stream = NULL; if(stream == base.stream) { - base.flags.is_up = add; + base.is_up = add ? (stream->is_connected ? stream->is_connected : is_connected) : is_not_connected; return true; } @@ -237,14 +265,14 @@ static bool stream_select (const io_stream_t *stream, bool add) switch(stream->type) { case StreamType_Serial: - if(active_stream && active_stream->type != StreamType_Serial && stream->state.connected) { + if(active_stream && active_stream->type != StreamType_Serial && connection_is_up((io_stream_t *)stream)) { hal.stream.write = stream->write; report_message("SERIAL STREAM ACTIVE", Message_Plain); } break; case StreamType_Telnet: - if(hal.stream.state.connected) + if(connection_is_up(&hal.stream)) report_message("TELNET STREAM ACTIVE", Message_Plain); if(add && sys.driver_started) { hal.stream.write_all = stream->write; @@ -253,7 +281,7 @@ static bool stream_select (const io_stream_t *stream, bool add) break; case StreamType_WebSocket: - if(hal.stream.state.connected) + if(connection_is_up(&hal.stream)) report_message("WEBSOCKET STREAM ACTIVE", Message_Plain); if(add && sys.driver_started && !hal.stream.state.webui_connected) { hal.stream.write_all = stream->write; @@ -262,7 +290,7 @@ static bool stream_select (const io_stream_t *stream, bool add) break; case StreamType_Bluetooth: - if(hal.stream.state.connected) + if(connection_is_up(&hal.stream)) report_message("BLUETOOTH STREAM ACTIVE", Message_Plain); if(add && sys.driver_started) { hal.stream.write_all = stream->write; @@ -321,9 +349,9 @@ io_stream_flags_t stream_get_flags (io_stream_t stream) bool stream_connect (const io_stream_t *stream) { - bool ok = hal.stream_select ? hal.stream_select(stream) : stream_select(stream, true); + bool ok; - if(ok && stream->type == StreamType_Serial && hal.periph_port.set_pin_description) { + if((ok = stream_select(stream, true)) && stream->type == StreamType_Serial && !stream->state.is_usb && hal.periph_port.set_pin_description) { hal.periph_port.set_pin_description(Input_RX, (pin_group_t)(PinGroup_UART + stream->instance), "Primary UART"); hal.periph_port.set_pin_description(Output_TX, (pin_group_t)(PinGroup_UART + stream->instance), "Primary UART"); } @@ -356,9 +384,7 @@ bool stream_connect_instance (uint8_t instance, uint32_t baud_rate) void stream_disconnect (const io_stream_t *stream) { - if(hal.stream_select) - hal.stream_select(NULL); - else if(stream) + if(stream) stream_select(stream, false); } @@ -381,14 +407,14 @@ bool stream_mpg_register (const io_stream_t *stream, bool rx_only, stream_write_ if(stream == NULL || stream->type != StreamType_Serial || stream->disable_rx == NULL) return false; - base.flags.is_up = On; +// base.flags.is_up = On; mpg_write_char = write_char; if(stream->write == NULL || rx_only) { mpg.stream = stream; - mpg.flags.is_up = stream->state.connected; + mpg.is_up = is_connected; return true; } @@ -527,7 +553,7 @@ const io_stream_t *stream_null_init (uint32_t baud_rate) { static const io_stream_t stream = { .type = StreamType_Null, - .state.connected = On, + .is_connected = is_connected, .read = stream_get_null, .write = null_write_string, .write_n = null_write, diff --git a/stream.h b/stream.h index fa7678d..8b872ad 100644 --- a/stream.h +++ b/stream.h @@ -89,6 +89,11 @@ typedef enum { StreamType_Null } stream_type_t; +/*! \brief Pointer to function for getting stream connected status. +\returns \a true connected, \a false otherwise. +*/ +typedef bool (*stream_is_connected_ptr)(void); + /*! \brief Pointer to function for getting number of characters available or free in a stream buffer. \returns number of characters available or free. */ @@ -197,7 +202,7 @@ typedef bool (*disable_rx_stream_ptr)(bool disable); typedef union { uint8_t value; struct { - uint8_t connected :1, + uint8_t connected :1, //!< deprecated claimable :1, claimed :1, can_set_baud :1, @@ -223,6 +228,7 @@ typedef struct { stream_type_t type; //!< Type of stream. uint8_t instance; //!< Instance of stream type, starts from 0. io_stream_state_t state; //!< Optional status flags such as connected status. + stream_is_connected_ptr is_connected; //!< Handler for getting stream connected status. get_stream_buffer_count_ptr get_rx_buffer_free; //!< Handler for getting number of free characters in the input buffer. stream_write_ptr write; //!< Handler for writing string to current output stream only. stream_write_ptr write_all; //!< Handler for writing string to all active output streams.