1use super::DshotSpeed;
2
3#[derive(Copy, Clone, Debug, PartialEq)]
4pub struct EscDshot {
5 protocol: DshotSpeed,
6 cpu_frequency: u32,
7 data_high_pulse_width: u16,
8 data_low_pulse_width: u16,
9 wrap_cycle_count: u16,
10}
11
12impl Default for EscDshot {
13 fn default() -> Self {
14 Self::new(DshotSpeed::Dshot150)
15 }
16}
17
18impl EscDshot {
19 pub const DEFAULT_CPU_FREQUENCY: u32 = 150_000_000;
20 const DSHOT_BIT_COUNT: usize = 16;
21 const DMA_BUFFER_SIZE: usize = Self::DSHOT_BIT_COUNT + 1;
22
23 const DSHOT150_T0H: u32 = 2500;
24 const DSHOT150_T1H: u32 = 5000;
25 const DSHOT150_T: u32 = 6680;
26
27 #[must_use]
28 pub const fn new(protocol: DshotSpeed) -> Self {
29 let mut this = Self {
30 protocol,
31 cpu_frequency: Self::DEFAULT_CPU_FREQUENCY,
32
33 data_high_pulse_width: 0,
34 data_low_pulse_width: 0,
35 wrap_cycle_count: 0,
36 };
37 this.set_protocol(protocol);
38 this
39 }
40
41 #[must_use]
43 pub const fn with_cpu_frequency(mut self, cpu_frequency: u32) -> Self {
44 self.set_cpu_frequency(cpu_frequency);
45 self
46 }
47}
48
49#[allow(unused)]
50impl EscDshot {
51 #[must_use]
52 pub const fn nano_seconds_to_cycles(self, nano_seconds: u32) -> u16 {
53 const K: u64 = 128;
55 let d = K * 1_000_000_000 / (self.cpu_frequency as u64);
56 #[allow(clippy::cast_possible_truncation)]
57 {
58 ((nano_seconds as u64) * K / d) as u16
59 }
60 }
61
62 pub const fn set_cpu_frequency(&mut self, cpu_frequency: u32) {
63 self.cpu_frequency = cpu_frequency;
64 self.set_protocol(self.protocol);
65 }
66
67 pub const fn set_protocol(&mut self, protocol: DshotSpeed) {
68 self.protocol = protocol;
69
70 self.data_low_pulse_width = self.nano_seconds_to_cycles(Self::DSHOT150_T0H); self.data_high_pulse_width = self.nano_seconds_to_cycles(Self::DSHOT150_T1H); self.wrap_cycle_count = self.nano_seconds_to_cycles(Self::DSHOT150_T); match protocol {
77 DshotSpeed::Dshot150 => {
78 _ = protocol;
79 }
80 DshotSpeed::Dshot300 => {
81 self.data_low_pulse_width /= 2;
82 self.data_high_pulse_width /= 2;
83 self.wrap_cycle_count /= 2;
84 }
85 DshotSpeed::Dshot600 => {
86 self.data_low_pulse_width /= 4;
87 self.data_high_pulse_width /= 4;
88 self.wrap_cycle_count /= 4;
89 }
90 DshotSpeed::Dshot1200 => {
91 self.data_low_pulse_width /= 8;
92 self.data_high_pulse_width /= 8;
93 self.wrap_cycle_count /= 8;
94 }
95 }
96 }
97
98 #[must_use]
102 pub fn duty_cycles_u16(&self, frame: u16) -> [u16; Self::DMA_BUFFER_SIZE] {
103 let mut ret = [0u16; Self::DMA_BUFFER_SIZE];
104
105 let mut mask_bit = 1 << (Self::DSHOT_BIT_COUNT - 1);
106 for item in &mut ret {
107 *item = if frame & mask_bit == 0 { self.data_high_pulse_width } else { self.data_low_pulse_width };
108 mask_bit >>= 1;
109 }
110
111 ret[Self::DMA_BUFFER_SIZE - 1] = 0;
113 ret
114 }
115
116 #[must_use]
120 pub fn duty_cycles_u32(&self, frame: u16, use_high_order_bits: bool) -> [u32; Self::DMA_BUFFER_SIZE] {
121 let mut ret = [0u32; Self::DMA_BUFFER_SIZE];
122
123 let mut mask_bit = 1 << (Self::DSHOT_BIT_COUNT - 1);
124 if use_high_order_bits {
125 for item in &mut ret {
126 let byte = if frame & mask_bit == 0 {
127 u32::from(self.data_high_pulse_width)
128 } else {
129 u32::from(self.data_low_pulse_width)
130 };
131 *item = byte << 16;
132 mask_bit >>= 1;
133 }
134 } else {
135 for item in &mut ret {
136 *item = if frame & mask_bit == 0 {
137 u32::from(self.data_high_pulse_width)
138 } else {
139 u32::from(self.data_low_pulse_width)
140 };
141 mask_bit >>= 1;
142 }
143 }
144
145 ret[Self::DMA_BUFFER_SIZE - 1] = 0;
147 ret
148 }
149}
150
151#[cfg(test)]
152mod test_traits {
153 use super::*;
154
155 fn is_full<T: Sized + Send + Sync + Unpin + Copy + Clone + Default + PartialEq>() {}
156
157 #[test]
158 fn normal_types() {
159 is_full::<EscDshot>();
160 }
161}
162
163#[cfg(test)]
164mod test {
165
166 use super::*;
167
168 #[test]
169 fn nano_seconds_to_cycles() {
170 let esc = EscDshot::new(DshotSpeed::Dshot150);
171 assert_eq!(126, esc.nano_seconds_to_cycles(840));
172 assert_eq!(187, esc.nano_seconds_to_cycles(1250));
173 assert_eq!(313, esc.nano_seconds_to_cycles(2090));
174 assert_eq!(375, esc.nano_seconds_to_cycles(2500));
175 assert_eq!(750, esc.nano_seconds_to_cycles(5000));
176 assert_eq!(1125, esc.nano_seconds_to_cycles(7500));
177
178 assert_eq!(350, esc.nano_seconds_to_cycles(2333));
179 assert_eq!(700, esc.nano_seconds_to_cycles(4666));
180 assert_eq!(1000, esc.nano_seconds_to_cycles(6666));
181 }
182 #[test]
183 fn pulse_widths() {
184 let esc150 = EscDshot::new(DshotSpeed::Dshot150);
185 assert_eq!(750, esc150.data_high_pulse_width);
186 assert_eq!(375, esc150.data_low_pulse_width);
187
188 let esc300 = EscDshot::new(DshotSpeed::Dshot300);
189 assert_eq!(375, esc300.data_high_pulse_width);
190 assert_eq!(187, esc300.data_low_pulse_width);
191
192 let esc600 = EscDshot::new(DshotSpeed::Dshot600);
193 assert_eq!(187, esc600.data_high_pulse_width);
194 assert_eq!(93, esc600.data_low_pulse_width);
195 }
196}