Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 84 additions & 0 deletions src/helpers/radiolib/CustomLR1121.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
#pragma once

#include <RadioLib.h>
#include "MeshCore.h"

#define LR1121_IRQ_HAS_PREAMBLE 0b0000000100 // 4 4 valid LoRa header received
#define LR1121_IRQ_HEADER_VALID 0b0000010000 // 4 4 valid LoRa header received

class CustomLR1121 : public LR1121 {
public:
CustomLR1121(Module *mod) : LR1121(mod) { }

size_t getPacketLength(bool update) override {
size_t len = LR1121::getPacketLength(update);
if (len == 0 && getIrqStatus() & RADIOLIB_LR11X0_IRQ_HEADER_ERR) {
// we've just recieved a corrupted packet
// this may have triggered a bug causing subsequent packets to be shifted
// call standby() to return radio to known-good state
// recvRaw will call startReceive() to restart rx
MESH_DEBUG_PRINTLN("LR1121: got header err, calling standby()");
standby();
}
return len;
}

RadioLibTime_t getTimeOnAir(size_t len) override {
// calculate number of symbols
float N_symbol = 0;
if(this->codingRate <= RADIOLIB_LR11X0_LORA_CR_4_8_SHORT) {
// legacy coding rate - nice and simple
// get SF coefficients
float coeff1 = 0;
int16_t coeff2 = 0;
int16_t coeff3 = 0;
if(this->spreadingFactor < 7) {
// SF5, SF6
coeff1 = 6.25;
coeff2 = 4*this->spreadingFactor;
coeff3 = 4*this->spreadingFactor;
} else if(this->spreadingFactor < 11) {
// SF7. SF8, SF9, SF10
coeff1 = 4.25;
coeff2 = 4*this->spreadingFactor + 8;
coeff3 = 4*this->spreadingFactor;
} else {
// SF11, SF12
coeff1 = 4.25;
coeff2 = 4*this->spreadingFactor + 8;
coeff3 = 4*(this->spreadingFactor - 2);
}

// get CRC length
int16_t N_bitCRC = 16;
if(this->crcTypeLoRa == RADIOLIB_LR11X0_LORA_CRC_DISABLED) {
N_bitCRC = 0;
}

// get header length
int16_t N_symbolHeader = 20;
if(this->headerType == RADIOLIB_LR11X0_LORA_HEADER_IMPLICIT) {
N_symbolHeader = 0;
}

// calculate number of LoRa preamble symbols - NO! Lora preamble is already in symbols
// uint32_t N_symbolPreamble = (this->preambleLengthLoRa & 0x0F) * (uint32_t(1) << ((this->preambleLengthLoRa & 0xF0) >> 4));

// calculate the number of symbols - nope
// N_symbol = (float)N_symbolPreamble + coeff1 + 8.0f + ceilf((float)RADIOLIB_MAX((int16_t)(8 * len + N_bitCRC - coeff2 + N_symbolHeader), (int16_t)0) / (float)coeff3) * (float)(this->codingRate + 4);
// calculate the number of symbols - using only preamblelora because it's already in symbols
N_symbol = (float)preambleLengthLoRa + coeff1 + 8.0f + ceilf((float)RADIOLIB_MAX((int16_t)(8 * len + N_bitCRC - coeff2 + N_symbolHeader), (int16_t)0) / (float)coeff3) * (float)(this->codingRate + 4);
} else {
// long interleaving - not needed for this modem
}

// get time-on-air in us
return(((uint32_t(1) << this->spreadingFactor) / this->bandwidthKhz) * N_symbol * 1000.0f);
}

bool isReceiving() {
uint16_t irq = getIrqStatus();
bool detected = ((irq & LR1121_IRQ_HEADER_VALID) || (irq & LR1121_IRQ_HAS_PREAMBLE));
return detected;
}
};
26 changes: 26 additions & 0 deletions src/helpers/radiolib/CustomLR1121Wrapper.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#pragma once

#include "CustomLR1121.h"
#include "RadioLibWrappers.h"

class CustomLR1121Wrapper : public RadioLibWrapper {
public:
CustomLR1121Wrapper(CustomLR1121& radio, mesh::MainBoard& board) : RadioLibWrapper(radio, board) { }
bool isReceivingPacket() override {
return ((CustomLR1121 *)_radio)->isReceiving();
}
float getCurrentRSSI() override {
float rssi = -110;
((CustomLR1121 *)_radio)->getRssiInst(&rssi);
return rssi;
}

void onSendFinished() override {
RadioLibWrapper::onSendFinished();
_radio->setPreambleLength(16); // overcomes weird issues with small and big pkts
}

float getLastRSSI() const override { return ((CustomLR1121 *)_radio)->getRSSI(); }
float getLastSNR() const override { return ((CustomLR1121 *)_radio)->getSNR(); }
int16_t setRxBoostedGainMode(bool en) { return ((CustomLR1121 *)_radio)->setRxBoostedGainMode(en); };
};
124 changes: 124 additions & 0 deletions variants/lilygo_t3s3_lr1121/platformio.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
[LilyGo_T3S3_lr1121]
extends = esp32_base
board = t3_s3_v1_x
build_flags =
${esp32_base.build_flags}
-I variants/lilygo_t3s3_lr1121
-D LILYGO_T3S3
-D P_LORA_DIO_9=36
-D P_LORA_BUSY=34
-D P_LORA_NSS=7
-D P_LORA_RESET=8
-D P_LORA_SCLK=5
-D P_LORA_MISO=3
-D P_LORA_MOSI=6
-D P_LORA_TX_LED=37
-D PIN_VBAT_READ=1
-D PIN_USER_BTN=0
-D PIN_BOARD_SDA=18
-D PIN_BOARD_SCL=17
-D PIN_OLED_RESET=21
-D RADIO_CLASS=CustomLR1121
-D WRAPPER_CLASS=CustomLR1121Wrapper
-D LORA_TX_POWER=22
build_src_filter = ${esp32_base.build_src_filter}
+<../variants/lilygo_t3s3_lr1121>
lib_deps =
${esp32_base.lib_deps}
adafruit/Adafruit SSD1306 @ ^2.5.13

; === LilyGo T3S3 with LR1121 environments ===
[env:LilyGo_T3S3_lr1121_repeater]
extends = LilyGo_T3S3_lr1121
build_flags =
${LilyGo_T3S3_lr1121.build_flags}
-D DISPLAY_CLASS=SSD1306Display
-D ADVERT_NAME='"T3S3-1121 Repeater"'
-D ADVERT_LAT=0.0
-D ADVERT_LON=0.0
-D ADMIN_PASSWORD='"password"'
-D MAX_NEIGHBOURS=50
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
build_src_filter = ${LilyGo_T3S3_lr1121.build_src_filter}
+<helpers/ui/SSD1306Display.cpp>
+<../examples/simple_repeater>
lib_deps =
${LilyGo_T3S3_lr1121.lib_deps}
${esp32_ota.lib_deps}

[env:LilyGo_T3S3_lr1121_terminal_chat]
extends = LilyGo_T3S3_lr1121
build_flags =
${LilyGo_T3S3_lr1121.build_flags}
-D MAX_CONTACTS=300
-D MAX_GROUP_CHANNELS=1
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
build_src_filter = ${LilyGo_T3S3_lr1121.build_src_filter}
+<../examples/simple_secure_chat/main.cpp>
lib_deps =
${LilyGo_T3S3_lr1121.lib_deps}
densaugeo/base64 @ ~1.4.0

[env:LilyGo_T3S3_lr1121_room_server]
extends = LilyGo_T3S3_lr1121
build_flags =
${LilyGo_T3S3_lr1121.build_flags}
-D DISPLAY_CLASS=SSD1306Display
-D ADVERT_NAME='"T3S3-1121 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 = ${LilyGo_T3S3_lr1121.build_src_filter}
+<helpers/ui/SSD1306Display.cpp>
+<../examples/simple_room_server>
lib_deps =
${LilyGo_T3S3_lr1121.lib_deps}
${esp32_ota.lib_deps}

