]> code.octet-stream.net Git - m17rt/commitdiff
Round trip packet modulation and demodulation via RRC
authorThomas Karpiniec <tom.karpiniec@outlook.com>
Wed, 22 Jan 2025 11:06:05 +0000 (22:06 +1100)
committerThomas Karpiniec <tom.karpiniec@outlook.com>
Wed, 22 Jan 2025 11:06:05 +0000 (22:06 +1100)
Cargo.lock
Cargo.toml
m17app/src/adapter.rs
m17app/src/app.rs
m17app/src/link_setup.rs
m17codec2/src/lib.rs
m17core/src/tnc.rs
tools/m17rt-rxpacket/Cargo.toml [new file with mode: 0755]
tools/m17rt-rxpacket/src/main.rs [new file with mode: 0755]
tools/m17rt-txpacket/Cargo.toml [new file with mode: 0644]
tools/m17rt-txpacket/src/main.rs [new file with mode: 0644]

index 8faa53c885876ea570602474c0d859717a1c1fbd..a1a9c8b72c3adcb7e94ebaa608670ef29dea7630 100755 (executable)
@@ -505,6 +505,27 @@ dependencies = [
  "m17core",
 ]
 
  "m17core",
 ]
 
+[[package]]
+name = "m17rt-rxpacket"
+version = "0.1.0"
+dependencies = [
+ "cpal",
+ "env_logger",
+ "log",
+ "m17app",
+ "m17core",
+]
+
+[[package]]
+name = "m17rt-txpacket"
+version = "0.1.0"
+dependencies = [
+ "env_logger",
+ "log",
+ "m17app",
+ "m17core",
+]
+
 [[package]]
 name = "mach2"
 version = "0.4.2"
 [[package]]
 name = "mach2"
 version = "0.4.2"
index 2e53deccc19d9e51126e801f88a441d8cc5876a0..8d1b91d605c7fd98ee081979b474d629b45bf4d6 100755 (executable)
@@ -1,5 +1,5 @@
 [workspace]
 resolver = "2"
 members = [
 [workspace]
 resolver = "2"
 members = [
-    "m17app", "m17codec2", "m17core", "tools/m17rt-demod", "tools/m17rt-mod",
+    "m17app", "m17codec2", "m17core", "tools/m17rt-demod", "tools/m17rt-mod", "tools/m17rt-txpacket", "tools/m17rt-rxpacket"
 ]
 ]
index a03cf09c901ab5c7ba009a7797c2ca01b73b6982..57e01bbbabae6e35947a07ceacdb50219446e67b 100644 (file)
@@ -1,22 +1,28 @@
-use crate::app::TxHandle;
-use m17core::protocol::{LsfFrame, PacketType};
+use crate::{app::TxHandle, link_setup::LinkSetup};
+use m17core::protocol::PacketType;
 use std::sync::Arc;
 
 pub trait PacketAdapter: Send + Sync + 'static {
 use std::sync::Arc;
 
 pub trait PacketAdapter: Send + Sync + 'static {
-    fn adapter_registered(&self, id: usize, handle: TxHandle);
-    fn adapter_removed(&self);
-    fn tnc_started(&self);
-    fn tnc_closed(&self);
-    fn packet_received(&self, lsf: LsfFrame, packet_type: PacketType, content: Arc<[u8]>);
+    fn adapter_registered(&self, _id: usize, _handle: TxHandle) {}
+    fn adapter_removed(&self) {}
+    fn tnc_started(&self) {}
+    fn tnc_closed(&self) {}
+    fn packet_received(
+        &self,
+        _link_setup: LinkSetup,
+        _packet_type: PacketType,
+        _content: Arc<[u8]>,
+    ) {
+    }
 }
 
 pub trait StreamAdapter: Send + Sync + 'static {
 }
 
 pub trait StreamAdapter: Send + Sync + 'static {
