Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,17 @@ class CellularDevice {
*/
virtual nsapi_error_t soft_power_off() = 0;

/** Resets the modem via AT command
*
* @remark CellularStateMachine disconnect or destruct does not reset the modem,
* but you need to do that yourself.
*
* @pre You must call shutdown to prepare the modem for reset.
*
* @return NSAPI_ERROR_OK on success
*/
virtual nsapi_error_t soft_reset() = 0;

/** Open the SIM card by setting the pin code for SIM.
*
* @param sim_pin PIN for the SIM card
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ class AT_CellularDevice : public CellularDevice {

virtual nsapi_error_t soft_power_off();

virtual nsapi_error_t soft_reset();

virtual nsapi_error_t set_pin(const char *sim_pin);

virtual nsapi_error_t get_sim_state(SimState &state);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ class GEMALTO_CINTERION : public AT_CellularDevice {

protected:
virtual nsapi_error_t init();
virtual nsapi_error_t shutdown();
virtual nsapi_error_t soft_power_off();
virtual nsapi_error_t soft_reset();

private:
static Module _module;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ class GEMALTO_CINTERION_CellularStack : public AT_CellularStack {
void stopGNSS();
void PSMEnable();
void PSMDisable();
int ping(const char *host, int ttl);

protected:

Expand Down
113 changes: 85 additions & 28 deletions libraries/GSM/src/GSM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,28 @@ mbed::CellularDevice *mbed::CellularDevice::get_default_instance()

int arduino::GSMClass::begin(const char* pin, const char* apn, const char* username, const char* password, RadioAccessTechnologyType rat, uint32_t band, bool restart) {

if (restart || isCmuxEnable()) {
reset();
/* Assume module is powered ON. Uncomment this line is you are using
* Edge Control without Arduino_ConnectionHandler
* #if defined (ARDUINO_EDGE_CONTROL)
* pinMode(ON_MKR2, OUTPUT);
* digitalWrite(ON_MKR2, HIGH);
* #endif
*/

/* Ensure module is not under reset */
pinMode(MBED_CONF_GEMALTO_CINTERION_RST, OUTPUT);
digitalWrite(MBED_CONF_GEMALTO_CINTERION_RST, LOW);

/* Reset module if needed */
const bool emergencyReset = restart || isCmuxEnable();
DEBUG_INFO("Emergency reset %s", emergencyReset ? "enabled" : "disabled");
if (emergencyReset) {
hardwareReset();
}

/* Create rising edge on pin ON */
on();

if (!_context) {
_context = mbed::CellularContext::get_default_instance();
}
Expand All @@ -59,20 +77,18 @@ int arduino::GSMClass::begin(const char* pin, const char* apn, const char* usern
return 0;
}

pinMode(MBED_CONF_GEMALTO_CINTERION_ON, INPUT_PULLDOWN);

#if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_PORTENTA_H7_M4)
/* This is needed to wakeup module if hw flow control is enabled */
static mbed::DigitalOut rts(MBED_CONF_GEMALTO_CINTERION_RTS, 0);
#endif

_device = _context->get_device();
_device->modem_debug_on(_at_debug);

if (!isReady()) {
DEBUG_ERROR("Cellular device not ready");
return 0;
}

DEBUG_INFO("CMUX %s", _cmuxGSMenable ? "enabled" : "disabled");
_device->set_cmux_status_flag(_cmuxGSMenable);
_device->set_retry_timeout_array(_retry_timeout, sizeof(_retry_timeout) / sizeof(_retry_timeout[0]));
_device->set_timeout(_timeout);
_device->attach(mbed::callback(this, &GSMClass::onStatusChange));
_device->init();

Expand Down Expand Up @@ -106,6 +122,10 @@ int arduino::GSMClass::begin(const char* pin, const char* apn, const char* usern
return connect_status == NSAPI_ERROR_OK ? 1 : 0;
}

void arduino::GSMClass::setTimeout(unsigned long timeout) {
_timeout = timeout;
}

void arduino::GSMClass::enableCmux() {
_cmuxGSMenable = true;
}
Expand All @@ -115,13 +135,62 @@ bool arduino::GSMClass::isCmuxEnable() {
}

void arduino::GSMClass::end() {
if(_device) {
_device->shutdown();
}
}

void arduino::GSMClass::reset() {
if(_device) {
_device->soft_reset();
}
}

void arduino::GSMClass::off() {
if(_device) {
_device->soft_power_off();
}
}

int arduino::GSMClass::ping(const char* hostname, int ttl) {

mbed::GEMALTO_CINTERION_CellularStack* stack = (mbed::GEMALTO_CINTERION_CellularStack*)_context->get_stack();
if (!stack) {
return -1;
}
return stack->ping(hostname, ttl);
}

int arduino::GSMClass::ping(const String &hostname, int ttl)
{
return ping(hostname.c_str(), ttl);
}

int arduino::GSMClass::ping(IPAddress ip, int ttl)
{
String host;
host.reserve(15);

host += ip[0];
host += '.';
host += ip[1];
host += '.';
host += ip[2];
host += '.';
host += ip[3];

return ping(host, ttl);
}

int arduino::GSMClass::disconnect() {
if (_context) {
if (!_context) {
return 0;
}

if (_context->is_connected()) {
return _context->disconnect();
}

return 0;
}

Expand Down Expand Up @@ -158,34 +227,22 @@ NetworkInterface* arduino::GSMClass::getNetwork() {
return _context;
}

void arduino::GSMClass::reset() {
void arduino::GSMClass::hardwareReset() {
/* Reset logic is inverted */
pinMode(MBED_CONF_GEMALTO_CINTERION_RST, OUTPUT);
digitalWrite(MBED_CONF_GEMALTO_CINTERION_RST, HIGH);
delay(800);
digitalWrite(MBED_CONF_GEMALTO_CINTERION_RST, LOW);
}

void arduino::GSMClass::on() {
/* Module needs a rising edge to power on */
pinMode(MBED_CONF_GEMALTO_CINTERION_ON, OUTPUT);
digitalWrite(MBED_CONF_GEMALTO_CINTERION_ON, LOW);
delay(1);
digitalWrite(MBED_CONF_GEMALTO_CINTERION_ON, HIGH);
delay(1);
}

bool arduino::GSMClass::isReady(const int timeout) {
if (!_device) {
DEBUG_ERROR("No device found");
return false;
}

const unsigned int start = millis();
while (_device->is_ready() != NSAPI_ERROR_OK) {

if (millis() - start > timeout) {
DEBUG_WARNING("Timeout waiting device ready");
return false;
}
delay(100);
}
return true;
}

arduino::GSMClass GSM;
63 changes: 42 additions & 21 deletions libraries/GSM/src/GSM.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,30 +75,47 @@ class GSMClass : public MbedSocketClass {
}
}

/* Start GSM connection.
* Configure the credentials into the device.
*
* param pin: Pointer to the pin string.
* param apn: Pointer to the apn string.
* param username: Pointer to the username string.
* param password: Pointer to the password string.
* param rat: Radio Access Technology.
*
* return: 0 in case of success, negative number in case of failure
*/
int begin(const char* pin, const char* apn, const char* username, const char* password, RadioAccessTechnologyType rat = CATNB, uint32_t band = BAND_20, bool restart = true);
/*
* Start GSM connection. Configure the credentials into the device.
*
* param pin: Pointer to the pin string.
* param apn: Pointer to the apn string.
* param username: Pointer to the username string.
* param password: Pointer to the password string.
* param rat: Radio Access Technology.
*
* return: 0 in case of success, negative number in case of failure
*/
int begin(const char* pin, const char* apn, const char* username, const char* password, RadioAccessTechnologyType rat = CATNB, uint32_t band = BAND_20, bool restart = false);

/*
* Disconnect from the network
*
* return: one value of wl_status_t enum
*/
* Disconnect from the network
*
* return: one value of wl_status_t enum
*/
int disconnect(void);

/*
* Reset internal state machine in order to be ready to reconnect again.
*/
void end(void);

unsigned long getTime();
/*
* Send AT+CFUN=1,1 command to trigger a software reset. To be called only after end();
*/
void reset();

/*
* Send AT^SMSO="fast command to power off the modem. To be called only after end();
*/
void off();

/*
* Change cellular state timeouts. Needs to be called before GSM.begin()
*/
void setTimeout(unsigned long timeout);

unsigned long getTime();
unsigned long getLocalTime();

bool setTime(unsigned long const epoch, int const timezone = 0);
Expand All @@ -108,6 +125,9 @@ class GSMClass : public MbedSocketClass {
void trace(Stream& stream);
void setTraceLevel(int trace_level, bool timestamp = false, bool at_trace = false);
#endif
int ping(const char* hostname, int ttl = 5000);
int ping(const String& hostname, int ttl = 5000);
int ping(IPAddress host, int ttl = 5000);
bool isConnected();

friend class GSMClient;
Expand All @@ -127,11 +147,12 @@ class GSMClass : public MbedSocketClass {
mbed::CellularContext* _context = nullptr;
mbed::CellularDevice* _device = nullptr;
bool _at_debug = false;
unsigned long _timeout = 1000;

/* Internal cellular state machine retries. Values are in seconds.
* This array also defines the maximum number of retries to 6
* This array also defines the maximum number of retries to CELLULAR_RETRY_ARRAY_SIZE
*/
const uint16_t _retry_timeout[6] = {1, 2, 4, 8, 16, 32};
const uint16_t _retry_timeout[CELLULAR_RETRY_ARRAY_SIZE] = {1, 2, 4, 8, 8, 8, 8, 8, 8, 8};

static constexpr int RSSI_UNKNOWN = 99;
static const char * const sim_state_str[];
Expand All @@ -146,8 +167,8 @@ class GSMClass : public MbedSocketClass {
static const char * getRegistrationStateString(const mbed::CellularNetwork::RegistrationStatus state);
void onStatusChange(nsapi_event_t ev, intptr_t in);

void reset();
bool isReady(const int timeout = 5000);
void hardwareReset();
void on();
};

}
Expand Down
20 changes: 20 additions & 0 deletions libraries/GSM/src/GSMClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,29 @@
namespace arduino {

class GSMClient : public AClient {
private:
NetworkInterface *getNetwork() {
return GSM.getNetwork();
}

public:
size_t write(uint8_t b) {
int ret = 0;
do {
ret = client->write(b);
delay(0);
} while (ret == 0 && status());
return ret;
}

size_t write(const uint8_t *buf, size_t size) {
int ret = 0;
do {
ret = client->write(buf, size);
delay(0);
} while (ret == 0 && status());
return ret;
}
};

}
Expand Down
19 changes: 19 additions & 0 deletions libraries/GSM/src/GSMSSLClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,25 @@ class GSMSSLClient : public arduino::ASslClient {
NetworkInterface *getNetwork() {
return GSM.getNetwork();
}

public:
size_t write(uint8_t b) {
int ret = 0;
do {
ret = client->write(b);
delay(0);
} while (ret == 0 && status());
return ret;
}

size_t write(const uint8_t *buf, size_t size) {
int ret = 0;
do {
ret = client->write(buf, size);
delay(0);
} while (ret == 0 && status());
return ret;
}
};

}
Expand Down
Loading