blob: f01eb3f687031c2c66713a4ef57aeeb759f51df4 [file] [log] [blame]
Brian Silverman41cdd3e2019-01-19 19:48:58 -08001/*----------------------------------------------------------------------------*/
2/* Copyright (c) 2018 FIRST. All Rights Reserved. */
3/* Open Source Software - may be modified and shared by FRC teams. The code */
4/* must be accompanied by the FIRST BSD license file in the root directory of */
5/* the project. */
6/*----------------------------------------------------------------------------*/
7
8#include "frc/CAN.h"
9
10#include <utility>
11
12#include <hal/CAN.h>
13#include <hal/CANAPI.h>
14#include <hal/Errors.h>
15#include <hal/FRCUsageReporting.h>
16#include <hal/HALBase.h>
17
18using namespace frc;
19
20CAN::CAN(int deviceId) {
21 int32_t status = 0;
22 m_handle =
23 HAL_InitializeCAN(kTeamManufacturer, deviceId, kTeamDeviceType, &status);
24 if (status != 0) {
25 wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
26 m_handle = HAL_kInvalidHandle;
27 return;
28 }
29
30 HAL_Report(HALUsageReporting::kResourceType_CAN, deviceId);
31}
32
33CAN::CAN(int deviceId, int deviceManufacturer, int deviceType) {
34 int32_t status = 0;
35 m_handle = HAL_InitializeCAN(
36 static_cast<HAL_CANManufacturer>(deviceManufacturer), deviceId,
37 static_cast<HAL_CANDeviceType>(deviceType), &status);
38 if (status != 0) {
39 wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
40 m_handle = HAL_kInvalidHandle;
41 return;
42 }
43
44 HAL_Report(HALUsageReporting::kResourceType_CAN, deviceId);
45}
46
47CAN::~CAN() {
48 if (StatusIsFatal()) return;
49 if (m_handle != HAL_kInvalidHandle) {
50 HAL_CleanCAN(m_handle);
51 m_handle = HAL_kInvalidHandle;
52 }
53}
54
55CAN::CAN(CAN&& rhs) : ErrorBase(std::move(rhs)) {
56 std::swap(m_handle, rhs.m_handle);
57}
58
59CAN& CAN::operator=(CAN&& rhs) {
60 ErrorBase::operator=(std::move(rhs));
61
62 std::swap(m_handle, rhs.m_handle);
63
64 return *this;
65}
66
67void CAN::WritePacket(const uint8_t* data, int length, int apiId) {
68 int32_t status = 0;
69 HAL_WriteCANPacket(m_handle, data, length, apiId, &status);
70 wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
71}
72
73void CAN::WritePacketRepeating(const uint8_t* data, int length, int apiId,
74 int repeatMs) {
75 int32_t status = 0;
76 HAL_WriteCANPacketRepeating(m_handle, data, length, apiId, repeatMs, &status);
77 wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
78}
79
80void CAN::StopPacketRepeating(int apiId) {
81 int32_t status = 0;
82 HAL_StopCANPacketRepeating(m_handle, apiId, &status);
83 wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
84}
85
86bool CAN::ReadPacketNew(int apiId, CANData* data) {
87 int32_t status = 0;
88 HAL_ReadCANPacketNew(m_handle, apiId, data->data, &data->length,
89 &data->timestamp, &status);
90 if (status == HAL_ERR_CANSessionMux_MessageNotFound) {
91 return false;
92 }
93 if (status != 0) {
94 wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
95 return false;
96 } else {
97 return true;
98 }
99}
100
101bool CAN::ReadPacketLatest(int apiId, CANData* data) {
102 int32_t status = 0;
103 HAL_ReadCANPacketLatest(m_handle, apiId, data->data, &data->length,
104 &data->timestamp, &status);
105 if (status == HAL_ERR_CANSessionMux_MessageNotFound) {
106 return false;
107 }
108 if (status != 0) {
109 wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
110 return false;
111 } else {
112 return true;
113 }
114}
115
116bool CAN::ReadPacketTimeout(int apiId, int timeoutMs, CANData* data) {
117 int32_t status = 0;
118 HAL_ReadCANPacketTimeout(m_handle, apiId, data->data, &data->length,
119 &data->timestamp, timeoutMs, &status);
120 if (status == HAL_CAN_TIMEOUT ||
121 status == HAL_ERR_CANSessionMux_MessageNotFound) {
122 return false;
123 }
124 if (status != 0) {
125 wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
126 return false;
127 } else {
128 return true;
129 }
130}
131
132bool CAN::ReadPeriodicPacket(int apiId, int timeoutMs, int periodMs,
133 CANData* data) {
134 int32_t status = 0;
135 HAL_ReadCANPeriodicPacket(m_handle, apiId, data->data, &data->length,
136 &data->timestamp, timeoutMs, periodMs, &status);
137 if (status == HAL_CAN_TIMEOUT ||
138 status == HAL_ERR_CANSessionMux_MessageNotFound) {
139 return false;
140 }
141 if (status != 0) {
142 wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
143 return false;
144 } else {
145 return true;
146 }
147}