grblHAL core  20250922
rgb.h
Go to the documentation of this file.
1 /*
2  rgb.h - typedefs, API structure and helper functions for RGB lights and LED strips
3 
4  Part of grblHAL
5 
6  Copyright (c) 2024-2025 Terje Io
7 
8  grblHAL 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  grblHAL 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 grblHAL. If not, see <http://www.gnu.org/licenses/>.
20 */
21 
22 typedef union {
23  uint8_t value;
24  uint8_t mask;
25  struct {
26  uint8_t B :1,
27  G :1,
28  R :1,
29  W :1,
30  unused :4;
31  };
33 
34 typedef union {
35  uint32_t value;
36  struct {
37  uint8_t B;
38  uint8_t G;
39  uint8_t R;
40  uint8_t W;
41  };
42 } rgb_color_t;
43 
44 typedef union {
45  uint8_t mask;
46  struct {
47  uint8_t is_blocking :1,
50  };
52 
56 typedef void (*rgb_set_color_ptr)(uint16_t device, rgb_color_t color);
57 
62 typedef void (*rgb_set_color_masked_ptr)(uint16_t device, rgb_color_t color, rgb_color_mask_t mask);
63 
68 typedef uint8_t (*rgb_set_intensity_ptr)(uint8_t intensity);
69 
72 typedef void (*rgb_write_ptr)(void);
73 
74 typedef struct {
81  uint16_t num_devices;
82 } rgb_ptr_t;
83 
84 // helper structure and functions, not used by the core
85 
86 typedef struct {
87  uint16_t num_leds;
88  uint16_t num_bytes;
89  uint8_t *leds;
90  uint8_t intensity;
92 
93 static inline bool rgb_is_neopixels (rgb_ptr_t *device)
94 {
95  return device->out != NULL && device->cap.R > 126 && device->cap.G > 126 && device->cap.B > 126;
96 }
97 
98 static inline bool rgb_is_onoff (rgb_ptr_t *device)
99 {
100  return device->out != NULL && device->cap.R == 1 && device->cap.G == 1 && device->cap.B == 1;
101 }
102 
103 static inline void rgb_clear (rgb_ptr_t *device)
104 {
105  if(device->set_intensity)
106  device->set_intensity(255);
107 
108  if(rgb_is_neopixels(device) && device->num_devices) {
109 
110  uint32_t idx;
111 
112  for(idx = 0; idx <= device->num_devices; idx++)
113  device->out(idx, (rgb_color_t){0});
114 
115  if(device->num_devices > 1 && device->write)
116  device->write();
117  }
118 }
119 
120 // Intensity conversions
121 
122 static inline rgb_color_t rgb_set_intensity (rgb_color_t color, uint8_t intensity)
123 {
124  color.R = (uint8_t)(((color.R + 1) * intensity) >> 8);
125  color.G = (uint8_t)(((color.G + 1) * intensity) >> 8);
126  color.B = (uint8_t)(((color.B + 1) * intensity) >> 8);
127 
128  return color;
129 }
130 
131 static inline rgb_color_t rgb_reset_intensity (rgb_color_t color, uint8_t intensity)
132 {
133  color.R = (uint8_t)((color.R << 8) / (intensity + 1));
134  color.G = (uint8_t)((color.G << 8) / (intensity + 1));
135  color.B = (uint8_t)((color.B << 8) / (intensity + 1));
136 
137  return color;
138 }
139 
140 // RGB to/from 3 bytes per pixel packed format
141 
142 static inline void rgb_3bpp_pack (uint8_t *led, rgb_color_t color, rgb_color_mask_t mask, uint8_t intensity)
143 {
144  uint32_t R = 0, G = 0, B = 0;
145  uint8_t bitmask = 0b10000000;
146 
147  color = rgb_set_intensity(color, intensity);
148 
149  do {
150  R <<= 3;
151  R |= color.R & bitmask ? 0b011 : 0b010;
152  G <<= 3;
153  G |= color.G & bitmask ? 0b011 : 0b010;
154  B <<= 3;
155  B |= color.B & bitmask ? 0b011 : 0b010;
156  } while(bitmask >>= 1);
157 
158  if(mask.G) {
159  *led++ = (uint8_t)(G >> 16);
160  *led++ = (uint8_t)(G >> 8);
161  *led++ = (uint8_t)G;
162  } else
163  led += 3;
164 
165  if(mask.R) {
166  *led++ = (uint8_t)(R >> 16);
167  *led++ = (uint8_t)(R >> 8);
168  *led++ = (uint8_t)R;
169  } else
170  led += 3;
171 
172  if(mask.B) {
173  *led++ = (uint8_t)(B >> 16);
174  *led++ = (uint8_t)(B >> 8);
175  *led = (uint8_t)B;
176  }
177 }
178 
179 static inline rgb_color_t rgb_3bpp_unpack (uint8_t *led, uint8_t intensity)
180 {
181  rgb_color_t color = {0};
182 
183  if(intensity) {
184 
185  uint32_t R = 0, G = 0, B = 0;
186  uint8_t bitmask = 0b00000001;
187 
188  G = *led++ << 16;
189  G |= *led++ << 8;
190  G |= *led++;
191  R = *led++ << 16;
192  R |= *led++ << 8;
193  R |= *led++;
194  B = *led++ << 16;
195  B |= *led++ << 8;
196  B |= *led;
197 
198  do {
199  if((R & 0b011) == 0b011)
200  color.R |= bitmask;
201  R >>= 3;
202  if((G & 0b011) == 0b011)
203  color.G |= bitmask;
204  G >>= 3;
205  if((B & 0b011) == 0b011)
206  color.B |= bitmask;
207  B >>= 3;
208  } while(bitmask <<= 1);
209 
210  color = rgb_reset_intensity(color, intensity);
211  }
212 
213  return color;
214 }
215 
216 // RGB to/from 1 byte per pixel packed format
217 
218 static inline void rgb_1bpp_assign (uint8_t *led, rgb_color_t color, rgb_color_mask_t mask)
219 {
220  if(mask.G)
221  *led++ = color.G;
222  else
223  led++;
224 
225  if(mask.R)
226  *led++ = color.R;
227  else
228  led++;
229 
230  if(mask.B)
231  *led = color.B;
232 }
233 
234 static inline void rgb_1bpp_pack (uint8_t *led, rgb_color_t color, rgb_color_mask_t mask, uint8_t intensity)
235 {
236  color = rgb_set_intensity(color, intensity);
237  rgb_1bpp_assign(led, color, mask);
238 }
239 
240 static inline rgb_color_t rgb_1bpp_unpack (uint8_t *led, uint8_t intensity)
241 {
242  rgb_color_t color = {0};
243 
244  if(intensity) {
245 
246  color.G = *led++;
247  color.R = *led++;
248  color.B = *led;
249 
250  color = rgb_reset_intensity(color, intensity);
251  }
252 
253  return color;
254 }
255 
256 //
uint8_t(* rgb_set_intensity_ptr)(uint8_t intensity)
Pointer to function for setting RGB (LED) intensity.
Definition: rgb.h:68
void(* rgb_write_ptr)(void)
Pointer to function for outputting RGB (LED) data to Neopixel strip.
Definition: rgb.h:72
void(* rgb_set_color_masked_ptr)(uint16_t device, rgb_color_t color, rgb_color_mask_t mask)
Pointer to function for setting RGB (LED) output, with mask for which LEDs to change.
Definition: rgb.h:62
void(* rgb_set_color_ptr)(uint16_t device, rgb_color_t color)
Pointer to function for setting RGB (LED) output.
Definition: rgb.h:56
Definition: rgb.h:86
uint8_t intensity
Definition: rgb.h:90
uint16_t num_bytes
Definition: rgb.h:88
uint8_t * leds
Definition: rgb.h:89
uint16_t num_leds
Definition: rgb.h:87
Definition: rgb.h:74
rgb_write_ptr write
Optional handler for outputting data to Neopixel strip.
Definition: rgb.h:77
rgb_set_intensity_ptr set_intensity
Optional handler for setting intensity, range 0 - 255.
Definition: rgb.h:78
rgb_set_color_ptr out
Optional handler for setting device (LED) color.
Definition: rgb.h:75
rgb_set_color_masked_ptr out_masked
Optional handler for setting device (LED) color, with mask for which LEDs to change.
Definition: rgb.h:76
rgb_properties_t flags
Driver property flags.
Definition: rgb.h:80
rgb_color_t cap
Driver capability, color value: 0 - not available, 1 - on off, > 1 - intensity range 0 - n.
Definition: rgb.h:79
uint16_t num_devices
Number of devices (LEDs) available.
Definition: rgb.h:81
Definition: rgb.h:22
uint8_t W
Definition: rgb.h:29
uint8_t value
Definition: rgb.h:23
uint8_t B
Definition: rgb.h:26
uint8_t mask
Definition: rgb.h:24
uint8_t G
Definition: rgb.h:27
uint8_t R
Definition: rgb.h:28
uint8_t unused
Definition: rgb.h:30
Definition: rgb.h:34
uint8_t W
White.
Definition: rgb.h:40
uint8_t B
Blue.
Definition: rgb.h:37
uint8_t G
Green.
Definition: rgb.h:38
uint8_t R
Red.
Definition: rgb.h:39
uint32_t value
Definition: rgb.h:35
Definition: rgb.h:44
uint8_t is_strip
Definition: rgb.h:48
uint8_t unassigned
Definition: rgb.h:49
uint8_t mask
Definition: rgb.h:45
uint8_t is_blocking
Definition: rgb.h:47