Tactiliest/Tactility/Source/hal/radio/RadioDevice.cpp

139 lines
3.5 KiB
C++

#include "Tactility/hal/radio/RadioDevice.h"
#include <cstring>
namespace tt::hal::radio {
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 {
auto lock = mutex.asScopedLock();
lock.lock();
return state; // Make copy because of thread safety
}
void RadioDevice::setState(State newState) {
auto lock = mutex.asScopedLock();
lock.lock();
state = newState;
}
void RadioDevice::publishRx(const RxPacket& packet) {
mutex.lock();
for (auto& subscription : rxSubscriptions) {
(*subscription.onData)(getId(), packet);
}
mutex.unlock();
}
const char* toString(RadioDevice::Modulation modulation) {
using enum RadioDevice::Modulation;
switch (modulation) {
case Fsk:
return "FSK";
case LoRa:
return "LoRa";
case LrFhss:
return "LR-FHSS";
default:
return "Unkown";
}
}
const char* toString(RadioDevice::Parameter parameter) {
using enum RadioDevice::Parameter;
switch (parameter) {
case Power:
return TT_STRINGIFY(Power);
case Frequency:
return TT_STRINGIFY(Frequency);
case Bandwidth:
return TT_STRINGIFY(Bandwidth);
case SpreadFactor:
return TT_STRINGIFY(SpreadFactor);
case CodingRate:
return TT_STRINGIFY(CodingRate);
case SyncWord:
return TT_STRINGIFY(SyncWord);
case PreambleLength:
return TT_STRINGIFY(PreambleLength);
case FrequencyDeviation:
return TT_STRINGIFY(FrequencyDeviation);
case DataRate:
return TT_STRINGIFY(DataRate);
case AddressWidth:
return TT_STRINGIFY(AddressWidth);
default:
return "Unknown";
}
}
} // namespace tt::hal::radio