Refactor i2cScan.h To Handle 2 Bus (#2337)

* Break i2cScan out into a set of classes for scanning i2c

* refactor i2cscan addresses to be structs that allow addressing by port + address

* build whoopsies

* trunk fmt

* trunk fmt

* lost some build fixes from the merge

* more cleaning for build safety, RTC behavior
This commit is contained in:
A. Rager
2023-03-08 19:13:46 -08:00
committed by GitHub
parent 9150c2e568
commit e6d69e2b67
20 changed files with 739 additions and 315 deletions

70
src/detect/ScanI2C.cpp Normal file
View File

@@ -0,0 +1,70 @@
#include "ScanI2C.h"
const ScanI2C::DeviceAddress ScanI2C::ADDRESS_NONE = ScanI2C::DeviceAddress();
const ScanI2C::FoundDevice ScanI2C::DEVICE_NONE = ScanI2C::FoundDevice(ScanI2C::DeviceType::NONE, ADDRESS_NONE);
ScanI2C::ScanI2C() = default;
void ScanI2C::scanPort(ScanI2C::I2CPort port) {}
void ScanI2C::setSuppressScreen()
{
shouldSuppressScreen = true;
}
ScanI2C::FoundDevice ScanI2C::firstScreen() const
{
// Allow to override the scanner results for screen
if (shouldSuppressScreen)
return DEVICE_NONE;
ScanI2C::DeviceType types[] = {SCREEN_SSD1306, SCREEN_SH1106, SCREEN_ST7567, SCREEN_UNKNOWN};
return firstOfOrNONE(4, types);
}
ScanI2C::FoundDevice ScanI2C::firstRTC() const
{
ScanI2C::DeviceType types[] = {RTC_RV3028, RTC_PCF8563};
return firstOfOrNONE(2, types);
}
ScanI2C::FoundDevice ScanI2C::firstKeyboard() const
{
ScanI2C::DeviceType types[] = {CARDKB, RAK14004};
return firstOfOrNONE(2, types);
}
ScanI2C::FoundDevice ScanI2C::find(ScanI2C::DeviceType) const
{
return DEVICE_NONE;
}
bool ScanI2C::exists(ScanI2C::DeviceType) const
{
return false;
}
ScanI2C::FoundDevice ScanI2C::firstOfOrNONE(size_t count, ScanI2C::DeviceType *types) const
{
return DEVICE_NONE;
}
size_t ScanI2C::countDevices() const
{
return 0;
}
ScanI2C::DeviceAddress::DeviceAddress(ScanI2C::I2CPort port, uint8_t address) : port(port), address(address) {}
ScanI2C::DeviceAddress::DeviceAddress() : DeviceAddress(I2CPort::NO_I2C, 0) {}
bool ScanI2C::DeviceAddress::operator<(const ScanI2C::DeviceAddress &other) const
{
return
// If this one has no port and other has a port
(port == NO_I2C && other.port != NO_I2C)
// if both have a port and this one's address is lower
|| (port != NO_I2C && other.port != NO_I2C && (address < other.address));
}
ScanI2C::FoundDevice::FoundDevice(ScanI2C::DeviceType type, ScanI2C::DeviceAddress address) : type(type), address(address) {}

93
src/detect/ScanI2C.h Normal file
View File

@@ -0,0 +1,93 @@
#pragma once
#include <stddef.h>
#include <stdint.h>
class ScanI2C
{
public:
typedef enum DeviceType {
NONE,
SCREEN_SSD1306,
SCREEN_SH1106,
SCREEN_UNKNOWN, // has the same address as the two above but does not respond to the same commands
SCREEN_ST7567,
ATECC608B,
RTC_RV3028,
RTC_PCF8563,
CARDKB,
RAK14004,
PMU_AXP192_AXP2101,
BME_680,
BME_280,
BMP_280,
INA260,
INA219,
MCP9808,
SHT31,
SHTC3,
LPS22HB,
QMC6310,
QMI8658,
QMC5883L,
PMSA0031,
} DeviceType;
// typedef uint8_t DeviceAddress;
typedef enum I2CPort {
NO_I2C,
WIRE,
WIRE1,
} I2CPort;
typedef struct DeviceAddress {
I2CPort port;
uint8_t address;
explicit DeviceAddress(I2CPort port, uint8_t address);
DeviceAddress();
bool operator<(const DeviceAddress &other) const;
} DeviceAddress;
static const DeviceAddress ADDRESS_NONE;
typedef uint8_t RegisterAddress;
typedef struct FoundDevice {
DeviceType type;
DeviceAddress address;
explicit FoundDevice(DeviceType = DeviceType::NONE, DeviceAddress = ADDRESS_NONE);
} FoundDevice;
static const FoundDevice DEVICE_NONE;
public:
ScanI2C();
virtual void scanPort(ScanI2C::I2CPort);
/*
* A bit of a hack, this tells the scanner not to tell later systems there is a screen to avoid enabling it.
*/
void setSuppressScreen();
FoundDevice firstScreen() const;
FoundDevice firstRTC() const;
FoundDevice firstKeyboard() const;
virtual FoundDevice find(DeviceType) const;
virtual bool exists(DeviceType) const;
virtual size_t countDevices() const;
protected:
virtual FoundDevice firstOfOrNONE(size_t, DeviceType[]) const;
private:
bool shouldSuppressScreen = false;
};

View File

@@ -0,0 +1,297 @@
#include "ScanI2CTwoWire.h"
#include "concurrency/LockGuard.h"
#include "configuration.h"
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL)
#include "main.h" // atecc
#endif
// AXP192 and AXP2101 have the same device address, we just need to identify it in Power.cpp
#ifndef XPOWERS_AXP192_AXP2101_ADDRESS
#define XPOWERS_AXP192_AXP2101_ADDRESS 0x34
#endif
ScanI2C::FoundDevice ScanI2CTwoWire::find(ScanI2C::DeviceType type) const
{
concurrency::LockGuard guard((concurrency::Lock *)&lock);
return exists(type) ? ScanI2C::FoundDevice(type, deviceAddresses.at(type)) : DEVICE_NONE;
}
bool ScanI2CTwoWire::exists(ScanI2C::DeviceType type) const
{
return deviceAddresses.find(type) != deviceAddresses.end();
}
ScanI2C::FoundDevice ScanI2CTwoWire::firstOfOrNONE(size_t count, DeviceType types[]) const
{
concurrency::LockGuard guard((concurrency::Lock *)&lock);
for (size_t k = 0; k < count; k++) {
ScanI2C::DeviceType current = types[k];
if (exists(current)) {
return ScanI2C::FoundDevice(current, deviceAddresses.at(current));
}
}
return DEVICE_NONE;
}
ScanI2C::DeviceType ScanI2CTwoWire::probeOLED(ScanI2C::DeviceAddress addr) const
{
TwoWire *i2cBus = fetchI2CBus(addr);
uint8_t r = 0;
uint8_t r_prev = 0;
uint8_t c = 0;
ScanI2C::DeviceType o_probe = ScanI2C::DeviceType::SCREEN_UNKNOWN;
do {
r_prev = r;
i2cBus->beginTransmission(addr.address);
i2cBus->write((uint8_t)0x00);
i2cBus->endTransmission();
i2cBus->requestFrom((int)addr.address, 1);
if (i2cBus->available()) {
r = i2cBus->read();
}
r &= 0x0f;
if (r == 0x08 || r == 0x00) {
LOG_INFO("sh1106 display found\n");
o_probe = SCREEN_SH1106; // SH1106
} else if (r == 0x03 || r == 0x04 || r == 0x06 || r == 0x07) {
LOG_INFO("ssd1306 display found\n");
o_probe = SCREEN_SSD1306; // SSD1306
}
c++;
} while ((r != r_prev) && (c < 4));
LOG_DEBUG("0x%x subtype probed in %i tries \n", r, c);
return o_probe;
}
void ScanI2CTwoWire::printATECCInfo() const
{
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL)
atecc.readConfigZone(false);
LOG_DEBUG("ATECC608B Serial Number: ");
for (int i = 0; i < 9; i++) {
LOG_DEBUG("%02x", atecc.serialNumber[i]);
}
LOG_DEBUG(", Rev Number: ");
for (int i = 0; i < 4; i++) {
LOG_DEBUG("%02x", atecc.revisionNumber[i]);
}
LOG_DEBUG("\n");
LOG_DEBUG("ATECC608B Config %s", atecc.configLockStatus ? "Locked" : "Unlocked");
LOG_DEBUG(", Data %s", atecc.dataOTPLockStatus ? "Locked" : "Unlocked");
LOG_DEBUG(", Slot 0 %s\n", atecc.slot0LockStatus ? "Locked" : "Unlocked");
if (atecc.configLockStatus && atecc.dataOTPLockStatus && atecc.slot0LockStatus) {
if (atecc.generatePublicKey() == false) {
LOG_DEBUG("ATECC608B Error generating public key\n");
} else {
LOG_DEBUG("ATECC608B Public Key: ");
for (int i = 0; i < 64; i++) {
LOG_DEBUG("%02x", atecc.publicKey64Bytes[i]);
}
LOG_DEBUG("\n");
}
}
#endif
}
uint16_t ScanI2CTwoWire::getRegisterValue(const ScanI2CTwoWire::RegisterLocation &registerLocation,
ScanI2CTwoWire::ResponseWidth responseWidth) const
{
uint16_t value = 0x00;
TwoWire *i2cBus = fetchI2CBus(registerLocation.i2cAddress);
i2cBus->beginTransmission(registerLocation.i2cAddress.address);
i2cBus->write(registerLocation.registerAddress);
i2cBus->endTransmission();
delay(20);
i2cBus->requestFrom(registerLocation.i2cAddress.address, responseWidth);
LOG_DEBUG("Wire.available() = %d\n", i2cBus->available());
if (i2cBus->available() == 2) {
// Read MSB, then LSB
value = (uint16_t)i2cBus->read() << 8;
value |= i2cBus->read();
} else if (i2cBus->available()) {
value = i2cBus->read();
}
return value;
}
#define SCAN_SIMPLE_CASE(ADDR, T, ...) \
case ADDR: \
LOG_INFO(__VA_ARGS__); \
type = T; \
break;
void ScanI2CTwoWire::scanPort(I2CPort port)
{
concurrency::LockGuard guard((concurrency::Lock *)&lock);
LOG_DEBUG("Scanning for i2c devices on port %d\n", port);
uint8_t err;
DeviceAddress addr(port, 0x00);
uint16_t registerValue = 0x00;
ScanI2C::DeviceType type;
TwoWire *i2cBus;
#ifdef RV3028_RTC
Melopero_RV3028 rtc;
#endif
#ifdef I2C_SDA1
if (port == I2CPort::WIRE1) {
i2cBus = &Wire1;
} else {
#endif
i2cBus = &Wire;
#ifdef I2C_SDA1
}
#endif
for (addr.address = 1; addr.address < 127; addr.address++) {
i2cBus->beginTransmission(addr.address);
err = i2cBus->endTransmission();
type = NONE;
if (err == 0) {
LOG_DEBUG("I2C device found at address 0x%x\n", addr.address);
switch (addr.address) {
case SSD1306_ADDRESS:
type = probeOLED(addr);
break;
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL)
case ATECC608B_ADDR:
type = ATECC608B;
if (atecc.begin(addr.address) == true) {
LOG_INFO("ATECC608B initialized\n");
} else {
LOG_WARN("ATECC608B initialization failed\n");
}
printATECCInfo();
break;
#endif
#ifdef RV3028_RTC
case RV3028_RTC:
// foundDevices[addr] = RTC_RV3028;
type = RTC_RV3028;
LOG_INFO("RV3028 RTC found\n");
rtc.initI2C(*i2cBus);
rtc.writeToRegister(0x35, 0x07); // no Clkout
rtc.writeToRegister(0x37, 0xB4);
break;
#endif
#ifdef PCF8563_RTC
SCAN_SIMPLE_CASE(PCF8563_RTC, RTC_PCF8563, "PCF8563 RTC found\n")
#endif
case CARDKB_ADDR:
// Do we have the RAK14006 instead?
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x04), 1);
if (registerValue == 0x02) {
// KEYPAD_VERSION
LOG_INFO("RAK14004 found\n");
type = RAK14004;
} else {
LOG_INFO("m5 cardKB found\n");
type = CARDKB;
}
break;
SCAN_SIMPLE_CASE(ST7567_ADDRESS, SCREEN_ST7567, "st7567 display found\n")
#ifdef HAS_PMU
SCAN_SIMPLE_CASE(XPOWERS_AXP192_AXP2101_ADDRESS, PMU_AXP192_AXP2101, "axp192/axp2101 PMU found\n")
#endif
case BME_ADDR:
case BME_ADDR_ALTERNATE:
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0xD0), 1); // GET_ID
switch (registerValue) {
case 0x61:
LOG_INFO("BME-680 sensor found at address 0x%x\n", (uint8_t)addr.address);
type = BME_680;
break;
case 0x60:
LOG_INFO("BME-280 sensor found at address 0x%x\n", (uint8_t)addr.address);
type = BME_280;
break;
default:
LOG_INFO("BMP-280 sensor found at address 0x%x\n", (uint8_t)addr.address);
type = BMP_280;
}
break;
case INA_ADDR:
case INA_ADDR_ALTERNATE:
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0xFE), 2);
LOG_DEBUG("Register MFG_UID: 0x%x\n", registerValue);
if (registerValue == 0x5449) {
LOG_INFO("INA260 sensor found at address 0x%x\n", (uint8_t)addr.address);
type = INA260;
} else { // Assume INA219 if INA260 ID is not found
LOG_INFO("INA219 sensor found at address 0x%x\n", (uint8_t)addr.address);
type = INA219;
}
break;
SCAN_SIMPLE_CASE(MCP9808_ADDR, MCP9808, "MCP9808 sensor found\n")
SCAN_SIMPLE_CASE(SHT31_ADDR, SHT31, "SHT31 sensor found\n")
SCAN_SIMPLE_CASE(SHTC3_ADDR, SHTC3, "SHTC3 sensor found\n")
case LPS22HB_ADDR_ALT:
SCAN_SIMPLE_CASE(LPS22HB_ADDR, LPS22HB, "LPS22HB sensor found\n")
SCAN_SIMPLE_CASE(QMC6310_ADDR, QMC6310, "QMC6310 Highrate 3-Axis magnetic sensor found\n")
SCAN_SIMPLE_CASE(QMI8658_ADDR, QMI8658, "QMI8658 Highrate 6-Axis inertial measurement sensor found\n")
SCAN_SIMPLE_CASE(QMC5883L_ADDR, QMC5883L, "QMC5883L Highrate 3-Axis magnetic sensor found\n")
SCAN_SIMPLE_CASE(PMSA0031_ADDR, PMSA0031, "PMSA0031 air quality sensor found\n")
default:
LOG_INFO("Device found at address 0x%x was not able to be enumerated\n", addr.address);
}
} else if (err == 4) {
LOG_ERROR("Unknown error at address 0x%x\n", addr);
}
// Check if a type was found for the enumerated device - save, if so
if (type != NONE) {
deviceAddresses[type] = addr;
foundDevices[addr] = type;
}
}
}
TwoWire *ScanI2CTwoWire::fetchI2CBus(ScanI2C::DeviceAddress address) const
{
if (address.port == ScanI2C::I2CPort::WIRE1) {
return &Wire;
} else {
#ifdef I2C_SDA1
return &Wire1;
#else
return &Wire;
#endif
}
}
size_t ScanI2CTwoWire::countDevices() const
{
return foundDevices.size();
}

