1use crate::calibration::{self, Calibration, CalibrationData, Point};
2
3pub const DEFAULT_FREQUENCY: f32 = 50.0;
4pub const MIN_FREQUENCY: f32 = 10.0;
5pub const MAX_FREQUENCY: f32 = 350.0;
6const MIN_VALID_PULSE: f32 = 1.0;
7
8pub struct ServoState<C> {
10 servo_value: f32,
12 last_enabled_pulse: Option<f32>,
14 enabled: bool,
16 calibration: Calibration<C>,
18}
19
20impl<C> ServoState<C>
21where
22 C: Default + Clone + CalibrationData,
23{
24 pub fn new() -> Option<Self> {
26 Some(Self {
27 servo_value: 0.0,
28 last_enabled_pulse: None,
29 enabled: false,
30 calibration: Calibration::new()?,
31 })
32 }
33}
34
35impl<C> ServoState<C>
36where
37 C: CalibrationData,
38 for<'a> <C as CalibrationData>::Iterator<'a>: Iterator<Item = (Point, Point)>,
39{
40 pub fn with_calibration(calibration: Calibration<C>) -> Self {
42 Self {
43 servo_value: 0.0,
44 last_enabled_pulse: None,
45 enabled: false,
46 calibration,
47 }
48 }
49
50 pub fn enable_with_return(&mut self) -> f32 {
52 if let Some(pulse) = self.last_enabled_pulse {
53 self.enabled = true;
54 pulse
55 } else {
56 self.go_to_mid_with_return()
57 }
58 }
59
60 #[inline]
62 fn go_to_mid_with_return(&mut self) -> f32 {
63 self.set_value_with_return(self.calibration.mid_value())
64 }
65
66 #[inline]
69 fn inner_enable_with_return(&mut self) -> Option<f32> {
70 self.enabled = true;
71 self.last_enabled_pulse
72 }
73
74 pub fn set_value_with_return(&mut self, value: f32) -> f32 {
76 let point = self.calibration.value_to_pulse(value);
77 self.last_enabled_pulse = Some(point.pulse);
78 self.servo_value = point.value;
79 self.enabled = true;
80 point.pulse
81 }
82
83 #[inline]
85 pub fn disable(&mut self) {
86 self.enabled = false;
87 }
88
89 #[inline]
91 pub fn enabled(&self) -> bool {
92 self.enabled
93 }
94
95 pub fn pulse_to_level(pulse: f32, resolution: u32, frequency: f32) -> u32 {
97 if pulse >= MIN_VALID_PULSE {
98 ((pulse * resolution as f32 * frequency) as u64 / 1_000_000) as u32
99 } else {
100 0
101 }
102 }
103
104 #[inline]
106 pub fn pulse(&self) -> Option<f32> {
107 self.last_enabled_pulse
108 }
109
110 pub fn set_pulse_with_return(&mut self, pulse: f32) -> Option<f32> {
113 if pulse >= MIN_VALID_PULSE {
114 if let Some(point) = self.calibration.pulse_to_value(pulse) {
115 self.servo_value = point.value;
116 self.last_enabled_pulse = Some(point.pulse);
117 return self.inner_enable_with_return();
118 }
119 }
120 self.disable();
121 None
122 }
123
124 #[inline]
126 pub fn value(&self) -> f32 {
127 self.servo_value
128 }
129
130 #[inline]
132 pub(crate) fn min_value(&self) -> f32 {
133 self.calibration.first().value
134 }
135
136 #[inline]
138 pub(crate) fn mid_value(&self) -> f32 {
139 self.calibration.mid_value()
140 }
141
142 #[inline]
144 pub(crate) fn max_value(&self) -> f32 {
145 self.calibration.last().value
146 }
147
148 #[inline]
150 pub fn to_min_with_return(&mut self) -> f32 {
151 self.set_value_with_return(self.min_value())
152 }
153
154 #[inline]
156 pub fn to_mid_with_return(&mut self) -> f32 {
157 self.set_value_with_return(self.mid_value())
158 }
159
160 #[inline]
162 pub fn to_max_with_return(&mut self) -> f32 {
163 self.set_value_with_return(self.max_value())
164 }
165
166 pub fn to_percent_with_return(&mut self, percent: f32) -> f32 {
170 let value = calibration::map_float(percent, 0.0, 100.0, self.min_value(), self.max_value());
171 self.set_value_with_return(value)
172 }
173
174 #[inline]
176 pub fn calibration(&self) -> &Calibration<C> {
177 &self.calibration
178 }
179
180 #[inline]
182 pub fn calibration_mut(&mut self) -> &mut Calibration<C> {
183 &mut self.calibration
184 }
185}