blob: dabcd2ee54c8be5f57ad638f7c6cbe5a03b25d81 [file] [log] [blame]
Brian Silverman41cdd3e2019-01-19 19:48:58 -08001/*----------------------------------------------------------------------------*/
James Kuszmaul4f3ad3c2019-12-01 16:35:21 -08002/* Copyright (c) 2008-2019 FIRST. All Rights Reserved. */
Brian Silverman41cdd3e2019-01-19 19:48:58 -08003/* 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
8#include "frc/PWM.h"
9
10#include <utility>
11
James Kuszmaul4b81d302019-12-14 20:53:14 -080012#include <hal/FRCUsageReporting.h>
13#include <hal/HALBase.h>
Brian Silverman41cdd3e2019-01-19 19:48:58 -080014#include <hal/PWM.h>
15#include <hal/Ports.h>
16
17#include "frc/SensorUtil.h"
18#include "frc/Utility.h"
19#include "frc/WPIErrors.h"
20#include "frc/smartdashboard/SendableBuilder.h"
James Kuszmaul4f3ad3c2019-12-01 16:35:21 -080021#include "frc/smartdashboard/SendableRegistry.h"
Brian Silverman41cdd3e2019-01-19 19:48:58 -080022
23using namespace frc;
24
25PWM::PWM(int channel) {
26 if (!SensorUtil::CheckPWMChannel(channel)) {
27 wpi_setWPIErrorWithContext(ChannelIndexOutOfRange,
28 "PWM Channel " + wpi::Twine(channel));
29 return;
30 }
31
32 int32_t status = 0;
33 m_handle = HAL_InitializePWMPort(HAL_GetPort(channel), &status);
34 if (status != 0) {
James Kuszmaul4b81d302019-12-14 20:53:14 -080035 wpi_setHALErrorWithRange(status, 0, HAL_GetNumPWMChannels(), channel);
Brian Silverman41cdd3e2019-01-19 19:48:58 -080036 m_channel = std::numeric_limits<int>::max();
37 m_handle = HAL_kInvalidHandle;
38 return;
39 }
40
41 m_channel = channel;
42
43 HAL_SetPWMDisabled(m_handle, &status);
James Kuszmaul4b81d302019-12-14 20:53:14 -080044 wpi_setHALError(status);
Brian Silverman41cdd3e2019-01-19 19:48:58 -080045 status = 0;
46 HAL_SetPWMEliminateDeadband(m_handle, false, &status);
James Kuszmaul4b81d302019-12-14 20:53:14 -080047 wpi_setHALError(status);
Brian Silverman41cdd3e2019-01-19 19:48:58 -080048
James Kuszmaul4b81d302019-12-14 20:53:14 -080049 HAL_Report(HALUsageReporting::kResourceType_PWM, channel + 1);
James Kuszmaul4f3ad3c2019-12-01 16:35:21 -080050 SendableRegistry::GetInstance().AddLW(this, "PWM", channel);
Brian Silverman41cdd3e2019-01-19 19:48:58 -080051
52 SetSafetyEnabled(false);
53}
54
55PWM::~PWM() {
56 int32_t status = 0;
57
58 HAL_SetPWMDisabled(m_handle, &status);
James Kuszmaul4b81d302019-12-14 20:53:14 -080059 wpi_setHALError(status);
Brian Silverman41cdd3e2019-01-19 19:48:58 -080060
61 HAL_FreePWMPort(m_handle, &status);
James Kuszmaul4b81d302019-12-14 20:53:14 -080062 wpi_setHALError(status);
Brian Silverman41cdd3e2019-01-19 19:48:58 -080063}
64
Brian Silverman41cdd3e2019-01-19 19:48:58 -080065void PWM::StopMotor() { SetDisabled(); }
66
67void PWM::GetDescription(wpi::raw_ostream& desc) const {
68 desc << "PWM " << GetChannel();
69}
70
71void PWM::SetRaw(uint16_t value) {
72 if (StatusIsFatal()) return;
73
74 int32_t status = 0;
75 HAL_SetPWMRaw(m_handle, value, &status);
James Kuszmaul4b81d302019-12-14 20:53:14 -080076 wpi_setHALError(status);
Brian Silverman41cdd3e2019-01-19 19:48:58 -080077}
78
79uint16_t PWM::GetRaw() const {
80 if (StatusIsFatal()) return 0;
81
82 int32_t status = 0;
83 uint16_t value = HAL_GetPWMRaw(m_handle, &status);
James Kuszmaul4b81d302019-12-14 20:53:14 -080084 wpi_setHALError(status);
Brian Silverman41cdd3e2019-01-19 19:48:58 -080085
86 return value;
87}
88
89void PWM::SetPosition(double pos) {
90 if (StatusIsFatal()) return;
91 int32_t status = 0;
92 HAL_SetPWMPosition(m_handle, pos, &status);
James Kuszmaul4b81d302019-12-14 20:53:14 -080093 wpi_setHALError(status);
Brian Silverman41cdd3e2019-01-19 19:48:58 -080094}
95
96double PWM::GetPosition() const {
97 if (StatusIsFatal()) return 0.0;
98 int32_t status = 0;
99 double position = HAL_GetPWMPosition(m_handle, &status);
James Kuszmaul4b81d302019-12-14 20:53:14 -0800100 wpi_setHALError(status);
Brian Silverman41cdd3e2019-01-19 19:48:58 -0800101 return position;
102}
103
104void PWM::SetSpeed(double speed) {
105 if (StatusIsFatal()) return;
106 int32_t status = 0;
107 HAL_SetPWMSpeed(m_handle, speed, &status);
James Kuszmaul4b81d302019-12-14 20:53:14 -0800108 wpi_setHALError(status);
Brian Silverman41cdd3e2019-01-19 19:48:58 -0800109
110 Feed();
111}
112
113double PWM::GetSpeed() const {
114 if (StatusIsFatal()) return 0.0;
115 int32_t status = 0;
116 double speed = HAL_GetPWMSpeed(m_handle, &status);
James Kuszmaul4b81d302019-12-14 20:53:14 -0800117 wpi_setHALError(status);
Brian Silverman41cdd3e2019-01-19 19:48:58 -0800118 return speed;
119}
120
121void PWM::SetDisabled() {
122 if (StatusIsFatal()) return;
123
124 int32_t status = 0;
125
126 HAL_SetPWMDisabled(m_handle, &status);
James Kuszmaul4b81d302019-12-14 20:53:14 -0800127 wpi_setHALError(status);
Brian Silverman41cdd3e2019-01-19 19:48:58 -0800128}
129
130void PWM::SetPeriodMultiplier(PeriodMultiplier mult) {
131 if (StatusIsFatal()) return;
132
133 int32_t status = 0;
134
135 switch (mult) {
136 case kPeriodMultiplier_4X:
137 HAL_SetPWMPeriodScale(m_handle, 3,
138 &status); // Squelch 3 out of 4 outputs
139 break;
140 case kPeriodMultiplier_2X:
141 HAL_SetPWMPeriodScale(m_handle, 1,
142 &status); // Squelch 1 out of 2 outputs
143 break;
144 case kPeriodMultiplier_1X:
145 HAL_SetPWMPeriodScale(m_handle, 0, &status); // Don't squelch any outputs
146 break;
147 default:
148 wpi_assert(false);
149 }
150
James Kuszmaul4b81d302019-12-14 20:53:14 -0800151 wpi_setHALError(status);
Brian Silverman41cdd3e2019-01-19 19:48:58 -0800152}
153
154void PWM::SetZeroLatch() {
155 if (StatusIsFatal()) return;
156
157 int32_t status = 0;
158
159 HAL_LatchPWMZero(m_handle, &status);
James Kuszmaul4b81d302019-12-14 20:53:14 -0800160 wpi_setHALError(status);
Brian Silverman41cdd3e2019-01-19 19:48:58 -0800161}
162
163void PWM::EnableDeadbandElimination(bool eliminateDeadband) {
164 if (StatusIsFatal()) return;
165 int32_t status = 0;
166 HAL_SetPWMEliminateDeadband(m_handle, eliminateDeadband, &status);
James Kuszmaul4b81d302019-12-14 20:53:14 -0800167 wpi_setHALError(status);
Brian Silverman41cdd3e2019-01-19 19:48:58 -0800168}
169
170void PWM::SetBounds(double max, double deadbandMax, double center,
171 double deadbandMin, double min) {
172 if (StatusIsFatal()) return;
173 int32_t status = 0;
174 HAL_SetPWMConfig(m_handle, max, deadbandMax, center, deadbandMin, min,
175 &status);
James Kuszmaul4b81d302019-12-14 20:53:14 -0800176 wpi_setHALError(status);
Brian Silverman41cdd3e2019-01-19 19:48:58 -0800177}
178
179void PWM::SetRawBounds(int max, int deadbandMax, int center, int deadbandMin,
180 int min) {
181 if (StatusIsFatal()) return;
182 int32_t status = 0;
183 HAL_SetPWMConfigRaw(m_handle, max, deadbandMax, center, deadbandMin, min,
184 &status);
James Kuszmaul4b81d302019-12-14 20:53:14 -0800185 wpi_setHALError(status);
Brian Silverman41cdd3e2019-01-19 19:48:58 -0800186}
187
188void PWM::GetRawBounds(int* max, int* deadbandMax, int* center,
189 int* deadbandMin, int* min) {
190 int32_t status = 0;
191 HAL_GetPWMConfigRaw(m_handle, max, deadbandMax, center, deadbandMin, min,
192 &status);
James Kuszmaul4b81d302019-12-14 20:53:14 -0800193 wpi_setHALError(status);
Brian Silverman41cdd3e2019-01-19 19:48:58 -0800194}
195
196int PWM::GetChannel() const { return m_channel; }
197
198void PWM::InitSendable(SendableBuilder& builder) {
199 builder.SetSmartDashboardType("PWM");
200 builder.SetActuator(true);
201 builder.SetSafeState([=]() { SetDisabled(); });
202 builder.AddDoubleProperty("Value", [=]() { return GetRaw(); },
203 [=](double value) { SetRaw(value); });
204}