#include "Tactility/hal/radio/RadioDevice.h" #include 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( 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"; 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