AT Parser and bufferedSerial based SPWF library

Dependencies:   ATParser

Dependents:   X_NUCLEO_IDW01M1v2

Fork of SPWF01SA by ST Expansion SW Team

Revision:
0:9e5d98ceea74
Child:
1:becf69a794fb
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SPWFSA01.cpp	Thu Jun 30 06:04:46 2016 +0000
@@ -0,0 +1,297 @@
+/* SPWFInterface Example
+ * Copyright (c) 2015 ARM Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "SPWFSA01.h"
+
+#define SPWFSA01_CONNECT_TIMEOUT 15000
+#define SPWFSA01_SEND_TIMEOUT    500
+#define SPWFSA01_RECV_TIMEOUT    1000//some commands like AT&F/W takes some time to get the result back!
+#define SPWFSA01_MISC_TIMEOUT    500
+
+SPWFSA01::SPWFSA01(PinName tx, PinName rx, bool debug)
+    : _serial(tx, rx, 1024), _parser(_serial),
+      _wakeup(PC_8, PIN_INPUT, PullNone, 0), _reset(PC_12, PIN_INPUT, PullNone, 1)
+      //Pin PC_8 is wakeup pin
+      //Pin PA_12 is reset pin
+{
+    _serial.baud(115200);
+    _reset.output();
+    _wakeup.output();
+    _parser.debugOn(debug);
+}
+
+bool SPWFSA01::startup(int mode)
+{
+    setTimeout(SPWFSA01_RECV_TIMEOUT);
+    
+    /*Test module before reset*/
+    waitSPWFReady();
+    /*Reset module*/
+    reset();
+     
+    /*set local echo to 0*/
+    if(!(_parser.send("AT+S.SCFG=localecho1,%d", 0) && _parser.recv("OK"))) 
+        {
+            printf("\r\nerror local echo set\n");
+            return false;
+        }   
+    /*reset factory settings*/
+    if(!(_parser.send("AT&F") && _parser.recv("OK"))) 
+        {
+            printf("\r\nerror AT&F\n");
+            return false;
+        }
+
+    /*set idle mode (0->idle, 1->STA,3->miniAP, 2->IBSS)*/
+    if(!(_parser.send("AT+S.SCFG=wifi_mode,%d\r", mode) && _parser.recv("OK")))
+        {
+            printf("\r\nerror wifi mode set\n");
+            return false;
+        } 
+
+    /* save current setting in flash */
+    if(!(_parser.send("AT&W") && _parser.recv("OK")))
+        {
+            printf("\r\nerror AT&W\n");
+            return false;
+        }
+        
+    /*reset again and send AT command and check for result (AT->OK)*/
+    reset();
+        
+    return true;    
+}
+
+bool SPWFSA01::hw_reset(void)
+{    
+    /* reset the pin PC12 */  
+    _reset.write(0);
+    wait_ms(200);
+    _reset.write(1); 
+    wait_ms(100);
+    return 1;
+}
+
+bool SPWFSA01::reset(void)
+{
+    if(!_parser.send("AT+CFUN=1")) return false;
+    while(1) {
+        if (_parser.recv("+WIND:32:WiFi Hardware Started")) {
+            return true;
+        }
+    }
+}
+
+void SPWFSA01::waitSPWFReady(void)
+{
+    //wait_ms(200);
+    while(1) 
+        if(_parser.send("AT") && _parser.recv("OK"))
+            //till we get OK from AT command
+            //printf("\r\nwaiting for reset to complete..\n");
+            return;
+                
+}
+
+/* Security Mode
+    None          = 0, 
+    WEP           = 1,
+    WPA_Personal  = 2,
+*/
+bool SPWFSA01::connect(const char *ap, const char *passPhrase, int securityMode)
+{
+    uint32_t n1, n2, n3, n4;
+    
+    //AT+S.SCFG=wifi_wpa_psk_text,%s\r
+    if(!(_parser.send("AT+S.SCFG=wifi_wpa_psk_text,%s", passPhrase) && _parser.recv("OK"))) 
+        {
+            printf("\r\nerror pass set\n");
+            return false;
+        } 
+    //AT+S.SSIDTXT=%s\r
+    if(!(_parser.send("AT+S.SSIDTXT=%s", ap) && _parser.recv("OK"))) 
+        {
+            printf("\r\nerror ssid set\n");
+            return false;
+        }
+    //AT+S.SCFG=wifi_priv_mode,%d\r
+    if(!(_parser.send("AT+S.SCFG=wifi_priv_mode,%d", securityMode) && _parser.recv("OK"))) 
+        {
+            printf("\r\nerror security mode set\n");
+            return false;
+        } 
+    //"AT+S.SCFG=wifi_mode,%d\r"
+    /*set idle mode (0->idle, 1->STA,3->miniAP, 2->IBSS)*/
+    if(!(_parser.send("AT+S.SCFG=wifi_mode,%d\r", 1) && _parser.recv("OK")))
+        {
+            printf("\r\nerror wifi mode set\n");
+            return false;
+        }
+    //AT&W
+    /* save current setting in flash */
+    if(!(_parser.send("AT&W") && _parser.recv("OK")))
+        {
+            printf("\r\nerror AT&W\n");
+            return false;
+        }
+    //reset module
+    reset();
+    
+    while(1)
+        if((_parser.recv("+WIND:24:WiFi Up:%u.%u.%u.%u",&n1, &n2, &n3, &n4)))
+        //if((_parser.recv("+WIND:24:WiFi Up:%[^\\r]",_ip_buffer)))
+            {
+                break;
+            }
+            
+    printf("\r\nip address:%u.%u.%u.%u\n",n1, n2, n3, n4);
+        
+    return true;
+}
+
+bool SPWFSA01::disconnect(void)
+{
+    //"AT+S.SCFG=wifi_mode,%d\r"
+    /*set idle mode (0->idle, 1->STA,3->miniAP, 2->IBSS)*/
+    if(!(_parser.send("AT+S.SCFG=wifi_mode,%d\r", 0) && _parser.recv("OK")))
+        {
+            printf("\r\nerror wifi mode set\n");
+            return false;
+        }
+    //AT&W
+    /* save current setting in flash */
+    if(!(_parser.send("AT&W") && _parser.recv("OK")))
+        {
+            printf("\r\nerror AT&W\n");
+            return false;
+        }
+    //reset module
+    reset();
+    return true;
+}
+
+bool SPWFSA01::dhcp(bool enabled, int mode)
+{
+    //only 3 valid modes
+    if(mode < 0 || mode > 2) {
+        return false;
+    }
+
+    return _parser.send("AT+CWDHCP=%d,%d", enabled?1:0, mode)
+        && _parser.recv("OK");
+}
+
+
+const char *SPWFSA01::getIPAddress(void)
+{
+    uint32_t n1, n2, n3, n4;
+    
+    if (!(_parser.send("AT+S.STS=ip_ipaddr")
+        && _parser.recv("ip_ipaddr = %u.%u.%u.%u", &n1, &n2, &n3, &n4)
+        && _parser.recv("OK"))) {
+            printf("\r\ngetIPAddress error\n");
+        return 0;
+    }
+    printf("\r\nip address:%u.%u.%u.%u\n",n1, n2, n3, n4);
+    sprintf((char*)_ip_buffer,"%u.%u.%u.%u", n1, n2, n3, n4);
+
+    return _ip_buffer;
+}
+
+const char *SPWFSA01::getMACAddress(void)
+{
+    if (!(_parser.send("AT+CIFSR")
+        && _parser.recv("+CIFSR:STAMAC,\"%[^\"]\"", _mac_buffer)
+        && _parser.recv("OK"))) {
+        return 0;
+    }
+
+    return _mac_buffer;
+}
+
+bool SPWFSA01::isConnected(void)
+{
+    return getIPAddress() != 0;
+}
+
+bool SPWFSA01::open(const char *type, int id, const char* addr, int port)
+{
+    //IDs only 0-4
+    if(id > 4) {
+        return false;
+    }
+
+    return _parser.send("AT+CIPSTART=%d,\"%s\",\"%s\",%d", id, type, addr, port)
+        && _parser.recv("OK");
+}
+
+bool SPWFSA01::send(int id, const void *data, uint32_t amount)
+{
+    //May take a second try if device is busy
+    for (unsigned i = 0; i < 2; i++) {
+        if (_parser.send("AT+CIPSEND=%d,%d", id, amount)
+            && _parser.recv(">")
+            && _parser.write((char*)data, (int)amount) >= 0) {
+            return true;
+        }
+    }
+
+    return false;
+}
+
+int32_t SPWFSA01::recv(int id, void *data, uint32_t amount)
+{
+    uint32_t recv_amount;
+    int recv_id;
+
+    if (!(_parser.recv("+IPD,%d,%d:", &recv_id, &recv_amount)
+        && recv_id == id
+        && recv_amount <= amount
+        && _parser.read((char*)data, recv_amount)
+        && _parser.recv("OK"))) {
+        return -1;
+    }
+
+    return recv_amount;
+}
+
+bool SPWFSA01::close(int id)
+{
+    //May take a second try if device is busy
+    for (unsigned i = 0; i < 2; i++) {
+        if (_parser.send("AT+CIPCLOSE=%d", id)
+            && _parser.recv("OK")) {
+            return true;
+        }
+    }
+
+    return false;
+}
+
+void SPWFSA01::setTimeout(uint32_t timeout_ms)
+{
+    _parser.setTimeout(timeout_ms);
+}
+
+bool SPWFSA01::readable()
+{
+    return _serial.readable();
+}
+
+bool SPWFSA01::writeable()
+{
+    return _serial.writeable();
+}