ic7300.rs (6254B)
1 use log::{debug, trace}; 2 use serialport::{DataBits::Eight, Parity::None, StopBits::One}; 3 use std::{ 4 sync::mpsc::{Receiver, Sender}, 5 time::{Duration, Instant}, 6 }; 7 8 use crate::{Freq, Ptt, State}; 9 10 enum CivCmd { 11 SetFreq(Freq), 12 SetPtt(Ptt), 13 ReadPtt, 14 } 15 16 fn to_bcd(n: u8) -> u8 { 17 ((n / 10) * 16) + (n % 10) 18 } 19 20 fn from_bcd(n: u8) -> u8 { 21 ((n / 16) * 10) + (n % 16) 22 } 23 24 impl From<CivCmd> for Vec<u8> { 25 fn from(value: CivCmd) -> Self { 26 match value { 27 CivCmd::SetFreq(f) => { 28 let tens_ones_hz = (f % 100) as u8; 29 let thousands_hundreds_hz = ((f / 100) % 100) as u8; 30 let hundreds_tens_khz = ((f / 10_000) % 100) as u8; 31 let tens_ones_mhz = ((f / 1_000_000) % 100) as u8; 32 let bytes = vec![ 33 0xfe, 34 0xfe, 35 0x94, 36 0xe1, 37 0x00, 38 to_bcd(tens_ones_hz), 39 to_bcd(thousands_hundreds_hz), 40 to_bcd(hundreds_tens_khz), 41 to_bcd(tens_ones_mhz), 42 0x00, 43 0xfd, 44 ]; 45 trace!("Frequency is {}, converted to {:x?}", f, bytes); 46 bytes 47 } 48 CivCmd::SetPtt(p) => { 49 let bytes = vec![ 50 0xfe, 51 0xfe, 52 0x94, 53 0xe1, 54 0x1c, 55 0x00, 56 if p { 0x01 } else { 0x00 }, 57 0xfd, 58 ]; 59 trace!("PTT is {}, converted to {:x?}", p, bytes); 60 bytes 61 } 62 CivCmd::ReadPtt => vec![0xfe, 0xfe, 0x94, 0xe1, 0x1c, 0x00, 0xfd], 63 } 64 } 65 } 66 67 #[derive(Debug)] 68 enum CivMsg { 69 Freq(Freq), 70 Ptt(Ptt), 71 } 72 73 #[derive(Debug)] 74 enum CivMsgError { 75 InputTooShort, 76 InvalidStartOrEnd, 77 WrongAddress, 78 WrongCommand, 79 } 80 81 impl TryFrom<&[u8]> for CivMsg { 82 type Error = CivMsgError; 83 fn try_from(value: &[u8]) -> Result<Self, Self::Error> { 84 if value.len() < 8 { 85 trace!("Input too short: {} < 8", value.len()); 86 return Err(CivMsgError::InputTooShort); 87 } 88 if value[..2] != [0xfe, 0xfe] || *value.last().unwrap() != 0xfd { 89 trace!( 90 "Invalid start or end: [0x{:x}, 0x{:x}, ... , 0x{:x}]", 91 value[0], 92 value[1], 93 value.last().unwrap() 94 ); 95 return Err(CivMsgError::InvalidStartOrEnd); 96 } 97 if value[2..4] != [0xe1, 0x94] && value[2..4] != [0x00, 0x94] { 98 trace!( 99 "Wrong address: [..., 0x{:x}, 0x{:x}, ...]", 100 value[2], 101 value[3] 102 ); 103 return Err(CivMsgError::WrongAddress); 104 } 105 if value[4] == 0x00 && value.len() == 11 { 106 let freq = from_bcd(value[5]) as u32 107 + from_bcd(value[6]) as u32 * 100 108 + from_bcd(value[7]) as u32 * 10_000 109 + from_bcd(value[8]) as u32 * 1_000_000; 110 return Ok(CivMsg::Freq(freq)); 111 } 112 if value[4..6] == [0x1c, 0x00] && value.len() == 8 { 113 return Ok(CivMsg::Ptt(value[6] != 0x00)); 114 } 115 trace!("Command doesn't apply to us"); 116 Err(CivMsgError::WrongCommand) 117 } 118 } 119 120 pub(crate) fn ic7300_handler(tx: Sender<State>, rx: Receiver<State>) { 121 let mut port = serialport::new("/dev/ttyUSB1", 115_200) 122 .data_bits(Eight) 123 .parity(None) 124 .stop_bits(One) 125 .open() 126 .unwrap(); 127 debug!("Serial port set up"); 128 let mut current_state = State::default(); 129 let mut read_buf = [0u8; 1024]; 130 let mut last_ptt_check = Instant::now(); 131 loop { 132 if let Some(new_state) = rx.try_iter().last() { 133 trace!("Got new state from main thread"); 134 if new_state.freq != current_state.freq { 135 let mut freq_bytes: Vec<u8> = CivCmd::SetFreq(new_state.freq).into(); 136 port.write_all(&mut freq_bytes).unwrap(); 137 debug!("Set new frequency to {}", new_state.freq); 138 } 139 if new_state.ptt != current_state.ptt { 140 let mut ptt_bytes: Vec<u8> = CivCmd::SetPtt(new_state.ptt).into(); 141 port.write_all(&mut ptt_bytes).unwrap(); 142 debug!("Set PTT to {}", new_state.ptt); 143 } 144 current_state = new_state; 145 } 146 if last_ptt_check.elapsed() > Duration::from_millis(100) { 147 let mut ptt_bytes: Vec<u8> = CivCmd::ReadPtt.into(); 148 port.write_all(&mut ptt_bytes).unwrap(); 149 last_ptt_check = Instant::now(); 150 trace!("Sent ReadPtt command"); 151 } 152 let mut new_state = current_state; 153 if port.bytes_to_read().unwrap() == 0 { 154 // trace!("No bytes to read, continuing"); 155 continue; 156 } 157 let n = match port.read(&mut read_buf) { 158 Ok(n) => n, 159 Err(_) => return, 160 }; 161 trace!("{:?}", read_buf[..n].to_vec()); 162 let mut idx = 0; 163 let mut start = Option::None; 164 let mut msgs: Vec<CivMsg> = vec![]; 165 while idx < n { 166 // trace!("{}", idx); 167 if read_buf[idx] == 0xfe && read_buf[idx + 1] == 0xfe { 168 start = Some(idx); 169 } else if read_buf[idx] == 0xfd { 170 let end = idx + 1; 171 match read_buf[start.unwrap()..end].try_into() { 172 Ok(msg) => { 173 debug!("Got new CivMsg: {:?}", msg); 174 msgs.push(msg); 175 } 176 Err(e) => trace!("Got a message that we don't care about: {:?}", e), 177 } 178 start = Option::None; 179 } 180 idx += 1; 181 } 182 for msg in msgs { 183 match msg { 184 CivMsg::Freq(f) => new_state.freq = f, 185 CivMsg::Ptt(p) => new_state.ptt = p, 186 } 187 } 188 if new_state != current_state { 189 tx.send(new_state).unwrap(); 190 debug!("Sent new state to main thread"); 191 } 192 } 193 }