[env:LilyGo_T3S3_lr1121_companion_radio_usb]
extends = LilyGo_T3S3_lr1121
upload_speed = 115200
build_flags =
${LilyGo_T3S3_lr1121.build_flags}
-I examples/companion_radio/ui-new
-D DISPLAY_CLASS=SSD1306Display
-D MAX_CONTACTS=300
-D MAX_GROUP_CHANNELS=8
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
build_src_filter = ${LilyGo_T3S3_lr1121.build_src_filter}
+<helpers/ui/SSD1306Display.cpp>
+<helpers/ui/MomentaryButton.cpp>
+<../examples/companion_radio/*.cpp>
+<../examples/companion_radio/ui-new/*.cpp>
lib_deps =
${LilyGo_T3S3_lr1121.lib_deps}
densaugeo/base64 @ ~1.4.0

[env:LilyGo_T3S3_lr1121_companion_radio_ble]
extends = LilyGo_T3S3_lr1121
build_flags =
${LilyGo_T3S3_lr1121.build_flags}
-I examples/companion_radio/ui-new
-D DISPLAY_CLASS=SSD1306Display
-D MAX_CONTACTS=300
-D MAX_GROUP_CHANNELS=8
-D BLE_PIN_CODE=123456
-D BLE_DEBUG_LOGGING=1
-D OFFLINE_QUEUE_SIZE=256
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
build_src_filter = ${LilyGo_T3S3_lr1121.build_src_filter}
+<helpers/esp32/*.cpp>
+<helpers/ui/SSD1306Display.cpp>
+<helpers/ui/MomentaryButton.cpp>
+<../examples/companion_radio/*.cpp>
+<../examples/companion_radio/ui-new/*.cpp>
lib_deps =
${LilyGo_T3S3_lr1121.lib_deps}
densaugeo/base64 @ ~1.4.0
95 changes: 95 additions & 0 deletions variants/lilygo_t3s3_lr1121/target.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
#include <Arduino.h>
#include "target.h"

ESP32Board board;

static SPIClass spi;
RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_9, 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;
MomentaryButton user_btn(PIN_USER_BTN, 1000, true);
#endif

#ifndef LORA_CR
#define LORA_CR 5
#endif

#ifdef RF_SWITCH_TABLE
static const uint32_t rfswitch_dios[Module::RFSWITCH_MAX_PINS] = {
RADIOLIB_LR11X0_DIO5,
RADIOLIB_LR11X0_DIO6,
RADIOLIB_LR11X0_DIO7,
RADIOLIB_LR11X0_DIO8,
RADIOLIB_NC
};

static const Module::RfSwitchMode_t rfswitch_table[] = {
// mode DIO5 DIO6 DIO7 DIO8
{ LR11x0::MODE_STBY, {LOW, LOW, LOW, LOW }},
{ LR11x0::MODE_RX, {HIGH, LOW, LOW, HIGH }},
{ LR11x0::MODE_TX, {HIGH, HIGH, LOW, HIGH }},
{ LR11x0::MODE_TX_HP, {LOW, HIGH, LOW, HIGH }},
{ LR11x0::MODE_TX_HF, {LOW, LOW, LOW, LOW }},
{ LR11x0::MODE_GNSS, {LOW, LOW, HIGH, LOW }},
{ LR11x0::MODE_WIFI, {LOW, LOW, LOW, LOW }},
END_OF_MODE_TABLE,
};
#endif

bool radio_init() {
fallback_clock.begin();
rtc_clock.begin(Wire);

#ifdef LR11X0_DIO3_TCXO_VOLTAGE
float tcxo = LR11X0_DIO3_TCXO_VOLTAGE;
#else
float tcxo = 1.6f;
#endif

spi.begin(P_LORA_SCLK, P_LORA_MISO, P_LORA_MOSI, P_LORA_NSS);
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);
return false; // fail
}

radio.setCRC(2);
radio.explicitHeader();

#ifdef RF_SWITCH_TABLE
radio.setRfSwitchTable(rfswitch_dios, rfswitch_table);
#endif
#ifdef RX_BOOSTED_GAIN
radio.setRxBoostedGainMode(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
}
29 changes: 29 additions & 0 deletions variants/lilygo_t3s3_lr1121/target.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#pragma once

#define RADIOLIB_STATIC_ONLY 1
#include <RadioLib.h>
#include <helpers/radiolib/RadioLibWrappers.h>
#include <helpers/ESP32Board.h>
#include <helpers/radiolib/CustomLR1121Wrapper.h>
#include <helpers/AutoDiscoverRTCClock.h>
#include <helpers/SensorManager.h>
#ifdef DISPLAY_CLASS
#include <helpers/ui/SSD1306Display.h>
#include <helpers/ui/MomentaryButton.h>
#endif

extern ESP32Board board;
extern WRAPPER_CLASS radio_driver;
extern AutoDiscoverRTCClock rtc_clock;
extern SensorManager sensors;

#ifdef DISPLAY_CLASS
extern DISPLAY_CLASS display;
extern MomentaryButton user_btn;
#endif

bool radio_init();
uint32_t radio_get_rng_seed();
void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr);
void radio_set_tx_power(uint8_t dbm);
mesh::LocalIdentity radio_new_identity();