Bus Pirate: Binary I2C mode

Posted on Wednesday, October 14th, 2009 in binmode, Bus Pirate by Ian


See the latest version in the documentation wiki.

The Bus Pirate’s new binary modes provide a consistent, logical way to script actions from Python, Perl, etc. We already introduced the new binary bitbang and SPI modes, today we’ll document the binary I2C mode. Binary I2C will be in the v2.6 firmware release, for now you can grab the v2.6 nightly compile.

We want your scripts! If you script something for any of the new modes, in any language, we’d like to host it in the example scripts folder. We’ll send Bus Pirate probe cable kits to two authors of Bus Pirate binary mode scripts posted by the end of next week (October 24th, 2009).

Binary I2C mode specification follows after the break.

Binary I2C mode command table

  • 00000000 – Exit to bitbang mode, responds “BBIOx”
  • 00000001 – Mode version string (I2C1)
  • 00000010 – Send I2C start bit
  • 00000011 – Send I2C stop bit
  • 00000100 – I2C read byte
  • 00000110 – Send I2C ACK bit
  • 00000111 – Send I2C NACK bit
  • 00001111 – Start bus sniffer
  • 0001xxxx – Bulk transfer, send 1-16 bytes (0=1byte!)
  • 0100wxyz – Configure peripherals w=power, x=pullups, y=AUX, z=CS
  • 011000xx – Set I2C speed, 3=~400kHz, 2=~100kHz, 1=~50kHz, 0=~5kHz

Enter binary I2C mode by first entering bitbang mode, then send 0x02 to enter I2C mode.

Most I2C mode commands are a single byte. Commands generally return 1 for success, 0 for failure.

00000000 – Exit to bitbang mode, responds “BBIOx”

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

00000001 – Display mode version string, responds “I2Cx”

Once in binary I2C mode, send 0×01 to get the current mode version string. The Bus Pirate responds ‘I2Cx’, where x is the raw I2C protocol version (currently 1). Get the version string at any time by sending 0×01 again. This command is the same in all binary modes, the current mode can always be determined by sending 0x01.

00000010 – I2C start bit

Send an I2C start bit. Responds 0x01.

00000011 – I2C stop bit

Send an I2C stop bit. Responds 0x01.

00000100 – I2C read byte

Reads a byte from the I2C bus, returns the byte. You must ACK or NACK each byte manually!

00000110 – ACK bit

Send an I2C ACK bit after reading a byte. Tells a slave device that you will read another byte. Responds 0x01.

00000111 – NACK bit

Send an I2C NACK bit after reading a byte. Tells a slave device that you will stop reading, next bit should be an I2C stop bit. Responds oxo1.

00001111 – Start bus sniffer

Sniff traffic on an I2C bus.

  • [/]  – Start/stop bit
  • \ – escape character precedes a data byte value
  • +/-  – ACK/NACK

Sniffed traffic is encoded according to the table above. Data bytes are escaped with the ‘\’ character. Send a single byte to exit, Bus Pirate responds 0x01 on exit.

0001xxxx – Bulk I2C write, send 1-16 bytes (0=1byte!)

Bulk I2C allows multi-byte writes. The Bus Pirate expects xxxx+1 data bytes. Up to 16 data bytes can be sent at once. Note that 0000 indicates 1 byte because there’s no reason to send 0.

BP replies 0×01 to the bulk I2C command. After each data byte the Bus Pirate returns the ACK (0x00) or NACK (0x01) bit from the slave device.

0100wxyz – Configure peripherals w=power, x=pullups, y=AUX, z=CS

Enable (1) and disable (0) Bus Pirate peripherals and pins. Bit w enables the power supplies, bit x toggles the on-board pull-up resistors, y sets the state of the auxiliary pin, and z sets the chip select pin. Features not present in a specific hardware version are ignored. Bus Pirate responds 0×01 on success.

Note: CS pin always follows the current HiZ pin configuration. AUX is always a normal pin output (0=GND, 1=3.3volts).

NOTE: due to a typo this was previously command 0110.

0110000x – Set I2C speed, 1=high (50kHz) 0=low (5kHz)

