General Purpose I/O on the BT200

This setup may or may not be shared with other kinds of phone. To be on the safe side, only the setup for BT200 phones is defined below.


JTAG setup

Using OpenOCD with Generic BSDL support, the following can be used to prepare for GPIO access over JTAG:

jtag newtap bt200 bs -irlen 38 -ircapture 0x01 -irmask 0x03
target create bt200bs generic_bsdl -chain-position
#?# jtag init
bt200bs bsdlfile tms320vc5501pgf.bsdl

You can find the BSDL file in this BSDL zip where it is named sprm158.bsm instead of tms320vc5501pgf.bsdl like above.

Crystal clock

The crystal has a period of 60 ns, so it gives out a frequency of about 16.2/3 MHz. More accurately, the frequency is 16.384 MHz.

After division by four, the remaining fast peripheral clock SYSCLK1 or CLKOUT is 4.096 MHz. This is also what drives the timers if the internal clock is selected as a source.

We will setup timer 0 as a general timer, after dividing by 4096000 to get ticks with 1 ms resolution. This can be done in the first/prescaler 32-bit half of timer 0, and then the second 32-bit half can be read as a millisecond-resolution timer that can describe periods of up to 49.7 days.

Hook contact

The hook contact is connected to GPIO5. When the horn is on the hook, this input is 0, otherwise it is 1.

TODO: Is readout over JTAG possible? Is it useful??

LCD backlight LED

This is driven from DX0, an output normally associated with synchronous serial port McBSP0. According to spru592e, this pin can be used as GPIO when the following settings are made:

These settings are already part of the ones for keyboard scanning, below.

We can thus switch the LCD backlight on and off for a second using JTAG:

bt200bs force high BDX(0)   # on?
sleep 1000
bt200bs force low  BDX(0)   # off?

Admittedly, doing this over JTAG is a tad bit more complicated than the problem requires -- but it could be a good exercise to see if JTAG is working.

Message LED

Believe it or not, but this was the last piece in reverse engineering the phone. I've had to tell people that 99% of the hardware was understood, and then point to this LED as the last bit of knowledge missing.

The trouble was that it was wired through resistors, so that my ohm-meter would not beep for a connection, and through a NOR port that acts as an inverter. Also, it was routed over the back of the PCB, making it hard to co-ordinate measuring pins on both sides. Alas, it was no match for determination, of course.

Anyhow, the Message LED is driven from the XF pin. This is operated with dedicated assembly instructions, bset xf and bclr xf. With this knowledge in place, 100% of the BT200 hardware has been reverse engineered. As expected, driving this bit was trivial; it took me seconds to implement.

Much to my surprise, a potential GPIO pin from McBSP0, CLKS0, cannot be used as this is input-only. Had that one been used for the keyboard, a signal that could function as output would have been freed up, making it possible to do all the "extra" work for keyboard and LEDs through McBSP0 hacks.

Keyboard scanning

The keyboard is a 5x5 matrix with active lines D0-D4 and passive lines C0-C4 on peripheral connector J403.

Lines D0-D4 are copies of the data bus during a write (C2=EMIF.nWE low) to EMIF space CE3 (C2=EMIF.nCE3 low). The following copies from the data bus are made during such writing phases:

D0 keyboard active scanline D0
D1 keyboard active scanline D1
D2 keyboard active scanline D2
D3 keyboard active scanline D3
D4 keyboard active scanline D4

The inputs from the keyboard come in as passive lines C0-C4. These lines connect to the SoC directly, using the McBSP0 input lines as GPIO lines:

C0 GPIO function of CLKR0
C1 GPIO function of CLKX0
C2 GPIO function of FSR0
C3 GPIO function of FSX0
C4 GPIO function of DR0

This alternative use of the McBSP0 lines is possible since this serial port is not otherwise used; document spru592e describes the conditions under which this is possible:

Clever as this trick may sound, it rules out a nice facility, namely to make a tickless bottom layer for the 0cpm tickless RTOS. That is because it does not seem possible to read this keyboard without active scanning; the incoming C0-C4 lines have no facility for interrupts on change.

Had it been me, I would have preferred to combine selected D0-D4 scan rows into one interrupting input, perhaps through a port or series of diodes. That way, it is possible to sleep continuously while no keys are being pressed. Phones are usually inactive, and having them sleep deep for long is a good idea. Scanning the keyboard while a key is pressed is much less expensive. The current solution uses a D-flipflop chip, which is useless for storing the columns to watch; given no reason to retain the column for interrupt stability, columns might just as easily have been taken from the address bus!

The following table presents how keys are located in the 5x5 matrix driven by D0-D4 and read back from C0-C4:

The Matrix C0 C1 C2 C3 C4
D0 1 2 3 Message Hold
D1 4 5 6 Transfer Conference
D2 7 8 9 Flash Mute/Del
D3 * 0 # Send Speaker
D4 Down Up Callers Called Menu

Gosh, I was messing around with pins in the peripheral connector until I realised that the keyboard PCB was a straighforward, single-sided PCB with a course layout. I could just track the keys instead of measuring them -- silly me ;-)

LCD access

As explained above, a write to the CE3 area copies data bits to the LCD connectivity:

The LCD receives new data values during a write (C2=EMIF.nWE low) to EMIF space CE3 (C2=EMIF.nCE3 low). The following copies from the data bus are made during such writing phases:

D5 LCD driver pin RD
D6 LCD driver pin WR
D7 LCD driver pin DATA
GPIO1 LCD driver pin CS

Specifically note that the lines D0-D4 are not available to the LCD.

An LCD driver chip that shows up promiscuously when looking for these signal names is the HT1621D chip by Holtek. Note that there is no good way to know if this chip is used! However, as a logic analyser shows all too clearly, the commands sent to the chip make a lot of sense when interpreted as HT1621 commands:

100-0000-0010-0 LCD OFF Switch off the LCD
100-1110-0011-0 NORMAL Not testing, but normal-use mode
100-0001-1000-0 RC 256K Use internal RC-osc at 256 kHz
100-0000-0001-0 SYS EN Turn on system oscillator
100-0000-0011-0 LCD ON Switch on the LCD
100-0000-0100-0 TIMER DIS Disable timer
100-0000-0101-0 WDT DIS Disable watchdog timer
100-0000-1000-0 TONE OFF Switch off unused buzzer output
100-0010-1001-0 BIAS 1/3 Bias 1/3 with 4 commons option
100-0110-0000-0 TONE 2K Any tone generated is 2 kHz

The beginning of these signals is shown below, where:


The BT200 does not actually use the RD connector to read data from the RAM built into the display; instead, it simply sends out what needs to be stored:


The chip clocks DATA in on a rising edge on WR. It should be possible to use CS to avoid disrupting the LCD during other work, such as scanning the keyboard.

I do not understand why RD is available, as I cannot trace a link for DATA back to the DSP chip. It appears that the peripheral interface was designed separately, before the rest of the phone. The uselessness of reading from a deterministic output-only device may have dawned on the designers at that later stage.

What now remains to be done is to map the various bits in the LCD driver RAM (32 words of 4 bits each) to their display segment. The following image shows this, with x@y to represent bit x at address y. The addresses are byte addresses, so the LCD driver receives doubled addresses; furthermore, data is shifted out in units of 8 bits, with the high bit (under the image's numbering) sent first. This is consistent with the data sheet, where any number of nibbles can be shifted out in sequence; only the data bit numbering differs from the datasheet, because it would be silly to follow them and number data and address bits in opposite orders (?!?)


Sound channels