Add support for KISS extension for radio control and signal reports

pull/15/head
sh123 2021-02-05 18:57:06 +02:00
rodzic 1f1b3efb7e
commit 4c178d8c65
7 zmienionych plików z 110 dodań i 36 usunięć

Wyświetl plik

@ -33,3 +33,4 @@
#define CFG_RF_TO_IS true #define CFG_RF_TO_IS true
#define CFG_IS_TO_RF false #define CFG_IS_TO_RF false
#define CFG_BEACON false #define CFG_BEACON false
#define CFG_KISS_EXTENSIONS false

Wyświetl plik

@ -64,6 +64,7 @@ void initializeConfig(LoraPrs::Config &cfg) {
cfg.EnableIsToRf = CFG_IS_TO_RF; // send data from aprsis to rf cfg.EnableIsToRf = CFG_IS_TO_RF; // send data from aprsis to rf
cfg.EnableRepeater = CFG_DIGIREPEAT; // digirepeat incoming packets 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.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; LoraPrs::Service loraPrsService;

Wyświetl plik

@ -61,12 +61,13 @@ void Processor::resetState()
state_ = State::Void; state_ = State::Void;
} }
bool Processor::processCommand(unsigned char rxByte) { bool Processor::processCommand(byte rxByte) {
switch (rxByte) { switch (rxByte) {
case Cmd::Data: case Cmd::Data:
if (!onRigTxBegin()) return false; if (!onRigTxBegin()) return false;
state_ = State::GetData; state_ = State::GetData;
dataType_ = DataType::Raw;
break; break;
case Cmd::P: case Cmd::P:
state_ = State::GetP; state_ = State::GetP;
@ -74,6 +75,11 @@ bool Processor::processCommand(unsigned char rxByte) {
case Cmd::SlotTime: case Cmd::SlotTime:
state_ = State::GetSlotTime; state_ = State::GetSlotTime;
break; break;
case Cmd::RadioControl:
state_ = State::GetData;
dataType_ = DataType::Control;
cmdBuffer_.clear();
break;
default: default:
// unknown command // unknown command
resetState(); resetState();
@ -83,7 +89,34 @@ bool Processor::processCommand(unsigned char rxByte) {
return true; 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_) { switch (state_) {
case State::Void: case State::Void:
@ -106,18 +139,7 @@ bool Processor::receiveByte(unsigned char rxByte) {
state_ = State::GetData; state_ = State::GetData;
break; break;
case State::GetData: case State::GetData:
if (rxByte == Marker::Fesc) { processData(rxByte);
state_ = State::Escape;
}
else if (rxByte == Marker::Fend) {
if (cmd_ == Cmd::Data) {
onRigTxEnd();
}
resetState();
}
else if (cmd_ == Cmd::Data) {
onRigTx(rxByte);
}
break; break;
case State::Escape: case State::Escape:
if (rxByte == Marker::Tfend) { if (rxByte == Marker::Tfend) {

Wyświetl plik

@ -40,22 +40,20 @@ protected:
SlotTime = 0x03, SlotTime = 0x03,
// extended to modem // extended to modem
Frequency = 0x10, RadioControl = 0x10,
Bandwidth = 0x11,
Power = 0x12,
SyncWord = 0x13,
SpreadingFactor = 0x14,
CodingRate = 0x15,
EnableCrc = 0x16,
// extended events from modem // extended from modem
SignalLevelRssi = 0x30, RadioSignalLevel = 0x30,
SignalLevelSnr = 0x31,
// end of cmds // end of cmds
NoCmd = 0x80 NoCmd = 0x80
}; };
enum DataType {
Raw = 0,
Control
};
const int CfgTxQueueSize = 4096; const int CfgTxQueueSize = 4096;
protected: protected:
@ -68,20 +66,20 @@ protected:
virtual bool onSerialRx(byte *b) = 0; virtual bool onSerialRx(byte *b) = 0;
virtual void onControlCommand(Cmd cmd, byte value) = 0; virtual void onControlCommand(Cmd cmd, byte value) = 0;
/* virtual void onRadioControlCommand(const std::vector<byte> &command) = 0;
virtual void onControlCommand(Cmd cmd, int value) = 0;
virtual void onControlCommand(Cmd cmd, long value) = 0;
*/
private: private:
bool receiveByte(unsigned char rxByte); bool receiveByte(byte rxByte);
bool processCommand(unsigned char rxByte); void processData(byte rxByte);
bool processCommand(byte rxByte);
void resetState(); void resetState();
private: private:
Cmd cmd_; Cmd cmd_;
DataType dataType_;
State state_; State state_;
std::shared_ptr<cppQueue> txQueue_; std::shared_ptr<cppQueue> txQueue_;
std::vector<byte> cmdBuffer_;
}; };
} // Kiss } // Kiss

Wyświetl plik

@ -13,8 +13,8 @@ struct Config
long LoraBw; // lora bandwidth, e.g. 125e3 long LoraBw; // lora bandwidth, e.g. 125e3
int LoraSf; // lora spreading factor, e.g. 12 int LoraSf; // lora spreading factor, e.g. 12
int LoraCodingRate; // lora coding rate, e.g. 7 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 LoraPower; // lora power level in dbm, 20
int LoraSync; // lora sync word/packet id, 0x3f
bool LoraEnableCrc; // lora crc check enabled bool LoraEnableCrc; // lora crc check enabled
byte LoraPinSs; // lora ss pin byte LoraPinSs; // lora ss pin
@ -41,6 +41,7 @@ struct Config
bool EnableIsToRf; // true - enable APRS-IS to RF submission bool EnableIsToRf; // true - enable APRS-IS to RF submission
bool EnableRepeater; // true - digirepeat incoming packets based on WIDEn-n paths 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 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 } // LoraPrs

Wyświetl plik

@ -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) bool Service::sendAX25ToLora(const AX25::Payload &payload)
{ {
byte buf[CfgMaxAX25PayloadSize]; byte buf[CfgMaxAX25PayloadSize];
@ -256,6 +266,10 @@ void Service::onLoraDataAvailable(int packetSize)
LoRa.setFrequency(config_.LoraFreq); LoRa.setFrequency(config_.LoraFreq);
} }
if (config_.EnableKissExtensions) {
sendSignalReportEvent(LoRa.packetRssi(), LoRa.packetSnr());
}
if (!config_.IsClientMode) { if (!config_.IsClientMode) {
processIncomingRawPacketAsServer(rxBuf, rxBufIndex); processIncomingRawPacketAsServer(rxBuf, rxBufIndex);
} }
@ -348,4 +362,22 @@ void Service::onControlCommand(Cmd cmd, byte value)
} }
} }
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 } // LoraPrs

