'****************************************************************************
'GLIPICW.BAS Graphic application for use with a Samsung KS0108 (or compatible)
'graphic LCD controller connected to a Microchip(TM) PIC 16F877 microcontroller
'Written in MELabs PicBasicPro(TM) Ver 3.32
'Beta version 0.8.0
'GLiPIC.exe Beta 0.8.0 is an MS Windows based interface that is used in conjunction
'with GLIPICW.BAS
'================== NOT FOR COMMERICIAL USE =================================
'
'       Author: Ranjit Diol - COMPSys LLC, March 2000
'            (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 LLC shall be held liable for any damages caused
'   by its use.
'
'   LICENSE: This application may be used in its entirety or 
'   in parts within some other non-commercial application(s) as long
'   as the author is given credit for those parts used.
'
'        Contact: rsdiol@compsys1.com for more information
'
'************************************************************************
'                  IMPORTANT, PLEASE NOTE THE FOLLOWING
'This application assumes you have a 64KBit external eeprom connected
'via I2C. Without that you will only be able to send images directly
'to the LCD display and not be able to store them -- See the readme.txt
'for the Windows GLiPIC interface.
'
'Adjust the PIN assignments as neccessary for your prototype
'This was tested using a 20MHz xtal if you use a different OSC speed
'you may have to make some adjustement in the 'strobe' subroutine.
'************************************************************************


DEFINE	ONINT_USED	1	'Required if using ISP
DEFINE OSC 20			'OSC speed, you may have to tweak the 'strobe'
				'routine's e_pause constant for other speeds
ADCON1	= 7			'Make all pins digital, you may adjust as needed


lcd_dat	 VAR 	PORTD		'LCD bus Pins 7-14 LSB-MSB
scl	 VAR 	PORTC.3		'I2C SCL  for ext eeprom 
sda	 VAR	PORTC.4		'I2C SDA for ext eeprom
in_pin   VAR    PORTC.7         'Serial input pin
out_pin  VAR    PORTC.6         'Serial output pin
lcd_e	 VAR 	PORTC.0		'Enable pin on LCD
lcd_cd	 VAR	PORTC.1		'Data/Command Pin 4 on LCD
lcd_rw	 VAR 	PORTC.2		'Read/Write Pin 5 on LCD
lcd_cs1	 VAR 	PORTB.1		'ChipSelect1 Pin 15 on LCD
lcd_cs2	 VAR	PORTB.2		'ChipSelect2 Pin 16 on LCD
lcd_rst	 VAR	PORTC.5		'Reset Pin 17 on LCD

'Set pins for output
TRISB.0  = 0
TRISB.1  = 0
TRISB.2  = 0
TRISD	 = 0
TRISC.0	 = 0
TRISC.1	 = 0
TRISC.2	 = 0
TRISC.3	 = 0
TRISC.4	 = 0
TRISC.5	 = 0

'Constants used
ser_baud  CON    84             '9600 baud serout/serin
ctl       CON    $A0		'EEprom control code
row 	  CON	 $b8		'LCD page 0
last_row  CON    $bf		'LCD page 7
col	  CON    $40	        'Line byte position 0
last_col  CON    63             'Last column (1-64)
first_col CON    0		'First column
max_col   CON    128            'Last column (1-127)
max_line  CON    8		'Line 8 (based on 1-8)
max_pos   CON    64             'Column 64 positon per side (1-64)
cr        CON    13		'CR for serout
lf        CON    10		'LF for serout
disp_on   CON    $3f		'LCD Display ON
disp_off  CON    $3e            'LCD Display OFF
disp_ram  CON    $c0            'Ram Display 0 (Page 0 at top of display) 
blank     CON    $00		'Blank character
e_pause	  CON    6		'Pauseus 6 for Strobe routine

'Word variables used
eepaddr  VAR    WORD
addr     VAR    WORD

'Arrays used
in_array VAR    byte[32]
in_ctl   VAR    byte[8]

