;**************************************************************************
;* PROGRAMMA OM 16 SERVO'S AAN TE STUREN MET DCC PROTOCOL                 *
;*                                                                        *
;* Geschreven door Geert Giebens voor PIC 16F887 microcontroller          *
;*                                                                        *
;* Datum: 15 februari 2013                Versie PIC16F887_SERVO_DCC_V3.3 *
;*                                                                        *
;* Filenaam: servosturingDCC_v3p3.asm                                     *
;*								          *
;* Aanpassingen versie 3.2:					          * 
;*   -T0 uit ISR gehaald                                       		  *
;*                        					          *
;* Aanpassingen versie 3.3:					          * 
;*   -Relais uitgangen appart DCC adres gegeven: ADR5, ADR6, ADR7 en ADR8 *
;*   -EEWRITE SUBROUTINE ingevoerd (i.p.v. elke schrijfopdracht apart)    *
;*   -Foutje in bereking ADR LOW er uit gehaald: punt voor 64 -->.64 (DEC)*
;*                        					          *
;*                        					          *
;*                         _____________________		          *
;*       ingang keuze MIN | 1  RE3 *  *  RB7 40 | Relais 10               *
;*                Relais 1| 2  RA0  **   RB6 39 | Relais 11               *
;*                Relais 2| 3  RA1       RB5 38 | Relais 12               *
;*                Relais 3| 4  RA2       RB4 37 | Relais 13               *
;*                Relais 4| 5  RA3   I   RB3 36 | Relais 14               *
;*                Relais 5| 6  RA4   C   RB2 35 | Relais 15               *
;*                Relais 6| 7  RA5       RB1 34 | Relais 16               *
;*                Relais 7| 8  RE0   P   RB0 33 | DCC in via R 100kOhm    *
;*                Relais 8| 9  RE1   I       32 | +5V		 	  *
;*        ingang potmeter | 10 RE2   C       31 | Massa	 	          *
;*	    	      +5V | 11           RD7 30 | Puls Servo 9            *
;*	    	    Massa | 12       1   RD6 29 | Puls Servo 10           *
;*       ingang keuze MAX | 13 RA7   6   RD5 28 | Puls Servo 11           *
;*                Relais 9| 14 RA6   F   RD4 27 | Puls Servo 12           *
;*            Puls Servo 1| 15 RC0   8   RC7 26 | Puls Servo 13           *
;*            Puls Servo 2| 16 RC1   8   RC6 25 | Puls Servo 14           *
;*            Puls Servo 3| 17 RC2   7   RC5 24 | Puls Servo 15           *
;*            Puls Servo 4| 18 RC3       RC4 23 | Puls Servo 16           *
;*            Puls Servo 5| 19 RD0       RD3 22 | Puls Servo 8            *
;*            Puls Servo 6| 20 RD1       RD2 21 | Puls Servo 7            *
;*                         _____________________			  *
;*								          * 
;**************************************************************************

;Opbouw DCC basic Accessory Decoder Packet Format volgens norm NMRA RP 9.2.1 (elk cijfer of letter is één logische bit)


;1111111111 0 |10AAAAAA 0 |1AAACDDD 0 |EEEEEEEE 1 |-->Basic Accessory Decoder Packet Format
;SPRONG1      |SPRONG2    |SPRONG3    |SPRONG4    |-->ISR (Interrupt Service Routine) sprongadres waar DCC-data wordt ingelezen (zie ISR code)

;1111111111 0 |AAAAAAAA 0 |DDDDDDDD 0 |EEEEEEEE 1 |-->Totaal packet 'zoals' ingelezen en verwerkt door ISR 
;1111111111   |           |           |           |-->minstens 10 preable bits = '1'
;           0 |           |           |           |-->preable bits worden afgesloten met '0'
;             |AAAAAAAA   |           |           |-->adresbyte bestaande uit:
;             |10         |           |           |  -->bit 7 en 6 van het adres is altijd '10' voor 'Accessory Decoders'
;             |  AAAAAA   |           |           |  -->LOW byte adres [0-63]
;             |         0 |           |           |-->Indien '0' dan volgt er een nieuwe byte
;             |           |DDDDDDDD   |           |-->Databyte (instruction byte) bestaande uit:
;             |           |1          |           |  -->moet '1' zijn 
;             |           | AAA       |           |  -->HIGH byte adres[0-7]  totaal adres van Accessory Decoder= ~[HIGH BYTE]x64+[LOW BYTE]  (~ = complement)
;             |           |    C      |           |  -->C='1'activating -->C='0'deactivating. Enkel activating '1' wordt gebruikt (deactivering-->wisselspoel uit)
;             |           |     DD    |           |  -->'00'= FFbit1; '01' = FFbit2; '10' = FFbit3; '11' = FFbit4
;             |           |       D   |           |  -->'0' RESET één van de 4 FFbit's (zie hiervoor); '1' SET één van de 4 FFbit's
;             |           |         0 |           |-->Indien '0' dan volgt er een nieuwe byte
;             |           |           |EEEEEEEE   |-->Error Byte: AAAAAAAA XOR DDDDDDDD XOR EEEEEEEE = '0' dan OK
;             |           |           |         1 |-->Indien '1' dan einde 3 byte data packet


;Principewerking program: (sterk vereenvoudigd!)
;
;- MAIN program zorgt eerst dat INIT subroutine wordt uitgevoerd (initiatie uitgangen, klok, TIMERS, opvragen data EEPROM enz...)
;    Daarna zal MAIN program in een oneindige LUS terecht komen die elke 20ms sequentieel nagaat of de servo's en relais aangestuurd moeten worden
;    Ook zal MAIN program elke 20ms da waarde van een externe potmeter via een A/D convertor inlezen en verwerken voor instelmodus servo
;    Zolang die 20ms nog niet voorbij is, zal MAIN program subroutine 'LOOP PULS' blijven oproepen (zie verder)
;
;- MACRO SERVO: 16x in 'MAIN', dit deel gaat per servo na of deze van positie moet veranderen of dat de servo in instelmodus staat.
;     De communicatie tussen gewenste DCC stand en servo stuurprogram gebeurd door een FF bit per servo
;     Veranderd deze FF bit van toestand, dan zal servo stuurprogram pulsen uitsturen om de servo om te zetten (één puls per 20ms)
;     Tijdens zulke puls (variatie tussen 0,5ms en 2,5ms) zal het SERVO stuurprogram subroutine 'LOOP PULS' blijven oproepen (zie verder)
;     Als een servo zijn positie heeft bereikt, dan stoppen ook de pulsen. Servo's blijven mechanisch vast in deze positie staan (geen gebrom) 
;     Het kan ook zijn dat de servo in instelmodus staat. Kort samengevat werkt dit zo:
;       -Zorg er voor dat al de 16 FF's via DCC protocol nul zijn. (hoe dat nu juist zit op een commerciële centrale moet ik nog uitzoeken)
;       -Zet een brugje over keuze MIN. De servo die ju nu selecteerd via DCC (FF bit=1) volgt direct de potmeter die instelbaar is tussen 0,5 en 2,5ms
;           ben je tevreden met de instelling, dan zorg je er voor dat de FF bit via DCC protocol 0 wordt. Op dit moment wordt de instelling opgeslagen in EEPROM
;       -Hetzelfde kan je doen met een brugje over keuze MAX. 
;       -Instelling van omlooptijd doe je met zowel een brug over keuze MIN en MAX. Weer dezelfde procedure maar de servo beweegt nu wel niet!
;
;- MACRO RELAIS: 16x in 'MAIN', zal de toestand van FF bit via DCC protocol rechtsteeks een RELAIS uitgang aansturen.
;
;- LOOP PULS subroutine: Deze procedure zal een eventueel correct DCC data protocol decoderen en nagaan of het DCC adres voorkomt in lijst van 8 adressen
;    Is er adres dat overeenkomt dan zal subroutine DECDCCWD deze data decoderen naar de FF die voor de communicatie zorgt tussen SERVO en RELAIS program.
;    Het is belangrijk dat 'LOOP PULS' subroutine regelmatig wordt opgeroepen tijdens het totale program verloop, 
;      anders kan het zijn dat DCC data overschreven wordt door ISR. 
;
;- ISR: Interupt Service Routine. Wordt enkel opgeroepen en direct uitgevoerd indien:   
;       1 een servopuls voorblij is, zal ISR de servo uitgang(en) uitschakelen en dit melden aan 'LOOP PULS' program
;       2 DCC data bit op DCC ingang lezen (werking zie ISR) 
;         Als er een volledig correct DCC data protocol is ingelezen, dan zal ISR dit melden aan 'LOOP PULS' program
;


