From WikiTI
Jump to: navigation, search


Port Number: 10h

Function: LCD Command and Status Port

This port is used to check the status of and send commands to the calculator's LCD driver.

TI 84 Plus C SE

Information on the LCD driver for the TI-84 Plus C SE is on another page.

TI-83 Plus, TI-83 Plus SE, TI-84 Plus, TI-84 Plus SE

Note: Official documentation for the LCD controller uses "X" to refer to rows and "Y" to refer to columns.

Read Values

The state of the LCD can be determined by reading this port.

  • Bit 0: Set if auto-increment mode (commands 05 and 07) is selected, reset if auto-decrement mode (commands 04 and 06) is selected.
  • Bit 1: Set if auto-increment or auto-decrement will affect the current column, or reset if auto-increment/decrement will affect the current row.
  • Bit 2, 3: Not used.
  • Bit 4: Set if in reset state, reset if in operating state. (Whatever that means.)
  • Bit 5: Set if the display is enabled. Reset if disabled. (Note: LCD is completely turned off via Port 03h.)
  • Bit 6: Set if the LCD will transfer 8 bits at a time through Port 11. Reset if the LCD will only transfer 6 bits at a time.
  • Bit 7: Set if the LCD is busy. Reset if a command can be accepted. (Not on newer models, see Comments.)

Write Values

