Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: X_NUCLEO_IDW01M1v2-lapi-1
Fork of SPWF01SA by
SPWFSA01.cpp
00001 /* SPWFInterface Example 00002 * Copyright (c) 2015 ARM Limited 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 00017 #include "SPWFSA01.h" 00018 #include "mbed_debug.h" 00019 00020 #define SPWFSA01_CONNECT_TIMEOUT 15000 00021 #define SPWFSA01_SEND_TIMEOUT 500 00022 #define SPWFSA01_RECV_TIMEOUT 1500//some commands like AT&F/W takes some time to get the result back! 00023 #define SPWFSA01_MISC_TIMEOUT 500 00024 #define SPWFSA01_SOCKQ_TIMEOUT 3000 00025 00026 SPWFSA01::SPWFSA01(PinName tx, PinName rx, bool debug, PinName resetPin, PinName wakeupPin) : 00027 _serial(tx, rx, 1024), _parser(_serial), 00028 _reset(resetPin, PIN_INPUT, PullNone, 1), _wakeup(wakeupPin, PIN_INPUT, PullNone, 0), 00029 dbg_on(debug) 00030 { 00031 _serial.baud(115200); 00032 _reset.output(); 00033 _wakeup.output(); 00034 _parser.debugOn(debug); 00035 } 00036 00037 bool SPWFSA01::startup(int mode) 00038 { 00039 setTimeout(SPWFSA01_RECV_TIMEOUT); 00040 00041 /*Test module before reset*/ 00042 waitSPWFReady(); 00043 /*Reset module*/ 00044 reset(); 00045 00046 /*set local echo to 0*/ 00047 if(!(_parser.send("AT+S.SCFG=localecho1,%d\r", 0) && _parser.recv("OK"))) 00048 { 00049 debug_if(dbg_on, "SPWF> error local echo set\r\n"); 00050 return false; 00051 } 00052 /*reset factory settings*/ 00053 if(!(_parser.send("AT&F") && _parser.recv("OK"))) 00054 { 00055 debug_if(dbg_on, "SPWF> error AT&F\r\n"); 00056 return false; 00057 } 00058 00059 /*set Wi-Fi mode and rate to b/g/n*/ 00060 if(!(_parser.send("AT+S.SCFG=wifi_ht_mode,%d\r",1) && _parser.recv("OK"))) 00061 { 00062 debug_if(dbg_on, "SPWF> error setting ht_mode\r\n"); 00063 return false; 00064 } 00065 00066 if(!(_parser.send("AT+S.SCFG=wifi_opr_rate_mask,0x003FFFCF\r") && _parser.recv("OK"))) 00067 { 00068 debug_if(dbg_on, "SPWF> error setting operational rates\r\n"); 00069 return false; 00070 } 00071 00072 /*set idle mode (0->idle, 1->STA,3->miniAP, 2->IBSS)*/ 00073 if(!(_parser.send("AT+S.SCFG=wifi_mode,%d\r", mode) && _parser.recv("OK"))) 00074 { 00075 debug_if(dbg_on, "SPWF> error wifi mode set\r\n"); 00076 return false; 00077 } 00078 00079 /* save current setting in flash */ 00080 if(!(_parser.send("AT&W") && _parser.recv("OK"))) 00081 { 00082 debug_if(dbg_on, "SPWF> error AT&W\r\n"); 00083 return false; 00084 } 00085 00086 /*reset again and send AT command and check for result (AT->OK)*/ 00087 reset(); 00088 00089 return true; 00090 } 00091 00092 bool SPWFSA01::hw_reset(void) 00093 { 00094 /* reset the pin PC12 */ 00095 _reset.write(0); 00096 wait_ms(200); 00097 _reset.write(1); 00098 wait_ms(100); 00099 return 1; 00100 } 00101 00102 bool SPWFSA01::reset(void) 00103 { 00104 if(!_parser.send("AT+CFUN=1")) return false; 00105 while(1) { 00106 if (_parser.recv("+WIND:32:WiFi Hardware Started\r")) { 00107 return true; 00108 } 00109 } 00110 } 00111 00112 void SPWFSA01::waitSPWFReady(void) 00113 { 00114 //wait_ms(200); 00115 while(1) { 00116 if(_parser.send("AT") && _parser.recv("OK")) { 00117 //till we get OK from AT command 00118 printf("\r\nwaiting for SPWFSA01 Ready..\n"); 00119 return; 00120 } 00121 } 00122 } 00123 00124 /* Security Mode 00125 None = 0, 00126 WEP = 1, 00127 WPA_Personal = 2, 00128 */ 00129 bool SPWFSA01::connect(const char *ap, const char *passPhrase, int securityMode, int channel) 00130 { 00131 uint32_t n1, n2, n3, n4; 00132 00133 //AT+S.SCFG=wifi_wpa_psk_text,%s\r 00134 if(!(_parser.send("AT+S.SCFG=wifi_wpa_psk_text,%s", passPhrase) && _parser.recv("OK"))) 00135 { 00136 debug_if(dbg_on, "SPWF> error pass set\r\n"); 00137 return false; 00138 } 00139 //AT+S.SSIDTXT=%s\r 00140 if(!(_parser.send("AT+S.SSIDTXT=%s", ap) && _parser.recv("OK"))) 00141 { 00142 debug_if(dbg_on, "SPWF> error ssid set\r\n"); 00143 return false; 00144 } 00145 //AT+S.SCFG=wifi_auth_type,%d\r, is 1 for WEP, 0 for none and WPA/WPA2 00146 if(!(_parser.send("AT+S.SCFG=wifi_auth_type,%d", securityMode == 1 ? 1 : 0) && _parser.recv("OK"))) 00147 { 00148 debug_if(dbg_on, "SPWF> error auth type set\r\n"); 00149 return false; 00150 } 00151 //AT+S.SCFG=wifi_priv_mode,%d\r 00152 if(!(_parser.send("AT+S.SCFG=wifi_priv_mode,%d", securityMode) && _parser.recv("OK"))) 00153 { 00154 debug_if(dbg_on, "SPWF> error security mode set\r\n"); 00155 return false; 00156 } 00157 //"AT+S.SCFG=wifi_mode,%d\r" 00158 /*set idle mode (0->idle, 1->STA,3->miniAP, 2->IBSS)*/ 00159 if(!(_parser.send("AT+S.SCFG=wifi_mode,%d\r", 1) && _parser.recv("OK"))) 00160 { 00161 debug_if(dbg_on, "SPWF> error wifi mode set\r\n"); 00162 return false; 00163 } 00164 //"AT+S.SCFG=wifi_channelnum,%d\r" 00165 /*set channel*/ 00166 if(!(_parser.send("AT+S.SCFG=wifi_channelnum,%d\r", channel) && _parser.recv("OK"))) 00167 { 00168 debug_if(dbg_on, "SPWF> error wifi channel set\r\n"); 00169 return false; 00170 } 00171 //AT&W 00172 /* save current setting in flash */ 00173 if(!(_parser.send("AT&W") && _parser.recv("OK"))) 00174 { 00175 debug_if(dbg_on, "SPWF> error AT&W\r\n"); 00176 return false; 00177 } 00178 //reset module 00179 reset(); 00180 00181 while(1) 00182 if((_parser.recv("+WIND:24:WiFi Up:%u.%u.%u.%u",&n1, &n2, &n3, &n4))) 00183 { 00184 break; 00185 } 00186 00187 return true; 00188 } 00189 00190 bool SPWFSA01::disconnect(void) 00191 { 00192 //"AT+S.SCFG=wifi_mode,%d\r" 00193 /*set idle mode (0->idle, 1->STA,3->miniAP, 2->IBSS)*/ 00194 if(!(_parser.send("AT+S.SCFG=wifi_mode,%d\r", 0) && _parser.recv("OK"))) 00195 { 00196 debug_if(dbg_on, "SPWF> error wifi mode set\r\n"); 00197 return false; 00198 } 00199 //AT&W 00200 /* save current setting in flash */ 00201 if(!(_parser.send("AT&W") && _parser.recv("OK"))) 00202 { 00203 debug_if(dbg_on, "SPWF> error AT&W\r\n"); 00204 return false; 00205 } 00206 //reset module 00207 reset(); 00208 return true; 00209 } 00210 00211 bool SPWFSA01::dhcp(int mode) 00212 { 00213 //only 3 valid modes 00214 //0->off(ip_addr must be set by user), 1->on(auto set by AP), 2->on&customize(miniAP ip_addr can be set by user) 00215 if(mode < 0 || mode > 2) { 00216 return false; 00217 } 00218 00219 return _parser.send("AT+S.SCFG=ip_use_dhcp,%d\r", mode) 00220 && _parser.recv("OK"); 00221 } 00222 00223 00224 int8_t SPWFSA01::getRSSI(void) 00225 { 00226 int32_t rssi; 00227 00228 if (!(_parser.send("AT+S.RCFG=rx_rssi") 00229 && _parser.recv("# rx_rssi = %d", &rssi) 00230 && _parser.recv("OK"))) { 00231 debug_if(dbg_on, "SPWF> getIPAddress error\r\n"); 00232 return 0; 00233 } 00234 00235 return (int8_t)rssi; 00236 } 00237 00238 00239 const char *SPWFSA01::getIPAddress(void) 00240 { 00241 uint32_t n1, n2, n3, n4; 00242 00243 if (!(_parser.send("AT+S.STS=ip_ipaddr") 00244 && _parser.recv("# ip_ipaddr = %u.%u.%u.%u", &n1, &n2, &n3, &n4) 00245 && _parser.recv("OK"))) { 00246 debug_if(dbg_on, "SPWF> getIPAddress error\r\n"); 00247 return 0; 00248 } 00249 00250 sprintf((char*)_ip_buffer,"%u.%u.%u.%u", n1, n2, n3, n4); 00251 00252 return _ip_buffer; 00253 } 00254 00255 const char *SPWFSA01::getMACAddress(void) 00256 { 00257 uint32_t n1, n2, n3, n4, n5, n6; 00258 00259 if (!(_parser.send("AT+S.GCFG=nv_wifi_macaddr") 00260 && _parser.recv("# nv_wifi_macaddr = %x:%x:%x:%x:%x:%x", &n1, &n2, &n3, &n4, &n5, &n6) 00261 && _parser.recv("OK"))) { 00262 debug_if(dbg_on, "SPWF> getMACAddress error\r\n"); 00263 return 0; 00264 } 00265 00266 sprintf((char*)_mac_buffer,"%02X:%02X:%02X:%02X:%02X:%02X", n1, n2, n3, n4, n5, n6); 00267 00268 return _mac_buffer; 00269 } 00270 00271 bool SPWFSA01::isConnected(void) 00272 { 00273 return getIPAddress() != 0; 00274 } 00275 00276 bool SPWFSA01::open(const char *type, int* id, const char* addr, int port) 00277 { 00278 Timer timer; 00279 timer.start(); 00280 00281 if(!_parser.send("AT+S.SOCKON=%s,%d,%s,ind", addr, port, type)) 00282 { 00283 debug_if(dbg_on, "SPWF> error opening socket\r\n"); 00284 return false; 00285 } 00286 00287 while(1) 00288 { 00289 if( _parser.recv(" ID: %d", id) 00290 && _parser.recv("OK")) 00291 break; 00292 00293 if (timer.read_ms() > SPWFSA01_CONNECT_TIMEOUT) { 00294 return false; 00295 } 00296 00297 //TODO:implement time-out functionality in case of no response 00298 //if(timeout) return false; 00299 //TODO: deal with errors like "ERROR: Failed to resolve name" 00300 //TODO: deal with errors like "ERROR: Data mode not available" 00301 } 00302 00303 return true; 00304 } 00305 00306 bool SPWFSA01::send(int id, const void *data, uint32_t amount) 00307 { 00308 char _buf[18]; 00309 00310 setTimeout(SPWFSA01_SEND_TIMEOUT); 00311 00312 sprintf((char*)_buf,"AT+S.SOCKW=%d,%d\r", id, amount); 00313 00314 //May take a second try if device is busy 00315 for (unsigned i = 0; i < 2; i++) { 00316 if (_parser.write((char*)_buf, strlen(_buf)) >=0 00317 && _parser.write((char*)data, (int)amount) >= 0 00318 && _parser.recv("OK")) { 00319 return true; 00320 } 00321 } 00322 00323 return false; 00324 } 00325 00326 /* 00327 int32_t SPWFSA01::recv(int id, void *data, uint32_t amount) 00328 { 00329 uint32_t recv_amount; 00330 int recv_id; 00331 bool wind_recv = true; 00332 00333 if (!(_parser.recv("+WIND:55:Pending Data:%d:%u", &recv_id, &recv_amount) 00334 && recv_id == id 00335 && recv_amount <= amount 00336 && recv_amount%730 00337 && _parser.send("AT+S.SOCKQ=%d", id) //send a query (will be required for secure sockets) 00338 && _parser.recv(" DATALEN: %u", &recv_amount) 00339 && _parser.recv("OK") 00340 && recv_amount > 0 00341 && _parser.send("AT+S.SOCKR=%d,%d", id, recv_amount) 00342 && (_parser.read((char*)data, recv_amount) >0) 00343 && _parser.recv("OK"))) { 00344 if(!(recv_amount%730)) 00345 { 00346 // receive all the WIND messages 00347 do { 00348 if (!(_parser.recv("+WIND:55:Pending Data:%d:%u", &recv_id, &recv_amount) 00349 && recv_id == id 00350 && recv_amount <= amount 00351 && recv_amount > 0)) 00352 wind_recv = false; 00353 } while (!(recv_amount%730) && wind_recv); 00354 00355 // Read all the data pending on a socket 00356 if(!( recv_amount > 0 00357 && _parser.send("AT+S.SOCKR=%d,%d", id, recv_amount) 00358 && (_parser.read((char*)data, recv_amount) >0) 00359 && _parser.recv("OK"))) { 00360 return -1; 00361 } 00362 } 00363 else { 00364 return -2; 00365 } 00366 } 00367 return recv_amount; 00368 } 00369 */ 00370 00371 int32_t SPWFSA01::recv(int id, void *data, uint32_t amount) 00372 { 00373 Timer timer; 00374 timer.start(); 00375 00376 uint32_t recv_amount=0; 00377 int recv_id; 00378 00379 if(!(_parser.recv("+WIND:55:Pending Data:%d:", &recv_id))) { 00380 //do nothing; 00381 debug_if(dbg_on, "SPWF> WIND:55 Timeout\r\n"); 00382 } 00383 00384 while(!recv_amount) { 00385 if(!(_parser.send("AT+S.SOCKQ=%d", id) //send a query (will be required for secure sockets) 00386 && _parser.recv(" DATALEN: %u", &recv_amount) 00387 && _parser.recv("OK"))) { 00388 return -2; 00389 } 00390 if (timer.read_ms() > SPWFSA01_SOCKQ_TIMEOUT) { 00391 return -1; 00392 } 00393 } 00394 if(recv_amount > amount) 00395 recv_amount = amount; 00396 00397 _parser.flush(); 00398 if(!(_parser.send("AT+S.SOCKR=%d,%d", id, recv_amount))) 00399 return -2; 00400 00401 /* only when the data recv is greater than 3 bytes */ 00402 if(recv_amount > 3) { 00403 /* look for WIND messages in data */ 00404 00405 // get first 3 bytes of data 00406 for(int i=0;i<3;i++) { 00407 int c = -1; 00408 while(c < 0) { 00409 c = _parser.getc(); 00410 } 00411 ((char *)data)[i] = c; 00412 } 00413 00414 /* 0xD: \r && 0xA: \n */ 00415 if(((char *)data)[0] == 0xD 00416 &&((char *)data)[1] == 0xA 00417 &&((char *)data)[2] == '+') { 00418 ((char *)data)[0] = 0; 00419 while(((char *)data)[0] != 0xA) { 00420 ((char *)data)[0] = _parser.getc(); 00421 } 00422 00423 // complete data is yet to be read 00424 if(!((_parser.read((char*)data, recv_amount) >0) 00425 && _parser.recv("OK"))) { 00426 return -2; 00427 } 00428 } 00429 else { 00430 // data left to be read is 3 bytes less. 00431 if(!((_parser.read((char*)data+3, recv_amount-3) >0) 00432 && _parser.recv("OK"))) { 00433 return -2; 00434 } 00435 } 00436 } 00437 else { 00438 if(!((_parser.read((char*)data, recv_amount) >0) 00439 && _parser.recv("OK"))) { 00440 return -2; 00441 } 00442 } 00443 return recv_amount; 00444 } 00445 00446 bool SPWFSA01::close(int id) 00447 { 00448 //May take a second try if device is busy or error is returned 00449 for (unsigned i = 0; i < 2; i++) { 00450 if (_parser.send("AT+S.SOCKC=%d", id) 00451 && _parser.recv("OK")) { 00452 return true; 00453 } 00454 else 00455 { 00456 if(_parser.recv("ERROR: Pending data")) 00457 debug_if(dbg_on, "SPWF> ERROR!!!!\r\n"); 00458 return false; 00459 } 00460 //TODO: Deal with "ERROR: Pending data" (Closing a socket with pending data) 00461 } 00462 00463 return false; 00464 } 00465 00466 void SPWFSA01::setTimeout(uint32_t timeout_ms) 00467 { 00468 _parser.setTimeout(timeout_ms); 00469 } 00470 00471 bool SPWFSA01::readable() 00472 { 00473 return _serial.readable(); 00474 } 00475 00476 bool SPWFSA01::writeable() 00477 { 00478 return _serial.writeable(); 00479 }
Generated on Tue Jul 19 2022 11:37:49 by
1.7.2
