blob: 9ad45b57bea7b5c9e879d0b90a2a864b6dec07d0 [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>
14
15#include <fmt/format.h>
16
17#include "HALInitializer.h"
18#include "HALInternal.h"
19#include "PortsInternal.h"
20#include "rev/PDHFrames.h"
21
22using namespace hal;
23
24static constexpr HAL_CANManufacturer manufacturer =
25 HAL_CANManufacturer::HAL_CAN_Man_kREV;
26
27static constexpr HAL_CANDeviceType deviceType =
28 HAL_CANDeviceType::HAL_CAN_Dev_kPowerDistribution;
29
30static constexpr int32_t kDefaultControlPeriod = 50;
31
32namespace {
33
34struct REV_PDHObj {
35 int32_t controlPeriod;
36 HAL_CANHandle hcan;
37 std::string previousAllocation;
38};
39
40} // namespace
41
42static constexpr uint32_t APIFromExtId(uint32_t extId) {
43 return (extId >> 6) & 0x3FF;
44}
45
46static constexpr uint32_t PDH_SWITCH_CHANNEL_SET_FRAME_API =
47 APIFromExtId(PDH_SWITCH_CHANNEL_SET_FRAME_ID);
48
49static constexpr uint32_t PDH_STATUS0_FRAME_API =
50 APIFromExtId(PDH_STATUS0_FRAME_ID);
51static constexpr uint32_t PDH_STATUS1_FRAME_API =
52 APIFromExtId(PDH_STATUS1_FRAME_ID);
53static constexpr uint32_t PDH_STATUS2_FRAME_API =
54 APIFromExtId(PDH_STATUS2_FRAME_ID);
55static constexpr uint32_t PDH_STATUS3_FRAME_API =
56 APIFromExtId(PDH_STATUS3_FRAME_ID);
57static constexpr uint32_t PDH_STATUS4_FRAME_API =
58 APIFromExtId(PDH_STATUS4_FRAME_ID);
59
60static constexpr uint32_t PDH_CLEAR_FAULTS_FRAME_API =
61 APIFromExtId(PDH_CLEAR_FAULTS_FRAME_ID);
62
63static constexpr uint32_t PDH_IDENTIFY_FRAME_API =
64 APIFromExtId(PDH_IDENTIFY_FRAME_ID);
65
66static constexpr uint32_t PDH_VERSION_FRAME_API =
67 APIFromExtId(PDH_VERSION_FRAME_ID);
68
69static constexpr uint32_t PDH_CONFIGURE_HR_CHANNEL_FRAME_API =
70 APIFromExtId(PDH_CONFIGURE_HR_CHANNEL_FRAME_ID);
71
72static constexpr int32_t kPDHFrameStatus0Timeout = 20;
73static constexpr int32_t kPDHFrameStatus1Timeout = 20;
74static constexpr int32_t kPDHFrameStatus2Timeout = 20;
75static constexpr int32_t kPDHFrameStatus3Timeout = 20;
76static constexpr int32_t kPDHFrameStatus4Timeout = 20;
77
78static IndexedHandleResource<HAL_REVPDHHandle, REV_PDHObj, kNumREVPDHModules,
79 HAL_HandleEnum::REVPDH>* REVPDHHandles;
80
81namespace hal::init {
82void InitializeREVPDH() {
83 static IndexedHandleResource<HAL_REVPDHHandle, REV_PDHObj, kNumREVPDHModules,
84 HAL_HandleEnum::REVPDH>
85 rH;
86 REVPDHHandles = &rH;
87}
88} // namespace hal::init
89
90extern "C" {
91
92static PDH_status0_t HAL_REV_ReadPDHStatus0(HAL_CANHandle hcan,
93 int32_t* status) {
94 uint8_t packedData[8] = {0};
95 int32_t length = 0;
96 uint64_t timestamp = 0;
97 PDH_status0_t result = {};
98
99 HAL_ReadCANPacketTimeout(hcan, PDH_STATUS0_FRAME_API, packedData, &length,
100 &timestamp, kPDHFrameStatus0Timeout * 2, status);
101
102 if (*status != 0) {
103 return result;
104 }
105
106 PDH_status0_unpack(&result, packedData, PDH_STATUS0_LENGTH);
107
108 return result;
109}
110
111static PDH_status1_t HAL_REV_ReadPDHStatus1(HAL_CANHandle hcan,
112 int32_t* status) {
113 uint8_t packedData[8] = {0};
114 int32_t length = 0;
115 uint64_t timestamp = 0;
116 PDH_status1_t result = {};
117
118 HAL_ReadCANPacketTimeout(hcan, PDH_STATUS1_FRAME_API, packedData, &length,
119 &timestamp, kPDHFrameStatus1Timeout * 2, status);
120
121 if (*status != 0) {
122 return result;
123 }
124
125 PDH_status1_unpack(&result, packedData, PDH_STATUS1_LENGTH);
126
127 return result;
128}
129
130static PDH_status2_t HAL_REV_ReadPDHStatus2(HAL_CANHandle hcan,
131 int32_t* status) {
132 uint8_t packedData[8] = {0};
133 int32_t length = 0;
134 uint64_t timestamp = 0;
135 PDH_status2_t result = {};
136
137 HAL_ReadCANPacketTimeout(hcan, PDH_STATUS2_FRAME_API, packedData, &length,
138 &timestamp, kPDHFrameStatus2Timeout * 2, status);
139
140 if (*status != 0) {
141 return result;
142 }
143
144 PDH_status2_unpack(&result, packedData, PDH_STATUS2_LENGTH);
145
146 return result;
147}
148
149static PDH_status3_t HAL_REV_ReadPDHStatus3(HAL_CANHandle hcan,
150 int32_t* status) {
151 uint8_t packedData[8] = {0};
152 int32_t length = 0;
153 uint64_t timestamp = 0;
154 PDH_status3_t result = {};
155
156 HAL_ReadCANPacketTimeout(hcan, PDH_STATUS3_FRAME_API, packedData, &length,
157 &timestamp, kPDHFrameStatus3Timeout * 2, status);
158
159 if (*status != 0) {
160 return result;
161 }
162
163 PDH_status3_unpack(&result, packedData, PDH_STATUS3_LENGTH);
164
165 return result;
166}
167
168static PDH_status4_t HAL_REV_ReadPDHStatus4(HAL_CANHandle hcan,
169 int32_t* status) {
170 uint8_t packedData[8] = {0};
171 int32_t length = 0;
172 uint64_t timestamp = 0;
173 PDH_status4_t result = {};
174
175 HAL_ReadCANPacketTimeout(hcan, PDH_STATUS4_FRAME_API, packedData, &length,
176 &timestamp, kPDHFrameStatus4Timeout * 2, status);
177
178 if (*status != 0) {
179 return result;
180 }
181
182 PDH_status4_unpack(&result, packedData, PDH_STATUS4_LENGTH);
183
184 return result;
185}
186
187/**
188 * Helper function for the individual getter functions for status 4
189 */
190PDH_status4_t HAL_REV_GetPDHStatus4(HAL_REVPDHHandle handle, int32_t* status) {
191 PDH_status4_t statusFrame = {};
192 auto hpdh = REVPDHHandles->Get(handle);
193 if (hpdh == nullptr) {
194 *status = HAL_HANDLE_ERROR;
195 return statusFrame;
196 }
197
198 statusFrame = HAL_REV_ReadPDHStatus4(hpdh->hcan, status);
199 return statusFrame;
200}
201
202HAL_REVPDHHandle HAL_REV_InitializePDH(int32_t module,
203 const char* allocationLocation,
204 int32_t* status) {
205 hal::init::CheckInit();
206 if (!HAL_REV_CheckPDHModuleNumber(module)) {
207 *status = RESOURCE_OUT_OF_RANGE;
208 return HAL_kInvalidHandle;
209 }
210
211 HAL_REVPDHHandle handle;
212 auto hpdh = REVPDHHandles->Allocate(module, &handle, status);
213 if (*status != 0) {
214 if (hpdh) {
215 hal::SetLastErrorPreviouslyAllocated(status, "REV PDH", module,
216 hpdh->previousAllocation);
217 } else {
218 hal::SetLastErrorIndexOutOfRange(status, "Invalid Index for REV PDH", 0,
219 kNumREVPDHModules, module);
220 }
221 return HAL_kInvalidHandle; // failed to allocate. Pass error back.
222 }
223
224 HAL_CANHandle hcan =
225 HAL_InitializeCAN(manufacturer, module, deviceType, status);
226
227 if (*status != 0) {
228 REVPDHHandles->Free(handle);
229 return HAL_kInvalidHandle;
230 }
231
232 hpdh->previousAllocation = allocationLocation ? allocationLocation : "";
233 hpdh->hcan = hcan;
234 hpdh->controlPeriod = kDefaultControlPeriod;
235
236 return handle;
237}
238
239void HAL_REV_FreePDH(HAL_REVPDHHandle handle) {
240 auto hpdh = REVPDHHandles->Get(handle);
241 if (hpdh == nullptr) {
242 return;
243 }
244
245 HAL_CleanCAN(hpdh->hcan);
246
247 REVPDHHandles->Free(handle);
248}
249
250int32_t HAL_REV_GetPDHModuleNumber(HAL_REVPDHHandle handle, int32_t* status) {
251 return hal::getHandleIndex(handle);
252}
253
254HAL_Bool HAL_REV_CheckPDHModuleNumber(int32_t module) {
255 return ((module >= 1) && (module < kNumREVPDHModules)) ? 1 : 0;
256}
257
258HAL_Bool HAL_REV_CheckPDHChannelNumber(int32_t channel) {
259 return ((channel >= 0) && (channel < kNumREVPDHChannels)) ? 1 : 0;
260}
261
262double HAL_REV_GetPDHChannelCurrent(HAL_REVPDHHandle handle, int32_t channel,
263 int32_t* status) {
264 auto hpdh = REVPDHHandles->Get(handle);
265 if (hpdh == nullptr) {
266 *status = HAL_HANDLE_ERROR;
267 return 0;
268 }
269
270 if (!HAL_REV_CheckPDHChannelNumber(channel)) {
271 *status = RESOURCE_OUT_OF_RANGE;
272 return 0;
273 }
274
275 // Determine what periodic status the channel is in
276 if (channel < 6) {
277 // Periodic status 0
278 PDH_status0_t statusFrame = HAL_REV_ReadPDHStatus0(hpdh->hcan, status);
279 switch (channel) {
280 case 0:
281 return PDH_status0_channel_0_current_decode(
282 statusFrame.channel_0_current);
283 case 1:
284 return PDH_status0_channel_1_current_decode(
285 statusFrame.channel_1_current);
286 case 2:
287 return PDH_status0_channel_2_current_decode(
288 statusFrame.channel_2_current);
289 case 3:
290 return PDH_status0_channel_3_current_decode(
291 statusFrame.channel_3_current);
292 case 4:
293 return PDH_status0_channel_4_current_decode(
294 statusFrame.channel_4_current);
295 case 5:
296 return PDH_status0_channel_5_current_decode(
297 statusFrame.channel_5_current);
298 }
299 } else if (channel < 12) {
300 // Periodic status 1
301 PDH_status1_t statusFrame = HAL_REV_ReadPDHStatus1(hpdh->hcan, status);
302 switch (channel) {
303 case 6:
304 return PDH_status1_channel_6_current_decode(
305 statusFrame.channel_6_current);
306 case 7:
307 return PDH_status1_channel_7_current_decode(
308 statusFrame.channel_7_current);
309 case 8:
310 return PDH_status1_channel_8_current_decode(
311 statusFrame.channel_8_current);
312 case 9:
313 return PDH_status1_channel_9_current_decode(
314 statusFrame.channel_9_current);
315 case 10:
316 return PDH_status1_channel_10_current_decode(
317 statusFrame.channel_10_current);
318 case 11:
319 return PDH_status1_channel_11_current_decode(
320 statusFrame.channel_11_current);
321 }
322 } else if (channel < 18) {
323 // Periodic status 2
324 PDH_status2_t statusFrame = HAL_REV_ReadPDHStatus2(hpdh->hcan, status);
325 switch (channel) {
326 case 12:
327 return PDH_status2_channel_12_current_decode(
328 statusFrame.channel_12_current);
329 case 13:
330 return PDH_status2_channel_13_current_decode(
331 statusFrame.channel_13_current);
332 case 14:
333 return PDH_status2_channel_14_current_decode(
334 statusFrame.channel_14_current);
335 case 15:
336 return PDH_status2_channel_15_current_decode(
337 statusFrame.channel_15_current);
338 case 16:
339 return PDH_status2_channel_16_current_decode(
340 statusFrame.channel_16_current);
341 case 17:
342 return PDH_status2_channel_17_current_decode(
343 statusFrame.channel_17_current);
344 }
345 } else if (channel < 24) {
346 // Periodic status 3
347 PDH_status3_t statusFrame = HAL_REV_ReadPDHStatus3(hpdh->hcan, status);
348 switch (channel) {
349 case 18:
350 return PDH_status3_channel_18_current_decode(
351 statusFrame.channel_18_current);
352 case 19:
353 return PDH_status3_channel_19_current_decode(
354 statusFrame.channel_19_current);
355 case 20:
356 return PDH_status3_channel_20_current_decode(
357 statusFrame.channel_20_current);
358 case 21:
359 return PDH_status3_channel_21_current_decode(
360 statusFrame.channel_21_current);
361 case 22:
362 return PDH_status3_channel_22_current_decode(
363 statusFrame.channel_22_current);
364 case 23:
365 return PDH_status3_channel_23_current_decode(
366 statusFrame.channel_23_current);
367 }
368 }
369 return 0;
370}
371
372void HAL_REV_GetPDHAllChannelCurrents(HAL_REVPDHHandle handle, double* currents,
373 int32_t* status) {
374 auto hpdh = REVPDHHandles->Get(handle);
375 if (hpdh == nullptr) {
376 *status = HAL_HANDLE_ERROR;
377 return;
378 }
379
380 PDH_status0_t statusFrame0 = HAL_REV_ReadPDHStatus0(hpdh->hcan, status);
381 PDH_status1_t statusFrame1 = HAL_REV_ReadPDHStatus1(hpdh->hcan, status);
382 PDH_status2_t statusFrame2 = HAL_REV_ReadPDHStatus2(hpdh->hcan, status);
383 PDH_status3_t statusFrame3 = HAL_REV_ReadPDHStatus3(hpdh->hcan, status);
384
385 currents[0] =
386 PDH_status0_channel_0_current_decode(statusFrame0.channel_0_current);
387 currents[1] =
388 PDH_status0_channel_1_current_decode(statusFrame0.channel_1_current);
389 currents[2] =
390 PDH_status0_channel_2_current_decode(statusFrame0.channel_2_current);
391 currents[3] =
392 PDH_status0_channel_3_current_decode(statusFrame0.channel_3_current);
393 currents[4] =
394 PDH_status0_channel_4_current_decode(statusFrame0.channel_4_current);
395 currents[5] =
396 PDH_status0_channel_5_current_decode(statusFrame0.channel_5_current);
397 currents[6] =
398 PDH_status1_channel_6_current_decode(statusFrame1.channel_6_current);
399 currents[7] =
400 PDH_status1_channel_7_current_decode(statusFrame1.channel_7_current);
401 currents[8] =
402 PDH_status1_channel_8_current_decode(statusFrame1.channel_8_current);
403 currents[9] =
404 PDH_status1_channel_9_current_decode(statusFrame1.channel_9_current);
405 currents[10] =
406 PDH_status1_channel_10_current_decode(statusFrame1.channel_10_current);
407 currents[11] =
408 PDH_status1_channel_11_current_decode(statusFrame1.channel_11_current);
409 currents[12] =
410 PDH_status2_channel_12_current_decode(statusFrame2.channel_12_current);
411 currents[13] =
412 PDH_status2_channel_13_current_decode(statusFrame2.channel_13_current);
413 currents[14] =
414 PDH_status2_channel_14_current_decode(statusFrame2.channel_14_current);
415 currents[15] =
416 PDH_status2_channel_15_current_decode(statusFrame2.channel_15_current);
417 currents[16] =
418 PDH_status2_channel_16_current_decode(statusFrame2.channel_16_current);
419 currents[17] =
420 PDH_status2_channel_17_current_decode(statusFrame2.channel_17_current);
421 currents[18] =
422 PDH_status3_channel_18_current_decode(statusFrame3.channel_18_current);
423 currents[19] =
424 PDH_status3_channel_19_current_decode(statusFrame3.channel_19_current);
425 currents[20] =
426 PDH_status3_channel_20_current_decode(statusFrame3.channel_20_current);
427 currents[21] =
428 PDH_status3_channel_21_current_decode(statusFrame3.channel_21_current);
429 currents[22] =
430 PDH_status3_channel_22_current_decode(statusFrame3.channel_22_current);
431 currents[23] =
432 PDH_status3_channel_23_current_decode(statusFrame3.channel_23_current);
433}
434
435uint16_t HAL_REV_GetPDHTotalCurrent(HAL_REVPDHHandle handle, int32_t* status) {
436 PDH_status4_t statusFrame = HAL_REV_GetPDHStatus4(handle, status);
437
438 if (*status != 0) {
439 return 0;
440 }
441
442 return PDH_status4_total_current_decode(statusFrame.total_current);
443}
444
445void HAL_REV_SetPDHSwitchableChannel(HAL_REVPDHHandle handle, HAL_Bool enabled,
446 int32_t* status) {
447 auto hpdh = REVPDHHandles->Get(handle);
448 if (hpdh == nullptr) {
449 *status = HAL_HANDLE_ERROR;
450 return;
451 }
452
453 uint8_t packedData[8] = {0};
454 PDH_switch_channel_set_t frame;
455 frame.output_set_value = enabled;
456 frame.use_system_enable = false;
457 PDH_switch_channel_set_pack(packedData, &frame, 1);
458
459 HAL_WriteCANPacket(hpdh->hcan, packedData, PDH_SWITCH_CHANNEL_SET_LENGTH,
460 PDH_SWITCH_CHANNEL_SET_FRAME_API, status);
461}
462
463HAL_Bool HAL_REV_GetPDHSwitchableChannelState(HAL_REVPDHHandle handle,
464 int32_t* status) {
465 PDH_status4_t statusFrame = HAL_REV_GetPDHStatus4(handle, status);
466
467 if (*status != 0) {
468 return 0.0;
469 }
470
471 return PDH_status4_sw_state_decode(statusFrame.sw_state);
472}
473
474HAL_Bool HAL_REV_CheckPDHChannelBrownout(HAL_REVPDHHandle handle,
475 int32_t channel, int32_t* status) {
476 auto hpdh = REVPDHHandles->Get(handle);
477 if (hpdh == nullptr) {
478 *status = HAL_HANDLE_ERROR;
479 return 0;
480 }
481
482 if (!HAL_REV_CheckPDHChannelNumber(channel)) {
483 *status = RESOURCE_OUT_OF_RANGE;
484 return 0;
485 }
486
487 // Determine what periodic status the channel is in
488 if (channel < 4) {
489 // Periodic status 0
490 PDH_status0_t statusFrame = HAL_REV_ReadPDHStatus0(hpdh->hcan, status);
491 switch (channel) {
492 case 0:
493 return PDH_status0_channel_0_brownout_decode(
494 statusFrame.channel_0_brownout);
495 case 1:
496 return PDH_status0_channel_1_brownout_decode(
497 statusFrame.channel_1_brownout);
498 case 2:
499 return PDH_status0_channel_2_brownout_decode(
500 statusFrame.channel_2_brownout);
501 case 3:
502 return PDH_status0_channel_3_brownout_decode(
503 statusFrame.channel_3_brownout);
504 }
505 } else if (channel < 8) {
506 // Periodic status 1
507 PDH_status1_t statusFrame = HAL_REV_ReadPDHStatus1(hpdh->hcan, status);
508 switch (channel) {
509 case 4:
510 return PDH_status1_channel_4_brownout_decode(
511 statusFrame.channel_4_brownout);
512 case 5:
513 return PDH_status1_channel_5_brownout_decode(
514 statusFrame.channel_5_brownout);
515 case 6:
516 return PDH_status1_channel_6_brownout_decode(
517 statusFrame.channel_6_brownout);
518 case 7:
519 return PDH_status1_channel_7_brownout_decode(
520 statusFrame.channel_7_brownout);
521 }
522 } else if (channel < 12) {
523 // Periodic status 2
524 PDH_status2_t statusFrame = HAL_REV_ReadPDHStatus2(hpdh->hcan, status);
525 switch (channel) {
526 case 8:
527 return PDH_status2_channel_8_brownout_decode(
528 statusFrame.channel_8_brownout);
529 case 9:
530 return PDH_status2_channel_9_brownout_decode(
531 statusFrame.channel_9_brownout);
532 case 10:
533 return PDH_status2_channel_10_brownout_decode(
534 statusFrame.channel_10_brownout);
535 case 11:
536 return PDH_status2_channel_11_brownout_decode(
537 statusFrame.channel_11_brownout);
538 }
539 } else if (channel < 24) {
540 // Periodic status 3
541 PDH_status3_t statusFrame = HAL_REV_ReadPDHStatus3(hpdh->hcan, status);
542 switch (channel) {
543 case 12:
544 return PDH_status3_channel_12_brownout_decode(
545 statusFrame.channel_12_brownout);
546 case 13:
547 return PDH_status3_channel_13_brownout_decode(
548 statusFrame.channel_13_brownout);
549 case 14:
550 return PDH_status3_channel_14_brownout_decode(
551 statusFrame.channel_14_brownout);
552 case 15:
553 return PDH_status3_channel_15_brownout_decode(
554 statusFrame.channel_15_brownout);
555 case 16:
556 return PDH_status3_channel_16_brownout_decode(
557 statusFrame.channel_16_brownout);
558 case 17:
559 return PDH_status3_channel_17_brownout_decode(
560 statusFrame.channel_17_brownout);
561 case 18:
562 return PDH_status3_channel_18_brownout_decode(
563 statusFrame.channel_18_brownout);
564 case 19:
565 return PDH_status3_channel_19_brownout_decode(
566 statusFrame.channel_19_brownout);
567 case 20:
568 return PDH_status3_channel_20_brownout_decode(
569 statusFrame.channel_20_brownout);
570 case 21:
571 return PDH_status3_channel_21_brownout_decode(
572 statusFrame.channel_21_brownout);
573 case 22:
574 return PDH_status3_channel_22_brownout_decode(
575 statusFrame.channel_22_brownout);
576 case 23:
577 return PDH_status3_channel_23_brownout_decode(
578 statusFrame.channel_23_brownout);
579 }
580 }
581 return 0;
582}
583
584double HAL_REV_GetPDHSupplyVoltage(HAL_REVPDHHandle handle, int32_t* status) {
585 PDH_status4_t statusFrame = HAL_REV_GetPDHStatus4(handle, status);
586
587 if (*status != 0) {
588 return 0.0;
589 }
590
591 return PDH_status4_v_bus_decode(statusFrame.v_bus);
592}
593
594HAL_Bool HAL_REV_IsPDHEnabled(HAL_REVPDHHandle handle, int32_t* status) {
595 PDH_status4_t statusFrame = HAL_REV_GetPDHStatus4(handle, status);
596
597 if (*status != 0) {
598 return false;
599 }
600
601 return PDH_status4_system_enable_decode(statusFrame.system_enable);
602}
603
604HAL_Bool HAL_REV_CheckPDHBrownout(HAL_REVPDHHandle handle, int32_t* status) {
605 PDH_status4_t statusFrame = HAL_REV_GetPDHStatus4(handle, status);
606
607 if (*status != 0) {
608 return false;
609 }
610
611 return PDH_status4_brownout_decode(statusFrame.brownout);
612}
613
614HAL_Bool HAL_REV_CheckPDHCANWarning(HAL_REVPDHHandle handle, int32_t* status) {
615 PDH_status4_t statusFrame = HAL_REV_GetPDHStatus4(handle, status);
616
617 if (*status != 0) {
618 return 0.0;
619 }
620
621 return PDH_status4_can_warning_decode(statusFrame.can_warning);
622}
623
624HAL_Bool HAL_REV_CheckPDHHardwareFault(HAL_REVPDHHandle handle,
625 int32_t* status) {
626 PDH_status4_t statusFrame = HAL_REV_GetPDHStatus4(handle, status);
627
628 if (*status != 0) {
629 return 0.0;
630 }
631
632 return PDH_status4_hardware_fault_decode(statusFrame.hardware_fault);
633}
634
635HAL_Bool HAL_REV_CheckPDHStickyBrownout(HAL_REVPDHHandle handle,
636 int32_t* status) {
637 PDH_status4_t statusFrame = HAL_REV_GetPDHStatus4(handle, status);
638
639 if (*status != 0) {
640 return 0.0;
641 }
642
643 return PDH_status4_sticky_brownout_decode(statusFrame.sticky_brownout);
644}
645
646HAL_Bool HAL_REV_CheckPDHStickyCANWarning(HAL_REVPDHHandle handle,
647 int32_t* status) {
648 PDH_status4_t statusFrame = HAL_REV_GetPDHStatus4(handle, status);
649
650 if (*status != 0) {
651 return 0.0;
652 }
653
654 return PDH_status4_sticky_can_warning_decode(statusFrame.sticky_can_warning);
655}
656
657HAL_Bool HAL_REV_CheckPDHStickyCANBusOff(HAL_REVPDHHandle handle,
658 int32_t* status) {
659 PDH_status4_t statusFrame = HAL_REV_GetPDHStatus4(handle, status);
660
661 if (*status != 0) {
662 return 0.0;
663 }
664
665 return PDH_status4_sticky_can_bus_off_decode(statusFrame.sticky_can_bus_off);
666}
667
668HAL_Bool HAL_REV_CheckPDHStickyHardwareFault(HAL_REVPDHHandle handle,
669 int32_t* status) {
670 PDH_status4_t statusFrame = HAL_REV_GetPDHStatus4(handle, status);
671
672 if (*status != 0) {
673 return 0.0;
674 }
675
676 return PDH_status4_sticky_hardware_fault_decode(
677 statusFrame.sticky_hardware_fault);
678}
679
680HAL_Bool HAL_REV_CheckPDHStickyFirmwareFault(HAL_REVPDHHandle handle,
681 int32_t* status) {
682 PDH_status4_t statusFrame = HAL_REV_GetPDHStatus4(handle, status);
683
684 if (*status != 0) {
685 return 0.0;
686 }
687
688 return PDH_status4_sticky_firmware_fault_decode(
689 statusFrame.sticky_firmware_fault);
690}
691
692HAL_Bool HAL_REV_CheckPDHStickyChannelBrownout(HAL_REVPDHHandle handle,
693 int32_t channel,
694 int32_t* status) {
695 if (channel < 20 || channel > 23) {
696 *status = RESOURCE_OUT_OF_RANGE;
697 return 0.0;
698 }
699
700 PDH_status4_t statusFrame = HAL_REV_GetPDHStatus4(handle, status);
701
702 if (*status != 0) {
703 return 0.0;
704 }
705
706 switch (channel) {
707 case 20:
708 return PDH_status4_sticky_ch20_brownout_decode(
709 statusFrame.sticky_ch20_brownout);
710 case 21:
711 return PDH_status4_sticky_ch21_brownout_decode(
712 statusFrame.sticky_ch21_brownout);
713 case 22:
714 return PDH_status4_sticky_ch22_brownout_decode(
715 statusFrame.sticky_ch22_brownout);
716 case 23:
717 return PDH_status4_sticky_ch23_brownout_decode(
718 statusFrame.sticky_ch23_brownout);
719 }
720 return 0;
721}
722
723HAL_Bool HAL_REV_CheckPDHStickyHasReset(HAL_REVPDHHandle handle,
724 int32_t* status) {
725 PDH_status4_t statusFrame = HAL_REV_GetPDHStatus4(handle, status);
726
727 if (*status != 0) {
728 return 0.0;
729 }
730
731 return PDH_status4_sticky_has_reset_decode(statusFrame.sticky_has_reset);
732}
733
734REV_PDH_Version HAL_REV_GetPDHVersion(HAL_REVPDHHandle handle,
735 int32_t* status) {
736 REV_PDH_Version version;
737 std::memset(&version, 0, sizeof(version));
738 uint8_t packedData[8] = {0};
739 int32_t length = 0;
740 uint64_t timestamp = 0;
741 PDH_version_t result = {};
742 auto hpdh = REVPDHHandles->Get(handle);
743 if (hpdh == nullptr) {
744 *status = HAL_HANDLE_ERROR;
745 return version;
746 }
747
748 HAL_WriteCANRTRFrame(hpdh->hcan, PDH_VERSION_LENGTH, PDH_VERSION_FRAME_API,
749 status);
750
751 if (*status != 0) {
752 return version;
753 }
754
755 HAL_ReadCANPacketTimeout(hpdh->hcan, PDH_VERSION_FRAME_API, packedData,
756 &length, &timestamp, kDefaultControlPeriod * 2,
757 status);
758
759 if (*status != 0) {
760 return version;
761 }
762
763 PDH_version_unpack(&result, packedData, PDH_VERSION_LENGTH);
764
765 version.firmwareMajor = result.firmware_year;
766 version.firmwareMinor = result.firmware_minor;
767 version.firmwareFix = result.firmware_fix;
768 version.hardwareRev = result.hardware_code;
769 version.uniqueId = result.unique_id;
770
771 return version;
772}
773
774void HAL_REV_ClearPDHFaults(HAL_REVPDHHandle handle, int32_t* status) {
775 auto hpdh = REVPDHHandles->Get(handle);
776 if (hpdh == nullptr) {
777 *status = HAL_HANDLE_ERROR;
778 return;
779 }
780
781 uint8_t packedData[8] = {0};
782 HAL_WriteCANPacket(hpdh->hcan, packedData, PDH_CLEAR_FAULTS_LENGTH,
783 PDH_CLEAR_FAULTS_FRAME_API, status);
784}
785
786void HAL_REV_IdentifyPDH(HAL_REVPDHHandle handle, int32_t* status) {
787 auto hpdh = REVPDHHandles->Get(handle);
788 if (hpdh == nullptr) {
789 *status = HAL_HANDLE_ERROR;
790 return;
791 }
792
793 uint8_t packedData[8] = {0};
794 HAL_WriteCANPacket(hpdh->hcan, packedData, PDH_IDENTIFY_LENGTH,
795 PDH_IDENTIFY_FRAME_API, status);
796}
797
798} // extern "C"