Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,12 @@

#include "SARA4_PPP.h"
#include "SARA4_PPP_CellularNetwork.h"
#include "CellularUtil.h"
#include "CellularLog.h"

using namespace mbed;
using namespace events;
using namespace mbed_cellular_util;

static const intptr_t cellular_properties[AT_CellularDevice::PROPERTY_MAX] = {
AT_CellularNetwork::RegistrationModeLAC, // C_EREG
Expand Down Expand Up @@ -54,6 +57,122 @@ AT_CellularNetwork *SARA4_PPP::open_network_impl(ATHandler &at)
return new SARA4_PPP_CellularNetwork(at, *this);
}

nsapi_error_t SARA4_PPP::set_power_save_mode(int periodic_time, int active_time)
{
_at.lock();

if (periodic_time == 0 && active_time == 0) {
// disable PSM
_at.at_cmd_discard("+CPSMS", "=0");
} else {
const int PSMTimerBits = 5;

/**
Table 10.5.163a/3GPP TS 24.008: GPRS Timer 3 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:
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 <= 60 * ie_value_max) { // multiples of 1 minute
periodic_timer = periodic_time / 60;
strcpy(pt, "10100000");
} else {
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 <= 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");
}
}
}
}
}
}

uint_to_binary_str(periodic_timer, &pt[3], sizeof(pt) - 3, PSMTimerBits);
pt[8] = '\0';

/**
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:
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");
}
}

uint_to_binary_str(active_timer, &at[3], sizeof(at) - 3, PSMTimerBits);
at[8] = '\0';

// request for both GPRS and LTE

_at.at_cmd_discard("+CPSMS", "=1,,,", "%s%s", pt, at);

if (_at.get_last_error() != NSAPI_ERROR_OK) {
tr_warn("Power save mode not enabled!");
} else {
// network may not agree with power save options but
// that should be fine as timeout is not longer than requested
}
}

return _at.unlock_return_error();
}

#if MBED_CONF_SARA4_PPP_PROVIDE_DEFAULT
#include "drivers/BufferedSerial.h"
CellularDevice *CellularDevice::get_default_instance()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ class SARA4_PPP : public AT_CellularDevice {

public: // CellularDevice
virtual AT_CellularNetwork *open_network_impl(ATHandler &at);
virtual nsapi_error_t set_power_save_mode(int periodic_time, int active_time = 0);
};

} // namespace mbed
Expand Down