;;======================================================================;;
;;			DCC ACCESORY DECODER				;;
;;======================================================================;;
;;									;;
;; Program:         DCC4SEMAF -- DCC four semaphore			;;
;; Code:	    Paco Caņada ( http://www.fut.es/~fmco )		;;
;; Platform:        Microchip PIC16F84 and PIC16F628, 8 Mhz		;;
;; Date:            14.06.2005						;;
;; First release:   16.06.2005						;;
;; LastDate:        25.03.2007						;;
;;									;;
;;======================================================================;;

; This program is distributed as is but WITHOUT ANY WARRANTY
; I hope you enjoy!!
;
; Revisions:
; 14.06.2005	Start of writting code
; 26.06.2005	Added saving outputs status
; 27.06.2005	Changed max. light to 0..15. Added Direct mode programming
; 02.07.2005	Added 3 lights Renfe style semaphore and pair selection
; 04.07.2005	Changed to turn off first then light up
; 05.07.2005	Added RENFE maneouvres style and change switch programming (flashing)
; 02.09.2005	Added Lenz mode, corrected bug on CV513
; 09.09.2005	Added change mode on start pressing button
; 25.10.2005	4 semaphore retail version for PIC16F84 (MERG decoder)
; 15.04.2006	Unique asm file for 16F628 and 16F84. Added pushbutton to enable programming
; 25.03.2007	Corrected bug on 16F84 code

; ----- Definitions

#define		__VERNUM	D'2'
#define		__VERDAY	0x25
#define		__VERMONTH	0x03
#define		__VERYEAR	0x07


;#define		__PIC628	1		; select processor. Uncomment this line for 16F628, comment it for 16F84
;#define		__PUSHBUTTON	1		; Uncomment this line for enable programming by pushbutton status



		errorlevel	-302		; suppress Bank warnings


	ifdef	__PIC628

                list    p=16F628,r=hex

	        INCLUDE "P16F628.INC"

                __FUSES _BODEN_ON & _CP_OFF & _PWRTE_ON & _WDT_OFF & _LVP_OFF & _MCLRE_OFF  & _HS_OSC

#define		RAMINI0		0x020		; 80 bytes
#define		RAMINI1		0x0A0		; 80 bytes
#define		RAMINI2		0x120		; 48 bytes
#define		RAMINT		0x070		; 16 bytes

	else

               list    p=16F84,r=hex

	        INCLUDE "P16F84.INC"

                __FUSES _CP_OFF & _PWRTE_ON & _WDT_OFF  & _HS_OSC

#define		RAMINI0		0x0C		; 68 bytes

	endif


; --- Macros

#define		DNOP		goto	$+1


; --- Constant values 

FXTAL		equ	D'8000000'

	ifdef	__PUSHBUTTON

RB_TRIS		equ	0xA0			; RB7,RB5: input

	else

RB_TRIS		equ	0x80			; RB7: input

	endif

RA_TRIS         equ     0x10			; RA4: input
RA_INI          equ     0x00			; all zero
RB_INI          equ     0x00			; all zero
OPTION_INI	equ	0x88			; Option register: no pull-up, no prescaler, wdt 1:1

	ifdef	__PIC628

INTC_INI	equ	0x88			; GIE, RBIE enable, PEIE disable
PIE1_INI	equ	0x00			; no interrupts

	else

INTC_INI	equ	0x88			; GIE, RBIE enable

	endif

#define		OUT1A	0			; Semaphore 1. Port A
#define		OUT1B	1			; 
#define		OUT2A	2			; Semaphore 2
#define		OUT2B	3			; 
#define		OUT3A	4			; Semaphore 3. Port B
#define		OUT3B	5			; 
#define		OUT4A	6			; Semaphore 4
#define		OUT4B	7			;
#define		SWITCH	PORTB,5			; switch
#define		ACKOUT	PORTB,6			; acknowledge
#define		DCCIN	PORTB,7			; DCC input pin

MAX_LIGHT	equ	0x0F

; --- EEPROM Section

#define		EE_INI		0x00

E_CV513		equ	EE_INI+0x00		; CV513	Primary Adress low
E_CV515		equ	EE_INI+0x02		; CV515	Max.light 0..15
E_CV516		equ	EE_INI+0x03		; CV516	
E_CV517		equ	EE_INI+0x04		; CV517	
E_CV518		equ	EE_INI+0x05		; CV518	
E_CV7		equ	EE_INI+0x06		; Manufacturer Version
E_CV8		equ	EE_INI+0x07		; Manufacturer ID
E_CV521		equ	EE_INI+0x08		; CV521	Primary Adress high
E_CV541		equ	EE_INI+0x1C		; config
E_CV545		equ	EE_INI+0x20		; CV545	Slope
E_CV546		equ	EE_INI+0x21		; CV546	Accesory flags

EE_OUT		equ	EE_INI+0x3F		; saved outputs


; ----- Variables

; --- Internal RAM Section

	ifdef	__PIC628

; --- Top on all banks

INT_W		equ	RAMINT+0x00		; interrupt context registers
INT_STAT	equ	RAMINT+0x01

EEDATA0		equ	RAMINT+0x0B		; EEPROM shadow variables
;EEADR0		equ	RAMINT+0x0C

; --- Bank 0

	else

; --- Bank 0

INT_W		equ	RAMINI0+0x00		; interrupt context registers
INT_STAT	equ	RAMINI0+0x01

EEDATA0		equ	RAMINI0+0x41		; EEPROM shadow variables

	endif



SHIFT0		equ	RAMINI0+0x02
SHIFT1		equ	RAMINI0+0x03		; interrupt shift register
SHIFT2		equ	RAMINI0+0x04
SHIFT3		equ	RAMINI0+0x05
SHIFT4		equ	RAMINI0+0x06
SHIFT5		equ	RAMINI0+0x07
DATA00		equ	RAMINI0+0x08
DATA0		equ	RAMINI0+0x09		; received packet
DATA1		equ	RAMINI0+0x0A
DATA2		equ	RAMINI0+0x0B
DATA3		equ	RAMINI0+0x0C

PAGEREG		equ	RAMINI0+0x0D		; Page register

CV513		equ	RAMINI0+0x10		; Primary Adress low byte
CV521		equ	RAMINI0+0x11		; Primary Adress high byte

CV515		equ	RAMINI0+0x12		; max. bright
CV516		equ	RAMINI0+0x13		; 
CV517		equ	RAMINI0+0x14		; 
CV518		equ	RAMINI0+0x15		; 

CV545		equ	RAMINI0+0x16		; slope
CV546		equ	RAMINI0+0x17		; Accesory flags

SPEED1A		equ	RAMINI0+0x20		; final bright
SPEED1B		equ	RAMINI0+0x21
SPEED2A		equ	RAMINI0+0x22
SPEED2B		equ	RAMINI0+0x23
SPEED3A		equ	RAMINI0+0x24
SPEED3B		equ	RAMINI0+0x25
SPEED4A		equ	RAMINI0+0x26
SPEED4B		equ	RAMINI0+0x27

TEMP		equ	RAMINI0+0x28
COUNT		equ	RAMINI0+0x29
DEBOUNCE	equ	RAMINI0+0x2A
DBC_CNT		equ	RAMINI0+0x2B

ACC_COUNT	equ	RAMINI0+0x30		; slope timer

OUTPUT		equ	RAMINI0+0x32		; output buffer
DIR_UP		equ	RAMINI0+0x33		; bright / fade
LIGHT_UP	equ	RAMINI0+0x34		; light up pending
TIMER		equ	RAMINI0+0x35		; timer 1:16

PWM1A		equ	RAMINI0+0x38		; current bright
PWM1B		equ	RAMINI0+0x39
PWM2A		equ	RAMINI0+0x3A
PWM2B		equ	RAMINI0+0x3B
PWM3A		equ	RAMINI0+0x3C
PWM3B		equ	RAMINI0+0x3D
PWM4A		equ	RAMINI0+0x3E
PWM4B		equ	RAMINI0+0x3F

FLAGS		equ	RAMINI0+0x40


; --- Flags
						; FLAGS
#define		NEW_PACKET	FLAGS,0		; New packet received
#define		NOCV		FLAGS,1		; No CV finded
#define		RDONLY		FLAGS,2		; CV read only
#define		DCC4BYTE	FLAGS,3		; DCC command 4 bytes
#define		PROG_2X		FLAGS,6		; 2x prog
#define		RESET_FLG	FLAGS,7		; reset packet

						; CV546
#define		RENFE		CV546,0		; One RENFE semaphore
#define		SAVE_OUTPUTS	CV546,3		; Save outputs to EEPROM




; --------------- Program Section --------------------------------------


		org	0x000

PowerUp:
		clrf	STATUS			; Bank 0 default
		clrf	INTCON			; Disable all interrupts
		clrf	PCLATH			; tables on page 0
		goto	INIT

; ----------------------------------------------------------------------

		org	0x004

Interrupt:
		movwf	INT_W			; save context registers		;1
		swapf	STATUS,w							;2
		movwf	INT_STAT							;3
		clrf	STATUS			; interrupt uses bank 0			;4

		btfsc	DCCIN								;5
		goto	Int_High_Half							;6,7
Int_Low_Half:
		movlw	d'256' - d'154'		; 77us: between 64us (one) and 90us (zero);7
		movwf	TMR0								;8
		bcf	INTCON,T0IF		; clear overflow flag for counting	;9

		bcf	INTCON,RBIF							;10
		goto	EndInt								;13,14

; 1111111111 CCCCCCCC 0 AAAAAAAA 0 DDDDDDDD 0 EEEEEEEE 1
; 'x1111111''111 0 CCCC''CCCC 0 AAA' 'AAAAA 0 DD' DDDDDD 0 E' 'EEEEEEE 1'
;   SHIFT0     SHIFT1      SHIFT2       SHIFT3      SHIFT4      SHIFT5

; 1111111111 0 AAAAAAAA 0 DDDDDDDD 0 EEEEEEEE 1
; 'xxxxxxxx''xx111111''1111 0 AAA' 'AAAAA 0 DD' DDDDDD 0 E' 'EEEEEEE 1'
;   SHIFT0    SHIFT1     SHIFT2       SHIFT3      SHIFT4      SHIFT5


Int_High_Half:
		bsf	STATUS,C							;8
		btfsc	INTCON,T0IF		; if timer 0 overflows then is a DCC zero;9
		bcf	STATUS,C							;10
		rlf	SHIFT5,f		; receiver shift register		;11
		rlf	SHIFT4,f							;12
		rlf	SHIFT3,f							;13
		rlf	SHIFT2,f							;14
		rlf	SHIFT1,f							;15
		rlf	SHIFT0,f							;16

		movlw	0xC0			; ignore older bits			;17
		iorwf	SHIFT1,w		; 					;18
		xorlw	0xFF			;'xx111111' ? first 6 preamble bits	;19
		btfss	STATUS,Z							;20
		goto	Int_High_Check4							;21,22

Int_High_Check3:
		movlw	0xF8			; check 4 preamble and start bit	;23
		andwf	SHIFT2,w		; '1111 0 xxx'				;24
		xorlw	0xF0								;25
		btfss	STATUS,Z		; 					;26
		goto	EndHighHalf							;27,28

		btfss	SHIFT5,0		; check end bit				;29
		goto	EndHighHalf		; is zero, may be 4 byte packet		;30,31

		bsf	NEW_PACKET		; fill received packet			;31
		movf	SHIFT5,w							;32
		movwf	DATA3								;33
		movf	SHIFT4,w							;34
		movwf	DATA2								;35
		movf	SHIFT3,w							;36
		movwf	DATA1								;37
		movf	SHIFT2,w							;38
		movwf	DATA0								;39
		clrf	SHIFT1			; prevent 4 byte command decoding	;40

EndHighHalf:
		bcf	INTCON,RBIF						;46	;31
EndInt:
		swapf	INT_STAT,w		; restore context registers	;49	;34
		movwf	STATUS							;50	;35
		swapf	INT_W,f							;51	;36
		swapf	INT_W,w							;52	;37
		retfie								;53,54	;38,39


Int_High_Check4:
		bsf	SHIFT0,7		; command 4 bytes, check 7 preamble bits;23
		incfsz	SHIFT0,w		;'x1111111'				;24
		goto	EndHighHalf							;25,26

		movlw	0xF0			; check 4 preamble and start bit	;26
		andwf	SHIFT1,w		; '1111 0 xxx'				;27
		xorlw	0xE0								;28
		btfss	STATUS,Z		; 					;29
		goto	EndHighHalf							;30,31

		bsf	NEW_PACKET		; fill received packet			;32
		bsf	DCC4BYTE		; command 4 bytes			;33
		movf	SHIFT5,w							;34
		movwf	DATA3								;35
		movf	SHIFT4,w							;36
		movwf	DATA2								;37
		movf	SHIFT3,w							;38
		movwf	DATA1								;39
		movf	SHIFT2,w							;40
		movwf	DATA0								;41
		movf	SHIFT1,w							;42
		movwf	DATA00								;43
		goto	EndHighHalf							;44,45

; ----------------------------------------------------------------------

BitPos:
		addwf	PCL,f

		retlw	0x01
		retlw	0x02
		retlw	0x04
		retlw	0x08
		retlw	0x10
		retlw	0x20
		retlw	0x40
		retlw	0x80

; ----------------------------------------------------------------------

Accessory:
		movf	CV521,w			; check high address bits
		iorlw	0x80			;'1AAAxxxx'
		xorwf	DATA2,w
		andlw	0xF0
		btfss	STATUS,Z
		goto	ExitDecode
		movf	DATA1,w			; check low address bits
		andlw	0x3F
		xorwf	CV513,w
		btfss	STATUS,Z
		goto	ExitDecode

		movf	DATA2,w			; activate outputs
		andlw	0x0F			; 'xxxxCDDD'
		btfsc	RENFE
		iorlw	0x10
		addwf	PCL,f

		goto	F1A_Clear		; normal style
		goto	F1B_Clear
		goto	F2A_Clear
		goto	F2B_Clear
		goto	F3A_Clear
		goto	F3B_Clear
		goto	F4A_Clear
		goto	F4B_Clear
		goto	F1A_Set
		goto	F1B_Set
		goto	F2A_Set
		goto	F2B_Set
		goto	F3A_Set
		goto	F3B_Set
		goto	F4A_Set
		goto	F4B_Set

		goto	F1A_Clear		; RENFE style
		goto	F1B_Clear
		goto	F2A_Clear
		goto	F2B_Clear
		goto	F3A_Clear
		goto	F3B_Clear
		goto	F4A_Clear
		goto	F4B_Clear
		goto	Renfe_Red
		goto	Renfe_Green
		goto	Renfe_Yellow
		goto	Renfe_Proceed
		goto	Renfe_Red2
		goto	Renfe_Green2
		goto	Renfe_Yellow2
		goto	Renfe_Proceed2

; ----------------------------------------------------------------------

INIT:
		clrf	PORTA
		clrf	PORTB

	ifdef	__PIC628

		movlw	0x07
		movwf	CMCON			; all digital

	endif

		bsf	STATUS,RP0		; bank 1
		movlw	RB_TRIS
		movwf   TRISB
		movlw   RA_TRIS         	; Set port A I/O configuration
		movwf   TRISA

	ifdef	__PIC628

		clrf	VRCON			; voltage reference off
		movlw	PIE1_INI
		movwf	PIE1

	endif
		movlw	OPTION_INI		; Option register: no pull-up, no prescaler, wdt 1:1
		movwf	OPTION_REG
		bcf	STATUS,RP0		; bank 0

	ifdef	__PIC628

		clrf	PIR1
		movlw	0x31			; Timer 1 on, 1:8
		movwf	T1CON

	endif

		movlw	0x20			; clear RAM
		movwf	FSR
ClearRAM:
		clrf	INDF
		incf	FSR,f
		movlw	0x50
		xorwf	FSR,w
		btfss	STATUS,Z
		goto	ClearRAM

		movlw	INTC_INI
		movwf	INTCON			; enable RB4..7 change interrupt

		clrf	PAGEREG			; page register default

		call	LoadCV			; load CV values

		btfsc	SAVE_OUTPUTS		; load saved outputs
		call	LoadOutputs

		movlw	d'2'			; init slope counter
		movwf	ACC_COUNT

; ----------------------------------------------------------------------

MainLoop:
		btfsc	NEW_PACKET		; new packet?
		call	Decode			; yes, decode

Loop:
		btfsc	RESET_FLG		; no output on reset
		goto	MainLoop

		decfsz	ACC_COUNT,f		; slope
		goto	SpeedOn

		movf	CV545,w			; slope CV
		movwf	ACC_COUNT

		btfsc	RENFE
		goto	DoRENFE
DoLight1:
		movf	PWM1A,w			; all off?
		iorwf	PWM1B,w
		btfss	STATUS,Z
		goto	DoLight2
DoLight1A:
		btfss	LIGHT_UP,OUT1A
		goto	DoLight1B
		bcf	LIGHT_UP,OUT1A
		bsf	DIR_UP,OUT1A
		movf	CV515,w
		movwf	SPEED1A
DoLight1B:		
		btfss	LIGHT_UP,OUT1B
		goto	DoLight2
		bcf	LIGHT_UP,OUT1B
		bsf	DIR_UP,OUT1B
		movf	CV515,w
		movwf	SPEED1B
DoLight2:
		movf	PWM2A,w			; all off?
		iorwf	PWM2B,w
		btfss	STATUS,Z
		goto	DoLight3

DoLight2A:
		btfss	LIGHT_UP,OUT2A
		goto	DoLight2B
		bcf	LIGHT_UP,OUT2A
		bsf	DIR_UP,OUT2A
		movf	CV516,w
		movwf	SPEED2A
DoLight2B:		
		btfss	LIGHT_UP,OUT2B
		goto	DoLight3
		bcf	LIGHT_UP,OUT2B
		bsf	DIR_UP,OUT2B
		movf	CV516,w
		movwf	SPEED2B
		goto	DoPWM1A

DoLight3:
		movf	PWM3A,w			; all off?
		iorwf	PWM3B,w
		btfss	STATUS,Z
		goto	DoLight4
DoLight3A:
		btfss	LIGHT_UP,OUT3A
		goto	DoLight3B
		bcf	LIGHT_UP,OUT3A
		bsf	DIR_UP,OUT3A
		movf	CV517,w
		movwf	SPEED3A
DoLight3B:		
		btfss	LIGHT_UP,OUT3B
		goto	DoLight4
		bcf	LIGHT_UP,OUT3B
		bsf	DIR_UP,OUT3B
		movf	CV517,w
		movwf	SPEED3B
DoLight4:
		movf	PWM4A,w			; all off?
		iorwf	PWM4B,w
		btfss	STATUS,Z
		goto	DoPWM1A

DoLight4A:
		btfss	LIGHT_UP,OUT4A
		goto	DoLight4B
		bcf	LIGHT_UP,OUT4A
		bsf	DIR_UP,OUT4A
		movf	CV518,w
		movwf	SPEED4A
DoLight4B:		
		btfss	LIGHT_UP,OUT4B
		goto	DoPWM1A
		bcf	LIGHT_UP,OUT4B
		bsf	DIR_UP,OUT4B
		movf	CV518,w
		movwf	SPEED4B
		goto	DoPWM1A


DoRENFE:
		movf	PWM1A,w			; all off?
		iorwf	PWM1B,w
		iorwf	PWM2A,w
		btfss	STATUS,Z
		goto	DoRENFE2
DoRENFE1A:
		btfss	LIGHT_UP,OUT1A
		goto	DoRENFE1B
		bcf	LIGHT_UP,OUT1A
		bsf	DIR_UP,OUT1A
		movf	CV515,w
		movwf	SPEED1A
DoRENFE1B:		
		btfss	LIGHT_UP,OUT1B
		goto	DoRENFE2A
		bcf	LIGHT_UP,OUT1B
		bsf	DIR_UP,OUT1B
		movf	CV516,w
		movwf	SPEED1B
DoRENFE2A:
		btfss	LIGHT_UP,OUT2A
		goto	DoRENFE2
		bcf	LIGHT_UP,OUT2A
		bsf	DIR_UP,OUT2A
		movf	CV517,w
		movwf	SPEED2A


DoRENFE2:
		movf	PWM3A,w			; all off?
		iorwf	PWM3B,w
		iorwf	PWM4A,w
		btfss	STATUS,Z
		goto	DoPWM1A
DoRENFE3A:
		btfss	LIGHT_UP,OUT3A
		goto	DoRENFE3B
		bcf	LIGHT_UP,OUT3A
		bsf	DIR_UP,OUT3A
		movf	CV515,w
		movwf	SPEED3A
DoRENFE3B:		
		btfss	LIGHT_UP,OUT3B
		goto	DoRENFE4A
		bcf	LIGHT_UP,OUT3B
		bsf	DIR_UP,OUT3B
		movf	CV516,w
		movwf	SPEED3B
DoRENFE4A:
		btfss	LIGHT_UP,OUT4A
		goto	DoPWM1A
		bcf	LIGHT_UP,OUT4A
		bsf	DIR_UP,OUT4A
		movf	CV517,w
		movwf	SPEED4A


DoPWM1A:
		movf	PWM1A,w			; calc PWM acc/dec
		xorwf	SPEED1A,w
		btfsc	STATUS,Z
		goto	DoPWM1B
		movlw	0x01
		btfss	DIR_UP,OUT1A
		movlw	0xFF
		addwf	PWM1A,f

DoPWM1B:
		movf	PWM1B,w
		xorwf	SPEED1B,w
		btfsc	STATUS,Z
		goto	DoPWM2A
		movlw	0x01
		btfss	DIR_UP,OUT1B
		movlw	0xFF
		addwf	PWM1B,f
DoPWM2A:
		movf	PWM2A,w
		xorwf	SPEED2A,w
		btfsc	STATUS,Z
		goto	DoPWM2B
		movlw	0x01
		btfss	DIR_UP,OUT2A
		movlw	0xFF
		addwf	PWM2A,f
DoPWM2B:
		movf	PWM2B,w
		xorwf	SPEED2B,w
		btfsc	STATUS,Z
		goto	DoPWM3A
		movlw	0x01
		btfss	DIR_UP,OUT2B
		movlw	0xFF
		addwf	PWM2B,f
DoPWM3A:
		movf	PWM3A,w			; calc PWM acc/dec
		xorwf	SPEED3A,w
		btfsc	STATUS,Z
		goto	DoPWM3B
		movlw	0x01
		btfss	DIR_UP,OUT3A
		movlw	0xFF
		addwf	PWM3A,f
DoPWM3B:
		movf	PWM3B,w
		xorwf	SPEED3B,w
		btfsc	STATUS,Z
		goto	DoPWM4A
		movlw	0x01
		btfss	DIR_UP,OUT3B
		movlw	0xFF
		addwf	PWM3B,f
DoPWM4A:
		movf	PWM4A,w
		xorwf	SPEED4A,w
		btfsc	STATUS,Z
		goto	DoPWM4B
		movlw	0x01
		btfss	DIR_UP,OUT4A
		movlw	0xFF
		addwf	PWM4A,f
DoPWM4B:
		movf	PWM4B,w
		xorwf	SPEED4B,w
		btfsc	STATUS,Z
		goto	MainLoop
		movlw	0x01
		btfss	DIR_UP,OUT4B
		movlw	0xFF
		addwf	PWM4B,f
		goto	MainLoop


SpeedOn:
		clrf	OUTPUT			; do PWM of outputs
		
	ifdef	__PIC628

		rrf	TMR1H,w
		rrf	TMR1L,w
		movwf	TIMER
		bcf	STATUS,C
		rrf	TIMER,w
		btfsc	TMR1H,1
		iorlw	0x80
		iorlw	0x0F

;		movf	TMR1L,w
;		iorlw	0x0F
		movwf	TIMER

	else
		movlw	0x10
		addwf	TIMER,w
		movwf	TIMER

	endif

		addwf	PWM1A,w
		btfsc	STATUS,C
		bsf	OUTPUT,OUT1A
		movf	TIMER,w
		addwf	PWM1B,w
		btfsc	STATUS,C
		bsf	OUTPUT,OUT1B
		movf	TIMER,w
		addwf	PWM2A,w
		btfsc	STATUS,C
		bsf	OUTPUT,OUT2A
		movf	TIMER,w
		addwf	PWM2B,w
		btfsc	STATUS,C
		bsf	OUTPUT,OUT2B
		movf	TIMER,w
		addwf	PWM3A,w
		btfsc	STATUS,C
		bsf	OUTPUT,OUT3A
		movf	TIMER,w
		addwf	PWM3B,w
		btfsc	STATUS,C
		bsf	OUTPUT,OUT3B
		movf	TIMER,w
		addwf	PWM4A,w
		btfsc	STATUS,C
		bsf	OUTPUT,OUT4A
		movf	TIMER,w
		addwf	PWM4B,w
		btfsc	STATUS,C
		bsf	OUTPUT,OUT4B

		movf	OUTPUT,w
		andlw	0x0F
		movwf	PORTA			; output
		swapf	OUTPUT,w
		andlw	0x0F
		movwf	PORTB
		goto	MainLoop

; ----------------------------------------------------------------------


Decode:
		bcf	NEW_PACKET		; prepare for next packet
		bcf	INTCON,GIE		; disable interrupts for more speed
		btfsc	DCC4BYTE
		goto	Decode4bytes

; 3 byte packets:
; 1111111111 0 AAAAAAAA 0 DDDDDDDD 0 EEEEEEEE 1
; '1111 0 AAA' 'AAAAA 0 DD' DDDDDD 0 E' 'EEEEEEE 1'
;    DATA0        DATA1       DATA2        DATA3

Decode3bytes:
		rrf	DATA0,f
		rrf	DATA1,f
		rrf	DATA2,f
		rrf	DATA3,f			; 'x1111 0 AA''AAAAAA 0 D''DDDDDDD 0''EEEEEEE'
		btfss	STATUS,C		; check end bit
		goto	ExitDecode

		rrf	DATA0,f			; 'xx1111 0 A''AAAAAAA 0''DDDDDDDD''EEEEEEEE'
		rrf	DATA1,f
		rrf	DATA2,f
		btfsc	STATUS,C		; check start bit
		goto	ExitDecode

		rrf	DATA0,f
		rrf	DATA1,f			; 'xxx1111 0''AAAAAAAA''DDDDDDDD''EEEEEEEE'
		btfsc	STATUS,C		; check start bit
		goto	ExitDecode

		movf	DATA1,w			; exclusive or check
		xorwf	DATA2,w
		xorwf	DATA3,w
		btfss	STATUS,Z		; valid packet?
		goto	ExitDecode		; no, return

; 'AAAAAAAA''DDDDDDDD''EEEEEEEE'		; 3 byte packet
;   DATA1     DATA2     DATA3

		movf	DATA1,w			; address = '00000000' ?
		btfsc	STATUS,Z
		goto	Broadcast
;		movf	DATA1,w
		andlw	0xF0
		xorlw	0x70			; '0111xxxx'?
		btfsc	STATUS,Z
		goto	CheckSM			; yes, may be service mode

		movf	DATA1,w
		andlw	0xC0
		xorlw	0x80			;'10xxxxxx'? accessory operation
		btfsc	STATUS,Z
		goto	Accessory

		incfsz	DATA1,w			;'11111111' idle packet
		goto	ExitDecode
		bsf	INTCON,GIE		; yes, don't clear reset flag
		return

; 4 byte packets:
; 1111111111 CCCCCCCC 0 AAAAAAAA 0 DDDDDDDD 0 EEEEEEEE 1
; '111 0 CCCC''CCCC 0 AAA' 'AAAAA 0 DD' DDDDDD 0 E' 'EEEEEEE 1'
;    DATA00      DATA0        DATA1       DATA2        DATA3


Decode4bytes:
		bcf	DCC4BYTE
		rrf	DATA00,f
		rrf	DATA0,f
		rrf	DATA1,f
		rrf	DATA2,f
		rrf	DATA3,f			; 'x111 0 CCC''CCCCC 0 AA''AAAAAA 0 D''DDDDDDD 0''EEEEEEE'
		btfss	STATUS,C		; check end bit
		goto	ExitDecode

		rrf	DATA00,f
		rrf	DATA0,f			; 'xx111 0 CC''CCCCCC 0 A''AAAAAAA 0''DDDDDDDD''EEEEEEEE'
		rrf	DATA1,f
		rrf	DATA2,f
		btfsc	STATUS,C		; check start bit
		goto	ExitDecode

		rrf	DATA00,f
		rrf	DATA0,f
		rrf	DATA1,f			; 'xxx111 0 C''CCCCCCC 0''AAAAAAAA''DDDDDDDD''EEEEEEEE'
		btfsc	STATUS,C		; check start bit
		goto	ExitDecode

		rrf	DATA00,f
		rrf	DATA0,f			; 'xxxx111 0''CCCCCCCC''AAAAAAAA''DDDDDDDD''EEEEEEEE'
		btfsc	STATUS,C		; check start bit
		goto	ExitDecode


		movf	DATA0,w			; exclusive or check
		xorwf	DATA1,w
		xorwf	DATA2,w
		xorwf	DATA3,w
		btfss	STATUS,Z		; valid packet?
		goto	ExitDecode		; no, return

; '0111CCAA''AAAAAAAA''DDDDDDDD''EEEEEEEE'	; Direct mode
;    DATA0    DATA1     DATA2     DATA3

		movf	DATA0,w
		andlw	0xF0
		xorlw	0x70			; '0111xxxx'?
		btfss	STATUS,Z
		goto	ExitDecode		; yes, may be service mode

		btfss	RESET_FLG		; check for SM, reset packet has to come first
		goto	ServModeError
		btfss	PROG_2X
		goto	SetSM_Flag

		bcf	PROG_2X
;		bcf	RESET_FLG
		movf	DATA2,w			; save data
		movwf	EEDATA0

		btfsc	DATA0,0			; CV513.. or CV1..
		goto	ExitProg

		movf	DATA1,w			; x0AAAAAAAA
		call	FindCV
		btfsc	NOCV
		goto	ExitProg
ProgDirect:
		btfsc	DATA0,3	
		goto	RomNxt
		btfss	DATA0,2
		goto	ExitProg		;00 not defined
RomNxt:
		btfss	DATA0,2
		goto	BitMan			;10 Bit Manipulation
		btfss	DATA0,3
		goto	EEVERI			;01 Verify byte
WriteDirect:					;11 Write byte
	ifdef	__PUSHBUTTON

		btfsc	SWITCH
		goto	ExitProg
	endif

		btfsc	RDONLY
		goto	CheckCV8
		call	SetParm
		call	AckPulse
		bcf	PROG_2X
		bcf	NEW_PACKET
		call	LoadCV
		goto	ExitProg

BitMan:
		call	EE_Read
		movwf	EEDATA0
		movlw	EEDATA0
		movwf	FSR
		movlw	b'00000111'
		andwf	DATA2,w
		call	BitPos
		btfss	DATA2,4			; K
		goto	Vbit			; K=0,verify bit
		btfsc	DATA2,3
		iorwf	INDF,f			; D=1,set bit
		xorlw	0xFF
		btfss	DATA2,3
		andwf	INDF,f			; D=0,clear bit
		movf	DATA1,w
		call	FindCV
		goto	ProgDirect		; write complete byte

Vbit:
		andwf	INDF,w
		btfsc	STATUS,Z
		goto	BitClear
BitSet:
		btfsc	DATA2,3			;D=0
		goto	DoAck			;D=1, ack
		goto	ExitProg
BitClear:
		btfss	DATA2,3			;D=1
		goto	DoAck			;D=0, ack
		goto	ExitProg
		


; ----------------------------------------------------------------------
		
F1A_Clear:
F1B_Clear:
F2A_Clear:
F2B_Clear:
F3A_Clear:
F3B_Clear:
F4A_Clear:
F4B_Clear:
		goto	ExitFunction


F1A_Set:
		clrf	SPEED1B			; turn off
		bcf	DIR_UP,OUT1B
		bcf	LIGHT_UP,OUT1B
		btfss	DIR_UP,OUT1A		; if lights, nothing to do
		bsf	LIGHT_UP,OUT1A		; next light this
		goto	ExitFunction
F1B_Set:
		clrf	SPEED1A			; turn off
		bcf	DIR_UP,OUT1A
		bcf	LIGHT_UP,OUT1A
		btfss	DIR_UP,OUT1B		; if lights nothing to do
		bsf	LIGHT_UP,OUT1B		; next light this
		goto	ExitFunction
F2A_Set:
		clrf	SPEED2B			; turn off
		bcf	DIR_UP,OUT2B
		bcf	LIGHT_UP,OUT2B
		btfss	DIR_UP,OUT2A		; if lights, nothing to do
		bsf	LIGHT_UP,OUT2A		; next light this
		goto	ExitFunction
F2B_Set:
		clrf	SPEED2A			; turn off
		bcf	DIR_UP,OUT2A
		bcf	LIGHT_UP,OUT2A
		btfss	DIR_UP,OUT2B		; if lights, nothing to do
		bsf	LIGHT_UP,OUT2B		; next light this
		goto	ExitFunction

F3A_Set:
		clrf	SPEED3B			; turn off
		bcf	DIR_UP,OUT3B
		bcf	LIGHT_UP,OUT3B
		btfss	DIR_UP,OUT3A		; if lights, nothing to do
		bsf	LIGHT_UP,OUT3A		; next light this
		goto	ExitFunction
F3B_Set:
		clrf	SPEED3A			; turn off
		bcf	DIR_UP,OUT3A
		bcf	LIGHT_UP,OUT3A
		btfss	DIR_UP,OUT3B		; if lights nothing to do
		bsf	LIGHT_UP,OUT3B		; next light this
		goto	ExitFunction
F4A_Set:
		clrf	SPEED4B			; turn off
		bcf	DIR_UP,OUT4B
		bcf	LIGHT_UP,OUT4B
		btfss	DIR_UP,OUT4A		; if lights, nothing to do
		bsf	LIGHT_UP,OUT4A		; next light this
		goto	ExitFunction
F4B_Set:
		clrf	SPEED4A			; turn off
		bcf	DIR_UP,OUT4A
		bcf	LIGHT_UP,OUT4A
		btfss	DIR_UP,OUT4B		; if lights, nothing to do
		bsf	LIGHT_UP,OUT4B		; next light this
		goto	ExitFunction


ExitFunction:
		bcf	RESET_FLG
		bsf	INTCON,GIE		; enable interrupts
		btfss	SAVE_OUTPUTS
		return
		movf	DIR_UP,w		; save output state
		iorwf	LIGHT_UP,w
		movwf	EEDATA0
		movlw	EE_OUT
		goto	SetParm

Renfe_Red:
		movlw	0xFF			; rele on
		movwf	SPEED2B
		movwf	PWM2B
		bsf	DIR_UP,OUT2B
		clrf	SPEED2A			; turn off yellow
		bcf	DIR_UP,OUT2A
		bcf	LIGHT_UP,OUT2A
		goto	F1A_Set			; turn off green, turn on red

Renfe_Red2:
		movlw	0xFF			; rele on
		movwf	SPEED4B
		movwf	PWM4B
		bsf	DIR_UP,OUT4B
		clrf	SPEED4A			; turn off yellow
		bcf	DIR_UP,OUT4A
		bcf	LIGHT_UP,OUT4A
		goto	F3A_Set			; turn off green, turn on red


Renfe_Green:
		clrf	SPEED2B			; rele off
		clrf	PWM2B
		bcf	DIR_UP,OUT2B
		clrf	SPEED2A			; turn off yellow
		bcf	DIR_UP,OUT2A
		bcf	LIGHT_UP,OUT2A
		goto	F1B_Set			; turn off red, turn on green

Renfe_Green2:
		clrf	SPEED4B			; rele off
		clrf	PWM4B
		bcf	DIR_UP,OUT4B
		clrf	SPEED4A			; turn off yellow
		bcf	DIR_UP,OUT4A
		bcf	LIGHT_UP,OUT4A
		goto	F3B_Set			; turn off red, turn on green


Renfe_Proceed:
		clrf	SPEED2B			; rele off
		clrf	PWM2B
		bcf	DIR_UP,OUT2B
		clrf	SPEED1A			; turn off red
		bcf	DIR_UP,OUT1A
		bcf	LIGHT_UP,OUT1A

		btfsc	DIR_UP,OUT1B		; all two on?
		btfss	DIR_UP,OUT2A
		goto	Renfe_Proceed_On	; no, turn off and light
		goto	ExitFunction		; yes, nothing to do
Renfe_Proceed_On:
		clrf	SPEED1B
		clrf	SPEED2A
		bcf	DIR_UP,OUT1B
		bcf	DIR_UP,OUT2A
		bsf	LIGHT_UP,OUT1B		; next light green
		bsf	LIGHT_UP,OUT2A		; next light yellow
		goto	ExitFunction

Renfe_Proceed2:
		clrf	SPEED4B			; rele off
		clrf	PWM4B
		bcf	DIR_UP,OUT4B
		clrf	SPEED3A			; turn off red
		bcf	DIR_UP,OUT3A
		bcf	LIGHT_UP,OUT3A

		btfsc	DIR_UP,OUT3B		; all two on?
		btfss	DIR_UP,OUT4A
		goto	Renfe_Proceed_On2	; no, turn off and light
		goto	ExitFunction		; yes, nothing to do
Renfe_Proceed_On2:
		clrf	SPEED3B
		clrf	SPEED4A
		bcf	DIR_UP,OUT3B
		bcf	DIR_UP,OUT4A
		bsf	LIGHT_UP,OUT3B		; next light green
		bsf	LIGHT_UP,OUT4A		; next light yellow
		goto	ExitFunction


Renfe_Yellow:
		clrf	SPEED2B			; rele off
		clrf	PWM2B
		bcf	DIR_UP,OUT2B
		clrf	SPEED1A			; turn off all
		clrf	SPEED1B			; 
		bcf	DIR_UP,OUT1A
		bcf	DIR_UP,OUT1B
		bcf	LIGHT_UP,OUT1A
		bcf	LIGHT_UP,OUT1B
		btfss	DIR_UP,OUT2A		; if lights, nothing to do
		bsf	LIGHT_UP,OUT2A		; next light yellow
		goto	ExitFunction

Renfe_Yellow2:
		clrf	SPEED4B			; rele off
		clrf	PWM4B
		bcf	DIR_UP,OUT4B
		clrf	SPEED3A			; turn off all
		clrf	SPEED3B			; 
		bcf	DIR_UP,OUT3A
		bcf	DIR_UP,OUT3B
		bcf	LIGHT_UP,OUT3A
		bcf	LIGHT_UP,OUT3B
		btfss	DIR_UP,OUT4A		; if lights, nothing to do
		bsf	LIGHT_UP,OUT4A		; next light yellow
		goto	ExitFunction
		
; ----------------------------------------------------------------------

Broadcast:
		movf	DATA2,w			; reset packet?
		btfss	STATUS,Z
		goto	ExitDecode
		bcf	PROG_2X
		bsf	RESET_FLG
						; reset decoder
		clrf	PORTA
		clrf	PORTB

		bsf	INTCON,GIE		; enable interrupts
		return


ExitDecode:
		bcf	RESET_FLG
		bsf	INTCON,GIE		; enable interrupts
		return

;************* SM Mode *******************************************
; Service Mode

CheckSM:
		btfss	RESET_FLG		; check for SM, reset packet has to come first
		goto	ServModeError
		btfss	PROG_2X
		goto	SetSM_Flag

		bcf	PROG_2X
		movf	DATA2,w				; save data
		movwf	EEDATA0

		movf	DATA1,w				; 3 byte programming
		andlw	b'11110111'
		xorlw	b'01110101'			; Reg6
		btfsc	STATUS,Z		
		goto	REG6
		xorlw	(b'01110101')^(b'01110100')	; Reg5
		btfsc	STATUS,Z		
		goto	REG5
		xorlw	(b'01110100')^(b'01110110')	; reg7
		btfsc	STATUS,Z
		goto	REG7	
		xorlw	(b'01110110')^(b'01110111')	; reg8
		btfsc	STATUS,Z
		goto	REG8	

		movf	DATA1,w
		andlw	0x03
		addwf	PAGEREG,w
		call	FindCV
		btfsc	NOCV
		goto	ExitProg
ProgReg:
		btfss	DATA1,3
		goto	EEVERI
		goto	EEPROG

REG5:
		movlw	E_CV541			; CV541 configuration
		goto	ProgReg

REG6:
		btfss	DATA1,3			; read or write
		goto	REG6RD
		decf	DATA2,f			; Page register
		rlf	DATA2,f
		rlf	DATA2,w
		andlw	b'11111100'		; page 1 and 129 are the same. CV1 & CV513
		movwf	PAGEREG
		goto	ExitProg
REG6RD:
		decf	DATA2,f			; read page register
		rlf	DATA2,f
		rlf	DATA2,w
		andlw	b'11111100'		; page 1 and 129 are the same. CV1 & CV513
		xorwf	PAGEREG,w
		goto	EEVERIP

REG7:
		movlw	E_CV7			; only read
		btfss	DATA1,3
		goto	EEVERI
		goto	ExitProg

REG8:
		movlw	E_CV8			; only read
		btfss	DATA1,3
		goto	EEVERI
		goto	CheckResetCV		; if CV8 = 33 reset CV

	
EEPROG:
	ifdef	__PUSHBUTTON

		btfsc	SWITCH
		goto	ExitProg
	endif

		btfsc	RDONLY
		goto	CheckCV8
		call	SetParm			; program EEPROM
		call	AckPulse		; do ACK
		bcf	PROG_2X
		bcf	NEW_PACKET
		call	LoadCV
		goto	ExitProg


EEVERI:
		call	EE_Read			; check data
		xorwf	DATA2,w
EEVERIP:
		btfss	STATUS,Z
		goto	ExitProg
DoAck:
		call	AckPulse		; equal, do ACK
		bcf	PROG_2X
;		bcf	NEW_PACKET
		goto	ExitProg


SetSM_Flag:
		bsf	PROG_2X
		goto	ExitProg

ServModeError:
		bcf	RESET_FLG
		bcf	PROG_2X
		goto	ExitProg

CheckCV8:
		xorlw	E_CV8			; CV8?
		btfss	STATUS,Z
		goto	ExitProg
CheckResetCV:
		movlw	d'33'			; CV8 = 33 -> reset CV
		xorwf	DATA2,w
		btfss	STATUS,Z
		goto	ExitProg
		call	ResetCV			; program CV defaults
		call	AckPulse		; do ACK
		bcf	PROG_2X
		bcf	NEW_PACKET
		call	LoadCV
		goto	ExitProg

ExitProg:
		bsf	INTCON,GIE		; enable interrupts
		return
		
; -----------------------------------------------------------------------------------

AckPulse:
		movlw	b'00001111'		; all lights on
		movwf	PORTA
		movlw	b'01001111'		; all lights on, Ack out
		movwf	PORTB
		movlw	d'6'			; 6ms pulse
		movwf	TEMP
		movlw	0x00
AckNext:
		DNOP				;1,2
		DNOP				;3,4
		addlw	0xFF			;1
		btfss	STATUS,Z		;2
		goto	$-2			;3,4
		decfsz	TEMP,f
		goto	AckNext
		clrf	PORTA			; all light off	
		clrf	PORTB
		return

; -----------------------------------------------------------------------------------

LoadCV:
		movlw	E_CV513			; address low
		call	EE_Read
		movwf	CV513			; set value for comparison
		movlw	E_CV521			; address high
		call	EE_Read
		movwf	CV521
		swapf	CV521,f
		comf	CV521,w			; top address is complemented
		andlw	0x70
		movwf	CV521			; now CV521='0AAA0000'

		movlw	E_CV515			; 
		call	EE_Read
		iorlw	0xF0			; 'xxxxABCD'
		movwf	CV515			; '1111ABCD'
		swapf	CV515,f			; 'ABCD1111'

		movlw	E_CV516			; 
		call	EE_Read
		iorlw	0xF0			; 'xxxxABCD'
		movwf	CV516			; '1111ABCD'
		swapf	CV516,f			; 'ABCD1111'

		movlw	E_CV517			; 
		call	EE_Read
		iorlw	0xF0			; 'xxxxABCD'
		movwf	CV517			; '1111ABCD'
		swapf	CV517,f			; 'ABCD1111'

		movlw	E_CV518			; 
		call	EE_Read
		iorlw	0xF0			; 'xxxxABCD'
		movwf	CV518			; '1111ABCD'
		swapf	CV518,f			; 'ABCD1111'

		movlw	E_CV545			; slope
		call	EE_Read
		movwf	CV545
		movlw	E_CV546			; accesory flags
		call	EE_Read
		movwf	CV546

		return


LoadOutputs:
		movlw	EE_OUT			; read saved outputs
		call	EE_Read
		movwf	DIR_UP			

		movf	CV515,w
		btfss	DIR_UP,OUT1A
		clrw
		movwf	SPEED1A
		movf	CV515,w
		btfsc	RENFE
		movf	CV516,w
		btfss	DIR_UP,OUT1B
		clrw
		movwf	SPEED1B
		movf	CV516,w
		btfsc	RENFE
		movf	CV517,w
		btfss	DIR_UP,OUT2A
		clrw
		movwf	SPEED2A
		movf	CV516,w
		btfsc	RENFE
		movlw	MAX_LIGHT
		btfss	DIR_UP,OUT2B
		clrw
		movwf	SPEED2B

		movf	CV517,w
		btfsc	RENFE
		movf	CV515,w
		btfss	DIR_UP,OUT3A
		clrw
		movwf	SPEED3A
		movf	CV517,w
		btfsc	RENFE
		movf	CV516,w
		btfss	DIR_UP,OUT3B
		clrw
		movwf	SPEED3B
		movf	CV518,w
		btfsc	RENFE
		movf	CV517,w
		btfss	DIR_UP,OUT4A
		clrw
		movwf	SPEED4A
		movf	CV518,w
		btfsc	RENFE
		movlw	MAX_LIGHT
		btfss	DIR_UP,OUT4B
		clrw
		movwf	SPEED4B

		clrf	LIGHT_UP
		return
		

; -----------------------------------------------------------------------------------

FindCV:
		bcf	NOCV
		bcf	RDONLY

		xorlw	0x00			; CV513
		btfsc	STATUS,Z
		retlw	E_CV513
		xorlw	(0x00 ^ 0x08)		; CV521
		btfsc	STATUS,Z
		retlw	E_CV521
		xorlw	(0x08 ^ 0x1C)		; CV541
		btfsc	STATUS,Z
		retlw	E_CV541

		xorlw	(0x1C ^ 0x02)		; CV515
		btfsc	STATUS,Z
		retlw	E_CV515
		xorlw	(0x02 ^ 0x03)		; CV516
		btfsc	STATUS,Z
		retlw	E_CV516
		xorlw	(0x03 ^ 0x04)		; CV517
		btfsc	STATUS,Z
		retlw	E_CV517
		xorlw	(0x04 ^ 0x05)		; CV518
		btfsc	STATUS,Z
		retlw	E_CV518

		xorlw	(0x05 ^ 0x20)		; CV545
		btfsc	STATUS,Z
		retlw	E_CV545
		xorlw	(0x20 ^ 0x21)		; CV546
		btfsc	STATUS,Z
		retlw	E_CV546


		bsf	RDONLY
		xorlw	(0x21 ^ 0x06)		; CV519
		btfsc	STATUS,Z
		retlw	E_CV7
		xorlw	(0x06 ^ 0x07)		; CV520
		btfsc	STATUS,Z
		retlw	E_CV8

		bsf	NOCV			; CV not finded
		retlw	0x7F			; return last location

;---------------------------------------------------------------------------

ResetCV:
		movlw	0x01			; reset CV to default values
		movwf	EEDATA0
		movlw	E_CV513
		call	SetParm

		movlw	MAX_LIGHT		; max. bright
		movwf	EEDATA0
		movlw	E_CV515
		call	SetParm
		movlw	E_CV516
		call	SetParm
		movlw	E_CV517
		call	SetParm
		movlw	E_CV518
		call	SetParm

		movlw	0x00
		movwf	EEDATA0
		movlw	E_CV521
		call	SetParm
	
		movlw	0x80
		movwf	EEDATA0
		movlw	E_CV541
		call	SetParm

		movlw	0x28			; slope
		movwf	EEDATA0
		movlw	E_CV545
		call	SetParm

		movlw	0x08			; save outputs
		movwf	EEDATA0
		movlw	E_CV546
		call	SetParm

		return


;---------------------------------------------------------------------------

	ifdef	__PIC628

EE_Read:
		bsf	STATUS,RP0		; w=ADR
		movwf	EEADR
		bsf	EECON1,RD
		movf	EEDATA,w
		bcf	STATUS,RP0
		return

SetParm:
		call	EE_Read			; w=ADR, EEDATA0=data. Write only changes
		xorwf	EEDATA0,w
		btfsc	STATUS,Z
		return
EE_Write:		
		movf	EEDATA0,w
		bsf	STATUS,RP0
		movwf	EEDATA
		bsf	EECON1,WREN
		bcf	INTCON,GIE
		movlw	0x55
		movwf	EECON2
		movlw	0xAA
		movwf	EECON2
		bsf	EECON1,WR
		bsf	INTCON,GIE
		bcf	EECON1,WREN
EEWrite0:
		btfsc	EECON1,WR
		goto	EEWrite0
		bcf	STATUS,RP0
		return

	else

EE_Read:
		movwf	EEADR
		bsf	STATUS,RP0		; w=ADR
		bsf	EECON1,RD
		bcf	STATUS,RP0
		movf	EEDATA,w
		return

SetParm:
		call	EE_Read			; w=ADR, EEDATA0=data. Write only changes
		xorwf	EEDATA0,w
		btfsc	STATUS,Z
		return
EE_Write:		
		movf	EEDATA0,w
		movwf	EEDATA
		bsf	STATUS,RP0
		bsf	EECON1,WREN
		bcf	INTCON,GIE
		movlw	0x55
		movwf	EECON2
		movlw	0xAA
		movwf	EECON2
		bsf	EECON1,WR
		bsf	INTCON,GIE
		bcf	EECON1,WREN
EEWrite0:
		btfsc	EECON1,WR
		goto	EEWrite0
		bcf	STATUS,RP0
		return

	endif


; ----- EEPROM default values


		org	0x2100

		dw	0x01			; CV513	Adress low
		dw	0xFF			; 
		dw	MAX_LIGHT		; CV515 Max. bright
		dw	MAX_LIGHT		; CV516
		dw	MAX_LIGHT		; CV517
		dw	MAX_LIGHT		; CV518
		dw	0x14			; CV519 Manufacturer Version
		dw	0x0D			; CV520	Manufacturer ID
		dw	0x00			; CV521 Address high
		dw	0xFF			; 
		dw	0xFF			;
		dw	0xFF			;
		dw	0xFF			;
		dw	0xFF			;
		dw	0xFF			; 
		dw	0xFF			;

	ifdef	__PUSHBUTTON
		dt	"4semaf-P"
	else
		dt	"4-semaf."
	endif

	ifdef	__PIC628
		dt	"F628"
	else
		dt	"F84 "
	endif


		dw	0x80			; CV541 Config
		dw	0xFF			; 
		dw	0xFF			; 
		dw	0xFF			; 
		dw	0x28			; CV545 Slope
		dw	0x08			; CV546 Accesory flags

		org	0x2128


		dt	"F.Caņada"
		dt	(__VERDAY   >> 4)  +0x30
		dt	(__VERDAY   & 0x0F)+0x30,"/"
		dt	(__VERMONTH >> 4)  +0x30
		dt	(__VERMONTH & 0x0F)+0x30,"/"
		dt	(__VERYEAR  >> 4)  +0x30
		dt	(__VERYEAR  & 0x0F)+0x30

		org	0x213F

		dw	b'10011001'		; default output

	end

