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