DAY 26. The LCD Driver

novice intermediate advanced expert

Unfortunately, the "crap series" (everything lower than a TI-85) uses a driver that stores the screen image in its own RAM. In order to change the display, you have to send each byte in the image to the driver. It is also a very slow driver which needs a delay every time it is accessed.

Hopefully you are sufficiently depressed now, so let's look at how to make the Toshiba T6A04 (that's the name of the driver) our bitch.

Control Ports

$10 Command Port Alters the driver's status. $11 Data Port Let's you muck about with the driver's RAM.

_LCD_BUSY_QUICK Creates a sufficient delay for the LCD driver, regardless of what model. Location $000B Remarks For this routine, you use a CALL instead of the normal b_call() .

Driver RAM

Instruction Effect $20 to $2E Set column: 0 (leftmost 8 pixels) to 14 (rightmost 8 pixels). $80 to $BF Set row: 0 (top row) to 63 (bottom row).

Auto-Addressing

$04 X auto-decrement Driver moves back one byte along X. $05 X auto-increment Driver moves forward one byte along X. $06 Y auto-decrement Driver moves back one byte along Y. $07 Y auto-increment Driver moves forward one byte along Y.

The TI-OS expects X auto-increment mode for all its routines, and must be set back to this mode if you change it. Although the results could be interesting if you don't.

Reading and Writing (But Thank God No 'Rithmetic)

IN A , ($11)

To write (which doesn't require a dummy):

OUT ($11), A

Program 26-1

Pic0

_LCD_BUSY_QUICK .EQU $000B LD HL , Pic0Name RST 20h RST 10h JR NC , ExistError b_call(_CreatePict) EX DE , HL INC HL INC HL CALL ScanLCDToPic EI RET ScanLCDToPic: DI LD A , $80 ; Set row 0 OUT ($10), A LD C , $20-1 ; C will hold column Row: INC C LD A , C CP $2C ; See if C exceeded maximum column value RET Z CALL _LCD_BUSY_QUICK OUT ($10), A ; Set column CALL _LCD_BUSY_QUICK IN A , ($11) ; Dummy read LD B , 63 ; 63 display rows to a picture LD DE , 12 ; Because LCD is read in column-major order, ; and picture data is in row-major order. Column: CALL _LCD_BUSY_QUICK IN A , ($11) ; Read one byte LD (HL) , A ; And put it to the picture ADD HL , DE DJNZ Column CALL _LCD_BUSY_QUICK ; Restart at row 0 LD A , $80 OUT ($10), A LD DE , -(12 * 63) + 1 ; -(12*63) returns to the first row. ADD HL , DE ; + 1 moves one column over. JR Row ExistError: ; Display an error message if Pic0 already exists b_call(_ClrLCDFull) LD HL , 0 LD (CurRow) , HL LD HL , ExistErrorMsg SET TextInverse , (IY + TextFlags ) b_call(_PutS) RES TextInverse , (IY + TextFlags ) b_call(_PutS) b_call(_GetKey) RET Pic0Name: .DB PictObj , tVarPict , tPic0 , 0 ExistErrorMsg: .DB "ERR: PIC EXISTS", 0 .DB "Press any key...", 0

Contrast

command = contrast + (24 OR $C0)

Reading the command port does not tell you what the current contrast setting is, so the system's contrast value is held in (contrast). The value here is in the range 0 to 39.

Program 26-2

_LCD_BUSY_QUICK .EQU $000B #define DEC_A_OP $3D #define INC_A_OP $3C b_call(_RunIndicOff) b_call(_GrBufClr) LD A , (contrast) LD B , A ; Number of times to decrease contrast ADD A , $18 | $C0 ; "|": TASM command for bitwise OR PUSH BC ; Save current contrast so we can fade back LD HL , FadePatch ; SMC Fade routine to fade to white. LD (HL) , DEC_A_OP CALL Fade ; Display a picture here. Make sure to keep A intact. POP BC ; Restore counter -- number of times to increase ; contrast to restore the original setting. LD HL , FadePatch ; SMC Fade routine to fade in. LD (HL) , INC_A_OP Fade: OUT ($10), A HALT HALT ; Delay for approx. 1/20th second HALT HALT HALT HALT HALT HALT FadePatch: DEC A DJNZ Fade RET

Test Mode

$1C

$1F

$18

Now that you know about test mode, please, don't use it. There is no way to make the BLODs appear on a specific row, nor can they be constrained. If you had any hopes of making some kind of waterfall animation, you can just as well forget about it.

As well, test mode is dangerous. If you leave the calculator in test mode for more than a minute, you risk damaging the LCD. Even a few seconds of BLODs may leave an imprint on the screen (not unlike phosphor burn-in when you forget your screen saver).

Power

$02

$03

Z-Address

$40

$7F

$40

Program 26-3

LD B , 63 LD A , $41 Scroll: OUT ($10), A INC A LD C , 5 ;Use a bigger number for slower scrolling. Delay: HALT DEC C JR NZ , Delay DJNZ Scroll LD A , $40 OUT ($10), A RET

Word Size

The word size is changed with two commands:

$00 Configure six bits per word $01 Configure eight bits per word

Program 26-4

b_call(_ClrLCDFull) b_call(_HomeUp) LD HL , text CALL CustomStr RET text: .DB "Hello ", 1, 0 CustomStr: LD A , (HL) OR A RET Z CP 1 JR NZ , NormalChar ; Trap for char $01 (custom) PUSH AF XOR A ; Configure word size OUT ($10), A LD A , $05 ; Configure X auto-increment CALL $000B OUT ($10), A LD A , (CurCol) ; Set LCD Row ADD A , $20 CALL $000B OUT ($10), A LD A , (CurRow) ; Set LCD Row ADD A , A ADD A , A ADD A , A ADD A , $80 OUT ($10), A LD DE , Smilie LD B , 8 FontLoop: LD A , (DE) CALL $000B OUT ($11), A INC DE DJNZ FontLoop LD A , (CurCol) ; Advance cursor position INC A AND %00001111 LD (CurCol) , A JR NZ , DoneCustomFont LD A , (CurRow) ; Advance row. This doesn't check for a bad INC A ; position or scroll. Do that on your own time. LD (CurRow) , A DoneCustomFont: POP AF JR DoneChar NormalChar: b_call(_PutC) DoneChar: INC HL JR CustomStr ; Our custom character! smilie: .DB %00011110 .DB %00101101 .DB %00101101 .DB %00111111 .DB %00101101 .DB %00110011 .DB %00011110 .DB %00000000

LCD Command Port Cheat Sheet

Outputs Command Function $00 Configure six bits per word $01 Configure eight bits per word $02 Turn off $03 Turn on $04 X auto-decrement mode $05 X auto-increment mode $06 Y auto-decrement mode $07 Y auto-increment mode $08 – $0B Power supply enhancement. $08 is lowest. $10 – $13 Power supply level. $10 is lowest. $14 – $17 Unknown $18 Exit test mode $19 – $1B Unknown $1C – $1F Enter test mode $20 – $2E Set column in 8-bit word mode $20 – $33 Set column in 6-bit word mode $34 – $3F Unknown $40 – $7F Set Z-address $80 – $BF Set row $C0 – $FF Set contrast

Inputs Bit State 7 1 : LCD is busy

0 : LCD can accept a command 6 1 : 8 bits-per-word

0 : 6 bits-per-word 5 1 : Display is on

0 : Display is off 4 1 : In reset state

0 : In operating state 3 Not defined 2 Not defined 1 1 : Y-Auto mode

0 : X-Auto mode 0 1 : Auto increment mode

0 : Auto decrement mode

This is part of Learn TI-83 Plus Assembly In 28 Days

Copyright (c) 2002, 2003, 2004 Sean McLaughlin

See the file gfdl.html for copying conditions