Microsoft MakeCode

How to deal with bitorder for SPI communication (MSB<->LSB)?

I guess, just like Mbed, that the micro:bit does MSB first for the communication. But is there an easy way to deal with LSB? I noticed that I was not able to use _rbit when I tried to use this as a C extrension. What would be the easy fix? A lookup table, but this likely wastes resources …

Look up table is only 256 bytes. You can put it in as a hex literal so it’s only stored in flash. If it’s not much data you can do it using bit operations but it may work out to be similar size when compiled.

A solution like:

let ReverseLookupTable =
        0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
        0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,

function BlahlaDoStuff() {
    let input = 0x42
    let output = BitReverseLookupTable[input]
    // output should be 0x42

would not work, as ading more netries will result in an error 84 or similar and that is likely caused by an out of memory. Each of these are likely claimed as a 32bit? So a lookup table does not fly if defined in TypeScript. Or … ?

Use hex literal like this:

1 Like

Ah, I see. Actually wanted to approach this as a buffer. Seems that would be taken care of:

Right. You need to use it like in the melody example above. The compiler treats these specially, similar to string literals, in that they are only stored in flash and do not occupy any RAM.

Probably a lot more of these gems exist in the platform…

I had looked at that code and noticed the NumberFormat option, etc. It made me wonder why there was no SPIWriteBuffer option (since I2C has).

const rbits = hex`

function rbit(input: number): number {
    return rbits.getNumber(NumberFormat.UInt8LE, input) || 0x00;

serial.writeLine("01 => " + rbit(0x01))
serial.writeLine("42 => " + rbit(0x42))
serial.writeLine("5a => " + rbit(0x5a))
serial.writeLine("ff => " + rbit(0xff))
serial.writeLine("00 => " + rbit(0x00))
serial.writeLine("fe => " + rbit(0xfe))

Note: will create an extension for this at

There should be spi write buffer. I’ll look into that.

For your code it’s slightly more efficient to access the buffer directly via rbits[input] than with get number (only works for uint8)

I figured, as you essentially pick a byte… so you do not have to execute a subroutine.

But at the moment I can’t get a stable SPI clock from my library. Not sure what is happening …

There’s spiTransfer which is read and write combined. You can (and usually should) pass null as either of the buffers. I guess we should add spiRead and spiWrite - @peli what do you think?

For people less familiar with SPI - typically, in SPI there are separate lines for data going from master to slave (MOSI - master out slave in) and the other way around (MISO - master in slave out). These lines are meant to work at the same time, so when the master clocks the SCK line, for every bit, the master writes to MOSI and slave to MISO. This is why spiTransfer takes two buffers, and why the return value of spiWrite is the value read.

Typically most peripherals expect the master to write the command, possibly make a little break. Then the master is supposed to write zeros, while the slave writes the response, so there is no utilization of MISO and MOSI at the same time.

One can perform such a transaction with a single spiTransfer, by sending a buffer that starts with command and ends with padding, and getting back a buffer that starts with padding and ends with response. But most often what you will do, is to write the command with response == null, and then read the response with command == null in two spiTransfers.


Are you sure… not as part of the pins namespace at least.


I can haz it on Arcade, but not for the Micro:bit editor… :thinking: version:  2.0.17
Microsoft MakeCode version:  5.15.19
microbit runtime version:  pxtgc-0

Oh, right. Micro:bit is on legacy version of everything. We’re (or rather @peli is) trying to move it over to pxt-common-packages but this will take a while. Also, there’s no DMA for SPI master on micro:bit, so you may as well implement spiTransfer by running spiWrite in a loop.

Currently doing this… and the result is nasty. For some reason the clock is not stable (or almost non-existent) when probing with an analyzer.

Got it working: PS2 Controller extension

The extension can do rbit and rbuffer: