forked from wpilibsuite/allwpilib
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathAddressableLED.cpp
175 lines (153 loc) · 5.32 KB
/
AddressableLED.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
#include "hal/AddressableLED.h"
#include <fmt/format.h>
#include "DigitalInternal.h"
#include "HALInitializer.h"
#include "HALInternal.h"
#include "PortsInternal.h"
#include "hal/Errors.h"
#include "hal/handles/HandlesInternal.h"
#include "hal/handles/LimitedHandleResource.h"
#include "mockdata/AddressableLEDDataInternal.h"
using namespace hal;
namespace {
struct AddressableLED {
uint8_t index;
};
} // namespace
static LimitedHandleResource<HAL_AddressableLEDHandle, AddressableLED,
kNumAddressableLEDs,
HAL_HandleEnum::AddressableLED>* ledHandles;
namespace hal::init {
void InitializeAddressableLED() {
static LimitedHandleResource<HAL_AddressableLEDHandle, AddressableLED,
kNumAddressableLEDs,
HAL_HandleEnum::AddressableLED>
dcH;
ledHandles = &dcH;
}
} // namespace hal::init
extern "C" {
HAL_AddressableLEDHandle HAL_InitializeAddressableLED(
HAL_DigitalHandle outputPort, int32_t* status) {
hal::init::CheckInit();
auto digitalPort =
hal::digitalChannelHandles->Get(outputPort, hal::HAL_HandleEnum::PWM);
if (!digitalPort) {
// If DIO was passed, channel error, else generic error
if (getHandleType(outputPort) == hal::HAL_HandleEnum::DIO) {
*status = HAL_LED_CHANNEL_ERROR;
} else {
*status = HAL_HANDLE_ERROR;
}
return HAL_kInvalidHandle;
}
if (digitalPort->channel >= kNumPWMHeaders) {
*status = HAL_LED_CHANNEL_ERROR;
return HAL_kInvalidHandle;
}
HAL_AddressableLEDHandle handle = ledHandles->Allocate();
if (handle == HAL_kInvalidHandle) {
*status = NO_AVAILABLE_RESOURCES;
return HAL_kInvalidHandle;
}
auto led = ledHandles->Get(handle);
if (!led) { // would only occur on thread issue
*status = HAL_HANDLE_ERROR;
return HAL_kInvalidHandle;
}
int16_t index = getHandleIndex(handle);
SimAddressableLEDData[index].outputPort = digitalPort->channel;
SimAddressableLEDData[index].length = 1;
SimAddressableLEDData[index].running = false;
SimAddressableLEDData[index].initialized = true;
led->index = index;
return handle;
}
void HAL_FreeAddressableLED(HAL_AddressableLEDHandle handle) {
auto led = ledHandles->Get(handle);
ledHandles->Free(handle);
if (!led) {
return;
}
SimAddressableLEDData[led->index].running = false;
SimAddressableLEDData[led->index].initialized = false;
}
void HAL_SetAddressableLEDOutputPort(HAL_AddressableLEDHandle handle,
HAL_DigitalHandle outputPort,
int32_t* status) {
auto led = ledHandles->Get(handle);
if (!led) {
*status = HAL_HANDLE_ERROR;
return;
}
if (auto port = digitalChannelHandles->Get(outputPort, HAL_HandleEnum::PWM)) {
SimAddressableLEDData[led->index].outputPort = port->channel;
} else {
SimAddressableLEDData[led->index].outputPort = -1;
}
}
void HAL_SetAddressableLEDLength(HAL_AddressableLEDHandle handle,
int32_t length, int32_t* status) {
auto led = ledHandles->Get(handle);
if (!led) {
*status = HAL_HANDLE_ERROR;
return;
}
if (length > HAL_kAddressableLEDMaxLength || length < 0) {
*status = PARAMETER_OUT_OF_RANGE;
hal::SetLastError(
status,
fmt::format(
"LED length must be less than or equal to {}. {} was requested",
HAL_kAddressableLEDMaxLength, length));
return;
}
SimAddressableLEDData[led->index].length = length;
}
void HAL_WriteAddressableLEDData(HAL_AddressableLEDHandle handle,
const struct HAL_AddressableLEDData* data,
int32_t length, int32_t* status) {
auto led = ledHandles->Get(handle);
if (!led) {
*status = HAL_HANDLE_ERROR;
return;
}
if (length > SimAddressableLEDData[led->index].length) {
*status = PARAMETER_OUT_OF_RANGE;
hal::SetLastError(
status,
fmt::format(
"Data length must be less than or equal to {}. {} was requested",
SimAddressableLEDData[led->index].length.Get(), length));
return;
}
SimAddressableLEDData[led->index].SetData(data, length);
}
void HAL_SetAddressableLEDBitTiming(HAL_AddressableLEDHandle handle,
int32_t highTime0, int32_t lowTime0,
int32_t highTime1, int32_t lowTime1,
int32_t* status) {}
void HAL_SetAddressableLEDSyncTime(HAL_AddressableLEDHandle handle,
int32_t syncTime, int32_t* status) {}
void HAL_StartAddressableLEDOutput(HAL_AddressableLEDHandle handle,
int32_t* status) {
auto led = ledHandles->Get(handle);
if (!led) {
*status = HAL_HANDLE_ERROR;
return;
}
SimAddressableLEDData[led->index].running = true;
}
void HAL_StopAddressableLEDOutput(HAL_AddressableLEDHandle handle,
int32_t* status) {
auto led = ledHandles->Get(handle);
if (!led) {
*status = HAL_HANDLE_ERROR;
return;
}
SimAddressableLEDData[led->index].running = false;
}
} // extern "C"