Line data Source code
1 : #include "LR11x0.h"
2 :
3 : #include <string.h>
4 :
5 : #if !RADIOLIB_EXCLUDE_LR11X0
6 :
7 0 : int16_t LR11x0::startWifiScan(char wifiType, uint8_t mode, uint16_t chanMask, uint8_t numScans, uint16_t timeout) {
8 : // LR1121 cannot do WiFi scanning
9 0 : if(this->chipType == RADIOLIB_LR11X0_DEVICE_LR1121) {
10 0 : return(RADIOLIB_ERR_UNSUPPORTED);
11 : }
12 :
13 : uint8_t type;
14 0 : switch(wifiType) {
15 0 : case('b'):
16 0 : type = RADIOLIB_LR11X0_WIFI_SCAN_802_11_B;
17 0 : break;
18 0 : case('g'):
19 0 : type = RADIOLIB_LR11X0_WIFI_SCAN_802_11_G;
20 0 : break;
21 0 : case('n'):
22 0 : type = RADIOLIB_LR11X0_WIFI_SCAN_802_11_N;
23 0 : break;
24 0 : case('*'):
25 0 : type = RADIOLIB_LR11X0_WIFI_SCAN_ALL;
26 0 : break;
27 0 : default:
28 0 : return(RADIOLIB_ERR_INVALID_WIFI_TYPE);
29 : }
30 :
31 : // go to standby
32 0 : int16_t state = standby();
33 0 : RADIOLIB_ASSERT(state);
34 :
35 : // reset cumulative timings
36 0 : state = wifiResetCumulTimings();
37 0 : RADIOLIB_ASSERT(state);
38 :
39 : // set DIO mapping
40 0 : state = setDioIrqParams(RADIOLIB_LR11X0_IRQ_WIFI_DONE);
41 0 : RADIOLIB_ASSERT(state);
42 :
43 : // start scan with the maximum number of results and abort on timeout
44 0 : this->wifiScanMode = mode;
45 0 : state = wifiScan(type, chanMask, this->wifiScanMode, RADIOLIB_LR11X0_WIFI_MAX_NUM_RESULTS, numScans, timeout, RADIOLIB_LR11X0_WIFI_ABORT_ON_TIMEOUT_ENABLED);
46 0 : return(state);
47 : }
48 :
49 0 : void LR11x0::setWiFiScanAction(void (*func)(void)) {
50 0 : this->setIrqAction(func);
51 0 : }
52 :
53 0 : void LR11x0::clearWiFiScanAction() {
54 0 : this->clearIrqAction();
55 0 : }
56 :
57 0 : int16_t LR11x0::getWifiScanResultsCount(uint8_t* count) {
58 : // clear IRQ first, as this is likely to be called right after scan has finished
59 0 : int16_t state = clearIrqState(RADIOLIB_LR11X0_IRQ_ALL);
60 0 : RADIOLIB_ASSERT(state);
61 :
62 0 : uint8_t buff[1] = { 0 };
63 0 : state = this->SPIcommand(RADIOLIB_LR11X0_CMD_WIFI_GET_NB_RESULTS, false, buff, sizeof(buff));
64 :
65 : // pass the replies
66 0 : if(count) { *count = buff[0]; }
67 :
68 0 : return(state);
69 : }
70 :
71 0 : int16_t LR11x0::getWifiScanResult(LR11x0WifiResult_t* result, uint8_t index, bool brief) {
72 0 : RADIOLIB_ASSERT_PTR(result);
73 :
74 : // read a single result
75 0 : uint8_t format = brief ? RADIOLIB_LR11X0_WIFI_RESULT_TYPE_BASIC : RADIOLIB_LR11X0_WIFI_RESULT_TYPE_COMPLETE;
76 0 : uint8_t raw[RADIOLIB_LR11X0_WIFI_RESULT_MAX_LEN] = { 0 };
77 0 : int16_t state = wifiReadResults(index, 1, format, raw);
78 0 : RADIOLIB_ASSERT(state);
79 :
80 : // parse the information
81 0 : switch(raw[0] & 0x03) {
82 0 : case(RADIOLIB_LR11X0_WIFI_SCAN_802_11_B):
83 0 : result->type = 'b';
84 0 : break;
85 0 : case(RADIOLIB_LR11X0_WIFI_SCAN_802_11_G):
86 0 : result->type = 'g';
87 0 : break;
88 0 : case(RADIOLIB_LR11X0_WIFI_SCAN_802_11_N):
89 0 : result->type = 'n';
90 0 : break;
91 : }
92 0 : result->dataRateId = (raw[0] & 0xFC) >> 2;
93 0 : result->channelFreq = 2407 + (raw[1] & 0x0F)*5;
94 0 : result->origin = (raw[1] & 0x30) >> 4;
95 0 : result->ap = (raw[1] & 0x40) != 0;
96 0 : result->rssi = (float)raw[2] / -2.0f;;
97 0 : memcpy(result->mac, &raw[3], RADIOLIB_LR11X0_WIFI_RESULT_MAC_LEN);
98 :
99 0 : if(!brief) {
100 0 : if(this->wifiScanMode == RADIOLIB_LR11X0_WIFI_ACQ_MODE_FULL_BEACON) {
101 0 : LR11x0WifiResultExtended_t* resultExtended = reinterpret_cast<LR11x0WifiResultExtended_t*>(result);
102 0 : resultExtended->rate = raw[3];
103 0 : resultExtended->service = (((uint16_t)raw[4] << 8) | ((uint16_t)raw[5]));
104 0 : resultExtended->length = (((uint16_t)raw[6] << 8) | ((uint16_t)raw[7]));
105 0 : resultExtended->frameType = raw[9] & 0x03;
106 0 : resultExtended->frameSubType = (raw[9] & 0x3C) >> 2;
107 0 : resultExtended->toDistributionSystem = (raw[9] & 0x40) != 0;
108 0 : resultExtended->fromDistributionSystem = (raw[9] & 0x80) != 0;
109 0 : memcpy(resultExtended->mac0, &raw[10], RADIOLIB_LR11X0_WIFI_RESULT_MAC_LEN);
110 0 : memcpy(resultExtended->mac, &raw[16], RADIOLIB_LR11X0_WIFI_RESULT_MAC_LEN);
111 0 : memcpy(resultExtended->mac2, &raw[22], RADIOLIB_LR11X0_WIFI_RESULT_MAC_LEN);
112 0 : resultExtended->timestamp = (((uint64_t)raw[28] << 56) | ((uint64_t)raw[29] << 48)) |
113 0 : (((uint64_t)raw[30] << 40) | ((uint64_t)raw[31] << 32)) |
114 0 : (((uint64_t)raw[32] << 24) | ((uint64_t)raw[33] << 16)) |
115 0 : (((uint64_t)raw[34] << 8) | (uint64_t)raw[35]);
116 0 : resultExtended->periodBeacon = (((uint16_t)raw[36] << 8) | ((uint16_t)raw[37])) * 1024UL;
117 0 : resultExtended->seqCtrl = (((uint16_t)raw[38] << 8) | ((uint16_t)raw[39]));
118 0 : memcpy(resultExtended->ssid, &raw[40], RADIOLIB_LR11X0_WIFI_RESULT_SSID_LEN);
119 0 : resultExtended->currentChannel = raw[72];
120 0 : memcpy(resultExtended->countryCode, &raw[73], 2);
121 0 : resultExtended->countryCode[2] = '\0';
122 0 : resultExtended->ioReg = raw[75];
123 0 : resultExtended->fcsCheckOk = (raw[76] != 0);
124 0 : resultExtended->phiOffset = (((uint16_t)raw[77] << 8) | ((uint16_t)raw[78]));
125 0 : return(RADIOLIB_ERR_NONE);
126 : }
127 :
128 0 : LR11x0WifiResultFull_t* resultFull = reinterpret_cast<LR11x0WifiResultFull_t*>(result);
129 0 : resultFull->frameType = raw[3] & 0x03;
130 0 : resultFull->frameSubType = (raw[3] & 0x3C) >> 2;
131 0 : resultFull->toDistributionSystem = (raw[3] & 0x40) != 0;
132 0 : resultFull->fromDistributionSystem = (raw[3] & 0x80) != 0;
133 0 : memcpy(resultFull->mac, &raw[4], RADIOLIB_LR11X0_WIFI_RESULT_MAC_LEN);
134 0 : resultFull->phiOffset = (((uint16_t)raw[10] << 8) | ((uint16_t)raw[11]));
135 0 : resultFull->timestamp = (((uint64_t)raw[12] << 56) | ((uint64_t)raw[13] << 48)) |
136 0 : (((uint64_t)raw[14] << 40) | ((uint64_t)raw[15] << 32)) |
137 0 : (((uint64_t)raw[16] << 24) | ((uint64_t)raw[17] << 16)) |
138 0 : (((uint64_t)raw[18] << 8) | (uint64_t)raw[19]);
139 0 : resultFull->periodBeacon = (((uint16_t)raw[20] << 8) | ((uint16_t)raw[21])) * 1024UL;
140 : }
141 :
142 0 : return(RADIOLIB_ERR_NONE);
143 : }
144 :
145 0 : int16_t LR11x0::wifiScan(uint8_t wifiType, uint8_t* count, uint8_t mode, uint16_t chanMask, uint8_t numScans, uint16_t timeout) {
146 0 : RADIOLIB_ASSERT_PTR(count);
147 :
148 : // start scan
149 : RADIOLIB_DEBUG_BASIC_PRINTLN("WiFi scan start");
150 0 : int16_t state = startWifiScan(wifiType, mode, chanMask, numScans, timeout);
151 0 : RADIOLIB_ASSERT(state);
152 :
153 : // wait for scan finished or timeout
154 0 : RadioLibTime_t softTimeout = 30UL * 1000UL;
155 0 : RadioLibTime_t start = this->mod->hal->millis();
156 0 : while(!this->mod->hal->digitalRead(this->mod->getIrq())) {
157 0 : this->mod->hal->yield();
158 0 : if(this->mod->hal->millis() - start > softTimeout) {
159 : RADIOLIB_DEBUG_BASIC_PRINTLN("Timeout waiting for IRQ");
160 0 : this->standby();
161 0 : return(RADIOLIB_ERR_RX_TIMEOUT);
162 : }
163 : }
164 : RADIOLIB_DEBUG_BASIC_PRINTLN("WiFi scan done in %lu ms", (long unsigned int)(this->mod->hal->millis() - start));
165 :
166 : // read number of results
167 0 : return(getWifiScanResultsCount(count));
168 : }
169 :
170 0 : int16_t LR11x0::wifiScan(uint8_t type, uint16_t mask, uint8_t acqMode, uint8_t nbMaxRes, uint8_t nbScanPerChan, uint16_t timeout, uint8_t abortOnTimeout) {
171 : uint8_t buff[9] = {
172 0 : type, (uint8_t)((mask >> 8) & 0xFF), (uint8_t)(mask & 0xFF),
173 : acqMode, nbMaxRes, nbScanPerChan,
174 0 : (uint8_t)((timeout >> 8) & 0xFF), (uint8_t)(timeout & 0xFF),
175 : abortOnTimeout
176 0 : };
177 :
178 : // call the SPI write stream directly to skip waiting for BUSY - it will be set to high once the scan starts
179 0 : return(this->mod->SPIwriteStream(RADIOLIB_LR11X0_CMD_WIFI_SCAN, buff, sizeof(buff), false, false));
180 : }
181 :
182 0 : int16_t LR11x0::wifiScanTimeLimit(uint8_t type, uint16_t mask, uint8_t acqMode, uint8_t nbMaxRes, uint16_t timePerChan, uint16_t timeout) {
183 : uint8_t buff[9] = {
184 0 : type, (uint8_t)((mask >> 8) & 0xFF), (uint8_t)(mask & 0xFF),
185 : acqMode, nbMaxRes,
186 0 : (uint8_t)((timePerChan >> 8) & 0xFF), (uint8_t)(timePerChan & 0xFF),
187 0 : (uint8_t)((timeout >> 8) & 0xFF), (uint8_t)(timeout & 0xFF)
188 0 : };
189 0 : return(this->SPIcommand(RADIOLIB_LR11X0_CMD_WIFI_SCAN_TIME_LIMIT, true, buff, sizeof(buff)));
190 : }
191 :
192 0 : int16_t LR11x0::wifiCountryCode(uint16_t mask, uint8_t nbMaxRes, uint8_t nbScanPerChan, uint16_t timeout, uint8_t abortOnTimeout) {
193 : uint8_t buff[7] = {
194 0 : (uint8_t)((mask >> 8) & 0xFF), (uint8_t)(mask & 0xFF),
195 : nbMaxRes, nbScanPerChan,
196 0 : (uint8_t)((timeout >> 8) & 0xFF), (uint8_t)(timeout & 0xFF),
197 : abortOnTimeout
198 0 : };
199 0 : return(this->SPIcommand(RADIOLIB_LR11X0_CMD_WIFI_COUNTRY_CODE, true, buff, sizeof(buff)));
200 : }
201 :
202 0 : int16_t LR11x0::wifiCountryCodeTimeLimit(uint16_t mask, uint8_t nbMaxRes, uint16_t timePerChan, uint16_t timeout) {
203 : uint8_t buff[7] = {
204 0 : (uint8_t)((mask >> 8) & 0xFF), (uint8_t)(mask & 0xFF),
205 : nbMaxRes,
206 0 : (uint8_t)((timePerChan >> 8) & 0xFF), (uint8_t)(timePerChan & 0xFF),
207 0 : (uint8_t)((timeout >> 8) & 0xFF), (uint8_t)(timeout & 0xFF)
208 0 : };
209 0 : return(this->SPIcommand(RADIOLIB_LR11X0_CMD_WIFI_COUNTRY_CODE_TIME_LIMIT, true, buff, sizeof(buff)));
210 : }
211 :
212 0 : int16_t LR11x0::wifiReadResults(uint8_t index, uint8_t nbResults, uint8_t format, uint8_t* results) {
213 0 : uint8_t buff[3] = { index, nbResults, format };
214 0 : return(this->SPIcommand(RADIOLIB_LR11X0_CMD_WIFI_READ_RESULTS, false, results, RADIOLIB_LR11X0_WIFI_RESULT_MAX_LEN, buff, sizeof(buff)));
215 : }
216 :
217 0 : int16_t LR11x0::wifiResetCumulTimings(void) {
218 0 : return(this->SPIcommand(RADIOLIB_LR11X0_CMD_WIFI_RESET_CUMUL_TIMINGS, true, NULL, 0));
219 : }
220 :
221 0 : int16_t LR11x0::wifiReadCumulTimings(uint32_t* detection, uint32_t* capture, uint32_t* demodulation) {
222 0 : uint8_t buff[16] = { 0 };
223 0 : int16_t state = this->SPIcommand(RADIOLIB_LR11X0_CMD_WIFI_READ_CUMUL_TIMINGS, false, buff, sizeof(buff));
224 :
225 : // pass the replies
226 0 : if(detection) { *detection = ((uint32_t)(buff[4]) << 24) | ((uint32_t)(buff[5]) << 16) | ((uint32_t)(buff[6]) << 8) | (uint32_t)buff[7]; }
227 0 : if(capture) { *capture = ((uint32_t)(buff[8]) << 24) | ((uint32_t)(buff[9]) << 16) | ((uint32_t)(buff[10]) << 8) | (uint32_t)buff[11]; }
228 0 : if(demodulation) { *demodulation = ((uint32_t)(buff[12]) << 24) | ((uint32_t)(buff[13]) << 16) | ((uint32_t)(buff[14]) << 8) | (uint32_t)buff[15]; }
229 :
230 0 : return(state);
231 : }
232 :
233 0 : int16_t LR11x0::wifiGetNbCountryCodeResults(uint8_t* nbResults) {
234 0 : uint8_t buff[1] = { 0 };
235 0 : int16_t state = this->SPIcommand(RADIOLIB_LR11X0_CMD_WIFI_GET_NB_COUNTRY_CODE_RESULTS, false, buff, sizeof(buff));
236 :
237 : // pass the replies
238 0 : if(nbResults) { *nbResults = buff[0]; }
239 :
240 0 : return(state);
241 : }
242 :
243 0 : int16_t LR11x0::wifiReadCountryCodeResults(uint8_t index, uint8_t nbResults, uint8_t* results) {
244 0 : uint8_t reqBuff[2] = { index, nbResults };
245 0 : return(this->SPIcommand(RADIOLIB_LR11X0_CMD_WIFI_READ_COUNTRY_CODE_RESULTS, false, results, nbResults, reqBuff, sizeof(reqBuff)));
246 : }
247 :
248 0 : int16_t LR11x0::wifiCfgTimestampAPphone(uint32_t timestamp) {
249 : uint8_t buff[4] = {
250 0 : (uint8_t)((timestamp >> 24) & 0xFF), (uint8_t)((timestamp >> 16) & 0xFF),
251 0 : (uint8_t)((timestamp >> 8) & 0xFF), (uint8_t)(timestamp & 0xFF)
252 0 : };
253 0 : return(this->SPIcommand(RADIOLIB_LR11X0_CMD_WIFI_COUNTRY_CODE_TIME_LIMIT, true, buff, sizeof(buff)));
254 : }
255 :
256 0 : int16_t LR11x0::wifiReadVersion(uint8_t* major, uint8_t* minor) {
257 0 : uint8_t buff[2] = { 0 };
258 0 : int16_t state = this->SPIcommand(RADIOLIB_LR11X0_CMD_WIFI_READ_VERSION, false, buff, sizeof(buff));
259 :
260 : // pass the replies
261 0 : if(major) { *major = buff[0]; }
262 0 : if(minor) { *minor = buff[1]; }
263 :
264 0 : return(state);
265 : }
266 :
267 : #endif
|