diff --git a/features/cellular/framework/targets/TELIT/ME910/TELIT_ME910.cpp b/features/cellular/framework/targets/TELIT/ME910/TELIT_ME910.cpp index 5406d18701..62039b4332 100644 --- a/features/cellular/framework/targets/TELIT/ME910/TELIT_ME910.cpp +++ b/features/cellular/framework/targets/TELIT/ME910/TELIT_ME910.cpp @@ -16,13 +16,31 @@ */ #include "TELIT_ME910.h" +#include "TELIT_ME910_CellularContext.h" #include "AT_CellularNetwork.h" -#include "gpio_api.h" -#include "platform/mbed_wait_api.h" +#include "PinNames.h" +#include "rtos/ThisThread.h" using namespace mbed; +using namespace rtos; using namespace events; +#if !defined(MBED_CONF_TELIT_ME910_PWR) +#define MBED_CONF_TELIT_ME910_PWR NC +#endif + +#if !defined(MBED_CONF_TELIT_ME910_TX) +#define MBED_CONF_TELIT_ME910_TX NC +#endif + +#if !defined(MBED_CONF_TELIT_ME910_RX) +#define MBED_CONF_TELIT_ME910_RX NC +#endif + +#if !defined(MBED_CONF_TELIT_ME910_POLARITY) +#define MBED_CONF_TELIT_ME910_POLARITY 1 // active high +#endif + static const intptr_t cellular_properties[AT_CellularBase::PROPERTY_MAX] = { AT_CellularNetwork::RegistrationModeLAC, // C_EREG AT_CellularNetwork::RegistrationModeLAC, // C_GREG @@ -41,11 +59,20 @@ static const intptr_t cellular_properties[AT_CellularBase::PROPERTY_MAX] = { 1, // PROPERTY_AT_CGEREP }; -TELIT_ME910::TELIT_ME910(FileHandle *fh) : AT_CellularDevice(fh) +TELIT_ME910::TELIT_ME910(FileHandle *fh, PinName pwr, bool active_high) + : AT_CellularDevice(fh), + _active_high(active_high), + _pwr_key(pwr, !_active_high) { AT_CellularBase::set_cellular_properties(cellular_properties); } +AT_CellularContext *TELIT_ME910::create_context_impl(ATHandler &at, const char *apn, bool cp_req, bool nonip_req) +{ + return new TELIT_ME910_CellularContext(at, this, apn, cp_req, nonip_req); +} + + uint16_t TELIT_ME910::get_send_delay() const { return DEFAULT_DELAY_BETWEEN_AT_COMMANDS; @@ -65,6 +92,99 @@ nsapi_error_t TELIT_ME910::init() #endif _at->cmd_stop_read_resp(); + // AT#QSS=1 + // Enable the Query SIM Status unsolicited indication in the ME. The format of the + // unsolicited indication is the following: + // #QSS: + // The ME informs at + // every SIM status change through the basic unsolicited indication where range is 0...1 + // values: + // - 0: SIM not inserted + // - 1: SIM inserted + _at->cmd_start("AT#QSS=1"); + _at->cmd_stop_read_resp(); + + // AT#PSNT=1 + // Set command enables unsolicited result code for packet service network type (PSNT) + // having the following format: + // #PSNT: + // values: + // - 0: GPRS network + // - 4: LTE network + // - 5: unknown or not registered + _at->cmd_start("AT#PSNT=1"); + _at->cmd_stop_read_resp(); + + // AT+CGEREP=2 + // Set command enables sending of unsolicited result codes in case of certain events + // occurring in the module or in the network. + // Current setting: buffer unsolicited result codes in the TA when TA-TE link is reserved (e.g. + // in on-line data mode) and flush them to the TE when TA-TE link becomes + // available; otherwise forward them directly to the TE. + _at->cmd_start("AT+CGEREP=2"); + _at->cmd_stop_read_resp(); + + // AT+CMER=2 + // Set command enables sending of unsolicited result codes from TA to TE in the case of + // indicator state changes. + // Current setting: buffer +CIEV Unsolicited Result Codes in the TA when TA-TE link is + // reserved (e.g. on-line data mode) and flush them to the TE after + // reservation; otherwise forward them directly to the TE + _at->cmd_start("AT+CMER=2"); + _at->cmd_stop_read_resp(); + + // AT+CREG=1 + // Set command enables the network registration unsolicited result code and selects one of + // the two available formats: + // short format: +CREG: + // long format: +CREG: [,,[,]] + // Current setting: enable the network registration unsolicited result code, and selects the + // short format + _at->cmd_start("AT+CREG=1"); + _at->cmd_stop_read_resp(); + + // AT+CGREG=1 + // Set command enables/disables the +CGREG: unsolicited result code, and selects one of the + // available formats: + // short format: + // +CGREG: + // long format: + // +CGREG:[,,[,,]] + // extra long format: + // +CGREG:[,[],[],[],[][,,[,[],[],[]]]] + // Current setting: enable the network registration unsolicited result code, and selects the + // short format + _at->cmd_start("AT+CGREG=1"); + _at->cmd_stop_read_resp(); + + // AT+CEREG=1 + // Set command enables the EPS network registration unsolicited result code (URC) in LTE, + // and selects one of the available formats: + // short format: +CEREG: + // long format: +CEREG: [,[],[],[]] + // , , and are reported by the command only if available. + // Current setting: enable the network registration unsolicited result code, and select the short + // format + _at->cmd_start("AT+CEREG=1"); + _at->cmd_stop_read_resp(); + + // AT+CMEE=2 + // Set command disables the use of result code +CME ERROR: as an indication of an + // error relating to the +Cxxx command issued. When enabled, device related errors cause the +CME + // ERROR: final result code instead of the default ERROR final result code. ERROR is returned + // normally when the error message is related to syntax, invalid parameters or DTE functionality. + // Current setting: enable and use verbose values + _at->cmd_start("AT+CMEE=2"); + _at->cmd_stop_read_resp(); + + // AT&W&P + // - AT&W: Execution command stores on profile the complete configuration of the device. If + // parameter is omitted, the command has the same behavior of AT&W0. + // - AT&P: Execution command defines which full profile will be loaded at startup. If parameter + // is omitted, the command has the same behavior as AT&P0 + _at->cmd_start("AT&W&P"); + _at->cmd_stop_read_resp(); + return _at->unlock_return_error(); } @@ -76,7 +196,9 @@ CellularDevice *CellularDevice::get_default_instance() #if defined (MBED_CONF_TELIT_ME910_RTS) && defined (MBED_CONF_TELIT_ME910_CTS) serial.set_flow_control(SerialBase::RTSCTS, MBED_CONF_TELIT_ME910_RTS, MBED_CONF_TELIT_ME910_CTS); #endif - static TELIT_ME910 device(&serial); + static TELIT_ME910 device(&serial, + MBED_CONF_TELIT_ME910_PWR, + MBED_CONF_TELIT_ME910_POLARITY); return &device; } #endif @@ -90,28 +212,20 @@ nsapi_error_t TELIT_ME910::hard_power_on() nsapi_error_t TELIT_ME910::soft_power_on() { - gpio_t gpio; - - gpio_init_out_ex(&gpio, MDMPWRON, 1); - wait_ms(500); - gpio_write(&gpio, 0); - wait_ms(5000); - gpio_write(&gpio, 1); - wait_ms(5000); + _pwr_key = _active_high; + ThisThread::sleep_for(500); + _pwr_key = !_active_high; + ThisThread::sleep_for(5000); + _pwr_key = _active_high; + ThisThread::sleep_for(5000); return NSAPI_ERROR_OK; } nsapi_error_t TELIT_ME910::hard_power_off() { - gpio_t gpio; - - gpio_init_out_ex(&gpio, MDMPWRON, 0); - /* keep the power line low for more than 10 seconds. - * If 3G_ON_OFF pin is kept low for more than a second, a controlled disconnect and shutdown takes - * place, Due to the network disconnect, shut-off can take up to 30 seconds. However, we wait for 10 - * seconds only */ - wait_ms(10 * 1000); + _pwr_key = !_active_high; + ThisThread::sleep_for(10000); return NSAPI_ERROR_OK; } diff --git a/features/cellular/framework/targets/TELIT/ME910/TELIT_ME910.h b/features/cellular/framework/targets/TELIT/ME910/TELIT_ME910.h index 849b809e2c..edbb5d6024 100644 --- a/features/cellular/framework/targets/TELIT/ME910/TELIT_ME910.h +++ b/features/cellular/framework/targets/TELIT/ME910/TELIT_ME910.h @@ -27,6 +27,7 @@ #endif #endif /* TARGET_FF_ARDUINO */ +#include "DigitalOut.h" #include "AT_CellularDevice.h" //the delay between sending AT commands @@ -36,15 +37,23 @@ namespace mbed { class TELIT_ME910 : public AT_CellularDevice { public: - TELIT_ME910(FileHandle *fh); + /** + * Constructs the Telit ME910 series driver. It is mandatory to provide + * a FileHandle object, the power pin and the polarity of the pin. + */ + TELIT_ME910(FileHandle *fh, PinName pwr, bool active_high); protected: // AT_CellularDevice virtual uint16_t get_send_delay() const; + virtual AT_CellularContext *create_context_impl(ATHandler &at, const char *apn, bool cp_req = false, bool nonip_req = false); virtual nsapi_error_t init(); virtual nsapi_error_t hard_power_on(); virtual nsapi_error_t hard_power_off(); virtual nsapi_error_t soft_power_on(); virtual nsapi_error_t soft_power_off(); +private: + bool _active_high; + DigitalOut _pwr_key; }; } // namespace mbed #endif /* CELLULAR_TARGETS_TELIT_ME910_TELIT_ME910_H_ */ diff --git a/features/cellular/framework/targets/TELIT/ME910/TELIT_ME910_CellularContext.cpp b/features/cellular/framework/targets/TELIT/ME910/TELIT_ME910_CellularContext.cpp new file mode 100644 index 0000000000..ff286f2f16 --- /dev/null +++ b/features/cellular/framework/targets/TELIT/ME910/TELIT_ME910_CellularContext.cpp @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2018, Arm Limited and affiliates. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "TELIT_ME910_CellularContext.h" +#include "CellularLog.h" + +#include "Semaphore.h" + +namespace mbed { + +TELIT_ME910_CellularContext::TELIT_ME910_CellularContext(ATHandler &at, CellularDevice *device, const char *apn, bool cp_req, bool nonip_req) : + AT_CellularContext(at, device, apn, cp_req, nonip_req) +{ +} + +TELIT_ME910_CellularContext::~TELIT_ME910_CellularContext() +{ +} + +bool TELIT_ME910_CellularContext::get_context() +{ + bool modem_supports_ipv6 = get_property(PROPERTY_IPV6_PDP_TYPE); + bool modem_supports_ipv4 = get_property(PROPERTY_IPV4_PDP_TYPE); + _at.cmd_start("AT+CGDCONT?"); + _at.cmd_stop(); + _at.resp_start("+CGDCONT:"); + _cid = -1; + int cid_max = 0; // needed when creating new context + char apn[MAX_ACCESSPOINT_NAME_LENGTH]; + int apn_len = 0; + + while (_at.info_resp()) { + int cid = _at.read_int(); + if (cid > cid_max) { + cid_max = cid; + } + char pdp_type_from_context[10]; + int pdp_type_len = _at.read_string(pdp_type_from_context, sizeof(pdp_type_from_context) - 1); + if (pdp_type_len > 0) { + apn_len = _at.read_string(apn, sizeof(apn) - 1); + if (apn_len >= 0) { + if (_apn && apn_len > 0 && (strcmp(apn, _apn) != 0)) { + continue; + } + + // APN matched -> Check PDP type + pdp_type_t pdp_type = string_to_pdp_type(pdp_type_from_context); + + // Accept exact matching PDP context type or dual PDP context for IPv4/IPv6 only modems + if (get_property(pdp_type_t_to_cellular_property(pdp_type)) || + ((pdp_type == IPV4V6_PDP_TYPE && (modem_supports_ipv4 || modem_supports_ipv6)) && !_nonip_req)) { + _pdp_type = pdp_type; + _cid = cid; + break; + } + } + } + } + + _at.resp_stop(); + if (_cid == -1) { // no suitable context was found so create a new one + if (!set_new_context(1)) { + return false; + } + } + + // save the apn + if (apn_len > 0 && !_apn) { + memcpy(_found_apn, apn, apn_len + 1); + } + + tr_info("Found PDP context %d", _cid); + return true; +} + +} /* namespace mbed */ diff --git a/features/cellular/framework/targets/TELIT/ME910/TELIT_ME910_CellularContext.h b/features/cellular/framework/targets/TELIT/ME910/TELIT_ME910_CellularContext.h new file mode 100644 index 0000000000..2f373ca792 --- /dev/null +++ b/features/cellular/framework/targets/TELIT/ME910/TELIT_ME910_CellularContext.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2018, Arm Limited and affiliates. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef TELIT_ME910_CELLULARCONTEXT_H_ +#define TELIT_ME910_CELLULARCONTEXT_H_ + +#include "AT_CellularContext.h" + +namespace mbed { + +class TELIT_ME910_CellularContext: public AT_CellularContext { +public: + TELIT_ME910_CellularContext(ATHandler &at, CellularDevice *device, const char *apn, bool cp_req = false, bool nonip_req = false); + virtual ~TELIT_ME910_CellularContext(); +protected: + virtual bool get_context(); +}; + +} /* namespace mbed */ + +#endif // TELIT_ME910_CELLULARCONTEXT_H_ diff --git a/features/cellular/framework/targets/TELIT/ME910/mbed_lib.json b/features/cellular/framework/targets/TELIT/ME910/mbed_lib.json index d3d6abc78f..e70e703354 100644 --- a/features/cellular/framework/targets/TELIT/ME910/mbed_lib.json +++ b/features/cellular/framework/targets/TELIT/ME910/mbed_lib.json @@ -17,6 +17,14 @@ "help": "CTS pin for serial connection", "value": null }, + "pwr": { + "help": "Power control pin", + "value": null + }, + "polarity": { + "help": "Pin polarity, 1 = Active high, 0 = Active low", + "value": null + }, "baudrate" : { "help": "Serial connection baud rate", "value": 115200