M5Unit-COLOR 0.1.1 git rev:9de2836
Loading...
Searching...
No Matches
unit_TCS3472x.hpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2025 M5Stack Technology CO LTD
3 *
4 * SPDX-License-Identifier: MIT
5 */
10#ifndef M5_UNIT_COLOR_UNIT_TCS3472_HPP
11#define M5_UNIT_COLOR_UNIT_TCS3472_HPP
12
13#include <M5UnitComponent.hpp>
14#include <m5_utility/container/circular_buffer.hpp>
15#include <array>
16
17namespace m5 {
18namespace unit {
19
24namespace tcs3472x {
25
30enum class Persistence : uint8_t {
31 Every,
32 Cycle1,
33 Cycle2,
34 Cycle3,
35 Cycle5,
36 Cycle10,
37 Cycle15,
38 Cycle20,
39 Cycle25,
40 Cycle30,
41 Cycle35,
42 Cycle40,
43 Cycle45,
44 Cycle50,
45 Cycle55,
46 Cycle60,
47};
48
53enum class Gain : uint8_t {
54 Controlx1,
55 Controlx4,
58};
59
64struct Data {
65 std::array<uint8_t, 8> raw{};
66
70 inline uint16_t R16() const
71 {
72 return (static_cast<uint16_t>(raw[3]) << 8) | raw[2];
73 }
75 inline uint16_t G16() const
76 {
77 return (static_cast<uint16_t>(raw[5]) << 8) | raw[4];
78 }
80 inline uint16_t B16() const
81 {
82 return (static_cast<uint16_t>(raw[7]) << 8) | raw[6];
83 }
85 inline uint16_t C16() const
86 {
87 return (static_cast<uint16_t>(raw[1]) << 8) | raw[0];
88 }
90 inline uint16_t RnoIR16() const
91 {
92 return std::max(std::min(R16() - IR(), static_cast<int32_t>(0xFFFF)), static_cast<int32_t>(0x0000));
93 }
95 inline uint16_t GnoIR16() const
96 {
97 return std::max(std::min(G16() - IR(), static_cast<int32_t>(0xFFFF)), static_cast<int32_t>(0x0000));
98 }
100 inline uint16_t BnoIR16() const
101 {
102 return std::max(std::min(B16() - IR(), static_cast<int32_t>(0xFFFF)), static_cast<int32_t>(0x0000));
103 }
105 inline uint16_t CnoIR16() const
106 {
107 return std::max(std::min(C16() - IR(), static_cast<int32_t>(0xFFFF)), static_cast<int32_t>(0x0000));
108 }
110
114 inline uint8_t R8() const
115 {
116 return raw_to_uint8(R16(), C16());
117 }
119 inline uint8_t G8() const
120 {
121 return raw_to_uint8(G16(), C16());
122 }
124 inline uint8_t B8() const
125 {
126 return raw_to_uint8(B16(), C16());
127 }
129 inline uint8_t RnoIR8() const
130 {
131 return raw_to_uint8(RnoIR16(), CnoIR16());
132 }
134 inline uint8_t GnoIR8() const
135 {
136 return raw_to_uint8(GnoIR16(), CnoIR16());
137 }
139 inline uint8_t BnoIR8() const
140 {
141 return raw_to_uint8(BnoIR16(), CnoIR16());
142 }
143
145 inline uint16_t RGB565() const
146 {
147 return color565(R8(), G8(), B8());
148 }
150 inline uint32_t RGB888() const
151 {
152 return color888(R8(), G8(), B8());
153 }
155 inline uint16_t RGBnoIR565() const
156 {
157 return color565(RnoIR8(), GnoIR8(), BnoIR8());
158 }
160 inline uint32_t RGBnoIR888() const
161 {
162 return color888(RnoIR8(), GnoIR8(), BnoIR8());
163 }
165
171 inline int32_t IR(bool usingCache = true) const
172 {
173 if (!usingCache || !_cacheValid) {
174 _cache = static_cast<int32_t>((static_cast<int32_t>(R16()) + static_cast<int32_t>(G16()) +
175 static_cast<int32_t>(B16()) - static_cast<int32_t>(C16())) *
176 0.5f);
177 _cacheValid = true;
178 }
179 return _cache;
180 }
181
188 inline static uint8_t raw_to_uint8(const int32_t v, const int32_t c)
189 {
190 return std::max(std::min(static_cast<int>(c ? (static_cast<float>(v) / c) * 255.f : 0), 0xFF), 0x00);
191 }
192
196 inline static constexpr uint8_t color332(uint8_t r, uint8_t g, uint8_t b)
197 {
198 return ((((r >> 5) << 3) + (g >> 5)) << 2) + (b >> 6);
199 }
201 inline static constexpr uint16_t color565(uint8_t r, uint8_t g, uint8_t b)
202 {
203 return (r >> 3) << 11 | (g >> 2) << 5 | b >> 3;
204 }
206 inline static constexpr uint32_t color888(uint8_t r, uint8_t g, uint8_t b)
207 {
208 return r << 16 | g << 8 | b;
209 }
211 inline static constexpr uint16_t swap565(uint8_t r, uint8_t g, uint8_t b)
212 {
213 return (((r >> 3) << 3) + (g >> 5)) | (((g >> 2) << 5) | (b >> 3)) << 8;
214 }
216 inline static constexpr uint32_t swap888(uint8_t r, uint8_t g, uint8_t b)
217 {
218 return b << 16 | g << 8 | r;
219 }
221
222private:
223 mutable int32_t _cache{}; // IR component value cache
224 mutable bool _cacheValid{}; // True if _cache holds a computed value
225};
226
227} // namespace tcs3472x
228
234class UnitTCS3472x : public Component, public PeriodicMeasurementAdapter<UnitTCS3472x, tcs3472x::Data> {
235 M5_UNIT_COMPONENT_HPP_BUILDER(UnitTCS3472x, 0x00);
236
237public:
242 struct config_t {
244 bool start_periodic{true};
246 float atime{614.4f};
248 float wtime{2.4f};
250 tcs3472x::Gain gain{tcs3472x::Gain::Controlx4};
251 };
252
257 explicit UnitTCS3472x(const uint8_t addr = DEFAULT_ADDRESS)
258 : Component(addr), _data{new m5::container::CircularBuffer<tcs3472x::Data>(1)}
259 {
260 auto ccfg = component_config();
261 ccfg.clock = 400 * 1000U;
262 component_config(ccfg);
263 }
266 {
267 }
268
271 virtual bool begin() override;
274 virtual void update(const bool force = false) override;
275
278
280 {
281 return _cfg;
282 }
284 inline void config(const config_t& cfg)
285 {
286 _cfg = cfg;
287 }
289
293 inline uint8_t R8() const
294 {
295 return !empty() ? oldest().R8() : 0U;
296 }
298 inline uint8_t G8() const
299 {
300 return !empty() ? oldest().G8() : 0U;
301 }
303 inline uint8_t B8() const
304 {
305 return !empty() ? oldest().B8() : 0U;
306 }
308 inline uint16_t RGB565() const
309 {
310 return !empty() ? oldest().RGB565() : 0U;
311 }
313
316
333 bool readGain(tcs3472x::Gain& gc);
339 bool writeGain(const tcs3472x::Gain gc);
345 bool readAtime(uint8_t& raw);
351 bool readAtime(float& ms);
357 template <typename T, typename std::enable_if<std::is_integral<T>::value, std::nullptr_t>::type = nullptr>
358 inline bool writeAtime(const T raw)
359 {
360 return write_atime(static_cast<uint8_t>(raw));
361 }
369 bool writeAtime(const float ms);
376 bool readWtime(uint8_t& raw, bool& wlong);
382 bool readWtime(float& ms);
389 bool writeWtime(const uint8_t raw, const bool wlong);
397 bool writeWtime(const float ms);
399
402
409 inline bool startPeriodicMeasurement(const tcs3472x::Gain gc, const float atime, const float wtime)
410 {
411 return PeriodicMeasurementAdapter<UnitTCS3472x, tcs3472x::Data>::startPeriodicMeasurement(gc, atime, wtime);
412 }
415 {
416 return PeriodicMeasurementAdapter<UnitTCS3472x, tcs3472x::Data>::startPeriodicMeasurement();
417 }
423 inline bool stopPeriodicMeasurement(const bool power_off = true)
424 {
425 return PeriodicMeasurementAdapter<UnitTCS3472x, tcs3472x::Data>::stopPeriodicMeasurement(power_off);
426 }
428
431
440 bool measureSingleshot(tcs3472x::Data& d, const tcs3472x::Gain gc, const float atime);
444
447
452 bool readInterrupt(bool& enable);
458 bool writeInterrupt(const bool enable);
465 bool readInterruptThreshold(uint16_t& low, uint16_t& high);
472 bool writeInterruptThreshold(const uint16_t low, const uint16_t high);
473
475 bool clearInterrupt();
477
483 bool readStatus(uint8_t& status);
484
485protected:
486 inline virtual bool is_valid_id(const uint8_t id)
487 {
488 return false;
489 }
490
491 bool read_register8(const uint8_t reg, uint8_t& val);
492 bool write_register8(const uint8_t reg, const uint8_t val);
493 // bool read_register16(const uint8_t reg, uint16_t& val);
494 // bool write_register16(const uint8_t reg, const uint16_t val);
495 bool read_register(const uint8_t reg, uint8_t* buf, const uint32_t len);
496 bool write_register(const uint8_t reg, const uint8_t* buf, const uint32_t len);
497
498 bool start_periodic_measurement(const tcs3472x::Gain gc, const float atime, const float wtime);
499 bool start_periodic_measurement();
500 bool stop_periodic_measurement(const bool power_off);
501
502 bool is_data_ready();
503 bool read_measurement(tcs3472x::Data& d);
504
505 bool write_atime(const uint8_t raw);
506
507 M5_UNIT_COMPONENT_PERIODIC_MEASUREMENT_ADAPTER_HPP_BUILDER(UnitTCS3472x, tcs3472x::Data);
508
509private:
510 std::unique_ptr<m5::container::CircularBuffer<tcs3472x::Data>> _data{};
511 config_t _cfg{};
512};
513
519 M5_UNIT_COMPONENT_HPP_BUILDER(UnitTCS34725, 0x29);
520
521public:
524 explicit UnitTCS34725(const uint8_t addr = DEFAULT_ADDRESS) : UnitTCS3472x(addr)
525 {
526 }
529 {
530 }
532 static constexpr uint8_t UNIT_ID{0x44};
533
534protected:
535 inline virtual bool is_valid_id(const uint8_t id) override
536 {
537 return id == UNIT_ID;
538 }
539};
540
546 M5_UNIT_COMPONENT_HPP_BUILDER(UnitTCS34727, 0x29);
547
548public:
551 explicit UnitTCS34727(const uint8_t addr = DEFAULT_ADDRESS) : UnitTCS3472x(addr)
552 {
553 }
556 {
557 }
559 static constexpr uint8_t UNIT_ID{0x4D};
560
561protected:
562 inline virtual bool is_valid_id(const uint8_t id) override
563 {
564 return id == UNIT_ID;
565 }
566};
567
569namespace tcs3472x {
570namespace command {
571// R/W
572constexpr uint8_t ENABLE_REG{0x00};
573constexpr uint8_t ATIME_REG{0x01};
574constexpr uint8_t WTIME_REG{0x03};
575constexpr uint8_t AILTL_REG{0x04};
576constexpr uint8_t AILTH_REG{0x05};
577constexpr uint8_t AIHTL_REG{0x06};
578constexpr uint8_t AIHTH_REG{0x07};
579constexpr uint8_t PERS_REG{0x0C};
580constexpr uint8_t CONFIG_REG{0x0D};
581constexpr uint8_t CONTROL_REG{0x0F};
582// R
583constexpr uint8_t ID_REG{0x12};
584constexpr uint8_t STATUS_REG{0x13};
585constexpr uint8_t CDATAL_REG{0x14};
586constexpr uint8_t CDATAH_REG{0x15};
587constexpr uint8_t RDATAL_REG{0x16};
588constexpr uint8_t RDATAH_REG{0x17};
589constexpr uint8_t GDATAL_REG{0x18};
590constexpr uint8_t GDATAH_REG{0x19};
591constexpr uint8_t BDATAL_REG{0x1A};
592constexpr uint8_t BDATAH_REG{0x1B};
593
594} // namespace command
595} // namespace tcs3472x
597
598} // namespace unit
599} // namespace m5
600#endif
Color recognition unit.
Definition unit_TCS3472x.hpp:518
virtual ~UnitTCS34725()
Destructor.
Definition unit_TCS3472x.hpp:528
static constexpr uint8_t UNIT_ID
Device ID for TCS34725.
Definition unit_TCS3472x.hpp:532
UnitTCS34725(const uint8_t addr=DEFAULT_ADDRESS)
Constructor.
Definition unit_TCS3472x.hpp:524
Color recognition unit.
Definition unit_TCS3472x.hpp:545
virtual ~UnitTCS34727()
Destructor.
Definition unit_TCS3472x.hpp:555
static constexpr uint8_t UNIT_ID
Device ID for TCS34727.
Definition unit_TCS3472x.hpp:559
UnitTCS34727(const uint8_t addr=DEFAULT_ADDRESS)
Constructor.
Definition unit_TCS3472x.hpp:551
Color recognition unit.
Definition unit_TCS3472x.hpp:234
bool readAtime(uint8_t &raw)
Read the RGBC integration time (ATIME)
Definition unit_TCS3472x.cpp:278
bool writeInterruptThreshold(const uint16_t low, const uint16_t high)
Write the interrupt thresholds for clear channel.
Definition unit_TCS3472x.cpp:394
uint8_t R8() const
Oldest measured Red.
Definition unit_TCS3472x.hpp:293
bool readWtime(uint8_t &raw, bool &wlong)
Read the wait time (WTIME)
Definition unit_TCS3472x.cpp:316
uint8_t B8() const
Oldest measured Blue.
Definition unit_TCS3472x.hpp:303
uint8_t G8() const
Oldest measured Green.
Definition unit_TCS3472x.hpp:298
bool readStatus(uint8_t &status)
Read the status register.
Definition unit_TCS3472x.cpp:409
bool stopPeriodicMeasurement(const bool power_off=true)
Stop periodic measurement.
Definition unit_TCS3472x.hpp:423
bool clearInterrupt()
Clear interrupt.
Definition unit_TCS3472x.cpp:404
virtual bool begin() override
Begin communication with the sensor.
Definition unit_TCS3472x.cpp:109
bool writeAtime(const T raw)
Write the RGBC integration time (ATIME)
Definition unit_TCS3472x.hpp:358
uint16_t RGB565() const
Oldest measured RGB565.
Definition unit_TCS3472x.hpp:308
virtual ~UnitTCS3472x()
Destructor.
Definition unit_TCS3472x.hpp:265
bool writeWtime(const uint8_t raw, const bool wlong)
Write the wait time (WTIME)
Definition unit_TCS3472x.cpp:337
bool startPeriodicMeasurement()
Start periodic measurement using current settings.
Definition unit_TCS3472x.hpp:414
bool writeGain(const tcs3472x::Gain gc)
Write the gain control.
Definition unit_TCS3472x.cpp:269
UnitTCS3472x(const uint8_t addr=DEFAULT_ADDRESS)
Constructor.
Definition unit_TCS3472x.hpp:257
bool writeInterrupt(const bool enable)
Write the interrupt status.
Definition unit_TCS3472x.cpp:373
bool readInterrupt(bool &enable)
Read the interrupt status.
Definition unit_TCS3472x.cpp:363
void config(const config_t &cfg)
Set the configuration.
Definition unit_TCS3472x.hpp:284
bool readInterruptThreshold(uint16_t &low, uint16_t &high)
Read the interrupt thresholds for clear channel.
Definition unit_TCS3472x.cpp:383
bool writePersistence(const tcs3472x::Persistence pers)
Write the persistence.
Definition unit_TCS3472x.cpp:248
bool readGain(tcs3472x::Gain &gc)
Read the gain control.
Definition unit_TCS3472x.cpp:259
virtual void update(const bool force=false) override
Update periodic measurement data.
Definition unit_TCS3472x.cpp:129
bool measureSingleshot(tcs3472x::Data &d, const tcs3472x::Gain gc, const float atime)
Measurement single shot.
Definition unit_TCS3472x.cpp:196
config_t config()
Gets the configuration.
Definition unit_TCS3472x.hpp:279
bool readPersistence(tcs3472x::Persistence &pers)
Read the persistence.
Definition unit_TCS3472x.cpp:238
bool startPeriodicMeasurement(const tcs3472x::Gain gc, const float atime, const float wtime)
Start periodic measurement.
Definition unit_TCS3472x.hpp:409
Top level namespace of M5Stack.
For TCS3472x.
Unit-related namespace.
Settings for begin.
Definition unit_TCS3472x.hpp:242
float wtime
Wait time(ms) if start on begin.
Definition unit_TCS3472x.hpp:248
float atime
RGBC integration time(ms) if start on begin.
Definition unit_TCS3472x.hpp:246
bool start_periodic
Start periodic measurement on begin?
Definition unit_TCS3472x.hpp:244
tcs3472x::Gain gain
Gain if start on begin.
Definition unit_TCS3472x.hpp:250
Measurement data group.
Definition unit_TCS3472x.hpp:64
static constexpr uint16_t swap565(uint8_t r, uint8_t g, uint8_t b)
Converts 8-bit RGB channels to byte-swapped RGB565 format.
Definition unit_TCS3472x.hpp:211
static constexpr uint16_t color565(uint8_t r, uint8_t g, uint8_t b)
Converts 8-bit RGB channels to RGB565 format.
Definition unit_TCS3472x.hpp:201
uint16_t RGBnoIR565() const
Gets the value in RGB565 format without IR component.
Definition unit_TCS3472x.hpp:155
uint8_t G8() const
Gets the green value (0-255)
Definition unit_TCS3472x.hpp:119
std::array< uint8_t, 8 > raw
Raw data ClCh/RlRh/GlGh/BlBh.
Definition unit_TCS3472x.hpp:65
static uint8_t raw_to_uint8(const int32_t v, const int32_t c)
Raw to uint8_t.
Definition unit_TCS3472x.hpp:188
int32_t IR(bool usingCache=true) const
Gets the IR component.
Definition unit_TCS3472x.hpp:171
uint32_t RGBnoIR888() const
Gets the value in RGB888 format without IR component.
Definition unit_TCS3472x.hpp:160
uint16_t RnoIR16() const
Gets the raw red value without IR component.
Definition unit_TCS3472x.hpp:90
uint16_t RGB565() const
Gets the value in RGB565 format.
Definition unit_TCS3472x.hpp:145
static constexpr uint8_t color332(uint8_t r, uint8_t g, uint8_t b)
Converts 8-bit RGB channels to RGB332 format.
Definition unit_TCS3472x.hpp:196
uint16_t G16() const
Gets the raw green value.
Definition unit_TCS3472x.hpp:75
static constexpr uint32_t swap888(uint8_t r, uint8_t g, uint8_t b)
Converts 8-bit RGB channels to byte-swapped RGB888 format.
Definition unit_TCS3472x.hpp:216
uint16_t R16() const
Gets the raw red value.
Definition unit_TCS3472x.hpp:70
uint16_t B16() const
Gets the raw blue value.
Definition unit_TCS3472x.hpp:80
uint8_t BnoIR8() const
Gets the blue value without IR component (0-255)
Definition unit_TCS3472x.hpp:139
uint8_t GnoIR8() const
Gets the green value without IR component (0-255)
Definition unit_TCS3472x.hpp:134
uint16_t BnoIR16() const
Gets the raw blue value without IR component.
Definition unit_TCS3472x.hpp:100
uint16_t CnoIR16() const
Gets the raw clear value without IR component.
Definition unit_TCS3472x.hpp:105
uint16_t GnoIR16() const
Gets the raw green value without IR component.
Definition unit_TCS3472x.hpp:95
uint32_t RGB888() const
Gets the value in RGB888 format.
Definition unit_TCS3472x.hpp:150
uint8_t R8() const
Gets the red value (0-255)
Definition unit_TCS3472x.hpp:114
static constexpr uint32_t color888(uint8_t r, uint8_t g, uint8_t b)
Converts 8-bit RGB channels to RGB888 format.
Definition unit_TCS3472x.hpp:206
uint8_t RnoIR8() const
Gets the red value without IR component (0-255)
Definition unit_TCS3472x.hpp:129
uint16_t C16() const
Gets the raw clear value.
Definition unit_TCS3472x.hpp:85
uint8_t B8() const
Gets the blue value (0-255)
Definition unit_TCS3472x.hpp:124
Gain
RGBC Gain Control.
Definition unit_TCS3472x.hpp:53
Persistence
Interrupt persistence.
Definition unit_TCS3472x.hpp:30
@ Cycle35
35 clear channel value outside of threshold range
@ Cycle15
15 clear channel value outside of threshold range
@ Cycle45
45 clear channel value outside of threshold range
@ Cycle40
40 clear channel value outside of threshold range
@ Cycle3
3 clear channel value outside of threshold range
@ Cycle55
55 clear channel value outside of threshold range
@ Cycle5
5 clear channel value outside of threshold range
@ Cycle10
10 clear channel value outside of threshold range
@ Cycle30
30 clear channel value outside of threshold range
@ Cycle1
1 clear channel value outside of threshold range
@ Cycle2
2 clear channel value outside of threshold range
@ Cycle25
25 clear channel value outside of threshold range
@ Cycle50
50 clear channel value outside of threshold range
@ Cycle60
60 clear channel value outside of threshold range
@ Cycle20
20 clear channel value outside of threshold range
@ Every
Every RGBC cycle generates an interrupt.