Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: TYBLE16_simple_data_logger TYBLE16_MP3_Air
QUECTEL_BG96.cpp
00001 /* 00002 * Copyright (c) 2017, Arm Limited and affiliates. 00003 * SPDX-License-Identifier: Apache-2.0 00004 * 00005 * Licensed under the Apache License, Version 2.0 (the "License"); 00006 * you may not use this file except in compliance with the License. 00007 * You may obtain a copy of the License at 00008 * 00009 * http://www.apache.org/licenses/LICENSE-2.0 00010 * 00011 * Unless required by applicable law or agreed to in writing, software 00012 * distributed under the License is distributed on an "AS IS" BASIS, 00013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00014 * See the License for the specific language governing permissions and 00015 * limitations under the License. 00016 */ 00017 00018 #include "rtos/ThisThread.h" 00019 #include "QUECTEL_BG96.h" 00020 #include "QUECTEL_BG96_CellularNetwork.h" 00021 #include "QUECTEL_BG96_CellularStack.h" 00022 #include "QUECTEL_BG96_CellularInformation.h" 00023 #include "QUECTEL_BG96_CellularContext.h" 00024 #include "CellularLog.h" 00025 00026 using namespace mbed; 00027 using namespace events; 00028 using namespace rtos; 00029 00030 #define CONNECT_DELIM "\r\n" 00031 #define CONNECT_BUFFER_SIZE (1280 + 80 + 80) // AT response + sscanf format 00032 #define CONNECT_TIMEOUT 8000 00033 00034 #define DEVICE_READY_URC "CPIN:" 00035 00036 #if !defined(MBED_CONF_QUECTEL_BG96_PWR) 00037 #define MBED_CONF_QUECTEL_BG96_PWR NC 00038 #endif 00039 00040 #if !defined(MBED_CONF_QUECTEL_BG96_RST) 00041 #define MBED_CONF_QUECTEL_BG96_RST NC 00042 #endif 00043 00044 #if !defined(MBED_CONF_QUECTEL_BG96_POLARITY) 00045 #define MBED_CONF_QUECTEL_BG96_POLARITY 1 // active high 00046 #endif 00047 00048 static const intptr_t cellular_properties[AT_CellularDevice::PROPERTY_MAX] = { 00049 AT_CellularNetwork::RegistrationModeLAC, // C_EREG 00050 AT_CellularNetwork::RegistrationModeLAC, // C_GREG 00051 AT_CellularNetwork::RegistrationModeLAC, // C_REG 00052 0, // AT_CGSN_WITH_TYPE 00053 0, // AT_CGDATA 00054 1, // AT_CGAUTH 00055 1, // AT_CNMI 00056 1, // AT_CSMP 00057 1, // AT_CMGF 00058 1, // AT_CSDH 00059 1, // PROPERTY_IPV4_STACK 00060 1, // PROPERTY_IPV6_STACK 00061 0, // PROPERTY_IPV4V6_STACK 00062 1, // PROPERTY_NON_IP_PDP_TYPE 00063 1, // PROPERTY_AT_CGEREP 00064 }; 00065 00066 QUECTEL_BG96::QUECTEL_BG96(FileHandle *fh, PinName pwr, bool active_high, PinName rst) 00067 : AT_CellularDevice(fh), 00068 _active_high(active_high), 00069 _pwr(pwr, !_active_high), 00070 _rst(rst, !_active_high) 00071 { 00072 set_cellular_properties(cellular_properties); 00073 } 00074 00075 void QUECTEL_BG96::set_at_urcs_impl() 00076 { 00077 _at->set_urc_handler("+QIURC: \"pdpde", mbed::Callback<void()>(this, &QUECTEL_BG96::urc_pdpdeact)); 00078 } 00079 00080 AT_CellularNetwork *QUECTEL_BG96::open_network_impl(ATHandler &at) 00081 { 00082 return new QUECTEL_BG96_CellularNetwork(at, *this); 00083 } 00084 00085 AT_CellularContext *QUECTEL_BG96::create_context_impl(ATHandler &at, const char *apn, bool cp_req, bool nonip_req) 00086 { 00087 return new QUECTEL_BG96_CellularContext(at, this, apn, cp_req, nonip_req); 00088 } 00089 00090 AT_CellularInformation *QUECTEL_BG96::open_information_impl(ATHandler &at) 00091 { 00092 return new QUECTEL_BG96_CellularInformation(at, *this); 00093 } 00094 00095 void QUECTEL_BG96::set_ready_cb(Callback<void()> callback) 00096 { 00097 _at->set_urc_handler(DEVICE_READY_URC, callback); 00098 } 00099 00100 nsapi_error_t QUECTEL_BG96::soft_power_on() 00101 { 00102 if (_pwr.is_connected()) { 00103 tr_info("QUECTEL_BG96::soft_power_on"); 00104 // check if modem was powered on already 00105 if (!wake_up()) { 00106 if (!wake_up(true)) { 00107 tr_error("Modem not responding"); 00108 soft_power_off(); 00109 return NSAPI_ERROR_DEVICE_ERROR ; 00110 } 00111 } 00112 } 00113 00114 #if defined (MBED_CONF_QUECTEL_BG96_RTS) && defined(MBED_CONF_QUECTEL_BG96_CTS) 00115 if (_at->at_cmd_discard("+IFC", "=", "%d%d", 2, 2) != NSAPI_ERROR_OK ) { 00116 tr_warn("Set flow control failed"); 00117 return NSAPI_ERROR_DEVICE_ERROR ; 00118 } 00119 #endif 00120 00121 return NSAPI_ERROR_OK ; 00122 } 00123 00124 nsapi_error_t QUECTEL_BG96::soft_power_off() 00125 { 00126 _at->lock(); 00127 _at->cmd_start("AT+QPOWD"); 00128 _at->cmd_stop_read_resp(); 00129 if (_at->get_last_error() != NSAPI_ERROR_OK ) { 00130 tr_warn("Force modem off"); 00131 if (_pwr.is_connected()) { 00132 press_button(_pwr, 650); // BG96_Hardware_Design_V1.1: Power off signal at least 650 ms 00133 } 00134 } 00135 return _at->unlock_return_error(); 00136 } 00137 00138 #if MBED_CONF_QUECTEL_BG96_PROVIDE_DEFAULT 00139 #include "UARTSerial.h" 00140 CellularDevice *CellularDevice::get_default_instance() 00141 { 00142 static UARTSerial serial(MBED_CONF_QUECTEL_BG96_TX, MBED_CONF_QUECTEL_BG96_RX, MBED_CONF_QUECTEL_BG96_BAUDRATE); 00143 #if defined (MBED_CONF_QUECTEL_BG96_RTS) && defined(MBED_CONF_QUECTEL_BG96_CTS) 00144 tr_debug("QUECTEL_BG96 flow control: RTS %d CTS %d", MBED_CONF_QUECTEL_BG96_RTS, MBED_CONF_QUECTEL_BG96_CTS); 00145 serial.set_flow_control(SerialBase::RTSCTS, MBED_CONF_QUECTEL_BG96_RTS, MBED_CONF_QUECTEL_BG96_CTS); 00146 #endif 00147 static QUECTEL_BG96 device(&serial, 00148 MBED_CONF_QUECTEL_BG96_PWR, 00149 MBED_CONF_QUECTEL_BG96_POLARITY, 00150 MBED_CONF_QUECTEL_BG96_RST); 00151 return &device; 00152 } 00153 #endif 00154 00155 void QUECTEL_BG96::urc_pdpdeact() 00156 { 00157 _at->lock(); 00158 _at->skip_param(); 00159 int cid = _at->read_int(); 00160 const nsapi_error_t err = _at->unlock_return_error(); 00161 00162 if (err != NSAPI_ERROR_OK ) { 00163 return; 00164 } 00165 send_disconnect_to_context(cid); 00166 } 00167 00168 void QUECTEL_BG96::press_button(DigitalOut &button, uint32_t timeout) 00169 { 00170 if (!button.is_connected()) { 00171 return; 00172 } 00173 button = _active_high; 00174 ThisThread::sleep_for(timeout); 00175 button = !_active_high; 00176 } 00177 00178 bool QUECTEL_BG96::wake_up(bool reset) 00179 { 00180 // check if modem is already ready 00181 _at->lock(); 00182 _at->flush(); 00183 _at->set_at_timeout(30); 00184 _at->cmd_start("AT"); 00185 _at->cmd_stop_read_resp(); 00186 nsapi_error_t err = _at->get_last_error(); 00187 _at->restore_at_timeout(); 00188 _at->unlock(); 00189 // modem is not responding, power it on 00190 if (err != NSAPI_ERROR_OK ) { 00191 if (!reset) { 00192 // BG96_Hardware_Design_V1.1 requires VBAT to be stable over 30 ms, that's handled above 00193 tr_info("Power on modem"); 00194 press_button(_pwr, 250); // BG96_Hardware_Design_V1.1 requires time 100 ms, but 250 ms seems to be more robust 00195 } else { 00196 tr_warn("Reset modem"); 00197 press_button(_rst, 150); // BG96_Hardware_Design_V1.1 requires RESET_N timeout at least 150 ms 00198 } 00199 _at->lock(); 00200 // According to BG96_Hardware_Design_V1.1 USB is active after 4.2s, but it seems to take over 5s 00201 _at->set_at_timeout(6000); 00202 _at->resp_start(); 00203 _at->set_stop_tag("RDY"); 00204 bool rdy = _at->consume_to_stop_tag(); 00205 _at->set_stop_tag(OK); 00206 _at->restore_at_timeout(); 00207 _at->unlock(); 00208 if (!rdy) { 00209 return false; 00210 } 00211 } 00212 00213 // sync to check that AT is really responsive and to clear garbage 00214 return _at->sync(500); 00215 }
Generated on Tue Jul 12 2022 13:54:46 by
1.7.2