; accdec.asm - accessory decoder with 25us time loop for PIC12C519
; 5 I/O ports for pointing motors
; every port programmable over switch, pom & dir mode

; Version: 2    Date: 03 March 2002
; Copyright (C) 2002  Georg Ziegler

; timer for every port 
; cv515 timer for GP0
; cv516 timer for GP1
; cv517 timer for GP2
; cv518 timer for GP4 & GP5
; Zero for constant output

; switch adr
; 1 2 3 4 5   GP0 1 2  4 5
; x             1 0 0  - -
;   x           0 1 0  - -
;     x         0 0 1  - -
;       x       - - -  1 0
;         x     - - -  0 1
; write =! 0xAA in cv519 resets the port adresses and timer

;    This program is free software; you can redistribute it and/or
;    modify it under the terms of the GNU General Public License as
;    published by the Free Software Foundation; either version 2 of
;    the License, or (at your option) any later version.

;    This program is distributed in the hope that it will be useful,
;    but WITHOUT ANY WARRANTY; without even the implied warranty of
;    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
;    General Public License for more details.

;    You should have received a copy of the GNU General Public License
;    along with this program; if not, write to the Free Software
;    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

;    Contact:
;    Georg Ziegler
;    Zwehrener Weg 23a
;    34121 Kassel
;    -Germany-
;    g.zi@gmx.de
;--------------------------------------------------------------------
	LIST	P=12CE519, R=DEC
	INCLUDE <P12CE519.INC>
	 __CONFIG _MCLRE_OFF & _CP_OFF & _WDT_ON & _IntRC_OSC 
;====================================================================
;                                             ___ 1 (IB = 8-15 high)
;                       adr IB  =   76 5432   A98  10
ADRGP0	EQU	2		; 10AA AAAA  1AAA CDDD
F1F8GP0	EQU	1		;   ^^ ^^^^   ^^^  ^^
TONGP0	EQU	10		; 0 = longest time ca. 3 sec.

ADRGP1	EQU	ADRGP0		; 11 bit adress from IB (including bits 21 from DDD)
F1F8GP1	EQU	2		; activ at F1-F8	(0-7 low; 8-15 high, inverted for simple use with IB adresses)
TONGP1	EQU	10		; time on gp1		(max 255)

ADRGP2	EQU	ADRGP0
F1F8GP2	EQU	3
TONGP2	EQU	10

ADRGP4	EQU	ADRGP0
F1F8GP4	EQU	4
TONGP4	EQU	10

ADRGP5	EQU	ADRGP0
F1F8GP5	EQU	5		; TONGP5 same as TONGP4
				; eeprom adr0 not programable!!

LTIMER	EQU	4		; 1 ~3sec ; highest value 254 ~12min
				; 4 ~12sec
; programming on main with IB:
; ADRGP0 * 2 = adress over POM
; 511*8(NMRA) or 2044*2(IB)
;====================================================================
#DEFINE	DCCIN	3		; DCC input pin (GPIO,3 only input)
;--------------------------------------------------------------------
CV520	EQU	0x0D	; Home Made Decoder		10 0000 1000	
CV519	EQU	0x01	; Version No.  XX00 0000	10 0000 0111
			; 00=Coil(0x00)  01=Stepper(0x40)
			; 10=Free(0x80)  11=Other(0xC0)
;--------------------------------------------------------------------
INDF	EQU	0x00	; Indirect Adressing
tmr0	EQU	0x01	; Timer
PC	EQU	0x02	; Program Counter
STATUS	EQU	0x03	; Status Register
FSR	EQU	0x04	; Special Funcion Register
OSCCAL	EQU	0x05	; Calibration Register
GPIO	EQU	0x06	; GP0-GP5 input/output
;------------------------
PRGBITS	EQU	0x07	; dummy for progbits
CONFIG	EQU	0x08	;
;	EQU	0x09	;
BT1	EQU	0x0A	; FSR auf 0x09
BT2	EQU	0x0B	;
BT3	EQU	0x0C	;
BT4	EQU	0x0D	;
BT5	EQU	0x0E	;
BT6	EQU	0x0F	; FSR auf 0x10
;------------------------
Z1	EQU	0x10	;
GP0TON	EQU	0x11	;
GP1TON	EQU	0x12	;
GP2TON	EQU	0x13	;
GP4TON	EQU	0x14	;
GP5TON	EQU	0x15	;
Z2	EQU	0x16	;
;	EQU	0x17	;
XOR	EQU	0x18	;
NOADR	EQU	0x19	; no adress since ... 
CV1	EQU	0x1A	;
CV17	EQU	0x1B	;
CV18	EQU	0x1C	;
PRE	EQU	0x1D	; Preample 12 BIT
LO	EQU	0x1E	; low bit counter
HI	EQU	0x1F	; hi bit counter
;------------------------
MAPCV	EQU	0x3F	; rom CV's copied to here, also used for init EEPROM

; cv515-518 Time On for Functions F1-F4 

CV513	EQU	0x35	; GP0 high	10 0000 0000	 3
CV521	EQU	0x3A	; GP0 low	10 0000 1000	 3

CV515	EQU	0x31	; Time On GP0	10 0000 0010	 3
CV516	EQU	0x32	; Time On GP1	10 0000 0011	 6
CV517	EQU	0x33	; Time On GP2	10 0000 0100	 9
CV518	EQU	0x34	; Time On GP4	10 0000 0101	12
;CV519	EQU	0x30	; Time On GP5	10 0000 0110	15

; CV545-CV593=49 Reserved for manufacturer use 

CV545	EQU	0x35	; GP0 high	10 0010 0001	 1
CV546	EQU	0x3A	; GP0 low	10 0010 0010	 2
CV547	EQU	0x31	; Time On GP0	10 0010 0011	 3

CV548	EQU	0x36	; GP1 high	10 0010 0100	 4
CV549	EQU	0x3B	; GP1 low	10 0010 0101	 5
CV550	EQU	0x32	; Time On GP1	10 0010 0110	 6

CV551	EQU	0x37	; GP2 high	10 0010 0111	 7
CV552	EQU	0x3C	; GP2 low	10 0010 1000	 8
CV553	EQU	0x33	; Time On GP2	10 0010 1001	 9

CV554	EQU	0x38	; GP4 high	10 0010 1010	10
CV555	EQU	0x3D	; GP4 low	10 0010 1011	11
CV556	EQU	0x34	; Time On GP4	10 0010 1100	12

CV557	EQU	0x39	; GP5 high	10 0010 1101	13
CV558	EQU	0x3E	; GP5 low	10 0010 1110	14
CV559	EQU	0x30	; Time On GP5	10 0010 1111	15

;--------------------------------
CARRY	EQU	0
ZERO	EQU	2
SEITE	EQU	5

#DEFINE	STEPOK?	CONFIG,2	;
#DEFINE	NOCV	CONFIG,2	; is mapped with STEPOK?
#DEFINE	ROMCV	CONFIG,3	; is mapped with FLACKER
#DEFINE	BITHI	CONFIG,6	;

