GSMA version

Dependencies:   FXOS8700CQ mbed sfh7779

Fork of StarterKit by Rick McConney

Revision:
42:8500f0cb2ea5
Child:
43:3979ea0a2df3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Wnc.cpp	Fri Oct 07 17:01:22 2016 +0000
@@ -0,0 +1,508 @@
+#include "Wnc.h"
+#include "mbed.h"
+#include <cctype>
+#include <string>
+#include "config_me.h"
+#include "SerialBuffered.h"
+
+
+extern Serial pc;
+
+DigitalOut  mdm_uart2_rx_boot_mode_sel(PTC17);  // on powerup, 0 = boot mode, 1 = normal boot
+DigitalOut  mdm_power_on(PTB9);                 // 0 = turn modem on, 1 = turn modem off (should be held high for >5 seconds to cycle modem)
+DigitalInOut  mdm_wakeup_in(PTC2);                // 0 = let modem sleep, 1 = keep modem awake -- Note: pulled high on shield
+
+DigitalOut  mdm_reset(PTC12);                   // active high      
+
+DigitalOut  shield_3v3_1v8_sig_trans_ena(PTC4); // 0 = disabled (all signals high impedence, 1 = translation active
+DigitalOut  mdm_uart1_cts(PTD0);
+
+SerialBuffered mdm(PTD3, PTD2, 512);
+
+bool powerSave = false;
+
+Wnc::Wnc(void)
+{
+}
+
+void Wnc::checkPassthrough()
+{
+    if(pc.readable())
+    {
+        if(pc.getc() == '~')
+        passthrough();
+    }
+}
+               
+
+void Wnc::passthrough()
+{
+    pc.printf(">>\r\n");
+    while(1)
+    {
+        char c;
+        if(pc.readable())
+        {
+            c =  pc.getc();
+            pc.putc(c);
+            if(c == '~')
+            {
+                pc.printf("exit\r\n");
+                 break;
+            }
+            else if(c == '<')
+            {
+                
+                 mdm_wakeup_in = 0;
+                 pc.printf("sleep\r\n");
+            }
+            else if(c == '>')
+            {
+                 mdm_wakeup_in = 1;
+                 pc.printf("wake\r\n");
+            }
+            else if(c == '^')
+            {
+                pc.printf("reboot\r\n");
+                NVIC_SystemReset();
+            }
+            else
+            {
+               
+                mdm.putc(c);
+            }
+        }
+        if(mdm.readable())
+            pc.putc(mdm.getc());
+    }
+}
+
+bool Wnc::isPowerSaveOn()
+{
+    return powerSave;
+}
+
+void Wnc::resumePowerSave()
+{
+    mdm_wakeup_in = 0;
+}
+
+char* Wnc::read(int timeout_ms)
+{
+    static char response[3200]; 
+    int len = 0;
+    
+    if(timeout_ms > 0) // read until timeout or OK
+    {
+        Timer timer;
+        timer.start();
+        while ((len < (3200-1)) && (timer.read_ms() < timeout_ms)) {
+            if (mdm.readable()) {
+                response[len++] = mdm.getc();
+                if(len>1 && response[len-2] == 'O' && response[len-1] == 'K')
+                    break;
+            }
+        }
+    }
+ 
+    response[len] = (char)NULL;
+    pc.printf("{%s}\r\n",response);
+    return response;
+}
+
+char* Wnc::send(const char *cmd, int timeout_ms)
+{
+    char* reply;
+        
+    int tries = 4;
+    while(tries > 0)
+    {
+        tries--;        
+        pc.printf("\r\n<%s>",cmd);
+        const char *pt = cmd;
+        size_t n = strlen(cmd);
+        while (n--) {
+            mdm.putc(*pt++);
+        };
+        mdm.putc('\r');
+        mdm.putc('\n');
+        reply = read(timeout_ms);
+        if(strlen(reply) > 0 && strstr(reply,"OK") !=0)
+            break; 
+        checkPassthrough();
+    }
+    return reply;
+}
+
+bool Wnc::isModemResponding()
+{    
+    char *reply = send("AT",WNC_WAIT_TIME_MS);
+    if(strlen(reply) > 0 && strstr(reply,"OK") !=0)
+        return true;
+    return false;
+}
+
+void Wnc::setIn()
+{
+    mdm_wakeup_in.input();
+}
+
+void Wnc::toggleWake()
+{
+    mdm_wakeup_in = 0;
+    wait_ms(2000);  
+    mdm_wakeup_in = 0; 
+}
+
+int Wnc::init(void) {
+    mdm_wakeup_in.output();
+    // disable signal level translator (necessary
+    // for the modem to boot properly)
+    shield_3v3_1v8_sig_trans_ena = 0;
+
+    // Hard reset the modem (doesn't go through
+    // the signal level translator)
+    mdm_reset = 1;
+    
+   // wait a moment for the modem to react
+    wait_ms(10);
+    
+    // Let modem boot
+    mdm_reset = 0;
+    
+    // wait a moment for the modem to react
+    wait(1.0);
+    
+    // power modem on //off
+    mdm_power_on = 0; //1;
+    
+    // insure modem boots into normal operating mode
+    // and does not go to sleep when powered on
+    mdm_uart2_rx_boot_mode_sel = 1;
+    mdm_wakeup_in = 1;
+    
+    // initialze comm with the modem
+    mdm.baud(115200);
+    // clear out potential garbage
+    while (mdm.readable())
+      mdm.getc();
+
+    mdm_uart1_cts = 0;
+    
+    // wait a moment for the modem to react to signal
+    // conditions while the level translator is disabled
+    // (sorry, don't have enough information to know
+    // what exactly the modem is doing with the current
+    // pin settings)
+    wait(1.0);
+
+    // enable the signal level translator to start
+    // modem reset process (modem will be powered down)
+    shield_3v3_1v8_sig_trans_ena = 1;
+    
+    // Give the modem 60 secons to start responding by
+    // sending simple 'AT' commands to modem once per second.
+    Timer timer;
+    timer.start();
+    while (timer.read() < 60) {
+        SetLedColor(0x1); //red     
+        if(isModemResponding())
+        {
+            SetLedColor(0);
+            return true; 
+        }
+        SetLedColor(0); //off
+        wait_ms(1000 - (timer.read_ms() % 1000));
+        pc.printf("\r%d",timer.read_ms()/1000);
+         
+    }
+    return false;       
+}
+int Wnc::secToTau(int time)
+{
+    /*
+    0 - value is incremented in multiples of 10 minutes
+    1 - value is incremented in multiples of 1 hour
+    2 - value is incremented in multiples of 10 hours
+    3 - value is incremented in multiples of 2 seconds
+    4 - value is incremented in multiples of 30 seconds
+    5 - value is incremented in multiples of 1 minute
+*/
+    if(time/2 < 32)
+    {
+        return (0x3<<5)+time/2;
+    }
+    else if(time/30 < 32)
+    {
+        return (0x4<<5)+time/30;
+    }
+    else if(time/60 < 32)
+    {
+        return (0x5<<5)+time/60;
+    }
+    else if(time/3600 < 32)
+    {
+        return (0x1<<5)+time/3600;
+    }
+    else if(time/36000 < 32)
+    {
+        return (0x2<<5)+time/36000;
+    }
+    else
+        return (0x7<<5);
+        
+
+}
+int Wnc::secToActivity(int time)
+{
+    /*
+    0 - value is incremented in multiples of 2 seconds
+    1 - value is incremented in multiples of 1 minute
+    2 - value is incremented in multiples of decihours
+    7 - value indicates that the timer is deactivated.
+    */
+    if(time/2 < 32)
+    {
+        return (0x0<<5)+time/2;
+    }
+    else if(time/60 < 32)
+    {
+        return (0x1<<5)+time/60;
+    }
+    else if(time/36000 < 32)
+    {
+        return (0x2<<5)+time/36000;
+    }
+    else
+        return (0x7<<5);
+
+}    
+void Wnc::setPowerSave(bool on,int t3412,int t3324)
+{
+    if(on)
+    {
+        int tau = secToTau(t3412);
+        int activity = secToActivity(t3324);
+        mdm_wakeup_in = 0; //allow power sleep mode
+        powerSave = true;
+        char cmd[32];
+        sprintf(cmd,"AT+CPSMS=1,,,%d,%d",tau,activity);
+        send(cmd,  WNC_WAIT_TIME_MS);
+    }
+    else
+    {
+        mdm_wakeup_in = 1; //disallow power sleep mode
+        powerSave = false;
+        send("AT+CPSMS=0",  WNC_WAIT_TIME_MS);
+    }
+}
+
+char* Wnc::getIccid()
+{
+    static char iccidBuf[32];
+    iccidBuf[0] = NULL;
+    char* reply = send("AT%CCID",500);
+    int index = 0;
+    int begin = -1;
+    int i = 0;
+
+    while (reply[index]) { // While there are more characters to process...
+        if (begin == -1 && isdigit(reply[index])) { // Upon finding a digit, ...
+            begin = index;
+        }
+        if(begin != -1)
+        { 
+            if(isdigit(reply[index]))
+            { 
+                iccidBuf[i++] = reply[index];
+            }
+            else
+            {
+                iccidBuf[i++] = NULL;
+                return iccidBuf;
+            }
+        }
+        index++;
+    }
+    return iccidBuf;
+}
+
+void Wnc::wakeFromPowerSave()
+{
+    char *reply;
+    mdm_wakeup_in = 1;
+    reply = send("AT+CFUN=1", WNC_WAIT_TIME_MS);
+    reply = send("AT%CMATT=1",  WNC_WAIT_TIME_MS);
+    wait(2); // wait to attach
+    reply = send("AT+CREG?",  WNC_WAIT_TIME_MS);
+    reply = send("AT@INTERNET=1",  WNC_WAIT_TIME_MS);  // Internet services enabled
+    reply = send("AT@SOCKDIAL=1",  WNC_WAIT_TIME_MS);
+    
+
+}
+
+void Wnc::startInternet()
+{
+  char *reply;
+  reply = send("ATE1",WNC_WAIT_TIME_MS);           // Echo ON
+  char apn [32];
+  sprintf(apn,"AT%%PDNSET=1,%s,IP",MY_APN_STR);
+
+  reply = send(apn, 2*WNC_WAIT_TIME_MS); // Set APN, cmd seems to take a little longer sometimes
+  reply = send("AT+CREG?",  WNC_WAIT_TIME_MS);
+  reply = send("AT@INTERNET=1",  WNC_WAIT_TIME_MS);  // Internet services enabled
+  reply = send("AT@SOCKDIAL=1",  WNC_WAIT_TIME_MS);
+}
+
+char* Wnc::ping(char* ip)
+{
+    char cmd[32];
+    sprintf(cmd,"AT@PINGREQ=\"%s\"",ip);
+    return send(cmd,WNC_WAIT_TIME_MS);
+}
+// AT@SOCKCONN=1,"108.244.165.22",5005"
+bool Wnc::connect(char* ip, int port)
+{
+  char *reply;
+
+    reply = send("AT@SOCKCREAT=1", WNC_WAIT_TIME_MS);
+    if(strlen(reply) == 0 || strstr(reply,"OK") ==0)
+        return false;
+    char cmd[32];
+    sprintf(cmd,"AT@SOCKCONN=1,\"%s\",%d",ip,port);
+    reply = send(cmd,WNC_WAIT_TIME_MS);
+    if(strlen(reply) == 0 || strstr(reply,"OK") ==0)
+        return false;
+    return true;
+}
+
+void Wnc::disconnect()
+{
+     send("AT@SOCKCLOSE=1", WNC_WAIT_TIME_MS);
+}
+
+char* Wnc::encode(int value, char* result, int base)                                                                                                          
+{                                                                                                                                                        
+    // check that the base if valid                                                                                                                      
+    if ( base < 2 || base > 36 ) {                                                                                                                       
+        *result = '\0';                                                                                                                                  
+        return result;                                                                                                                                   
+    }                                                                                                                                                    
+ 
+    char* ptr = result, *ptr1 = result, tmp_char;                                                                                                        
+    int tmp_value;                                                                                                                                       
+ 
+    do {                                                                                                                                                 
+        tmp_value = value;                                                                                                                               
+        value /= base;                                                                                                                                   
+        *ptr++ = "zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz"[35 + (tmp_value - value * base)];                             
+    } while ( value );                                                                                                                                   
+ 
+    // Apply negative sign                                                                                                                               
+    if ( tmp_value < 0 )                                                                                                                                 
+    *ptr++ = '-';                                                                                                                                    
+    *ptr-- = '\0';                                                                                                                                       
+ 
+    while ( ptr1 < ptr ) {                                                                                                                               
+    tmp_char = *ptr;                                                                                                                                 
+    *ptr-- = *ptr1;                                                                                                                                  
+    *ptr1++ = tmp_char;                                                                                                                              
+    }                                                                                                                                                    
+    return result;                                                                                                                                       
+}
+
+char* Wnc::writeSocket(const char * s)
+{
+
+  char *reply;
+  char num2str[6];
+  size_t sLen = strlen(s);
+  if (sLen <= 99999)
+  {
+
+    string cmd_str("AT@SOCKWRITE=1,");
+    encode(sLen, num2str, 10);
+    cmd_str += num2str;
+    cmd_str += ",\"";
+    while(*s != '\0')
+    {
+      encode((int)*s++, num2str, 16);
+      // Always 2-digit ascii hex:
+      if (strlen(num2str) == 1)
+      {
+        num2str[2] = '\0';
+        num2str[1] = num2str[0];
+        num2str[0] = '0';
+      }
+      cmd_str += num2str;
+    }
+    cmd_str += "\"";
+    reply = send(cmd_str.c_str(), WNC_WAIT_TIME_MS);
+  }
+  else
+    pc.puts("sockwrite Err, string to long\r\n");
+  return NULL;
+}
+
+int Wnc::hex_to_int(char c){
+    if(c >=97)
+        c=c-32;
+    int first = c / 16 - 3;
+    int second = c % 16;
+    int result = first*10 + second;
+    if(result > 9) result--;
+    return result;
+}
+
+int Wnc::hex_to_ascii(char h, char l){
+        int high = hex_to_int(h) * 16;
+        int low = hex_to_int(l);
+        return high+low;       
+}
+
+int Wnc::indexOf(char* str, char c)
+{
+    int index = 0;
+    while(str[index] != 0)
+    {
+        if(str[index] == c)
+            return index;
+        index++;
+    }
+    return -1;
+}
+
+char* Wnc::readSocket()
+{
+
+     static char data[1000];
+     int i = 0;
+     char *reply;
+     reply = send("AT@SOCKREAD=1,1024",1000);
+     if(strlen(reply) > 0)
+     {
+        int pos_start = indexOf(reply,'"');
+ 
+        if(pos_start > 0)
+        {
+            pos_start+=1;
+            int length  = indexOf(&reply[pos_start],'"');
+
+            if(length > 0)
+            {
+                char hi;
+                char low;
+                for(i = 0; i < length; i++){
+                    if(i % 2 != 0){
+                        low = reply[pos_start++];
+                        data[i/2] = (char) hex_to_ascii(hi,low);
+                    }else{
+                        hi = reply[pos_start++];
+                    }
+                }
+            }
+        }
+    }
+    data[i] = NULL;
+    return data;
+}
\ No newline at end of file