;Dbacc4p: Modified by paco Caņada (17JUN02)
;	now when Fxa is turned on, Fxb is turned off and vice-versa, avoid simultaneous activation
;	of two coils of the same turnout. Added write enable pin.
;	Watchdog disabled for manual turnout control from MiniDCC
;Dbacc4:  Accessory decoder based on original loco decoder program by D Probst
;	Modifications by M. Bolton (2DEC98) and G.Ising (16OCT00)
;		MERG-DCC http://home.freeuk.net/merg/resources/dcc.htm 
;	Modified by Stefano Curtarolo (1NOV01)
;		Accessory decoder configuration variable access istruction
;		http://www.tttrains.com/nmradcc/rp921.html#accessory_packets
;		was added. NCE and SYS1 systems uses that protocol in accessory
;		OPS mode (prog-7-enter). 
;		For other DCC projects of Stefano Curtarolo pleas look @ MIT
;		web:   http://nietzsche.mit.edu/auro/trains/tech/DCC/
;	Program is intended to be used with the accessory decoder design    	
;	by M Bolton. The decoder is opto isolated so the ack function is a LED 
;	on the decoder board itself. No power booster is required but the signals
;	can be taken from the track if desired. 
;	A separate 20v AC power supply is needed.
;	Decoder includes circuitry to drive solenoid
;	point motors using a capacitor discharge technique. 
;
;	Tested with one set of four switches, with all addresses.
;	Seems OK so far.
;
;	Schematic, PCB layout and source listing (+ HEX file) available. Contact
;	Mike Bolton at bolton@fs1.with.man.ac.uk.
;
;	Details of a matching accessory encoder are also available.
;
;
;This is code for a PIC16F84 (or 16C84). This
;program will read three, four, and five byte packets and supports paged
;and direct CV servTRK mode access of CV data. 
;
;The decoder follows the NMRA standard for an Accessory Decoder. It controls
;four pairs of outputs with on times set by the CVs in increments of 
;10 millisecs. Range is 10 ms to 2.54 sec.or continuous.
;
;Supports 9 bit addressing.(3 byte packets) at present.

;The processor is configured to operate at 8MHz. 
;When programming,the fuses should be set with HS clock, WDT On.
;

;The following NMRA defined CV's and ranges are supported...

;CV513  Lower 6 address bits    00h - 3Fh  
;CV514  Auxiliary activation    00h - FFh  Bits 0 to 7.Each bit sets an output.
;					   1 is active, 0 is inactive   
;CV515  F1 function 'on' time   00h - FFh  Time in 10ms steps. 0 is continuous.
;CV516  F2  
;CV517  F3                                        
;CV518  F4
;CV519  Version Number     	00h -FFh   Cannot be changed (same as CV8)
;CV520  Manufacturers ID        00h -FFh   Cannot be changed (same as CV9)
;                
;CV521  Upper 3 bits of		00h -07h
;	address     
;CV541  Configuration		Bit 7 = 1  Cannot be changed (same as CV29)

;	No other CVs are supported.

        processor       16F84
	__CONFIG	h'3FF2' ; PUTimer on, WDT off, HS clock

;Variable definition - I/O Port assignments

;F1a  	equ    	PORTA,0		;pin 17
;F1b	equ	PORTA,1		;pin 18   
;F2a  	equ     PORTA,2		;pin 1
;F2b  	equ    	PORTA,3		;pin 2
;F3a	equ	PORTB,0		;pin 6
;F3b  	equ     PORTB,1		;pin 7
;F4a  	equ	PORTB,2    	;pin 8
;F4b	equ     PORTB,3		;pin 9              
;WRen	equ	PORTB,5		;pin 11 (enable write CV)
;ackout	equ	PORTB,6		;pin 12 (acknowledge)
;dat	equ	PORTB,7		;DCC data in

;Variable definition - PIC16F84 control registers.

f0      equ     00
rtcc    equ     01
optreg	equ	81	;page 1
pc      equ     02
STATUS  equ     03
Carry   equ    	0
Zbit    equ    	2
RP0     equ    	5
rp1     equ    	6
fsr     equ     04
PORTA   equ     05
F1	equ	05
F2	equ	05
ddra	equ	85	;page 1
PORTB   equ     06
F3	equ	06
F4	equ	06
ddrb	equ	86	;page 1
EEDATA  equ     08
EEARD   equ     09
EECON1  equ     08
rd      equ    	0
WR      equ    	1
WREN    equ    	2
EECON2  equ     09
pclath  equ     0A
intcon  equ     0B
f       equ    	1
w       equ    	0

;Varible definition - User RAM.

addcfg  equ    	0C    	;address configuration
primary equ    	0     	;accessory address match
reset 	 equ    1     	;reset packet
brdcst	equ	2	;accessory broadcast
servTRK equ    	3
servOPS equ    	4
idle	equ	5
konfig	equ     0D
value   equ    	0
byte4   equ    	1     	;not used yet
byte5   equ    	2 	;not used yet

;registers

count   equ     0E	;counts which output
CV513a  equ     0F	;holds CV513 low address bits
CV521a  equ     10	;holds CV521 high address bits
CV514a	equ	11	;which outputs to activate
CV541a   equ    12	;config CV
data1   equ     13	;first packet byte
data2   equ     14	;second packet byte
data3   equ     15
data4   equ     16
data5   equ     17
endval  equ     18
lastd1  equ     19
lastd2  equ     1A
lastd3  equ     1B
lastd4  equ     1C
action	equ     1D	;4 bits of accessory command
tick1	equ     1E	;counts 10 millisec intervals
time1	equ     20	;on time for output 1 etc.
time2	equ	21
time3	equ	22
time4	equ	23
time5	equ	24
time6	equ	25
time7	equ	26
time8	equ	27

