mirror of
https://github.com/grblHAL/core.git
synced 2026-09-26 09:55:54 +08:00
Added new ioport capabilities.
Added registration scheme for 3rd party I/O expander plugins. Fixed minor bug in ioport numbering (P<n>/E<n>) for plugin based ioports.
This commit is contained in:
@@ -1,5 +1,28 @@
|
||||
## grblHAL changelog
|
||||
|
||||
<a name="20250409">Build 20250409
|
||||
|
||||
Core:
|
||||
|
||||
* For developers: added new ioport capabilities, added optional support for drivers/boards wanting to claim basic pins \(stepper enable, spindle, coolant, ...\) from expander plugins.
|
||||
Added registration scheme for 3rd party I/O expander plugins in [expanders_init.h](https://github.com/grblHAL/core/blob/master/expanders_init.h).
|
||||
|
||||
* Fixed minor bug in ioport numbering \(`P<n>`/`E<n>`\) for plugin based ioports.
|
||||
|
||||
Drivers:
|
||||
|
||||
* iMXRT1062: fixed compilation error when Laser PPI mode was enabled. Ref. issue comment [#645, 12764973](https://github.com/grblHAL/core/discussions/645#discussioncomment-12764973).
|
||||
|
||||
* ESP32, iMXRT1062, LPC176x, RP2040, SAMX3X8E, STM32F4xx and STM32F7xx: updated to use new scheme for I/O expander plugin initialization.
|
||||
|
||||
* ESP32, RP2040: added initial support for claiming basic pins from IO expanders. CNC BoosterPack board: switched to use the generic PCA9654E I2C IO expander plugin instead of a driver specific plugin.
|
||||
|
||||
Plugins:
|
||||
|
||||
* Misc: updated MCP3221 I2C ADC and PCA9654E I2C IO expander plugins to match core changes.
|
||||
|
||||
---
|
||||
|
||||
<a name="20250407">Build 20250407
|
||||
|
||||
Core:
|
||||
|
||||
+18
-3
@@ -573,6 +573,20 @@ typedef enum {
|
||||
PullMode_UpDown = 0b11 //!< 0b11 (0x03) - only used to report port capability.
|
||||
} pull_mode_t;
|
||||
|
||||
//! ADC/DAC resolution or multi pin register width.
|
||||
typedef enum {
|
||||
Resolution_4bit = 0, //!< 0 - 4 bit
|
||||
Resolution_8bit, //!< 1 - 8 bit
|
||||
Resolution_10bit, //!< 2 - 10 bit
|
||||
Resolution_12bit, //!< 3 - 12 bit
|
||||
Resolution_14bit, //!< 4 - 14 bit
|
||||
Resolution_16bit, //!< 5 - 16 bit
|
||||
Resolution_18bit, //!< 6 - 18 bit
|
||||
Resolution_20bit, //!< 7 - 20 bit
|
||||
Resolution_24bit, //!< 8 - 24 bit
|
||||
Resolution_32bit //!< 9 - 32 bit, NOTE: "wait for input" can only return 31 bits
|
||||
} resolution_t;
|
||||
|
||||
#define PINMODE_NONE (0)
|
||||
#define PINMODE_OUTPUT (1U<<1)
|
||||
#ifndef __LPC17XX__
|
||||
@@ -590,8 +604,8 @@ typedef union {
|
||||
uint32_t input :1,
|
||||
output :1,
|
||||
open_drain :1,
|
||||
pull_mode :2,
|
||||
irq_mode :5,
|
||||
pull_mode :2, //!< pull_mode_t - pull up/down modes
|
||||
irq_mode :5, //!< pin_irq_mode_t - IRQ modes
|
||||
invert :1,
|
||||
analog :1,
|
||||
pwm :1,
|
||||
@@ -600,7 +614,8 @@ typedef union {
|
||||
debounce :1,
|
||||
external :1,
|
||||
async :1,
|
||||
unused :14;
|
||||
resolution :4, //!< resolution_t - ADC/DAC resolution
|
||||
unused :10;
|
||||
};
|
||||
} pin_cap_t;
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
|
||||
#include "hal.h"
|
||||
#include "nuts_bolts.h"
|
||||
#include "expanders_init.h"
|
||||
|
||||
#ifdef OPTS_POSTPROCESSING
|
||||
#define NO_OPTS_POST 0
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
expanders_init.h - An embedded CNC Controller with rs274/ngc (g-code) support
|
||||
|
||||
Calls the init function of enabled expanders, this file is typically included early in driver.h
|
||||
io_expanders_init() should be called at the end of the drivers driver_init() implementation,
|
||||
just before the driver claims ports.
|
||||
|
||||
These are NOT referenced in the core grbl code
|
||||
|
||||
Part of grblHAL
|
||||
|
||||
Copyright (c) 2025 Terje Io
|
||||
|
||||
grblHAL is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
grblHAL is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with grblHAL. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
// I2C expanders
|
||||
|
||||
#if PCA9654E_ENABLE || MCP3221_ENABLE
|
||||
|
||||
#if defined(I2C_ENABLE) && !I2C_ENABLE
|
||||
#undef I2C_ENABLE
|
||||
#endif
|
||||
|
||||
#ifndef I2C_ENABLE
|
||||
#define I2C_ENABLE 1
|
||||
#endif
|
||||
|
||||
#if MCP3221_ENABLE
|
||||
extern void mcp3221_init (void);
|
||||
#endif
|
||||
|
||||
#if PCA9654E_ENABLE
|
||||
extern void pca9654e_init(void);
|
||||
#endif
|
||||
|
||||
// Third party I2C expander plugins goes after this line
|
||||
|
||||
#endif // I2C expanders
|
||||
|
||||
// SPI expanders
|
||||
|
||||
//
|
||||
|
||||
// ModBus expanders
|
||||
|
||||
//
|
||||
|
||||
// CANBus expanders
|
||||
|
||||
//
|
||||
|
||||
// Other expanders
|
||||
|
||||
//
|
||||
|
||||
static inline void io_expanders_init (void)
|
||||
{
|
||||
#if MCP3221_ENABLE
|
||||
mcp3221_init();
|
||||
#endif
|
||||
|
||||
#if PCA9654E_ENABLE
|
||||
pca9654e_init();
|
||||
#endif
|
||||
}
|
||||
@@ -42,7 +42,7 @@
|
||||
#else
|
||||
#define GRBL_VERSION "1.1f"
|
||||
#endif
|
||||
#define GRBL_BUILD 20250407
|
||||
#define GRBL_BUILD 20250409
|
||||
|
||||
#define GRBL_URL "https://github.com/grblHAL"
|
||||
|
||||
|
||||
@@ -480,9 +480,9 @@ static bool io_claim (io_port_type_t type, io_port_direction_t dir, uint8_t *por
|
||||
while(cfg->map[idx] != *port)
|
||||
idx++;
|
||||
|
||||
for(; idx < cfg->last_claimed; idx++) {
|
||||
if((cfg->map[idx] = cfg->map[idx + 1]) <= io_port->port[cfg->type].n_end)
|
||||
io_port->hal.set_pin_description(dir, cfg->map[idx], (cfg->pnum + (idx * 3) + (idx > 9 ? idx - 10 : 0)));
|
||||
for(; idx < cfg->last_claimed ; idx++) {
|
||||
if((cfg->map[idx] = cfg->map[idx + 1]) != 255)
|
||||
io_set_pin_description(type, dir, idx, (cfg->pnum + (idx * 3) + (idx > 9 ? idx - 10 : 0)));
|
||||
}
|
||||
|
||||
io_port->hal.set_pin_description(dir, *port - io_port->port[cfg->type].n_start, description);
|
||||
|
||||
+49
-16
@@ -51,6 +51,8 @@
|
||||
#error "Encoder select input is not supported in this configuration!"
|
||||
#endif
|
||||
|
||||
#define EXPANDER_PORT 1
|
||||
|
||||
// Control input signals
|
||||
|
||||
// Define the CONTROL_PORT symbol as a shorthand in the *_map.h file if all control inputs share the same port.
|
||||
@@ -410,41 +412,58 @@ static inline control_signals_t aux_ctrl_scan_status (control_signals_t signals)
|
||||
|
||||
// The following pins are bound explicitly to aux output pins
|
||||
static aux_ctrl_out_t aux_ctrl_out[] = {
|
||||
#if defined(ESP_PLATFORM) || defined(RP2040) // for now
|
||||
#if defined(STEPPERS_ENABLE_PIN) && STEPPERS_ENABLE_PORT == EXPANDER_PORT
|
||||
{ .function = Output_StepperEnable, .aux_port = 0xFF, .pin = STEPPERS_ENABLE_PIN, .port = (void *)STEPPERS_ENABLE_PORT },
|
||||
#endif
|
||||
#if defined(X_ENABLE_PIN) && X_ENABLE_PORT == EXPANDER_PORT
|
||||
{ .function = Output_StepperEnableX, .aux_port = 0xFF, .pin = X_ENABLE_PIN, .port = (void *)X_ENABLE_PORT },
|
||||
#endif
|
||||
#if defined(Y_ENABLE_PIN) && Y_ENABLE_PORT == EXPANDER_PORT
|
||||
{ .function = Output_StepperEnableY, .aux_port = 0xFF, .pin = Y_ENABLE_PIN, .port = (void *)Y_ENABLE_PORT },
|
||||
#endif
|
||||
#if defined(XY_ENABLE_PIN) && XY_ENABLE_PORT == EXPANDER_PORT
|
||||
{ .function = Output_StepperEnableXY, .aux_port = 0xFF, .pin = XY_ENABLE_PIN, .port = (void *)XY_ENABLE_PORT },
|
||||
#endif
|
||||
#if defined(Z_ENABLE_PIN) && Z_ENABLE_PORT == EXPANDER_PORT
|
||||
{ .function = Output_StepperEnableZ, .aux_port = 0xFF, .pin = Z_ENABLE_PIN, .port = (void *)Z_ENABLE_PORT },
|
||||
#endif
|
||||
#endif
|
||||
#if AUX_CONTROLS & AUX_CONTROL_SPINDLE
|
||||
#ifdef SPINDLE_ENABLE_PIN
|
||||
#ifndef SPINDLE_ENABLE_PORT
|
||||
#define SPINDLE_ENABLE_PORT NULL
|
||||
#define SPINDLE_ENABLE_PORT 0
|
||||
#endif
|
||||
{ .function = Output_SpindleOn, .aux_port = 0xFF, .pin = SPINDLE_ENABLE_PIN, .port = (void *)SPINDLE_ENABLE_PORT },
|
||||
#endif
|
||||
#ifdef SPINDLE_PWM_PIN
|
||||
#ifndef SPINDLE_PWM_PORT
|
||||
#define SPINDLE_PWM_PORT NULL
|
||||
#define SPINDLE_PWM_PORT 0
|
||||
#endif
|
||||
{ .function = Output_SpindlePWM, .aux_port = 0xFF, .pin = SPINDLE_PWM_PIN, .port = (void *)SPINDLE_PWM_PORT },
|
||||
#endif
|
||||
#ifdef SPINDLE_DIRECTION_PIN
|
||||
#ifndef SPINDLE_DIRECTION_PORT
|
||||
#define SPINDLE_DIRECTION_PORT NULL
|
||||
#define SPINDLE_DIRECTION_PORT 0
|
||||
#endif
|
||||
{ .function = Output_SpindleDir, .aux_port = 0xFF, .pin = SPINDLE_DIRECTION_PIN, .port = (void *)SPINDLE_DIRECTION_PORT },
|
||||
#endif
|
||||
|
||||
#ifdef SPINDLE1_ENABLE_PIN
|
||||
#ifndef SPINDLE1_ENABLE_PORT
|
||||
#define SPINDLE1_ENABLE_PORT NULL
|
||||
#define SPINDLE1_ENABLE_PORT 0
|
||||
#endif
|
||||
{ .function = Output_Spindle1On, .aux_port = 0xFF, .pin = SPINDLE1_ENABLE_PIN, .port = (void *)SPINDLE1_ENABLE_PORT },
|
||||
#endif
|
||||
#ifdef SPINDLE1_PWM_PIN
|
||||
#ifndef SPINDLE1_PWM_PORT
|
||||
#define SPINDLE1_PWM_PORT NULL
|
||||
#define SPINDLE1_PWM_PORT 0
|
||||
#endif
|
||||
{ .function = Output_Spindle1PWM, .aux_port = 0xFF, .pin = SPINDLE1_PWM_PIN, .port = (void *)SPINDLE1_PWM_PORT },
|
||||
#endif
|
||||
#ifdef SPINDLE1_DIRECTION_PIN
|
||||
#ifndef SPINDLE1_DIRECTION_PORT
|
||||
#define SPINDLE1_DIRECTION_PORT NULL
|
||||
#define SPINDLE1_DIRECTION_PORT 0
|
||||
#endif
|
||||
{ .function = Output_Spindle1Dir, .aux_port = 0xFF, .pin = SPINDLE1_DIRECTION_PIN, .port = (void *)SPINDLE1_DIRECTION_PORT },
|
||||
#endif
|
||||
@@ -453,13 +472,13 @@ static aux_ctrl_out_t aux_ctrl_out[] = {
|
||||
#if AUX_CONTROLS & AUX_CONTROL_COOLANT
|
||||
#ifdef COOLANT_FLOOD_PIN
|
||||
#ifndef COOLANT_FLOOD_PORT
|
||||
#define COOLANT_FLOOD_PORT NULL
|
||||
#define COOLANT_FLOOD_PORT 0
|
||||
#endif
|
||||
{ .function = Output_CoolantFlood, .aux_port = 0xFF, .pin = COOLANT_FLOOD_PIN, .port = (void *)COOLANT_FLOOD_PORT },
|
||||
#endif
|
||||
#ifdef COOLANT_MIST_PIN
|
||||
#ifndef COOLANT_MIST_PORT
|
||||
#define COOLANT_MIST_PORT NULL
|
||||
#define COOLANT_MIST_PORT 0
|
||||
#endif
|
||||
{ .function = Output_CoolantMist, .aux_port = 0xFF, .pin = COOLANT_MIST_PIN, .port = (void *)COOLANT_MIST_PORT },
|
||||
#endif
|
||||
@@ -467,13 +486,13 @@ static aux_ctrl_out_t aux_ctrl_out[] = {
|
||||
|
||||
#ifdef COPROC_RESET_PIN
|
||||
#ifndef COPROC_RESET_PORT
|
||||
#define COPROC_RESET_PORT NULL
|
||||
#define COPROC_RESET_PORT 0
|
||||
#endif
|
||||
{ .function = Output_CoProc_Reset, .aux_port = 0xFF, .pin = COPROC_RESET_PIN, .port = (void *)COPROC_RESET_PORT },
|
||||
#endif
|
||||
#ifdef COPROC_BOOT0_PIN
|
||||
#ifndef COPROC_BOOT0_PORT
|
||||
#define COPROC_BOOT0_PORT NULL
|
||||
#define COPROC_BOOT0_PORT 0
|
||||
#endif
|
||||
{ .function = Output_CoProc_Boot0, .aux_port = 0xFF, .pin = COPROC_BOOT0_PIN, .port = (void *)COPROC_BOOT0_PORT },
|
||||
#endif
|
||||
@@ -501,10 +520,13 @@ typedef bool (*aux_claim_explicit_out_ptr)(aux_ctrl_out_t *aux_ctrl);
|
||||
|
||||
static bool aux_ctrl_claim_out_port (xbar_t *properties, uint8_t port, void *data)
|
||||
{
|
||||
if(ioport_claim(Port_Digital, Port_Output, &port, xbar_fn_to_pinname(((aux_ctrl_t *)data)->function)))
|
||||
((aux_ctrl_t *)data)->aux_port = port;
|
||||
if(((aux_ctrl_out_t *)data)->port == (void *)EXPANDER_PORT) {
|
||||
if(((aux_ctrl_out_t *)data)->pin == properties->pin && properties->set_value)
|
||||
((aux_ctrl_out_t *)data)->aux_port = port;
|
||||
} else if(ioport_claim(Port_Digital, Port_Output, &port, xbar_fn_to_pinname(((aux_ctrl_out_t *)data)->function)))
|
||||
((aux_ctrl_out_t *)data)->aux_port = port;
|
||||
|
||||
return ((aux_ctrl_t *)data)->aux_port != 0xFF;
|
||||
return ((aux_ctrl_out_t *)data)->aux_port != 0xFF;
|
||||
}
|
||||
|
||||
static inline void aux_ctrl_claim_out_ports (aux_claim_explicit_out_ptr aux_claim_explicit, ioports_enumerate_callback_ptr aux_claim)
|
||||
@@ -515,9 +537,20 @@ static inline void aux_ctrl_claim_out_ports (aux_claim_explicit_out_ptr aux_clai
|
||||
aux_claim = aux_ctrl_claim_out_port;
|
||||
|
||||
for(idx = 0; idx < sizeof(aux_ctrl_out) / sizeof(aux_ctrl_out_t); idx++) {
|
||||
if(aux_ctrl_out[idx].pin == 0xFF)
|
||||
ioports_enumerate(Port_Digital, Port_Output, (pin_cap_t){ .claimable = On }, aux_claim, (void *)&aux_ctrl_out[idx]);
|
||||
else if(aux_ctrl_out[idx].aux_port != 0xFF)
|
||||
if(aux_ctrl_out[idx].port == (void *)EXPANDER_PORT) {
|
||||
if(ioports_enumerate(Port_Digital, Port_Output, (pin_cap_t){ .external = On, .claimable = On }, aux_claim, &aux_ctrl_out[idx])) {
|
||||
if(ioport_claim(Port_Digital, Port_Output, &aux_ctrl_out[idx].aux_port, ""/*xbar_fn_to_pinname(aux_ctrl_out[idx].function)*/)) {
|
||||
aux_ctrl_out[idx].output = hal.port.get_pin_info(Port_Digital, Port_Output, aux_ctrl_out[idx].aux_port);
|
||||
if(((xbar_t *)aux_ctrl_out[idx].output)->set_function)
|
||||
((xbar_t *)aux_ctrl_out[idx].output)->set_function((xbar_t *)aux_ctrl_out[idx].output, aux_ctrl_out[idx].function);
|
||||
// TODO: else set description?
|
||||
aux_claim_explicit(&aux_ctrl_out[idx]);
|
||||
}
|
||||
}
|
||||
} else if(aux_ctrl_out[idx].pin == 0xFF) {
|
||||
if(ioports_enumerate(Port_Digital, Port_Output, (pin_cap_t){ .claimable = On }, aux_claim, &aux_ctrl_out[idx]))
|
||||
aux_claim_explicit(&aux_ctrl_out[idx]);
|
||||
} else if(aux_ctrl_out[idx].aux_port != 0xFF)
|
||||
aux_claim_explicit(&aux_ctrl_out[idx]);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user