use super::sensor_util;
use wpilib_sys::usage::{instances, resource_types};
use wpilib_sys::*;
#[derive(Debug)]
pub struct SolenoidModule {
module: i32,
}
impl SolenoidModule {
pub fn all_with_module(module: i32) -> HalResult<i32> {
hal_call!(HAL_GetAllSolenoids(module))
}
pub fn all(&self) -> HalResult<i32> {
Self::all_with_module(self.module)
}
pub fn pcm_solenoid_blacklist_with_module(module: i32) -> i32 {
maybe_hal_call!(HAL_GetPCMSolenoidBlackList(module)).ok()
}
pub fn pcm_solenoid_blacklist(&self) -> i32 {
Self::pcm_solenoid_blacklist_with_module(self.module)
}
pub fn pcm_solenoid_voltage_sticky_fault_with_module(module: i32) -> bool {
maybe_hal_call!(HAL_GetPCMSolenoidVoltageStickyFault(module)).ok() != 0
}
pub fn pcm_solenoid_voltage_sticky_fault(&self) -> bool {
Self::pcm_solenoid_voltage_sticky_fault_with_module(self.module)
}
pub fn pcm_solenoid_voltage_fault_with_module(module: i32) -> bool {
maybe_hal_call!(HAL_GetPCMSolenoidVoltageFault(module)).ok() != 0
}
pub fn pcm_solenoid_voltage_fault(&self) -> bool {
Self::pcm_solenoid_voltage_fault_with_module(self.module)
}
pub fn clear_all_pcm_sticky_faults_with_module(module: i32) {
maybe_hal_call!(HAL_ClearAllPCMStickyFaults(module)).ok();
}
pub fn clear_all_pcm_sticky_faults(&self) {
Self::clear_all_pcm_sticky_faults_with_module(self.module);
}
}
#[derive(Debug)]
pub struct Solenoid {
solenoid_handle: HAL_SolenoidHandle,
channel: i32,
module: SolenoidModule,
}
impl Solenoid {
#[allow(clippy::new_ret_no_self)]
pub fn new(channel: i32) -> HalResult<Solenoid> {
Self::new_with_module(sensor_util::default_solenoid_module(), channel)
}
pub fn new_with_module(module_number: i32, channel: i32) -> HalResult<Solenoid> {
if !sensor_util::check_solenoid_module(module_number) {
return Err(HalError(0));
};
if !sensor_util::check_solenoid_channel(channel) {
return Err(HalError(0));
};
let handle = hal_call!(HAL_InitializeSolenoidPort(HAL_GetPortWithModule(
module_number,
channel
)))?;
report_usage_context(
resource_types::Solenoid,
channel as instances::Type,
module_number,
);
Ok(Solenoid {
solenoid_handle: handle,
channel,
module: SolenoidModule {
module: module_number,
},
})
}
pub fn set(&self, on: bool) -> HalResult<()> {
hal_call!(HAL_SetSolenoid(self.solenoid_handle, on as i32))
}
pub fn get(&self) -> HalResult<bool> {
Ok(hal_call!(HAL_GetSolenoid(self.solenoid_handle))? != 0)
}
pub fn is_blacklisted(&self) -> bool {
(self.module.pcm_solenoid_blacklist() & (1 << self.channel)) != 0
}
pub fn set_pulse_duration(&self, seconds: f64) -> HalResult<()> {
let duration_ms: i32 = (seconds * 1000.0) as i32;
hal_call!(HAL_SetOneShotDuration(self.solenoid_handle, duration_ms))
}
pub fn start_pulse(&self) -> HalResult<()> {
hal_call!(HAL_FireOneShot(self.solenoid_handle))
}
pub fn module(&self) -> &SolenoidModule {
&self.module
}
}
impl Drop for Solenoid {
fn drop(&mut self) {
unsafe { HAL_FreeSolenoidPort(self.solenoid_handle) }
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub enum Action {
Forward,
Reverse,
Off,
}
#[derive(Debug)]
pub struct DoubleSolenoid {
forward: Solenoid,
reverse: Solenoid,
}
impl DoubleSolenoid {
#[allow(clippy::new_ret_no_self)]
pub fn new(forward_channel: i32, reverse_channel: i32) -> HalResult<DoubleSolenoid> {
Self::new_with_module(
sensor_util::default_solenoid_module(),
forward_channel,
reverse_channel,
)
}
pub fn new_with_module(
module_number: i32,
forward_channel: i32,
reverse_channel: i32,
) -> HalResult<DoubleSolenoid> {
Ok(DoubleSolenoid {
forward: Solenoid::new_with_module(module_number, forward_channel)?,
reverse: Solenoid::new_with_module(module_number, reverse_channel)?,
})
}
pub fn set(&self, action: Action) -> HalResult<()> {
let forward;
let reverse;
match action {
Action::Forward => {
forward = true;
reverse = false;
}
Action::Reverse => {
forward = false;
reverse = true;
}
Action::Off => {
forward = false;
reverse = false;
}
};
self.forward.set(forward)?;
self.reverse.set(reverse)?;
Ok(())
}
pub fn get(&self) -> HalResult<Action> {
if self.forward.get()? {
return Ok(Action::Forward);
};
if self.reverse.get()? {
return Ok(Action::Reverse);
};
Ok(Action::Off)
}
pub fn is_fwd_blacklisted(&self) -> bool {
self.forward.is_blacklisted()
}
pub fn is_rev_blacklisted(&self) -> bool {
self.reverse.is_blacklisted()
}
pub fn module(&self) -> &SolenoidModule {
self.forward.module()
}
}
#[derive(Debug)]
pub struct Compressor {
compressor_handle: HAL_CompressorHandle,
module: i32,
}
impl Compressor {
#[allow(clippy::new_ret_no_self)]
pub fn new() -> HalResult<Self> {
Self::new_with_module(sensor_util::default_solenoid_module())
}
pub fn new_with_module(module: i32) -> HalResult<Self> {
let compressor_handle = hal_call!(HAL_InitializeCompressor(module))?;
Ok(Self {
compressor_handle,
module,
})
}
pub fn set_closed_loop_control(&self, on: bool) {
hal_call!(HAL_SetCompressorClosedLoopControl(
self.compressor_handle,
on as i32
))
.ok();
}
pub fn start(&self) {
self.set_closed_loop_control(true);
}
pub fn stop(&self) {
self.set_closed_loop_control(false);
}
pub fn enabled(&self) -> bool {
maybe_hal_call!(HAL_GetCompressor(self.compressor_handle)).ok() != 0
}
pub fn pressure_switch_value(&self) -> bool {
maybe_hal_call!(HAL_GetCompressorPressureSwitch(self.compressor_handle)).ok() != 0
}
pub fn compressor_current(&self) -> f64 {
maybe_hal_call!(HAL_GetCompressorCurrent(self.compressor_handle)).ok()
}
pub fn closed_loop_control(&self) -> bool {
maybe_hal_call!(HAL_GetCompressorClosedLoopControl(self.compressor_handle)).ok() != 0
}
pub fn compressor_current_too_high_fault(&self) -> bool {
maybe_hal_call!(HAL_GetCompressorCurrentTooHighStickyFault(
self.compressor_handle
))
.ok()
!= 0
}
pub fn compressor_current_too_high_sticky_fault(&self) -> bool {
maybe_hal_call!(HAL_GetCompressorCurrentTooHighStickyFault(
self.compressor_handle
))
.ok()
!= 0
}
pub fn compressor_shorted_sticky_fault(&self) -> bool {
maybe_hal_call!(HAL_GetCompressorShortedStickyFault(self.compressor_handle)).ok() != 0
}
pub fn compressor_shorted_fault(&self) -> bool {
maybe_hal_call!(HAL_GetCompressorShortedFault(self.compressor_handle)).ok() != 0
}
pub fn compressor_not_connected_sticky_fault(&self) -> bool {
maybe_hal_call!(HAL_GetCompressorNotConnectedStickyFault(
self.compressor_handle
))
.ok()
!= 0
}
pub fn compressor_not_connected_fault(&self) -> bool {
maybe_hal_call!(HAL_GetCompressorNotConnectedFault(self.compressor_handle)).ok() != 0
}
pub fn clear_all_pcm_sticky_faults(&self) {
hal_call!(HAL_ClearAllPCMStickyFaults(self.module)).ok();
}
}