blob: c6440709ef958e6f67a8803c5ecb0e1a2a84357f [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/Encoder.h"
6
7#include <utility>
8
9#include <hal/Encoder.h>
10#include <hal/FRCUsageReporting.h>
Austin Schuh812d0d12021-11-04 20:16:48 -070011#include <wpi/NullDeleter.h>
12#include <wpi/sendable/SendableBuilder.h>
13#include <wpi/sendable/SendableRegistry.h>
Brian Silverman8fce7482020-01-05 13:18:21 -080014
15#include "frc/DigitalInput.h"
Austin Schuh812d0d12021-11-04 20:16:48 -070016#include "frc/Errors.h"
Brian Silverman8fce7482020-01-05 13:18:21 -080017
18using namespace frc;
19
20Encoder::Encoder(int aChannel, int bChannel, bool reverseDirection,
21 EncodingType encodingType) {
22 m_aSource = std::make_shared<DigitalInput>(aChannel);
23 m_bSource = std::make_shared<DigitalInput>(bChannel);
24 InitEncoder(reverseDirection, encodingType);
Austin Schuh812d0d12021-11-04 20:16:48 -070025 wpi::SendableRegistry::AddChild(this, m_aSource.get());
26 wpi::SendableRegistry::AddChild(this, m_bSource.get());
Brian Silverman8fce7482020-01-05 13:18:21 -080027}
28
29Encoder::Encoder(DigitalSource* aSource, DigitalSource* bSource,
30 bool reverseDirection, EncodingType encodingType)
Austin Schuh812d0d12021-11-04 20:16:48 -070031 : m_aSource(aSource, wpi::NullDeleter<DigitalSource>()),
32 m_bSource(bSource, wpi::NullDeleter<DigitalSource>()) {
33 if (!m_aSource) {
James Kuszmaulcf324122023-01-14 14:07:17 -080034 throw FRC_MakeError(err::NullParameter, "aSource");
Austin Schuh812d0d12021-11-04 20:16:48 -070035 }
36 if (!m_bSource) {
James Kuszmaulcf324122023-01-14 14:07:17 -080037 throw FRC_MakeError(err::NullParameter, "bSource");
Austin Schuh812d0d12021-11-04 20:16:48 -070038 }
39 InitEncoder(reverseDirection, encodingType);
Brian Silverman8fce7482020-01-05 13:18:21 -080040}
41
42Encoder::Encoder(DigitalSource& aSource, DigitalSource& bSource,
43 bool reverseDirection, EncodingType encodingType)
Austin Schuh812d0d12021-11-04 20:16:48 -070044 : m_aSource(&aSource, wpi::NullDeleter<DigitalSource>()),
45 m_bSource(&bSource, wpi::NullDeleter<DigitalSource>()) {
Brian Silverman8fce7482020-01-05 13:18:21 -080046 InitEncoder(reverseDirection, encodingType);
47}
48
49Encoder::Encoder(std::shared_ptr<DigitalSource> aSource,
50 std::shared_ptr<DigitalSource> bSource, bool reverseDirection,
51 EncodingType encodingType)
Austin Schuh812d0d12021-11-04 20:16:48 -070052 : m_aSource(std::move(aSource)), m_bSource(std::move(bSource)) {
53 if (!m_aSource) {
James Kuszmaulcf324122023-01-14 14:07:17 -080054 throw FRC_MakeError(err::NullParameter, "aSource");
Austin Schuh812d0d12021-11-04 20:16:48 -070055 }
56 if (!m_bSource) {
James Kuszmaulcf324122023-01-14 14:07:17 -080057 throw FRC_MakeError(err::NullParameter, "bSource");
Austin Schuh812d0d12021-11-04 20:16:48 -070058 }
59 InitEncoder(reverseDirection, encodingType);
Brian Silverman8fce7482020-01-05 13:18:21 -080060}
61
62Encoder::~Encoder() {
63 int32_t status = 0;
64 HAL_FreeEncoder(m_encoder, &status);
James Kuszmaulcf324122023-01-14 14:07:17 -080065 FRC_ReportError(status, "FreeEncoder");
Brian Silverman8fce7482020-01-05 13:18:21 -080066}
67
68int Encoder::Get() const {
Brian Silverman8fce7482020-01-05 13:18:21 -080069 int32_t status = 0;
70 int value = HAL_GetEncoder(m_encoder, &status);
James Kuszmaulcf324122023-01-14 14:07:17 -080071 FRC_CheckErrorStatus(status, "Get");
Brian Silverman8fce7482020-01-05 13:18:21 -080072 return value;
73}
74
75void Encoder::Reset() {
Brian Silverman8fce7482020-01-05 13:18:21 -080076 int32_t status = 0;
77 HAL_ResetEncoder(m_encoder, &status);
James Kuszmaulcf324122023-01-14 14:07:17 -080078 FRC_CheckErrorStatus(status, "Reset");
Brian Silverman8fce7482020-01-05 13:18:21 -080079}
80
Austin Schuh812d0d12021-11-04 20:16:48 -070081units::second_t Encoder::GetPeriod() const {
Brian Silverman8fce7482020-01-05 13:18:21 -080082 int32_t status = 0;
83 double value = HAL_GetEncoderPeriod(m_encoder, &status);
James Kuszmaulcf324122023-01-14 14:07:17 -080084 FRC_CheckErrorStatus(status, "GetPeriod");
Austin Schuh812d0d12021-11-04 20:16:48 -070085 return units::second_t{value};
Brian Silverman8fce7482020-01-05 13:18:21 -080086}
87
Austin Schuh812d0d12021-11-04 20:16:48 -070088void Encoder::SetMaxPeriod(units::second_t maxPeriod) {
Brian Silverman8fce7482020-01-05 13:18:21 -080089 int32_t status = 0;
Austin Schuh812d0d12021-11-04 20:16:48 -070090 HAL_SetEncoderMaxPeriod(m_encoder, maxPeriod.value(), &status);
James Kuszmaulcf324122023-01-14 14:07:17 -080091 FRC_CheckErrorStatus(status, "SetMaxPeriod");
Brian Silverman8fce7482020-01-05 13:18:21 -080092}
93
94bool Encoder::GetStopped() const {
Brian Silverman8fce7482020-01-05 13:18:21 -080095 int32_t status = 0;
96 bool value = HAL_GetEncoderStopped(m_encoder, &status);
James Kuszmaulcf324122023-01-14 14:07:17 -080097 FRC_CheckErrorStatus(status, "GetStopped");
Brian Silverman8fce7482020-01-05 13:18:21 -080098 return value;
99}
100
101bool Encoder::GetDirection() const {
Brian Silverman8fce7482020-01-05 13:18:21 -0800102 int32_t status = 0;
103 bool value = HAL_GetEncoderDirection(m_encoder, &status);
James Kuszmaulcf324122023-01-14 14:07:17 -0800104 FRC_CheckErrorStatus(status, "GetDirection");
Brian Silverman8fce7482020-01-05 13:18:21 -0800105 return value;
106}
107
108int Encoder::GetRaw() const {
Brian Silverman8fce7482020-01-05 13:18:21 -0800109 int32_t status = 0;
110 int value = HAL_GetEncoderRaw(m_encoder, &status);
James Kuszmaulcf324122023-01-14 14:07:17 -0800111 FRC_CheckErrorStatus(status, "GetRaw");
Brian Silverman8fce7482020-01-05 13:18:21 -0800112 return value;
113}
114
115int Encoder::GetEncodingScale() const {
116 int32_t status = 0;
117 int val = HAL_GetEncoderEncodingScale(m_encoder, &status);
James Kuszmaulcf324122023-01-14 14:07:17 -0800118 FRC_CheckErrorStatus(status, "GetEncodingScale");
Brian Silverman8fce7482020-01-05 13:18:21 -0800119 return val;
120}
121
122double Encoder::GetDistance() const {
Brian Silverman8fce7482020-01-05 13:18:21 -0800123 int32_t status = 0;
124 double value = HAL_GetEncoderDistance(m_encoder, &status);
James Kuszmaulcf324122023-01-14 14:07:17 -0800125 FRC_CheckErrorStatus(status, "GetDistance");
Brian Silverman8fce7482020-01-05 13:18:21 -0800126 return value;
127}
128
129double Encoder::GetRate() const {
Brian Silverman8fce7482020-01-05 13:18:21 -0800130 int32_t status = 0;
131 double value = HAL_GetEncoderRate(m_encoder, &status);
James Kuszmaulcf324122023-01-14 14:07:17 -0800132 FRC_CheckErrorStatus(status, "GetRate");
Brian Silverman8fce7482020-01-05 13:18:21 -0800133 return value;
134}
135
136void Encoder::SetMinRate(double minRate) {
Brian Silverman8fce7482020-01-05 13:18:21 -0800137 int32_t status = 0;
138 HAL_SetEncoderMinRate(m_encoder, minRate, &status);
James Kuszmaulcf324122023-01-14 14:07:17 -0800139 FRC_CheckErrorStatus(status, "SetMinRate");
Brian Silverman8fce7482020-01-05 13:18:21 -0800140}
141
142void Encoder::SetDistancePerPulse(double distancePerPulse) {
Brian Silverman8fce7482020-01-05 13:18:21 -0800143 int32_t status = 0;
144 HAL_SetEncoderDistancePerPulse(m_encoder, distancePerPulse, &status);
James Kuszmaulcf324122023-01-14 14:07:17 -0800145 FRC_CheckErrorStatus(status, "SetDistancePerPulse");
Brian Silverman8fce7482020-01-05 13:18:21 -0800146}
147
148double Encoder::GetDistancePerPulse() const {
Brian Silverman8fce7482020-01-05 13:18:21 -0800149 int32_t status = 0;
150 double distancePerPulse = HAL_GetEncoderDistancePerPulse(m_encoder, &status);
James Kuszmaulcf324122023-01-14 14:07:17 -0800151 FRC_CheckErrorStatus(status, "GetDistancePerPulse");
Brian Silverman8fce7482020-01-05 13:18:21 -0800152 return distancePerPulse;
153}
154
155void Encoder::SetReverseDirection(bool reverseDirection) {
Brian Silverman8fce7482020-01-05 13:18:21 -0800156 int32_t status = 0;
157 HAL_SetEncoderReverseDirection(m_encoder, reverseDirection, &status);
James Kuszmaulcf324122023-01-14 14:07:17 -0800158 FRC_CheckErrorStatus(status, "SetReverseDirection");
Brian Silverman8fce7482020-01-05 13:18:21 -0800159}
160
161void Encoder::SetSamplesToAverage(int samplesToAverage) {
162 if (samplesToAverage < 1 || samplesToAverage > 127) {
Austin Schuh812d0d12021-11-04 20:16:48 -0700163 throw FRC_MakeError(
164 err::ParameterOutOfRange,
165 "Average counter values must be between 1 and 127, got {}",
166 samplesToAverage);
Brian Silverman8fce7482020-01-05 13:18:21 -0800167 }
168 int32_t status = 0;
169 HAL_SetEncoderSamplesToAverage(m_encoder, samplesToAverage, &status);
James Kuszmaulcf324122023-01-14 14:07:17 -0800170 FRC_CheckErrorStatus(status, "SetSamplesToAverage");
Brian Silverman8fce7482020-01-05 13:18:21 -0800171}
172
173int Encoder::GetSamplesToAverage() const {
174 int32_t status = 0;
175 int result = HAL_GetEncoderSamplesToAverage(m_encoder, &status);
James Kuszmaulcf324122023-01-14 14:07:17 -0800176 FRC_CheckErrorStatus(status, "GetSamplesToAverage");
Brian Silverman8fce7482020-01-05 13:18:21 -0800177 return result;
178}
179
Brian Silverman8fce7482020-01-05 13:18:21 -0800180void Encoder::SetIndexSource(int channel, Encoder::IndexingType type) {
181 // Force digital input if just given an index
182 m_indexSource = std::make_shared<DigitalInput>(channel);
Austin Schuh812d0d12021-11-04 20:16:48 -0700183 wpi::SendableRegistry::AddChild(this, m_indexSource.get());
Brian Silverman8fce7482020-01-05 13:18:21 -0800184 SetIndexSource(*m_indexSource.get(), type);
185}
186
187void Encoder::SetIndexSource(const DigitalSource& source,
188 Encoder::IndexingType type) {
189 int32_t status = 0;
Austin Schuh812d0d12021-11-04 20:16:48 -0700190 HAL_SetEncoderIndexSource(m_encoder, source.GetPortHandleForRouting(),
191 static_cast<HAL_AnalogTriggerType>(
192 source.GetAnalogTriggerTypeForRouting()),
193 static_cast<HAL_EncoderIndexingType>(type),
194 &status);
James Kuszmaulcf324122023-01-14 14:07:17 -0800195 FRC_CheckErrorStatus(status, "SetIndexSource");
Brian Silverman8fce7482020-01-05 13:18:21 -0800196}
197
198void Encoder::SetSimDevice(HAL_SimDeviceHandle device) {
199 HAL_SetEncoderSimDevice(m_encoder, device);
200}
201
202int Encoder::GetFPGAIndex() const {
203 int32_t status = 0;
204 int val = HAL_GetEncoderFPGAIndex(m_encoder, &status);
James Kuszmaulcf324122023-01-14 14:07:17 -0800205 FRC_CheckErrorStatus(status, "GetFPGAIndex");
Brian Silverman8fce7482020-01-05 13:18:21 -0800206 return val;
207}
208
Austin Schuh812d0d12021-11-04 20:16:48 -0700209void Encoder::InitSendable(wpi::SendableBuilder& builder) {
Brian Silverman8fce7482020-01-05 13:18:21 -0800210 int32_t status = 0;
211 HAL_EncoderEncodingType type = HAL_GetEncoderEncodingType(m_encoder, &status);
James Kuszmaulcf324122023-01-14 14:07:17 -0800212 FRC_CheckErrorStatus(status, "GetEncodingType");
Austin Schuh812d0d12021-11-04 20:16:48 -0700213 if (type == HAL_EncoderEncodingType::HAL_Encoder_k4X) {
Brian Silverman8fce7482020-01-05 13:18:21 -0800214 builder.SetSmartDashboardType("Quadrature Encoder");
Austin Schuh812d0d12021-11-04 20:16:48 -0700215 } else {
Brian Silverman8fce7482020-01-05 13:18:21 -0800216 builder.SetSmartDashboardType("Encoder");
Austin Schuh812d0d12021-11-04 20:16:48 -0700217 }
Brian Silverman8fce7482020-01-05 13:18:21 -0800218
Austin Schuh1e69f942020-11-14 15:06:14 -0800219 builder.AddDoubleProperty(
James Kuszmaulcf324122023-01-14 14:07:17 -0800220 "Speed", [=, this] { return GetRate(); }, nullptr);
Austin Schuh1e69f942020-11-14 15:06:14 -0800221 builder.AddDoubleProperty(
James Kuszmaulcf324122023-01-14 14:07:17 -0800222 "Distance", [=, this] { return GetDistance(); }, nullptr);
Austin Schuh1e69f942020-11-14 15:06:14 -0800223 builder.AddDoubleProperty(
James Kuszmaulcf324122023-01-14 14:07:17 -0800224 "Distance per Tick", [=, this] { return GetDistancePerPulse(); },
225 nullptr);
Brian Silverman8fce7482020-01-05 13:18:21 -0800226}
227
228void Encoder::InitEncoder(bool reverseDirection, EncodingType encodingType) {
229 int32_t status = 0;
230 m_encoder = HAL_InitializeEncoder(
231 m_aSource->GetPortHandleForRouting(),
Austin Schuh812d0d12021-11-04 20:16:48 -0700232 static_cast<HAL_AnalogTriggerType>(
233 m_aSource->GetAnalogTriggerTypeForRouting()),
Brian Silverman8fce7482020-01-05 13:18:21 -0800234 m_bSource->GetPortHandleForRouting(),
Austin Schuh812d0d12021-11-04 20:16:48 -0700235 static_cast<HAL_AnalogTriggerType>(
236 m_bSource->GetAnalogTriggerTypeForRouting()),
237 reverseDirection, static_cast<HAL_EncoderEncodingType>(encodingType),
238 &status);
James Kuszmaulcf324122023-01-14 14:07:17 -0800239 FRC_CheckErrorStatus(status, "InitEncoder");
Brian Silverman8fce7482020-01-05 13:18:21 -0800240
241 HAL_Report(HALUsageReporting::kResourceType_Encoder, GetFPGAIndex() + 1,
242 encodingType);
Austin Schuh812d0d12021-11-04 20:16:48 -0700243 wpi::SendableRegistry::AddLW(this, "Encoder", m_aSource->GetChannel());
Brian Silverman8fce7482020-01-05 13:18:21 -0800244}
245
246double Encoder::DecodingScaleFactor() const {
Brian Silverman8fce7482020-01-05 13:18:21 -0800247 int32_t status = 0;
248 double val = HAL_GetEncoderDecodingScaleFactor(m_encoder, &status);
James Kuszmaulcf324122023-01-14 14:07:17 -0800249 FRC_CheckErrorStatus(status, "DecodingScaleFactor");
Brian Silverman8fce7482020-01-05 13:18:21 -0800250 return val;
251}