-    fn adapter_registered(&self, id: usize, handle: TxHandle);
-    fn adapter_removed(&self);
-    fn tnc_started(&self);
-    fn tnc_closed(&self);
-    fn stream_began(&self, lsf: LsfFrame);
-    fn stream_data(&self, frame_number: u16, is_final: bool, data: Arc<[u8; 16]>);
+    fn adapter_registered(&self, _id: usize, _handle: TxHandle) {}
+    fn adapter_removed(&self) {}
+    fn tnc_started(&self) {}
+    fn tnc_closed(&self) {}
+    fn stream_began(&self, _link_setup: LinkSetup) {}
+    fn stream_data(&self, _frame_number: u16, _is_final: bool, _data: Arc<[u8; 16]>) {}
 
     // TODO
     // fn stream_lost(&self);
 
     // TODO
     // fn stream_lost(&self);
index a7bb3cd291b18efbf154ec5d54807fe32faf408a..7d363dd1808522b986e06e687e39b82c3c8bd544 100644 (file)
@@ -84,12 +84,7 @@ pub struct TxHandle {
 }
 
 impl TxHandle {
 }
 
 impl TxHandle {
-    pub fn transmit_packet(
-        &self,
-        link_setup: &LinkSetup,
-        packet_type: &PacketType,
-        payload: &[u8],
-    ) {
+    pub fn transmit_packet(&self, link_setup: &LinkSetup, packet_type: PacketType, payload: &[u8]) {
         let (pack_type, pack_type_len) = packet_type.as_proto();
         if pack_type_len + payload.len() > 823 {
             // TODO: error for invalid transmission type
         let (pack_type, pack_type_len) = packet_type.as_proto();
         if pack_type_len + payload.len() > 823 {
             // TODO: error for invalid transmission type
@@ -204,7 +199,7 @@ fn spawn_reader<T: Tnc>(mut tnc: T, adapters: Arc<RwLock<Adapters>>) {
                             adapters.read().unwrap().packet.values().cloned().collect();
                         for s in subs {
                             s.packet_received(
                             adapters.read().unwrap().packet.values().cloned().collect();
                         for s in subs {
                             s.packet_received(
-                                lsf.clone(),
+                                LinkSetup::new_raw(lsf.clone()),
                                 packet_type.clone(),
                                 packet_payload.clone(),
                             );
                                 packet_type.clone(),
                                 packet_payload.clone(),
                             );
@@ -226,7 +221,7 @@ fn spawn_reader<T: Tnc>(mut tnc: T, adapters: Arc<RwLock<Adapters>>) {
                             let subs: Vec<_> =
                                 adapters.read().unwrap().stream.values().cloned().collect();
                             for s in subs {
                             let subs: Vec<_> =
                                 adapters.read().unwrap().stream.values().cloned().collect();
                             for s in subs {
-                                s.stream_began(lsf.clone());
+                                s.stream_began(LinkSetup::new_raw(lsf.clone()));
                             }
                         } else if n == 26 {
                             if !stream_running {
                             }
                         } else if n == 26 {
                             if !stream_running {
index 007dc78fc3b2338cf6a9cd57734648c6d28856a5..2a701de676681aaefb4e6be74411affb18e432c1 100644 (file)
@@ -17,6 +17,14 @@ impl LinkSetup {
         Self { raw: frame }
     }
 
         Self { raw: frame }
     }
 
+    pub fn source(&self) -> M17Address {
+        M17Address(self.raw.source())
+    }
+
+    pub fn destination(&self) -> M17Address {
+        M17Address(self.raw.destination())
+    }
+
     /// Set up an unencrypted voice stream with channel access number 0 and the given source and destination.
     pub fn new_voice(source: &M17Address, destination: &M17Address) -> Self {
         Self {
     /// Set up an unencrypted voice stream with channel access number 0 and the given source and destination.
     pub fn new_voice(source: &M17Address, destination: &M17Address) -> Self {
         Self {
index 5eb54a4d6d4f20b7c2721bc85b2f39e6afcb71d2..0f3c8a5e2cb0199e7754fa3289d80818f8123d00 100755 (executable)
@@ -93,7 +93,7 @@ impl StreamAdapter for Codec2Adapter {
 
     fn tnc_closed(&self) {}
 
 
     fn tnc_closed(&self) {}
 
-    fn stream_began(&self, _lsf: LsfFrame) {
+    fn stream_began(&self, _link_setup: LinkSetup) {
         // for now we will assume:
         // - unencrypted
         // - data type is Voice (Codec2 3200), not Voice+Data
         // for now we will assume:
         // - unencrypted
         // - data type is Voice (Codec2 3200), not Voice+Data
index 8cd0152ae81d82520b6d65a73a37ef632ac74a00..93a4363ae62f0939100ee51a04166fc548595edd 100644 (file)
@@ -117,7 +117,10 @@ impl SoftTnc {
                     Mode::Stream => {
                         let kiss = KissFrame::new_stream_setup(&lsf.0).unwrap();
                         self.kiss_to_host(kiss);
                     Mode::Stream => {
                         let kiss = KissFrame::new_stream_setup(&lsf.0).unwrap();
                         self.kiss_to_host(kiss);
-                        self.state = State::RxStream(RxStreamState { lsf, index: 0 });
+                        self.state = State::RxStream(RxStreamState {
+                            _lsf: lsf,
+                            index: 0,
+                        });
                     }
                 }
             }
                     }
                 }
             }
@@ -139,7 +142,7 @@ impl SoftTnc {
                                 let start = 25 * rx.count;
                                 let end = start + payload_len;
                                 rx.packet[start..(start + payload_len)]
                                 let start = 25 * rx.count;
                                 let end = start + payload_len;
                                 rx.packet[start..(start + payload_len)]
-                                    .copy_from_slice(&packet.payload);
+                                    .copy_from_slice(&packet.payload[0..payload_len]);
                                 // TODO: compatible packets should be sent on port 0 too
                                 let kiss =
                                     KissFrame::new_full_packet(&rx.lsf.0, &rx.packet[0..end])
                                 // TODO: compatible packets should be sent on port 0 too
                                 let kiss =
                                     KissFrame::new_full_packet(&rx.lsf.0, &rx.packet[0..end])
@@ -186,7 +189,7 @@ impl SoftTnc {
                                 // TODO: avoid discarding the first data payload here
                                 // need a queue depth of 2 for outgoing kiss
                                 self.state = State::RxStream(RxStreamState {
                                 // TODO: avoid discarding the first data payload here
                                 // need a queue depth of 2 for outgoing kiss
                                 self.state = State::RxStream(RxStreamState {
-                                    lsf,
+                                    _lsf: lsf,
                                     index: stream.frame_number + 1,
                                 });
                             }
                                     index: stream.frame_number + 1,
                                 });
                             }
@@ -431,7 +434,7 @@ impl SoftTnc {
                 }
                 pending.lsf = Some(lsf);
                 let app_data_len = len - 30;
                 }
                 pending.lsf = Some(lsf);
                 let app_data_len = len - 30;
-                pending.app_data[0..app_data_len].copy_from_slice(&payload[30..]);
+                pending.app_data[0..app_data_len].copy_from_slice(&payload[30..len]);
                 pending.app_data_len = app_data_len;
                 self.packet_queue[self.packet_next] = pending;
                 self.packet_next = (self.packet_next + 1) % 4;
                 pending.app_data_len = app_data_len;
                 self.packet_queue[self.packet_next] = pending;
                 self.packet_next = (self.packet_next + 1) % 4;
@@ -531,7 +534,7 @@ struct RxAcquiringStreamState {
 
 struct RxStreamState {
     /// Track identifying information for this transmission so we can tell if it changes.
 
 struct RxStreamState {
     /// Track identifying information for this transmission so we can tell if it changes.
-    lsf: LsfFrame,
+    _lsf: LsfFrame,
 
     /// Expected next frame number. Allowed to skip values on RX, but not go backwards.
     index: u16,
 
     /// Expected next frame number. Allowed to skip values on RX, but not go backwards.
     index: u16,
@@ -594,7 +597,7 @@ impl PendingPacket {
             )
         };
         let mut payload = [0u8; 25];
             )
         };
         let mut payload = [0u8; 25];
-        payload.copy_from_slice(
+        payload[0..data_len].copy_from_slice(
             &self.app_data[self.app_data_transmitted..(self.app_data_transmitted + data_len)],
         );
         self.app_data_transmitted += data_len;
             &self.app_data[self.app_data_transmitted..(self.app_data_transmitted + data_len)],
         );
         self.app_data_transmitted += data_len;
diff --git a/tools/m17rt-rxpacket/Cargo.toml b/tools/m17rt-rxpacket/Cargo.toml
new file mode 100755 (executable)
index 0000000..2cab9a5
--- /dev/null
@@ -0,0 +1,15 @@
+[package]
+name = "m17rt-rxpacket"
+version = "0.1.0"
+edition = "2021"
+license = "MIT"
+authors = ["Thomas Karpiniec <tom.karpiniec@outlook.com"]
+publish = false
+
+[dependencies]
+m17core = { path = "../../m17core" }
+m17app = { path = "../../m17app" }
+
+cpal = "0.15.3"
+env_logger = "0.11.6"
+log = "0.4.22"
diff --git a/tools/m17rt-rxpacket/src/main.rs b/tools/m17rt-rxpacket/src/main.rs
new file mode 100755 (executable)
index 0000000..1cdd1d8
--- /dev/null
@@ -0,0 +1,37 @@
+use m17app::adapter::PacketAdapter;
+use m17app::app::M17App;
+use m17app::link_setup::LinkSetup;
+use m17app::soundmodem::{InputRrcFile, NullOutputSink, NullPtt, Soundmodem};
+use m17core::protocol::PacketType;
+use std::path::PathBuf;
+use std::sync::Arc;
+
+fn main() {
+    let path = PathBuf::from("../../../Data/mypacket.rrc");
+    let soundmodem = Soundmodem::new(
+        InputRrcFile::new(path),
+        NullOutputSink::new(),
+        NullPtt::new(),
+    );
+    let app = M17App::new(soundmodem);
+    app.add_packet_adapter(PacketPrinter);
+    app.start();
+
+    loop {
+        std::thread::park();
+    }
+}
+
+struct PacketPrinter;
+impl PacketAdapter for PacketPrinter {
+    fn packet_received(&self, link_setup: LinkSetup, packet_type: PacketType, content: Arc<[u8]>) {
+        println!(
+            "from {} to {} type {:?} len {}",
+            link_setup.source(),
+            link_setup.destination(),
+            packet_type,
+            content.len()
+        );
+        println!("{}", String::from_utf8_lossy(&content));
+    }
+}
diff --git a/tools/m17rt-txpacket/Cargo.toml b/tools/m17rt-txpacket/Cargo.toml
new file mode 100644 (file)
index 0000000..4f0283c
--- /dev/null
@@ -0,0 +1,14 @@
+[package]
+name = "m17rt-txpacket"
+version = "0.1.0"
+edition = "2021"
+license = "MIT"
+authors = ["Thomas Karpiniec <tom.karpiniec@outlook.com"]
+publish = false
+
+[dependencies]
+m17core = { path = "../../m17core" }
+m17app = { path = "../../m17app" }
+
+env_logger = "0.11.6"
+log = "0.4.22"
diff --git a/tools/m17rt-txpacket/src/main.rs b/tools/m17rt-txpacket/src/main.rs
new file mode 100644 (file)
index 0000000..538291a
--- /dev/null
@@ -0,0 +1,33 @@
+use m17app::app::M17App;
+use m17app::link_setup::{LinkSetup, M17Address};
+use m17app::soundmodem::{
+    InputRrcFile, InputSoundcard, NullInputSource, NullOutputSink, NullPtt, OutputRrcFile,
+    OutputSoundcard, Soundmodem,
+};
+use m17core::protocol::PacketType;
+use std::path::PathBuf;
+
+pub fn mod_test() {
+    let out_path = PathBuf::from("../../../Data/mypacket.rrc");
+    let output = OutputRrcFile::new(out_path);
+    //let output = OutputSoundcard::new();
+    let soundmodem = Soundmodem::new(NullInputSource::new(), output, NullPtt::new());
+    let app = M17App::new(soundmodem);
+    app.start();
+    std::thread::sleep(std::time::Duration::from_secs(1));
+    println!("Transmitting packet...");
+
+    let source = M17Address::from_callsign("VK7XT").unwrap();
+    let destination = M17Address::new_broadcast();
+    let link_setup = LinkSetup::new_packet(&source, &destination);
+    let payload = b"Hello, world!";
+    app.tx()
+        .transmit_packet(&link_setup, PacketType::Raw, payload);
+
+    std::thread::sleep(std::time::Duration::from_secs(5));
+}
+
+fn main() {
+    env_logger::init();
+    mod_test();
+}