Skip to content

Commit

Permalink
Add Peak CAN driver
Browse files Browse the repository at this point in the history
builds, driver works, no functional test (no pcan available)

---------

Co-authored-by: Jannes Brands <jannes@jannesbrands.de>
Co-authored-by: Austin Gill <notgnoshi@gmail.com>
  • Loading branch information
Jannes Brands and Notgnoshi committed Nov 7, 2023
1 parent 6ea2476 commit eec1282
Show file tree
Hide file tree
Showing 5 changed files with 451 additions and 11 deletions.
6 changes: 5 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,14 @@ keywords = ["agriculture", "can", "canbus", "isobus", "j1939", "agritech", "smar

[dependencies]
rand = "0.8.5"
pcan-basic = { version = "1.0.2", optional = true }
socketcan = { version = "2.0.0", optional = true }
tracing = { version = "0.1.37", optional = true }

[features]
default = []
# Peak driver
peak = ["dep:pcan-basic"]
# Socketcan driver
socketcan = ["dep:socketcan"]
# Optional logging instrumentation
Expand All @@ -21,8 +24,9 @@ tracing = ["dep:tracing"]
[dev-dependencies]
clap = { version = "4.3.19", features = ["derive"] }
ctrlc = "3.4.0"
tracing = "0.1.37"
tracing-subscriber = "0.3.17"

[[example]]
name = "forward"
required-features = ["socketcan", "tracing"]
required-features = ["tracing"]
73 changes: 64 additions & 9 deletions examples/forward.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,46 @@

use std::sync::mpsc::channel;

use ag_iso_stack::driver::{Driver, Frame, SocketcanDriver};
#[cfg(feature = "peak")]
use ag_iso_stack::driver::PeakDriver;
#[cfg(feature = "socketcan")]
use ag_iso_stack::driver::SocketcanDriver;
use ag_iso_stack::driver::{Driver, Frame};
use ag_iso_stack::tracing;
use clap::Parser;
use clap::{Parser, ValueEnum};
#[cfg(feature = "peak")]
use pcan_basic::bus::UsbBus;

fn parse_usb_bus(s: &str) -> Option<UsbBus> {
let s = s.to_uppercase();
match s.as_str() {
"USB1" => Some(UsbBus::USB1),
"USB2" => Some(UsbBus::USB2),
"USB3" => Some(UsbBus::USB3),
"USB4" => Some(UsbBus::USB4),
"USB5" => Some(UsbBus::USB5),
"USB6" => Some(UsbBus::USB6),
"USB7" => Some(UsbBus::USB7),
"USB8" => Some(UsbBus::USB8),
"USB9" => Some(UsbBus::USB9),
"USB10" => Some(UsbBus::USB10),
"USB11" => Some(UsbBus::USB11),
"USB12" => Some(UsbBus::USB12),
"USB13" => Some(UsbBus::USB13),
"USB14" => Some(UsbBus::USB14),
"USB15" => Some(UsbBus::USB15),
"USB16" => Some(UsbBus::USB16),
_ => None,
}
}

#[derive(Debug, Clone, ValueEnum)]
enum CanDriver {
#[cfg(feature = "socketcan")]
Socketcan,
#[cfg(feature = "peak")]
Pcan,
}

/// Forward CAN traffic from one interface to another
#[derive(Debug, Parser)]
Expand All @@ -25,13 +62,29 @@ struct Options {
/// Can be either a string interface name, or an integer interface index
#[clap(short, long, default_value_t = String::from("can1"))]
pub output_interface: String,

#[clap(short, long)]
pub driver: CanDriver,
}

fn create_driver(iface: &str) -> impl Driver {
if let Ok(index) = iface.parse::<u32>() {
SocketcanDriver::new_by_index(index)
} else {
SocketcanDriver::new_by_name(iface)
fn create_driver(iface: &str, driver: CanDriver) -> Box<dyn Driver> {
match driver {
#[cfg(feature = "socketcan")]
CanDriver::Socketcan => {
if let Ok(index) = iface.parse::<u32>() {
Box::new(SocketcanDriver::new_by_index(index))
} else {
Box::new(SocketcanDriver::new_by_name(iface))
}
}
#[cfg(feature = "peak")]
CanDriver::Pcan => {
let bus = parse_usb_bus(iface).unwrap();
let baud = ag_iso_stack::driver::Baudrate::Baud250K;
Box::new(PeakDriver::new_usb(bus, baud))
}
#[allow(unreachable_patterns)]
_ => unreachable!(),
}
}

Expand All @@ -45,14 +98,16 @@ fn main() {
.map_err(|_err| eprintln!("Unable to set global default subscriber"))
.unwrap();

tracing::info!("AgIsoStack-rs example starts...");

tracing::info!(
"Forwarding CAN traffic from {} to {}",
opts.input_interface,
opts.output_interface
);

let mut input = create_driver(&opts.input_interface);
let mut output = create_driver(&opts.output_interface);
let mut input = create_driver(&opts.input_interface, opts.driver.clone());
let mut output = create_driver(&opts.output_interface, opts.driver);

input.open().unwrap();
output.open().unwrap();
Expand Down
18 changes: 18 additions & 0 deletions src/driver/driver.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,24 @@
// Copyright 2023 Raven Industries inc.
use crate::driver::Frame;

#[derive(Debug, PartialEq, Copy, Clone)]
pub enum Baudrate {
Baud1M,
Baud800K,
Baud500K,
Baud250K,
Baud125K,
Baud100K,
Baud95K,
Baud83K,
Baud50K,
Baud47K,
Baud33K,
Baud20K,
Baud10K,
Baud5K,
}

#[derive(Debug)]
#[non_exhaustive]
pub enum DriverOpenError {
Expand Down
8 changes: 7 additions & 1 deletion src/driver/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,17 @@ mod pgn;
#[cfg(feature = "socketcan")]
mod socketcan;

#[cfg(feature = "peak")]
mod peak;

pub use address::Address;
pub use can_id::{CanId, Priority, Type};
pub use driver::{Driver, DriverCloseError, DriverOpenError, DriverReadError, DriverWriteError};
pub use driver::{Baudrate, Driver, DriverCloseError, DriverOpenError, DriverReadError, DriverWriteError};
pub use frame::{Channel, Frame};
pub use pgn::Pgn;

#[cfg(feature = "socketcan")]
pub use self::socketcan::SocketcanDriver;

#[cfg(feature = "peak")]
pub use self::peak::PeakDriver;
Loading

0 comments on commit eec1282

Please sign in to comment.