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