blob: f6347d906287cf150ca2a140a74e6c0233750b4e [file] [log] [blame]
Brian Silverman8fce7482020-01-05 13:18:21 -08001/*----------------------------------------------------------------------------*/
Austin Schuh1e69f942020-11-14 15:06:14 -08002/* Copyright (c) 2016-2020 FIRST. All Rights Reserved. */
Brian Silverman8fce7482020-01-05 13:18:21 -08003/* 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/DIO.h"
9
Brian Silverman8fce7482020-01-05 13:18:21 -080010#include "DigitalInternal.h"
11#include "HALInitializer.h"
12#include "PortsInternal.h"
13#include "hal/handles/HandlesInternal.h"
14#include "hal/handles/LimitedHandleResource.h"
15#include "mockdata/DIODataInternal.h"
16#include "mockdata/DigitalPWMDataInternal.h"
17
18using namespace hal;
19
20static LimitedHandleResource<HAL_DigitalPWMHandle, uint8_t,
21 kNumDigitalPWMOutputs, HAL_HandleEnum::DigitalPWM>*
22 digitalPWMHandles;
23
24namespace hal {
25namespace init {
26void InitializeDIO() {
27 static LimitedHandleResource<HAL_DigitalPWMHandle, uint8_t,
28 kNumDigitalPWMOutputs,
29 HAL_HandleEnum::DigitalPWM>
30 dpH;
31 digitalPWMHandles = &dpH;
32}
33} // namespace init
34} // namespace hal
35
36extern "C" {
37
38HAL_DigitalHandle HAL_InitializeDIOPort(HAL_PortHandle portHandle,
39 HAL_Bool input, int32_t* status) {
40 hal::init::CheckInit();
41 if (*status != 0) return HAL_kInvalidHandle;
42
43 int16_t channel = getPortHandleChannel(portHandle);
44 if (channel == InvalidHandleIndex) {
45 *status = PARAMETER_OUT_OF_RANGE;
46 return HAL_kInvalidHandle;
47 }
48
49 auto handle =
50 digitalChannelHandles->Allocate(channel, HAL_HandleEnum::DIO, status);
51
52 if (*status != 0)
53 return HAL_kInvalidHandle; // failed to allocate. Pass error back.
54
55 auto port = digitalChannelHandles->Get(handle, HAL_HandleEnum::DIO);
56 if (port == nullptr) { // would only occur on thread issue.
57 *status = HAL_HANDLE_ERROR;
58 return HAL_kInvalidHandle;
59 }
60
61 port->channel = static_cast<uint8_t>(channel);
62
63 SimDIOData[channel].initialized = true;
64 SimDIOData[channel].isInput = input;
65 SimDIOData[channel].simDevice = 0;
66
67 return handle;
68}
69
70HAL_Bool HAL_CheckDIOChannel(int32_t channel) {
71 return channel < kNumDigitalChannels && channel >= 0;
72}
73
74void HAL_FreeDIOPort(HAL_DigitalHandle dioPortHandle) {
75 auto port = digitalChannelHandles->Get(dioPortHandle, HAL_HandleEnum::DIO);
76 // no status, so no need to check for a proper free.
77 digitalChannelHandles->Free(dioPortHandle, HAL_HandleEnum::DIO);
78 if (port == nullptr) return;
79 SimDIOData[port->channel].initialized = false;
80}
81
82void HAL_SetDIOSimDevice(HAL_DigitalHandle handle, HAL_SimDeviceHandle device) {
83 auto port = digitalChannelHandles->Get(handle, HAL_HandleEnum::DIO);
84 if (port == nullptr) return;
85 SimDIOData[port->channel].simDevice = device;
86}
87
88HAL_DigitalPWMHandle HAL_AllocateDigitalPWM(int32_t* status) {
89 auto handle = digitalPWMHandles->Allocate();
90 if (handle == HAL_kInvalidHandle) {
91 *status = NO_AVAILABLE_RESOURCES;
92 return HAL_kInvalidHandle;
93 }
94
95 auto id = digitalPWMHandles->Get(handle);
96 if (id == nullptr) { // would only occur on thread issue.
97 *status = HAL_HANDLE_ERROR;
98 return HAL_kInvalidHandle;
99 }
100 *id = static_cast<uint8_t>(getHandleIndex(handle));
101
102 SimDigitalPWMData[*id].initialized = true;
103
104 return handle;
105}
106
107void HAL_FreeDigitalPWM(HAL_DigitalPWMHandle pwmGenerator, int32_t* status) {
108 auto port = digitalPWMHandles->Get(pwmGenerator);
109 digitalPWMHandles->Free(pwmGenerator);
110 if (port == nullptr) return;
111 int32_t id = *port;
112 SimDigitalPWMData[id].initialized = false;
113}
114
115void HAL_SetDigitalPWMRate(double rate, int32_t* status) {
116 // Currently rounding in the log rate domain... heavy weight toward picking a
117 // higher freq.
118 // TODO: Round in the linear rate domain.
119 // uint8_t pwmPeriodPower = static_cast<uint8_t>(
120 // std::log(1.0 / (kExpectedLoopTiming * 0.25E-6 * rate)) /
121 // std::log(2.0) +
122 // 0.5);
123 // TODO(THAD) : Add a case to set this in the simulator
124 // digitalSystem->writePWMPeriodPower(pwmPeriodPower, status);
125}
126
127void HAL_SetDigitalPWMDutyCycle(HAL_DigitalPWMHandle pwmGenerator,
128 double dutyCycle, int32_t* status) {
129 auto port = digitalPWMHandles->Get(pwmGenerator);
130 if (port == nullptr) {
131 *status = HAL_HANDLE_ERROR;
132 return;
133 }
134 int32_t id = *port;
135 if (dutyCycle > 1.0) dutyCycle = 1.0;
136 if (dutyCycle < 0.0) dutyCycle = 0.0;
137 SimDigitalPWMData[id].dutyCycle = dutyCycle;
138}
139
140void HAL_SetDigitalPWMOutputChannel(HAL_DigitalPWMHandle pwmGenerator,
141 int32_t channel, int32_t* status) {
142 auto port = digitalPWMHandles->Get(pwmGenerator);
143 if (port == nullptr) {
144 *status = HAL_HANDLE_ERROR;
145 return;
146 }
147 int32_t id = *port;
148 SimDigitalPWMData[id].pin = channel;
149}
150
151void HAL_SetDIO(HAL_DigitalHandle dioPortHandle, HAL_Bool value,
152 int32_t* status) {
153 auto port = digitalChannelHandles->Get(dioPortHandle, HAL_HandleEnum::DIO);
154 if (port == nullptr) {
155 *status = HAL_HANDLE_ERROR;
156 return;
157 }
158 if (value != 0 && value != 1) {
159 if (value != 0) value = 1;
160 }
161 SimDIOData[port->channel].value = value;
162}
163
164void HAL_SetDIODirection(HAL_DigitalHandle dioPortHandle, HAL_Bool input,
165 int32_t* status) {
166 auto port = digitalChannelHandles->Get(dioPortHandle, HAL_HandleEnum::DIO);
167 if (port == nullptr) {
168 *status = HAL_HANDLE_ERROR;
169 return;
170 }
171
172 SimDIOData[port->channel].isInput = input;
173}
174
175HAL_Bool HAL_GetDIO(HAL_DigitalHandle dioPortHandle, int32_t* status) {
176 auto port = digitalChannelHandles->Get(dioPortHandle, HAL_HandleEnum::DIO);
177 if (port == nullptr) {
178 *status = HAL_HANDLE_ERROR;
179 return false;
180 }
181 HAL_Bool value = SimDIOData[port->channel].value;
182 if (value > 1) value = 1;
183 if (value < 0) value = 0;
184 return value;
185}
186
187HAL_Bool HAL_GetDIODirection(HAL_DigitalHandle dioPortHandle, int32_t* status) {
188 auto port = digitalChannelHandles->Get(dioPortHandle, HAL_HandleEnum::DIO);
189 if (port == nullptr) {
190 *status = HAL_HANDLE_ERROR;
191 return false;
192 }
193 HAL_Bool value = SimDIOData[port->channel].isInput;
194 if (value > 1) value = 1;
195 if (value < 0) value = 0;
196 return value;
197}
198
199void HAL_Pulse(HAL_DigitalHandle dioPortHandle, double pulseLength,
200 int32_t* status) {
201 auto port = digitalChannelHandles->Get(dioPortHandle, HAL_HandleEnum::DIO);
202 if (port == nullptr) {
203 *status = HAL_HANDLE_ERROR;
204 return;
205 }
206 // TODO (Thad) Add this
207}
208
209HAL_Bool HAL_IsPulsing(HAL_DigitalHandle dioPortHandle, int32_t* status) {
210 auto port = digitalChannelHandles->Get(dioPortHandle, HAL_HandleEnum::DIO);
211 if (port == nullptr) {
212 *status = HAL_HANDLE_ERROR;
213 return false;
214 }
215 return false;
216 // TODO (Thad) Add this
217}
218
219HAL_Bool HAL_IsAnyPulsing(int32_t* status) {
220 return false; // TODO(Thad) Figure this out
221}
222
223void HAL_SetFilterSelect(HAL_DigitalHandle dioPortHandle, int32_t filterIndex,
224 int32_t* status) {
225 auto port = digitalChannelHandles->Get(dioPortHandle, HAL_HandleEnum::DIO);
226 if (port == nullptr) {
227 *status = HAL_HANDLE_ERROR;
228 return;
229 }
230
231 // TODO(Thad) Figure this out
232}
233
234int32_t HAL_GetFilterSelect(HAL_DigitalHandle dioPortHandle, int32_t* status) {
235 auto port = digitalChannelHandles->Get(dioPortHandle, HAL_HandleEnum::DIO);
236 if (port == nullptr) {
237 *status = HAL_HANDLE_ERROR;
238 return 0;
239 }
240 return 0;
241 // TODO(Thad) Figure this out
242}
243
244void HAL_SetFilterPeriod(int32_t filterIndex, int64_t value, int32_t* status) {
245 // TODO(Thad) figure this out
246}
247
248int64_t HAL_GetFilterPeriod(int32_t filterIndex, int32_t* status) {
249 return 0; // TODO(Thad) figure this out
250}
251} // extern "C"