Last active
January 17, 2021 12:47
-
-
Save HokieGeek/8fe2de6f19844d7311f0 to your computer and use it in GitHub Desktop.
Trying out bus pirate binary mode in python and haskell
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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 RX00000111
– Manual baud rate configuration, send 2 bytes00001111
- 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=CS0110xxxx
- Set UART speed100wxxyz
– Configure UART settings