Refactor I2C driver detection phase 1

This commit is contained in:
Theo Arends 2019-11-06 17:48:38 +01:00
parent e89b76adc7
commit d42e81402a
20 changed files with 96 additions and 52 deletions

View File

@ -1506,15 +1506,24 @@ bool I2cActive(uint32_t addr)
return false;
}
bool I2cDevice(uint8_t addr)
bool I2cDevice(uint32_t addr)
{
addr &= 0x7F; // Max I2C address is 127
if (I2cActive(addr)) {
return false; // If already active report as not present;
}
Wire.beginTransmission(addr);
Wire.beginTransmission((uint8_t)addr);
return (0 == Wire.endTransmission());
}
bool I2cSetDevice(uint32_t addr)
{
bool result = I2cDevice(addr);
if (result) {
I2cSetActive(addr, 1);
}
return result;
}
#endif // USE_I2C
/*********************************************************************************************\

View File

@ -669,4 +669,10 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c
#define DEBUG_SENSOR_LOG(...)
#endif
#ifdef DEBUG_TASMOTA_TRACE
#define DEBUG_TRACE_LOG(...) AddLog_Debug(__VA_ARGS__)
#else
#define DEBUG_TRACE_LOG(...)
#endif
#endif // _TASMOTA_POST_H_

View File

@ -823,12 +823,6 @@ void CmndMaxEnergyStart(void)
#endif // USE_ENERGY_POWER_LIMIT
#endif // USE_ENERGY_MARGIN_DETECTION
void EnergyDrvInit(void)
{
energy_flg = ENERGY_NONE;
XnrgCall(FUNC_PRE_INIT); // Find first energy driver
}
void EnergySnsInit(void)
{
XnrgCall(FUNC_INIT);
@ -1107,7 +1101,8 @@ bool Xdrv03(uint8_t function)
bool result = false;
if (FUNC_PRE_INIT == function) {
EnergyDrvInit();
energy_flg = ENERGY_NONE;
XnrgCall(FUNC_PRE_INIT); // Find first energy driver
}
else if (energy_flg) {
switch (function) {

View File

@ -19,6 +19,11 @@
#ifdef USE_I2C
#ifdef USE_PCA9685
/*********************************************************************************************\
* PCA9685 - 16-channel 12-bit pwm driver
*
* I2C Address: 0x40 .. 0x47
\*********************************************************************************************/
#define XDRV_15 15
#define XI2C_01 1 // See I2CDEVICES.md
@ -27,8 +32,11 @@
#define PCA9685_REG_LED0_ON_L 0x06
#define PCA9685_REG_PRE_SCALE 0xFE
#ifndef USE_PCA9685_ADDR
#define USE_PCA9685_ADDR 0x40
#endif
#ifndef USE_PCA9685_FREQ
#define USE_PCA9685_FREQ 50
#define USE_PCA9685_FREQ 50
#endif
uint8_t pca9685_detected = 0;
@ -38,15 +46,16 @@ uint16_t pca9685_pin_pwm_value[16];
void PCA9685_Detect(void)
{
if (pca9685_detected) { return; }
if (I2cActive(USE_PCA9685_ADDR)) { return; }
uint8_t buffer;
if (I2cValidRead8(&buffer, USE_PCA9685_ADDR, PCA9685_REG_MODE1)) {
I2cWrite8(USE_PCA9685_ADDR, PCA9685_REG_MODE1, 0x20);
if (I2cValidRead8(&buffer, USE_PCA9685_ADDR, PCA9685_REG_MODE1)) {
if (0x20 == buffer) {
I2cSetActive(USE_PCA9685_ADDR);
pca9685_detected = 1;
AddLog_P2(LOG_LEVEL_DEBUG, S_LOG_I2C_FOUND_AT, "PCA9685", USE_PCA9685_ADDR);
AddLog_P2(LOG_LEVEL_INFO, S_LOG_I2C_FOUND_AT, "PCA9685", USE_PCA9685_ADDR);
PCA9685_Reset(); // Reset the controller
}
}

View File

@ -80,8 +80,7 @@ void Pcf8574Init()
// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PCF: Probing addr: 0x%x for PCF8574"), pcf8574_address);
if (I2cDevice(pcf8574_address)) {
I2cSetActive(pcf8574_address);
if (I2cSetDevice(pcf8574_address)) {
Pcf8574.type = true;
Pcf8574.address[Pcf8574.max_devices] = pcf8574_address;
@ -91,7 +90,7 @@ void Pcf8574Init()
if (pcf8574_address >= PCF8574_ADDR2) {
strcpy(Pcf8574.stype, "PCF8574A");
}
AddLog_P2(LOG_LEVEL_DEBUG, S_LOG_I2C_FOUND_AT, Pcf8574.stype, pcf8574_address);
AddLog_P2(LOG_LEVEL_INFO, S_LOG_I2C_FOUND_AT, Pcf8574.stype, pcf8574_address);
}
pcf8574_address++;
if ((PCF8574_ADDR1 + 8) == pcf8574_address) {

View File

@ -889,6 +889,8 @@ bool XdrvCall(uint8_t Function)
{
bool result = false;
DEBUG_TRACE_LOG(PSTR("DRV: %d"), Function);
for (uint32_t x = 0; x < xdrv_present; x++) {
result = xdrv_func_ptr[x](Function);

View File

@ -58,17 +58,19 @@ void LcdInit(uint8_t mode)
void LcdInitDriver(void)
{
if (!Settings.display_model) {
if (I2cDevice(LCD_ADDRESS1)) {
if (I2cSetDevice(LCD_ADDRESS1)) {
Settings.display_address[0] = LCD_ADDRESS1;
Settings.display_model = XDSP_01;
}
else if (I2cDevice(LCD_ADDRESS2)) {
else if (I2cSetDevice(LCD_ADDRESS2)) {
Settings.display_address[0] = LCD_ADDRESS2;
Settings.display_model = XDSP_01;
}
}
if (XDSP_01 == Settings.display_model) {
AddLog_P2(LOG_LEVEL_INFO, S_LOG_I2C_FOUND_AT, "LCD", Settings.display_address[0]);
Settings.display_width = Settings.display_cols[0];
Settings.display_height = Settings.display_rows;
lcd = new LiquidCrystal_I2C(Settings.display_address[0], Settings.display_cols[0], Settings.display_rows);

View File

@ -50,17 +50,18 @@ extern uint8_t *buffer;
void SSD1306InitDriver()
{
if (!Settings.display_model) {
if (I2cDevice(OLED_ADDRESS1)) {
if (I2cSetDevice(OLED_ADDRESS1)) {
Settings.display_address[0] = OLED_ADDRESS1;
Settings.display_model = XDSP_02;
}
else if (I2cDevice(OLED_ADDRESS2)) {
else if (I2cSetDevice(OLED_ADDRESS2)) {
Settings.display_address[0] = OLED_ADDRESS2;
Settings.display_model = XDSP_02;
}
}
if (XDSP_02 == Settings.display_model) {
AddLog_P2(LOG_LEVEL_INFO, S_LOG_I2C_FOUND_AT, "OLED", Settings.display_address[0]);
if ((Settings.display_width != 64) && (Settings.display_width != 96) && (Settings.display_width != 128)) {
Settings.display_width = 128;

View File

@ -199,7 +199,7 @@ void MatrixInitDriver(void)
mtx_buffer = (char*)(malloc(MTX_MAX_SCREEN_BUFFER));
if (mtx_buffer != nullptr) {
if (!Settings.display_model) {
if (I2cDevice(Settings.display_address[1])) {
if (I2cSetDevice(Settings.display_address[1])) {
Settings.display_model = XDSP_03;
}
}
@ -208,6 +208,7 @@ void MatrixInitDriver(void)
mtx_state = 1;
for (mtx_matrices = 0; mtx_matrices < 8; mtx_matrices++) {
if (Settings.display_address[mtx_matrices]) {
AddLog_P2(LOG_LEVEL_INFO, S_LOG_I2C_FOUND_AT, "8x8Matrix", Settings.display_address[mtx_matrices]);
matrix[mtx_matrices] = new Adafruit_8x8matrix();
matrix[mtx_matrices]->begin(Settings.display_address[mtx_matrices]);
} else {

View File

@ -51,17 +51,18 @@ Adafruit_SH1106 *oled1106;
void SH1106InitDriver()
{
if (!Settings.display_model) {
if (I2cDevice(OLED_ADDRESS1)) {
if (I2cSetDevice(OLED_ADDRESS1)) {
Settings.display_address[0] = OLED_ADDRESS1;
Settings.display_model = XDSP_07;
}
else if (I2cDevice(OLED_ADDRESS2)) {
else if (I2cSetDevice(OLED_ADDRESS2)) {
Settings.display_address[0] = OLED_ADDRESS2;
Settings.display_model = XDSP_07;
}
}
if (XDSP_07 == Settings.display_model) {
AddLog_P2(LOG_LEVEL_INFO, S_LOG_I2C_FOUND_AT, "OLED", Settings.display_address[0]);
if (Settings.display_width != SH1106_LCDWIDTH) {
Settings.display_width = SH1106_LCDWIDTH;

View File

@ -123,6 +123,8 @@ bool XdspCall(uint8_t Function)
{
bool result = false;
DEBUG_TRACE_LOG(PSTR("DSP: %d"), Function);
for (uint32_t x = 0; x < xdsp_present; x++) {
result = xdsp_func_ptr[x](Function);

View File

@ -96,6 +96,8 @@ uint8_t xlgt_active = 0;
bool XlgtCall(uint8_t function)
{
DEBUG_TRACE_LOG(PSTR("LGT: %d"), function);
if (FUNC_MODULE_INIT == function) {
for (uint32_t x = 0; x < xlgt_present; x++) {
xlgt_func_ptr[x](function);

View File

@ -199,15 +199,15 @@ void Ade7953EnergyEverySecond()
void Ade7953DrvInit(void)
{
if (i2c_flg && (pin[GPIO_ADE7953_IRQ] < 99)) { // Irq on GPIO16 is not supported...
if (pin[GPIO_ADE7953_IRQ] < 99) { // Irq on GPIO16 is not supported...
delay(100); // Need 100mS to init ADE7953
if (I2cDevice(ADE7953_ADDR)) {
if (I2cSetDevice(ADE7953_ADDR)) {
if (HLW_PREF_PULSE == Settings.energy_power_calibration) {
Settings.energy_power_calibration = ADE7953_PREF;
Settings.energy_voltage_calibration = ADE7953_UREF;
Settings.energy_current_calibration = ADE7953_IREF;
}
AddLog_P2(LOG_LEVEL_DEBUG, S_LOG_I2C_FOUND_AT, "ADE7953", ADE7953_ADDR);
AddLog_P2(LOG_LEVEL_INFO, S_LOG_I2C_FOUND_AT, "ADE7953", ADE7953_ADDR);
Ade7953.init_step = 2;
Energy.phase_count = 2; // Handle two channels as two phases

View File

@ -96,6 +96,8 @@ uint8_t xnrg_active = 0;
bool XnrgCall(uint8_t function)
{
DEBUG_TRACE_LOG(PSTR("NRG: %d"), function);
if (FUNC_PRE_INIT == function) {
for (uint32_t x = 0; x < xnrg_present; x++) {
xnrg_func_ptr[x](function);

View File

@ -200,8 +200,11 @@ void HtuDetect(void)
if (htu_type) { return; }
htu_address = HTU21_ADDR;
if (I2cActive(htu_address)) { return; }
htu_type = HtuReadDeviceId();
if (htu_type) {
I2cSetActive(htu_address);
uint8_t index = 0;
HtuInit();
switch (htu_type) {
@ -224,7 +227,7 @@ void HtuDetect(void)
htu_delay_humidity = 23;
}
GetTextIndexed(htu_types, sizeof(htu_types), index, kHtuTypes);
AddLog_P2(LOG_LEVEL_DEBUG, S_LOG_I2C_FOUND_AT, htu_types, htu_address);
AddLog_P2(LOG_LEVEL_INFO, S_LOG_I2C_FOUND_AT, htu_types, htu_address);
}
}

View File

@ -447,7 +447,7 @@ void Bme680Read(uint8_t bmp_idx)
void BmpDetect(void)
{
if (bmp_count) return;
if (bmp_count) { return; }
int bmp_sensor_size = BMP_MAX_SENSORS * sizeof(bmp_sensors_t);
if (!bmp_sensors) {
@ -457,6 +457,7 @@ void BmpDetect(void)
memset(bmp_sensors, 0, bmp_sensor_size); // Init defaults to 0
for (uint32_t i = 0; i < BMP_MAX_SENSORS; i++) {
if (I2cActive(bmp_addresses[i])) { continue; }
uint8_t bmp_type = I2cRead8(bmp_addresses[i], BMP_REGISTER_CHIPID);
if (bmp_type) {
bmp_sensors[bmp_count].bmp_address = bmp_addresses[i];
@ -482,8 +483,9 @@ void BmpDetect(void)
#endif // USE_BME680
}
if (success) {
I2cSetActive(bmp_sensors[bmp_count].bmp_address);
GetTextIndexed(bmp_sensors[bmp_count].bmp_name, sizeof(bmp_sensors[bmp_count].bmp_name), bmp_sensors[bmp_count].bmp_model, kBmpTypes);
AddLog_P2(LOG_LEVEL_DEBUG, S_LOG_I2C_FOUND_AT, bmp_sensors[bmp_count].bmp_name, bmp_sensors[bmp_count].bmp_address);
AddLog_P2(LOG_LEVEL_INFO, S_LOG_I2C_FOUND_AT, bmp_sensors[bmp_count].bmp_name, bmp_sensors[bmp_count].bmp_address);
bmp_count++;
}
}

View File

@ -56,17 +56,17 @@ bool Bh1750Read(void)
void Bh1750Detect(void)
{
if (bh1750_type) {
return;
}
if (bh1750_type) { return; }
for (uint32_t i = 0; i < sizeof(bh1750_addresses); i++) {
bh1750_address = bh1750_addresses[i];
if (I2cActive(bh1750_address)) { continue; }
Wire.beginTransmission(bh1750_address);
Wire.write(BH1750_CONTINUOUS_HIGH_RES_MODE);
if (!Wire.endTransmission()) {
I2cSetActive(bh1750_address);
bh1750_type = 1;
AddLog_P2(LOG_LEVEL_DEBUG, S_LOG_I2C_FOUND_AT, bh1750_types, bh1750_address);
AddLog_P2(LOG_LEVEL_INFO, S_LOG_I2C_FOUND_AT, bh1750_types, bh1750_address);
break;
}
}

View File

@ -129,19 +129,21 @@ char str_uvrisk_text[10];
void Veml6070Detect(void)
{
if (veml6070_type) {
return;
}
if (veml6070_type) { return; }
if (I2cActive(VEML6070_ADDR_L)) { return; }
// init the UV sensor
Wire.beginTransmission(VEML6070_ADDR_L);
Wire.write((itime << 2) | 0x02);
uint8_t status = Wire.endTransmission();
// action on status
if (!status) {
I2cSetActive(VEML6070_ADDR_L);
veml6070_type = 1;
Veml6070UvTableInit(); // 1[ms], initalize the UV compare table only once
uint8_t veml_model = 0;
GetTextIndexed(veml6070_name, sizeof(veml6070_name), veml_model, kVemlTypes);
AddLog_P2(LOG_LEVEL_DEBUG, S_LOG_I2C_FOUND_AT, "VEML6070", VEML6070_ADDR_L);
AddLog_P2(LOG_LEVEL_INFO, S_LOG_I2C_FOUND_AT, "VEML6070", VEML6070_ADDR_L);
}
}
@ -171,15 +173,19 @@ void Veml6070EverySecond(void)
{
// all = 10..15[ms]
if (11 == (uptime %100)) {
Veml6070ModeCmd(1); // on = 1[ms], wakeup the UV sensor
Veml6070Detect(); // 1[ms], check for sensor and init with IT time
Veml6070ModeCmd(0); // off = 5[ms], suspend the UV sensor
if (!veml6070_type) {
// Veml6070ModeCmd(1); // on = 1[ms], wakeup the UV sensor - THIS CORRUPTS OTHER I2C DEVICES
Veml6070Detect(); // 1[ms], check for sensor and init with IT time
// Veml6070ModeCmd(0); // off = 5[ms], suspend the UV sensor - THIS CORRUPTS OTHER I2C DEVICES
}
} else {
Veml6070ModeCmd(1); // 1[ms], wakeup the UV sensor
uvlevel = Veml6070ReadUv(); // 1..2[ms], get UV raw values
uvrisk = Veml6070UvRiskLevel(uvlevel); // 0..1[ms], get UV risk level
uvpower = Veml6070UvPower(uvrisk); // 2[ms], get UV power in W/m2
Veml6070ModeCmd(0); // off = 5[ms], suspend the UV sensor
if (veml6070_type) {
Veml6070ModeCmd(1); // 1[ms], wakeup the UV sensor
uvlevel = Veml6070ReadUv(); // 1..2[ms], get UV raw values
uvrisk = Veml6070UvRiskLevel(uvlevel); // 0..1[ms], get UV risk level
uvpower = Veml6070UvPower(uvrisk); // 2[ms], get UV power in W/m2
Veml6070ModeCmd(0); // off = 5[ms], suspend the UV sensor
}
}
}
@ -305,16 +311,11 @@ void Veml6070Show(bool json)
bool Xsns11(uint8_t function)
{
if (!I2cEnabled(XI2C_12) ||
(pin[GPIO_ADE7953_IRQ] < 99)) { return false; } // The ADE7953 uses I2C address 0x38 too but needs priority
if (!I2cEnabled(XI2C_12)) { return false; }
bool result = false;
switch (function) {
case FUNC_INIT:
Veml6070Detect(); // 1[ms], detect and init the sensor
Veml6070UvTableInit(); // 1[ms], initalize the UV compare table only once
break;
case FUNC_EVERY_SECOND:
Veml6070EverySecond(); // 10..15[ms], tested with OLED display, do all the actions needed to get all sensor values
break;
@ -326,6 +327,9 @@ bool Xsns11(uint8_t function)
Veml6070Show(0);
break;
#endif // USE_WEBSERVER
case FUNC_INIT:
Veml6070Detect(); // 1[ms], detect and init the sensor
break;
}
return result;
}

View File

@ -165,16 +165,18 @@ void Ads1115Detect(void)
{
if (Ads1115.count) { return; }
uint16_t buffer;
for (uint32_t i = 0; i < sizeof(Ads1115.addresses); i++) {
if (!Ads1115.found[i]) {
Ads1115.address = Ads1115.addresses[i];
if (I2cActive(Ads1115.address)) { continue; }
uint16_t buffer;
if (I2cValidRead16(&buffer, Ads1115.address, ADS1115_REG_POINTER_CONVERT) &&
I2cValidRead16(&buffer, Ads1115.address, ADS1115_REG_POINTER_CONFIG)) {
Ads1115StartComparator(i, ADS1115_REG_CONFIG_MODE_CONTIN);
I2cSetActive(Ads1115.address);
Ads1115.count++;
Ads1115.found[i] = 1;
AddLog_P2(LOG_LEVEL_DEBUG, S_LOG_I2C_FOUND_AT, "ADS1115", Ads1115.address);
AddLog_P2(LOG_LEVEL_INFO, S_LOG_I2C_FOUND_AT, "ADS1115", Ads1115.address);
}
}
}

View File

@ -890,6 +890,8 @@ bool XsnsCall(uint8_t Function)
{
bool result = false;
DEBUG_TRACE_LOG(PSTR("SNS: %d"), Function);
#ifdef PROFILE_XSNS_EVERY_SECOND
uint32_t profile_start_millis = millis();
#endif // PROFILE_XSNS_EVERY_SECOND