
A Bus Pirate connected to the pins of a Kindle 3 battery
I’m trying to get into hardware some more, because it’s kind of cool and a lot of things I skipped over because “I’m a software guy” I’m starting to realize I really skipped because “I think that looks hella hard and I already look pretty cool doing software” even though I wanted to know about it. So I bought a Bus Pirate.
Just to get it out of the way, I got it at [Seeed Studios]. They’re made by [Dangerous Prototypes]. The version linked here has a counterfeit 232 chip (for the serial communication) so you’ll need an older set of FTDI drivers, version 2.08.28 (*NOT*, and this is important, 2.08.30 or 2.10 – they only work with legit ICs) which I got [here]. The page is unrelated afaik. Some may have non-counterfeit 232s and work with regulars, but mine doesn’t and I’m not thinking seeed has switched batches because they’re still on a batch from early 2012. There’s another version (4 instead of 3.6) of the bus pirate itself, which costs slightly more (not much) and does slightly other things (comparing is so over my head right now). I’ve also heard later drivers mess up under windows 8.1, but the 2.08.28 still works. I’m under 8.1, 64-bit, and they work fine fake chip and all. Beyond the driver thing, there’s apparently nothing much wrong with the counterfeits (hey, it’s all from china anyway, if anything counterfeits are slightly more likely to be made by small groups working for themselves on something resembling their own terms) and the later swaps apparently use a legal chip but one that’s slightly worse, so don’t fret too much over it function wise. I went with [TerraTerm] on Dangerous Prototypes suggestion, but a later version as I’ve installed drivers for ~1 zillion cell phones to work as serial devices and the older 3.11 version only goes up to COM12. The windows terminal will allegedly work but give you issues – I didn’t bother to find out because it’s a pretty sketch terminal anyway so I have no trouble believing the rumors and it’s not installed by default in win 8+ anyhow so something would be getting installed either way.
So if you were looking for links there they are. The Bus Pirate is a tool for reading, writing and evesdropping on a variety of protocols hardware devices use to talk to each other or, more commonly, parts of themselves. I’d heard about these in passing in electronics class in high school, but dismissed it as kind of useless unless I was building massive devices (wasn’t planning on it). However, *modifying* massive devices (by massive I mean like.. a microwave. Or a router. Or digital watch. You know, so much bigger than what you could reasonably design and build on a basement workbench. Unless you have mad ninja electronics skills, in which case good for you) is another matter and these days they’re harder because they’re all tiny and integrated but actually in some ways easier because they’re super modular. If, say, your microwave needs to time a minute, displaying the countdown and then beep, it doesn’t have a timer, a complex set of gates to translate it into LEDs lighting up and a little oscillator circuit that when powered puts a tone out a speaker. Well, it does, sort of, but they’re packed into chips. So it’s more like a microcontroller (system on a chip or a cpu and a small memory chip, like a tiny computer), a display driver (perhaps built into the display) and perhaps a buzzer thing by itself or a direct processor-to-speaker connection. No one built the whole thing, seperate people built each piece and someone (or someones) assembeled the end control circuitry like lego, picking up the pieces they wanted and making them talk to each other. So if you want to mod it, you don’t have to dive into the depths of it either, just figure out what each part does and modify it on that level. Just like software, hardware has become more and more high level – it’s cheaper to make a general purpose circuit and then use it for tons of stuff (even when it’s overkill) than to build custom circuits for everything. Some special things still need the low-level optimization touch, but mostly they don’t. So all that’s needed is a way for all these things to talk.
I’m trying to start with I2C. It’s a [protocol developed by Phillips](http://en.wikipedia.org/wiki/I%C2%B2C) sometime long ago (actually like early 80s). The basic idea is to transmit data between two things over two wires, one clock, one data. But it’s built to have lots of things connected, so they all have to be able to talk and not talk over each other or mess things up when they’re quiet. This is accomplished through two particular things. Each connected thing has an address (between 8 bit, so you can have 255 minus a bunch of reserved ones things connected at once). When communicating, no one ever tries to force either the clock or data line to have power on it, instead they remove power from it by connecting it to ground. One thing (usually the master or one of the masters if there’s several though that isn’t that super common, which also delegates who gets to talk and when) or a separate connection has both lines connected via a resistor to power, meaning it usually sits there floating calmy at five volts. If anyone talks, they ground it, making it 0v with a small current flowing into ground because of the resistor. Think of it as a rope along the side of a train you can pull to signal “stop at next stop”. When everyone is saying nothing, the rope just sits there.
Anyone can, however, pull it and now everyone sees the rope go taunt (should they bother to look) until it’s released. Everyone can look and, at times, interject with a pull – it doesn’t matter how many of you there are looking at it. In order to avoid lots of people pulling at once, one module (or more, but usually one) is the master. If it wants to hear from someone, it’ll yank both the clock and data lines low in a certain space of time. When this happens, all other modules pay attention to what happens next. The master either pulls the data low or leaves it high, then pulls the clock low and releases it. The high/low on data line when the clock moved was a bit. There’s lots more formatting to it, but in this manner the master bleeps out (with data pulls/no-pulls and repeated clock pull/release) an adress and if it wants to speak to it (like “I want to set bytes 1 through 8 on the display to what I’m sending next”) or hear from it (like “I want the whomever is the thermostat to state the current temperature”). Supposing it panned out, said device will pull on the lines in response (called an ACK, for acknowledgement) meaning “I heard that and I’m prepared to do that”. After, it and the master can use the two lines to signal (either to the master or slave device depending on which direction was specified) until whatever data it was came across. Once done, another specific clock/data yank (timing wise) is done to signal “Ok everyone, that’s all done now, we’re back to leaving the lines alone and listening for next time”.
It’s a lot more complicated than that and feel free to read over it, but the Bus Pirate (and lots of other things including all I2C compatible components) already implemets it so a general idea is really plenty. It’s perhaps noteworthy that it’s a somewhat fragile protocol – if one of the components fail in such a way that it grounds one or both of the lines, everything is now broken and no one can talk to anyone. Because of this many devices have more than one I2C bus (set of two lines) to keep critical systems safe even if lesser systems fail. For instance, in a car (which often indeed use I2C or a derative of it) often has a separate bus for comfort stuff like “Open the window” or “turn the air conditioner off” and another for “move transmission to reverse” or “adjust iginiton timing to these values” as one is more important than the other. Even so, it’s often quite muddled at this level – many things (yes, including cars) in fact have buses mixing quite a lot in terms of criticallity and purpose. It often gets that way when one bus is heavily loaded an one not used much, after all the end consumer is unlikely to know about it until it fails and even then they usually won’t know *why* it failed or see that another six foot of copper wire could have made the failure way less severe.
But anyhow.. I want speak it. So I installed the above serial drivers and hooked up the little board. Started teraterm, set the port (under Setup->serial port) to 11500 bps, 8 data bits, no parity, 1 stop bit, COM16 (the new serial device that popped up in Windows Device Manger) and pressed enter. The Bus pirate responded “HiZ>”.
Actually I did no such thing, I tinkered with failing drivers, messed up terminals, broken USB cables and so forth for ages. But if it had gone right that’s what would have happened. By “HiZ>” it means it’s in high-impedence mode, meaning all ports are measuing if they’re high or low (in some cases the exact voltage on them) and putting out no power itself. It’s the default setting at it’ll disturb nothing – if it’s connected to something powered it won’t short it to ground, if it’s connected to something grounded it won’t try to pump power into it. It’ll just sit there looking at things, not harming itself or others. The “>” is because it’s a prompt, you can type stuff to it. “?” for instance will give:
General Protocol interaction
---------------------------------------------------------------------------
? This help (0) List current macros
=X/|X Converts X/reverse X (x) Macro x
~ Selftest [ Start
# Reset ] Stop
$ Jump to bootloader { Start with read
&/% Delay 1 us/ms } Stop
a/A/@ AUXPIN (low/HI/READ) "abc" Send string
b Set baudrate 123
c/C AUX assignment (aux/CS) 0x123
d/D Measure ADC (once/CONT.) 0b110 Send value
f Measure frequency r Read
g/S Generate PWM/Servo / CLK hi
h Commandhistory \ CLK lo
i Versioninfo/statusinfo ^ CLK tick
l/L Bitorder (msb/LSB) - DAT hi
m Change mode _ DAT lo
o Set output type . DAT read
p/P Pullup resistors (off/ON) ! Bit read
s Script engine : Repeat e.g. r:10
v Show volts/states . Bits to read/write e.g. 0x55.2
w/W PSU (off/ON) /<x= >/ Usermacro x/assign x/list all
HiZ>
That’s kind of a mess of options, so lets not worry too much yet. To make it interact with I2C, I type “m”, getting:
1. HiZ
2. 1-WIRE
3. UART
4. I2C
5. SPI
6. 2WIRE
7. 3WIRE
8. LCD
9. DIO
x. exit(without change)
(1)>
and “4” to choose I2C:
(1)>4
Set speed:
1. ~5KHz
2. ~50KHz
3. ~100KHz
4. ~400KHz
(1)>
It’ll ask for a speed. I’m planning on talking (at least verify I can talk) to a battery. I have no idea what it speaks as such, so I go with 2 rather randomly (happened to work in this case, could have gotten no data in which case I’d try something else).
I now connect some of the pins on the board to what I want to talk to. If I had a probe kit (also available from seeed) I’d just connect, but I don’t because it’s still shipping from shanghai or something so I connected a random piece of wire from an old computer to it instead an labeled them. The board clearly (and somewhat helpfully) labels all pins on it, but many are used for more than one thing. In this case, the Clock pin (the up/down per bit one) is labled “CLK” on the board, on the battery it’s “C”. The Data pin (current bit being transmitted) is D on the battery and MOSI on the board. Yeah, for a while I thought it’d be AUX, which it isn’t. MOSI is really a term from another protocol, meaning “Master Out, Slave In” but when in I2C mode, that’s the data pin. Also, the battery has a 3.3v (ish) out, which I connect to 3.3v on the board, and a ground which I connect to GND.
Not done yet though. Remember how something has to hold these lines at voltage when not in use? Yeah, no one is doing that. But it has the option of doing it – one of the pins is labeled “VPU” for Voltage Pull Up. If I type “P” (capital p, lowercase p turns it off) it’ll connect that pin to the appropriate lines to hold high, via a resistor. So I connect that to the 3.3v as well since that’ll be what the battery considers high. Just for kicks, I connected the ADC pin (Analog/Digital Converter, by default it plain measures the voltage on it up to 6v) to it as well. So set the pullup and do a “v” to give a readout of the current state of the pins.
I2C>P
Pull-up resistors ON
Warning: no voltage on Vpullup pin
(as an aside here, I’ve yet to actually connect any of the wires above and the 5v and 3.3v are still turned off as is the default. So it’s right – the pullup resistor I just connected has no voltage on it)
I2C>v
Pinstates:
1.(BR) 2.(RD) 3.(OR) 4.(YW) 5.(GN) 6.(BL) 7.(PU) 8.(GR) 9.(WT) 0.(Blk)
GND 3.3V 5.0V ADC VPU AUX SCL SDA - -
P P P I I I I I I I
GND 0.00V 0.00V 0.00V 0.00V L L L L L
(Yup, zeros and lows as expected. I connect the four pin-bundles)
I2C>v
Pinstates:
1.(BR) 2.(RD) 3.(OR) 4.(YW) 5.(GN) 6.(BL) 7.(PU) 8.(GR) 9.(WT) 0.(Blk)
GND 3.3V 5.0V ADC VPU AUX SCL SDA - -
P P P I I I I I I I
GND 4.06V 0.00V 4.09V 4.06V L H H H H
(Woho! The battery is registering! As it’s a litium ion, it’s a bit over 3.3v, but that’s ok. As the pullup resistor is sufficiently large and not just a short to GND, it’s not violently catching fire as it overheats and sprews elemental lituium which is nice since it’s on my lap. It’s probably not that drastic in reality – it most likely has it’s own overcurrent protection and I’m only holding the wires in place with my hand so I’d yank them at once. I invoke “(1)” which is a macro to issue a read and a write order to each address possible, issuing a “done” in between regardless of answer)
I2C>(1)
Searching I2C address space. Found devices at:
0xAA(0x55 W) 0xAB(0x55 R)
I2C>
Double woho, it speaks! Apparently it considers 0xAA to be it’s name (0xAB for reading). Next step, attempt to find out what it says either by listening to the device pretending to be a battery, the battery pretending to be a device or just between them evesdropping. But that’s enough for now I think.
In case you made it this far, I’ll go ahead and mention that the battery and device is a Kindle Keyboard (aka Kindle 3, K3). My hope is to figure out the talk between it and the device as a first step to kindle 2 and kindle 4s batteries. I don’t have functional batteries for those and would like to program something to pretend to be one to run it off another power source.