blob: 70d3f6f1adcc0a3da410cb376a14c9d2d474f0b4 [file] [log] [blame]
James Kuszmaul4b81d302019-12-14 20:53:14 -08001/*----------------------------------------------------------------------------*/
2/* Copyright (c) 2019 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/AddressableLED.h"
9
10#include "DigitalInternal.h"
11#include "HALInitializer.h"
12#include "PortsInternal.h"
13#include "hal/Errors.h"
14#include "hal/handles/HandlesInternal.h"
15#include "hal/handles/LimitedHandleResource.h"
16#include "mockdata/AddressableLEDDataInternal.h"
17
18using namespace hal;
19
20namespace {
21struct AddressableLED {
22 uint8_t index;
23};
24} // namespace
25
26static LimitedHandleResource<HAL_AddressableLEDHandle, AddressableLED,
27 kNumAddressableLEDs,
28 HAL_HandleEnum::AddressableLED>* ledHandles;
29
30namespace hal {
31namespace init {
32void InitializeAddressableLED() {
33 static LimitedHandleResource<HAL_AddressableLEDHandle, AddressableLED,
34 kNumAddressableLEDs,
35 HAL_HandleEnum::AddressableLED>
36 dcH;
37 ledHandles = &dcH;
38}
39} // namespace init
40} // namespace hal
41
42extern "C" {
43HAL_AddressableLEDHandle HAL_InitializeAddressableLED(
44 HAL_DigitalHandle outputPort, int32_t* status) {
45 hal::init::CheckInit();
46
47 auto digitalPort =
48 hal::digitalChannelHandles->Get(outputPort, hal::HAL_HandleEnum::PWM);
49
50 if (!digitalPort) {
51 // If DIO was passed, channel error, else generic error
52 if (getHandleType(outputPort) == hal::HAL_HandleEnum::DIO) {
53 *status = HAL_LED_CHANNEL_ERROR;
54 } else {
55 *status = HAL_HANDLE_ERROR;
56 }
57 return HAL_kInvalidHandle;
58 }
59
60 if (digitalPort->channel >= kNumPWMHeaders) {
61 *status = HAL_LED_CHANNEL_ERROR;
62 return HAL_kInvalidHandle;
63 }
64
65 HAL_AddressableLEDHandle handle = ledHandles->Allocate();
66 if (handle == HAL_kInvalidHandle) {
67 *status = NO_AVAILABLE_RESOURCES;
68 return HAL_kInvalidHandle;
69 }
70
71 auto led = ledHandles->Get(handle);
72 if (!led) { // would only occur on thread issue
73 *status = HAL_HANDLE_ERROR;
74 return HAL_kInvalidHandle;
75 }
76
77 int16_t index = getHandleIndex(handle);
78 SimAddressableLEDData[index].outputPort = digitalPort->channel;
79 SimAddressableLEDData[index].length = 1;
80 SimAddressableLEDData[index].running = false;
81 SimAddressableLEDData[index].initialized = true;
82 led->index = index;
83 return handle;
84}
85
86void HAL_FreeAddressableLED(HAL_AddressableLEDHandle handle) {
87 auto led = ledHandles->Get(handle);
88 ledHandles->Free(handle);
89 if (!led) return;
90 SimAddressableLEDData[led->index].running = false;
91 SimAddressableLEDData[led->index].initialized = false;
92}
93
94void HAL_SetAddressableLEDOutputPort(HAL_AddressableLEDHandle handle,
95 HAL_DigitalHandle outputPort,
96 int32_t* status) {
97 auto led = ledHandles->Get(handle);
98 if (!led) {
99 *status = HAL_HANDLE_ERROR;
100 return;
101 }
102 if (auto port = digitalChannelHandles->Get(outputPort, HAL_HandleEnum::PWM)) {
103 SimAddressableLEDData[led->index].outputPort = port->channel;
104 } else {
105 SimAddressableLEDData[led->index].outputPort = -1;
106 }
107}
108
109void HAL_SetAddressableLEDLength(HAL_AddressableLEDHandle handle,
110 int32_t length, int32_t* status) {
111 auto led = ledHandles->Get(handle);
112 if (!led) {
113 *status = HAL_HANDLE_ERROR;
114 return;
115 }
116 if (length > HAL_kAddressableLEDMaxLength) {
117 *status = PARAMETER_OUT_OF_RANGE;
118 return;
119 }
120 SimAddressableLEDData[led->index].length = length;
121}
122
123void HAL_WriteAddressableLEDData(HAL_AddressableLEDHandle handle,
124 const struct HAL_AddressableLEDData* data,
125 int32_t length, int32_t* status) {
126 auto led = ledHandles->Get(handle);
127 if (!led) {
128 *status = HAL_HANDLE_ERROR;
129 return;
130 }
131 if (length > SimAddressableLEDData[led->index].length) {
132 *status = PARAMETER_OUT_OF_RANGE;
133 return;
134 }
135 SimAddressableLEDData[led->index].SetData(data, length);
136}
137
138void HAL_SetAddressableLEDBitTiming(HAL_AddressableLEDHandle handle,
139 int32_t lowTime0NanoSeconds,
140 int32_t highTime0NanoSeconds,
141 int32_t lowTime1NanoSeconds,
142 int32_t highTime1NanoSeconds,
143 int32_t* status) {}
144
145void HAL_SetAddressableLEDSyncTime(HAL_AddressableLEDHandle handle,
146 int32_t syncTimeMicroSeconds,
147 int32_t* status) {}
148
149void HAL_StartAddressableLEDOutput(HAL_AddressableLEDHandle handle,
150 int32_t* status) {
151 auto led = ledHandles->Get(handle);
152 if (!led) {
153 *status = HAL_HANDLE_ERROR;
154 return;
155 }
156 SimAddressableLEDData[led->index].running = true;
157}
158
159void HAL_StopAddressableLEDOutput(HAL_AddressableLEDHandle handle,
160 int32_t* status) {
161 auto led = ledHandles->Get(handle);
162 if (!led) {
163 *status = HAL_HANDLE_ERROR;
164 return;
165 }
166 SimAddressableLEDData[led->index].running = false;
167}
168} // extern "C"