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.
 
 
 
 
 
 

155 lines
3.2 KiB

/*
GPIO MODULE
Copyright (C) 2017-2019 by Xose Pérez <xose dot perez at gmail dot com>
*/
#include "espurna.h"
// --------------------------------------------------------------------------
#include <bitset>
#include <utility>
#include "gpio_pin.h"
#include "mcp23s08_pin.h"
namespace settings {
namespace internal {
template <>
GpioType convert(const String& value) {
auto type = static_cast<GpioType>(value.toInt());
switch (type) {
case GpioType::Hardware:
case GpioType::Mcp23s08:
return type;
case GpioType::None:
break;
}
return GpioType::None;
}
} // namespace internal
} // namespace settings
namespace {
class GpioHardware : public GpioBase {
public:
constexpr static size_t Pins { 17ul };
using Mask = std::bitset<Pins>;
using Pin = GpioPin;
GpioHardware() {
// https://github.com/espressif/esptool/blob/f04d34bcab29ace798d2d3800ba87020cccbbfdd/esptool.py#L1060-L1070
// "One or the other efuse bit is set for ESP8285"
// https://github.com/espressif/ESP8266_RTOS_SDK/blob/3c055779e9793e5f082afff63a011d6615e73639/components/esp8266/include/esp8266/efuse_register.h#L20-L21
// "define EFUSE_IS_ESP8285 (1 << 4)"
const uint32_t efuse_blocks[4] {
READ_PERI_REG(0x3ff00050),
READ_PERI_REG(0x3ff00054),
READ_PERI_REG(0x3ff00058),
READ_PERI_REG(0x3ff0005c)
};
_esp8285 = (
(efuse_blocks[0] & (1 << 4))
|| (efuse_blocks[2] & (1 << 16))
);
}
const char* id() const override {
return "hardware";
}
size_t pins() const override {
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 {
switch (index) {
case 0 ... 5:
return true;
case 9:
case 10:
return _esp8285;
case 12 ... 16:
return true;
}
return false;
}
BasePinPtr pin(unsigned char index) {
return std::make_unique<GpioPin>(index);
}
private:
bool _esp8285 { false };
Mask _lock;
};
} // namespace
String BasePin::description() const {
char buffer[64];
snprintf_P(buffer, sizeof(buffer), PSTR("%s @ GPIO%02u"), id(), pin());
return buffer;
}
BasePin::~BasePin() {
}
GpioBase& hardwareGpio() {
static GpioHardware gpio;
return gpio;
}
GpioBase* gpioBase(GpioType type) {
GpioBase* ptr { nullptr };
switch (type) {
case GpioType::Hardware:
ptr = &hardwareGpio();
break;
case GpioType::Mcp23s08:
#if MCP23S08_SUPPORT
ptr = &mcp23s08Gpio();
#endif
break;
case GpioType::None:
break;
}
return ptr;
}
BasePinPtr gpioRegister(GpioBase& base, unsigned char gpio) {
BasePinPtr result;
if (gpioLock(base, gpio)) {
result = std::move(base.pin(gpio));
}
return result;
}
BasePinPtr gpioRegister(unsigned char gpio) {
return gpioRegister(hardwareGpio(), gpio);
}
void gpioSetup() {
}