;********************************************************************
;************ µCONTROLLER AFHANKELIJKE INSTELLINGEN *****************
;********************************************************************

	list		p=16f887	; list directive to define processor
	#include	<p16f887.inc>	; processor specific variable definitions

	__CONFIG    _CONFIG1, _LVP_OFF & _FCMEN_ON & _IESO_OFF & _BOR_OFF & _CPD_OFF & _CP_OFF & _MCLRE_OFF & _PWRTE_ON & _WDT_OFF & _INTRC_OSC_NOCLKOUT
	__CONFIG    _CONFIG2, _WRT_OFF & _BOR21V

	errorlevel -302, -306


;********************************************************************
;************ CONSTANTEN ********************************************
;********************************************************************

			;Hier vul je de 8 DCC adressen in van de decoder. 
			;adres 0 mag niet gebruikt worden, max adres is 511. Vergeet het puntje niet voor de cijfers... (anders hex!)
			;dezelfde adressen zijn mogelijk. De relais kunnen zo gebruikt worden voor puntstukpolarisatie

ADR1			EQU .1	;adres decoder servo 1-4
ADR2			EQU .2	;adres decoder servo 5-8
ADR3			EQU .3  ;adres decoder servo 9-12
ADR4			EQU .4  ;adres decoder servo 13-16
ADR5			EQU .1  ;adres decoder relais 1-4
ADR6			EQU .2  ;adres decoder relais 5-8
ADR7			EQU .3  ;adres decoder relais 9-12
ADR8			EQU .4  ;adres decoder relais 13-16

			;berekende DCC protocol adressen

WISADRL1		EQU (ADR1 % .64)	;DCC adres LOW wissel 1-4
WISADRL2		EQU (ADR2 % .64)	;DCC adres LOW wissel 5-8
WISADRL3		EQU (ADR3 % .64)	;DCC adres LOW wissel 9-12
WISADRL4		EQU (ADR4 % .64)	;DCC adres LOW wissel 13-16
RELADRL1		EQU (ADR5 % .64)	;DCC adres LOW relais 1-4
RELADRL2		EQU (ADR6 % .64)	;DCC adres LOW relais 5-8
RELADRL3		EQU (ADR7 % .64)	;DCC adres LOW relais 9-12
RELADRL4		EQU (ADR8 % .64)	;DCC adres LOW relais 13-16


;(HIGH adres wordt als 1 complement doorgestuurd door de centrale.) 

WISADRH1		EQU ~((ADR1-WISADRL1)/4);DCC adres HIGH wissel 1-4
WISADRH2		EQU ~((ADR2-WISADRL2)/4);DCC adres HIGH wissel 5-8
WISADRH3		EQU ~((ADR3-WISADRL3)/4);DCC adres HIGH wissel 9-12
WISADRH4		EQU ~((ADR4-WISADRL4)/4);DCC adres HIGH wissel 13-16
RELADRH1		EQU ~((ADR5-RELADRL1)/4);DCC adres HIGH relais 1-4
RELADRH2		EQU ~((ADR6-RELADRL2)/4);DCC adres HIGH relais 5-8
RELADRH3		EQU ~((ADR7-RELADRL3)/4);DCC adres HIGH relais 9-12
RELADRH4		EQU ~((ADR8-RELADRL4)/4);DCC adres HIGH relais 13-16


				;Inhoud FLAG register:

FLAGPSZO		EQU 2	;geeft aan dat Persoonlijke Servo vertraging een Zero Overgang heeft gehad
FLAGDATA		EQU 4	;=1 dan correct ingelezen DCC data
CPORTB			EQU 5	;copy van poort B,0 gebruikt bij ISR routine
FLANK			EQU 6   ;FLANK ingang van 0 --> 1
INGANG			EQU 7	;toestand ingang

MINPULS			EQU .50	;minimale waarde servopuls 50/100 = 0,5ms
MAXPULS			EQU .250 ;maximale waarde servopuls 250/100 = 2,5ms

	#define MIN_KEUZE PORTE,3
	#define MAX_KEUZE PORTA,7
	#define DCCIN     PORTB,0

	#define RELAIS1  PORTA,0
	#define RELAIS2  PORTA,1
	#define RELAIS3  PORTA,2
	#define RELAIS4  PORTA,3
	#define RELAIS5  PORTA,4
	#define RELAIS6  PORTA,5
	#define RELAIS7  PORTE,0
	#define RELAIS8  PORTE,1
	#define RELAIS9  PORTA,6
	#define RELAIS10 PORTB,7
	#define RELAIS11 PORTB,6
	#define RELAIS12 PORTB,5
	#define RELAIS13 PORTB,4
	#define RELAIS14 PORTB,3
	#define RELAIS15 PORTB,2
	#define RELAIS16 PORTB,1


	#define SERVO1  PORTC,0
	#define SERVO2  PORTC,1
	#define SERVO3  PORTC,2
	#define SERVO4  PORTC,3
	#define SERVO5  PORTD,0
	#define SERVO6  PORTD,1
	#define SERVO7  PORTD,2
	#define SERVO8  PORTD,3
	#define SERVO9  PORTC,4
	#define SERVO10 PORTC,5
	#define SERVO11 PORTC,6
	#define SERVO12 PORTC,7
	#define SERVO13 PORTD,4
	#define SERVO14 PORTD,5
	#define SERVO15 PORTD,6
	#define SERVO16 PORTD,7

	
;********************************************************************
;************ VARIABELEN ********************************************
;********************************************************************

;de volgende MINSERVO MAXSERVO en TIMSERVO variabelen moeten in deze volgorde en eerst staan in ASM-program i.v.m. opslag en opvragen EEPROM !!!

	cblock 0x20	;(bank0)
MINSERVO		;Array[16] ingestelde Min waarde servo zoals opgeslagen in EEPROM
	endc

	cblock 0x30
MAXSERVO		;Array[16] ingestelde Max waarde servo zoals opgeslagen in EEPROM
	endc

	CBLOCK 0X40
TIMSERVO		;Array[16] looptijd servo (vertraging) zoals opgeslagen in EEPROM
	ENDC

	CBLOCK 0x50
PULS			;Array[16] huidige waarde pulsduur servo
	endc

	cblock 0x60
TELVERTR		;Array[16] hulpteller vertraging servo
	endc

	cblock 0x70
FF1_8				;gewenste toestand wissel 1 tot 8 (van DCC protocol naar SERVO program)
FF9_16				;gewenste toestand wissel 9 tot 16
FFR1_8				;gewenste toestand relais 1 tot 8 (van DCC protocol naar RELAIS program)
FFR9_16				;gewenste toestand relais 9 tot 16

