-
-
Notifications
You must be signed in to change notification settings - Fork 11
/
MCP23S17.h
166 lines (126 loc) · 4.7 KB
/
MCP23S17.h
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
159
160
161
162
163
164
165
#pragma once
//
// FILE: MCP23S17.h
// AUTHOR: Rob Tillaart
// VERSION: 0.6.0
// PURPOSE: Arduino library for SPI MCP23S17 16 channel port expander
// DATE: 2021-12-30
// URL: https://github.com/RobTillaart/MCP23S17
#include "Arduino.h"
#include "SPI.h"
#include "MCP23x17_registers.h"
#define MCP23S17_LIB_VERSION (F("0.6.0"))
// ERROR CODES
#define MCP23S17_OK 0x00
#define MCP23S17_PIN_ERROR 0x81
#define MCP23S17_SPI_ERROR 0x82
#define MCP23S17_VALUE_ERROR 0x83
#define MCP23S17_PORT_ERROR 0x84
#define MCP23S17_REGISTER_ERROR 0xFF
#define MCP23S17_INVALID_READ 0xFF
#ifndef __SPI_CLASS__
// MBED must be tested before RP2040
#if defined(ARDUINO_ARCH_MBED)
#define __SPI_CLASS__ SPIClass
#elif defined(ARDUINO_ARCH_RP2040)
#define __SPI_CLASS__ SPIClassRP2040
#else
#define __SPI_CLASS__ SPIClass
#endif
#endif
const uint32_t MCP23S17_TYP_SPI_SPEED = 8000000;
const uint32_t MCP23S17_MAX_SPI_SPEED = 10000000;
class MCP23S17
{
public:
// SOFTWARE SPI
MCP23S17(uint8_t select, uint8_t dataIn, uint8_t dataOut, uint8_t clock, uint8_t address = 0x00);
// HARDWARE SPI
MCP23S17(int select, __SPI_CLASS__ * spi);
MCP23S17(int select, int address = 0x00, __SPI_CLASS__ * spi = &SPI);
bool begin(bool pullup = true);
bool isConnected();
uint8_t getAddress(); // default returns 0x00
// single pin interface
// mode = INPUT, OUTPUT, INPUT_PULLUP (= same as INPUT)
// do not use 0, 1 for mode.
bool pinMode1(uint8_t pin, uint8_t mode);
bool write1(uint8_t pin, uint8_t value);
uint8_t read1(uint8_t pin);
bool setPolarity(uint8_t pin, bool reversed);
bool getPolarity(uint8_t pin, bool &reversed);
bool setPullup(uint8_t pin, bool pullup);
bool getPullup(uint8_t pin, bool &pullup);
// 8 pins interface
// port = 0..1
// mask = 0x00..0xFF bit pattern,
// bit 0 = output mode, bit 1 = input mode
// value = bit pattern.
bool pinMode8(uint8_t port, uint8_t mask);
bool write8(uint8_t port, uint8_t value);
int read8(uint8_t port);
bool setPolarity8(uint8_t port, uint8_t mask);
bool getPolarity8(uint8_t port, uint8_t &mask);
bool setPullup8(uint8_t port, uint8_t mask);
bool getPullup8(uint8_t port, uint8_t &mask);
// 16 pins interface
// mask = 0x0000..0xFFFF bit pattern
// bit 0 = output mode, bit 1 = input mode
// value = bit pattern.
bool pinMode16(uint16_t mask);
bool write16(uint16_t value);
uint16_t read16();
bool setPolarity16(uint16_t mask);
bool getPolarity16(uint16_t &mask);
bool setPullup16(uint16_t mask);
bool getPullup16(uint16_t &mask);
// INTERRUPTS (experimental)
// pin = 0..15, mode = { RISING, FALLING, CHANGE }
bool enableInterrupt(uint8_t pin, uint8_t mode);
bool disableInterrupt(uint8_t pin);
// mask = 0x0000..0xFFFF (overrides all earlier settings.
bool enableInterrupt16(uint16_t mask, uint8_t mode);
bool disableInterrupt16(uint16_t mask);
// which pins caused the INT?
uint16_t getInterruptFlagRegister();
uint16_t getInterruptCaptureRegister();
// polarity: 0 = LOW, 1 = HIGH, 2 = NONE/ODR
bool setInterruptPolarity(uint8_t polarity);
uint8_t getInterruptPolarity();
// merge INTA and INTB
bool mirrorInterrupts(bool on);
bool isMirroredInterrupts();
// SPI
// speed in Hz
void setSPIspeed(uint32_t speed);
uint32_t getSPIspeed() { return _SPIspeed; };
// debugging
bool usesHWSPI() { return _hwSPI; };
int lastError();
// set/clear IOCR bit fields
bool enableControlRegister(uint8_t mask);
bool disableControlRegister(uint8_t mask);
// 0.2.5 experimental
bool enableHardwareAddress();
bool disableHardwareAddress();
protected:
// access to low level registers (just make these functions public).
// USE WITH CARE !!!
bool writeReg(uint8_t reg, uint8_t value);
uint8_t readReg(uint8_t reg);
bool writeReg16(uint8_t reg, uint16_t value);
uint16_t readReg16(uint8_t reg);
uint8_t _address = 0;
uint8_t _select = 0;
uint8_t _dataOut = 0;
uint8_t _dataIn = 0;
uint8_t _clock = 0;
uint8_t _error = MCP23S17_OK;
bool _hwSPI = true;
// 10 MHz is maximum, 8 is a better clock divider on AVR.
uint32_t _SPIspeed = MCP23S17_TYP_SPI_SPEED;
__SPI_CLASS__ * _mySPI;
SPISettings _spi_settings;
uint8_t swSPI_transfer(uint8_t val);
};
// -- END OF FILE --