mirror of
https://github.com/meshtastic/firmware.git
synced 2025-12-14 14:52:32 +00:00
Compare commits
14 Commits
native-udp
...
indicator-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
45ecd139e5 | ||
|
|
79db7a5208 | ||
|
|
7289b2a972 | ||
|
|
9356be3f8f | ||
|
|
cce1b050c8 | ||
|
|
fd5ff679f3 | ||
|
|
7a7ef5f0c9 | ||
|
|
f084a8a11d | ||
|
|
37857941bf | ||
|
|
d544b41ab7 | ||
|
|
8c53ce82f2 | ||
|
|
7ee95f2a0c | ||
|
|
65b50babee | ||
|
|
3c30821337 |
@@ -40,7 +40,9 @@ template <typename T, std::size_t N> std::size_t array_count(const T (&)[N])
|
||||
}
|
||||
|
||||
#if defined(NRF52840_XXAA) || defined(NRF52833_XXAA) || defined(ARCH_ESP32) || defined(ARCH_PORTDUINO)
|
||||
#if defined(RAK2560)
|
||||
#if defined(SENSECAP_INDICATOR)
|
||||
FakeUART *GPS::_serial_gps = FakeSerial;
|
||||
#elif defined(RAK2560)
|
||||
HardwareSerial *GPS::_serial_gps = &Serial2;
|
||||
#else
|
||||
HardwareSerial *GPS::_serial_gps = &Serial1;
|
||||
@@ -1076,6 +1078,7 @@ void GPS::publishUpdate()
|
||||
|
||||
int32_t GPS::runOnce()
|
||||
{
|
||||
#if !defined(SENSECAP_INDICATOR)
|
||||
if (!GPSInitFinished) {
|
||||
if (!_serial_gps || config.position.gps_mode == meshtastic_Config_PositionConfig_GpsMode_NOT_PRESENT) {
|
||||
LOG_INFO("GPS set to not-present. Skip probe");
|
||||
@@ -1091,6 +1094,7 @@ int32_t GPS::runOnce()
|
||||
GPSInitFinished = true;
|
||||
publishUpdate();
|
||||
}
|
||||
#endif
|
||||
|
||||
// Repeaters have no need for GPS
|
||||
if (config.device.role == meshtastic_Config_DeviceConfig_Role_REPEATER) {
|
||||
@@ -1409,8 +1413,10 @@ GPS *GPS::createGps()
|
||||
if (!settingsMap[has_gps])
|
||||
return nullptr;
|
||||
#endif
|
||||
#if !defined(SENSECAP_INDICATOR)
|
||||
if (!_rx_gpio || !_serial_gps) // Configured to have no GPS at all
|
||||
return nullptr;
|
||||
#endif
|
||||
|
||||
GPS *new_gps = new GPS;
|
||||
new_gps->rx_gpio = _rx_gpio;
|
||||
|
||||
@@ -11,6 +11,10 @@
|
||||
#include "input/UpDownInterruptImpl1.h"
|
||||
#include "modules/PositionModule.h"
|
||||
|
||||
#ifdef SENSECAP_INDICATOR
|
||||
#include "mesh/comms/FakeUART.h"
|
||||
#endif
|
||||
|
||||
// Allow defining the polarity of the ENABLE output. default is active high
|
||||
#ifndef GPS_EN_ACTIVE
|
||||
#define GPS_EN_ACTIVE 1
|
||||
@@ -188,7 +192,9 @@ class GPS : private concurrency::OSThread
|
||||
CallbackObserver<GPS, void *> notifyDeepSleepObserver = CallbackObserver<GPS, void *>(this, &GPS::prepareDeepSleep);
|
||||
|
||||
/** If !NULL we will use this serial port to construct our GPS */
|
||||
#if defined(ARCH_RP2040)
|
||||
#if defined(SENSECAP_INDICATOR)
|
||||
static FakeUART *_serial_gps;
|
||||
#elif defined(ARCH_RP2040)
|
||||
static SerialUART *_serial_gps;
|
||||
#else
|
||||
static HardwareSerial *_serial_gps;
|
||||
|
||||
24
src/main.cpp
24
src/main.cpp
@@ -22,6 +22,11 @@
|
||||
#include "error.h"
|
||||
#include "power.h"
|
||||
|
||||
#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
|
||||
#include "detect/ScanI2CTwoWire.h"
|
||||
#include <Wire.h>
|
||||
@@ -457,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();
|
||||
@@ -515,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();
|
||||
@@ -748,6 +759,15 @@ void setup()
|
||||
} else
|
||||
router = new ReliableRouter();
|
||||
|
||||
// If we have an indicator, start process to service secondary port
|
||||
#ifdef SENSECAP_INDICATOR
|
||||
#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
|
||||
if (config.power.is_power_saving == true &&
|
||||
IS_ONE_OF(config.device.role, meshtastic_Config_DeviceConfig_Role_TRACKER,
|
||||
|
||||
154
src/mesh/IndicatorSerial.cpp
Normal file
154
src/mesh/IndicatorSerial.cpp
Normal file
@@ -0,0 +1,154 @@
|
||||
#ifdef SENSECAP_INDICATOR
|
||||
|
||||
#include "IndicatorSerial.h"
|
||||
#include "mesh/comms/FakeI2C.h"
|
||||
#include "mesh/comms/FakeUART.h"
|
||||
#include <HardwareSerial.h>
|
||||
#include <pb_decode.h>
|
||||
#include <pb_encode.h>
|
||||
|
||||
SensecapIndicator *sensecapIndicator;
|
||||
|
||||
SensecapIndicator::SensecapIndicator(HardwareSerial &serial) : OSThread("SensecapIndicator")
|
||||
{
|
||||
if (!running) {
|
||||
_serial = &serial;
|
||||
_serial->setRxBufferSize(PB_BUFSIZE);
|
||||
_serial->setPins(SENSOR_RP2040_RXD, SENSOR_RP2040_TXD);
|
||||
_serial->begin(SENSOR_BAUD_RATE);
|
||||
running = true;
|
||||
LOG_DEBUG("Start indicator communication thread");
|
||||
}
|
||||
}
|
||||
|
||||
int32_t SensecapIndicator::runOnce()
|
||||
{
|
||||
if (running) {
|
||||
size_t bytes_read = 0;
|
||||
|
||||
// See if there are any more bytes to add to our buffer.
|
||||
size_t space_left = PB_BUFSIZE - pb_rx_size;
|
||||
|
||||
bytes_read = serial_check((char *)pb_rx_buf + pb_rx_size, space_left);
|
||||
|
||||
pb_rx_size += bytes_read;
|
||||
check_packet();
|
||||
return (10);
|
||||
} else {
|
||||
LOG_DEBUG("Not running");
|
||||
return (1000);
|
||||
}
|
||||
}
|
||||
|
||||
bool SensecapIndicator::send_uplink(meshtastic_InterdeviceMessage message)
|
||||
{
|
||||
pb_tx_buf[0] = MT_MAGIC_0;
|
||||
pb_tx_buf[1] = MT_MAGIC_1;
|
||||
|
||||
pb_ostream_t stream = pb_ostream_from_buffer(pb_tx_buf + MT_HEADER_SIZE, PB_BUFSIZE);
|
||||
if (!pb_encode(&stream, meshtastic_InterdeviceMessage_fields, &message)) {
|
||||
LOG_DEBUG("pb_encode failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Store the payload length in the header
|
||||
pb_tx_buf[2] = stream.bytes_written / 256;
|
||||
pb_tx_buf[3] = stream.bytes_written % 256;
|
||||
|
||||
bool rv = send((const char *)pb_tx_buf, MT_HEADER_SIZE + stream.bytes_written);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
size_t SensecapIndicator::serial_check(char *buf, size_t space_left)
|
||||
{
|
||||
size_t bytes_read = 0;
|
||||
while (_serial->available()) {
|
||||
char c = _serial->read();
|
||||
*buf++ = c;
|
||||
if (++bytes_read >= space_left) {
|
||||
LOG_DEBUG("Serial overflow: %d > %d", bytes_read, space_left);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return bytes_read;
|
||||
}
|
||||
|
||||
void SensecapIndicator::check_packet()
|
||||
{
|
||||
if (pb_rx_size < MT_HEADER_SIZE) {
|
||||
// We don't even have a header yet
|
||||
delay(NO_NEWS_PAUSE);
|
||||
return;
|
||||
}
|
||||
|
||||
if (pb_rx_buf[0] != MT_MAGIC_0 || pb_rx_buf[1] != MT_MAGIC_1) {
|
||||
LOG_DEBUG("Got bad magic");
|
||||
memset(pb_rx_buf, 0, PB_BUFSIZE);
|
||||
pb_rx_size = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
uint16_t payload_len = pb_rx_buf[2] << 8 | pb_rx_buf[3];
|
||||
if (payload_len > PB_BUFSIZE) {
|
||||
LOG_DEBUG("Got packet claiming to be ridiculous length");
|
||||
return;
|
||||
}
|
||||
|
||||
if ((size_t)(payload_len + 4) > pb_rx_size) {
|
||||
delay(NO_NEWS_PAUSE);
|
||||
return;
|
||||
}
|
||||
|
||||
// We have a complete packet, handle it
|
||||
handle_packet(payload_len);
|
||||
}
|
||||
|
||||
bool SensecapIndicator::handle_packet(size_t payload_len)
|
||||
{
|
||||
meshtastic_InterdeviceMessage message = meshtastic_InterdeviceMessage_init_zero;
|
||||
|
||||
// Decode the protobuf and shift forward any remaining bytes in the buffer
|
||||
// (which, if present, belong to the packet that we're going to process on the
|
||||
// next loop)
|
||||
pb_istream_t stream = pb_istream_from_buffer(pb_rx_buf + MT_HEADER_SIZE, payload_len);
|
||||
bool status = pb_decode(&stream, meshtastic_InterdeviceMessage_fields, &message);
|
||||
memmove(pb_rx_buf, pb_rx_buf + MT_HEADER_SIZE + payload_len, PB_BUFSIZE - MT_HEADER_SIZE - payload_len);
|
||||
pb_rx_size -= MT_HEADER_SIZE + payload_len;
|
||||
|
||||
if (!status) {
|
||||
LOG_DEBUG("Decoding failed");
|
||||
return false;
|
||||
}
|
||||
switch (message.which_data) {
|
||||
case meshtastic_InterdeviceMessage_i2c_response_tag:
|
||||
LOG_DEBUG("Got I2C response");
|
||||
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:
|
||||
// send String to NMEA processing
|
||||
FakeSerial->stuff_buffer(message.data.nmea, strlen(message.data.nmea));
|
||||
return true;
|
||||
break;
|
||||
default:
|
||||
// the other messages really only flow downstream
|
||||
LOG_DEBUG("Got a message of unexpected type");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool SensecapIndicator::send(const char *buf, size_t len)
|
||||
{
|
||||
size_t wrote = _serial->write(buf, len);
|
||||
if (wrote == len)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif // SENSECAP_INDICATOR
|
||||
47
src/mesh/IndicatorSerial.h
Normal file
47
src/mesh/IndicatorSerial.h
Normal file
@@ -0,0 +1,47 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef INDICATORSERIAL_H
|
||||
#define INDICATORSERIAL_H
|
||||
|
||||
#ifdef SENSECAP_INDICATOR
|
||||
|
||||
#include "concurrency/OSThread.h"
|
||||
#include "configuration.h"
|
||||
|
||||
#include "mesh/generated/meshtastic/interdevice.pb.h"
|
||||
|
||||
// Magic number at the start of all MT packets
|
||||
#define MT_MAGIC_0 0x94
|
||||
#define MT_MAGIC_1 0xc3
|
||||
|
||||
// The header is the magic number plus a 16-bit payload-length field
|
||||
#define MT_HEADER_SIZE 4
|
||||
|
||||
// Wait this many msec if there's nothing new on the channel
|
||||
#define NO_NEWS_PAUSE 25
|
||||
|
||||
#define PB_BUFSIZE meshtastic_InterdeviceMessage_size + MT_HEADER_SIZE
|
||||
|
||||
class SensecapIndicator : public concurrency::OSThread
|
||||
{
|
||||
public:
|
||||
SensecapIndicator(HardwareSerial &serial);
|
||||
int32_t runOnce() override;
|
||||
bool send_uplink(meshtastic_InterdeviceMessage message);
|
||||
|
||||
private:
|
||||
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;
|
||||
bool running = false;
|
||||
size_t serial_check(char *buf, size_t space_left);
|
||||
void check_packet();
|
||||
bool handle_packet(size_t payload_len);
|
||||
bool send(const char *buf, size_t len);
|
||||
};
|
||||
|
||||
extern SensecapIndicator *sensecapIndicator;
|
||||
|
||||
#endif // SENSECAP_INDICATOR
|
||||
#endif // INDICATORSERIAL_H
|
||||
103
src/mesh/comms/FakeI2C.cpp
Normal file
103
src/mesh/comms/FakeI2C.cpp
Normal file
@@ -0,0 +1,103 @@
|
||||
// File: /master/FakeI2C.cpp
|
||||
|
||||
#include "FakeI2C.h"
|
||||
|
||||
#ifdef SENSECAP_INDICATOR
|
||||
|
||||
FakeI2C *FakeWire = new FakeI2C();
|
||||
|
||||
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
|
||||
38
src/mesh/comms/FakeI2C.h
Normal file
38
src/mesh/comms/FakeI2C.h
Normal file
@@ -0,0 +1,38 @@
|
||||
// File: /master/FakeI2C.h
|
||||
|
||||
#ifndef FAKEI2C_H
|
||||
#define FAKEI2C_H
|
||||
|
||||
#ifdef SENSECAP_INDICATOR
|
||||
|
||||
#include <Arduino.h>
|
||||
#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
|
||||
97
src/mesh/comms/FakeUART.cpp
Normal file
97
src/mesh/comms/FakeUART.cpp
Normal file
@@ -0,0 +1,97 @@
|
||||
#include "FakeUART.h"
|
||||
|
||||
#ifdef SENSECAP_INDICATOR
|
||||
|
||||
FakeUART *FakeSerial = new FakeUART();
|
||||
|
||||
FakeUART::FakeUART() {}
|
||||
|
||||
void FakeUART::begin(unsigned long baud, uint32_t config, int8_t rxPin, int8_t txPin, bool invert, unsigned long timeout_ms,
|
||||
uint8_t rxfifo_full_thrhd)
|
||||
{
|
||||
baudrate = baud;
|
||||
FakeBuf.clear();
|
||||
LOG_DEBUG("FakeUART::begin(%lu)", baud);
|
||||
}
|
||||
|
||||
void FakeUART::end()
|
||||
{
|
||||
FakeBuf.clear();
|
||||
}
|
||||
|
||||
int FakeUART::available()
|
||||
{
|
||||
return FakeBuf.size();
|
||||
}
|
||||
|
||||
int FakeUART::peek()
|
||||
{
|
||||
unsigned char ret;
|
||||
if (FakeBuf.peek(ret))
|
||||
return ret;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int FakeUART::read()
|
||||
{
|
||||
unsigned char ret;
|
||||
if (FakeBuf.pop(ret))
|
||||
return ret;
|
||||
return -1;
|
||||
}
|
||||
|
||||
void FakeUART::flush(bool wait)
|
||||
{
|
||||
FakeBuf.clear();
|
||||
}
|
||||
|
||||
uint32_t FakeUART::baudRate()
|
||||
{
|
||||
return baudrate;
|
||||
}
|
||||
|
||||
void FakeUART::updateBaudRate(unsigned long speed)
|
||||
{
|
||||
baudrate = speed;
|
||||
}
|
||||
|
||||
size_t FakeUART::setRxBufferSize(size_t size)
|
||||
{
|
||||
return size;
|
||||
}
|
||||
|
||||
size_t FakeUART::write(const char *buffer)
|
||||
{
|
||||
return write((char *)buffer, strlen(buffer));
|
||||
}
|
||||
|
||||
size_t FakeUART::write(uint8_t *buffer, size_t size)
|
||||
{
|
||||
return write((char *)buffer, size);
|
||||
}
|
||||
|
||||
size_t FakeUART::write(char *buffer, size_t size)
|
||||
{
|
||||
meshtastic_InterdeviceMessage message = meshtastic_InterdeviceMessage_init_zero;
|
||||
if (size > sizeof(message.data.nmea)) {
|
||||
size = sizeof(message.data.nmea); // Truncate if buffer is too large
|
||||
}
|
||||
memcpy(message.data.nmea, buffer, size);
|
||||
message.which_data = meshtastic_InterdeviceMessage_nmea_tag;
|
||||
LOG_DEBUG("FakeUART::write(%s)", message.data.nmea);
|
||||
sensecapIndicator->send_uplink(message);
|
||||
return size;
|
||||
}
|
||||
|
||||
size_t FakeUART::stuff_buffer(const char *buffer, size_t size)
|
||||
{
|
||||
// push buffer in a loop to FakeBuf
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
if (!FakeBuf.push(buffer[i])) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
#endif // SENSECAP_INDICATOR
|
||||
44
src/mesh/comms/FakeUART.h
Normal file
44
src/mesh/comms/FakeUART.h
Normal file
@@ -0,0 +1,44 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef FAKEUART_H
|
||||
#define FAKEUART_H
|
||||
|
||||
#ifdef SENSECAP_INDICATOR
|
||||
|
||||
#include "../IndicatorSerial.h"
|
||||
#include <RingBuf.h>
|
||||
#include <Stream.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
class FakeUART : public Stream
|
||||
{
|
||||
public:
|
||||
FakeUART();
|
||||
|
||||
void begin(unsigned long baud, uint32_t config = 0x800001c, int8_t rxPin = -1, int8_t txPin = -1, bool invert = false,
|
||||
unsigned long timeout_ms = 20000UL, uint8_t rxfifo_full_thrhd = 112);
|
||||
void end();
|
||||
int available();
|
||||
int peek();
|
||||
int read();
|
||||
void flush(bool wait = true);
|
||||
uint32_t baudRate();
|
||||
void updateBaudRate(unsigned long speed);
|
||||
size_t setRxBufferSize(size_t size);
|
||||
size_t write(const char *buffer);
|
||||
size_t write(char *buffer, size_t size);
|
||||
size_t write(uint8_t *buffer, size_t size);
|
||||
|
||||
size_t stuff_buffer(const char *buffer, size_t size);
|
||||
virtual size_t write(uint8_t c) { return write(&c, 1); }
|
||||
|
||||
private:
|
||||
unsigned long baudrate = 115200;
|
||||
RingBuf<unsigned char, 2048> FakeBuf;
|
||||
};
|
||||
|
||||
extern FakeUART *FakeSerial;
|
||||
|
||||
#endif // SENSECAP_INDICATOR
|
||||
|
||||
#endif // FAKEUART_H
|
||||
@@ -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;
|
||||
|
||||
@@ -1,166 +0,0 @@
|
||||
#include "configuration.h"
|
||||
|
||||
#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && defined(SENSECAP_INDICATOR)
|
||||
|
||||
#include "../mesh/generated/meshtastic/telemetry.pb.h"
|
||||
#include "IndicatorSensor.h"
|
||||
#include "TelemetrySensor.h"
|
||||
#include "serialization/cobs.h"
|
||||
#include <Adafruit_Sensor.h>
|
||||
#include <driver/uart.h>
|
||||
|
||||
IndicatorSensor::IndicatorSensor() : TelemetrySensor(meshtastic_TelemetrySensorType_SENSOR_UNSET, "Indicator") {}
|
||||
|
||||
#define SENSOR_BUF_SIZE (512)
|
||||
|
||||
uint8_t buf[SENSOR_BUF_SIZE]; // recv
|
||||
uint8_t data[SENSOR_BUF_SIZE]; // decode
|
||||
|
||||
#define ACK_PKT_PARA "ACK"
|
||||
|
||||
enum sensor_pkt_type {
|
||||
PKT_TYPE_ACK = 0x00, // uin32_t
|
||||
PKT_TYPE_CMD_COLLECT_INTERVAL = 0xA0, // uin32_t
|
||||
PKT_TYPE_CMD_BEEP_ON = 0xA1, // uin32_t ms: on time
|
||||
PKT_TYPE_CMD_BEEP_OFF = 0xA2,
|
||||
PKT_TYPE_CMD_SHUTDOWN = 0xA3, // uin32_t
|
||||
PKT_TYPE_CMD_POWER_ON = 0xA4,
|
||||
PKT_TYPE_SENSOR_SCD41_TEMP = 0xB0, // float
|
||||
PKT_TYPE_SENSOR_SCD41_HUMIDITY = 0xB1, // float
|
||||
PKT_TYPE_SENSOR_SCD41_CO2 = 0xB2, // float
|
||||
PKT_TYPE_SENSOR_AHT20_TEMP = 0xB3, // float
|
||||
PKT_TYPE_SENSOR_AHT20_HUMIDITY = 0xB4, // float
|
||||
PKT_TYPE_SENSOR_TVOC_INDEX = 0xB5, // float
|
||||
};
|
||||
|
||||
static int cmd_send(uint8_t cmd, const char *p_data, uint8_t len)
|
||||
{
|
||||
uint8_t send_buf[32] = {0};
|
||||
uint8_t send_data[32] = {0};
|
||||
|
||||
if (len > 31) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint8_t index = 1;
|
||||
|
||||
send_data[0] = cmd;
|
||||
|
||||
if (len > 0 && p_data != NULL) {
|
||||
memcpy(&send_data[1], p_data, len);
|
||||
index += len;
|
||||
}
|
||||
cobs_encode_result ret = cobs_encode(send_buf, sizeof(send_buf), send_data, index);
|
||||
|
||||
// LOG_DEBUG("cobs TX status:%d, len:%d, type 0x%x", ret.status, ret.out_len, cmd);
|
||||
|
||||
if (ret.status == COBS_ENCODE_OK) {
|
||||
return uart_write_bytes(SENSOR_PORT_NUM, send_buf, ret.out_len + 1);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
uart_config_t uart_config = {
|
||||
.baud_rate = SENSOR_BAUD_RATE,
|
||||
.data_bits = UART_DATA_8_BITS,
|
||||
.parity = UART_PARITY_DISABLE,
|
||||
.stop_bits = UART_STOP_BITS_1,
|
||||
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
|
||||
.source_clk = UART_SCLK_APB,
|
||||
};
|
||||
int intr_alloc_flags = 0;
|
||||
char buffer[11];
|
||||
|
||||
uart_driver_install(SENSOR_PORT_NUM, SENSOR_BUF_SIZE * 2, 0, 0, NULL, intr_alloc_flags);
|
||||
uart_param_config(SENSOR_PORT_NUM, &uart_config);
|
||||
uart_set_pin(SENSOR_PORT_NUM, SENSOR_RP2040_TXD, SENSOR_RP2040_RXD, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
|
||||
cmd_send(PKT_TYPE_CMD_POWER_ON, NULL, 0);
|
||||
// measure and send only once every minute, for the phone API
|
||||
const char *interval = ultoa(60000, buffer, 10);
|
||||
cmd_send(PKT_TYPE_CMD_COLLECT_INTERVAL, interval, strlen(interval) + 1);
|
||||
}
|
||||
|
||||
bool IndicatorSensor::getMetrics(meshtastic_Telemetry *measurement)
|
||||
{
|
||||
cobs_decode_result ret;
|
||||
int len = uart_read_bytes(SENSOR_PORT_NUM, buf, (SENSOR_BUF_SIZE - 1), 100 / portTICK_PERIOD_MS);
|
||||
|
||||
float value = 0.0;
|
||||
uint8_t *p_buf_start = buf;
|
||||
uint8_t *p_buf_end = buf;
|
||||
if (len > 0) {
|
||||
while (p_buf_start < (buf + len)) {
|
||||
p_buf_end = p_buf_start;
|
||||
while (p_buf_end < (buf + len)) {
|
||||
if (*p_buf_end == 0x00) {
|
||||
break;
|
||||
}
|
||||
p_buf_end++;
|
||||
}
|
||||
// decode buf
|
||||
memset(data, 0, sizeof(data));
|
||||
ret = cobs_decode(data, sizeof(data), p_buf_start, p_buf_end - p_buf_start);
|
||||
|
||||
// LOG_DEBUG("cobs RX status:%d, len:%d, type:0x%x ", ret.status, ret.out_len, data[0]);
|
||||
|
||||
if (ret.out_len > 1 && ret.status == COBS_DECODE_OK) {
|
||||
|
||||
value = 0.0;
|
||||
uint8_t pkt_type = data[0];
|
||||
switch (pkt_type) {
|
||||
case PKT_TYPE_SENSOR_SCD41_CO2: {
|
||||
memcpy(&value, &data[1], sizeof(value));
|
||||
// LOG_DEBUG("CO2: %.1f", value);
|
||||
cmd_send(PKT_TYPE_ACK, ACK_PKT_PARA, 4);
|
||||
break;
|
||||
}
|
||||
|
||||
case PKT_TYPE_SENSOR_AHT20_TEMP: {
|
||||
memcpy(&value, &data[1], sizeof(value));
|
||||
// LOG_DEBUG("Temp: %.1f", value);
|
||||
cmd_send(PKT_TYPE_ACK, ACK_PKT_PARA, 4);
|
||||
measurement->variant.environment_metrics.has_temperature = true;
|
||||
measurement->variant.environment_metrics.temperature = value;
|
||||
break;
|
||||
}
|
||||
|
||||
case PKT_TYPE_SENSOR_AHT20_HUMIDITY: {
|
||||
memcpy(&value, &data[1], sizeof(value));
|
||||
// LOG_DEBUG("Humidity: %.1f", value);
|
||||
cmd_send(PKT_TYPE_ACK, ACK_PKT_PARA, 4);
|
||||
measurement->variant.environment_metrics.has_relative_humidity = true;
|
||||
measurement->variant.environment_metrics.relative_humidity = value;
|
||||
break;
|
||||
}
|
||||
|
||||
case PKT_TYPE_SENSOR_TVOC_INDEX: {
|
||||
memcpy(&value, &data[1], sizeof(value));
|
||||
// LOG_DEBUG("Tvoc: %.1f", value);
|
||||
cmd_send(PKT_TYPE_ACK, ACK_PKT_PARA, 4);
|
||||
measurement->variant.environment_metrics.has_iaq = true;
|
||||
measurement->variant.environment_metrics.iaq = value;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
p_buf_start = p_buf_end + 1; // next message
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,19 +0,0 @@
|
||||
#include "configuration.h"
|
||||
|
||||
#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR
|
||||
|
||||
#include "../mesh/generated/meshtastic/telemetry.pb.h"
|
||||
#include "TelemetrySensor.h"
|
||||
|
||||
class IndicatorSensor : public TelemetrySensor
|
||||
{
|
||||
protected:
|
||||
virtual void setup() override;
|
||||
|
||||
public:
|
||||
IndicatorSensor();
|
||||
virtual int32_t runOnce() override;
|
||||
virtual bool getMetrics(meshtastic_Telemetry *measurement) override;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,129 +0,0 @@
|
||||
#include "cobs.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef SENSECAP_INDICATOR
|
||||
|
||||
cobs_encode_result cobs_encode(uint8_t *dst_buf_ptr, size_t dst_buf_len, const uint8_t *src_ptr, size_t src_len)
|
||||
{
|
||||
|
||||
cobs_encode_result result = {0, COBS_ENCODE_OK};
|
||||
|
||||
if (!dst_buf_ptr || !src_ptr) {
|
||||
result.status = COBS_ENCODE_NULL_POINTER;
|
||||
return result;
|
||||
}
|
||||
|
||||
const uint8_t *src_read_ptr = src_ptr;
|
||||
const uint8_t *src_end_ptr = src_read_ptr + src_len;
|
||||
uint8_t *dst_buf_start_ptr = dst_buf_ptr;
|
||||
uint8_t *dst_buf_end_ptr = dst_buf_start_ptr + dst_buf_len;
|
||||
uint8_t *dst_code_write_ptr = dst_buf_ptr;
|
||||
uint8_t *dst_write_ptr = dst_code_write_ptr + 1;
|
||||
uint8_t search_len = 1;
|
||||
|
||||
if (src_len != 0) {
|
||||
for (;;) {
|
||||
if (dst_write_ptr >= dst_buf_end_ptr) {
|
||||
result.status = (cobs_encode_status)(result.status | (cobs_encode_status)COBS_ENCODE_OUT_BUFFER_OVERFLOW);
|
||||
break;
|
||||
}
|
||||
|
||||
uint8_t src_byte = *src_read_ptr++;
|
||||
if (src_byte == 0) {
|
||||
*dst_code_write_ptr = search_len;
|
||||
dst_code_write_ptr = dst_write_ptr++;
|
||||
search_len = 1;
|
||||
if (src_read_ptr >= src_end_ptr) {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
*dst_write_ptr++ = src_byte;
|
||||
search_len++;
|
||||
if (src_read_ptr >= src_end_ptr) {
|
||||
break;
|
||||
}
|
||||
if (search_len == 0xFF) {
|
||||
*dst_code_write_ptr = search_len;
|
||||
dst_code_write_ptr = dst_write_ptr++;
|
||||
search_len = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (dst_code_write_ptr >= dst_buf_end_ptr) {
|
||||
result.status = (cobs_encode_status)(result.status | (cobs_encode_status)COBS_ENCODE_OUT_BUFFER_OVERFLOW);
|
||||
dst_write_ptr = dst_buf_end_ptr;
|
||||
} else {
|
||||
*dst_code_write_ptr = search_len;
|
||||
}
|
||||
|
||||
result.out_len = dst_write_ptr - dst_buf_start_ptr;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
cobs_decode_result cobs_decode(uint8_t *dst_buf_ptr, size_t dst_buf_len, const uint8_t *src_ptr, size_t src_len)
|
||||
{
|
||||
cobs_decode_result result = {0, COBS_DECODE_OK};
|
||||
|
||||
if (!dst_buf_ptr || !src_ptr) {
|
||||
result.status = COBS_DECODE_NULL_POINTER;
|
||||
return result;
|
||||
}
|
||||
|
||||
const uint8_t *src_read_ptr = src_ptr;
|
||||
const uint8_t *src_end_ptr = src_read_ptr + src_len;
|
||||
uint8_t *dst_buf_start_ptr = dst_buf_ptr;
|
||||
const uint8_t *dst_buf_end_ptr = dst_buf_start_ptr + dst_buf_len;
|
||||
uint8_t *dst_write_ptr = dst_buf_ptr;
|
||||
|
||||
if (src_len != 0) {
|
||||
for (;;) {
|
||||
uint8_t len_code = *src_read_ptr++;
|
||||
if (len_code == 0) {
|
||||
result.status = (cobs_decode_status)(result.status | (cobs_decode_status)COBS_DECODE_ZERO_BYTE_IN_INPUT);
|
||||
break;
|
||||
}
|
||||
len_code--;
|
||||
|
||||
size_t remaining_bytes = src_end_ptr - src_read_ptr;
|
||||
if (len_code > remaining_bytes) {
|
||||
result.status = (cobs_decode_status)(result.status | (cobs_decode_status)COBS_DECODE_INPUT_TOO_SHORT);
|
||||
len_code = remaining_bytes;
|
||||
}
|
||||
|
||||
remaining_bytes = dst_buf_end_ptr - dst_write_ptr;
|
||||
if (len_code > remaining_bytes) {
|
||||
result.status = (cobs_decode_status)(result.status | (cobs_decode_status)COBS_DECODE_OUT_BUFFER_OVERFLOW);
|
||||
len_code = remaining_bytes;
|
||||
}
|
||||
|
||||
for (uint8_t i = len_code; i != 0; i--) {
|
||||
uint8_t src_byte = *src_read_ptr++;
|
||||
if (src_byte == 0) {
|
||||
result.status = (cobs_decode_status)(result.status | (cobs_decode_status)COBS_DECODE_ZERO_BYTE_IN_INPUT);
|
||||
}
|
||||
*dst_write_ptr++ = src_byte;
|
||||
}
|
||||
|
||||
if (src_read_ptr >= src_end_ptr) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (len_code != 0xFE) {
|
||||
if (dst_write_ptr >= dst_buf_end_ptr) {
|
||||
result.status = (cobs_decode_status)(result.status | (cobs_decode_status)COBS_DECODE_OUT_BUFFER_OVERFLOW);
|
||||
break;
|
||||
}
|
||||
*dst_write_ptr++ = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result.out_len = dst_write_ptr - dst_buf_start_ptr;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,75 +0,0 @@
|
||||
#ifndef COBS_H_
|
||||
#define COBS_H_
|
||||
|
||||
#include "configuration.h"
|
||||
|
||||
#ifdef SENSECAP_INDICATOR
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define COBS_ENCODE_DST_BUF_LEN_MAX(SRC_LEN) ((SRC_LEN) + (((SRC_LEN) + 253u) / 254u))
|
||||
#define COBS_DECODE_DST_BUF_LEN_MAX(SRC_LEN) (((SRC_LEN) == 0) ? 0u : ((SRC_LEN)-1u))
|
||||
#define COBS_ENCODE_SRC_OFFSET(SRC_LEN) (((SRC_LEN) + 253u) / 254u)
|
||||
|
||||
typedef enum {
|
||||
COBS_ENCODE_OK = 0x00,
|
||||
COBS_ENCODE_NULL_POINTER = 0x01,
|
||||
COBS_ENCODE_OUT_BUFFER_OVERFLOW = 0x02
|
||||
} cobs_encode_status;
|
||||
|
||||
typedef struct {
|
||||
size_t out_len;
|
||||
cobs_encode_status status;
|
||||
} cobs_encode_result;
|
||||
|
||||
typedef enum {
|
||||
COBS_DECODE_OK = 0x00,
|
||||
COBS_DECODE_NULL_POINTER = 0x01,
|
||||
COBS_DECODE_OUT_BUFFER_OVERFLOW = 0x02,
|
||||
COBS_DECODE_ZERO_BYTE_IN_INPUT = 0x04,
|
||||
COBS_DECODE_INPUT_TOO_SHORT = 0x08
|
||||
} cobs_decode_status;
|
||||
|
||||
typedef struct {
|
||||
size_t out_len;
|
||||
cobs_decode_status status;
|
||||
} cobs_decode_result;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* COBS-encode a string of input bytes.
|
||||
*
|
||||
* dst_buf_ptr: The buffer into which the result will be written
|
||||
* dst_buf_len: Length of the buffer into which the result will be written
|
||||
* src_ptr: The byte string to be encoded
|
||||
* src_len Length of the byte string to be encoded
|
||||
*
|
||||
* returns: A struct containing the success status of the encoding
|
||||
* operation and the length of the result (that was written to
|
||||
* dst_buf_ptr)
|
||||
*/
|
||||
cobs_encode_result cobs_encode(uint8_t *dst_buf_ptr, size_t dst_buf_len, const uint8_t *src_ptr, size_t src_len);
|
||||
|
||||
/* Decode a COBS byte string.
|
||||
*
|
||||
* dst_buf_ptr: The buffer into which the result will be written
|
||||
* dst_buf_len: Length of the buffer into which the result will be written
|
||||
* src_ptr: The byte string to be decoded
|
||||
* src_len Length of the byte string to be decoded
|
||||
*
|
||||
* returns: A struct containing the success status of the decoding
|
||||
* operation and the length of the result (that was written to
|
||||
* dst_buf_ptr)
|
||||
*/
|
||||
cobs_decode_result cobs_decode(uint8_t *dst_buf_ptr, size_t dst_buf_len, const uint8_t *src_ptr, size_t src_len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* SENSECAP_INDICATOR */
|
||||
|
||||
#endif /* COBS_H_ */
|
||||
@@ -9,7 +9,7 @@ board_check = true
|
||||
board_build.partitions = default_8MB.csv
|
||||
upload_protocol = esptool
|
||||
|
||||
build_flags = ${esp32_base.build_flags}
|
||||
build_flags = ${esp32s3_base.build_flags}
|
||||
-Ivariants/seeed-sensecap-indicator
|
||||
-DSENSECAP_INDICATOR
|
||||
-DCONFIG_ARDUHAL_LOG_COLORS
|
||||
@@ -27,7 +27,7 @@ lib_deps = ${esp32s3_base.lib_deps}
|
||||
https://github.com/mverch67/LovyanGFX/archive/4c76238c1344162a234ae917b27651af146d6fb2.zip
|
||||
earlephilhower/ESP8266Audio@^1.9.9
|
||||
earlephilhower/ESP8266SAM@^1.0.1
|
||||
|
||||
locoduino/RingBuffer@^1.0.5
|
||||
|
||||
[env:seeed-sensecap-indicator-tft]
|
||||
extends = env:seeed-sensecap-indicator
|
||||
|
||||
@@ -44,13 +44,7 @@
|
||||
#define TOUCH_I2C_PORT 0
|
||||
#define TOUCH_SLAVE_ADDRESS 0x48
|
||||
|
||||
// in future, we may want to add a buzzer and add all sensors to the indicator via a data protocol for now only GPS is supported
|
||||
// // Buzzer
|
||||
// #define PIN_BUZZER 19
|
||||
|
||||
#define GPS_DEFAULT_NOT_PRESENT 1
|
||||
#define GPS_RX_PIN 20
|
||||
#define GPS_TX_PIN 19
|
||||
#define HAS_GPS 1
|
||||
|
||||
#define USE_SX1262
|
||||
@@ -78,3 +72,7 @@
|
||||
|
||||
#define USE_VIRTUAL_KEYBOARD 1
|
||||
#define DISPLAY_CLOCK_FRAME 1
|
||||
|
||||
// this powers the RP 2040 on boot.
|
||||
#define SENSOR_POWER_CTRL_EXPANDER (8 | IO_EXPANDER)
|
||||
#define SENSOR_POWER_ON_EXPANDER 1
|
||||
|
||||
Reference in New Issue
Block a user