-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathPWM.cpp
More file actions
199 lines (160 loc) · 6.39 KB
/
PWM.cpp
File metadata and controls
199 lines (160 loc) · 6.39 KB
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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
/*
Copyright 2018 Devin Gund (https://dgund.com)
https://github.com/dgund/BBBKit/
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include "PWM.h"
#include <unistd.h>
#include "Readwrite.h"
/*
The PWM interface configuration appears to change between kernel updates, so
these paths may change. To determine the new PWM interface paths, see my
post at https://stackoverflow.com/questions/50204329/pwm-chip-to-pin-mapping-on-beaglebone-black-v4-14.
*/
#define STR_HELPER(x) #x
#define STR(x) STR_HELPER(x)
#define PWM_SYSFS_PATH_PWMCHIP(chip) "/sys/class/pwm/pwmchip" STR(chip) "/"
#define PWM_SYSFS_PWM(chip, channel) "pwm-" STR(chip) ":" STR(channel)
//#define PWM_SYSFS_PWM(chip, channel) "pwm" STR(channel) // For old sysfs (pre-4.14)
#define PWM_SYSFS_EHRPWM0_CHIP 1
#define PWM_SYSFS_EHRPWM0A_CHANNEL 0
#define PWM_SYSFS_EHRPWM0B_CHANNEL 1
#define PWM_SYSFS_EHRPWM1_CHIP 3
#define PWM_SYSFS_EHRPWM1A_CHANNEL 0
#define PWM_SYSFS_EHRPWM1B_CHANNEL 1
#define PWM_SYSFS_EHRPWM2_CHIP 6
#define PWM_SYSFS_EHRPWM2A_CHANNEL 0
#define PWM_SYSFS_EHRPWM2B_CHANNEL 1
#define PWM_SYSFS_ECAPPWM0_CHIP 0
#define PWM_SYSFS_ECAPPWM0_CHANNEL 0
#define PWM_SYSFS_ECAPPWM2_CHIP 5
#define PWM_SYSFS_ECAPPWM2_CHANNEL 0
#define PWM_SYSFS_PATH_EHRPWM0 PWM_SYSFS_PATH_PWMCHIP(PWM_SYSFS_EHRPWM0_CHIP)
#define PWM_SYSFS_PATH_EHRPWM1 PWM_SYSFS_PATH_PWMCHIP(PWM_SYSFS_EHRPWM1_CHIP)
#define PWM_SYSFS_PATH_EHRPWM2 PWM_SYSFS_PATH_PWMCHIP(PWM_SYSFS_EHRPWM2_CHIP)
#define PWM_SYSFS_PATH_ECAPPWM0 PWM_SYSFS_PATH_PWMCHIP(PWM_SYSFS_ECAPPWM0_CHIP)
#define PWM_SYSFS_PATH_ECAPPWM2 PWM_SYSFS_PATH_PWMCHIP(PWM_SYSFS_ECAPPWM2_CHIP)
#define PWM_SYSFS_EHRPWM0A PWM_SYSFS_PWM(PWM_SYSFS_EHRPWM0_CHIP, PWM_SYSFS_EHRPWM0A_CHANNEL)
#define PWM_SYSFS_EHRPWM0B PWM_SYSFS_PWM(PWM_SYSFS_EHRPWM0_CHIP, PWM_SYSFS_EHRPWM0B_CHANNEL)
#define PWM_SYSFS_EHRPWM1A PWM_SYSFS_PWM(PWM_SYSFS_EHRPWM1_CHIP, PWM_SYSFS_EHRPWM1A_CHANNEL)
#define PWM_SYSFS_EHRPWM1B PWM_SYSFS_PWM(PWM_SYSFS_EHRPWM1_CHIP, PWM_SYSFS_EHRPWM1B_CHANNEL)
#define PWM_SYSFS_EHRPWM2A PWM_SYSFS_PWM(PWM_SYSFS_EHRPWM2_CHIP, PWM_SYSFS_EHRPWM2A_CHANNEL)
#define PWM_SYSFS_EHRPWM2B PWM_SYSFS_PWM(PWM_SYSFS_EHRPWM2_CHIP, PWM_SYSFS_EHRPWM2B_CHANNEL)
#define PWM_SYSFS_ECAPPWM0 PWM_SYSFS_PWM(PWM_SYSFS_ECAPPWM0_CHIP, PWM_SYSFS_ECAPPWM0_CHANNEL)
#define PWM_SYSFS_ECAPPWM2 PWM_SYSFS_PWM(PWM_SYSFS_ECAPPWM2_CHIP, PWM_SYSFS_ECAPPWM2_CHANNEL)
#define PWM_SYSFS_DELAY 300000
#define PWM_SYSFS_EXPORT "export"
#define PWM_SYSFS_DUTY "duty_cycle"
#define PWM_SYSFS_PERIOD "period"
#define PWM_SYSFS_POLARITY "polarity"
#define PWM_SYSFS_ENABLE "enable"
#define PWM_SYSFS_UNEXPORT "unexport"
#define PERCENT_MIN 0.0
#define PERCENT_MAX 100.0
#define NANO 1000000000.0
const std::string pathMap[8] = {
PWM_SYSFS_PATH_EHRPWM0,
PWM_SYSFS_PATH_EHRPWM0,
PWM_SYSFS_PATH_EHRPWM1,
PWM_SYSFS_PATH_EHRPWM1,
PWM_SYSFS_PATH_EHRPWM2,
PWM_SYSFS_PATH_EHRPWM2,
PWM_SYSFS_PATH_ECAPPWM0,
PWM_SYSFS_PATH_ECAPPWM2,
};
const std::string nameMap[8] = {
PWM_SYSFS_EHRPWM0A,
PWM_SYSFS_EHRPWM0B,
PWM_SYSFS_EHRPWM1A,
PWM_SYSFS_EHRPWM1B,
PWM_SYSFS_EHRPWM2A,
PWM_SYSFS_EHRPWM2B,
PWM_SYSFS_ECAPPWM0,
PWM_SYSFS_ECAPPWM2,
};
const int channelMap[8] = {
PWM_SYSFS_EHRPWM0A_CHANNEL,
PWM_SYSFS_EHRPWM0B_CHANNEL,
PWM_SYSFS_EHRPWM1A_CHANNEL,
PWM_SYSFS_EHRPWM1B_CHANNEL,
PWM_SYSFS_EHRPWM2A_CHANNEL,
PWM_SYSFS_EHRPWM2B_CHANNEL,
PWM_SYSFS_ECAPPWM0_CHANNEL,
PWM_SYSFS_ECAPPWM2_CHANNEL,
};
namespace bbbkit {
PWM::PWM(PWM::PIN pin, PWM::VALUE activeState) {
this->pin = pin;
this->name = nameMap[static_cast<int>(this->pin)];
this->path = pathMap[static_cast<int>(this->pin)] + this->name + "/";
// Export the pin (delay to give Linux some time)
this->exportPin();
usleep(PWM_SYSFS_DELAY);
// Set active state
this->setActiveState(activeState);
}
PWM::~PWM() {
this->unexportPin();
}
PWM::VALUE PWM::getActiveState() {
if (std::stoi(read(this->path, PWM_SYSFS_POLARITY)) == static_cast<int>(PWM::VALUE::LOW)) return PWM::VALUE::LOW;
else return PWM::VALUE::HIGH;
}
int PWM::setActiveState(PWM::VALUE activeState) {
return write(this->path, PWM_SYSFS_POLARITY, static_cast<int>(activeState));
}
unsigned int PWM::getPeriod() {
return std::stoi(read(this->path, PWM_SYSFS_PERIOD));
}
int PWM::setPeriod(unsigned int periodNS) {
return write(this->path, PWM_SYSFS_PERIOD, periodNS);
}
float PWM::getFrequency() {
unsigned int periodNS = this->getPeriod();
float periodS = (float)periodNS / NANO;
float frequencyHZ = 1.0 / periodS;
return frequencyHZ;
}
int PWM::setFrequency(float frequencyHZ) {
float periodS = 1.0 / frequencyHZ;
unsigned int periodNS = (unsigned int)(periodS * NANO);
return this->setPeriod(periodNS);
}
unsigned int PWM::getDutyCycle() {
return std::stoi(read(this->path, PWM_SYSFS_DUTY));
}
float PWM::getDutyCycleAsPercent() {
return PERCENT_MAX * (float)this->getDutyCycle() / (float)this->getPeriod();
}
int PWM::setDutyCycle(unsigned int dutyCycleNS) {
return write(this->path, PWM_SYSFS_DUTY, dutyCycleNS);
}
int PWM::setDutyCycleAsPercent(float dutyCyclePercent) {
if (PERCENT_MIN > dutyCyclePercent || dutyCyclePercent > PERCENT_MAX) return -1;
return this->setDutyCycle((float)this->getPeriod() * (dutyCyclePercent / PERCENT_MAX));
}
int PWM::start() {
return write(this->path, PWM_SYSFS_ENABLE, static_cast<int>(PWM::VALUE::HIGH));
}
bool PWM::isRunning() {
return std::stoi(read(this->path, PWM_SYSFS_ENABLE)) == static_cast<int>(PWM::VALUE::HIGH);
}
int PWM::stop() {
return write(this->path, PWM_SYSFS_ENABLE, static_cast<int>(PWM::VALUE::LOW));
}
// Private
int PWM::exportPin() {
return write(pathMap[static_cast<int>(this->pin)], PWM_SYSFS_EXPORT, channelMap[static_cast<int>(this->pin)]);
}
int PWM::unexportPin() {
return write(pathMap[static_cast<int>(this->pin)], PWM_SYSFS_UNEXPORT, channelMap[static_cast<int>(this->pin)]);
}
} /* namespace bbbkit */