pagereg equ     28
m       equ     29	;as in Dean Probst's decode
n       equ     2A
state   equ     2B
temp    equ     2C
  


;Init sets as all outputs, pin b7 as input and the rest of PORTB as
;outputs and sets the rtcc counter to divide by 32 (16us at 8MHz clock).
;FSR is set to 88h for indirect access to EECON register from page 00.

Init    bsf	STATUS,RP0	;set to page 1
;	movlw	B'00010000'	;port a0-3 outputs a4input 	STEFANO-MERG
	movlw	B'00010000'	;port a outputs 		MERG-STEFANO-PACO
	movwf	ddra
;	movlw	B'00000000'	;port b0-8 outputs		STEFANO-MERG
 	movlw	B'10110000'	;port b 7 is data in		MERG-STEFANO-PACO
	movwf	ddrb
	movlw	B'10000100'	;set option reg RTCC /32
	movwf	optreg
	bcf	STATUS,RP0
	clrf    PORTA
        clrf    PORTB
        clrf    intcon
        movlw   0x88
        movwf   fsr
        
        clrf    state
        clrf    m
        clrf    n
        clrf    konfig
        clrf	action

;The following routine loops between Starthi and Startlo in a precisely 
;timed sequence that samples track voltage at 22us intervals, decodes the
;incoming packet, and updates the decoder outputs. When a change in 
;voltage is detected, a half-bit is defined and the subroutine 
;Getstat is called to check the value of the half-bit and decode the 
;sequence. Subsequent delays between samplings call the update subroutine 
;to update the outputs and timing registers of the microcontoller. At 22us, 
;the values of the half-bits are determined as follows:
;
;       Delays          Possible Duration
;       1               1us  - 43us
;       2               23us - 65us
;       3               45us - 87us
;       4               67us - up
;
;With these values, one delay will be 43us or less and will reset 
;the packet decode sequence. Two or three delays will be 23us to 87us and 
;will be recognized as a hi (1) half-bit. This completely encompasses the 
;duration required by the NMRA DCC standards of 52us to 64us. Four or more 
;delays will be 67us or greater and are recognized as a low (0) half-bit.
;Again, this meets the NMRA DCC requirements of 90us to 10000us. Durations of
;~18ms in length, such as DC or when the signal is lost, will cause the
;watch dog timer to reset, reseting the decoder. 

;                               timing

Starthi call    Getval          ;3
Conthi  btfss   PORTB,7       	;44/0/88	MERG-STEFANO
;Conthi  btfss   PORTA,4       	;44/0/88	STEFANO-MERG
        goto    Startlo         ;45/1
        btfss   m,7             ;46
        incf    m,f             ;47        
        call    Update          ;48
        goto    Conthi          ;86

Startlo call    Getval          ;3
Contlo  btfsc   PORTB,7       	;44/0/88	MERG-STEFANO
;Contlo  btfsc   PORTA,4       	;44/0/88	STEFANO-MERG
        goto    Starthi         ;45/1
        btfss   m,7             ;46
        incf    m,f             ;47       
        call    Update          ;48
        goto    Contlo          ;86

;Getval checks m for a value of 0 (reset), 1 or 2 (hi) or greater (low).
;It then checks state for a value less than or equal to 24 (18h) and then
;adds state to pc register (program counter) to offset execution to a 
;specific subroutine.

Getval  incf    n,f             ;5
        movf    m,w             ;6
        btfsc   STATUS,Zbit     ;7
        goto    Resetv          ;8
;        clrwdt                  ;9
	nop			;9 *********
        clrf    m               ;10
        bcf     konfig,value    ;11
        addlw   0xFD            ;12
        btfss   STATUS,Carry    ;13
        bsf     konfig,value    ;14
        btfsc   STATUS,Carry    ;15
        clrf    n               ;16
        movlw   0xE7            ;17
        addwf   state,w         ;18
        btfsc   STATUS,Carry    ;19
        clrf    state           ;20
        movf    state,w         ;21
        addwf   pc,f            ;22
                                              ;state
        goto    Waitn           ;24             ;0     
        goto    Waitlo                          ;1
        goto    Testlo                          ;2

        goto    Bitset                          ;3
        goto    Lastv                           ;4
        goto    Bitset                          ;5
        goto    Lastv                           ;6
        goto    Bitset                          ;7
        goto    Lastv                           ;8
        goto    Bitset                          ;9
        goto    Lastv                           ;10
        goto    Bitset                          ;11
        goto    Lastv                           ;12
        goto    Bitset                          ;13
        goto    Lastv                           ;14
        goto    Bitset                          ;15
        goto    Lastv                           ;16
        goto    Bitset                          ;17
        goto    Endx                            ;18

        goto    End1                            ;19
        goto    End2                            ;20
        goto    End3                            ;21
        goto    End4                            ;22
        goto    End5                            ;23
        
;This is the last state of the packet decode sequence. It first checks for
;a high half-bit. It then XORs the five data bytes to check packet parity. 
;It then checks addcfg register flags to determine instruction address 
;and branches to CVserv or Decode.

        clrf    state           ;24        state = 24
        btfss   konfig,value    ;25
