Skip to content

Commit

Permalink
Finished implementation of new traits
Browse files Browse the repository at this point in the history
  • Loading branch information
amcelroy committed Nov 29, 2023
1 parent e445f3e commit df0a007
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 43 deletions.
6 changes: 3 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ license = "MIT"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[features]
default = ["std"]
default = []
std = []

[lib]
Expand All @@ -26,8 +26,8 @@ name = "flem"
path = "examples/example.rs"

[[example]]
name = "traits"
path = "examples/traits.rs"
name = "encode_decode"
path = "examples/encode_decode.rs"

[[example]]
name = "software_host_simple"
Expand Down
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
![Flem Build and Tests](https://github.com/amcelroy/flem-rust/actions/workflows/rust.yml/badge.svg)

# FLEM Rust 0.6.0
# FLEM Rust 0.6.2

FLEM stands for Flexible, Light-weight, Embedded Messaging and is a Little
Endian messaging protocol intended for use in communicating with embedded
Expand All @@ -10,7 +10,9 @@ systems targets over numerous types of buses.

### Changelog 0.6.2
- Added feature = ["std"]
- Added `Channel` trait. This
- Added `Channel` trait. This trait requires features = ["std"]. It servers as a set of traits that can be used
to implement different hardware or to emulate a device. It uses the `std` library for threading and `mpsc` channels.
- Added examples to show how to emulate a device use the `Channel` trait.

### Changelog 0.6.1
- Added fmt::Debug trait to Packet that prints the header, checksum, request, response, length, and status.
Expand Down
File renamed without changes.
95 changes: 57 additions & 38 deletions examples/software_host_complex.rs
Original file line number Diff line number Diff line change
@@ -1,25 +1,20 @@
use flem::{
Packet,
DataId,
traits::Channel
};
use flem::{traits::Channel, DataId, Packet};
use std::{
time::Duration,
sync::{
Arc,
Mutex,
mpsc::{self, Sender, Receiver}
mpsc::{self, Receiver, Sender},
Arc, Mutex,
},
thread,
time::Duration,
};

const PACKET_SIZE: usize = 512;
const PACKET_DEVICE_SIZE: usize = 128;

#[derive(Clone)]
struct FlemSoftwareHost<const PACKET_SIZE: usize>{
listening: Arc<Mutex<bool>>,
flem_packet_handler: Option<fn(&Packet<PACKET_DEVICE_SIZE>) -> Packet<PACKET_DEVICE_SIZE>>
struct FlemSoftwareHost<const PACKET_SIZE: usize> {
listening: Arc<Mutex<bool>>,
flem_packet_handler: Option<fn(&Packet<PACKET_DEVICE_SIZE>) -> Packet<PACKET_DEVICE_SIZE>>,
}

impl<const PACKET_SIZE: usize> FlemSoftwareHost<PACKET_SIZE> {
Expand Down Expand Up @@ -48,21 +43,26 @@ impl<const PACKET_SIZE: usize> Channel<PACKET_SIZE> for FlemSoftwareHost<PACKET_
Ok(())
}

fn listen(&mut self, rx_sleep_time_ms: u64, tx_sleep_time_ms: u64,) -> (Sender<Packet<PACKET_SIZE>>, Receiver<Packet<PACKET_SIZE>>) {
fn listen(
&mut self,
rx_sleep_time_ms: u64,
tx_sleep_time_ms: u64,
) -> (Sender<Packet<PACKET_SIZE>>, Receiver<Packet<PACKET_SIZE>>) {
// This example is similar to how flem-serial-rs works, except we need to add in a simulated byte-by-byte hardware transmission.
// If there is no need to simulate Rx and Tx hardware, a single thread would work that accepts a packet from `packet_to_transmit`,
// parses it, and sends a response on `validated_packet`.

// Tx packets are marshalled into a single queue, and dispatched over hardware.
let (tx_packet_from_program, packet_to_transmit) = mpsc::channel::<flem::Packet<PACKET_SIZE>>();
let (tx_packet_from_program, packet_to_transmit) =
mpsc::channel::<flem::Packet<PACKET_SIZE>>();

// Rx data is coming off of hardware, usually a byte at a time, and needs to be constructed into a packet and validated before passing back into the program
let (validated_packet, rx_packet_to_program) = mpsc::channel::<flem::Packet<PACKET_SIZE>>();

// This is a simple channel to simulated byte-by-byte transmission over hardware
let (simulated_hardware_host_tx, simulated_hardware_device_rx) = mpsc::channel::<u8>();
let (simulated_hardware_device_tx, simulated_hardware_host_rx) = mpsc::channel::<u8>();

*self.listening.lock().unwrap() = true;

let listening_clone_rx = self.listening.clone();
Expand All @@ -73,11 +73,17 @@ impl<const PACKET_SIZE: usize> Channel<PACKET_SIZE> for FlemSoftwareHost<PACKET_
let tx_handle = thread::spawn(move || {
while *listening_clone_tx.lock().unwrap() {
// Check if there is a packet to transmit, use recv_timeout to prevent a blocking thread
if let Ok(tx_packet) = packet_to_transmit.recv_timeout(Duration::from_millis(tx_sleep_time_ms)) {
if let Ok(tx_packet) =
packet_to_transmit.recv_timeout(Duration::from_millis(tx_sleep_time_ms))
{
// Send the packet one byte at a time
for byte in tx_packet.bytes() {
simulated_hardware_host_tx.send(*byte).unwrap();
}
println!(
"Raw packet from host to device in bytes: {:?}",
tx_packet.bytes()
);
println!("Host transmitted packet successfully");
}
}
Expand All @@ -88,32 +94,41 @@ impl<const PACKET_SIZE: usize> Channel<PACKET_SIZE> for FlemSoftwareHost<PACKET_
let simulated_device_thread = thread::spawn(move || {
let mut packet = flem::Packet::<PACKET_DEVICE_SIZE>::new();

while *listening_clone_device.lock().unwrap() {
while *listening_clone_device.lock().unwrap() {
// List for data on hardware
if let Ok(byte) = simulated_hardware_device_rx.recv_timeout(Duration::from_millis(10)) {
if let Ok(byte) =
simulated_hardware_device_rx.recv_timeout(Duration::from_millis(10))
{
match packet.construct(byte) {
Ok(_) => {
// Packet received
println!("Packet received on device successfully with checksum {}", packet.get_checksum());
println!(
"Packet received on device successfully with checksum {}",
packet.get_checksum()
);

if device_flem_handler.is_none() {
println!("Packet handler not set, working as a loop-back");
for byte in packet.bytes() {
simulated_hardware_device_tx.send(*byte).unwrap();
}
}else{
}
} else {
println!("Packet handler set, calling handler");
let handler = device_flem_handler.as_ref().unwrap();
let response = handler(&packet);
for byte in response.bytes() {
simulated_hardware_device_tx.send(*byte).unwrap();
}
}
println!(
"Raw packet from device to host in bytes: {:?}",
response.bytes()
);
}

println!("Packet sent from device successfully");

packet.reset_lazy();
},
packet.reset_lazy();
}
Err(error) => {
match error {
flem::Status::PacketBuilding => {
Expand All @@ -125,7 +140,7 @@ impl<const PACKET_SIZE: usize> Channel<PACKET_SIZE> for FlemSoftwareHost<PACKET_
}
}
}
}
}
}
}
});
Expand All @@ -136,17 +151,22 @@ impl<const PACKET_SIZE: usize> Channel<PACKET_SIZE> for FlemSoftwareHost<PACKET_

while *listening_clone_rx.lock().unwrap() {
// List for data on hardware
if let Ok(byte) = simulated_hardware_host_rx.recv_timeout(Duration::from_millis(rx_sleep_time_ms)) {
if let Ok(byte) =
simulated_hardware_host_rx.recv_timeout(Duration::from_millis(rx_sleep_time_ms))
{
match packet.construct(byte) {
Ok(_) => {
// Packet received
println!("Packet received successfully with checksum {}", packet.get_checksum());
println!(
"Packet received successfully with checksum {}",
packet.get_checksum()
);
validated_packet.send(packet);

println!("Packet sent to program");

packet.reset_lazy();
},
packet.reset_lazy();
}
Err(error) => {
match error {
flem::Status::PacketBuilding => {
Expand All @@ -158,7 +178,7 @@ impl<const PACKET_SIZE: usize> Channel<PACKET_SIZE> for FlemSoftwareHost<PACKET_
}
}
}
}
}
}
}
});
Expand Down Expand Up @@ -187,7 +207,7 @@ fn main() {
response.set_request(flem::request::ID);
response.set_response(flem::response::SUCCESS);
response.pack_id(&id, true);
},
}
_ => {
response.set_request(flem::request::ID);
response.set_response(flem::response::UNKNOWN_REQUEST);
Expand All @@ -211,23 +231,22 @@ fn main() {
tx.send(packet).unwrap();

loop {
if let Ok(packet) = rx.recv_timeout(Duration::from_millis(25))
{
if let Ok(packet) = rx.recv_timeout(Duration::from_millis(25)) {
println!("Received packet: {:?}", packet);

// Do stuff with the packet
// Do stuff with the packet
match packet.get_request() {
flem::request::ID => {
let id = DataId::from(&packet.get_data()).unwrap();
println!(
"DataId Message: {}, max packet size: {}, Major: {}, Minor: {}, Patch: {}",
"DataId Message: {}, max packet size: {}, Major: {}, Minor: {}, Patch: {}",
String::from_iter(id.get_name().iter()),
id.get_max_packet_size(),
id.get_major(),
id.get_minor(),
id.get_patch()
);
},
}
_ => {
// Unknown request
}
Expand All @@ -237,4 +256,4 @@ fn main() {
break;
}
}
}
}

0 comments on commit df0a007

Please sign in to comment.