use ::error::*;
use raw::*;
use std::ffi::CString;
use std::mem;
use std::ops::Index;
use time::Duration;
#[allow(missing_docs)] pub type RawControlWord = HAL_ControlWord;
#[allow(missing_docs)] pub type RawJoystickAxes = HAL_JoystickAxes;
#[allow(missing_docs)] pub type RawJoystickPovs = HAL_JoystickPOVs;
#[allow(missing_docs)] pub type RawJoystickButtons = HAL_JoystickButtons;
#[allow(missing_docs)] pub type RawJoystickDescriptor = HAL_JoystickDescriptor;
pub const MAX_JOYSTICK_AXES: usize = 12;
pub const MAX_JOYSTICK_POVS: usize = 12;
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct ControlWord {
pub enabled: bool,
pub autonomous: bool,
pub test: bool,
pub stopped: bool,
pub fms_attached: bool,
pub ds_attached: bool,
}
impl ControlWord {
#[inline]
pub fn all_off() -> ControlWord {
ControlWord {
enabled: false,
autonomous: false,
test: false,
stopped: false,
fms_attached: false,
ds_attached: false,
}
}
}
const ENABLED_OFFSET: i32 = 0;
const AUTONOMOUS_OFFSET: i32 = 1;
const TEST_OFFSET: i32 = 2;
const STOPPED_OFFSET: i32 = 3;
const FMS_ATTACHED_OFFSET: i32 = 4;
const DS_ATTACHED_OFFSET: i32 = 5;
fn extract_field(word: RawControlWord, offset: i32) -> u32 {
(word._bitfield_1 & (2 << offset - 1)) >> offset
}
impl From<RawControlWord> for ControlWord {
#[inline]
fn from(raw: RawControlWord) -> ControlWord {
ControlWord {
enabled: extract_field(raw, ENABLED_OFFSET) != 0,
autonomous: extract_field(raw, AUTONOMOUS_OFFSET) != 0,
test: extract_field(raw, TEST_OFFSET) != 0,
stopped: extract_field(raw, STOPPED_OFFSET) != 0,
fms_attached: extract_field(raw, FMS_ATTACHED_OFFSET) != 0,
ds_attached: extract_field(raw, DS_ATTACHED_OFFSET) != 0,
}
}
}
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct JoystickAxes {
axes: [f32; MAX_JOYSTICK_AXES],
count: i16,
}
impl Index<usize> for JoystickAxes {
type Output = f32;
fn index(&self, index: usize) -> &Self::Output {
&self.axes[index]
}
}
impl From<RawJoystickAxes> for JoystickAxes {
fn from(raw_axes: RawJoystickAxes) -> JoystickAxes {
JoystickAxes {
axes: raw_axes.axes,
count: raw_axes.count,
}
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct JoystickPovs {
povs: [i16; MAX_JOYSTICK_POVS],
count: i16,
}
impl Index<usize> for JoystickPovs {
type Output = i16;
fn index(&self, index: usize) -> &Self::Output {
&self.povs[index]
}
}
impl From<RawJoystickPovs> for JoystickPovs {
fn from(raw_povs: RawJoystickPovs) -> JoystickPovs {
JoystickPovs {
povs: raw_povs.povs,
count: raw_povs.count,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct JoystickButtons {
buttons_down: [bool; 32],
pub count: u16,
}
impl Index<usize> for JoystickButtons {
type Output = bool;
fn index(&self, index: usize) -> &Self::Output {
&self.buttons_down[index]
}
}
impl From<RawJoystickButtons> for JoystickButtons {
fn from(raw_buttons: RawJoystickButtons) -> JoystickButtons {
let mut buttons = JoystickButtons {
buttons_down: [false; 32],
count: 0,
};
for i in 0 .. 32 {
buttons.buttons_down[i] = raw_buttons.buttons & (1 << i) == 1;
buttons.count += 1;
}
buttons
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct JoystickDescriptor {
name: String,
is_xbox: bool,
stick_type: JoystickType,
button_count: u8,
axis_count: u8,
axis_types: [u8; MAX_JOYSTICK_AXES],
pov_count: u8,
}
impl From<RawJoystickDescriptor> for JoystickDescriptor {
fn from(raw_descriptor: RawJoystickDescriptor) -> JoystickDescriptor {
JoystickDescriptor {
name: String::from_utf8_lossy(raw_descriptor.name
.iter()
.map(|x| *x as u8)
.collect::<Vec<u8>>()
.as_slice())
.escape_default(),
is_xbox: raw_descriptor.isXbox != 0,
stick_type: JoystickType::from(raw_descriptor.type_ as i32),
button_count: raw_descriptor.buttonCount,
axis_types: raw_descriptor.axisTypes,
axis_count: raw_descriptor.axisCount,
pov_count: raw_descriptor.povCount,
}
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum AllianceStation {
Red(u8),
Blue(u8),
Invalid,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum JoystickType {
Unknown(i32),
}
impl From<i32> for JoystickType {
fn from(joystick_type: i32) -> JoystickType {
match joystick_type {
k => JoystickType::Unknown(k),
}
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum UserProgramMode {
Starting,
Disabled,
Autonomous,
TeleOperated,
Test,
}
pub fn set_error_data(errors: &str, errors_length: i32, wait_ms: i32) -> HalResult<()> {
unsafe { hal_call![ ret HAL_SetErrorData(CString::new(errors).map_err(HalError::from)?.as_ptr(), errors_length, wait_ms) ] }
}
pub fn get_joystick_descriptor(joystick_num: i32) -> HalResult<JoystickDescriptor> {
let mut descriptor = unsafe { mem::zeroed() };
unsafe { hal_call!(ret HAL_GetJoystickDescriptor(joystick_num, &mut descriptor as *mut RawJoystickDescriptor))?; }
Ok(JoystickDescriptor::from(descriptor))
}
pub fn get_joystick_axes(joystick_num: i32) -> HalResult<JoystickAxes> {
let mut raw_axes = unsafe { mem::zeroed() };
unsafe { hal_call!(ret HAL_GetJoystickAxes(joystick_num, &mut raw_axes as *mut RawJoystickAxes))?; }
Ok(JoystickAxes::from(raw_axes))
}
pub fn get_joystick_povs(joystick_num: i32) -> HalResult<JoystickPovs> {
let mut raw_povs = unsafe { mem::zeroed() };
unsafe { hal_call!(ret HAL_GetJoystickPOVs(joystick_num, &mut raw_povs as *mut RawJoystickPovs))?; }
Ok(JoystickPovs::from(raw_povs))
}
pub fn get_joystick_buttons(joystick_num: i32) -> HalResult<JoystickButtons> {
let mut raw_buttons: RawJoystickButtons = unsafe { mem::zeroed() };
unsafe { hal_call!(ret HAL_GetJoystickButtons(joystick_num, &mut raw_buttons as *mut RawJoystickButtons))?; }
Ok(JoystickButtons::from(raw_buttons))
}
pub fn get_joystick_is_xbox(joystick_num: i32) -> HalResult<bool> {
Ok(get_joystick_descriptor(joystick_num)?.is_xbox)
}
pub fn get_joystick_type(joystick_num: i32) -> HalResult<JoystickType> {
Ok(JoystickType::from(get_joystick_descriptor(joystick_num)?.stick_type))
}
pub fn get_joystick_name(joystick_num: i32) -> HalResult<String> {
Ok(get_joystick_descriptor(joystick_num)?.name)
}
pub fn get_joystick_axis_type(joystick_num: i32, axis: i32) -> HalResult<JoystickType> {
if axis >= 0 {
Ok(JoystickType::from(get_joystick_descriptor(joystick_num)?.axis_types[axis as usize] as
i32))
} else {
Err(HalError::Hal(FfiError::ParameterOutOfRange))
}
}
pub fn set_joystick_outputs(joystick_num: i32, outputs: i64, left_rumble: i32, right_rumble: i32)
-> HalResult<()> {
unsafe { hal_call!(ret HAL_SetJoystickOutputs(joystick_num, outputs, left_rumble, right_rumble)) }
}
pub fn observe_user_program(mode: UserProgramMode) {
match mode {
UserProgramMode::Starting => self::observe_user_program_starting(),
UserProgramMode::Disabled => self::observe_user_program_disabled(),
UserProgramMode::Autonomous => self::observe_user_program_autonomous(),
UserProgramMode::TeleOperated => self::observe_user_program_teleop(),
UserProgramMode::Test => self::observe_user_program_test(),
}
}
pub fn initialize_driver_station() {
unsafe { HAL_InitializeDriverStation() };
}
pub fn get_control_word() -> HalResult<ControlWord> {
let mut control_word: RawControlWord = unsafe { mem::zeroed() };
unsafe { hal_call!(ret HAL_GetControlWord(&mut control_word as *mut RawControlWord))?; }
Ok(ControlWord::from(control_word))
}
pub fn wait_for_ds_data() {
unsafe { HAL_WaitForDSData() };
}
pub fn send_error(is_error: bool, error_code: i32, is_lv_code: bool, details: &str,
location: &str, call_stack: &str, print_message: bool)
-> Result<(), HalError> {
let details_raw = CString::new(details).map_err(HalError::from)?;
let location_raw = CString::new(location).map_err(HalError::from)?;
let call_stack_raw = CString::new(call_stack).map_err(HalError::from)?;
unsafe { hal_call!(ret HAL_SendError(is_error as HAL_Bool, error_code, is_lv_code as HAL_Bool,
details_raw.as_ptr(), location_raw.as_ptr(), call_stack_raw.as_ptr(),
print_message as HAL_Bool)) }
}
pub fn get_alliance_station() -> HalResult<AllianceStation> {
let station_id = unsafe { hal_call!(ptr HAL_GetAllianceStation())? };
use raw::HAL_AllianceStationID;
Ok(match station_id {
HAL_AllianceStationID::HAL_AllianceStationID_kRed1 => AllianceStation::Red(1),
HAL_AllianceStationID::HAL_AllianceStationID_kRed2 => AllianceStation::Red(2),
HAL_AllianceStationID::HAL_AllianceStationID_kRed3 => AllianceStation::Red(3),
HAL_AllianceStationID::HAL_AllianceStationID_kBlue1 => AllianceStation::Blue(1),
HAL_AllianceStationID::HAL_AllianceStationID_kBlue2 => AllianceStation::Blue(2),
HAL_AllianceStationID::HAL_AllianceStationID_kBlue3 => AllianceStation::Blue(3),
})
}
pub fn get_match_time_approx() -> HalResult<Duration> {
let time = unsafe { hal_call![ ptr HAL_GetMatchTime() ]? };
let time_ns = (time * 1_000_000_000f64) as i64;
Ok(Duration::nanoseconds(time_ns))
}
pub fn observe_user_program_starting() {
unsafe { HAL_ObserveUserProgramStarting() }
}
pub fn observe_user_program_disabled() {
unsafe { HAL_ObserveUserProgramDisabled() }
}
pub fn observe_user_program_autonomous() {
unsafe { HAL_ObserveUserProgramAutonomous() }
}
pub fn observe_user_program_teleop() {
unsafe { HAL_ObserveUserProgramTeleop() }
}
pub fn observe_user_program_test() {
unsafe { HAL_ObserveUserProgramTest() }
}