Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add generic parameters to Transmit and Receive #12

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 19 additions & 15 deletions src/blocking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use structopt::StructOpt;
use crate::std::string::ToString;

use crate::{Transmit, Receive, State};
use crate::params::Param;

/// BlockingOptions for blocking radio functions
#[derive(Clone, PartialEq, Debug)]
Expand Down Expand Up @@ -60,6 +61,7 @@ impl <E> From<E> for BlockingError<E> {
# use radio::*;
# use radio::mock::*;
use radio::blocking::{BlockingTransmit, BlockingOptions};
use radio::params::Basic;

# let mut radio = MockRadio::new(&[
# Transaction::start_transmit(vec![0xaa, 0xbb], None),
Expand All @@ -69,26 +71,26 @@ use radio::blocking::{BlockingTransmit, BlockingOptions};
# ]);
#
// Transmit using a blocking call
let res = radio.do_transmit(&[0xaa, 0xbb], BlockingOptions::default());
let res = radio.do_transmit(&[0xaa, 0xbb], &Basic, BlockingOptions::default());

assert_eq!(res, Ok(()));

# radio.done();
```
"##)]
///
pub trait BlockingTransmit<E> {
fn do_transmit(&mut self, data: &[u8], tx_options: BlockingOptions) -> Result<(), BlockingError<E>>;
pub trait BlockingTransmit<P, E> {
fn do_transmit(&mut self, data: &[u8], params: &P, tx_options: BlockingOptions) -> Result<(), BlockingError<E>>;
}

impl <T, E> BlockingTransmit<E> for T
impl <T, P, E> BlockingTransmit<P, E> for T
where
T: Transmit<Error = E> + DelayUs<u32>,
T: Transmit<P, Error = E> + DelayUs<u32>,
E: core::fmt::Debug,
{
fn do_transmit(&mut self, data: &[u8], tx_options: BlockingOptions) -> Result<(), BlockingError<E>> {
fn do_transmit(&mut self, data: &[u8], params: &P, tx_options: BlockingOptions) -> Result<(), BlockingError<E>> {
// Enter transmit mode
self.start_transmit(data)?;
self.start_transmit(data, params)?;

let t = tx_options.timeout.as_micros();
let mut c = 0;
Expand Down Expand Up @@ -121,6 +123,7 @@ where
# use radio::*;
# use radio::mock::*;
use radio::blocking::{BlockingReceive, BlockingOptions};
use radio::params::Basic;

let data = [0xaa, 0xbb];
let info = BasicInfo::new(-81, 0);
Expand All @@ -136,10 +139,11 @@ let info = BasicInfo::new(-81, 0);
#

let mut buff = [0u8; 128];
let params = Basic;
let mut i = BasicInfo::new(0, 0);

// Receive using a blocking call
let res = radio.do_receive(&mut buff, &mut i, BlockingOptions::default());
let res = radio.do_receive(&mut buff, &params, &mut i, BlockingOptions::default());

assert_eq!(res, Ok(data.len()));
assert_eq!(&buff[..data.len()], &data);
Expand All @@ -148,19 +152,19 @@ assert_eq!(&buff[..data.len()], &data);
```
"##)]
///
pub trait BlockingReceive<I, E> {
fn do_receive(&mut self, buff: &mut [u8], info: &mut I, rx_options: BlockingOptions) -> Result<usize, BlockingError<E>>;
pub trait BlockingReceive<P: Param, E> {
fn do_receive(&mut self, buff: &mut [u8], params: &P, info: &mut P::Info, rx_options: BlockingOptions) -> Result<usize, BlockingError<E>>;
}

impl <T, I, E> BlockingReceive<I, E> for T
impl <T, P, E> BlockingReceive<P, E> for T
where
T: Receive<Info=I, Error=E> + DelayUs<u32>,
I: core::fmt::Debug,
T: Receive<P, Error=E> + DelayUs<u32>,
P: Param,
E: core::fmt::Debug,
{
fn do_receive(&mut self, buff: &mut [u8], info: &mut I, rx_options: BlockingOptions) -> Result<usize, BlockingError<E>> {
fn do_receive(&mut self, buff: &mut [u8], params: &P, info: &mut P::Info, rx_options: BlockingOptions) -> Result<usize, BlockingError<E>> {
// Start receive mode
self.start_receive()?;
self.start_receive(params)?;

let t = rx_options.timeout.as_micros();
let mut c = 0;
Expand Down
105 changes: 54 additions & 51 deletions src/helpers.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
//! Provides common helpers for implementing radio utilities
//!
//!
//! ## https://github.com/ryankurte/rust-radio
//! ## Copyright 2020 Ryan Kurte

use structopt::StructOpt;
use humantime::{Duration as HumanDuration};
use embedded_hal::blocking::delay::DelayUs;
use embedded_hal::delay::blocking::DelayUs;

extern crate std;
use std::prelude::v1::*;
Expand All @@ -22,6 +22,7 @@ use rolling_stats::Stats;

use crate::{Transmit, Receive, ReceiveInfo, Power, Rssi};
use crate::blocking::*;
use crate::params::Param;


/// Basic operations supported by the helpers package
Expand All @@ -48,25 +49,26 @@ pub enum Operation {
LinkTest(PingPongOptions),
}

pub fn do_operation<T, I, E>(radio: &mut T, operation: Operation) -> Result<(), BlockingError<E>>
pub fn do_operation<T, P, E>(radio: &mut T, operation: Operation, params: &P) -> Result<(), BlockingError<E>>
where
T: Transmit<Error=E> + Power<Error=E> + Receive<Info=I, Error=E> + Rssi<Error=E> + Power<Error=E> + DelayUs<u32, Error=E>,
I: ReceiveInfo + Default + std::fmt::Debug,
T: Transmit<P, Error=E> + Power<Error=E> + Receive<P, Error=E> + Rssi<Error=E> + Power<Error=E> + DelayUs<u32, Error=E>,
P: Param,
P::Info: Default,
E: std::fmt::Debug,
{
let mut buff = [0u8; 1024];
let mut info = I::default();
let mut info = P::Info::default();

// TODO: the rest
match operation {
Operation::Transmit(options) => do_transmit(radio, options)?,
Operation::Receive(options) => do_receive(radio, &mut buff, &mut info, options).map(|_| ())?,
Operation::Echo(options) => do_echo(radio, &mut buff, &mut info, options).map(|_| ())?,
Operation::Rssi(options) => do_rssi(radio, options).map(|_| ())?,
Operation::LinkTest(options) => do_ping_pong(radio, options).map(|_| ())?,
Operation::Transmit(options) => do_transmit(radio, params, options)?,
Operation::Receive(options) => do_receive(radio, &mut buff, params, &mut info, options).map(|_| ())?,
Operation::Echo(options) => do_echo(radio, &mut buff, params, &mut info, options).map(|_| ())?,
Operation::Rssi(options) => do_rssi(radio, params, options).map(|_| ())?,
Operation::LinkTest(options) => do_ping_pong(radio, params, options).map(|_| ())?,
//_ => warn!("unsuppored command: {:?}", opts.command),
}

Ok(())
}

Expand All @@ -89,9 +91,9 @@ pub struct TransmitOptions {
pub blocking_options: BlockingOptions,
}

pub fn do_transmit<T, E>(radio: &mut T, options: TransmitOptions) -> Result<(), BlockingError<E>>
pub fn do_transmit<T, P, E>(radio: &mut T, params: &P, options: TransmitOptions) -> Result<(), BlockingError<E>>
where
T: Transmit<Error=E> + Power<Error=E> + DelayUs<u32, Error=E>,
T: Transmit<P, Error=E> + Power<Error=E> + DelayUs<u32, Error=E>,
E: core::fmt::Debug,
{
// Set output power if specified
Expand All @@ -101,11 +103,11 @@ where

loop {
// Transmit packet
radio.do_transmit(&options.data, options.blocking_options.clone())?;
radio.do_transmit(&options.data, params, options.blocking_options.clone())?;

// Delay for repeated transmission or exit
match &options.period {
Some(p) => radio.try_delay_us(p.as_micros() as u32).unwrap(),
Some(p) => radio.delay_us(p.as_micros() as u32).unwrap(),
None => break,
}
}
Expand Down Expand Up @@ -154,28 +156,28 @@ impl PcapOptions {
(None, Some(pipe)) => {
// Ensure file doesn't already exist
let _ = std::fs::remove_file(pipe);

// Create pipe
let n = CString::new(pipe.as_str()).unwrap();
let status = unsafe { libc::mkfifo(n.as_ptr(), 0o644) };

// Manual status code handling
// TODO: return io::Error
if status != 0 {
panic!("Error creating fifo: {}", status);
}

// Open pipe
let f = OpenOptions::new()
.write(true)
.open(pipe)
.expect("Error opening PCAP pipe");

Some(f)
}

(None, None) => None,

_ => unimplemented!()
};

Expand All @@ -201,17 +203,17 @@ impl PcapOptions {
}

/// Receive from the radio using the provided configuration
pub fn do_receive<T, I, E>(radio: &mut T, mut buff: &mut [u8], mut info: &mut I, options: ReceiveOptions) -> Result<usize, E>
pub fn do_receive<T, P, E>(radio: &mut T, mut buff: &mut [u8], params: &P, mut info: &mut P::Info, options: ReceiveOptions) -> Result<usize, E>
where
T: Receive<Info=I, Error=E> + DelayUs<u32, Error=E>,
I: std::fmt::Debug,
T: Receive<P, Error=E> + DelayUs<u32, Error=E>,
P: Param,
E: std::fmt::Debug,
{
// Create and open pcap file for writing
let mut pcap_writer = options.pcap_options.open().expect("Error opening pcap file / pipe");

// Start receive mode
radio.start_receive()?;
radio.start_receive(params)?;

loop {
if radio.check_receive(true)? {
Expand All @@ -224,18 +226,18 @@ where

if let Some(p) = &mut pcap_writer {
let t = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap();

p.write(t.as_secs() as u32, t.as_nanos() as u32 % 1_000_000, &buff[0..n], n as u32).expect("Error writing pcap file");
}
if !options.continuous {

if !options.continuous {
return Ok(n)
}

radio.start_receive()?;
radio.start_receive(params)?;
}

radio.try_delay_us(options.blocking_options.poll_interval.as_micros() as u32).unwrap();
radio.delay_us(options.blocking_options.poll_interval.as_micros() as u32).unwrap();
}
}

Expand All @@ -251,14 +253,14 @@ pub struct RssiOptions {
pub continuous: bool,
}

pub fn do_rssi<T, I, E>(radio: &mut T, options: RssiOptions) -> Result<(), E>
pub fn do_rssi<T, P, E>(radio: &mut T, params: &P, options: RssiOptions) -> Result<(), E>
where
T: Receive<Info=I, Error=E> + Rssi<Error=E> + DelayUs<u32, Error=E>,
I: std::fmt::Debug,
T: Receive<P, Error=E> + Rssi<Error=E> + DelayUs<u32, Error=E>,
P: Param,
E: std::fmt::Debug,
{
// Enter receive mode
radio.start_receive()?;
radio.start_receive(params)?;

// Poll for RSSI
loop {
Expand All @@ -268,7 +270,7 @@ where

radio.check_receive(true)?;

radio.try_delay_us(options.period.as_micros() as u32).unwrap();
radio.delay_us(options.period.as_micros() as u32).unwrap();

if !options.continuous {
break
Expand All @@ -284,7 +286,7 @@ pub struct EchoOptions {
/// Run continuously
#[structopt(long = "continuous")]
pub continuous: bool,

/// Power in dBm (range -18dBm to 13dBm)
#[structopt(long = "power")]
pub power: Option<i8>,
Expand All @@ -302,10 +304,10 @@ pub struct EchoOptions {
}


pub fn do_echo<T, I, E>(radio: &mut T, mut buff: &mut [u8], mut info: &mut I, options: EchoOptions) -> Result<usize, BlockingError<E>>
pub fn do_echo<T, P, E>(radio: &mut T, mut buff: &mut [u8], params: &P, mut info: &mut P::Info, options: EchoOptions) -> Result<usize, BlockingError<E>>
where
T: Receive<Info=I, Error=E> + Transmit<Error=E> + Power<Error=E> + DelayUs<u32, Error=E>,
I: ReceiveInfo + std::fmt::Debug,
T: Receive<P, Error=E> + Transmit<P, Error=E> + Power<Error=E> + DelayUs<u32, Error=E>,
P: Param,
E: std::fmt::Debug,
{
// Set output power if specified
Expand All @@ -314,7 +316,7 @@ where
}

// Start receive mode
radio.start_receive()?;
radio.start_receive(params)?;

loop {
if radio.check_receive(true)? {
Expand All @@ -334,17 +336,17 @@ where
}

// Wait for turnaround delay
radio.try_delay_us(options.delay.as_micros() as u32).unwrap();
radio.delay_us(options.delay.as_micros() as u32).unwrap();

// Transmit respobnse
radio.do_transmit(&buff[..n], options.blocking_options.clone())?;
radio.do_transmit(&buff[..n], params, options.blocking_options.clone())?;

// Exit if non-continuous
if !options.continuous { return Ok(n) }
}

// Wait for poll delay
radio.try_delay_us(options.blocking_options.poll_interval.as_micros() as u32).unwrap();
radio.delay_us(options.blocking_options.poll_interval.as_micros() as u32).unwrap();
}
}

Expand Down Expand Up @@ -381,10 +383,11 @@ pub struct LinkTestInfo {
}


pub fn do_ping_pong<T, I, E>(radio: &mut T, options: PingPongOptions) -> Result<LinkTestInfo, BlockingError<E>>
pub fn do_ping_pong<T, P, E>(radio: &mut T, params: &P, options: PingPongOptions) -> Result<LinkTestInfo, BlockingError<E>>
where
T: Receive<Info=I, Error=E> + Transmit<Error=E> + Power<Error=E> + DelayUs<u32, Error=E>,
I: ReceiveInfo + Default + std::fmt::Debug,
T: Receive<P, Error=E> + Transmit<P, Error=E> + Power<Error=E> + DelayUs<u32, Error=E>,
P: Param,
P::Info: Default,
E: std::fmt::Debug,
{
let mut link_info = LinkTestInfo{
Expand All @@ -394,7 +397,7 @@ where
remote_rssi: Stats::new(),
};

let mut info = I::default();
let mut info = P::Info::default();
let mut buff = [0u8; 32];

// Set output power if specified
Expand All @@ -410,10 +413,10 @@ where
debug!("Sending message {}", i);

// Send message
radio.do_transmit(&buff[0..n], options.blocking_options.clone())?;
radio.do_transmit(&buff[0..n], params, options.blocking_options.clone())?;

// Await response
let n = match radio.do_receive(&mut buff, &mut info, options.blocking_options.clone()) {
let n = match radio.do_receive(&mut buff, params, &mut info, options.blocking_options.clone()) {
Ok(n) => n,
Err(BlockingError::Timeout) => {
debug!("Timeout awaiting response {}", i);
Expand Down Expand Up @@ -443,7 +446,7 @@ where
}

// Wait for send delay
radio.try_delay_us(options.delay.as_micros() as u32).unwrap();
radio.delay_us(options.delay.as_micros() as u32).unwrap();
}

Ok(link_info)
Expand Down
Loading