Bus Pirate: Binary bitbang mode


See the latest version in the documentation wiki.

There’s two new binary I/O libraries in the v2.3 Bus Pirate firmware. Raw bitbang mode provides direct control over the Bus Pirate pins and hardware using a simple single-byte protocol. We discussed the new raw SPI mode yesterday.

Hopefully the raw access modes inspire some interesting new Bus Pirate tools using PC software. There’s already a patch for AVRDude AVR programmer in the works.

Full documentation of the raw bitbang binary I/O mode after the break.


  • 00000000 – Reset, responds “BBIO1”
  • 00000001  – Enter binary SPI mode, responds “SPI1”
  • 00000010 – Enter binary I2C mode, responds “I2C1”
  • 00000011 – Enter binary UART mode, responds “ART1”
  • 00000100 – Enter binary 1-Wire mode, responds “1W01”
  • 00000101 – Enter binary raw-wire mode, responds “RAW1”
  • 0000xxxx – Reserved for future raw protocol modes
  • 00001111 – Reset Bus Pirate (returns to user terminal)
  • 00010000 – Short binary mode self-test
  • 00010001 – Long test (requires jumpers between +5 and Vpu, +3.3 and ADC)
  • 00010010 – Setup pulse-width modulation (requires 5 byte setup)
  • 00010011 – Clear/disable PWM
  • 00010100 – Take voltage probe measurement (returns 2 bytes)
  • 010xxxxx  – Set pins as input(1) or output(0), responds with read
  • 1xxxxxxx  – Set pins high (1) or low (0), responds with read

The bitbang protocol uses a single byte for all commands. The default start-up state is pin input (HiZ).

00000000 – Reset, responds “BBIO1”

This command resets the Bus Pirate into raw bitbang mode from the user terminal. It also resets to raw bitbang mode from raw SPI mode, or any other protocol mode. This command always returns a five byte bitbang version string “BBIOx”, where x is the current protocol version (currently 1).

Some terminals send a NULL character (0x00) on start-up, causing the Bus Pirate to enter binary mode when it wasn’t wanted. To get around this, you must now enter 0x00 at least 20 times to enter raw bitbang mode.

Note: The Bus Pirate user terminal could be stuck in a configuration menu when your program attempts to enter binary mode. One way to ensure that you’re at the command line is to send <enter> at least 10 times, and then send ‘#’ to reset. Next, send 0x00 to the command line 20+ times until you get the BBIOx version string.

00000001  – Enter binary SPI mode, responds “SPI1”

After entering bitbang mode, you can enter other binary protocol modes. Binary SPI mode is documented here.

00000010 – Enter binary I2C mode, responds “I2C1”

Binary I2C mode is documented here.

00000011 – Enter binary UART mode, responds “ART1”

Binary UART mode is documented here.

00000100 – Enter binary 1-Wire mode, responds “1W01”

Binary 1-Wire mode is documented here.

00000101 – Enter binary raw-wire mode, responds “RAW1”

Binary raw-wire mode is documented here.

00001111 – Reset Bus Pirate

The Bus Pirate responds 0x01 and then performs a complete hardware reset. The hardware and firmware version is printed (same as the ‘i’ command in the terminal), and the Bus Pirate returns to the user terminal interface. Send 0x00 20 times to enter binary mode again.

Note: there may be garbage data between the 0x01 reply and the version information as the PIC UART initializes.

0001000x – Bus Pirate self-tests

Binary self tests are documented here. Available only in v2go and v3 hardware.

00010010 – Setup pulse-width modulation (requires 5 byte setup)

Configure and enable pulse-width modulation output in the AUX pin. Requires a 5 byte configuration sequence. Responds 0x01 after a complete sequence is received. The PWM remains active after leaving binary bitbang mode!

Equations to calculate the PWM frequency and period are in the PIC24F output compare manual. Bit 0 and 1 of the first configuration byte set the prescaler value. The Next two bytes set the duty cycle register, high 8bits first. The final two bytes set the period register, high 8bits first.

00010011 – Clear/disable PWM

Clears the PWM, disables PWM output. Responds 0x01.

00010100 – Take voltage probe measurement (returns 2 bytes)

Take a measurement from the Bus Pirate voltage probe. Returns a 2 byte ADC reading, high 8bits come first. To determine the actual voltage measurement: (ADC/1024)*3.3volts*2; or simply (ADC/1024)*6.6.

010xxxxx  – Configure pins as input(1) or output(0): AUX|MOSI|CLK|MISO|CS

Configure pins as an input (1) or output(0). The pins are mapped to the lower five bits in this order:


The Bus pirate responds to each direction update with a byte showing the current state of the pins, regardless of direction. This is useful for open collector I/O modes.

Note: updated to correct order on 16/JAN/10

1xxxxxxx   – Set on (1) or off (0): POWER|PULLUP|AUX|MOSI|CLK|MISO|CS

The lower 7bits of the command byte control the Bus Pirate pins and peripherals. Bitbang works like a player piano or bitmap. The Bus Pirate pins map to the bits in the command byte as follows:


The Bus pirate responds to each update with a byte in the same format that shows the current state of the pins.

Note: updated to correct order on 16/JAN/10

Key Points

  • Send 0x00 to the user terminal 20 times to enter the raw binary bitbang mode.
  • Send 0x0F to exit raw bitbang mode and reset the Bus Pirate.
  • Other raw protocol modes are accessible from within bitbang mode, 0x00 always returns to raw bitbang mode and prints the version string.
  • There is a slight settling delay between pin updates, currently about 5us.


Join the Conversation


  1. When I get mine the first thing I’m going to do is implement a simple SWD script for uploading to Arm Cortex-M3’s.

    It took me ages to cobble together all the documentation needed to use that protocol ;)

  2. Tip to anyone using bin mode, when sending command strings read single replies before sending more commands, sending long commands and attempting to read long replies causes the bus pirate to miss part of the command when performing the first part. This is caused by the bus pirate polling the serial line, since it might be busy when the next byte comes in the pic’s buffer can overflow and the command is lost.

    1. Thank you very much for this tip. Although I’ve already lost quite a few hours on diagnosing that, but still having any confirmation is important:) I wish it were written right in the wiki. Are you sure it is 4 bytes? From my tests with firmware 6.1 on BP v3, I was able to successfully send 8-byte packets before reading anything, and it works quite stable.

    1. I’ll drop here my three cents: watch out not only for pullups and power, but also for the CS. The BP in the rawwire mode has small bug/feature: when you use CONFIG command to “drive the lines”, the CS line is automatically switched to HIGH state. If at this point your circuit is unpowered, this may damage the circuit (input line will have higher voltage than the power lines..), or if you’re lucky, the CS will power back the whole circuit. In my experiments this is was highly unwanted, because I my chips had CS that is ACTIVE-HIGH. Surely, on startup, when circuit is unpowered, I want to have CS logically inactive, thus LOW. I found no easy way to keep CS steady low during startup/config/setspeed. It seems that CONFIG just resets it the CS to high. It did that even if I manually ordered to set-cs-to-0 and then config. Due to this, for working with cs-active-high chips that are powered from BP, I had to first turn on the power, then config, then switch cs low, then work. This is not pretty, because for tiny moment the CS is high and the chip is too early ‘selected’ for a moment, but this at least does not power the whole circuit via the stubborn CS, and dont damage the chips.

  3. The PIC has a 4-byte hardware RX buffer, so you can probably get away with sending a few bytes in a shorter command. You can probably also load it up a bit and them send a new byte every time you get one back to eliminate some lag.

  4. My v2go running 3.6 has a different order of the input/direction bits:
    Is the order in the post wrong?

  5. I would like driving BP3 through a LibertyBasic simple basic program … sending simple characters command to the card (through COMp port) as done with a terminal program like Hyperterminal … How do I do that ?
    I can send the commands but no response is readed ?

    1. Hey Antonio – I’m not familiar with BASIC myself, but maybe if you post in the forum there will be a few people with some experience that can help.

  6. Thank you for your response, Ian, …
    Very simple in fact … Here is a short program …
    I did almost some thing with USB Bit Whalker card … and it works …

    ‘ Liberty Basic sample application code or any similar programming language …
    ‘ Written for BP3 … USB Bus Pirate …
    ‘ RS232 master commands … Through USB …

    mainwin 40 20

    ‘ First open the COM port to the BP3 through USB virtual port
    OPEN “COM4:300,N,8,1” FOR random AS #BP3
    PRINT #BP3, “#” ; ‘ send reset … or anything command else …

    FOR I=1 to 9
    L$=INPUT$(#BP3,LOF(#BP3)) ‘ Try to read BP3 responses characters …
    PRINT I,len(L$),L$ ‘ in fact nothing is read …
    next I

    CLOSE #BP3

  7. OK, Ian, … Found the problem …
    Must use some delay for reading BP3 messages … Hi …
    New one program that works …

    ‘ Liberty Basic application code
    ‘ Written for BP3 … USB Bus Pirate …
    ‘ See http://www.sparkfun.com
    ‘ RS232 master commands … Through USB …

    mainwin 40 20
    global time, nbl

    ‘ First open the COM port to the BP3
    OPEN “COM4:115200,N,8,1,CS0,DS0,RS” FOR RANDOM AS #BP3

    PRINT “Sending Reset …”
    PRINT #BP3, “#” ‘ send reset command …
    call rd 2 ‘ read some response …

    PRINT #BP3, “I”; chr$(13) ; ‘ send Info command …
    call rd 2 ‘ retrieve response …
    CLOSE #BP3

    sub del time ‘ wait delay time
    for i=0 to time
    next i
    end sub

    sub rd nbl
    FOR I=1 to nbl ‘ read nbl lines
    call del time
    L$=INPUT$(#BP3,LOF(#BP3)) ‘ Try to read BP3 responses characters …
    PRINT L$;
    next I
    end sub


  8. I’m currently writing code using bit bang mode. Can someone comment about the two ways to control the CS pin, and how they differ? Some modes have specific commands to control CS (i.e. SPI) but still have the ability to change it using the 0x40 command. If I use 0x40 will it still change the CS pin? I am confused as to the purpose of this redundancy.

    1. Hi Garrett,

      Either command will work. The dedicated CS command in SPI is so that you can change CS without tracking all the other bits in the multi-pin register.

  9. hey, does anyone know the clock speed of the timer that controls the PWM? It doesn’t say here, and that is kind of necessary to set a value :D

  10. Another question… your replies are great Ian (are you the major upkeeper of the project? You seem the most active on the forum as well).

    The question is about the ADC. In the documentation you only list 0x14 as a viable option, but there is also the possibility of 0x15 (which outputs continuously). From my working with it, the way to reset back to normal bb mode is to send a 0x00, correct?

    (I just realized that I can find the command in the source code. I must have downloaded an old version of the source code, because my version didn’t have it! )

    1. Glad you got it garrett, thanks for the update. Also feel free to ask questions in the forum, I generally see and respond to queries there first (even on the weekends).



  11. Hi guys,
    I’m able to go into binary mode, then I turn on the supplies, but when I go to SPI mode, the supplies go off again. I’d like the supplies to remain on, so I can power my SPI device and sniff on it simultaniously.
    Can this be done?
    Thanks a lot,

Leave a comment

Your email address will not be published. Required fields are marked *

Notify me of followup comments via e-mail. You can also subscribe without commenting.