blob: 0d2b963432af4960d4772270179423a869bb65e8 [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.
4
5#include "hal/PowerDistribution.h"
6
Austin Schuh75263e32022-02-22 18:05:32 -08007#include <cstring>
8#include <thread>
9
Austin Schuh812d0d12021-11-04 20:16:48 -070010#include "CTREPDP.h"
11#include "HALInternal.h"
12#include "PortsInternal.h"
13#include "REVPDH.h"
14#include "hal/Errors.h"
Austin Schuh75263e32022-02-22 18:05:32 -080015#include "hal/HALBase.h"
Austin Schuh812d0d12021-11-04 20:16:48 -070016#include "hal/handles/HandlesInternal.h"
17
18using namespace hal;
19
20extern "C" {
21
22HAL_PowerDistributionHandle HAL_InitializePowerDistribution(
23 int32_t moduleNumber, HAL_PowerDistributionType type,
24 const char* allocationLocation, int32_t* status) {
25 if (type == HAL_PowerDistributionType::HAL_PowerDistributionType_kAutomatic) {
Austin Schuh75263e32022-02-22 18:05:32 -080026 if (moduleNumber != HAL_DEFAULT_POWER_DISTRIBUTION_MODULE) {
27 *status = PARAMETER_OUT_OF_RANGE;
28 hal::SetLastError(
29 status, "Automatic PowerDistributionType must have default module");
30 return HAL_kInvalidHandle;
31 }
32
33 uint64_t waitTime = hal::GetDSInitializeTime() + 400000;
34
35 // Ensure we have been alive for long enough to receive a few Power packets.
36 do {
37 uint64_t currentTime = HAL_GetFPGATime(status);
38 if (*status != 0) {
39 return HAL_kInvalidHandle;
40 }
41 if (currentTime >= waitTime) {
42 break;
43 }
44 std::this_thread::sleep_for(
45 std::chrono::microseconds(waitTime - currentTime));
46 } while (true);
47
48 // Try PDP first
49 auto pdpHandle = HAL_InitializePDP(0, allocationLocation, status);
50 if (pdpHandle != HAL_kInvalidHandle) {
51 *status = 0;
52 HAL_GetPDPVoltage(pdpHandle, status);
53 if (*status == 0 || *status == HAL_CAN_TIMEOUT) {
54 return static_cast<HAL_PowerDistributionHandle>(pdpHandle);
55 }
56 HAL_CleanPDP(pdpHandle);
57 }
58 *status = 0;
59 auto pdhHandle = HAL_InitializeREVPDH(1, allocationLocation, status);
60 return static_cast<HAL_PowerDistributionHandle>(pdhHandle);
Austin Schuh812d0d12021-11-04 20:16:48 -070061 }
62
63 if (type == HAL_PowerDistributionType::HAL_PowerDistributionType_kCTRE) {
64 if (moduleNumber == HAL_DEFAULT_POWER_DISTRIBUTION_MODULE) {
65 moduleNumber = 0;
66 }
67 return static_cast<HAL_PowerDistributionHandle>(
Austin Schuh75263e32022-02-22 18:05:32 -080068 HAL_InitializePDP(moduleNumber, allocationLocation, status));
Austin Schuh812d0d12021-11-04 20:16:48 -070069 } else {
70 if (moduleNumber == HAL_DEFAULT_POWER_DISTRIBUTION_MODULE) {
71 moduleNumber = 1;
72 }
73 return static_cast<HAL_PowerDistributionHandle>(
Austin Schuh75263e32022-02-22 18:05:32 -080074 HAL_InitializeREVPDH(moduleNumber, allocationLocation, status));
Austin Schuh812d0d12021-11-04 20:16:48 -070075 }
76}
77
78#define IsCtre(handle) ::hal::isHandleType(handle, HAL_HandleEnum::CTREPDP)
79
80void HAL_CleanPowerDistribution(HAL_PowerDistributionHandle handle) {
81 if (IsCtre(handle)) {
82 HAL_CleanPDP(handle);
83 } else {
Austin Schuh75263e32022-02-22 18:05:32 -080084 HAL_FreeREVPDH(handle);
Austin Schuh812d0d12021-11-04 20:16:48 -070085 }
86}
87
88int32_t HAL_GetPowerDistributionModuleNumber(HAL_PowerDistributionHandle handle,
89 int32_t* status) {
90 if (IsCtre(handle)) {
91 return HAL_GetPDPModuleNumber(handle, status);
92 } else {
Austin Schuh75263e32022-02-22 18:05:32 -080093 return HAL_GetREVPDHModuleNumber(handle, status);
Austin Schuh812d0d12021-11-04 20:16:48 -070094 }
95}
96
97HAL_Bool HAL_CheckPowerDistributionChannel(HAL_PowerDistributionHandle handle,
98 int32_t channel) {
99 if (IsCtre(handle)) {
100 return HAL_CheckPDPChannel(channel);
101 } else {
Austin Schuh75263e32022-02-22 18:05:32 -0800102 return HAL_CheckREVPDHChannelNumber(channel);
Austin Schuh812d0d12021-11-04 20:16:48 -0700103 }
104}
105
106HAL_Bool HAL_CheckPowerDistributionModule(int32_t module,
107 HAL_PowerDistributionType type) {
108 if (type == HAL_PowerDistributionType::HAL_PowerDistributionType_kCTRE) {
109 return HAL_CheckPDPModule(module);
110 } else {
Austin Schuh75263e32022-02-22 18:05:32 -0800111 return HAL_CheckREVPDHModuleNumber(module);
Austin Schuh812d0d12021-11-04 20:16:48 -0700112 }
113}
114
115HAL_PowerDistributionType HAL_GetPowerDistributionType(
116 HAL_PowerDistributionHandle handle, int32_t* status) {
117 return IsCtre(handle)
118 ? HAL_PowerDistributionType::HAL_PowerDistributionType_kCTRE
119 : HAL_PowerDistributionType::HAL_PowerDistributionType_kRev;
120}
121
122int32_t HAL_GetPowerDistributionNumChannels(HAL_PowerDistributionHandle handle,
123 int32_t* status) {
124 if (IsCtre(handle)) {
125 return kNumCTREPDPChannels;
126 } else {
127 return kNumREVPDHChannels;
128 }
129}
130
131double HAL_GetPowerDistributionTemperature(HAL_PowerDistributionHandle handle,
132 int32_t* status) {
133 if (IsCtre(handle)) {
134 return HAL_GetPDPTemperature(handle, status);
135 } else {
136 // Not supported
137 return 0;
138 }
139}
140
141double HAL_GetPowerDistributionVoltage(HAL_PowerDistributionHandle handle,
142 int32_t* status) {
143 if (IsCtre(handle)) {
144 return HAL_GetPDPVoltage(handle, status);
145 } else {
Austin Schuh75263e32022-02-22 18:05:32 -0800146 return HAL_GetREVPDHVoltage(handle, status);
Austin Schuh812d0d12021-11-04 20:16:48 -0700147 }
148}
149
150double HAL_GetPowerDistributionChannelCurrent(
151 HAL_PowerDistributionHandle handle, int32_t channel, int32_t* status) {
152 if (IsCtre(handle)) {
153 return HAL_GetPDPChannelCurrent(handle, channel, status);
154 } else {
Austin Schuh75263e32022-02-22 18:05:32 -0800155 return HAL_GetREVPDHChannelCurrent(handle, channel, status);
Austin Schuh812d0d12021-11-04 20:16:48 -0700156 }
157}
158
159void HAL_GetPowerDistributionAllChannelCurrents(
160 HAL_PowerDistributionHandle handle, double* currents,
161 int32_t currentsLength, int32_t* status) {
162 if (IsCtre(handle)) {
163 if (currentsLength < kNumCTREPDPChannels) {
164 *status = PARAMETER_OUT_OF_RANGE;
165 SetLastError(status, "Output array not large enough");
166 return;
167 }
168 return HAL_GetPDPAllChannelCurrents(handle, currents, status);
169 } else {
170 if (currentsLength < kNumREVPDHChannels) {
171 *status = PARAMETER_OUT_OF_RANGE;
172 SetLastError(status, "Output array not large enough");
173 return;
174 }
Austin Schuh75263e32022-02-22 18:05:32 -0800175 return HAL_GetREVPDHAllChannelCurrents(handle, currents, status);
Austin Schuh812d0d12021-11-04 20:16:48 -0700176 }
177}
178
179double HAL_GetPowerDistributionTotalCurrent(HAL_PowerDistributionHandle handle,
180 int32_t* status) {
181 if (IsCtre(handle)) {
182 return HAL_GetPDPTotalCurrent(handle, status);
183 } else {
Austin Schuh75263e32022-02-22 18:05:32 -0800184 return HAL_GetREVPDHTotalCurrent(handle, status);
Austin Schuh812d0d12021-11-04 20:16:48 -0700185 }
186}
187
188double HAL_GetPowerDistributionTotalPower(HAL_PowerDistributionHandle handle,
189 int32_t* status) {
190 if (IsCtre(handle)) {
191 return HAL_GetPDPTotalPower(handle, status);
192 } else {
193 // Not currently supported
194 return 0;
195 }
196}
197
198double HAL_GetPowerDistributionTotalEnergy(HAL_PowerDistributionHandle handle,
199 int32_t* status) {
200 if (IsCtre(handle)) {
201 return HAL_GetPDPTotalEnergy(handle, status);
202 } else {
203 // Not currently supported
204 return 0;
205 }
206}
207
208void HAL_ResetPowerDistributionTotalEnergy(HAL_PowerDistributionHandle handle,
209 int32_t* status) {
210 if (IsCtre(handle)) {
211 HAL_ResetPDPTotalEnergy(handle, status);
212 } else {
213 // Not supported
214 }
215}
216
217void HAL_ClearPowerDistributionStickyFaults(HAL_PowerDistributionHandle handle,
218 int32_t* status) {
219 if (IsCtre(handle)) {
220 HAL_ClearPDPStickyFaults(handle, status);
221 } else {
Austin Schuh75263e32022-02-22 18:05:32 -0800222 HAL_ClearREVPDHStickyFaults(handle, status);
Austin Schuh812d0d12021-11-04 20:16:48 -0700223 }
224}
225
226void HAL_SetPowerDistributionSwitchableChannel(
227 HAL_PowerDistributionHandle handle, HAL_Bool enabled, int32_t* status) {
228 if (IsCtre(handle)) {
229 // No-op on CTRE
230 return;
231 } else {
Austin Schuh75263e32022-02-22 18:05:32 -0800232 HAL_SetREVPDHSwitchableChannel(handle, enabled, status);
Austin Schuh812d0d12021-11-04 20:16:48 -0700233 }
234}
235
236HAL_Bool HAL_GetPowerDistributionSwitchableChannel(
237 HAL_PowerDistributionHandle handle, int32_t* status) {
238 if (IsCtre(handle)) {
239 // No-op on CTRE
240 return false;
241 } else {
Austin Schuh75263e32022-02-22 18:05:32 -0800242 return HAL_GetREVPDHSwitchableChannelState(handle, status);
243 }
244}
245
246void HAL_GetPowerDistributionVersion(HAL_PowerDistributionHandle handle,
247 HAL_PowerDistributionVersion* version,
248 int32_t* status) {
249 if (IsCtre(handle)) {
250 std::memset(version, 0, sizeof(*version));
251 } else {
252 HAL_GetREVPDHVersion(handle, version, status);
253 }
254}
255
256void HAL_GetPowerDistributionFaults(HAL_PowerDistributionHandle handle,
257 HAL_PowerDistributionFaults* faults,
258 int32_t* status) {
259 if (IsCtre(handle)) {
260 std::memset(faults, 0, sizeof(*faults));
261 } else {
262 HAL_GetREVPDHFaults(handle, faults, status);
263 }
264}
265
266void HAL_GetPowerDistributionStickyFaults(
267 HAL_PowerDistributionHandle handle,
268 HAL_PowerDistributionStickyFaults* stickyFaults, int32_t* status) {
269 if (IsCtre(handle)) {
270 std::memset(stickyFaults, 0, sizeof(*stickyFaults));
271 } else {
272 HAL_GetREVPDHStickyFaults(handle, stickyFaults, status);
Austin Schuh812d0d12021-11-04 20:16:48 -0700273 }
274}
275
276} // extern "C"