/* GPIO MODULE Copyright (C) 2017-2019 by Xose PĂ©rez */ #include "espurna.h" // -------------------------------------------------------------------------- #include #include #include "gpio_pin.h" #include "mcp23s08_pin.h" namespace settings { namespace internal { template <> GpioType convert(const String& value) { auto type = static_cast(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; 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(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() { }