Added core support for new MPG mode that claims one serial stream and uses the 0x8B real-time command character for switching mode.

Moved RGB API definitions to separate file and added some utilities for drivers and plugins. Fixed minor bug.
stream_open_instance(), signature change - added optional description string.
This commit is contained in:
Terje Io
2024-02-05 23:39:27 +01:00
parent 068e6d37b1
commit e5d088eda7
11 changed files with 281 additions and 58 deletions

View File

@@ -13,7 +13,7 @@ It has been written to complement grblHAL and has features such as proper keyboa
---
Latest build date is 20240127, see the [changelog](changelog.md) for details.
Latest build date is 20240205, 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.
---
@@ -89,4 +89,4 @@ G/M-codes not supported by [legacy Grbl](https://github.com/gnea/grbl/wiki) are
Some [plugins](https://github.com/grblHAL/plugins) implements additional M-codes.
---
20240127
20240205

View File

@@ -1,5 +1,29 @@
## grblHAL changelog
<a name="20240205"/>20240205
Core:
* Added core support for new MPG mode that claims one serial stream and uses the `0x8B` real-time command character for switching mode. Does not require the keypad plugin.
* Moved RGB API definitions to separate file and added some utilities for drivers and plugins. Fixed minor bug.
* For developers: `stream_open_instance()`, signature change - added optional description string.
Drivers:
* Many: Updated to support new MPG mode. Updated for core signature change.
* ESP32, RP2040, STM32F4xx: enhanced Neopixel support. __Note:__ Not yet used by any boards.
* STM32F7xx: Added missing MPG mode handlers.
Plugins:
* Bluetooth: updated for core signature change.
---
<a name="20240202"/>20240202
Core:

View File

@@ -108,6 +108,8 @@
#if MPG_ENABLE == 1 && KEYPAD_ENABLE == 2
#define MPG_MODE 2
#elif MPG_ENABLE == 2
#define MPG_MODE 3
#elif MPG_ENABLE
#define MPG_MODE 1
#else

2
grbl.h
View File

@@ -42,7 +42,7 @@
#else
#define GRBL_VERSION "1.1f"
#endif
#define GRBL_BUILD 20240202
#define GRBL_BUILD 20240204
#define GRBL_URL "https://github.com/grblHAL"

50
hal.h
View File

@@ -38,6 +38,7 @@
#include "nvs.h"
#include "probe.h"
#include "ioports.h"
#include "rgb.h"
#include "plugins.h"
#define HAL_VERSION 10
@@ -506,55 +507,6 @@ typedef struct {
rtc_set_datetime_ptr set_datetime; //!< Optional handler setting the current datetime.
} rtc_ptrs_t;
/*******************
* RGB (LED) API *
*******************/
typedef union {
uint8_t value;
uint8_t mask;
struct {
uint8_t B :1,
G :1,
R :1,
W :1,
unused :4;
};
} rgb_color_mask_t;
typedef union {
uint32_t value;
struct {
uint8_t B; //!< Blue
uint8_t G; //!< Green
uint8_t R; //!< Red
uint8_t W; //!< White
};
} rgb_color_t;
/*! \brief Pointer to function for setting RGB (LED) output.
\param color a \a rgb_color_t union.
*/
typedef void (*rgb_set_color_ptr)(uint16_t device, rgb_color_t color);
/*! \brief Pointer to function for setting RGB (LED) output, with mask for which LEDs to change.
\param color a \a rgb_color_t union.
\param mask a \a rgb_color_mask_t union.
*/
typedef void (*rgb_set_color_masked_ptr)(uint16_t device, rgb_color_t color, rgb_color_mask_t mask);
/*! \brief Pointer to function for outputting RGB (LED) data to Neopixel strip.
*/
typedef void (*rgb_write_ptr)(void);
typedef struct {
rgb_set_color_ptr out; //!< Optional handler for setting device (LED) color.
rgb_set_color_masked_ptr out_masked; //!< Optional handler for setting device (LED) color, with mask for which LEDs to change.
rgb_write_ptr write; //!< Optional handler for outputting data to Neopixel strip.
rgb_color_t cap; //!< Driver capability, color value: 0 - not available, 1 - on off, > 1 - intensity range 0 - n.
uint8_t num_devices; //!< Number of devices (LEDs) available.
} rgb_ptr_t;
/**/
/*! \brief Pointer to function for performing a pallet shuttle.

View File

@@ -931,7 +931,7 @@ ISR_CODE bool ISR_FUNC(protocol_enqueue_realtime_command)(char c)
case CMD_MPG_MODE_TOGGLE: // Switch off MPG mode
if(hal.stream.type == StreamType_MPG)
stream_mpg_enable(false);
protocol_enqueue_foreground_task(stream_mpg_set_mode, NULL);
break;
case CMD_AUTO_REPORTING_TOGGLE:

View File

@@ -2060,7 +2060,9 @@ status_code_t report_setting_group_details (bool by_id, char *prefix)
do {
for(idx = 0; idx < details->n_groups; idx++) {
if(!group_is_dup(all_groups, details->groups[idx].id))
if(group_is_dup(all_groups, details->groups[idx].id))
n_groups--;
else
*group++ = (setting_group_detail_t *)&details->groups[idx];
}
} while((details = details->next));

215
rgb.h Normal file
View File

@@ -0,0 +1,215 @@
/*
rgb.h - typedefs, API structure and helper functions for RGB lights and LED strips
Part of grblHAL
Copyright (c) 2024 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/>.
*/
typedef union {
uint8_t value;
uint8_t mask;
struct {
uint8_t B :1,
G :1,
R :1,
W :1,
unused :4;
};
} rgb_color_mask_t;
typedef union {
uint32_t value;
struct {
uint8_t B; //!< Blue
uint8_t G; //!< Green
uint8_t R; //!< Red
uint8_t W; //!< White
};
} rgb_color_t;
/*! \brief Pointer to function for setting RGB (LED) output.
\param color a \a rgb_color_t union.
*/
typedef void (*rgb_set_color_ptr)(uint16_t device, rgb_color_t color);
/*! \brief Pointer to function for setting RGB (LED) output, with mask for which LEDs to change.
\param color a \a rgb_color_t union.
\param mask a \a rgb_color_mask_t union.
*/
typedef void (*rgb_set_color_masked_ptr)(uint16_t device, rgb_color_t color, rgb_color_mask_t mask);
/*! \brief Pointer to function for setting RGB (LED) intensity.
\param intensity in the range 0 - 255.
\returns previuous intensity.
*/
typedef uint8_t (*rgb_set_intensity_ptr)(uint8_t intensity);
/*! \brief Pointer to function for outputting RGB (LED) data to Neopixel strip.
*/
typedef void (*rgb_write_ptr)(void);
typedef struct {
rgb_set_color_ptr out; //!< Optional handler for setting device (LED) color.
rgb_set_color_masked_ptr out_masked; //!< Optional handler for setting device (LED) color, with mask for which LEDs to change.
rgb_write_ptr write; //!< Optional handler for outputting data to Neopixel strip.
rgb_set_intensity_ptr set_intensity; //!< Optional handler for setting intensity, range 0 - 255.
rgb_color_t cap; //!< Driver capability, color value: 0 - not available, 1 - on off, > 1 - intensity range 0 - n.
uint16_t num_devices; //!< Number of devices (LEDs) available.
} rgb_ptr_t;
// helper functions
typedef struct {
uint16_t num_leds;
uint16_t num_bytes;
uint8_t *leds;
uint8_t intensity;
} neopixel_cfg_t;
// RGB to/from 3 bytes per pixel packed format
static inline rgb_color_t rgb_set_intensity (rgb_color_t color, uint8_t intensity)
{
color.R = (uint8_t)(((color.R + 1) * intensity) >> 8);
color.G = (uint8_t)(((color.G + 1) * intensity) >> 8);
color.B = (uint8_t)(((color.B + 1) * intensity) >> 8);
return color;
}
static inline void rgb_3bpp_pack (uint8_t *led, rgb_color_t color, rgb_color_mask_t mask, uint8_t intensity)
{
uint32_t R = 0, G = 0, B = 0;
uint8_t bitmask = 0b10000000;
color = rgb_set_intensity(color, intensity);
do {
R <<= 3;
R |= color.R & bitmask ? 0b110 : 0b100;
G <<= 3;
G |= color.G & bitmask ? 0b110 : 0b100;
B <<= 3;
B |= color.B & bitmask ? 0b110 : 0b100;
} while(bitmask >>= 1);
if(mask.G) {
*led++ = (uint8_t)(G >> 16);
*led++ = (uint8_t)(G >> 8);
*led++ = (uint8_t)G;
} else
led += 3;
if(mask.R) {
*led++ = (uint8_t)(R >> 16);
*led++ = (uint8_t)(R >> 8);
*led++ = (uint8_t)R;
} else
led += 3;
if(mask.B) {
*led++ = (uint8_t)(B >> 16);
*led++ = (uint8_t)(B >> 8);
*led = (uint8_t)B;
}
}
static inline rgb_color_t rgb_reset_intensity (rgb_color_t color, uint8_t intensity)
{
color.R = (uint8_t)((color.R << 8) / (intensity + 1));
color.G = (uint8_t)((color.G << 8) / (intensity + 1));
color.B = (uint8_t)((color.B << 8) / (intensity + 1));
return color;
}
static inline rgb_color_t rgb_3bpp_unpack (uint8_t *led, uint8_t intensity)
{
rgb_color_t color = {0};
if(intensity) {
uint32_t R = 0, G = 0, B = 0;
uint8_t bitmask = 0b00000001;
G = *led++ << 16;
G |= *led++ << 8;
G |= *led++;
R = *led++ << 16;
R |= *led++ << 8;
R |= *led++;
B = *led++ << 16;
B |= *led++ << 8;
B |= *led;
do {
if((R & 0b110) == 0b110)
color.R |= bitmask;
R >>= 3;
if((G & 0b110) == 0b110)
color.G |= bitmask;
G >>= 3;
if((B & 0b110) == 0b110)
color.B |= bitmask;
B >>= 3;
} while(bitmask <<= 1);
color = rgb_reset_intensity(color, intensity);
}
return color;
}
static inline void rgb_1bpp_assign (uint8_t *led, rgb_color_t color, rgb_color_mask_t mask)
{
if(mask.G)
*led++ = color.G;
else
led++;
if(mask.R)
*led++ = color.R;
else
led++;
if(mask.B)
*led = color.B;
}
static inline void rgb_1bpp_pack (uint8_t *led, rgb_color_t color, rgb_color_mask_t mask, uint8_t intensity)
{
color = rgb_set_intensity(color, intensity);
rgb_1bpp_assign(led, color, mask);
}
static inline rgb_color_t rgb_1bpp_unpack (uint8_t *led, uint8_t intensity)
{
rgb_color_t color = {0};
if(intensity) {
color.G = *led++;
color.R = *led++;
color.B = *led;
color = rgb_reset_intensity(color, intensity);
}
return color;
}
//

View File

@@ -365,7 +365,9 @@ typedef enum {
Setting_MQTTBrokerPassword = 533,
Setting_NGCDebugOut = 534,
Setting_NetworkMAC = 535,
Setting_NetworkMAC = 535,
Setting_RGB_StripLengt0 = 536,
Setting_RGB_StripLengt1 = 537,
Setting_Panel_SpindleSpeed = 540, // NOTE: Reserving settings values 540 to 579 for panel settings.
Setting_Panel_ModbusAddress = 541,
@@ -717,15 +719,19 @@ typedef struct {
control_signals_t control_invert;
control_signals_t control_disable_pullup;
coolant_state_t coolant_invert;
uint8_t hole_0;
uint16_t hole_1;
spindle_settings_t spindle;
stepper_settings_t steppers;
reportmask_t status_report; // Mask to indicate desired report data.
settingflags_t flags; // Contains default boolean settings
probeflags_t probe;
uint8_t rgb_strip0_length;
offset_lock_t offset_lock;
fs_options_t fs_options;
homing_settings_t homing;
limit_settings_t limits;
uint8_t rgb_strip1_length;
parking_settings_t parking;
safety_door_settings_t safety_door;
position_pid_t position; // Used for synchronized motion

View File

@@ -415,20 +415,38 @@ void stream_disconnect (const io_stream_t *stream)
stream_select(stream, false);
}
io_stream_t const *stream_open_instance (uint8_t instance, uint32_t baud_rate, stream_write_char_ptr rx_handler)
io_stream_t const *stream_open_instance (uint8_t instance, uint32_t baud_rate, stream_write_char_ptr rx_handler, const char *description)
{
connection.instance = instance;
connection.baud_rate = baud_rate;
connection.stream = NULL;
if(stream_enumerate_streams(_open_instance))
if(stream_enumerate_streams(_open_instance)) {
connection.stream->set_enqueue_rt_handler(rx_handler);
if(description)
stream_set_description(connection.stream, description);
}
return connection.stream;
}
// MPG stream
void stream_mpg_set_mode (void *data)
{
stream_mpg_enable(data != NULL);
}
ISR_CODE bool ISR_FUNC(stream_mpg_check_enable)(char c)
{
if(c == CMD_MPG_MODE_TOGGLE)
protocol_enqueue_foreground_task(stream_mpg_set_mode, (void *)1);
else
protocol_enqueue_realtime_command(c);
return true;
}
bool stream_mpg_register (const io_stream_t *stream, bool rx_only, stream_write_char_ptr write_char)
{
if(stream == NULL || stream->type != StreamType_Serial || stream->disable_rx == NULL)

View File

@@ -325,6 +325,10 @@ bool stream_mpg_register (const io_stream_t *stream, bool rx_only, stream_write_
*/
bool stream_mpg_enable (bool on);
void stream_mpg_set_mode (void *data);
bool stream_mpg_check_enable (char c);
bool stream_buffer_all (char c);
bool stream_tx_blocking (void);
@@ -347,7 +351,7 @@ io_stream_flags_t stream_get_flags (io_stream_t stream);
const io_stream_t *stream_null_init (uint32_t baud_rate);
io_stream_t const *stream_open_instance (uint8_t instance, uint32_t baud_rate, stream_write_char_ptr rx_handler);
io_stream_t const *stream_open_instance (uint8_t instance, uint32_t baud_rate, stream_write_char_ptr rx_handler, const char *description);
bool stream_set_description (const io_stream_t *stream, const char *description);