;********************************************************************** ;* 8052.com Single Board Computer -- SBCMON Demonstration Program * ;* ---> LCD ECHO DEMONSTRATION PROGRAM <--- * ;* For 8052.com SBC, hardware rev 1.3 * ;*--------------------------------------------------------------------* ;* This program is offered as-is with no warranty or guarantee of any * ;* kind. Its purpose is to serve as an educational aid in mastering * ;* the topics and concepts covered by the program. You are free to * ;* use this code for any purpose you see fit--including commercial-- * ;* but the exclusive responsibility for its use is the user of this * ;* code. This code is offered completely free of charge and VIS' and * ;* 8052.com's liability will be limited to the amount paid: zero. * ;*--------------------------------------------------------------------* ;* This program was coded to be compatible with the Pinnacle 52 IDE. * ;* Pinnacle 52 is available at http://www.vaultbbs.com/pinnacle. The * ;* program may require minor modifications in order to assemble with * ;* other assemblers. * ;*--------------------------------------------------------------------* ;* NOTE: This program was designed to be loaded into SBCMON's XRAM * ;* and executed as an SBCMON external program. It depends on one or * ;* more SBCMON library routines and, as such, will not work without * ;* SBCMON. This program is not intended to be loaded via in-system * ;* programming, only loaded within SBCMON. Should you wish to load * ;* this program via ISP as a stand-alone program, the SBCMON library * ;* entry point equates should be removed and the respective routines * ;* should be copied from SBCMON into this program. The source code * ;* for SBCMON may be found at http://www.8052.com/sbc/sbcmon. * ;*====================================================================* ;* Filename: LCDECHO.ASM * ;* Description: This program will take input from the PC terminal and * ;* echo it to the LCD. The LCD should be first configured with the * ;* SBCMON 'M' command. The program first clears the screen and then* ;* allows input from the PC terminal (serial port). All input is * ;* echoed to the LCD. * ;* * ;* SCROLLING: If the user types past the end of line 1, subsequent * ;* input will continue at the beginning of line 2. If * ;* the user types past the end of line 2, the screen * ;* will be scolled and typing will continue at the * ;* beginning of line 2. The scroll is accomplished by * ;* reading the contents of line 2, copying it to line 1, * ;* writing 16 spaces to line 2, and then positioning the * ;* cursor at the beginning of line 2. * ;* * ;* CARRIAGE RETURN: The user may press enter. If on line 1, a CR * ;* will put the cursor at the beginning of line 2. If * ;* on line 2 then a CR will cause a scroll (see above). * ;* * ;* BACKSPACE: Backspace is implemented by obtaining the current * ;* cursor position from the LCD, decrementing by one (to * ;* point to the previous character position), writing * ;* out a space to that position to erase any character * ;* at that position, and finally repositioning the * ;* cursor at that same position so the next input will * ;* be echoed at the character position that was just * ;* erased. If the cursor was already at the upper left * ;* corner of the LCD then the backspace is ignored. If * ;* the cursor was at the beginning of line 2 then the * ;* current cursor position is assumed to be 10h rather * ;* than 40h so that the backspace will end up acting on * ;* the last visible character of line 1). * ;********************************************************************** ;========================================================== ; SBCMON LIBRARY ROUTINE ENTRY POINT EQUATES ; ;If you wish to make this a stand-alone program, remove ;these equates and copy the source code for the named ;routines from the SBCMON source code. SBCMON source code ;may be found at http://www.8052.com/sbc/sbcmon. ;=========================================================== SendSerial EQU 0041h SendLCDCommand EQU 0053h SendLCDText EQU 0050h ReadLCDStatus EQU 008Fh ReadLCDText EQU 0092h InitializeLCD EQU 008Ch ;========================================================== ; PROGRAM LOCATION ; ;The program is located at 2000h since this is where the ;8052.com SBC's XRAM/code memory is in the memory map. ;Programs loaded into this RAM area can be accessed as both ;data and executed as a program. If you are going to make ;this a stand-alone program the following ORG should be ;modified to 0000h rather than 2000h. ;=========================================================== ORG 8000h ;========================================================== ; PROGRAM CODE ; ;This is the actual guts of the demonstration code. ;=========================================================== LCALL InitializeLCD ;Make sure the LCD is initialized MOV A,#01h ;Clear LCD screen LCALL SendLCDCommand ;Send clear screen command ;The screen is now clear and cursor is in upper left hand ;corner. We send a welcome message to the serial port/ ;PC terminal program. LCALL SendSerial DB "Anything you type will be echoed to the LCD",13 DB "Press ESC to exit, CR for next line, CTRL-L for clear screen", 13,0 CLR RI ;Clear RI initially EchoLoop: JNB RI,$ ;Wait for a key to be pressed on PC terminal MOV A,SBUF ;Get the key that the user typed on the PC CLR RI ;Clear the RI bit so we're ready to receive another ;We now have the user keypress in the accumulator. We need to see if ;key that they pressed were any of the special characters (ESCAPE to ;exit the program, CR to go to the next line, backspace to back up a ;character, and CTRL-L to clear the screen). If the key wasn't any of ;the special characters then it is echoed to the LCD as a normal ;character. CJNE A,#27,NotEscape ;Not an escape so keep checking RET ;ESCAPe means exit, so return to SBCMON NotEscape: CJNE A,#13,NotCR ;If it's not a carriage reutrn, keep checking ;If we get here then it means the user pressed a CR ;key. If we're on line 1 then we just go to line 2. ;If we're on line 2 then we need to scroll. LCALL ReadLCDStatus ;Get the current cursor position CJNE A,#10h,$+3 ;Is it less than 10h? I.e. is it line 1? JNC ScrollLine2 ;We're on line 2, so go to code that scrolls ;If we got here then we got a CR while on line 1, so just ;go to the beginning of line 2. MOV A,#0C0h ;Set cursor position to line 2 char 1 LCALL SendLCDCommand ;Execute cursor positioning command SJMP EchoLoop ;Wait for next character NotCR: CJNE A,#08h,NotBS ;If it's not a backspace, keep checking ;If we got here then it means we got a backsapce character. ;So we need to read our current cursor position. If it's ;at 00h (upper left hand corner of LCD) then we ignore it ;bceause we can't backspace beyond that. Further, if it's ;40h (first character of line 2) then we modify the cursor ;position as if it were 10h (one character beyond the end ;of line 1). LCALL ReadLCDStatus ;Get current cursor position CJNE A,#00h,NotBSHome ;If it's not upper-left corner, process it SJMP EchoLoop ;We're already at upper-left corner so ;we ignore backspace by waiting for next ;character. NotBSHome: ;If we get here then it means the cursor is not in the upper ;left-hand corner. But we have to check for the remaining ;special condition: We need to check to see if we're at the ;beginning of line 2 (cursor position 40h) and, if we are, ;set the address to one beyond the end of line 1 (11h). CJNE A,#40h,NormalBS ;If we're not at line 2 char 1, process normally ;This means we're at beginning of line 2, so set cursor ;position to 10h which is as if it were one character ;past the end of line 1. MOV A,#10h ;Set to end of line 1, plus one character NormalBS: DEC A ;Decrement cursor position SETB ACC.7 ;Set high bit for set cursor position command MOV R1,A ;Save it temporarily in R1 LCALL SendLCDCommand ;Set the new cursor position MOV A,#' ' ;Going to send a space to erase that character LCALL SendLCDText ;Send the space to blank out character MOV A,R1 ;Restore the new cursor position LCALL SendLCDCommand ;Set cursor position to new position SJMP EchoLoop ;Wait for next character NotBS: CJNE A,#12,NotCLS ;If it's not CTRL-L (clear screen), keep checking ;If we get here it means the user typed CTRL-L which ;needs to clear the screen. We do this buy sending ;the LCD clear screen command and then waiting for the ;next character. MOV A,#01h ;This is the LCD clear screen command code LCALL SendLCDCommand ;Send the clear screen command to the LCD SJMP EchoLoop ;Wait for the next character NotCLS: ;If we get here then that means the key that was typed by the ;user was not one of the special characters. So we assume it ;is text that should be displayed on the LCD. So we just send ;the accumulator to the LCD as a text character. LCALL SendLCDText ;Display on LCD ;Having written the character to the LCD we need to check the ;new cursor position. If it has gone off the visible portion ;of line 1 then we need to set it to the first character position ;of line 2. If it has gone off the visible portion of line 2 ;then we need to scroll line 2 to line 1 and set the cursor ;position to the beginning of line 2. LCALL ReadLCDStatus ;Get current cursor position CJNE A,#10h,NotEOL1 ;If we aren't at the end of line 1, keep checking ;This means the cursor just moved off the visible area of line 1. ;So we set the cursor position to the first character of line 2. MOV A,#040h + 80h ;Set cursor position to 40h (first char line 2) LCALL SendLCDCommand ;Send the cursor positiong command SJMP EchoLoop ;Wait for next character NotEOL1: ;We now check to see if we've just went past the visible area ;of line 2. If the cursor is at character position 50h then ;we know we just went off the end of line 2. If not then the ;cursor hasn't "wrapped" so we don't need to handle any end of ;line scrolling and rather just wait for the next character. CJNE A,#50h,NotEOL2 ;Have we just passed the end of line 2? ScrollLine2: ;We went off the end of line2 so what needs to happen is a scroll. ;A scroll consists of moving the conents of line 2 to line 1, ;blanking out line 2, and setting the cursor position to the first ;character of line 2. MOV R1,#40h + 80h ;This is the first character position of line 2 MOV R2,#00h + 80h ;This is the first character position of line 1 ReadLCDLoop: MOV A,R1 ;Get the current read position LCALL SendLCDCommand ;Set cursor to read position on line 2 LCALL ReadLCDText ;Read the contents of the character from line 2 PUSH ACC ;Save it on the stack, we'll need it later MOV A,R1 ;Get the read position on line 2 again LCALL SendLCDCommand ;Set cursor to the position we just read on line 2 MOV A,#' ' ;Space character in order to blank out line 2 LCALL SendLCDText ;Write it out, blanking out character just read on line 2 MOV A,R2 ;Get current write position on line 1 LCALL SendLCDCommand ;Set cursor position to line 1 write position POP ACC ;Restore the value we had read from line 2 LCALL SendLCDText ;Write the character out to line 1 INC R1 ;Increment next character read position INC R2 ;Increment next character write position CJNE R1,#0D0h,ReadLCDLoop ;Repeat the process until the read position is at end of line 2 ;We've now copied all of line 2 to line 1 and also have ;blanked out line 2 completely. Now all that's left ;to do is to position the cursor at the beginning of ;line 2. MOV A,#40h + 80h ;Set cursor position to 40h (first char line 2) LCALL SendLCDCommand ;Send the cursor positioning command NotEOL2: LJMP EchoLoop ;Wait for next character