pub fn apply<'a,In,Out,SM,Ins>
(sm: &'a mut SM, ins: Ins) -> impl 'a+Iterator<Item=Out>
where In: 'a,
Out: 'a,
SM: 'a+Push<In,Out>,
Ins: 'a+Iterator<Item=In>
{
ins.filter_map(move |i| sm.push(i))
}
pub trait Push<I,O> {
fn push(&mut self, I) -> Option<O>;
}
pub trait Bus {
fn channel(&self, usize) -> usize;
fn as_usize(&self) -> usize;
}
macro_rules! impl_Bus {
($t:ty) => (
impl Bus for $t {
#[inline(always)]
fn channel(&self, c:usize) -> usize {
(((*self) >> c) & 1 ) as usize
}
#[inline(always)]
fn as_usize(&self) -> usize {
(*self) as usize
}
});
}
impl_Bus!(u8);
impl_Bus!(usize);
impl_Bus!(i32);
impl<'a,T> Bus for &'a T where T: Bus {
#[inline(always)]
fn channel(&self, c:usize) -> usize { (*self).channel(c) }
fn as_usize(&self) -> usize { (*self).as_usize() }
}
pub mod diff {
use sm::Push;
use sm::Bus;
#[derive(Copy,Clone)]
pub struct State { last: usize, }
pub fn init() -> State {State{last: 0}}
impl<B> Push<B,usize> for State where B: Bus {
#[inline(always)]
fn push(&mut self, input_bus:B) -> Option<usize> {
let input = input_bus.as_usize();
let x = input ^ self.last;
self.last = input;
if x == 0 { None } else { Some(input) }
}
}
}
pub mod uart {
use sm::Push;
use self::Mode::*;
#[derive(Copy,Clone)]
pub struct Config {
pub period: usize,
pub nb_bits: usize,
pub channel: usize,
}
pub struct Uart {
pub config: Config,
state: State,
}
struct State {
reg: usize,
bit: usize,
skip: usize,
mode: Mode,
clocks: usize,
}
enum Mode {
Idle, Shift, Break, FrameErr,
}
pub fn init(config: Config) -> Uart {
Uart {
config: config,
state: State {
reg: 0,
bit: 0,
skip: 0,
mode: Idle,
clocks: 0,
},
}
}
#[inline(always)]
pub fn start_delay(period: usize) -> usize {
let p1 = period - 1;
p1 + (p1 >> 1) + (period >> 2)
}
impl<B> Push<B,usize> for Uart where B: super::Bus {
#[inline(always)]
fn push(&mut self, input :B) -> Option<usize> {
let s = &mut self.state;
let c = &self.config;
s.clocks += 1;
if s.skip > 0 {
s.skip -= 1;
return None;
}
let i = input.channel(c.channel);
match s.mode {
Idle => {
if i == 0 {
s.mode = Shift;
s.bit = 0;
s.skip = start_delay(c.period);
s.reg = 0;
}
return None;
},
Shift => {
if s.bit < c.nb_bits {
s.reg |= i << s.bit;
s.bit += 1;
s.skip = c.period - 1;
return None;
}
else {
s.skip = 0;
if i == 1 {
s.mode = Idle;
return Some(s.reg);
}
else {
eprintln!("FrameErr/Break 0x{:x}", s.reg);
s.mode = match s.reg {
0 => Break,
_ => FrameErr,
};
return None;
}
}
},
_ => {
if i == 1 { s.mode = Idle; }
return None;
}
}
}
}
}
pub mod syncser {
use sm::Push;
#[derive(Copy,Clone)]
pub struct Config {
pub clock_channel: usize,
pub data_channel: usize,
pub frame_channel: usize,
pub clock_edge: usize,
pub clock_polarity: usize,
pub frame_active: usize,
pub frame_timeout: usize,
pub nb_bits: usize,
pub frame_enable: bool,
pub timeout_enable: bool,
}
struct State {
clock_state: usize,
frame_state: usize,
shift_count: usize,
shift_reg: usize,
frame_timeout_state: usize,
}
pub struct SyncSer {
pub config: Config,
state: State,
}
pub fn config() -> Config {
Config {
clock_channel: 0,
data_channel: 1,
frame_channel: 0,
frame_enable: false,
clock_edge: 1,
clock_polarity: 0,
frame_active: 0,
frame_timeout: 0,
timeout_enable: false,
nb_bits: 8,
}
}
pub fn init(c: Config) -> SyncSer {
SyncSer {
config: c,
state: State {
clock_state: c.clock_polarity,
frame_state: !c.frame_active,
frame_timeout_state: 0,
shift_count: 0,
shift_reg: 0,
}
}
}
impl<B> Push<B,usize> for SyncSer where B: super::Bus {
#[inline(always)]
fn push(&mut self, input :B) -> Option<usize> {
let s = &mut self.state;
let c = &self.config;
let clock_bit = input.channel(c.clock_channel);
let frame_bit = input.channel(c.frame_channel);
let data_bit = input.channel(c.data_channel);
let mut rv = None;
if c.frame_enable {
if frame_bit != s.frame_state {
if frame_bit == c.frame_active {
s.shift_reg = 0;
s.shift_count = 0;
}
}
}
if c.timeout_enable {
if c.frame_timeout > 0 {
if s.frame_timeout_state == 0 {
s.shift_reg = 0;
s.shift_count = 0;
s.frame_timeout_state = c.frame_timeout;
}
else {
s.frame_timeout_state -= 1;
}
}
}
if !c.frame_enable || (frame_bit == c.frame_active) {
if clock_bit != s.clock_state {
if clock_bit == c.clock_edge {
s.shift_reg <<= 1;
s.shift_reg |= data_bit;
s.shift_count += 1;
if s.shift_count == c.nb_bits {
rv = Some(s.shift_reg);
s.shift_reg = 0;
s.shift_count = 0;
s.frame_timeout_state = c.frame_timeout;
}
}
}
}
s.clock_state = clock_bit;
s.frame_state = frame_bit;
return rv;
}
}
}
pub mod slip {
use sm::Push;
use sm::Bus;
use std::mem;
#[derive(Copy,Clone)]
pub struct Config {
pub end: u8,
pub esc: u8,
pub esc_end: u8,
pub esc_esc: u8,
}
pub struct State {
buf: Vec<u8>,
esc: bool,
}
pub struct Slip {
config: Config,
state: State,
}
pub fn init(c: Config) -> Slip {
Slip {
config: c,
state: State {
buf: Vec::new(),
esc: false,
}
}
}
impl<B> Push<B,Vec<u8>> for Slip where B: Bus {
#[inline(always)]
fn push(&mut self, input_bus:B) -> Option<Vec<u8>> {
let c = &self.config;
let s = &mut self.state;
let i = input_bus.as_usize() as u8;
if s.esc {
s.esc = false;
if c.esc_end == i { s.buf.push(c.end); }
else if c.esc_esc == i { s.buf.push(c.esc); }
return None;
}
if c.esc == i {
s.esc = true;
return None;
}
if c.end == i {
let packet = mem::replace(&mut s.buf, Vec::new());
return Some(packet);
}
s.buf.push(i);
return None;
}
}
pub fn print(v: Vec<u8>) {
print!("({}) -", v.len());
for e in v { print!(" {:01$x}", e, 2); }
println!("");
}
}