ret16   goto    ret14           ;26
        movf    addcfg,w        ;27
        btfsc   STATUS,Zbit     ;28
        goto    ret11           ;29
        movf    data1,w         ;30
        xorwf   data2,w         ;31
        xorwf   data3,w         ;32
        xorwf   data4,w         ;33
        xorwf   data5,w         ;34
        btfss   STATUS,Zbit     ;35
        goto    ret4            ;36
        btfsc   addcfg,servOPS
        goto    CVservOPS       ;       if(SERVOPS_MODE) goto CVservOPS
        btfsc   addcfg,servTRK  ;37
        goto    CVserv          ;38
        clrf    n               ;39     
        bcf     konfig,servTRK	;40
        bcf     konfig,servOPS	;40
        	

Decode  ;btfsc	addcfg,primary
	;nop
	movf    data2,w         ;Dcontrl	action
	andlw	0xE0		;000
	btfsc	STATUS,Zbit 	;reset packet
	goto	Dcontrl 
	btfss	data2,7		;accessory instruction?
	goto	noacc
	movf	data2,w		;recover byte		
        andlw   B'00001111'     ;mask
	movwf	action		;decoder instruction (four bits)
	bsf	action,7	;set new action
noacc	return  

Nextbyt	return
       

Resetv  clrf    state           ;11
        clrf    n               ;12
        goto    ret27           ;13

;Counter jumps to alternating output update routines. It is called from the
;Update routine.

Counter incf    count,f         ;55
        movlw   B'00000111'     ;56
        andwf  	count,w         ;57
        addwf   pc,f            ;58
        goto	count1		;60
        goto    count2  
        goto    count3
        goto    count4
	goto	count5
        goto	count6
	goto	count7
	goto	count8

;CVpage is for three byte servTRK mode addressing (page addressing). It 
;uses the page register and the offset in data1 to calculate the CV number. 
;The data in data2 is moved to data3 and the calculated CV is stored in
;data2.

CVpage  movf    data2,w                
        movwf   data3
        movlw   0x07
        andwf   data1,w
        addwf   pc,f

        goto    CVfind
        goto    CVfind
        goto    CVfind
        goto    CVfind
        goto    CV541s
        goto    CVpgreg
        return
        return                                 
        
;

;Waitn waits for 20 hi half-bits (ten hi bits of the pre-amble) to start
;the decode sequence. Also reads CV514

Waitn   movlw   0xEC            ;26
        addwf   n,w             ;27
        btfss   STATUS,Carry    ;28
        goto    ret11           ;29
        incf    state,f         ;30
        clrf    data3           ;31
        clrf    data4           ;32
        clrf    addcfg          ;33
        clrf    endval          ;34
	movlw   0x01            ;35     EE=1    CV514
        movwf   EEARD           ;36
        bsf     f0,rd           ;37
        movf    EEDATA,w        ;38
	movwf	CV514a		;39
        nop	        	;40
	nop			;41
	nop			;42
	return     
        

;Waitlo waits for a low bit to signal the end of the pre-amble. Also reads
;CV513 

Waitlo  btfss   konfig,value    ;26
        incf    state,f         ;27
        movlw   0x00            ;28     EE=0    CV513
        movwf   EEARD           ;29
        bsf     f0,rd           ;30
        movf    EEDATA,w        ;31
        movwf   CV513a          ;32     lower 6 address bits
        bsf		CV513a,7        ;33     10AAAAAA to match 1st byte
        goto	ret6			;34
        

;Testlo must have a low half-bit. Also reads CV521.

Testlo  incf    state,f         ;26
        btfsc   konfig,value    ;27
        clrf    state           ;28
        movlw   0x08            ;29	get CV521 (00000AAA)              
        movwf   EEARD           ;30                  
        bsf     f0,rd           ;31
        movf    EEDATA,w        ;32
        movwf	CV521a          ;33	upper 3 address bits
        rlf		CV521a,f		;34
        rlf     CV521a,f        ;35
        rlf     CV521a,f        ;36
        rlf     CV521a,f        ;37	now 0AAA0000
       	comf	CV521a,f		;38     top address is complemeted
        movlw	B'01110000'     ;39     mask other bits             
        andwf   CV521a,f    	;40
        nop		        		;41
        return                  ;42
        
;Bitset reads the value of the just finished half-bit and rotates it
;into the LSB of data5. Eight cycles through Bitset will read a 
;complete byte of data. 
        
Bitset  incf    state,f         ;26
        bcf     STATUS,Carry    ;27
        btfsc   konfig,value    ;28
        bsf     STATUS,Carry    ;29
        rlf     data5,f         ;30
        goto	ret9		;31
ret2    goto    ret0            

;Lastv checks for the current half-bit to be the same as the previous
;half-bit. 

Lastv   incf    state,f         ;26
        btfss   konfig,value    ;27
        goto    lastv1          ;28
        btfss   data5,0         ;29
        clrf    state           ;30
	goto	ret9
lastv1  btfsc   data5,0         ;30
        clrf    state           ;31
ret10	goto	ret8		;32
       

;Endx compares the present half-bit to the previous half-bit (same as
;lastv) and then determines the offset for the intermediate bits.

Endx    btfss   konfig,value    ;26
        goto    endx1           ;27
        btfss   data5,0         ;28
        comf    state,f         ;29           
        goto    endx2           ;30
endx1   btfsc   data5,0         ;29
        comf    state,f         ;30
        nop                     ;31
endx2   incf    endval,f        ;32
        movf    endval,w        ;33
        addwf   state,f         ;34
        goto    ret5            ;35

;Intermediate bit after first byte - must be low. End1 also checks for
;broadcast and servTRK mode address.

End1    movlw   0x02            ;26
        movwf   state           ;27
        movf    data5,w         ;28
        movwf   data1           ;29
        btfsc   konfig,value    ;30
        clrf    state           ;31
        movf    data1,w         ;32	get first byte
; RESET PACKET CHECK
        btfsc	STATUS,Zbit     ;33
        bsf	addcfg,reset   	;34	yes so set bit 
; BROADCAST PACKET CHECK
        xorlw	B'10111111'     ;35	accessory broadcast low bits?
        btfsc	STATUS,Zbit     ;36
        bsf	addcfg,brdcst   ;37	set broadcast bit
; IDLE PACKET CHECK
        movf    data1,W         ;32	GET 1st byte in W
        xorlw	B'11111111'     ;35	IDLE ?
        btfsc	STATUS,Zbit     ;36
        bsf	addcfg,idle     ;37	if B'11111111' set IDLE bit
; OUT OF CYCLE
        movf	data1,w         ;38 
        andlw	B'01111111'	;39	;acc address has top bit set
        addlw	0x90            ;40
        btfsc   STATUS,Carry	;41
        bsf     addcfg,servTRK  ;42	servTRK so set bit
       	return          	;43

;Intermediate bit after second byte - must be low. End2 also checks for
;primary address (9 bits)and rest of broadcast.

End2    movlw   0x02            ;26
        movwf   state           ;27
        movf    data5,w         ;28
        movwf   data2           ;29
        btfsc   konfig,value    ;30
        clrf    state           ;31
; SERVICE-OPS CHECK
; 0 10AAAAAA 0 0AAACCaa 0 aaaaaaaa 0 DDDDDDDD 0 EEEEEEEE 1
        movf    data2,W         ;32     2nd byte
        andlw   B'10001100'     ;33     mask about  0AAA11aa
        xorlw   B'00001100'     ;34     mask to get 0xxx11xx
        btfsc   STATUS,Zbit     ;36
        bsf     addcfg,servOPS  ;37
; IDLE CHECK
        btfss   addcfg,idle
        goto    End2b
        movf    data2,W         ;38     2nd byte
        btfss   STATUS,Zbit     ;40     all zeros?
        bcf     addcfg,idle     ;41     IDLE only if we had idle before
; BROADCAST CHECK
End2b   movf    data2,W         ;38     2nd byte
        andlw	B'01110000'     ;33	mask except hi address bits
	btfss   STATUS,Zbit     ;34	all zeros?
        bcf     addcfg,brdcst   ;35	not broadcast	
; ADDRESSES CHECK BANK0 513a 512a
        bsf     addcfg,primary  ;43   
        movf    data2,W         ;       2nd byte             
        andlw   B'01110000'     ;       mask except hi addr     
        xorwf	CV521a,w	;36	hi bits match?
        btfsc	STATUS,Zbit     ;37
        bsf	addcfg,primary  ;38	yes
        movf	data1,w         ;39	get first byte
        xorwf   CV513a,w        ;40	match?
        btfsc   STATUS,Zbit     ;41
	return
End2c   bcf     addcfg,primary  ;42	n
	bcf	addcfg,servOPS	;59	if dont match clear SERVICE-OPS
        return                  ;43

;Intermediate bit after third byte - hi signals end of packet.

End3    btfsc   konfig,value    ;26
        goto    end3hi          ;27
        movlw   0x02            ;28
        movwf   state           ;29
        movf    data5,w         ;30
        movwf   data3           ;31
        goto    ret8            ;32

end3hi  movlw   0x18            ;29
        movwf   state           ;30
        bcf     konfig,byte4    ;31
        bcf     konfig,byte5    ;32
ret9    goto    ret7            ;33

;Intermediate bit after fourth byte - hi signals end of packet.

End4    btfsc   konfig,value    ;26
        goto    end4hi          ;27
        movlw   0x02            ;28
        movwf   state           ;29
        movf    data5,w         ;30
        movwf   data4           ;31
        goto    ret8            ;32

end4hi  movlw   0x18            ;29
        movwf   state           ;30
        bsf     konfig,byte4    ;31
        bcf     konfig,byte5    ;32
        goto    ret7            ;33

;End bit after fifth byte - must be hi.

End5    incf    state,f         ;26
        btfss   konfig,value    ;27
        clrf    state           ;28
        bsf     konfig,byte4    ;29
        bsf     konfig,byte5    ;30
        goto    ret9            ;31

;This subroutine is used to update the outputs of the microcontroller. 
;The rtcc is compared with the value 63. As rtcc increments every 16
;microsecs, count will match at about 1 millisec.A match condition (=>)
;will increment tick1 and reset the rtcc. Tick1 is compared with 10 and
;if => then all channel timers, (time1 to time8) are incremented.This
;sets the fundamental time interval at 10 millisec.
;Between tick1 updates, routine switches to 'Counter' which accesses each
;output routine in turn to see if the outputs should be on or off.

Update  movlw   .63             ;50		one millisec approx
        subwf   rtcc,w          ;51
        btfss   STATUS,Carry    ;52
        goto    Counter         ;53
        incf	tick1,f         ;54
        clrf	rtcc 		;55		reset rtcc
        nop           		;56
        movlw   .10         	;57
        subwf	tick1,w 	;58             
        btfss	STATUS,Carry 	;59             10ms
ret22   goto	ret20		;60
        clrf	tick1      	;61             
        incf    time1,f       	;62 		increment channel timers           
        incf    time2,f    	;63             
        incf    time3,f       	;64             
        incf    time4,f       	;65
        incf    time5,f       	;66
        incf    time6,f       	;67
        incf    time7,f       	;68
        incf    time8,f       	;69                     
        goto	ret12       	;70               
                   
        		       
                       


