
;This is an example of interrupt-driven serial reception
;The interrupt receives a byte, places it into the buffer (if there is space in it)
;DEL is not implemented here - non-printable characters are simply all discarded
;  except ENTER (CR), which terminates the reception, sets RxDoneFlag 
;  and sets the number of received characters into the first byte of buffer (Pascal-style)
;Received characters are echoed immediately, therefore the transmission
;  interrupt is ignored.

RxDoneFlag  EQU   20h.0

RxBuff   EQU   30h   ;this is the receiver buffer
RxSize   EQU   16    ;we will accept max. 16 characters

         ORG   0
         ljmp  Reset

         ORG   23h
         ljmp  ISR_UART

Reset:                        ;after reset, start here
         lcall Init_UART      ;initialize UART
         setb  es             ;enable serial interrupt

         setb  ea             ;enable interrupts globally
Main:
         lcall RxString       
         ;some processing here
         sjmp  Main


RxString:                     ;the string receiver routine
         clr   RxDoneFlag     ;basically everything is left to the interrupt
         jnb   RxDoneFlag,$   ;   which sets RxDoneFlag when done
         ret

Init_UART:                   ;initialize UART
          mov   SCON,#50h    ;set serial mode 1
          mov   TMOD,#22h    ;both timers autoreload
          mov   TH1,#-13     ;2400@12MHz
          setb  tr1          ;start timer 1
          ret

ISR_UART:                    ;UART interrupt
          push  psw          ;store registers
          push  acc
          setb  RS0          ;and switch to register bank 1

          jnb   ri,ISR_UART_TI   ;if no RI flag set, bypass the RI part
          clr   ri               ;if RI set, we need to clear it manually
          mov   a,SBUF           ;pick the received byte
          cjne  a,#13,ISR_UART_RxNotCR
          setb  RxDoneFlag       ;if CR, set the done flag
          mov   a,#RxBuff        ;  and calculate length
          clr   c
          xch   a,r0
          subb  a,r0
          mov   @r0,a            ;  store it at beginning of buffer
          sjmp  ISR_UART_Echo    ;  and leave, echoing back the CR
ISR_UART_RxNotCR:
          jb    acc.7,ISR_UART_TI   ;ignore >80h
          cjne  a,#20h,$+3
          jc    ISR_UART_TI         ;ignore <20h
          cjne  r0,#RxBuff+RxSize,ISR_UART_Store
          sjmp  ISR_UART_TI         ;ignore if buffer full
ISR_UART_Store:
          inc   r0                  ;next position in buffer
          mov   @r0,a               ;store the character
ISR_UART_Echo:
          mov   SBUF,a              ;echo back the character
                            ;and we are finished with Rx - fallthrough to Tx
ISR_UART_TI:
          jnb   ti,ISR_UART_END  ;check and clear TI flag
          clr   ti
                                 ;we have no more Tx processing here
ISR_UART_END:
          pop   acc          ;restore registers
          pop   psw
          reti

          end

