SensorLib 0.5.0
Multi-platform sensor driver library for Arduino, PlatformIO, and ESP-IDF
Loading...
Searching...
No Matches
IoExpanderPCA9570.hpp
Go to the documentation of this file.
1
30#pragma once
31
32#include "../SensorBuildOpt.h"
33#if !SENSORLIB_EXCLUDE_IO_EXPANDER_PCA9570
34
36#include "IoExpanderBase.hpp"
37
39static constexpr uint8_t PCA9570_SLAVE_ADDRESS = (0x24);
40
50{
51public:
52
53 enum Port {
54 PORT_ALL = 0x0F
55 };
56
62 IoExpanderPCA9570() : IoExpanderBase(PCA9570_PINS_COUNT) {}
63
67 ~IoExpanderPCA9570() = default;
68
79 void digitalWritePort(uint16_t mask, uint16_t values) override
80 {
81 // Read current output state
82 uint8_t current;
83 if (readBuff(&current, 1) < 0) {
84 SENSORLIB_LOG_E("Failed to read current output state");
85 return;
86 }
87
88 // Update only the bits specified by mask (mask is 16-bit, but only low 4 bits used)
89 uint8_t newVal = current;
90 for (uint8_t i = 0; i < PCA9570_PINS_COUNT; i++) {
91 if (mask & (1UL << i)) {
92 if ((values >> i) & 1) {
93 newVal |= (1 << i);
94 } else {
95 newVal &= ~(1 << i);
96 }
97 }
98 }
99
100 // Write back the new value
101 if (writeRegBuff(newVal, nullptr, 0) < 0) {
102 SENSORLIB_LOG_E("Failed to write output state");
103 return;
104 }
105
106 // Update cache
107 for (uint8_t i = 0; i < PCA9570_PINS_COUNT; i++) {
108 if (mask & (1UL << i)) {
109 _outputStates[i] = (values >> i) & 1;
110 }
111 }
112 }
113
119 uint16_t digitalReadPort() override
120 {
121 uint8_t state;
122 if (readBuff(&state, 1) < 0) {
123 SENSORLIB_LOG_E("Failed to read output state");
124 return 0;
125 }
126 return state & 0x0F; // Only low 4 bits are valid
127 }
128
129protected:
141 void pinModeImpl(uint8_t pin, uint8_t mode) override
142 {
143 if (mode != OUTPUT) {
144 SENSORLIB_LOG_E("Invalid pin mode, only OUTPUT is supported");
145 return;
146 }
147 // No hardware configuration needed; all pins are fixed as outputs.
148 }
149
164 void configPinsImpl(uint16_t pinMask, uint8_t mode) override
165 {
166 // PCA9570 only supports output mode; ignore any input request
167 if (mode != OUTPUT) {
168 SENSORLIB_LOG_E("PCA9570 only supports OUTPUT mode");
169 return;
170 }
171 // No hardware configuration needed; all pins are fixed as outputs.
172 // Update the internal cache for all pins specified in the mask.
173 for (uint8_t i = 0; i < PCA9570_PINS_COUNT; i++) {
174 if (pinMask & (1UL << i)) {
175 _pinModes[i] = OUTPUT;
176 }
177 }
178 }
179
189 void digitalWriteImpl(uint8_t pin, bool value) override
190 {
191 uint8_t current = digitalReadPort(); // Read current output state
192 if (value) {
193 current |= (1 << pin);
194 } else {
195 current &= ~(1 << pin);
196 }
197 writeRegBuff(current, nullptr, 0); // Write back to output register
198 }
199
210 bool digitalReadImpl(uint8_t pin) override
211 {
212 uint8_t value = digitalReadPort();
213 return (value >> pin) & 1;
214 }
215
226 bool initImpl(uint8_t param) override
227 {
228 uint8_t buffer[3] = {};
229 if (readRegBuff(PCA9570_DEVICE_ID_READ, buffer, 3) < 0 ) {
230 SENSORLIB_LOG_E("Failed to read device ID");
231 return false;
232 }
233 uint16_t manufacturerID, partID;
234 uint8_t revision;
235 manufacturerID = (buffer[0] << 4) | ((buffer[1] >> 4) & 0x0F); // 12‑bit manufacturer ID
236 partID = ((buffer[1] & 0x0F) << 5) | ((buffer[2] >> 3) & 0x1F); // 9‑bit part ID
237 revision = buffer[2] & 0x07; // 3‑bit revision
238 (void)manufacturerID;
239 (void)partID;
240 (void)revision;
241 SENSORLIB_LOG_D("ManufacturerID:0x%" PRIx16 ", PartID:0x%" PRIx16 ", Revision:0x%" PRIx8,
242 manufacturerID, partID, revision);
243 return true;
244 }
245
246private:
247 // Special addresses and commands (refer to PCA9570 datasheet)
248 static constexpr uint8_t PCA9570_GENERAL_CALL_ADDR = 0x00;
249 static constexpr uint8_t PCA9570_DEVICE_ID_WRITE = 0xF8;
250 static constexpr uint8_t PCA9570_DEVICE_ID_READ = 0xF9;
251 static constexpr uint8_t PCA9570_SOFT_RESET_CMD = 0x06;
252 static constexpr uint8_t PCA9570_PINS_COUNT = 4;
253};
254
255#endif
@license MIT License
@license MIT License
#define SENSORLIB_LOG_E(...)
#define SENSORLIB_LOG_D(...)
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 PCA9570 4‑bit output‑only I2C GPIO expander.
bool digitalReadImpl(uint8_t pin) override
Read the current output value of a pin.
void pinModeImpl(uint8_t pin, uint8_t mode) override
Set the direction of a single pin.
~IoExpanderPCA9570()=default
Destroy the IoExpanderPCA9570 object.
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.
void digitalWriteImpl(uint8_t pin, bool value) override
Write a digital value to an output pin.
void configPinsImpl(uint16_t pinMask, uint8_t mode) override
Hardware‑specific implementation for configuring multiple pins simultaneously.
uint16_t digitalReadPort() override
Read the current output register value.
IoExpanderPCA9570()
Construct a new IoExpanderPCA9570 object.
int writeRegBuff(uint8_t reg, uint8_t *buf, size_t len)
int readRegBuff(uint8_t reg, uint8_t *buf, size_t len) const
int readBuff(uint8_t *buf, size_t len) const
uint8_t i