ublox-cellular-base-n2xx

Committer:
philware
Date:
Tue Jan 09 14:35:43 2018 +0000
Revision:
10:1afe5ed24f0c
Parent:
9:4368e434de4e
Child:
11:e9b490d21afb
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