;==========================================================================
        Title  "Bike Advance"
;   http://www.perso.wanadoo.fr/transmic/
;       05 03 04      Version 4.23Beta  for 16f84     Thierry.P
; -------------------------------------------------------------------------
; Adaptation of the program Ign.txt "Auto Advance" from A. Nixon
; Title  "Auto Advance" for 16c54
;       24 08 94      Version 1.0      A. Nixon
;==========================================================================

        ;
        ; Ign advance starts at 1000 engine RPM
        ;
        ; Ign full advance is at 8000 engine RPM
        ;
        ; dwell time is fixed at 1mS, =  10 X 100uS loops
        ;
        ; After 1000 RPM, the ignition advance is calculated in 131 steps.
        ; This continues up until 8000 RPM is reached.
        ; 
        ;
        ; At a engine speed of 1200 RPM;
        ;
        ;        1200 / 60 = 20 revs per second
        ;          1 / 20 = 50mS per rev
        ;           1 rev = 360 degrees
        ;
        ;        36 degrees at 1200 RPM = (36 / 360) X 50 = 5mS
        ;
        ; Therefore maximum retard at 1200 RPM = 5mS after the firing
        ; point is reached. This figure remains constant down to 0 RPM.
        ;
        ; At a engine speed of 8000 RPM, maximum advance will have been reached,
        ; and ignition is immediately after the firing point is reached.
        ;
        ; The intermediate values will be looked up in an advance table map
        ; and will correspond to engine speed from 1000 RPM to 8000 RPM.
        ;
        ; As the engine RPM increases above 1000, the retard value becomes
        ; progressively lower until 8000 RPM is reached, whereby the 
        ; retard value will be 0.
        ; Under 1000 RPM the retard value is fixed at 12ms
        ;
        ;
        ; Map holds retard values in 100uS loops for every loop change
        ; in rpm rate.
        ;
        ;
        ;
;==========================================================================
;
;       PIC 16F84 wiring
;
;==========================================================================

	;                  
	;                        RA2   1+--O--+18  RA1
	;  pickup36°-----------> RA3   2|     |17  RA0
	;                        RA4   3|     |16  Osc ------ 4MHz
	;  +5V--+----R---------> MCLR  4|     |15  Osc ------ Quartz
	;  Ground--------------- Vss   5|     |14  Vcc ------ +5Vdc
	;  Thyristor    <------- RB0   6|     |13  RB7 ------>PickupLED
	;  LEDrpmLimit  <------- RB1   7|     |12  RB6
	;  ReverseOutput<------- RB2   8|     |11  RB5
	;                        RB3   9+-----+10  RB4 

;==========================================================================
;
;       Versions
;
;==========================================================================

        ; Version 2.3: add a reverse output to coil, detect rotor __-__
        ; Version 2.6: modif calculation, detect rotor --_--
        ; Version 2.8: modif register
        ; Version 3.0: correction at low RPM, or big retard.
        ; Version 3.1: deboun=1ms, initial delay=18ms, detect rotor high __-__
        ; Version 3.2: suppression extra pluses at low RPM
        ; Version 4.0: simplification, 4MHz cristal.trigger on decreasing edge
        ; Version 4.1: trigger on rising edge
        ; Version 4.2: map move at the end of the soft. max adv=0ms
        ;
        ;
        ;
        
;==========================================================================
;
;       Directives
;
;==========================================================================
        list p=16f84a    	; processor type
        ;
        __config  B'11111111110010'
        ; No code protect, PWRT on, no watchdog, Quartz 4to20Mhz
        ;
        ; Page 0: 0-FF page1: 100-1FF page2: 200-2FF page3: 300-3FF
;==========================================================================
;
;       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 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'

;==========================================================================
;
;       Define
;
;==========================================================================

#DEFINE rotor	PORTA,3     	; [pin2]= sensor input
#DEFINE coil	PORTB,0   	; [pin6]= output to coil
#DEFINE revcoil	PORTB,2		; [pin8]= reverse output to coil
#DEFINE rpmmax	PORTB,1    	; [pin7]= Min and Max RPM led
#DEFINE led	PORTB,7       	; [pin13]= pickup led

;==========================================================================
;
;       RAM Definition
;
;==========================================================================

rpmhi	equ 0Ch    	; RPM counter register high
rpmlo	equ 0Dh    	; RPM counter register low
dwell	equ 0Eh   	; dwell time counter
rtdset	equ 0Fh  	; retard value holding register
math	equ 11h   	; calculation register
coilflg	equ 12h    	; coil status
spkflg	equ 13h  	; flag after one spark
rotflg	equ 14h  	; rotor sense flag
retard	equ 15h  	; new retard value

;==========================================================================
;
;       Main Program
;
;==========================================================================


	org 0			; start adress 0
start   bsf    STATUS,RP0  	; go to bank 1
        movlw  H'FF'       	; set all portA..
        movlw  TRISA		; ..as inputs
        movlw  H'00'	 	; set all portB..
        movwf  TRISB		; ..as outputs
	;        			
        movlw b'11000001'	; no pull-up,rising edge int,internal timer,1:4
        movwf OPTION_REG
        bcf  STATUS,RP0    	; come back into bank 0
        ;
        clrw               	; clear all variables
        clrf PORTA         	; clear variables
        clrf PORTB
        clrf math
        clrf rpmlo
        clrf coilflg
        movlw 0xff         	; rpmhi = FF initially
        movwf rpmhi
        movwf spkflg		; no spark until pickup is high
        movwf rotflg		; and no spark loop if pickup stay up
	movwf retard		; retard value = 25ms initially
	;
        ;
        ;       100uS loop time
        ;       4MHz clock / 4 = 1MHz instruction cycle
        ;       cycle time = 1/1MHz  =  100uS
        ;       100uS/100uS  =  100 cycles
        ;       prescaler set to divide by 4
        ;       preset TMR0 = 231, when = 0  =  100uS
        ;       231 to 255 = 25 x 4(prescaler) = 100
        ;
        movlw .231	;movlw .206 for a 8MHz clock
        movwf TMR0
        ;
        ;
mnloop  movf TMR0,W
        btfss STATUS,Z		; is TMR0=0 ?
        goto mnloop     	; no, main delay loop
        ;
        movlw .231		; yes, re-preset TMR0 (240max)
        movwf TMR0
        ;
	incf rpmlo,F    	; increment rpmlo
        btfsc STATUS,Z  	; is rpmlo = 0 ?
        incf rpmhi,F    	; yes, increment rpmhi
        ;
	;       if rpm count > 1400h, 5120 x 100us=0.5 Secs, then it is assumed that the
        ;       motor has stopped. Reinitialize system.
        movlw 0x14
        subwf rpmhi,W
        btfsc STATUS,Z     	; rpmhi - 14 = 0 ?
        goto start         	; yes
        ;
        
rotchk  btfss rotor		; + is rotor high or low?
	;btfsc rotor		; (- detect pickup low)
        goto rnowlw             ; low
        ;
        movf rotflg,W   	; high, is it flagged high also? rotflg=FF?
        btfss STATUS,Z
        goto coilck     	; yes
        ;
        movlw 0xff 		; no
        movwf rotflg     	; flag rotor as up
        bsf led			; turn ignition pickup led on
	clrf spkflg	      	; reset flag for one spark
        goto rpmcalc		; calculate RPM
	;
	
rnowlw  movf rotflg,W   	; is it flagged low already ? rotflg=0?
        btfsc STATUS,Z
        goto coilck 	    	; yes, wasn't flagged high
        ;
        
dolow   bcf led		   	; no, turn ignition pickup led off
        clrf rotflg     	; flag rotor as down
        goto mnloop
        ;

decret	decf retard,F		; no, decrement retard then wait
	goto mnloop
	;
	                
coilck  movf coilflg,W	   	; is coil flagged high? coilflg=FF?
        btfss STATUS,Z
        goto upcoil             ; yes, then decrement dwell count
        movf retard,W		; is retard = 0 ?
        btfss STATUS,Z
        goto decret		; no, then decrement retard
        ;
	movf spkflg,W	   	; yes, a spark have been done? spkflg=FF?
        btfss STATUS,Z
        goto mnloop             ; yes, no more spark
        ;
        bsf coil		; no, go on for the first spark
        bcf revcoil
        movlw 0xff      	; set flag for high coil
        movwf coilflg
        movwf spkflg		; set flag for one spark
	
        ;   ****************** YOU CAN MODIFY THE DWELL VALUE BELLOW ********
        movlw .10		; 10 X 100uS  = 1mS
        movwf dwell		; set dwell time
        ;
        goto mnloop
	;
	
upcoil  ;       		if dwell # 0 then dwell - 1
        ;			if dwell now = 0, turn on coil
        ; 
        decfsz dwell,F  	; dwell = dwell - 1
        goto mnloop     	; dwell <> 0, wait
        bcf coil		; dwell = 0, turn coil off
        bsf revcoil	  	; dwell = 0, turn revcoil on
        clrf coilflg	      	; set flag for low coil
        goto mnloop
        ;

rpmcalc ;       engine RPM <= 1000 at maximum retard, = 60ms
	;	
        ;       60mS = 600 X 100us loops, = 258Ch
        ;       ( 1000RPM for a 1cyl - 4stroke with one spark loose )
        ;       ( 1000RPM for a 1cyl - 2stroke )
        ;       (  500RPM for a 4cyl - 4stroke = 16Hz )
        ;
        ;	engine RPM >= 8000 at maximum advance, = 7.5mS
        ;       7.5mS = 75 X 100uS loops, = 4Bh
        ;       ( 8000RPM for a 1cyl - 4stroke with one spark loose )
        ;       ( 8000RPM for a 1cyl - 2stroke )
        ;       (  4000RPM for a 4cyl - 4stroke = 133Hz )
        ;
        ;       this routine determines whether the engine RPM
        ;       value is below 75 loop counts - max advance, or above
        ;       600 loop counts - max retard, or some where in between.
        ;       
        ;       
        ; high RPM:     	; > 8000RPM
        ;
        movf rpmhi,W
        btfss STATUS,Z  	; is rpmhi = 0?
        goto bigfv      	; no
        ;
        movf rpmlo,W
        xorlw 0x4B	      	; yes, is rpmlo = 4Bh ?
        btfsc STATUS,Z
        goto maxadv     	; yes, do max advance
        ;
        movlw 0x4B
        subwf rpmlo,W   	; no, is rpmlo < 4Bh ?
        btfss STATUS,C
        goto maxadv     	; yes, do max advance
        ;
        ; medium RPM:
        goto caladv     	; no, calculate new advance
        ;
        ;
        ; low RPM:      	; < 1000RPM
bigfv   movf rpmhi,W
        xorlw .2        	; is rpmhi = 2 ?
        btfsc STATUS,Z
        goto resfv      	; yes, see if rpmlo = 58h
        ;
        movlw .2
        subwf rpmhi,W   	; no, is high byte > 2 ?
        btfsc STATUS,C
        goto maxret     	; yes, do max retard
        ;
        goto caladv     	; no, calculate new advance
        ;
resfv   movf rpmlo,W
        xorlw 0x58      	; rpmhi = 2, does rpmlo = 58h ?
        btfsc STATUS,Z
        goto maxret     	; yes, do max retard
        ;
        movlw 0x58
        subwf rpmlo,W   	; no, is rpmlo > 58h ?
        btfsc STATUS,C
        goto maxret     	; yes, do max retard
        ;
        ;
        ; the formula to get the data stored in the map is as follows
        ;
        ;                 rpmhi/lo count  -  74
        ;    131   -    ---------------------------
        ;                           4
        ;
caladv  movlw d'74'    		; rpmhi/lo - 74
        subwf rpmlo,F		; rpmlo = rpmlo - 74
        btfss STATUS,C
        decf rpmhi,F
        ;
        ; divide result by 4
        ;
        bcf STATUS,C
        rrf rpmhi,F
        rrf rpmlo,F     	; / 2
        ;
        bcf STATUS,C
        rrf rpmhi,F
        rrf rpmlo,F     	; / 4
        ;
        movlw .131      	; 131 entries in map list
        movwf math
        ;
        movf rpmlo,W
        subwf math,W    	; W = 131 - result
        ;
        bcf PCLATH,0		; be sure to go h'200'
        bsf PCLATH,1		; where is the map.
        call map		; read map
        movwf rtdset    	; come back with new retard value
        ;
rpmset  clrf rpmhi		; clear RPM counters
        clrf rpmlo
	movf rtdset,W		; transfert advance value
        movwf retard
        goto mnloop
        ;
maxret  movlw 0x32
        movwf rtdset     	; retard value = 32h (5ms)   258=600=16hz
        bcf rpmmax 		; turn off maxrpm led
        goto rpmset
        ;
maxadv  clrf rtdset      	; retard value = 0ms	4B=75=124hz
        bsf rpmmax	 	; turn on maxrpm led
        goto rpmset
        ;
map     org h'200'		; store map at 200h
	addwf PCL,1		; add W + PCL
	;  *********** INSERT YOUR OWN VALUES HERE *******************
                retlw 0h     ;0ms   1010rpm 
        retlw 0h     ;0ms   1016rpm 
        retlw 0h     ;0ms   1023rpm 
        retlw 0h     ;0ms   1030rpm 
        retlw 0h     ;0ms   1038rpm 
        retlw 0h     ;0ms   1045rpm 
        retlw 0h     ;0ms   1052rpm 
        retlw 0h     ;0ms   1060rpm 
        retlw 0h     ;0ms   1067rpm 
        retlw 0h     ;0ms   1075rpm 
        retlw 0h     ;0ms   1083rpm 
        retlw 0h     ;0ms   1090rpm 
        retlw 0h     ;0ms   1098rpm 
        retlw 0h     ;0ms   1107rpm 
        retlw 0h     ;0ms   1115rpm 
        retlw 0h     ;0ms   1123rpm 
        retlw 0h     ;0ms   1132rpm 
        retlw 0h     ;0ms   1140rpm 
        retlw 0h     ;0ms   1149rpm 
        retlw 0h     ;0ms   1158rpm 
        retlw 0h     ;0ms   1167rpm 
        retlw 0h     ;0ms   1176rpm 
        retlw 0h     ;0ms   1185rpm 
        retlw 0h     ;0ms   1195rpm 
        retlw 0h     ;0ms   1204rpm 
        retlw 0h     ;0ms   1214rpm 
        retlw 0h     ;0ms   1224rpm 
        retlw 0h     ;0ms   1234rpm 
        retlw 0h     ;0ms   1244rpm 
        retlw 0h     ;0ms   1255rpm 
        retlw 0h     ;0ms   1265rpm 
        retlw 0h     ;0ms   1276rpm 
        retlw 0h     ;0ms   1287rpm 
        retlw 0h     ;0ms   1298rpm 
        retlw 0h     ;0ms   1310rpm 
        retlw 0h     ;0ms   1321rpm 
        retlw 0h     ;0ms   1333rpm 
        retlw 0h     ;0ms   1345rpm 
        retlw 0h     ;0ms   1357rpm 
        retlw 0h     ;0ms   1369rpm 
        retlw 0h     ;0ms   1382rpm 
        retlw 0h     ;0ms   1395rpm 
        retlw 0h     ;0ms   1408rpm 
        retlw 0h     ;0ms   1421rpm 
        retlw 0h     ;0ms   1435rpm 
        retlw 0h     ;0ms   1449rpm 
        retlw 0h     ;0ms   1463rpm 
        retlw 0h     ;0ms   1477rpm 
        retlw 0h     ;0ms   1492rpm 
        retlw 0h     ;0ms   1507rpm 
        retlw 0h     ;0ms   1522rpm 
        retlw 0h     ;0ms   1538rpm 
        retlw 0h     ;0ms   1554rpm 
        retlw 0h     ;0ms   1570rpm 
        retlw 0h     ;0ms   1587rpm 
        retlw 0h     ;0ms   1604rpm 
        retlw 0h     ;0ms   1621rpm 
        retlw 0h     ;0ms   1639rpm 
        retlw 0h     ;0ms   1657rpm 
        retlw 0h     ;0ms   1675rpm 
        retlw 0h     ;0ms   1694rpm 
        retlw 0h     ;0ms   1714rpm 
        retlw 0h     ;0ms   1734rpm 
        retlw 0h     ;0ms   1754rpm 
        retlw 0h     ;0ms   1775rpm 
        retlw 0h     ;0ms   1796rpm 
        retlw 0h     ;0ms   1818rpm 
        retlw 0h     ;0ms   1840rpm 
        retlw 0h     ;0ms   1863rpm 
        retlw 0h     ;0ms   1886rpm 
        retlw 0h     ;0ms   1910rpm 
        retlw 0h     ;0ms   1935rpm 
        retlw 0h     ;0ms   1960rpm 
        retlw 0h     ;0ms   1986rpm 
        retlw 0h     ;0ms   2013rpm 
        retlw 0h     ;0ms   2040rpm 
        retlw 0h     ;0ms   2068rpm 
        retlw 0h     ;0ms   2097rpm 
        retlw 0h     ;0ms   2127rpm 
        retlw 0h     ;0ms   2158rpm 
        retlw 0h     ;0ms   2189rpm 
        retlw 0h     ;0ms   2222rpm 
        retlw 0h     ;0ms   2255rpm 
        retlw 0h     ;0ms   2290rpm 
        retlw 0h     ;0ms   2325rpm 
        retlw 0h     ;0ms   2362rpm 
        retlw FCh     ;25,2ms   2400rpm 
        retlw F7h     ;24,7ms   2439rpm 
        retlw F3h     ;24,3ms   2479rpm 
        retlw EEh     ;23,8ms   2521rpm 
        retlw EAh     ;23,4ms   2564rpm 
        retlw E6h     ;23ms   2608rpm 
        retlw E2h     ;22,6ms   2654rpm 
        retlw DDh     ;22,1ms   2702rpm 
        retlw D9h     ;21,7ms   2752rpm 
        retlw D4h     ;21,2ms   2803rpm 
        retlw D0h     ;20,8ms   2857rpm 
        retlw CCh     ;20,4ms   2912rpm 
        retlw C8h     ;20ms   2970rpm 
        retlw C3h     ;19,5ms   3030rpm 
        retlw BFh     ;19,1ms   3092rpm 
        retlw BBh     ;18,7ms   3157rpm 
        retlw B7h     ;18,3ms   3225rpm 
        retlw B2h     ;17,8ms   3296rpm 
        retlw AFh     ;17,5ms   3370rpm 
        retlw AAh     ;17ms   3448rpm 
        retlw A6h     ;16,6ms   3529rpm 
        retlw A2h     ;16,2ms   3614rpm 
        retlw 9Eh     ;15,8ms   3703rpm 
        retlw 9Ah     ;15,4ms   3797rpm 
        retlw 96h     ;15ms   3896rpm 
        retlw 91h     ;14,5ms   4000rpm 
        retlw 8Dh     ;14,1ms   4109rpm 
        retlw 89h     ;13,7ms   4225rpm 
        retlw 85h     ;13,3ms   4347rpm 
        retlw 81h     ;12,9ms   4477rpm 
        retlw 7Dh     ;12,5ms   4615rpm 
        retlw 79h     ;12,1ms   4761rpm 
        retlw 75h     ;11,7ms   4918rpm 
        retlw 71h     ;11,3ms   5084rpm 
        retlw 6Dh     ;10,9ms   5263rpm 
        retlw 6Ah     ;10,6ms   5454rpm 
        retlw 66h     ;10,2ms   5660rpm 
        retlw 62h     ;9,8ms   5882rpm 
        retlw 5Eh     ;9,4ms   6122rpm 
        retlw 5Ah     ;9ms   6382rpm 
        retlw 56h     ;8,6ms   6666rpm 
        retlw 52h     ;8,2ms   6976rpm 
        retlw 4Fh     ;7,9ms   7317rpm 
        retlw 4Bh     ;7,5ms   7692rpm 
        retlw 47h     ;7,1ms   8108rpm

        ;  *********** END OF YOUR OWN VALUES ******************************
        retlw 31h     ; in case of overlap
        ; line559
        ;
        ;       reset vector
        ;
        ;
        org 300h		; if the program is loose,
        ;
        ;
        ;
        goto start		; It goes back home.
        ;
        ;
        ;
        end
