Skip to content
Snippets Groups Projects
Commit a101d2a1 authored by Alberto Nidasio's avatar Alberto Nidasio
Browse files

[PWM] New PWM driver

Still to change other drivers and to test but fairly identical to the previous one
parent 14e82524
No related merge requests found
...@@ -39,7 +39,8 @@ foreach(OPT_BOARD ${BOARDS}) ...@@ -39,7 +39,8 @@ foreach(OPT_BOARD ${BOARDS})
${SBS_BASE}/src/shared/drivers/hbridge/HBridge.cpp ${SBS_BASE}/src/shared/drivers/hbridge/HBridge.cpp
${SBS_BASE}/src/shared/drivers/i2c/stm32f2_f4_i2c.cpp ${SBS_BASE}/src/shared/drivers/i2c/stm32f2_f4_i2c.cpp
${SBS_BASE}/src/shared/drivers/interrupt/external_interrupts.cpp ${SBS_BASE}/src/shared/drivers/interrupt/external_interrupts.cpp
${SBS_BASE}/src/shared/drivers/pwm/pwm.cpp ${SBS_BASE}/src/shared/drivers/timer/PWM.cpp
${SBS_BASE}/src/shared/drivers/timer/TimestampTimer.cpp
${SBS_BASE}/src/shared/drivers/runcam/Runcam.cpp ${SBS_BASE}/src/shared/drivers/runcam/Runcam.cpp
${SBS_BASE}/src/shared/drivers/servo/servo.cpp ${SBS_BASE}/src/shared/drivers/servo/servo.cpp
${SBS_BASE}/src/shared/drivers/spi/SPITransaction.cpp ${SBS_BASE}/src/shared/drivers/spi/SPITransaction.cpp
...@@ -77,9 +78,6 @@ foreach(OPT_BOARD ${BOARDS}) ...@@ -77,9 +78,6 @@ foreach(OPT_BOARD ${BOARDS})
${SBS_BASE}/src/shared/sensors/UbloxGPS/UbloxGPS.cpp ${SBS_BASE}/src/shared/sensors/UbloxGPS/UbloxGPS.cpp
${SBS_BASE}/src/shared/sensors/VN100/VN100.cpp ${SBS_BASE}/src/shared/sensors/VN100/VN100.cpp
# Timer
${SBS_BASE}/src/shared/drivers/timer/TimestampTimer.cpp
# AeroUtils # AeroUtils
${SBS_BASE}/src/shared/utils/aero/AeroUtils.cpp ${SBS_BASE}/src/shared/utils/aero/AeroUtils.cpp
......
...@@ -47,7 +47,7 @@ public: ...@@ -47,7 +47,7 @@ public:
* RCC_APB1ENR_TIM4EN, // TIM4 enable bit on the APB1 enable register * RCC_APB1ENR_TIM4EN, // TIM4 enable bit on the APB1 enable register
* *
* // APB1 Clock speed * // APB1 Clock speed
* TimerUtils::getPrescalerInputFrequency(TimerUtils::InputClock::APB1) * TimerUtils::getPrescalerInputFrequency(TimerUtils::APB::APB1)
* }; * };
*/ */
struct Timer struct Timer
......
/* Copyright (c) 2017-2021 Skyward Experimental Rocketry
* Authors: Andrea Palumbo, Luca Erbetta, Alberto Nidasio
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "PWM.h"
namespace Boardcore
{
PWM::PWM(TIM_TypeDef *timer, unsigned int pwmFrequency,
unsigned int dutyCycleResolution)
: timer(timer), pwmFrequency(pwmFrequency),
dutyCycleResolution(dutyCycleResolution)
{
// TODO: Enable the peripheral clock
// Erase the previous timer configuration
this->timer.reset();
// Set up and enable the timer
setTimerConfiguration();
}
PWM::~PWM()
{
// TODO: Disable the peripheral clock
timer.reset();
}
void PWM::setFrequency(unsigned int pwmFrequency)
{
this->pwmFrequency = pwmFrequency;
setTimerConfiguration();
}
void PWM::setDutyCycleResolution(unsigned int dutyCycleResolution)
{
this->dutyCycleResolution = dutyCycleResolution;
setTimerConfiguration();
}
void PWM::enableChannel(GP16bitTimer::Channel channel, Polarity polarity)
{
timer.setOutputCompareMode(channel,
GP16bitTimer::OutputCompareMode::PWM_MODE_1);
timer.setCaptureComparePolarity(
channel, static_cast<GP16bitTimer::OutputComparePolarity>(polarity));
// This will ensure that the duty cycle will change only at the next period
timer.enableCaptureComparePreload(channel);
timer.enableCaptureCompareOutput(channel);
}
void PWM::disableChannel(GP16bitTimer::Channel channel)
{
timer.disableCaptureCompareOutput(channel);
}
bool PWM::isChannelEnabled(GP16bitTimer::Channel channel)
{
return timer.isCaptureComapreOutputEnabled(channel);
}
void PWM::setDutyCycle(GP16bitTimer::Channel channel, float dutyCycle)
{
if (dutyCycle >= 0 && dutyCycle <= 1)
timer.setCaptureCompareRegister(
channel,
static_cast<uint16_t>(dutyCycle * timer.readAutoReloadRegister()));
}
void PWM::setTimerConfiguration()
{
timer.disable();
timer.setCounter(0);
timer.setFrequency(dutyCycleResolution * pwmFrequency);
timer.setAutoReloadRegister(TimerUtils::getFrequency(timer.getTimer()) /
pwmFrequency);
// Force the timer to update its configuration
timer.generateUpdate();
timer.enable();
}
} // namespace Boardcore
/* Copyright (c) 2017-2021 Skyward Experimental Rocketry
* Authors: Andrea Palumbo, Luca Erbetta, Alberto Nidasio
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#pragma once
#include <drivers/timer/GeneralPurposeTimer.h>
namespace Boardcore
{
/**
* @brief Driver for easy access to the PWM capabilities of the general purpose
* timers.
*
* The PWM driver accepts a the pointer to the peripheral registers of a timer
* and uses it as a 16bit general purpose timer. No checks are in place to this
* pointer, thus make shure to pass a proper value!
*
* Moreover, even 32bit general purpose timers are used as if they where 16bit.
* At the moment there is no need for further accuracy but if it ever will be,
* exending this class is simble, just add a template parameter and pass it to
* the GeneralPurposeTimer parameter.
*/
class PWM
{
public:
enum class Polarity : uint16_t
{
NORMAL = 0, ///< Signal is high for the duty cycle time.
REVERSED = 0x1 ///< Signal is low for the duty cycle time.
};
/**
* @brief Sets up the PWM timer.
*
* @param timer Pointer to the timer's peripheral registers.
* @param pwmFrequency Frequency of the PWM signal.
* @param dutyCycleResolution Duty cycle levels.
*/
explicit PWM(TIM_TypeDef *timer, unsigned int pwmFrequency = 50,
unsigned int dutyCycleResolution = 65535);
~PWM();
void setFrequency(unsigned int pwmFrequency);
void setDutyCycleResolution(unsigned int dutyCycleResolution);
void enableChannel(GP16bitTimer::Channel channel,
Polarity polarity = Polarity::NORMAL);
void disableChannel(GP16bitTimer::Channel channel);
bool isChannelEnabled(GP16bitTimer::Channel channel);
/**
* @brief Sets the duty cycle for the specified channel.
*
* Changes the duty cycle only if the specified value is in the range [0,1].
*
* @param channel Channel to change the duty cycle
* @param dutyCycle Relative duty cycle, ranges from 0 to 1
*/
void setDutyCycle(GP16bitTimer::Channel channel, float dutyCycle);
private:
void setTimerConfiguration();
GP16bitTimer timer;
unsigned int pwmFrequency;
unsigned int dutyCycleResolution;
};
} // namespace Boardcore
...@@ -20,24 +20,21 @@ ...@@ -20,24 +20,21 @@
* THE SOFTWARE. * THE SOFTWARE.
*/ */
#include <drivers/pwm/pwm.h> #include <drivers/timer/PWM.h>
#include <drivers/timer/GeneralPurposeTimer.h> #include <miosix.h>
using namespace Boardcore;
using namespace miosix; using namespace miosix;
using namespace Boardcore;
// TODO: Update this test typedef Gpio<GPIOC_BASE, 8> ch2; // TIM8 CH2
typedef Gpio<GPIOG_BASE, 2> timeunit; // Signaling output
typedef Gpio<GPIOC_BASE, 8> ch2; // ch1
// typedef Gpio<GPIOD_BASE, 13> ch2; // ch2
typedef Gpio<GPIOG_BASE, 2> timeunit; // ch2
void sep() void sep()
{ {
timeunit::high(); timeunit::high();
Thread::sleep(25); delayMs(1);
timeunit::low(); timeunit::low();
Thread::sleep(100); delayMs(499);
} }
int main() int main()
...@@ -46,9 +43,6 @@ int main() ...@@ -46,9 +43,6 @@ int main()
{ {
FastInterruptDisableLock dLock; FastInterruptDisableLock dLock;
// ch1::mode(Mode::ALTERNATE);
// ch1::alternateFunction(2);
ch2::mode(Mode::ALTERNATE); ch2::mode(Mode::ALTERNATE);
ch2::alternateFunction(3); ch2::alternateFunction(3);
...@@ -58,41 +52,25 @@ int main() ...@@ -58,41 +52,25 @@ int main()
RCC->APB2ENR |= RCC_APB2ENR_TIM8EN; RCC->APB2ENR |= RCC_APB2ENR_TIM8EN;
TIM8->PSC = 1; PWM pwm(TIM8);
TIM8->CNT = 0;
TIM8->EGR |= TIM_EGR_UG;
TIM8->CR1 = TIM_CR1_CEN;
printf("%lu\n", TIM8->CNT); pwm.setDutyCycle(GP16bitTimer::Channel::CHANNEL_2, 0.9);
pwm.enableChannel(GP16bitTimer::Channel::CHANNEL_2);
PWM::Timer t{TIM8, &(RCC->APB2ENR), RCC_APB2ENR_TIM8EN,
ClockUtils::getAPBFrequecy(ClockUtils::APB::APB2)};
for (;;)
{
PWM pwm{t, 150};
sep(); sep();
pwm.start(); for (int i = 0; i < 10; i++)
sep(); {
pwm.enableChannel(PWMChannel::CH2, 0.3); pwm.setDutyCycle(GP16bitTimer::Channel::CHANNEL_2, 0.7);
sep(); sep();
pwm.setDutyCycle(PWMChannel::CH2, 0.7); pwm.setDutyCycle(GP16bitTimer::Channel::CHANNEL_2, 0.5);
sep(); sep();
pwm.stop(); pwm.setDutyCycle(GP16bitTimer::Channel::CHANNEL_2, 0.3);
sep(); sep();
} }
sep(); while (true)
while (1)
{
printf("End\n");
Thread::sleep(10000); Thread::sleep(10000);
} }
return 0;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment