2015-01-12 20:54:16 +00:00
|
|
|
|
|
|
|
|
import struct
|
|
|
|
|
from time import sleep
|
|
|
|
|
import sys, os
|
|
|
|
|
|
|
|
|
|
import spidev
|
|
|
|
|
spidevname = "/dev/spidev0.0"
|
|
|
|
|
try:
|
|
|
|
|
spi = os.open(spidevname, os.O_RDWR)
|
|
|
|
|
spidev.set_mode(fd=spi, cpol=0, cpha=1)
|
2021-07-30 17:11:19 +00:00
|
|
|
except OSError as e:
|
2015-01-12 20:54:16 +00:00
|
|
|
sys.stderr.write("%s: %s\n" % (spidevname, repr(e)))
|
|
|
|
|
|
|
|
|
|
def gpio_read(port):
|
2021-07-30 17:11:19 +00:00
|
|
|
f = open("/sys/class/gpio/gpio%d/value" % port)
|
2015-01-12 20:54:16 +00:00
|
|
|
r = int(f.readline())
|
|
|
|
|
f.close()
|
|
|
|
|
return r
|
|
|
|
|
|
|
|
|
|
def gpio_write(port, value):
|
2021-07-30 17:11:19 +00:00
|
|
|
f = open("/sys/class/gpio/gpio%d/value" % port, "w")
|
2015-01-12 20:54:16 +00:00
|
|
|
f.write("%d\n" % value)
|
|
|
|
|
f.close()
|
|
|
|
|
|
|
|
|
|
nCONFIG=24
|
|
|
|
|
nSTATUS=25
|
|
|
|
|
CONF_DONE=23
|
|
|
|
|
|
|
|
|
|
def gpio_init(port, d=None, uwait=2):
|
2021-07-30 17:11:19 +00:00
|
|
|
f = open("/sys/class/gpio/export", "w")
|
2015-01-12 20:54:16 +00:00
|
|
|
f.write(str(port))
|
|
|
|
|
try:
|
|
|
|
|
f.close()
|
2021-07-30 17:11:19 +00:00
|
|
|
except IOError as e:
|
|
|
|
|
pass
|
2015-01-12 20:54:16 +00:00
|
|
|
if d:
|
|
|
|
|
try:
|
2021-07-30 17:11:19 +00:00
|
|
|
f = open("/sys/class/gpio/gpio%d/direction" % port, "w")
|
|
|
|
|
except IOError as e:
|
2015-01-12 20:54:16 +00:00
|
|
|
# wait for assignment of ownership (by udev?)
|
|
|
|
|
sleep(uwait)
|
2021-07-30 17:11:19 +00:00
|
|
|
f = open("/sys/class/gpio/gpio%d/direction" % port, "w")
|
2015-01-12 20:54:16 +00:00
|
|
|
f.write(d)
|
|
|
|
|
f.close()
|
|
|
|
|
|
|
|
|
|
_verbosity=1
|
|
|
|
|
def set_verbosity(v, incr=False):
|
2018-11-01 09:46:44 +00:00
|
|
|
global _verbosity
|
2015-01-12 20:54:16 +00:00
|
|
|
if incr:
|
|
|
|
|
_verbosity += v
|
|
|
|
|
else:
|
|
|
|
|
_verbosity = v
|
|
|
|
|
|
|
|
|
|
def altera_reset(timeout=10):
|
|
|
|
|
gpio_init(nSTATUS)
|
|
|
|
|
gpio_init(CONF_DONE)
|
|
|
|
|
gpio_init(nCONFIG, "out")
|
|
|
|
|
if _verbosity>=2:
|
|
|
|
|
sys.stderr.write("nCONFIG=%d nSTATUS=%d CONF_DONE=%d\n"
|
|
|
|
|
% (gpio_read(nCONFIG),
|
|
|
|
|
gpio_read(nSTATUS),
|
|
|
|
|
gpio_read(CONF_DONE),
|
|
|
|
|
))
|
|
|
|
|
gpio_write(nCONFIG, 0);
|
|
|
|
|
nST = gpio_read(nSTATUS)
|
|
|
|
|
n=0
|
|
|
|
|
while nST and n<timeout:
|
|
|
|
|
n += 1
|
|
|
|
|
nST = gpio_read(nSTATUS)
|
|
|
|
|
if _verbosity>=2:
|
|
|
|
|
sys.stderr.write("nCONFIG=%d nSTATUS=%d CONF_DONE=%d\n"
|
|
|
|
|
% (gpio_read(nCONFIG),
|
|
|
|
|
nST,
|
|
|
|
|
gpio_read(CONF_DONE),
|
|
|
|
|
))
|
|
|
|
|
gpio_write(nCONFIG, 1);
|
|
|
|
|
if nST:
|
|
|
|
|
raise IOError("nSTATUS does not go low")
|
|
|
|
|
nST = gpio_read(nSTATUS)
|
|
|
|
|
n=0
|
|
|
|
|
while not nST and n<timeout:
|
|
|
|
|
n += 1
|
|
|
|
|
nST = gpio_read(nSTATUS)
|
|
|
|
|
if _verbosity>=2:
|
|
|
|
|
sys.stderr.write("nCONFIG=%d nSTATUS=%d CONF_DONE=%d\n"
|
|
|
|
|
% (gpio_read(nCONFIG),
|
|
|
|
|
nST,
|
|
|
|
|
gpio_read(CONF_DONE),
|
|
|
|
|
))
|
|
|
|
|
if not nST:
|
|
|
|
|
raise IOError("nSTATUS does not go high")
|
|
|
|
|
|
|
|
|
|
def altera_from_file(fn='rpirena.rbf', hz=30000000):
|
|
|
|
|
altera_reset()
|
|
|
|
|
spidev.set_mode(cpol=0, cpha=0)
|
|
|
|
|
spidev.set_speed(hz=hz)
|
2021-07-30 17:11:19 +00:00
|
|
|
f = open(fn, "rb")
|
2015-01-12 20:54:16 +00:00
|
|
|
n = 0
|
|
|
|
|
while True:
|
|
|
|
|
b = f.read(1024)
|
|
|
|
|
if not b:
|
|
|
|
|
break
|
|
|
|
|
n += len(b)
|
|
|
|
|
spidev.sync_transfer(cmd=b, flags=spidev.INVERT_BITS_OUT, rsize=0)
|
|
|
|
|
nST = gpio_read(nSTATUS)
|
|
|
|
|
if not nST:
|
|
|
|
|
IOError("nSTATUS went low during config")
|
|
|
|
|
if _verbosity >= 2:
|
|
|
|
|
CD = gpio_read(CONF_DONE)
|
|
|
|
|
if _verbosity >= 3 or CD:
|
|
|
|
|
sys.stderr.write("Altera config %d bytes, CONF_DONE=%d\n"
|
|
|
|
|
% (n, CD))
|
2019-05-05 04:20:47 +00:00
|
|
|
sleep(1)
|
2015-01-12 20:54:16 +00:00
|
|
|
CD = gpio_read(CONF_DONE)
|
|
|
|
|
if not CD:
|
2026-06-24 13:23:53 +00:00
|
|
|
raise IOError(f"CONF_DONE did not go high after config nSTATUS={gpio_read(nSTATUS)}")
|
2015-01-12 20:54:16 +00:00
|
|
|
spidev.set_mode(cpol=0, cpha=1)
|
|
|
|
|
|
|
|
|
|
def cmdstr(w):
|
|
|
|
|
if w & 0xffff4000:
|
|
|
|
|
return struct.pack(">HH", w&0xffff, w>>16)
|
|
|
|
|
return struct.pack(">H", w)
|
|
|
|
|
|
|
|
|
|
def sync(w):
|
|
|
|
|
r = spidev.sync_transfer(cmd=cmdstr(w))
|
|
|
|
|
if len(r)==4:
|
|
|
|
|
return struct.unpack(">HH", r)
|
|
|
|
|
return struct.unpack(">H", r)[0]
|
|
|
|
|
|
|
|
|
|
def reg(a, d=None):
|
|
|
|
|
if d==None:
|
|
|
|
|
c = struct.pack(">3H", a|0x8000, 0x8001, 0);
|
|
|
|
|
else:
|
|
|
|
|
c = struct.pack(">4H", a|0xc000, d, 0x8001, 0);
|
|
|
|
|
return struct.unpack(">H", spidev.sync_transfer(cmd=c, rsize=2))[0]
|
|
|
|
|
|
2025-02-03 15:10:09 +00:00
|
|
|
def readfifo(fifo, magic=0, mask=0, size=0):
|
|
|
|
|
if magic and not mask:
|
|
|
|
|
mask = 0xffff
|
|
|
|
|
n = reg(0x10 | fifo) & 0xfff
|
|
|
|
|
c = struct.pack(f">{n+2}H", 0x8014 | fifo, *((0x8001,)*n), 0)
|
|
|
|
|
d = struct.unpack(f">{n}H", spidev.sync_transfer(cmd=c, rsize=2*n))
|
2025-01-26 18:56:30 +00:00
|
|
|
i = 0
|
|
|
|
|
while i < n and (d[i] & mask) != magic:
|
|
|
|
|
i += 1
|
2025-02-03 15:10:09 +00:00
|
|
|
if size and i + size > n:
|
2025-01-26 18:56:30 +00:00
|
|
|
raise IOError(f"invalid packet({fifo}, {magic:04x}, {mask:04x}) → {repr(d)}")
|
|
|
|
|
return d[i:]
|