use super::sensor_util;
use std::{thread, time};
use wpilib_sys::usage::{instances, resource_types};
use wpilib_sys::*;
#[derive(Debug)]
pub struct AnalogInput {
channel: i32,
port: HAL_AnalogInputHandle,
accumulator_offset: i64,
}
impl AnalogInput {
#[allow(clippy::new_ret_no_self)]
pub fn new(channel: i32) -> HalResult<AnalogInput> {
if !sensor_util::check_analog_input_channel(channel) {
return Err(HalError(0));
}
let port = hal_call!(HAL_InitializeAnalogInputPort(HAL_GetPort(channel)))?;
report_usage(resource_types::AnalogChannel, channel as instances::Type);
Ok(AnalogInput {
channel,
port,
accumulator_offset: 0,
})
}
pub fn value(&self) -> HalResult<i32> {
hal_call!(HAL_GetAnalogValue(self.port))
}
pub fn average_value(&self) -> HalResult<i32> {
hal_call!(HAL_GetAnalogAverageValue(self.port))
}
pub fn voltage(&self) -> HalResult<f64> {
hal_call!(HAL_GetAnalogVoltage(self.port))
}
pub fn average_voltage(&self) -> HalResult<f64> {
hal_call!(HAL_GetAnalogAverageVoltage(self.port))
}
pub fn channel(&self) -> i32 {
self.channel
}
pub fn set_average_bits(&mut self, bits: i32) -> HalResult<()> {
hal_call!(HAL_SetAnalogAverageBits(self.port, bits))
}
pub fn average_bits(&self) -> HalResult<i32> {
hal_call!(HAL_GetAnalogAverageBits(self.port))
}
pub fn set_oversample_bits(&mut self, bits: i32) -> HalResult<()> {
hal_call!(HAL_SetAnalogOversampleBits(self.port, bits))
}
pub fn oversample_bits(&self) -> HalResult<i32> {
hal_call!(HAL_GetAnalogOversampleBits(self.port))
}
pub fn lsb_weight(&self) -> HalResult<i32> {
hal_call!(HAL_GetAnalogLSBWeight(self.port))
}
pub fn offset(&self) -> HalResult<i32> {
hal_call!(HAL_GetAnalogOffset(self.port))
}
pub fn is_accumulator_channel(&self) -> HalResult<bool> {
Ok(hal_call!(HAL_IsAccumulatorChannel(self.port))? != 0)
}
pub fn init_accumulator(&mut self) -> HalResult<()> {
hal_call!(HAL_InitAccumulator(self.port))
}
pub fn set_accumulator_offset(&mut self, value: i64) {
self.accumulator_offset = value;
}
pub fn reset_accumulator(&mut self) -> HalResult<()> {
hal_call!(HAL_ResetAccumulator(self.port))?;
let sample_time = 1f64 / AnalogInput::sample_rate()?;
let over_samples = 1 << self.oversample_bits()?;
let average_samples = 1 << self.average_bits()?;
thread::sleep(time::Duration::from_micros(
1000 * 1000 * over_samples * average_samples * sample_time as u64,
));
Ok(())
}
pub fn set_accumulator_center(&mut self, center: i32) -> HalResult<()> {
hal_call!(HAL_SetAccumulatorCenter(self.port, center))
}
pub fn set_accumulator_deadband(&self, deadband: i32) -> HalResult<()> {
hal_call!(HAL_SetAccumulatorDeadband(self.port, deadband))
}
pub fn accumulator_value(&self) -> HalResult<i64> {
hal_call!(HAL_GetAccumulatorValue(self.port))
}
pub fn accumulator_count(&self) -> HalResult<i64> {
hal_call!(HAL_GetAccumulatorCount(self.port))
}
pub fn accumulator_output(&self) -> HalResult<(i64, i64)> {
let value: i64 = 0;
let count: i64 = 0;
hal_call!(HAL_GetAccumulatorOutput(
self.port,
value as *mut i64,
count as *mut i64
))?;
Ok((value, count))
}
pub fn set_sample_rate(samples_per_second: f64) -> HalResult<()> {
hal_call!(HAL_SetAnalogSampleRate(samples_per_second))
}
pub fn sample_rate() -> HalResult<f64> {
hal_call!(HAL_GetAnalogSampleRate())
}
}
impl Drop for AnalogInput {
fn drop(&mut self) {
unsafe {
HAL_FreeAnalogInputPort(self.port);
}
}
}