diff --git a/Cargo.lock b/Cargo.lock index da09b26f7d4311ba0d81d18cf0d0abe47f8a4afc..424abf97447ed81c86b7ffe845e4d30560e2bec5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -216,7 +216,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" [[package]] -name = "cats-sdr-igate-decoder" +name = "cats-sdr-igate" version = "0.1.0" dependencies = [ "anyhow", @@ -234,6 +234,7 @@ dependencies = [ "rand", "serde", "serde_with", + "subprocess", "tokio", "tokio-stream", "toml", @@ -1336,6 +1337,16 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +[[package]] +name = "subprocess" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c2e86926081dda636c546d8c5e641661049d7562a68f5488be4a1f7f66f6086" +dependencies = [ + "libc", + "winapi", +] + [[package]] name = "syn" version = "1.0.109" @@ -1734,6 +1745,28 @@ dependencies = [ "rustix", ] +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + [[package]] name = "windows-core" version = "0.52.0" diff --git a/Cargo.toml b/Cargo.toml index 2d52f9e3e75c7c8ba26519678114041b359f08f1..886be17042ff5aeb5d291e3bc897a11783b3cd61 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "cats-sdr-igate-decoder" +name = "cats-sdr-igate" version = "0.1.0" edition = "2021" license = "MIT OR LGPL-2.1-only" @@ -8,10 +8,9 @@ description = "An RX-only SDR CATS I-gate" [package.metadata.deb] assets = [ - ["target/release/cats-sdr-igate-decoder", "/usr/bin/", "755"], + ["target/release/cats-sdr-igate", "/usr/bin/", "755"], ["debian/cats-sdr-igate.service", "/lib/systemd/system/cats-sdr-igate.service", "644"], ["config.example.toml", "/etc/cats-sdr-igate/config.toml", "644"], - ["debian/start.sh", "/usr/bin/cats-sdr-igate", "755"] ] conf-files = ["/etc/cats-sdr-igate/config.toml"] maintainer-scripts = "debian/maintainer_scripts/" @@ -39,6 +38,7 @@ rand = "0.8.5" bitvec = "1.0.1" libc = "0.2.152" itertools = "0.12.0" +subprocess = "0.2.9" [build-dependencies] tonic-build = "0.9" diff --git a/README.md b/README.md index a5d4d739e28f0c72e7b9986e5a925f7eb9b2554e..5234d1f1dc65d2fc8fc0a785768281424918e8de 100644 --- a/README.md +++ b/README.md @@ -18,11 +18,11 @@ git pull cargo deb ``` -The resulting deb package will placed in `target/debian/cats-sdr-igate-decoder_VERSION.deb` +The resulting deb package will placed in `target/debian/cats-sdr-igate_VERSION.deb` ### Installing -Once built, the package can be installed with `sudo dpkg -i target/debian/cats-sdr-igate-decoder_VERSION.deb`, replacing `VERSION` with whatever version and architecture was built. +Once built, the package can be installed with `sudo dpkg -i target/debian/cats-sdr-igate_VERSION.deb`, replacing `VERSION` with whatever version and architecture was built. ### Configuring diff --git a/debian/start.sh b/debian/start.sh deleted file mode 100755 index 3623a67a836844ba26c1026bd264a84668d71f1b..0000000000000000000000000000000000000000 --- a/debian/start.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh - -rtl_fm -M raw -F9 -p 0 -d 0 -s 48000 -f 430500000 - | /usr/bin/cats-sdr-igate-decoder diff --git a/src/decoder/mod.rs b/src/decoder/mod.rs index 3b77cc0b868802802bf1131a601fdd808f96e74d..97554aef8158afb16a86c92da0c62a7af568fac3 100644 --- a/src/decoder/mod.rs +++ b/src/decoder/mod.rs @@ -7,6 +7,7 @@ use uuid::Uuid; use crate::{ codec2::{Complex, Fsk}, config::FelinetConfig, + decoder::rtl::RtlSdr, felinet::PacketIn as SemiPacketIn, util::{append_internet_to_packet_route, print_packet}, }; @@ -16,16 +17,25 @@ use self::{dc_bias::RemoveDcBias, demod::Demod}; mod dc_bias; mod demod; mod packet; +mod rtl; pub fn decode_forever( felinet_send: mpsc::Sender<SemiPacketIn>, felinet_config: &Option<FelinetConfig>, uuid: &Uuid, ) { - let stdin = io::stdin(); - let iq = stdin - .bytes() - .map(|x| x.expect("Could not read from stdin")) + const USE_STDIN: bool = false; + + let bytes: Box<dyn Iterator<Item = u8>> = if USE_STDIN { + let stdin = io::stdin(); + + Box::new(stdin.bytes().map(|x| x.expect("Could not read from stdin"))) + } else { + let rtl = RtlSdr::new().unwrap(); + Box::new(rtl) + }; + + let iq = bytes .tuples() .map(|(a, b)| i16::from_le_bytes([a, b])) .tuples() @@ -34,11 +44,8 @@ pub fn decode_forever( let imag = imag as f32; Complex { real, imag } }); - let iq_no_dc = RemoveDcBias::new(iq); - let soft_bits = Fsk::new(iq_no_dc); - let demod = Demod::new(soft_bits); demod.demod(|mut p| { diff --git a/src/decoder/rtl.rs b/src/decoder/rtl.rs new file mode 100644 index 0000000000000000000000000000000000000000..563d3b5bc673aa7f35a2949b2b62ef24345224fd --- /dev/null +++ b/src/decoder/rtl.rs @@ -0,0 +1,76 @@ +use std::collections::VecDeque; + +use anyhow::Context; +use subprocess::{Communicator, Popen, PopenConfig, Redirection}; + +pub struct RtlSdr { + comms: Communicator, + out_buf: VecDeque<u8>, + err_buf: Vec<u8>, +} + +impl RtlSdr { + pub fn new() -> anyhow::Result<Self> { + let mut p = Popen::create( + &[ + "rtl_fm", + "-f", + "430500000", + "-M", + "raw", + "-F9", + "-p", + "0", + "-d", + "0", + "-s", + "48000", + ], + PopenConfig { + stdout: Redirection::Pipe, + stderr: Redirection::Pipe, + detached: true, + ..Default::default() + }, + ) + .context("Error starting rtl-fm")?; + + let comms = p.communicate_start(None).limit_size(1024); + + Ok(Self { + comms, + out_buf: VecDeque::new(), + err_buf: vec![], + }) + } +} + +impl Iterator for RtlSdr { + type Item = u8; + + fn next(&mut self) -> Option<Self::Item> { + if let Some(b) = self.out_buf.pop_front() { + return Some(b); + } + + let (out, err) = self.comms.read().ok()?; + let out = out.expect("Missing stdout"); + let err = err.expect("Missing stderr"); + + self.out_buf.extend(out.iter()); + for e in err { + if e == b'\n' { + handle_err(&self.err_buf); + self.err_buf.clear(); + } else { + self.err_buf.push(e); + } + } + + self.out_buf.pop_front() + } +} + +fn handle_err(err: &[u8]) { + eprintln!("[rtl_fm] {}", String::from_utf8_lossy(err)); +} diff --git a/start.sh b/start.sh deleted file mode 100755 index 66402a5d611af9eb4be15f4934c1e60e32fa81ea..0000000000000000000000000000000000000000 --- a/start.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh - -rtl_fm -M raw -F9 -p 0 -d 0 -s 48000 -f 430500000 - | target/release/cats-sdr-igate-decoder