libDaisy
Hardware Library for Daisy
Loading...
Searching...
No Matches
mcp23x17.h
Go to the documentation of this file.
1#pragma once
2
3#include "per/gpio.h"
4#include "per/i2c.h"
5
6// This get defined in a public (ST) header file
7#undef SetBit
8
9namespace daisy
10{
11// Adapted from https://github.com/blemasle/arduino-mcp23017
12
18enum class MCPRegister : uint8_t
19{
20 IODIR_A = 0x00, // Controls the direction of the data I/O for port A.
21 IODIR_B = 0x01, // Controls the direction of the data I/O for port B.
22 IPOL_A
23 = 0x02, // Configures the polarity on the corresponding GPIO_ port bits for port A.
24 IPOL_B
25 = 0x03, // Configures the polarity on the corresponding GPIO_ port bits for port B.
27 = 0x04, // Controls the interrupt-on-change for each pin of port A.
29 = 0x05, // Controls the interrupt-on-change for each pin of port B.
31 = 0x06, // Controls the default comparaison value for interrupt-on-change for port A.
33 = 0x07, // Controls the default comparaison value for interrupt-on-change for port B.
35 = 0x08, // Controls how the associated pin value is compared for the interrupt-on-change for port A.
37 = 0x09, // Controls how the associated pin value is compared for the interrupt-on-change for port B.
38 IOCON = 0x0A, // Controls the device.
39 GPPU_A = 0x0C, // Controls the pull-up resistors for the port A pins.
40 GPPU_B = 0x0D, // Controls the pull-up resistors for the port B pins.
41 INTF_A = 0x0E, // Reflects the interrupt condition on the port A pins.
42 INTF_B = 0x0F, // Reflects the interrupt condition on the port B pins.
44 = 0x10, // Captures the port A value at the time the interrupt occured.
46 = 0x11, // Captures the port B value at the time the interrupt occured.
47 GPIO_A = 0x12, // Reflects the value on the port A.
48 GPIO_B = 0x13, // Reflects the value on the port B.
49 OLAT_A = 0x14, // Provides access to the port A output latches.
50 OLAT_B = 0x15, // Provides access to the port B output latches.
51};
52
53enum class MCPPort : uint8_t
54{
55 A = 0,
56 B = 1
57};
58
60{
61 return static_cast<MCPRegister>(static_cast<uint8_t>(a)
62 + static_cast<uint8_t>(b));
63}
64
65enum class MCPMode : uint8_t
66{
67 INPUT,
69 OUTPUT,
70};
71
85{
86 public:
101
102 void Init()
103 {
105 config.Defaults();
106 Init(config);
107 };
108
109 void Init(const Config& config)
110 {
111 i2c_address_ = config.i2c_address << 1;
112 i2c_.Init(config.i2c_config);
113 };
114
116 {
117 uint8_t data[1] = {val};
119 i2c_address_, static_cast<uint8_t>(reg), 1, data, 1, timeout);
120 }
121
123 {
124 uint8_t data[2] = {portA, portB};
126 i2c_address_, static_cast<uint8_t>(reg), 1, data, 2, timeout);
127 }
128
130 {
131 uint8_t data[1] = {0x00};
133 i2c_address_, static_cast<uint8_t>(reg), 1, data, 1, timeout);
134 return data[0];
135 }
136
138 {
139 uint8_t data[2];
141 i2c_address_, static_cast<uint8_t>(reg), 1, data, 2, timeout);
142
143 portA = data[0];
144 portB = data[1];
145 }
146
150};
151
152template <typename Transport>
154{
155 public:
156 struct Config
157 {
158 typename Transport::Config transport_config;
159 };
160
161 void Init()
162 {
164 config.transport_config.Defaults();
165 Init(config);
166 };
167
168 void Init(const Config& config)
169 {
170 transport.Init(config.transport_config);
171
172 //BANK = 0 : sequential register addresses
173 //MIRROR = 0 : use configureInterrupt
174 //SEQOP = 1 : sequential operation disabled, address pointer does not increment
175 //DISSLW = 0 : slew rate enabled
176 //HAEN = 0 : hardware address pin is always enabled on 23017
177 //ODR = 0 : open drain output
178 //INTPOL = 0 : interrupt active low
179 transport.WriteReg(MCPRegister::IOCON, 0b00100000);
180
181 //enable all pull up resistors (will be effective for input pins only)
182 transport.WriteReg(MCPRegister::GPPU_A, 0xFF, 0xFF);
183 };
184
194 void PortMode(MCPPort port,
196 uint8_t pullups = 0xFF,
197 uint8_t inverted = 0x00)
198 {
199 transport.WriteReg(MCPRegister::IODIR_A + port, directions);
200 transport.WriteReg(MCPRegister::GPPU_A + port, pullups);
201 transport.WriteReg(MCPRegister::IPOL_A + port, inverted);
202 }
203
213 void PinMode(uint8_t pin, MCPMode mode, bool inverted)
214 {
218 uint8_t iodir, pol, pull;
219 if(pin > 7)
220 {
224 pin -= 8;
225 }
226 iodir = transport.ReadReg(iodirreg);
227 if(mode == MCPMode::INPUT || mode == MCPMode::INPUT_PULLUP)
228 SetBit(iodir, pin);
229 else
230 ClearBit(iodir, pin);
231 pull = transport.ReadReg(pullupreg);
232 if(mode == MCPMode::INPUT_PULLUP)
233 SetBit(pull, pin);
234 else
235 ClearBit(pull, pin);
236 pol = transport.ReadReg(polreg);
237 if(inverted)
238 SetBit(pol, pin);
239 else
240 ClearBit(pol, pin);
241 transport.WriteReg(iodirreg, iodir);
242 transport.WriteReg(pullupreg, pull);
243 transport.WriteReg(polreg, pol);
244 }
245
256 {
259 if(pin > 7)
260 {
262 pin -= 8;
263 }
264
265 gpio = transport.ReadReg(gpioreg);
266 if(state > 0)
267 {
268 gpio = SetBit(gpio, pin);
269 }
270 else
271 {
272 gpio = ClearBit(gpio, pin);
273 }
274
275 transport.WriteReg(gpioreg, gpio);
276 }
277
288 {
291 if(pin > 7)
292 {
294 pin -= 8;
295 }
296
297 gpio = transport.ReadReg(gpioreg);
298 if(ReadBit(gpio, pin))
299 {
300 return 1;
301 }
302
303 return 0;
304 }
305
314 void WritePort(MCPPort port, uint8_t value)
315 {
316 transport.WriteReg(MCPRegister::GPIO_A + port, value);
317 }
318
328 {
329 return transport.ReadReg(MCPRegister::GPIO_A + port);
330 }
331
340 void Write(uint16_t value)
341 {
342 transport.WriteReg(
343 MCPRegister::GPIO_A, LowByte(value), HighByte(value));
344 }
345
355 {
358
359 pin_data = a | b << 8;
360 return pin_data;
361 }
362
369 uint8_t GetPin(uint8_t id) { return ReadBit(pin_data, id); }
370
371 private:
372 uint8_t GetBit(uint8_t data, uint8_t id)
373 {
374 uint8_t mask = 1 << id;
375 uint8_t masked_n = data & mask;
376 return masked_n >> id;
377 }
378
379 uint8_t SetBit(uint8_t data, uint8_t pos)
380 {
381 data = (data | (1 << pos));
382 return data;
383 }
384
385 uint8_t ClearBit(uint8_t data, uint8_t pos)
386 {
387 data = (data & (~(1 << pos)));
388 return data;
389 }
390
391 uint8_t ReadBit(uint16_t data, uint8_t pos)
392 {
393 return data & (1 << pos) ? 0xff : 0x00;
394 }
395
396 uint8_t LowByte(uint16_t val) { return val & 0xFF; }
397 uint8_t HighByte(uint16_t val) { return (val >> 8) & 0xff; }
398
399 uint16_t pin_data;
400 Transport transport;
401};
402
404} // namespace daisy
Definition i2c.h:25
Result ReadDataAtAddress(uint16_t address, uint16_t mem_address, uint16_t mem_address_size, uint8_t *data, uint16_t data_size, uint32_t timeout)
Result Init(const Config &config)
Result
Definition i2c.h:71
Result WriteDataAtAddress(uint16_t address, uint16_t mem_address, uint16_t mem_address_size, uint8_t *data, uint16_t data_size, uint32_t timeout)
Definition leddriver.h:33
void Init(I2CHandle i2c, const uint8_t(&addresses)[numDrivers], DmaBuffer dma_buffer_a, DmaBuffer dma_buffer_b, dsy_gpio_pin oe_pin={DSY_GPIOX, 0})
Definition leddriver.h:65
Definition mcp23x17.h:85
void ReadReg(MCPRegister reg, uint8_t &portA, uint8_t &portB)
Definition mcp23x17.h:137
uint8_t timeout
Definition mcp23x17.h:149
void Init(const Config &config)
Definition mcp23x17.h:109
uint8_t i2c_address_
Definition mcp23x17.h:148
uint8_t ReadReg(MCPRegister reg)
Definition mcp23x17.h:129
void Init()
Definition mcp23x17.h:102
I2CHandle::Result WriteReg(MCPRegister reg, uint8_t portA, uint8_t portB)
Definition mcp23x17.h:122
I2CHandle::Result WriteReg(MCPRegister reg, uint8_t val)
Definition mcp23x17.h:115
daisy::I2CHandle i2c_
Definition mcp23x17.h:147
Definition mcp23x17.h:154
void WritePin(uint8_t pin, uint8_t state)
Definition mcp23x17.h:255
uint16_t Read()
Definition mcp23x17.h:354
uint8_t ReadPort(MCPPort port)
Definition mcp23x17.h:327
void PinMode(uint8_t pin, MCPMode mode, bool inverted)
Definition mcp23x17.h:213
uint8_t GetPin(uint8_t id)
Fetches pin state from the result of recent Read() call. Useful to preserve unneeded reads.
Definition mcp23x17.h:369
void Init(const Config &config)
Definition mcp23x17.h:168
void Write(uint16_t value)
Definition mcp23x17.h:340
void Init()
Definition mcp23x17.h:161
uint8_t ReadPin(uint8_t pin)
Definition mcp23x17.h:287
void PortMode(MCPPort port, uint8_t directions, uint8_t pullups=0xFF, uint8_t inverted=0x00)
Definition mcp23x17.h:194
void WritePort(MCPPort port, uint8_t value)
Definition mcp23x17.h:314
@ DSY_GPIOB
Definition daisy_core.h:183
Hardware defines and helpers for daisy field platform.
Definition index.h:2
MCPPort
Definition mcp23x17.h:54
MCPMode
Definition mcp23x17.h:66
MCPRegister
Definition mcp23x17.h:19
MCPRegister operator+(MCPRegister a, MCPPort b)
Definition mcp23x17.h:59
Definition i2c.h:29
Mode mode
Definition i2c.h:64
Speed speed
Definition i2c.h:63
struct daisy::I2CHandle::Config::@13 pin_config
Peripheral periph
Definition i2c.h:56
Definition mcp23x17.h:88
uint8_t i2c_address
Definition mcp23x17.h:90
I2CHandle::Config i2c_config
Definition mcp23x17.h:89
void Defaults()
Definition mcp23x17.h:91
Definition mcp23x17.h:157
Transport::Config transport_config
Definition mcp23x17.h:158