ublox-cellular-base

Committer:
rob.meades@u-blox.com
Date:
Tue Jun 13 10:08:52 2017 +0100
Revision:
2:73fcc33c9400
Parent:
1:5aaecf2572dc
Child:
3:f9b2cd6f72b1
Make debug prints conditional on _debug_trace_on.

Who changed what in which revision?

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