blob: 0bf38a3110077fe7316b2400a123b22c504958fa [file] [log] [blame]
Parker Schuhd3b7a8872018-02-19 16:42:27 -08001/*----------------------------------------------------------------------------*/
2/* Copyright (c) FIRST 2008-2017. All Rights Reserved. */
3/* Open Source Software - may be modified and shared by FRC teams. The code */
4/* must be accompanied by the FIRST BSD license file in the root directory of */
5/* the project. */
6/*----------------------------------------------------------------------------*/
7
Austin Schuhf6b94632019-02-02 22:11:27 -08008#include "hal/PWM.h"
Parker Schuhd3b7a8872018-02-19 16:42:27 -08009#include "frc971/wpilib/ahal/PWM.h"
10
11#include <sstream>
12
Austin Schuhf6b94632019-02-02 22:11:27 -080013#include "hal/HAL.h"
14#include "hal/Ports.h"
Parker Schuhd3b7a8872018-02-19 16:42:27 -080015#include "frc971/wpilib/ahal/Utility.h"
16#include "frc971/wpilib/ahal/WPIErrors.h"
17
18using namespace frc;
19
20#define HAL_FATAL_ERROR()
21
22/**
23 * Allocate a PWM given a channel number.
24 *
25 * Checks channel value range and allocates the appropriate channel.
26 * The allocation is only done to help users ensure that they don't double
27 * assign channels.
28 *
29 * @param channel The PWM channel number. 0-9 are on-board, 10-19 are on the
30 * MXP port
31 */
32PWM::PWM(int channel) {
33 if (!CheckPWMChannel(channel)) {
34 fprintf(stderr, "Channel Index out of range: PWM Channel %d\n", channel);
35 exit(-1);
36 return;
37 }
38
39 int32_t status = 0;
40 m_handle = HAL_InitializePWMPort(HAL_GetPort(channel), &status);
41 if (status != 0) {
42 // wpi_setErrorWithContextRange(status, 0, HAL_GetNumPWMChannels(),
43 // channel,
44 // HAL_GetErrorMessage(status));
45 HAL_FATAL_ERROR();
46 m_channel = std::numeric_limits<int>::max();
47 m_handle = HAL_kInvalidHandle;
48 return;
49 }
50
51 m_channel = channel;
52
53 HAL_SetPWMDisabled(m_handle, &status);
54 HAL_FATAL_ERROR();
55 status = 0;
56 HAL_SetPWMEliminateDeadband(m_handle, false, &status);
57 HAL_FATAL_ERROR();
58
59 HAL_Report(HALUsageReporting::kResourceType_PWM, channel);
60}
61
62/**
63 * Free the PWM channel.
64 *
65 * Free the resource associated with the PWM channel and set the value to 0.
66 */
67PWM::~PWM() {
68 int32_t status = 0;
69
70 HAL_SetPWMDisabled(m_handle, &status);
71 HAL_FATAL_ERROR();
72
73 HAL_FreePWMPort(m_handle, &status);
74 HAL_FATAL_ERROR();
75}
76
77/**
78 * Optionally eliminate the deadband from a speed controller.
79 *
80 * @param eliminateDeadband If true, set the motor curve on the Jaguar to
81 * eliminate the deadband in the middle of the range.
82 * Otherwise, keep the full range without modifying
83 * any values.
84 */
85void PWM::EnableDeadbandElimination(bool eliminateDeadband) {
86 int32_t status = 0;
87 HAL_SetPWMEliminateDeadband(m_handle, eliminateDeadband, &status);
88 HAL_FATAL_ERROR();
89}
90
91/**
92 * Set the bounds on the PWM pulse widths.
93 *
94 * This sets the bounds on the PWM values for a particular type of controller.
95 * The values determine the upper and lower speeds as well as the deadband
96 * bracket.
97 *
98 * @param max The max PWM pulse width in ms
99 * @param deadbandMax The high end of the deadband range pulse width in ms
100 * @param center The center (off) pulse width in ms
101 * @param deadbandMin The low end of the deadband pulse width in ms
102 * @param min The minimum pulse width in ms
103 */
104void PWM::SetBounds(double max, double deadbandMax, double center,
105 double deadbandMin, double min) {
106 int32_t status = 0;
107 HAL_SetPWMConfig(m_handle, max, deadbandMax, center, deadbandMin, min,
108 &status);
109 HAL_FATAL_ERROR();
110}
111
112/**
113 * Set the bounds on the PWM values.
114 *
115 * This sets the bounds on the PWM values for a particular each type of
116 * controller. The values determine the upper and lower speeds as well as the
117 * deadband bracket.
118 *
119 * @param max The Minimum pwm value
120 * @param deadbandMax The high end of the deadband range
121 * @param center The center speed (off)
122 * @param deadbandMin The low end of the deadband range
123 * @param min The minimum pwm value
124 */
125void PWM::SetRawBounds(int max, int deadbandMax, int center, int deadbandMin,
126 int min) {
127 int32_t status = 0;
128 HAL_SetPWMConfigRaw(m_handle, max, deadbandMax, center, deadbandMin, min,
129 &status);
130 HAL_FATAL_ERROR();
131}
132
133/**
134 * Get the bounds on the PWM values.
135 *
136 * This Gets the bounds on the PWM values for a particular each type of
137 * controller. The values determine the upper and lower speeds as well as the
138 * deadband bracket.
139 *
140 * @param max The Minimum pwm value
141 * @param deadbandMax The high end of the deadband range
142 * @param center The center speed (off)
143 * @param deadbandMin The low end of the deadband range
144 * @param min The minimum pwm value
145 */
146void PWM::GetRawBounds(int *max, int *deadbandMax, int *center,
147 int *deadbandMin, int *min) {
148 int32_t status = 0;
149 HAL_GetPWMConfigRaw(m_handle, max, deadbandMax, center, deadbandMin, min,
150 &status);
151 HAL_FATAL_ERROR();
152}
153
154/**
155 * Set the PWM value based on a position.
156 *
157 * This is intended to be used by servos.
158 *
159 * @pre SetMaxPositivePwm() called.
160 * @pre SetMinNegativePwm() called.
161 *
162 * @param pos The position to set the servo between 0.0 and 1.0.
163 */
164void PWM::SetPosition(double pos) {
165 int32_t status = 0;
166 HAL_SetPWMPosition(m_handle, pos, &status);
167 HAL_FATAL_ERROR();
168}
169
170/**
171 * Get the PWM value in terms of a position.
172 *
173 * This is intended to be used by servos.
174 *
175 * @pre SetMaxPositivePwm() called.
176 * @pre SetMinNegativePwm() called.
177 *
178 * @return The position the servo is set to between 0.0 and 1.0.
179 */
180double PWM::GetPosition() const {
181 int32_t status = 0;
182 double position = HAL_GetPWMPosition(m_handle, &status);
183 HAL_FATAL_ERROR();
184 return position;
185}
186
187/**
188 * Set the PWM value based on a speed.
189 *
190 * This is intended to be used by speed controllers.
191 *
192 * @pre SetMaxPositivePwm() called.
193 * @pre SetMinPositivePwm() called.
194 * @pre SetCenterPwm() called.
195 * @pre SetMaxNegativePwm() called.
196 * @pre SetMinNegativePwm() called.
197 *
198 * @param speed The speed to set the speed controller between -1.0 and 1.0.
199 */
200void PWM::SetSpeed(double speed) {
201 int32_t status = 0;
202 HAL_SetPWMSpeed(m_handle, speed, &status);
203 HAL_FATAL_ERROR();
204}
205
206/**
207 * Get the PWM value in terms of speed.
208 *
209 * This is intended to be used by speed controllers.
210 *
211 * @pre SetMaxPositivePwm() called.
212 * @pre SetMinPositivePwm() called.
213 * @pre SetMaxNegativePwm() called.
214 * @pre SetMinNegativePwm() called.
215 *
216 * @return The most recently set speed between -1.0 and 1.0.
217 */
218double PWM::GetSpeed() const {
219 int32_t status = 0;
220 double speed = HAL_GetPWMSpeed(m_handle, &status);
221 HAL_FATAL_ERROR();
222 return speed;
223}
224
225/**
226 * Set the PWM value directly to the hardware.
227 *
228 * Write a raw value to a PWM channel.
229 *
230 * @param value Raw PWM value.
231 */
232void PWM::SetRaw(uint16_t value) {
233 int32_t status = 0;
234 HAL_SetPWMRaw(m_handle, value, &status);
235 HAL_FATAL_ERROR();
236}
237
238/**
239 * Get the PWM value directly from the hardware.
240 *
241 * Read a raw value from a PWM channel.
242 *
243 * @return Raw PWM control value.
244 */
245uint16_t PWM::GetRaw() const {
246 int32_t status = 0;
247 uint16_t value = HAL_GetPWMRaw(m_handle, &status);
248 HAL_FATAL_ERROR();
249
250 return value;
251}
252
253/**
254 * Slow down the PWM signal for old devices.
255 *
256 * @param mult The period multiplier to apply to this channel
257 */
258void PWM::SetPeriodMultiplier(PeriodMultiplier mult) {
259 int32_t status = 0;
260
261 switch (mult) {
262 case kPeriodMultiplier_4X:
263 HAL_SetPWMPeriodScale(m_handle, 3,
264 &status); // Squelch 3 out of 4 outputs
265 break;
266 case kPeriodMultiplier_2X:
267 HAL_SetPWMPeriodScale(m_handle, 1,
268 &status); // Squelch 1 out of 2 outputs
269 break;
270 case kPeriodMultiplier_1X:
271 HAL_SetPWMPeriodScale(m_handle, 0, &status); // Don't squelch any outputs
272 break;
273 default:
274 wpi_assert(false);
275 }
276
277 HAL_FATAL_ERROR();
278}
279
280/**
281 * Temporarily disables the PWM output. The next set call will reenable
282 * the output.
283 */
284void PWM::SetDisabled() {
285 int32_t status = 0;
286
287 HAL_SetPWMDisabled(m_handle, &status);
288 HAL_FATAL_ERROR();
289}
290
291void PWM::SetZeroLatch() {
292 int32_t status = 0;
293
294 HAL_LatchPWMZero(m_handle, &status);
295 HAL_FATAL_ERROR();
296}