Skip to content

File pwm.h

File List > external-docs > libDaisy > src > per > pwm.h

Go to the documentation of this file

Source Code

#pragma once
#ifndef DSY_PWM_H
#define DSY_PWM_H

#include "daisy_core.h"
#include "stm32h7xx_hal.h"
#include <cstdint>

namespace daisy
{
class PWMHandle
{
  public:
    class Impl;

    struct Config
    {
        enum class Peripheral
        {
            TIM_3 = 0, 
            TIM_4 = 1, 
            TIM_5 = 2  
        };
        Peripheral periph; 
        uint32_t prescaler;

        uint32_t period;

        Config() : periph(Peripheral::TIM_3), prescaler(0), period(0xffff) {}
        Config(Peripheral periph_,
               uint32_t   prescaler_ = 0,
               uint32_t   period_    = 0xffff)
        : periph(periph_), prescaler(prescaler_), period(period_)
        {
        }
    };

    enum class Result
    {
        OK  = 0,
        ERR = 1,
    };

    class Channel
    {
      public:
        struct Config
        {
            Pin pin;

            enum class Polarity
            {
                HIGH = 0, 
                LOW       
            };
            Polarity polarity;

            Config() : pin(), polarity(Polarity::HIGH) {}
            Config(Pin pin_, Polarity polarity_ = Polarity::HIGH)
            : pin(pin_), polarity(polarity_)
            {
            }
        };

        Channel(PWMHandle *owner, uint32_t channel)
        : owner_(*owner), channel_(channel), scale_(65535.0f), handle_(nullptr)
        {
        }

        inline const Config &GetConfig() const { return config_; }

        PWMHandle::Result Init(const Channel::Config &config);

        PWMHandle::Result Init();

        PWMHandle::Result DeInit();

        inline void SetRaw(uint32_t raw)
        {
            __HAL_TIM_SET_COMPARE(handle_, channel_, raw);
        }

        inline void Set(float val)
        {
            if(val < 0.0f)
                val = 0.0f;
            if(val > 1.0f)
                val = 1.0f;
            SetRaw(static_cast<uint32_t>(val * scale_));
        }

      private:
        PWMHandle &        owner_;
        const uint32_t     channel_;
        Channel::Config    config_;
        float              scale_;
        TIM_HandleTypeDef *handle_;
    };

    PWMHandle();

    PWMHandle(const PWMHandle &other) = default;
    PWMHandle &operator=(const PWMHandle &other) = default;
    ~PWMHandle() {}

    Result Init(const Config &config);

    Result DeInit();

    const Config &GetConfig() const;

    inline Channel &Channel1() { return ch1_; }

    inline Channel &Channel2() { return ch2_; }

    inline Channel &Channel3() { return ch3_; }

    inline Channel &Channel4() { return ch4_; };

    void SetPrescaler(uint32_t prescaler);

    void SetPeriod(uint32_t period);

  private:
    Impl *pimpl_;

    // NOTE: These are stored here, not in the Impl class, so that channel
    // references are valid even if taken before a call to PWMHandle::Init
    Channel ch1_;
    Channel ch2_;
    Channel ch3_;
    Channel ch4_;
};

} // namespace daisy

#endif