Bowen Feng / Mbed 2 deprecated Hiking_Pal

Dependencies:   FXOS8700CQ MODSERIAL mbed

Fork of Avnet_ATT_Cellular_IOT by Avnet

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers cell_modem.cpp Source File

cell_modem.cpp

00001 /* ===================================================================
00002 Copyright c 2016, AVNET Inc.  
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, 
00011 software distributed under the License is distributed on an 
00012 "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 
00013 either express or implied. See the License for the specific 
00014 language governing permissions and limitations under the License.
00015 
00016 ======================================================================== */
00017 
00018 #include "mbed.h"
00019 #include <cctype>
00020 #include <string>
00021 
00022 #include "config_me.h"
00023 #include "wnc_control.h"
00024 #include "hardware.h"
00025 
00026 #define MDM_DBG_OFF                             0
00027 #define MDM_DBG_AT_CMDS                         (1 << 0)
00028 int mdm_dbgmask = MDM_DBG_OFF;
00029 
00030 #define WNC_WAIT_FOR_AT_CMD_MS 40
00031 
00032 DigitalOut  mdm_uart2_rx_boot_mode_sel(PTC17);  // on powerup, 0 = boot mode, 1 = normal boot
00033 DigitalOut  mdm_power_on(PTB9);                 // 0 = turn modem on, 1 = turn modem off (should be held high for >5 seconds to cycle modem)
00034 DigitalOut  mdm_wakeup_in(PTC2);                // 0 = let modem sleep, 1 = keep modem awake -- Note: pulled high on shield
00035 
00036 DigitalOut  mdm_reset(PTC12);                   // active high      
00037 
00038 DigitalOut  shield_3v3_1v8_sig_trans_ena(PTC4); // 0 = disabled (all signals high impedence, 1 = translation active
00039 DigitalOut  mdm_uart1_cts(PTD0);
00040 
00041 #define TOUPPER(a) (a) //toupper(a)
00042 
00043 const char ok_str[] = "OK";
00044 const char error_str[] = "ERROR";
00045 
00046 #define MDM_OK                                  0
00047 #define MDM_ERR_TIMEOUT                         -1
00048 
00049 #define MAX_AT_RSP_LEN                          255
00050 
00051 ssize_t mdm_getline(char *buff, size_t size, int timeout_ms) {
00052     int cin = -1;
00053     int cin_last;
00054     
00055     if (NULL == buff || size == 0) {
00056         return -1;
00057     }
00058 
00059     size_t len = 0;
00060     Timer timer;
00061     timer.start();
00062     while ((len < (size-1)) && (timer.read_ms() < timeout_ms)) {
00063         if (mdm.readable()) {
00064             cin_last = cin;
00065             cin = mdm.getc();
00066             if (isprint(cin)) {
00067                 buff[len++] = (char)cin;
00068                 continue;
00069             } else if (('\r' == cin_last) && ('\n' == cin)) {
00070                 break;
00071             }
00072         }
00073 //        wait_ms(1);
00074     }
00075     buff[len] = (char)NULL;
00076     
00077     return len;
00078 }
00079 
00080 int mdm_sendAtCmd(const char *cmd, const char **rsp_list, int timeout_ms) {
00081     // Per WNC wait:
00082     wait_ms(WNC_WAIT_FOR_AT_CMD_MS);
00083 
00084     if (cmd && strlen(cmd) > 0) {
00085         if (mdm_dbgmask & MDM_DBG_AT_CMDS) {
00086             PRINTF(MAG "ATCMD: " DEF "--> " GRN "%s" DEF "\n", cmd);
00087         }
00088         mdm.puts(cmd);
00089         mdm.puts("\r\n");
00090     }
00091 
00092     if (rsp_list) {
00093         Timer   timer;
00094         char    rsp[MAX_AT_RSP_LEN+1];
00095         int     len;
00096         
00097         timer.start();
00098         while (timer.read_ms() < timeout_ms) {
00099             len = mdm_getline(rsp, sizeof(rsp), timeout_ms - timer.read_ms());
00100             
00101             if (len < 0)
00102                 return MDM_ERR_TIMEOUT;
00103 
00104             if (len == 0)
00105                 continue;
00106                 
00107             if (mdm_dbgmask & MDM_DBG_AT_CMDS) {
00108                 PRINTF(MAG "ATRSP: " DEF "<-- " CYN "%s" DEF "\n", rsp);
00109             }
00110         
00111             if (rsp_list) {
00112                 int rsp_idx = 0;
00113                 while (rsp_list[rsp_idx]) {
00114                     if (strcasecmp(rsp, rsp_list[rsp_idx]) == 0) {
00115                         return rsp_idx;
00116                     } else if (strncmp(rsp, "@EXTERR", 7) == 0){
00117                         pc.printf("----- We got EXTERR ---\r\n");
00118                         return 2;    
00119                     } else if (strncmp(rsp, "+CME", 4) == 0){
00120                         return 3;    
00121                     } 
00122                     rsp_idx++;
00123                 }
00124             }
00125         }
00126         return MDM_ERR_TIMEOUT;
00127     }
00128     return MDM_OK;
00129 }
00130 
00131 int mdm_init(void) {
00132     // Hard reset the modem (doesn't go through
00133     // the signal level translator)
00134     mdm_reset = 0;
00135 
00136     // disable signal level translator (necessary
00137     // for the modem to boot properly).  All signals
00138     // except mdm_reset go through the level translator
00139     // and have internal pull-up/down in the module. While
00140     // the level translator is disabled, these pins will
00141     // be in the correct state.  
00142     shield_3v3_1v8_sig_trans_ena = 0;
00143 
00144     // While the level translator is disabled and ouptut pins
00145     // are tristated, make sure the inputs are in the same state
00146     // as the WNC Module pins so that when the level translator is
00147     // enabled, there are no differences.
00148     mdm_uart2_rx_boot_mode_sel = 1;   // UART2_RX should be high
00149     mdm_power_on = 0;                 // powr_on should be low
00150     mdm_wakeup_in = 1;                // wake-up should be high
00151     mdm_uart1_cts = 0;                // indicate that it is ok to send
00152 
00153    // Now, wait for the WNC Module to perform its initial boot correctly
00154     wait(1.0);
00155   
00156     // The WNC module initializes comms at 115200 8N1 so set it up
00157      mdm.baud(115200);
00158     
00159     //Now, enable the level translator, the input pins should now be the
00160     //same as how the M14A module is driving them with internal pull ups/downs.
00161     //When enabled, there will be no changes in these 4 pins...
00162     shield_3v3_1v8_sig_trans_ena = 1;
00163 
00164     // Now, give the modem 60 seconds to start responding by
00165     // sending simple 'AT' commands to modem once per second.
00166     Timer timer;
00167     timer.start();
00168     while (timer.read() < 60) {
00169         const char * rsp_lst[] = { ok_str, error_str, NULL };
00170         int rc = mdm_sendAtCmd("AT", rsp_lst, 500);
00171         if (rc == 0)
00172             return true; //timer.read();
00173         wait_ms(1000 - (timer.read_ms() % 1000));
00174         PRINTF("\r%d",timer.read_ms()/1000);
00175     }
00176     return false;       
00177 }
00178 
00179 int mdm_sendAtCmdRsp(const char *cmd, const char **rsp_list, int timeout_ms, string * rsp, int * len) {
00180     static char cmd_buf[3200];  // Need enough room for the WNC sockreads (over 3000 chars)
00181     size_t n = strlen(cmd);
00182 
00183     // Per WNC wait:
00184     wait_ms(WNC_WAIT_FOR_AT_CMD_MS);
00185 
00186     if (cmd && n > 0) {
00187         if (mdm_dbgmask & MDM_DBG_AT_CMDS) {
00188             PRINTF(MAG "ATCMD: " DEF "--> " GRN "%s" DEF "\n", cmd);
00189         }
00190 //        mdm.puts(cmd);
00191 //        mdm.puts("\r\n");
00192         while (n--) {
00193             mdm.putc(*cmd++);
00194             wait_us(1000);
00195         };
00196         mdm.putc('\r');
00197         wait_us(1000);
00198         mdm.putc('\n');
00199         wait_us(1000);
00200     }
00201 
00202     if (rsp_list) {
00203         rsp->erase(); // Clean up from prior cmd response
00204         *len = 0;
00205         Timer   timer;
00206         timer.start();
00207         while (timer.read_ms() < timeout_ms) {
00208             int lenCmd = mdm_getline(cmd_buf, sizeof(cmd_buf), timeout_ms - timer.read_ms());
00209 
00210             if (lenCmd == 0)
00211                 continue;
00212 
00213             if (lenCmd < 0)
00214                 return MDM_ERR_TIMEOUT;
00215             else {
00216                 *len += lenCmd;
00217                 *rsp += cmd_buf;
00218             }
00219 
00220             if (mdm_dbgmask & MDM_DBG_AT_CMDS) {
00221                 PRINTF(MAG "ATRSP: " DEF "<-- " CYN "%s" DEF "\n", cmd_buf);
00222             }
00223 
00224             int rsp_idx = 0;
00225             // TODO: Test if @EXTERR:<code>
00226             while (rsp_list[rsp_idx]) {
00227                 if (strcasecmp(cmd_buf, rsp_list[rsp_idx]) == 0) {
00228                     return rsp_idx;
00229                 } else if (strncmp(cmd_buf, "@EXTERR", 7) == 0){
00230                     PRINTF("----- We got EXTERR ---\r\n");
00231                     return 2;    
00232                 } else if (strncmp(cmd_buf, "+CME", 4) == 0){
00233                     return 3;    
00234                 } 
00235                 rsp_idx++;
00236             }
00237         }
00238         return MDM_ERR_TIMEOUT;
00239     }
00240 
00241     return MDM_OK;
00242 }
00243 
00244 void reinitialize_mdm(void)
00245 {
00246     // Initialize the modem
00247     PRINTF(GRN "Modem RE-initializing..." DEF "\r\n");
00248     if (!mdm_init()) {
00249         PRINTF(RED "\n\rModem RE-initialization failed!" DEF "\n");
00250     }
00251     PRINTF("\r\n");
00252 }
00253 // These are built on the fly
00254 string MyServerIpAddress;
00255 string MySocketData;
00256 
00257 //********************************************************************************************************************************************
00258 //* Process JSON response messages
00259 //********************************************************************************************************************************************
00260 bool extract_JSON(char* search_field, char* found_string)
00261 {
00262     char* beginquote;
00263     char* endquote;
00264     beginquote = strchr(search_field, '{'); //start of JSON
00265     endquote = strchr(search_field, '}'); //end of JSON
00266     if (beginquote)
00267     {
00268         uint16_t ifoundlen;
00269         if (endquote)
00270         {
00271             ifoundlen = (uint16_t) (endquote - beginquote) + 1;
00272             strncpy(found_string, beginquote, ifoundlen );
00273             found_string[ifoundlen] = 0; //null terminate
00274             return true;
00275         }
00276         else
00277         {
00278             endquote = strchr(search_field, '\0'); //end of string...  sometimes the end bracket is missing
00279             ifoundlen = (uint16_t) (endquote - beginquote) + 1;
00280             strncpy(found_string, beginquote, ifoundlen );
00281             found_string[ifoundlen] = 0; //null terminate
00282             return false;
00283         }
00284     }
00285     else
00286     {
00287         return false;
00288     }
00289 } //extract_JSON
00290 
00291 int cell_modem_init() 
00292 {
00293     int i;
00294 
00295     pc.baud(115200);
00296      // Initialize the modem
00297     PRINTF(GRN "Modem initializing... will take up to 60 seconds" DEF "\r\n");
00298     do {
00299         i=mdm_init();
00300         if (!i) {
00301             PRINTF(RED "Modem initialization failed!" DEF "\n");
00302         }
00303     } while (!i);
00304     
00305     //Software init
00306     software_init_mdm();
00307  
00308     // Resolve URL to IP address to connect to
00309     resolve_mdm();
00310     // Open the socket (connect to the server)
00311     sockopen_mdm();
00312     return (0);
00313 }
00314 
00315 int cell_modem_Sendreceive(char* tx_string, char* rx_string) 
00316 {
00317     int iStatus = 0; //error by default
00318     PRINTF(DEF "\r\n");
00319     PRINTF(BLU "Sending to modem : %s" DEF "\r\n", &tx_string[0]); 
00320     sockwrite_mdm(&tx_string[0]);
00321     if (sockread_mdm(&MySocketData, 1024, 20))
00322     {
00323         PRINTF(DEF "\r\n");
00324         PRINTF(YEL "Read back : %s" DEF "\r\n", MySocketData.c_str());
00325         char stringToCharBuf[BUF_SIZE_FOR_N_MAX_SOCKREAD*MAX_WNC_SOCKREAD_PAYLOAD+1]; // WNC can return max of 1500 (per sockread)
00326         if ((MySocketData.length() + 1) < sizeof(stringToCharBuf))
00327         {
00328             strcpy(stringToCharBuf, MySocketData.c_str());
00329             char* body = strstr(stringToCharBuf, "\r\n\r\n");
00330             sprintf(rx_string, body + 4);
00331             iStatus = 1; //all good
00332         }
00333         else
00334         {
00335             PRINTF(RED "BUFFER not big enough for sock data!" DEF "\r\n");
00336         }
00337     }
00338     else
00339     {
00340         PRINTF(RED "No response..." DEF "\r\n");
00341     }
00342     return iStatus;
00343 }
00344 
00345 void display_wnc_firmware_rev(void)
00346 {
00347     display_modem_firmware_version();
00348 }