lora: asynchronous packet reception

Adds functionality to receive LoRa packets asynchronously. Reception
runs continuously until cancelled by another call to `lora_recv_async`.

Signed-off-by: Jordan Yates <jordan.yates@data61.csiro.au>
This commit is contained in:
Jordan Yates 2021-08-14 17:40:28 +10:00 committed by Carles Cufí
commit 526b3e9605
5 changed files with 85 additions and 0 deletions

View file

@ -472,6 +472,7 @@ static const struct lora_driver_api sx126x_lora_api = {
.send = sx12xx_lora_send,
.send_async = sx12xx_lora_send_async,
.recv = sx12xx_lora_recv,
.recv_async = sx12xx_lora_recv_async,
.test_cw = sx12xx_lora_test_cw,
};

View file

@ -660,6 +660,7 @@ static const struct lora_driver_api sx127x_lora_api = {
.send = sx12xx_lora_send,
.send_async = sx12xx_lora_send_async,
.recv = sx12xx_lora_recv,
.recv_async = sx12xx_lora_recv_async,
.test_cw = sx12xx_lora_test_cw,
};

View file

@ -30,7 +30,9 @@ struct sx12xx_rx_params {
};
static struct sx12xx_data {
const struct device *dev;
struct k_poll_signal *operation_done;
lora_recv_cb async_rx_cb;
RadioEvents_t events;
struct lora_modem_config tx_cfg;
atomic_t modem_usage;
@ -101,6 +103,16 @@ static void sx12xx_ev_rx_done(uint8_t *payload, uint16_t size, int16_t rssi,
{
struct k_poll_signal *sig = dev_data.operation_done;
/* Receiving in asynchronous mode */
if (dev_data.async_rx_cb) {
/* Start receiving again */
Radio.Rx(0);
/* Run the callback */
dev_data.async_rx_cb(dev_data.dev, payload, size, rssi, snr);
/* Don't run the synchronous code */
return;
}
/* Manually release the modem instead of just calling modem_release
* as we need to perform cleanup operations while still ensuring
* others can't use the modem.
@ -232,6 +244,7 @@ int sx12xx_lora_recv(const struct device *dev, uint8_t *data, uint8_t size,
return -EBUSY;
}
dev_data.async_rx_cb = NULL;
/* Store operation signal */
dev_data.operation_done = &done;
/* Set data output location */
@ -262,6 +275,32 @@ int sx12xx_lora_recv(const struct device *dev, uint8_t *data, uint8_t size,
return size;
}
int sx12xx_lora_recv_async(const struct device *dev, lora_recv_cb cb)
{
/* Cancel ongoing reception */
if (cb == NULL) {
if (!modem_release(&dev_data)) {
/* Not receiving or already being stopped */
return -EINVAL;
}
return 0;
}
/* Ensure available */
if (!modem_acquire(&dev_data)) {
return -EBUSY;
}
/* Store parameters */
dev_data.async_rx_cb = cb;
/* Start reception */
Radio.SetMaxPayloadLength(MODEM_LORA, 255);
Radio.Rx(0);
return 0;
}
int sx12xx_lora_config(const struct device *dev,
struct lora_modem_config *config)
{
@ -309,6 +348,7 @@ int sx12xx_init(const struct device *dev)
{
atomic_set(&dev_data.modem_usage, 0);
dev_data.dev = dev;
dev_data.events.TxDone = sx12xx_ev_tx_done;
dev_data.events.RxDone = sx12xx_ev_rx_done;
Radio.Init(&dev_data.events);

View file

@ -34,6 +34,8 @@ int sx12xx_lora_send_async(const struct device *dev, uint8_t *data,
int sx12xx_lora_recv(const struct device *dev, uint8_t *data, uint8_t size,
k_timeout_t timeout, int16_t *rssi, int8_t *snr);
int sx12xx_lora_recv_async(const struct device *dev, lora_recv_cb cb);
int sx12xx_lora_config(const struct device *dev,
struct lora_modem_config *config);

View file

@ -52,6 +52,15 @@ struct lora_modem_config {
bool tx;
};
/**
* @typedef lora_recv_cb()
* @brief Callback API for receiving data asynchronously
*
* @see lora_recv() for argument descriptions.
*/
typedef void (*lora_recv_cb)(const struct device *dev, uint8_t *data, uint16_t size,
int16_t rssi, int8_t snr);
/**
* @typedef lora_api_config()
* @brief Callback API for configuring the LoRa module
@ -90,6 +99,15 @@ typedef int (*lora_api_recv)(const struct device *dev, uint8_t *data,
uint8_t size,
k_timeout_t timeout, int16_t *rssi, int8_t *snr);
/**
* @typedef lora_api_recv_async()
* @brief Callback API for receiving data asynchronously over LoRa
*
* @param dev Modem to receive data on.
* @param cb Callback to run on receiving data.
*/
typedef int (*lora_api_recv_async)(const struct device *dev, lora_recv_cb cb);
/**
* @typedef lora_api_test_cw()
* @brief Callback API for transmitting a continuous wave
@ -104,6 +122,7 @@ struct lora_driver_api {
lora_api_send send;
lora_api_send_async send_async;
lora_api_recv recv;
lora_api_recv_async recv_async;
lora_api_test_cw test_cw;
};
@ -191,6 +210,28 @@ static inline int lora_recv(const struct device *dev, uint8_t *data,
return api->recv(dev, data, size, timeout, rssi, snr);
}
/**
* @brief Receive data asynchronously over LoRa
*
* Receive packets continuously under the configuration previously setup
* by @ref lora_config.
*
* Reception is cancelled by calling this function again with @p cb = NULL.
* This can be done within the callback handler.
*
* @param dev Modem to receive data on.
* @param cb Callback to run on receiving data. If NULL, any pending
* asynchronous receptions will be cancelled.
* @return 0 when reception successfully setup, negative on error
*/
static inline int lora_recv_async(const struct device *dev, lora_recv_cb cb)
{
const struct lora_driver_api *api =
(const struct lora_driver_api *)dev->api;
return api->recv_async(dev, cb);
}
/**
* @brief Transmit an unmodulated continuous wave at a given frequency
*