blob: d6451780bb1905f24759ed56cd0732cc73bf8646 [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 "frc/PowerDistribution.h"
6
7#include <fmt/format.h>
8#include <hal/FRCUsageReporting.h>
9#include <hal/Ports.h>
10#include <hal/PowerDistribution.h>
11#include <wpi/StackTrace.h>
12#include <wpi/sendable/SendableBuilder.h>
13#include <wpi/sendable/SendableRegistry.h>
14
15#include "frc/Errors.h"
16#include "frc/SensorUtil.h"
17
18static_assert(static_cast<HAL_PowerDistributionType>(
Austin Schuh812d0d12021-11-04 20:16:48 -070019 frc::PowerDistribution::ModuleType::kCTRE) ==
20 HAL_PowerDistributionType::HAL_PowerDistributionType_kCTRE);
21static_assert(static_cast<HAL_PowerDistributionType>(
22 frc::PowerDistribution::ModuleType::kRev) ==
23 HAL_PowerDistributionType::HAL_PowerDistributionType_kRev);
24static_assert(frc::PowerDistribution::kDefaultModule ==
25 HAL_DEFAULT_POWER_DISTRIBUTION_MODULE);
26
27using namespace frc;
28
Austin Schuh75263e32022-02-22 18:05:32 -080029PowerDistribution::PowerDistribution() {
30 auto stack = wpi::GetStackTrace(1);
31
32 int32_t status = 0;
33 m_handle = HAL_InitializePowerDistribution(
34 kDefaultModule,
35 HAL_PowerDistributionType::HAL_PowerDistributionType_kAutomatic,
36 stack.c_str(), &status);
37 FRC_CheckErrorStatus(status, "Module {}", kDefaultModule);
38 m_module = HAL_GetPowerDistributionModuleNumber(m_handle, &status);
39 FRC_ReportError(status, "Module {}", m_module);
40
41 HAL_Report(HALUsageReporting::kResourceType_PDP, m_module + 1);
42 wpi::SendableRegistry::AddLW(this, "PowerDistribution", m_module);
43}
Austin Schuh812d0d12021-11-04 20:16:48 -070044
45PowerDistribution::PowerDistribution(int module, ModuleType moduleType) {
46 auto stack = wpi::GetStackTrace(1);
47
48 int32_t status = 0;
49 m_handle = HAL_InitializePowerDistribution(
50 module, static_cast<HAL_PowerDistributionType>(moduleType), stack.c_str(),
51 &status);
52 FRC_CheckErrorStatus(status, "Module {}", module);
53 m_module = HAL_GetPowerDistributionModuleNumber(m_handle, &status);
54 FRC_ReportError(status, "Module {}", module);
55
56 HAL_Report(HALUsageReporting::kResourceType_PDP, m_module + 1);
57 wpi::SendableRegistry::AddLW(this, "PowerDistribution", m_module);
58}
59
60PowerDistribution::~PowerDistribution() {
61 if (m_handle != HAL_kInvalidHandle) {
62 HAL_CleanPowerDistribution(m_handle);
63 m_handle = HAL_kInvalidHandle;
64 }
65}
66
67double PowerDistribution::GetVoltage() const {
68 int32_t status = 0;
69 double voltage = HAL_GetPowerDistributionVoltage(m_handle, &status);
70 FRC_ReportError(status, "Module {}", m_module);
71 return voltage;
72}
73
74double PowerDistribution::GetTemperature() const {
75 int32_t status = 0;
76 double temperature = HAL_GetPowerDistributionTemperature(m_handle, &status);
77 FRC_ReportError(status, "Module {}", m_module);
78 return temperature;
79}
80
81double PowerDistribution::GetCurrent(int channel) const {
82 int32_t status = 0;
83 double current =
84 HAL_GetPowerDistributionChannelCurrent(m_handle, channel, &status);
85 FRC_ReportError(status, "Module {} Channel {}", m_module, channel);
86
87 return current;
88}
89
90double PowerDistribution::GetTotalCurrent() const {
91 int32_t status = 0;
92 double current = HAL_GetPowerDistributionTotalCurrent(m_handle, &status);
93 FRC_ReportError(status, "Module {}", m_module);
94 return current;
95}
96
97double PowerDistribution::GetTotalPower() const {
98 int32_t status = 0;
99 double power = HAL_GetPowerDistributionTotalPower(m_handle, &status);
100 FRC_ReportError(status, "Module {}", m_module);
101 return power;
102}
103
104double PowerDistribution::GetTotalEnergy() const {
105 int32_t status = 0;
106 double energy = HAL_GetPowerDistributionTotalEnergy(m_handle, &status);
107 FRC_ReportError(status, "Module {}", m_module);
108 return energy;
109}
110
111void PowerDistribution::ResetTotalEnergy() {
112 int32_t status = 0;
113 HAL_ResetPowerDistributionTotalEnergy(m_handle, &status);
114 FRC_ReportError(status, "Module {}", m_module);
115}
116
117void PowerDistribution::ClearStickyFaults() {
118 int32_t status = 0;
119 HAL_ClearPowerDistributionStickyFaults(m_handle, &status);
120 FRC_ReportError(status, "Module {}", m_module);
121}
122
123int PowerDistribution::GetModule() const {
124 return m_module;
125}
126
Austin Schuh75263e32022-02-22 18:05:32 -0800127PowerDistribution::ModuleType PowerDistribution::GetType() const {
128 int32_t status = 0;
129 auto type = HAL_GetPowerDistributionType(m_handle, &status);
130 FRC_ReportError(status, "Module {}", m_module);
131 return static_cast<ModuleType>(type);
132}
133
Austin Schuh812d0d12021-11-04 20:16:48 -0700134bool PowerDistribution::GetSwitchableChannel() const {
135 int32_t status = 0;
136 bool state = HAL_GetPowerDistributionSwitchableChannel(m_handle, &status);
137 FRC_ReportError(status, "Module {}", m_module);
138 return state;
139}
140
141void PowerDistribution::SetSwitchableChannel(bool enabled) {
142 int32_t status = 0;
143 HAL_SetPowerDistributionSwitchableChannel(m_handle, enabled, &status);
144 FRC_ReportError(status, "Module {}", m_module);
145}
146
Austin Schuh75263e32022-02-22 18:05:32 -0800147PowerDistribution::Version PowerDistribution::GetVersion() const {
148 int32_t status = 0;
149 HAL_PowerDistributionVersion halVersion;
150 std::memset(&halVersion, 0, sizeof(halVersion));
151 HAL_GetPowerDistributionVersion(m_handle, &halVersion, &status);
152 FRC_ReportError(status, "Module {}", m_module);
153 PowerDistribution::Version version;
154 static_assert(sizeof(halVersion) == sizeof(version));
155 static_assert(std::is_standard_layout_v<decltype(version)>);
156 static_assert(std::is_trivial_v<decltype(version)>);
157 std::memcpy(&version, &halVersion, sizeof(version));
158 return version;
159}
160
161PowerDistribution::Faults PowerDistribution::GetFaults() const {
162 int32_t status = 0;
163 HAL_PowerDistributionFaults halFaults;
164 std::memset(&halFaults, 0, sizeof(halFaults));
165 HAL_GetPowerDistributionFaults(m_handle, &halFaults, &status);
166 FRC_ReportError(status, "Module {}", m_module);
167 PowerDistribution::Faults faults;
168 static_assert(sizeof(halFaults) == sizeof(faults));
169 static_assert(std::is_standard_layout_v<decltype(faults)>);
170 static_assert(std::is_trivial_v<decltype(faults)>);
171 std::memcpy(&faults, &halFaults, sizeof(faults));
172 return faults;
173}
174
Maxwell Henderson80bec322024-01-09 15:48:44 -0800175bool PowerDistribution::Faults::GetBreakerFault(int channel) const {
176 switch (channel) {
177 case 0:
178 return Channel0BreakerFault != 0;
179 case 1:
180 return Channel1BreakerFault != 0;
181 case 2:
182 return Channel2BreakerFault != 0;
183 case 3:
184 return Channel3BreakerFault != 0;
185 case 4:
186 return Channel4BreakerFault != 0;
187 case 5:
188 return Channel5BreakerFault != 0;
189 case 6:
190 return Channel6BreakerFault != 0;
191 case 7:
192 return Channel7BreakerFault != 0;
193 case 8:
194 return Channel8BreakerFault != 0;
195 case 9:
196 return Channel9BreakerFault != 0;
197 case 10:
198 return Channel10BreakerFault != 0;
199 case 11:
200 return Channel11BreakerFault != 0;
201 case 12:
202 return Channel12BreakerFault != 0;
203 case 13:
204 return Channel13BreakerFault != 0;
205 case 14:
206 return Channel14BreakerFault != 0;
207 case 15:
208 return Channel15BreakerFault != 0;
209 case 16:
210 return Channel16BreakerFault != 0;
211 case 17:
212 return Channel17BreakerFault != 0;
213 case 18:
214 return Channel18BreakerFault != 0;
215 case 19:
216 return Channel19BreakerFault != 0;
217 case 20:
218 return Channel20BreakerFault != 0;
219 case 21:
220 return Channel21BreakerFault != 0;
221 case 22:
222 return Channel22BreakerFault != 0;
223 case 23:
224 return Channel23BreakerFault != 0;
225 default:
226 throw FRC_MakeError(err::ChannelIndexOutOfRange,
227 "Power distribution fault channel out of bounds!");
228 }
229}
230
231bool PowerDistribution::StickyFaults::GetBreakerFault(int channel) const {
232 switch (channel) {
233 case 0:
234 return Channel0BreakerFault != 0;
235 case 1:
236 return Channel1BreakerFault != 0;
237 case 2:
238 return Channel2BreakerFault != 0;
239 case 3:
240 return Channel3BreakerFault != 0;
241 case 4:
242 return Channel4BreakerFault != 0;
243 case 5:
244 return Channel5BreakerFault != 0;
245 case 6:
246 return Channel6BreakerFault != 0;
247 case 7:
248 return Channel7BreakerFault != 0;
249 case 8:
250 return Channel8BreakerFault != 0;
251 case 9:
252 return Channel9BreakerFault != 0;
253 case 10:
254 return Channel10BreakerFault != 0;
255 case 11:
256 return Channel11BreakerFault != 0;
257 case 12:
258 return Channel12BreakerFault != 0;
259 case 13:
260 return Channel13BreakerFault != 0;
261 case 14:
262 return Channel14BreakerFault != 0;
263 case 15:
264 return Channel15BreakerFault != 0;
265 case 16:
266 return Channel16BreakerFault != 0;
267 case 17:
268 return Channel17BreakerFault != 0;
269 case 18:
270 return Channel18BreakerFault != 0;
271 case 19:
272 return Channel19BreakerFault != 0;
273 case 20:
274 return Channel20BreakerFault != 0;
275 case 21:
276 return Channel21BreakerFault != 0;
277 case 22:
278 return Channel22BreakerFault != 0;
279 case 23:
280 return Channel23BreakerFault != 0;
281 default:
282 throw FRC_MakeError(err::ChannelIndexOutOfRange,
283 "Power distribution fault channel out of bounds!");
284 }
285}
286
Austin Schuh75263e32022-02-22 18:05:32 -0800287PowerDistribution::StickyFaults PowerDistribution::GetStickyFaults() const {
288 int32_t status = 0;
289 HAL_PowerDistributionStickyFaults halStickyFaults;
290 std::memset(&halStickyFaults, 0, sizeof(halStickyFaults));
291 HAL_GetPowerDistributionStickyFaults(m_handle, &halStickyFaults, &status);
292 FRC_ReportError(status, "Module {}", m_module);
293 PowerDistribution::StickyFaults stickyFaults;
294 static_assert(sizeof(halStickyFaults) == sizeof(stickyFaults));
295 static_assert(std::is_standard_layout_v<decltype(stickyFaults)>);
296 static_assert(std::is_trivial_v<decltype(stickyFaults)>);
297 std::memcpy(&stickyFaults, &halStickyFaults, sizeof(stickyFaults));
298 return stickyFaults;
299}
300
Austin Schuh812d0d12021-11-04 20:16:48 -0700301void PowerDistribution::InitSendable(wpi::SendableBuilder& builder) {
302 builder.SetSmartDashboardType("PowerDistribution");
303 int32_t status = 0;
304 int numChannels = HAL_GetPowerDistributionNumChannels(m_handle, &status);
305 FRC_ReportError(status, "Module {}", m_module);
Austin Schuh75263e32022-02-22 18:05:32 -0800306 // Use manual reads to avoid printing errors
Austin Schuh812d0d12021-11-04 20:16:48 -0700307 for (int i = 0; i < numChannels; ++i) {
308 builder.AddDoubleProperty(
Austin Schuh75263e32022-02-22 18:05:32 -0800309 fmt::format("Chan{}", i),
James Kuszmaulcf324122023-01-14 14:07:17 -0800310 [=, this] {
Austin Schuh75263e32022-02-22 18:05:32 -0800311 int32_t lStatus = 0;
312 return HAL_GetPowerDistributionChannelCurrent(m_handle, i, &lStatus);
313 },
314 nullptr);
Austin Schuh812d0d12021-11-04 20:16:48 -0700315 }
316 builder.AddDoubleProperty(
Austin Schuh75263e32022-02-22 18:05:32 -0800317 "Voltage",
James Kuszmaulcf324122023-01-14 14:07:17 -0800318 [=, this] {
Austin Schuh75263e32022-02-22 18:05:32 -0800319 int32_t lStatus = 0;
320 return HAL_GetPowerDistributionVoltage(m_handle, &lStatus);
321 },
322 nullptr);
Austin Schuh812d0d12021-11-04 20:16:48 -0700323 builder.AddDoubleProperty(
Austin Schuh75263e32022-02-22 18:05:32 -0800324 "TotalCurrent",
James Kuszmaulcf324122023-01-14 14:07:17 -0800325 [=, this] {
Austin Schuh75263e32022-02-22 18:05:32 -0800326 int32_t lStatus = 0;
327 return HAL_GetPowerDistributionTotalCurrent(m_handle, &lStatus);
328 },
329 nullptr);
Austin Schuh812d0d12021-11-04 20:16:48 -0700330 builder.AddBooleanProperty(
Austin Schuh75263e32022-02-22 18:05:32 -0800331 "SwitchableChannel",
James Kuszmaulcf324122023-01-14 14:07:17 -0800332 [=, this] {
Austin Schuh75263e32022-02-22 18:05:32 -0800333 int32_t lStatus = 0;
334 return HAL_GetPowerDistributionSwitchableChannel(m_handle, &lStatus);
335 },
James Kuszmaulcf324122023-01-14 14:07:17 -0800336 [=, this](bool value) {
Austin Schuh75263e32022-02-22 18:05:32 -0800337 int32_t lStatus = 0;
338 HAL_SetPowerDistributionSwitchableChannel(m_handle, value, &lStatus);
339 });
Austin Schuh812d0d12021-11-04 20:16:48 -0700340}