blob: 220c89796635c9f38b79702aa5323b54defa13da [file] [log] [blame]
Brian Silvermanf7f267a2017-02-04 16:16:08 -08001/*----------------------------------------------------------------------------*/
2/* Copyright (c) FIRST 2008-2017. 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 "AnalogTrigger.h"
9
10#include <memory>
11
12#include "AnalogInput.h"
13#include "HAL/HAL.h"
14#include "WPIErrors.h"
15
16using namespace frc;
17
18/**
19 * Constructor for an analog trigger given a channel number.
20 *
21 * @param channel The channel number on the roboRIO to represent. 0-3 are
22 * on-board 4-7 are on the MXP port.
23 */
24AnalogTrigger::AnalogTrigger(int channel)
25 : AnalogTrigger(new AnalogInput(channel)) {
26 m_ownsAnalog = true;
27}
28
29/**
30 * Construct an analog trigger given an analog input.
31 *
32 * This should be used in the case of sharing an analog channel between the
33 * trigger and an analog input object.
34 *
35 * @param channel The pointer to the existing AnalogInput object
36 */
37AnalogTrigger::AnalogTrigger(AnalogInput* input) {
38 m_analogInput = input;
39 int32_t status = 0;
40 int index = 0;
41 m_trigger = HAL_InitializeAnalogTrigger(input->m_port, &index, &status);
42 if (status != 0) {
43 wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
44 m_index = std::numeric_limits<int>::max();
45 m_trigger = HAL_kInvalidHandle;
46 return;
47 }
48 m_index = index;
49
50 HAL_Report(HALUsageReporting::kResourceType_AnalogTrigger, input->m_channel);
51}
52
53AnalogTrigger::~AnalogTrigger() {
54 int32_t status = 0;
55 HAL_CleanAnalogTrigger(m_trigger, &status);
56
57 if (m_ownsAnalog && m_analogInput != nullptr) {
58 delete m_analogInput;
59 }
60}
61
62/**
63 * Set the upper and lower limits of the analog trigger.
64 *
65 * The limits are given in ADC codes. If oversampling is used, the units must
66 * be scaled appropriately.
67 *
68 * @param lower The lower limit of the trigger in ADC codes (12-bit values).
69 * @param upper The upper limit of the trigger in ADC codes (12-bit values).
70 */
71void AnalogTrigger::SetLimitsRaw(int lower, int upper) {
72 if (StatusIsFatal()) return;
73 int32_t status = 0;
74 HAL_SetAnalogTriggerLimitsRaw(m_trigger, lower, upper, &status);
75 wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
76}
77
78/**
79 * Set the upper and lower limits of the analog trigger.
80 *
81 * The limits are given as floating point voltage values.
82 *
83 * @param lower The lower limit of the trigger in Volts.
84 * @param upper The upper limit of the trigger in Volts.
85 */
86void AnalogTrigger::SetLimitsVoltage(double lower, double upper) {
87 if (StatusIsFatal()) return;
88 int32_t status = 0;
89 HAL_SetAnalogTriggerLimitsVoltage(m_trigger, lower, upper, &status);
90 wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
91}
92
93/**
94 * Configure the analog trigger to use the averaged vs. raw values.
95 *
96 * If the value is true, then the averaged value is selected for the analog
97 * trigger, otherwise the immediate value is used.
98 *
99 * @param useAveragedValue If true, use the Averaged value, otherwise use the
100 * instantaneous reading
101 */
102void AnalogTrigger::SetAveraged(bool useAveragedValue) {
103 if (StatusIsFatal()) return;
104 int32_t status = 0;
105 HAL_SetAnalogTriggerAveraged(m_trigger, useAveragedValue, &status);
106 wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
107}
108
109/**
110 * Configure the analog trigger to use a filtered value.
111 *
112 * The analog trigger will operate with a 3 point average rejection filter. This
113 * is designed to help with 360 degree pot applications for the period where
114 * the pot crosses through zero.
115 *
116 * @param useFilteredValue If true, use the 3 point rejection filter, otherwise
117 * use the unfiltered value
118 */
119void AnalogTrigger::SetFiltered(bool useFilteredValue) {
120 if (StatusIsFatal()) return;
121 int32_t status = 0;
122 HAL_SetAnalogTriggerFiltered(m_trigger, useFilteredValue, &status);
123 wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
124}
125
126/**
127 * Return the index of the analog trigger.
128 *
129 * This is the FPGA index of this analog trigger instance.
130 *
131 * @return The index of the analog trigger.
132 */
133int AnalogTrigger::GetIndex() const {
134 if (StatusIsFatal()) return -1;
135 return m_index;
136}
137
138/**
139 * Return the InWindow output of the analog trigger.
140 *
141 * True if the analog input is between the upper and lower limits.
142 *
143 * @return True if the analog input is between the upper and lower limits.
144 */
145bool AnalogTrigger::GetInWindow() {
146 if (StatusIsFatal()) return false;
147 int32_t status = 0;
148 bool result = HAL_GetAnalogTriggerInWindow(m_trigger, &status);
149 wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
150 return result;
151}
152
153/**
154 * Return the TriggerState output of the analog trigger.
155 *
156 * True if above upper limit.
157 * False if below lower limit.
158 * If in Hysteresis, maintain previous state.
159 *
160 * @return True if above upper limit. False if below lower limit. If in
161 * Hysteresis, maintain previous state.
162 */
163bool AnalogTrigger::GetTriggerState() {
164 if (StatusIsFatal()) return false;
165 int32_t status = 0;
166 bool result = HAL_GetAnalogTriggerTriggerState(m_trigger, &status);
167 wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
168 return result;
169}
170
171/**
172 * Creates an AnalogTriggerOutput object.
173 *
174 * Gets an output object that can be used for routing.
175 * Caller is responsible for deleting the AnalogTriggerOutput object.
176 *
177 * @param type An enum of the type of output object to create.
178 * @return A pointer to a new AnalogTriggerOutput object.
179 */
180std::shared_ptr<AnalogTriggerOutput> AnalogTrigger::CreateOutput(
181 AnalogTriggerType type) const {
182 if (StatusIsFatal()) return nullptr;
183 return std::shared_ptr<AnalogTriggerOutput>(
184 new AnalogTriggerOutput(*this, type), NullDeleter<AnalogTriggerOutput>());
185}