blob: bf5a8ee544300dd23c6b5c021c072cf897afe7cc [file] [log] [blame]
Brian Silverman41cdd3e2019-01-19 19:48:58 -08001/*----------------------------------------------------------------------------*/
2/* Copyright (c) 2014-2018 FIRST. 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
8#include "frc/Encoder.h" // NOLINT(build/include_order)
9
10#include "TestBench.h"
11#include "frc/AnalogOutput.h"
12#include "frc/AnalogTrigger.h"
13#include "frc/DigitalOutput.h"
14#include "frc/Timer.h"
15#include "gtest/gtest.h"
16
17using namespace frc;
18
19static const double kDelayTime = 0.001;
20
21class FakeEncoderTest : public testing::Test {
22 protected:
23 DigitalOutput* m_outputA;
24 DigitalOutput* m_outputB;
25 AnalogOutput* m_indexOutput;
26
27 Encoder* m_encoder;
28 AnalogTrigger* m_indexAnalogTrigger;
29 std::shared_ptr<AnalogTriggerOutput> m_indexAnalogTriggerOutput;
30
31 void SetUp() override {
32 m_outputA = new DigitalOutput(TestBench::kLoop2OutputChannel);
33 m_outputB = new DigitalOutput(TestBench::kLoop1OutputChannel);
34 m_indexOutput = new AnalogOutput(TestBench::kAnalogOutputChannel);
35 m_outputA->Set(false);
36 m_outputB->Set(false);
37 m_encoder = new Encoder(TestBench::kLoop1InputChannel,
38 TestBench::kLoop2InputChannel);
39 m_indexAnalogTrigger =
40 new AnalogTrigger(TestBench::kFakeAnalogOutputChannel);
41 m_indexAnalogTrigger->SetLimitsVoltage(2.0, 3.0);
42 m_indexAnalogTriggerOutput =
43 m_indexAnalogTrigger->CreateOutput(AnalogTriggerType::kState);
44 }
45
46 void TearDown() override {
47 delete m_outputA;
48 delete m_outputB;
49 delete m_indexOutput;
50 delete m_encoder;
51 delete m_indexAnalogTrigger;
52 }
53
54 /**
55 * Output pulses to the encoder's input channels to simulate a change of 100
56 * ticks
57 */
58 void Simulate100QuadratureTicks() {
59 for (int32_t i = 0; i < 100; i++) {
60 m_outputA->Set(true);
61 Wait(kDelayTime);
62 m_outputB->Set(true);
63 Wait(kDelayTime);
64 m_outputA->Set(false);
65 Wait(kDelayTime);
66 m_outputB->Set(false);
67 Wait(kDelayTime);
68 }
69 }
70
71 void SetIndexHigh() {
72 m_indexOutput->SetVoltage(5.0);
73 Wait(kDelayTime);
74 }
75
76 void SetIndexLow() {
77 m_indexOutput->SetVoltage(0.0);
78 Wait(kDelayTime);
79 }
80};
81
82/**
83 * Test the encoder by reseting it to 0 and reading the value.
84 */
85TEST_F(FakeEncoderTest, TestDefaultState) {
86 EXPECT_FLOAT_EQ(0.0, m_encoder->Get()) << "The encoder did not start at 0.";
87}
88
89/**
90 * Test the encoder by setting the digital outputs and reading the value.
91 */
92TEST_F(FakeEncoderTest, TestCountUp) {
93 m_encoder->Reset();
94 Simulate100QuadratureTicks();
95
96 EXPECT_FLOAT_EQ(100.0, m_encoder->Get()) << "Encoder did not count to 100.";
97}
98
99/**
100 * Test that the encoder can stay reset while the index source is high
101 */
102TEST_F(FakeEncoderTest, TestResetWhileHigh) {
103 m_encoder->SetIndexSource(*m_indexAnalogTriggerOutput,
104 Encoder::IndexingType::kResetWhileHigh);
105
106 SetIndexLow();
107 Simulate100QuadratureTicks();
108 SetIndexHigh();
109 EXPECT_EQ(0, m_encoder->Get());
110
111 Simulate100QuadratureTicks();
112 EXPECT_EQ(0, m_encoder->Get());
113}
114
115/**
116 * Test that the encoder can reset when the index source goes from low to high
117 */
118TEST_F(FakeEncoderTest, TestResetOnRisingEdge) {
119 m_encoder->SetIndexSource(*m_indexAnalogTriggerOutput,
120 Encoder::IndexingType::kResetOnRisingEdge);
121
122 SetIndexLow();
123 Simulate100QuadratureTicks();
124 SetIndexHigh();
125 EXPECT_EQ(0, m_encoder->Get());
126
127 Simulate100QuadratureTicks();
128 EXPECT_EQ(100, m_encoder->Get());
129}
130
131/**
132 * Test that the encoder can stay reset while the index source is low
133 */
134TEST_F(FakeEncoderTest, TestResetWhileLow) {
135 m_encoder->SetIndexSource(*m_indexAnalogTriggerOutput,
136 Encoder::IndexingType::kResetWhileLow);
137
138 SetIndexHigh();
139 Simulate100QuadratureTicks();
140 SetIndexLow();
141 EXPECT_EQ(0, m_encoder->Get());
142
143 Simulate100QuadratureTicks();
144 EXPECT_EQ(0, m_encoder->Get());
145}
146
147/**
148 * Test that the encoder can reset when the index source goes from high to low
149 */
150TEST_F(FakeEncoderTest, TestResetOnFallingEdge) {
151 m_encoder->SetIndexSource(*m_indexAnalogTriggerOutput,
152 Encoder::IndexingType::kResetOnFallingEdge);
153
154 SetIndexHigh();
155 Simulate100QuadratureTicks();
156 SetIndexLow();
157 EXPECT_EQ(0, m_encoder->Get());
158
159 Simulate100QuadratureTicks();
160 EXPECT_EQ(100, m_encoder->Get());
161}