blob: 6a4c0f58c73b084de7901a06246baa7443251cf1 [file] [log] [blame]
Austin Schuh812d0d12021-11-04 20:16:48 -07001// Copyright (c) FIRST and other WPILib contributors.
2// Open Source Software; you can modify and/or share it under the terms of
3// the WPILib BSD license file in the root directory of this project.
Brian Silverman8fce7482020-01-05 13:18:21 -08004
5#include "frc/PWM.h"
6
7#include <utility>
8
9#include <hal/FRCUsageReporting.h>
10#include <hal/HALBase.h>
11#include <hal/PWM.h>
12#include <hal/Ports.h>
Austin Schuh812d0d12021-11-04 20:16:48 -070013#include <wpi/StackTrace.h>
14#include <wpi/sendable/SendableBuilder.h>
15#include <wpi/sendable/SendableRegistry.h>
Brian Silverman8fce7482020-01-05 13:18:21 -080016
Austin Schuh812d0d12021-11-04 20:16:48 -070017#include "frc/Errors.h"
Brian Silverman8fce7482020-01-05 13:18:21 -080018#include "frc/SensorUtil.h"
Brian Silverman8fce7482020-01-05 13:18:21 -080019
20using namespace frc;
21
Austin Schuh812d0d12021-11-04 20:16:48 -070022PWM::PWM(int channel, bool registerSendable) {
Brian Silverman8fce7482020-01-05 13:18:21 -080023 if (!SensorUtil::CheckPWMChannel(channel)) {
Austin Schuh812d0d12021-11-04 20:16:48 -070024 throw FRC_MakeError(err::ChannelIndexOutOfRange, "Channel {}", channel);
Brian Silverman8fce7482020-01-05 13:18:21 -080025 }
26
Austin Schuh812d0d12021-11-04 20:16:48 -070027 auto stack = wpi::GetStackTrace(1);
Brian Silverman8fce7482020-01-05 13:18:21 -080028 int32_t status = 0;
Austin Schuh812d0d12021-11-04 20:16:48 -070029 m_handle =
30 HAL_InitializePWMPort(HAL_GetPort(channel), stack.c_str(), &status);
31 FRC_CheckErrorStatus(status, "Channel {}", channel);
Brian Silverman8fce7482020-01-05 13:18:21 -080032
33 m_channel = channel;
34
35 HAL_SetPWMDisabled(m_handle, &status);
Austin Schuh812d0d12021-11-04 20:16:48 -070036 FRC_CheckErrorStatus(status, "Channel {}", channel);
Brian Silverman8fce7482020-01-05 13:18:21 -080037 status = 0;
38 HAL_SetPWMEliminateDeadband(m_handle, false, &status);
Austin Schuh812d0d12021-11-04 20:16:48 -070039 FRC_CheckErrorStatus(status, "Channel {}", channel);
Brian Silverman8fce7482020-01-05 13:18:21 -080040
41 HAL_Report(HALUsageReporting::kResourceType_PWM, channel + 1);
Austin Schuh812d0d12021-11-04 20:16:48 -070042 if (registerSendable) {
43 wpi::SendableRegistry::AddLW(this, "PWM", channel);
44 }
Brian Silverman8fce7482020-01-05 13:18:21 -080045}
46
47PWM::~PWM() {
48 int32_t status = 0;
49
50 HAL_SetPWMDisabled(m_handle, &status);
Austin Schuh812d0d12021-11-04 20:16:48 -070051 FRC_ReportError(status, "Channel {}", m_channel);
Brian Silverman8fce7482020-01-05 13:18:21 -080052
53 HAL_FreePWMPort(m_handle, &status);
Austin Schuh812d0d12021-11-04 20:16:48 -070054 FRC_ReportError(status, "Channel {}", m_channel);
Brian Silverman8fce7482020-01-05 13:18:21 -080055}
56
James Kuszmaulb13e13f2023-11-22 20:44:04 -080057void PWM::SetPulseTime(units::microsecond_t time) {
Brian Silverman8fce7482020-01-05 13:18:21 -080058 int32_t status = 0;
James Kuszmaulb13e13f2023-11-22 20:44:04 -080059 HAL_SetPWMPulseTimeMicroseconds(m_handle, time.value(), &status);
Austin Schuh812d0d12021-11-04 20:16:48 -070060 FRC_CheckErrorStatus(status, "Channel {}", m_channel);
Brian Silverman8fce7482020-01-05 13:18:21 -080061}
62
James Kuszmaulb13e13f2023-11-22 20:44:04 -080063units::microsecond_t PWM::GetPulseTime() const {
Brian Silverman8fce7482020-01-05 13:18:21 -080064 int32_t status = 0;
James Kuszmaulb13e13f2023-11-22 20:44:04 -080065 double value = HAL_GetPWMPulseTimeMicroseconds(m_handle, &status);
Austin Schuh812d0d12021-11-04 20:16:48 -070066 FRC_CheckErrorStatus(status, "Channel {}", m_channel);
Brian Silverman8fce7482020-01-05 13:18:21 -080067
James Kuszmaulb13e13f2023-11-22 20:44:04 -080068 return units::microsecond_t{value};
Brian Silverman8fce7482020-01-05 13:18:21 -080069}
70
71void PWM::SetPosition(double pos) {
Brian Silverman8fce7482020-01-05 13:18:21 -080072 int32_t status = 0;
73 HAL_SetPWMPosition(m_handle, pos, &status);
Austin Schuh812d0d12021-11-04 20:16:48 -070074 FRC_CheckErrorStatus(status, "Channel {}", m_channel);
Brian Silverman8fce7482020-01-05 13:18:21 -080075}
76
77double PWM::GetPosition() const {
Brian Silverman8fce7482020-01-05 13:18:21 -080078 int32_t status = 0;
79 double position = HAL_GetPWMPosition(m_handle, &status);
Austin Schuh812d0d12021-11-04 20:16:48 -070080 FRC_CheckErrorStatus(status, "Channel {}", m_channel);
Brian Silverman8fce7482020-01-05 13:18:21 -080081 return position;
82}
83
84void PWM::SetSpeed(double speed) {
Brian Silverman8fce7482020-01-05 13:18:21 -080085 int32_t status = 0;
86 HAL_SetPWMSpeed(m_handle, speed, &status);
Austin Schuh812d0d12021-11-04 20:16:48 -070087 FRC_CheckErrorStatus(status, "Channel {}", m_channel);
Brian Silverman8fce7482020-01-05 13:18:21 -080088}
89
90double PWM::GetSpeed() const {
Brian Silverman8fce7482020-01-05 13:18:21 -080091 int32_t status = 0;
92 double speed = HAL_GetPWMSpeed(m_handle, &status);
Austin Schuh812d0d12021-11-04 20:16:48 -070093 FRC_CheckErrorStatus(status, "Channel {}", m_channel);
Brian Silverman8fce7482020-01-05 13:18:21 -080094 return speed;
95}
96
97void PWM::SetDisabled() {
Brian Silverman8fce7482020-01-05 13:18:21 -080098 int32_t status = 0;
Brian Silverman8fce7482020-01-05 13:18:21 -080099 HAL_SetPWMDisabled(m_handle, &status);
Austin Schuh812d0d12021-11-04 20:16:48 -0700100 FRC_CheckErrorStatus(status, "Channel {}", m_channel);
Brian Silverman8fce7482020-01-05 13:18:21 -0800101}
102
103void PWM::SetPeriodMultiplier(PeriodMultiplier mult) {
Brian Silverman8fce7482020-01-05 13:18:21 -0800104 int32_t status = 0;
105
106 switch (mult) {
107 case kPeriodMultiplier_4X:
108 HAL_SetPWMPeriodScale(m_handle, 3,
109 &status); // Squelch 3 out of 4 outputs
110 break;
111 case kPeriodMultiplier_2X:
112 HAL_SetPWMPeriodScale(m_handle, 1,
113 &status); // Squelch 1 out of 2 outputs
114 break;
115 case kPeriodMultiplier_1X:
116 HAL_SetPWMPeriodScale(m_handle, 0, &status); // Don't squelch any outputs
117 break;
118 default:
Austin Schuh812d0d12021-11-04 20:16:48 -0700119 throw FRC_MakeError(err::InvalidParameter, "PeriodMultiplier value {}",
James Kuszmaulcf324122023-01-14 14:07:17 -0800120 static_cast<int>(mult));
Brian Silverman8fce7482020-01-05 13:18:21 -0800121 }
122
Austin Schuh812d0d12021-11-04 20:16:48 -0700123 FRC_CheckErrorStatus(status, "Channel {}", m_channel);
Brian Silverman8fce7482020-01-05 13:18:21 -0800124}
125
126void PWM::SetZeroLatch() {
Brian Silverman8fce7482020-01-05 13:18:21 -0800127 int32_t status = 0;
Brian Silverman8fce7482020-01-05 13:18:21 -0800128 HAL_LatchPWMZero(m_handle, &status);
Austin Schuh812d0d12021-11-04 20:16:48 -0700129 FRC_CheckErrorStatus(status, "Channel {}", m_channel);
Brian Silverman8fce7482020-01-05 13:18:21 -0800130}
131
132void PWM::EnableDeadbandElimination(bool eliminateDeadband) {
Brian Silverman8fce7482020-01-05 13:18:21 -0800133 int32_t status = 0;
134 HAL_SetPWMEliminateDeadband(m_handle, eliminateDeadband, &status);
Austin Schuh812d0d12021-11-04 20:16:48 -0700135 FRC_CheckErrorStatus(status, "Channel {}", m_channel);
Brian Silverman8fce7482020-01-05 13:18:21 -0800136}
137
James Kuszmaulb13e13f2023-11-22 20:44:04 -0800138void PWM::SetBounds(units::microsecond_t max, units::microsecond_t deadbandMax,
139 units::microsecond_t center,
140 units::microsecond_t deadbandMin,
141 units::microsecond_t min) {
Brian Silverman8fce7482020-01-05 13:18:21 -0800142 int32_t status = 0;
James Kuszmaulb13e13f2023-11-22 20:44:04 -0800143 HAL_SetPWMConfigMicroseconds(m_handle, max.value(), deadbandMax.value(),
144 center.value(), deadbandMin.value(), min.value(),
145 &status);
Austin Schuh812d0d12021-11-04 20:16:48 -0700146 FRC_CheckErrorStatus(status, "Channel {}", m_channel);
Brian Silverman8fce7482020-01-05 13:18:21 -0800147}
148
James Kuszmaulb13e13f2023-11-22 20:44:04 -0800149void PWM::GetBounds(units::microsecond_t* max,
150 units::microsecond_t* deadbandMax,
151 units::microsecond_t* center,
152 units::microsecond_t* deadbandMin,
153 units::microsecond_t* min) {
Brian Silverman8fce7482020-01-05 13:18:21 -0800154 int32_t status = 0;
James Kuszmaulb13e13f2023-11-22 20:44:04 -0800155 int32_t rawMax, rawDeadbandMax, rawCenter, rawDeadbandMin, rawMin;
156 HAL_GetPWMConfigMicroseconds(m_handle, &rawMax, &rawDeadbandMax, &rawCenter,
157 &rawDeadbandMin, &rawMin, &status);
158 *max = units::microsecond_t{static_cast<double>(rawMax)};
159 *deadbandMax = units::microsecond_t{static_cast<double>(rawDeadbandMax)};
160 *center = units::microsecond_t{static_cast<double>(rawCenter)};
161 *deadbandMin = units::microsecond_t{static_cast<double>(rawDeadbandMin)};
162 *min = units::microsecond_t{static_cast<double>(rawMin)};
Austin Schuh812d0d12021-11-04 20:16:48 -0700163 FRC_CheckErrorStatus(status, "Channel {}", m_channel);
Brian Silverman8fce7482020-01-05 13:18:21 -0800164}
165
James Kuszmaulb13e13f2023-11-22 20:44:04 -0800166void PWM::SetAlwaysHighMode() {
Brian Silverman8fce7482020-01-05 13:18:21 -0800167 int32_t status = 0;
James Kuszmaulb13e13f2023-11-22 20:44:04 -0800168 HAL_SetPWMAlwaysHighMode(m_handle, &status);
Austin Schuh812d0d12021-11-04 20:16:48 -0700169 FRC_CheckErrorStatus(status, "Channel {}", m_channel);
Brian Silverman8fce7482020-01-05 13:18:21 -0800170}
171
Austin Schuh812d0d12021-11-04 20:16:48 -0700172int PWM::GetChannel() const {
173 return m_channel;
174}
Brian Silverman8fce7482020-01-05 13:18:21 -0800175
Austin Schuh812d0d12021-11-04 20:16:48 -0700176void PWM::InitSendable(wpi::SendableBuilder& builder) {
Brian Silverman8fce7482020-01-05 13:18:21 -0800177 builder.SetSmartDashboardType("PWM");
178 builder.SetActuator(true);
James Kuszmaulcf324122023-01-14 14:07:17 -0800179 builder.SetSafeState([=, this] { SetDisabled(); });
Austin Schuh1e69f942020-11-14 15:06:14 -0800180 builder.AddDoubleProperty(
James Kuszmaulb13e13f2023-11-22 20:44:04 -0800181 "Value", [=, this] { return GetPulseTime().value(); },
182 [=, this](double value) { SetPulseTime(units::millisecond_t{value}); });
183 builder.AddDoubleProperty(
184 "Speed", [=, this] { return GetSpeed(); },
185 [=, this](double value) { SetSpeed(value); });
186 builder.AddDoubleProperty(
187 "Position", [=, this] { return GetPosition(); },
188 [=, this](double value) { SetPosition(value); });
Brian Silverman8fce7482020-01-05 13:18:21 -0800189}