Daniel Vizcaya / Mbed OS 04_RTOS_Embebidos
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers AT_CellularPower.cpp Source File

AT_CellularPower.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 "AT_CellularPower.h"
00019 #include "CellularUtil.h"
00020 #include "CellularLog.h"
00021 #include "CellularTargets.h"
00022 #include "nsapi_types.h"
00023 
00024 static const int PSMTimerBits = 5;
00025 
00026 using namespace mbed_cellular_util;
00027 using namespace mbed;
00028 
00029 AT_CellularPower::AT_CellularPower(ATHandler &at) : AT_CellularBase(at)
00030 {
00031 }
00032 
00033 AT_CellularPower::~AT_CellularPower()
00034 {
00035 }
00036 
00037 nsapi_error_t AT_CellularPower::on()
00038 {
00039     return NSAPI_ERROR_UNSUPPORTED ;
00040 }
00041 
00042 nsapi_error_t AT_CellularPower::off()
00043 {
00044     return NSAPI_ERROR_UNSUPPORTED ;
00045 }
00046 
00047 nsapi_error_t AT_CellularPower::set_at_mode()
00048 {
00049     _at.lock();
00050     _at.flush();
00051     _at.cmd_start("ATE0"); // echo off
00052     _at.cmd_stop();
00053     _at.resp_start();
00054     _at.resp_stop();
00055 
00056     _at.cmd_start("AT+CMEE=1"); // verbose responses
00057     _at.cmd_stop();
00058     _at.resp_start();
00059     _at.resp_stop();
00060     return _at.unlock_return_error();
00061 }
00062 
00063 nsapi_error_t AT_CellularPower::set_power_level(int func_level)
00064 {
00065     _at.lock();
00066     _at.cmd_start("AT+CFUN=");
00067     _at.write_int(func_level);
00068     _at.cmd_stop();
00069     _at.resp_start();
00070     _at.resp_stop();
00071     return _at.unlock_return_error();
00072 }
00073 
00074 nsapi_error_t AT_CellularPower::reset()
00075 {
00076     _at.lock();
00077     _at.cmd_start("AT+CFUN=");// reset to full power levels
00078     _at.write_int(1);
00079     _at.write_int(1);
00080     _at.cmd_stop();
00081     _at.resp_start();
00082     _at.resp_stop();
00083     return _at.unlock_return_error();
00084 }
00085 
00086 nsapi_error_t AT_CellularPower::opt_power_save_mode(int periodic_time, int active_time)
00087 {
00088     _at.lock();
00089 
00090     if (periodic_time == 0 && active_time == 0) {
00091         // disable PSM
00092         _at.cmd_start("AT+CPSMS=");
00093         _at.write_int(0);
00094         _at.cmd_stop();
00095         _at.resp_start();
00096         _at.resp_stop();
00097     } else {
00098         /**
00099             Table 10.5.163a/3GPP TS 24.008: GPRS Timer 3 information element
00100 
00101             Bits 5 to 1 represent the binary coded timer value.
00102 
00103             Bits 6 to 8 defines the timer value unit for the GPRS timer as follows:
00104             8 7 6
00105             0 0 0 value is incremented in multiples of 10 minutes
00106             0 0 1 value is incremented in multiples of 1 hour
00107             0 1 0 value is incremented in multiples of 10 hours
00108             0 1 1 value is incremented in multiples of 2 seconds
00109             1 0 0 value is incremented in multiples of 30 seconds
00110             1 0 1 value is incremented in multiples of 1 minute
00111             1 1 0 value is incremented in multiples of 320 hours (NOTE 1)
00112             1 1 1 value indicates that the timer is deactivated (NOTE 2).
00113          */
00114         char pt[8+1];// timer value encoded as 3GPP IE
00115         const int ie_value_max = 0x1f;
00116         uint32_t periodic_timer = 0;
00117         if (periodic_time <= 2*ie_value_max) { // multiples of 2 seconds
00118             periodic_timer = periodic_time/2;
00119             strcpy(pt, "01100000");
00120         } else {
00121             if (periodic_time <= 30*ie_value_max) { // multiples of 30 seconds
00122                 periodic_timer = periodic_time/30;
00123                 strcpy(pt, "10000000");
00124             } else {
00125                 if (periodic_time <= 60*ie_value_max) { // multiples of 1 minute
00126                     periodic_timer = periodic_time/60;
00127                     strcpy(pt, "10100000");
00128                 } else {
00129                     if (periodic_time <= 10*60*ie_value_max) { // multiples of 10 minutes
00130                         periodic_timer = periodic_time/(10*60);
00131                         strcpy(pt, "00000000");
00132                     } else {
00133                         if (periodic_time <= 60*60*ie_value_max) { // multiples of 1 hour
00134                             periodic_timer = periodic_time/(60*60);
00135                             strcpy(pt, "00100000");
00136                         } else {
00137                             if (periodic_time <= 10*60*60*ie_value_max) { // multiples of 10 hours
00138                                 periodic_timer = periodic_time/(10*60*60);
00139                                 strcpy(pt, "01000000");
00140                             } else { // multiples of 320 hours
00141                                 int t = periodic_time / (320*60*60);
00142                                 if (t > ie_value_max) {
00143                                     t = ie_value_max;
00144                                 }
00145                                 periodic_timer = t;
00146                                 strcpy(pt, "11000000");
00147                             }
00148                         }
00149                     }
00150                 }
00151             }
00152         }
00153 
00154         uint_to_binary_str(periodic_timer, &pt[3], sizeof(pt)-3, PSMTimerBits);
00155         pt[8] = '\0';
00156 
00157         /**
00158             Table 10.5.172/3GPP TS 24.008: GPRS Timer information element
00159 
00160             Bits 5 to 1 represent the binary coded timer value.
00161 
00162             Bits 6 to 8 defines the timer value unit for the GPRS timer as follows:
00163 
00164             8 7 6
00165             0 0 0  value is incremented in multiples of 2 seconds
00166             0 0 1  value is incremented in multiples of 1 minute
00167             0 1 0  value is incremented in multiples of decihours
00168             1 1 1  value indicates that the timer is deactivated.
00169 
00170             Other values shall be interpreted as multiples of 1 minute in this version of the protocol.
00171         */
00172         char at[8+1];
00173         uint32_t active_timer; // timer value encoded as 3GPP IE
00174         if (active_time <= 2*ie_value_max) { // multiples of 2 seconds
00175             active_timer = active_time/2;
00176             strcpy(at, "00000000");
00177         } else {
00178             if (active_time <= 60*ie_value_max) { // multiples of 1 minute
00179                 active_timer = (1<<5) | (active_time/60);
00180                 strcpy(at, "00100000");
00181             } else { // multiples of decihours
00182                 int t = active_time / (6*60);
00183                 if (t > ie_value_max) {
00184                     t = ie_value_max;
00185                 }
00186                 active_timer = t;
00187                 strcpy(at, "01000000");
00188             }
00189         }
00190 
00191         uint_to_binary_str(active_timer, &at[3], sizeof(at)-3, PSMTimerBits);
00192         pt[8] = '\0';
00193 
00194         // request for both GPRS and LTE
00195         _at.cmd_start("AT+CPSMS=");
00196         _at.write_int(1);
00197         _at.write_string(pt);
00198         _at.write_string(at);
00199         _at.write_string(pt);
00200         _at.write_string(at);
00201         _at.cmd_stop();
00202         _at.resp_start();
00203         _at.resp_stop();
00204 
00205 
00206         if (_at.get_last_error() != NSAPI_ERROR_OK ) {
00207             tr_warn("Power save mode not enabled!");
00208         } else {
00209             // network may not agree with power save options but
00210             // that should be fine as timeout is not longer than requested
00211         }
00212     }
00213 
00214     return _at.unlock_return_error();
00215 }
00216 
00217 nsapi_error_t AT_CellularPower::opt_receive_period(int mode, EDRXAccessTechnology act_type, uint8_t edrx_value)
00218 {
00219     char edrx[5];
00220     uint_to_binary_str(edrx_value, edrx, 5, 4);
00221     edrx[4] = '\0';
00222 
00223     _at.lock();
00224 
00225     _at.cmd_start("AT+CEDRXS=");
00226     _at.write_int(mode);
00227     _at.write_int(act_type);
00228     _at.write_string(edrx);
00229     _at.cmd_stop();
00230     _at.resp_start();
00231     _at.resp_stop();
00232 
00233     return _at.unlock_return_error();
00234 }
00235 
00236 nsapi_error_t AT_CellularPower::set_device_ready_urc_cb(mbed::Callback<void()> callback)
00237 {
00238     return NSAPI_ERROR_UNSUPPORTED ;
00239 }
00240 
00241 void AT_CellularPower::remove_device_ready_urc_cb(mbed::Callback<void()> callback)
00242 {
00243 }