??? 05/14/07 22:17 Read: times |
#139249 - ReceiveString, rev.1 Responding to: ???'s previous message |
;------------------------------------------------------------------------------
; ReceiveString I modified slightly the specs. Comments? JW ;------------------------------------------------------------------------------ ; DESCRIPTION: This subroutine is called from many places to receive a line of ; input from a human user via a terminal connected to the onboard ; UART. Each line of input starts with the first character ; entered after this subroutine is called, and ends with a ; carriage return. ; ; This subroutine accumulates the data in a buffer called ; 'RxBuffer', which is located in the internal data RAM and is ; accessed only via indirect addressing (i.e. can be located ; in the upper 128 bytes). ; The symbol RX_BUFFER_SIZE gives the size of the buffer, ; in bytes. Note, that to be able to store the trailing zero, ; the actual number of characters received is maximum ; RX_BUFFER_SIZE-1. ; ; On entry, this function does minor internal housekeeping to ; prepare for a new line of input (i.e. resets the pointer :-) ; It then receives characters one by one from the user. ; It handles each received character as follows: ; ; - Backspace (08h): If the buffer is not empty, removes the ; newest character from the buffer and echoes the ; three-character sequence 08h 20h 08h (backspace space ; backspace) to the terminal to erase the most recently typed ; character from the user's screen. If the buffer is empty ; when the backspace character is received, echoes a single ; 07h (beep) to the terminal. ; ; - Carriage Return (0Dh): Appends zero character to the buffer ; to mark the end of the line and returns to the caller with ; the accumulator set to NO_ERROR. ; ; - Printable characters (20h through 7Eh, inclusive): If the ; buffer is full, echoes a single 07h (beep) to the terminal. ; Otherwise appends the character to the buffer. ; ; - All other characters: Does nothing. ; ; As noted above, this function returns when it receives a ; carriage return. Nothing specific is returned in registers. ; ; The function won't guarantee to keep the value of registers ; (this is the standard behaviour of C routines both in Keil ; and SDCC), although resources usage will be determined and ; noted below. ; ; A test program is written to try the routine, which is not ; part of the routine. Test with Hyperterminal or equivalent, ; 9600 baud, 8N1, no handshake, auto terminal mode. ; Should beep when 10th character is attempted to be entered. ; Deleting should "eat" characters until the last one, after ; it deleting should beep. After enter, should write ; number of characters and the string again. ; ; ; ; ; REVISIONS: 13 May 07 - RAC - Initial specification ; 13 May 07 - JW - modified specification & initial implementation ; ----------------------------------------------------------------------------- ;---- TEST main RxBuffer EQU 30h RX_BUFFER_SIZE EQU 10 CSEG AT 0 ; assumes X=18.432MHz and baud=9600 ;-- init first mov SCON,#52h ;set serial mode 1 ORL PCON,#80h mov TMOD,#21h ;timer0 16-bit, timer1 autoreload mov TH1,#-10 ;0FAh ;9600 setb tr1 ;enable timer 1 Loop: ;-- call the ReceiveString itself call ReceiveString ;-- print a CRLF call TxCRLF ;-- then print the string length (i.e. exit value of R0 minus the base) mov a,r0 clr c subb a,#RxBuffer call TxHexa call TxCRLF ;-- finally print the string itself mov r0,#RxBuffer Loop1: mov a,@r0 jz Loop2 call TxChar inc r0 sjmp Loop1 Loop2: ;-- print a CRLF call TxCRLF ;-- and loop infinitely sjmp Loop ;-- some print utilities TxCRLF: mov a,#13 call TxChar mov a,#10 call TxChar ret TxHexa: push acc swap a anl a,#0Fh add a,#TxHexaT-TxHexaX1 movc a,@a+pc TxHexaX1: call TxChar pop acc anl a,#0Fh add a,#TxHexaT-TxHexaX2 movc a,@a+pc TxHexaX2: ;fallover TxChar: jnb ti,$ clr ti mov sbuf,a ret TxHexaT: db '0123456789ABCDEF' ;---- end of TEST ; ;-- uses and destroys r0 and acc only ; no stack, no external memory, no interrupts disable ; ReceiveString: mov r0,#RxBuffer ;initialize receiver pointer jb ti,LoopReceive ;security measure - if somebody forgets to set ti setb ti ; this prevents deadlock later in sending char LoopReceive: jnb ri,$ ;wait until character received clr ri mov a,SBUF ;get the received character jb acc.7,LoopReceive ;if unprintable (>= 80h), ignore it cjne a,#20h,$+3 jc ControlChars ;if control char (<20h), separate processing cjne r0,#RxBuffer+RX_BUFFER_SIZE-1,StoreChar EchoBeep: ;this would overflow - beep mov a,#07h sjmp SendChar StoreChar: ;printable character: mov @r0,a ;put it into buffer inc r0 ;bump pointer SendChar: jnb ti,$ clr ti mov SBUF,a sjmp LoopReceive ;and continue receiving ControlChars: cjne a,#08h,NotBackSpace cjne r0,#RxBuffer,EatCharacter ;if BackSpace, eat last character sjmp EchoBeep ;if empty buffer, just beep EatCharacter: jnb ti,$ ;do what is needed to eat a character clr ti ;on the terminal mov SBUF,#08h jnb ti,$ clr ti mov SBUF,#' ' jnb ti,$ clr ti mov SBUF,#08h dec r0 ;and do the pointer decrement itself sjmp LoopReceive NotBackSpace: cjne a,#0Dh,LoopReceive ;if not Carriage Return, receive more characters mov @r0,#0 ;put endmark ret end |