use std::{thread, time};
use gpio_cdev::{Chip, LineRequestFlags, LineHandle};
pub mod builder;
use crate::builder::{TransmissionBuilder, ProtocolBuilder};
#[derive(Debug, Default, Clone, PartialEq)]
pub struct Transmission {
pub sequence: String,
pub pulse_length: u16,
pub repeats: u8,
pub protocol: ProtocolProperties,
}
#[derive(Debug, Default, Copy, Clone, PartialEq)]
pub struct ProtocolProperties {
pub short: u8,
pub long: u8,
pub sync_bit: u8,
pub sync_gap: u8,
}
impl ProtocolProperties {
pub fn new() -> Self {
Default::default()
}
pub fn builder() -> ProtocolBuilder {
ProtocolBuilder::default()
}
}
pub const P1: ProtocolProperties = ProtocolProperties {
short: 1,
long: 3,
sync_bit: 1,
sync_gap: 31,
};
pub const P2: ProtocolProperties = ProtocolProperties {
short: 1,
long: 2,
sync_bit: 1,
sync_gap: 10,
};
pub const XEN: ProtocolProperties = ProtocolProperties {
short: 1,
long: 2,
sync_bit: 1,
sync_gap: 11,
};
impl Transmission {
pub fn send_to(&self, gpio_dev: &str, gpio_pin: u8) -> Result<(), gpio_cdev::Error> {
let mut chip = Chip::new(gpio_dev)?;
let lh = chip
.get_line(gpio_pin as u32)?
.request(LineRequestFlags::OUTPUT, 0, "tx")?;
for _ in 0..self.repeats {
for c in self.sequence.chars() {
if c == '1' {
send_bit(&lh, true, self.pulse_length, self.protocol.long, self.protocol.short)?;
} else if c == '0' {
send_bit(&lh, false, self.pulse_length, self.protocol.long, self.protocol.short)?;
} else {
send_sync_bit(&lh, self.pulse_length, self.protocol.sync_gap, self.protocol.sync_bit)?;
}
}
}
Ok(())
}
pub fn sequence(&mut self, seq: &str) {
self.sequence = String::from(seq);
}
pub fn new() -> Self {
Default::default()
}
pub fn builder() -> TransmissionBuilder {
TransmissionBuilder::default()
}
pub fn csv_as_bytes(&self) -> Vec<u8> {
let output = String::from(&format!("{},{},{},{},{},{},{}",
self.sequence,
self.pulse_length,
self.repeats,
self.protocol.short,
self.protocol.long,
self.protocol.sync_bit,
self.protocol.sync_gap));
output.as_bytes().to_vec()
}
}
fn send_bit(lh: &LineHandle, bit: bool, pulse_length: u16, factor1: u8, factor2: u8) -> Result<(), gpio_cdev::Error> {
if bit {
lh.set_value(1)?;
thread::sleep(time::Duration::from_micros(pulse_length as u64 * factor1 as u64));
lh.set_value(0)?;
thread::sleep(time::Duration::from_micros(pulse_length as u64 * factor2 as u64));
} else {
lh.set_value(1)?;
thread::sleep(time::Duration::from_micros(pulse_length as u64 * factor2 as u64));
lh.set_value(0)?;
thread::sleep(time::Duration::from_micros(pulse_length as u64 * factor1 as u64));
}
Ok(())
}
fn send_sync_bit(lh: &LineHandle, pulse_length: u16, factor1: u8, factor2: u8) -> Result<(), gpio_cdev::Error> {
lh.set_value(1)?;
thread::sleep(time::Duration::from_micros(pulse_length as u64 * factor2 as u64));
lh.set_value(0)?;
thread::sleep(time::Duration::from_micros(pulse_length as u64 * factor1 as u64));
Ok(())
}