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.

171 lines
3.6 KiB

  1. /*
  2. MCP23S08 MODULE
  3. Copyright (C) 2020 by Eddi De Pieri <eddi at depieri dot com>
  4. Adapted from https://github.com/kmpelectronics/Arduino
  5. Copyright (C) 2016 Plamen Kovandjiev <p.kovandiev@kmpelectronics.eu> & Dimitar Antonov <d.antonov@kmpelectronics.eu>
  6. (ref. https://github.com/kmpelectronics/Arduino/blob/master/ProDinoWiFiEsp/src/PRODINoESP8266/src/KMPDinoWiFiESP.cpp)
  7. */
  8. #include "mcp23s08.h"
  9. #if MCP23S08_SUPPORT
  10. #include <SPI.h>
  11. #include <bitset>
  12. // TODO: check if this needed for SPI operation
  13. #define MCP23S08_CS_PIN 15
  14. // Known commands
  15. #define READ_CMD 0x41
  16. #define WRITE_CMD 0x40
  17. // Registers
  18. #define IODIR 0x00
  19. #define IPOL 0x01
  20. #define GPINTEN 0x02
  21. #define DEFVAL 0x03
  22. #define INTCON 0x04
  23. #define IOCON 0x05
  24. #define GPPU 0x06
  25. #define INTF 0x07
  26. #define INTCAP 0x08
  27. #define GPIO 0x09
  28. #define OLAT 0x0A
  29. static uint8_t _mcp23s08TxData[16] __attribute__((aligned(4)));
  30. static uint8_t _mcp23s08RxData[16] __attribute__((aligned(4)));
  31. void MCP23S08Setup()
  32. {
  33. DEBUG_MSG_P(PSTR("[MCP23S08] Initialize SPI bus\n"));
  34. // Expander SPI settings
  35. SPI.begin();
  36. SPI.setHwCs(true);
  37. SPI.setFrequency(1000000);
  38. SPI.setDataMode(SPI_MODE0);
  39. pinMode(MCP23S08_CS_PIN, OUTPUT);
  40. digitalWrite(MCP23S08_CS_PIN, HIGH);
  41. }
  42. /**
  43. * @brief Set a expander MCP23S08 the pin direction.
  44. *
  45. * @param pinNumber Pin number for set.
  46. * @param mode direction mode. 0 - INPUT, 1 - OUTPUT.
  47. *
  48. * @return void
  49. */
  50. void MCP23S08SetDirection(uint8_t pinNumber, uint8_t mode)
  51. {
  52. uint8_t registerData = MCP23S08ReadRegister(IODIR);
  53. if (INPUT == mode)
  54. {
  55. registerData |= (1 << pinNumber);
  56. }
  57. else
  58. {
  59. registerData &= ~(1 << pinNumber);
  60. }
  61. MCP23S08WriteRegister(IODIR, registerData);
  62. }
  63. /**
  64. * @brief Read an expander MCP23S08 a register.
  65. *
  66. * @param address A register address.
  67. *
  68. * @return The data from the register.
  69. */
  70. uint8_t MCP23S08ReadRegister(uint8_t address)
  71. {
  72. _mcp23s08TxData[0] = READ_CMD;
  73. _mcp23s08TxData[1] = address;
  74. digitalWrite(MCP23S08_CS_PIN, LOW);
  75. SPI.transferBytes(_mcp23s08TxData, _mcp23s08RxData, 3);
  76. digitalWrite(MCP23S08_CS_PIN, HIGH);
  77. return _mcp23s08RxData[2];
  78. }
  79. /**
  80. * @brief Write data in expander MCP23S08 register.
  81. *
  82. * @param address A register address.
  83. * @param data A byte for write.
  84. *
  85. * @return void.
  86. */
  87. void MCP23S08WriteRegister(uint8_t address, uint8_t data)
  88. {
  89. _mcp23s08TxData[0] = WRITE_CMD;
  90. _mcp23s08TxData[1] = address;
  91. _mcp23s08TxData[2] = data;
  92. digitalWrite(MCP23S08_CS_PIN, LOW);
  93. SPI.transferBytes(_mcp23s08TxData, _mcp23s08RxData, 3);
  94. digitalWrite(MCP23S08_CS_PIN, HIGH);
  95. }
  96. /**
  97. * @brief Set expander MCP23S08 pin state.
  98. *
  99. * @param pinNumber The number of pin to be set.
  100. * @param state The pin state, true - 1, false - 0.
  101. *
  102. * @return void
  103. */
  104. void MCP23S08SetPin(uint8_t pinNumber, bool state)
  105. {
  106. uint8_t registerData = MCP23S08ReadRegister(OLAT);
  107. if (state)
  108. {
  109. registerData |= (1 << pinNumber);
  110. }
  111. else
  112. {
  113. registerData &= ~(1 << pinNumber);
  114. }
  115. MCP23S08WriteRegister(OLAT, registerData);
  116. }
  117. /**
  118. * @brief Get MCP23S08 pin state.
  119. *
  120. * @param pinNumber The number of pin to get.
  121. *
  122. * @return State true - 1, false - 0.
  123. */
  124. bool MCP23S08GetPin(uint8_t pinNumber)
  125. {
  126. uint8_t registerData = MCP23S08ReadRegister(GPIO);
  127. return registerData & (1 << pinNumber);
  128. }
  129. /**
  130. * @brief Ensure pin number is valid.
  131. *
  132. * @param pinNumber The number of pin to be get.
  133. *
  134. * @return State true - 1, false - 0.
  135. */
  136. bool mcpGpioValid(unsigned char gpio)
  137. {
  138. return gpio < McpGpioPins;
  139. }
  140. #endif // MCP23S08_SUPPORT