39 : m_SPIDevHandle(nullptr)
50 bool MCP23S17::begin(
int MISO,
int MOSI,
int CLK,
int CS,
int CSActiveState,
int host)
57 switch (getChipPackage()) {
66 if (CSActiveState == -1)
82 m_MISO = int2gpio(MISO);
83 m_MOSI = int2gpio(MOSI);
84 m_CLK = int2gpio(CLK);
86 m_SPIHost = (spi_host_device_t) host;
88 bool r = SPIBegin(CSActiveState);
92 m_IOCON[0] = MCP_IOCON_SEQOP;
94 r =
readReg(MCP_IOCON) == m_IOCON[0];
107 if (hwAddr < MCP_MAXDEVICES)
108 writeReg(MCP_IOCON, MCP_IOCON_SEQOP | MCP_IOCON_HAEN);
118 bool MCP23S17::SPIBegin(
int CSActiveState)
120 spi_bus_config_t busconf = { };
121 busconf.mosi_io_num = m_MOSI;
122 busconf.miso_io_num = m_MISO;
123 busconf.sclk_io_num = m_CLK;
124 busconf.quadwp_io_num = -1;
125 busconf.quadhd_io_num = -1;
126 busconf.flags = SPICOMMON_BUSFLAG_MASTER;
127 auto r = spi_bus_initialize(m_SPIHost, &busconf, MCP_DMACHANNEL);
128 if (r == ESP_OK || r == ESP_ERR_INVALID_STATE) {
129 spi_device_interface_config_t devconf = { };
131 devconf.clock_speed_hz = MCP_SPI_FREQ;
132 devconf.spics_io_num = m_CS;
133 devconf.flags = (CSActiveState == 1 ? SPI_DEVICE_POSITIVE_CS : 0);
134 devconf.queue_size = 1;
135 r = spi_bus_add_device(m_SPIHost, &devconf, &m_SPIDevHandle);
137 spi_bus_free(m_SPIHost);
144 void MCP23S17::SPIEnd()
146 if (m_SPIDevHandle) {
147 spi_bus_remove_device(m_SPIDevHandle);
148 m_SPIDevHandle =
nullptr;
149 spi_bus_free(m_SPIHost);
156 spi_device_acquire_bus(m_SPIDevHandle, portMAX_DELAY);
158 uint8_t txdata[3] = { (uint8_t)(0b01000000 | (hwAddr << 1)), addr, value };
159 spi_transaction_t ta;
163 ta.rx_buffer =
nullptr;
164 ta.tx_buffer = txdata;
165 spi_device_transmit(m_SPIDevHandle, &ta);
167 spi_device_release_bus(m_SPIDevHandle);
173 spi_device_acquire_bus(m_SPIDevHandle, portMAX_DELAY);
175 uint8_t txdata[3] = { (uint8_t)(0b01000001 | (hwAddr << 1)), addr };
176 uint8_t rxdata[3] = { 0 };
177 spi_transaction_t ta;
181 ta.rx_buffer = rxdata;
182 ta.tx_buffer = txdata;
184 if (spi_device_transmit(m_SPIDevHandle, &ta) == ESP_OK)
187 spi_device_release_bus(m_SPIDevHandle);
195 spi_device_acquire_bus(m_SPIDevHandle, portMAX_DELAY);
197 uint8_t txdata[4] = { (uint8_t)(0b01000000 | (hwAddr << 1)), addr, (uint8_t)(value & 0xff), (uint8_t)(value >> 8) };
198 spi_transaction_t ta;
202 ta.rx_buffer =
nullptr;
203 ta.tx_buffer = txdata;
204 spi_device_transmit(m_SPIDevHandle, &ta);
206 spi_device_release_bus(m_SPIDevHandle);
212 spi_device_acquire_bus(m_SPIDevHandle, portMAX_DELAY);
214 uint8_t txdata[4] = { (uint8_t)(0b01000001 | (hwAddr << 1)), addr };
215 uint8_t rxdata[4] = { 0 };
216 spi_transaction_t ta;
220 ta.rx_buffer = rxdata;
221 ta.tx_buffer = txdata;
223 if (spi_device_transmit(m_SPIDevHandle, &ta) == ESP_OK)
224 r = rxdata[2] | (rxdata[3] << 8);
226 spi_device_release_bus(m_SPIDevHandle);
234 writeReg(MCP_IOCON, value ? m_IOCON[hwAddr] | MCP_IOCON_MIRROR : m_IOCON[hwAddr] & ~MCP_IOCON_MIRROR, hwAddr);
240 writeReg(MCP_IOCON, value ? m_IOCON[hwAddr] | MCP_IOCON_ODR : m_IOCON[hwAddr] & ~MCP_IOCON_ODR, hwAddr);
246 writeReg(MCP_IOCON, value ? m_IOCON[hwAddr] | MCP_IOCON_INTPOL : m_IOCON[hwAddr] & ~MCP_IOCON_INTPOL, hwAddr);
252 uint8_t mask = MCP_GPIO2MASK(gpio);
254 uint8_t reg = MCP_GPIO2REG(MCP_IODIR, gpio);
260 reg = MCP_GPIO2REG(MCP_GPPU, gpio);
261 writeReg(reg, (
readReg(reg, hwAddr) & ~mask) | ((
int)pullup * mask), hwAddr);
267 uint8_t olat =
readReg(MCP_GPIO2REG(MCP_OLAT, gpio), hwAddr);
268 uint8_t mask = MCP_GPIO2MASK(gpio);
269 uint8_t reg = MCP_GPIO2REG(MCP_OLAT, gpio);
270 writeReg(reg, value ? olat | mask : olat & ~mask, hwAddr);
276 return readReg(MCP_GPIO2REG(MCP_GPIO, gpio), hwAddr) & MCP_GPIO2MASK(gpio);
282 uint8_t mask = MCP_GPIO2MASK(gpio);
286 writeReg(MCP_GPIO2REG(MCP_INTCON, gpio),
readReg(MCP_GPIO2REG(MCP_INTCON, gpio), hwAddr) | mask, hwAddr);
287 writeReg(MCP_GPIO2REG(MCP_DEFVAL, gpio), (
readReg(MCP_GPIO2REG(MCP_DEFVAL, gpio), hwAddr) & ~mask) | ((
int)defaultValue * mask), hwAddr);
290 writeReg(MCP_GPIO2REG(MCP_INTCON, gpio),
readReg(MCP_GPIO2REG(MCP_INTCON, gpio), hwAddr) & ~mask, hwAddr);
293 writeReg(MCP_GPIO2REG(MCP_GPINTEN, gpio),
readReg(MCP_GPIO2REG(MCP_GPINTEN, gpio), hwAddr) | mask, hwAddr);
299 uint8_t reg = MCP_GPIO2REG(MCP_GPINTEN, gpio);
308 writeReg(MCP_IOCON, m_IOCON[hwAddr] | MCP_IOCON_SEQOP | MCP_IOCON_BANK);
310 spi_device_acquire_bus(m_SPIDevHandle, portMAX_DELAY);
312 spi_transaction_ext_t ta = { };
315 ta.base.cmd = 0b01000000 | (hwAddr << 1);
316 ta.base.addr = MCP_BNK1_OLAT + port * 0x10;
317 ta.base.flags = SPI_TRANS_VARIABLE_CMD | SPI_TRANS_VARIABLE_ADDR;
318 ta.base.length = 16 + 8 * length;
319 ta.base.rxlength = 0;
320 ta.base.rx_buffer =
nullptr;
321 ta.base.tx_buffer = buffer;
322 spi_device_polling_transmit(m_SPIDevHandle, (spi_transaction_t*) &ta);
324 spi_device_release_bus(m_SPIDevHandle);
327 writeReg(MCP_BNK1_IOCON, m_IOCON[hwAddr]);
335 writeReg(MCP_IOCON, m_IOCON[hwAddr] | MCP_IOCON_SEQOP | MCP_IOCON_BANK);
337 spi_device_acquire_bus(m_SPIDevHandle, portMAX_DELAY);
339 spi_transaction_ext_t ta = { };
342 ta.base.cmd = 0b01000001 | (hwAddr << 1);
343 ta.base.addr = MCP_BNK1_GPIO + port * 0x10;
344 ta.base.flags = SPI_TRANS_VARIABLE_CMD | SPI_TRANS_VARIABLE_ADDR;
345 ta.base.length = 16 + 8 * length;
346 ta.base.rxlength = 8 * length;
347 ta.base.rx_buffer = buffer;
348 ta.base.tx_buffer =
nullptr;
349 spi_device_polling_transmit(m_SPIDevHandle, (spi_transaction_t*) &ta);
351 spi_device_release_bus(m_SPIDevHandle);
354 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 initDevice(uint8_t hwAddr)
Initializes additional MCP23S17 devices connected to the same SPI bus but with a different hardware a...
void enableINTMirroring(bool value, uint8_t hwAddr=0)
Enables/disables INTs pins mirroring.
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.