;Count1 controls output1 

count1 	btfss   action,7        ;62	new action
        goto	t1a             ;63	no
        movf	action,w      	;64
        andlw	B'00000111'     ;65	mask
        xorlw	B'00000000'     ;66	is it output 1?
        btfss   STATUS,Zbit     ;67	yes
        goto    t1b          	;68
        btfss   CV514a,0       	;69	is this bit enabled?
        goto    t1c             ;70	no
        btfss	action,3        ;71	on or off
        goto	off1            ;72
        bsf	PORTA,0        	;73	F1a on
	bcf	PORTA,1		;	******
	clrf	tick1		;74
	clrf	time1      	;75  	start timer   
        bcf	action,7      	;76	action done
        goto	ret4		;77	*******
off1	bcf	PORTA,0		;74	F1a off
	bcf	action,7       	;75
	goto	ret6		;76
t1a	nop			;65
	nop			;66
	nop			;67
	nop			;68
	nop			;69
t1b	nop			;70
	nop			;71
t1c	movlw	2		;72	get CV515 time on
	movwf	EEARD		;73
	bsf	f0,rd		;74
	movf	EEDATA,w	;75
	btfsc	STATUS,Zbit	;76	if zero then always on
	goto	ret5		;77
	subwf	time1,w		;78	compare time
	btfsc	STATUS,Carry	;79
	bcf	PORTA,0		;80 	time out so put off
	goto	ret2

ret13	goto	ret11
ret11	goto	ret9
ret5    goto	ret3
ret3	goto	ret1	
                        
ret1    nop                     ;83
ret0    return                  ;84



;Count2 controls F1b
 
count2 	btfss   action,7        ;62	new action
        goto	t2a             ;63	no
        movf	action,w      	;64
        andlw	B'00000111'     ;65	mask
        xorlw	B'00000001'     ;66	is it output 1b?
        btfss   STATUS,Zbit     ;67	yes
        goto    t2b          	;68
        btfss   CV514a,1       	;69	is this bit enabled?
        goto    t2c             ;70	no
        btfss	action,3        ;71	on or off
        goto	off2            ;72
        bsf	PORTA,1        	;73	F1b on
	bcf	PORTA,0		; **********
	clrf	tick1		;74
	clrf	time2      	;75  	start timer   
        bcf	action,7      	;76	action done
        goto	ret4		;77	*****
off2	bcf	PORTA,1		;74	F1b off
	bcf	action,7       	;75
	goto	ret6		;76

t2a	nop			;65
	nop			;66
	nop			;67
	nop			;68
	nop			;69
t2b	nop			;70
	nop			;71
t2c	movlw	2		;72	get CV515 time on
	movwf	EEARD		;73
	bsf	f0,rd		;74
	movf	EEDATA,w	;75
	btfsc	STATUS,Zbit	;76	if zero then always on
	goto	ret5		;77
	subwf	time2,w		;78	compare time
	btfsc	STATUS,Carry	;79
	bcf	PORTA,1		;80 	time out so put off
	goto	ret2


;Count3 controls F2a

count3 	btfss   action,7        ;62	new action
        goto	t3a             ;63	no
        movf	action,w      	;64
        andlw	B'00000111'     ;65	mask
        xorlw	B'00000010'    ;66	is it output 2a?
        btfss   STATUS,Zbit     ;67	yes
        goto    t3b          	;68
        btfss   CV514a,2       	;69	is this bit enabled?
        goto    t3c             ;70	no
        btfss	action,3        ;71	on or off
        goto	off3            ;72
        bsf	PORTA,2        	;73	F2a on
	bcf	PORTA,3		;	*********
	clrf	tick1		;74
	clrf	time3      	;75  	start timer   
        bcf	action,7      	;76	action done
        goto	ret4		;77	*********
off3	bcf	PORTA,2		;74	F2a off
	bcf	action,7       	;75
	goto	ret6		;76
t3a	nop			;65
	nop			;66
	nop			;67
	nop			;68
	nop			;69
t3b	nop			;70
	nop			;71
t3c	movlw	3		;72	get CV516 time on
	movwf	EEARD		;73
	bsf	f0,rd		;74
	movf	EEDATA,w	;75
	btfsc	STATUS,Zbit	;76	if zero then always on
	goto	ret5		;77
	subwf	time3,w		;78	compare time
	btfsc	STATUS,Carry	;79
	bcf	PORTA,2		;80 	time out so put off
	goto	ret2



;Count4 controls F2b

count4 	btfss   action,7        ;62	new action
        goto	t4a             ;63	no
        movf	action,w      	;64
        andlw	B'00000111'     ;65	mask
        xorlw	B'00000011'     ;66	is it output F2b?
        btfss   STATUS,Zbit     ;67	yes
        goto    t4b          	;68
        btfss   CV514a,3       	;69	is this bit enabled?
        goto    t4c             ;70	no
        btfss	action,3        ;71	on or off
        goto	off4            ;72
        bsf	PORTA,3        	;73	F2b on
	bcf	PORTA,2		; 	********
	clrf	tick1		;74
	clrf	time4      	;75  	start timer   
        bcf	action,7      	;76	action done
        goto	ret4		;77	*******
off4	bcf	PORTA,3		;74	F2b off
	bcf	action,7       	;75
	goto	ret6		;76
t4a	nop			;65
	nop			;66
	nop			;67
	nop			;68
	nop			;69
t4b	nop			;70
	nop			;71
t4c	movlw	3		;72	get CV516 time on
	movwf	EEARD		;73
	bsf	f0,rd		;74
	movf	EEDATA,w	;75
	btfsc	STATUS,Zbit	;76	if zero then always on
	goto	ret5		;77
	subwf	time4,w		;78	compare time
	btfsc	STATUS,Carry	;79
	bcf	PORTA,3		;80 	time out so put off
	goto	ret2



;Count5 controls output F3a

count5 	btfss   action,7        ;62	new action
        goto	t5a             ;63	no
        movf	action,w      	;64
        andlw	B'00000111'     ;65	mask
        xorlw	B'00000100'     ;66	is it output F3a?
        btfss   STATUS,Zbit     ;67	yes
        goto    t5b          	;68
        btfss   CV514a,4       	;69	is this bit enabled?
        goto    t5c             ;70	no
        btfss	action,3        ;71	on or off
        goto	off5            ;72
        bsf	PORTB,0        	;73	F3a on
	bcf	PORTB,1		; 	*********
	clrf	tick1		;74
	clrf	time5      	;75  	start timer   
        bcf	action,7      	;76	action done
        goto	ret4		;77	*********
off5	bcf	PORTB,0		;74	F3a off
	bcf	action,7       	;75
	goto	ret6		;76
t5a	nop			;65
	nop			;66
	nop			;67
	nop			;68
	nop			;69
t5b	nop			;70
	nop			;71
t5c	movlw	4		;72	get CV517 time on
	movwf	EEARD		;73
	bsf	f0,rd		;74
	movf	EEDATA,w	;75
	btfsc	STATUS,Zbit	;76	if zero then always on
	goto	ret5		;77
	subwf	time5,w		;78	compare time
	btfsc	STATUS,Carry	;79
	bcf	PORTB,0		;80 	time out so put off
	goto	ret2

;Count6	controls the output F3b

count6 	btfss   action,7        ;62	new action
        goto	t6a             ;63	no
        movf	action,w      	;64
        andlw	B'00000111'     ;65	mask
        xorlw	B'00000101'     ;66	is it output F3b?
        btfss   STATUS,Zbit     ;67	yes
        goto    t6b          	;68
        btfss   CV514a,5       	;69	is this bit enabled?
        goto    t6c             ;70	no
        btfss	action,3        ;71	on or off
        goto	off6            ;72
        bsf	PORTB,1        	;73	F3b on
	bcf	PORTB,0		;	***********
	clrf	tick1		;74
	clrf	time6      	;75  	start timer   
        bcf	action,7      	;76	action done
        goto	ret4		;77	***********
off6	bcf	PORTB,1		;74	F3b off
	bcf	action,7       	;75
	goto	ret6		;76
t6a	nop			;65
	nop			;66
	nop			;67
	nop			;68
	nop			;69
t6b	nop			;70
	nop			;71
t6c	movlw	4		;72	get CV517 time on
	movwf	EEARD		;73
	bsf	f0,rd		;74
	movf	EEDATA,w	;75
	btfsc	STATUS,Zbit	;76	if zero then always on
	goto	ret5		;77
	subwf	time6,w		;78	compare time
	btfsc	STATUS,Carry	;79
	bcf	PORTB,1		;80 	time out so put off
	goto	ret2

;Count7	controls output F4a

count7 	btfss   action,7        ;62	new action
        goto	t7a             ;63	no
        movf	action,w      	;64
        andlw	B'00000111'     ;65	mask
        xorlw	B'00000110'     ;66	is it output F4a?
        btfss   STATUS,Zbit     ;67	yes
        goto    t7b          	;68
        btfss   CV514a,6       	;69	is this bit enabled?
        goto    t7c             ;70	no
        btfss	action,3        ;71	on or off
        goto	off7            ;72
        bsf	PORTB,2        	;73	F4a on
	bcf	PORTB,3		; 	*******
	clrf	tick1		;74
	clrf	time7      	;75  	start timer   
        bcf	action,7      	;76	action done
        goto	ret4		;77	**********
off7	bcf	PORTB,2		;74	F4a off
	bcf	action,7       	;75
	goto	ret6		;76
t7a	nop			;65
	nop			;66
	nop			;67
	nop			;68
	nop			;69
t7b	nop			;70
	nop			;71
t7c	movlw	5		;72	get CV518 time on
	movwf	EEARD		;73
	bsf	f0,rd		;74
	movf	EEDATA,w	;75
	btfsc	STATUS,Zbit	;76	if zero then always on
	goto	ret5		;77
	subwf	time7,w		;78	compare time
	btfsc	STATUS,Carry	;79
	bcf	PORTB,2		;80 	time out so put off
	goto	ret2

;Count8	controls output F4b

count8 	btfss   action,7        ;62	new action
        goto	t8a             ;63	no
        movf	action,w      	;64
        andlw	B'00000111'     ;65	mask
        xorlw	B'00000111'     ;66	is it output F4b?
        btfss   STATUS,Zbit     ;67	yes
        goto    t8b          	;68
        btfss   CV514a,7       	;69	is this bit enabled?
        goto    t8c             ;70	no
        btfss	action,3        ;71	on or off
        goto	off8            ;72
        bsf	PORTB,3        	;73	F4b on
	bcf	PORTB,2		; 	********
	clrf	tick1		;74
	clrf	time8      	;75  	start timer   
        bcf	action,7      	;76	action done
        goto	ret4		;77	********
off8	bcf	PORTB,3		;74	F4b off
	bcf	action,7       	;75
	goto	ret6		;76
t8a	nop			;65
	nop			;66
	nop			;67
	nop			;68
	nop			;69
t8b	nop			;70
	nop			;71
t8c	movlw	5		;72	get CV518 time on
	movwf	EEARD		;73
	bsf	f0,rd		;74
	movf	EEDATA,w	;75
	btfsc	STATUS,Zbit	;76	if zero then always on
	goto	ret5		;77
	subwf	time8,w		;78	compare time
	btfsc	STATUS,Carry	;79
	bcf	PORTB,3		;80 	time out so put off
	goto	ret2

    
ret7    goto    ret5            ;77        
ret6    goto    ret4            ;78

;Additional goto sequences.

ret27   goto    ret25           ;15 
ret25   goto    ret23           ;17
ret24   goto    ret22  
ret23   goto    ret21           ;19
			        ;20 62
ret21   goto    ret19           ;21 63
ret20   goto    ret18           ;22 64
ret19   goto    ret17           ;23 65
ret18   goto    ret16           ;24 66
ret17   goto    ret15           ;25 67
ret15   goto    ret13           ;27 69
ret14   goto    ret12           ;28 70
ret12   goto    ret10           ;30 72
ret8    goto    ret6            ;34 76
ret4	goto	ret2


; ********************************************************************************
; ********************************************************************************
; ********************************************************************************
; ********************************************************************************

;CVservOPS checks/WRites for servOPS mode instructions with the decoder in 
;servOPS mode. If the CV number in data2 is 06h (CV519), 07h (CV520)or 
;1Ch (CV541), then the WRite does not take place.

CVservOPS
	; 	 btfss   konfig,byte5
	;        return
        btfss   addcfg,servOPS  ;
        return                  ;
        clrf    n
        call    Twonrow         ; check two identical packets
        iorlw   0x00            ; check two identical packets
        btfsc   STATUS,Zbit     ; check two identical packets
        return                  ; check two identical packets
        movf    data2,W
        andlw   B'00000011'     ; at least CV513 !
        xorlw   B'00000010'     ; at least CV513 !
        btfss   STATUS,Zbit     ; at least CV513 !
        return                  ; nothing done
        movf    data3,W         ;addresses start at 0
        xorlw   0x06            ; CV519    CV520   CV541
        btfsc   STATUS,Zbit     ;00000110 00000111 00011100
        return  ; got 519       ;00000110 00000110 00000110 XOR 0x06=00000110  
        xorlw   0x01            ;00000000 00000001 00011010
        btfsc   STATUS,Zbit     ;         00000001 00000001 XOR 0x01=00000010
        return  ; got 520       ;         00000000 00011011 
        xorlw   0x1B            ;                  00011011 XOR 0x1B=00011011
        btfsc   STATUS,Zbit     ;                  00000000
        return  ; got 541       ;
        movf    data3,W         ;addresses start at 0   
        sublw   0x1F            ;only CVs 513(0x00) to 542(0x1D)
        btfss   STATUS,Carry
        return
; all ok, now WRite EEARD as data3  EEDATA as data4
        movfw   data3           ;
        movwf   EEARD           ;
        movfw   data4           ; 
        movwf   EEDATA          ;
        call    EEWRite 	;
        bcf     addcfg,servOPS  ;
        call    Ackn            ;
        return                  ; WRITTEN OPS !!!!

;CVserv checks for servTRK mode instructions with the decoder in servTRK
;mode. It then checks values of data1, data2, data3 and data4 with previous
;values to ensure a duplicate packet has been sent. It then checks for
;three or four byte packet to determine paged or direct CV access. 

CVserv  btfss   konfig,byte5    ;40
        btfss   konfig,servTRK  ;41
        return                  ;42
        clrf    n
        nop
        call    Twonrow
        iorlw   0x00
        btfsc   STATUS,Zbit
        return
        btfss   konfig,byte4
        goto    CVpage
        movf    data1,w
        xorlw   0x76	; [gi] DIR Mode cmd: 0111CCAA where AA=10 for CV >512
        btfsc   STATUS,Zbit
        goto    Ver1dir ; [gi] data2 contains offset in EEDATA
        xorlw   0x08
        btfss   STATUS,Zbit
        return
	goto	WR1dir	; [gi] data2 contains offset in EEDATA
        
;WR1 WRites the data in data3 into the CV listed in data2. If the CV
;number in data2 is 06h (CV519), 07h (CV520)or 1Ch (CV541), then the WRite
;does not take place.

