;Dbacc5; Merg-AuroTrains accessory decoder with PIC16F628. 
;       Based on original loco decoder program by D Probst
;	Porting to PIC16F628 by Stefano Curtarolo (10NOV01)
;		web:  http://nietzsche.mit.edu/auro/trains/tech/DCC/
;	Developed with GNU LINUX FREE SOFTWARE: www.gnupic.org
;	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 PIC16F628. 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       16F628
	__CONFIG	h'3F26' ; PUTimer on, WDT on, 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              
;ackout	equ	PORTB,6		;pin 12 (acknowledge)
;dat	equ	PORTB,7		;DCC data in

; Variable definition - PIC16F628 control registers.
; Updated bu Stefano Curtarolo. Note the EEDATA and 
; EEADR are in bank1, but the addresses 
; 70h-7Fh, F0h-FFh, 170h-17Fh,1F0h-1FFh are in common 
; between banks.

f       equ    	1
W       equ    	0
TMR0    equ     01h
PC      equ     02h
STATUS  equ     03h	; STATUS
Carry   equ    	0	; STATUS
Zbit    equ    	2	; STATUS
RP0     equ    	5	; STATUS
RP1     equ    	6	; STATUS
FSR     equ     04h
PORTA   equ     05h
PORTB   equ     06h
PCLATH  equ     0Ah
INTCON  equ     0Bh	; INTCON
GIE	equ	7
PIR1	equ	0Ch
TMR1L	equ	0Eh
TMR1H	equ	0Fh
T1CON	equ	10h
TMR2	equ	11h
T2CON	equ	12h
CCPR1L	equ	15h
CCPR1H	equ	16h
CCP1CON	equ	17h
RCSTA	equ	18h
TXREG	equ	19h
RCREG	equ	1Ah
CMCON	equ	1Fh
f       equ    	1
W       equ    	0
EEDATA0 equ	7Eh
EEADR0  equ	7Fh

OPTIONR	equ	81h	;page 1
TRISA	equ	85h	;page 1
TRISB	equ	86h	;page 1
PIE1	equ	8Ch
PCON	equ	8Eh
PR2	equ	92h
TXSTA	equ	98h
SPBRG	equ	99h
EEDATA  equ     9Ah
EEADR   equ     9Bh
EECON1  equ     9Ch
RD      equ    	0
WR      equ    	1
WREN    equ    	2
WRERR   equ    	3
EECON2  equ     9Dh
EEDATA1 equ	0xFE
EEADR1  equ	0xFF

;Varible definition - User RAM.

addcfg  equ    	0x20    	;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
config	equ     0x21
value   equ    	0
byte4   equ    	1     	;not used yet
byte5   equ    	2 	;not used yet

;registers

count   equ     0x22	;counts which output
CV513a  equ     0x23	;holds CV513 low address bits
CV521a  equ     0x24	;holds CV521 high address bits
CV514a	equ	0x25	;which outputs to activate
CV541a   equ    0x26	;config CV
data1   equ     0x27	;first packet byte
data2   equ     0x28	;se8cond packet byte
data3   equ     0x29
data4   equ     0x2A
data5   equ     0x2B
endval  equ     0x2C
lastd1  equ     0x2D
lastd2  equ     0x2E
lastd3  equ     0x2F
lastd4  equ     0x30
action	equ     0x31	;4 bits of accessory command
tick1	equ     0x32	;counts 10 millisec intervals
time1	equ     0x33	;on time for output 1 etc.
time2	equ	0x34
time3	equ	0x35
time4	equ	0x36
time5	equ	0x37
time6	equ	0x38
time7	equ	0x39
time8	equ	0x30

pagereg equ     0x3A
m       equ     0x3B	;as in Dean Probst's decode
n       equ     0x3C
state   equ     0x3D
temp    equ     0x3E
  


;Init sets as all outputs, pin b7 as input and the rest of PORTB as
;outputs and sets the TMR0 counter to divide by 32 (16us at 8MHz clock).
;FSR is set to 88h for indirect access to EECON register from page 00.

Init    bcf     STATUS,RP1	;set off banks2,3
	bsf	STATUS,RP0	;set to page 1
;	movlw	B'00010000'	;port a0-3 outputs a4input 	STEFANO-MERG
	movlw	B'00000000'	;port a outputs 		MERG-STEFANO
	movwf	TRISA
