blob: d04224a4a647634c44a5e90d7082943004108b01 [file] [log] [blame]
Austin Schuh812d0d12021-11-04 20:16:48 -07001// Copyright (c) FIRST and other WPILib contributors.
2// Open Source Software; you can modify and/or share it under the terms of
3// the WPILib BSD license file in the root directory of this project.
Brian Silverman8fce7482020-01-05 13:18:21 -08004
5#include "hal/AnalogOutput.h"
6
Austin Schuh812d0d12021-11-04 20:16:48 -07007#include <string>
8
Brian Silverman8fce7482020-01-05 13:18:21 -08009#include "HALInitializer.h"
Austin Schuh812d0d12021-11-04 20:16:48 -070010#include "HALInternal.h"
Brian Silverman8fce7482020-01-05 13:18:21 -080011#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;
Austin Schuh812d0d12021-11-04 20:16:48 -070022 std::string previousAllocation;
Brian Silverman8fce7482020-01-05 13:18:21 -080023};
24} // namespace
25
26static IndexedHandleResource<HAL_AnalogOutputHandle, AnalogOutput,
27 kNumAnalogOutputs, HAL_HandleEnum::AnalogOutput>*
28 analogOutputHandles;
29
Austin Schuh812d0d12021-11-04 20:16:48 -070030namespace hal::init {
Brian Silverman8fce7482020-01-05 13:18:21 -080031void InitializeAnalogOutput() {
32 static IndexedHandleResource<HAL_AnalogOutputHandle, AnalogOutput,
33 kNumAnalogOutputs, HAL_HandleEnum::AnalogOutput>
34 aoH;
35 analogOutputHandles = &aoH;
36}
Austin Schuh812d0d12021-11-04 20:16:48 -070037} // namespace hal::init
Brian Silverman8fce7482020-01-05 13:18:21 -080038
39extern "C" {
Austin Schuh812d0d12021-11-04 20:16:48 -070040HAL_AnalogOutputHandle HAL_InitializeAnalogOutputPort(
41 HAL_PortHandle portHandle, const char* allocationLocation,
42 int32_t* status) {
Brian Silverman8fce7482020-01-05 13:18:21 -080043 hal::init::CheckInit();
44 int16_t channel = getPortHandleChannel(portHandle);
Austin Schuh812d0d12021-11-04 20:16:48 -070045 if (channel == InvalidHandleIndex || channel >= kNumAnalogOutputs) {
46 *status = RESOURCE_OUT_OF_RANGE;
47 hal::SetLastErrorIndexOutOfRange(status, "Invalid Index for Analog Output",
48 0, kNumAnalogOutputs, channel);
Brian Silverman8fce7482020-01-05 13:18:21 -080049 return HAL_kInvalidHandle;
50 }
51
Austin Schuh812d0d12021-11-04 20:16:48 -070052 HAL_AnalogOutputHandle handle;
53 auto port = analogOutputHandles->Allocate(channel, &handle, status);
Brian Silverman8fce7482020-01-05 13:18:21 -080054
Austin Schuh812d0d12021-11-04 20:16:48 -070055 if (*status != 0) {
56 if (port) {
57 hal::SetLastErrorPreviouslyAllocated(status, "Analog Output", channel,
58 port->previousAllocation);
59 } else {
60 hal::SetLastErrorIndexOutOfRange(status,
61 "Invalid Index for Analog Output", 0,
62 kNumAnalogOutputs, channel);
63 }
Brian Silverman8fce7482020-01-05 13:18:21 -080064 return HAL_kInvalidHandle; // failed to allocate. Pass error back.
Brian Silverman8fce7482020-01-05 13:18:21 -080065 }
66
67 port->channel = static_cast<uint8_t>(channel);
68
69 // Initialize sim analog input
70 SimAnalogOutData[channel].initialized = true;
Austin Schuh812d0d12021-11-04 20:16:48 -070071
72 port->previousAllocation = allocationLocation ? allocationLocation : "";
Brian Silverman8fce7482020-01-05 13:18:21 -080073 return handle;
74}
75
76void HAL_FreeAnalogOutputPort(HAL_AnalogOutputHandle analogOutputHandle) {
77 // no status, so no need to check for a proper free.
78 auto port = analogOutputHandles->Get(analogOutputHandle);
Austin Schuh812d0d12021-11-04 20:16:48 -070079 if (port == nullptr) {
80 return;
81 }
Brian Silverman8fce7482020-01-05 13:18:21 -080082 analogOutputHandles->Free(analogOutputHandle);
83 SimAnalogOutData[port->channel].initialized = false;
84}
85
86HAL_Bool HAL_CheckAnalogOutputChannel(int32_t channel) {
87 return channel < kNumAnalogOutputs && channel >= 0;
88}
89
90void HAL_SetAnalogOutput(HAL_AnalogOutputHandle analogOutputHandle,
91 double voltage, int32_t* status) {
92 auto port = analogOutputHandles->Get(analogOutputHandle);
93 if (port == nullptr) {
94 *status = HAL_HANDLE_ERROR;
95 return;
96 }
97
98 SimAnalogOutData[port->channel].voltage = voltage;
99}
100
101double HAL_GetAnalogOutput(HAL_AnalogOutputHandle analogOutputHandle,
102 int32_t* status) {
103 auto port = analogOutputHandles->Get(analogOutputHandle);
104 if (port == nullptr) {
105 *status = HAL_HANDLE_ERROR;
106 return 0.0;
107 }
108
109 return SimAnalogOutData[port->channel].voltage;
110}
111} // extern "C"