removed debug messages that are sent before spbrg set to correct value
since 1827 has more resources have increased buffer size, u may not need pacing any longer to compensate for
the 4 bit lcd interface being a bit slower

baud rate is only shown on lcd at boot , setting is stored in eeprom


Code:
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' 
' Name  : 16F1827 LCD BACKPACK                                                *
' Date  : oct 2025    richard                                                 *
' Note  : RING BUFFERED                                                       *
' Notes : DEFA BAUD RATE 9600 Intrc_OSC 8Mhz                                  *
'         eeprom full case is unhandled,factory reset would be advisable      *
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
#CONFIG
  __config  _CONFIG1, _FOSC_INTOSC & _WDTE_ON & _PWRTE_OFF & _MCLRE_ON & _CP_OFF & _CPD_OFF & _BOREN_ON & _CLKOUTEN_OFF & _IESO_ON & _FCMEN_ON
  __config  _CONFIG2, _WRT_OFF & _PLLEN_OFF & _STVREN_ON & _BORV_19 & _LVP_OFF
#ENDCONFIG


;commands eg   SEROUT2 lcd,84,[255,11]  set baudrate from 9600 to 19200
'255 0/8  backlight 
'255 10/11/12  baud rate  9600/19200/38400
'255 "F"  factory reset
;TX PORTB.2  RX PORTB.1 BACKLIGHT PORTB.0
    DEFINE OSC 8  
    DEFINE INTHAND myint 
    DEFINE WRITE_INT 1
    ANSELA = 0           ' Set all pins digital
    ANSELB = 0          ' Set all pins digital
'    OPTION_REG.7 = 0    ' PORTA/PORTB pull-ups are enabled by individual port latch values
    
    CLEAR
    DEFINE LCD_BITS 4 	'defines the number of data interface lines (4 or 8) 
    DEFINE LCD_DREG PORTA	'defines the port where data lines are connected to
    DEFINE LCD_DBIT 0
    DEFINE LCD_RSREG PORTB	'defines the port where RS line is connected to
    DEFINE LCD_RSBIT 6 	'defines the pin where RS line is connected to 
    DEFINE LCD_EREG PORTB 	'defines the port where E line is connected to 
    DEFINE LCD_EBIT 4 	'defines the pin where E line is connected 
    DEFINE LCD_COMMANDUS 1500 	'defines the delay after LCDOUT statement 
    DEFINE LCD_DATAUS 50 		'delay in micro seconds






    RCSTA = $90   ' Enable serial port & continuous receive
    TXSTA = $20   ' Enable transmit, BRGH = 0
    SP1BRG = 51    ' 19200 Baud @ 8MHz, 0.16%, 51 ' 9600 Baud @ 8MHz, 0.16%, 12 ' 38400 Baud @ 8MHz, 0.16%
    SP1BRGH = 0
    BAUDCON.3 = 1 ' Enable 16 bit baudrate generator
    buffer_size      CON 64                ' Sets the size of the ring buffer
    index_in         VAR BYTE bank0         ' Pointer - next empty location in buffer
    index_out        VAR BYTE bank0         ' Pointer - location of oldest character in buffer
    errflag          VAR BYTE bank0         ' Error flag
    UartFlag         VAR errflag.0
    BufferFlag       VAR errflag.1
    buffer           VAR BYTE[buffer_size] ' Array variable for holding received characters 
    bufchar          VAR BYTE              ' Stores the character retrieved from the buffer
    Bl               var byte 
    inx              var byte
    Br               var byte 
GOTO overint ' Jump over the interrupt handler 
ASM
myint
; Check for hardware overrun error
   banksel RCSTA
   btfsc   RCSTA,OERR   ; Check for usart overrun
   goto    usart_err    ; jump to assembly error routine
; Test for buffer overrun 
   banksel 0           
   incf   _index_in,W   ; Increment index_in to W
   subwf  _index_out,W  ; Subtract indexes to test for buffer overrun
   btfsc   STATUS,Z      ; check for zero (index_in = index_out)
   goto    buffer_err    ; jump to error routine if zero
; Increment the index_in pointer and reset it if it's outside the ring buffer
   incf   _index_in,F   ; Increment index_in to index_in
   movf   _index_in,W   ; Move new index_in to W
   sublw  _buffer_size-1; Subtract index_in from buffer_size-1
   btfss   STATUS, C     ; If index_in => buffer_size
   clrf   _index_in     ; Clear index_in
; Set FSR with the location of the next empty location in buffer
   movlw   High _buffer  ;Store the High byte of buffer to FSR0H
   movwf   FSR0H
   movlw   Low _buffer  ; Get the Low byte of buffer[0]
   addwf  _index_in,W  ; Add index_in to point to next empty slot
   movwf   FSR0L        ; Store Low byte of pointer in FSR0
; Read and store the character from the USART 
   banksel RCREG       
   movf    RCREG,W       ; Read the received character
   movwf   INDF0         ; Put the received character in FSR location
   banksel PIR1
   BTFSC   PIR1,RCIF     ;ANY MORE ?
   goto    myint
finished 
   ;RST?RP
   retfie ; Return from interrupt 
; Error routines        
buffer_err    ; Jump here on buffer error
   bsf   _errflag,1     ; Set the buffer flag
usart_err               ; Jump here on USART error
   banksel  _errflag
   bsf   _errflag,0     ; Set the USART flag
   banksel RCREG 
   movf  RCREG, W       ; Trash the received character
   goto finished       ; Restore state and return to program
ENDASM
overint: 
    
    TRISB = % 00101010
    TRISA = % 11110000 
    OSCCON = $70
    PAUSE 500
    gosub getbaud
    PAUSE 5
    LCDOUT $FE,1 
    hserout [13,"ready"]
    LCDOUT "ready "
    if br==51 then
      hserout ["@9600"]
      LCDOUT  "@9600"
    elseif br==25 then
      hserout ["@19200"]
      LCDOUT  "@19200"
    else       
      hserout ["@38400"]
      LCDOUT  "@38400"
    endif 
    PAUSE 500
@  bsf   LCD_RSREG ,LCD_RSBIT
    GOSUB error
    INTCON = $C0
    PIE1.5 = 1
main:
   IF errflag Then GOSUB error ' Goto error routine if needed
   IF index_in = index_out Then main ' loop if nothing in buffer     
   GoSub getbuf  ' Get a character from buffer
   if bl then
        if bufchar = 0 then 
             portB.0 = 0 ' Back Light OFF
             portB.7 = 1 ' Back Light OFF
        endif
        if bufchar = 8 then 
             portB.0 = 1 ' Back Light ON
             portB.7 = 0 ' Back Light OFF
        endif
        if bufchar = 10 then 
             write inx+1,51
             gosub getbaud
        endif
        if bufchar = 11 then 
             write inx+1,25
             gosub getbaud
        endif
        if bufchar = 12 then 
             write inx+1,12
             gosub getbaud
        endif
        if bufchar = "F" then 
             gosub factory
        endif


        bl = 0
        goto main
   endif
   if bufchar = 255 then 
         bl = 1
         goto main
   endif
   if bufchar = 254 then
@  bcf   LCD_RSREG ,LCD_RSBIT
         goto main 
   endif 
@  MOVE?BB _bufchar,R3
@  MOVE?CT 1,FLAGS ,0
@  L?CALL lcdsend
@  bsf   LCD_RSREG ,LCD_RSBIT
goto main             ' loop back to top
    


error:                          ' Display error message
   INTCON = 0                   ' Disable interrupts while in the error routine
   IF errflag.1 Then            ' Determine the error
      hserout [" Buffer overflow",13]' Display buffer error on line-2
   Else
      hserout [" Uart reset",13]  ' Display usart error on line_2
   EndIF  
   errflag = 0          ' Reset the error flag    ;clear any rcsta error
   RCSTA.4 = 0           'CREN = 0 Disable continuous receive to clear hardware error
   RCSTA.4 = 1           'CREN = 1 Enable continuous receive
   INTCON = % 11000000   ' Enable interrupts
RETURN         ' repeat


    
getbuf:  ' Move the next character in buffer to bufchar
   index_out = index_out + 1     ' Increment index_out pointer (0 to 31)
   IF index_out => buffer_size Then index_out = 0 ' Reset pointer if outside buffer
   bufchar = buffer[index_out]  ' Read buffer location(index_out)
Return


getbaud:
    bufchar = 0
    inx = 255
    read inx,Br
    while Br==255
        read inx,Br
        if  Br==255  then 
            if inx == 0  then  
                br=51
                write inx,51
'                hserout [13,"init@9600 " ,dec inx,",",dec Br]
            else
                inx = inx-1
            endif
        endif
    wend   ;note if inx=255 then eeprom full
'    hserout [" index " ,dec inx,",",dec Br]
    SP1BRG = Br
Return


factory:
  write 0,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff
  write 16,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff
  write 32,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff
  write 48,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff
  write 64,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff
  write 80,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff
  write 96,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff
  write 112,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff
  write 128,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff
  write 144,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff
  write 160,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff
  write 176,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff
  write 192,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff
  write 208,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff
  write 224,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff
  write 240,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff
  gosub getbaud
Return