Base class for the u-blox N2xx modems. Cannot be used standalone, only inherited by classes that do properly useful stuff. Or, to put it another way, if you are using any of the classes ending with 'n2xx', you will need this class also. Note: requires the N211 module firmware to be at least 06.57 A01.02.

Dependents:   example-ublox-cellular-interface HelloMQTT example-ublox-cellular-interface_r410M example-ublox-mbed-client ... more

Committer:
philware
Date:
Thu Sep 28 15:34:08 2017 +0100
Revision:
5:66451d314225
Parent:
3:39eadc84c5ac
Child:
6:377997119ef1
Added quotes around the nconfig command

Who changed what in which revision?

UserRevisionLine numberNew contents of line
philware 1:d4ff95ab40ae 1 /* Copyright (c) 2017 ublox Limited
philware 1:d4ff95ab40ae 2 *
philware 1:d4ff95ab40ae 3 * Licensed under the Apache License, Version 2.0 (the "License");
philware 1:d4ff95ab40ae 4 * you may not use this file except in compliance with the License.
philware 1:d4ff95ab40ae 5 * You may obtain a copy of the License at
philware 1:d4ff95ab40ae 6 *
philware 1:d4ff95ab40ae 7 * http://www.apache.org/licenses/LICENSE-2.0
philware 1:d4ff95ab40ae 8 *
philware 1:d4ff95ab40ae 9 * Unless required by applicable law or agreed to in writing, software
philware 1:d4ff95ab40ae 10 * distributed under the License is distributed on an "AS IS" BASIS,
philware 1:d4ff95ab40ae 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
philware 1:d4ff95ab40ae 12 * See the License for the specific language governing permissions and
philware 1:d4ff95ab40ae 13 * limitations under the License.
philware 1:d4ff95ab40ae 14 */
philware 1:d4ff95ab40ae 15
philware 1:d4ff95ab40ae 16 #include "UARTSerial.h"
philware 1:d4ff95ab40ae 17 #include "APN_db.h"
philware 1:d4ff95ab40ae 18 #include "UbloxCellularBaseN2xx.h"
philware 1:d4ff95ab40ae 19 #include "onboard_modem_api.h"
philware 1:d4ff95ab40ae 20 #ifdef FEATURE_COMMON_PAL
philware 1:d4ff95ab40ae 21 #include "mbed_trace.h"
philware 1:d4ff95ab40ae 22 #define TRACE_GROUP "UCB"
philware 1:d4ff95ab40ae 23 #else
philware 1:d4ff95ab40ae 24 #define tr_debug(format, ...) debug_if(_debug_trace_on, format "\n", ## __VA_ARGS__)
philware 1:d4ff95ab40ae 25 #define tr_info(format, ...) debug_if(_debug_trace_on, format "\n", ## __VA_ARGS__)
philware 1:d4ff95ab40ae 26 #define tr_warn(format, ...) debug_if(_debug_trace_on, format "\n", ## __VA_ARGS__)
philware 1:d4ff95ab40ae 27 #define tr_error(format, ...) debug_if(_debug_trace_on, format "\n", ## __VA_ARGS__)
philware 1:d4ff95ab40ae 28 #endif
philware 1:d4ff95ab40ae 29
philware 1:d4ff95ab40ae 30 #define ATOK _at->recv("OK")
philware 1:d4ff95ab40ae 31
philware 1:d4ff95ab40ae 32 /**********************************************************************
philware 1:d4ff95ab40ae 33 * PRIVATE METHODS
philware 1:d4ff95ab40ae 34 **********************************************************************/
philware 1:d4ff95ab40ae 35
philware 1:d4ff95ab40ae 36 void UbloxCellularBaseN2xx::set_nwk_reg_status_csd(int status)
philware 1:d4ff95ab40ae 37 {
philware 1:d4ff95ab40ae 38 switch (status) {
philware 1:d4ff95ab40ae 39 case CSD_NOT_REGISTERED_NOT_SEARCHING:
philware 1:d4ff95ab40ae 40 case CSD_NOT_REGISTERED_SEARCHING:
philware 1:d4ff95ab40ae 41 tr_info("Not (yet) registered for circuit switched service");
philware 1:d4ff95ab40ae 42 break;
philware 1:d4ff95ab40ae 43 case CSD_REGISTERED:
philware 1:d4ff95ab40ae 44 case CSD_REGISTERED_ROAMING:
philware 1:d4ff95ab40ae 45 tr_info("Registered for circuit switched service");
philware 1:d4ff95ab40ae 46 break;
philware 1:d4ff95ab40ae 47 case CSD_REGISTRATION_DENIED:
philware 1:d4ff95ab40ae 48 tr_info("Circuit switched service denied");
philware 1:d4ff95ab40ae 49 break;
philware 1:d4ff95ab40ae 50 case CSD_UNKNOWN_COVERAGE:
philware 1:d4ff95ab40ae 51 tr_info("Out of circuit switched service coverage");
philware 1:d4ff95ab40ae 52 break;
philware 1:d4ff95ab40ae 53 case CSD_SMS_ONLY:
philware 1:d4ff95ab40ae 54 tr_info("SMS service only");
philware 1:d4ff95ab40ae 55 break;
philware 1:d4ff95ab40ae 56 case CSD_SMS_ONLY_ROAMING:
philware 1:d4ff95ab40ae 57 tr_info("SMS service only");
philware 1:d4ff95ab40ae 58 break;
philware 1:d4ff95ab40ae 59 case CSD_CSFB_NOT_PREFERRED:
philware 1:d4ff95ab40ae 60 tr_info("Registered for circuit switched service with CSFB not preferred");
philware 1:d4ff95ab40ae 61 break;
philware 1:d4ff95ab40ae 62 default:
philware 1:d4ff95ab40ae 63 tr_info("Unknown circuit switched service registration status. %d", status);
philware 1:d4ff95ab40ae 64 break;
philware 1:d4ff95ab40ae 65 }
philware 1:d4ff95ab40ae 66
philware 1:d4ff95ab40ae 67 _dev_info.reg_status_csd = static_cast<NetworkRegistrationStatusCsd>(status);
philware 1:d4ff95ab40ae 68 }
philware 1:d4ff95ab40ae 69
philware 1:d4ff95ab40ae 70 void UbloxCellularBaseN2xx::set_nwk_reg_status_psd(int status)
philware 1:d4ff95ab40ae 71 {
philware 1:d4ff95ab40ae 72 switch (status) {
philware 1:d4ff95ab40ae 73 case PSD_NOT_REGISTERED_NOT_SEARCHING:
philware 1:d4ff95ab40ae 74 case PSD_NOT_REGISTERED_SEARCHING:
philware 1:d4ff95ab40ae 75 tr_info("Not (yet) registered for packet switched service");
philware 1:d4ff95ab40ae 76 break;
philware 1:d4ff95ab40ae 77 case PSD_REGISTERED:
philware 1:d4ff95ab40ae 78 case PSD_REGISTERED_ROAMING:
philware 1:d4ff95ab40ae 79 tr_info("Registered for packet switched service");
philware 1:d4ff95ab40ae 80 break;
philware 1:d4ff95ab40ae 81 case PSD_REGISTRATION_DENIED:
philware 1:d4ff95ab40ae 82 tr_info("Packet switched service denied");
philware 1:d4ff95ab40ae 83 break;
philware 1:d4ff95ab40ae 84 case PSD_UNKNOWN_COVERAGE:
philware 1:d4ff95ab40ae 85 tr_info("Out of packet switched service coverage");
philware 1:d4ff95ab40ae 86 break;
philware 1:d4ff95ab40ae 87 case PSD_EMERGENCY_SERVICES_ONLY:
philware 1:d4ff95ab40ae 88 tr_info("Limited access for packet switched service. Emergency use only.");
philware 1:d4ff95ab40ae 89 break;
philware 1:d4ff95ab40ae 90 default:
philware 1:d4ff95ab40ae 91 tr_info("Unknown packet switched service registration status. %d", status);
philware 1:d4ff95ab40ae 92 break;
philware 1:d4ff95ab40ae 93 }
philware 1:d4ff95ab40ae 94
philware 1:d4ff95ab40ae 95 _dev_info.reg_status_psd = static_cast<NetworkRegistrationStatusPsd>(status);
philware 1:d4ff95ab40ae 96 }
philware 1:d4ff95ab40ae 97
philware 1:d4ff95ab40ae 98 void UbloxCellularBaseN2xx::set_nwk_reg_status_eps(int status)
philware 1:d4ff95ab40ae 99 {
philware 1:d4ff95ab40ae 100 switch (status) {
philware 1:d4ff95ab40ae 101 case EPS_NOT_REGISTERED_NOT_SEARCHING:
philware 1:d4ff95ab40ae 102 case EPS_NOT_REGISTERED_SEARCHING:
philware 1:d4ff95ab40ae 103 tr_info("Not (yet) registered for EPS service");
philware 1:d4ff95ab40ae 104 break;
philware 1:d4ff95ab40ae 105 case EPS_REGISTERED:
philware 1:d4ff95ab40ae 106 case EPS_REGISTERED_ROAMING:
philware 1:d4ff95ab40ae 107 tr_info("Registered for EPS service");
philware 1:d4ff95ab40ae 108 break;
philware 1:d4ff95ab40ae 109 case EPS_REGISTRATION_DENIED:
philware 1:d4ff95ab40ae 110 tr_info("EPS service denied");
philware 1:d4ff95ab40ae 111 break;
philware 1:d4ff95ab40ae 112 case EPS_UNKNOWN_COVERAGE:
philware 1:d4ff95ab40ae 113 tr_info("Out of EPS service coverage");
philware 1:d4ff95ab40ae 114 break;
philware 1:d4ff95ab40ae 115 case EPS_EMERGENCY_SERVICES_ONLY:
philware 1:d4ff95ab40ae 116 tr_info("Limited access for EPS service. Emergency use only.");
philware 1:d4ff95ab40ae 117 break;
philware 1:d4ff95ab40ae 118 default:
philware 1:d4ff95ab40ae 119 tr_info("Unknown EPS service registration status. %d", status);
philware 1:d4ff95ab40ae 120 break;
philware 1:d4ff95ab40ae 121 }
philware 1:d4ff95ab40ae 122
philware 1:d4ff95ab40ae 123 _dev_info.reg_status_eps = static_cast<NetworkRegistrationStatusEps>(status);
philware 1:d4ff95ab40ae 124 }
philware 1:d4ff95ab40ae 125
philware 1:d4ff95ab40ae 126 void UbloxCellularBaseN2xx::set_rat(int AcTStatus)
philware 1:d4ff95ab40ae 127 {
philware 1:d4ff95ab40ae 128 switch (AcTStatus) {
philware 1:d4ff95ab40ae 129 case GSM:
philware 1:d4ff95ab40ae 130 case COMPACT_GSM:
philware 1:d4ff95ab40ae 131 tr_info("Connected in GSM");
philware 1:d4ff95ab40ae 132 break;
philware 1:d4ff95ab40ae 133 case UTRAN:
philware 1:d4ff95ab40ae 134 tr_info("Connected to UTRAN");
philware 1:d4ff95ab40ae 135 break;
philware 1:d4ff95ab40ae 136 case EDGE:
philware 1:d4ff95ab40ae 137 tr_info("Connected to EDGE");
philware 1:d4ff95ab40ae 138 break;
philware 1:d4ff95ab40ae 139 case HSDPA:
philware 1:d4ff95ab40ae 140 tr_info("Connected to HSDPA");
philware 1:d4ff95ab40ae 141 break;
philware 1:d4ff95ab40ae 142 case HSUPA:
philware 1:d4ff95ab40ae 143 tr_info("Connected to HSPA");
philware 1:d4ff95ab40ae 144 break;
philware 1:d4ff95ab40ae 145 case HSDPA_HSUPA:
philware 1:d4ff95ab40ae 146 tr_info("Connected to HDPA/HSPA");
philware 1:d4ff95ab40ae 147 break;
philware 1:d4ff95ab40ae 148 case LTE:
philware 1:d4ff95ab40ae 149 tr_info("Connected to LTE");
philware 1:d4ff95ab40ae 150 break;
philware 1:d4ff95ab40ae 151 default:
philware 1:d4ff95ab40ae 152 tr_info("Unknown RAT %d", AcTStatus);
philware 1:d4ff95ab40ae 153 break;
philware 1:d4ff95ab40ae 154 }
philware 1:d4ff95ab40ae 155
philware 1:d4ff95ab40ae 156 _dev_info.rat = static_cast<RadioAccessNetworkType>(AcTStatus);
philware 1:d4ff95ab40ae 157 }
philware 1:d4ff95ab40ae 158
philware 1:d4ff95ab40ae 159 bool UbloxCellularBaseN2xx::get_sara_n2xx_info()
philware 1:d4ff95ab40ae 160 {
philware 1:d4ff95ab40ae 161 return (
philware 1:d4ff95ab40ae 162 cgmi(_sara_n2xx_info.cgmi) &&
philware 1:d4ff95ab40ae 163 cgmm(_sara_n2xx_info.cgmm) &&
philware 1:d4ff95ab40ae 164 cgmr(_sara_n2xx_info.cgmr) &&
philware 1:d4ff95ab40ae 165 cgsn(1, _sara_n2xx_info.cgsn)
philware 1:d4ff95ab40ae 166 );
philware 1:d4ff95ab40ae 167 }
philware 1:d4ff95ab40ae 168
philware 1:d4ff95ab40ae 169 bool UbloxCellularBaseN2xx::at_req(const char *cmd, const char *recvFormat, const char *response) {
philware 1:d4ff95ab40ae 170 bool success = false;
philware 1:d4ff95ab40ae 171 LOCK();
philware 1:d4ff95ab40ae 172
philware 1:d4ff95ab40ae 173 MBED_ASSERT(_at != NULL);
philware 1:d4ff95ab40ae 174
philware 1:d4ff95ab40ae 175 tr_debug("ATREQ: %s => %s", cmd, recvFormat);
philware 1:d4ff95ab40ae 176 if(_at->send(cmd) && _at->recv(recvFormat, response) && ATOK) {
philware 1:d4ff95ab40ae 177 tr_debug("ATRESULT: %s", response);
philware 1:d4ff95ab40ae 178 success = true;
philware 1:d4ff95ab40ae 179 } else {
philware 1:d4ff95ab40ae 180 tr_error("ATRESULT: No Answer!");
philware 1:d4ff95ab40ae 181 }
philware 1:d4ff95ab40ae 182
philware 1:d4ff95ab40ae 183 UNLOCK();
philware 1:d4ff95ab40ae 184 return success;
philware 1:d4ff95ab40ae 185 }
philware 1:d4ff95ab40ae 186
philware 1:d4ff95ab40ae 187 bool UbloxCellularBaseN2xx::at_req(const char *cmd, const char *recvFormat, int *response) {
philware 1:d4ff95ab40ae 188 bool success = false;
philware 1:d4ff95ab40ae 189 LOCK();
philware 1:d4ff95ab40ae 190
philware 1:d4ff95ab40ae 191 MBED_ASSERT(_at != NULL);
philware 1:d4ff95ab40ae 192
philware 1:d4ff95ab40ae 193 tr_debug("ATREQ: %s => %s", cmd, recvFormat);
philware 1:d4ff95ab40ae 194 if(_at->send(cmd) && _at->recv(recvFormat, response) && ATOK) {
philware 1:d4ff95ab40ae 195 tr_debug("ATRESULT: %d", *response);
philware 1:d4ff95ab40ae 196 success = true;
philware 1:d4ff95ab40ae 197 } else {
philware 1:d4ff95ab40ae 198 tr_error("ATRESULT: No Answer!");
philware 1:d4ff95ab40ae 199 }
philware 1:d4ff95ab40ae 200
philware 1:d4ff95ab40ae 201 UNLOCK();
philware 1:d4ff95ab40ae 202 return success;
philware 1:d4ff95ab40ae 203 }
philware 1:d4ff95ab40ae 204
philware 1:d4ff95ab40ae 205 bool UbloxCellularBaseN2xx::at_send(const char *cmd) {
philware 1:d4ff95ab40ae 206 bool success = false;
philware 1:d4ff95ab40ae 207 LOCK();
philware 1:d4ff95ab40ae 208
philware 1:d4ff95ab40ae 209 MBED_ASSERT(_at != NULL);
philware 1:d4ff95ab40ae 210
philware 1:d4ff95ab40ae 211 tr_debug("ATSEND: %s", cmd);
philware 1:d4ff95ab40ae 212 if(_at->send(cmd) && ATOK) {
philware 1:d4ff95ab40ae 213 success = true;
philware 1:d4ff95ab40ae 214 } else {
philware 1:d4ff95ab40ae 215 tr_error("Failed to send %s", cmd);
philware 1:d4ff95ab40ae 216 }
philware 1:d4ff95ab40ae 217
philware 1:d4ff95ab40ae 218 UNLOCK();
philware 1:d4ff95ab40ae 219 return success;
philware 1:d4ff95ab40ae 220 }
philware 1:d4ff95ab40ae 221
philware 1:d4ff95ab40ae 222 bool UbloxCellularBaseN2xx::at_send(const char *cmd, int n) {
philware 1:d4ff95ab40ae 223 bool success = false;
philware 1:d4ff95ab40ae 224 LOCK();
philware 1:d4ff95ab40ae 225
philware 1:d4ff95ab40ae 226 MBED_ASSERT(_at != NULL);
philware 1:d4ff95ab40ae 227
philware 1:d4ff95ab40ae 228 tr_debug("ATSEND: %s, %d", cmd, n);
philware 1:d4ff95ab40ae 229 if(_at->send(cmd, n) && ATOK) {
philware 1:d4ff95ab40ae 230 success = true;
philware 1:d4ff95ab40ae 231 } else {
philware 1:d4ff95ab40ae 232 tr_error("Failed to send %s,%d", cmd, n);
philware 1:d4ff95ab40ae 233 }
philware 1:d4ff95ab40ae 234
philware 1:d4ff95ab40ae 235 UNLOCK();
philware 1:d4ff95ab40ae 236 return success;
philware 1:d4ff95ab40ae 237 }
philware 1:d4ff95ab40ae 238
philware 1:d4ff95ab40ae 239 bool UbloxCellularBaseN2xx::at_send(const char *cmd, const char *arg) {
philware 1:d4ff95ab40ae 240 bool success = false;
philware 1:d4ff95ab40ae 241 LOCK();
philware 1:d4ff95ab40ae 242
philware 1:d4ff95ab40ae 243 MBED_ASSERT(_at != NULL);
philware 1:d4ff95ab40ae 244
philware 1:d4ff95ab40ae 245 tr_debug("ATSEND: %s,%s", cmd, arg);
philware 1:d4ff95ab40ae 246 if(_at->send(cmd, arg) && ATOK) {
philware 1:d4ff95ab40ae 247 success = true;
philware 1:d4ff95ab40ae 248 } else {
philware 1:d4ff95ab40ae 249 tr_error("Failed to send %s,%s", cmd, arg);
philware 1:d4ff95ab40ae 250 }
philware 1:d4ff95ab40ae 251
philware 1:d4ff95ab40ae 252 UNLOCK();
philware 1:d4ff95ab40ae 253 return success;
philware 1:d4ff95ab40ae 254 }
philware 1:d4ff95ab40ae 255
philware 1:d4ff95ab40ae 256 bool UbloxCellularBaseN2xx::cgmi(const char *response)
philware 1:d4ff95ab40ae 257 {
philware 1:d4ff95ab40ae 258 return at_req("AT+CGMI", "%32[^\n]\n", response);
philware 1:d4ff95ab40ae 259 }
philware 1:d4ff95ab40ae 260
philware 1:d4ff95ab40ae 261 bool UbloxCellularBaseN2xx::cgmm(const char *response) {
philware 1:d4ff95ab40ae 262 return at_req("AT+CGMM", "%32[^\n]\n", response);
philware 1:d4ff95ab40ae 263 }
philware 1:d4ff95ab40ae 264
philware 1:d4ff95ab40ae 265 bool UbloxCellularBaseN2xx::cimi(const char *response) {
philware 1:d4ff95ab40ae 266 return at_req("AT+CIMI", "%32[^\n]\n", response);
philware 1:d4ff95ab40ae 267 }
philware 1:d4ff95ab40ae 268
philware 1:d4ff95ab40ae 269 bool UbloxCellularBaseN2xx::ccid(const char *response) {
philware 1:d4ff95ab40ae 270 return at_req("AT+NCCID", "+NCCID:%32[^\n]\n", response);
philware 1:d4ff95ab40ae 271 }
philware 1:d4ff95ab40ae 272
philware 1:d4ff95ab40ae 273 bool UbloxCellularBaseN2xx::cgmr(const char *response) {
philware 1:d4ff95ab40ae 274 return at_req("AT+CGMR", "%32[^\n]\n", response);
philware 1:d4ff95ab40ae 275 }
philware 1:d4ff95ab40ae 276
philware 1:d4ff95ab40ae 277 bool UbloxCellularBaseN2xx::cgsn(int snt, const char *response) {
philware 1:d4ff95ab40ae 278 char cmd[10];
philware 1:d4ff95ab40ae 279 sprintf(cmd, "AT+CGSN=%d", snt);
philware 1:d4ff95ab40ae 280
philware 1:d4ff95ab40ae 281 return at_req(cmd, "+CGSN:%32[^\n]\n", response);
philware 1:d4ff95ab40ae 282 }
philware 1:d4ff95ab40ae 283
philware 1:d4ff95ab40ae 284 bool UbloxCellularBaseN2xx::cereg(int n) {
philware 1:d4ff95ab40ae 285 return at_send("AT+CEREG=%d", n);
philware 1:d4ff95ab40ae 286 }
philware 1:d4ff95ab40ae 287
philware 1:d4ff95ab40ae 288 nsapi_error_t UbloxCellularBaseN2xx::get_cereg() {
philware 1:d4ff95ab40ae 289 nsapi_error_t r = NSAPI_ERROR_DEVICE_ERROR;
philware 1:d4ff95ab40ae 290 LOCK();
philware 1:d4ff95ab40ae 291
philware 1:d4ff95ab40ae 292 MBED_ASSERT(_at != NULL);
philware 1:d4ff95ab40ae 293
philware 1:d4ff95ab40ae 294 // The response will be handled by the CEREG URC, by waiting for the OK we know it has been serviced.
philware 1:d4ff95ab40ae 295 if (at_send("AT+CEREG?")){
philware 1:d4ff95ab40ae 296 r = _dev_info.reg_status_eps;
philware 1:d4ff95ab40ae 297 }
philware 1:d4ff95ab40ae 298
philware 1:d4ff95ab40ae 299 UNLOCK();
philware 1:d4ff95ab40ae 300 return r;
philware 1:d4ff95ab40ae 301 }
philware 1:d4ff95ab40ae 302
philware 1:d4ff95ab40ae 303 nsapi_error_t UbloxCellularBaseN2xx::get_cscon() {
philware 1:d4ff95ab40ae 304 char resp[3+1];
philware 1:d4ff95ab40ae 305
philware 1:d4ff95ab40ae 306 int n, stat;
philware 1:d4ff95ab40ae 307
philware 1:d4ff95ab40ae 308 if (at_req("AT+CSCON?", "+CSCON:%3[^\n]\n", resp) &&
philware 1:d4ff95ab40ae 309 sscanf(resp, "%d,%d", &n, &stat)) {
philware 1:d4ff95ab40ae 310 return stat;
philware 1:d4ff95ab40ae 311 }
philware 1:d4ff95ab40ae 312
philware 1:d4ff95ab40ae 313 return NSAPI_ERROR_DEVICE_ERROR;
philware 1:d4ff95ab40ae 314 }
philware 1:d4ff95ab40ae 315
philware 1:d4ff95ab40ae 316 nsapi_error_t UbloxCellularBaseN2xx::get_csq() {
philware 1:d4ff95ab40ae 317 char resp[5+1];
philware 1:d4ff95ab40ae 318 nsapi_error_t rssi = NSAPI_ERROR_DEVICE_ERROR;
philware 1:d4ff95ab40ae 319
philware 1:d4ff95ab40ae 320 LOCK();
philware 1:d4ff95ab40ae 321 MBED_ASSERT(_at != NULL);
philware 1:d4ff95ab40ae 322
philware 1:d4ff95ab40ae 323 if (at_req("AT+CSQ", "+CSQ:%5[^\n]\n", resp) &&
philware 1:d4ff95ab40ae 324 sscanf(resp, "%d,%*d", &rssi)) {
philware 1:d4ff95ab40ae 325 return rssi;
philware 1:d4ff95ab40ae 326 }
philware 1:d4ff95ab40ae 327
philware 1:d4ff95ab40ae 328 UNLOCK();
philware 1:d4ff95ab40ae 329 return rssi;
philware 1:d4ff95ab40ae 330 }
philware 1:d4ff95ab40ae 331
philware 1:d4ff95ab40ae 332 bool UbloxCellularBaseN2xx::cops(const char *plmn) {
philware 1:d4ff95ab40ae 333 return at_send("AT+COPS=1,2,\"%s\"", plmn);
philware 1:d4ff95ab40ae 334 }
philware 1:d4ff95ab40ae 335
philware 1:d4ff95ab40ae 336 bool UbloxCellularBaseN2xx::cops(int mode) {
philware 1:d4ff95ab40ae 337 return at_send("AT+COPS=%d", mode);
philware 1:d4ff95ab40ae 338 }
philware 1:d4ff95ab40ae 339
philware 1:d4ff95ab40ae 340 bool UbloxCellularBaseN2xx::get_cops(int *status) {
philware 1:d4ff95ab40ae 341 return at_req("AT+COPS?", "+COPS: %d", status);
philware 1:d4ff95ab40ae 342 }
philware 1:d4ff95ab40ae 343
philware 1:d4ff95ab40ae 344 bool UbloxCellularBaseN2xx::cfun(int mode) {
philware 1:d4ff95ab40ae 345 return at_send("AT+CFUN=%d", mode);
philware 1:d4ff95ab40ae 346 }
philware 1:d4ff95ab40ae 347
philware 1:d4ff95ab40ae 348 bool UbloxCellularBaseN2xx::reboot() {
philware 1:d4ff95ab40ae 349 return at_send("AT+NRB");
philware 1:d4ff95ab40ae 350 }
philware 1:d4ff95ab40ae 351
philware 1:d4ff95ab40ae 352 bool UbloxCellularBaseN2xx::auto_connect(bool state) {
philware 1:d4ff95ab40ae 353 return nconfig("AUTOCONNECT", state);
philware 1:d4ff95ab40ae 354 }
philware 1:d4ff95ab40ae 355
philware 1:d4ff95ab40ae 356 bool UbloxCellularBaseN2xx::nconfig(const char *name, bool state) {
philware 1:d4ff95ab40ae 357 char n[50];
philware 1:d4ff95ab40ae 358
philware 1:d4ff95ab40ae 359 if (state)
philware 5:66451d314225 360 sprintf(n, "AT+NCONFIG=\"%s\",\"TRUE\"", name);
philware 1:d4ff95ab40ae 361 else
philware 5:66451d314225 362 sprintf(n, "AT+NCONFIG=\"%s\",\"FALSE\"", name);
philware 1:d4ff95ab40ae 363
philware 1:d4ff95ab40ae 364 return at_send(n);
philware 1:d4ff95ab40ae 365 }
philware 1:d4ff95ab40ae 366
philware 1:d4ff95ab40ae 367 bool UbloxCellularBaseN2xx::get_iccid()
philware 1:d4ff95ab40ae 368 {
philware 1:d4ff95ab40ae 369 // Returns the ICCID (Integrated Circuit Card ID) of the SIM-card.
philware 1:d4ff95ab40ae 370 // ICCID is a serial number identifying the SIM.
philware 1:d4ff95ab40ae 371 // AT Command Manual UBX-13002752, section 4.12
philware 1:d4ff95ab40ae 372 bool success = ccid(_dev_info.iccid);
philware 1:d4ff95ab40ae 373 tr_info("DevInfo: ICCID=%s", _dev_info.iccid);
philware 1:d4ff95ab40ae 374
philware 1:d4ff95ab40ae 375 return success;
philware 1:d4ff95ab40ae 376 }
philware 1:d4ff95ab40ae 377
philware 1:d4ff95ab40ae 378 bool UbloxCellularBaseN2xx::get_imsi()
philware 1:d4ff95ab40ae 379 {
philware 1:d4ff95ab40ae 380 // International mobile subscriber identification
philware 1:d4ff95ab40ae 381 // AT Command Manual UBX-13002752, section 4.11
philware 1:d4ff95ab40ae 382 bool success = cimi(_dev_info.imsi);
philware 1:d4ff95ab40ae 383 tr_info("DevInfo: IMSI=%s", _dev_info.imsi);
philware 1:d4ff95ab40ae 384
philware 1:d4ff95ab40ae 385 return success;
philware 1:d4ff95ab40ae 386 }
philware 1:d4ff95ab40ae 387
philware 1:d4ff95ab40ae 388 bool UbloxCellularBaseN2xx::get_imei()
philware 1:d4ff95ab40ae 389 {
philware 1:d4ff95ab40ae 390 // International mobile equipment identifier
philware 1:d4ff95ab40ae 391 // AT Command Manual UBX-13002752, section 4.7
philware 1:d4ff95ab40ae 392 bool success = cgsn(1, _dev_info.imei);
philware 1:d4ff95ab40ae 393 tr_info("DevInfo: IMEI=%s", _dev_info.imei);
philware 1:d4ff95ab40ae 394
philware 1:d4ff95ab40ae 395 return success;
philware 1:d4ff95ab40ae 396 }
philware 1:d4ff95ab40ae 397
philware 1:d4ff95ab40ae 398 bool UbloxCellularBaseN2xx::get_meid()
philware 1:d4ff95ab40ae 399 {
philware 1:d4ff95ab40ae 400 // *** NOT IMPLEMENTED
philware 1:d4ff95ab40ae 401 return false;
philware 1:d4ff95ab40ae 402
philware 1:d4ff95ab40ae 403 bool success;
philware 1:d4ff95ab40ae 404 LOCK();
philware 1:d4ff95ab40ae 405
philware 1:d4ff95ab40ae 406 MBED_ASSERT(_at != NULL);
philware 1:d4ff95ab40ae 407
philware 1:d4ff95ab40ae 408 // Mobile equipment identifier
philware 1:d4ff95ab40ae 409 // AT Command Manual UBX-13002752, section 4.8
philware 1:d4ff95ab40ae 410 success = _at->send("AT+GSN") && _at->recv("%18[^\n]\nOK\n", _dev_info.meid);
philware 1:d4ff95ab40ae 411
philware 1:d4ff95ab40ae 412 // tr_info("DevInfo: MEID=%s", _dev_info.meid);
philware 1:d4ff95ab40ae 413
philware 1:d4ff95ab40ae 414 UNLOCK();
philware 1:d4ff95ab40ae 415 return success;
philware 1:d4ff95ab40ae 416 }
philware 1:d4ff95ab40ae 417
philware 1:d4ff95ab40ae 418 bool UbloxCellularBaseN2xx::set_sms()
philware 1:d4ff95ab40ae 419 {
philware 1:d4ff95ab40ae 420 // *** NOT IMPLEMENTED
philware 1:d4ff95ab40ae 421 return false;
philware 1:d4ff95ab40ae 422
philware 1:d4ff95ab40ae 423 bool success = false;
philware 1:d4ff95ab40ae 424 char buf[32];
philware 1:d4ff95ab40ae 425 LOCK();
philware 1:d4ff95ab40ae 426
philware 1:d4ff95ab40ae 427 MBED_ASSERT(_at != NULL);
philware 1:d4ff95ab40ae 428
philware 1:d4ff95ab40ae 429 // Set up SMS format and enable URC
philware 1:d4ff95ab40ae 430 // AT Command Manual UBX-13002752, section 11
philware 1:d4ff95ab40ae 431 if (_at->send("AT+CMGF=1") && _at->recv("OK")) {
philware 1:d4ff95ab40ae 432 tr_debug("SMS in text mode");
philware 1:d4ff95ab40ae 433 if (_at->send("AT+CNMI=2,1") && _at->recv("OK")) {
philware 1:d4ff95ab40ae 434 tr_debug("SMS URC enabled");
philware 1:d4ff95ab40ae 435 // Set to CS preferred since PS preferred doesn't work
philware 1:d4ff95ab40ae 436 // on some networks
philware 1:d4ff95ab40ae 437 if (_at->send("AT+CGSMS=1") && _at->recv("OK")) {
philware 1:d4ff95ab40ae 438 tr_debug("SMS set to CS preferred");
philware 1:d4ff95ab40ae 439 success = true;
philware 1:d4ff95ab40ae 440 memset (buf, 0, sizeof (buf));
philware 1:d4ff95ab40ae 441 if (_at->send("AT+CSCA?") &&
philware 1:d4ff95ab40ae 442 _at->recv("+CSCA: \"%31[^\"]\"", buf) &&
philware 1:d4ff95ab40ae 443 _at->recv("OK")) {
philware 1:d4ff95ab40ae 444 tr_info("SMS Service Centre address is \"%s\"", buf);
philware 1:d4ff95ab40ae 445 }
philware 1:d4ff95ab40ae 446 }
philware 1:d4ff95ab40ae 447 }
philware 1:d4ff95ab40ae 448 }
philware 1:d4ff95ab40ae 449
philware 1:d4ff95ab40ae 450 UNLOCK();
philware 1:d4ff95ab40ae 451 return success;
philware 1:d4ff95ab40ae 452 }
philware 1:d4ff95ab40ae 453
philware 1:d4ff95ab40ae 454 void UbloxCellularBaseN2xx::parser_abort_cb()
philware 1:d4ff95ab40ae 455 {
philware 1:d4ff95ab40ae 456 _at->abort();
philware 1:d4ff95ab40ae 457 }
philware 1:d4ff95ab40ae 458
philware 1:d4ff95ab40ae 459 // Callback for CME ERROR and CMS ERROR.
philware 1:d4ff95ab40ae 460 void UbloxCellularBaseN2xx::CMX_ERROR_URC()
philware 1:d4ff95ab40ae 461 {
philware 1:d4ff95ab40ae 462 char buf[48];
philware 1:d4ff95ab40ae 463
philware 1:d4ff95ab40ae 464 if (read_at_to_char(buf, sizeof (buf), '\n') > 0) {
philware 1:d4ff95ab40ae 465 tr_debug("AT error %s", buf);
philware 1:d4ff95ab40ae 466 }
philware 1:d4ff95ab40ae 467 parser_abort_cb();
philware 1:d4ff95ab40ae 468 }
philware 1:d4ff95ab40ae 469
philware 1:d4ff95ab40ae 470 // Callback for EPS registration URC.
philware 1:d4ff95ab40ae 471 void UbloxCellularBaseN2xx::CEREG_URC()
philware 1:d4ff95ab40ae 472 {
philware 1:d4ff95ab40ae 473 char buf[20];
philware 1:d4ff95ab40ae 474 int status;
philware 1:d4ff95ab40ae 475 int n, AcT;
philware 1:d4ff95ab40ae 476 char tac[4], ci[4];
philware 1:d4ff95ab40ae 477
philware 1:d4ff95ab40ae 478 // If this is the URC it will be a single
philware 1:d4ff95ab40ae 479 // digit followed by \n. If it is the
philware 1:d4ff95ab40ae 480 // answer to a CEREG query, it will be
philware 1:d4ff95ab40ae 481 // a ": %d,%d\n" where the second digit
philware 1:d4ff95ab40ae 482 // indicates the status
philware 1:d4ff95ab40ae 483 // Note: not calling _at->recv() from here as we're
philware 1:d4ff95ab40ae 484 // already in an _at->recv()
philware 1:d4ff95ab40ae 485 // We also hanlde the extended 4 or 5 argument
philware 1:d4ff95ab40ae 486 // response if cereg is set to 2.
philware 1:d4ff95ab40ae 487 if (read_at_to_newline(buf, sizeof (buf)) > 0) {
philware 1:d4ff95ab40ae 488 if (sscanf(buf, ":%d,%d,%[0123456789abcdef],%[0123456789abcdef],%d\n", &n, &status, tac, ci, &AcT) == 5) {
philware 1:d4ff95ab40ae 489 set_nwk_reg_status_eps(status);
philware 1:d4ff95ab40ae 490 } else if (sscanf(buf, ":%d,%[0123456789abcdef],%[0123456789abcdef],%d\n`", &status, tac, ci, &AcT) == 4) {
philware 1:d4ff95ab40ae 491 set_nwk_reg_status_eps(status);
philware 1:d4ff95ab40ae 492 } else if (sscanf(buf, ":%d,%d\n", &n, &status) == 2) {
philware 1:d4ff95ab40ae 493 set_nwk_reg_status_eps(status);
philware 1:d4ff95ab40ae 494 } else if (sscanf(buf, ":%d\n", &status) == 1) {
philware 1:d4ff95ab40ae 495 set_nwk_reg_status_eps(status);
philware 1:d4ff95ab40ae 496 }
philware 1:d4ff95ab40ae 497 }
philware 1:d4ff95ab40ae 498 }
philware 1:d4ff95ab40ae 499
philware 1:d4ff95ab40ae 500 /**********************************************************************
philware 1:d4ff95ab40ae 501 * PROTECTED METHODS
philware 1:d4ff95ab40ae 502 **********************************************************************/
philware 1:d4ff95ab40ae 503
philware 1:d4ff95ab40ae 504 #if MODEM_ON_BOARD
philware 1:d4ff95ab40ae 505 void UbloxCellularBaseN2xx::modem_init()
philware 1:d4ff95ab40ae 506 {
philware 1:d4ff95ab40ae 507 ::onboard_modem_init();
philware 1:d4ff95ab40ae 508 }
philware 1:d4ff95ab40ae 509
philware 1:d4ff95ab40ae 510 void UbloxCellularBaseN2xx::modem_deinit()
philware 1:d4ff95ab40ae 511 {
philware 1:d4ff95ab40ae 512 ::onboard_modem_deinit();
philware 1:d4ff95ab40ae 513 }
philware 1:d4ff95ab40ae 514
philware 1:d4ff95ab40ae 515 void UbloxCellularBaseN2xx::modem_power_up()
philware 1:d4ff95ab40ae 516 {
philware 1:d4ff95ab40ae 517 ::onboard_modem_power_up();
philware 1:d4ff95ab40ae 518 }
philware 1:d4ff95ab40ae 519
philware 1:d4ff95ab40ae 520 void UbloxCellularBaseN2xx::modem_power_down()
philware 1:d4ff95ab40ae 521 {
philware 1:d4ff95ab40ae 522 ::onboard_modem_power_down();
philware 1:d4ff95ab40ae 523 }
philware 1:d4ff95ab40ae 524 #else
philware 1:d4ff95ab40ae 525 void UbloxCellularBaseN2xx::modem_init()
philware 1:d4ff95ab40ae 526 {
philware 1:d4ff95ab40ae 527 // Meant to be overridden
philware 1:d4ff95ab40ae 528 #error need to do something here!
philware 1:d4ff95ab40ae 529 }
philware 1:d4ff95ab40ae 530
philware 1:d4ff95ab40ae 531 void UbloxCellularBaseN2xx::modem_deinit()
philware 1:d4ff95ab40ae 532 {
philware 1:d4ff95ab40ae 533 // Meant to be overridden
philware 1:d4ff95ab40ae 534 }
philware 1:d4ff95ab40ae 535
philware 1:d4ff95ab40ae 536 void UbloxCellularBaseN2xx::modem_power_up()
philware 1:d4ff95ab40ae 537 {
philware 1:d4ff95ab40ae 538 // Meant to be overridden
philware 1:d4ff95ab40ae 539 }
philware 1:d4ff95ab40ae 540
philware 1:d4ff95ab40ae 541 void UbloxCellularBaseN2xx::modem_power_down()
philware 1:d4ff95ab40ae 542 {
philware 1:d4ff95ab40ae 543 // Mmeant to be overridden
philware 1:d4ff95ab40ae 544 }
philware 1:d4ff95ab40ae 545 #endif
philware 1:d4ff95ab40ae 546
philware 1:d4ff95ab40ae 547 // Constructor.
philware 1:d4ff95ab40ae 548 // Note: to allow this base class to be inherited as a virtual base class
philware 1:d4ff95ab40ae 549 // by everyone, it takes no parameters. See also comment above classInit()
philware 1:d4ff95ab40ae 550 // in the header file.
philware 1:d4ff95ab40ae 551 UbloxCellularBaseN2xx::UbloxCellularBaseN2xx()
philware 1:d4ff95ab40ae 552 {
philware 1:d4ff95ab40ae 553 tr_debug("UbloxATCellularBaseN2xx Constructor");
philware 1:d4ff95ab40ae 554
philware 1:d4ff95ab40ae 555 _pin = NULL;
philware 1:d4ff95ab40ae 556 _at = NULL;
philware 1:d4ff95ab40ae 557 _at_timeout = AT_PARSER_TIMEOUT;
philware 1:d4ff95ab40ae 558 _fh = NULL;
philware 1:d4ff95ab40ae 559 _modem_initialised = false;
philware 1:d4ff95ab40ae 560 _sim_pin_check_enabled = false;
philware 1:d4ff95ab40ae 561 _debug_trace_on = false;
philware 1:d4ff95ab40ae 562
philware 1:d4ff95ab40ae 563 _dev_info.dev = DEV_TYPE_NONE;
philware 1:d4ff95ab40ae 564 _dev_info.reg_status_csd = CSD_NOT_REGISTERED_NOT_SEARCHING;
philware 1:d4ff95ab40ae 565 _dev_info.reg_status_psd = PSD_NOT_REGISTERED_NOT_SEARCHING;
philware 1:d4ff95ab40ae 566 _dev_info.reg_status_eps = EPS_NOT_REGISTERED_NOT_SEARCHING;
philware 1:d4ff95ab40ae 567 }
philware 1:d4ff95ab40ae 568
philware 1:d4ff95ab40ae 569 // Destructor.
philware 1:d4ff95ab40ae 570 UbloxCellularBaseN2xx::~UbloxCellularBaseN2xx()
philware 1:d4ff95ab40ae 571 {
philware 1:d4ff95ab40ae 572 deinit();
philware 1:d4ff95ab40ae 573 delete _at;
philware 1:d4ff95ab40ae 574 delete _fh;
philware 1:d4ff95ab40ae 575 }
philware 1:d4ff95ab40ae 576
philware 1:d4ff95ab40ae 577 // Initialise the portions of this class that are parameterised.
philware 1:d4ff95ab40ae 578 void UbloxCellularBaseN2xx::baseClassInit(PinName tx, PinName rx,
philware 1:d4ff95ab40ae 579 int baud, bool debug_on)
philware 1:d4ff95ab40ae 580 {
philware 1:d4ff95ab40ae 581 // Only initialise ourselves if it's not already been done
philware 1:d4ff95ab40ae 582 if (_at == NULL) {
philware 1:d4ff95ab40ae 583 if (_debug_trace_on == false) {
philware 1:d4ff95ab40ae 584 _debug_trace_on = debug_on;
philware 1:d4ff95ab40ae 585 }
philware 1:d4ff95ab40ae 586
philware 1:d4ff95ab40ae 587 // Set up File Handle for buffered serial comms with cellular module
philware 1:d4ff95ab40ae 588 // (which will be used by the AT parser)
philware 1:d4ff95ab40ae 589 _fh = new UARTSerial(tx, rx, baud);
philware 1:d4ff95ab40ae 590
philware 1:d4ff95ab40ae 591 // Set up the AT parser
philware 1:d4ff95ab40ae 592 _at = new ATCmdParser(_fh, OUTPUT_ENTER_KEY, AT_PARSER_BUFFER_SIZE,
philware 1:d4ff95ab40ae 593 _at_timeout, _debug_trace_on);
philware 1:d4ff95ab40ae 594
philware 1:d4ff95ab40ae 595 // Error cases, out of band handling
philware 1:d4ff95ab40ae 596 _at->oob("ERROR", callback(this, &UbloxCellularBaseN2xx::parser_abort_cb));
philware 1:d4ff95ab40ae 597 _at->oob("+CME ERROR", callback(this, &UbloxCellularBaseN2xx::CMX_ERROR_URC));
philware 1:d4ff95ab40ae 598 _at->oob("+CMS ERROR", callback(this, &UbloxCellularBaseN2xx::CMX_ERROR_URC));
philware 1:d4ff95ab40ae 599
philware 1:d4ff95ab40ae 600 // Registration status, out of band handling
philware 1:d4ff95ab40ae 601 _at->oob("+CEREG", callback(this, &UbloxCellularBaseN2xx::CEREG_URC));
philware 1:d4ff95ab40ae 602 }
philware 1:d4ff95ab40ae 603 }
philware 1:d4ff95ab40ae 604
philware 1:d4ff95ab40ae 605 // Set the AT parser timeout.
philware 1:d4ff95ab40ae 606 // Note: the AT interface should be locked before this is called.
philware 1:d4ff95ab40ae 607 void UbloxCellularBaseN2xx::at_set_timeout(int timeout) {
philware 1:d4ff95ab40ae 608
philware 1:d4ff95ab40ae 609 MBED_ASSERT(_at != NULL);
philware 1:d4ff95ab40ae 610
philware 1:d4ff95ab40ae 611 _at_timeout = timeout;
philware 1:d4ff95ab40ae 612 _at->set_timeout(timeout);
philware 1:d4ff95ab40ae 613 }
philware 1:d4ff95ab40ae 614
philware 1:d4ff95ab40ae 615 // Read up to size bytes from the AT interface up to a "end".
philware 1:d4ff95ab40ae 616 // Note: the AT interface should be locked before this is called.
philware 1:d4ff95ab40ae 617 int UbloxCellularBaseN2xx::read_at_to_char(char * buf, int size, char end)
philware 1:d4ff95ab40ae 618 {
philware 1:d4ff95ab40ae 619 int count = 0;
philware 1:d4ff95ab40ae 620 int x = 0;
philware 1:d4ff95ab40ae 621
philware 1:d4ff95ab40ae 622 if (size > 0) {
philware 1:d4ff95ab40ae 623 for (count = 0; (count < size) && (x >= 0) && (x != end); count++) {
philware 1:d4ff95ab40ae 624 x = _at->getc();
philware 1:d4ff95ab40ae 625 *(buf + count) = (char) x;
philware 1:d4ff95ab40ae 626 }
philware 1:d4ff95ab40ae 627
philware 1:d4ff95ab40ae 628 count--;
philware 1:d4ff95ab40ae 629 *(buf + count) = 0;
philware 1:d4ff95ab40ae 630
philware 1:d4ff95ab40ae 631 // Convert line endings:
philware 1:d4ff95ab40ae 632 // If end was '\n' (0x0a) and the preceding character was 0x0d, then
philware 1:d4ff95ab40ae 633 // overwrite that with null as well.
philware 1:d4ff95ab40ae 634 if ((count > 0) && (end == '\n') && (*(buf + count - 1) == '\x0d')) {
philware 1:d4ff95ab40ae 635 count--;
philware 1:d4ff95ab40ae 636 *(buf + count) = 0;
philware 1:d4ff95ab40ae 637 }
philware 1:d4ff95ab40ae 638 }
philware 1:d4ff95ab40ae 639
philware 1:d4ff95ab40ae 640 return count;
philware 1:d4ff95ab40ae 641 }
philware 1:d4ff95ab40ae 642
philware 1:d4ff95ab40ae 643 // Power up the modem.
philware 1:d4ff95ab40ae 644 // Enables the GPIO lines to the modem and then wriggles the power line in short pulses.
philware 1:d4ff95ab40ae 645 bool UbloxCellularBaseN2xx::power_up()
philware 1:d4ff95ab40ae 646 {
philware 1:d4ff95ab40ae 647 bool success = false;
philware 1:d4ff95ab40ae 648 int at_timeout;
philware 1:d4ff95ab40ae 649 LOCK();
philware 1:d4ff95ab40ae 650
philware 1:d4ff95ab40ae 651 at_timeout = _at_timeout; // Has to be inside LOCK()s
philware 1:d4ff95ab40ae 652
philware 1:d4ff95ab40ae 653 MBED_ASSERT(_at != NULL);
philware 1:d4ff95ab40ae 654
philware 1:d4ff95ab40ae 655 /* Initialize GPIO lines */
philware 1:d4ff95ab40ae 656 tr_info("Powering up modem...");
philware 1:d4ff95ab40ae 657 onboard_modem_init();
philware 1:d4ff95ab40ae 658 /* Give SARA-N2XX time to reset */
philware 1:d4ff95ab40ae 659 tr_debug("Waiting for 5 seconds (booting SARA-N2xx)...");
philware 1:d4ff95ab40ae 660 wait_ms(5000);
philware 1:d4ff95ab40ae 661
philware 1:d4ff95ab40ae 662 at_set_timeout(1000);
philware 1:d4ff95ab40ae 663 for (int retry_count = 0; !success && (retry_count < 20); retry_count++) {
philware 1:d4ff95ab40ae 664 _at->flush();
philware 1:d4ff95ab40ae 665 if (at_send("AT")) {
philware 1:d4ff95ab40ae 666 success = true;
philware 1:d4ff95ab40ae 667 }
philware 1:d4ff95ab40ae 668 }
philware 1:d4ff95ab40ae 669 at_set_timeout(at_timeout);
philware 1:d4ff95ab40ae 670
philware 1:d4ff95ab40ae 671 // perform any initialisation AT commands here
philware 1:d4ff95ab40ae 672 if (success) {
philware 1:d4ff95ab40ae 673 success = at_send("AT+CMEE=1"); // Turn on verbose responses
philware 1:d4ff95ab40ae 674 }
philware 1:d4ff95ab40ae 675
philware 1:d4ff95ab40ae 676 if (!success) {
philware 1:d4ff95ab40ae 677 tr_error("Preliminary modem setup failed.");
philware 1:d4ff95ab40ae 678 }
philware 1:d4ff95ab40ae 679
philware 1:d4ff95ab40ae 680 UNLOCK();
philware 1:d4ff95ab40ae 681 return success;
philware 1:d4ff95ab40ae 682 }
philware 1:d4ff95ab40ae 683
philware 1:d4ff95ab40ae 684 // Power down modem via AT interface.
philware 1:d4ff95ab40ae 685 void UbloxCellularBaseN2xx::power_down()
philware 1:d4ff95ab40ae 686 {
philware 1:d4ff95ab40ae 687 LOCK();
philware 1:d4ff95ab40ae 688
philware 1:d4ff95ab40ae 689 MBED_ASSERT(_at != NULL);
philware 1:d4ff95ab40ae 690
philware 1:d4ff95ab40ae 691 // If we have been running, do a soft power-off first
philware 1:d4ff95ab40ae 692 if (_modem_initialised && (_at != NULL)) {
philware 1:d4ff95ab40ae 693 // NOT IMPLEMENTED in B656 firmware
philware 1:d4ff95ab40ae 694 // at_send("AT+CPWROFF");
philware 1:d4ff95ab40ae 695 }
philware 1:d4ff95ab40ae 696
philware 1:d4ff95ab40ae 697 // Now do a hard power-off
philware 1:d4ff95ab40ae 698 onboard_modem_power_down();
philware 1:d4ff95ab40ae 699 onboard_modem_deinit();
philware 1:d4ff95ab40ae 700
philware 1:d4ff95ab40ae 701 _dev_info.reg_status_csd = CSD_NOT_REGISTERED_NOT_SEARCHING;
philware 1:d4ff95ab40ae 702 _dev_info.reg_status_psd = PSD_NOT_REGISTERED_NOT_SEARCHING;
philware 1:d4ff95ab40ae 703 _dev_info.reg_status_eps = EPS_NOT_REGISTERED_NOT_SEARCHING;
philware 1:d4ff95ab40ae 704
philware 1:d4ff95ab40ae 705 UNLOCK();
philware 1:d4ff95ab40ae 706 }
philware 1:d4ff95ab40ae 707
philware 1:d4ff95ab40ae 708 // Get the device ID.
philware 1:d4ff95ab40ae 709 bool UbloxCellularBaseN2xx::set_device_identity(DeviceType *dev)
philware 1:d4ff95ab40ae 710 {
philware 1:d4ff95ab40ae 711 char buf[20];
philware 1:d4ff95ab40ae 712 bool success;
philware 1:d4ff95ab40ae 713 LOCK();
philware 1:d4ff95ab40ae 714
philware 1:d4ff95ab40ae 715 MBED_ASSERT(_at != NULL);
philware 1:d4ff95ab40ae 716
philware 1:d4ff95ab40ae 717 success = at_req("AT+CGMM", "%19[^\n]\n", buf);
philware 1:d4ff95ab40ae 718
philware 1:d4ff95ab40ae 719 if (success) {
philware 1:d4ff95ab40ae 720 if (strstr(buf, "Neul Hi2110"))
philware 1:d4ff95ab40ae 721 *dev = DEV_SARA_N2;
philware 1:d4ff95ab40ae 722 }
philware 1:d4ff95ab40ae 723
philware 1:d4ff95ab40ae 724 UNLOCK();
philware 1:d4ff95ab40ae 725 return success;
philware 1:d4ff95ab40ae 726 }
philware 1:d4ff95ab40ae 727
philware 1:d4ff95ab40ae 728 // Send initialisation AT commands that are specific to the device.
philware 1:d4ff95ab40ae 729 bool UbloxCellularBaseN2xx::device_init(DeviceType dev)
philware 1:d4ff95ab40ae 730 {
philware 1:d4ff95ab40ae 731 // SARA-N2xx doesn't have anything to initialise
philware 1:d4ff95ab40ae 732 return true;
philware 1:d4ff95ab40ae 733 }
philware 1:d4ff95ab40ae 734
philware 1:d4ff95ab40ae 735 // Get the SIM card going.
philware 1:d4ff95ab40ae 736 bool UbloxCellularBaseN2xx::initialise_sim_card()
philware 1:d4ff95ab40ae 737 {
philware 1:d4ff95ab40ae 738 // SARA-N2XX doesn't have any SIM AT Commands for now.
philware 1:d4ff95ab40ae 739 return true;
philware 1:d4ff95ab40ae 740 }
philware 1:d4ff95ab40ae 741
philware 1:d4ff95ab40ae 742 /**********************************************************************
philware 1:d4ff95ab40ae 743 * PUBLIC METHODS
philware 1:d4ff95ab40ae 744 **********************************************************************/
philware 1:d4ff95ab40ae 745
philware 1:d4ff95ab40ae 746 // Initialise the modem.
philware 1:d4ff95ab40ae 747 bool UbloxCellularBaseN2xx::init(const char *pin)
philware 1:d4ff95ab40ae 748 {
philware 1:d4ff95ab40ae 749 MBED_ASSERT(_at != NULL);
philware 1:d4ff95ab40ae 750
philware 1:d4ff95ab40ae 751 if (!_modem_initialised) {
philware 3:39eadc84c5ac 752 tr_warn("Modem not initialised, initialising...");
philware 1:d4ff95ab40ae 753 if (power_up()) {
philware 3:39eadc84c5ac 754 tr_info("Modem Powered Up.");
philware 1:d4ff95ab40ae 755 if (pin != NULL) {
philware 1:d4ff95ab40ae 756 _pin = pin;
philware 1:d4ff95ab40ae 757 }
philware 1:d4ff95ab40ae 758
philware 1:d4ff95ab40ae 759 if (initialise_sim_card()) {
philware 3:39eadc84c5ac 760 tr_info("Sim ready...");
philware 1:d4ff95ab40ae 761 if (set_device_identity(&_dev_info.dev) && // Set up device identity
philware 1:d4ff95ab40ae 762 device_init(_dev_info.dev) &&
philware 1:d4ff95ab40ae 763 get_sara_n2xx_info())
philware 1:d4ff95ab40ae 764 {
philware 1:d4ff95ab40ae 765 tr_debug("CGMM: %s", _sara_n2xx_info.cgmm);
philware 1:d4ff95ab40ae 766 tr_debug("CGMI: %s", _sara_n2xx_info.cgmi);
philware 1:d4ff95ab40ae 767 tr_debug("CGMR: %s", _sara_n2xx_info.cgmr);
philware 1:d4ff95ab40ae 768 tr_debug("CGSN: %s", _sara_n2xx_info.cgsn);
philware 1:d4ff95ab40ae 769
philware 1:d4ff95ab40ae 770 // The modem is initialised. The following checks my still fail,
philware 1:d4ff95ab40ae 771 // of course, but they are all of a "fatal" nature and so we wouldn't
philware 1:d4ff95ab40ae 772 // want to retry them anyway
philware 1:d4ff95ab40ae 773 _modem_initialised = true;
philware 1:d4ff95ab40ae 774 }
philware 1:d4ff95ab40ae 775 }
philware 3:39eadc84c5ac 776 } else {
philware 3:39eadc84c5ac 777 tr_error("Couldn't power up modem.");
philware 1:d4ff95ab40ae 778 }
philware 1:d4ff95ab40ae 779 }
philware 3:39eadc84c5ac 780 else {
philware 3:39eadc84c5ac 781 tr_info("Modem already initialised.");
philware 3:39eadc84c5ac 782 }
philware 1:d4ff95ab40ae 783
philware 1:d4ff95ab40ae 784 return _modem_initialised;
philware 1:d4ff95ab40ae 785 }
philware 1:d4ff95ab40ae 786
philware 1:d4ff95ab40ae 787 // Perform registration.
philware 1:d4ff95ab40ae 788 bool UbloxCellularBaseN2xx::nwk_registration()
philware 1:d4ff95ab40ae 789 {
philware 1:d4ff95ab40ae 790 bool registered = false;
philware 1:d4ff95ab40ae 791 int status;
philware 1:d4ff95ab40ae 792 int at_timeout;
philware 1:d4ff95ab40ae 793 LOCK();
philware 1:d4ff95ab40ae 794
philware 1:d4ff95ab40ae 795 at_timeout = _at_timeout; // Has to be inside LOCK()s
philware 1:d4ff95ab40ae 796
philware 1:d4ff95ab40ae 797 MBED_ASSERT(_at != NULL);
philware 1:d4ff95ab40ae 798
philware 1:d4ff95ab40ae 799 // Enable the packet switched and network registration unsolicited result codes
philware 1:d4ff95ab40ae 800 if (cereg(1)) {
philware 1:d4ff95ab40ae 801 // See if we are already in automatic mode
philware 1:d4ff95ab40ae 802 if (get_cops(&status)) {
philware 1:d4ff95ab40ae 803 if (status != 0) {
philware 1:d4ff95ab40ae 804 // Don't check return code here as there's not much
philware 1:d4ff95ab40ae 805 // we can do if this fails.
philware 1:d4ff95ab40ae 806 cops(0);
philware 1:d4ff95ab40ae 807 }
philware 1:d4ff95ab40ae 808 }
philware 1:d4ff95ab40ae 809
philware 1:d4ff95ab40ae 810 // query cereg just in case
philware 1:d4ff95ab40ae 811 get_cereg();
philware 1:d4ff95ab40ae 812 registered = is_registered_eps();
philware 1:d4ff95ab40ae 813
philware 1:d4ff95ab40ae 814 at_set_timeout(1000);
philware 1:d4ff95ab40ae 815 for (int waitSeconds = 0; !registered && (waitSeconds < 180); waitSeconds++) {
philware 1:d4ff95ab40ae 816 _at->recv(UNNATURAL_STRING);
philware 1:d4ff95ab40ae 817 registered = is_registered_eps();
philware 1:d4ff95ab40ae 818 }
philware 1:d4ff95ab40ae 819 at_set_timeout(at_timeout);
philware 1:d4ff95ab40ae 820 } else {
philware 1:d4ff95ab40ae 821 tr_error("Failed to set CEREG=1");
philware 1:d4ff95ab40ae 822 }
philware 1:d4ff95ab40ae 823
philware 1:d4ff95ab40ae 824 UNLOCK();
philware 1:d4ff95ab40ae 825 return registered;
philware 1:d4ff95ab40ae 826 }
philware 1:d4ff95ab40ae 827
philware 1:d4ff95ab40ae 828 bool UbloxCellularBaseN2xx::is_registered_csd()
philware 1:d4ff95ab40ae 829 {
philware 1:d4ff95ab40ae 830 return (_dev_info.reg_status_csd == CSD_REGISTERED) ||
philware 1:d4ff95ab40ae 831 (_dev_info.reg_status_csd == CSD_REGISTERED_ROAMING) ||
philware 1:d4ff95ab40ae 832 (_dev_info.reg_status_csd == CSD_CSFB_NOT_PREFERRED);
philware 1:d4ff95ab40ae 833 }
philware 1:d4ff95ab40ae 834
philware 1:d4ff95ab40ae 835 bool UbloxCellularBaseN2xx::is_registered_psd()
philware 1:d4ff95ab40ae 836 {
philware 1:d4ff95ab40ae 837 return (_dev_info.reg_status_psd == PSD_REGISTERED) ||
philware 1:d4ff95ab40ae 838 (_dev_info.reg_status_psd == PSD_REGISTERED_ROAMING);
philware 1:d4ff95ab40ae 839 }
philware 1:d4ff95ab40ae 840
philware 1:d4ff95ab40ae 841 bool UbloxCellularBaseN2xx::is_registered_eps()
philware 1:d4ff95ab40ae 842 {
philware 1:d4ff95ab40ae 843 return (_dev_info.reg_status_eps == EPS_REGISTERED) ||
philware 1:d4ff95ab40ae 844 (_dev_info.reg_status_eps == EPS_REGISTERED_ROAMING);
philware 1:d4ff95ab40ae 845 }
philware 1:d4ff95ab40ae 846
philware 1:d4ff95ab40ae 847 // Perform deregistration.
philware 1:d4ff95ab40ae 848 bool UbloxCellularBaseN2xx::nwk_deregistration()
philware 1:d4ff95ab40ae 849 {
philware 1:d4ff95ab40ae 850 bool success = false;
philware 1:d4ff95ab40ae 851
philware 1:d4ff95ab40ae 852 MBED_ASSERT(_at != NULL);
philware 1:d4ff95ab40ae 853
philware 1:d4ff95ab40ae 854 if (cops(2)) {
philware 1:d4ff95ab40ae 855 // we need to wait here so that the internal status of the module
philware 1:d4ff95ab40ae 856 wait_ms(1000);
philware 1:d4ff95ab40ae 857
philware 1:d4ff95ab40ae 858 _dev_info.reg_status_csd = CSD_NOT_REGISTERED_NOT_SEARCHING;
philware 1:d4ff95ab40ae 859 _dev_info.reg_status_psd = PSD_NOT_REGISTERED_NOT_SEARCHING;
philware 1:d4ff95ab40ae 860 _dev_info.reg_status_eps = EPS_NOT_REGISTERED_NOT_SEARCHING;
philware 1:d4ff95ab40ae 861
philware 1:d4ff95ab40ae 862 success = true;
philware 1:d4ff95ab40ae 863 } else {
philware 1:d4ff95ab40ae 864 tr_error("Failed to set COPS=2");
philware 1:d4ff95ab40ae 865 }
philware 1:d4ff95ab40ae 866
philware 1:d4ff95ab40ae 867 return success;
philware 1:d4ff95ab40ae 868 }
philware 1:d4ff95ab40ae 869
philware 1:d4ff95ab40ae 870 // Put the modem into its lowest power state.
philware 1:d4ff95ab40ae 871 void UbloxCellularBaseN2xx::deinit()
philware 1:d4ff95ab40ae 872 {
philware 1:d4ff95ab40ae 873 power_down();
philware 1:d4ff95ab40ae 874 _modem_initialised = false;
philware 1:d4ff95ab40ae 875 }
philware 1:d4ff95ab40ae 876
philware 1:d4ff95ab40ae 877 // Set the PIN.
philware 1:d4ff95ab40ae 878 void UbloxCellularBaseN2xx::set_pin(const char *pin) {
philware 1:d4ff95ab40ae 879 _pin = pin;
philware 1:d4ff95ab40ae 880 }
philware 1:d4ff95ab40ae 881
philware 1:d4ff95ab40ae 882 // Enable or disable SIM pin checking.
philware 1:d4ff95ab40ae 883 bool UbloxCellularBaseN2xx:: sim_pin_check_enable(bool enableNotDisable)
philware 1:d4ff95ab40ae 884 {
philware 1:d4ff95ab40ae 885 // *** NOT IMPLEMENTED on SARA-N2XX
philware 1:d4ff95ab40ae 886 return false;
philware 1:d4ff95ab40ae 887
philware 1:d4ff95ab40ae 888 bool success = false;
philware 1:d4ff95ab40ae 889 LOCK();
philware 1:d4ff95ab40ae 890
philware 1:d4ff95ab40ae 891 MBED_ASSERT(_at != NULL);
philware 1:d4ff95ab40ae 892
philware 1:d4ff95ab40ae 893 if (_pin != NULL) {
philware 1:d4ff95ab40ae 894 if (_sim_pin_check_enabled && !enableNotDisable) {
philware 1:d4ff95ab40ae 895 // Disable the SIM lock
philware 1:d4ff95ab40ae 896 if (_at->send("AT+CLCK=\"SC\",0,\"%s\"", _pin) && _at->recv("OK")) {
philware 1:d4ff95ab40ae 897 _sim_pin_check_enabled = false;
philware 1:d4ff95ab40ae 898 success = true;
philware 1:d4ff95ab40ae 899 }
philware 1:d4ff95ab40ae 900 } else if (!_sim_pin_check_enabled && enableNotDisable) {
philware 1:d4ff95ab40ae 901 // Enable the SIM lock
philware 1:d4ff95ab40ae 902 if (_at->send("AT+CLCK=\"SC\",1,\"%s\"", _pin) && _at->recv("OK")) {
philware 1:d4ff95ab40ae 903 _sim_pin_check_enabled = true;
philware 1:d4ff95ab40ae 904 success = true;
philware 1:d4ff95ab40ae 905 }
philware 1:d4ff95ab40ae 906 } else {
philware 1:d4ff95ab40ae 907 success = true;
philware 1:d4ff95ab40ae 908 }
philware 1:d4ff95ab40ae 909 }
philware 1:d4ff95ab40ae 910
philware 1:d4ff95ab40ae 911 UNLOCK();
philware 1:d4ff95ab40ae 912 return success;
philware 1:d4ff95ab40ae 913 }
philware 1:d4ff95ab40ae 914
philware 1:d4ff95ab40ae 915 // Change the pin code for the SIM card.
philware 1:d4ff95ab40ae 916 bool UbloxCellularBaseN2xx::change_sim_pin(const char *pin)
philware 1:d4ff95ab40ae 917 {
philware 1:d4ff95ab40ae 918 // *** NOT IMPLEMENTED on SARA-N2XX
philware 1:d4ff95ab40ae 919 return false;
philware 1:d4ff95ab40ae 920
philware 1:d4ff95ab40ae 921 bool success = false;
philware 1:d4ff95ab40ae 922 LOCK();
philware 1:d4ff95ab40ae 923
philware 1:d4ff95ab40ae 924 MBED_ASSERT(_at != NULL);
philware 1:d4ff95ab40ae 925
philware 1:d4ff95ab40ae 926 // Change the SIM pin
philware 1:d4ff95ab40ae 927 if ((pin != NULL) && (_pin != NULL)) {
philware 1:d4ff95ab40ae 928 if (_at->send("AT+CPWD=\"SC\",\"%s\",\"%s\"", _pin, pin) && _at->recv("OK")) {
philware 1:d4ff95ab40ae 929 _pin = pin;
philware 1:d4ff95ab40ae 930 success = true;
philware 1:d4ff95ab40ae 931 }
philware 1:d4ff95ab40ae 932 }
philware 1:d4ff95ab40ae 933
philware 1:d4ff95ab40ae 934 UNLOCK();
philware 1:d4ff95ab40ae 935 return success;
philware 1:d4ff95ab40ae 936 }
philware 1:d4ff95ab40ae 937
philware 1:d4ff95ab40ae 938 // Read up to size bytes from the AT interface up to a newline.
philware 1:d4ff95ab40ae 939 // This doesn't need a LOCK() UNLOCK() Wrapping as it's only called
philware 1:d4ff95ab40ae 940 // from the URC function, which are already in a lock
philware 1:d4ff95ab40ae 941 int UbloxCellularBaseN2xx::read_at_to_newline(char * buf, int size)
philware 1:d4ff95ab40ae 942 {
philware 1:d4ff95ab40ae 943 int count = 0;
philware 1:d4ff95ab40ae 944 int x = 0;
philware 1:d4ff95ab40ae 945
philware 1:d4ff95ab40ae 946 if (size > 0) {
philware 1:d4ff95ab40ae 947 for (count = 0; (count < size) && (x >= 0) && (x != '\n'); count++) {
philware 1:d4ff95ab40ae 948 x = _at->getc();
philware 1:d4ff95ab40ae 949 *(buf + count) = (char) x;
philware 1:d4ff95ab40ae 950 }
philware 1:d4ff95ab40ae 951
philware 1:d4ff95ab40ae 952 *(buf + count - 1) = 0;
philware 1:d4ff95ab40ae 953 count--;
philware 1:d4ff95ab40ae 954 }
philware 1:d4ff95ab40ae 955
philware 1:d4ff95ab40ae 956 return count;
philware 1:d4ff95ab40ae 957 }
philware 1:d4ff95ab40ae 958 // End of File
philware 1:d4ff95ab40ae 959