libNeon
Loading...
Searching...
No Matches
strip.hpp
Go to the documentation of this file.
1//
2// Created by spak on 5/28/21.
3//
4
5#ifndef NEO_STRIP_HPP
6#define NEO_STRIP_HPP
7
8#include <cmath>
9#include <limits>
10#include <neo/color.hpp>
11#include <neo/gamma.hpp>
12#include <neo/rmt.hpp>
13#include <vector>
14
15namespace neo {
16
17 template <class OutputIt>
18 OutputIt populate(OutputIt it, std::uint8_t b, rmt_item32_t zero, rmt_item32_t one);
19
20 template <class OutputIt, class T, class = std::enable_if_t<not std::is_polymorphic_v<T>>>
21 OutputIt populate(OutputIt it, T const &t, rmt_item32_t zero, rmt_item32_t one);
22
23 template <class Led>
24 class ref;
25
26 template <class Led>
27 class cref;
28
30 public:
31 [[nodiscard]] virtual esp_err_t update(std::vector<rgb> const &colors, rmt_channel_t channel, bool wait_tx_done) = 0;
32 [[nodiscard]] virtual esp_err_t update(rgb color, rmt_channel_t channel, bool wait_tx_done) = 0;
33 [[nodiscard]] virtual std::size_t size() const = 0;
34
35 virtual ~transmittable_rgb_strip() = default;
36 };
37
38 template <class Led>
39 class strip final : public transmittable_rgb_strip {
40 rmt_item32_t _zero;
41 rmt_item32_t _one;
42 float _gamma;
44 std::vector<Led> _pixels;
45 std::vector<rmt_item32_t> _rmt_buffer;
46
47 public:
48 static constexpr float default_gamma = 2.8f;
49 static constexpr float no_gamma = std::numeric_limits<float>::quiet_NaN();
50
51 static_assert(std::has_unique_object_representations_v<Led>, "The Led class will be transmitted directly");
52
53 explicit strip(std::pair<rmt_item32_t, rmt_item32_t> zero_one, std::size_t size = 0, float gamma = default_gamma);
54
55 strip(rmt_manager const &manager, controller chip, std::size_t size = 0, bool inverted = false, float gamma = default_gamma);
56
57 [[nodiscard]] esp_err_t update(std::vector<rgb> const &colors, rmt_channel_t channel, bool wait_tx_done) override;
58 [[nodiscard]] esp_err_t update(rgb color, rmt_channel_t channel, bool wait_tx_done) override;
59
60 [[nodiscard]] esp_err_t transmit(rmt_channel_t channel, bool wait_tx_done) const;
61
62 template <class Neopix, class CRTPIt>
63 class iterator_base;
64
65 class const_iterator;
66
67 class iterator;
68
69 [[nodiscard]] inline rmt_item32_t zero() const;
70
71 [[nodiscard]] inline rmt_item32_t one() const;
72
73 [[nodiscard]] inline std::size_t size() const override;
74
75 [[nodiscard]] inline bool empty() const;
76
77 [[nodiscard]] inline float gamma() const;
78
79 [[nodiscard]] inline gamma_table const *get_gamma_table() const;
80
81 inline void set_gamma(float gamma);
82
83 void clear();
84
85 inline void resize(std::size_t new_size);
86 void resize(std::size_t new_size, Led led);
87
88 [[nodiscard]] inline ref<Led> operator[](std::size_t i);
89
90 [[nodiscard]] inline cref<Led> operator[](std::size_t i) const;
91
92 [[nodiscard]] inline const_iterator begin() const;
93
94 [[nodiscard]] inline const_iterator cbegin() const;
95
96 [[nodiscard]] inline const_iterator end() const;
97
98 [[nodiscard]] inline const_iterator cend() const;
99
100 [[nodiscard]] inline iterator begin();
101
102 [[nodiscard]] inline iterator end();
103 };
104
105
106 template <class Led>
107 template <class Neopix, class CRTPIt>
108 class strip<Led>::iterator_base {
109 protected:
110 Neopix *_neopix = nullptr;
111 std::size_t _i = std::numeric_limits<std::size_t>::max();
112
113 public:
114 iterator_base() = default;
115
116 iterator_base(Neopix &neopix, std::size_t i) : _neopix{&neopix}, _i{i} {}
117
118 [[nodiscard]] inline decltype(auto) operator*() const;
119
120 inline CRTPIt &operator++();
121
122 inline const CRTPIt operator++(int);
123
124 inline CRTPIt &operator--();
125
126 inline const CRTPIt operator--(int);
127
128 [[nodiscard]] inline bool operator==(CRTPIt const &other) const;
129
130 [[nodiscard]] inline bool operator!=(CRTPIt const &other) const;
131
132 inline CRTPIt &operator+=(std::size_t n);
133
134 inline CRTPIt &operator-=(std::size_t n);
135
136 inline CRTPIt operator+(std::size_t n) const;
137
138 inline CRTPIt operator-(std::size_t n) const;
139 };
140
141
142 template <class Led>
143 class strip<Led>::const_iterator : public iterator_base<strip const, const_iterator> {
144 public:
145 using iterator_category = std::random_access_iterator_tag;
146 using value_type = decltype(std::declval<strip const &>()[0]);
147 using difference_type = void;
148 using pointer = void;
149 using reference = void;
150
151 using iterator_base<strip const, const_iterator>::iterator_base;
152 };
153
154
155 template <class Led>
156 class strip<Led>::iterator : public iterator_base<strip, iterator> {
157 protected:
158 using iterator_base<strip, iterator>::_neopix;
159 using iterator_base<strip, iterator>::_i;
160
161 public:
162 using iterator_category = std::random_access_iterator_tag;
163 using value_type = decltype(std::declval<strip &>()[0]);
164 using difference_type = void;
165 using pointer = void;
166 using reference = void;
167
168 using iterator_base<strip, iterator>::iterator_base;
169
170 inline operator const_iterator() const;
171 };
172
173 template <class Led>
174 class cref {
175 protected:
177 Led const &_cref;
178
179 public:
180 cref(strip<Led> const &neo, Led const &cref);
181
182 [[nodiscard]] inline explicit operator Led() const;
183
184 [[nodiscard]] rgb get_color() const;
185 };
186
187
188 template <class Led>
189 class ref : public cref<Led> {
190 std::vector<rmt_item32_t>::iterator _repr_it;
191 using cref<Led>::_strip;
192 using cref<Led>::_cref;
193
194 [[nodiscard]] inline Led &get_ref() { return const_cast<Led &>(_cref); }
195
196 public:
197 explicit ref(strip<Led> const &neo, Led &ref, std::vector<rmt_item32_t>::iterator repr_it);
198
199 using cref<Led>::operator Led;
200 using cref<Led>::get_color;
201
202 void set_color(rgb c);
203
204 ref &operator=(Led v);
205 inline ref &operator=(rgb c);
206 };
207
208}// namespace neo
209
210namespace neo {
211
212 template <class Led>
213 strip<Led>::strip(rmt_manager const &manager, controller chip, std::size_t size, bool inverted, float gamma)
214 : _zero{},
215 _one{},
216 _gamma{no_gamma},
217 _gamma_table{nullptr} {
218 auto [zero, one] = make_zero_one(manager, chip, inverted);
219 _zero = zero;
220 _one = one;
222 if (size > 0) {
223 resize(size);
224 }
225 }
226
227 template <class Led>
228 strip<Led>::strip(std::pair<rmt_item32_t, rmt_item32_t> zero_one, std::size_t size, float gamma)
229 : _zero{zero_one.first},
230 _one{zero_one.second},
231 _gamma{no_gamma},
232 _gamma_table{nullptr} {
234 if (size > 0) {
235 resize(size);
236 }
237 }
238
239
240 template <class Led>
241 float strip<Led>::gamma() const {
242 return _gamma;
243 }
244
245 template <class Led>
247 return _gamma_table;
248 }
249
250 template <class Led>
251 void strip<Led>::set_gamma(float gamma) {
252 _gamma = gamma;
253 _gamma_table = std::isnan(gamma) ? nullptr : &get_cached_gamma_table(gamma);
254 }
255
256 template <class Led>
257 std::size_t strip<Led>::size() const {
258 return _pixels.size();
259 }
260
261 template <class Led>
262 void strip<Led>::resize(std::size_t new_size) {
263 resize(new_size, Led{});
264 }
265
266 template <class Led>
267 void strip<Led>::resize(std::size_t new_size, Led led) {
268 const auto old_size = size();
269 _pixels.resize(new_size, led);
270 _rmt_buffer.resize(new_size * 8 * sizeof(Led), zero());
271 if (new_size > old_size) {
272 for (std::size_t i = old_size; i < new_size; ++i) {
273 (*this)[i] = led;
274 }
275 }
276 }
277
278 template <class Led>
280 _pixels.clear();
281 _rmt_buffer.clear();
282 }
283
284 template <class Led>
285 template <class Neopix, class CRTPIt>
287 return (*_neopix)[_i];
288 }
289
290
291 template <class Led>
292 template <class Neopix, class CRTPIt>
294 ++_i;
295 return *reinterpret_cast<CRTPIt *>(this);
296 }
297
298 template <class Led>
299 template <class Neopix, class CRTPIt>
301 CRTPIt copy = *reinterpret_cast<CRTPIt *>(this);
302 ++(*this);
303 return copy;
304 }
305
306 template <class Led>
307 template <class Neopix, class CRTPIt>
309 --_i;
310 return *reinterpret_cast<CRTPIt *>(this);
311 }
312
313 template <class Led>
314 template <class Neopix, class CRTPIt>
316 CRTPIt copy = *reinterpret_cast<CRTPIt *>(this);
317 --(*this);
318 return copy;
319 }
320
321
322 template <class Led>
323 template <class Neopix, class CRTPIt>
325 auto const &other_base = static_cast<iterator_base<Neopix, CRTPIt> const &>(other);
326 if (_neopix == other_base._neopix) {
327 if (_neopix != nullptr) {
328 return _i == other_base._i;
329 }
330 return true;
331 }
332 return false;
333 }
334
335 template <class Led>
336 template <class Neopix, class CRTPIt>
338 return not operator==(other);
339 }
340
341
342 template <class Led>
343 template <class Neopix, class CRTPIt>
345 _i += n;
346 return *reinterpret_cast<CRTPIt *>(this);
347 }
348
349
350 template <class Led>
351 template <class Neopix, class CRTPIt>
353 _i -= n;
354 return *reinterpret_cast<CRTPIt *>(this);
355 }
356
357 template <class Led>
358 template <class Neopix, class CRTPIt>
360 CRTPIt copy = *reinterpret_cast<CRTPIt const *>(this);
361 copy += n;
362 return copy;
363 }
364
365 template <class Led>
366 template <class Neopix, class CRTPIt>
368 CRTPIt copy = *reinterpret_cast<CRTPIt const *>(this);
369 copy -= n;
370 return copy;
371 }
372
373 template <class Led>
375 if (_neopix == nullptr) {
376 return const_iterator{};
377 }
378 return const_iterator{*_neopix, _i};
379 }
380
381 template <class Led>
383 return {*this, 0};
384 }
385
386 template <class Led>
388 return {*this, 0};
389 }
390
391
392 template <class Led>
394 return {*this, size() - 1};
395 }
396
397
398 template <class Led>
400 return {*this, size() - 1};
401 }
402
403
404 template <class Led>
406 return {*this, 0};
407 }
408
409
410 template <class Led>
412 return {*this, size() - 1};
413 }
414
415 template <class Led>
417 using diff_t = typename decltype(_rmt_buffer)::difference_type;
418 return ref{*this, _pixels.at(i), std::begin(_rmt_buffer) + diff_t(i * 8 * sizeof(Led))};
419 }
420
421 template <class Led>
422 cref<Led> strip<Led>::operator[](std::size_t i) const {
423 return cref{*this, _pixels.at(i)};
424 }
425
426 template <class Led>
427 bool strip<Led>::empty() const {
428 return _pixels.empty();
429 }
430
431 template <class Led>
433 return _cref;
434 }
435
436 template <class Led>
438 return _cref.get_color(_strip.get_gamma_table());
439 }
440
441 template <class Led>
442 cref<Led>::cref(strip<Led> const &neo, Led const &cref) : _strip{neo}, _cref{cref} {}
443
444 template <class Led>
445 ref<Led>::ref(strip<Led> const &neo, Led &ref, std::vector<rmt_item32_t>::iterator repr_it)
446 : cref<Led>{neo, ref},
447 _repr_it{repr_it} {}
448
449
450 template <class Led>
452 get_ref().set_color(c, _strip.get_gamma_table());
453 // Make sure to copy the byte representation
454 populate(_repr_it, Led(*this), _strip.zero(), _strip.one());
455 }
456
457 template <class Led>
459 set_color(c);
460 return *this;
461 }
462
463 template <class Led>
465 get_ref() = v;
466 // Make sure to copy the byte representation
467 populate(_repr_it, Led(*this), _strip.zero(), _strip.one());
468 return *this;
469 }
470
471 template <class OutputIt>
472 OutputIt populate(OutputIt it, std::uint8_t b, rmt_item32_t zero, rmt_item32_t one) {
473 for (std::uint8_t mask = 1 << 7; mask != 0; mask >>= 1) {
474 *(it++) = (b & mask) != 0 ? one : zero;
475 }
476 return it;
477 }
478
479 template <class OutputIt, class T, class>
480 OutputIt populate(OutputIt it, T const &t, rmt_item32_t zero, rmt_item32_t one) {
481 auto const *byte_rep = reinterpret_cast<std::uint8_t const *>(&t);
482 for (std::size_t i = 0; i < sizeof(T); ++i, ++byte_rep) {
483 it = populate(it, *byte_rep, zero, one);
484 }
485 return it;
486 }
487
488
489 template <class Led>
490 rmt_item32_t strip<Led>::zero() const {
491 return _zero;
492 }
493
494 template <class Led>
495 rmt_item32_t strip<Led>::one() const {
496 return _one;
497 }
498
499 template <class Led>
500 esp_err_t strip<Led>::transmit(rmt_channel_t channel, bool wait_tx_done) const {
501 return rmt_write_items(channel, _rmt_buffer.data(), _rmt_buffer.size(), wait_tx_done);
502 }
503
504 template <class Led>
505 esp_err_t strip<Led>::update(std::vector<rgb> const &colors, rmt_channel_t channel, bool wait_tx_done) {
506 if (size() != colors.size()) {
507 resize(colors.size(), Led{});
508 }
509 std::copy(std::begin(colors), std::end(colors), std::begin(*this));
510 return transmit(channel, wait_tx_done);
511 }
512
513 template <class Led>
514 esp_err_t strip<Led>::update(rgb color, rmt_channel_t channel, bool wait_tx_done) {
515 for (auto led : *this) {
516 led = color;
517 }
518 return transmit(channel, wait_tx_done);
519 }
520
521}// namespace neo
522
523#endif//NEO_STRIP_HPP
Definition: strip.hpp:174
Led const & _cref
Definition: strip.hpp:177
strip< Led > const & _strip
Definition: strip.hpp:176
cref(strip< Led > const &neo, Led const &cref)
Definition: strip.hpp:442
rgb get_color() const
Definition: strip.hpp:437
Definition: led.hpp:34
Definition: strip.hpp:189
std::vector< rmt_item32_t >::iterator _repr_it
Definition: strip.hpp:190
void set_color(rgb c)
Definition: strip.hpp:451
ref & operator=(Led v)
Definition: strip.hpp:464
ref(strip< Led > const &neo, Led &ref, std::vector< rmt_item32_t >::iterator repr_it)
Definition: strip.hpp:445
Led & get_ref()
Definition: strip.hpp:194
Definition: rmt.hpp:28
Definition: strip.hpp:143
decltype(std::declval< strip const & >()[0]) value_type
Definition: strip.hpp:146
void pointer
Definition: strip.hpp:148
std::random_access_iterator_tag iterator_category
Definition: strip.hpp:145
void reference
Definition: strip.hpp:149
void difference_type
Definition: strip.hpp:147
Definition: strip.hpp:108
CRTPIt & operator--()
Definition: strip.hpp:308
const CRTPIt operator--(int)
Definition: strip.hpp:315
CRTPIt & operator++()
Definition: strip.hpp:293
iterator_base(Neopix &neopix, std::size_t i)
Definition: strip.hpp:116
CRTPIt & operator-=(std::size_t n)
Definition: strip.hpp:352
bool operator==(CRTPIt const &other) const
Definition: strip.hpp:324
CRTPIt operator+(std::size_t n) const
Definition: strip.hpp:359
CRTPIt operator-(std::size_t n) const
Definition: strip.hpp:367
bool operator!=(CRTPIt const &other) const
Definition: strip.hpp:337
std::size_t _i
Definition: strip.hpp:111
CRTPIt & operator+=(std::size_t n)
Definition: strip.hpp:344
const CRTPIt operator++(int)
Definition: strip.hpp:300
Definition: strip.hpp:156
void difference_type
Definition: strip.hpp:164
decltype(std::declval< strip & >()[0]) value_type
Definition: strip.hpp:163
std::random_access_iterator_tag iterator_category
Definition: strip.hpp:162
void pointer
Definition: strip.hpp:165
void reference
Definition: strip.hpp:166
Definition: strip.hpp:39
rmt_item32_t _one
Definition: strip.hpp:41
static constexpr float default_gamma
Definition: strip.hpp:48
void resize(std::size_t new_size)
Definition: strip.hpp:262
esp_err_t transmit(rmt_channel_t channel, bool wait_tx_done) const
Definition: strip.hpp:500
gamma_table const * _gamma_table
Definition: strip.hpp:43
const_iterator begin() const
Definition: strip.hpp:382
bool empty() const
Definition: strip.hpp:427
void clear()
Definition: strip.hpp:279
std::size_t size() const override
Definition: strip.hpp:257
const_iterator cend() const
Definition: strip.hpp:399
gamma_table const * get_gamma_table() const
Definition: strip.hpp:246
std::vector< Led > _pixels
Definition: strip.hpp:44
std::vector< rmt_item32_t > _rmt_buffer
Definition: strip.hpp:45
float _gamma
Definition: strip.hpp:42
strip(std::pair< rmt_item32_t, rmt_item32_t > zero_one, std::size_t size=0, float gamma=default_gamma)
Definition: strip.hpp:228
rmt_item32_t _zero
Definition: strip.hpp:40
const_iterator end() const
Definition: strip.hpp:393
const_iterator cbegin() const
Definition: strip.hpp:387
rmt_item32_t zero() const
Definition: strip.hpp:490
float gamma() const
Definition: strip.hpp:241
static constexpr float no_gamma
Definition: strip.hpp:49
void set_gamma(float gamma)
Definition: strip.hpp:251
ref< Led > operator[](std::size_t i)
Definition: strip.hpp:416
rmt_item32_t one() const
Definition: strip.hpp:495
esp_err_t update(std::vector< rgb > const &colors, rmt_channel_t channel, bool wait_tx_done) override
Definition: strip.hpp:505
Definition: strip.hpp:29
virtual std::size_t size() const =0
virtual esp_err_t update(rgb color, rmt_channel_t channel, bool wait_tx_done)=0
virtual esp_err_t update(std::vector< rgb > const &colors, rmt_channel_t channel, bool wait_tx_done)=0
virtual ~transmittable_rgb_strip()=default
Definition: any_fx.cpp:7
gamma_table const & get_cached_gamma_table(float gamma)
Definition: gamma.cpp:46
OutputIt populate(OutputIt it, std::uint8_t b, rmt_item32_t zero, rmt_item32_t one)
Definition: strip.hpp:472
std::pair< rmt_item32_t, rmt_item32_t > make_zero_one(rmt_manager const &manager, controller chip, bool inverted)
Definition: rmt.cpp:72
controller
Definition: rmt.hpp:15
Definition: gamma.hpp:14
Definition: color.hpp:47