blob: 10c019d59ef51fe0b6dd7f98eaef70c60bfbf7e9 [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 "REVPDH.h"
6
7#include <hal/CANAPI.h>
8#include <hal/CANAPITypes.h>
9#include <hal/Errors.h>
10#include <hal/handles/HandlesInternal.h>
11#include <hal/handles/IndexedHandleResource.h>
12
13#include <cstring>
Austin Schuh75263e32022-02-22 18:05:32 -080014#include <thread>
Austin Schuh812d0d12021-11-04 20:16:48 -070015
16#include <fmt/format.h>
17
18#include "HALInitializer.h"
19#include "HALInternal.h"
20#include "PortsInternal.h"
21#include "rev/PDHFrames.h"
22
23using namespace hal;
24
25static constexpr HAL_CANManufacturer manufacturer =
26 HAL_CANManufacturer::HAL_CAN_Man_kREV;
27
28static constexpr HAL_CANDeviceType deviceType =
29 HAL_CANDeviceType::HAL_CAN_Dev_kPowerDistribution;
30
31static constexpr int32_t kDefaultControlPeriod = 50;
32
33namespace {
34
35struct REV_PDHObj {
36 int32_t controlPeriod;
37 HAL_CANHandle hcan;
38 std::string previousAllocation;
Austin Schuh75263e32022-02-22 18:05:32 -080039 HAL_PowerDistributionVersion versionInfo;
Austin Schuh812d0d12021-11-04 20:16:48 -070040};
41
42} // namespace
43
44static constexpr uint32_t APIFromExtId(uint32_t extId) {
45 return (extId >> 6) & 0x3FF;
46}
47
Austin Schuh75263e32022-02-22 18:05:32 -080048static constexpr uint32_t PDH_SET_SWITCH_CHANNEL_FRAME_API =
49 APIFromExtId(PDH_SET_SWITCH_CHANNEL_FRAME_ID);
Austin Schuh812d0d12021-11-04 20:16:48 -070050
Austin Schuh75263e32022-02-22 18:05:32 -080051static constexpr uint32_t PDH_STATUS_0_FRAME_API =
52 APIFromExtId(PDH_STATUS_0_FRAME_ID);
53static constexpr uint32_t PDH_STATUS_1_FRAME_API =
54 APIFromExtId(PDH_STATUS_1_FRAME_ID);
55static constexpr uint32_t PDH_STATUS_2_FRAME_API =
56 APIFromExtId(PDH_STATUS_2_FRAME_ID);
57static constexpr uint32_t PDH_STATUS_3_FRAME_API =
58 APIFromExtId(PDH_STATUS_3_FRAME_ID);
59static constexpr uint32_t PDH_STATUS_4_FRAME_API =
60 APIFromExtId(PDH_STATUS_4_FRAME_ID);
Austin Schuh812d0d12021-11-04 20:16:48 -070061
62static constexpr uint32_t PDH_CLEAR_FAULTS_FRAME_API =
63 APIFromExtId(PDH_CLEAR_FAULTS_FRAME_ID);
64
Austin Schuh812d0d12021-11-04 20:16:48 -070065static constexpr uint32_t PDH_VERSION_FRAME_API =
66 APIFromExtId(PDH_VERSION_FRAME_ID);
67
Austin Schuh812d0d12021-11-04 20:16:48 -070068static constexpr int32_t kPDHFrameStatus0Timeout = 20;
69static constexpr int32_t kPDHFrameStatus1Timeout = 20;
70static constexpr int32_t kPDHFrameStatus2Timeout = 20;
71static constexpr int32_t kPDHFrameStatus3Timeout = 20;
72static constexpr int32_t kPDHFrameStatus4Timeout = 20;
73
74static IndexedHandleResource<HAL_REVPDHHandle, REV_PDHObj, kNumREVPDHModules,
75 HAL_HandleEnum::REVPDH>* REVPDHHandles;
76
77namespace hal::init {
78void InitializeREVPDH() {
79 static IndexedHandleResource<HAL_REVPDHHandle, REV_PDHObj, kNumREVPDHModules,
80 HAL_HandleEnum::REVPDH>
81 rH;
82 REVPDHHandles = &rH;
83}
84} // namespace hal::init
85
86extern "C" {
87
Austin Schuh75263e32022-02-22 18:05:32 -080088static PDH_status_0_t HAL_ReadREVPDHStatus0(HAL_CANHandle hcan,
Austin Schuh812d0d12021-11-04 20:16:48 -070089 int32_t* status) {
90 uint8_t packedData[8] = {0};
91 int32_t length = 0;
92 uint64_t timestamp = 0;
Austin Schuh75263e32022-02-22 18:05:32 -080093 PDH_status_0_t result = {};
Austin Schuh812d0d12021-11-04 20:16:48 -070094
Austin Schuh75263e32022-02-22 18:05:32 -080095 HAL_ReadCANPacketTimeout(hcan, PDH_STATUS_0_FRAME_API, packedData, &length,
Austin Schuh812d0d12021-11-04 20:16:48 -070096 &timestamp, kPDHFrameStatus0Timeout * 2, status);
97
98 if (*status != 0) {
99 return result;
100 }
101
Austin Schuh75263e32022-02-22 18:05:32 -0800102 PDH_status_0_unpack(&result, packedData, PDH_STATUS_0_LENGTH);
Austin Schuh812d0d12021-11-04 20:16:48 -0700103
104 return result;
105}
106
Austin Schuh75263e32022-02-22 18:05:32 -0800107static PDH_status_1_t HAL_ReadREVPDHStatus1(HAL_CANHandle hcan,
Austin Schuh812d0d12021-11-04 20:16:48 -0700108 int32_t* status) {
109 uint8_t packedData[8] = {0};
110 int32_t length = 0;
111 uint64_t timestamp = 0;
Austin Schuh75263e32022-02-22 18:05:32 -0800112 PDH_status_1_t result = {};
Austin Schuh812d0d12021-11-04 20:16:48 -0700113
Austin Schuh75263e32022-02-22 18:05:32 -0800114 HAL_ReadCANPacketTimeout(hcan, PDH_STATUS_1_FRAME_API, packedData, &length,
Austin Schuh812d0d12021-11-04 20:16:48 -0700115 &timestamp, kPDHFrameStatus1Timeout * 2, status);
116
117 if (*status != 0) {
118 return result;
119 }
120
Austin Schuh75263e32022-02-22 18:05:32 -0800121 PDH_status_1_unpack(&result, packedData, PDH_STATUS_1_LENGTH);
Austin Schuh812d0d12021-11-04 20:16:48 -0700122
123 return result;
124}
125
Austin Schuh75263e32022-02-22 18:05:32 -0800126static PDH_status_2_t HAL_ReadREVPDHStatus2(HAL_CANHandle hcan,
Austin Schuh812d0d12021-11-04 20:16:48 -0700127 int32_t* status) {
128 uint8_t packedData[8] = {0};
129 int32_t length = 0;
130 uint64_t timestamp = 0;
Austin Schuh75263e32022-02-22 18:05:32 -0800131 PDH_status_2_t result = {};
Austin Schuh812d0d12021-11-04 20:16:48 -0700132
Austin Schuh75263e32022-02-22 18:05:32 -0800133 HAL_ReadCANPacketTimeout(hcan, PDH_STATUS_2_FRAME_API, packedData, &length,
Austin Schuh812d0d12021-11-04 20:16:48 -0700134 &timestamp, kPDHFrameStatus2Timeout * 2, status);
135
136 if (*status != 0) {
137 return result;
138 }
139
Austin Schuh75263e32022-02-22 18:05:32 -0800140 PDH_status_2_unpack(&result, packedData, PDH_STATUS_2_LENGTH);
Austin Schuh812d0d12021-11-04 20:16:48 -0700141
142 return result;
143}
144
Austin Schuh75263e32022-02-22 18:05:32 -0800145static PDH_status_3_t HAL_ReadREVPDHStatus3(HAL_CANHandle hcan,
Austin Schuh812d0d12021-11-04 20:16:48 -0700146 int32_t* status) {
147 uint8_t packedData[8] = {0};
148 int32_t length = 0;
149 uint64_t timestamp = 0;
Austin Schuh75263e32022-02-22 18:05:32 -0800150 PDH_status_3_t result = {};
Austin Schuh812d0d12021-11-04 20:16:48 -0700151
Austin Schuh75263e32022-02-22 18:05:32 -0800152 HAL_ReadCANPacketTimeout(hcan, PDH_STATUS_3_FRAME_API, packedData, &length,
Austin Schuh812d0d12021-11-04 20:16:48 -0700153 &timestamp, kPDHFrameStatus3Timeout * 2, status);
154
155 if (*status != 0) {
156 return result;
157 }
158
Austin Schuh75263e32022-02-22 18:05:32 -0800159 PDH_status_3_unpack(&result, packedData, PDH_STATUS_3_LENGTH);
Austin Schuh812d0d12021-11-04 20:16:48 -0700160
161 return result;
162}
163
Austin Schuh75263e32022-02-22 18:05:32 -0800164static PDH_status_4_t HAL_ReadREVPDHStatus4(HAL_CANHandle hcan,
Austin Schuh812d0d12021-11-04 20:16:48 -0700165 int32_t* status) {
166 uint8_t packedData[8] = {0};
167 int32_t length = 0;
168 uint64_t timestamp = 0;
Austin Schuh75263e32022-02-22 18:05:32 -0800169 PDH_status_4_t result = {};
Austin Schuh812d0d12021-11-04 20:16:48 -0700170
Austin Schuh75263e32022-02-22 18:05:32 -0800171 HAL_ReadCANPacketTimeout(hcan, PDH_STATUS_4_FRAME_API, packedData, &length,
Austin Schuh812d0d12021-11-04 20:16:48 -0700172 &timestamp, kPDHFrameStatus4Timeout * 2, status);
173
174 if (*status != 0) {
175 return result;
176 }
177
Austin Schuh75263e32022-02-22 18:05:32 -0800178 PDH_status_4_unpack(&result, packedData, PDH_STATUS_4_LENGTH);
Austin Schuh812d0d12021-11-04 20:16:48 -0700179
180 return result;
181}
182
183/**
184 * Helper function for the individual getter functions for status 4
185 */
Austin Schuh75263e32022-02-22 18:05:32 -0800186PDH_status_4_t HAL_GetREVPDHStatus4(HAL_REVPDHHandle handle, int32_t* status) {
187 PDH_status_4_t statusFrame = {};
Austin Schuh812d0d12021-11-04 20:16:48 -0700188 auto hpdh = REVPDHHandles->Get(handle);
189 if (hpdh == nullptr) {
190 *status = HAL_HANDLE_ERROR;
191 return statusFrame;
192 }
193
Austin Schuh75263e32022-02-22 18:05:32 -0800194 statusFrame = HAL_ReadREVPDHStatus4(hpdh->hcan, status);
Austin Schuh812d0d12021-11-04 20:16:48 -0700195 return statusFrame;
196}
197
Austin Schuh75263e32022-02-22 18:05:32 -0800198HAL_REVPDHHandle HAL_InitializeREVPDH(int32_t module,
199 const char* allocationLocation,
200 int32_t* status) {
Austin Schuh812d0d12021-11-04 20:16:48 -0700201 hal::init::CheckInit();
Austin Schuh75263e32022-02-22 18:05:32 -0800202 if (!HAL_CheckREVPDHModuleNumber(module)) {
Austin Schuh812d0d12021-11-04 20:16:48 -0700203 *status = RESOURCE_OUT_OF_RANGE;
204 return HAL_kInvalidHandle;
205 }
206
207 HAL_REVPDHHandle handle;
208 auto hpdh = REVPDHHandles->Allocate(module, &handle, status);
209 if (*status != 0) {
210 if (hpdh) {
211 hal::SetLastErrorPreviouslyAllocated(status, "REV PDH", module,
212 hpdh->previousAllocation);
213 } else {
214 hal::SetLastErrorIndexOutOfRange(status, "Invalid Index for REV PDH", 0,
215 kNumREVPDHModules, module);
216 }
217 return HAL_kInvalidHandle; // failed to allocate. Pass error back.
218 }
219
220 HAL_CANHandle hcan =
221 HAL_InitializeCAN(manufacturer, module, deviceType, status);
222
223 if (*status != 0) {
224 REVPDHHandles->Free(handle);
225 return HAL_kInvalidHandle;
226 }
227
228 hpdh->previousAllocation = allocationLocation ? allocationLocation : "";
229 hpdh->hcan = hcan;
230 hpdh->controlPeriod = kDefaultControlPeriod;
Austin Schuh75263e32022-02-22 18:05:32 -0800231 std::memset(&hpdh->versionInfo, 0, sizeof(hpdh->versionInfo));
Austin Schuh812d0d12021-11-04 20:16:48 -0700232
233 return handle;
234}
235
Austin Schuh75263e32022-02-22 18:05:32 -0800236void HAL_FreeREVPDH(HAL_REVPDHHandle handle) {
Austin Schuh812d0d12021-11-04 20:16:48 -0700237 auto hpdh = REVPDHHandles->Get(handle);
238 if (hpdh == nullptr) {
239 return;
240 }
241
242 HAL_CleanCAN(hpdh->hcan);
243
244 REVPDHHandles->Free(handle);
245}
246
Austin Schuh75263e32022-02-22 18:05:32 -0800247int32_t HAL_GetREVPDHModuleNumber(HAL_REVPDHHandle handle, int32_t* status) {
Austin Schuh812d0d12021-11-04 20:16:48 -0700248 return hal::getHandleIndex(handle);
249}
250
Austin Schuh75263e32022-02-22 18:05:32 -0800251HAL_Bool HAL_CheckREVPDHModuleNumber(int32_t module) {
Austin Schuh812d0d12021-11-04 20:16:48 -0700252 return ((module >= 1) && (module < kNumREVPDHModules)) ? 1 : 0;
253}
254
Austin Schuh75263e32022-02-22 18:05:32 -0800255HAL_Bool HAL_CheckREVPDHChannelNumber(int32_t channel) {
Austin Schuh812d0d12021-11-04 20:16:48 -0700256 return ((channel >= 0) && (channel < kNumREVPDHChannels)) ? 1 : 0;
257}
258
Austin Schuh75263e32022-02-22 18:05:32 -0800259double HAL_GetREVPDHChannelCurrent(HAL_REVPDHHandle handle, int32_t channel,
260 int32_t* status) {
Austin Schuh812d0d12021-11-04 20:16:48 -0700261 auto hpdh = REVPDHHandles->Get(handle);
262 if (hpdh == nullptr) {
263 *status = HAL_HANDLE_ERROR;
264 return 0;
265 }
266
Austin Schuh75263e32022-02-22 18:05:32 -0800267 if (!HAL_CheckREVPDHChannelNumber(channel)) {
Austin Schuh812d0d12021-11-04 20:16:48 -0700268 *status = RESOURCE_OUT_OF_RANGE;
269 return 0;
270 }
271
272 // Determine what periodic status the channel is in
273 if (channel < 6) {
274 // Periodic status 0
Austin Schuh75263e32022-02-22 18:05:32 -0800275 PDH_status_0_t statusFrame = HAL_ReadREVPDHStatus0(hpdh->hcan, status);
Austin Schuh812d0d12021-11-04 20:16:48 -0700276 switch (channel) {
277 case 0:
Austin Schuh75263e32022-02-22 18:05:32 -0800278 return PDH_status_0_channel_0_current_decode(
Austin Schuh812d0d12021-11-04 20:16:48 -0700279 statusFrame.channel_0_current);
280 case 1:
Austin Schuh75263e32022-02-22 18:05:32 -0800281 return PDH_status_0_channel_1_current_decode(
Austin Schuh812d0d12021-11-04 20:16:48 -0700282 statusFrame.channel_1_current);
283 case 2:
Austin Schuh75263e32022-02-22 18:05:32 -0800284 return PDH_status_0_channel_2_current_decode(
Austin Schuh812d0d12021-11-04 20:16:48 -0700285 statusFrame.channel_2_current);
286 case 3:
Austin Schuh75263e32022-02-22 18:05:32 -0800287 return PDH_status_0_channel_3_current_decode(
Austin Schuh812d0d12021-11-04 20:16:48 -0700288 statusFrame.channel_3_current);
289 case 4:
Austin Schuh75263e32022-02-22 18:05:32 -0800290 return PDH_status_0_channel_4_current_decode(
Austin Schuh812d0d12021-11-04 20:16:48 -0700291 statusFrame.channel_4_current);
292 case 5:
Austin Schuh75263e32022-02-22 18:05:32 -0800293 return PDH_status_0_channel_5_current_decode(
Austin Schuh812d0d12021-11-04 20:16:48 -0700294 statusFrame.channel_5_current);
295 }
296 } else if (channel < 12) {
297 // Periodic status 1
Austin Schuh75263e32022-02-22 18:05:32 -0800298 PDH_status_1_t statusFrame = HAL_ReadREVPDHStatus1(hpdh->hcan, status);
Austin Schuh812d0d12021-11-04 20:16:48 -0700299 switch (channel) {
300 case 6:
Austin Schuh75263e32022-02-22 18:05:32 -0800301 return PDH_status_1_channel_6_current_decode(
Austin Schuh812d0d12021-11-04 20:16:48 -0700302 statusFrame.channel_6_current);
303 case 7:
Austin Schuh75263e32022-02-22 18:05:32 -0800304 return PDH_status_1_channel_7_current_decode(
Austin Schuh812d0d12021-11-04 20:16:48 -0700305 statusFrame.channel_7_current);
306 case 8:
Austin Schuh75263e32022-02-22 18:05:32 -0800307 return PDH_status_1_channel_8_current_decode(
Austin Schuh812d0d12021-11-04 20:16:48 -0700308 statusFrame.channel_8_current);
309 case 9:
Austin Schuh75263e32022-02-22 18:05:32 -0800310 return PDH_status_1_channel_9_current_decode(
Austin Schuh812d0d12021-11-04 20:16:48 -0700311 statusFrame.channel_9_current);
312 case 10:
Austin Schuh75263e32022-02-22 18:05:32 -0800313 return PDH_status_1_channel_10_current_decode(
Austin Schuh812d0d12021-11-04 20:16:48 -0700314 statusFrame.channel_10_current);
315 case 11:
Austin Schuh75263e32022-02-22 18:05:32 -0800316 return PDH_status_1_channel_11_current_decode(
Austin Schuh812d0d12021-11-04 20:16:48 -0700317 statusFrame.channel_11_current);
318 }
319 } else if (channel < 18) {
320 // Periodic status 2
Austin Schuh75263e32022-02-22 18:05:32 -0800321 PDH_status_2_t statusFrame = HAL_ReadREVPDHStatus2(hpdh->hcan, status);
Austin Schuh812d0d12021-11-04 20:16:48 -0700322 switch (channel) {
323 case 12:
Austin Schuh75263e32022-02-22 18:05:32 -0800324 return PDH_status_2_channel_12_current_decode(
Austin Schuh812d0d12021-11-04 20:16:48 -0700325 statusFrame.channel_12_current);
326 case 13:
Austin Schuh75263e32022-02-22 18:05:32 -0800327 return PDH_status_2_channel_13_current_decode(
Austin Schuh812d0d12021-11-04 20:16:48 -0700328 statusFrame.channel_13_current);
329 case 14:
Austin Schuh75263e32022-02-22 18:05:32 -0800330 return PDH_status_2_channel_14_current_decode(
Austin Schuh812d0d12021-11-04 20:16:48 -0700331 statusFrame.channel_14_current);
332 case 15:
Austin Schuh75263e32022-02-22 18:05:32 -0800333 return PDH_status_2_channel_15_current_decode(
Austin Schuh812d0d12021-11-04 20:16:48 -0700334 statusFrame.channel_15_current);
335 case 16:
Austin Schuh75263e32022-02-22 18:05:32 -0800336 return PDH_status_2_channel_16_current_decode(
Austin Schuh812d0d12021-11-04 20:16:48 -0700337 statusFrame.channel_16_current);
338 case 17:
Austin Schuh75263e32022-02-22 18:05:32 -0800339 return PDH_status_2_channel_17_current_decode(
Austin Schuh812d0d12021-11-04 20:16:48 -0700340 statusFrame.channel_17_current);
341 }
342 } else if (channel < 24) {
343 // Periodic status 3
Austin Schuh75263e32022-02-22 18:05:32 -0800344 PDH_status_3_t statusFrame = HAL_ReadREVPDHStatus3(hpdh->hcan, status);
Austin Schuh812d0d12021-11-04 20:16:48 -0700345 switch (channel) {
346 case 18:
Austin Schuh75263e32022-02-22 18:05:32 -0800347 return PDH_status_3_channel_18_current_decode(
Austin Schuh812d0d12021-11-04 20:16:48 -0700348 statusFrame.channel_18_current);
349 case 19:
Austin Schuh75263e32022-02-22 18:05:32 -0800350 return PDH_status_3_channel_19_current_decode(
Austin Schuh812d0d12021-11-04 20:16:48 -0700351 statusFrame.channel_19_current);
352 case 20:
Austin Schuh75263e32022-02-22 18:05:32 -0800353 return PDH_status_3_channel_20_current_decode(
Austin Schuh812d0d12021-11-04 20:16:48 -0700354 statusFrame.channel_20_current);
355 case 21:
Austin Schuh75263e32022-02-22 18:05:32 -0800356 return PDH_status_3_channel_21_current_decode(
Austin Schuh812d0d12021-11-04 20:16:48 -0700357 statusFrame.channel_21_current);
358 case 22:
Austin Schuh75263e32022-02-22 18:05:32 -0800359 return PDH_status_3_channel_22_current_decode(
Austin Schuh812d0d12021-11-04 20:16:48 -0700360 statusFrame.channel_22_current);
361 case 23:
Austin Schuh75263e32022-02-22 18:05:32 -0800362 return PDH_status_3_channel_23_current_decode(
Austin Schuh812d0d12021-11-04 20:16:48 -0700363 statusFrame.channel_23_current);
364 }
365 }
366 return 0;
367}
368
Austin Schuh75263e32022-02-22 18:05:32 -0800369void HAL_GetREVPDHAllChannelCurrents(HAL_REVPDHHandle handle, double* currents,
Austin Schuh812d0d12021-11-04 20:16:48 -0700370 int32_t* status) {
371 auto hpdh = REVPDHHandles->Get(handle);
372 if (hpdh == nullptr) {
373 *status = HAL_HANDLE_ERROR;
374 return;
375 }
376
Austin Schuh75263e32022-02-22 18:05:32 -0800377 PDH_status_0_t statusFrame0 = HAL_ReadREVPDHStatus0(hpdh->hcan, status);
378 PDH_status_1_t statusFrame1 = HAL_ReadREVPDHStatus1(hpdh->hcan, status);
379 PDH_status_2_t statusFrame2 = HAL_ReadREVPDHStatus2(hpdh->hcan, status);
380 PDH_status_3_t statusFrame3 = HAL_ReadREVPDHStatus3(hpdh->hcan, status);
Austin Schuh812d0d12021-11-04 20:16:48 -0700381
Austin Schuh75263e32022-02-22 18:05:32 -0800382 currents[0] =
383 PDH_status_0_channel_0_current_decode(statusFrame0.channel_0_current);
384 currents[1] =
385 PDH_status_0_channel_1_current_decode(statusFrame0.channel_1_current);
386 currents[2] =
387 PDH_status_0_channel_2_current_decode(statusFrame0.channel_2_current);
388 currents[3] =
389 PDH_status_0_channel_3_current_decode(statusFrame0.channel_3_current);
390 currents[4] =
391 PDH_status_0_channel_4_current_decode(statusFrame0.channel_4_current);
392 currents[5] =
393 PDH_status_0_channel_5_current_decode(statusFrame0.channel_5_current);
394 currents[6] =
395 PDH_status_1_channel_6_current_decode(statusFrame1.channel_6_current);
396 currents[7] =
397 PDH_status_1_channel_7_current_decode(statusFrame1.channel_7_current);
398 currents[8] =
399 PDH_status_1_channel_8_current_decode(statusFrame1.channel_8_current);
400 currents[9] =
401 PDH_status_1_channel_9_current_decode(statusFrame1.channel_9_current);
402 currents[10] =
403 PDH_status_1_channel_10_current_decode(statusFrame1.channel_10_current);
404 currents[11] =
405 PDH_status_1_channel_11_current_decode(statusFrame1.channel_11_current);
406 currents[12] =
407 PDH_status_2_channel_12_current_decode(statusFrame2.channel_12_current);
408 currents[13] =
409 PDH_status_2_channel_13_current_decode(statusFrame2.channel_13_current);
410 currents[14] =
411 PDH_status_2_channel_14_current_decode(statusFrame2.channel_14_current);
412 currents[15] =
413 PDH_status_2_channel_15_current_decode(statusFrame2.channel_15_current);
414 currents[16] =
415 PDH_status_2_channel_16_current_decode(statusFrame2.channel_16_current);
416 currents[17] =
417 PDH_status_2_channel_17_current_decode(statusFrame2.channel_17_current);
418 currents[18] =
419 PDH_status_3_channel_18_current_decode(statusFrame3.channel_18_current);
420 currents[19] =
421 PDH_status_3_channel_19_current_decode(statusFrame3.channel_19_current);
422 currents[20] =
423 PDH_status_3_channel_20_current_decode(statusFrame3.channel_20_current);
424 currents[21] =
425 PDH_status_3_channel_21_current_decode(statusFrame3.channel_21_current);
426 currents[22] =
427 PDH_status_3_channel_22_current_decode(statusFrame3.channel_22_current);
428 currents[23] =
429 PDH_status_3_channel_23_current_decode(statusFrame3.channel_23_current);
Austin Schuh812d0d12021-11-04 20:16:48 -0700430}
431
Austin Schuh75263e32022-02-22 18:05:32 -0800432uint16_t HAL_GetREVPDHTotalCurrent(HAL_REVPDHHandle handle, int32_t* status) {
433 PDH_status_4_t statusFrame = HAL_GetREVPDHStatus4(handle, status);
Austin Schuh812d0d12021-11-04 20:16:48 -0700434
435 if (*status != 0) {
Austin Schuh75263e32022-02-22 18:05:32 -0800436 return 0;
Austin Schuh812d0d12021-11-04 20:16:48 -0700437 }
438
Austin Schuh75263e32022-02-22 18:05:32 -0800439 return PDH_status_4_total_current_decode(statusFrame.total_current);
Austin Schuh812d0d12021-11-04 20:16:48 -0700440}
441
Austin Schuh75263e32022-02-22 18:05:32 -0800442void HAL_SetREVPDHSwitchableChannel(HAL_REVPDHHandle handle, HAL_Bool enabled,
443 int32_t* status) {
Austin Schuh812d0d12021-11-04 20:16:48 -0700444 auto hpdh = REVPDHHandles->Get(handle);
445 if (hpdh == nullptr) {
446 *status = HAL_HANDLE_ERROR;
Austin Schuh75263e32022-02-22 18:05:32 -0800447 return;
Austin Schuh812d0d12021-11-04 20:16:48 -0700448 }
449
Austin Schuh75263e32022-02-22 18:05:32 -0800450 uint8_t packedData[8] = {0};
451 PDH_set_switch_channel_t frame;
452 frame.output_set_value = enabled;
453 PDH_set_switch_channel_pack(packedData, &frame,
454 PDH_SET_SWITCH_CHANNEL_LENGTH);
Austin Schuh812d0d12021-11-04 20:16:48 -0700455
Austin Schuh75263e32022-02-22 18:05:32 -0800456 HAL_WriteCANPacket(hpdh->hcan, packedData, PDH_SET_SWITCH_CHANNEL_LENGTH,
457 PDH_SET_SWITCH_CHANNEL_FRAME_API, status);
Austin Schuh812d0d12021-11-04 20:16:48 -0700458}
459
Austin Schuh75263e32022-02-22 18:05:32 -0800460HAL_Bool HAL_GetREVPDHSwitchableChannelState(HAL_REVPDHHandle handle,
Austin Schuh812d0d12021-11-04 20:16:48 -0700461 int32_t* status) {
Austin Schuh75263e32022-02-22 18:05:32 -0800462 PDH_status_4_t statusFrame = HAL_GetREVPDHStatus4(handle, status);
Austin Schuh812d0d12021-11-04 20:16:48 -0700463
464 if (*status != 0) {
465 return 0.0;
466 }
467
Austin Schuh75263e32022-02-22 18:05:32 -0800468 return PDH_status_4_switch_channel_state_decode(
469 statusFrame.switch_channel_state);
Austin Schuh812d0d12021-11-04 20:16:48 -0700470}
471
Austin Schuh75263e32022-02-22 18:05:32 -0800472double HAL_GetREVPDHVoltage(HAL_REVPDHHandle handle, int32_t* status) {
473 PDH_status_4_t statusFrame = HAL_GetREVPDHStatus4(handle, status);
Austin Schuh812d0d12021-11-04 20:16:48 -0700474
475 if (*status != 0) {
476 return 0.0;
477 }
478
Austin Schuh75263e32022-02-22 18:05:32 -0800479 return PDH_status_4_v_bus_decode(statusFrame.v_bus);
Austin Schuh812d0d12021-11-04 20:16:48 -0700480}
481
Austin Schuh75263e32022-02-22 18:05:32 -0800482void HAL_GetREVPDHVersion(HAL_REVPDHHandle handle,
483 HAL_PowerDistributionVersion* version,
484 int32_t* status) {
485 std::memset(version, 0, sizeof(*version));
Austin Schuh812d0d12021-11-04 20:16:48 -0700486 uint8_t packedData[8] = {0};
487 int32_t length = 0;
488 uint64_t timestamp = 0;
489 PDH_version_t result = {};
490 auto hpdh = REVPDHHandles->Get(handle);
491 if (hpdh == nullptr) {
492 *status = HAL_HANDLE_ERROR;
Austin Schuh75263e32022-02-22 18:05:32 -0800493 return;
494 }
495
496 if (hpdh->versionInfo.firmwareMajor > 0) {
497 version->firmwareMajor = hpdh->versionInfo.firmwareMajor;
498 version->firmwareMinor = hpdh->versionInfo.firmwareMinor;
499 version->firmwareFix = hpdh->versionInfo.firmwareFix;
500 version->hardwareMajor = hpdh->versionInfo.hardwareMajor;
501 version->hardwareMinor = hpdh->versionInfo.hardwareMinor;
502 version->uniqueId = hpdh->versionInfo.uniqueId;
503
504 *status = 0;
505 return;
Austin Schuh812d0d12021-11-04 20:16:48 -0700506 }
507
508 HAL_WriteCANRTRFrame(hpdh->hcan, PDH_VERSION_LENGTH, PDH_VERSION_FRAME_API,
509 status);
510
511 if (*status != 0) {
Austin Schuh75263e32022-02-22 18:05:32 -0800512 return;
Austin Schuh812d0d12021-11-04 20:16:48 -0700513 }
514
Austin Schuh75263e32022-02-22 18:05:32 -0800515 uint32_t timeoutMs = 100;
516 for (uint32_t i = 0; i <= timeoutMs; i++) {
517 HAL_ReadCANPacketNew(hpdh->hcan, PDH_VERSION_FRAME_API, packedData, &length,
518 &timestamp, status);
519 if (*status == 0) {
520 break;
521 }
522 std::this_thread::sleep_for(std::chrono::milliseconds(1));
523 }
Austin Schuh812d0d12021-11-04 20:16:48 -0700524
525 if (*status != 0) {
Austin Schuh75263e32022-02-22 18:05:32 -0800526 return;
Austin Schuh812d0d12021-11-04 20:16:48 -0700527 }
528
529 PDH_version_unpack(&result, packedData, PDH_VERSION_LENGTH);
530
Austin Schuh75263e32022-02-22 18:05:32 -0800531 version->firmwareMajor = result.firmware_year;
532 version->firmwareMinor = result.firmware_minor;
533 version->firmwareFix = result.firmware_fix;
534 version->hardwareMinor = result.hardware_minor;
535 version->hardwareMajor = result.hardware_major;
536 version->uniqueId = result.unique_id;
Austin Schuh812d0d12021-11-04 20:16:48 -0700537
Austin Schuh75263e32022-02-22 18:05:32 -0800538 hpdh->versionInfo = *version;
Austin Schuh812d0d12021-11-04 20:16:48 -0700539}
540
Austin Schuh75263e32022-02-22 18:05:32 -0800541void HAL_GetREVPDHFaults(HAL_REVPDHHandle handle,
542 HAL_PowerDistributionFaults* faults, int32_t* status) {
543 std::memset(faults, 0, sizeof(*faults));
544 auto hpdh = REVPDHHandles->Get(handle);
545 if (hpdh == nullptr) {
546 *status = HAL_HANDLE_ERROR;
547 return;
548 }
549
550 PDH_status_0_t status0 = HAL_ReadREVPDHStatus0(hpdh->hcan, status);
551 PDH_status_1_t status1 = HAL_ReadREVPDHStatus1(hpdh->hcan, status);
552 PDH_status_2_t status2 = HAL_ReadREVPDHStatus2(hpdh->hcan, status);
553 PDH_status_3_t status3 = HAL_ReadREVPDHStatus3(hpdh->hcan, status);
554 PDH_status_4_t status4 = HAL_ReadREVPDHStatus4(hpdh->hcan, status);
555
556 faults->channel0BreakerFault = status0.channel_0_breaker_fault;
557 faults->channel1BreakerFault = status0.channel_1_breaker_fault;
558 faults->channel2BreakerFault = status0.channel_2_breaker_fault;
559 faults->channel3BreakerFault = status0.channel_3_breaker_fault;
560 faults->channel4BreakerFault = status1.channel_4_breaker_fault;
561 faults->channel5BreakerFault = status1.channel_5_breaker_fault;
562 faults->channel6BreakerFault = status1.channel_6_breaker_fault;
563 faults->channel7BreakerFault = status1.channel_7_breaker_fault;
564 faults->channel8BreakerFault = status2.channel_8_breaker_fault;
565 faults->channel9BreakerFault = status2.channel_9_breaker_fault;
566 faults->channel10BreakerFault = status2.channel_10_breaker_fault;
567 faults->channel11BreakerFault = status2.channel_11_breaker_fault;
568 faults->channel12BreakerFault = status3.channel_12_breaker_fault;
569 faults->channel13BreakerFault = status3.channel_13_breaker_fault;
570 faults->channel14BreakerFault = status3.channel_14_breaker_fault;
571 faults->channel15BreakerFault = status3.channel_15_breaker_fault;
572 faults->channel16BreakerFault = status3.channel_16_breaker_fault;
573 faults->channel17BreakerFault = status3.channel_17_breaker_fault;
574 faults->channel18BreakerFault = status3.channel_18_breaker_fault;
575 faults->channel19BreakerFault = status3.channel_19_breaker_fault;
576 faults->channel20BreakerFault = status3.channel_20_breaker_fault;
577 faults->channel21BreakerFault = status3.channel_21_breaker_fault;
578 faults->channel22BreakerFault = status3.channel_22_breaker_fault;
579 faults->channel23BreakerFault = status3.channel_23_breaker_fault;
580 faults->brownout = status4.brownout_fault;
581 faults->canWarning = status4.can_warning_fault;
582 faults->hardwareFault = status4.hardware_fault;
583}
584
585void HAL_GetREVPDHStickyFaults(HAL_REVPDHHandle handle,
586 HAL_PowerDistributionStickyFaults* stickyFaults,
587 int32_t* status) {
588 std::memset(stickyFaults, 0, sizeof(*stickyFaults));
589 auto hpdh = REVPDHHandles->Get(handle);
590 if (hpdh == nullptr) {
591 *status = HAL_HANDLE_ERROR;
592 return;
593 }
594
595 PDH_status_4_t status4 = HAL_ReadREVPDHStatus4(hpdh->hcan, status);
596
597 stickyFaults->channel0BreakerFault = status4.sticky_ch0_breaker_fault;
598 stickyFaults->channel1BreakerFault = status4.sticky_ch1_breaker_fault;
599 stickyFaults->channel2BreakerFault = status4.sticky_ch2_breaker_fault;
600 stickyFaults->channel3BreakerFault = status4.sticky_ch3_breaker_fault;
601 stickyFaults->channel4BreakerFault = status4.sticky_ch4_breaker_fault;
602 stickyFaults->channel5BreakerFault = status4.sticky_ch5_breaker_fault;
603 stickyFaults->channel6BreakerFault = status4.sticky_ch6_breaker_fault;
604 stickyFaults->channel7BreakerFault = status4.sticky_ch7_breaker_fault;
605 stickyFaults->channel8BreakerFault = status4.sticky_ch8_breaker_fault;
606 stickyFaults->channel9BreakerFault = status4.sticky_ch9_breaker_fault;
607 stickyFaults->channel10BreakerFault = status4.sticky_ch10_breaker_fault;
608 stickyFaults->channel11BreakerFault = status4.sticky_ch11_breaker_fault;
609 stickyFaults->channel12BreakerFault = status4.sticky_ch12_breaker_fault;
610 stickyFaults->channel13BreakerFault = status4.sticky_ch13_breaker_fault;
611 stickyFaults->channel14BreakerFault = status4.sticky_ch14_breaker_fault;
612 stickyFaults->channel15BreakerFault = status4.sticky_ch15_breaker_fault;
613 stickyFaults->channel16BreakerFault = status4.sticky_ch16_breaker_fault;
614 stickyFaults->channel17BreakerFault = status4.sticky_ch17_breaker_fault;
615 stickyFaults->channel18BreakerFault = status4.sticky_ch18_breaker_fault;
616 stickyFaults->channel19BreakerFault = status4.sticky_ch19_breaker_fault;
617 stickyFaults->channel20BreakerFault = status4.sticky_ch20_breaker_fault;
618 stickyFaults->channel21BreakerFault = status4.sticky_ch21_breaker_fault;
619 stickyFaults->channel22BreakerFault = status4.sticky_ch22_breaker_fault;
620 stickyFaults->channel23BreakerFault = status4.sticky_ch23_breaker_fault;
621 stickyFaults->brownout = status4.sticky_brownout_fault;
622 stickyFaults->canWarning = status4.sticky_can_warning_fault;
623 stickyFaults->canBusOff = status4.sticky_can_bus_off_fault;
624 stickyFaults->hasReset = status4.sticky_has_reset_fault;
625}
626
627void HAL_ClearREVPDHStickyFaults(HAL_REVPDHHandle handle, int32_t* status) {
Austin Schuh812d0d12021-11-04 20:16:48 -0700628 auto hpdh = REVPDHHandles->Get(handle);
629 if (hpdh == nullptr) {
630 *status = HAL_HANDLE_ERROR;
631 return;
632 }
633
634 uint8_t packedData[8] = {0};
635 HAL_WriteCANPacket(hpdh->hcan, packedData, PDH_CLEAR_FAULTS_LENGTH,
636 PDH_CLEAR_FAULTS_FRAME_API, status);
637}
638
Austin Schuh812d0d12021-11-04 20:16:48 -0700639} // extern "C"