Austin Schuh | 812d0d1 | 2021-11-04 20:16:48 -0700 | [diff] [blame^] | 1 | // 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. |
| 4 | |
| 5 | #include <units/time.h> |
Brian Silverman | 8fce748 | 2020-01-05 13:18:21 -0800 | [diff] [blame] | 6 | |
| 7 | #include "TestBench.h" |
| 8 | #include "frc/AnalogInput.h" |
| 9 | #include "frc/AnalogOutput.h" |
| 10 | #include "frc/AnalogTrigger.h" |
Austin Schuh | 812d0d1 | 2021-11-04 20:16:48 -0700 | [diff] [blame^] | 11 | #include "frc/AsynchronousInterrupt.h" |
Brian Silverman | 8fce748 | 2020-01-05 13:18:21 -0800 | [diff] [blame] | 12 | #include "frc/Counter.h" |
| 13 | #include "frc/Timer.h" |
| 14 | #include "gtest/gtest.h" |
| 15 | |
Austin Schuh | 812d0d1 | 2021-11-04 20:16:48 -0700 | [diff] [blame^] | 16 | static constexpr auto kDelayTime = 10_ms; |
Brian Silverman | 8fce748 | 2020-01-05 13:18:21 -0800 | [diff] [blame] | 17 | |
| 18 | /** |
| 19 | * Test analog inputs and outputs by setting one and making sure the other |
| 20 | * matches. |
| 21 | */ |
Austin Schuh | 812d0d1 | 2021-11-04 20:16:48 -0700 | [diff] [blame^] | 22 | TEST(AnalogLoopTest, AnalogInputWorks) { |
| 23 | frc::AnalogInput input{TestBench::kFakeAnalogOutputChannel}; |
| 24 | frc::AnalogOutput output{TestBench::kAnalogOutputChannel}; |
| 25 | |
Brian Silverman | 8fce748 | 2020-01-05 13:18:21 -0800 | [diff] [blame] | 26 | // Set the output voltage and check if the input measures the same voltage |
| 27 | for (int32_t i = 0; i < 50; i++) { |
Austin Schuh | 812d0d1 | 2021-11-04 20:16:48 -0700 | [diff] [blame^] | 28 | output.SetVoltage(i / 10.0); |
Brian Silverman | 8fce748 | 2020-01-05 13:18:21 -0800 | [diff] [blame] | 29 | |
Austin Schuh | 812d0d1 | 2021-11-04 20:16:48 -0700 | [diff] [blame^] | 30 | frc::Wait(kDelayTime); |
Brian Silverman | 8fce748 | 2020-01-05 13:18:21 -0800 | [diff] [blame] | 31 | |
Austin Schuh | 812d0d1 | 2021-11-04 20:16:48 -0700 | [diff] [blame^] | 32 | EXPECT_NEAR(output.GetVoltage(), input.GetVoltage(), 0.01); |
Brian Silverman | 8fce748 | 2020-01-05 13:18:21 -0800 | [diff] [blame] | 33 | } |
| 34 | } |
| 35 | |
| 36 | /** |
| 37 | * Test if we can use an analog trigger to check if the output is within a |
| 38 | * range correctly. |
| 39 | */ |
Austin Schuh | 812d0d1 | 2021-11-04 20:16:48 -0700 | [diff] [blame^] | 40 | TEST(AnalogLoopTest, AnalogTriggerWorks) { |
| 41 | frc::AnalogInput input{TestBench::kFakeAnalogOutputChannel}; |
| 42 | frc::AnalogOutput output{TestBench::kAnalogOutputChannel}; |
| 43 | |
| 44 | frc::AnalogTrigger trigger{&input}; |
Brian Silverman | 8fce748 | 2020-01-05 13:18:21 -0800 | [diff] [blame] | 45 | trigger.SetLimitsVoltage(2.0, 3.0); |
| 46 | |
Austin Schuh | 812d0d1 | 2021-11-04 20:16:48 -0700 | [diff] [blame^] | 47 | output.SetVoltage(1.0); |
| 48 | frc::Wait(kDelayTime); |
Brian Silverman | 8fce748 | 2020-01-05 13:18:21 -0800 | [diff] [blame] | 49 | |
| 50 | EXPECT_FALSE(trigger.GetInWindow()) |
| 51 | << "Analog trigger is in the window (2V, 3V)"; |
| 52 | EXPECT_FALSE(trigger.GetTriggerState()) << "Analog trigger is on"; |
| 53 | |
Austin Schuh | 812d0d1 | 2021-11-04 20:16:48 -0700 | [diff] [blame^] | 54 | output.SetVoltage(2.5); |
| 55 | frc::Wait(kDelayTime); |
Brian Silverman | 8fce748 | 2020-01-05 13:18:21 -0800 | [diff] [blame] | 56 | |
| 57 | EXPECT_TRUE(trigger.GetInWindow()) |
| 58 | << "Analog trigger is not in the window (2V, 3V)"; |
| 59 | EXPECT_FALSE(trigger.GetTriggerState()) << "Analog trigger is on"; |
| 60 | |
Austin Schuh | 812d0d1 | 2021-11-04 20:16:48 -0700 | [diff] [blame^] | 61 | output.SetVoltage(4.0); |
| 62 | frc::Wait(kDelayTime); |
Brian Silverman | 8fce748 | 2020-01-05 13:18:21 -0800 | [diff] [blame] | 63 | |
| 64 | EXPECT_FALSE(trigger.GetInWindow()) |
| 65 | << "Analog trigger is in the window (2V, 3V)"; |
| 66 | EXPECT_TRUE(trigger.GetTriggerState()) << "Analog trigger is not on"; |
| 67 | } |
| 68 | |
| 69 | /** |
| 70 | * Test if we can count the right number of ticks from an analog trigger with |
| 71 | * a counter. |
| 72 | */ |
Austin Schuh | 812d0d1 | 2021-11-04 20:16:48 -0700 | [diff] [blame^] | 73 | TEST(AnalogLoopTest, AnalogTriggerCounterWorks) { |
| 74 | frc::AnalogInput input{TestBench::kFakeAnalogOutputChannel}; |
| 75 | frc::AnalogOutput output{TestBench::kAnalogOutputChannel}; |
| 76 | |
| 77 | frc::AnalogTrigger trigger{&input}; |
Brian Silverman | 8fce748 | 2020-01-05 13:18:21 -0800 | [diff] [blame] | 78 | trigger.SetLimitsVoltage(2.0, 3.0); |
| 79 | |
Austin Schuh | 812d0d1 | 2021-11-04 20:16:48 -0700 | [diff] [blame^] | 80 | frc::Counter counter{trigger}; |
Brian Silverman | 8fce748 | 2020-01-05 13:18:21 -0800 | [diff] [blame] | 81 | |
| 82 | // Turn the analog output low and high 50 times |
| 83 | for (int32_t i = 0; i < 50; i++) { |
Austin Schuh | 812d0d1 | 2021-11-04 20:16:48 -0700 | [diff] [blame^] | 84 | output.SetVoltage(1.0); |
| 85 | frc::Wait(kDelayTime); |
| 86 | output.SetVoltage(4.0); |
| 87 | frc::Wait(kDelayTime); |
Brian Silverman | 8fce748 | 2020-01-05 13:18:21 -0800 | [diff] [blame] | 88 | } |
| 89 | |
| 90 | // The counter should be 50 |
| 91 | EXPECT_EQ(50, counter.Get()) |
| 92 | << "Analog trigger counter did not count 50 ticks"; |
| 93 | } |
| 94 | |
Austin Schuh | 812d0d1 | 2021-11-04 20:16:48 -0700 | [diff] [blame^] | 95 | TEST(AnalogLoopTest, AsynchronusInterruptWorks) { |
| 96 | frc::AnalogInput input{TestBench::kFakeAnalogOutputChannel}; |
| 97 | frc::AnalogOutput output{TestBench::kAnalogOutputChannel}; |
Brian Silverman | 8fce748 | 2020-01-05 13:18:21 -0800 | [diff] [blame] | 98 | |
Brian Silverman | 8fce748 | 2020-01-05 13:18:21 -0800 | [diff] [blame] | 99 | int32_t param = 0; |
Austin Schuh | 812d0d1 | 2021-11-04 20:16:48 -0700 | [diff] [blame^] | 100 | frc::AnalogTrigger trigger{&input}; |
Brian Silverman | 8fce748 | 2020-01-05 13:18:21 -0800 | [diff] [blame] | 101 | trigger.SetLimitsVoltage(2.0, 3.0); |
| 102 | |
| 103 | // Given an interrupt handler that sets an int32_t to 12345 |
Austin Schuh | 812d0d1 | 2021-11-04 20:16:48 -0700 | [diff] [blame^] | 104 | std::shared_ptr<frc::AnalogTriggerOutput> triggerOutput = |
| 105 | trigger.CreateOutput(frc::AnalogTriggerType::kState); |
| 106 | |
| 107 | frc::AsynchronousInterrupt interrupt{triggerOutput, |
| 108 | [&](auto a, auto b) { param = 12345; }}; |
| 109 | |
| 110 | interrupt.Enable(); |
Brian Silverman | 8fce748 | 2020-01-05 13:18:21 -0800 | [diff] [blame] | 111 | |
| 112 | // If the analog output moves from below to above the window |
Austin Schuh | 812d0d1 | 2021-11-04 20:16:48 -0700 | [diff] [blame^] | 113 | output.SetVoltage(0.0); |
| 114 | frc::Wait(kDelayTime); |
| 115 | output.SetVoltage(5.0); |
Brian Silverman | 8fce748 | 2020-01-05 13:18:21 -0800 | [diff] [blame] | 116 | // Then the int32_t should be 12345 |
Austin Schuh | 812d0d1 | 2021-11-04 20:16:48 -0700 | [diff] [blame^] | 117 | frc::Wait(kDelayTime); |
| 118 | interrupt.Disable(); |
| 119 | |
Brian Silverman | 8fce748 | 2020-01-05 13:18:21 -0800 | [diff] [blame] | 120 | EXPECT_EQ(12345, param) << "The interrupt did not run."; |
| 121 | } |