'Byte Variables used
buff_count VAR  BYTE	'buffer count
hex_nibble VAR  BYTE	'hex nibble from serin
in_ascii   VAR  BYTE	'ASCII char from serin
buf_cnt    VAR  BYTE	'buffer counter
byte_pos   VAR  BYTE	'To keep track of a byte's position
in_byte    VAR  BYTE	'The incoming byte
tmp	   VAR	BYTE	'Temporary var
index	   VAR	BYTE	'Index for arrays
j	   VAR  BYTE	'General counter
k	   VAR  BYTE	'General counter
line	   VAR  BYTE	'An LCD row
delay      VAR  BYTE	'Execution delay, used with 'pause'

'Initialize variables
hex_nibble = 0
byte_pos   = 0
delay      = 10
in_byte    = 0
tmp        = 0
index      = 0


'Reset LCD
lcd_dat = 0	' Clear PORTD
lcd_cd =  0
lcd_rw =  0
lcd_e =   0
lcd_cs1 = 1
lcd_cs2 = 0
lcd_rst = 1
pause 100	'Let things  stabilize
lcd_rst = 0
pause 10	' Reset LCD
lcd_rst = 1
pause  500


'Jump over subroutines to main program
goto main

' **** (GO)SUB ROUTINES ****

strobe:
	lcd_e = 1
	pauseus e_pause
	lcd_e = 0
return

clearall:
	lcd_cd = 0		' Command mode
	lcd_dat = disp_off	' Display Off
	gosub strobe
	lcd_cs1=1
	lcd_cs2=0
	for index = 1 to 2
          for j = row to last_row
	        lcd_cd = 0	        'Command mode
 	        gosub strobe	' Write the data
	        lcd_dat = col	' Column address = 0
	        gosub strobe
	        lcd_dat = j
	        gosub strobe	
	        lcd_cd = 1		' Write mode
	          for k = first_col to last_col
	             lcd_dat = blank
	             gosub strobe
	          next
	  next
	  swap lcd_cs1,lcd_cs2
        next

	lcd_cs1=0
	lcd_cs2=1
	lcd_cd=0
	lcd_dat=row
	gosub strobe
	lcd_dat = disp_ram	' Ram Line 0
	gosub strobe
	lcd_dat=col
	gosub strobe
	lcd_cs1=1
	lcd_cs2=0
	lcd_dat=row
	gosub strobe
	lcd_dat = disp_ram	' Ram Line 0
	gosub strobe
	lcd_dat=col
	gosub strobe
	lcd_dat = disp_on	'display on
	gosub strobe
	lcd_cd = 1		' Set Data command
	lcd_cs1 = 1		' Left side active
	lcd_cs2 = 0

return	


init:			'Initialization

	lcd_cd = 0			' Set command mode
	lcd_cs1 = 1			' Left Side on
	lcd_cs2 = 0			' Right Side off	
         for index = 1 to 2
	   lcd_dat = disp_off	' Display Off
	   lcd_dat = disp_ram	' Ram Line 0
	   gosub strobe		' Write the data
	   lcd_dat = col		' Y address = 0
	   gosub strobe
	   lcd_dat = row		' Page = 0
	   gosub strobe
	   lcd_dat = disp_on	' Display On
	   gosub strobe
	   swap lcd_cs1,lcd_cs2
         next
	lcd_cs1=1
	lcd_cs2=0


return

'****Place char on LCD Routine *****
'Place byte of data on lcd assumes in_byte, byte_pos and line (line)
'Char position on LCD byte_pos = 0-127 (Horiz), ROW 0-7 (vert)

putbyte: 
	lcd_dat = in_byte		'Display the byte
	gosub strobe   
	byte_pos=byte_pos+1	'Increment position

	'Now do some LCD house cleaning and adjust counters
	if byte_pos=max_pos then
	   lcd_cs1=0
	   lcd_cs2=1
	   lcd_cd = 0
	   lcd_dat = col
	   gosub strobe
	   lcd_dat = disp_ram
	   gosub strobe
	   lcd_dat = row + line
	   gosub strobe
	   lcd_cd = 1
	endif
     if byte_pos = max_col then	'Check if
	   line = line + 1		'New Line
              if line = max_line then
	        line = 0
              endif
    	byte_pos = 0		'Reset byte_pos
        lcd_cs1=1
	lcd_cs2=0
	lcd_cd = 0
	lcd_dat=col
	gosub strobe
	lcd_dat = row + line
	gosub strobe
	lcd_dat = disp_ram
	gosub strobe
        lcd_cd =1 
     endif
  
