blob: 1841c51161ba09d7ca88b10afa3a68da074a81be [file] [log] [blame]
Brian Silverman41cdd3e2019-01-19 19:48:58 -08001/*----------------------------------------------------------------------------*/
2/* Copyright (c) 2016-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 "hal/AnalogTrigger.h"
9
10#include "AnalogInternal.h"
11#include "HALInitializer.h"
12#include "PortsInternal.h"
13#include "hal/AnalogInput.h"
14#include "hal/Errors.h"
15#include "hal/handles/HandlesInternal.h"
16#include "hal/handles/LimitedHandleResource.h"
17
18using namespace hal;
19
20namespace {
21
22struct AnalogTrigger {
23 std::unique_ptr<tAnalogTrigger> trigger;
24 HAL_AnalogInputHandle analogHandle;
25 uint8_t index;
26};
27
28} // namespace
29
30static LimitedHandleResource<HAL_AnalogTriggerHandle, AnalogTrigger,
31 kNumAnalogTriggers, HAL_HandleEnum::AnalogTrigger>*
32 analogTriggerHandles;
33
34namespace hal {
35namespace init {
36void InitializeAnalogTrigger() {
37 static LimitedHandleResource<HAL_AnalogTriggerHandle, AnalogTrigger,
38 kNumAnalogTriggers,
39 HAL_HandleEnum::AnalogTrigger>
40 atH;
41 analogTriggerHandles = &atH;
42}
43} // namespace init
44} // namespace hal
45
46extern "C" {
47
48HAL_AnalogTriggerHandle HAL_InitializeAnalogTrigger(
49 HAL_AnalogInputHandle portHandle, int32_t* index, int32_t* status) {
50 hal::init::CheckInit();
51 // ensure we are given a valid and active AnalogInput handle
52 auto analog_port = analogInputHandles->Get(portHandle);
53 if (analog_port == nullptr) {
54 *status = HAL_HANDLE_ERROR;
55 return HAL_kInvalidHandle;
56 }
57 HAL_AnalogTriggerHandle handle = analogTriggerHandles->Allocate();
58 if (handle == HAL_kInvalidHandle) {
59 *status = NO_AVAILABLE_RESOURCES;
60 return HAL_kInvalidHandle;
61 }
62 auto trigger = analogTriggerHandles->Get(handle);
63 if (trigger == nullptr) { // would only occur on thread issue
64 *status = HAL_HANDLE_ERROR;
65 return HAL_kInvalidHandle;
66 }
67 trigger->analogHandle = portHandle;
68 trigger->index = static_cast<uint8_t>(getHandleIndex(handle));
69 *index = trigger->index;
70
71 trigger->trigger.reset(tAnalogTrigger::create(trigger->index, status));
72 trigger->trigger->writeSourceSelect_Channel(analog_port->channel, status);
73 return handle;
74}
75
76void HAL_CleanAnalogTrigger(HAL_AnalogTriggerHandle analogTriggerHandle,
77 int32_t* status) {
78 analogTriggerHandles->Free(analogTriggerHandle);
79 // caller owns the analog input handle.
80}
81
82void HAL_SetAnalogTriggerLimitsRaw(HAL_AnalogTriggerHandle analogTriggerHandle,
83 int32_t lower, int32_t upper,
84 int32_t* status) {
85 auto trigger = analogTriggerHandles->Get(analogTriggerHandle);
86 if (trigger == nullptr) {
87 *status = HAL_HANDLE_ERROR;
88 return;
89 }
90 if (lower > upper) {
91 *status = ANALOG_TRIGGER_LIMIT_ORDER_ERROR;
92 }
93 trigger->trigger->writeLowerLimit(lower, status);
94 trigger->trigger->writeUpperLimit(upper, status);
95}
96
97void HAL_SetAnalogTriggerLimitsVoltage(
98 HAL_AnalogTriggerHandle analogTriggerHandle, double lower, double upper,
99 int32_t* status) {
100 auto trigger = analogTriggerHandles->Get(analogTriggerHandle);
101 if (trigger == nullptr) {
102 *status = HAL_HANDLE_ERROR;
103 return;
104 }
105 if (lower > upper) {
106 *status = ANALOG_TRIGGER_LIMIT_ORDER_ERROR;
107 }
108
109 // TODO: This depends on the averaged setting. Only raw values will work as
110 // is.
111 trigger->trigger->writeLowerLimit(
112 HAL_GetAnalogVoltsToValue(trigger->analogHandle, lower, status), status);
113 trigger->trigger->writeUpperLimit(
114 HAL_GetAnalogVoltsToValue(trigger->analogHandle, upper, status), status);
115}
116
117void HAL_SetAnalogTriggerAveraged(HAL_AnalogTriggerHandle analogTriggerHandle,
118 HAL_Bool useAveragedValue, int32_t* status) {
119 auto trigger = analogTriggerHandles->Get(analogTriggerHandle);
120 if (trigger == nullptr) {
121 *status = HAL_HANDLE_ERROR;
122 return;
123 }
124 if (trigger->trigger->readSourceSelect_Filter(status) != 0) {
125 *status = INCOMPATIBLE_STATE;
126 // TODO: wpi_setWPIErrorWithContext(IncompatibleMode, "Hardware does not
127 // support average and filtering at the same time.");
128 }
129 trigger->trigger->writeSourceSelect_Averaged(useAveragedValue, status);
130}
131
132void HAL_SetAnalogTriggerFiltered(HAL_AnalogTriggerHandle analogTriggerHandle,
133 HAL_Bool useFilteredValue, int32_t* status) {
134 auto trigger = analogTriggerHandles->Get(analogTriggerHandle);
135 if (trigger == nullptr) {
136 *status = HAL_HANDLE_ERROR;
137 return;
138 }
139 if (trigger->trigger->readSourceSelect_Averaged(status) != 0) {
140 *status = INCOMPATIBLE_STATE;
141 // TODO: wpi_setWPIErrorWithContext(IncompatibleMode, "Hardware does not "
142 // "support average and filtering at the same time.");
143 }
144 trigger->trigger->writeSourceSelect_Filter(useFilteredValue, status);
145}
146
147HAL_Bool HAL_GetAnalogTriggerInWindow(
148 HAL_AnalogTriggerHandle analogTriggerHandle, int32_t* status) {
149 auto trigger = analogTriggerHandles->Get(analogTriggerHandle);
150 if (trigger == nullptr) {
151 *status = HAL_HANDLE_ERROR;
152 return false;
153 }
154 return trigger->trigger->readOutput_InHysteresis(trigger->index, status) != 0;
155}
156
157HAL_Bool HAL_GetAnalogTriggerTriggerState(
158 HAL_AnalogTriggerHandle analogTriggerHandle, int32_t* status) {
159 auto trigger = analogTriggerHandles->Get(analogTriggerHandle);
160 if (trigger == nullptr) {
161 *status = HAL_HANDLE_ERROR;
162 return false;
163 }
164 return trigger->trigger->readOutput_OverLimit(trigger->index, status) != 0;
165}
166
167HAL_Bool HAL_GetAnalogTriggerOutput(HAL_AnalogTriggerHandle analogTriggerHandle,
168 HAL_AnalogTriggerType type,
169 int32_t* status) {
170 auto trigger = analogTriggerHandles->Get(analogTriggerHandle);
171 if (trigger == nullptr) {
172 *status = HAL_HANDLE_ERROR;
173 return false;
174 }
175 bool result = false;
176 switch (type) {
177 case HAL_Trigger_kInWindow:
178 result =
179 trigger->trigger->readOutput_InHysteresis(trigger->index, status);
180 break; // XXX: Backport
181 case HAL_Trigger_kState:
182 result = trigger->trigger->readOutput_OverLimit(trigger->index, status);
183 break; // XXX: Backport
184 case HAL_Trigger_kRisingPulse:
185 case HAL_Trigger_kFallingPulse:
186 *status = ANALOG_TRIGGER_PULSE_OUTPUT_ERROR;
187 return false;
188 }
189 return result;
190}
191
192} // extern "C"