;	GM_counter program
;	2013. szeptember 12.
		list p=18F242
		#include "p18F242.inc"
;-------------------------------------------------------------------
		ORG 0x00
ZERO	bra SETUP
;-------------------------------------------------------------------
		ORG 0x08
INTRPT1	bcf INTCON, GIE, 0; interrupt disable (stack save)
		bra INTRPT
		ORG 0x18
INTRPT2 bcf INTCON, GIE, 0; interrupt disable (stack save)
		bra INTRPT
;-------------------------------------------------------------------
		CBLOCK 0x10
		RTMR0; 10H TMR0L preset value. (TMR0H register presetting in SETUP prg)
		RSWITCH; 11H Status register of swithches
		RRESL; 12H Result lo register
		RRESH; 13H Result hi register
		RADMAXH; 14H Max. A/D value hi byte
		RADMAXL; 15H Max. A/D value lo byte
		RTIMEPRL; 16H TIME preset lo (integral time in 0,1s unit)
		RTIMEPRH; 17H TIME preset hi (integral time in 0,1s unit)
		RTIMCNTL; 18H Present TIME COUNTER lo (0,1s unit)
		RTIMCNTH; 19H Present TIME COUNTER lo (0,1s unit)
		RVOVER; 1AH If RVOVER = 0, POWER CK enable, if > 0, than disable
		ENDC
;--------------------------------------------------------------------------
		ORG 0x100;
SETUP	nop
		__CONFIG 0x300001, 0x02; HS osc, PLL disable
		__CONFIG 0x300002, 0x00; Brown out reset disable, PWRT enable
		__CONFIG 0x300003, 0x0E; WDT disable, control=WDTEN, postscaler=128, 
		__CONFIG 0x300005, 0x00; PORTB A/D disable, CCP2 and RB3 multiplexed
;		__CONFIG 0x300006, 0x01; DEBUGGER enable, LVP disable, STACK-RESET
		__CONFIG 0x300006, 0x81; DEBUGGER disable, LVP disable, STACK-RESET
		bcf RCON, IPEN, 0; Interrupt priority disable
		bcf INTCON, GIE, 0; Valamennyi interrupt disable
		bcf INTCON, PEIE, 0; Pheripheral interrupt disable
		bcf PIE1, ADIE, 0; A/D interrupt disable
		bcf INTCON, RBIE, 0; PORTB change interrupt disable
		bsf INTCON2, RBPU, 0; PORTB pull-ups disable
		bcf INTCON2, INTEDG0, 0; Interrupt at PORTB0 falling edge 
		movlw 0xFF;
		movwf TRISA, 0; PORTA input
		movlw B'10000001'; analog input AN0, A/D module powered
		movwf ADCON0, 0; (Fosc/32)x10bit = 32 microsec, A/D stop
		movlw B'10001101'; AN3=Vref+, AN2=Vref-
		movwf ADCON1, 0; A/D converter ready for starting
		movlw 0x02; RADMAXH = 2 (512d)
		movwf RADMAXH, 0; A/D max limit hi byte
		movlw 0x34; RADMAXL = 34h (52d)
		movwf RADMAXL, 0; A/D max limit preset = 564d (320V)
		clrf T3CON, 0; TIMER3 stand by48
		setf TMR3H, 0; TMR3H register = FFh
		movlw 0xD0; TMR3L preset (25 microsec on/off to the coil)
		movwf TMR3L, 0; TIMER3 ready for starting
		bsf T3CON, RD16, 0; TIMER3 16bit R/W mode
		clrf T0CON, 0; TIMER0 16 bits counter
		bsf T0CON, T0PS1, 0; clock = fosc/8
		movlw 0x85; TIMER0H preset
		movwf TMR0H, 0;
		movlw 0xED; TIMER0L preset
		movwf TMR0L, 0; (0,1s timer ready)
		movwf RTMR0, 0; TMR0 preset value to register
		movlw 0xF0;
		movwf TRISC, 0; PORTC 0~3bit output, 4~7bit input
		movwf LATC, 0; PORTC 0~3bit = 0V
		clrf RRESH, 0;
		clrf RRESL, 0;
		movf PORTC, 0; Status of switches to W
		andlw 0xF0; Masking the switches status bits
		movwf RSWITCH, 0; Save the INTEGRAL TIME switch status
		call INTTIME; Integral time preset
		clrf RTIMCNTL, 0; TIMER counter clear
		clrf RTIMCNTH, 0; TIMER counter clear
; ---------------------------------------------------------- PWM setup:
		movlw 0xFF; max. freq. 39,06 kHz, if Fclock=10MHz
		movwf PR2, 0;(max. output duty cycle FFh, at 8 bit resolution) 
		movlw B'00001100'; PWM mode, 8 bit resolution
		movwf CCP1CON, 0; 
		movlw 0xD0; decimal 200 (max. normal output duty cycle)
		movwf CCPR1L, 0;
		movlw B'00000110'; 
		movwf T2CON, 0; TIMER2 start, prescaler = 16
; -------------------------------------------------------- PWM setup end		
		movlw B'00110000';
		movwf T1CON, 0; TIMER1 prescaler 1:8
		clrf TMR1L, 0; GM dead time counter ready
		bsf INTCON, TMR0IE, 0; TIMER0 (0,1s timer) interrupt enable
		bsf T0CON, TMR0ON, 0; TIMER0 START
		bsf PIE2, TMR3IE, 0; TIMER3 interrupt enable
		bsf T3CON, TMR3ON, 0; TIMER3 start (GM POWER clock)
		bsf INTCON, INT0IE, 0; INT0 (RB0) interrupt enable (GM signal sense)
		bsf INTCON,PEIE, 0; Interrupt enable
		clrf ADRESH, 0; A/D result hi byte clear
		bsf ADCON0, 2, 0; A/D conversion start
		clrf RVOVER, 0; GM power out enable
; ------------------------------------------------------------------
MAIN	btfss ADCON0, 2, 0; skip, if A/D not yet not ready
		bsf ADCON0, 2, 0; A/D conversion start
		bcf INTCON, GIE, 0; Interrupt disable
		movf RSWITCH, 0, 0; It were the status of the switches
		xorwf PORTC, 0, 0; There are change?
		andlw 0xF0; masking
		btfss STATUS, Z, 0; Skip if NOT SWITCH CHANGE
		reset; SWITCH CHANGE: NEW START
		bsf INTCON, GIE, 0; Interrupt enable
		movf RADMAXH, 0, 0; GM overvoltage testing (RADMAX = 512d)
		cpfslt ADRESH, 0; skip if A/D < 512d
		call GMOVER; Overvoltage testing
		movlw 0x4B; 4Bh=75d
		cpfslt TMR1L, 0; skip if deadtime counter < 120 us
		call DEADTME;Deadtime counter stop and clear
		bra MAIN;
; ------------------------------------------------------------------
;                        		SUBRUTINES
INTTIME	clrf RTIMEPRH, 0; 
		movlw 0x01; 0,1s integral time
		btfss RSWITCH, 7, 0; skip if not switching
		movwf RTIMEPRL, 0; preset time: 0,1s
		movlw 0x0A; 1s integral time
		btfss RSWITCH, 6, 0; skip if not switching
		movwf RTIMEPRL, 0; preset time: 1s
		movlw 0x64; 10s integral time
		btfss RSWITCH, 5, 0; skip if not switching
		movwf RTIMEPRL, 0; preset time: 10s 
		movlw 0xE8; 100s integral time (1000x0,1s=3E8h)
		btfss RSWITCH, 4, 0; skip if not switching
		movwf RTIMEPRL, 0; preset time: 100s 
		xorwf RTIMEPRL, 0, 0; Need useing the RTIMEPRH?
		bnz CONTi; Skip if not zero
		movlw 0x03; (100s = 03E8h)
		movwf RTIMEPRH, 0; preset time 100s
CONTi	clrf WREG, 0; W = 0
		cpfseq RSWITCH, 0; skip if all switches ON
		return
		setf RTIMEPRH, 0; max time (All swithches there are ON)
		movlw 0xD0; decimal 200 (max. normal output duty cycle)
		movwf CCPR1L, 0;
		return
GMOVER	movf RADMAXH, 0, 0; W=2 (A/D max. hi byte)
		cpfseq ADRESH, 0; skip if A/D hi byte = 2 (512d)
		bra GMOVER1; GM voltage clock disable
		movf RADMAXL, 0, 0; W=34h
		cpfslt ADRESL, 0; skip if A/D value < 564d
		bra GMOVER1; GM voltage clock disable
		clrf RVOVER, 0; GM voltage clock enable
		return
GMOVER1	movlw 0xFF;
		movwf RVOVER, 0; GM voltage clock disable
		return
DEADTME bcf T1CON, TMR1ON, 0; TIMER1 (dead time counter) STOP
		clrf TMR1L, 0; deadtime counter clear
		bsf INTCON, INT0IE, 0; INT0 (RB0) interrupt enable (GM signal sense)
		return
; ------------------------------------------------------------------
;								INTERRUPT
INTRPT	btfsc PIR2, TMR3IF, 0;
		call GMCLOCK; GM POWER clock toggle interrupt
		btfsc INTCON, TMR0IF, 0;
		call TIME; 0,1s 
		btfsc INTCON, INT0IF, 0;
		call PULSE; There are GM PULSE
		bsf INTCON, GIE, 0; interrupt enable
		retfie 1; return from interrupt
GMCLOCK	movf RVOVER, 0, 0;
		bz TOGLE; If GM POWER CLOCK enable, skip
		bcf LATC, 1, 0; If GM POWER CLOCK disable, PORTC1=0V
		movlw 0xD0; TMR3L preset (25 microsec on/off to the coil)
		movwf TMR3L, 0; do TMR3H refreshing also
		bcf PIR2, TMR3IF, 0; TIMER3 interrupt flag clear
		return
TOGLE	btg LATC, 1, 0; bit change
		movlw 0xD0; TMR3L preset (25 microsec on/off to the coil)
		movwf TMR3L, 0; do TMR3H refreshing also
		bcf PIR2, TMR3IF, 0; TIMER3 interrupt flag clear
		return
; -----------------------------------------------------------------
TIME	infsnz RTIMCNTL, 1, 0; skip, if TIMCNT > 0
		incf RTIMCNTH, 1, 0; incremented, if RTIMCNTL overflowed
		movlw 0x04; max, hi byte preset value + 1
		cpfslt RTIMCNTH, 0; skip, if RTIMCNTH <= 3
		RESET; TIMER misstake RESET 
		movf RTIMEPRL, 0, 0; TIMEPRESET lo to W
		cpfseq RTIMCNTL, 0; skip if RTIMCNTL = RTIMEPRL
		bra TIMEND; NOT PRESET TIME
		movf RTIMEPRH, 0, 0; TIMEPRESET hi to W
		cpfseq RTIMCNTH, 0; skip if RTIMCNTH = RTIMEPRH
		bra TIMEND; NOT PRESET TIME
		clrf RTIMCNTL, 0; New cycle beginning
		clrf RTIMCNTH, 0; New cycle beginning
		clrf STATUS, 0; All status bit zero
		rlcf RRESL, 1, 0; result counter multiply by 2
		movff RRESL, CCPR1L; Result to the PWM
		movlw D'201'; Max result value + 1
		cpfslt RRESL, 0; Skip if result <= 200
		setf CCPR1L, 0; Overload: FFh to the PWM
		clrf RRESL, 0; Pulse number register clear
		movf RRESH, 0, 0; Result hi byte to the WREG
		bz TIM; Branch if not OVER
		setf CCPR1L, 0; Overload: FFh to the PWM
TIM		clrf RRESH; Pulse number over byte clear
TIMEND	movff RTMR0, TMR0L; TIMER0 set up (0,1s START)
		bcf INTCON, TMR0IF, 0; TMR0IF clear
		return
; -------------------------------------------------------------------
PULSE 	bsf T1CON, TMR1ON, 0; TIMER1 START (DEAD TIME COUNTER START)
		infsnz RRESL, 1, 0; inrement and skip if not zero result lo byte
		incf RRESH, 1, 0; increment the result counter hi byte
		bcf INTCON, INT0IF, 0; Input pulse flag clesr 
		return
end