proto_lab/device/
wireless_modem.rs1use std::{
2 collections::VecDeque,
3 sync::{Arc, Mutex},
4};
5
6use super::IODriverSimulator;
7
8enum AntennaState {
9 Transmit(u8),
10 Receive(u8),
11 Idle,
12}
13
14enum TickState {
43 InTick,
44 OffTick,
45}
46
47struct InternalState {
48 tick_state: TickState,
49 from_antenna_buffer: VecDeque<u8>,
50 to_antenna_buffer: VecDeque<u8>,
51 antennta_state: AntennaState,
52}
53
54impl embedded_io::ErrorType for WirelessModemFake {
55 type Error = core::convert::Infallible;
56}
57
58impl embedded_io::ReadReady for WirelessModemFake {
59 fn read_ready(&mut self) -> Result<bool, Self::Error> {
60 Ok(self.readable())
61 }
62}
63
64impl embedded_io::Read for WirelessModemFake {
65 fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
66 WirelessModemFake::read(&self, buf)
67 }
68}
69
70impl embedded_io::Write for WirelessModemFake {
71 fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
72 WirelessModemFake::write(&self, buf)
73 }
74
75 fn flush(&mut self) -> Result<(), Self::Error> {
76 WirelessModemFake::flush(&self)
77 }
78}
79
80pub struct WirelessModemFake {
81 arc_mutexed_internal_state: Arc<Mutex<InternalState>>,
82 name: String,
83}
84
85impl WirelessModemFake {
86 pub fn new(name: &str) -> Self {
87 WirelessModemFake {
88 arc_mutexed_internal_state: Arc::new(Mutex::new(InternalState {
89 tick_state: TickState::OffTick,
90 from_antenna_buffer: VecDeque::new(),
91 to_antenna_buffer: VecDeque::new(),
92 antennta_state: AntennaState::Idle,
93 })),
94 name: String::from(name),
95 }
96 }
97
98 pub fn read(&self, buf: &mut [u8]) -> Result<usize, core::convert::Infallible> {
99 let mut count_red: usize = 0;
100 for buf_vancant_place in buf.iter_mut() {
101 if let Some(byte) = self.get_from_tx_pin() {
102 *buf_vancant_place = byte;
103 count_red += 1;
104 }
105 }
106 Ok(count_red)
107 }
108
109 pub fn write(&self, buf: &[u8]) -> Result<usize, core::convert::Infallible> {
110 let mut count_written: usize = 0;
111 for b in buf {
112 self.put_to_rx_pin(*b);
113 count_written += 1;
114 }
115 Ok(count_written)
116 }
117
118 pub fn flush(&self) -> Result<(), core::convert::Infallible> {
119 Ok(())
120 }
121
122 pub fn clone(&self) -> Self {
126 WirelessModemFake {
127 arc_mutexed_internal_state: Arc::clone(&self.arc_mutexed_internal_state),
128 name: self.name.clone(),
129 }
130 }
131}
132
133impl IODriverSimulator for WirelessModemFake {
134 fn get_from_device_network_side(&self) -> Option<u8> {
152 let locked_internal_state = self
153 .arc_mutexed_internal_state
154 .lock()
155 .expect(format!("Fail to lock mutex for modem :{}", self.name).as_str());
156
157 match locked_internal_state.tick_state {
158 TickState::OffTick => panic!("Impossible to put_to_device_network_side. Device not in simulation mode. Simulation is within the tick. You shall start tick first."),
159 TickState::InTick => match locked_internal_state.antennta_state {
160 AntennaState::Transmit(byte) => Some(byte),
161 _ => None,
162 },
163 }
164 }
165
166 fn put_to_device_network_side(&self, byte: u8) {
179 let mut locked_internal_state = self
180 .arc_mutexed_internal_state
181 .lock()
182 .expect(format!("Fail to lock mutex for modem :{}", self.name).as_str());
183
184 match locked_internal_state.tick_state {
185 TickState::OffTick => panic!("Impossible to put_to_device_network_side. Device not in simulation mode. Simulation is within the tick. You shall start tick first."),
186 TickState::InTick => match locked_internal_state.antennta_state {
187 AntennaState::Transmit(_) => (),
188 AntennaState::Idle | AntennaState::Receive(_) => {
189 locked_internal_state.antennta_state = AntennaState::Receive(byte)
190 }
191 },
192 }
193 }
194
195 fn get_from_tx_pin(&self) -> Option<u8> {
208 let mut locked_internal_state = self
209 .arc_mutexed_internal_state
210 .lock()
211 .expect(format!("Fail to lock mutex for modem :{}", self.name).as_str());
212
213 locked_internal_state.from_antenna_buffer.pop_front()
214 }
215
216 fn put_to_rx_pin(&self, byte: u8) {
227 let mut locked_internal_state = self
228 .arc_mutexed_internal_state
229 .lock()
230 .expect(format!("Fail to lock mutex for modem :{}", self.name).as_str());
231
232 locked_internal_state.to_antenna_buffer.push_back(byte);
233 }
234
235 fn start_tick(&self) {
238 let mut locked_internal_state = self
239 .arc_mutexed_internal_state
240 .lock()
241 .expect(format!("Fail to lock mutex for modem :{}", self.name).as_str());
242
243 match locked_internal_state.tick_state {
244 TickState::OffTick => {
245 locked_internal_state.antennta_state =
246 match locked_internal_state.to_antenna_buffer.pop_front() {
247 Some(byte) => AntennaState::Transmit(byte),
248 _ => AntennaState::Idle,
249 };
250
251 locked_internal_state.tick_state = TickState::InTick;
252 }
253 TickState::InTick => (),
254 }
255 }
256
257 fn end_tick(&self) {
260 let mut locked_internal_state = self
261 .arc_mutexed_internal_state
262 .lock()
263 .expect(format!("Fail to lock mutex for modem :{}", self.name).as_str());
264
265 match locked_internal_state.tick_state {
266 TickState::OffTick => (),
267 TickState::InTick => {
268 match locked_internal_state.antennta_state {
269 AntennaState::Receive(byte) => {
270 locked_internal_state.from_antenna_buffer.push_back(byte);
271 }
272 _ => (),
273 }
274
275 locked_internal_state.antennta_state = AntennaState::Idle;
276
277 locked_internal_state.tick_state = TickState::OffTick;
278 }
279 }
280 }
281
282 fn readable(&self) -> bool {
295 let locked_internal_state = self
296 .arc_mutexed_internal_state
297 .lock()
298 .expect(format!("Fail to lock mutex for modem :{}", self.name).as_str());
299
300 !locked_internal_state.from_antenna_buffer.is_empty()
301 }
302
303 fn writable(&self) -> bool {
310 true
311 }
312
313 fn get_name(&self) -> &str {
321 &self.name
322 }
323}
324
325#[cfg(test)]
326mod radio_modem_device_tests {
327 use super::*;
328
329 #[test]
330 fn test_half_duplex_send_per_tick() {
331 let modem_device = WirelessModemFake::new("");
332 modem_device.start_tick();
333 modem_device.put_to_device_network_side(b'a');
334 modem_device.put_to_rx_pin(b'b');
335 modem_device.end_tick();
336
337 let byte_on_tx_pin = modem_device.get_from_tx_pin();
338
339 modem_device.start_tick();
340 assert_eq!(modem_device.get_from_device_network_side(), Some(b'b'));
341 modem_device.end_tick();
342 assert_eq!(byte_on_tx_pin, Some(b'a'));
343 }
344
345 #[test]
347 fn test_data_collision_per_tick() {
348 let modem_device = WirelessModemFake::new("");
349 modem_device.start_tick();
350 modem_device.put_to_device_network_side(b'a');
351 modem_device.put_to_device_network_side(b'b');
352 modem_device.put_to_device_network_side(b'c');
353 modem_device.end_tick();
354 assert_eq!(modem_device.get_from_tx_pin(), Some(b'c'));
355 }
356}