Control Surface
2.1.2
MIDI Control Surface library for Arduino
Toggle main menu visibility
Loading...
Searching...
No Matches
src
AH
Hardware
MCP23017Encoders.hpp
Go to the documentation of this file.
1
#pragma once
2
3
#include <
AH/Arduino-Wrapper.h
>
4
5
#include <
AH/Hardware/ExtendedInputOutput/ExtendedInputOutput.hpp
>
6
#include <
AH/Hardware/RegisterEncoders.hpp
>
7
#include <
AH/Settings/NamespaceSettings.hpp
>
8
9
BEGIN_AH_NAMESPACE
10
31
template
<
class
WireType,
class
EncoderPositionType = int32_t,
32
bool
InterruptSafe =
false
>
33
class
MCP23017Encoders
{
34
private
:
35
constexpr
static
uint8_t
I2C_BASE_ADDRESS
= 0x20;
36
37
WireType *
wire
;
38
uint8_t
address
;
39
pin_t
interrupt_pin
;
40
41
using
RegisterEncoderType
=
42
RegisterEncoders<uint16_t, 8, EncoderPositionType, InterruptSafe>
;
43
44
RegisterEncoderType
encs
;
45
46
protected
:
48
template
<
size_t
N>
49
void
writeI2C
(
const
uint8_t (&values)[N]) {
50
this->wire->beginTransmission(
address
);
51
this->wire->write(values, N);
52
this->wire->endTransmission();
53
}
54
63
template
<
class
... Args>
64
void
writeI2C
(uint8_t addr, Args... values) {
65
const
uint8_t v[] = {addr,
static_cast<
uint8_t
>
(values)...};
66
writeI2C
(v);
67
}
68
70
uint16_t
readGPIO
() {
71
// No need to specify the register address, since this was done in the
72
// begin method, and the MCP23017 mode was set to Byte mode with
73
// IOCON.BANK = 0 (see §3.2.1 in the datasheet).
74
//
75
// TODO:
76
// For some reason, it sometimes seems to mess up though, and it'll read
77
// the wrong register, so we'll select the register again (for now).
78
79
writeI2C
(0x12);
// GPIOA
80
81
this->wire->requestFrom(
address
,
size_t
(2));
82
uint8_t a = this->wire->read();
83
uint16_t b = this->wire->read();
84
return
a | (b << 8);
85
}
86
87
public
:
106
MCP23017Encoders
(WireType &
wire
, uint8_t addr_offset = 0,
107
pin_t
interrupt_pin
=
NO_PIN
)
108
:
wire
(&
wire
),
address
(
I2C_BASE_ADDRESS
| addr_offset),
109
interrupt_pin
(
interrupt_pin
) {}
110
125
void
begin
() {
126
// Set the IOCON register (configuration register)
127
writeI2C
(0x0A,
// IOCON register for BANK=0
128
0b01100100);
129
// │││││││└─ Unimplemented
130
// ││││││└── INTPOL = Active-low
131
// │││││└─── ODR = Open-drain output (overrides the INTPOL bit)
132
// ││││└──── HAEN = Disables the MCP23S17 address pins
133
// │││└───── DISSLW = Slew rate enabled
134
// ││└────── SEQOP = Sequential operation disabled, address pointer does not increment
135
// │└─────── MIRROR = The INT pins are internally connected
136
// └──────── BANK = The registers are in the same bank (addresses are sequential)
137
138
// Set all GPIO pins to input mode
139
writeI2C
(0x00,
// IODIRA
140
0xFF,
// input mode for GPIO A
141
0xFF);
// input mode for GPIO B
142
143
// Enable all pin change interrupts
144
writeI2C
(0x04,
// GPINTENA
145
0xFF,
// interrupt enable for GPIO A
146
0xFF);
// interrupt enable for GPIO B
147
148
// Enable all internal pullups
149
writeI2C
(0x0C,
// GPPUA
150
0xFF,
// pullup enable for GPIO A
151
0xFF);
// pullup enable for GPIO B
152
153
// Interrupts are configured in open-drain mode, so enable
154
// the internal pullup resistor on the Arduino pin that
155
// reads the interrupt pin.
156
if
(
interrupt_pin
!=
NO_PIN
)
157
ExtIO::pinMode
(
interrupt_pin
,
INPUT_PULLUP
);
158
159
// Set the address pointer to the GPIOA register.
160
// This means that subsequent reads will all toggle between the
161
// GPIOA and GPIOB register, so we can speedup reading the GPIO
162
// by not having to send an opcode/register address each time.
163
writeI2C
(0x12);
// GPIOA
164
166
encs
.reset(
readGPIO
());
167
}
168
179
void
update
() {
180
// Only update if a pin change interrupt happened
181
if
(
interrupt_pin
!=
NO_PIN
&&
182
ExtIO::digitalRead
(
interrupt_pin
) ==
HIGH
)
183
return
;
184
// Read both GPIO A and B
185
uint16_t newstate =
readGPIO
();
186
encs
.update(newstate);
187
}
188
199
EncoderPositionType
read
(uint8_t idx)
const
{
return
encs
.read(idx); }
200
211
EncoderPositionType
readAndReset
(uint8_t idx) {
212
return
encs
.readAndReset(idx);
213
}
214
225
void
write
(uint8_t idx, EncoderPositionType pos) {
encs
.write(idx, pos); }
226
231
using
MCP23017Encoder
=
typename
RegisterEncoderType::Encoder;
232
240
MCP23017Encoder
operator[]
(uint8_t index) {
return
encs
[index]; }
241
};
242
243
END_AH_NAMESPACE
NamespaceSettings.hpp
END_AH_NAMESPACE
#define END_AH_NAMESPACE
Definition
AH/Settings/NamespaceSettings.hpp:14
BEGIN_AH_NAMESPACE
#define BEGIN_AH_NAMESPACE
Definition
AH/Settings/NamespaceSettings.hpp:11
HIGH
constexpr PinStatus_t HIGH
Definition
Arduino-Hardware-Types.hpp:62
INPUT_PULLUP
constexpr PinMode_t INPUT_PULLUP
Definition
Arduino-Hardware-Types.hpp:66
Arduino-Wrapper.h
ExtendedInputOutput.hpp
RegisterEncoders.hpp
::MCP23017Encoders
Class for reading 8 rotary encoders using a MCP23017 I²C port expander.
Definition
MCP23017Encoders.hpp:33
AH::MCP23017Encoders::MCP23017Encoders
MCP23017Encoders(WireType &wire, uint8_t addr_offset=0, pin_t interrupt_pin=NO_PIN)
Constructor.
Definition
MCP23017Encoders.hpp:106
AH::MCP23017Encoders::encs
RegisterEncoderType encs
Definition
MCP23017Encoders.hpp:44
AH::MCP23017Encoders::MCP23017Encoder
typename RegisterEncoderType::Encoder MCP23017Encoder
Proxy to access a single encoder of the 8 encoders managed by MCP23017Encoders.
Definition
MCP23017Encoders.hpp:231
AH::MCP23017Encoders::read
EncoderPositionType read(uint8_t idx) const
Read the position of the given encoder.
Definition
MCP23017Encoders.hpp:199
AH::MCP23017Encoders::readGPIO
uint16_t readGPIO()
Read the state of all GPIO pins.
Definition
MCP23017Encoders.hpp:70
AH::MCP23017Encoders::I2C_BASE_ADDRESS
static constexpr uint8_t I2C_BASE_ADDRESS
Definition
MCP23017Encoders.hpp:35
AH::MCP23017Encoders::begin
void begin()
Initialize the MCP23017.
Definition
MCP23017Encoders.hpp:125
AH::MCP23017Encoders::wire
WireType * wire
Definition
MCP23017Encoders.hpp:37
AH::MCP23017Encoders::operator[]
MCP23017Encoder operator[](uint8_t index)
Get a proxy to one of the encoders managed by this MCP23017.
Definition
MCP23017Encoders.hpp:240
AH::MCP23017Encoders::readAndReset
EncoderPositionType readAndReset(uint8_t idx)
Read the position of the given encoder and reset it to zero.
Definition
MCP23017Encoders.hpp:211
AH::MCP23017Encoders::update
void update()
If the state of the MCP23017's GPIO changed, read the new state and update the encoder positions.
Definition
MCP23017Encoders.hpp:179
AH::MCP23017Encoders::interrupt_pin
pin_t interrupt_pin
Definition
MCP23017Encoders.hpp:39
AH::MCP23017Encoders::writeI2C
void writeI2C(uint8_t addr, Args... values)
Write any data to the MCP23017.
Definition
MCP23017Encoders.hpp:64
AH::MCP23017Encoders::RegisterEncoderType
RegisterEncoders< uint16_t, 8, EncoderPositionType, InterruptSafe > RegisterEncoderType
Definition
MCP23017Encoders.hpp:41
AH::MCP23017Encoders::write
void write(uint8_t idx, EncoderPositionType pos)
Set the position of the given encoder.
Definition
MCP23017Encoders.hpp:225
AH::MCP23017Encoders::address
uint8_t address
Definition
MCP23017Encoders.hpp:38
AH::MCP23017Encoders::writeI2C
void writeI2C(const uint8_t(&values)[N])
Write any data to the MCP23017.
Definition
MCP23017Encoders.hpp:49
AH::RegisterEncoders
Class for keeping track of the position of multiple rotary encoders.
Definition
RegisterEncoders.hpp:52
AH::ExtIO::pinMode
void pinMode(pin_t pin, PinMode_t mode)
An ExtIO version of the Arduino function.
Definition
ExtendedInputOutput.cpp:32
AH::ExtIO::digitalRead
PinStatus_t digitalRead(pin_t pin)
An ExtIO version of the Arduino function.
Definition
ExtendedInputOutput.cpp:54
AH::NO_PIN
constexpr pin_t NO_PIN
A special pin number that indicates an unused or invalid pin.
Definition
Hardware-Types.hpp:96
AH::ExtIO::pin_t
Type for storing pin numbers of Extended Input/Output elements.
Definition
Hardware-Types.hpp:25
Generated by
1.17.0