-
Notifications
You must be signed in to change notification settings - Fork 0
/
MCP23S08.cpp
134 lines (98 loc) · 3.31 KB
/
MCP23S08.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
/**********************************************************************
*
* This is the C++ part of the MCP23S08 library.
* See MCP23S08.h and the example files for a full documentation.
*
*********************************************************************/
#include "MCP23S08.h"
/*##################################### PUBLIC FUNCTIONS #####################################*/
MCP23S08::MCP23S08(uint8_t csPin) : csPin(csPin) {}
MCP23S08::MCP23S08(uint8_t csPin, uint8_t deviceAddr) : csPin(csPin) {
deviceOpcode |= ((deviceAddr & 0x03) << 1);
}
void MCP23S08::begin() {
SPI.beginTransaction(SPISettings(10000000, MSBFIRST, SPI_MODE0));
pinMode(csPin, OUTPUT);
digitalWrite(csPin, LOW);
// reset all registers to default:
SPI.transfer(MCP23S08_IODIR); //set address pointer to first register
SPI.transfer(0xFF); // reset first register
for (uint8_t i = 0; i < MCP23S08_OLAT; i++) {
SPI.transfer(0x00); // reset other 10 registers
}
digitalWrite(csPin, HIGH);
SPI.endTransaction();
}
bool MCP23S08::digitalReadIO(uint8_t pin) {
if (pin > 7) {
return 0;
}
return (getInputStates() >> pin) & 1;
}
void MCP23S08::digitalWriteIO(uint8_t pin, bool state) {
if (pin > 7) {
return;
}
setOutputStates((getOutputStates() & ~(1 << pin)) | (state << pin));
}
void MCP23S08::pinModeIO(uint8_t pin, uint8_t mode) {
if (pin > 7) {
return;
}
switch (mode) {
case INPUT:
setPinModes(getPinModes() & ~(1 << pin)); // set pin to input
enablePullups(getEnabledPullups() & ~(1 << pin)); // disable pullup for pin
break;
case OUTPUT:
setPinModes(getPinModes() | (1 << pin)); // set pin to output
enablePullups(getEnabledPullups() & ~(1 << pin)); // disable pullup for pin
break;
case INPUT_PULLUP:
setPinModes(getPinModes() & ~(1 << pin)); // set pin to input
enablePullups(getEnabledPullups() | (1 << pin)); // enable pullup for pin
break;
}
}
void MCP23S08::setOutputStates(uint8_t states) {
writeRegister(MCP23S08_OLAT, states);
}
void MCP23S08::setPinModes(uint8_t modes) {
writeRegister(MCP23S08_IODIR, ~(modes)); // inverted to match IDE defaults
}
void MCP23S08::enablePullups(uint8_t enables) {
writeRegister(MCP23S08_GPPU, enables);
}
uint8_t MCP23S08::getInputStates() {
return readRegister(MCP23S08_GPIO);
}
uint8_t MCP23S08::getOutputStates() {
return readRegister(MCP23S08_OLAT);
}
uint8_t MCP23S08::getPinModes() {
return ~(readRegister(MCP23S08_IODIR)); // inverted to match IDE defaults
}
uint8_t MCP23S08::getEnabledPullups() {
return readRegister(MCP23S08_GPPU);
}
/*##################################### PRIVATE FUNCTIONS #####################################*/
void MCP23S08::writeRegister(uint8_t address, uint8_t data) {
SPI.beginTransaction(SPISettings(10000000, MSBFIRST, SPI_MODE0));
digitalWrite(csPin, LOW);
SPI.transfer(deviceOpcode); // initialize transfer with opcode and R/W-flag cleared
SPI.transfer(address);
SPI.transfer(data);
digitalWrite(csPin, HIGH);
SPI.endTransaction();
}
uint8_t MCP23S08::readRegister(uint8_t address) {
uint8_t data;
SPI.beginTransaction(SPISettings(10000000, MSBFIRST, SPI_MODE0));
digitalWrite(csPin, LOW);
SPI.transfer(deviceOpcode | 1); // initialize transfer with opcode and R/W-flag set
SPI.transfer(address);
data = SPI.transfer(0);
digitalWrite(csPin, HIGH);
SPI.endTransaction();
return data;
}