;******************************************************************************
;Software License Agreement                                         
;                                                                    
;The software supplied herewith by Microchip Technology             
;Incorporated (the "Company") is intended and supplied to you, the  
;Company’s customer, for use solely and exclusively on Microchip    
;products. The software is owned by the Company and/or its supplier,
;and is protected under applicable copyright laws. All rights are   
;reserved. Any use in violation of the foregoing restrictions may   
;subject the user to criminal sanctions under applicable laws, as   
;well as to civil liability for the breach of the terms and         
;conditions of this license.                                        
;                                                                    
;THIS SOFTWARE IS PROVIDED IN AN "AS IS" CONDITION. NO WARRANTIES,  
;WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED  
;TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A       
;PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT,  
;IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR         
;CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.       
;******************************************************************************
;Filename:	state.asm
;Author:	Reston Condit
;Date:		1/15/03  	
;Version:	1.00
;Description:  	
;  This firmware implements a simple state machine.  There are eight states:
;	STATE1 = D0 LED on
;	STATE2 = D1 LED on
;	STATE3 = D2 LED on
;	STATE4 = D3 LED on
;	STATE5 = D4 LED on
;	STATE6 = D5 LED on
;	STATE7 = D6 LED on
;	STATE8 = D7 LED on
;
;  User's Note: Under Edit -> Properties... -> Tabs set tabs to 3
;******************************************************************************
;Revision History:
;  none
;******************************************************************************

;******************************************************************************
;Instructions On How To Use This Program
;******************************************************************************
;  Press Switch 1 (SW1) on the PICkit(tm) demonstration board to cycle through
;  the eight LED states.
;******************************************************************************

	list      p=12f675            ; list directive to define processor
	#include <p12f675.inc>        ; processor specific variable definitions

	errorlevel  -302              ; suppress message 302 from list file

	__CONFIG   _CP_OFF & _CPD_OFF & _BODEN_OFF & _MCLRE_OFF & _WDT_ON & _PWRTE_ON & _INTRC_OSC_NOCLKOUT  

; '__CONFIG' directive is used to embed configuration word within .asm file.
; The labels following the directive are located in the respective .inc file.
; See data sheet for additional information on configuration word settings.

;************************** VARIABLE DEFINITIONS ******************************

      cblock	0x20			
	STATE_LED			; LED state machine counter
	STATE_DEBOUNCE			; button debounce state machine counter
      endc

;*************************** DEFINE STATEMENTS ********************************

; input and output definitions	

#define POT		GPIO,2		; potentiometer (not used in this 
					;   example)
#define SW1		GPIO,3		; toggle switch

; define input/output designation for LEDs (what TRISIO will equal)

#define TRIS_D0_D1	B'00001111'	; TRISIO setting for D0 and D1
#define TRIS_D2_D3	B'00101011'	; TRISIO setting for D2 and D3
#define TRIS_D4_D5	B'00011011'	; TRISIO setting for D4 and D5
#define TRIS_D6_D7	B'00111001'	; TRISIO setting for D6 and D7

; define LED state (what GPIO will equal)

#define D0_ON	B'00010000'		; D0 LED
#define D1_ON	B'00100000'		; D1 LED
#define D2_ON	B'00010000'		; D2 LED
#define D3_ON	B'00000100'		; D3 LED
#define D4_ON	B'00100000'		; D4 LED
#define D5_ON	B'00000100'		; D5 LED
#define D6_ON	B'00000100'		; D6 LED
#define D7_ON	B'00000010'	 	; D7 LED

;****************************** Start of Program ******************************
	org     0x000			; processor reset vector
	goto	Initialize

;******************************************************************************
; Initialize
;	Initialize Special Function Registers     
;******************************************************************************
	org	0x005			; Start of Programm Memory Vector
Initialize:
	call    0x3FF      ; retrieve factory calibration value
						; comment instruction if using simulator, ICD2, or ICE2000
	bsf     STATUS,RP0		; Bank 1 
	movwf   OSCCAL			; update register with factory cal 
					;  value 
	movlw	B'00111111'		; Set all I/O pins as inputs
	movwf	TRISIO			
	clrf	ANSEL			; Set all inputs as digital	
	movlw	B'10000100'		; Weak pullups: disabled
	movwf	OPTION_REG		; TMR0 prescaler: 1:32 (TMR0 will 
					;  overflow in 8.2ms)
	clrf	INTCON			; disable all interrupts, clear all 
					;  flags	
	bcf     STATUS,RP0		; Bank 0
	clrf	GPIO			; clear all outputs
	clrf 	TMR0			; clear Timer 0
	clrf	STATE_LED		; clear LED state machine counter
	clrf	STATE_DEBOUNCE		; clear debounce state machine counter

;******************************************************************************
; State_Machine
;	Implements a state machine that lights up the LEDs on the PICkit board
;       sequentially when SW1 is pressed.     
;******************************************************************************

