forked from julianschuler/MCP23S08
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathMCP23S08.cpp
More file actions
158 lines (120 loc) · 3.91 KB
/
Copy pathMCP23S08.cpp
File metadata and controls
158 lines (120 loc) · 3.91 KB
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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
/**********************************************************************
*
* 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(SPIClass & spi,
uint8_t csPin,
uint8_t deviceAddr,
bool haen,
uint32_t spi_speed)
: spi(spi), csPin(csPin), haen(haen), spi_settings(spi_speed, MSBFIRST, SPI_MODE0) {
deviceOpcode |= ((deviceAddr & 0x03) << 1);
}
void MCP23S08::begin() {
// Why do we initialize the pin here
// yet expect the spi bus to be initialized?
pinMode(csPin, OUTPUT);
// enable chip hardware addresses
if (haen) {
spi.beginTransaction(spi_settings);
digitalWrite(csPin, LOW);
spi.transfer(0x40); // command write, address 0 (hardware addressing is disabled on POR)
spi.transfer(MCP23S08_IOCON);
spi.transfer(0x08);
digitalWrite(csPin, HIGH);
spi.endTransaction();
}
}
// reset all registers to default:
void MCP23S08::reset() {
spi.beginTransaction(spi_settings);
digitalWrite(csPin, LOW);
spi.transfer(deviceOpcode); // initialize transfer with opcode and R/W-flag cleared
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++) {
if (haen && (MCP23S08_IOCON == i))
spi.transfer(0x08); // enable hardware address (HAEN)
else
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(spi_settings);
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(spi_settings);
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;
}