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:30:37 2017 +0100
Revision:
3:39eadc84c5ac
Parent:
1:d4ff95ab40ae
Child:
5:66451d314225
Improved some tr_debug lines

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 3:39eadc84c5ac 754 tr_warn("Modem not initialised, initialising...");
philware 1:d4ff95ab40ae 755 if (power_up()) {
philware 3:39eadc84c5ac 756 tr_info("Modem Powered Up.");
philware 1:d4ff95ab40ae 757 if (pin != NULL) {
philware 1:d4ff95ab40ae 758 _pin = pin;
philware 1:d4ff95ab40ae 759 }
philware 1:d4ff95ab40ae 760
philware 1:d4ff95ab40ae 761 if (initialise_sim_card()) {
philware 3:39eadc84c5ac 762 tr_info("Sim ready...");
philware 1:d4ff95ab40ae 763 if (set_device_identity(&_dev_info.dev) && // Set up device identity
philware 1:d4ff95ab40ae 764 device_init(_dev_info.dev) &&
philware 1:d4ff95ab40ae 765 get_sara_n2xx_info())
philware 1:d4ff95ab40ae 766 {
philware 1:d4ff95ab40ae 767 tr_debug("CGMM: %s", _sara_n2xx_info.cgmm);
philware 1:d4ff95ab40ae 768 tr_debug("CGMI: %s", _sara_n2xx_info.cgmi);
philware 1:d4ff95ab40ae 769 tr_debug("CGMR: %s", _sara_n2xx_info.cgmr);
philware 1:d4ff95ab40ae 770 tr_debug("CGSN: %s", _sara_n2xx_info.cgsn);
philware 1:d4ff95ab40ae 771
philware 1:d4ff95ab40ae 772 // The modem is initialised. The following checks my still fail,
philware 1:d4ff95ab40ae 773 // of course, but they are all of a "fatal" nature and so we wouldn't
philware 1:d4ff95ab40ae 774 // want to retry them anyway
philware 1:d4ff95ab40ae 775 _modem_initialised = true;
philware 1:d4ff95ab40ae 776 }
philware 1:d4ff95ab40ae 777 }
philware 3:39eadc84c5ac 778 } else {
philware 3:39eadc84c5ac 779 tr_error("Couldn't power up modem.");
philware 1:d4ff95ab40ae 780 }
philware 1:d4ff95ab40ae 781 }
philware 3:39eadc84c5ac 782 else {
philware 3:39eadc84c5ac 783 tr_info("Modem already initialised.");
philware 3:39eadc84c5ac 784 }
philware 1:d4ff95ab40ae 785
philware 1:d4ff95ab40ae 786 return _modem_initialised;
philware 1:d4ff95ab40ae 787 }
philware 1:d4ff95ab40ae 788
philware 1:d4ff95ab40ae 789 // Perform registration.
philware 1:d4ff95ab40ae 790 bool UbloxCellularBaseN2xx::nwk_registration()
philware 1:d4ff95ab40ae 791 {
philware 1:d4ff95ab40ae 792 bool registered = false;
philware 1:d4ff95ab40ae 793 int status;
philware 1:d4ff95ab40ae 794 int at_timeout;
philware 1:d4ff95ab40ae 795 LOCK();
philware 1:d4ff95ab40ae 796
philware 1:d4ff95ab40ae 797 at_timeout = _at_timeout; // Has to be inside LOCK()s
philware 1:d4ff95ab40ae 798
philware 1:d4ff95ab40ae 799 MBED_ASSERT(_at != NULL);
philware 1:d4ff95ab40ae 800
philware 1:d4ff95ab40ae 801 // Enable the packet switched and network registration unsolicited result codes
philware 1:d4ff95ab40ae 802 if (cereg(1)) {
philware 1:d4ff95ab40ae 803 // See if we are already in automatic mode
philware 1:d4ff95ab40ae 804 if (get_cops(&status)) {
philware 1:d4ff95ab40ae 805 if (status != 0) {
philware 1:d4ff95ab40ae 806 // Don't check return code here as there's not much
philware 1:d4ff95ab40ae 807 // we can do if this fails.
philware 1:d4ff95ab40ae 808 cops(0);
philware 1:d4ff95ab40ae 809 }
philware 1:d4ff95ab40ae 810 }
philware 1:d4ff95ab40ae 811
philware 1:d4ff95ab40ae 812 // query cereg just in case
philware 1:d4ff95ab40ae 813 get_cereg();
philware 1:d4ff95ab40ae 814 registered = is_registered_eps();
philware 1:d4ff95ab40ae 815
philware 1:d4ff95ab40ae 816 at_set_timeout(1000);
philware 1:d4ff95ab40ae 817 for (int waitSeconds = 0; !registered && (waitSeconds < 180); waitSeconds++) {
philware 1:d4ff95ab40ae 818 _at->recv(UNNATURAL_STRING);
philware 1:d4ff95ab40ae 819 registered = is_registered_eps();
philware 1:d4ff95ab40ae 820 }
philware 1:d4ff95ab40ae 821 at_set_timeout(at_timeout);
philware 1:d4ff95ab40ae 822 } else {
philware 1:d4ff95ab40ae 823 tr_error("Failed to set CEREG=1");
philware 1:d4ff95ab40ae 824 }
philware 1:d4ff95ab40ae 825
philware 1:d4ff95ab40ae 826 UNLOCK();
philware 1:d4ff95ab40ae 827 return registered;
philware 1:d4ff95ab40ae 828 }
philware 1:d4ff95ab40ae 829
philware 1:d4ff95ab40ae 830 bool UbloxCellularBaseN2xx::is_registered_csd()
philware 1:d4ff95ab40ae 831 {
philware 1:d4ff95ab40ae 832 return (_dev_info.reg_status_csd == CSD_REGISTERED) ||
philware 1:d4ff95ab40ae 833 (_dev_info.reg_status_csd == CSD_REGISTERED_ROAMING) ||
philware 1:d4ff95ab40ae 834 (_dev_info.reg_status_csd == CSD_CSFB_NOT_PREFERRED);
philware 1:d4ff95ab40ae 835 }
philware 1:d4ff95ab40ae 836
philware 1:d4ff95ab40ae 837 bool UbloxCellularBaseN2xx::is_registered_psd()
philware 1:d4ff95ab40ae 838 {
philware 1:d4ff95ab40ae 839 return (_dev_info.reg_status_psd == PSD_REGISTERED) ||
philware 1:d4ff95ab40ae 840 (_dev_info.reg_status_psd == PSD_REGISTERED_ROAMING);
philware 1:d4ff95ab40ae 841 }
philware 1:d4ff95ab40ae 842
philware 1:d4ff95ab40ae 843 bool UbloxCellularBaseN2xx::is_registered_eps()
philware 1:d4ff95ab40ae 844 {
philware 1:d4ff95ab40ae 845 return (_dev_info.reg_status_eps == EPS_REGISTERED) ||
philware 1:d4ff95ab40ae 846 (_dev_info.reg_status_eps == EPS_REGISTERED_ROAMING);
philware 1:d4ff95ab40ae 847 }
philware 1:d4ff95ab40ae 848
philware 1:d4ff95ab40ae 849 // Perform deregistration.
philware 1:d4ff95ab40ae 850 bool UbloxCellularBaseN2xx::nwk_deregistration()
philware 1:d4ff95ab40ae 851 {
philware 1:d4ff95ab40ae 852 bool success = false;
philware 1:d4ff95ab40ae 853
philware 1:d4ff95ab40ae 854 MBED_ASSERT(_at != NULL);
philware 1:d4ff95ab40ae 855
philware 1:d4ff95ab40ae 856 if (cops(2)) {
philware 1:d4ff95ab40ae 857 // we need to wait here so that the internal status of the module
philware 1:d4ff95ab40ae 858 wait_ms(1000);
philware 1:d4ff95ab40ae 859
philware 1:d4ff95ab40ae 860 _dev_info.reg_status_csd = CSD_NOT_REGISTERED_NOT_SEARCHING;
philware 1:d4ff95ab40ae 861 _dev_info.reg_status_psd = PSD_NOT_REGISTERED_NOT_SEARCHING;
philware 1:d4ff95ab40ae 862 _dev_info.reg_status_eps = EPS_NOT_REGISTERED_NOT_SEARCHING;
philware 1:d4ff95ab40ae 863
philware 1:d4ff95ab40ae 864 success = true;
philware 1:d4ff95ab40ae 865 } else {
philware 1:d4ff95ab40ae 866 tr_error("Failed to set COPS=2");
philware 1:d4ff95ab40ae 867 }
philware 1:d4ff95ab40ae 868
philware 1:d4ff95ab40ae 869 return success;
philware 1:d4ff95ab40ae 870 }
philware 1:d4ff95ab40ae 871
philware 1:d4ff95ab40ae 872 // Put the modem into its lowest power state.
philware 1:d4ff95ab40ae 873 void UbloxCellularBaseN2xx::deinit()
philware 1:d4ff95ab40ae 874 {
philware 1:d4ff95ab40ae 875 power_down();
philware 1:d4ff95ab40ae 876 _modem_initialised = false;
philware 1:d4ff95ab40ae 877 }
philware 1:d4ff95ab40ae 878
philware 1:d4ff95ab40ae 879 // Set the PIN.
philware 1:d4ff95ab40ae 880 void UbloxCellularBaseN2xx::set_pin(const char *pin) {
philware 1:d4ff95ab40ae 881 _pin = pin;
philware 1:d4ff95ab40ae 882 }
philware 1:d4ff95ab40ae 883
philware 1:d4ff95ab40ae 884 // Enable or disable SIM pin checking.
philware 1:d4ff95ab40ae 885 bool UbloxCellularBaseN2xx:: sim_pin_check_enable(bool enableNotDisable)
philware 1:d4ff95ab40ae 886 {
philware 1:d4ff95ab40ae 887 // *** NOT IMPLEMENTED on SARA-N2XX
philware 1:d4ff95ab40ae 888 return false;
philware 1:d4ff95ab40ae 889
philware 1:d4ff95ab40ae 890 bool success = false;
philware 1:d4ff95ab40ae 891 LOCK();
philware 1:d4ff95ab40ae 892
philware 1:d4ff95ab40ae 893 MBED_ASSERT(_at != NULL);
philware 1:d4ff95ab40ae 894
philware 1:d4ff95ab40ae 895 if (_pin != NULL) {
philware 1:d4ff95ab40ae 896 if (_sim_pin_check_enabled && !enableNotDisable) {
philware 1:d4ff95ab40ae 897 // Disable the SIM lock
philware 1:d4ff95ab40ae 898 if (_at->send("AT+CLCK=\"SC\",0,\"%s\"", _pin) && _at->recv("OK")) {
philware 1:d4ff95ab40ae 899 _sim_pin_check_enabled = false;
philware 1:d4ff95ab40ae 900 success = true;
philware 1:d4ff95ab40ae 901 }
philware 1:d4ff95ab40ae 902 } else if (!_sim_pin_check_enabled && enableNotDisable) {
philware 1:d4ff95ab40ae 903 // Enable the SIM lock
philware 1:d4ff95ab40ae 904 if (_at->send("AT+CLCK=\"SC\",1,\"%s\"", _pin) && _at->recv("OK")) {
philware 1:d4ff95ab40ae 905 _sim_pin_check_enabled = true;
philware 1:d4ff95ab40ae 906 success = true;
philware 1:d4ff95ab40ae 907 }
philware 1:d4ff95ab40ae 908 } else {
philware 1:d4ff95ab40ae 909 success = true;
philware 1:d4ff95ab40ae 910 }
philware 1:d4ff95ab40ae 911 }
philware 1:d4ff95ab40ae 912
philware 1:d4ff95ab40ae 913 UNLOCK();
philware 1:d4ff95ab40ae 914 return success;
philware 1:d4ff95ab40ae 915 }
philware 1:d4ff95ab40ae 916
philware 1:d4ff95ab40ae 917 // Change the pin code for the SIM card.
philware 1:d4ff95ab40ae 918 bool UbloxCellularBaseN2xx::change_sim_pin(const char *pin)
philware 1:d4ff95ab40ae 919 {
philware 1:d4ff95ab40ae 920 // *** NOT IMPLEMENTED on SARA-N2XX
philware 1:d4ff95ab40ae 921 return false;
philware 1:d4ff95ab40ae 922
philware 1:d4ff95ab40ae 923 bool success = false;
philware 1:d4ff95ab40ae 924 LOCK();
philware 1:d4ff95ab40ae 925
philware 1:d4ff95ab40ae 926 MBED_ASSERT(_at != NULL);
philware 1:d4ff95ab40ae 927
philware 1:d4ff95ab40ae 928 // Change the SIM pin
philware 1:d4ff95ab40ae 929 if ((pin != NULL) && (_pin != NULL)) {
philware 1:d4ff95ab40ae 930 if (_at->send("AT+CPWD=\"SC\",\"%s\",\"%s\"", _pin, pin) && _at->recv("OK")) {
philware 1:d4ff95ab40ae 931 _pin = pin;
philware 1:d4ff95ab40ae 932 success = true;
philware 1:d4ff95ab40ae 933 }
philware 1:d4ff95ab40ae 934 }
philware 1:d4ff95ab40ae 935
philware 1:d4ff95ab40ae 936 UNLOCK();
philware 1:d4ff95ab40ae 937 return success;
philware 1:d4ff95ab40ae 938 }
philware 1:d4ff95ab40ae 939
philware 1:d4ff95ab40ae 940 // Read up to size bytes from the AT interface up to a newline.
philware 1:d4ff95ab40ae 941 // This doesn't need a LOCK() UNLOCK() Wrapping as it's only called
philware 1:d4ff95ab40ae 942 // from the URC function, which are already in a lock
philware 1:d4ff95ab40ae 943 int UbloxCellularBaseN2xx::read_at_to_newline(char * buf, int size)
philware 1:d4ff95ab40ae 944 {
philware 1:d4ff95ab40ae 945 int count = 0;
philware 1:d4ff95ab40ae 946 int x = 0;
philware 1:d4ff95ab40ae 947
philware 1:d4ff95ab40ae 948 if (size > 0) {
philware 1:d4ff95ab40ae 949 for (count = 0; (count < size) && (x >= 0) && (x != '\n'); count++) {
philware 1:d4ff95ab40ae 950 x = _at->getc();
philware 1:d4ff95ab40ae 951 *(buf + count) = (char) x;
philware 1:d4ff95ab40ae 952 }
philware 1:d4ff95ab40ae 953
philware 1:d4ff95ab40ae 954 *(buf + count - 1) = 0;
philware 1:d4ff95ab40ae 955 count--;
philware 1:d4ff95ab40ae 956 }
philware 1:d4ff95ab40ae 957
philware 1:d4ff95ab40ae 958 return count;
philware 1:d4ff95ab40ae 959 }
philware 1:d4ff95ab40ae 960 // End of File
philware 1:d4ff95ab40ae 961