kopia lustrzana https://github.com/sh123/esp32_loraprs
Add support for KISS extension for radio control and signal reports
rodzic
1f1b3efb7e
commit
4c178d8c65
1
config.h
1
config.h
|
@ -33,3 +33,4 @@
|
|||
#define CFG_RF_TO_IS true
|
||||
#define CFG_IS_TO_RF false
|
||||
#define CFG_BEACON false
|
||||
#define CFG_KISS_EXTENSIONS false
|
||||
|
|
|
@ -25,7 +25,7 @@ void initializeConfig(LoraPrs::Config &cfg) {
|
|||
|
||||
// client/server mode switch
|
||||
cfg.IsClientMode = CFG_IS_CLIENT_MODE;
|
||||
|
||||
|
||||
// lora parameters
|
||||
cfg.LoraFreq = CFG_LORA_FREQ;
|
||||
cfg.LoraBw = CFG_LORA_BW;
|
||||
|
@ -64,6 +64,7 @@ void initializeConfig(LoraPrs::Config &cfg) {
|
|||
cfg.EnableIsToRf = CFG_IS_TO_RF; // send data from aprsis to rf
|
||||
cfg.EnableRepeater = CFG_DIGIREPEAT; // digirepeat incoming packets
|
||||
cfg.EnableBeacon = CFG_BEACON; // enable periodic AprsRawBeacon beacon to rf and aprsis if rf to aprsis is enabled
|
||||
cfg.EnableKissExtensions = CFG_KISS_EXTENSIONS; // radio control and signal reports
|
||||
}
|
||||
|
||||
LoraPrs::Service loraPrsService;
|
||||
|
|
|
@ -61,12 +61,13 @@ void Processor::resetState()
|
|||
state_ = State::Void;
|
||||
}
|
||||
|
||||
bool Processor::processCommand(unsigned char rxByte) {
|
||||
bool Processor::processCommand(byte rxByte) {
|
||||
|
||||
switch (rxByte) {
|
||||
case Cmd::Data:
|
||||
if (!onRigTxBegin()) return false;
|
||||
state_ = State::GetData;
|
||||
dataType_ = DataType::Raw;
|
||||
break;
|
||||
case Cmd::P:
|
||||
state_ = State::GetP;
|
||||
|
@ -74,6 +75,11 @@ bool Processor::processCommand(unsigned char rxByte) {
|
|||
case Cmd::SlotTime:
|
||||
state_ = State::GetSlotTime;
|
||||
break;
|
||||
case Cmd::RadioControl:
|
||||
state_ = State::GetData;
|
||||
dataType_ = DataType::Control;
|
||||
cmdBuffer_.clear();
|
||||
break;
|
||||
default:
|
||||
// unknown command
|
||||
resetState();
|
||||
|
@ -83,7 +89,34 @@ bool Processor::processCommand(unsigned char rxByte) {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool Processor::receiveByte(unsigned char rxByte) {
|
||||
void Processor::processData(byte rxByte) {
|
||||
switch (rxByte) {
|
||||
case Marker::Fesc:
|
||||
state_ = State::Escape;
|
||||
break;
|
||||
case Marker::Fend:
|
||||
if (cmd_ == Cmd::Data) {
|
||||
if (dataType_ == DataType::Raw) {
|
||||
onRigTxEnd();
|
||||
} else if (dataType_ == DataType::Control) {
|
||||
onRadioControlCommand(cmdBuffer_);
|
||||
}
|
||||
}
|
||||
resetState();
|
||||
break;
|
||||
default:
|
||||
if (cmd_ == Cmd::Data) {
|
||||
if (dataType_ == DataType::Raw) {
|
||||
onRigTx(rxByte);
|
||||
} else if (dataType_ == DataType::Control) {
|
||||
cmdBuffer_.push_back(rxByte);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool Processor::receiveByte(byte rxByte) {
|
||||
|
||||
switch (state_) {
|
||||
case State::Void:
|
||||
|
@ -106,18 +139,7 @@ bool Processor::receiveByte(unsigned char rxByte) {
|
|||
state_ = State::GetData;
|
||||
break;
|
||||
case State::GetData:
|
||||
if (rxByte == Marker::Fesc) {
|
||||
state_ = State::Escape;
|
||||
}
|
||||
else if (rxByte == Marker::Fend) {
|
||||
if (cmd_ == Cmd::Data) {
|
||||
onRigTxEnd();
|
||||
}
|
||||
resetState();
|
||||
}
|
||||
else if (cmd_ == Cmd::Data) {
|
||||
onRigTx(rxByte);
|
||||
}
|
||||
processData(rxByte);
|
||||
break;
|
||||
case State::Escape:
|
||||
if (rxByte == Marker::Tfend) {
|
||||
|
|
|
@ -40,22 +40,20 @@ protected:
|
|||
SlotTime = 0x03,
|
||||
|
||||
// extended to modem
|
||||
Frequency = 0x10,
|
||||
Bandwidth = 0x11,
|
||||
Power = 0x12,
|
||||
SyncWord = 0x13,
|
||||
SpreadingFactor = 0x14,
|
||||
CodingRate = 0x15,
|
||||
EnableCrc = 0x16,
|
||||
RadioControl = 0x10,
|
||||
|
||||
// extended events from modem
|
||||
SignalLevelRssi = 0x30,
|
||||
SignalLevelSnr = 0x31,
|
||||
// extended from modem
|
||||
RadioSignalLevel = 0x30,
|
||||
|
||||
// end of cmds
|
||||
NoCmd = 0x80
|
||||
};
|
||||
|
||||
enum DataType {
|
||||
Raw = 0,
|
||||
Control
|
||||
};
|
||||
|
||||
const int CfgTxQueueSize = 4096;
|
||||
|
||||
protected:
|
||||
|
@ -68,20 +66,20 @@ protected:
|
|||
virtual bool onSerialRx(byte *b) = 0;
|
||||
|
||||
virtual void onControlCommand(Cmd cmd, byte value) = 0;
|
||||
/*
|
||||
virtual void onControlCommand(Cmd cmd, int value) = 0;
|
||||
virtual void onControlCommand(Cmd cmd, long value) = 0;
|
||||
*/
|
||||
virtual void onRadioControlCommand(const std::vector<byte> &command) = 0;
|
||||
|
||||
private:
|
||||
bool receiveByte(unsigned char rxByte);
|
||||
bool processCommand(unsigned char rxByte);
|
||||
bool receiveByte(byte rxByte);
|
||||
void processData(byte rxByte);
|
||||
bool processCommand(byte rxByte);
|
||||
void resetState();
|
||||
|
||||
|
||||
private:
|
||||
Cmd cmd_;
|
||||
DataType dataType_;
|
||||
State state_;
|
||||
std::shared_ptr<cppQueue> txQueue_;
|
||||
std::vector<byte> cmdBuffer_;
|
||||
};
|
||||
|
||||
} // Kiss
|
||||
|
|
|
@ -13,8 +13,8 @@ struct Config
|
|||
long LoraBw; // lora bandwidth, e.g. 125e3
|
||||
int LoraSf; // lora spreading factor, e.g. 12
|
||||
int LoraCodingRate; // lora coding rate, e.g. 7
|
||||
int LoraSync; // lora sync word/packet id, 0x3f
|
||||
int LoraPower; // lora power level in dbm, 20
|
||||
int LoraSync; // lora sync word/packet id, 0x3f
|
||||
bool LoraEnableCrc; // lora crc check enabled
|
||||
|
||||
byte LoraPinSs; // lora ss pin
|
||||
|
@ -41,6 +41,7 @@ struct Config
|
|||
bool EnableIsToRf; // true - enable APRS-IS to RF submission
|
||||
bool EnableRepeater; // true - digirepeat incoming packets based on WIDEn-n paths
|
||||
bool EnableBeacon; // true - send AprsRawBeacon to RF and APRS-IS if EnableRfToIs is true
|
||||
bool EnableKissExtensions; // true - enable kiss extensions for radio control and signal reports
|
||||
};
|
||||
|
||||
} // LoraPrs
|
||||
|
|
|
@ -225,6 +225,16 @@ void Service::onAprsisDataAvailable()
|
|||
}
|
||||
}
|
||||
|
||||
void Service::sendSignalReportEvent(int rssi, float snr)
|
||||
{
|
||||
struct LoraSignalLevelEvent event;
|
||||
|
||||
event.rssi = htobe16(rssi);
|
||||
event.snr = htobe16(snr * 100);
|
||||
|
||||
serialSend((const byte *)&event, sizeof(LoraSignalLevelEvent));
|
||||
}
|
||||
|
||||
bool Service::sendAX25ToLora(const AX25::Payload &payload)
|
||||
{
|
||||
byte buf[CfgMaxAX25PayloadSize];
|
||||
|
@ -250,12 +260,16 @@ void Service::onLoraDataAvailable(int packetSize)
|
|||
}
|
||||
serialSend(rxBuf, rxBufIndex);
|
||||
long frequencyError = LoRa.packetFrequencyError();
|
||||
|
||||
|
||||
if (config_.EnableAutoFreqCorrection) {
|
||||
config_.LoraFreq -= frequencyError;
|
||||
LoRa.setFrequency(config_.LoraFreq);
|
||||
}
|
||||
|
||||
if (config_.EnableKissExtensions) {
|
||||
sendSignalReportEvent(LoRa.packetRssi(), LoRa.packetSnr());
|
||||
}
|
||||
|
||||
if (!config_.IsClientMode) {
|
||||
processIncomingRawPacketAsServer(rxBuf, rxBufIndex);
|
||||
}
|
||||
|
@ -347,5 +361,23 @@ void Service::onControlCommand(Cmd cmd, byte value)
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Service::onRadioControlCommand(const std::vector<byte> &rawCommand) {
|
||||
|
||||
if (config_.EnableKissExtensions && rawCommand.size() == sizeof(LoraControlCommand)) {
|
||||
const struct LoraControlCommand * controlCommand = reinterpret_cast<const struct LoraControlCommand*>(rawCommand.data());
|
||||
|
||||
config_.LoraFreq = be32toh(controlCommand->freq);
|
||||
config_.LoraBw = be32toh(controlCommand->bw);
|
||||
config_.LoraSf = be16toh(controlCommand->sf);
|
||||
config_.LoraCodingRate = be16toh(controlCommand->cr);
|
||||
config_.LoraPower = be16toh(controlCommand->pwr);
|
||||
config_.LoraSync = be16toh(controlCommand->sync);
|
||||
config_.LoraEnableCrc = controlCommand->crc;
|
||||
|
||||
setupLora(config_.LoraFreq, config_.LoraBw, config_.LoraSf,
|
||||
config_.LoraCodingRate, config_.LoraPower, config_.LoraSync, config_.LoraEnableCrc);
|
||||
}
|
||||
}
|
||||
|
||||
} // LoraPrs
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include <LoRa.h>
|
||||
#include <WiFi.h>
|
||||
#include <cppQueue.h>
|
||||
#include <endian.h>
|
||||
|
||||
#include "BluetoothSerial.h"
|
||||
#include "ax25_payload.h"
|
||||
|
@ -33,6 +34,7 @@ private:
|
|||
void onLoraDataAvailable(int packetSize);
|
||||
void onAprsisDataAvailable();
|
||||
|
||||
void sendSignalReportEvent(int rssi, float snr);
|
||||
void sendPeriodicBeacon();
|
||||
void sendToAprsis(const String &aprsMessage);
|
||||
bool sendAX25ToLora(const AX25::Payload &payload);
|
||||
|
@ -55,7 +57,24 @@ protected:
|
|||
virtual bool onSerialRx(byte *b);
|
||||
|
||||
virtual void onControlCommand(Cmd cmd, byte value);
|
||||
virtual void onRadioControlCommand(const std::vector<byte> &command);
|
||||
|
||||
private:
|
||||
struct LoraSignalLevelEvent {
|
||||
int rssi;
|
||||
int snr;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct LoraControlCommand {
|
||||
long freq;
|
||||
long bw;
|
||||
int sf;
|
||||
int cr;
|
||||
int pwr;
|
||||
int sync;
|
||||
bool crc;
|
||||
} __attribute__((packed));
|
||||
|
||||
private:
|
||||
const String CfgLoraprsVersion = "LoRAPRS 0.1";
|
||||
|
||||
|
@ -65,7 +84,7 @@ private:
|
|||
const int CfgWiFiConnRetryMaxTimes = 10;
|
||||
const int CfgMaxAX25PayloadSize = 512;
|
||||
|
||||
// csma paramters, overriden with KISS commands
|
||||
// csma parameters, overriden with KISS commands
|
||||
const long CfgCsmaPersistence = 100; // 255 for real time, lower for higher traffic
|
||||
const long CfgCsmaSlotTimeMs = 500; // 0 for real time, otherwise set to average tx duration
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue