'********************************************************
'*                                                      *
'*      LCD and USART LIBRARY FOR USE WITH BOOST BASIC  *
'*                                                      *
'*      WRITTEN BY      :  PUNERJOT SINGH MANGAT        *
'*      EMAIL           :  punerjot@rackeys.com         *
'*      SOURCEBOOST ID  :  c58_4311                     *
'*      RELEASE DATE    :  March 03, 2006               *
'*      REVISED DATE    :  May 24, 2006                 *
'*                                                      *
'********************************************************
'
'Any 16x2 alphanumeric LCD can be used if it has a Hitachi HD44780 compatible chipset
' 
' Pin connections of pic16f917A to LCD
'
' PIC Pins          LCD Pins     LCD Function
' --------          --------     ------------
'    RC3               6          E strobe
'    RC2               4          RS
'    RD4              11          D0
'    RD5              12          D1
'    RD6              13          D2
'    RD7              14          D3
'                      1          Gnd
'                      2          +5V
'                      3          Contrast
'                      5          +5V
'
'

'*************************************************************************************
'******************    LCD Code      *************************************************
'*************************************************************************************

' commands are
' lcd_putch(decimal ASCII value of char to be displayed)
' lcd_clear()
' lcd_line1()
' lcd_line2()
' lcd_init()

'******************************* Delay routines for the LCD **************************
sub wait_us()
DIM wait_count as byte
asm
{
MOVLW   d'45'
MOVWF   _wait_count
LOOP_LCD:
DECFSZ  _wait_count, F
GOTO    LOOP_LCD
return
}
end sub
'******************************* Delay routines for the LCD end **********************


'***************************** Support Subroutines begin  ****************************
sub lcd_strobe()
portc.3 = 1
portc.3 = 0
end sub


sub lcd_byte(c as byte)
portd = (portd & 0x0f)
portd = (portd | (c & 0xf0))
call lcd_strobe()
portd = (portd & 0x0f)
portd = (portd | (c << 4))
call lcd_strobe()
call wait_us()
end sub
'******************************* Support Subroutines end ************************


'************************ Procedure to output char to LCD *****************************
sub lcd_putch(c as byte)
portc.2 = 1               'pin 3 of port C is high
call lcd_byte(c)
end sub
'************************ Procedure to output char to LCD end *************************



'************************ Procedure to give commands to LCD ****************************
sub lcd_putcmd(c as byte)
portc.2 = 0               'pin 3 of port C is low
call lcd_byte(c)
end sub
'************************ Procedure to give commands to LCD end ************************



'************************ LCD Initializing routines ************************************
sub lcd_init()
trisc = ( 10000000b )       'Port C, pin 7 is RS232 in
trisd = ( 00000000b )       'pin(0) and pin(1) of PORTB are free so it can be used for RS232
lcdcon = ( 00000000b )		'Disable VLCD<3:1> ;inputs on RC<2:0>
portc.2 = 0
call delay_ms(50)
portd = (portd & 0x0f)
portd = (portd | 0x30)
call lcd_strobe()
call delay_ms(5)
call lcd_strobe()
call wait_us()
call lcd_strobe()
call delay_ms(5)
portd = (portd & 0x0f)
portd = (portd | 0x20)
call lcd_strobe()
call wait_us()
call lcd_putcmd(0x28)
call lcd_putcmd(0x08)
call lcd_putcmd(0x0C)
call lcd_putcmd(0x06)
end sub
'************************ LCD Initializing routines end  ************************



'************************ Procedure to clear the LCD *****************************
sub lcd_clear()
call lcd_putcmd(0x01)
call delay_ms(2)
end sub
'************************ Procedure to clear the LCD end ************************



'******************** Procedure to go to the begining of line1 of the LCD ************
sub lcd_line1()
call lcd_putcmd(0x02)          'start of first line
end sub
'******************** Procedure to go to the begining of line1 of the LCD end ********



'******************** Procedure to go to the begining of line2 of the LCD ************
sub lcd_line2()
call lcd_putcmd(0x80+40)       'start of second line
end sub
'******************** Procedure to go to the begining of line2 of the LCD end *******





'******************************************************************************
'*******************     USART Code   *****************************************
'******************************************************************************

' commands are
' usart_tx(ASCII value of the char to be sent)
' usart_rx() as byte
' usart_init()
'
' RC6 = output to TX
' RC7 = input from RX
'
' Parameters are: Baud rate = 4800, Data bits = 8, Parity = none, Stop bits = 1
' Use spbrg = 12 in the USART init section below if a 4.000 MHz clock is used.

'*************** USART Initializing routines ***********************
sub usart_init()
    trisc.6 = 0         'RC6 is output from UART transmitter
    trisc.7 = 1         'RC7 is input to UART receiver
    txsta = 0
    spbrg = 11          'for 4800 baud with 3.6864 Mhz clock frequency
    txsta = 0x22        '00100010
    rcsta = (10010000b) 'with continuous receive
end sub
'************** USART Initializing routines end ********************


'******************** USART TX procedure ***************************
sub usart_tx(b as byte)
    do while ( !(txsta & 0x02) )
        _asm nop
        _asm clrwdt
    loop
    txreg = b
end sub
'******************** USART TX procedure end ***********************


'******************** USART RX procedure ***************************
function usart_rx() as byte
            
    if ( (rcsta.OERR = 1) ) then    
        rcsta.CREN = 0
        rcsta.CREN = 1
        usart_rx = 0x00
    else
        do while (pir1.RCIF = 0)
            _asm nop
        loop
        usart_rx = rcreg
    end if

end function
'******************** USART RX procedure end **********************