Writing this port sends a command to the LCD. Once you send a command, wait until bit 7 reads 0 before sending another. You need a minimum delay of 10 microseconds (60 cycles of whatever else on the 6MHz TI-83+, or ~150 on a TI-83+ Silver or any TI-84+ when running in fast mode).

  • 00 : Switch to 6-bit mode. (Port 11 transfers 6-bits at a time.)
  • 01 : Switch to 8-bit mode. (Port 11 transfers 8-bits at a time.)
  • 02 : Disable the screen. This blanks the screen and disconnects the LCD RAM from the physical screen, thus allowing you to use the LCD RAM as extra saferam. (But accessing it is so horribly slow that you should only do this if the usual saferam areas aren't enough and you don't need to display anything.)
  • 03 : Enable the screen. This resumes displaying the LCD's RAM contents to the physical screen. (So any garbage you put into LCD RAM while it was off will show up, so B_CALL ClrLCDFull before this!)
  • 04 : Set X auto-decrement mode. Every read or write operation from the data port will cause the LCD's internal pointer to move up one row.
  • 05 : Set X auto-increment mode. Every read or write operation from the data port will cause the LCD's internal pointer to move down one row. The TI-83+ expects the LCD to be in this mode for most display routines.
  • 06 : Set Y auto-decrement mode. Every read or write operation from the data port will cause the LCD's internal pointer to move left one column.
  • 07 : Set Y auto-increment mode. Every read or write operation from the data port will cause the LCD's internal pointer to move right one column.
  • [08~0B]: Set power supply enhancement. You'd be well advised to just leave this alone.
  • [0C~0F]: Applies screen mirroring on newer calculators. Bit 0 set enables horizontal mirroring, bit 1 set enables vertical mirroring.
  • [10~13]: Set power supply level. You'd be well advised to just leave this alone.
  • [14~17]: Undefined.
  • [18]: Cancel test mode (see Comments).
  • [19~1B]: Undefined.
  • [1C~1F]: Enter test mode (see Comments).
  • [20~3F]: Set column. [20~2E] are valid columns in 8-bit mode, [20~33] are valid columns in 6-bit mode. [34~3F] values are also accepted, but do not correspond to a drawable area.
  • [40~7F]: "Z addressing" (It just changed what phyiscal row the top row of RAM is displayed on. The LCD will wrap the bottom of it's RAM to the top of the screen as needed.)
  • [80~BF]: Set row.
  • [C0~FF]: Set contrast. (C0 is lowest. Note that there is a System RAM area (contrast) for this which will need to be updated if you want 2nd+Up/2nd+Down to change the contrast as expected (instead of causing a sudden jump...).)


Necessary LCD communication delay

As mentioned, a 10 microsecond delay is required after sending the command. TI provides a routine at 000B (use normal CALL, not BCALL) that will delay the required amount of time. (Because this was not originally an LCD delay routine, on OS's prior to 1.13, calling it destroys the zero flag.)

On older calculators, this code sequence should also provide sufficient delay while also preserving the carry flag:

 ex (sp),hl ;19
 ex (sp),hl ;38
 inc (hl)   ;49
 dec (hl)   ;60

But I would advise you actually make use of these waste cycles somehow (process a buffer or something).

On some newer calculators, a fixed delay can still be used in combination with slowing the CPU through port 20 and/or adjusting ports 29 and 2A. However, a large number of calculators have been produced recently whose LCD drivers, for whatever reason, do not respond as quickly. For this reason, except where the speed loss is absolutely unacceptable (such as for grayscale display) fixed delays should not be used. Instead either use the routine at 000B, or poll this port or Port 02h manually.

Since recently (late 2018), new calculators have started appearing which do not set the 7th bit when busy. Therefore, you can't use it to check if the LCD is ready. The best workaround is to wait for long enough and hope for the best, or use a different port to measure the delay.

Unused screen area

The LCD driver's video memory holds a display 120 pixels wide, even though the screen is only 96 pixels wide. The 24 pixel wide offscreen area can still be read from and written to, and is not affected by soft power-off.

Test mode

This is a very dangerous mode. The first test mode command (1C~1F) causes the screen to receive an unusually high amount of energy. The result is that the screen seems to go blank, save for a single blue(!) line on the TI 83, but on the TI 84's, the entire screen turns blue! Each subsequent command adds more blue lines. After you've had your fill of blueness, exit test mode by sending a exit test mode command (18), which also sets the contrast to it's highest. Now why is it dangerous? Sure it looks cool to make a supposedly black and white LCD to display BLUE, but you are pumping so much energy through the LCD to get this effect that leaving it in this mode for too long can cause long-term damage. Ever left your monitor on for a day or two and forget to set a screen saver? Remember how when you turned it off a burnt image of your screen remained? Well that's what can happen if you leave test mode on for too long. Other possible side effects include "dead pixels" (pixels that stay off no matter what you do).

So don't use test mode okay? Just pretend you didn't hear about it...

On newer calculators, the test mode commands seem to be ignored, so this is yet another reason to not rely on this function.

Power settings

On my (fghsgh's) calculator, the power supply command extends to 17. The boot code even initializes this setting to 17. Settings 10~13 all make the screen slowly fade to black, then fade to white, and then it stays blank. Writing any command in the range 14~17 makes the display come back to life. The power supply enhancement doesn't seem to do anything, but the (1.03) boot code initializes it to 0B.

Cursor movement and out-of-bounds behavior

It is possible to set the column number out of range, either by directly writing a column number out of bounds, or by switching to 6-bit mode, moving the column to a position outside of 8-bit mode's range, then switching back to 8-bit mode.

If the column is out of range, no write is made to the display, but the column will continue to increment or decrement.

8-bit mode

In 8-bit mode, the column will wrap from 14 to 0 when moving right, and wrap from 0 to 14 when moving left. If the column>14, then there is no wrapping, the column will continue to increment or decrement within the full range of 0-31. Exceeding column 31 returns to column 0.


Same as 8-bit mode, but column wraps from 19 to 0 when moving right, and 0 to 19 when moving left.


Turn the LCD "off" and back "on".

 ld a,02h
 out (10h),a
 ex (sp),hl ;Or do something else that takes ~60 cycles.
 ex (sp),hl
 inc (hl)
 dec (hl)
 inc a
 out (10h),a

Safely wait for the LCD to become available

 in a,($10) ;bit 7 set if LCD is busy
 jr c,lcd_busy_loop

See Also