forked from M-Labs/artiq
grabber: add parser, report detected frame size in core device log
This commit is contained in:
parent
37e303dafc
commit
4f56710e4b
|
@ -1,6 +1,13 @@
|
||||||
use board_misoc::csr;
|
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 {
|
fn get_pll_reset(g: usize) -> bool {
|
||||||
unsafe { (csr::GRABBER[g].pll_reset_read)() != 0 }
|
unsafe { (csr::GRABBER[g].pll_reset_read)() != 0 }
|
||||||
|
@ -64,14 +71,25 @@ fn clock_align(g: usize) -> bool {
|
||||||
true
|
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() {
|
pub fn tick() {
|
||||||
for g in 0..csr::GRABBER.len() {
|
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) {
|
if !clock_pattern_ok(g) || !pll_locked(g) {
|
||||||
set_pll_reset(g, true);
|
set_pll_reset(g, true);
|
||||||
unsafe { GRABBER_UP[g] = false; }
|
unsafe { GRABBER_STATE[g] = State::Down; }
|
||||||
info!("grabber{} is down", g);
|
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 {
|
} else {
|
||||||
if get_pll_reset(g) {
|
if get_pll_reset(g) {
|
||||||
set_pll_reset(g, false);
|
set_pll_reset(g, false);
|
||||||
|
@ -80,7 +98,7 @@ pub fn tick() {
|
||||||
info!("grabber{} PLL is locked", g);
|
info!("grabber{} PLL is locked", g);
|
||||||
if clock_align(g) {
|
if clock_align(g) {
|
||||||
info!("grabber{} is up", g);
|
info!("grabber{} is up", g);
|
||||||
unsafe { GRABBER_UP[g] = true; }
|
unsafe { GRABBER_STATE[g] = State::WaitResolution; }
|
||||||
} else {
|
} else {
|
||||||
set_pll_reset(g, true);
|
set_pll_reset(g, true);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
]
|
|
@ -2,6 +2,7 @@ from migen import *
|
||||||
|
|
||||||
from artiq.gateware.rtio import rtlink
|
from artiq.gateware.rtio import rtlink
|
||||||
from artiq.gateware.grabber import deserializer_7series
|
from artiq.gateware.grabber import deserializer_7series
|
||||||
|
from artiq.gateware.grabber.core import *
|
||||||
|
|
||||||
|
|
||||||
class Grabber(Module):
|
class Grabber(Module):
|
||||||
|
@ -11,6 +12,8 @@ class Grabber(Module):
|
||||||
rtlink.IInterface(10))
|
rtlink.IInterface(10))
|
||||||
|
|
||||||
self.submodules.deserializer = deserializer_7series.Deserializer(pins)
|
self.submodules.deserializer = deserializer_7series.Deserializer(pins)
|
||||||
|
self.submodules.parser = Parser()
|
||||||
|
self.comb += self.parser.cl.eq(self.deserializer.q)
|
||||||
|
|
||||||
def get_csrs(self):
|
def get_csrs(self):
|
||||||
return self.deserializer.get_csrs()
|
return self.deserializer.get_csrs() + self.parser.get_csrs()
|
||||||
|
|
Loading…
Reference in New Issue