Mirror of espurna firmware for wireless switches and more
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.

89 lines
2.5 KiB

  1. /*
  2. GPIO MODULE
  3. Copyright (C) 2017-2019 by Xose Pérez <xose dot perez at gmail dot com>
  4. */
  5. #include "gpio.h"
  6. #include <bitset>
  7. // We need to explicitly call the constructor, because we need to set the const `pin`:
  8. // https://isocpp.org/wiki/faq/multiple-inheritance#virtual-inheritance-ctors
  9. GpioPin::GpioPin(unsigned char pin) :
  10. BasePin(pin)
  11. {}
  12. inline void GpioPin::pinMode(int8_t mode) {
  13. ::pinMode(this->pin, mode);
  14. }
  15. inline void GpioPin::digitalWrite(int8_t val) {
  16. ::digitalWrite(this->pin, val);
  17. }
  18. inline int GpioPin::digitalRead() {
  19. return ::digitalRead(this->pin);
  20. }
  21. // --------------------------------------------------------------------------
  22. std::bitset<GpioPins> _gpio_locked;
  23. std::bitset<GpioPins> _gpio_available;
  24. bool gpioValid(unsigned char gpio) {
  25. if (gpio >= GpioPins) return false;
  26. return _gpio_available.test(gpio);
  27. }
  28. bool gpioGetLock(unsigned char gpio) {
  29. if (gpioValid(gpio)) {
  30. if (!_gpio_locked.test(gpio)) {
  31. _gpio_locked.set(gpio);
  32. DEBUG_MSG_P(PSTR("[GPIO] GPIO%u locked\n"), gpio);
  33. return true;
  34. }
  35. }
  36. DEBUG_MSG_P(PSTR("[GPIO] Failed getting lock for GPIO%u\n"), gpio);
  37. return false;
  38. }
  39. bool gpioReleaseLock(unsigned char gpio) {
  40. if (gpioValid(gpio)) {
  41. _gpio_locked.reset(gpio);
  42. DEBUG_MSG_P(PSTR("[GPIO] GPIO%u lock released\n"), gpio);
  43. return true;
  44. }
  45. DEBUG_MSG_P(PSTR("[GPIO] Failed releasing lock for GPIO%u\n"), gpio);
  46. return false;
  47. }
  48. void gpioSetup() {
  49. // https://github.com/espressif/esptool/blob/f04d34bcab29ace798d2d3800ba87020cccbbfdd/esptool.py#L1060-L1070
  50. // "One or the other efuse bit is set for ESP8285"
  51. // https://github.com/espressif/ESP8266_RTOS_SDK/blob/3c055779e9793e5f082afff63a011d6615e73639/components/esp8266/include/esp8266/efuse_register.h#L20-L21
  52. // "define EFUSE_IS_ESP8285 (1 << 4)"
  53. const uint32_t efuse_blocks[4] {
  54. READ_PERI_REG(0x3ff00050),
  55. READ_PERI_REG(0x3ff00054),
  56. READ_PERI_REG(0x3ff00058),
  57. READ_PERI_REG(0x3ff0005c)
  58. };
  59. const bool esp8285 = (
  60. (efuse_blocks[0] & (1 << 4))
  61. || (efuse_blocks[2] & (1 << 16))
  62. );
  63. // TODO: GPIO16 is only for basic I/O, gpioGetLock before attachInterrupt should check for that
  64. for (unsigned char pin=0; pin < GpioPins; ++pin) {
  65. if (pin <= 5) _gpio_available.set(pin);
  66. if (((pin == 9) || (pin == 10)) && (esp8285)) _gpio_available.set(pin);
  67. if (12 <= pin && pin <= 16) _gpio_available.set(pin);
  68. }
  69. }