
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;										;
;	bouncing balls ver 1.0				;
;	by brad slattery 2008				;
;										;
;	bouncing balls demonstration for	;
;	the 8x8 game system					;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


	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 h'02'						; The program counter is now called PC

	cblock h'20' 				;	start of general purpose registers
		counta					;	used in the delay routine
		countb 					;	used in the delay routine
		ball_x_green			;	holds the data for the green ball, x co-ordinate
		ball_y_green			;	holds the data for the green ball, y co-ordinate
		ball_up_green			;	holds the data for the green ball, up movement		
		ball_down_green			;	holds the data for the green ball, down movement	
		ball_left_green			;	holds the data for the green ball, left movement
		ball_right_green		;	holds the data for the green ball, right movement
		ball_x_red				;	holds the data for the red ball, x co-ordinate
		ball_y_red				;	holds the data for the red ball, y co-ordinate
		ball_up_red				;	holds the data for the red ball, up movement		
		ball_down_red			;	holds the data for the red ball, down movement	
		ball_left_red			;	holds the data for the red ball, left movement
		ball_right_red			;	holds the data for the red ball, right movement
		ball_x_orange			;	holds the data for the orange ball, x co-ordinate
		ball_y_orange			;	holds the data for the orange ball, y co-ordinate
		ball_up_orange			;	holds the data for the orange ball, up movement		
		ball_down_orange		;	holds the data for the orange ball, down movement	
		ball_left_orange		;	holds the data for the orange ball, left movement
		ball_right_orange		;	holds the data for the orange ball, right movement
		ball_refresh_green		;	green ball refresh data
		ball_refresh_red		;	red ball refresh data
		ball_refresh_orange		;	orange ball refresh data
		endc

	org h'0000'						;	This sets our start point at address 0000 hex


	movlw h'07'
	movwf CMCON 					;	turn comparators off

	bsf STATUS, RP0 				;	select bank 1 (So we can modify 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 					;
	bcf STATUS, RP0 				;	and back to bank 0 again (ready for our program!)




setup								;	Here we will setup our variables and ports with data
	movlw b'11011010'				;	This disables all 74373 outputs, and closes
	movwf PORTA						;	all 74373 latches.
	movlw b'00100000'				;	These next four lines setup the x and y
	movwf ball_x_green				;	co-ordinates for the starting position
	movlw b'10000000'				;	of the green ball.
	movwf ball_y_green				;
	movlw b'00001000'				;	These next four lines setup the x and y
	movwf ball_x_red				;	co-ordinates for the starting position
	movlw b'10000000'				;	of the red ball
	movwf ball_y_red				;	
	movlw b'10000000'				;	These next four lines setup the x and y	
	movwf ball_x_orange				;	co-ordinates for the starting position
	movlw b'00000000'				;	of the orange ball
	movwf ball_y_orange				;
	clrf ball_up_green				;	These next 12 lines clear all
	clrf ball_down_green			;	the three coloured balls direction
	clrf ball_left_green			;	information. (Then we can set which
	clrf ball_right_green			;	direction the balls go on start-up)
	clrf ball_up_red				;	...
	clrf ball_down_red				;	...
	clrf ball_left_red				;	...
	clrf ball_right_red				;	...
	clrf ball_up_orange				;	...
	clrf ball_down_orange			;	...
	clrf ball_left_orange			;	...
	clrf ball_right_orange			;	...
	bsf ball_down_green, 0			;	Sets the green ball to move down AND
	bsf ball_left_green, 0			;	left on startup
	bsf ball_left_red, 0			;	Sets the red ball to move down AND
	bsf ball_down_red, 0			;	left on startup
	bsf ball_right_orange, 0		;	Sets the orange ball to move down AND
	bsf ball_down_orange, 0			;	right on startup
	movlw d'45'						;	These next 6 lines setup how fast each ball will move
	movwf ball_refresh_green		;	you can make the number anything upto 255. The higher
	movlw d'40'						;	the number, the slower the ball speed. This is because
	movwf ball_refresh_red			;	we are telling the ball how many times to display
	movlw d'35'						;	itself before moving (you would notice the orange ball
	movwf ball_refresh_orange		;	moves faster than the red and green...)



begin								;	Our main program now starts!
	call check_balls				;	Run the check_balls routine
	call draw_balls					;	Run the draw_balls routine
	call move_ball_green			;	Run the move_ball_green routine
	call move_ball_red				;	Run the move_ball_red routine
	call move_ball_orange			;	Run the move_ball_orange routine
	goto begin						;	Go back the beginning




check_balls						;	This routine checks to see if any balls have hit a wall
	btfsc ball_y_green, 7		;	has the green ball hit the screen top?
	call set_down_green			;	if it has then call set_down_green routine.
	btfsc ball_y_green, 0		;	has the green ball hit the screen bottom?
	call set_up_green			;	if it has then call set_up_green routine.
	btfsc ball_x_green, 1		;	has the green ball hit the screen left?
	call set_right_green		;	if it has then call the set_right_green routine
	btfsc ball_x_green, 7		;	has the green ball hit the screen right?
	call set_left_green			;	if it has then call the set_left_green routine
	btfsc ball_y_red, 7			;	has the red ball hit the screen top?
	call set_down_red			;	if it has then call set_down_red routine.
	btfsc ball_y_red, 0			;	has the red ball hit the screen bottom?
	call set_up_red				;	if it has then call set_up_red routine.
	btfsc ball_x_red, 1			;	has the red ball hit the screen left?
	call set_right_red			;	if it has then call the set_right_red routine
	btfsc ball_x_red, 7			;	has the red ball hit the screen right?
	call set_left_red			;	if it has then call the set_left_red routine
	btfsc ball_y_orange, 7		;	has the orange ball hit the screen top?
	call set_down_orange		;	if it has then call set_down_orange routine.
	btfsc ball_y_orange, 0		;	has the orange ball hit the screen bottom?
	call set_up_orange			;	if it has then call set_up_orange routine.
	btfsc ball_x_orange, 1		;	has the orange ball hit the screen left?
	call set_right_orange		;	if it has then call the set_right_orange routine
	btfsc ball_x_orange, 7		;	has the orange ball hit the screen right?
	call set_left_orange		;	if it has then call the set_left_orange routine
	return						;	Now return to our main program


move_ball_green							;	This routine will move the green ball
	decfsz ball_refresh_green, f		;	decrement ball_refresh_green by one skip the next line if
	return								;	we have reached zero, otherwise return to the main program
	movlw d'45'							;	set our ball refresh back to decimal 45
	movwf ball_refresh_green			;	(remember the ball wont move until this routine is called 45 times...)
	btfsc ball_up_green, 0				;	Check to see if the ball_up is set, if it is then, 
	rlf ball_y_green, f					;	make the ball move up one space
	btfsc ball_down_green, 0			;	Check to see if the ball_down is set, if it is then,	
	rrf ball_y_green, f					;	make the ball move down one space
	btfsc ball_left_green, 0			;	Check to see if the ball_left is set, if it is then,
	rrf ball_x_green, f					;	make the ball move left one space
	btfsc ball_right_green, 0			;	Check to see if the ball_right is set, if it is then,
	rlf ball_x_green, f					;	make the ball move right one space
	return								;	Now return to the main program


move_ball_red							;	This routine will move the red ball
	decfsz ball_refresh_red, f			;	decrement ball_refresh_red by one skip the next line if
	return								;	we have reached zero, otherwise return to the main program
	movlw d'40'							;	set our ball refresh back to decimal 40
	movwf ball_refresh_red				;	(remember the ball wont move until this routine is called 40 times...)
	btfsc ball_up_red, 0				;	Check to see if the ball_up is set, if it is then, 
	rlf ball_y_red, f					;	make the ball move up one space
	btfsc ball_down_red, 0				;	Check to see if the ball_down is set, if it is then,	
	rrf ball_y_red, f					;	make the ball move down one space
	btfsc ball_left_red, 0				;	Check to see if the ball_left is set, if it is then,
	rrf ball_x_red, f					;	make the ball move left one space
	btfsc ball_right_red, 0				;	Check to see if the ball_right is set, if it is then,
	rlf ball_x_red, f					;	make the ball move right one space
	return								;	Now return to the main program


move_ball_orange							;	This routine will move the red ball
	decfsz ball_refresh_orange, f			;	decrement ball_refresh_orange by one skip the next line if
	return									;	we have reached zero, otherwise return to the main program
	movlw d'35'								;	set our ball refresh back to decimal 35
	movwf ball_refresh_orange				;	(remember the ball wont move until this routine is called 40 times...)
	btfsc ball_up_orange, 0					;	Check to see if the ball_up is set, if it is then, 
	rlf ball_y_orange, f					;	make the ball move up one space
	btfsc ball_down_orange, 0				;	Check to see if the ball_down is set, if it is then,	
	rrf ball_y_orange, f					;	make the ball move down one space
	btfsc ball_left_orange, 0				;	Check to see if the ball_left is set, if it is then,
	rrf ball_x_orange, f					;	make the ball move left one space
	btfsc ball_right_orange, 0				;	Check to see if the ball_right is set, if it is then,
	rlf ball_x_orange, f					;	make the ball move right one space
	return									;	Now return to the main program


set_up_green					;	This routine sets a flag
	bcf ball_down_green, 0		;	so that the ball will move
	bsf ball_up_green, 0		;	upward.
	return						;	return to our main program

set_down_green					;	This routine sets a flag
	bcf ball_up_green, 0		;	so that the ball will move
	bsf ball_down_green, 0		;	downward
	return						;	return to our main program

set_left_green					;	This routine sets a flag
	bcf ball_right_green, 0		;	so that the ball will move
	bsf ball_left_green, 0		;	to the left
	return						;	return to our main program

set_right_green					;	This routine sets a flag
	bcf ball_left_green, 0		;	so that the ball will move
	bsf ball_right_green, 0		;	to the right
	return						;	return to our main program


set_up_red						;	This routine sets a flag
	bcf ball_down_red, 0		;	so that the ball will move
	bsf ball_up_red, 0			;	upward.
	return						;	return to our main program

set_down_red					;	This routine sets a flag
	bcf ball_up_red, 0			;	so that the ball will move
	bsf ball_down_red, 0		;	downward
	return						;	return to our main program

set_left_red					;	This routine sets a flag
	bcf ball_right_red, 0		;	so that the ball will move
	bsf ball_left_red, 0		;	to the left
	return						;	return to our main program
	
set_right_red					;	This routine sets a flag
	bcf ball_left_red, 0		;	so that the ball will move
	bsf ball_right_red, 0		;	to the right
	return						;	return to our main program


set_up_orange						;	This routine sets a flag
	bcf ball_down_orange, 0			;	so that the ball will move
	bsf ball_up_orange, 0			;	upward.
	return							;	return to our main program

set_down_orange						;	This routine sets a flag
	bcf ball_up_orange, 0			;	so that the ball will move
	bsf ball_down_orange, 0			;	downward
	return							;	return to our main program

set_left_orange						;	This routine sets a flag
	bcf ball_right_orange, 0		;	so that the ball will move
	bsf ball_left_orange, 0			;	to the left
	return							;	return to our main program

set_right_orange					;	This routine sets a flag
	bcf ball_left_orange, 0			;	so that the ball will move
	bsf ball_right_orange, 0		;	to the right
	return							;	return to our main program



draw_balls						;	This routine takes care of drawing all the balls on the screen
	movf ball_y_green, w		;	copy the y co-ordinate green ball data from ball_y_green to PORTB - 
	movwf PORTB					;	this data is now felt at the input of the 74373's
	bsf PORTA, 2				;	now we open up the GREEN 74373 latches to allow the data to pass to the output.
	bcf PORTA, 2				;	now we close the latches and our data will be retained in this 74373
	movf ball_x_green, w		;	copy the x co-ordinate green ball data from ball_y_green to PORTB -
	movwf PORTB					;	this data is now felt at the input of the 74373's
	bsf PORTA, 4				;	now we open up the COLUMN DATA 74373 latches to allow the data to pass to the output.
	bcf PORTA, 4				;	now we close the latches and our data will be retained in this 74373
	bcf PORTA, 3				;	enable the GREEN 74373 tri-state buffer outputs 
	bcf PORTA, 6				;	enable the COLUMN DATA 74373 tri-state buffer outputs
	call delay					;	hold the data their for just a split second (determined by our delay routine)
	bsf PORTA, 3				;	now disable the GREEN 74373 tri-state buffer outputs
	bsf PORTA, 6				;	now disable the COLUMN DATA 74373 tri-state buffer outputs

	movf ball_y_red, w			;	copy the y co-ordinate red ball data from ball_y_red to PORTB - 
	movwf PORTB					;	this data is now felt at the input of the 74373's
	bsf PORTA, 0				;	now we open up the RED 74373 latches to allow the data to pass to the output.
	bcf PORTA, 0				;	now we close the latches and our data will be retained in this 74373
	movf ball_x_red, w			;	copy the x co-ordinate red ball data from ball_y_red to PORTB -
	movwf PORTB					;	this data is now felt at the input of the 74373's
	bsf PORTA, 4				;	now we open up the COLUMN DATA 74373 latches to allow the data to pass to the output.
	bcf PORTA, 4				;	now we close the latches and our data will be retained in this 74373
	bcf PORTA, 1				;	enable the RED 74373 tri-state buffer outputs 
	bcf PORTA, 6				;	enable the COLUMN DATA 74373 tri-state buffer outputs
	call delay					;	hold the data their for just a split second (determined by our delay routine)
	bsf PORTA, 1				;	now disable the RED 74373 tri-state buffer outputs
	bsf PORTA, 6				;	now disable the COLUMN DATA 74373 tri-state buffer outputs

	movf ball_y_orange, w		;	copy the y co-ordinate red ball data from ball_y_orange to PORTB - 	
	movwf PORTB					;	this data is now felt at the input of the 74373's
	bsf PORTA, 0				;	now we open up the RED 74373 latches to allow the data to pass to the output.			
	bcf PORTA, 0				;	now we close the latches and our data will be retained in this 74373
	bsf PORTA, 2				;	now we open up the GREEN 74373 latches to allow the data to pass to the output.
	bcf PORTA, 2				;	now we close the latches and our data will be retained in this 74373
	movf ball_x_orange, w		;	copy the x co-ordinate orange ball data from ball_y_orange to PORTB -
	movwf PORTB					;	this data is now felt at the input of the 74373's
	bsf PORTA, 4				;	now we open up the COLUMN DATA 74373 latches to allow the data to pass to the output.
	bcf PORTA, 4				;	now we close the latches and our data will be retained in this 74373
	bcf PORTA, 1				;	enable the RED 74373 tri-state buffer outputs 
	bcf PORTA, 3				;	enable the GREEN 74373 tri-state buffer outputs 
	bcf PORTA, 6				;	enable the COLUMN DATA 74373 tri-state buffer outputs
	call delay					;	hold the data their for just a split second (determined by our delay routine)
	bsf PORTA, 1				;	now disable the RED 74373 tri-state buffer outputs
	bsf PORTA, 3				;	now disable the GREEN 74373 tri-state buffer outputs
	bsf PORTA, 6				;	now disable the COLUMN DATA 74373 tri-state buffer outputs
	return						;	now we can return to our main program



delay
		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		;	thats it!
