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:
parent
c89d5c5e45
commit
526b3e9605
5 changed files with 85 additions and 0 deletions
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
*
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue