PwmDAC is a library to run more the one PWM channel and channel updates at the time. Maximum PWM frequency is 48MHz. You can use for in example for rgb applications or as a multi channel dac with connected active lowpass. Written for mbed LPC1768. Not completly tested. I will upload my results as soon as possible. Although some deeper informations and LTSpice simulations
Dependents: DiscoTech filter_implement
PwmDAC.cpp
- Committer:
- flash_ahaa
- Date:
- 2013-09-15
- Revision:
- 0:13e0b9ea312f
- Child:
- 1:381bd99d10a4
File content as of revision 0:13e0b9ea312f:
#include "PwmDAC.h" #include "mbed.h" void PwmDAC::init() { _allActive = true; _resolution = 255; _frequency = (double) SYS_CLK / _resolution; _period = 1 / _frequency; for(int i = 0; i < 6; i++) { _pulsewidth[i] = 0.0; _duty[i] = 0.0; _steps[i] = 0; } LPC_SC->PCONP |= (1 << 6); // Bit 6 -> 1 == Poweron PWM1 LPC_SC->PCLKSEL0 |= (1 << 12); // Bit 13/12 -> 0/1 == Full clock 96MHz LPC_PINCON->PINSEL4 |= (1 << 0) | (1 << 2) | (1 << 4) | (1 << 6) | (1 << 8) | (1 << 10); // PWM on ch. 1-6 p26 p25 p24 p23 p22 p21 LPC_PINCON->PINMODE4 |= (2 << 0) | (2 << 2) | (2 << 4) | (2 << 6) | (2 << 8) | (2 << 10); // no pull up/ down p26 p25 p24 p23 p22 p21 // 0 - pull up enabled // 1 - repeater mode enabled // 2 - no pull up/down // 3 - pull down enabled LPC_PWM1->MCR = 2; // no reset, stop or interrupt on timer compare match // only TC reset on match with MR0 == new period of pwm cycle LPC_PWM1->CTCR |= (0 << 0); // PWM used in timer mode LPC_PWM1->PCR = 0; // all channels are single edge controlled, outputs disable LPC_PWM1->PCR |= (0x3F << 9); // Bit 14:9 -> 1 PWM outputs ch. 1-6 enabled LPC_PWM1->PR = 0; // no prescaling for PWM1 TC MR[0] = &LPC_PWM1->MR0; MR[1] = &LPC_PWM1->MR1; MR[2] = &LPC_PWM1->MR2; MR[3] = &LPC_PWM1->MR3; MR[4] = &LPC_PWM1->MR4; MR[5] = &LPC_PWM1->MR5; MR[6] = &LPC_PWM1->MR6; *MR[0] = _resolution; // period of 1 PWM cycle LPC_PWM1->LER |= (1 << 0); // update shadowregister, set cycle to output for(int i = 1; i < 7; i++) { // update ch. 1-6 *MR[i] = 0; LPC_PWM1->LER |= (1 << i); } LPC_PWM1->TCR |= (1 << 3) | (1 << 0); // enable PWM and Timer (PWM unit) // ==> output update from MR1-6 are load and // enabled with LPC_PWM1->LER Bit 6:1 set to "1" } void PwmDAC::deactivate(unsigned int ch) { if(ch < 6) { LPC_PINCON->PINSEL4 &= ~(1 << (ch + ch)); LPC_PINCON->PINMODE4 |= (3 << (ch + ch)); } else {// deactivate all LPC_PINCON->PINSEL4 &= 0xFFFFFB00; // PWM on ch. 0-5 p26 p25 p24 p23 p22 p21 LPC_PINCON->PINMODE4 |= (3 << 0) | (3 << 2) | (3 << 4) | (3 << 6) | (3 << 8) | (3 << 10); } _allActive = false; } void PwmDAC::activate(unsigned int ch) { if(ch < 6) { LPC_PINCON->PINSEL4 |= (1 << (ch + ch)); LPC_PINCON->PINMODE4 |= (2 << (ch + ch)); _allActive = false; } else {// activate all LPC_PINCON->PINSEL4 |= (1 << 0) | (1 << 2) | (1 << 4) | (1 << 6) | (1 << 8) | (1 << 10); // PWM on ch. 0-5 p26 p25 p24 p23 p22 p21 LPC_PINCON->PINMODE4 |= (2 << 0) | (2 << 2) | (2 << 4) | (2 << 6) | (2 << 8) | (2 << 10); _allActive = true; } } void PwmDAC::setFrequency(double frequency) { _frequency = frequency; _period = 1/frequency; _resolution = (uint32_t) ((double) SYS_CLK / frequency); *MR[0] = _resolution; // period of 1 PWM cycle LPC_PWM1->LER |= (1 << 0); // update shadowregister, set cycle to output } void PwmDAC::setPeriod(double seconds) { _frequency = 1/seconds; _period = seconds; _resolution = (uint32_t) ((double) SYS_CLK * seconds); *MR[0] = _resolution; // period of 1 PWM cycle LPC_PWM1->LER |= (1 << 0); // update shadowregister, set cycle to output } void PwmDAC::setResolution(uint32_t resolution) { _resolution = resolution; _frequency = (double) SYS_CLK / resolution; _period = 1 / _frequency; *MR[0] = _resolution; // period of 1 PWM cycle LPC_PWM1->LER |= (1 << 0); // update shadowregister, set cycle to output } void PwmDAC::updateDuty(double duty[]) { for(int i = 0; i < 6; i++) { if(duty[i] <= 100.0) { _duty[i] = duty[i]; _pulsewidth[i] = duty[i] / 100.0 * _period; _steps[i] = (uint32_t) ((double) SYS_CLK * _pulsewidth[i]); *MR[i+1] = _steps[i]; LPC_PWM1->LER |= (1 << (i+1)); } } } void PwmDAC::updatePulsewidth(double pulsewidth[]) { for(int i = 0; i < 6; i++) { if(pulsewidth[i] <= _period) { _duty[i] = pulsewidth[i] / _period; _pulsewidth[i] = pulsewidth[i]; _steps[i] = (uint32_t) ((double) SYS_CLK * pulsewidth[i]); *MR[i+1] = _steps[i]; LPC_PWM1->LER |= (1 << (i+1)); } } } void PwmDAC::updateSteps(uint32_t steps[]) { for(int i = 0; i < 6; i++) { if(steps[i] <= _resolution) { _duty[i] = (double) steps[i] / _resolution; _pulsewidth[i] = _duty[i] * _period; _steps[i] = steps[i]; *MR[i+1] = steps[i]; LPC_PWM1->LER |= (1 << (i+1)); } } } void PwmDAC::stop() { for(int i = 0; i < 6; i++) { *MR[i+1] = 0; LPC_PWM1->LER |= (1 << (i+1)); } } void PwmDAC::start() { for(int i = 0; i < 6; i++) { *MR[i+1] = _steps[i]; LPC_PWM1->LER |= (1 << (i+1)); } }