[hal, wpilib] Add REV PneumaticsHub (#3600)

This commit is contained in:
Thad House
2021-10-10 20:04:50 -07:00
committed by GitHub
parent 4c61a13057
commit 10f19e6fc3
49 changed files with 8383 additions and 19 deletions

View File

@@ -41,6 +41,7 @@ namespace hal {
namespace init {
void InitializeHAL() {
InitializeCTREPCM();
InitializeREVPH();
InitializeAddressableLED();
InitializeAccelerometer();
InitializeAnalogAccumulator();

View File

@@ -17,6 +17,7 @@ inline void CheckInit() {
}
extern void InitializeCTREPCM();
extern void InitializeREVPH();
extern void InitializeAccelerometer();
extern void InitializeAddressableLED();
extern void InitializeAnalogAccumulator();

View File

@@ -74,6 +74,12 @@ int32_t HAL_GetNumREVPDHModules(void) {
int32_t HAL_GetNumREVPDHChannels(void) {
return kNumREVPDHChannels;
}
int32_t HAL_GetNumREVPHModules(void) {
return kNumREVPHModules;
}
int32_t HAL_GetNumREVPHChannels(void) {
return kNumREVPHChannels;
}
int32_t HAL_GetNumDutyCycles(void) {
return kNumDutyCycles;
}

View File

@@ -36,5 +36,7 @@ constexpr int32_t kNumREVPDHModules = 63;
constexpr int32_t kNumREVPDHChannels = 24;
constexpr int32_t kNumDutyCycles = tDutyCycle::kNumSystems;
constexpr int32_t kNumAddressableLEDs = tLED::kNumSystems;
constexpr int32_t kNumREVPHModules = 63;
constexpr int32_t kNumREVPHChannels = 16;
} // namespace hal

View File

@@ -0,0 +1,479 @@
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
#include "hal/REVPH.h"
#include <fmt/format.h>
#include "HALInitializer.h"
#include "HALInternal.h"
#include "PortsInternal.h"
#include "hal/CANAPI.h"
#include "hal/Errors.h"
#include "hal/handles/IndexedHandleResource.h"
#include "rev/PHFrames.h"
using namespace hal;
static constexpr HAL_CANManufacturer manufacturer =
HAL_CANManufacturer::HAL_CAN_Man_kREV;
static constexpr HAL_CANDeviceType deviceType =
HAL_CANDeviceType::HAL_CAN_Dev_kPneumatics;
static constexpr int32_t kDefaultControlPeriod = 20;
// static constexpr uint8_t kDefaultSensorMask = (1 <<
// HAL_REV_PHSENSOR_DIGITAL);
static constexpr uint8_t kDefaultCompressorDuty = 255;
static constexpr uint8_t kDefaultPressureTarget = 120;
static constexpr uint8_t kDefaultPressureHysteresis = 60;
#define HAL_REV_MAX_PULSE_TIME 65534
#define HAL_REV_MAX_PRESSURE_TARGET 120
#define HAL_REV_MAX_PRESSURE_HYSTERESIS HAL_REV_MAX_PRESSURE_TARGET
static constexpr uint32_t APIFromExtId(uint32_t extId) {
return (extId >> 6) & 0x3FF;
}
static constexpr uint32_t PH_SET_ALL_FRAME_API =
APIFromExtId(PH_SET_ALL_FRAME_ID);
static constexpr uint32_t PH_PULSE_ONCE_FRAME_API =
APIFromExtId(PH_PULSE_ONCE_FRAME_ID);
static constexpr uint32_t PH_STATUS0_FRAME_API =
APIFromExtId(PH_STATUS0_FRAME_ID);
static constexpr uint32_t PH_STATUS1_FRAME_API =
APIFromExtId(PH_STATUS1_FRAME_ID);
static constexpr int32_t kPHFrameStatus0Timeout = 50;
static constexpr int32_t kPHFrameStatus1Timeout = 50;
namespace {
struct REV_PHObj {
int32_t controlPeriod;
PH_set_all_t desiredSolenoidsState;
wpi::mutex solenoidLock;
HAL_CANHandle hcan;
std::string previousAllocation;
};
} // namespace
static IndexedHandleResource<HAL_REVPHHandle, REV_PHObj, 63,
HAL_HandleEnum::REVPH>* REVPHHandles;
namespace hal::init {
void InitializeREVPH() {
static IndexedHandleResource<HAL_REVPHHandle, REV_PHObj, kNumREVPHModules,
HAL_HandleEnum::REVPH>
rH;
REVPHHandles = &rH;
}
} // namespace hal::init
static PH_status0_t HAL_REV_ReadPHStatus0(HAL_CANHandle hcan, int32_t* status) {
uint8_t packedData[8] = {0};
int32_t length = 0;
uint64_t timestamp = 0;
PH_status0_t result = {};
HAL_ReadCANPacketTimeout(hcan, PH_STATUS0_FRAME_API, packedData, &length,
&timestamp, kPHFrameStatus0Timeout * 2, status);
if (*status != 0) {
return result;
}
PH_status0_unpack(&result, packedData, PH_STATUS0_LENGTH);
return result;
}
static PH_status1_t HAL_REV_ReadPHStatus1(HAL_CANHandle hcan, int32_t* status) {
uint8_t packedData[8] = {0};
int32_t length = 0;
uint64_t timestamp = 0;
PH_status1_t result = {};
HAL_ReadCANPacketTimeout(hcan, PH_STATUS1_FRAME_API, packedData, &length,
&timestamp, kPHFrameStatus1Timeout * 2, status);
if (*status != 0) {
return result;
}
PH_status1_unpack(&result, packedData, PH_STATUS1_LENGTH);
return result;
}
enum REV_SolenoidState {
kSolenoidDisabled = 0,
kSolenoidEnabled,
kSolenoidControlledViaPulse
};
static void HAL_REV_UpdateDesiredPHSolenoidState(REV_PHObj* hph,
int32_t solenoid,
REV_SolenoidState state) {
switch (solenoid) {
case 0:
hph->desiredSolenoidsState.channel_0 = state;
break;
case 1:
hph->desiredSolenoidsState.channel_1 = state;
break;
case 2:
hph->desiredSolenoidsState.channel_2 = state;
break;
case 3:
hph->desiredSolenoidsState.channel_3 = state;
break;
case 4:
hph->desiredSolenoidsState.channel_4 = state;
break;
case 5:
hph->desiredSolenoidsState.channel_5 = state;
break;
case 6:
hph->desiredSolenoidsState.channel_6 = state;
break;
case 7:
hph->desiredSolenoidsState.channel_7 = state;
break;
case 8:
hph->desiredSolenoidsState.channel_8 = state;
break;
case 9:
hph->desiredSolenoidsState.channel_9 = state;
break;
case 10:
hph->desiredSolenoidsState.channel_10 = state;
break;
case 11:
hph->desiredSolenoidsState.channel_11 = state;
break;
case 12:
hph->desiredSolenoidsState.channel_12 = state;
break;
case 13:
hph->desiredSolenoidsState.channel_13 = state;
break;
case 14:
hph->desiredSolenoidsState.channel_14 = state;
break;
case 15:
hph->desiredSolenoidsState.channel_15 = state;
break;
}
}
static void HAL_REV_SendSolenoidsState(REV_PHObj* hph, int32_t* status) {
uint8_t packedData[PH_SET_ALL_LENGTH] = {0};
PH_set_all_pack(packedData, &(hph->desiredSolenoidsState), PH_SET_ALL_LENGTH);
HAL_WriteCANPacketRepeating(hph->hcan, packedData, PH_SET_ALL_LENGTH,
PH_SET_ALL_FRAME_API, hph->controlPeriod, status);
}
static HAL_Bool HAL_REV_CheckPHPulseTime(int32_t time) {
return ((time > 0) && (time <= HAL_REV_MAX_PULSE_TIME)) ? 1 : 0;
}
HAL_REVPHHandle HAL_InitializeREVPH(int32_t module,
const char* allocationLocation,
int32_t* status) {
hal::init::CheckInit();
if (!HAL_CheckREVPHModuleNumber(module)) {
hal::SetLastErrorIndexOutOfRange(status, "Invalid Index for REV PH", 1,
kNumREVPHModules, module);
return HAL_kInvalidHandle;
}
HAL_REVPHHandle handle;
auto hph = REVPHHandles->Allocate(module, &handle, status);
if (*status != 0) {
if (hph) {
hal::SetLastErrorPreviouslyAllocated(status, "REV PH", module,
hph->previousAllocation);
} else {
hal::SetLastErrorIndexOutOfRange(status, "Invalid Index for REV PH", 1,
kNumREVPHModules, module);
}
return HAL_kInvalidHandle; // failed to allocate. Pass error back.
}
HAL_CANHandle hcan =
HAL_InitializeCAN(manufacturer, module, deviceType, status);
if (*status != 0) {
REVPHHandles->Free(handle);
return HAL_kInvalidHandle;
}
hph->previousAllocation = allocationLocation ? allocationLocation : "";
hph->hcan = hcan;
hph->controlPeriod = kDefaultControlPeriod;
// TODO any other things
return handle;
}
void HAL_FreeREVPH(HAL_REVPHHandle handle) {
auto hph = REVPHHandles->Get(handle);
if (hph == nullptr)
return;
HAL_CleanCAN(hph->hcan);
REVPHHandles->Free(handle);
}
HAL_Bool HAL_CheckREVPHModuleNumber(int32_t module) {
return module >= 1 && module < kNumREVPDHModules;
}
HAL_Bool HAL_CheckREVPHSolenoidChannel(int32_t channel) {
return channel >= 0 && channel < kNumREVPHChannels;
}
HAL_Bool HAL_GetREVPHCompressor(HAL_REVPHHandle handle, int32_t* status) {
auto ph = REVPHHandles->Get(handle);
if (ph == nullptr) {
*status = HAL_HANDLE_ERROR;
return false;
}
PH_status0_t status0 = HAL_REV_ReadPHStatus0(ph->hcan, status);
if (*status != 0) {
return false;
}
return status0.compressor_on;
}
void HAL_SetREVPHClosedLoopControl(HAL_REVPHHandle handle, HAL_Bool enabled,
int32_t* status) {
// TODO
}
HAL_Bool HAL_GetREVPHClosedLoopControl(HAL_REVPHHandle handle,
int32_t* status) {
return false; // TODO
}
HAL_Bool HAL_GetREVPHPressureSwitch(HAL_REVPHHandle handle, int32_t* status) {
auto ph = REVPHHandles->Get(handle);
if (ph == nullptr) {
*status = HAL_HANDLE_ERROR;
return false;
}
PH_status0_t status0 = HAL_REV_ReadPHStatus0(ph->hcan, status);
if (*status != 0) {
return false;
}
return status0.digital_sensor;
}
double HAL_GetREVPHCompressorCurrent(HAL_REVPHHandle handle, int32_t* status) {
auto ph = REVPHHandles->Get(handle);
if (ph == nullptr) {
*status = HAL_HANDLE_ERROR;
return 0;
}
PH_status1_t status1 = HAL_REV_ReadPHStatus1(ph->hcan, status);
if (*status != 0) {
return 0;
}
return PH_status1_compressor_current_decode(status1.compressor_current);
}
double HAL_GetREVPHAnalogPressure(HAL_REVPHHandle handle, int32_t channel,
int32_t* status) {
auto ph = REVPHHandles->Get(handle);
if (ph == nullptr) {
*status = HAL_HANDLE_ERROR;
return 0;
}
if (channel < 0 || channel > 1) {
*status = PARAMETER_OUT_OF_RANGE;
hal::SetLastErrorIndexOutOfRange(status, "Invalid REV Analog Index", 0, 2,
channel);
return 0;
}
PH_status0_t status0 = HAL_REV_ReadPHStatus0(ph->hcan, status);
if (*status != 0) {
return 0;
}
if (channel == 1) {
return PH_status0_analog_0_decode(status0.analog_0);
}
return PH_status0_analog_1_decode(status0.analog_1);
}
int32_t HAL_GetREVPHSolenoids(HAL_REVPHHandle handle, int32_t* status) {
auto ph = REVPHHandles->Get(handle);
if (ph == nullptr) {
*status = HAL_HANDLE_ERROR;
return 0;
}
PH_status0_t status0 = HAL_REV_ReadPHStatus0(ph->hcan, status);
if (*status != 0) {
return 0;
}
uint32_t result = status0.channel_0;
result |= status0.channel_1 << 1;
result |= status0.channel_2 << 2;
result |= status0.channel_3 << 3;
result |= status0.channel_4 << 4;
result |= status0.channel_5 << 5;
result |= status0.channel_6 << 6;
result |= status0.channel_7 << 7;
result |= status0.channel_8 << 8;
result |= status0.channel_9 << 9;
result |= status0.channel_10 << 10;
result |= status0.channel_11 << 11;
result |= status0.channel_12 << 12;
result |= status0.channel_13 << 13;
result |= status0.channel_14 << 14;
result |= status0.channel_15 << 15;
return result;
}
void HAL_SetREVPHSolenoids(HAL_REVPHHandle handle, int32_t mask, int32_t values,
int32_t* status) {
auto ph = REVPHHandles->Get(handle);
if (ph == nullptr) {
*status = HAL_HANDLE_ERROR;
return;
}
std::scoped_lock lock{ph->solenoidLock};
for (int solenoid = 0; solenoid < kNumREVPHChannels; solenoid++) {
if (mask & (1 << solenoid)) {
// The mask bit for the solenoid is set, so we update the solenoid state
REV_SolenoidState desiredSolenoidState =
values & (1 << solenoid) ? kSolenoidEnabled : kSolenoidDisabled;
HAL_REV_UpdateDesiredPHSolenoidState(ph.get(), solenoid,
desiredSolenoidState);
}
}
HAL_REV_SendSolenoidsState(ph.get(), status);
}
void HAL_FireREVPHOneShot(HAL_REVPHHandle handle, int32_t index, int32_t durMs,
int32_t* status) {
auto ph = REVPHHandles->Get(handle);
if (ph == nullptr) {
*status = HAL_HANDLE_ERROR;
return;
}
if (index >= kNumREVPHChannels || index < 0) {
*status = PARAMETER_OUT_OF_RANGE;
hal::SetLastError(
status,
fmt::format("Only [0-15] are valid index values. Requested {}", index));
return;
}
if (!HAL_REV_CheckPHPulseTime(durMs)) {
*status = PARAMETER_OUT_OF_RANGE;
hal::SetLastError(
status,
fmt::format("Time not within expected range [0-65534]. Requested {}",
durMs));
return;
}
{
std::scoped_lock lock{ph->solenoidLock};
HAL_REV_UpdateDesiredPHSolenoidState(ph.get(), index,
kSolenoidControlledViaPulse);
HAL_REV_SendSolenoidsState(ph.get(), status);
}
if (*status != 0) {
return;
}
PH_pulse_once_t pulse = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
pulse.pulse_length_ms = durMs;
// Specify which solenoid should be pulsed
// The protocol supports specifying any number of solenoids to be pulsed at
// the same time, should that functionality be exposed to users in the future.
switch (index) {
case 0:
pulse.channel_0 = true;
break;
case 1:
pulse.channel_1 = true;
break;
case 2:
pulse.channel_2 = true;
break;
case 3:
pulse.channel_3 = true;
break;
case 4:
pulse.channel_4 = true;
break;
case 5:
pulse.channel_5 = true;
break;
case 6:
pulse.channel_6 = true;
break;
case 7:
pulse.channel_7 = true;
break;
case 8:
pulse.channel_8 = true;
break;
case 9:
pulse.channel_9 = true;
break;
case 10:
pulse.channel_10 = true;
break;
case 11:
pulse.channel_11 = true;
break;
case 12:
pulse.channel_12 = true;
break;
case 13:
pulse.channel_13 = true;
break;
case 14:
pulse.channel_14 = true;
break;
case 15:
pulse.channel_15 = true;
break;
}
// Send pulse command
uint8_t packedData[PH_PULSE_ONCE_LENGTH] = {0};
PH_pulse_once_pack(packedData, &pulse, PH_PULSE_ONCE_LENGTH);
HAL_WriteCANPacket(ph->hcan, packedData, PH_PULSE_ONCE_LENGTH,
PH_PULSE_ONCE_FRAME_API, status);
}

View File

@@ -0,0 +1,37 @@
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
#include "hal/simulation/REVPHData.h"
#include "hal/simulation/SimDataValue.h"
extern "C" {
void HALSIM_ResetREVPHData(int32_t index) {}
#define DEFINE_CAPI(TYPE, CAPINAME, RETURN) \
HAL_SIMDATAVALUE_STUB_CAPI(TYPE, HALSIM, REVPH##CAPINAME, RETURN)
HAL_SIMDATAVALUE_STUB_CAPI_CHANNEL(HAL_Bool, HALSIM, REVPHSolenoidOutput, false)
DEFINE_CAPI(HAL_Bool, Initialized, false)
DEFINE_CAPI(HAL_Bool, CompressorOn, false)
DEFINE_CAPI(HAL_Bool, ClosedLoopEnabled, false)
DEFINE_CAPI(HAL_Bool, PressureSwitch, false)
DEFINE_CAPI(double, CompressorCurrent, 0)
void HALSIM_GetREVPHAllSolenoids(int32_t index, uint8_t* values) {
*values = 0;
}
void HALSIM_SetREVPHAllSolenoids(int32_t index, uint8_t values) {}
void HALSIM_RegisterREVPHAllNonSolenoidCallbacks(int32_t index,
HAL_NotifyCallback callback,
void* param,
HAL_Bool initialNotify) {}
void HALSIM_RegisterREVPHAllSolenoidCallbacks(int32_t index, int32_t channel,
HAL_NotifyCallback callback,
void* param,
HAL_Bool initialNotify) {}
} // extern "C"

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -272,4 +272,30 @@ Java_edu_wpi_first_hal_PortsJNI_getNumREVPDHChannels
jint value = HAL_GetNumREVPDHChannels();
return value;
}
/*
* Class: edu_wpi_first_hal_PortsJNI
* Method: getNumREVPHModules
* Signature: ()I
*/
JNIEXPORT jint JNICALL
Java_edu_wpi_first_hal_PortsJNI_getNumREVPHModules
(JNIEnv* env, jclass)
{
jint value = HAL_GetNumREVPHModules();
return value;
}
/*
* Class: edu_wpi_first_hal_PortsJNI
* Method: getNumREVPHChannels
* Signature: ()I
*/
JNIEXPORT jint JNICALL
Java_edu_wpi_first_hal_PortsJNI_getNumREVPHChannels
(JNIEnv* env, jclass)
{
jint value = HAL_GetNumREVPHChannels();
return value;
}
} // extern "C"

View File

@@ -0,0 +1,191 @@
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
#include <jni.h>
#include <wpi/jni_util.h>
#include "HALUtil.h"
#include "edu_wpi_first_hal_REVPHJNI.h"
#include "hal/Ports.h"
#include "hal/REVPH.h"
#include "hal/handles/HandlesInternal.h"
using namespace hal;
extern "C" {
/*
* Class: edu_wpi_first_hal_REVPHJNI
* Method: initialize
* Signature: (I)I
*/
JNIEXPORT jint JNICALL
Java_edu_wpi_first_hal_REVPHJNI_initialize
(JNIEnv* env, jclass, jint module)
{
int32_t status = 0;
auto stack = wpi::java::GetJavaStackTrace(env, "edu.wpi.first");
auto handle = HAL_InitializeREVPH(module, stack.c_str(), &status);
CheckStatusForceThrow(env, status);
return handle;
}
/*
* Class: edu_wpi_first_hal_REVPHJNI
* Method: free
* Signature: (I)V
*/
JNIEXPORT void JNICALL
Java_edu_wpi_first_hal_REVPHJNI_free
(JNIEnv* env, jclass, jint handle)
{
HAL_FreeREVPH(handle);
}
/*
* Class: edu_wpi_first_hal_REVPHJNI
* Method: checkSolenoidChannel
* Signature: (I)Z
*/
JNIEXPORT jboolean JNICALL
Java_edu_wpi_first_hal_REVPHJNI_checkSolenoidChannel
(JNIEnv*, jclass, jint channel)
{
return HAL_CheckREVPHSolenoidChannel(channel);
}
/*
* Class: edu_wpi_first_hal_REVPHJNI
* Method: getCompressor
* Signature: (I)Z
*/
JNIEXPORT jboolean JNICALL
Java_edu_wpi_first_hal_REVPHJNI_getCompressor
(JNIEnv* env, jclass, jint handle)
{
int32_t status = 0;
auto result = HAL_GetREVPHCompressor(handle, &status);
CheckStatus(env, status, false);
return result;
}
/*
* Class: edu_wpi_first_hal_REVPHJNI
* Method: setClosedLoopControl
* Signature: (IZ)V
*/
JNIEXPORT void JNICALL
Java_edu_wpi_first_hal_REVPHJNI_setClosedLoopControl
(JNIEnv* env, jclass, jint handle, jboolean enabled)
{
int32_t status = 0;
HAL_SetREVPHClosedLoopControl(handle, enabled, &status);
CheckStatus(env, status, false);
}
/*
* Class: edu_wpi_first_hal_REVPHJNI
* Method: getClosedLoopControl
* Signature: (I)Z
*/
JNIEXPORT jboolean JNICALL
Java_edu_wpi_first_hal_REVPHJNI_getClosedLoopControl
(JNIEnv* env, jclass, jint handle)
{
int32_t status = 0;
auto result = HAL_GetREVPHClosedLoopControl(handle, &status);
CheckStatus(env, status, false);
return result;
}
/*
* Class: edu_wpi_first_hal_REVPHJNI
* Method: getPressureSwitch
* Signature: (I)Z
*/
JNIEXPORT jboolean JNICALL
Java_edu_wpi_first_hal_REVPHJNI_getPressureSwitch
(JNIEnv* env, jclass, jint handle)
{
int32_t status = 0;
auto result = HAL_GetREVPHPressureSwitch(handle, &status);
CheckStatus(env, status, false);
return result;
}
/*
* Class: edu_wpi_first_hal_REVPHJNI
* Method: getAnalogPressure
* Signature: (II)D
*/
JNIEXPORT jdouble JNICALL
Java_edu_wpi_first_hal_REVPHJNI_getAnalogPressure
(JNIEnv* env, jclass, jint handle, jint channel)
{
int32_t status = 0;
auto result = HAL_GetREVPHAnalogPressure(handle, channel, &status);
CheckStatus(env, status, false);
return result;
}
/*
* Class: edu_wpi_first_hal_REVPHJNI
* Method: getCompressorCurrent
* Signature: (I)D
*/
JNIEXPORT jdouble JNICALL
Java_edu_wpi_first_hal_REVPHJNI_getCompressorCurrent
(JNIEnv* env, jclass, jint handle)
{
int32_t status = 0;
auto result = HAL_GetREVPHCompressorCurrent(handle, &status);
CheckStatus(env, status, false);
return result;
}
/*
* Class: edu_wpi_first_hal_REVPHJNI
* Method: getSolenoids
* Signature: (I)I
*/
JNIEXPORT jint JNICALL
Java_edu_wpi_first_hal_REVPHJNI_getSolenoids
(JNIEnv* env, jclass, jint handle)
{
int32_t status = 0;
auto result = HAL_GetREVPHSolenoids(handle, &status);
CheckStatus(env, status, false);
return result;
}
/*
* Class: edu_wpi_first_hal_REVPHJNI
* Method: setSolenoids
* Signature: (III)V
*/
JNIEXPORT void JNICALL
Java_edu_wpi_first_hal_REVPHJNI_setSolenoids
(JNIEnv* env, jclass, jint handle, jint mask, jint value)
{
int32_t status = 0;
HAL_SetREVPHSolenoids(handle, mask, value, &status);
CheckStatus(env, status, false);
}
/*
* Class: edu_wpi_first_hal_REVPHJNI
* Method: fireOneShot
* Signature: (III)V
*/
JNIEXPORT void JNICALL
Java_edu_wpi_first_hal_REVPHJNI_fireOneShot
(JNIEnv* env, jclass, jint handle, jint index, jint durMs)
{
int32_t status = 0;
HAL_FireREVPHOneShot(handle, index, durMs, &status);
CheckStatus(env, status, false);
}
} // extern "C"

View File

@@ -0,0 +1,365 @@
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
#include <jni.h>
#include "CallbackStore.h"
#include "edu_wpi_first_hal_simulation_REVPHDataJNI.h"
#include "hal/simulation/REVPHData.h"
using namespace hal;
extern "C" {
/*
* Class: edu_wpi_first_hal_simulation_REVPHDataJNI
* Method: registerInitializedCallback
* Signature: (ILjava/lang/Object;Z)I
*/
JNIEXPORT jint JNICALL
Java_edu_wpi_first_hal_simulation_REVPHDataJNI_registerInitializedCallback
(JNIEnv* env, jclass, jint index, jobject callback, jboolean initialNotify)
{
return sim::AllocateCallback(env, index, callback, initialNotify,
&HALSIM_RegisterREVPHInitializedCallback);
}
/*
* Class: edu_wpi_first_hal_simulation_REVPHDataJNI
* Method: cancelInitializedCallback
* Signature: (II)V
*/
JNIEXPORT void JNICALL
Java_edu_wpi_first_hal_simulation_REVPHDataJNI_cancelInitializedCallback
(JNIEnv* env, jclass, jint index, jint handle)
{
return sim::FreeCallback(env, handle, index,
&HALSIM_CancelREVPHInitializedCallback);
}
/*
* Class: edu_wpi_first_hal_simulation_REVPHDataJNI
* Method: getInitialized
* Signature: (I)Z
*/
JNIEXPORT jboolean JNICALL
Java_edu_wpi_first_hal_simulation_REVPHDataJNI_getInitialized
(JNIEnv*, jclass, jint index)
{
return HALSIM_GetREVPHInitialized(index);
}
/*
* Class: edu_wpi_first_hal_simulation_REVPHDataJNI
* Method: setInitialized
* Signature: (IZ)V
*/
JNIEXPORT void JNICALL
Java_edu_wpi_first_hal_simulation_REVPHDataJNI_setInitialized
(JNIEnv*, jclass, jint index, jboolean value)
{
HALSIM_SetREVPHInitialized(index, value);
}
/*
* Class: edu_wpi_first_hal_simulation_REVPHDataJNI
* Method: registerSolenoidOutputCallback
* Signature: (IILjava/lang/Object;Z)I
*/
JNIEXPORT jint JNICALL
Java_edu_wpi_first_hal_simulation_REVPHDataJNI_registerSolenoidOutputCallback
(JNIEnv* env, jclass, jint index, jint channel, jobject callback,
jboolean initialNotify)
{
return sim::AllocateChannelCallback(
env, index, channel, callback, initialNotify,
&HALSIM_RegisterREVPHSolenoidOutputCallback);
}
/*
* Class: edu_wpi_first_hal_simulation_REVPHDataJNI
* Method: cancelSolenoidOutputCallback
* Signature: (III)V
*/
JNIEXPORT void JNICALL
Java_edu_wpi_first_hal_simulation_REVPHDataJNI_cancelSolenoidOutputCallback
(JNIEnv* env, jclass, jint index, jint channel, jint handle)
{
return sim::FreeChannelCallback(env, handle, index, channel,
&HALSIM_CancelREVPHSolenoidOutputCallback);
}
/*
* Class: edu_wpi_first_hal_simulation_REVPHDataJNI
* Method: getSolenoidOutput
* Signature: (II)Z
*/
JNIEXPORT jboolean JNICALL
Java_edu_wpi_first_hal_simulation_REVPHDataJNI_getSolenoidOutput
(JNIEnv*, jclass, jint index, jint channel)
{
return HALSIM_GetREVPHSolenoidOutput(index, channel);
}
/*
* Class: edu_wpi_first_hal_simulation_REVPHDataJNI
* Method: setSolenoidOutput
* Signature: (IIZ)V
*/
JNIEXPORT void JNICALL
Java_edu_wpi_first_hal_simulation_REVPHDataJNI_setSolenoidOutput
(JNIEnv*, jclass, jint index, jint channel, jboolean value)
{
HALSIM_SetREVPHSolenoidOutput(index, channel, value);
}
/*
* Class: edu_wpi_first_hal_simulation_REVPHDataJNI
* Method: registerCompressorOnCallback
* Signature: (ILjava/lang/Object;Z)I
*/
JNIEXPORT jint JNICALL
Java_edu_wpi_first_hal_simulation_REVPHDataJNI_registerCompressorOnCallback
(JNIEnv* env, jclass, jint index, jobject callback, jboolean initialNotify)
{
return sim::AllocateCallback(env, index, callback, initialNotify,
&HALSIM_RegisterREVPHCompressorOnCallback);
}
/*
* Class: edu_wpi_first_hal_simulation_REVPHDataJNI
* Method: cancelCompressorOnCallback
* Signature: (II)V
*/
JNIEXPORT void JNICALL
Java_edu_wpi_first_hal_simulation_REVPHDataJNI_cancelCompressorOnCallback
(JNIEnv* env, jclass, jint index, jint handle)
{
return sim::FreeCallback(env, handle, index,
&HALSIM_CancelREVPHCompressorOnCallback);
}
/*
* Class: edu_wpi_first_hal_simulation_REVPHDataJNI
* Method: getCompressorOn
* Signature: (I)Z
*/
JNIEXPORT jboolean JNICALL
Java_edu_wpi_first_hal_simulation_REVPHDataJNI_getCompressorOn
(JNIEnv*, jclass, jint index)
{
return HALSIM_GetREVPHCompressorOn(index);
}
/*
* Class: edu_wpi_first_hal_simulation_REVPHDataJNI
* Method: setCompressorOn
* Signature: (IZ)V
*/
JNIEXPORT void JNICALL
Java_edu_wpi_first_hal_simulation_REVPHDataJNI_setCompressorOn
(JNIEnv*, jclass, jint index, jboolean value)
{
HALSIM_SetREVPHCompressorOn(index, value);
}
/*
* Class: edu_wpi_first_hal_simulation_REVPHDataJNI
* Method: registerClosedLoopEnabledCallback
* Signature: (ILjava/lang/Object;Z)I
*/
JNIEXPORT jint JNICALL
Java_edu_wpi_first_hal_simulation_REVPHDataJNI_registerClosedLoopEnabledCallback
(JNIEnv* env, jclass, jint index, jobject callback, jboolean initialNotify)
{
return sim::AllocateCallback(env, index, callback, initialNotify,
&HALSIM_RegisterREVPHClosedLoopEnabledCallback);
}
/*
* Class: edu_wpi_first_hal_simulation_REVPHDataJNI
* Method: cancelClosedLoopEnabledCallback
* Signature: (II)V
*/
JNIEXPORT void JNICALL
Java_edu_wpi_first_hal_simulation_REVPHDataJNI_cancelClosedLoopEnabledCallback
(JNIEnv* env, jclass, jint index, jint handle)
{
return sim::FreeCallback(env, handle, index,
&HALSIM_CancelREVPHClosedLoopEnabledCallback);
}
/*
* Class: edu_wpi_first_hal_simulation_REVPHDataJNI
* Method: getClosedLoopEnabled
* Signature: (I)Z
*/
JNIEXPORT jboolean JNICALL
Java_edu_wpi_first_hal_simulation_REVPHDataJNI_getClosedLoopEnabled
(JNIEnv*, jclass, jint index)
{
return HALSIM_GetREVPHClosedLoopEnabled(index);
}
/*
* Class: edu_wpi_first_hal_simulation_REVPHDataJNI
* Method: setClosedLoopEnabled
* Signature: (IZ)V
*/
JNIEXPORT void JNICALL
Java_edu_wpi_first_hal_simulation_REVPHDataJNI_setClosedLoopEnabled
(JNIEnv*, jclass, jint index, jboolean value)
{
HALSIM_SetREVPHClosedLoopEnabled(index, value);
}
/*
* Class: edu_wpi_first_hal_simulation_REVPHDataJNI
* Method: registerPressureSwitchCallback
* Signature: (ILjava/lang/Object;Z)I
*/
JNIEXPORT jint JNICALL
Java_edu_wpi_first_hal_simulation_REVPHDataJNI_registerPressureSwitchCallback
(JNIEnv* env, jclass, jint index, jobject callback, jboolean initialNotify)
{
return sim::AllocateCallback(env, index, callback, initialNotify,
&HALSIM_RegisterREVPHPressureSwitchCallback);
}
/*
* Class: edu_wpi_first_hal_simulation_REVPHDataJNI
* Method: cancelPressureSwitchCallback
* Signature: (II)V
*/
JNIEXPORT void JNICALL
Java_edu_wpi_first_hal_simulation_REVPHDataJNI_cancelPressureSwitchCallback
(JNIEnv* env, jclass, jint index, jint handle)
{
return sim::FreeCallback(env, handle, index,
&HALSIM_CancelREVPHPressureSwitchCallback);
}
/*
* Class: edu_wpi_first_hal_simulation_REVPHDataJNI
* Method: getPressureSwitch
* Signature: (I)Z
*/
JNIEXPORT jboolean JNICALL
Java_edu_wpi_first_hal_simulation_REVPHDataJNI_getPressureSwitch
(JNIEnv*, jclass, jint index)
{
return HALSIM_GetREVPHPressureSwitch(index);
}
/*
* Class: edu_wpi_first_hal_simulation_REVPHDataJNI
* Method: setPressureSwitch
* Signature: (IZ)V
*/
JNIEXPORT void JNICALL
Java_edu_wpi_first_hal_simulation_REVPHDataJNI_setPressureSwitch
(JNIEnv*, jclass, jint index, jboolean value)
{
HALSIM_SetREVPHPressureSwitch(index, value);
}
/*
* Class: edu_wpi_first_hal_simulation_REVPHDataJNI
* Method: registerCompressorCurrentCallback
* Signature: (ILjava/lang/Object;Z)I
*/
JNIEXPORT jint JNICALL
Java_edu_wpi_first_hal_simulation_REVPHDataJNI_registerCompressorCurrentCallback
(JNIEnv* env, jclass, jint index, jobject callback, jboolean initialNotify)
{
return sim::AllocateCallback(env, index, callback, initialNotify,
&HALSIM_RegisterREVPHCompressorCurrentCallback);
}
/*
* Class: edu_wpi_first_hal_simulation_REVPHDataJNI
* Method: cancelCompressorCurrentCallback
* Signature: (II)V
*/
JNIEXPORT void JNICALL
Java_edu_wpi_first_hal_simulation_REVPHDataJNI_cancelCompressorCurrentCallback
(JNIEnv* env, jclass, jint index, jint handle)
{
return sim::FreeCallback(env, handle, index,
&HALSIM_CancelREVPHCompressorCurrentCallback);
}
/*
* Class: edu_wpi_first_hal_simulation_REVPHDataJNI
* Method: getCompressorCurrent
* Signature: (I)D
*/
JNIEXPORT jdouble JNICALL
Java_edu_wpi_first_hal_simulation_REVPHDataJNI_getCompressorCurrent
(JNIEnv*, jclass, jint index)
{
return HALSIM_GetREVPHCompressorCurrent(index);
}
/*
* Class: edu_wpi_first_hal_simulation_REVPHDataJNI
* Method: setCompressorCurrent
* Signature: (ID)V
*/
JNIEXPORT void JNICALL
Java_edu_wpi_first_hal_simulation_REVPHDataJNI_setCompressorCurrent
(JNIEnv*, jclass, jint index, jdouble value)
{
HALSIM_SetREVPHCompressorCurrent(index, value);
}
/*
* Class: edu_wpi_first_hal_simulation_REVPHDataJNI
* Method: registerAllNonSolenoidCallbacks
* Signature: (ILjava/lang/Object;Z)V
*/
JNIEXPORT void JNICALL
Java_edu_wpi_first_hal_simulation_REVPHDataJNI_registerAllNonSolenoidCallbacks
(JNIEnv* env, jclass, jint index, jobject callback, jboolean initialNotify)
{
sim::AllocateCallback(
env, index, callback, initialNotify,
[](int32_t index, HAL_NotifyCallback cb, void* param, HAL_Bool in) {
HALSIM_RegisterREVPHAllNonSolenoidCallbacks(index, cb, param, in);
return 0;
});
}
/*
* Class: edu_wpi_first_hal_simulation_REVPHDataJNI
* Method: registerAllSolenoidCallbacks
* Signature: (IILjava/lang/Object;Z)V
*/
JNIEXPORT void JNICALL
Java_edu_wpi_first_hal_simulation_REVPHDataJNI_registerAllSolenoidCallbacks
(JNIEnv* env, jclass, jint index, jint channel, jobject callback,
jboolean initialNotify)
{
sim::AllocateChannelCallback(
env, index, channel, callback, initialNotify,
[](int32_t index, int32_t channel, HAL_NotifyCallback cb, void* param,
HAL_Bool in) {
HALSIM_RegisterREVPHAllSolenoidCallbacks(index, channel, cb, param, in);
return 0;
});
}
/*
* Class: edu_wpi_first_hal_simulation_REVPHDataJNI
* Method: resetData
* Signature: (I)V
*/
JNIEXPORT void JNICALL
Java_edu_wpi_first_hal_simulation_REVPHDataJNI_resetData
(JNIEnv*, jclass, jint index)
{
HALSIM_ResetREVPHData(index);
}
} // extern "C"

View File

@@ -156,6 +156,20 @@ int32_t HAL_GetNumREVPDHModules(void);
*/
int32_t HAL_GetNumREVPDHChannels(void);
/**
* Gets the number of PH modules in the current system.
*
* @return the number of PH modules
*/
int32_t HAL_GetNumREVPHModules(void);
/**
* Gets the number of PH channels in the current system.
*
* @return the number of PH channels
*/
int32_t HAL_GetNumREVPHChannels(void);
/**
* Gets the number of duty cycle inputs in the current system.
*

View File

@@ -0,0 +1,49 @@
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
#pragma once
#include <stdint.h>
#include "hal/Types.h"
/**
* @defgroup hal_rev_ph REV PH Functions
* @ingroup hal_capi
* @{
*/
#ifdef __cplusplus
extern "C" {
#endif
HAL_REVPHHandle HAL_InitializeREVPH(int32_t module,
const char* allocationLocation,
int32_t* status);
void HAL_FreeREVPH(HAL_REVPHHandle handle);
HAL_Bool HAL_CheckREVPHSolenoidChannel(int32_t channel);
HAL_Bool HAL_CheckREVPHModuleNumber(int32_t module);
HAL_Bool HAL_GetREVPHCompressor(HAL_REVPHHandle handle, int32_t* status);
void HAL_SetREVPHClosedLoopControl(HAL_REVPHHandle handle, HAL_Bool enabled,
int32_t* status);
HAL_Bool HAL_GetREVPHClosedLoopControl(HAL_REVPHHandle handle, int32_t* status);
HAL_Bool HAL_GetREVPHPressureSwitch(HAL_REVPHHandle handle, int32_t* status);
double HAL_GetREVPHCompressorCurrent(HAL_REVPHHandle handle, int32_t* status);
double HAL_GetREVPHAnalogPressure(HAL_REVPHHandle handle, int32_t channel,
int32_t* status);
int32_t HAL_GetREVPHSolenoids(HAL_REVPHHandle handle, int32_t* status);
void HAL_SetREVPHSolenoids(HAL_REVPHHandle handle, int32_t mask, int32_t values,
int32_t* status);
void HAL_FireREVPHOneShot(HAL_REVPHHandle handle, int32_t index, int32_t durMs,
int32_t* status);
#ifdef __cplusplus
} // extern "C"
#endif
/** @} */

View File

@@ -68,6 +68,8 @@ typedef HAL_Handle HAL_CTREPCMHandle;
typedef HAL_Handle HAL_REVPDHHandle;
typedef HAL_Handle HAL_REVPHHandle;
typedef int32_t HAL_Bool;
#ifdef __cplusplus

View File

@@ -68,7 +68,8 @@ enum class HAL_HandleEnum {
AddressableLED = 23,
CTREPCM = 24,
CTREPDP = 25,
REVPDH = 26
REVPDH = 26,
REVPH = 27,
};
/**

View File

@@ -0,0 +1,80 @@
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
#pragma once
#include "hal/Types.h"
#include "hal/simulation/NotifyListener.h"
#ifdef __cplusplus
extern "C" {
#endif
void HALSIM_ResetREVPHData(int32_t index);
int32_t HALSIM_RegisterREVPHInitializedCallback(int32_t index,
HAL_NotifyCallback callback,
void* param,
HAL_Bool initialNotify);
void HALSIM_CancelREVPHInitializedCallback(int32_t index, int32_t uid);
HAL_Bool HALSIM_GetREVPHInitialized(int32_t index);
void HALSIM_SetREVPHInitialized(int32_t index, HAL_Bool solenoidInitialized);
int32_t HALSIM_RegisterREVPHSolenoidOutputCallback(int32_t index,
int32_t channel,
HAL_NotifyCallback callback,
void* param,
HAL_Bool initialNotify);
void HALSIM_CancelREVPHSolenoidOutputCallback(int32_t index, int32_t channel,
int32_t uid);
HAL_Bool HALSIM_GetREVPHSolenoidOutput(int32_t index, int32_t channel);
void HALSIM_SetREVPHSolenoidOutput(int32_t index, int32_t channel,
HAL_Bool solenoidOutput);
int32_t HALSIM_RegisterREVPHCompressorOnCallback(int32_t index,
HAL_NotifyCallback callback,
void* param,
HAL_Bool initialNotify);
void HALSIM_CancelREVPHCompressorOnCallback(int32_t index, int32_t uid);
HAL_Bool HALSIM_GetREVPHCompressorOn(int32_t index);
void HALSIM_SetREVPHCompressorOn(int32_t index, HAL_Bool compressorOn);
int32_t HALSIM_RegisterREVPHClosedLoopEnabledCallback(
int32_t index, HAL_NotifyCallback callback, void* param,
HAL_Bool initialNotify);
void HALSIM_CancelREVPHClosedLoopEnabledCallback(int32_t index, int32_t uid);
HAL_Bool HALSIM_GetREVPHClosedLoopEnabled(int32_t index);
void HALSIM_SetREVPHClosedLoopEnabled(int32_t index,
HAL_Bool closedLoopEnabled);
int32_t HALSIM_RegisterREVPHPressureSwitchCallback(int32_t index,
HAL_NotifyCallback callback,
void* param,
HAL_Bool initialNotify);
void HALSIM_CancelREVPHPressureSwitchCallback(int32_t index, int32_t uid);
HAL_Bool HALSIM_GetREVPHPressureSwitch(int32_t index);
void HALSIM_SetREVPHPressureSwitch(int32_t index, HAL_Bool pressureSwitch);
int32_t HALSIM_RegisterREVPHCompressorCurrentCallback(
int32_t index, HAL_NotifyCallback callback, void* param,
HAL_Bool initialNotify);
void HALSIM_CancelREVPHCompressorCurrentCallback(int32_t index, int32_t uid);
double HALSIM_GetREVPHCompressorCurrent(int32_t index);
void HALSIM_SetREVPHCompressorCurrent(int32_t index, double compressorCurrent);
void HALSIM_GetREVPHAllSolenoids(int32_t index, uint8_t* values);
void HALSIM_SetREVPHAllSolenoids(int32_t index, uint8_t values);
void HALSIM_RegisterREVPHAllNonSolenoidCallbacks(int32_t index,
HAL_NotifyCallback callback,
void* param,
HAL_Bool initialNotify);
void HALSIM_RegisterREVPHAllSolenoidCallbacks(int32_t index, int32_t channel,
HAL_NotifyCallback callback,
void* param,
HAL_Bool initialNotify);
#ifdef __cplusplus
} // extern "C"
#endif

View File

@@ -48,7 +48,7 @@ HAL_CTREPCMHandle HAL_InitializeCTREPCM(int32_t module,
pcm->previousAllocation);
} else {
hal::SetLastErrorIndexOutOfRange(status, "Invalid Index for CTRE PCM", 0,
kNumAccumulators, module);
kNumCTREPCMModules, module);
}
return HAL_kInvalidHandle; // failed to allocate. Pass error back.
}

View File

@@ -74,6 +74,7 @@ void InitializeHAL() {
InitializeEncoderData();
InitializeI2CData();
InitializeCTREPCMData();
InitializeREVPHData();
InitializePowerDistributionData();
InitializePWMData();
InitializeRelayData();
@@ -107,6 +108,7 @@ void InitializeHAL() {
InitializePorts();
InitializePower();
InitializeCTREPCM();
InitializeREVPH();
InitializePWM();
InitializeRelay();
InitializeSerialPort();

View File

@@ -32,6 +32,7 @@ extern void InitializeDriverStationData();
extern void InitializeEncoderData();
extern void InitializeI2CData();
extern void InitializeCTREPCMData();
extern void InitializeREVPHData();
extern void InitializePowerDistributionData();
extern void InitializePWMData();
extern void InitializeRelayData();
@@ -65,6 +66,7 @@ extern void InitializePowerDistribution();
extern void InitializePorts();
extern void InitializePower();
extern void InitializeCTREPCM();
extern void InitializeREVPH();
extern void InitializePWM();
extern void InitializeRelay();
extern void InitializeSerialPort();

View File

@@ -73,6 +73,12 @@ int32_t HAL_GetNumREVPDHModules(void) {
int32_t HAL_GetNumREVPDHChannels(void) {
return kNumREVPDHChannels;
}
int32_t HAL_GetNumREVPHModules(void) {
return kNumREVPHModules;
}
int32_t HAL_GetNumREVPHChannels(void) {
return kNumREVPHChannels;
}
int32_t HAL_GetNumDutyCycles(void) {
return kNumDutyCycles;
}

View File

@@ -29,4 +29,6 @@ constexpr int32_t kNumREVPDHModules = 63;
constexpr int32_t kNumREVPDHChannels = 24;
constexpr int32_t kNumDutyCycles = 8;
constexpr int32_t kNumAddressableLEDs = 1;
constexpr int32_t kNumREVPHModules = 63;
constexpr int32_t kNumREVPHChannels = 16;
} // namespace hal

View File

@@ -0,0 +1,181 @@
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
#include "hal/REVPH.h"
#include "HALInitializer.h"
#include "HALInternal.h"
#include "PortsInternal.h"
#include "hal/CANAPI.h"
#include "hal/Errors.h"
#include "hal/handles/IndexedHandleResource.h"
#include "mockdata/REVPHDataInternal.h"
using namespace hal;
namespace {
struct PCM {
int32_t module;
wpi::mutex lock;
std::string previousAllocation;
};
} // namespace
static IndexedHandleResource<HAL_REVPHHandle, PCM, kNumREVPHModules,
HAL_HandleEnum::REVPH>* pcmHandles;
namespace hal::init {
void InitializeREVPH() {
static IndexedHandleResource<HAL_REVPHHandle, PCM, kNumREVPHModules,
HAL_HandleEnum::REVPH>
pH;
pcmHandles = &pH;
}
} // namespace hal::init
HAL_REVPHHandle HAL_InitializeREVPH(int32_t module,
const char* allocationLocation,
int32_t* status) {
hal::init::CheckInit();
if (module == 0) {
hal::SetLastErrorIndexOutOfRange(status, "Invalid Index for REV PH", 1,
kNumREVPHModules, module);
return HAL_kInvalidHandle;
}
HAL_REVPHHandle handle;
auto pcm = pcmHandles->Allocate(module, &handle, status);
if (*status != 0) {
if (pcm) {
hal::SetLastErrorPreviouslyAllocated(status, "REV PH", module,
pcm->previousAllocation);
} else {
hal::SetLastErrorIndexOutOfRange(status, "Invalid Index for REV PH", 1,
kNumREVPHModules, module);
}
return HAL_kInvalidHandle; // failed to allocate. Pass error back.
}
pcm->previousAllocation = allocationLocation ? allocationLocation : "";
pcm->module = module;
SimREVPHData[module].initialized = true;
// Enable closed loop
SimREVPHData[module].closedLoopEnabled = true;
return handle;
}
void HAL_FreeREVPH(HAL_REVPHHandle handle) {
auto pcm = pcmHandles->Get(handle);
if (pcm == nullptr) {
pcmHandles->Free(handle);
return;
}
SimREVPHData[pcm->module].initialized = false;
pcmHandles->Free(handle);
}
HAL_Bool HAL_CheckREVPHModuleNumber(int32_t module) {
return module >= 1 && module < kNumREVPDHModules;
}
HAL_Bool HAL_CheckREVPHSolenoidChannel(int32_t channel) {
return channel < kNumREVPHChannels && channel >= 0;
}
HAL_Bool HAL_GetREVPHCompressor(HAL_REVPHHandle handle, int32_t* status) {
auto pcm = pcmHandles->Get(handle);
if (pcm == nullptr) {
*status = HAL_HANDLE_ERROR;
return false;
}
return SimREVPHData[pcm->module].compressorOn;
}
void HAL_SetREVPHClosedLoopControl(HAL_REVPHHandle handle, HAL_Bool enabled,
int32_t* status) {
auto pcm = pcmHandles->Get(handle);
if (pcm == nullptr) {
*status = HAL_HANDLE_ERROR;
return;
}
SimREVPHData[pcm->module].closedLoopEnabled = enabled;
}
HAL_Bool HAL_GetREVPHClosedLoopControl(HAL_REVPHHandle handle,
int32_t* status) {
auto pcm = pcmHandles->Get(handle);
if (pcm == nullptr) {
*status = HAL_HANDLE_ERROR;
return false;
}
return SimREVPHData[pcm->module].closedLoopEnabled;
}
HAL_Bool HAL_GetREVPHPressureSwitch(HAL_REVPHHandle handle, int32_t* status) {
auto pcm = pcmHandles->Get(handle);
if (pcm == nullptr) {
*status = HAL_HANDLE_ERROR;
return false;
}
return SimREVPHData[pcm->module].pressureSwitch;
}
double HAL_GetREVPHAnalogPressure(HAL_REVPHHandle handle, int32_t channel,
int32_t* status) {
return 0;
}
double HAL_GetREVPHCompressorCurrent(HAL_REVPHHandle handle, int32_t* status) {
auto pcm = pcmHandles->Get(handle);
if (pcm == nullptr) {
*status = HAL_HANDLE_ERROR;
return 0;
}
return SimREVPHData[pcm->module].compressorCurrent;
}
int32_t HAL_GetREVPHSolenoids(HAL_REVPHHandle handle, int32_t* status) {
auto pcm = pcmHandles->Get(handle);
if (pcm == nullptr) {
*status = HAL_HANDLE_ERROR;
return 0;
}
std::scoped_lock lock{pcm->lock};
auto& data = SimREVPHData[pcm->module].solenoidOutput;
uint8_t ret = 0;
for (int i = 0; i < kNumREVPHChannels; i++) {
ret |= (data[i] << i);
}
return ret;
}
void HAL_SetREVPHSolenoids(HAL_REVPHHandle handle, int32_t mask, int32_t values,
int32_t* status) {
auto pcm = pcmHandles->Get(handle);
if (pcm == nullptr) {
*status = HAL_HANDLE_ERROR;
return;
}
auto& data = SimREVPHData[pcm->module].solenoidOutput;
std::scoped_lock lock{pcm->lock};
for (int i = 0; i < kNumREVPHChannels; i++) {
auto indexMask = (1 << i);
if ((mask & indexMask) != 0) {
data[i] = (values & indexMask) != 0;
}
}
}
void HAL_FireREVPHOneShot(HAL_REVPHHandle handle, int32_t index, int32_t durMs,
int32_t* status) {}

View File

@@ -0,0 +1,83 @@
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
#include "../PortsInternal.h"
#include "REVPHDataInternal.h"
using namespace hal;
namespace hal::init {
void InitializeREVPHData() {
static REVPHData spd[kNumREVPHModules];
::hal::SimREVPHData = spd;
}
} // namespace hal::init
REVPHData* hal::SimREVPHData;
void REVPHData::ResetData() {
for (int i = 0; i < kNumREVPHChannels; i++) {
solenoidOutput[i].Reset(false);
}
initialized.Reset(false);
compressorOn.Reset(false);
closedLoopEnabled.Reset(true);
pressureSwitch.Reset(false);
compressorCurrent.Reset(0.0);
}
extern "C" {
void HALSIM_ResetREVPHData(int32_t index) {
SimREVPHData[index].ResetData();
}
#define DEFINE_CAPI(TYPE, CAPINAME, LOWERNAME) \
HAL_SIMDATAVALUE_DEFINE_CAPI(TYPE, HALSIM, REVPH##CAPINAME, SimREVPHData, \
LOWERNAME)
HAL_SIMDATAVALUE_DEFINE_CAPI_CHANNEL(HAL_Bool, HALSIM, REVPHSolenoidOutput,
SimREVPHData, solenoidOutput)
DEFINE_CAPI(HAL_Bool, Initialized, initialized)
DEFINE_CAPI(HAL_Bool, CompressorOn, compressorOn)
DEFINE_CAPI(HAL_Bool, ClosedLoopEnabled, closedLoopEnabled)
DEFINE_CAPI(HAL_Bool, PressureSwitch, pressureSwitch)
DEFINE_CAPI(double, CompressorCurrent, compressorCurrent)
void HALSIM_GetREVPHAllSolenoids(int32_t index, uint8_t* values) {
auto& data = SimREVPHData[index].solenoidOutput;
uint8_t ret = 0;
for (int i = 0; i < kNumCTRESolenoidChannels; i++) {
ret |= (data[i] << i);
}
*values = ret;
}
void HALSIM_SetREVPHAllSolenoids(int32_t index, uint8_t values) {
auto& data = SimREVPHData[index].solenoidOutput;
for (int i = 0; i < kNumCTRESolenoidChannels; i++) {
data[i] = (values & 0x1) != 0;
values >>= 1;
}
}
#define REGISTER(NAME) \
SimREVPHData[index].NAME.RegisterCallback(callback, param, initialNotify)
void HALSIM_RegisterREVPHAllNonSolenoidCallbacks(int32_t index,
HAL_NotifyCallback callback,
void* param,
HAL_Bool initialNotify) {
REGISTER(initialized);
REGISTER(compressorOn);
REGISTER(closedLoopEnabled);
REGISTER(pressureSwitch);
REGISTER(compressorCurrent);
}
void HALSIM_RegisterREVPHAllSolenoidCallbacks(int32_t index, int32_t channel,
HAL_NotifyCallback callback,
void* param,
HAL_Bool initialNotify) {
REGISTER(solenoidOutput[channel]);
}
} // extern "C"

View File

@@ -0,0 +1,43 @@
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
#pragma once
#include "../PortsInternal.h"
#include "hal/simulation/REVPHData.h"
#include "hal/simulation/SimDataValue.h"
namespace hal {
class REVPHData {
HAL_SIMDATAVALUE_DEFINE_NAME(Initialized)
HAL_SIMDATAVALUE_DEFINE_NAME(SolenoidOutput)
HAL_SIMDATAVALUE_DEFINE_NAME(CompressorOn)
HAL_SIMDATAVALUE_DEFINE_NAME(ClosedLoopEnabled)
HAL_SIMDATAVALUE_DEFINE_NAME(PressureSwitch)
HAL_SIMDATAVALUE_DEFINE_NAME(CompressorCurrent)
static LLVM_ATTRIBUTE_ALWAYS_INLINE constexpr HAL_Bool
GetSolenoidOutputDefault() {
return false;
}
public:
SimDataValue<HAL_Bool, HAL_MakeBoolean, GetInitializedName> initialized{
false};
SimDataValue<HAL_Bool, HAL_MakeBoolean, GetSolenoidOutputName,
GetSolenoidOutputDefault>
solenoidOutput[kNumREVPHChannels];
SimDataValue<HAL_Bool, HAL_MakeBoolean, GetCompressorOnName> compressorOn{
false};
SimDataValue<HAL_Bool, HAL_MakeBoolean, GetClosedLoopEnabledName>
closedLoopEnabled{true};
SimDataValue<HAL_Bool, HAL_MakeBoolean, GetPressureSwitchName> pressureSwitch{
false};
SimDataValue<double, HAL_MakeDouble, GetCompressorCurrentName>
compressorCurrent{0.0};
virtual void ResetData();
};
extern REVPHData* SimREVPHData;
} // namespace hal