;
; This program interfaces to a 240 x 64 dot matrix LCD module,
;  using the Tosh T6963C control chip

;****************************************************************************
;* This file and the resulting compiled code copyright1993-96 Steve Lawther *
;*      Use of any of this code requires Steve Lawther to have a credit     *
;*        within the source code. Commercial use of any of this code        *
;*           requires the permission of the author, Steve Lawther           *
;*   For more details read 'README.TXT' or email 100255.157@compuserve.com  *
;****************************************************************************

;****************************************************************************
;* Heavily modifyed by Tim Thompson for persinal use.                       *
;****************************************************************************
 include <t6963c.h>
;

; page

;*******************************************************************
;* The LCD Module Subroutines                                      *
;*******************************************************************
;

;******************************************
;* init_lcd
;* Initilizes the lcd, text mode, no clear.
;******************************************
init_lcd

	movlw	(low(GRAPHICSTART))		; set graphics home adder
	movwf	DATABUFB
	movlw	(high(GRAPHICSTART))
	movwf	DATABUFA
	movlw	GRAPH_HOME_SET	
	movwf	COMMANDBUF
	call	lcd_send_2data_cmd

	movlw	BYTES_PER_ROW			; set graphics area
	movwf	DATABUFB
	clrf	DATABUFA
	movlw	GRAPH_AREA_SET
	movwf	COMMANDBUF
	call	lcd_send_2data_cmd


	movlw	(low(TEXTSTART))		; set text home adder
	movwf	DATABUFB
	movlw	(high(TEXTSTART))
	movwf	DATABUFA
	movlw	TEXT_HOME_SET	
	movwf	COMMANDBUF
	call	lcd_send_2data_cmd


	movlw	BYTES_PER_ROW			; set text area
	movwf	DATABUFB
	clrf	DATABUFA
	movlw	TEXT_AREA_SET
	movwf	COMMANDBUF
	call	lcd_send_2data_cmd
	

	movlw	b'10000000'
;	movlw	0x80				; Text OR graphic, cg-rom
	movwf	COMMANDBUF
	call	lcd_send_cmd


;        movlw   OR_MODE				; put it into OR mode
 ;       movwf   COMMANDBUF
  ;      call    lcd_send_cmd

	movlw	b'10010111'	;TEXT_ON	; turn on text
	movwf	COMMANDBUF
	call	lcd_send_cmd
	
	movlw	0xA7				; cursor full block
	movwf	COMMANDBUF
	call	lcd_send_cmd

	clrf	DATABUFA
	clrf	DATABUFB
	movlw	ADDR_PTR_SET			; move address pointer to 0,0
	movwf	COMMANDBUF
	call	lcd_send_2data_cmd

	clrf	DATABUFA
	clrf	DATABUFB
	movlw	CURSOR_PTR_SET			; move cursor to 0,0
	movwf	COMMANDBUF
	call	lcd_send_2data_cmd

	return


;*******************************************************************
;*AutoSend - Sends a byte to the LCD                               *
;* data1 in DATABUFA                                               * 
;* assumes that the autowrite command has been sent                *
;*******************************************************************

lcd_autosend
                CALL    lcd_autosend_check      ; Wait for LCD to be ready
                ;sets CE, C/D & WR, clears RD, Data lines O/Ps
                movf    DATABUFA, W
                movwf   LCD_DATA

                bcf     LCD_C_D
                bsf     LCD_RD
                bcf     LCD_CE
                bcf     LCD_WR
                nop                    ;busy check call long enough
		nop
                bsf     LCD_WR
                bsf     LCD_CE         ;busy_check will set CE high again
                return


;*******************************************************************
;* HOME_POINTER - addr pointer to high addr in W, low = 0          *
;* MOVE_POINTER - sets addr pointer to high addr in W,             *
;* low addr in DATABUFB                                            *
;*******************************************************************

lcd_home_text
	movlw	(low(TEXTSTART))
        movwf	DATABUFB
	movlw	(high(TEXTSTART))
	goto	lcd_move_pointer

lcd_home_graph
	movlw	(low(GRAPHICSTART))
        movwf	DATABUFB
	movlw	(high(GRAPHICSTART))
	goto	lcd_move_pointer

lcd_move_pointer                        
	movwf   DATABUFA
	movlw   ADDR_PTR_SET
	movwf   COMMANDBUF

;*******************************************************************
;* SEND_2DATA_CMD - Sends 2 byte of data and command to LCD        *
;* command in COMMANDBUF, data1 in DATABUFA, data2 in DATABUFB     *
;*******************************************************************

lcd_send_2data_cmd
                CALL    lcd_busy_check			; Wait for LCD to be ready
                ;sets CE, C/D & WR, clears RD, Data lines O/Ps
                movf    DATABUFB, W
                movwf   LCD_DATA
                bcf     LCD_C_D
                bsf     LCD_RD
                bcf     LCD_CE
                bcf     LCD_WR
                nop                    ;busy check call long enough
		nop
                bsf     LCD_WR
                bsf     LCD_CE         ;busy_check will set CE high again

;*******************************************************************
;* SEND_1DATA_CMD - Sends 1 byte of data and command to LCD        *
;* command in COMMANDBUF, data in DATABUFA                         *
;*******************************************************************

lcd_send_1data_cmd
                CALL    lcd_busy_check      ; Wait for LCD to be ready
                ;sets CE, C/D & WR, clears RD, Data lines O/Ps
                movf    DATABUFA, W
                movwf   LCD_DATA
                bcf     LCD_C_D
                bsf     LCD_RD
                bcf     LCD_CE
                bcf     LCD_WR
		nop
                nop                    ;wait long enough
                bsf     LCD_WR
                bsf     LCD_CE         ;busy_check will set CE high again

