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