Fork for new features

Committer:
wajahat.abbas@u-blox.com
Date:
Mon Mar 25 14:50:56 2019 +0500
Revision:
22:b69465e9f076
Parent:
20:31d5e048fbfa
set_plmn() implementation

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 14:e420232ee4e7 30 /* Array to convert the 3G qual number into a median EC_NO_LEV number.
RobMeades 14:e420232ee4e7 31 */
RobMeades 14:e420232ee4e7 32 /* 0 1 2 3 4 5 6 7 */
fahim.alavi@u-blox.com 15:93b157a47b8d 33 /* 44, 41, 35, 29, 23, 17, 11, 7*/
fahim.alavi@u-blox.com 15:93b157a47b8d 34 const int qualConvert3G[] = {-2, -4, -7, -10, -13, -16, -19, -21};
RobMeades 14:e420232ee4e7 35
RobMeades 14:e420232ee4e7 36 /* Array to convert the 3G "rssi" number into a dBm RSCP value rounded up to the
RobMeades 14:e420232ee4e7 37 * nearest whole number.
RobMeades 14:e420232ee4e7 38 */
RobMeades 14:e420232ee4e7 39 const int rscpConvert3G[] = {-108, -105, -103, -100, -98, -96, -94, -93, /* 0 - 7 */
RobMeades 14:e420232ee4e7 40 -91, -89, -88, -85, -83, -80, -78, -76, /* 8 - 15 */
RobMeades 14:e420232ee4e7 41 -74, -73, -70, -68, -66, -64, -63, -60, /* 16 - 23 */
RobMeades 14:e420232ee4e7 42 -58, -56, -54, -53, -51, -49, -48, -46}; /* 24 - 31 */
RobMeades 14:e420232ee4e7 43
RobMeades 14:e420232ee4e7 44 /* Array to convert the LTE rssi number into a dBm value rounded up to the
RobMeades 14:e420232ee4e7 45 * nearest whole number.
RobMeades 14:e420232ee4e7 46 */
RobMeades 14:e420232ee4e7 47 const int rssiConvertLte[] = {-118, -115, -113, -110, -108, -105, -103, -100, /* 0 - 7 */
RobMeades 14:e420232ee4e7 48 -98, -95, -93, -90, -88, -85, -83, -80, /* 8 - 15 */
RobMeades 14:e420232ee4e7 49 -78, -76, -74, -73, -71, -69, -68, -65, /* 16 - 23 */
RobMeades 14:e420232ee4e7 50 -63, -61, -60, -59, -58, -55, -53, -48}; /* 24 - 31 */
RobMeades 14:e420232ee4e7 51
RobMeades 0:5cffef3371f6 52 /**********************************************************************
RobMeades 0:5cffef3371f6 53 * PRIVATE METHODS
RobMeades 0:5cffef3371f6 54 **********************************************************************/
RobMeades 0:5cffef3371f6 55
RobMeades 0:5cffef3371f6 56 void UbloxCellularBase::set_nwk_reg_status_csd(int status)
RobMeades 0:5cffef3371f6 57 {
RobMeades 0:5cffef3371f6 58 switch (status) {
RobMeades 0:5cffef3371f6 59 case CSD_NOT_REGISTERED_NOT_SEARCHING:
RobMeades 0:5cffef3371f6 60 case CSD_NOT_REGISTERED_SEARCHING:
RobMeades 0:5cffef3371f6 61 tr_info("Not (yet) registered for circuit switched service");
RobMeades 0:5cffef3371f6 62 break;
RobMeades 0:5cffef3371f6 63 case CSD_REGISTERED:
RobMeades 0:5cffef3371f6 64 case CSD_REGISTERED_ROAMING:
RobMeades 0:5cffef3371f6 65 tr_info("Registered for circuit switched service");
RobMeades 0:5cffef3371f6 66 break;
RobMeades 0:5cffef3371f6 67 case CSD_REGISTRATION_DENIED:
RobMeades 0:5cffef3371f6 68 tr_info("Circuit switched service denied");
RobMeades 0:5cffef3371f6 69 break;
RobMeades 0:5cffef3371f6 70 case CSD_UNKNOWN_COVERAGE:
RobMeades 0:5cffef3371f6 71 tr_info("Out of circuit switched service coverage");
RobMeades 0:5cffef3371f6 72 break;
RobMeades 0:5cffef3371f6 73 case CSD_SMS_ONLY:
RobMeades 0:5cffef3371f6 74 tr_info("SMS service only");
RobMeades 0:5cffef3371f6 75 break;
RobMeades 0:5cffef3371f6 76 case CSD_SMS_ONLY_ROAMING:
RobMeades 0:5cffef3371f6 77 tr_info("SMS service only");
RobMeades 0:5cffef3371f6 78 break;
RobMeades 0:5cffef3371f6 79 case CSD_CSFB_NOT_PREFERRED:
RobMeades 0:5cffef3371f6 80 tr_info("Registered for circuit switched service with CSFB not preferred");
RobMeades 0:5cffef3371f6 81 break;
RobMeades 0:5cffef3371f6 82 default:
RobMeades 0:5cffef3371f6 83 tr_info("Unknown circuit switched service registration status. %d", status);
RobMeades 0:5cffef3371f6 84 break;
RobMeades 0:5cffef3371f6 85 }
RobMeades 0:5cffef3371f6 86
RobMeades 0:5cffef3371f6 87 _dev_info.reg_status_csd = static_cast<NetworkRegistrationStatusCsd>(status);
RobMeades 0:5cffef3371f6 88 }
RobMeades 0:5cffef3371f6 89
RobMeades 0:5cffef3371f6 90 void UbloxCellularBase::set_nwk_reg_status_psd(int status)
RobMeades 0:5cffef3371f6 91 {
RobMeades 0:5cffef3371f6 92 switch (status) {
RobMeades 0:5cffef3371f6 93 case PSD_NOT_REGISTERED_NOT_SEARCHING:
RobMeades 0:5cffef3371f6 94 case PSD_NOT_REGISTERED_SEARCHING:
RobMeades 0:5cffef3371f6 95 tr_info("Not (yet) registered for packet switched service");
RobMeades 0:5cffef3371f6 96 break;
RobMeades 0:5cffef3371f6 97 case PSD_REGISTERED:
RobMeades 0:5cffef3371f6 98 case PSD_REGISTERED_ROAMING:
RobMeades 0:5cffef3371f6 99 tr_info("Registered for packet switched service");
RobMeades 0:5cffef3371f6 100 break;
RobMeades 0:5cffef3371f6 101 case PSD_REGISTRATION_DENIED:
RobMeades 0:5cffef3371f6 102 tr_info("Packet switched service denied");
RobMeades 0:5cffef3371f6 103 break;
RobMeades 0:5cffef3371f6 104 case PSD_UNKNOWN_COVERAGE:
RobMeades 0:5cffef3371f6 105 tr_info("Out of packet switched service coverage");
RobMeades 0:5cffef3371f6 106 break;
RobMeades 0:5cffef3371f6 107 case PSD_EMERGENCY_SERVICES_ONLY:
RobMeades 0:5cffef3371f6 108 tr_info("Limited access for packet switched service. Emergency use only.");
RobMeades 0:5cffef3371f6 109 break;
RobMeades 0:5cffef3371f6 110 default:
RobMeades 0:5cffef3371f6 111 tr_info("Unknown packet switched service registration status. %d", status);
RobMeades 0:5cffef3371f6 112 break;
RobMeades 0:5cffef3371f6 113 }
RobMeades 0:5cffef3371f6 114
RobMeades 0:5cffef3371f6 115 _dev_info.reg_status_psd = static_cast<NetworkRegistrationStatusPsd>(status);
RobMeades 0:5cffef3371f6 116 }
RobMeades 0:5cffef3371f6 117
RobMeades 0:5cffef3371f6 118 void UbloxCellularBase::set_nwk_reg_status_eps(int status)
RobMeades 0:5cffef3371f6 119 {
RobMeades 0:5cffef3371f6 120 switch (status) {
RobMeades 0:5cffef3371f6 121 case EPS_NOT_REGISTERED_NOT_SEARCHING:
RobMeades 0:5cffef3371f6 122 case EPS_NOT_REGISTERED_SEARCHING:
RobMeades 0:5cffef3371f6 123 tr_info("Not (yet) registered for EPS service");
RobMeades 0:5cffef3371f6 124 break;
RobMeades 0:5cffef3371f6 125 case EPS_REGISTERED:
RobMeades 0:5cffef3371f6 126 case EPS_REGISTERED_ROAMING:
RobMeades 0:5cffef3371f6 127 tr_info("Registered for EPS service");
RobMeades 0:5cffef3371f6 128 break;
RobMeades 0:5cffef3371f6 129 case EPS_REGISTRATION_DENIED:
RobMeades 0:5cffef3371f6 130 tr_info("EPS service denied");
RobMeades 0:5cffef3371f6 131 break;
RobMeades 0:5cffef3371f6 132 case EPS_UNKNOWN_COVERAGE:
RobMeades 0:5cffef3371f6 133 tr_info("Out of EPS service coverage");
RobMeades 0:5cffef3371f6 134 break;
RobMeades 0:5cffef3371f6 135 case EPS_EMERGENCY_SERVICES_ONLY:
RobMeades 0:5cffef3371f6 136 tr_info("Limited access for EPS service. Emergency use only.");
RobMeades 0:5cffef3371f6 137 break;
RobMeades 0:5cffef3371f6 138 default:
RobMeades 0:5cffef3371f6 139 tr_info("Unknown EPS service registration status. %d", status);
RobMeades 0:5cffef3371f6 140 break;
RobMeades 0:5cffef3371f6 141 }
RobMeades 0:5cffef3371f6 142
RobMeades 0:5cffef3371f6 143 _dev_info.reg_status_eps = static_cast<NetworkRegistrationStatusEps>(status);
RobMeades 0:5cffef3371f6 144 }
RobMeades 0:5cffef3371f6 145
RobMeades 14:e420232ee4e7 146 void UbloxCellularBase::set_rat(int acTStatus)
RobMeades 0:5cffef3371f6 147 {
RobMeades 14:e420232ee4e7 148 switch (acTStatus) {
RobMeades 0:5cffef3371f6 149 case GSM:
RobMeades 0:5cffef3371f6 150 case COMPACT_GSM:
RobMeades 0:5cffef3371f6 151 tr_info("Connected in GSM");
RobMeades 0:5cffef3371f6 152 break;
RobMeades 0:5cffef3371f6 153 case UTRAN:
RobMeades 0:5cffef3371f6 154 tr_info("Connected to UTRAN");
RobMeades 0:5cffef3371f6 155 break;
RobMeades 0:5cffef3371f6 156 case EDGE:
RobMeades 0:5cffef3371f6 157 tr_info("Connected to EDGE");
RobMeades 0:5cffef3371f6 158 break;
RobMeades 0:5cffef3371f6 159 case HSDPA:
RobMeades 0:5cffef3371f6 160 tr_info("Connected to HSDPA");
RobMeades 0:5cffef3371f6 161 break;
RobMeades 0:5cffef3371f6 162 case HSUPA:
RobMeades 0:5cffef3371f6 163 tr_info("Connected to HSPA");
RobMeades 0:5cffef3371f6 164 break;
RobMeades 0:5cffef3371f6 165 case HSDPA_HSUPA:
RobMeades 0:5cffef3371f6 166 tr_info("Connected to HDPA/HSPA");
RobMeades 0:5cffef3371f6 167 break;
RobMeades 0:5cffef3371f6 168 case LTE:
RobMeades 0:5cffef3371f6 169 tr_info("Connected to LTE");
RobMeades 0:5cffef3371f6 170 break;
fahimalavi 10:c4281fa79b8f 171 case EC_GSM_IoT:
fahimalavi 10:c4281fa79b8f 172 tr_info("Connected to EC_GSM_IoT");
fahimalavi 10:c4281fa79b8f 173 break;
fahimalavi 10:c4281fa79b8f 174 case E_UTRAN_NB_S1:
fahimalavi 10:c4281fa79b8f 175 tr_info("Connected to E_UTRAN NB1");
fahimalavi 10:c4281fa79b8f 176 break;
RobMeades 0:5cffef3371f6 177 default:
RobMeades 14:e420232ee4e7 178 tr_info("Unknown RAT %d", acTStatus);
RobMeades 0:5cffef3371f6 179 break;
RobMeades 0:5cffef3371f6 180 }
RobMeades 0:5cffef3371f6 181
RobMeades 14:e420232ee4e7 182 _dev_info.rat = static_cast<RadioAccessNetworkType>(acTStatus);
RobMeades 0:5cffef3371f6 183 }
RobMeades 0:5cffef3371f6 184
RobMeades 0:5cffef3371f6 185 bool UbloxCellularBase::get_iccid()
RobMeades 0:5cffef3371f6 186 {
RobMeades 0:5cffef3371f6 187 bool success;
RobMeades 0:5cffef3371f6 188 LOCK();
RobMeades 0:5cffef3371f6 189
RobMeades 0:5cffef3371f6 190 MBED_ASSERT(_at != NULL);
RobMeades 0:5cffef3371f6 191
RobMeades 0:5cffef3371f6 192 // Returns the ICCID (Integrated Circuit Card ID) of the SIM-card.
RobMeades 0:5cffef3371f6 193 // ICCID is a serial number identifying the SIM.
RobMeades 0:5cffef3371f6 194 // AT Command Manual UBX-13002752, section 4.12
RobMeades 0:5cffef3371f6 195 success = _at->send("AT+CCID") && _at->recv("+CCID: %20[^\n]\nOK\n", _dev_info.iccid);
RobMeades 0:5cffef3371f6 196 tr_info("DevInfo: ICCID=%s", _dev_info.iccid);
RobMeades 0:5cffef3371f6 197
RobMeades 0:5cffef3371f6 198 UNLOCK();
RobMeades 0:5cffef3371f6 199 return success;
RobMeades 0:5cffef3371f6 200 }
RobMeades 0:5cffef3371f6 201
RobMeades 0:5cffef3371f6 202 bool UbloxCellularBase::get_imsi()
RobMeades 0:5cffef3371f6 203 {
RobMeades 0:5cffef3371f6 204 bool success;
RobMeades 0:5cffef3371f6 205 LOCK();
RobMeades 0:5cffef3371f6 206
RobMeades 0:5cffef3371f6 207 MBED_ASSERT(_at != NULL);
RobMeades 0:5cffef3371f6 208
RobMeades 0:5cffef3371f6 209 // International mobile subscriber identification
RobMeades 0:5cffef3371f6 210 // AT Command Manual UBX-13002752, section 4.11
RobMeades 0:5cffef3371f6 211 success = _at->send("AT+CIMI") && _at->recv("%15[^\n]\nOK\n", _dev_info.imsi);
RobMeades 0:5cffef3371f6 212 tr_info("DevInfo: IMSI=%s", _dev_info.imsi);
RobMeades 0:5cffef3371f6 213
RobMeades 0:5cffef3371f6 214 UNLOCK();
RobMeades 0:5cffef3371f6 215 return success;
RobMeades 0:5cffef3371f6 216 }
RobMeades 0:5cffef3371f6 217
RobMeades 0:5cffef3371f6 218 bool UbloxCellularBase::get_imei()
RobMeades 0:5cffef3371f6 219 {
RobMeades 0:5cffef3371f6 220 bool success;
RobMeades 0:5cffef3371f6 221 LOCK();
RobMeades 0:5cffef3371f6 222
RobMeades 0:5cffef3371f6 223 MBED_ASSERT(_at != NULL);
RobMeades 0:5cffef3371f6 224
RobMeades 0:5cffef3371f6 225 // International mobile equipment identifier
RobMeades 0:5cffef3371f6 226 // AT Command Manual UBX-13002752, section 4.7
RobMeades 0:5cffef3371f6 227 success = _at->send("AT+CGSN") && _at->recv("%15[^\n]\nOK\n", _dev_info.imei);
RobMeades 0:5cffef3371f6 228 tr_info("DevInfo: IMEI=%s", _dev_info.imei);
RobMeades 0:5cffef3371f6 229
RobMeades 0:5cffef3371f6 230 UNLOCK();
RobMeades 0:5cffef3371f6 231 return success;
RobMeades 0:5cffef3371f6 232 }
RobMeades 0:5cffef3371f6 233
RobMeades 0:5cffef3371f6 234 bool UbloxCellularBase::get_meid()
RobMeades 0:5cffef3371f6 235 {
RobMeades 0:5cffef3371f6 236 bool success;
RobMeades 0:5cffef3371f6 237 LOCK();
RobMeades 0:5cffef3371f6 238
RobMeades 0:5cffef3371f6 239 MBED_ASSERT(_at != NULL);
RobMeades 0:5cffef3371f6 240
RobMeades 0:5cffef3371f6 241 // Mobile equipment identifier
RobMeades 0:5cffef3371f6 242 // AT Command Manual UBX-13002752, section 4.8
RobMeades 0:5cffef3371f6 243 success = _at->send("AT+GSN") && _at->recv("%18[^\n]\nOK\n", _dev_info.meid);
RobMeades 0:5cffef3371f6 244 tr_info("DevInfo: MEID=%s", _dev_info.meid);
RobMeades 0:5cffef3371f6 245
RobMeades 0:5cffef3371f6 246 UNLOCK();
RobMeades 0:5cffef3371f6 247 return success;
RobMeades 0:5cffef3371f6 248 }
RobMeades 0:5cffef3371f6 249
RobMeades 0:5cffef3371f6 250 bool UbloxCellularBase::set_sms()
RobMeades 0:5cffef3371f6 251 {
RobMeades 0:5cffef3371f6 252 bool success = false;
RobMeades 0:5cffef3371f6 253 char buf[32];
RobMeades 0:5cffef3371f6 254 LOCK();
RobMeades 0:5cffef3371f6 255
RobMeades 0:5cffef3371f6 256 MBED_ASSERT(_at != NULL);
RobMeades 0:5cffef3371f6 257
RobMeades 0:5cffef3371f6 258 // Set up SMS format and enable URC
RobMeades 0:5cffef3371f6 259 // AT Command Manual UBX-13002752, section 11
RobMeades 0:5cffef3371f6 260 if (_at->send("AT+CMGF=1") && _at->recv("OK")) {
RobMeades 0:5cffef3371f6 261 tr_debug("SMS in text mode");
RobMeades 0:5cffef3371f6 262 if (_at->send("AT+CNMI=2,1") && _at->recv("OK")) {
RobMeades 0:5cffef3371f6 263 tr_debug("SMS URC enabled");
RobMeades 0:5cffef3371f6 264 // Set to CS preferred since PS preferred doesn't work
RobMeades 0:5cffef3371f6 265 // on some networks
RobMeades 0:5cffef3371f6 266 if (_at->send("AT+CGSMS=1") && _at->recv("OK")) {
RobMeades 0:5cffef3371f6 267 tr_debug("SMS set to CS preferred");
RobMeades 0:5cffef3371f6 268 success = true;
RobMeades 0:5cffef3371f6 269 memset (buf, 0, sizeof (buf));
RobMeades 0:5cffef3371f6 270 if (_at->send("AT+CSCA?") &&
RobMeades 0:5cffef3371f6 271 _at->recv("+CSCA: \"%31[^\"]\"", buf) &&
RobMeades 0:5cffef3371f6 272 _at->recv("OK")) {
RobMeades 0:5cffef3371f6 273 tr_info("SMS Service Centre address is \"%s\"", buf);
RobMeades 0:5cffef3371f6 274 }
RobMeades 0:5cffef3371f6 275 }
RobMeades 0:5cffef3371f6 276 }
RobMeades 0:5cffef3371f6 277 }
RobMeades 0:5cffef3371f6 278
RobMeades 0:5cffef3371f6 279 UNLOCK();
RobMeades 0:5cffef3371f6 280 return success;
RobMeades 0:5cffef3371f6 281 }
RobMeades 0:5cffef3371f6 282
RobMeades 0:5cffef3371f6 283 void UbloxCellularBase::parser_abort_cb()
RobMeades 0:5cffef3371f6 284 {
RobMeades 0:5cffef3371f6 285 _at->abort();
RobMeades 0:5cffef3371f6 286 }
RobMeades 0:5cffef3371f6 287
RobMeades 0:5cffef3371f6 288 // Callback for CME ERROR and CMS ERROR.
RobMeades 0:5cffef3371f6 289 void UbloxCellularBase::CMX_ERROR_URC()
RobMeades 0:5cffef3371f6 290 {
RobMeades 0:5cffef3371f6 291 char buf[48];
RobMeades 0:5cffef3371f6 292
RobMeades 0:5cffef3371f6 293 if (read_at_to_char(buf, sizeof (buf), '\n') > 0) {
RobMeades 0:5cffef3371f6 294 tr_debug("AT error %s", buf);
RobMeades 0:5cffef3371f6 295 }
RobMeades 0:5cffef3371f6 296 parser_abort_cb();
RobMeades 0:5cffef3371f6 297 }
RobMeades 0:5cffef3371f6 298
RobMeades 0:5cffef3371f6 299 // Callback for circuit switched registration URC.
RobMeades 0:5cffef3371f6 300 void UbloxCellularBase::CREG_URC()
RobMeades 0:5cffef3371f6 301 {
RobMeades 0:5cffef3371f6 302 char buf[10];
RobMeades 0:5cffef3371f6 303 int status;
RobMeades 14:e420232ee4e7 304 int acTStatus;
RobMeades 0:5cffef3371f6 305
RobMeades 0:5cffef3371f6 306 // If this is the URC it will be a single
RobMeades 0:5cffef3371f6 307 // digit followed by \n. If it is the
RobMeades 0:5cffef3371f6 308 // answer to a CREG query, it will be
RobMeades 0:5cffef3371f6 309 // a ": %d,%d\n" where the second digit
RobMeades 0:5cffef3371f6 310 // indicates the status
RobMeades 0:5cffef3371f6 311 // Note: not calling _at->recv() from here as we're
RobMeades 0:5cffef3371f6 312 // already in an _at->recv()
RobMeades 0:5cffef3371f6 313 if (read_at_to_char(buf, sizeof (buf), '\n') > 0) {
RobMeades 14:e420232ee4e7 314 if (sscanf(buf, ": %*d,%d,%*d,%*d,%d,", &status, &acTStatus) == 2) {
RobMeades 14:e420232ee4e7 315 set_nwk_reg_status_csd(status);
RobMeades 14:e420232ee4e7 316 set_rat(acTStatus);
RobMeades 14:e420232ee4e7 317 } else if (sscanf(buf, ": %*d,%d", &status) == 1) {
RobMeades 0:5cffef3371f6 318 set_nwk_reg_status_csd(status);
RobMeades 0:5cffef3371f6 319 } else if (sscanf(buf, ": %d", &status) == 1) {
RobMeades 0:5cffef3371f6 320 set_nwk_reg_status_csd(status);
RobMeades 0:5cffef3371f6 321 }
RobMeades 0:5cffef3371f6 322 }
RobMeades 0:5cffef3371f6 323 }
RobMeades 0:5cffef3371f6 324
RobMeades 0:5cffef3371f6 325 // Callback for packet switched registration URC.
RobMeades 0:5cffef3371f6 326 void UbloxCellularBase::CGREG_URC()
RobMeades 0:5cffef3371f6 327 {
RobMeades 0:5cffef3371f6 328 char buf[10];
RobMeades 0:5cffef3371f6 329 int status;
RobMeades 14:e420232ee4e7 330 int acTStatus;
RobMeades 0:5cffef3371f6 331
RobMeades 0:5cffef3371f6 332 // If this is the URC it will be a single
RobMeades 0:5cffef3371f6 333 // digit followed by \n. If it is the
RobMeades 0:5cffef3371f6 334 // answer to a CGREG query, it will be
RobMeades 0:5cffef3371f6 335 // a ": %d,%d\n" where the second digit
RobMeades 0:5cffef3371f6 336 // indicates the status
RobMeades 0:5cffef3371f6 337 // Note: not calling _at->recv() from here as we're
RobMeades 0:5cffef3371f6 338 // already in an _at->recv()
RobMeades 0:5cffef3371f6 339 if (read_at_to_char(buf, sizeof (buf), '\n') > 0) {
RobMeades 14:e420232ee4e7 340 if (sscanf(buf, ": %*d,%d,%*d,%*d,%d,", &status, &acTStatus) == 2) {
RobMeades 14:e420232ee4e7 341 set_nwk_reg_status_csd(status);
RobMeades 14:e420232ee4e7 342 set_rat(acTStatus);
RobMeades 14:e420232ee4e7 343 } else if (sscanf(buf, ": %*d,%d", &status) == 1) {
RobMeades 0:5cffef3371f6 344 set_nwk_reg_status_psd(status);
RobMeades 0:5cffef3371f6 345 } else if (sscanf(buf, ": %d", &status) == 1) {
RobMeades 0:5cffef3371f6 346 set_nwk_reg_status_psd(status);
RobMeades 0:5cffef3371f6 347 }
RobMeades 0:5cffef3371f6 348 }
RobMeades 0:5cffef3371f6 349 }
RobMeades 0:5cffef3371f6 350
RobMeades 0:5cffef3371f6 351 // Callback for EPS registration URC.
RobMeades 0:5cffef3371f6 352 void UbloxCellularBase::CEREG_URC()
RobMeades 0:5cffef3371f6 353 {
RobMeades 0:5cffef3371f6 354 char buf[10];
RobMeades 0:5cffef3371f6 355 int status;
RobMeades 14:e420232ee4e7 356 int acTStatus;
RobMeades 0:5cffef3371f6 357
RobMeades 0:5cffef3371f6 358 // If this is the URC it will be a single
RobMeades 0:5cffef3371f6 359 // digit followed by \n. If it is the
RobMeades 0:5cffef3371f6 360 // answer to a CEREG query, it will be
RobMeades 0:5cffef3371f6 361 // a ": %d,%d\n" where the second digit
RobMeades 0:5cffef3371f6 362 // indicates the status
RobMeades 0:5cffef3371f6 363 // Note: not calling _at->recv() from here as we're
RobMeades 0:5cffef3371f6 364 // already in an _at->recv()
RobMeades 0:5cffef3371f6 365 if (read_at_to_char(buf, sizeof (buf), '\n') > 0) {
RobMeades 14:e420232ee4e7 366 if (sscanf(buf, ": %*d,%d,%*d,%*d,%d,", &status, &acTStatus) == 2) {
RobMeades 14:e420232ee4e7 367 set_nwk_reg_status_csd(status);
RobMeades 14:e420232ee4e7 368 set_rat(acTStatus);
RobMeades 14:e420232ee4e7 369 } else if (sscanf(buf, ": %*d,%d", &status) == 1) {
RobMeades 0:5cffef3371f6 370 set_nwk_reg_status_eps(status);
RobMeades 0:5cffef3371f6 371 } else if (sscanf(buf, ": %d", &status) == 1) {
RobMeades 0:5cffef3371f6 372 set_nwk_reg_status_eps(status);
RobMeades 0:5cffef3371f6 373 }
RobMeades 0:5cffef3371f6 374 }
RobMeades 0:5cffef3371f6 375 }
RobMeades 0:5cffef3371f6 376
RobMeades 0:5cffef3371f6 377 // Callback UMWI, just filtering it out.
RobMeades 0:5cffef3371f6 378 void UbloxCellularBase::UMWI_URC()
RobMeades 0:5cffef3371f6 379 {
RobMeades 0:5cffef3371f6 380 char buf[10];
RobMeades 0:5cffef3371f6 381
RobMeades 0:5cffef3371f6 382 // Note: not calling _at->recv() from here as we're
RobMeades 0:5cffef3371f6 383 // already in an _at->recv()
RobMeades 0:5cffef3371f6 384 read_at_to_char(buf, sizeof (buf), '\n');
RobMeades 0:5cffef3371f6 385 }
RobMeades 0:5cffef3371f6 386
RobMeades 0:5cffef3371f6 387 /**********************************************************************
RobMeades 0:5cffef3371f6 388 * PROTECTED METHODS
RobMeades 0:5cffef3371f6 389 **********************************************************************/
RobMeades 0:5cffef3371f6 390
RobMeades 0:5cffef3371f6 391 #if MODEM_ON_BOARD
RobMeades 0:5cffef3371f6 392 void UbloxCellularBase::modem_init()
RobMeades 0:5cffef3371f6 393 {
RobMeades 0:5cffef3371f6 394 ::onboard_modem_init();
RobMeades 0:5cffef3371f6 395 }
RobMeades 0:5cffef3371f6 396
RobMeades 0:5cffef3371f6 397 void UbloxCellularBase::modem_deinit()
RobMeades 0:5cffef3371f6 398 {
RobMeades 0:5cffef3371f6 399 ::onboard_modem_deinit();
RobMeades 0:5cffef3371f6 400 }
RobMeades 0:5cffef3371f6 401
RobMeades 0:5cffef3371f6 402 void UbloxCellularBase::modem_power_up()
RobMeades 0:5cffef3371f6 403 {
RobMeades 0:5cffef3371f6 404 ::onboard_modem_power_up();
RobMeades 0:5cffef3371f6 405 }
RobMeades 0:5cffef3371f6 406
RobMeades 0:5cffef3371f6 407 void UbloxCellularBase::modem_power_down()
RobMeades 0:5cffef3371f6 408 {
RobMeades 0:5cffef3371f6 409 ::onboard_modem_power_down();
RobMeades 0:5cffef3371f6 410 }
RobMeades 0:5cffef3371f6 411 #else
RobMeades 0:5cffef3371f6 412 void UbloxCellularBase::modem_init()
RobMeades 0:5cffef3371f6 413 {
RobMeades 0:5cffef3371f6 414 // Meant to be overridden
RobMeades 0:5cffef3371f6 415 }
RobMeades 0:5cffef3371f6 416
RobMeades 0:5cffef3371f6 417 void UbloxCellularBase::modem_deinit()
RobMeades 0:5cffef3371f6 418 {
RobMeades 0:5cffef3371f6 419 // Meant to be overridden
RobMeades 0:5cffef3371f6 420 }
RobMeades 0:5cffef3371f6 421
RobMeades 0:5cffef3371f6 422 void UbloxCellularBase::modem_power_up()
RobMeades 0:5cffef3371f6 423 {
RobMeades 0:5cffef3371f6 424 // Meant to be overridden
RobMeades 0:5cffef3371f6 425 }
RobMeades 0:5cffef3371f6 426
RobMeades 0:5cffef3371f6 427 void UbloxCellularBase::modem_power_down()
RobMeades 0:5cffef3371f6 428 {
RobMeades 0:5cffef3371f6 429 // Mmeant to be overridden
RobMeades 0:5cffef3371f6 430 }
RobMeades 0:5cffef3371f6 431 #endif
RobMeades 0:5cffef3371f6 432
RobMeades 0:5cffef3371f6 433 // Constructor.
RobMeades 0:5cffef3371f6 434 // Note: to allow this base class to be inherited as a virtual base class
RobMeades 0:5cffef3371f6 435 // by everyone, it takes no parameters. See also comment above classInit()
RobMeades 0:5cffef3371f6 436 // in the header file.
RobMeades 0:5cffef3371f6 437 UbloxCellularBase::UbloxCellularBase()
RobMeades 0:5cffef3371f6 438 {
RobMeades 0:5cffef3371f6 439 _pin = NULL;
RobMeades 0:5cffef3371f6 440 _at = NULL;
RobMeades 0:5cffef3371f6 441 _at_timeout = AT_PARSER_TIMEOUT;
RobMeades 0:5cffef3371f6 442 _fh = NULL;
RobMeades 0:5cffef3371f6 443 _modem_initialised = false;
RobMeades 0:5cffef3371f6 444 _sim_pin_check_enabled = false;
RobMeades 0:5cffef3371f6 445 _debug_trace_on = false;
wajahat.abbas@u-blox.com 22:b69465e9f076 446 memset(_plmn, 0, sizeof(_plmn));
RobMeades 0:5cffef3371f6 447
RobMeades 0:5cffef3371f6 448 _dev_info.dev = DEV_TYPE_NONE;
RobMeades 0:5cffef3371f6 449 _dev_info.reg_status_csd = CSD_NOT_REGISTERED_NOT_SEARCHING;
RobMeades 0:5cffef3371f6 450 _dev_info.reg_status_psd = PSD_NOT_REGISTERED_NOT_SEARCHING;
RobMeades 0:5cffef3371f6 451 _dev_info.reg_status_eps = EPS_NOT_REGISTERED_NOT_SEARCHING;
RobMeades 0:5cffef3371f6 452 }
RobMeades 0:5cffef3371f6 453
RobMeades 0:5cffef3371f6 454 // Destructor.
RobMeades 0:5cffef3371f6 455 UbloxCellularBase::~UbloxCellularBase()
RobMeades 0:5cffef3371f6 456 {
RobMeades 0:5cffef3371f6 457 deinit();
RobMeades 0:5cffef3371f6 458 delete _at;
RobMeades 0:5cffef3371f6 459 delete _fh;
RobMeades 0:5cffef3371f6 460 }
RobMeades 0:5cffef3371f6 461
RobMeades 0:5cffef3371f6 462 // Initialise the portions of this class that are parameterised.
RobMeades 0:5cffef3371f6 463 void UbloxCellularBase::baseClassInit(PinName tx, PinName rx,
RobMeades 0:5cffef3371f6 464 int baud, bool debug_on)
RobMeades 0:5cffef3371f6 465 {
RobMeades 0:5cffef3371f6 466 // Only initialise ourselves if it's not already been done
RobMeades 0:5cffef3371f6 467 if (_at == NULL) {
RobMeades 0:5cffef3371f6 468 if (_debug_trace_on == false) {
RobMeades 0:5cffef3371f6 469 _debug_trace_on = debug_on;
RobMeades 0:5cffef3371f6 470 }
rob.meades@u-blox.com 4:2e640a101db1 471 _baud = baud;
RobMeades 0:5cffef3371f6 472
RobMeades 0:5cffef3371f6 473 // Set up File Handle for buffered serial comms with cellular module
RobMeades 0:5cffef3371f6 474 // (which will be used by the AT parser)
rob.meades@u-blox.com 4:2e640a101db1 475 // Note: the UART is initialised to run no faster than 115200 because
rob.meades@u-blox.com 4:2e640a101db1 476 // the modems cannot reliably auto-baud at faster rates. The faster
rob.meades@u-blox.com 4:2e640a101db1 477 // rate is adopted later with a specific AT command and the
rob.meades@u-blox.com 4:2e640a101db1 478 // UARTSerial rate is adjusted at that time
rob.meades@u-blox.com 4:2e640a101db1 479 if (baud > 115200) {
rob.meades@u-blox.com 4:2e640a101db1 480 baud = 115200;
rob.meades@u-blox.com 4:2e640a101db1 481 }
RobMeades 0:5cffef3371f6 482 _fh = new UARTSerial(tx, rx, baud);
RobMeades 0:5cffef3371f6 483
RobMeades 0:5cffef3371f6 484 // Set up the AT parser
RobMeades 0:5cffef3371f6 485 _at = new ATCmdParser(_fh, OUTPUT_ENTER_KEY, AT_PARSER_BUFFER_SIZE,
rob.meades@u-blox.com 3:f9b2cd6f72b1 486 _at_timeout, _debug_trace_on);
RobMeades 0:5cffef3371f6 487
RobMeades 0:5cffef3371f6 488 // Error cases, out of band handling
RobMeades 0:5cffef3371f6 489 _at->oob("ERROR", callback(this, &UbloxCellularBase::parser_abort_cb));
RobMeades 0:5cffef3371f6 490 _at->oob("+CME ERROR", callback(this, &UbloxCellularBase::CMX_ERROR_URC));
RobMeades 0:5cffef3371f6 491 _at->oob("+CMS ERROR", callback(this, &UbloxCellularBase::CMX_ERROR_URC));
RobMeades 0:5cffef3371f6 492
RobMeades 0:5cffef3371f6 493 // Registration status, out of band handling
RobMeades 0:5cffef3371f6 494 _at->oob("+CREG", callback(this, &UbloxCellularBase::CREG_URC));
RobMeades 0:5cffef3371f6 495 _at->oob("+CGREG", callback(this, &UbloxCellularBase::CGREG_URC));
RobMeades 0:5cffef3371f6 496 _at->oob("+CEREG", callback(this, &UbloxCellularBase::CEREG_URC));
RobMeades 0:5cffef3371f6 497
RobMeades 0:5cffef3371f6 498 // Capture the UMWI, just to stop it getting in the way
RobMeades 0:5cffef3371f6 499 _at->oob("+UMWI", callback(this, &UbloxCellularBase::UMWI_URC));
RobMeades 0:5cffef3371f6 500 }
RobMeades 0:5cffef3371f6 501 }
RobMeades 0:5cffef3371f6 502
RobMeades 0:5cffef3371f6 503 // Set the AT parser timeout.
RobMeades 0:5cffef3371f6 504 // Note: the AT interface should be locked before this is called.
RobMeades 0:5cffef3371f6 505 void UbloxCellularBase::at_set_timeout(int timeout) {
RobMeades 0:5cffef3371f6 506
RobMeades 0:5cffef3371f6 507 MBED_ASSERT(_at != NULL);
RobMeades 0:5cffef3371f6 508
RobMeades 0:5cffef3371f6 509 _at_timeout = timeout;
RobMeades 0:5cffef3371f6 510 _at->set_timeout(timeout);
RobMeades 0:5cffef3371f6 511 }
RobMeades 0:5cffef3371f6 512
RobMeades 0:5cffef3371f6 513 // Read up to size bytes from the AT interface up to a "end".
RobMeades 0:5cffef3371f6 514 // Note: the AT interface should be locked before this is called.
RobMeades 0:5cffef3371f6 515 int UbloxCellularBase::read_at_to_char(char * buf, int size, char end)
RobMeades 0:5cffef3371f6 516 {
RobMeades 0:5cffef3371f6 517 int count = 0;
RobMeades 0:5cffef3371f6 518 int x = 0;
RobMeades 0:5cffef3371f6 519
RobMeades 0:5cffef3371f6 520 if (size > 0) {
RobMeades 0:5cffef3371f6 521 for (count = 0; (count < size) && (x >= 0) && (x != end); count++) {
RobMeades 0:5cffef3371f6 522 x = _at->getc();
RobMeades 0:5cffef3371f6 523 *(buf + count) = (char) x;
RobMeades 0:5cffef3371f6 524 }
RobMeades 0:5cffef3371f6 525
RobMeades 0:5cffef3371f6 526 count--;
RobMeades 0:5cffef3371f6 527 *(buf + count) = 0;
RobMeades 0:5cffef3371f6 528
RobMeades 0:5cffef3371f6 529 // Convert line endings:
RobMeades 0:5cffef3371f6 530 // If end was '\n' (0x0a) and the preceding character was 0x0d, then
RobMeades 0:5cffef3371f6 531 // overwrite that with null as well.
RobMeades 0:5cffef3371f6 532 if ((count > 0) && (end == '\n') && (*(buf + count - 1) == '\x0d')) {
RobMeades 0:5cffef3371f6 533 count--;
RobMeades 0:5cffef3371f6 534 *(buf + count) = 0;
RobMeades 0:5cffef3371f6 535 }
RobMeades 0:5cffef3371f6 536 }
RobMeades 0:5cffef3371f6 537
RobMeades 0:5cffef3371f6 538 return count;
RobMeades 0:5cffef3371f6 539 }
RobMeades 0:5cffef3371f6 540
RobMeades 0:5cffef3371f6 541 // Power up the modem.
RobMeades 0:5cffef3371f6 542 // Enables the GPIO lines to the modem and then wriggles the power line in short pulses.
RobMeades 0:5cffef3371f6 543 bool UbloxCellularBase::power_up()
RobMeades 0:5cffef3371f6 544 {
RobMeades 0:5cffef3371f6 545 bool success = false;
RobMeades 0:5cffef3371f6 546 int at_timeout;
RobMeades 0:5cffef3371f6 547 LOCK();
RobMeades 0:5cffef3371f6 548
RobMeades 0:5cffef3371f6 549 at_timeout = _at_timeout; // Has to be inside LOCK()s
RobMeades 0:5cffef3371f6 550
RobMeades 0:5cffef3371f6 551 MBED_ASSERT(_at != NULL);
RobMeades 0:5cffef3371f6 552
RobMeades 0:5cffef3371f6 553 /* Initialize GPIO lines */
RobMeades 0:5cffef3371f6 554 tr_info("Powering up modem...");
pilotak 7:c2cf27a981b3 555 modem_init();
RobMeades 0:5cffef3371f6 556 /* Give modem a little time to settle down */
RobMeades 0:5cffef3371f6 557 wait_ms(250);
RobMeades 0:5cffef3371f6 558
RobMeades 0:5cffef3371f6 559 for (int retry_count = 0; !success && (retry_count < 20); retry_count++) {
wajahat.abbas@u-blox.com 16:afb3ca2d9915 560 //In case of SARA-R4, modem takes a while to turn on, constantly toggling the power pin every ~2 secs causes the modem to never power up.
wajahat.abbas@u-blox.com 16:afb3ca2d9915 561 if ( (retry_count % 5) == 0) {
wajahat.abbas@u-blox.com 16:afb3ca2d9915 562 modem_power_up();
wajahat.abbas@u-blox.com 16:afb3ca2d9915 563 }
RobMeades 0:5cffef3371f6 564 wait_ms(500);
RobMeades 0:5cffef3371f6 565 // Modem tends to spit out noise during power up - don't confuse the parser
RobMeades 0:5cffef3371f6 566 _at->flush();
RobMeades 0:5cffef3371f6 567 at_set_timeout(1000);
RobMeades 0:5cffef3371f6 568 if (_at->send("AT")) {
RobMeades 0:5cffef3371f6 569 // C027 needs a delay here
RobMeades 0:5cffef3371f6 570 wait_ms(100);
RobMeades 0:5cffef3371f6 571 if (_at->recv("OK")) {
RobMeades 0:5cffef3371f6 572 success = true;
RobMeades 0:5cffef3371f6 573 }
RobMeades 0:5cffef3371f6 574 }
RobMeades 0:5cffef3371f6 575 at_set_timeout(at_timeout);
RobMeades 0:5cffef3371f6 576 }
RobMeades 0:5cffef3371f6 577
rob.meades@u-blox.com 4:2e640a101db1 578 if (success) {
rob.meades@u-blox.com 4:2e640a101db1 579 // Set the final baud rate
rob.meades@u-blox.com 4:2e640a101db1 580 if (_at->send("AT+IPR=%d", _baud) && _at->recv("OK")) {
rob.meades@u-blox.com 4:2e640a101db1 581 // Need to wait for things to be sorted out on the modem side
rob.meades@u-blox.com 4:2e640a101db1 582 wait_ms(100);
rob.meades@u-blox.com 4:2e640a101db1 583 ((UARTSerial *)_fh)->set_baud(_baud);
rob.meades@u-blox.com 4:2e640a101db1 584 }
rob.meades@u-blox.com 4:2e640a101db1 585
rob.meades@u-blox.com 4:2e640a101db1 586 // Turn off modem echoing and turn on verbose responses
rob.meades@u-blox.com 4:2e640a101db1 587 success = _at->send("ATE0;+CMEE=2") && _at->recv("OK") &&
rob.meades@u-blox.com 4:2e640a101db1 588 // The following commands are best sent separately
rob.meades@u-blox.com 4:2e640a101db1 589 _at->send("AT&K0") && _at->recv("OK") && // Turn off RTC/CTS handshaking
rob.meades@u-blox.com 4:2e640a101db1 590 _at->send("AT&C1") && _at->recv("OK") && // Set DCD circuit(109), changes in accordance with the carrier detect status
rob.meades@u-blox.com 4:2e640a101db1 591 _at->send("AT&D0") && _at->recv("OK"); // Set DTR circuit, we ignore the state change of DTR
rob.meades@u-blox.com 4:2e640a101db1 592 }
RobMeades 0:5cffef3371f6 593
RobMeades 0:5cffef3371f6 594 if (!success) {
RobMeades 0:5cffef3371f6 595 tr_error("Preliminary modem setup failed.");
RobMeades 0:5cffef3371f6 596 }
RobMeades 0:5cffef3371f6 597
RobMeades 0:5cffef3371f6 598 UNLOCK();
RobMeades 0:5cffef3371f6 599 return success;
RobMeades 0:5cffef3371f6 600 }
RobMeades 0:5cffef3371f6 601
RobMeades 0:5cffef3371f6 602 // Power down modem via AT interface.
RobMeades 0:5cffef3371f6 603 void UbloxCellularBase::power_down()
RobMeades 0:5cffef3371f6 604 {
RobMeades 0:5cffef3371f6 605 LOCK();
RobMeades 0:5cffef3371f6 606
RobMeades 0:5cffef3371f6 607 MBED_ASSERT(_at != NULL);
RobMeades 0:5cffef3371f6 608
Mudassar Hussain 17:c6a4d5072589 609 // power-off modem
pilotak 7:c2cf27a981b3 610 modem_power_down();
pilotak 7:c2cf27a981b3 611 modem_deinit();
RobMeades 0:5cffef3371f6 612
Mudassar Hussain 17:c6a4d5072589 613 if (_modem_initialised && (_at != NULL)) {
Mudassar Hussain 17:c6a4d5072589 614 int at_timeout = _at_timeout; // Save previous timeout
Mudassar Hussain 17:c6a4d5072589 615 _at->set_timeout(1000);
Mudassar Hussain 17:c6a4d5072589 616 // Check modem is powered off
Mudassar Hussain 17:c6a4d5072589 617 if(_at->send("AT") && _at->recv("OK")) {
Mudassar Hussain 17:c6a4d5072589 618 _at->send("AT+CPWROFF") && _at->recv("OK");
Mudassar Hussain 17:c6a4d5072589 619 }
Mudassar Hussain 17:c6a4d5072589 620 _at->set_timeout(at_timeout);
Mudassar Hussain 17:c6a4d5072589 621 }
Mudassar Hussain 17:c6a4d5072589 622
RobMeades 0:5cffef3371f6 623 _dev_info.reg_status_csd = CSD_NOT_REGISTERED_NOT_SEARCHING;
RobMeades 0:5cffef3371f6 624 _dev_info.reg_status_psd = PSD_NOT_REGISTERED_NOT_SEARCHING;
RobMeades 0:5cffef3371f6 625 _dev_info.reg_status_eps = EPS_NOT_REGISTERED_NOT_SEARCHING;
RobMeades 0:5cffef3371f6 626
RobMeades 0:5cffef3371f6 627 UNLOCK();
RobMeades 0:5cffef3371f6 628 }
RobMeades 0:5cffef3371f6 629
RobMeades 0:5cffef3371f6 630 // Get the device ID.
RobMeades 0:5cffef3371f6 631 bool UbloxCellularBase::set_device_identity(DeviceType *dev)
RobMeades 0:5cffef3371f6 632 {
RobMeades 0:5cffef3371f6 633 char buf[20];
RobMeades 0:5cffef3371f6 634 bool success;
RobMeades 0:5cffef3371f6 635 LOCK();
RobMeades 0:5cffef3371f6 636
RobMeades 0:5cffef3371f6 637 MBED_ASSERT(_at != NULL);
RobMeades 0:5cffef3371f6 638
RobMeades 0:5cffef3371f6 639 success = _at->send("ATI") && _at->recv("%19[^\n]\nOK\n", buf);
RobMeades 0:5cffef3371f6 640
RobMeades 0:5cffef3371f6 641 if (success) {
RobMeades 0:5cffef3371f6 642 if (strstr(buf, "SARA-G35"))
RobMeades 0:5cffef3371f6 643 *dev = DEV_SARA_G35;
RobMeades 0:5cffef3371f6 644 else if (strstr(buf, "LISA-U200-03S"))
RobMeades 0:5cffef3371f6 645 *dev = DEV_LISA_U2_03S;
RobMeades 0:5cffef3371f6 646 else if (strstr(buf, "LISA-U2"))
RobMeades 0:5cffef3371f6 647 *dev = DEV_LISA_U2;
RobMeades 0:5cffef3371f6 648 else if (strstr(buf, "SARA-U2"))
RobMeades 0:5cffef3371f6 649 *dev = DEV_SARA_U2;
fahimalavi 10:c4281fa79b8f 650 else if (strstr(buf, "SARA-R4"))
fahimalavi 10:c4281fa79b8f 651 *dev = DEV_SARA_R4;
RobMeades 0:5cffef3371f6 652 else if (strstr(buf, "LEON-G2"))
RobMeades 0:5cffef3371f6 653 *dev = DEV_LEON_G2;
RobMeades 0:5cffef3371f6 654 else if (strstr(buf, "TOBY-L2"))
RobMeades 0:5cffef3371f6 655 *dev = DEV_TOBY_L2;
RobMeades 0:5cffef3371f6 656 else if (strstr(buf, "MPCI-L2"))
RobMeades 0:5cffef3371f6 657 *dev = DEV_MPCI_L2;
RobMeades 0:5cffef3371f6 658 }
RobMeades 0:5cffef3371f6 659
RobMeades 0:5cffef3371f6 660 UNLOCK();
RobMeades 0:5cffef3371f6 661 return success;
RobMeades 0:5cffef3371f6 662 }
RobMeades 0:5cffef3371f6 663
RobMeades 0:5cffef3371f6 664 // Send initialisation AT commands that are specific to the device.
RobMeades 0:5cffef3371f6 665 bool UbloxCellularBase::device_init(DeviceType dev)
RobMeades 0:5cffef3371f6 666 {
RobMeades 0:5cffef3371f6 667 bool success = false;
RobMeades 0:5cffef3371f6 668 LOCK();
RobMeades 0:5cffef3371f6 669
RobMeades 0:5cffef3371f6 670 MBED_ASSERT(_at != NULL);
RobMeades 0:5cffef3371f6 671
RobMeades 0:5cffef3371f6 672 if ((dev == DEV_LISA_U2) || (dev == DEV_LEON_G2) || (dev == DEV_TOBY_L2)) {
RobMeades 0:5cffef3371f6 673 success = _at->send("AT+UGPIOC=20,2") && _at->recv("OK");
RobMeades 0:5cffef3371f6 674 } else if ((dev == DEV_SARA_U2) || (dev == DEV_SARA_G35)) {
RobMeades 0:5cffef3371f6 675 success = _at->send("AT+UGPIOC=16,2") && _at->recv("OK");
RobMeades 0:5cffef3371f6 676 } else {
RobMeades 0:5cffef3371f6 677 success = true;
RobMeades 0:5cffef3371f6 678 }
RobMeades 0:5cffef3371f6 679
RobMeades 0:5cffef3371f6 680 UNLOCK();
RobMeades 0:5cffef3371f6 681 return success;
RobMeades 0:5cffef3371f6 682 }
RobMeades 0:5cffef3371f6 683
RobMeades 0:5cffef3371f6 684 // Get the SIM card going.
RobMeades 0:5cffef3371f6 685 bool UbloxCellularBase::initialise_sim_card()
RobMeades 0:5cffef3371f6 686 {
RobMeades 0:5cffef3371f6 687 bool success = false;
RobMeades 0:5cffef3371f6 688 int retry_count = 0;
RobMeades 0:5cffef3371f6 689 bool done = false;
RobMeades 0:5cffef3371f6 690 LOCK();
RobMeades 0:5cffef3371f6 691
RobMeades 0:5cffef3371f6 692 MBED_ASSERT(_at != NULL);
RobMeades 0:5cffef3371f6 693
RobMeades 0:5cffef3371f6 694 /* SIM initialisation may take a significant amount, so an error is
RobMeades 0:5cffef3371f6 695 * kind of expected. We should retry 10 times until we succeed or timeout. */
RobMeades 0:5cffef3371f6 696 for (retry_count = 0; !done && (retry_count < 10); retry_count++) {
RobMeades 0:5cffef3371f6 697 char pinstr[16];
RobMeades 0:5cffef3371f6 698
RobMeades 0:5cffef3371f6 699 if (_at->send("AT+CPIN?") && _at->recv("+CPIN: %15[^\n]\n", pinstr) &&
RobMeades 0:5cffef3371f6 700 _at->recv("OK")) {
RobMeades 0:5cffef3371f6 701 done = true;
RobMeades 0:5cffef3371f6 702 if (strcmp(pinstr, "SIM PIN") == 0) {
RobMeades 0:5cffef3371f6 703 _sim_pin_check_enabled = true;
RobMeades 0:5cffef3371f6 704 if (_at->send("AT+CPIN=\"%s\"", _pin)) {
RobMeades 0:5cffef3371f6 705 if (_at->recv("OK")) {
RobMeades 0:5cffef3371f6 706 tr_info("PIN correct");
RobMeades 0:5cffef3371f6 707 success = true;
RobMeades 0:5cffef3371f6 708 } else {
RobMeades 0:5cffef3371f6 709 tr_error("Incorrect PIN");
RobMeades 0:5cffef3371f6 710 }
RobMeades 0:5cffef3371f6 711 }
RobMeades 0:5cffef3371f6 712 } else if (strcmp(pinstr, "READY") == 0) {
RobMeades 0:5cffef3371f6 713 _sim_pin_check_enabled = false;
RobMeades 0:5cffef3371f6 714 tr_info("No PIN required");
RobMeades 0:5cffef3371f6 715 success = true;
RobMeades 0:5cffef3371f6 716 } else {
RobMeades 0:5cffef3371f6 717 tr_debug("Unexpected response from SIM: \"%s\"", pinstr);
RobMeades 0:5cffef3371f6 718 }
RobMeades 0:5cffef3371f6 719 }
RobMeades 0:5cffef3371f6 720
RobMeades 0:5cffef3371f6 721 /* wait for a second before retry */
RobMeades 0:5cffef3371f6 722 wait_ms(1000);
RobMeades 0:5cffef3371f6 723 }
RobMeades 0:5cffef3371f6 724
RobMeades 0:5cffef3371f6 725 if (done) {
RobMeades 0:5cffef3371f6 726 tr_info("SIM Ready.");
RobMeades 0:5cffef3371f6 727 } else {
RobMeades 0:5cffef3371f6 728 tr_error("SIM not ready.");
RobMeades 0:5cffef3371f6 729 }
RobMeades 0:5cffef3371f6 730
RobMeades 0:5cffef3371f6 731 UNLOCK();
RobMeades 0:5cffef3371f6 732 return success;
RobMeades 0:5cffef3371f6 733 }
RobMeades 0:5cffef3371f6 734
RobMeades 0:5cffef3371f6 735 /**********************************************************************
RobMeades 0:5cffef3371f6 736 * PUBLIC METHODS
RobMeades 0:5cffef3371f6 737 **********************************************************************/
RobMeades 0:5cffef3371f6 738
RobMeades 0:5cffef3371f6 739 // Initialise the modem.
RobMeades 0:5cffef3371f6 740 bool UbloxCellularBase::init(const char *pin)
RobMeades 0:5cffef3371f6 741 {
RobMeades 8:a15349fcab25 742 int x;
RobMeades 0:5cffef3371f6 743 MBED_ASSERT(_at != NULL);
RobMeades 0:5cffef3371f6 744
RobMeades 0:5cffef3371f6 745 if (!_modem_initialised) {
RobMeades 0:5cffef3371f6 746 if (power_up()) {
RobMeades 0:5cffef3371f6 747 tr_info("Modem Ready.");
RobMeades 0:5cffef3371f6 748 if (pin != NULL) {
RobMeades 0:5cffef3371f6 749 _pin = pin;
RobMeades 0:5cffef3371f6 750 }
RobMeades 0:5cffef3371f6 751 if (initialise_sim_card()) {
RobMeades 0:5cffef3371f6 752 if (set_device_identity(&_dev_info.dev) && // Set up device identity
rob.meades@u-blox.com 6:8fadf1e49487 753 device_init(_dev_info.dev)) {// Initialise this device
rob.meades@u-blox.com 6:8fadf1e49487 754 // Get the integrated circuit ID of the SIM
rob.meades@u-blox.com 6:8fadf1e49487 755 if (get_iccid()) {
rob.meades@u-blox.com 6:8fadf1e49487 756 // Try a few times to get the IMSI (since on some modems this can
rob.meades@u-blox.com 6:8fadf1e49487 757 // take a while to be retrieved, especially if a SIM PIN
rob.meades@u-blox.com 6:8fadf1e49487 758 // was set)
RobMeades 8:a15349fcab25 759 for (x = 0; (x < 3) && !get_imsi(); x++) {
rob.meades@u-blox.com 6:8fadf1e49487 760 wait_ms(1000);
rob.meades@u-blox.com 6:8fadf1e49487 761 }
rob.meades@u-blox.com 6:8fadf1e49487 762
RobMeades 8:a15349fcab25 763 if (x < 3) { // If we got the IMSI, can get the others
rob.meades@u-blox.com 6:8fadf1e49487 764 if (get_imei() && // Get international mobile equipment identifier
rob.meades@u-blox.com 6:8fadf1e49487 765 get_meid() && // Probably the same as the IMEI
rob.meades@u-blox.com 6:8fadf1e49487 766 set_sms()) { // And set up SMS
rob.meades@u-blox.com 6:8fadf1e49487 767 // The modem is initialised.
rob.meades@u-blox.com 6:8fadf1e49487 768 _modem_initialised = true;
rob.meades@u-blox.com 6:8fadf1e49487 769 }
rob.meades@u-blox.com 6:8fadf1e49487 770 }
rob.meades@u-blox.com 6:8fadf1e49487 771 }
RobMeades 0:5cffef3371f6 772 }
RobMeades 0:5cffef3371f6 773 }
RobMeades 0:5cffef3371f6 774 }
RobMeades 0:5cffef3371f6 775 }
RobMeades 0:5cffef3371f6 776
RobMeades 0:5cffef3371f6 777 return _modem_initialised;
RobMeades 0:5cffef3371f6 778 }
RobMeades 0:5cffef3371f6 779
RobMeades 0:5cffef3371f6 780 // Perform registration.
RobMeades 0:5cffef3371f6 781 bool UbloxCellularBase::nwk_registration()
RobMeades 0:5cffef3371f6 782 {
RobMeades 0:5cffef3371f6 783 bool atSuccess = false;
RobMeades 0:5cffef3371f6 784 bool registered = false;
RobMeades 0:5cffef3371f6 785 int status;
RobMeades 0:5cffef3371f6 786 int at_timeout;
RobMeades 0:5cffef3371f6 787 LOCK();
RobMeades 0:5cffef3371f6 788
RobMeades 0:5cffef3371f6 789 at_timeout = _at_timeout; // Has to be inside LOCK()s
RobMeades 0:5cffef3371f6 790
RobMeades 0:5cffef3371f6 791 MBED_ASSERT(_at != NULL);
RobMeades 0:5cffef3371f6 792
RobMeades 0:5cffef3371f6 793 if (!is_registered_psd() && !is_registered_csd() && !is_registered_eps()) {
RobMeades 0:5cffef3371f6 794 tr_info("Searching Network...");
RobMeades 0:5cffef3371f6 795 // Enable the packet switched and network registration unsolicited result codes
RobMeades 0:5cffef3371f6 796 if (_at->send("AT+CREG=1") && _at->recv("OK") &&
RobMeades 0:5cffef3371f6 797 _at->send("AT+CGREG=1") && _at->recv("OK")) {
RobMeades 0:5cffef3371f6 798 atSuccess = true;
RobMeades 0:5cffef3371f6 799 if (_at->send("AT+CEREG=1")) {
RobMeades 0:5cffef3371f6 800 _at->recv("OK");
RobMeades 0:5cffef3371f6 801 // Don't check return value as this works for LTE only
RobMeades 0:5cffef3371f6 802 }
RobMeades 0:5cffef3371f6 803
RobMeades 0:5cffef3371f6 804 if (atSuccess) {
wajahat.abbas@u-blox.com 22:b69465e9f076 805 // See if a PLMN is set by user
wajahat.abbas@u-blox.com 22:b69465e9f076 806 if (_plmn[0] != 0) {
wajahat.abbas@u-blox.com 22:b69465e9f076 807 tr_debug("Manual network registration to %s, please wait upto 3 minutes", _plmn);
wajahat.abbas@u-blox.com 22:b69465e9f076 808 at_set_timeout(3*60*1000);
wajahat.abbas@u-blox.com 22:b69465e9f076 809 _at->send("AT+COPS=1,2,\"%s\"", _plmn) && _at->recv("OK");
wajahat.abbas@u-blox.com 22:b69465e9f076 810 } else {
wajahat.abbas@u-blox.com 22:b69465e9f076 811 tr_debug("Automatic network registration");
wajahat.abbas@u-blox.com 22:b69465e9f076 812 _at->send("AT+COPS=0") && _at->recv("OK");
RobMeades 0:5cffef3371f6 813 }
wajahat.abbas@u-blox.com 22:b69465e9f076 814 at_set_timeout(at_timeout);
RobMeades 0:5cffef3371f6 815
RobMeades 0:5cffef3371f6 816 // Query the registration status directly as well,
RobMeades 0:5cffef3371f6 817 // just in case
RobMeades 0:5cffef3371f6 818 if (_at->send("AT+CREG?") && _at->recv("OK")) {
RobMeades 0:5cffef3371f6 819 // Answer will be processed by URC
RobMeades 0:5cffef3371f6 820 }
RobMeades 0:5cffef3371f6 821 if (_at->send("AT+CGREG?") && _at->recv("OK")) {
RobMeades 0:5cffef3371f6 822 // Answer will be processed by URC
RobMeades 0:5cffef3371f6 823 }
RobMeades 0:5cffef3371f6 824 if (_at->send("AT+CEREG?")) {
RobMeades 0:5cffef3371f6 825 _at->recv("OK");
RobMeades 0:5cffef3371f6 826 // Don't check return value as this works for LTE only
RobMeades 0:5cffef3371f6 827 }
RobMeades 0:5cffef3371f6 828 }
RobMeades 0:5cffef3371f6 829 }
RobMeades 0:5cffef3371f6 830 // Wait for registration to succeed
RobMeades 0:5cffef3371f6 831 at_set_timeout(1000);
RobMeades 0:5cffef3371f6 832 for (int waitSeconds = 0; !registered && (waitSeconds < 180); waitSeconds++) {
RobMeades 0:5cffef3371f6 833 registered = is_registered_psd() || is_registered_csd() || is_registered_eps();
RobMeades 0:5cffef3371f6 834 _at->recv(UNNATURAL_STRING);
RobMeades 0:5cffef3371f6 835 }
RobMeades 0:5cffef3371f6 836 at_set_timeout(at_timeout);
RobMeades 0:5cffef3371f6 837
RobMeades 0:5cffef3371f6 838 if (registered) {
RobMeades 0:5cffef3371f6 839 // This should return quickly but sometimes the status field is not returned
RobMeades 0:5cffef3371f6 840 // so make the timeout short
RobMeades 0:5cffef3371f6 841 at_set_timeout(1000);
RobMeades 0:5cffef3371f6 842 if (_at->send("AT+COPS?") && _at->recv("+COPS: %*d,%*d,\"%*[^\"]\",%d\n", &status)) {
RobMeades 0:5cffef3371f6 843 set_rat(status);
RobMeades 0:5cffef3371f6 844 }
RobMeades 0:5cffef3371f6 845 at_set_timeout(at_timeout);
RobMeades 0:5cffef3371f6 846 }
RobMeades 0:5cffef3371f6 847 } else {
RobMeades 0:5cffef3371f6 848 registered = true;
RobMeades 0:5cffef3371f6 849 }
RobMeades 0:5cffef3371f6 850
RobMeades 0:5cffef3371f6 851 UNLOCK();
RobMeades 0:5cffef3371f6 852 return registered;
RobMeades 0:5cffef3371f6 853 }
RobMeades 0:5cffef3371f6 854
RobMeades 0:5cffef3371f6 855 bool UbloxCellularBase::is_registered_csd()
RobMeades 0:5cffef3371f6 856 {
RobMeades 0:5cffef3371f6 857 return (_dev_info.reg_status_csd == CSD_REGISTERED) ||
RobMeades 0:5cffef3371f6 858 (_dev_info.reg_status_csd == CSD_REGISTERED_ROAMING) ||
RobMeades 0:5cffef3371f6 859 (_dev_info.reg_status_csd == CSD_CSFB_NOT_PREFERRED);
RobMeades 0:5cffef3371f6 860 }
RobMeades 0:5cffef3371f6 861
RobMeades 0:5cffef3371f6 862 bool UbloxCellularBase::is_registered_psd()
RobMeades 0:5cffef3371f6 863 {
RobMeades 0:5cffef3371f6 864 return (_dev_info.reg_status_psd == PSD_REGISTERED) ||
RobMeades 0:5cffef3371f6 865 (_dev_info.reg_status_psd == PSD_REGISTERED_ROAMING);
RobMeades 0:5cffef3371f6 866 }
RobMeades 0:5cffef3371f6 867
RobMeades 0:5cffef3371f6 868 bool UbloxCellularBase::is_registered_eps()
RobMeades 0:5cffef3371f6 869 {
RobMeades 0:5cffef3371f6 870 return (_dev_info.reg_status_eps == EPS_REGISTERED) ||
RobMeades 0:5cffef3371f6 871 (_dev_info.reg_status_eps == EPS_REGISTERED_ROAMING);
RobMeades 0:5cffef3371f6 872 }
RobMeades 0:5cffef3371f6 873
RobMeades 0:5cffef3371f6 874 // Perform deregistration.
RobMeades 0:5cffef3371f6 875 bool UbloxCellularBase::nwk_deregistration()
RobMeades 0:5cffef3371f6 876 {
RobMeades 0:5cffef3371f6 877 bool success = false;
RobMeades 0:5cffef3371f6 878 LOCK();
RobMeades 0:5cffef3371f6 879
RobMeades 0:5cffef3371f6 880 MBED_ASSERT(_at != NULL);
RobMeades 0:5cffef3371f6 881
RobMeades 0:5cffef3371f6 882 if (_at->send("AT+COPS=2") && _at->recv("OK")) {
RobMeades 0:5cffef3371f6 883 _dev_info.reg_status_csd = CSD_NOT_REGISTERED_NOT_SEARCHING;
RobMeades 0:5cffef3371f6 884 _dev_info.reg_status_psd = PSD_NOT_REGISTERED_NOT_SEARCHING;
RobMeades 0:5cffef3371f6 885 _dev_info.reg_status_eps = EPS_NOT_REGISTERED_NOT_SEARCHING;
RobMeades 0:5cffef3371f6 886 success = true;
RobMeades 0:5cffef3371f6 887 }
RobMeades 0:5cffef3371f6 888
RobMeades 0:5cffef3371f6 889 UNLOCK();
RobMeades 0:5cffef3371f6 890 return success;
RobMeades 0:5cffef3371f6 891 }
RobMeades 0:5cffef3371f6 892
RobMeades 0:5cffef3371f6 893 // Put the modem into its lowest power state.
RobMeades 0:5cffef3371f6 894 void UbloxCellularBase::deinit()
RobMeades 0:5cffef3371f6 895 {
RobMeades 0:5cffef3371f6 896 power_down();
RobMeades 0:5cffef3371f6 897 _modem_initialised = false;
RobMeades 0:5cffef3371f6 898 }
RobMeades 0:5cffef3371f6 899
RobMeades 0:5cffef3371f6 900 // Set the PIN.
RobMeades 0:5cffef3371f6 901 void UbloxCellularBase::set_pin(const char *pin) {
RobMeades 0:5cffef3371f6 902 _pin = pin;
RobMeades 0:5cffef3371f6 903 }
RobMeades 0:5cffef3371f6 904
RobMeades 0:5cffef3371f6 905 // Enable or disable SIM pin checking.
rob.meades@u-blox.com 4:2e640a101db1 906 bool UbloxCellularBase::sim_pin_check_enable(bool enableNotDisable)
RobMeades 0:5cffef3371f6 907 {
RobMeades 0:5cffef3371f6 908 bool success = false;;
RobMeades 0:5cffef3371f6 909 LOCK();
RobMeades 0:5cffef3371f6 910
RobMeades 0:5cffef3371f6 911 MBED_ASSERT(_at != NULL);
RobMeades 0:5cffef3371f6 912
RobMeades 0:5cffef3371f6 913 if (_pin != NULL) {
RobMeades 0:5cffef3371f6 914 if (_sim_pin_check_enabled && !enableNotDisable) {
RobMeades 0:5cffef3371f6 915 // Disable the SIM lock
RobMeades 0:5cffef3371f6 916 if (_at->send("AT+CLCK=\"SC\",0,\"%s\"", _pin) && _at->recv("OK")) {
RobMeades 0:5cffef3371f6 917 _sim_pin_check_enabled = false;
RobMeades 0:5cffef3371f6 918 success = true;
RobMeades 0:5cffef3371f6 919 }
RobMeades 0:5cffef3371f6 920 } else if (!_sim_pin_check_enabled && enableNotDisable) {
RobMeades 0:5cffef3371f6 921 // Enable the SIM lock
RobMeades 0:5cffef3371f6 922 if (_at->send("AT+CLCK=\"SC\",1,\"%s\"", _pin) && _at->recv("OK")) {
RobMeades 0:5cffef3371f6 923 _sim_pin_check_enabled = true;
RobMeades 0:5cffef3371f6 924 success = true;
RobMeades 0:5cffef3371f6 925 }
RobMeades 0:5cffef3371f6 926 } else {
RobMeades 0:5cffef3371f6 927 success = true;
RobMeades 0:5cffef3371f6 928 }
RobMeades 0:5cffef3371f6 929 }
RobMeades 0:5cffef3371f6 930
RobMeades 0:5cffef3371f6 931 UNLOCK();
RobMeades 0:5cffef3371f6 932 return success;
RobMeades 0:5cffef3371f6 933 }
RobMeades 0:5cffef3371f6 934
RobMeades 0:5cffef3371f6 935 // Change the pin code for the SIM card.
RobMeades 0:5cffef3371f6 936 bool UbloxCellularBase::change_sim_pin(const char *pin)
RobMeades 0:5cffef3371f6 937 {
RobMeades 0:5cffef3371f6 938 bool success = false;;
RobMeades 0:5cffef3371f6 939 LOCK();
RobMeades 0:5cffef3371f6 940
RobMeades 0:5cffef3371f6 941 MBED_ASSERT(_at != NULL);
RobMeades 0:5cffef3371f6 942
RobMeades 0:5cffef3371f6 943 // Change the SIM pin
RobMeades 0:5cffef3371f6 944 if ((pin != NULL) && (_pin != NULL)) {
RobMeades 0:5cffef3371f6 945 if (_at->send("AT+CPWD=\"SC\",\"%s\",\"%s\"", _pin, pin) && _at->recv("OK")) {
RobMeades 0:5cffef3371f6 946 _pin = pin;
RobMeades 0:5cffef3371f6 947 success = true;
RobMeades 0:5cffef3371f6 948 }
RobMeades 0:5cffef3371f6 949 }
RobMeades 0:5cffef3371f6 950
RobMeades 0:5cffef3371f6 951 UNLOCK();
RobMeades 0:5cffef3371f6 952 return success;
RobMeades 0:5cffef3371f6 953 }
RobMeades 0:5cffef3371f6 954
RobMeades 14:e420232ee4e7 955 // Get the IMEI.
fahim alavi 13:158a035b1b50 956 bool UbloxCellularBase::get_imei(char *imei_to_send, int size)
fahim alavi 13:158a035b1b50 957 {
fahim alavi 13:158a035b1b50 958 bool success;
fahim alavi 13:158a035b1b50 959 LOCK();
fahim alavi 13:158a035b1b50 960
fahim alavi 13:158a035b1b50 961 MBED_ASSERT(_at != NULL);
fahim alavi 13:158a035b1b50 962
fahim alavi 13:158a035b1b50 963 // International mobile equipment identifier
fahim alavi 13:158a035b1b50 964 // AT Command Manual UBX-13002752, section 4.7
fahim alavi 13:158a035b1b50 965 success = _at->send("AT+CGSN") && _at->recv("%15[^\n]\nOK\n", _dev_info.imei);
fahim alavi 13:158a035b1b50 966 tr_info("DevInfo: IMEI=%s", _dev_info.imei);
fahim alavi 13:158a035b1b50 967
fahim alavi 13:158a035b1b50 968 if (success) {
fahim alavi 13:158a035b1b50 969 memcpy(imei_to_send,_dev_info.imei,size);
fahim alavi 13:158a035b1b50 970 imei_to_send[size-1] = '\0';
fahim alavi 13:158a035b1b50 971 }
fahim alavi 13:158a035b1b50 972
fahim alavi 13:158a035b1b50 973 UNLOCK();
fahim alavi 13:158a035b1b50 974 return success;
fahim alavi 13:158a035b1b50 975 }
fahim alavi 13:158a035b1b50 976
RobMeades 14:e420232ee4e7 977 // Get the IMEI of the module.
RobMeades 14:e420232ee4e7 978 const char *UbloxCellularBase::imei()
RobMeades 14:e420232ee4e7 979 {
RobMeades 14:e420232ee4e7 980 return _dev_info.imei;
RobMeades 14:e420232ee4e7 981 }
RobMeades 14:e420232ee4e7 982
RobMeades 14:e420232ee4e7 983 // Get the Mobile Equipment ID (which may be the same as the IMEI).
RobMeades 14:e420232ee4e7 984 const char *UbloxCellularBase::meid()
RobMeades 14:e420232ee4e7 985 {
RobMeades 14:e420232ee4e7 986 return _dev_info.meid;
RobMeades 14:e420232ee4e7 987 }
RobMeades 14:e420232ee4e7 988
RobMeades 14:e420232ee4e7 989 // Get the IMSI of the SIM.
RobMeades 14:e420232ee4e7 990 const char *UbloxCellularBase::imsi()
RobMeades 14:e420232ee4e7 991 {
RobMeades 14:e420232ee4e7 992 // (try) to update the IMSI, just in case the SIM has changed
RobMeades 14:e420232ee4e7 993 get_imsi();
RobMeades 14:e420232ee4e7 994
RobMeades 14:e420232ee4e7 995 return _dev_info.imsi;
RobMeades 14:e420232ee4e7 996 }
RobMeades 14:e420232ee4e7 997
RobMeades 14:e420232ee4e7 998 // Get the ICCID of the SIM.
RobMeades 14:e420232ee4e7 999 const char *UbloxCellularBase::iccid()
RobMeades 14:e420232ee4e7 1000 {
RobMeades 14:e420232ee4e7 1001 // (try) to update the ICCID, just in case the SIM has changed
RobMeades 14:e420232ee4e7 1002 get_iccid();
RobMeades 14:e420232ee4e7 1003
RobMeades 14:e420232ee4e7 1004 return _dev_info.iccid;
RobMeades 14:e420232ee4e7 1005 }
RobMeades 14:e420232ee4e7 1006
RobMeades 14:e420232ee4e7 1007 // Get the RSSI in dBm.
RobMeades 14:e420232ee4e7 1008 int UbloxCellularBase::rssi()
RobMeades 14:e420232ee4e7 1009 {
RobMeades 14:e420232ee4e7 1010 char buf[7] = {0};
RobMeades 14:e420232ee4e7 1011 int rssi = 0;
RobMeades 14:e420232ee4e7 1012 int qual = 0;
RobMeades 14:e420232ee4e7 1013 int rssiRet = 0;
RobMeades 14:e420232ee4e7 1014 bool success;
RobMeades 14:e420232ee4e7 1015 LOCK();
RobMeades 14:e420232ee4e7 1016
RobMeades 14:e420232ee4e7 1017 MBED_ASSERT(_at != NULL);
RobMeades 14:e420232ee4e7 1018
RobMeades 14:e420232ee4e7 1019 success = _at->send("AT+CSQ") && _at->recv("+CSQ: %6[^\n]\nOK\n", buf);
RobMeades 14:e420232ee4e7 1020
RobMeades 14:e420232ee4e7 1021 if (success) {
RobMeades 14:e420232ee4e7 1022 if (sscanf(buf, "%d,%d", &rssi, &qual) == 2) {
RobMeades 14:e420232ee4e7 1023 // AT+CSQ returns a coded RSSI value and an RxQual value
RobMeades 14:e420232ee4e7 1024 // For 2G an RSSI of 0 corresponds to -113 dBm or less,
RobMeades 14:e420232ee4e7 1025 // an RSSI of 31 corresponds to -51 dBm or less and hence
RobMeades 14:e420232ee4e7 1026 // each value is a 2 dB step.
RobMeades 14:e420232ee4e7 1027 // For LTE the mapping is defined in the array rssiConvertLte[].
RobMeades 14:e420232ee4e7 1028 // For 3G the mapping to RSCP is defined in the array rscpConvert3G[]
RobMeades 14:e420232ee4e7 1029 // and the RSSI value is then RSCP - the EC_NO_LEV number derived
RobMeades 14:e420232ee4e7 1030 // by putting the qual number through qualConvert3G[].
RobMeades 14:e420232ee4e7 1031 if ((rssi >= 0) && (rssi <= 31)) {
RobMeades 14:e420232ee4e7 1032 switch (_dev_info.rat) {
RobMeades 14:e420232ee4e7 1033 case UTRAN:
RobMeades 14:e420232ee4e7 1034 case HSDPA:
RobMeades 14:e420232ee4e7 1035 case HSUPA:
RobMeades 14:e420232ee4e7 1036 case HSDPA_HSUPA:
RobMeades 14:e420232ee4e7 1037 // 3G
RobMeades 14:e420232ee4e7 1038 if ((qual >= 0) && (qual <= 7)) {
RobMeades 14:e420232ee4e7 1039 qual = qualConvert3G[qual];
fahim.alavi@u-blox.com 15:93b157a47b8d 1040 rssiRet = rscpConvert3G[rssi];
fahim.alavi@u-blox.com 15:93b157a47b8d 1041 rssiRet -= qual;
RobMeades 14:e420232ee4e7 1042 }
fahim.alavi@u-blox.com 15:93b157a47b8d 1043
RobMeades 14:e420232ee4e7 1044 break;
RobMeades 14:e420232ee4e7 1045 case LTE:
RobMeades 14:e420232ee4e7 1046 // LTE
RobMeades 14:e420232ee4e7 1047 rssiRet = rssiConvertLte[rssi];
RobMeades 14:e420232ee4e7 1048 break;
RobMeades 14:e420232ee4e7 1049 case GSM:
RobMeades 14:e420232ee4e7 1050 case COMPACT_GSM:
RobMeades 14:e420232ee4e7 1051 case EDGE:
RobMeades 14:e420232ee4e7 1052 default:
RobMeades 14:e420232ee4e7 1053 // GSM or assumed GSM if the RAT is not known
RobMeades 14:e420232ee4e7 1054 rssiRet = -(113 - (rssi << 2));
RobMeades 14:e420232ee4e7 1055 break;
RobMeades 14:e420232ee4e7 1056 }
RobMeades 14:e420232ee4e7 1057 }
RobMeades 14:e420232ee4e7 1058 }
RobMeades 14:e420232ee4e7 1059 }
RobMeades 14:e420232ee4e7 1060
RobMeades 14:e420232ee4e7 1061 UNLOCK();
RobMeades 14:e420232ee4e7 1062 return rssiRet;
RobMeades 14:e420232ee4e7 1063 }
RobMeades 14:e420232ee4e7 1064
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1065 //RAT should be set in a detached state (AT+COPS=2)
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1066 bool UbloxCellularBase::set_modem_rat(RAT selected_rat, RAT preferred_rat, RAT second_preferred_rat)
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1067 {
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1068 bool success = false;
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1069 char command[16] = {0x00};
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1070
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1071 //check if modem is registered with network
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1072 if (is_registered_csd() || is_registered_psd() || is_registered_eps()) {
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1073 tr_error("RAT should only be set in detached state");
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1074 return false;
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1075 }
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1076
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1077 if (preferred_rat != NOT_USED && second_preferred_rat != NOT_USED) {
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1078 sprintf(command, "AT+URAT=%d,%d,%d", selected_rat, preferred_rat, second_preferred_rat);
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1079 } else if (preferred_rat != NOT_USED) {
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1080 sprintf(command, "AT+URAT=%d,%d", selected_rat, preferred_rat);
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1081 } else if (second_preferred_rat != NOT_USED) {
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1082 sprintf(command, "AT+URAT=%d,%d", selected_rat, second_preferred_rat);
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1083 } else {
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1084 sprintf(command, "AT+URAT=%d", selected_rat);
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1085 }
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1086
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1087 LOCK();
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1088 if (_at->send(command) && _at->recv("OK")) {
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1089 success = true;
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1090 } else {
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1091 tr_error("unable to set the specified RAT");
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1092 success = false;
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1093 }
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1094 UNLOCK();
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1095
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1096 return success;
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1097 }
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1098
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1099 bool UbloxCellularBase::get_modem_rat(RAT *selected_rat, RAT *preferred_rat, RAT *second_preferred_rat)
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1100 {
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1101 bool success = false;
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1102 char buf[24] = {0x00};
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1103
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1104 if (selected_rat == NULL || preferred_rat == NULL || second_preferred_rat == NULL) {
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1105 tr_info("invalid pointers");
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1106 return false;
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1107 }
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1108
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1109 MBED_ASSERT(_at != NULL);
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1110
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1111 *selected_rat = NOT_USED;
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1112 *preferred_rat = NOT_USED;
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1113 *second_preferred_rat = NOT_USED;
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1114
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1115 LOCK();
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1116
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1117 if (_at->send("AT+URAT?") && _at->recv("%23[^\n]\nOK\n", buf)) {
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1118 if (sscanf(buf, "+URAT: %d,%d,%d", (int*)selected_rat, (int*)preferred_rat, (int*)second_preferred_rat) == 3) {
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1119 success = true;
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1120 } else if (sscanf(buf, "+URAT: %d,%d", (int*)selected_rat, (int*)preferred_rat) == 2) {
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1121 success = true;
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1122 } else if (sscanf(buf, "+URAT: %d", (int*)selected_rat) == 1) {
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1123 success = true;
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1124 }
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1125 }
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1126
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1127 UNLOCK();
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1128 return success;
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1129 }
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1130
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1131 // Power down modem via AT interface.
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1132 bool UbloxCellularBase::reboot_modem()
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1133 {
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1134 bool return_val = false;
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1135 int at_timeout;
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1136 LOCK();
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1137
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1138 MBED_ASSERT(_at != NULL);
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1139
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1140 at_timeout = _at_timeout; // Has to be inside LOCK()s
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1141 at_set_timeout(3*60*1000); //command has 3 minutes timeout
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1142 tr_info("rebooting modem...");
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1143
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1144 if (_at->send("AT+CFUN=15") && _at->recv("OK")) {
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1145 tr_info("reboot successful");
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1146 return_val = true;
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1147 }
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1148
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1149 _dev_info.reg_status_csd = CSD_NOT_REGISTERED_NOT_SEARCHING;
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1150 _dev_info.reg_status_psd = PSD_NOT_REGISTERED_NOT_SEARCHING;
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1151 _dev_info.reg_status_eps = EPS_NOT_REGISTERED_NOT_SEARCHING;
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1152 _modem_initialised = false;
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1153 at_set_timeout(at_timeout);
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1154 UNLOCK();
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1155
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1156 return return_val;
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1157 }
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1158
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1159 #ifdef TARGET_UBLOX_C030_R41XM
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1160 bool UbloxCellularBase::set_mno_profile(MNOProfile profile)
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1161 {
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1162 bool return_val = false;
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1163
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1164 MNOProfile mno_profile;
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1165 if (get_mno_profile(&mno_profile)) {
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1166 tr_info("Current MNO profile is: %d", (int)mno_profile);
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1167 if (mno_profile != profile) {
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1168
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1169 if (is_registered_csd() || is_registered_psd() || is_registered_eps()) {
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1170 tr_error("MNO profile should only be set in detached state");
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1171 return false;
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1172 }
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1173
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1174 LOCK();
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1175 if (_at->send("AT+UMNOPROF=%d", profile) && _at->recv("OK")) {
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1176 return_val = true;
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1177 } else {
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1178 tr_error("unable to set specified profile");
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1179 }
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1180 UNLOCK();
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1181
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1182 } else {
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1183 return_val = true;
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1184 }
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1185 } else {
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1186 tr_error("could not read MNO profile");
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1187 }
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1188
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1189 return return_val;
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1190 }
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1191
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1192 bool UbloxCellularBase::get_mno_profile(MNOProfile *profile)
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1193 {
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1194 bool return_val = false;
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1195
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1196 if (profile == NULL) {
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1197 return false;
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1198 }
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1199
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1200 LOCK();
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1201 MBED_ASSERT(_at != NULL);
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1202
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1203 if ( (_at->send("AT+UMNOPROF?") && _at->recv("+UMNOPROF: %d", (int*)profile) && _at->recv("OK")) ) {
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1204 return_val = true;
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1205 }
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1206
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1207 UNLOCK();
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1208 return return_val;
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1209 }
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1210 #endif
wajahat.abbas@u-blox.com 20:31d5e048fbfa 1211
RobMeades 0:5cffef3371f6 1212 // End of File
RobMeades 0:5cffef3371f6 1213