Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 05752a7

Browse files
authored
Merge branch 'master' into master
2 parents 1f1e7e7 + 72a7e96 commit 05752a7

File tree

5 files changed

+181
-59
lines changed

5 files changed

+181
-59
lines changed

Adafruit_GPIO/FT232H.py

Lines changed: 149 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -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

529629
class 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

Adafruit_GPIO/GPIO.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -422,5 +422,8 @@ def get_platform_gpio(**keywords):
422422
elif plat == Platform.MINNOWBOARD:
423423
import mraa
424424
return AdafruitMinnowAdapter(mraa, **keywords)
425+
elif plat == Platform.JETSON_NANO:
426+
import Jetson.GPIO
427+
return RPiGPIOAdapter(Jetson.GPIO, **keywords)
425428
elif plat == Platform.UNKNOWN:
426429
raise RuntimeError('Could not determine platform.')

Adafruit_GPIO/Platform.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
RASPBERRY_PI = 1
2727
BEAGLEBONE_BLACK = 2
2828
MINNOWBOARD = 3
29+
JETSON_NANO = 4
2930

3031
def platform_detect():
3132
"""Detect if running on the Raspberry Pi or Beaglebone Black and return the
@@ -45,6 +46,8 @@ def platform_detect():
4546
return BEAGLEBONE_BLACK
4647
elif plat.lower().find('armv7l-with-glibc2.4') > -1:
4748
return BEAGLEBONE_BLACK
49+
elif plat.lower().find('tegra-aarch64-with-ubuntu') > -1:
50+
return JETSON_NANO
4851

4952
# Handle Minnowboard
5053
# Assumption is that mraa is installed

README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
Deprecation Warning
2+
===================
3+
This library has been deprecated, we have replaced all of the libraries that use this repo with CircuitPython libraries that are Python3 compatible, and support a wide range of single board computers!
4+
5+
Visit https://circuitpython.org/blinka for more information
6+
7+
8+
9+
110
Adafruit Python GPIO Library
211
============================
312

0 commit comments

Comments
 (0)