LCMControllerDetection

From S1MP3 Wiki
Jump to: navigation, search

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).