Tactiliest/Drivers/RadioLibCompat/Source/RadiolibThreadedDevice.cpp

100 lines
2.3 KiB
C++

#include "RadiolibThreadedDevice.h"
#include <cstring>
constexpr const char* TAG = "RadiolibThreadedDevice";
bool RadiolibThreadedDevice::start(const Modulation modulation) {
auto lock = getMutex().asScopedLock();
if (!canTransmit(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;
}