// src/send.rs use embassy_stm32::gpio::{Level, Output}; use embassy_sync::{ blocking_mutex::raw::CriticalSectionRawMutex, channel::{Receiver, Sender}, }; use embassy_time::{Duration, Ticker}; use crate::{level_for_bit, Encoding}; const START: u8 = 0x7E; const STOP: u8 = 0x81; const BIT_PERIOD: Duration = Duration::from_millis(10); pub type Tx = Sender<'static, CriticalSectionRawMutex, u8, 128>; fn set_level(pin: &mut Output<'static>, is_high: bool) { pin.set_level(if is_high { Level::High } else { Level::Low }); } async fn send_byte(byte: u8, tx: &Tx) { for i in (0..8).rev() { tx.send((byte >> i) & 1).await; } } /// [START] [LEN] [PAYLOAD ...] [CRC] [P] [STOP] pub async fn msg_encode(payload: &[u8], tx: &Tx) { // start send_byte(START, tx).await; // len let len = payload.len() as u8; send_byte(len, tx).await; for &b in payload { send_byte(b, tx).await; } // crc let mut crc = crc8(0, len); for &b in payload { crc = crc8(crc, b); } send_byte(crc, tx).await; let mut ones = len.count_ones() + crc.count_ones(); for &b in payload { ones += b.count_ones(); } tx.send((ones as u8) & 1).await; send_byte(STOP, tx).await; // idle tx.send(1).await; } fn crc8(crc: u8, byte: u8) -> u8 { let mut c = crc ^ byte; for _ in 0..8 { c = if c & 0x80 != 0 { (c << 1) ^ 0x07 } else { c << 1 }; } c } #[embassy_executor::task] pub async fn bit_send( mut pin: Output<'static>, rx: Receiver<'static, CriticalSectionRawMutex, u8, 128>, encoding: Encoding, ) { let mut ticker = Ticker::every(BIT_PERIOD / 2); let mut is_high = level_for_bit(1); set_level(&mut pin, is_high); loop { let bit = rx.receive().await; match encoding { Encoding::Nrz => { is_high = level_for_bit(bit); set_level(&mut pin, is_high); ticker.next().await; } // toggle, ak sme v 1, inac sa nedeje nic Encoding::Nrzi => { if bit == 1 { is_high = !is_high; if is_high { pin.set_high(); } else { pin.set_low(); } } ticker.next().await; } // manchester xor tabulka Encoding::Manchester => { if bit == 1 { // high -> low set_level(&mut pin, level_for_bit(1)); ticker.next().await; set_level(&mut pin, level_for_bit(0)); ticker.next().await; } else { // low -> high set_level(&mut pin, level_for_bit(0)); ticker.next().await; set_level(&mut pin, level_for_bit(1)); ticker.next().await; } } }; } }