Compare commits

...

22 Commits

Author SHA1 Message Date
Scott Powell
0963341f79 Merge branch 'dev' 2025-07-02 21:11:38 +10:00
Scott Powell
483b31665c * ver bump to v1.7.2 2025-07-02 21:11:07 +10:00
ripplebiz
54fd7049df Merge pull request #467 from LitBomb/patch-14
Update faq.md
2025-07-02 15:26:48 +10:00
uncle lit
811ea175fa Update faq.md
- rewrite Linux firmware update with more detailed instructions 
- fix T114 reset typo: double click twice, not once
- add link reference to MeshCore logo on github
- add public channel key for t-deck to the t-deck section
- reference the verbiage "what is meshcore?" on meshcore.co.uk homepage
2025-07-01 22:04:16 -07:00
ripplebiz
79a75b8b0e Merge pull request #465 from fdlamotte/t1000e_preamble_16
t1000e: set preamble to 16 at init
2025-07-01 23:56:24 +10:00
Florent de Lamotte
b80d99edd1 t1000e: set preamble to 16 at init 2025-07-01 15:42:54 +02:00
ripplebiz
1d1bafb3eb Merge pull request #455 from jquatier/wireless-paper
Initial Support for Heltec Wireless Paper
2025-07-01 15:23:58 +10:00
ripplebiz
f8d277de83 Merge pull request #426 from 446564/feat-GH109
allows manual BLE pin even when device has display
2025-07-01 15:09:43 +10:00
ripplebiz
387e2c7e74 Merge pull request #464 from oltaco/lilygo_t3s3-radio.std_init
refactor: lilygo_t3s3 with CustomSX1262::std_init()
2025-07-01 12:26:43 +10:00
Scott Powell
3dc4607d89 * PAYLOAD_TYPE_PATH: reserving upper 4 bits if 'extra_type' field, for future use 2025-06-30 23:18:16 +10:00
Scott Powell
a72fafcbf1 Merge branch 'main' into dev 2025-06-30 17:07:01 +10:00
ripplebiz
d04fd377b6 Merge pull request #463 from jankowski-t/main
Support MeshAdventurer
2025-06-30 17:06:19 +10:00
ripplebiz
28a38e674b Merge pull request #462 from seagull9000/Refactor-Heltec-Tracker-radiolib-init
Refactor radiolib for Heltec Wireless Tracker
2025-06-30 17:01:55 +10:00
jankowski-t
c91356016b Fixed MeshAdventurer repeater build failing
Update build_src_filter in platformio.ini
2025-06-30 05:40:07 +02:00
jankowski-t
4541380632 Support MeshAdventurer
Added support for MeshAdventurer, including radio, display, button, GPS, voltage reading
2025-06-30 03:46:18 +02:00
taco
c56da5e6aa refactor: lilgo_t3s3 with CustomSX1262::std_init() 2025-06-30 08:51:18 +10:00
seagull9000
1bfa3d338c Refactor radiolib for Heltec Wireless Tracker
Made changes and tested transmission and reception.

Note:
TX to T1000E would not work direct, but always went through a repeater.

TX to two Thinknode M1's went through direct..
2025-06-30 09:48:18 +12:00
ripplebiz
eb4f81f9ae Merge pull request #459 from liquidraver/dev
change fixed preamble to match the new 16
2025-06-30 00:26:19 +10:00
liquidraver
ddbf27c245 change fixed preamble to match the new 16 2025-06-29 15:17:15 +02:00
JQ
ff3e888dfd formatting 2025-06-27 23:30:52 -07:00
JQ
e417c43c30 wireless paper board support 2025-06-27 22:57:49 -07:00
Rob Loranger
f4463154cf allows manual BLE pin even when device has display
also updates remaining variants to use default of
123456 instead of 0 for random pin
2025-06-20 14:20:42 -07:00
24 changed files with 977 additions and 133 deletions

View File

