diff --git a/code/espurna/config/prototypes.h b/code/espurna/config/prototypes.h index ee7a97a8..31aabfcc 100644 --- a/code/espurna/config/prototypes.h +++ b/code/espurna/config/prototypes.h @@ -66,12 +66,19 @@ unsigned char i2cFindAndLock(size_t size, unsigned char * addresses); bool i2cGetLock(unsigned char address); bool i2cReleaseLock(unsigned char address); +void i2c_write_buffer(uint8_t address, uint8_t * buffer, size_t len); +void i2c_write_uint8(uint8_t address, uint8_t value); void i2c_write_uint8(uint8_t address, uint8_t reg, uint8_t value); +void i2c_write_uint16(uint8_t address, uint16_t value); +void i2c_write_uint16(uint8_t address, uint8_t reg, uint16_t value); +uint8_t i2c_read_uint8(uint8_t address); uint8_t i2c_read_uint8(uint8_t address, uint8_t reg); +uint16_t i2c_read_uint16(uint8_t address); uint16_t i2c_read_uint16(uint8_t address, uint8_t reg); uint16_t i2c_read_uint16_le(uint8_t address, uint8_t reg); int16_t i2c_read_int16(uint8_t address, uint8_t reg); int16_t i2c_read_int16_le(uint8_t address, uint8_t reg); +void i2c_read_buffer(uint8_t address, uint8_t * buffer, size_t len); // ----------------------------------------------------------------------------- // GPIO diff --git a/code/espurna/config/sensors.h b/code/espurna/config/sensors.h index 1b798bf8..bf59d731 100644 --- a/code/espurna/config/sensors.h +++ b/code/espurna/config/sensors.h @@ -272,7 +272,7 @@ #define EMON_ADS1X15_I2C_ADDRESS 0x00 // 0x00 means auto #define EMON_ADS1X15_TYPE ADS1X15_CHIP_ADS1115 #define EMON_ADS1X15_GAIN ADS1X15_REG_CONFIG_PGA_4_096V -#define EMON_ADS1X15_MASK 0x0F // A0=1 A1=2 A2=4 A4=8 +#define EMON_ADS1X15_MASK 0x0F // A0=1 A1=2 A2=4 A3=8 #if EMON_ADS1X15_SUPPORT #undef I2C_SUPPORT diff --git a/code/espurna/i2c.ino b/code/espurna/i2c.ino index 2e7a237b..0c1b2d46 100644 --- a/code/espurna/i2c.ino +++ b/code/espurna/i2c.ino @@ -108,38 +108,142 @@ int _i2cClearbus(int sda, int scl) { // I2C API // --------------------------------------------------------------------- -void i2c_write_uint8(uint8_t address, uint8_t reg, uint8_t value) { +#if I2C_USE_BRZO + +void i2c_write_buffer(uint8_t address, uint8_t * buffer, size_t len) { + brzo_i2c_start_transaction(_address, _i2c_scl_frequency); + brzo_i2c_write_uint8(buffer, len, false); + brzo_i2c_end_transaction(); +} + +void i2c_write_uint8(uint8_t address, uint8_t value) { + uint8_t buffer[1] = {value}; + brzo_i2c_start_transaction(_address, _i2c_scl_frequency); + brzo_i2c_write_uint8(buffer, 1, false); + brzo_i2c_end_transaction(); +} + +uint8_t i2c_read_uint8(uint8_t address) { + uint8_t buffer[1] = {reg}; + brzo_i2c_start_transaction(_address, _i2c_scl_frequency); + brzo_i2c_read(buffer, 1, false); + brzo_i2c_end_transaction(); + return buffer[0]; +}; + +uint8_t i2c_read_uint8(uint8_t address, uint8_t reg) { + uint8_t buffer[1] = {reg}; + brzo_i2c_start_transaction(_address, _i2c_scl_frequency); + brzo_i2c_write_uint8(buffer, 1, false); + brzo_i2c_read(buffer, 1, false); + brzo_i2c_end_transaction(); + return buffer[0]; +}; + +uint16_t i2c_read_uint16(uint8_t address) { + uint8_t buffer[2] = {reg, 0}; + brzo_i2c_start_transaction(_address, _i2c_scl_frequency); + brzo_i2c_read(buffer, 2, false); + brzo_i2c_end_transaction(); + return (buffer[0] * 256) | buffer[1]; +}; + +uint16_t i2c_read_uint16(uint8_t address, uint8_t reg) { + uint8_t buffer[2] = {reg, 0}; + brzo_i2c_start_transaction(_address, _i2c_scl_frequency); + brzo_i2c_write_uint8(buffer, 1, false); + brzo_i2c_read(buffer, 2, false); + brzo_i2c_end_transaction(); + return (buffer[0] * 256) | buffer[1]; +}; + +void i2c_read_buffer(uint8_t address, uint8_t * buffer, size_t len) { + brzo_i2c_start_transaction(address, _i2c_scl_frequency); + brzo_i2c_read(buffer, len, false); + brzo_i2c_end_transaction(); +} + +#else // not I2C_USE_BRZO + +void i2c_write_buffer(uint8_t address, uint8_t * buffer, size_t len) { + Wire.beginTransmission((uint8_t) address); + Wire.write(buffer, len); + Wire.endTransmission(); +} + +void i2c_write_uint8(uint8_t address, uint8_t value) { Wire.beginTransmission((uint8_t) address); - Wire.write((uint8_t) reg); Wire.write((uint8_t) value); Wire.endTransmission(); } +uint8_t i2c_read_uint8(uint8_t address) { + uint8_t value; + Wire.beginTransmission((uint8_t) address); + Wire.requestFrom((uint8_t) address, (uint8_t) 1); + value = Wire.read(); + Wire.endTransmission(); + return value; +}; + uint8_t i2c_read_uint8(uint8_t address, uint8_t reg) { uint8_t value; Wire.beginTransmission((uint8_t) address); Wire.write((uint8_t) reg); Wire.endTransmission(); - Wire.requestFrom((uint8_t)address, (uint8_t) 1); + Wire.requestFrom((uint8_t) address, (uint8_t) 1); value = Wire.read(); Wire.endTransmission(); return value; }; +uint16_t i2c_read_uint16(uint8_t address) { + uint16_t value; + Wire.beginTransmission((uint8_t) address); + Wire.requestFrom((uint8_t) address, (uint8_t) 2); + value = (Wire.read() * 256) | Wire.read(); + Wire.endTransmission(); + return value; +}; + uint16_t i2c_read_uint16(uint8_t address, uint8_t reg) { uint16_t value; Wire.beginTransmission((uint8_t) address); Wire.write((uint8_t) reg); Wire.endTransmission(); Wire.requestFrom((uint8_t) address, (uint8_t) 2); - value = (Wire.read() << 8) | Wire.read(); + value = (Wire.read() * 256) | Wire.read(); Wire.endTransmission(); return value; }; +void i2c_read_buffer(uint8_t address, uint8_t * buffer, size_t len) { + Wire.beginTransmission((uint8_t) address); + Wire.requestFrom(address, (uint8_t) len); + for (int i=0; i> 8, value & 0xFF}; + i2c_write_buffer(address, buffer, 3); +} + +void i2c_write_uint16(uint8_t address, uint16_t value) { + uint8_t buffer[2] = {value >> 8, value & 0xFF}; + i2c_write_buffer(address, buffer, 2); +} + uint16_t i2c_read_uint16_le(uint8_t address, uint8_t reg) { uint16_t temp = i2c_read_uint16(address, reg); - return (temp >> 8) | (temp << 8); + return (temp / 256) | (temp * 256); }; int16_t i2c_read_int16(uint8_t address, uint8_t reg) { diff --git a/code/espurna/sensors/BH1750Sensor.h b/code/espurna/sensors/BH1750Sensor.h index 47a84927..c4bbe8fe 100644 --- a/code/espurna/sensors/BH1750Sensor.h +++ b/code/espurna/sensors/BH1750Sensor.h @@ -9,11 +9,6 @@ #include "Arduino.h" #include "I2CSensor.h" -#if I2C_USE_BRZO -#include -#else -#include -#endif #define BH1750_CONTINUOUS_HIGH_RES_MODE 0x10 // Start measurement at 1lx resolution. Measurement time is approx 120ms. #define BH1750_CONTINUOUS_HIGH_RES_MODE_2 0x11 // Start measurement at 0.5lx resolution. Measurement time is approx 120ms. @@ -99,23 +94,11 @@ class BH1750Sensor : public I2CSensor { protected: void _configure() { - #if I2C_USE_BRZO - uint8_t buffer[1] = {_mode}; - brzo_i2c_start_transaction(_address, I2C_SCL_FREQUENCY); - brzo_i2c_write(buffer, 1, false); - brzo_i2c_end_transaction(); - #else - Wire.beginTransmission(_address); - Wire.write(_mode); - Wire.endTransmission(); - #endif + i2c_write_uint8(_address, _mode); } double _read() { - double level; - uint8_t buffer[2]; - // For one-shot modes reconfigure sensor & wait for conversion if (_mode & 0x20) { @@ -131,19 +114,7 @@ class BH1750Sensor : public I2CSensor { } - #if I2C_USE_BRZO - brzo_i2c_start_transaction(_address, I2C_SCL_FREQUENCY); - brzo_i2c_read(buffer, 2, false); - brzo_i2c_end_transaction(); - #else - Wire.beginTransmission(_address); - Wire.requestFrom(_address, (unsigned char) 2); - buffer[0] = Wire.read(); - buffer[1] = Wire.read(); - Wire.endTransmission(); - #endif - - level = buffer[0] * 256 + buffer[1]; + double level = (double) i2c_read_uint16(_address); return level / 1.2; } diff --git a/code/espurna/sensors/EmonADC121Sensor.h b/code/espurna/sensors/EmonADC121Sensor.h index d96d4aec..f413e345 100644 --- a/code/espurna/sensors/EmonADC121Sensor.h +++ b/code/espurna/sensors/EmonADC121Sensor.h @@ -10,12 +10,6 @@ #include "Arduino.h" #include "EmonSensor.h" -#if I2C_USE_BRZO -#include -#else -#include -#endif - // ADC121 Registers #define ADC121_REG_RESULT 0x00 #define ADC121_REG_ALERT 0x01 @@ -59,19 +53,7 @@ class EmonADC121Sensor : public EmonSensor { if (_address == 0) return; // Init sensor - #if I2C_USE_BRZO - uint8_t buffer[2]; - buffer[0] = ADC121_REG_CONFIG; - buffer[1] = 0x00; - brzo_i2c_start_transaction(_address, I2C_SCL_FREQUENCY); - brzo_i2c_write(buffer, 2, false); - brzo_i2c_end_transaction(); - #else - Wire.beginTransmission(_address); - Wire.write(ADC121_REG_CONFIG); - Wire.write(0x00); - Wire.endTransmission(); - #endif + _init(); // Just one channel _count = _magnitudes; @@ -159,32 +141,14 @@ class EmonADC121Sensor : public EmonSensor { // Protected // --------------------------------------------------------------------- - unsigned int readADC(unsigned char channel) { + void _init() { + i2c_write_uint8(_address, ADC121_REG_CONFIG, 0); + } + unsigned int readADC(unsigned char channel) { (void) channel; - - unsigned int value; - - #if I2C_USE_BRZO - uint8_t buffer[2]; - buffer[0] = ADC121_REG_RESULT; - brzo_i2c_start_transaction(_address, I2C_SCL_FREQUENCY); - brzo_i2c_write(buffer, 1, false); - brzo_i2c_read(buffer, 2, false); - brzo_i2c_end_transaction(); - value = (buffer[0] & 0x0F) << 8; - value |= buffer[1]; - #else - Wire.beginTransmission(_address); - Wire.write(ADC121_REG_RESULT); - Wire.endTransmission(); - Wire.requestFrom(_address, (unsigned char) 2); - value = (Wire.read() & 0x0F) << 8; - value = value + Wire.read(); - #endif - + unsigned int value = i2c_read_uint16(_address, ADC121_REG_RESULT) & 0x0FFF; return value; - } }; diff --git a/code/espurna/sensors/EmonADS1X15Sensor.h b/code/espurna/sensors/EmonADS1X15Sensor.h index 1a2bef55..280b9570 100644 --- a/code/espurna/sensors/EmonADS1X15Sensor.h +++ b/code/espurna/sensors/EmonADS1X15Sensor.h @@ -10,12 +10,6 @@ #include "Arduino.h" #include "EmonSensor.h" -#if I2C_USE_BRZO - #include -#else - #include -#endif - #define ADS1X15_CHANNELS (4) #define ADS1X15_CHIP_ADS1015 (0) @@ -326,21 +320,7 @@ class EmonADS1X15Sensor : public EmonSensor { #endif // Write config register to the ADC - #if I2C_USE_BRZO - uint8_t buffer[3]; - buffer[0] = ADS1X15_REG_POINTER_CONFIG; - buffer[1] = config >> 8; - buffer[2] = config & 0xFF; - brzo_i2c_start_transaction(_address, I2C_SCL_FREQUENCY); - brzo_i2c_write(buffer, 3, false); - brzo_i2c_end_transaction(); - #else - Wire.beginTransmission(_address); - Wire.write((uint8_t) ADS1X15_REG_POINTER_CONFIG); - Wire.write((uint8_t) (config >> 8)); - Wire.write((uint8_t) (config & 0xFF)); - Wire.endTransmission(); - #endif + i2c_write_uint16(_address, ADS1X15_REG_POINTER_CONFIG, config); } @@ -363,36 +343,11 @@ class EmonADS1X15Sensor : public EmonSensor { } unsigned int readADC(unsigned char channel) { - (void) channel; - - unsigned int value = 0; - - #if I2C_USE_BRZO - uint8_t buffer[3]; - buffer[0] = ADS1X15_REG_POINTER_CONVERT; - brzo_i2c_start_transaction(_address, I2C_SCL_FREQUENCY); - brzo_i2c_write(buffer, 1, false); - brzo_i2c_read(buffer, 2, false); - brzo_i2c_end_transaction(); - value |= buffer[0] << 8; - value |= buffer[1]; - - #else - Wire.beginTransmission(_address); - Wire.write(ADS1X15_REG_POINTER_CONVERT); - Wire.endTransmission(); - Wire.requestFrom(_address, (unsigned char) 2); - value |= Wire.read() << 8; - value |= Wire.read(); - #endif - + unsigned int value = i2c_read_uint16(_address, ADS1X15_REG_POINTER_CONVERT); if (_type = ADS1X15_CHIP_ADS1015) value >>= ADS1015_BIT_SHIFT; - delayMicroseconds(500); - return value; - } unsigned char _type = ADS1X15_CHIP_ADS1115; diff --git a/code/espurna/sensors/SHT3XI2CSensor.h b/code/espurna/sensors/SHT3XI2CSensor.h index 74b29d61..5d6804d5 100644 --- a/code/espurna/sensors/SHT3XI2CSensor.h +++ b/code/espurna/sensors/SHT3XI2CSensor.h @@ -9,11 +9,6 @@ #include "Arduino.h" #include "I2CSensor.h" -#if I2C_USE_BRZO -#include -#else -#include -#endif class SHT3XI2CSensor : public I2CSensor { @@ -67,36 +62,9 @@ class SHT3XI2CSensor : public I2CSensor { void pre() { unsigned char buffer[6]; - - #if I2C_USE_BRZO - buffer[0] = 0x2C; - buffer[1] = 0x06; - brzo_i2c_start_transaction(_address, I2C_SCL_FREQUENCY); - brzo_i2c_write(buffer, 2, false); - #else - Wire.beginTransmission(_address); - Wire.write(0x2C); - Wire.write(0x06); - if (Wire.endTransmission() != 0) { - _error = SENSOR_ERROR_TIMEOUT; - return; - } - #endif - + i2c_write_uint8(_address, 0x2C, 0x06); delay(500); - - #if I2C_USE_BRZO - brzo_i2c_read(buffer, 6, false); - brzo_i2c_end_transaction(); - #else - Wire.requestFrom(_address, (unsigned char) 6); - for (int i=0; i<6; i++) buffer[i] = Wire.read(); - delay(50); - if (Wire.available() != 0) { - _error = SENSOR_ERROR_CRC; - return; - } - #endif + i2c_read_buffer(_address, buffer, 6); // cTemp msb, cTemp lsb, cTemp crc, humidity msb, humidity lsb, humidity crc _temperature = ((((buffer[0] * 256.0) + buffer[1]) * 175) / 65535.0) - 45; diff --git a/code/espurna/sensors/SI7021Sensor.h b/code/espurna/sensors/SI7021Sensor.h index b69f60a0..d7e102a6 100644 --- a/code/espurna/sensors/SI7021Sensor.h +++ b/code/espurna/sensors/SI7021Sensor.h @@ -9,11 +9,6 @@ #include "Arduino.h" #include "I2CSensor.h" -#if I2C_USE_BRZO -#include -#else -#include -#endif #define SI7021_SCL_FREQUENCY 200 @@ -53,21 +48,8 @@ class SI7021Sensor : public I2CSensor { if (_address == 0) return; // Check device - #if I2C_USE_BRZO - uint8_t buffer[2] = {0xFC, 0xC9}; - brzo_i2c_start_transaction(_address, SI7021_SCL_FREQUENCY); - brzo_i2c_write(buffer, 2, false); - brzo_i2c_read(buffer, 1, false); - brzo_i2c_end_transaction(); - _chip = buffer[0]; - #else - Wire.beginTransmission(_address); - Wire.write(0xFC); - Wire.write(0xC9); - Wire.endTransmission(); - Wire.requestFrom(_address, (unsigned char) 1); - _chip = Wire.read(); - #endif + i2c_write_uint8(_address, 0xFC, 0xC9); + _chip = i2c_read_uint8(_address); if ((_chip != SI7021_CHIP_SI7021) & (_chip != SI7021_CHIP_HTU21D)) { i2cReleaseLock(_address); @@ -104,7 +86,6 @@ class SI7021Sensor : public I2CSensor { // Current value for slot # index double value(unsigned char index) { if (index < _count) { - _error = SENSOR_ERROR_OK; double value; if (index == 0) { value = read(SI7021_CMD_TMP_NOHOLD); @@ -129,17 +110,8 @@ class SI7021Sensor : public I2CSensor { unsigned int read(uint8_t command) { - unsigned char bytes = (command == 0xE0) ? 2 : 3; - - #if I2C_USE_BRZO - uint8_t buffer[2] = {command, 0x00}; - brzo_i2c_start_transaction(_address, SI7021_SCL_FREQUENCY); - brzo_i2c_write(buffer, 1, false); - #else - Wire.beginTransmission(_address); - Wire.write(command); - Wire.endTransmission(); - #endif + // Request measurement + i2c_write_uint8(_address, command); // When not using clock stretching (*_NOHOLD commands) delay here // is needed to wait for the measurement. @@ -147,28 +119,14 @@ class SI7021Sensor : public I2CSensor { unsigned long start = millis(); while (millis() - start < 50) delay(1); - #if I2C_USE_BRZO - brzo_i2c_read(buffer, 2, false); - brzo_i2c_end_transaction(); - unsigned int msb = buffer[0]; - unsigned int lsb = buffer[1]; - #else - Wire.requestFrom(_address, bytes); - if (Wire.available() != bytes) { - _error = SENSOR_ERROR_CRC; - return 0; - } - unsigned int msb = Wire.read(); - unsigned int lsb = Wire.read(); - #endif - // Clear the last to bits of LSB to 00. // According to datasheet LSB of RH is always xxxxxx10 - lsb &= 0xFC; - - unsigned int value = (msb << 8) | lsb; + unsigned int value = i2c_read_uint16(_address) & 0xFFFC; + // We should be checking there are no pending bytes in the buffer + // and raise a CRC error if there are _error = SENSOR_ERROR_OK; + return value; }