#![cfg_attr(not(feature = "std"), no_std)]
mod lib {
#[cfg(feature = "std")]
pub use std::*;
#[cfg(not(feature = "std"))]
pub use core::*;
}
extern crate interior_mut;
#[cfg(feature = "socketcan")]
extern crate socketcan;
#[cfg(feature = "socketcan")]
mod socketcan_impl;
mod instructions;
#[macro_use]
mod axis_parameters;
pub mod modules;
pub use instructions::Instruction;
use instructions::Return;
pub trait Interface {
type Error;
fn transmit_command<T: Instruction>(&mut self, command: &Command<T>) -> Result<(), Self::Error>;
fn receive_reply(&mut self) -> Result<Reply, Self::Error>;
}
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum Error<T> {
InterfaceUnavailable,
InterfaceError(T),
ProtocolError(ErrStatus),
}
#[derive(Debug, PartialEq)]
pub struct Command<T: Instruction> {
module_address: u8,
instruction: T,
}
#[derive(Debug, PartialEq, Clone)]
pub struct Reply {
reply_address: u8,
module_address: u8,
status: Status,
command_number: u8,
operand: [u8; 4],
}
pub trait AxisParameter {
const NUMBER: u8;
}
pub trait ReadableAxisParameter: AxisParameter + Return {}
pub trait WriteableAxisParameter: AxisParameter {
fn operand(&self) -> [u8; 4];
}
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum OkStatus {
Ok = 100,
LoadedIntoEEPROM = 101,
}
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum ErrStatus {
WrongChecksum = 1,
InvalidCommand = 2,
WrongType = 3,
InvalidValue = 4,
EEPROMLocked = 5,
CommandNotAvailable = 6,
}
#[must_use]
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum Status {
Ok(OkStatus),
Err(ErrStatus),
}
impl<T: Instruction> Command<T> {
pub fn new(module_address: u8, instruction: T) -> Command<T> {
Command{module_address, instruction}
}
pub fn module_address(&self) -> u8 {
self.module_address
}
pub fn serialize(&self) -> [u8; 9] {
unimplemented!()
}
pub fn serialize_i2c(&self) -> [u8; 8] {
unimplemented!()
}
pub fn serialize_can(&self) -> [u8; 7] {
[
T::INSTRUCTION_NUMBER,
self.instruction.type_number(),
self.instruction.motor_bank_number(),
self.instruction.operand()[3],
self.instruction.operand()[2],
self.instruction.operand()[1],
self.instruction.operand()[0],
]
}
}
impl Reply {
pub fn new(
reply_address: u8,
module_address: u8,
status: Status,
command_number: u8,
operand: [u8; 4],
) -> Self {
Reply {
reply_address,
module_address,
status,
command_number,
operand,
}
}
fn operand(&self) -> [u8; 4] {
self.operand
}
fn status(&self) -> Status {
self.status
}
}
impl Status {
pub fn try_from_u8(id: u8) -> Result<Status, NonValidErrorCode> {
match id {
100 => Ok(Status::Ok(OkStatus::Ok)),
101 => Ok(Status::Ok(OkStatus::LoadedIntoEEPROM)),
1 => Ok(Status::Err(ErrStatus::WrongChecksum)),
2 => Ok(Status::Err(ErrStatus::InvalidCommand)),
3 => Ok(Status::Err(ErrStatus::WrongType)),
4 => Ok(Status::Err(ErrStatus::InvalidValue)),
5 => Ok(Status::Err(ErrStatus::EEPROMLocked)),
6 => Ok(Status::Err(ErrStatus::CommandNotAvailable)),
_ => Err(NonValidErrorCode),
}
}
}
#[derive(Debug)]
pub struct NonValidErrorCode;
impl Return for () {
fn from_operand(_operand: [u8; 4]) -> () {()}
}
impl Return for [u8; 4] {
fn from_operand(array: [u8; 4]) -> [u8; 4] {
array
}
}
impl Return for bool {
fn from_operand(array: [u8; 4]) -> bool {(array[0] & 1) != 0}
}
impl Return for i32 {
fn from_operand(array: [u8; 4]) -> i32 {
(array[0] as u32 | ((array[1] as u32) << 8) | ((array[2] as u32) << 16) |((array[3] as u32) << 24)) as i32
}
}
impl Return for i16 {
fn from_operand(array: [u8; 4]) -> i16 {
(array[0] as u16 | ((array[1] as u16) << 8)) as i16
}
}
impl Return for i8 {
fn from_operand(array: [u8; 4]) -> i8 {
array[0] as i8
}
}
impl Return for u32 {
fn from_operand(array: [u8; 4]) -> u32 {
(array[0] as u32 | ((array[1] as u32) << 8) | ((array[2] as u32) << 16) |((array[3] as u32) << 24))
}
}
impl Return for u16 {
fn from_operand(array: [u8; 4]) -> u16 {
array[0] as u16 | ((array[1] as u16) << 8)
}
}
impl Return for u8 {
fn from_operand(array: [u8; 4]) -> u8 {
array[0]
}
}
impl<T> From<ErrStatus> for Error<T> {
fn from(es: ErrStatus) -> Self {
Error::ProtocolError(es)
}
}