/* * Copyright (c) 2019 Manivannan Sadhasivam * * SPDX-License-Identifier: Apache-2.0 */ /** * @file * @brief Public LoRa driver APIs */ #ifndef ZEPHYR_INCLUDE_DRIVERS_LORA_H_ #define ZEPHYR_INCLUDE_DRIVERS_LORA_H_ /** * @file * @brief Public LoRa APIs * @defgroup lora_api LoRa APIs * @ingroup io_interfaces * @{ */ #include #include #include #ifdef __cplusplus extern "C" { #endif /** * @brief LoRa signal bandwidth */ enum lora_signal_bandwidth { BW_125_KHZ = 0, BW_250_KHZ, BW_500_KHZ, }; /** * @brief LoRa data-rate */ enum lora_datarate { SF_6 = 6, SF_7, SF_8, SF_9, SF_10, SF_11, SF_12, }; /** * @brief LoRa coding rate */ enum lora_coding_rate { CR_4_5 = 1, CR_4_6 = 2, CR_4_7 = 3, CR_4_8 = 4, }; /** * @struct lora_modem_config * Structure containing the configuration of a LoRa modem */ struct lora_modem_config { /** Frequency in Hz to use for transceiving */ uint32_t frequency; /** The bandwidth to use for transceiving */ enum lora_signal_bandwidth bandwidth; /** The data-rate to use for transceiving */ enum lora_datarate datarate; /** The coding rate to use for transceiving */ enum lora_coding_rate coding_rate; /** Length of the preamble */ uint16_t preamble_len; /** TX-power in dBm to use for transmission */ int8_t tx_power; /** Set to true for transmission, false for receiving */ bool tx; /** * Invert the In-Phase and Quadrature (IQ) signals. Normally this * should be set to false. In advanced use-cases where a * differentation is needed between "uplink" and "downlink" traffic, * the IQ can be inverted to create two different channels on the * same frequency */ bool iq_inverted; /** * Sets the sync-byte to use: * - false: for using the private network sync-byte * - true: for using the public network sync-byte * The public network sync-byte is only intended for advanced usage. * Normally the private network sync-byte should be used for peer * to peer communications and the LoRaWAN APIs should be used for * interacting with a public network. */ bool public_network; }; /** * @cond INTERNAL_HIDDEN * * For internal driver use only, skip these in public documentation. */ /** * @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 * * @see lora_config() for argument descriptions. */ typedef int (*lora_api_config)(const struct device *dev, struct lora_modem_config *config); /** * @typedef lora_api_send() * @brief Callback API for sending data over LoRa * * @see lora_send() for argument descriptions. */ typedef int (*lora_api_send)(const struct device *dev, uint8_t *data, uint32_t data_len); /** * @typedef lora_api_send_async() * @brief Callback API for sending data asynchronously over LoRa * * @see lora_send_async() for argument descriptions. */ typedef int (*lora_api_send_async)(const struct device *dev, uint8_t *data, uint32_t data_len, struct k_poll_signal *async); /** * @typedef lora_api_recv() * @brief Callback API for receiving data over LoRa * * @see lora_recv() for argument descriptions. */ 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 * * @see lora_test_cw() for argument descriptions. */ typedef int (*lora_api_test_cw)(const struct device *dev, uint32_t frequency, int8_t tx_power, uint16_t duration); struct lora_driver_api { lora_api_config config; 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; }; /** @endcond */ /** * @brief Configure the LoRa modem * * @param dev LoRa device * @param config Data structure containing the intended configuration for the modem * @return 0 on success, negative on error */ static inline int lora_config(const struct device *dev, struct lora_modem_config *config) { const struct lora_driver_api *api = (const struct lora_driver_api *)dev->api; return api->config(dev, config); } /** * @brief Send data over LoRa * * @note This blocks until transmission is complete. * * @param dev LoRa device * @param data Data to be sent * @param data_len Length of the data to be sent * @return 0 on success, negative on error */ static inline int lora_send(const struct device *dev, uint8_t *data, uint32_t data_len) { const struct lora_driver_api *api = (const struct lora_driver_api *)dev->api; return api->send(dev, data, data_len); } /** * @brief Asynchronously send data over LoRa * * @note This returns immediately after starting transmission, and locks * the LoRa modem until the transmission completes. * * @param dev LoRa device * @param data Data to be sent * @param data_len Length of the data to be sent * @param async A pointer to a valid and ready to be signaled * struct k_poll_signal. (Note: if NULL this function will not * notify the end of the transmission). * @return 0 on success, negative on error */ static inline int lora_send_async(const struct device *dev, uint8_t *data, uint32_t data_len, struct k_poll_signal *async) { const struct lora_driver_api *api = (const struct lora_driver_api *)dev->api; return api->send_async(dev, data, data_len, async); } /** * @brief Receive data over LoRa * * @note This is a blocking call. * * @param dev LoRa device * @param data Buffer to hold received data * @param size Size of the buffer to hold the received data. Max size allowed is 255. * @param timeout Duration to wait for a packet. * @param rssi RSSI of received data * @param snr SNR of received data * @return Length of the data received on success, negative on error */ static inline int lora_recv(const struct device *dev, uint8_t *data, uint8_t size, k_timeout_t timeout, int16_t *rssi, int8_t *snr) { const struct lora_driver_api *api = (const struct lora_driver_api *)dev->api; 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 * * @note Only use this functionality in a test setup where the * transmission does not interfere with other devices. * * @param dev LoRa device * @param frequency Output frequency (Hertz) * @param tx_power TX power (dBm) * @param duration Transmission duration in seconds. * @return 0 on success, negative on error */ static inline int lora_test_cw(const struct device *dev, uint32_t frequency, int8_t tx_power, uint16_t duration) { const struct lora_driver_api *api = (const struct lora_driver_api *)dev->api; if (api->test_cw == NULL) { return -ENOSYS; } return api->test_cw(dev, frequency, tx_power, duration); } #ifdef __cplusplus } #endif /** * @} */ #endif /* ZEPHYR_INCLUDE_DRIVERS_LORA_H_ */