LCOV - code coverage report
Current view: top level - hal - pwm.cpp (source / functions) Hit Total Coverage
Test: "4d72c01" Lines: 48 48 100.0 %
Date: 2024-02-24 14:56:23 Functions: 12 12 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // ---------------------------------------------------------------------------
       2             : // USB EPROM/Flash Programmer
       3             : //
       4             : // Copyright (2022) Robson Martins
       5             : //
       6             : // This work is licensed under a Creative Commons Attribution-NonCommercial-
       7             : // ShareAlike 4.0 International License.
       8             : // ---------------------------------------------------------------------------
       9             : /**
      10             :  * @ingroup Firmware
      11             :  * @file hal/pwm.cpp
      12             :  * @brief Implementation of the Pico PWM Class.
      13             :  * 
      14             :  * @author Robson Martins (https://www.robsonmartins.com)
      15             :  */
      16             : // ---------------------------------------------------------------------------
      17             : 
      18             : #include <vector>
      19             : 
      20             : #include "hal/pwm.hpp"
      21             : 
      22             : #include "hardware/gpio.h"
      23             : #include "hardware/clocks.h"
      24             : #include "hardware/pwm.h"
      25             : 
      26             : // ---------------------------------------------------------------------------
      27             : 
      28             : // typical choose for RP PWM module clock: 12.5 MHz
      29             : constexpr uint32_t kPwmDefaultClock = 12'500'000UL;
      30             : 
      31             : // clksys: typically 125 MHz
      32             : // let's arbitrarily choose to run pwm clock at kPwmDefaultClock
      33             : float Pwm::divider_ = clock_get_hz(clk_sys) / kPwmDefaultClock;
      34             : 
      35             : // ---------------------------------------------------------------------------
      36             : 
      37          57 : Pwm::Pwm(uint pin): pin_(pin), freq_(0), duty_(0.0f), running_(false) {
      38          57 :     slice_ = pwm_gpio_to_slice_num(pin);
      39          57 :     channel_ = pwm_gpio_to_channel(pin);
      40          57 :     setFreq(kPwmDefaultFreq);
      41          57 : }
      42             : 
      43          57 : Pwm::~Pwm() {
      44          57 :     stop();
      45          57 : }
      46             : 
      47           1 : uint Pwm::getPin() const {
      48           1 :     return pin_;
      49             : }
      50             : 
      51           1 : uint Pwm::getSlice() const {
      52           1 :     return slice_;
      53             : }
      54             : 
      55           1 : uint Pwm::getChannel() const {
      56           1 :     return channel_;
      57             : }
      58             : 
      59          79 : void Pwm::setFreq(uint32_t freq) {
      60          79 :     if (!freq) { freq = 1; }
      61          79 :     if (freq > (kPwmDefaultClock / 2)) { freq = kPwmDefaultClock / 2; }
      62          79 :     if (freq == freq_) { return; }
      63             :     // set frequency
      64             :     // determine top given Hz - assumes free-running counter rather than
      65             :     // phase-correct
      66             :     // pwm clock should now be running at kPwmDefaultClock
      67          60 :     pwm_set_clkdiv(slice_, divider_);
      68          60 :     uint32_t top =  kPwmDefaultClock / freq -1;
      69          60 :     pwm_set_wrap(slice_, top);
      70          60 :     freq_ = freq;
      71             : }
      72             : 
      73           5 : uint32_t Pwm::getFreq() const {
      74           5 :     return freq_;
      75             : }
      76             : 
      77        1991 : void Pwm::setDuty(float duty) {
      78        1991 :     if (duty < 0.0f) duty = 0.0f;
      79        1991 :     if (duty > 100.0f) duty = 100.0f;
      80        1991 :     if (duty == duty_) { return; }
      81             :     // set duty cycle
      82        1977 :     uint32_t top =  kPwmDefaultClock / freq_ -1;
      83             :     // calculate channel level from given duty cycle in %
      84        1977 :     uint16_t level = (uint16_t)((top + 1.0f) * duty / 100.0f);
      85        1977 :     pwm_set_chan_level(slice_, channel_, level);
      86        1977 :     duty_ = duty;
      87             : }
      88             : 
      89           5 : float Pwm::getDuty() const {
      90           5 :     return duty_;
      91             : }
      92             : 
      93          16 : void Pwm::start() {
      94          16 :     if (running_) { return; }
      95             :     // set PWM function for pin
      96          16 :     gpio_set_function(pin_, GPIO_FUNC_PWM);
      97             :     // enable PWM
      98          16 :     pwm_set_enabled(slice_, true);
      99          16 :     running_ = true;
     100             : }
     101             : 
     102          73 : void Pwm::stop() {
     103          73 :     if (!running_) { return; }
     104             :     // disable PWM
     105          16 :     pwm_set_enabled(slice_, false);
     106             :     // set GPIO/SIO function for pin
     107          16 :     gpio_set_function(pin_, GPIO_FUNC_SIO);
     108             :     // reset state of pin (set to low)
     109          16 :     gpio_set_dir(pin_, GPIO_OUT);
     110          16 :     gpio_put(pin_, false);
     111          16 :     running_ = false;
     112             : }
     113             : 
     114      225465 : bool Pwm::isRunning() const {
     115      225465 :     return running_;
     116             : }

Generated by: LCOV version 1.14