~aleteoryx/muditaos

5aab08b515f22260bafcddbf273038dcde1f9ba4 — Lefucjusz 1 year, 2 months ago b83a325
[BH-2085] Modify PWM driver to handle duty cycles <1%

Modified current PWM driver implementation
so that PWM module is able to generate
signals with duty cycle below 1%. This is
needed to reduce frontlight brightness
for Harmony 2 Pro version.
M module-bsp/board/rt1051/bsp/eink_frontlight/eink_frontlight.cpp => module-bsp/board/rt1051/bsp/eink_frontlight/eink_frontlight.cpp +7 -4
@@ 10,15 10,18 @@ namespace bsp::eink_frontlight
{
    namespace
    {
        std::shared_ptr<drivers::DriverPWM> pwm;
        constexpr auto pwmOutputFrequencyHz = 5000;
        constexpr auto pwmChannel = static_cast<drivers::PWMChannel>(BoardDefinitions::EINK_FRONTLIGHT_PWM_CHANNEL);

        auto gammaFactor          = 2.5f;
        std::shared_ptr<drivers::DriverPWM> pwm;

        std::uint8_t gammaCorrection(BrightnessPercentage brightness)
        float gammaCorrection(BrightnessPercentage brightness)
        {
            std::clamp(brightness, 0.0f, 100.0f);
            return static_cast<std::uint8_t>(100 * std::pow((brightness / 100.0f), gammaFactor));
            constexpr auto minPercent = 0.0f;
            constexpr auto maxPercent = 100.0f;
            std::clamp(brightness, minPercent, maxPercent);
            return (maxPercent * std::pow(brightness / maxPercent, gammaFactor));
        }
    } // namespace


M module-bsp/board/rt1051/drivers/RT1051DriverPWM.cpp => module-bsp/board/rt1051/drivers/RT1051DriverPWM.cpp +37 -19
@@ 11,6 11,8 @@ namespace drivers
    namespace
    {
        constexpr auto pwmMode = kPWM_SignedCenterAligned;
        constexpr auto minPercent = 0.0f;
        constexpr auto maxPercent = 100.0f;

        inline bool isPwmGeneratorEnabled(PWM_Type *base, std::uint8_t pwmModuleToCheck)
        {


@@ 21,6 23,23 @@ namespace drivers
        {
            return CLOCK_GetFreq(kCLOCK_IpgClk);
        }

        inline constexpr std::uint16_t dutyCycleToReloadValue(float dutyCyclePercent)
        {
            constexpr auto maxPwmReloadValue = std::numeric_limits<std::uint16_t>::max();
            return static_cast<std::uint16_t>(maxPwmReloadValue * dutyCyclePercent / maxPercent);
        }

        inline void updatePwmDutyCycle(PWM_Type *base,
                                       pwm_submodule_t pwmModule,
                                       pwm_channels_t pwmChannel,
                                       pwm_mode_t currPwmMode,
                                       float dutyCyclePercent)
        {
            const auto reloadValue = dutyCycleToReloadValue(dutyCyclePercent);
            PWM_UpdatePwmDutycycleHighAccuracy(base, pwmModule, pwmChannel, currPwmMode, reloadValue);
            PWM_SetPwmLdok(base, 1 << pwmModule, true);
        }
    }

    RT1051DriverPWM::RT1051DriverPWM(PWMInstances inst, PWMModules mod, const DriverPWMParams &params)


@@ 93,20 112,18 @@ namespace drivers
        LOG_DEBUG("Deinit: PWM");
    }

    void RT1051DriverPWM::SetDutyCycle(std::uint8_t dutyCyclePercent, PWMChannel channel)
    void RT1051DriverPWM::SetDutyCycle(float dutyCyclePercent, PWMChannel channel)
    {
        const auto dutyCycle =
            std::clamp(dutyCyclePercent, static_cast<std::uint8_t>(0), static_cast<std::uint8_t>(100));
        const auto pwmChannel = getChannelMask(channel);
        std::clamp(dutyCyclePercent, minPercent, maxPercent);

        for (unsigned i = 0; i < enabledChannels.size(); ++i) {
        const auto pwmChannel = getChannelMask(channel);
        for (auto i = 0; i < enabledChannels.size(); ++i) {
            if (pwmSignalsConfig[i].pwmChannel == pwmChannel) {
                pwmSignalsConfig[i].dutyCyclePercent = dutyCycle;
                pwmSignalsConfig[i].dutyCyclePercent = dutyCyclePercent;
            }
        }

        PWM_UpdatePwmDutycycle(base, pwmModule, pwmChannel, pwmMode, dutyCycle);
        PWM_SetPwmLdok(base, 1 << pwmModule, true);
        updatePwmDutyCycle(base, pwmModule, pwmChannel, pwmMode, dutyCyclePercent);
    }

    void RT1051DriverPWM::Start(PWMChannel channel)


@@ 144,16 161,16 @@ namespace drivers
        const auto currentInstance = enabledChannels.size();
        const auto pwmChannel      = getChannelMask(channel);

        pwmSignalsConfig[currentInstance].pwmChannel       = pwmChannel;
        pwmSignalsConfig[currentInstance].dutyCyclePercent = 0;
        pwmSignalsConfig[currentInstance].level            = kPWM_HighTrue;
        pwmSignalsConfig[currentInstance].deadtimeValue    = 0;
        pwmSignalsConfig[currentInstance].faultState       = kPWM_PwmFaultState0;
        pwmSignalsConfig[currentInstance].pwmchannelenable = true;

        pwmSignalsConfig[currentInstance] = {.pwmChannel       = pwmChannel,
                                             .dutyCyclePercent = 0.0f,
                                             .level            = kPWM_HighTrue,
                                             .deadtimeValue    = 0,
                                             .faultState       = kPWM_PwmFaultState0,
                                             .pwmchannelenable = true};
        pwmModuleClockFrequency = getCurrentPwmSourceFrequency();
        SetupPWMInstance(&pwmSignalsConfig[currentInstance], 1, pwmModuleClockFrequency);

        auto pwmConfig = pwmSignalsConfig[currentInstance].getFslConfig();
        SetupPWMInstance(&pwmConfig, 1, pwmModuleClockFrequency);
        PWM_SetupFaultDisableMap(base, pwmModule, pwmChannel, kPWM_faultchannel_0, 0);

        // Force logic config


@@ 191,7 208,9 @@ namespace drivers
            return;
        }

        SetupPWMInstance(pwmSignalsConfig.data(), enabledChannels.size(), newSourceFrequency);
        /* Get any of the configs and use it for both channels; they differ only by PWM value setting */
        auto config = pwmSignalsConfig[0].getFslConfig();
        SetupPWMInstance(&config, enabledChannels.size(), newSourceFrequency);
        if (GetPwmState() == PwmState::On) {
            stopAll();
            restoreDutyCycle();


@@ 258,9 277,8 @@ namespace drivers
    void RT1051DriverPWM::restoreDutyCycle()
    {
        for (auto i = 0; i < enabledChannels.size(); ++i) {
            PWM_UpdatePwmDutycycle(
            updatePwmDutyCycle(
                base, pwmModule, pwmSignalsConfig[i].pwmChannel, pwmMode, pwmSignalsConfig[i].dutyCyclePercent);
            PWM_SetPwmLdok(base, 1 << pwmModule, true);
        }
    }
} // namespace drivers

M module-bsp/board/rt1051/drivers/RT1051DriverPWM.hpp => module-bsp/board/rt1051/drivers/RT1051DriverPWM.hpp +33 -12
@@ 21,17 21,17 @@ namespace drivers
      public:
        RT1051DriverPWM(PWMInstances inst, PWMModules mod, const DriverPWMParams &params);

        ~RT1051DriverPWM();
        ~RT1051DriverPWM() override;

        void InitNextChannel(const DriverPWMParams &params);
        void InitNextChannel(const DriverPWMParams &params) override;

        void SetDutyCycle(std::uint8_t dutyCyclePercent, PWMChannel channel);
        void SetDutyCycle(float dutyCyclePercent, PWMChannel channel) override;

        void Start(PWMChannel channel);
        void Start(PWMChannel channel) override;

        void Stop(PWMChannel channel);
        void Stop(PWMChannel channel) override;

        void UpdateClockFrequency();
        void UpdateClockFrequency() override;

        enum class PwmState
        {


@@ 40,6 40,28 @@ namespace drivers
        };

      private:
        struct PwmSignalConfig
        {
          public:
            pwm_channels_t pwmChannel;
            float dutyCyclePercent;
            pwm_level_select_t level;
            std::uint16_t deadtimeValue;
            pwm_fault_state_t faultState;
            bool pwmchannelenable;

            constexpr pwm_signal_param_t getFslConfig()
            {
                pwm_signal_param_t config = {.pwmChannel       = pwmChannel,
                                             .dutyCyclePercent = static_cast<std::uint8_t>(dutyCyclePercent),
                                             .level            = level,
                                             .deadtimeValue    = deadtimeValue,
                                             .faultState       = faultState,
                                             .pwmchannelenable = pwmchannelenable};
                return config;
            }
        };

        PwmState GetPwmState();

        void SetupPWMChannel(PWMChannel channel);


@@ 62,19 84,18 @@ namespace drivers

        void restoreDutyCycle();

        PWM_Type *base = nullptr;
        PWM_Type *base{nullptr};

        pwm_submodule_t pwmModule = kPWM_Module_0;
        pwm_submodule_t pwmModule{kPWM_Module_0};

        std::array<pwm_signal_param_t, 2> pwmSignalsConfig;
        std::array<PwmSignalConfig, 2> pwmSignalsConfig{};

        std::vector<PWMChannel> enabledChannels;
        std::map<PWMChannel, PwmState> pwmChannelState = {
        std::map<PWMChannel, PwmState> pwmChannelState{
            {PWMChannel::A, PwmState::Off}, {PWMChannel::B, PwmState::Off}, {PWMChannel::X, PwmState::Off}};

        cpp_freertos::MutexStandard frequencyChangeMutex;

        std::uint32_t pwmModuleClockFrequency = 0;
        std::uint32_t pwmModuleClockFrequency{0};
    };

} // namespace drivers

M module-bsp/drivers/pwm/DriverPWM.hpp => module-bsp/drivers/pwm/DriverPWM.hpp +1 -1
@@ 55,7 55,7 @@ namespace drivers
        virtual void InitNextChannel(const DriverPWMParams &params) = 0;

        // Duty cycle in percent: 0 - 100
        virtual void SetDutyCycle(std::uint8_t duty_cycle, PWMChannel channel) = 0;
        virtual void SetDutyCycle(float dutyCyclePercent, PWMChannel channel) = 0;

        virtual void Start(PWMChannel channel) = 0;