'************************************************************************
'GLIPICT.BAS Graphic application for use with a T6963C (or compatible)
'graphic LCD controller connected to a Microchip(TM) PIC 16F877
'Written in MELabs PicBasicPro(TM) Ver 3.32
'Beta version 0.8.0
'SHARP LCD used: 240x64 graphic LCD (EL backlight)
'================== NOT FOR COMMERICIAL USE =============================
'
'       Author: Ranjit Diol - COMPSys, May 2001
'            (c) Copyright Ranjit Diol, 2001
'
'   DISCLAIMER: This file is being released as non-commericial
'   freeware. It is being provided "AS IS", neither the author, 
'   nor COMPSys shall be held liable for any damages direct or indirect 
'   caused by its use.
'
'   LICENSE: This application may be used in its entirety or 
'   in parts within some other non-commercial application as long
'   as the author is given credit for those parts used.
'
'        Contact: rsdiol@compsys1.com for more information
'
'	Many thanks to Steve Lawther for his documentation on the T6963
'	and his sample assembly code which made this project possible
'
'**************************************************************************
device = 16F877

DEFINE	ONINT_USED	1	'If using ISP

DEFINE OSC 4			'Adjust to suit your design
'ADCON1	= 7			'Adjust ADC for your needs

SPBRG=0				'************ NOTE ***********

ALL_DIGITAL = True
'Variables used
' *** MODIFY AS REQUIRED FOR OTHER PINS AND PORTS *****
'
glcd_tris 	var 	TRISD		'Data bus direction
glcd_dat	var 	PORTD		'LCD 8 bit data bus
glcd_wr	 	var	    PORTc.2		'Write control bit
glcd_rd	 	var 	PORTe.0		'Read control bit
glcd_ce	 	var 	PORTe.1		'Chip enable control bit
glcd_cd	 	var 	PORTe.2		'Command and Data toggle bit
glcd_rst	var	PORTa.5		'Reset control bit
'glcd_fs	 	var	PORTC.5		'Font select control bit
'glcd_bl	 	var	PORTA.5		'Back light control bit
glcd_bsy	var	PORTD.7         'In case there is a need, not really used
glcd_btn	var     PORTB.0		'A button for debugging purposes
glcd_sta0	var     PORTD.0		'Status Bit 0	
glcd_sta1	var     PORTD.1		'Status Bit 1
glcd_sta2       var     PORTD.2		'Status Bit 2
glcd_sta3       var     PORTD.3		'Status Bit 3

'General use variables used
glcd_msb	var	BYTE		'Data 1 variable
glcd_lsb	var	BYTE 		'Data 2 variable
glcd_cmd	var	BYTE 		'Command variable
gl_tmp	 	var	BYTE		'Temp var		
gl_old	 	var     BYTE		'Previous byte var
gl_x     	var     WORD		'16 bit var for address loop
gl_y	 	var     WORD		'16 bit var for address loop
gl_i	 	var	BYTE
gl_j	 	var     BYTE
gl_k	 	var     BYTE
gl_l	 	var     BYTE
num_1	 	var	BYTE
num_2	 	var	BYTE
gl_stp	 	var	BYTE		'Step var in FOR..NEXT
gl_ad1	 	var	BYTE		'Addr var
gl_ad2	 	var	BYTE		'Addr var
graph_home 	var 	WORD		'LCD graphic start addr
graph_area 	var 	WORD		'LCD graphic bytes per line
text_home  	var 	WORD		'LCD text start addr
text_area  	var 	WORD		'LCD text chars per line

'Initialize variables
gl_tmp   =  0
gl_i     =  0
gl_stp   =  1

'************************
' LCD Module constants  *
'************************
'
'Register set commands:
CURSOR_PTR_SET          con     $21   'Cursor Pointer Set
OFFSET_REG_SET          con     $22   'Offset Register Set
ADDR_PTR_SET            con     $24   'Address Pointer Set

'Control Word Set commands:
TEXT_HOME_SET           con     $40   'Text Home Address Set
TEXT_AREA_SET           con     $41   'Text Area Set
GRAPH_HOME_SET          con     $42   'Graphics Home address Set
GRAPH_AREA_SET          con     $43   'Graphics Area Set

'Mode Set commands (OR with CG rom commands):
OR_MODE                 con     $80   'OR mode
XOR_MODE                con     $81   'XOR mode
AND_MODE                con     $83   'AND mode
TEXT_ATTR_MODE          con     $84   'Text Attribute mode
INT_CG_MODE             con     $80   'Internal CG ROM mode
EXT_CG_MODE             con     $88   'External CG ROM mode

'Display Mode commands (OR together required bits):
DISPLAY_OFF             con     $90   'display off
BLINK_ON                con     $91
CURSOR_ON               con     $92
TEXT_ON                 con     $94
GRAPHIC_ON              con     $98
TEXT_AND_GRAPH_ON	con     $9C

'Cursor Pattern Select
CURSOR_1LINE            con     $A0
CURSOR_2LINE            con     $A1
CURSOR_3LINE            con     $A2
CURSOR_4LINE            con     $A3
CURSOR_5LINE            con     $A4
CURSOR_6LINE            con     $A5
CURSOR_7LINE            con     $A6
CURSOR_8LINE            con     $A7

'Data Auto Read/Write
DATA_AUTO_WR            con     $B0
DATA_AUTO_RD            con     $B1
AUTO_DATA_RESET         con     $B2

'Data Read/Write
DATA_WR_INC             con     $C0   'Data write and increment addr
DATA_RD_INC             con     $C1   'Data read and increment addr
DATA_WR_DEC             con     $C2   'Data write and decrement addr
DATA_RD_DEC             con     $C3   'Data read and decrement addr
DATA_WR                 con     $C4   'Data write - no addr change
DATA_RD                 con     $C5   'Data read - no addr change

'Screen Peek
SCREEN_PEEK             con     $E0

'Screen Copy
SCREEN_COPY             con     $E8

'Bit Set/Reset (OR with bit number 0-7)

BIT_RESET               con     $F0
BIT_SET                 con     $F8

'************************
' STATUS bits           *
'************************

STA0                    con     0       'command excution status
STA1                    con     1       'data read/write status
STA2                    con     2       'auto data read status
STA3                    con     3       'auto data write status
STA5                    con     5       'controller status
STA6                    con     6       'peek/copy error flag
STA7                    con     7       'blink? or blank? status

ASCII_OFFSET		con     $20     'ASCII offset for conversion
GL_PAUSE		con     2

'Initialize LCD VRAM area variables
graph_home       	=     $1000    'Decimal 4096
graph_area		=     $0028    '40 bytes per line
text_home		=     $0000
text_area               =     $0028    '40 6x8 chars per line




'Set appropriate port/bit dir
TRISB.0  =      0
TRISB.1  =      0
TRISB.2  =      0
TRISD	 = 	0
TRISC = 0
TRISC.0	 =	0
TRISC.2	 =	0
TRISC.5	 =	0
TRISA.4	 =	0
TRISA.5	 =	0
trise = 0

'Initial settings of port and bits
glcd_dat = 0	'Clear PORTD
glcd_wr  = 1    'Write high 
glcd_rd  = 1	'Read high
glcd_ce  = 1  	'Chip enable high (active low)
glcd_cd  = 1  	'Command high
'glcd_fs  = 1	'Set Font size (1=6x8 and 0=8x8 font)
glcd_rst = 1 	'RESET always high (low will reset the LCD controller)
'glcd_bl  = 0	'Backlight 0=off 1=on
glcd_btn = 0 	'debug led
pause 500	'Let things stabilize

glcd_rst = 0	' Reset after power-on
pause 1
glcd_rst = 1

portc.0 = 0

goto init '****** jump past the routines below ******


'*********** PBP Subroutines used in this program *******

send_2:
	gosub busy_chk
	glcd_dat = glcd_lsb
	glcd_cd  = 0
	glcd_rd  = 1
	glcd_ce  = 0
	glcd_wr  = 0
	pauseus GL_PAUSE
	glcd_wr  = 1
	glcd_ce  = 1
send_1:
	gosub busy_chk
	glcd_dat = glcd_msb
	glcd_cd  = 0
	glcd_rd  = 1
	glcd_ce  = 0
	glcd_wr  = 0
	pauseus GL_PAUSE
	glcd_wr  = 1
	glcd_ce  = 1
send_cmd:
	gosub busy_chk
	glcd_dat = glcd_cmd
	glcd_rd  = 1
	glcd_ce  = 0
	glcd_wr  = 0
	pauseus GL_PAUSE
	glcd_wr  = 1
	glcd_ce  = 1
return


busy_chk:
	glcd_ce = 1
	glcd_tris= %11111111
	glcd_cd = 1
	glcd_wr = 1
	glcd_ce = 0
	glcd_rd = 0
	pauseus GL_PAUSE
	if glcd_sta0 <> 1 AND glcd_sta1 <> 1 then busy_chk
	glcd_rd = 1
        glcd_ce = 1
	glcd_tris = %00000000
return

ln1:

	' Set Addr Ptr
	glcd_msb = gl_ad1
	glcd_lsb = gl_ad2
	glcd_cmd = ADDR_PTR_SET
	'call SEND2
	gosub send_2

    for gl_x = num_1 to num_2 step gl_stp
	glcd_msb = gl_k
	glcd_cmd = DATA_WR_INC
	gosub send_1 
     
    next

 return

setadr:
	' Set Addr Ptr
	glcd_msb = gl_ad1
	glcd_lsb = gl_ad2
	glcd_cmd = ADDR_PTR_SET
	gosub send_2
return

write1:
	glcd_msb = gl_k
	glcd_cmd = DATA_WR_INC
	gosub send_1 
return

design1:
gl_j =$00
for gl_i = $00 to $07	
  for gl_y=($1820+gl_j) to ($1847+gl_j) step 2
	gl_ad1= gl_y.BYTE1
	gl_ad2= gl_y.BYTE0
	gosub setadr
	gosub write1	
  next
gl_j=gl_j+$28
next
return

'**********  End of PBP subroutines *********************
'========================================================
'************End of all subroutines *********************


'********************************************************                                                     
'************* BEGIN MAIN PROGRAM *********************** 
'********************************************************   


'***Initialize and setup display headings,titles etc ****

init:				'Initialization

	'See data sheets for more info for the commands and parameters
        
	' Set Graphic Home Addr
	glcd_msb = graph_home.BYTE1		
	glcd_lsb = graph_home.BYTE0
	glcd_cmd = GRAPH_HOME_SET
        gosub send_2

	' Set Graphic Area
	glcd_msb = graph_area.BYTE1
	glcd_lsb = graph_area.BYTE0
	glcd_cmd = GRAPH_AREA_SET
        gosub send_2

        ' Set Text Home Addr
	glcd_msb = text_home.BYTE1
	glcd_lsb = text_home.BYTE0
	glcd_cmd = TEXT_HOME_SET
        gosub send_2

	' Set Text Area
	glcd_msb = text_area.BYTE1
	glcd_lsb = text_area.BYTE0
	glcd_cmd = TEXT_AREA_SET
        gosub send_2

	' Set OR mode
	glcd_cmd = OR_MODE
	gosub send_cmd

	' Set Addr Ptr
	glcd_msb = $00
	glcd_lsb = $00
	glcd_cmd = ADDR_PTR_SET
	gosub send_2

	' Set Graphic mode on
	glcd_cmd = GRAPHIC_ON
	gosub send_cmd
	
       for gl_i = 1 to 240		' Clear Graphic Screen
	for gl_j = 1 to 64
	  glcd_msb = $00		'Clear byte
	  glcd_cmd = DATA_WR_INC	'Command
	  gosub send_1			'Send glcd_msb followed by glcd_cmd
	next
       next				'Do it 240x64 times
	
	' Set Addr Ptr
	glcd_msb = $10		
	glcd_lsb = $00
	glcd_cmd = ADDR_PTR_SET
	gosub send_2

for gl_y= $1000 to $14d8 step $28 'Left Vert Line
	gl_ad1= gl_y.BYTE1
	gl_ad2= gl_y.BYTE0
        gl_k=%11100000
	num_1 =1
	num_2 =1
	gosub ln1
next


for gl_y= $1027 to $1528 step $28 'Right Vert Line
	gl_ad1= gl_y.BYTE1
	gl_ad2= gl_y.BYTE0
	gl_k= %11000001
	num_1 =1
	num_2 =1
	gosub ln1
