diff --git a/src/gps/GPS.cpp b/src/gps/GPS.cpp index 7524e63ec..080c0e636 100644 --- a/src/gps/GPS.cpp +++ b/src/gps/GPS.cpp @@ -41,7 +41,7 @@ template std::size_t array_count(const T (&)[N]) #if defined(NRF52840_XXAA) || defined(NRF52833_XXAA) || defined(ARCH_ESP32) || defined(ARCH_PORTDUINO) #if defined(SENSECAP_INDICATOR) -FakeUART *GPS::_serial_gps = nullptr; +FakeUART *GPS::_serial_gps = FakeSerial; #elif defined(RAK2560) HardwareSerial *GPS::_serial_gps = &Serial2; #else diff --git a/src/gps/GPS.h b/src/gps/GPS.h index fb3efd7c1..4b398ec9b 100644 --- a/src/gps/GPS.h +++ b/src/gps/GPS.h @@ -12,7 +12,7 @@ #include "modules/PositionModule.h" #ifdef SENSECAP_INDICATOR -#include "FakeUART.h" +#include "mesh/comms/FakeUART.h" #endif // Allow defining the polarity of the ENABLE output. default is active high diff --git a/src/main.cpp b/src/main.cpp index 047271c1c..d8a291ac4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -24,6 +24,7 @@ #ifdef SENSECAP_INDICATOR // on the indicator run the additional serial port for the RP2040 #include "IndicatorSerial.h" +#include "mesh/comms/FakeI2C.h" #endif #if !MESHTASTIC_EXCLUDE_I2C @@ -461,7 +462,11 @@ void setup() fsInit(); #if !MESHTASTIC_EXCLUDE_I2C -#if defined(I2C_SDA1) && defined(ARCH_RP2040) +// The Sensecap Indicator hast I2C on the secondary MCU. Tunnel this as wire1 +#if defined(SENSECAP_INDICATOR) + FakeI2C Wire1 = *FakeWire; + Wire1.begin(); +#elif defined(I2C_SDA1) && defined(ARCH_RP2040) Wire1.setSDA(I2C_SDA1); Wire1.setSCL(I2C_SCL1); Wire1.begin(); @@ -519,7 +524,9 @@ void setup() LOG_INFO("Scan for i2c devices"); #endif -#if defined(I2C_SDA1) && defined(ARCH_RP2040) +#if defined(SENSECAP_INDICATOR) + i2cScanner->scanPort(ScanI2C::I2CPort::WIRE1); +#elif defined(I2C_SDA1) && defined(ARCH_RP2040) Wire1.setSDA(I2C_SDA1); Wire1.setSCL(I2C_SCL1); Wire1.begin(); @@ -754,7 +761,11 @@ void setup() // If we have an indicator, start process to service secondary port #ifdef SENSECAP_INDICATOR - sensecapIndicator.begin(Serial2); +#if SENSOR_PORT_NUM == 2 + sensecapIndicator = new SensecapIndicator(Serial2); +#elif SENSOR_PORT_NUM == 1 + sensecapIndicator = new SensecapIndicator(Serial1); +#endif #endif // only play start melody when role is not tracker or sensor diff --git a/src/mesh/IndicatorSerial.cpp b/src/mesh/IndicatorSerial.cpp index 64794a35d..2cce4594a 100644 --- a/src/mesh/IndicatorSerial.cpp +++ b/src/mesh/IndicatorSerial.cpp @@ -1,24 +1,20 @@ #ifdef SENSECAP_INDICATOR #include "IndicatorSerial.h" -#include "../modules/Telemetry/Sensor/IndicatorSensor.h" -#include "FakeUART.h" +#include "mesh/comms/FakeUART.h" +#include "mesh/comms/FakeI2C.h" #include #include #include -extern IndicatorSensor indicatorSensor; +SensecapIndicator *sensecapIndicator; -SensecapIndicator sensecapIndicator; - -SensecapIndicator::SensecapIndicator() : OSThread("SensecapIndicator") {} - -void SensecapIndicator::begin(HardwareSerial serial) -{ +SensecapIndicator::SensecapIndicator(HardwareSerial &serial) : OSThread("SensecapIndicator") { if (!running) { - _serial = serial; - _serial.setRxBufferSize(PB_BUFSIZE); - _serial.begin(115200); + _serial = &serial; + _serial->setRxBufferSize(PB_BUFSIZE); + _serial->setPins(SENSOR_RP2040_RXD, SENSOR_RP2040_TXD); + _serial->begin(SENSOR_BAUD_RATE); running = true; LOG_DEBUG("Start communication thread"); } @@ -66,8 +62,8 @@ bool SensecapIndicator::send_uplink(meshtastic_InterdeviceMessage message) size_t SensecapIndicator::serial_check(char *buf, size_t space_left) { size_t bytes_read = 0; - while (_serial.available()) { - char c = _serial.read(); + while (_serial->available()) { + char c = _serial->read(); *buf++ = c; if (++bytes_read >= space_left) { LOG_DEBUG("Serial overflow: %d > %d", bytes_read, space_left); @@ -124,8 +120,13 @@ bool SensecapIndicator::handle_packet(size_t payload_len) return false; } switch (message.which_data) { - case meshtastic_InterdeviceMessage_sensor_tag: - indicatorSensor.stuff_buffer(message.data.sensor); + case meshtastic_InterdeviceMessage_i2c_response_tag: + if (message.data.i2c_response.status != meshtastic_I2CResponse_Status_OK) { + LOG_DEBUG("I2C response error: %d", message.data.i2c_response.status); + return false; + } + // send I2C response to FakeI2C + FakeWire->ingest(message.data.i2c_response); return true; break; case meshtastic_InterdeviceMessage_nmea_tag: @@ -142,7 +143,7 @@ bool SensecapIndicator::handle_packet(size_t payload_len) bool SensecapIndicator::send(const char *buf, size_t len) { - size_t wrote = _serial.write(buf, len); + size_t wrote = _serial->write(buf, len); if (wrote == len) return true; return false; diff --git a/src/mesh/IndicatorSerial.h b/src/mesh/IndicatorSerial.h index c1eb19abb..f76e9e2b5 100644 --- a/src/mesh/IndicatorSerial.h +++ b/src/mesh/IndicatorSerial.h @@ -25,8 +25,7 @@ class SensecapIndicator : public concurrency::OSThread { public: - SensecapIndicator(); - void begin(HardwareSerial serial); + SensecapIndicator(HardwareSerial& serial); int32_t runOnce() override; bool send_uplink(meshtastic_InterdeviceMessage message); @@ -34,7 +33,7 @@ class SensecapIndicator : public concurrency::OSThread pb_byte_t pb_tx_buf[PB_BUFSIZE]; pb_byte_t pb_rx_buf[PB_BUFSIZE]; size_t pb_rx_size = 0; // Number of bytes currently in the buffer - HardwareSerial _serial = Serial2; + HardwareSerial* _serial = &Serial2; bool running = false; size_t serial_check(char *buf, size_t space_left); void check_packet(); @@ -42,7 +41,7 @@ class SensecapIndicator : public concurrency::OSThread bool send(const char *buf, size_t len); }; -extern SensecapIndicator sensecapIndicator; +extern SensecapIndicator *sensecapIndicator; #endif // SENSECAP_INDICATOR #endif // INDICATORSERIAL_H \ No newline at end of file diff --git a/src/mesh/comms/FakeI2C.cpp b/src/mesh/comms/FakeI2C.cpp new file mode 100644 index 000000000..cda673682 --- /dev/null +++ b/src/mesh/comms/FakeI2C.cpp @@ -0,0 +1,103 @@ +// File: /master/FakeI2C.cpp + +#include "FakeI2C.h" + +#ifdef SENSECAP_INDICATOR + +FakeI2C *FakeWire; + +void FakeI2C::begin() {} + +void FakeI2C::beginTransmission(uint8_t address) { + _currentAddress = address; + // create a default interdevice message for I2C start + meshtastic_InterdeviceMessage cmd = meshtastic_InterdeviceMessage_init_default; + cmd.which_data = meshtastic_InterdeviceMessage_i2c_command_tag; + cmd.data.i2c_command.op = meshtastic_I2CCommand_Operation_START; + cmd.data.i2c_command.addr = _currentAddress; + sensecapIndicator->send_uplink(cmd); +} + +void FakeI2C::endTransmission() { + meshtastic_InterdeviceMessage cmd = meshtastic_InterdeviceMessage_init_default; + cmd.which_data = meshtastic_InterdeviceMessage_i2c_command_tag; + cmd.data.i2c_command.op = meshtastic_I2CCommand_Operation_STOP; + sensecapIndicator->send_uplink(cmd); +} + +void FakeI2C::write(uint8_t val) { + meshtastic_InterdeviceMessage cmd = meshtastic_InterdeviceMessage_init_default; + cmd.which_data = meshtastic_InterdeviceMessage_i2c_command_tag; + cmd.data.i2c_command.op = meshtastic_I2CCommand_Operation_WRITE; + cmd.data.i2c_command.data = val; + sensecapIndicator->send_uplink(cmd); +} + +uint8_t FakeI2C::requestFrom(uint8_t address, uint8_t quantity) { + if (quantity != 1) return 0xFF; + meshtastic_InterdeviceMessage cmd = meshtastic_InterdeviceMessage_init_default; + cmd.which_data = meshtastic_InterdeviceMessage_i2c_command_tag; + cmd.data.i2c_command.op = meshtastic_I2CCommand_Operation_READ; + cmd.data.i2c_command.addr = address; + cmd.data.i2c_command.ack = false; + sensecapIndicator->send_uplink(cmd); + // Wait for the response coming in asynchronously till there is a timeout + + unsigned long start = millis(); + while (millis() - start < 100) { + if (_pending) { + _pending = false; // Clear the pending flag + return 1; // Indicate that we have read one byte + } + delay(10); // Avoid busy waiting + } + return 0; + } + +int FakeI2C::read() { + return _lastByte; +} + +uint8_t FakeI2C::readRegister(uint8_t reg) { + beginTransmission(_currentAddress); + write(reg); + endTransmission(); + requestFrom(_currentAddress, 1); + return read(); +} + +void FakeI2C::writeRegister(uint8_t reg, uint8_t val) { + beginTransmission(_currentAddress); + write(reg); + write(val); + endTransmission(); +} + +uint16_t FakeI2C::readRegister16(uint8_t reg) { + beginTransmission(_currentAddress); + write(reg); + endTransmission(); + + uint16_t result = 0; + for (int i = 0; i < 2; i++) { + requestFrom(_currentAddress, 1); + result |= ((uint16_t)read()) << (8 * (1 - i)); + } + return result; +} + +void FakeI2C::writeRegister16(uint8_t reg, uint16_t val) { + beginTransmission(_currentAddress); + write(reg); + write((uint8_t)(val >> 8)); + write((uint8_t)(val & 0xFF)); + endTransmission(); +} + +void FakeI2C::ingest(meshtastic_I2CResponse data) { + // Simulate receiving data as if it were from an I2C device + _lastByte = data.data; // Store the last byte read + _pending = true; // Indicate that we have pending data +} + +#endif // SENSECAP_INDICATOR \ No newline at end of file diff --git a/src/mesh/comms/FakeI2C.h b/src/mesh/comms/FakeI2C.h new file mode 100644 index 000000000..7f66ba083 --- /dev/null +++ b/src/mesh/comms/FakeI2C.h @@ -0,0 +1,38 @@ +// File: /master/FakeI2C.h + +#ifndef FAKEI2C_H +#define FAKEI2C_H + +#ifdef SENSECAP_INDICATOR + +#include +#include "../IndicatorSerial.h" +#include "../generated/meshtastic/interdevice.pb.h" + +class FakeI2C { +public: + void begin(); + void beginTransmission(uint8_t address); + void endTransmission(); + void write(uint8_t val); + uint8_t requestFrom(uint8_t address, uint8_t quantity); + int read(); + + uint8_t readRegister(uint8_t reg); + void writeRegister(uint8_t reg, uint8_t val); + uint16_t readRegister16(uint8_t reg); + void writeRegister16(uint8_t reg, uint16_t val); + + void ingest(meshtastic_I2CResponse data); + +private: + uint8_t _currentAddress = 0; + uint8_t _lastByte = 0; + bool _pending = false; // Indicates if there is pending data to be read +}; + +extern FakeI2C *FakeWire; + +#endif // SENSECAP_INDICATOR + +#endif // FAKEI2C_H diff --git a/src/gps/FakeUART.cpp b/src/mesh/comms/FakeUART.cpp similarity index 91% rename from src/gps/FakeUART.cpp rename to src/mesh/comms/FakeUART.cpp index ad5a59630..434d0e6b6 100644 --- a/src/gps/FakeUART.cpp +++ b/src/mesh/comms/FakeUART.cpp @@ -2,6 +2,8 @@ #ifdef SENSECAP_INDICATOR +FakeUART *FakeSerial; + FakeUART::FakeUART() {} void FakeUART::begin(unsigned long baud, uint32_t config, int8_t rxPin, int8_t txPin, bool invert, unsigned long timeout_ms, @@ -9,6 +11,7 @@ void FakeUART::begin(unsigned long baud, uint32_t config, int8_t rxPin, int8_t t { baudrate = baud; FakeBuf.clear(); + LOG_DEBUG("FakeUART::begin(%lu)", baud); } void FakeUART::end() @@ -37,7 +40,7 @@ int FakeUART::read() return -1; } -void FakeUART::flush() +void FakeUART::flush(bool wait) { FakeBuf.clear(); } @@ -74,7 +77,7 @@ size_t FakeUART::write(char *buffer, size_t size) size = sizeof(message.data.nmea); // Truncate if buffer is too large } memcpy(message.data.nmea, buffer, size); - sensecapIndicator.send_uplink(message); + sensecapIndicator->send_uplink(message); return size; } @@ -89,6 +92,4 @@ size_t FakeUART::stuff_buffer(const char *buffer, size_t size) return size; } -FakeUART *FakeSerial; - -#endif \ No newline at end of file +#endif // SENSECAP_INDICATOR \ No newline at end of file diff --git a/src/gps/FakeUART.h b/src/mesh/comms/FakeUART.h similarity index 96% rename from src/gps/FakeUART.h rename to src/mesh/comms/FakeUART.h index c1161d035..f6cd837e3 100644 --- a/src/gps/FakeUART.h +++ b/src/mesh/comms/FakeUART.h @@ -21,7 +21,7 @@ class FakeUART : public Stream int available(); int peek(); int read(); - void flush(); + void flush(bool wait = true); uint32_t baudRate(); void updateBaudRate(unsigned long speed); size_t setRxBufferSize(size_t size); diff --git a/src/modules/Telemetry/EnvironmentTelemetry.cpp b/src/modules/Telemetry/EnvironmentTelemetry.cpp index 46a24a816..8d34a1b5b 100644 --- a/src/modules/Telemetry/EnvironmentTelemetry.cpp +++ b/src/modules/Telemetry/EnvironmentTelemetry.cpp @@ -193,10 +193,6 @@ CGRadSensSensor cgRadSens; #include "Sensor/T1000xSensor.h" T1000xSensor t1000xSensor; #endif -#ifdef SENSECAP_INDICATOR -#include "Sensor/IndicatorSensor.h" -IndicatorSensor indicatorSensor; -#endif #define FAILED_STATE_SENSOR_READ_MULTIPLIER 10 #define DISPLAY_RECEIVEID_MEASUREMENTS_ON_SCREEN true @@ -236,9 +232,6 @@ int32_t EnvironmentTelemetryModule::runOnce() if (moduleConfig.telemetry.environment_measurement_enabled || ENVIRONMENTAL_TELEMETRY_MODULE_ENABLE) { LOG_INFO("Environment Telemetry: init"); -#ifdef SENSECAP_INDICATOR - result = indicatorSensor.runOnce(); -#endif #ifdef T1000X_SENSOR_EN result = t1000xSensor.runOnce(); #elif !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR_EXTERNAL @@ -540,10 +533,6 @@ bool EnvironmentTelemetryModule::getEnvironmentTelemetry(meshtastic_Telemetry *m m->which_variant = meshtastic_Telemetry_environment_metrics_tag; m->variant.environment_metrics = meshtastic_EnvironmentMetrics_init_zero; -#ifdef SENSECAP_INDICATOR - valid = valid && indicatorSensor.getMetrics(m); - hasSensor = true; -#endif #ifdef T1000X_SENSOR_EN // add by WayenWeng valid = valid && t1000xSensor.getMetrics(m); hasSensor = true; diff --git a/src/modules/Telemetry/Sensor/IndicatorSensor.cpp b/src/modules/Telemetry/Sensor/IndicatorSensor.cpp deleted file mode 100644 index 924800b7e..000000000 --- a/src/modules/Telemetry/Sensor/IndicatorSensor.cpp +++ /dev/null @@ -1,91 +0,0 @@ -#include "configuration.h" - -#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && defined(SENSECAP_INDICATOR) - -#include "IndicatorSensor.h" -#include "IndicatorSerial.h" -#include "TelemetrySensor.h" -#include -#include - -IndicatorSensor::IndicatorSensor() : TelemetrySensor(meshtastic_TelemetrySensorType_SENSOR_UNSET, "Indicator") {} - -static int cmd_send(meshtastic_MessageType cmd, uint32_t value) -{ - meshtastic_InterdeviceMessage message = meshtastic_InterdeviceMessage_init_zero; - - message.data.sensor.type = cmd; - message.data.sensor.data.uint32_value = value; - return sensecapIndicator.send_uplink(message); -} - -int32_t IndicatorSensor::runOnce() -{ - LOG_INFO("%s: init", sensorName); - setup(); - return 2 * DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS; // give it some time to start up -} - -void IndicatorSensor::setup() -{ - cmd_send(meshtastic_MessageType_POWER_ON, 0); - // measure and send only once every minute, for the phone API - cmd_send(meshtastic_MessageType_COLLECT_INTERVAL, 60000); -} - -bool IndicatorSensor::getMetrics(meshtastic_Telemetry *measurement) -{ - meshtastic_SensorData data = meshtastic_SensorData_init_zero; - - if (ringBuf.pop(data)) { - - switch (data.type) { - case meshtastic_MessageType_SCD41_CO2: { - - // LOG_DEBUG("CO2: %.1f", value); - - break; - } - - case meshtastic_MessageType_AHT20_TEMP: { - - // LOG_DEBUG("Temp: %.1f", value); - - measurement->variant.environment_metrics.has_temperature = true; - measurement->variant.environment_metrics.temperature = data.data.float_value; - break; - } - - case meshtastic_MessageType_AHT20_HUMIDITY: { - - // LOG_DEBUG("Humidity: %.1f", value); - - measurement->variant.environment_metrics.has_relative_humidity = true; - measurement->variant.environment_metrics.relative_humidity = data.data.float_value; - break; - } - - case meshtastic_MessageType_TVOC_INDEX: { - - // LOG_DEBUG("Tvoc: %.1f", value); - - measurement->variant.environment_metrics.has_iaq = true; - measurement->variant.environment_metrics.iaq = data.data.float_value; - break; - } - default: - break; - } - - return true; - } - return false; -} - -size_t IndicatorSensor::stuff_buffer(meshtastic_SensorData message) -{ - - return ringBuf.push(message) ? 1 : 0; -} - -#endif \ No newline at end of file diff --git a/src/modules/Telemetry/Sensor/IndicatorSensor.h b/src/modules/Telemetry/Sensor/IndicatorSensor.h deleted file mode 100644 index 94ebf9921..000000000 --- a/src/modules/Telemetry/Sensor/IndicatorSensor.h +++ /dev/null @@ -1,25 +0,0 @@ -#include "configuration.h" - -#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR - -#include "../mesh/generated/meshtastic/interdevice.pb.h" -#include "../mesh/generated/meshtastic/telemetry.pb.h" -#include "TelemetrySensor.h" -#include - -class IndicatorSensor : public TelemetrySensor -{ - protected: - virtual void setup() override; - - public: - IndicatorSensor(); - virtual int32_t runOnce() override; - virtual bool getMetrics(meshtastic_Telemetry *measurement) override; - size_t stuff_buffer(meshtastic_SensorData message); - - private: - RingBuf ringBuf; -}; - -#endif \ No newline at end of file