Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
SoftPdmOut.cpp
00001 /******************************************************************************************************/ 00002 /* Pulse Density Modulation driver. */ 00003 /* FILE: PDM.cpp */ 00004 /* */ 00005 /* Code based on an article and source code released by Ken Wada from Aurium Technologies Inc. */ 00006 /* http://www.embedded.com/electronics-blogs/embedded-round-table/4414405/Pulse-density-modulation */ 00007 /* */ 00008 /******************************************************************************************************/ 00009 00010 #include "SoftPdmOut.h" 00011 00012 SoftPdmOut::SoftPdmOut(PinName pdm, uint32_t PulseWidth, uint32_t Dmax, float StartLevel) : _pdm(pdm), _PulseWidth(PulseWidth), _Dmax(Dmax) 00013 { 00014 _pdm = 0; 00015 _running = 0; 00016 if(StartLevel >= 0.0f && StartLevel <= 1.0f) _Level = (uint32_t)(StartLevel * (float)_Dmax); 00017 else _Level = 0; 00018 start(); 00019 } 00020 00021 void SoftPdmOut::start(void) 00022 { 00023 if (!_running) { 00024 // enable ONLY if state has changed 00025 _accumulator = 0; // zero out the error accumulator 00026 _running = 1; // NOW ... enable the controller 00027 _pdmTicker.attach_us(this,&SoftPdmOut::pdmTick,_PulseWidth); // Start the PDM. 00028 wait_ms(5); // Wait for output to settle 00029 } 00030 } 00031 00032 void SoftPdmOut::stop(bool idleState) 00033 { 00034 if (_running) { 00035 // disable ONLY if state has changed 00036 _running = 0; // disable the controller 00037 _pdmTicker.detach(); // Stop the PDM. 00038 _pdm = idleState; // Set output (default = 0) 00039 } 00040 } 00041 00042 void SoftPdmOut::PulseWidth(uint32_t level) 00043 { 00044 if(!_running) // When pdm is inactive, only change the pulse width and don't start the pdm 00045 _PulseWidth = level; 00046 else 00047 { 00048 stop(); 00049 _PulseWidth = level; 00050 start(); 00051 } 00052 } 00053 00054 uint32_t SoftPdmOut::getPulseWidth(void) 00055 { 00056 return _PulseWidth; 00057 } 00058 00059 void SoftPdmOut::Dmax(uint32_t level) 00060 { 00061 _Level = (uint32_t)((float)_Level * ((float)level / (float)_Dmax)); // Rescale level : level = level * (new level / current DMAX) 00062 _Dmax = level; 00063 _accumulator = 0; // zero out the error accumulator 00064 } 00065 00066 uint32_t SoftPdmOut::getDmax(void) 00067 { 00068 return _Dmax; 00069 } 00070 00071 void SoftPdmOut::write(float level) 00072 { 00073 // Only change the level when the desired level is within range 00074 if(level <= 0.0f) _Level = 0; 00075 else if(level >= 1.0f) _Level = _Dmax; 00076 else if (level > 0.0f && level < 1.0f) _Level = (uint32_t)(level * (float)_Dmax); 00077 } 00078 00079 float SoftPdmOut::read(void) 00080 { 00081 return ((float)_Level / (float)_Dmax); 00082 } 00083 00084 SoftPdmOut::operator float() 00085 { 00086 return read(); 00087 } 00088 00089 SoftPdmOut & SoftPdmOut::operator= (float value) 00090 { 00091 write(value); 00092 return(*this); 00093 } 00094 00095 void SoftPdmOut::pdmTick(void) 00096 { 00097 if(_Level == 0) { 00098 _pdm = 0; 00099 return; 00100 } 00101 if(_Level == _Dmax) { 00102 _pdm = 1; 00103 return; 00104 } 00105 _accumulator += _Level; // accumulate error integral 00106 if (_accumulator > _Dmax) { 00107 _accumulator -= _Dmax; 00108 _pdm = 1; 00109 } else 00110 _pdm = 0; 00111 }
Generated on Wed Jul 20 2022 00:19:18 by
1.7.2