-
Notifications
You must be signed in to change notification settings - Fork 9
Expand file tree
/
Copy pathmod.rs
More file actions
131 lines (122 loc) · 3.41 KB
/
mod.rs
File metadata and controls
131 lines (122 loc) · 3.41 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
use core::cell::RefCell;
use critical_section::Mutex;
use rp2040_hal::{
self as hal,
gpio::{
bank0::{Gpio0, Gpio1, Gpio2, Gpio3},
FunctionI2C, FunctionNull, Pin, PullUp,
},
i2c::peripheral::Event,
};
pub mod blocking;
pub mod non_blocking;
pub const ADDR_7BIT: u8 = 0x2c;
pub const ADDR_10BIT: u16 = 0x12c;
type P<T, U> = (Pin<T, FunctionI2C, PullUp>, Pin<U, FunctionI2C, PullUp>);
pub type Target = hal::I2C<hal::pac::I2C1, P<Gpio2, Gpio3>, hal::i2c::Peripheral>;
pub type Controller<'a> = i2c_pio::I2C<'a, hal::pac::PIO0, hal::pio::SM0, CtrlPinSda, CtrlPinScl>;
pub type CtrlPinSda = Pin<Gpio0, FunctionNull, PullUp>;
pub type CtrlPinScl = Pin<Gpio1, FunctionNull, PullUp>;
type MutexCell<T> = Mutex<RefCell<T>>;
type FIFOBuffer = heapless::Vec<u8, 128>;
#[derive(Debug, defmt::Format, Default)]
pub struct TargetState {
first: bool,
gen: Generator,
vec: FIFOBuffer,
restart_cnt: u32,
stop_cnt: u32,
}
impl TargetState {
pub const fn new() -> TargetState {
TargetState {
first: true,
gen: Generator::fib(),
vec: FIFOBuffer::new(),
restart_cnt: 0,
stop_cnt: 0,
}
}
}
#[derive(Debug, defmt::Format, Clone, Copy)]
pub enum Generator {
Sequence(u8),
Fibonacci(u8, u8),
}
impl Generator {
const fn fib() -> Generator {
Generator::Fibonacci(0, 1)
}
const fn seq() -> Generator {
Generator::Sequence(0)
}
fn switch(&mut self) {
*self = if matches!(self, Generator::Sequence(_)) {
Generator::Fibonacci(0, 1)
} else {
Generator::Sequence(0)
};
}
}
impl Default for Generator {
fn default() -> Self {
Generator::Sequence(0)
}
}
impl Iterator for Generator {
type Item = u8;
fn next(&mut self) -> Option<Self::Item> {
let out;
match self {
Generator::Sequence(prev) => {
(out, *prev) = (*prev, prev.wrapping_add(1));
}
Generator::Fibonacci(a, b) => {
out = *a;
(*a, *b) = (*b, a.wrapping_add(*b));
}
}
Some(out)
}
}
fn target_handler(
target: &mut Target,
evt: rp2040_hal::i2c::peripheral::Event,
payload: &mut TargetState,
throttle: bool,
) {
let TargetState {
first,
gen,
vec,
restart_cnt,
stop_cnt,
} = payload;
match evt {
Event::Start => *first = true,
Event::Restart => *restart_cnt += 1,
Event::TransferRead => {
let n = throttle.then_some(1).unwrap_or(target.tx_fifo_available());
let v: FIFOBuffer = gen.take(n.into()).collect();
target.write(&v);
}
Event::TransferWrite => {
if *first {
gen.switch();
*first = false;
}
// when throttling, treat 1 byte at a time
let max = throttle
.then_some(1)
.unwrap_or_else(|| target.rx_fifo_used().into());
vec.extend(target.take(max));
}
Event::Stop => {
*stop_cnt += 1;
// notify the other core a stop was detected
cortex_m::asm::sev();
}
}
}
pub trait ValidAddress: i2c_pio::ValidAddressMode + rp2040_hal::i2c::ValidAddress {}
impl<T> ValidAddress for T where T: rp2040_hal::i2c::ValidAddress + i2c_pio::ValidAddressMode {}