Line data Source code
1 1 : /*
2 : * Copyright (c) 2019 Manivannan Sadhasivam
3 : *
4 : * SPDX-License-Identifier: Apache-2.0
5 : */
6 :
7 : /**
8 : * @file
9 : * @ingroup lora_interface
10 : * @brief Main header file for LoRa driver API.
11 : */
12 : #ifndef ZEPHYR_INCLUDE_DRIVERS_LORA_H_
13 : #define ZEPHYR_INCLUDE_DRIVERS_LORA_H_
14 :
15 : /**
16 : * @brief Interfaces for LoRa transceivers.
17 : * @defgroup lora_interface LoRa
18 : * @since 2.2
19 : * @version 0.1.0
20 : * @ingroup io_interfaces
21 : * @{
22 : */
23 :
24 : #include <stdint.h>
25 : #include <zephyr/kernel.h>
26 : #include <zephyr/device.h>
27 :
28 : #ifdef __cplusplus
29 : extern "C" {
30 : #endif
31 :
32 : /**
33 : * @brief LoRa signal bandwidth
34 : *
35 : * This enumeration defines the bandwidth of a LoRa signal.
36 : *
37 : * The bandwidth determines how much spectrum is used to transmit data. Wider bandwidths enable
38 : * higher data rates but typically reduce sensitivity and range.
39 : */
40 1 : enum lora_signal_bandwidth {
41 : BW_125_KHZ = 0, /**< 125 kHz */
42 : BW_250_KHZ, /**< 250 kHz */
43 : BW_500_KHZ, /**< 500 kHz */
44 : };
45 :
46 : /**
47 : * @brief LoRa data-rate
48 : *
49 : * This enumeration represents the data rate of a LoRa signal, expressed as a Spreading Factor (SF).
50 : *
51 : * The Spreading Factor determines how many chirps are used to encode each symbol (2^SF chips per
52 : * symbol). Higher values result in lower data rates but increased range and robustness.
53 : */
54 1 : enum lora_datarate {
55 : SF_6 = 6, /**< Spreading factor 6 (fastest, shortest range) */
56 : SF_7, /**< Spreading factor 7 */
57 : SF_8, /**< Spreading factor 8 */
58 : SF_9, /**< Spreading factor 9 */
59 : SF_10, /**< Spreading factor 10 */
60 : SF_11, /**< Spreading factor 11 */
61 : SF_12, /**< Spreading factor 12 (slowest, longest range) */
62 : };
63 :
64 : /**
65 : * @brief LoRa coding rate
66 : *
67 : * This enumeration defines the LoRa coding rate, used for forward error correction (FEC).
68 : *
69 : * The coding rate is expressed as 4/x, where a lower denominator (e.g., 4/5) means less redundancy,
70 : * resulting in a higher data rate but reduced robustness. Higher redundancy (e.g., 4/8) improves
71 : * error tolerance at the cost of data rate.
72 : */
73 1 : enum lora_coding_rate {
74 : CR_4_5 = 1, /**< Coding rate 4/5 (4 information bits, 1 error correction bit) */
75 : CR_4_6 = 2, /**< Coding rate 4/6 (4 information bits, 2 error correction bits) */
76 : CR_4_7 = 3, /**< Coding rate 4/7 (4 information bits, 3 error correction bits) */
77 : CR_4_8 = 4, /**< Coding rate 4/8 (4 information bits, 4 error correction bits) */
78 : };
79 :
80 : /**
81 : * @struct lora_modem_config
82 : * Structure containing the configuration of a LoRa modem
83 : */
84 1 : struct lora_modem_config {
85 : /** Frequency in Hz to use for transceiving */
86 1 : uint32_t frequency;
87 :
88 : /** The bandwidth to use for transceiving */
89 1 : enum lora_signal_bandwidth bandwidth;
90 :
91 : /** The data-rate to use for transceiving */
92 1 : enum lora_datarate datarate;
93 :
94 : /** The coding rate to use for transceiving */
95 1 : enum lora_coding_rate coding_rate;
96 :
97 : /** Length of the preamble */
98 1 : uint16_t preamble_len;
99 :
100 : /** TX-power in dBm to use for transmission */
101 1 : int8_t tx_power;
102 :
103 : /** Set to true for transmission, false for receiving */
104 1 : bool tx;
105 :
106 : /**
107 : * Invert the In-Phase and Quadrature (IQ) signals. Normally this
108 : * should be set to false. In advanced use-cases where a
109 : * differentation is needed between "uplink" and "downlink" traffic,
110 : * the IQ can be inverted to create two different channels on the
111 : * same frequency
112 : */
113 1 : bool iq_inverted;
114 :
115 : /**
116 : * Sets the sync-byte to use:
117 : * - false: for using the private network sync-byte
118 : * - true: for using the public network sync-byte
119 : * The public network sync-byte is only intended for advanced usage.
120 : * Normally the private network sync-byte should be used for peer
121 : * to peer communications and the LoRaWAN APIs should be used for
122 : * interacting with a public network.
123 : */
124 1 : bool public_network;
125 : };
126 :
127 : /**
128 : * @cond INTERNAL_HIDDEN
129 : *
130 : * For internal driver use only, skip these in public documentation.
131 : */
132 :
133 : /**
134 : * @typedef lora_recv_cb()
135 : * @brief Callback API for receiving data asynchronously
136 : *
137 : * @see lora_recv() for argument descriptions.
138 : */
139 : typedef void (*lora_recv_cb)(const struct device *dev, uint8_t *data, uint16_t size,
140 : int16_t rssi, int8_t snr, void *user_data);
141 :
142 : /**
143 : * @typedef lora_api_config()
144 : * @brief Callback API for configuring the LoRa module
145 : *
146 : * @see lora_config() for argument descriptions.
147 : */
148 : typedef int (*lora_api_config)(const struct device *dev,
149 : struct lora_modem_config *config);
150 :
151 : /**
152 : * @typedef lora_api_send()
153 : * @brief Callback API for sending data over LoRa
154 : *
155 : * @see lora_send() for argument descriptions.
156 : */
157 : typedef int (*lora_api_send)(const struct device *dev,
158 : uint8_t *data, uint32_t data_len);
159 :
160 : /**
161 : * @typedef lora_api_send_async()
162 : * @brief Callback API for sending data asynchronously over LoRa
163 : *
164 : * @see lora_send_async() for argument descriptions.
165 : */
166 : typedef int (*lora_api_send_async)(const struct device *dev,
167 : uint8_t *data, uint32_t data_len,
168 : struct k_poll_signal *async);
169 :
170 : /**
171 : * @typedef lora_api_recv()
172 : * @brief Callback API for receiving data over LoRa
173 : *
174 : * @see lora_recv() for argument descriptions.
175 : */
176 : typedef int (*lora_api_recv)(const struct device *dev, uint8_t *data,
177 : uint8_t size,
178 : k_timeout_t timeout, int16_t *rssi, int8_t *snr);
179 :
180 : /**
181 : * @typedef lora_api_recv_async()
182 : * @brief Callback API for receiving data asynchronously over LoRa
183 : *
184 : * @param dev Modem to receive data on.
185 : * @param cb Callback to run on receiving data.
186 : */
187 : typedef int (*lora_api_recv_async)(const struct device *dev, lora_recv_cb cb,
188 : void *user_data);
189 :
190 : /**
191 : * @typedef lora_api_test_cw()
192 : * @brief Callback API for transmitting a continuous wave
193 : *
194 : * @see lora_test_cw() for argument descriptions.
195 : */
196 : typedef int (*lora_api_test_cw)(const struct device *dev, uint32_t frequency,
197 : int8_t tx_power, uint16_t duration);
198 :
199 : __subsystem struct lora_driver_api {
200 : lora_api_config config;
201 : lora_api_send send;
202 : lora_api_send_async send_async;
203 : lora_api_recv recv;
204 : lora_api_recv_async recv_async;
205 : lora_api_test_cw test_cw;
206 : };
207 :
208 : /** @endcond */
209 :
210 : /**
211 : * @brief Configure the LoRa modem
212 : *
213 : * @param dev LoRa device
214 : * @param config Data structure containing the intended configuration for the
215 : modem
216 : * @return 0 on success, negative on error
217 : */
218 1 : static inline int lora_config(const struct device *dev,
219 : struct lora_modem_config *config)
220 : {
221 : const struct lora_driver_api *api =
222 : (const struct lora_driver_api *)dev->api;
223 :
224 : return api->config(dev, config);
225 : }
226 :
227 : /**
228 : * @brief Send data over LoRa
229 : *
230 : * @note This blocks until transmission is complete.
231 : *
232 : * @param dev LoRa device
233 : * @param data Data to be sent
234 : * @param data_len Length of the data to be sent
235 : * @return 0 on success, negative on error
236 : */
237 1 : static inline int lora_send(const struct device *dev,
238 : uint8_t *data, uint32_t data_len)
239 : {
240 : const struct lora_driver_api *api =
241 : (const struct lora_driver_api *)dev->api;
242 :
243 : return api->send(dev, data, data_len);
244 : }
245 :
246 : /**
247 : * @brief Asynchronously send data over LoRa
248 : *
249 : * @note This returns immediately after starting transmission, and locks
250 : * the LoRa modem until the transmission completes.
251 : *
252 : * @param dev LoRa device
253 : * @param data Data to be sent
254 : * @param data_len Length of the data to be sent
255 : * @param async A pointer to a valid and ready to be signaled
256 : * struct k_poll_signal. (Note: if NULL this function will not
257 : * notify the end of the transmission).
258 : * @return 0 on success, negative on error
259 : */
260 1 : static inline int lora_send_async(const struct device *dev,
261 : uint8_t *data, uint32_t data_len,
262 : struct k_poll_signal *async)
263 : {
264 : const struct lora_driver_api *api =
265 : (const struct lora_driver_api *)dev->api;
266 :
267 : return api->send_async(dev, data, data_len, async);
268 : }
269 :
270 : /**
271 : * @brief Receive data over LoRa
272 : *
273 : * @note This is a blocking call.
274 : *
275 : * @param dev LoRa device
276 : * @param data Buffer to hold received data
277 : * @param size Size of the buffer to hold the received data. Max size
278 : allowed is 255.
279 : * @param timeout Duration to wait for a packet.
280 : * @param rssi RSSI of received data
281 : * @param snr SNR of received data
282 : * @return Length of the data received on success, negative on error
283 : */
284 1 : static inline int lora_recv(const struct device *dev, uint8_t *data,
285 : uint8_t size,
286 : k_timeout_t timeout, int16_t *rssi, int8_t *snr)
287 : {
288 : const struct lora_driver_api *api =
289 : (const struct lora_driver_api *)dev->api;
290 :
291 : return api->recv(dev, data, size, timeout, rssi, snr);
292 : }
293 :
294 : /**
295 : * @brief Receive data asynchronously over LoRa
296 : *
297 : * Receive packets continuously under the configuration previously setup
298 : * by @ref lora_config.
299 : *
300 : * Reception is cancelled by calling this function again with @p cb = NULL.
301 : * This can be done within the callback handler.
302 : *
303 : * @param dev Modem to receive data on.
304 : * @param cb Callback to run on receiving data. If NULL, any pending
305 : * asynchronous receptions will be cancelled.
306 : * @param user_data User data passed to callback
307 : * @return 0 when reception successfully setup, negative on error
308 : */
309 1 : static inline int lora_recv_async(const struct device *dev, lora_recv_cb cb,
310 : void *user_data)
311 : {
312 : const struct lora_driver_api *api =
313 : (const struct lora_driver_api *)dev->api;
314 :
315 : return api->recv_async(dev, cb, user_data);
316 : }
317 :
318 : /**
319 : * @brief Transmit an unmodulated continuous wave at a given frequency
320 : *
321 : * @note Only use this functionality in a test setup where the
322 : * transmission does not interfere with other devices.
323 : *
324 : * @param dev LoRa device
325 : * @param frequency Output frequency (Hertz)
326 : * @param tx_power TX power (dBm)
327 : * @param duration Transmission duration in seconds.
328 : * @return 0 on success, negative on error
329 : */
330 1 : static inline int lora_test_cw(const struct device *dev, uint32_t frequency,
331 : int8_t tx_power, uint16_t duration)
332 : {
333 : const struct lora_driver_api *api =
334 : (const struct lora_driver_api *)dev->api;
335 :
336 : if (api->test_cw == NULL) {
337 : return -ENOSYS;
338 : }
339 :
340 : return api->test_cw(dev, frequency, tx_power, duration);
341 : }
342 :
343 : #ifdef __cplusplus
344 : }
345 : #endif
346 :
347 : /**
348 : * @}
349 : */
350 :
351 : #endif /* ZEPHYR_INCLUDE_DRIVERS_LORA_H_ */
|