;*******************************************************************
;* SEND_CMD - Sends command to LCD                                 *
;* command in COMMANDBUF                                           *
;*******************************************************************

lcd_send_cmd
;		bcf	INTCON, T0IE
                CALL    lcd_busy_check      ; Wait for LCD to be ready

                ;sets CE, C/D & WR, clears RD, Data lines O/Ps
                movf    COMMANDBUF, W
                movwf   LCD_DATA
                bsf     LCD_RD
                bcf     LCD_CE
                bcf     LCD_WR
                nop                    ;busy check call long enough
		nop
                bsf     LCD_WR
                bsf     LCD_CE
;		bsf	INTCON, T0IE
                return            
            
  
;*******************************************************************
;* This routine checks the busy flags, returns when not busy       *
;*                                                                 *
;* this routine assumes data lines set to O/P                      *
;*******************************************************************
;
lcd_status_read
lcd_busy_check
                bsf     LCD_CE
		Bank1
                clrf    LCD_DATA_TRIS		; sets it to O/P
                comf    LCD_DATA_TRIS, F	; sets it to I/P
		Bank0
                bsf     LCD_C_D         	; Set LCD to status read
                BSF     LCD_WR

                bcf     LCD_RD
                BCF     LCD_CE          	; Enable
                nop                    		;incase the clk is >10MHz (comment out if not -IRule)
		nop
                btfsc   LCD_DATA, STA0  	;if both are high, ready
                btfss   LCD_DATA, STA1
                goto    lcd_busy_check

                BSF     LCD_RD
                BSF     LCD_CE        
		Bank1
                clrf    LCD_DATA_TRIS   	; back to O/Ps
		Bank0
		return
                
;**********
;* Clears the graphics memmory
;**********
lcd_clear_graphic
	call	lcd_home_graph
                        
	clrf	DATABUFA		; clear bufa
	btfsc	SYS_OPTS, SOPT_LCDCOL	; Color all on?
	comf	DATABUFA, 1 		; Yup, make em all on

	movlw	BYTES_PER_ROW		; 40 per line
	movwf	tmp_lcd1
lcdloop1
	movlw	64
	movwf	tmp_lcd2
lcdloop2
	movlw	DATA_WR_INC
	movwf	COMMANDBUF
	call	lcd_send_1data_cmd
	decfsz	tmp_lcd2, 1
	goto	lcdloop2
	decfsz	tmp_lcd1, 1
	goto	lcdloop1
                        
	call	lcd_home_graph
	return

;**********
;* Clears the text memmory
;**********

lcd_clear_text
	call	lcd_home_text

	movlw	8
	movwf	tmp_lcd1
clear_loop1
	movlw	BYTES_PER_ROW
	movwf	tmp_lcd2
clear_loop2	clrf	DATABUFA
	movlw	DATA_WR_INC
	movwf	COMMANDBUF
	call	lcd_send_1data_cmd

	decfsz	tmp_lcd2, 1
	goto	clear_loop2

	decfsz	tmp_lcd1, 1
	goto	clear_loop1
	

	call	lcd_home_text
	return
		

;*******************************************************************
;* This routine checks the auto busy flags, returns when not busy  *
;*                                                                 *
;* this routine assumes data lines set to O/P                      *
;*******************************************************************
;
lcd_autosend_check

	bsf     LCD_CE
	Bank1
	clrf    LCD_DATA_TRIS   ; sets it to O/P
	comf    LCD_DATA_TRIS, F ; sets it to I/P
	Bank0
	bsf     LCD_C_D         ; Set LCD to status read
	BSF     LCD_WR

	bcf     LCD_RD
	BCF     LCD_CE          ; Enable
	nop                    ;incase the clk is >10MHz (comment out if not -IRule)
	nop
	btfsc   LCD_DATA, STA2  ;if both are high, ready
	btfss   LCD_DATA, STA3
	goto    lcd_busy_check

	BSF     LCD_RD
	BSF     LCD_CE        
	Bank1
	clrf    LCD_DATA_TRIS   ; back to O/Ps
	Bank0
	return



;*****
;*This routine prints the letter in W to the lcd
;*****
lcd_put_char
	movwf	DATABUFA		; Put W into DATABUFA
	movlw	0x20			; subtract 20h to get
	subwf	DATABUFA, F		; charictor address in chip

	movlw	DATA_WR_INC		; Put 'write and inc ptr' into W
	movwf	COMMANDBUF		; Put it into COMMANDBUF
	call	lcd_send_1data_cmd	; Send it!
	return

;*****
;* Same as lcd_put_char, but sets the address right for binarie numericals.
;*****
lcd_put_num
	addlw	0x10			; add 0x10 to number to get number adder
	movwf	DATABUFA

	movlw	DATA_WR_INC
	movwf	COMMANDBUF
	call	lcd_send_1data_cmd
	return

;*****
;* Sets the LCD contrast, value to adjust is in W
;*****
lcd_contrast_adj
	movwf	tmp_lcd1
bias_loop
	bsf	LCD_BIAS_ADJ
;	Wait	1 Millisec, 0
	bcf	LCD_BIAS_ADJ
	decfsz	tmp_lcd1, F
	goto bias_loop
	return

;*****
;* Resets the MAX749's internal counter to mid range
;*****
lcd_contrast_rst
	bcf	LCD_BIAS_CTRL
	Wait	1 Millisec, 0
	bsf	LCD_BIAS_ADJ
	Wait	1 Millisec, 0
	bcf	LCD_BIAS_ADJ
	return


