.equ locat, 0xF100 ;Location for this program ; Constants to define the display size. These are needed by the lcd_set_xy ; routine to turn X-Y coordinates into addresses within the display's ; buffer. These settings work with the 16x2 display available from ; PJRC.COM, at: http://www.pjrc.com/store/dev_display_16x2.html .equ lcd_horiz_size, 16 .equ lcd_vert_size, 2 .equ lcd_bytes_per_line, (128 / lcd_vert_size) ; Misc constants to define commands give to the display. .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_shift_cmd, 0x10 .equ lcd_config_cmd, 0x38 ;config 8 bit, 2 lines, 5x7 ; Memory mapped locations to accessing the LCD. .equ lcd_command_wr, 0xFE00 .equ lcd_status_rd, 0xFE01 .equ lcd_data_wr, 0xFE02 .equ lcd_data_rd, 0xFE03 ; Serial I/O in PAULMON2 .equ cout, 0x0030 .equ cin, 0x0032 .equ phex, 0x0034 .equ phex16, 0x0036 .equ pstr, 0x0038 .equ newline, 0x0048 .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 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: acall lcd_init acall lcd_clear mov r2, #0 mov r3, #0 acall lcd_set_xy mov dptr, #mesg1 acall lcd_pstr mov r2, #0 mov r3, #1 acall lcd_set_xy mov dptr, #mesg2 acall lcd_pstr lcall cin add a, #256 - 27 jz quit mov r2, #0 mov r3, #0 acall lcd_set_xy mov dptr, #mesg3 acall lcd_pstr mov r2, #0 mov r3, #1 acall lcd_set_xy mov dptr, #mesg3 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 "* 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 ; .db 255,255,255,255,255,255,255,255,0 ;---------------------------------------------------------------- ; General purpose routines for accessing the LCD ;---------------------------------------------------------------- ; Print a single character in Acc to the display. lcd_cout: push dpl push dph push acc acall lcd_busy mov dptr, #lcd_data_wr pop acc movx @dptr, a pop dph pop dpl ret ; Print a string @DPTR to the display. lcd_pstr: clr a movc a, @a+dptr inc dptr jz lcd_pstr_end acall lcd_cout sjmp lcd_pstr lcd_pstr_end: ret ; Wait for the display to be ready for a command or data. lcd_busy: mov dptr, #lcd_status_rd lcd_busy_wait: movx a, @dptr jb acc.7, lcd_busy_wait ret ; Set the display's cursor position. ; R2 = X position (0 to 15), R3 = Y position (0 to 1) lcd_set_xy: ;check X is within display size mov a, r2 add a, #256 - lcd_horiz_size jnc lcd_set_xok mov r2, #lcd_horiz_size - 1 lcd_set_xok: ;check Y is within display size mov a, r3 add a, #256 - lcd_vert_size jnc lcd_set_yok mov r3, #lcd_vert_size - 1 lcd_set_yok: acall lcd_busy ;compute address within data display ram in LCD controller chip mov a, r3 mov b, #lcd_bytes_per_line mul ab add a, r2 orl a, #0x80 ;msb set for set DD RAM address mov dptr, #lcd_command_wr movx @dptr, a ret ; Initialize the display for use. 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_on_cmd movx @dptr, a lcall lcd_busy mov dptr, #lcd_command_wr mov a, #lcd_shift_cmd movx @dptr, a ret ; Clear the screen. lcd_clear: lcall lcd_busy mov dptr, #lcd_command_wr mov a, #lcd_clear_cmd movx @dptr, a ret ; Return the cursor to the home position. lcd_home: lcall lcd_busy mov dptr, #lcd_command_wr mov a, #lcd_home_cmd movx @dptr, a ret