;********************************************************************
;====================================================================
;Program:non_effic_gfx.asm
;programmer(s): Dincer Aydin 
;function:Displays bitmap image on LCD
;====================================================================
;********************************************************************
; Example presented here require that the KS0108 cotrolled 128*64 LCD is connected to an
; 8255 with base address of 00h.
; This program was tested on a Powertip PG12864-D 128*64 Graphic LCD
; The Z80 was clocked at 2 MHz
;
; Connections:
; LCD data bus(pins #14-#7) connected to Port A of an 8255 with 00h base address
; LCD Enable pin(#6) connected to Port C bit #7 of the 8255
; LCD R/W pin(#5) connected to Port C bit #6 of the 8255
; LCD RS pin(#4) connected to Port C bit #5 of the 8255
; CSA Chip selection driver 1 connected to Port C bit #4 of the 8255
; CSB Chip selection driver 2 connected to Port C bit #3 of the 8255

;8255 port address(base 00h):	
	paadr equ 00h
	pbadr equ 01h
	pcadr equ 02h
	cwadr equ 03h
;stuff to be written into the control word of the 8255:
;Some of the change the state of the ports and some manipulate
;bits on port C
	allpsin equ 9bh
	paincout equ 90h
	pandcout equ 80h
	pacoutbin equ 82h
	enable equ 0fh
	disable	equ 0eh
	read equ 0dh
	write equ 0ch
	command equ 0ah
	data equ 0bh	
	
;initialization:		
	ld 	sp,200h ;Set stack pointer
	ld 	c,cwadr 
	ld 	a,pacoutbin ;Ports A&C out,B in
	out 	(c),a
;====================================================================
;number of commands and image location:
	numofc equ 4h
	image equ 300h
;*********it all begins here**********:
	call 	choose_right
	call 	prepare_lcd
	
	call 	clear
	call 	prepare_lcd
	call 	choose_left
	call 	clear
	call 	prepare_lcd

	ld 	hl,image
	call 	load_graph
	call 	choose_right
	call 	load_graph
	halt

;***********************************************
;commands to prepare KS0108 for graphic loading
;these will set page address,display start address
;and y adress
;***********************************************
prepare_lcd:		
	ld 	hl,combegadr
	ld 	b,numofc
nextcom:
	call 	sendcom
	inc 	hl
	dec 	b
	jp 	nz,nextcom
	ret

;====================================================================
; Subroutine name:load_graph
; programmer:Dincer Aydin
; input:HL loaded with image location
; output:
; Registers altered: many
; function:starting from (HL) will load the first 512 bayts of a bitmap 
; image	and will fill the half of the display (64*64 pixels) 
; Statrs from the first byte of the 8th page, then the first byte of the 7th
; page, their first byte of the sixth page... and when all pages have their first
; byte each page is given its second byte and so on. 
; See the animated gif on
; http://www.geocities.com/SiliconValley/Circuit/8882/lcd/gfxhowto.htm 	
; It demonstrates how this routine works, but It starts from page 0 ...   	 			
;===================================================================
load_graph:
	ld 	a,40h	; Set Y address command		
nxtcol:	
	ld 	b,8	; 			
nxtpage:
		
	push 	af	
	call 	sendchar
	pop	af

	call	sendcomA	; set Y address command

	push 	af
	ld	a,0B7h
	add	a,b		
	call 	sendcomA	; set page command
	pop 	af	
	inc 	hl
	djnz 	nxtpage
	inc 	a
	cp   	80h		; 80-
	jp	nz,nxtcol
	ret
 	
;***********************************************
; routine to select the left part of the display
;***********************************************
choose_left:
	push 	bc
	ld 	c,pcadr		
	ld 	b,08h
	out 	(c),b
	pop	bc
	ret
	    
;***********************************************
;routine to select the right part of the display
;***********************************************
choose_right:
	push 	bc
	ld 	c,pcadr	
	ld 	b,10h
	out 	(c),b
	pop	bc
	ret

;***********************************
;routine to clear the display
;***********************************
clear:  
	ld 	a,0b8h
	ld 	e,a
dgrstr:	ld 	a,e
	ld 	b,40h
	call 	sendcomA	
sil:	ld 	a,00h
	call 	sendcharA
	djnz 	sil
	inc 	e
	ld 	a,0c0h
	cp 	a,e
	jp 	nz,dgrstr
	ret		

;====================================================================
;  Subroutine name:sendcomA & sendcom & sendcharA & sendchar
;  programmer:Caner Buyuktuna & Dincer Aydin
;  input:A or (HL)
;  output:
;  Registers altered:A
;  function:    sendcharA sends the data in A to the LCD
;               sendchar sends the data in (HL) to the LCD
;               sendcomA sends the command in A to the LCD
;               sendcom sends the command in (HL) to the LCD
; !!!!!!!!!!- The busy flag is not checked -!!!!!!!!!!
;====================================================================
sendchar:
        ld      a,(hl)          ; put the data to be sent to the LCD in A
sendcharA:    
        push    bc              ; save BC
        push    de              ; save DE
        ld      e,data          
        jp      common

sendcom:
        ld      a,(hl)
sendcomA:     
        push    bc              ; save BC
        push    de              ; save DE 
        ld      e,command        

common:
        ld      c,cwadr
        out     (c),e           ; Set/reset RS accoring to the content of register E
        ld      d,write       
        out     (c),d           ; reset RW pin for writing to LCD
        out     (paadr),a       ; place data/instrucrtion to be written into portA
        ld      d,enable      
        out     (c),d           ; enable the LCD
        ld      d,disable     
        out     (c),d           ; disable the LCD
        pop     de              ; restore DE
        pop     bc              ; restore BC
        ret                     ; return
combegadr:
	db 	3fh,40h,0b8h,0c0h