|
|
- /*
-
- MCP23S08 MODULE
-
- Copyright (C) 2020 by Eddi De Pieri <eddi at depieri dot com>
-
- Adapted from https://github.com/kmpelectronics/Arduino
- Copyright (C) 2016 Plamen Kovandjiev <p.kovandiev@kmpelectronics.eu> & Dimitar Antonov <d.antonov@kmpelectronics.eu>
-
- (ref. https://github.com/kmpelectronics/Arduino/blob/master/ProDinoWiFiEsp/src/PRODINoESP8266/src/KMPDinoWiFiESP.cpp)
-
- */
-
- #include "mcp23s08.h"
-
- #if MCP23S08_SUPPORT
-
- #include <SPI.h>
-
- #include <bitset>
-
- // TODO: check if this needed for SPI operation
- #define MCP23S08_CS_PIN 15
-
- // Known commands
- #define READ_CMD 0x41
- #define WRITE_CMD 0x40
-
- // Registers
- #define IODIR 0x00
- #define IPOL 0x01
- #define GPINTEN 0x02
- #define DEFVAL 0x03
- #define INTCON 0x04
- #define IOCON 0x05
- #define GPPU 0x06
- #define INTF 0x07
- #define INTCAP 0x08
- #define GPIO 0x09
- #define OLAT 0x0A
-
- static uint8_t _mcp23s08TxData[16] __attribute__((aligned(4)));
- static uint8_t _mcp23s08RxData[16] __attribute__((aligned(4)));
-
- McpGpioPin::McpGpioPin(unsigned char pin) :
- BasePin(pin)
- {}
-
- inline void McpGpioPin::pinMode(int8_t mode) {
- ::MCP23S08SetDirection(this->pin, mode);
- }
-
- inline void McpGpioPin::digitalWrite(int8_t val) {
- ::MCP23S08SetPin(this->pin, val);
- }
-
- inline int McpGpioPin::digitalRead() {
- return ::MCP23S08GetPin(this->pin);
- }
-
- void MCP23S08Setup()
- {
- DEBUG_MSG_P(PSTR("[MCP23S08] Initialize SPI bus\n"));
-
- // Expander SPI settings
- SPI.begin();
- SPI.setHwCs(true);
- SPI.setFrequency(1000000);
- SPI.setDataMode(SPI_MODE0);
-
- pinMode(MCP23S08_CS_PIN, OUTPUT);
- digitalWrite(MCP23S08_CS_PIN, HIGH);
- }
-
- /**
- * @brief Set a expander MCP23S08 the pin direction.
- *
- * @param pinNumber Pin number for set.
- * @param mode direction mode. 0 - INPUT, 1 - OUTPUT.
- *
- * @return void
- */
- void MCP23S08SetDirection(uint8_t pinNumber, uint8_t mode)
- {
- uint8_t registerData = MCP23S08ReadRegister(IODIR);
-
- if (INPUT == mode)
- {
- registerData |= (1 << pinNumber);
- }
- else
- {
- registerData &= ~(1 << pinNumber);
- }
-
- MCP23S08WriteRegister(IODIR, registerData);
- }
-
- /**
- * @brief Read an expander MCP23S08 a register.
- *
- * @param address A register address.
- *
- * @return The data from the register.
- */
- uint8_t MCP23S08ReadRegister(uint8_t address)
- {
- _mcp23s08TxData[0] = READ_CMD;
- _mcp23s08TxData[1] = address;
-
- digitalWrite(MCP23S08_CS_PIN, LOW);
- SPI.transferBytes(_mcp23s08TxData, _mcp23s08RxData, 3);
- digitalWrite(MCP23S08_CS_PIN, HIGH);
-
- return _mcp23s08RxData[2];
- }
-
- /**
- * @brief Write data in expander MCP23S08 register.
- *
- * @param address A register address.
- * @param data A byte for write.
- *
- * @return void.
- */
- void MCP23S08WriteRegister(uint8_t address, uint8_t data)
- {
- _mcp23s08TxData[0] = WRITE_CMD;
- _mcp23s08TxData[1] = address;
- _mcp23s08TxData[2] = data;
-
- digitalWrite(MCP23S08_CS_PIN, LOW);
- SPI.transferBytes(_mcp23s08TxData, _mcp23s08RxData, 3);
- digitalWrite(MCP23S08_CS_PIN, HIGH);
- }
-
- /**
- * @brief Set expander MCP23S08 pin state.
- *
- * @param pinNumber The number of pin to be set.
- * @param state The pin state, true - 1, false - 0.
- *
- * @return void
- */
- void MCP23S08SetPin(uint8_t pinNumber, bool state)
- {
- uint8_t registerData = MCP23S08ReadRegister(OLAT);
-
- if (state)
- {
- registerData |= (1 << pinNumber);
- }
- else
- {
- registerData &= ~(1 << pinNumber);
- }
-
- MCP23S08WriteRegister(OLAT, registerData);
- }
-
- /**
- * @brief Get MCP23S08 pin state.
- *
- * @param pinNumber The number of pin to get.
- *
- * @return State true - 1, false - 0.
- */
- bool MCP23S08GetPin(uint8_t pinNumber)
- {
- uint8_t registerData = MCP23S08ReadRegister(GPIO);
-
- return registerData & (1 << pinNumber);
- }
-
- /**
- * @brief Ensure pin number is valid.
- *
- * @param pinNumber The number of pin to be get.
- *
- * @return State true - 1, false - 0.
- */
- bool mcpGpioValid(unsigned char gpio)
- {
- return gpio < McpGpioPins;
- }
-
- #endif // MCP23S08_SUPPORT
|