Compare commits

..

No commits in common. "8473c178e648fe1bfc37de56ef3f4a9731f6429a" and "cbfc7305f3b3baea351f3ca744be8a1265ac8f57" have entirely different histories.

13 changed files with 88 additions and 422 deletions

View File

@ -24,7 +24,7 @@ DeviceVector createDevices() {
auto tca8418 = std::make_shared<Tca8418>(I2C_NUM_0);
auto keyboard = std::make_shared<TpagerKeyboard>(tca8418);
auto sx1262 = std::make_shared<Sx1262>(Sx1262::Configuration{
auto sx1262 = std::make_shared<Sx1262>("SX1262", Sx1262::Configuration{
.spiHostDevice = SPI2_HOST,
.spiFrequency = 10'000'000,
.csPin = GPIO_NUM_36,

View File

@ -54,16 +54,11 @@ void RadiolibTactilityHal::attachInterrupt(uint32_t interruptNum, void (*interru
return;
}
if (!isrServiceInitialized) {
gpio_install_isr_service((int)ESP_INTR_FLAG_IRAM);
isrServiceInitialized = true;
}
gpio_install_isr_service((int)ESP_INTR_FLAG_IRAM);
gpio_set_intr_type((gpio_num_t)interruptNum, (gpio_int_type_t)(mode & 0x7));
// this uses function typecasting, which is not defined when the functions have different signatures
// untested and might not work
// TODO: I think the wisest course of action is forbidding registration via RadioLib entirely,
// as it doesn't suit Tactility with its lack of context passing
gpio_isr_handler_add((gpio_num_t)interruptNum, (void (*)(void*))interruptCb, NULL);
}

View File

@ -21,10 +21,9 @@ private:
spi_device_handle_t spiDeviceHandle;
std::shared_ptr<tt::Lock> lock;
bool spiInitialized;
bool isrServiceInitialized;
public:
explicit RadiolibTactilityHal(spi_host_device_t spiHostDevice, int spiFrequency, gpio_num_t csPin)
explicit RadiolibTactilityHal(spi_host_device_t spiHostDevice, int spiFrequency, gpio_num_t csPin, std::shared_ptr<tt::Lock> spiLock)
: RadioLibHal(
GPIO_MODE_INPUT,
GPIO_MODE_OUTPUT,
@ -35,9 +34,10 @@ public:
, spiHostDevice(spiHostDevice)
, spiFrequency(spiFrequency)
, csPin(csPin)
, lock(tt::hal::spi::getLock(spiHostDevice))
, spiInitialized(false)
, isrServiceInitialized(false) {}
, lock(spiLock)
, spiInitialized(false) {
if (!lock) lock = tt::hal::spi::getLock(spiHostDevice);
}
void init() override;
void term() override;

View File

@ -3,8 +3,14 @@
constexpr const char* TAG = "RadiolibThreadedDevice";
bool RadiolibThreadedDevice::start() {
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)) {
@ -20,8 +26,8 @@ bool RadiolibThreadedDevice::start() {
thread = std::make_unique<tt::Thread>(
threadName,
threadSize,
[this]() {
return this->threadMain();
[this, modulation]() {
return this->threadMain(modulation);
}
);
thread->setPriority(tt::Thread::Priority::High);
@ -65,9 +71,9 @@ bool RadiolibThreadedDevice::isThreadInterrupted() const {
return threadInterrupted;
}
int32_t RadiolibThreadedDevice::threadMain() {
int32_t RadiolibThreadedDevice::threadMain(const Modulation modulation) {
int rc = doBegin(getModulation());
int rc = doBegin(modulation);
if (rc != 0) {
return rc;
}

View File

@ -12,7 +12,7 @@ private:
bool threadInterrupted = false;
protected:
virtual int32_t threadMain();
virtual int32_t threadMain(const Modulation modulation);
bool isThreadInterrupted() const;
virtual void interruptSignal() = 0;
@ -31,6 +31,7 @@ public:
~RadiolibThreadedDevice() override = default;
virtual bool start() override;
virtual bool start(const Modulation modulation) override;
virtual bool stop() override;
};

View File

@ -5,266 +5,94 @@
constexpr const char* TAG = "Sx1262";
template<typename T>
static constexpr Sx1262::ParameterStatus checkLimitsAndApply(T &target, const float value, const float lower, const float upper, const unsigned step = 0) {
if ((value >= lower) && (value <= upper)) {
if (step != 0) {
int ivalue = static_cast<int>(value);
if ((ivalue % step) != 0) {
return Sx1262::ParameterStatus::ValueError;
}
}
target = static_cast<T>(value);
return Sx1262::ParameterStatus::Success;
}
return Sx1262::ParameterStatus::ValueError;
}
template<typename T>
static constexpr Sx1262::ParameterStatus checkValuesAndApply(T &target, const float value, std::initializer_list<float> valids) {
for (float valid : valids) {
if (value == valid) {
target = static_cast<T>(value);
return Sx1262::ParameterStatus::Success;
}
}
return Sx1262::ParameterStatus::ValueError;
}
void IRAM_ATTR dio1handler(void* context) {
((Sx1262*)context)->dio1Event();
}
Sx1262::ParameterStatus Sx1262::setLoraParameter(const Parameter parameter, const float value) {
bool Sx1262::setParameter(const Parameter parameter, const float value) {
using enum Parameter;
switch (parameter) {
case Power:
return checkLimitsAndApply(power, value, -9.0, 22.0);
power = value;
return true;
case Frequency:
return checkLimitsAndApply(frequency, value, 150.0, 960.0);
frequency = value;
return true;
case Bandwidth:
return checkValuesAndApply(bandwidth, value, {
7.8, 10.4, 15.6, 20.8, 31.25, 41.7, 62.5, 125.0, 250.0, 500.0
});
bandwidth = value;
return true;
case SpreadFactor:
return checkLimitsAndApply(spreadFactor, value, 7.0, 12.0, 1);
spreadFactor = value;
return true;
case CodingRate:
return checkLimitsAndApply(codingRate, value, 5.0, 8.0, 1);
codingRate = value;
return true;
case SyncWord:
return checkLimitsAndApply(syncWord, value, 0.0, 255.0, 1);
syncWord = value;
return true;
case PreambleLength:
return checkLimitsAndApply(preambleLength, value, 0.0, 65535.0, 1);
default:
break;
}
TT_LOG_W(TAG, "Tried to set unsupported LoRa parameter \"%s\" to %f", toString(parameter), value);
return Sx1262::ParameterStatus::Unavailable;
}
Sx1262::ParameterStatus Sx1262::setFskParameter(const Parameter parameter, const float value) {
using enum Parameter;
switch (parameter) {
case Power:
return checkLimitsAndApply(power, value, -9.0, 22.0);
case Frequency:
return checkLimitsAndApply(frequency, value, 150.0, 960.0);
case Bandwidth:
return checkValuesAndApply(bandwidth, value, {
4.8, 5.8, 7.3, 9.7, 11.7, 14.6, 19.5, 23.4, 29.3, 39.0, 46.9, 58.6, 78.2
});
case PreambleLength:
return checkLimitsAndApply(preambleLength, value, 0.0, 65535.0, 1);
preambleLength = value;
return true;
case DataRate:
return checkLimitsAndApply(bitRate, value, 0.6, 300.0);
bitRate = value;
return true;
case FrequencyDeviation:
return checkLimitsAndApply(frequencyDeviation, value, 0.0, 200.0);
default:
break;
}
TT_LOG_W(TAG, "Tried to set unsupported FSK parameter \"%s\" to %f", toString(parameter), value);
return Sx1262::ParameterStatus::Unavailable;
}
Sx1262::ParameterStatus Sx1262::setLrFhssParameter(const Parameter parameter, const float value) {
using enum Parameter;
switch (parameter) {
case Bandwidth:
return checkValuesAndApply(bandwidth, value, {
39.06, 85.94, 136.72, 183.59, 335.94, 386.72, 722.66, 773.44, 1523.4, 1574.2
});
case CodingRate:
return checkValuesAndApply(codingRate, value, {
RADIOLIB_SX126X_LR_FHSS_CR_5_6,
RADIOLIB_SX126X_LR_FHSS_CR_2_3,
RADIOLIB_SX126X_LR_FHSS_CR_1_2,
RADIOLIB_SX126X_LR_FHSS_CR_1_3
});
frequencyDeviation = value;
return true;
case NarrowGrid:
return checkLimitsAndApply(narrowGrid, value, 0.0, 1.0, 1);
narrowGrid = value;
return true;
default:
break;
}
TT_LOG_W(TAG, "Tried to set unsupported LR-FHSS parameter \"%s\" to %f", toString(parameter), value);
return Sx1262::ParameterStatus::Unavailable;
TT_LOG_W(TAG, "Tried to set unsupported parameter \"%s\" to %f", toString(parameter), value);
return false;
}
Sx1262::ParameterStatus Sx1262::setParameter(const Parameter parameter, const float value) {
const auto currentModulation = getModulation();
switch (currentModulation) {
case Modulation::LoRa:
return setLoraParameter(parameter, value);
case Modulation::Fsk:
return setFskParameter(parameter, value);
case Modulation::LrFhss:
return setLrFhssParameter(parameter, value);
default:
break;
}
// Shouldn't be reachable, return failsafe value
return Sx1262::ParameterStatus::Unavailable;
}
Sx1262::ParameterStatus Sx1262::getLoraParameter(const Parameter parameter, float &value) const {
bool Sx1262::getParameter(const Parameter parameter, float &value) const {
using enum Parameter;
switch (parameter) {
case Power:
value = power;
return Sx1262::ParameterStatus::Success;
return true;
case Frequency:
value = frequency;
return Sx1262::ParameterStatus::Success;
return true;
case Bandwidth:
value = bandwidth;
return Sx1262::ParameterStatus::Success;
return true;
case SpreadFactor:
value = spreadFactor;
return Sx1262::ParameterStatus::Success;
return true;
case CodingRate:
value = codingRate;
return Sx1262::ParameterStatus::Success;
return true;
case SyncWord:
value = syncWord;
return Sx1262::ParameterStatus::Success;
return true;
case PreambleLength:
value = preambleLength;
return Sx1262::ParameterStatus::Success;
default:
break;
}
TT_LOG_W(TAG, "Tried to get unsupported LoRa parameter \"%s\"", toString(parameter));
return Sx1262::ParameterStatus::Unavailable;
}
Sx1262::ParameterStatus Sx1262::getFskParameter(const Parameter parameter, float &value) const {
using enum Parameter;
switch (parameter) {
case Power:
value = power;
return Sx1262::ParameterStatus::Success;
case Frequency:
value = frequency;
return Sx1262::ParameterStatus::Success;
case Bandwidth:
value = bandwidth;
return Sx1262::ParameterStatus::Success;
return true;
case DataRate:
value = bitRate;
return Sx1262::ParameterStatus::Success;
return true;
case FrequencyDeviation:
value = frequencyDeviation;
return Sx1262::ParameterStatus::Success;
default:
break;
}
TT_LOG_W(TAG, "Tried to get unsupported FSK parameter \"%s\"", toString(parameter));
return Sx1262::ParameterStatus::Unavailable;
}
Sx1262::ParameterStatus Sx1262::getLrFhssParameter(const Parameter parameter, float &value) const {
using enum Parameter;
switch (parameter) {
case Power:
value = power;
return Sx1262::ParameterStatus::Success;
case Bandwidth:
value = bandwidth;
return Sx1262::ParameterStatus::Success;
case CodingRate:
value = codingRate;
return Sx1262::ParameterStatus::Success;
return true;
case NarrowGrid:
value = narrowGrid;
return Sx1262::ParameterStatus::Success;
return true;
default:
break;
}
TT_LOG_W(TAG, "Tried to get unsupported LR-FHSS parameter \"%s\"", toString(parameter));
return Sx1262::ParameterStatus::Unavailable;
}
TT_LOG_W(TAG, "Tried to get unsupported parameter \"%s\"", toString(parameter));
Sx1262::ParameterStatus Sx1262::getParameter(const Parameter parameter, float &value) const {
const auto currentModulation = getModulation();
switch (currentModulation) {
case Modulation::LoRa:
return getLoraParameter(parameter, value);
case Modulation::Fsk:
return getFskParameter(parameter, value);
case Modulation::LrFhss:
return getLrFhssParameter(parameter, value);
default:
break;
}
// Shouldn't be reachable, return failsafe value
return Sx1262::ParameterStatus::Unavailable;
}
tt::hal::radio::Unit Sx1262::getParameterUnit(const Parameter parameter) const {
using enum Parameter;
using Unit = tt::hal::radio::Unit;
switch (parameter) {
case Power:
return Unit(Unit::Name::DecibelMilliwatts);
case Frequency:
return Unit(Unit::Prefix::Mega, Unit::Name::Herz);
case Bandwidth:
return Unit(Unit::Prefix::Kilo, Unit::Name::Herz);
case SpreadFactor:
case CodingRate: // no break
case SyncWord: // no break
case PreambleLength: // no break
return Unit(Unit::Name::None);
case DataRate:
return Unit(Unit::Prefix::Kilo, Unit::Name::BitsPerSecond);
case FrequencyDeviation:
return Unit(Unit::Prefix::Kilo, Unit::Name::Herz);
case NarrowGrid:
return Unit(Unit::Name::None);
default:
break;
}
TT_LOG_W(TAG, "Tried to get unit for unsupported parameter \"%s\"", toString(parameter));
return Unit(Unit::Name::None);
return false;
}
void Sx1262::registerDio1Isr() {
@ -353,6 +181,7 @@ int Sx1262::doBegin(const Modulation modulation) {
return -1;
}
currentModem = modulation;
registerDio1Isr();
return 0;
}
@ -369,18 +198,11 @@ void Sx1262::doTransmit() {
TT_LOG_W(TAG, "RadioLib returned %hi on standby", rc);
}
if (getModulation() == Modulation::Fsk) {
rc = radio.startTransmit(currentTx.packet.data.data(), currentTx.packet.data.size(),
currentTx.packet.address);
} else {
rc = radio.startTransmit(currentTx.packet.data.data(), currentTx.packet.data.size());
}
rc = radio.startTransmit(currentTx.packet.data.data(), currentTx.packet.data.size());
if (rc == RADIOLIB_ERR_NONE) {
currentTx.callback(currentTx.id, TransmissionState::PendingTransmit);
auto txEventFlags = events.wait(SX1262_INTERRUPT_BIT | SX1262_DIO1_EVENT_BIT, tt::EventFlag::WaitAny,
pdMS_TO_TICKS(SX1262_TX_TIMEOUT_MILLIS));
auto txEventFlags = events.wait(SX1262_INTERRUPT_BIT | SX1262_DIO1_EVENT_BIT, tt::EventFlag::WaitAny, pdMS_TO_TICKS(2000));
// Thread might've been interrupted in the meanwhile
if (isThreadInterrupted()) {
@ -401,7 +223,7 @@ void Sx1262::doTransmit() {
}
void Sx1262::doListen() {
if (getModulation() != Modulation::LrFhss) {
if (currentModem != Modulation::LrFhss) {
radio.startReceive();
events.wait(SX1262_INTERRUPT_BIT | SX1262_DIO1_EVENT_BIT | SX1262_QUEUED_TX_BIT);
} else {
@ -412,7 +234,7 @@ void Sx1262::doListen() {
void Sx1262::doReceive() {
// LR-FHSS modem only supports TX
if (getModulation() == Modulation::LrFhss) return;
if (currentModem == Modulation::LrFhss) return;
uint16_t rxSize = radio.getPacketLength(true);
std::vector<uint8_t> data(rxSize);

View File

@ -25,9 +25,7 @@ public:
};
private:
static constexpr auto SX1262_DEFAULT_NAME = "SX1262";
static constexpr auto SX1262_COOLDOWN_MILLIS = 100;
static constexpr auto SX1262_TX_TIMEOUT_MILLIS = 2000;
static constexpr auto SX1262_INTERRUPT_BIT = BIT0;
static constexpr auto SX1262_DIO1_EVENT_BIT = BIT1;
static constexpr auto SX1262_QUEUED_TX_BIT = BIT2;
@ -40,6 +38,7 @@ private:
Module radioModule;
SX1262 radio;
TxItem currentTx;
Modulation currentModem;
int8_t power = 0;
float frequency = 0.0;
@ -55,14 +54,6 @@ private:
void registerDio1Isr();
void unregisterDio1Isr();
ParameterStatus setLoraParameter(const Parameter parameter, const float value);
ParameterStatus setFskParameter(const Parameter parameter, const float value);
ParameterStatus setLrFhssParameter(const Parameter parameter, const float value);
ParameterStatus getLoraParameter(const Parameter parameter, float &value) const;
ParameterStatus getFskParameter(const Parameter parameter, float &value) const;
ParameterStatus getLrFhssParameter(const Parameter parameter, float &value) const;
protected:
virtual void txQueuedSignal() override;
virtual void interruptSignal() override;
@ -75,23 +66,24 @@ protected:
public:
explicit Sx1262(const Configuration& configuration, const std::string& name = SX1262_DEFAULT_NAME)
explicit Sx1262(const std::string& name, const Configuration& configuration, std::shared_ptr<tt::Lock> lock = nullptr)
: RadiolibThreadedDevice(name, 4096)
, name(name)
, configuration(configuration)
, hal(configuration.spiHostDevice, configuration.spiFrequency, configuration.csPin)
, hal(configuration.spiHostDevice, configuration.spiFrequency, configuration.csPin, lock)
, radioModule(&hal, configuration.csPin, configuration.irqPin, configuration.resetPin, configuration.busyPin)
, radio(&radioModule)
, currentModem(Modulation::None)
{}
~Sx1262() override = default;
std::string getName() const override { return name; }
std::string getDescription() const override { return "Semtech SX1262 LoRa, FSK and LR-FHSS capable radio"; }
ParameterStatus setParameter(const Parameter parameter, const float value) override;
ParameterStatus getParameter(const Parameter parameter, float &value) const override;
tt::hal::radio::Unit getParameterUnit(const Parameter parameter) const override;
bool setParameter(const Parameter parameter, const float value) override;
bool getParameter(const Parameter parameter, float &value) const override;
bool canTransmit(const Modulation modulation) override {
return (modulation == Modulation::Fsk) ||

View File

@ -34,29 +34,23 @@ public:
}
return false;
}
void clear() { parameters.clear(); }
bool apply(RadioDevice &radio) {
bool successful = true;
for (const auto& [parameter, value] : parameters) {
// No break on error chosen to apply all parameters,
// a bad one doesn't make the successive tries any more invalid
successful &= (radio.setParameter(parameter, value) == RadioDevice::ParameterStatus::Success);
successful &= radio.setParameter(parameter, value);
}
return successful;
}
void load(const RadioDevice &radio) {
// This loop has to be ajusted for each new parameter.
// Could be made more maintainable with a template enum iterator in an utility header.
for (RadioDevice::Parameter p = RadioDevice::Parameter::Power;
p < RadioDevice::Parameter::NarrowGrid;
p = static_cast<RadioDevice::Parameter>((size_t)p + 1)) {
float value = 0.0;
if (radio.getParameter(p, value) == RadioDevice::ParameterStatus::Success) {
set(p, value);
}
bool load(const RadioDevice &radio) {
bool successful = true;
for (const auto& [parameter, value] : parameters) {
successful &= radio.getParameter(parameter, parameters[parameter]);
}
return successful;
}
};

View File

@ -1,7 +1,6 @@
#pragma once
#include "../Device.h"
#include "Unit.h"
#include <Tactility/Mutex.h>
#include <Tactility/Thread.h>
@ -46,12 +45,6 @@ public:
NarrowGrid
};
enum class ParameterStatus {
Unavailable,
ValueError,
Success
};
typedef int RxSubscriptionId;
typedef int TxId;
@ -88,7 +81,6 @@ private:
};
State state;
Modulation modulation;
Mutex mutex = Mutex(Mutex::Type::Recursive);
std::vector<RxSubscription> rxSubscriptions;
std::deque<TxItem> txQueue;
@ -122,21 +114,18 @@ protected:
public:
explicit RadioDevice()
: state(State::Off), modulation(Modulation::None) {}
: state(State::Off) {}
~RadioDevice() override = default;
Type getType() const override { return Type::Radio; }
bool setModulation(const Modulation newModulation);
Modulation getModulation() const;
virtual ParameterStatus setParameter(const Parameter parameter, const float value) = 0;
virtual ParameterStatus getParameter(const Parameter parameter, float &value) const = 0;
virtual Unit getParameterUnit(const Parameter parameter) const = 0;
virtual bool setParameter(const Parameter parameter, const float value) = 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() = 0;
virtual bool start(const Modulation modulation) = 0;
virtual bool stop() = 0;
TxId transmit(const TxPacket& packet, TxStateCallback callback) {

View File

@ -1,46 +0,0 @@
#pragma once
#include <string>
namespace tt::hal::radio {
class Unit {
public:
enum class Prefix {
Femto,
Pico,
Nano,
Milli,
None,
Kilo,
Mega,
Giga,
Terra,
Peta
};
enum class Name
{
None,
BitsPerSecond,
BytesPerSecond,
Herz,
Decibel,
DecibelMilliwatts
};
const Prefix prefix;
const Name unit;
explicit Unit(const Prefix si, const Name unit)
: prefix(si), unit(unit) {}
explicit Unit(const Name unit)
: prefix(Prefix::None), unit(unit) {}
std::string toString() const;
};
const char* toString(Unit::Prefix prefix);
const char* toString(Unit::Name unit);
}

View File

@ -428,18 +428,17 @@ public:
void configureFromForm() {
using enum tt::hal::radio::RadioDevice::Parameter;
using enum tt::hal::radio::RadioDevice::ParameterStatus;
std::string buffer;
int value = 0;
bool configured = true;
buffer = lv_textarea_get_text(frequencyInput);
if (!buffer.empty()) {
configured &= (loraDevice->setParameter(Frequency, std::stof(buffer)) == Success);
configured &= loraDevice->setParameter(Frequency, std::stof(buffer));
}
buffer = lv_textarea_get_text(bandwidthInput);
if (!buffer.empty()) {
configured &= (loraDevice->setParameter(Bandwidth, std::stof(buffer)) == Success);
configured &= loraDevice->setParameter(Bandwidth, std::stof(buffer));
}
buffer = lv_textarea_get_text(syncwordInput);
if (!buffer.empty()) {
@ -447,20 +446,20 @@ public:
std::stringstream ss(buffer);
ss >> std::hex >> syncWord;
configured &= (loraDevice->setParameter(SyncWord, std::stoi(buffer, nullptr, 16)) == Success);
configured &= loraDevice->setParameter(SyncWord, std::stoi(buffer, nullptr, 16));
}
value = lv_slider_get_value(deBitsInput);
configured &= (loraDevice->setParameter(CodingRate, value) == Success);
configured &= loraDevice->setParameter(CodingRate, value);
value = lv_slider_get_value(sfInput);
configured &= (loraDevice->setParameter(SpreadFactor, value) == Success);
configured &= loraDevice->setParameter(SpreadFactor, value);
value = lv_slider_get_value(preambleChirpsInput);
configured &= (loraDevice->setParameter(PreambleLength, value) == Success);
configured &= loraDevice->setParameter(PreambleLength, value);
buffer = lv_textarea_get_text(txPowInput);
if (!buffer.empty()) {
configured &= (loraDevice->setParameter(Power, std::stof(buffer)) == Success);
configured &= loraDevice->setParameter(Power, std::stof(buffer));
}
}
@ -469,9 +468,8 @@ public:
loraDevice = loraDevs[lv_dropdown_get_selected(loraDeviceInput)];
if (loraDevice) {
disableForm();
loraDevice->setModulation(tt::hal::radio::RadioDevice::Modulation::LoRa);
configureFromForm();
loraDevice->start();
loraDevice->start(tt::hal::radio::RadioDevice::Modulation::LoRa);
vTaskDelay(pdMS_TO_TICKS(500));
if (loraDevice->getState() != tt::hal::radio::RadioDevice::State::On) {
lv_obj_clear_state(loraDeviceOn, LV_STATE_CHECKED);

View File

@ -5,31 +5,6 @@ namespace tt::hal::radio {
constexpr const char* TAG = "RadioDevice";
bool RadioDevice::setModulation(const RadioDevice::Modulation newModulation) {
// A bool is chosen over an enum class because:
// - this is not tied to user input and
// - the programmer can infer why it didn't work using
// other methods such as getState() and canTransmit/Receive()
const auto state = getState();
if ((state == State::PendingOn) || (state == State::On)) {
return false;
} else if (!(canTransmit(newModulation) || canReceive(newModulation))) {
return false;
} else {
auto lock = mutex.asScopedLock();
lock.lock();
modulation = newModulation;
}
return true;
}
RadioDevice::Modulation RadioDevice::getModulation() const {
auto lock = mutex.asScopedLock();
lock.lock();
return modulation;
}
RadioDevice::State RadioDevice::getState() const {
auto lock = mutex.asScopedLock();
lock.lock();

View File

@ -1,60 +0,0 @@
#include "Tactility/hal/radio/Unit.h"
#include <cstring>
namespace tt::hal::radio {
std::string Unit::toString() const {
return std::string(toString(prefix))+std::string(toString(unit));
}
const char* toString(Unit::Prefix prefix) {
using enum Unit::Prefix;
switch (prefix) {
case Femto:
return "f";
case Pico:
return "p";
case Nano:
return "n";
case Milli:
return "m";
case None:
return "";
case Kilo:
return "k";
case Mega:
return "M";
case Giga:
return "G";
case Terra:
return "T";
case Peta:
return "P";
}
return "?";
}
const char* toString(Unit::Name unit) {
using enum Unit::Name;
switch (unit) {
case None:
return "";
case BitsPerSecond:
return "bps";
case BytesPerSecond:
return "Bps";
case Herz:
return "Hz";
case Decibel:
return "dB";
case DecibelMilliwatts:
return "dBm";
}
return "?";
}
}