iic_readbyte
        ; Every byte on the IC bus is 8 bits in
        ; length. The MSB is received first. After
        ; we have received all eight bits, we must
        ; send an Ack bit if there is more data to
        ; follow, but we dont Ack the last byte of
        ; a multi-byte transfer.
        ; [I2C bus specification, section 5.1, 5.2]
        ;
        ; As we are called:
        ;   R0 = Whether or not an Ack should be
        ;        sent for this byte
        ; When we leave:
        ;   R0 = Byte weve read
        ; or otherwise well raise an error.
        Push     "R1-R5, R14"

        ; store ack it? value
        MOV      R5, R0
        
        MOV      R3, #0              ; byte = 0
        MOV      R4, #7              ; bit count

iic_readbyte_loop
        ; set up and clock in bit
        ; allows slave to pull SDA
        MOV      R1, #(SDA_HIGH + SCL_LOW)
        BL       toggle_printer
        ; clock it in
        MOV      R1, #(SDA_HIGH + SCL_HIGH)
        BL       toggle_printer

        ; read the bit
        MOV      R0, #0
        SWI      XParallel_Op
        ; mask out everything else
        AND      R2, R2, #SDA_IN
        MOV      R1, #1
        ; invert it and make it lsb (powerful op!)
        SUB      R2, R1, R2, ASR #7

        ; store the bit into the byte (remember,
        ; the msb comes *first*)
        ADD       R3, R2, R3, LSL #1
        ; byte = ((byte * 2) + (bit AND 1)

        ; clock it out now
        MOV      R1, #(SDA_HIGH + SCL_LOW)
        BL       toggle_printer

        ; more bits?
        SUBS     R4, R4, #1
        BCS      iic_readbyte_loop

        ; set byte to return with
        MOV      R0, R3

        ; do want we an ACK?
        CMP      R5, #1
        Pull     "R1-R5, PC", "NE"  ; no ACK, leave

        ; an ACK is wanted
        MOV      R1, #(SDA_LOW + SCL_LOW)
        BL       toggle_printer
        ; clock a zero bit down the bus
        MOV      R1, #(SDA_LOW + SCL_HIGH)
        BL       toggle_printer
        MOV      R1, #(SDA_LOW + SCL_LOW)
        BL       toggle_printer

        ; byte to return with...
        MOV      R0, R3
        Pull     "R1-R5, PC"
