	;/////////////////////////////////////////////////////////////////////////////////
	;                      R O F
	;		
	;     M A D E  B Y  B R U N O  F A S C E N D I N I
	;     bipus24hs@hotmail.com
	;/////////////////////////////////////////////////////////////////////////////////
	
	;/////////////////////////////////////////////////////////////////////////////////
	; Project Name:
	; Date created: 02/01/2011 (mm/dd/yyyy)
	; Description: 
	;
	;
	;
	;
	;/////////////////////////////////////////////////////////////////////////////////
	
		LIST P=16F1823
		#include <p16F1823.inc>

		__CONFIG	_CONFIG1, _FOSC_INTOSC & _WDTE_OFF & _PWRTE_ON & _MCLRE_OFF & _CP_ON & _CPD_ON & _BOREN_OFF & _CLKOUTEN_OFF & _IESO_OFF & _FCMEN_OFF
		__CONFIG	_CONFIG2, _WRT_ALL & _PLLEN_ON & _STVREN_ON & _BORV_19 & _LVP_OFF
	
		ERRORLEVEL -302

	;/////////////////////////////////////////////////////////////////////////////////
	;   R A M
	;/////////////////////////////////////////////////////////////////////////////////
	
		CBLOCK	0x20
			PWM1
			PWM_BUTTON1R
			PWM_BUTTON1G
			PWM_BUTTON1B

			PWM_BUTTON2R
			PWM_BUTTON2G
			PWM_BUTTON2B

			PWM_BUTTON3R
			PWM_BUTTON3G
			PWM_BUTTON3B
	
			CPS0L				;CAPACITIVE PERIPHERAL SENSOR 0 ACTUAL MEASUREMENT
			CPS0H
			CPS1L				;CAPACITIVE PERIPHERAL SENSOR 1 ACTUAL MEASUREMENT
			CPS1H
			CPS2L				;CAPACITIVE PERIPHERAL SENSOR 2 ACTUAL MEASUREMENT
			CPS2H

			CPS0L_PROM			;CAPACITIVE PERIPHERAL SENSOR 0 PROMEDY
			CPS0H_PROM
			CPS1L_PROM			;CAPACITIVE PERIPHERAL SENSOR 1 PROMEDY
			CPS1H_PROM
			CPS2L_PROM			;CAPACITIVE PERIPHERAL SENSOR 2 PROMEDY
			CPS2H_PROM

			CPS_FSR_AUXL
			CPS_FSR_AUXH
	
			PWM_COUNTER  		;Temporal Variable
			PORT_AUX  			;Temporal Variable
			ADC_STAGE			;ADC stage control
			ADC_LOOPS

			W_TEMP
			STATUS_TEMP
			FSR_TEMP

			MAX_MINUTESL
			MAX_MINUTESH

			USED_MINUTESL
			USED_MINUTESH
			AUX_MINUTES

			BUFFER_TMP
			BUFFER_SUML
			BUFFER_SUMH	
			BUFFER_SUMTEMPL
			BUFFER_SUMTEMPH	
			BUFFER_START
		ENDC

#DEFINE		SAMPLES			.32
#DEFINE		BUFFER_END 		BUFFER_START + SAMPLES - .1
	
	;/////////////////////////////////////////////////////////////////////////////////
	;   D E F I N I T I O N S
	;/////////////////////////////////////////////////////////////////////////////////
	
	#DEFINE	ADC_CONVERTING	ADC_STAGE,0	;indicates if a conversion is running
	#DEFINE	ADC_RELAX_LOOPS		    0	;pause between conversions
	#DEFINE	BUTTON1			PORTA,  0	;ADC inout 0
	#DEFINE	BUTTON2			PORTA,  0	;ADC inout 1
	#DEFINE	BUTTON3			PORTA,  2	;ADC inout 2
	#DEFINE	PWM1_OUT		LATC,   5	;ACTUAL PWM VALUE
	
	
	#DEFINE	EEPROM_MINUTESL			0
	#DEFINE	EEPROM_MINUTESH			1

	#DEFINE	EEPROM_MINUTESMAXL		2
	#DEFINE	EEPROM_MINUTESMAXH		3

	;max minutes ON
	#DEFINE	MAXL					0xA0
	#DEFINE	MAXH					0x05

	#DEFINE	BUTTON1_MINR			.255
	#DEFINE	BUTTON1_MING			.255
	#DEFINE	BUTTON1_MINB			.255

	#DEFINE	BUTTON2_MINR			.255
	#DEFINE	BUTTON2_MING			.255
	#DEFINE	BUTTON2_MINB			.255

	#DEFINE	BUTTON3_MINR			.255
	#DEFINE	BUTTON3_MING			.255
	#DEFINE	BUTTON3_MINB			.255

	#DEFINE	BUTTON1_MAXR			.255
	#DEFINE	BUTTON1_MAXG			.0
	#DEFINE	BUTTON1_MAXB			.255

	#DEFINE	BUTTON2_MAXR			.255
	#DEFINE	BUTTON2_MAXG			.0
	#DEFINE	BUTTON2_MAXB			.255

	#DEFINE	BUTTON3_MAXR			.0
	#DEFINE	BUTTON3_MAXG			.0
	#DEFINE	BUTTON3_MAXB			.0


	;/////////////////////////////////////////////////////////////////////////////////
	; E E P R O M
	;/////////////////////////////////////////////////////////////////////////////////
		ORG		0xF000
		DE		0, 0, MAXL, MAXH

	;/////////////////////////////////////////////////////////////////////////////////
	;   R O M
	;/////////////////////////////////////////////////////////////////////////////////
		ORG 	0x000
		goto	CONFIG_INIT
	
		ORG		0x004
ISR
		banksel	INTCON
		btfsc	INTCON,TMR0IF
		call	CSP_ISR

		retfie

CSP_ISR
		banksel	TMR1ON			;TURN OFF TIMER1
		clrf	TMR1ON

		;STORE TIMER1 VALUE IN MEMORY
		movf	CPS_FSR_AUXL,W
		movwf	FSR1L
		movf	CPS_FSR_AUXH,W
		movwf	FSR1H

		movf	TMR1L,W
		movwf	INDF1

		incf	FSR1L,F			;increment pointer
		btfsc	STATUS,Z
		incf	FSR1H,F

		movf	TMR1H,W
		movwf	INDF1

		clrf	TMR1L			;CLEAR TIMER1 VALUE
		clrf	TMR1H

		incf	CPS_FSR_AUXL,F	;increment pointer
		btfsc	STATUS,Z
		incf	CPS_FSR_AUXH,F

		;@TODO!! RESET TIMER1!! AND CLEAR FREQ TIMER!

		incf	CPS_FSR_AUXL,F	;increment pointer
		btfsc	STATUS,Z
		incf	CPS_FSR_AUXH,F

		incf	CPSCON1,F
		movf	CPSCON1,W
		xorlw	0x03			;only using CPS0,1 and 2
		btfsc	STATUS,Z
		call	RESET_CSP_CHANNEL

		bcf		INTCON,TMR0IF	;clear TIMER0 interrupt flag and reset TIMER0 value
		clrf	TMR0

		movlw	0x01			;TURN ON TIMER1 AS A COUNTER
		movwf	TMR1ON

		return
	
RESET_CSP_CHANNEL
		clrf	CPSCON1
		movlw	CPS0L
		movwf	CPS_FSR_AUXL
		movlw	CPS0H
		movwf	CPS_FSR_AUXH
		return
	
CONFIG_INIT
		banksel	PORTA				;Bank 0
		clrf 	PORTA				;Clear latches
		clrf	PORTC
	
		banksel	TRISA
	
		movlw 	b'00000111'
		movwf	TRISA				;A0,A1,A2 as input.
		movlw	b'00000000'
		movwf	TRISC				;C as output

		banksel	ADCON0
		;ADC Config
		movlw	b'00000001'			;ADFM Left Justified, VCFG Vdd, channel 0,module ON.
		movwf	ADCON0
		
		banksel	ANSELA
		movlw	b'00000111'			;A0,A1,A2 as analog inputs
		movwf	ANSELA

		banksel	ANSELC
		movlw	b'00000000'			;PORTC all digital
		movwf	ANSELC

		banksel	CPSCON0
		movlw	0x8C
		movwf	CPSCON0				;Capacitive module ON. High Freq.

		banksel	CPSCON1
		movlw	0x00
		movwf	CPSCON1				;select channel 0

		banksel	T1CON
	
		;TIMER1 CONFIG!
		movlw	b'00110101'			;TIMER1 ON, FOSC/4, 1:8 preescaler
		movwf	T1CON

		bcf		PIR1,TMR1IF			;clear TIMER1 interrupt flag

		clrf	AUX_MINUTES			;set aux minutes to zero

		clrf	PWM1				;clear PWM1 value!
	
		clrf	ADC_STAGE			;initialize adc stage
		bcf		ADC_CONVERTING		;indicate that we are not converting anything
		
		movlw	.1					;initialize PWM_COUNTER
		movwf	PWM_COUNTER
	
BEGIN
		movlw	0x20				;FIRST RAM POSITION
		movwf	FSR0L
		clrf	FSR0H
		
NEXT_CLEAR_RAM
		clrf	INDF0
	
		incf	FSR0L,F				
		movlw	0x60				;LAST RAM + 1
		xorwf	FSR0L,W
		btfss	STATUS,Z
		goto	NEXT_CLEAR_RAM

		movlw	BUFFER_START
		movwf	FSR0L				;initialize buffer pointer

		banksel	0
		;REMOVE!!!
		movlw	BUTTON1_MINR
		movwf	PWM_BUTTON1R
		movlw	BUTTON1_MING
		movwf	PWM_BUTTON1G
		movlw	BUTTON1_MINB
		movwf	PWM_BUTTON1B

		movlw	BUTTON2_MINR
		movwf	PWM_BUTTON2R
		movlw	BUTTON2_MING
		movwf	PWM_BUTTON2G
		movlw	BUTTON2_MINB
		movwf	PWM_BUTTON2B

		movlw	BUTTON3_MINR
		movwf	PWM_BUTTON3R
		movlw	BUTTON3_MING
		movwf	PWM_BUTTON3G
		movlw	BUTTON3_MINB
		movwf	PWM_BUTTON3B

		;call	RESTORE_MINUTES		;load previous minutes saved
		call	CONFIGURE_CAPACITIVE_MODULE
LOOP
	
	;-----------------------------------------
	;PWM GENERATION SUB-ROUTINE
	;-----------------------------------------
CHECK_PWM		
		movf	PWM_COUNTER,W
		subwf	PWM1,W
		rlf		PORT_AUX,F

		movf	PWM_COUNTER,W
		subwf	PWM_BUTTON3G,W
		rlf		PORT_AUX,F

		movf	PWM_COUNTER,W
		subwf	PWM_BUTTON3R,W
		rlf		PORT_AUX,F

		movf	PWM_COUNTER,W
		subwf	PWM_BUTTON1B,W
		rlf		PORT_AUX,F

		movf	PWM_COUNTER,W
		subwf	PWM_BUTTON1G,W
		rlf		PORT_AUX,F

		movf	PWM_COUNTER,W
		subwf	PWM_BUTTON1R,W
		rlf		PORT_AUX,W

		movwf	LATC


		clrf	PORT_AUX
		
		movf	PWM_COUNTER,W
		subwf	PWM_BUTTON2B,W
		btfsc	STATUS,C
		bsf		PORT_AUX,5

		movf	PWM_COUNTER,W
		subwf	PWM_BUTTON2G,W
		btfsc	STATUS,C
		bsf		PORT_AUX,4

		movf	PWM_COUNTER,W
		subwf	PWM_BUTTON2R,W
		btfsc	STATUS,C
		bsf		PORT_AUX,3

		movf	PORT_AUX,W
		movwf	LATA
		
PWM_READY
		incfsz	PWM_COUNTER,F
		goto	LOOP

		incf	PWM_COUNTER,F
	
		call	CHECK_ADC
		;call	CHECK_MINUTES

		goto	LOOP

;////////////////////////////////////////////////
;////////////////////////////////////////////////
;	S	U	B	R	O	U	T	I	N	E	S
;////////////////////////////////////////////////
;////////////////////////////////////////////////	

CONFIGURE_CAPACITIVE_MODULE
		banksel	OPTION_REG
		movlw	0xC7			;TIMER0 prescaler 1:256
		movwf	OPTION_REG

		banksel	INTCON
		bcf		INTCON,T0IF		;clear TMR0 interr flag
		bsf		INTCON,T0IE		;enable TMR0 interr
		bsf		INTCON,PEIE		;enable peripheral interrupts

		banksel	T1CON
		movlw	0xC5
		movwf	T1CON

		banksel	T1GCON
		movlw	0xE1
		movwf	T1GCON

		banksel	PIR1
		bcf		PIR1,TMR1GIF

		banksel	PIE1
		bcf		PIE1,TMR1GIE

		banksel	INTCON
		bsf		INTCON,GIE		;enable interrupts

		return


	;-----------------------------------------
	;ADC CONVERSION SUB-ROUTINE
	;-----------------------------------------
	
CHECK_ADC
		btfss	ADC_CONVERTING
		goto	ADC_WAITING
	
ADC_IS_CONVERTING
		btfsc	ADCON0, GO_NOT_DONE
		return

		movf	INDF0,W
		subwf	BUFFER_SUML,F
		btfss	STATUS,C
		decf	BUFFER_SUMH,F

		movf	ADRESH,W			;store readed value into buffer
		movwf	INDF0

		addwf	BUFFER_SUML,F
		btfsc	STATUS,C
		incf	BUFFER_SUMH,F	

		movf	BUFFER_SUML,W
		movwf	BUFFER_SUMTEMPL
		movf	BUFFER_SUMH,W
		movwf	BUFFER_SUMTEMPH

BUFFER_DIVISION_BY_2	MACRO
		bcf		STATUS,C
		rrf		BUFFER_SUMTEMPH,F
		rrf		BUFFER_SUMTEMPL,F
	ENDM
		
		BUFFER_DIVISION_BY_2
		BUFFER_DIVISION_BY_2
		BUFFER_DIVISION_BY_2
		BUFFER_DIVISION_BY_2
		BUFFER_DIVISION_BY_2
		
		movf	BUFFER_SUMTEMPL,W
		movwf	PWM1
		btfsc	STATUS,Z
		incf	PWM1,F			;PWM1 must be never zero!

		btfsc	BUTTON3			;if key is power off, shut down lights
		clrf	PWM1

		movf	USED_MINUTESH,W	
		subwf	MAX_MINUTESH,W
		btfss	STATUS,C
		clrf	PWM1

		btfss	STATUS,Z
		goto	OK_CHECKMIN

		movf	USED_MINUTESL,W
		subwf	MAX_MINUTESL,W
		btfss	STATUS,C
		clrf	PWM1

		btfsc	STATUS,Z
		clrf	PWM1

OK_CHECKMIN
		;movlw	.64
		;movwf	PWM1

		;movf	PWM1,W
		;movwf	PWM_BUTTON1G

		;comf	PWM1,W
		;movwf	PWM_BUTTON2G

		incf	FSR0L,F			;next buffer element
		movf	FSR0L,W
		xorlw	BUFFER_END + .1
		movlw	BUFFER_START
		btfsc	STATUS,Z
		movwf	FSR0L
	
		bcf		ADC_CONVERTING
		clrf	ADC_LOOPS
		return
	
ADC_WAITING
		movlw	ADC_RELAX_LOOPS
		xorwf	ADC_LOOPS,W
		btfsc	STATUS,Z
		goto	START_ADC_CONVERSION	
		
		incf	ADC_LOOPS,F
		return
	
START_ADC_CONVERSION
		bsf		ADCON0, GO			;start conversion
		bsf		ADC_CONVERTING		;indicate that we're converting a value	
		return
	
	

CHECK_MINUTES
		btfss	PIR1,TMR1IF
		return

		bcf		PIR1,TMR1IF
	
		movlw	0x0B		;timer each 500ms
		movwf	TMR1H
		movlw	0xDC
		movwf	TMR1L

		incf	AUX_MINUTES,F
		movf	AUX_MINUTES,W
		xorlw	.119
		btfss	STATUS,Z
		return

		clrf	AUX_MINUTES

		incfsz	USED_MINUTESL,F
		goto	OK_INC
	
		incf	USED_MINUTESH,F
		btfsc	STATUS,Z
		decf	USED_MINUTESH,F		;do not allow overflow

WRITE_HIGH
		movlw	EEPROM_MINUTESH
		banksel	EEADR
		movwf	EEADR
		banksel	USED_MINUTESH
		movf	USED_MINUTESH,W
		banksel	EEDAT
		movwf	EEDAT
		banksel	0

		call	WRITE_EEPROM
OK_INC

WRITE_LOW
		banksel	EECON1
		btfsc	EECON1,WR
		goto	$-1
		
		banksel	0

		movlw	EEPROM_MINUTESL
		banksel	EEADR
		movwf	EEADR
		banksel	USED_MINUTESL
		movf	USED_MINUTESL,W
		banksel	EEDAT
		movwf	EEDAT
		banksel	0

		call	WRITE_EEPROM

CHECK_READY		return

RESTORE_MINUTES
	movlw	EEPROM_MINUTESMAXL
	call	READ_EEPROM
	movwf	MAX_MINUTESL
	movlw	EEPROM_MINUTESMAXH
	call	READ_EEPROM
	movwf	MAX_MINUTESH

	movlw	EEPROM_MINUTESL
	call	READ_EEPROM
	movwf	USED_MINUTESL
	movlw	EEPROM_MINUTESH
	call	READ_EEPROM
	movwf	USED_MINUTESH
	return

READ_EEPROM
		banksel	EECON1
		btfsc	EECON1,WR	;wait for previous write to end
		goto	$-1

		movwf 	EEADR	 	;Address to read
		bsf 	EECON1,RD 	;EE Read
		movf 	EEDAT,W 	;Move data to W			
		banksel	0
		return

WRITE_EEPROM
		banksel	EECON1
		btfsc	EECON1,WR	;wait for previous write to end
		goto	$-1

		bsf 	EECON1,WREN ;Enable write
		bcf 	INTCON,GIE 	;Disable INTs
		movlw 	0x55 		;Unlock write
		movwf 	EECON2 		;
		movlw 	0xAA 		;
		movwf 	EECON2		;
		bsf 	EECON1,WR 	;Start the write
		bsf 	INTCON,GIE 	;Enable INTS		
		banksel	0
		return

		END