mirror of
https://github.com/meshtastic/firmware.git
synced 2025-02-26 22:33:24 +00:00
Merge branch 'master' into tft-gui-work
This commit is contained in:
commit
38b31a816f
2
.github/workflows/build_native.yml
vendored
2
.github/workflows/build_native.yml
vendored
@ -10,7 +10,7 @@ jobs:
|
||||
build-native:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Install libbluetooth
|
||||
- name: Install libs needed for native build
|
||||
shell: bash
|
||||
run: |
|
||||
sudo apt-get update --fix-missing
|
||||
|
@ -1,4 +1,4 @@
|
||||
name: Test Simulator
|
||||
name: End to end tests
|
||||
|
||||
on:
|
||||
schedule:
|
||||
@ -55,3 +55,37 @@ jobs:
|
||||
name: PlatformIO Tests
|
||||
path: testreport.xml
|
||||
reporter: java-junit
|
||||
|
||||
hardware-tests:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Upgrade python tools
|
||||
shell: bash
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -U --no-build-isolation --no-cache-dir "setuptools<72"
|
||||
pip install -U platformio adafruit-nrfutil --no-build-isolation
|
||||
pip install -U poetry --no-build-isolation
|
||||
pip install -U meshtastic --pre --no-build-isolation
|
||||
|
||||
- name: Upgrade platformio
|
||||
shell: bash
|
||||
run: |
|
||||
pio upgrade
|
||||
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: latest
|
||||
|
||||
- name: Install Dependencies
|
||||
run: pnpm install
|
||||
|
||||
- name: Setup devices
|
||||
run: pnpm run setup
|
||||
|
||||
- name: Execute end to end tests on connected hardware
|
||||
run: pnpm run test
|
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -4,3 +4,6 @@
|
||||
[submodule "lib/device-ui"]
|
||||
path = lib/device-ui
|
||||
url = https://github.com/meshtastic/device-ui.git
|
||||
[submodule "meshtestic"]
|
||||
path = meshtestic
|
||||
url = https://github.com/meshtastic/meshTestic
|
||||
|
1
meshtestic
Submodule
1
meshtestic
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 31ee3d90c8bef61e835c3271be2c7cda8c4a5cc2
|
@ -131,6 +131,7 @@ lib_deps =
|
||||
adafruit/Adafruit BMP280 Library@^2.6.8
|
||||
adafruit/Adafruit BMP085 Library@^1.2.4
|
||||
adafruit/Adafruit BME280 Library@^2.2.2
|
||||
adafruit/Adafruit BMP3XX Library@^2.1.5
|
||||
adafruit/Adafruit MCP9808 Library@^2.0.0
|
||||
adafruit/Adafruit INA260 Library@^1.5.0
|
||||
adafruit/Adafruit INA219@^1.2.0
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 28492e88e515aabf5c886dd23631518d6dee82d7
|
||||
Subproject commit 5f7c91adb97187e0cb2140de7057344d93444bd1
|
@ -10,6 +10,13 @@ void GpioVirtPin::set(bool value)
|
||||
}
|
||||
}
|
||||
|
||||
void GpioHwPin::set(bool value)
|
||||
{
|
||||
// if (num == 3) LOG_DEBUG("Setting pin %d to %d\n", num, value);
|
||||
pinMode(num, OUTPUT);
|
||||
digitalWrite(num, value);
|
||||
}
|
||||
|
||||
GpioTransformer::GpioTransformer(GpioPin *outPin) : outPin(outPin) {}
|
||||
|
||||
void GpioTransformer::set(bool value)
|
||||
@ -17,7 +24,7 @@ void GpioTransformer::set(bool value)
|
||||
outPin->set(value);
|
||||
}
|
||||
|
||||
GpioNotTransformer::GpioNotTransformer(GpioVirtPin *inPin, GpioPin *outPin) : GpioTransformer(outPin), inPin(inPin)
|
||||
GpioUnaryTransformer::GpioUnaryTransformer(GpioVirtPin *inPin, GpioPin *outPin) : GpioTransformer(outPin), inPin(inPin)
|
||||
{
|
||||
assert(!inPin->dependentPin); // We only allow one dependent pin
|
||||
inPin->dependentPin = this;
|
||||
@ -27,6 +34,18 @@ GpioNotTransformer::GpioNotTransformer(GpioVirtPin *inPin, GpioPin *outPin) : Gp
|
||||
// update();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the output pin based on the current state of the input pin.
|
||||
*/
|
||||
void GpioUnaryTransformer::update()
|
||||
{
|
||||
auto p = inPin->get();
|
||||
if (p == GpioVirtPin::PinState::Unset)
|
||||
return; // Not yet fully initialized
|
||||
|
||||
set(p);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the output pin based on the current state of the input pin.
|
||||
*/
|
||||
@ -69,6 +88,7 @@ void GpioBinaryTransformer::update()
|
||||
newValue = (GpioVirtPin::PinState)(p1 && p2);
|
||||
break;
|
||||
case Or:
|
||||
// LOG_DEBUG("Doing GPIO OR\n");
|
||||
newValue = (GpioVirtPin::PinState)(p1 || p2);
|
||||
break;
|
||||
case Xor:
|
||||
|
@ -29,7 +29,7 @@ class GpioHwPin : public GpioPin
|
||||
public:
|
||||
explicit GpioHwPin(uint32_t num) : num(num) {}
|
||||
|
||||
void set(bool value) { digitalWrite(num, value); }
|
||||
void set(bool value);
|
||||
};
|
||||
|
||||
class GpioTransformer;
|
||||
@ -42,7 +42,7 @@ class GpioBinaryTransformer;
|
||||
class GpioVirtPin : public GpioPin
|
||||
{
|
||||
friend class GpioBinaryTransformer;
|
||||
friend class GpioNotTransformer;
|
||||
friend class GpioUnaryTransformer;
|
||||
|
||||
public:
|
||||
enum PinState { On = true, Off = false, Unset = 2 };
|
||||
@ -79,12 +79,31 @@ class GpioTransformer
|
||||
};
|
||||
|
||||
/**
|
||||
* A transformer that performs a unary NOT operation from an input.
|
||||
* A transformer that just drives a hw pin based on a virtual pin.
|
||||
*/
|
||||
class GpioNotTransformer : public GpioTransformer
|
||||
class GpioUnaryTransformer : public GpioTransformer
|
||||
{
|
||||
public:
|
||||
GpioNotTransformer(GpioVirtPin *inPin, GpioPin *outPin);
|
||||
GpioUnaryTransformer(GpioVirtPin *inPin, GpioPin *outPin);
|
||||
|
||||
protected:
|
||||
friend class GpioVirtPin;
|
||||
|
||||
/**
|
||||
* Update the output pin based on the current state of the input pin.
|
||||
*/
|
||||
virtual void update();
|
||||
|
||||
GpioVirtPin *inPin;
|
||||
};
|
||||
|
||||
/**
|
||||
* A transformer that performs a unary NOT operation from an input.
|
||||
*/
|
||||
class GpioNotTransformer : public GpioUnaryTransformer
|
||||
{
|
||||
public:
|
||||
GpioNotTransformer(GpioVirtPin *inPin, GpioPin *outPin) : GpioUnaryTransformer(inPin, outPin) {}
|
||||
|
||||
protected:
|
||||
friend class GpioVirtPin;
|
||||
@ -93,9 +112,6 @@ class GpioNotTransformer : public GpioTransformer
|
||||
* Update the output pin based on the current state of the input pin.
|
||||
*/
|
||||
void update();
|
||||
|
||||
private:
|
||||
GpioVirtPin *inPin;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -136,6 +136,30 @@ using namespace meshtastic;
|
||||
*/
|
||||
static HasBatteryLevel *batteryLevel; // Default to NULL for no battery level sensor
|
||||
|
||||
static void adcEnable()
|
||||
{
|
||||
#ifdef ADC_CTRL // enable adc voltage divider when we need to read
|
||||
#ifdef ADC_USE_PULLUP
|
||||
pinMode(ADC_CTRL, INPUT_PULLUP);
|
||||
#else
|
||||
pinMode(ADC_CTRL, OUTPUT);
|
||||
digitalWrite(ADC_CTRL, ADC_CTRL_ENABLED);
|
||||
#endif
|
||||
delay(10);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void adcDisable()
|
||||
{
|
||||
#ifdef ADC_CTRL // disable adc voltage divider when we need to read
|
||||
#ifdef ADC_USE_PULLUP
|
||||
pinMode(ADC_CTRL, INPUT_PULLDOWN);
|
||||
#else
|
||||
digitalWrite(ADC_CTRL, !ADC_CTRL_ENABLED);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* A simple battery level sensor that assumes the battery voltage is attached via a voltage-divider to an analog input
|
||||
*/
|
||||
@ -226,25 +250,19 @@ class AnalogBatteryLevel : public HasBatteryLevel
|
||||
uint32_t raw = 0;
|
||||
float scaled = 0;
|
||||
|
||||
adcEnable();
|
||||
#ifdef ARCH_ESP32 // ADC block for espressif platforms
|
||||
raw = espAdcRead();
|
||||
scaled = esp_adc_cal_raw_to_voltage(raw, adc_characs);
|
||||
scaled *= operativeAdcMultiplier;
|
||||
#else // block for all other platforms
|
||||
#ifdef ADC_CTRL // enable adc voltage divider when we need to read
|
||||
pinMode(ADC_CTRL, OUTPUT);
|
||||
digitalWrite(ADC_CTRL, ADC_CTRL_ENABLED);
|
||||
delay(10);
|
||||
#endif
|
||||
#else // block for all other platforms
|
||||
for (uint32_t i = 0; i < BATTERY_SENSE_SAMPLES; i++) {
|
||||
raw += analogRead(BATTERY_PIN);
|
||||
}
|
||||
raw = raw / BATTERY_SENSE_SAMPLES;
|
||||
scaled = operativeAdcMultiplier * ((1000 * AREF_VOLTAGE) / pow(2, BATTERY_SENSE_RESOLUTION_BITS)) * raw;
|
||||
#ifdef ADC_CTRL // disable adc voltage divider when we need to read
|
||||
digitalWrite(ADC_CTRL, !ADC_CTRL_ENABLED);
|
||||
#endif
|
||||
#endif
|
||||
adcDisable();
|
||||
|
||||
if (!initial_read_done) {
|
||||
// Flush the smoothing filter with an ADC reading, if the reading is plausibly correct
|
||||
@ -275,11 +293,6 @@ class AnalogBatteryLevel : public HasBatteryLevel
|
||||
uint8_t raw_c = 0; // raw reading counter
|
||||
|
||||
#ifndef BAT_MEASURE_ADC_UNIT // ADC1
|
||||
#ifdef ADC_CTRL // enable adc voltage divider when we need to read
|
||||
pinMode(ADC_CTRL, OUTPUT);
|
||||
digitalWrite(ADC_CTRL, ADC_CTRL_ENABLED);
|
||||
delay(10);
|
||||
#endif
|
||||
for (int i = 0; i < BATTERY_SENSE_SAMPLES; i++) {
|
||||
int val_ = adc1_get_raw(adc_channel);
|
||||
if (val_ >= 0) { // save only valid readings
|
||||
@ -288,18 +301,7 @@ class AnalogBatteryLevel : public HasBatteryLevel
|
||||
}
|
||||
// delayMicroseconds(100);
|
||||
}
|
||||
#ifdef ADC_CTRL // disable adc voltage divider when we need to read
|
||||
digitalWrite(ADC_CTRL, !ADC_CTRL_ENABLED);
|
||||
#endif
|
||||
#else // ADC2
|
||||
#ifdef ADC_CTRL
|
||||
#if defined(HELTEC_WIRELESS_PAPER) || defined(HELTEC_WIRELESS_PAPER_V1_0)
|
||||
pinMode(ADC_CTRL, OUTPUT);
|
||||
digitalWrite(ADC_CTRL, LOW); // ACTIVE LOW
|
||||
delay(10);
|
||||
#endif
|
||||
#endif // End ADC_CTRL
|
||||
|
||||
#else // ADC2
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32S3 // ESP32S3
|
||||
// ADC2 wifi bug workaround not required, breaks compile
|
||||
// On ESP32S3, ADC2 can take turns with Wifi (?)
|
||||
@ -334,12 +336,6 @@ class AnalogBatteryLevel : public HasBatteryLevel
|
||||
}
|
||||
#endif // BAT_MEASURE_ADC_UNIT
|
||||
|
||||
#ifdef ADC_CTRL
|
||||
#if defined(HELTEC_WIRELESS_PAPER) || defined(HELTEC_WIRELESS_PAPER_V1_0)
|
||||
digitalWrite(ADC_CTRL, HIGH);
|
||||
#endif
|
||||
#endif // End ADC_CTRL
|
||||
|
||||
#endif // End BAT_MEASURE_ADC_UNIT
|
||||
return (raw / (raw_c < 1 ? 1 : raw_c));
|
||||
}
|
||||
|
@ -177,6 +177,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
/* Step #1: offer chance for variant-specific defines */
|
||||
#include "variant.h"
|
||||
|
||||
#if defined(VEXT_ENABLE) && !defined(VEXT_ON_VALUE)
|
||||
// Older variant.h files might not be defining this value, so stay with the old default
|
||||
#define VEXT_ON_VALUE LOW
|
||||
#endif
|
||||
|
||||
#ifndef GPS_BAUDRATE
|
||||
#define GPS_BAUDRATE 9600
|
||||
#endif
|
||||
|
@ -24,6 +24,7 @@ class ScanI2C
|
||||
BME_280,
|
||||
BMP_280,
|
||||
BMP_085,
|
||||
BMP_3XX,
|
||||
INA260,
|
||||
INA219,
|
||||
INA3221,
|
||||
|
@ -267,8 +267,19 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
|
||||
type = BMP_085;
|
||||
break;
|
||||
default:
|
||||
LOG_INFO("BMP-280 sensor found at address 0x%x\n", (uint8_t)addr.address);
|
||||
type = BMP_280;
|
||||
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x00), 1); // GET_ID
|
||||
switch (registerValue) {
|
||||
case 0x50: // BMP-388 should be 0x50
|
||||
LOG_INFO("BMP-388 sensor found at address 0x%x\n", (uint8_t)addr.address);
|
||||
type = BMP_3XX;
|
||||
break;
|
||||
case 0x58: // BMP-280 should be 0x58
|
||||
default:
|
||||
LOG_INFO("BMP-280 sensor found at address 0x%x\n", (uint8_t)addr.address);
|
||||
type = BMP_280;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
#ifndef HAS_NCP5623
|
||||
|
@ -2,6 +2,7 @@
|
||||
#if !MESHTASTIC_EXCLUDE_GPS
|
||||
#include "Default.h"
|
||||
#include "GPS.h"
|
||||
#include "GpioLogic.h"
|
||||
#include "NodeDB.h"
|
||||
#include "PowerMon.h"
|
||||
#include "RTC.h"
|
||||
@ -876,16 +877,8 @@ void GPS::writePinEN(bool on)
|
||||
if (HW_VENDOR == meshtastic_HardwareModel_RAK4631 && (rotaryEncoderInterruptImpl1 || upDownInterruptImpl1))
|
||||
return;
|
||||
|
||||
// Abort: if pin unset
|
||||
if (!en_gpio)
|
||||
return;
|
||||
|
||||
// Determine new value for the pin
|
||||
bool val = GPS_EN_ACTIVE ? on : !on;
|
||||
|
||||
// Write and log
|
||||
pinMode(en_gpio, OUTPUT);
|
||||
digitalWrite(en_gpio, val);
|
||||
enablePin->set(on);
|
||||
#ifdef GPS_EXTRAVERBOSE
|
||||
LOG_DEBUG("Pin EN %s\n", val == HIGH ? "HIGH" : "LOW");
|
||||
#endif
|
||||
@ -1422,7 +1415,20 @@ GPS *GPS::createGps()
|
||||
GPS *new_gps = new GPS;
|
||||
new_gps->rx_gpio = _rx_gpio;
|
||||
new_gps->tx_gpio = _tx_gpio;
|
||||
new_gps->en_gpio = _en_gpio;
|
||||
|
||||
GpioVirtPin *virtPin = new GpioVirtPin();
|
||||
new_gps->enablePin = virtPin; // Always at least populate a virtual pin
|
||||
if (_en_gpio) {
|
||||
GpioPin *p = new GpioHwPin(_en_gpio);
|
||||
|
||||
if (!GPS_EN_ACTIVE) { // Need to invert the pin before hardware
|
||||
new GpioNotTransformer(
|
||||
virtPin, p); // We just leave this created object on the heap so it can stay watching virtPin and driving en_gpio
|
||||
} else {
|
||||
new GpioUnaryTransformer(
|
||||
virtPin, p); // We just leave this created object on the heap so it can stay watching virtPin and driving en_gpio
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef PIN_GPS_PPS
|
||||
// pulse per second
|
||||
|
@ -3,6 +3,7 @@
|
||||
#if !MESHTASTIC_EXCLUDE_GPS
|
||||
|
||||
#include "GPSStatus.h"
|
||||
#include "GpioLogic.h"
|
||||
#include "Observer.h"
|
||||
#include "TinyGPS++.h"
|
||||
#include "concurrency/OSThread.h"
|
||||
@ -73,7 +74,6 @@ class GPS : private concurrency::OSThread
|
||||
uint32_t lastWakeStartMsec = 0, lastSleepStartMsec = 0, lastFixStartMsec = 0;
|
||||
uint32_t rx_gpio = 0;
|
||||
uint32_t tx_gpio = 0;
|
||||
uint32_t en_gpio = 0;
|
||||
|
||||
int speedSelect = 0;
|
||||
int probeTries = 2;
|
||||
@ -152,6 +152,13 @@ class GPS : private concurrency::OSThread
|
||||
|
||||
meshtastic_Position p = meshtastic_Position_init_default;
|
||||
|
||||
/** This is normally bound to config.position.gps_en_gpio but some rare boards (like heltec tracker) need more advanced
|
||||
* implementations. Those boards will set this public variable to a custom implementation.
|
||||
*
|
||||
* Normally set by GPS::createGPS()
|
||||
*/
|
||||
GpioVirtPin *enablePin = NULL;
|
||||
|
||||
GPS() : concurrency::OSThread("GPS") {}
|
||||
|
||||
virtual ~GPS();
|
||||
@ -303,4 +310,4 @@ class GPS : private concurrency::OSThread
|
||||
};
|
||||
|
||||
extern GPS *gps;
|
||||
#endif // Exclude GPS
|
||||
#endif // Exclude GPS
|
@ -309,7 +309,7 @@ class Screen : public concurrency::OSThread
|
||||
static char customFontTableLookup(const uint8_t ch)
|
||||
{
|
||||
// UTF-8 to font table index converter
|
||||
// Code form http://playground.arduino.cc/Main/Utf8ascii
|
||||
// Code from http://playground.arduino.cc/Main/Utf8ascii
|
||||
static uint8_t LASTCHAR;
|
||||
static bool SKIPREST; // Only display a single unconvertable-character symbol per sequence of unconvertable characters
|
||||
|
||||
@ -322,13 +322,20 @@ class Screen : public concurrency::OSThread
|
||||
uint8_t last = LASTCHAR; // get last char
|
||||
LASTCHAR = ch;
|
||||
|
||||
#if defined(OLED_PL)
|
||||
|
||||
switch (last) { // conversion depending on first UTF8-character
|
||||
switch (last) {
|
||||
case 0xC2: {
|
||||
SKIPREST = false;
|
||||
return (uint8_t)ch;
|
||||
}
|
||||
}
|
||||
|
||||
// We want to strip out prefix chars for two-byte char formats
|
||||
if (ch == 0xC2)
|
||||
return (uint8_t)0;
|
||||
|
||||
#if defined(OLED_PL)
|
||||
|
||||
switch (last) {
|
||||
case 0xC3: {
|
||||
|
||||
if (ch == 147)
|
||||
@ -365,11 +372,7 @@ class Screen : public concurrency::OSThread
|
||||
|
||||
#if defined(OLED_UA) || defined(OLED_RU)
|
||||
|
||||
switch (last) { // conversion depending on first UTF8-character
|
||||
case 0xC2: {
|
||||
SKIPREST = false;
|
||||
return (uint8_t)ch;
|
||||
}
|
||||
switch (last) {
|
||||
case 0xC3: {
|
||||
SKIPREST = false;
|
||||
return (uint8_t)(ch | 0xC0);
|
||||
|
@ -21,10 +21,6 @@ extern SX1509 gpioExtender;
|
||||
#if defined(ST7735S)
|
||||
#include <LovyanGFX.hpp> // Graphics and font library for ST7735 driver chip
|
||||
|
||||
#if defined(ST7735_BACKLIGHT_EN) && !defined(TFT_BL)
|
||||
#define TFT_BL ST7735_BACKLIGHT_EN
|
||||
#endif
|
||||
|
||||
#ifndef TFT_INVERT
|
||||
#define TFT_INVERT true
|
||||
#endif
|
||||
@ -91,24 +87,20 @@ class LGFX : public lgfx::LGFX_Device
|
||||
_panel_instance.config(cfg);
|
||||
}
|
||||
|
||||
#ifdef TFT_BL
|
||||
// Set the backlight control
|
||||
{
|
||||
auto cfg = _light_instance.config(); // Gets a structure for backlight settings.
|
||||
|
||||
#ifdef ST7735_BL_V03
|
||||
cfg.pin_bl = ST7735_BL_V03;
|
||||
#elif defined(ST7735_BL_V05)
|
||||
cfg.pin_bl = ST7735_BL_V05;
|
||||
#else
|
||||
cfg.pin_bl = ST7735_BL; // Pin number to which the backlight is connected
|
||||
#endif
|
||||
cfg.invert = true; // true to invert the brightness of the backlight
|
||||
cfg.pin_bl = TFT_BL; // Pin number to which the backlight is connected
|
||||
cfg.invert = true; // true to invert the brightness of the backlight
|
||||
// cfg.freq = 44100; // PWM frequency of backlight
|
||||
// cfg.pwm_channel = 1; // PWM channel number to use
|
||||
|
||||
_light_instance.config(cfg);
|
||||
_panel_instance.setLight(&_light_instance); // Set the backlight on the panel.
|
||||
}
|
||||
#endif
|
||||
|
||||
setPanel(&_panel_instance);
|
||||
}
|
||||
@ -131,10 +123,6 @@ static void rak14014_tpIntHandle(void)
|
||||
#elif defined(ST7789_CS)
|
||||
#include <LovyanGFX.hpp> // Graphics and font library for ST7735 driver chip
|
||||
|
||||
#if defined(ST7789_BACKLIGHT_EN) && !defined(TFT_BL)
|
||||
#define TFT_BL ST7789_BACKLIGHT_EN
|
||||
#endif
|
||||
|
||||
class LGFX : public lgfx::LGFX_Device
|
||||
{
|
||||
lgfx::Panel_ST7789 _panel_instance;
|
||||
@ -204,6 +192,7 @@ class LGFX : public lgfx::LGFX_Device
|
||||
_panel_instance.config(cfg);
|
||||
}
|
||||
|
||||
#ifdef ST7789_BL
|
||||
// Set the backlight control. (delete if not necessary)
|
||||
{
|
||||
auto cfg = _light_instance.config(); // Gets a structure for backlight settings.
|
||||
@ -215,6 +204,7 @@ class LGFX : public lgfx::LGFX_Device
|
||||
_light_instance.config(cfg);
|
||||
_panel_instance.setLight(&_light_instance); // Set the backlight on the panel.
|
||||
}
|
||||
#endif
|
||||
|
||||
#if HAS_TOUCHSCREEN
|
||||
// Configure settings for touch screen control.
|
||||
@ -324,6 +314,7 @@ class LGFX : public lgfx::LGFX_Device
|
||||
_panel_instance.config(cfg);
|
||||
}
|
||||
|
||||
#ifdef TFT_BL
|
||||
// Set the backlight control
|
||||
{
|
||||
auto cfg = _light_instance.config(); // Gets a structure for backlight settings.
|
||||
@ -336,6 +327,7 @@ class LGFX : public lgfx::LGFX_Device
|
||||
_light_instance.config(cfg);
|
||||
_panel_instance.setLight(&_light_instance); // Set the backlight on the panel.
|
||||
}
|
||||
#endif
|
||||
|
||||
setPanel(&_panel_instance);
|
||||
}
|
||||
@ -532,9 +524,26 @@ static LGFX *tft = nullptr;
|
||||
extern unPhone unphone;
|
||||
#endif
|
||||
|
||||
GpioPin *TFTDisplay::backlightEnable = NULL;
|
||||
|
||||
TFTDisplay::TFTDisplay(uint8_t address, int sda, int scl, OLEDDISPLAY_GEOMETRY geometry, HW_I2C i2cBus)
|
||||
{
|
||||
LOG_DEBUG("TFTDisplay!\n");
|
||||
|
||||
#ifdef TFT_BL
|
||||
GpioPin *p = new GpioHwPin(TFT_BL);
|
||||
|
||||
if (!TFT_BACKLIGHT_ON) { // Need to invert the pin before hardware
|
||||
auto virtPin = new GpioVirtPin();
|
||||
new GpioNotTransformer(
|
||||
virtPin, p); // We just leave this created object on the heap so it can stay watching virtPin and driving en_gpio
|
||||
p = virtPin;
|
||||
}
|
||||
#else
|
||||
GpioPin *p = new GpioVirtPin(); // Just simulate a pin
|
||||
#endif
|
||||
backlightEnable = p;
|
||||
|
||||
#if ARCH_PORTDUINO
|
||||
if (settingsMap[displayRotate]) {
|
||||
setGeometry(GEOMETRY_RAWMODE, settingsMap[configNames::displayHeight], settingsMap[configNames::displayWidth]);
|
||||
@ -588,24 +597,15 @@ void TFTDisplay::sendCommand(uint8_t com)
|
||||
// handle display on/off directly
|
||||
switch (com) {
|
||||
case DISPLAYON: {
|
||||
// LOG_DEBUG("Display on\n");
|
||||
backlightEnable->set(true);
|
||||
#if ARCH_PORTDUINO
|
||||
display(true);
|
||||
if (settingsMap[displayBacklight] > 0)
|
||||
digitalWrite(settingsMap[displayBacklight], TFT_BACKLIGHT_ON);
|
||||
#elif defined(ST7735_BL_V03)
|
||||
digitalWrite(ST7735_BL_V03, TFT_BACKLIGHT_ON);
|
||||
#elif defined(ST7735_BL_V05)
|
||||
pinMode(ST7735_BL_V05, OUTPUT);
|
||||
digitalWrite(ST7735_BL_V05, TFT_BACKLIGHT_ON);
|
||||
#elif !defined(RAK14014) && !defined(M5STACK) && !defined(UNPHONE)
|
||||
tft->wakeup();
|
||||
tft->powerSaveOff();
|
||||
#elif defined(TFT_BL) && defined(TFT_BACKLIGHT_ON)
|
||||
digitalWrite(TFT_BL, TFT_BACKLIGHT_ON);
|
||||
#endif
|
||||
|
||||
#ifdef VTFT_CTRL_V03
|
||||
digitalWrite(VTFT_CTRL_V03, LOW);
|
||||
#endif
|
||||
|
||||
#ifdef VTFT_CTRL
|
||||
@ -621,25 +621,17 @@ void TFTDisplay::sendCommand(uint8_t com)
|
||||
break;
|
||||
}
|
||||
case DISPLAYOFF: {
|
||||
// LOG_DEBUG("Display off\n");
|
||||
backlightEnable->set(false);
|
||||
#if ARCH_PORTDUINO
|
||||
tft->clear();
|
||||
if (settingsMap[displayBacklight] > 0)
|
||||
digitalWrite(settingsMap[displayBacklight], !TFT_BACKLIGHT_ON);
|
||||
#elif defined(ST7735_BL_V03)
|
||||
digitalWrite(ST7735_BL_V03, !TFT_BACKLIGHT_ON);
|
||||
#elif defined(ST7735_BL_V05)
|
||||
pinMode(ST7735_BL_V05, OUTPUT);
|
||||
digitalWrite(ST7735_BL_V05, !TFT_BACKLIGHT_ON);
|
||||
#elif !defined(RAK14014) && !defined(M5STACK) && !defined(UNPHONE)
|
||||
tft->sleep();
|
||||
tft->powerSaveOn();
|
||||
#elif defined(TFT_BL) && defined(TFT_BACKLIGHT_ON)
|
||||
digitalWrite(TFT_BL, !TFT_BACKLIGHT_ON);
|
||||
#endif
|
||||
|
||||
#ifdef VTFT_CTRL_V03
|
||||
digitalWrite(VTFT_CTRL_V03, HIGH);
|
||||
#endif
|
||||
#ifdef VTFT_CTRL
|
||||
digitalWrite(VTFT_CTRL, HIGH);
|
||||
#endif
|
||||
@ -723,20 +715,9 @@ bool TFTDisplay::connect()
|
||||
tft = new LGFX;
|
||||
#endif
|
||||
|
||||
#ifdef TFT_BL
|
||||
pinMode(TFT_BL, OUTPUT);
|
||||
digitalWrite(TFT_BL, TFT_BACKLIGHT_ON);
|
||||
// pinMode(PIN_3V3_EN, OUTPUT);
|
||||
// digitalWrite(PIN_3V3_EN, HIGH);
|
||||
backlightEnable->set(true);
|
||||
LOG_INFO("Power to TFT Backlight\n");
|
||||
#endif
|
||||
|
||||
#ifdef ST7735_BL_V03
|
||||
digitalWrite(ST7735_BL_V03, TFT_BACKLIGHT_ON);
|
||||
#elif defined(ST7735_BL_V05)
|
||||
pinMode(ST7735_BL_V05, OUTPUT);
|
||||
digitalWrite(ST7735_BL_V05, TFT_BACKLIGHT_ON);
|
||||
#endif
|
||||
#ifdef UNPHONE
|
||||
unphone.backlight(true); // using unPhone library
|
||||
LOG_INFO("Power to TFT Backlight\n");
|
||||
|
@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <GpioLogic.h>
|
||||
#include <OLEDDisplay.h>
|
||||
|
||||
/**
|
||||
@ -39,6 +40,14 @@ class TFTDisplay : public OLEDDisplay
|
||||
*/
|
||||
void setDetected(uint8_t detected);
|
||||
|
||||
/**
|
||||
* This is normally managed entirely by TFTDisplay, but some rare applications (heltec tracker) might need to replace the
|
||||
* default GPIO behavior with something a bit more complex.
|
||||
*
|
||||
* We (cruftily) make it static so that variant.cpp can access it without needing a ptr to the TFTDisplay instance.
|
||||
*/
|
||||
static GpioPin *backlightEnable;
|
||||
|
||||
protected:
|
||||
// the header size of the buffer used, e.g. for the SPI command header
|
||||
virtual int getBufferOffset(void) override { return 0; }
|
||||
|
30
src/main.cpp
30
src/main.cpp
@ -239,6 +239,11 @@ __attribute__((weak, noinline)) bool loopCanSleep()
|
||||
return true;
|
||||
}
|
||||
|
||||
// Weak empty variant initialization function.
|
||||
// May be redefined by variant files.
|
||||
void lateInitVariant() __attribute__((weak));
|
||||
void lateInitVariant() {}
|
||||
|
||||
/**
|
||||
* Print info as a structured log message (for automated log processing)
|
||||
*/
|
||||
@ -305,29 +310,9 @@ void setup()
|
||||
digitalWrite(LORA_TCXO_GPIO, HIGH);
|
||||
#endif
|
||||
|
||||
#if defined(VEXT_ENABLE_V03)
|
||||
pinMode(VEXT_ENABLE_V03, OUTPUT);
|
||||
pinMode(ST7735_BL_V03, OUTPUT);
|
||||
digitalWrite(VEXT_ENABLE_V03, 0); // turn on the display power and antenna boost
|
||||
digitalWrite(ST7735_BL_V03, 1); // display backligth on
|
||||
LOG_DEBUG("HELTEC Detect Tracker V1.0\n");
|
||||
#elif defined(VEXT_ENABLE_V05)
|
||||
pinMode(VEXT_ENABLE_V05, OUTPUT);
|
||||
pinMode(ST7735_BL_V05, OUTPUT);
|
||||
digitalWrite(VEXT_ENABLE_V05, 1); // turn on the lora antenna boost
|
||||
digitalWrite(ST7735_BL_V05, 1); // turn on display backligth
|
||||
LOG_DEBUG("HELTEC Detect Tracker V1.1\n");
|
||||
#elif defined(VEXT_ENABLE) && defined(VEXT_ON_VALUE)
|
||||
#if defined(VEXT_ENABLE)
|
||||
pinMode(VEXT_ENABLE, OUTPUT);
|
||||
digitalWrite(VEXT_ENABLE, VEXT_ON_VALUE); // turn on the display power
|
||||
#elif defined(VEXT_ENABLE)
|
||||
pinMode(VEXT_ENABLE, OUTPUT);
|
||||
digitalWrite(VEXT_ENABLE, 0); // turn on the display power
|
||||
#endif
|
||||
|
||||
#if defined(VTFT_CTRL_V03)
|
||||
pinMode(VTFT_CTRL_V03, OUTPUT);
|
||||
digitalWrite(VTFT_CTRL_V03, LOW);
|
||||
#endif
|
||||
|
||||
#if defined(VTFT_CTRL)
|
||||
@ -583,6 +568,7 @@ void setup()
|
||||
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::BME_680, meshtastic_TelemetrySensorType_BME680)
|
||||
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::BME_280, meshtastic_TelemetrySensorType_BME280)
|
||||
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::BMP_280, meshtastic_TelemetrySensorType_BMP280)
|
||||
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::BMP_3XX, meshtastic_TelemetrySensorType_BMP3XX)
|
||||
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::BMP_085, meshtastic_TelemetrySensorType_BMP085)
|
||||
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::INA260, meshtastic_TelemetrySensorType_INA260)
|
||||
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::INA219, meshtastic_TelemetrySensorType_INA219)
|
||||
@ -1131,6 +1117,8 @@ void setup()
|
||||
}
|
||||
}
|
||||
|
||||
lateInitVariant(); // Do board specific init (see extra_variants/README.md for documentation)
|
||||
|
||||
#if !MESHTASTIC_EXCLUDE_MQTT
|
||||
mqttInit();
|
||||
#endif
|
||||
|
@ -44,11 +44,19 @@ void fixPriority(meshtastic_MeshPacket *p)
|
||||
p->priority = (p->want_ack ? meshtastic_MeshPacket_Priority_RELIABLE : meshtastic_MeshPacket_Priority_DEFAULT);
|
||||
if (p->which_payload_variant == meshtastic_MeshPacket_decoded_tag) {
|
||||
// if acks/naks give very high priority
|
||||
if (p->decoded.portnum == meshtastic_PortNum_ROUTING_APP)
|
||||
if (p->decoded.portnum == meshtastic_PortNum_ROUTING_APP) {
|
||||
p->priority = meshtastic_MeshPacket_Priority_ACK;
|
||||
// if text give high priority
|
||||
else if (p->decoded.portnum == meshtastic_PortNum_TEXT_MESSAGE_APP)
|
||||
// if text or admin, give high priority
|
||||
} else if (p->decoded.portnum == meshtastic_PortNum_TEXT_MESSAGE_APP ||
|
||||
p->decoded.portnum == meshtastic_PortNum_ADMIN_APP) {
|
||||
p->priority = meshtastic_MeshPacket_Priority_HIGH;
|
||||
// if it is a response, give higher priority to let it arrive early and stop the request being relayed
|
||||
} else if (p->decoded.request_id != 0) {
|
||||
p->priority = meshtastic_MeshPacket_Priority_RESPONSE;
|
||||
// Also if we want a response, give a bit higher priority
|
||||
} else if (p->decoded.want_response) {
|
||||
p->priority = meshtastic_MeshPacket_Priority_RELIABLE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -350,6 +350,9 @@ typedef enum _meshtastic_MeshPacket_Priority {
|
||||
/* If priority is unset but the message is marked as want_ack,
|
||||
assume it is important and use a slightly higher priority */
|
||||
meshtastic_MeshPacket_Priority_RELIABLE = 70,
|
||||
/* If priority is unset but the packet is a response to a request, we want it to get there relatively quickly.
|
||||
Furthermore, responses stop relaying packets directed to a node early. */
|
||||
meshtastic_MeshPacket_Priority_RESPONSE = 80,
|
||||
/* Higher priority for specific message types (portnums) to distinguish between other reliable packets. */
|
||||
meshtastic_MeshPacket_Priority_HIGH = 100,
|
||||
/* Ack/naks are sent with very high priority to ensure that retransmission
|
||||
|
@ -107,6 +107,7 @@ void NeighborInfoModule::sendNeighborInfo(NodeNum dest, bool wantReplies)
|
||||
// because we want to get neighbors for the next cycle
|
||||
p->to = dest;
|
||||
p->decoded.want_response = wantReplies;
|
||||
p->priority = meshtastic_MeshPacket_Priority_BACKGROUND;
|
||||
printNeighborInfo("SENDING", &neighborInfo);
|
||||
service->sendToMesh(p, RX_SRC_LOCAL, true);
|
||||
}
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "Sensor/BME680Sensor.h"
|
||||
#include "Sensor/BMP085Sensor.h"
|
||||
#include "Sensor/BMP280Sensor.h"
|
||||
#include "Sensor/BMP3XXSensor.h"
|
||||
#include "Sensor/DFRobotLarkSensor.h"
|
||||
#include "Sensor/LPS22HBSensor.h"
|
||||
#include "Sensor/MCP9808Sensor.h"
|
||||
@ -54,6 +55,7 @@ AHT10Sensor aht10Sensor;
|
||||
MLX90632Sensor mlx90632Sensor;
|
||||
DFRobotLarkSensor dfRobotLarkSensor;
|
||||
NAU7802Sensor nau7802Sensor;
|
||||
BMP3XXSensor bmp3xxSensor;
|
||||
#ifdef T1000X_SENSOR_EN
|
||||
T1000xSensor t1000xSensor;
|
||||
#endif
|
||||
@ -107,6 +109,8 @@ int32_t EnvironmentTelemetryModule::runOnce()
|
||||
result = bmp280Sensor.runOnce();
|
||||
if (bme280Sensor.hasSensor())
|
||||
result = bme280Sensor.runOnce();
|
||||
if (bmp3xxSensor.hasSensor())
|
||||
result = bmp3xxSensor.runOnce();
|
||||
if (bme680Sensor.hasSensor())
|
||||
result = bme680Sensor.runOnce();
|
||||
if (mcp9808Sensor.hasSensor())
|
||||
@ -327,6 +331,10 @@ bool EnvironmentTelemetryModule::getEnvironmentTelemetry(meshtastic_Telemetry *m
|
||||
valid = valid && bme280Sensor.getMetrics(m);
|
||||
hasSensor = true;
|
||||
}
|
||||
if (bmp3xxSensor.hasSensor()) {
|
||||
valid = valid && bmp3xxSensor.getMetrics(m);
|
||||
hasSensor = true;
|
||||
}
|
||||
if (bme680Sensor.hasSensor()) {
|
||||
valid = valid && bme680Sensor.getMetrics(m);
|
||||
hasSensor = true;
|
||||
@ -372,15 +380,21 @@ bool EnvironmentTelemetryModule::getEnvironmentTelemetry(meshtastic_Telemetry *m
|
||||
hasSensor = true;
|
||||
}
|
||||
if (aht10Sensor.hasSensor()) {
|
||||
if (!bmp280Sensor.hasSensor()) {
|
||||
if (!bmp280Sensor.hasSensor() && !bmp3xxSensor.hasSensor()) {
|
||||
valid = valid && aht10Sensor.getMetrics(m);
|
||||
hasSensor = true;
|
||||
} else {
|
||||
} else if (bmp280Sensor.hasSensor()) {
|
||||
// prefer bmp280 temp if both sensors are present, fetch only humidity
|
||||
meshtastic_Telemetry m_ahtx = meshtastic_Telemetry_init_zero;
|
||||
LOG_INFO("AHTX0+BMP280 module detected: using temp from BMP280 and humy from AHTX0\n");
|
||||
aht10Sensor.getMetrics(&m_ahtx);
|
||||
m->variant.environment_metrics.relative_humidity = m_ahtx.variant.environment_metrics.relative_humidity;
|
||||
} else {
|
||||
// prefer bmp3xx temp if both sensors are present, fetch only humidity
|
||||
meshtastic_Telemetry m_ahtx = meshtastic_Telemetry_init_zero;
|
||||
LOG_INFO("AHTX0+BMP3XX module detected: using temp from BMP3XX and humy from AHTX0\n");
|
||||
aht10Sensor.getMetrics(&m_ahtx);
|
||||
m->variant.environment_metrics.relative_humidity = m_ahtx.variant.environment_metrics.relative_humidity;
|
||||
}
|
||||
}
|
||||
|
||||
@ -508,6 +522,11 @@ AdminMessageHandleResult EnvironmentTelemetryModule::handleAdminMessageForModule
|
||||
if (result != AdminMessageHandleResult::NOT_HANDLED)
|
||||
return result;
|
||||
}
|
||||
if (bmp3xxSensor.hasSensor()) {
|
||||
result = bmp3xxSensor.handleAdminMessage(mp, request, response);
|
||||
if (result != AdminMessageHandleResult::NOT_HANDLED)
|
||||
return result;
|
||||
}
|
||||
if (bme680Sensor.hasSensor()) {
|
||||
result = bme680Sensor.handleAdminMessage(mp, request, response);
|
||||
if (result != AdminMessageHandleResult::NOT_HANDLED)
|
||||
|
89
src/modules/Telemetry/Sensor/BMP3XXSensor.cpp
Normal file
89
src/modules/Telemetry/Sensor/BMP3XXSensor.cpp
Normal file
@ -0,0 +1,89 @@
|
||||
#include "configuration.h"
|
||||
|
||||
#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR
|
||||
|
||||
#include "BMP3XXSensor.h"
|
||||
|
||||
BMP3XXSensor::BMP3XXSensor() : TelemetrySensor(meshtastic_TelemetrySensorType_BMP3XX, "BMP3XX") {}
|
||||
|
||||
void BMP3XXSensor::setup() {}
|
||||
|
||||
int32_t BMP3XXSensor::runOnce()
|
||||
{
|
||||
LOG_INFO("Init sensor: %s\n", sensorName);
|
||||
if (!hasSensor()) {
|
||||
return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
|
||||
}
|
||||
|
||||
// Get a singleton instance and initialise the bmp3xx
|
||||
if (bmp3xx == nullptr) {
|
||||
bmp3xx = BMP3XXSingleton::GetInstance();
|
||||
}
|
||||
status = bmp3xx->begin_I2C(nodeTelemetrySensorsMap[sensorType].first, nodeTelemetrySensorsMap[sensorType].second);
|
||||
|
||||
// set up oversampling and filter initialization
|
||||
bmp3xx->setTemperatureOversampling(BMP3_OVERSAMPLING_4X);
|
||||
bmp3xx->setPressureOversampling(BMP3_OVERSAMPLING_8X);
|
||||
bmp3xx->setIIRFilterCoeff(BMP3_IIR_FILTER_COEFF_3);
|
||||
bmp3xx->setOutputDataRate(BMP3_ODR_25_HZ);
|
||||
|
||||
// take a couple of initial readings to settle the sensor filters
|
||||
for (int i = 0; i < 3; i++) {
|
||||
bmp3xx->performReading();
|
||||
}
|
||||
return initI2CSensor();
|
||||
}
|
||||
|
||||
bool BMP3XXSensor::getMetrics(meshtastic_Telemetry *measurement)
|
||||
{
|
||||
if (bmp3xx == nullptr) {
|
||||
bmp3xx = BMP3XXSingleton::GetInstance();
|
||||
}
|
||||
if ((int)measurement->which_variant == meshtastic_Telemetry_environment_metrics_tag) {
|
||||
bmp3xx->performReading();
|
||||
|
||||
measurement->variant.environment_metrics.has_temperature = true;
|
||||
measurement->variant.environment_metrics.has_barometric_pressure = true;
|
||||
measurement->variant.environment_metrics.has_relative_humidity = false;
|
||||
|
||||
measurement->variant.environment_metrics.temperature = static_cast<float>(bmp3xx->temperature);
|
||||
measurement->variant.environment_metrics.barometric_pressure = static_cast<float>(bmp3xx->pressure) / 100.0F;
|
||||
measurement->variant.environment_metrics.relative_humidity = 0.0f;
|
||||
|
||||
LOG_DEBUG("BMP3XXSensor::getMetrics id: %i temp: %.1f press %.1f\n", measurement->which_variant,
|
||||
measurement->variant.environment_metrics.temperature,
|
||||
measurement->variant.environment_metrics.barometric_pressure);
|
||||
} else {
|
||||
LOG_DEBUG("BMP3XXSensor::getMetrics id: %i\n", measurement->which_variant);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Get a singleton wrapper for an Adafruit_bmp3xx
|
||||
BMP3XXSingleton *BMP3XXSingleton::GetInstance()
|
||||
{
|
||||
if (pinstance == nullptr) {
|
||||
pinstance = new BMP3XXSingleton();
|
||||
}
|
||||
return pinstance;
|
||||
}
|
||||
|
||||
BMP3XXSingleton::BMP3XXSingleton() {}
|
||||
|
||||
BMP3XXSingleton::~BMP3XXSingleton() {}
|
||||
|
||||
BMP3XXSingleton *BMP3XXSingleton::pinstance{nullptr};
|
||||
|
||||
bool BMP3XXSingleton::performReading()
|
||||
{
|
||||
bool result = Adafruit_BMP3XX::performReading();
|
||||
if (result) {
|
||||
double atmospheric = this->pressure / 100.0;
|
||||
altitudeAmslMetres = 44330.0 * (1.0 - pow(atmospheric / SEAL_LEVEL_HPA, 0.1903));
|
||||
} else {
|
||||
altitudeAmslMetres = 0.0;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif
|
56
src/modules/Telemetry/Sensor/BMP3XXSensor.h
Normal file
56
src/modules/Telemetry/Sensor/BMP3XXSensor.h
Normal file
@ -0,0 +1,56 @@
|
||||
#include "configuration.h"
|
||||
|
||||
#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR
|
||||
|
||||
#ifndef _BMP3XX_SENSOR_H
|
||||
#define _BMP3XX_SENSOR_H
|
||||
|
||||
#define SEAL_LEVEL_HPA 1013.2f
|
||||
|
||||
#include "TelemetrySensor.h"
|
||||
#include <Adafruit_BMP3XX.h>
|
||||
#include <typeinfo>
|
||||
|
||||
// Singleton wrapper for the Adafruit_BMP3XX class
|
||||
class BMP3XXSingleton : public Adafruit_BMP3XX
|
||||
{
|
||||
private:
|
||||
static BMP3XXSingleton *pinstance;
|
||||
|
||||
protected:
|
||||
BMP3XXSingleton();
|
||||
~BMP3XXSingleton();
|
||||
|
||||
public:
|
||||
// Create a singleton instance (not thread safe)
|
||||
static BMP3XXSingleton *GetInstance();
|
||||
|
||||
// Singletons should not be cloneable.
|
||||
BMP3XXSingleton(BMP3XXSingleton &other) = delete;
|
||||
|
||||
// Singletons should not be assignable.
|
||||
void operator=(const BMP3XXSingleton &) = delete;
|
||||
|
||||
// Performs a full reading of all sensors in the BMP3XX. Assigns
|
||||
// the internal temperature, pressure and altitudeAmsl variables
|
||||
bool performReading();
|
||||
|
||||
// Altitude in metres above mean sea level, assigned after calling performReading()
|
||||
double altitudeAmslMetres = 0.0f;
|
||||
};
|
||||
|
||||
class BMP3XXSensor : public TelemetrySensor
|
||||
{
|
||||
protected:
|
||||
BMP3XXSingleton *bmp3xx = nullptr;
|
||||
virtual void setup() override;
|
||||
|
||||
public:
|
||||
BMP3XXSensor();
|
||||
virtual int32_t runOnce() override;
|
||||
virtual bool getMetrics(meshtastic_Telemetry *measurement) override;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
15
src/platform/extra_variants/README.md
Normal file
15
src/platform/extra_variants/README.md
Normal file
@ -0,0 +1,15 @@
|
||||
# About extra_variants
|
||||
|
||||
This directory tree is designed to solve two problems.
|
||||
|
||||
- The ESP32 arduino/platformio project doesn't support the nice "if initVariant() is found, call that after init" behavior of the nrf52 builds (they use initVariant() internally).
|
||||
- Over the years a lot of 'board specific' init code has been added to init() in main.cpp. It would be great to have a general/clean mechanism to allow developers to specify board specific/unique code in a clean fashion without mucking in main.
|
||||
|
||||
So we are borrowing the initVariant() ideas here (by using weak gcc references). You can now define lateInitVariant() if your board needs it.
|
||||
|
||||
If you'd like a board specific variant to be run, add the variant.cpp file to an appropriately named
|
||||
subdirectory and check for \_VARIANT_boardname in the cpp file (so that your code is only built for your board).
|
||||
You'll need to define \_VARIANT_boardname in your corresponding variant.h file.
|
||||
See existing boards for examples.
|
||||
|
||||
This approach has no added runtime cost.
|
@ -0,0 +1,34 @@
|
||||
#include "configuration.h"
|
||||
|
||||
#ifdef _VARIANT_HELTEC_WIRELESS_TRACKER
|
||||
|
||||
#include "GPS.h"
|
||||
#include "GpioLogic.h"
|
||||
#include "graphics/TFTDisplay.h"
|
||||
|
||||
// Heltec tracker specific init
|
||||
void lateInitVariant()
|
||||
{
|
||||
// LOG_DEBUG("Heltec tracker initVariant\n");
|
||||
#ifdef VEXT_ENABLE
|
||||
GpioPin *hwEnable = new GpioHwPin(VEXT_ENABLE);
|
||||
GpioVirtPin *virtGpsEnable = gps ? gps->enablePin : new GpioVirtPin();
|
||||
|
||||
// On this board we are actually using the backlightEnable signal to already be controlling a physical enable to the
|
||||
// display controller. But we'd _ALSO_ like to have that signal drive a virtual GPIO. So nest it as needed.
|
||||
GpioVirtPin *virtScreenEnable = new GpioVirtPin();
|
||||
if (TFTDisplay::backlightEnable) {
|
||||
GpioPin *physScreenEnable = TFTDisplay::backlightEnable;
|
||||
GpioPin *splitter = new GpioSplitter(virtScreenEnable, physScreenEnable);
|
||||
TFTDisplay::backlightEnable = splitter;
|
||||
|
||||
// Assume screen is initially powered
|
||||
splitter->set(true);
|
||||
}
|
||||
|
||||
// If either the GPS or the screen is on, turn on the external power regulator
|
||||
new GpioBinaryTransformer(virtGpsEnable, virtScreenEnable, hwEnable, GpioBinaryTransformer::Or);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
@ -246,15 +246,8 @@ void doDeepSleep(uint32_t msecToWake, bool skipPreflight = false)
|
||||
digitalWrite(RESET_OLED, 1); // put the display in reset before killing its power
|
||||
#endif
|
||||
|
||||
#if defined(VEXT_ENABLE_V03)
|
||||
digitalWrite(VEXT_ENABLE_V03, 1); // turn off the display power
|
||||
#elif defined(VEXT_ENABLE_V05)
|
||||
digitalWrite(VEXT_ENABLE_V05, 0); // turn off the lora amplifier power
|
||||
digitalWrite(ST7735_BL_V05, 0); // turn off the display power
|
||||
#elif defined(VEXT_ENABLE) && defined(VEXT_ON_VALUE)
|
||||
#if defined(VEXT_ENABLE)
|
||||
digitalWrite(VEXT_ENABLE, !VEXT_ON_VALUE); // turn on the display power
|
||||
#elif defined(VEXT_ENABLE)
|
||||
digitalWrite(VEXT_ENABLE, 1); // turn off the display power
|
||||
#endif
|
||||
|
||||
#ifdef ARCH_ESP32
|
||||
|
@ -54,7 +54,7 @@
|
||||
#define ST7735_RESET 15
|
||||
#define ST7735_MISO -1
|
||||
#define ST7735_BUSY -1
|
||||
#define ST7735_BL 32
|
||||
#define TFT_BL 32
|
||||
#define ST7735_SPI_HOST HSPI_HOST // SPI2_HOST for S3, auto may work too
|
||||
#define SPI_FREQUENCY 40000000
|
||||
#define SPI_READ_FREQUENCY 16000000
|
||||
|
@ -49,7 +49,7 @@ extern "C" {
|
||||
// #define ST7789_BL (32+6)
|
||||
#define TFT_BACKLIGHT_ON LOW
|
||||
#define ST7789_SPI_HOST SPI1_HOST
|
||||
// #define ST7789_BACKLIGHT_EN (32+6)
|
||||
// #define TFT_BL (32+6)
|
||||
#define SPI_FREQUENCY 40000000
|
||||
#define SPI_READ_FREQUENCY 16000000
|
||||
#define TFT_HEIGHT 135
|
||||
|
@ -22,6 +22,7 @@
|
||||
|
||||
// Power
|
||||
#define VEXT_ENABLE 45 // Active low, powers the E-Ink display
|
||||
#define VEXT_ON_VALUE LOW
|
||||
#define ADC_CTRL 19
|
||||
#define BATTERY_PIN 20
|
||||
#define ADC_CHANNEL ADC2_GPIO20_CHANNEL
|
||||
@ -29,6 +30,7 @@
|
||||
#define BAT_MEASURE_ADC_UNIT 2 // Use ADC2
|
||||
#define ADC_ATTENUATION ADC_ATTEN_DB_12 // Voltage divider output is quite high
|
||||
#define HAS_32768HZ
|
||||
#define ADC_CTRL_ENABLED LOW
|
||||
|
||||
// LoRa
|
||||
#define USE_SX1262
|
||||
@ -49,4 +51,4 @@
|
||||
#define SX126X_RESET LORA_RESET
|
||||
|
||||
#define SX126X_DIO2_AS_RF_SWITCH
|
||||
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
|
||||
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
|
@ -22,6 +22,7 @@
|
||||
|
||||
// Power
|
||||
#define VEXT_ENABLE 45 // Active low, powers the E-Ink display
|
||||
#define VEXT_ON_VALUE LOW
|
||||
#define ADC_CTRL 19
|
||||
#define BATTERY_PIN 20
|
||||
#define ADC_CHANNEL ADC2_GPIO20_CHANNEL
|
||||
@ -29,6 +30,7 @@
|
||||
#define BAT_MEASURE_ADC_UNIT 2 // Use ADC2
|
||||
#define ADC_ATTENUATION ADC_ATTEN_DB_12 // Voltage divider output is quite high
|
||||
#define HAS_32768HZ
|
||||
#define ADC_CTRL_ENABLED LOW
|
||||
|
||||
// LoRa
|
||||
#define USE_SX1262
|
||||
@ -49,4 +51,4 @@
|
||||
#define SX126X_RESET LORA_RESET
|
||||
|
||||
#define SX126X_DIO2_AS_RF_SWITCH
|
||||
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
|
||||
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
|
@ -1,5 +1,6 @@
|
||||
#define LED_PIN 18
|
||||
|
||||
#define _VARIANT_HELTEC_WIRELESS_TRACKER
|
||||
#define HELTEC_TRACKER_V1_X
|
||||
|
||||
// I2C
|
||||
@ -15,7 +16,7 @@
|
||||
#define ST7735_RESET 39
|
||||
#define ST7735_MISO -1
|
||||
#define ST7735_BUSY -1
|
||||
#define ST7735_BL_V05 21 /* V1.1 PCB marking */
|
||||
#define TFT_BL 21 /* V1.1 PCB marking */
|
||||
#define ST7735_SPI_HOST SPI3_HOST
|
||||
#define SPI_FREQUENCY 40000000
|
||||
#define SPI_READ_FREQUENCY 16000000
|
||||
@ -31,15 +32,17 @@
|
||||
// GPS UC6580: GPS V_DET(8), VDD_IO(7), DCDC_IN(21), pulls up RESETN(17), D_SEL(33) and BOOT_MODE(34) through 10kR
|
||||
// GPS LNA SW7125DE: VCC(4), pulls up SHDN(5) through 10kR
|
||||
// LED: VDD, LEDA (through diode)
|
||||
#define VEXT_ENABLE_V05 3 // active HIGH - powers the GPS, GPS LNA and OLED VDD/anode
|
||||
|
||||
#define VEXT_ENABLE 3 // active HIGH - powers the GPS, GPS LNA and OLED
|
||||
#define VEXT_ON_VALUE HIGH
|
||||
#define BUTTON_PIN 0
|
||||
|
||||
#define BATTERY_PIN 1 // A battery voltage measurement pin, voltage divider connected here to measure battery voltage
|
||||
#define ADC_CHANNEL ADC1_GPIO1_CHANNEL
|
||||
#define ADC_ATTENUATION ADC_ATTEN_DB_2_5 // lower dB for high resistance voltage divider
|
||||
#define ADC_MULTIPLIER 4.9 * 1.045
|
||||
#define ADC_CTRL 2 // active HIGH, powers the voltage divider. Only on 1.1
|
||||
#define ADC_CTRL_ENABLED HIGH
|
||||
#define ADC_CTRL 2 // active HIGH, powers the voltage divider. Only on 1.1
|
||||
#define ADC_USE_PULLUP // Use internal pullup/pulldown instead of actively driving the output
|
||||
|
||||
#undef GPS_RX_PIN
|
||||
#undef GPS_TX_PIN
|
||||
@ -72,4 +75,4 @@
|
||||
#define SX126X_RESET LORA_RESET
|
||||
|
||||
#define SX126X_DIO2_AS_RF_SWITCH
|
||||
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
|
||||
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
|
@ -15,7 +15,7 @@
|
||||
#define ST7735_RESET 39
|
||||
#define ST7735_MISO -1
|
||||
#define ST7735_BUSY -1
|
||||
#define ST7735_BL_V03 45
|
||||
#define TFT_BL 45
|
||||
#define ST7735_SPI_HOST SPI3_HOST
|
||||
#define SPI_FREQUENCY 40000000
|
||||
#define SPI_READ_FREQUENCY 16000000
|
||||
@ -24,11 +24,12 @@
|
||||
#define TFT_WIDTH DISPLAY_HEIGHT
|
||||
#define TFT_OFFSET_X 26
|
||||
#define TFT_OFFSET_Y -1
|
||||
#define VTFT_CTRL_V03 46 // Heltec Tracker needs this pulled low for TFT
|
||||
#define VTFT_CTRL 46 // Heltec Tracker needs this pulled low for TFT
|
||||
#define SCREEN_TRANSITION_FRAMERATE 3 // fps
|
||||
#define DISPLAY_FORCE_SMALL_FONTS
|
||||
|
||||
#define VEXT_ENABLE_V03 Vext // active low, powers the oled display and the lora antenna boost
|
||||
#define VEXT_ENABLE Vext // active low, powers the oled display and the lora antenna boost
|
||||
#define VEXT_ON_VALUE LOW
|
||||
#define BUTTON_PIN 0
|
||||
|
||||
#define BATTERY_PIN 1 // A battery voltage measurement pin, voltage divider connected here to measure battery voltage
|
||||
@ -43,8 +44,7 @@
|
||||
#define PIN_GPS_RESET 35
|
||||
#define PIN_GPS_PPS 36
|
||||
|
||||
#define VGNSS_CTRL_V03 37 // Heltec Tracker needs this pulled low for GPS
|
||||
#define PIN_GPS_EN VGNSS_CTRL_V03
|
||||
#define PIN_GPS_EN 37 // Heltec Tracker needs this pulled low for GPS
|
||||
#define GPS_EN_ACTIVE LOW
|
||||
|
||||
#define GPS_RESET_MODE LOW
|
||||
@ -69,4 +69,4 @@
|
||||
#define SX126X_RESET LORA_RESET
|
||||
|
||||
#define SX126X_DIO2_AS_RF_SWITCH
|
||||
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
|
||||
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
|
@ -4,6 +4,7 @@
|
||||
#define LED_PIN LED
|
||||
|
||||
#define VEXT_ENABLE Vext // active low, powers the oled display and the lora antenna boost
|
||||
#define VEXT_ON_VALUE LOW
|
||||
#define BUTTON_PIN 0
|
||||
|
||||
#define ADC_CTRL 37
|
||||
@ -32,4 +33,4 @@
|
||||
#define SX126X_RESET LORA_RESET
|
||||
|
||||
#define SX126X_DIO2_AS_RF_SWITCH
|
||||
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
|
||||
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
|
@ -144,7 +144,7 @@ static const uint8_t SCK = PIN_SPI_SCK;
|
||||
|
||||
#define ST7735_RESET (11) // Output
|
||||
#define ST7735_CS (12)
|
||||
#define ST7735_BACKLIGHT_EN (13)
|
||||
#define TFT_BL (13)
|
||||
#define ST7735_RS (9)
|
||||
|
||||
// #define LORA_DISABLE_SENDING // The board can brownout during lora TX if you don't have a battery connected. Disable sending
|
||||
@ -158,4 +158,4 @@ static const uint8_t SCK = PIN_SPI_SCK;
|
||||
* Arduino objects - C++ only
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#endif
|
||||
#endif
|
@ -166,7 +166,7 @@ static const uint8_t SCK = PIN_SPI_SCK;
|
||||
// ST7565 SPI
|
||||
#define ST7735_RESET (11) // Output
|
||||
#define ST7735_CS (12)
|
||||
#define ST7735_BACKLIGHT_EN (13)
|
||||
#define TFT_BL (13)
|
||||
#define ST7735_RS (9)
|
||||
#define ST7735_SDA (39) // actually spi MOSI
|
||||
#define ST7735_SCK (37) // actually spi clk
|
||||
@ -185,4 +185,4 @@ static const uint8_t SCK = PIN_SPI_SCK;
|
||||
* Arduino objects - C++ only
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#endif
|
||||
#endif
|
@ -37,7 +37,7 @@
|
||||
#define ST7789_MISO -1
|
||||
#define ST7789_BUSY -1
|
||||
#define ST7789_SPI_HOST SPI3_HOST
|
||||
#define ST7789_BACKLIGHT_EN 5
|
||||
#define TFT_BL 5
|
||||
#define SPI_FREQUENCY 40000000
|
||||
#define SPI_READ_FREQUENCY 16000000
|
||||
#define TFT_HEIGHT 320
|
||||
|
@ -8,7 +8,7 @@
|
||||
#define ST7789_BUSY -1
|
||||
#define ST7789_BL 42
|
||||
#define ST7789_SPI_HOST SPI2_HOST
|
||||
#define ST7789_BACKLIGHT_EN 42
|
||||
#define TFT_BL 42
|
||||
#define SPI_FREQUENCY 40000000
|
||||
#define SPI_READ_FREQUENCY 16000000
|
||||
#define TFT_HEIGHT 320
|
||||
|
@ -8,7 +8,7 @@
|
||||
#define ST7789_BUSY -1
|
||||
#define ST7789_BL 45
|
||||
#define ST7789_SPI_HOST SPI3_HOST
|
||||
#define ST7789_BACKLIGHT_EN 45
|
||||
#define TFT_BL 45
|
||||
#define SPI_FREQUENCY 40000000
|
||||
#define SPI_READ_FREQUENCY 16000000
|
||||
#define TFT_HEIGHT 240
|
||||
@ -30,8 +30,6 @@
|
||||
#define I2C_SDA1 39 // Used for capacitive touch
|
||||
#define I2C_SCL1 40 // Used for capacitive touch
|
||||
|
||||
#define TFT_BL ST7789_BACKLIGHT_EN
|
||||
|
||||
#define HAS_I2S
|
||||
#define DAC_I2S_BCK 48
|
||||
#define DAC_I2S_WS 15
|
||||
|
@ -4,8 +4,9 @@
|
||||
#define RESET_OLED 16 // If defined, this pin will be used to reset the display controller
|
||||
|
||||
#define VEXT_ENABLE 21 // active low, powers the oled display and the lora antenna boost
|
||||
#define LED_PIN 2 // If defined we will blink this LED
|
||||
#define BUTTON_PIN 0 // If defined, this will be used for user button presses
|
||||
#define VEXT_ON_VALUE LOW
|
||||
#define LED_PIN 2 // If defined we will blink this LED
|
||||
#define BUTTON_PIN 0 // If defined, this will be used for user button presses
|
||||
#define BUTTON_NEED_PULLUP
|
||||
#define EXT_NOTIFY_OUT 13 // Default pin to use for Ext Notify Module.
|
||||
|
||||
|
@ -17,7 +17,7 @@
|
||||
#define ST7735_RESET 39
|
||||
#define ST7735_MISO -1
|
||||
#define ST7735_BUSY -1
|
||||
#define ST7735_BL_V05 21 /* V1.1 PCB marking */
|
||||
#define TFT_BL 21 /* V1.1 PCB marking */
|
||||
#define ST7735_SPI_HOST SPI3_HOST
|
||||
#define SPI_FREQUENCY 40000000
|
||||
#define SPI_READ_FREQUENCY 16000000
|
||||
@ -29,7 +29,8 @@
|
||||
#define SCREEN_TRANSITION_FRAMERATE 3 // fps
|
||||
#define DISPLAY_FORCE_SMALL_FONTS
|
||||
|
||||
#define VEXT_ENABLE_V05 3 // active HIGH, powers the lora antenna boost
|
||||
#define VEXT_ENABLE 3 // active HIGH, powers the lora antenna boost
|
||||
#define VEXT_ON_VALUE HIGH
|
||||
#define BUTTON_PIN 0
|
||||
|
||||
#define BATTERY_PIN 1 // A battery voltage measurement pin, voltage divider connected here to measure battery voltage
|
||||
@ -88,4 +89,4 @@
|
||||
{ \
|
||||
26, 37, 17, 16, 15, 7 \
|
||||
}
|
||||
// #end keyboard
|
||||
// #end keyboard
|
@ -16,13 +16,13 @@
|
||||
#define ST7789_CS 38
|
||||
#define ST7789_RS 40
|
||||
#define ST7789_BL 21
|
||||
// P#define ST7735_BL_V05 21 /* V1.1 PCB marking */
|
||||
// P#define TFT_BL 21 /* V1.1 PCB marking */
|
||||
|
||||
#define ST7789_RESET -1
|
||||
#define ST7789_MISO -1
|
||||
#define ST7789_BUSY -1
|
||||
#define ST7789_SPI_HOST SPI3_HOST
|
||||
#define ST7789_BACKLIGHT_EN 21
|
||||
#define TFT_BL 21
|
||||
#define SPI_FREQUENCY 40000000
|
||||
#define SPI_READ_FREQUENCY 16000000
|
||||
#define TFT_HEIGHT 320
|
||||
@ -41,7 +41,7 @@
|
||||
// #define ST7735_RESET 39
|
||||
// #define ST7735_MISO -1
|
||||
// #define ST7735_BUSY -1
|
||||
#define ST7735_BL_V05 21 /* V1.1 PCB marking */
|
||||
#define TFT_BL 21 /* V1.1 PCB marking */
|
||||
// #define ST7735_SPI_HOST SPI3_HOST
|
||||
// #define SPI_FREQUENCY 40000000
|
||||
// #define SPI_READ_FREQUENCY 16000000
|
||||
@ -53,7 +53,8 @@
|
||||
#define SCREEN_TRANSITION_FRAMERATE 3 // fps
|
||||
// #define DISPLAY_FORCE_SMALL_FONTS
|
||||
|
||||
#define VEXT_ENABLE_V05 3 // active HIGH, powers the lora antenna boost
|
||||
#define VEXT_ENABLE 3 // active HIGH, powers the lora antenna boost
|
||||
#define VEXT_ON_VALUE HIGH
|
||||
#define BUTTON_PIN 0
|
||||
|
||||
#define BATTERY_PIN 1 // A battery voltage measurement pin, voltage divider connected here to measure battery voltage
|
||||
@ -112,4 +113,4 @@
|
||||
{ \
|
||||
26, 37, 17, 16, 15, 7 \
|
||||
}
|
||||
// #end keyboard
|
||||
// #end keyboard
|
@ -19,7 +19,7 @@
|
||||
// #define ST7735_RESET 39
|
||||
// #define ST7735_MISO -1
|
||||
// #define ST7735_BUSY -1
|
||||
#define ST7735_BL_V05 21 /* V1.1 PCB marking */
|
||||
#define TFT_BL 21 /* V1.1 PCB marking */
|
||||
// #define ST7735_SPI_HOST SPI3_HOST
|
||||
// #define SPI_FREQUENCY 40000000
|
||||
// #define SPI_READ_FREQUENCY 16000000
|
||||
@ -31,7 +31,8 @@
|
||||
#define SCREEN_TRANSITION_FRAMERATE 3 // fps
|
||||
// #define DISPLAY_FORCE_SMALL_FONTS
|
||||
|
||||
#define VEXT_ENABLE_V05 3 // active HIGH, powers the lora antenna boost
|
||||
#define VEXT_ENABLE 3 // active HIGH, powers the lora antenna boost
|
||||
#define VEXT_ON_VALUE HIGH
|
||||
#define BUTTON_PIN 0
|
||||
|
||||
#define BATTERY_PIN 1 // A battery voltage measurement pin, voltage divider connected here to measure battery voltage
|
||||
@ -90,4 +91,4 @@
|
||||
{ \
|
||||
26, 37, 17, 16, 15, 7 \
|
||||
}
|
||||
// #end keyboard
|
||||
// #end keyboard
|
@ -34,13 +34,17 @@
|
||||
#define ST7789_SCK 18
|
||||
#define ST7789_CS 5
|
||||
#define ST7789_RS 26
|
||||
#define ST7789_BL -1 // EXTENDER_PIN(9)
|
||||
// I don't have a 'wiphone' but this I think should not be defined this way (don't set TFT_BL if we don't have a hw way to control
|
||||
// it)
|
||||
// #define ST7789_BL -1 // EXTENDER_PIN(9)
|
||||
|
||||
#define ST7789_RESET -1
|
||||
#define ST7789_MISO 19
|
||||
#define ST7789_BUSY -1
|
||||
#define ST7789_SPI_HOST SPI3_HOST
|
||||
#define ST7789_BACKLIGHT_EN -1 // EXTENDER_PIN(9)
|
||||
// I don't have a 'wiphone' but this I think should not be defined this way (don't set TFT_BL if we don't have a hw way to control
|
||||
// it)
|
||||
// #define TFT_BL -1 // EXTENDER_PIN(9)
|
||||
#define SPI_FREQUENCY 40000000
|
||||
#define SPI_READ_FREQUENCY 16000000
|
||||
#define TFT_HEIGHT 240
|
||||
|
Loading…
Reference in New Issue
Block a user