-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathPWM.cpp
138 lines (127 loc) · 3.77 KB
/
PWM.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
#include "PWM.h"
using namespace myRIO;
extern NiFpga_Session myrio_session;
/** Create PWM signal
*@param out the pin where the PWM signal will be created (PWM0, PWM1)
*@param frequency the frequency of the PWM signal
*@param duty_cycle the duty cycle of the signal; for 50%, duty_cycle = 50
*@param prescaler the clock prescaler. Must be a power of 2 between 1 and 64 in bits : 0b001 = 1, 0b010 = 2, 0b011 = 4...
*/
PWM::PWM(uint32_t out, double frequency, double duty_cycle, short prescaler) : out(out), dutyCycle(duty_cycle), frequency(frequency), prescaler(prescaler) {
uint8_t select, pin;
// Activate the PWM signals in the selected pin
if(out == PWMA_0CNFG || out == PWMA_1CNFG || out == PWMA_2CNFG) {
if(out == PWMA_0CNFG) pin = 2;
if(out == PWMA_1CNFG) pin = 3;
if(out == PWMA_2CNFG) pin = 4;
status = NiFpga_ReadU8(myrio_session, SYSSELECTA, &select);
select |= (1<<pin);
NiFpga_MergeStatus(&status,
NiFpga_WriteU8(myrio_session, SYSSELECTA, select));
}
else if(out == PWMB_0CNFG || out == PWMB_1CNFG || out == PWMB_2CNFG) {
if (out == PWMB_0CNFG) pin = 2;
if (out == PWMB_1CNFG) pin = 3;
if (out == PWMB_2CNFG) pin = 4;
status = NiFpga_ReadU8(myrio_session, SYSSELECTB, &select);
select |= (1<<pin);
NiFpga_MergeStatus(&status,
NiFpga_WriteU8(myrio_session, SYSSELECTB, select));
}
else if(out == PWMC_0CNFG || out == PWMC_1CNFG) {
if (out == PWMC_0CNFG) pin = 1;
if (out == PWMC_1CNFG) pin = 3;
status = NiFpga_ReadU8(myrio_session, SYSSELECTC, &select);
select |= (1<<pin);
NiFpga_MergeStatus(&status,
NiFpga_WriteU8(myrio_session, SYSSELECTC, select));
}
else {
status = -1;
return;
}
// Selection of the needed PWM registers (can be configured as needed)
if(out == PWMA_0CNFG){
outcs = PWMA_0CS;
outmax = PWMA_0MAX;
outcmp = PWMA_0CMP;
}
else if(out == PWMA_1CNFG){
outcs = PWMA_1CS;
outmax = PWMA_1MAX;
outcmp = PWMA_1CMP;
}
else if(out == PWMA_2CNFG){
outcs = PWMA_2CS;
outmax = PWMA_2MAX;
outcmp = PWMA_2CMP;
}
else if(out == PWMB_0CNFG){
outcs = PWMB_0CS;
outmax = PWMB_0MAX;
outcmp = PWMB_0CMP;
}
else if(out == PWMB_1CNFG){
outcs = PWMB_1CS;
outmax = PWMB_1MAX;
outcmp = PWMB_1CMP;
}
else if(out == PWMB_2CNFG){
outcs = PWMB_2CS;
outmax = PWMB_2MAX;
outcmp = PWMB_2CMP;
}
else if(out == PWMC_0CNFG){
outcs = PWMC_0CS;
outmax = PWMC_0MAX;
outcmp = PWMC_0CMP;
}
else if(out == PWMC_1CNFG){
outcs = PWMC_1CS;
outmax = PWMC_1MAX;
outcmp = PWMC_1CMP;
} else {
status = -1;
return;
}
NiFpga_MergeStatus(&status,
NiFpga_WriteU8(myrio_session, out, 0b100)); //PWM generation mode , not inverted (can be configured as needed)
NiFpga_MergeStatus(&status,
NiFpga_WriteU8(myrio_session, outcs, prescaler)); // Clock divider : 32 (can be configured as needed)
setPrescaler(prescaler); // will also set the frequency and the duty cycle
}
/** Set the Duty Cycle
*@param dutyCycle the duty cycle to set
*/
void PWM::setDutyCycle(double dutyCycle) {
uint16_t cmp = round((double)max*dutyCycle/100.0);
status = NiFpga_WriteU16(myrio_session, outcmp, cmp);
}
/** Set the Frequency
* Will try to keep the current duty cycle.
*@param frequency the frequency to set
*/
void PWM::setFrequency(double frequency) {
this->frequency = frequency;
max = (long)40e6/(prescaler*frequency)-1; //Maximum value that the PWM counts
NiFpga_MergeStatus(&status,
NiFpga_WriteU16(myrio_session, outmax, max));
setDutyCycle(dutyCycle);
}
/** Set the clock prescaler
* Will try to keep the old frequency.
*@param clockDiv the prescaler. Must be 1, 2, 4, 8, 16, 32 or 64
*/
void PWM::setPrescaler(short clockDiv) {
prescaler = clockDiv;
setFrequency(frequency);
}
/**Destructor
* Desactivate the channel
*/
PWM::~PWM() {
status = NiFpga_WriteU8(myrio_session, out, 0x00);
}
/**
* \example example_pwm.cpp
*/