grabber: add parser, report detected frame size in core device log

pull/1104/merge
Sebastien Bourdeauducq 2018-07-10 02:06:37 +08:00
parent 37e303dafc
commit 4f56710e4b
3 changed files with 103 additions and 5 deletions

View File

@ -1,6 +1,13 @@
use board_misoc::csr;
static mut GRABBER_UP: &'static mut [bool] = &mut [false; csr::GRABBER_LEN];
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum State {
Down,
WaitResolution,
Up
}
static mut GRABBER_STATE: &'static mut [State] = &mut [State::Down; csr::GRABBER_LEN];
fn get_pll_reset(g: usize) -> bool {
unsafe { (csr::GRABBER[g].pll_reset_read)() != 0 }
@ -64,14 +71,25 @@ fn clock_align(g: usize) -> bool {
true
}
fn get_last_pixels(g: usize) -> (u16, u16) {
unsafe { ((csr::GRABBER[g].last_x_read)(),
(csr::GRABBER[g].last_y_read)()) }
}
pub fn tick() {
for g in 0..csr::GRABBER.len() {
if unsafe { GRABBER_UP[g] } {
if unsafe { GRABBER_STATE[g] != State::Down } {
if !clock_pattern_ok(g) || !pll_locked(g) {
set_pll_reset(g, true);
unsafe { GRABBER_UP[g] = false; }
unsafe { GRABBER_STATE[g] = State::Down; }
info!("grabber{} is down", g);
}
if unsafe { GRABBER_STATE[g] == State::WaitResolution } {
let (last_x, last_y) = get_last_pixels(g);
info!("grabber{} detected frame size: {}x{}",
g, last_x + 1, last_y + 1);
unsafe { GRABBER_STATE[g] = State::Up; }
}
} else {
if get_pll_reset(g) {
set_pll_reset(g, false);
@ -80,7 +98,7 @@ pub fn tick() {
info!("grabber{} PLL is locked", g);
if clock_align(g) {
info!("grabber{} is up", g);
unsafe { GRABBER_UP[g] = true; }
unsafe { GRABBER_STATE[g] = State::WaitResolution; }
} else {
set_pll_reset(g, true);
}

View File

@ -0,0 +1,77 @@
from migen import *
from migen.genlib.cdc import MultiReg
from misoc.interconnect.csr import *
bitseq = [
# 0 1 2 3 4 5 6
6, 5, 4, 3, 2, 1, 27,
# 7 8 9 10 11 12 13
26, 0, 13, 12, 11, 10, 9,
# 14 15 16 17 18 19 20
25, 24, 8, 7, 20, 19, 18,
# 21 22 23
17, 23, 22
]
assert len(set(bitseq)) == 24
class Parser(Module, AutoCSR):
"""Parses 28 bit encoded words and track pixel coordinates."""
def __init__(self, width=12):
self.cl = cl = Signal(28)
self.last_x = CSRStatus(width)
self.last_y = CSRStatus(width)
self.pix = pix = Record([
("x", width),
("y", width),
("a", 8),
("b", 8),
("c", 8),
("stb", 1), # dval
("eop", 1), # ~fval (i.e. not together with stb)
])
# # #
last_x = Signal(width)
last_y = Signal(width)
lval = Signal()
fval = Signal()
dval = Signal()
self.comb += [
Cat(dval, fval, lval).eq(cl[14:17]),
pix.stb.eq(dval),
pix.eop.eq(~fval),
Cat(pix.a, pix.b, pix.c).eq(Cat(cl[i] for i in bitseq))
]
last_lval = Signal()
last_fval = Signal()
self.sync.cl += [
last_lval.eq(lval),
last_fval.eq(fval),
pix.x.eq(pix.x + 1),
If(~lval,
pix.x.eq(0),
If(last_lval, last_x.eq(pix.x)),
If(last_fval & last_lval,
pix.y.eq(pix.y + 1)
)
),
If(~fval,
If(last_fval, last_y.eq(pix.y)),
pix.y.eq(0)
)
]
self.specials += [
MultiReg(last_x, self.last_x.status),
MultiReg(last_y, self.last_y.status)
]

View File

@ -2,6 +2,7 @@ from migen import *
from artiq.gateware.rtio import rtlink
from artiq.gateware.grabber import deserializer_7series
from artiq.gateware.grabber.core import *
class Grabber(Module):
@ -11,6 +12,8 @@ class Grabber(Module):
rtlink.IInterface(10))
self.submodules.deserializer = deserializer_7series.Deserializer(pins)
self.submodules.parser = Parser()
self.comb += self.parser.cl.eq(self.deserializer.q)
def get_csrs(self):
return self.deserializer.get_csrs()
return self.deserializer.get_csrs() + self.parser.get_csrs()