Merge remote-tracking branch 'upstream/dev' into dev

This commit is contained in:
kelsey hudson
2025-09-06 15:13:58 -07:00
109 changed files with 1891 additions and 947 deletions

View File

@@ -0,0 +1,53 @@
{
"build": {
"arduino": {
"ldscript": "nrf52840_s140_v6.ld"
},
"core": "nRF5",
"cpu": "cortex-m4",
"extra_flags": "-DNRF52840_XXAA",
"f_cpu": "64000000L",
"hwids": [
["0x239A", "0x4405"],
["0x239A", "0x0029"],
["0x239A", "0x002A"]
],
"usb_product": "HT-n5262",
"mcu": "nrf52840",
"variant": "heltec_mesh_pocket",
"variants_dir": "variants",
"bsp": {
"name": "adafruit"
},
"softdevice": {
"sd_flags": "-DS140",
"sd_name": "s140",
"sd_version": "6.1.1",
"sd_fwid": "0x00B6"
},
"bootloader": {
"settings_addr": "0xFF000"
}
},
"connectivity": ["bluetooth"],
"debug": {
"jlink_device": "nRF52840_xxAA",
"onboard_tools": ["jlink"],
"svd_path": "nrf52840.svd",
"openocd_target": "nrf52840-mdk-rs"
},
"frameworks": ["arduino"],
"name": "Heltec nrf (Adafruit BSP)",
"upload": {
"maximum_ram_size": 248832,
"maximum_size": 815104,
"speed": 115200,
"protocol": "nrfutil",
"protocols": ["jlink", "nrfjprog", "nrfutil", "stlink"],
"use_1200bps_touch": true,
"require_upload_port": true,
"wait_for_upload_port": true
},
"url": "https://heltec.org/project/meshpocket/",
"vendor": "Heltec"
}

View File

