1 /*
2  * Copyright (c) 2019 Manivannan Sadhasivam
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #ifndef ZEPHYR_INCLUDE_DRIVERS_LORA_H_
8 #define ZEPHYR_INCLUDE_DRIVERS_LORA_H_
9 
10 /**
11  * @file
12  * @brief Public LoRa APIs
13  */
14 
15 #include <zephyr/types.h>
16 #include <device.h>
17 
18 #ifdef __cplusplus
19 extern "C" {
20 #endif
21 
22 enum lora_signal_bandwidth {
23 	BW_125_KHZ = 0,
24 	BW_250_KHZ,
25 	BW_500_KHZ,
26 };
27 
28 enum lora_datarate {
29 	SF_6 = 6,
30 	SF_7,
31 	SF_8,
32 	SF_9,
33 	SF_10,
34 	SF_11,
35 	SF_12,
36 };
37 
38 enum lora_coding_rate {
39 	CR_4_5 = 1,
40 	CR_4_6 = 2,
41 	CR_4_7 = 3,
42 	CR_4_8 = 4,
43 };
44 
45 struct lora_modem_config {
46 	uint32_t frequency;
47 	enum lora_signal_bandwidth bandwidth;
48 	enum lora_datarate datarate;
49 	enum lora_coding_rate coding_rate;
50 	uint16_t preamble_len;
51 	int8_t tx_power;
52 	bool tx;
53 };
54 
55 /**
56  * @typedef lora_api_config()
57  * @brief Callback API for configuring the LoRa module
58  *
59  * @see lora_config() for argument descriptions.
60  */
61 typedef int (*lora_api_config)(const struct device *dev,
62 			       struct lora_modem_config *config);
63 
64 /**
65  * @typedef lora_api_send()
66  * @brief Callback API for sending data over LoRa
67  *
68  * @see lora_send() for argument descriptions.
69  */
70 typedef int (*lora_api_send)(const struct device *dev,
71 			     uint8_t *data, uint32_t data_len);
72 
73 /**
74  * @typedef lora_api_send_async()
75  * @brief Callback API for sending data asynchronously over LoRa
76  *
77  * @see lora_send_async() for argument descriptions.
78  */
79 typedef int (*lora_api_send_async)(const struct device *dev,
80 				   uint8_t *data, uint32_t data_len,
81 				   struct k_poll_signal *async);
82 
83 /**
84  * @typedef lora_api_recv()
85  * @brief Callback API for receiving data over LoRa
86  *
87  * @see lora_recv() for argument descriptions.
88  */
89 typedef int (*lora_api_recv)(const struct device *dev, uint8_t *data,
90 			     uint8_t size,
91 			     k_timeout_t timeout, int16_t *rssi, int8_t *snr);
92 
93 /**
94  * @typedef lora_api_test_cw()
95  * @brief Callback API for transmitting a continuous wave
96  *
97  * @see lora_test_cw() for argument descriptions.
98  */
99 typedef int (*lora_api_test_cw)(const struct device *dev, uint32_t frequency,
100 				int8_t tx_power, uint16_t duration);
101 
102 struct lora_driver_api {
103 	lora_api_config config;
104 	lora_api_send send;
105 	lora_api_send_async send_async;
106 	lora_api_recv recv;
107 	lora_api_test_cw test_cw;
108 };
109 
110 /**
111  * @brief Configure the LoRa modem
112  *
113  * @param dev     LoRa device
114  * @param config  Data structure containing the intended configuration for the
115 		  modem
116  * @return 0 on success, negative on error
117  */
lora_config(const struct device * dev,struct lora_modem_config * config)118 static inline int lora_config(const struct device *dev,
119 			      struct lora_modem_config *config)
120 {
121 	const struct lora_driver_api *api =
122 		(const struct lora_driver_api *)dev->api;
123 
124 	return api->config(dev, config);
125 }
126 
127 /**
128  * @brief Send data over LoRa
129  *
130  * @note This blocks until transmission is complete.
131  *
132  * @param dev       LoRa device
133  * @param data      Data to be sent
134  * @param data_len  Length of the data to be sent
135  * @return 0 on success, negative on error
136  */
lora_send(const struct device * dev,uint8_t * data,uint32_t data_len)137 static inline int lora_send(const struct device *dev,
138 			    uint8_t *data, uint32_t data_len)
139 {
140 	const struct lora_driver_api *api =
141 		(const struct lora_driver_api *)dev->api;
142 
143 	return api->send(dev, data, data_len);
144 }
145 
146 /**
147  * @brief Asynchronously send data over LoRa
148  *
149  * @note This returns immediately after starting transmission, and locks
150  *       the LoRa modem until the transmission completes.
151  *
152  * @param dev       LoRa device
153  * @param data      Data to be sent
154  * @param data_len  Length of the data to be sent
155  * @param async A pointer to a valid and ready to be signaled
156  *        struct k_poll_signal. (Note: if NULL this function will not
157  *        notify the end of the transmission).
158  * @return 0 on success, negative on error
159  */
lora_send_async(const struct device * dev,uint8_t * data,uint32_t data_len,struct k_poll_signal * async)160 static inline int lora_send_async(const struct device *dev,
161 				  uint8_t *data, uint32_t data_len,
162 				  struct k_poll_signal *async)
163 {
164 	const struct lora_driver_api *api =
165 		(const struct lora_driver_api *)dev->api;
166 
167 	return api->send_async(dev, data, data_len, async);
168 }
169 
170 /**
171  * @brief Receive data over LoRa
172  *
173  * @note This is a blocking call.
174  *
175  * @param dev       LoRa device
176  * @param data      Buffer to hold received data
177  * @param size      Size of the buffer to hold the received data. Max size
178 		    allowed is 255.
179  * @param timeout   Duration to wait for a packet.
180  * @param rssi      RSSI of received data
181  * @param snr       SNR of received data
182  * @return Length of the data received on success, negative on error
183  */
lora_recv(const struct device * dev,uint8_t * data,uint8_t size,k_timeout_t timeout,int16_t * rssi,int8_t * snr)184 static inline int lora_recv(const struct device *dev, uint8_t *data,
185 			    uint8_t size,
186 			    k_timeout_t timeout, int16_t *rssi, int8_t *snr)
187 {
188 	const struct lora_driver_api *api =
189 		(const struct lora_driver_api *)dev->api;
190 
191 	return api->recv(dev, data, size, timeout, rssi, snr);
192 }
193 
194 /**
195  * @brief Transmit an unmodulated continuous wave at a given frequency
196  *
197  * @note Only use this functionality in a test setup where the
198  * transmission does not interfere with other devices.
199  *
200  * @param dev       LoRa device
201  * @param frequency Output frequency (Hertz)
202  * @param tx_power  TX power (dBm)
203  * @param duration  Transmission duration in seconds.
204  * @return 0 on success, negative on error
205  */
lora_test_cw(const struct device * dev,uint32_t frequency,int8_t tx_power,uint16_t duration)206 static inline int lora_test_cw(const struct device *dev, uint32_t frequency,
207 			       int8_t tx_power, uint16_t duration)
208 {
209 	const struct lora_driver_api *api =
210 		(const struct lora_driver_api *)dev->api;
211 
212 	if (api->test_cw == NULL) {
213 		return -ENOSYS;
214 	}
215 
216 	return api->test_cw(dev, frequency, tx_power, duration);
217 }
218 
219 #ifdef __cplusplus
220 }
221 #endif
222 
223 #endif	/* ZEPHYR_INCLUDE_DRIVERS_LORA_H_ */
224