I did some analysis of Pinephone keyboard prototype's schematics,
components and firmware. Here are some of my observations.
First let's look at major parts of the keyboard, and what features
Charging controller – IP5209
The chip is designed for use in power banks with optional LED flashlight.
It takes input from a 5V power supply or the battery and provides 5V output
using a boost step-up DC-DC converter.
It has some other minor features, like LED indication, and timed key input
(long/short press of the key do different things).
It also has rather detailed control of its functionality over I2C bus:
- Independent control (enable/disable) of
- Boost (5V VOUT to power Pinephone)
- Battery Charger
- Light (100mA output for flashligh LED)
- Optiobal automatic shutdown when VOUT has light load (customizable via reg
0×0c, min. is 100mA, shutdown lastsa 8–64s (see reg 0×04))
- Optional automatic power on when load is inserted
- Optional auto enable of VOUT when disconnecting VIN (reg 0×04)
- NTC control
- Charger_CTL1 0×22
- Control of charging current based on VOUT undervoltage (it tries to keep
VOUT in a certain range by reducing load on VIN by decreasing charging
- Needs CSIN and CSIN_S connected properly? https://megous.com/dl/tmp/84945e77ee74ddd6.png
- Battery type selection 4.2/4.3/4.35V
- + extra margin 0–42mV during constant voltage phase?
- External (via VSET pin) or internal setting (via reg 0×24)
- Charging current selection (100mA – 2.3A ?)
- Charging status register
- charging state – idle, trickle, constant voltage/current phase, full,
- LED heavey load indication
- VIN overvoltage indication (> 5.6V)
- Button press status
- current state: UP/DOWN
- long press
- short press
- KEY input
- Long press button time selection 1–4s
- Enable/disable 2× short press shutdown function
- L3/L4 function selection:
- LIGHT pin function selection:
- VSET (normal function to select battery voltage via PIN setting)
- battery internal resistance selection via resistor on the RSET pin
- separate input/output enable register for all 5 GPIOs
- GPIO data register to read/write values to pins
- 14 bit two register VBAT, IBAT, VBAT_OCV readings
This is quite a lot of useful functionality for Pinephone
keyboard's use case!
USB microcontroller –
This is rather generic and simple microcontroller with USB bus support. There
is nothing really remarkable about it.
It uses 8051 instruction set, and has 32768 bytes of flash memory for code
with 10,000 write/erase cycles. 2048 bytes of XRAM and 256 bytes of RAM.
Pin change wakeup is available on ports 5, 6, 9. There's a I2C slave
peripheral, that is connected via POGO pins to Pinephone.
It has low power mode, that allows disabling CPU clock. Remaining features
are not useful for the keyboard use case.
Documentation for the basic features is available on the Elan
Pinephone keyboard schematic
Keyboard schematic is rather simple:
- USB microcontroller GPIO ports are connected to some matrix of wires that
are connected together when the key is pressed.
- Pressed keys can be scanned by applying voltage to each row in sequence and
checking the voltage on the columns of the wire grid. Quite typical.
- One I2C port is connected over POGO pins to Pinephone.
- This is the only way the phone can communicate with the keyboard.
- Interrupt line is connected over POGO pins to the phone.
- This is used by USB microcontroller to signal to Pinephone that a key was
pressed, and that data are available over I2C for readout.
- It can also be configured as a HW reset pin for the USB
- USB data pins are exposed to a Type-C USB connector in the keyboard body.
- This is used as one way to program the keyboard firmware.
- Keyboard controller is powered from the POGO pins (USB-5V).
- USB-5V is a power path that can't be disabled, on Pinephone, and is turned
off only when the phone itself is off.
- Looks like the keyboard will only be flasheable when connected to the phone
and with the phone powered up.
- Programming interface pins exposed on the PCB for easy access. Interface is
Proprietary firmware written in C was sent to some developers, incl. me, and
I was able to compile it using Keil C. Firmware is half C code, half
„bootloader“ distributed in binary object form. So it's possible and rather
easy to modify the firmware. The issue will be with flashing it.
At this time, only sure way to program this microcontroller is to have a HW
programmer from Elan microelectronics, install a windows driver and software,
and use some windows GUI tool to flash the firmware over pads exposed on the PCB
inside the keyboard.
There's also a possibility of flashing the firmware over USB, but the
protocol is not documented, and there's no non-proprietary program available to
This flashing method currently depends on proprietary bootloader, and
cooperation of the existing keyboard firmware with entering the flashing mode.
So if a broken application code is flashed, it will not be possible to re-flash
it again using this method.
At my request, TL Lim sent me a Windows flashing tool for the
keyboard's firmware. I've started reverse engineering it, and at this time
I have the basic protocol reverse engineered, and I should be able to
communicate with the keyboard using
/dev/hidraw# device. I don't
have the keyboard prototype HW, so I can't do much more at this time.
Next step is to get a capture of USB communication of the original flashing
tool for Windows using usbpcap and
cross-check the reverse engineering data with the actual communication and then
write a Linux port of the flashing tool. This will allow me to create a better
firmware updating mechanism for the keyboard controller, and experiment with key
scanning routines. Looks like there should be no limit to how many keys can be
pressed at the same time. :)
It would be nice if people with the keyboard prototype did the capture,
otherwise the development will stall until I receive the prototype, too.
charging/battery circuit schematic
Charging circuit can not be controled over I2C bus, because I2C bus from
Pinephone is not connected to it. This is rather limiting.
- There are 4 LEDs that visually indicate actual charge in 25% increments.
- Either these LEDs can be used or the charger can be connected over I2C to
- There's a button in the keyboard body, that is connected to the charging
circuit and allows to control the charger.
- This is the only input that can affect the operation of the charger. The
rest is fully automatic and outside of the control of the user or
- Battery charging circuit is connected to Type-C connector's VBUS, from
which it draws power.
- There's no provision for detecting advertised power source capabilities of
the adapter plugged to the Type-C port.
- Keyboard does not feature a PD controller, nor does it monitor USB 2.0 data
pins on the Type-C connector, because those are connected to keyboard's USB
- This means that there's no way to detect current allowance of whatever
other end it connects to or to detect how much current the other end can
- The charger will draw ~10–11W from the Type-C connector when charging or
passing through power to VOUT.
- Thus the circuit is not compliant with USB standards, it will require some
care when connecting to normal SDP PC USB ports. You'll have to make sure the
battery is charged, and Pinephone is not using power from the keyboard
(it's turned off and fully charged, too).
- Failing to do this there will be over-current condition on the SDP port and
it will shut down.
- It will also be troublesome in using this with Type-C power sources that can
only provide 1.5A (some hubs, docks, etc.)
- There's some provision to reduce load so that VBUS of the source doesn't
drop bellow 4.5V (with hysteresis of 200mV – I'm not sure how hysteresis is
supposed to work in this case).
- This is not enough to make it a fully standard conforming USB device, but it
should work with 2.1A+ DCP or 5V/3A PD chargers just fine.
- It's unclear if input current can be meaningfully limited. It's possible
to limit the charging current, but not the input current, which is sum of the
charging and Iout currents.
- Boost output (VOUT/5V) is connected to Pinephone via POGO pins.
- It is not possible to turn VOUT on/off based on the needs of the
- Keyboard's charging circuit can enable VOUT at any time either
automatically, or via user pressing the button, so it's unpredictable.
- You'll not be able to use Pinephone's Type-C port for charging while the
keyboard is connected.
- Keyboard charger VOUT is directly connected to Pinephone Type-C VBUS/DCIN,
so PD charger would probably not enable its VBUS if it detects non-V0safe
voltage on VBUS during plugin.
- This also makes it somewhat tricky to use type-c docks/hubs, because both
USB-5V boost circuit inside Pinephone and keyboard charging circuit inside the
keyboard would be powering the OTG devices, which may confuse them.
- VBUS control is part of the type-c/PD negotiation state charts, and ANX7688
will not be able to control it when the keyboard is connected and has VOUT
enabled outside of the control of the phone.
- There's no way for Pinephone to determine the status of the keyboard
battery (charge level) or the charger.
- IP5209 has an adaptive power-path management system with priority to output
load, so as long as Pinephone will draw more than 10W, keyboard battery will not
- Shunt resistor for current sensing in not present in the schematic, so this
or other current limiting features may not work.
- Connect IP5209 to the i2c bus, instead of using 4 LEDs for charge
- Revise the charger schematic according to the suggested reference circuit
from the manufacturer of the chip. Add the current sensing resistor.
- (keyboard v2?) Add support for a lid switch.
- (myabe with optional mod/soldering bridge) Allow to share interrupt lines
with keyboard controller and charge controller (not share by default)
- Can interrupt pins from both charging controller and keyboard controller be
safely shared? It's too risky to try at this time.
- How to reset the keyboard controller without disassembling the
- How to flash the keyboard controller in a safe way during development?