1use crate::{
4 adi::AdiExpander,
5 bindings,
6 distance::DistanceSensor,
7 error::Error,
8 imu::InertialSensor,
9 motor::{EncoderUnits, Gearset, Motor, MotorError},
10 rotation::{RotationSensor, RotationSensorError},
11 serial::Serial,
12};
13use core::convert::{TryFrom, TryInto};
14
15pub struct SmartPort {
17 port: u8,
18}
19
20impl SmartPort {
21 pub unsafe fn new(port: u8) -> Self {
29 assert!(
30 (1..22).contains(&port),
31 "Cannot construct a smart port on port {}",
32 port
33 );
34 Self { port }
35 }
36
37 #[inline]
38 pub fn plugged_type(&self) -> DeviceType {
40 unsafe { smart_port_type(self.port) }
41 }
42
43 pub fn into_motor(
45 self,
46 gearset: Gearset,
47 encoder_units: EncoderUnits,
48 reverse: bool,
49 ) -> Result<Motor, MotorError> {
50 (self, gearset, encoder_units, reverse).try_into()
51 }
52
53 pub fn into_serial(self, baudrate: i32) -> Result<Serial, Error> {
55 (self, baudrate).try_into()
56 }
57
58 pub fn into_expander(self) -> AdiExpander {
60 self.into()
61 }
62
63 pub fn into_distance(self) -> DistanceSensor {
66 self.into()
67 }
68
69 pub fn into_imu(self) -> InertialSensor {
72 self.into()
73 }
74
75 #[inline]
78 pub fn into_rotation(self, reversed: bool) -> Result<RotationSensor, RotationSensorError> {
79 (self, reversed).try_into()
80 }
81}
82
83impl TryFrom<(SmartPort, Gearset, EncoderUnits, bool)> for Motor {
84 type Error = MotorError;
85
86 fn try_from(
87 (port, gearset, encoder_units, reverse): (SmartPort, Gearset, EncoderUnits, bool),
88 ) -> Result<Self, Self::Error> {
89 unsafe { Self::new(port.port, gearset, encoder_units, reverse) }
90 }
91}
92
93impl TryFrom<(SmartPort, i32)> for Serial {
94 type Error = Error;
95
96 fn try_from((port, baudrate): (SmartPort, i32)) -> Result<Self, Self::Error> {
97 unsafe { Self::new(port.port, baudrate) }
98 }
99}
100
101impl From<SmartPort> for AdiExpander {
102 fn from(port: SmartPort) -> Self {
103 unsafe { AdiExpander::new(port.port) }
104 }
105}
106
107impl From<SmartPort> for DistanceSensor {
108 fn from(port: SmartPort) -> Self {
109 unsafe { DistanceSensor::new(port.port) }
110 }
111}
112impl From<SmartPort> for InertialSensor {
113 fn from(port: SmartPort) -> Self {
114 unsafe { InertialSensor::new(port.port) }
115 }
116}
117
118impl TryFrom<(SmartPort, bool)> for RotationSensor {
119 type Error = RotationSensorError;
120
121 #[inline]
122 fn try_from((port, reversed): (SmartPort, bool)) -> Result<Self, Self::Error> {
123 unsafe { RotationSensor::new(port.port, reversed) }
124 }
125}
126
127#[derive(Clone, Copy, Debug, PartialEq, Eq)]
129pub enum DeviceType {
130 None,
132
133 Motor,
135
136 Rotation,
138
139 Imu,
141
142 Distance,
144
145 Radio,
147
148 Vision,
150
151 Adi,
153
154 Optical,
156
157 Serial,
159
160 Undefined,
162
163 Unknown(u32),
165}
166
167impl From<bindings::v5_device_e_t> for DeviceType {
168 fn from(t: bindings::v5_device_e_t) -> Self {
169 match t {
170 bindings::v5_device_e_E_DEVICE_NONE => Self::None,
171 bindings::v5_device_e_E_DEVICE_MOTOR => Self::Motor,
172 bindings::v5_device_e_E_DEVICE_ROTATION => Self::Rotation,
173 bindings::v5_device_e_E_DEVICE_IMU => Self::Imu,
174 bindings::v5_device_e_E_DEVICE_DISTANCE => Self::Distance,
175 bindings::v5_device_e_E_DEVICE_RADIO => Self::Radio,
176 bindings::v5_device_e_E_DEVICE_VISION => Self::Vision,
177 bindings::v5_device_e_E_DEVICE_ADI => Self::Adi,
178 bindings::v5_device_e_E_DEVICE_OPTICAL => Self::Optical,
179 bindings::v5_device_e_E_DEVICE_GENERIC => Self::Serial,
180 bindings::v5_device_e_E_DEVICE_UNDEFINED => Self::Undefined,
181 _ => Self::Unknown(t),
182 }
183 }
184}
185
186pub unsafe fn smart_port_type(port: u8) -> DeviceType {
192 bindings::registry_get_plugged_type(port - 1).into()
193}