[Tutor] Help with building bytearray arrays
Cameron Simpson
cs at cskk.id.au
Sat Sep 8 06:49:45 EDT 2018
On 08Sep2018 20:01, Cameron Simpson <cs at cskk.id.au> wrote:
>>So, if I'm understanding the transfer() function correctly, the
>>function takes and returns a bytearray type.
>
>It would be good to see the specification for the transfer function.
>They we can adhere to its requirements. Can you supply a URL?
I see you supplied the whole transfer function in your first message :-(
I'll recite it here and walk through its contents to explain:
def transfer(self, data):
Ok, this is a method, a particular type of function associated with a class
instance. (All objects are class instances, and the class is their type.)
So to call this you would normally have a control object of some kind. [...]
Ah, it looks like you should have an SpiDev instance, inferring from this code:
https://github.com/adafruit/Adafruit_Python_GPIO/blob/master/Adafruit_GPIO/SPI.py
So suppose you've got such an object and a variable referring to it, let's say
it is named "spi". You'd normally call the transfer function like this:
spi.transfer(some_data)
instead of calling transfer() "bare", as it were.
When you call a Python method, the instance itself is implicitly passed as the
parameter "self" (well, the first parameter - in Python we always call this
"self" like C++ uses "this").
"""Full-duplex SPI read and write. The specified array of bytes will be
clocked out the MOSI line, while simultaneously bytes will be read from
the MISO line. Read bytes will be returned as a bytearray object.
"""
This is a docstring. It is like a comment but it gets attached to the function
and can be inspected. Not your problem.
# Build command to read and write SPI data.
command = 0x30 | (self.lsbfirst << 3) | (self.read_clock_ve << 2) | self.write_clock_ve
This constructs a value just as you would in C.
logger.debug('SPI transfer with command {0:2X}.'.format(command))
Write a debugging message.
# Compute length low and high bytes.
# NOTE: Must actually send length minus one because the MPSSE engine
# considers 0 a length of 1 and FFFF a length of 65536
length = len(data)
len_low = (length-1) & 0xFF
len_high = ((length-1) >> 8) & 0xFF
All just like C.
# Send command and length.
self._assert_cs()
I would guess that this raises a control signal. Ah, RS-232? So clear-to-send
then.
self._ft232h._write(str(bytearray((command, len_low, len_high))))
Ok, it looks like this is Python 2, not Python 3. Let's unpack it.
"(command, len_low, len_high)" is a tuple of 3 values. A tuple is like a read
only list. We're passing that to the bytearray() constructor, which will accept
an iterable of values and make a bytes buffer. And we want to write that to
"self._ft232h". Which expects a str, which is why I think this is Python 2. In
Python 2 there's no "bytes" type and str is an immutable array of 8-bit
character values. So writing bytes uses str.
So this tabkes a tuple of values, to be bytes, makes those into a bytearray and
makes that into a str, and writes that str to the serial line.
self._ft232h._write(str(bytearray(data)))
We write that data itself.
self._ft232h._write('\x87')
self._deassert_cs()
And here we lower the control signal.
# Read response bytes.
return bytearray(self._ft232h._poll_read(length))
This calls the _poll_read method, presumably requesting "length" bytes, the
same length as the supplied data. I presume we get a str back: we make a new
bytearray with those bytes in it and return it.
So you do get a new bytearray back from each call, so we can accumulate them
into a list and then join them together later to make a single bytearray.
Why this faffing about with str and bytearray? Probably for Python 2/3
compatibility, and because you want to deal with bytes (small ints) instead of
characters. Ignore it: we're dealing with bytes.
Cheers,
Cameron Simpson <cs at cskk.id.au>
More information about the Tutor
mailing list