011000xx – Set I2C speed, 3=~400kHz, 2=~100kHz, 1=~50kHz, 0=~5kHz (updated in v4.2 firmware)

The last bit of the speed command determines the I2C bus speed. Binary mode currently uses the software I2C library, though it may be configurable in a future update. Startup default is high-speed. Bus Pirate responds 0×01 on success.

NOTE: due to a typo this was previously command 0100.

This entry was posted on Wednesday, October 14th, 2009 at 8:33 am and is filed under binmode, Bus Pirate. You can follow any responses to this entry through the RSS 2.0 feed. You can skip to the end and leave a response. Pinging is currently not allowed.

19 Responses to “Bus Pirate: Binary I2C mode”

  1. James says:

    When I set the speed the power supply turns off…

  2. Ian says:

    I accidentally switched the speed and peripheral mode opcode in the I2C library. It’s fixed, but I haven’t uploaded a new nightly yet. I’ll do that today after I add the UART library.

  3. James says:

    The responses aren’t what I’m expecting, are you sure start and stop bits respond with 0x01?

  4. James says:

    …the problem might be on my side but I’m getting the exact same response when doing a successful write as when the chip I’m talking to isn’t even connected. For example when sending:

    02 13 a0 00 00 ff 03

    to do an eeprom write I get:

    00 01 01 01 00 00 00

    regardless of the success of the write.

  5. Ian says:

    I double checked, but I haven’t actually run it using a terminal. I’ll take another look tomorrow. You should be getting 0x01 from 02 and 03:

  6. James says:

    Line url’s is a pretty usefull feature, I’ll go recheck, maybe I need to clear a buffer or something.

  7. James says:

    Ahh, found it, sorry for making my bugs yours :)

  8. James says:

    I did find the answer for the missing chip confirmations though, with a floating I2C bus the line is low which makes the bbReadBit function return 0, when using this function to read the ACK bit after a I2C write it looks like a valid confirmation even though no chip responded.

  9. Ian says:

    When you do the read sequence, are you ACKing and NACKing each byte? If not, you’ll be a bit behind and have random errors.

    When you do the read bytes, send an ACK if you’re going to read another byte, and a NACK if it’s the last byte before a stop condition.

  10. Peter Huewe says:


    Ian was so kind to change the Binary I2C mode so that it now supports I2C Speeds upto 400khz

    The speed parameters are now these:
    #011000xx – Set I2C speed, 11 = 400khz 10=100khz 01=50khz 00=5

    Ians changes can be viewed here:

    I’ll update the python example soon.

  11. Vikram Kopuri says:

    So how do I do read in bitbang guys. In the user terminal I used to do
    [0x90 0x10 [0x91 r]
    (start chip_write_addr reg_addr start chip_read_addr read )

    In bitbang should I do
    02 90 10 02 91 04 03

  12. tissit says:

    So is 1-wire coming too?

  13. Brian says:

    I need to be able to push a read response onto the bus, ie

    [ 0x41 ACK? 0xFE NACK? ]

    Will i2C binary mode allow me to do this? Also, since I’m emulating a slave do I need to send the ACK/NACK and if so, how would I do that?

    • Ian says:

      Hi Brian – The Bus Pirate doesn’t currently support I2C slave modes. It’s been discussed, but nobody is sure how it would work without writing custom slave emulation because the clock is driven by the master.

  14. Albert says:


    Is there any straight forward way in Binary mode to check the addresses of all the I2C devices connected to the Bus Pirate?, in other words is there any way to issue the 7 bit address search command in Binary mode?

    I have an I2C to 1-wire master (DS2482-100) device which I need to poll before I even think about talking to the device in the 1-wire side. that is because I might have more devices in the I2C bus.


  15. Albert says:

    Thanks for the reply Ian, I checked but it appears the command (or the Macro command) is not implemented in Binary mode. As a point of reference, I am using the Perl script created by you for the SPI EEPROM but my devices are generic I2C devices (like digipots and I2C expanders) and a I2C to 1-Wire master device.

    I want to use the traditional macro capability to check for different devices attached to the I2C bus in binary mode. I can share with all once it works

    : )


Leave a Reply

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

Recent Comments