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.
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 bt200.bs #?# 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.
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.
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??
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.
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.
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 ;-)
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:
101-00000-0101-0111-1101-...
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 (?!?)
TODO: