kopia lustrzana https://github.com/sh123/esp32_loraprs
rodzic
b5b61e6318
commit
e1520628c5
1
config.h
1
config.h
|
@ -19,6 +19,7 @@
|
|||
#define CFG_LORA_PIN_SS SS
|
||||
#define CFG_LORA_PIN_RST LORA_RST
|
||||
#define CFG_LORA_PIN_DIO0 LORA_IRQ
|
||||
#define CFG_LORA_PIN_DIO1 LORA_IRQ
|
||||
#define CFG_LORA_USE_ISR false // set to true for incoming packet ISR usage (stream mode, e.g. speech)
|
||||
|
||||
#define CFG_LORA_FREQ 433.775E6
|
||||
|
|
|
@ -1,12 +1,16 @@
|
|||
#include <arduino-timer.h>
|
||||
#include "WiFi.h"
|
||||
|
||||
// when defined RadioLib will be used, otherwise arduino-LoRa
|
||||
//#define USE_RADIOLIB
|
||||
|
||||
#include "loraprs_service.h"
|
||||
|
||||
#if __has_include("/tmp/esp32_loraprs_config.h")
|
||||
#pragma message("Using external config")
|
||||
#include "/tmp/esp32_loraprs_config.h"
|
||||
#else
|
||||
#pragma message("Using default config")
|
||||
#pragma message("Using default built-in config")
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
|
@ -34,6 +38,7 @@ void initializeConfig(LoraPrs::Config &cfg) {
|
|||
cfg.LoraPinSs = CFG_LORA_PIN_SS;
|
||||
cfg.LoraPinRst = CFG_LORA_PIN_RST;
|
||||
cfg.LoraPinDio0 = CFG_LORA_PIN_DIO0;
|
||||
cfg.LoraPinDio1 = CFG_LORA_PIN_DIO1;
|
||||
cfg.LoraUseIsr = CFG_LORA_USE_ISR; // set to true for incoming packet ISR usage (stream mode, e.g. speech)
|
||||
|
||||
// aprs configuration
|
||||
|
|
|
@ -22,6 +22,7 @@ struct Config
|
|||
byte LoraPinSs; // lora ss pin
|
||||
byte LoraPinRst; // lora rst pin
|
||||
byte LoraPinDio0; // lora dio0 pin
|
||||
byte LoraPinDio1; // lora dio1 pin
|
||||
bool LoraUseIsr; // true to use interrupts, false for fallback polling, e.g. if Dio0 is not connected
|
||||
|
||||
// bluetooth
|
||||
|
|
|
@ -1,7 +1,14 @@
|
|||
#include "loraprs_service.h"
|
||||
|
||||
namespace LoraPrs {
|
||||
|
||||
|
||||
byte Service::rxBuf_[256];
|
||||
|
||||
#ifdef USE_RADIOLIB
|
||||
bool Service::interruptEnabled_ = true;
|
||||
std::shared_ptr<SX1278> Service::radio_;
|
||||
#endif
|
||||
|
||||
Service::Service()
|
||||
: Kiss::Processor()
|
||||
, csmaP_(CfgCsmaPersistence)
|
||||
|
@ -10,6 +17,9 @@ Service::Service()
|
|||
, serialBt_()
|
||||
, serialBLE_()
|
||||
{
|
||||
#ifdef USE_RADIOLIB
|
||||
interruptEnabled_ = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
void Service::setup(const Config &conf)
|
||||
|
@ -118,7 +128,27 @@ void Service::setupLora(long loraFreq, long bw, int sf, int cr, int pwr, int syn
|
|||
Serial.print(enableCrc); Serial.print("...");
|
||||
|
||||
isImplicitHeaderMode_ = sf == 6;
|
||||
|
||||
#ifdef USE_RADIOLIB
|
||||
radio_ = std::make_shared<SX1278>(new Module(config_.LoraPinSs, config_.LoraPinDio0, config_.LoraPinRst, RADIOLIB_NC));
|
||||
int state = radio_->begin((float)loraFreq / 1e6, (float)bw / 1e3, sf, cr, sync, pwr);
|
||||
if (state != ERR_NONE) {
|
||||
Serial.print("Radio start error: "); Serial.println(state);
|
||||
}
|
||||
radio_->setCRC(enableCrc);
|
||||
//radio_->forceLDRO(false);
|
||||
//radio_->setRfSwitchPins(4, 5);
|
||||
|
||||
radio_->clearDio0Action();
|
||||
radio_->setDio0Action(onLoraDataAvailableIsr);
|
||||
|
||||
state = radio_->startReceive();
|
||||
if (state != ERR_NONE) {
|
||||
Serial.print("Receive start error: "); Serial.println(state);
|
||||
}
|
||||
|
||||
#else // USE_RADIOLIB
|
||||
|
||||
LoRa.setPins(config_.LoraPinSs, config_.LoraPinRst, config_.LoraPinDio0);
|
||||
|
||||
int retryCnt = 0;
|
||||
|
@ -135,6 +165,7 @@ void Service::setupLora(long loraFreq, long bw, int sf, int cr, int pwr, int syn
|
|||
LoRa.setSignalBandwidth(bw);
|
||||
LoRa.setCodingRate4(cr);
|
||||
LoRa.setTxPower(pwr);
|
||||
|
||||
if (enableCrc) {
|
||||
LoRa.enableCrc();
|
||||
}
|
||||
|
@ -143,30 +174,25 @@ void Service::setupLora(long loraFreq, long bw, int sf, int cr, int pwr, int syn
|
|||
LoRa.onReceive(onLoraDataAvailableIsr);
|
||||
LoRa.receive();
|
||||
}
|
||||
#endif // USE_RADIOLIB
|
||||
|
||||
Serial.println("ok");
|
||||
}
|
||||
|
||||
void Service::setupBt(const String &btName)
|
||||
{
|
||||
if (config_.BtEnableBle) {
|
||||
Serial.print("BLE init " + btName + "...");
|
||||
if (serialBLE_.begin(btName.c_str())) {
|
||||
Serial.println("ok");
|
||||
}
|
||||
else {
|
||||
Serial.println("failed");
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
Serial.print("BT init " + btName + "...");
|
||||
String btType = config_.BtEnableBle ? "BLE" : "BT";
|
||||
Serial.print(btType + " init " + btName + "...");
|
||||
|
||||
if (serialBt_.begin(btName)) {
|
||||
Serial.println("ok");
|
||||
}
|
||||
else {
|
||||
Serial.println("failed");
|
||||
}
|
||||
bool btOk = config_.BtEnableBle
|
||||
? serialBLE_.begin(btName.c_str())
|
||||
: serialBt_.begin(btName);
|
||||
|
||||
if (btOk) {
|
||||
Serial.println("ok");
|
||||
}
|
||||
else {
|
||||
Serial.println("failed");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -182,6 +208,9 @@ void Service::loop()
|
|||
// RX path, Rig -> Serial
|
||||
bool isRigToSerialProcessed = false;
|
||||
|
||||
#ifdef USE_RADIOLIB
|
||||
isRigToSerialProcessed = processRigToSerial();
|
||||
#else
|
||||
if (config_.LoraUseIsr) {
|
||||
isRigToSerialProcessed = processRigToSerial();
|
||||
} else {
|
||||
|
@ -190,6 +219,7 @@ void Service::loop()
|
|||
isRigToSerialProcessed = true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// TX path, Serial -> Rig
|
||||
if (!isRigToSerialProcessed) {
|
||||
|
@ -202,8 +232,18 @@ void Service::loop()
|
|||
if (needsBeacon()) {
|
||||
sendPeriodicBeacon();
|
||||
}
|
||||
if (processSerialToRig() && config_.LoraUseIsr) {
|
||||
LoRa.receive();
|
||||
bool allTxProcessed = processSerialToRig();
|
||||
if (allTxProcessed) {
|
||||
#ifdef USE_RADIOLIB
|
||||
int state = radio_->startReceive();
|
||||
if (state != ERR_NONE) {
|
||||
Serial.print("Start receive error: "); Serial.println(state);
|
||||
}
|
||||
#else
|
||||
if (config_.LoraUseIsr) {
|
||||
LoRa.receive();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
csmaSlotTimePrev_ = currentTime;
|
||||
}
|
||||
|
@ -211,18 +251,43 @@ void Service::loop()
|
|||
delay(CfgPollDelayMs);
|
||||
}
|
||||
|
||||
#ifdef USE_RADIOLIB
|
||||
|
||||
ICACHE_RAM_ATTR void Service::onLoraDataAvailableIsr() {
|
||||
if (interruptEnabled_) {
|
||||
int packetSize = radio_->getPacketLength();
|
||||
|
||||
if (packetSize > 0) {
|
||||
|
||||
int state = radio_->readData(rxBuf_, packetSize);
|
||||
if (state == ERR_NONE) {
|
||||
queueRigToSerialIsr(Cmd::Data, rxBuf_, packetSize);
|
||||
} else {
|
||||
Serial.print("Read data error: "); Serial.println(state);
|
||||
}
|
||||
|
||||
state = radio_->startReceive();
|
||||
if (state != ERR_NONE) {
|
||||
Serial.print("Start receive error: "); Serial.println(state);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#else // USE_RADIOLIB
|
||||
|
||||
ICACHE_RAM_ATTR void Service::onLoraDataAvailableIsr(int packetSize)
|
||||
{
|
||||
// TODO, move to separate ESP32 task
|
||||
int rxBufIndex = 0;
|
||||
byte rxBuf[packetSize];
|
||||
|
||||
for (int i = 0; i < packetSize; i++) {
|
||||
rxBuf[rxBufIndex++] = LoRa.read();
|
||||
rxBuf_[rxBufIndex++] = LoRa.read();
|
||||
}
|
||||
queueRigToSerialIsr(Cmd::Data, rxBuf, rxBufIndex);
|
||||
queueRigToSerialIsr(Cmd::Data, rxBuf_, rxBufIndex);
|
||||
}
|
||||
|
||||
#endif // USE_RADIOLIB
|
||||
|
||||
void Service::sendPeriodicBeacon()
|
||||
{
|
||||
long currentMs = millis();
|
||||
|
@ -309,20 +374,35 @@ bool Service::sendAX25ToLora(const AX25::Payload &payload)
|
|||
|
||||
void Service::onRigPacket(void *packet, int packetLength)
|
||||
{
|
||||
long frequencyError = LoRa.packetFrequencyError();
|
||||
|
||||
if (config_.EnableAutoFreqCorrection && abs(frequencyError) > config_.AutoFreqCorrectionDeltaHz) {
|
||||
config_.LoraFreq -= frequencyError;
|
||||
Serial.print("Correcting frequency: "); Serial.println(frequencyError);
|
||||
#ifdef USE_RADIOLIB
|
||||
long frequencyErrorHz = radio_->getFrequencyError();
|
||||
#else
|
||||
long frequencyErrorHz = LoRa.packetFrequencyError();
|
||||
#endif
|
||||
if (config_.EnableAutoFreqCorrection && abs(frequencyErrorHz) > config_.AutoFreqCorrectionDeltaHz) {
|
||||
config_.LoraFreq -= frequencyErrorHz;
|
||||
Serial.print("Correcting frequency: "); Serial.println(frequencyErrorHz);
|
||||
#ifdef USE_RADIOLIB
|
||||
radio_->setFrequency((float)config_.LoraFreq / 1e6);
|
||||
int state = radio_->startReceive();
|
||||
if (state != ERR_NONE) {
|
||||
Serial.print("Start receive error: "); Serial.println(state);
|
||||
}
|
||||
#else
|
||||
LoRa.setFrequency(config_.LoraFreq);
|
||||
if (config_.LoraUseIsr) {
|
||||
LoRa.idle();
|
||||
LoRa.receive();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (config_.EnableKissExtensions) {
|
||||
#ifdef USE_RADIOLIB
|
||||
sendSignalReportEvent(radio_->getRSSI(), radio_->getSNR());
|
||||
#else
|
||||
sendSignalReportEvent(LoRa.packetRssi(), LoRa.packetSnr());
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!config_.IsClientMode) {
|
||||
|
@ -330,17 +410,19 @@ void Service::onRigPacket(void *packet, int packetLength)
|
|||
}
|
||||
}
|
||||
|
||||
#ifndef USE_RADIOLIB
|
||||
void Service::loraReceive(int packetSize)
|
||||
{
|
||||
int rxBufIndex = 0;
|
||||
byte rxBuf[packetSize];
|
||||
|
||||
|
||||
while (LoRa.available()) {
|
||||
rxBuf[rxBufIndex++] = LoRa.read();
|
||||
}
|
||||
sendRigToSerial(Cmd::Data, rxBuf, rxBufIndex);
|
||||
onRigPacket(rxBuf, rxBufIndex);
|
||||
}
|
||||
#endif
|
||||
|
||||
void Service::processIncomingRawPacketAsServer(const byte *packet, int packetLength) {
|
||||
|
||||
|
@ -348,10 +430,15 @@ void Service::processIncomingRawPacketAsServer(const byte *packet, int packetLen
|
|||
|
||||
if (payload.IsValid()) {
|
||||
|
||||
#ifdef USE_RADIOLIB
|
||||
float snr = radio_->getSNR();
|
||||
int rssi = radio_->getRSSI();
|
||||
long frequencyError = radio_->getFrequencyError();
|
||||
#else
|
||||
float snr = LoRa.packetSnr();
|
||||
int rssi = LoRa.packetRssi();
|
||||
long frequencyError = LoRa.packetFrequencyError();
|
||||
|
||||
#endif
|
||||
String signalReport = String(" ") +
|
||||
String("rssi: ") +
|
||||
String(snr < 0 ? rssi + snr : rssi) +
|
||||
|
@ -387,22 +474,50 @@ bool Service::onRigTxBegin()
|
|||
} else {
|
||||
delay(CfgPollDelayMs);
|
||||
}
|
||||
#ifdef USE_RADIOLIB
|
||||
return true;
|
||||
#else
|
||||
return (LoRa.beginPacket(isImplicitHeaderMode_) == 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Service::onRigTx(byte b)
|
||||
{
|
||||
#ifdef USE_RADIOLIB
|
||||
txQueue_.push(b);
|
||||
#else
|
||||
LoRa.write(b);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Service::onRigTxEnd()
|
||||
{
|
||||
#ifdef USE_RADIOLIB
|
||||
int txPacketSize = txQueue_.size();
|
||||
byte txBuf[txPacketSize];
|
||||
|
||||
for (int i = 0; i < txPacketSize; i++) {
|
||||
txBuf[i] = txQueue_.shift();
|
||||
}
|
||||
|
||||
interruptEnabled_ = false;
|
||||
int state = radio_->transmit(txBuf, txPacketSize);
|
||||
if (state != ERR_NONE) {
|
||||
Serial.print("TX error: "); Serial.println(state);
|
||||
}
|
||||
interruptEnabled_ = true;
|
||||
#endif
|
||||
|
||||
if (config_.PttEnable) {
|
||||
#ifndef USE_RADIOLIB
|
||||
LoRa.endPacket(false);
|
||||
#endif
|
||||
delay(config_.PttTxTailMs);
|
||||
digitalWrite(config_.PttPin, LOW);
|
||||
} else {
|
||||
#ifndef USE_RADIOLIB
|
||||
LoRa.endPacket(true);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -428,7 +543,10 @@ bool Service::onSerialRxHasData()
|
|||
|
||||
bool Service::onSerialRx(byte *b)
|
||||
{
|
||||
int rxResult = config_.BtEnableBle ? serialBLE_.read() : serialBt_.read();
|
||||
int rxResult = config_.BtEnableBle
|
||||
? serialBLE_.read()
|
||||
: serialBt_.read();
|
||||
|
||||
if (rxResult == -1) {
|
||||
return false;
|
||||
}
|
||||
|
@ -482,6 +600,7 @@ void Service::onRadioControlCommand(const std::vector<byte> &rawCommand) {
|
|||
|
||||
void Service::onRebootCommand()
|
||||
{
|
||||
Serial.println("Reboot requested");
|
||||
ESP.restart();
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,15 @@
|
|||
|
||||
#include <Arduino.h>
|
||||
#include <SPI.h>
|
||||
|
||||
#ifdef USE_RADIOLIB
|
||||
#include <RadioLib.h>
|
||||
#pragma message("Using RadioLib")
|
||||
#else
|
||||
#include <LoRa.h>
|
||||
#pragma message("Using arduino-LoRa")
|
||||
#endif
|
||||
|
||||
#include <WiFi.h>
|
||||
#include <endian.h>
|
||||
|
||||
|
@ -31,9 +39,13 @@ private:
|
|||
void reconnectWifi() const;
|
||||
bool reconnectAprsis();
|
||||
|
||||
#ifdef USE_RADIOLIB
|
||||
void onLoraDataAvailable();
|
||||
static ICACHE_RAM_ATTR void onLoraDataAvailableIsr();
|
||||
#else
|
||||
static ICACHE_RAM_ATTR void onLoraDataAvailableIsr(int packetSize);
|
||||
|
||||
void loraReceive(int packetSize);
|
||||
#endif
|
||||
void onAprsisDataAvailable();
|
||||
|
||||
void sendSignalReportEvent(int rssi, float snr);
|
||||
|
@ -109,6 +121,12 @@ private:
|
|||
long previousBeaconMs_;
|
||||
|
||||
// peripherals
|
||||
static byte rxBuf_[256];
|
||||
#ifdef USE_RADIOLIB
|
||||
static bool interruptEnabled_;
|
||||
CircularBuffer<uint8_t, 256> txQueue_;
|
||||
static std::shared_ptr<SX1278> radio_;
|
||||
#endif
|
||||
BluetoothSerial serialBt_;
|
||||
BLESerial serialBLE_;
|
||||
WiFiClient aprsisConn_;
|
||||
|
|
Ładowanie…
Reference in New Issue