takashi kadono / Mbed OS Nucleo_446

Dependencies:   ssd1331

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, int do_reset)
00064 {
00065     _at.lock();
00066     _at.cmd_start("AT+CFUN=");
00067     _at.write_int(func_level);
00068     _at.write_int(do_reset);
00069     _at.cmd_stop();
00070     _at.resp_start();
00071     _at.resp_stop();
00072     return _at.unlock_return_error();
00073 }
00074 
00075 nsapi_error_t AT_CellularPower::reset()
00076 {
00077     _at.lock();
00078     _at.cmd_start("AT+CFUN=");// reset to full power levels
00079     _at.write_int(1);
00080     _at.write_int(1);
00081     _at.cmd_stop();
00082     _at.resp_start();
00083     _at.resp_stop();
00084     return _at.unlock_return_error();
00085 }
00086 
00087 nsapi_error_t AT_CellularPower::opt_power_save_mode(int periodic_time, int active_time)
00088 {
00089     _at.lock();
00090 
00091     if (periodic_time == 0 && active_time == 0) {
00092         // disable PSM
00093         _at.cmd_start("AT+CPSMS=");
00094         _at.write_int(0);
00095         _at.cmd_stop();
00096         _at.resp_start();
00097         _at.resp_stop();
00098     } else {
00099         /**
00100             Table 10.5.163a/3GPP TS 24.008: GPRS Timer 3 information element
00101 
00102             Bits 5 to 1 represent the binary coded timer value.
00103 
00104             Bits 6 to 8 defines the timer value unit for the GPRS timer as follows:
00105             8 7 6
00106             0 0 0 value is incremented in multiples of 10 minutes
00107             0 0 1 value is incremented in multiples of 1 hour
00108             0 1 0 value is incremented in multiples of 10 hours
00109             0 1 1 value is incremented in multiples of 2 seconds
00110             1 0 0 value is incremented in multiples of 30 seconds
00111             1 0 1 value is incremented in multiples of 1 minute
00112             1 1 0 value is incremented in multiples of 320 hours (NOTE 1)
00113             1 1 1 value indicates that the timer is deactivated (NOTE 2).
00114          */
00115         char pt[8 + 1]; // timer value encoded as 3GPP IE
00116         const int ie_value_max = 0x1f;
00117         uint32_t periodic_timer = 0;
00118         if (periodic_time <= 2 * ie_value_max) { // multiples of 2 seconds
00119             periodic_timer = periodic_time / 2;
00120             strcpy(pt, "01100000");
00121         } else {
00122             if (periodic_time <= 30 * ie_value_max) { // multiples of 30 seconds
00123                 periodic_timer = periodic_time / 30;
00124                 strcpy(pt, "10000000");
00125             } else {
00126                 if (periodic_time <= 60 * ie_value_max) { // multiples of 1 minute
00127                     periodic_timer = periodic_time / 60;
00128                     strcpy(pt, "10100000");
00129                 } else {
00130                     if (periodic_time <= 10 * 60 * ie_value_max) { // multiples of 10 minutes
00131                         periodic_timer = periodic_time / (10 * 60);
00132                         strcpy(pt, "00000000");
00133                     } else {
00134                         if (periodic_time <= 60 * 60 * ie_value_max) { // multiples of 1 hour
00135                             periodic_timer = periodic_time / (60 * 60);
00136                             strcpy(pt, "00100000");
00137                         } else {
00138                             if (periodic_time <= 10 * 60 * 60 * ie_value_max) { // multiples of 10 hours
00139                                 periodic_timer = periodic_time / (10 * 60 * 60);
00140                                 strcpy(pt, "01000000");
00141                             } else { // multiples of 320 hours
00142                                 int t = periodic_time / (320 * 60 * 60);
00143                                 if (t > ie_value_max) {
00144                                     t = ie_value_max;
00145                                 }
00146                                 periodic_timer = t;
00147                                 strcpy(pt, "11000000");
00148                             }
00149                         }
00150                     }
00151                 }
00152             }
00153         }
00154 
00155         uint_to_binary_str(periodic_timer, &pt[3], sizeof(pt) - 3, PSMTimerBits);
00156         pt[8] = '\0';
00157 
00158         /**
00159             Table 10.5.172/3GPP TS 24.008: GPRS Timer information element
00160 
00161             Bits 5 to 1 represent the binary coded timer value.
00162 
00163             Bits 6 to 8 defines the timer value unit for the GPRS timer as follows:
00164 
00165             8 7 6
00166             0 0 0  value is incremented in multiples of 2 seconds
00167             0 0 1  value is incremented in multiples of 1 minute
00168             0 1 0  value is incremented in multiples of decihours
00169             1 1 1  value indicates that the timer is deactivated.
00170 
00171             Other values shall be interpreted as multiples of 1 minute in this version of the protocol.
00172         */
00173         char at[8 + 1];
00174         uint32_t active_timer; // timer value encoded as 3GPP IE
00175         if (active_time <= 2 * ie_value_max) { // multiples of 2 seconds
00176             active_timer = active_time / 2;
00177             strcpy(at, "00000000");
00178         } else {
00179             if (active_time <= 60 * ie_value_max) { // multiples of 1 minute
00180                 active_timer = (1 << 5) | (active_time / 60);
00181                 strcpy(at, "00100000");
00182             } else { // multiples of decihours
00183                 int t = active_time / (6 * 60);
00184                 if (t > ie_value_max) {
00185                     t = ie_value_max;
00186                 }
00187                 active_timer = t;
00188                 strcpy(at, "01000000");
00189             }
00190         }
00191 
00192         uint_to_binary_str(active_timer, &at[3], sizeof(at) - 3, PSMTimerBits);
00193         at[8] = '\0';
00194 
00195         // request for both GPRS and LTE
00196         _at.cmd_start("AT+CPSMS=");
00197         _at.write_int(1);
00198         _at.write_string(pt);
00199         _at.write_string(at);
00200         _at.write_string(pt);
00201         _at.write_string(at);
00202         _at.cmd_stop();
00203         _at.resp_start();
00204         _at.resp_stop();
00205 
00206 
00207         if (_at.get_last_error() != NSAPI_ERROR_OK ) {
00208             tr_warn("Power save mode not enabled!");
00209         } else {
00210             // network may not agree with power save options but
00211             // that should be fine as timeout is not longer than requested
00212         }
00213     }
00214 
00215     return _at.unlock_return_error();
00216 }
00217 
00218 nsapi_error_t AT_CellularPower::opt_receive_period(int mode, EDRXAccessTechnology act_type, uint8_t edrx_value)
00219 {
00220     char edrx[5];
00221     uint_to_binary_str(edrx_value, edrx, 5, 4);
00222     edrx[4] = '\0';
00223 
00224     _at.lock();
00225 
00226     _at.cmd_start("AT+CEDRXS=");
00227     _at.write_int(mode);
00228     _at.write_int(act_type);
00229     _at.write_string(edrx);
00230     _at.cmd_stop();
00231     _at.resp_start();
00232     _at.resp_stop();
00233 
00234     return _at.unlock_return_error();
00235 }
00236 
00237 nsapi_error_t AT_CellularPower::is_device_ready()
00238 {
00239     _at.lock();
00240     _at.cmd_start("AT");
00241     _at.cmd_stop();
00242     _at.resp_start();
00243     _at.resp_stop();
00244 
00245     // we need to do this twice because for example after data mode the first 'AT' command will give modem a
00246     // stimulus that we are back to command mode.
00247     _at.clear_error();
00248     _at.cmd_start("AT");
00249     _at.cmd_stop();
00250     _at.resp_start();
00251     _at.resp_stop();
00252 
00253     return _at.unlock_return_error();
00254 }
00255 
00256 nsapi_error_t AT_CellularPower::set_device_ready_urc_cb(mbed::Callback<void()> callback)
00257 {
00258     return NSAPI_ERROR_UNSUPPORTED ;
00259 }
00260 
00261 void AT_CellularPower::remove_device_ready_urc_cb(mbed::Callback<void()> callback)
00262 {
00263 }