
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;											;
;	text scroller version 1.0				;
;	by brad slattery 2008					;
;											;
;	a text scroller for the 8x8 game board	;
;											;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


	LIST p=16f648a 				;	tell assembler what chip we are using
	include "P16f648a.inc"		;	include the defaults for the chip
	__config 0x3f18				;	sets the configuration settings (oscillator type etc.)

PC equ 0x02						;	The program counter will be refered to as PC

	cblock 0x20				;	start of general purpose registers - this is where we start defining variable names
		counta				;	used in the delay routines
		countb 				;	used in the delay routines
		pc_data				;	used in the display data program counter
		vram_1				;	a video ram location
		vram_2				;	a video ram location
		vram_3				;	a video ram location
		vram_4				;	a video ram location
		vram_5				;	a video ram location
		vram_6				;	a video ram location
		vram_7				;	a video ram location
		vram_8				;	a video ram location
		vtemp_1				;	a temporary video ram location (used when tranfering vram data to the next vram location)
		vtemp_2				;	a temporary video ram location (used when tranfering vram data to the next vram location)
		vtemp_3				;	a temporary video ram location (used when tranfering vram data to the next vram location)
		vtemp_4				;	a temporary video ram location (used when tranfering vram data to the next vram location)
		vtemp_5				;	a temporary video ram location (used when tranfering vram data to the next vram location)
		vtemp_6				;	a temporary video ram location (used when tranfering vram data to the next vram location)
		vtemp_7				;	a temporary video ram location (used when tranfering vram data to the next vram location)
		repeat_frame		;	used to determine how many times we will be repeating each 'frame'
	endc

	org 0x0000					; org sets the start address for our program 0000 hex


	movlw h'07'					;	turn comparators off						
	movwf CMCON					;	this makes all ports digital

	bsf STATUS, RP0 			; select bank 1 (so we can edit some status bits)
	movlw b'00000000' 			; set PORTB all outputs
	movwf TRISB					;
	movlw b'00100000' 			; set PORTA all outputs except for bit 5
	movwf TRISA 				; remember bit 5 cannot be an output
	bcf STATUS, RP0 			; select bank 0

	goto setup

text_data
	incf pc_data, 1			;	increment pc_data by one and then
	movf pc_data, w			;	move it into our working register THEN
	addwf PC				;	add this number to our program counter
	nop						;	skip one step...
	retlw b'00110110'		;	now each time this routine is called, we will grab the
	retlw b'01001001'		;	next successive byte of data!
	retlw b'01001001'
	retlw b'00110110'
	retlw b'00000000'
	retlw b'00000101'
	retlw b'00000010'
	retlw b'00000101'
	retlw b'00000000'
	retlw b'00110110'
	retlw b'01001001'
	retlw b'01001001'
	retlw b'00110110'
	retlw b'00000000'
	retlw b'00000000'
	retlw b'00000000'
	retlw b'00111110'
	retlw b'01000001'
	retlw b'01000101'
	retlw b'01000101'
	retlw b'00100110'
	retlw b'00000000'
	retlw b'00111111'
	retlw b'01000100'
	retlw b'01000100'
	retlw b'01000100'
	retlw b'00111111'
	retlw b'00000000'
	retlw b'00111111'
	retlw b'01000000'
	retlw b'00111100'
	retlw b'01000000'
	retlw b'00111111'
	retlw b'00000000'
	retlw b'01111111'
	retlw b'01001001'
	retlw b'01001001'
	retlw b'01000001'
	retlw b'00000000'
	retlw b'00000000'
	retlw b'00000000'
	retlw b'01111111'
	retlw b'01001001'
	retlw b'01001001'
	retlw b'01001001'
	retlw b'00110110'
	retlw b'00000000'
	retlw b'00111110'
	retlw b'01000001'
	retlw b'01000001'
	retlw b'01000001'
	retlw b'00111110'
	retlw b'00000000'
	retlw b'00111111'
	retlw b'01000100'
	retlw b'01000100'
	retlw b'01000100'
	retlw b'00111111'
	retlw b'00000000'
	retlw b'01111111'
	retlw b'01001000'
	retlw b'01001000'
	retlw b'01001000'
	retlw b'00110111'
	retlw b'00000000'
	retlw b'01111111'
	retlw b'01000001'
	retlw b'01000001'
	retlw b'01000001'
	retlw b'00111110'
	retlw b'00000000'
	retlw b'00000011'
	retlw b'00000011'
	retlw b'00000000'
	retlw b'00000000'
	retlw b'00000000'
	retlw b'00000000'
	retlw b'00000000'
	retlw b'00000000'
	retlw b'00000000'
	retlw b'00000000'
	retlw b'00000000'
	movlw h'01'			;	and now reset our pc_data variable so that we can
	movwf pc_data		;	draw the text again from the start
	return				;	return to our main program


setup						;	Okay, lets get everything setup.
	movlw b'11011010'		;	This disables all 74373 outputs, and closes
	movwf PORTA				;	all 74373 latches.
	clrf vram_1				;	these next lines clear our video ram.
	clrf vram_2				;	if we didnt clear them, then we would get random
	clrf vram_3				;	dots on our screen on startup
	clrf vram_4				;	experiment with not
	clrf vram_5				;	clearing all these vrams and see what happens!)
	clrf vram_6				;	....
	clrf vram_7				;	....
	clrf vram_8				;	....
	clrf pc_data			;	clear pc_data (so we start from the top)


begin							;	Our main program!
	call display				;	call the display routine
	call fill_vram				;	call the fill video ram routine
	goto begin					;	do it all again!




display	
			movlw d'06'						;	This determines how many times to repeat each frame (more frames = slower speed)
			movwf repeat_frame				;	so we grab that data from speed and copy it to our frame_rate
loop		movf vram_1, w					;	Now we grab the first COLUMN of data from vram_1.
			movwf PORTB						;	then we copy it to PORTB
			bsf PORTA, 0					;	now that its in PORTB we need to latch it to the red memory.
			bcf PORTA, 0					;	so the latch was opened, now we need to close it (the data will now stay there)
				movlw b'10000000'			;	This now activates the rightmost column of anodes by moving
				movwf PORTB					;	'10000000' to PORTB, 	
				bsf PORTA, 4				;	then latching it onto the COLUMN data latch
				bcf PORTA, 4				;	then closing the latch (the data is now held there)
			bcf PORTA, 6					;	Now that all our data is ready, we can enable our 74373 outputs.
			bcf PORTA, 1					;	PORTA, 6 is the COLUMN data enable - PORTA, 1 is the red data enable
			call delay						;	Call the delay (to hold that one column ON for a split second)
			bsf PORTA, 6					;	Now disable both outputs (remember PORTA, 6 is the COLUMN data
			bsf PORTA, 1					;	and PORTA, 1 is the red data)
										

			movf vram_2, w					;	Now we grab the second COLUMN of data from vram_2.
			movwf PORTB						;	then we copy it to PORTB
			bsf PORTA, 0					;	now that its in PORTB we need to latch it to the red memory.
			bcf PORTA, 0					;	so the latch was opened, now we need to close it (the data will now stay there)
				movlw b'01000000'			;	This now activates the next column of anodes
				movwf PORTB					;	in sequence from the right
				bsf PORTA, 4				;	then latching it onto the COLUMN data latch
				bcf PORTA, 4				;	then close the latch (the data is now held there)
			bcf PORTA, 6					;	Now that all our data is ready, we can enable our 74373 outputs.
			bcf PORTA, 1					;	PORTA, 6 is the COLUMN data enable - PORTA, 1 is the red data enable
			call delay						;	Call the delay (to hold that one column ON for a split second)
			bsf PORTA, 6					;	Now disable both outputs (remember PORTA, 6 is the COLUMN data
			bsf PORTA, 1					;	and PORTA, 1 is the red data)

			movf vram_3, w					;	Now we grab the second COLUMN of data from vram_3.
			movwf PORTB						;	then we copy it to PORTB
			bsf PORTA, 0					;	now that its in PORTB we need to latch it to the red memory.
			bcf PORTA, 0					;	so the latch was opened, now we need to close it (the data will now stay there)
				movlw b'00100000'			;	This now activates the next column of anodes
				movwf PORTB					;	in sequence from the right
				bsf PORTA, 4				;	then latching it onto the COLUMN data latch
				bcf PORTA, 4				;	then close the latch (the data is now held there)
			bcf PORTA, 6					;	Now that all our data is ready, we can enable our 74373 outputs.
			bcf PORTA, 1					;	PORTA, 6 is the COLUMN data enable - PORTA, 1 is the red data enable
			call delay						;	Call the delay (to hold that one column ON for a split second)
			bsf PORTA, 6					;	Now disable both outputs (remember PORTA, 6 is the COLUMN data
			bsf PORTA, 1					;	and PORTA, 1 is the red data)

			movf vram_4, w					;	Now we grab the second COLUMN of data from vram_4.
			movwf PORTB						;	then we copy it to PORTB
			bsf PORTA, 0					;	now that its in PORTB we need to latch it to the red memory.
			bcf PORTA, 0					;	so the latch was opened, now we need to close it (the data will now stay there)
				movlw b'00010000'			;	This now activates the next column of anodes
				movwf PORTB					;	in sequence from the right
				bsf PORTA, 4				;	then latching it onto the COLUMN data latch
				bcf PORTA, 4				;	then close the latch (the data is now held there)
			bcf PORTA, 6					;	Now that all our data is ready, we can enable our 74373 outputs.
			bcf PORTA, 1					;	PORTA, 6 is the COLUMN data enable - PORTA, 1 is the red data enable
			call delay						;	Call the delay (to hold that one column ON for a split second)
			bsf PORTA, 6					;	Now disable both outputs (remember PORTA, 6 is the COLUMN data
			bsf PORTA, 1					;	and PORTA, 1 is the red data)

			movf vram_5, w					;	Now we grab the second COLUMN of data from vram_5.
			movwf PORTB						;	then we copy it to PORTB
			bsf PORTA, 0					;	now that its in PORTB we need to latch it to the red memory.
			bcf PORTA, 0					;	so the latch was opened, now we need to close it (the data will now stay there)
				movlw b'00001000'			;	This now activates the next column of anodes
				movwf PORTB					;	in sequence from the right
				bsf PORTA, 4				;	then latching it onto the COLUMN data latch
				bcf PORTA, 4				;	then close the latch (the data is now held there)
			bcf PORTA, 6					;	Now that all our data is ready, we can enable our 74373 outputs.
			bcf PORTA, 1					;	PORTA, 6 is the COLUMN data enable - PORTA, 1 is the red data enable
			call delay						;	Call the delay (to hold that one column ON for a split second)
			bsf PORTA, 6					;	Now disable both outputs (remember PORTA, 6 is the COLUMN data
			bsf PORTA, 1					;	and PORTA, 1 is the red data)

			movf vram_6, w					;	Now we grab the second COLUMN of data from vram_6.
			movwf PORTB						;	then we copy it to PORTB
			bsf PORTA, 0					;	now that its in PORTB we need to latch it to the red memory.
			bcf PORTA, 0					;	so the latch was opened, now we need to close it (the data will now stay there)
				movlw b'00000100'			;	This now activates the next column of anodes
				movwf PORTB					;	in sequence from the right
				bsf PORTA, 4				;	then latching it onto the COLUMN data latch
				bcf PORTA, 4				;	then close the latch (the data is now held there)
			bcf PORTA, 6					;	Now that all our data is ready, we can enable our 74373 outputs.
			bcf PORTA, 1					;	PORTA, 6 is the COLUMN data enable - PORTA, 1 is the red data enable
			call delay						;	Call the delay (to hold that one column ON for a split second)
			bsf PORTA, 6					;	Now disable both outputs (remember PORTA, 6 is the COLUMN data
			bsf PORTA, 1					;	and PORTA, 1 is the red data)

			movf vram_7, w					;	Now we grab the second COLUMN of data from vram_7.
			movwf PORTB						;	then we copy it to PORTB
			bsf PORTA, 0					;	now that its in PORTB we need to latch it to the red memory.
			bcf PORTA, 0					;	so the latch was opened, now we need to close it (the data will now stay there)
				movlw b'00000010'			;	This now activates the next column of anodes
				movwf PORTB					;	in sequence from the right
				bsf PORTA, 4				;	then latching it onto the COLUMN data latch
				bcf PORTA, 4				;	then close the latch (the data is now held there)
			bcf PORTA, 6					;	Now that all our data is ready, we can enable our 74373 outputs.
			bcf PORTA, 1					;	PORTA, 6 is the COLUMN data enable - PORTA, 1 is the red data enable
			call delay						;	Call the delay (to hold that one column ON for a split second)
			bsf PORTA, 6					;	Now disable both outputs (remember PORTA, 6 is the COLUMN data
			bsf PORTA, 1					;	and PORTA, 1 is the red data)

			movf vram_8, w					;	Now we grab the second COLUMN of data from vram_8.
			movwf PORTB						;	then we copy it to PORTB
			bsf PORTA, 0					;	now that its in PORTB we need to latch it to the red memory.
			bcf PORTA, 0					;	so the latch was opened, now we need to close it (the data will now stay there)
				movlw b'00000001'			;	This now activates the next column of anodes
				movwf PORTB					;	in sequence from the right
				bsf PORTA, 4				;	then latching it onto the COLUMN data latch
				bcf PORTA, 4				;	then close the latch (the data is now held there)
			bcf PORTA, 6					;	Now that all our data is ready, we can enable our 74373 outputs.
			bcf PORTA, 1					;	PORTA, 6 is the COLUMN data enable - PORTA, 1 is the red data enable
			call delay						;	Call the delay (to hold that one COLUMN ON for a split second)
			bsf PORTA, 6					;	Now disable both outputs (remember PORTA, 6 is the COLUMN data
			bsf PORTA, 1					;	and PORTA, 1 is the red data)
		decfsz repeat_frame					;	then decrease repeat_frame by one, 
	goto loop								;	if its not zero then draw it all again!
	return									;	if it is zero, then go back to where we came from...