@@ -31,13 +31,14 @@ author: https://github.com/LitBomb<!-- omit from toc -->
- [4.2. Q: Why is my T-Deck Plus not getting any satellite lock?](#42-q-why-is-my-t-deck-plus-not-getting-any-satellite-lock)
- [4.3. Q: Why is my OG (non-Plus) T-Deck not getting any satellite lock?](#43-q-why-is-my-og-non-plus-t-deck-not-getting-any-satellite-lock)
- [4.4. Q: What size of SD card does the T-Deck support?](#44-q-what-size-of-sd-card-does-the-t-deck-support)
- [4.5. Q: How do I get maps on T-Deck?](#45-q-how-do-i-get-maps-on-t-deck)
- [4.6. Q: Where do the map tiles go?](#46-q-where-do-the-map-tiles-go)
- [4.7. Q: How to unlock deeper map zoom and server management features on T-Deck?](#47-q-how-to-unlock-deeper-map-zoom-and-server-management-features-on-t-deck)
- [4.8. Q: How to decipher the diagnostics screen on T-Deck?](#48-q-how-to-decipher-the-diagnostics-screen-on-t-deck)
- [4.9. Q: The T-Deck sound is too loud?](#49-q-the-t-deck-sound-is-too-loud)
- [4.10. Q: Can you customize the sound?](#410-q-can-you-customize-the-sound)
- [4.11. Q: What is the 'Import from Clipboard' feature on the t-deck and is there a way to manually add nodes without having to receive adverts?](#411-q-what-is-the-import-from-clipboard-feature-on-the-t-deck-and-is-there-a-way-to-manually-add-nodes-without-having-to-receive-adverts)
- [4.5. Q: What is the public key for the default public channel?](#45-q-what-is-the-public-key-for-the-default-public-channel)
- [4.6. Q: How do I get maps on T-Deck?](#46-q-how-do-i-get-maps-on-t-deck)
- [4.7. Q: Where do the map tiles go?](#47-q-where-do-the-map-tiles-go)
- [4.8. Q: How to unlock deeper map zoom and server management features on T-Deck?](#48-q-how-to-unlock-deeper-map-zoom-and-server-management-features-on-t-deck)
- [4.9. Q: How to decipher the diagnostics screen on T-Deck?](#49-q-how-to-decipher-the-diagnostics-screen-on-t-deck)
- [4.10. Q: The T-Deck sound is too loud?](#410-q-the-t-deck-sound-is-too-loud)
- [4.11. Q: Can you customize the sound?](#411-q-can-you-customize-the-sound)
- [4.12. Q: What is the 'Import from Clipboard' feature on the t-deck and is there a way to manually add nodes without having to receive adverts?](#412-q-what-is-the-import-from-clipboard-feature-on-the-t-deck-and-is-there-a-way-to-manually-add-nodes-without-having-to-receive-adverts)
- [5. General](#5-general)
- [5.1. Q: What are BW, SF, and CR?](#51-q-what-are-bw-sf-and-cr)
- [5.2. Q: Do MeshCore clients repeat?](#52-q-do-meshcore-clients-repeat)
@@ -65,18 +66,20 @@ author: https://github.com/LitBomb<!-- omit from toc -->
- [6.4. Q: I can't connect via Bluetooth, what is the Bluetooth pairing code?](#64-q-i-cant-connect-via-bluetooth-what-is-the-bluetooth-pairing-code)
- [6.5. Q: My Heltec V3 keeps disconnecting from my smartphone. It can't hold a solid Bluetooth connection.](#65-q-my-heltec-v3-keeps-disconnecting-from-my-smartphone--it-cant-hold-a-solid-bluetooth-connection)
- [6.6. Q: My RAK/T1000-E/xiao\_nRF52 device seems to be corrupted, how do I wipe it clean to start fresh?](#66-q-my-rakt1000-exiao_nrf52-device-seems-to-be-corrupted-how-do-i-wipe-it-clean-to-start-fresh)
- [6.7. Q: WebFlasher fails on Linux with failed to open](#67-q-webflasher-fails-on-Linux-with-failed-to-open)
- [6.7. Q: WebFlasher fails on Linux with failed to open](#67-q-webflasher-fails-on-linux-with-failed-to-open)
- [7. Other Questions:](#7-other-questions)
- [7.1 Q: How to update nRF (RAK, T114, Seed XIAO) repeater and room server firmware over the air using the new simpler DFU app?](#71-q-how-to-update-nrf-rak-t114-seed-xiao-repeater-and-room-server-firmware-over-the-air-using-the-new-simpler-dfu-app)
- [7.2 Q: How to update ESP32-based devices over the air?](#72-q-how-to-update-esp32-based-devices-over-the-air)
- [7.3 Q: Is there a way to lower the chance of a failed OTA device firmware update (DFU)?](#73-q-is-there-a-way-to-lower-the-chance-of-a-failed-ota-device-firmware-update-dfu)
- [7.4 Q are the MeshCore logo and font available?](#74-q-are-the-meshcore-logo-and-font-available)
## 1. Introduction
### 1.1. Q: What is MeshCore?
**A:** MeshCore is free and open source
**A:** MeshCore is a multi platform system for enabling secure text based communications utilising LoRa radio hardware. It can be used for Off-Grid Communication, Emergency Response & Disaster Recovery, Outdoor Activities, Tactical Security including law enforcement and private security and also IoT sensor networks. ([source](https://meshcore.co.uk/))
MeshCore is free and open source:
* MeshCore is the routing and firmware etc, available on GitHub under MIT license
* There are clients made by the community, such as the web clients, these are free to use, and some are open source too
* The cross platform mobile app developed by [Liam Cottle](https://liamcottle.net) for Android/iOS/PC etc is free to download and use
@@ -276,7 +279,18 @@ GPS on T-Deck is always enabled. You can skip the "GPS clock sync" and the T-De
### 4.4. Q: What size of SD card does the T-Deck support?
**A:** Users have had no issues using 16GB or 32GB SD cards. Format the SD card to **FAT32**.
### 4.5. Q: How do I get maps on T-Deck?
### 4.5. Q: what is the public key for the default public channel?
**A:**
T-Deck uses the same key the smartphone apps use but in base64
`izOH6cXN6mrJ5e26oRXNcg==`
The third character is the capital letter 'O', not zero `0`
The smartphone app key is in hex:
` 8b3387e9c5cdea6ac9e5edbaa115cd72`
[Source](https://discord.com/channels/826570251612323860/1330643963501351004/1354194409213792388)
### 4.6. Q: How do I get maps on T-Deck?
**A:** You need map tiles. You can get pre-downloaded map tiles here (a good way to support development):
- <https://buymeacoffee.com/ripplebiz/e/342543> (Europe)
- <https://buymeacoffee.com/ripplebiz/e/342542> (US)
@@ -290,14 +304,14 @@ There is also a modified script that adds additional error handling and parallel
UK map tiles are available separately from Andy Kirby on his discord server:
<https://discord.com/channels/826570251612323860/1330643963501351004/1331346597367386224>
### 4.6. Q: Where do the map tiles go?
### 4.7. Q: Where do the map tiles go?
Once you have the tiles downloaded, copy the `\tiles` folder to the root of your T-Deck's SD card.
### 4.7. Q: How to unlock deeper map zoom and server management features on T-Deck?
### 4.8. Q: How to unlock deeper map zoom and server management features on T-Deck?
**A:** You can download, install, and use the T-Deck firmware for free, but it has some features (map zoom, server administration) that are enabled if you purchase an unlock code for \$10 per T-Deck device.
Unlock page: <https://buymeacoffee.com/ripplebiz/e/249834>
### 4.8. Q: How to decipher the diagnostics screen on T-Deck?
### 4.9. Q: How to decipher the diagnostics screen on T-Deck?
**A: ** Space is tight on T-Deck's screen, so the information is a bit cryptic. The format is :
`{hops} l:{packet-length}({payload-len}) t:{packet-type} snr:{n} rssi:{n}`
@@ -316,12 +330,12 @@ See here for packet-type: [https://github.com/ripplebiz/MeshCore/blob/main/src/P
[Source](https://discord.com/channels/1343693475589263471/1343693475589263474/1350611321040932966)
### 4.9. Q: The T-Deck sound is too loud?
### 4.10. Q: Can you customize the sound?
### 4.10. Q: The T-Deck sound is too loud?
### 4.11. Q: Can you customize the sound?
**A:** You can customise the sounds on the T-Deck, just by placing `.mp3` files onto the `root` dir of the SD card. `startup.mp3`, `alert.mp3` and `new-advert.mp3`
### 4.11. Q: What is the 'Import from Clipboard' feature on the t-deck and is there a way to manually add nodes without having to receive adverts?
### 4.12. Q: What is the 'Import from Clipboard' feature on the t-deck and is there a way to manually add nodes without having to receive adverts?
**A:** 'Import from Clipboard' is for importing a contact via a file named 'clipboard.txt' on the SD card. The opposite, is in the Identity screen, the 'Card to Clipboard' menu, which writes to 'clipboard.txt' so you can share yourself (call these 'biz cards', that start with "meshcore://...")
@@ -450,45 +464,65 @@ This could change in the future if MeshCore develops a client firmware that repe
### 5.13. Q: Can I use a Raspberry Pi to update a MeshCore radio?
** A:** Yes.
You will need to install picocom on the pi.
`sudo apt install picocom`
Below are the instructions to flash firmware onto a supported LoRa device using a Raspberry Pi over USB serial.
Then run the following commands to setup the repeater.
```
picocom -b 115200 /dev/ttyUSB0 --imap lfcrlf
set name your_repeater_name
time epoch_time
password your_unique_password
set advert.interval 240
advert
```
Note: If using a RAK the path will most likely be /dev/ttyACM0
> Instructions for nRF devices like RAK, T1000-E, T114 are immediately after the ESP instructions
Epoch time comes from https://www.epochconverter.com/
For ESP-based devices (e.g. Heltec V3) you need:
- Download firmware file from flasher.meshcore.co.uk
- Go to the web site on a browser, find the section that has the firmware up need
- Click the Download button, right click on the file you need, for example,
- `Heltec_V3_companion_radio_ble-v1.7.1-165fb33.bin`
- Non-merged bin keeps the existing Bluetooth pairing database
- `Heltec_v3_companion_radio_usb-v1.7.1-165fb33-merged.bin`
- Merged bin overwrites everything including the bootloader, existing Bluetooth pairing database, but keeps configurations.
- Right click on the file name and copy the link and note it for later use here is an example: `https://flasher.meshcore.dev/releases/download/companion-v1.7.1/Heltec_v3_companion_radio_ble-v1.7.1-165fb33.bin`
- Run:
- `wget https://flasher.meshcore.dev/releases/download/companion-v1.7.1/Heltec_v3_companion_radio_ble-v1.7.1-165fb33.bin` to download the firmware file for your device type. or the version you need - USB, BLE, Repeater, Room Server, merged bin or non-merged bin
- If the above wget command only downloads a very small file (10K bytes instead of more than 100K byte, use this command instead:
- `wget --user-agent="Mozilla/5.0" --content-disposition "https://flasher.meshcore.dev/releases/download/companion-v1.7.1/Heltec_v3_companion_radio_usb-v1.7.1-165fb33.bin"`
- Confirm the `ttyXXXX` device path on your Raspberry Pi:
- Go to `/dev` directory, run ls command to find confirm your device path
- They are usually `/dev/ttyUSB0` for ESP devices
- For ESP-based devices, install esptool from the shell:
- `pip install esptool --break-system-packages`
- To flash, use the following command:
- For non-merged bin:
- `esptool.py -p /dev/ttyUSB0 --chip esp32-s3 write_flash 0x10000 <non-merged_firmware>.bin`
- For merged bin:
- `esptool.py -p /dev/ttyUSB0 --chip esp32-s3 write_flash 0x00000 <merged_firmware>.bin`
You can also flash the repeater using esptool. You will need to install esptool with the following command...
`pip install esptool --break-system-packages`
**Instructions for nRF devices:**
Then to flash the firmware to Heltec, obtain the .bin file from https://flasher.meshcore.co.uk/ (download all firmware link)
For nRF devices (e.g. RAK, Heltec T114) you need the following:
- Download firmware file from flasher.meshcore.co.uk
- Go to the web site on a browser, find the section that has the firmware up need
- You need the ZIP version for the adafruit flash tool (below)
- Click the Download button, right click on the ZIP file, for example:
- `RAK_4631_companion_radio_ble-v1.7.1-165fb33.zip`
- Right click on the file name and copy the link and note it for later use here is an example: `https://flasher.meshcore.dev/releases/download/companion-v1.7.1/RAK_4631_companion_radio_ble-v1.7.1-165fb33.zip`
- Run:
- `wget https://flasher.meshcore.dev/releases/download/companion-v1.7.1/RAK_4631_companion_radio_ble-v1.7.1-165fb33.zip` to download the firmware file for your device type. or the version you need - USB, BLE, Repeater, Room Server, ZIP file only
- Confirm the `ttyXXXX` device path on your Raspberry Pi:
- Go to `/dev` directory, run ls command to find confirm your device path
- They are usually `/dev/ttyACM0` for nRF devices
- For nRF-based devices, install adafruit-nrfutil
- `pip install adafruit-nrfutil --break-system-packages`
- Use this command to flash the nRF device:
- `adafruit-nrfutil --verbose dfu serial --package RAK_4631_companion_radio_usb-v1.7.1-165fb33.zip -p /dev/ttyACM0 -b 115200 --singlebank --touch 1200`
To manage a repeater or room server connected to a Pi over USB serial using shell commands, you need to install `picocom`. To install `picocom`, run the following command:
- `sudo apt install picocom`
For Heltec:
`esptool.py -p /dev/ttyUSB0 --chip esp32-s3 write_flash 0x00000 firmware.bin`
To start managing your USB serial-connected device using picocom, use the following command:
- `picocom -b 115200 /dev/ttyUSB0 --imap lfcrlf`
If flashing a visual studio code build bin file, flash with the following offset:
`esptool.py -p /dev/ttyUSB0 --chip esp32-s3 write_flash 0x10000 firmware.bin`
From here, reference repeater and room server command line commands on MeshCore github wiki here:
- https://github.com/ripplebiz/MeshCore/wiki/Repeater-&-Room-Server-CLI-Reference
For Pi
Download the zip from the online flasher website and use the following command:
Note: Requires adafruit-nrfutil command which can be installed as follows.
`pip install adafruit-nrfutil --break-system-packages`
```
adafruit-nrfutil --verbose dfu serial --package t1000_e_bootloader-0.9.1-5-g488711a_s140_7.3.0.zip -p /dev/ttyACM0 -b 115200 --singlebank --touch 1200
```
[Source](https://discord.com/channels/826570251612323860/1330643963501351004/1342120825251299388)
### 5.14. Q: Are there are projects built around MeshCore?
@@ -541,9 +575,9 @@ You can get the epoch time on <https://www.epochconverter.com/> and use it to se
**A:**
1. Connect USB-C cable to your device, per your device's instruction, get it to flash mode:
- For RAK, double click its reset button
- For T1000-e, quickly disconnect and reconnect the magnetic side of the cable from the device TWICE
- For Heltec T114, click the reset button once (the bottom button)
- For RAK, click the reset button **TWICE**
- For T1000-e, quickly disconnect and reconnect the magnetic side of the cable from the device **TWICE**
- For Heltec T114, click the reset button **TWICE** (the bottom button)
- For Xiao nRF52, click the reset button once. If that doesn't work, quickly double click the reset button twice. If that doesn't work, disconnection the board from your PC and reconnect again ([seeed studio wiki](https://wiki.seeedstudio.com/XIAO_BLE/#access-the-swd-pins-for-debugging-and-reflashing-bootloader))
5. A new folder will appear on your computer's desktop
6. Download the `flash_erase*.uf2` file for your device on flasher.meshcore.co.uk
@@ -612,7 +646,9 @@ Currently, the following boards are supported:
- Seeed Studio XIAO nRF52840 BLE SENSE
- RAK 4631
### 7.4 Q are the MeshCore logo and font available?
**A:** Yes, it is on the MeshCore github repo here: https://github.com/ripplebiz/MeshCore/tree/main/logo
---

View File

@@ -613,10 +613,10 @@ void MyMesh::begin(bool has_display) {
_prefs.cr = constrain(_prefs.cr, 5, 8);
_prefs.tx_power_dbm = constrain(_prefs.tx_power_dbm, 1, MAX_LORA_TX_POWER);
#ifdef BLE_PIN_CODE
#ifdef BLE_PIN_CODE // 123456 by default
if (_prefs.ble_pin == 0) {
#ifdef DISPLAY_CLASS
if (has_display) {
if (has_display && BLE_PIN_CODE == 123456) {
StdRNG rng;
_active_ble_pin = rng.nextInt(100000, 999999); // random pin each session
} else {

View File

@@ -10,11 +10,11 @@
#define FIRMWARE_VER_CODE 6
#ifndef FIRMWARE_BUILD_DATE
#define FIRMWARE_BUILD_DATE "29 Jun 2025"
#define FIRMWARE_BUILD_DATE "2 Jul 2025"
#endif
#ifndef FIRMWARE_VERSION
#define FIRMWARE_VERSION "v1.7.1"
#define FIRMWARE_VERSION "v1.7.2"
#endif
#if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM)

View File

@@ -22,11 +22,11 @@
/* ------------------------------ Config -------------------------------- */
#ifndef FIRMWARE_BUILD_DATE
#define FIRMWARE_BUILD_DATE "29 Jun 2025"
#define FIRMWARE_BUILD_DATE "2 Jul 2025"
#endif
#ifndef FIRMWARE_VERSION
#define FIRMWARE_VERSION "v1.7.1"
#define FIRMWARE_VERSION "v1.7.2"
#endif
#ifndef LORA_FREQ

View File

@@ -22,11 +22,11 @@
/* ------------------------------ Config -------------------------------- */
#ifndef FIRMWARE_BUILD_DATE
#define FIRMWARE_BUILD_DATE "29 Jun 2025"
#define FIRMWARE_BUILD_DATE "2 Jul 2025"
#endif
#ifndef FIRMWARE_VERSION
#define FIRMWARE_VERSION "v1.7.1"
#define FIRMWARE_VERSION "v1.7.2"
#endif
#ifndef LORA_FREQ

View File

@@ -135,7 +135,7 @@ DispatcherAction Mesh::onRecvPacket(Packet* pkt) {
int k = 0;
uint8_t path_len = data[k++];
uint8_t* path = &data[k]; k += path_len;
uint8_t extra_type = data[k++];
uint8_t extra_type = data[k++] & 0x0F; // upper 4 bits reserved for future use
uint8_t* extra = &data[k];
uint8_t extra_len = len - k; // remainder of packet (may be padded with zeroes!)
if (onPeerPathRecv(pkt, j, secret, path, path_len, extra_type, extra, extra_len)) {

View File

@@ -17,7 +17,7 @@ public:
void onSendFinished() override {
RadioLibWrapper::onSendFinished();
_radio->setPreambleLength(8); // overcomes weird issues with small and big pkts
_radio->setPreambleLength(16); // overcomes weird issues with small and big pkts
}
float getLastRSSI() const override { return ((CustomLR1110 *)_radio)->getRSSI(); }

View File

@@ -4,7 +4,7 @@
#include <helpers/RefCountedDigitalPin.h>
// LoRa radio module pins for Heltec V3
// Also for Heltec Wireless Tracker
// Also for Heltec Wireless Tracker/Paper
#define P_LORA_DIO_1 14
#define P_LORA_NSS 8
#define P_LORA_RESET RADIOLIB_NC
@@ -14,7 +14,9 @@
#define P_LORA_MOSI 10
// built-ins
#define PIN_VBAT_READ 1
#ifndef PIN_VBAT_READ // set in platformio.ini for boards like Heltec Wireless Paper (20)
#define PIN_VBAT_READ 1
#endif
#ifndef PIN_ADC_CTRL // set in platformio.ini for Heltec Wireless Tracker (2)
#define PIN_ADC_CTRL 37
#endif

View File

@@ -0,0 +1,81 @@
#pragma once
#include <Arduino.h>
// LoRa radio module pins for Meshadventurer
#define P_LORA_DIO_1 33
#define P_LORA_NSS 18
#define P_LORA_RESET 23
#define P_LORA_BUSY 32
#define P_LORA_SCLK 5
#define P_LORA_MISO 19
#define P_LORA_MOSI 27
#define PIN_VBAT_READ 35
#include "ESP32Board.h"
#include <driver/rtc_io.h>
class MeshadventurerBoard : public ESP32Board {
public:
void begin() {
ESP32Board::begin();
esp_reset_reason_t reason = esp_reset_reason();
if (reason == ESP_RST_DEEPSLEEP) {
long wakeup_source = esp_sleep_get_ext1_wakeup_status();
if (wakeup_source & (1 << P_LORA_DIO_1)) { // received a LoRa packet (while in deep sleep)
startup_reason = BD_STARTUP_RX_PACKET;
}
rtc_gpio_hold_dis((gpio_num_t)P_LORA_NSS);
rtc_gpio_deinit((gpio_num_t)P_LORA_DIO_1);
}
}
void enterDeepSleep(uint32_t secs, int pin_wake_btn = -1) {
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);
// Make sure the DIO1 and NSS GPIOs are held on required levels during deep sleep
rtc_gpio_set_direction((gpio_num_t)P_LORA_DIO_1, RTC_GPIO_MODE_INPUT_ONLY);
rtc_gpio_pulldown_en((gpio_num_t)P_LORA_DIO_1);
rtc_gpio_hold_en((gpio_num_t)P_LORA_NSS);
if (pin_wake_btn < 0) {
esp_sleep_enable_ext1_wakeup( (1L << P_LORA_DIO_1), ESP_EXT1_WAKEUP_ANY_HIGH); // wake up on: recv LoRa packet
} else {
esp_sleep_enable_ext1_wakeup( (1L << P_LORA_DIO_1) | (1L << pin_wake_btn), ESP_EXT1_WAKEUP_ANY_HIGH); // wake up on: recv LoRa packet OR wake btn
}
if (secs > 0) {
esp_sleep_enable_timer_wakeup(secs * 1000000);
}
// Finally set ESP32 into sleep
esp_deep_sleep_start(); // CPU halts here and never returns!
}
void powerOff() override {
// TODO: re-enable this when there is a definite wake-up source pin:
// enterDeepSleep(0);
}
uint16_t getBattMilliVolts() override {
analogReadResolution(12);
uint32_t raw = 0;
for (int i = 0; i < 4; i++) {
raw += analogReadMilliVolts(PIN_VBAT_READ);
}
raw = raw / 4;
return (2 * raw);
}
const char* getManufacturerName() const override {
return "Meshadventurer";
}
};

View File

@@ -0,0 +1,116 @@
#include "E213Display.h"
#include "../../MeshCore.h"
bool E213Display::begin() {
if (_init) return true;
powerOn();
display.begin();
// Set to landscape mode rotated 180 degrees
display.setRotation(3);
_init = true;
_isOn = true;
clear();
display.fastmodeOn(); // Enable fast mode for quicker (partial) updates
return true;
}
void E213Display::powerOn() {
#ifdef PIN_VEXT_EN
pinMode(PIN_VEXT_EN, OUTPUT);
digitalWrite(PIN_VEXT_EN, LOW); // Active low
delay(50); // Allow power to stabilize
#endif
}
void E213Display::powerOff() {
#ifdef PIN_VEXT_EN
digitalWrite(PIN_VEXT_EN, HIGH); // Turn off power
#endif
}
void E213Display::turnOn() {
if (!_init) begin();
powerOn();
_isOn = true;
}
void E213Display::turnOff() {
powerOff();
_isOn = false;
}
void E213Display::clear() {
display.clear();
}
void E213Display::startFrame(Color bkg) {
// Fill screen with white first to ensure clean background
display.fillRect(0, 0, width(), height(), WHITE);
if (bkg == LIGHT) {
// Fill with black if light background requested (inverted for e-ink)
display.fillRect(0, 0, width(), height(), BLACK);
}
}
void E213Display::setTextSize(int sz) {
// The library handles text size internally
display.setTextSize(sz);
}
void E213Display::setColor(Color c) {
// implemented in individual display methods
}
void E213Display::setCursor(int x, int y) {
display.setCursor(x, y);
}
void E213Display::print(const char *str) {
display.print(str);
}
void E213Display::fillRect(int x, int y, int w, int h) {
display.fillRect(x, y, w, h, BLACK);
}
void E213Display::drawRect(int x, int y, int w, int h) {
display.drawRect(x, y, w, h, BLACK);
}
void E213Display::drawXbm(int x, int y, const uint8_t *bits, int w, int h) {
// Width in bytes for bitmap processing
uint16_t widthInBytes = (w + 7) / 8;
// Process the bitmap row by row
for (int by = 0; by < h; by++) {
// Scan across the row bit by bit
for (int bx = 0; bx < w; bx++) {
// Get the current bit using MSB ordering (like GxEPDDisplay)
uint16_t byteOffset = (by * widthInBytes) + (bx / 8);
uint8_t bitMask = 0x80 >> (bx & 7);
bool bitSet = bits[byteOffset] & bitMask;
// If the bit is set, draw the pixel
if (bitSet) {
display.drawPixel(x + bx, y + by, BLACK);
}
}
}
}
uint16_t E213Display::getTextWidth(const char *str) {
int16_t x1, y1;
uint16_t w, h;
display.getTextBounds(str, 0, 0, &x1, &y1, &w, &h);
return w;
}
void E213Display::endFrame() {
display.update();
}

View File

@@ -0,0 +1,37 @@
#pragma once
#include "DisplayDriver.h"
#include <SPI.h>
#include <Wire.h>
#include <heltec-eink-modules.h>
// Display driver for E213 e-ink display
class E213Display : public DisplayDriver {
EInkDisplay_VisionMasterE213 display;
bool _init = false;
bool _isOn = false;
public:
E213Display() : DisplayDriver(250, 122) {}
bool begin();
bool isOn() override { return _isOn; }
void turnOn() override;
void turnOff() override;
void clear() override;
void startFrame(Color bkg = DARK) override;
void setTextSize(int sz) override;
void setColor(Color c) override;
void setCursor(int x, int y) override;
void print(const char *str) override;
void fillRect(int x, int y, int w, int h) override;
void drawRect(int x, int y, int w, int h) override;
void drawXbm(int x, int y, const uint8_t *bits, int w, int h) override;
uint16_t getTextWidth(const char *str) override;
void endFrame() override;
private:
void powerOn();
void powerOff();
};

View File

@@ -23,43 +23,16 @@ HWTSensorManager sensors = HWTSensorManager(nmea);
DISPLAY_CLASS display(&board.periph_power); // peripheral power pin is shared
#endif
#ifndef LORA_CR
#define LORA_CR 5
#endif
bool radio_init() {
fallback_clock.begin();
rtc_clock.begin(Wire);
#ifdef SX126X_DIO3_TCXO_VOLTAGE
float tcxo = SX126X_DIO3_TCXO_VOLTAGE;
#else
float tcxo = 1.6f;
#endif
#if defined(P_LORA_SCLK)
spi.begin(P_LORA_SCLK, P_LORA_MISO, P_LORA_MOSI);
#endif
int status = radio.begin(LORA_FREQ, LORA_BW, LORA_SF, LORA_CR, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, LORA_TX_POWER, 8, tcxo);
if (status != RADIOLIB_ERR_NONE) {
Serial.print("ERROR: radio init failed: ");
Serial.println(status);
return false; // fail
}
radio.setCRC(1);
#ifdef SX126X_CURRENT_LIMIT
radio.setCurrentLimit(SX126X_CURRENT_LIMIT);
#endif
#ifdef SX126X_DIO2_AS_RF_SWITCH
radio.setDio2AsRfSwitch(SX126X_DIO2_AS_RF_SWITCH);
#endif
#ifdef SX126X_RX_BOOSTED_GAIN
radio.setRxBoostedGainMode(SX126X_RX_BOOSTED_GAIN);
return radio.std_init(&spi);
#else
return radio.std_init();
#endif
return true; // success
}
uint32_t radio_get_rng_seed() {

View File

@@ -96,7 +96,7 @@ build_flags =
-D DISPLAY_CLASS=SSD1306Display
-D MAX_CONTACTS=100
-D MAX_GROUP_CHANNELS=8
-D BLE_PIN_CODE=0
-D BLE_PIN_CODE=123456
-D BLE_DEBUG_LOGGING=1
-D OFFLINE_QUEUE_SIZE=256
; -D MESH_PACKET_LOGGING=1

View File

@@ -114,7 +114,7 @@ build_flags =
-D MAX_CONTACTS=100
-D MAX_GROUP_CHANNELS=8
-D DISPLAY_CLASS=SSD1306Display
-D BLE_PIN_CODE=0 ; dynamic, random PIN
-D BLE_PIN_CODE=123456 ; dynamic, random PIN
-D BLE_DEBUG_LOGGING=1
-D OFFLINE_QUEUE_SIZE=256
; -D MESH_PACKET_LOGGING=1

View File

@@ -0,0 +1,84 @@
[Heltec_Wireless_Paper_base]
extends = esp32_base
board = esp32-s3-devkitc-1
build_flags =
${esp32_base.build_flags}
-I variants/heltec_wireless_paper
-D HELTEC_WIRELESS_PAPER
-D RADIO_CLASS=CustomSX1262
-D WRAPPER_CLASS=CustomSX1262Wrapper
-D LORA_TX_POWER=22
-D P_LORA_TX_LED=18
; -D PIN_BOARD_SDA=17
; -D PIN_BOARD_SCL=18
-D PIN_USER_BTN=0
-D PIN_VEXT_EN=45
-D PIN_VBAT_READ=20
-D PIN_ADC_CTRL=19
-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 DISP_CS=4
-D DISP_BUSY=7
-D DISP_DC=5
-D DISP_RST=6
-D DISP_SCLK=3
-D DISP_MOSI=2
-D ARDUINO_heltec_wifi_lora_32_V3
-D WIRELESS_PAPER
build_src_filter = ${esp32_base.build_src_filter}
+<../variants/heltec_wireless_paper>
lib_deps =
${esp32_base.lib_deps}
todd-herbert/heltec-eink-modules @ 4.5.0
[env:Heltec_Wireless_Paper_companion_radio_ble]
extends = Heltec_Wireless_Paper_base
build_flags =
${Heltec_Wireless_Paper_base.build_flags}
-D MAX_CONTACTS=100
-D MAX_GROUP_CHANNELS=8
-D DISPLAY_CLASS=E213Display
-D BLE_PIN_CODE=0 ; dynamic, random PIN
-D BLE_DEBUG_LOGGING=1
-D OFFLINE_QUEUE_SIZE=256
build_src_filter = ${Heltec_Wireless_Paper_base.build_src_filter}
+<helpers/ui/E213Display.cpp>
+<helpers/esp32/*.cpp>
+<../examples/companion_radio>
lib_deps =
${Heltec_Wireless_Paper_base.lib_deps}
densaugeo/base64 @ ~1.4.0
[env:Heltec_Wireless_Paper_repeater]
extends = Heltec_Wireless_Paper_base
build_flags =
${Heltec_Wireless_Paper_base.build_flags}
-D DISPLAY_CLASS=E213Display
-D ADVERT_NAME='"Heltec WP Repeater"'
-D ADVERT_LAT=0.0
-D ADVERT_LON=0.0
build_src_filter = ${Heltec_Wireless_Paper_base.build_src_filter}
+<helpers/ui/E213Display.cpp>
+<../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 =
${Heltec_Wireless_Paper_base.build_flags}
-D DISPLAY_CLASS=E213Display
-D ADVERT_NAME='"Heltec WP Room"'
-D ADVERT_LAT=0.0
-D ADVERT_LON=0.0
-D ADMIN_PASSWORD='"password"'
-D ROOM_PASSWORD='"hello"'
build_src_filter = ${Heltec_Wireless_Paper_base.build_src_filter}
+<helpers/ui/E213Display.cpp>
+<../examples/simple_room_server>
lib_deps =
${Heltec_Wireless_Paper_base.lib_deps}
${esp32_ota.lib_deps}

View File

@@ -0,0 +1,45 @@
#include "target.h"
#include <Arduino.h>
HeltecV3Board board;
static SPIClass spi;
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);
ESP32RTCClock fallback_clock;
AutoDiscoverRTCClock rtc_clock(fallback_clock);
SensorManager sensors;
#ifdef DISPLAY_CLASS
DISPLAY_CLASS display;
#endif
bool radio_init() {
fallback_clock.begin();
rtc_clock.begin(Wire);
return radio.std_init(&spi);
}
uint32_t radio_get_rng_seed() {
return radio.random(0x7FFFFFFF);
}
void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr) {
radio.setFrequency(freq);
radio.setSpreadingFactor(sf);
radio.setBandwidth(bw);
radio.setCodingRate(cr);
}
void radio_set_tx_power(uint8_t dbm) {
radio.setOutputPower(dbm);
}
mesh::LocalIdentity radio_new_identity() {
RadioNoiseListener rng(radio);
return mesh::LocalIdentity(&rng); // create new random identity
}

View File

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

View File

@@ -3,13 +3,8 @@
ESP32Board board;
#if defined(P_LORA_SCLK)
static SPIClass spi;
RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, spi);
#else
RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY);
#endif
static SPIClass spi;
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);
ESP32RTCClock fallback_clock;
@@ -28,35 +23,7 @@ bool radio_init() {
fallback_clock.begin();
rtc_clock.begin(Wire);
#ifdef SX126X_DIO3_TCXO_VOLTAGE
float tcxo = SX126X_DIO3_TCXO_VOLTAGE;
#else
float tcxo = 1.6f;
#endif
#if defined(P_LORA_SCLK)
spi.begin(P_LORA_SCLK, P_LORA_MISO, P_LORA_MOSI);
#endif
int status = radio.begin(LORA_FREQ, LORA_BW, LORA_SF, LORA_CR, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, LORA_TX_POWER, 8, tcxo);
if (status != RADIOLIB_ERR_NONE) {
Serial.print("ERROR: radio init failed: ");
Serial.println(status);
return false; // fail
}
radio.setCRC(1);
#ifdef SX126X_CURRENT_LIMIT
radio.setCurrentLimit(SX126X_CURRENT_LIMIT);
#endif
#ifdef SX126X_DIO2_AS_RF_SWITCH
radio.setDio2AsRfSwitch(SX126X_DIO2_AS_RF_SWITCH);
#endif
#ifdef SX126X_RX_BOOSTED_GAIN
radio.setRxBoostedGainMode(SX126X_RX_BOOSTED_GAIN);
#endif
return true; // success
return radio.std_init(&spi);
}
uint32_t radio_get_rng_seed() {

View File

@@ -0,0 +1,234 @@
[Meshadventurer]
extends = esp32_base
board = esp32doit-devkit-v1
board_build.partitions = min_spiffs.csv ; get around 4mb flash limit
build_flags =
${esp32_base.build_flags}
-I variants/meshadventurer
-D MESHADVENTURER
-D P_LORA_TX_LED=2
-D PIN_VBAT_READ=35
-D PIN_USER_BTN_ANA=39
-D P_LORA_DIO_1=33
-D P_LORA_NSS=18
-D P_LORA_RESET=23
-D P_LORA_BUSY=32
-D P_LORA_SCLK=5
-D P_LORA_MOSI=27
-D P_LORA_MISO=19
-D SX126X_TXEN=13
-D SX126X_RXEN=14
-D PIN_BOARD_SDA=21
-D PIN_BOARD_SCL=22
-D SX126X_DIO2_AS_RF_SWITCH=false
-D SX126X_DIO3_TCXO_VOLTAGE=1.8
-D SX126X_RX_BOOSTED_GAIN=1
-D PIN_GPS_RX=12
-D PIN_GPS_TX=15
-D DISPLAY_CLASS=SSD1306Display
build_src_filter = ${esp32_base.build_src_filter}
+<../variants/meshadventurer>
lib_deps =
${esp32_base.lib_deps}
stevemarple/MicroNMEA @ ^2.0.6
adafruit/Adafruit SSD1306 @ ^2.5.13
[env:Meshadventurer_sx1262_repeater]
extends = Meshadventurer
build_src_filter = ${Meshadventurer.build_src_filter}
+<../examples/simple_repeater>
+<helpers/ui/SSD1306Display.cpp>
build_flags =
${Meshadventurer.build_flags}
-D RADIO_CLASS=CustomSX1262
-D WRAPPER_CLASS=CustomSX1262Wrapper
-D LORA_TX_POWER=22
-D ADVERT_NAME='"Meshadventurer 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
lib_deps =
${Meshadventurer.lib_deps}
${esp32_ota.lib_deps}
[env:Meshadventurer_sx1268_repeater]
extends = Meshadventurer
build_src_filter = ${Meshadventurer.build_src_filter}
+<../examples/simple_repeater>
+<helpers/ui/SSD1306Display.cpp>
build_flags =
${Meshadventurer.build_flags}
-D RADIO_CLASS=CustomSX1268
-D WRAPPER_CLASS=CustomSX1268Wrapper
-D LORA_TX_POWER=22
-D ADVERT_NAME='"Meshadventurer 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
lib_deps =
${Meshadventurer.lib_deps}
${esp32_ota.lib_deps}
[env:Meshadventurer_sx1262_companion_radio_usb]
extends = Meshadventurer
build_src_filter = ${Meshadventurer.build_src_filter}
+<../examples/companion_radio>
+<helpers/ui/SSD1306Display.cpp>
build_flags =
${Meshadventurer.build_flags}
-D RADIO_CLASS=CustomSX1262
-D WRAPPER_CLASS=CustomSX1262Wrapper
-D LORA_TX_POWER=22
-D MAX_CONTACTS=100
-D MAX_GROUP_CHANNELS=8
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
lib_deps =
${Meshadventurer.lib_deps}
densaugeo/base64 @ ~1.4.0
[env:Meshadventurer_sx1262_companion_radio_ble]
extends = Meshadventurer
build_src_filter = ${Meshadventurer.build_src_filter}
+<../examples/companion_radio>
+<helpers/esp32/*.cpp>
+<helpers/ui/SSD1306Display.cpp>
build_flags =
${Meshadventurer.build_flags}
-D RADIO_CLASS=CustomSX1262
-D WRAPPER_CLASS=CustomSX1262Wrapper
-D LORA_TX_POWER=22
-D MAX_CONTACTS=100
-D MAX_GROUP_CHANNELS=8
-D BLE_PIN_CODE=123456
-D BLE_DEBUG_LOGGING=1
-D OFFLINE_QUEUE_SIZE=256
-D MESH_PACKET_LOGGING=1
-D MESH_DEBUG=1
lib_deps =
${Meshadventurer.lib_deps}
densaugeo/base64 @ ~1.4.0
[env:Meshadventurer_sx1262_terminal_chat]
extends = Meshadventurer
build_flags =
${Meshadventurer.build_flags}
-D RADIO_CLASS=CustomSX1262
-D WRAPPER_CLASS=CustomSX1262Wrapper
-D LORA_TX_POWER=22
-D MAX_CONTACTS=100
-D MAX_GROUP_CHANNELS=1
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
build_src_filter = ${Meshadventurer.build_src_filter}
+<../examples/simple_secure_chat/main.cpp>
+<helpers/ui/SSD1306Display.cpp>
lib_deps =
${Meshadventurer.lib_deps}
densaugeo/base64 @ ~1.4.0
[env:Meshadventurer_sx1262_room_server]
extends = Meshadventurer
build_flags =
${Meshadventurer.build_flags}
-D RADIO_CLASS=CustomSX1262
-D WRAPPER_CLASS=CustomSX1262Wrapper
-D LORA_TX_POWER=22
-D ADVERT_NAME='"Meshadventurer 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 = ${Meshadventurer.build_src_filter}
+<../examples/simple_room_server>
+<helpers/ui/SSD1306Display.cpp>
lib_deps =
${Meshadventurer.lib_deps}
${esp32_ota.lib_deps}
[env:Meshadventurer_sx1268_companion_radio_usb]
extends = Meshadventurer
build_src_filter = ${Meshadventurer.build_src_filter}
+<../examples/companion_radio>
+<helpers/ui/SSD1306Display.cpp>
build_flags =
${Meshadventurer.build_flags}
-D RADIO_CLASS=CustomSX1268
-D WRAPPER_CLASS=CustomSX1268Wrapper
-D LORA_TX_POWER=22
-D MAX_CONTACTS=100
-D MAX_GROUP_CHANNELS=8
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
lib_deps =
${Meshadventurer.lib_deps}
densaugeo/base64 @ ~1.4.0
[env:Meshadventurer_sx1268_companion_radio_ble]
extends = Meshadventurer
build_src_filter = ${Meshadventurer.build_src_filter}
+<../examples/companion_radio>
+<helpers/esp32/*.cpp>
+<helpers/ui/SSD1306Display.cpp>
build_flags =
${Meshadventurer.build_flags}
-D RADIO_CLASS=CustomSX1268
-D WRAPPER_CLASS=CustomSX1268Wrapper
-D LORA_TX_POWER=22
-D MAX_CONTACTS=100
-D MAX_GROUP_CHANNELS=8
-D BLE_PIN_CODE=123456
-D BLE_DEBUG_LOGGING=1
-D OFFLINE_QUEUE_SIZE=256
-D MESH_PACKET_LOGGING=1
-D MESH_DEBUG=1
lib_deps =
${Meshadventurer.lib_deps}
densaugeo/base64 @ ~1.4.0
[env:Meshadventurer_sx1268_terminal_chat]
extends = Meshadventurer
build_flags =
${Meshadventurer.build_flags}
-D RADIO_CLASS=CustomSX1268
-D WRAPPER_CLASS=CustomSX1268Wrapper
-D LORA_TX_POWER=22
-D MAX_CONTACTS=100
-D MAX_GROUP_CHANNELS=1
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
build_src_filter = ${Meshadventurer.build_src_filter}
+<../examples/simple_secure_chat/main.cpp>
+<helpers/ui/SSD1306Display.cpp>
lib_deps =
${Meshadventurer.lib_deps}
densaugeo/base64 @ ~1.4.0
[env:Meshadventurer_sx1268_room_server]
extends = Meshadventurer
build_flags =
${Meshadventurer.build_flags}
-D RADIO_CLASS=CustomSX1268
-D WRAPPER_CLASS=CustomSX1268Wrapper
-D LORA_TX_POWER=22
-D ADVERT_NAME='"Meshadventurer 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 = ${Meshadventurer.build_src_filter}
+<../examples/simple_room_server>
+<helpers/ui/SSD1306Display.cpp>
lib_deps =
${Meshadventurer.lib_deps}
${esp32_ota.lib_deps}

View File

@@ -0,0 +1,152 @@
#include <Arduino.h>
#include "target.h"
#include <helpers/sensors/MicroNMEALocationProvider.h>
MeshadventurerBoard board;
#if defined(P_LORA_SCLK)
static SPIClass spi;
RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, spi);
#else
RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY);
#endif
WRAPPER_CLASS radio_driver(radio, board);
ESP32RTCClock fallback_clock;
AutoDiscoverRTCClock rtc_clock(fallback_clock);
MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Serial1);
MASensorManager sensors = MASensorManager(nmea);
#ifdef DISPLAY_CLASS
DISPLAY_CLASS display;
#endif
#ifndef LORA_CR
#define LORA_CR 5
#endif
bool radio_init() {
fallback_clock.begin();
rtc_clock.begin(Wire);
#ifdef SX126X_DIO3_TCXO_VOLTAGE
float tcxo = SX126X_DIO3_TCXO_VOLTAGE;
#else
float tcxo = 1.6f;
#endif
#if defined(P_LORA_SCLK)
spi.begin(P_LORA_SCLK, P_LORA_MISO, P_LORA_MOSI);
#endif
int status = radio.begin(LORA_FREQ, LORA_BW, LORA_SF, LORA_CR, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, LORA_TX_POWER, 8, tcxo);
if (status != RADIOLIB_ERR_NONE) {
Serial.print("ERROR: radio init failed: ");
Serial.println(status);
return false; // fail
}
radio.setCRC(1);
#if defined(SX126X_RXEN) && defined(SX126X_TXEN)
radio.setRfSwitchPins(SX126X_RXEN, SX126X_TXEN);
#endif
#ifdef SX126X_CURRENT_LIMIT
radio.setCurrentLimit(SX126X_CURRENT_LIMIT);
#endif
#ifdef SX126X_DIO2_AS_RF_SWITCH
radio.setDio2AsRfSwitch(SX126X_DIO2_AS_RF_SWITCH);
#endif
#ifdef SX126X_RX_BOOSTED_GAIN
radio.setRxBoostedGainMode(SX126X_RX_BOOSTED_GAIN);
#endif
return true; // success
}
uint32_t radio_get_rng_seed() {
return radio.random(0x7FFFFFFF);
}
void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr) {
radio.setFrequency(freq);
radio.setSpreadingFactor(sf);
radio.setBandwidth(bw);
radio.setCodingRate(cr);
}
void radio_set_tx_power(uint8_t dbm) {
radio.setOutputPower(dbm);
}
mesh::LocalIdentity radio_new_identity() {
RadioNoiseListener rng(radio);
return mesh::LocalIdentity(&rng); // create new random identity
}
void MASensorManager::start_gps() {
if(!gps_active) {
MESH_DEBUG_PRINTLN("starting GPS");
gps_active = true;
}
}
void MASensorManager::stop_gps() {
if(gps_active) {
MESH_DEBUG_PRINTLN("stopping GPS");
gps_active = false;
}
}
bool MASensorManager::begin() {
Serial1.setPins(PIN_GPS_RX, PIN_GPS_TX);
Serial1.begin(9600);
delay(500);
return true;
}
bool MASensorManager::querySensors(uint8_t requester_permissions, CayenneLPP& telemetry) {
if(requester_permissions & TELEM_PERM_LOCATION) { // does requester have permission?
telemetry.addGPS(TELEM_CHANNEL_SELF, node_lat, node_lon, node_altitude);
}
return true;
}
void MASensorManager::loop() {
static long next_gps_update = 0;
_location->loop();
if(millis() > next_gps_update && gps_active) {
if(_location->isValid()) {
node_lat = ((double)_location->getLatitude()) / 1000000.;
node_lon = ((double)_location->getLongitude()) / 1000000.;
node_altitude = ((double)_location->getAltitude()) / 1000.0;
MESH_DEBUG_PRINTLN("lat %f lon %f", node_lat, node_lon);
}
next_gps_update = millis() + 1000;
}
}
int MASensorManager::getNumSettings() const { return 1; } // just one supported: "gps" (power switch)
const char* MASensorManager::getSettingName(int i) const {
return i == 0 ? "gps" : NULL;
}
const char* MASensorManager::getSettingValue(int i) const {
if(i == 0) {
return gps_active ? "1" : "0";
}
return NULL;
}
bool MASensorManager::setSettingValue(const char* name, const char* value) {
if(strcmp(name, "gps") == 0) {
if(strcmp(value, "0") == 0) {
stop_gps();
} else {
start_gps();
}
return true;
}
return false; // not supported
}

View File

@@ -0,0 +1,46 @@
#pragma once
#define RADIOLIB_STATIC_ONLY 1
#include <RadioLib.h>
#include <helpers/RadioLibWrappers.h>
#include <helpers/MeshadventurerBoard.h>
#include <helpers/CustomSX1262Wrapper.h>
#include <helpers/CustomSX1268Wrapper.h>
#include <helpers/AutoDiscoverRTCClock.h>
#include <helpers/SensorManager.h>
#include <helpers/sensors/LocationProvider.h>
#ifdef DISPLAY_CLASS
#include <helpers/ui/SSD1306Display.h>
#endif
class MASensorManager : public SensorManager {
bool gps_active = false;
LocationProvider * _location;
void start_gps();
void stop_gps();
public:
MASensorManager(LocationProvider &location): _location(&location) { }
bool begin() override;
bool querySensors(uint8_t requester_permissions, CayenneLPP& telemetry) override;
void loop() override;
int getNumSettings() const override;
const char* getSettingName(int i) const override;
const char* getSettingValue(int i) const override;
bool setSettingValue(const char* name, const char* value) override;
};
extern MeshadventurerBoard board;
extern WRAPPER_CLASS radio_driver;
extern AutoDiscoverRTCClock rtc_clock;
extern MASensorManager sensors;
#ifdef DISPLAY_CLASS
extern DISPLAY_CLASS display;
#endif
bool radio_init();
uint32_t radio_get_rng_seed();
void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr);
void radio_set_tx_power(uint8_t dbm);
mesh::LocalIdentity radio_new_identity();

View File

@@ -0,0 +1,44 @@
// For OLED LCD
#define I2C_SDA 21
#define I2C_SCL 22
// For GPS, 'undef's not needed
#define GPS_TX_PIN 15
#define GPS_RX_PIN 12
#define PIN_GPS_EN 4
#define GPS_POWER_TOGGLE // Moved definition from platformio.ini to here
#define BUTTON_PIN 39 // The middle button GPIO on the T-Beam
#define BATTERY_PIN 35 // A battery voltage measurement pin, voltage divider connected here to measure battery voltage
#define ADC_CHANNEL ADC1_GPIO35_CHANNEL
#define ADC_MULTIPLIER 2
#define EXT_PWR_DETECT 4 // Pin to detect connected external power source for LILYGO® TTGO T-Energy T18 and other DIY boards
#define EXT_NOTIFY_OUT 12 // Overridden default pin to use for Ext Notify Module (#975).
#define LED_PIN 2 // add status LED (compatible with core-pcb and DIY targets)
// Radio
#define USE_SX1262 // E22-900M30S uses SX1262
#define USE_SX1268 // E22-400M30S uses SX1268
#define SX126X_MAX_POWER 22 // Outputting 22dBm from SX1262 results in ~30dBm E22-900M30S output (module only uses last stage of the YP2233W PA)
#define SX126X_DIO3_TCXO_VOLTAGE 1.8 // E22 series TCXO reference voltage is 1.8V
#define SX126X_CS 18 // EBYTE module's NSS pin
#define SX126X_SCK 5 // EBYTE module's SCK pin
#define SX126X_MOSI 27 // EBYTE module's MOSI pin
#define SX126X_MISO 19 // EBYTE module's MISO pin
#define SX126X_RESET 23 // EBYTE module's NRST pin
#define SX126X_BUSY 32 // EBYTE module's BUSY pin
#define SX126X_DIO1 33 // EBYTE module's DIO1 pin
// The E22's TXEN pin is connected to MCU pin, E22's RXEN pin is connected to MCU pin (allows for ramping up PA before transmission
// Don't define DIO2_AS_RF_SWITCH because we only use DIO2 or an MCU pin mutually exclusively to connect to E22's TXEN (to prevent
// a short if they are both connected at the same time and there's a slight non-neglibible delay and/or voltage difference between
// DIO2 and TXEN).
#define SX126X_TXEN 13 // Schematic connects EBYTE module's TXEN pin to MCU
#define SX126X_RXEN 14 // Schematic connects EBYTE module's RXEN pin to MCU
#define LORA_CS SX126X_CS // Compatibility with variant file configuration structure
#define LORA_SCK SX126X_SCK // Compatibility with variant file configuration structure
#define LORA_MOSI SX126X_MOSI // Compatibility with variant file configuration structure
#define LORA_MISO SX126X_MISO // Compatibility with variant file configuration structure
#define LORA_DIO1 SX126X_DIO1 // Compatibility with variant file configuration structure

View File

@@ -36,7 +36,7 @@ build_flags =
-I src/helpers/ui
-D MAX_CONTACTS=100
-D MAX_GROUP_CHANNELS=8
-D BLE_PIN_CODE=0
-D BLE_PIN_CODE=123456
-D BLE_DEBUG_LOGGING=1
-D OFFLINE_QUEUE_SIZE=256
-D DISPLAY_CLASS=SH1106Display

View File

@@ -54,7 +54,7 @@ bool radio_init() {
SPI.setPins(P_LORA_MISO, P_LORA_SCLK, P_LORA_MOSI);
SPI.begin();
int status = radio.begin(LORA_FREQ, LORA_BW, LORA_SF, LORA_CR, RADIOLIB_LR11X0_LORA_SYNC_WORD_PRIVATE, LORA_TX_POWER, 8, tcxo);
int status = radio.begin(LORA_FREQ, LORA_BW, LORA_SF, LORA_CR, RADIOLIB_LR11X0_LORA_SYNC_WORD_PRIVATE, LORA_TX_POWER, 16, tcxo);
if (status != RADIOLIB_ERR_NONE) {
Serial.print("ERROR: radio init failed: ");
Serial.println(status);