~aleteoryx/muditaos

ref: 317baa04e949a32ef1e72b2dd2b61c1e7a97ca25 muditaos/module-bsp/board/rt1051/drivers/RT1051DriverPWM.cpp -rw-r--r-- 4.8 KiB
317baa04 — Wojtek Rzepecki [BH-872] Fix encoder hadnling 4 years ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "RT1051DriverPWM.hpp"
#include "RT1051DriverPWMhelper.hpp"
#include <log/log.hpp>
#include "../board.h"
#include <algorithm>

namespace drivers
{
    RT1051DriverPWM::RT1051DriverPWM(PWMInstances inst, PWMModules mod, const DriverPWMParams &params)
        : DriverPWM(inst, mod, params)
    {

        pwm_config_t pwmConfig = {};

        switch (instance) {
        case PWMInstances::PWM_1:
            base = PWM1;
            LOG_DEBUG("Init: PWM1");
            break;
        case PWMInstances::PWM_2:
            base = PWM2;
            LOG_DEBUG("Init: PWM2");
            break;
        case PWMInstances::PWM_3:
            base = PWM3;
            LOG_DEBUG("Init: PWM3");
            break;
        case PWMInstances::PWM_4:
            base = PWM4;
            LOG_DEBUG("Init: PWM4");
            break;
        default:
            break;
        }

        switch (module) {
        case PWMModules::MODULE0:
            pwmModule = kPWM_Module_0;
            LOG_DEBUG("Init: PWM module 0");
            break;
        case PWMModules::MODULE1:
            pwmModule = kPWM_Module_1;
            LOG_DEBUG("Init: PWM module 1");
            break;
        case PWMModules::MODULE2:
            pwmModule = kPWM_Module_2;
            LOG_DEBUG("Init: PWM module 2");
            break;
        case PWMModules::MODULE3:
            pwmModule = kPWM_Module_3;
            LOG_DEBUG("Init: PWM module 3");
            break;
        default:
            break;
        }

        PWM_GetDefaultConfig(&pwmConfig);
        PWM_Init(base, pwmModule, &pwmConfig);

        SetupPWMChannel(parameters.channel);
        Start();
    }

    RT1051DriverPWM::~RT1051DriverPWM()
    {
        PWM_Deinit(base, pwmModule);
        LOG_DEBUG("Deinit: PWM");
    }

    void RT1051DriverPWM::SetDutyCycle(std::uint8_t dutyCyclePercent)
    {
        pwm_mode_t pwmMode = kPWM_SignedCenterAligned;

        std::uint8_t dutyCycle =
            std::clamp(dutyCyclePercent, static_cast<std::uint8_t>(0), static_cast<std::uint8_t>(100));
        pwmSignalConfig.dutyCyclePercent = dutyCycle;
        PWM_UpdatePwmDutycycle(base, pwmModule, pwmSignalConfig.pwmChannel, pwmMode, dutyCycle);
        PWM_SetPwmLdok(base, 1 << pwmModule, true);
    }

    void RT1051DriverPWM::Start()
    {
        RestorePwmOutput();
        PWM_StartTimer(base, 1 << pwmModule);
    }

    void RT1051DriverPWM::Stop()
    {
        PWM_StopTimer(base, 1 << pwmModule);
        ForceLowOutput();
    }

    RT1051DriverPWM::PwmState RT1051DriverPWM::GetPwmState()
    {
        if (PWM_GetPwmGeneratorState(base, 1 << pwmModule)) {
            return PwmState::On;
        }
        else {
            return PwmState::Off;
        }
    }

    void RT1051DriverPWM::SetupPWMChannel(PWMChannel channel)
    {
        switch (parameters.channel) {
        case PWMChannel::A:
            pwmSignalConfig.pwmChannel = kPWM_PwmA;
            LOG_DEBUG("Init: PWM channel A");
            break;
        case PWMChannel::B:
            pwmSignalConfig.pwmChannel = kPWM_PwmB;
            LOG_DEBUG("Init: PWM channel B");
            break;
        case PWMChannel::X:
            pwmSignalConfig.pwmChannel = kPWM_PwmX;
            LOG_DEBUG("Init: PWM channel X");
            break;
        }

        // Currently connected to IPbus clock
        const auto clockSource = CLOCK_GetFreq(kCLOCK_IpgClk);
        SetupPWMInstance(clockSource);

        PWM_SetupFaultDisableMap(base, pwmModule, pwmSignalConfig.pwmChannel, kPWM_faultchannel_0, 0);

        // Force logic config
        PWM_SetupSwCtrlOut(base, pwmModule, pwmSignalConfig.pwmChannel, false);
        base->SM[pwmModule].CTRL2 |= PWM_CTRL2_FRCEN(1U);
    }

    void RT1051DriverPWM::SetupPWMInstance(std::uint32_t clockFrequency)
    {
        pwm_mode_t pwmMode = kPWM_SignedCenterAligned;
        PWM_SetupPwm(base, pwmModule, &pwmSignalConfig, 1, pwmMode, parameters.frequency, clockFrequency);
    }

    void RT1051DriverPWM::ForceLowOutput()
    {
        PWM_SetupForceSignal(base, pwmModule, pwmSignalConfig.pwmChannel, kPWM_SoftwareControl);
        base->SM[pwmModule].CTRL2 |= PWM_CTRL2_FORCE(1U);
    }

    void RT1051DriverPWM::RestorePwmOutput()
    {
        PWM_SetupForceSignal(base, pwmModule, pwmSignalConfig.pwmChannel, kPWM_UsePwm);
        base->SM[pwmModule].CTRL2 |= PWM_CTRL2_FORCE(1U);
    }

    void RT1051DriverPWM::UpdateClockFrequency(std::uint32_t newFrequency)
    {
        cpp_freertos::LockGuard lock(frequencyChangeMutex);

        SetupPWMInstance(newFrequency);
        if (GetPwmState() == PwmState::On) {
            Stop();
            SetDutyCycle(pwmSignalConfig.dutyCyclePercent);
            Start();
        }
    }

} // namespace drivers