~aleteoryx/muditaos

5e52e0324fd20a1ac254f25a02f03edf9cedd6bf — Lefucjusz 1 year, 7 months ago 10d9658
[BH-2009] Change charger chip name to proper one

Renamed some legacy name of battery charger
chip to the one that is used in the device.
Minor cleanups.
M module-bsp/CMakeLists.txt => module-bsp/CMakeLists.txt +1 -1
@@ 14,7 14,7 @@ target_sources(
        bsp/lpm/bsp_lpm.cpp
        devices/Device.cpp
        devices/power/CW2015.cpp
        devices/power/MP2639B.cpp
        devices/power/MP2615GQ.cpp
        devices/temperature/CT7117.cpp
        drivers/dma/DriverDMA.cpp
        drivers/dmamux/DriverDMAMux.cpp

M module-bsp/board/rt1051/bellpx/hal/battery_charger/BatteryCharger.cpp => module-bsp/board/rt1051/bellpx/hal/battery_charger/BatteryCharger.cpp +14 -14
@@ 10,7 10,7 @@
#include "timers.h"

#include <hal/battery_charger/AbstractBatteryCharger.hpp>
#include <devices/power/MP2639B.hpp>
#include <devices/power/MP2615GQ.hpp>
#include <devices/power/CW2015.hpp>
#include <board/BoardDefinitions.hpp>
#include <log/log.hpp>


@@ 74,7 74,7 @@ namespace hal::battery
        using BatteryWorkerQueue = WorkerQueue<IrqEvents>;

        explicit BellBatteryCharger(xQueueHandle irqQueueHandle);
        ~BellBatteryCharger();
        ~BellBatteryCharger() override;

        std::optional<Voltage> getBatteryVoltage() const final;
        std::optional<SOC> getSOC() const final;


@@ 92,7 92,7 @@ namespace hal::battery
        void pollFuelGauge();

        void handleIrqEvents(IrqEvents event);
        void handleChargerEvents(MP2639B::ChargingStatus status);
        void handleChargerEvents(MP2615GQ::ChargingStatus status);

        xTimerHandle reinit_timer;
        xQueueHandle notification_channel;


@@ 102,7 102,7 @@ namespace hal::battery
        std::shared_ptr<drivers::DriverI2C> i2c;
        std::shared_ptr<drivers::DriverGPIO> charger_gpio_chgok;
        std::shared_ptr<drivers::DriverGPIO> charger_gpio;
        mutable bsp::devices::power::MP2639B charger;
        mutable bsp::devices::power::MP2615GQ charger;

        std::shared_ptr<drivers::DriverGPIO> fuel_gauge_gpio;
        mutable bsp::devices::power::CW2015 fuel_gauge;


@@ 111,7 111,7 @@ namespace hal::battery
    BellBatteryCharger::BellBatteryCharger(xQueueHandle irqQueueHandle)
        : notification_channel{irqQueueHandle}, i2c{drivers::DriverI2C::Create(i2c_instance, i2c_params)},
          charger_gpio_chgok{drivers::DriverGPIO::Create(charger_irq_gpio_chgok, {})},
          charger_gpio{drivers::DriverGPIO::Create(charger_irq_gpio, {})}, charger{MP2639B::Configuration{
          charger_gpio{drivers::DriverGPIO::Create(charger_irq_gpio, {})}, charger{MP2615GQ::Configuration{
                                                                               charger_gpio,
                                                                               charger_irq_pin_mode,
                                                                               charger_gpio,


@@ 127,7 127,7 @@ namespace hal::battery
    {

        reinit_timer = xTimerCreate("reinit_timer", reinit_poll_time, pdFALSE, this, [](TimerHandle_t xTimer) {
            BellBatteryCharger *inst = static_cast<BellBatteryCharger *>(pvTimerGetTimerID(xTimer));
            auto inst = static_cast<BellBatteryCharger *>(pvTimerGetTimerID(xTimer));
            inst->fuel_gauge.reinit();
            inst->pollFuelGauge();
        });


@@ 169,26 169,26 @@ namespace hal::battery

    AbstractBatteryCharger::ChargingStatus BellBatteryCharger::getChargingStatus() const
    {
        /// Charger status fetched from MP2639B alone is not enough to be 100% sure what state we are currently in. For
        /// more info check the Table 2 (page 26) from the MP2639B datasheet. It is required to also take into account
        /// Charger status fetched from MP2615GQ alone is not enough to be 100% sure what state we are currently in. For
        /// more info check the Table 2 (page 26) from the MP2615GQ datasheet. It is required to also take into account
        /// the current state of SOC.

        const auto charger_status = charger.get_charge_status();
        const auto current_soc    = getSOC();

        if (charger_status == MP2639B::ChargingStatus::Complete && current_soc >= 100) {
        if (charger_status == MP2615GQ::ChargingStatus::Complete && current_soc >= 100) {
            return ChargingStatus::ChargingDone;
        }
        else if (charger_status == MP2639B::ChargingStatus::Discharging) {
        else if (charger_status == MP2615GQ::ChargingStatus::Discharging) {
            return ChargingStatus::Discharging;
        }
        else if (charger_status == MP2639B::ChargingStatus::Charging && current_soc < 100) {
        else if (charger_status == MP2615GQ::ChargingStatus::Charging && current_soc < 100) {
            return ChargingStatus::Charging;
        }
        else if (charger_status == MP2639B::ChargingStatus::Complete && current_soc < 100) {
        else if (charger_status == MP2615GQ::ChargingStatus::Complete && current_soc < 100) {
            return ChargingStatus::PluggedNotCharging;
        }
        else if (charger_status == MP2639B::ChargingStatus::Charging && current_soc >= 100) {
        else if (charger_status == MP2615GQ::ChargingStatus::Charging && current_soc >= 100) {
            LOG_INFO("The charger reports 'Charging state', but the battery SOC is 100");
            return ChargingStatus::ChargingDone;
        }


@@ 261,7 261,7 @@ namespace hal::battery
                              }},
                   event);
    }
    void BellBatteryCharger::handleChargerEvents(const MP2639B::ChargingStatus)
    void BellBatteryCharger::handleChargerEvents([[maybe_unused]] MP2615GQ::ChargingStatus status)
    {
        sendNotification(Events::Charger);
    }

M module-bsp/devices/power/CW2015.cpp => module-bsp/devices/power/CW2015.cpp +12 -3
@@ 1,4 1,4 @@
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "CW2015.hpp"


@@ 19,7 19,6 @@
namespace
{
    constexpr std::uint32_t i2c_subaddr_size = 1;

} // namespace

namespace bsp::devices::power


@@ 30,10 29,12 @@ namespace bsp::devices::power
    {
        status = init_chip();
    }

    CW2015::~CW2015()
    {
        sleep();
    }

    std::optional<units::SOC> CW2015::get_battery_soc()
    {
        // Only higher byte of SOC register pair is needed here. Accuracy will be enough


@@ 44,6 45,7 @@ namespace bsp::devices::power
            return std::nullopt;
        }
    }

    std::optional<units::Voltage> CW2015::get_battery_voltage()
    {
        constexpr auto median_samples          = 3;


@@ 83,6 85,7 @@ namespace bsp::devices::power

        return ADResult * adc_conversion_constant / micro_to_milli_ratio; // mV
    }

    CW2015::RetCodes CW2015::clear_irq()
    {
        const auto lsb = read(RRT_ALERT::ADDRESS_L);


@@ 154,6 157,7 @@ namespace bsp::devices::power

        return RetCodes::Ok;
    }

    CW2015::RetCodes CW2015::reset_chip()
    {
        if (not write(Mode::ADDRESS, Mode{}.set_power_on_reset().get_raw())) {


@@ 165,12 169,14 @@ namespace bsp::devices::power
        }
        return RetCodes::Ok;
    }

    void CW2015::irq_handler()
    {
        if (const auto result = clear_irq(); result != RetCodes::Ok) {
            LOG_ERROR("Error during handling irq, %s", magic_enum::enum_name(result).data());
        }
    }

    void CW2015::init_irq_pin(std::shared_ptr<drivers::DriverGPIO> gpio, uint32_t pin)
    {
        drivers::DriverGPIOPinParams ALRTPinConfig{};


@@ 182,6 188,7 @@ namespace bsp::devices::power

        gpio->EnableInterrupt(1 << pin);
    }

    CW2015::RetCodes CW2015::quick_start()
    {
        if (not write(Mode::ADDRESS, Mode{}.set_quick_start().get_raw())) {


@@ 193,6 200,7 @@ namespace bsp::devices::power
        }
        return RetCodes::Ok;
    }

    CW2015::RetCodes CW2015::poll() const
    {
        return status;


@@ 333,13 341,14 @@ namespace bsp::devices::power
        }
        return false;
    }

    CW2015::operator bool() const
    {
        return status == RetCodes::Ok;
    }

    CW2015::RetCodes CW2015::calibrate()
    {
        return quick_start();
    }

} // namespace bsp::devices::power

M module-bsp/devices/power/CW2015.hpp => module-bsp/devices/power/CW2015.hpp +3 -4
@@ 1,4 1,4 @@
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once


@@ 10,7 10,7 @@

namespace bsp::devices::power
{
    /// MP2639B fuel gauge driver
    /// CW2015 fuel gauge driver
    /// To enable interrupts support call \ref init_irq_pin and then invoke \ref handle_irq in the corresponding IRQ
    /// routine.
    class CW2015


@@ 33,7 33,7 @@ namespace bsp::devices::power
        CW2015 &operator=(CW2015 &&) noexcept = delete;

        /// Returns the result of the chip initialization
        RetCodes poll() const;
        [[nodiscard]] RetCodes poll() const;
        /// Returns true if the chip initialization success, otherwise false
        explicit operator bool() const;
        /// Explicitly triggers chip initialization procedure. The result can be polled by \ref poll or using bool


@@ 79,5 79,4 @@ namespace bsp::devices::power
        RetCodes status{};
        units::SOC alert_threshold;
    };

} // namespace bsp::devices::power

R module-bsp/devices/power/MP2639B.cpp => module-bsp/devices/power/MP2615GQ.cpp +38 -37
@@ 1,23 1,26 @@
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "MP2639B.hpp"
#include "MP2615GQ.hpp"

namespace bsp::devices::power
{
    MP2639B::MP2639B(const Configuration &conf) : configuration{conf}
    MP2615GQ::MP2615GQ(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<MP2639B *>(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());
                }
            });
        irq_filter_timer = xTimerCreate(irq_filter_timer_name,
                                        pdMS_TO_TICKS(irq_filter_timer_interval_ms),
                                        pdFALSE,
                                        this,
                                        [](TimerHandle_t xTimer) {
                                            auto inst = static_cast<MP2615GQ *>(pvTimerGetTimerID(xTimer));
                                            /// Charging disable is done automatically if the conditions are met.
                                            if (!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;


@@ 30,44 33,40 @@ namespace bsp::devices::power
        enable_charging(false);
    }

    MP2639B::~MP2639B()
    MP2615GQ::~MP2615GQ()
    {
        xTimerDelete(irq_filter_timer, pdMS_TO_TICKS(100));
        xTimerDelete(irq_filter_timer, pdMS_TO_TICKS(irq_filter_timer_cmd_timeout_ms));
        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()

    MP2615GQ::ChargingStatus MP2615GQ::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) {
        ChargingStatus status{};
        if (!valid_voltage) {
            status = ChargingStatus::Discharging;
        }
        else if (valid_voltage and is_charging_enabled()) {
        else if (is_charging_enabled()) {
            status = charging ? ChargingStatus::Charging : ChargingStatus::Complete;
        }
        else if (valid_voltage and not is_charging_enabled()) {
        else if (!is_charging_enabled()) {
            status = ChargingStatus::PluggedNotCharging;
        }
        return status;
    }
    void MP2639B::enable_charging(bool ctrl)

    void MP2615GQ::enable_charging(bool ctrl)
    {
        if (ctrl) {
            configuration.mode_gpio->WritePin(configuration.mode_pin, 0);
        }
        else {
            configuration.mode_gpio->WritePin(configuration.mode_pin, 1);
        }
        configuration.mode_gpio->WritePin(configuration.mode_pin, ctrl ? 0 : 1);
    }
    void MP2639B::enable_irq()

    void MP2615GQ::enable_irq()
    {
        drivers::DriverGPIOPinParams ACOKPinConfig{};
        ACOKPinConfig.dir      = drivers::DriverGPIOPinParams::Direction::Input;


@@ 87,27 86,29 @@ namespace bsp::devices::power
        configuration.acok_gpio->EnableInterrupt(1U << configuration.acok_pin);
    }

    void MP2639B::handle_irq()
    void MP2615GQ::handle_irq()
    {
        if (xTimerIsTimerActive(irq_filter_timer) == pdFALSE) {
            xTimerStart(irq_filter_timer, pdMS_TO_TICKS(500));
            xTimerStart(irq_filter_timer, pdMS_TO_TICKS(irq_filter_timer_cmd_timeout_ms));
        }
    }
    bool MP2639B::is_charging_enabled() const

    bool MP2615GQ::is_charging_enabled() const
    {
        return configuration.mode_gpio->ReadPin(configuration.mode_pin) == 0;
    }
    bool MP2639B::is_valid_voltage() const

    bool MP2615GQ::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

    bool MP2615GQ::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

R module-bsp/devices/power/MP2639B.hpp => module-bsp/devices/power/MP2615GQ.hpp +16 -12
@@ 12,10 12,10 @@

namespace bsp::devices::power
{
    /// MP2639B charger driver
    /// MP2615GQ charger driver
    /// To enable interrupts support call \ref enable_irq and then invoke \ref handle_irq in the corresponding IRQ
    /// routine.
    class MP2639B
    class MP2615GQ
    {
      public:
        enum class ChargingStatus : std::uint8_t


@@ 44,13 44,13 @@ namespace bsp::devices::power
            std::function<void(const ChargingStatus)> notification;
        };

        explicit MP2639B(const Configuration &conf);
        ~MP2639B();
        explicit MP2615GQ(const Configuration &conf);
        ~MP2615GQ();

        MP2639B(const MP2639B &) = delete;
        MP2639B &operator=(const MP2639B &) = delete;
        MP2639B(MP2639B &&)                 = default;
        MP2639B &operator=(MP2639B &&) = delete;
        MP2615GQ(const MP2615GQ &) = delete;
        MP2615GQ &operator=(const MP2615GQ &) = delete;
        MP2615GQ(MP2615GQ &&)                 = default;
        MP2615GQ &operator=(MP2615GQ &&) = delete;

        ChargingStatus get_charge_status();
        void enable_charging(bool ctrl);


@@ 59,11 59,15 @@ namespace bsp::devices::power
        void handle_irq();

      private:
        bool is_charging() const;
        bool is_valid_voltage() const;
        bool is_charging_enabled() const;
        [[nodiscard]] bool is_charging() const;
        [[nodiscard]] bool is_valid_voltage() const;
        [[nodiscard]] bool is_charging_enabled() const;

        static constexpr auto irq_filter_timer_interval_ms    = 50;
        static constexpr auto irq_filter_timer_name           = "irq_charger_filter";
        static constexpr auto irq_filter_timer_cmd_timeout_ms = 100;

        Configuration configuration;
        xTimerHandle irq_filter_timer;
    };

} // namespace bsp::devices::power

M module-bsp/hal/include/hal/battery_charger/AbstractBatteryCharger.hpp => module-bsp/hal/include/hal/battery_charger/AbstractBatteryCharger.hpp +8 -7
@@ 1,4 1,4 @@
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once


@@ 18,6 18,7 @@ namespace hal::battery
      public:
        using SOC     = units::SOC;
        using Voltage = units::Voltage;

        enum class ChargingStatus
        {
            Discharging,


@@ 50,16 51,16 @@ namespace hal::battery

        struct Factory
        {
            static std::unique_ptr<AbstractBatteryCharger> create(xQueueHandle);
            static std::unique_ptr<AbstractBatteryCharger> create(xQueueHandle irqQueueHandle);
        };

        virtual ~AbstractBatteryCharger() = default;

        virtual std::optional<Voltage> getBatteryVoltage() const = 0;
        virtual std::optional<SOC> getSOC() const                = 0;
        virtual ChargingStatus getChargingStatus() const         = 0;
        virtual ChargerPresence getChargerPresence() const       = 0;
        virtual TemperatureState getTemperatureState() const     = 0;
        [[nodiscard]] virtual std::optional<Voltage> getBatteryVoltage() const = 0;
        [[nodiscard]] virtual std::optional<SOC> getSOC() const                = 0;
        [[nodiscard]] virtual ChargingStatus getChargingStatus() const         = 0;
        [[nodiscard]] virtual ChargerPresence getChargerPresence() const       = 0;
        [[nodiscard]] virtual TemperatureState getTemperatureState() const     = 0;

        static_assert(sizeof(Events) == sizeof(std::uint8_t),
                      "All events processed by event manager ought to have size of std::uint8_t");