.equ locat, 0xF100 ;Location for this program ; LCD memory mapped locations: ;.equ lcd_command_wr, 0xFF80 ;.equ lcd_status_rd, 0xFF81 ;.equ lcd_data_wr, 0xFF82 ;.equ lcd_data_rd, 0xFF83 .equ lcd_command_wr, 0xFE00 .equ lcd_status_rd, 0xFE01 .equ lcd_data_wr, 0xFE02 .equ lcd_data_rd, 0xFE03 .equ esc, 0x003E ;paulmon2's check for esc key .org locat .db 0xA5,0xE5,0xE0,0xA5 ;signiture bytes .db 35,255,0,0 ;id (35=prog) .db 0,0,0,0 ;prompt code vector .db 0,0,0,0 ;reserved .db 0,0,0,0 ;reserved .db 0,0,0,0 ;reserved .db 0,0,0,0 ;user defined .db 255,255,255,255 ;length and checksum (255=unused) .db "LCD Test",0 ;max 31 characters, plus the zero .org locat+64 ;executable code begins here startup: .equ cout, 0x0030 .equ cin, 0x0032 .equ phex, 0x0034 .equ phex16, 0x0036 .equ pstr, 0x0038 .equ newline, 0x0048 .equ lcd_clear_cmd, 0x01 ;clears display .equ lcd_home_cmd, 0x02 ;put cursor at home position .equ lcd_on_cmd, 0x0C ;turn on display (cursor off) .equ lcd_left_move_cmd, 0x10 .equ lcd_right_move_cmd, 0x14 .equ lcd_left_shift_cmd, 0x18 .equ lcd_right_shift_cmd, 0x1C .equ lcd_config_cmd, 0x38 ;configure, 8 bit interface, 2 lines, 5x7 digits .equ lcd_horiz_size, 16 .equ lcd_vert_size, 2 .equ lcd_bytes_per_line, 80 / lcd_vert_size begin: mov dptr, #mesg_start lcall pstr main_loop: lcd_init: lcall lcd_busy mov dptr, #lcd_command_wr mov a, #lcd_config_cmd movx @dptr, a lcall lcd_busy mov dptr, #lcd_command_wr mov a, #lcd_clear_cmd movx @dptr, a lcall lcd_busy mov dptr, #lcd_command_wr mov a, #lcd_on_cmd movx @dptr, a lcall lcd_busy mov dptr, #lcd_command_wr mov a, #lcd_left_shift_cmd movx @dptr, a lcall lcd_busy mov dptr, #lcd_command_wr mov a, #0x81 movx @dptr, a mov r0, #0 mov r1, #0 acall lcd_set_xy mov dptr, #mesg1 acall lcd_pstr mov r0, #0 mov r1, #1 acall lcd_set_xy mov dptr, #mesg2 acall lcd_pstr lcall cin add a, #256 - 27 jz quit mov r0, #0 mov r1, #0 acall lcd_set_xy mov dptr, #mesg3 acall lcd_pstr mov r0, #0 mov r1, #1 acall lcd_set_xy mov dptr, #mesg4 acall lcd_pstr lcall cin add a, #256 - 27 jnz main_loop quit: ljmp 0 mesg_start: .db "LCD Test Program... press a key to toggle",13,10 .db "between two messages, or ESC to exit",13,10,13,10,0 mesg1: .db "LCD 2x16 Display",0 mesg2: .db "y* www.pjrc.com *",0 mesg3: .db 255,255,255,255,255,255,255,255 .db 255,255,255,255,255,255,255,255,0 mesg4: .db 255,255,255,255,255,255,255,255,255 .db 255,255,255,255,255,255,255,255,0 lcd_pstr: clr a movc a, @a+dptr inc dptr jz lcd_pstr_end push dpl push dph acall lcd_cout pop dph pop dpl sjmp lcd_pstr lcd_pstr_end: ret lcd_cout: push acc acall lcd_busy mov dptr, #lcd_data_wr pop acc movx @dptr, a ret lcd_busy: mov dptr, #lcd_status_rd movx a, @dptr jb acc.7, lcd_busy ret ;R0 = X position (0 to 15), R1 = Y position (0 to 1) lcd_set_xy: ;check X is within display size mov a, r0 add a, #256 - lcd_horiz_size jnc lcd_set_xok mov r0, #lcd_horiz_size - 1 lcd_set_xok: ;check Y is within display size mov a, r1 add a, #256 - lcd_vert_size jnc lcd_set_yok mov r1, #lcd_vert_size - 1 lcd_set_yok: acall lcd_busy ;compute address within data display ram in LCD controller chip mov a, r1 mov b, #lcd_bytes_per_line mul ab add a, r0 inc a orl a, #0x80 ;msb set for set DD RAM address mov dptr, #lcd_command_wr movx @dptr, a ret