HULPREG				;kan voor diverse doeleinden gebruikt worden
FLAG				;bits van FLAG register geven diverse toestanden weer (zie bij constanten)
VTFF1_8				;vorige toestand FF 1-8
VTFF9_16			;vorige toestand FF 9-16
AAAAAAAA			;opslag deel A byte DCC formaat
DDDDDDDD			;opslag deel D byte DCC formaat
EEEEEEEE			;opslag deel E byte DCC formaat
SPRADR				;houd sprongadres bij gebruikt in ISR routine
BITTEL				;ingelezen bit teller gebruikt in ISR routine
		
STATUS_TEMP			;tijdelijke opslag tijdens Interruptroutine
W_TEMP
PCLATH_TEMP	

	endc

	cblock 0xA0		;(bank1)
VERTRAGING			;Berekende vertraging uit ADC register
SERVOTIJD			;Berekende tijd servo uit ADC register	
	
	endc


;********************************************************************
;*******  MACRO DECDCCWD   ******************************************
;********************************************************************

DECDCCWD MACRO FF, FFBIT1, FFBIT2, FFBIT3, FFBIT4
	
	LOCAL DE_spr11, DE_spr12, DE_spr13, DE_spr14, DE_spr15, DE_spr16, DE_spr17, DE_END


;1111111111 0 |10AAAAAA 0 |1AAACDDD 0 |EEEEEEEE 1 |-->Basic Accessory Decoder Packet Format
;1111111111 0 |AAAAAAAA 0 |DDDDDDDD 0 |EEEEEEEE 1 |-->Data ingelezen door ISR 
;             |           |     DDD   |           |-->Enkel dit deel wordt hier gedecodeerd


		BTFSC DDDDDDDD,2		;is D2=0?
		GOTO  DE_spr11

		BTFSC DDDDDDDD,1		;is D2D1=00?	
		GOTO DE_spr12
	
		BTFSC DDDDDDDD,0		
		GOTO DE_spr13
		BCF FF,FFBIT1			;is D2D1D0=000 dan FF,FFBIT1 = 0
		GOTO DE_END
DE_spr13	BSF FF,FFBIT1			;is D2D1D0=001 dan FF,FFBIT1 = 1
		GOTO DE_END

DE_spr12	BTFSC DDDDDDDD,0
		GOTO DE_spr14
		BCF FF,FFBIT2			;is D2D1D0=010 dan FF,FFBIT2 = 0
		GOTO DE_END
DE_spr14	BSF FF,FFBIT2			;is D2D1D0=011 dan FF,FFBIT2 = 1 
		GOTO DE_END

DE_spr11	BTFSC DDDDDDDD,1		;is D2D1=10?
		GOTO DE_spr17

		BTFSC DDDDDDDD,0		
		GOTO DE_spr15
		BCF FF,FFBIT3			;is D2D1D0=100 dan FF,FFBIT3 = 0
		GOTO DE_END
DE_spr15	BSF FF,FFBIT3			;is D2D1D0=101 dan FF,FFBIT3 = 1
		GOTO DE_END

DE_spr17	BTFSC DDDDDDDD,0		
		GOTO DE_spr16
		BCF FF,FFBIT4			;is D2D1D0=110 dan FF,FFBIT4 = 0
		GOTO DE_END
DE_spr16	BSF FF,FFBIT4			;is D2D1D0=111 dan FF,FFBIT4 = 1 
		GOTO DE_END

DE_END	NOP
		ENDM
	

;********************************************************************
;*******  MACRO SERVO ***********************************************
;********************************************************************

SERVO MACRO  M_MINSERVO, M_MAXSERVO, M_TIMSERVO, M_PULS,M_TELVERT,M_VTFF,M_FF,M_FFBIT,M_PORTOUT,M_BITOUT

					
	LOCAL  M_END,M_SPR10,M_SPR20, M_SPR25,M_SPR27,M_SPR30,M_SPR31,M_SPR40,M_SPR35,M_SPR23,M_SPR50,M_SPR55,M_SPR00, M_SPR42

					;EERST TOESTAND FF ACHTERHALEN o.a. voor negatieve FLANK detectie instelling servopuls

	BSF FLAG,INGANG			;clear en set de flag's
	BCF FLAG,FLANK
	BTFSC M_FF,M_FFBIT		;is FF '0'
	GOTO M_SPR50
	BCF FLAG,INGANG			;  JA: clear flag INGANG
	BTFSS M_VTFF,M_FFBIT		;      is vorige toestand FF '1'
	GOTO M_SPR00			;        NEE: ga naar INSTELLING VERTRAGING
	BSF FLAG,FLANK			;        JA: SET flag FLANK 
	BCF M_VTFF,M_FFBIT		;            RESET vorige toestand FF
	GOTO M_SPR00
	
	
M_SPR50 BSF M_VTFF,M_FFBIT		;  NEE: set vorige toestand FF 
	
					;INSTELLEN VERTRAGING? (KEUZE MIN en MAX gelijktijdig geselecteerd)

M_SPR00	BTFSC MAX_KEUZE			;is ingang keuze max '0'
	GOTO M_SPR10			;  NEE: ga naar TEST SERVO MIN INSTELLING
	BTFSC MIN_KEUZE			;  JA: is ingang keuze min '0'
	GOTO M_SPR20			;        NEE: ga naar INSTELLEN SERVOPULS MAX
	BTFSS FLAG,FLANK		;        JA: is er een flank
	GOTO M_END			;             NEE: ga naar einde macro
	banksel VERTRAGING
	MOVF VERTRAGING,w		;             JA: Laad vertraging in array TIMSERVO	
	banksel M_TIMSERVO
	MOVWF M_TIMSERVO	  
	MOVLW LOW M_TIMSERVO		;             en opslaan in EEPROM en einde MACRO	
	banksel EEADR		
	MOVWF EEADR 		
	banksel M_TIMSERVO
	MOVF M_TIMSERVO,w
	banksel EEDAT
	MOVWF EEDAT
	CALL EEWRITE
	GOTO M_END

					;INSTELLEN SERVOPULS MIN?
	
M_SPR10 BTFSC MIN_KEUZE			;is ingang keuze min '0'
	GOTO M_SPR30			;  NEE: ga naar TEST SERVOPULS <> SERVOPULS MAX of SERVOPULS MIN
	BTFSC FLAG,INGANG		;  JA: is FF '0'
	GOTO M_SPR25			;        NEE: GA NAAR SERVO UITGANG AANSTUREN
	BTFSS FLAG,FLANK		;        JA: is er een flank
	GOTO M_END			;              NEE: ga naar einde macro
	banksel SERVOTIJD
	MOVF SERVOTIJD,w		;      	       JA: laad servotijd in array MINSERVO
	banksel M_MINSERVO
	MOVWF M_MINSERVO
	MOVLW LOW M_MINSERVO		;                  en opslaan in EEPROM en einde MACRO	
	banksel EEADR		
	MOVWF EEADR 		
	banksel M_MINSERVO
	MOVF M_MINSERVO,w
	banksel EEDAT
	MOVWF EEDAT
	CALL EEWRITE
	GOTO M_END

					;INSTELLEN SERVOPULS MAX?

M_SPR20 BTFSC MAX_KEUZE			;is ingang keuze max '0'
	GOTO M_SPR30			;  NEE: ga naar TEST SERVOPULS <> SERVOPULS MAX of SERVOPULS MIN
	BTFSC FLAG,INGANG		;  JA: is FF '0'
	GOTO M_SPR25			;        NEE: GA NAAR SERVO UITGANG AANSTUREN
	BTFSS FLAG,FLANK		;        JA: is er een flank
	GOTO M_END			;              NEE: ga naar einde macro
	banksel SERVOTIJD
	MOVF SERVOTIJD,w		;      	       JA: laad servotijd in array MAXSERVO
	banksel M_MAXSERVO
	MOVWF M_MAXSERVO

	MOVLW LOW M_MAXSERVO		;                   en opslaan in EEPROM en einde MACRO	
	banksel EEADR		
	MOVWF EEADR 		
	banksel M_MAXSERVO
	MOVF M_MAXSERVO,w
	banksel EEDAT
	MOVWF EEDAT
	CALL EEWRITE			
	GOTO M_END
					;SERVO UITGANG AANSTUREN BIJ INSTELLING SERVO MIN of MAX

M_SPR25	
	banksel SERVOTIJD
	MOVF SERVOTIJD,w		;Waarde SERVOTIJD  in Timer 2
	banksel PR2			;RAM Bankselectie 
	MOVWF PR2
	banksel TMR2
	CLRF TMR2
	BSF T2CON,TMR2ON		;Start T2
	banksel M_PORTOUT
	BSF M_PORTOUT,M_BITOUT		;Uitgang servo-->1
	GOTO M_END

					;SERVOPULS <> SERVOPULS MAX of SERVOPULS MIN

M_SPR30 BCF FLAG, FLAGPSZO
	DECFSZ M_TELVERT,f		;eerst persoonlijke servo vertraging aanpassen
	GOTO M_SPR31
	MOVF M_TIMSERVO,w
	MOVWF M_TELVERT

	BSF FLAG,FLAGPSZO		;is er een overgang geweest geeft dit dan aan via een flag

M_SPR31 BTFSS FLAG,INGANG		;is schakelaar '1'
	GOTO M_SPR42			;  

					;  JA: VERWERKING INDIEN SCHAKELAAR '1'
	MOVF M_PULS,w
	SUBWF M_MINSERVO,w	
	BTFSC STATUS,C			;      is servoPULS groter dan MINPULS
	GOTO M_END			;        NEE: einde macro
	MOVF M_PULS,w			;	 	 JA: Waarde servoPULS  in Timer 2
	banksel PR2			;             RAM Bankselectie 
	MOVWF PR2
	banksel TMR2
	CLRF TMR2
	BSF T2CON,TMR2ON		;             Start T2
	banksel M_PORTOUT
	BSF M_PORTOUT,M_BITOUT		;             Uitgang servo-->1
	BTFSS FLAG,FLAGPSZO		;		    is er een persoonlijke vertraging overgang geweest
	GOTO M_END			;		      NEE: einde macro
	DECF M_PULS,f			;		      JA: verlaag puls en einde macro
	GOTO M_END

M_SPR42					;  NEE: VERWERKING INDIEN SCHAKELAAR '0'
	MOVF M_MAXSERVO,w
	SUBWF M_PULS,w	
	BTFSC STATUS,C			;      is servoPULS kleiner dan MAXPULS
	GOTO M_END			;        NEE: einde macro
	MOVF M_PULS,w	 		;	 	 JA: Waarde servoPULS  in Timer 2
	banksel PR2			;             RAM Bankselectie 
	MOVWF PR2
	banksel TMR2
	CLRF TMR2
	BSF T2CON,TMR2ON
	banksel M_PORTOUT		;             Start T2
	BSF M_PORTOUT,M_BITOUT		;             Uitgang servo-->1
	BTFSS FLAG,FLAGPSZO		;		    is er een persoonlijke vertraging overgang geweest
	GOTO M_END			;		      NEE: einde macro
	INCF M_PULS,f			;		      JA: verhoog puls en einde macro

M_END
	pagesel LOOP			;
	CALL LOOP
	pagesel $

	ENDM


;********************************************************************
;*******  MACRO INITPULS ********************************************
;********************************************************************

INITPULS MACRO M2_FF, M2_FFBIT, M2_PULS, M2_MINSERVO, M2_MAXSERVO, M2_TIMSERVO, M2_TELVERTR, M2_OUT, M2_OUTBIT

	LOCAL M2_END, M2_SPR1

	MOVF M2_MAXSERVO,w		;afhankelijk stand schakelaar var PULS servo instellen
	MOVWF M2_PULS
	BTFSS M2_FF,M2_FFBIT
	goto M2_SPR1
	MOVF M2_MINSERVO,w
	MOVWF M2_PULS
M2_SPR1 MOVF M2_TIMSERVO,w
	MOVWF M2_TELVERTR

	BCF M2_OUT,M2_OUTBIT		;clear SERVO uitgang
M2_END	NOP

	ENDM

;********************************************************************
;*******  MACRO RELAIS **********************************************
;********************************************************************

RELAIS MACRO MR_FF, MR_FFBIT, MR_REL, MR_RELBIT

	LOCAL MR_SPR1

	BTFSS MR_FF,MR_FFBIT
	GOTO MR_SPR1
	BSF MR_REL,MR_RELBIT
	GOTO $+2
MR_SPR1	BCF MR_REL, MR_RELBIT


	ENDM	

;********************************************************************
;*******  START ASSEMBLER CODE **************************************
;********************************************************************

		ORG     0x0000    	; processor reset vector is altijd adres 0000

		clrf PCLATH
		pagesel MAIN	
  		GOTO    MAIN        	; ga naar begin van program


;********************************************************************
;******************* INTERRUPT SERVICE ROUTINE  *********************
;********************************************************************

	     	ORG    0x0004		;startadres interrupt code is altijd adres 0004

		;****************************************************
       		;****** EERST COPY MAKEN BELANGRIJKE REGISTERS ******
		;****************************************************
ISR     	
		MOVWF W_TEMP 		
		SWAPF STATUS,W 		
		CLRF STATUS 		
		MOVWF STATUS_TEMP 	
		MOVF PCLATH,W 		
		MOVWF PCLATH_TEMP 	
		CLRF PCLATH 


		

		;****************************************************
       		;****** DIT DEEL HEEFT TE MAKEN MET SERVOPULS *******
		;****************************************************

		BTFSS	PIR1,TMR2IF	;TIMER 2 INTERRUPT?
		GOTO ISR_SPR1
		CLRF PORTC		;Alle servouitgangen 0 (er is er wel maar telkens 1 actief!)
		CLRF PORTD
		BCF T2CON,TMR2ON	;stop timer2
		BCF PIR1,TMR2IF		;wis interruptflag
		GOTO END_ISR

		;****************************************************
       		;****** DIT DEEL HEEFT TE MAKEN MET INLEZEN DCC *****
		;****************************************************

		;Een logische '1' bestaat uit een negatieve puls van 58µs en een positieve puls van 58µs (mits wat tolerantie)
		;Een logische '0' bestaat uit een negatieve puls van 116µs en een positieve puls van 116µs (mits wat tolerantie)
		;De detectiemethode logische bit bestaat uit het principe dat we gaan kijken na een 80µs of het DCC signaal terug hoog is '1' of nog laag is '0'

		;Om niet telkens in het ISR na te gaan waar welke data er eigenlijk ingelezen wordt, 
		;wordt er gewerkt met sprong adressen die aangepast worden als data correct ingelezen is. Dit gaat sneller en overzichtelijker...

ISR_SPR1 	BTFSS 	INTCON,INTF	;DCCIN (portB,0) INTERRUPT ?  (als DCCIN laag wordt)
		GOTO ISR_SPR2


		MOVLW .196 		;196=(256-60) LAAD TIMER 1 nog voor 60µs (hierbij komt nog een 20µs bij, tijd gebruikt door instructies in ISR)
		MOVWF TMR1L
		MOVLW .255
		MOVWF TMR1H
		BCF INTCON,INTF
		GOTO END_ISR

ISR_SPR2 				;TIMER 1 INTERRUPT


		BCF FLAG,CPORTB		;maak eerst een copy van DCC in 
		BTFSC DCCIN
		BSF FLAG,CPORTB 
		BCF PIR1,TMR1IF		;wis interruptflag T1
		movf SPRADR,w		;PCL aanpassen met sprongadres
		MOVWF PCL

SPRONG1					;SPRONG1 telt aantal preamble bits (alle bits die '1' zijn) tot bit = '0'

					;1111111111 0 |AAAAAAAA 0 |DDDDDDDD 0 |EEEEEEEE 1
					;SPRONG1      |SPRONG2    |SPRONG3    |SPRONG4
					;1111111111 0 |           |           |

		BTFSC FLAG,CPORTB       ;lees logische toestand op DCC pin is deze = 0?
		GOTO ISR_SPR42		;  NEE: verhoog bitteler		
		MOVLW	0xF6		;  JA: is er minstens 10 keer een 1 (preamble bit) ingelezen?		
		addwf	BITTEL,w		
		btfss	STATUS,C
		GOTO ISR_SPR48		;      NEE: geen correct packet!
		MOVLW LOW SPRONG2	;      JA: laad adres volgende SPRONGADRES
		MOVWF SPRADR
		CLRF BITTEL
		GOTO END_ISR

ISR_SPR42	INCF BITTEL,F		;verhoog bitteller
		GOTO END_ISR


SPRONG2					;SPRONG2 lees adresbyte en '0' bit

					;1111111111 0 |AAAAAAAA 0 |DDDDDDDD 0 |EEEEEEEE 1
					;SPRONG1      |SPRONG2    |SPRONG3    |SPRONG4
					;             |AAAAAAAA 0 |           |


		MOVF BITTEL,w		;zijn er 8 bits ingelezen?
		XORLW 	.8
		BTFSC STATUS,Z
		GOTO ISR_SPR22
		BCF STATUS,C
		BTFSC FLAG,CPORTB   	;  NEE: leest logische toestand van copy DCC pin en schuif in AAAAAAAA
		BSF STATUS,C
		RLF AAAAAAAA,f
		INCF BITTEL,F
		GOTO END_ISR
 
ISR_SPR22	BTFSC FLAG,CPORTB    	;  JA: lees logische toestand op DCC pin is deze = 0?
		GOTO ISR_SPR48		;        NEE: geen correct packet
		MOVLW LOW SPRONG3	;        JA:laad adres volgend SPRONGADRES
		MOVWF SPRADR
		CLRF BITTEL
		GOTO END_ISR


SPRONG3					;SPRONG3 lees databyte en '0' bit

					;1111111111 0 |AAAAAAAA 0 |DDDDDDDD 0 |EEEEEEEE 1
					;SPRONG1      |SPRONG2    |SPRONG3    |SPRONG4
					;             |           |DDDDDDDD 0 |



		MOVF BITTEL,w		;zijn er 8 bits ingelezen?
		XORLW 	.8
		BTFSC STATUS,Z
		GOTO ISR_SPR32
		BCF STATUS,C		;  NEE: leest logische toestand van copy DCC pin en schuif in DDDDDDDD 
		BTFSC FLAG,CPORTB   	
		BSF STATUS,C
		RLF DDDDDDDD,f
		INCF BITTEL,F
		GOTO END_ISR

ISR_SPR32	BTFSC FLAG,CPORTB    	;  JA:lees logische toestand op DCC pin is deze = 0?
		GOTO ISR_SPR48		;       NEE: geen correct packet
		MOVLW LOW SPRONG4	;       Ja: laad adres volgend SPRONGADRES
		MOVWF SPRADR
		CLRF BITTEL
		GOTO END_ISR


SPRONG4					;SPRONG4 lees errorbyte en '1' bit (einde 3 data packet)

					;1111111111 0 |AAAAAAAA 0 |DDDDDDDD 0 |EEEEEEEE 1
					;SPRONG1      |SPRONG2    |SPRONG3    |SPRONG4
					;             |           |           |EEEEEEEE 1

		MOVF BITTEL,w		;zijn er 8 bits ingelezen?
		XORLW 	.8
		BTFSC STATUS,Z
		GOTO ISR_SPR45
		BCF STATUS,C
		BTFSC FLAG,CPORTB   	;  NEE:leest logische toestand van copy DCC pin en schuif in EEEEEEEE
		BSF STATUS,C
		RLF EEEEEEEE,f
		INCF BITTEL,F
		GOTO END_ISR

ISR_SPR45	BTFSS FLAG,CPORTB   	;   JA: lees logische toestand op DCC pin is deze = 1?
		GOTO ISR_SPR48		;         NEE: geen correct packet = kan een 4 of meer data packet zijn, maar niet van toepassing hier
		BSF FLAG,FLAGDATA	;         Ja: set bit correct data packet ingelezen

ISR_SPR48	CLRF BITTEL		;herstart inlezen packet
		MOVLW LOW SPRONG1
		MOVWF SPRADR


		;****************************************************
       		;**** DATA BELANGRIJKE REGISTERS TERRUGPLAATSEN *****
		;****************************************************

END_ISR		MOVF PCLATH_TEMP, W 	;Restore PCLATH
		MOVWF PCLATH		;Move W into PCLATH
		SWAPF STATUS_TEMP,W 	;Swap STATUS_TEMP register into W
		MOVWF STATUS 		;Move W into STATUS register
		SWAPF W_TEMP,F 		;Swap W_TEMP
		SWAPF W_TEMP,W 		;Swap W_TEMP into W
       		RETFIE


;********************************************************************
;********  INITIATIE  SUBROUTINE  ***********************************
;********************************************************************
	
INIT	

		;****************************************************
		;*******  INIT REGISTERS ****************************
		;****************************************************

		BCF STATUS,IRP		;voor indirect adresseren in bank 00

		BSF STATUS,RP0		;Bankselect OSCCON register
		BSF OSCCON,4		; van 4 naar 8MHz interne Oscilator
		BSF OSCCON,SCS
		BCF STATUS,RP0

		movlw b'00000001'
		movwf FLAG		;bits in FLAG register initieren  ??????
		

		;****************************************************
		;*******  INIT I/O POORTEN  *************************
		;****************************************************

		banksel ANSEL
		movlw b'10000000'
		movwf ANSEL		;ANS7 enable als analoog in (PORTE,2)
		CLRF ANSELH		;Geen analoge ingangen hoog
		
		banksel	TRISA		;0 is uitgang, 1 is ingang
		movlw b'10000000'
		movwf TRISA
		
		movlw b'00000001'		
		movwf TRISB		

		movlw b'00000000'		
		movwf TRISC	

		movlw b'00000000'		
		movwf TRISD	

		movlw b'11111100'
		movwf TRISE		

		;****************************************************
		;*******  INIT TIMER 0 ******************************
		;****************************************************

		banksel OPTION_REG
		movf OPTION_REG,w		;voor opwekking 20ms (50Hz)
		andlw b'11000000'	
		iorlw b'00000111'	
		       ;--0-----                 TOCS =0 (timer0 in timer mode)
		       ;----0---                 PSA=0 (prescaler voor timer0)
		       ;-----111                 prescaler=256
		movwf OPTION_REG 


		;****************************************************
		;*******  INIT TIMER 1 ******************************
		;****************************************************
	
		banksel T1CON
		movlw b'00010001'	;gebruikt voor detectie DCC protocol bit 1 of 0

		       ;--01----         prescaler=2 =1µs basis
		       ;-------1         timer 1 ON
		movwf T1CON


		;****************************************************
		;*******  INIT TIMER 2 ******************************
		;****************************************************
	
		banksel T2CON
		movlw b'00100001'	;gebruikt voor opwekking servopulsen
		       ;------01         prescaler=4   =2µs	
		       ;-0100---         postscaler=1/5 =2x5=10µs per stap 10*256 stappen=2,56ms max pulsduur
		movwf T2CON


		;****************************************************
		;*******  INIT A/D CONVERTOR ************************
		;****************************************************

		banksel ADCON0
		movlw b'10011101'
		       ;10------	Fosc/32
		       ;--0111--	AN7 (portE,2)
		       ;-------1	ADC enable
		movwf ADCON1

		;****************************************************
		;*******  INIT INTERRUPT ****************************
		;****************************************************
		
		banksel SPRADR
		movlw LOW SPRONG1
		movwf SPRADR
		CLRF BITTEL
		banksel INTCON
		movlw b'11010000'
		movwf INTCON
		banksel PIE1
		movlw b'00000011'
		       ;------1-   	enable Timer 2 interrupt
		       ;-------1        enable Timer 1 interrupt
		movwf PIE1
		banksel OPTION_REG
		BCF OPTION_REG,INTEDG	;INT B0 op negatieve flank
				

		;****************************************************
		;* Opvragen MIN, MAX, en VERTRAGING SERVO uit EEPROM*
		;****************************************************

		banksel HULPREG
		movlw 0x30		;startpositie HULPREG (aantal in te lezen data uit EEPROM)
		movwf HULPREG
		movlw 0x20		;startpositie  FSR indirect register (adres in RAM van var MINSERVO en in EEPROM)
		movwf FSR
		
I_LOOP
		banksel EEADR	
		MOVF FSR,w  
		MOVWF EEADR 		;Data Memory
		
		banksel EECON1	
		BCF EECON1, EEPGD 	;Point to DATA memory
		BSF EECON1, RD 		;EE Read
		banksel EEDAT	
		MOVF EEDAT, W 		;EEdata naar POSserv,x
		movwf INDF		;
			
		incf FSR,1 		;verhoog adres 
		decf HULPREG,f		;verlaag HULPREG
		btfss STATUS,Z 		;als Carry bit <> 1 dan voer subr terug uit 
		goto I_LOOP
		banksel 0


		;****************************************************
		;* Opvragen opgeslagen FF en FFR uit EEPROM**********
		;****************************************************

		movlw 0x4		;startpositie HULPREG (aantal in te lezen data uit EEPROM)
		movwf HULPREG
		movlw LOW FF1_8		;startpositie  FSR indirect register (adres in RAM van var FF1-FF8 en in EEPROM)
		movwf FSR
		
I_LOOP2
		banksel EEADR	
		MOVF FSR,w  
		MOVWF EEADR 		;Data Memory
		
		banksel EECON1	
		BCF EECON1, EEPGD 	;Point to DATA memory
		BSF EECON1, RD 		;EE Read
		banksel EEDAT	
		MOVF EEDAT, W 		;EEdata naar POSserv,x
		movwf INDF		;
			
		incf FSR,1 		;verhoog adres 
		decf HULPREG,f		;verlaag HULPREG
		btfss STATUS,Z 		;als Carry bit <> 1 dan voer subr terug uit 
		goto I_LOOP2
		banksel 0	


		;****************************************************
		;** INIT VARIABELEN, CLEAR SERVO EN SET RELAIS UIT **
		;****************************************************
		
		INITPULS FF1_8,0,PULS+0,MINSERVO+0,MAXSERVO+0,TIMSERVO+0,TELVERTR+0, SERVO1
		INITPULS FF1_8,1,PULS+1,MINSERVO+1,MAXSERVO+1,TIMSERVO+1,TELVERTR+1, SERVO2
		INITPULS FF1_8,2,PULS+2,MINSERVO+2,MAXSERVO+2,TIMSERVO+2,TELVERTR+2, SERVO3
		INITPULS FF1_8,3,PULS+3,MINSERVO+3,MAXSERVO+3,TIMSERVO+3,TELVERTR+3, SERVO4
		INITPULS FF1_8,4,PULS+4,MINSERVO+4,MAXSERVO+4,TIMSERVO+4,TELVERTR+4, SERVO5
		INITPULS FF1_8,5,PULS+5,MINSERVO+5,MAXSERVO+5,TIMSERVO+5,TELVERTR+5, SERVO6
		INITPULS FF1_8,6,PULS+6,MINSERVO+6,MAXSERVO+6,TIMSERVO+6,TELVERTR+6, SERVO7
		INITPULS FF1_8,7,PULS+7,MINSERVO+7,MAXSERVO+7,TIMSERVO+7,TELVERTR+7, SERVO8
		INITPULS FF9_16,0,PULS+8,MINSERVO+8,MAXSERVO+8,TIMSERVO+8,TELVERTR+8, SERVO9
		INITPULS FF9_16,1,PULS+9,MINSERVO+9,MAXSERVO+9,TIMSERVO+9,TELVERTR+9, SERVO10
		INITPULS FF9_16,2,PULS+.10,MINSERVO+.10,MAXSERVO+.10,TIMSERVO+.10,TELVERTR+.10, SERVO11
		INITPULS FF9_16,3,PULS+.11,MINSERVO+.11,MAXSERVO+.11,TIMSERVO+.11,TELVERTR+.11, SERVO12
		INITPULS FF9_16,4,PULS+.12,MINSERVO+.12,MAXSERVO+.12,TIMSERVO+.12,TELVERTR+.12, SERVO13
		INITPULS FF9_16,5,PULS+.13,MINSERVO+.13,MAXSERVO+.13,TIMSERVO+.13,TELVERTR+.13, SERVO14
		INITPULS FF9_16,6,PULS+.14,MINSERVO+.14,MAXSERVO+.14,TIMSERVO+.14,TELVERTR+.14, SERVO15
		INITPULS FF9_16,7,PULS+.15,MINSERVO+.15,MAXSERVO+.15,TIMSERVO+.15,TELVERTR+.15, SERVO16
			
		RETURN 			;EINDE INITIATIE


;********************************************************************
;********  ADC VERWERKING SUBROUTINE ********************************
;********************************************************************

ADC_VERWERKING
		MOVF ADRESH,w		;ADC register ADRESH/8+1 --> VERTRAGING
		banksel VERTRAGING
		MOVWF VERTRAGING
		RRF VERTRAGING,F
		RRF VERTRAGING,F
		RRF VERTRAGING,W
		ANDLW b'00011111'
		MOVWF VERTRAGING
		INCF VERTRAGING,f

		banksel ADRESH
		MOVF ADRESH,w		;ADC register --> SERVOTIJD gelimiteerd tussen MINPULS en MAXPULS
		banksel SERVOTIJD
		MOVWF SERVOTIJD
		SUBLW MINPULS
		BTFSS STATUS,C
		GOTO ADC_SPR1
		MOVLW MINPULS
		MOVWF SERVOTIJD
		GOTO ADC_END
ADC_SPR1	
		banksel ADRESH
		MOVF ADRESH,w
		SUBLW MAXPULS
		BTFSC STATUS,C
		GOTO ADC_END
		banksel SERVOTIJD
		MOVLW MAXPULS
		MOVWF SERVOTIJD

ADC_END	
		banksel ADCON0
		BSF ADCON0,1		;herstart ADC conversie
		RETURN


;********************************************************************
;********  EEPROM SCHRIJF SUBROUTINE  *******************************
;********************************************************************

EEWRITE	
	banksel EECON1			;gemeenschapelijk deel verder verloop opslag EEPROM, uitleg zie µC manual
	BCF EECON1, EEPGD 	
	BSF EECON1, WREN 	
	BCF INTCON, GIE 	
	BTFSC INTCON, GIE 	
	GOTO $-2
	MOVLW 0x55 
	MOVWF EECON2 		
	MOVLW 0xAA 
	MOVWF EECON2 		
	BSF EECON1, WR 		
	BSF INTCON, GIE 	
	BCF EECON1, WREN	
	banksel STATUS
	RETURN


;********************************************************************
;********  LOOP PULS SUBROUTINE  ************************************
;********************************************************************

;deze Subroutine blijft zich herhalen tijdens servopuls op één van de uitgangen anders 1 keer.



LOOP
		BTFSS 	FLAG,FLAGDATA		;TEST OF ER EEN CORRECT DCC direct DATA DOORGESTUURD IS
		GOTO 	DCC_END			;  NEE: dan kunnen we hier verder niets meer komen doen ;)
		BCF 	FLAG,FLAGDATA		;  JA: reset FLAGDATA en verwerk data

;1111111111 0 |10AAAAAA 0 |1AAACDDD 0 |EEEEEEEE 1 |-->Basic Accessory Decoder Packet Format
;1111111111 0 |AAAAAAAA 0 |DDDDDDDD 0 |EEEEEEEE 1 |-->Data ingelezen door ISR
;             |           |           |EEEEEEEE   |-->Error Byte: AAAAAAAA XOR DDDDDDDD XOR EEEEEEEE = '0' dan OK

		movf	AAAAAAAA,w		
		XORWF   DDDDDDDD,w	
		XORWF   EEEEEEEE,w
		BTFSS 	STATUS,Z	
		GOTO 	DCC_END

;1111111111 0 |10AAAAAA 0 |1AAACDDD 0 |EEEEEEEE 1 |-->Basic Accessory Decoder Packet Format
;1111111111 0 |AAAAAAAA 0 |DDDDDDDD 0 |EEEEEEEE 1 |-->Data ingelezen door ISR
;             |10         |           |           |  -->bit 7 en 6 van het adres is altijd '10' voor 'Accessory Decoders'



		MOVLW 	b'11000000'		
		ANDWF 	AAAAAAAA,w
		XORLW	b'10000000'
		BTFSS 	STATUS,Z
		GOTO 	DCC_END	

;1111111111 0 |10AAAAAA 0 |1AAACDDD 0 |EEEEEEEE 1 |-->Basic Accessory Decoder Packet Format
;1111111111 0 |AAAAAAAA 0 |DDDDDDDD 0 |EEEEEEEE 1 |-->Data ingelezen door ISR
;             |           |1   1      |           |-->bit 7= 1 en bit 3 = 1 (activate)	



		MOVLW 	b'10001000'		
		ANDWF 	DDDDDDDD,w
		XORLW   b'10001000'
		BTFSS 	STATUS,Z
		GOTO 	DCC_END


;1111111111 0 |10AAAAAA 0 |1AAACDDD 0 |EEEEEEEE 1 |-->Basic Accessory Decoder Packet Format
;1111111111 0 |AAAAAAAA 0 |DDDDDDDD 0 |EEEEEEEE 1 |-->Data ingelezen door ISR
;             |  AAAAAA 0 | AAA     0 |           |-->Enkel dit deel wordt hier getest (8x)


		MOVLW 	b'00111111'		;enkel in bits 0 tot 5 staat adres LOW
		ANDWF 	AAAAAAAA,f

		MOVF    AAAAAAAA,W		;DCC adres 1 LOW match? 
        	XORLW   WISADRL1
        	BTFSS   STATUS,Z
        	GOTO    DCC_spr20		;  NEE: ga naar volgende adres test
		MOVLW   b'10001111'		;  JA: DCC adres 1 HIGH match? 
		IORWF 	DDDDDDDD,w
		XORLW   WISADRH1
		BTFSS   STATUS,Z
		GOTO	DCC_spr20		;      NEE: ga naar volgende adres test
		DECDCCWD FF1_8,0,1,2,3		;      JA: decodeer data (subroutine)
		MOVLW 	LOW FF1_8		;	   en opslaan in EEPROM
		BSF 	STATUS,RP1		
		MOVWF 	EEADR 		
		MOVF 	FF1_8,W
		MOVWF 	EEDAT 
		CALL 	EEWRITE

DCC_spr20 	MOVF    AAAAAAAA,W		;DCC adres 2 match? 
        	XORLW   WISADRL2
        	BTFSS   STATUS,Z
        	GOTO    DCC_spr30
		MOVLW   b'10001111'		
		IORWF 	DDDDDDDD,w
		XORLW   WISADRH2
		BTFSS   STATUS,Z
		GOTO	DCC_spr30
		DECDCCWD FF1_8,4,5,6,7
		MOVLW 	LOW FF1_8			
		BSF 	STATUS,RP1		
		MOVWF 	EEADR 		
		MOVF 	FF1_8,W
		MOVWF 	EEDAT 
		CALL 	EEWRITE
	
DCC_spr30	MOVF    AAAAAAAA,W		;DCC adres 3 match? 
        	XORLW   WISADRL3
        	BTFSS   STATUS,Z
        	GOTO    DCC_spr40
		MOVLW   b'10001111'		
		IORWF 	DDDDDDDD,w
		XORLW   WISADRH3
		BTFSS   STATUS,Z
		GOTO	DCC_spr40
		DECDCCWD FF9_16,0,1,2,3
		MOVLW 	LOW FF9_16			
		BSF 	STATUS,RP1		
		MOVWF 	EEADR 		
		MOVF 	FF9_16,W
		MOVWF 	EEDAT 
		CALL 	EEWRITE

DCC_spr40 	MOVF    AAAAAAAA,W		;DCC adres 4 match? 
        	XORLW   WISADRL4
        	BTFSS   STATUS,Z
        	GOTO    DCC_spr50
		MOVLW   b'10001111'		
		IORWF 	DDDDDDDD,w
		XORLW   WISADRH4
		BTFSS   STATUS,Z
		GOTO	DCC_spr50
		DECDCCWD FF9_16,4,5,6,7
		MOVLW 	LOW FF9_16			
		BSF 	STATUS,RP1		
		MOVWF 	EEADR 		
		MOVF 	FF9_16,W
		MOVWF 	EEDAT 
		CALL 	EEWRITE

DCC_spr50 	MOVF    AAAAAAAA,W		;DCC adres 5 match? 
        	XORLW   RELADRL1
        	BTFSS   STATUS,Z
        	GOTO    DCC_spr60
		MOVLW   b'10001111'		
		IORWF 	DDDDDDDD,w
		XORLW   RELADRH1
		BTFSS   STATUS,Z
		GOTO	DCC_spr60
		DECDCCWD FFR1_8,0,1,2,3
		MOVLW 	LOW FFR1_8			
		BSF 	STATUS,RP1		
		MOVWF 	EEADR 		
		MOVF 	FFR1_8,W
		MOVWF 	EEDAT 
		CALL 	EEWRITE