WR1	decf	data2,f			; [gi] Jump Target for PageMode (data2=CV#)
WR1dir	movf    data3,w			; [gi] data2 now contains offset in EEDATA. 
        movwf   EEDATA      
        movf	data2,w    				 ;addresses start at 0       
        xorlw   0x06                    ;  CV519   CV520   	CV521	  CV541
        btfsc   STATUS,Zbit             ;00000110 00000111 00001000	00011100
        return                          ;00000110 00000110 00000110	00000110
        xorlw   0x01                    ;00000000 00000001 00001111	00011010
        btfsc   STATUS,Zbit             ;         00000001 00000001	00000001
        return                          ;         00000000 00001110	00011011
        xorlw   0x1B                    ;                  			00011011
        btfsc   STATUS,Zbit             ;                  			00000000
        goto    WRcon1
WRcont  movlw	09h			;only CVs 513(1) to 521(9)
	subwf	data2,w
	btfsc	STATUS,Carry
	return
WRcon1	movf    data2,w
        movwf   EEARD
;        clrwdt			; ********
        call    EEWRite
        goto    Ackn

;Two in a row checks that the current packet is the second identical packet
;before performing a servTRK mode instruction or Advanced programming
;function.

Twonrow movf    data1,w        
        xorwf   lastd1,w
        btfss   STATUS,Zbit
        goto    Lastpak
        movf    data2,w
        xorwf   lastd2,w
        btfss   STATUS,Zbit
        goto    Lastpak
        movf    data3,w
        xorwf   lastd3,w
        btfss   STATUS,Zbit
        goto    Lastpak
        movf    data4,w
        xorwf   lastd4,w
        btfsc   STATUS,Zbit
        retlw   0xFF

;Lastpak saves the packet byte values to check for a repeated packet,
;necessary to execute a servTRK mode instruction.

Lastpak movf    data1,w
        movwf   lastd1
        movf    data2,w
        movwf   lastd2
        movf    data3,w
        movwf   lastd3
        movf    data4,w
        movwf   lastd4
        retlw   0x00                 

;CV541s sets data2 to 1Ch (28).    

CV541s  movlw   0x1C
        movwf   data2
        goto    CVcont

;CVfind determines the CV using the page register and the offset in the
;instruction. If the page is less than 128 then no action is taken as it
;is not an accessory CV. 

CVfind  decf    pagereg,w
        movwf   data2
        bcf     STATUS,Carry
        rlf     data2,f
        btfss   STATUS,Carry		;page must be 80h or more
        return
        rlf     data2,f
        
        movlw   0x03
        andwf   data1,w
        addwf   data2,f
CVcont  btfss   data1,3
        goto    Ver1
        goto    WR1

;CVpgreg verifies or WRites the page register with data3 (data2).

CVpgreg btfss   data1,3
        goto    Pagever
        movf    data3,w
        movwf   pagereg
        return

Pagever movf    pagereg,w                        
        xorwf   data3,w                            
        btfss   STATUS,Zbit
        return
        goto    AcknV		; ******
        
;CVverfy XORs the EE value at data2 with the value in data3.
;only CV 513 to 521 and 541 will verify. 

Ver1    decf	data2,f	        ; [gi] Jump Target for PageMode (data2=CV#)
				; [gi] data2 now contains offset in EEDATA

Ver1dir movlw	1Ch		;is it CV541
	xorwf	data2,w
	btfsc	STATUS,Zbit
	goto	ver2
	movlw	09h		;only CVs 513(1) to 521(9)
	subwf	data2,w
	btfsc	STATUS,Carry
	return
ver2	movf    data2,w 	;CVs address directly        
        movwf   EEARD
        call    EEread
        xorwf   data3,w
        btfss   STATUS,Zbit
        return
        goto    AcknV		; ******

Dcontrl	btfss	konfig,byte5
	btfsc	konfig,byte4
        return
        movf	data2,w
        btfsc	STATUS,Zbit
        goto	Dreset
        xorlw	0x0E
        btfsc	STATUS,Zbit
        goto	AcknV		; ******  Ack request
        return

Dreset	clrf	action		;clear action
	btfss	addcfg,reset
        return
        bsf	konfig,servTRK
        goto	Nextbyt



;Ackn sets ack output for 250ms (1024us X 5). 1024us is counted by
;bit 6 of rtcc register.Ack is used to flash the ack LED

Ackn:
	btfsc	PORTB,5		; *****  check write enable
	return			; *****
AcknV:				; *****    
;	clrwdt			; *********
       	bsf	PORTB,6		;set ack line high
        clrf    rtcc
        movlw   .250          
        movwf   temp
aloop   btfss   rtcc,6
        goto    aloop
        bcf     rtcc,6
        decfsz  temp,f
        goto    aloop
        bcf	PORTB,6		;set ack line low
        return

        

;Generic EE WRite subroutine that WRites EEDATA into EEARD. If the processor
;is busy with a previous WRite operation, the subroutine returns without
;WRiting. Inputs are EEARD and eeread.

EEWRite 
	btfsc	PORTB,5		; ****** check write enable
	return			; ******
	bsf	STATUS,RP0
	bsf	EECON1,WREN
	movlw   0x55
        movwf   EECON2
        movlw   0xAA
        movwf   EECON2
        bsf     EECON1,WR
eeWRcon btfsc   EECON1,WR
        goto    eeWRcon
        bcf     EECON1,WREN
        bcf     STATUS,RP0
        return


;EEread uses the file selct register to read the data stored in the EE
;memory location pointed to by EEARD.

EEread  bsf     f0,rd
        movf    EEDATA,w
asmend	return

        ORG     0x2100

        DATA    0x01	; cv513
        DATA    0xFF	; cv514
        DATA    0x0A	; cv515
        DATA    0x0A	; cv516
        DATA    0x0A	; cv517
        DATA    0x0A	; cv518
        DATA    0x00	; cv519
        DATA    0x0D	; cv520
        DATA    0x00	; cv521
        DATA    0x00
        DATA    0x00
        DATA    0x00
        DATA    0x00
        DATA    0x00
        DATA    0x00
        DATA    0x00
        DATA    0x00
        DATA    0x00
        DATA    0x00
        DATA    0x00
        DATA    0x00
        DATA    0x00
        DATA    0x00
        DATA    0x00
        DATA    0x00
        DATA    0x00
        DATA    0x00
        DATA    0x00
        DATA    0x80	; cv541
        DATA    0x00
        DATA    0x00
        DATA    0x00

        END

