Arduino Helpers master
Utility library for Arduino
MCP23017.ipp
Go to the documentation of this file.
1#include "MCP23017.hpp"
2
4
6 IODIRA = 0x00,
7 IODIRB = 0x01,
8 IPOLA = 0x02,
9 IPOLB = 0x03,
10 GPINTENA = 0x04,
11 GPINTENB = 0x05,
12 DEFVALA = 0x06,
13 DEFVALB = 0x07,
14 INTCONA = 0x08,
15 INTCONB = 0x09,
16 IOCON = 0x0A,
17 GPPUA = 0x0C,
18 GPPUB = 0x0D,
19 INTFA = 0x0E,
20 INTFB = 0x0F,
21 INTCAPA = 0x10,
22 INTCAPB = 0x11,
23 GPIOA = 0x12,
24 GPIOB = 0x13,
25 OLATA = 0x14,
26 OLATB = 0x15,
27};
28
29template <class WireType>
30MCP23017<WireType>::MCP23017(WireType &wire, uint8_t addressOffset,
31 pin_t interruptPin)
32 : wire(&wire), address(I2C_BASE_ADDRESS | addressOffset),
33 interruptPin(interruptPin) {
34 // Input mode by default
37}
38
39template <class WireType>
41 if (mode == INPUT) {
42 pinModesDirty |= bufferedPinModes.get(pin) == 0;
43 pullupsDirty |= bufferedPullups.get(pin) == 1;
44 bufferedPinModes.set(pin);
45 bufferedPullups.clear(pin);
46 } else if (mode == OUTPUT) {
47 pinModesDirty |= bufferedPinModes.get(pin) == 1;
48 bufferedPinModes.clear(pin);
49 } else if (mode == INPUT_PULLUP) {
50 pinModesDirty |= bufferedPinModes.get(pin) == 0;
51 pullupsDirty |= bufferedPullups.get(pin) == 0;
52 bufferedPinModes.set(pin);
53 bufferedPullups.set(pin);
54 }
55}
56
57template <class WireType>
59 bool boolstate = status == HIGH;
60 outputsDirty |= bufferedOutputs.get(pin) != boolstate;
61 bufferedOutputs.set(pin, boolstate);
62}
63
64template <class WireType>
66 return bufferedInputs.get(pin) ? HIGH : LOW;
67}
68
69template <class WireType>
71 return bufferedInputs.get(pin) ? 1023 : 0;
72}
73
74template <class WireType>
76 digitalWriteBuffered(pin, value >= 0x80 ? HIGH : LOW);
77}
78
79template <class WireType>
81 if (interruptPin != NO_PIN)
82 ExtIO::pinMode(interruptPin, INPUT_PULLUP);
83 // Set the IOCON register (configuration register)
84 writeI2C(IOCON, //
85 0b01100100);
86 // │││││││└─ Unimplemented
87 // ││││││└── INTPOL = Active-low
88 // │││││└─── ODR = Open-drain output (overrides the INTPOL bit)
89 // ││││└──── HAEN = Disables the MCP23S17 address pins
90 // │││└───── DISSLW = Slew rate enabled
91 // ││└────── SEQOP = Sequential operation disabled, address pointer does not increment
92 // │└─────── MIRROR = The INT pins are internally connected
93 // └──────── BANK = The registers are in the same bank (addresses are sequential)
94}
95
96template <class WireType>
98 updateBufferedPinModes();
99 if (!outputsDirty)
100 return;
101 writeI2C(GPIOA, //
102 bufferedOutputs.getByte(0), //
103 bufferedOutputs.getByte(1));
104 outputsDirty = false;
105}
106
107template <class WireType>
109 // Only update if at least one pin is configured as input
110 if (!hasInputs())
111 return;
112 // Only update if a pin change interrupt happened
113 if (interruptPin != NO_PIN && ExtIO::digitalRead(interruptPin) == HIGH)
114 return;
115 writeI2C(GPIOA);
116 wire->requestFrom(address, size_t(2));
117 bufferedInputs.setByte(0, wire->read());
118 bufferedInputs.setByte(1, wire->read());
119}
120
121template <class WireType>
123 if (pinModesDirty) {
124 writeI2C(IODIRA, //
125 bufferedPinModes.getByte(0), //
126 bufferedPinModes.getByte(1));
127 writeI2C(GPINTENA, //
128 bufferedPinModes.getByte(0), //
129 bufferedPinModes.getByte(1));
130 pinModesDirty = false;
131 }
132 if (pullupsDirty) {
133 writeI2C(GPPUA, //
134 bufferedPullups.getByte(0), //
135 bufferedPullups.getByte(1));
136 pullupsDirty = false;
137 }
138}
139
140template <class WireType>
142 return bufferedPinModes.getByte(0) != 0 || bufferedPinModes.getByte(1) != 0;
143}
144
145template <class WireType>
146template <size_t N>
147void MCP23017<WireType>::writeI2C(const uint8_t (&values)[N]) {
148 this->wire->beginTransmission(address);
149 this->wire->write(values, N);
150 this->wire->endTransmission();
151}
152
153template <class WireType>
154template <class... Args>
155void MCP23017<WireType>::writeI2C(uint8_t addr, Args... values) {
156 const uint8_t v[] = {addr, static_cast<uint8_t>(values)...};
157 writeI2C(v);
158}
159
constexpr PinStatus_t LOW
constexpr PinMode_t INPUT
constexpr PinStatus_t HIGH
AH::function_traits< decltype(::pinMode)>::argument_t< 1 > PinMode_t
AH::function_traits< decltype(::digitalWrite)>::argument_t< 1 > PinStatus_t
constexpr PinMode_t INPUT_PULLUP
constexpr PinMode_t OUTPUT
uint16_t analog_t
The type returned from analogRead and similar functions.
constexpr pin_t NO_PIN
A special pin number that indicates an unused or invalid pin.
uint16_t pin_t
The type for Arduino pins (and ExtendedIOElement pins).
MCP23017RegAddr
Definition: MCP23017.ipp:5
@ INTCONB
Definition: MCP23017.ipp:15
@ IPOLA
Definition: MCP23017.ipp:8
@ INTCAPB
Definition: MCP23017.ipp:22
@ OLATA
Definition: MCP23017.ipp:25
@ GPPUA
Definition: MCP23017.ipp:17
@ IPOLB
Definition: MCP23017.ipp:9
@ GPIOB
Definition: MCP23017.ipp:24
@ GPINTENA
Definition: MCP23017.ipp:10
@ IODIRA
Definition: MCP23017.ipp:6
@ GPINTENB
Definition: MCP23017.ipp:11
@ IODIRB
Definition: MCP23017.ipp:7
@ GPPUB
Definition: MCP23017.ipp:18
@ DEFVALA
Definition: MCP23017.ipp:12
@ DEFVALB
Definition: MCP23017.ipp:13
@ GPIOA
Definition: MCP23017.ipp:23
@ IOCON
Definition: MCP23017.ipp:16
@ INTFA
Definition: MCP23017.ipp:19
@ INTCONA
Definition: MCP23017.ipp:14
@ INTFB
Definition: MCP23017.ipp:20
@ OLATB
Definition: MCP23017.ipp:26
@ INTCAPA
Definition: MCP23017.ipp:21
#define END_AH_NAMESPACE
#define BEGIN_AH_NAMESPACE
void setByte(uint16_t byteIndex, uint8_t value)
Set the byte at the given index.
Definition: BitArray.hpp:118
MCP23017(WireType &wire, uint8_t addressOffset=0, pin_t interruptPin=NO_PIN)
Constructor.
Definition: MCP23017.ipp:30
void updateBufferedPinModes()
Send the new pin modes to the chip after calling pinModeBuffered.
Definition: MCP23017.ipp:122
void updateBufferedOutputs() override
Write the internal state to the physical outputs.
Definition: MCP23017.ipp:97
void analogWriteBuffered(pin_t, analog_t) override
Write an analog (or PWM) value to the software buffer given pin.
Definition: MCP23017.ipp:75
PinStatus_t digitalReadBuffered(pin_t pin) override
Read the state of the given pin from the software buffer.
Definition: MCP23017.ipp:65
void pinModeBuffered(pin_t pin, PinMode_t mode) override
Set the mode of a given pin in the software buffer.
Definition: MCP23017.ipp:40
void updateBufferedInputs() override
Read the physical state into the input buffers.
Definition: MCP23017.ipp:108
void begin() override
Initialize the extended IO element.
Definition: MCP23017.ipp:80
analog_t analogReadBuffered(pin_t pin) override
Read the analog value of the given pin from the software buffer.
Definition: MCP23017.ipp:70
bool hasInputs() const
Check if any of the pins are configured as inputs.
Definition: MCP23017.ipp:141
void digitalWriteBuffered(pin_t pin, PinStatus_t status) override
Set the output of a given pin in the software buffer.
Definition: MCP23017.ipp:58
BitArray< 16 > bufferedPinModes
Definition: MCP23017.hpp:72
void writeI2C(const uint8_t(&values)[N])
Write any data to the MCP23017.
Definition: MCP23017.ipp:147
void digitalWriteBuffered(pin_t pin, PinStatus_t val)
A buffered ExtIO version of the Arduino function.
void pinMode(pin_t pin, PinMode_t mode)
An ExtIO version of the Arduino function.
PinStatus_t digitalRead(pin_t pin)
An ExtIO version of the Arduino function.