Fork of the espurna firmware for `mhsw` switches
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

216 lines
4.4 KiB

/*
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 "mcp23s08_pin.h"
#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)));
namespace {
class GpioMcp23s08 : public GpioBase {
public:
constexpr static size_t Pins { 8ul };
using Pin = McpGpioPin;
using Mask = std::bitset<Pins>;
const char* id() const {
return "mcp23s08";
}
size_t pins() const {
return Pins;
}
bool lock(unsigned char index) const override {
return _lock[index];
}
void lock(unsigned char index, bool value) override {
_lock.set(index, value);
}
bool valid(unsigned char index) const override {
return (index < Pins);
}
BasePinPtr pin(unsigned char index) override {
return std::make_unique<McpGpioPin>(index);
}
private:
Mask _lock;
};
} // namespace
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;
}
GpioBase& mcp23s08Gpio() {
static GpioMcp23s08 gpio;
return gpio;
}
#endif // MCP23S08_SUPPORT