Skip to content

Instantly share code, notes, and snippets.

@HokieGeek
Last active January 17, 2021 12:47
Show Gist options
  • Save HokieGeek/8fe2de6f19844d7311f0 to your computer and use it in GitHub Desktop.
Save HokieGeek/8fe2de6f19844d7311f0 to your computer and use it in GitHub Desktop.
Trying out bus pirate binary mode in python and haskell
#!/usr/bin/python
import serial
import signal
import sys
import time
def BinaryModeEnter(connection):
connection.flushInput()
for x in range(0, 20): # Try at most 20 times
connection.write(b'\x00') # 0000 0000
if b'BBIO' in connection.read(10):
return True
return False
def BinaryModeExit(connection):
connection.write(b'\x0F') # 0000 1111
def InterfaceSelect_SPI(connection):
# TODO
connection.write(b'\x01') # Enter SPI: 0000 0001
## Configure the SPI connection
connection.write(b'\x49') # Power ON, CS High 0100 1001
return
# def handleSigint(signal, frame):
# sys.exit(0)
conn = serial.Serial("/dev/buspirate", 115200, timeout=0.1)
if BinaryModeEnter(conn):
print("Connected")
else:
print("Error connecting!")
ConfigurePower(conn, True)
while True:
try:
print(".", end="", flush=True)
time.sleep(2)
except KeyboardInterrupt:
print("Adios")
BinaryModeExit(conn)
sys.exit()
import System.IO
import System.Exit
import System.Posix.Signals
import Control.Concurrent
import Control.Monad
-- import System.Hardware.Serialport
-- port = "/dev/buspirate"
-- let startBitbang = 0
-- binaryModeEnter :: IO Handle -> Bool
-- binaryModeEnter h
-- | hGetLine h == 'BBIO' = True
-- Else, do a send or putstr of startBitbang
-- h <- hOpenSerial port defaultSerialSettings { commSpeed = CS115200 }
-- not hPut_Str_ is my guess... send?
-- hGetLine h == 'BBIO'
-- hPutStr h startBitbang
-- Start power
-- hPutStr h \xC0
-- TODO: only get here when the user wants to
-- hClose h
main :: IO ()
main = forever $ do
tid <- myThreadId
installHandler keyboardSignal (Catch (killThread tid)) Nothing
putStr "."
hFlush stdout
threadDelay(2000000)
#!/usr/bin/python
import argparse
import serial
import signal
import struct
import sys
import time
def BinaryModeEnter(connection):
connection.flushInput()
for x in range(0, 22): # Try at least 20 times
connection.write(b'\x00')
if b'BBIO' in connection.read(10):
print("Entered (or reset) binary mode")
return True
print("Error connecting!")
return False
def BinaryModeExit(connection):
connection.write(b'\x0F') # 0000 1111
print("Exited binary mode")
def ConfigurePower(connection, enabled):
if enabled:
connection.write(b'\xC0') # 1100 0000
else:
connection.write(b'\x80') # 1000 0000
def SelfTest(connection, testType):
print("Starting %s self-test" % testType)
if testType == "short":
connection.write(b'\x10') # 0001 0000
else:
print("Please connect the following pins together:")
print(" +5 <-> Vpu")
print(" +3.3 <-> ADC")
input("Press Enter to continue...")
connection.write(b'\x11') # 0001 0001
time.sleep(5) # give it time...
print("Found %d errors." % int.from_bytes(connection.read(1), byteorder='big'))
connection.write(b'\xFF')
def ReadVoltage(connection):
reading = int.from_bytes(connection.read(2), byteorder='big')
return (reading/1024)*6.6
def VoltageProbe(connection):
# connection.write(b'\x14') # 0001 0100
# print("%d" % ReadVoltage(connection), flush=True)
connection.write(b'\x15') # 0001 0101
while True:
try:
print("%d" % ReadVoltage(connection), flush=True)
time.sleep(1)
except KeyboardInterrupt:
break
def ConfigurePins(connection):
print("TODO")
def spiEnter(connection):
connection.write(b'\x01')
if b'SPI' in connection.read(10):
print("Entered SPI mode")
def spiPeripherals(connection, power, pullups, aux, cs):
peripherals = 0x40
if power:
peripherals |= 0x08
if pullups:
peripherals |= 0x04
if aux:
peripherals |= 0x02
if cs:
peripherals |= 0x01
print("Setting peripherals to: %s" % str(hex(peripherals)))
connection.write(struct.pack('B', peripherals))
# return b'\x01' in connection.read(2)
def spiSpeed(connection, speed_str):
speed = 0x60 # Implies 30kHz
if speed_str == "125k":
speed |= 0x01 # 0001
elif speed_str == "250k":
speed |= 0x02 # 0010
elif speed_str == "1m":
speed |= 0x03 # 0011
elif speed_str == "2m":
speed |= 0x04 # 0100
elif speed_str == "2.6m":
speed |= 0x05 # 0101
elif speed_str == "4m":
speed |= 0x06 # 0110
elif speed_str == "8m":
speed |= 0x07 # 0111
else: # 30kHz. Here purely for completeness
speed |= 0x00 # 0000
connection.write(struct.pack('B', speed))
def spiToggleChipSelect(connection, high):
if high:
connection.write(b'\x03')
else:
connection.write(b'\x02')
def spiConfig(connection, pinOutput3v3, clockIdlePhaseHigh, clockEdgeActiveToIdle):
config = 0x80
if pinOutput3v3:
config |= 0x08
if clockIdlePhaseHigh:
config |= 0x04
if clockEdgeActiveToIdle:
config |= 0x02
# TODO: sample time?
connection.write(struct.pack('B', config))
return b'\x01' in connection.read(2)
def spiSniff(connection, csLow):
if csLow:
connection.write(b'\x06') #000011 10
else:
connection.write(b'\x05') #000011 01
while True:
try:
print("%d" % connection.read(2), flush=True)
except KeyboardInterrupt:
connection.write(b'\xF0')
break
def spiBulkTransfer(connection, numBytes, writeBytes, readBytes):
# connection.write()
print("TODO")
def spiWriteThenRead(connection, numBytesToWrite, writeBytes, numBytesToRead, readBytes):
print("TODO")
connection.write(b'\x04') # WriteThenRead blah
# command
# def spiWrite(connection):
# print("TODO")
# def spiRead(connection):
# print("TODO")
def SpiCommand(connection, arguments):
print("SpiCommand")
# Commands: sniff, read, write, readwrite
parser = argparse.ArgumentParser(add_help=False)
parser.add_argument("cmd", choices=['sniff', 'read', 'write', 'readwrite'])
parser.add_argument("-p", "--peripherals", action="store")
parser.add_argument("-c", "--config", action="store")
parser.add_argument("-s", "--speed", action="store")
# TODO: input and output files?
args = parser.parse_args(arguments)
# print(arguments)
# print(args.cmd)
BinaryModeEnter(conn)
spiEnter(connection)
## Setup the peripherals
if args.peripherals is not None:
power = False
pullups = False
aux = False
cs = False
for p in args.peripherals.split(','):
if p.lower() == "power":
power = True
elif p.lower() == "pullups":
pullups = True
elif p.lower() == "aux":
aux = True
elif p.lower() == "cs":
cs = True
spiPeripherals(connection, power, pullups, aux, cs)
## Set the speed
if args.speed is not None:
spiSpeed(connection, args.speed)
## Configure the SPI settings
if args.config is not None:
pinOutput3v3 = False
clockIdlePhaseHigh = False
clockEdgeActiveToIdle = False
for c in args.config.split(','):
if c.lower() == "3v3":
pinOutput3v3 = True
elif c.lower() == "clk-idle-high":
clockIdlePhaseHigh = True
elif c.lower() == "clk-edge-ati":
clockEdgeActiveToIdle = True
spiConfig(connection, pinOutput3v3, clockIdlePhaseHigh, clockEdgeActiveToIdle)
## Execute the operation
if cmd == "sniff":
spiSniff(connection, False) # TODO: how to do the options
# elif cmd == "read":
# print("TODO")
# elif cmd == "write":
# print("TODO")
# elif cmd == "readwrite":
# print("TODO")
## Now exit
BinaryModeEnter(connection)
BinaryModeExit(connection)
## Arguments
# [done] --power
# --pwm <width> (clear it on exit)
# --voltage
# --freq
# --output <[aux|mosi|clk|miso|cs]>
# [done] --test (remind to do pins)
parser = argparse.ArgumentParser(prog="buspirate", description="Bus Pirate script interface")
parser.add_argument("--device", help="Serial device to use. Defaults to /dev/buspirate", default="/dev/buspirate", action="store")
parser.add_argument("-i", "--interactive", help="Enter interactive mode", action="store_true", dest="interactive")
parser.add_argument("--power", choices=['on','off'], help="Enable or disable power", action="store")
parser.add_argument("--voltage", help="Probe for voltage at ADC pin", action="store_true")
parser.add_argument("--test", choices=['short','long'], help="Perform short or long self-test", action="store")
parser.add_argument("--enter", help="Resets back to raw bitbang mode", action="store_true")
parser.add_argument("--exit", help="Enable or disable power", action="store_true")
parser.add_argument("--reset", help="Resets back to raw bitbang mode", action="store_true")
parser.add_argument("--spi", help="Performs SPI commands", action="store_true")
# parser.add_argument("--i2c", help="Performs I2C commands", action="store_true")
# parser.add_argument("--uart", help="Performs UART commands", action="store_true")
# parser.add_argument("raw", help="Send raw byte", action="store")
args, extra_args = parser.parse_known_args()
# if args.spi:
# SpiCommand(None, extra_args)
# print("args = %s" % args)
# print("extra_args = %s" % extra_args)
# sys.exit()
## Connect
conn = serial.Serial(args.device, 115200, timeout=0.1)
if args.enter or args.reset:
BinaryModeEnter(conn)
if args.interactive:
print("TODO")
# while True:
# try:
# print(".", end="", flush=True)
# time.sleep(2)
# except KeyboardInterrupt:
# print("Adios")
# ConfigurePower(conn, False)
# BinaryModeExit(conn)
# sys.exit()
elif args.test is not None:
if BinaryModeEnter(conn):
SelfTest(conn, args.test)
BinaryModeExit(conn)
elif args.power is not None:
if BinaryModeEnter(conn):
if args.power == "on":
ConfigurePower(conn, True)
print("Power supplies are ON")
else:
ConfigurePower(conn, False)
print("Power supplies are OFF")
elif args.voltage:
VoltageProbe(conn)
elif args.spi:
SpiCommand(conn, extra_args)
# if args.raw is not None:
# conn.write(????)
if args.exit:
BinaryModeEnter(conn)
BinaryModeExit(conn)
@HokieGeek
Copy link
Author

Bitbang mode commands

http://dangerousprototypes.com/docs/Bitbang

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"
00000110 - Enter OpenOCD JTAG mode
0000xxxx - Reserved for future raw protocol modes
00001111 - Reset Bus Pirate
0001000x - Bus Pirate self-tests
00010010 - Setup pulse-width modulation (requires 5 byte setup)
00010011 - Clear/disable PWM
00010100 - Take voltage probe measurement (returns 2 bytes)
00010101 - Continuous voltage probe measurement
00010110 - Frequency measurement on AUX pin
010xxxxx - Configure pins as input(1) or output(0): AUX|MOSI|CLK|MISO|CS
1xxxxxxx - Set on (1) or off (0): POWER|PULLUP|AUX|MOSI|CLK|MISO|CS

@HokieGeek
Copy link
Author

SPI

http://dangerousprototypes.com/docs/SPI_(binary)

00000000 - Enter raw bitbang mode, reset to raw bitbang mode
00000001 - Enter raw SPI mode, display version string
0000001x - CS high (1) or low (0)
000011XX - Sniff SPI traffic when CS low(10)/all(01)
0001xxxx - Bulk SPI transfer, send/read 1-16 bytes (0=1byte!)
0100wxyz - Configure peripherals w=power, x=pull-ups, y=AUX, z=CS
01100xxx - SPI speed
1000wxyz - SPI config, w=HiZ/3.3v, x=CKP idle, y=CKE edge, z=SMP sample
00000100 - Write then read
00000101 - Write then read, no CS