@@ -1,7 +1,13 @@
#include <Arduino.h>
#include "DataStore.h"
DataStore::DataStore(FILESYSTEM& fs, mesh::RTCClock& clock) : _fs(&fs), _clock(&clock),
#if defined(EXTRAFS) || defined(QSPIFLASH)
#define MAX_BLOBRECS 100
#else
#define MAX_BLOBRECS 20
#endif
DataStore::DataStore(FILESYSTEM& fs, mesh::RTCClock& clock) : _fs(&fs), _fsExtra(nullptr), _clock(&clock),
#if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM)
identity_store(fs, "")
#elif defined(RP2040_PLATFORM)
@@ -12,14 +18,27 @@ DataStore::DataStore(FILESYSTEM& fs, mesh::RTCClock& clock) : _fs(&fs), _clock(&
{
}
static File openWrite(FILESYSTEM* _fs, const char* filename) {
#if defined(EXTRAFS) || defined(QSPIFLASH)
DataStore::DataStore(FILESYSTEM& fs, FILESYSTEM& fsExtra, mesh::RTCClock& clock) : _fs(&fs), _fsExtra(&fsExtra), _clock(&clock),
#if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM)
_fs->remove(filename);
return _fs->open(filename, FILE_O_WRITE);
identity_store(fs, "")
#elif defined(RP2040_PLATFORM)
return _fs->open(filename, "w");
identity_store(fs, "/identity")
#else
return _fs->open(filename, "w", true);
identity_store(fs, "/identity")
#endif
{
}
#endif
static File openWrite(FILESYSTEM* fs, const char* filename) {
#if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM)
fs->remove(filename);
return fs->open(filename, FILE_O_WRITE);
#elif defined(RP2040_PLATFORM)
return fs->open(filename, "w");
#else
return fs->open(filename, "w", true);
#endif
}
@@ -30,6 +49,9 @@ void DataStore::begin() {
#if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM)
checkAdvBlobFile();
#if defined(EXTRAFS) || defined(QSPIFLASH)
migrateToSecondaryFS();
#endif
#else
// init 'blob store' support
_fs->mkdir("/bl");
@@ -41,7 +63,13 @@ void DataStore::begin() {
#elif defined(RP2040_PLATFORM)
#include <LittleFS.h>
#elif defined(NRF52_PLATFORM) || defined(STM32_PLATFORM)
#include <InternalFileSystem.h>
#if defined(QSPIFLASH)
#include <CustomLFS_QSPIFlash.h>
#elif defined(EXTRAFS)
#include <CustomLFS.h>
#else
#include <InternalFileSystem.h>
#endif
#endif
#if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM)
@@ -51,9 +79,9 @@ int _countLfsBlock(void *p, lfs_block_t block){
return 0;
}
lfs_ssize_t _getLfsUsedBlockCount() {
lfs_ssize_t _getLfsUsedBlockCount(FILESYSTEM* fs) {
lfs_size_t size = 0;
lfs_traverse(InternalFS._getFS(), _countLfsBlock, &size);
lfs_traverse(fs->_getFS(), _countLfsBlock, &size);
return size;
}
#endif
@@ -67,8 +95,8 @@ uint32_t DataStore::getStorageUsedKb() const {
_fs->info(info);
return info.usedBytes / 1024;
#elif defined(NRF52_PLATFORM) || defined(STM32_PLATFORM)
const lfs_config* config = InternalFS._getFS()->cfg;
int usedBlockCount = _getLfsUsedBlockCount();
const lfs_config* config = _getContactsChannelsFS()->_getFS()->cfg;
int usedBlockCount = _getLfsUsedBlockCount(_getContactsChannelsFS());
int usedBytes = config->block_size * usedBlockCount;
return usedBytes / 1024;
#else
@@ -85,7 +113,7 @@ uint32_t DataStore::getStorageTotalKb() const {
_fs->info(info);
return info.totalBytes / 1024;
#elif defined(NRF52_PLATFORM) || defined(STM32_PLATFORM)
const lfs_config* config = InternalFS._getFS()->cfg;
const lfs_config* config = _getContactsChannelsFS()->_getFS()->cfg;
int totalBytes = config->block_size * config->block_count;
return totalBytes / 1024;
#else
@@ -103,13 +131,31 @@ File DataStore::openRead(const char* filename) {
#endif
}
File DataStore::openRead(FILESYSTEM* fs, const char* filename) {
#if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM)
return fs->open(filename, FILE_O_READ);
#elif defined(RP2040_PLATFORM)
return fs->open(filename, "r");
#else
return fs->open(filename, "r", false);
#endif
}
bool DataStore::removeFile(const char* filename) {
return _fs->remove(filename);
}
bool DataStore::removeFile(FILESYSTEM* fs, const char* filename) {
return fs->remove(filename);
}
bool DataStore::formatFileSystem() {
#if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM)
return _fs->format();
if (_fsExtra == nullptr) {
return _fs->format();
} else {
return _fs->format() && _fsExtra->format();
}
#elif defined(RP2040_PLATFORM)
return LittleFS.format();
#elif defined(ESP32)
@@ -203,11 +249,15 @@ void DataStore::savePrefs(const NodePrefs& _prefs, double node_lat, double node_
}
void DataStore::loadContacts(DataStoreHost* host) {
if (_fs->exists("/contacts3")) {
#if defined(RP2040_PLATFORM)
#if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM)
if (_getContactsChannelsFS()->exists("/contacts3")) {
File file = _getContactsChannelsFS()->open("/contacts3");
#elif defined(RP2040_PLATFORM)
if (_fs->exists("/contacts3")) {
File file = _fs->open("/contacts3", "r");
#else
File file = _fs->open("/contacts3");
if (_fs->exists("/contacts3")) {
File file = _fs->open("/contacts3", "r", false);
#endif
if (file) {
bool full = false;
@@ -240,7 +290,7 @@ void DataStore::loadContacts(DataStoreHost* host) {
}
void DataStore::saveContacts(DataStoreHost* host) {
File file = openWrite(_fs, "/contacts3");
File file = openWrite(_getContactsChannelsFS(), "/contacts3");
if (file) {
uint32_t idx = 0;
ContactInfo c;
@@ -269,11 +319,15 @@ void DataStore::saveContacts(DataStoreHost* host) {
}
void DataStore::loadChannels(DataStoreHost* host) {
#if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM)
if (_getContactsChannelsFS()->exists("/channels2")) {
File file = _getContactsChannelsFS()->open("/channels2");
#elif defined(RP2040_PLATFORM)
if (_fs->exists("/channels2")) {
#if defined(RP2040_PLATFORM)
File file = _fs->open("/channels2", "r");
#else
File file = _fs->open("/channels2");
if (_fs->exists("/channels2")) {
File file = _fs->open("/channels2", "r", false);
#endif
if (file) {
bool full = false;
@@ -300,7 +354,7 @@ void DataStore::loadChannels(DataStoreHost* host) {
}
void DataStore::saveChannels(DataStoreHost* host) {
File file = openWrite(_fs, "/channels2");
File file = openWrite(_getContactsChannelsFS(), "/channels2");
if (file) {
uint8_t channel_idx = 0;
ChannelDetails ch;
@@ -331,12 +385,12 @@ struct BlobRec {
};
void DataStore::checkAdvBlobFile() {
if (!_fs->exists("/adv_blobs")) {
File file = openWrite(_fs, "/adv_blobs");
if (!_getContactsChannelsFS()->exists("/adv_blobs")) {
File file = openWrite(_getContactsChannelsFS(), "/adv_blobs");
if (file) {
BlobRec zeroes;
memset(&zeroes, 0, sizeof(zeroes));
for (int i = 0; i < 20; i++) { // pre-allocate to fixed size
for (int i = 0; i < MAX_BLOBRECS; i++) { // pre-allocate to fixed size
file.write((uint8_t *) &zeroes, sizeof(zeroes));
}
file.close();
@@ -344,10 +398,117 @@ void DataStore::checkAdvBlobFile() {
}
}
uint8_t DataStore::getBlobByKey(const uint8_t key[], int key_len, uint8_t dest_buf[]) {
File file = _fs->open("/adv_blobs");
uint8_t len = 0; // 0 = not found
void DataStore::migrateToSecondaryFS() {
// migrate old adv_blobs, contacts3 and channels2 files to secondary FS if they don't already exist
if (!_fsExtra->exists("/adv_blobs")) {
if (_fs->exists("/adv_blobs")) {
File oldAdvBlobs = openRead(_fs, "/adv_blobs");
File newAdvBlobs = openWrite(_fsExtra, "/adv_blobs");
if (oldAdvBlobs && newAdvBlobs) {
BlobRec rec;
size_t count = 0;
// Copy 20 BlobRecs from old to new
while (count < 20 && oldAdvBlobs.read((uint8_t *)&rec, sizeof(rec)) == sizeof(rec)) {
newAdvBlobs.seek(count * sizeof(BlobRec));
newAdvBlobs.write((uint8_t *)&rec, sizeof(rec));
count++;
}
}
if (oldAdvBlobs) oldAdvBlobs.close();
if (newAdvBlobs) newAdvBlobs.close();
_fs->remove("/adv_blobs");
}
}
if (!_fsExtra->exists("/contacts3")) {
if (_fs->exists("/contacts3")) {
File oldFile = openRead(_fs, "/contacts3");
File newFile = openWrite(_fsExtra, "/contacts3");
if (oldFile && newFile) {
uint8_t buf[64];
int n;
while ((n = oldFile.read(buf, sizeof(buf))) > 0) {
newFile.write(buf, n);
}
}
if (oldFile) oldFile.close();
if (newFile) newFile.close();
_fs->remove("/contacts3");
}
}
if (!_fsExtra->exists("/channels2")) {
if (_fs->exists("/channels2")) {
File oldFile = openRead(_fs, "/channels2");
File newFile = openWrite(_fsExtra, "/channels2");
if (oldFile && newFile) {
uint8_t buf[64];
int n;
while ((n = oldFile.read(buf, sizeof(buf))) > 0) {
newFile.write(buf, n);
}
}
if (oldFile) oldFile.close();
if (newFile) newFile.close();
_fs->remove("/channels2");
}
}
// cleanup nodes which have been testing the extra fs, copy _main.id and new_prefs back to primary
if (_fsExtra->exists("/_main.id")) {
if (_fs->exists("/_main.id")) {_fs->remove("/_main.id");}
File oldFile = openRead(_fsExtra, "/_main.id");
File newFile = openWrite(_fs, "/_main.id");
if (oldFile && newFile) {
uint8_t buf[64];
int n;
while ((n = oldFile.read(buf, sizeof(buf))) > 0) {
newFile.write(buf, n);
}
}
if (oldFile) oldFile.close();
if (newFile) newFile.close();
_fsExtra->remove("/_main.id");
}
if (_fsExtra->exists("/new_prefs")) {
if (_fs->exists("/new_prefs")) {_fs->remove("/new_prefs");}
File oldFile = openRead(_fsExtra, "/new_prefs");
File newFile = openWrite(_fs, "/new_prefs");
if (oldFile && newFile) {
uint8_t buf[64];
int n;
while ((n = oldFile.read(buf, sizeof(buf))) > 0) {
newFile.write(buf, n);
}
}
if (oldFile) oldFile.close();
if (newFile) newFile.close();
_fsExtra->remove("/new_prefs");
}
// remove files from where they should not be anymore
if (_fs->exists("/adv_blobs")) {
_fs->remove("/adv_blobs");
}
if (_fs->exists("/contacts3")) {
_fs->remove("/contacts3");
}
if (_fs->exists("/channels2")) {
_fs->remove("/channels2");
}
if (_fsExtra->exists("/_main.id")) {
_fsExtra->remove("/_main.id");
}
if (_fsExtra->exists("/new_prefs")) {
_fsExtra->remove("/new_prefs");
}
}
uint8_t DataStore::getBlobByKey(const uint8_t key[], int key_len, uint8_t dest_buf[]) {
File file = _getContactsChannelsFS()->open("/adv_blobs");
uint8_t len = 0; // 0 = not found
if (file) {
BlobRec tmp;
while (file.read((uint8_t *) &tmp, sizeof(tmp)) == sizeof(tmp)) {
@@ -364,10 +525,8 @@ uint8_t DataStore::getBlobByKey(const uint8_t key[], int key_len, uint8_t dest_b
bool DataStore::putBlobByKey(const uint8_t key[], int key_len, const uint8_t src_buf[], uint8_t len) {
if (len < PUB_KEY_SIZE+4+SIGNATURE_SIZE || len > MAX_ADVERT_PKT_LEN) return false;
checkAdvBlobFile();
File file = _fs->open("/adv_blobs", FILE_O_WRITE);
File file = _getContactsChannelsFS()->open("/adv_blobs", FILE_O_WRITE);
if (file) {
uint32_t pos = 0, found_pos = 0;
uint32_t min_timestamp = 0xFFFFFFFF;

View File

@@ -15,6 +15,7 @@ public:
class DataStore {
FILESYSTEM* _fs;
FILESYSTEM* _fsExtra;
mesh::RTCClock* _clock;
IdentityStore identity_store;
@@ -25,8 +26,11 @@ class DataStore {
public:
DataStore(FILESYSTEM& fs, mesh::RTCClock& clock);
DataStore(FILESYSTEM& fs, FILESYSTEM& fsExtra, mesh::RTCClock& clock);
void begin();
bool formatFileSystem();
FILESYSTEM* getPrimaryFS() const { return _fs; }
FILESYSTEM* getSecondaryFS() const { return _fsExtra; }
bool loadMainIdentity(mesh::LocalIdentity &identity);
bool saveMainIdentity(const mesh::LocalIdentity &identity);
void loadPrefs(NodePrefs& prefs, double& node_lat, double& node_lon);
@@ -35,10 +39,16 @@ public:
void saveContacts(DataStoreHost* host);
void loadChannels(DataStoreHost* host);
void saveChannels(DataStoreHost* host);
void migrateToSecondaryFS();
uint8_t getBlobByKey(const uint8_t key[], int key_len, uint8_t dest_buf[]);
bool putBlobByKey(const uint8_t key[], int key_len, const uint8_t src_buf[], uint8_t len);
File openRead(const char* filename);
File openRead(FILESYSTEM* fs, const char* filename);
bool removeFile(const char* filename);
bool removeFile(FILESYSTEM* fs, const char* filename);
uint32_t getStorageUsedKb() const;
uint32_t getStorageTotalKb() const;
private:
FILESYSTEM* _getContactsChannelsFS() const { if (_fsExtra) return _fsExtra; return _fs;};
};

View File

@@ -1524,33 +1524,72 @@ void MyMesh::checkCLIRescueCmd() {
// get path from command e.g: "ls /adafruit"
const char *path = &cli_command[3];
bool is_fs2 = false;
if (memcmp(path, "UserData/", 9) == 0) {
path += 8; // skip "UserData"
} else if (memcmp(path, "ExtraFS/", 8) == 0) {
path += 7; // skip "ExtraFS"
is_fs2 = true;
}
Serial.printf("Listing files in %s\n", path);
// log each file and directory
File root = _store->openRead(path);
if(root){
File file = root.openNextFile();
while (file) {
if (file.isDirectory()) {
Serial.printf("[dir] %s\n", file.name());
} else {
Serial.printf("[file] %s (%d bytes)\n", file.name(), file.size());
if (is_fs2 == false) {
if (root) {
File file = root.openNextFile();
while (file) {
if (file.isDirectory()) {
Serial.printf("[dir] UserData%s/%s\n", path, file.name());
} else {
Serial.printf("[file] UserData%s/%s (%d bytes)\n", path, file.name(), file.size());
}
// move to next file
file = root.openNextFile();
}
// move to next file
file = root.openNextFile();
root.close();
}
root.close();
}
if (is_fs2 == true || strlen(path) == 0 || strcmp(path, "/") == 0) {
if (_store->getSecondaryFS() != nullptr) {
File root2 = _store->openRead(_store->getSecondaryFS(), path);
File file = root2.openNextFile();
while (file) {
if (file.isDirectory()) {
Serial.printf("[dir] ExtraFS%s/%s\n", path, file.name());
} else {
Serial.printf("[file] ExtraFS%s/%s (%d bytes)\n", path, file.name(), file.size());
}
// move to next file
file = root2.openNextFile();
}
root2.close();
}
}
} else if (memcmp(cli_command, "cat", 3) == 0) {
// get path from command e.g: "cat /contacts3"
const char *path = &cli_command[4];
bool is_fs2 = false;
if (memcmp(path, "UserData/", 9) == 0) {
path += 8; // skip "UserData"
} else if (memcmp(path, "ExtraFS/", 8) == 0) {
path += 7; // skip "ExtraFS"
is_fs2 = true;
} else {
Serial.println("Invalid path provided, must start with UserData/ or ExtraFS/");
cli_command[0] = 0;
return;
}
// log file content as hex
File file = _store->openRead(path);
if (is_fs2 == true) {
file = _store->openRead(_store->getSecondaryFS(), path);
}
if(file){
// get file content
@@ -1567,17 +1606,30 @@ void MyMesh::checkCLIRescueCmd() {
}
} else if (memcmp(cli_command, "rm ", 3) == 0) {
// get path from command e.g: "rm /adv_blobs"
const char *path = &cli_command[4];
const char *path = &cli_command[3];
MESH_DEBUG_PRINTLN("Removing file: %s", path);
// ensure path is not empty, or root dir
if(!path || strlen(path) == 0 || strcmp(path, "/") == 0){
Serial.println("Invalid path provided");
} else {
bool is_fs2 = false;
if (memcmp(path, "UserData/", 9) == 0) {
path += 8; // skip "UserData"
} else if (memcmp(path, "ExtraFS/", 8) == 0) {
path += 7; // skip "ExtraFS"
is_fs2 = true;
}
// remove file
bool removed = _store->removeFile(path);
bool removed;
if (is_fs2) {
MESH_DEBUG_PRINTLN("Removing file from ExtraFS: %s", path);
removed = _store->removeFile(_store->getSecondaryFS(), path);
} else {
MESH_DEBUG_PRINTLN("Removing file from UserData: %s", path);
removed = _store->removeFile(path);
}
if(removed){
Serial.println("File removed");
} else {

View File

@@ -8,11 +8,11 @@
#define FIRMWARE_VER_CODE 7
#ifndef FIRMWARE_BUILD_DATE
#define FIRMWARE_BUILD_DATE "31 Aug 2025"
#define FIRMWARE_BUILD_DATE "1 Sep 2025"
#endif
#ifndef FIRMWARE_VERSION
#define FIRMWARE_VERSION "v1.8.0"
#define FIRMWARE_VERSION "v1.8.1"
#endif
#if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM)

View File

@@ -14,7 +14,18 @@ static uint32_t _atoi(const char* sp) {
#if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM)
#include <InternalFileSystem.h>
DataStore store(InternalFS, rtc_clock);
#if defined(QSPIFLASH)
#include <CustomLFS_QSPIFlash.h>
DataStore store(InternalFS, QSPIFlash, rtc_clock);
#else
#if defined(EXTRAFS)
#include <CustomLFS.h>
CustomLFS ExtraFS(0xD4000, 0x19000, 128);
DataStore store(InternalFS, ExtraFS, rtc_clock);
#else
DataStore store(InternalFS, rtc_clock);
#endif
#endif
#elif defined(RP2040_PLATFORM)
#include <LittleFS.h>
DataStore store(LittleFS, rtc_clock);
@@ -118,6 +129,18 @@ void setup() {
#if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM)
InternalFS.begin();
#if defined(QSPIFLASH)
if (!QSPIFlash.begin()) {
// debug output might not be available at this point, might be too early. maybe should fall back to InternalFS here?
MESH_DEBUG_PRINTLN("CustomLFS_QSPIFlash: failed to initialize");
} else {
MESH_DEBUG_PRINTLN("CustomLFS_QSPIFlash: initialized successfully");
}
#else
#if defined(EXTRAFS)
ExtraFS.begin();
#endif
#endif
store.begin();
the_mesh.begin(
#ifdef DISPLAY_CLASS

View File

@@ -3,7 +3,9 @@
#include "../MyMesh.h"
#include "target.h"
#define AUTO_OFF_MILLIS 15000 // 15 seconds
#ifndef AUTO_OFF_MILLIS
#define AUTO_OFF_MILLIS 15000 // 15 seconds
#endif
#define BOOT_SCREEN_MILLIS 3000 // 3 seconds
#ifdef PIN_STATUS_LED
@@ -200,8 +202,8 @@ public:
display.print(tmp);
} else if (_page == HomePage::BLUETOOTH) {
display.setColor(DisplayDriver::GREEN);
display.drawXbm((display.width() - 32) / 2, 18,
_task->isSerialEnabled() ? bluetooth_on : bluetooth_off,
display.drawXbm((display.width() - 32) / 2, 18,
_task->isSerialEnabled() ? bluetooth_on : bluetooth_off,
32, 32);
display.setTextSize(1);
display.drawTextCentered(display.width() / 2, 64 - 11, "toggle: " PRESS_LABEL);
@@ -223,11 +225,11 @@ public:
}
bool handleInput(char c) override {
if (c == KEY_LEFT) {
if (c == KEY_LEFT || c == KEY_PREV) {
_page = (_page + HomePage::Count - 1) % HomePage::Count;
return true;
}
if (c == KEY_RIGHT || c == KEY_SELECT) {
if (c == KEY_NEXT || c == KEY_RIGHT) {
_page = (_page + 1) % HomePage::Count;
if (_page == HomePage::RECENT) {
_task->showAlert("Recent adverts", 800);
@@ -321,11 +323,15 @@ public:
display.setColor(DisplayDriver::LIGHT);
display.printWordWrap(p->msg, display.width());
#if AUTO_OFF_MILLIS==0 // probably e-ink
return 10000; // 10 s
#else
return 1000; // next render after 1000 ms
#endif
}
bool handleInput(char c) override {
if (c == KEY_SELECT || c == KEY_RIGHT) {
if (c == KEY_NEXT || c == KEY_RIGHT) {
num_unread--;
if (num_unread == 0) {
_task->gotoHomeScreen();
@@ -354,6 +360,9 @@ void UITask::begin(DisplayDriver* display, SensorManager* sensors, NodePrefs* no
#if defined(PIN_USER_BTN)
user_btn.begin();
#endif
#if defined(PIN_USER_BTN_ANA)
analog_btn.begin();
#endif
_node_prefs = node_prefs;
if (_display != NULL) {
@@ -416,42 +425,38 @@ void UITask::newMsg(uint8_t path_len, const char* from_name, const char* text, i
if (_display != NULL) {
if (!_display->isOn()) _display->turnOn();
_auto_off = millis() + AUTO_OFF_MILLIS; // extend the auto-off timer
_next_refresh = 0; // trigger refresh
_next_refresh = 100; // trigger refresh
}
}
void UITask::userLedHandler() {
#ifdef PIN_STATUS_LED
static int state = 0;
static int next_change = 0;
static int last_increment = 0;
int cur_time = millis();
if (cur_time > next_change) {
if (state == 0) {
state = 1;
if (cur_time > next_led_change) {
if (led_state == 0) {
led_state = 1;
if (_msgcount > 0) {
last_increment = LED_ON_MSG_MILLIS;
last_led_increment = LED_ON_MSG_MILLIS;
} else {
last_increment = LED_ON_MILLIS;
last_led_increment = LED_ON_MILLIS;
}
next_change = cur_time + last_increment;
next_led_change = cur_time + last_led_increment;
} else {
state = 0;
next_change = cur_time + LED_CYCLE_MILLIS - last_increment;
led_state = 0;
next_led_change = cur_time + LED_CYCLE_MILLIS - last_led_increment;
}
digitalWrite(PIN_STATUS_LED, state);
digitalWrite(PIN_STATUS_LED, led_state);
}
#endif
}
void UITask::setCurrScreen(UIScreen* c) {
curr = c;
_next_refresh = 0;
_next_refresh = 100;
}
/*
hardware-agnostic pre-shutdown activity should be done here
/*
hardware-agnostic pre-shutdown activity should be done here
*/
void UITask::shutdown(bool restart){
@@ -489,9 +494,13 @@ void UITask::loop() {
#if defined(PIN_USER_BTN)
int ev = user_btn.check();
if (ev == BUTTON_EVENT_CLICK) {
c = checkDisplayOn(KEY_SELECT);
c = checkDisplayOn(KEY_NEXT);
} else if (ev == BUTTON_EVENT_LONG_PRESS) {
c = handleLongPress(KEY_ENTER);
} else if (ev == BUTTON_EVENT_DOUBLE_CLICK) {
c = handleDoubleClick(KEY_PREV);
} else if (ev == BUTTON_EVENT_TRIPLE_CLICK) {
c = handleTripleClick(KEY_SELECT);
}
#endif
#if defined(WIO_TRACKER_L1)
@@ -508,11 +517,30 @@ void UITask::loop() {
c = handleLongPress(KEY_RIGHT);
}
#endif
#if defined(PIN_USER_BTN_ANA)
ev = analog_btn.check();
if (ev == BUTTON_EVENT_CLICK) {
c = checkDisplayOn(KEY_NEXT);
} else if (ev == BUTTON_EVENT_LONG_PRESS) {
c = handleLongPress(KEY_ENTER);
} else if (ev == BUTTON_EVENT_DOUBLE_CLICK) {
c = handleDoubleClick(KEY_PREV);
} else if (ev == BUTTON_EVENT_TRIPLE_CLICK) {
c = handleTripleClick(KEY_SELECT);
}
#endif
#if defined(DISP_BACKLIGHT) && defined(BACKLIGHT_BTN)
if (millis() > next_backlight_btn_check) {
bool touch_state = digitalRead(PIN_BUTTON2);
digitalWrite(DISP_BACKLIGHT, !touch_state);
next_backlight_btn_check = millis() + 300;
}
#endif
if (c != 0 && curr) {
curr->handleInput(c);
_auto_off = millis() + AUTO_OFF_MILLIS; // extend auto-off timer
_next_refresh = 0; // trigger refresh
_next_refresh = 100; // trigger refresh
}
userLedHandler();
@@ -542,9 +570,11 @@ void UITask::loop() {
}
_display->endFrame();
}
#if AUTO_OFF_MILLIS > 0
if (millis() > _auto_off) {
_display->turnOff();
}
#endif
}
#ifdef AUTO_SHUTDOWN_MILLIVOLTS
@@ -554,7 +584,7 @@ void UITask::loop() {
// show low battery shutdown alert
// we should only do this for eink displays, which will persist after power loss
#ifdef THINKNODE_M1
#if defined(THINKNODE_M1) || defined(LILYGO_TECHO)
if (_display != NULL) {
_display->startFrame();
_display->setTextSize(2);
@@ -593,20 +623,53 @@ char UITask::handleLongPress(char c) {
return c;
}
/*
void UITask::handleButtonTriplePress() {
MESH_DEBUG_PRINTLN("UITask: triple press triggered");
// Toggle buzzer quiet mode
char UITask::handleDoubleClick(char c) {
MESH_DEBUG_PRINTLN("UITask: double click triggered");
checkDisplayOn(c);
return c;
}
char UITask::handleTripleClick(char c) {
MESH_DEBUG_PRINTLN("UITask: triple click triggered");
checkDisplayOn(c);
toggleBuzzer();
c = 0;
return c;
}
void UITask::toggleGPS() {
if (_sensors != NULL) {
// toggle GPS on/off
int num = _sensors->getNumSettings();
for (int i = 0; i < num; i++) {
if (strcmp(_sensors->getSettingName(i), "gps") == 0) {
if (strcmp(_sensors->getSettingValue(i), "1") == 0) {
_sensors->setSettingValue("gps", "0");
soundBuzzer(UIEventType::ack);
showAlert("GPS: Disabled", 800);
} else {
_sensors->setSettingValue("gps", "1");
soundBuzzer(UIEventType::ack);
showAlert("GPS: Enabled", 800);
}
_next_refresh = 0;
break;
}
}
}
}
void UITask::toggleBuzzer() {
// Toggle buzzer quiet mode
#ifdef PIN_BUZZER
if (buzzer.isQuiet()) {
buzzer.quiet(false);
soundBuzzer(UIEventType::ack);
showAlert("Buzzer: ON", 600);
showAlert("Buzzer: ON", 800);
} else {
buzzer.quiet(true);
showAlert("Buzzer: OFF", 600);
showAlert("Buzzer: OFF", 800);
}
_next_refresh = 0; // trigger refresh
#endif
}
*/

View File

@@ -26,6 +26,12 @@ class UITask : public AbstractUITask {
unsigned long _alert_expiry;
int _msgcount;
unsigned long ui_started_at, next_batt_chck;
int next_backlight_btn_check = 0;
#ifdef PIN_STATUS_LED
int led_state = 0;
int next_led_change = 0;
int last_led_increment = 0;
#endif
UIScreen* splash;
UIScreen* home;
@@ -37,6 +43,8 @@ class UITask : public AbstractUITask {
// Button action handlers
char checkDisplayOn(char c);
char handleLongPress(char c);
char handleDoubleClick(char c);
char handleTripleClick(char c);
void setCurrScreen(UIScreen* c);
@@ -55,6 +63,10 @@ public:
bool hasDisplay() const { return _display != NULL; }
bool isButtonPressed() const;
void toggleBuzzer();
void toggleGPS();
// from AbstractUITask
void msgRead(int msgcount) override;
void newMsg(uint8_t path_len, const char* from_name, const char* text, int msgcount) override;

View File

@@ -22,11 +22,11 @@
/* ------------------------------ Config -------------------------------- */
#ifndef FIRMWARE_BUILD_DATE
#define FIRMWARE_BUILD_DATE "31 Aug 2025"
#define FIRMWARE_BUILD_DATE "1 Sep 2025"
#endif
#ifndef FIRMWARE_VERSION
#define FIRMWARE_VERSION "v1.8.0"
#define FIRMWARE_VERSION "v1.8.1"
#endif
#ifndef LORA_FREQ
@@ -732,6 +732,20 @@ public:
mesh::LocalIdentity& getSelfId() override { return self_id; }
void saveIdentity(const mesh::LocalIdentity& new_id) override {
self_id = new_id;
#if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM)
IdentityStore store(*_fs, "");
#elif defined(ESP32)
IdentityStore store(*_fs, "/identity");
#elif defined(RP2040_PLATFORM)
IdentityStore store(*_fs, "/identity");
#else
#error "need to define saveIdentity()"
#endif
store.save("_main", self_id);
}
void clearStats() override {
radio_driver.resetStats();
resetStats();
@@ -804,6 +818,7 @@ void setup() {
#ifdef DISPLAY_CLASS
if (display.begin()) {
display.startFrame();
display.setCursor(0, 0);
display.print("Please wait...");
display.endFrame();
}

View File

@@ -22,11 +22,11 @@
/* ------------------------------ Config -------------------------------- */
#ifndef FIRMWARE_BUILD_DATE
#define FIRMWARE_BUILD_DATE "31 Aug 2025"
#define FIRMWARE_BUILD_DATE "1 Sep 2025"
#endif
#ifndef FIRMWARE_VERSION
#define FIRMWARE_VERSION "v1.8.0"
#define FIRMWARE_VERSION "v1.8.1"
#endif
#ifndef LORA_FREQ
@@ -865,6 +865,20 @@ public:
mesh::LocalIdentity& getSelfId() override { return self_id; }
void saveIdentity(const mesh::LocalIdentity& new_id) override {
self_id = new_id;
#if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM)
IdentityStore store(*_fs, "");
#elif defined(ESP32)
IdentityStore store(*_fs, "/identity");
#elif defined(RP2040_PLATFORM)
IdentityStore store(*_fs, "/identity");
#else
#error "need to define saveIdentity()"
#endif
store.save("_main", self_id);
}
void clearStats() override {
radio_driver.resetStats();
resetStats();
@@ -979,6 +993,7 @@ void setup() {
#ifdef DISPLAY_CLASS
if (display.begin()) {
display.startFrame();
display.setCursor(0, 0);
display.print("Please wait...");
display.endFrame();
}

View File

@@ -837,6 +837,20 @@ bool SensorMesh::formatFileSystem() {
#endif
}
void SensorMesh::saveIdentity(const mesh::LocalIdentity& new_id) {
self_id = new_id;
#if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM)
IdentityStore store(*_fs, "");
#elif defined(ESP32)
IdentityStore store(*_fs, "/identity");
#elif defined(RP2040_PLATFORM)
IdentityStore store(*_fs, "/identity");
#else
#error "need to define saveIdentity()"
#endif
store.save("_main", self_id);
}
void SensorMesh::applyTempRadioParams(float freq, float bw, uint8_t sf, uint8_t cr, int timeout_mins) {
set_radio_at = futureMillis(2000); // give CLI reply some time to be sent back, before applying temp radio params
pending_freq = freq;

View File

@@ -49,11 +49,11 @@ struct ContactInfo {
};
#ifndef FIRMWARE_BUILD_DATE
#define FIRMWARE_BUILD_DATE "31 Aug 2025"
#define FIRMWARE_BUILD_DATE "1 Sep 2025"
#endif
#ifndef FIRMWARE_VERSION
#define FIRMWARE_VERSION "v1.8.0"
#define FIRMWARE_VERSION "v1.8.1"
#endif
#define FIRMWARE_ROLE "sensor"
@@ -89,6 +89,7 @@ public:
strcpy(reply, "not supported");
}
mesh::LocalIdentity& getSelfId() override { return self_id; }
void saveIdentity(const mesh::LocalIdentity& new_id) override;
void clearStats() override { }
void applyTempRadioParams(float freq, float bw, uint8_t sf, uint8_t cr, int timeout_mins) override;

View File

@@ -53,7 +53,7 @@ build_src_filter =
[esp32_base]
extends = arduino_base
platform = platformio/espressif32@^6.11.0
platform = platformio/espressif32@6.11.0
monitor_filters = esp32_exception_decoder
extra_scripts = merge-bin.py
build_flags = ${arduino_base.build_flags}
@@ -78,6 +78,10 @@ platform = nordicnrf52
build_flags = ${arduino_base.build_flags}
-D NRF52_PLATFORM
-D LFS_NO_ASSERT=1
-D EXTRAFS=1
lib_deps =
${arduino_base.lib_deps}
https://github.com/oltaco/CustomLFS @ 0.2
; ----------------- RP2040 ---------------------

View File

@@ -305,7 +305,9 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, const char* command, ch
uint8_t prv_key[PRV_KEY_SIZE];
bool success = mesh::Utils::fromHex(prv_key, PRV_KEY_SIZE, &config[8]);
if (success) {
_callbacks->getSelfId().readFrom(prv_key, PRV_KEY_SIZE);
mesh::LocalIdentity new_id;
new_id.readFrom(prv_key, PRV_KEY_SIZE);
_callbacks->saveIdentity(new_id);
strcpy(reply, "OK");
} else {
strcpy(reply, "Error, invalid key");

View File

@@ -47,6 +47,7 @@ public:
// no op by default
};
virtual mesh::LocalIdentity& getSelfId() = 0;
virtual void saveIdentity(const mesh::LocalIdentity& new_id) = 0;
virtual void clearStats() = 0;
virtual void applyTempRadioParams(float freq, float bw, uint8_t sf, uint8_t cr, int timeout_mins) = 0;
};

View File

@@ -85,8 +85,7 @@ public:
}
void powerOff() override {
// TODO: re-enable this when there is a definite wake-up source pin:
// enterDeepSleep(0);
enterDeepSleep(0);
}
uint16_t getBattMilliVolts() override {

View File

@@ -9,7 +9,6 @@
using namespace Adafruit_LittleFS_Namespace;
#endif
#include <Identity.h>
class IdentityStore {
@@ -18,7 +17,8 @@ class IdentityStore {
public:
IdentityStore(FILESYSTEM& fs, const char* dir): _fs(&fs), _dir(dir) { }
void begin() { if (_dir && _dir[0] == '/') { _fs->mkdir(_dir); } }
void begin() {
if (_dir && _dir[0] == '/') { _fs->mkdir(_dir); } }
bool load(const char *name, mesh::LocalIdentity& id);
bool load(const char *name, mesh::LocalIdentity& id, char display_name[], int max_name_sz);
bool save(const char *name, const mesh::LocalIdentity& id);

View File

@@ -5,9 +5,6 @@
#define DISPLAY_ROTATION 3
#endif
#define SCALE_X 1.5625f // 200 / 128
#define SCALE_Y 1.5625f // 200 / 128
bool GxEPDDisplay::begin() {
display.epd2.selectSPI(SPI1, SPISettings(4000000, MSBFIRST, SPI_MODE0));
SPI1.begin();
@@ -19,6 +16,7 @@ bool GxEPDDisplay::begin() {
display.fillScreen(GxEPD_WHITE);
display.display(true);
#if DISP_BACKLIGHT
digitalWrite(DISP_BACKLIGHT, LOW);
pinMode(DISP_BACKLIGHT, OUTPUT);
#endif
_init = true;
@@ -27,14 +25,14 @@ bool GxEPDDisplay::begin() {
void GxEPDDisplay::turnOn() {
if (!_init) begin();
#if DISP_BACKLIGHT
#if defined(DISP_BACKLIGHT) && !defined(BACKLIGHT_BTN)
digitalWrite(DISP_BACKLIGHT, HIGH);
#endif
_isOn = true;
}
void GxEPDDisplay::turnOff() {
#if DISP_BACKLIGHT
#if defined(DISP_BACKLIGHT) && !defined(BACKLIGHT_BTN)
digitalWrite(DISP_BACKLIGHT, LOW);
#endif
_isOn = false;
@@ -43,14 +41,17 @@ void GxEPDDisplay::turnOff() {
void GxEPDDisplay::clear() {
display.fillScreen(GxEPD_WHITE);
display.setTextColor(GxEPD_BLACK);
display_crc.reset();
}
void GxEPDDisplay::startFrame(Color bkg) {
display.fillScreen(GxEPD_WHITE);
display.setTextColor(_curr_color = GxEPD_BLACK);
display_crc.reset();
}
void GxEPDDisplay::setTextSize(int sz) {
display_crc.update<int>(sz);
switch(sz) {
case 1: // Small
display.setFont(&FreeSans9pt7b);
@@ -68,6 +69,7 @@ void GxEPDDisplay::setTextSize(int sz) {
}
void GxEPDDisplay::setColor(Color c) {
display_crc.update<Color> (c);
// colours need to be inverted for epaper displays
if (c == DARK) {
display.setTextColor(_curr_color = GxEPD_WHITE);
@@ -77,25 +79,41 @@ void GxEPDDisplay::setColor(Color c) {
}
void GxEPDDisplay::setCursor(int x, int y) {
display.setCursor(x*SCALE_X, (y+10)*SCALE_Y);
display_crc.update<int>(x);
display_crc.update<int>(y);
display.setCursor((x+offset_x)*scale_x, (y+offset_y)*scale_y);
}
void GxEPDDisplay::print(const char* str) {
display_crc.update<char>(str, strlen(str));
display.print(str);
}
void GxEPDDisplay::fillRect(int x, int y, int w, int h) {
display.fillRect(x*SCALE_X, y*SCALE_Y, w*SCALE_X, h*SCALE_Y, _curr_color);
display_crc.update<int>(x);
display_crc.update<int>(y);
display_crc.update<int>(w);
display_crc.update<int>(h);
display.fillRect(x*scale_x, y*scale_y, w*scale_x, h*scale_y, _curr_color);
}
void GxEPDDisplay::drawRect(int x, int y, int w, int h) {
display.drawRect(x*SCALE_X, y*SCALE_Y, w*SCALE_X, h*SCALE_Y, _curr_color);
display_crc.update<int>(x);
display_crc.update<int>(y);
display_crc.update<int>(w);
display_crc.update<int>(h);
display.drawRect(x*scale_x, y*scale_y, w*scale_x, h*scale_y, _curr_color);
}
void GxEPDDisplay::drawXbm(int x, int y, const uint8_t* bits, int w, int h) {
display_crc.update<int>(x);
display_crc.update<int>(y);
display_crc.update<int>(w);
display_crc.update<int>(h);
display_crc.update<uint8_t>(bits, w * h / 8);
// Calculate the base position in display coordinates
uint16_t startX = x * SCALE_X;
uint16_t startY = y * SCALE_Y;
uint16_t startX = x * scale_x;
uint16_t startY = y * scale_y;
// Width in bytes for bitmap processing
uint16_t widthInBytes = (w + 7) / 8;
@@ -103,15 +121,15 @@ void GxEPDDisplay::drawXbm(int x, int y, const uint8_t* bits, int w, int h) {
// Process the bitmap row by row
for (uint16_t by = 0; by < h; by++) {
// Calculate the target y-coordinates for this logical row
int y1 = startY + (int)(by * SCALE_Y);
int y2 = startY + (int)((by + 1) * SCALE_Y);
int y1 = startY + (int)(by * scale_y);
int y2 = startY + (int)((by + 1) * scale_y);
int block_h = y2 - y1;
// Scan across the row bit by bit
for (uint16_t bx = 0; bx < w; bx++) {
// Calculate the target x-coordinates for this logical column
int x1 = startX + (int)(bx * SCALE_X);
int x2 = startX + (int)((bx + 1) * SCALE_X);
int x1 = startX + (int)(bx * scale_x);
int x2 = startX + (int)((bx + 1) * scale_x);
int block_w = x2 - x1;
// Get the current bit
@@ -132,9 +150,13 @@ uint16_t GxEPDDisplay::getTextWidth(const char* str) {
int16_t x1, y1;
uint16_t w, h;
display.getTextBounds(str, 0, 0, &x1, &y1, &w, &h);
return ceil((w + 1) / SCALE_X);
return ceil((w + 1) / scale_x);
}
void GxEPDDisplay::endFrame() {
display.display(true);
uint32_t crc = display_crc.finalize();
if (crc != last_display_crc_value) {
display.display(true);
last_display_crc_value = crc;
}
}

View File

@@ -13,10 +13,9 @@
#include <Fonts/FreeSansBold12pt7b.h>
#include <Fonts/FreeSans18pt7b.h>
#define GxEPD2_DISPLAY_CLASS GxEPD2_BW
#define GxEPD2_DRIVER_CLASS GxEPD2_150_BN // DEPG0150BN 200x200, SSD1681, (FPC8101), TTGO T5 V2.4.1
#include <epd/GxEPD2_150_BN.h> // 1.54" b/w
#include <epd/GxEPD2_213_B74.h> // 2.13" b/w
#include <CRC32.h>
#include "DisplayDriver.h"
@@ -25,15 +24,32 @@
class GxEPDDisplay : public DisplayDriver {
#if defined(HELTEC_MESH_POCKET)
GxEPD2_BW<EINK_DISPLAY_MODEL, EINK_DISPLAY_MODEL::HEIGHT> display;
const float scale_x = EINK_SCALE_X;
const float scale_y = EINK_SCALE_Y;
const float offset_x = EINK_X_OFFSET;
const float offset_y = EINK_Y_OFFSET;
#else
GxEPD2_BW<GxEPD2_150_BN, 200> display;
const float scale_x = 1.5625f;
const float scale_y = 1.5625f;
const float offset_x = 0;
const float offset_y = 10;
#endif
bool _init = false;
bool _isOn = false;
uint16_t _curr_color;
CRC32 display_crc;
int last_display_crc_value = 0;
public:
// there is a margin in y...
GxEPDDisplay() : DisplayDriver(128, 128), display(GxEPD2_150_BN(DISP_CS, DISP_DC, DISP_RST, DISP_BUSY)) {
}
#if defined(HELTEC_MESH_POCKET)
GxEPDDisplay() : DisplayDriver(128, 128), display(EINK_DISPLAY_MODEL(PIN_DISPLAY_CS, PIN_DISPLAY_DC, PIN_DISPLAY_RST, PIN_DISPLAY_BUSY)) {}
#else
GxEPDDisplay() : DisplayDriver(128, 128), display(GxEPD2_150_BN(DISP_CS, DISP_DC, DISP_RST, DISP_BUSY)) {}
#endif
bool begin();

View File

@@ -1,5 +1,7 @@
#include "MomentaryButton.h"
#define MULTI_CLICK_WINDOW_MS 280
MomentaryButton::MomentaryButton(int8_t pin, int long_press_millis, bool reverse, bool pulldownup) {
_pin = pin;
_reverse = reverse;
@@ -8,23 +10,51 @@ MomentaryButton::MomentaryButton(int8_t pin, int long_press_millis, bool reverse
prev = _reverse ? HIGH : LOW;
cancel = 0;
_long_millis = long_press_millis;
_threshold = 0;
_click_count = 0;
_last_click_time = 0;
_multi_click_window = MULTI_CLICK_WINDOW_MS;
_pending_click = false;
}
MomentaryButton::MomentaryButton(int8_t pin, int long_press_millis, int analog_threshold) {
_pin = pin;
_reverse = false;
_pull = false;
down_at = 0;
prev = LOW;
cancel = 0;
_long_millis = long_press_millis;
_threshold = analog_threshold;
_click_count = 0;
_last_click_time = 0;
_multi_click_window = MULTI_CLICK_WINDOW_MS;
_pending_click = false;
}
void MomentaryButton::begin() {
if (_pin >= 0) {
if (_pin >= 0 && _threshold == 0) {
pinMode(_pin, _pull ? (_reverse ? INPUT_PULLUP : INPUT_PULLDOWN) : INPUT);
}
}
bool MomentaryButton::isPressed() const {
return isPressed(digitalRead(_pin));
int btn = _threshold > 0 ? (analogRead(_pin) < _threshold) : digitalRead(_pin);
return isPressed(btn);
}
void MomentaryButton::cancelClick() {
cancel = 1;
down_at = 0;
_click_count = 0;
_last_click_time = 0;
_pending_click = false;
}
bool MomentaryButton::isPressed(int level) const {
if (_threshold > 0) {
return level;
}
if (_reverse) {
return level == LOW;
} else {
@@ -36,7 +66,7 @@ int MomentaryButton::check(bool repeat_click) {
if (_pin < 0) return BUTTON_EVENT_NONE;
int event = BUTTON_EVENT_NONE;
int btn = digitalRead(_pin);
int btn = _threshold > 0 ? (analogRead(_pin) < _threshold) : digitalRead(_pin);
if (btn != prev) {
if (isPressed(btn)) {
down_at = millis();
@@ -44,13 +74,20 @@ int MomentaryButton::check(bool repeat_click) {
// button UP
if (_long_millis > 0) {
if (down_at > 0 && (unsigned long)(millis() - down_at) < _long_millis) { // only a CLICK if still within the long_press millis
event = BUTTON_EVENT_CLICK;
_click_count++;
_last_click_time = millis();
_pending_click = true;
}
} else {
event = BUTTON_EVENT_CLICK; // any UP results in CLICK event when NOT using long_press feature
_click_count++;
_last_click_time = millis();
_pending_click = true;
}
if (event == BUTTON_EVENT_CLICK && cancel) {
event = BUTTON_EVENT_NONE;
_click_count = 0;
_last_click_time = 0;
_pending_click = false;
}
down_at = 0;
}
@@ -61,8 +98,16 @@ int MomentaryButton::check(bool repeat_click) {
}
if (_long_millis > 0 && down_at > 0 && (unsigned long)(millis() - down_at) >= _long_millis) {
event = BUTTON_EVENT_LONG_PRESS;
down_at = 0;
if (_pending_click) {
// long press during multi-click detection - cancel pending clicks
cancelClick();
} else {
event = BUTTON_EVENT_LONG_PRESS;
down_at = 0;
_click_count = 0;
_last_click_time = 0;
_pending_click = false;
}
}
if (down_at > 0 && repeat_click) {
unsigned long diff = (unsigned long)(millis() - down_at);
@@ -71,5 +116,30 @@ int MomentaryButton::check(bool repeat_click) {
}
}
if (_pending_click && (millis() - _last_click_time) >= _multi_click_window) {
if (down_at > 0) {
// still pressed - wait for button release before processing clicks
return event;
}
switch (_click_count) {
case 1:
event = BUTTON_EVENT_CLICK;
break;
case 2:
event = BUTTON_EVENT_DOUBLE_CLICK;
break;
case 3:
event = BUTTON_EVENT_TRIPLE_CLICK;
break;
default:
// For 4+ clicks, treat as triple click?
event = BUTTON_EVENT_TRIPLE_CLICK;
break;
}
_click_count = 0;
_last_click_time = 0;
_pending_click = false;
}
return event;
}

View File

@@ -5,18 +5,26 @@
#define BUTTON_EVENT_NONE 0
#define BUTTON_EVENT_CLICK 1
#define BUTTON_EVENT_LONG_PRESS 2
#define BUTTON_EVENT_DOUBLE_CLICK 3
#define BUTTON_EVENT_TRIPLE_CLICK 4
class MomentaryButton {
int8_t _pin;
int8_t prev, cancel;
bool _reverse, _pull;
int _long_millis;
int _threshold; // analog mode
unsigned long down_at;
uint8_t _click_count;
unsigned long _last_click_time;
int _multi_click_window;
bool _pending_click;
bool isPressed(int level) const;
public:
MomentaryButton(int8_t pin, int long_press_mills=0, bool reverse=false, bool pulldownup=false);
MomentaryButton(int8_t pin, int long_press_mills, int analog_threshold);
void begin();
int check(bool repeat_click=false); // returns one of BUTTON_EVENT_*
void cancelClick(); // suppress next BUTTON_EVENT_CLICK (if already in DOWN state)

View File

@@ -2,13 +2,17 @@
#include "DisplayDriver.h"
#define KEY_LEFT 0xB4
#define KEY_UP 0xB5
#define KEY_DOWN 0xB6
#define KEY_RIGHT 0xB7
#define KEY_SELECT 10
#define KEY_ENTER 13
#define KEY_BACK 27 // Esc
#define KEY_LEFT 0xB4
#define KEY_UP 0xB5
#define KEY_DOWN 0xB6
#define KEY_RIGHT 0xB7
#define KEY_SELECT 10
#define KEY_ENTER 13
#define KEY_CANCEL 27 // Esc
#define KEY_HOME 0xF0
#define KEY_NEXT 0xF1
#define KEY_PREV 0xF2
#define KEY_CONTEXT_MENU 0xF3
class UIScreen {
protected:

View File

@@ -16,47 +16,15 @@ ESP32RTCClock fallback_clock;
AutoDiscoverRTCClock rtc_clock(fallback_clock);
SensorManager sensors;
#ifndef LORA_CR
#define LORA_CR 5
#endif
bool radio_init() {
fallback_clock.begin();
rtc_clock.begin(Wire);
#ifdef SX126X_DIO3_TCXO_VOLTAGE
float tcxo = SX126X_DIO3_TCXO_VOLTAGE;
#else
float tcxo = 1.6f;
#endif
#if defined(P_LORA_SCLK)
spi.begin(P_LORA_SCLK, P_LORA_MISO, P_LORA_MOSI);
#endif
int status = radio.begin(LORA_FREQ, LORA_BW, LORA_SF, LORA_CR, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, LORA_TX_POWER, 8, tcxo);
if (status != RADIOLIB_ERR_NONE) {
Serial.print("ERROR: radio init failed: ");
Serial.println(status);
return false; // fail
}
radio.setCRC(1);
#if defined(SX126X_RXEN) && defined(SX126X_TXEN)
radio.setRfSwitchPins(SX126X_RXEN, SX126X_TXEN);
#endif
#ifdef SX126X_CURRENT_LIMIT
radio.setCurrentLimit(SX126X_CURRENT_LIMIT);
#endif
#ifdef SX126X_DIO2_AS_RF_SWITCH
radio.setDio2AsRfSwitch(SX126X_DIO2_AS_RF_SWITCH);
#endif
#ifdef SX126X_RX_BOOSTED_GAIN
radio.setRxBoostedGainMode(SX126X_RX_BOOSTED_GAIN);
#endif
return true; // success
#if defined(P_LORA_SCLK)
return radio.std_init(&spi);
#else
return radio.std_init();
#endif
}
uint32_t radio_get_rng_seed() {

View File

@@ -23,7 +23,7 @@ void HeltecE213Board::begin() {
void HeltecE213Board::enterDeepSleep(uint32_t secs, int pin_wake_btn) {
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);
// Make sure the DIO1 and NSS GPIOs are hold on required levels during deep sleep
// Make sure the DIO1 and NSS GPIOs are hold on required levels during deep sleep
rtc_gpio_set_direction((gpio_num_t)P_LORA_DIO_1, RTC_GPIO_MODE_INPUT_ONLY);
rtc_gpio_pulldown_en((gpio_num_t)P_LORA_DIO_1);
@@ -44,8 +44,7 @@ void HeltecE213Board::begin() {
}
void HeltecE213Board::powerOff() {
// TODO: re-enable this when there is a definite wake-up source pin:
// enterDeepSleep(0);
enterDeepSleep(0);
}
uint16_t HeltecE213Board::getBattMilliVolts() {
@@ -66,4 +65,3 @@ void HeltecE213Board::begin() {
const char* HeltecE213Board::getManufacturerName() const {
return "Heltec E213";
}

View File

@@ -5,15 +5,6 @@
#include <helpers/ESP32Board.h>
#include <driver/rtc_io.h>
// LoRa radio module pins for heltec_vision_master_e213
#define P_LORA_DIO_1 14
#define P_LORA_NSS 8
#define P_LORA_RESET 12
#define P_LORA_BUSY 13
#define P_LORA_SCLK 9
#define P_LORA_MISO 11
#define P_LORA_MOSI 10
class HeltecE213Board : public ESP32Board {
public:
@@ -26,5 +17,4 @@ public:
void powerOff() override;
uint16_t getBattMilliVolts() override;
const char* getManufacturerName() const override ;
};

View File

@@ -1,14 +1,22 @@
[Heltec_Vision_Master_E213_base]
[Heltec_E213_base]
extends = esp32_base
board = heltec_vision_master_e213
board = heltec_e213
build_flags =
${esp32_base.build_flags}
-I variants/heltec_vision_master_e213
-D HELTEC_VISION_MASTER_E213
-I variants/heltec_e213
-D Vision_Master_E213
-D ARDUINO_USB_CDC_ON_BOOT=1
-D RADIO_CLASS=CustomSX1262
-D WRAPPER_CLASS=CustomSX1262Wrapper
-D LORA_TX_POWER=22
-D P_LORA_DIO_1=14
-D P_LORA_NSS=8
-D P_LORA_RESET=12
-D P_LORA_BUSY=13
-D P_LORA_SCLK=9
-D P_LORA_MISO=11
-D P_LORA_MOSI=10
-D P_LORA_TX_LED=45
-D LORA_TX_POWER=22
-D PIN_USER_BTN=0
-D PIN_VEXT_EN=18
-D PIN_VEXT_EN_ACTIVE=HIGH
@@ -26,17 +34,16 @@ build_flags =
-D DISP_RST=3
-D DISP_SCLK=4
-D DISP_MOSI=6
-D Vision_Master_E213
build_src_filter = ${esp32_base.build_src_filter}
+<../variants/heltec_vision_master_e213>
+<../variants/heltec_e213>
lib_deps =
${esp32_base.lib_deps}
https://github.com/Quency-D/heltec-eink-modules/archive/563dd41fd850a1bc3039b8723da4f3a20fe1c800.zip
[env:Heltec_Vision_Master_E213_radio_ble]
extends = Heltec_Vision_Master_E213_base
[env:Heltec_E213_companion_radio_ble]
extends = Heltec_E213_base
build_flags =
${Heltec_Vision_Master_E213_base.build_flags}
${Heltec_E213_base.build_flags}
-I examples/companion_radio/ui-new
-D MAX_CONTACTS=300
-D MAX_GROUP_CHANNELS=8
@@ -44,43 +51,61 @@ build_flags =
-D BLE_PIN_CODE=123456 ; dynamic, random PIN
-D BLE_DEBUG_LOGGING=1
-D OFFLINE_QUEUE_SIZE=256
build_src_filter = ${Heltec_Vision_Master_E213_base.build_src_filter}
build_src_filter = ${Heltec_E213_base.build_src_filter}
+<helpers/ui/E213Display.cpp>
+<helpers/esp32/*.cpp>
+<../examples/companion_radio/*.cpp>
+<../examples/companion_radio/ui-new/*.cpp>
lib_deps =
${Heltec_Vision_Master_E213_base.lib_deps}
${Heltec_E213_base.lib_deps}
densaugeo/base64 @ ~1.4.0
[env:Heltec_Vision_Master_E213_repeater]
extends = Heltec_Vision_Master_E213_base
[env:Heltec_E213_companion_radio_usb]
extends = Heltec_E213_base
build_flags =
${Heltec_Vision_Master_E213_base.build_flags}
${Heltec_E213_base.build_flags}
-I examples/companion_radio/ui-new
-D MAX_CONTACTS=300
-D MAX_GROUP_CHANNELS=8
-D DISPLAY_CLASS=E213Display
-D OFFLINE_QUEUE_SIZE=256
build_src_filter = ${Heltec_E213_base.build_src_filter}
+<helpers/ui/E213Display.cpp>
+<helpers/esp32/*.cpp>
+<../examples/companion_radio/*.cpp>
+<../examples/companion_radio/ui-new/*.cpp>
lib_deps =
${Heltec_E213_base.lib_deps}
densaugeo/base64 @ ~1.4.0
[env:Heltec_E213_repeater]
extends = Heltec_E213_base
build_flags =
${Heltec_E213_base.build_flags}
-D DISPLAY_CLASS=E213Display
-D ADVERT_NAME='"Heltec E213 Repeater"'
-D ADVERT_LAT=0.0
-D ADVERT_LON=0.0
build_src_filter = ${Heltec_Vision_Master_E213_base.build_src_filter}
build_src_filter = ${Heltec_E213_base.build_src_filter}
+<helpers/ui/E213Display.cpp>
+<../examples/simple_repeater>
lib_deps =
${Heltec_Vision_Master_E213_base.lib_deps}
${Heltec_E213_base.lib_deps}
${esp32_ota.lib_deps}
[env:Heltec_Vision_Master_E213_room_server]
extends = Heltec_Vision_Master_E213_base
[env:Heltec_E213_room_server]
extends = Heltec_E213_base
build_flags =
${Heltec_Vision_Master_E213_base.build_flags}
${Heltec_E213_base.build_flags}
-D DISPLAY_CLASS=E213Display
-D ADVERT_NAME='"Heltec E213 Room"'
-D ADVERT_LAT=0.0
-D ADVERT_LON=0.0
-D ADMIN_PASSWORD='"password"'
-D ROOM_PASSWORD='"hello"'
build_src_filter = ${Heltec_Vision_Master_E213_base.build_src_filter}
build_src_filter = ${Heltec_E213_base.build_src_filter}
+<helpers/ui/E213Display.cpp>
+<../examples/simple_room_server>
lib_deps =
${Heltec_Vision_Master_E213_base.lib_deps}
${Heltec_E213_base.lib_deps}
${esp32_ota.lib_deps}

View File

@@ -23,7 +23,7 @@ void HeltecE290Board::begin() {
void HeltecE290Board::enterDeepSleep(uint32_t secs, int pin_wake_btn) {
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);
// Make sure the DIO1 and NSS GPIOs are hold on required levels during deep sleep
// Make sure the DIO1 and NSS GPIOs are hold on required levels during deep sleep
rtc_gpio_set_direction((gpio_num_t)P_LORA_DIO_1, RTC_GPIO_MODE_INPUT_ONLY);
rtc_gpio_pulldown_en((gpio_num_t)P_LORA_DIO_1);
@@ -44,8 +44,7 @@ void HeltecE290Board::begin() {
}
void HeltecE290Board::powerOff() {
// TODO: re-enable this when there is a definite wake-up source pin:
// enterDeepSleep(0);
enterDeepSleep(0);
}
uint16_t HeltecE290Board::getBattMilliVolts() {
@@ -66,4 +65,3 @@ void HeltecE290Board::begin() {
const char* HeltecE290Board::getManufacturerName() const {
return "Heltec E290";
}

View File

@@ -5,15 +5,6 @@
#include <helpers/ESP32Board.h>
#include <driver/rtc_io.h>
// LoRa radio module pins for heltec_vision_master_e290
#define P_LORA_DIO_1 14
#define P_LORA_NSS 8
#define P_LORA_RESET 12
#define P_LORA_BUSY 13
#define P_LORA_SCLK 9
#define P_LORA_MISO 11
#define P_LORA_MOSI 10
class HeltecE290Board : public ESP32Board {
public:

View File

@@ -1,13 +1,21 @@
[Heltec_Vision_Master_E290_base]
[Heltec_E290_base]
extends = esp32_base
board = heltec_vision_master_e290
board = heltec_e290
build_flags =
${esp32_base.build_flags}
-I variants/heltec_vision_master_e290
-D HELTEC_VISION_MASTER_E290
-I variants/heltec_e290
-D Vision_Master_E290
-D ARDUINO_USB_CDC_ON_BOOT=1
-D RADIO_CLASS=CustomSX1262
-D WRAPPER_CLASS=CustomSX1262Wrapper
-D LORA_TX_POWER=22
-D P_LORA_DIO_1=14
-D P_LORA_NSS=8
-D P_LORA_RESET=12
-D P_LORA_BUSY=13
-D P_LORA_SCLK=9
-D P_LORA_MISO=11
-D P_LORA_MOSI=10
-D P_LORA_TX_LED=45
-D PIN_USER_BTN=0
-D PIN_VEXT_EN=18
@@ -20,17 +28,16 @@ build_flags =
-D SX126X_RX_BOOSTED_GAIN=1
-D PIN_BOARD_SDA=39
-D PIN_BOARD_SCL=38
-D Vision_Master_E290
build_src_filter = ${esp32_base.build_src_filter}
+<../variants/heltec_vision_master_e290>
+<../variants/heltec_e290>
lib_deps =
${esp32_base.lib_deps}
https://github.com/Quency-D/heltec-eink-modules/archive/563dd41fd850a1bc3039b8723da4f3a20fe1c800.zip
[env:Heltec_Vision_Master_E290_radio_ble]
extends = Heltec_Vision_Master_E290_base
[env:Heltec_E290_companion_radio_ble]
extends = Heltec_E290_base
build_flags =
${Heltec_Vision_Master_E290_base.build_flags}
${Heltec_E290_base.build_flags}
-I examples/companion_radio/ui-new
-D MAX_CONTACTS=300
-D MAX_GROUP_CHANNELS=8
@@ -38,43 +45,63 @@ build_flags =
-D BLE_PIN_CODE=123456 ; dynamic, random PIN
-D BLE_DEBUG_LOGGING=1
-D OFFLINE_QUEUE_SIZE=256
build_src_filter = ${Heltec_Vision_Master_E290_base.build_src_filter}
build_src_filter = ${Heltec_E290_base.build_src_filter}
+<helpers/ui/E290Display.cpp>
+<helpers/esp32/*.cpp>
+<../examples/companion_radio/*.cpp>
+<../examples/companion_radio/ui-new/*.cpp>
lib_deps =
${Heltec_Vision_Master_E290_base.lib_deps}
${Heltec_E290_base.lib_deps}
densaugeo/base64 @ ~1.4.0
[env:Heltec_Vision_Master_E290_repeater]
extends = Heltec_Vision_Master_E290_base
[env:Heltec_E290_companion_radio_usb]
extends = Heltec_E290_base
build_flags =
${Heltec_Vision_Master_E290_base.build_flags}
${Heltec_E290_base.build_flags}
-I examples/companion_radio/ui-new
-D MAX_CONTACTS=300
-D MAX_GROUP_CHANNELS=8
-D DISPLAY_CLASS=E290Display
-D BLE_PIN_CODE=123456 ; dynamic, random PIN
-D BLE_DEBUG_LOGGING=1
-D OFFLINE_QUEUE_SIZE=256
build_src_filter = ${Heltec_E290_base.build_src_filter}
+<helpers/ui/E290Display.cpp>
+<helpers/esp32/*.cpp>
+<../examples/companion_radio/*.cpp>
+<../examples/companion_radio/ui-new/*.cpp>
lib_deps =
${Heltec_E290_base.lib_deps}
densaugeo/base64 @ ~1.4.0
[env:Heltec_E290_repeater]
extends = Heltec_E290_base
build_flags =
${Heltec_E290_base.build_flags}
-D DISPLAY_CLASS=E290Display
-D ADVERT_NAME='"Heltec E290 Repeater"'
-D ADVERT_LAT=0.0
-D ADVERT_LON=0.0
build_src_filter = ${Heltec_Vision_Master_E290_base.build_src_filter}
build_src_filter = ${Heltec_E290_base.build_src_filter}
+<helpers/ui/E290Display.cpp>
+<../examples/simple_repeater>
lib_deps =
${Heltec_Vision_Master_E290_base.lib_deps}
${Heltec_E290_base.lib_deps}
${esp32_ota.lib_deps}
[env:Heltec_Vision_Master_E290_room_server]
extends = Heltec_Vision_Master_E290_base
[env:Heltec_E290_room_server]
extends = Heltec_E290_base
build_flags =
${Heltec_Vision_Master_E290_base.build_flags}
${Heltec_E290_base.build_flags}
-D DISPLAY_CLASS=E290Display
-D ADVERT_NAME='"Heltec E290 Room"'
-D ADVERT_LAT=0.0
-D ADVERT_LON=0.0
-D ADMIN_PASSWORD='"password"'
-D ROOM_PASSWORD='"hello"'
build_src_filter = ${Heltec_Vision_Master_E290_base.build_src_filter}
build_src_filter = ${Heltec_E290_base.build_src_filter}
+<helpers/ui/E290Display.cpp>
+<../examples/simple_room_server>
lib_deps =
${Heltec_Vision_Master_E290_base.lib_deps}
${Heltec_E290_base.lib_deps}
${esp32_ota.lib_deps}

View File

@@ -59,8 +59,8 @@ build_flags =
extends = Heltec_mesh_solar
build_flags =
${Heltec_mesh_solar.build_flags}
-D MAX_CONTACTS=100
-D MAX_GROUP_CHANNELS=8
-D MAX_CONTACTS=350
-D MAX_GROUP_CHANNELS=40
-D BLE_PIN_CODE=123456
; -D BLE_DEBUG_LOGGING=1
-D OFFLINE_QUEUE_SIZE=256
@@ -77,8 +77,8 @@ lib_deps =
extends = Heltec_mesh_solar
build_flags =
${Heltec_mesh_solar.build_flags}
-D MAX_CONTACTS=100
-D MAX_GROUP_CHANNELS=8
-D MAX_CONTACTS=350
-D MAX_GROUP_CHANNELS=40
; -D BLE_PIN_CODE=123456
; -D BLE_DEBUG_LOGGING=1
; -D MESH_PACKET_LOGGING=1

View File

@@ -1,19 +1,17 @@
#include <Arduino.h>
#include "T114Board.h"
#include <bluefruit.h>
#include <Arduino.h>
#include <Wire.h>
#include <bluefruit.h>
static BLEDfu bledfu;
static void connect_callback(uint16_t conn_handle)
{
static void connect_callback(uint16_t conn_handle) {
(void)conn_handle;
MESH_DEBUG_PRINTLN("BLE client connected");
}
static void disconnect_callback(uint16_t conn_handle, uint8_t reason)
{
static void disconnect_callback(uint16_t conn_handle, uint8_t reason) {
(void)conn_handle;
(void)reason;
@@ -60,7 +58,7 @@ void T114Board::begin() {
// Disable unused analog peripherals
// SAADC channels - only keep what's needed for battery monitoring
NRF_SAADC->ENABLE = 0; // Re-enable only when needed for measurements
NRF_SAADC->ENABLE = 0; // Re-enable only when needed for measurements
// COMP - Comparator not used
NRF_COMP->ENABLE = 0;
@@ -78,10 +76,10 @@ void T114Board::begin() {
pinMode(SX126X_POWER_EN, OUTPUT);
digitalWrite(SX126X_POWER_EN, HIGH);
delay(10); // give sx1262 some time to power up
delay(10); // give sx1262 some time to power up
}
bool T114Board::startOTAUpdate(const char* id, char reply[]) {
bool T114Board::startOTAUpdate(const char *id, char reply[]) {
// Config the peripheral connection with maximum bandwidth
// more SRAM required by SoftDevice
// Note: All config***() function must be called before begin()

View File

@@ -3,19 +3,6 @@
#include <MeshCore.h>
#include <Arduino.h>
// LoRa radio module pins for Heltec T114
#define P_LORA_DIO_1 20
#define P_LORA_NSS 24
#define P_LORA_RESET 25
#define P_LORA_BUSY 17
#define P_LORA_SCLK 19
#define P_LORA_MISO 23
#define P_LORA_MOSI 22
#define SX126X_POWER_EN 37
#define SX126X_DIO2_AS_RF_SWITCH true
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
// built-ins
#define PIN_VBAT_READ 4
#define PIN_BAT_CTL 6

View File

@@ -0,0 +1,196 @@
;
; Heltec T114 without display
;
[Heltec_t114]
extends = nrf52_base
board = heltec_t114
board_build.ldscript = boards/nrf52840_s140_v6.ld
build_flags = ${nrf52_base.build_flags}
-I lib/nrf52/s140_nrf52_6.1.1_API/include
-I lib/nrf52/s140_nrf52_6.1.1_API/include/nrf52
-I variants/heltec_t114
-I src/helpers/ui
-D HELTEC_T114
-D P_LORA_DIO_1=20
-D P_LORA_NSS=24
-D P_LORA_RESET=25
-D P_LORA_BUSY=17
-D P_LORA_SCLK=19
-D P_LORA_MISO=23
-D P_LORA_MOSI=22
-D P_LORA_TX_LED=35
-D RADIO_CLASS=CustomSX1262
-D WRAPPER_CLASS=CustomSX1262Wrapper
-D LORA_TX_POWER=22
-D SX126X_POWER_EN=37
-D SX126X_DIO2_AS_RF_SWITCH=true
-D SX126X_DIO3_TCXO_VOLTAGE=1.8
-D SX126X_CURRENT_LIMIT=140
-D SX126X_RX_BOOSTED_GAIN=1
-D DISPLAY_CLASS=NullDisplayDriver
-D ST7789
build_src_filter = ${nrf52_base.build_src_filter}
+<helpers/*.cpp>
+<../variants/heltec_t114>
lib_deps =
${nrf52_base.lib_deps}
stevemarple/MicroNMEA @ ^2.0.6
adafruit/Adafruit GFX Library @ ^1.12.1
debug_tool = jlink
upload_protocol = nrfutil
[env:Heltec_t114_without_display_repeater]
extends = Heltec_t114
build_src_filter = ${Heltec_t114.build_src_filter}
+<../examples/simple_repeater>
build_flags =
${Heltec_t114.build_flags}
-D ADVERT_NAME='"Heltec_T114 Repeater"'
-D ADVERT_LAT=0.0
-D ADVERT_LON=0.0
-D ADMIN_PASSWORD='"password"'
-D MAX_NEIGHBOURS=8
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
[env:Heltec_t114_without_display_room_server]
extends = Heltec_t114
build_src_filter = ${Heltec_t114.build_src_filter}
+<../examples/simple_room_server>
build_flags =
${Heltec_t114.build_flags}
-D ADVERT_NAME='"Heltec_T114 Room"'
-D ADVERT_LAT=0.0
-D ADVERT_LON=0.0
-D ADMIN_PASSWORD='"password"'
-D ROOM_PASSWORD='"hello"'
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
[env:Heltec_t114_without_display_companion_radio_ble]
extends = Heltec_t114
build_flags =
${Heltec_t114.build_flags}
-I examples/companion_radio/ui-new
-D MAX_CONTACTS=350
-D MAX_GROUP_CHANNELS=40
-D BLE_PIN_CODE=123456
; -D BLE_DEBUG_LOGGING=1
-D OFFLINE_QUEUE_SIZE=256
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
build_src_filter = ${Heltec_t114.build_src_filter}
+<helpers/nrf52/SerialBLEInterface.cpp>
+<../examples/companion_radio/*.cpp>
+<../examples/companion_radio/ui-new/*.cpp>
lib_deps =
${Heltec_t114.lib_deps}
densaugeo/base64 @ ~1.4.0
[env:Heltec_t114_without_display_companion_radio_usb]
extends = Heltec_t114
build_flags =
${Heltec_t114.build_flags}
-I examples/companion_radio/ui-new
-D MAX_CONTACTS=350
-D MAX_GROUP_CHANNELS=40
; -D BLE_PIN_CODE=123456
; -D BLE_DEBUG_LOGGING=1
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
build_src_filter = ${Heltec_t114.build_src_filter}
+<helpers/nrf52/*.cpp>
+<../examples/companion_radio/*.cpp>
+<../examples/companion_radio/ui-new/*.cpp>
lib_deps =
${Heltec_t114.lib_deps}
densaugeo/base64 @ ~1.4.0
;
; Heltec T114 with ST7789 display
;
[Heltec_t114_with_display]
extends = Heltec_t114
board = heltec_t114
board_build.ldscript = boards/nrf52840_s140_v6.ld
build_flags = ${Heltec_t114.build_flags}
-D HELTEC_T114_WITH_DISPLAY
-D DISPLAY_CLASS=ST7789Display
build_src_filter = ${Heltec_t114.build_src_filter}
+<helpers/ui/ST7789Display.cpp>
+<helpers/ui/MomentaryButton.cpp>
+<helpers/ui/OLEDDisplay.cpp>
+<helpers/ui/OLEDDisplayFonts.cpp>
lib_deps =
${Heltec_t114.lib_deps}
debug_tool = jlink
upload_protocol = nrfutil
[env:Heltec_t114_repeater]
extends = Heltec_t114_with_display
build_src_filter = ${Heltec_t114_with_display.build_src_filter}
+<../examples/simple_repeater>
build_flags =
${Heltec_t114_with_display.build_flags}
-D ADVERT_NAME='"Heltec_T114 Repeater"'
-D ADVERT_LAT=0.0
-D ADVERT_LON=0.0
-D ADMIN_PASSWORD='"password"'
-D MAX_NEIGHBOURS=8
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
[env:Heltec_t114_room_server]
extends = Heltec_t114_with_display
build_src_filter = ${Heltec_t114_with_display.build_src_filter}
+<../examples/simple_room_server>
build_flags =
${Heltec_t114_with_display.build_flags}
-D ADVERT_NAME='"Heltec_T114 Room"'
-D ADVERT_LAT=0.0
-D ADVERT_LON=0.0
-D ADMIN_PASSWORD='"password"'
-D ROOM_PASSWORD='"hello"'
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
[env:Heltec_t114_companion_radio_ble]
extends = Heltec_t114_with_display
build_flags =
${Heltec_t114_with_display.build_flags}
-I examples/companion_radio/ui-new
-D MAX_CONTACTS=100
-D MAX_GROUP_CHANNELS=8
-D BLE_PIN_CODE=123456
; -D BLE_DEBUG_LOGGING=1
-D OFFLINE_QUEUE_SIZE=256
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
build_src_filter = ${Heltec_t114_with_display.build_src_filter}
+<helpers/nrf52/SerialBLEInterface.cpp>
+<../examples/companion_radio/*.cpp>
+<../examples/companion_radio/ui-new/*.cpp>
lib_deps =
${Heltec_t114_with_display.lib_deps}
densaugeo/base64 @ ~1.4.0
[env:Heltec_t114_companion_radio_usb]
extends = Heltec_t114_with_display
build_flags =
${Heltec_t114_with_display.build_flags}
-I examples/companion_radio/ui-new
-D MAX_CONTACTS=100
-D MAX_GROUP_CHANNELS=8
; -D BLE_PIN_CODE=123456
; -D BLE_DEBUG_LOGGING=1
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
build_src_filter = ${Heltec_t114_with_display.build_src_filter}
+<helpers/nrf52/*.cpp>
+<../examples/companion_radio/*.cpp>
+<../examples/companion_radio/ui-new/*.cpp>
lib_deps =
${Heltec_t114_with_display.lib_deps}
densaugeo/base64 @ ~1.4.0

View File

@@ -3,14 +3,19 @@
#define RADIOLIB_STATIC_ONLY 1
#include <RadioLib.h>
#include <helpers/radiolib/RadioLibWrappers.h>
#include <helpers/nrf52/T114Board.h>
#include <T114Board.h>
#include <helpers/radiolib/CustomSX1262Wrapper.h>
#include <helpers/AutoDiscoverRTCClock.h>
#include <helpers/SensorManager.h>
#include <helpers/sensors/LocationProvider.h>
#ifdef DISPLAY_CLASS
#include <helpers/ui/ST7789Display.h>
#include <helpers/ui/MomentaryButton.h>
#include <helpers/ui/MomentaryButton.h>
#ifdef HELTEC_T114_WITH_DISPLAY
#include <helpers/ui/ST7789Display.h>
#else
#include "helpers/ui/NullDisplayDriver.h"
#endif
#endif
class T114SensorManager : public SensorManager {

View File

@@ -23,7 +23,7 @@ void HeltecT190Board::begin() {
void HeltecT190Board::enterDeepSleep(uint32_t secs, int pin_wake_btn) {
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);
// Make sure the DIO1 and NSS GPIOs are hold on required levels during deep sleep
// Make sure the DIO1 and NSS GPIOs are hold on required levels during deep sleep
rtc_gpio_set_direction((gpio_num_t)P_LORA_DIO_1, RTC_GPIO_MODE_INPUT_ONLY);
rtc_gpio_pulldown_en((gpio_num_t)P_LORA_DIO_1);
@@ -44,8 +44,7 @@ void HeltecT190Board::begin() {
}
void HeltecT190Board::powerOff() {
// TODO: re-enable this when there is a definite wake-up source pin:
// enterDeepSleep(0);
enterDeepSleep(0);
}
uint16_t HeltecT190Board::getBattMilliVolts() {
@@ -66,4 +65,3 @@ void HeltecT190Board::begin() {
const char* HeltecT190Board::getManufacturerName() const {
return "Heltec T190";
}

View File

@@ -5,15 +5,6 @@
#include <helpers/ESP32Board.h>
#include <driver/rtc_io.h>
// LoRa radio module pins for heltec_vision_master_e290
#define P_LORA_DIO_1 14
#define P_LORA_NSS 8
#define P_LORA_RESET 12
#define P_LORA_BUSY 13
#define P_LORA_SCLK 9
#define P_LORA_MISO 11
#define P_LORA_MOSI 10
class HeltecT190Board : public ESP32Board {
public:

View File

@@ -1,13 +1,20 @@
[Heltec_Vision_Master_T190_base]
[Heltec_T190_base]
extends = esp32_base
board = heltec_vision_master_t190
board = heltec_t190
build_flags =
${esp32_base.build_flags}
-I variants/heltec_vision_master_t190
-I variants/heltec_t190
-I src/helpers/ui
-D HELTEC_VISION_MASTER_T190
-D RADIO_CLASS=CustomSX1262
-D WRAPPER_CLASS=CustomSX1262Wrapper
-D P_LORA_DIO_1=14
-D P_LORA_NSS=8
-D P_LORA_RESET=12
-D P_LORA_BUSY=13
-D P_LORA_SCLK=9
-D P_LORA_MISO=11
-D P_LORA_MOSI=10
-D LORA_TX_POWER=22
-D PIN_USER_BTN=0
-D PIN_VEXT_EN=5
@@ -31,7 +38,7 @@ build_flags =
-D ST7789
-D DISPLAY_CLASS=ST7789Display
build_src_filter = ${esp32_base.build_src_filter}
+<../variants/heltec_vision_master_t190>
+<../variants/heltec_t190>
+<helpers/*.cpp>
+<helpers/ui/ST7789Display.cpp>
+<helpers/ui/OLEDDisplay.cpp>
@@ -40,48 +47,64 @@ lib_deps =
${esp32_base.lib_deps}
adafruit/Adafruit GFX Library @ ^1.12.1
[env:Heltec_Vision_Master_T190_radio_ble]
extends = Heltec_Vision_Master_T190_base
[env:Heltec_T190_companion_radio_ble]
extends = Heltec_T190_base
build_flags =
${Heltec_Vision_Master_T190_base.build_flags}
${Heltec_T190_base.build_flags}
-I examples/companion_radio/ui-new
-D MAX_CONTACTS=300
-D MAX_GROUP_CHANNELS=8
-D BLE_PIN_CODE=123456 ; dynamic, random PIN
-D BLE_DEBUG_LOGGING=1
-D OFFLINE_QUEUE_SIZE=256
build_src_filter = ${Heltec_Vision_Master_T190_base.build_src_filter}
build_src_filter = ${Heltec_T190_base.build_src_filter}
+<helpers/esp32/*.cpp>
+<../examples/companion_radio/*.cpp>
+<../examples/companion_radio/ui-new/*.cpp>
lib_deps =
${Heltec_Vision_Master_T190_base.lib_deps}
${Heltec_T190_base.lib_deps}
densaugeo/base64 @ ~1.4.0
[env:Heltec_Vision_Master_T190_repeater]
extends = Heltec_Vision_Master_T190_base
[env:Heltec_T190_companion_radio_usb]
extends = Heltec_T190_base
build_flags =
${Heltec_Vision_Master_T190_base.build_flags}
${Heltec_T190_base.build_flags}
-I examples/companion_radio/ui-new
-D MAX_CONTACTS=300
-D MAX_GROUP_CHANNELS=8
-D OFFLINE_QUEUE_SIZE=256
build_src_filter = ${Heltec_T190_base.build_src_filter}
+<helpers/esp32/*.cpp>
+<../examples/companion_radio/*.cpp>
+<../examples/companion_radio/ui-new/*.cpp>
lib_deps =
${Heltec_T190_base.lib_deps}
densaugeo/base64 @ ~1.4.0
[env:Heltec_T190_repeater]
extends = Heltec_T190_base
build_flags =
${Heltec_T190_base.build_flags}
-D ADVERT_NAME='"Heltec T190 Repeater"'
-D ADVERT_LAT=0.0
-D ADVERT_LON=0.0
build_src_filter = ${Heltec_Vision_Master_T190_base.build_src_filter}
build_src_filter = ${Heltec_T190_base.build_src_filter}
+<../examples/simple_repeater>
lib_deps =
${Heltec_Vision_Master_T190_base.lib_deps}
${Heltec_T190_base.lib_deps}
${esp32_ota.lib_deps}
[env:Heltec_Vision_Master_T190_room_server]
extends = Heltec_Vision_Master_T190_base
[env:Heltec_T190_room_server]
extends = Heltec_T190_base
build_flags =
${Heltec_Vision_Master_T190_base.build_flags}
${Heltec_T190_base.build_flags}
-D ADVERT_NAME='"Heltec T190 Room"'
-D ADVERT_LAT=0.0
-D ADVERT_LON=0.0
-D ADMIN_PASSWORD='"password"'
-D ROOM_PASSWORD='"hello"'
build_src_filter = ${Heltec_Vision_Master_T190_base.build_src_filter}
build_src_filter = ${Heltec_T190_base.build_src_filter}
+<../examples/simple_room_server>
lib_deps =
${Heltec_Vision_Master_T190_base.lib_deps}
${Heltec_T190_base.lib_deps}
${esp32_ota.lib_deps}

View File

@@ -64,7 +64,7 @@ lib_deps =
extends = Heltec_lora32_v2
build_flags =
${Heltec_lora32_v2.build_flags}
-D MAX_CONTACTS=100
-D MAX_CONTACTS=170
-D MAX_GROUP_CHANNELS=1
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
@@ -80,7 +80,7 @@ build_flags =
${Heltec_lora32_v2.build_flags}
-I examples/companion_radio/ui-new
-D DISPLAY_CLASS=SSD1306Display
-D MAX_CONTACTS=100
-D MAX_CONTACTS=170
-D MAX_GROUP_CHANNELS=8
; NOTE: DO NOT ENABLE --> -D MESH_PACKET_LOGGING=1
; NOTE: DO NOT ENABLE --> -D MESH_DEBUG=1
@@ -100,7 +100,7 @@ build_flags =
${Heltec_lora32_v2.build_flags}
-I examples/companion_radio/ui-new
-D DISPLAY_CLASS=SSD1306Display
-D MAX_CONTACTS=100
-D MAX_CONTACTS=170
-D MAX_GROUP_CHANNELS=8
-D BLE_PIN_CODE=123456
-D BLE_DEBUG_LOGGING=1

View File

@@ -17,7 +17,7 @@ build_flags =
-D PIN_VEXT_EN=36
-D SX126X_DIO2_AS_RF_SWITCH=true
-D SX126X_DIO3_TCXO_VOLTAGE=1.8
-D SX126X_CURRENT_LIMIT=160
-D SX126X_CURRENT_LIMIT=140
-D SX126X_RX_BOOSTED_GAIN=1
-D PIN_GPS_RX=47
-D PIN_GPS_TX=48
@@ -87,7 +87,7 @@ extends = Heltec_lora32_v3
build_flags =
${Heltec_lora32_v3.build_flags}
-I examples/companion_radio/ui-new
-D MAX_CONTACTS=100
-D MAX_CONTACTS=300
-D MAX_GROUP_CHANNELS=8
-D DISPLAY_CLASS=SSD1306Display
; NOTE: DO NOT ENABLE --> -D MESH_PACKET_LOGGING=1
@@ -106,7 +106,7 @@ extends = Heltec_lora32_v3
build_flags =
${Heltec_lora32_v3.build_flags}
-I examples/companion_radio/ui-new
-D MAX_CONTACTS=160
-D MAX_CONTACTS=300
-D MAX_GROUP_CHANNELS=8
-D DISPLAY_CLASS=SSD1306Display
-D BLE_PIN_CODE=123456 ; dynamic, random PIN
@@ -130,7 +130,7 @@ extends = Heltec_lora32_v3
build_flags =
${Heltec_lora32_v3.build_flags}
-I examples/companion_radio/ui-new
-D MAX_CONTACTS=100
-D MAX_CONTACTS=300
-D MAX_GROUP_CHANNELS=8
-D DISPLAY_CLASS=SSD1306Display
-D WIFI_DEBUG_LOGGING=1
@@ -207,7 +207,7 @@ lib_deps =
extends = Heltec_lora32_v3
build_flags =
${Heltec_lora32_v3.build_flags}
-D MAX_CONTACTS=100
-D MAX_CONTACTS=300
-D MAX_GROUP_CHANNELS=8
-D BLE_PIN_CODE=123456
-D BLE_DEBUG_LOGGING=1

View File

@@ -106,8 +106,8 @@ build_src_filter = ${nrf52840_xiao.build_src_filter}
extends = ikoka_stick_nrf_baseboard
build_flags =
${ikoka_stick_nrf_baseboard.build_flags}
-D MAX_CONTACTS=100
-D MAX_GROUP_CHANNELS=8
-D MAX_CONTACTS=350
-D MAX_GROUP_CHANNELS=40
-D BLE_PIN_CODE=123456
-D OFFLINE_QUEUE_SIZE=256
-I examples/companion_radio/ui-new
@@ -126,8 +126,8 @@ lib_deps =
extends = ikoka_stick_nrf_baseboard
build_flags =
${ikoka_stick_nrf_baseboard.build_flags}
-D MAX_CONTACTS=100
-D MAX_GROUP_CHANNELS=8
-D MAX_CONTACTS=350
-D MAX_GROUP_CHANNELS=40
-I examples/companion_radio/ui-new
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1

View File

@@ -24,7 +24,7 @@ build_src_filter = ${esp32_base.build_src_filter}
+<../variants/lilygo_tbeam_SX1262>
+<helpers/ui/SSD1306Display.cpp>
+<helpers/esp32/TBeamBoard.cpp>
+<helpers/sensors>
+<helpers/sensors>
board_build.partitions = min_spiffs.csv ; get around 4mb flash limit
lib_deps =
${esp32_base.lib_deps}
@@ -38,7 +38,7 @@ board_build.upload.maximum_ram_size=2000000
build_flags =
${LilyGo_TBeam_SX1262.build_flags}
-I examples/companion_radio/ui-new
-D MAX_CONTACTS=100
-D MAX_CONTACTS=160
-D MAX_GROUP_CHANNELS=8
-D BLE_PIN_CODE=123456
-D OFFLINE_QUEUE_SIZE=256

View File

@@ -22,7 +22,7 @@ build_src_filter = ${esp32_base.build_src_filter}
+<../variants/lilygo_tbeam_SX1276>
+<helpers/ui/SSD1306Display.cpp>
+<helpers/esp32/TBeamBoard.cpp>
+<helpers/sensors>
+<helpers/sensors>
board_build.partitions = min_spiffs.csv ; get around 4mb flash limit
lib_deps =
${esp32_base.lib_deps}
@@ -37,7 +37,7 @@ board_build.upload.maximum_ram_size=2000000
build_flags =
${LilyGo_TBeam_SX1276.build_flags}
-I examples/companion_radio/ui-new
-D MAX_CONTACTS=100
-D MAX_CONTACTS=160
-D MAX_GROUP_CHANNELS=8
-D BLE_PIN_CODE=123456
; -D BLE_DEBUG_LOGGING=1

View File

@@ -3,19 +3,6 @@
#include <MeshCore.h>
#include <Arduino.h>
// LoRa radio module pins for LilyGo T-Echo
#define P_LORA_DIO_1 20
#define P_LORA_NSS 24
#define P_LORA_RESET 25
#define P_LORA_BUSY 17
#define P_LORA_SCLK 19
#define P_LORA_MISO 23
#define P_LORA_MOSI 22
#define SX126X_POWER_EN 37
#define SX126X_DIO2_AS_RF_SWITCH true
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
// built-ins
#define VBAT_MV_PER_LSB (0.73242188F) // 3.0V ADC range and 12-bit ADC resolution = 3000mV/4096

View File

@@ -0,0 +1,118 @@
[LilyGo_T-Echo]
extends = nrf52_base
board = t-echo
board_build.ldscript = boards/nrf52840_s140_v6.ld
build_flags = ${nrf52_base.build_flags}
-I variants/lilygo_techo
-I src/helpers/nrf52
-I lib/nrf52/s140_nrf52_6.1.1_API/include
-I lib/nrf52/s140_nrf52_6.1.1_API/include/nrf52
-D LILYGO_TECHO
-D RADIO_CLASS=CustomSX1262
-D WRAPPER_CLASS=CustomSX1262Wrapper
-D LORA_TX_POWER=22
-D P_LORA_DIO_1=20
-D P_LORA_NSS=24
-D P_LORA_RESET=25
-D P_LORA_BUSY=17
-D P_LORA_SCLK=19
-D P_LORA_MISO=23
-D P_LORA_MOSI=22
-D SX126X_POWER_EN=37
-D SX126X_DIO2_AS_RF_SWITCH=true
-D SX126X_DIO3_TCXO_VOLTAGE=1.8
-D SX126X_CURRENT_LIMIT=140
-D SX126X_RX_BOOSTED_GAIN=1
-D P_LORA_TX_LED=LED_GREEN
-D DISABLE_DIAGNOSTIC_OUTPUT
-D ENV_INCLUDE_GPS=1
-D ENV_INCLUDE_BME280=1
-D GPS_BAUD_RATE=9600
-D PIN_GPS_EN=GPS_EN
-D TELEM_BME280_ADDRESS=0x77
-D DISPLAY_CLASS=GxEPDDisplay
-D BACKLIGHT_BTN=PIN_BUTTON2
-D AUTO_OFF_MILLIS=0
build_src_filter = ${nrf52_base.build_src_filter}
+<helpers/*.cpp>
+<TechoBoard.cpp>
+<helpers/sensors/EnvironmentSensorManager.cpp>
+<helpers/ui/GxEPDDisplay.cpp>
+<helpers/ui/MomentaryButton.cpp>
+<../variants/lilygo_techo>
lib_deps =
${nrf52_base.lib_deps}
stevemarple/MicroNMEA @ ^2.0.6
adafruit/Adafruit BME280 Library @ ^2.3.0
zinggjm/GxEPD2 @ 1.6.2
bakercp/CRC32 @ ^2.0.0
debug_tool = jlink
upload_protocol = nrfutil
[env:LilyGo_T-Echo_repeater]
extends = LilyGo_T-Echo
build_src_filter = ${LilyGo_T-Echo.build_src_filter}
+<../examples/simple_repeater>
build_flags =
${LilyGo_T-Echo.build_flags}
-D ADVERT_NAME='"T-Echo Repeater"'
-D ADVERT_LAT=0.0
-D ADVERT_LON=0.0
-D ADMIN_PASSWORD='"password"'
-D MAX_NEIGHBOURS=8
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
[env:LilyGo_T-Echo_room_server]
extends = LilyGo_T-Echo
build_src_filter = ${LilyGo_T-Echo.build_src_filter}
+<../examples/simple_room_server>
build_flags =
${LilyGo_T-Echo.build_flags}
-D ADVERT_NAME='"T-Echo Room"'
-D ADVERT_LAT=0.0
-D ADVERT_LON=0.0
-D ADMIN_PASSWORD='"password"'
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
[env:LilyGo_T-Echo_companion_radio_ble]
extends = LilyGo_T-Echo
build_flags =
${LilyGo_T-Echo.build_flags}
-I src/helpers/ui
-I examples/companion_radio/ui-new
-D MAX_CONTACTS=350
-D MAX_GROUP_CHANNELS=40
-D QSPIFLASH=1
-D BLE_PIN_CODE=123456
; -D BLE_DEBUG_LOGGING=1
-D OFFLINE_QUEUE_SIZE=256
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
-D AUTO_SHUTDOWN_MILLIVOLTS=3300
build_src_filter = ${LilyGo_T-Echo.build_src_filter}
+<helpers/nrf52/SerialBLEInterface.cpp>
+<../examples/companion_radio/*.cpp>
+<../examples/companion_radio/ui-new/*.cpp>
lib_deps =
${LilyGo_T-Echo.lib_deps}
densaugeo/base64 @ ~1.4.0
[env:LilyGo_T-Echo_companion_radio_usb]
extends = LilyGo_T-Echo
build_flags =
${LilyGo_T-Echo.build_flags}
-I src/helpers/ui
-I examples/companion_radio/ui-new
-D MAX_CONTACTS=100
-D MAX_GROUP_CHANNELS=8
-D OFFLINE_QUEUE_SIZE=256
-D UI_RECENT_LIST_SIZE=9
-D AUTO_SHUTDOWN_MILLIVOLTS=3300
build_src_filter = ${LilyGo_T-Echo.build_src_filter}
+<../examples/companion_radio/*.cpp>
+<../examples/companion_radio/ui-new/*.cpp>
lib_deps =
${LilyGo_T-Echo.lib_deps}
densaugeo/base64 @ ~1.4.0

View File

@@ -0,0 +1,53 @@
#include <Arduino.h>
#include "target.h"
#include <helpers/ArduinoHelpers.h>
#include <helpers/sensors/MicroNMEALocationProvider.h>
TechoBoard board;
RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, SPI);
WRAPPER_CLASS radio_driver(radio, board);
VolatileRTCClock fallback_clock;
AutoDiscoverRTCClock rtc_clock(fallback_clock);
#ifdef ENV_INCLUDE_GPS
MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Serial1, &rtc_clock);
EnvironmentSensorManager sensors = EnvironmentSensorManager(nmea);
#else
EnvironmentSensorManager sensors = EnvironmentSensorManager();
#endif
#ifdef DISPLAY_CLASS
DISPLAY_CLASS display;
MomentaryButton user_btn(PIN_USER_BTN, 1000, true);
#endif
bool radio_init() {
rtc_clock.begin(Wire);
return radio.std_init(&SPI);
}
uint32_t radio_get_rng_seed() {
return radio.random(0x7FFFFFFF);
}
void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr) {
radio.setFrequency(freq);
radio.setSpreadingFactor(sf);
radio.setBandwidth(bw);
radio.setCodingRate(cr);
}
void radio_set_tx_power(uint8_t dbm) {
radio.setOutputPower(dbm);
}
mesh::LocalIdentity radio_new_identity() {
RadioNoiseListener rng(radio);
return mesh::LocalIdentity(&rng); // create new random identity
}

View File

@@ -3,37 +3,21 @@
#define RADIOLIB_STATIC_ONLY 1
#include <RadioLib.h>
#include <helpers/radiolib/RadioLibWrappers.h>
#include <helpers/nrf52/TechoBoard.h>
#include <TechoBoard.h>
#include <helpers/radiolib/CustomSX1262Wrapper.h>
#include <helpers/AutoDiscoverRTCClock.h>
#include <helpers/SensorManager.h>
#include <helpers/sensors/EnvironmentSensorManager.h>
#include <helpers/sensors/LocationProvider.h>
#ifdef DISPLAY_CLASS
#include <helpers/ui/GxEPDDisplay.h>
#include <helpers/ui/MomentaryButton.h>
#endif
class TechoSensorManager : public SensorManager {
bool gps_active = false;
LocationProvider* _location;
void start_gps();
void stop_gps();
public:
TechoSensorManager(LocationProvider &location): _location(&location) { }
bool begin() override;
bool querySensors(uint8_t requester_permissions, CayenneLPP& telemetry) override;
void loop() override;
int getNumSettings() const override;
const char* getSettingName(int i) const override;
const char* getSettingValue(int i) const override;
bool setSettingValue(const char* name, const char* value) override;
};
extern TechoBoard board;
extern WRAPPER_CLASS radio_driver;
extern AutoDiscoverRTCClock rtc_clock;
extern TechoSensorManager sensors;
extern EnvironmentSensorManager sensors;
#ifdef DISPLAY_CLASS
extern DISPLAY_CLASS display;

View File

@@ -16,49 +16,15 @@ ESP32RTCClock fallback_clock;
AutoDiscoverRTCClock rtc_clock(fallback_clock);
SensorManager sensors;
#ifndef LORA_CR
#define LORA_CR 5
#endif
bool radio_init() {
fallback_clock.begin();
rtc_clock.begin(Wire);
#ifdef SX126X_DIO3_TCXO_VOLTAGE
float tcxo = SX126X_DIO3_TCXO_VOLTAGE;
#else
float tcxo = 1.6f;
#endif
#if defined(P_LORA_SCLK)
spi.begin(P_LORA_SCLK, P_LORA_MISO, P_LORA_MOSI);
return radio.std_init(&spi);
#else
return radio.std_init();
#endif
int status = radio.begin(LORA_FREQ, LORA_BW, LORA_SF, LORA_CR, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, LORA_TX_POWER, 8, tcxo);
if (status != RADIOLIB_ERR_NONE) {
Serial.print("ERROR: radio init failed: ");
Serial.println(status);
return false; // fail
}
radio.setCRC(1);
#if defined(SX126X_RXEN) && defined(SX126X_TXEN)
radio.setRfSwitchPins(SX126X_RXEN, SX126X_TXEN);
#endif
#ifdef SX126X_CURRENT_LIMIT
radio.setCurrentLimit(SX126X_CURRENT_LIMIT);
#endif
#ifdef SX126X_DIO2_AS_RF_SWITCH
radio.setDio2AsRfSwitch(SX126X_DIO2_AS_RF_SWITCH);
#endif
#ifdef SX126X_RX_BOOSTED_GAIN
radio.setRxBoostedGainMode(SX126X_RX_BOOSTED_GAIN);
#endif
return true; // success
}
uint32_t radio_get_rng_seed() {

View File

@@ -68,7 +68,7 @@ lib_deps =
extends = LilyGo_TLora_V2_1_1_6
build_flags =
${LilyGo_TLora_V2_1_1_6.build_flags}
-D MAX_CONTACTS=100
-D MAX_CONTACTS=160
-D MAX_GROUP_CHANNELS=8
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
@@ -84,7 +84,7 @@ extends = LilyGo_TLora_V2_1_1_6
build_flags =
${LilyGo_TLora_V2_1_1_6.build_flags}
-I examples/companion_radio/ui-new
-D MAX_CONTACTS=100
-D MAX_CONTACTS=160
-D MAX_GROUP_CHANNELS=8
; NOTE: DO NOT ENABLE --> -D MESH_PACKET_LOGGING=1
; NOTE: DO NOT ENABLE --> -D MESH_DEBUG=1
@@ -102,7 +102,7 @@ extends = LilyGo_TLora_V2_1_1_6
build_flags =
${LilyGo_TLora_V2_1_1_6.build_flags}
-I examples/companion_radio/ui-new
-D MAX_CONTACTS=100
-D MAX_CONTACTS=160
-D MAX_GROUP_CHANNELS=8
-D BLE_PIN_CODE=123456
-D OFFLINE_QUEUE_SIZE=256
@@ -136,3 +136,23 @@ build_flags =
lib_deps =
${LilyGo_TLora_V2_1_1_6.lib_deps}
${esp32_ota.lib_deps}
[env:LilyGo_TLora_V2_1_1_6_companion_radio_wifi]
extends = LilyGo_TLora_V2_1_1_6
build_flags =
${LilyGo_TLora_V2_1_1_6.build_flags}
-I examples/companion_radio/ui-new
-D MAX_CONTACTS=160
-D MAX_GROUP_CHANNELS=8
-D WIFI_SSID='"ssid"'
-D WIFI_PWD='"password"'
-D WIFI_DEBUG_LOGGING=1
build_src_filter = ${LilyGo_TLora_V2_1_1_6.build_src_filter}
+<helpers/esp32/*.cpp>
+<helpers/ui/SSD1306Display.cpp>
+<helpers/ui/MomentaryButton.cpp>
+<../examples/companion_radio/*.cpp>
+<../examples/companion_radio/ui-new/*.cpp>
lib_deps =
${LilyGo_TLora_V2_1_1_6.lib_deps}
densaugeo/base64 @ ~1.4.0

View File

@@ -0,0 +1,72 @@
#include <Arduino.h>
#include "MeshPocket.h"
#include <bluefruit.h>
#include <Wire.h>
static BLEDfu bledfu;
static void connect_callback(uint16_t conn_handle)
{
(void)conn_handle;
MESH_DEBUG_PRINTLN("BLE client connected");
}
static void disconnect_callback(uint16_t conn_handle, uint8_t reason)
{
(void)conn_handle;
(void)reason;
MESH_DEBUG_PRINTLN("BLE client disconnected");
}
void HeltecMeshPocket::begin() {
// for future use, sub-classes SHOULD call this from their begin()
startup_reason = BD_STARTUP_NORMAL;
Serial.begin(115200);
pinMode(PIN_VBAT_READ, INPUT);
pinMode(PIN_USER_BTN, INPUT);
}
bool HeltecMeshPocket::startOTAUpdate(const char* id, char reply[]) {
// Config the peripheral connection with maximum bandwidth
// more SRAM required by SoftDevice
// Note: All config***() function must be called before begin()
Bluefruit.configPrphBandwidth(BANDWIDTH_MAX);
Bluefruit.configPrphConn(92, BLE_GAP_EVENT_LENGTH_MIN, 16, 16);
Bluefruit.begin(1, 0);
// Set max power. Accepted values are: -40, -30, -20, -16, -12, -8, -4, 0, 4
Bluefruit.setTxPower(4);
// Set the BLE device name
Bluefruit.setName("MESH_POCKET_OTA");
Bluefruit.Periph.setConnectCallback(connect_callback);
Bluefruit.Periph.setDisconnectCallback(disconnect_callback);
// To be consistent OTA DFU should be added first if it exists
bledfu.begin();
// Set up and start advertising
// Advertising packet
Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE);
Bluefruit.Advertising.addTxPower();
Bluefruit.Advertising.addName();
/* Start Advertising
- Enable auto advertising if disconnected
- Interval: fast mode = 20 ms, slow mode = 152.5 ms
- Timeout for fast mode is 30 seconds
- Start(timeout) with timeout = 0 will advertise forever (until connected)
For recommended advertising interval
https://developer.apple.com/library/content/qa/qa1931/_index.html
*/
Bluefruit.Advertising.restartOnDisconnect(true);
Bluefruit.Advertising.setInterval(32, 244); // in unit of 0.625 ms
Bluefruit.Advertising.setFastTimeout(30); // number of seconds in fast mode
Bluefruit.Advertising.start(0); // 0 = Don't stop advertising after n seconds
strcpy(reply, "OK - started");
return true;
}

View File

@@ -0,0 +1,45 @@
#pragma once
#include <Arduino.h>
#include <MeshCore.h>
// built-ins
#define PIN_VBAT_READ 29
#define PIN_BAT_CTL 34
#define MV_LSB (3000.0F / 4096.0F) // 12-bit ADC with 3.0V input range
class HeltecMeshPocket : public mesh::MainBoard {
protected:
uint8_t startup_reason;
public:
void begin();
uint8_t getStartupReason() const override { return startup_reason; }
uint16_t getBattMilliVolts() override {
int adcvalue = 0;
analogReadResolution(12);
analogReference(AR_INTERNAL_3_0);
pinMode(PIN_BAT_CTL, OUTPUT); // battery adc can be read only ctrl pin set to high
pinMode(PIN_VBAT_READ, INPUT);
digitalWrite(PIN_BAT_CTL, HIGH);
delay(10);
adcvalue = analogRead(PIN_VBAT_READ);
digitalWrite(PIN_BAT_CTL, LOW);
return (uint16_t)((float)adcvalue * MV_LSB * 4.9);
}
const char* getManufacturerName() const override {
return "Heltec MeshPocket";
}
void reboot() override {
NVIC_SystemReset();
}
bool startOTAUpdate(const char* id, char reply[]) override;
};

View File

@@ -1,53 +1,49 @@
[nrf52840_t114]
[Mesh_pocket]
extends = nrf52_base
board = heltec_mesh_pocket
platform_packages = framework-arduinoadafruitnrf52
build_flags = ${nrf52_base.build_flags}
board_build.ldscript = boards/nrf52840_s140_v6.ld
build_flags = ${nrf52_base.build_flags}
-I src/helpers/nrf52
-I lib/nrf52/s140_nrf52_6.1.1_API/include
-I lib/nrf52/s140_nrf52_6.1.1_API/include/nrf52
lib_deps =
${nrf52_base.lib_deps}
rweather/Crypto @ ^0.4.0
[Heltec_t114]
extends = nrf52840_t114
board = heltec_t114
board_build.ldscript = boards/nrf52840_s140_v6.ld
build_flags = ${nrf52840_t114.build_flags}
-I variants/t114
-I src/helpers/ui
-DHELTEC_T114
-D P_LORA_TX_LED=35
-I variants/mesh_pocket
-D HELTEC_MESH_POCKET
-D RADIO_CLASS=CustomSX1262
-D WRAPPER_CLASS=CustomSX1262Wrapper
-D LORA_TX_POWER=22
-D SX126X_CURRENT_LIMIT=140
-D SX126X_RX_BOOSTED_GAIN=1
-D ST7789
-D DISPLAY_CLASS=ST7789Display
build_src_filter = ${nrf52840_t114.build_src_filter}
-D EINK_DISPLAY_MODEL=GxEPD2_213_B74
-D EINK_SCALE_X=1.953125f
-D EINK_SCALE_Y=1.28f
-D EINK_X_OFFSET=0
-D EINK_Y_OFFSET=10
-D DISPLAY_CLASS=GxEPDDisplay
-D DISABLE_DIAGNOSTIC_OUTPUT
build_src_filter = ${nrf52_base.build_src_filter}
+<helpers/*.cpp>
+<helpers/nrf52/T114Board.cpp>
+<../variants/t114>
+<helpers/ui/ST7789Display.cpp>
+<helpers/ui/MomentaryButton.cpp>
+<helpers/ui/OLEDDisplay.cpp>
+<helpers/ui/OLEDDisplayFonts.cpp>
+<../variants/mesh_pocket>
+<helpers/ui/GxEPDDisplay.cpp>
lib_deps =
${nrf52840_t114.lib_deps}
${nrf52_base.lib_deps}
adafruit/Adafruit EPD @ 4.6.1
rweather/Crypto @ ^0.4.0
stevemarple/MicroNMEA @ ^2.0.6
adafruit/Adafruit GFX Library @ ^1.12.1
zinggjm/GxEPD2 @ 1.6.2
bakercp/CRC32 @ ^2.0.0
debug_tool = jlink
upload_protocol = nrfutil
[env:Heltec_t114_repeater]
extends = Heltec_t114
build_src_filter = ${Heltec_t114.build_src_filter}
[env:Mesh_pocket_repeater]
extends = Mesh_pocket
build_src_filter = ${Mesh_pocket.build_src_filter}
+<../examples/simple_repeater>
build_flags =
${Heltec_t114.build_flags}
-D ADVERT_NAME='"Heltec_T114 Repeater"'
${Mesh_pocket.build_flags}
-D ADVERT_NAME='"Heltec_Mesh_Pocket Repeater"'
-D ADVERT_LAT=0.0
-D ADVERT_LON=0.0
-D ADMIN_PASSWORD='"password"'
@@ -55,13 +51,13 @@ build_flags =
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
[env:Heltec_t114_room_server]
extends = Heltec_t114
build_src_filter = ${Heltec_t114.build_src_filter}
[env:Mesh_pocket_room_server]
extends = Mesh_pocket
build_src_filter = ${Mesh_pocket.build_src_filter}
+<../examples/simple_room_server>
build_flags =
${Heltec_t114.build_flags}
-D ADVERT_NAME='"Heltec_T114 Room"'
${Mesh_pocket.build_flags}
-D ADVERT_NAME='"Heltec_Mesh_Pocket Room"'
-D ADVERT_LAT=0.0
-D ADVERT_LON=0.0
-D ADMIN_PASSWORD='"password"'
@@ -69,41 +65,44 @@ build_flags =
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
[env:Heltec_t114_companion_radio_ble]
extends = Heltec_t114
[env:Mesh_pocket_companion_radio_ble]
extends = Mesh_pocket
build_flags =
${Heltec_t114.build_flags}
${Mesh_pocket.build_flags}
-I examples/companion_radio/ui-new
-D MAX_CONTACTS=100
-D MAX_GROUP_CHANNELS=8
-D BLE_PIN_CODE=123456
; -D BLE_DEBUG_LOGGING=1
-D OFFLINE_QUEUE_SIZE=256
-D AUTO_OFF_MILLIS=0
; -D BLE_DEBUG_LOGGING=1
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
build_src_filter = ${Heltec_t114.build_src_filter}
build_src_filter = ${Mesh_pocket.build_src_filter}
+<helpers/nrf52/SerialBLEInterface.cpp>
+<../examples/companion_radio/*.cpp>
+<../examples/companion_radio/ui-new/*.cpp>
lib_deps =
${Heltec_t114.lib_deps}
${Mesh_pocket.lib_deps}
densaugeo/base64 @ ~1.4.0
[env:Heltec_t114_companion_radio_usb]
extends = Heltec_t114
[env:Mesh_pocket_companion_radio_usb]
extends = Mesh_pocket
build_flags =
${Heltec_t114.build_flags}
${Mesh_pocket.build_flags}
-I examples/companion_radio/ui-new
-D MAX_CONTACTS=100
-D MAX_GROUP_CHANNELS=8
-D AUTO_OFF_MILLIS=0
; -D BLE_PIN_CODE=123456
; -D BLE_DEBUG_LOGGING=1
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
build_src_filter = ${Heltec_t114.build_src_filter}
build_src_filter = ${Mesh_pocket.build_src_filter}
+<helpers/nrf52/*.cpp>
+<../examples/companion_radio/*.cpp>
+<../examples/companion_radio/ui-new/*.cpp>
lib_deps =
${Heltec_t114.lib_deps}
${Mesh_pocket.lib_deps}
densaugeo/base64 @ ~1.4.0

View File

@@ -0,0 +1,44 @@
#include <Arduino.h>
#include "target.h"
#include <helpers/ArduinoHelpers.h>
#include <helpers/sensors/MicroNMEALocationProvider.h>
HeltecMeshPocket board;
RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, SPI);
WRAPPER_CLASS radio_driver(radio, board);
SensorManager sensors = SensorManager();
VolatileRTCClock fallback_clock;
AutoDiscoverRTCClock rtc_clock(fallback_clock);
#ifdef DISPLAY_CLASS
DISPLAY_CLASS display;
MomentaryButton user_btn(PIN_USER_BTN, 1000, true);
#endif
bool radio_init() {
return radio.std_init(&SPI);
}
uint32_t radio_get_rng_seed() {
return radio.random(0x7FFFFFFF);
}
void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr) {
radio.setFrequency(freq);
radio.setSpreadingFactor(sf);
radio.setBandwidth(bw);
radio.setCodingRate(cr);
}
void radio_set_tx_power(uint8_t dbm) {
radio.setOutputPower(dbm);
}
mesh::LocalIdentity radio_new_identity() {
RadioNoiseListener rng(radio);
return mesh::LocalIdentity(&rng); // create new random identity
}

View File

@@ -0,0 +1,33 @@
#pragma once
#define RADIOLIB_STATIC_ONLY 1
#include <RadioLib.h>
#include <helpers/radiolib/RadioLibWrappers.h>
#include <helpers/radiolib/CustomSX1262Wrapper.h>
#include <helpers/AutoDiscoverRTCClock.h>
#include <helpers/SensorManager.h>
#include <helpers/sensors/LocationProvider.h>
#include "MeshPocket.h"
#ifdef DISPLAY_CLASS
#include <helpers/ui/GxEPDDisplay.h>
#include <helpers/ui/MomentaryButton.h>
#endif
extern HeltecMeshPocket board;
extern WRAPPER_CLASS radio_driver;
extern AutoDiscoverRTCClock rtc_clock;
#ifdef DISPLAY_CLASS
extern DISPLAY_CLASS display;
extern MomentaryButton user_btn;
#endif
bool radio_init();
uint32_t radio_get_rng_seed();
void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr);
void radio_set_tx_power(uint8_t dbm);
mesh::LocalIdentity radio_new_identity();
extern SensorManager sensors;

View File

@@ -0,0 +1,15 @@
#include "variant.h"
#include "nrf.h"
#include "wiring_constants.h"
#include "wiring_digital.h"
const int MISO = PIN_SPI1_MISO;
const int MOSI = PIN_SPI1_MOSI;
const int SCK = PIN_SPI1_SCK;
const uint32_t g_ADigitalPinMap[] = {
// P0 - pins 0 and 1 are hardwired for xtal and should never be enabled
0xff, 0xff, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
// P1
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47};

View File

@@ -0,0 +1,124 @@
/*
* variant.h
* MIT License
*/
#pragma once
#include "WVariant.h"
////////////////////////////////////////////////////////////////////////////////
// Low frequency clock source
#define USE_LFXO // 32.768 kHz crystal oscillator
#define VARIANT_MCK (64000000ul)
////////////////////////////////////////////////////////////////////////////////
// Power
#define BATTERY_PIN (0 + 29)
#define PIN_BAT_CTRL (32 + 2)
#define ADC_MULTIPLIER (4.90F)
#define ADC_RESOLUTION (14)
#define BATTERY_SENSE_RES (12)
#define AREF_VOLTAGE (3.0)
////////////////////////////////////////////////////////////////////////////////
// Number of pins
#define PINS_COUNT (48)
#define NUM_DIGITAL_PINS (48)
#define NUM_ANALOG_INPUTS (1)
#define NUM_ANALOG_OUTPUTS (0)
////////////////////////////////////////////////////////////////////////////////
// UART pin definition
#define PIN_SERIAL1_RX (37)
#define PIN_SERIAL1_TX (39)
#define PIN_SERIAL2_RX (7)
#define PIN_SERIAL2_TX (8)
////////////////////////////////////////////////////////////////////////////////
// I2C pin definition
#define WIRE_INTERFACES_COUNT (1)
#define PIN_WIRE_SDA (32+15)
#define PIN_WIRE_SCL (32+13)
////////////////////////////////////////////////////////////////////////////////
// Builtin LEDs
#define LED_BUILTIN (13)
#define PIN_LED LED_BUILTIN
#define LED_RED LED_BUILTIN
#define LED_BLUE (-1) // No blue led, prevents Bluefruit flashing the green LED during advertising
#define PIN_STATUS_LED LED_BUILTIN
#define LED_STATE_ON LOW
////////////////////////////////////////////////////////////////////////////////
// Builtin buttons
#define PIN_BUTTON1 (32 + 10)
#define BUTTON_PIN PIN_BUTTON1
// #define PIN_BUTTON2 (0 + 18)
// #define BUTTON_PIN2 PIN_BUTTON2
#define PIN_USER_BTN BUTTON_PIN
////////////////////////////////////////////////////////////////////////////////
// SPI pin definition
#define SPI_INTERFACES_COUNT (2)
// Lora
#define USE_SX1262
#define SX126X_CS (0 + 26)
#define SX126X_DIO1 (0 + 16)
#define SX126X_BUSY (0 + 15)
#define SX126X_RESET (0 + 12)
#define SX126X_DIO2_AS_RF_SWITCH true
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
#define PIN_SPI_MISO (32 + 9)
#define PIN_SPI_MOSI (0 + 5)
#define PIN_SPI_SCK (0 + 4)
#define LORA_CS SX126X_CS
#define P_LORA_DIO_1 SX126X_DIO1
#define P_LORA_NSS SX126X_CS
#define P_LORA_RESET SX126X_RESET
#define P_LORA_BUSY SX126X_BUSY
#define P_LORA_SCLK PIN_SPI_SCK
#define P_LORA_MISO PIN_SPI_MISO
#define P_LORA_MOSI PIN_SPI_MOSI
////////////////////////////////////////////////////////////////////////////////
// EInk
#define PIN_DISPLAY_CS (24)
#define PIN_DISPLAY_BUSY (32 + 6)
#define PIN_DISPLAY_DC (31)
#define PIN_DISPLAY_RST (32 + 4)
#define PIN_SPI1_MISO (-1)
#define PIN_SPI1_MOSI (20)
#define PIN_SPI1_SCK (22)
// GxEPD2 needs that for a panel that is not even used !
extern const int MISO;
extern const int MOSI;
extern const int SCK;
#undef HAS_GPS
#define HAS_GPS 0
#define HAS_RTC 0

View File

@@ -80,6 +80,8 @@ extends = Meshadventurer
build_src_filter = ${Meshadventurer.build_src_filter}
+<../examples/companion_radio/*.cpp>
+<helpers/ui/SSD1306Display.cpp>
+<../examples/companion_radio/*.cpp>
+<../examples/companion_radio/ui-new/*.cpp>
build_flags =
${Meshadventurer.build_flags}
-I examples/companion_radio/ui-new

View File

@@ -52,8 +52,8 @@ lib_deps = ${nrf52840_me25ls01.lib_deps}
extends = me25ls01
build_flags = ${me25ls01.build_flags}
-I examples/companion_radio/ui-orig
-D MAX_CONTACTS=100
-D MAX_GROUP_CHANNELS=8
-D MAX_CONTACTS=350
-D MAX_GROUP_CHANNELS=40
-D BLE_PIN_CODE=123456
; -D BLE_DEBUG_LOGGING=1
-D MESH_PACKET_LOGGING=1
@@ -149,8 +149,8 @@ lib_deps = ${me25ls01.lib_deps}
extends = me25ls01
build_flags = ${me25ls01.build_flags}
-I examples/companion_radio/ui-orig
-D MAX_CONTACTS=100
-D MAX_GROUP_CHANNELS=8
-D MAX_CONTACTS=350
-D MAX_GROUP_CHANNELS=40
;-D BLE_PIN_CODE=123456
; -D BLE_DEBUG_LOGGING=1
-D MESH_PACKET_LOGGING=1

View File

@@ -35,13 +35,14 @@ build_flags =
${Nano_G2_Ultra.build_flags}
-I src/helpers/ui
-I examples/companion_radio/ui-new
-D MAX_CONTACTS=100
-D MAX_GROUP_CHANNELS=8
-D MAX_CONTACTS=350
-D MAX_GROUP_CHANNELS=40
-D BLE_PIN_CODE=123456
; -D BLE_DEBUG_LOGGING=0
-D OFFLINE_QUEUE_SIZE=256
-D DISPLAY_CLASS=SH1106Display
-D PIN_BUZZER=4
-D QSPIFLASH=1
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
build_src_filter = ${Nano_G2_Ultra.build_src_filter}
@@ -65,8 +66,8 @@ build_flags =
${Nano_G2_Ultra.build_flags}
-I src/helpers/ui
-I examples/companion_radio/ui-new
-D MAX_CONTACTS=100
-D MAX_GROUP_CHANNELS=8
-D MAX_CONTACTS=350
-D MAX_GROUP_CHANNELS=40
-D OFFLINE_QUEUE_SIZE=256
-D DISPLAY_CLASS=SH1106Display
-D PIN_BUZZER=4

View File

@@ -60,6 +60,10 @@ public:
void reboot() override {
NVIC_SystemReset();
}
void powerOff() override {
sd_power_system_off();
}
bool startOTAUpdate(const char* id, char reply[]) override;
};

View File

@@ -88,8 +88,8 @@ lib_deps = ${Faketec.lib_deps}
extends = Faketec
build_flags = ${Faketec.build_flags}
-I examples/companion_radio/ui-new
-D MAX_CONTACTS=100
-D MAX_GROUP_CHANNELS=8
-D MAX_CONTACTS=350
-D MAX_GROUP_CHANNELS=40
-D DISPLAY_CLASS=SSD1306Display
; NOTE: DO NOT ENABLE --> -D MESH_PACKET_LOGGING=1
; NOTE: DO NOT ENABLE --> -D MESH_DEBUG=1
@@ -106,8 +106,8 @@ lib_deps = ${Faketec.lib_deps}
extends = Faketec
build_flags = ${Faketec.build_flags}
-I examples/companion_radio/ui-new
-D MAX_CONTACTS=100
-D MAX_GROUP_CHANNELS=8
-D MAX_CONTACTS=350
-D MAX_GROUP_CHANNELS=40
-D BLE_PIN_CODE=123456
-D BLE_DEBUG_LOGGING=1
-D OFFLINE_QUEUE_SIZE=256

View File

@@ -70,8 +70,8 @@ build_flags =
-D PIN_USER_BTN=9
-D PIN_USER_BTN_ANA=31
-D DISPLAY_CLASS=SSD1306Display
-D MAX_CONTACTS=100
-D MAX_GROUP_CHANNELS=8
-D MAX_CONTACTS=350
-D MAX_GROUP_CHANNELS=40
; NOTE: DO NOT ENABLE --> -D MESH_PACKET_LOGGING=1
; NOTE: DO NOT ENABLE --> -D MESH_DEBUG=1
build_src_filter = ${rak4631.build_src_filter}
@@ -89,8 +89,8 @@ build_flags =
-D PIN_USER_BTN=9
-D PIN_USER_BTN_ANA=31
-D DISPLAY_CLASS=SSD1306Display
-D MAX_CONTACTS=100
-D MAX_GROUP_CHANNELS=8
-D MAX_CONTACTS=350
-D MAX_GROUP_CHANNELS=40
-D BLE_PIN_CODE=123456
-D BLE_DEBUG_LOGGING=1
-D OFFLINE_QUEUE_SIZE=256

View File

@@ -10,7 +10,11 @@ RAK4631Board board;
#ifdef DISPLAY_CLASS
DISPLAY_CLASS display;
MomentaryButton user_btn(PIN_USER_BTN, 1000, true);
MomentaryButton user_btn(PIN_USER_BTN, 1000, true, true);
#if defined(PIN_USER_BTN_ANA)
MomentaryButton analog_btn(PIN_USER_BTN_ANA, 1000, 20);
#endif
#endif
RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, SPI);

View File

@@ -13,6 +13,9 @@
extern DISPLAY_CLASS display;
#include <helpers/ui/MomentaryButton.h>
extern MomentaryButton user_btn;
#if defined(PIN_USER_BTN_ANA)
extern MomentaryButton analog_btn;
#endif
#endif
extern RAK4631Board board;

View File

@@ -3,19 +3,6 @@
#include <MeshCore.h>
#include <Arduino.h>
// LoRa radio module pins for PicoW
#define P_LORA_DIO_1 20
#define P_LORA_NSS 3
#define P_LORA_RESET 15
#define P_LORA_BUSY 2
#define P_LORA_SCLK 10
#define P_LORA_MISO 12
#define P_LORA_MOSI 11
//#define SX126X_POWER_EN ??? // Not Sure
#define SX126X_DIO2_AS_RF_SWITCH true
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
// built-ins
#define PIN_VBAT_READ 26
#define ADC_MULTIPLIER (3.1 * 3.3 * 1000) // MT Uses 3.1

View File

@@ -1,26 +1,35 @@
[picow]
[rpi_picow]
extends = rp2040_base
platform = https://github.com/maxgerhardt/platform-raspberrypi.git
board = rpipicow
board_build.core = earlephilhower
board_build.filesystem_size = 0.5m
build_flags = ${rp2040_base.build_flags}
-I variants/picow
-I variants/rpi_picow
; -D PICOW
; -D HW_SPI1_DEVICE
-D P_LORA_DIO_1=20
-D P_LORA_NSS=3
-D P_LORA_RESET=15
-D P_LORA_BUSY=2
-D P_LORA_SCLK=10
-D P_LORA_MISO=12
-D P_LORA_MOSI=11
-D SX126X_DIO2_AS_RF_SWITCH=true
-D SX126X_DIO3_TCXO_VOLTAGE=1.8
-D SX126X_CURRENT_LIMIT=130
-D SX126X_RX_BOOSTED_GAIN=1
-D LORA_TX_POWER=22
-D RADIO_CLASS=CustomSX1262
-D WRAPPER_CLASS=CustomSX1262Wrapper
-D LORA_TX_POWER=22
-D SX126X_RX_BOOSTED_GAIN=1
build_src_filter = ${rp2040_base.build_src_filter}
+<helpers/rp2040/PicoWBoard.cpp>
+<../variants/picow>
+<PicoWBoard.cpp>
+<../variants/rpi_picow>
lib_deps = ${rp2040_base.lib_deps}
[env:PicoW_Repeater]
extends = picow
build_flags = ${picow.build_flags}
extends = rpi_picow
build_flags = ${rpi_picow.build_flags}
-D ADVERT_NAME='"PicoW Repeater"'
-D ADVERT_LAT=0.0
-D ADVERT_LON=0.0
@@ -28,12 +37,12 @@ build_flags = ${picow.build_flags}
-D MAX_NEIGHBOURS=8
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
build_src_filter = ${picow.build_src_filter}
build_src_filter = ${rpi_picow.build_src_filter}
+<../examples/simple_repeater>
[env:PicoW_room_server]
extends = picow
build_flags = ${picow.build_flags}
extends = rpi_picow
build_flags = ${rpi_picow.build_flags}
-D ADVERT_NAME='"Test Room"'
-D ADVERT_LAT=0.0
-D ADVERT_LON=0.0
@@ -41,38 +50,38 @@ build_flags = ${picow.build_flags}
-D ROOM_PASSWORD='"hello"'
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
build_src_filter = ${picow.build_src_filter}
build_src_filter = ${rpi_picow.build_src_filter}
+<../examples/simple_room_server>
[env:PicoW_companion_radio_usb]
extends = picow
build_flags = ${picow.build_flags}
extends = rpi_picow
build_flags = ${rpi_picow.build_flags}
-D MAX_CONTACTS=100
-D MAX_GROUP_CHANNELS=8
; NOTE: DO NOT ENABLE --> -D MESH_PACKET_LOGGING=1
; NOTE: DO NOT ENABLE --> -D MESH_DEBUG=1
build_src_filter = ${picow.build_src_filter}
build_src_filter = ${rpi_picow.build_src_filter}
+<../examples/companion_radio/*.cpp>
lib_deps = ${picow.lib_deps}
lib_deps = ${rpi_picow.lib_deps}
densaugeo/base64 @ ~1.4.0
; [env:PicoW_companion_radio_ble]
; extends = picow
; build_flags = ${picow.build_flags}
; extends = rpi_picow
; build_flags = ${rpi_picow.build_flags}
; -D MAX_CONTACTS=100
; -D MAX_GROUP_CHANNELS=8
; -D BLE_PIN_CODE=123456
; -D BLE_DEBUG_LOGGING=1
; ; -D MESH_PACKET_LOGGING=1
; ; -D MESH_DEBUG=1
; build_src_filter = ${picow.build_src_filter}
; build_src_filter = ${rpi_picow.build_src_filter}
; +<../examples/companion_radio/*.cpp>
; lib_deps = ${picow.lib_deps}
; lib_deps = ${rpi_picow.lib_deps}
; densaugeo/base64 @ ~1.4.0
; [env:PicoW_companion_radio_wifi]
; extends = picow
; build_flags = ${picow.build_flags}
; extends = rpi_picow
; build_flags = ${rpi_picow.build_flags}
; -D MAX_CONTACTS=100
; -D MAX_GROUP_CHANNELS=8
; -D WIFI_DEBUG_LOGGING=1
@@ -80,19 +89,19 @@ lib_deps = ${picow.lib_deps}
; -D WIFI_PWD='"mypwd"'
; ; -D MESH_PACKET_LOGGING=1
; ; -D MESH_DEBUG=1
; build_src_filter = ${picow.build_src_filter}
; build_src_filter = ${rpi_picow.build_src_filter}
; +<../examples/companion_radio/*.cpp>
; lib_deps = ${picow.lib_deps}
; lib_deps = ${rpi_picow.lib_deps}
; densaugeo/base64 @ ~1.4.0
[env:PicoW_terminal_chat]
extends = picow
build_flags = ${picow.build_flags}
extends = rpi_picow
build_flags = ${rpi_picow.build_flags}
-D MAX_CONTACTS=100
-D MAX_GROUP_CHANNELS=1
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
build_src_filter = ${picow.build_src_filter}
build_src_filter = ${rpi_picow.build_src_filter}
+<../examples/simple_secure_chat/main.cpp>
lib_deps = ${picow.lib_deps}
lib_deps = ${rpi_picow.lib_deps}
densaugeo/base64 @ ~1.4.0

View File

@@ -3,7 +3,7 @@
#define RADIOLIB_STATIC_ONLY 1
#include <RadioLib.h>
#include <helpers/radiolib/RadioLibWrappers.h>
#include <helpers/rp2040/PicoWBoard.h>
#include <PicoWBoard.h>
#include <helpers/radiolib/CustomSX1262Wrapper.h>
#include <helpers/AutoDiscoverRTCClock.h>
#include <helpers/SensorManager.h>

View File

@@ -76,8 +76,8 @@ build_src_filter = ${SenseCap_Solar.build_src_filter}
extends = SenseCap_Solar
build_flags =
${SenseCap_Solar.build_flags}
-D MAX_CONTACTS=100
-D MAX_GROUP_CHANNELS=8
-D MAX_CONTACTS=350
-D MAX_GROUP_CHANNELS=40
-D BLE_PIN_CODE=123456
-D OFFLINE_QUEUE_SIZE=256
; -D BLE_DEBUG_LOGGING=1
@@ -94,8 +94,8 @@ lib_deps =
extends = SenseCap_Solar
build_flags =
${SenseCap_Solar.build_flags}
-D MAX_CONTACTS=100
-D MAX_GROUP_CHANNELS=8
-D MAX_CONTACTS=350
-D MAX_GROUP_CHANNELS=40
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
build_src_filter = ${SenseCap_Solar.build_src_filter}

View File

@@ -3,22 +3,6 @@
#include <MeshCore.h>
#include <Arduino.h>
// LoRa and SPI pins
#define P_LORA_DIO_1 (32 + 1) // P1.1
#define P_LORA_NSS (0 + 12) // P0.12
#define P_LORA_RESET (32 + 10) // P1.10
#define P_LORA_BUSY (0 + 7) // P0.7
#define P_LORA_SCLK (0 + 11) // P0.11
#define P_LORA_MISO (32 + 8) // P1.8
#define P_LORA_MOSI (32 + 9) // P0.9
#define LR11X0_DIO_AS_RF_SWITCH true
#define LR11X0_DIO3_TCXO_VOLTAGE 1.6
// built-ins
//#define PIN_VBAT_READ 5
//#define ADC_MULTIPLIER (3 * 1.73 * 1000)
class T1000eBoard : public mesh::MainBoard {
protected:
uint8_t startup_reason;
@@ -75,11 +59,11 @@ public:
pinMode(GPS_RESETB, OUTPUT);
digitalWrite(GPS_RESETB, LOW);
#endif
#ifdef BUZZER_EN
digitalWrite(BUZZER_EN, LOW);
#endif
#ifdef PIN_3V3_EN
digitalWrite(PIN_3V3_EN, LOW);
#endif

View File

@@ -1,25 +1,13 @@
; ----------------- NRF52 T1000e---------------------
[nrf52840_t1000e]
[t1000-e]
extends = nrf52_base
platform_packages = framework-arduinoadafruitnrf52
board = tracker-t1000-e
board_build.ldscript = boards/nrf52840_s140_v7.ld
build_flags = ${nrf52_base.build_flags}
-I src/helpers/nrf52
-I lib/nrf52/s140_nrf52_7.3.0_API/include
-I lib/nrf52/s140_nrf52_7.3.0_API/include/nrf52
lib_ignore =
BluetoothOTA
lvgl
lib5b4
lib_deps =
${nrf52_base.lib_deps}
rweather/Crypto @ ^0.4.0
[t1000-e]
extends = nrf52840_t1000e
board = tracker-t1000-e
board_build.ldscript = boards/nrf52840_s140_v7.ld
build_flags = ${nrf52840_t1000e.build_flags}
-I variants/t1000-e
-I src/helpers/ui
-D T1000_E
-D PIN_USER_BTN=6
-D USER_BTN_PRESSED=HIGH
@@ -27,7 +15,18 @@ build_flags = ${nrf52840_t1000e.build_flags}
-D RADIO_CLASS=CustomLR1110
-D WRAPPER_CLASS=CustomLR1110Wrapper
-D LORA_TX_POWER=22
build_src_filter = ${nrf52840_t1000e.build_src_filter}
-D RF_SWITCH_TABLE
-D RX_BOOSTED_GAIN=true
-D P_LORA_BUSY=7 ; P0.7
-D P_LORA_SCLK=11 ; P0.11
-D P_LORA_NSS=12 ; P0.12
-D P_LORA_DIO_1=33 ; P1.1
-D P_LORA_MISO=40 ; P1.8
-D P_LORA_MOSI=41 ; P0.9
-D P_LORA_RESET=42 ; P1.10
-D LR11X0_DIO_AS_RF_SWITCH=true
-D LR11X0_DIO3_TCXO_VOLTAGE=1.6
build_src_filter = ${nrf52_base.build_src_filter}
+<helpers/*.cpp>
+<helpers/nrf52/T1000eBoard.cpp>
+<../variants/t1000-e>
@@ -45,8 +44,6 @@ build_flags = ${t1000-e.build_flags}
-D MAX_NEIGHBOURS=8
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
-D RX_BOOSTED_GAIN=true
-D RF_SWITCH_TABLE
build_src_filter = ${t1000-e.build_src_filter}
+<../examples/simple_repeater>
lib_deps = ${t1000-e.lib_deps}
@@ -63,7 +60,6 @@ build_flags = ${t1000-e.build_flags}
-D ROOM_PASSWORD='"hello"'
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
-D RX_BOOSTED_GAIN=true
-D RF_SWITCH_TABLE
build_src_filter = ${t1000-e.build_src_filter}
+<../examples/simple_room_server>
@@ -79,8 +75,6 @@ build_flags = ${t1000-e.build_flags}
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
-D OFFLINE_QUEUE_SIZE=256
-D RX_BOOSTED_GAIN=true
-D RF_SWITCH_TABLE
-D DISPLAY_CLASS=NullDisplayDriver
-D PIN_BUZZER=25
-D PIN_BUZZER_EN=37 ; P1/5 - required for T1000-E
@@ -97,15 +91,13 @@ lib_deps = ${t1000-e.lib_deps}
extends = t1000-e
build_flags = ${t1000-e.build_flags}
-I examples/companion_radio/ui-orig
-D MAX_CONTACTS=100
-D MAX_GROUP_CHANNELS=8
-D MAX_CONTACTS=350
-D MAX_GROUP_CHANNELS=40
-D BLE_PIN_CODE=123456
; -D BLE_DEBUG_LOGGING=1
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
-D OFFLINE_QUEUE_SIZE=256
-D RX_BOOSTED_GAIN=true
-D RF_SWITCH_TABLE
-D DISPLAY_CLASS=NullDisplayDriver
-D PIN_BUZZER=25
-D PIN_BUZZER_EN=37 ; P1/5 - required for T1000-E

View File

@@ -1,119 +1,99 @@
#include <Arduino.h>
#include "t1000e_sensors.h"
#define HEATER_NTC_BX 4250 // thermistor coefficient B
#define HEATER_NTC_RP 8250 // ohm, series resistance to thermistor
#define HEATER_NTC_KA 273.15 // 25 Celsius at Kelvin
#define NTC_REF_VCC 3000 // mV, output voltage of LDO
#define LIGHT_REF_VCC 2400 //
static unsigned int ntc_res2[136]={
113347,107565,102116,96978,92132,87559,83242,79166,75316,71677,
68237,64991,61919,59011,56258,53650,51178,48835,46613,44506,
42506,40600,38791,37073,35442,33892,32420,31020,29689,28423,
27219,26076,24988,23951,22963,22021,21123,20267,19450,18670,
17926,17214,16534,15886,15266,14674,14108,13566,13049,12554,
12081,11628,11195,10780,10382,10000,9634,9284,8947,8624,
8315,8018,7734,7461,7199,6948,6707,6475,6253,6039,
5834,5636,5445,5262,5086,4917,4754,4597,4446,4301,
4161,4026,3896,3771,3651,3535,3423,3315,3211,3111,
3014,2922,2834,2748,2666,2586,2509,2435,2364,2294,
2228,2163,2100,2040,1981,1925,1870,1817,1766,1716,
1669,1622,1578,1535,1493,1452,1413,1375,1338,1303,
1268,1234,1202,1170,1139,1110,1081,1053,1026,999,
974,949,925,902,880,858,
};
static char ntc_temp2[136]=
{
-30,-29,-28,-27,-26,-25,-24,-23,-22,-21,
-20,-19,-18,-17,-16,-15,-14,-13,-12,-11,
-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,
0,1,2,3,4,5,6,7,8,9,
10,11,12,13,14,15,16,17,18,19,
20,21,22,23,24,25,26,27,28,29,
30,31,32,33,34,35,36,37,38,39,
40,41,42,43,44,45,46,47,48,49,
50,51,52,53,54,55,56,57,58,59,
60,61,62,63,64,65,66,67,68,69,
70,71,72,73,74,75,76,77,78,79,
80,81,82,83,84,85,86,87,88,89,
90,91,92,93,94,95,96,97,98,99,
100,101,102,103,104,105,
#include <Arduino.h>
#define HEATER_NTC_BX 4250 // thermistor coefficient B
#define HEATER_NTC_RP 8250 // ohm, series resistance to thermistor
#define HEATER_NTC_KA 273.15 // 25 Celsius at Kelvin
#define NTC_REF_VCC 3000 // mV, output voltage of LDO
#define LIGHT_REF_VCC 2400 //
static unsigned int ntc_res2[136] = {
113347, 107565, 102116, 96978, 92132, 87559, 83242, 79166, 75316, 71677, 68237, 64991, 61919, 59011,
56258, 53650, 51178, 48835, 46613, 44506, 42506, 40600, 38791, 37073, 35442, 33892, 32420, 31020,
29689, 28423, 27219, 26076, 24988, 23951, 22963, 22021, 21123, 20267, 19450, 18670, 17926, 17214,
16534, 15886, 15266, 14674, 14108, 13566, 13049, 12554, 12081, 11628, 11195, 10780, 10382, 10000,
9634, 9284, 8947, 8624, 8315, 8018, 7734, 7461, 7199, 6948, 6707, 6475, 6253, 6039,
5834, 5636, 5445, 5262, 5086, 4917, 4754, 4597, 4446, 4301, 4161, 4026, 3896, 3771,
3651, 3535, 3423, 3315, 3211, 3111, 3014, 2922, 2834, 2748, 2666, 2586, 2509, 2435,
2364, 2294, 2228, 2163, 2100, 2040, 1981, 1925, 1870, 1817, 1766, 1716, 1669, 1622,
1578, 1535, 1493, 1452, 1413, 1375, 1338, 1303, 1268, 1234, 1202, 1170, 1139, 1110,
1081, 1053, 1026, 999, 974, 949, 925, 902, 880, 858,
};
static float get_heater_temperature( unsigned int vcc_volt, unsigned int ntc_volt )
{
int i = 0;
float Vout = 0, Rt = 0, temp = 0;
Vout = ntc_volt;
Rt = ( HEATER_NTC_RP * vcc_volt ) / Vout - HEATER_NTC_RP;
for( i = 0; i < 136; i++ )
{
if( Rt >= ntc_res2[i] )
{
break;
}
static char ntc_temp2[136] = {
-30, -29, -28, -27, -26, -25, -24, -23, -22, -21, -20, -19, -18, -17, -16, -15, -14, -13, -12, -11,
-10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105,
};
static float get_heater_temperature(unsigned int vcc_volt, unsigned int ntc_volt) {
int i = 0;
float Vout = 0, Rt = 0, temp = 0;
Vout = ntc_volt;
Rt = (HEATER_NTC_RP * vcc_volt) / Vout - HEATER_NTC_RP;
for (i = 0; i < 136; i++) {
if (Rt >= ntc_res2[i]) {
break;
}
temp = ntc_temp2[i - 1] + 1 * ( ntc_res2[i - 1] - Rt ) / ( float )( ntc_res2[i - 1] - ntc_res2[i] );
temp = ( temp * 100 + 5 ) / 100;
return temp;
}
temp = ntc_temp2[i - 1] + 1 * (ntc_res2[i - 1] - Rt) / (float)(ntc_res2[i - 1] - ntc_res2[i]);
temp = (temp * 100 + 5) / 100;
return temp;
}
static int get_light_lv( unsigned int light_volt )
{
float Vout = 0, Vin = 0, Rt = 0, temp = 0;
unsigned int light_level = 0;
if( light_volt <= 80 )
{
light_level = 0;
return light_level;
}
else if( light_volt >= 2480 )
{
light_level = 100;
return light_level;
}
Vout = light_volt;
light_level = 100 * ( Vout - 80 ) / LIGHT_REF_VCC;
static int get_light_lv(unsigned int light_volt) {
float Vout = 0, Vin = 0, Rt = 0, temp = 0;
unsigned int light_level = 0;
if (light_volt <= 80) {
light_level = 0;
return light_level;
}
} else if (light_volt >= 2480) {
light_level = 100;
return light_level;
}
Vout = light_volt;
light_level = 100 * (Vout - 80) / LIGHT_REF_VCC;
float t1000e_get_temperature( void )
{
unsigned int ntc_v, vcc_v;
digitalWrite(PIN_3V3_EN, HIGH);
digitalWrite(SENSOR_EN, HIGH);
analogReference(AR_INTERNAL_3_0);
analogReadResolution(12);
delay(10);
vcc_v = (1000.0*(analogRead(BATTERY_PIN) * ADC_MULTIPLIER * AREF_VOLTAGE)) / 4096;
ntc_v = (1000.0 * AREF_VOLTAGE * analogRead(TEMP_SENSOR)) / 4096;
digitalWrite(PIN_3V3_EN, LOW);
digitalWrite(SENSOR_EN, LOW);
return get_heater_temperature (vcc_v, ntc_v);
return light_level;
}
uint32_t t1000e_get_light( void )
{
int lux = 0;
unsigned int lux_v = 0;
digitalWrite(SENSOR_EN, HIGH);
analogReference(AR_INTERNAL_3_0);
analogReadResolution(12);
delay(10);
lux_v = 1000 * analogRead(LUX_SENSOR) * AREF_VOLTAGE / 4096;
lux = get_light_lv( lux_v );
digitalWrite(SENSOR_EN, LOW);
return lux;
float t1000e_get_temperature(void) {
unsigned int ntc_v, vcc_v;
digitalWrite(PIN_3V3_EN, HIGH);
digitalWrite(SENSOR_EN, HIGH);
analogReference(AR_INTERNAL_3_0);
analogReadResolution(12);
delay(10);
vcc_v = (1000.0 * (analogRead(BATTERY_PIN) * ADC_MULTIPLIER * AREF_VOLTAGE)) / 4096;
ntc_v = (1000.0 * AREF_VOLTAGE * analogRead(TEMP_SENSOR)) / 4096;
digitalWrite(PIN_3V3_EN, LOW);
digitalWrite(SENSOR_EN, LOW);
return get_heater_temperature(vcc_v, ntc_v);
}
uint32_t t1000e_get_light(void) {
int lux = 0;
unsigned int lux_v = 0;
digitalWrite(SENSOR_EN, HIGH);
analogReference(AR_INTERNAL_3_0);
analogReadResolution(12);
delay(10);
lux_v = 1000 * analogRead(LUX_SENSOR) * AREF_VOLTAGE / 4096;
lux = get_light_lv(lux_v);
digitalWrite(SENSOR_EN, LOW);
return lux;
}

View File

@@ -1,7 +1,8 @@
#pragma once
#include <stdint.h>
// Light and temperature sensors are on ADC ports
// functions adapted from Seeed examples to get values
// functions adapted from Seeed examples to get values
// see : https://github.com/Seeed-Studio/Seeed-Tracker-T1000-E-for-LoRaWAN-dev-board
extern uint32_t t1000e_get_light();

View File

@@ -1,85 +0,0 @@
[nrf52840_techo]
extends = nrf52_base
platform_packages = framework-arduinoadafruitnrf52
build_flags = ${nrf52_base.build_flags}
-I src/helpers/nrf52
-I lib/nrf52/s140_nrf52_6.1.1_API/include
-I lib/nrf52/s140_nrf52_6.1.1_API/include/nrf52
lib_deps =
${nrf52_base.lib_deps}
rweather/Crypto @ ^0.4.0
[LilyGo_Techo]
extends = nrf52840_techo
board = t-echo
board_build.ldscript = boards/nrf52840_s140_v6.ld
build_flags = ${nrf52840_techo.build_flags}
-I variants/techo
-DLILYGO_TECHO
-D RADIO_CLASS=CustomSX1262
-D WRAPPER_CLASS=CustomSX1262Wrapper
-D LORA_TX_POWER=22
-D SX126X_CURRENT_LIMIT=140
-D SX126X_RX_BOOSTED_GAIN=1
-D P_LORA_TX_LED=LED_GREEN
build_src_filter = ${nrf52840_techo.build_src_filter}
+<helpers/*.cpp>
+<helpers/nrf52/TechoBoard.cpp>
+<../variants/techo>
lib_deps =
${nrf52840_techo.lib_deps}
stevemarple/MicroNMEA @ ^2.0.6
debug_tool = jlink
upload_protocol = nrfutil
[env:LilyGo_T-Echo_repeater]
extends = LilyGo_Techo
build_src_filter = ${LilyGo_Techo.build_src_filter} +<../examples/simple_repeater/main.cpp>
build_flags =
${LilyGo_Techo.build_flags}
-D ADVERT_NAME='"T-Echo Repeater"'
-D ADVERT_LAT=0.0
-D ADVERT_LON=0.0
-D ADMIN_PASSWORD='"password"'
-D MAX_NEIGHBOURS=8
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
[env:LilyGo_T-Echo_room_server]
extends = LilyGo_Techo
build_src_filter = ${LilyGo_Techo.build_src_filter} +<../examples/simple_room_server/main.cpp>
build_flags =
${LilyGo_Techo.build_flags}
-D ADVERT_NAME='"T-Echo Room"'
-D ADVERT_LAT=0.0
-D ADVERT_LON=0.0
-D ADMIN_PASSWORD='"password"'
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
[env:LilyGo_T-Echo_companion_radio_ble]
extends = LilyGo_Techo
build_flags =
${LilyGo_Techo.build_flags}
-I src/helpers/ui
-I examples/companion_radio/ui-new
-D MAX_CONTACTS=100
-D MAX_GROUP_CHANNELS=8
-D BLE_PIN_CODE=123456
-D BLE_DEBUG_LOGGING=1
-D DISPLAY_CLASS=GxEPDDisplay
-D OFFLINE_QUEUE_SIZE=256
-D UI_RECENT_LIST_SIZE=9
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
build_src_filter = ${LilyGo_Techo.build_src_filter}
+<helpers/nrf52/TechoBoard.cpp>
+<helpers/nrf52/SerialBLEInterface.cpp>
+<helpers/ui/GxEPDDisplay.cpp>
+<helpers/ui/MomentaryButton.cpp>
+<../examples/companion_radio/*.cpp>
+<../examples/companion_radio/ui-new/*.cpp>
lib_deps =
${LilyGo_Techo.lib_deps}
densaugeo/base64 @ ~1.4.0
zinggjm/GxEPD2 @ 1.6.2

View File

@@ -1,123 +0,0 @@
#include <Arduino.h>
#include "target.h"
#include <helpers/ArduinoHelpers.h>
#include <helpers/sensors/MicroNMEALocationProvider.h>
TechoBoard board;
RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, SPI);
WRAPPER_CLASS radio_driver(radio, board);
VolatileRTCClock fallback_clock;
AutoDiscoverRTCClock rtc_clock(fallback_clock);
MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Serial1);
TechoSensorManager sensors = TechoSensorManager(nmea);
#ifdef DISPLAY_CLASS
DISPLAY_CLASS display;
MomentaryButton user_btn(PIN_USER_BTN, 1000, true);
#endif
bool radio_init() {
rtc_clock.begin(Wire);
return radio.std_init(&SPI);
}
uint32_t radio_get_rng_seed() {
return radio.random(0x7FFFFFFF);
}
void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr) {
radio.setFrequency(freq);
radio.setSpreadingFactor(sf);
radio.setBandwidth(bw);
radio.setCodingRate(cr);
}
void radio_set_tx_power(uint8_t dbm) {
radio.setOutputPower(dbm);
}
mesh::LocalIdentity radio_new_identity() {
RadioNoiseListener rng(radio);
return mesh::LocalIdentity(&rng); // create new random identity
}
void TechoSensorManager::start_gps() {
if (!gps_active) {
gps_active = true;
_location->begin();
}
}
void TechoSensorManager::stop_gps() {
if (gps_active) {
gps_active = false;
_location->stop();
}
}
bool TechoSensorManager::begin() {
Serial1.begin(9600);
// GPS enabled pin
pinMode(GPS_EN, OUTPUT);
return true;
}
bool TechoSensorManager::querySensors(uint8_t requester_permissions, CayenneLPP& telemetry) {
if (requester_permissions & TELEM_PERM_LOCATION) { // does requester have permission?
telemetry.addGPS(TELEM_CHANNEL_SELF, node_lat, node_lon, node_altitude);
}
return true;
}
void TechoSensorManager::loop() {
static long next_gps_update = 0;
if (!gps_active) {
return; // GPS is not active, skip further processing
}
_location->loop();
if (millis() > next_gps_update) {
if (_location->isValid()) {
node_lat = ((double)_location->getLatitude())/1000000.;
node_lon = ((double)_location->getLongitude())/1000000.;
node_altitude = ((double)_location->getAltitude()) / 1000.0;
MESH_DEBUG_PRINTLN("lat %f lon %f", node_lat, node_lon);
}
next_gps_update = millis() + 1000;
}
}
int TechoSensorManager::getNumSettings() const {
return 1; // always show GPS setting
}
const char* TechoSensorManager::getSettingName(int i) const {
return (i == 0) ? "gps" : NULL;
}
const char* TechoSensorManager::getSettingValue(int i) const {
if (i == 0) {
return gps_active ? "1" : "0";
}
return NULL;
}
bool TechoSensorManager::setSettingValue(const char* name, const char* value) {
if (strcmp(name, "gps") == 0) {
if (strcmp(value, "0") == 0) {
stop_gps();
} else {
start_gps();
}
return true;
}
return false; // not supported
}

View File

@@ -1,10 +1,10 @@
#include <Arduino.h>
#include "ThinkNodeM1Board.h"
#include <Arduino.h>
#ifdef THINKNODE_M1
#include <bluefruit.h>
#include <Wire.h>
#include <bluefruit.h>
static BLEDfu bledfu;
@@ -26,14 +26,14 @@ void ThinkNodeM1Board::begin() {
Wire.begin();
#ifdef P_LORA_TX_LED
pinMode(P_LORA_TX_LED, OUTPUT);
digitalWrite(P_LORA_TX_LED, LOW);
#endif
#ifdef P_LORA_TX_LED
pinMode(P_LORA_TX_LED, OUTPUT);
digitalWrite(P_LORA_TX_LED, LOW);
#endif
pinMode(SX126X_POWER_EN, OUTPUT);
digitalWrite(SX126X_POWER_EN, HIGH);
delay(10); // give sx1262 some time to power up
delay(10); // give sx1262 some time to power up
}
uint16_t ThinkNodeM1Board::getBattMilliVolts() {
@@ -50,7 +50,7 @@ uint16_t ThinkNodeM1Board::getBattMilliVolts() {
return (uint16_t)((float)adcvalue * REAL_VBAT_MV_PER_LSB);
}
bool ThinkNodeM1Board::startOTAUpdate(const char* id, char reply[]) {
bool ThinkNodeM1Board::startOTAUpdate(const char *id, char reply[]) {
// Config the peripheral connection with maximum bandwidth
// more SRAM required by SoftDevice
// Note: All config***() function must be called before begin()

View File

@@ -3,19 +3,6 @@
#include <MeshCore.h>
#include <Arduino.h>
// LoRa radio module pins for Elecrow ThinkNode M1
#define P_LORA_DIO_1 20
#define P_LORA_NSS 24
#define P_LORA_RESET 25
#define P_LORA_BUSY 17
#define P_LORA_SCLK 19
#define P_LORA_MISO 23
#define P_LORA_MOSI 22
#define SX126X_POWER_EN 37
#define SX126X_DIO2_AS_RF_SWITCH true
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
// built-ins
#define VBAT_MV_PER_LSB (0.73242188F) // 3.0V ADC range and 12-bit ADC resolution = 3000mV/4096

View File

@@ -1,33 +1,35 @@
[nrf52840_thinknode_m1]
[ThinkNode_M1]
extends = nrf52_base
platform_packages = framework-arduinoadafruitnrf52
board = thinknode_m1
board_build.ldscript = boards/nrf52840_s140_v6.ld
build_flags = ${nrf52_base.build_flags}
-I src/helpers/nrf52
-I lib/nrf52/s140_nrf52_6.1.1_API/include
-I lib/nrf52/s140_nrf52_6.1.1_API/include/nrf52
lib_deps =
${nrf52_base.lib_deps}
rweather/Crypto @ ^0.4.0
[ThinkNode_M1]
extends = nrf52840_thinknode_m1
board = thinknode_m1
board_build.ldscript = boards/nrf52840_s140_v6.ld
build_flags = ${nrf52840_thinknode_m1.build_flags}
-I variants/thinknode_m1
-D THINKNODE_M1=1
-D RADIO_CLASS=CustomSX1262
-D WRAPPER_CLASS=CustomSX1262Wrapper
-D LORA_TX_POWER=22
-D P_LORA_TX_LED=13
-D P_LORA_DIO_1=20
-D P_LORA_NSS=24
-D P_LORA_RESET=25
-D P_LORA_BUSY=17
-D P_LORA_SCLK=19
-D P_LORA_MISO=23
-D P_LORA_MOSI=22
-D SX126X_POWER_EN=37
-D SX126X_DIO2_AS_RF_SWITCH=true
-D SX126X_DIO3_TCXO_VOLTAGE=1.8
-D SX126X_CURRENT_LIMIT=140
-D SX126X_RX_BOOSTED_GAIN=1
build_src_filter = ${nrf52840_thinknode_m1.build_src_filter}
-D LORA_TX_POWER=22
-D P_LORA_TX_LED=13
build_src_filter = ${nrf52_base.build_src_filter}
+<helpers/*.cpp>
+<helpers/nrf52/ThinkNodeM1Board.cpp>
+<ThinkNodeM1Board.cpp>
+<../variants/thinknode_m1>
lib_deps =
${nrf52840_thinknode_m1.lib_deps}
${nrf52_base.lib_deps}
stevemarple/MicroNMEA @ ^2.0.6
debug_tool = jlink
upload_protocol = nrfutil
@@ -69,8 +71,8 @@ build_flags =
${ThinkNode_M1.build_flags}
-I src/helpers/ui
-I examples/companion_radio/ui-new
-D MAX_CONTACTS=100
-D MAX_GROUP_CHANNELS=8
-D MAX_CONTACTS=350
-D MAX_GROUP_CHANNELS=40
-D BLE_PIN_CODE=123456
-D BLE_DEBUG_LOGGING=1
-D DISPLAY_ROTATION=4
@@ -78,10 +80,10 @@ build_flags =
-D OFFLINE_QUEUE_SIZE=256
-D PIN_BUZZER=6
-D AUTO_SHUTDOWN_MILLIVOLTS=3300
-D QSPIFLASH=1
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
build_src_filter = ${ThinkNode_M1.build_src_filter}
+<helpers/nrf52/ThinkNodeM1.cpp>
+<helpers/nrf52/SerialBLEInterface.cpp>
+<helpers/ui/GxEPDDisplay.cpp>
+<helpers/ui/buzzer.cpp>
@@ -92,4 +94,5 @@ lib_deps =
${ThinkNode_M1.lib_deps}
densaugeo/base64 @ ~1.4.0
zinggjm/GxEPD2 @ 1.6.2
bakercp/CRC32 @ ^2.0.0
end2endzone/NonBlockingRTTTL@^1.3.0

View File

@@ -3,7 +3,7 @@
#define RADIOLIB_STATIC_ONLY 1
#include <RadioLib.h>
#include <helpers/radiolib/RadioLibWrappers.h>
#include <helpers/nrf52/ThinkNodeM1Board.h>
#include <ThinkNodeM1Board.h>
#include <helpers/radiolib/CustomSX1262Wrapper.h>
#include <helpers/AutoDiscoverRTCClock.h>
#include <helpers/SensorManager.h>

View File

@@ -110,6 +110,15 @@ extern const int MISO;
extern const int MOSI;
extern const int SCK;
////////////////////////////////////////////////////////////////////////////////
// QSPI
#define PIN_QSPI_SCK (46)
#define PIN_QSPI_CS (47)
#define PIN_QSPI_IO0 (44) // MOSI if using two bit interface
#define PIN_QSPI_IO1 (45) // MISO if using two bit interface
#define PIN_QSPI_IO2 (7) // WP if using two bit interface (i.e. not used)
#define PIN_QSPI_IO3 (5) // HOLD if using two bit interface (i.e. not used)
////////////////////////////////////////////////////////////////////////////////
// Display

Some files were not shown because too many files have changed in this diff Show More