2017-02-01 22:38:32 +00:00
|
|
|
#! /usr/bin/ipython -i
|
2014-05-18 17:51:46 +00:00
|
|
|
# encoding: utf-8
|
2014-05-16 14:24:53 +00:00
|
|
|
|
2015-01-12 20:54:16 +00:00
|
|
|
from altera_ctrl import *
|
|
|
|
|
|
2014-05-16 14:24:53 +00:00
|
|
|
sys.ps1="RPiGSE> "
|
|
|
|
|
sys.ps2="RPiGSE. "
|
2017-02-01 22:38:32 +00:00
|
|
|
try:
|
|
|
|
|
get_ipython().prompt_manager.templates = {
|
|
|
|
|
'in': 'In [{color.number}{count}{color.prompt}] RPIGSE> ',
|
|
|
|
|
'in2': ' .{dots}. RPIGSE. ',
|
|
|
|
|
'out': 'Out[{color.number}{count}{color.prompt}] RPIGSE> ',
|
|
|
|
|
}
|
|
|
|
|
except NameError:
|
|
|
|
|
pass
|
2014-05-16 14:24:53 +00:00
|
|
|
|
2015-01-12 21:10:51 +00:00
|
|
|
def icucore_msg(ad=0, sz=0, da=0):
|
2014-05-16 14:24:53 +00:00
|
|
|
h = struct.pack(">HH", 0x3c3d, ad + (sz<<14))
|
|
|
|
|
if sz==1:
|
|
|
|
|
h+=struct.pack(">H", da)
|
|
|
|
|
if sz==2:
|
|
|
|
|
h+=struct.pack(">L", da)
|
|
|
|
|
if sz==3:
|
|
|
|
|
h+=struct.pack(">LL", da>>32, da&0xffffffff)
|
|
|
|
|
h += struct.pack(">H", crc1021(0xffff, [ord(b) for b in h]))
|
|
|
|
|
spidev.sync_transfer(cmd='\x8a'+"\x8a".join(h))
|
2014-05-16 17:44:15 +00:00
|
|
|
|
2017-02-01 22:38:32 +00:00
|
|
|
sys.path[1:1] = ["../../python"]
|
2015-01-12 21:10:51 +00:00
|
|
|
import solomsgclass
|
|
|
|
|
solomsg = solomsgclass.solomsg(icucore_msg)
|
|
|
|
|
solomsg._export(globals())
|
|
|
|
|
|
2017-02-01 22:38:32 +00:00
|
|
|
from crc1021 import crc1021
|
|
|
|
|
|
2014-11-28 11:14:29 +00:00
|
|
|
def routing(table={}, arb=False, **k):
|
|
|
|
|
switch = {
|
|
|
|
|
"RxD": (0, { "TxD": 0, "tx": 1, "Rx2": 2, "Rx1": 3,}),
|
|
|
|
|
"rx": (2, { "TxD": 0, "tx": 1, "Rx2": 2, "Rx1": 3,}),
|
|
|
|
|
"Tx1": (4, { "TxD": 0, "RxD": 1, "px": 2, "tx": 3,}),
|
|
|
|
|
"Tx2": (6, { "TxD": 0, "RxD": 1, "tx": 2, "px": 3,}),
|
|
|
|
|
}
|
|
|
|
|
for kk in switch:
|
|
|
|
|
if not kk in table:
|
|
|
|
|
table[kk] = 3
|
|
|
|
|
for kk in k:
|
|
|
|
|
table[kk] = k[kk]
|
|
|
|
|
for kk in table:
|
|
|
|
|
if table[kk] in switch[kk][1]:
|
|
|
|
|
table[kk] = switch[kk][1][table[kk]]
|
|
|
|
|
m = 0
|
|
|
|
|
for kk in switch:
|
|
|
|
|
m |= table[kk] << switch[kk][0]
|
|
|
|
|
if arb:
|
|
|
|
|
m |= 0x8000
|
|
|
|
|
reg(0x108, m)
|
|
|
|
|
|
2014-05-16 17:44:15 +00:00
|
|
|
def boot(rbf="rpigse.rbf"):
|
|
|
|
|
altera_from_file(rbf)
|
2014-05-16 17:45:49 +00:00
|
|
|
|
|
|
|
|
# serial bit clock from 96MHz mclk
|
2014-05-16 17:44:15 +00:00
|
|
|
MCLK=96000000
|
|
|
|
|
BAUD=115200
|
|
|
|
|
BAUDMODULO = 240
|
|
|
|
|
DIV = MCLK/16/BAUD
|
|
|
|
|
FRAC = (MCLK/16*BAUDMODULO)/BAUD - DIV*BAUDMODULO
|
|
|
|
|
reg(0x810, (DIV-1)*256 + FRAC)
|
2014-05-16 17:45:49 +00:00
|
|
|
|
|
|
|
|
# routing:
|
|
|
|
|
# Setup for sologse.py @/dev/ttyAMA0
|
|
|
|
|
# w/ Rx2 for analog streaming
|
|
|
|
|
# RxD = Rx1 (0x03/0x03) TxD, tx, Rx2, Rx1
|
2014-11-28 11:14:29 +00:00
|
|
|
# rx = Rx1 (0x0c/0x0c) TxD, tx, Rx2, Rx1
|
2014-05-16 17:45:49 +00:00
|
|
|
# Tx1 = TxD (0x00/0x30) TxD, RxD, px, tx
|
|
|
|
|
# Tx2 = px (0xc0/0xc0) TxD, RxD, tx, px
|
2014-11-28 11:14:29 +00:00
|
|
|
routing(RxD="Rx1", rx="Rx1", Tx1="TxD", Tx2="px")
|
|
|
|
|
#reg(0x108, 0xcf)
|
2014-05-16 17:44:15 +00:00
|
|
|
|
2015-01-15 15:28:19 +00:00
|
|
|
def pps_en(on=True):
|
|
|
|
|
if on:
|
|
|
|
|
return reg(10, 1)
|
|
|
|
|
else:
|
|
|
|
|
return reg(9, 1)
|
|
|
|
|
|
2014-05-18 17:51:46 +00:00
|
|
|
def readrecordcmd(a, n, w=0):
|
|
|
|
|
return struct.pack(">%dH"%(n+2+w), *( (a,)+(0,)*w+(0x8001,)*n+(0,) ))
|
|
|
|
|
|
|
|
|
|
def readrecord(a, n, w=0):
|
|
|
|
|
c = readrecordcmd(a, n, w)
|
|
|
|
|
return struct.unpack(">%dH"%n, spidev.sync_transfer(cmd=c, rsize=2*n))
|
|
|
|
|
|
|
|
|
|
def HK():
|
|
|
|
|
return [i & 0xfff for i in readrecord(0x8030, 8)]
|
|
|
|
|
|
|
|
|
|
# master status register[15:12] bits tell if a packet is available
|
|
|
|
|
read_stat_cmd = readrecordcmd(0x8005, 1)
|
2014-05-29 08:14:56 +00:00
|
|
|
# match an ARB header and read two words
|
2014-05-29 11:01:46 +00:00
|
|
|
read_arb_header_cmd = struct.pack(">2H", 0xc101,0x5ead)+readrecordcmd(0x8016,2)
|
2014-05-29 08:14:56 +00:00
|
|
|
# read one word from fifo 2
|
|
|
|
|
read_header_iter = struct.pack(">2H", 0x8001,0x8000)
|
2014-05-18 17:51:46 +00:00
|
|
|
# disable ARB header match
|
2014-05-21 07:07:43 +00:00
|
|
|
read_arb_body_prefix = struct.pack(">2H", 0xc101,0x0000)
|
2014-05-18 17:51:46 +00:00
|
|
|
# read two words from fifo 2
|
2014-05-21 07:07:43 +00:00
|
|
|
read_arb_body_iter = struct.pack(">2H", 0x8016,0x8001)
|
2014-05-18 17:51:46 +00:00
|
|
|
# read a word from fifo 2
|
2014-05-21 07:07:43 +00:00
|
|
|
read_uart_cmd = struct.pack(">H", 0x8016) + read_stat_cmd
|
2014-05-29 08:14:56 +00:00
|
|
|
# read 6/8 words from fifo 3
|
2014-05-18 17:51:46 +00:00
|
|
|
read_ev_header_cmd = readrecordcmd(0x8017,8)[:-4]
|
2014-05-21 07:07:43 +00:00
|
|
|
read_ev_body_iter = struct.pack(">HH", 0x8001,0x8001)
|
2014-05-28 11:31:23 +00:00
|
|
|
read_samp_cmd = readrecordcmd(0x8017,25)[:-4] + read_stat_cmd
|
2014-11-28 18:45:59 +00:00
|
|
|
# read 5 words from fifo 3
|
|
|
|
|
read_step_header_cmd = readrecordcmd(0x8017,7)[:-4]
|
2014-05-18 17:51:46 +00:00
|
|
|
|
2014-11-28 18:45:59 +00:00
|
|
|
|
2015-01-16 11:10:19 +00:00
|
|
|
def search_for_header(h, fmt, val, cmd=read_header_iter, mask=0xffffffff):
|
2014-05-29 08:14:56 +00:00
|
|
|
r = ""
|
|
|
|
|
rr = struct.unpack(fmt, h)
|
2014-11-28 18:45:59 +00:00
|
|
|
while (rr[0] & mask) != val:
|
2014-05-29 08:14:56 +00:00
|
|
|
r += h[:2]
|
|
|
|
|
if len(r)>=2048:
|
|
|
|
|
while len(r)>16 and r[-2:] == "\0\0":
|
|
|
|
|
r = r[:-2]
|
|
|
|
|
e = "".join(["%02x" % ord(c) for c in r])
|
|
|
|
|
raise IOError("invalid header (0x%04x): %s" % (val, e))
|
|
|
|
|
h = h[2:] + spidev.sync_transfer(cmd=read_header_iter, rsize=2)
|
|
|
|
|
rr = struct.unpack(fmt, h)
|
|
|
|
|
return h, rr
|
|
|
|
|
|
2015-01-12 20:54:16 +00:00
|
|
|
def packetfifo2_config(size, header, mask=0xffff, idx=0, mmask=0x00000000, scale=0, offset=0, count=False):
|
2014-11-28 11:14:29 +00:00
|
|
|
"""Configure the packet fifo2 in the rpigse.
|
|
|
|
|
header: packet header
|
|
|
|
|
size: max size of the packet in words (16bit)
|
2015-01-12 20:54:16 +00:00
|
|
|
mask: valid bits in the header word.
|
2014-11-28 11:14:29 +00:00
|
|
|
idx: number of words to read before the match shall be made
|
2015-01-12 20:54:16 +00:00
|
|
|
mmask: 32 bit mask of bits to use for the size match
|
2014-11-28 11:14:29 +00:00
|
|
|
scale: log₂ of the scale factor in words.
|
|
|
|
|
offset: number of extra words
|
|
|
|
|
count: False: count the bits, True: use the field as a number
|
|
|
|
|
"""
|
2014-11-28 18:45:59 +00:00
|
|
|
if idx:
|
|
|
|
|
idx = (size-idx+1) & 0x3ff
|
2014-11-28 11:14:29 +00:00
|
|
|
count = 0x8000 if count else 0
|
|
|
|
|
m = 0;
|
|
|
|
|
for mm,bb in ((0xffff0000, 0x4000), (0xc000,0x2000), (0x3f00,0x1000), (0xfe,0x800), (1,0x400)):
|
2015-01-12 20:54:16 +00:00
|
|
|
if mmask & mm:
|
|
|
|
|
if (mmask & mm) != mm:
|
2014-11-28 11:14:29 +00:00
|
|
|
raise ValueError("partial mask 0x%08x" % mm)
|
|
|
|
|
m |= bb
|
2015-01-12 20:54:16 +00:00
|
|
|
reg(0x103, size-1)
|
|
|
|
|
reg(0x104, header)
|
|
|
|
|
reg(0x105, mask)
|
2014-11-28 11:14:29 +00:00
|
|
|
reg(0x106, count | m | idx)
|
|
|
|
|
reg(0x107, (offset & 0x3ff) | (scale << 10))
|
|
|
|
|
|
|
|
|
|
|
2015-01-12 20:54:16 +00:00
|
|
|
def packetfifo1_config(size, header, mask=0xffff):
|
2014-11-28 11:14:29 +00:00
|
|
|
"""Configure the packet fifo1 in the rpigse.
|
|
|
|
|
header: packet header
|
2015-01-12 20:54:16 +00:00
|
|
|
mask: valid bits in the header word.
|
2014-11-28 11:14:29 +00:00
|
|
|
size: max size of the packet in words (16bit)
|
|
|
|
|
"""
|
|
|
|
|
reg(0x100, size-1)
|
|
|
|
|
reg(0x101, header)
|
2015-01-12 20:54:16 +00:00
|
|
|
reg(0x102, mask)
|
2014-11-28 11:14:29 +00:00
|
|
|
|
2014-11-28 18:45:59 +00:00
|
|
|
def stream_to_binary(f, arb=True, samp=False, step=False, bug=1):
|
2015-01-15 16:34:51 +00:00
|
|
|
from time import time
|
2015-01-09 20:12:19 +00:00
|
|
|
if arb:
|
|
|
|
|
routing(arb=True, Tx1="TxD")
|
2015-01-12 20:54:16 +00:00
|
|
|
packetfifo1_config(2, 0x5ead)
|
2015-01-09 20:12:19 +00:00
|
|
|
else:
|
|
|
|
|
routing(arb=False, Tx1="TxD")
|
2015-01-12 20:54:16 +00:00
|
|
|
packetfifo1_config(1, 0, 0)
|
2015-01-09 20:12:19 +00:00
|
|
|
if step:
|
2015-01-12 20:54:16 +00:00
|
|
|
packetfifo2_config(header=0x8def, size=38, idx=5, mmask=0xffffffff, scale=0, offset=1)
|
2015-01-09 20:12:19 +00:00
|
|
|
elif samp:
|
|
|
|
|
packetfifo2_config(size=25-bug, header=0x5a61)
|
|
|
|
|
else:
|
2015-01-12 20:54:16 +00:00
|
|
|
packetfifo2_config(header=0xbeef, size=66, idx=4, mmask=0xffff3fff, scale=1, offset=2)
|
2014-05-18 17:51:46 +00:00
|
|
|
stat = reg(5)
|
|
|
|
|
recv_buf = ""
|
|
|
|
|
while True:
|
|
|
|
|
ne = 0
|
2014-05-29 08:14:56 +00:00
|
|
|
nr = 0
|
2014-05-18 17:51:46 +00:00
|
|
|
while stat & 0x4000:
|
2014-05-29 08:14:56 +00:00
|
|
|
nr += 1
|
2014-05-18 17:51:46 +00:00
|
|
|
if arb:
|
|
|
|
|
h = spidev.sync_transfer(cmd=read_arb_header_cmd, rsize=4)
|
2014-05-29 08:14:56 +00:00
|
|
|
h, rr = search_for_header(h, ">HH", 0x5ead)
|
2014-05-18 17:51:46 +00:00
|
|
|
n = 0
|
|
|
|
|
for i in range(16):
|
|
|
|
|
if rr[1] & (1<<i):
|
|
|
|
|
n += (8,92,2,12,16,30,30,30,30,30,0,0,0,0,0,0)[i]
|
2014-05-29 11:01:46 +00:00
|
|
|
c = read_arb_body_prefix + n/2*read_arb_body_iter + read_stat_cmd
|
2014-05-18 17:51:46 +00:00
|
|
|
r = spidev.sync_transfer(cmd=c, rsize=2*n+2)
|
|
|
|
|
stat = struct.unpack(">H", r[2*n:])[0]
|
|
|
|
|
f.write(h+r[:2*n])
|
|
|
|
|
else:
|
2014-05-21 07:07:43 +00:00
|
|
|
r = spidev.sync_transfer(cmd=read_uart_cmd, rsize=4)
|
|
|
|
|
rr = struct.unpack(">BBH", r)
|
2014-05-18 17:51:46 +00:00
|
|
|
stat = rr[2]
|
|
|
|
|
if rr[0] == 0x80:
|
2014-05-21 07:07:43 +00:00
|
|
|
f.write(r[1])
|
2014-05-18 17:51:46 +00:00
|
|
|
while stat & 0x8000:
|
|
|
|
|
ne += 1
|
2014-11-28 18:45:59 +00:00
|
|
|
if step:
|
|
|
|
|
h = spidev.sync_transfer(cmd=read_step_header_cmd, rsize=10)
|
|
|
|
|
rr = struct.unpack(">HLL", h)
|
|
|
|
|
if (rr[0] & 0xefff) != 0x8def:
|
2015-01-09 20:12:19 +00:00
|
|
|
h, rr = search_for_header(h, ">HLL", 0x8def, mask=0xefff, cmd=read_header_iter[:2])
|
2014-11-28 18:45:59 +00:00
|
|
|
n = 1
|
|
|
|
|
m = rr[2]
|
|
|
|
|
while m:
|
|
|
|
|
n+=1
|
|
|
|
|
m &= m-1
|
|
|
|
|
c = read_ev_body_iter[:2] * (n-1) + read_stat_cmd
|
|
|
|
|
r = spidev.sync_transfer(cmd=c, rsize=2*n+2)
|
|
|
|
|
stat = struct.unpack(">H", r[2*n:])[0]
|
|
|
|
|
f.write(h+r[:2*n])
|
|
|
|
|
elif samp:
|
2014-05-18 17:51:46 +00:00
|
|
|
r = spidev.sync_transfer(cmd=read_samp_cmd, rsize=52)
|
2014-05-28 11:31:23 +00:00
|
|
|
rr = struct.unpack(">H", r[:2])
|
2014-05-18 17:51:46 +00:00
|
|
|
if rr[0] != 0x5a61:
|
2014-05-29 08:14:56 +00:00
|
|
|
r, rr = search_for_header(r, ">H12LH", 0x5a61)
|
2014-05-18 17:51:46 +00:00
|
|
|
stat = struct.unpack(">H", r[50:])[0]
|
2014-05-29 08:14:56 +00:00
|
|
|
f.write(r[0:50])
|
2014-05-18 17:51:46 +00:00
|
|
|
else:
|
|
|
|
|
h = spidev.sync_transfer(cmd=read_ev_header_cmd, rsize=12)
|
2014-05-21 07:07:43 +00:00
|
|
|
rr = struct.unpack(">LLL", h)
|
2014-05-18 17:51:46 +00:00
|
|
|
if rr[0] != 0xbeefa128L:
|
2014-05-30 08:23:35 +00:00
|
|
|
h, rr = search_for_header(h, ">LLL", 0xbeefa128L, read_header_iter[:2])
|
2014-05-29 08:14:56 +00:00
|
|
|
if rr[1] & 0x00008000 or rr[1]==0xffff3fff:
|
2014-05-18 17:51:46 +00:00
|
|
|
n = 30
|
|
|
|
|
else:
|
|
|
|
|
n = 0
|
|
|
|
|
m = rr[1]
|
|
|
|
|
while m:
|
|
|
|
|
n+=1
|
|
|
|
|
m &= m-1
|
|
|
|
|
c = read_ev_body_iter * (n-1) + read_stat_cmd
|
|
|
|
|
r = spidev.sync_transfer(cmd=c, rsize=4*n+2)
|
|
|
|
|
stat = struct.unpack(">H", r[4*n:])[0]
|
|
|
|
|
f.write(h+r[:4*n])
|
2014-05-29 08:14:56 +00:00
|
|
|
if not stat & 0xc000:
|
2014-05-29 11:01:46 +00:00
|
|
|
if nr or ne:
|
2014-05-29 08:14:56 +00:00
|
|
|
sys.stderr.write("\r%10u R: %-5u E: %-5u " % (time(), nr, ne))
|
|
|
|
|
stat = reg(5)
|
2014-05-18 17:51:46 +00:00
|
|
|
if not stat & 0xc000:
|
|
|
|
|
if ne:
|
|
|
|
|
sleep(0.001)
|
|
|
|
|
else:
|
|
|
|
|
f.flush()
|
|
|
|
|
sleep(0.1)
|
|
|
|
|
stat = reg(5)
|
|
|
|
|
|
2017-02-01 22:38:32 +00:00
|
|
|
class sysclock(object):
|
|
|
|
|
|
|
|
|
|
sync = "\xd7\x1c\x70\xcb"
|
|
|
|
|
|
|
|
|
|
def __init__(self, filename, mode, sparse=10):
|
|
|
|
|
self.sparse = sparse
|
|
|
|
|
self.file = open(filename, mode)
|
|
|
|
|
self.__old = self.__won = 0
|
|
|
|
|
|
|
|
|
|
def timestamp(self, now):
|
|
|
|
|
snow = struct.pack(">LH", int(now), int(now*0x10000)&0xffff)
|
|
|
|
|
self.file.write(self.sync + snow)
|
|
|
|
|
|
|
|
|
|
def write(self, s):
|
|
|
|
|
import time
|
|
|
|
|
|
|
|
|
|
if not self.file.closed:
|
|
|
|
|
now = time.time()
|
|
|
|
|
if self.sparse:
|
|
|
|
|
self.__won = now - (now % self.sparse)
|
|
|
|
|
if self.__won > self.__old:
|
|
|
|
|
self.timestamp(now)
|
|
|
|
|
self.__old = self.__won
|
|
|
|
|
else:
|
|
|
|
|
self.timestamp(now)
|
|
|
|
|
self.file.write(s)
|
|
|
|
|
|
|
|
|
|
def close(self):
|
|
|
|
|
self.file.close()
|
|
|
|
|
|
|
|
|
|
def flush(self):
|
|
|
|
|
self.file.flush()
|
|
|
|
|
|
|
|
|
|
def __str__(self):
|
|
|
|
|
return "SYSCLOCK "+str(self.file)
|
|
|
|
|
|
|
|
|
|
def __repr__(self):
|
|
|
|
|
return "SYSCLOCK "+repr(self.file)
|
|
|
|
|
|
|
|
|
|
def stream_file(fn, open=open, **args):
|
|
|
|
|
aa={}
|
|
|
|
|
if "sparse" in args:
|
|
|
|
|
aa["sparse"]=args["sparse"]
|
|
|
|
|
del args["sparse"]
|
|
|
|
|
f = open(fn, "a", **aa)
|
2014-05-18 17:51:46 +00:00
|
|
|
reg(7, 0x1f0)
|
|
|
|
|
reg(10, 9)
|
|
|
|
|
while True:
|
|
|
|
|
try:
|
|
|
|
|
stream_to_binary(f, **args)
|
|
|
|
|
except IOError, e:
|
|
|
|
|
reg(7, 0x1f0)
|
2014-05-28 11:28:43 +00:00
|
|
|
print e
|
2014-05-18 17:51:46 +00:00
|
|
|
except KeyboardInterrupt:
|
|
|
|
|
f.close()
|
|
|
|
|
break
|
|
|
|
|
|