;**************************************************************************
;*          					 COIN COUNTER        					  *
;**************************************************************************
;*          (C) DIRK & DIRK,2009  All rights reserved             		  *
;*          Hardware & software by Dirk							  		  *
;**************************************************************************
;*          Hardw. Rev: 1	             Softw. Rev:  1.01                *
;*          OSC.......: XT 4MHz Max.     POWER.....:  15V DC              *
;**************************************************************************

;==========================================================================
;	Counts coins:
;		- Each coin triggers an update to the EEPROM
;		- Count is maintained in EEBYTE1 & EEBYTE2 and volatile
;		  variables COUNT1 & COUNT2
;		- LED connected to RB0 flashes x times; where x is the coin
;		  count
;		- NOTE: Querying the count when it's 0 or over 256 will produce
;		  odd effects
;		- LED connected to RB1 is on when EEPROM is being written
;		- RA0: Increment count
;		- RA1: Query value of coin count
;		- RA2: Reset EEPROM
;==========================================================================

	

;==========================================================================
;
;       Configuration Bits
;
;==========================================================================

_CP_ON                       EQU     H'000F'
_CP_OFF                      EQU     H'3FFF'
_PWRTE_ON                    EQU     H'3FF7'
_PWRTE_OFF                   EQU     H'3FFF'
_WDT_ON                      EQU     H'3FFF'
_WDT_OFF                     EQU     H'3FFB'
_LP_OSC                      EQU     H'3FFC'
_XT_OSC                      EQU     H'3FFD'
_HS_OSC                      EQU     H'3FFE'
_RC_OSC                      EQU     H'3FFF'

	__CONFIG        _CP_OFF & _PWRTE_ON & _WDT_OFF & _XT_OSC 


;==========================================================================
;
;       Register Definitions
;
;==========================================================================

W                            EQU     H'0000'
F                            EQU     H'0001'

;----- Register Files------------------------------------------------------

INDF                         EQU     H'0000'
TMR0                         EQU     H'0001'
PCL                          EQU     H'0002'
STATUS                       EQU     H'0003'
FSR                          EQU     H'0004'
PORTA                        EQU     H'0005'
PORTB                        EQU     H'0006'
EEDATA                       EQU     H'0008'
EEADR                        EQU     H'0009'
PCLATH                       EQU     H'000A'
INTCON                       EQU     H'000B'

OPTION_REG                   EQU     H'0081'
TRISA                        EQU     H'0085'
TRISB                        EQU     H'0086'
EECON1                       EQU     H'0088'
EECON2                       EQU     H'0089'

;----- STATUS Bits --------------------------------------------------------

IRP                          EQU     H'0007'
RP1                          EQU     H'0006'
RP0                          EQU     H'0005'
NOT_TO                       EQU     H'0004'
NOT_PD                       EQU     H'0003'
Z                            EQU     H'0002'
DC                           EQU     H'0001'
C                            EQU     H'0000'

;----- INTCON Bits --------------------------------------------------------

GIE                          EQU     H'0007'
EEIE                         EQU     H'0006'
T0IE                         EQU     H'0005'
INTE                         EQU     H'0004'
RBIE                         EQU     H'0003'
T0IF                         EQU     H'0002'
INTF                         EQU     H'0001'
RBIF                         EQU     H'0000'

;----- OPTION_REG Bits ----------------------------------------------------

NOT_RBPU                     EQU     H'0007'
INTEDG                       EQU     H'0006'
T0CS                         EQU     H'0005'
T0SE                         EQU     H'0004'
PSA                          EQU     H'0003'
PS2                          EQU     H'0002'
PS1                          EQU     H'0001'
PS0                          EQU     H'0000'

;----- EECON1 Bits --------------------------------------------------------

EEIF                         EQU     H'0004'
WRERR                        EQU     H'0003'
WREN                         EQU     H'0002'
WR                           EQU     H'0001'
RD                           EQU     H'0000'

;INPUTS
SW1		EQU     H'00'		;SW1 is triggering RA0 (Increment)
SW2		EQU     H'01'		;SW2 is triggering RA1 (Flash value of count times on RB0)
SW3		EQU		H'02'		;SW3 is triggering RA2 (Reset EEPROM)
SW4		EQU		H'03'		;SW4 is triggering RA3 (Signal payout)
SW5		EQU		H'04'		;SW5 is triggering RB4 (decrement coin signal)

;OUTPUTS
PO		EQU		H'02'		;PO is triggering RA4 (switch on coin hopper motor)
;==========================================================================
;
;       RAM Definition
;
;==========================================================================

        __MAXRAM H'CF'
        __BADRAM H'07', H'50'-H'7F', H'87'


;==========================================================================
;
;       Variables
;
;==========================================================================

COUNT1			EQU		H'0C'	;Local count byte 1
COUNT2			EQU		H'0D'	;Local count byte 2
DECRM			EQU		H'0E'	;Stores temp value of count for flashing
TIMER1          EQU     H'0F'   ;Timer 1, Used for general delay
TIMER2          EQU     H'10'   ;Timer 2, used for delay !
FREQCOUNT		EQU		H'11'	;Frequency counter

;==========================================================================
;
;       EEPROM Variables
;
;==========================================================================

EEBYTE1			EQU		H'00'	;Stores the first byte of the count in the eeprom
EEBYTE2			EQU		H'01'	;Stores the second byte of the count in the eeprom


		ORG		0				;Setting Reset vector, reset vector address is 000h in PIC16F84
		GOTO	RESET			;Jump to RESET procedure when boot-up PIC device.
	
		
;**************************
;*     main routine:      *
;**************************

RESET	BSF		STATUS,RP0		;Jump to bank 1 of PIC16F84 to access special registers.
		MOVLW	B'00001111'		;Config Port A, Low nibble = Ra0 are inputs, high nibble not implemented.
		MOVWF	TRISA			;Set I/O configuration for PORTA
		MOVLW	B'00010000'		;Rb7...Rb0 are outputs.
		MOVWF	TRISB			;Set I/O configuration for PORTB
		BCF	STATUS,RP0			;Jump back to bank 0 of PIC.

		CLRF	PORTA			;Clear all I/O's of PORTA
		CLRF	PORTB			;Clear all I/O's of PORTB

		CALL	FETCHEEPROM
								;Loop starts here !!!

LOOP	BTFSC 	PORTA,SW1		;See if button 1 is on (increment button)
		CALL	INCREM			;Increment the count
		BTFSC	PORTA,SW2		;See if button 2 is down (flash the number of the count)
		CALL	SHOWCOUNT		;Start flasher
		BTFSC	PORTA,SW3		;See if button 3 is on (reset eeprom)
		CALL	RESETEEPROM		;Reset eeprom
		BTFSC	PORTA,SW4		;See if button 4 is on (payout signal)
		CALL	PAYOUT			;Begin payout function
		GOTO 	LOOP

;*******************
;* Payout function *
;*******************
PAYOUT	CALL	PAYON			;Switch hopper motor on
		CALL	DELAY
; Probably not the right way to do it but this part checks the switch 5 times to make
; sure it isn't that weird spiking thing.
P1		BTFSS	PORTB,4			;Is the coin decrement switch on?
		GOTO	P1				;No
		BTFSS	PORTB,4			;Is the coin decrement switch on?
		GOTO	P1				;No
		BTFSS	PORTB,4			;Is the coin decrement switch on?
		GOTO	P1				;No
		BTFSS	PORTB,4			;Is the coin decrement switch on?
		GOTO	P1				;No
		BTFSS	PORTB,4			;Is the coin decrement switch on?
		GOTO	P1				;No
		BSF		PORTB,3			;Real decr switch occurred, switch light on
P2		BTFSC	PORTB,4			;Is the coin decrement switch up?
		GOTO	P2				;No
		BCF		PORTB,3			;End of decr switch, turn off light
DEC1	DECFSZ	COUNT1,1		;Decrement first count byte
		GOTO	P1				;COUNT1 != 0, so go back to P1
		DECFSZ	COUNT2,1		;COUNT1 == 0, now check COUNT2
		GOTO	DEC2			;COUNT2	!= 0, so set COUNT1 = D'255' then go back to P1
		GOTO	DEC3			;COUNT2 == 0, hopper is empty, go to DEC3 to halt and clean up
DEC2	MOVLW	H'FF'			;
		MOVWF	COUNT1			;Set count back to FF (256)
		GOTO 	P1				;Start checking for clicks again
DEC3	CALL	PAYOFF			;Switch of the motor
		CALL 	RESETEEPROM		;Reset count to 0 (count1:0, count2:1)
		RETURN

		

;		BCF		PORTB,3			;FOO: This is just to check if a switch signal is received from the hopper
;P2		BTFSC	PORTB,SW5		;Is the coin dec switch off?
;		GOTO	P2				;No, go back
; Here one switch from the hopper has occurred, now decrement count
; and check to see if we are at 0
;DEC1	DECFSZ	COUNT1,1		;Decrement first count byte
;		GOTO	P1				;COUNT1 != 0, so go back to P1
;		DECFSZ	COUNT2,1		;COUNT1 == 0, now check COUNT2
;		GOTO	DEC2			;COUNT2	!= 0, so set COUNT1 = D'255' then go back to P1
;		GOTO	DEC3			;COUNT2 == 0, hopper is empty, go to DEC3 to halt and clean up
;DEC2	MOVLW	H'FF'			;
;		MOVWF	COUNT1			;Set count back to FF (256)
;		GOTO 	P1				;Start checking for clicks again
;DEC3	CALL	PAYOFF			;Switch of the motor
;		CALL 	RESETEEPROM		;Reset count to 0 (count1:0, count2:1)
;		RETURN

;TEMPTEMPTEMPTEMPTEMPTEMPTEMPTEMP
;LED4ON	MOVLW	H'01'
;		MOVWF	FREQCOUNT
;ITSON	BTFSS	PORTB,SW5
;		GOTO	STILLON
;		GOTO 	GONEOFF

;STILLON	DECFSZ	FREQCOUNT,1
;		GOTO	ITSON
;LOOPER	BSF		PORTB,3
;		GOTO	LOOPER

;GONEOFF	GOTO	P1

;LED4OFF	BCF		PORTB,3
;		GOTO	P1



;PAYOUT	BTFSC	PORTA,SW4		;Is button down?
;		GOTO	PAYON			;Yes
;		GOTO	PAYOFF			;No

;**********************
;* Payout on function *
;**********************
PAYON	BSF		PORTB,PO		;Set PO pin to high
		RETURN
;***********************
;* Payout off function *
;***********************
PAYOFF	BCF		PORTB,PO		;Set PO pin to low
		RETURN					;

;******************************
;* Count incrementer function *
;******************************
INCREM	BTFSC	PORTA,SW1		;Make sure they aren't still holding down the button
		GOTO	INCREM			;
		CALL	DELAY			;Short delay for mechanical bouncing on the button
		INCFSZ	COUNT1,1		;Increment COUNT1 register
		GOTO	WRTRET			;Go to write then return section if COUNT1 didn't click over to 0
		INCFSZ	COUNT2,1		;Increment COUNT2 register if COUNT1 did click over to 0

WRTRET	CALL 	SETEEPROM		;
		RETURN					;

;********************
;* Flasher function *
;********************
;##############################################################################################################
;################ FOO: NEEDS TO BE UPDATED FOR 2 BYTE COUNT ###################################################
;##############################################################################################################
SHOWCOUNT	BTFSC	PORTA,SW2	;Make sure they aren't still holding down the button
			GOTO	SHOWCOUNT	;
			MOVF	COUNT1,0	;Move the count to W
			MOVWF	DECRM		;Move W to decrm register
MORECOUNT	CALL	LED1ON		;Switch LED on
			CALL	DELAY		;Wait
			CALL	LED1OFF		;Switch LED off
			CALL	DELAY		;Wait
			DECFSZ	DECRM,1		;Decrement count
			GOTO 	MORECOUNT
			RETURN

;*******************************************************
;* Fetches count from EEPROM, moves to COUNT1 & COUNT2 *
;*******************************************************
FETCHEEPROM	MOVLW	EEBYTE1			;Grab first byte
			MOVWF	EEADR			;Address to read
			BSF		STATUS,RP0		;Bank 1
			BSF		EECON1,RD		;EE read
			BCF		STATUS,RP0		;Bank 0
			MOVF	EEDATA,0		;Copy EEDATA to W
			MOVWF	COUNT1			;Copy EEDATA (from W) to COUNT1
			MOVLW	EEBYTE2			;Grab second byte
			MOVWF	EEADR			;Address to read
			BSF		STATUS,RP0		;Bank 1
			BSF		EECON1,RD		;EE read
			BCF		STATUS,RP0		;Bank 0
			MOVF	EEDATA,0		;Copy EEDATA to W
			MOVWF	COUNT2			;Copy EEDATA (from W) to COUNT2
			RETURN

