]>
iEval git - yule.git/blob - libiceblink.py
6cdfe1e32f0aec7276946cc06c4251fcd9678386
8 class ProtocolError(Exception):
11 class SPIProtocolError(Exception):
12 def __init__(self
, cmd
, rescode
):
15 4: "Resource not opened",
21 err
= "error code %d" % rescode
23 ProtocolError
.__init
__(self
, "Command %s failed with error: %s" %( cmd
,
31 CMD_WRITE_ENABLE
= 0x6
35 CMD_PAGE_PROGRAM
= 0x02
38 def __init__(self
, iofn
):
42 self
.io([self
.CMD_WAKEUP
])
44 def setWritable(self
):
45 self
.io([self
.CMD_WRITE_ENABLE
])
49 self
.io([self
.CMD_CHIP_ERASE
])
52 def read(self
, addr
, size
):
53 return self
.io([self
.CMD_FAST_READ
, (addr
>>16) & 0xFF, (addr
>>8)&0xFF, addr
&
54 0xFF, 0x00], size
+5)[5:]
55 def pageProgram(self
, addr
, buf
):
57 assert len(buf
) <= 256
58 assert addr
& 0xFF == 0
60 self
.io([self
.CMD_PAGE_PROGRAM
, (addr
>>16) & 0xFF, (addr
>>8)&0xFF, addr
&
65 while self
.getStatus() & self
.STAT_BUSY
:
69 return self
.io([self
.CMD_GET_STATUS
],2)[1]
72 return self
.io([self
.CMD_READ_ID
],4)[1:]
75 class ICE40Board(object):
77 CMD_GET_BOARD_TYPE
= 0xE2
78 CMD_GET_BOARD_SERIAL
= 0xE4
80 class __ICE40BoardComm(object):
81 def __init__(self
, dev
):
82 self
.__is
_open
= False
89 def __exit__(self
, type, err
, traceback
):
100 assert not self
.__is
_open
101 self
.dev
.checked_cmd(0x04, 0x00, "bcommopen", [0x00], noret
=True)
102 self
.__is
_open
= True
105 assert self
.__is
_open
106 self
.dev
.checked_cmd(0x04, 0x01, "bcommclose", [0x00], noret
=True,
108 self
.__is
_open
= False
110 def __check_counts(self
, status
, resb
, wr
, rd
):
112 wb
= struct
.unpack('<L', resb
[:4])[0]
114 #print (wb, write_byte_count)
118 rb
= struct
.unpack('<L', resb
[:4])[0]
122 def readReg(self
, regno
):
123 self
.dev
.checked_cmd(0x04, 0x05, "bcommsetval", [0x00, regno
,
124 0x01, 0x00, 0x00, 0x0])
125 res
= self
.dev
.ep_datain
.read(1)
126 status
, pl
= self
.dev
.cmd(0x04, 0x85, [0x00])
127 self
.__check
_counts
(status
, pl
, 0, 1)
130 def writeReg(self
, regno
, value
):
131 self
.dev
.checked_cmd(0x04, 0x04, "bcommsetval", [0x00, regno
,
132 0x01, 0x00, 0x00, 0x0])
133 self
.dev
.ep_dataout
.write([value
])
134 status
, pl
= self
.dev
.cmd(0x04, 0x85, [0x00])
135 self
.__check
_counts
(status
, pl
, 1, 0)
137 def readMulti(self
, addrs
):
140 def writeMulti(self
, addrvals
):
143 class __ICE40GPIO(object):
144 def __init__(self
, dev
):
145 self
.__is
_open
= False
152 def __exit__(self
, type, err
, traceback
):
159 assert not self
.__is
_open
161 self
.dev
.checked_cmd(0x03, 0x00, "gpioopen", [0x00], noret
=True)
162 self
.__is
_open
= True
165 assert self
.__is
_open
166 self
.dev
.checked_cmd(0x03, 0x01, "gpioclose", 0x00)
167 self
.__is
_open
= False
173 def __set_dir(self
, direction
):
174 self
.dev
.checked_cmd(0x03, 0x04, "0304", [0x00, direction
, 0x00,
177 def __set_value(self
, value
):
178 self
.dev
.checked_cmd(0x03, 0x06, "0306", [0x00, value
, 0x00, 0x00,
181 def ice40SetReset(self
, assert_reset
):
189 class __ICE40SPIPort(object):
190 def __init__(self
, dev
, portno
):
192 self
.__portno
= portno
193 assert portno
== 0x00
194 self
.__is
_open
= False
200 def __exit__(self
, type, exc
, traceback
):
210 def io(self
, write_bytes
, read_byte_count
=0):
211 assert self
.__is
_open
212 write_bytes
= list(write_bytes
)
214 # Pad write bytes to include 00's for readback
215 if len(write_bytes
) < read_byte_count
:
216 write_bytes
.extend([0] * (read_byte_count
- len(write_bytes
)))
218 write_byte_count
= len(write_bytes
)
221 # probably assert nCS
222 self
.dev
.checked_cmd(0x06, 0x06, "SPIStart", [0x00, 0x00])
226 self
.dev
.checked_cmd(0x06, 0x07, "SPIIOStart",
228 # the meaning of the first 3 bytes is unknown
229 struct
.pack("<BBBBL", 0x00, 0x00, 0x00,
230 0x01 if read_byte_count
else 0x00,
231 write_byte_count
),noret
=True)
234 while write_bytes
or len(read_bytes
) < read_byte_count
:
236 self
.dev
.ep_dataout
.write(write_bytes
[:64])
237 write_bytes
= write_bytes
[64:]
240 to_read
= min(64, read_byte_count
)
241 read_bytes
.extend(self
.dev
.ep_datain
.read(to_read
))
246 status
, resb
=self
.dev
.cmd(0x06, 0x87,[0x00])
248 # status & 0x80 indicates presence of write size
249 # status & 0x40 indicates presence of read size
252 wb
= struct
.unpack('<L', resb
[:4])[0]
254 #print (wb, write_byte_count)
255 assert wb
== write_byte_count
258 rb
= struct
.unpack('<L', resb
[:4])[0]
260 assert rb
== read_byte_count
263 self
.dev
.checked_cmd(0x06, 0x06, "0606", [0x00, 0x01])
265 return bytes(read_bytes
)
268 assert not self
.__is
_open
269 pl
= self
.dev
.checked_cmd(0x06, 0x00, "SPIOpen", [self
.__portno
])
271 self
.__is
_open
= True
274 pl
= self
.dev
.checked_cmd(0x06, 0x01, "SPIClose", [self
.__portno
])
276 self
.__is
_open
= False
279 """May be mode-setting. [0,2] causes bits to be returned shifted right
281 assert self
.__is
_open
282 pl
= self
.dev
.checked_cmd(0x06, 0x05, "SpiMode", [0,0])
285 def setSpeed(self
, speed
):
286 """ sets the desired speed for the SPI interface. Returns actual speed
288 pl
= self
.dev
.checked_cmd(0x06, 0x03, "SPISpeed", b
'\x00' +
289 struct
.pack("<L", speed
))
290 assert self
.__is
_open
291 return (struct
.unpack("<L",pl
),)
295 # find our self.device
296 self
.dev
= usb
.core
.find(idVendor
=0x1443, idProduct
=0x0007)
298 raise ValueError('Device not found')
300 self
.dev
.set_configuration()
302 # get an endpoint instance
303 cfg
= self
.dev
.get_active_configuration()
304 intf
= usb
.util
.find_descriptor(cfg
)
306 # Allocate and verify all the endpoints used for comms
307 self
.ep_cmdout
= usb
.util
.find_descriptor(intf
, bEndpointAddress
= 1)
308 self
.ep_cmdin
= usb
.util
.find_descriptor(intf
, bEndpointAddress
= 0x82)
309 self
.ep_dataout
= usb
.util
.find_descriptor(intf
, bEndpointAddress
= 3)
310 self
.ep_datain
= usb
.util
.find_descriptor(intf
, bEndpointAddress
= 0x84)
312 assert self
.ep_cmdout
is not None
313 assert self
.ep_cmdin
is not None
314 assert self
.ep_dataout
is not None
315 assert self
.ep_datain
is not None
317 # Make sure we're talking to what we expect
318 btype
= self
.get_board_type()
319 assert btype
== 'iCE40'
321 def get_spi_port(self
, pn
):
322 return self
.__ICE
40SPIPort
(self
, pn
)
325 return self
.__ICE
40GPIO
(self
)
327 def get_board_comm(self
):
328 return self
.__ICE
40BoardComm
(self
)
330 def ctrl(self
, selector
, size_or_data
, show
=False):
331 val
= self
.dev
.ctrl_transfer(0xC0 if isinstance(size_or_data
, int) else 0x04,
332 selector
, 0x00, 0x00, size_or_data
)
333 if show
and isinstance(val
, array
.array
):
334 print("%2x < %s" % (selector
, "".join("%02x" % i
for i
in val
)))
337 def checked_cmd(self
, cmd
, subcmd
, name
, payload
=[], ressize
=16, show
=False,
339 status
, respl
= self
.cmd(cmd
, subcmd
, payload
, ressize
, show
)
341 raise SPIProtocolError(name
, status
)
343 assert len(respl
) == 0
346 def cmd(self
, cmd
, subcmd
, payload
, ressize
=16, show
=False):
348 struct
.pack("<BB", cmd
, subcmd
) + bytes(payload
),
353 print ("%02x:%02x (%s) < %02x:(%s)" % (cmd
, subcmd
,
354 binascii
.hexlify(bytes(payload
)).decode('ascii'),
356 binascii
.hexlify(res
[1:]).decode('ascii')))
357 return status
, res
[1:]
359 def cmd_i(self
, cmd_bytes
, result_size
, show
=False):
360 payload
= struct
.pack('<B', len(cmd_bytes
)) + bytes(cmd_bytes
)
361 self
.ep_cmdout
.write(payload
)
362 res
= bytes(self
.ep_cmdin
.read(result_size
))
365 print("%s:%s" % (binascii
.hexlify(payload
).decode('ascii'),
366 binascii
.hexlify(res
).decode('ascii')))
367 assert res
[0] == len(res
[1:])
370 def get_board_type(self
):
371 btype
= self
.ctrl(0xE2, 16)
372 return btype
[:btype
.index(b
'\x00')].decode('ascii')
374 def get_serial(self
):
375 return self
.ctrl(0xE4, 16).decode('ascii')
This page took 0.066641 seconds and 5 git commands to generate.