;UNICORN LCD test, jumper on J1VEB, 8 bit mode with full handshaking
list p=16F887
include <p16F887.inc>
__CONFIG _CONFIG1, _HS_OSC & _WDT_OFF & _LVP_OFF & _DEBUG_ON
; CONFIG FOSC = INTOSC_HS, WDT = OFF, LVP = OFF, PBADEN = OFF
errorlevel -302,-305
#define LCD_E PORTE,2
#define LCD_RS PORTE,0
#define LCD_RW PORTE,1
#define LCD_BL PORTB,3
#define LED_N PORTC,1
cblock 0x20
msdelay:2
delay
temp
endc
org 0
banksel ANSEL ; select BANK 3
clrf ANSEL
clrf ANSELH
movlw 0x80 ; prepare to read FLASH
movwf EECON1
bcf STATUS,RP0 ; select BANK 3 -> BANK 2
movlw HIGH LCD_CC
movwf EEADRH
banksel TRISB ; select BANK 1
bcf TRISB,3 ; LCD backlight control
clrf TRISD ; LCD data output
clrf TRISE ; LCD control outputs
bcf TRISC,1
clrf PSTRCON
bcf STATUS,RP0 ; select BANK 0
clrf PORTE ; LCD E, RS, RW
bsf LED_N
; LCD soft reset (ignores/enables busy flag polling)
movlw .4 ; repeat sending 0x38 to reset LCD
movwf temp ; loop counter
init3: movlw .50 ; delay > 50 ms
movwf delay ; enter with delay in ms via W
dec01: call mswait ; wait 1 ms
decfsz delay ; decrement delay and skip when zero
goto dec01 ; branch backwards one instruction
bsf LCD_E ; LCD enable bit high
nop
nop
nop
nop
movlw 0x38 ; send 0x38 four times
movwf PORTD ; LCD = 0x38 (8 bit mode x 2 line)
nop
nop
nop
nop
nop
nop
bcf LCD_E ; latches on High to Low transition
decfsz temp
goto init3 ; repeat 3 times
bsf LCD_BL ; turn on backlight
call mswait
; load special charaters into LCD RAM using LCD busy flag
movlw b'01000000' ; set LCD CG address to 00
call LCD_Ins ; relative call
clrf temp
movlw LOW LCD_CC ; pointer to custom character table
bsf STATUS,RP1 ; BANK0 -> BANK2
movwf EEADR
nextcc: call rdflash
call LCD_Chr ; send the character into LCD RAM
incf temp
btfss temp, 6 ; 64 bytes total
goto nextcc
; clear & enable LCD DRAM, no visible cursor
movlw 0x0C ; display on, cursor off
call LCD_Ins
; display top 16 characters
movlw 0x01 ; clear display, home cursor
call LCD_Ins
movlw .16
movwf temp
bsf STATUS,RP1 ; BANK0 -> BANK2
movlw LOW Text_ ; low byte pointer
movwf EEADR
top: call rdflash
call LCD_Chr
decfsz temp
goto top
; display bottom 16 characters
movlw 0xC0 ; set cursor to second line
call LCD_Ins ; LCD instruction mode
movlw .16
movwf temp
bottom: call rdflash
call LCD_Chr ; LCD character mode
decfsz temp
goto bottom
nop
nop
bcf LED_N
goto $ ; endless loop done
; wait approx 1 ms
mswait movlw 4
movwf msdelay+1
msd movlw .250
movwf msdelay
msdl nop
decfsz msdelay
goto msdl
decfsz msdelay+1
goto msd
return
; read one byte from program flash, increment EEADDR
rdflash: bsf STATUS,RP0 ; BANK3
bsf STATUS,RP1 ; BANK3
bsf EECON1,EEPGD
bsf EECON1,RD ; 2 NOPs MUST (!) follow after reading program FLASH
nop
nop
bcf STATUS,RP0 ; BANK3 -> BANK2
incf EEADR
movf EEDAT,W
bcf STATUS,RP1 ; BANK2 -> BANK0
return
; LCD entry routines watches busy flag
LCD_Chr bsf LCD_RS ; enable character mode
LCD_Ins bsf STATUS,RP0 ; -> BANK1
clrf TRISD ; make PORTD an output
bcf STATUS,RP0 ; -> BANK0
movwf PORTD ; put data on LCD port
bcf LCD_RW
nop
bsf LCD_E
nop
nop
nop
nop
bcf LCD_E ; latch byte to LCD
nop
bcf LCD_RS
bsf STATUS,RP0 ; -> BANK1
movlw 0xff
movwf TRISD ; make LCD port input
bcf STATUS,RP0 ; -> BANK0
bsf LCD_RW ; enter read mode
bsf LCD_E ; enable LCD
BusyF btfsc PORTD,7 ; wait for bit 7 to be pulled low
goto BusyF
bcf LCD_E
bcf LCD_RW ; return to instruction mode
return
; text to display (Table with two bytes per word)
org 0x0400
Text_ dt "blueroom ",.0,.1
dt "electronics ",.2,.3
; *** 2x2 blueroomelectronics logo (house)
LCD_CC dt .128,.128,.129,.131,.135,.143,.159,.159
dt .128,.128,.128,.144,.152,.156,.158,.130
dt .159,.159,.159,.145,.145,.145,.159,.128
dt .130,.130,.158,.130,.130,.130,.158,.128
END