GSMA version
Dependencies: FXOS8700CQ mbed sfh7779
Fork of StarterKit by
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 }
Generated on Tue Jul 12 2022 20:08:47 by 1.7.2