#DEFINE	PRG_GP0	PRGBITS,0	; marker for PROGGP0
#DEFINE	PRG_GP1	PRGBITS,1	; marker for PROGGP1
#DEFINE	PRG_GP2	PRGBITS,2	; marker for PROGGP2
#DEFINE	PRG_GP4	PRGBITS,4	; marker for PROGGP4
#DEFINE	PRG_GP5	PRGBITS,5	; marker for PROGGP5
#DEFINE	PROGBIT	PRGBITS,6	;
#DEFINE	PROGBT1	PRGBITS,7	;

#DEFINE	ACKBIT	STATUS,6	; never overwriten

;--------------------------------------------------------------------
	ORG     0		; Reset Vector

INIT	MOVLW	00000000b	; start value (information about OSCCAL in pdf file rong!! linear speed increase!)
	MOVWF	OSCCAL		; write calibration value

	MOVLW	11010001b	; no wakeup, no pullup, T0 int., hightolow, T0, 1:4
	OPTION

;	GOTO	EEEXIT		; test
;....................................................................
CALI	BTFSS	GPIO,DCCIN	;-----------------
	GOTO	CALI		;	Anfang
CALI1	BTFSC	GPIO,DCCIN	;	finden
	GOTO	CALI1		;-----------------
	CLRF	tmr0		; Timer auf 0
CALI2	BTFSS	GPIO,DCCIN	;
	GOTO	CALI2		;-----------------
	MOVF	tmr0,0		; Timer 
	MOVWF	BT5		; sichern
	MOVLW	34		;-----------------
	SUBWF	BT5,0		;	LOW
	BTFSC	STATUS,CARRY	;	BIT
	GOTO	CALI		;-----------------
	MOVLW	26		; <- Loop +1 (lowest 26; highest 27)
	SUBWF	BT5,0		;
	BTFSC	STATUS,CARRY	; Hi BIT > 25?
	GOTO	CALEX		;-----------------
	MOVLW	00001000b	;
	ADDWF	OSCCAL,1	;
	GOTO	CALI		;-----------------
;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
				; -----------------------------------
CALEX	CLRF	GPIO
	MOVLW	(1<<DCCIN)	; GP3 input, rest output
	TRIS	GPIO		; tristate port GPIO

	MOVLW	11010110b	; no wakeup, no pullup, T0 int., hightolow, T0, 1:128
	OPTION

CLEAR	BCF	ACKBIT		;
	CLRF	LO		;
	CLRF	HI		; set PWM to 1 to force a jump
	CLRF	Z1		; counter
	CLRF	Z2		; counter

BEGIN
; EEPROM ............................................................

LOADREG	MOVLW	0x30		;
	MOVWF	FSR		; Pointer for indirect Adressing

	CLRF	EEADDR		;
EEREAD	BSF	STATUS,SEITE	; set to 200H begin EEPROM
	CALL	READ_RANDOM	;
	BCF	STATUS,SEITE	; auf ROM seite 0
	BTFSS	PC_OFFSET,EE_OK ;(BTFSC STATUS,ZERO) ERROR?
	GOTO	EEREAD		;
	MOVF	EEDATA,0	;
	MOVWF	INDF		;
	MOVLW	0x3F		;
	XORWF	FSR,0		;
	ANDLW	00111111b	;
	BTFSC	STATUS,ZERO	;
	GOTO	EEEXIT		;
	INCF	FSR,1		;
	INCF	EEADDR		;
	GOTO	EEREAD		;

EEEXIT	MOVF	CV518,0		;TONGP4
	MOVWF	CV559		;TONGP5
;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

; Register Preset ...................................................
;	BSF	FSR,5

	MOVLW	0xAA		;
	XORWF	MAPCV,0		; test cv
	BTFSC	STATUS,ZERO	; skip if not 0
	GOTO	SETEXIT		;


	CLRF	EEADDR		; 0
	INCF	EEADDR		; 1
	MOVLW	TONGP0
	MOVWF	EEDATA		; cv515
	CALL	DPROG

	INCF	EEADDR		; 2
	MOVLW	TONGP1
	MOVWF	EEDATA		; cv516
	CALL	DPROG

	INCF	EEADDR		; 3
	MOVLW	TONGP2
	MOVWF	EEDATA		; cv517
	CALL	DPROG

	INCF	EEADDR		; 4
	MOVLW	TONGP4
	MOVWF	EEDATA		; cv518
	CALL	DPROG
	; TONGP5 same as TONGP4


	INCF	EEADDR		; 5
	MOVLW	((((ADRGP0-1)<<1)+(F1F8GP0-1))>>3)+1&00111111b|10000000b
	MOVWF	EEDATA		; cv545
	CALL	DPROG

	INCF	EEADDR		; 6
	MOVLW	((((ADRGP1-1)<<1)+(F1F8GP1-1))>>3)+1&00111111b|10000000b
	MOVWF	EEDATA		; cv548
	CALL	DPROG

	INCF	EEADDR		; 7
	MOVLW	((((ADRGP2-1)<<1)+(F1F8GP2-1))>>3)+1&00111111b|10000000b
	MOVWF	EEDATA		; cv551
	CALL	DPROG

	INCF	EEADDR		; 8
	MOVLW	((((ADRGP4-1)<<1)+(F1F8GP4-1))>>3)+1&00111111b|10000000b
	MOVWF	EEDATA		; cv554
	CALL	DPROG

	INCF	EEADDR		; 9
	MOVLW	((((ADRGP5-1)<<1)+(F1F8GP5-1))>>3)+1&00111111b|10000000b
	MOVWF	EEDATA		; cv557
	CALL	DPROG


	INCF	EEADDR		; A
	MOVLW	((((((ADRGP0-1)<<1)+(F1F8GP0-1))>>5)&01110000)^11111000b)+(((ADRGP0-1)<<1)+(F1F8GP0-1)&00000111b)
	MOVWF	EEDATA		; cv546
	CALL	DPROG

	INCF	EEADDR		; B
	MOVLW	((((((ADRGP1-1)<<1)+(F1F8GP1-1))>>5)&01110000)^11111000b)+(((ADRGP1-1)<<1)+(F1F8GP1-1)&00000111b)
	MOVWF	EEDATA		; cv547
	CALL	DPROG

	INCF	EEADDR		; C
	MOVLW	((((((ADRGP2-1)<<1)+(F1F8GP2-1))>>5)&01110000)^11111000b)+(((ADRGP2-1)<<1)+(F1F8GP2-1)&00000111b)
	MOVWF	EEDATA		; cv552
	CALL	DPROG

	INCF	EEADDR		; D
	MOVLW	((((((ADRGP4-1)<<1)+(F1F8GP4-1))>>5)&01110000)^11111000b)+(((ADRGP4-1)<<1)+(F1F8GP4-1)&00000111b)
	MOVWF	EEDATA		; cv555
	CALL	DPROG

	INCF	EEADDR		; E
	MOVLW	((((((ADRGP5-1)<<1)+(F1F8GP5-1))>>5)&01110000)^11111000b)+(((ADRGP5-1)<<1)+(F1F8GP5-1)&00000111b)
	MOVWF	EEDATA		; cv558
	CALL	DPROG

	INCF	EEADDR		; F
	MOVLW	0xAA
	MOVWF	EEDATA		; marker
	CALL	DPROG

