blob: f01eb3f687031c2c66713a4ef57aeeb759f51df4 [file] [log] [blame]
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2018 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#include "frc/CAN.h"
#include <utility>
#include <hal/CAN.h>
#include <hal/CANAPI.h>
#include <hal/Errors.h>
#include <hal/FRCUsageReporting.h>
#include <hal/HALBase.h>
using namespace frc;
CAN::CAN(int deviceId) {
int32_t status = 0;
m_handle =
HAL_InitializeCAN(kTeamManufacturer, deviceId, kTeamDeviceType, &status);
if (status != 0) {
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
m_handle = HAL_kInvalidHandle;
return;
}
HAL_Report(HALUsageReporting::kResourceType_CAN, deviceId);
}
CAN::CAN(int deviceId, int deviceManufacturer, int deviceType) {
int32_t status = 0;
m_handle = HAL_InitializeCAN(
static_cast<HAL_CANManufacturer>(deviceManufacturer), deviceId,
static_cast<HAL_CANDeviceType>(deviceType), &status);
if (status != 0) {
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
m_handle = HAL_kInvalidHandle;
return;
}
HAL_Report(HALUsageReporting::kResourceType_CAN, deviceId);
}
CAN::~CAN() {
if (StatusIsFatal()) return;
if (m_handle != HAL_kInvalidHandle) {
HAL_CleanCAN(m_handle);
m_handle = HAL_kInvalidHandle;
}
}
CAN::CAN(CAN&& rhs) : ErrorBase(std::move(rhs)) {
std::swap(m_handle, rhs.m_handle);
}
CAN& CAN::operator=(CAN&& rhs) {
ErrorBase::operator=(std::move(rhs));
std::swap(m_handle, rhs.m_handle);
return *this;
}
void CAN::WritePacket(const uint8_t* data, int length, int apiId) {
int32_t status = 0;
HAL_WriteCANPacket(m_handle, data, length, apiId, &status);
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
}
void CAN::WritePacketRepeating(const uint8_t* data, int length, int apiId,
int repeatMs) {
int32_t status = 0;
HAL_WriteCANPacketRepeating(m_handle, data, length, apiId, repeatMs, &status);
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
}
void CAN::StopPacketRepeating(int apiId) {
int32_t status = 0;
HAL_StopCANPacketRepeating(m_handle, apiId, &status);
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
}
bool CAN::ReadPacketNew(int apiId, CANData* data) {
int32_t status = 0;
HAL_ReadCANPacketNew(m_handle, apiId, data->data, &data->length,
&data->timestamp, &status);
if (status == HAL_ERR_CANSessionMux_MessageNotFound) {
return false;
}
if (status != 0) {
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
return false;
} else {
return true;
}
}
bool CAN::ReadPacketLatest(int apiId, CANData* data) {
int32_t status = 0;
HAL_ReadCANPacketLatest(m_handle, apiId, data->data, &data->length,
&data->timestamp, &status);
if (status == HAL_ERR_CANSessionMux_MessageNotFound) {
return false;
}
if (status != 0) {
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
return false;
} else {
return true;
}
}
bool CAN::ReadPacketTimeout(int apiId, int timeoutMs, CANData* data) {
int32_t status = 0;
HAL_ReadCANPacketTimeout(m_handle, apiId, data->data, &data->length,
&data->timestamp, timeoutMs, &status);
if (status == HAL_CAN_TIMEOUT ||
status == HAL_ERR_CANSessionMux_MessageNotFound) {
return false;
}
if (status != 0) {
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
return false;
} else {
return true;
}
}
bool CAN::ReadPeriodicPacket(int apiId, int timeoutMs, int periodMs,
CANData* data) {
int32_t status = 0;
HAL_ReadCANPeriodicPacket(m_handle, apiId, data->data, &data->length,
&data->timestamp, timeoutMs, periodMs, &status);
if (status == HAL_CAN_TIMEOUT ||
status == HAL_ERR_CANSessionMux_MessageNotFound) {
return false;
}
if (status != 0) {
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
return false;
} else {
return true;
}
}