	processor	16F84
	title	"dcc8g.asm	Issue 	1 Rev e	26/02/00"
;**********************************************************************************************
;
;	This program is for a  NMRA standard DCC 'Command Station'
;	Written by Mike Bolton,  (May 1999 - initial veresion)
;	No aspects of the program are copyright and it may be freely used
;	copied, modified or distributed in whole or part. Acknowledgement of the original
;	author would be appreciated. 
;
;	Hardware schematics and PCB layout are also freely available from the author
;	email bolton@fs1.with.man.ac.uk
;
;	The objective of this command station was to duplicate the ease and
;	operability of a conventional analog system while maintaining the 
;	advantages of DCC. Keeping the cost low and using standard parts were
;	also criteria. The system uses up to eight handsets giving a maximum of
;	eight locos at the same time. Each handset has a potentiometer for speed control
;	two, low cost thumbwheel switches for loco address selection (00 to 99), an on/off
;	switch for direction, four function pushbuttons (simple normally open PBs), an 
;	optional handset deactivate switch (same as unplugging the handset), and 
;	two jumpers (or switches) to select the speed mode. Again optional if only one 
;	speed mode is required. Switching off a handset (or unplugging it) sends an emergency
;	stop packet to its loco.
;
;	Speed modes are 14 step, 28 step or 128 step. In 28 step mode,
;	intermediate steps are filled in by adding a step on a 1 in 4, 2 in 4 or 3 in 4 packet
;	basis to create effectively 128 step control. This intermediate step mode can be selected
;	by a jumper on port_b,7. If b7 is lo, mode is standard 28 step. If hi (tied to b6), then
;	the intermediate step mode is selected. (there are jumper pads on the PCB for this)
;	Not all 28 step mode decoders were happy with the alternating packets, notably the Lenz
;	LE130 feedback decoder. In 14 step mode, bit 4 controls F0(FL).
;
;	Different handsets can be in different modes and modes can be changed whilst running.
;	
;	There is an address 00 analog function available on any one handset. This allows
;	control of a conventional (non DCC) loco by the 'stretched zeros' method. Not 
;	advised for ironless rotor motors (Escap, Faulhaber, Minimotor etc). In analog mode, the 
;	waveform is similar to a conventional PWM controller with a PRF of about 40Hz. This gives
;	excellent slow speed control but is a bit noisy.
;
;	The hardware is based on a PIC 16F84/10P microcontroller chip with an 8 channel
;	8 bit ADC (MAX 1112) and a 8 channel digital multiplexer 74HC151. The speed
;	information is sampled from the potentiometer voltage on each handset by the ADC.
;	Function and address information is read serially from the handsets using a clock
;	signal from the PIC. A 5 wire connection to the handsets is required.
; 
;	The program continually scans all handsets for information in rotation.  The
;	handset info. is read and 'parsed' during the packet preamble. If there is no 
;	handset on that channel or the address is 00, then an idle packet is sent. Function
;	packets are sent every 4th speed packet. 
;
;	On startup, all handsets are deactivated until or unless the speed control is at
;	zero. This avoids locos starting unexpectedly. Also, when a new address is dialled
;	on the thumbwheels, it will not become valid until the speed is turned to zero.
;	The 'old' loco remains under control until stopped, then the new one will start if
;	the address is available. If not, there is an audible alarm.  To change locos, select
;	address of new loco. Turn speed to zero. Current loco stops and new loco is selected 
;	if not in use otherwise alarm sounds, new loco is not selected and old one deselected.
;
;	System allows for upto 4 consists, each of upto 4 locos. Advanced consisting is
;	not used. The primary address of each loco in a consist is stored in EEPROM. 
;	If a consist address is selected (90 to 93), the speed and direction info. is sent
;	in successive packets to each loco in that consist. It is possible to have the same 
;	loco in more than one consist. Once in a consist, function data but not speed data 
;	can be sent to individual locos. Function data cannot be sent to all locos
;	in a consist from the 'consist' handset. 
;
;	A consist is selected as if it was an individual loco by dialling in the consist
;	address and turning the speed to zero. It is possible to use addresses 90 to 93 
;	for individual locos but only those addresses can be used for consists.
;
;	To set a loco into a consist, that loco must be 'active'. Hold in the consist button 
;	and then press a function button and release. Then release the consist button.
;	To 'de-consist' repeat the process. The addresses of the locos in each consist are 
;	stored in EEPROM so will be remembered when the system is powered off. F0 sets the 
;	loco on that handset to consist 90, F1 to 91 etc. If you have forgotten which locos
;	are in a consist, you can clear it by activating address 00 and putting this into the
;	consist. It will clear one loco at a time on a first in, first out basis. To completely
;	clear a consist, repeat with 00 four times. You cannot have an analog (00) loco in a 
;	consist.
;
;	The function buttons have a toggle action. Press for on, press again for off.
;
;	Zero stretching for analog control has 64 step resolution. A lookup table is used
;	to create a set of 16 straight line approximations for the non-linear curve.
;	This gives approximate correspondence between the speed setting and the mean DC level.
;
;	The system output is a 5v logic level DCC bit stream. A separate booster and 5v
;	power supply is required.
;
;	Summary
; 
;	8 channel 'command station' 
;	8 channel 8 bit ADC
;	17 bit serial data input per channel
;	14, 28 and 128 speed steps 
;	8 bit BCD address select (00 to 99 used)
;	4 function pushbuttons
;	1 consist set pushbutton
;	1 switch for direction
;	2 mode switches (4 modes)
;	analog speed on address zero
;	
;	
;	Filename	dcc8g.asm	 uses 16F84/10
;
;	Date	26/02/00	modified version of dcc8e
;				28 step mode has alternating
;				intermediate speeds to give
;				effectively 128 steps.
;		rev b		one extra preamble added
;		rev c		correction in 28 step mode
;		rev d		correction in kill2
;				mods to emergency stop
;		rev e		mode option for 28 step
;				
;	Program methodology.				
;				
;			
;	All time intervals are derived by polling the real time clock (RTCC)	
;	overflow flag. No interrupts or timing loops are used. This gives simple
;	but precise timing control and allows changes and mods. to be made without
;	affecting the timing. This method entails breaking the program up into sections
;	which take a relatively short time to execute - less than 58 microsecs. 
;	At the end of each section, the w register is loaded with a jump value pointing
;	to the next section to be executed. The RTCC is polled for overflow, reset and a
;	programmed jump is executed via the main 'goto' table. 	The exception to this
;	is in the zero and stretched zero bits where the polling is internal to the 
;	routine and does not use the main jump table. The alarm sounds if an address is selected 
;	on one handset that is is use by another and the speed is turned to the
;	zero position. Turning the speed off zero will silence the alarm as will selecting a
;	valid address. Each bit in 'alarm'corresponds to one channel. The bit is set or cleared
;	depending on the alarm state for that handset. Any bit set will sound the alarm. 		 
;				
;				
;	Programming
;
;	HS  	on
;	WDT	off
;	RST	on
;
	__CONFIG	h'3FF2' ; PUTimer on, WDT off, HS clock
