29 #include "freertos/FreeRTOS.h" 30 #include "freertos/task.h" 42 : m_SPIDevHandle(nullptr)
53 bool MCP23S17::begin(
int MISO,
int MOSI,
int CLK,
int CS,
int CSActiveState,
int host)
60 switch (getChipPackage()) {
69 if (CSActiveState == -1)
85 m_MISO = int2gpio(MISO);
86 m_MOSI = int2gpio(MOSI);
87 m_CLK = int2gpio(CLK);
89 m_SPIHost = (spi_host_device_t) host;
91 bool r = SPIBegin(CSActiveState) &&
initDevice(0);
104 if (hwAddr < MCP_MAXDEVICES) {
105 m_IOCON[hwAddr] = MCP_IOCON_SEQOP | MCP_IOCON_HAEN;
106 writeReg(MCP_IOCON, m_IOCON[hwAddr], hwAddr);
107 r =
readReg(MCP_IOCON, hwAddr) == m_IOCON[hwAddr];
119 bool MCP23S17::SPIBegin(
int CSActiveState)
121 spi_bus_config_t busconf = { };
122 busconf.mosi_io_num = m_MOSI;
123 busconf.miso_io_num = m_MISO;
124 busconf.sclk_io_num = m_CLK;
125 busconf.quadwp_io_num = -1;
126 busconf.quadhd_io_num = -1;
127 busconf.flags = SPICOMMON_BUSFLAG_MASTER;
128 auto r = spi_bus_initialize(m_SPIHost, &busconf, MCP_DMACHANNEL);
129 if (r == ESP_OK || r == ESP_ERR_INVALID_STATE) {
130 spi_device_interface_config_t devconf = { };
132 devconf.clock_speed_hz = MCP_SPI_FREQ;
133 devconf.spics_io_num = m_CS;
134 devconf.flags = (CSActiveState == 1 ? SPI_DEVICE_POSITIVE_CS : 0);
135 devconf.queue_size = 1;
136 r = spi_bus_add_device(m_SPIHost, &devconf, &m_SPIDevHandle);
137 if (r != ESP_OK && !FileBrowser::mountedSDCard())
138 spi_bus_free(m_SPIHost);
145 void MCP23S17::SPIEnd()
147 if (m_SPIDevHandle) {
148 spi_bus_remove_device(m_SPIDevHandle);
149 m_SPIDevHandle =
nullptr;
150 if (!FileBrowser::mountedSDCard())
151 spi_bus_free(m_SPIHost);
158 spi_device_acquire_bus(m_SPIDevHandle, portMAX_DELAY);
160 uint8_t txdata[3] = { (uint8_t)(0b01000000 | (hwAddr << 1)), addr, value };
161 spi_transaction_t ta;
165 ta.rx_buffer =
nullptr;
166 ta.tx_buffer = txdata;
167 spi_device_transmit(m_SPIDevHandle, &ta);
169 spi_device_release_bus(m_SPIDevHandle);
175 spi_device_acquire_bus(m_SPIDevHandle, portMAX_DELAY);
177 uint8_t txdata[3] = { (uint8_t)(0b01000001 | (hwAddr << 1)), addr };
178 uint8_t rxdata[3] = { 0 };
179 spi_transaction_t ta;
183 ta.rx_buffer = rxdata;
184 ta.tx_buffer = txdata;
186 if (spi_device_transmit(m_SPIDevHandle, &ta) == ESP_OK)
189 spi_device_release_bus(m_SPIDevHandle);
197 spi_device_acquire_bus(m_SPIDevHandle, portMAX_DELAY);
199 uint8_t txdata[4] = { (uint8_t)(0b01000000 | (hwAddr << 1)), addr, (uint8_t)(value & 0xff), (uint8_t)(value >> 8) };
200 spi_transaction_t ta;
204 ta.rx_buffer =
nullptr;
205 ta.tx_buffer = txdata;
206 spi_device_transmit(m_SPIDevHandle, &ta);
208 spi_device_release_bus(m_SPIDevHandle);
214 spi_device_acquire_bus(m_SPIDevHandle, portMAX_DELAY);
216 uint8_t txdata[4] = { (uint8_t)(0b01000001 | (hwAddr << 1)), addr };
217 uint8_t rxdata[4] = { 0 };
218 spi_transaction_t ta;
222 ta.rx_buffer = rxdata;
223 ta.tx_buffer = txdata;
225 if (spi_device_transmit(m_SPIDevHandle, &ta) == ESP_OK)
226 r = rxdata[2] | (rxdata[3] << 8);
228 spi_device_release_bus(m_SPIDevHandle);
236 writeReg(MCP_IOCON, value ? m_IOCON[hwAddr] | MCP_IOCON_MIRROR : m_IOCON[hwAddr] & ~MCP_IOCON_MIRROR, hwAddr);
242 writeReg(MCP_IOCON, value ? m_IOCON[hwAddr] | MCP_IOCON_ODR : m_IOCON[hwAddr] & ~MCP_IOCON_ODR, hwAddr);
248 writeReg(MCP_IOCON, value ? m_IOCON[hwAddr] | MCP_IOCON_INTPOL : m_IOCON[hwAddr] & ~MCP_IOCON_INTPOL, hwAddr);
254 uint8_t mask = MCP_GPIO2MASK(gpio);
256 uint8_t reg = MCP_GPIO2REG(MCP_IODIR, gpio);
262 reg = MCP_GPIO2REG(MCP_GPPU, gpio);
263 writeReg(reg, (
readReg(reg, hwAddr) & ~mask) | ((
int)pullup * mask), hwAddr);
269 uint8_t olat =
readReg(MCP_GPIO2REG(MCP_OLAT, gpio), hwAddr);
270 uint8_t mask = MCP_GPIO2MASK(gpio);
271 uint8_t reg = MCP_GPIO2REG(MCP_OLAT, gpio);
272 writeReg(reg, value ? olat | mask : olat & ~mask, hwAddr);
278 return readReg(MCP_GPIO2REG(MCP_GPIO, gpio), hwAddr) & MCP_GPIO2MASK(gpio);
284 uint8_t mask = MCP_GPIO2MASK(gpio);
288 writeReg(MCP_GPIO2REG(MCP_INTCON, gpio),
readReg(MCP_GPIO2REG(MCP_INTCON, gpio), hwAddr) | mask, hwAddr);
289 writeReg(MCP_GPIO2REG(MCP_DEFVAL, gpio), (
readReg(MCP_GPIO2REG(MCP_DEFVAL, gpio), hwAddr) & ~mask) | ((
int)defaultValue * mask), hwAddr);
292 writeReg(MCP_GPIO2REG(MCP_INTCON, gpio),
readReg(MCP_GPIO2REG(MCP_INTCON, gpio), hwAddr) & ~mask, hwAddr);
295 writeReg(MCP_GPIO2REG(MCP_GPINTEN, gpio),
readReg(MCP_GPIO2REG(MCP_GPINTEN, gpio), hwAddr) | mask, hwAddr);
301 uint8_t reg = MCP_GPIO2REG(MCP_GPINTEN, gpio);
310 writeReg(MCP_IOCON, m_IOCON[hwAddr] | MCP_IOCON_SEQOP | MCP_IOCON_BANK);
312 spi_device_acquire_bus(m_SPIDevHandle, portMAX_DELAY);
314 spi_transaction_ext_t ta = { };
317 ta.base.cmd = 0b01000000 | (hwAddr << 1);
318 ta.base.addr = MCP_BNK1_OLAT + port * 0x10;
319 ta.base.flags = SPI_TRANS_VARIABLE_CMD | SPI_TRANS_VARIABLE_ADDR;
320 ta.base.length = 16 + 8 * length;
321 ta.base.rxlength = 0;
322 ta.base.rx_buffer =
nullptr;
323 ta.base.tx_buffer = buffer;
324 spi_device_polling_transmit(m_SPIDevHandle, (spi_transaction_t*) &ta);
326 spi_device_release_bus(m_SPIDevHandle);
329 writeReg(MCP_BNK1_IOCON, m_IOCON[hwAddr]);
337 writeReg(MCP_IOCON, m_IOCON[hwAddr] | MCP_IOCON_SEQOP | MCP_IOCON_BANK);
339 spi_device_acquire_bus(m_SPIDevHandle, portMAX_DELAY);
341 spi_transaction_ext_t ta = { };
344 ta.base.cmd = 0b01000001 | (hwAddr << 1);
345 ta.base.addr = MCP_BNK1_GPIO + port * 0x10;
346 ta.base.flags = SPI_TRANS_VARIABLE_CMD | SPI_TRANS_VARIABLE_ADDR;
347 ta.base.length = 16 + 8 * length;
348 ta.base.rxlength = 8 * length;
349 ta.base.rx_buffer = buffer;
350 ta.base.tx_buffer =
nullptr;
351 spi_device_polling_transmit(m_SPIDevHandle, (spi_transaction_t*) &ta);
353 spi_device_release_bus(m_SPIDevHandle);
356 writeReg(MCP_BNK1_IOCON, m_IOCON[hwAddr]);
bool readGPIO(int gpio, uint8_t hwAddr=0)
Reads input status of a pin.
void writeReg16(uint8_t addr, uint16_t value, uint8_t hwAddr=0)
Writes 16 bit value to two consecutive registers.
uint8_t readReg(uint8_t addr, uint8_t hwAddr=0)
Reads 8 bit value from an internal register.
MCPDir
Represents GPIO directioon.
uint8_t readPort(int port, uint8_t hwAddr=0)
Gets status of input pins of specified port.
bool begin(int MISO=-1, int MOSI=-1, int CLK=-1, int CS=-1, int CSActiveState=-1, int host=HSPI_HOST)
Initializes MCP23S17 driver.
void writeGPIO(int gpio, bool value, uint8_t hwAddr=0)
Sets output status of a pin.
void disableInterrupt(int gpio, uint8_t hwAddr=0)
Disables any interrupt on the specified pin.
void end()
Deinitializes MCP23S17 driver.
void writeReg(uint8_t addr, uint8_t value, uint8_t hwAddr=0)
Writes 8 bit value to an internal register.
void enableINTOpenDrain(bool value, uint8_t hwAddr=0)
Enables/disables the INT pin open-drain.
MCPIntTrigger
Represents interrupt trigger mode.
This file contains the MCP23S17 driver class.
void setINTActiveHigh(bool value, uint8_t hwAddr=0)
Sets the polarity of the INT pins.
void configureGPIO(int gpio, MCPDir dir, bool pullup=false, uint8_t hwAddr=0)
Configure a pin direction and pullup.
void writePort(int port, uint8_t value, uint8_t hwAddr=0)
Sets status of output pins of specified port.
void enableINTMirroring(bool value, uint8_t hwAddr=0)
Enables/disables INTs pins mirroring.
bool initDevice(uint8_t hwAddr)
Initializes additional MCP23S17 devices connected to the same SPI bus but with a different hardware a...
uint16_t readReg16(uint8_t addr, uint8_t hwAddr=0)
Reads 16 bit value from two consecutive registers.
void enableInterrupt(int gpio, MCPIntTrigger trigger, bool defaultValue=false, uint8_t hwAddr=0)
Enables interrupt on the specific pin.