LoraApi callbacks refactored to events (#632)
This commit is contained in:
committed by
GitHub
parent
b7577f2328
commit
d2442bedb4
@@ -8,7 +8,6 @@
|
||||
#include <tactility/drivers/gpio_controller.h>
|
||||
#include <tactility/log.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <initializer_list>
|
||||
|
||||
#include <RadioLib.h>
|
||||
@@ -345,12 +344,9 @@ void Sx1262Radio::setState(enum LoraRadioState newState) {
|
||||
}
|
||||
LOG_I(TAG, "State: %s -> %s", toString(state), toString(newState));
|
||||
state = newState;
|
||||
auto callbacks = stateCallbacks;
|
||||
unlock();
|
||||
|
||||
for (const auto& entry : callbacks) {
|
||||
entry.callback(settings.device, entry.context, newState);
|
||||
}
|
||||
lora_state_event_emit(settings.device, newState);
|
||||
}
|
||||
|
||||
error_t Sx1262Radio::setModulation(enum LoraModulation newModulation) {
|
||||
@@ -377,76 +373,12 @@ enum LoraModulation Sx1262Radio::getModulation() const {
|
||||
return result;
|
||||
}
|
||||
|
||||
// Callbacks are invoked on a snapshot of the list, with the radio mutex released:
|
||||
// consumers take their own locks in callbacks and also call into this API while
|
||||
// holding those locks, so invoking under the radio mutex would set up an AB-BA
|
||||
// deadlock between the radio thread and any consumer thread.
|
||||
void Sx1262Radio::publishRx(const struct LoraRxPacket& packet) {
|
||||
lock();
|
||||
auto callbacks = rxCallbacks;
|
||||
unlock();
|
||||
|
||||
for (const auto& entry : callbacks) {
|
||||
entry.callback(settings.device, entry.context, &packet);
|
||||
}
|
||||
error_t Sx1262Radio::publishRx(const uint8_t* data, size_t length, float rssi, float snr) {
|
||||
return lora_rx_event_emit(settings.device, data, length, rssi, snr);
|
||||
}
|
||||
|
||||
void Sx1262Radio::publishTx(LoraTxId id, enum LoraTransmissionState txState) {
|
||||
lock();
|
||||
auto callbacks = txCallbacks;
|
||||
unlock();
|
||||
|
||||
for (const auto& entry : callbacks) {
|
||||
entry.callback(settings.device, entry.context, id, txState);
|
||||
}
|
||||
}
|
||||
|
||||
error_t Sx1262Radio::addRxCallback(void* context, LoraRxCallback callback) {
|
||||
lock();
|
||||
rxCallbacks.push_back({context, callback});
|
||||
unlock();
|
||||
return ERROR_NONE;
|
||||
}
|
||||
|
||||
error_t Sx1262Radio::removeRxCallback(LoraRxCallback callback) {
|
||||
lock();
|
||||
const auto old_size = rxCallbacks.size();
|
||||
std::erase_if(rxCallbacks, [callback](const auto& entry) { return entry.callback == callback; });
|
||||
const auto result = (rxCallbacks.size() == old_size) ? ERROR_NOT_FOUND : ERROR_NONE;
|
||||
unlock();
|
||||
return result;
|
||||
}
|
||||
|
||||
error_t Sx1262Radio::addStateCallback(void* context, LoraStateCallback callback) {
|
||||
lock();
|
||||
stateCallbacks.push_back({context, callback});
|
||||
unlock();
|
||||
return ERROR_NONE;
|
||||
}
|
||||
|
||||
error_t Sx1262Radio::removeStateCallback(LoraStateCallback callback) {
|
||||
lock();
|
||||
const auto old_size = stateCallbacks.size();
|
||||
std::erase_if(stateCallbacks, [callback](const auto& entry) { return entry.callback == callback; });
|
||||
const auto result = (stateCallbacks.size() == old_size) ? ERROR_NOT_FOUND : ERROR_NONE;
|
||||
unlock();
|
||||
return result;
|
||||
}
|
||||
|
||||
error_t Sx1262Radio::addTxCallback(void* context, LoraTxCallback callback) {
|
||||
lock();
|
||||
txCallbacks.push_back({context, callback});
|
||||
unlock();
|
||||
return ERROR_NONE;
|
||||
}
|
||||
|
||||
error_t Sx1262Radio::removeTxCallback(LoraTxCallback callback) {
|
||||
lock();
|
||||
const auto old_size = txCallbacks.size();
|
||||
std::erase_if(txCallbacks, [callback](const auto& entry) { return entry.callback == callback; });
|
||||
const auto result = (txCallbacks.size() == old_size) ? ERROR_NOT_FOUND : ERROR_NONE;
|
||||
unlock();
|
||||
return result;
|
||||
error_t Sx1262Radio::publishTx(LoraTxId id, enum LoraTransmissionState txState) {
|
||||
return lora_tx_event_emit(settings.device, id, txState);
|
||||
}
|
||||
|
||||
// endregion
|
||||
@@ -952,15 +884,10 @@ void Sx1262Radio::doReceive() {
|
||||
} else if (rxSize == 0) {
|
||||
// Empty read: skip silently to avoid log flooding on spurious IRQs.
|
||||
} else {
|
||||
const struct LoraRxPacket packet = {
|
||||
.data = data.data(),
|
||||
.length = data.size(),
|
||||
.rssi = radio.getRSSI(),
|
||||
.snr = radio.getSNR(),
|
||||
};
|
||||
|
||||
LOG_I(TAG, "RX: %u bytes, RSSI %.1f dBm, SNR %.1f dB", (unsigned)packet.length, packet.rssi, packet.snr);
|
||||
publishRx(packet);
|
||||
const float rssi = radio.getRSSI();
|
||||
const float snr = radio.getSNR();
|
||||
LOG_I(TAG, "RX: %u bytes, RSSI %.1f dBm, SNR %.1f dB", (unsigned)data.size(), rssi, snr);
|
||||
publishRx(data.data(), data.size(), rssi, snr);
|
||||
radio.finishReceive();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,10 +19,9 @@ struct Device;
|
||||
struct GpioDescriptor;
|
||||
|
||||
/**
|
||||
* SX1262 radio engine: owns the radio thread, the TX queue and the callback lists.
|
||||
* The public methods are thread-safe. Callbacks are invoked on a snapshot of the list with
|
||||
* the internal mutex released, either from the radio thread (RX, TX progress, state) or from
|
||||
* the caller of transmit() (QUEUED).
|
||||
* SX1262 radio engine: owns the radio thread and the TX queue. The public methods are
|
||||
* thread-safe. State/RX/TX events are published via lora_event_emit(), either from the radio
|
||||
* thread (RX, TX progress, state) or from the caller of transmit() (QUEUED).
|
||||
*
|
||||
* The RadioLib types live behind the RadioParts indirection: RadioLib declares a global
|
||||
* `class Module` that collides with the kernel's `struct Module` when both are visible
|
||||
@@ -59,12 +58,6 @@ private:
|
||||
std::vector<uint8_t> data;
|
||||
};
|
||||
|
||||
template<typename Callback>
|
||||
struct CallbackEntry {
|
||||
void* context;
|
||||
Callback callback;
|
||||
};
|
||||
|
||||
const Settings settings;
|
||||
RadioParts* parts;
|
||||
mutable RecursiveMutex mutex = {};
|
||||
@@ -80,10 +73,6 @@ private:
|
||||
TxItem currentTx;
|
||||
LoraTxId lastTxId = 0;
|
||||
|
||||
std::vector<CallbackEntry<LoraStateCallback>> stateCallbacks;
|
||||
std::vector<CallbackEntry<LoraRxCallback>> rxCallbacks;
|
||||
std::vector<CallbackEntry<LoraTxCallback>> txCallbacks;
|
||||
|
||||
// Parameter store, applied on the next doBegin(). Frequencies/rates are held in base SI
|
||||
// units (Hz, bit/s) and converted to RadioLib's MHz/kHz/kbps floats in doBegin().
|
||||
int8_t power = -9;
|
||||
@@ -111,8 +100,8 @@ private:
|
||||
int32_t threadMain();
|
||||
|
||||
void setState(enum LoraRadioState newState);
|
||||
void publishRx(const struct LoraRxPacket& packet);
|
||||
void publishTx(LoraTxId id, enum LoraTransmissionState txState);
|
||||
error_t publishRx(const uint8_t* data, size_t length, float rssi, float snr);
|
||||
error_t publishTx(LoraTxId id, enum LoraTransmissionState txState);
|
||||
|
||||
size_t getTxQueueSize() const;
|
||||
TxItem popNextQueuedTx();
|
||||
@@ -165,11 +154,4 @@ public:
|
||||
error_t getParameter(enum LoraParameter parameter, int32_t* value) const;
|
||||
|
||||
error_t transmit(const uint8_t* data, size_t length, LoraTxId* id);
|
||||
|
||||
error_t addRxCallback(void* context, LoraRxCallback callback);
|
||||
error_t removeRxCallback(LoraRxCallback callback);
|
||||
error_t addStateCallback(void* context, LoraStateCallback callback);
|
||||
error_t removeStateCallback(LoraStateCallback callback);
|
||||
error_t addTxCallback(void* context, LoraTxCallback callback);
|
||||
error_t removeTxCallback(LoraTxCallback callback);
|
||||
};
|
||||
|
||||
@@ -312,42 +312,6 @@ static error_t api_transmit(Device* device, const uint8_t* data, size_t length,
|
||||
return radio->transmit(data, length, id);
|
||||
}
|
||||
|
||||
static error_t api_add_rx_callback(Device* device, void* callback_context, LoraRxCallback callback) {
|
||||
auto* radio = get_radio(device);
|
||||
if (radio == nullptr) return ERROR_INVALID_STATE;
|
||||
return radio->addRxCallback(callback_context, callback);
|
||||
}
|
||||
|
||||
static error_t api_remove_rx_callback(Device* device, LoraRxCallback callback) {
|
||||
auto* radio = get_radio(device);
|
||||
if (radio == nullptr) return ERROR_INVALID_STATE;
|
||||
return radio->removeRxCallback(callback);
|
||||
}
|
||||
|
||||
static error_t api_add_state_callback(Device* device, void* callback_context, LoraStateCallback callback) {
|
||||
auto* radio = get_radio(device);
|
||||
if (radio == nullptr) return ERROR_INVALID_STATE;
|
||||
return radio->addStateCallback(callback_context, callback);
|
||||
}
|
||||
|
||||
static error_t api_remove_state_callback(Device* device, LoraStateCallback callback) {
|
||||
auto* radio = get_radio(device);
|
||||
if (radio == nullptr) return ERROR_INVALID_STATE;
|
||||
return radio->removeStateCallback(callback);
|
||||
}
|
||||
|
||||
static error_t api_add_tx_callback(Device* device, void* callback_context, LoraTxCallback callback) {
|
||||
auto* radio = get_radio(device);
|
||||
if (radio == nullptr) return ERROR_INVALID_STATE;
|
||||
return radio->addTxCallback(callback_context, callback);
|
||||
}
|
||||
|
||||
static error_t api_remove_tx_callback(Device* device, LoraTxCallback callback) {
|
||||
auto* radio = get_radio(device);
|
||||
if (radio == nullptr) return ERROR_INVALID_STATE;
|
||||
return radio->removeTxCallback(callback);
|
||||
}
|
||||
|
||||
static const struct LoraApi sx1262_lora_api = {
|
||||
.get_radio_state = api_get_radio_state,
|
||||
.set_enabled = api_set_enabled,
|
||||
@@ -358,12 +322,6 @@ static const struct LoraApi sx1262_lora_api = {
|
||||
.set_parameter = api_set_parameter,
|
||||
.get_parameter = api_get_parameter,
|
||||
.transmit = api_transmit,
|
||||
.add_rx_callback = api_add_rx_callback,
|
||||
.remove_rx_callback = api_remove_rx_callback,
|
||||
.add_state_callback = api_add_state_callback,
|
||||
.remove_state_callback = api_remove_state_callback,
|
||||
.add_tx_callback = api_add_tx_callback,
|
||||
.remove_tx_callback = api_remove_tx_callback,
|
||||
};
|
||||
|
||||
// endregion
|
||||
|
||||
Reference in New Issue
Block a user