Compare commits
3 commits
bc82d2658f
...
4c36c00e64
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4c36c00e64 | ||
|
|
a88421a781 | ||
|
|
3f9a100e7c |
6 changed files with 121 additions and 19 deletions
|
|
@ -1 +1 @@
|
||||||
Subproject commit 60aae89495f05eedb48c9c1468e4c8d4dd92f79f
|
Subproject commit 9bbfeb3316098af16370c10355c94ed7ec06f5ee
|
||||||
|
|
@ -231,3 +231,4 @@ set_global_assignment -name VERILOG_MACRO "L2_AHEPAM=1"
|
||||||
set_global_assignment -name VERILOG_MACRO "WITH_SPI_SSEL=1"
|
set_global_assignment -name VERILOG_MACRO "WITH_SPI_SSEL=1"
|
||||||
set_global_assignment -name VERILOG_MACRO "AX_PORT=1"
|
set_global_assignment -name VERILOG_MACRO "AX_PORT=1"
|
||||||
set_global_assignment -name VERILOG_MACRO "SER_FIFO_ALTERA=1"
|
set_global_assignment -name VERILOG_MACRO "SER_FIFO_ALTERA=1"
|
||||||
|
set_global_assignment -name VERILOG_MACRO "SPI_TIMEOUT_1024=1"
|
||||||
|
|
|
||||||
|
|
@ -137,6 +137,6 @@ quartus/thhor_crs.map.rpt: Warning (13040): bidirectional pin "P33[4]" has no
|
||||||
quartus/thhor_crs.map.rpt: Warning (13040): bidirectional pin "P33[5]" has no driver
|
quartus/thhor_crs.map.rpt: Warning (13040): bidirectional pin "P33[5]" has no driver
|
||||||
quartus/thhor_crs.map.rpt: Warning (13040): bidirectional pin "P33[6]" has no driver
|
quartus/thhor_crs.map.rpt: Warning (13040): bidirectional pin "P33[6]" has no driver
|
||||||
quartus/thhor_crs.map.rpt: Warning (13040): bidirectional pin "P33[7]" has no driver
|
quartus/thhor_crs.map.rpt: Warning (13040): bidirectional pin "P33[7]" has no driver
|
||||||
quartus/thhor_crs.map.rpt:Info: Quartus Prime Analysis & Synthesis was successful. 0 errors, 237 warnings
|
quartus/thhor_crs.map.rpt:Info: Quartus Prime Analysis & Synthesis was successful. 0 errors, 238 warnings
|
||||||
quartus/thhor_crs.sta.rpt:Warning (18236): Number of processors has not been specified which may cause overloading on shared machines. Set the global assignment NUM_PARALLEL_PROCESSORS in your QSF to an appropriate value for best performance.
|
quartus/thhor_crs.sta.rpt:Warning (18236): Number of processors has not been specified which may cause overloading on shared machines. Set the global assignment NUM_PARALLEL_PROCESSORS in your QSF to an appropriate value for best performance.
|
||||||
quartus/thhor_crs.sta.rpt:Info: Quartus Prime Timing Analyzer was successful. 0 errors, 1 warning
|
quartus/thhor_crs.sta.rpt:Info: Quartus Prime Timing Analyzer was successful. 0 errors, 1 warning
|
||||||
|
|
|
||||||
91
src/dose.py
91
src/dose.py
|
|
@ -128,7 +128,7 @@ class dose_cmd(uart.uart):
|
||||||
d = bytes(d)
|
d = bytes(d)
|
||||||
if s is None:
|
if s is None:
|
||||||
s = len(d)
|
s = len(d)
|
||||||
d = struct.pack("<HBB", a,s,ccp) + d + b'\0\0\0\0\0\0\0\0\0\0\0\0'
|
d = struct.pack("<HBB", a,s,ccp) + d + bytes(12)
|
||||||
cc, nn, dd = self.cmd(c, d[:16])
|
cc, nn, dd = self.cmd(c, d[:16])
|
||||||
if dd and nn:
|
if dd and nn:
|
||||||
aa,ss,cc = struct.unpack("<HBB", dd[:4])
|
aa,ss,cc = struct.unpack("<HBB", dd[:4])
|
||||||
|
|
@ -139,6 +139,9 @@ class dose_cmd(uart.uart):
|
||||||
return name, d
|
return name, d
|
||||||
return cc, nn, dd
|
return cc, nn, dd
|
||||||
|
|
||||||
|
def peek_byte(self, a):
|
||||||
|
return self.peek(a)[-1][0]
|
||||||
|
|
||||||
def more(self, flags=b''):
|
def more(self, flags=b''):
|
||||||
return self.cmd(self.last_cmd + b'=' + flags)
|
return self.cmd(self.last_cmd + b'=' + flags)
|
||||||
|
|
||||||
|
|
@ -371,6 +374,92 @@ class dose_cmd(uart.uart):
|
||||||
print(f"Power was {("off", "ON")[r[1]]}", file=sys.stderr)
|
print(f"Power was {("off", "ON")[r[1]]}", file=sys.stderr)
|
||||||
return r
|
return r
|
||||||
|
|
||||||
|
def fpga_reset(self):
|
||||||
|
return self.cmd("C@")
|
||||||
|
|
||||||
|
FPGA_FLGS = {
|
||||||
|
"ABORT": 0x01,
|
||||||
|
"ABORTED": 0x10,
|
||||||
|
"BUSY": 0x20,
|
||||||
|
"SUBMITTED": 0x40,
|
||||||
|
"CONFIG": 0x80,
|
||||||
|
"NOOP": 0x8000,
|
||||||
|
}
|
||||||
|
|
||||||
|
def fpga_cmd(self, c, read=0, wait=0, flags=()):
|
||||||
|
n = len(c) & 0xe
|
||||||
|
if n != len(c):
|
||||||
|
raise ValueError(f"FPGA command must be even 2…14 bytes {c!r}")
|
||||||
|
n |= flags2int(self.FPGA_FLGS, flags)
|
||||||
|
z = read << 1
|
||||||
|
if wait:
|
||||||
|
if wait > 7 or z > 14:
|
||||||
|
raise ValueError("FPGA cannot wait-read more than 14 bytes")
|
||||||
|
z |= wait << 4
|
||||||
|
z |= 1
|
||||||
|
z |= n >> 8
|
||||||
|
n &= 0xff
|
||||||
|
c = bytes((n, z)) + c + bytes(14)
|
||||||
|
r, e, d = self.cmd("C", c[:16])
|
||||||
|
s = int2flags(self.FPGA_FLGS, d[0])
|
||||||
|
print(f"FPGA cmd status {s!r}", file=sys.stderr)
|
||||||
|
return d
|
||||||
|
|
||||||
|
def fpga_config(self, filename="../fpga/quartus/thhor_crs.rbf"):
|
||||||
|
self.fpga_reset()
|
||||||
|
n = 0
|
||||||
|
nn = 0
|
||||||
|
with open(filename, "rb") as f:
|
||||||
|
c = f.read(14)
|
||||||
|
while c:
|
||||||
|
if len(c) & 1:
|
||||||
|
c += b'\0'
|
||||||
|
d = fpga_cmd(c, flags="CONFIG")
|
||||||
|
if d[0] & self.FPGA_FLGS["SUBMITTED"]:
|
||||||
|
n += len(c)
|
||||||
|
c = f.read(14)
|
||||||
|
if n > nn + 1024:
|
||||||
|
if ~self.peek_byte("VPORTA_IN") & 0x10:
|
||||||
|
raise FPGA_Error("nSTATUS went low during config")
|
||||||
|
print(f"{n} bytes sent", file=sys.stderr)
|
||||||
|
nn += 1024
|
||||||
|
return n
|
||||||
|
|
||||||
|
def icmd(self, c, p=None, r=2):
|
||||||
|
w = [c | 0x8000]
|
||||||
|
if p is not None:
|
||||||
|
w[0] |= 0x4000
|
||||||
|
w.append(p)
|
||||||
|
if r:
|
||||||
|
w.extend([0x8001]*(r-1))
|
||||||
|
w.append(0)
|
||||||
|
d = struct.pack(f">{len(w)}H", *w)
|
||||||
|
print(f"icmd → {[f"{ww:04x}" for ww in w]}")
|
||||||
|
d = self.fpga_cmd(d)
|
||||||
|
r = struct.unpack(f">{len(w)+1}H", d[:2*len(w)+2])
|
||||||
|
print(f" ← {[f"{rr:04x}" for rr in r]}")
|
||||||
|
return r
|
||||||
|
|
||||||
|
def flags2int(FLAGS, flags):
|
||||||
|
r = 0
|
||||||
|
if isinstance(flags, int):
|
||||||
|
return flags
|
||||||
|
if isinstance(flags, str):
|
||||||
|
return FLAGS[flags]
|
||||||
|
for f in flags:
|
||||||
|
if isinstance(f, int):
|
||||||
|
r |= f
|
||||||
|
else:
|
||||||
|
r |= FLAGS[f]
|
||||||
|
return r
|
||||||
|
|
||||||
|
def int2flags(FLAGS, flags):
|
||||||
|
r = []
|
||||||
|
for f in FLAGS:
|
||||||
|
if flags & FLAGS[f]:
|
||||||
|
r.append(f)
|
||||||
|
return r
|
||||||
|
|
||||||
if tty:
|
if tty:
|
||||||
tty = dose_cmd(tty, baud)
|
tty = dose_cmd(tty, baud)
|
||||||
tty._export(globals())
|
tty._export(globals())
|
||||||
|
|
|
||||||
33
src/fpga.c
33
src/fpga.c
|
|
@ -22,36 +22,37 @@ void fpga_reset()
|
||||||
|
|
||||||
void fpga_cmd(struct fpga_cmd *c)
|
void fpga_cmd(struct fpga_cmd *c)
|
||||||
{
|
{
|
||||||
|
uint8_t n = c->n;
|
||||||
|
uint8_t z = c->z;
|
||||||
if (fpga_reset_poll()) {
|
if (fpga_reset_poll()) {
|
||||||
c->n |= 0x20; // busy flag
|
c->n = n | fpga_busy;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (c->n & 1 && spi_abort()) {
|
if (n & fpga_abort && spi_abort()) {
|
||||||
c->n |= 0x10; // aborted flag
|
c->n = n | fpga_aborted;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (spi_busy_p()) {
|
else if (spi_busy_p()) {
|
||||||
c->n |= 0x20; // busy flag
|
c->n = n | fpga_busy;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
c->n &=~ 0x10; // not busy
|
c->n = n & ~fpga_busy;
|
||||||
if (c->n & 0x40)
|
if (n & fpga_submitted)
|
||||||
return;
|
return;
|
||||||
c->n |= 0x40; // submitted flag
|
c->n = n | fpga_submitted;
|
||||||
uint8_t n = c->n & 0x0e; // send up to seven cmd words
|
|
||||||
uint8_t z = c->z & 0x7e; // and up to 63 zeros
|
spi_select(n & fpga_config ? SPI_CONFIG : 0);
|
||||||
spi_select(0);
|
spi.csize = n &= fpga_size;
|
||||||
spi.zero = c->n & 0x80; // send nop: 0x8080 (please), or zeros
|
spi.zero = z & 0x80; // send 0x0000 or 0x8080
|
||||||
spi.csize = n;
|
|
||||||
spi.cmd = c->d;
|
spi.cmd = c->d;
|
||||||
spi.rdata = c->d;
|
spi.rdata = c->d;
|
||||||
if (c->z & 0x80) {
|
if (z & fpga_wait_nonzero) {
|
||||||
spi.isize = n + z>>3 & 0x0e; // ignore cmd ± (z[6:4])
|
spi.isize = n + (z>>3 & fpga_size); // ignore cmd ± (z[6:4])
|
||||||
spi.zsize = spi.rsize = z & 0x0e; // read x[3:1] words
|
spi.zsize = spi.rsize = z & fpga_size; // read x[3:1] words
|
||||||
spi.mask = 0xff; // start reading at the first nonzero byte after cmd
|
spi.mask = 0xff; // start reading at the first nonzero byte after cmd
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
spi.zsize = z; // send z zeros/nop after cmd
|
spi.zsize = z &= 0x7e; // send z zeros/nop after cmd
|
||||||
spi.rsize = 14; // save the last 7 words returned
|
spi.rsize = 14; // save the last 7 words returned
|
||||||
if (n + z > 14)
|
if (n + z > 14)
|
||||||
spi.isize = n + z - 14;
|
spi.isize = n + z - 14;
|
||||||
|
|
|
||||||
11
src/fpga.h
11
src/fpga.h
|
|
@ -7,6 +7,17 @@ struct fpga_cmd {
|
||||||
uint8_t d[14];
|
uint8_t d[14];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum fpga_flags {
|
||||||
|
fpga_abort = 0x01,
|
||||||
|
fpga_size = 0x0e,
|
||||||
|
fpga_aborted = 0x10,
|
||||||
|
fpga_busy = 0x20,
|
||||||
|
fpga_submitted = 0x40,
|
||||||
|
fpga_config = 0x80,
|
||||||
|
|
||||||
|
fpga_wait_nonzero = 0x01,
|
||||||
|
};
|
||||||
|
|
||||||
void fpga_reset();
|
void fpga_reset();
|
||||||
uint8_t fpga_reset_poll();
|
uint8_t fpga_reset_poll();
|
||||||
void fpga_cmd(struct fpga_cmd *c);
|
void fpga_cmd(struct fpga_cmd *c);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue