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