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.

96 lines
3.8 KiB

  1. // -----------------------------------------------------------------------------
  2. // Abstract I2C sensor class (other sensor classes extend this class)
  3. // Copyright (C) 2017-2019 by Xose Pérez <xose dot perez at gmail dot com>
  4. // -----------------------------------------------------------------------------
  5. #if SENSOR_SUPPORT && ( I2C_SUPPORT || EMON_ANALOG_SUPPORT )
  6. #if I2C_USE_BRZO
  7. #define I2C_TRANS_SUCCESS 0 // All i2c commands were executed without errors
  8. #define I2C_TRANS_ERROR_BUS_NOT_FREE 1 // Bus not free, i.e. either SDA or SCL is low
  9. #define I2C_TRANS_ERROR_NACK_WRITE 2 // Not ACK ("NACK") by slave during write:
  10. // Either the slave did not respond to the given slave address; or the slave did not ACK a byte transferred by the master.
  11. #define I2C_TRANS_ERROR_NACK_READ 4 // Not ACK ("NACK") by slave during read,
  12. // i.e. slave did not respond to the given slave address
  13. #define I2C_TRANS_ERROR_CLOCK 8 // Clock Stretching by slave exceeded maximum clock stretching time. Most probably, there is a bus stall now!
  14. #define I2C_TRANS_ERROR_READ_NULL 16 // Read was called with 0 bytes to be read by the master. Command not sent to the slave, since this could yield to a bus stall
  15. #define I2C_TRANS_ERROR_TIMEOUT 32 // ACK Polling timeout exceeded
  16. #else // Wire
  17. #define I2C_TRANS_SUCCESS 0 // success
  18. #define I2C_TRANS_ERROR_BUFFER_OVERLOW 1 // data too long to fit in transmit buffer
  19. #define I2C_TRANS_ERROR_NACK_ADDRESS 2 // received NACK on transmit of address
  20. #define I2C_TRANS_ERROR_NACK_DATA 3 // received NACK on transmit of data
  21. #define I2C_TRANS_ERROR_OTHER 4 // other error
  22. #endif
  23. #pragma once
  24. #include "BaseSensor.h"
  25. template <typename T = BaseSensor>
  26. class I2CSensor : public T {
  27. public:
  28. void setAddress(unsigned char address) {
  29. if (_address == address) return;
  30. _address = address;
  31. T::_dirty = true;
  32. }
  33. unsigned char getAddress() {
  34. return _address;
  35. }
  36. // Descriptive name of the slot # index
  37. String slot(unsigned char index) {
  38. return static_cast<T*>(this)->description();
  39. };
  40. // Address of the sensor (it could be the GPIO or I2C address)
  41. String address(unsigned char index) {
  42. char buffer[5];
  43. snprintf(buffer, sizeof(buffer), "0x%02X", _address);
  44. return String(buffer);
  45. }
  46. protected:
  47. // Specific for I2C sensors
  48. unsigned char _begin_i2c(unsigned char address, size_t size, unsigned char * addresses) {
  49. // If we have already locked this address for this sensor quit
  50. if ((address > 0) && (address == _previous_address)) {
  51. return _previous_address;
  52. }
  53. // Check if we should release a previously locked address
  54. if ((_previous_address > 0) && (_previous_address != address)) {
  55. i2cReleaseLock(_previous_address);
  56. _previous_address = 0;
  57. }
  58. // If requesting a specific address, try to ger a lock to it
  59. if ((0 < address) && i2cGetLock(address)) {
  60. _previous_address = address;
  61. return _previous_address;
  62. }
  63. // If everything else fails, perform an auto-discover
  64. _previous_address = i2cFindAndLock(size, addresses);
  65. // Flag error
  66. if (0 == _previous_address) {
  67. T::_error = SENSOR_ERROR_I2C;
  68. }
  69. return _previous_address;
  70. }
  71. unsigned char _previous_address = 0;
  72. unsigned char _address = 0;
  73. };
  74. #endif // SENSOR_SUPPORT && I2C_SUPPORT