View File

@@ -0,0 +1,56 @@
#pragma once
#include <map>
#include <memory>
#include <stddef.h>
#include <stdint.h>
#include <Wire.h>
#include "ScanI2C.h"
#include "../concurrency/Lock.h"
class ScanI2CTwoWire : public ScanI2C
{
public:
void scanPort(ScanI2C::I2CPort) override;
ScanI2C::FoundDevice find(ScanI2C::DeviceType) const override;
bool exists(ScanI2C::DeviceType) const override;
size_t countDevices() const override;
protected:
FoundDevice firstOfOrNONE(size_t, DeviceType[]) const override;
private:
typedef struct RegisterLocation {
DeviceAddress i2cAddress;
RegisterAddress registerAddress;
RegisterLocation(DeviceAddress deviceAddress, RegisterAddress registerAddress)
: i2cAddress(deviceAddress), registerAddress(registerAddress)
{
}
} RegisterLocation;
typedef uint8_t ResponseWidth;
std::map<ScanI2C::DeviceAddress, ScanI2C::DeviceType> foundDevices;
// note: prone to overwriting if multiple devices of a type are added at different addresses (rare?)
std::map<ScanI2C::DeviceType, ScanI2C::DeviceAddress> deviceAddresses;
concurrency::Lock lock;
void printATECCInfo() const;
uint16_t getRegisterValue(const RegisterLocation &, ResponseWidth) const;
DeviceType probeOLED(ScanI2C::DeviceAddress) const;
TwoWire *fetchI2CBus(ScanI2C::DeviceAddress) const;
};

