use sensor_util;
use wpilib_sys::usage::{instances, resource_types};
use wpilib_sys::*;
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub enum PeriodMultiplier {
Multiplier1x = 0,
Multiplier2x = 1,
Multiplier4x = 3,
}
#[derive(Debug)]
pub struct PWM {
channel: i32,
handle: HAL_DigitalHandle,
}
impl PWM {
#[allow(clippy::new_ret_no_self)]
pub fn new(channel: i32) -> HalResult<Self> {
if !sensor_util::check_pwm_channel(channel) {
return Err(HalError(0));
}
let handle = hal_call!(HAL_InitializePWMPort(HAL_GetPort(channel)))?;
hal_call!(HAL_SetPWMDisabled(handle))?;
hal_call!(HAL_SetPWMEliminateDeadband(handle, false as i32))?;
report_usage(resource_types::PWM, channel as instances::Type);
Ok(PWM { channel, handle })
}
pub fn set_raw(&mut self, value: i32) -> HalResult<()> {
hal_call!(HAL_SetPWMRaw(self.handle, value))
}
pub fn raw(&self) -> HalResult<i32> {
hal_call!(HAL_GetPWMRaw(self.handle))
}
pub fn set_position(&mut self, pos: f64) -> HalResult<()> {
hal_call!(HAL_SetPWMPosition(self.handle, pos))
}
pub fn position(&self) -> HalResult<f64> {
hal_call!(HAL_GetPWMPosition(self.handle))
}
pub fn set_speed(&mut self, speed: f64) -> HalResult<()> {
hal_call!(HAL_SetPWMSpeed(self.handle, speed))
}
pub fn speed(&self) -> HalResult<f64> {
hal_call!(HAL_GetPWMSpeed(self.handle))
}
pub fn set_disabled(&mut self) -> HalResult<()> {
hal_call!(HAL_SetPWMDisabled(self.handle))
}
pub fn set_period_multiplier(&mut self, mult: PeriodMultiplier) -> HalResult<()> {
hal_call!(HAL_SetPWMPeriodScale(self.handle, mult as i32))
}
pub fn set_zero_latch(&mut self) -> HalResult<()> {
hal_call!(HAL_LatchPWMZero(self.handle))
}
pub fn enable_deadband_elimination(&mut self, eliminate_deadband: bool) -> HalResult<()> {
hal_call!(HAL_SetPWMEliminateDeadband(
self.handle,
eliminate_deadband as i32
))
}
pub fn set_bounds(
&mut self,
max: f64,
deadband_max: f64,
center: f64,
deadband_min: f64,
min: f64,
) -> HalResult<()> {
hal_call!(HAL_SetPWMConfig(
self.handle,
max,
deadband_max,
center,
deadband_min,
min
))
}
pub fn set_raw_bounds(
&mut self,
max: i32,
deadband_max: i32,
center: i32,
deadband_min: i32,
min: i32,
) -> HalResult<()> {
hal_call!(HAL_SetPWMConfigRaw(
self.handle,
max,
deadband_max,
center,
deadband_min,
min
))
}
pub fn raw_bounds(
&self,
max: &mut i32,
deadband_max: &mut i32,
center: &mut i32,
deadband_min: &mut i32,
min: &mut i32,
) -> HalResult<()> {
hal_call!(HAL_GetPWMConfigRaw(
self.handle,
max,
deadband_max,
center,
deadband_min,
min
))
}
pub fn channel(&self) -> i32 {
self.channel
}
}
impl Drop for PWM {
fn drop(&mut self) {
hal_call!(HAL_SetPWMDisabled(self.handle)).ok();
hal_call!(HAL_FreePWMPort(self.handle)).ok();
}
}
#[derive(Debug)]
pub struct PwmSpeedController {
pwm: PWM,
inverted: bool,
}
impl PwmSpeedController {
#[allow(clippy::new_ret_no_self)]
pub fn new(channel: i32) -> HalResult<Self> {
Ok(PwmSpeedController {
pwm: PWM::new(channel)?,
inverted: false,
})
}
pub fn new_talon(channel: i32) -> HalResult<PwmSpeedController> {
let mut pwm = PWM::new(channel)?;
pwm.set_bounds(2.004, 1.52, 1.5, 1.48, 0.997)?;
pwm.set_period_multiplier(PeriodMultiplier::Multiplier1x)?;
pwm.set_speed(0.0)?;
pwm.set_zero_latch()?;
report_usage(resource_types::PWMTalonSRX, channel as instances::Type);
Ok(PwmSpeedController {
pwm,
inverted: false,
})
}
pub fn set(&mut self, speed: f64) -> HalResult<()> {
self.pwm
.set_speed(if self.inverted { -speed } else { speed })
}
pub fn get(&self) -> HalResult<f64> {
if self.inverted {
Ok(-self.pwm.speed()?)
} else {
self.pwm.speed()
}
}
pub fn set_inverted(&mut self, inverted: bool) {
self.inverted = inverted;
}
pub fn inverted(&self) -> bool {
self.inverted
}
pub fn disable(&mut self) -> HalResult<()> {
self.pwm.set_disabled()
}
}