;			
;**********************************************************************************************
;
;	Registers used	predefined
;
ind	equ	00	;indirection reg
rtcc	equ	01	;rtcc reg
pcl	equ	02	;prog counter low                                       
status	equ	03	;status register
fcr	equ	04	;file control reg
port_a	equ	05	;port a
port_b	equ	06	;port b
eedata	equ	08	;eeprom data
eeadr	equ	09	;eeprom address
pclath	equ	0a	;PC high byte
intcon	equ	0b	;interrupt control
optreg	equ	81	;option register (page 1)
ddra	equ	85	;port a direction reg (page 1)
ddrb	equ	86	;port b direction reg (page 1)
eecon1	equ	88	;ee control	(page 1)
eecon2	equ	89	;ee control	(page 1)

;
;	working registers
;
fcount	equ	0c	;function counter
conbit	equ	0d	;consist bit register
adrtmp	equ	0e	;temp for address
temp	equ	0f	;general temp reg
byte1	equ	10	;first byte of packet
byte2	equ	11	;second byte of packet
byte3	equ	12	;third byte of packet (error on 3 byte packets)
err1	equ	13	;error byte
count0	equ	14	;counter 0 (number of packets)
count1	equ	15	;counter 1
bytcnt	equ	16	;byte counter in packet
bitcnt	equ	17	;bit counter in a byte
count4	equ	18	;counter 4
alarm	equ	19	;flag for alarm
temp2	equ	1A	;another temp
chcnt	equ	1B	;channel counter 
zcount	equ	1C	;zeros counter
adcset	equ	1D	;setup data for adc
adcdat	equ	1E	;data from ADC (7 bit)
chdata	equ	1F	;channel data (function and mode)
curadr	equ	20	;current loco address
curfun	equ	21	;current functions
funflgs	equ	22	;flag for function change
count	equ	23	;local counter
tcount	equ	24	;count in adc setup / read





fcrtmp	equ	25	;temp for fcr
consis	equ	26	;flag tor consist setup
mask	equ	27	;used in consist direction
loopt	equ	28	;special temp in loop routine
strch	equ	29	;temp for stretch value
div	equ	2a	;used in stretch
used	equ	2b	;non zero if address in use
ftoggl	equ	2c	;toggle for functions
chadr	equ	2d	;channel address from handset
temp1	equ	2e	;another temp
alarmc	equ	2f	;alarm counter (shift register)


locos	equ	30	;loco addresses against channel
			;30 to 37
loco1a	equ	31	
loco2a	equ	32
loco3a	equ	33
loco4a	equ	34
loco5a	equ	35
loco6a	equ	36
loco7a	equ	37
functs	equ	38	;functions against channel
func1a	equ	39	;38 to 3f
func2a	equ	3a
func3a	equ	3b
func4a	equ	3c
func5a	equ	3d
func6a	equ	3e
func7a	equ	3f


cons00	equ	40	;first loco in consist 90	
cons01	equ	41
cons02	equ	42
cons03	equ	43
cons10	equ	44	;first loco in consist 91
cons11	equ	45
cons12	equ	46
cons13	equ	47
cons20	equ	48	;first loco in consist 92
cons21	equ	49
cons22	equ	4a
cons23	equ	4b
cons30	equ	4c	;first loco in consist 93
cons31	equ	4d
cons32	equ	4e
cons33	equ	4f

;	bits used		predefined

zbit	equ	2	;status zero bit
carry	equ	0	;carry bit

pagno   equ    	5	;page bit	

rd      equ    	0	;read bit for eeprom
wr      equ    	1	;write bit for eeprom
wren    equ    	2	;write enable
f       equ    	1
w       equ    	0



;
;
;	end of definitions
;**************************************************************************
;
;	start of program
;
;*************************************************************************
;
	org	0
	goto	setup	;reset vector
;
;
;************************************************************************
;
; Sets up ports etc.

	
setup	bsf	status,pagno	;set to page 1
	movlw	B'00000000'	;set up rtcc (divide by 2)
	movwf	optreg
	movlw	B'11101000'	;set port a (pa4 is data out)
				;pa0 ADC clock
				;pa1 ADC not chip select
				;pa2 data to ADC
				;pa3 data from ADC
				;pa4 DCC data out to booster
	movwf	ddra
	movlw	B'10001000'	;set up port b 
				;pb0, pb1, pb2 channel select
				;pb3  channel data in
				;pb4  data clock out
				;pb5  alarm out
				;pb6  mode +ve
				;pb7 mode input

	movwf	ddrb
	
	bcf	status,pagno	;back to page 0

	movlw	B'00010010'	;set port a
	movwf	port_a
	movlw	B'01000000'	;set port b
	movwf	port_b
	clrf	chcnt
	movlw	.16		;clear tables
	movwf	count0
	movlw	locos
	movwf	fcr
clear	clrf	ind
	incf	fcr,f
	decfsz	count0,f
	goto	clear
	movlw	.16		;read consist table
	movwf	count0
	movlw	cons00		;start of consist table
	movwf	fcr
	clrf	temp1		;start of eeprom 
ldcon	movf	temp1,w
	movwf	eeadr
	call	eeread		;get consist info from eeprom
	movwf	ind		;put in RAM stack

	incf	fcr,f
	incf	temp1,f
	decfsz	count0,f
	goto	ldcon
	
	bcf	port_a,4	;set output to zero
	clrf	alarmc		;counter for alarm
	clrf	alarm     	;alarm bit register
	clrf	consis		;consist setup flag
	clrf	fcount		;counter for function packets
	clrf	conbit		;bits show which handsets 
	clrf	strch		;stretch value
	movlw	.29		;goto initialise
	


;
;	end of setup
;
;	main jump table	