;	movlw	B'00000000'	;port b0-8 outputs		STEFANO-MERG
 	movlw	B'10000000'	;port b 7 is data in		MERG-STEFANO
	movwf	TRISB
	movlw	B'10000100'	;set option reg TMR0 /32
	movwf	OPTIONR
	bcf	STATUS,RP0	; set to page 0
	movlw	B'00000111'	;
	movwf	CMCON		; turn comparstors OFF
	clrf    PORTA
        clrf    PORTB
        clrf    INTCON
        movlw   0x88
        movwf   FSR
        
        clrf    state
        clrf    m
        clrf    n
        clrf    config
        clrf	action

;	call	reset

;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
        clrf    m               ;10
        bcf     config,value    ;11
        addlw   0xFD            ;12
        btfss   STATUS,Carry    ;13
        bsf     config,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 CVservTRK or Decode.

        clrf    state           ;24        state = 24
        btfss   config,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    CVservTRK          ;38
        clrf    n               ;39     
        bcf     config,servTRK	;40
        bcf     config,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
	call	EEreadW		;
 	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   config,value    ;
        incf    state,f         ;
        movlw   0x00            ;     EE=0    CV513
	call	EEreadW		;
        movwf   CV513a          ;     lower 6 address bits
        bsf	CV513a,7        ;     10AAAAAA to match 1st byte
        goto	ret6			;34
        

;Testlo must have a low half-bit. Also reads CV521.

Testlo  incf    state,f         ;26
        btfsc   config,value    ;27
        clrf    state           ;28
        movlw   0x08            ;29	get CV521 (00000AAA)              
	call	EEreadW		;
        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   config,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   config,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   config,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   config,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   config,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   config,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     config,byte4    ;31
        bcf     config,byte5    ;32
ret9    goto    ret7            ;33

;Intermediate bit after fourth byte - hi signals end of packet.

End4    btfsc   config,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     config,byte4    ;31
        bcf     config,byte5    ;32
        goto    ret7            ;33

;End bit after fifth byte - must be hi.

End5    incf    state,f         ;26
        btfss   config,value    ;27
        clrf    state           ;28
        bsf     config,byte4    ;29
        bsf     config,byte5    ;30
        goto    ret9            ;31

;This subroutine is used to update the outputs of the microcontroller. 
;The TMR0 is compared with the value 63. As TMR0 increments every 16
;microsecs, count will match at about 1 millisec.A match condition (=>)
;will increment tick1 and reset the TMR0. 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   TMR0,w          ;51
        btfss   STATUS,Carry    ;52
        goto    Counter         ;53
        incf	tick1,f         ;54
        clrf	TMR0 		;55		reset TMR0
        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
	clrf	tick1		;74
	clrf	time1      	;75  	start timer   
        bcf	action,7      	;76	action done
        goto	ret5		;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
	call	EEreadW	
	movf	EEDATA0,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
	clrf	tick1		;74
	clrf	time2      	;75  	start timer   
        bcf	action,7      	;76	action done
        goto	ret5		;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
	call	EEreadW
	movf	EEDATA0,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
	clrf	tick1		;74
	clrf	time3      	;75  	start timer   
        bcf	action,7      	;76	action done
        goto	ret5		;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
	call	EEreadW
	movf	EEDATA0,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
	clrf	tick1		;74
	clrf	time4      	;75  	start timer   
        bcf	action,7      	;76	action done
        goto	ret5		;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
	call	EEreadW
	movf	EEDATA0,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
	clrf	tick1		;74
	clrf	time5      	;75  	start timer   
        bcf	action,7      	;76	action done
        goto	ret5		;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
	call	EEreadW
	movf	EEDATA0,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
	clrf	tick1		;74
	clrf	time6      	;75  	start timer   
        bcf	action,7      	;76	action done
        goto	ret5		;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
	call	EEreadW
	movf	EEDATA0,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
	clrf	tick1		;74
	clrf	time7      	;75  	start timer   
        bcf	action,7      	;76	action done
        goto	ret5		;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
	call	EEreadW
	movf	EEDATA0,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
	clrf	tick1		;74
	clrf	time8      	;75  	start timer   
        bcf	action,7      	;76	action done
        goto	ret5		;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
	call	EEreadW
	movf	EEDATA0,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   config,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
;        call    Ackn            ; DEBUG
        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 EEADR0 as data3  EEDATA0 as data4
        movfw   data3           ;
        movwf   EEADR0          ;
        movfw   data4           ; 
        movwf   EEDATA0         ;
        call    EEwrite 	;
        bcf     addcfg,servOPS  ;
        call    Ackn            ;
        return                  ; WRITTEN OPS !!!!

;CVservTRK 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. 

CVservTRK  btfss   config,byte5    ;40
        btfss   config,servTRK  ;41
        return                  ;42
        clrf    n
        nop
        call    Twonrow
        iorlw   0x00
        btfsc   STATUS,Zbit
        return
        btfss   config,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 EEDATA0
        xorlw   0x08
        btfss   STATUS,Zbit
        return
	goto	WR1dir	; [gi] data2 contains offset in EEDATA0
        
;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 EEDATA0. 
        movwf   EEDATA0      
        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   EEADR0
        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    Ackn
        
;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 EEDATA0

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   EEADR0
        call    EEread
        xorwf   data3,w
        btfss   STATUS,Zbit
        return
        goto    Ackn

Dcontrl	btfss	config,byte5
	btfsc	config,byte4
        return
        movf	data2,w
        btfsc	STATUS,Zbit
        goto	Dreset
        xorlw	0x0E
        btfsc	STATUS,Zbit
        goto	Ackn
        return

Dreset	clrf	action		;clear action
	btfss	addcfg,reset
        return
        bsf	config,servTRK
        goto	Nextbyt


;Ackn sets ack output for 250ms (1024us X 5). 1024us is counted by
;bit 6 of TMR0 register.Ack is used to flash the ack LED

Ackn    clrwdt
       	bsf	PORTB,6		;set ack line high
;	comf	PORTB		; DEBUG STEFANO-MERG
        clrf    TMR0
        movlw   .250          
        movwf   temp
aloop   btfss   TMR0,6
        goto    aloop
        bcf     TMR0,6
        decfsz  temp,f
        goto    aloop
;	comf	PORTB		; DEBUG STEFANO-MERG
        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.
;EEread uses the file selct register to read the data stored in the EE
;memory location pointed to by EEARD.


EEwrite	bsf	STATUS,RP0	; bank1
	movf	EEADR1,W	; get from copy of bank0
	movwf	EEADR		; 
	movf	EEDATA1,W	; get from copy of bank0
	movwf	EEDATA		;
        bsf     EECON1,WREN	; enable write EEPROM capability
	bcf	INTCON,GIE	; 
	movlw   0x55		;
	movwf   EECON2		; write 55h
	movlw   0xAA		;
	movwf   EECON2		; write AAh
        bsf     EECON1,WR	; set WE bit enable write, start writing
EEWRcon btfsc   EECON1,WR	; wait until WRITE is over
        goto    EEWRcon		; wait until WRITE is over
        bcf     EECON1,WREN	; disable write EEPROM capability
	bcf	STATUS,RP0	; bank0
	return			;
EEreadW	movwf   EEADR0		; read what is in W	
EEread  bsf	STATUS,RP0	; Bank 1
	movf	EEADR1,W	; get from copy of bank0
	movwf   EEADR           ; Address to read
	bsf	EECON1,RD	; EE Read
        movf    EEDATA,W        ; W = EEDATA
	movwf	EEDATA1		; EEDATA1 = EEDATA
	bcf	STATUS,RP0	; Bank 0
	return			;

; ****************************************************
; extra DEBUG STUFF
; ********************************************************************************
; STANDARD RESET CONFIGURATION CVS
resetCV
        call    reset513        ;
        call    reset514        ;
        call    reset515        ;
        call    reset521        ;
        return                  ;
reset513 movlw 0x01             ; CV513a DEFAULT
        movwf   EEDATA0         ;
        movlw   0x00            ;
        movwf   EEADR0          ;
        goto    EEwrite         ;
reset514 movlw 0xFF             ; CV514 DEFAULT
        movwf   EEDATA0         ;
        movlw   0x01            ;
        movwf   EEADR0          ;
        goto    EEwrite         ;
reset515 movlw 0x0A             ; CV514 DEFAULT
        movwf   EEDATA0         ;
        movlw   0x02            ;
        movwf   EEADR0          ;
        call    EEwrite         ;
	incf	EEADR0		;
        call    EEwrite         ;
	incf	EEADR0		;
        call    EEwrite         ;
	incf	EEADR0		;
        call    EEwrite         ;
	return
reset521 movlw 0x00             ; CV521a DEFAULT
        movwf   EEDATA0         ;
        movlw   0x08            ;
        movwf   EEADR0          ;
        goto    EEwrite         ;

fakeaddresses
	movlw B'10000001'	;
	movwf CV513a		;
	movlw B'01110000'	;
	movwf CV521a		;
	return			;

; ********************************************************************************


        ORG     0x2100
        DATA    0x01	;513
        DATA    0xFF	;514
        DATA    0x0A	;515
        DATA    0x0A	;516
        DATA    0x0A	;517
        DATA    0x0A	;518
        DATA    0x00	;519
        DATA    0x00	;520
        DATA    0x00	;521
        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
        DATA    0x00
        DATA    0x00
        DATA    0x00

        END
