GSMA version

Dependencies:   FXOS8700CQ mbed sfh7779

Fork of StarterKit by Rick McConney

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers Wnc.cpp Source File

Wnc.cpp

00001 #include "Wnc.h"
00002 #include "mbed.h"
00003 #include <cctype>
00004 #include "config_me.h"
00005 #include "SerialBuffered.h"
00006 
00007 
00008 extern Serial pc;
00009 
00010 DigitalOut  mdm_uart2_rx_boot_mode_sel(PTC17);  // on powerup, 0 = boot mode, 1 = normal boot
00011 DigitalOut  mdm_power_on(PTB9);                 // 0 = turn modem on, 1 = turn modem off (should be held high for >5 seconds to cycle modem)
00012 DigitalInOut  mdm_wakeup_in(PTC2);                // 0 = let modem sleep, 1 = keep modem awake -- Note: pulled high on shield
00013 
00014 DigitalOut  mdm_reset(PTC12);                   // active high      
00015 
00016 DigitalOut  shield_3v3_1v8_sig_trans_ena(PTC4); // 0 = disabled (all signals high impedence, 1 = translation active
00017 DigitalOut  mdm_uart1_cts(PTD0);
00018 
00019 DigitalOut uart1Rts(PTD1);
00020 
00021 SerialBuffered mdm(PTD3, PTD2, 512);
00022 
00023 int t3412Timer = 4*60*60;
00024 int t3324Timer = 20;
00025 bool powerSave = false;
00026 
00027 
00028 Wnc::Wnc(void)
00029 {
00030 }
00031 
00032 void Wnc::checkPassthrough()
00033 {
00034     if(pc.readable())
00035     {
00036         if(pc.getc() == '~')
00037         passthrough();
00038     }
00039 }
00040                
00041 
00042 void Wnc::passthrough()
00043 {
00044     pc.printf(">>\r\n");
00045     while(1)
00046     {
00047         char c;
00048         if(pc.readable())
00049         {
00050             c =  pc.getc();
00051             pc.putc(c);
00052             if(c == '~')
00053             {
00054                 pc.printf("exit\r\n");
00055                  break;
00056             }
00057             else if(c == '<')
00058             {
00059                 
00060                  mdm_wakeup_in = 0;
00061                  pc.printf("sleep\r\n");
00062             }
00063             else if(c == '>')
00064             {
00065                  mdm_wakeup_in = 1;
00066                  pc.printf("wake\r\n");
00067             }
00068             else if(c == '}')
00069             {
00070                  mdm_uart2_rx_boot_mode_sel = 1;
00071                  pc.printf("rx hi\r\n");
00072             }
00073             else if(c == '{')
00074             {
00075                  mdm_uart2_rx_boot_mode_sel = 0;
00076                  pc.printf("rx low\r\n");
00077             }
00078 
00079             else if(c == '^')
00080             {
00081                 pc.printf("reboot\r\n");
00082                 NVIC_SystemReset();
00083             }
00084             else
00085             {
00086                
00087                 mdm.putc(c);
00088             }
00089         }
00090         if(mdm.readable())
00091             pc.putc(mdm.getc());
00092     }
00093 }
00094 
00095 bool Wnc::isPowerSaveOn()
00096 {
00097     return powerSave;
00098 }
00099 
00100 void Wnc::resumePowerSave()
00101 {
00102     mdm_wakeup_in = 0;
00103 }
00104 
00105 int Wnc::gett3412Timer()
00106 {
00107     return t3412Timer;
00108 }
00109 
00110 int Wnc::gett3324Timer()
00111 {
00112     return t3324Timer;
00113 }
00114 
00115 char* Wnc::read(int timeout_ms)
00116 {
00117     static char response[3200]; 
00118     int len = 0;
00119     char c;
00120     
00121     if(timeout_ms > 0) // read until timeout or OK
00122     {
00123         Timer timer;
00124         timer.start();
00125         while ((len < (3200-1)) && (timer.read_ms() < timeout_ms)) {
00126             if (mdm.readable()) {
00127                 c = mdm.getc();
00128                 // replace \r\n to make debug messages more compact
00129                 if(c == '\r') c = ' ';
00130                 if(c == '\n') c = ' ';
00131                 
00132                 response[len++] = c;
00133                 if(len>1 && response[len-2] == 'O' && response[len-1] == 'K')
00134                     break;
00135 
00136             }
00137         }
00138     }
00139  
00140     response[len] = (char)NULL;
00141     pc.printf("{%d %s}\r\n",len,response);
00142     return response;
00143 }
00144 
00145 char* Wnc::send(const char *cmd, int timeout_ms)
00146 {
00147     char *reply;
00148     
00149     while (mdm.readable()) {
00150          mdm.getc();
00151     }
00152         
00153     int tries = 4;
00154     while(tries > 0)
00155     {
00156         tries--;        
00157         pc.printf("\r\n<%s>",cmd);
00158         const char *pt = cmd;
00159         size_t n = strlen(cmd);
00160         while (n--) {
00161             mdm.putc(*pt++);
00162         };
00163         mdm.putc('\r');
00164         mdm.putc('\n');
00165         reply = read(timeout_ms);
00166         if(strlen(reply) > 0 && strstr(reply,"OK") !=0)
00167             break; 
00168         checkPassthrough();
00169     }
00170     return reply;
00171 }
00172 
00173 bool Wnc::isModemResponding()
00174 {    
00175     char *reply = send("AT",WNC_WAIT_TIME_MS);
00176     if(strlen(reply) > 0 && strstr(reply,"OK") !=0)
00177         return true;
00178     return false;
00179 }
00180 
00181 void Wnc::setIn()
00182 {
00183     mdm_wakeup_in.input();
00184 }
00185 
00186 void Wnc::toggleWake()
00187 {
00188     mdm_wakeup_in = 0;
00189     wait_ms(2000);  
00190     mdm_wakeup_in = 0; 
00191 }
00192 
00193 bool Wnc::init(void) {
00194     uart1Rts = 0;
00195     mdm_wakeup_in.output();
00196     // disable signal level translator (necessary
00197     // for the modem to boot properly)
00198     shield_3v3_1v8_sig_trans_ena = 0;
00199 
00200     // Hard reset the modem (doesn't go through
00201     // the signal level translator)
00202     mdm_reset = 1;
00203     
00204    // wait a moment for the modem to react
00205     wait_ms(10);
00206     
00207     // Let modem boot
00208     mdm_reset = 0;
00209     
00210     // wait a moment for the modem to react
00211     wait(1.0);
00212     
00213     // power modem on //off
00214     mdm_power_on = 0; //1;
00215     
00216     // insure modem boots into normal operating mode
00217     // and does not go to sleep when powered on
00218     mdm_uart2_rx_boot_mode_sel = 1;
00219     mdm_wakeup_in = 1;
00220     
00221     // initialze comm with the modem
00222     mdm.baud(115200);
00223     // clear out potential garbage
00224     while (mdm.readable())
00225       mdm.getc();
00226 
00227     mdm_uart1_cts = 0;
00228     
00229     // wait a moment for the modem to react to signal
00230     // conditions while the level translator is disabled
00231     // (sorry, don't have enough information to know
00232     // what exactly the modem is doing with the current
00233     // pin settings)
00234     wait(1.0);
00235 
00236     // enable the signal level translator to start
00237     // modem reset process (modem will be powered down)
00238     shield_3v3_1v8_sig_trans_ena = 1;
00239     
00240     // Give the modem 60 secons to start responding by
00241     // sending simple 'AT' commands to modem once per second.
00242     Timer timer;
00243     timer.start();
00244     while (timer.read() < 60) {
00245         SetLedColor(0x1); //red     
00246         if(isModemResponding())
00247         {
00248             SetLedColor(0);
00249             //mdm_uart2_rx_boot_mode_sel = 0;
00250             return true; 
00251         }
00252         SetLedColor(0); //off
00253         wait_ms(1000 - (timer.read_ms() % 1000));
00254         pc.printf("\r%d",timer.read_ms()/1000);
00255          
00256     }
00257     return false;       
00258 }
00259 int Wnc::secToTau(int time)
00260 {
00261     /*
00262     0 - value is incremented in multiples of 10 minutes
00263     1 - value is incremented in multiples of 1 hour
00264     2 - value is incremented in multiples of 10 hours
00265     3 - value is incremented in multiples of 2 seconds
00266     4 - value is incremented in multiples of 30 seconds
00267     5 - value is incremented in multiples of 1 minute
00268 */
00269     if(time/2 < 32)
00270     {
00271         return (0x3<<5)+time/2;
00272     }
00273     else if(time/30 < 32)
00274     {
00275         return (0x4<<5)+time/30;
00276     }
00277     else if(time/60 < 32)
00278     {
00279         return (0x5<<5)+time/60;
00280     }
00281     else if(time/3600 < 32)
00282     {
00283         return (0x1<<5)+time/3600;
00284     }
00285     else if(time/36000 < 32)
00286     {
00287         return (0x2<<5)+time/36000;
00288     }
00289     else
00290         return (0x7<<5);
00291         
00292 
00293 }
00294 int Wnc::secToActivity(int time)
00295 {
00296     /*
00297     0 - value is incremented in multiples of 2 seconds
00298     1 - value is incremented in multiples of 1 minute
00299     2 - value is incremented in multiples of decihours
00300     7 - value indicates that the timer is deactivated.
00301     */
00302     if(time/2 < 32)
00303     {
00304         return (0x0<<5)+time/2;
00305     }
00306     else if(time/60 < 32)
00307     {
00308         return (0x1<<5)+time/60;
00309     }
00310     else if(time/36000 < 32)
00311     {
00312         return (0x2<<5)+time/36000;
00313     }
00314     else
00315         return (0x7<<5);
00316 
00317 }    
00318 void Wnc::setPowerSave(bool on,int t3412,int t3324)
00319 {
00320     if(on)
00321     {
00322         t3412Timer = t3412;
00323         t3324Timer = t3324;
00324         int tau = secToTau(t3412);
00325         int activity = secToActivity(t3324);
00326         mdm_wakeup_in = 0; //allow power sleep mode
00327         powerSave = true;
00328         char cmd[32];
00329         snprintf(cmd,sizeof(cmd),"AT+CPSMS=1,,,%d,%d",tau,activity);
00330         send(cmd,  WNC_WAIT_TIME_MS);
00331     }
00332     else
00333     {
00334         mdm_wakeup_in = 1; //disallow power sleep mode
00335         powerSave = false;
00336         send("AT+CPSMS=0",  WNC_WAIT_TIME_MS);
00337     }
00338 }
00339 
00340 char* Wnc::getIccid()
00341 {
00342     static char iccidBuf[32];
00343     iccidBuf[0] = NULL;
00344     char* reply = send("AT%CCID",500);
00345     int index = 0;
00346     int begin = -1;
00347     int i = 0;
00348 
00349     while (reply[index]) { // While there are more characters to process...
00350         if (begin == -1 && isdigit(reply[index])) { // Upon finding a digit, ...
00351             begin = index;
00352         }
00353         if(begin != -1)
00354         { 
00355             if(isdigit(reply[index]))
00356             { 
00357                 iccidBuf[i++] = reply[index];
00358             }
00359             else
00360             {
00361                 iccidBuf[i++] = NULL;
00362                 return iccidBuf;
00363             }
00364         }
00365         index++;
00366     }
00367     return iccidBuf;
00368 }
00369 
00370 void Wnc::wakeFromPowerSave()
00371 {
00372     mdm_wakeup_in = 1;
00373     pc.printf("wake from power save\r\n");
00374 }
00375 
00376 bool Wnc::cmdFailed(char* reply,char* msg)
00377 {
00378     if(strstr(reply,"OK") > 0)
00379         return false;
00380     pc.printf("%s\r\n",msg);
00381     return true;
00382 }
00383     
00384 bool Wnc::startInternet()
00385 {
00386   char *reply;
00387   reply = send("ATE1",WNC_WAIT_TIME_MS);           // Echo ON
00388   char apn [32];
00389   snprintf(apn,sizeof(apn),"AT%%PDNSET=1,%s,IP",MY_APN_STR);
00390 
00391   reply = send(apn, 2*WNC_WAIT_TIME_MS); // Set APN, cmd seems to take a little longer sometimes
00392   if(cmdFailed(reply,"Failed to set APN")) return false;
00393 
00394   reply = send("AT%PDNSET?",  WNC_WAIT_TIME_MS);
00395   
00396   //pc.printf("Wiating ...\r\n");
00397   //wait(10);
00398   
00399   reply = send("AT@INTERNET=1",  WNC_WAIT_TIME_MS);  // Internet services enabled
00400   if(cmdFailed(reply,"Failed to start INTERNET"))
00401   {
00402     return false;
00403   }
00404   reply = send("AT@SOCKDIAL=1",  4*WNC_WAIT_TIME_MS);
00405   if(cmdFailed(reply,"SOCKDIAL Failed")) 
00406   {
00407      // passthrough();
00408       return false;
00409   }
00410   return true;
00411 }
00412 
00413 char* Wnc::ping(char* ip)
00414 {
00415     char cmd[32];
00416     snprintf(cmd,sizeof(cmd),"AT@PINGREQ=\"%s\"",ip);
00417     return send(cmd,WNC_WAIT_TIME_MS);
00418 }
00419 
00420 bool Wnc::connect(char* ip, int port)
00421 {
00422   char *reply;
00423 
00424     for(int i = 0;i<2;i++)
00425     {
00426        if(isModemResponding()) 
00427          break;
00428        wait(0.5);
00429     }
00430     
00431     if(isModemResponding())
00432     {
00433         reply = send("AT@SOCKCREAT=1", WNC_WAIT_TIME_MS);
00434         if(cmdFailed(reply,"Socket Create Failed")) return false;
00435     }
00436     else
00437     {
00438         pc.printf("Error Modem not responding\r\n");
00439         return false;
00440     }
00441 
00442     
00443     char cmd[64];
00444 
00445     snprintf(cmd,sizeof(cmd),"AT@SOCKCONN=1,\"%s\",%d",ip,port);
00446     reply = send(cmd,12*WNC_WAIT_TIME_MS);
00447     if(cmdFailed(reply,"Socket Connect Failed")) return false;
00448     
00449     for(int i = 0;i<10;i++)
00450     {
00451         reply = send("AT+CREG?",WNC_WAIT_TIME_MS);
00452         if(strlen(reply) > 0 && strstr(reply,"2,1") != 0)
00453         {
00454              pc.printf("Connected %s\r\n",reply);
00455             return true;
00456         }
00457         else
00458         {
00459             pc.printf("Unconnected %s\r\n",reply);
00460         }
00461         wait(1);
00462     }
00463     return false;
00464 }
00465 
00466 void Wnc::disconnect()
00467 {
00468      send("AT@SOCKCLOSE=1", WNC_WAIT_TIME_MS);
00469 }
00470 
00471 char* Wnc::encode(int value, char* result, int base)                                                                                                          
00472 {                                                                                                                                                        
00473     // check that the base if valid                                                                                                                      
00474     if ( base < 2 || base > 36 ) {                                                                                                                       
00475         *result = '\0';                                                                                                                                  
00476         return result;                                                                                                                                   
00477     }                                                                                                                                                    
00478  
00479     char* ptr = result, *ptr1 = result, tmp_char;                                                                                                        
00480     int tmp_value;                                                                                                                                       
00481  
00482     do {                                                                                                                                                 
00483         tmp_value = value;                                                                                                                               
00484         value /= base;                                                                                                                                   
00485         *ptr++ = "zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz"[35 + (tmp_value - value * base)];                             
00486     } while ( value );                                                                                                                                   
00487  
00488     // Apply negative sign                                                                                                                               
00489     if ( tmp_value < 0 )                                                                                                                                 
00490     *ptr++ = '-';                                                                                                                                    
00491     *ptr-- = '\0';                                                                                                                                       
00492  
00493     while ( ptr1 < ptr ) {                                                                                                                               
00494     tmp_char = *ptr;                                                                                                                                 
00495     *ptr-- = *ptr1;                                                                                                                                  
00496     *ptr1++ = tmp_char;                                                                                                                              
00497     }                                                                                                                                                    
00498     return result;                                                                                                                                       
00499 }
00500 
00501 bool Wnc::writeSocket(const char * s)
00502 {
00503 
00504   char num2str[6];
00505   size_t sLen = strlen(s);
00506   if (sLen <= 99999)
00507   {
00508     char cmd[sLen*2+32];
00509     int index = snprintf(cmd,sizeof(cmd),"AT@SOCKWRITE=1,%d,\"",sLen);
00510 
00511     while(*s != '\0')
00512     {
00513       encode((int)*s++, num2str, 16);
00514       // Always 2-digit ascii hex:
00515       if (strlen(num2str) == 1)
00516       {
00517         num2str[2] = '\0';
00518         num2str[1] = num2str[0];
00519         num2str[0] = '0';
00520       }
00521       cmd[index++] = num2str[0];
00522       cmd[index++] = num2str[1];
00523     }
00524     cmd[index++] =  '"';
00525     cmd[index] = '\0';
00526     char* reply = send(cmd, WNC_WAIT_TIME_MS);
00527     if(cmdFailed(reply,"Send Failed")) return false;
00528     return true;
00529   }
00530   else
00531   {
00532     pc.puts("sockwrite Err, string to long\r\n");
00533     return false;
00534   }
00535 
00536 }
00537 
00538 int Wnc::hex_to_int(char A)
00539 {
00540     return (A > '9')? (A &~ 0x20) - 'A' + 10: (A - '0');
00541 }
00542 
00543 int Wnc::hex_to_ascii(char h, char l)
00544 {  
00545     return hex_to_int(h) * 16 + hex_to_int(l);      
00546 }
00547 
00548 int Wnc::indexOf(char* str, char c)
00549 {
00550     int index = 0;
00551     while(str[index] != 0)
00552     {
00553         if(str[index] == c)
00554             return index;
00555         index++;
00556     }
00557     return -1;
00558 }
00559 
00560 char* Wnc::readSocket()
00561 {
00562 
00563      static char data[1000];
00564      int i = 0;
00565      char *reply;
00566      reply = send("AT@SOCKREAD=1,1024",1000);
00567      if(strlen(reply) > 0)
00568      {
00569         int pos_start = indexOf(reply,'"');
00570  
00571         if(pos_start > 0)
00572         {
00573             pos_start+=1;
00574             int length  = indexOf(&reply[pos_start],'"');
00575 
00576             if(length > 0)
00577             {
00578                 char hi;
00579                 char low;
00580                 for(i = 0; i < length; i++){
00581                     if(i % 2 != 0){
00582                         low = reply[pos_start++];
00583                         data[i/2] = (char) hex_to_ascii(hi,low);
00584                     }else{
00585                         hi = reply[pos_start++];
00586                     }
00587                 }
00588                 data[length/2] = NULL;
00589             }
00590         }
00591     }
00592     data[i] = NULL;
00593     return data;
00594 }
00595 
00596 char* Wnc::resolveDn(const char* name)
00597 {
00598     char cmd[64];
00599 
00600     snprintf(cmd,sizeof(cmd),"AT@DNSRESVDON=\"%s\"",name);
00601     char* reply = send(cmd,12*WNC_WAIT_TIME_MS);
00602     static char ipBuf[32];
00603     ipBuf[0] = NULL; 
00604     int index = 0;
00605     int begin = -1;
00606     int i = 0;
00607 
00608     while (reply[index]) { // While there are more characters to process...
00609         if (begin == -1 && isdigit(reply[index])) { // Upon finding a digit, ...
00610             begin = index;
00611         }
00612         if(begin != -1)
00613         { 
00614             if(isdigit(reply[index]) || reply[index] == '.')
00615             { 
00616                 ipBuf[i++] = reply[index];
00617             }
00618             else
00619             {
00620                 ipBuf[i++] = NULL;
00621                 return ipBuf;
00622             }
00623         }
00624         index++;
00625     }
00626     return ipBuf; 
00627 }