View File

@@ -1,237 +0,0 @@
#include "../configuration.h"
#include "../main.h"
#include "mesh/generated/meshtastic/telemetry.pb.h"
#include <Wire.h>
// AXP192 and AXP2101 have the same device address, we just need to identify it in Power.cpp
#ifndef XPOWERS_AXP192_AXP2101_ADDRESS
#define XPOWERS_AXP192_AXP2101_ADDRESS 0x34
#endif
#if HAS_WIRE
void printATECCInfo()
{
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL)
atecc.readConfigZone(false);
LOG_DEBUG("ATECC608B Serial Number: ");
for (int i = 0; i < 9; i++) {
LOG_DEBUG("%02x", atecc.serialNumber[i]);
}
LOG_DEBUG(", Rev Number: ");
for (int i = 0; i < 4; i++) {
LOG_DEBUG("%02x", atecc.revisionNumber[i]);
}
LOG_DEBUG("\n");
LOG_DEBUG("ATECC608B Config %s", atecc.configLockStatus ? "Locked" : "Unlocked");
LOG_DEBUG(", Data %s", atecc.dataOTPLockStatus ? "Locked" : "Unlocked");
LOG_DEBUG(", Slot 0 %s\n", atecc.slot0LockStatus ? "Locked" : "Unlocked");
if (atecc.configLockStatus && atecc.dataOTPLockStatus && atecc.slot0LockStatus) {
if (atecc.generatePublicKey() == false) {
LOG_DEBUG("ATECC608B Error generating public key\n");
} else {
LOG_DEBUG("ATECC608B Public Key: ");
for (int i = 0; i < 64; i++) {
LOG_DEBUG("%02x", atecc.publicKey64Bytes[i]);
}
LOG_DEBUG("\n");
}
}
#endif
}
uint16_t getRegisterValue(uint8_t address, uint8_t reg, uint8_t length)
{
uint16_t value = 0x00;
Wire.beginTransmission(address);
Wire.write(reg);
Wire.endTransmission();
delay(20);
Wire.requestFrom(address, length);
LOG_DEBUG("Wire.available() = %d\n", Wire.available());
if (Wire.available() == 2) {
// Read MSB, then LSB
value = (uint16_t)Wire.read() << 8;
value |= Wire.read();
} else if (Wire.available()) {
value = Wire.read();
}
return value;
}
uint8_t oled_probe(byte addr)
{
uint8_t r = 0;
uint8_t r_prev = 0;
uint8_t c = 0;
uint8_t o_probe = 0;
do {
r_prev = r;
Wire.beginTransmission(addr);
Wire.write(0x00);
Wire.endTransmission();
Wire.requestFrom((int)addr, 1);
if (Wire.available()) {
r = Wire.read();
}
r &= 0x0f;
if (r == 0x08 || r == 0x00) {
o_probe = 2; // SH1106
} else if (r == 0x03 || r == 0x04 || r == 0x06 || r == 0x07) {
o_probe = 1; // SSD1306
}
c++;
} while ((r != r_prev) && (c < 4));
LOG_DEBUG("0x%x subtype probed in %i tries \n", r, c);
return o_probe;
}
void scanI2Cdevice()
{
byte err, addr;
uint16_t registerValue = 0x00;
int nDevices = 0;
for (addr = 1; addr < 127; addr++) {
Wire.beginTransmission(addr);
err = Wire.endTransmission();
if (err == 0) {
LOG_DEBUG("I2C device found at address 0x%x\n", addr);
nDevices++;
if (addr == SSD1306_ADDRESS) {
screen_found = addr;
screen_model = oled_probe(addr);
if (screen_model == 1) {
LOG_INFO("ssd1306 display found\n");
} else if (screen_model == 2) {
LOG_INFO("sh1106 display found\n");
} else {
LOG_INFO("unknown display found\n");
}
}
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL)
if (addr == ATECC608B_ADDR) {
keystore_found = addr;
if (atecc.begin(keystore_found) == true) {
LOG_INFO("ATECC608B initialized\n");
} else {
LOG_WARN("ATECC608B initialization failed\n");
}
printATECCInfo();
}
#endif
#ifdef RV3028_RTC
if (addr == RV3028_RTC) {
rtc_found = addr;
LOG_INFO("RV3028 RTC found\n");
Melopero_RV3028 rtc;
rtc.initI2C();
rtc.writeToRegister(0x35, 0x07); // no Clkout
rtc.writeToRegister(0x37, 0xB4);
}
#endif
#ifdef PCF8563_RTC
if (addr == PCF8563_RTC) {
rtc_found = addr;
LOG_INFO("PCF8563 RTC found\n");
}
#endif
if (addr == CARDKB_ADDR) {
cardkb_found = addr;
// Do we have the RAK14006 instead?
registerValue = getRegisterValue(addr, 0x04, 1);
if (registerValue == 0x02) { // KEYPAD_VERSION
LOG_INFO("RAK14004 found\n");
kb_model = 0x02;
} else {
LOG_INFO("m5 cardKB found\n");
kb_model = 0x00;
}
}
if (addr == ST7567_ADDRESS) {
screen_found = addr;
LOG_INFO("st7567 display found\n");
}
#ifdef HAS_PMU
if (addr == XPOWERS_AXP192_AXP2101_ADDRESS) {
pmu_found = true;
LOG_INFO("axp192/axp2101 PMU found\n");
}
#endif
if (addr == BME_ADDR || addr == BME_ADDR_ALTERNATE) {
registerValue = getRegisterValue(addr, 0xD0, 1); // GET_ID
if (registerValue == 0x61) {
LOG_INFO("BME-680 sensor found at address 0x%x\n", (uint8_t)addr);
nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_BME680] = addr;
} else if (registerValue == 0x60) {
LOG_INFO("BME-280 sensor found at address 0x%x\n", (uint8_t)addr);
nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_BME280] = addr;
} else {
LOG_INFO("BMP-280 sensor found at address 0x%x\n", (uint8_t)addr);
nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_BMP280] = addr;
}
}
if (addr == INA_ADDR || addr == INA_ADDR_ALTERNATE) {
registerValue = getRegisterValue(addr, 0xFE, 2);
LOG_DEBUG("Register MFG_UID: 0x%x\n", registerValue);
if (registerValue == 0x5449) {
LOG_INFO("INA260 sensor found at address 0x%x\n", (uint8_t)addr);
nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_INA260] = addr;
} else { // Assume INA219 if INA260 ID is not found
LOG_INFO("INA219 sensor found at address 0x%x\n", (uint8_t)addr);
nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_INA219] = addr;
}
}
if (addr == MCP9808_ADDR) {
nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_MCP9808] = addr;
LOG_INFO("MCP9808 sensor found\n");
}
if (addr == SHT31_ADDR) {
LOG_INFO("SHT31 sensor found\n");
nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_SHT31] = addr;
}
if (addr == SHTC3_ADDR) {
LOG_INFO("SHTC3 sensor found\n");
nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_SHTC3] = addr;
}
if (addr == LPS22HB_ADDR || addr == LPS22HB_ADDR_ALT) {
LOG_INFO("LPS22HB sensor found\n");
nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_LPS22] = addr;
}
// High rate sensors, will be processed internally
if (addr == QMC6310_ADDR) {
LOG_INFO("QMC6310 Highrate 3-Axis magnetic sensor found\n");
nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_QMC6310] = addr;
}
if (addr == QMI8658_ADDR) {
LOG_INFO("QMI8658 Highrate 6-Axis inertial measurement sensor found\n");
nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_QMI8658] = addr;
}
if (addr == QMC5883L_ADDR) {
LOG_INFO("QMC5883L Highrate 3-Axis magnetic sensor found\n");
nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_QMC5883L] = addr;
}
if (addr == PMSA0031_ADDR) {
LOG_INFO("PMSA0031 air quality sensor found\n");
nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_PMSA003I] = addr;
}
} else if (err == 4) {
LOG_ERROR("Unknow error at address 0x%x\n", addr);
}
}
if (nDevices == 0)
LOG_INFO("No I2C devices found\n");
else
LOG_INFO("%i I2C devices found\n", nDevices);
}
#else
void scanI2Cdevice() {}
#endif