fill_vram
		movf vram_1, 0		;	Copy vram_1 into vtemp_1 to use as a backup
		movwf vtemp_1		;	storage location. (just before we overwrite vram_1)
		movf vram_2, 0		;	Copy vram_1 into vtemp_2 to use as a backup
		movwf vtemp_2		;	storage location. (just before we overwrite vram_2)
		movf vram_3, 0		;	Copy vram_1 into vtemp_3 to use as a backup
		movwf vtemp_3		;	storage location. (just before we overwrite vram_3)
		movf vram_4, 0		;	Copy vram_1 into vtemp_4 to use as a backup
		movwf vtemp_4		;	storage location. (just before we overwrite vram_4)
		movf vram_5, 0		;	Copy vram_1 into vtemp_5 to use as a backup
		movwf vtemp_5		;	storage location. (just before we overwrite vram_5)
		movf vram_6, 0		;	Copy vram_1 into vtemp_6 to use as a backup
		movwf vtemp_6		;	storage location. (just before we overwrite vram_6)
		movf vram_7, 0		;	Copy vram_7 into vtemp_7 to use as a backup
		movwf vtemp_7		;	storage location. (just before we overwrite vram_7)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;																	;
;	Did you notice that we don't need to make a backup of vram_8?	;
;	That's because there are only 8 lines on the screen. So after 	;
;	we display the 8th line, it is then shifted out of the screen.	;
;																	;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;																	;
;	Now that we have backed up our old vram data, we then need to	;
;	copy them to the next successive vram location - this basically	;
;	shifts everything on the screen down one space. It also grabs	;
;	a brand new byte of data and copies it into vram_1 (which		;
;	means it will be displayed at the top of the screen, before		;
;	It gets shifted again...										;
;																	;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

	call text_data		;	Call track_data routine and return with a byte of data in the w register
	movwf vram_1		;	then copy the new byte of data to the first vram location
	movf vtemp_1, 0		;	copy what was in vram_1 into vram_2 (remember how we made
	movwf vram_2		;	a backup of vram_1 and called it vtemp_1.)
	movf vtemp_2, 0		;	copy what was in vram_2 into vram_3 (remember how we made
	movwf vram_3		;	a backup of vram_2 and called it vtemp_2.)
	movf vtemp_3, 0		;	copy what was in vram_3 into vram_4 (remember how we made
	movwf vram_4		;	a backup of vram_3 and called it vtemp_3.)
	movf vtemp_4, 0		;	copy what was in vram_4 into vram_5 (remember how we made
	movwf vram_5		;	a backup of vram_4 and called it vtemp_4.)
	movf vtemp_5, 0		;	copy what was in vram_5 into vram_6 (remember how we made
	movwf vram_6		;	a backup of vram_5 and called it vtemp_5.)
	movf vtemp_6, 0		;	copy what was in vram_6 into vram_7 (remember how we made
	movwf vram_7		;	a backup of vram_6 and called it vtemp_6.)
	movf vtemp_7, 0		;	copy what was in vram_7 into vram_8 (remember how we made
	movwf vram_8		;	a backup of vram_7 and called it vtemp_7.)
	return				;	Now that we're all done here, go back to our main program.



delay								;	This delay is a rather fast one.
		movlw d'03'					;	You can make the delay longer by
		movwf counta				;	increasing the decimal value. Or you
		movwf countb				;	can make the delay shorter by decreasing
again	decfsz counta, 1			;	the decimal value.
	goto again						;
		decfsz countb, 1			;
	goto again						;	once counta and countb have reached zero
	return							;	it will return to the main program


	end								;	That's it!
