Radio: Refactor parameters and ParameterSet
This commit is contained in:
parent
6fabd3354c
commit
982f3e11c7
@ -6,14 +6,14 @@ constexpr const char* TAG = "RadiolibThreadedDevice";
|
|||||||
bool RadiolibThreadedDevice::start(const Modulation modulation) {
|
bool RadiolibThreadedDevice::start(const Modulation modulation) {
|
||||||
auto lock = getMutex().asScopedLock();
|
auto lock = getMutex().asScopedLock();
|
||||||
|
|
||||||
if (!isCapableOf(modulation)) {
|
if (!canTransmit(modulation)) {
|
||||||
TT_LOG_E(TAG, "Can't start device \"%s\", not capable of modulation \"%s\"", getName().c_str(), toString(modulation));
|
TT_LOG_E(TAG, "Can't start device \"%s\", not capable of modulation \"%s\"", getName().c_str(), toString(modulation));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
lock.lock();
|
lock.lock();
|
||||||
|
|
||||||
if (thread != nullptr && thread->getState() != tt::Thread::State::Stopped) {
|
if ((thread != nullptr) && (thread->getState() != tt::Thread::State::Stopped)) {
|
||||||
TT_LOG_W(TAG, "Already started");
|
TT_LOG_W(TAG, "Already started");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,37 +9,30 @@ void IRAM_ATTR dio1handler(void* context) {
|
|||||||
((Sx1262*)context)->dio1Event();
|
((Sx1262*)context)->dio1Event();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Sx1262::configure(const Parameter parameter, const float value) {
|
bool Sx1262::setParameter(const Parameter parameter, const float value) {
|
||||||
using enum Parameter;
|
using enum Parameter;
|
||||||
|
|
||||||
switch (parameter) {
|
switch (parameter) {
|
||||||
case Power:
|
case Power:
|
||||||
power = value;
|
power = value;
|
||||||
TT_LOG_I(TAG, "Configure %s=%d", toString(parameter), power);
|
|
||||||
return true;
|
return true;
|
||||||
case Frequency:
|
case Frequency:
|
||||||
frequency = value;
|
frequency = value;
|
||||||
TT_LOG_I(TAG, "Configure %s=%f", toString(parameter), frequency);
|
|
||||||
return true;
|
return true;
|
||||||
case Bandwidth:
|
case Bandwidth:
|
||||||
bandwidth = value;
|
bandwidth = value;
|
||||||
TT_LOG_I(TAG, "Configure %s=%f", toString(parameter), bandwidth);
|
|
||||||
return true;
|
return true;
|
||||||
case SpreadFactor:
|
case SpreadFactor:
|
||||||
spreadFactor = value;
|
spreadFactor = value;
|
||||||
TT_LOG_I(TAG, "Configure %s=%d", toString(parameter), spreadFactor);
|
|
||||||
return true;
|
return true;
|
||||||
case CodingRate:
|
case CodingRate:
|
||||||
codingRate = value;
|
codingRate = value;
|
||||||
TT_LOG_I(TAG, "Configure %s=%d", toString(parameter), codingRate);
|
|
||||||
return true;
|
return true;
|
||||||
case SyncWord:
|
case SyncWord:
|
||||||
syncWord = value;
|
syncWord = value;
|
||||||
TT_LOG_I(TAG, "Configure %s=%X", toString(parameter), syncWord);
|
|
||||||
return true;
|
return true;
|
||||||
case PreambleLength:
|
case PreambleLength:
|
||||||
preambleLength = value;
|
preambleLength = value;
|
||||||
TT_LOG_I(TAG, "Configure %s=%d", toString(parameter), preambleLength);
|
|
||||||
return true;
|
return true;
|
||||||
case DataRate:
|
case DataRate:
|
||||||
bitRate = value;
|
bitRate = value;
|
||||||
@ -47,17 +40,62 @@ bool Sx1262::configure(const Parameter parameter, const float value) {
|
|||||||
case FrequencyDeviation:
|
case FrequencyDeviation:
|
||||||
frequencyDeviation = value;
|
frequencyDeviation = value;
|
||||||
return true;
|
return true;
|
||||||
|
case NarrowGrid:
|
||||||
|
narrowGrid = value;
|
||||||
|
return true;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TT_LOG_W(TAG, "Tried to set unsupported parameter \"%s\" to %f", toString(parameter), value);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Sx1262::getParameter(const Parameter parameter, float &value) const {
|
||||||
|
using enum Parameter;
|
||||||
|
|
||||||
|
switch (parameter) {
|
||||||
|
case Power:
|
||||||
|
value = power;
|
||||||
|
return true;
|
||||||
|
case Frequency:
|
||||||
|
value = frequency;
|
||||||
|
return true;
|
||||||
|
case Bandwidth:
|
||||||
|
value = bandwidth;
|
||||||
|
return true;
|
||||||
|
case SpreadFactor:
|
||||||
|
value = spreadFactor;
|
||||||
|
return true;
|
||||||
|
case CodingRate:
|
||||||
|
value = codingRate;
|
||||||
|
return true;
|
||||||
|
case SyncWord:
|
||||||
|
value = syncWord;
|
||||||
|
return true;
|
||||||
|
case PreambleLength:
|
||||||
|
value = preambleLength;
|
||||||
|
return true;
|
||||||
|
case DataRate:
|
||||||
|
value = bitRate;
|
||||||
|
return true;
|
||||||
|
case FrequencyDeviation:
|
||||||
|
value = frequencyDeviation;
|
||||||
|
return true;
|
||||||
|
case NarrowGrid:
|
||||||
|
value = narrowGrid;
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
TT_LOG_W(TAG, "Tried to get unsupported parameter \"%s\"", toString(parameter));
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sx1262::registerDio1Isr() {
|
void Sx1262::registerDio1Isr() {
|
||||||
hal.pinMode(GPIO_NUM_9, GPIO_MODE_OUTPUT);
|
|
||||||
gpio_set_level(GPIO_NUM_9, 0);
|
|
||||||
|
|
||||||
gpio_hal_context_t gpiohal;
|
gpio_hal_context_t gpiohal;
|
||||||
gpiohal.dev = GPIO_LL_GET_HW(GPIO_PORT_0);
|
gpiohal.dev = GPIO_LL_GET_HW(GPIO_PORT_0);
|
||||||
|
|
||||||
@ -123,6 +161,14 @@ int Sx1262::doBegin(const Modulation modulation) {
|
|||||||
configuration.tcxoVoltage,
|
configuration.tcxoVoltage,
|
||||||
configuration.useRegulatorLdo
|
configuration.useRegulatorLdo
|
||||||
);
|
);
|
||||||
|
} else if (modulation == Modulation::LrFhss) {
|
||||||
|
rc = radio.beginLRFHSS(
|
||||||
|
bandwidth,
|
||||||
|
codingRate,
|
||||||
|
narrowGrid,
|
||||||
|
configuration.tcxoVoltage,
|
||||||
|
configuration.useRegulatorLdo
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
TT_LOG_E(TAG, "SX1262 not capable of modulation \"%s\"", toString(modulation));
|
TT_LOG_E(TAG, "SX1262 not capable of modulation \"%s\"", toString(modulation));
|
||||||
setState(State::Error);
|
setState(State::Error);
|
||||||
@ -130,11 +176,12 @@ int Sx1262::doBegin(const Modulation modulation) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (rc != RADIOLIB_ERR_NONE) {
|
if (rc != RADIOLIB_ERR_NONE) {
|
||||||
TT_LOG_E(TAG, "Radiolib init failed with code %hi", rc);
|
TT_LOG_E(TAG, "Radiolib initialization failed with code %hi", rc);
|
||||||
setState(State::Error);
|
setState(State::Error);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
currentModem = modulation;
|
||||||
registerDio1Isr();
|
registerDio1Isr();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -145,19 +192,24 @@ void Sx1262::doEnd() {
|
|||||||
|
|
||||||
void Sx1262::doTransmit() {
|
void Sx1262::doTransmit() {
|
||||||
currentTx = popNextQueuedTx();
|
currentTx = popNextQueuedTx();
|
||||||
radio.standby();
|
uint16_t rc = RADIOLIB_ERR_NONE;
|
||||||
uint16_t rc = radio.startTransmit(currentTx.packet.data.data(), currentTx.packet.data.size());
|
rc = radio.standby();
|
||||||
|
if (rc != RADIOLIB_ERR_NONE) {
|
||||||
|
TT_LOG_W(TAG, "RadioLib returned %hi on standby", rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = radio.startTransmit(currentTx.packet.data.data(), currentTx.packet.data.size());
|
||||||
if (rc == RADIOLIB_ERR_NONE) {
|
if (rc == RADIOLIB_ERR_NONE) {
|
||||||
currentTx.callback(currentTx.id, TransmissionState::PendingTransmit);
|
currentTx.callback(currentTx.id, TransmissionState::PendingTransmit);
|
||||||
|
|
||||||
TT_LOG_I(TAG, "WAIT TX FLAG");
|
|
||||||
auto txEventFlags = events.wait(SX1262_INTERRUPT_BIT | SX1262_DIO1_EVENT_BIT, tt::EventFlag::WaitAny, pdMS_TO_TICKS(2000));
|
auto txEventFlags = events.wait(SX1262_INTERRUPT_BIT | SX1262_DIO1_EVENT_BIT, tt::EventFlag::WaitAny, pdMS_TO_TICKS(2000));
|
||||||
TT_LOG_W(TAG, "Event, flag=%X", txEventFlags);
|
|
||||||
|
|
||||||
// Thread might've been interrupted in the meanwhile
|
// Thread might've been interrupted in the meanwhile
|
||||||
if (isThreadInterrupted()) {
|
if (isThreadInterrupted()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the DIO1 bit is unset, this means the wait timed out
|
||||||
if (txEventFlags & SX1262_DIO1_EVENT_BIT) {
|
if (txEventFlags & SX1262_DIO1_EVENT_BIT) {
|
||||||
currentTx.callback(currentTx.id, TransmissionState::Transmitted);
|
currentTx.callback(currentTx.id, TransmissionState::Transmitted);
|
||||||
} else {
|
} else {
|
||||||
@ -171,24 +223,31 @@ void Sx1262::doTransmit() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Sx1262::doListen() {
|
void Sx1262::doListen() {
|
||||||
radio.startReceive();
|
if (currentModem != Modulation::LrFhss) {
|
||||||
TT_LOG_I(TAG, "WAIT FLAG");
|
radio.startReceive();
|
||||||
auto eventFlags = events.wait(SX1262_INTERRUPT_BIT | SX1262_DIO1_EVENT_BIT | SX1262_QUEUED_TX_BIT);
|
events.wait(SX1262_INTERRUPT_BIT | SX1262_DIO1_EVENT_BIT | SX1262_QUEUED_TX_BIT);
|
||||||
TT_LOG_W(TAG, "Event, flag=%X", eventFlags);
|
} else {
|
||||||
|
// LR-FHSS modem only supports TX
|
||||||
|
events.wait(SX1262_INTERRUPT_BIT | SX1262_QUEUED_TX_BIT);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sx1262::doReceive() {
|
void Sx1262::doReceive() {
|
||||||
|
// LR-FHSS modem only supports TX
|
||||||
|
if (currentModem == Modulation::LrFhss) return;
|
||||||
|
|
||||||
uint16_t rxSize = radio.getPacketLength(true);
|
uint16_t rxSize = radio.getPacketLength(true);
|
||||||
std::vector<uint8_t> data(rxSize);
|
std::vector<uint8_t> data(rxSize);
|
||||||
uint16_t rc = radio.readData(data.data(), rxSize);
|
uint16_t rc = radio.readData(data.data(), rxSize);
|
||||||
if (rc != RADIOLIB_ERR_NONE) {
|
if (rc != RADIOLIB_ERR_NONE) {
|
||||||
TT_LOG_E(TAG, "Error receiving data, RadioLib returned %hi", rc);
|
TT_LOG_E(TAG, "Error receiving data, RadioLib returned %hi", rc);
|
||||||
} else if(rxSize == 0) {
|
} else if(rxSize == 0) {
|
||||||
//TT_LOG_W(TAG, "Received data length 0");
|
// This can cause a flood of messages if there are ones emitted here,
|
||||||
|
// as a warning here doesn't bring that much to the table it is skipped.
|
||||||
|
// The body is kept empty intentionally.'
|
||||||
} else {
|
} else {
|
||||||
float rssi = radio.getRSSI();
|
float rssi = radio.getRSSI();
|
||||||
float snr = radio.getSNR();
|
float snr = radio.getSNR();
|
||||||
TT_LOG_I(TAG, "LoRa RX size=%d RSSI=%f SNR=%f", rxSize, rssi, snr);
|
|
||||||
auto rxPacket = tt::hal::radio::RxPacket {
|
auto rxPacket = tt::hal::radio::RxPacket {
|
||||||
.data = data,
|
.data = data,
|
||||||
.rssi = rssi,
|
.rssi = rssi,
|
||||||
@ -198,7 +257,7 @@ void Sx1262::doReceive() {
|
|||||||
publishRx(rxPacket);
|
publishRx(rxPacket);
|
||||||
}
|
}
|
||||||
|
|
||||||
// A delay is needed before a new command
|
// A delay before a new command improves reliability
|
||||||
vTaskDelay(pdMS_TO_TICKS(100));
|
vTaskDelay(pdMS_TO_TICKS(SX1262_COOLDOWN_MILLIS));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -25,6 +25,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
static constexpr auto SX1262_COOLDOWN_MILLIS = 100;
|
||||||
static constexpr auto SX1262_INTERRUPT_BIT = BIT0;
|
static constexpr auto SX1262_INTERRUPT_BIT = BIT0;
|
||||||
static constexpr auto SX1262_DIO1_EVENT_BIT = BIT1;
|
static constexpr auto SX1262_DIO1_EVENT_BIT = BIT1;
|
||||||
static constexpr auto SX1262_QUEUED_TX_BIT = BIT2;
|
static constexpr auto SX1262_QUEUED_TX_BIT = BIT2;
|
||||||
@ -37,6 +38,7 @@ private:
|
|||||||
Module radioModule;
|
Module radioModule;
|
||||||
SX1262 radio;
|
SX1262 radio;
|
||||||
TxItem currentTx;
|
TxItem currentTx;
|
||||||
|
Modulation currentModem;
|
||||||
|
|
||||||
int8_t power = 0;
|
int8_t power = 0;
|
||||||
float frequency = 0.0;
|
float frequency = 0.0;
|
||||||
@ -47,6 +49,7 @@ private:
|
|||||||
uint16_t preambleLength = 0;
|
uint16_t preambleLength = 0;
|
||||||
float bitRate = 0.0;
|
float bitRate = 0.0;
|
||||||
float frequencyDeviation = 0.0;
|
float frequencyDeviation = 0.0;
|
||||||
|
bool narrowGrid = false;
|
||||||
|
|
||||||
void registerDio1Isr();
|
void registerDio1Isr();
|
||||||
void unregisterDio1Isr();
|
void unregisterDio1Isr();
|
||||||
@ -70,17 +73,25 @@ public:
|
|||||||
, hal(configuration.spiHostDevice, configuration.spiFrequency, configuration.csPin, lock)
|
, hal(configuration.spiHostDevice, configuration.spiFrequency, configuration.csPin, lock)
|
||||||
, radioModule(&hal, configuration.csPin, configuration.irqPin, configuration.resetPin, configuration.busyPin)
|
, radioModule(&hal, configuration.csPin, configuration.irqPin, configuration.resetPin, configuration.busyPin)
|
||||||
, radio(&radioModule)
|
, radio(&radioModule)
|
||||||
|
, currentModem(Modulation::None)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
~Sx1262() override = default;
|
~Sx1262() override = default;
|
||||||
|
|
||||||
std::string getName() const override { return name; }
|
std::string getName() const override { return name; }
|
||||||
|
|
||||||
std::string getDescription() const override { return "SX1262 LoRa and FSK capable radio"; }
|
std::string getDescription() const override { return "Semtech SX1262 LoRa, FSK and LR-FHSS capable radio"; }
|
||||||
|
|
||||||
bool configure(const Parameter parameter, const float value) override;
|
bool setParameter(const Parameter parameter, const float value) override;
|
||||||
|
bool getParameter(const Parameter parameter, float &value) const override;
|
||||||
|
|
||||||
bool isCapableOf(const Modulation modulation) {
|
bool canTransmit(const Modulation modulation) override {
|
||||||
|
return (modulation == Modulation::Fsk) ||
|
||||||
|
(modulation == Modulation::LoRa) ||
|
||||||
|
(modulation == Modulation::LrFhss);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool canReceive(const Modulation modulation) override {
|
||||||
return (modulation == Modulation::Fsk) || (modulation == Modulation::LoRa);
|
return (modulation == Modulation::Fsk) || (modulation == Modulation::LoRa);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -8,13 +8,21 @@ namespace tt::hal::radio {
|
|||||||
|
|
||||||
class ParameterSet {
|
class ParameterSet {
|
||||||
private:
|
private:
|
||||||
using Map = std::unordered_map<RadioDevice::Parameter, float, std::hash<int> >;
|
struct ParameterHash
|
||||||
|
{
|
||||||
|
std::size_t operator()(RadioDevice::Parameter t) const
|
||||||
|
{
|
||||||
|
return static_cast<std::size_t>(t);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
using Map = std::unordered_map<RadioDevice::Parameter, float, ParameterHash>;
|
||||||
Map parameters;
|
Map parameters;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit ParameterSet() {}
|
explicit ParameterSet() {}
|
||||||
explicit ParameterSet(const ParameterSet& other) { parameters = other.parameters; }
|
explicit ParameterSet(const ParameterSet& other) { parameters = other.parameters; }
|
||||||
~ParameterSet() override = default;
|
~ParameterSet() = default;
|
||||||
|
|
||||||
float get(const RadioDevice::Parameter parameter) { return parameters[parameter]; }
|
float get(const RadioDevice::Parameter parameter) { return parameters[parameter]; }
|
||||||
void set(const RadioDevice::Parameter parameter, const float value) { parameters[parameter] = value; }
|
void set(const RadioDevice::Parameter parameter, const float value) { parameters[parameter] = value; }
|
||||||
@ -32,7 +40,15 @@ public:
|
|||||||
for (const auto& [parameter, value] : parameters) {
|
for (const auto& [parameter, value] : parameters) {
|
||||||
// No break on error chosen to apply all parameters,
|
// No break on error chosen to apply all parameters,
|
||||||
// a bad one doesn't make the successive tries any more invalid
|
// a bad one doesn't make the successive tries any more invalid
|
||||||
successful &= radio.configure(parameter, value);
|
successful &= radio.setParameter(parameter, value);
|
||||||
|
}
|
||||||
|
return successful;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool load(const RadioDevice &radio) {
|
||||||
|
bool successful = true;
|
||||||
|
for (const auto& [parameter, value] : parameters) {
|
||||||
|
successful &= radio.getParameter(parameter, parameters[parameter]);
|
||||||
}
|
}
|
||||||
return successful;
|
return successful;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -25,6 +25,7 @@ class RadioDevice : public Device {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
enum class Modulation {
|
enum class Modulation {
|
||||||
|
None,
|
||||||
Fsk,
|
Fsk,
|
||||||
LoRa,
|
LoRa,
|
||||||
LrFhss
|
LrFhss
|
||||||
@ -40,7 +41,8 @@ public:
|
|||||||
PreambleLength,
|
PreambleLength,
|
||||||
FrequencyDeviation,
|
FrequencyDeviation,
|
||||||
DataRate,
|
DataRate,
|
||||||
AddressWidth
|
AddressWidth,
|
||||||
|
NarrowGrid
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef int RxSubscriptionId;
|
typedef int RxSubscriptionId;
|
||||||
@ -118,8 +120,10 @@ public:
|
|||||||
|
|
||||||
Type getType() const override { return Type::Radio; }
|
Type getType() const override { return Type::Radio; }
|
||||||
|
|
||||||
virtual bool configure(const Parameter parameter, const float value) = 0;
|
virtual bool setParameter(const Parameter parameter, const float value) = 0;
|
||||||
virtual bool isCapableOf(const Modulation modulation) = 0;
|
virtual bool getParameter(const Parameter parameter, float &value) const = 0;
|
||||||
|
virtual bool canTransmit(const Modulation modulation) = 0;
|
||||||
|
virtual bool canReceive(const Modulation modulation) = 0;
|
||||||
|
|
||||||
virtual bool start(const Modulation modulation) = 0;
|
virtual bool start(const Modulation modulation) = 0;
|
||||||
virtual bool stop() = 0;
|
virtual bool stop() = 0;
|
||||||
|
|||||||
@ -5,6 +5,7 @@
|
|||||||
#include <Tactility/Assets.h>
|
#include <Tactility/Assets.h>
|
||||||
#include <Tactility/StringUtils.h>
|
#include <Tactility/StringUtils.h>
|
||||||
#include <Tactility/hal/radio/RadioDevice.h>
|
#include <Tactility/hal/radio/RadioDevice.h>
|
||||||
|
#include <Tactility/hal/radio/ParameterSet.h>
|
||||||
|
|
||||||
#include "Tactility/lvgl/LvglSync.h"
|
#include "Tactility/lvgl/LvglSync.h"
|
||||||
|
|
||||||
@ -90,6 +91,29 @@ std::string hexdump(const std::vector<uint8_t>& data) {
|
|||||||
return oss.str();
|
return oss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isValidHexString(const std::string& hex) {
|
||||||
|
if (hex.empty() || (hex.size() % 2) != 0) return false;
|
||||||
|
for (char c : hex)
|
||||||
|
if (!std::isxdigit(static_cast<unsigned char>(c)))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool parseHexString(const std::string& hex, std::vector<uint8_t>& out) {
|
||||||
|
if (!isValidHexString(hex)) return false;
|
||||||
|
out.clear();
|
||||||
|
out.reserve(hex.size() / 2);
|
||||||
|
for (size_t i = 0; i < hex.size(); i += 2) {
|
||||||
|
uint8_t high = std::isdigit(hex[i]) ? (hex[i] - '0')
|
||||||
|
: (std::tolower(hex[i]) - 'a' + 10);
|
||||||
|
uint8_t low = std::isdigit(hex[i+1]) ? (hex[i+1] - '0')
|
||||||
|
: (std::tolower(hex[i+1]) - 'a' + 10);
|
||||||
|
out.push_back(static_cast<uint8_t>((high << 4) | low));
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class LoraView {
|
class LoraView {
|
||||||
public:
|
public:
|
||||||
@ -110,7 +134,8 @@ private:
|
|||||||
loraDevs.clear();
|
loraDevs.clear();
|
||||||
|
|
||||||
for (const auto& radio: radios) {
|
for (const auto& radio: radios) {
|
||||||
if (radio->isCapableOf(tt::hal::radio::RadioDevice::Modulation::LoRa)) {
|
if (radio->canTransmit(tt::hal::radio::RadioDevice::Modulation::LoRa) &&
|
||||||
|
radio->canReceive(tt::hal::radio::RadioDevice::Modulation::LoRa)) {
|
||||||
loraDevNames.push_back(radio->getName());
|
loraDevNames.push_back(radio->getName());
|
||||||
loraDevs.push_back(radio);
|
loraDevs.push_back(radio);
|
||||||
}
|
}
|
||||||
@ -409,11 +434,11 @@ public:
|
|||||||
bool configured = true;
|
bool configured = true;
|
||||||
buffer = lv_textarea_get_text(frequencyInput);
|
buffer = lv_textarea_get_text(frequencyInput);
|
||||||
if (!buffer.empty()) {
|
if (!buffer.empty()) {
|
||||||
configured &= loraDevice->configure(Frequency, std::stof(buffer));
|
configured &= loraDevice->setParameter(Frequency, std::stof(buffer));
|
||||||
}
|
}
|
||||||
buffer = lv_textarea_get_text(bandwidthInput);
|
buffer = lv_textarea_get_text(bandwidthInput);
|
||||||
if (!buffer.empty()) {
|
if (!buffer.empty()) {
|
||||||
configured &= loraDevice->configure(Bandwidth, std::stof(buffer));
|
configured &= loraDevice->setParameter(Bandwidth, std::stof(buffer));
|
||||||
}
|
}
|
||||||
buffer = lv_textarea_get_text(syncwordInput);
|
buffer = lv_textarea_get_text(syncwordInput);
|
||||||
if (!buffer.empty()) {
|
if (!buffer.empty()) {
|
||||||
@ -421,20 +446,20 @@ public:
|
|||||||
std::stringstream ss(buffer);
|
std::stringstream ss(buffer);
|
||||||
ss >> std::hex >> syncWord;
|
ss >> std::hex >> syncWord;
|
||||||
|
|
||||||
configured &= loraDevice->configure(SyncWord, std::stoi(buffer, nullptr, 16));
|
configured &= loraDevice->setParameter(SyncWord, std::stoi(buffer, nullptr, 16));
|
||||||
}
|
}
|
||||||
value = lv_slider_get_value(deBitsInput);
|
value = lv_slider_get_value(deBitsInput);
|
||||||
configured &= loraDevice->configure(CodingRate, value);
|
configured &= loraDevice->setParameter(CodingRate, value);
|
||||||
|
|
||||||
value = lv_slider_get_value(sfInput);
|
value = lv_slider_get_value(sfInput);
|
||||||
configured &= loraDevice->configure(SpreadFactor, value);
|
configured &= loraDevice->setParameter(SpreadFactor, value);
|
||||||
|
|
||||||
value = lv_slider_get_value(preambleChirpsInput);
|
value = lv_slider_get_value(preambleChirpsInput);
|
||||||
configured &= loraDevice->configure(PreambleLength, value);
|
configured &= loraDevice->setParameter(PreambleLength, value);
|
||||||
|
|
||||||
buffer = lv_textarea_get_text(txPowInput);
|
buffer = lv_textarea_get_text(txPowInput);
|
||||||
if (!buffer.empty()) {
|
if (!buffer.empty()) {
|
||||||
configured &= loraDevice->configure(Power, std::stof(buffer));
|
configured &= loraDevice->setParameter(Power, std::stof(buffer));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -558,12 +583,11 @@ class ChirpChatterApp : public App {
|
|||||||
|
|
||||||
lv_obj_t* msg_label = lv_label_create(msg_container);
|
lv_obj_t* msg_label = lv_label_create(msg_container);
|
||||||
|
|
||||||
std::vector<uint8_t> data(packet.data, packet.data + packet.size);
|
|
||||||
std::string messageBuf = "";
|
std::string messageBuf = "";
|
||||||
if (isPrintableData(data)) {
|
if (isPrintableData(packet.data)) {
|
||||||
messageBuf = std::string((char*)packet.data, packet.size);
|
messageBuf = std::string(packet.data.begin(), packet.data.end());
|
||||||
} else {
|
} else {
|
||||||
messageBuf = hexdump(data);
|
messageBuf = hexdump(packet.data);
|
||||||
}
|
}
|
||||||
lv_label_set_text(msg_label, messageBuf.c_str());
|
lv_label_set_text(msg_label, messageBuf.c_str());
|
||||||
lv_obj_set_width(msg_label, lv_pct(100));
|
lv_obj_set_width(msg_label, lv_pct(100));
|
||||||
@ -793,8 +817,22 @@ public:
|
|||||||
|
|
||||||
void sendMessage() {
|
void sendMessage() {
|
||||||
std::string message = lv_textarea_get_text(inputField);
|
std::string message = lv_textarea_get_text(inputField);
|
||||||
std::vector<uint8_t> data(message.begin(), message.end());
|
std::vector<uint8_t> data;
|
||||||
loraDevice->transmit(data, [this](hal::radio::RadioDevice::TxId id, hal::radio::RadioDevice::TransmissionState state) {
|
if (message == "!test1") {
|
||||||
|
parseHexString("ffffffff1147fec0c60940e5810800009671ad09dd2a0e7841ce266a3d759e967dc32a16bf4d5eecafde28d82b690f22eccf968a", data);
|
||||||
|
} else if (message == "!ack") {
|
||||||
|
parseHexString("ffffffff1147fec0f1dee9ab81080000922bf53364151a15", data);
|
||||||
|
} else if (message == "!gdn8") {
|
||||||
|
parseHexString("ffffffff1147fec025ffdd7a81080000768023f848619a3782ddadb5f686dc", data);
|
||||||
|
} else if (message == "!gm") {
|
||||||
|
parseHexString("ffffffff1147fec08a27ff4b810800003185053566e837fb0b88ade5fc84d9a13e", data);
|
||||||
|
} else if (message == "!ptest1") {
|
||||||
|
parseHexString("ffffffff1147fec0ef0e5bd48108000035f4be1f4bf703b3cce235423dd218a0c9ec745032a1f04be19c", data);
|
||||||
|
} else {
|
||||||
|
data = std::vector<uint8_t>(message.begin(), message.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
loraDevice->transmit(tt::hal::radio::TxPacket{.data = data}, [this](hal::radio::RadioDevice::TxId id, hal::radio::RadioDevice::TransmissionState state) {
|
||||||
this->onTxStatus(id, state);
|
this->onTxStatus(id, state);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -28,6 +28,8 @@ void RadioDevice::publishRx(const RxPacket& packet) {
|
|||||||
const char* toString(RadioDevice::Modulation modulation) {
|
const char* toString(RadioDevice::Modulation modulation) {
|
||||||
using enum RadioDevice::Modulation;
|
using enum RadioDevice::Modulation;
|
||||||
switch (modulation) {
|
switch (modulation) {
|
||||||
|
case None:
|
||||||
|
return "none";
|
||||||
case Fsk:
|
case Fsk:
|
||||||
return "FSK";
|
return "FSK";
|
||||||
case LoRa:
|
case LoRa:
|
||||||
@ -62,6 +64,8 @@ const char* toString(RadioDevice::Parameter parameter) {
|
|||||||
return TT_STRINGIFY(DataRate);
|
return TT_STRINGIFY(DataRate);
|
||||||
case AddressWidth:
|
case AddressWidth:
|
||||||
return TT_STRINGIFY(AddressWidth);
|
return TT_STRINGIFY(AddressWidth);
|
||||||
|
case NarrowGrid:
|
||||||
|
return TT_STRINGIFY(NarrowGrid);
|
||||||
default:
|
default:
|
||||||
return "Unknown";
|
return "Unknown";
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user