diff --git a/examples/companion_radio/DataStore.cpp b/examples/companion_radio/DataStore.cpp index b5d70edc..7631b905 100644 --- a/examples/companion_radio/DataStore.cpp +++ b/examples/companion_radio/DataStore.cpp @@ -1,7 +1,13 @@ #include #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 #elif defined(NRF52_PLATFORM) || defined(STM32_PLATFORM) - #include + #if defined(QSPIFLASH) + #include + #elif defined(EXTRAFS) + #include + #else + #include + #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; diff --git a/examples/companion_radio/DataStore.h b/examples/companion_radio/DataStore.h index 7bd33301..62580942 100644 --- a/examples/companion_radio/DataStore.h +++ b/examples/companion_radio/DataStore.h @@ -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;}; }; diff --git a/examples/companion_radio/MyMesh.cpp b/examples/companion_radio/MyMesh.cpp index 1fa5478b..7847d652 100644 --- a/examples/companion_radio/MyMesh.cpp +++ b/examples/companion_radio/MyMesh.cpp @@ -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 { diff --git a/examples/companion_radio/main.cpp b/examples/companion_radio/main.cpp index 1d5ec564..89adca59 100644 --- a/examples/companion_radio/main.cpp +++ b/examples/companion_radio/main.cpp @@ -14,7 +14,18 @@ static uint32_t _atoi(const char* sp) { #if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM) #include - DataStore store(InternalFS, rtc_clock); + #if defined(QSPIFLASH) + #include + DataStore store(InternalFS, QSPIFlash, rtc_clock); + #else + #if defined(EXTRAFS) + #include + CustomLFS ExtraFS(0xD4000, 0x19000, 128); + DataStore store(InternalFS, ExtraFS, rtc_clock); + #else + DataStore store(InternalFS, rtc_clock); + #endif + #endif #elif defined(RP2040_PLATFORM) #include 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 diff --git a/examples/companion_radio/ui-new/UITask.cpp b/examples/companion_radio/ui-new/UITask.cpp index 1adabffa..0236a381 100644 --- a/examples/companion_radio/ui-new/UITask.cpp +++ b/examples/companion_radio/ui-new/UITask.cpp @@ -226,8 +226,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); @@ -512,8 +512,8 @@ void UITask::setCurrScreen(UIScreen* c) { _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){ @@ -641,7 +641,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); diff --git a/examples/simple_repeater/main.cpp b/examples/simple_repeater/main.cpp index 3f0c0ebe..e4d8a454 100644 --- a/examples/simple_repeater/main.cpp +++ b/examples/simple_repeater/main.cpp @@ -78,28 +78,38 @@ /* ------------------------------ Code -------------------------------- */ -#define REQ_TYPE_GET_STATUS 0x01 // same as _GET_STATS -#define REQ_TYPE_KEEP_ALIVE 0x02 -#define REQ_TYPE_GET_TELEMETRY_DATA 0x03 +#ifdef WITH_RS232_BRIDGE +#include "helpers/bridges/RS232Bridge.h" +#define WITH_BRIDGE +#endif -#define RESP_SERVER_LOGIN_OK 0 // response to ANON_REQ +#ifdef WITH_ESPNOW_BRIDGE +#include "helpers/bridges/ESPNowBridge.h" +#define WITH_BRIDGE +#endif -struct RepeaterStats { - uint16_t batt_milli_volts; - uint16_t curr_tx_queue_len; - int16_t noise_floor; - int16_t last_rssi; - uint32_t n_packets_recv; - uint32_t n_packets_sent; - uint32_t total_air_time_secs; - uint32_t total_up_time_secs; - uint32_t n_sent_flood, n_sent_direct; - uint32_t n_recv_flood, n_recv_direct; - uint16_t err_events; // was 'n_full_events' - int16_t last_snr; // x 4 - uint16_t n_direct_dups, n_flood_dups; - uint32_t total_rx_air_time_secs; -}; +#define REQ_TYPE_GET_STATUS 0x01 // same as _GET_STATS +#define REQ_TYPE_KEEP_ALIVE 0x02 +#define REQ_TYPE_GET_TELEMETRY_DATA 0x03 + +#define RESP_SERVER_LOGIN_OK 0 // response to ANON_REQ + + struct RepeaterStats { + uint16_t batt_milli_volts; + uint16_t curr_tx_queue_len; + int16_t noise_floor; + int16_t last_rssi; + uint32_t n_packets_recv; + uint32_t n_packets_sent; + uint32_t total_air_time_secs; + uint32_t total_up_time_secs; + uint32_t n_sent_flood, n_sent_direct; + uint32_t n_recv_flood, n_recv_direct; + uint16_t err_events; // was 'n_full_events' + int16_t last_snr; // x 4 + uint16_t n_direct_dups, n_flood_dups; + uint32_t total_rx_air_time_secs; + }; struct ClientInfo { mesh::Identity id; @@ -140,6 +150,11 @@ class MyMesh : public mesh::Mesh, public CommonCLICallbacks { float pending_bw; uint8_t pending_sf; uint8_t pending_cr; +#if defined(WITH_RS232_BRIDGE) + RS232Bridge bridge; +#elif defined(WITH_ESPNOW_BRIDGE) + ESPNowBridge bridge; +#endif ClientInfo* putClient(const mesh::Identity& id) { uint32_t min_time = 0xFFFFFFFF; @@ -300,6 +315,9 @@ protected: } } void logTx(mesh::Packet* pkt, int len) override { +#ifdef WITH_BRIDGE + bridge.onPacketTransmitted(pkt); +#endif if (_logging) { File f = openAppend(PACKET_LOG_FILE); if (f) { @@ -364,9 +382,9 @@ protected: } else if (strcmp((char *) &data[4], _prefs.guest_password) == 0) { // check guest password is_admin = false; } else { - #if MESH_DEBUG +#if MESH_DEBUG MESH_DEBUG_PRINTLN("Invalid password: %s", &data[4]); - #endif +#endif return; } @@ -384,15 +402,15 @@ protected: uint32_t now = getRTCClock()->getCurrentTimeUnique(); memcpy(reply_data, &now, 4); // response packets always prefixed with timestamp - #if 0 +#if 0 memcpy(&reply_data[4], "OK", 2); // legacy response - #else +#else reply_data[4] = RESP_SERVER_LOGIN_OK; reply_data[5] = 0; // NEW: recommended keep-alive interval (secs / 16) reply_data[6] = is_admin ? 1 : 0; reply_data[7] = 0; // FUTURE: reserved getRNG()->random(&reply_data[8], 4); // random blob to help packet-hash uniqueness - #endif +#endif if (packet->isRouteFlood()) { // let this sender know path TO here, so they can use sendDirect(), and ALSO encode the response @@ -564,15 +582,20 @@ public: MyMesh(mesh::MainBoard& board, mesh::Radio& radio, mesh::MillisecondClock& ms, mesh::RNG& rng, mesh::RTCClock& rtc, mesh::MeshTables& tables) : mesh::Mesh(radio, ms, rng, rtc, *new StaticPoolPacketManager(32), tables), _cli(board, rtc, &_prefs, this), telemetry(MAX_PACKET_PAYLOAD - 4) +#if defined(WITH_RS232_BRIDGE) + , bridge(WITH_RS232_BRIDGE, _mgr, &rtc) +#elif defined(WITH_ESPNOW_BRIDGE) + , bridge(_mgr, &rtc) +#endif { memset(known_clients, 0, sizeof(known_clients)); next_local_advert = next_flood_advert = 0; set_radio_at = revert_radio_at = 0; _logging = false; - #if MAX_NEIGHBOURS +#if MAX_NEIGHBOURS memset(neighbours, 0, sizeof(neighbours)); - #endif +#endif // defaults memset(&_prefs, 0, sizeof(_prefs)); @@ -600,6 +623,10 @@ public: // load persisted prefs _cli.loadPrefs(_fs); + #ifdef WITH_BRIDGE + bridge.begin(); + #endif + radio_set_params(_prefs.freq, _prefs.bw, _prefs.sf, _prefs.cr); radio_set_tx_power(_prefs.tx_power_dbm); @@ -765,6 +792,10 @@ public: } void loop() { +#ifdef WITH_BRIDGE + bridge.loop(); +#endif + mesh::Mesh::loop(); if (next_flood_advert && millisHasNowPassed(next_flood_advert)) { @@ -824,7 +855,9 @@ void setup() { } #endif - if (!radio_init()) { halt(); } + if (!radio_init()) { + halt(); + } fast_rng.begin(radio_get_rng_seed()); diff --git a/platformio.ini b/platformio.ini index 1c89465f..11814a22 100644 --- a/platformio.ini +++ b/platformio.ini @@ -47,6 +47,7 @@ build_src_filter = +<*.cpp> + + + + + ; ----------------- ESP32 --------------------- @@ -78,7 +79,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.1 ; ----------------- RP2040 --------------------- [rp2040_base] diff --git a/src/helpers/AbstractBridge.h b/src/helpers/AbstractBridge.h new file mode 100644 index 00000000..a348e933 --- /dev/null +++ b/src/helpers/AbstractBridge.h @@ -0,0 +1,34 @@ +#pragma once + +#include + +class AbstractBridge { +public: + virtual ~AbstractBridge() {} + + /** + * @brief Initializes the bridge. + */ + virtual void begin() = 0; + + /** + * @brief A method to be called on every main loop iteration. + * Used for tasks like checking for incoming data. + */ + virtual void loop() = 0; + + /** + * @brief A callback that is triggered when the mesh transmits a packet. + * The bridge can use this to forward the packet. + * + * @param packet The packet that was transmitted. + */ + virtual void onPacketTransmitted(mesh::Packet* packet) = 0; + + /** + * @brief Processes a received packet from the bridge's medium. + * + * @param packet The packet that was received. + */ + virtual void onPacketReceived(mesh::Packet* packet) = 0; +}; diff --git a/src/helpers/IdentityStore.h b/src/helpers/IdentityStore.h index e81290e7..d0d7ee45 100644 --- a/src/helpers/IdentityStore.h +++ b/src/helpers/IdentityStore.h @@ -9,7 +9,6 @@ using namespace Adafruit_LittleFS_Namespace; #endif - #include 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); diff --git a/src/helpers/bridges/BridgeBase.cpp b/src/helpers/bridges/BridgeBase.cpp new file mode 100644 index 00000000..03871418 --- /dev/null +++ b/src/helpers/bridges/BridgeBase.cpp @@ -0,0 +1,36 @@ +#include "BridgeBase.h" + +#include + +const char *BridgeBase::getLogDateTime() { + static char tmp[32]; + uint32_t now = _rtc->getCurrentTime(); + DateTime dt = DateTime(now); + sprintf(tmp, "%02d:%02d:%02d - %d/%d/%d U", dt.hour(), dt.minute(), dt.second(), dt.day(), dt.month(), + dt.year()); + return tmp; +} + +uint16_t BridgeBase::fletcher16(const uint8_t *data, size_t len) { + uint8_t sum1 = 0, sum2 = 0; + + for (size_t i = 0; i < len; i++) { + sum1 = (sum1 + data[i]) % 255; + sum2 = (sum2 + sum1) % 255; + } + + return (sum2 << 8) | sum1; +} + +bool BridgeBase::validateChecksum(const uint8_t *data, size_t len, uint16_t received_checksum) { + uint16_t calculated_checksum = fletcher16(data, len); + return received_checksum == calculated_checksum; +} + +void BridgeBase::handleReceivedPacket(mesh::Packet *packet) { + if (!_seen_packets.hasSeen(packet)) { + _mgr->queueInbound(packet, millis() + BRIDGE_DELAY); + } else { + _mgr->free(packet); + } +} diff --git a/src/helpers/bridges/BridgeBase.h b/src/helpers/bridges/BridgeBase.h new file mode 100644 index 00000000..ab62619f --- /dev/null +++ b/src/helpers/bridges/BridgeBase.h @@ -0,0 +1,112 @@ +#pragma once + +#include "helpers/AbstractBridge.h" +#include "helpers/SimpleMeshTables.h" + +#include + +/** + * @brief Base class implementing common bridge functionality + * + * This class provides common functionality used by different bridge implementations + * like packet tracking, checksum calculation, timestamping, and duplicate detection. + * + * Features: + * - Fletcher-16 checksum calculation for data integrity + * - Packet duplicate detection using SimpleMeshTables + * - Common timestamp formatting for debug logging + * - Shared packet management and queuing logic + */ +class BridgeBase : public AbstractBridge { +public: + virtual ~BridgeBase() = default; + + /** + * @brief Common magic number used by all bridge implementations for packet identification + * + * This magic number is placed at the beginning of bridge packets to identify + * them as mesh bridge packets and provide frame synchronization. + */ + static constexpr uint16_t BRIDGE_PACKET_MAGIC = 0xC03E; + + /** + * @brief Common field sizes used by bridge implementations + * + * These constants define the size of common packet fields used across bridges. + * BRIDGE_MAGIC_SIZE is used by all bridges for packet identification. + * BRIDGE_LENGTH_SIZE is used by bridges that need explicit length fields (like RS232). + * BRIDGE_CHECKSUM_SIZE is used by all bridges for Fletcher-16 checksums. + */ + static constexpr uint16_t BRIDGE_MAGIC_SIZE = sizeof(BRIDGE_PACKET_MAGIC); + static constexpr uint16_t BRIDGE_LENGTH_SIZE = sizeof(uint16_t); + static constexpr uint16_t BRIDGE_CHECKSUM_SIZE = sizeof(uint16_t); + + /** + * @brief Default delay in milliseconds for scheduling inbound packet processing + * + * It provides a buffer to prevent immediate processing conflicts in the mesh network. + * Used in handleReceivedPacket() as: millis() + BRIDGE_DELAY + */ + static constexpr uint16_t BRIDGE_DELAY = 500; // TODO: maybe too high ? + +protected: + /** Packet manager for allocating and queuing mesh packets */ + mesh::PacketManager *_mgr; + + /** RTC clock for timestamping debug messages */ + mesh::RTCClock *_rtc; + + /** Tracks seen packets to prevent loops in broadcast communications */ + SimpleMeshTables _seen_packets; + + /** + * @brief Constructs a BridgeBase instance + * + * @param mgr PacketManager for allocating and queuing packets + * @param rtc RTCClock for timestamping debug messages + */ + BridgeBase(mesh::PacketManager *mgr, mesh::RTCClock *rtc) : _mgr(mgr), _rtc(rtc) {} + + /** + * @brief Gets formatted date/time string for logging + * + * Format: "HH:MM:SS - DD/MM/YYYY U" + * + * @return Formatted date/time string + */ + const char *getLogDateTime(); + + /** + * @brief Calculate Fletcher-16 checksum + * + * Based on: https://en.wikipedia.org/wiki/Fletcher%27s_checksum + * Used to verify data integrity of received packets + * + * @param data Pointer to data to calculate checksum for + * @param len Length of data in bytes + * @return Calculated Fletcher-16 checksum + */ + static uint16_t fletcher16(const uint8_t *data, size_t len); + + /** + * @brief Validate received checksum against calculated checksum + * + * @param data Pointer to data to validate + * @param len Length of data in bytes + * @param received_checksum Checksum received with data + * @return true if checksum is valid, false otherwise + */ + bool validateChecksum(const uint8_t *data, size_t len, uint16_t received_checksum); + + /** + * @brief Common packet handling for received packets + * + * Implements the standard pattern used by all bridges: + * - Check if packet was seen before using _seen_packets.hasSeen() + * - Queue packet for mesh processing if not seen before + * - Free packet if already seen to prevent duplicates + * + * @param packet The received mesh packet + */ + void handleReceivedPacket(mesh::Packet *packet); +}; diff --git a/src/helpers/bridges/ESPNowBridge.cpp b/src/helpers/bridges/ESPNowBridge.cpp new file mode 100644 index 00000000..a02f804e --- /dev/null +++ b/src/helpers/bridges/ESPNowBridge.cpp @@ -0,0 +1,196 @@ +#include "ESPNowBridge.h" + +#include +#include + +#ifdef WITH_ESPNOW_BRIDGE + +// Static member to handle callbacks +ESPNowBridge *ESPNowBridge::_instance = nullptr; + +// Static callback wrappers +void ESPNowBridge::recv_cb(const uint8_t *mac, const uint8_t *data, int32_t len) { + if (_instance) { + _instance->onDataRecv(mac, data, len); + } +} + +void ESPNowBridge::send_cb(const uint8_t *mac, esp_now_send_status_t status) { + if (_instance) { + _instance->onDataSent(mac, status); + } +} + +ESPNowBridge::ESPNowBridge(mesh::PacketManager *mgr, mesh::RTCClock *rtc) + : BridgeBase(mgr, rtc), _rx_buffer_pos(0) { + _instance = this; +} + +void ESPNowBridge::begin() { + // Initialize WiFi in station mode + WiFi.mode(WIFI_STA); + + // Initialize ESP-NOW + if (esp_now_init() != ESP_OK) { + Serial.printf("%s: ESPNOW BRIDGE: Error initializing ESP-NOW\n", getLogDateTime()); + return; + } + + // Register callbacks + esp_now_register_recv_cb(recv_cb); + esp_now_register_send_cb(send_cb); + + // Add broadcast peer + esp_now_peer_info_t peerInfo = {}; + memset(&peerInfo, 0, sizeof(peerInfo)); + memset(peerInfo.peer_addr, 0xFF, ESP_NOW_ETH_ALEN); // Broadcast address + peerInfo.channel = 0; + peerInfo.encrypt = false; + + if (esp_now_add_peer(&peerInfo) != ESP_OK) { + Serial.printf("%s: ESPNOW BRIDGE: Failed to add broadcast peer\n", getLogDateTime()); + return; + } +} + +void ESPNowBridge::loop() { + // Nothing to do here - ESP-NOW is callback based +} + +void ESPNowBridge::xorCrypt(uint8_t *data, size_t len) { + size_t keyLen = strlen(_secret); + for (size_t i = 0; i < len; i++) { + data[i] ^= _secret[i % keyLen]; + } +} + +void ESPNowBridge::onDataRecv(const uint8_t *mac, const uint8_t *data, int32_t len) { + // Ignore packets that are too small to contain header + checksum + if (len < (BRIDGE_MAGIC_SIZE + BRIDGE_CHECKSUM_SIZE)) { +#if MESH_PACKET_LOGGING + Serial.printf("%s: ESPNOW BRIDGE: RX packet too small, len=%d\n", getLogDateTime(), len); +#endif + return; + } + + // Validate total packet size + if (len > MAX_ESPNOW_PACKET_SIZE) { +#if MESH_PACKET_LOGGING + Serial.printf("%s: ESPNOW BRIDGE: RX packet too large, len=%d\n", getLogDateTime(), len); +#endif + return; + } + + // Check packet header magic + uint16_t received_magic = (data[0] << 8) | data[1]; + if (received_magic != BRIDGE_PACKET_MAGIC) { +#if MESH_PACKET_LOGGING + Serial.printf("%s: ESPNOW BRIDGE: RX invalid magic 0x%04X\n", getLogDateTime(), received_magic); +#endif + return; + } + + // Make a copy we can decrypt + uint8_t decrypted[MAX_ESPNOW_PACKET_SIZE]; + const size_t encryptedDataLen = len - BRIDGE_MAGIC_SIZE; + memcpy(decrypted, data + BRIDGE_MAGIC_SIZE, encryptedDataLen); + + // Try to decrypt (checksum + payload) + xorCrypt(decrypted, encryptedDataLen); + + // Validate checksum + uint16_t received_checksum = (decrypted[0] << 8) | decrypted[1]; + const size_t payloadLen = encryptedDataLen - BRIDGE_CHECKSUM_SIZE; + + if (!validateChecksum(decrypted + BRIDGE_CHECKSUM_SIZE, payloadLen, received_checksum)) { + // Failed to decrypt - likely from a different network +#if MESH_PACKET_LOGGING + Serial.printf("%s: ESPNOW BRIDGE: RX checksum mismatch, rcv=0x%04X\n", getLogDateTime(), + received_checksum); +#endif + return; + } + +#if MESH_PACKET_LOGGING + Serial.printf("%s: ESPNOW BRIDGE: RX, payload_len=%d\n", getLogDateTime(), payloadLen); +#endif + + // Create mesh packet + mesh::Packet *pkt = _instance->_mgr->allocNew(); + if (!pkt) return; + + if (pkt->readFrom(decrypted + BRIDGE_CHECKSUM_SIZE, payloadLen)) { + _instance->onPacketReceived(pkt); + } else { + _instance->_mgr->free(pkt); + } +} + +void ESPNowBridge::onDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) { + // Could add transmission error handling here if needed +} + +void ESPNowBridge::onPacketReceived(mesh::Packet *packet) { + handleReceivedPacket(packet); +} + +void ESPNowBridge::onPacketTransmitted(mesh::Packet *packet) { + // First validate the packet pointer + if (!packet) { +#if MESH_PACKET_LOGGING + Serial.printf("%s: ESPNOW BRIDGE: TX invalid packet pointer\n", getLogDateTime()); +#endif + return; + } + + if (!_seen_packets.hasSeen(packet)) { + + // Create a temporary buffer just for size calculation and reuse for actual writing + uint8_t sizingBuffer[MAX_PAYLOAD_SIZE]; + uint16_t meshPacketLen = packet->writeTo(sizingBuffer); + + // Check if packet fits within our maximum payload size + if (meshPacketLen > MAX_PAYLOAD_SIZE) { +#if MESH_PACKET_LOGGING + Serial.printf("%s: ESPNOW BRIDGE: TX packet too large (payload=%d, max=%d)\n", getLogDateTime(), + meshPacketLen, MAX_PAYLOAD_SIZE); +#endif + return; + } + + uint8_t buffer[MAX_ESPNOW_PACKET_SIZE]; + + // Write magic header (2 bytes) + buffer[0] = (BRIDGE_PACKET_MAGIC >> 8) & 0xFF; + buffer[1] = BRIDGE_PACKET_MAGIC & 0xFF; + + // Write packet payload starting after magic header and checksum + const size_t packetOffset = BRIDGE_MAGIC_SIZE + BRIDGE_CHECKSUM_SIZE; + memcpy(buffer + packetOffset, sizingBuffer, meshPacketLen); + + // Calculate and add checksum (only of the payload) + uint16_t checksum = fletcher16(buffer + packetOffset, meshPacketLen); + buffer[2] = (checksum >> 8) & 0xFF; // High byte + buffer[3] = checksum & 0xFF; // Low byte + + // Encrypt payload and checksum (not including magic header) + xorCrypt(buffer + BRIDGE_MAGIC_SIZE, meshPacketLen + BRIDGE_CHECKSUM_SIZE); + + // Total packet size: magic header + checksum + payload + const size_t totalPacketSize = BRIDGE_MAGIC_SIZE + BRIDGE_CHECKSUM_SIZE + meshPacketLen; + + // Broadcast using ESP-NOW + uint8_t broadcastAddress[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; + esp_err_t result = esp_now_send(broadcastAddress, buffer, totalPacketSize); + +#if MESH_PACKET_LOGGING + if (result == ESP_OK) { + Serial.printf("%s: ESPNOW BRIDGE: TX, len=%d\n", getLogDateTime(), meshPacketLen); + } else { + Serial.printf("%s: ESPNOW BRIDGE: TX FAILED!\n", getLogDateTime()); + } +#endif + } +} + +#endif diff --git a/src/helpers/bridges/ESPNowBridge.h b/src/helpers/bridges/ESPNowBridge.h new file mode 100644 index 00000000..b43f1744 --- /dev/null +++ b/src/helpers/bridges/ESPNowBridge.h @@ -0,0 +1,156 @@ +#pragma once + +#include "MeshCore.h" +#include "esp_now.h" +#include "helpers/bridges/BridgeBase.h" + +#ifdef WITH_ESPNOW_BRIDGE + +#ifndef WITH_ESPNOW_BRIDGE_SECRET +#error WITH_ESPNOW_BRIDGE_SECRET must be defined to use ESPNowBridge +#endif + +/** + * @brief Bridge implementation using ESP-NOW protocol for packet transport + * + * This bridge enables mesh packet transport over ESP-NOW, a connectionless communication + * protocol provided by Espressif that allows ESP32 devices to communicate directly + * without WiFi router infrastructure. + * + * Features: + * - Broadcast-based communication (all bridges receive all packets) + * - Network isolation using XOR encryption with shared secret + * - Duplicate packet detection using SimpleMeshTables tracking + * - Maximum packet size of 250 bytes (ESP-NOW limitation) + * + * Packet Structure: + * [2 bytes] Magic Header - Used to identify ESPNowBridge packets + * [2 bytes] Fletcher-16 checksum of encrypted payload (calculated over payload only) + * [246 bytes max] Encrypted payload containing the mesh packet + * + * The Fletcher-16 checksum is used to validate packet integrity and detect + * corrupted or tampered packets. It's calculated over the encrypted payload + * and provides a simple but effective way to verify packets are both + * uncorrupted and from the same network (since the checksum is calculated + * after encryption). + * + * Configuration: + * - Define WITH_ESPNOW_BRIDGE to enable this bridge + * - Define WITH_ESPNOW_BRIDGE_SECRET with a string to set the network encryption key + * + * Network Isolation: + * Multiple independent mesh networks can coexist by using different + * WITH_ESPNOW_BRIDGE_SECRET values. Packets encrypted with a different key will + * fail the checksum validation and be discarded. + */ +class ESPNowBridge : public BridgeBase { +private: + static ESPNowBridge *_instance; + static void recv_cb(const uint8_t *mac, const uint8_t *data, int32_t len); + static void send_cb(const uint8_t *mac, esp_now_send_status_t status); + + /** + * ESP-NOW Protocol Structure: + * - ESP-NOW header: 20 bytes (handled by ESP-NOW protocol) + * - ESP-NOW payload: 250 bytes maximum + * Total ESP-NOW packet: 270 bytes + * + * Our Bridge Packet Structure (must fit in ESP-NOW payload): + * - Magic header: 2 bytes + * - Checksum: 2 bytes + * - Available payload: 246 bytes + */ + static const size_t MAX_ESPNOW_PACKET_SIZE = 250; + + /** + * Size constants for packet parsing + */ + static const size_t MAX_PAYLOAD_SIZE = MAX_ESPNOW_PACKET_SIZE - (BRIDGE_MAGIC_SIZE + BRIDGE_CHECKSUM_SIZE); + + /** Buffer for receiving ESP-NOW packets */ + uint8_t _rx_buffer[MAX_ESPNOW_PACKET_SIZE]; + + /** Current position in receive buffer */ + size_t _rx_buffer_pos; + + /** + * Network encryption key from build define + * Must be defined with WITH_ESPNOW_BRIDGE_SECRET + * Used for XOR encryption to isolate different mesh networks + */ + const char *_secret = WITH_ESPNOW_BRIDGE_SECRET; + + /** + * Performs XOR encryption/decryption of data + * + * Uses WITH_ESPNOW_BRIDGE_SECRET as the key in a simple XOR operation. + * The same operation is used for both encryption and decryption. + * While not cryptographically secure, it provides basic network isolation. + * + * @param data Pointer to data to encrypt/decrypt + * @param len Length of data in bytes + */ + void xorCrypt(uint8_t *data, size_t len); + + /** + * ESP-NOW receive callback + * Called by ESP-NOW when a packet is received + * + * @param mac Source MAC address + * @param data Received data + * @param len Length of received data + */ + void onDataRecv(const uint8_t *mac, const uint8_t *data, int32_t len); + + /** + * ESP-NOW send callback + * Called by ESP-NOW after a transmission attempt + * + * @param mac_addr Destination MAC address + * @param status Transmission status + */ + void onDataSent(const uint8_t *mac_addr, esp_now_send_status_t status); + +public: + /** + * Constructs an ESPNowBridge instance + * + * @param mgr PacketManager for allocating and queuing packets + * @param rtc RTCClock for timestamping debug messages + */ + ESPNowBridge(mesh::PacketManager *mgr, mesh::RTCClock *rtc); + + /** + * Initializes the ESP-NOW bridge + * + * - Configures WiFi in station mode + * - Initializes ESP-NOW protocol + * - Registers callbacks + * - Sets up broadcast peer + */ + void begin() override; + + /** + * Main loop handler + * ESP-NOW is callback-based, so this is currently empty + */ + void loop() override; + + /** + * Called when a packet is received via ESP-NOW + * Queues the packet for mesh processing if not seen before + * + * @param packet The received mesh packet + */ + void onPacketReceived(mesh::Packet *packet) override; + + /** + * Called when a packet needs to be transmitted via ESP-NOW + * Encrypts and broadcasts the packet if not seen before + * + * @param packet The mesh packet to transmit + */ + void onPacketTransmitted(mesh::Packet *packet) override; +}; + +#endif diff --git a/src/helpers/bridges/RS232Bridge.cpp b/src/helpers/bridges/RS232Bridge.cpp new file mode 100644 index 00000000..d182aea6 --- /dev/null +++ b/src/helpers/bridges/RS232Bridge.cpp @@ -0,0 +1,147 @@ +#include "RS232Bridge.h" + +#include + +#ifdef WITH_RS232_BRIDGE + +RS232Bridge::RS232Bridge(Stream &serial, mesh::PacketManager *mgr, mesh::RTCClock *rtc) + : BridgeBase(mgr, rtc), _serial(&serial) {} + +void RS232Bridge::begin() { +#if !defined(WITH_RS232_BRIDGE_RX) || !defined(WITH_RS232_BRIDGE_TX) +#error "WITH_RS232_BRIDGE_RX and WITH_RS232_BRIDGE_TX must be defined" +#endif + +#if defined(ESP32) + ((HardwareSerial *)_serial)->setPins(WITH_RS232_BRIDGE_RX, WITH_RS232_BRIDGE_TX); +#elif defined(NRF52_PLATFORM) + ((HardwareSerial *)_serial)->setPins(WITH_RS232_BRIDGE_RX, WITH_RS232_BRIDGE_TX); +#elif defined(RP2040_PLATFORM) + ((SerialUART *)_serial)->setRX(WITH_RS232_BRIDGE_RX); + ((SerialUART *)_serial)->setTX(WITH_RS232_BRIDGE_TX); +#elif defined(STM32_PLATFORM) + ((HardwareSerial *)_serial)->setRx(WITH_RS232_BRIDGE_RX); + ((HardwareSerial *)_serial)->setTx(WITH_RS232_BRIDGE_TX); +#else +#error RS232Bridge was not tested on the current platform +#endif + ((HardwareSerial *)_serial)->begin(115200); +} + +void RS232Bridge::onPacketTransmitted(mesh::Packet *packet) { + // First validate the packet pointer + if (!packet) { +#if MESH_PACKET_LOGGING + Serial.printf("%s: RS232 BRIDGE: TX invalid packet pointer\n", getLogDateTime()); +#endif + return; + } + + if (!_seen_packets.hasSeen(packet)) { + + uint8_t buffer[MAX_SERIAL_PACKET_SIZE]; + uint16_t len = packet->writeTo(buffer + 4); + + // Check if packet fits within our maximum payload size + if (len > (MAX_TRANS_UNIT + 1)) { +#if MESH_PACKET_LOGGING + Serial.printf("%s: RS232 BRIDGE: TX packet too large (payload=%d, max=%d)\n", getLogDateTime(), len, + MAX_TRANS_UNIT + 1); +#endif + return; + } + + // Build packet header + buffer[0] = (BRIDGE_PACKET_MAGIC >> 8) & 0xFF; // Magic high byte + buffer[1] = BRIDGE_PACKET_MAGIC & 0xFF; // Magic low byte + buffer[2] = (len >> 8) & 0xFF; // Length high byte + buffer[3] = len & 0xFF; // Length low byte + + // Calculate checksum over the payload + uint16_t checksum = fletcher16(buffer + 4, len); + buffer[4 + len] = (checksum >> 8) & 0xFF; // Checksum high byte + buffer[5 + len] = checksum & 0xFF; // Checksum low byte + + // Send complete packet + _serial->write(buffer, len + SERIAL_OVERHEAD); + +#if MESH_PACKET_LOGGING + Serial.printf("%s: RS232 BRIDGE: TX, len=%d crc=0x%04x\n", getLogDateTime(), len, checksum); +#endif + } +} + +void RS232Bridge::loop() { + while (_serial->available()) { + uint8_t b = _serial->read(); + + if (_rx_buffer_pos < 2) { + // Waiting for magic word + if ((_rx_buffer_pos == 0 && b == ((BRIDGE_PACKET_MAGIC >> 8) & 0xFF)) || + (_rx_buffer_pos == 1 && b == (BRIDGE_PACKET_MAGIC & 0xFF))) { + _rx_buffer[_rx_buffer_pos++] = b; + } else { + // Invalid magic byte, reset and start over + _rx_buffer_pos = 0; + // Check if this byte could be the start of a new magic word + if (b == ((BRIDGE_PACKET_MAGIC >> 8) & 0xFF)) { + _rx_buffer[_rx_buffer_pos++] = b; + } + } + } else { + // Reading length, payload, and checksum + _rx_buffer[_rx_buffer_pos++] = b; + + if (_rx_buffer_pos >= 4) { + uint16_t len = (_rx_buffer[2] << 8) | _rx_buffer[3]; + + // Validate length field + if (len > (MAX_TRANS_UNIT + 1)) { +#if MESH_PACKET_LOGGING + Serial.printf("%s: RS232 BRIDGE: RX invalid length %d, resetting\n", getLogDateTime(), len); +#endif + _rx_buffer_pos = 0; // Invalid length, reset + continue; + } + + if (_rx_buffer_pos == len + SERIAL_OVERHEAD) { // Full packet received + uint16_t received_checksum = (_rx_buffer[4 + len] << 8) | _rx_buffer[5 + len]; + + if (validateChecksum(_rx_buffer + 4, len, received_checksum)) { +#if MESH_PACKET_LOGGING + Serial.printf("%s: RS232 BRIDGE: RX, len=%d crc=0x%04x\n", getLogDateTime(), len, + received_checksum); +#endif + mesh::Packet *pkt = _mgr->allocNew(); + if (pkt) { + if (pkt->readFrom(_rx_buffer + 4, len)) { + onPacketReceived(pkt); + } else { +#if MESH_PACKET_LOGGING + Serial.printf("%s: RS232 BRIDGE: RX failed to parse packet\n", getLogDateTime()); +#endif + _mgr->free(pkt); + } + } else { +#if MESH_PACKET_LOGGING + Serial.printf("%s: RS232 BRIDGE: RX failed to allocate packet\n", getLogDateTime()); +#endif + } + } else { +#if MESH_PACKET_LOGGING + Serial.printf("%s: RS232 BRIDGE: RX checksum mismatch, rcv=0x%04x\n", getLogDateTime(), + received_checksum); +#endif + } + _rx_buffer_pos = 0; // Reset for next packet + } + } + } + } +} + +void RS232Bridge::onPacketReceived(mesh::Packet *packet) { + handleReceivedPacket(packet); +} + +#endif diff --git a/src/helpers/bridges/RS232Bridge.h b/src/helpers/bridges/RS232Bridge.h new file mode 100644 index 00000000..3b09de75 --- /dev/null +++ b/src/helpers/bridges/RS232Bridge.h @@ -0,0 +1,141 @@ +#pragma once + +#include "helpers/bridges/BridgeBase.h" + +#include + +#ifdef WITH_RS232_BRIDGE + +/** + * @brief Bridge implementation using RS232/UART protocol for packet transport + * + * This bridge enables mesh packet transport over serial/UART connections, + * allowing nodes to communicate over wired serial links. It implements a simple + * packet framing protocol with checksums for reliable transfer. + * + * Features: + * - Point-to-point communication over hardware UART + * - Fletcher-16 checksum for data integrity verification + * - Magic header for packet synchronization and frame alignment + * - Duplicate packet detection using SimpleMeshTables tracking + * - Configurable RX/TX pins via build defines + * - Fixed baud rate at 115200 for consistent timing + * + * Packet Structure: + * [2 bytes] Magic Header (0xC03E) - Used to identify start of RS232Bridge packets + * [2 bytes] Payload Length - Length of the mesh packet payload + * [n bytes] Mesh Packet Payload - The actual mesh packet data + * [2 bytes] Fletcher-16 Checksum - Calculated over the payload for integrity verification + * + * The Fletcher-16 checksum is calculated over the mesh packet payload and provides + * error detection capabilities suitable for serial communication where electrical + * noise, timing issues, or hardware problems could corrupt data. The checksum + * validation ensures only valid packets are forwarded to the mesh. + * + * Configuration: + * - Define WITH_RS232_BRIDGE to enable this bridge + * - Define WITH_RS232_BRIDGE_RX with the RX pin number + * - Define WITH_RS232_BRIDGE_TX with the TX pin number + * + * Platform Support: + * Different platforms require different pin configuration methods: + * - ESP32: Uses HardwareSerial::setPins(rx, tx) + * - NRF52: Uses HardwareSerial::setPins(rx, tx) + * - RP2040: Uses SerialUART::setRX(rx) and SerialUART::setTX(tx) + * - STM32: Uses HardwareSerial::setRx(rx) and HardwareSerial::setTx(tx) + */ +class RS232Bridge : public BridgeBase { +public: + /** + * @brief Constructs an RS232Bridge instance + * + * @param serial The hardware serial port to use + * @param mgr PacketManager for allocating and queuing packets + * @param rtc RTCClock for timestamping debug messages + */ + RS232Bridge(Stream &serial, mesh::PacketManager *mgr, mesh::RTCClock *rtc); + + /** + * Initializes the RS232 bridge + * + * - Validates that RX/TX pins are defined + * - Configures UART pins based on target platform + * - Sets baud rate to 115200 for consistent communication + * - Platform-specific pin configuration methods are used + */ + void begin() override; + + /** + * @brief Main loop handler for processing incoming serial data + * + * Implements a state machine for packet reception: + * 1. Searches for magic header bytes for packet synchronization + * 2. Reads length field to determine expected packet size + * 3. Validates packet length against maximum allowed size + * 4. Receives complete packet payload and checksum + * 5. Validates Fletcher-16 checksum for data integrity + * 6. Creates mesh packet and forwards if valid + */ + void loop() override; + + /** + * @brief Called when a packet needs to be transmitted over serial + * + * Formats the mesh packet with RS232 framing protocol: + * - Adds magic header for synchronization + * - Includes payload length field + * - Calculates Fletcher-16 checksum over payload + * - Transmits complete framed packet + * - Uses duplicate detection to prevent retransmission + * + * @param packet The mesh packet to transmit + */ + void onPacketTransmitted(mesh::Packet *packet) override; + + /** + * @brief Called when a complete valid packet has been received from serial + * + * Forwards the received packet to the mesh for processing. + * The packet has already been validated for checksum integrity + * and parsed successfully at this point. + * + * @param packet The received mesh packet ready for processing + */ + void onPacketReceived(mesh::Packet *packet) override; + +private: + /** + * RS232 Protocol Structure: + * - Magic header: 2 bytes (packet identification) + * - Length field: 2 bytes (payload length) + * - Payload: variable bytes (mesh packet data) + * - Checksum: 2 bytes (Fletcher-16 over payload) + * Total overhead: 6 bytes + */ + + /** + * @brief The total overhead of the serial protocol in bytes. + * Includes: MAGIC_WORD (2) + LENGTH (2) + CHECKSUM (2) = 6 bytes + */ + static constexpr uint16_t SERIAL_OVERHEAD = BRIDGE_MAGIC_SIZE + BRIDGE_LENGTH_SIZE + BRIDGE_CHECKSUM_SIZE; + + /** + * @brief The maximum size of a complete packet on the serial line. + * + * This is calculated as the sum of: + * - MAX_TRANS_UNIT + 1 for the maximum mesh packet size + * - SERIAL_OVERHEAD for the framing (magic + length + checksum) + */ + static constexpr uint16_t MAX_SERIAL_PACKET_SIZE = (MAX_TRANS_UNIT + 1) + SERIAL_OVERHEAD; + + /** Hardware serial port interface */ + Stream *_serial; + + /** Buffer for building received packets */ + uint8_t _rx_buffer[MAX_SERIAL_PACKET_SIZE]; + + /** Current position in the receive buffer */ + uint16_t _rx_buffer_pos = 0; +}; + +#endif diff --git a/src/helpers/nrf52/SerialBLEInterface.cpp b/src/helpers/nrf52/SerialBLEInterface.cpp index 170a7331..4bc9d10a 100644 --- a/src/helpers/nrf52/SerialBLEInterface.cpp +++ b/src/helpers/nrf52/SerialBLEInterface.cpp @@ -27,8 +27,8 @@ void SerialBLEInterface::begin(const char* device_name, uint32_t pin_code) { Bluefruit.configPrphBandwidth(BANDWIDTH_MAX); Bluefruit.configPrphConn(250, BLE_GAP_EVENT_LENGTH_MIN, 16, 16); // increase MTU + Bluefruit.setTxPower(BLE_TX_POWER); Bluefruit.begin(); - Bluefruit.setTxPower(4); // Check bluefruit.h for supported values Bluefruit.setName(device_name); Bluefruit.Security.setMITM(true); @@ -80,7 +80,7 @@ void SerialBLEInterface::startAdv() { * https://developer.apple.com/library/content/qa/qa1931/_index.html */ Bluefruit.Advertising.restartOnDisconnect(false); // don't restart automatically as we handle it in onDisconnect - Bluefruit.Advertising.setInterval(32, 244); // in unit of 0.625 ms + Bluefruit.Advertising.setInterval(32, 1600); Bluefruit.Advertising.setFastTimeout(30); // number of seconds in fast mode Bluefruit.Advertising.start(0); // 0 = Don't stop advertising after n seconds diff --git a/src/helpers/nrf52/SerialBLEInterface.h b/src/helpers/nrf52/SerialBLEInterface.h index 12a4f46a..239cf6c4 100644 --- a/src/helpers/nrf52/SerialBLEInterface.h +++ b/src/helpers/nrf52/SerialBLEInterface.h @@ -3,6 +3,10 @@ #include "../BaseSerialInterface.h" #include +#ifndef BLE_TX_POWER +#define BLE_TX_POWER 4 +#endif + class SerialBLEInterface : public BaseSerialInterface { BLEUart bleuart; bool _isEnabled; diff --git a/src/helpers/sensors/EnvironmentSensorManager.cpp b/src/helpers/sensors/EnvironmentSensorManager.cpp index f444b67b..df08ed78 100644 --- a/src/helpers/sensors/EnvironmentSensorManager.cpp +++ b/src/helpers/sensors/EnvironmentSensorManager.cpp @@ -66,8 +66,8 @@ static Adafruit_INA260 INA260; #endif #if ENV_INCLUDE_INA226 -#define TELEM_INA226_ADDRESS 0x44 -#define TELEM_INA226_SHUNT_VALUE 0.100 +#define TELEM_INA226_ADDRESS 0x44 +#define TELEM_INA226_SHUNT_VALUE 0.100 #define TELEM_INA226_MAX_AMP 0.8 #include static INA226 INA226(TELEM_INA226_ADDRESS); @@ -85,7 +85,11 @@ static Adafruit_MLX90614 MLX90614; static Adafruit_VL53L0X VL53L0X; #endif -#if ENV_INCLUDE_GPS && RAK_BOARD +#if ENV_INCLUDE_GPS && defined(RAK_BOARD) && !defined(RAK_WISMESH_TAG) +#define RAK_WISBLOCK_GPS +#endif + +#ifdef RAK_WISBLOCK_GPS static uint32_t gpsResetPin = 0; static bool i2cGPSFlag = false; static bool serialGPSFlag = false; @@ -96,7 +100,7 @@ static SFE_UBLOX_GNSS ublox_GNSS; bool EnvironmentSensorManager::begin() { #if ENV_INCLUDE_GPS - #if RAK_BOARD + #ifdef RAK_WISBLOCK_GPS rakGPSInit(); //probe base board/sockets for GPS #else initBasicGPS(); @@ -457,7 +461,7 @@ void EnvironmentSensorManager::initBasicGPS() { gps_active = false; //Set GPS visibility off until setting is changed } -#ifdef RAK_BOARD +#ifdef RAK_WISBLOCK_GPS void EnvironmentSensorManager::rakGPSInit(){ Serial1.setPins(PIN_GPS_TX, PIN_GPS_RX); @@ -531,7 +535,7 @@ bool EnvironmentSensorManager::gpsIsAwake(uint8_t ioPin){ void EnvironmentSensorManager::start_gps() { gps_active = true; - #ifdef RAK_BOARD + #ifdef RAK_WISBLOCK_GPS pinMode(gpsResetPin, OUTPUT); digitalWrite(gpsResetPin, HIGH); return; @@ -547,7 +551,7 @@ void EnvironmentSensorManager::start_gps() { void EnvironmentSensorManager::stop_gps() { gps_active = false; - #ifdef RAK_BOARD + #ifdef RAK_WISBLOCK_GPS pinMode(gpsResetPin, OUTPUT); digitalWrite(gpsResetPin, LOW); return; @@ -568,13 +572,7 @@ void EnvironmentSensorManager::loop() { if (millis() > next_gps_update) { if(gps_active){ - #ifndef RAK_BOARD - if (_location->isValid()) { - node_lat = ((double)_location->getLatitude())/1000000.; - node_lon = ((double)_location->getLongitude())/1000000.; - MESH_DEBUG_PRINTLN("lat %f lon %f", node_lat, node_lon); - } - #else + #ifdef RAK_WISBLOCK_GPS if(i2cGPSFlag){ node_lat = ((double)ublox_GNSS.getLatitude())/10000000.; node_lon = ((double)ublox_GNSS.getLongitude())/10000000.; @@ -585,8 +583,12 @@ void EnvironmentSensorManager::loop() { node_lon = ((double)_location->getLongitude())/1000000.; MESH_DEBUG_PRINTLN("lat %f lon %f", node_lat, node_lon); } - //else - //MESH_DEBUG_PRINTLN("No valid GPS data"); + #else + if (_location->isValid()) { + node_lat = ((double)_location->getLatitude())/1000000.; + node_lon = ((double)_location->getLongitude())/1000000.; + MESH_DEBUG_PRINTLN("lat %f lon %f", node_lat, node_lon); + } #endif } next_gps_update = millis() + 1000; diff --git a/variants/t1000-e/NullDisplayDriver.h b/src/helpers/ui/NullDisplayDriver.h similarity index 100% rename from variants/t1000-e/NullDisplayDriver.h rename to src/helpers/ui/NullDisplayDriver.h diff --git a/variants/generic-e22/platformio.ini b/variants/generic-e22/platformio.ini index 8b2c293b..c9a67220 100644 --- a/variants/generic-e22/platformio.ini +++ b/variants/generic-e22/platformio.ini @@ -47,6 +47,53 @@ lib_deps = ${Generic_E22.lib_deps} ${esp32_ota.lib_deps} +; [env:Generic_E22_sx1262_repeater_bridge_rs232] +; extends = Generic_E22 +; build_src_filter = ${Generic_E22.build_src_filter} +; + +; +<../examples/simple_repeater/main.cpp> +; build_flags = +; ${Generic_E22.build_flags} +; -D RADIO_CLASS=CustomSX1262 +; -D WRAPPER_CLASS=CustomSX1262Wrapper +; -D LORA_TX_POWER=22 +; -D ADVERT_NAME='"RS232 Bridge"' +; -D ADVERT_LAT=0.0 +; -D ADVERT_LON=0.0 +; -D ADMIN_PASSWORD='"password"' +; -D MAX_NEIGHBOURS=8 +; -D WITH_RS232_BRIDGE=Serial2 +; -D WITH_RS232_BRIDGE_RX=5 +; -D WITH_RS232_BRIDGE_TX=6 +; ; -D MESH_PACKET_LOGGING=1 +; ; -D MESH_DEBUG=1 +; lib_deps = +; ${Generic_E22.lib_deps} +; ${esp32_ota.lib_deps} + +[env:Generic_E22_sx1262_repeater_bridge_espnow] +extends = Generic_E22 +build_src_filter = ${Generic_E22.build_src_filter} + + + +<../examples/simple_repeater/main.cpp> +build_flags = + ${Generic_E22.build_flags} + -D RADIO_CLASS=CustomSX1262 + -D WRAPPER_CLASS=CustomSX1262Wrapper + -D LORA_TX_POWER=22 + -D ADVERT_NAME='"ESPNow Bridge"' + -D ADVERT_LAT=0.0 + -D ADVERT_LON=0.0 + -D ADMIN_PASSWORD='"password"' + -D MAX_NEIGHBOURS=8 + -D WITH_ESPNOW_BRIDGE=1 + -D WITH_ESPNOW_BRIDGE_SECRET='"shared-secret"' +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +lib_deps = + ${Generic_E22.lib_deps} + ${esp32_ota.lib_deps} + [env:Generic_E22_sx1268_repeater] extends = Generic_E22 build_src_filter = ${Generic_E22.build_src_filter} @@ -66,3 +113,50 @@ build_flags = lib_deps = ${Generic_E22.lib_deps} ${esp32_ota.lib_deps} + +; [env:Generic_E22_sx1268_repeater_bridge_rs232] +; extends = Generic_E22 +; build_src_filter = ${Generic_E22.build_src_filter} +; + +; +<../examples/simple_repeater/main.cpp> +; build_flags = +; ${Generic_E22.build_flags} +; -D RADIO_CLASS=CustomSX1268 +; -D WRAPPER_CLASS=CustomSX1268Wrapper +; -D LORA_TX_POWER=22 +; -D ADVERT_NAME='"RS232 Bridge"' +; -D ADVERT_LAT=0.0 +; -D ADVERT_LON=0.0 +; -D ADMIN_PASSWORD='"password"' +; -D MAX_NEIGHBOURS=8 +; -D WITH_RS232_BRIDGE=Serial2 +; -D WITH_RS232_BRIDGE_RX=5 +; -D WITH_RS232_BRIDGE_TX=6 +; ; -D MESH_PACKET_LOGGING=1 +; ; -D MESH_DEBUG=1 +; lib_deps = +; ${Generic_E22.lib_deps} +; ${esp32_ota.lib_deps} + +[env:Generic_E22_sx1268_repeater_bridge_espnow] +extends = Generic_E22 +build_src_filter = ${Generic_E22.build_src_filter} + + + +<../examples/simple_repeater/main.cpp> +build_flags = + ${Generic_E22.build_flags} + -D RADIO_CLASS=CustomSX1268 + -D WRAPPER_CLASS=CustomSX1268Wrapper + -D LORA_TX_POWER=22 + -D ADVERT_NAME='"ESPNow Bridge"' + -D ADVERT_LAT=0.0 + -D ADVERT_LON=0.0 + -D ADMIN_PASSWORD='"password"' + -D MAX_NEIGHBOURS=8 + -D WITH_ESPNOW_BRIDGE=1 + -D WITH_ESPNOW_BRIDGE_SECRET='"shared-secret"' +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +lib_deps = + ${Generic_E22.lib_deps} + ${esp32_ota.lib_deps} diff --git a/variants/heltec_ct62/platformio.ini b/variants/heltec_ct62/platformio.ini index 0dc512b9..1b83adbf 100644 --- a/variants/heltec_ct62/platformio.ini +++ b/variants/heltec_ct62/platformio.ini @@ -49,6 +49,47 @@ lib_deps = ${Heltec_ct62.lib_deps} ${esp32_ota.lib_deps} +; [env:Heltec_ct62_repeater_bridge_rs232] +; extends = Heltec_ct62 +; build_flags = +; ${Heltec_ct62.build_flags} +; -D ADVERT_NAME='"RS232 Bridge"' +; -D ADVERT_LAT=0.0 +; -D ADVERT_LON=0.0 +; -D ADMIN_PASSWORD='"password"' +; -D MAX_NEIGHBOURS=8 +; -D WITH_RS232_BRIDGE=Serial2 +; -D WITH_RS232_BRIDGE_RX=5 +; -D WITH_RS232_BRIDGE_TX=6 +; ; -D MESH_PACKET_LOGGING=1 +; ; -D MESH_DEBUG=1 +; build_src_filter = ${Heltec_ct62.build_src_filter} +; + +; +<../examples/simple_repeater> +; lib_deps = +; ${Heltec_ct62.lib_deps} +; ${esp32_ota.lib_deps} + +[env:Heltec_ct62_repeater_bridge_espnow] +extends = Heltec_ct62 +build_flags = + ${Heltec_ct62.build_flags} + -D ADVERT_NAME='"ESPNow Bridge"' + -D ADVERT_LAT=0.0 + -D ADVERT_LON=0.0 + -D ADMIN_PASSWORD='"password"' + -D MAX_NEIGHBOURS=8 + -D WITH_ESPNOW_BRIDGE=1 + -D WITH_ESPNOW_BRIDGE_SECRET='"shared-secret"' +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +build_src_filter = ${Heltec_ct62.build_src_filter} + + + +<../examples/simple_repeater> +lib_deps = + ${Heltec_ct62.lib_deps} + ${esp32_ota.lib_deps} + [env:Heltec_ct62_companion_radio_usb] extends = Heltec_ct62 build_flags = diff --git a/variants/heltec_e213/platformio.ini b/variants/heltec_e213/platformio.ini index c8efc819..a6fe2560 100644 --- a/variants/heltec_e213/platformio.ini +++ b/variants/heltec_e213/platformio.ini @@ -93,6 +93,51 @@ lib_deps = ${Heltec_E213_base.lib_deps} ${esp32_ota.lib_deps} +; [env:Heltec_E213_repeater_bridge_rs232] +; extends = Heltec_E213_base +; build_flags = +; ${Heltec_E213_base.build_flags} +; -D DISPLAY_CLASS=E213Display +; -D ADVERT_NAME='"RS232 Bridge"' +; -D ADVERT_LAT=0.0 +; -D ADVERT_LON=0.0 +; -D ADMIN_PASSWORD='"password"' +; -D MAX_NEIGHBOURS=8 +; -D WITH_RS232_BRIDGE=Serial2 +; -D WITH_RS232_BRIDGE_RX=5 +; -D WITH_RS232_BRIDGE_TX=6 +; ; -D MESH_PACKET_LOGGING=1 +; ; -D MESH_DEBUG=1 +; build_src_filter = ${Heltec_E213_base.build_src_filter} +; + +; + +; +<../examples/simple_repeater> +; lib_deps = +; ${Heltec_E213_base.lib_deps} +; ${esp32_ota.lib_deps} + +[env:Heltec_E213_repeater_bridge_espnow] +extends = Heltec_E213_base +build_flags = + ${Heltec_E213_base.build_flags} + -D DISPLAY_CLASS=E213Display + -D ADVERT_NAME='"ESPNow Bridge"' + -D ADVERT_LAT=0.0 + -D ADVERT_LON=0.0 + -D ADMIN_PASSWORD='"password"' + -D MAX_NEIGHBOURS=8 + -D WITH_ESPNOW_BRIDGE=1 + -D WITH_ESPNOW_BRIDGE_SECRET='"shared-secret"' +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +build_src_filter = ${Heltec_E213_base.build_src_filter} + + + + + +<../examples/simple_repeater> +lib_deps = + ${Heltec_E213_base.lib_deps} + ${esp32_ota.lib_deps} + [env:Heltec_E213_room_server] extends = Heltec_E213_base build_flags = diff --git a/variants/heltec_e290/platformio.ini b/variants/heltec_e290/platformio.ini index 377162f4..0223b30c 100644 --- a/variants/heltec_e290/platformio.ini +++ b/variants/heltec_e290/platformio.ini @@ -89,6 +89,51 @@ lib_deps = ${Heltec_E290_base.lib_deps} ${esp32_ota.lib_deps} +; [env:Heltec_E290_repeater_bridge_rs232] +; extends = Heltec_E290_base +; build_flags = +; ${Heltec_E290_base.build_flags} +; -D DISPLAY_CLASS=E290Display +; -D ADVERT_NAME='"RS232 Bridge"' +; -D ADVERT_LAT=0.0 +; -D ADVERT_LON=0.0 +; -D ADMIN_PASSWORD='"password"' +; -D MAX_NEIGHBOURS=8 +; -D WITH_RS232_BRIDGE=Serial2 +; -D WITH_RS232_BRIDGE_RX=5 +; -D WITH_RS232_BRIDGE_TX=6 +; ; -D MESH_PACKET_LOGGING=1 +; ; -D MESH_DEBUG=1 +; build_src_filter = ${Heltec_E290_base.build_src_filter} +; + +; + +; +<../examples/simple_repeater> +; lib_deps = +; ${Heltec_E290_base.lib_deps} +; ${esp32_ota.lib_deps} + +[env:Heltec_E290_repeater_bridge_espnow] +extends = Heltec_E290_base +build_flags = + ${Heltec_E290_base.build_flags} + -D DISPLAY_CLASS=E290Display + -D ADVERT_NAME='"ESPNow Bridge"' + -D ADVERT_LAT=0.0 + -D ADVERT_LON=0.0 + -D ADMIN_PASSWORD='"password"' + -D MAX_NEIGHBOURS=8 + -D WITH_ESPNOW_BRIDGE=1 + -D WITH_ESPNOW_BRIDGE_SECRET='"shared-secret"' +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +build_src_filter = ${Heltec_E290_base.build_src_filter} + + + + + +<../examples/simple_repeater> +lib_deps = + ${Heltec_E290_base.lib_deps} + ${esp32_ota.lib_deps} + [env:Heltec_E290_room_server] extends = Heltec_E290_base build_flags = diff --git a/variants/heltec_mesh_solar/platformio.ini b/variants/heltec_mesh_solar/platformio.ini index 9fd3edd5..18c4ac73 100644 --- a/variants/heltec_mesh_solar/platformio.ini +++ b/variants/heltec_mesh_solar/platformio.ini @@ -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 diff --git a/variants/heltec_t114/platformio.ini b/variants/heltec_t114/platformio.ini index 2cac2eae..dec3282d 100644 --- a/variants/heltec_t114/platformio.ini +++ b/variants/heltec_t114/platformio.ini @@ -1,3 +1,6 @@ +; +; Heltec T114 without display +; [Heltec_t114] extends = nrf52_base board = heltec_t114 @@ -24,15 +27,11 @@ build_flags = ${nrf52_base.build_flags} -D SX126X_DIO3_TCXO_VOLTAGE=1.8 -D SX126X_CURRENT_LIMIT=140 -D SX126X_RX_BOOSTED_GAIN=1 + -D DISPLAY_CLASS=NullDisplayDriver -D ST7789 - -D DISPLAY_CLASS=ST7789Display build_src_filter = ${nrf52_base.build_src_filter} + +<../variants/heltec_t114> - + - + - + - + lib_deps = ${nrf52_base.lib_deps} stevemarple/MicroNMEA @ ^2.0.6 @@ -40,7 +39,7 @@ lib_deps = debug_tool = jlink upload_protocol = nrfutil -[env:Heltec_t114_repeater] +[env:Heltec_t114_without_display_repeater] extends = Heltec_t114 build_src_filter = ${Heltec_t114.build_src_filter} +<../examples/simple_repeater> @@ -55,7 +54,7 @@ build_flags = ; -D MESH_PACKET_LOGGING=1 ; -D MESH_DEBUG=1 -[env:Heltec_t114_room_server] +[env:Heltec_t114_without_display_room_server] extends = Heltec_t114 build_src_filter = ${Heltec_t114.build_src_filter} +<../examples/simple_room_server> @@ -69,13 +68,13 @@ build_flags = ; -D MESH_PACKET_LOGGING=1 ; -D MESH_DEBUG=1 -[env:Heltec_t114_companion_radio_ble] +[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=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 @@ -89,13 +88,13 @@ lib_deps = ${Heltec_t114.lib_deps} densaugeo/base64 @ ~1.4.0 -[env:Heltec_t114_companion_radio_usb] +[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=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 @@ -106,4 +105,92 @@ build_src_filter = ${Heltec_t114.build_src_filter} +<../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} + + + + + + + + +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=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_with_display.build_src_filter} + + + +<../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=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_with_display.build_src_filter} + + + +<../examples/companion_radio/*.cpp> + +<../examples/companion_radio/ui-new/*.cpp> +lib_deps = + ${Heltec_t114_with_display.lib_deps} densaugeo/base64 @ ~1.4.0 \ No newline at end of file diff --git a/variants/heltec_t114/target.h b/variants/heltec_t114/target.h index 053a7c44..1876aadc 100644 --- a/variants/heltec_t114/target.h +++ b/variants/heltec_t114/target.h @@ -8,9 +8,14 @@ #include #include #include + #ifdef DISPLAY_CLASS - #include - #include +#include +#ifdef HELTEC_T114_WITH_DISPLAY +#include +#else +#include "helpers/ui/NullDisplayDriver.h" +#endif #endif class T114SensorManager : public SensorManager { diff --git a/variants/heltec_t190/platformio.ini b/variants/heltec_t190/platformio.ini index 7debe178..52bb79e0 100644 --- a/variants/heltec_t190/platformio.ini +++ b/variants/heltec_t190/platformio.ini @@ -94,6 +94,47 @@ lib_deps = ${Heltec_T190_base.lib_deps} ${esp32_ota.lib_deps} +; [env:Heltec_T190_repeater_bridge_rs232] +; extends = Heltec_T190_base +; build_flags = +; ${Heltec_T190_base.build_flags} +; -D ADVERT_NAME='"RS232 Bridge"' +; -D ADVERT_LAT=0.0 +; -D ADVERT_LON=0.0 +; -D ADMIN_PASSWORD='"password"' +; -D MAX_NEIGHBOURS=8 +; -D WITH_RS232_BRIDGE=Serial2 +; -D WITH_RS232_BRIDGE_RX=5 +; -D WITH_RS232_BRIDGE_TX=6 +; ; -D MESH_PACKET_LOGGING=1 +; ; -D MESH_DEBUG=1 +; build_src_filter = ${Heltec_T190_base.build_src_filter} +; + +; +<../examples/simple_repeater> +; lib_deps = +; ${Heltec_T190_base.lib_deps} +; ${esp32_ota.lib_deps} + +[env:Heltec_T190_repeater_bridge_espnow] +extends = Heltec_T190_base +build_flags = + ${Heltec_T190_base.build_flags} + -D ADVERT_NAME='"ESPNow Bridge"' + -D ADVERT_LAT=0.0 + -D ADVERT_LON=0.0 + -D ADMIN_PASSWORD='"password"' + -D MAX_NEIGHBOURS=8 + -D WITH_ESPNOW_BRIDGE=1 + -D WITH_ESPNOW_BRIDGE_SECRET='"shared-secret"' +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +build_src_filter = ${Heltec_T190_base.build_src_filter} + + + +<../examples/simple_repeater> +lib_deps = + ${Heltec_T190_base.lib_deps} + ${esp32_ota.lib_deps} + [env:Heltec_T190_room_server] extends = Heltec_T190_base build_flags = diff --git a/variants/heltec_tracker/platformio.ini b/variants/heltec_tracker/platformio.ini index f1477e9f..5c0df007 100644 --- a/variants/heltec_tracker/platformio.ini +++ b/variants/heltec_tracker/platformio.ini @@ -80,6 +80,53 @@ lib_deps = ${Heltec_tracker_base.lib_deps} ${esp32_ota.lib_deps} +; [env:Heltec_Wireless_Tracker_repeater_bridge_rs232] +; extends = Heltec_tracker_base +; build_flags = +; ${Heltec_tracker_base.build_flags} +; -D DISPLAY_ROTATION=1 +; -D DISPLAY_CLASS=ST7735Display +; -D ADVERT_NAME='"RS232 Bridge"' +; -D ADVERT_LAT=0.0 +; -D ADVERT_LON=0.0 +; -D ADMIN_PASSWORD='"password"' +; -D MAX_NEIGHBOURS=8 +; -D WITH_RS232_BRIDGE=Serial2 +; -D WITH_RS232_BRIDGE_RX=5 +; -D WITH_RS232_BRIDGE_TX=6 +; ; -D MESH_PACKET_LOGGING=1 +; ; -D MESH_DEBUG=1 +; build_src_filter = ${Heltec_tracker_base.build_src_filter} +; + +; + +; +<../examples/simple_repeater> +; lib_deps = +; ${Heltec_tracker_base.lib_deps} +; ${esp32_ota.lib_deps} + +[env:Heltec_Wireless_Tracker_repeater_bridge_espnow] +extends = Heltec_tracker_base +build_flags = + ${Heltec_tracker_base.build_flags} + -D DISPLAY_ROTATION=1 + -D DISPLAY_CLASS=ST7735Display + -D ADVERT_NAME='"ESPNow Bridge"' + -D ADVERT_LAT=0.0 + -D ADVERT_LON=0.0 + -D ADMIN_PASSWORD='"password"' + -D MAX_NEIGHBOURS=8 + -D WITH_ESPNOW_BRIDGE=1 + -D WITH_ESPNOW_BRIDGE_SECRET='"shared-secret"' +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +build_src_filter = ${Heltec_tracker_base.build_src_filter} + + + + + +<../examples/simple_repeater> +lib_deps = + ${Heltec_tracker_base.lib_deps} + ${esp32_ota.lib_deps} + [env:Heltec_Wireless_Tracker_room_server] extends = Heltec_tracker_base build_flags = diff --git a/variants/heltec_v2/platformio.ini b/variants/heltec_v2/platformio.ini index 352ea34d..d2afe4db 100644 --- a/variants/heltec_v2/platformio.ini +++ b/variants/heltec_v2/platformio.ini @@ -40,6 +40,53 @@ lib_deps = ${Heltec_lora32_v2.lib_deps} ${esp32_ota.lib_deps} +; [env:Heltec_v2_repeater_bridge_rs232] +; extends = Heltec_lora32_v2 +; build_flags = +; ${Heltec_lora32_v2.build_flags} +; -D DISPLAY_CLASS=SSD1306Display +; -D ADVERT_NAME='"RS232 Bridge"' +; -D ADVERT_LAT=0.0 +; -D ADVERT_LON=0.0 +; -D ADMIN_PASSWORD='"password"' +; -D MAX_NEIGHBOURS=8 +; -D WITH_RS232_BRIDGE=Serial2 +; -D WITH_RS232_BRIDGE_RX=5 +; -D WITH_RS232_BRIDGE_TX=6 +; ; -D MESH_PACKET_LOGGING=1 +; ; -D MESH_DEBUG=1 +; build_src_filter = ${Heltec_lora32_v2.build_src_filter} +; + +; + +; + +; +<../examples/simple_repeater> +; lib_deps = +; ${Heltec_lora32_v2.lib_deps} +; ${esp32_ota.lib_deps} + +[env:Heltec_v2_repeater_bridge_espnow] +extends = Heltec_lora32_v2 +build_flags = + ${Heltec_lora32_v2.build_flags} + -D DISPLAY_CLASS=SSD1306Display + -D ADVERT_NAME='"ESPNow Bridge"' + -D ADVERT_LAT=0.0 + -D ADVERT_LON=0.0 + -D ADMIN_PASSWORD='"password"' + -D MAX_NEIGHBOURS=8 + -D WITH_ESPNOW_BRIDGE=1 + -D WITH_ESPNOW_BRIDGE_SECRET='"shared-secret"' +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +build_src_filter = ${Heltec_lora32_v2.build_src_filter} + + + + + + + +<../examples/simple_repeater> +lib_deps = + ${Heltec_lora32_v2.lib_deps} + ${esp32_ota.lib_deps} + [env:Heltec_v2_room_server] extends = Heltec_lora32_v2 build_flags = diff --git a/variants/heltec_v3/platformio.ini b/variants/heltec_v3/platformio.ini index 2e7ac80c..417f6edb 100644 --- a/variants/heltec_v3/platformio.ini +++ b/variants/heltec_v3/platformio.ini @@ -49,6 +49,51 @@ lib_deps = ${esp32_ota.lib_deps} bakercp/CRC32 @ ^2.0.0 +[env:Heltec_v3_repeater_bridge_rs232] +extends = Heltec_lora32_v3 +build_flags = + ${Heltec_lora32_v3.build_flags} + -D DISPLAY_CLASS=SSD1306Display + -D ADVERT_NAME='"RS232 Bridge"' + -D ADVERT_LAT=0.0 + -D ADVERT_LON=0.0 + -D ADMIN_PASSWORD='"password"' + -D MAX_NEIGHBOURS=8 + -D WITH_RS232_BRIDGE=Serial2 + -D WITH_RS232_BRIDGE_RX=5 + -D WITH_RS232_BRIDGE_TX=6 +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +build_src_filter = ${Heltec_lora32_v3.build_src_filter} + + + + + +<../examples/simple_repeater> +lib_deps = + ${Heltec_lora32_v3.lib_deps} + ${esp32_ota.lib_deps} + +[env:Heltec_v3_repeater_bridge_espnow] +extends = Heltec_lora32_v3 +build_flags = + ${Heltec_lora32_v3.build_flags} + -D DISPLAY_CLASS=SSD1306Display + -D ADVERT_NAME='"ESPNow Bridge"' + -D ADVERT_LAT=0.0 + -D ADVERT_LON=0.0 + -D ADMIN_PASSWORD='"password"' + -D MAX_NEIGHBOURS=8 + -D WITH_ESPNOW_BRIDGE=1 + -D WITH_ESPNOW_BRIDGE_SECRET='"shared-secret"' +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +build_src_filter = ${Heltec_lora32_v3.build_src_filter} + + + + + +<../examples/simple_repeater> +lib_deps = + ${Heltec_lora32_v3.lib_deps} + ${esp32_ota.lib_deps} + [env:Heltec_v3_room_server] extends = Heltec_lora32_v3 build_flags = @@ -186,6 +231,49 @@ lib_deps = ${esp32_ota.lib_deps} bakercp/CRC32 @ ^2.0.0 +[env:Heltec_WSL3_repeater_bridge_rs232] +extends = Heltec_lora32_v3 +build_flags = + ${Heltec_lora32_v3.build_flags} + -D ADVERT_NAME='"RS232 Bridge"' + -D ADVERT_LAT=0.0 + -D ADVERT_LON=0.0 + -D ADMIN_PASSWORD='"password"' + -D MAX_NEIGHBOURS=8 + -D WITH_RS232_BRIDGE=Serial2 + -D WITH_RS232_BRIDGE_RX=5 + -D WITH_RS232_BRIDGE_TX=6 +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +build_src_filter = ${Heltec_lora32_v3.build_src_filter} + + + +<../examples/simple_repeater> +lib_deps = + ${Heltec_lora32_v3.lib_deps} + ${esp32_ota.lib_deps} + bakercp/CRC32 @ ^2.0.0 + +[env:Heltec_WSL3_repeater_bridge_espnow] +extends = Heltec_lora32_v3 +build_flags = + ${Heltec_lora32_v3.build_flags} + -D ADVERT_NAME='"ESPNow Bridge"' + -D ADVERT_LAT=0.0 + -D ADVERT_LON=0.0 + -D ADMIN_PASSWORD='"password"' + -D MAX_NEIGHBOURS=8 + -D WITH_ESPNOW_BRIDGE=1 + -D WITH_ESPNOW_BRIDGE_SECRET='"shared-secret"' +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +build_src_filter = ${Heltec_lora32_v3.build_src_filter} + + + +<../examples/simple_repeater> +lib_deps = + ${Heltec_lora32_v3.lib_deps} + ${esp32_ota.lib_deps} + bakercp/CRC32 @ ^2.0.0 + [env:Heltec_WSL3_room_server] extends = Heltec_lora32_v3 build_src_filter = ${Heltec_lora32_v3.build_src_filter} diff --git a/variants/heltec_wireless_paper/platformio.ini b/variants/heltec_wireless_paper/platformio.ini index 8de826e4..43ac2a82 100644 --- a/variants/heltec_wireless_paper/platformio.ini +++ b/variants/heltec_wireless_paper/platformio.ini @@ -68,6 +68,51 @@ lib_deps = ${Heltec_Wireless_Paper_base.lib_deps} ${esp32_ota.lib_deps} +; [env:Heltec_Wireless_Paper_repeater_bridge_rs232] +; extends = Heltec_Wireless_Paper_base +; build_flags = +; ${Heltec_Wireless_Paper_base.build_flags} +; -D DISPLAY_CLASS=E213Display +; -D ADVERT_NAME='"RS232 Bridge"' +; -D ADVERT_LAT=0.0 +; -D ADVERT_LON=0.0 +; -D ADMIN_PASSWORD='"password"' +; -D MAX_NEIGHBOURS=8 +; -D WITH_RS232_BRIDGE=Serial2 +; -D WITH_RS232_BRIDGE_RX=5 +; -D WITH_RS232_BRIDGE_TX=6 +; ; -D MESH_PACKET_LOGGING=1 +; ; -D MESH_DEBUG=1 +; build_src_filter = ${Heltec_Wireless_Paper_base.build_src_filter} +; + +; + +; +<../examples/simple_repeater> +; lib_deps = +; ${Heltec_Wireless_Paper_base.lib_deps} +; ${esp32_ota.lib_deps} + +[env:Heltec_Wireless_Paper_repeater_bridge_espnow] +extends = Heltec_Wireless_Paper_base +build_flags = + ${Heltec_Wireless_Paper_base.build_flags} + -D DISPLAY_CLASS=E213Display + -D ADVERT_NAME='"ESPNow Bridge"' + -D ADVERT_LAT=0.0 + -D ADVERT_LON=0.0 + -D ADMIN_PASSWORD='"password"' + -D MAX_NEIGHBOURS=8 + -D WITH_ESPNOW_BRIDGE=1 + -D WITH_ESPNOW_BRIDGE_SECRET='"shared-secret"' +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +build_src_filter = ${Heltec_Wireless_Paper_base.build_src_filter} + + + + + +<../examples/simple_repeater> +lib_deps = + ${Heltec_Wireless_Paper_base.lib_deps} + ${esp32_ota.lib_deps} + [env:Heltec_Wireless_Paper_room_server] extends = Heltec_Wireless_Paper_base build_flags = diff --git a/variants/ikoka_stick_nrf/platformio.ini b/variants/ikoka_stick_nrf/platformio.ini index 6e6ae101..1f2bbfe9 100644 --- a/variants/ikoka_stick_nrf/platformio.ini +++ b/variants/ikoka_stick_nrf/platformio.ini @@ -103,8 +103,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 @@ -123,8 +123,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 diff --git a/variants/lilygo_t3s3/platformio.ini b/variants/lilygo_t3s3/platformio.ini index 637cc123..ca221108 100644 --- a/variants/lilygo_t3s3/platformio.ini +++ b/variants/lilygo_t3s3/platformio.ini @@ -52,6 +52,51 @@ lib_deps = ${LilyGo_T3S3_sx1262.lib_deps} ${esp32_ota.lib_deps} +; [env:LilyGo_T3S3_sx1262_Repeater_bridge_rs232] +; extends = LilyGo_T3S3_sx1262 +; build_flags = +; ${LilyGo_T3S3_sx1262.build_flags} +; -D DISPLAY_CLASS=SSD1306Display +; -D ADVERT_NAME='"RS232 Bridge"' +; -D ADVERT_LAT=0.0 +; -D ADVERT_LON=0.0 +; -D ADMIN_PASSWORD='"password"' +; -D MAX_NEIGHBOURS=8 +; -D WITH_RS232_BRIDGE=Serial2 +; -D WITH_RS232_BRIDGE_RX=5 +; -D WITH_RS232_BRIDGE_TX=6 +; ; -D MESH_PACKET_LOGGING=1 +; ; -D MESH_DEBUG=1 +; build_src_filter = ${LilyGo_T3S3_sx1262.build_src_filter} +; + +; + +; +<../examples/simple_repeater> +; lib_deps = +; ${LilyGo_T3S3_sx1262.lib_deps} +; ${esp32_ota.lib_deps} + +[env:LilyGo_T3S3_sx1262_Repeater_bridge_espnow] +extends = LilyGo_T3S3_sx1262 +build_flags = + ${LilyGo_T3S3_sx1262.build_flags} + -D DISPLAY_CLASS=SSD1306Display + -D ADVERT_NAME='"ESPNow Bridge"' + -D ADVERT_LAT=0.0 + -D ADVERT_LON=0.0 + -D ADMIN_PASSWORD='"password"' + -D MAX_NEIGHBOURS=8 + -D WITH_ESPNOW_BRIDGE=1 + -D WITH_ESPNOW_BRIDGE_SECRET='"shared-secret"' +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +build_src_filter = ${LilyGo_T3S3_sx1262.build_src_filter} + + + + + +<../examples/simple_repeater> +lib_deps = + ${LilyGo_T3S3_sx1262.lib_deps} + ${esp32_ota.lib_deps} + [env:LilyGo_T3S3_sx1262_terminal_chat] extends = LilyGo_T3S3_sx1262 build_flags = diff --git a/variants/lilygo_t3s3_sx1276/platformio.ini b/variants/lilygo_t3s3_sx1276/platformio.ini index 23c58fb8..1c0d5cf1 100644 --- a/variants/lilygo_t3s3_sx1276/platformio.ini +++ b/variants/lilygo_t3s3_sx1276/platformio.ini @@ -50,6 +50,51 @@ lib_deps = ${LilyGo_T3S3_sx1276.lib_deps} ${esp32_ota.lib_deps} +; [env:LilyGo_T3S3_sx1276_Repeater_bridge_rs232] +; extends = LilyGo_T3S3_sx1276 +; build_flags = +; ${LilyGo_T3S3_sx1276.build_flags} +; -D DISPLAY_CLASS=SSD1306Display +; -D ADVERT_NAME='"RS232 Bridge"' +; -D ADVERT_LAT=0.0 +; -D ADVERT_LON=0.0 +; -D ADMIN_PASSWORD='"password"' +; -D MAX_NEIGHBOURS=8 +; -D WITH_RS232_BRIDGE=Serial2 +; -D WITH_RS232_BRIDGE_RX=5 +; -D WITH_RS232_BRIDGE_TX=6 +; ; -D MESH_PACKET_LOGGING=1 +; ; -D MESH_DEBUG=1 +; build_src_filter = ${LilyGo_T3S3_sx1276.build_src_filter} +; + +; + +; +<../examples/simple_repeater> +; lib_deps = +; ${LilyGo_T3S3_sx1276.lib_deps} +; ${esp32_ota.lib_deps} + +[env:LilyGo_T3S3_sx1276_Repeater_bridge_espnow] +extends = LilyGo_T3S3_sx1276 +build_flags = + ${LilyGo_T3S3_sx1276.build_flags} + -D DISPLAY_CLASS=SSD1306Display + -D ADVERT_NAME='"ESPNow Bridge"' + -D ADVERT_LAT=0.0 + -D ADVERT_LON=0.0 + -D ADMIN_PASSWORD='"password"' + -D MAX_NEIGHBOURS=8 + -D WITH_ESPNOW_BRIDGE=1 + -D WITH_ESPNOW_BRIDGE_SECRET='"shared-secret"' + ; -D MESH_PACKET_LOGGING=1 + ; -D MESH_DEBUG=1 +build_src_filter = ${LilyGo_T3S3_sx1276.build_src_filter} + + + + + +<../examples/simple_repeater> +lib_deps = + ${LilyGo_T3S3_sx1276.lib_deps} + ${esp32_ota.lib_deps} + [env:LilyGo_T3S3_sx1276_terminal_chat] extends = LilyGo_T3S3_sx1276 build_flags = diff --git a/variants/lilygo_tbeam_SX1262/platformio.ini b/variants/lilygo_tbeam_SX1262/platformio.ini index ea8872de..f7d1a764 100644 --- a/variants/lilygo_tbeam_SX1262/platformio.ini +++ b/variants/lilygo_tbeam_SX1262/platformio.ini @@ -74,6 +74,47 @@ lib_deps = ${LilyGo_TBeam_SX1262.lib_deps} ${esp32_ota.lib_deps} +; [env:Tbeam_SX1262_repeater_bridge_rs232] +; extends = LilyGo_TBeam_SX1262 +; build_flags = +; ${LilyGo_TBeam_SX1262.build_flags} +; -D ADVERT_NAME='"RS232 Bridge"' +; -D ADVERT_LAT=0.0 +; -D ADVERT_LON=0.0 +; -D ADMIN_PASSWORD='"password"' +; -D MAX_NEIGHBOURS=8 +; -D WITH_RS232_BRIDGE=Serial2 +; -D WITH_RS232_BRIDGE_RX=5 +; -D WITH_RS232_BRIDGE_TX=6 +; ; -D MESH_PACKET_LOGGING=1 +; ; -D MESH_DEBUG=1 +; build_src_filter = ${LilyGo_TBeam_SX1262.build_src_filter} +; + +; +<../examples/simple_repeater> +; lib_deps = +; ${LilyGo_TBeam_SX1262.lib_deps} +; ${esp32_ota.lib_deps} + +[env:Tbeam_SX1262_repeater_bridge_espnow] +extends = LilyGo_TBeam_SX1262 +build_flags = + ${LilyGo_TBeam_SX1262.build_flags} + -D ADVERT_NAME='"ESPNow Bridge"' + -D ADVERT_LAT=0.0 + -D ADVERT_LON=0.0 + -D ADMIN_PASSWORD='"password"' + -D MAX_NEIGHBOURS=8 + -D WITH_ESPNOW_BRIDGE=1 + -D WITH_ESPNOW_BRIDGE_SECRET='"shared-secret"' +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +build_src_filter = ${LilyGo_TBeam_SX1262.build_src_filter} + + + +<../examples/simple_repeater> +lib_deps = + ${LilyGo_TBeam_SX1262.lib_deps} + ${esp32_ota.lib_deps} + [env:Tbeam_SX1262_room_server] extends = LilyGo_TBeam_SX1262 build_flags = diff --git a/variants/lilygo_tbeam_SX1276/platformio.ini b/variants/lilygo_tbeam_SX1276/platformio.ini index 782b74c7..d7e119ef 100644 --- a/variants/lilygo_tbeam_SX1276/platformio.ini +++ b/variants/lilygo_tbeam_SX1276/platformio.ini @@ -72,6 +72,49 @@ lib_deps = ${LilyGo_TBeam_SX1276.lib_deps} ${esp32_ota.lib_deps} +; [env:Tbeam_SX1276_repeater_bridge_rs232] +; extends = LilyGo_TBeam_SX1276 +; build_flags = +; ${LilyGo_TBeam_SX1276.build_flags} +; -D ADVERT_NAME='"RS232 Bridge"' +; -D ADVERT_LAT=0.0 +; -D ADVERT_LON=0.0 +; -D ADMIN_PASSWORD='"password"' +; -D MAX_NEIGHBOURS=8 +; -D PERSISTANT_GPS=1 +; -D WITH_RS232_BRIDGE=Serial2 +; -D WITH_RS232_BRIDGE_RX=5 +; -D WITH_RS232_BRIDGE_TX=6 +; ; -D MESH_PACKET_LOGGING=1 +; ; -D MESH_DEBUG=1 +; build_src_filter = ${LilyGo_TBeam_SX1276.build_src_filter} +; + +; +<../examples/simple_repeater> +; lib_deps = +; ${LilyGo_TBeam_SX1276.lib_deps} +; ${esp32_ota.lib_deps} + +[env:Tbeam_SX1276_repeater_bridge_espnow] +extends = LilyGo_TBeam_SX1276 +build_flags = + ${LilyGo_TBeam_SX1276.build_flags} + -D ADVERT_NAME='"ESPNow Bridge"' + -D ADVERT_LAT=0.0 + -D ADVERT_LON=0.0 + -D ADMIN_PASSWORD='"password"' + -D MAX_NEIGHBOURS=8 + -D PERSISTANT_GPS=1 + -D WITH_ESPNOW_BRIDGE=1 + -D WITH_ESPNOW_BRIDGE_SECRET='"shared-secret"' +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +build_src_filter = ${LilyGo_TBeam_SX1276.build_src_filter} + + + +<../examples/simple_repeater> +lib_deps = + ${LilyGo_TBeam_SX1276.lib_deps} + ${esp32_ota.lib_deps} + [env:Tbeam_SX1276_room_server] extends = LilyGo_TBeam_SX1276 build_flags = diff --git a/variants/lilygo_tbeam_supreme_SX1262/platformio.ini b/variants/lilygo_tbeam_supreme_SX1262/platformio.ini index e6135872..328ebf07 100644 --- a/variants/lilygo_tbeam_supreme_SX1262/platformio.ini +++ b/variants/lilygo_tbeam_supreme_SX1262/platformio.ini @@ -52,6 +52,47 @@ lib_deps = ${T_Beam_S3_Supreme_SX1262.lib_deps} ${esp32_ota.lib_deps} +; [env:T_Beam_S3_Supreme_SX1262_repeater_bridge_rs232] +; extends = T_Beam_S3_Supreme_SX1262 +; build_flags = +; ${T_Beam_S3_Supreme_SX1262.build_flags} +; -D ADVERT_NAME='"RS232 Bridge"' +; -D ADVERT_LAT=0 +; -D ADVERT_LON=0 +; -D ADMIN_PASSWORD='"password"' +; -D MAX_NEIGHBOURS=8 +; -D WITH_RS232_BRIDGE=Serial2 +; -D WITH_RS232_BRIDGE_RX=5 +; -D WITH_RS232_BRIDGE_TX=6 +; ; -D MESH_PACKET_LOGGING=1 +; ; -D MESH_DEBUG=1 +; build_src_filter = ${T_Beam_S3_Supreme_SX1262.build_src_filter} +; + +; +<../examples/simple_repeater> +; lib_deps = +; ${T_Beam_S3_Supreme_SX1262.lib_deps} +; ${esp32_ota.lib_deps} + +[env:T_Beam_S3_Supreme_SX1262_repeater_bridge_espnow] +extends = T_Beam_S3_Supreme_SX1262 +build_flags = + ${T_Beam_S3_Supreme_SX1262.build_flags} + -D ADVERT_NAME='"ESPNow Bridge"' + -D ADVERT_LAT=0 + -D ADVERT_LON=0 + -D ADMIN_PASSWORD='"password"' + -D MAX_NEIGHBOURS=8 + -D WITH_ESPNOW_BRIDGE=1 + -D WITH_ESPNOW_BRIDGE_SECRET='"shared-secret"' +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +build_src_filter = ${T_Beam_S3_Supreme_SX1262.build_src_filter} + + + +<../examples/simple_repeater> +lib_deps = + ${T_Beam_S3_Supreme_SX1262.lib_deps} + ${esp32_ota.lib_deps} + [env:T_Beam_S3_Supreme_SX1262_room_server] extends = T_Beam_S3_Supreme_SX1262 build_flags = diff --git a/src/helpers/nrf52/TechoBoard.cpp b/variants/lilygo_techo/TechoBoard.cpp similarity index 100% rename from src/helpers/nrf52/TechoBoard.cpp rename to variants/lilygo_techo/TechoBoard.cpp diff --git a/src/helpers/nrf52/TechoBoard.h b/variants/lilygo_techo/TechoBoard.h similarity index 78% rename from src/helpers/nrf52/TechoBoard.h rename to variants/lilygo_techo/TechoBoard.h index 2c05c4ed..4792153a 100644 --- a/src/helpers/nrf52/TechoBoard.h +++ b/variants/lilygo_techo/TechoBoard.h @@ -3,19 +3,6 @@ #include #include -// 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 diff --git a/variants/techo/platformio.ini b/variants/lilygo_techo/platformio.ini similarity index 57% rename from variants/techo/platformio.ini rename to variants/lilygo_techo/platformio.ini index 812baa78..7d64fad7 100644 --- a/variants/techo/platformio.ini +++ b/variants/lilygo_techo/platformio.ini @@ -1,24 +1,26 @@ -[nrf52840_techo] +[LilyGo_T-Echo] extends = nrf52_base -platform_packages = framework-arduinoadafruitnrf52 +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 -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 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 @@ -28,23 +30,31 @@ build_flags = ${nrf52840_techo.build_flags} -D GPS_BAUD_RATE=9600 -D PIN_GPS_EN=GPS_EN -D TELEM_BME280_ADDRESS=0x77 -build_src_filter = ${nrf52840_techo.build_src_filter} + -D DISPLAY_CLASS=GxEPDDisplay + -D BACKLIGHT_BTN=PIN_BUTTON2 + -D AUTO_OFF_MILLIS=0 +build_src_filter = ${nrf52_base.build_src_filter} + - + + + + - +<../variants/techo> + + + + + +<../variants/lilygo_techo> lib_deps = - ${nrf52840_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_Techo -build_src_filter = ${LilyGo_Techo.build_src_filter} +<../examples/simple_repeater/main.cpp> +extends = LilyGo_T-Echo +build_src_filter = ${LilyGo_T-Echo.build_src_filter} + +<../examples/simple_repeater> build_flags = - ${LilyGo_Techo.build_flags} + ${LilyGo_T-Echo.build_flags} -D ADVERT_NAME='"T-Echo Repeater"' -D ADVERT_LAT=0.0 -D ADVERT_LON=0.0 @@ -54,10 +64,11 @@ build_flags = ; -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> +extends = LilyGo_T-Echo +build_src_filter = ${LilyGo_T-Echo.build_src_filter} + +<../examples/simple_room_server> build_flags = - ${LilyGo_Techo.build_flags} + ${LilyGo_T-Echo.build_flags} -D ADVERT_NAME='"T-Echo Room"' -D ADVERT_LAT=0.0 -D ADVERT_LON=0.0 @@ -66,31 +77,42 @@ build_flags = ; -D MESH_DEBUG=1 [env:LilyGo_T-Echo_companion_radio_ble] -extends = LilyGo_Techo +extends = LilyGo_T-Echo build_flags = - ${LilyGo_Techo.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 MAX_CONTACTS=350 + -D MAX_GROUP_CHANNELS=40 + -D QSPIFLASH=1 -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 BACKLIGHT_BTN=PIN_BUTTON2 - -D AUTO_OFF_MILLIS=0 ; -D MESH_PACKET_LOGGING=1 ; -D MESH_DEBUG=1 -build_src_filter = ${LilyGo_Techo.build_src_filter} - + + -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_Techo.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=350 + -D MAX_GROUP_CHANNELS=40 + -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 - zinggjm/GxEPD2 @ 1.6.2 - bakercp/CRC32 @ ^2.0.0 diff --git a/variants/techo/target.cpp b/variants/lilygo_techo/target.cpp similarity index 100% rename from variants/techo/target.cpp rename to variants/lilygo_techo/target.cpp diff --git a/variants/techo/target.h b/variants/lilygo_techo/target.h similarity index 95% rename from variants/techo/target.h rename to variants/lilygo_techo/target.h index 134f13b5..2b6ed45f 100644 --- a/variants/techo/target.h +++ b/variants/lilygo_techo/target.h @@ -3,7 +3,7 @@ #define RADIOLIB_STATIC_ONLY 1 #include #include -#include +#include #include #include #include diff --git a/variants/techo/variant.cpp b/variants/lilygo_techo/variant.cpp similarity index 100% rename from variants/techo/variant.cpp rename to variants/lilygo_techo/variant.cpp diff --git a/variants/techo/variant.h b/variants/lilygo_techo/variant.h similarity index 90% rename from variants/techo/variant.h rename to variants/lilygo_techo/variant.h index da8d81d4..1de62d91 100644 --- a/variants/techo/variant.h +++ b/variants/lilygo_techo/variant.h @@ -58,6 +58,19 @@ #define PIN_SPI_SCK (19) #define PIN_SPI_NSS (24) +//////////////////////////////////////////////////////////////////////////////// +// QSPI FLASH + +#define PIN_QSPI_SCK (46) +#define PIN_QSPI_CS (47) +#define PIN_QSPI_IO0 (44) +#define PIN_QSPI_IO1 (45) +#define PIN_QSPI_IO2 (7) +#define PIN_QSPI_IO3 (5) + +#define EXTERNAL_FLASH_DEVICES ZD25WQ16BUIGR +#define EXTERNAL_FLASH_USE_QSPI + //////////////////////////////////////////////////////////////////////////////// // Builtin LEDs diff --git a/variants/lilygo_tlora_v2_1/platformio.ini b/variants/lilygo_tlora_v2_1/platformio.ini index 05a87d70..aa957fba 100644 --- a/variants/lilygo_tlora_v2_1/platformio.ini +++ b/variants/lilygo_tlora_v2_1/platformio.ini @@ -156,3 +156,51 @@ build_src_filter = ${LilyGo_TLora_V2_1_1_6.build_src_filter} lib_deps = ${LilyGo_TLora_V2_1_1_6.lib_deps} densaugeo/base64 @ ~1.4.0 + +; +; Repeater Bridges +; +[env:LilyGo_TLora_V2_1_1_6_bridge_rs232] +extends = LilyGo_TLora_V2_1_1_6 +build_src_filter = ${LilyGo_TLora_V2_1_1_6.build_src_filter} + + + + + +<../examples/simple_repeater> +build_flags = + ${LilyGo_TLora_V2_1_1_6.build_flags} + -D ADVERT_NAME='"RS232 Bridge"' + -D ADVERT_LAT=0.0 + -D ADVERT_LON=0.0 + -D ADMIN_PASSWORD='"password"' + -D MAX_NEIGHBOURS=8 + -D WITH_RS232_BRIDGE=Serial2 + -D WITH_RS232_BRIDGE_RX=34 + -D WITH_RS232_BRIDGE_TX=25 +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +; -D CORE_DEBUG_LEVEL=3 +lib_deps = + ${LilyGo_TLora_V2_1_1_6.lib_deps} + ${esp32_ota.lib_deps} + +[env:LilyGo_TLora_V2_1_1_6_bridge_espnow] +extends = LilyGo_TLora_V2_1_1_6 +build_src_filter = ${LilyGo_TLora_V2_1_1_6.build_src_filter} + + + + + +<../examples/simple_repeater> +build_flags = + ${LilyGo_TLora_V2_1_1_6.build_flags} + -D ADVERT_NAME='"ESPNow Bridge"' + -D ADVERT_LAT=0.0 + -D ADVERT_LON=0.0 + -D ADMIN_PASSWORD='"password"' + -D MAX_NEIGHBOURS=8 + -D WITH_ESPNOW_BRIDGE=1 + -D WITH_ESPNOW_BRIDGE_SECRET='"shared-secret"' +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +; -D CORE_DEBUG_LEVEL=3 +lib_deps = + ${LilyGo_TLora_V2_1_1_6.lib_deps} + ${esp32_ota.lib_deps} \ No newline at end of file diff --git a/variants/mesh_pocket/platformio.ini b/variants/mesh_pocket/platformio.ini index 3fa4c7b8..7c996157 100644 --- a/variants/mesh_pocket/platformio.ini +++ b/variants/mesh_pocket/platformio.ini @@ -70,8 +70,8 @@ extends = Mesh_pocket build_flags = ${Mesh_pocket.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 OFFLINE_QUEUE_SIZE=256 -D AUTO_OFF_MILLIS=0 @@ -92,8 +92,8 @@ extends = Mesh_pocket build_flags = ${Mesh_pocket.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 AUTO_OFF_MILLIS=0 ; -D BLE_PIN_CODE=123456 ; -D BLE_DEBUG_LOGGING=1 diff --git a/variants/meshadventurer/platformio.ini b/variants/meshadventurer/platformio.ini index 1b881c1a..be3b4943 100644 --- a/variants/meshadventurer/platformio.ini +++ b/variants/meshadventurer/platformio.ini @@ -54,6 +54,55 @@ lib_deps = ${Meshadventurer.lib_deps} ${esp32_ota.lib_deps} +; [env:Meshadventurer_sx1262_repeater_bridge_rs232] +; extends = Meshadventurer +; build_src_filter = ${Meshadventurer.build_src_filter} +; + +; +<../examples/simple_repeater> +; + +; build_flags = +; ${Meshadventurer.build_flags} +; -D RADIO_CLASS=CustomSX1262 +; -D WRAPPER_CLASS=CustomSX1262Wrapper +; -D LORA_TX_POWER=22 +; -D ADVERT_NAME='"RS232 Bridge"' +; -D ADVERT_LAT=0.0 +; -D ADVERT_LON=0.0 +; -D ADMIN_PASSWORD='"password"' +; -D MAX_NEIGHBOURS=8 +; -D WITH_RS232_BRIDGE=Serial2 +; -D WITH_RS232_BRIDGE_RX=5 +; -D WITH_RS232_BRIDGE_TX=6 +; ; -D MESH_PACKET_LOGGING=1 +; ; -D MESH_DEBUG=1 +; lib_deps = +; ${Meshadventurer.lib_deps} +; ${esp32_ota.lib_deps} + +[env:Meshadventurer_sx1262_repeater_bridge_espnow] +extends = Meshadventurer +build_src_filter = ${Meshadventurer.build_src_filter} + + + +<../examples/simple_repeater> + + +build_flags = + ${Meshadventurer.build_flags} + -D RADIO_CLASS=CustomSX1262 + -D WRAPPER_CLASS=CustomSX1262Wrapper + -D LORA_TX_POWER=22 + -D ADVERT_NAME='"ESPNow Bridge"' + -D ADVERT_LAT=0.0 + -D ADVERT_LON=0.0 + -D ADMIN_PASSWORD='"password"' + -D MAX_NEIGHBOURS=8 + -D WITH_ESPNOW_BRIDGE=1 + -D WITH_ESPNOW_BRIDGE_SECRET='"shared-secret"' +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +lib_deps = + ${Meshadventurer.lib_deps} + ${esp32_ota.lib_deps} + [env:Meshadventurer_sx1268_repeater] extends = Meshadventurer build_src_filter = ${Meshadventurer.build_src_filter} @@ -75,6 +124,55 @@ lib_deps = ${Meshadventurer.lib_deps} ${esp32_ota.lib_deps} +; [env:Meshadventurer_sx1268_repeater_bridge_rs232] +; extends = Meshadventurer +; build_src_filter = ${Meshadventurer.build_src_filter} +; + +; +<../examples/simple_repeater> +; + +; build_flags = +; ${Meshadventurer.build_flags} +; -D RADIO_CLASS=CustomSX1268 +; -D WRAPPER_CLASS=CustomSX1268Wrapper +; -D LORA_TX_POWER=22 +; -D ADVERT_NAME='"RS232 Bridge"' +; -D ADVERT_LAT=0.0 +; -D ADVERT_LON=0.0 +; -D ADMIN_PASSWORD='"password"' +; -D MAX_NEIGHBOURS=8 +; -D WITH_RS232_BRIDGE=Serial2 +; -D WITH_RS232_BRIDGE_RX=5 +; -D WITH_RS232_BRIDGE_TX=6 +; ; -D MESH_PACKET_LOGGING=1 +; ; -D MESH_DEBUG=1 +; lib_deps = +; ${Meshadventurer.lib_deps} +; ${esp32_ota.lib_deps} + +[env:Meshadventurer_sx1268_repeater_bridge_espnow] +extends = Meshadventurer +build_src_filter = ${Meshadventurer.build_src_filter} + + + +<../examples/simple_repeater> + + +build_flags = + ${Meshadventurer.build_flags} + -D RADIO_CLASS=CustomSX1268 + -D WRAPPER_CLASS=CustomSX1268Wrapper + -D LORA_TX_POWER=22 + -D ADVERT_NAME='"ESPNow Bridge"' + -D ADVERT_LAT=0.0 + -D ADVERT_LON=0.0 + -D ADMIN_PASSWORD='"password"' + -D MAX_NEIGHBOURS=8 + -D WITH_ESPNOW_BRIDGE=1 + -D WITH_ESPNOW_BRIDGE_SECRET='"shared-secret"' +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +lib_deps = + ${Meshadventurer.lib_deps} + ${esp32_ota.lib_deps} + [env:Meshadventurer_sx1262_companion_radio_usb] extends = Meshadventurer build_src_filter = ${Meshadventurer.build_src_filter} diff --git a/variants/minewsemi_me25ls01/platformio.ini b/variants/minewsemi_me25ls01/platformio.ini index 3436062f..71887002 100644 --- a/variants/minewsemi_me25ls01/platformio.ini +++ b/variants/minewsemi_me25ls01/platformio.ini @@ -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 diff --git a/variants/nano_g2_ultra/platformio.ini b/variants/nano_g2_ultra/platformio.ini index 7fb2de28..163f4311 100644 --- a/variants/nano_g2_ultra/platformio.ini +++ b/variants/nano_g2_ultra/platformio.ini @@ -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 diff --git a/variants/promicro/platformio.ini b/variants/promicro/platformio.ini index 6b77bdcf..5a70f7ba 100644 --- a/variants/promicro/platformio.ini +++ b/variants/promicro/platformio.ini @@ -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 diff --git a/variants/rak4631/platformio.ini b/variants/rak4631/platformio.ini index c9091878..7e7d2234 100644 --- a/variants/rak4631/platformio.ini +++ b/variants/rak4631/platformio.ini @@ -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 diff --git a/variants/rak_wismesh_tag/RAKWismeshTagBoard.cpp b/variants/rak_wismesh_tag/RAKWismeshTagBoard.cpp new file mode 100644 index 00000000..68ce2fd8 --- /dev/null +++ b/variants/rak_wismesh_tag/RAKWismeshTagBoard.cpp @@ -0,0 +1,81 @@ +#include +#include "RAKWismeshTagBoard.h" + +#include +#include + +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 RAKWismeshTagBoard::begin() { + // for future use, sub-classes SHOULD call this from their begin() + startup_reason = BD_STARTUP_NORMAL; + pinMode(PIN_VBAT_READ, INPUT); + pinMode(PIN_USER_BTN, INPUT_PULLUP); + + Wire.setPins(PIN_BOARD_SDA, PIN_BOARD_SCL); + Wire.begin(); + + pinMode(SX126X_POWER_EN, OUTPUT); + digitalWrite(SX126X_POWER_EN, HIGH); + delay(10); // give sx1262 some time to power up +} + +bool RAKWismeshTagBoard::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("WISMESHTAG_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 + + uint8_t mac_addr[6]; + memset(mac_addr, 0, sizeof(mac_addr)); + Bluefruit.getAddr(mac_addr); + sprintf(reply, "OK - mac: %02X:%02X:%02X:%02X:%02X:%02X", + mac_addr[5], mac_addr[4], mac_addr[3], mac_addr[2], mac_addr[1], mac_addr[0]); + + return true; +} diff --git a/variants/rak_wismesh_tag/RAKWismeshTagBoard.h b/variants/rak_wismesh_tag/RAKWismeshTagBoard.h new file mode 100644 index 00000000..22af6f74 --- /dev/null +++ b/variants/rak_wismesh_tag/RAKWismeshTagBoard.h @@ -0,0 +1,80 @@ +#pragma once + +#include +#include + +// built-ins +#define PIN_VBAT_READ 5 +#define ADC_MULTIPLIER (3 * 1.73 * 1.187 * 1000) + +class RAKWismeshTagBoard : public mesh::MainBoard { +protected: + uint8_t startup_reason; + +public: + void begin(); + uint8_t getStartupReason() const override { return startup_reason; } + +#if defined(P_LORA_TX_LED) && defined(LED_STATE_ON) + void onBeforeTransmit() override { + digitalWrite(P_LORA_TX_LED, LED_STATE_ON); // turn TX LED on + } + void onAfterTransmit() override { + digitalWrite(P_LORA_TX_LED, !LED_STATE_ON); // turn TX LED off + } +#endif + + #define BATTERY_SAMPLES 8 + + uint16_t getBattMilliVolts() override { + analogReadResolution(12); + + uint32_t raw = 0; + for (int i = 0; i < BATTERY_SAMPLES; i++) { + raw += analogRead(PIN_VBAT_READ); + } + raw = raw / BATTERY_SAMPLES; + + return (ADC_MULTIPLIER * raw) / 4096; + } + + const char* getManufacturerName() const override { + return "RAK WisMesh Tag"; + } + + void reboot() override { + NVIC_SystemReset(); + } + + bool startOTAUpdate(const char* id, char reply[]) override; + + void powerOff() override { + #ifdef BUZZER_EN + digitalWrite(BUZZER_EN, LOW); + #endif + + #ifdef PIN_GPS_EN + digitalWrite(PIN_GPS_EN, LOW); + #endif + + // set led on and wait for button release before poweroff + #ifdef LED_PIN + digitalWrite(LED_PIN, HIGH); + #endif + #ifdef BUTTON_PIN + while(digitalRead(BUTTON_PIN)); + #endif + #ifdef LED_GREEN + digitalWrite(LED_GREEN, LOW); + #endif + #ifdef LED_BLUE + digitalWrite(LED_BLUE, LOW); + #endif + + #ifdef BUTTON_PIN + nrf_gpio_cfg_sense_input(digitalPinToInterrupt(BUTTON_PIN), NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_SENSE_HIGH); + #endif + + sd_power_system_off(); + } +}; diff --git a/variants/rak_wismesh_tag/platformio.ini b/variants/rak_wismesh_tag/platformio.ini new file mode 100644 index 00000000..572919eb --- /dev/null +++ b/variants/rak_wismesh_tag/platformio.ini @@ -0,0 +1,116 @@ +[rak_wismesh_tag] +extends = nrf52_base +platform = https://github.com/maxgerhardt/platform-nordicnrf52.git#rak +board = wiscore_rak4631 +board_check = true +build_flags = ${nrf52_base.build_flags} + ${sensor_base.build_flags} + -I variants/rak_wismesh_tag + -I src/helpers/ui + -D RAK_WISMESH_TAG + -D RAK_BOARD + -D P_LORA_TX_LED=LED_GREEN + -D P_LORA_DIO_1=SX126X_DIO1 + -D P_LORA_NSS=PIN_SPI_NSS + -D P_LORA_RESET=SX126X_RESET + -D P_LORA_BUSY=SX126X_BUSY + -D P_LORA_SCLK=PIN_SPI_SCK + -D P_LORA_MISO=PIN_SPI_MISO + -D P_LORA_MOSI=PIN_SPI_MOSI + -D RADIO_CLASS=CustomSX1262 + -D WRAPPER_CLASS=CustomSX1262Wrapper + -D DISPLAY_CLASS=NullDisplayDriver + -D LORA_TX_POWER=22 + -D SX126X_CURRENT_LIMIT=140 + -D SX126X_RX_BOOSTED_GAIN=1 + -D PIN_BUZZER=21 + -D PIN_BOARD_SDA=PIN_WIRE_SDA + -D PIN_BOARD_SCL=PIN_WIRE_SCL +build_src_filter = ${nrf52_base.build_src_filter} + +<../variants/rak_wismesh_tag> + + + + + + + + +lib_deps = + ${nrf52_base.lib_deps} + ${sensor_base.lib_deps} + +[env:RAK_WisMesh_Tag_Repeater] +extends = rak_wismesh_tag +build_flags = + ${rak_wismesh_tag.build_flags} + -D ADVERT_NAME='"RAK WM 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 +build_src_filter = ${rak_wismesh_tag.build_src_filter} + +<../examples/simple_repeater> + +[env:RAK_WisMesh_Tag_room_server] +extends = rak_wismesh_tag +build_flags = + ${rak_wismesh_tag.build_flags} + -D ADVERT_NAME='"RAK WM 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 +build_src_filter = ${rak_wismesh_tag.build_src_filter} + +<../examples/simple_room_server> + +[env:RAK_WisMesh_Tag_companion_radio_usb] +extends = rak_wismesh_tag +build_flags = + ${rak_wismesh_tag.build_flags} + -I examples/companion_radio/ui-orig + -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 = ${rak_wismesh_tag.build_src_filter} + +<../examples/companion_radio/*.cpp> + +<../examples/companion_radio/ui-orig/*.cpp> +lib_deps = + ${rak_wismesh_tag.lib_deps} + densaugeo/base64 @ ~1.4.0 + end2endzone/NonBlockingRTTTL@^1.3.0 + +[env:RAK_WisMesh_Tag_companion_radio_ble] +extends = rak_wismesh_tag +build_flags = + ${rak_wismesh_tag.build_flags} + -I examples/companion_radio/ui-orig + -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 = ${rak_wismesh_tag.build_src_filter} + + + +<../examples/companion_radio/*.cpp> + +<../examples/companion_radio/ui-orig/*.cpp> +lib_deps = + ${rak4631.lib_deps} + densaugeo/base64 @ ~1.4.0 + end2endzone/NonBlockingRTTTL@^1.3.0 + +[env:RAK_WisMesh_Tag_sensor] +extends = rak4631 +build_flags = + ${rak4631.build_flags} + -D ADVERT_NAME='"RAK WM Sensor"' + -D ADVERT_LAT=0.0 + -D ADVERT_LON=0.0 + -D ADMIN_PASSWORD='"password"' +; -D MESH_PACKET_LOGGING=1 + -D MESH_DEBUG=1 +build_src_filter = ${rak4631.build_src_filter} + +<../examples/simple_sensor> \ No newline at end of file diff --git a/variants/rak_wismesh_tag/target.cpp b/variants/rak_wismesh_tag/target.cpp new file mode 100644 index 00000000..2bd30864 --- /dev/null +++ b/variants/rak_wismesh_tag/target.cpp @@ -0,0 +1,54 @@ +#include +#include "target.h" +#include + +RAKWismeshTagBoard board; + +#ifndef PIN_USER_BTN + #define PIN_USER_BTN (-1) +#endif + +#ifdef DISPLAY_CLASS + DISPLAY_CLASS display; + MomentaryButton user_btn(PIN_USER_BTN, 1000, true, true); +#endif + +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); + +#if ENV_INCLUDE_GPS + #include + MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Serial1); + EnvironmentSensorManager sensors = EnvironmentSensorManager(nmea); +#else + EnvironmentSensorManager sensors; +#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 +} diff --git a/variants/rak_wismesh_tag/target.h b/variants/rak_wismesh_tag/target.h new file mode 100644 index 00000000..150d0831 --- /dev/null +++ b/variants/rak_wismesh_tag/target.h @@ -0,0 +1,27 @@ +#pragma once + +#define RADIOLIB_STATIC_ONLY 1 +#include +#include +#include +#include +#include +#include + +#ifdef DISPLAY_CLASS + #include + extern DISPLAY_CLASS display; + #include + extern MomentaryButton user_btn; +#endif + +extern RAKWismeshTagBoard board; +extern WRAPPER_CLASS radio_driver; +extern AutoDiscoverRTCClock rtc_clock; +extern EnvironmentSensorManager sensors; + +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(); diff --git a/variants/rak_wismesh_tag/variant.cpp b/variants/rak_wismesh_tag/variant.cpp new file mode 100644 index 00000000..ac3af5d2 --- /dev/null +++ b/variants/rak_wismesh_tag/variant.cpp @@ -0,0 +1,21 @@ +#include "variant.h" +#include "nrf.h" +#include "wiring_constants.h" +#include "wiring_digital.h" + +const uint32_t g_ADigitalPinMap[] = { + 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 +}; + +void initVariant() { + // LEDs + pinMode(LED_BLUE, OUTPUT); + pinMode(LED_GREEN, OUTPUT); + digitalWrite(LED_BLUE, LOW); + digitalWrite(LED_GREEN, LOW); + + // GPS + pinMode(PIN_GPS_EN, OUTPUT); + digitalWrite(PIN_GPS_EN, HIGH); +} \ No newline at end of file diff --git a/variants/rak_wismesh_tag/variant.h b/variants/rak_wismesh_tag/variant.h new file mode 100644 index 00000000..b0e51efc --- /dev/null +++ b/variants/rak_wismesh_tag/variant.h @@ -0,0 +1,121 @@ +/* + * variant.h + * Copyright (C) 2023 Seeed K.K. + * MIT License + */ + +#pragma once + +#include "WVariant.h" + +//////////////////////////////////////////////////////////////////////////////// +// Low frequency clock source + +#define USE_LFXO // 32.768 kHz crystal oscillator +#define VARIANT_MCK (64000000ul) + +#define WIRE_INTERFACES_COUNT (1) +#define PIN_TXCO (21) +//////////////////////////////////////////////////////////////////////////////// +// Power + +#define PIN_PWR_EN (12) + +#define BATTERY_PIN (5) +#define ADC_MULTIPLIER (1.73F) + +#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 (6) +#define NUM_ANALOG_OUTPUTS (0) + +//////////////////////////////////////////////////////////////////////////////// +// UART pin definition + +#define PIN_SERIAL1_RX (15) +#define PIN_SERIAL1_TX (16) + +//////////////////////////////////////////////////////////////////////////////// +// I2C pin definition +#define WIRE_INTERFACES_COUNT (1) +#define PIN_WIRE_SDA (25) +#define PIN_WIRE_SCL (24) + +//////////////////////////////////////////////////////////////////////////////// +// SPI pin definition + +#define SPI_INTERFACES_COUNT (2) + +#define PIN_SPI_MISO (45) +#define PIN_SPI_MOSI (44) +#define PIN_SPI_SCK (43) +#define PIN_SPI_NSS (42) + +//////////////////////////////////////////////////////////////////////////////// +// Builtin LEDs + +#define LED_RED (-1) +#define LED_BLUE (36) +#define LED_GREEN (35) + +//#define PIN_STATUS_LED LED_BLUE +#define LED_BUILTIN LED_GREEN +#define LED_PIN LED_GREEN +#define LED_STATE_ON HIGH + +//////////////////////////////////////////////////////////////////////////////// +// Builtin buttons + +#define PIN_BUTTON1 (9) +#define BUTTON_PIN PIN_BUTTON1 +#define PIN_USER_BTN BUTTON_PIN + +#define PIN_BUTTON2 (12) +#define BUTTON_PIN2 PIN_BUTTON2 + +//////////////////////////////////////////////////////////////////////////////// +// Lora + +#define USE_SX1262 +#define LORA_CS (42) +#define SX126X_DIO1 (47) +#define SX126X_BUSY (46) +#define SX126X_RESET (38) +#define SX126X_POWER_EN (37) +#define SX126X_DIO2_AS_RF_SWITCH +#define SX126X_DIO3_TCXO_VOLTAGE 1.8 + +//////////////////////////////////////////////////////////////////////////////// +// SPI1 + +#define PIN_SPI1_MISO (29) +#define PIN_SPI1_MOSI (30) +#define PIN_SPI1_SCK (3) + +// GxEPD2 needs that for a panel that is not even used ! +extern const int MISO; +extern const int MOSI; +extern const int SCK; + +//////////////////////////////////////////////////////////////////////////////// +// GPS + +#define PIN_GPS_RX (PIN_SERIAL1_TX) +#define PIN_GPS_TX (PIN_SERIAL1_RX) +#define PIN_GPS_PPS (17) +#define PIN_GPS_EN (34) + +/////////////////////////////////////////////////////////////////////////////// +// OTHER PINS +#define PIN_AREF (2) +#define PIN_NFC1 (9) +#define PIN_NFC2 (10) +#define PIN_BUZZER (21) diff --git a/variants/sensecap_solar/platformio.ini b/variants/sensecap_solar/platformio.ini index bbac5d99..649ace84 100644 --- a/variants/sensecap_solar/platformio.ini +++ b/variants/sensecap_solar/platformio.ini @@ -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} diff --git a/variants/station_g2/platformio.ini b/variants/station_g2/platformio.ini index 0e1631a8..908d6443 100644 --- a/variants/station_g2/platformio.ini +++ b/variants/station_g2/platformio.ini @@ -45,6 +45,47 @@ lib_deps = ${Station_G2.lib_deps} ${esp32_ota.lib_deps} +; [env:Station_G2_repeater_bridge_rs232] +; extends = Station_G2 +; build_flags = +; ${Station_G2.build_flags} +; -D ADVERT_NAME='"RS232 Bridge"' +; -D ADVERT_LAT=0.0 +; -D ADVERT_LON=0.0 +; -D ADMIN_PASSWORD='"password"' +; -D MAX_NEIGHBOURS=8 +; -D WITH_RS232_BRIDGE=Serial2 +; -D WITH_RS232_BRIDGE_RX=5 +; -D WITH_RS232_BRIDGE_TX=6 +; ; -D MESH_PACKET_LOGGING=1 +; ; -D MESH_DEBUG=1 +; build_src_filter = ${Station_G2.build_src_filter} +; + +; +<../examples/simple_repeater> +; lib_deps = +; ${Station_G2.lib_deps} +; ${esp32_ota.lib_deps} + +[env:Station_G2_repeater_bridge_espnow] +extends = Station_G2 +build_flags = + ${Station_G2.build_flags} + -D ADVERT_NAME='"ESPNow Bridge"' + -D ADVERT_LAT=0.0 + -D ADVERT_LON=0.0 + -D ADMIN_PASSWORD='"password"' + -D MAX_NEIGHBOURS=8 + -D WITH_ESPNOW_BRIDGE=1 + -D WITH_ESPNOW_BRIDGE_SECRET='"shared-secret"' +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +build_src_filter = ${Station_G2.build_src_filter} + + + +<../examples/simple_repeater> +lib_deps = + ${Station_G2.lib_deps} + ${esp32_ota.lib_deps} + [env:Station_G2_logging_repeater] extends = Station_G2 build_flags = @@ -64,6 +105,49 @@ lib_deps = ${Station_G2.lib_deps} ${esp32_ota.lib_deps} +; [env:Station_G2_logging_repeater_bridge_rs232] +; extends = Station_G2 +; build_flags = +; ${Station_G2.build_flags} +; -D ADVERT_NAME='"RS232 Bridge"' +; -D ADVERT_LAT=0.0 +; -D ADVERT_LON=0.0 +; -D ADMIN_PASSWORD='"password"' +; -D MAX_NEIGHBOURS=8 +; -D MESH_PACKET_LOGGING=1 +; -D SX126X_RX_BOOSTED_GAIN=1 +; -D WITH_RS232_BRIDGE=Serial2 +; -D WITH_RS232_BRIDGE_RX=5 +; -D WITH_RS232_BRIDGE_TX=6 +; ; -D MESH_DEBUG=1 +; build_src_filter = ${Station_G2.build_src_filter} +; + +; +<../examples/simple_repeater> +; lib_deps = +; ${Station_G2.lib_deps} +; ${esp32_ota.lib_deps} + +[env:Station_G2_logging_repeater_bridge_espnow] +extends = Station_G2 +build_flags = + ${Station_G2.build_flags} + -D ADVERT_NAME='"ESPNow Bridge"' + -D ADVERT_LAT=0.0 + -D ADVERT_LON=0.0 + -D ADMIN_PASSWORD='"password"' + -D MAX_NEIGHBOURS=8 + -D MESH_PACKET_LOGGING=1 + -D SX126X_RX_BOOSTED_GAIN=1 + -D WITH_ESPNOW_BRIDGE=1 + -D WITH_ESPNOW_BRIDGE_SECRET='"shared-secret"' +; -D MESH_DEBUG=1 +build_src_filter = ${Station_G2.build_src_filter} + + + +<../examples/simple_repeater> +lib_deps = + ${Station_G2.lib_deps} + ${esp32_ota.lib_deps} + [env:Station_G2_room_server] extends = Station_G2 build_src_filter = ${Station_G2.build_src_filter} diff --git a/variants/t1000-e/T1000eBoard.cpp b/variants/t1000-e/T1000eBoard.cpp index a17711db..4bcdf98a 100644 --- a/variants/t1000-e/T1000eBoard.cpp +++ b/variants/t1000-e/T1000eBoard.cpp @@ -11,6 +11,9 @@ void T1000eBoard::begin() { sd_power_mode_set(NRF_POWER_MODE_LOWPWR); + // Enable DC/DC converter for improved power efficiency + NRF_POWER->DCDCEN = 1; + #ifdef BUTTON_PIN pinMode(BATTERY_PIN, INPUT); pinMode(BUTTON_PIN, INPUT); diff --git a/variants/t1000-e/T1000eBoard.h b/variants/t1000-e/T1000eBoard.h index f87d71e0..359e5e9a 100644 --- a/variants/t1000-e/T1000eBoard.h +++ b/variants/t1000-e/T1000eBoard.h @@ -3,22 +3,6 @@ #include #include -// 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; @@ -72,18 +56,24 @@ public: digitalWrite(GPS_RESET, LOW); digitalWrite(GPS_SLEEP_INT, LOW); digitalWrite(GPS_RTC_INT, LOW); - pinMode(GPS_RESETB, OUTPUT); - digitalWrite(GPS_RESETB, LOW); + digitalWrite(GPS_EN, LOW); #endif - + #ifdef BUZZER_EN digitalWrite(BUZZER_EN, LOW); #endif - + #ifdef PIN_3V3_EN digitalWrite(PIN_3V3_EN, LOW); #endif + #ifdef PIN_3V3_ACC_EN + digitalWrite(PIN_3V3_ACC_EN, LOW); + #endif + #ifdef SENSOR_EN + digitalWrite(SENSOR_EN, LOW); + #endif + // set led on and wait for button release before poweroff #ifdef LED_PIN digitalWrite(LED_PIN, HIGH); @@ -96,7 +86,7 @@ public: #endif #ifdef BUTTON_PIN - nrf_gpio_cfg_sense_input(digitalPinToInterrupt(BUTTON_PIN), NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_SENSE_HIGH); + nrf_gpio_cfg_sense_input(BUTTON_PIN, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_SENSE_HIGH); #endif sd_power_system_off(); diff --git a/variants/t1000-e/platformio.ini b/variants/t1000-e/platformio.ini index b1826139..1f7d60dd 100644 --- a/variants/t1000-e/platformio.ini +++ b/variants/t1000-e/platformio.ini @@ -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} + + +<../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,14 @@ 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_TX_POWER=0 ; -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 diff --git a/variants/t1000-e/t1000e_sensors.cpp b/variants/t1000-e/t1000e_sensors.cpp index 17693022..a5b443cf 100644 --- a/variants/t1000-e/t1000e_sensors.cpp +++ b/variants/t1000-e/t1000e_sensors.cpp @@ -1,119 +1,99 @@ -#include #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 + +#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; } \ No newline at end of file diff --git a/variants/t1000-e/t1000e_sensors.h b/variants/t1000-e/t1000e_sensors.h index 8f3967ca..e8f790b6 100644 --- a/variants/t1000-e/t1000e_sensors.h +++ b/variants/t1000-e/t1000e_sensors.h @@ -1,7 +1,8 @@ #pragma once +#include // 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(); diff --git a/variants/t1000-e/target.cpp b/variants/t1000-e/target.cpp index 06509c4f..2a6380d5 100644 --- a/variants/t1000-e/target.cpp +++ b/variants/t1000-e/target.cpp @@ -146,15 +146,6 @@ void T1000SensorManager::stop_gps() { bool T1000SensorManager::begin() { // init GPS Serial1.begin(115200); - - // make sure gps pin are off - digitalWrite(GPS_VRTC_EN, LOW); - digitalWrite(GPS_RESET, LOW); - digitalWrite(GPS_SLEEP_INT, LOW); - digitalWrite(GPS_RTC_INT, LOW); - pinMode(GPS_RESETB, OUTPUT); - digitalWrite(GPS_RESETB, LOW); - return true; } diff --git a/variants/tenstar_c3/platformio.ini b/variants/tenstar_c3/platformio.ini index 4967ec55..c22b3771 100644 --- a/variants/tenstar_c3/platformio.ini +++ b/variants/tenstar_c3/platformio.ini @@ -44,6 +44,55 @@ lib_deps = ${Tenstar_esp32_C3.lib_deps} ${esp32_ota.lib_deps} +; [env:Tenstar_C3_Repeater_sx1262_bridge_rs232] +; extends = Tenstar_esp32_C3 +; build_src_filter = ${Tenstar_esp32_C3.build_src_filter} +; + +; +<../examples/simple_repeater/main.cpp> +; build_flags = +; ${Tenstar_esp32_C3.build_flags} +; -D RADIO_CLASS=CustomSX1262 +; -D WRAPPER_CLASS=CustomSX1262Wrapper +; -D SX126X_RX_BOOSTED_GAIN=1 +; -D LORA_TX_POWER=22 +; -D ADVERT_NAME='"RS232 Bridge"' +; -D ADVERT_LAT=0.0 +; -D ADVERT_LON=0.0 +; -D ADMIN_PASSWORD='"password"' +; -D MAX_NEIGHBOURS=8 +; -D WITH_RS232_BRIDGE=Serial2 +; -D WITH_RS232_BRIDGE_RX=5 +; -D WITH_RS232_BRIDGE_TX=6 +; ; -D MESH_PACKET_LOGGING=1 +; ; -D MESH_DEBUG=1 +; lib_deps = +; ${Tenstar_esp32_C3.lib_deps} +; ${esp32_ota.lib_deps} + +[env:Tenstar_C3_Repeater_sx1262_bridge_espnow] +extends = Tenstar_esp32_C3 +build_src_filter = ${Tenstar_esp32_C3.build_src_filter} + + + +<../examples/simple_repeater/main.cpp> +build_flags = + ${Tenstar_esp32_C3.build_flags} + -D RADIO_CLASS=CustomSX1262 + -D WRAPPER_CLASS=CustomSX1262Wrapper + -D SX126X_RX_BOOSTED_GAIN=1 + -D LORA_TX_POWER=22 + -D ADVERT_NAME='"ESPNow Bridge"' + -D ADVERT_LAT=0.0 + -D ADVERT_LON=0.0 + -D ADMIN_PASSWORD='"password"' + -D MAX_NEIGHBOURS=8 + -D WITH_ESPNOW_BRIDGE=1 + -D WITH_ESPNOW_BRIDGE_SECRET='"shared-secret"' +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +lib_deps = + ${Tenstar_esp32_C3.lib_deps} + ${esp32_ota.lib_deps} + [env:Tenstar_C3_Repeater_sx1268] extends = Tenstar_esp32_C3 build_src_filter = ${Tenstar_esp32_C3.build_src_filter} @@ -63,3 +112,50 @@ build_flags = lib_deps = ${Tenstar_esp32_C3.lib_deps} ${esp32_ota.lib_deps} + +; [env:Tenstar_C3_Repeater_sx1268_bridge_rs232] +; extends = Tenstar_esp32_C3 +; build_src_filter = ${Tenstar_esp32_C3.build_src_filter} +; + +; +<../examples/simple_repeater/main.cpp> +; build_flags = +; ${Tenstar_esp32_C3.build_flags} +; -D RADIO_CLASS=CustomSX1268 +; -D WRAPPER_CLASS=CustomSX1268Wrapper +; -D LORA_TX_POWER=22 +; -D ADVERT_NAME='"RS232 Bridge"' +; -D ADVERT_LAT=0.0 +; -D ADVERT_LON=0.0 +; -D ADMIN_PASSWORD='"password"' +; -D MAX_NEIGHBOURS=8 +; -D WITH_RS232_BRIDGE=Serial2 +; -D WITH_RS232_BRIDGE_RX=5 +; -D WITH_RS232_BRIDGE_TX=6 +; ; -D MESH_PACKET_LOGGING=1 +; ; -D MESH_DEBUG=1 +; lib_deps = +; ${Tenstar_esp32_C3.lib_deps} +; ${esp32_ota.lib_deps} + +[env:Tenstar_C3_Repeater_sx1268_bridge_espnow] +extends = Tenstar_esp32_C3 +build_src_filter = ${Tenstar_esp32_C3.build_src_filter} + + + +<../examples/simple_repeater/main.cpp> +build_flags = + ${Tenstar_esp32_C3.build_flags} + -D RADIO_CLASS=CustomSX1268 + -D WRAPPER_CLASS=CustomSX1268Wrapper + -D LORA_TX_POWER=22 + -D ADVERT_NAME='"ESPNow Bridge"' + -D ADVERT_LAT=0.0 + -D ADVERT_LON=0.0 + -D ADMIN_PASSWORD='"password"' + -D MAX_NEIGHBOURS=8 + -D WITH_ESPNOW_BRIDGE=1 + -D WITH_ESPNOW_BRIDGE_SECRET='"shared-secret"' + ; -D MESH_PACKET_LOGGING=1 + ; -D MESH_DEBUG=1 +lib_deps = + ${Tenstar_esp32_C3.lib_deps} + ${esp32_ota.lib_deps} diff --git a/variants/thinknode_m1/platformio.ini b/variants/thinknode_m1/platformio.ini index e29e1471..eeeb692e 100644 --- a/variants/thinknode_m1/platformio.ini +++ b/variants/thinknode_m1/platformio.ini @@ -71,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 @@ -80,6 +80,7 @@ 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} @@ -95,3 +96,30 @@ lib_deps = zinggjm/GxEPD2 @ 1.6.2 bakercp/CRC32 @ ^2.0.0 end2endzone/NonBlockingRTTTL@^1.3.0 + +[env:ThinkNode_M1_companion_radio_usb] +extends = ThinkNode_M1 +build_flags = + ${ThinkNode_M1.build_flags} + -I src/helpers/ui + -I examples/companion_radio/ui-new + -D MAX_CONTACTS=350 + -D MAX_GROUP_CHANNELS=40 + -D DISPLAY_ROTATION=4 + -D QSPIFLASH=1 + -D DISPLAY_CLASS=GxEPDDisplay + -D OFFLINE_QUEUE_SIZE=256 + -D PIN_BUZZER=6 + -D AUTO_SHUTDOWN_MILLIVOLTS=3300 +build_src_filter = ${ThinkNode_M1.build_src_filter} + + + + + + + +<../examples/companion_radio/*.cpp> + +<../examples/companion_radio/ui-new/*.cpp> +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 \ No newline at end of file diff --git a/variants/thinknode_m1/variant.h b/variants/thinknode_m1/variant.h index 2b58e341..f7f52a6a 100644 --- a/variants/thinknode_m1/variant.h +++ b/variants/thinknode_m1/variant.h @@ -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 diff --git a/src/helpers/rp2040/WaveshareBoard.cpp b/variants/waveshare_rp2040_lora/WaveshareBoard.cpp similarity index 100% rename from src/helpers/rp2040/WaveshareBoard.cpp rename to variants/waveshare_rp2040_lora/WaveshareBoard.cpp diff --git a/src/helpers/rp2040/WaveshareBoard.h b/variants/waveshare_rp2040_lora/WaveshareBoard.h similarity index 81% rename from src/helpers/rp2040/WaveshareBoard.h rename to variants/waveshare_rp2040_lora/WaveshareBoard.h index c2b5aff5..694b8bd1 100644 --- a/src/helpers/rp2040/WaveshareBoard.h +++ b/variants/waveshare_rp2040_lora/WaveshareBoard.h @@ -6,18 +6,6 @@ // LoRa radio module pins for Waveshare RP2040-LoRa-HF/LF // https://files.waveshare.com/wiki/RP2040-LoRa/Rp2040-lora-sch.pdf -#define P_LORA_DIO_1 16 -#define P_LORA_NSS 13 // CS -#define P_LORA_RESET 23 -#define P_LORA_BUSY 18 -#define P_LORA_SCLK 14 -#define P_LORA_MISO 24 -#define P_LORA_MOSI 15 -#define P_LORA_TX_LED 25 - -#define SX126X_DIO2_AS_RF_SWITCH true -#define SX126X_DIO3_TCXO_VOLTAGE 0 - /* * This board has no built-in way to read battery voltage. * Nevertheless it's very easy to make it work, you only require two 1% resistors. diff --git a/variants/waveshare_rp2040_lora/platformio.ini b/variants/waveshare_rp2040_lora/platformio.ini index 933c7661..f2f180aa 100644 --- a/variants/waveshare_rp2040_lora/platformio.ini +++ b/variants/waveshare_rp2040_lora/platformio.ini @@ -3,28 +3,34 @@ [waveshare_rp2040_lora] extends = rp2040_base - board = pico board_build.filesystem_size = 0.5m - build_flags = ${rp2040_base.build_flags} -I variants/waveshare_rp2040_lora -D SX126X_CURRENT_LIMIT=140 -D RADIO_CLASS=CustomSX1262 -D WRAPPER_CLASS=CustomSX1262Wrapper - -D LORA_TX_POWER=22 + -D P_LORA_DIO_1=16 + -D P_LORA_NSS=13 ; CS + -D P_LORA_RESET=23 + -D P_LORA_BUSY=18 + -D P_LORA_SCLK=14 + -D P_LORA_MISO=24 + -D P_LORA_MOSI=15 + -D P_LORA_TX_LED=25 + -D SX126X_DIO2_AS_RF_SWITCH=true + -D SX126X_DIO3_TCXO_VOLTAGE=0 -D SX126X_RX_BOOSTED_GAIN=1 + -D LORA_TX_POWER=22 ; Debug options ; -D DEBUG_RP2040_WIRE=1 ; -D DEBUG_RP2040_SPI=1 ; -D DEBUG_RP2040_CORE=1 ; -D RADIOLIB_DEBUG_SPI=1 ; -D DEBUG_RP2040_PORT=Serial - build_src_filter = ${rp2040_base.build_src_filter} - + + + +<../variants/waveshare_rp2040_lora> - lib_deps = ${rp2040_base.lib_deps} [env:waveshare_rp2040_lora_Repeater] @@ -40,6 +46,23 @@ build_flags = ${waveshare_rp2040_lora.build_flags} build_src_filter = ${waveshare_rp2040_lora.build_src_filter} +<../examples/simple_repeater> +[env:waveshare_rp2040_lora_repeater_bridge_rs232] +extends = waveshare_rp2040_lora +build_flags = ${waveshare_rp2040_lora.build_flags} + -D ADVERT_NAME='"RS232 Bridge"' + -D ADVERT_LAT=0.0 + -D ADVERT_LON=0.0 + -D ADMIN_PASSWORD='"password"' + -D MAX_NEIGHBOURS=8 + -D WITH_RS232_BRIDGE=Serial2 + -D WITH_RS232_BRIDGE_RX=9 + -D WITH_RS232_BRIDGE_TX=8 +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +build_src_filter = ${waveshare_rp2040_lora.build_src_filter} + + + +<../examples/simple_repeater> + [env:waveshare_rp2040_lora_room_server] extends = waveshare_rp2040_lora build_flags = ${waveshare_rp2040_lora.build_flags} diff --git a/variants/waveshare_rp2040_lora/target.h b/variants/waveshare_rp2040_lora/target.h index 149b9469..aed55893 100644 --- a/variants/waveshare_rp2040_lora/target.h +++ b/variants/waveshare_rp2040_lora/target.h @@ -7,7 +7,7 @@ #include #include #include -#include +#include extern WaveshareBoard board; extern WRAPPER_CLASS radio_driver; diff --git a/variants/wio-tracker-l1/platformio.ini b/variants/wio-tracker-l1/platformio.ini index be0086c4..87670bd0 100644 --- a/variants/wio-tracker-l1/platformio.ini +++ b/variants/wio-tracker-l1/platformio.ini @@ -79,13 +79,14 @@ lib_deps = ${WioTrackerL1.lib_deps} extends = WioTrackerL1 build_flags = ${WioTrackerL1.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 -D DISPLAY_CLASS=SH1106Display -D PIN_BUZZER=12 + -D QSPIFLASH=1 ; -D MESH_PACKET_LOGGING=1 ; -D MESH_DEBUG=1 build_src_filter = ${WioTrackerL1.build_src_filter} diff --git a/variants/xiao_nrf52/platformio.ini b/variants/xiao_nrf52/platformio.ini index fd4c362b..10807476 100644 --- a/variants/xiao_nrf52/platformio.ini +++ b/variants/xiao_nrf52/platformio.ini @@ -59,13 +59,14 @@ upload_protocol = nrfutil extends = Xiao_nrf52 build_flags = ${Xiao_nrf52.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 ; -D MESH_PACKET_LOGGING=1 -; -D MESH_DEBUG=1 + -D MESH_DEBUG=1 + -D QSPIFLASH=1 build_src_filter = ${Xiao_nrf52.build_src_filter} + +<../examples/companion_radio/*.cpp> @@ -77,8 +78,8 @@ lib_deps = extends = Xiao_nrf52 build_flags = ${Xiao_nrf52.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 = ${Xiao_nrf52.build_src_filter} diff --git a/src/helpers/rp2040/XiaoRP2040Board.cpp b/variants/xiao_rp2040/XiaoRP2040Board.cpp similarity index 100% rename from src/helpers/rp2040/XiaoRP2040Board.cpp rename to variants/xiao_rp2040/XiaoRP2040Board.cpp diff --git a/src/helpers/rp2040/XiaoRP2040Board.h b/variants/xiao_rp2040/XiaoRP2040Board.h similarity index 79% rename from src/helpers/rp2040/XiaoRP2040Board.h rename to variants/xiao_rp2040/XiaoRP2040Board.h index c9353906..d2951c75 100644 --- a/src/helpers/rp2040/XiaoRP2040Board.h +++ b/variants/xiao_rp2040/XiaoRP2040Board.h @@ -3,21 +3,6 @@ #include #include -// LoRa radio module pins for the Xiao RP2040 -// https://wiki.seeedstudio.com/XIAO-RP2040/ - -#define P_LORA_DIO_1 27 // D1 -#define P_LORA_NSS 6 // D4 -#define P_LORA_RESET 28 // D2 -#define P_LORA_BUSY 29 // D3 -#define P_LORA_TX_LED 17 - -#define SX126X_RXEN 7 // D5 -#define SX126X_TXEN -1 - -#define SX126X_DIO2_AS_RF_SWITCH true -#define SX126X_DIO3_TCXO_VOLTAGE 1.8 - /* * This board has no built-in way to read battery voltage. * Nevertheless it's very easy to make it work, you only require two 1% resistors. diff --git a/variants/xiao_rp2040/platformio.ini b/variants/xiao_rp2040/platformio.ini index 619350ec..6c9c70f6 100644 --- a/variants/xiao_rp2040/platformio.ini +++ b/variants/xiao_rp2040/platformio.ini @@ -1,27 +1,32 @@ [Xiao_rp2040] extends = rp2040_base - board = seeed_xiao_rp2040 board_build.filesystem_size = 0.5m - build_flags = ${rp2040_base.build_flags} -I variants/xiao_rp2040 -D SX126X_CURRENT_LIMIT=140 -D RADIO_CLASS=CustomSX1262 -D WRAPPER_CLASS=CustomSX1262Wrapper - -D LORA_TX_POWER=22 + -D P_LORA_DIO_1=27 ; D1 + -D P_LORA_NSS=6 ; D4 + -D P_LORA_RESET=28 ; D2 + -D P_LORA_BUSY=29 ; D3 + -D P_LORA_TX_LED=17 + -D SX126X_RXEN=7 ; D5 + -D SX126X_TXEN=RADIOLIB_NC + -D SX126X_DIO2_AS_RF_SWITCH=true + -D SX126X_DIO3_TCXO_VOLTAGE=1.8 -D SX126X_RX_BOOSTED_GAIN=1 + -D LORA_TX_POWER=22 ; Debug options ; -D DEBUG_RP2040_WIRE=1 ; -D DEBUG_RP2040_SPI=1 ; -D DEBUG_RP2040_CORE=1 ; -D RADIOLIB_DEBUG_SPI=1 ; -D DEBUG_RP2040_PORT=Serial - build_src_filter = ${rp2040_base.build_src_filter} - + + + +<../variants/xiao_rp2040> - lib_deps = ${rp2040_base.lib_deps} [env:Xiao_rp2040_Repeater] diff --git a/variants/xiao_rp2040/target.h b/variants/xiao_rp2040/target.h index 34861db3..33b3766c 100644 --- a/variants/xiao_rp2040/target.h +++ b/variants/xiao_rp2040/target.h @@ -7,7 +7,7 @@ #include #include #include -#include +#include extern XiaoRP2040Board board; extern WRAPPER_CLASS radio_driver; diff --git a/variants/xiao_s3_wio/platformio.ini b/variants/xiao_s3_wio/platformio.ini index b4f25e53..7408f85d 100644 --- a/variants/xiao_s3_wio/platformio.ini +++ b/variants/xiao_s3_wio/platformio.ini @@ -44,6 +44,47 @@ lib_deps = ${Xiao_S3_WIO.lib_deps} ${esp32_ota.lib_deps} +; [env:Xiao_S3_WIO_Repeater_bridge_rs232] +; extends = Xiao_S3_WIO +; build_src_filter = ${Xiao_S3_WIO.build_src_filter} +; + +; +<../examples/simple_repeater/main.cpp> +; build_flags = +; ${Xiao_S3_WIO.build_flags} +; -D ADVERT_NAME='"RS232 Bridge"' +; -D ADVERT_LAT=0.0 +; -D ADVERT_LON=0.0 +; -D ADMIN_PASSWORD='"password"' +; -D MAX_NEIGHBOURS=8 +; -D WITH_RS232_BRIDGE=Serial2 +; -D WITH_RS232_BRIDGE_RX=5 +; -D WITH_RS232_BRIDGE_TX=6 +; ; -D MESH_PACKET_LOGGING=1 +; ; -D MESH_DEBUG=1 +; lib_deps = +; ${Xiao_S3_WIO.lib_deps} +; ${esp32_ota.lib_deps} + +[env:Xiao_S3_WIO_Repeater_bridge_espnow] +extends = Xiao_S3_WIO +build_src_filter = ${Xiao_S3_WIO.build_src_filter} + + + +<../examples/simple_repeater/main.cpp> +build_flags = + ${Xiao_S3_WIO.build_flags} + -D ADVERT_NAME='"ESPNow Bridge"' + -D ADVERT_LAT=0.0 + -D ADVERT_LON=0.0 + -D ADMIN_PASSWORD='"password"' + -D MAX_NEIGHBOURS=8 + -D WITH_ESPNOW_BRIDGE=1 + -D WITH_ESPNOW_BRIDGE_SECRET='"shared-secret"' +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +lib_deps = + ${Xiao_S3_WIO.lib_deps} + ${esp32_ota.lib_deps} + [env:Xiao_S3_WIO_room_server] extends = Xiao_S3_WIO build_src_filter = ${Xiao_S3_WIO.build_src_filter}