blob: 33642a9e9e03611ee3e0b643b3104a640d9411c9 [file] [log] [blame]
Brian Silvermanf7f267a2017-02-04 16:16:08 -08001/*----------------------------------------------------------------------------*/
2/* Copyright (c) FIRST 2016-2017. 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 "HAL/Errors.h"
12#include "HAL/handles/HandlesInternal.h"
13#include "HAL/handles/IndexedHandleResource.h"
14#include "PortsInternal.h"
15
16using namespace hal;
17
18namespace {
19struct AnalogOutput {
20 uint8_t channel;
21};
22}
23
24static IndexedHandleResource<HAL_AnalogOutputHandle, AnalogOutput,
25 kNumAnalogOutputs, HAL_HandleEnum::AnalogOutput>
26 analogOutputHandles;
27
28extern "C" {
29
30/**
31 * Initialize the analog output port using the given port object.
32 */
33HAL_AnalogOutputHandle HAL_InitializeAnalogOutputPort(HAL_PortHandle portHandle,
34 int32_t* status) {
35 initializeAnalog(status);
36
37 if (*status != 0) return HAL_kInvalidHandle;
38
39 int16_t channel = getPortHandleChannel(portHandle);
40 if (channel == InvalidHandleIndex) {
41 *status = PARAMETER_OUT_OF_RANGE;
42 return HAL_kInvalidHandle;
43 }
44
45 HAL_AnalogOutputHandle handle = analogOutputHandles.Allocate(channel, status);
46
47 if (*status != 0)
48 return HAL_kInvalidHandle; // failed to allocate. Pass error back.
49
50 auto port = analogOutputHandles.Get(handle);
51 if (port == nullptr) { // would only error on thread issue
52 *status = HAL_HANDLE_ERROR;
53 return HAL_kInvalidHandle;
54 }
55
56 port->channel = static_cast<uint8_t>(channel);
57 return handle;
58}
59
60void HAL_FreeAnalogOutputPort(HAL_AnalogOutputHandle analogOutputHandle) {
61 // no status, so no need to check for a proper free.
62 analogOutputHandles.Free(analogOutputHandle);
63}
64
65/**
66 * Check that the analog output channel number is value.
67 * Verify that the analog channel number is one of the legal channel numbers.
68 * Channel numbers are 0-based.
69 *
70 * @return Analog channel is valid
71 */
72HAL_Bool HAL_CheckAnalogOutputChannel(int32_t channel) {
73 return channel < kNumAnalogOutputs && channel >= 0;
74}
75
76void HAL_SetAnalogOutput(HAL_AnalogOutputHandle analogOutputHandle,
77 double voltage, int32_t* status) {
78 auto port = analogOutputHandles.Get(analogOutputHandle);
79 if (port == nullptr) {
80 *status = HAL_HANDLE_ERROR;
81 return;
82 }
83
84 uint16_t rawValue = static_cast<uint16_t>(voltage / 5.0 * 0x1000);
85
86 if (voltage < 0.0)
87 rawValue = 0;
88 else if (voltage > 5.0)
89 rawValue = 0x1000;
90
91 analogOutputSystem->writeMXP(port->channel, rawValue, status);
92}
93
94double HAL_GetAnalogOutput(HAL_AnalogOutputHandle analogOutputHandle,
95 int32_t* status) {
96 auto port = analogOutputHandles.Get(analogOutputHandle);
97 if (port == nullptr) {
98 *status = HAL_HANDLE_ERROR;
99 return 0.0;
100 }
101
102 uint16_t rawValue = analogOutputSystem->readMXP(port->channel, status);
103
104 return rawValue * 5.0 / 0x1000;
105}
106}