State_Machine:
	clrwdt				; clear Watch Dog Timer

	call	Button_Press		; Increments STATE if button is pressed

	movf	STATE_LED, w		; Mask out the high order bits of 
	andlw	B'00000111'		;   STATE_LED
	addwf	PCL, f			; The program clock (PCL) is incre-
	goto	State0			;   mented by STATE_LED in order
	goto	State1	  		;   to go to the appropiate routine
	goto	State2			
	goto	State3			
	goto	State4
	goto	State5
	goto	State6
	goto	State7
	
State0:				
; Turns on D0 LED
	bsf	STATUS, RP0		; Bank 1
	movlw	TRIS_D0_D1		; move predefined value to TRISIO
	movwf	TRISIO
	bcf	STATUS, RP0		; Bank 0
	movlw	D0_ON			; move predefined value to GPIO
	movwf	GPIO
	goto 	State_Machine		; go back to state machine jump table

State1:
; Turns on D1 LED
	bsf	STATUS, RP0		; Bank 1
	movlw	TRIS_D0_D1		; move predefined value to TRISIO
	movwf	TRISIO
	bcf	STATUS, RP0		; Bank 0
	movlw	D1_ON			; move predefined value to GPIO
	movwf	GPIO
	goto 	State_Machine		; go back to state machine jump table
	
State2:
; Turns on D2 LED
	bsf	STATUS, RP0		; Bank 1
	movlw	TRIS_D2_D3		; move predefined value to TRISIO
	movwf	TRISIO
	bcf	STATUS, RP0		; Bank 0
	movlw	D2_ON			; move predefined value to GPIO
	movwf	GPIO
	goto 	State_Machine		; go back to state machine jump table

State3:
; Turns on D3 LED
	bsf	STATUS, RP0		; Bank 1
	movlw	TRIS_D2_D3		; move predefined value to TRISIO
	movwf	TRISIO
	bcf	STATUS, RP0		; Bank 0
	movlw	D3_ON			; move predefined value to GPIO
	movwf	GPIO
	goto 	State_Machine		; go back to state machine jump table

State4:
; Turns on D4 LED
	bsf	STATUS, RP0		; Bank 1
	movlw	TRIS_D4_D5		; move predefined value to TRISIO
	movwf	TRISIO
	bcf	STATUS, RP0		; Bank 0
	movlw	D4_ON			; move predefined value to GPIO
	movwf	GPIO
	goto 	State_Machine		; go back to state machine jump table

State5:
; Turns on D5 LED
	bsf	STATUS, RP0		; Bank 1
	movlw	TRIS_D4_D5		; move predefined value to TRISIO
	movwf	TRISIO
	bcf	STATUS, RP0		; Bank 0
	movlw	D5_ON			; move predefined value to GPIO
	movwf	GPIO
	goto 	State_Machine		; go back to state machine jump table
	
State6:
; Turns on D6 LED
	bsf	STATUS, RP0		; Bank 1
	movlw	TRIS_D6_D7		; move predefined value to TRISIO
	movwf	TRISIO
	bcf	STATUS, RP0		; Bank 0
	movlw	D6_ON			; move predefined value to GPIO
	movwf	GPIO
	goto 	State_Machine		; go back to state machine jump table
	
State7:
; Turns on D7 LED
	bsf	STATUS, RP0		; Bank 1
	movlw	TRIS_D6_D7		; move predefined value to TRISIO
	movwf	TRISIO
	bcf	STATUS, RP0		; Bank 0
	movlw	D7_ON			; move predefined value to GPIO
	movwf	GPIO
	goto 	State_Machine		; go back to state machine jump table

;******************************************************************************
; Button_Press
;	Looks for button press and implements a button debounce routine.
;******************************************************************************
Button_Press:
	movf	STATE_DEBOUNCE, w	; Mask out the high order bits of 
	andlw	B'00000011'		;  STATE_DEBOUNCE.
	addwf	PCL, f	
	goto	Debounce_1		
	goto	Debounce_2	
	goto	Debounce_3
	goto	Debounce_2		; Send to second state if noise 
					;  corrupts debounce state counter.

Debounce_1:
	btfsc	SW1			; Is Switch 1 pushed?
	retlw	0			; No, then return
	incf	STATE_DEBOUNCE, f	; Yes, then increment both state 
	incf	STATE_LED, f		;  machines.
	retlw	0

Debounce_2:
	btfss	SW1			; Is Switch 1 released? 
	retlw	0			; No, then return
	clrf 	TMR0			; Yes, clear Timer0 and Timer0 flag
	bcf	INTCON, T0IF			
	incf	STATE_DEBOUNCE, f	; Increment debounce state machine
	retlw	0				
	
Debounce_3:
; Switch must be high for approximately 8.2 ms before debounce state machine is 
;  re-initialized.
	btfss	INTCON, T0IF		; Has 8.2 ms passed?
	goto	Debounce_3a		; No, then check for switch jitter
	clrf	STATE_DEBOUNCE		; Yes, then re-initialize state machine
	retlw	0
	
Debounce_3a:	
	btfss	SW1			; Is Switch 1 low again (due to switch 
					;  jitter)?
	decf	STATE_DEBOUNCE, f	; Yes, then go back to debounce state2
	retlw	0			; No, then return.

	end                     	; directive 'end of program'