1use alloc::string::ToString;
2
3use crate::{
4 bindings,
5 error::{get_errno, Error},
6 rtos::DataSource,
7};
8
9pub struct AdiGyro {
11 port: bindings::ext_adi_gyro_t,
12}
13impl AdiGyro {
14 pub unsafe fn new(
24 adi_port: u8,
25 multiplier: f64,
26 extender_port: u8,
27 ) -> Result<Self, AdiGyroError> {
28 match bindings::ext_adi_gyro_init(extender_port, adi_port, multiplier) {
29 bindings::PROS_ERR_ => Err(AdiGyroError::from_errno()),
30 x => Ok(Self { port: x }),
31 }
32 }
33
34 pub fn reset(&mut self) -> Result<(), AdiGyroError> {
36 match unsafe { bindings::ext_adi_gyro_reset(self.port) } {
37 bindings::PROS_ERR_ => Err(AdiGyroError::from_errno()),
38 _ => Ok(()),
39 }
40 }
41
42 pub fn get(&self) -> Result<f64, AdiGyroError> {
48 let out = unsafe { bindings::ext_adi_gyro_get(self.port) };
49 if out == bindings::PROS_ERR_F_ {
50 Err(AdiGyroError::from_errno())
51 } else {
52 Ok(out)
53 }
54 }
55}
56
57impl DataSource for AdiGyro {
58 type Data = f64;
59
60 type Error = AdiGyroError;
61
62 fn read(&self) -> Result<Self::Data, Self::Error> {
63 self.get()
64 }
65}
66
67impl Drop for AdiGyro {
68 fn drop(&mut self) {
69 if let bindings::PROS_ERR_ = unsafe { bindings::ext_adi_gyro_shutdown(self.port) } {
70 panic!(
71 "failed to shutdown ADI gyro: {:?}",
72 AdiGyroError::from_errno()
73 );
74 }
75 }
76}
77
78#[derive(Debug)]
80pub enum AdiGyroError {
81 PortOutOfRange,
83 PortNotAdiEncoder,
85 Unknown(i32),
87}
88impl AdiGyroError {
89 fn from_errno() -> Self {
90 match get_errno() {
91 libc::ENXIO => Self::PortOutOfRange,
92 libc::EADDRINUSE => Self::PortNotAdiEncoder,
93 x => Self::Unknown(x),
94 }
95 }
96}
97impl From<AdiGyroError> for Error {
98 fn from(err: AdiGyroError) -> Self {
99 match err {
100 AdiGyroError::PortOutOfRange => Error::Custom("port out of range".to_string()),
101 AdiGyroError::PortNotAdiEncoder => Error::Custom("port not an adi gyro".to_string()),
102 AdiGyroError::Unknown(n) => Error::System(n),
103 }
104 }
105}