@@ -164,7 +164,7 @@ def __init__(self, vid=FT232H_VID, pid=FT232H_PID, serial=None):
164164 self ._mpsse_enable ()
165165 self ._mpsse_sync ()
166166 # Initialize all GPIO as inputs.
167- self ._write ('\x80 \x00 \x00 \x82 \x00 \x00 ' )
167+ self ._write (b '\x80 \x00 \x00 \x82 \x00 \x00 ' )
168168 self ._direction = 0x0000
169169 self ._level = 0x0000
170170
@@ -181,14 +181,17 @@ def _write(self, string):
181181 # Get modem status. Useful to enable for debugging.
182182 #ret, status = ftdi.poll_modem_status(self._ctx)
183183 #if ret == 0:
184- # logger.debug('Modem status {0:02X}'.format(status))
184+ # logger.debug('Modem status {0:02X}'.format(status))
185185 #else:
186- # logger.debug('Modem status error {0}'.format(ret))
186+ # logger.debug('Modem status error {0}'.format(ret))
187187 length = len (string )
188- ret = ftdi .write_data (self ._ctx , string , length )
188+ try :
189+ ret = ftdi .write_data (self ._ctx , string , length )
190+ except TypeError :
191+ ret = ftdi .write_data (self ._ctx , string ); #compatible with libFtdi 1.3
189192 # Log the string that was written in a python hex string format using a very
190193 # ugly one-liner list comprehension for brevity.
191- #logger.debug('Wrote {0}'.format(''.join(['\\x{0:02X}'.format(ord(x)) for x in string])))
194+ #logger.debug('Wrote {0}'.format(''.join(['\\x{0:02X}'.format(x) for x in bytearray( string) ])))
192195 if ret < 0 :
193196 raise RuntimeError ('ftdi_write_data failed with error {0}: {1}' .format (ret , ftdi .get_error_string (self ._ctx )))
194197 if ret != length :
@@ -224,7 +227,7 @@ def _poll_read(self, expected, timeout_s=5.0):
224227 index += ret
225228 # Buffer is full, return the result data.
226229 if index >= expected :
227- return str (response )
230+ return bytes (response )
228231 time .sleep (0.01 )
229232 raise RuntimeError ('Timeout while polling ftdi_read_data for {0} bytes!' .format (expected ))
230233
@@ -240,14 +243,14 @@ def _mpsse_sync(self, max_retries=10):
240243 error response. Should be called once after enabling MPSSE."""
241244 # Send a bad/unknown command (0xAB), then read buffer until bad command
242245 # response is found.
243- self ._write ('\xAB ' )
246+ self ._write (b '\xAB ' )
244247 # Keep reading until bad command response (0xFA 0xAB) is returned.
245248 # Fail if too many read attempts are made to prevent sticking in a loop.
246249 tries = 0
247250 sync = False
248251 while not sync :
249252 data = self ._poll_read (2 )
250- if data == '\xFA \xAB ' :
253+ if data == b '\xFA \xAB ' :
251254 sync = True
252255 tries += 1
253256 if tries >= max_retries :
@@ -258,20 +261,20 @@ def mpsse_set_clock(self, clock_hz, adaptive=False, three_phase=False):
258261 to 30mhz and will pick that speed or the closest speed below it.
259262 """
260263 # Disable clock divisor by 5 to enable faster speeds on FT232H.
261- self ._write ('\x8A ' )
264+ self ._write (b '\x8A ' )
262265 # Turn on/off adaptive clocking.
263266 if adaptive :
264- self ._write ('\x96 ' )
267+ self ._write (b '\x96 ' )
265268 else :
266- self ._write ('\x97 ' )
269+ self ._write (b '\x97 ' )
267270 # Turn on/off three phase clock (needed for I2C).
268271 # Also adjust the frequency for three-phase clocking as specified in section 2.2.4
269272 # of this document:
270273 # http://www.ftdichip.com/Support/Documents/AppNotes/AN_255_USB%20to%20I2C%20Example%20using%20the%20FT232H%20and%20FT201X%20devices.pdf
271274 if three_phase :
272- self ._write ('\x8C ' )
275+ self ._write (b '\x8C ' )
273276 else :
274- self ._write ('\x8D ' )
277+ self ._write (b '\x8D ' )
275278 # Compute divisor for requested clock.
276279 # Use equation from section 3.8.1 of:
277280 # http://www.ftdichip.com/Support/Documents/AppNotes/AN_108_Command_Processor_for_MPSSE_and_MCU_Host_Bus_Emulation_Modes.pdf
@@ -281,14 +284,14 @@ def mpsse_set_clock(self, clock_hz, adaptive=False, three_phase=False):
281284 divisor = int (divisor * (2.0 / 3.0 ))
282285 logger .debug ('Setting clockspeed with divisor value {0}' .format (divisor ))
283286 # Send command to set divisor from low and high byte values.
284- self ._write (str (bytearray ((0x86 , divisor & 0xFF , (divisor >> 8 ) & 0xFF ))))
287+ self ._write (bytes (bytearray ((0x86 , divisor & 0xFF , (divisor >> 8 ) & 0xFF ))))
285288
286289 def mpsse_read_gpio (self ):
287290 """Read both GPIO bus states and return a 16 bit value with their state.
288291 D0-D7 are the lower 8 bits and C0-C7 are the upper 8 bits.
289292 """
290293 # Send command to read low byte and high byte.
291- self ._write ('\x81 \x83 ' )
294+ self ._write (b '\x81 \x83 ' )
292295 # Wait for 2 byte response.
293296 data = self ._poll_read (2 )
294297 # Assemble response into 16 bit value.
@@ -301,11 +304,11 @@ def mpsse_gpio(self):
301304 """Return command to update the MPSSE GPIO state to the current direction
302305 and level.
303306 """
304- level_low = chr (self ._level & 0xFF )
305- level_high = chr ((self ._level >> 8 ) & 0xFF )
306- dir_low = chr (self ._direction & 0xFF )
307- dir_high = chr ((self ._direction >> 8 ) & 0xFF )
308- return str (bytearray ((0x80 , level_low , dir_low , 0x82 , level_high , dir_high )))
307+ level_low = (self ._level & 0xFF )
308+ level_high = ((self ._level >> 8 ) & 0xFF )
309+ dir_low = (self ._direction & 0xFF )
310+ dir_high = ((self ._direction >> 8 ) & 0xFF )
311+ return bytes (bytearray ((0x80 , level_low , dir_low , 0x82 , level_high , dir_high )))
309312
310313 def mpsse_write_gpio (self ):
311314 """Write the current MPSSE GPIO state to the FT232H chip."""
@@ -395,8 +398,8 @@ def __init__(self, ft232h, cs=None, max_speed_hz=1000000, mode=0, bitorder=MSBFI
395398 self ._ft232h = ft232h
396399 # Initialize chip select pin if provided to output high.
397400 if cs is not None :
398- ft232h .setup (cs , GPIO .OUT )
399401 ft232h .set_high (cs )
402+ ft232h .setup (cs , GPIO .OUT )
400403 self ._cs = cs
401404 # Initialize clock, mode, and bit order.
402405 self .set_clock_hz (max_speed_hz )
@@ -467,64 +470,161 @@ def write(self, data):
467470 """Half-duplex SPI write. The specified array of bytes will be clocked
468471 out the MOSI line.
469472 """
473+ #check for hardware limit of FT232H and similar MPSSE chips
474+ if (len (data ) > 65536 ):
475+ print ('the FTDI chip is limited to 65536 bytes (64 KB) of input/output per command!' )
476+ print ('use for loops for larger reads' )
477+ exit (1 )
470478 # Build command to write SPI data.
471479 command = 0x10 | (self .lsbfirst << 3 ) | self .write_clock_ve
472480 logger .debug ('SPI write with command {0:2X}.' .format (command ))
473481 # Compute length low and high bytes.
474482 # NOTE: Must actually send length minus one because the MPSSE engine
475483 # considers 0 a length of 1 and FFFF a length of 65536
476- length = len (data )- 1
477- len_low = length & 0xFF
478- len_high = (length >> 8 ) & 0xFF
484+ # splitting into two lists for two commands to prevent buffer errors
485+ data1 = data [:len (data )// 2 ]
486+ data2 = data [len (data )// 2 :]
487+ len_low1 = (len (data1 ) - 1 ) & 0xFF
488+ len_high1 = ((len (data1 ) - 1 ) >> 8 ) & 0xFF
489+ len_low2 = (len (data2 ) - 1 ) & 0xFF
490+ len_high2 = ((len (data2 ) - 1 ) >> 8 ) & 0xFF
479491 self ._assert_cs ()
480- # Send command and length.
481- self ._ft232h ._write (str (bytearray ((command , len_low , len_high ))))
482- # Send data.
483- self ._ft232h ._write (str (bytearray (data )))
492+ # Send command and length, then data, split into two commands, handle for length 1
493+ if len (data1 ) > 0 :
494+ self ._ft232h ._write (bytes (bytearray ((command , len_low1 , len_high1 ))))
495+ self ._ft232h ._write (bytes (bytearray (data1 )))
496+ if len (data2 ) > 0 :
497+ self ._ft232h ._write (bytes (bytearray ((command , len_low2 , len_high2 ))))
498+ self ._ft232h ._write (bytes (bytearray (data2 )))
484499 self ._deassert_cs ()
485500
486501 def read (self , length ):
487502 """Half-duplex SPI read. The specified length of bytes will be clocked
488503 in the MISO line and returned as a bytearray object.
489504 """
505+ #check for hardware limit of FT232H and similar MPSSE chips
506+ if (1 > length > 65536 ):
507+ print ('the FTDI chip is limited to 65536 bytes (64 KB) of input/output per command!' )
508+ print ('use for loops for larger reads' )
509+ exit (1 )
490510 # Build command to read SPI data.
491511 command = 0x20 | (self .lsbfirst << 3 ) | (self .read_clock_ve << 2 )
492512 logger .debug ('SPI read with command {0:2X}.' .format (command ))
493513 # Compute length low and high bytes.
494514 # NOTE: Must actually send length minus one because the MPSSE engine
495515 # considers 0 a length of 1 and FFFF a length of 65536
496- len_low = (length - 1 ) & 0xFF
497- len_high = ((length - 1 ) >> 8 ) & 0xFF
516+ #force odd numbers to round up instead of down
517+ lengthR = length
518+ if length % 2 == 1 :
519+ lengthR += 1
520+ lengthR = lengthR // 2
521+ #when odd length requested, get the remainder instead of the same number
522+ lenremain = length - lengthR
523+ len_low = (lengthR - 1 ) & 0xFF
524+ len_high = ((lengthR - 1 ) >> 8 ) & 0xFF
498525 self ._assert_cs ()
499526 # Send command and length.
500- self ._ft232h ._write (str (bytearray ((command , len_low , len_high , 0x87 ))))
527+ # Perform twice to prevent error from hardware defect/limits
528+ self ._ft232h ._write (bytes (bytearray ((command , len_low , len_high ))))
529+ payload1 = self ._ft232h ._poll_read (lengthR )
530+ self ._ft232h ._write (bytes (bytearray ((command , len_low , len_high ))))
531+ payload2 = self ._ft232h ._poll_read (lenremain )
501532 self ._deassert_cs ()
502- # Read response bytes.
503- return bytearray (self ._ft232h ._poll_read (length ))
533+ # Read response bytes
534+ return bytearray (payload1 + payload2 )
535+
536+ def bulkread (self , data = [], lengthR = 'None' , readmode = 1 ):
537+ """Half-duplex SPI write then read. Send command and payload to slave as bytearray
538+ then consequently read out response from the slave for length in bytes.
539+ Designed for use with NOR or NAND flash chips, and possibly SD cards...etc...
540+ Read command is cut in half and performed twice in series to prevent single byte errors.
541+ Hardware limits per command are enforced before doing anything.
542+ Read length is an optional argument, so that it can function similar to transfer
543+ but still half-duplex.
544+ For reading without writing, one can send a blank array or skip that argument.
545+ """
546+ #check for hardware limit of FT232H and similar MPSSE chips
547+ if (1 > lengthR > 65536 )| (len (data ) > 65536 ):
548+ print ('the FTDI chip is limited to 65536 bytes (64 KB) of input/output per command!' )
549+ print ('use for loops for larger reads' )
550+ exit (1 )
551+ #default mode is to act like `transfer` but half-duplex
552+ if (lengthR == 'None' )& (readmode == 1 ):
553+ lengthR = len (data )
554+ #command parameters definition and math
555+ #MPSSE engine sees length 0 as 1 byte, so - 1 lengths
556+ commandW = 0x10 | (self .lsbfirst << 3 ) | self .write_clock_ve
557+ lengthW = len (data ) - 1
558+ len_lowW = (lengthW ) & 0xFF
559+ len_highW = ((lengthW ) >> 8 ) & 0xFF
560+ commandR = 0x20 | (self .lsbfirst << 3 ) | (self .read_clock_ve << 2 )
561+ #force odd numbers to round up instead of down
562+ length = lengthR
563+ if lengthR % 2 == 1 :
564+ length += 1
565+ length = length // 2
566+ #when odd length requested, get the remainder instead of the same number
567+ lenremain = lengthR - length
568+ len_lowR = (length - 1 ) & 0xFF
569+ len_highR = ((length - 1 ) >> 8 ) & 0xFF
570+ #logger debug info
571+ logger .debug ('SPI bulkread with write command {0:2X}.' .format (commandW ))
572+ logger .debug ('and read command {0:2X}.' .format (commandR ))
573+ #begin command set
574+ self ._assert_cs ()
575+ #write command, these have to be separated due to TypeError
576+ self ._ft232h ._write (bytes (bytearray ((commandW , len_lowW , len_highW ))))
577+ self ._ft232h ._write (bytes (bytearray (data )))
578+ #read command, which is divided into two commands
579+ self ._ft232h ._write (bytes (bytearray ((commandR , len_lowR , len_highR ))))
580+ payload1 = self ._ft232h ._poll_read (length )
581+ self ._ft232h ._write (bytes (bytearray ((commandR , len_lowR , len_highR ))))
582+ payload2 = self ._ft232h ._poll_read (lenremain )
583+ self ._deassert_cs ()
584+ #end command set
585+ # Read response bytes
586+ return bytearray (payload1 + payload2 )
504587
505588 def transfer (self , data ):
506589 """Full-duplex SPI read and write. The specified array of bytes will be
507590 clocked out the MOSI line, while simultaneously bytes will be read from
508591 the MISO line. Read bytes will be returned as a bytearray object.
509592 """
593+ #check for hardware limit of FT232H and similar MPSSE chips
594+ if (len (data ) > 65536 ):
595+ print ('the FTDI chip is limited to 65536 bytes (64 KB) of input/output per command!' )
596+ print ('use for loops for larger reads' )
597+ exit (1 )
510598 # Build command to read and write SPI data.
511599 command = 0x30 | (self .lsbfirst << 3 ) | (self .read_clock_ve << 2 ) | self .write_clock_ve
512600 logger .debug ('SPI transfer with command {0:2X}.' .format (command ))
513601 # Compute length low and high bytes.
514602 # NOTE: Must actually send length minus one because the MPSSE engine
515603 # considers 0 a length of 1 and FFFF a length of 65536
516- length = len (data )
517- len_low = (length - 1 ) & 0xFF
518- len_high = ((length - 1 ) >> 8 ) & 0xFF
519- # Send command and length.
604+ data1 = data [:len (data )// 2 ]
605+ data2 = data [len (data )// 2 :]
606+ len_low1 = (len (data1 ) - 1 ) & 0xFF
607+ len_high1 = ((len (data1 ) - 1 ) >> 8 ) & 0xFF
608+ len_low2 = (len (data2 ) - 1 ) & 0xFF
609+ len_high2 = ((len (data2 ) - 1 ) >> 8 ) & 0xFF
610+ payload1 = ''
611+ payload2 = ''
612+ #start command set
520613 self ._assert_cs ()
521- self ._ft232h ._write (str (bytearray ((command , len_low , len_high ))))
522- self ._ft232h ._write (str (bytearray (data )))
523- self ._ft232h ._write ('\x87 ' )
614+ # Perform twice to prevent error from hardware defect/limits
615+ # Send command and length, then data, split into two commands, handle for length 1
616+ if len (data1 ) > 0 :
617+ self ._ft232h ._write (bytes (bytearray ((command , len_low1 , len_high1 ))))
618+ self ._ft232h ._write (bytes (bytearray (data1 )))
619+ payload1 = self ._ft232h ._poll_read (len (data1 ))
620+ if len (data2 ) > 0 :
621+ self ._ft232h ._write (bytes (bytearray ((command , len_low2 , len_high2 ))))
622+ self ._ft232h ._write (bytes (bytearray (data2 )))
623+ payload2 = self ._ft232h ._poll_read (len (data2 ))
624+ #self._ft232h._write('\x87')
524625 self ._deassert_cs ()
525626 # Read response bytes.
526- return bytearray (self ._ft232h ._poll_read (length ))
527-
627+ return bytearray (payload1 + payload2 )
528628
529629class I2CDevice (object ):
530630 """Class for communicating with an I2C device using the smbus library.
@@ -542,7 +642,7 @@ def __init__(self, ft232h, address, clock_hz=100000):
542642 # Enable drive-zero mode to drive outputs low on 0 and tri-state on 1.
543643 # This matches the protocol for I2C communication so multiple devices can
544644 # share the I2C bus.
545- self ._ft232h ._write ('\x9E \x07 \x00 ' )
645+ self ._ft232h ._write (b '\x9E \x07 \x00 ' )
546646 self ._idle ()
547647
548648 def _idle (self ):
@@ -560,9 +660,9 @@ def _transaction_start(self):
560660 def _transaction_end (self ):
561661 """End I2C transaction and get response bytes, including ACKs."""
562662 # Ask to return response bytes immediately.
563- self ._command .append ('\x87 ' )
663+ self ._command .append (b '\x87 ' )
564664 # Send the entire command to the MPSSE.
565- self ._ft232h ._write ('' .join (self ._command ))
665+ self ._ft232h ._write (b '' .join (self ._command ))
566666 # Read response bytes and return them.
567667 return bytearray (self ._ft232h ._poll_read (self ._expected ))
568668
@@ -603,12 +703,12 @@ def _i2c_read_bytes(self, length=1):
603703 """
604704 for i in range (length - 1 ):
605705 # Read a byte and send ACK.
606- self ._command .append ('\x20 \x00 \x00 \x13 \x00 \x00 ' )
706+ self ._command .append (b '\x20 \x00 \x00 \x13 \x00 \x00 ' )
607707 # Make sure pins are back in idle state with clock low and data high.
608708 self ._ft232h .output_pins ({0 : GPIO .LOW , 1 : GPIO .HIGH }, write = False )
609709 self ._command .append (self ._ft232h .mpsse_gpio ())
610710 # Read last byte and send NAK.
611- self ._command .append ('\x20 \x00 \x00 \x13 \x00 \xFF ' )
711+ self ._command .append (b '\x20 \x00 \x00 \x13 \x00 \xFF ' )
612712 # Make sure pins are back in idle state with clock low and data high.
613713 self ._ft232h .output_pins ({0 : GPIO .LOW , 1 : GPIO .HIGH }, write = False )
614714 self ._command .append (self ._ft232h .mpsse_gpio ())
@@ -619,12 +719,12 @@ def _i2c_write_bytes(self, data):
619719 """Write the specified number of bytes to the chip."""
620720 for byte in data :
621721 # Write byte.
622- self ._command .append (str (bytearray ((0x11 , 0x00 , 0x00 , byte ))))
722+ self ._command .append (bytes (bytearray ((0x11 , 0x00 , 0x00 , byte ))))
623723 # Make sure pins are back in idle state with clock low and data high.
624724 self ._ft232h .output_pins ({0 : GPIO .LOW , 1 : GPIO .HIGH }, write = False )
625725 self ._command .append (self ._ft232h .mpsse_gpio () * _REPEAT_DELAY )
626726 # Read bit for ACK/NAK.
627- self ._command .append ('\x22 \x00 ' )
727+ self ._command .append (b '\x22 \x00 ' )
628728 # Increase expected response bytes.
629729 self ._expected += len (data )
630730
0 commit comments