SETEXIT
	BCF	FSR,5

;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

; calc CV17/CV18 ....................................................
;             ___
; 10AA AAAA  1AAA CDDD -> 9 Bit Accessory on/off F1-F8 
;   87 6543   BA9  210
; 11AA AAAA  AAAA AAAA -> long Adress
;      BA98  7654 3210

	BSF	FSR,5		;  ___
	MOVF	CV546,0		; 1AAA CDDD
	BCF	FSR,5		;  ___
	MOVWF	CV17		; 1AAA CDDD
	ANDLW	00000111b	;
	MOVWF	CV18		; oooo oDDD
	SWAPF	CV17,1		;      ___
	RLF	CV17,1		; DDD1 AAAx
	COMF	CV17,0		;
	ANDLW	00001110b	; oooo AAAo
	IORLW	11000000b	; 11oo BA9o
	MOVWF	CV17		;

	BSF	FSR,5
	MOVF	CV545,0		; GP0 high
	BCF	FSR,5		;

	MOVWF	PRE		; 10AA AAAA
	BTFSC	PRE,5		; xx8x xxxx
	BSF	CV17,0		; 11oo BA98
	DECF	PRE,1
	RLF	PRE,1		; 0AAA AAAx
	RLF	PRE,1		; AAAA AAx
	RLF	PRE,0		; AAAA Axxx
	ANDLW	11111000b	; 7654 3ooo
	IORWF	CV18		; 7654 3210

	INCF	CV18,1		;
	INCF	CV18,1		;

	MOVF	CV18,0		;
	MOVWF	CV1		;
	BCF	CV1,7		;

	MOVF	CV17,0		;
	ANDLW	00111111b	;
	BTFSS	STATUS,ZERO	;
	CLRF	CV1		;

; complete adress with F1-F8 calculated for GP0
; 511*8(NMRA) or 2044*2(IB)
; programming on main over adress of GP0 possible (adress = 9 adr. bits + 3 bits from f1-f8)
;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

;SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS

START	CLRWDT			;				11

	MOVLW	0xFF		;				12
	MOVWF	BT4		;				13
	MOVWF	BT5		;				14
	MOVWF	BT6		;				15

	MOVLW	0x09		; Pointer for ind. Adressing	16
	MOVWF	FSR		; (BT1 - 1)			17

	MOVLW	11		;				18
	MOVWF	PRE		; PRE to 10 Bit for Preample	19
;-------------
INTEST	CLRF	HI		;				20
INTST	BCF	STEPOK?		;				21
	NOP			;				22
	CALL	IN		;				23-24
	BTFSC	STEPOK?		;				4.
	GOTO	STEPOK		;				5.-6
	CALL	STEP		;				6.-7.
	BTFSC	GPIO,DCCIN	; ########### input ##########	1  (25)
	BSF	BITHI		;				2
	GOTO	$+1		;				3-4
	GOTO	$+1		;				5-6

STEPOK	MOVLW	11111100b	; FF-03				7
	MOVF	HI,1		;				8
	BTFSC	STATUS,ZERO	; 0? 				9
	GOTO	LOWBIT		; low half of bit		10-11
	ADDWF	HI,0		; BIT im Carry			11
	DECFSZ	PRE,1		; Pre=0?			12
	GOTO	PRETEST		;				13-14
	BTFSC	STATUS,CARRY	; waiting for 0			14
	GOTO	BYTE		; Preample ok!			15-16
	INCF	PRE,1		;				16
	NOP			;				17
	GOTO	INTEST		; next Bit			18-19

PRETEST	DECFSZ	HI,0		; HI=1?				15
	BTFSC	STATUS,CARRY	;				16
	GOTO	START20		; no Preample!			17-18
	GOTO	INTEST		;				18-19

LOWBIT	NOP			;				12
	GOTO	$+1		;				13-14
	BTFSC	BITHI		;				15
	INCF	HI		;				16
	BCF	BITHI		;				17
	INCFSZ	LO,1		;				18
	GOTO	INTST		;				19-20
	GOTO	BEGIN		; >10000uS			20-21

;....................................................................
DPROG	CLRWDT			;
	BSF	STATUS,SEITE	; set to 200H begin EEPROM
	CALL	WRITE_BYTE	;
	BCF	STATUS,SEITE	;
	BTFSS	PC_OFFSET,EE_OK ; ERROR?
	GOTO	DPROG
	RETLW	0
;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
IN	BTFSS	GPIO,DCCIN	; ########### input ##########	1  (25)
	RETLW	0		; 				2.-3.
	INCF	HI		;				3.
	CLRF	LO		;				4.
	BSF	STEPOK?		;				5.
	CALL	STEP		;				6.-7.
	BTFSS	GPIO,DCCIN	; ########### input ##########	1  (25)
	RETLW	0		; FF-03				2-3
	INCF	HI		;				3
	NOP			;				4
	GOTO	$+1		;				5-6
	GOTO	$+1		;				7-8
;--------------------------------
	BSF	FSR,5		;				9
	MOVF	CV515,1		; time on GP0			10
	BCF	FSR,5		;				11
	BTFSC	STATUS,ZERO	; is zero?			12
	CLRF	GP0TON		; clear for constant output	13
	BSF	FSR,5		;				14
	MOVF	CV518,1		; time on GP4			15
	BCF	FSR,5		;				16
	BTFSC	STATUS,ZERO	; is zero?			17
	CLRF	GP4TON		; clear for constant output	18
	BTFSC	STATUS,ZERO	; is zero?			19
	CLRF	GP5TON		; clear for constant output	20
;--------------------------------
	BCF	STEPOK?		;				21
	INCFSZ	HI,0		;				22
	GOTO	IN		;				23-24
	GOTO	BEGIN		; >10000uS			24-25
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

;....................................................................
STEP	INCFSZ	tmr0,0		; ISO				8.
	GOTO	TMREX		;				9.-10.
	DECFSZ	Z1		;				10.
	GOTO	TMREX1		;				11.-12.

	MOVLW	LTIMER		;				12.
	MOVWF	Z1		;				13.

	DECFSZ	GP0TON		;				14.
	GOTO	GP0TIME		;				15.-16.
	BCF	GPIO,0		;				16.

GP0TIME	DECFSZ	GP1TON		;				17.
	GOTO	GP1TIME		;				18.-19.
	BCF	GPIO,1		;				19.

GP1TIME	DECFSZ	GP2TON		;				20.
	GOTO	GP2TIME		;				21.-22.
	BCF	GPIO,2		;				22.

GP2TIME	DECFSZ	GP4TON		;				23.
	GOTO	GP4TIME		;				24.-25.
	BCF	GPIO,4		;				25.

GP4TIME	DECFSZ	GP5TON		;				26.
	GOTO	GP5TIME		;				27.-28.
	BCF	GPIO,5		;				28.

GP5TIME	RETLW	0		;				29.-30.

;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