main	bcf	intcon,2	;clear RTCC flag
main1	addwf	pcl,f
;
;	start of main goto table
;
	goto	p2          	;0      packet routine
	goto	one1		;1
	goto	zero1		;2
	goto	zero2		;3
	goto	one2		;4
	goto	nxtby1		;5 
	goto	setup		;6	dummy
	goto	setup		;7
	goto	setup		;8
	goto	adcclk		;9	in ADC setup
	goto	adcck2		;10
	goto	adcck3		;11 
	goto	adc2		;12
	goto	chr2		;13		
	goto	bcdout		;14	finish getting channel data
	goto	nchng1		;15	at end of function setup
	goto	chrex2		;16
        goto	nexld1		;17     in conchk

        
        goto	lid2		;18     idle 2 half cycles
        goto	lid1		;19     idle 3 half cycles
        goto	spdo1		;20	before speed packet
	goto	not0a		;21	part of loco
	goto	chngz		;22	part of loco 		
	goto	chngy		;23	part of loco
	goto	nexlu1		;24	in conchk
		
	goto	inv1            ;25	inval first

	goto	inv2		;26	inval second cycle 
	goto	loc1		;27	extra in loco
	goto	noz		;28	nozero
	goto	init       	;29	initialise
	goto	init1       	;30	second part of initialise
	goto	kill1		;31	kill old loco
	goto	kill2		;32	next stage of kill
	goto	nexld2		;33
	goto	nexlu2		;34
	goto	setc1		;35	in consist setup
	goto	setc2		;36	in consist setup
;
;******************************************************************
;
;	consist button convert
;
conbut	addwf	pcl,f		;add button no. to pc
	retlw	0		;0 is invalid combination
	retlw	1		;returns with address +1
	retlw	5
	retlw	0
	retlw	9
	retlw	0
	retlw	0
	retlw	0
	retlw	.13
;
;	timing loop. Waits for RTCC, resets and jumps
	
loop	btfss	intcon,2	;wait loop
	goto	loop
	movwf	loopt		;save w
	movlw	0xC9		;reset rtcc
	movwf	rtcc
	movf	loopt,w		;recover w
	goto	main
;
;******************************************************************
;
;	initialisation on startup
;
init	bsf	port_a,4	;output hi		
	movlw	1

	movlw	0xCB		;timing value for 58 usec.
	movwf	rtcc
	movlw	.30		;init1
	goto	loop

init1	bsf	port_a,4	;output hi     
	movlw	.20
	movwf	count0		;20 reset packets 
	call 	reset
	movlw	.20 
	movwf	count0		;20 idle packets
	call	idle 
                   
;*******************************************************************        
;
;	main continuous scan and send routine
;
;
scan	movf	alarm,f		;test alarm
	btfsc	status,zbit
	goto	alarm1
	bsf	port_b,5	;alarm on
	goto	scan1
alarm1	bcf	port_b,5	;alarm off
scan1	incf	chcnt,w		;next channel
	andlw	B'00000111'	;eight channels only
	movwf	chcnt		
	call	adcgo		;set up adc 
	call	adcrd		;read adc 
	call	chread		;get channel data
				
	call	setfun		;sets up functions
		
	call	loco		;check for valid loco or consist
				;and send packet(s)
		
main3	movf	chcnt,w		;send function packet
	andlw	B'00000011'	;every 4th channel
	btfsc	status,zbit
	call	sndchg		;send function 
	
main2	goto	scan	


;******************************************************
;
;	subroutines
;
;******************************************************
;
;	sends a complete reset packet
;
reset	
	clrf	byte1
	clrf	byte2
	
	movlw	3
	movwf	bytcnt
	call	preamb
	call	packet
	decfsz	count0,f
	goto	reset 
    	return 
;
;	sends a complete idle packet
;
    
idle	movlw	.10
	call	lidle1		;idle packet with preamble
	decfsz	count0,f
	goto	idle
	return
;****************************************************************
;
;	main packet routine
;
;	sends a packet without preamble
;	data to be set in byte1 to byte3 etc
;	number of bytes in packet in bytcnt
;	routine works out the error byte itself
;	adds start bits and handles any stretches
;	must arrive with the DCC output high
;
;			 
packet	movlw	1		;add preamble
	call	addpre
	movlw	byte1    	;point fcr to start of bytes
	movwf	fcr
	movf	bytcnt,w	;get no of bytes
	movwf	temp
	decf	temp,f
	decf	temp,f
	movf	ind,w		;get 1st byte
	incf	fcr,f 
p1	xorwf	ind,w		;work out error
	incf	fcr,f 
	decfsz	temp,f
	goto	p1 
	movwf	ind		;error byte
	movlw	byte1 		;reset index
	movwf	fcr
	
	

		
ploop	btfss	intcon,2  	;wait for RTCC
	goto	ploop 
        movlw	0xD9		;sets non stretched zero for 100 usec. *
	movwf	rtcc
	bcf	intcon,2

	incf	zcount,f	;increment zeros counter
	btfss	strch,7		;check direction of DC
    	call	strtch		;nonlinear stretch of first half

    
	
	movlw	.9
	movwf	bitcnt		;set bitcount (8 bits)
	movlw	0		;wait for RTCC in main loop
	goto	loop		;jump to p2
p2	bcf	port_a,4	;output lo (first half of start bit complete)
;
;	second half of start bit
;
		 
ploop2	btfss	intcon,2
	goto	ploop2 
	movlw	0xD9		;reset  rtcc *
	movwf	rtcc 
	bcf	intcon,2

   	btfsc	strch,7		;check direction of DC	
	call	strtch


	
;
;	setup for a byte
;
nxt1	decfsz	bitcnt,f	;last bit?
	goto	nxtbit		;no so next bit
	goto	nxtbyt		;yes so next byte
		
nxtbit	rlf	ind,f		;roll the data
	btfss	status,carry
	goto	zero		;wait for RTCC then jump to 
				;a one or a zero

	movlw	1		;one1
	goto	loop
;
;	bit is a zero
;
zero	movlw	2		;zero1
	goto	loop
	
zero1	bsf	port_a,4	;output up 

z1	btfss	intcon,2  	;miss a count as it is a zero
	goto	z1
	movlw	0xD9		;reset rtcc *
	movwf	rtcc		;value to make zero = 100usec.
	bcf	intcon,2
	incf	zcount,f	;increment zeros counter
	btfss	strch,7		;check direction of DC
	call	strtch
	movlw	3 		;wait again then goto zero2
	goto	loop
	
zero2  	bcf	port_a,4	;output down (end of first half)
;
;	second half of a zero
;
    	
