LCOV - code coverage report
Current view: top level - circuits - dc2dc.cpp (source / functions) Hit Total Coverage
Test: "4d72c01" Lines: 137 137 100.0 %
Date: 2024-02-24 14:56:23 Functions: 22 22 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 circuits/dc2dc.cpp
      12             :  * @brief Implementation of the DC To DC Converter Class.
      13             :  * 
      14             :  * @author Robson Martins (https://www.robsonmartins.com)
      15             :  */
      16             : // ---------------------------------------------------------------------------
      17             : 
      18             : #include "circuits/dc2dc.hpp"
      19             : 
      20             : constexpr float kDc2DcDefaultAdcBufferSize = 1000;
      21             : 
      22             : // ---------------------------------------------------------------------------
      23             : 
      24         325 : Dc2DcConfig::Dc2DcConfig():
      25         325 :         pwmPin(0xFF),
      26         325 :         pwmFreq(Pwm::kPwmDefaultFreq),
      27         325 :         adcVref(Adc::kAdcDefaultVRef),
      28         325 :         adcChannel(0xFF),
      29         325 :         divider(1.0f),
      30         325 :         pwmMinDuty(kPwmMinDutyCycleDefault),
      31         325 :         pwmMaxDuty(kPwmMaxDutyCycleDefault),
      32         325 :         pwmSlowStepDuty(kPwmSlowStepDutyCycleDefault),
      33         325 :         pwmFastStepDuty(kPwmFastStepDutyCycleDefault),
      34         325 :         pwmToleranceToFast(kPwmToleranceToFastDefault),
      35         325 :         vTolerance(kDc2DcVoutToleranceDefault) {}
      36             : 
      37           1 : Dc2DcConfig::Dc2DcConfig(uint pwmPin, uint adcChannel, float divider,
      38             :                          uint32_t pwmFreq, float adcVref,
      39             :                          float pwmMinDuty, float pwmMaxDuty,
      40             :                          float pwmSlowStepDuty, float pwmFastStepDuty,
      41           1 :                          float pwmToleranceToFast, float vTolerance):
      42           1 :         pwmPin(pwmPin),
      43           1 :         pwmFreq(pwmFreq),
      44           1 :         adcVref(adcVref),
      45           1 :         adcChannel(adcChannel),
      46           1 :         divider(divider),
      47           1 :         pwmMinDuty(pwmMinDuty),
      48           1 :         pwmMaxDuty(pwmMaxDuty),
      49           1 :         pwmSlowStepDuty(pwmSlowStepDuty),
      50           1 :         pwmFastStepDuty(pwmFastStepDuty),
      51           1 :         pwmToleranceToFast(pwmToleranceToFast),
      52           1 :         vTolerance(vTolerance) {}
      53             : 
      54          35 : Dc2DcConfig& Dc2DcConfig::operator=(const Dc2DcConfig& src) {
      55          35 :     this->pwmPin             =             src.pwmPin;
      56          35 :     this->pwmFreq            =            src.pwmFreq;
      57          35 :     this->adcVref            =            src.adcVref;
      58          35 :     this->adcChannel         =         src.adcChannel;
      59          35 :     this->divider            =            src.divider;
      60          35 :     this->pwmMinDuty         =         src.pwmMinDuty;
      61          35 :     this->pwmMaxDuty         =         src.pwmMaxDuty;
      62          35 :     this->pwmSlowStepDuty    =    src.pwmSlowStepDuty;
      63          35 :     this->pwmFastStepDuty    =    src.pwmFastStepDuty;
      64          35 :     this->pwmToleranceToFast = src.pwmToleranceToFast;
      65          35 :     this->vTolerance         =         src.vTolerance;
      66          35 :     return *this;
      67             : }
      68             : 
      69          12 : bool operator==(const Dc2DcConfig& a, const Dc2DcConfig& b) {
      70          21 :     return (a.pwmPin             ==             b.pwmPin &&
      71           9 :             a.pwmFreq            ==            b.pwmFreq &&
      72           9 :             a.adcVref            ==            b.adcVref &&
      73           9 :             a.adcChannel         ==         b.adcChannel &&
      74           9 :             a.divider            ==            b.divider &&
      75           9 :             a.pwmMinDuty         ==         b.pwmMinDuty &&
      76           9 :             a.pwmMaxDuty         ==         b.pwmMaxDuty &&
      77           9 :             a.pwmSlowStepDuty    ==    b.pwmSlowStepDuty &&
      78           9 :             a.pwmFastStepDuty    ==    b.pwmFastStepDuty &&
      79          30 :             a.pwmToleranceToFast == b.pwmToleranceToFast &&
      80          21 :             a.vTolerance         ==         b.vTolerance);
      81             : }
      82             : 
      83           1 : bool operator!=(const Dc2DcConfig& a, const Dc2DcConfig& b) {
      84           1 :     return !operator==(a, b);
      85             : }
      86             : 
      87             : // ---------------------------------------------------------------------------
      88             : 
      89         246 : Dc2Dc::Dc2Dc(): adc_(nullptr), pwm_(nullptr), vTarget_(0.0f),
      90         123 :         vActual_(0.0f), dutyActual_(0.0f), calibration_(0.0f) {}
      91             : 
      92           1 : Dc2Dc::Dc2Dc(const Dc2DcConfig& config): Dc2Dc() {
      93           1 :     configure(config);
      94           1 : }
      95             : 
      96         123 : Dc2Dc::~Dc2Dc() {
      97         123 :     stop();
      98         123 :     if (adc_) { delete adc_; }
      99         123 :     if (pwm_) { delete pwm_; }
     100         123 : }
     101             : 
     102          19 : void Dc2Dc::configure(const Dc2DcConfig& config) {
     103          19 :     bool configPwmPinEq  = (config.pwmPin  ==  config_.pwmPin);
     104          19 :     bool configAdcVrefEq = (config.adcVref == config_.adcVref);
     105          19 :     if (!configPwmPinEq || !configAdcVrefEq) { stop(); }
     106          19 :     if (!configAdcVrefEq && adc_) {
     107           1 :         delete adc_;
     108           1 :         adc_ = nullptr;
     109             :     }
     110          19 :     if (!configPwmPinEq  && pwm_) {
     111           3 :         delete pwm_;
     112           3 :         pwm_ = nullptr;
     113             :     }
     114          19 :     config_ = config;
     115          19 :     if (!adc_) { adc_ = new Adc(config_.adcVref); }
     116          19 :     if (!pwm_) { pwm_ = new Pwm(config_.pwmPin);  }
     117          19 :     pwm_->setFreq(config_.pwmFreq);
     118          19 : }
     119             : 
     120          14 : bool Dc2Dc::start() {
     121          14 :     if (isRunning()) { return true; }
     122          14 :     if (!isValidConfig_()) { return false; }
     123          14 :     pwm_->setDuty(config_.pwmMinDuty);
     124          14 :     pwm_->start();
     125          14 :     return true;
     126             : }
     127             : 
     128         155 : bool Dc2Dc::stop() {
     129         155 :     if (!isRunning()) { return true; }
     130          14 :     if (!isValidConfig_()) { return false; }
     131          14 :     pwm_->stop();
     132          14 :     return true;
     133             : }
     134             : 
     135      225581 : bool Dc2Dc::isRunning() const {
     136      225581 :     if (!pwm_) { return false; }
     137      225458 :     return pwm_->isRunning();
     138             : }
     139             : 
     140          89 : void Dc2Dc::setCalibration(float value) {
     141          89 :     calibration_ = value;
     142          89 : }
     143             : 
     144           6 : float Dc2Dc::getCalibration() const {
     145           6 :     return calibration_;
     146             : }
     147             : 
     148      225401 : void Dc2Dc::adjust() {
     149      225401 :     if (!isRunning()) {
     150           6 :         vActual_ = 0.0f;
     151           6 :         dutyActual_ = 0.0f;
     152           6 :         return;
     153             :     }
     154      225395 :     vActual_ = measureV_();
     155      225395 :     float duty = dutyActual_;
     156      225395 :     float vTargetMin = vTarget_ * (1.0f - config_.vTolerance);
     157      225395 :     float vTargetMax = vTarget_ * (1.0f + config_.vTolerance);
     158      225395 :     if (vActual_ < vTargetMin * (1.0f - config_.pwmToleranceToFast)) {
     159        1771 :         duty += config_.pwmFastStepDuty;
     160      223624 :     } else if (vActual_ > vTargetMax * (1.0f + config_.pwmToleranceToFast)) {
     161      220067 :         duty -= config_.pwmFastStepDuty;
     162        3557 :     } else if (vActual_ < vTargetMin) {
     163        1766 :         duty += config_.pwmSlowStepDuty;
     164        1791 :     } else if (vActual_ > vTargetMax) {
     165        1767 :         duty -= config_.pwmSlowStepDuty;
     166             :     }
     167      225395 :     if (duty > config_.pwmMaxDuty) { duty = config_.pwmMaxDuty; }
     168      225395 :     if (duty < config_.pwmMinDuty) { duty = config_.pwmMinDuty; }
     169      225395 :     if (duty != dutyActual_) {
     170        1974 :         dutyActual_ = duty;
     171        1974 :         pwm_->setDuty(dutyActual_);
     172             :     }
     173             : }
     174             : 
     175          16 : void Dc2Dc::setV(float v) {
     176          16 :     if (v < 0.0f) { v = 0.0f; }
     177          16 :     if (vTarget_ == v) { return; }
     178          16 :     vTarget_ = v;
     179             : }
     180             : 
     181          23 : float Dc2Dc::getV() const {
     182          23 :     return vActual_;
     183             : }
     184             : 
     185           6 : float Dc2Dc::getVTarget() const {
     186           6 :     return vTarget_;
     187             : }
     188             : 
     189           3 : float Dc2Dc::getDuty() const {
     190           3 :     return dutyActual_;
     191             : }
     192             : 
     193           4 : Dc2DcConfig Dc2Dc::getConfig() const {
     194           4 :     return config_;
     195             : }
     196             : 
     197          28 : bool Dc2Dc::isValidConfig_() const {
     198          28 :     return (config_.pwmPin != 0xFF
     199          28 :             && config_.pwmFreq != 0.0f
     200          56 :             && config_.adcChannel != 0xFF);
     201             : }
     202             : 
     203      225395 : float Dc2Dc::measureV_() const {
     204      225395 :     return (adc_->capture(config_.adcChannel, kDc2DcDefaultAdcBufferSize)
     205      225395 :         * config_.divider + calibration_);
     206             : }

Generated by: LCOV version 1.14