Radio: Refactor RadioDevice thread into compat class
This commit is contained in:
parent
c705359427
commit
98c9fb7201
99
Drivers/RadioLibCompat/Source/RadiolibThreadedDevice.cpp
Normal file
99
Drivers/RadioLibCompat/Source/RadiolibThreadedDevice.cpp
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
#include "RadiolibThreadedDevice.h"
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
constexpr const char* TAG = "RadiolibThreadedDevice";
|
||||||
|
|
||||||
|
bool RadiolibThreadedDevice::start(const Modulation modulation) {
|
||||||
|
auto lock = getMutex().asScopedLock();
|
||||||
|
|
||||||
|
if (!isCapableOf(modulation)) {
|
||||||
|
TT_LOG_E(TAG, "Can't start device \"%s\", not capable of modulation \"%s\"", getName().c_str(), toString(modulation));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
lock.lock();
|
||||||
|
|
||||||
|
if (thread != nullptr && thread->getState() != tt::Thread::State::Stopped) {
|
||||||
|
TT_LOG_W(TAG, "Already started");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
threadInterrupted = false;
|
||||||
|
|
||||||
|
TT_LOG_I(TAG, "Starting thread");
|
||||||
|
setState(State::PendingOn);
|
||||||
|
|
||||||
|
thread = std::make_unique<tt::Thread>(
|
||||||
|
threadName,
|
||||||
|
threadSize,
|
||||||
|
[this, modulation]() {
|
||||||
|
return this->threadMain(modulation);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
thread->setPriority(tt::Thread::Priority::High);
|
||||||
|
thread->start();
|
||||||
|
|
||||||
|
TT_LOG_I(TAG, "Starting finished");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RadiolibThreadedDevice::stop() {
|
||||||
|
auto lock = getMutex().asScopedLock();
|
||||||
|
lock.lock();
|
||||||
|
|
||||||
|
setState(State::PendingOff);
|
||||||
|
|
||||||
|
if (thread != nullptr) {
|
||||||
|
threadInterrupted = true;
|
||||||
|
interruptSignal();
|
||||||
|
|
||||||
|
// Detach thread, it will auto-delete when leaving the current scope
|
||||||
|
auto old_thread = std::move(thread);
|
||||||
|
|
||||||
|
if (old_thread->getState() != tt::Thread::State::Stopped) {
|
||||||
|
// Unlock so thread can lock
|
||||||
|
lock.unlock();
|
||||||
|
// Wait for thread to finish
|
||||||
|
old_thread->join();
|
||||||
|
// Re-lock to continue logic below
|
||||||
|
lock.lock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setState(State::Off);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RadiolibThreadedDevice::isThreadInterrupted() const {
|
||||||
|
auto lock = getMutex().asScopedLock();
|
||||||
|
lock.lock();
|
||||||
|
return threadInterrupted;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t RadiolibThreadedDevice::threadMain(const Modulation modulation) {
|
||||||
|
|
||||||
|
int rc = doBegin(modulation);
|
||||||
|
if (rc != 0) {
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
setState(State::On);
|
||||||
|
|
||||||
|
while (!isThreadInterrupted()) {
|
||||||
|
doListen();
|
||||||
|
|
||||||
|
// Thread might've been interrupted in the meanwhile
|
||||||
|
if (isThreadInterrupted()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getTxQueueSize() > 0) {
|
||||||
|
doTransmit();
|
||||||
|
} else {
|
||||||
|
doReceive();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
doEnd();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
37
Drivers/RadioLibCompat/Source/RadiolibThreadedDevice.h
Normal file
37
Drivers/RadioLibCompat/Source/RadiolibThreadedDevice.h
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Tactility/hal/radio/RadioDevice.h>
|
||||||
|
#include <Tactility/Thread.h>
|
||||||
|
|
||||||
|
class RadiolibThreadedDevice : public tt::hal::radio::RadioDevice {
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string threadName;
|
||||||
|
size_t threadSize;
|
||||||
|
std::unique_ptr<tt::Thread> _Nullable thread;
|
||||||
|
bool threadInterrupted = false;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual int32_t threadMain(const Modulation modulation);
|
||||||
|
bool isThreadInterrupted() const;
|
||||||
|
|
||||||
|
virtual void interruptSignal() = 0;
|
||||||
|
|
||||||
|
virtual int doBegin(const Modulation modulation) = 0;
|
||||||
|
virtual void doEnd() = 0;
|
||||||
|
virtual void doTransmit() = 0;
|
||||||
|
virtual void doListen() = 0;
|
||||||
|
virtual void doReceive() = 0;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit RadiolibThreadedDevice(const std::string& threadName, const size_t threadSize)
|
||||||
|
: threadName(threadName)
|
||||||
|
, threadSize(threadSize)
|
||||||
|
{}
|
||||||
|
|
||||||
|
~RadiolibThreadedDevice() override = default;
|
||||||
|
|
||||||
|
virtual bool start(const Modulation modulation) override;
|
||||||
|
virtual bool stop() override;
|
||||||
|
|
||||||
|
};
|
||||||
@ -83,36 +83,21 @@ void Sx1262::unregisterDio1Isr() {
|
|||||||
gpio_wakeup_disable(configuration.irqPin);
|
gpio_wakeup_disable(configuration.irqPin);
|
||||||
gpio_set_intr_type(configuration.irqPin, GPIO_INTR_DISABLE);
|
gpio_set_intr_type(configuration.irqPin, GPIO_INTR_DISABLE);
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
void IRAM_ATTR Sx1262::dio1Event() {
|
|
||||||
static const auto DRAM_ATTR rxbit = RADIO_RECEIVED_BIT;
|
|
||||||
static const auto DRAM_ATTR txbit = RADIO_TRANSMITTED_BIT;
|
|
||||||
|
|
||||||
switch (exchangeState) {
|
|
||||||
case ExchangeState::Receive:
|
|
||||||
getEventFlag().set(rxbit);
|
|
||||||
break;
|
|
||||||
case ExchangeState::TransmitWaiting:
|
|
||||||
getEventFlag().set(txbit);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
gpio_set_level(GPIO_NUM_9, 1);
|
|
||||||
}*/
|
|
||||||
|
|
||||||
|
|
||||||
void IRAM_ATTR Sx1262::dio1Event() {
|
void IRAM_ATTR Sx1262::dio1Event() {
|
||||||
static const auto DRAM_ATTR bit = SX1262_DIO1_EVENT_BIT;
|
static const auto DRAM_ATTR bit = SX1262_DIO1_EVENT_BIT;
|
||||||
getEventFlag().set(bit);
|
events.set(bit);
|
||||||
|
|
||||||
gpio_set_level(GPIO_NUM_9, 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t Sx1262::threadMain(const Modulation modulation) {
|
void Sx1262::txQueuedSignal() {
|
||||||
using enum ExchangeState;
|
events.set(SX1262_QUEUED_TX_BIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Sx1262::interruptSignal() {
|
||||||
|
events.set(SX1262_INTERRUPT_BIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
int Sx1262::doBegin(const Modulation modulation) {
|
||||||
uint16_t rc = RADIOLIB_ERR_NONE;
|
uint16_t rc = RADIOLIB_ERR_NONE;
|
||||||
|
|
||||||
if (modulation == Modulation::LoRa) {
|
if (modulation == Modulation::LoRa) {
|
||||||
@ -127,13 +112,6 @@ int32_t Sx1262::threadMain(const Modulation modulation) {
|
|||||||
configuration.tcxoVoltage,
|
configuration.tcxoVoltage,
|
||||||
configuration.useRegulatorLdo
|
configuration.useRegulatorLdo
|
||||||
);
|
);
|
||||||
/*
|
|
||||||
radio.forceLDRO(false);
|
|
||||||
radio.setCRC(true);
|
|
||||||
radio.invertIQ(false);
|
|
||||||
radio.setWhitening(true, 0x00FF);
|
|
||||||
radio.explicitHeader();*/
|
|
||||||
|
|
||||||
} else if (modulation == Modulation::Fsk) {
|
} else if (modulation == Modulation::Fsk) {
|
||||||
rc = radio.beginFSK(
|
rc = radio.beginFSK(
|
||||||
frequency,
|
frequency,
|
||||||
@ -158,79 +136,69 @@ int32_t Sx1262::threadMain(const Modulation modulation) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
registerDio1Isr();
|
registerDio1Isr();
|
||||||
setState(State::On);
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
TT_LOG_I(TAG, "SX1262 device ready to receive!");
|
void Sx1262::doEnd() {
|
||||||
exchangeState = Receive;
|
unregisterDio1Isr();
|
||||||
|
}
|
||||||
|
|
||||||
while (!isThreadInterrupted()) {
|
void Sx1262::doTransmit() {
|
||||||
radio.startReceive();
|
currentTx = popNextQueuedTx();
|
||||||
TT_LOG_I(TAG, "WAIT FLAG");
|
radio.standby();
|
||||||
auto eventFlags = getEventFlag().wait(RADIO_TERMINATE_BIT | SX1262_DIO1_EVENT_BIT | RADIO_TRANSMIT_QUEUED_BIT);
|
uint16_t rc = radio.startTransmit(currentTx.packet.data.data(), currentTx.packet.data.size());
|
||||||
TT_LOG_W(TAG, "Event, flag=%X", eventFlags);
|
if (rc == RADIOLIB_ERR_NONE) {
|
||||||
|
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));
|
||||||
|
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()) {
|
||||||
break;
|
return;
|
||||||
}
|
}
|
||||||
|
if (txEventFlags & SX1262_DIO1_EVENT_BIT) {
|
||||||
if ((eventFlags & RADIO_TRANSMIT_QUEUED_BIT) && (getTxQueueSize() > 0)) {
|
currentTx.callback(currentTx.id, TransmissionState::Transmitted);
|
||||||
currentTx = popNextQueuedTx();
|
|
||||||
radio.standby();
|
|
||||||
uint16_t rc = radio.startTransmit(currentTx.packet.data.data(), currentTx.packet.data.size());
|
|
||||||
if (rc == RADIOLIB_ERR_NONE) {
|
|
||||||
exchangeState = TransmitWaiting;
|
|
||||||
currentTx.callback(currentTx.id, TransmissionState::PendingTransmit);
|
|
||||||
|
|
||||||
TT_LOG_I(TAG, "WAIT TX FLAG");
|
|
||||||
auto txEventFlags = getEventFlag().wait(RADIO_TERMINATE_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
|
|
||||||
if (isThreadInterrupted()) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (txEventFlags & SX1262_DIO1_EVENT_BIT) {
|
|
||||||
currentTx.callback(currentTx.id, TransmissionState::Transmitted);
|
|
||||||
} else {
|
|
||||||
currentTx.callback(currentTx.id, TransmissionState::Timeout);
|
|
||||||
}
|
|
||||||
exchangeState = Receive;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
TT_LOG_E(TAG, "Error transmitting id=%d, rc=%hi", currentTx.id, rc);
|
|
||||||
currentTx.callback(currentTx.id, TransmissionState::Error);
|
|
||||||
exchangeState = Receive;
|
|
||||||
}
|
|
||||||
} else if (eventFlags & SX1262_DIO1_EVENT_BIT) {
|
|
||||||
uint16_t rxSize = radio.getPacketLength(true);
|
|
||||||
std::vector<uint8_t> data(rxSize);
|
|
||||||
uint16_t rc = radio.readData(data.data(), rxSize);
|
|
||||||
if (rc != RADIOLIB_ERR_NONE) {
|
|
||||||
TT_LOG_E(TAG, "Error receiving data, RadioLib returned %hi", rc);
|
|
||||||
} else if(rxSize == 0) {
|
|
||||||
//TT_LOG_W(TAG, "Received data length 0");
|
|
||||||
} else {
|
|
||||||
float rssi = radio.getRSSI();
|
|
||||||
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 {
|
|
||||||
.data = data,
|
|
||||||
.rssi = rssi,
|
|
||||||
.snr = snr
|
|
||||||
};
|
|
||||||
|
|
||||||
publishRx(rxPacket);
|
|
||||||
}
|
|
||||||
|
|
||||||
// A delay is needed before a new command
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(100));
|
|
||||||
gpio_set_level(GPIO_NUM_9, 0);
|
|
||||||
} else {
|
} else {
|
||||||
TT_LOG_W(TAG, "Unhandled event, flag=%X", eventFlags);
|
currentTx.callback(currentTx.id, TransmissionState::Timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
TT_LOG_E(TAG, "Error transmitting id=%d, rc=%hi", currentTx.id, rc);
|
||||||
|
currentTx.callback(currentTx.id, TransmissionState::Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Sx1262::doListen() {
|
||||||
|
radio.startReceive();
|
||||||
|
TT_LOG_I(TAG, "WAIT FLAG");
|
||||||
|
auto eventFlags = events.wait(SX1262_INTERRUPT_BIT | SX1262_DIO1_EVENT_BIT | SX1262_QUEUED_TX_BIT);
|
||||||
|
TT_LOG_W(TAG, "Event, flag=%X", eventFlags);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Sx1262::doReceive() {
|
||||||
|
uint16_t rxSize = radio.getPacketLength(true);
|
||||||
|
std::vector<uint8_t> data(rxSize);
|
||||||
|
uint16_t rc = radio.readData(data.data(), rxSize);
|
||||||
|
if (rc != RADIOLIB_ERR_NONE) {
|
||||||
|
TT_LOG_E(TAG, "Error receiving data, RadioLib returned %hi", rc);
|
||||||
|
} else if(rxSize == 0) {
|
||||||
|
//TT_LOG_W(TAG, "Received data length 0");
|
||||||
|
} else {
|
||||||
|
float rssi = radio.getRSSI();
|
||||||
|
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 {
|
||||||
|
.data = data,
|
||||||
|
.rssi = rssi,
|
||||||
|
.snr = snr
|
||||||
|
};
|
||||||
|
|
||||||
|
publishRx(rxPacket);
|
||||||
}
|
}
|
||||||
|
|
||||||
unregisterDio1Isr();
|
// A delay is needed before a new command
|
||||||
return 0;
|
vTaskDelay(pdMS_TO_TICKS(100));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,14 +1,16 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Tactility/hal/radio/RadioDevice.h>
|
|
||||||
#include <Tactility/hal/spi/Spi.h>
|
#include <Tactility/hal/spi/Spi.h>
|
||||||
|
#include <Tactility/EventFlag.h>
|
||||||
|
#include <Tactility/Lock.h>
|
||||||
|
|
||||||
#include <RadioLib.h>
|
#include <RadioLib.h>
|
||||||
#include "RadiolibTactilityHal.h"
|
#include "RadiolibTactilityHal.h"
|
||||||
|
#include "RadiolibThreadedDevice.h"
|
||||||
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
class Sx1262 final : public tt::hal::radio::RadioDevice {
|
class Sx1262 final : public RadiolibThreadedDevice {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
struct Configuration {
|
struct Configuration {
|
||||||
@ -23,23 +25,18 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static constexpr auto SX1262_DIO1_EVENT_BIT = BIT8;
|
static constexpr auto SX1262_INTERRUPT_BIT = BIT0;
|
||||||
|
static constexpr auto SX1262_DIO1_EVENT_BIT = BIT1;
|
||||||
enum class ExchangeState {
|
static constexpr auto SX1262_QUEUED_TX_BIT = BIT2;
|
||||||
Idle,
|
|
||||||
Receive,
|
|
||||||
//TransmitInitiated,
|
|
||||||
TransmitWaiting
|
|
||||||
};
|
|
||||||
|
|
||||||
std::string name;
|
std::string name;
|
||||||
const Configuration configuration;
|
const Configuration configuration;
|
||||||
std::shared_ptr<tt::Lock> lock;
|
std::shared_ptr<tt::Lock> lock;
|
||||||
|
tt::EventFlag events;
|
||||||
RadiolibTactilityHal hal;
|
RadiolibTactilityHal hal;
|
||||||
Module radioModule;
|
Module radioModule;
|
||||||
SX1262 radio;
|
SX1262 radio;
|
||||||
TxItem currentTx;
|
TxItem currentTx;
|
||||||
ExchangeState exchangeState;
|
|
||||||
|
|
||||||
int8_t power = 0;
|
int8_t power = 0;
|
||||||
float frequency = 0.0;
|
float frequency = 0.0;
|
||||||
@ -51,20 +48,29 @@ private:
|
|||||||
float bitRate = 0.0;
|
float bitRate = 0.0;
|
||||||
float frequencyDeviation = 0.0;
|
float frequencyDeviation = 0.0;
|
||||||
|
|
||||||
int32_t threadMain();
|
|
||||||
void registerDio1Isr();
|
void registerDio1Isr();
|
||||||
void unregisterDio1Isr();
|
void unregisterDio1Isr();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void txQueuedSignal() override;
|
||||||
|
virtual void interruptSignal() override;
|
||||||
|
|
||||||
|
virtual int doBegin(const Modulation modulation) override;
|
||||||
|
virtual void doEnd() override;
|
||||||
|
virtual void doTransmit() override;
|
||||||
|
virtual void doListen() override;
|
||||||
|
virtual void doReceive() override;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
explicit Sx1262(const std::string& name, const Configuration& configuration, std::shared_ptr<tt::Lock> lock = nullptr)
|
explicit Sx1262(const std::string& name, const Configuration& configuration, std::shared_ptr<tt::Lock> lock = nullptr)
|
||||||
: RadioDevice(name, 4096)
|
: RadiolibThreadedDevice(name, 4096)
|
||||||
, name(name)
|
, name(name)
|
||||||
, configuration(configuration)
|
, configuration(configuration)
|
||||||
, 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)
|
||||||
, exchangeState(ExchangeState::Idle) {}
|
{}
|
||||||
|
|
||||||
~Sx1262() override = default;
|
~Sx1262() override = default;
|
||||||
|
|
||||||
@ -78,12 +84,5 @@ public:
|
|||||||
return (modulation == Modulation::Fsk) || (modulation == Modulation::LoRa);
|
return (modulation == Modulation::Fsk) || (modulation == Modulation::LoRa);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hasReceived();
|
|
||||||
|
|
||||||
void dio1Event();
|
void dio1Event();
|
||||||
//void IRAM_ATTR setRxEvent() { rxFlag = true; }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
int32_t threadMain(const Modulation modulation) override;
|
|
||||||
};
|
};
|
||||||
|
|||||||
@ -2,8 +2,6 @@
|
|||||||
|
|
||||||
#include "../Device.h"
|
#include "../Device.h"
|
||||||
|
|
||||||
#include <Tactility/EventFlag.h>
|
|
||||||
#include <Tactility/Lock.h>
|
|
||||||
#include <Tactility/Mutex.h>
|
#include <Tactility/Mutex.h>
|
||||||
#include <Tactility/Thread.h>
|
#include <Tactility/Thread.h>
|
||||||
|
|
||||||
@ -80,31 +78,19 @@ private:
|
|||||||
std::shared_ptr<std::function<void(Device::Id id, const RxPacket&)>> onData;
|
std::shared_ptr<std::function<void(Device::Id id, const RxPacket&)>> onData;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::string threadName;
|
|
||||||
size_t threadSize;
|
|
||||||
State state;
|
State state;
|
||||||
EventFlag events;
|
|
||||||
Mutex mutex = Mutex(Mutex::Type::Recursive);
|
Mutex mutex = Mutex(Mutex::Type::Recursive);
|
||||||
std::unique_ptr<Thread> _Nullable thread;
|
|
||||||
bool threadInterrupted = false;
|
|
||||||
std::vector<RxSubscription> rxSubscriptions;
|
std::vector<RxSubscription> rxSubscriptions;
|
||||||
std::deque<TxItem> txQueue;
|
std::deque<TxItem> txQueue;
|
||||||
TxId lastTxId = 0;
|
TxId lastTxId = 0;
|
||||||
RxSubscriptionId lastRxSubscriptionId = 0;
|
RxSubscriptionId lastRxSubscriptionId = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
const Mutex &getMutex() const { return mutex; }
|
||||||
static constexpr auto RADIO_TERMINATE_BIT = BIT0;
|
|
||||||
static constexpr auto RADIO_TRANSMIT_QUEUED_BIT = BIT1;
|
|
||||||
static constexpr auto RADIO_RECEIVED_BIT = BIT2;
|
|
||||||
static constexpr auto RADIO_TRANSMITTED_BIT = BIT3;
|
|
||||||
|
|
||||||
virtual int32_t threadMain(const Modulation modulation) = 0;
|
|
||||||
Mutex &getMutex() { return mutex; }
|
|
||||||
EventFlag &getEventFlag() { return events; }
|
|
||||||
bool isThreadInterrupted() const;
|
|
||||||
void setState(State newState);
|
void setState(State newState);
|
||||||
|
|
||||||
|
virtual void txQueuedSignal() = 0;
|
||||||
|
|
||||||
size_t getTxQueueSize() const {
|
size_t getTxQueueSize() const {
|
||||||
auto lock = mutex.asScopedLock();
|
auto lock = mutex.asScopedLock();
|
||||||
lock.lock();
|
lock.lock();
|
||||||
@ -125,10 +111,8 @@ protected:
|
|||||||
void publishRx(const RxPacket& packet);
|
void publishRx(const RxPacket& packet);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit RadioDevice(const std::string& threadName, const size_t threadSize)
|
explicit RadioDevice()
|
||||||
: threadName(threadName)
|
: state(State::Off) {}
|
||||||
, threadSize(threadSize)
|
|
||||||
, state(State::Off) {}
|
|
||||||
|
|
||||||
~RadioDevice() override = default;
|
~RadioDevice() override = default;
|
||||||
|
|
||||||
@ -137,8 +121,8 @@ public:
|
|||||||
virtual bool configure(const Parameter parameter, const float value) = 0;
|
virtual bool configure(const Parameter parameter, const float value) = 0;
|
||||||
virtual bool isCapableOf(const Modulation modulation) = 0;
|
virtual bool isCapableOf(const Modulation modulation) = 0;
|
||||||
|
|
||||||
bool start(const Modulation modulation);
|
virtual bool start(const Modulation modulation) = 0;
|
||||||
bool stop();
|
virtual bool stop() = 0;
|
||||||
|
|
||||||
TxId transmit(const TxPacket& packet, TxStateCallback callback) {
|
TxId transmit(const TxPacket& packet, TxStateCallback callback) {
|
||||||
auto lock = mutex.asScopedLock();
|
auto lock = mutex.asScopedLock();
|
||||||
@ -147,7 +131,7 @@ public:
|
|||||||
txQueue.push_back(TxItem{.id = txId, .packet = packet, .callback = callback});
|
txQueue.push_back(TxItem{.id = txId, .packet = packet, .callback = callback});
|
||||||
callback(txId, TransmissionState::Queued);
|
callback(txId, TransmissionState::Queued);
|
||||||
lastTxId++;
|
lastTxId++;
|
||||||
getEventFlag().set(RADIO_TRANSMIT_QUEUED_BIT);
|
txQueuedSignal();
|
||||||
return txId;
|
return txId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -60,6 +60,7 @@ namespace app {
|
|||||||
namespace boot { extern const AppManifest manifest; }
|
namespace boot { extern const AppManifest manifest; }
|
||||||
namespace calculator { extern const AppManifest manifest; }
|
namespace calculator { extern const AppManifest manifest; }
|
||||||
namespace chat { extern const AppManifest manifest; }
|
namespace chat { extern const AppManifest manifest; }
|
||||||
|
namespace chirp { extern const AppManifest manifest; }
|
||||||
namespace development { extern const AppManifest manifest; }
|
namespace development { extern const AppManifest manifest; }
|
||||||
namespace display { extern const AppManifest manifest; }
|
namespace display { extern const AppManifest manifest; }
|
||||||
namespace files { extern const AppManifest manifest; }
|
namespace files { extern const AppManifest manifest; }
|
||||||
@ -121,6 +122,7 @@ static void registerSystemApps() {
|
|||||||
addApp(app::wifiapsettings::manifest);
|
addApp(app::wifiapsettings::manifest);
|
||||||
addApp(app::wificonnect::manifest);
|
addApp(app::wificonnect::manifest);
|
||||||
addApp(app::wifimanage::manifest);
|
addApp(app::wifimanage::manifest);
|
||||||
|
addApp(app::chirp::manifest);
|
||||||
|
|
||||||
#if defined(CONFIG_TINYUSB_MSC_ENABLED) && CONFIG_TINYUSB_MSC_ENABLED
|
#if defined(CONFIG_TINYUSB_MSC_ENABLED) && CONFIG_TINYUSB_MSC_ENABLED
|
||||||
addApp(app::usbsettings::manifest);
|
addApp(app::usbsettings::manifest);
|
||||||
|
|||||||
@ -5,74 +5,6 @@ namespace tt::hal::radio {
|
|||||||
|
|
||||||
constexpr const char* TAG = "RadioDevice";
|
constexpr const char* TAG = "RadioDevice";
|
||||||
|
|
||||||
bool RadioDevice::start(const Modulation modulation) {
|
|
||||||
auto lock = mutex.asScopedLock();
|
|
||||||
|
|
||||||
if (!isCapableOf(modulation)) {
|
|
||||||
TT_LOG_E(TAG, "Can't start device \"%s\", not capable of modulation \"%s\"", getName().c_str(), toString(modulation));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
lock.lock();
|
|
||||||
|
|
||||||
if (thread != nullptr && thread->getState() != Thread::State::Stopped) {
|
|
||||||
TT_LOG_W(TAG, "Already started");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
threadInterrupted = false;
|
|
||||||
|
|
||||||
TT_LOG_I(TAG, "Starting thread");
|
|
||||||
setState(State::PendingOn);
|
|
||||||
|
|
||||||
thread = std::make_unique<Thread>(
|
|
||||||
threadName,
|
|
||||||
threadSize,
|
|
||||||
[this, modulation]() {
|
|
||||||
return this->threadMain(modulation);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
thread->setPriority(tt::Thread::Priority::High);
|
|
||||||
thread->start();
|
|
||||||
|
|
||||||
TT_LOG_I(TAG, "Starting finished");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool RadioDevice::stop() {
|
|
||||||
auto lock = mutex.asScopedLock();
|
|
||||||
lock.lock();
|
|
||||||
|
|
||||||
setState(State::PendingOff);
|
|
||||||
|
|
||||||
if (thread != nullptr) {
|
|
||||||
threadInterrupted = true;
|
|
||||||
getEventFlag().set(RADIO_TERMINATE_BIT);
|
|
||||||
|
|
||||||
// Detach thread, it will auto-delete when leaving the current scope
|
|
||||||
auto old_thread = std::move(thread);
|
|
||||||
|
|
||||||
if (old_thread->getState() != Thread::State::Stopped) {
|
|
||||||
// Unlock so thread can lock
|
|
||||||
lock.unlock();
|
|
||||||
// Wait for thread to finish
|
|
||||||
old_thread->join();
|
|
||||||
// Re-lock to continue logic below
|
|
||||||
lock.lock();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
setState(State::Off);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool RadioDevice::isThreadInterrupted() const {
|
|
||||||
auto lock = mutex.asScopedLock();
|
|
||||||
lock.lock();
|
|
||||||
return threadInterrupted;
|
|
||||||
}
|
|
||||||
|
|
||||||
RadioDevice::State RadioDevice::getState() const {
|
RadioDevice::State RadioDevice::getState() const {
|
||||||
auto lock = mutex.asScopedLock();
|
auto lock = mutex.asScopedLock();
|
||||||
lock.lock();
|
lock.lock();
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user