blob: bef6d76aeab579928e99eaf14e70e4801ec0c027 [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) {
34 throw FRC_MakeError(err::NullParameter, "{}", "aSource");
35 }
36 if (!m_bSource) {
37 throw FRC_MakeError(err::NullParameter, "{}", "bSource");
38 }
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) {
54 throw FRC_MakeError(err::NullParameter, "{}", "aSource");
55 }
56 if (!m_bSource) {
57 throw FRC_MakeError(err::NullParameter, "{}", "bSource");
58 }
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);
Austin Schuh812d0d12021-11-04 20:16:48 -070065 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);
Austin Schuh812d0d12021-11-04 20:16:48 -070071 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);
Austin Schuh812d0d12021-11-04 20:16:48 -070078 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);
Austin Schuh812d0d12021-11-04 20:16:48 -070084 FRC_CheckErrorStatus(status, "{}", "GetPeriod");
85 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);
91 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);
Austin Schuh812d0d12021-11-04 20:16:48 -070097 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);
Austin Schuh812d0d12021-11-04 20:16:48 -0700104 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);
Austin Schuh812d0d12021-11-04 20:16:48 -0700111 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);
Austin Schuh812d0d12021-11-04 20:16:48 -0700118 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);
Austin Schuh812d0d12021-11-04 20:16:48 -0700125 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);
Austin Schuh812d0d12021-11-04 20:16:48 -0700132 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);
Austin Schuh812d0d12021-11-04 20:16:48 -0700139 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);
Austin Schuh812d0d12021-11-04 20:16:48 -0700145 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);
Austin Schuh812d0d12021-11-04 20:16:48 -0700151 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);
Austin Schuh812d0d12021-11-04 20:16:48 -0700158 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);
Austin Schuh812d0d12021-11-04 20:16:48 -0700170 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);
Austin Schuh812d0d12021-11-04 20:16:48 -0700176 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);
195 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);
Austin Schuh812d0d12021-11-04 20:16:48 -0700205 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);
Austin Schuh812d0d12021-11-04 20:16:48 -0700212 FRC_CheckErrorStatus(status, "{}", "GetEncodingType");
213 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(
Austin Schuh812d0d12021-11-04 20:16:48 -0700220 "Speed", [=] { return GetRate(); }, nullptr);
Austin Schuh1e69f942020-11-14 15:06:14 -0800221 builder.AddDoubleProperty(
Austin Schuh812d0d12021-11-04 20:16:48 -0700222 "Distance", [=] { return GetDistance(); }, nullptr);
Austin Schuh1e69f942020-11-14 15:06:14 -0800223 builder.AddDoubleProperty(
Austin Schuh812d0d12021-11-04 20:16:48 -0700224 "Distance per Tick", [=] { return GetDistancePerPulse(); }, nullptr);
Brian Silverman8fce7482020-01-05 13:18:21 -0800225}
226
227void Encoder::InitEncoder(bool reverseDirection, EncodingType encodingType) {
228 int32_t status = 0;
229 m_encoder = HAL_InitializeEncoder(
230 m_aSource->GetPortHandleForRouting(),
Austin Schuh812d0d12021-11-04 20:16:48 -0700231 static_cast<HAL_AnalogTriggerType>(
232 m_aSource->GetAnalogTriggerTypeForRouting()),
Brian Silverman8fce7482020-01-05 13:18:21 -0800233 m_bSource->GetPortHandleForRouting(),
Austin Schuh812d0d12021-11-04 20:16:48 -0700234 static_cast<HAL_AnalogTriggerType>(
235 m_bSource->GetAnalogTriggerTypeForRouting()),
236 reverseDirection, static_cast<HAL_EncoderEncodingType>(encodingType),
237 &status);
238 FRC_CheckErrorStatus(status, "{}", "InitEncoder");
Brian Silverman8fce7482020-01-05 13:18:21 -0800239
240 HAL_Report(HALUsageReporting::kResourceType_Encoder, GetFPGAIndex() + 1,
241 encodingType);
Austin Schuh812d0d12021-11-04 20:16:48 -0700242 wpi::SendableRegistry::AddLW(this, "Encoder", m_aSource->GetChannel());
Brian Silverman8fce7482020-01-05 13:18:21 -0800243}
244
245double Encoder::DecodingScaleFactor() const {
Brian Silverman8fce7482020-01-05 13:18:21 -0800246 int32_t status = 0;
247 double val = HAL_GetEncoderDecodingScaleFactor(m_encoder, &status);
Austin Schuh812d0d12021-11-04 20:16:48 -0700248 FRC_CheckErrorStatus(status, "{}", "DecodingScaleFactor");
Brian Silverman8fce7482020-01-05 13:18:21 -0800249 return val;
250}