grabber: refactor state machine

This commit is contained in:
Robert Jördens 2018-08-07 17:27:36 +02:00
parent 6cd2432e30
commit f7678cc24a

View File

@ -1,14 +1,21 @@
use board_misoc::csr; use board_misoc::csr;
#[derive(PartialEq)] #[derive(PartialEq, Clone, Copy)]
enum State { enum State {
Down, Reset,
WaitResolution, ExitReset,
Up Lock,
Align,
Watch
} }
static mut GRABBER_STATE: [State; csr::GRABBER_LEN] = [State::Down; csr::GRABBER_LEN]; struct Info {
static mut GRABBER_RESOLUTION: [(u16, u16); csr::GRABBER_LEN] = [(0, 0); csr::GRABBER_LEN]; state: State,
frame_size: (u16, u16),
}
static mut INFO: [Info; csr::GRABBER_LEN] =
[Info { state: State::Reset, frame_size: (0, 0) }; csr::GRABBER_LEN];
fn get_pll_reset(g: usize) -> bool { fn get_pll_reset(g: usize) -> bool {
unsafe { (csr::GRABBER[g].pll_reset_read)() != 0 } unsafe { (csr::GRABBER[g].pll_reset_read)() != 0 }
@ -16,7 +23,7 @@ fn get_pll_reset(g: usize) -> bool {
fn set_pll_reset(g: usize, reset: bool) { fn set_pll_reset(g: usize, reset: bool) {
let val = if reset { 1 } else { 0 }; let val = if reset { 1 } else { 0 };
unsafe { (csr::GRABBER[g].pll_reset_write)(val) } unsafe { (csr::GRABBER[g].pll_reset_write)(val) }
} }
fn pll_locked(g: usize) -> bool { fn pll_locked(g: usize) -> bool {
@ -86,43 +93,62 @@ fn get_video_clock(g: usize) -> u32 {
pub fn tick() { pub fn tick() {
for g in 0..csr::GRABBER.len() { for g in 0..csr::GRABBER.len() {
if unsafe { GRABBER_STATE[g] != State::Down } { let next = match unsafe { INFO[g].state } {
if !clock_pattern_ok(g) || !pll_locked(g) { State::Reset => {
set_pll_reset(g, true); set_pll_reset(g, true);
unsafe { GRABBER_STATE[g] = State::Down; } unsafe { INFO[g].frame_size = (0, 0); }
info!("grabber{} is down", g); State::ExitReset
} }
if unsafe { GRABBER_STATE[g] == State::WaitResolution } { State::ExitReset => {
let last_xy = get_last_pixels(g); if get_pll_reset(g) {
unsafe { GRABBER_RESOLUTION[g] = last_xy; } set_pll_reset(g, false);
info!("grabber{} frame size: {}x{}", State::Lock
g, last_xy.0 + 1, last_xy.1 + 1); } else {
info!("grabber{} video clock: {}MHz", g, get_video_clock(g)); State::ExitReset
unsafe { GRABBER_STATE[g] = State::Up; }
} else {
let last_xy = get_last_pixels(g);
if unsafe { last_xy != GRABBER_RESOLUTION[g] } {
info!("grabber{} frame size: {}x{}",
g, last_xy.0 + 1, last_xy.1 + 1);
unsafe { GRABBER_RESOLUTION[g] = last_xy; }
} }
} }
} else { State::Lock => {
if get_pll_reset(g) { if pll_locked(g) {
set_pll_reset(g, false); info!("grabber{} locked: {}MHz", g, get_video_clock(g));
} else { State::Align
} else {
State::Lock
}
}
State::Align => {
if pll_locked(g) { if pll_locked(g) {
info!("grabber{} PLL is locked", g);
if clock_align(g) { if clock_align(g) {
info!("grabber{} is up", g); info!("grabber{} alignment success", g);
unsafe { GRABBER_STATE[g] = State::WaitResolution; } State::Watch
} else { } else {
set_pll_reset(g, true); info!("grabber{} alignment failure", g);
State::Reset
} }
} else { } else {
set_pll_reset(g, true); info!("grabber{} lock lost", g);
State::Reset
} }
} }
} State::Watch => {
if pll_locked(g) {
if clock_pattern_ok(g) {
let last_xy = get_last_pixels(g);
if last_xy != unsafe { INFO[g].frame_size } {
info!("grabber{} frame size: {}x{}",
g, last_xy.0 + 1, last_xy.1 + 1);
unsafe { INFO[g].frame_size = last_xy }
}
State::Watch
} else {
info!("grabber{} alignment lost", g);
State::Reset
}
} else {
info!("grabber{} lock lost", g);
State::Reset
}
}
};
unsafe { INFO[g].state = next; }
} }
} }