~aleteoryx/muditaos

2ae8f8d6b392a03cb0ae45097a330235e6cad4cf — Wojtek Rzepecki 4 years ago 9acd593
[BH-821] Add battery abstraction layer

Added Abstraction layer for batter charger
to provide support for bell/pure/linux
M module-bsp/CMakeLists.txt => module-bsp/CMakeLists.txt +1 -0
@@ 26,6 26,7 @@ target_sources(

    PUBLIC
        hal/temperature_source/TemperatureSource.hpp
        hal/battery_charger/AbstractBatteryCharger.hpp
)
add_board_subdirectory(board)


M module-bsp/board/linux/CMakeLists.txt => module-bsp/board/linux/CMakeLists.txt +1 -1
@@ 4,7 4,6 @@ target_sources(module-bsp
        PRIVATE
                board.cpp

                battery-charger/battery_charger.cpp
                bluetooth/Bluetooth.cpp
                bluetooth/test/bsp_bt.cpp
                cellular/linux_cellular.cpp


@@ 24,6 23,7 @@ target_sources(module-bsp
                watchdog/software_watchdog.cpp
                watchdog/watchdog.cpp
                hal/temperature_source/TemperatureSource.cpp
                hal/battery_charger/BatteryCharger.cpp

                ${CMAKE_CURRENT_BINARY_DIR}/eink-config.h
)

R module-bsp/board/linux/battery-charger/battery_charger.cpp => module-bsp/board/linux/hal/battery_charger/BatteryCharger.cpp +65 -115
@@ 1,39 1,57 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "BatteryCharger.hpp"

#include <sys/stat.h>
#include <fcntl.h>
#include <EventStore.hpp>
#include <hal/GenericFactory.hpp>
#include <service-evtmgr/battery-level-check/BatteryLevelCheck.hpp>
#include <service-evtmgr/BatteryMessages.hpp>
#include <service-evtmgr/EventManagerCommon.hpp>
#include <magic_enum.hpp>

#include "board.h"
#include "bsp/battery-charger/battery_charger.hpp"
#include <algorithm>

namespace bsp::battery_charger
namespace hal::battery
{
    std::shared_ptr<AbstractBatteryCharger> AbstractBatteryCharger::Factory::create(sys::Service *service)
    {
        return hal::impl::factory<LinuxBatteryCharger, AbstractBatteryCharger>(service);
    }

    namespace
    {
        xQueueHandle IRQQueueHandle         = nullptr;
        xQueueHandle DCDQueueHandle         = nullptr;
        TaskHandle_t batteryWorkerHandle    = nullptr;
        enum class USBSourceType
        {
            DcdSDP,
            DcdCDP,
            DcdDCP,
        };

        constexpr auto batteryFIFO          = "/tmp/fifoBattKeys";
        constexpr auto fifoFileAccessRights = 0666;
        constexpr auto fifoBuffSize         = 10;
        constexpr auto queueTimeoutTicks    = 100;
        constexpr auto taskDelay            = 50;

        StateOfCharge battLevel             = 100;
        constexpr StateOfCharge fullBattery = 100;
        bool plugged                        = false;
        topControllerIRQsource IRQSrc       = topControllerIRQsource::CHGR_INT;
        constexpr unsigned fullBattery = 100;

        constexpr auto chargerPlugStateChange = 'p';
        constexpr auto batteryLevelUp         = ']';
        constexpr auto batteryLevelDown       = '[';
        constexpr auto chargerTypeDcdSDP      = 'l';
        constexpr auto chargerTypeDcdCDP      = ';';
        constexpr auto chargerTypeDcdDCP      = '\'';

        constexpr auto chargerTypeDcdSDP = 'l';
        constexpr auto chargerTypeDcdCDP = ';';
        constexpr auto chargerTypeDcdDCP = '\'';
        xQueueHandle IRQQueueHandle      = nullptr;
        xQueueHandle DCDQueueHandle      = nullptr;
        TaskHandle_t batteryWorkerHandle = nullptr;
        unsigned batteryLevel            = 100;
        bool isPlugged                   = false;

        void battery_worker(void *parameters)
        void batteryWorker(void *parameters)
        {
            mkfifo(batteryFIFO, fifoFileAccessRights);



@@ 50,45 68,27 @@ namespace bsp::battery_charger
                    std::uint8_t notification = 0;
                    switch (static_cast<char>(buff[0])) {
                    case chargerPlugStateChange:
                        notification      = static_cast<std::uint8_t>(batteryIRQSource::INTB);
                        IRQSrc            = topControllerIRQsource::CHGR_INT;
                        plugged           = !plugged;
                        isPlugged         = !isPlugged;
                        targetQueueHandle = IRQQueueHandle;
                        break;
                    case batteryLevelUp:
                        notification = static_cast<std::uint8_t>(batteryIRQSource::INTB);
                        IRQSrc       = topControllerIRQsource::FG_INT;
                        if (battLevel < fullBattery)
                            battLevel++;
                        else {
                            // second 100% in a row
                            if (plugged && Store::Battery::get().level == fullBattery) {
                                Store::Battery::modify().state = Store::Battery::State::ChargingDone;
                            }
                        }
                        batteryLevel++;
                        targetQueueHandle = IRQQueueHandle;
                        break;
                    case batteryLevelDown:
                        notification = static_cast<std::uint8_t>(batteryIRQSource::INTB);
                        IRQSrc       = topControllerIRQsource::FG_INT;
                        if (battLevel >= 1)
                            battLevel--;
                        if (plugged && Store::Battery::get().level == fullBattery) {
                            // charging but not 100% anymore
                            Store::Battery::modify().state = Store::Battery::State::Charging;
                        }
                        batteryLevel--;
                        targetQueueHandle = IRQQueueHandle;
                        break;
                    case chargerTypeDcdSDP:
                        notification      = static_cast<std::uint8_t>(batteryChargerType::DcdSDP);
                        notification      = static_cast<std::uint8_t>(USBSourceType::DcdSDP);
                        targetQueueHandle = DCDQueueHandle;
                        break;
                    case chargerTypeDcdCDP:
                        notification      = static_cast<std::uint8_t>(batteryChargerType::DcdCDP);
                        notification      = static_cast<std::uint8_t>(USBSourceType::DcdCDP);
                        targetQueueHandle = DCDQueueHandle;
                        break;
                    case chargerTypeDcdDCP:
                        notification      = static_cast<std::uint8_t>(batteryChargerType::DcdDCP);
                        notification      = static_cast<std::uint8_t>(USBSourceType::DcdDCP);
                        targetQueueHandle = DCDQueueHandle;
                        break;
                    default:


@@ 101,102 101,52 @@ namespace bsp::battery_charger
        }
    } // namespace

    int init(xQueueHandle irqQueueHandle, xQueueHandle dcdQueueHandle)
    LinuxBatteryCharger::LinuxBatteryCharger(sys::Service *service) : service{service}
    {}

    void LinuxBatteryCharger::init(xQueueHandle irqQueueHandle, xQueueHandle dcdQueueHandle)
    {
        IRQQueueHandle = irqQueueHandle;
        DCDQueueHandle = dcdQueueHandle;

        if (xTaskCreate(battery_worker, "battery", 512, nullptr, 0, &batteryWorkerHandle) != pdPASS) {
            return 1;
        }
        Store::Battery::modify().level = battLevel;

        return 0;
        xTaskCreate(batteryWorker, "battery", 512, nullptr, 0, &batteryWorkerHandle);
        Store::Battery::modify().level = batteryLevel;
    }

    void deinit()
    void LinuxBatteryCharger::deinit()
    {
        IRQQueueHandle = nullptr;
        DCDQueueHandle = nullptr;
        vTaskDelete(batteryWorkerHandle);
    }

    StateOfCharge getBatteryLevel()
    void LinuxBatteryCharger::processStateChangeNotification(std::uint8_t notification)
    {
        Store::Battery::modify().level = battLevel;
        return battLevel;
    }

    bool getChargeStatus()
    {
        bool status = plugged;
        if (status) {
            Store::Battery::modify().state = Store::Battery::State::Charging;
        if (isPlugged) {
            if (batteryLevel > fullBattery) {
                if (isPlugged && Store::Battery::get().level == fullBattery) {
                    Store::Battery::modify().state = Store::Battery::State::ChargingDone;
                }
            }
            else {
                Store::Battery::modify().state = Store::Battery::State::Charging;
            }
        }
        else {
            Store::Battery::modify().state = Store::Battery::State::Discharging;
        }
        return status;
    }

    // TODO function unused in linux driver, left for compatibility with target driver
    void clearAllChargerIRQs()
    {}
    // TODO function unused in linux driver, left for compatibility with target driver
    void clearFuelGuageIRQ(std::uint16_t)
    {}

    std::uint16_t getStatusRegister()
    {
        return static_cast<std::uint16_t>(batteryINTBSource::SOCOnePercentChange);
    }

    std::uint8_t getTopControllerINTSource()
    {
        return static_cast<std::uint8_t>(IRQSrc);
    }

    void checkTemperatureRange()
    {}

    void setUSBCurrentLimit(batteryChargerType chargerType)
    {
        switch (chargerType) {
        case batteryChargerType::DcdTimeOut:
            [[fallthrough]];
        case batteryChargerType::DcdUnknownType:
            [[fallthrough]];
        case batteryChargerType::DcdError:
            [[fallthrough]];
        case batteryChargerType::DcdSDP:
            LOG_INFO("USB current limit set to 500mA");
            break;
        case batteryChargerType::DcdCDP:
            [[fallthrough]];
        case batteryChargerType::DcdDCP:
            LOG_INFO("USB current limit set to 1000mA");
            break;
        }
    }

    void actionIfChargerUnplugged()
    {
        if (Store::Battery::get().state == Store::Battery::State::Discharging) {
            LOG_INFO("USB unplugged");
        }
    }
        batteryLevel                   = std::clamp(batteryLevel, unsigned{0}, fullBattery);
        Store::Battery::modify().level = batteryLevel;
        battery_level_check::checkBatteryLevel();

    int getVoltageFilteredMeasurement()
    {
        constexpr auto nominalVoltage = 4350;
        return nominalVoltage;
        auto message = std::make_shared<sevm::BatteryStatusChangeMessage>();
        service->bus.sendUnicast(std::move(message), service::name::evt_manager);
    }

    void printFuelGaugeInfo()
    {}

    BaseType_t INTB_IRQHandler()
    void LinuxBatteryCharger::setChargingCurrentLimit(std::uint8_t usbType)
    {
        return 1;
        auto usbTypeStr = magic_enum::enum_name(static_cast<USBSourceType>(usbType));
        LOG_INFO("Setup charging current for usb source type: %s", usbTypeStr.data());
    }

} // namespace bsp::battery_charger
} // namespace hal::battery

A module-bsp/board/linux/hal/battery_charger/BatteryCharger.hpp => module-bsp/board/linux/hal/battery_charger/BatteryCharger.hpp +24 -0
@@ 0,0 1,24 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#include <module-bsp/hal/battery_charger/AbstractBatteryCharger.hpp>

#include <memory>

namespace hal::battery
{
    class LinuxBatteryCharger : public AbstractBatteryCharger
    {
      public:
        explicit LinuxBatteryCharger(sys::Service *service);
        void init(xQueueHandle irqQueueHandle, xQueueHandle dcdQueueHandle) final;
        void deinit() final;
        void processStateChangeNotification(std::uint8_t notification) final;
        void setChargingCurrentLimit(std::uint8_t usbType) final;

      private:
        sys::Service *service;
    };
} // namespace hal::battery

M module-bsp/board/rt1051/CMakeLists.txt => module-bsp/board/rt1051/CMakeLists.txt +0 -1
@@ 8,7 8,6 @@ target_sources(module-bsp
		bluetooth/BluetoothCommon.cpp
		bsp/audio/CodecMAX98090.cpp
		bsp/audio/qfilter.c
		bsp/battery-charger/battery_charger.cpp
		bsp/cellular/rt1051_cellular.cpp
		bsp/eeprom/eeprom.cpp
		bsp/eink_frontlight/eink_frontlight.cpp

M module-bsp/board/rt1051/bellpx/CMakeLists.txt => module-bsp/board/rt1051/bellpx/CMakeLists.txt +1 -0
@@ 11,6 11,7 @@ target_sources(

    PRIVATE
        hal/temperature_source/TemperatureSource.cpp
        hal/battery_charger/BatteryCharger.cpp

    PUBLIC
        eink-config.h

A module-bsp/board/rt1051/bellpx/hal/battery_charger/BatteryCharger.cpp => module-bsp/board/rt1051/bellpx/hal/battery_charger/BatteryCharger.cpp +50 -0
@@ 0,0 1,50 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "BatteryCharger.hpp"

#include <hal/GenericFactory.hpp>
#include <EventStore.hpp>
#include <service-evtmgr/battery-level-check/BatteryLevelCheck.hpp>
#include <service-evtmgr/BatteryMessages.hpp>
#include <service-evtmgr/EventManagerCommon.hpp>
namespace hal::battery
{
    std::shared_ptr<AbstractBatteryCharger> AbstractBatteryCharger::Factory::create(sys::Service *service)
    {
        return hal::impl::factory<BatteryCharger, AbstractBatteryCharger>(service);
    }

    BatteryCharger::BatteryCharger(sys::Service *service) : service{service}
    {}

    void BatteryCharger::init(xQueueHandle queueBatteryHandle, xQueueHandle)
    {
        // Mocking initial state to make system run
        Store::Battery::modify().state = Store::Battery::State::Discharging;
        Store::Battery::modify().level = 100;
        auto message                   = std::make_shared<sevm::BatteryStatusChangeMessage>();
        service->bus.sendUnicast(std::move(message), service::name::evt_manager);
    }

    void BatteryCharger::BatteryCharger::deinit()
    {}

    void BatteryCharger::processStateChangeNotification(std::uint8_t notification)
    {}

    void BatteryCharger::setChargingCurrentLimit(std::uint8_t)
    {}

    BaseType_t IRQHandler()
    {
        return 0;
    }

    extern "C"
    {
        void USB_ChargerDetectedCB(std::uint8_t)
        {}
    }

} // namespace hal::battery

A module-bsp/board/rt1051/bellpx/hal/battery_charger/BatteryCharger.hpp => module-bsp/board/rt1051/bellpx/hal/battery_charger/BatteryCharger.hpp +24 -0
@@ 0,0 1,24 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#include <module-bsp/hal/battery_charger/AbstractBatteryCharger.hpp>

#include <memory>

namespace hal::battery
{
    class BatteryCharger : public AbstractBatteryCharger
    {
      public:
        explicit BatteryCharger(sys::Service *);
        void init(xQueueHandle queueBatteryHandle, xQueueHandle) final;
        void deinit() final;
        void processStateChangeNotification(std::uint8_t notification) final;
        void setChargingCurrentLimit(std::uint8_t) final;

      private:
        sys::Service *service;
    };
} // namespace hal::battery

M module-bsp/board/rt1051/common/irq/irq_gpio.cpp => module-bsp/board/rt1051/common/irq/irq_gpio.cpp +2 -2
@@ 9,7 9,7 @@
#include "fsl_common.h"

#include "board/rt1051/bsp/eink/bsp_eink.h"
#include "bsp/battery-charger/battery_charger.hpp"
#include <hal/battery_charger/AbstractBatteryCharger.hpp>
#include "bsp/cellular/bsp_cellular.hpp"
#include "bsp/keyboard/keyboard.hpp"
#include "bsp/headset/headset.hpp"


@@ 118,7 118,7 @@ namespace bsp
            if (irq_mask & (1 << BOARD_BATTERY_CHARGER_WCINOKB_PIN)) {}

            if (irq_mask & (1 << BOARD_BATTERY_CHARGER_INTB_PIN)) {
                xHigherPriorityTaskWoken |= bsp::battery_charger::INTB_IRQHandler();
                xHigherPriorityTaskWoken |= hal::battery::IRQHandler();
            }

            if (irq_mask & (1 << BSP_CELLULAR_SIM_TRAY_INSERTED_PIN)) {

M module-bsp/board/rt1051/puretx/CMakeLists.txt => module-bsp/board/rt1051/puretx/CMakeLists.txt +5 -0
@@ 8,6 8,11 @@ target_include_directories(

target_sources(
        module-bsp

    PRIVATE
        hal/battery_charger/BatteryCharger.cpp
        bsp/battery_charger/battery_charger.cpp
        
    PUBLIC
        eink-config.h
)

R module-bsp/board/rt1051/bsp/battery-charger/MAX77818.hpp => module-bsp/board/rt1051/puretx/bsp/battery_charger/MAX77818.hpp +0 -0
R module-bsp/board/rt1051/bsp/battery-charger/battery_charger.cpp => module-bsp/board/rt1051/puretx/bsp/battery_charger/battery_charger.cpp +15 -39
@@ 1,19 1,19 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "bsp/battery-charger/battery_charger.hpp"
#include "MAX77818.hpp"
#include "fsl_common.h"
#include "battery_charger.hpp"
#include "battery_charger_utils.hpp"

#include "bsp/BoardDefinitions.hpp"
#include <fsl_common.h>
#include <bsp/BoardDefinitions.hpp>
#include <EventStore.hpp>
#include "drivers/gpio/DriverGPIO.hpp"
#include "drivers/i2c/DriverI2C.hpp"
#include <drivers/gpio/DriverGPIO.hpp>
#include <drivers/i2c/DriverI2C.hpp>
#include <purefs/filesystem_paths.hpp>

#include <utility>
#include <fstream>
#include <map>
#include "battery_charger_utils.hpp"

namespace bsp::battery_charger
{


@@ 224,14 224,6 @@ namespace bsp::battery_charger
            }
        }

        void setMaxBusCurrent(USBCurrentLimit limit)
        {
            const auto value = static_cast<std::uint8_t>(limit);
            if (chargerWrite(Registers::CHG_CNFG_09, value) != kStatus_Success) {
                LOG_ERROR("Maximum usb current write fail");
            }
        }

        void setMaxChargeCurrent(ChargeCurrentLimit limit)
        {
            unlockProtectedChargerRegisters();


@@ 705,24 697,11 @@ namespace bsp::battery_charger
        return value.second;
    }

    void setUSBCurrentLimit(batteryChargerType chargerType)
    void setMaxBusCurrent(USBCurrentLimit limit)
    {
        switch (chargerType) {
        case batteryChargerType::DcdTimeOut:
            [[fallthrough]];
        case batteryChargerType::DcdUnknownType:
            [[fallthrough]];
        case batteryChargerType::DcdError:
            [[fallthrough]];
        case batteryChargerType::DcdSDP:
            resetUSBCurrrentLimit();
            break;
        case batteryChargerType::DcdCDP:
            [[fallthrough]];
        case batteryChargerType::DcdDCP:
            LOG_INFO("USB current limit set to 1000mA");
            setMaxBusCurrent(USBCurrentLimit::lim1000mA);
            break;
        const auto value = static_cast<std::uint8_t>(limit);
        if (chargerWrite(Registers::CHG_CNFG_09, value) != kStatus_Success) {
            LOG_ERROR("Maximum usb current write fail");
        }
    }



@@ 791,14 770,11 @@ namespace bsp::battery_charger
        return xHigherPriorityTaskWoken;
    }

    extern "C"
    void USBChargerDetectedHandler(std::uint8_t detectedType)
    {
        void USB_ChargerDetectedCB(std::uint8_t detectedType)
        {
            if (DCDQueueHandle != nullptr) {
                std::uint8_t val = static_cast<std::uint8_t>(detectedType);
                xQueueSend(DCDQueueHandle, &val, portMAX_DELAY);
            }
        if (DCDQueueHandle != nullptr) {
            std::uint8_t val = static_cast<std::uint8_t>(detectedType);
            xQueueSend(DCDQueueHandle, &val, portMAX_DELAY);
        }
    }
} // namespace bsp::battery_charger

R module-bsp/bsp/battery-charger/battery_charger.hpp => module-bsp/board/rt1051/puretx/bsp/battery_charger/battery_charger.hpp +15 -15
@@ 3,6 3,8 @@

#pragma once

#include "MAX77818.hpp"

#include <cstdint>
extern "C"
{


@@ 17,6 19,16 @@ namespace bsp::battery_charger
{
    using StateOfCharge = std::uint8_t;

    enum class batteryChargerType
    {
        DcdTimeOut = 0x00U, /*!< Dcd detect result is timeout */
        DcdUnknownType,     /*!< Dcd detect result is unknown type */
        DcdError,           /*!< Dcd detect result is error*/
        DcdSDP,             /*!< The SDP facility is detected */
        DcdCDP,             /*!< The CDP facility is detected */
        DcdDCP,             /*!< The DCP facility is detected */
    };

    enum class batteryRetval
    {
        OK,


@@ 48,16 60,6 @@ namespace bsp::battery_charger
        all                 = 0xFFFF
    };

    enum class batteryChargerType
    {
        DcdTimeOut = 0x00U, /*!< Dcd detect result is timeout */
        DcdUnknownType,     /*!< Dcd detect result is unknown type */
        DcdError,           /*!< Dcd detect result is error*/
        DcdSDP,             /*!< The SDP facility is detected */
        DcdCDP,             /*!< The CDP facility is detected */
        DcdDCP,             /*!< The DCP facility is detected */
    };

    struct MaxMinVolt
    {
        unsigned minMilliVolt{0};


@@ 82,7 84,7 @@ namespace bsp::battery_charger

    std::uint8_t getTopControllerINTSource();

    void setUSBCurrentLimit(batteryChargerType chargerType);
    void setMaxBusCurrent(USBCurrentLimit limit);

    void actionIfChargerUnplugged();



@@ 96,8 98,6 @@ namespace bsp::battery_charger

    BaseType_t INTB_IRQHandler();

    extern "C"
    {
        void USB_ChargerDetectedCB(std::uint8_t detectedType);
    }
    void USBChargerDetectedHandler(std::uint8_t detectedType);

} // namespace bsp::battery_charger

R module-bsp/board/rt1051/bsp/battery-charger/battery_charger_utils.hpp => module-bsp/board/rt1051/puretx/bsp/battery_charger/battery_charger_utils.hpp +0 -0
A module-bsp/board/rt1051/puretx/hal/battery_charger/BatteryCharger.cpp => module-bsp/board/rt1051/puretx/hal/battery_charger/BatteryCharger.cpp +128 -0
@@ 0,0 1,128 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "BatteryCharger.hpp"

#include <hal/GenericFactory.hpp>

#include <bsp/battery_charger/battery_charger.hpp>
#include <service-evtmgr/battery-level-check/BatteryLevelCheck.hpp>
#include <service-evtmgr/BatteryMessages.hpp>
#include <SystemManager/SystemManagerCommon.hpp>
#include <service-evtmgr/EventManagerCommon.hpp>

namespace hal::battery
{
    std::shared_ptr<AbstractBatteryCharger> AbstractBatteryCharger::Factory::create(sys::Service *service)
    {
        return hal::impl::factory<BatteryCharger, AbstractBatteryCharger>(service);
    }

    BatteryCharger::BatteryCharger(sys::Service *service)
        : service{service}, batteryBrownoutDetector{
                                service,
                                []() { return bsp::battery_charger::getVoltageFilteredMeasurement(); },
                                [service]() {
                                    auto messageBrownout = std::make_shared<sevm::BatteryBrownoutMessage>();
                                    service->bus.sendUnicast(std::move(messageBrownout), service::name::system_manager);
                                },
                                [this]() { checkBatteryChargerInterrupts(); }}
    {}

    void BatteryCharger::init(xQueueHandle queueBatteryHandle, xQueueHandle queueChargerDetect)
    {
        bsp::battery_charger::init(queueBatteryHandle, queueChargerDetect);
    }

    void BatteryCharger::BatteryCharger::deinit()
    {
        bsp::battery_charger::deinit();
    }

    void BatteryCharger::processStateChangeNotification(std::uint8_t notification)
    {
        if (notification == static_cast<std::uint8_t>(bsp::battery_charger::batteryIRQSource::INTB)) {
            checkBatteryChargerInterrupts();
        }
    }

    void BatteryCharger::setChargingCurrentLimit(std::uint8_t chargerType)
    {
        using namespace bsp::battery_charger;
        switch (static_cast<batteryChargerType>(chargerType)) {
        case batteryChargerType::DcdTimeOut:
            [[fallthrough]];
        case batteryChargerType::DcdUnknownType:
            [[fallthrough]];
        case batteryChargerType::DcdError:
            [[fallthrough]];
        case batteryChargerType::DcdSDP:
            setMaxBusCurrent(USBCurrentLimit::lim500mA);
            break;
        case batteryChargerType::DcdCDP:
            [[fallthrough]];
        case batteryChargerType::DcdDCP:
            LOG_INFO("USB current limit set to 1000mA");
            setMaxBusCurrent(USBCurrentLimit::lim1000mA);
            break;
        }
    }

    void BatteryCharger::checkBatteryChargerInterrupts()
    {
        auto topINT = bsp::battery_charger::getTopControllerINTSource();
        if (topINT & static_cast<std::uint8_t>(bsp::battery_charger::topControllerIRQsource::CHGR_INT)) {
            bsp::battery_charger::getChargeStatus();
            bsp::battery_charger::actionIfChargerUnplugged();
            auto message = std::make_shared<sevm::BatteryStatusChangeMessage>();
            service->bus.sendUnicast(std::move(message), service::name::evt_manager);
            battery_level_check::checkBatteryLevel();
            bsp::battery_charger::clearAllChargerIRQs();
        }
        if (topINT & static_cast<std::uint8_t>(bsp::battery_charger::topControllerIRQsource::FG_INT)) {
            const auto status = bsp::battery_charger::getStatusRegister();
            if (status & static_cast<std::uint16_t>(bsp::battery_charger::batteryINTBSource::minVAlert)) {
                batteryBrownoutDetector.startDetection();
                bsp::battery_charger::clearFuelGuageIRQ(
                    static_cast<std::uint16_t>(bsp::battery_charger::batteryINTBSource::minVAlert));
            }
            if (status & static_cast<std::uint16_t>(bsp::battery_charger::batteryINTBSource::SOCOnePercentChange)) {
                bsp::battery_charger::printFuelGaugeInfo();
                bsp::battery_charger::clearFuelGuageIRQ(
                    static_cast<std::uint16_t>(bsp::battery_charger::batteryINTBSource::SOCOnePercentChange));
                bsp::battery_charger::getBatteryLevel();
                auto message = std::make_shared<sevm::BatteryStatusChangeMessage>();
                service->bus.sendUnicast(std::move(message), service::name::evt_manager);
                battery_level_check::checkBatteryLevel();
            }
            if (status & static_cast<std::uint16_t>(bsp::battery_charger::batteryINTBSource::maxTemp) ||
                status & static_cast<std::uint16_t>(bsp::battery_charger::batteryINTBSource::minTemp)) {
                bsp::battery_charger::clearFuelGuageIRQ(
                    static_cast<std::uint16_t>(bsp::battery_charger::batteryINTBSource::maxTemp) |
                    static_cast<std::uint16_t>(bsp::battery_charger::batteryINTBSource::minTemp));
                bsp::battery_charger::checkTemperatureRange();
                bsp::battery_charger::getChargeStatus();
                auto message = std::make_shared<sevm::BatteryStatusChangeMessage>();
                service->bus.sendUnicast(std::move(message), service::name::evt_manager);
                battery_level_check::checkBatteryLevel();
            }
            // Clear other unsupported IRQ sources just in case
            bsp::battery_charger::clearFuelGuageIRQ(
                static_cast<std::uint16_t>(bsp::battery_charger::batteryINTBSource::all));
        }
    }

    BaseType_t IRQHandler()
    {
        return bsp::battery_charger::INTB_IRQHandler();
    }

    extern "C"
    {
        void USB_ChargerDetectedCB(std::uint8_t detectedType)
        {
            bsp::battery_charger::USBChargerDetectedHandler(detectedType);
        }
    }

} // namespace hal::battery

A module-bsp/board/rt1051/puretx/hal/battery_charger/BatteryCharger.hpp => module-bsp/board/rt1051/puretx/hal/battery_charger/BatteryCharger.hpp +28 -0
@@ 0,0 1,28 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#include <module-bsp/hal/battery_charger/AbstractBatteryCharger.hpp>
#include <service-evtmgr/battery-brownout-detector/BatteryBrownoutDetector.hpp>

#include <memory>

namespace hal::battery
{
    class BatteryCharger : public AbstractBatteryCharger
    {
      public:
        explicit BatteryCharger(sys::Service *service);
        void init(xQueueHandle queueBatteryHandle, xQueueHandle queueChargerDetect) final;
        void deinit() final;
        void processStateChangeNotification(std::uint8_t notification) final;
        void setChargingCurrentLimit(std::uint8_t chargerType) final;

      private:
        void checkBatteryChargerInterrupts();

        sys::Service *service;
        BatteryBrownoutDetector batteryBrownoutDetector;
    };
} // namespace hal::battery

A module-bsp/hal/battery_charger/AbstractBatteryCharger.hpp => module-bsp/hal/battery_charger/AbstractBatteryCharger.hpp +35 -0
@@ 0,0 1,35 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#include <FreeRTOS.h>
#include <queue.h>
#include <Service/Service.hpp>

#include <memory>

namespace hal::battery
{
    class AbstractBatteryCharger
    {
      public:
        struct Factory
        {
            static std::shared_ptr<AbstractBatteryCharger> create(sys::Service *service);
        };

        virtual ~AbstractBatteryCharger() = default;

        virtual void init(xQueueHandle, xQueueHandle)             = 0;
        virtual void deinit()                                     = 0;
        virtual void processStateChangeNotification(std::uint8_t) = 0;
        virtual void setChargingCurrentLimit(std::uint8_t)        = 0;
    };

    BaseType_t IRQHandler();
    extern "C"
    {
        void USB_ChargerDetectedCB(std::uint8_t detectedType);
    }
} // namespace hal::battery

M module-bsp/tests/test-battery-charger-utils.cpp => module-bsp/tests/test-battery-charger-utils.cpp +1 -1
@@ 2,7 2,7 @@
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include <catch2/catch.hpp>
#include <module-bsp/board/rt1051/bsp/battery-charger/battery_charger_utils.hpp>
#include <module-bsp/board/rt1051/puretx/bsp/battery_charger/battery_charger_utils.hpp>

TEST_CASE("BatteryChargerUtilsTest")
{

M module-services/service-evtmgr/EventManager.cpp => module-services/service-evtmgr/EventManager.cpp +0 -1
@@ 18,7 18,6 @@
#include <SystemManager/SystemManagerCommon.hpp>
#include <bsp/common.hpp>
#include <bsp/rtc/rtc.hpp>
#include <bsp/battery-charger/battery_charger.hpp>
#include <bsp/keyboard/key_codes.hpp>
#include <log.hpp>
#include <Logger.hpp>

M module-services/service-evtmgr/WorkerEventCommon.cpp => module-services/service-evtmgr/WorkerEventCommon.cpp +13 -67
@@ 1,7 1,6 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "service-evtmgr/BatteryMessages.hpp"
#include "service-evtmgr/EVMessages.hpp"
#include "service-evtmgr/KbdMessage.hpp"
#include "service-evtmgr/Constants.hpp"


@@ 11,7 10,6 @@
#include <Audio/AudioCommon.hpp>
#include <MessageType.hpp>
#include <Service/Worker.hpp>
#include <bsp/battery-charger/battery_charger.hpp>
#include <bsp/cellular/bsp_cellular.hpp>
#include <bsp/keyboard/keyboard.hpp>
#include <bsp/magnetometer/magnetometer.hpp>


@@ 47,15 45,8 @@ extern "C"
#include <vector>      // for vector

WorkerEventCommon::WorkerEventCommon(sys::Service *service)
    : sys::Worker(service, stackDepthBytes), service(service),
      batteryBrownoutDetector(
          service,
          []() { return bsp::battery_charger::getVoltageFilteredMeasurement(); },
          [service]() {
              auto messageBrownout = std::make_shared<sevm::BatteryBrownoutMessage>();
              service->bus.sendUnicast(std::move(messageBrownout), service::name::system_manager);
          },
          [this]() { checkBatteryChargerInterrupts(); })
    : sys::Worker(service, stackDepthBytes),
      service(service), batteryCharger{hal::battery::AbstractBatteryCharger::Factory::create(service)}
{}

bool WorkerEventCommon::handleMessage(uint32_t queueID)


@@ 87,9 78,16 @@ bool WorkerEventCommon::handleMessage(uint32_t queueID)
        if (!queue->Dequeue(&notification, 0)) {
            return false;
        }
        if (notification == static_cast<std::uint8_t>(bsp::battery_charger::batteryIRQSource::INTB)) {
            checkBatteryChargerInterrupts();
        batteryCharger->processStateChangeNotification(notification);
    }

    if (queueID == static_cast<uint32_t>(WorkerEventQueues::queueChargerDetect)) {
        std::uint8_t notification;
        if (!queue->Dequeue(&notification, 0)) {
            return false;
        }
        LOG_DEBUG("USB charger type: %d", notification);
        batteryCharger->setChargingCurrentLimit(notification);
    }

    if (queueID == static_cast<uint32_t>(WorkerEventQueues::queueRTC)) {


@@ 107,14 105,6 @@ bool WorkerEventCommon::handleMessage(uint32_t queueID)
        service->bus.sendUnicast(message, service::name::evt_manager);
    }

    if (queueID == static_cast<uint32_t>(WorkerEventQueues::queueChargerDetect)) {
        std::uint8_t notification;
        if (!queue->Dequeue(&notification, 0)) {
            return false;
        }
        LOG_DEBUG("USB charger type: %d", notification);
        bsp::battery_charger::setUSBCurrentLimit(static_cast<bsp::battery_charger::batteryChargerType>(notification));
    }

    return true;
}


@@ 148,7 138,7 @@ bool WorkerEventCommon::initCommonHardwareComponents()
    bsp::keyboard::init(queues[static_cast<int32_t>(WorkerEventQueues::queueKeyboardIRQ)]->GetQueueHandle());
    auto queueBatteryHandle = queues[static_cast<int32_t>(WorkerEventQueues::queueBattery)]->GetQueueHandle();
    auto queueChargerDetect = queues[static_cast<int32_t>(WorkerEventQueues::queueChargerDetect)]->GetQueueHandle();
    bsp::battery_charger::init(queueBatteryHandle, queueChargerDetect);
    batteryCharger->init(queueBatteryHandle, queueChargerDetect);
    bsp::rtc::init(queues[static_cast<int32_t>(WorkerEventQueues::queueRTC)]->GetQueueHandle());

    time_t timestamp;


@@ 182,7 172,7 @@ bool WorkerEventCommon::deinit(void)
    deinitProductHardware();

    bsp::keyboard::deinit();
    bsp::battery_charger::deinit();
    batteryCharger->deinit();
    battery_level_check::deinit();

    return true;


@@ 224,50 214,6 @@ void WorkerEventCommon::processKeyEvent(bsp::KeyEvents event, bsp::KeyCodes code
    service->bus.sendUnicast(message, service::name::evt_manager);
}

void WorkerEventCommon::checkBatteryChargerInterrupts()
{
    auto topINT = bsp::battery_charger::getTopControllerINTSource();
    if (topINT & static_cast<std::uint8_t>(bsp::battery_charger::topControllerIRQsource::CHGR_INT)) {
        bsp::battery_charger::getChargeStatus();
        bsp::battery_charger::actionIfChargerUnplugged();
        auto message = std::make_shared<sevm::BatteryStatusChangeMessage>();
        service->bus.sendUnicast(std::move(message), service::name::evt_manager);
        battery_level_check::checkBatteryLevel();
        bsp::battery_charger::clearAllChargerIRQs();
    }
    if (topINT & static_cast<std::uint8_t>(bsp::battery_charger::topControllerIRQsource::FG_INT)) {
        const auto status = bsp::battery_charger::getStatusRegister();
        if (status & static_cast<std::uint16_t>(bsp::battery_charger::batteryINTBSource::minVAlert)) {
            batteryBrownoutDetector.startDetection();
            bsp::battery_charger::clearFuelGuageIRQ(
                static_cast<std::uint16_t>(bsp::battery_charger::batteryINTBSource::minVAlert));
        }
        if (status & static_cast<std::uint16_t>(bsp::battery_charger::batteryINTBSource::SOCOnePercentChange)) {
            bsp::battery_charger::printFuelGaugeInfo();
            bsp::battery_charger::clearFuelGuageIRQ(
                static_cast<std::uint16_t>(bsp::battery_charger::batteryINTBSource::SOCOnePercentChange));
            bsp::battery_charger::getBatteryLevel();
            auto message = std::make_shared<sevm::BatteryStatusChangeMessage>();
            service->bus.sendUnicast(std::move(message), service::name::evt_manager);
            battery_level_check::checkBatteryLevel();
        }
        if (status & static_cast<std::uint16_t>(bsp::battery_charger::batteryINTBSource::maxTemp) ||
            status & static_cast<std::uint16_t>(bsp::battery_charger::batteryINTBSource::minTemp)) {
            bsp::battery_charger::clearFuelGuageIRQ(
                static_cast<std::uint16_t>(bsp::battery_charger::batteryINTBSource::maxTemp) |
                static_cast<std::uint16_t>(bsp::battery_charger::batteryINTBSource::minTemp));
            bsp::battery_charger::checkTemperatureRange();
            bsp::battery_charger::getChargeStatus();
            auto message = std::make_shared<sevm::BatteryStatusChangeMessage>();
            service->bus.sendUnicast(std::move(message), service::name::evt_manager);
            battery_level_check::checkBatteryLevel();
        }
        // Clear other unsupported IRQ sources just in case
        bsp::battery_charger::clearFuelGuageIRQ(
            static_cast<std::uint16_t>(bsp::battery_charger::batteryINTBSource::all));
    }
}

void WorkerEventCommon::updateResourcesAfterCpuFrequencyChange(bsp::CpuFrequencyHz newFrequency)
{
    bsp::eink_frontlight::updateClockFrequency(newFrequency);

M module-services/service-evtmgr/service-evtmgr/WorkerEventCommon.hpp => module-services/service-evtmgr/service-evtmgr/WorkerEventCommon.hpp +2 -3
@@ 12,7 12,7 @@
#include <bsp/keyboard/key_codes.hpp>
#include <bsp/keyboard/key_codes.hpp>
#include <Service/CpuSentinel.hpp>
#include <module-services/service-evtmgr/battery-brownout-detector/BatteryBrownoutDetector.hpp>
#include <hal/battery_charger/AbstractBatteryCharger.hpp>

#include <cstdint>
#include <list>


@@ 81,7 81,7 @@ class WorkerEventCommon : public sys::Worker
    bsp::KeyEvents lastState  = bsp::KeyEvents::Released;
    bsp::KeyCodes lastPressed = static_cast<bsp::KeyCodes>(0);
    std::shared_ptr<sys::CpuSentinel> cpuSentinel;
    BatteryBrownoutDetector batteryBrownoutDetector;
    std::shared_ptr<hal::battery::AbstractBatteryCharger> batteryCharger;

  public:
    explicit WorkerEventCommon(sys::Service *service);


@@ 94,5 94,4 @@ class WorkerEventCommon : public sys::Worker
     * @param queueID Index of the queue in the queues vector.
     */
    bool handleMessage(uint32_t queueID) override;
    void checkBatteryChargerInterrupts();
};