return

'***** Convert incoming ascii to hex byte Routine *****
find:
Lookdown in_array[index],["0123456789abcdef"],hex_nibble
return	


'===============================
' **** BEGIN MAIN PROGRAM ******
'===============================
	
main:
	gosub init	' Initialize LCD
	gosub clearall	' Clear all pages
goto term

logo:	gosub init	' Initialize LCD
	gosub clearall	' Clear all pages



'**** DISPLAY IMAGES IN EXTERNAL 64KBit EEPROM VIA I2C *****

' Load opening screen from eeprom assuming a 64KBit eeprom

	byte_pos=0
	line =0
	for addr = 0 to 8192		'Eight 1kbyte pages of eeprom
        I2CREAD sda,scl,ctl,addr,[in_byte]
	gosub putbyte

        if (addr=1024) OR (addr=2048) OR (addr= 3072) OR (addr=4096) OR (addr=5120) OR (addr=6144) OR (addr=7168) OR (addr=8192) then
	pause 4000

	gosub init
	gosub clearall
	endif

	if addr=8192 then
	addr = 0
	endif

	next

goto logo		'Continue looping inifitum!

'********************************************

'Terminal Subroutine
term:		'Assumes Home Position

'Setup variables
j=0
index=0
k=0
line=0
addr=0
in_ascii = 0
buff_count = 32
delay = 10
addr = 0
byte_pos = 0

'Get the initial parameters
get_param:
	serin2 in_pin,ser_baud,[wait ("*"),STR in_ctl\9]
	for index = 0 to 8
        Lookdown in_ctl[index],["0123456789abcdef"],hex_nibble
	in_ctl[index]=hex_nibble
	next
	delay = (in_ctl[7]<<4) | in_ctl[8]
	buff_count = (in_ctl[1]<<4) | in_ctl[2]
	addr.byte1 = (in_ctl[3] <<4) | in_ctl[4]
	addr.byte0 = (in_ctl[5] <<4) | in_ctl[6]
	buf_cnt = (buff_count - 1)
        eepaddr = addr
	j=in_ctl[0]
	if j = 0 then lcd_loop 		'Display directly on LCD
	if j = 1 then eep_loop		'Load ext eeprom
	if j = 2 then logo		'Display images loop
	goto get_param     




eep_loop:
	 
	 serin2 in_pin,ser_baud,[wait ("]"),STR in_array\buff_count] 	'Wait for ] and the load in_array

	 for index = 0 to buf_cnt
                'Get char and place in array
	        Lookdown in_array[index],["0123456789abcdef"],hex_nibble
		in_array[index]=hex_nibble
	 next

	for index = 0 to buf_cnt step 2
		in_byte = (in_array[index]<<4) | (in_array[index+1])	'Form a hex number MSB-LSB
	        I2CWRITE sda,scl,ctl,eepaddr,[in_byte]
	        pause 10
                eepaddr=eepaddr+1                
	next
goto eep_loop

lcd_loop:   
	 serin2 in_pin,ser_baud,[wait ("]"),STR in_array\buff_count] 	'Wait for ] and the load in_array

	 for index = 0 to (buff_count - 1)
                gosub find			'Get char and place in array
	        in_array[index]=hex_nibble
	 next
	
	for index = 0 to (buff_count - 1) step 2
		in_byte = (in_array[index]<<4) | (in_array[index+1])	'Form a hex number MSB-LSB
	        gosub putbyte 
	
	
	next


goto lcd_loop

'*********** E N D ************
end
' **** END OF MAIN PROGRAM ****