Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: FXOS8700CQ MODSERIAL mbed
Fork of Avnet_ATT_Cellular_IOT by
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 }
Generated on Tue Jul 12 2022 17:36:29 by
1.7.2
