SensorLib 0.5.0
Multi-platform sensor driver library for Arduino, PlatformIO, and ESP-IDF
Loading...
Searching...
No Matches
expander/IoExpanderXL9555.hpp
Go to the documentation of this file.
1
29#pragma once
30
31#include "../SensorBuildOpt.h"
32#if !SENSORLIB_EXCLUDE_IO_EXPANDER_XL9555
33
35#include "IoExpanderBase.hpp"
36
43static constexpr uint8_t XL9555_UNKNOWN_ADDRESS = (0xFF);
44
46static constexpr uint8_t XL9555_SLAVE_ADDRESS0 = (0x20);
47
49static constexpr uint8_t XL9555_SLAVE_ADDRESS1 = (0x21);
50
52static constexpr uint8_t XL9555_SLAVE_ADDRESS2 = (0x22);
53
55static constexpr uint8_t XL9555_SLAVE_ADDRESS3 = (0x23);
56
58static constexpr uint8_t XL9555_SLAVE_ADDRESS4 = (0x24);
59
61static constexpr uint8_t XL9555_SLAVE_ADDRESS5 = (0x25);
62
64static constexpr uint8_t XL9555_SLAVE_ADDRESS6 = (0x26);
65
67static constexpr uint8_t XL9555_SLAVE_ADDRESS7 = (0x27);
68
69
// end of XL9555_Constants
71
72#ifdef __GNUC__
74#define DEPRECATED_ATTR __attribute__((deprecated("use XL9555_UNKNOWN_ADDRESS instead")))
75#else
76#define DEPRECATED_ATTR
77#endif
78
85static const int XL9555_UNKOWN_ADDRESS DEPRECATED_ATTR = XL9555_UNKNOWN_ADDRESS;
86
87
88
98{
99public:
100 enum Port {
101 PORT0 = 0x00FF,
102 PORT1 = 0xFF00,
103 PORT_ALL = 0xFFFF
104 };
105
107 IO0 __attribute__((deprecated("Use integer pin numbers (0-15) directly instead."))),
108 IO1 __attribute__((deprecated("Use integer pin numbers (0-15) directly instead."))),
109 IO2 __attribute__((deprecated("Use integer pin numbers (0-15) directly instead."))),
110 IO3 __attribute__((deprecated("Use integer pin numbers (0-15) directly instead."))),
111 IO4 __attribute__((deprecated("Use integer pin numbers (0-15) directly instead."))),
112 IO5 __attribute__((deprecated("Use integer pin numbers (0-15) directly instead."))),
113 IO6 __attribute__((deprecated("Use integer pin numbers (0-15) directly instead."))),
114 IO7 __attribute__((deprecated("Use integer pin numbers (0-15) directly instead."))),
115 IO8 __attribute__((deprecated("Use integer pin numbers (0-15) directly instead."))),
116 IO9 __attribute__((deprecated("Use integer pin numbers (0-15) directly instead."))),
117 IO10 __attribute__((deprecated("Use integer pin numbers (0-15) directly instead."))),
118 IO11 __attribute__((deprecated("Use integer pin numbers (0-15) directly instead."))),
119 IO12 __attribute__((deprecated("Use integer pin numbers (0-15) directly instead."))),
120 IO13 __attribute__((deprecated("Use integer pin numbers (0-15) directly instead."))),
121 IO14 __attribute__((deprecated("Use integer pin numbers (0-15) directly instead."))),
122 IO15 __attribute__((deprecated("Use integer pin numbers (0-15) directly instead."))),
123 };
124
130 IoExpanderXL9555() : IoExpanderBase(XL9555_PINS_COUNT) {}
131
135 ~IoExpanderXL9555() = default;
136
146 void digitalWritePort(uint16_t mask, uint16_t values) override
147 {
148 uint8_t lowByte = values & 0xFF;
149 uint8_t highByte = (values >> 8) & 0xFF;
150 if (!_outputStates) {
151 SENSORLIB_LOG_E("Output states array not initialized");
152 return;
153 }
154 if (mask & 0x00FF) {
155 writeReg(XL9555_CTRL_OUTP0, lowByte);
156 }
157 if (mask & 0xFF00) {
158 writeReg(XL9555_CTRL_OUTP1, highByte);
159 }
160 for (uint8_t i = 0; i < XL9555_PINS_COUNT; i++) {
161 if (mask & (1UL << i)) {
162 _outputStates[i] = (values >> i) & 1;
163 }
164 }
165 }
166
177 uint16_t digitalReadPort() override
178 {
179 uint16_t result = 0;
180 uint8_t lowByte = readReg(XL9555_CTRL_INP0);
181 uint8_t highByte = readReg(XL9555_CTRL_INP1);
182 result = (highByte << 8) | lowByte;
183 return result;
184 }
185
186protected:
197 void pinModeImpl(uint8_t pin, uint8_t mode) override
198 {
199 if (pin >= XL9555_PINS_COUNT) {
200 SENSORLIB_LOG_E("Invalid pin number, pin range is 0-%d", XL9555_PINS_COUNT - 1);
201 return;
202 }
203 uint8_t reg = (pin < 8) ? XL9555_CTRL_CFG0 : XL9555_CTRL_CFG1;
204 uint8_t bit = pin % 8;
205 if (mode == OUTPUT) {
206 clrRegBit(reg, bit);
207 } else {
208 setRegBit(reg, bit);
209 }
210 }
211
212
232 void configPinsImpl(uint16_t pinMask, uint8_t mode) override
233 {
234 uint8_t lowMask = pinMask & 0xFF; // Bits for Port 0 (pins 0‑7)
235 uint8_t highMask = (pinMask >> 8) & 0xFF; // Bits for Port 1 (pins 8‑15)
236
237 // --- Configure Port 0 (CFG0) ---
238 if (lowMask) {
239 // Read current configuration
240 uint8_t cur = readReg(XL9555_CTRL_CFG0);
241 // Modify only the bits specified in lowMask
242 if (mode == INPUT) {
243 cur |= lowMask; // Set bits to 1 for INPUT
244 } else {
245 cur &= ~lowMask; // Clear bits to 0 for OUTPUT
246 }
247 // Write back updated value
248 writeReg(XL9555_CTRL_CFG0, cur);
249
250 // Update the internal pin mode cache for Port 0 pins
251 for (uint8_t i = 0; i < 8; i++) {
252 if (lowMask & (1 << i)) {
253 _pinModes[i] = mode;
254 }
255 }
256 }
257
258 // --- Configure Port 1 (CFG1) ---
259 if (highMask) {
260 uint8_t cur = readReg(XL9555_CTRL_CFG1);
261 if (mode == INPUT) {
262 cur |= highMask;
263 } else {
264 cur &= ~highMask;
265 }
266 writeReg(XL9555_CTRL_CFG1, cur);
267
268 // Update the internal pin mode cache for Port 1 pins
269 for (uint8_t i = 0; i < 8; i++) {
270 if (highMask & (1 << i)) {
271 _pinModes[i + 8] = mode;
272 }
273 }
274 }
275 }
276
286 void digitalWriteImpl(uint8_t pin, bool value) override
287 {
288 if (pin >= XL9555_PINS_COUNT) {
289 SENSORLIB_LOG_E("Invalid pin number, pin range is 0-%d", XL9555_PINS_COUNT - 1);
290 return;
291 }
292 uint8_t reg = (pin < 8) ? XL9555_CTRL_OUTP0 : XL9555_CTRL_OUTP1;
293 uint8_t bit = pin % 8;
294 if (value) {
295 setRegBit(reg, bit);
296 } else {
297 clrRegBit(reg, bit);
298 }
299 }
300
310 bool digitalReadImpl(uint8_t pin) override
311 {
312 if (pin >= XL9555_PINS_COUNT) {
313 SENSORLIB_LOG_E("Invalid pin number, pin range is 0-%d", XL9555_PINS_COUNT - 1);
314 return false;
315 }
316 if (!ensureValid()) {
317 return false;
318 }
319 uint8_t reg = (pin < 8) ? XL9555_CTRL_INP0 : XL9555_CTRL_INP1;
320 uint8_t bit = pin % 8;
321 uint8_t value = readReg(reg);
322 return (value >> bit) & 1;
323 }
324
337 bool initImpl(uint8_t param) override
338 {
339 if (param == XL9555_UNKNOWN_ADDRESS) {
340 SENSORLIB_LOG_D("Try to automatically discover the device");
341 for (uint8_t address = XL9555_SLAVE_ADDRESS0; address <= XL9555_SLAVE_ADDRESS7; ++address) {
342 setAddress(address);
343 SENSORLIB_LOG_D("Try to use 0x%" PRIx8 " address.", address);
344 if (readReg(XL9555_CTRL_INP0) >= 0) {
345 SENSORLIB_LOG_D("Found the xl9555 chip address is 0x%" PRIx8, address);
346 return true;
347 }
348 }
349 SENSORLIB_LOG_E("No found xl9555 chip ...");
350 return false;
351 }
352 if (readReg(XL9555_CTRL_INP0) < 0 ) {
353 return false;
354 }
355 return true;
356 }
357
358private:
359 // Register addresses (as per XL9555 datasheet)
360 static constexpr uint8_t XL9555_CTRL_INP0 = (0x00);
361 static constexpr uint8_t XL9555_CTRL_INP1 = (0x01);
362 static constexpr uint8_t XL9555_CTRL_OUTP0 = (0x02);
363 static constexpr uint8_t XL9555_CTRL_OUTP1 = (0x03);
364 static constexpr uint8_t XL9555_CTRL_PIP0 = (0x04);
365 static constexpr uint8_t XL9555_CTRL_PIP1 = (0x05);
366 static constexpr uint8_t XL9555_CTRL_CFG0 = (0x06);
367 static constexpr uint8_t XL9555_CTRL_CFG1 = (0x07);
368 static constexpr uint8_t XL9555_PINS_COUNT = 16;
369};
370
371#endif
@license MIT License
@license MIT License
#define SENSORLIB_LOG_E(...)
#define SENSORLIB_LOG_D(...)
virtual bool ensureValid() const override
Abstract base class for GPIO expander devices.
std::unique_ptr< bool[]> _outputStates
Cached output states (true = HIGH)
std::unique_ptr< uint8_t[]> _pinModes
Cached pin modes (INPUT/OUTPUT)
Concrete driver for the XL9555 16‑bit I2C GPIO expander.
uint16_t digitalReadPort() override
Read the values of all 16 input pins as a single 16-bit word.
void digitalWriteImpl(uint8_t pin, bool value) override
Write a digital value to an output pin.
~IoExpanderXL9555()=default
Destroy the IoExpanderXL9555 object.
bool digitalReadImpl(uint8_t pin) override
Read the digital value from an input pin.
void configPinsImpl(uint16_t pinMask, uint8_t mode) override
Hardware‑specific implementation for configuring multiple pins simultaneously.
bool initImpl(uint8_t param) override
Perform chip‑specific initialization.
void digitalWritePort(uint16_t mask, uint16_t values) override
Write to multiple pins simultaneously using a mask.
IoExpanderXL9555()
Construct a new IoExpanderXL9555 object.
void pinModeImpl(uint8_t pin, uint8_t mode) override
Set the direction of a single pin.
bool clrRegBit(uint8_t reg, uint8_t bit)
int readReg(uint8_t reg) const
int writeReg(uint8_t reg, uint8_t val)
void setAddress(uint8_t address)
bool setRegBit(uint8_t reg, uint8_t bit)
#define DEPRECATED_ATTR
uint8_t i