DCC_spr60 	MOVF    AAAAAAAA,W		;DCC adres 6 match? 
        	XORLW   RELADRL2
        	BTFSS   STATUS,Z
        	GOTO    DCC_spr70
		MOVLW   b'10001111'		
		IORWF 	DDDDDDDD,w
		XORLW   RELADRH2
		BTFSS   STATUS,Z
		GOTO	DCC_spr70
		DECDCCWD FFR1_8,4,5,6,7
		MOVLW 	LOW FFR1_8			
		BSF 	STATUS,RP1		
		MOVWF 	EEADR 		
		MOVF 	FFR1_8,W
		MOVWF 	EEDAT 
		CALL 	EEWRITE

DCC_spr70 	MOVF    AAAAAAAA,W		;DCC adres 7 match? 
        	XORLW   RELADRL3
        	BTFSS   STATUS,Z
        	GOTO    DCC_spr80
		MOVLW   b'10001111'		
		IORWF 	DDDDDDDD,w
		XORLW   RELADRH3
		BTFSS   STATUS,Z
		GOTO	DCC_spr80
		DECDCCWD FFR9_16,0,1,2,3
		MOVLW 	LOW FFR9_16			
		BSF 	STATUS,RP1		
		MOVWF 	EEADR 		
		MOVF 	FFR9_16,W
		MOVWF 	EEDAT 
		CALL 	EEWRITE

DCC_spr80 	MOVF    AAAAAAAA,W		;DCC adres 8 match? 
        	XORLW   RELADRL4
        	BTFSS   STATUS,Z
        	GOTO    DCC_END
		MOVLW   b'10001111'		
		IORWF 	DDDDDDDD,w
		XORLW   RELADRH4
		BTFSS   STATUS,Z
		GOTO	DCC_END
		DECDCCWD FFR9_16,4,5,6,7
		MOVLW 	LOW FFR9_16			
		BSF 	STATUS,RP1		
		MOVWF 	EEADR 		
		MOVF 	FFR9_16,W
		MOVWF 	EEDAT 
		CALL 	EEWRITE

DCC_END		BTFSC T2CON,TMR2ON	;TEST OF SERVOPULS VOORBIJ IS
		GOTO LOOP		;  NEE: herhaal LOOP
		RETURN			;  Ja: exit LOOP


;********************************************************************
;********  MAIN PROGRAM  ********************************************
;********************************************************************

		ORG 0x0800	;program kan niet helemaal in één pagina 

MAIN
		pagesel INIT
		CALL INIT
		pagesel $			

LUS		
		pagesel ADC_VERWERKING
		CALL ADC_VERWERKING
		pagesel $
	
		SERVO MINSERVO+0, MAXSERVO+0, TIMSERVO+0, PULS+0, TELVERTR+0, VTFF1_8,FF1_8, 0, SERVO1
		SERVO MINSERVO+1, MAXSERVO+1, TIMSERVO+1, PULS+1, TELVERTR+1, VTFF1_8,FF1_8, 1, SERVO2
		SERVO MINSERVO+2, MAXSERVO+2, TIMSERVO+2, PULS+2, TELVERTR+2, VTFF1_8,FF1_8, 2, SERVO3
		SERVO MINSERVO+3, MAXSERVO+3, TIMSERVO+3, PULS+3, TELVERTR+3, VTFF1_8,FF1_8, 3, SERVO4
		SERVO MINSERVO+4, MAXSERVO+4, TIMSERVO+4, PULS+4, TELVERTR+4, VTFF1_8,FF1_8, 4, SERVO5
		SERVO MINSERVO+5, MAXSERVO+5, TIMSERVO+5, PULS+5, TELVERTR+5, VTFF1_8,FF1_8, 5, SERVO6
		SERVO MINSERVO+6, MAXSERVO+6, TIMSERVO+6, PULS+6, TELVERTR+6, VTFF1_8,FF1_8, 6, SERVO7
		SERVO MINSERVO+7, MAXSERVO+7, TIMSERVO+7, PULS+7, TELVERTR+7, VTFF1_8,FF1_8, 7, SERVO8
	
		pagesel VERVOLG		
		GOTO VERVOLG

		ORG 0x1000
VERVOLG	
		SERVO MINSERVO+8, MAXSERVO+8, TIMSERVO+8, PULS+8, TELVERTR+8, VTFF9_16,FF9_16,0, SERVO9
		SERVO MINSERVO+9, MAXSERVO+9, TIMSERVO+9, PULS+9, TELVERTR+9, VTFF9_16,FF9_16,1, SERVO10
		SERVO MINSERVO+.10,MAXSERVO+.10,TIMSERVO+.10,PULS+.10,TELVERTR+.10,VTFF9_16,FF9_16,2, SERVO11
		SERVO MINSERVO+.11,MAXSERVO+.11,TIMSERVO+.11,PULS+.11,TELVERTR+.11,VTFF9_16,FF9_16,3, SERVO12
		SERVO MINSERVO+.12,MAXSERVO+.12,TIMSERVO+.12,PULS+.12,TELVERTR+.12,VTFF9_16,FF9_16,4, SERVO13
		SERVO MINSERVO+.13,MAXSERVO+.13,TIMSERVO+.13,PULS+.13,TELVERTR+.13,VTFF9_16,FF9_16,5, SERVO14
		SERVO MINSERVO+.14,MAXSERVO+.14,TIMSERVO+.14,PULS+.14,TELVERTR+.14,VTFF9_16,FF9_16,6, SERVO15
		SERVO MINSERVO+.15,MAXSERVO+.15,TIMSERVO+.15,PULS+.15,TELVERTR+.15,VTFF9_16,FF9_16,7, SERVO16

		RELAIS FFR1_8,0,RELAIS1
		RELAIS FFR1_8,1,RELAIS2
		RELAIS FFR1_8,2,RELAIS3
		RELAIS FFR1_8,3,RELAIS4
		RELAIS FFR1_8,4,RELAIS5
		RELAIS FFR1_8,5,RELAIS6
		RELAIS FFR1_8,6,RELAIS7
		RELAIS FFR1_8,7,RELAIS8

		RELAIS FFR9_16,0,RELAIS9
		RELAIS FFR9_16,1,RELAIS10
		RELAIS FFR9_16,2,RELAIS11
		RELAIS FFR9_16,3,RELAIS12
		RELAIS FFR9_16,4,RELAIS13
		RELAIS FFR9_16,5,RELAIS14
		RELAIS FFR9_16,6,RELAIS15
		RELAIS FFR9_16,7,RELAIS16

LUS_SPR1	BTFSS INTCON,T0IF	;TEST OF 20ms VOORBIJ ZIJN	
		GOTO	LUS_SPR2


		MOVLW .98		;nieuwe waarde teller 0 (telt van 98-->256 = 20ms)
		MOVWF TMR0
		BCF INTCON,T0IF
		pagesel LUS
		GOTO LUS
LUS_SPR2

		pagesel LOOP
		CALL LOOP
		pagesel $
		GOTO LUS_SPR1
  

;********************************************************************
;********  EEPROM WAARDES  ******************************************
;********************************************************************

		ORG 	0x2120		;start DATA EEPROM adres
					
		;bij eerste gebruik µC staan de volgende waardes in EEPROM: MIN = 1ms ; MAX = 2ms

		DE .100,.100,.100,.100,.100,.100,.100,.100,.100,.100,.100,.100,.100,.100,.100,.100 ;MINSERCO
		DE .200,.200,.200,.200,.200,.200,.200,.200,.200,.200,.200,.200,.200,.200,.200,.200 ;MAXSERVO
		DE 0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04 ;TIMSERVO
		
		ORG	0x2170		;allereerste stand servo's en relais

		DE 0xFF, 0xFF, 0xFF, 0xFF


		END
;********************************************************************