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