blob: 40fd87c1c1d7763323cd904d331cc9d60e07db28 [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 "TestBench.h"
9#include "frc/AnalogInput.h"
10#include "frc/AnalogOutput.h"
11#include "frc/AnalogTrigger.h"
12#include "frc/Counter.h"
13#include "frc/Timer.h"
14#include "gtest/gtest.h"
15
16using namespace frc;
17
18static const double kDelayTime = 0.01;
19
20/**
21 * A fixture with an analog input and an analog output wired together
22 */
23class AnalogLoopTest : public testing::Test {
24 protected:
25 AnalogInput* m_input;
26 AnalogOutput* m_output;
27
28 void SetUp() override {
29 m_input = new AnalogInput(TestBench::kFakeAnalogOutputChannel);
30 m_output = new AnalogOutput(TestBench::kAnalogOutputChannel);
31 }
32
33 void TearDown() override {
34 delete m_input;
35 delete m_output;
36 }
37};
38
39/**
40 * Test analog inputs and outputs by setting one and making sure the other
41 * matches.
42 */
43TEST_F(AnalogLoopTest, AnalogInputWorks) {
44 // Set the output voltage and check if the input measures the same voltage
45 for (int32_t i = 0; i < 50; i++) {
46 m_output->SetVoltage(i / 10.0);
47
48 Wait(kDelayTime);
49
50 EXPECT_NEAR(m_output->GetVoltage(), m_input->GetVoltage(), 0.01);
51 }
52}
53
54/**
55 * Test if we can use an analog trigger to check if the output is within a
56 * range correctly.
57 */
58TEST_F(AnalogLoopTest, AnalogTriggerWorks) {
59 AnalogTrigger trigger(m_input);
60 trigger.SetLimitsVoltage(2.0, 3.0);
61
62 m_output->SetVoltage(1.0);
63 Wait(kDelayTime);
64
65 EXPECT_FALSE(trigger.GetInWindow())
66 << "Analog trigger is in the window (2V, 3V)";
67 EXPECT_FALSE(trigger.GetTriggerState()) << "Analog trigger is on";
68
69 m_output->SetVoltage(2.5);
70 Wait(kDelayTime);
71
72 EXPECT_TRUE(trigger.GetInWindow())
73 << "Analog trigger is not in the window (2V, 3V)";
74 EXPECT_FALSE(trigger.GetTriggerState()) << "Analog trigger is on";
75
76 m_output->SetVoltage(4.0);
77 Wait(kDelayTime);
78
79 EXPECT_FALSE(trigger.GetInWindow())
80 << "Analog trigger is in the window (2V, 3V)";
81 EXPECT_TRUE(trigger.GetTriggerState()) << "Analog trigger is not on";
82}
83
84/**
85 * Test if we can count the right number of ticks from an analog trigger with
86 * a counter.
87 */
88TEST_F(AnalogLoopTest, AnalogTriggerCounterWorks) {
89 AnalogTrigger trigger(m_input);
90 trigger.SetLimitsVoltage(2.0, 3.0);
91
92 Counter counter(trigger);
93
94 // Turn the analog output low and high 50 times
95 for (int32_t i = 0; i < 50; i++) {
96 m_output->SetVoltage(1.0);
97 Wait(kDelayTime);
98 m_output->SetVoltage(4.0);
99 Wait(kDelayTime);
100 }
101
102 // The counter should be 50
103 EXPECT_EQ(50, counter.Get())
104 << "Analog trigger counter did not count 50 ticks";
105}
106
107static void InterruptHandler(uint32_t interruptAssertedMask, void* param) {
108 *reinterpret_cast<int32_t*>(param) = 12345;
109}
110
111TEST_F(AnalogLoopTest, AsynchronusInterruptWorks) {
112 int32_t param = 0;
113 AnalogTrigger trigger(m_input);
114 trigger.SetLimitsVoltage(2.0, 3.0);
115
116 // Given an interrupt handler that sets an int32_t to 12345
117 std::shared_ptr<AnalogTriggerOutput> triggerOutput =
118 trigger.CreateOutput(AnalogTriggerType::kState);
119 triggerOutput->RequestInterrupts(InterruptHandler, &param);
120 triggerOutput->EnableInterrupts();
121
122 // If the analog output moves from below to above the window
123 m_output->SetVoltage(0.0);
124 Wait(kDelayTime);
125 m_output->SetVoltage(5.0);
126 triggerOutput->CancelInterrupts();
127
128 // Then the int32_t should be 12345
129 Wait(kDelayTime);
130 EXPECT_EQ(12345, param) << "The interrupt did not run.";
131}