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