@HokieGeek
Copy link
Author

I2C

http://dangerousprototypes.com/docs/I2C_(binary)

00000000 - Exit to bitbang mode, responds "BBIOx"
00000001 – Display mode version string, responds "I2Cx"
00000010 – I2C start bit
00000011 – I2C stop bit
00000100 - I2C read byte
00000110 - ACK bit
00000111 - NACK bit
00001111 - Start bus sniffer
0001xxxx – Bulk I2C write, send 1-16 bytes (0=1byte!)
0100wxyz – Configure peripherals w=power, x=pullups, y=AUX, z=CS
010100xy - Pull up voltage select (BPV4 only)- x=5v y=3.3v
011000xx - Set I2C speed, 3=~400kHz, 2=~100kHz, 1=~50kHz, 0=~5kHz (updated in v4.2 firmware)

0x08 - Write then read

@HokieGeek
Copy link
Author

UART

http://dangerousprototypes.com/docs/UART_(binary)

00000000 - Exit to bitbang mode, responds "BBIOx"
00000001 – Display mode version string, responds "ARTx"
0000001x – Start (0)/stop(1) echo UART RX
00000111 – Manual baud rate configuration, send 2 bytes
00001111 - UART bridge mode (reset to exit)
0001xxxx – Bulk UART write, send 1-16 bytes (0=1byte!)
0100wxyz – Configure peripherals w=power, x=pullups, y=AUX, z=CS
0110xxxx - Set UART speed
100wxxyz – Configure UART settings

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment