Commit 077d77d1 authored by Qiang Du's avatar Qiang Du

Update Etherbone IO classes. Support of multiple register IO using eb_cycle_read/write.

parent 9b3842f3
......@@ -48,5 +48,5 @@
# communication-type-specific parameters is the elma.write() and elma.read()
# methods, in the case of the ELMA_I2C_MULTIBOOT type.
ELMA_I2C_MULTIBOOT = 0;
ETHERBONE_MULTIBOOT = 1;
ETHERBONE = 1;
......@@ -27,7 +27,6 @@ class EB:
self.port_ip = 'udp/' + ip
self.write_cnt = 0
self.read_cnt = 0
self.open()
def open(self):
self.socket = eb.Socket()
......@@ -36,148 +35,32 @@ class EB:
self.device = eb.Device(self.socket, self.port_ip)
self.device.__enter__()
self.cycle = eb.Cycle(self.device, 0, 0)
self.cycle.__enter__()
def close(self):
self.cycle.close()
self.device.close()
self.socket.close()
def write(self, addr, val):
self.device.write(addr, val)
def writemregs(self, addr, dlist):
curr_addr = addr
self.cycle = eb.Cycle(self.device, 0, 0)
self.cycle.__enter__()
for i in dlist:
curr_addr += i
self.cycle.write(curr_addr, i)
self.cycle.close()
def read(self, addr):
return self.device.read(addr)
class EI2C:
"""Access a VME crate through Telnet."""
def __init__(self, ip, user, pwd):
"""Initialize EI2C class.
The arguments to init the class are mandatory:
ip -- IP address of VME crate
user -- username to login to VME crate
pwd -- password to login to VME crate
"""
self.ip = ip
self.user = user
self.pwd = pwd
self.write_cnt = 0
self.read_cnt = 0
if (ei2cdefine.DUMP):
self.f = open("dump.txt", 'w')
def open(self):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM);
try:
s.connect((self.ip, 23))
s.recv(30)
except (socket.gaierror, socket.error) as e:
raise BadHostnameError
s.send(self.user + "\r\n")
if "password" not in s.recv(30):
raise BadUsernameError
s.send(self.pwd + "\r\n")
if "Wrong password" in s.recv(30):
raise BadPasswordError
self.handle = s
def close(self):
self.handle.close()
if (ei2cdefine.DUMP):
self.f.close()
def write(self, slot, addr, val):
self.write_cnt += 1
#reg = addr/4 + 1
cmd = "writereg %d %x %x\r\n" % (slot, addr, val)
if (ei2cdefine.DUMP):
self.f.write(cmd);
self.handle.send(cmd)
self._strip_resp(self.handle.recv(30))
def read(self, slot, addr):
self.read_cnt += 1
#reg = addr/4 + 1
cmd = "readreg %d %x\r\n" % (slot, addr)
if (ei2cdefine.DUMP):
self.f.write(cmd);
self.handle.send(cmd)
resp = self._strip_resp(self.handle.recv(30))
return resp
def writemregs(self, slot, addr, val):
self.write_cnt += 1
#reg = addr/4 + 1
#print '%02x' % sl
cmd = "writemregs %d %x %s\r\n" % (slot, addr, ' '.join(format(b,'x') for b in val))
if (ei2cdefine.DUMP):
self.f.write(cmd);
#print cmd
self.handle.send(cmd)
self._strip_resp(self.handle.recv(30))
def readmregs(self, slot, addr, nrregs):
self.read_cnt += 1
#reg = addr/4 + 1
cmd = "readmregs %d %x %d\r\n" % (slot, addr, nrregs)
if (ei2cdefine.DUMP):
self.f.write(cmd);
self.handle.send(cmd)
resp = self._strip_resp(self.handle.recv(30))
return resp
def _strip_resp(self, msg):
"""Strip useful message from SysMon response.
The response string from the SysMon is stripped of unnecessary characters
and a "useful" string is returned. In case one of the error messages appear,
the function raises one of the EI2C exceptions."""
#print msg.splitlines()
msg = msg.splitlines()[1]
if (ei2cdefine.DUMP):
self.f.write(msg + "\n")
if "Not Ack" in msg:
raise NAckError
if "Invalid register number!" in msg:
raise RegNumberError
if "Bad command!" in msg:
raise InvalidCmdError
if "I2C Timer expired" in msg:
raise TimerExpiredError
if "Invalid slot number!" in msg:
raise SlotError
if "Read Data:" in msg:
msg = msg.split(" ")[3]
msg = int(msg,16)
return msg
# MAIN "FUNCTION"
if __name__ == "__main__":
address = 0x20810
if (0):
with eb.Socket() as socket:
with eb.Device(socket, 'udp/rflab2') as device:
with eb.Cycle(device, 0, 0) as cycle:
data = cycle.read(address)
print hex(data.value)
print 'EB test'
ebi = EB('rflab2')
print hex(ebi.read(address).value)
def readmregs(self, addr, nrregs):
curr_addr = addr
dlist = []
self.cycle = eb.Cycle(self.device, 0, 0)
self.cycle.__enter__()
for i in xrange(nrregs):
curr_addr += i
dlist[i] = self.cycle.read(curr_addr)
self.cycle.close()
return dlist
......@@ -104,14 +104,6 @@ class Socket():
All method return codes are identical to their plain C interface
counterparts.
"""
#_fields_ = [
# ('device_ring', Ring),
# ('vdevice_ring', Ring),
# ('socket', POINTER(eb_socket_t)),
# ('response_table', POINTER(Response)),
# ('response_index', c_int),
#]
def __init__(self, port=0, widths=EB_ADDRX|EB_DATAX):
self.abi_code = EB_ABI_CODE
self.socket = eb_socket_t()
......@@ -193,14 +185,10 @@ class Device():
"""
return lib.eb_device_width(self.device)
def flush(self):
"""flush commands queued on the device out the socket
"""
return lib.eb_device_flush(self.device)
def read(self, address):
"""perform a single-read wishbone cycle
Semantically equivalent to cycle_open, cycle_read, cycle_close, device_flush.
Semantically equivalent to cycle_open, cycle_read, cycle_close.
The given address is read on the remote device.
The callback cb(user, status, data) is invoked with the result.
......@@ -210,12 +198,12 @@ class Device():
user_data = None
callback = None
lib.eb_device_read(self.device, address, self.data_format, byref(data), user_data, callback)
return data
return data.value
def write(self, address, data):
"""perform a single-write wishbone cycle
Semantically equivalent to cycle_open, cycle_write, cycle_close, device_flush.
Semantically equivalent to cycle_open, cycle_write, cycle_close.
data is written to the given address on the remote device.
"""
user_data = None
......@@ -268,7 +256,7 @@ class Cycle():
"""
data = eb_data_t()
lib.eb_cycle_read(self.cycle, address, self.data_format, byref(data))
return data
return data.value
def write(self, address, data):
"""perform a wishbone write phase
......@@ -400,52 +388,10 @@ def eb_device_socket(device):
"""
return lib.eb_device_socket(device)
def eb_device_flush(socket):
"""
Flush commands queued on the device out the socket.
"""
return lib.eb_device_flush(socket)
def eb_cycle_open_read_only(device, userdata, cycle_callback):
"""
Begin a wishbone cycle on the remote device.
Read/write phases within a cycle hold the device locked.
All reads are executed first followed by all writes.
Until the cycle is closed, the operations are not queued.
If data was read, the callback is run upon cycle completion.
Status codes:
OK - the operation completed successfully
FAIL - the operation failed due to an wishbone ERR_O signal
ABORT - an earlier operation failed and this operation was thus aborted
OVERFLOW - too many operations queued for this cycle
"""
return lib.eb_cycle_open_read_only(device, userdata, cycle_callback)
def eb_cycle_open_read_write(device, user, cb, write_base, write_mode):
"""
Begin a wishbone cycle on the remote device.
Read/write phases within a cycle hold the device locked.
All reads are executed first followed by all writes.
Until the cycle is closed, the operations are not queued.
If data was read, the callback is run upon cycle completion.
Status codes:
OK - the operation completed successfully
FAIL - the operation failed due to an wishbone ERR_O signal
ABORT - an earlier operation failed and this operation was thus aborted
OVERFLOW - too many operations queued for this cycle
"""
return lib.eb_cycle_open_read_write(device, user, cb, write_base, write_mode)
def eb_cycle_close(cycle):
"""
End a wishbone cycle.
This places the complete cycle at end of the device''s send queue.
You will probably want to eb_flush_device soon after calling eb_cycle_close.
"""
return lib.eb_cycle_close(cycle)
......@@ -473,7 +419,7 @@ def eb_device_read(device, address, userdata, cb):
"""
Perform a single-read wishbone cycle.
Semantically equivalent to cycle_open, cycle_read, cycle_close, device_flush.
Semantically equivalent to cycle_open, cycle_read, cycle_close.
The given address is read on the remote device.
The callback cb(user, status, data) is invoked with the result.
......@@ -489,7 +435,7 @@ def eb_device_read(device, address, userdata, cb):
def eb_device_write(device, address, data):
"""
Perform a single-write wishbone cycle.
Semantically equivalent to cycle_open, cycle_write, cycle_close, device_flush.
Semantically equivalent to cycle_open, cycle_write, cycle_close.
data is written to the given address on the remote device.
"""
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment