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