z2	btfss	intcon,2  	;miss a count
	goto	z2
	movlw	0xD9		;reset rtcc *
	movwf	rtcc
	bcf	intcon,2
	btfsc	strch,7		;check direction of DC
	call	strtch
	
z3	goto	nxt1
;
;	bit is a one	
;

one1	bsf	port_a,4	;output up
	movlw	4      		;one2
	goto	loop 
;
;	second half of a one
; 
one2	bcf	port_a,4   	;output down 
	goto	nxt1
;
;	get next byte
;
	
nxtbyt	incf	fcr,f
	movlw	.9
	movwf	bitcnt
	movlw	5 		;nxtby1
	goto	loop
nxtby1	bsf	port_a,4	;output up
	decfsz	bytcnt,f	;last byte	
	goto	ploop		;start bit of next byte

	return			;no more bytes in packet

;************************************************************
;
;	nonlinear stretch routine
;	uses lookup table in eeprom to give 16 linear
;	segment approximation for stretch curve
;	also for each speed step (0 to 127) it stretches
;	progressively more zeros.
;	If stretch value is zero then no stretch
;	Note. Bit 7 of strch is the DC direction bit.
;
strtch	btfsc	zcount,6	;if counter = 64 then reset
	clrf	zcount
	movf	strch,w		;get DC speed value
	andlw	B'01111111'	;mask direction
	subwf	zcount,w	;stretch this zero?
	btfsc	status,carry
	goto	strend
	movf	zcount,w	;get cycle number
	movwf	div		;ready to divide by 4
	rrf	div,f
	rrf	div,w
	andlw	B'00001111'	;mask any carries
	addlw	.48		;table starts at 48
	movwf	eeadr
	call	eeread
	movwf	div		;use div again as loop counter
loopy	call 	dely		;delay loop
	decfsz	div,f
	goto	loopy 
	movlw	0xF5		;reset  rtcc *
	movwf	rtcc 
	bcf	intcon,2

strend	return

dely	movlw	.28		;need to adjust
	movwf	temp
dely1	decfsz	temp,f
	goto	dely1
	return



;*************************************************************
;
;sends a passive preamble of 10 cycles
;arrive with output hi
;leaves with output hi  (ready for packet)


preamb	movlw	.10		;10 preamb cycles
	call	addpre
	return
	

	
;**************************************************************
;
;	set up ADC and start conversion
;
;	
;
adcgo	movlw	9
	goto	loop
adcclk	bcf	port_a,4	;output lo
	clrf	adcset		;clear adcset
	btfsc	chcnt,0		;bit shuffle for channel select
	bsf	adcset,6	
	btfsc	chcnt,1
	bsf	adcset,4
	btfsc	chcnt,2
	bsf	adcset,5
	movf	adcset,w	;get adcset
	iorlw	B'10001110'	;unipolar, 
				;single ended, 
				;int. clock
	movwf	adcset
	bcf	port_a,1	;chip select lo 
	movlw	8		;one byte
	movwf	count	
	
adcin	rlf	adcset,f	;shift data out
	btfss	status,carry
	goto	abit0
	bsf	port_a,2
	goto	clok0
abit0	bcf	port_a,2 
clok0	bsf	port_a,0	;clock hi				
	bcf	port_a,0	;clock lo
	decfsz	count,f		;last bit?
	goto	adcin
	
	bsf	port_a,1	;chip select hi 
	movlw 	.10
	goto	loop
adcck2	bsf	port_a,4	;output up
    	movlw	.11    
    	goto	loop		;allow for AD conversion
adcck3	bcf	port_a,4	;output down
	return 			;end of ADC setup
	

;
;	get data from ADC   
;
adcrd	clrf	adcdat		;clear for data
	movlw	7		;top 7 bits only
	movwf	bitcnt
	bcf	port_a,1	;chip select
	bsf	port_a,0	;clock up
	bcf	port_a,0	;two dummy cycles
	bsf	port_a,0
	bcf	port_a,0
adcrd0	btfss	port_a,3	;read bit
	goto	adcr0
	bsf	status,carry
	goto	roll
adcr0	bcf	status,carry
roll	rlf	adcdat,f
	bsf	port_a,0	;clock up
	bcf	port_a,0	;clock down 
	decfsz	bitcnt,f
	goto	adcrd0		;next bit

	bsf	port_a,1	;deselect
	movlw	.12
	goto	loop
adc2	bsf	port_a,4	;output up
	return			;ADC read complete

;
;	read channel settings.  two data bits for each half of
;	preamble cycle
;
chread	clrf	temp1		;temp store for data byte
	movlw	B'11111000'
	andwf	port_b,f	;clear address
	movf	chcnt,w		;get channel
	iorwf	port_b,f	;set port
	movlw	2
	movwf	bytcnt		;two bytes (16 bits of data)
chrr1	movlw	2
	movwf	count0
	
chrr	movlw	4
	movwf	count4		;bits per half output
	
chrd2	bsf	port_b,4	;clock down
	nop
	nop
	nop 
	btfss	port_b,3	;read data
	goto	dat0
	bsf	status,carry
	goto	roldat
dat0	bcf	status,carry
roldat	bcf	port_b,4	;clock up 
	nop
	nop
	
	rlf	temp1,f		;bit 7 = no handset if 1
				;bit 5 and 6 = 0 mode 0
				;bit 6 = 1 mode 2
				;bit 5 = 1 mode 1
				;bits 5 and 6 = 1 mode 3
				;bit 4 = fwd / rev
				;functions lo nibble
	decfsz	count4,f
	goto	chrd2		;next bit of 4
	decfsz	count0,f		
	goto	opdown
	
	movlw	.16		;chrex2
	goto 	loop


opdown 	movlw	.13		;goto chr2
	goto	loop
chr2	bcf	port_a,4    	;output down
	goto	chrr

secbyt	movf	temp1,w		;store channel data
	movwf	chdata
	goto	chrr1

chrex2	bsf	port_a,4	;output up
	decfsz	bytcnt,f	;last byte?
	goto	secbyt
	movf	temp1,w		;finished getting channel data
	movwf	curadr  	;store channel data	
	
			
hndtst	btfss	chdata,7	;any handset?
	goto	bcdcon		;yes
	goto	notbcd		;don't do BCD conversion
	
;	converts BCD address from thumbwheels
;	uses jump table	for speed

