~aleteoryx/muditaos

180bfbadcd2e5eaa4ec949ffa3afce086ad808ef — Hubert Chrzaniuk 5 years ago c9df893
[EGD-4170] Cellular - modem reset (#929)

M changelog.md => changelog.md +2 -0
@@ 3,8 3,10 @@
## Current release

### Added

* `[settings][bluetooth]` Add "Phone name" window.
* `[gui]` Add "ButtonOnOff" widget.
* `[cellular]` Add support for modem reset

### Changed


M module-cellular/at/Commands.hpp => module-cellular/at/Commands.hpp +12 -1
@@ 96,6 96,7 @@ namespace at
        ATD,  /// setup call
        IPR,  /// set baudrate
        CMUX, /// setup cmux params
        CFUN, /// set phone functionality
        CMGS, /// sms
        QCMGS,
        CREG,       /// network registration status


@@ 122,9 123,14 @@ namespace at
        DISABLE_TIME_ZONE_UPDATE,
        DISABLE_TIME_ZONE_REPORTING,
        ENABLE_NETWORK_REGISTRATION_URC,
        SET_SMS_TEXT_MODE_UCS2
        SET_SMS_TEXT_MODE_UCS2,
        CFUN_RESET,
        CFUN_MIN_FUNCTIONALITY,    /// Set minimum functionality
        CFUN_FULL_FUNCTIONALITY,   /// Full functionality
        CFUN_DISABLE_TRANSMITTING, /// Disable the ME from both transmitting and receiving RF signals
    };

    // below timeouts are defined in Quectel_EC25&EC21_AT_Commands_Manual_V1.3.pdf
    inline auto factory(AT at) -> const Cmd &
    {
        static const std::map<AT, const Cmd> fact{


@@ 164,6 170,11 @@ namespace at
            {AT::ATD, {"ATD"}},
            {AT::IPR, {"AT+IPR="}},
            {AT::CMUX, {"AT+CMUX="}},
            {AT::CFUN, {"AT+CFUN=", 15000}},
            {AT::CFUN_RESET, {"AT+CFUN=1,1", 15000}},
            {AT::CFUN_MIN_FUNCTIONALITY, {"AT+CFUN=0", 15000}},
            {AT::CFUN_FULL_FUNCTIONALITY, {"AT+CFUN=1", 15000}},
            {AT::CFUN_DISABLE_TRANSMITTING, {"AT+CFUN=4", 15000}},
            {AT::CMGS, {"AT+CMGS=\""}},
            {AT::QCMGS, {"AT+QCMGS=\""}},
            {AT::CREG, {"AT+CREG?", default_doc_timeout}},

M module-services/service-cellular/ServiceCellular.cpp => module-services/service-cellular/ServiceCellular.cpp +48 -4
@@ 243,6 243,36 @@ void ServiceCellular::registerMessageHandlers()
    handle_CellularGetChannelMessage();
}

bool ServiceCellular::resetCellularModule(ResetType type)
{
    LOG_DEBUG("Cellular modem reset. Type %d", static_cast<int>(type));

    auto channel = cmux->get(TS0710::Channel::Commands);
    if (!channel) {
        LOG_ERROR("Bad channel");
        return false;
    }

    switch (type) {
    case ResetType::SoftReset:
        if (auto response = channel->cmd(at::AT::CFUN_RESET); response.code == at::Result::Code::OK) {
            return true;
        }
        LOG_ERROR("Cellular modem reset failed.");
        return false;
    case ResetType::PowerCycle:
        cmux->TurnOffModem();
        cmux->TurnOnModem();
        isAfterForceReboot = true;
        return true;
    case ResetType::HardReset:
        cmux->ResetModem();
        isAfterForceReboot = true;
        return true;
    }
    return false;
}

void ServiceCellular::change_state(cellular::StateChange *msg)
{
    assert(msg);


@@ 367,6 397,11 @@ bool ServiceCellular::handle_power_up_procedure()

bool ServiceCellular::handle_power_up_in_progress_procedure(void)
{
    if (isAfterForceReboot) {
        constexpr auto msModemUartInitTime = 12000;
        vTaskDelay(pdMS_TO_TICKS(msModemUartInitTime));
        isAfterForceReboot = false;
    }
    auto ret = cmux->BaudDetectProcedure();
    if (ret == TS0710::ConfState::Success) {
        state.set(this, cellular::State::ST::CellularConfProcedure);


@@ 406,6 441,7 @@ bool ServiceCellular::handle_power_down_waiting()
bool ServiceCellular::handle_power_down()
{
    LOG_DEBUG("Powered Down");
    isAfterForceReboot = true;
    cmux.reset();
    cmux = std::make_unique<TS0710>(PortSpeed_e::PS460800, this);
    InitHandler();


@@ 801,11 837,19 @@ sys::Message_t ServiceCellular::DataReceivedHandler(sys::DataMessage *msgl, sys:
        if (msg != nullptr) {
            if (board == bsp::Board::T4) {
                auto status_pin = msg->state;
                if (status_pin == value::ACTIVE && state.get() == State::ST::PowerUpProcedure) {
                    state.set(this, State::ST::PowerUpInProgress); // and go to baud detect as usual
                if (status_pin == value::ACTIVE) {
                    if (state.get() == State::ST::PowerUpProcedure) {
                        state.set(this, State::ST::PowerUpInProgress); // and go to baud detect as usual
                    }
                    else {
                        // asynchronous power toggle should fall back to PowerDown regardless the state
                        state.set(this, State::ST::PowerDown);
                    }
                }
                else if (status_pin == value::INACTIVE && state.get() == State::ST::PowerDownWaiting) {
                    state.set(this, State::ST::PowerDown);
                else if (status_pin == value::INACTIVE) {
                    if (isAfterForceReboot == true || state.get() == State::ST::PowerDownWaiting) {
                        state.set(this, State::ST::PowerDown);
                    }
                }
            }
        }

M module-services/service-cellular/ServiceCellular.hpp => module-services/service-cellular/ServiceCellular.hpp +9 -0
@@ 98,6 98,15 @@ class ServiceCellular : public sys::Service

    ussd::State ussdState = ussd::State::none;

    enum class ResetType
    {
        SoftReset,  //<! AT CFUN reset
        PowerCycle, //<! PWRKEY pin toggle
        HardReset   //<! RESET_N pin
    };
    bool resetCellularModule(ResetType type);
    bool isAfterForceReboot = false;

    /// one point of state change handling
    void change_state(cellular::StateChange *msg);