blob: 2e3a3488e585810e4baf255646abfaeb01e3c487 [file] [log] [blame]
Brian Silverman41cdd3e2019-01-19 19:48:58 -08001/*----------------------------------------------------------------------------*/
2/* Copyright (c) 2017-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/AnalogOutput.h"
9
10#include "HALInitializer.h"
11#include "PortsInternal.h"
12#include "hal/Errors.h"
13#include "hal/handles/HandlesInternal.h"
14#include "hal/handles/IndexedHandleResource.h"
15#include "mockdata/AnalogOutDataInternal.h"
16
17using namespace hal;
18
19namespace {
20struct AnalogOutput {
21 uint8_t channel;
22};
23} // namespace
24
25static IndexedHandleResource<HAL_AnalogOutputHandle, AnalogOutput,
26 kNumAnalogOutputs, HAL_HandleEnum::AnalogOutput>*
27 analogOutputHandles;
28
29namespace hal {
30namespace init {
31void InitializeAnalogOutput() {
32 static IndexedHandleResource<HAL_AnalogOutputHandle, AnalogOutput,
33 kNumAnalogOutputs, HAL_HandleEnum::AnalogOutput>
34 aoH;
35 analogOutputHandles = &aoH;
36}
37} // namespace init
38} // namespace hal
39
40extern "C" {
41HAL_AnalogOutputHandle HAL_InitializeAnalogOutputPort(HAL_PortHandle portHandle,
42 int32_t* status) {
43 hal::init::CheckInit();
44 int16_t channel = getPortHandleChannel(portHandle);
45 if (channel == InvalidHandleIndex) {
46 *status = PARAMETER_OUT_OF_RANGE;
47 return HAL_kInvalidHandle;
48 }
49
50 HAL_AnalogOutputHandle handle =
51 analogOutputHandles->Allocate(channel, status);
52
53 if (*status != 0)
54 return HAL_kInvalidHandle; // failed to allocate. Pass error back.
55
56 auto port = analogOutputHandles->Get(handle);
57 if (port == nullptr) { // would only error on thread issue
58 *status = HAL_HANDLE_ERROR;
59 return HAL_kInvalidHandle;
60 }
61
62 port->channel = static_cast<uint8_t>(channel);
63
64 // Initialize sim analog input
65 SimAnalogOutData[channel].initialized = true;
66 return handle;
67}
68
69void HAL_FreeAnalogOutputPort(HAL_AnalogOutputHandle analogOutputHandle) {
70 // no status, so no need to check for a proper free.
71 auto port = analogOutputHandles->Get(analogOutputHandle);
72 if (port == nullptr) return;
73 analogOutputHandles->Free(analogOutputHandle);
74 SimAnalogOutData[port->channel].initialized = false;
75}
76
77HAL_Bool HAL_CheckAnalogOutputChannel(int32_t channel) {
78 return channel < kNumAnalogOutputs && channel >= 0;
79}
80
81void HAL_SetAnalogOutput(HAL_AnalogOutputHandle analogOutputHandle,
82 double voltage, int32_t* status) {
83 auto port = analogOutputHandles->Get(analogOutputHandle);
84 if (port == nullptr) {
85 *status = HAL_HANDLE_ERROR;
86 return;
87 }
88
89 SimAnalogOutData[port->channel].voltage = voltage;
90}
91
92double HAL_GetAnalogOutput(HAL_AnalogOutputHandle analogOutputHandle,
93 int32_t* status) {
94 auto port = analogOutputHandles->Get(analogOutputHandle);
95 if (port == nullptr) {
96 *status = HAL_HANDLE_ERROR;
97 return 0.0;
98 }
99
100 return SimAnalogOutData[port->channel].voltage;
101}
102} // extern "C"