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

Revision:
0:13e0b9ea312f
Child:
1:381bd99d10a4
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/PwmDAC.cpp	Sun Sep 15 22:20:47 2013 +0000
@@ -0,0 +1,157 @@
+#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));
+    }    
+}
\ No newline at end of file