// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #include "MP2639B.hpp" namespace bsp::devices::power { MP2639B::MP2639B(const Configuration &conf) : configuration{conf} { irq_filter_timer = xTimerCreate("irq_charger_filter", pdMS_TO_TICKS(50), pdFALSE, this, [](TimerHandle_t xTimer) { MP2639B *inst = static_cast(pvTimerGetTimerID(xTimer)); /// Charging disable is done automatically if the conditions are met. if (not inst->is_valid_voltage()) { inst->enable_charging(false); } if (inst->configuration.notification) { inst->configuration.notification(inst->get_charge_status()); } }); drivers::DriverGPIOPinParams mode_pin_params{}; mode_pin_params.dir = drivers::DriverGPIOPinParams::Direction::Output; mode_pin_params.irqMode = drivers::DriverGPIOPinParams::InterruptMode::NoIntmode; mode_pin_params.defLogic = 0; mode_pin_params.pin = configuration.mode_pin; configuration.mode_gpio->ConfPin(mode_pin_params); /// Always start with charging disabled enable_charging(false); } MP2639B::~MP2639B() { xTimerDelete(irq_filter_timer, pdMS_TO_TICKS(100)); configuration.chgok_gpio->DisableInterrupt(1 << configuration.chgok_pin); configuration.acok_gpio->DisableInterrupt(1 << configuration.acok_pin); enable_charging(false); } MP2639B::ChargingStatus MP2639B::get_charge_status() { /// For more info, please refer to the Table 1 "Charging Status Indication" in reference manual. ChargingStatus status{}; const auto valid_voltage = is_valid_voltage(); const auto charging = is_charging(); if (not valid_voltage) { status = ChargingStatus::Discharging; } else if (valid_voltage and is_charging_enabled()) { status = charging ? ChargingStatus::Charging : ChargingStatus::Complete; } else if (valid_voltage and not is_charging_enabled()) { status = ChargingStatus::PluggedNotCharging; } return status; } void MP2639B::enable_charging(bool ctrl) { if (ctrl) { configuration.mode_gpio->WritePin(configuration.mode_pin, 0); } else { configuration.mode_gpio->WritePin(configuration.mode_pin, 1); } } void MP2639B::enable_irq() { drivers::DriverGPIOPinParams ACOKPinConfig{}; ACOKPinConfig.dir = drivers::DriverGPIOPinParams::Direction::Input; ACOKPinConfig.irqMode = drivers::DriverGPIOPinParams::InterruptMode::IntRisingOrFallingEdge; ACOKPinConfig.defLogic = 0; ACOKPinConfig.pin = configuration.acok_pin; configuration.acok_gpio->ConfPin(ACOKPinConfig); drivers::DriverGPIOPinParams CHGOKPinConfig{}; CHGOKPinConfig.dir = drivers::DriverGPIOPinParams::Direction::Input; CHGOKPinConfig.irqMode = drivers::DriverGPIOPinParams::InterruptMode::IntRisingOrFallingEdge; CHGOKPinConfig.defLogic = 0; CHGOKPinConfig.pin = configuration.chgok_pin; configuration.chgok_gpio->ConfPin(CHGOKPinConfig); configuration.chgok_gpio->EnableInterrupt(1U << configuration.chgok_pin); configuration.acok_gpio->EnableInterrupt(1U << configuration.acok_pin); } void MP2639B::handle_irq() { if (xTimerIsTimerActive(irq_filter_timer) == pdFALSE) { xTimerStart(irq_filter_timer, pdMS_TO_TICKS(500)); } } bool MP2639B::is_charging_enabled() const { return configuration.mode_gpio->ReadPin(configuration.mode_pin) == 0; } bool MP2639B::is_valid_voltage() const { /// ACOK -> Valid Input Supply Indicator. A logic Low on this pin indicates the presence of a valid input power /// supply. return configuration.acok_gpio->ReadPin(configuration.acok_pin) == 0; } bool MP2639B::is_charging() const { /// CHGOK -> Charging Completion Indicator. A logic Low indicates charging operation. The pin will become an /// open drain once the charge is completed or suspended. return configuration.chgok_gpio->ReadPin(configuration.chgok_pin) == 0; } } // namespace bsp::devices::power