Merge branch 'develop' into clear-rangetest-results

This commit is contained in:
Ford Jones 2025-09-23 10:31:09 +12:00 committed by GitHub
commit a4e09aa9da
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
24 changed files with 360 additions and 139 deletions

View File

@ -10,7 +10,7 @@ permissions:
jobs:
check-label:
runs-on: ubuntu-24.04
runs-on: ubuntu-latest
steps:
- name: Check for PR labels
uses: actions/github-script@v8

43
boards/heltec_v4.json Normal file
View File

@ -0,0 +1,43 @@
{
"build": {
"arduino": {
"ldscript": "esp32s3_out.ld",
"partitions": "default_16MB.csv",
"memory_type": "qio_qspi"
},
"core": "esp32",
"extra_flags": [
"-DBOARD_HAS_PSRAM",
"-DARDUINO_USB_CDC_ON_BOOT=1",
"-DARDUINO_USB_MODE=0",
"-DARDUINO_RUNNING_CORE=1",
"-DARDUINO_EVENT_RUNNING_CORE=1"
],
"f_cpu": "240000000L",
"f_flash": "80000000L",
"flash_mode": "qio",
"psram_type": "qspi",
"hwids": [["0x303A", "0x1001"]],
"mcu": "esp32s3",
"variant": "heltec_v4"
},
"connectivity": ["wifi", "bluetooth", "lora"],
"debug": {
"default_tool": "esp-builtin",
"onboard_tools": ["esp-builtin"],
"openocd_target": "esp32s3.cfg"
},
"frameworks": ["arduino", "espidf"],
"name": "heltec_wifi_lora_32 v4 (16 MB FLASH, 2 MB PSRAM)",
"upload": {
"flash_size": "16MB",
"maximum_ram_size": 2097152,
"maximum_size": 16777216,
"use_1200bps_touch": true,
"wait_for_upload_port": true,
"require_upload_port": true,
"speed": 921600
},
"url": "https://heltec.org/",
"vendor": "heltec"
}

View File

@ -114,7 +114,7 @@ lib_deps =
[radiolib_base]
lib_deps =
# renovate: datasource=custom.pio depName=RadioLib packageName=jgromes/library/RadioLib
jgromes/RadioLib@7.2.1
jgromes/RadioLib@7.3.0
[device-ui_base]
lib_deps =

View File