next

        gl_k = $ff
	num_1 = 1
	num_2 = 40
	gl_stp = 1

	gl_ad1 = $10
	gl_ad2 = $00
        gosub ln1		' Graphic Line Top

	gl_ad1 = $15
	gl_ad2 = $00
  gosub ln1		' Graphic Line Middle
	gl_ad1 = $19
	gl_ad2 = $d8
  gosub ln1		' Graphic Line Bottom



	' Set Graphic & Text mode on
	glcd_cmd = TEXT_ON
	gosub send_cmd

		' Set Addr Ptr
	glcd_msb = $00
	glcd_lsb = $29
	glcd_cmd = ADDR_PTR_SET
	gosub send_2

	for gl_i = 0 to 35
         lookup gl_i,["TOSHIBA T6963 "] ,glcd_msb
	 glcd_msb = glcd_msb - ASCII_OFFSET
	 glcd_cmd = DATA_WR_INC
	 gosub send_1
	next

	' Set Addr Ptr
	glcd_msb = $00
	glcd_lsb = $54
	glcd_cmd = ADDR_PTR_SET
	gosub send_2

	for gl_i = 0 to 7
         lookup gl_i,["Counter"],glcd_msb
	 glcd_msb = glcd_msb - ASCII_OFFSET
	 glcd_cmd = DATA_WR_INC
	 gosub send_1
	next

	' Set Addr Ptr
	glcd_msb = $00
	glcd_lsb = $65
	glcd_cmd = ADDR_PTR_SET
	gosub send_2

	for gl_i = 0 to 6
         lookup gl_i,["Button"],glcd_msb
	 glcd_msb = glcd_msb - ASCII_OFFSET
	 glcd_cmd = DATA_WR_INC
	 gosub send_1
	next


	' Set Addr Ptr
	glcd_msb = $00
	glcd_lsb = $ca
	glcd_cmd = ADDR_PTR_SET
	gosub send_2

	for gl_i = 0 to 33
         lookup gl_i,["By Ranjit Diol using PIC Basic Pro"],glcd_msb
	 glcd_msb = glcd_msb - ASCII_OFFSET
	 glcd_cmd = DATA_WR_INC
	 gosub send_1
	next


	' Set Graphic & Text mode on
	glcd_cmd = TEXT_AND_GRAPH_ON
	gosub send_cmd
gl_tmp = 0
gl_old = 0


'************* MAIN LOOP ******************
'********** Continuous Cycle **************
'******************************************

looper:
'if glcd_btn =1 then		'Debugging code to check if main loop works
'glcd_btn = 0
'pause 200
'else
'glcd_btn = 1
'pause 200
'endif

for gl_l = $f8 to $ff
gl_k = gl_l
gosub design1

	' Set Addr Ptr
	glcd_msb = $00
	glcd_lsb = $6d
	glcd_cmd = ADDR_PTR_SET
	gosub send_2
   if glcd_btn = 1 then
	for gl_i = 0 to 2
          lookup gl_i,["OFF"],glcd_msb
	  glcd_msb = glcd_msb - ASCII_OFFSET
	  glcd_cmd = DATA_WR_INC
	  gosub send_1
	next
     else
	for gl_i = 0 to 2
          lookup gl_i,["ON "],glcd_msb
	  glcd_msb = glcd_msb - ASCII_OFFSET
	  glcd_cmd = DATA_WR_INC
	  gosub send_1
	next
    endif
pause 200
next
     if gl_tmp > 9 then
	gl_tmp = 0
     endif
	' Set Addr Ptr
	glcd_msb = $00
	glcd_lsb = $5d
	glcd_cmd = ADDR_PTR_SET
	gosub send_2
        lookup gl_tmp,["0123456789"],glcd_msb
	glcd_msb = glcd_msb - ASCII_OFFSET
	glcd_cmd = DATA_WR_INC
	gosub send_1
        gl_tmp = gl_tmp + 1
  if gl_old =0 then jmp
        gl_ad1=$14
	gl_ad2=gl_old
	gosub setadr
	gl_k = $00
	gosub write1
jmp:	
	gl_ad1=$14
	gl_ad2=$3b+gl_tmp
	gl_old =gl_ad2
	gosub setadr
	gl_k = %11111111
	gosub write1

goto looper

'*********** Keeping on looping forever ****


end
'******** END OF MAIN PROGRAM **************