;....................................................................
PGP	MOVF	PRGBITS,0	;
	ANDLW	00110111b	;
	BTFSS	STATUS,ZERO	;
	RETLW	0		;

	BTFSC	PROGBIT		;
	GOTO	PGP3		;
	BSF	PROGBIT		; 2x prog
	RETLW	0		;

PGP3	BTFSC	PROGBT1		;
	GOTO	PGP4		;
	BSF	PROGBT1		; 3x prog
	RETLW	0		;

PGP4	MOVF	BT1,0		;
	MOVWF	INDF		; low byte copy indirect to ram
	MOVWF	EEDATA		; low byte
	MOVF	FSR,0		;
	ANDLW	00001111b	;
	MOVWF	EEADDR		;

	CALL	DPROG

	MOVLW	5		;
	ADDWF	FSR,1		; 
	MOVF	BT2,0		;
	MOVWF	INDF		; high byte copy indirect to ram

	MOVWF	EEDATA		; high byte
	MOVF	FSR,0		;
	ANDLW	00001111b	;
	MOVWF	EEADDR		;

	CALL	DPROG

	MOVLW	5+CV545		;
	SUBWF	FSR,1		; 
	MOVLW	00000111b	;
	ANDWF	FSR,0		;
	ADDWF	PC		;
	RETLW	00000001b	; 0	
	RETLW	00000010b	; 1	
	RETLW	00000100b	; 2	
	RETLW	00010000b	; 4	
	RETLW	00100000b	; 5	
	RETLW	0		;
	RETLW	0		;
	RETLW	0		;
;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

;....................................................................
TMREX	GOTO	$+1		;				11.-12.
TMREX1	BSF	FSR,5		;				13.
	MOVF	CV516,1		; time on GP1			14.
	BCF	FSR,5		;				15.
	BTFSC	STATUS,ZERO	; is zero?			16.
	CLRF	GP1TON		; clear for constant output	17.
	BSF	FSR,5		;				18.
	MOVF	CV517,1		; time on GP2			19.
	BCF	FSR,5		;				20.
	BTFSC	STATUS,ZERO	; is zero?			21.
	CLRF	GP2TON		; clear for constant output	22.
	RETLW	0		;				23.-24.
;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^


LOWBIT1	MOVLW	0x10		; -----------------------------	12
	SUBWF	FSR,0		;				13
	ANDLW	00000111b	; more than 6 BYTE read		14
	BTFSC	STATUS,ZERO	; begin new!			15
	GOTO	START18		; -----------------------------	16-17
	BTFSC	BITHI		;				17
	INCF	HI		;				18
	GOTO	INTST1		;				19-20

BYTE	MOVLW	9		; PRE to 8 Bit for 1.Byte	17
	MOVWF	PRE		;				18
	INCF	FSR,1		; Pointer for ind. Adressing	19

INTEST1	CLRF	HI		;				20
INTST1	BCF	STEPOK?		;				21
	BCF	BITHI		;				22
	CALL	IN		;				23-24
	BTFSC	STEPOK?		;				4.
	GOTO	STEPOK1		;				5.-6
	CALL	STEP		;				6.-7.
	BTFSC	GPIO,DCCIN	; ########### input ##########	1  (25)
	BSF	BITHI		;				2

	GOTO	$+1		;				3-4
	GOTO	$+1		;				5-6

STEPOK1	MOVLW	11111100b	; FF-03				7
	MOVF	HI,1		;				8
	BTFSC	STATUS,ZERO	; 0? 				9
	GOTO	LOWBIT1		; low half of bit		10-11
	ADDWF	HI,0		; BIT im Carry			11
	DECFSZ	PRE,1		; Pre=0?			12
	GOTO	NEXT		;				13-14
	BTFSC	STATUS,CARRY	;				14
	GOTO	BYTE		; 9.Bit=0			15-16
;------------- Letztes BIT=1 -------------

	CLRF	NOADR		; for IB with M*

	MOVF	BT1,0		;				17
	XORWF	BT2,0		;				18
	XORWF	BT3,0		;				19
	XORWF	BT4,0		;				20
	XORWF	BT5,0		;				21
	XORWF	BT6,0		;				22
	BTFSS	STATUS,ZERO	; all Bytes ok?			23
	GOTO	START2.		;				24-1.
	COMF	BT1,1		; 9.Bit=1  (inverting BYTE)	1.
	COMF	BT2,1		; 	   (inverting BYTE)	2.
	COMF	BT3,1		; 	   (inverting BYTE)	3.
	COMF	BT4,1		; 	   (inverting BYTE)	4.
	COMF	BT5,1		; 	   (inverting BYTE)	5.
	CALL	STEP		;				6.-7.
	DECF	FSR,1		; auf vorletztes Byte		1

;....................................................................
; 10AA AAAA  1AAA CDDD -> 9 Bit Accessory on/off F1-F8 
; 1011 1111  1000 CDDD -> Broadcast Command for all Accessory Decoder
;--------------------------------
CV	BCF	FSR,5		; rampage to 0x10..		2
	MOVF	BT1,0		;				3
	BTFSS	BT1,7		; >0<AAA AAAA			4
	GOTO	SHORTA		; short adress			5-6
	XORWF	CV17,0		;				6
	BTFSS	STATUS,ZERO	;				7
	GOTO	CHKPORT		;				8-9
	MOVF	BT2,0		;				9
	XORWF	CV18,0		;				10
	BTFSS	STATUS,ZERO	;				11
	GOTO	CHKPORT		;				12-13
	MOVLW	0x2C		; BT3				13
	MOVWF	FSR		; to 3. byte			14
	BSF	FSR,5		; rampage to 0x30..		15
	BSF	STATUS,SEITE	;				16
	GOTO	DECOD		;				17-18
;====================================================================
CHKPORT	BSF	FSR,5		; 10AA AAAA  1AAA CDDD -> 9 Bit Accessory on/off F1-F8 
	BTFSS	BT1,6		; 1>0<AA AAAA  1AAA CDDD 1=exit
	BTFSS	BT1,7		; >1<0AA AAAA  1AAA CDDD 0=exit
	GOTO	EXCKPT		; no accessory command 
	BTFSS	BT2,7		; >1<0AA AAAA  1AAA CDDD 0=exit
	GOTO	EXCKPT		; no accessory command

	MOVF	GPIO,0		;
	ANDLW	00110111b	;
	BTFSS	STATUS,ZERO	;
	GOTO	EXCKPT		; wait until port is set

	MOVLW	00111111b	; all input
	TRIS	GPIO		; set port GPIO

	MOVLW	CV545		;
	MOVWF	FSR		; cv545
	CLRW			;

	BTFSC	GPIO,0		;
	CALL	PGP		;
	BTFSS	GPIO,0		; release
	BCF	PRG_GP0		;

	INCF	FSR,1		; cv548
	BTFSC	GPIO,1		;
	CALL	PGP		;
	BTFSS	GPIO,1		; release
	BCF	PRG_GP1		;

	INCF	FSR,1		; cv551
	BTFSC	GPIO,2		; set
	CALL	PGP		;
	BTFSS	GPIO,2		; release
	BCF	PRG_GP2		;

	INCF	FSR,1		; cv554
	BTFSC	GPIO,4		;
	CALL	PGP		;
	BTFSS	GPIO,4		; release
	BCF	PRG_GP4		;

	INCF	FSR,1		; cv557
	BTFSC	GPIO,5		;
	CALL	PGP		;
	BTFSS	GPIO,5		; release
	BCF	PRG_GP5		;

	IORWF	PRGBITS		; set progbits

EXCKPT	MOVLW	(1<<DCCIN)	; GP3 input, rest output
	TRIS	GPIO		; set port GPIO
	BSF	STATUS,SEITE	;
	GOTO	GP0		;
;====================================================================
SHORTA	XORWF	CV1,0		;				7
	BTFSS	STATUS,ZERO	;				8
	GOTO	START		;				9-10
	MOVLW	0x2B		; BT2 + FSR,5			11
	MOVWF	FSR		; to 2. byte			12
	BSF	STATUS,SEITE	;				13
	GOTO	DECOD		;				14-15
;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

;....................................................................
NEXT	NOP			;				15
	RLF	INDF,1		; 1.Byte zusammenbauen		16
	DECFSZ	HI,0		; HI=1?				17
	GOTO	INTEST1		; next bit			18-19
	GOTO	START21		;				19-20
;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

;.....................................................................
START1.	NOP			;				1.
START2.	GOTO	$+1		;*				2.-3.
START4.	GOTO	$+1		;				4.-5.
START6.	CALL	STEP		;				6.-7.
START1	GOTO	$+1		;				1-2
START3	GOTO	$+1		;				3-4
START5	GOTO	$+1		;				5-6
START7	GOTO	$+1		;				7-8
START9	NOP			;				9
START10	GOTO	START		;				10-11
START11	GOTO	$+1		;				11-12
START13	GOTO	$+1		;				13-14
START15	GOTO	$+1		;				15-16
START17	NOP			;				17
START18	NOP			;*				18
;--------------------------------------------------------------------
START19	INCF	NOADR		; for IB with M*		19
START20	BTFSS	NOADR,7		; counts if no			20
START21	GOTO	START23		; DCC signal is 		21
	GOTO	INIT		; readable			22
;--------------------------------------------------------------------
START23	GOTO	START1.		;				23-24
;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

;*******************************************************************

	ORG	0200h

	TITLE "PIC with EEPROM Data Memory Interface"
	LIST	P=12CE519

SCL	EQU	0x07		; EEPROM Clock, SCL (I/O bit 7)
SDA	EQU	0x06		; EEPROM Data,  SDA (I/O bit 6)

OK	EQU	1
NO	EQU	0
EE_OK	EQU	7		; Bit 7 in PC_OFFSET used as OK flag for EE

PC_OFFSET	EQU	0x30	; PC offset register (low order 4 bits),
				; value based on operating mode of EEPROM.
				; Also, bit 7 used for EE_OK flag
COUNTER		EQU	0x08	; Bit counter for serial transfer
EEBYTE		EQU	0x09	; Byte sent to or received from
				; EEPROM (control, address, or data)
EEADDR		EQU	0x0A	; EEPROM Address
EEDATA		EQU	0x0F	; EEPROM Data

;********************** Set up EEPROM control bytes ************************

WRITE_BYTE
	MOVLW	B'10000000'	; PC offset for write byte. EE_OK: bit7 = '1'
	GOTO	INIT_WRITE_CONTROL

READ_RANDOM
	MOVLW	B'10000011'	; PC offset for read random. EE_OK: bit7 = '1'

INIT_WRITE_CONTROL
	MOVWF	PC_OFFSET	; Load PC offset register, value preset in W
	MOVLW	B'10100000'	; Control byte with write bit, bit 0 = '0'

START_BIT
	BCF	GPIO,SDA	; Start bit, SDA and SCL preset to '1'

;******* Set up output data (control, address, or data) and counter ********

PREP_TRANSFER_BYTE
	MOVWF	EEBYTE		; Byte to transfer to EEPROM already in W
	MOVLW	8		; Counter to transfer 8 bits
	MOVWF	COUNTER

;************ Clock out data (control, address, or data) byte ************

OUTPUT_BYTE
	BCF	GPIO,SCL	; Set clock low during data set-up
	RLF	EEBYTE,1	; Rotate left, high order bit into carry bit
	BCF	GPIO,SDA	; Set data low, if rotated carry bit is
	BTFSC	STATUS,CARRY	;(SKPNC) a '1', then:
	BSF	GPIO,SDA	; reset data pin to a one, otherwise leave low
	NOP
	BSF	GPIO,SCL	; clock data into EEPROM
	DECFSZ	COUNTER,1	; Repeat until entire byte is sent
	GOTO	OUTPUT_BYTE
	NOP			; Needed to meet Timing (Thigh=4000nS)

;************************** Acknowkedge Check *****************************

	BCF	GPIO,SCL	; Set SCL low, 0.5us < ack valid < 3us
	NOP			; Needed to meet Timing (Tlow= 4700nS)
	BSF	GPIO,SDA
	NOP			; Necessary for SCL Tlow at low voltage,
	NOP			; Tlow=4700nS
	BSF	GPIO,SCL	; Raise SCL, EEPROM acknowledge still valid
	BTFSC	GPIO,SDA	; Check SDA for acknowledge (low)
	BCF	PC_OFFSET,EE_OK	; If SDA not low (no ack), set error flag
	BCF	GPIO,SCL	; Lower SCL, EEPROM release bus
	BTFSS	PC_OFFSET,EE_OK	; If no error continue, else stop bit
	GOTO	STOP_BIT

;***** Set up program counter offset, based on EEPROM operating mode *****

	MOVF	PC_OFFSET,0
	ANDLW	B'00001111'
	ADDWF	PC
	GOTO	INIT_ADDRESS		;PC offset=0, write control done, send address
	GOTO	INIT_WRITE_DATA		;PC offset=1, write address done, send data
	GOTO	STOP_BIT		;PC offset=2, write done, send stop bit
	GOTO	INIT_ADDRESS		;PC offset=3, write control done, send address
	GOTO	INIT_READ_CONTROL	;PC offset=4, send read control
	GOTO	READ_BIT_COUNTER	;PC offset=5, set counter and read byte
	GOTO	STOP_BIT		;PC offset=6, random read done, send stop

;********** Initalize EEPROM data (address, data, or control) bytes ******

INIT_ADDRESS
	INCF	PC_OFFSET,1	; Increment PC offset to 2 (write) or to 4 (read)
	MOVF	EEADDR,W	; Put EEPROM address in W, ready to send to EEPROM
	GOTO	PREP_TRANSFER_BYTE

INIT_WRITE_DATA
	INCF	PC_OFFSET,1	; Increment PC offset to go to STOP_BIT next
	MOVF	EEDATA,0	; Put EEPROM data in W, ready to send to EEPROM
	GOTO	PREP_TRANSFER_BYTE

INIT_READ_CONTROL
	BSF	GPIO,SCL	; Raise SCL
	NOP
	BSF	GPIO,SDA	; raise SDA
	INCF	PC_OFFSET,1	; Increment PC offset to go to READ_BIT_COUNTER next
	MOVLW	B'10100001'	; Set up read control byte, ready to send to EEPROM
	GOTO	START_BIT	; bit 0 = '1' for read operation

;************************** Read EEPROM data *****************************

READ_BIT_COUNTER
	BSF	GPIO,SDA	; set data bit to 1 so we're not pulling bus down.
	NOP
	BSF	GPIO,SCL
	MOVLW	8		; Set counter so 8 bits will be read into EEDATA
	MOVWF	COUNTER

READ_BYTE
	BSF	GPIO,SCL	; Raise SCL, SDA valid. SDA still input from ack
	BSF	STATUS,CARRY	;(SETC) Assume bit to be read = 1
	BTFSS	GPIO,SDA	; Check if SDA = 1
	BCF	STATUS,CARRY	;(CLRC) if SDA not = 1 then clear carry bit
	RLF	EEDATA,1	; rotate carry bit (=SDA) into EEDATA;
	BCF	GPIO,SCL	; Lower SCL
	bsf	GPIO,SDA	; reset SDA
	DECFSZ	COUNTER,1	; Decrement counter
	GOTO	READ_BYTE	; Read next bit if not finished reading byte
	BSF	GPIO,SCL
	NOP
	BCF	GPIO,SCL

;****************** Generate a STOP bit and RETURN ***********************

STOP_BIT
	BCF	GPIO,SDA	; SDA=0, on TRIS, to prepare for transition to '1'
	BSF	GPIO,SCL	; SCL = 1 to prepare for STOP bit
	GOTO	$+1		; equivalent 4 NOPs neccessary for I2C spec Tsu:sto = 4.7us
	GOTO	$+1
	BSF	GPIO,SDA	; Stop bit, SDA transition to '1' while SCL high
	BTFSS	PC_OFFSET,EE_OK ; Check for error
	RETLW	NO		; if error, send back NO
	RETLW	OK		; if no error, send back OK

;************************ End EEPROM Subroutines **************************
;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

;.....................................................................
GP0	MOVF	BT1,0		;
	XORWF	CV545,0		; GP0 low
	BTFSS	STATUS,ZERO	;
	GOTO	GP1		;
	MOVF	BT2,0		; 1AAA CDDD
	XORWF	CV546,0		; GP0 hi
	BTFSS	STATUS,ZERO	;
	GOTO	GP1		;
	MOVF	CV547,0		; time on GP0
	BCF	FSR,5		;
	MOVWF	GP0TON		;
	BSF	FSR,5		;
	BSF	GPIO,0		;
	BCF	GPIO,1		; Jaroslav
	BCF	GPIO,2		; Jaroslav
;--------------------------------
GP1	MOVF	BT1,0		;
	XORWF	CV548,0		; GP1 low
	BTFSS	STATUS,ZERO	;
	GOTO	GP2		;
	MOVF	BT2,0		; 1AAA CDDD
	XORWF	CV549,0		; GP1 hi
	BTFSS	STATUS,ZERO	;
	GOTO	GP2		;
	MOVF	CV550,0		; time on GP1
	BCF	FSR,5		;
	MOVWF	GP1TON		;
	BSF	FSR,5		;
	BSF	GPIO,1		;
	BCF	GPIO,0		; Jaroslav
	BCF	GPIO,2		; Jaroslav
;--------------------------------
GP2	MOVF	BT1,0		;
	XORWF	CV551,0		; GP2 low
	BTFSS	STATUS,ZERO	;
	GOTO	GP4		;
	MOVF	BT2,0		; 1AAA CDDD
	XORWF	CV552,0		; GP2 hi
	BTFSS	STATUS,ZERO	;
	GOTO	GP4		;
	MOVF	CV553,0		; time on GP2
	BCF	FSR,5		;
	MOVWF	GP2TON		;
	BSF	FSR,5		;
	BSF	GPIO,2		;
	BCF	GPIO,0		; Jaroslav
	BCF	GPIO,1		; Jaroslav
;--------------------------------
GP4	MOVF	BT1,0		;
	XORWF	CV554,0		; GP4 low
	BTFSS	STATUS,ZERO	;
	GOTO	GP5		;
	MOVF	BT2,0		; 1AAA CDDD
	XORWF	CV555,0		; GP4 hi
	BTFSS	STATUS,ZERO	;
	GOTO	GP5		;
	MOVF	CV556,0		; time on GP4
	BCF	FSR,5		;
	MOVWF	GP4TON		;
	BSF	FSR,5		;
	BSF	GPIO,4		;
	BCF	GPIO,5		; Jaroslav
;--------------------------------
GP5	MOVF	BT1,0		;
	XORWF	CV557,0		; GP5 low
	BTFSS	STATUS,ZERO	;
	GOTO	CHKPROG		;
	MOVF	BT2,0		; 1AAA CDDD
	XORWF	CV558,0		; GP5 hi
	BTFSS	STATUS,ZERO	;
	GOTO	CHKPROG		;
	MOVF	CV559,0		; time on GP5
	BCF	FSR,5		;
	MOVWF	GP5TON		;
	BSF	FSR,5		;
	BSF	GPIO,5		;
	BCF	GPIO,4		; Jaroslav
;--------------------------------
CHKPROG	MOVF	BT1,0		;
	ANDLW	11110000b	; untere 3bit ausblenden
	XORLW	01110000b	; >= 120 (120=CV1 121=CV2 ...)
	BTFSS	STATUS,ZERO	;
	GOTO	PROGEX		;
	GOTO	PROG		; register mode (CV1-CV8)
;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
;
; 0111 1RRR  DDDD DDDD  ->  register mode
;
; 0111 10AA  AAAA AAAA  111K DBBB ; Bit manipulation
;              verify/write^
;
;.....................................................................
DECOD	SWAPF	INDF,0		;
	MOVWF	BT6		;
	RRF	BT6,0		;
	ANDLW	00000111b	;
	ADDWF	PC		;
	GOTO	DECCON		; 000
	GOTO	ADVAN		; 001
	GOTO	FORWARD		; 010
	GOTO	REVERSE		; 011
	GOTO	FTION		; 100
	GOTO	FTION1		; 101
	GOTO	TELNEW		; 110

	MOVF	BT2,0		;--------------------------------
	XORLW	11111001b	; old acknowledge mode
	BTFSC	STATUS,ZERO	;
	GOTO	ACKNOW		;--------------------------------

	MOVF	INDF,0		; OTM mode -copy bytes
	MOVWF	BT1		; 
	INCF	FSR,1		; 
	MOVF	INDF,0		; CV to pogram
	MOVWF	BT2		;
	INCF	FSR,1		; DATA for cv
	MOVF	INDF,0		; INDF looks to data
	MOVWF	BT3		;
	GOTO	PROGOTM		; 111
;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

;.....................................................................
BITMAN	MOVWF	FSR		;
	MOVLW	00000111b	;
	ANDWF	BT3,0		;
	CALL	BITPOS		;
	BTFSS	BT3,4		;
	GOTO	VBIT		; verify bit
	BTFSC	BT3,3		;
	IORWF	INDF,1		; set bit
	XORLW	0XFF		;
	BTFSS	BT3,3		;
	ANDWF	INDF,1		; clear bit
	MOVF	FSR,0		; EEADDR
	GOTO	EEPROG		; write complete byte
;--------------------------------
VBIT	ANDWF	INDF,0		;
	BTFSC	STATUS,ZERO	;
	GOTO	BITCLR		;

BITSET	BTFSC	BT3,3		;
	GOTO	ACKNOW		; =1 
	GOTO	HOPP		;

BITCLR	BTFSS	BT3,3		;
	GOTO	ACKNOW		; =0
	GOTO	HOPP		;
;--------------------------------
BITPOS	ADDWF	PC		;
	RETLW	00000001b	; 0	
	RETLW	00000010b	; 1	
	RETLW	00000100b	; 2	
	RETLW	00001000b	; 3	
	RETLW	00010000b	; 4	
	RETLW	00100000b	; 5	
	RETLW	01000000b	; 6	
	RETLW	10000000b	; 7	
;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

;....................................................................
FINDCV	BCF	NOCV			;
	BCF	ROMCV			;

	XORLW	(00100000b)		; CV545
	BTFSC	STATUS,ZERO		;
	RETLW	CV545			; GP0 low

	XORLW	(00100000b)^(00100001b)	; CV546
	BTFSC	STATUS,ZERO		;
	RETLW	CV546			; GP0 hi

	XORLW	(00100001b)^(00100010b)	; CV547
	BTFSC	STATUS,ZERO		;
	RETLW	CV547			; Time On GP0 

	XORLW	(00100010b)^(00100011b)	; CV548
	BTFSC	STATUS,ZERO		;
	RETLW	CV548			; GP1 low

	XORLW	(00100011b)^(00100100b)	; CV549
	BTFSC	STATUS,ZERO		;
	RETLW	CV549			; GP1 hi

	XORLW	(00100100b)^(00100101b)	; CV550
	BTFSC	STATUS,ZERO		;
	RETLW	CV550			; Time On GP1

	XORLW	(00100101b)^(00100110b)	; CV551
	BTFSC	STATUS,ZERO		;
	RETLW	CV551			; GP2 low

	XORLW	(00100110b)^(00100111b)	; CV552
	BTFSC	STATUS,ZERO		;
	RETLW	CV552			; GP2 hi

	XORLW	(00100111b)^(00101000b)	; CV553
	BTFSC	STATUS,ZERO		;
	RETLW	CV553			; Time On GP2

	XORLW	(00101000b)^(00101001b)	; CV554
	BTFSC	STATUS,ZERO		;
	RETLW	CV554			; GP4 low

	XORLW	(00101001b)^(00101010b)	; CV555
	BTFSC	STATUS,ZERO		;
	RETLW	CV555			; GP4 hi

	XORLW	(00101010b)^(00101011b)	; CV556
	BTFSC	STATUS,ZERO		;
	RETLW	CV556			; Time On GP4

	XORLW	(00101011b)^(00101100b)	; CV557
	BTFSC	STATUS,ZERO		;
	RETLW	CV557			; GP5 low

	XORLW	(00101100b)^(00101101b)	; CV558
	BTFSC	STATUS,ZERO		;
	RETLW	CV558			; GP5 hi

	XORLW	(00101101b)^(00101110b)	; CV559
	BTFSC	STATUS,ZERO		;
	RETLW	CV559			; Time On GP5

	XORLW	(00101110b)^(00000000b)	; CV513
	BTFSC	STATUS,ZERO		;
	RETLW	CV513			; Decoder Address (LSB)

	XORLW	(00000000b)^(00001000b)	; CV521
	BTFSC	STATUS,ZERO		;
	RETLW	CV521			; Decoder Address (MSB)

	XORLW	(00001000b)^(00000010b)	; CV515
	BTFSC	STATUS,ZERO		;
	RETLW	CV515			; Time On GP0

	XORLW	(00000010b)^(00000011b)	; CV516
	BTFSC	STATUS,ZERO		;
	RETLW	CV516			; Time On GP1

	XORLW	(00000011b)^(00000100b)	; CV517
	BTFSC	STATUS,ZERO		;
	RETLW	CV517			; Time On GP2

	XORLW	(00000100b)^(00000101b)	; CV518
	BTFSC	STATUS,ZERO		;
	RETLW	CV518			; Time On GP4

	BSF	ROMCV			;
	XORLW	(00000101b)^(00000110b)	; CV519
	BTFSC	STATUS,ZERO		;
	RETLW	CV519			; Version No

	XORLW	(00000110b)^(00000111b)	; CV520
	BTFSC	STATUS,ZERO		;
	RETLW	CV520			; Manufacturer

	BCF	ROMCV			;
	BSF	NOCV			;
	RETLW	0xFF			; no CV's to program
;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

;....................................................................
PROG	MOVF	FSR,0		;
	ANDLW	00001111b	;
	XORLW	BT3		;
	BTFSS	STATUS,ZERO	;
	GOTO	PROGREG		; 3 byte command

PROGOTM	MOVF	BT2,0		;
	CALL	FINDCV		;
	BTFSC	NOCV		;
	GOTO	HOPP		;
				;
	BTFSS	BT1,0		; 0xxxxxA>A< 1=exit
	BTFSS	BT1,1		; 0xxxxx>A<A 0=exit
	GOTO	HOPP		; 0xxxxx10 ok cv>511

	BTFSC	ROMCV		;
	BTFSS	BT1,3		; write/verify bit
	GOTO	ROMNEXT		;
	MOVWF	MAPCV		;
	MOVLW	MAPCV		;

ROMNEXT	BTFSS	BT1,2		;
	GOTO	BITMAN		; bit manipulation

	BTFSS	BT1,3		; write/verify bit
	GOTO	EEVERI		;
;--------------------------------
EEPROG	ANDLW	00001111b	;
	MOVWF	EEADDR		;
READ	CALL	READ_RANDOM	; *******************************
	BTFSS	PC_OFFSET,EE_OK ;(BTFSC STATUS,ZERO) ERROR?
	GOTO	READ
	CLRF	CONFIG
	MOVF	INDF,0		;
	XORWF	EEDATA,0	;

	BTFSC	STATUS,ZERO	;
	BCF	STATUS,SEITE	; auf ROM seite 0
	BTFSC	STATUS,ZERO	;
	GOTO	LOADREG		;

	MOVF	INDF,0		;
	MOVWF	EEDATA		;

	BTFSC	PROGBIT		;
	GOTO	PROG3		;
	BSF	PROGBIT		; 2x prog
	GOTO	PROGEX		;

PROG3	BTFSC	PROGBT1		;
	GOTO	EEIN		;
	BSF	PROGBT1		; 3x prog
	GOTO	PROGEX		;

EEIN	CALL	WRITE_BYTE	; ********************************
	BTFSS	PC_OFFSET,EE_OK ;(BTFSC STATUS,ZERO) ERROR?
	GOTO	EEIN		;
	CLRF	CONFIG
	BCF	STATUS,SEITE	; auf ROM seite 0
	BCF	PROGBIT		;
	BCF	PROGBT1		;

	MOVF	EEADDR,0		;

;CV547	EQU	0x31	; Time On GP0	0001	1
;CV550	EQU	0x32	; Time On GP1	0010	2
;CV553	EQU	0x33	; Time On GP2	0011	3
;CV556	EQU	0x34	; Time On GP4	0100	4
;CV559	EQU	0x35	; Time On GP5	0101	5
	XORLW	(00000001b)		; CV547 Time On GP0
	BTFSC	STATUS,ZERO		;
	BSF	GPIO,0			;
	XORLW	(00000001b)^(00000010b)	; CV550 Time On GP1
	BTFSC	STATUS,ZERO		;
	BSF	GPIO,1			;
	XORLW	(00000010b)^(00000011b)	; CV553 Time On GP2
	BTFSC	STATUS,ZERO		;
	BSF	GPIO,2			;
	XORLW	(00000011b)^(00000100b)	; CV556 Time On GP4
	BTFSC	STATUS,ZERO		;
	BSF	GPIO,4			;
	XORLW	(00000100b)^(00000101b)	; CV559 Time On GP5
	BTFSC	STATUS,ZERO		;
	BSF	GPIO,5			;

;CV545	EQU	0x36	; GP0 low	0110	6
;CV548	EQU	0x37	; GP1 low	0111	7
;CV551	EQU	0x38	; GP2 low	1000	8
;CV554	EQU	0x39	; GP4 low	1001	9
;CV557	EQU	0x3A	; GP5 low	1010	10
	XORLW	(00000101b)^(00000110b)	; CV545 GP0 low
	BTFSC	STATUS,ZERO		;
	BSF	GPIO,0			;
	XORLW	(00000110b)^(00000111b)	; CV548 GP1 low
	BTFSC	STATUS,ZERO		;
	BSF	GPIO,1			;
	XORLW	(00000111b)^(00001000b)	; CV551 GP2 low
	BTFSC	STATUS,ZERO		;
	BSF	GPIO,2			;
	XORLW	(00001000b)^(00001001b)	; CV554 GP4 low
	BTFSC	STATUS,ZERO		;
	BSF	GPIO,4			;
	XORLW	(00001001b)^(00001010b)	; CV557 GP5 low
	BTFSC	STATUS,ZERO		;
	BSF	GPIO,5			;

;CV546	EQU	0x3B	; GP0 high	1011	11
;CV549	EQU	0x3C	; GP1 high	1100	12
;CV552	EQU	0x3D	; GP2 high	1101	13
;CV555	EQU	0x3E	; GP4 high	1110	14
;CV558	EQU	0x3F	; GP5 high	1111	15
	XORLW	(00001010b)^(00001011b)	; CV546 GP0 high
	BTFSC	STATUS,ZERO		;
	BSF	GPIO,0			;
	XORLW	(00001011b)^(00001100b)	; CV549 GP1 high
	BTFSC	STATUS,ZERO		;
	BSF	GPIO,1			;
	XORLW	(00001100b)^(00001101b)	; CV552 GP2 high
	BTFSC	STATUS,ZERO		;
	BSF	GPIO,2			;
	XORLW	(00001101b)^(00001110b)	; CV555 GP4 high
	BTFSC	STATUS,ZERO		;
	BSF	GPIO,4			;
	XORLW	(00001110b)^(00001111b)	; CV558 GP5 high
	BTFSC	STATUS,ZERO		;
	BSF	GPIO,5			;

	MOVLW	MAPCV			; write in MAPCV value 0xAA
	MOVWF	EEADDR			;
	MOVLW	0xAA			;
	MOVWF	EEDATA			;

AA	CALL	WRITE_BYTE	; ********************************
	BTFSS	PC_OFFSET,EE_OK ;(BTFSC STATUS,ZERO) ERROR?
	GOTO	AA		;

	BCF	FSR,5		;
	BCF	STATUS,SEITE	; auf ROM seite 0
	GOTO	INIT		; 

;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

;....................................................................

OLDACK	MOVF	BT1,0		;------ for old DCC-Programmer ------
	MOVWF	INDF		; save loco adress
	CLRW			; CV1
	CLRF	MAPCV		; for old acknowledge
	GOTO	OACK		;

EEVERI	BTFSC	ROMCV		;
	GOTO	RDROMCV		;

	ANDLW	00001111b	;
OACK	MOVWF	EEADDR		;
	CALL	READ_RANDOM	; ********************************
	CLRF	CONFIG
	MOVF	INDF,0		;
	XORWF	EEDATA,0	;

VERIBK	BTFSS	STATUS,ZERO	;
	BCF	STATUS,SEITE	; auf ROM seite 0
	BTFSS	STATUS,ZERO	;
	GOTO	START		;

ACKNOW	BTFSC	ACKBIT		;
	GOTO	ACKNOW1		;
	BSF	ACKBIT		; 2x verify 
	GOTO	PROGEX		;

ACKNOW1	MOVLW	00110111b	; set all ports on
	MOVWF	GPIO		;

LOOP	MOVLW	9		; 7x765uS (5355) 4,5,6,7 ok; 8 9 10 IB
	MOVWF	BT5		;
OLOOP	CLRF	BT6		; help register
	CLRWDT
ILOOP	INCFSZ	BT6,1		; 765uS ON	1
	GOTO	ILOOP		;		2-3
	DECFSZ	BT5,1		;		
	GOTO	OLOOP		;		

	CLRF	GPIO		;
	BCF	ACKBIT		;
	BCF	FSR,5		;
	BCF	STATUS,SEITE	; auf ROM seite 0

	GOTO	START		;

RDROMCV	XORWF	INDF,0		;
	GOTO	VERIBK		;
;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

;....................................................................

PROGREG	MOVF	BT1,0		; CV5=CV29
	XORLW	01111101b	; reg6
	ANDLW	11110111b
	BTFSC	STATUS,ZERO	;
	GOTO	REG6		;
	XORLW	(01111101b)^(01111100b)	; reg5
	BTFSC	STATUS,ZERO	;
	GOTO	REG5		;
	MOVF	BT1,0		;
	ANDLW	00000111b	; lower 3bit
	ADDWF	MAPCV,0		;
	CALL	FINDCV		;
	BTFSC	NOCV		;
	GOTO	HOPP		;
PREG	BTFSS	BT1,3		;
	GOTO	EEVERI		;
	GOTO	EEPROG		;

REG6	DECF	BT2,1		;
	BCF	STATUS,CARRY	;
	RLF	BT2,1		;
	RLF	BT2,1		;

REG5	MOVF	BT1,0		;
	ANDLW	00000111b	; lower 3bit
	GOTO	PREG		;

;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

DECCON		; 000
ADVAN		; 001
FORWARD		; 010
REVERSE		; 011
FTION		; 100
FTION1		; 101
TELNEW		; 110

HOPP	BCF	PROGBIT		;
	BCF	PROGBT1		;
	BCF	ACKBIT		;
PROGEX	BCF	STATUS,SEITE	;
	BCF	FSR,5		;
	GOTO	START		;

;********************************************************************

	ORG	03FFh
	MOVLW	0x80		; for OSCCAL

	END

