From e5d088eda75d6f32ae82a9bb0bc7d2dac21999b0 Mon Sep 17 00:00:00 2001 From: Terje Io Date: Mon, 5 Feb 2024 23:39:27 +0100 Subject: [PATCH] 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. --- README.md | 4 +- changelog.md | 24 ++++++ driver_opts.h | 2 + grbl.h | 2 +- hal.h | 50 +----------- protocol.c | 2 +- report.c | 4 +- rgb.h | 215 ++++++++++++++++++++++++++++++++++++++++++++++++++ settings.h | 8 +- stream.c | 22 +++++- stream.h | 6 +- 11 files changed, 281 insertions(+), 58 deletions(-) create mode 100644 rgb.h diff --git a/README.md b/README.md index bb6c01f..cdb71ec 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 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 diff --git a/changelog.md b/changelog.md index 58675ec..e577461 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,29 @@ ## grblHAL changelog +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. + +--- + 20240202 Core: diff --git a/driver_opts.h b/driver_opts.h index 296906b..8f1c559 100644 --- a/driver_opts.h +++ b/driver_opts.h @@ -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 diff --git a/grbl.h b/grbl.h index 03553f1..e377ae2 100644 --- a/grbl.h +++ b/grbl.h @@ -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" diff --git a/hal.h b/hal.h index 84cab04..5a866fc 100644 --- a/hal.h +++ b/hal.h @@ -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. diff --git a/protocol.c b/protocol.c index 84e4ae6..39c7fde 100644 --- a/protocol.c +++ b/protocol.c @@ -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: diff --git a/report.c b/report.c index 032c281..f45b059 100644 --- a/report.c +++ b/report.c @@ -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)); diff --git a/rgb.h b/rgb.h new file mode 100644 index 0000000..938986f --- /dev/null +++ b/rgb.h @@ -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 . +*/ + +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; +} + +// diff --git a/settings.h b/settings.h index 9f41b70..c2ce043 100644 --- a/settings.h +++ b/settings.h @@ -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 diff --git a/stream.c b/stream.c index bcf33d2..907d00e 100644 --- a/stream.c +++ b/stream.c @@ -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) diff --git a/stream.h b/stream.h index 4950035..36b791a 100644 --- a/stream.h +++ b/stream.h @@ -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);