Bus Pirate: Binary I2C mode


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.

Join the Conversation


  1. 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.

  2. …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.

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

  4. 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.

  5. 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.

  6. 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

  7. 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?

    1. 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.

  8. Ian.

    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.


  9. 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 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.