bcdcon	comf	curadr,f	;recover address and complement
	movf	curadr,w
	movwf	temp1        	;BCD to binary 
	swapf	temp1,f			
	movlw	B'00001111'	;mask 
	andwf	curadr,f        ;has low nibble
	andwf	temp1,f         ;has hi nibble
	movlw	.10		;start bcd conversion
bcdlp	movf	temp1,f
	btfsc	status,zbit
	goto	bcdfin
	addwf	curadr,f	;add 10
	decf	temp1,f
	goto	bcdlp

 	;	sets bit in alarm counter
;	works like a shift register
;	bit moves along with each channel count
;
bcdfin	movf	chcnt,f		;roll the alarm counter bit
	btfss	status,zbit	;is it channel 0
	goto	aroll0
	bsf	status,carry	;set carry
	rlf	alarmc,f	;roll in a one
	goto	aroll1
aroll0	bcf	status,carry	;clear carry
	rlf	alarmc,f	;roll bit along	
aroll1	bsf	port_b,4	;read consist switch
	nop
	btfsc	port_b,3	;test bit (0 = consist)
	goto	conoff
	movf	alarmc,w	;get handset counter
	andwf	conbit,w	;test for zero
	btfsc	status,zbit
	bsf	consis,4
	goto	conout
conoff	movf	alarmc,w	;toggle consist set off
	andwf	conbit,w
	btfsc	status,zbit
	goto	conout
	comf	alarmc,w	
	andwf	alarm,f 	;clear alarm
	andwf	conbit,f	;clear consist flag

conout	bcf	port_b,4
	movlw	.14		;bcdout
	goto	loop
bcdout	bcf 	port_a,4	;output down
	return

notbcd	clrf	curadr		;invalid address
	goto	bcdfin

;
;	
;
;
;	set up function byte
;	checks if there has been a change
;	sets / clears toggle action
;
setfun	comf	chdata,w	;hi is off on receipt
	movwf	curfun		;current functions (lo nibble)

	btfsc	consis,4	;is it a consist set up
	goto	nchng2		;yes so leave alone
	movf	alarmc,w	;check consist toggle
	andwf	conbit,w
	btfss	status,zbit
	goto	nchng2

	
	movlw	functs		;point to function table
	addwf	chcnt,w		;offset by channel
	movwf	fcr
	movlw	B'00100000'	;counter for 28 step mode
	addwf	ind,f
	movlw	B'00001111'	;toggle action for functions
	andwf	curfun,w
	btfss	status,zbit	;are all buttons released?
	goto	fchnge		;yes so set toggle
	bsf	ind,4		;toggle is bit 4
	goto	nchng2

fchnge	btfsc	ind,4		;toggle set?
	goto	fchng1
	goto	nchng2

				
fchng1	movlw	B'00001111'	;mask functions
	andwf	curfun,w	;get new functions to change
	xorwf	ind,f		;change funct. bit	
	bcf	ind,4		;clear toggle


nchng2	movlw	.15		;wait for RTCC
	goto	loop
nchng1	bsf	port_a,4	;output up
	return


;
;	checks loco address for in use
;	a valid address has the top bit set
;
loco	movlw	locos		;get table start
	addwf	chcnt,w		;add channel count
	movwf	fcr		;set indirection
	btfss	chdata,7	;handset off?
	goto	okadr      	;no so continue
	comf	alarmc,w	;handset off so no alarm on this channel
	andwf	alarm,f
	btfss	ind,7		;old address valid?
	goto	lidle5		;no so idle
	bcf	ind,7		;set address to invalid
	movf	ind,w		;get old address
	goto	estop		;handset now off so stop
				;loco that was assigned to it
				;and set to invalid
;
;	address is OK to check
;
				
	

okadr	bsf	curadr,7	;set valid bit on new one	
	movf	curadr,w	;get new address to w
	subwf	ind,w		;is it same as old one?
	btfss	status,zbit	;skip if same
	goto	new1		;new address different
	btfss	consis,4	;test for consist setup
	goto	nocons		;no consist button
        goto	setcon		;set / unset consist

	
	
nocons	goto	speed		;put out speed packet to same address
new1	movf	adcdat,f	;is speed zero?
	btfsc	status,zbit
	goto	change		;yes so change?
	comf	alarmc,w	;speed not zero so no alarm on this channel
	andwf	alarm,f
	btfss	ind,7		;old address valid? 
	goto	lidle5		;old one was not and speed not zero so idle
	
				;old one was valid and speed not zero
	comf	alarmc,w	;clear alarm bit
	andwf	alarm,f

	movf	ind,w		;get old address
	movwf	curadr
	goto	speed		;send speed packet to old address

;
;	speed is zero so see if address is in use
;	interleaved with sending preamble bits
;	if there is a match, the 'used' flag is set
;
change	clrf	used    	;clear flag for address in use
	movlw	locos		;reset fcr
	movwf	fcr
	movlw	2               ;loop 2 channels	
	movwf	count0
chng1	movf	curadr,w	;get new address
	subwf	ind,w
	btfsc	status,zbit	;same?
	incf	used,f
	incf	fcr,f
	decfsz	count0,f
	goto	chng1		

	movlw	.22
	goto	loop
	
	
chngz	bcf	port_a,4        ;output down 
	movlw	4           	;loop another 4
	movwf	count0		

chng2	movf	curadr,w	;get new address
	subwf	ind,w
	btfsc	status,zbit	;same?
	incf	used,f
	incf	fcr,f
	decfsz	count0,f
	goto	chng2		
	movlw	.23
		
	goto	loop        	;wait for timer
chngy	bsf	port_a,4	;output up
	movlw	2           	;loop another 2
	movwf	count0		

chng3	movf	curadr,w	;get new address
	subwf	ind,w
	btfsc	status,zbit	;same?
	incf	used,f
	incf	fcr,f
	decfsz	count0,f
	goto	chng3		

	movf	used,f		;test used flag
	btfss	status,zbit
	goto	kill	    	;address in use so kill old loco
	movlw	.27		;wait for RTCC
	goto	loop
loc1	bcf	port_a,4	;output down
	movlw	locos		;OK so put new address
	movwf	fcr		;in loco table
	movf	chcnt,w
	addwf	fcr,f       	;now check if old address was 00
	btfss	ind,7		;is address valid
	goto	nozero		;not valid so don't reset 
	movf	ind,w		;test for zero
	andlw	B'01111111'
	btfss	status,zbit
	goto	nozero		;not zero
	clrf	strch		;was zero so reset stretch

nozero 	comf	alarmc,w	;clear alarm bit
	andwf	alarm,f
			
;mod to ensure old loco stops
 
