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:
Mon Jun 26 13:48:04 2017 +0100
Revision:
1:d4ff95ab40ae
Child:
3:39eadc84c5ac
Base class for SARA-N2xx modules including helper functions for SARA AT commands.

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
philware 1:d4ff95ab40ae 176 tr_debug("ATREQ: %s => %s", cmd, recvFormat);
philware 1:d4ff95ab40ae 177 if(_at->send(cmd) && _at->recv(recvFormat, response) && ATOK) {
philware 1:d4ff95ab40ae 178 tr_debug("ATRESULT: %s", response);
philware 1:d4ff95ab40ae 179 success = true;
philware 1:d4ff95ab40ae 180 } else {
philware 1:d4ff95ab40ae 181 tr_error("ATRESULT: No Answer!");
philware 1:d4ff95ab40ae 182 }
philware 1:d4ff95ab40ae 183
philware 1:d4ff95ab40ae 184
philware 1:d4ff95ab40ae 185 UNLOCK();
philware 1:d4ff95ab40ae 186 return success;
philware 1:d4ff95ab40ae 187 }
philware 1:d4ff95ab40ae 188
philware 1:d4ff95ab40ae 189 bool UbloxCellularBaseN2xx::at_req(const char *cmd, const char *recvFormat, int *response) {
philware 1:d4ff95ab40ae 190 bool success = false;
philware 1:d4ff95ab40ae 191 LOCK();
philware 1:d4ff95ab40ae 192
philware 1:d4ff95ab40ae 193 MBED_ASSERT(_at != NULL);
philware 1:d4ff95ab40ae 194
philware 1:d4ff95ab40ae 195 tr_debug("ATREQ: %s => %s", cmd, recvFormat);
philware 1:d4ff95ab40ae 196 if(_at->send(cmd) && _at->recv(recvFormat, response) && ATOK) {
philware 1:d4ff95ab40ae 197 tr_debug("ATRESULT: %d", *response);
philware 1:d4ff95ab40ae 198 success = true;
philware 1:d4ff95ab40ae 199 } else {
philware 1:d4ff95ab40ae 200 tr_error("ATRESULT: No Answer!");
philware 1:d4ff95ab40ae 201 }
philware 1:d4ff95ab40ae 202
philware 1:d4ff95ab40ae 203 UNLOCK();
philware 1:d4ff95ab40ae 204 return success;
philware 1:d4ff95ab40ae 205 }
philware 1:d4ff95ab40ae 206
philware 1:d4ff95ab40ae 207 bool UbloxCellularBaseN2xx::at_send(const char *cmd) {
philware 1:d4ff95ab40ae 208 bool success = false;
philware 1:d4ff95ab40ae 209 LOCK();
philware 1:d4ff95ab40ae 210
philware 1:d4ff95ab40ae 211 MBED_ASSERT(_at != NULL);
philware 1:d4ff95ab40ae 212
philware 1:d4ff95ab40ae 213 tr_debug("ATSEND: %s", cmd);
philware 1:d4ff95ab40ae 214 if(_at->send(cmd) && ATOK) {
philware 1:d4ff95ab40ae 215 success = true;
philware 1:d4ff95ab40ae 216 } else {
philware 1:d4ff95ab40ae 217 tr_error("Failed to send %s", cmd);
philware 1:d4ff95ab40ae 218 }
philware 1:d4ff95ab40ae 219
philware 1:d4ff95ab40ae 220 UNLOCK();
philware 1:d4ff95ab40ae 221 return success;
philware 1:d4ff95ab40ae 222 }
philware 1:d4ff95ab40ae 223
philware 1:d4ff95ab40ae 224 bool UbloxCellularBaseN2xx::at_send(const char *cmd, int n) {
philware 1:d4ff95ab40ae 225 bool success = false;
philware 1:d4ff95ab40ae 226 LOCK();
philware 1:d4ff95ab40ae 227
philware 1:d4ff95ab40ae 228 MBED_ASSERT(_at != NULL);
philware 1:d4ff95ab40ae 229
philware 1:d4ff95ab40ae 230 tr_debug("ATSEND: %s, %d", cmd, n);
philware 1:d4ff95ab40ae 231 if(_at->send(cmd, n) && ATOK) {
philware 1:d4ff95ab40ae 232 success = true;
philware 1:d4ff95ab40ae 233 } else {
philware 1:d4ff95ab40ae 234 tr_error("Failed to send %s,%d", cmd, n);
philware 1:d4ff95ab40ae 235 }
philware 1:d4ff95ab40ae 236
philware 1:d4ff95ab40ae 237 UNLOCK();
philware 1:d4ff95ab40ae 238 return success;
philware 1:d4ff95ab40ae 239 }
philware 1:d4ff95ab40ae 240
philware 1:d4ff95ab40ae 241 bool UbloxCellularBaseN2xx::at_send(const char *cmd, const char *arg) {
philware 1:d4ff95ab40ae 242 bool success = false;
philware 1:d4ff95ab40ae 243 LOCK();
philware 1:d4ff95ab40ae 244
philware 1:d4ff95ab40ae 245 MBED_ASSERT(_at != NULL);
philware 1:d4ff95ab40ae 246
philware 1:d4ff95ab40ae 247 tr_debug("ATSEND: %s,%s", cmd, arg);
philware 1:d4ff95ab40ae 248 if(_at->send(cmd, arg) && ATOK) {
philware 1:d4ff95ab40ae 249 success = true;
philware 1:d4ff95ab40ae 250 } else {
philware 1:d4ff95ab40ae 251 tr_error("Failed to send %s,%s", cmd, arg);
philware 1:d4ff95ab40ae 252 }
philware 1:d4ff95ab40ae 253
philware 1:d4ff95ab40ae 254 UNLOCK();
philware 1:d4ff95ab40ae 255 return success;
philware 1:d4ff95ab40ae 256 }
philware 1:d4ff95ab40ae 257
philware 1:d4ff95ab40ae 258 bool UbloxCellularBaseN2xx::cgmi(const char *response)
philware 1:d4ff95ab40ae 259 {
philware 1:d4ff95ab40ae 260 return at_req("AT+CGMI", "%32[^\n]\n", response);
philware 1:d4ff95ab40ae 261 }
philware 1:d4ff95ab40ae 262
philware 1:d4ff95ab40ae 263 bool UbloxCellularBaseN2xx::cgmm(const char *response) {
philware 1:d4ff95ab40ae 264 return at_req("AT+CGMM", "%32[^\n]\n", response);
philware 1:d4ff95ab40ae 265 }
philware 1:d4ff95ab40ae 266
philware 1:d4ff95ab40ae 267 bool UbloxCellularBaseN2xx::cimi(const char *response) {
philware 1:d4ff95ab40ae 268 return at_req("AT+CIMI", "%32[^\n]\n", response);
philware 1:d4ff95ab40ae 269 }
philware 1:d4ff95ab40ae 270
philware 1:d4ff95ab40ae 271 bool UbloxCellularBaseN2xx::ccid(const char *response) {
philware 1:d4ff95ab40ae 272 return at_req("AT+NCCID", "+NCCID:%32[^\n]\n", response);
philware 1:d4ff95ab40ae 273 }
philware 1:d4ff95ab40ae 274
philware 1:d4ff95ab40ae 275 bool UbloxCellularBaseN2xx::cgmr(const char *response) {
philware 1:d4ff95ab40ae 276 return at_req("AT+CGMR", "%32[^\n]\n", response);
philware 1:d4ff95ab40ae 277 }
philware 1:d4ff95ab40ae 278
philware 1:d4ff95ab40ae 279 bool UbloxCellularBaseN2xx::cgsn(int snt, const char *response) {
philware 1:d4ff95ab40ae 280 char cmd[10];
philware 1:d4ff95ab40ae 281 sprintf(cmd, "AT+CGSN=%d", snt);
philware 1:d4ff95ab40ae 282
philware 1:d4ff95ab40ae 283 return at_req(cmd, "+CGSN:%32[^\n]\n", response);
philware 1:d4ff95ab40ae 284 }
philware 1:d4ff95ab40ae 285
philware 1:d4ff95ab40ae 286 bool UbloxCellularBaseN2xx::cereg(int n) {
philware 1:d4ff95ab40ae 287 return at_send("AT+CEREG=%d", n);
philware 1:d4ff95ab40ae 288 }
philware 1:d4ff95ab40ae 289
philware 1:d4ff95ab40ae 290 nsapi_error_t UbloxCellularBaseN2xx::get_cereg() {
philware 1:d4ff95ab40ae 291 nsapi_error_t r = NSAPI_ERROR_DEVICE_ERROR;
philware 1:d4ff95ab40ae 292 LOCK();
philware 1:d4ff95ab40ae 293
philware 1:d4ff95ab40ae 294 MBED_ASSERT(_at != NULL);
philware 1:d4ff95ab40ae 295
philware 1:d4ff95ab40ae 296 // The response will be handled by the CEREG URC, by waiting for the OK we know it has been serviced.
philware 1:d4ff95ab40ae 297 if (at_send("AT+CEREG?")){
philware 1:d4ff95ab40ae 298 r = _dev_info.reg_status_eps;
philware 1:d4ff95ab40ae 299 }
philware 1:d4ff95ab40ae 300
philware 1:d4ff95ab40ae 301 UNLOCK();
philware 1:d4ff95ab40ae 302 return r;
philware 1:d4ff95ab40ae 303 }
philware 1:d4ff95ab40ae 304
philware 1:d4ff95ab40ae 305 nsapi_error_t UbloxCellularBaseN2xx::get_cscon() {
philware 1:d4ff95ab40ae 306 char resp[3+1];
philware 1:d4ff95ab40ae 307
philware 1:d4ff95ab40ae 308 int n, stat;
philware 1:d4ff95ab40ae 309
philware 1:d4ff95ab40ae 310 if (at_req("AT+CSCON?", "+CSCON:%3[^\n]\n", resp) &&
philware 1:d4ff95ab40ae 311 sscanf(resp, "%d,%d", &n, &stat)) {
philware 1:d4ff95ab40ae 312 return stat;
philware 1:d4ff95ab40ae 313 }
philware 1:d4ff95ab40ae 314
philware 1:d4ff95ab40ae 315 return NSAPI_ERROR_DEVICE_ERROR;
philware 1:d4ff95ab40ae 316 }
philware 1:d4ff95ab40ae 317
philware 1:d4ff95ab40ae 318 nsapi_error_t UbloxCellularBaseN2xx::get_csq() {
philware 1:d4ff95ab40ae 319 char resp[5+1];
philware 1:d4ff95ab40ae 320 nsapi_error_t rssi = NSAPI_ERROR_DEVICE_ERROR;
philware 1:d4ff95ab40ae 321
philware 1:d4ff95ab40ae 322 LOCK();
philware 1:d4ff95ab40ae 323 MBED_ASSERT(_at != NULL);
philware 1:d4ff95ab40ae 324
philware 1:d4ff95ab40ae 325 if (at_req("AT+CSQ", "+CSQ:%5[^\n]\n", resp) &&
philware 1:d4ff95ab40ae 326 sscanf(resp, "%d,%*d", &rssi)) {
philware 1:d4ff95ab40ae 327 return rssi;
philware 1:d4ff95ab40ae 328 }
philware 1:d4ff95ab40ae 329
philware 1:d4ff95ab40ae 330 UNLOCK();
philware 1:d4ff95ab40ae 331 return rssi;
philware 1:d4ff95ab40ae 332 }
philware 1:d4ff95ab40ae 333
philware 1:d4ff95ab40ae 334 bool UbloxCellularBaseN2xx::cops(const char *plmn) {
philware 1:d4ff95ab40ae 335 return at_send("AT+COPS=1,2,\"%s\"", plmn);
philware 1:d4ff95ab40ae 336 }
philware 1:d4ff95ab40ae 337
philware 1:d4ff95ab40ae 338 bool UbloxCellularBaseN2xx::cops(int mode) {
philware 1:d4ff95ab40ae 339 return at_send("AT+COPS=%d", mode);
philware 1:d4ff95ab40ae 340 }
philware 1:d4ff95ab40ae 341
philware 1:d4ff95ab40ae 342 bool UbloxCellularBaseN2xx::get_cops(int *status) {
philware 1:d4ff95ab40ae 343 return at_req("AT+COPS?", "+COPS: %d", status);
philware 1:d4ff95ab40ae 344 }
philware 1:d4ff95ab40ae 345
philware 1:d4ff95ab40ae 346 bool UbloxCellularBaseN2xx::cfun(int mode) {
philware 1:d4ff95ab40ae 347 return at_send("AT+CFUN=%d", mode);
philware 1:d4ff95ab40ae 348 }
philware 1:d4ff95ab40ae 349
philware 1:d4ff95ab40ae 350 bool UbloxCellularBaseN2xx::reboot() {
philware 1:d4ff95ab40ae 351 return at_send("AT+NRB");
philware 1:d4ff95ab40ae 352 }
philware 1:d4ff95ab40ae 353
philware 1:d4ff95ab40ae 354 bool UbloxCellularBaseN2xx::auto_connect(bool state) {
philware 1:d4ff95ab40ae 355 return nconfig("AUTOCONNECT", state);
philware 1:d4ff95ab40ae 356 }
philware 1:d4ff95ab40ae 357
philware 1:d4ff95ab40ae 358 bool UbloxCellularBaseN2xx::nconfig(const char *name, bool state) {
philware 1:d4ff95ab40ae 359 char n[50];
philware 1:d4ff95ab40ae 360
philware 1:d4ff95ab40ae 361 if (state)
philware 1:d4ff95ab40ae 362 sprintf(n, "AT+NCONFIG=%s,TRUE", name);
philware 1:d4ff95ab40ae 363 else
philware 1:d4ff95ab40ae 364 sprintf(n, "AT+NCONFIG=%s,FALSE", name);
philware 1:d4ff95ab40ae 365
philware 1:d4ff95ab40ae 366 return at_send(n);
philware 1:d4ff95ab40ae 367 }
philware 1:d4ff95ab40ae 368
philware 1:d4ff95ab40ae 369 bool UbloxCellularBaseN2xx::get_iccid()
philware 1:d4ff95ab40ae 370 {
philware 1:d4ff95ab40ae 371 // Returns the ICCID (Integrated Circuit Card ID) of the SIM-card.
philware 1:d4ff95ab40ae 372 // ICCID is a serial number identifying the SIM.
philware 1:d4ff95ab40ae 373 // AT Command Manual UBX-13002752, section 4.12
philware 1:d4ff95ab40ae 374 bool success = ccid(_dev_info.iccid);
philware 1:d4ff95ab40ae 375 tr_info("DevInfo: ICCID=%s", _dev_info.iccid);
philware 1:d4ff95ab40ae 376
philware 1:d4ff95ab40ae 377 return success;
philware 1:d4ff95ab40ae 378 }
philware 1:d4ff95ab40ae 379
philware 1:d4ff95ab40ae 380 bool UbloxCellularBaseN2xx::get_imsi()
philware 1:d4ff95ab40ae 381 {
philware 1:d4ff95ab40ae 382 // International mobile subscriber identification
philware 1:d4ff95ab40ae 383 // AT Command Manual UBX-13002752, section 4.11
philware 1:d4ff95ab40ae 384 bool success = cimi(_dev_info.imsi);
philware 1:d4ff95ab40ae 385 tr_info("DevInfo: IMSI=%s", _dev_info.imsi);
philware 1:d4ff95ab40ae 386
philware 1:d4ff95ab40ae 387 return success;
philware 1:d4ff95ab40ae 388 }
philware 1:d4ff95ab40ae 389
philware 1:d4ff95ab40ae 390 bool UbloxCellularBaseN2xx::get_imei()
philware 1:d4ff95ab40ae 391 {
philware 1:d4ff95ab40ae 392 // International mobile equipment identifier
philware 1:d4ff95ab40ae 393 // AT Command Manual UBX-13002752, section 4.7
philware 1:d4ff95ab40ae 394 bool success = cgsn(1, _dev_info.imei);
philware 1:d4ff95ab40ae 395 tr_info("DevInfo: IMEI=%s", _dev_info.imei);
philware 1:d4ff95ab40ae 396
philware 1:d4ff95ab40ae 397 return success;
philware 1:d4ff95ab40ae 398 }
philware 1:d4ff95ab40ae 399
philware 1:d4ff95ab40ae 400 bool UbloxCellularBaseN2xx::get_meid()
philware 1:d4ff95ab40ae 401 {
philware 1:d4ff95ab40ae 402 // *** NOT IMPLEMENTED
philware 1:d4ff95ab40ae 403 return false;
philware 1:d4ff95ab40ae 404
philware 1:d4ff95ab40ae 405 bool success;
philware 1:d4ff95ab40ae 406 LOCK();
philware 1:d4ff95ab40ae 407
philware 1:d4ff95ab40ae 408 MBED_ASSERT(_at != NULL);
philware 1:d4ff95ab40ae 409
philware 1:d4ff95ab40ae 410 // Mobile equipment identifier
philware 1:d4ff95ab40ae 411 // AT Command Manual UBX-13002752, section 4.8
philware 1:d4ff95ab40ae 412 success = _at->send("AT+GSN") && _at->recv("%18[^\n]\nOK\n", _dev_info.meid);
philware 1:d4ff95ab40ae 413
philware 1:d4ff95ab40ae 414 // tr_info("DevInfo: MEID=%s", _dev_info.meid);
philware 1:d4ff95ab40ae 415
philware 1:d4ff95ab40ae 416 UNLOCK();
philware 1:d4ff95ab40ae 417 return success;
philware 1:d4ff95ab40ae 418 }
philware 1:d4ff95ab40ae 419
philware 1:d4ff95ab40ae 420 bool UbloxCellularBaseN2xx::set_sms()
philware 1:d4ff95ab40ae 421 {
philware 1:d4ff95ab40ae 422 // *** NOT IMPLEMENTED
philware 1:d4ff95ab40ae 423 return false;
philware 1:d4ff95ab40ae 424
philware 1:d4ff95ab40ae 425 bool success = false;
philware 1:d4ff95ab40ae 426 char buf[32];
philware 1:d4ff95ab40ae 427 LOCK();
philware 1:d4ff95ab40ae 428
philware 1:d4ff95ab40ae 429 MBED_ASSERT(_at != NULL);
philware 1:d4ff95ab40ae 430
philware 1:d4ff95ab40ae 431 // Set up SMS format and enable URC
philware 1:d4ff95ab40ae 432 // AT Command Manual UBX-13002752, section 11
philware 1:d4ff95ab40ae 433 if (_at->send("AT+CMGF=1") && _at->recv("OK")) {
philware 1:d4ff95ab40ae 434 tr_debug("SMS in text mode");
philware 1:d4ff95ab40ae 435 if (_at->send("AT+CNMI=2,1") && _at->recv("OK")) {
philware 1:d4ff95ab40ae 436 tr_debug("SMS URC enabled");
philware 1:d4ff95ab40ae 437 // Set to CS preferred since PS preferred doesn't work
philware 1:d4ff95ab40ae 438 // on some networks
philware 1:d4ff95ab40ae 439 if (_at->send("AT+CGSMS=1") && _at->recv("OK")) {
philware 1:d4ff95ab40ae 440 tr_debug("SMS set to CS preferred");
philware 1:d4ff95ab40ae 441 success = true;
philware 1:d4ff95ab40ae 442 memset (buf, 0, sizeof (buf));
philware 1:d4ff95ab40ae 443 if (_at->send("AT+CSCA?") &&
philware 1:d4ff95ab40ae 444 _at->recv("+CSCA: \"%31[^\"]\"", buf) &&
philware 1:d4ff95ab40ae 445 _at->recv("OK")) {
philware 1:d4ff95ab40ae 446 tr_info("SMS Service Centre address is \"%s\"", buf);
philware 1:d4ff95ab40ae 447 }
philware 1:d4ff95ab40ae 448 }
philware 1:d4ff95ab40ae 449 }
philware 1:d4ff95ab40ae 450 }
philware 1:d4ff95ab40ae 451
philware 1:d4ff95ab40ae 452 UNLOCK();
philware 1:d4ff95ab40ae 453 return success;
philware 1:d4ff95ab40ae 454 }
philware 1:d4ff95ab40ae 455
philware 1:d4ff95ab40ae 456 void UbloxCellularBaseN2xx::parser_abort_cb()
philware 1:d4ff95ab40ae 457 {
philware 1:d4ff95ab40ae 458 _at->abort();
philware 1:d4ff95ab40ae 459 }
philware 1:d4ff95ab40ae 460
philware 1:d4ff95ab40ae 461 // Callback for CME ERROR and CMS ERROR.
philware 1:d4ff95ab40ae 462 void UbloxCellularBaseN2xx::CMX_ERROR_URC()
philware 1:d4ff95ab40ae 463 {
philware 1:d4ff95ab40ae 464 char buf[48];
philware 1:d4ff95ab40ae 465
philware 1:d4ff95ab40ae 466 if (read_at_to_char(buf, sizeof (buf), '\n') > 0) {
philware 1:d4ff95ab40ae 467 tr_debug("AT error %s", buf);
philware 1:d4ff95ab40ae 468 }
philware 1:d4ff95ab40ae 469 parser_abort_cb();
philware 1:d4ff95ab40ae 470 }
philware 1:d4ff95ab40ae 471
philware 1:d4ff95ab40ae 472 // Callback for EPS registration URC.
philware 1:d4ff95ab40ae 473 void UbloxCellularBaseN2xx::CEREG_URC()
philware 1:d4ff95ab40ae 474 {
philware 1:d4ff95ab40ae 475 char buf[20];
philware 1:d4ff95ab40ae 476 int status;
philware 1:d4ff95ab40ae 477 int n, AcT;
philware 1:d4ff95ab40ae 478 char tac[4], ci[4];
philware 1:d4ff95ab40ae 479
philware 1:d4ff95ab40ae 480 // If this is the URC it will be a single
philware 1:d4ff95ab40ae 481 // digit followed by \n. If it is the
philware 1:d4ff95ab40ae 482 // answer to a CEREG query, it will be
philware 1:d4ff95ab40ae 483 // a ": %d,%d\n" where the second digit
philware 1:d4ff95ab40ae 484 // indicates the status
philware 1:d4ff95ab40ae 485 // Note: not calling _at->recv() from here as we're
philware 1:d4ff95ab40ae 486 // already in an _at->recv()
philware 1:d4ff95ab40ae 487 // We also hanlde the extended 4 or 5 argument
philware 1:d4ff95ab40ae 488 // response if cereg is set to 2.
philware 1:d4ff95ab40ae 489 if (read_at_to_newline(buf, sizeof (buf)) > 0) {
philware 1:d4ff95ab40ae 490 if (sscanf(buf, ":%d,%d,%[0123456789abcdef],%[0123456789abcdef],%d\n", &n, &status, tac, ci, &AcT) == 5) {
philware 1:d4ff95ab40ae 491 set_nwk_reg_status_eps(status);
philware 1:d4ff95ab40ae 492 } else if (sscanf(buf, ":%d,%[0123456789abcdef],%[0123456789abcdef],%d\n`", &status, tac, ci, &AcT) == 4) {
philware 1:d4ff95ab40ae 493 set_nwk_reg_status_eps(status);
philware 1:d4ff95ab40ae 494 } else if (sscanf(buf, ":%d,%d\n", &n, &status) == 2) {
philware 1:d4ff95ab40ae 495 set_nwk_reg_status_eps(status);
philware 1:d4ff95ab40ae 496 } else if (sscanf(buf, ":%d\n", &status) == 1) {
philware 1:d4ff95ab40ae 497 set_nwk_reg_status_eps(status);
philware 1:d4ff95ab40ae 498 }
philware 1:d4ff95ab40ae 499 }
philware 1:d4ff95ab40ae 500 }
philware 1:d4ff95ab40ae 501
philware 1:d4ff95ab40ae 502 /**********************************************************************
philware 1:d4ff95ab40ae 503 * PROTECTED METHODS
philware 1:d4ff95ab40ae 504 **********************************************************************/
philware 1:d4ff95ab40ae 505
philware 1:d4ff95ab40ae 506 #if MODEM_ON_BOARD
philware 1:d4ff95ab40ae 507 void UbloxCellularBaseN2xx::modem_init()
philware 1:d4ff95ab40ae 508 {
philware 1:d4ff95ab40ae 509 ::onboard_modem_init();
philware 1:d4ff95ab40ae 510 }
philware 1:d4ff95ab40ae 511
philware 1:d4ff95ab40ae 512 void UbloxCellularBaseN2xx::modem_deinit()
philware 1:d4ff95ab40ae 513 {
philware 1:d4ff95ab40ae 514 ::onboard_modem_deinit();
philware 1:d4ff95ab40ae 515 }
philware 1:d4ff95ab40ae 516
philware 1:d4ff95ab40ae 517 void UbloxCellularBaseN2xx::modem_power_up()
philware 1:d4ff95ab40ae 518 {
philware 1:d4ff95ab40ae 519 ::onboard_modem_power_up();
philware 1:d4ff95ab40ae 520 }
philware 1:d4ff95ab40ae 521
philware 1:d4ff95ab40ae 522 void UbloxCellularBaseN2xx::modem_power_down()
philware 1:d4ff95ab40ae 523 {
philware 1:d4ff95ab40ae 524 ::onboard_modem_power_down();
philware 1:d4ff95ab40ae 525 }
philware 1:d4ff95ab40ae 526 #else
philware 1:d4ff95ab40ae 527 void UbloxCellularBaseN2xx::modem_init()
philware 1:d4ff95ab40ae 528 {
philware 1:d4ff95ab40ae 529 // Meant to be overridden
philware 1:d4ff95ab40ae 530 #error need to do something here!
philware 1:d4ff95ab40ae 531 }
philware 1:d4ff95ab40ae 532
philware 1:d4ff95ab40ae 533 void UbloxCellularBaseN2xx::modem_deinit()
philware 1:d4ff95ab40ae 534 {
philware 1:d4ff95ab40ae 535 // Meant to be overridden
philware 1:d4ff95ab40ae 536 }
philware 1:d4ff95ab40ae 537
philware 1:d4ff95ab40ae 538 void UbloxCellularBaseN2xx::modem_power_up()
philware 1:d4ff95ab40ae 539 {
philware 1:d4ff95ab40ae 540 // Meant to be overridden
philware 1:d4ff95ab40ae 541 }
philware 1:d4ff95ab40ae 542
philware 1:d4ff95ab40ae 543 void UbloxCellularBaseN2xx::modem_power_down()
philware 1:d4ff95ab40ae 544 {
philware 1:d4ff95ab40ae 545 // Mmeant to be overridden
philware 1:d4ff95ab40ae 546 }
philware 1:d4ff95ab40ae 547 #endif
philware 1:d4ff95ab40ae 548
philware 1:d4ff95ab40ae 549 // Constructor.
philware 1:d4ff95ab40ae 550 // Note: to allow this base class to be inherited as a virtual base class
philware 1:d4ff95ab40ae 551 // by everyone, it takes no parameters. See also comment above classInit()
philware 1:d4ff95ab40ae 552 // in the header file.
philware 1:d4ff95ab40ae 553 UbloxCellularBaseN2xx::UbloxCellularBaseN2xx()
philware 1:d4ff95ab40ae 554 {
philware 1:d4ff95ab40ae 555 tr_debug("UbloxATCellularBaseN2xx Constructor");
philware 1:d4ff95ab40ae 556
philware 1:d4ff95ab40ae 557 _pin = NULL;
philware 1:d4ff95ab40ae 558 _at = NULL;
philware 1:d4ff95ab40ae 559 _at_timeout = AT_PARSER_TIMEOUT;
philware 1:d4ff95ab40ae 560 _fh = NULL;
philware 1:d4ff95ab40ae 561 _modem_initialised = false;
philware 1:d4ff95ab40ae 562 _sim_pin_check_enabled = false;
philware 1:d4ff95ab40ae 563 _debug_trace_on = false;
philware 1:d4ff95ab40ae 564
philware 1:d4ff95ab40ae 565 _dev_info.dev = DEV_TYPE_NONE;
philware 1:d4ff95ab40ae 566 _dev_info.reg_status_csd = CSD_NOT_REGISTERED_NOT_SEARCHING;
philware 1:d4ff95ab40ae 567 _dev_info.reg_status_psd = PSD_NOT_REGISTERED_NOT_SEARCHING;
philware 1:d4ff95ab40ae 568 _dev_info.reg_status_eps = EPS_NOT_REGISTERED_NOT_SEARCHING;
philware 1:d4ff95ab40ae 569 }
philware 1:d4ff95ab40ae 570
philware 1:d4ff95ab40ae 571 // Destructor.
philware 1:d4ff95ab40ae 572 UbloxCellularBaseN2xx::~UbloxCellularBaseN2xx()
philware 1:d4ff95ab40ae 573 {
philware 1:d4ff95ab40ae 574 deinit();
philware 1:d4ff95ab40ae 575 delete _at;
philware 1:d4ff95ab40ae 576 delete _fh;
philware 1:d4ff95ab40ae 577 }
philware 1:d4ff95ab40ae 578
philware 1:d4ff95ab40ae 579 // Initialise the portions of this class that are parameterised.
philware 1:d4ff95ab40ae 580 void UbloxCellularBaseN2xx::baseClassInit(PinName tx, PinName rx,
philware 1:d4ff95ab40ae 581 int baud, bool debug_on)
philware 1:d4ff95ab40ae 582 {
philware 1:d4ff95ab40ae 583 // Only initialise ourselves if it's not already been done
philware 1:d4ff95ab40ae 584 if (_at == NULL) {
philware 1:d4ff95ab40ae 585 if (_debug_trace_on == false) {
philware 1:d4ff95ab40ae 586 _debug_trace_on = debug_on;
philware 1:d4ff95ab40ae 587 }
philware 1:d4ff95ab40ae 588
philware 1:d4ff95ab40ae 589 // Set up File Handle for buffered serial comms with cellular module
philware 1:d4ff95ab40ae 590 // (which will be used by the AT parser)
philware 1:d4ff95ab40ae 591 _fh = new UARTSerial(tx, rx, baud);
philware 1:d4ff95ab40ae 592
philware 1:d4ff95ab40ae 593 // Set up the AT parser
philware 1:d4ff95ab40ae 594 _at = new ATCmdParser(_fh, OUTPUT_ENTER_KEY, AT_PARSER_BUFFER_SIZE,
philware 1:d4ff95ab40ae 595 _at_timeout, _debug_trace_on);
philware 1:d4ff95ab40ae 596
philware 1:d4ff95ab40ae 597 // Error cases, out of band handling
philware 1:d4ff95ab40ae 598 _at->oob("ERROR", callback(this, &UbloxCellularBaseN2xx::parser_abort_cb));
philware 1:d4ff95ab40ae 599 _at->oob("+CME ERROR", callback(this, &UbloxCellularBaseN2xx::CMX_ERROR_URC));
philware 1:d4ff95ab40ae 600 _at->oob("+CMS ERROR", callback(this, &UbloxCellularBaseN2xx::CMX_ERROR_URC));
philware 1:d4ff95ab40ae 601
philware 1:d4ff95ab40ae 602 // Registration status, out of band handling
philware 1:d4ff95ab40ae 603 _at->oob("+CEREG", callback(this, &UbloxCellularBaseN2xx::CEREG_URC));
philware 1:d4ff95ab40ae 604 }
philware 1:d4ff95ab40ae 605 }
philware 1:d4ff95ab40ae 606
philware 1:d4ff95ab40ae 607 // Set the AT parser timeout.
philware 1:d4ff95ab40ae 608 // Note: the AT interface should be locked before this is called.
philware 1:d4ff95ab40ae 609 void UbloxCellularBaseN2xx::at_set_timeout(int timeout) {
philware 1:d4ff95ab40ae 610
philware 1:d4ff95ab40ae 611 MBED_ASSERT(_at != NULL);
philware 1:d4ff95ab40ae 612
philware 1:d4ff95ab40ae 613 _at_timeout = timeout;
philware 1:d4ff95ab40ae 614 _at->set_timeout(timeout);
philware 1:d4ff95ab40ae 615 }
philware 1:d4ff95ab40ae 616
philware 1:d4ff95ab40ae 617 // Read up to size bytes from the AT interface up to a "end".
philware 1:d4ff95ab40ae 618 // Note: the AT interface should be locked before this is called.
philware 1:d4ff95ab40ae 619 int UbloxCellularBaseN2xx::read_at_to_char(char * buf, int size, char end)
philware 1:d4ff95ab40ae 620 {
philware 1:d4ff95ab40ae 621 int count = 0;
philware 1:d4ff95ab40ae 622 int x = 0;
philware 1:d4ff95ab40ae 623
philware 1:d4ff95ab40ae 624 if (size > 0) {
philware 1:d4ff95ab40ae 625 for (count = 0; (count < size) && (x >= 0) && (x != end); count++) {
philware 1:d4ff95ab40ae 626 x = _at->getc();
philware 1:d4ff95ab40ae 627 *(buf + count) = (char) x;
philware 1:d4ff95ab40ae 628 }
philware 1:d4ff95ab40ae 629
philware 1:d4ff95ab40ae 630 count--;
philware 1:d4ff95ab40ae 631 *(buf + count) = 0;
philware 1:d4ff95ab40ae 632
philware 1:d4ff95ab40ae 633 // Convert line endings:
philware 1:d4ff95ab40ae 634 // If end was '\n' (0x0a) and the preceding character was 0x0d, then
philware 1:d4ff95ab40ae 635 // overwrite that with null as well.
philware 1:d4ff95ab40ae 636 if ((count > 0) && (end == '\n') && (*(buf + count - 1) == '\x0d')) {
philware 1:d4ff95ab40ae 637 count--;
philware 1:d4ff95ab40ae 638 *(buf + count) = 0;
philware 1:d4ff95ab40ae 639 }
philware 1:d4ff95ab40ae 640 }
philware 1:d4ff95ab40ae 641
philware 1:d4ff95ab40ae 642 return count;
philware 1:d4ff95ab40ae 643 }
philware 1:d4ff95ab40ae 644
philware 1:d4ff95ab40ae 645 // Power up the modem.
philware 1:d4ff95ab40ae 646 // Enables the GPIO lines to the modem and then wriggles the power line in short pulses.
philware 1:d4ff95ab40ae 647 bool UbloxCellularBaseN2xx::power_up()
philware 1:d4ff95ab40ae 648 {
philware 1:d4ff95ab40ae 649 bool success = false;
philware 1:d4ff95ab40ae 650 int at_timeout;
philware 1:d4ff95ab40ae 651 LOCK();
philware 1:d4ff95ab40ae 652
philware 1:d4ff95ab40ae 653 at_timeout = _at_timeout; // Has to be inside LOCK()s
philware 1:d4ff95ab40ae 654
philware 1:d4ff95ab40ae 655 MBED_ASSERT(_at != NULL);
philware 1:d4ff95ab40ae 656
philware 1:d4ff95ab40ae 657 /* Initialize GPIO lines */
philware 1:d4ff95ab40ae 658 tr_info("Powering up modem...");
philware 1:d4ff95ab40ae 659 onboard_modem_init();
philware 1:d4ff95ab40ae 660 /* Give SARA-N2XX time to reset */
philware 1:d4ff95ab40ae 661 tr_debug("Waiting for 5 seconds (booting SARA-N2xx)...");
philware 1:d4ff95ab40ae 662 wait_ms(5000);
philware 1:d4ff95ab40ae 663
philware 1:d4ff95ab40ae 664 at_set_timeout(1000);
philware 1:d4ff95ab40ae 665 for (int retry_count = 0; !success && (retry_count < 20); retry_count++) {
philware 1:d4ff95ab40ae 666 _at->flush();
philware 1:d4ff95ab40ae 667 if (at_send("AT")) {
philware 1:d4ff95ab40ae 668 success = true;
philware 1:d4ff95ab40ae 669 }
philware 1:d4ff95ab40ae 670 }
philware 1:d4ff95ab40ae 671 at_set_timeout(at_timeout);
philware 1:d4ff95ab40ae 672
philware 1:d4ff95ab40ae 673 // perform any initialisation AT commands here
philware 1:d4ff95ab40ae 674 if (success) {
philware 1:d4ff95ab40ae 675 success = at_send("AT+CMEE=1"); // Turn on verbose responses
philware 1:d4ff95ab40ae 676 }
philware 1:d4ff95ab40ae 677
philware 1:d4ff95ab40ae 678 if (!success) {
philware 1:d4ff95ab40ae 679 tr_error("Preliminary modem setup failed.");
philware 1:d4ff95ab40ae 680 }
philware 1:d4ff95ab40ae 681
philware 1:d4ff95ab40ae 682 UNLOCK();
philware 1:d4ff95ab40ae 683 return success;
philware 1:d4ff95ab40ae 684 }
philware 1:d4ff95ab40ae 685
philware 1:d4ff95ab40ae 686 // Power down modem via AT interface.
philware 1:d4ff95ab40ae 687 void UbloxCellularBaseN2xx::power_down()
philware 1:d4ff95ab40ae 688 {
philware 1:d4ff95ab40ae 689 LOCK();
philware 1:d4ff95ab40ae 690
philware 1:d4ff95ab40ae 691 MBED_ASSERT(_at != NULL);
philware 1:d4ff95ab40ae 692
philware 1:d4ff95ab40ae 693 // If we have been running, do a soft power-off first
philware 1:d4ff95ab40ae 694 if (_modem_initialised && (_at != NULL)) {
philware 1:d4ff95ab40ae 695 // NOT IMPLEMENTED in B656 firmware
philware 1:d4ff95ab40ae 696 // at_send("AT+CPWROFF");
philware 1:d4ff95ab40ae 697 }
philware 1:d4ff95ab40ae 698
philware 1:d4ff95ab40ae 699 // Now do a hard power-off
philware 1:d4ff95ab40ae 700 onboard_modem_power_down();
philware 1:d4ff95ab40ae 701 onboard_modem_deinit();
philware 1:d4ff95ab40ae 702
philware 1:d4ff95ab40ae 703 _dev_info.reg_status_csd = CSD_NOT_REGISTERED_NOT_SEARCHING;
philware 1:d4ff95ab40ae 704 _dev_info.reg_status_psd = PSD_NOT_REGISTERED_NOT_SEARCHING;
philware 1:d4ff95ab40ae 705 _dev_info.reg_status_eps = EPS_NOT_REGISTERED_NOT_SEARCHING;
philware 1:d4ff95ab40ae 706
philware 1:d4ff95ab40ae 707 UNLOCK();
philware 1:d4ff95ab40ae 708 }
philware 1:d4ff95ab40ae 709
philware 1:d4ff95ab40ae 710 // Get the device ID.
philware 1:d4ff95ab40ae 711 bool UbloxCellularBaseN2xx::set_device_identity(DeviceType *dev)
philware 1:d4ff95ab40ae 712 {
philware 1:d4ff95ab40ae 713 char buf[20];
philware 1:d4ff95ab40ae 714 bool success;
philware 1:d4ff95ab40ae 715 LOCK();
philware 1:d4ff95ab40ae 716
philware 1:d4ff95ab40ae 717 MBED_ASSERT(_at != NULL);
philware 1:d4ff95ab40ae 718
philware 1:d4ff95ab40ae 719 success = at_req("AT+CGMM", "%19[^\n]\n", buf);
philware 1:d4ff95ab40ae 720
philware 1:d4ff95ab40ae 721 if (success) {
philware 1:d4ff95ab40ae 722 if (strstr(buf, "Neul Hi2110"))
philware 1:d4ff95ab40ae 723 *dev = DEV_SARA_N2;
philware 1:d4ff95ab40ae 724 }
philware 1:d4ff95ab40ae 725
philware 1:d4ff95ab40ae 726 UNLOCK();
philware 1:d4ff95ab40ae 727 return success;
philware 1:d4ff95ab40ae 728 }
philware 1:d4ff95ab40ae 729
philware 1:d4ff95ab40ae 730 // Send initialisation AT commands that are specific to the device.
philware 1:d4ff95ab40ae 731 bool UbloxCellularBaseN2xx::device_init(DeviceType dev)
philware 1:d4ff95ab40ae 732 {
philware 1:d4ff95ab40ae 733 // SARA-N2xx doesn't have anything to initialise
philware 1:d4ff95ab40ae 734 return true;
philware 1:d4ff95ab40ae 735 }
philware 1:d4ff95ab40ae 736
philware 1:d4ff95ab40ae 737 // Get the SIM card going.
philware 1:d4ff95ab40ae 738 bool UbloxCellularBaseN2xx::initialise_sim_card()
philware 1:d4ff95ab40ae 739 {
philware 1:d4ff95ab40ae 740 // SARA-N2XX doesn't have any SIM AT Commands for now.
philware 1:d4ff95ab40ae 741 return true;
philware 1:d4ff95ab40ae 742 }
philware 1:d4ff95ab40ae 743
philware 1:d4ff95ab40ae 744 /**********************************************************************
philware 1:d4ff95ab40ae 745 * PUBLIC METHODS
philware 1:d4ff95ab40ae 746 **********************************************************************/
philware 1:d4ff95ab40ae 747
philware 1:d4ff95ab40ae 748 // Initialise the modem.
philware 1:d4ff95ab40ae 749 bool UbloxCellularBaseN2xx::init(const char *pin)
philware 1:d4ff95ab40ae 750 {
philware 1:d4ff95ab40ae 751 MBED_ASSERT(_at != NULL);
philware 1:d4ff95ab40ae 752
philware 1:d4ff95ab40ae 753 if (!_modem_initialised) {
philware 1:d4ff95ab40ae 754 if (power_up()) {
philware 1:d4ff95ab40ae 755 tr_info("Modem Ready.");
philware 1:d4ff95ab40ae 756 if (pin != NULL) {
philware 1:d4ff95ab40ae 757 _pin = pin;
philware 1:d4ff95ab40ae 758 }
philware 1:d4ff95ab40ae 759
philware 1:d4ff95ab40ae 760 if (initialise_sim_card()) {
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 1:d4ff95ab40ae 776 }
philware 1:d4ff95ab40ae 777 }
philware 1:d4ff95ab40ae 778
philware 1:d4ff95ab40ae 779 return _modem_initialised;
philware 1:d4ff95ab40ae 780 }
philware 1:d4ff95ab40ae 781
philware 1:d4ff95ab40ae 782 // Perform registration.
philware 1:d4ff95ab40ae 783 bool UbloxCellularBaseN2xx::nwk_registration()
philware 1:d4ff95ab40ae 784 {
philware 1:d4ff95ab40ae 785 bool registered = false;
philware 1:d4ff95ab40ae 786 int status;
philware 1:d4ff95ab40ae 787 int at_timeout;
philware 1:d4ff95ab40ae 788 LOCK();
philware 1:d4ff95ab40ae 789
philware 1:d4ff95ab40ae 790 at_timeout = _at_timeout; // Has to be inside LOCK()s
philware 1:d4ff95ab40ae 791
philware 1:d4ff95ab40ae 792 MBED_ASSERT(_at != NULL);
philware 1:d4ff95ab40ae 793
philware 1:d4ff95ab40ae 794 // Enable the packet switched and network registration unsolicited result codes
philware 1:d4ff95ab40ae 795 if (cereg(1)) {
philware 1:d4ff95ab40ae 796 // See if we are already in automatic mode
philware 1:d4ff95ab40ae 797 if (get_cops(&status)) {
philware 1:d4ff95ab40ae 798 if (status != 0) {
philware 1:d4ff95ab40ae 799 // Don't check return code here as there's not much
philware 1:d4ff95ab40ae 800 // we can do if this fails.
philware 1:d4ff95ab40ae 801 cops(0);
philware 1:d4ff95ab40ae 802 }
philware 1:d4ff95ab40ae 803 }
philware 1:d4ff95ab40ae 804
philware 1:d4ff95ab40ae 805 // query cereg just in case
philware 1:d4ff95ab40ae 806 get_cereg();
philware 1:d4ff95ab40ae 807 registered = is_registered_eps();
philware 1:d4ff95ab40ae 808
philware 1:d4ff95ab40ae 809 at_set_timeout(1000);
philware 1:d4ff95ab40ae 810 for (int waitSeconds = 0; !registered && (waitSeconds < 180); waitSeconds++) {
philware 1:d4ff95ab40ae 811 _at->recv(UNNATURAL_STRING);
philware 1:d4ff95ab40ae 812 registered = is_registered_eps();
philware 1:d4ff95ab40ae 813 }
philware 1:d4ff95ab40ae 814 at_set_timeout(at_timeout);
philware 1:d4ff95ab40ae 815 } else {
philware 1:d4ff95ab40ae 816 tr_error("Failed to set CEREG=1");
philware 1:d4ff95ab40ae 817 }
philware 1:d4ff95ab40ae 818
philware 1:d4ff95ab40ae 819 UNLOCK();
philware 1:d4ff95ab40ae 820 return registered;
philware 1:d4ff95ab40ae 821 }
philware 1:d4ff95ab40ae 822
philware 1:d4ff95ab40ae 823 bool UbloxCellularBaseN2xx::is_registered_csd()
philware 1:d4ff95ab40ae 824 {
philware 1:d4ff95ab40ae 825 return (_dev_info.reg_status_csd == CSD_REGISTERED) ||
philware 1:d4ff95ab40ae 826 (_dev_info.reg_status_csd == CSD_REGISTERED_ROAMING) ||
philware 1:d4ff95ab40ae 827 (_dev_info.reg_status_csd == CSD_CSFB_NOT_PREFERRED);
philware 1:d4ff95ab40ae 828 }
philware 1:d4ff95ab40ae 829
philware 1:d4ff95ab40ae 830 bool UbloxCellularBaseN2xx::is_registered_psd()
philware 1:d4ff95ab40ae 831 {
philware 1:d4ff95ab40ae 832 return (_dev_info.reg_status_psd == PSD_REGISTERED) ||
philware 1:d4ff95ab40ae 833 (_dev_info.reg_status_psd == PSD_REGISTERED_ROAMING);
philware 1:d4ff95ab40ae 834 }
philware 1:d4ff95ab40ae 835
philware 1:d4ff95ab40ae 836 bool UbloxCellularBaseN2xx::is_registered_eps()
philware 1:d4ff95ab40ae 837 {
philware 1:d4ff95ab40ae 838 return (_dev_info.reg_status_eps == EPS_REGISTERED) ||
philware 1:d4ff95ab40ae 839 (_dev_info.reg_status_eps == EPS_REGISTERED_ROAMING);
philware 1:d4ff95ab40ae 840 }
philware 1:d4ff95ab40ae 841
philware 1:d4ff95ab40ae 842 // Perform deregistration.
philware 1:d4ff95ab40ae 843 bool UbloxCellularBaseN2xx::nwk_deregistration()
philware 1:d4ff95ab40ae 844 {
philware 1:d4ff95ab40ae 845 bool success = false;
philware 1:d4ff95ab40ae 846
philware 1:d4ff95ab40ae 847 MBED_ASSERT(_at != NULL);
philware 1:d4ff95ab40ae 848
philware 1:d4ff95ab40ae 849 if (cops(2)) {
philware 1:d4ff95ab40ae 850 // we need to wait here so that the internal status of the module
philware 1:d4ff95ab40ae 851 wait_ms(1000);
philware 1:d4ff95ab40ae 852
philware 1:d4ff95ab40ae 853 _dev_info.reg_status_csd = CSD_NOT_REGISTERED_NOT_SEARCHING;
philware 1:d4ff95ab40ae 854 _dev_info.reg_status_psd = PSD_NOT_REGISTERED_NOT_SEARCHING;
philware 1:d4ff95ab40ae 855 _dev_info.reg_status_eps = EPS_NOT_REGISTERED_NOT_SEARCHING;
philware 1:d4ff95ab40ae 856
philware 1:d4ff95ab40ae 857 success = true;
philware 1:d4ff95ab40ae 858 } else {
philware 1:d4ff95ab40ae 859 tr_error("Failed to set COPS=2");
philware 1:d4ff95ab40ae 860 }
philware 1:d4ff95ab40ae 861
philware 1:d4ff95ab40ae 862 return success;
philware 1:d4ff95ab40ae 863 }
philware 1:d4ff95ab40ae 864
philware 1:d4ff95ab40ae 865 // Put the modem into its lowest power state.
philware 1:d4ff95ab40ae 866 void UbloxCellularBaseN2xx::deinit()
philware 1:d4ff95ab40ae 867 {
philware 1:d4ff95ab40ae 868 power_down();
philware 1:d4ff95ab40ae 869 _modem_initialised = false;
philware 1:d4ff95ab40ae 870 }
philware 1:d4ff95ab40ae 871
philware 1:d4ff95ab40ae 872 // Set the PIN.
philware 1:d4ff95ab40ae 873 void UbloxCellularBaseN2xx::set_pin(const char *pin) {
philware 1:d4ff95ab40ae 874 _pin = pin;
philware 1:d4ff95ab40ae 875 }
philware 1:d4ff95ab40ae 876
philware 1:d4ff95ab40ae 877 // Enable or disable SIM pin checking.
philware 1:d4ff95ab40ae 878 bool UbloxCellularBaseN2xx:: sim_pin_check_enable(bool enableNotDisable)
philware 1:d4ff95ab40ae 879 {
philware 1:d4ff95ab40ae 880 // *** NOT IMPLEMENTED on SARA-N2XX
philware 1:d4ff95ab40ae 881 return false;
philware 1:d4ff95ab40ae 882
philware 1:d4ff95ab40ae 883 bool success = false;
philware 1:d4ff95ab40ae 884 LOCK();
philware 1:d4ff95ab40ae 885
philware 1:d4ff95ab40ae 886 MBED_ASSERT(_at != NULL);
philware 1:d4ff95ab40ae 887
philware 1:d4ff95ab40ae 888 if (_pin != NULL) {
philware 1:d4ff95ab40ae 889 if (_sim_pin_check_enabled && !enableNotDisable) {
philware 1:d4ff95ab40ae 890 // Disable the SIM lock
philware 1:d4ff95ab40ae 891 if (_at->send("AT+CLCK=\"SC\",0,\"%s\"", _pin) && _at->recv("OK")) {
philware 1:d4ff95ab40ae 892 _sim_pin_check_enabled = false;
philware 1:d4ff95ab40ae 893 success = true;
philware 1:d4ff95ab40ae 894 }
philware 1:d4ff95ab40ae 895 } else if (!_sim_pin_check_enabled && enableNotDisable) {
philware 1:d4ff95ab40ae 896 // Enable the SIM lock
philware 1:d4ff95ab40ae 897 if (_at->send("AT+CLCK=\"SC\",1,\"%s\"", _pin) && _at->recv("OK")) {
philware 1:d4ff95ab40ae 898 _sim_pin_check_enabled = true;
philware 1:d4ff95ab40ae 899 success = true;
philware 1:d4ff95ab40ae 900 }
philware 1:d4ff95ab40ae 901 } else {
philware 1:d4ff95ab40ae 902 success = true;
philware 1:d4ff95ab40ae 903 }
philware 1:d4ff95ab40ae 904 }
philware 1:d4ff95ab40ae 905
philware 1:d4ff95ab40ae 906 UNLOCK();
philware 1:d4ff95ab40ae 907 return success;
philware 1:d4ff95ab40ae 908 }
philware 1:d4ff95ab40ae 909
philware 1:d4ff95ab40ae 910 // Change the pin code for the SIM card.
philware 1:d4ff95ab40ae 911 bool UbloxCellularBaseN2xx::change_sim_pin(const char *pin)
philware 1:d4ff95ab40ae 912 {
philware 1:d4ff95ab40ae 913 // *** NOT IMPLEMENTED on SARA-N2XX
philware 1:d4ff95ab40ae 914 return false;
philware 1:d4ff95ab40ae 915
philware 1:d4ff95ab40ae 916 bool success = false;
philware 1:d4ff95ab40ae 917 LOCK();
philware 1:d4ff95ab40ae 918
philware 1:d4ff95ab40ae 919 MBED_ASSERT(_at != NULL);
philware 1:d4ff95ab40ae 920
philware 1:d4ff95ab40ae 921 // Change the SIM pin
philware 1:d4ff95ab40ae 922 if ((pin != NULL) && (_pin != NULL)) {
philware 1:d4ff95ab40ae 923 if (_at->send("AT+CPWD=\"SC\",\"%s\",\"%s\"", _pin, pin) && _at->recv("OK")) {
philware 1:d4ff95ab40ae 924 _pin = pin;
philware 1:d4ff95ab40ae 925 success = true;
philware 1:d4ff95ab40ae 926 }
philware 1:d4ff95ab40ae 927 }
philware 1:d4ff95ab40ae 928
philware 1:d4ff95ab40ae 929 UNLOCK();
philware 1:d4ff95ab40ae 930 return success;
philware 1:d4ff95ab40ae 931 }
philware 1:d4ff95ab40ae 932
philware 1:d4ff95ab40ae 933 // Read up to size bytes from the AT interface up to a newline.
philware 1:d4ff95ab40ae 934 // This doesn't need a LOCK() UNLOCK() Wrapping as it's only called
philware 1:d4ff95ab40ae 935 // from the URC function, which are already in a lock
philware 1:d4ff95ab40ae 936 int UbloxCellularBaseN2xx::read_at_to_newline(char * buf, int size)
philware 1:d4ff95ab40ae 937 {
philware 1:d4ff95ab40ae 938 int count = 0;
philware 1:d4ff95ab40ae 939 int x = 0;
philware 1:d4ff95ab40ae 940
philware 1:d4ff95ab40ae 941 if (size > 0) {
philware 1:d4ff95ab40ae 942 for (count = 0; (count < size) && (x >= 0) && (x != '\n'); count++) {
philware 1:d4ff95ab40ae 943 x = _at->getc();
philware 1:d4ff95ab40ae 944 *(buf + count) = (char) x;
philware 1:d4ff95ab40ae 945 }
philware 1:d4ff95ab40ae 946
philware 1:d4ff95ab40ae 947 *(buf + count - 1) = 0;
philware 1:d4ff95ab40ae 948 count--;
philware 1:d4ff95ab40ae 949 }
philware 1:d4ff95ab40ae 950
philware 1:d4ff95ab40ae 951 return count;
philware 1:d4ff95ab40ae 952 }
philware 1:d4ff95ab40ae 953 // End of File
philware 1:d4ff95ab40ae 954