Lauri Pirttiaho / SPWF01SA-lapi-1

Dependencies:   ATParser

Dependents:   X_NUCLEO_IDW01M1v2-lapi-1

Fork of SPWF01SA by ST

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers SPWFSA01.cpp Source File

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 }