Skip to content

Commit 0c47a68

Browse files
committedNov 17, 2021
Enhanced ioports API, fix for issue grblHAL#87 ++
1 parent f306bfa commit 0c47a68

19 files changed

+374
-108
lines changed
 

‎CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ target_sources(grbl INTERFACE
2626
${CMAKE_CURRENT_LIST_DIR}/ngc_params.c
2727
${CMAKE_CURRENT_LIST_DIR}/ngc_expr.c
2828
${CMAKE_CURRENT_LIST_DIR}/regex.c
29+
${CMAKE_CURRENT_LIST_DIR}/ioports.c
2930
)
3031

3132
target_include_directories(grbl INTERFACE ${CMAKE_CURRENT_LIST_DIR})

‎README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ It has been written to complement grblHAL and has features such as proper keyboa
1111

1212
---
1313

14-
Latest build date is 20211109, see the [changelog](changelog.md) for details.
14+
Latest build date is 20211117, see the [changelog](changelog.md) for details.
1515
__NOTE:__ Drivers built with more than three axes configured \(`N_AXIS` > `3`\) will force a settings reset when upgraded. Backup and restore of settings is recommended for these.
1616

1717
---
@@ -80,4 +80,4 @@ List of Supported G-Codes:
8080
Some [plugins](https://github.com/grblHAL/plugins) implements additional M-codes.
8181

8282
---
83-
2021-10-24
83+
2021-11-17

‎changelog.md

+25-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,29 @@
11
## grblHAL changelog
22

3+
Build 20211117:
4+
5+
Core:
6+
7+
* Enhanced [ioports API](http://svn.io-engineering.com/grblHAL/html/ioports_8h.html) with new calls for claiming ports and swapping pin to port mappings.
8+
* Fixed bug #87 where executing G28/G30 with explicit motion when a motion mode was not active \(following a G80\) raised error 31.
9+
* Replaced string symbol `GRBL_VERSION_BUILD` with numeric symbol `GRBL_BUILD`.
10+
The new symbol can be used by plugin code to check for functionality.
11+
12+
Plugins:
13+
14+
* Updated Bluetooth plugin for enhanced ioports API, bug fix.
15+
* Updated Spindle plugin for dual spindle support, merged PR#4.
16+
* Updated some to use the new `GRBL_BUILD` symbol.
17+
18+
Drivers:
19+
20+
* Updated many for define symbol changes (harmonization) and enhanced ioports API.
21+
* iMRXT1062 \(Teensy 4\): Fixed bugs, one was a typo and one slowed down max USB streaming rate.
22+
* RP2040 \(Pi Pico\): Added support for SD card and ioports API for aux output pins on Pico CNC board.
23+
* STM32F3xx: Fixed typo and some compiler warnings.
24+
25+
---
26+
327
Build 20211108:
428

529
Core:
@@ -15,7 +39,7 @@ Plugins:
1539
* Made Modbus plugin configuration symbols settable from compiler command line, added pin description to claimed UART pins.
1640

1741
Drivers:
18-
* Updated most to provide peripheral pin info to `$pins` report.
42+
* Updated to provide peripheral pin info to `$pins` report.
1943
* Some bug fixes.
2044

2145
---

‎crossbar.h

+8-4
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,7 @@ typedef enum {
281281
IRQ_Mode_Rising = 0b00001, //!< 0b00001 (0x01)
282282
IRQ_Mode_Falling = 0b00010, //!< 0b00010 (0x02)
283283
IRQ_Mode_Change = 0b00100, //!< 0b00100 (0x04)
284+
IRQ_Mode_Edges = 0b00111, //!< 0b00111 (0x07) - only used to report port capability.
284285
IRQ_Mode_High = 0b01000, //!< 0b01000 (0x08)
285286
IRQ_Mode_Low = 0b10000, //!< 0b10000 (0x10)
286287
IRQ_Mode_All = 0b11111 //!< 0b11111 (0x1F) - only used to report port capability.
@@ -298,10 +299,12 @@ typedef struct driver_irq_handler {
298299
struct driver_irq_handler *next;
299300
} driver_irq_handler_t;
300301

302+
//! Pin pullup and pulldown modes, may be or'ed when reporting pin capability.
301303
typedef enum {
302-
PullMode_None = 0b00,
303-
PullMode_Up = 0b01,
304-
PullMode_Down = 0b10
304+
PullMode_None = 0b00, //!< 0b00 (0x00)
305+
PullMode_Up = 0b01, //!< 0b01 (0x01)
306+
PullMode_Down = 0b10, //!< 0b10 (0x02)
307+
PullMode_UpDown = 0b11 //!< 0b11 (0x03) - only used to report port capability.
305308
} pull_mode_t;
306309

307310
#define PINMODE_NONE (0)
@@ -324,7 +327,8 @@ typedef union {
324327
pwm :1,
325328
analog :1,
326329
peripheral :1,
327-
reserved :2,
330+
claimed :1,
331+
remapped :1,
328332
can_remap :1;
329333
};
330334
} pin_mode_t;

‎driver_opts.h

+14-3
Original file line numberDiff line numberDiff line change
@@ -125,16 +125,27 @@
125125
#ifndef PPI_ENABLE
126126
#define PPI_ENABLE 0
127127
#endif
128-
#ifndef SPINDLE_HUANYANG
129-
#define SPINDLE_HUANYANG 0
128+
129+
#ifndef HUANYANG_ENABLE
130+
#define HUANYANG_ENABLE 0
131+
#else
132+
#ifndef VFD_SPINDLE
133+
#define VFD_SPINDLE 1
130134
#endif
135+
#endif
136+
137+
#ifndef VFD_SPINDLE
138+
#define VFD_SPINDLE 0
139+
#endif
140+
131141
#ifndef MODBUS_ENABLE
132-
#if SPINDLE_HUANYANG
142+
#if HUANYANG_ENABLE
133143
#define MODBUS_ENABLE 1
134144
#else
135145
#define MODBUS_ENABLE 0
136146
#endif
137147
#endif
148+
138149
#ifndef QEI_ENABLE
139150
#define QEI_ENABLE 0
140151
#endif

‎gcode.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -1771,7 +1771,7 @@ status_code_t gc_execute_block(char *block)
17711771
FAIL(Status_GcodeUnsupportedCoordSys); // [Greater than N sys]
17721772
// Determine coordinate system to change and try to load from non-volatile storage.
17731773
gc_block.values.coord_data.id = p_value == 0
1774-
? gc_block.modal.coord_system.id // Index P0 as the active coordinate system
1774+
? gc_block.modal.coord_system.id // Index P0 as the active coordinate system
17751775
: (coord_system_id_t)(p_value - 1); // else adjust index to NVS coordinate data indexing.
17761776

17771777
if (!settings_read_coord_data(gc_block.values.coord_data.id, &gc_block.values.coord_data.xyz))
@@ -1924,7 +1924,7 @@ status_code_t gc_execute_block(char *block)
19241924

19251925
// [G80 Errors]: Axis word are programmed while G80 is active.
19261926
// NOTE: Even non-modal commands or TLO that use axis words will throw this strict error.
1927-
if (axis_words.mask) // [No axis words allowed]
1927+
if (axis_words.mask && axis_command != AxisCommand_NonModal) // [No axis words allowed]
19281928
FAIL(Status_GcodeAxisWordsExist);
19291929

19301930
gc_block.modal.retract_mode = CCRetractMode_Previous;

‎grbl.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
#else
3535
#define GRBL_VERSION "1.1f"
3636
#endif
37-
#define GRBL_VERSION_BUILD "20211107"
37+
#define GRBL_BUILD 20211117
3838

3939
// The following symbols are set here if not already set by the compiler or in config.h
4040
// Do NOT change here!

‎hal.h

+1-84
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
#include "stepper.h"
3636
#include "nvs.h"
3737
#include "probe.h"
38+
#include "ioports.h"
3839
#include "plugins.h"
3940

4041
#define HAL_VERSION 8
@@ -86,90 +87,6 @@ __NOTE:__ required if the networking plugin is to be supported.
8687
*/
8788
typedef bool (*stream_select_ptr)(const io_stream_t *stream);
8889

89-
90-
/*************
91-
* Aux I/O *
92-
*************/
93-
94-
typedef enum {
95-
Port_Analog = 0,
96-
Port_Digital = 1
97-
} io_port_type_t;
98-
99-
typedef enum {
100-
Port_Input = 0,
101-
Port_Output = 1
102-
} io_port_direction_t;
103-
104-
/*! \brief Pointer to function for setting a digital output.
105-
\param port port number
106-
\param on true to set ouput high, false to set it low
107-
*/
108-
typedef void (*digital_out_ptr)(uint8_t port, bool on);
109-
110-
/*! \brief Pointer to function for setting an analog output.
111-
\param port port number.
112-
\param value
113-
\returns true if successful, false otherwise.
114-
*/
115-
typedef bool (*analog_out_ptr)(uint8_t port, float value);
116-
117-
/*! \brief Pointer to function for reading a digital or analog input.
118-
119-
__NOTE:__ The latest value read is stored in \ref #sys \ref #sys#var5399.
120-
121-
\param digital true if port is digital, false if analog.
122-
\param port port number.
123-
\param wait_mode a #wait_mode_t enum value.
124-
\param timeout in seconds, ignored if wait_mode is #WaitMode_Immediate (0).
125-
\returns read value if successful, -1 otherwise.
126-
*/
127-
typedef int32_t (*wait_on_input_ptr)(bool digital, uint8_t port, wait_mode_t wait_mode, float timeout);
128-
129-
/*! \brief Pointer to function for setting pin description for a digital or analog port.
130-
\param digital true if port is digital, false if analog.
131-
\param output true if port is an output, false if an input.
132-
\param port port number.
133-
\param s pointer to null terminated description string.
134-
*/
135-
typedef void (*set_pin_description_ptr)(bool digital, bool output, uint8_t port, const char *s);
136-
137-
/*! \brief Pointer to function for getting information about a digital or analog port.
138-
\param digital true if port is digital, false if analog.
139-
\param output true if port is an output, false if an input.
140-
\param port port number.
141-
\returns pointer to port information in a xbar_t struct if successful, NULL if not.
142-
*/
143-
typedef xbar_t *(*get_pin_info_ptr)(bool digital, bool output, uint8_t port);
144-
145-
/*! \brief Pointer to callback function for input port interrupt events.
146-
\param port port number.
147-
\param state true if port level is high, false if it is low.
148-
*/
149-
typedef void (*ioport_interrupt_callback_ptr)(uint8_t port, bool state);
150-
151-
/*! \brief Pointer to function for registering or deregistering an interrupt handler for a digital input port.
152-
\param port port number.
153-
\param irq_mode a \a #pin_irq_mode_t enum value.
154-
\param interrupt_callback pointer to the callback function to register or NULL to deregister the current callback.
155-
\returns true if successful, false otherwise.
156-
*/
157-
typedef bool (*ioport_register_interrupt_handler_ptr)(uint8_t port, pin_irq_mode_t irq_mode, ioport_interrupt_callback_ptr interrupt_callback);
158-
159-
//! Properties and handlers for auxillary digital and analog I/O.
160-
typedef struct {
161-
uint8_t num_digital_in; //!< Number of digital inputs available.
162-
uint8_t num_digital_out; //!< Number of digital outputs available.
163-
uint8_t num_analog_in; //!< Number of analog inputs available.
164-
uint8_t num_analog_out; //!< Number of analog outputs available.
165-
digital_out_ptr digital_out; //!< Optional handler for setting a digital output.
166-
analog_out_ptr analog_out; //!< Optional handler for setting an analog output.
167-
wait_on_input_ptr wait_on_input; //!< Optional handler for reading a digital or analog input.
168-
set_pin_description_ptr set_pin_description; //!< Optional handler for setting a description of an auxillary pin.
169-
get_pin_info_ptr get_pin_info; //!< Optional handler for getting information about an auxillary pin.
170-
ioport_register_interrupt_handler_ptr register_interrupt_handler;
171-
} io_port_t;
172-
17390
/*! \brief Pointer to function for registering information about a peripheral pin.
17491
\param pin as periph_pin_t struct containing pin information.
17592
*/

‎ioports.c

+121
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
/*
2+
ioports.c - some wrapper functions for the ioports HAL API
3+
4+
Part of grblHAL
5+
6+
Copyright (c) 2021 Terje Io
7+
8+
Grbl is free software: you can redistribute it and/or modify
9+
it under the terms of the GNU General Public License as published by
10+
the Free Software Foundation, either version 3 of the License, or
11+
(at your option) any later version.
12+
13+
Grbl is distributed in the hope that it will be useful,
14+
but WITHOUT ANY WARRANTY; without even the implied warranty of
15+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16+
GNU General Public License for more details.
17+
18+
You should have received a copy of the GNU General Public License
19+
along with Grbl. If not, see <http://www.gnu.org/licenses/>.
20+
*/
21+
22+
/**
23+
* @file
24+
*
25+
* Some wrapper functions for the #io_port_t API.
26+
* They perform the neccesary checks for both availablity of ports
27+
* and advanced functionality simplifying plugin code that uses them.
28+
*/
29+
30+
#include "hal.h"
31+
32+
static int16_t digital_in = -1, digital_out = -1, analog_in = -1, analog_out = -1;
33+
34+
static uint8_t ioports_count (io_port_type_t type, io_port_direction_t dir)
35+
{
36+
xbar_t *port;
37+
uint8_t n_ports = 0;
38+
39+
// determine how many ports, including claimed ports, that are available
40+
do {
41+
if((port = hal.port.get_pin_info(type, type, n_ports)))
42+
n_ports++;
43+
} while(port != NULL);
44+
45+
return n_ports;
46+
}
47+
48+
/*! \brief Get number of digital or analog ports available.
49+
\param type as an \a #io_port_type_t enum value.
50+
\param dir as an \a #io_port_direction_t enum value.
51+
\returns number of ports available including claimed ports if the API implementation supports that.
52+
*/
53+
uint8_t ioports_available (io_port_type_t type, io_port_direction_t dir)
54+
{
55+
uint8_t ports = 0;
56+
57+
if(hal.port.get_pin_info) {
58+
59+
if(type == Port_Digital) {
60+
if(dir == Port_Input)
61+
ports = digital_in == -1 ? (digital_in = ioports_count(type, dir)) : (uint8_t)digital_in;
62+
else
63+
ports = digital_out == -1 ? (digital_out = ioports_count(type, dir)) : (uint8_t)digital_out;
64+
} else {
65+
if(dir == Port_Input)
66+
ports = analog_in == -1 ? (analog_in = ioports_count(type, dir)) : (uint8_t)analog_in;
67+
else
68+
ports = analog_out == -1 ? (analog_out = ioports_count(type, dir)) : (uint8_t)analog_out;
69+
}
70+
} else {
71+
if(type == Port_Digital)
72+
ports = dir == Port_Input ? hal.port.num_digital_in : hal.port.num_digital_out;
73+
else
74+
ports = dir == Port_Input ? hal.port.num_analog_in : hal.port.num_analog_out;
75+
}
76+
77+
return ports;
78+
}
79+
80+
/*! \brief Claim a digital or analog port for exclusive use.
81+
\param type as an \a #io_port_type_t enum value.
82+
\param dir as an \a #io_port_direction_t enum value.
83+
\param port pointer to a \a uint8_t holding the ports aux number, returns the actual port number to use if successful.
84+
\param description pointer to a \a char constant for the pin description.
85+
\returns true if successful, false if not.
86+
*/
87+
bool ioport_claim (io_port_type_t type, io_port_direction_t dir, uint8_t *port, const char *description)
88+
{
89+
bool ok = false;
90+
uint8_t n_ports = ioports_available(type, dir);
91+
92+
if(hal.port.claim != 0) {
93+
94+
xbar_t *portinfo = NULL;
95+
96+
if(n_ports > 0) do {
97+
n_ports--;
98+
portinfo = hal.port.get_pin_info(type, dir, n_ports);
99+
if((ok = portinfo && !portinfo->mode.claimed && (portinfo->function - Output_Aux0) == *port)) {
100+
hal.port.claim(type, dir, port, description);
101+
break;
102+
}
103+
} while(n_ports && !ok);
104+
105+
} else if((ok = n_ports > 0)) {
106+
if(type == Port_Digital)
107+
*port = dir == Port_Input ? --hal.port.num_digital_in : --hal.port.num_digital_out;
108+
else
109+
*port = dir == Port_Input ? --hal.port.num_analog_in : --hal.port.num_analog_out;
110+
}
111+
112+
return ok;
113+
}
114+
115+
/*! \brief Check if ports can be claimed by aux number or not.
116+
\returns true if ports can be claimed by aux number, false if claimed ports are allocated by the API.
117+
*/
118+
bool ioport_can_claim_explicit (void)
119+
{
120+
return !(hal.port.claim == NULL || hal.port.get_pin_info == NULL);
121+
}

0 commit comments

Comments
 (0)
Please sign in to comment.