
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;											;
;	PIC Microcontroller Tutorial Module 5	;
;											;
;	By Brad Slattery 2009					;
;	www.bradsprojects.com					;
;	brad@bradsprojects.com					;
;											;
;	'Designing electronic projects,			;
;	to spread the name of Jesus'			;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

								;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
								;																						;
								;	NOTE: If you are brand new to programming, then don't concern yourself to			;
								;	much with all of these initial lines of code. You can read up all about this		;
								;	at a later date if you wish. I'm sure that you would rather make an LED flash		;
								;	or make something interesting happen straight away right?							;
								;	All you have to know for now is that we will be placing our code just underneath	;
								;	the SETUP label, and then underneath the BEGIN label. it's really quite simple!		;
								;																						;
								;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


	LIST p=16f648a 				;	tell assembler what chip we are using (if you are using the 16f628a, then
	include "P16f648a.inc"		;	make sure you change this line and the previous line to read p16f628a
	__config h'3f18'			;	sets the configuration settings - internal oscillator, watchdog timer OFF
								;	Power Up Timer DISABLED, Master Clear DISABLED, Brown Out Detect DISABLED,
								;	Low Voltage Programming DISABLED, Data EE Read Protect Disabled,
								;	Code Protect OFF. (this will remain the same for all tutorials)


PC equ h'02'					;	The program counter will be refered to as PC - The program counter is
								;	a little counter within the microcontroller to let itself know what line number
								;	it is upto when running a program. We can make the microcontroller jump to a certain
								;	line number by changing the value stored in PC. (we will do this in a later tutorial)

	cblock h'20'				;	Within this cblock and endc, we can define our variables. More info on this, later.
	delay_1						;	set aside 1 byte for a variable called delay_1
	delay_2						;	set aside 1 byte for a variable called delay_1
	data_counter				;	set aside 1 byte for a variable called data_counter
	endc						;	that's the end of defining our variables



	org h'0000'					;	This line just tells the microcontroller what address to start running our program from.
								;	It will always be 0000 hex for all the tutorials.


	movlw h'07'					;	This will turn the comparators OFF.	
	movwf CMCON 				;	(we just want to use the ports as digital ports)


	bsf STATUS, RP0 			;	select bank 1 (to enable us to change the Input / Output status of our ports)
	movlw b'00000000' 			;	set PORTB all outputs (A '0' means output, A '1' means input. We can set each
	movwf TRISB					;	We can set each bit individualy. Each port having 8-bits or 8 pins.
	movlw b'00100000' 			;	set PORTA all outputs except for bit 5. Bit 5 is an input ONLY pin.
	movwf TRISA 				;	It cannot be set to an output!
	bcf STATUS, RP0 			;	select bank 0


	goto setup					;	Go straight to the main part of our code.


display_data						;	This contains data for the different led positions
	incf data_counter, f			;	increment data_counter by one, then
	movf data_counter, w			;	copy the answer to our working register and then,
	addwf PC						;	add this number to our program counter (this just skips one line everytime we come here)
	nop								;	skip one step.
	retlw b'11101111'				;	these next lot of retlw instructions will be sent to
	retlw b'11101111'				;	PORTB to light up one LED at a time in a chasing light pattern.
	retlw b'11110111'				;	once the last LED is lit, then program counter will increment one more
	retlw b'10111111'				;	time but there are no more retlw statements, so it goes back to setup
	retlw b'10111111'				;	(which is underneath all these retlw statements) and starts the pattern again.
	retlw b'11111110'				;	
	retlw b'11111101'				;
	retlw b'11111101'				;	
	retlw b'11111011'				;
	retlw b'10111111'				;
	retlw b'10111111'				;
	retlw b'11011111'				;



setup							;	I always have a title labelled 'setup' this is where we set everything up
		clrf data_counter		;	we want to start at the start so we need to make sure that data_counter contains zero
		bcf PORTA, 0			;	turn OFF the first display (by disconnecting +5v from the anodes)
		bcf PORTA, 1			;	turn OFF the second display (by disconnecting +5v from the anodes)



begin							;	This is where our main program starts.

		call display_data		;	call display data to grab a byte of data which we then
		movwf PORTB				;	send to PORTB for display on a certain screen.	
		bsf PORTA, 1			;	in this case it is the left screen
		call delay				;	call the delay to keep it on for a moment and then
		bcf PORTA, 1			;	turn the display off

		call display_data		;	call display data to grab a byte of data which we then
		movwf PORTB				;	send to PORTB for display on a certain screen.	
		bsf PORTA, 0			;	in this case it is the right screen
		call delay				;	call the delay to keep it on for a moment and then
		bcf PORTA, 0			;	turn the display off

		call display_data		;	call display data to grab a byte of data which we then
		movwf PORTB				;	send to PORTB for display on a certain screen.	
		bsf PORTA, 0			;	in this case it is the right screen
		call delay				;	call the delay to keep it on for a moment and then
		bcf PORTA, 0			;	turn the display off

		call display_data		;	call display data to grab a byte of data which we then
		movwf PORTB				;	send to PORTB for display on a certain screen.	
		bsf PORTA, 0			;	in this case it is the right screen
		call delay				;	call the delay to keep it on for a moment and then
		bcf PORTA, 0			;	turn the display off

		call display_data		;	call display data to grab a byte of data which we then
		movwf PORTB				;	send to PORTB for display on a certain screen.	
		bsf PORTA, 1			;	in this case it is the left screen
		call delay				;	call the delay to keep it on for a moment and then
		bcf PORTA, 1			;	turn the display off

		call display_data		;	call display data to grab a byte of data which we then
		movwf PORTB				;	send to PORTB for display on a certain screen.	
		bsf PORTA, 1			;	in this case it is the left screen
		call delay				;	call the delay to keep it on for a moment and then
		bcf PORTA, 1			;	turn the display off

		call display_data		;	call display data to grab a byte of data which we then
		movwf PORTB				;	send to PORTB for display on a certain screen.	
		bsf PORTA, 1			;	in this case it is the left screen
		call delay				;	call the delay to keep it on for a moment and then
		bcf PORTA, 1			;	turn the display off

		call display_data		;	call display data to grab a byte of data which we then
		movwf PORTB				;	send to PORTB for display on a certain screen.	
		bsf PORTA, 0			;	in this case it is the right screen
		call delay				;	call the delay to keep it on for a moment and then
		bcf PORTA, 0			;	turn the display off

		call display_data		;	call display data to grab a byte of data which we then
		movwf PORTB				;	send to PORTB for display on a certain screen.	
		bsf PORTA, 0			;	in this case it is the right screen
		call delay				;	call the delay to keep it on for a moment and then
		bcf PORTA, 0			;	turn the display off

		call display_data		;	call display data to grab a byte of data which we then
		movwf PORTB				;	send to PORTB for display on a certain screen.	
		bsf PORTA, 0			;	in this case it is the right screen
		call delay				;	call the delay to keep it on for a moment and then
		bcf PORTA, 0			;	turn the display off

		call display_data		;	call display data to grab a byte of data which we then
		movwf PORTB				;	send to PORTB for display on a certain screen.	
		bsf PORTA, 1			;	in this case it is the left screen
		call delay				;	call the delay to keep it on for a moment and then
		bcf PORTA, 1			;	turn the display off

		call display_data		;	call display data to grab a byte of data which we then
		movwf PORTB				;	send to PORTB for display on a certain screen.	
		bsf PORTA, 1			;	in this case it is the left screen
		call delay				;	call the delay to keep it on for a moment and then
		bcf PORTA, 1			;	turn the display off

	goto begin					;	and repeat!






delay							;	here is a nice and simple delay routine
	movlw d'100'				;	copy the decimal number 100 to the working register
	movwf delay_1				;	and now copy it from the w register to delay_1 and delay_2
	movwf delay_2				;	Now the rest of the routine will focus on counting down to zero.
delay_loop						;	We come back to this label when we have not yet reached zero.
	decfsz delay_1, f			;	decrement whatever is in delay_1 by 1 and store the answer back in delay_1
		goto delay_loop			;	if the answer is not zero, then go back to the delay_loop label. but if the
	decfsz delay_2, f			;	answer is zero then decrement delay_2 by one and store the answer in delay_2
		goto delay_loop			;	if the answer is not zero, then go back to delay_loop label. but if the answer
	return						;	is zero, then we have completed our delay and now we can return to our main program!



	end							;	We always need to have end at the end, even if we don't want the program
								;	to actually end, it still must be here!
