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

Committer:
flash_ahaa
Date:
Sat Sep 21 08:47:27 2013 +0000
Revision:
1:381bd99d10a4
Parent:
0:13e0b9ea312f
Remove update LER from for loop. Put update command after for loop and set all at once.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
flash_ahaa 0:13e0b9ea312f 1 #include "PwmDAC.h"
flash_ahaa 0:13e0b9ea312f 2 #include "mbed.h"
flash_ahaa 0:13e0b9ea312f 3
flash_ahaa 0:13e0b9ea312f 4 void PwmDAC::init() {
flash_ahaa 0:13e0b9ea312f 5 _allActive = true;
flash_ahaa 0:13e0b9ea312f 6 _resolution = 255;
flash_ahaa 0:13e0b9ea312f 7 _frequency = (double) SYS_CLK / _resolution;
flash_ahaa 0:13e0b9ea312f 8 _period = 1 / _frequency;
flash_ahaa 0:13e0b9ea312f 9 for(int i = 0; i < 6; i++) {
flash_ahaa 0:13e0b9ea312f 10 _pulsewidth[i] = 0.0;
flash_ahaa 0:13e0b9ea312f 11 _duty[i] = 0.0;
flash_ahaa 0:13e0b9ea312f 12 _steps[i] = 0;
flash_ahaa 0:13e0b9ea312f 13 }
flash_ahaa 0:13e0b9ea312f 14
flash_ahaa 0:13e0b9ea312f 15 LPC_SC->PCONP |= (1 << 6); // Bit 6 -> 1 == Poweron PWM1
flash_ahaa 0:13e0b9ea312f 16 LPC_SC->PCLKSEL0 |= (1 << 12); // Bit 13/12 -> 0/1 == Full clock 96MHz
flash_ahaa 0:13e0b9ea312f 17 LPC_PINCON->PINSEL4 |= (1 << 0) | (1 << 2) | (1 << 4) | (1 << 6) | (1 << 8) | (1 << 10);
flash_ahaa 0:13e0b9ea312f 18 // PWM on ch. 1-6 p26 p25 p24 p23 p22 p21
flash_ahaa 0:13e0b9ea312f 19 LPC_PINCON->PINMODE4 |= (2 << 0) | (2 << 2) | (2 << 4) | (2 << 6) | (2 << 8) | (2 << 10);
flash_ahaa 0:13e0b9ea312f 20 // no pull up/ down p26 p25 p24 p23 p22 p21
flash_ahaa 0:13e0b9ea312f 21 // 0 - pull up enabled
flash_ahaa 0:13e0b9ea312f 22 // 1 - repeater mode enabled
flash_ahaa 0:13e0b9ea312f 23 // 2 - no pull up/down
flash_ahaa 0:13e0b9ea312f 24 // 3 - pull down enabled
flash_ahaa 0:13e0b9ea312f 25
flash_ahaa 0:13e0b9ea312f 26 LPC_PWM1->MCR = 2; // no reset, stop or interrupt on timer compare match
flash_ahaa 0:13e0b9ea312f 27 // only TC reset on match with MR0 == new period of pwm cycle
flash_ahaa 0:13e0b9ea312f 28 LPC_PWM1->CTCR |= (0 << 0); // PWM used in timer mode
flash_ahaa 0:13e0b9ea312f 29 LPC_PWM1->PCR = 0; // all channels are single edge controlled, outputs disable
flash_ahaa 0:13e0b9ea312f 30 LPC_PWM1->PCR |= (0x3F << 9); // Bit 14:9 -> 1 PWM outputs ch. 1-6 enabled
flash_ahaa 0:13e0b9ea312f 31 LPC_PWM1->PR = 0; // no prescaling for PWM1 TC
flash_ahaa 0:13e0b9ea312f 32
flash_ahaa 0:13e0b9ea312f 33 MR[0] = &LPC_PWM1->MR0;
flash_ahaa 0:13e0b9ea312f 34 MR[1] = &LPC_PWM1->MR1;
flash_ahaa 0:13e0b9ea312f 35 MR[2] = &LPC_PWM1->MR2;
flash_ahaa 0:13e0b9ea312f 36 MR[3] = &LPC_PWM1->MR3;
flash_ahaa 0:13e0b9ea312f 37 MR[4] = &LPC_PWM1->MR4;
flash_ahaa 0:13e0b9ea312f 38 MR[5] = &LPC_PWM1->MR5;
flash_ahaa 0:13e0b9ea312f 39 MR[6] = &LPC_PWM1->MR6;
flash_ahaa 0:13e0b9ea312f 40
flash_ahaa 0:13e0b9ea312f 41 *MR[0] = _resolution; // period of 1 PWM cycle
flash_ahaa 0:13e0b9ea312f 42 LPC_PWM1->LER |= (1 << 0); // update shadowregister, set cycle to output
flash_ahaa 0:13e0b9ea312f 43
flash_ahaa 0:13e0b9ea312f 44 for(int i = 1; i < 7; i++) { // update ch. 1-6
flash_ahaa 0:13e0b9ea312f 45 *MR[i] = 0;
flash_ahaa 0:13e0b9ea312f 46 }
flash_ahaa 1:381bd99d10a4 47 LPC_PWM1->LER |= (0x3F << 1);
flash_ahaa 1:381bd99d10a4 48
flash_ahaa 0:13e0b9ea312f 49 LPC_PWM1->TCR |= (1 << 3) | (1 << 0); // enable PWM and Timer (PWM unit)
flash_ahaa 0:13e0b9ea312f 50 // ==> output update from MR1-6 are load and
flash_ahaa 0:13e0b9ea312f 51 // enabled with LPC_PWM1->LER Bit 6:1 set to "1"
flash_ahaa 0:13e0b9ea312f 52
flash_ahaa 0:13e0b9ea312f 53 }
flash_ahaa 0:13e0b9ea312f 54
flash_ahaa 0:13e0b9ea312f 55 void PwmDAC::deactivate(unsigned int ch) {
flash_ahaa 0:13e0b9ea312f 56 if(ch < 6) {
flash_ahaa 0:13e0b9ea312f 57 LPC_PINCON->PINSEL4 &= ~(1 << (ch + ch));
flash_ahaa 0:13e0b9ea312f 58 LPC_PINCON->PINMODE4 |= (3 << (ch + ch));
flash_ahaa 0:13e0b9ea312f 59 }
flash_ahaa 0:13e0b9ea312f 60 else {// deactivate all
flash_ahaa 0:13e0b9ea312f 61 LPC_PINCON->PINSEL4 &= 0xFFFFFB00;
flash_ahaa 0:13e0b9ea312f 62 // PWM on ch. 0-5 p26 p25 p24 p23 p22 p21
flash_ahaa 0:13e0b9ea312f 63 LPC_PINCON->PINMODE4 |= (3 << 0) | (3 << 2) | (3 << 4) | (3 << 6) | (3 << 8) | (3 << 10);
flash_ahaa 0:13e0b9ea312f 64 }
flash_ahaa 0:13e0b9ea312f 65 _allActive = false;
flash_ahaa 0:13e0b9ea312f 66 }
flash_ahaa 0:13e0b9ea312f 67
flash_ahaa 0:13e0b9ea312f 68 void PwmDAC::activate(unsigned int ch) {
flash_ahaa 0:13e0b9ea312f 69 if(ch < 6) {
flash_ahaa 0:13e0b9ea312f 70 LPC_PINCON->PINSEL4 |= (1 << (ch + ch));
flash_ahaa 0:13e0b9ea312f 71 LPC_PINCON->PINMODE4 |= (2 << (ch + ch));
flash_ahaa 0:13e0b9ea312f 72 _allActive = false;
flash_ahaa 0:13e0b9ea312f 73 }
flash_ahaa 0:13e0b9ea312f 74 else {// activate all
flash_ahaa 0:13e0b9ea312f 75 LPC_PINCON->PINSEL4 |= (1 << 0) | (1 << 2) | (1 << 4) | (1 << 6) | (1 << 8) | (1 << 10);
flash_ahaa 0:13e0b9ea312f 76 // PWM on ch. 0-5 p26 p25 p24 p23 p22 p21
flash_ahaa 0:13e0b9ea312f 77 LPC_PINCON->PINMODE4 |= (2 << 0) | (2 << 2) | (2 << 4) | (2 << 6) | (2 << 8) | (2 << 10);
flash_ahaa 0:13e0b9ea312f 78 _allActive = true;
flash_ahaa 0:13e0b9ea312f 79 }
flash_ahaa 0:13e0b9ea312f 80 }
flash_ahaa 0:13e0b9ea312f 81
flash_ahaa 0:13e0b9ea312f 82 void PwmDAC::setFrequency(double frequency) {
flash_ahaa 0:13e0b9ea312f 83 _frequency = frequency;
flash_ahaa 0:13e0b9ea312f 84 _period = 1/frequency;
flash_ahaa 0:13e0b9ea312f 85 _resolution = (uint32_t) ((double) SYS_CLK / frequency);
flash_ahaa 0:13e0b9ea312f 86
flash_ahaa 0:13e0b9ea312f 87 *MR[0] = _resolution; // period of 1 PWM cycle
flash_ahaa 0:13e0b9ea312f 88 LPC_PWM1->LER |= (1 << 0); // update shadowregister, set cycle to output
flash_ahaa 0:13e0b9ea312f 89 }
flash_ahaa 0:13e0b9ea312f 90
flash_ahaa 0:13e0b9ea312f 91 void PwmDAC::setPeriod(double seconds) {
flash_ahaa 0:13e0b9ea312f 92 _frequency = 1/seconds;
flash_ahaa 0:13e0b9ea312f 93 _period = seconds;
flash_ahaa 0:13e0b9ea312f 94 _resolution = (uint32_t) ((double) SYS_CLK * seconds);
flash_ahaa 0:13e0b9ea312f 95
flash_ahaa 0:13e0b9ea312f 96 *MR[0] = _resolution; // period of 1 PWM cycle
flash_ahaa 0:13e0b9ea312f 97 LPC_PWM1->LER |= (1 << 0); // update shadowregister, set cycle to output
flash_ahaa 0:13e0b9ea312f 98 }
flash_ahaa 0:13e0b9ea312f 99
flash_ahaa 0:13e0b9ea312f 100 void PwmDAC::setResolution(uint32_t resolution) {
flash_ahaa 0:13e0b9ea312f 101 _resolution = resolution;
flash_ahaa 0:13e0b9ea312f 102 _frequency = (double) SYS_CLK / resolution;
flash_ahaa 0:13e0b9ea312f 103 _period = 1 / _frequency;
flash_ahaa 0:13e0b9ea312f 104
flash_ahaa 0:13e0b9ea312f 105 *MR[0] = _resolution; // period of 1 PWM cycle
flash_ahaa 0:13e0b9ea312f 106 LPC_PWM1->LER |= (1 << 0); // update shadowregister, set cycle to output
flash_ahaa 0:13e0b9ea312f 107 }
flash_ahaa 0:13e0b9ea312f 108
flash_ahaa 0:13e0b9ea312f 109 void PwmDAC::updateDuty(double duty[]) {
flash_ahaa 0:13e0b9ea312f 110 for(int i = 0; i < 6; i++) {
flash_ahaa 0:13e0b9ea312f 111 if(duty[i] <= 100.0) {
flash_ahaa 0:13e0b9ea312f 112 _duty[i] = duty[i];
flash_ahaa 0:13e0b9ea312f 113 _pulsewidth[i] = duty[i] / 100.0 * _period;
flash_ahaa 0:13e0b9ea312f 114 _steps[i] = (uint32_t) ((double) SYS_CLK * _pulsewidth[i]);
flash_ahaa 0:13e0b9ea312f 115 *MR[i+1] = _steps[i];
flash_ahaa 0:13e0b9ea312f 116 }
flash_ahaa 1:381bd99d10a4 117 }
flash_ahaa 1:381bd99d10a4 118 LPC_PWM1->LER |= (0x3F << 1);
flash_ahaa 0:13e0b9ea312f 119 }
flash_ahaa 0:13e0b9ea312f 120
flash_ahaa 0:13e0b9ea312f 121 void PwmDAC::updatePulsewidth(double pulsewidth[]) {
flash_ahaa 0:13e0b9ea312f 122 for(int i = 0; i < 6; i++) {
flash_ahaa 0:13e0b9ea312f 123 if(pulsewidth[i] <= _period) {
flash_ahaa 0:13e0b9ea312f 124 _duty[i] = pulsewidth[i] / _period;
flash_ahaa 0:13e0b9ea312f 125 _pulsewidth[i] = pulsewidth[i];
flash_ahaa 0:13e0b9ea312f 126 _steps[i] = (uint32_t) ((double) SYS_CLK * pulsewidth[i]);
flash_ahaa 0:13e0b9ea312f 127 *MR[i+1] = _steps[i];
flash_ahaa 0:13e0b9ea312f 128 }
flash_ahaa 1:381bd99d10a4 129 }
flash_ahaa 1:381bd99d10a4 130 LPC_PWM1->LER |= (0x3F << 1);
flash_ahaa 0:13e0b9ea312f 131 }
flash_ahaa 0:13e0b9ea312f 132
flash_ahaa 0:13e0b9ea312f 133 void PwmDAC::updateSteps(uint32_t steps[]) {
flash_ahaa 0:13e0b9ea312f 134 for(int i = 0; i < 6; i++) {
flash_ahaa 0:13e0b9ea312f 135 if(steps[i] <= _resolution) {
flash_ahaa 0:13e0b9ea312f 136 _duty[i] = (double) steps[i] / _resolution;
flash_ahaa 0:13e0b9ea312f 137 _pulsewidth[i] = _duty[i] * _period;
flash_ahaa 0:13e0b9ea312f 138 _steps[i] = steps[i];
flash_ahaa 0:13e0b9ea312f 139 *MR[i+1] = steps[i];
flash_ahaa 0:13e0b9ea312f 140 }
flash_ahaa 1:381bd99d10a4 141 }
flash_ahaa 1:381bd99d10a4 142 LPC_PWM1->LER |= (0x3F << 1);
flash_ahaa 0:13e0b9ea312f 143 }
flash_ahaa 0:13e0b9ea312f 144
flash_ahaa 0:13e0b9ea312f 145 void PwmDAC::stop() {
flash_ahaa 0:13e0b9ea312f 146 for(int i = 0; i < 6; i++) {
flash_ahaa 0:13e0b9ea312f 147 *MR[i+1] = 0;
flash_ahaa 0:13e0b9ea312f 148 }
flash_ahaa 1:381bd99d10a4 149 LPC_PWM1->LER |= (0x3F << 1);
flash_ahaa 0:13e0b9ea312f 150 }
flash_ahaa 0:13e0b9ea312f 151
flash_ahaa 0:13e0b9ea312f 152 void PwmDAC::start() {
flash_ahaa 0:13e0b9ea312f 153 for(int i = 0; i < 6; i++) {
flash_ahaa 0:13e0b9ea312f 154 *MR[i+1] = _steps[i];
flash_ahaa 1:381bd99d10a4 155 }
flash_ahaa 1:381bd99d10a4 156 LPC_PWM1->LER |= (0x3F << 1);
flash_ahaa 0:13e0b9ea312f 157 }