Base class for the ublox-xxx-cellular-xxx classes. Cannot be used standalone, only inherited by classes that do properly useful stuff. Or, to put it another way, if you are using any of the ublox-xxx-cellular-xxx classes, you will need this class also.
Dependents: example-ublox-cellular-interface example-ublox-cellular-driver-gen HelloMQTT example-ublox-cellular-interface_r410M ... more
Diff: UbloxCellularBase.cpp
- Revision:
- 34:d239824bfb8f
- Parent:
- 32:1fc4850f1253
- Child:
- 36:2f8ef6ac16dc
diff -r 1fc4850f1253 -r d239824bfb8f UbloxCellularBase.cpp
--- a/UbloxCellularBase.cpp Wed Sep 04 16:29:43 2019 +0500
+++ b/UbloxCellularBase.cpp Wed Oct 09 15:13:04 2019 +0500
@@ -25,6 +25,7 @@
#define tr_info(format, ...) debug_if(_debug_trace_on, format "\n", ## __VA_ARGS__)
#define tr_warn(format, ...) debug_if(_debug_trace_on, format "\n", ## __VA_ARGS__)
#define tr_error(format, ...) debug_if(_debug_trace_on, format "\n", ## __VA_ARGS__)
+#define tr_critical(format, ...) debug("\n" format "\n", ## __VA_ARGS__)
#endif
/* Array to convert the 3G qual number into a median EC_NO_LEV number.
@@ -493,15 +494,12 @@
_dev_info.reg_status_eps = EPS_NOT_REGISTERED_NOT_SEARCHING;
#ifdef TARGET_UBLOX_C030_R412M
_dev_info.modem_psm_state = AWAKE;
- _psm_status = false;
+ _psm_status = UNKNOWN;
_cb_param_psm_going_in = NULL;
_func_psm_going_in = NULL;
_cb_param_psm_coming_out = NULL;
_func_psm_coming_out = NULL;
#endif
-#ifdef TARGET_UBLOX_C030_R41XM
- _edrx_configured = false;
-#endif
}
// Destructor.
@@ -605,10 +603,6 @@
bool UbloxCellularBase::power_up()
{
bool success = false;
- int at_timeout;
- LOCK();
-
- at_timeout = _at_timeout; // Has to be inside LOCK()s
MBED_ASSERT(_at != NULL);
@@ -620,31 +614,28 @@
for (int retry_count = 0; !success && (retry_count < 20); retry_count++) {
//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.
- if ( (retry_count % 5) == 0) {
+ if ( (retry_count % 5) == 0) {
modem_power_up();
}
- wait_ms(500);
- // Modem tends to spit out noise during power up - don't confuse the parser
- _at->flush();
- at_set_timeout(1000);
- if (_at->send("AT")) {
- // C027 needs a delay here
- wait_ms(100);
- if (_at->recv("OK")) {
- success = true;
- }
- }
- at_set_timeout(at_timeout);
+ success = is_modem_ready();
}
- if (success) {
- // Set the final baud rate
- if (_at->send("AT+IPR=%d", _baud) && _at->recv("OK")) {
- // Need to wait for things to be sorted out on the modem side
- wait_ms(100);
- ((UARTSerial *)_fh)->set_baud(_baud);
- }
-
+ return success;
+}
+
+bool UbloxCellularBase::setup_modem()
+{
+ bool success = false;
+ LOCK();
+
+ MBED_ASSERT(_at != NULL);
+
+ // Set the final baud rate
+ if (_at->send("AT+IPR=%d", _baud) && _at->recv("OK")) {
+ // Need to wait for things to be sorted out on the modem side
+ wait_ms(100);
+ ((UARTSerial *)_fh)->set_baud(_baud);
+
// Turn off modem echoing and turn on verbose responses
success = _at->send("ATE0;+CMEE=2") && _at->recv("OK") &&
// The following commands are best sent separately
@@ -661,6 +652,43 @@
return success;
}
+bool UbloxCellularBase::is_modem_ready()
+{
+ bool success = false;
+ int at_timeout;
+ LOCK();
+
+ at_timeout = _at_timeout; // Has to be inside LOCK()s
+
+ MBED_ASSERT(_at != NULL);
+
+ _at->flush();
+ at_set_timeout(1000);
+ if (_at->send("AT")) {
+ // C027 needs a delay here
+ wait_ms(100);
+ if (_at->recv("OK")) {
+ success = true;
+ }
+ }
+ at_set_timeout(at_timeout);
+
+ UNLOCK();
+ return success;
+}
+
+bool UbloxCellularBase::initialize_modem()
+{
+ bool success = false;
+
+ if (power_up()) {
+ success = setup_modem();
+ } else {
+ tr_error("Preliminary modem setup failed.");
+ }
+ return success;
+}
+
// Power down modem via AT interface.
void UbloxCellularBase::power_down()
{
@@ -801,11 +829,11 @@
// Initialise the modem.
bool UbloxCellularBase::init(const char *pin)
{
- int x;
+ int x;
MBED_ASSERT(_at != NULL);
if (!_modem_initialised) {
- if (power_up()) {
+ if (initialize_modem()) {
tr_info("Modem Ready.");
if (pin != NULL) {
_pin = pin;
@@ -816,29 +844,48 @@
if (set_functionality_mode(FUNC_AIRPLANE)) {
#endif
if (initialise_sim_card()) {
+#ifdef TARGET_UBLOX_C030_R41XM
int mno_profile;
-
+ if (get_mno_profile(&mno_profile)) {
+#ifdef MBED_CONF_UBLOX_CELL_DEFAULT_MNO_PROFILE
+ if (set_mno_profile((MNOProfile)MBED_CONF_UBLOX_CELL_DEFAULT_MNO_PROFILE)) {
+ reboot_modem();
+ while(is_modem_ready() == false) {
+ wait_ms(1000);
+ }
+ setup_modem();
+ }
+#endif
+ if (mno_profile == SW_DEFAULT) {
+ tr_critical("!!CANNOT USE PROFILE 0(SW_DEFAULT). PLEASE SET AN APPROPRIATE MNO PROFILE!!");
+ _default_profile_is_set = true;
+ return false;
+ }
+ }
#ifdef TARGET_UBLOX_C030_R412M
- if (_psm_status == false) { //psm is not enabled by application yet so disable it at start-up
- set_power_saving_mode(0, 0);
+ int status = 0, periodic_time = 0, active_time = 0;
+ if (_psm_status == UNKNOWN) {
+ if (get_power_saving_mode(&status, &periodic_time, &active_time)) {
+ if (status) { //PSM is already enabled either by a previous run or MNO profile
+ tr_info("PSM is already enabled, periodic_time %d, active_time %d", periodic_time, active_time);
+ _psm_status = ENABLED;
+ if ( !(set_psm_urcs(true)) ) { //enable PSM URCs
+ tr_error("Modem does not support PSM URCs, disabling PSM");
+ set_power_saving_mode(0, 0);
+ } else if (!_func_psm_going_in){
+ tr_critical("!!PSM IS ENABLED, CALLBACK NOT ATTACHED. PLEASE REGISTER ONE!!");
+ }
+ }
+ }
+ } else if (_psm_status == ENABLED && !_func_psm_going_in){
+ tr_critical("!!PSM IS ENABLED, CALLBACK NOT ATTACHED. PLEASE REGISTER ONE!!");
}
+#elif TARGET_UBLOX_C030_R410M
+ disable_psm(); //PSM is currently not supported by driver for R410M due to lack of URCs
#endif
-#ifdef TARGET_UBLOX_C030_R41XM
if (_at->is_idle_mode_enabled() == false) {
set_idle_mode(false); //disable idle mode at start up
}
- if(_edrx_configured == false) {
- // A special form of the command can be given as +CEDRXS=3.
- // In this form, eDRX will be disabled and data for all parameters in the command +CEDRXS will be removed or,
- // if available, set to the manufacturer specific default values.
- set_receive_period(3,UbloxCellularBase::EDRXGSM_A_Gb_mode);
- set_receive_period(3,UbloxCellularBase::EDRXEUTRAN_WB_S1_mode);
- set_receive_period(3,UbloxCellularBase::EDRXEUTRAN_NB_S1_mode);
- }
- get_receive_period();
-
- if (get_mno_profile(&mno_profile))
- tr_info("Current MNO profile is: %d", mno_profile);
#endif
if (set_device_identity(&_dev_info.dev) && // Set up device identity
device_init(_dev_info.dev)) {// Initialise this device
@@ -933,7 +980,7 @@
// This should return quickly but sometimes the status field is not returned
// so make the timeout short
at_set_timeout(1000);
- if (_at->send("AT+COPS?") && _at->recv("+COPS: %*d,%*d,\"%*[^\"]\",%d\n", &status)) {
+ if (_at->send("AT+COPS?") && _at->recv("+COPS: %*d,%*d,\"%*[^\"]\",%d\nOK\n", &status)) {
set_rat(status);
}
at_set_timeout(at_timeout);
@@ -1064,10 +1111,10 @@
success = _at->send("AT+CGSN") && _at->recv("%15[^\n]\nOK\n", _dev_info.imei);
tr_info("DevInfo: IMEI=%s", _dev_info.imei);
- if (success) {
- memcpy(imei_to_send,_dev_info.imei,size);
- imei_to_send[size-1] = '\0';
- }
+ if (success) {
+ memcpy(imei_to_send,_dev_info.imei,size);
+ imei_to_send[size-1] = '\0';
+ }
UNLOCK();
return success;
@@ -1164,6 +1211,13 @@
//RAT should be set in a detached state (AT+COPS=2)
bool UbloxCellularBase::set_modem_rat(RAT selected_rat, RAT preferred_rat, RAT second_preferred_rat)
{
+#ifdef TARGET_UBLOX_C030_R41XM
+ if (_default_profile_is_set == true) {
+ tr_critical("!!CANNOT USE PROFILE 0(SW_DEFAULT). PLEASE SET AN APPROPRIATE MNO PROFILE!!");
+ return false;
+ }
+#endif
+
bool success = false;
char command[16] = {0x00};
@@ -1197,6 +1251,13 @@
bool UbloxCellularBase::get_modem_rat(int *selected_rat, int *preferred_rat, int *second_preferred_rat)
{
+#ifdef TARGET_UBLOX_C030_R41XM
+ if (_default_profile_is_set == true) {
+ tr_critical("!!CANNOT USE PROFILE 0(SW_DEFAULT). PLEASE SET AN APPROPRIATE MNO PROFILE!!");
+ return false;
+ }
+#endif
+
bool success = false;
char buf[24] = {0x00};
@@ -1283,7 +1344,7 @@
bool return_val = false;
int current_profile;
MNOProfile arr[MAX_NUM_PROFILES] = { SW_DEFAULT, SIM_ICCID, ATT, TMO, VODAFONE, DT, STANDARD_EU
-#ifdef TARGET_UBLOX_C030_R410M
+#ifdef TARGET_UBLOX_C030_R410M
, VERIZON, TELSTRA, CT, SPRINT, TELUS
#endif
};
@@ -1305,12 +1366,18 @@
LOCK();
if (_at->send("AT+UMNOPROF=%d", current_profile) && _at->recv("OK")) {
- tr_error("temporary MNO profile set: %d", current_profile);
+ tr_info("temporary MNO profile set: %d", current_profile);
}
UNLOCK();
}
LOCK();
if (_at->send("AT+UMNOPROF=%d", profile) && _at->recv("OK")) {
+ if (profile == SW_DEFAULT) {
+ tr_critical("!!CANNOT USE PROFILE 0(SW_DEFAULT). PLEASE SET AN APPROPRIATE MNO PROFILE!!");
+ _default_profile_is_set = true;
+ } else {
+ _default_profile_is_set = false;
+ }
return_val = true;
} else {
tr_error("unable to set user specified profile");
@@ -1347,7 +1414,7 @@
bool UbloxCellularBase::set_idle_mode(bool enable)
{
#ifdef TARGET_UBLOX_C030_R412M
- if (_psm_status == true && enable == true) {
+ if (_psm_status == ENABLED && enable == true) {
return false;
}
#endif
@@ -1402,7 +1469,6 @@
LOCK();
if (_at->send("AT+CEDRXS=%d,%d,\"%s\"", mode, act_type, edrx) && _at->recv("OK")) {
- _edrx_configured = true;
status = 0;
}
else {
@@ -1514,6 +1580,11 @@
bool UbloxCellularBase::set_band_bitmask(RAT rat, uint64_t bitmask) {
+ if (_default_profile_is_set == true) {
+ tr_critical("!!CANNOT USE PROFILE 0(SW_DEFAULT). PLEASE SET AN APPROPRIATE MNO PROFILE!!");
+ return false;
+ }
+
bool status = false;
UBandmaskRAT eBandMastRat;
@@ -1541,8 +1612,12 @@
return status;
}
-
-bool UbloxCellularBase::get_band_bitmask(uint64_t *m1_bitmask, uint64_t *nb1_bitmask) {
+bool UbloxCellularBase::get_band_bitmask(uint64_t *m1_bitmask, uint64_t *nb1_bitmask)
+{
+ if (_default_profile_is_set == true) {
+ tr_critical("!!CANNOT USE PROFILE 0(SW_DEFAULT). PLEASE SET AN APPROPRIATE MNO PROFILE!!");
+ return false;
+ }
bool status = false;
int eBandMastRat0, eBandMastRat1;
@@ -1557,8 +1632,22 @@
return status;
}
+
+bool UbloxCellularBase::disable_psm()
+{
+ bool return_value = false;
+
+ LOCK();
+ if (_at->send("AT+CPSMS=0") && _at->recv("OK")) {
+ return_value = true;
+ }
+ UNLOCK();
+
+ return return_value;
+}
#endif //TARGET_UBLOX_C030_R41XM
+
#ifdef TARGET_UBLOX_C030_R412M
bool UbloxCellularBase::get_power_saving_mode(int *status, int *periodic_time, int *active_time)
{
@@ -1573,7 +1662,7 @@
LOCK();
//+UCPSMS:1,,,"01000011","01000011"
- if (_at->send("AT+UCPSMS?") && _at->recv("+UCPSMS:%d,,,\"%8c\",\"%8c\"\n", status, pt_encoded, at_encoded)) {
+ if (_at->send("AT+UCPSMS?") && _at->recv("+UCPSMS:%d,,,\"%8c\",\"%8c\"\nOK\n", status, pt_encoded, at_encoded)) {
if (*status == true) {
//PSM is enabled, decode the timer values, periodic TAU first
value = (pt_encoded[7]- '0');
@@ -1671,6 +1760,7 @@
bool UbloxCellularBase::set_power_saving_mode(int periodic_time, int active_time)
{
+
if (_at->is_idle_mode_enabled() == true && periodic_time != 0 && active_time != 0 ) {
return false;
}
@@ -1680,133 +1770,129 @@
int at_timeout = _at_timeout;
at_set_timeout(10000); //AT+CPSMS has response time of < 10s
- //check if modem supports PSM URCs
- if (_at->send("AT+UPSMR?") && _at->recv("OK")) {
- if (periodic_time == 0 && active_time == 0) {
- // disable PSM
- if (_at->send("AT+CPSMS=0") && _at->recv("OK")) {
- if (_at->send("AT+UPSMR=0") && _at->recv("OK")) {//disable the URC
- //de-register the callback
- detach_cb_psm_going_in();
- detach_cb_psm_coming_out();
- _psm_status = false;
- return_val = true;
- }
- }
- } else { //PSM string encoding code borrowed from AT_CellularPower.cpp
- /**
- Table 10.5.163a/3GPP TS 24.008: GPRS Timer 3 information element
+ if (periodic_time == 0 && active_time == 0) {
+ // disable PSM
+ if (_at->send("AT+CPSMS=0") && _at->recv("OK")) {
+ set_psm_urcs(false); //disable the URC
+ _psm_status = DISABLED;
+ return_val = true;
+ }
+ } else if (_at->send("AT+UPSMR?") && _at->recv("OK")) { //PSM string encoding code borrowed from AT_CellularPower.cpp
+ /**
+ Table 10.5.163a/3GPP TS 24.008: GPRS Timer 3 information element
- Bits 5 to 1 represent the binary coded timer value.
+ Bits 5 to 1 represent the binary coded timer value.
- Bits 6 to 8 defines the timer value unit for the GPRS timer as follows:
- 8 7 6
- 0 0 0 value is incremented in multiples of 10 minutes
- 0 0 1 value is incremented in multiples of 1 hour
- 0 1 0 value is incremented in multiples of 10 hours
- 0 1 1 value is incremented in multiples of 2 seconds
- 1 0 0 value is incremented in multiples of 30 seconds
- 1 0 1 value is incremented in multiples of 1 minute
- 1 1 0 value is incremented in multiples of 320 hours (NOTE 1)
- 1 1 1 value indicates that the timer is deactivated (NOTE 2).
- */
- char pt[8+1];// timer value encoded as 3GPP IE
- const int ie_value_max = 0x1f;
- uint32_t periodic_timer = 0;
- if (periodic_time <= 2*ie_value_max) { // multiples of 2 seconds
- periodic_timer = periodic_time/2;
- strcpy(pt, "01100000");
+ Bits 6 to 8 defines the timer value unit for the GPRS timer as follows:
+ 8 7 6
+ 0 0 0 value is incremented in multiples of 10 minutes
+ 0 0 1 value is incremented in multiples of 1 hour
+ 0 1 0 value is incremented in multiples of 10 hours
+ 0 1 1 value is incremented in multiples of 2 seconds
+ 1 0 0 value is incremented in multiples of 30 seconds
+ 1 0 1 value is incremented in multiples of 1 minute
+ 1 1 0 value is incremented in multiples of 320 hours (NOTE 1)
+ 1 1 1 value indicates that the timer is deactivated (NOTE 2).
+ */
+ char pt[8+1];// timer value encoded as 3GPP IE
+ const int ie_value_max = 0x1f;
+ uint32_t periodic_timer = 0;
+ if (periodic_time <= 2*ie_value_max) { // multiples of 2 seconds
+ periodic_timer = periodic_time/2;
+ strcpy(pt, "01100000");
+ } else {
+ if (periodic_time <= 30*ie_value_max) { // multiples of 30 seconds
+ periodic_timer = periodic_time/30;
+ strcpy(pt, "10000000");
} else {
- if (periodic_time <= 30*ie_value_max) { // multiples of 30 seconds
- periodic_timer = periodic_time/30;
- strcpy(pt, "10000000");
+ if (periodic_time <= 60*ie_value_max) { // multiples of 1 minute
+ periodic_timer = periodic_time/60;
+ strcpy(pt, "10100000");
} else {
- if (periodic_time <= 60*ie_value_max) { // multiples of 1 minute
- periodic_timer = periodic_time/60;
- strcpy(pt, "10100000");
+ if (periodic_time <= 10*60*ie_value_max) { // multiples of 10 minutes
+ periodic_timer = periodic_time/(10*60);
+ strcpy(pt, "00000000");
} else {
- if (periodic_time <= 10*60*ie_value_max) { // multiples of 10 minutes
- periodic_timer = periodic_time/(10*60);
- strcpy(pt, "00000000");
+ if (periodic_time <= 60*60*ie_value_max) { // multiples of 1 hour
+ periodic_timer = periodic_time/(60*60);
+ strcpy(pt, "00100000");
} else {
- if (periodic_time <= 60*60*ie_value_max) { // multiples of 1 hour
- periodic_timer = periodic_time/(60*60);
- strcpy(pt, "00100000");
- } else {
- if (periodic_time <= 10*60*60*ie_value_max) { // multiples of 10 hours
- periodic_timer = periodic_time/(10*60*60);
- strcpy(pt, "01000000");
- } else { // multiples of 320 hours
- int t = periodic_time / (320*60*60);
- if (t > ie_value_max) {
- t = ie_value_max;
- }
- periodic_timer = t;
- strcpy(pt, "11000000");
+ if (periodic_time <= 10*60*60*ie_value_max) { // multiples of 10 hours
+ periodic_timer = periodic_time/(10*60*60);
+ strcpy(pt, "01000000");
+ } else { // multiples of 320 hours
+ int t = periodic_time / (320*60*60);
+ if (t > ie_value_max) {
+ t = ie_value_max;
}
+ periodic_timer = t;
+ strcpy(pt, "11000000");
}
}
}
}
}
+ }
- uint_to_binary_str(periodic_timer, &pt[3], sizeof(pt)-3, 5);
- pt[8] = '\0';
+ uint_to_binary_str(periodic_timer, &pt[3], sizeof(pt)-3, 5);
+ pt[8] = '\0';
+
+ /**
+ Table 10.5.172/3GPP TS 24.008: GPRS Timer information element
- /**
- Table 10.5.172/3GPP TS 24.008: GPRS Timer information element
+ Bits 5 to 1 represent the binary coded timer value.
+
+ Bits 6 to 8 defines the timer value unit for the GPRS timer as follows:
- Bits 5 to 1 represent the binary coded timer value.
-
- Bits 6 to 8 defines the timer value unit for the GPRS timer as follows:
+ 8 7 6
+ 0 0 0 value is incremented in multiples of 2 seconds
+ 0 0 1 value is incremented in multiples of 1 minute
+ 0 1 0 value is incremented in multiples of decihours
+ 1 1 1 value indicates that the timer is deactivated.
- 8 7 6
- 0 0 0 value is incremented in multiples of 2 seconds
- 0 0 1 value is incremented in multiples of 1 minute
- 0 1 0 value is incremented in multiples of decihours
- 1 1 1 value indicates that the timer is deactivated.
+ Other values shall be interpreted as multiples of 1 minute in this version of the protocol.
+ */
+ char at[8+1];
+ uint32_t active_timer; // timer value encoded as 3GPP IE
+ if (active_time <= 2*ie_value_max) { // multiples of 2 seconds
+ active_timer = active_time/2;
+ strcpy(at, "00000000");
+ } else {
+ if (active_time <= 60*ie_value_max) { // multiples of 1 minute
+ active_timer = (1<<5) | (active_time/60);
+ strcpy(at, "00100000");
+ } else { // multiples of decihours
+ int t = active_time / (6*60);
+ if (t > ie_value_max) {
+ t = ie_value_max;
+ }
+ active_timer = t;
+ strcpy(at, "01000000");
+ }
+ }
- Other values shall be interpreted as multiples of 1 minute in this version of the protocol.
- */
- char at[8+1];
- uint32_t active_timer; // timer value encoded as 3GPP IE
- if (active_time <= 2*ie_value_max) { // multiples of 2 seconds
- active_timer = active_time/2;
- strcpy(at, "00000000");
+ uint_to_binary_str(active_timer, &at[3], sizeof(at)-3, 5);
+ at[8] = '\0';
+
+ if (_at->send("AT+CPSMS=1,,,\"%s\",\"%s\"", pt, at) && _at->recv("OK")) {
+ if (set_psm_urcs(true)) {//enable the PSM URC
+ tr_info("PSM enabled successfully!");
+ _psm_status = ENABLED;
+ return_val = true;
} else {
- if (active_time <= 60*ie_value_max) { // multiples of 1 minute
- active_timer = (1<<5) | (active_time/60);
- strcpy(at, "00100000");
- } else { // multiples of decihours
- int t = active_time / (6*60);
- if (t > ie_value_max) {
- t = ie_value_max;
- }
- active_timer = t;
- strcpy(at, "01000000");
- }
- }
-
- uint_to_binary_str(active_timer, &at[3], sizeof(at)-3, 5);
- at[8] = '\0';
-
- if (_at->send("AT+CPSMS=1,,,\"%s\",\"%s\"", pt, at) && _at->recv("OK")) {
- if (_at->send("AT+UPSMR=1") && _at->recv("OK")) {//enable the PSM URC
- tr_info("PSM enabled successfully!");
- _psm_status = true;
- return_val = true;
- } else {
- tr_error("PSM URCs not supported");
- return_val = false;
- }
- } else {
- tr_error("+CPSMS command failed");
+ tr_error("Error enabling PSM URCs, PSM not enabled");
+ _at->send("AT+CPSMS=0");
+ _at->recv("OK");
return_val = false;
}
+ } else {
+ tr_error("+CPSMS command failed");
+ return_val = false;
}
} else {
tr_error("PSM URCs not supported by this version of modem");
}
+
at_set_timeout(at_timeout);
UNLOCK();
return return_val;
@@ -1835,6 +1921,22 @@
UNLOCK();
}
+
+bool UbloxCellularBase::set_psm_urcs(bool enable)
+{
+
+ bool success = false;
+ LOCK();
+
+ MBED_ASSERT(_at != NULL);
+
+ if (_at->send("AT+UPSMR=%d", enable ? 1 : 0) && _at->recv("OK")) {
+ success = true;
+ }
+
+ UNLOCK();
+ return success;
+}
#endif
// End of File
u-blox