@ -516,6 +516,7 @@ bool GPS::setup()
}
}
// Rare Serial Speeds
#ifndef CONFIG_IDF_TARGET_ESP32C6
if (probeTries == GPS_PROBETRIES) {
LOG_DEBUG("Probe for GPS at %d", rareSerialSpeeds[speedSelect]);
gnssModel = probe(rareSerialSpeeds[speedSelect]);
@ -526,6 +527,7 @@ bool GPS::setup()
}
}
}
#endif
}
if (gnssModel != GNSS_MODEL_UNKNOWN) {

View File

@ -1037,7 +1037,7 @@ void Screen::setFrames(FrameFocus focus)
if (!hiddenFrames.chirpy) {
fsi.positions.chirpy = numframes;
normalFrames[numframes++] = graphics::DebugRenderer::drawChirpy;
indicatorIcons.push_back(small_chirpy);
indicatorIcons.push_back(chirpy_small);
}
#if HAS_WIFI && !defined(ARCH_PORTDUINO)

View File

@ -31,19 +31,21 @@ uint8_t test_count = 0;
void menuHandler::loraMenu()
{
static const char *optionsArray[] = {"Back", "Region Picker", "Device Role"};
enum optionsNumbers { Back = 0, lora_picker = 1, device_role_picker = 2 };
static const char *optionsArray[] = {"Back", "Device Role", "Radio Preset", "LoRa Region"};
enum optionsNumbers { Back = 0, device_role_picker = 1, radio_preset_picker = 2, lora_picker = 3 };
BannerOverlayOptions bannerOptions;
bannerOptions.message = "LoRa Actions";
bannerOptions.optionsArrayPtr = optionsArray;
bannerOptions.optionsCount = 3;
bannerOptions.optionsCount = 4;
bannerOptions.bannerCallback = [](int selected) -> void {
if (selected == Back) {
// No action
} else if (selected == lora_picker) {
menuHandler::menuQueue = menuHandler::lora_picker;
} else if (selected == device_role_picker) {
menuHandler::menuQueue = menuHandler::device_role_picker;
} else if (selected == radio_preset_picker) {
menuHandler::menuQueue = menuHandler::radio_preset_picker;
} else if (selected == lora_picker) {
menuHandler::menuQueue = menuHandler::lora_picker;
}
};
screen->showOverlayBanner(bannerOptions);
@ -180,6 +182,53 @@ void menuHandler::DeviceRolePicker()
screen->showOverlayBanner(bannerOptions);
}
void menuHandler::RadioPresetPicker()
{
static const char *optionsArray[] = {"Back", "LongSlow", "LongModerate", "LongFast", "MediumSlow",
"MediumFast", "ShortSlow", "ShortFast", "ShortTurbo"};
enum optionsNumbers {
Back = 0,
radiopreset_LongSlow = 1,
radiopreset_LongModerate = 2,
radiopreset_LongFast = 3,
radiopreset_MediumSlow = 4,
radiopreset_MediumFast = 5,
radiopreset_ShortSlow = 6,
radiopreset_ShortFast = 7,
radiopreset_ShortTurbo = 8
};
BannerOverlayOptions bannerOptions;
bannerOptions.message = "Radio Preset";
bannerOptions.optionsArrayPtr = optionsArray;
bannerOptions.optionsCount = 9;
bannerOptions.bannerCallback = [](int selected) -> void {
if (selected == Back) {
menuHandler::menuQueue = menuHandler::lora_Menu;
screen->runNow();
return;
} else if (selected == radiopreset_LongSlow) {
config.lora.modem_preset = meshtastic_Config_LoRaConfig_ModemPreset_LONG_SLOW;
} else if (selected == radiopreset_LongModerate) {
config.lora.modem_preset = meshtastic_Config_LoRaConfig_ModemPreset_LONG_MODERATE;
} else if (selected == radiopreset_LongFast) {
config.lora.modem_preset = meshtastic_Config_LoRaConfig_ModemPreset_LONG_FAST;
} else if (selected == radiopreset_MediumSlow) {
config.lora.modem_preset = meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_SLOW;
} else if (selected == radiopreset_MediumFast) {
config.lora.modem_preset = meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_FAST;
} else if (selected == radiopreset_ShortSlow) {
config.lora.modem_preset = meshtastic_Config_LoRaConfig_ModemPreset_SHORT_SLOW;
} else if (selected == radiopreset_ShortFast) {
config.lora.modem_preset = meshtastic_Config_LoRaConfig_ModemPreset_SHORT_FAST;
} else if (selected == radiopreset_ShortTurbo) {
config.lora.modem_preset = meshtastic_Config_LoRaConfig_ModemPreset_SHORT_TURBO;
}
service->reloadConfig(SEGMENT_CONFIG);
rebootAtMsec = (millis() + DEFAULT_REBOOT_SECONDS * 1000);
};
screen->showOverlayBanner(bannerOptions);
}
void menuHandler::TwelveHourPicker()
{
static const char *optionsArray[] = {"Back", "12-hour", "24-hour"};
@ -1478,6 +1527,9 @@ void menuHandler::handleMenuSwitch(OLEDDisplay *display)
case device_role_picker:
DeviceRolePicker();
break;
case radio_preset_picker:
RadioPresetPicker();
break;
case no_timeout_lora_picker:
LoraRegionPicker(0);
break;

View File

@ -12,6 +12,7 @@ class menuHandler
lora_Menu,
lora_picker,
device_role_picker,
radio_preset_picker,
no_timeout_lora_picker,
TZ_picker,
twelve_hour_picker,
@ -50,6 +51,7 @@ class menuHandler
static void LoraRegionPicker(uint32_t duration = 30000);
static void loraMenu();
static void DeviceRolePicker();
static void RadioPresetPicker();
static void handleMenuSwitch(OLEDDisplay *display);
static void showConfirmationBanner(const char *message, std::function<void()> onConfirm);
static void clockMenu();

View File

@ -20,7 +20,9 @@
// External variables
extern graphics::Screen *screen;
#if defined(M5STACK_UNITC6L)
static uint32_t lastSwitchTime = 0;
#endif
namespace graphics
{
NodeNum UIRenderer::currentFavoriteNodeNum = 0;
@ -126,8 +128,10 @@ void UIRenderer::drawGpsCoordinates(OLEDDisplay *display, int16_t x, int16_t y,
strcpy(displayLine, "No GPS present");
display->drawString(x, y, displayLine);
} else if (!gps->getHasLock() && !config.position.fixed_position) {
strcpy(displayLine, "No GPS Lock");
display->drawString(x, y, displayLine);
if (strcmp(mode, "line1") == 0) {
strcpy(displayLine, "No GPS Lock");
display->drawString(x, y, displayLine);
}
} else {
geoCoord.updateCoords(int32_t(gps->getLatitude()), int32_t(gps->getLongitude()), int32_t(gps->getAltitude()));
@ -285,9 +289,9 @@ void UIRenderer::drawNodeInfo(OLEDDisplay *display, const OLEDDisplayUiState *st
meshtastic_NodeInfoLite *node = favoritedNodes[nodeIndex];
if (!node || node->num == nodeDB->getNodeNum() || !node->is_favorite)
return;
uint32_t now = millis();
display->clear();
#if defined(M5STACK_UNITC6L)
uint32_t now = millis();
if (now - lastSwitchTime >= 10000) // 10000 ms = 10 秒
{
display->display();
@ -732,7 +736,6 @@ void UIRenderer::drawDeviceFocused(OLEDDisplay *display, OLEDDisplayUiState *sta
int textWidth = 0;
int nameX = 0;
int yOffset = (isHighResolution) ? 0 : 5;
const char *longName = nullptr;
std::string longNameStr;
meshtastic_NodeInfoLite *ourNode = nodeDB->getMeshNode(nodeDB->getNodeNum());
@ -1277,14 +1280,13 @@ void UIRenderer::drawNavigationBar(OLEDDisplay *display, OLEDDisplayUiState *sta
const int totalWidth = (pageEnd - pageStart) * iconSize + (pageEnd - pageStart - 1) * spacing;
const int xStart = (SCREEN_WIDTH - totalWidth) / 2;
// Only show bar briefly after switching frames
static uint32_t navBarLastShown = 0;
static bool cosmeticRefreshDone = false;
bool navBarVisible = millis() - lastFrameChangeTime <= ICON_DISPLAY_DURATION_MS;
int y = navBarVisible ? (SCREEN_HEIGHT - iconSize - 1) : SCREEN_HEIGHT;
#if defined(USE_EINK)
// Only show bar briefly after switching frames
static uint32_t navBarLastShown = 0;
static bool cosmeticRefreshDone = false;
static bool navBarPrevVisible = false;
if (navBarVisible && !navBarPrevVisible) {

View File

@ -287,12 +287,10 @@ const uint8_t digital_icon_clock[] PROGMEM = {0b00111100, 0b01000010, 0b10000101
#define analog_icon_clock_height 8
const uint8_t analog_icon_clock[] PROGMEM = {0b11111111, 0b01000010, 0b00100100, 0b00011000,
0b00100100, 0b01000010, 0b01000010, 0b11111111};
#ifdef M5STACK_UNITC6L
#include "img/icon_small.xbm"
#else
#define chirpy_width 38
#define chirpy_height 50
static unsigned char chirpy[] = {
const uint8_t chirpy[] = {
0xfe, 0xff, 0xff, 0xff, 0xdf, 0x01, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x80, 0xe3, 0x01,
0x00, 0x00, 0xc0, 0xe7, 0x01, 0x00, 0x00, 0xc0, 0xe7, 0x01, 0x00, 0x00, 0xc0, 0xe7, 0x01, 0x00, 0x00, 0x80, 0xe3, 0x01, 0x00,
0x00, 0x00, 0xe0, 0x81, 0xff, 0xff, 0x7f, 0xe0, 0xc1, 0xff, 0xff, 0xff, 0xe0, 0xc1, 0xff, 0xff, 0xff, 0xe0, 0xc1, 0xcf, 0x7f,
@ -308,7 +306,7 @@ static unsigned char chirpy[] = {
#define chirpy_width_hirez 76
#define chirpy_height_hirez 100
static unsigned char chirpy_hirez[] = {
const uint8_t chirpy_hirez[] = {
0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0x03,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00,
@ -360,8 +358,11 @@ static unsigned char chirpy_hirez[] = {
#define chirpy_small_image_width 8
#define chirpy_small_image_height 8
static unsigned char small_chirpy[] = {0x7f, 0x41, 0x55, 0x55, 0x55, 0x55, 0x41, 0x7f};
const uint8_t chirpy_small[] = {0x7f, 0x41, 0x55, 0x55, 0x55, 0x55, 0x41, 0x7f};
#ifdef M5STACK_UNITC6L
#include "img/icon_small.xbm"
#else
#include "img/icon.xbm"
#endif
static_assert(sizeof(icon_bits) >= 0, "Silence unused variable warning");

View File

@ -27,90 +27,4 @@ static uint8_t icon_bits[] = {
0x00, 0x1c, 0x00, 0x00, 0x70, 0x00, 0x10, 0x00,
0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00 };
#endif
// Chirpy image definitions for M5STACK_UNITC6L compatibility
#define chirpy_width 38
#define chirpy_height 50
static unsigned char chirpy[] = {
0xfe, 0xff, 0xff, 0xff, 0xdf, 0x01, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x80, 0xe3, 0x01,
0x00, 0x00, 0xc0, 0xe7, 0x01, 0x00, 0x00, 0xc0, 0xe7, 0x01, 0x00, 0x00, 0xc0, 0xe7, 0x01, 0x00, 0x00, 0x80, 0xe3, 0x01, 0x00,
0x00, 0x00, 0xe0, 0x81, 0xff, 0xff, 0x7f, 0xe0, 0xc1, 0xff, 0xff, 0xff, 0xe0, 0xc1, 0xff, 0xff, 0xff, 0xe0, 0xc1, 0xcf, 0x7f,
0xfe, 0xe0, 0xc1, 0x87, 0x3f, 0xfc, 0xe0, 0xc1, 0x87, 0x3f, 0xfc, 0xe0, 0xc1, 0x87, 0x3f, 0xfc, 0xe0, 0xc1, 0x87, 0x3f, 0xfc,
0xe0, 0xc1, 0x87, 0x3f, 0xfc, 0xe0, 0xc1, 0x87, 0x3f, 0xfc, 0xe0, 0xc1, 0x87, 0x3f, 0xfc, 0xe0, 0xc1, 0x87, 0x3f, 0xfc, 0xe0,
0xc1, 0x87, 0x3f, 0xfc, 0xe0, 0xc1, 0x87, 0x3f, 0xfc, 0xe0, 0xc1, 0x87, 0x3f, 0xfc, 0xe0, 0xc1, 0x87, 0x3f, 0xfc, 0xe0, 0xc1,
0x87, 0x3f, 0xfc, 0xe0, 0xc1, 0xcf, 0x7f, 0xfe, 0xe0, 0xc1, 0xff, 0xff, 0xff, 0xe0, 0xc1, 0xff, 0xff, 0xff, 0xe0, 0x81, 0xff,
0xff, 0x7f, 0xe0, 0x01, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x00, 0xc3, 0x00, 0xe0, 0x01, 0x00, 0xc3,
0x00, 0xe0, 0x01, 0x80, 0xe1, 0x01, 0xe0, 0x01, 0x80, 0xe1, 0x01, 0xe0, 0x01, 0xc0, 0x30, 0x03, 0xe0, 0x01, 0xc0, 0x30, 0x03,
0xe0, 0x01, 0x60, 0x18, 0x06, 0xe0, 0x01, 0x60, 0x18, 0x06, 0xe0, 0x01, 0x30, 0x0c, 0x0c, 0xe0, 0x01, 0x30, 0x0c, 0x0c, 0xe0,
0x01, 0x18, 0x06, 0x18, 0xe0, 0x01, 0x18, 0x06, 0x18, 0xe0, 0x01, 0x0c, 0x03, 0x30, 0xe0, 0x01, 0x0c, 0x03, 0x30, 0xe0, 0x01,
0x00, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x00, 0xe0, 0xfe, 0xff, 0xff, 0xff, 0xdf};
#define chirpy_width_hirez 76
#define chirpy_height_hirez 100
static unsigned char chirpy_hirez[] = {
0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0x03,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xc0, 0x0f, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x0f, 0xfc, 0x03, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xf0, 0x3f, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x3f, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xf0, 0x3f, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x3f, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xf0, 0x3f, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x3f, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xc0, 0x0f, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x0f, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00,
0xfc, 0x03, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0xfc,
0x03, 0xe0, 0x1f, 0xff, 0xff, 0xff, 0xf8, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03,
0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0,
0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f,
0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe,
0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff,
0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f,
0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0,
0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f,
0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00,
0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc,
0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03,
0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0,
0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f,
0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe,
0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff,
0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f,
0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0,
0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f,
0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00,
0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc,
0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03,
0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0,
0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x0f, 0xfe, 0xff, 0x7f, 0xf0, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0x1f,
0xff, 0xff, 0xff, 0xf8, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0xfc, 0x03, 0xe0, 0xff, 0xff,
0xff, 0xff, 0xff, 0x7f, 0x00, 0xfc, 0x03, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x86, 0x61, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x86, 0x61, 0x00,
0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x86, 0x61, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x80, 0x87, 0xe1, 0x01, 0x00,
0x00, 0xfc, 0x03, 0x00, 0x00, 0x80, 0x87, 0xe1, 0x01, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0xc0, 0x83, 0xc1, 0x03, 0x00, 0x00,
0xfc, 0x03, 0x00, 0x00, 0xc0, 0x83, 0xc1, 0x03, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0xe0, 0x01, 0x80, 0x07, 0x00, 0x00, 0xfc,
0x03, 0x00, 0x00, 0xe0, 0x01, 0x80, 0x07, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x0f, 0x00, 0x00, 0xfc, 0x03,
0x00, 0x00, 0xf0, 0x00, 0x00, 0x0f, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x78, 0x00, 0x00, 0x1e, 0x00, 0x00, 0xfc, 0x03, 0x00,
0x00, 0x78, 0x00, 0x00, 0x1e, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00,
0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x78, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x1e,
0x00, 0x00, 0x78, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x0f, 0x00, 0x00, 0xf0, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x0f, 0x00,
0x00, 0xf0, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x80, 0x07, 0x00, 0x00, 0xe0, 0x01, 0x00, 0xfc, 0x03, 0x00, 0x80, 0x07, 0x00, 0x00,
0xe0, 0x01, 0x00, 0xfc, 0x03, 0x00, 0xc0, 0x03, 0x00, 0x00, 0xc0, 0x03, 0x00, 0xfc, 0x03, 0x00, 0xc0, 0x03, 0x00, 0x00, 0xc0,
0x03, 0x00, 0xfc, 0x03, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x80, 0x07, 0x00, 0xfc, 0x03, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x80, 0x07,
0x00, 0xfc, 0x03, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0xfc, 0x03, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00,
0xfc, 0x03, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0xfc, 0x03, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0xfc,
0x03, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0xfc, 0x03, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0xfc, 0x03,
0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0xfc, 0x03, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0xfc, 0x03, 0x00,
0x0f, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0xfc, 0x03, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0xfc, 0x03, 0x80, 0x07,
0x00, 0x00, 0x00, 0x00, 0xe0, 0x01, 0xfc, 0x03, 0x80, 0x07, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x01, 0xfc, 0x03, 0xc0, 0x03, 0x00,
0x00, 0x00, 0x00, 0xc0, 0x03, 0xfc, 0x03, 0xc0, 0x03, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x03, 0xfc, 0x03, 0xe0, 0x01, 0x00, 0x00,
0x00, 0x00, 0x80, 0x07, 0xfc, 0x03, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0x07, 0xfc, 0x03, 0xf0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x0f, 0xfc, 0x03, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xfc, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3
};
#define chirpy_small_image_width 8
#define chirpy_small_image_height 8
static unsigned char small_chirpy[] = {0x7f, 0x41, 0x55, 0x55, 0x55, 0x55, 0x41, 0x7f};
#endif

View File

@ -27,7 +27,7 @@ void RotaryEncoderInterruptBase::init(
if (!isRAK || pinPress != 0) {
pinMode(pinPress, INPUT_PULLUP);
attachInterrupt(pinPress, onIntPress, RISING);
attachInterrupt(pinPress, onIntPress, CHANGE);
}
if (!isRAK || this->_pinA != 0) {
pinMode(this->_pinA, INPUT_PULLUP);

View File

@ -428,8 +428,8 @@ bool Channels::setDefaultPresetCryptoForHash(ChannelHash channelHash)
// Iterate all known presets
for (int preset = _meshtastic_Config_LoRaConfig_ModemPreset_MIN; preset <= _meshtastic_Config_LoRaConfig_ModemPreset_MAX;
++preset) {
const char *name =
DisplayFormatters::getModemPresetDisplayName((meshtastic_Config_LoRaConfig_ModemPreset)preset, false, false);
const char *name = DisplayFormatters::getModemPresetDisplayName((meshtastic_Config_LoRaConfig_ModemPreset)preset, false,
config.lora.use_preset);
if (!name)
continue;
if (strcmp(name, "Invalid") == 0)

View File

@ -97,27 +97,34 @@ bool ReliableRouter::shouldFilterReceived(const meshtastic_MeshPacket *p)
void ReliableRouter::sniffReceived(const meshtastic_MeshPacket *p, const meshtastic_Routing *c)
{
if (isToUs(p)) { // ignore ack/nak/want_ack packets that are not address to us (we only handle 0 hop reliability)
if (p->want_ack) {
if (MeshModule::currentReply) {
LOG_DEBUG("Another module replied to this message, no need for 2nd ack");
} else if (p->which_payload_variant == meshtastic_MeshPacket_decoded_tag) {
// A response may be set to want_ack for retransmissions, but we don't need to ACK a response if it received an
// implicit ACK already. If we received it directly, only ACK with a hop limit of 0
if (!p->decoded.request_id)
sendAckNak(meshtastic_Routing_Error_NONE, getFrom(p), p->id, p->channel,
if (!MeshModule::currentReply) {
if (p->want_ack) {
if (p->which_payload_variant == meshtastic_MeshPacket_decoded_tag) {
/* A response may be set to want_ack for retransmissions, but we don't need to ACK a response if it received
an implicit ACK already. If we received it directly or via NextHopRouter, only ACK with a hop limit of 0 to
make sure the other side stops retransmitting. */
if (!p->decoded.request_id && !p->decoded.reply_id) {
sendAckNak(meshtastic_Routing_Error_NONE, getFrom(p), p->id, p->channel,
routingModule->getHopLimitForResponse(p->hop_start, p->hop_limit));
} else if ((p->hop_start > 0 && p->hop_start == p->hop_limit) || p->next_hop != NO_NEXT_HOP_PREFERENCE) {
sendAckNak(meshtastic_Routing_Error_NONE, getFrom(p), p->id, p->channel, 0);
}
} else if (p->which_payload_variant == meshtastic_MeshPacket_encrypted_tag && p->channel == 0 &&
(nodeDB->getMeshNode(p->from) == nullptr || nodeDB->getMeshNode(p->from)->user.public_key.size == 0)) {
LOG_INFO("PKI packet from unknown node, send PKI_UNKNOWN_PUBKEY");
sendAckNak(meshtastic_Routing_Error_PKI_UNKNOWN_PUBKEY, getFrom(p), p->id, channels.getPrimaryIndex(),
routingModule->getHopLimitForResponse(p->hop_start, p->hop_limit));
else if (p->hop_start > 0 && p->hop_start == p->hop_limit)
sendAckNak(meshtastic_Routing_Error_NONE, getFrom(p), p->id, p->channel, 0);
} else if (p->which_payload_variant == meshtastic_MeshPacket_encrypted_tag && p->channel == 0 &&
(nodeDB->getMeshNode(p->from) == nullptr || nodeDB->getMeshNode(p->from)->user.public_key.size == 0)) {
LOG_INFO("PKI packet from unknown node, send PKI_UNKNOWN_PUBKEY");
sendAckNak(meshtastic_Routing_Error_PKI_UNKNOWN_PUBKEY, getFrom(p), p->id, channels.getPrimaryIndex(),
routingModule->getHopLimitForResponse(p->hop_start, p->hop_limit));
} else {
// Send a 'NO_CHANNEL' error on the primary channel if want_ack packet destined for us cannot be decoded
sendAckNak(meshtastic_Routing_Error_NO_CHANNEL, getFrom(p), p->id, channels.getPrimaryIndex(),
routingModule->getHopLimitForResponse(p->hop_start, p->hop_limit));
} else {
// Send a 'NO_CHANNEL' error on the primary channel if want_ack packet destined for us cannot be decoded
sendAckNak(meshtastic_Routing_Error_NO_CHANNEL, getFrom(p), p->id, channels.getPrimaryIndex(),
routingModule->getHopLimitForResponse(p->hop_start, p->hop_limit));
}
} else if (p->next_hop == nodeDB->getLastByteOfNodeNum(getNodeNum()) && p->hop_limit > 0) {
// No wantAck, but we need to ACK with hop limit of 0 if we were the next hop to stop their retransmissions
sendAckNak(meshtastic_Routing_Error_NONE, getFrom(p), p->id, p->channel, 0);
}
} else {
LOG_DEBUG("Another module replied to this message, no need for 2nd ack");
}
if (p->which_payload_variant == meshtastic_MeshPacket_decoded_tag && c &&
c->error_reason == meshtastic_Routing_Error_PKI_UNKNOWN_PUBKEY) {

View File

@ -52,6 +52,16 @@ template <typename T> bool SX126xInterface<T>::init()
pinMode(SX126X_POWER_EN, OUTPUT);
#endif
#ifdef HELTEC_V4
pinMode(LORA_PA_POWER, OUTPUT);
digitalWrite(LORA_PA_POWER, HIGH);
pinMode(LORA_PA_EN, OUTPUT);
digitalWrite(LORA_PA_EN, LOW);
pinMode(LORA_PA_TX_EN, OUTPUT);
digitalWrite(LORA_PA_TX_EN, LOW);
#endif
#if ARCH_PORTDUINO
tcxoVoltage = (float)portduino_config.dio3_tcxo_voltage / 1000;
if (portduino_config.lora_sx126x_ant_sw_pin.pin != RADIOLIB_NC) {
@ -63,7 +73,7 @@ template <typename T> bool SX126xInterface<T>::init()
LOG_DEBUG("SX126X_DIO3_TCXO_VOLTAGE not defined, not using DIO3 as TCXO reference voltage");
else
LOG_DEBUG("SX126X_DIO3_TCXO_VOLTAGE defined, using DIO3 as TCXO reference voltage at %f V", tcxoVoltage);
setTransmitEnable(false);
// FIXME: May want to set depending on a definition, currently all SX126x variant files use the DC-DC regulator option
bool useRegulatorLDO = false; // Seems to depend on the connection to pin 9/DCC_SW - if an inductor DCDC?
@ -259,6 +269,7 @@ template <typename T> void SX126xInterface<T>::addReceiveMetadata(meshtastic_Mes
*/
template <typename T> void SX126xInterface<T>::configHardwareForSend()
{
setTransmitEnable(true);
RadioLibInterface::configHardwareForSend();
}
@ -271,6 +282,7 @@ template <typename T> void SX126xInterface<T>::startReceive()
sleep();
#else
setTransmitEnable(false);
setStandby();
// We use a 16 bit preamble so this should save some power by letting radio sit in standby mostly.
@ -298,7 +310,7 @@ template <typename T> bool SX126xInterface<T>::isChannelActive()
.irqFlags = RADIOLIB_IRQ_CAD_DEFAULT_FLAGS,
.irqMask = RADIOLIB_IRQ_CAD_DEFAULT_MASK}};
int16_t result;
setTransmitEnable(false);
setStandby();
result = lora.scanChannel(cfg);
if (result == RADIOLIB_LORA_DETECTED)
@ -337,6 +349,26 @@ template <typename T> bool SX126xInterface<T>::sleep()
digitalWrite(SX126X_POWER_EN, LOW);
#endif
#ifdef HELTEC_V4
/*
* Do not switch the power on and off frequently.
* After turning off LORA_PA_EN, the power consumption has dropped to the uA level.
* // digitalWrite(LORA_PA_POWER, LOW);
*/
digitalWrite(LORA_PA_EN, LOW);
digitalWrite(LORA_PA_TX_EN, LOW);
#endif
return true;
}
/** Some boards require GPIO control of tx vs rx paths */
template <typename T> void SX126xInterface<T>::setTransmitEnable(bool txon)
{
#ifdef HELTEC_V4
digitalWrite(LORA_PA_POWER, HIGH);
digitalWrite(LORA_PA_EN, HIGH);
digitalWrite(LORA_PA_TX_EN, txon ? 1 : 0);
#endif
}
#endif

View File

@ -71,5 +71,9 @@ template <class T> class SX126xInterface : public RadioLibInterface
virtual void addReceiveMetadata(meshtastic_MeshPacket *mp) override;
virtual void setStandby() override;
private:
/** Some boards require GPIO control of tx vs rx paths */
void setTransmitEnable(bool txon);
};
#endif

View File

@ -55,12 +55,12 @@ HTTPClient httpClient;
// We need to specify some content-type mapping, so the resources get delivered with the
// right content type and are displayed correctly in the browser
char contentTypes[][2][32] = {{".txt", "text/plain"}, {".html", "text/html"},
{".js", "text/javascript"}, {".png", "image/png"},
{".jpg", "image/jpg"}, {".gz", "application/gzip"},
{".gif", "image/gif"}, {".json", "application/json"},
{".css", "text/css"}, {".ico", "image/vnd.microsoft.icon"},
{".svg", "image/svg+xml"}, {"", ""}};
char const *contentTypes[][2] = {{".txt", "text/plain"}, {".html", "text/html"},
{".js", "text/javascript"}, {".png", "image/png"},
{".jpg", "image/jpg"}, {".gz", "application/gzip"},
{".gif", "image/gif"}, {".json", "application/json"},
{".css", "text/css"}, {".ico", "image/vnd.microsoft.icon"},
{".svg", "image/svg+xml"}, {"", ""}};
// const char *certificate = NULL; // change this as needed, leave as is for no TLS check (yolo security)

View File

@ -231,6 +231,10 @@ class NimbleBluetoothServerCallback : public NimBLEServerCallbacks
{
LOG_INFO("BLE disconnect");
#endif
#ifdef NIMBLE_TWO
if (ble->isDeInit)
return;
#endif
meshtastic::BluetoothStatus newStatus(meshtastic::BluetoothStatus::ConnectionState::DISCONNECTED);
bluetoothStatus->updateStatus(&newStatus);
@ -270,6 +274,7 @@ void NimbleBluetooth::deinit()
{
#ifdef ARCH_ESP32
LOG_INFO("Disable bluetooth until reboot");
isDeInit = true;
#ifdef BLE_LED
#ifdef BLE_LED_INVERTED
@ -278,8 +283,10 @@ void NimbleBluetooth::deinit()
digitalWrite(BLE_LED, LOW);
#endif
#endif
#ifndef NIMBLE_TWO
NimBLEDevice::deinit();
#endif
#endif
}
// Has initial setup been completed

View File

@ -15,6 +15,7 @@ class NimbleBluetooth : BluetoothApi
#if defined(NIMBLE_TWO)
void startAdvertising();
#endif
bool isDeInit = false;
private:
void setupService();

View File

@ -197,6 +197,8 @@
#define HW_VENDOR meshtastic_HardwareModel_T_DECK_PRO
#elif defined(T_LORA_PAGER)
#define HW_VENDOR meshtastic_HardwareModel_T_LORA_PAGER
#elif defined(HELTEC_V4)
#define HW_VENDOR meshtastic_HardwareModel_HELTEC_V4
#elif defined(M5STACK_UNITC6L)
#define HW_VENDOR meshtastic_HardwareModel_M5STACK_C6L
#endif

View File

@ -545,6 +545,12 @@ void enableLoraInterrupt()
gpio_pullup_en((gpio_num_t)LORA_CS);
#endif
#ifdef HELTEC_V4
gpio_pullup_en((gpio_num_t)LORA_PA_POWER);
gpio_pullup_en((gpio_num_t)LORA_PA_EN);
gpio_pulldown_en((gpio_num_t)LORA_PA_TX_EN);
#endif
LOG_INFO("setup LORA_DIO1 (GPIO%02d) with wakeup by gpio interrupt", LORA_DIO1);
gpio_wakeup_enable((gpio_num_t)LORA_DIO1, GPIO_INTR_HIGH_LEVEL);

View File

@ -0,0 +1,70 @@
#ifndef Pins_Arduino_h
#define Pins_Arduino_h
#include <stdint.h>
#define USB_VID 0x303a
#define USB_PID 0x1001
static const uint8_t LED_BUILTIN = 35;
#define BUILTIN_LED LED_BUILTIN // backward compatibility
#define LED_BUILTIN LED_BUILTIN // allow testing #ifdef LED_BUILTIN
static const uint8_t TX = 43;
static const uint8_t RX = 44;
static const uint8_t SDA = 3;
static const uint8_t SCL = 4;
static const uint8_t SS = 8;
static const uint8_t MOSI = 10;
static const uint8_t MISO = 11;
static const uint8_t SCK = 9;
static const uint8_t A0 = 1;
static const uint8_t A1 = 2;
static const uint8_t A2 = 3;
static const uint8_t A3 = 4;
static const uint8_t A4 = 5;
static const uint8_t A5 = 6;
static const uint8_t A6 = 7;
static const uint8_t A7 = 8;
static const uint8_t A8 = 9;
static const uint8_t A9 = 10;
static const uint8_t A10 = 11;
static const uint8_t A11 = 12;
static const uint8_t A12 = 13;
static const uint8_t A13 = 14;
static const uint8_t A14 = 15;
static const uint8_t A15 = 16;
static const uint8_t A16 = 17;
static const uint8_t A17 = 18;
static const uint8_t A18 = 19;
static const uint8_t A19 = 20;
static const uint8_t T1 = 1;
static const uint8_t T2 = 2;
static const uint8_t T3 = 3;
static const uint8_t T4 = 4;
static const uint8_t T5 = 5;
static const uint8_t T6 = 6;
static const uint8_t T7 = 7;
static const uint8_t T8 = 8;
static const uint8_t T9 = 9;
static const uint8_t T10 = 10;
static const uint8_t T11 = 11;
static const uint8_t T12 = 12;
static const uint8_t T13 = 13;
static const uint8_t T14 = 14;
static const uint8_t Vext = 36;
static const uint8_t LED = 35;
static const uint8_t RST_OLED = 21;
static const uint8_t SCL_OLED = 18;
static const uint8_t SDA_OLED = 17;
static const uint8_t RST_LoRa = 12;
static const uint8_t BUSY_LoRa = 13;
static const uint8_t DIO0 = 14;
#endif /* Pins_Arduino_h */

View File

@ -0,0 +1,10 @@
[env:heltec-v4]
extends = esp32s3_base
board = heltec_v4
board_check = true
build_flags =
${esp32s3_base.build_flags}
-D HELTEC_V4
-I variants/esp32s3/heltec_v4
-D GPS_POWER_TOGGLE ; comment this line to disable triple press function on the user button to turn off gps entirely.
-D SX126X_MAX_POWER=11

View File

@ -0,0 +1,58 @@
#define LED_PIN 35
#define USE_SSD1306 // Heltec_v4 has an SSD1315 display (compatible with SSD1306 driver)
#define RESET_OLED 21
#define I2C_SDA 17 // I2C pins for this board
#define I2C_SCL 18
#define VEXT_ENABLE 36 // active low, powers the oled display and the lora antenna boost
#define BUTTON_PIN 0
#define ADC_CTRL 37
#define ADC_CTRL_ENABLED HIGH
#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 USE_SX1262
#define LORA_DIO0 -1 // a No connect on the SX1262 module
#define LORA_RESET 12
#define LORA_DIO1 14 // SX1262 IRQ
#define LORA_DIO2 13 // SX1262 BUSY
#define LORA_DIO3 // Not connected on PCB, but internally on the TTGO SX1262, if DIO3 is high the TCXO is enabled
#define LORA_SCK 9
#define LORA_MISO 11
#define LORA_MOSI 10
#define LORA_CS 8
#define SX126X_CS LORA_CS
#define SX126X_DIO1 LORA_DIO1
#define SX126X_BUSY LORA_DIO2
#define SX126X_RESET LORA_RESET
#define SX126X_DIO2_AS_RF_SWITCH
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
#define LORA_PA_POWER 7 // power en
#define LORA_PA_EN 2
#define LORA_PA_TX_EN 46 // enable tx
/*
* GPS pins
*/
#define GPS_L76K
#define PIN_GPS_RESET (42) // An output to reset L76K GPS. As per datasheet, low for > 100ms will reset the L76K
#define GPS_RESET_MODE LOW
#define PIN_GPS_EN (34)
#define GPS_EN_ACTIVE LOW
#define PERIPHERAL_WARMUP_MS 1000 // Make sure I2C QuickLink has stable power before continuing
#define PIN_GPS_STANDBY (40) // An output to wake GPS, low means allow sleep, high means force wake
#define PIN_GPS_PPS (41)
// Seems to be missing on this new board
#define GPS_TX_PIN (38) // This is for bits going TOWARDS the CPU
#define GPS_RX_PIN (39) // This is for bits going TOWARDS the GPS
#define GPS_THREAD_INTERVAL 50

View File

@ -16,3 +16,11 @@ lib_deps =
debug_tool = jlink
; If not set we will default to uploading over serial (first it forces bootloader entry by talking 1200bps to cdcacm)
;upload_protocol = jlink
; Seeed Xiao BLE but with GPS undefined, and therefore i2c active
[env:seeed_xiao_nrf52840_kit_i2c]
extends = env:seeed_xiao_nrf52840_kit
board_level = extra
build_flags = ${env:seeed_xiao_nrf52840_kit.build_flags}
-DSEEED_XIAO_NRF52840_KIT
build_unflags = -DGPS_L76K