;lcd.asm: Hitachi LC-Display / RS232 interface with PIC16C71 @3.6864MHz TITLE "LCD" RTCC EQU 1 PC EQU 2 STATUS EQU 3 PORTB EQU 6 PCLATH EQU 0x0A INTCON EQU 0x0B _OPT EQU 0x81 ; OPTION register in page 1 _TRB EQU 0x86 ; TRISB in page 1 C EQU 0 DC EQU 1 Z EQU 2 P EQU 5 tmp0 EQU 0x0C tmp1 EQU 0x0D tmp2 EQU 0x0E pos EQU 0x0F sav0 EQU 0x10 sav1 EQU 0x11 rxdata EQU 0x12 ; receive data rxshft EQU 0x13 ; receiver shift register bitcnt EQU 0x14 ; receiver bit counter rxavl EQU 7 ; rx data available (IRP bit in STATUS) ORG 0 ; reset GOTO main ORG 4 ; interrupt GOTO intserv ORG 8 intserv MOVWF sav0 ; save working register MOVF STATUS,W ; save status register MOVWF sav1 BCF STATUS,P ; set page 0 MOVF bitcnt,F ; bitcounter 0? (startbit) BTFSS STATUS,Z GOTO datab startb MOVLW -.130 ; rtc interrupt in middle of first bit MOVWF RTCC CLRF INTCON ; clear all flags and enable-bits BSF INTCON,5 ; enable rtc interrupt INCF bitcnt,F GOTO intend datab RRF rxshft,F ; shift in new bit BCF rxshft,7 BTFSS PORTB,0 ; poll rx-line BSF rxshft,7 BTFSC bitcnt,3 ; test if this was the eight bit GOTO lastbit INCF bitcnt,F ; prepare polling for next bit MOVLW -.93 ; tmr0-(cycles-3) ADDWF RTCC,F CLRF INTCON ; clear all flags and enable-bits BSF INTCON,5 ; enable rtc interrupt GOTO intend lastbit CLRF bitcnt MOVF rxshft,W ; copy to data register MOVWF rxdata BSF sav1,rxavl ; status is restored from sav1 CLRF INTCON ; clear all flags and enable-bits BSF INTCON,4 ; enable int for next startbit intend MOVF sav1,W ; restore status register MOVWF STATUS MOVF sav0,W ; restore working register BCF STATUS,Z BTFSC sav1,Z ; restore zero bit BSF STATUS,Z RETFIE main CALL init CALL loadcgr CALL line0 MOVLW 0 CALL dispstr CALL line0 CLRF pos waitrx BTFSS STATUS,rxavl ; wait here until char received GOTO waitrx MOVF rxdata,W ; get data BCF STATUS,rxavl ; reset flag tstcr MOVWF tmp0 XORLW .13 BTFSS STATUS,Z GOTO tstlf MOVLW .40 SUBWF pos,W ; is pos >= 40 BTFSC STATUS,C GOTO crlin1 ; yes: we are in line 1 crlin0 CALL line0 CLRF pos ; pos to 0 GOTO waitrx ; loop crlin1 CALL line1 MOVLW .40 ; pos to 40 MOVWF pos GOTO waitrx ; loop tstlf MOVF tmp0,W XORLW .10 BTFSS STATUS,Z GOTO tstbs MOVLW .40 SUBWF pos,W ; is pos >= 40 BTFSC STATUS,C GOTO lflin1 ; yes: we are in line 1 lflin0 MOVF pos,W ADDLW 0xC0 CALL outcmd MOVLW .40 ADDWF pos,F GOTO waitrx ; loop lflin1 MOVLW .40 SUBWF pos,F MOVF pos,W ADDLW 0x80 CALL outcmd GOTO waitrx ; loop tstbs MOVF tmp0,W XORLW .08 BTFSS STATUS,Z GOTO tstff MOVLW .41 SUBWF pos,W ; is pos >= 41 BTFSC STATUS,C GOTO bslin1 ; yes: we stay in line 1 bslin0 MOVF pos,W BTFSC STATUS,Z GOTO bslin00 ; pos = 0: move to end of line 1 XORLW .40 BTFSC STATUS,Z GOTO bslin40 ; pos = 40: move to end of line 0 DECF pos,F MOVF pos,W ADDLW 0x80 GOTO bsend bslin1 DECF pos,F MOVF pos,W ADDLW 0x98 GOTO bsend bslin00 MOVLW .79 MOVWF pos ADDLW 0x98 GOTO bsend bslin40 MOVLW .39 MOVWF pos ADDLW 0x80 bsend CALL outcmd GOTO waitrx ; loop tstff MOVF tmp0,W XORLW .12 BTFSS STATUS,Z GOTO other CALL clrdisp CLRF pos GOTO waitrx ; loop other MOVF tmp0,W CALL dispch INCF pos,F MOVLW .40 ; check if at display line 0 end XORWF pos,W BTFSC STATUS,Z CALL line1 MOVLW .80 ; check if at display line 1 end XORWF pos,W BTFSS STATUS,Z GOTO waitrx ; loop CALL line0 CLRF pos GOTO waitrx ; loop init CALL initlcd BSF STATUS,P ; set page 1 MOVLW B'11011111' ; int on rising edge, no prescaler for rtc MOVWF _OPT BCF STATUS,P ; set page 0 CLRF bitcnt MOVLW B'10010000' ; int enable, global interrupt enable MOVWF INTCON DATA 0xFF DATA 0xFF DATA 0xFF DATA 0xFF RETLW 0 initlcd MOVLW B'00110000' ; bit3..0,dat/cmd,rd/wr,ena,0 MOVWF PORTB ; command, write, ena low BSF STATUS,P ; set page 1 MOVLW B'00000001' ; 7..1 outputs, 0 input MOVWF _TRB BCF STATUS,P ; set page 0 MOVLW .20 CALL delayw CALL latch MOVLW .5 CALL delayw CALL latch MOVLW .1 CALL delayw CALL latch CALL pollbsy MOVLW B'00100000' ; 4-Bit interface MOVWF PORTB CALL latch MOVLW 0x28 ; 4 bit, 2 lines, 5x7 matrix CALL outcmd MOVLW 0x08 ; display off CALL outcmd MOVLW 0x01 ; display on CALL outcmd MOVLW 0x06 ; increment, no shift CALL outcmd CALL curson ; display on, cursor on CALL clrdisp ; clear display, cursor home RETLW 0 delayw MOVWF tmp0 ; delay w * 1000 cycles (w/o call and ret) dlyw0 MOVLW .249 MOVWF tmp1 dlyw1 NOP DECFSZ tmp1,F GOTO dlyw1 DECFSZ tmp0,F GOTO dlyw0 RETLW 0 latch BSF PORTB,1 ; ena high BCF PORTB,1 ; ena low RETLW 0 pollbsy BSF STATUS,P ; set page 1 MOVLW B'11110001' MOVWF _TRB ; data inputs BCF STATUS,P ; set page 0 MOVLW B'00000100' ; command, read, ena low MOVWF PORTB pollbs0 BSF PORTB,1 ; ena high (higher nibble) MOVF PORTB,W MOVWF tmp0 BCF PORTB,1 ; ena low BSF PORTB,1 ; latch lower nibble BCF PORTB,1 ; ena low BTFSC tmp0,7 GOTO pollbs0 CLRF PORTB ; ena low, write, command BSF STATUS,P ; set page 1 MOVLW B'00000001' MOVWF _TRB ; data outputs BCF STATUS,P ; set page 0 RETLW 0 outcmd MOVWF tmp1 ; tmp0 is needed by pollbsy CALL pollbsy ; command, write, ena low GOTO outbyte dispch MOVWF tmp1 ; tmp0 is needed by pollbsy CALL pollbsy MOVLW B'00001000' ; data, write, ena low outbyte MOVWF PORTB MOVF tmp1,W ; high nibble first ANDLW 0xF0 IORWF PORTB,F CALL latch MOVLW 0x0F ANDWF PORTB,F SWAPF tmp1,W ; low nibble ANDLW 0xF0 IORWF PORTB,F CALL latch MOVF tmp1,W ; restore W RETURN clrdisp MOVLW 0x01 ; clear display, cursor home CALL outcmd RETLW 0 curson MOVLW 0x0D ; cursor blink CALL outcmd RETLW 0 cursoff MOVLW 0x0C ; cursor invisible CALL outcmd RETLW 0 line0 MOVLW 0x80 ; cursor to line 0 (home) CALL outcmd RETLW 0 line1 MOVLW 0xC0 ; cursor to line 1 CALL outcmd RETLW 0 hexchr ANDLW 0x0F ; 0..15 to '0'..'F' MOVWF tmp0 ; store SUBLW .9 ; check if >= 10 (carry clr) MOVLW .48 BTFSS STATUS,C ; add 7 if carry clr ADDLW .7 ADDWF tmp0,W RETURN disphex MOVWF tmp2 ; display as two hex chars, save SWAPF tmp2,W CALL hexchr CALL dispch MOVF tmp2,W CALL hexchr CALL dispch MOVF tmp2,W ; restore RETURN dispstr MOVWF tmp2 ; string display (W is offset from msg0) MOVLW B'00001' ; PCLATH to pattern MOVWF PCLATH MOVF tmp2,W dispst0 CALL message ; get char XORLW 0 ; test if zero BTFSC STATUS,Z RETLW 0 ; return if char is zero CALL dispch ; display INCF tmp2,F ; next char MOVF tmp2,W GOTO dispst0 loadcgr MOVLW B'00001' ; PCLATH to pattern MOVWF PCLATH MOVLW 0x40 ; character generator rom CALL outcmd CLRF tmp2 ; byte counter loadcg0 MOVF tmp2,W XORLW .64 ; test if all 64 bytes out BTFSC STATUS,Z RETLW 0 ; return if so MOVF tmp2,W CALL pattern ; get byte from table, write to cgr CALL dispch INCF tmp2,F ; point to next byte GOTO loadcg0 ORG 0x110 message ADDWF PC,F ; return char from table below msg0 RETLW 'm' ; offset 0 RETLW 'i' RETLW 'n' RETLW 'i' RETLW 't' RETLW 'e' RETLW 'r' RETLW 'm' RETLW ' ' RETLW '9' RETLW '6' RETLW '0' RETLW '0' RETLW ',' RETLW 'n' RETLW ',' RETLW '8' RETLW ',' RETLW '1' RETLW 0 pattern ADDWF PC,F ; return char from table below cgrtb0 RETLW B'00000' RETLW B'00000' RETLW B'00000' RETLW B'00000' RETLW B'00000' RETLW B'00000' RETLW B'00000' RETLW B'11111' cgrtb1 RETLW B'00000' RETLW B'00000' RETLW B'00000' RETLW B'00000' RETLW B'00000' RETLW B'00000' RETLW B'11111' RETLW B'11111' cgrtb2 RETLW B'00000' RETLW B'00000' RETLW B'00000' RETLW B'00000' RETLW B'00000' RETLW B'11111' RETLW B'11111' RETLW B'11111' cgrtb3 RETLW B'00000' RETLW B'00000' RETLW B'00000' RETLW B'00000' RETLW B'11111' RETLW B'11111' RETLW B'11111' RETLW B'11111' cgrtb4 RETLW B'00000' RETLW B'00000' RETLW B'00000' RETLW B'11111' RETLW B'11111' RETLW B'11111' RETLW B'11111' RETLW B'11111' cgrtb5 RETLW B'00000' RETLW B'00000' RETLW B'11111' RETLW B'11111' RETLW B'11111' RETLW B'11111' RETLW B'11111' RETLW B'11111' cgrtb6 RETLW B'00000' RETLW B'11111' RETLW B'11111' RETLW B'11111' RETLW B'11111' RETLW B'11111' RETLW B'11111' RETLW B'11111' cgrtb7 RETLW B'00100' RETLW B'00100' RETLW B'01110' RETLW B'01110' RETLW B'11111' RETLW B'00100' RETLW B'00000' RETLW B'00000' END