ublox-cellular-base-n2xx

Committer:
philware
Date:
Thu Sep 28 15:30:37 2017 +0100
Revision:
3:39eadc84c5ac
Parent:
1:d4ff95ab40ae
Child:
5:66451d314225
Improved some tr_debug lines

Who changed what in which revision?

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