[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