ADDR B1 B2 B3 B4 F:\chicken\lcd.asm PAGE 1 * lcd.asm - Code for working with the LCD (Liquid-Crystal . Display) *--------------------------------------- * LCD-related equates *--------------------------------------- * LCD I/O registers LCD_BASE EQU $B5F0 ; LCD port, base . address LCD_CTL EQU LCD_BASE|0 ; LCD control address . = base address + 0 LCD_DAT EQU LCD_BASE|1 ; LCD data address = . base address + 1 * LCD instruction codes CLR_HOM EQU BIT0 ; Clear display and . home the cursor E ^ Unknown identifier. RET_HOM EQU BIT1 ; Return cursor home . & reset display shift E ^ Unknown identifier. ENT_MOD EQU BIT2 ; Entry mode set E ^ Unknown identifier. ID_INC EQU BIT1 ; Increment/ . Decrement = Increment (else Decrement) E ^ Unknown identifier. S_shift EQU BIT0 ; With display . shift (else not) E ^ Unknown identifier. DISP_ONOFF EQU BIT3 ; Display On/Off . Control E ^ Unknown identifier. D_disp EQU BIT2 ; Turn display . on (else off) E ^ Unknown identifier. C_cursor EQU BIT1 ; Turn cursor . on (else off) E ^ Unknown identifier. B_blink EQU BIT0 ; Turn blink on . (else off) E ^ Unknown identifier. CD_shift EQU BIT4 ; Cursor/Display . Shift E ^ Unknown identifier. SC_shift EQU BIT3 ; Shift/Cursor . = display shift (else cursor movement) E ^ Unknown identifier. RL_right EQU BIT2 ; Right/Left = . shift right (else shift left) E ^ Unknown identifier. FUNC_SET EQU BIT5 ; Function Set E ^ Unknown identifier. DL_8bit EQU BIT4 ; Interface . data length = 8 bits (else 4 bits) E ^ Unknown identifier. N_2lines EQU BIT3 ; Number of . display lines = 2 (else 1 lines) E ^ Unknown identifier. F_5x10dots EQU BIT2 ; Character . font = 5x10 dots (else 5x7 dots) E ^ Unknown identifier. CGRAM_addrset EQU BIT6 ; Character Generator ADDR B1 B2 B3 B4 F:\chicken\lcd.asm PAGE 2 . RAM address set E ^ Unknown identifier. DDRAM_addrset EQU BIT7 ; Display Data RAM . address set E ^ Unknown identifier. BF EQU BIT7 ; Busy Flag: LCD is . busy processing instruction E ^ Unknown identifier. * LCD Display Data Ram (DDRAM) location equates. Row_length EQU 20 Row1_start EQU $00 Row1_end EQU Row1_start+Row_length-1 Row3_start EQU Row1_end+1 Row3_end EQU Row3_start+Row_length-1 Row2_start EQU $40 Row2_end EQU Row2_start+Row_length-1 Row4_start EQU Row2_end+1 Row4_end EQU Row4_start+Row_length-1 *------------------------------------------------------------ . ------------- * Initialize the LCD, for 2 virtual 40-character lines * (which in reality are broken into 4 rows of 20 characters . each) * and a blinking cursor that moves the right. *------------------------------------------------------------ . ------------- init_LCD: * Wait more than 15 milliseconds after power-up. C000 CE 13 88 LDX #5000 ; 5000 . iterations = 15 ms C003 BD C1 1A JSR dloop ; Wait this . long before sending 1st cmd * Send a Function Set 8-bit data length command LDAA #FUNC_SET|DL_8bit ; Function . set, data length 8-bit E ^ Unknown identifier. E ^ Unknown identifier. C006 B7 B5 F0 STAA LCD_CTL ; Store 8-bit . command to LCD control register * Wait more than 4.1 milliseconds. C009 CE 05 58 LDX #1368 ; 1368 . iterations = 4.1 ms. C00C BD C1 1A JSR dloop ; Wait that . long after first function set. * Send the 8-bit data length command again. C00F B7 B5 F0 STAA LCD_CTL ; Store 8-bit . command, second time * Wait more than 100 microseconds. C012 CE 00 22 LDX #34 ; 34 . iterations = 100 us. C015 BD C1 1A JSR dloop ; Wait that . long after 2nd function set * Send the 8-bit data length command a third time. C018 B7 B5 F0 STAA LCD_CTL ; Store 8-bit . command, third time. BF now works. ADDR B1 B2 B3 B4 F:\chicken\lcd.asm PAGE 3 * At this point, the LCD's Busy Flag bit should now be . responding properly. * Set the display to have two 40-character lines, with 5x7- . dot characters. LDAA #FUNC_SET|DL_8bit|N_2lines ; Set to 8 . bit data length, 2 virtual 40-char "lines", 5x7 dot font E ^ Unknown identifier. E ^ Unknown identifier. E ^ Unknown identifier. C01B BD C1 02 JSR send_cmd ; Send that . command. * Clear the LCD display contents, return to home position, . unshift display. C01E BD C0 F4 JSR clear_disp ; Clear . display LDAA #RET_HOM E ^ Unknown identifier. C021 BD C1 02 JSR send_cmd * Set the entry mode to increment the cursor position, and . not shift the display. * (Actually this is the default behavior for our LCD anyway.) LDAA #ENT_MOD|ID_INC ; Entry mode: . increment, no shift E ^ Unknown identifier. E ^ Unknown identifier. C024 BD C1 02 JSR send_cmd ; Send that . command. * Turn on the display, turn on the cursor, and turn on cursor . blinking. LDAA #DISP_ONOFF|D_disp|B_blink|C_cursor ; . Turn on display/cursor/blink. E ^ Unknown identifier. E ^ Unknown identifier. E ^ Unknown identifier. E ^ . Unknown identifier. C027 BD C1 02 JSR send_cmd ; . Send that command. * The display is now initialized! C02A 39 RTS ; End of init_LCD . subroutine. *------------------------------------------------------------ . - * Read the present display location (DDRAM address) into . accB. *------------------------------------------------------------ . - read_loc: C02B BD C1 10 JSR wait_LCD ; Wait till the LCD is ready. C02E F6 B5 F0 LDAB LCD_CTL ; Get current cursor location . (DDRAM address) into accB. C031 39 RTS ; Return from read_loc . subroutine. * Map of locations C032 00 01 02 03 locmap: fcb $00,$01,$02,$03,$04,$05,$06,$07,$08,$09,$0a, . C036 04 05 06 07 $0b,$0c,$0d,$0e,$0f,$10,$11,$12,$13 . C03A 08 30 0A 0B ADDR B1 B2 B3 B4 F:\chicken\lcd.asm PAGE 4 . C03E 0C 0D 0E 0F . C042 10 11 12 13 C046 40 41 42 43 fcb $40,$41,$42,$43,$44,$45,$46,$47,$48,$49,$4a, . C04A 44 45 46 47 $4b,$4c,$4d,$4e,$4f,$50,$51,$52,$53 . C04E 48 49 4A 4B . C052 4C 4D 4E 4F . C056 50 51 52 53 C05A 14 15 16 17 fcb $14,$15,$16,$17,$18,$19,$1a,$1b,$1c,$1d,$1e, . C05E 18 19 1A 1B $1f,$20,$21,$22,$23,$24,$25,$26,$27 . C062 1C 1D 1E 1F . C066 20 21 22 23 . C06A 24 25 26 27 C06E 54 55 56 57 fcb $54,$55,$56,$57,$58,$59,$5a,$5b,$5c,$5d,$5e, . C072 58 59 5A 5B $5f,$60,$61,$62,$63,$64,$65,$66,$67 . C076 5C 5D 5E 5F . C07A 60 61 62 63 . C07E 64 65 66 67 * If A,B contain (x,y) coordinates, go to that display . location tmpx: rmb 1 C083 36 gotoxy: psha C084 37 pshb C085 3C pshx * jsr printA * jsr printB C086 B7 C0 82 staa tmpx C089 86 14 ldaa #20 C08B 3D mul C08C FB C0 82 addb tmpx C08F C3 C0 32 addd #locmap C092 8F xgdx C093 E6 00 ldab 0,x * jsr printB C095 BD C0 EB jsr set_loc * jsr OUTCRLF C098 38 pulx C099 33 pulb C09A 32 pula C09B 39 rts *------------------------------------------------------------ . ------------- * Write character in accA to current location on LCD display . screen, and * advance the cursor location appropriately. * This version adjusts for 4x20 keypad row addressing if . you're expecting * continuous rows 1,2,3,4 *------------------------------------------------------------ . ------------- lcd_out: C09C BD C0 2B JSR read_loc ; Read the current LCD cursor . location into accB. * Check to see if we're at the end of one row and we need to . jump to the start of the next. C09F C1 13 CMPB #Row1_end ; Are we at the end of the . 1st row of characters? C0A1 27 1A BEQ lcd_ad1 ; Make adjustment for end of . row 1. C0A3 C1 53 CMPB #Row2_end ; Are we at the end of the . 2nd row of characters? C0A5 27 1A BEQ lcd_ad2 ; Make adjustment for end of ADDR B1 B2 B3 B4 F:\chicken\lcd.asm PAGE 5 . row 2. C0A7 C1 27 CMPB #Row3_end ; Are we at the end of the . 3rd row of characters? C0A9 27 1A BEQ lcd_ad3 ; Make adjustment for end of . row 3. C0AB C1 67 CMPB #Row4_end ; End of 4th row? C0AD 27 1A BEQ lcd_ad4 ; Adjust. * Normal case: Just write the character. C0AF BD C1 09 JSR write_lcd ; Write the character in accA . to the LCD screen. C0B2 39 RTS ; Return from the lcd_out . subroutine * Adjustment cases: Figure out the new location, then write . the character, * then jump to the new location. lcd_ad1: C0B3 C6 40 ldab #Row2_start ; Location $40 = start of 2nd . row. C0B5 20 14 bra lcd_fix ; Continue fix lcd_ad2: C0B7 C6 14 ldab #Row3_start ; Location $14 = start of 3rd . row. C0B9 20 10 bra lcd_fix ; Continue fix lcd_ad3: C0BB C6 54 ldab #Row4_start ; Location $54 = start of 4th . row. C0BD 20 0C bra lcd_fix ; Continue fix lcd_ad4: C0BF C6 00 ldab #Row1_start ; Location $00 = start of 1st . row. lcd_fix: C0C1 BD C1 09 JSR write_lcd ; Write the character in accA . to the LCD screen. C0C4 BD C0 EB JSR set_loc ; Set the new LCD screen . location (DDRAM address) to accB. C0C7 39 RTS ; Return from the lcd_out . subroutine. ENDSTR equ $ff ; Use non-ASCII byte code $FF . to denote end of string * Print ENDSTR-terminated string pointed to by X C0C8 36 lcdstr: psha C0C9 3C pshx C0CA A6 00 lstrl: ldaa 0,x * jsr printA C0CC 81 FF cmpa #ENDSTR C0CE 27 18 beq nomore C0D0 3C pshx C0D1 BD C0 9C jsr lcd_out C0D4 CE 03 E8 ldx #1000 C0D7 BD C1 1A jsr dloop C0DA 38 pulx C0DB 08 inx C0DC 20 EC bra lstrl nomore: * jsr OUTCRLF C0DE 38 pulx C0DF 32 pula ADDR B1 B2 B3 B4 F:\chicken\lcd.asm PAGE 6 C0E0 39 rts *------------------------------------------------------ * Set the LCD Display Data RAM (DDRAM) address to accB. *------------------------------------------------------ set_loc: C0E1 36 PSHA ; Preserve accA. C0E2 17 TBA ; Copy address from B to A. ORAA #DDRAM_addrset ; Turn it into a "DDRAM . address set" command. E ^ Unknown identifier. C0E3 BD C1 02 JSR send_cmd ; Send that command to the . LCD. C0E6 32 PULA ; Restore accA. C0E7 39 RTS ; Return from the set_loc . subroutine. *-------------------------------------------------- * Clear the LCD display contents. *-------------------------------------------------- C0E8 36 clear_disp: PSHA LDAA #CLR_HOM ; Load the clear- . display-and-home command E ^ Unknown identifier. C0E9 BD C1 02 JSR send_cmd ; Send it to the LCD C0EC 32 PULA *------------------------------------------------------------ . -- * Shift the LCD display contents to the left. *------------------------------------------------------------ . -- C0ED 36 shift_left: PSHA LDAA #CD_shift|SC_shift ; Display . shift to the left E ^ Unknown identifier. E ^ Unknown identifier. C0EE BD C1 02 JSR send_cmd C0F1 32 PULA *------------------------------------------------------------ . ------ * Send the LCD command (instruction) in accA to the LCD. *------------------------------------------------------------ . ------ C0F2 BD C1 10 send_cmd: JSR wait_LCD ; Wait until the LCD . is ready. C0F5 B7 B5 F0 STAA LCD_CTL ; Store the . instruction at the LCD control register. C0F8 39 RTS ; Return from send_ . cmd subroutine. *------------------------------------------------------------ . ----- * Write the character whose code is in accA to the LCD. *------------------------------------------------------------ . ----- C0F9 BD C1 10 write_lcd: JSR wait_LCD ; Wait until the LCD . is ready. C0FC B7 B5 F1 STAA LCD_DAT ; Store the character . at the LCD data address. C0FF 39 RTS ; Return from the . write_lcd subroutine. *--------------------------------------------------------- ADDR B1 B2 B3 B4 F:\chicken\lcd.asm PAGE 7 * Wait for the LCD to finish processing the last command. * Use this before sending a new command or data value. *---------------------------------------------------------- C100 3C wait_LCD: PSHX C101 CE B5 F0 LDX #LCD_CTL ; Let X point . to the LCD control register. wait_loop: BRSET 0,X BF wait_loop ; Wait for BF . bit of LCD control register to be 0. E ^ Unknown identifier. C104 38 PULX C105 39 RTS ; Return from . wait_LCD subroutine. *----------------------------------------------------------- * Delay for 6*X clock cycles (3*X microseconds). Stomps X. *----------------------------------------------------------- C106 09 dloop: DEX ; Decrement X (3 . cycles) C107 26 FD BNE dloop ; Repeat if not 0 (3 . cycles) C109 39 RTS ; Return from dloop . subroutine. *----------------------------------------------- * Store the eight glyphs in glyph_table in the CGRAM. * Stomps A,B,X,Y *----------------------------------------------- store_glyphs: C10A 4F CLRA ; Clear accA (select . character #0). LDX #glyph_table ; X will point to the table . of glyph pointers. E ^ Unknown identifier. C10B 1A EE 00 nextgl: LDY 0,X ; Load Y with pointer to next . glyph. C10E 36 PSHA ; Preserve A. C10F 3C PSHX ; Preserve X. C110 BD C1 34 JSR store_glyph ; Store the glyph at the . selected CGRAM location. C113 38 PULX ; Restore X. C114 32 PULA ; Restore A. C115 4C INCA ; Go to the next CGRAM . location. C116 08 INX ; Go to the next entry in the . table of glyph pointers. C117 08 INX ; . C118 81 08 CMPA #8 ; Did we fill all 8 . characters yet? C11A 25 EF BLO nextgl ; If not, do the next one. C11C 39 RTS ; Return from store_glyphs . subroutine. *------------------------------------------------------------ . -------- * Store the 8-byte graphic pointed to by Y as character code . A (0-7). * Stomps A,B,X *------------------------------------------------------------ . --------- store_glyph: C11D BD C0 2B JSR read_loc ; Read current cursor loc . into accB. C120 48 LSLA ; Shift A's value over into . bits 3-5. C121 48 LSLA ADDR B1 B2 B3 B4 F:\chicken\lcd.asm PAGE 8 C122 48 LSLA ORAA #CGRAM_addrset ; Turn A into command "set . CGRAM address to first row of that character" E ^ Unknown identifier. C123 BD C0 F2 JSR send_cmd ; Send that command to the . LCD. C126 37 PSHB ; Preserve present value of B . (cursor loc). C127 C6 08 LDAB #8 ; Load B with row count: 8. C129 18 A6 00 nextrow: LDAA 0,Y ; Load next row of font . graphics. C12C BD C0 F9 JSR write_lcd ; Write it to the LCD. C12F 18 08 INY ; Increment graphics data . pointer. C131 5A DECB ; Decrement number of rows . left to process. C132 26 F5 BNE nextrow ; Continue if there are rows . left. C134 33 PULB ; Restore the old value of B . (DDRAM address). C135 BD C0 E1 JSR set_loc ; Go back into DDRAM-writing . mode. C138 39 RTS ; Return from store_glyph . subroutine. *------------------------------------------------- * Show all 8 glyphs in the CGRAM on the display. *------------------------------------------------- show_glyphs: C139 4F CLRA ; For A=0 to 7 C13A BD C0 9C printit: JSR lcd_out ; Output character A to . the LCD C13D 4C INCA ; Next A (A=A+1) C13E 81 07 CMPA #7 ; . (Compare A . with 7) C140 23 F8 BLS printit ; . (If lower or . same, repeat) C142 39 RTS ; Return from show_glyphs . subrotuine. Symbol Table SEND_CMD C0F2 STORE_GLYPH C11D ENDSTR 00FF ROW4_END 0067 TMPX C082 ROW1_START 0000 WRITE_LCD C0F9 NOMORE C0DE ROW3_END 0027 ROW_LENGTH 0014 DLOOP C106 LSTRL C0CA WAIT_LCD C100 LCD_OUT C09C SHOW_GLYPHS C139 STORE_GLYPHS C10A NEXTGL C10B NEXTROW C129 LCD_CTL B5F0 INIT_LCD C000 ROW2_END 0053 LCD_BASE B5F0 SHIFT_LEFT C0ED Symbol Table F:\chicken\lcd.asm PAGE 9 ROW1_END 0013 ROW4_START 0054 LCD_DAT B5F1 LOCMAP C032 LCD_FIX C0C1 LCD_AD1 C0B3 LCD_AD2 C0B7 LCD_AD3 C0BB LCD_AD4 C0BF ROW3_START 0014 SET_LOC C0E1 LCDSTR C0C8 GOTOXY C083 PRINTIT C13A CLEAR_DISP C0E8 ROW2_START 0040 READ_LOC C02B