LCMControllerDetection
This page explains how one can, with relative ease, find the display controller and its connectivity used in a particular s1mp3 device.
Theory and Assumptions
This procedure was created by noticing the following simple facts:
- The hourglass image is displayed by the BREC
- To display this image, code that controls the display must be present
- Thus, the BREC contains display controller code.
Upon closer inspection and analysis of the BREC, it is found that the code which initializes LCM and displays hourglass is located at address 3000 within the BREC (which is loaded at address 0.) Thus, we are able to find this code and consequently inspect it to determine the LCM type and its connectivity.
To carry out this procedure successfully, we assume that the reader has the following:
- General understanding of the s1mp3 boot process
- General understanding of connectivity and concepts of s1mp3 Display
- Knowledge of Z80 assembly language
- Knowledge of the GPIO registers for the SoC used in the device
- Z80 disassembler
Procedure
Obtaining BREC
A BREC for the device in question is obtained. There are multiple ways in which this step can be carried out.
Via s1clone
If using s1clone, one will also need a USB logger to intercept the communication between s1clone and , since the current dump format used by s1clone is both compressed and contains extra (ECC) data. When logging, one will see that s1clone uploads s1giveio to the device, instructs it to read the BROM, twice, and immediately after should come the pages of flash which contain the BREC, each page being followed by the extra ECC data. The start of the BREC can be detected in the data stream by the bytes C3 00 02 00 followed by "BRECFxxx" where xxx is the type of BREC currently in the device. After BREC has been read by s1clone there will be no need to dump rest of the data, s1clone can then exited.
TODO: elaborate more on process, figure out s1clone dump format, or remove, write, and discuss use of different BREC dump tool...
Via Existing Firmware
s1fwx or similar can be used to extract a BREC from an existing firmware file.
Other
If one already have a BREC or other way of obtaining it from the device, that is also possible.
Validating BREC
Follow the procedure of validating BREC that is performed by the BROM (check for 55AA signature and do checksum) to ensure it is correct. See BREC#The_Checksum for details. The resulting file should be exactly 16,384 bytes.
Disassemble BREC
Load the BREC file into a Z80 disassembler with a starting offset of 0000 and begin to manually follow the code flow. Shortly after one should arrive at 3000 where the LCM controller code is located. This code can be divided into several parts, as follows (example code is given, but will be definitely different for your device, unless it is also a ZX-6012M-TLS V4.0 with CGS150B05 LCM which these examples are from.)
Initialize MCU and GPIO
X3000: in a,(5) ld b,a or 7 ; map in B1+B2+URAM out (5),a in a,(70h) ld c,a set 5,a set 4,a out (70h),a ; set PLL to 36MHz ld a,b ld (X31d7),a ld a,c ld (X31d8),a in a,(0) ld (X31d6),a ld a,11h ; MCU clock = HOSC/2 (12MHz) out (0),a in a,(0eeh) and 1fh ; F1 (GPIO mode) or 8 ; turn on GPO A3 (CE3 when in a different MFP mode) and 0fbh ; turn off GPO A2 (backlight) out (0eeh),a in a,(0efh) and 0cfh ; GPIO B4 and B5 to GPIO mode out (0efh),a in a,(0f1h) and 0cfh ; GPIO B4 and B5 disable input out (0f1h),a in a,(0f0h) or 30h ; *** GPIO B4 and B5 enable output out (0f0h),a in a,(2) ld (X31da),a ld a,18h ; select CE3 out (2),a
Ignoring the backlight setting (may not be present on some models), one can already determine that B4 and B5 will be in some way connected to LCM, and in this device it is connected to CE3.
Reset LCM
This next piece of code shows that LCM reset signal is active-low, and is connected to GPIO B4. (At 3157 is a delay routine, the details of which are not important to the current topic.)
ld c,10h ld d,0efh in a,(0f2h) ; the following sequence generates LCD reset pulse or c ; GPIO B4 on out (0f2h),a call X3157 ; wait a little and d ; ...and turn B4 off again out (0f2h),a call X3157 ; wait a little or c ; ...then on again out (0f2h),a
LCM Initialize Sequence
Here is where the code will differ significantly between devices. The important details to notice are the bytes which get written to the high memory area, and the subroutines which switch between command and data mode. The first byte to be sent will obviously be a command, and thus the first subroutine which is called will be one that sets the appropriate GPIO to command mode state. Here is the pair in the example device:
; write command c X3166: in a,(0f2h) and 0dfh ; GPIO B5 off out (0f2h),a ld a,c ld (X8000),a ; write command in a,(0f2h) or 20h ; GPIO B5 on (back to data mode) out (0f2h),a ret ; write data c X3179: in a,(0f2h) or 20h ; GPIO B5 on out (0f2h),a ld a,c X3180: ld (X8000),a ret
From the above code one can gather that B5 is the command/data GPIO, and commands are sent when it is low, data when it is high. The following information is thus obtained in total:
- LCM is selected on CE3
- GPIO B4: active-low reset signal
- GPIO B5: low/high command/data signal
Clear Display and Show Hourglass
ld c,2ch ; enter memory write mode call X3166 ld bc,X8000 ; 128x128x2 = 32768 bytes ld hl,X8000 ld de,Xfcc0 ; color fcc0 X30f8: ld a,d ld (hl),a ld a,e ld (hl),a dec bc ld a,b or c jr nz,X30f8
This part of the code will be relatively similar between different devices; nonetheless, one can gather more information from it, such as the fact that on this particular example, the display is 128x128 16bpp (64K colors) and the command to enter the mode to write data to the display RAM is 2C. Because display RAM is set to random values on power-on and remains so even after reset, this code is necessary to uniform the color of display.
ld c,2ah ; column address call X3166 ld c,36h call X3179 ld c,49h call X3179 ld c,2bh ; row address call X3166 ld c,2eh call X3179 ld c,51h call X3179 ld c,2ch ; memory write mode call X3166 ld hl,X31db ld de,X8000 ld bc,X05a0 ldir ; write hourglass image
The next step is to write the hourglass image itself. This is usually accomplished by setting the starting row and column to the dimensions of the hourglass, then transferring the data to the display by once again entering memory write mode. The dimensions of the hourglass image are left as an exercise for the reader.
Enable Backlight
in a,(0eeh) or 4 ; GPO A2 on (backlight) out (0eeh),a
After writing the hourglass image, the backlight is turned on to show it. Devices that do not have a backlighted display will not have this part in the code, but instead continues immediately to the part after the above, which will restore the registers saved near the beginning and return. From the above code, one can see that GPO A2 is an active-high backlight enable.
Summary
- LCM is selected on CE3
- GPIO B4: active-low reset signal
- GPIO B5: low/high command/data signal
- GPO A3: active-high backlight enable
Determine LCM Controller Type
This part is slightly more difficult, but can be completed if one looks at the sequence of commands sent to the controller and compares them with the command sets of known controller types (see LCMControllers). Notable commands to recognize include those to set the width and height of the display, and those to set the current write position and enter display RAM write mode (present between clearing the screen and showing the hourglass).