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);
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 
173 /**
174  * @typedef lora_api_test_cw()
175  * @brief Callback API for transmitting a continuous wave
176  *
177  * @see lora_test_cw() for argument descriptions.
178  */
179 typedef int (*lora_api_test_cw)(const struct device *dev, uint32_t frequency,
180 				int8_t tx_power, uint16_t duration);
181 
182 __subsystem struct lora_driver_api {
183 	lora_api_config config;
184 	lora_api_send send;
185 	lora_api_send_async send_async;
186 	lora_api_recv recv;
187 	lora_api_recv_async recv_async;
188 	lora_api_test_cw test_cw;
189 };
190 
191 /** @endcond */
192 
193 /**
194  * @brief Configure the LoRa modem
195  *
196  * @param dev     LoRa device
197  * @param config  Data structure containing the intended configuration for the
198 		  modem
199  * @return 0 on success, negative on error
200  */
lora_config(const struct device * dev,struct lora_modem_config * config)201 static inline int lora_config(const struct device *dev,
202 			      struct lora_modem_config *config)
203 {
204 	const struct lora_driver_api *api =
205 		(const struct lora_driver_api *)dev->api;
206 
207 	return api->config(dev, config);
208 }
209 
210 /**
211  * @brief Send data over LoRa
212  *
213  * @note This blocks until transmission is complete.
214  *
215  * @param dev       LoRa device
216  * @param data      Data to be sent
217  * @param data_len  Length of the data to be sent
218  * @return 0 on success, negative on error
219  */
lora_send(const struct device * dev,uint8_t * data,uint32_t data_len)220 static inline int lora_send(const struct device *dev,
221 			    uint8_t *data, uint32_t data_len)
222 {
223 	const struct lora_driver_api *api =
224 		(const struct lora_driver_api *)dev->api;
225 
226 	return api->send(dev, data, data_len);
227 }
228 
229 /**
230  * @brief Asynchronously send data over LoRa
231  *
232  * @note This returns immediately after starting transmission, and locks
233  *       the LoRa modem until the transmission completes.
234  *
235  * @param dev       LoRa device
236  * @param data      Data to be sent
237  * @param data_len  Length of the data to be sent
238  * @param async A pointer to a valid and ready to be signaled
239  *        struct k_poll_signal. (Note: if NULL this function will not
240  *        notify the end of the transmission).
241  * @return 0 on success, negative on error
242  */
lora_send_async(const struct device * dev,uint8_t * data,uint32_t data_len,struct k_poll_signal * async)243 static inline int lora_send_async(const struct device *dev,
244 				  uint8_t *data, uint32_t data_len,
245 				  struct k_poll_signal *async)
246 {
247 	const struct lora_driver_api *api =
248 		(const struct lora_driver_api *)dev->api;
249 
250 	return api->send_async(dev, data, data_len, async);
251 }
252 
253 /**
254  * @brief Receive data over LoRa
255  *
256  * @note This is a blocking call.
257  *
258  * @param dev       LoRa device
259  * @param data      Buffer to hold received data
260  * @param size      Size of the buffer to hold the received data. Max size
261 		    allowed is 255.
262  * @param timeout   Duration to wait for a packet.
263  * @param rssi      RSSI of received data
264  * @param snr       SNR of received data
265  * @return Length of the data received on success, negative on error
266  */
lora_recv(const struct device * dev,uint8_t * data,uint8_t size,k_timeout_t timeout,int16_t * rssi,int8_t * snr)267 static inline int lora_recv(const struct device *dev, uint8_t *data,
268 			    uint8_t size,
269 			    k_timeout_t timeout, int16_t *rssi, int8_t *snr)
270 {
271 	const struct lora_driver_api *api =
272 		(const struct lora_driver_api *)dev->api;
273 
274 	return api->recv(dev, data, size, timeout, rssi, snr);
275 }
276 
277 /**
278  * @brief Receive data asynchronously over LoRa
279  *
280  * Receive packets continuously under the configuration previously setup
281  * by @ref lora_config.
282  *
283  * Reception is cancelled by calling this function again with @p cb = NULL.
284  * This can be done within the callback handler.
285  *
286  * @param dev Modem to receive data on.
287  * @param cb Callback to run on receiving data. If NULL, any pending
288  *	     asynchronous receptions will be cancelled.
289  * @return 0 when reception successfully setup, negative on error
290  */
lora_recv_async(const struct device * dev,lora_recv_cb cb)291 static inline int lora_recv_async(const struct device *dev, lora_recv_cb cb)
292 {
293 	const struct lora_driver_api *api =
294 		(const struct lora_driver_api *)dev->api;
295 
296 	return api->recv_async(dev, cb);
297 }
298 
299 /**
300  * @brief Transmit an unmodulated continuous wave at a given frequency
301  *
302  * @note Only use this functionality in a test setup where the
303  * transmission does not interfere with other devices.
304  *
305  * @param dev       LoRa device
306  * @param frequency Output frequency (Hertz)
307  * @param tx_power  TX power (dBm)
308  * @param duration  Transmission duration in seconds.
309  * @return 0 on success, negative on error
310  */
lora_test_cw(const struct device * dev,uint32_t frequency,int8_t tx_power,uint16_t duration)311 static inline int lora_test_cw(const struct device *dev, uint32_t frequency,
312 			       int8_t tx_power, uint16_t duration)
313 {
314 	const struct lora_driver_api *api =
315 		(const struct lora_driver_api *)dev->api;
316 
317 	if (api->test_cw == NULL) {
318 		return -ENOSYS;
319 	}
320 
321 	return api->test_cw(dev, frequency, tx_power, duration);
322 }
323 
324 #ifdef __cplusplus
325 }
326 #endif
327 
328 /**
329  * @}
330  */
331 
332 #endif	/* ZEPHYR_INCLUDE_DRIVERS_LORA_H_ */
333