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