;******************************
;* Reset EEPROM function      * 
;* - Sets COUNT1 & COUNT2 to  *
; 	 0 then writes the EEPROM *
;******************************
RESETEEPROM	MOVLW	H'0'		;Move 0 into W
			MOVWF	COUNT1		;Move W into COUNT1
			MOVLW	H'1'		;Move 0 into W
			MOVWF	COUNT2		;Move 0 into COUNT2
			CALL 	SETEEPROM	;Now set EEPROM since COUNT1 & COUNT2 are 0
			RETURN				;Return from reset call

;**************************************
;* Set EEPROM function                *
;* - Writes COUNT1 & COUNT2 to EEPROM *
;**************************************
; Write the first byte
SETEEPROM	CALL	LED2ON		;Turn on LED 2 to show it's writing
			BCF		STATUS,RP0	;Bank 0
			MOVF	COUNT1,0	;Move COUNT1 into EEDATA for writing
			MOVWF	EEDATA
			MOVLW	EEBYTE1		;Address to read from (EEBYTE1)
			MOVWF	EEADR		
			BSF		STATUS,RP0	;Bank 1
			BCF		INTCON,GIE	;Disable interrupts
			BSF		EECON1,WREN	;Enable write
			MOVLW	H'55'		;Confirm write 1
			MOVWF	EECON2		;
			MOVLW	H'AA'		;Confirm write 2
			MOVWF	EECON2		;
			BSF		EECON1,WR	;Set WR bit, begin write
			BSF 	INTCON,GIE	;Enable INT's
			CALL 	WAITFOREE	;Wait for EE to be written
; Write the second byte
			BCF		STATUS,RP0	;Bank 0
			MOVF	COUNT2,0	;Move COUNT2 into EEDATA for writing
			MOVWF	EEDATA
			MOVLW	EEBYTE2		;Address to read from (EEBYTE2)
			MOVWF	EEADR		
			BSF		STATUS,RP0	;Bank 1
			BCF		INTCON,GIE	;Disable interrupts
			BSF		EECON1,WREN	;Enable write
			MOVLW	H'55'		;Confirm write 1
			MOVWF	EECON2		;
			MOVLW	H'AA'		;Confirm write 2
			MOVWF	EECON2		;
			BSF		EECON1,WR	;Set WR bit, begin write
			BSF		INTCON,GIE	;Enable INT's
			CALL	WAITFOREE	;Wait for EE to be written
			BCF		STATUS,RP0	;Bank 0
			CALL	LED2OFF		;Switch off LED to show stopped writing

			RETURN				;End of reset EEPROM function

;**********************************
;* Waits for EEPROM to be written *
;**********************************
WAITFOREE	BTFSC	EECON1,WR	;Check if WR is still 1
			GOTO	WAITFOREE	;Yes, go back
			RETURN				;No return

;*******************
;* LED 1 on function *
;*******************
LED1ON	BSF		PORTB,0
		RETURN


;********************
;* LED 1 off function *
;*********************
LED1OFF	BCF		PORTB,0
		RETURN

;*********************
;* LED 2 on function *
;*********************
LED2ON	BSF		PORTB,1
		RETURN

;**********************
;* LED 2 off function *
;**********************
LED2OFF	BCF		PORTB,1
		RETURN

;******************
;* Delay function *
;******************
DELAY	MOVLW   D'250'      	;*	;Put 150 decimal in the 'TIMER1' register.
       	MOVWF   TIMER1      	;*
               					;
DELAY2	MOVLW	D'250'			;Put 150 decimal in the 'TIMER2' register.
		MOVWF	TIMER2
		DECFSZ  TIMER2,F    	;*	;Timer2 = Timer2 -1, skip next instruction if Timer2 = 0.
                GOTO    $-1 	;*	;Jump back 1 instruction.
                
		DECFSZ	TIMER1,F		;Timer1 = Timer1 - 1, skip next instruction if Timer1 = 0
		GOTO	DELAY2			;Jump to 'DELAY2' routine	
		RETLW   0				;Return (jump back to main) and load W-reg with 0.

	    END                 	;End of source code.
