def read(self, length, assert_ss=True, deassert_ss=True):
if self._miso is None:<EOL><INDENT>raise RuntimeError('<STR_LIT>')<EOL><DEDENT>if assert_ss and self._ss is not None:<EOL><INDENT>self._gpio.set_low(self._ss)<EOL><DEDENT>result = bytearray(length)<EOL>for i in range(length):<EOL><INDENT>for j in range(<NUM_LIT:8>):<EOL><INDENT>self._gpio.output(self._sclk, not self._clock_base)<EOL>if self._read_leading:<EOL><INDENT>if self._gpio.is_high(self._miso):<EOL><INDENT>result[i] |= self._read_shift(self._mask, j)<EOL><DEDENT>else:<EOL><INDENT>result[i] &= ~self._read_shift(self._mask, j)<EOL><DEDENT><DEDENT>self._gpio.output(self._sclk, self._clock_base)<EOL>if not self._read_leading:<EOL><INDENT>if self._gpio.is_high(self._miso):<EOL><INDENT>result[i] |= self._read_shift(self._mask, j)<EOL><DEDENT>else:<EOL><INDENT>result[i] &= ~self._read_shift(self._mask, j)<EOL><DEDENT><DEDENT><DEDENT><DEDENT>if deassert_ss and self._ss is not None:<EOL><INDENT>self._gpio.set_high(self._ss)<EOL><DEDENT>return result<EOL>
Half-duplex SPI read.  If assert_ss is true, the SS line will be
        asserted low, the specified length of bytes will be clocked in the MISO
        line, and if deassert_ss is true the SS line will be put back high.
        Bytes which are read will be returned as a bytearray object.