Wyświetl plik

@ -6,6 +6,7 @@
#include <LoRa.h> #include <LoRa.h>
#include <WiFi.h> #include <WiFi.h>
#include <cppQueue.h> #include <cppQueue.h>
#include <endian.h>
#include "BluetoothSerial.h" #include "BluetoothSerial.h"
#include "ax25_payload.h" #include "ax25_payload.h"
@ -33,6 +34,7 @@ private:
void onLoraDataAvailable(int packetSize); void onLoraDataAvailable(int packetSize);
void onAprsisDataAvailable(); void onAprsisDataAvailable();
void sendSignalReportEvent(int rssi, float snr);
void sendPeriodicBeacon(); void sendPeriodicBeacon();
void sendToAprsis(const String &aprsMessage); void sendToAprsis(const String &aprsMessage);
bool sendAX25ToLora(const AX25::Payload &payload); bool sendAX25ToLora(const AX25::Payload &payload);
@ -55,6 +57,23 @@ protected:
virtual bool onSerialRx(byte *b); virtual bool onSerialRx(byte *b);
virtual void onControlCommand(Cmd cmd, byte value); 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: private:
const String CfgLoraprsVersion = "LoRAPRS 0.1"; const String CfgLoraprsVersion = "LoRAPRS 0.1";
@ -65,7 +84,7 @@ private:
const int CfgWiFiConnRetryMaxTimes = 10; const int CfgWiFiConnRetryMaxTimes = 10;
const int CfgMaxAX25PayloadSize = 512; 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 CfgCsmaPersistence = 100; // 255 for real time, lower for higher traffic
const long CfgCsmaSlotTimeMs = 500; // 0 for real time, otherwise set to average tx duration const long CfgCsmaSlotTimeMs = 500; // 0 for real time, otherwise set to average tx duration