Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b01079a281 | ||
|
|
b9a0100c0d | ||
|
|
65c7112a39 | ||
|
|
6c23fcddf0 | ||
|
|
4d7d021ef5 | ||
|
|
025c6854e8 |
@@ -0,0 +1,42 @@
|
||||
{
|
||||
"build": {
|
||||
"arduino": {
|
||||
"ldscript": "esp32s3_out.ld",
|
||||
"memory_type": "qio_opi"
|
||||
},
|
||||
"core": "esp32",
|
||||
"extra_flags": [
|
||||
"-D BOARD_HAS_PSRAM",
|
||||
"-D ARDUINO_USB_CDC_ON_BOOT=1",
|
||||
"-D ARDUINO_USB_MODE=1",
|
||||
"-D ARDUINO_RUNNING_CORE=1",
|
||||
"-D ARDUINO_EVENT_RUNNING_CORE=1"
|
||||
],
|
||||
"f_cpu": "240000000L",
|
||||
"f_flash": "80000000L",
|
||||
"flash_mode": "qio",
|
||||
"psram_type": "opi",
|
||||
"hwids": [["0x303A", "0x1001"]],
|
||||
"mcu": "esp32s3",
|
||||
"variant": "esp32s3"
|
||||
},
|
||||
"connectivity": ["wifi", "bluetooth", "lora"],
|
||||
"debug": {
|
||||
"default_tool": "esp-builtin",
|
||||
"onboard_tools": ["esp-builtin"],
|
||||
"openocd_target": "esp32s3.cfg"
|
||||
},
|
||||
"frameworks": ["arduino", "espidf"],
|
||||
"name": "seeed_wio_tracker_L2 (16 MB FLASH, 8 MB PSRAM)",
|
||||
"upload": {
|
||||
"flash_size": "16MB",
|
||||
"maximum_ram_size": 327680,
|
||||
"maximum_size": 16777216,
|
||||
"use_1200bps_touch": true,
|
||||
"wait_for_upload_port": true,
|
||||
"require_upload_port": true,
|
||||
"speed": 921600
|
||||
},
|
||||
"url": "https://www.seeedstudio.com/",
|
||||
"vendor": "Seeed Studio"
|
||||
}
|
||||
+1
-1
@@ -126,7 +126,7 @@ lib_deps =
|
||||
[device-ui_base]
|
||||
lib_deps =
|
||||
# renovate: datasource=git-refs depName=meshtastic/device-ui packageName=https://github.com/meshtastic/device-ui gitBranch=master
|
||||
https://github.com/meshtastic/device-ui/archive/34e96d298e78ddf28b7c7e0e82b7bea503abafc3.zip
|
||||
https://github.com/meshtastic/device-ui/archive/c23fdc22f2ba949829661fdf851846fcf7433d89.zip
|
||||
|
||||
; Common libs for environmental measurements in telemetry module
|
||||
[environmental_base]
|
||||
|
||||
+1
-1
@@ -307,7 +307,7 @@ void fsInit()
|
||||
*/
|
||||
void setupSDCard()
|
||||
{
|
||||
#if defined(HAS_SDCARD) && !defined(SDCARD_USE_SOFT_SPI)
|
||||
#if defined(HAS_SDCARD) && !defined(SDCARD_USE_SOFT_SPI) && !defined(HAS_SD_MMC)
|
||||
concurrency::LockGuard g(spiLock);
|
||||
SDHandler.begin(SPI_SCK, SPI_MISO, SPI_MOSI);
|
||||
if (!SD.begin(SDCARD_CS, SDHandler, SD_SPI_FREQUENCY)) {
|
||||
|
||||
+166
@@ -31,6 +31,10 @@
|
||||
#include "input/LinuxInputImpl.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAS_ADS1115
|
||||
#include <Adafruit_ADS1X15.h>
|
||||
#endif
|
||||
|
||||
// Working USB detection for powered/charging states on the RAK platform
|
||||
#ifdef NRF_APM
|
||||
#include "nrfx_power.h"
|
||||
@@ -616,6 +620,164 @@ class AnalogBatteryLevel : public HasBatteryLevel
|
||||
|
||||
static AnalogBatteryLevel analogLevel;
|
||||
|
||||
#ifdef HAS_ADS1115
|
||||
#include "SPILock.h"
|
||||
// AW35615 USB-C CC controller register constants (Arduino Wire, no ESP-IDF dependency)
|
||||
static constexpr uint8_t AW35615_ADDR = 0x22;
|
||||
static constexpr uint8_t AW35615_REG_DEVID = 0x01; // Device ID (probe)
|
||||
static constexpr uint8_t AW35615_REG_ST1A = 0x3D; // STATUS1A: TOGSS[5:3]
|
||||
static constexpr uint8_t AW35615_REG_ST0 = 0x40; // STATUS0: VBUSOK[7]
|
||||
static constexpr uint8_t AW35615_VBUSOK = (1 << 7);
|
||||
static constexpr uint8_t AW35615_TOGSS_MASK = 0x38;
|
||||
static constexpr uint8_t AW35615_TOGSS_SHIFT = 3;
|
||||
static constexpr uint8_t AW35615_TOGSS_SNK_CC1 = 5; // device is sink on CC1
|
||||
static constexpr uint8_t AW35615_TOGSS_SNK_CC2 = 6; // device is sink on CC2
|
||||
|
||||
/**
|
||||
* Battery level sensor using an ADS1115 16-bit ADC on I2C (address 0x48).
|
||||
* Channel 0 is battery voltage through a ×2 resistive divider, so the
|
||||
* measured voltage is multiplied by 2.0 to recover the true cell voltage.
|
||||
* USB/charging state is read from the AW35615 USB-C CC controller (0x22)
|
||||
* when present; falls back to a voltage threshold when not.
|
||||
*/
|
||||
class ADS1115BatteryLevel : public AnalogBatteryLevel
|
||||
{
|
||||
public:
|
||||
bool init()
|
||||
{
|
||||
concurrency::LockGuard guard(spiLock);
|
||||
// Wire is already configured (SDA=47, SCL=48) and the ADC-enable
|
||||
// expander pin (pin 15) is already HIGH from initVariant().
|
||||
if (!_ads.begin(ADS1115_ADDR, &Wire)) {
|
||||
LOG_WARN("ADS1115 not found on I2C bus — battery sensor unavailable");
|
||||
return false;
|
||||
}
|
||||
_ads.setGain(GAIN_TWO); // ±2.048 V FSR matches the voltage-divider ratio
|
||||
initialized = true;
|
||||
LOG_INFO("[ADS1115] battery sensor initialized");
|
||||
|
||||
// Probe and configure AW35615 USB-C CC controller for VBUS / charging detection
|
||||
uint8_t devId = 0;
|
||||
if (aw35615Read(AW35615_REG_DEVID, devId)) {
|
||||
aw35615_initialized = true;
|
||||
LOG_INFO("[AW35615] found at 0x22, DEVICE_ID=0x%02x", devId);
|
||||
// Enable all internal power blocks
|
||||
aw35615Write(0x0B, 0x0F); // POWER = 0x0F
|
||||
// Put Rd (pull-down) resistors on both CC pins → device acts as USB-C sink
|
||||
aw35615Write(0x02, 0x03); // SWITCHES0: PDWN1|PDWN2
|
||||
// Enable sink toggle so the chip detects CC attachment and sets VBUSOK
|
||||
aw35615Write(0x08, 0x05); // CONTROL2: MODE=SINK (2<<1) | TOGGLE=1
|
||||
} else {
|
||||
LOG_WARN("[AW35615] not found at 0x22, falling back to voltage threshold for USB detection");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual uint16_t getBattVoltage() override
|
||||
{
|
||||
if (!initialized) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
concurrency::LockGuard guard(spiLock);
|
||||
static constexpr uint32_t MIN_READ_INTERVAL_MS = 30000;
|
||||
if (!initial_read_done || !Throttle::isWithinTimespanMs(last_read_ms, MIN_READ_INTERVAL_MS)) {
|
||||
last_read_ms = millis();
|
||||
float sum = 0;
|
||||
for (int i = 0; i < SAMPLE_COUNT; i++) {
|
||||
int16_t raw = _ads.readADC_SingleEnded(0);
|
||||
float v = _ads.computeVolts(raw);
|
||||
sum += v;
|
||||
}
|
||||
// Channel 0 sees battery/2 (resistive divider); multiply back, convert to mV
|
||||
float v = (sum / SAMPLE_COUNT) * 2.0f * 1000.0f;
|
||||
if (!initial_read_done) {
|
||||
cached_mv = (uint16_t)v;
|
||||
initial_read_done = true;
|
||||
} else {
|
||||
cached_mv = (uint16_t)(cached_mv + (v - cached_mv) * 0.5f);
|
||||
}
|
||||
}
|
||||
return cached_mv;
|
||||
}
|
||||
|
||||
virtual bool isVbusIn() override
|
||||
{
|
||||
concurrency::LockGuard guard(spiLock);
|
||||
if (aw35615_initialized) {
|
||||
uint8_t st0 = 0;
|
||||
if (aw35615Read(AW35615_REG_ST0, st0)) {
|
||||
bool vbus = (st0 & AW35615_VBUSOK) != 0;
|
||||
//LOG_DEBUG("[AW35615] STATUS0=0x%02x VBUSOK=%d", st0, (int)vbus);
|
||||
return vbus;
|
||||
}
|
||||
}
|
||||
// Fallback: CV-phase voltage threshold
|
||||
static constexpr uint16_t CHARGING_THRESH_MV = (4190 + 10) * NUM_CELLS;
|
||||
return getBattVoltage() > CHARGING_THRESH_MV;
|
||||
}
|
||||
|
||||
virtual bool isCharging() override
|
||||
{
|
||||
if (!isBatteryConnect())
|
||||
return false;
|
||||
if (aw35615_initialized) {
|
||||
concurrency::LockGuard guard(spiLock);
|
||||
uint8_t st1a = 0;
|
||||
if (aw35615Read(AW35615_REG_ST1A, st1a)) {
|
||||
uint8_t togss = (st1a & AW35615_TOGSS_MASK) >> AW35615_TOGSS_SHIFT;
|
||||
bool charging = (togss == AW35615_TOGSS_SNK_CC1 || togss == AW35615_TOGSS_SNK_CC2);
|
||||
//LOG_DEBUG("[AW35615] STATUS1A=0x%02x TOGSS=%d charging=%d", st1a, (int)togss, (int)charging);
|
||||
return charging;
|
||||
}
|
||||
}
|
||||
return isVbusIn();
|
||||
}
|
||||
|
||||
private:
|
||||
// arduino Wire helpers for AW35615 register access
|
||||
bool aw35615Read(uint8_t reg, uint8_t &val)
|
||||
{
|
||||
Wire.beginTransmission(AW35615_ADDR);
|
||||
Wire.write(reg);
|
||||
if (Wire.endTransmission(false) != 0)
|
||||
return false;
|
||||
if (Wire.requestFrom(AW35615_ADDR, (uint8_t)1) != 1)
|
||||
return false;
|
||||
val = Wire.read();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool aw35615Write(uint8_t reg, uint8_t val)
|
||||
{
|
||||
Wire.beginTransmission(AW35615_ADDR);
|
||||
Wire.write(reg);
|
||||
Wire.write(val);
|
||||
return Wire.endTransmission() == 0;
|
||||
}
|
||||
|
||||
static constexpr uint8_t SAMPLE_COUNT = 3;
|
||||
Adafruit_ADS1115 _ads;
|
||||
bool initialized = false;
|
||||
bool aw35615_initialized = false;
|
||||
bool initial_read_done = false;
|
||||
uint16_t cached_mv = 0;
|
||||
uint32_t last_read_ms = 0;
|
||||
};
|
||||
|
||||
static ADS1115BatteryLevel ads1115BattLevel;
|
||||
|
||||
bool Power::ads1115Init()
|
||||
{
|
||||
if (ads1115BattLevel.init()) {
|
||||
batteryLevel = &ads1115BattLevel;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
#endif // HAS_ADS1115
|
||||
|
||||
Power::Power() : OSThread("Power")
|
||||
{
|
||||
statusHandler = {};
|
||||
@@ -725,6 +887,10 @@ bool Power::setup()
|
||||
found = true;
|
||||
} else if (meshSolarInit()) {
|
||||
found = true;
|
||||
#ifdef HAS_ADS1115
|
||||
} else if (ads1115Init()) {
|
||||
found = true;
|
||||
#endif
|
||||
} else if (analogInit()) {
|
||||
found = true;
|
||||
} else {
|
||||
|
||||
+9
-1
@@ -293,6 +293,13 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
// -----------------------------------------------------------------------------
|
||||
#define NCP5623_ADDR 0x38
|
||||
#define LP5562_ADDR 0x30
|
||||
#define LP5814_ADDR 0x2C
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Audio Codec
|
||||
// -----------------------------------------------------------------------------
|
||||
#define ES8311_ADDR 0x18 // same address as MCP9808_ADDR / STK8BXX_ADDR / LIS3DH_ADDR
|
||||
#define ES7243E_ADDR 0x14
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Security
|
||||
@@ -307,10 +314,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
// -----------------------------------------------------------------------------
|
||||
// Touchscreen
|
||||
// -----------------------------------------------------------------------------
|
||||
#define FT6336U_ADDR 0x48
|
||||
#define FT6336U_ADDR 0x48 // same address as ADS1115
|
||||
#define CST328_ADDR 0x1A // same address as CST226SE
|
||||
#define CHSC6X_ADDR 0x2E
|
||||
#define CST226SE_ADDR_ALT 0x5A
|
||||
#define GT911_ADDR 0x5D // same address as SFA30_ADDR / LPS22HB_ADDR_ALT
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// RAK12035VB Soil Monitor (using RAK12023 up to 3 RAK12035 monitors can be connected)
|
||||
|
||||
@@ -48,6 +48,7 @@ class ScanI2C
|
||||
BMA423,
|
||||
BQ24295,
|
||||
LSM6DS3,
|
||||
AW35615,
|
||||
TCA9535,
|
||||
TCA9555,
|
||||
VEML7700,
|
||||
@@ -97,6 +98,10 @@ class ScanI2C
|
||||
CW2015,
|
||||
SCD30,
|
||||
ADS1115,
|
||||
GT911,
|
||||
LP5814,
|
||||
ES8311,
|
||||
ES7243E,
|
||||
} DeviceType;
|
||||
|
||||
// typedef uint8_t DeviceAddress;
|
||||
|
||||
@@ -362,7 +362,14 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
|
||||
#ifdef HAS_LP5562
|
||||
SCAN_SIMPLE_CASE(LP5562_ADDR, LP5562, "LP5562", (uint8_t)addr.address);
|
||||
#endif
|
||||
case XPOWERS_AXP192_AXP2101_ADDRESS:
|
||||
#ifdef HAS_LP5814
|
||||
SCAN_SIMPLE_CASE(LP5814_ADDR, LP5814, "LP5814", (uint8_t)addr.address);
|
||||
#endif
|
||||
#ifdef HAS_ES7243E
|
||||
SCAN_SIMPLE_CASE(ES7243E_ADDR, ES7243E, "ES7243E", (uint8_t)addr.address);
|
||||
#endif
|
||||
case XPOWERS_AXP192_AXP2101_ADDRESS:
|
||||
#ifndef SEEED_WIO_TRACKER_L2 // false positive
|
||||
// Do we have the axp2101/192 or the TCA8418
|
||||
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x90), 1);
|
||||
if (registerValue == 0x0) {
|
||||
@@ -372,6 +379,7 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
|
||||
logFoundDevice("AXP192/AXP2101", (uint8_t)addr.address);
|
||||
type = PMU_AXP192_AXP2101;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case BME_ADDR:
|
||||
case BME_ADDR_ALTERNATE:
|
||||
@@ -479,6 +487,13 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
|
||||
// We need to check for STK8BAXX first, since register 0x07 is new data flag for the z-axis and can produce some
|
||||
// weird result. and register 0x00 doesn't seems to be colliding with MCP9808 and LIS3DH chips.
|
||||
{
|
||||
// Check register 0xFD for 0x83 to ID ES8311 audio codec.
|
||||
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0xFD), 1);
|
||||
if (registerValue == 0x83) {
|
||||
type = ES8311;
|
||||
logFoundDevice("ES8311", (uint8_t)addr.address);
|
||||
break;
|
||||
}
|
||||
#ifdef HAS_STK8XXX
|
||||
// Check register 0x00 for 0x8700 response to ID STK8BA53 chip.
|
||||
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x00), 2);
|
||||
@@ -535,6 +550,22 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
|
||||
break;
|
||||
|
||||
case LPS22HB_ADDR_ALT:
|
||||
// GT911 touchscreen: product ID register 0x8140 returns "911"
|
||||
{
|
||||
uint8_t gt911_reg[] = {0x81, 0x40};
|
||||
uint8_t gt911_buf[4] = {0};
|
||||
i2cBus->beginTransmission(addr.address);
|
||||
i2cBus->write(gt911_reg, 2);
|
||||
if (i2cBus->endTransmission() == 0) {
|
||||
i2cBus->requestFrom((int)addr.address, 4);
|
||||
i2cBus->readBytes(gt911_buf, 4);
|
||||
if (gt911_buf[0] == '9' && gt911_buf[1] == '1' && gt911_buf[2] == '1') {
|
||||
type = GT911;
|
||||
logFoundDevice("GT911", (uint8_t)addr.address);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// SFA30 detection: send 2-byte command 0xD060 (Get Device Marking) and check for 48-byte response
|
||||
if (i2cCommandResponseLength(addr, 0xD060, 48)) {
|
||||
type = SFA30;
|
||||
@@ -591,9 +622,18 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
|
||||
logFoundDevice("BMA423", (uint8_t)addr.address);
|
||||
}
|
||||
break;
|
||||
case RAK120353_ADDR: { // AW35615 USB-C CC controller — must be checked before
|
||||
// RAK120353_ADDR which shares 0x22 but is a TCA9535 variant
|
||||
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x01), 1);
|
||||
if ((registerValue & 0xF0) == 0x90) { // DEVICE_ID upper nibble = 0x9 for AW35615
|
||||
type = AW35615;
|
||||
logFoundDevice("AW35615", (uint8_t)addr.address);
|
||||
break;
|
||||
}
|
||||
// Fall through to TCA9535/RAK check
|
||||
}
|
||||
case TCA9535_ADDR:
|
||||
case RAK120352_ADDR:
|
||||
case RAK120353_ADDR:
|
||||
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x02), 1);
|
||||
if (registerValue == addr.address) { // RAK12035 returns its I2C address at 0x02 (eg 0x20)
|
||||
type = RAK12035;
|
||||
@@ -797,6 +837,17 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
|
||||
break;
|
||||
|
||||
case 0x48: {
|
||||
// Check for ADS1115 FIRST — the SE050 probe below writes 5 bytes
|
||||
// to the device, which corrupts the ADS1115 Lo_thresh register and
|
||||
// leaves its pointer off register 0x01, making the later config-
|
||||
// register read return 0xC000 instead of the expected 0x8583.
|
||||
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x01), 2);
|
||||
if (registerValue == 0x8583 || registerValue == 0x8580) {
|
||||
type = ADS1115;
|
||||
logFoundDevice("ADS1115 ADC", (uint8_t)addr.address);
|
||||
break;
|
||||
}
|
||||
|
||||
i2cBus->beginTransmission(addr.address);
|
||||
uint8_t getInfo[] = {0x5A, 0xC0, 0x00, 0xFF, 0xFC};
|
||||
uint8_t expectedInfo[] = {0xa5, 0xE0, 0x00, 0x3F, 0x19};
|
||||
@@ -811,13 +862,6 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
|
||||
break;
|
||||
}
|
||||
|
||||
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x01), 2);
|
||||
if (registerValue == 0x8583 || registerValue == 0x8580) {
|
||||
type = ADS1115;
|
||||
logFoundDevice("ADS1115 ADC", (uint8_t)addr.address);
|
||||
break;
|
||||
}
|
||||
|
||||
LOG_INFO("FT6336U touchscreen found");
|
||||
type = FT6336U;
|
||||
break;
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
#include "MeshLED.h"
|
||||
|
||||
// Default global instance: no-op dummy. Replace in variant initVariant() for device-specific behaviour.
|
||||
std::shared_ptr<MeshLED> meshLED = std::make_shared<MeshLED>();
|
||||
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
|
||||
/**
|
||||
* Interface for a "mesh activity" LED that lights while the LoRa radio is transmitting.
|
||||
* The default implementation is a no-op; device variants may replace the global instance
|
||||
* with a concrete subclass.
|
||||
*/
|
||||
class MeshLED
|
||||
{
|
||||
public:
|
||||
virtual ~MeshLED() = default;
|
||||
virtual void init() {}
|
||||
virtual void on() {}
|
||||
virtual void off() {}
|
||||
};
|
||||
|
||||
extern std::shared_ptr<MeshLED> meshLED;
|
||||
+1
-1
@@ -696,7 +696,7 @@ void NodeDB::installDefaultConfig(bool preserveKey = false)
|
||||
strncpy(config.network.ntp_server, "meshtastic.pool.ntp.org", 32);
|
||||
|
||||
#if (defined(T_DECK) || defined(T_WATCH_S3) || defined(UNPHONE) || defined(PICOMPUTER_S3) || defined(SENSECAP_INDICATOR) || \
|
||||
defined(ELECROW_PANEL) || defined(HELTEC_V4_TFT) || defined(HELTEC_V4_R8_TFT)) && \
|
||||
defined(ELECROW_PANEL) || defined(HELTEC_V4_TFT) || defined(HELTEC_V4_R8_TFT) || defined(SEEED_WIO_TRACKER_L2)) && \
|
||||
HAS_TFT
|
||||
// switch BT off by default; use TFT programming mode or hotkey to enable
|
||||
config.bluetooth.enabled = false;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "RadioLibInterface.h"
|
||||
#include "MeshLED.h"
|
||||
#include "MeshTypes.h"
|
||||
#include "NodeDB.h"
|
||||
#include "PowerMon.h"
|
||||
@@ -425,6 +426,7 @@ void RadioLibInterface::completeSending()
|
||||
auto p = sendingPacket;
|
||||
sendingPacket = NULL;
|
||||
|
||||
meshLED->off();
|
||||
if (p) {
|
||||
// Packet has been sent, count it toward our TX airtime utilization.
|
||||
uint32_t xmitMsec = getPacketTime(p);
|
||||
@@ -596,6 +598,7 @@ bool RadioLibInterface::startSend(meshtastic_MeshPacket *txp)
|
||||
powerMon->clearState(meshtastic_PowerMon_State_Lora_TXOn); // Transmitter off now
|
||||
startReceive(); // Restart receive mode (because startTransmit failed to put us in xmit mode)
|
||||
} else {
|
||||
meshLED->on();
|
||||
// Must be done AFTER, starting transmit, because startTransmit clears (possibly stale) interrupt pending register
|
||||
// bits
|
||||
enableInterrupt(isrTxLevel0);
|
||||
|
||||
@@ -121,6 +121,10 @@ class Power : public concurrency::OSThread
|
||||
bool meshSolarInit();
|
||||
/// Setup a serial battery sensor
|
||||
bool serialBatteryInit();
|
||||
#ifdef HAS_ADS1115
|
||||
/// Setup ADS1115 I2C battery level sensor
|
||||
bool ads1115Init();
|
||||
#endif
|
||||
|
||||
private:
|
||||
void shutdown();
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
#ifndef Pins_Arduino_h
|
||||
#define Pins_Arduino_h
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
static const uint8_t SDA = 47;
|
||||
static const uint8_t SCL = 48;
|
||||
|
||||
// Default SPI will be mapped to Radio
|
||||
static const uint8_t SS = 21;
|
||||
static const uint8_t MOSI = 6;
|
||||
static const uint8_t MISO = 5;
|
||||
static const uint8_t SCK = 4;
|
||||
|
||||
#endif /* Pins_Arduino_h */
|
||||
@@ -0,0 +1,69 @@
|
||||
[env:seeed_wio_tracker_L2]
|
||||
custom_meshtastic_hw_model = 99 ; TODO: assign a unique number to this hardware model
|
||||
custom_meshtastic_hw_model_slug = SEEED_WIO_TRACKER_L2
|
||||
custom_meshtastic_architecture = esp32s3
|
||||
custom_meshtastic_actively_supported = true
|
||||
custom_meshtastic_support_level = 1
|
||||
custom_meshtastic_display_name = Seeed Wio Tracker L2
|
||||
custom_meshtastic_images = wio_tracker_l2_case.svg
|
||||
custom_meshtastic_tags = Seeed
|
||||
custom_meshtastic_requires_dfu = true
|
||||
|
||||
board = seeed_wio_tracker_L2
|
||||
board_level = pr
|
||||
extends = esp32s3_base
|
||||
board_check = true
|
||||
upload_protocol = esptool
|
||||
board_build.partitions = default_16MB.csv
|
||||
build_flags = ${esp32s3_base.build_flags}
|
||||
-I variants/esp32s3/seeed_wio_tracker_L2
|
||||
-D SEEED_WIO_TRACKER_L2
|
||||
-D CONFIG_ARDUHAL_ESP_LOG
|
||||
-D CONFIG_ARDUHAL_LOG_COLORS=1
|
||||
-D CONFIG_DISABLE_HAL_LOCKS=1
|
||||
-D MESHTASTIC_EXCLUDE_WEBSERVER=1
|
||||
-D LV_LVGL_H_INCLUDE_SIMPLE
|
||||
-D LV_CONF_INCLUDE_SIMPLE
|
||||
-D LV_COMP_CONF_INCLUDE_SIMPLE
|
||||
-D INPUTDRIVER_BUTTON_TYPE=0
|
||||
-D LV_USE_LOG=0
|
||||
-D LV_BUILD_TEST=0
|
||||
-D USE_LOG_DEBUG
|
||||
-D LOG_DEBUG_INC=\"DebugConfiguration.h\"
|
||||
-D RADIOLIB_SPI_PARANOID=0
|
||||
-D HAS_SCREEN=0
|
||||
-D HAS_TFT=1
|
||||
-D USE_I2S_BUZZER
|
||||
-D HAS_SDCARD
|
||||
-D HAS_SD_MMC ; SDIO mode 1-bit
|
||||
-D SD_SCLK_PIN=2
|
||||
-D SD_MOSI_PIN=3 ; CMD
|
||||
-D SD_MISO_PIN=1 ; D0
|
||||
-D SDCARD_CS=-1
|
||||
-D RAM_SIZE=5120
|
||||
-D LGFX_BUFSIZE=153600
|
||||
-D LV_CACHE_DEF_SIZE=2097152
|
||||
-D DISPLAY_SIZE=320x240 ; landscape mode
|
||||
-D LGFX_DRIVER=LGFX_WIO_TRACKER_L2
|
||||
-D GFX_DRIVER_INC=\"graphics/LGFX/LGFX_WIO_TRACKER_L2.h\"
|
||||
-D VIEW_320x240
|
||||
-D MAP_FULL_REDRAW
|
||||
-D USE_PACKET_API
|
||||
|
||||
|
||||
build_src_filter = ${esp32s3_base.build_src_filter} +<../variants/esp32s3/seeed_wio_tracker_L2>
|
||||
lib_deps =
|
||||
${esp32s3_base.lib_deps}
|
||||
${device-ui_base.lib_deps}
|
||||
# renovate: datasource=git-refs depName=ESP8266Audio packageName=https://github.com/meshtastic/ESP8266Audio gitBranch=meshtastic-2.0.0-dacfix
|
||||
https://github.com/meshtastic/ESP8266Audio/archive/343024632ee78d6216907b2353fc943a62422d80.zip
|
||||
# renovate: datasource=custom.pio depName=ESP8266SAM packageName=earlephilhower/library/ESP8266SAM
|
||||
earlephilhower/ESP8266SAM@1.1.0
|
||||
# renovate: datasource=github-tags depName=pschatzmann_arduino-audio-driver packageName=pschatzmann/arduino-audio-driver
|
||||
https://github.com/pschatzmann/arduino-audio-driver/archive/v0.2.1.zip
|
||||
# renovate: datasource=github-tags depName=RobTillaart_TCA9555 packageName=RobTillaart/TCA9555
|
||||
https://github.com/RobTillaart/TCA9555/archive/refs/tags/0.4.4.zip
|
||||
# renovate: datasource=github-tags depName=LovyanGFX packageName=lovyan03/LovyanGFX
|
||||
https://github.com/lovyan03/LovyanGFX/archive/29c590749059be69698eaeccaf4da6596755455d.zip
|
||||
# renovate: datasource=github-tags depName=Adafruit_ADS1X15 packageName=adafruit/Adafruit_ADS1X15
|
||||
https://github.com/adafruit/Adafruit_ADS1X15/archive/refs/tags/2.6.2.zip
|
||||
@@ -0,0 +1,107 @@
|
||||
#include "variant.h"
|
||||
#include "TCA9555.h"
|
||||
#include "AudioBoard.h"
|
||||
#include "DebugConfiguration.h"
|
||||
#include "mesh/MeshLED.h"
|
||||
|
||||
TCA9535 ioExpander(0x21);
|
||||
DriverPins PinsAudioBoardES8311;
|
||||
AudioBoard board(AudioDriverES8311, PinsAudioBoardES8311);
|
||||
|
||||
class WioTrackerMeshLED : public MeshLED
|
||||
{
|
||||
public:
|
||||
void init() override { ioExpander.write1(10, LOW); } // ensure LED starts off
|
||||
void on() override { ioExpander.write1(10, HIGH); }
|
||||
void off() override { ioExpander.write1(10, LOW); }
|
||||
};
|
||||
|
||||
static bool initOK = false;
|
||||
|
||||
void initVariant()
|
||||
{
|
||||
Wire.begin(I2C_SDA, I2C_SCL);
|
||||
if (ioExpander.begin()) {
|
||||
ioExpander.pinMode1(0, INPUT); // wakeup button
|
||||
ioExpander.pinMode1(1, INPUT); // IIC IRQ
|
||||
ioExpander.pinMode1(2, INPUT); // SD detect
|
||||
|
||||
ioExpander.pinMode1(11, OUTPUT); // OTG EN
|
||||
ioExpander.write1(11, LOW); // OTG EN low
|
||||
delay(10);
|
||||
ioExpander.pinMode1(12, OUTPUT); // PA EN
|
||||
ioExpander.write1(12, HIGH); // PA EN high
|
||||
delay(10);
|
||||
ioExpander.pinMode1(14, OUTPUT); // TF EN
|
||||
ioExpander.write1(14, HIGH); // TF EN high
|
||||
delay(10);
|
||||
ioExpander.pinMode1(15, OUTPUT); // BAT ADC EN
|
||||
ioExpander.write1(15, HIGH); // BAT ADC EN high
|
||||
delay(10);
|
||||
ioExpander.pinMode1(13, OUTPUT); // GNSS EN
|
||||
ioExpander.write1(13, HIGH); // GNSS EN high
|
||||
delay(10);
|
||||
ioExpander.pinMode1(9, OUTPUT); // GNSS RST (active HIGH on this board)
|
||||
// Expander output defaults to HIGH, so module is already in reset.
|
||||
// Hold reset for 10ms, then release LOW so the module starts running.
|
||||
delay(10);
|
||||
ioExpander.write1(9, LOW); // release reset - module starts running
|
||||
ioExpander.pinMode1(10, OUTPUT); // User LED / GNSS wakeup
|
||||
ioExpander.write1(10, LOW); // User LED / GNSS wakeup low
|
||||
delay(10);
|
||||
ioExpander.pinMode1(7, OUTPUT); // GROVE EN
|
||||
ioExpander.write1(7, HIGH); // GROVE EN high
|
||||
delay(10);
|
||||
|
||||
ioExpander.pinMode1(5, OUTPUT); // LCD EN
|
||||
ioExpander.write1(5, HIGH); // LCD EN high
|
||||
delay(50);
|
||||
ioExpander.pinMode1(6, OUTPUT); // LCD RST
|
||||
ioExpander.write1(6, HIGH); // LCD RST high
|
||||
delay(5);
|
||||
ioExpander.write1(6, LOW); // LCD RST low
|
||||
delay(10);
|
||||
ioExpander.write1(6, HIGH); // LCD RST high
|
||||
delay(500);
|
||||
ioExpander.pinMode1(4, OUTPUT); // LCD CS
|
||||
ioExpander.write1(4, HIGH); // LCD CS high
|
||||
delay(10);
|
||||
|
||||
ioExpander.pinMode1(8, OUTPUT); // TP RST
|
||||
ioExpander.write1(8, LOW); // TP RST low
|
||||
ioExpander.pinMode1(3, OUTPUT); // TP INT
|
||||
ioExpander.write1(3, LOW); // TP INT low
|
||||
delay(10);
|
||||
ioExpander.write1(3, LOW); // TP INT low
|
||||
delay(1);
|
||||
ioExpander.write1(8, HIGH); // TP RST high
|
||||
delay(60);
|
||||
initOK = true;
|
||||
|
||||
meshLED = std::make_shared<WioTrackerMeshLED>();
|
||||
meshLED->init();
|
||||
}
|
||||
}
|
||||
|
||||
void lateInitVariant()
|
||||
{
|
||||
if (!initOK) {
|
||||
LOG_ERROR("TCA9535 initialization failed");
|
||||
return;
|
||||
}
|
||||
// AudioDriverLogger.begin(Serial, AudioDriverLogLevel::Debug);
|
||||
// I2C: function, scl, sda
|
||||
PinsAudioBoardES8311.addI2C(PinFunction::CODEC, Wire);
|
||||
// I2S: function, mclk, bck, ws, data_out, data_in
|
||||
PinsAudioBoardES8311.addI2S(PinFunction::CODEC, DAC_I2S_MCLK, DAC_I2S_BCK, DAC_I2S_WS, DAC_I2S_DOUT, DAC_I2S_DIN);
|
||||
|
||||
// configure codec
|
||||
CodecConfig cfg;
|
||||
cfg.input_device = ADC_INPUT_LINE1;
|
||||
cfg.output_device = DAC_OUTPUT_ALL;
|
||||
cfg.i2s.bits = BIT_LENGTH_16BITS;
|
||||
cfg.i2s.rate = RATE_44K;
|
||||
board.begin(cfg);
|
||||
board.setVolume(75); // 75% volume
|
||||
LOG_INFO("ES8311 Audio board initialized");
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
#pragma once
|
||||
|
||||
#define BUTTON_PIN 0
|
||||
|
||||
#define I2C_SDA 47
|
||||
#define I2C_SCL 48
|
||||
|
||||
#define USE_POWERSAVE
|
||||
#define SLEEP_TIME 120
|
||||
|
||||
#define HAS_ADS1115
|
||||
#define ADS1115_ADDR 0x48
|
||||
|
||||
// LED controller
|
||||
#define HAS_LP5814
|
||||
|
||||
// ES8311 DAC / AMP
|
||||
#define HAS_I2S
|
||||
|
||||
#define HAS_ES8311
|
||||
#define DAC_I2S_BCK 11 // SCLK
|
||||
#define DAC_I2S_WS 12 // LRLK
|
||||
#define DAC_I2S_DOUT 16
|
||||
#define DAC_I2S_DIN -1
|
||||
#define DAC_I2S_MCLK 10
|
||||
|
||||
#define HAS_ES7243E
|
||||
#define ADC_I2S_BCK 11
|
||||
#define ADC_I2S_WS 12
|
||||
#define ADC_I2S_DOUT -1
|
||||
#define ADC_I2S_DIN 15
|
||||
#define ADC_I2S_MCLK 10
|
||||
|
||||
// SX1262 LoRa Module Pins
|
||||
#define USE_SX1262
|
||||
#define LORA_SCK 4
|
||||
#define LORA_MISO 5
|
||||
#define LORA_MOSI 6
|
||||
#define LORA_CS 21
|
||||
#define LORA_RESET 7
|
||||
|
||||
#define LORA_DIO1 9
|
||||
#define LORA_DIO0 -1
|
||||
#define LORA_DIO2 8
|
||||
#define LORA_DIO3
|
||||
|
||||
#define SX126X_CS LORA_CS
|
||||
#define SX126X_DIO1 LORA_DIO1
|
||||
#define SX126X_BUSY LORA_DIO2
|
||||
#define SX126X_RESET LORA_RESET
|
||||
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
|
||||
#define SX126X_DIO2_AS_RF_SWITCH
|
||||
|
||||
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
// GPS L76KB
|
||||
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
#define GPS_L76K
|
||||
#ifdef GPS_L76K
|
||||
#define GPS_TX_PIN 17
|
||||
#define GPS_RX_PIN 18
|
||||
#define HAS_GPS 1
|
||||
#define GPS_THREAD_INTERVAL 50
|
||||
//#define GPS_EN // TODO: add GPS enable pin control via io/expander
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user