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:
Tue Jan 09 14:35:43 2018 +0000
Revision:
10:1afe5ed24f0c
Parent:
9:4368e434de4e
Added new imei() imsi() type functions

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