loc3	movlw   .28		;noz
	goto	loop
noz	bsf	port_a,4	;output up
	
	
	call	activ		;if new is a consist, activate
	movf	curadr,w 	;swap old and new addresses
	movwf	temp1		;save 
	movf	ind,w         
	movwf	curadr
	movf	temp1,w
	movwf	ind
	btfss	curadr,7	;was old one valid
	goto	lidle5 
	clrf	adcdat     	;make sure old address is off	
	call	deact		;if old was a consist, then deactivate
	goto	speed

activ	bcf	curadr,7	;clear valid flag
	movlw	.90		;sets consist active flag for speed check
	subwf	curadr,w
	btfsc	status,zbit	;no match
	bsf	consis,0	;flag for consist 90
	movlw	.91		
	subwf	curadr,w
	btfsc	status,zbit	;no match
	bsf	consis,1	;flag for consist 91
	movlw	.92		
	subwf	curadr,w
	btfsc	status,zbit	;no match
	bsf	consis,2	;flag for consist 92
	movlw	.93		
	subwf	curadr,w
	btfsc	status,zbit	;no match
	bsf	consis,3	;flag for consist 93 
	bsf	curadr,7	;restore valid flag
	return

deact	bcf	curadr,7	;clear valid flag
	movlw	.90		;clears consist active flag 
	subwf	curadr,w
	btfsc	status,zbit	;no match
	bcf	consis,0	;flag for consist 90
	movlw	.91		
	subwf	curadr,w
	btfsc	status,zbit	;no match
	bcf	consis,1	;flag for consist 91
	movlw	.92		
	subwf	curadr,w
	btfsc	status,zbit	;no match
	bcf	consis,2	;flag for consist 92
	movlw	.93		
	subwf	curadr,w
	btfsc	status,zbit	;no match
	bcf	consis,3	;flag for consist 93
	return
;
;	address in use so stop old loco and set hansdet address to invalid
;	also set alarm 
;
kill	movlw	.31
	goto	loop
kill1	bsf	port_a,4	;output up
	movlw	locos		;get old address
	movwf	fcr		;in loco table
	movf	chcnt,w
	addwf	fcr,f       	;now check if old address was 00
	movf	ind,w		;test for zero
	andlw	B'01111111'
	btfss	status,zbit

	goto	kzero		;not zero
	clrf	strch		;was zero so reset stretch

kzero	movf	alarmc,w	;set alarm register 
	iorwf	alarm,f
			
	movlw	.32
	goto	loop
kill2	bcf	port_a,4	;output down
	btfsc	ind,7
	goto	kill3		;is old address valid?
	movlw	5               ;5 extra preambles
	goto	lidle1		;no so idle
kill3   bcf	ind,7		;set invalid
	movf	ind,w		;get old address
	movwf	curadr
	call	deact		;if a consist, deactivate
	clrf	adcdat		;stop
	incf	adcdat,f	;em stop
	goto	speed
;
;
;	sends an idle packet without preamble
;
				
 
	
lidle3	movlw	B'11111111'	;set idle bytes
	movwf	byte1
	movlw	B'00000000'
	movwf	byte2
	movlw	3
	movwf	bytcnt
	call	packet
	goto	spdo2		;check for part of consist
		
lidle5	movlw	5
	
lidle1 	call	addpre 		;add preamble cycles
	goto	lidle3
	
;
;	subroutine to add extra preamble cycles
;	number of extras in w
;	arrives with output hi
;	leaves with output hi
;
			
addpre	movwf	count1		;extra preamble cycles
addpr1	movlw	.19		
	goto	loop
lid1	bcf	port_a,4     	;output down
	movlw	.18
	goto	loop
lid2 	bsf	port_a,4	;output up 
	decfsz	count1,f
	goto	addpr1
	return

;
;	sends a speed packet
;	checks on speed mode and sets accordingly
;	mode for a consist is that of the consist handset
;	cannot mix modes within a consist
;	checks for address zero and sets stretches
;	arrives with output high
;	exits to packet with output high
	
	
speed	bcf	curadr,7	;clear valid flag
	
	movf	curadr,f	;is address zero?
	btfss	status,zbit
	goto	not0		;no

	
	movf	adcdat,w	;put adc data into stretch
	movwf	strch
	rrf	strch,f		;64 steps for DC
	btfss	chdata,4	;check direction bit
	goto	fwd0
	bsf	strch,7		;set direction bit (1 = reverse)
	goto	speedy
fwd0	bcf	strch,7
speedy	movlw	3		;3 extra preambles
	goto	lidle5        	;put out idle packet (address 00)
	
not0	goto	conchk		;is it a consist 
speedz	movf	curadr,f	;consist address is zero (no loco)
	btfsc	status,zbit
	goto	speedy
	movlw	.21		
	goto	loop		;wait for RTCC
	
not0a	bcf	port_a,4	;output down	
	movlw	B'01100000'  	;test for current speed mode
	andwf	chdata,w
	movwf	temp1
	btfsc	status,zbit
	goto	spd3		;mode 0 is 128 for now 
	movlw	B'01100000'
	subwf	temp1,w
	btfsc	status,zbit
	goto	spd3		;128 step speed mode
	
	btfss	temp1,5
	goto	spd2         	;28 step mode

	goto	spd1         	;14 step mode
	

;	set up speed bytes
;
;	spd3 is 128 step mode
;
spd3	movf	curadr,w	;get address
	movwf	byte1 
	bcf	byte1,7		;clear valid flag
	movlw	B'00111111'	;128 bit speed
	movwf	byte2
	movf	adcdat,w
	movwf	byte3
;	btfsc	consis,6	;a consist?
;	goto	confn3
;	movlw	functs		;point to function table *
;	addwf	chcnt,w		;add channel*
;	movwf	fcr		;indirection*
;	btfss	ind,4		;check direction
	btfsc	chdata,4
	goto	revset
fwdset	bsf	byte3,7		;forward
	goto	errset
revset	bcf	byte3,7		;reverse
			
errset	movlw	4
	movwf	bytcnt
	goto	spdout      	;send speed packet


;
;	spd2 is 28 step mode
;
		
spd2	movf	curadr,w	;get address
	movwf	byte1
	bcf	byte1,7		;remove valid bit
	clrf	byte2		;clear speed byte
	decf	adcdat,w	;em stop?
	btfsc	status,zbit
	goto	spd2e
	movlw	B'00000011'	;save last two bits
	andwf	adcdat,w
	movwf	div		;reuse div
	movf	adcdat,w	;save adcdat
	movwf	adcset		;reuse adcset as temp
	rrf	adcset,f        ;reduce speed to 4 bits
	rrf	adcset,f
	movlw	B'00011111'	
	andwf	adcset,f	;mask
	movlw	2
	subwf	adcset,w
	btfss	status,carry	;2 or more?
	goto	nonout
	movlw	functs		;point to function table 
	addwf	chcnt,w		;add channel
	movwf	fcr		;indirection
	swapf	ind,w
	movwf	temp
	rrf	temp,w
	andlw	B'00000011'	;mask except count
	subwf	div,w
	btfss	status,carry	;count > div
	goto	nojit
	btfsc	status,zbit	;count = div
	goto	nojit
	btfss	port_b,7	;no jitter mode?
	goto	nojit
	movlw	B'00011111'	;is it step 28 already
	andwf	adcset,f	;mask
	subwf	adcset,w
	btfss	status,zbit
		
	incf	adcset,f	;add 1



nojit	rrf	adcset,w        ;in 28 step mode
	btfsc	status,carry
	bsf	byte2,4
	iorwf	byte2,f		;set speed
	
	
	
	
spd2f	call	dirsub		;set direction
	goto	spdout

nonout	clrf	adcset		;stop 
	goto	nojit
		
spd2e	movf	adcdat,w	;em stop
	movwf	byte2
	goto	spd2f

;
;	spd1 is 14 step mode. FO bit is set
;

spd1	movf	curadr,w	;get address
	movwf	byte1
        bcf	byte1,7
	decf	adcdat,w	;em stop?
	btfsc	status,zbit
	goto	spd1e
	rrf	adcdat,f	;set for 14 steps only
	rrf	adcdat,f        ;reduce speed to 4 bits
	rrf	adcdat,w
	movwf	byte2		;set speed

	bcf	byte2,4		;F0 bit
	movlw	functs		;point to function table 
	addwf	chcnt,w		;add channel
	movwf	fcr		;indirection
	btfsc	ind,0		;test F0 bit
	bsf	byte2,4		;F0 on 
spd1f	call	dirsub		;set direction
	

spdout	movlw	.20
	goto	loop
spdo1	bsf	port_a,4	;output up
	call	packet		;send speed packet
spdo2	btfss	consis,6	;a consist
	return 
	btfss	consis,7
	goto	lstcn1
	movlw	5
	call	addpre		;add 5 preamble cycles
	goto	nxtloc		;next in consist

spd1e	movf	adcdat,w
	movwf	byte2
	goto	spd1f

lstcn1	bcf	consis,6	;last in consist
	return

dirsub	btfsc	chdata,4	;check direction
	goto	revse1
fwdse1	bsf	byte2,5		;forward
	goto	errse1
revse1	bcf	byte2,5		;reverse
	
errse1	bcf	byte2,7
	bsf	byte2,6		;speed packet
	
	movlw	3
	movwf	bytcnt
	return

confn1	btfss	chdata,4	;direction in consist
	goto	revse1
	goto	fwdse1 




;	sends a stop to current loco
;
estop	movwf	curadr		;old address
	clrf	adcdat		;speed to zero
	incf	adcdat,f	;em stop
	call	deact		;deactivate if a consist
	

	
;*********************************
;
;	set up consist
;	loco address in curadr
;	consist number is function button
;	
;
setcon	movf	curfun,w	;get function button
	andlw	B'00001111'
	movwf	temp
	btfsc	status,zbit	;no button?
	goto	noput
	movlw	.9		;too high?
	subwf	temp,w
	btfsc	status,carry
	goto	noput 
	movf	temp,w
	call	conbut		;converts button number to address
	btfsc	status,zbit	;invalid combination? (only one button
				;allowed)
	goto	noput
	movwf	temp		;for consist address
 
	movlw	.35             ;wait
	goto	loop
setc1	bcf	port_a,4	;output down
	decf	temp,f		;less 1
		                                              	
lookup	clrf	temp1
        clrf	temp2
	clrf	count4
	movf	curadr,w	;get handset address
	movwf	adrtmp
	bcf	adrtmp,7	;clear valid bit
	incf	count4,f	;1 in count 4
	movf	temp,w
	addlw	cons00		;start of consist block
	movwf	fcr
looku1	movf	ind,w		;get loco
	btfsc	status,zbit	;blank?
	goto	setblk		
looku2	andlw	B'01111111'	;mask direction bit
	subwf	adrtmp,w	;same?
	btfsc	status,zbit	;no
	goto	looku3
	movf	adrtmp,f	;is address 00?
	btfss	status,zbit	
	goto	again		;no
looku3	movf	count4,w
	movwf	temp2		;number that matches	
		
again	incf	count4,f
	incf	fcr,f
	movlw	5
	subwf	count4,w
	btfss	status,zbit
	goto	looku1
	goto	check 
	
setblk	movf	count4,w
	movwf	temp1		;number that is a blank
	goto	again
	
check	movlw	4     		;set fcr back to block start
	subwf	fcr,f

	movf	temp2,w         ;was there a match?
	btfsc	status,zbit
	goto	check1  	;no
	decf	temp2,w		;get which one
	addwf	fcr,f
	goto	clrout		;clear loco

check1	movf	temp1,w
	btfsc	status,zbit	;was there a blank
	goto	noput	
	decf	temp1,w
	addwf	fcr,f
putin	movf	adrtmp,w	;get address
	movwf	ind		;put in block
	btfsc	chdata,4	;direction for consist
	bsf	ind,7		;top bit of address is direction

	movf	ind,w
	movwf	eedata
putcon	movlw	cons00          ;get eeprom address
	subwf	fcr,w		;get block offset
	
	movwf	eeadr 
	movlw	.36
	call	loop		;wait
setc2	bsf	port_a,4	;output up
	
	bsf	status,pagno	;page 1
	bsf	eecon1,wren
	call	eewrit		;write loco to eeprom
				;end of write
	movf	alarmc,w	;set toggle
	iorwf	conbit,f
	iorwf	alarm,f		;set alarm for acknowledge
noput	bcf	consis,4
	movlw	4
	call	addpre		;add 4 preambles

	goto	speed

clrout	clrf	ind
	clrf	eedata
	goto	putcon		;clear table entry

;******************************************************
;
;	check if address is a consist and if so
;	send speed packets to all in the consist
;	else send speed packet as normal
;
			
conchk	movlw	.90		;consist address?
	subwf	curadr,w	;90 or higher
	btfss	status,carry
	goto	notcon		;not a consist
	sublw	.3
	btfss	status,carry	
	goto	notcon		;not a consist
	bsf	consis,7	;is a consist
	bsf	consis,6
	movf	chdata,w	;save chdata
	movwf	mask
	movlw	.90
	subwf	curadr,f	;consist block address starts at 0
	bcf	status,carry
	rlf	curadr,f
	rlf	curadr,f	;multiply by 4
	movlw	cons00		;start of table
	addwf	curadr,w
	movwf	temp2		;set index
conck1	movlw	.4		;4 locos per consist
	movwf	count4		;4 in count4
loadu1	movf	temp2,w
	movwf	fcr
	movf	ind,w		;get table entry
	btfss	status,zbit	;is it blank
	goto	spdin		;send packet to loco
	decfsz	count4,f	;block end?
	goto	nxtloc
	goto	lstloc		;last in consist
nxtloc	incf	temp2,f
	goto	loadu1		;next in block
spdin	movwf	curadr		;loco address to curadr
	movf	mask,w		;recover original chdata

	btfss	curadr,7	;consist direction		
	goto	norev		;not reverse
	xorlw	B'00010000'	;direction for consist
norev	movwf	chdata		;set for this loco
	bcf	curadr,7	;clear direction bit
	movlw	4
	call	addpre		;4 extra preamble cycles
	goto	speedz
	
lstloc	bcf	consis,7	;last of consist
	goto	spdin				
;********************************************
;
;	checks if loco is in an active consist and if so
;	does not send speed packet. As a loco may be in
;	more than one consist which may or not be active, 
;	this is a bit messy.
;
notcon	clrf	used
	movlw	cons00
	movwf	fcr

nexloc	movlw	.17
	goto	loop
nexld1  bcf	port_a,4	;output down
	call	conloc
	sublw	0
	btfsc	status,zbit
	goto	nexlo1		;no match in consist 90
	btfsc	consis,0	;consist active?
	incf	used,f
nexlo1	movlw	.24
        goto	loop
nexlu1	bsf	port_a,4	;output up
	movlw	2
	call	addpre		;add 2 preamble cycles
	incf	fcr,f
	call	conloc
	sublw	0
	btfsc	status,zbit
	goto	nexlo2		;no match in consist 91
	btfsc	consis,1	;consist active?
	incf	used,f
nexlo2	movlw	.33
        goto	loop
nexld2  bcf	port_a,4	;output down
	incf	fcr,f
	call	conloc 
	sublw	0
	btfsc	status,zbit
	goto	nexlo3		;no match in consist 92
	btfsc	consis,2	;consist active?
	incf	used,f
nexlo3	movlw	.34
        goto	loop
nexlu2	bsf	port_a,4	;output up
	incf	fcr,f
	call	conloc 
	sublw	0
	btfsc	status,zbit
	goto	nexlo4		;no match in consist 93
	btfsc	consis,3	;consist active?
	incf	used,f
nexlo4	movf	used,f		;not zero if in a consist?
	btfsc	status,zbit
	goto	speedz		;send speed packet to loco
	movlw	4		;4 extra cycles
	goto	lidle1		;send an idle instead

conloc	movlw	4
	movwf	count
conlo1	movf	ind,w		;get loco
	andlw	B'01111111'	;mask direction
	subwf	curadr,w
	btfsc	status,zbit	;not in a consist
	retlw	1		;match
	decfsz	count,f
	goto	conlo2
	retlw	0		;no match
conlo2	incf	fcr,f
	goto	conlo1
	
	
;********************************************
;	sends a function packet if required
;
		
sndchg	incf	fcount,w	;increment function counter
	andlw	B'00000111'	;eight channels
	movwf	fcount
	movf	fcount,f	;is fcount zero
	btfss	status,zbit
	goto	getfun
	movlw	1
	movwf	count0
	call	idle		;was zero so add an idle packet
getfun	movlw	locos		;loco table
	addwf	fcount,w	;add offset
	movwf	fcr
	btfss	ind,7		;invalid address?
	goto	inval		;don't send a function
	
	movf	ind,w		;get address
	movwf	byte1
	bcf	byte1,7		;clear valid flag
	movf	byte1,f		;is address zero?
	btfsc	status,zbit
	goto	inval		;yes so dont send function
	
	movlw	functs		;start of function stack
	addwf	fcount,w	;offset
	movwf	fcr		;set pointer
	

	movf	ind,w		;get function
	andlw	B'00001111'	;mask mode bits	
	movwf	byte2
	rrf	byte2,f		;mod for f0
	
	btfsc	status,carry	;F0 was zero
	bsf	byte2,4		;set F0
		
	
	bsf	byte2,7		;set for function group 1
	
	movlw	3
	movwf	bytcnt
	call	preamb        	;preamble
	call	packet        	;send function packet
	return
	
inval 	movlw	.25	    	;no function packet
	goto	loop            ;but needs an extra
                              	;preamble cycle to make up time
inv1	bcf	port_a,4	;output down
	movlw	8
	addwf	fcr,f		;point to function
	movlw	B'11100000'
	andwf	ind,f		;clear any old function data
	movlw	.26
	goto	loop
inv2	bsf	port_a,4	;output up		
	return
	
;		

;	eeprom write subroutine. Write eedata into eeadr
;	does not wait for write complete as this would interfere
;	with the DCC bit stream timing.
;	can only write every 8th packet anyway.

eewrit	movlw   0x55
        movwf   eecon2
        movlw   0xAA
        movwf   eecon2
        bsf     eecon1,wr
	nop
        bcf     eecon1,wren
        bcf     status,pagno
        return

eeread	bsf	status,pagno	;page 1
	bsf	eecon1,rd	;set read bit
	bcf	status,pagno	;back to page 0
	movf	eedata,w	;get data
last	return



;************************************************
;
;	clear consist EEPROM space
;
	org	0x2100
	de	0
	de	0
	de	0
	de	0
	de	0
	de	0
	de	0
	de	0
	de	0
	de	0
	de	0
	de	0
	de	0
	de	0
	de	0
	de	0
	
;	lookup table for speed curve in EEPROM
;	not finalised yet
;
	org	0x2130 
	de	.7
	de	.8
	de	.9
	de	.10
	de	.12
	de	.14
	de	.16
	de	.19
	de	.24
	de	.29
	de	.37
	de	.48
	de	.65
	de	.93
	de	.145
	de	.255
		

	
	
	end

	
