;original program by D Probst modified by M Bolton and G Hopkins
;filename decod10d.asm
;
;modified for decod10 PCB. (also decod11)
;uses two static direction lines and one PWM output
;mod to turn on both low side MOSFETs during PWM off period
;this gives much quieter running and better speed control
;rev d now has a switch to disable the motor short.
;CV29 bit 6 if set gives motor damping
;CV29 bit 6 if clear leaves motor open in the off state

;Updated 8/6/00 to rev d
;CV7 set to 10.2 GH 17-06-00
;CV8 set to 13. Manufacturer code for a DIY system
;
;Modified to use Consist Control Instruction 0001001X version 10.1 GH 03/04/00
;
;	
;Now has hardware input for brown-out detect	
;Sets speed to zero if POR but uses last speed if		
;short drop-out		
;	
;
;On power up or reset goes to DC mode. Reset routine looks for transition
;and checks for AC. If AC assumes DCC and sets outputs. 
;
;
;inputs rearranged for MERG decoder and separate power stage
;Default CVs and speed table now included in program

;This is code for a PIC16F84 to be used as a NMRA DCC decoder. This
;program will read three, four, and five byte packets and supports paged
;and direct CV service mode access of CV data. It also supports advanced
;programming functions for "on the main" programming of CV's. Other
;functions include 28 speed (linear between CV2 and CV5) and user defined 
;28 speed curves. It also supports 128 speed step instructions. Five outputs
;can be set up for special effects such as strobe and ditch lights. 

;The processor is configured to operate at 8MHz. Each of the outputs and the 
;signal input can be configured for any of the 13 I/O pins. Users need only
;change the variable definitions to match the desired I/O pin combination 
;and change the DDR values to match the I/O configuration. When programming,
;the fuses should be set with HS clock, WDT On.

;The following NMRA defined CV's and ranges are supported...

;CV1    Primary Address         00h - 69h  Values >119 are not valid
;CV2    Start Voltage           00h - FFh  00 is off, FF is full speed   
;CV5    Hi Voltage              00h - FFh  FF is continuous on. 80h is 50% 
;                                          duty cycle.
;CV7    Version Number          00h - FFh  102 for this build
;CV9    Motor PWM               00h - 17h  PWMt is [CV9 + 8]ms. If a CV9 is
;                                          greater than 23, then max is 31ms.
;CV11   Packet Time Out         00h - FFh  t is [CV11]sec. If 0, then no 
;                                          time-out is used.
;CV19   Consist Address         00h - 7Fh  Bit 7 is direction relative to
;                               (bit 7)    locomotive front. 0 is normal.
;CV29   Configuration Data      Only bits 0 (Direction), 4 (Speed Table)
;                               and 6 (motor mode) are changable.
;CV49-54 General Purpose        00h - FFh  Can be used to store data.

;CV55   Output 1 Control        00h - FFh  These CV's are used to select which
;CV56   Output 2 Control        00h - FFh  DCC functions control the specific
;CV57   Output 3 Control        00h - FFh  output. The value is masked with 
;CV58   Output 4 Control        00h - FFh  the function instruction to
;CV59   Output 5 Control        00h - FFh  determine the control.

;       Example: 00010000 would be controlled by F0.
;                00010001 would be controlled by F0 OR F1.
;                1XXXXXXX would be on all the time.

;CV60   Output 1 Effect(Purple) 00h - FFh  These CV's are used to select the
;CV61   Output 2 Effect(Green)  00h - FFh  desired special effect. The value
;CV62   Output 3 Effect(White)  00h - FFh  is masked with the Effect register
;CV63   Output 4 Effect(Yellow) 00h - FFh  to determine the effect.
;CV64   Output 5 Effect         00h - FFh

;       Effect Register:   Bit7  Bit6  Bit5  Bit4  Bit3  Bit2  Bit1  Bit0 
;                          1/2   1/4A  1/4B  Fwd   Rev   MARs  Strb  Dim

;       Example: 01000000 is .25sec On/.25sec Off (Phase A).
;                00100000 is .25sec Off/.25sec On (Phase B).
;                00000010 produces a strobe light effect.
;                00000000 is simple On/Off switch effect.

;       Note: effects can be ANDed together...
;                00010100 is MARs effect in Forward direction only.

;CV67-94 Speed Table Values     00h - FFh  00h is no output. FFh is 
;                                          continuous on.

        processor       16F84A

;fuses	WDT on
;	PUT off
;	HS  clock

 __CONFIG	h'3FFE' ; PUTimer off, WDT on, HS clock


;Variable definition - I/O Port assignments

inport  equ     06		;signal input 	port b
in      equ    2		;sig. input 1 	port b2 
in2	equ    3       		;sig. input 2	port b3
porprt	equ	05		;POR test 	port a	
por	equ	4		;power on test 	port a4 
mfport  equ     06		;motor fwd.   	port b0
fwd     equ    0
mrport  equ     06		;motor rev.   	port b1
rev     equ    1
pwmprt	equ	05		;PWM port	port a
pwm	equ	2		;PWM output	port a2
o1port  equ     06              ;F0 		port b4
out1    equ    4
o2port  equ     06              ;F1		port b5
out2    equ    5
o3port  equ     06              ;F2		port b6
out3    equ    6
o4port  equ     05              ;F3		port a0
out4    equ    0
o5port  equ     05              ;F4		port a1
out5    equ    1

;Variable definition - PIC16F84 control registers.

f0      equ     00
rtcc    equ     01
optreg	equ	81	;page 1
pc      equ     02
status  equ     03
carry   equ    0
zbit    equ    2
rp0     equ    5
rp1     equ    6

fsr     equ     04
porta   equ     05
ddra	equ	85	;page 1
portb   equ     06
ddrb	equ	86	;page 1
eedata  equ     08
eeadr   equ     09
eecon1  equ     08
rd      equ    0
wr      equ    1
wren    equ    2
eecon2  equ     09
pclath  equ     0A
intcon  equ     0B
f       equ    1
w       equ    0

;Varible definition - User RAM.

addcfg  equ     0C
primary equ    0
brdcst  equ    1
config  equ     0D
value   equ    0
byte4   equ    1
byte5   equ    2
service equ    3
reverse equ    4
consist equ    5
count   equ     0E
CV1     equ     0F
CV2     equ     10
CV5     equ     11
CV9     equ     12
CV11    equ     13
CV19    equ     14
CV29    equ     15
data1   equ     16
data2   equ     17
data3   equ     18
data4   equ     19
data5   equ     1A
endval  equ     1B
effect  equ     1C
functn  equ     1D
lastd1  equ     1E
lastd2  equ     1F
lastd3  equ     20
lastd4  equ     21
lastspd equ     22
light1  equ     23
light2  equ     24
pagereg equ     25
m       equ     26
mult1   equ     1E
mult2   equ     1F
multhi  equ     20
multlo  equ     21
n       equ     27
ramp    equ     28
speed   equ     29
state   equ     2A
step    equ     2B
temp    equ     2C
timerp  equ     2D
timers  equ     2E
mask1   equ     2F	;for motor damping

;Hardware status after a reset is both ports as all inputs 
;so functions and motor are off and decoder operates in DC mode.
;Init checks voltage on port b, bit 1. If lo then it was a power on
;and speed is reset. If still hi, then it was a short dropout and
;speed is not reset.
;Init1 scans for a hi / lo transition on input 1. (inport,in)
;Then checks input 2. If this is lo then it must be pulsed DC
;If it is hi then it is AC (assumed to be DCC)
;Only when a DCC signal is recognised are the ports set to outputs.
;
;Init1 also sets the rtcc counter to divide by 32 (16us at 8MHz clock).
;FSR is set to 88h for indirect access to EECON register from page 00.

Init    btfsc	porprt,por	;is it a power on or dropout?
 	goto	Init1		;dropout so carry on
 	clrf	speed		;power on so clear speed
	 clrf	config		;and config
Init1	btfss	inport,in	;if hi, look for low else wait for hi
 	goto	Init1
scan	call	del22		;delay 22 microsecs
 	btfsc	inport,in	;look for low
 	goto	scan		;try again
	btfsc	inport,in2	;check other polarity
 	goto	DCC		;must be AC
 	goto	Init1		;DC so keep looping

DCC	bsf	status,rp0	;set to page 1
 	movlw	B'11111000'	;port a0, a1 are function outputs
    				;a2 is PWM output, a4 is POR sense.
    				;a3 must be an input (not used as such)
 	movwf	ddra
 	movlw	B'00001100'	;port b2, b3 are data in, b0,b1 are direction
    				;b4, b5, b6 are function outputs
 	movwf	ddrb		
 	movlw	B'10000100'	;set option reg RTCC /32
 	movwf	optreg
 	bcf	status,rp0
 	clrf    porta

        clrf    portb
        clrf    intcon
        movlw   0x88
        movwf   fsr

        clrf    state
        clrf    m
        clrf    n
 	clrf	mask1		;for motor damping mod
 				;default is undamped

 	






;The following routine loops between Starthi and Startlo in a precisely 
;timed sequence that samples track voltage at 22us intervals, decodes the
;incoming packet, and updates the decoder outputs. When a change in 
;track voltage is detected, a half-bit is defined and the subroutine 
;Getstat is called to check the value of the half-bit and decode the 
;sequence. Subsequent delays between samplings call the update subroutine 
;to update the outputs and timing registers of the microcontoller. At 22us, 
;the values of the half-bits are determined as follows:
;
;       Delays          Possible Duration
;       1               1us  - 43us
;       2               23us - 65us
;       3               45us - 87us
;       4               67us - up
;
;With these values, one delay will be 43us or less and will reset 
;the packet decode sequence. Two or three delays will be 23us to 87us and 
;will be recognized as a hi (1) half-bit. This completely encompasses the 
;duration required by the NMRA DCC standards of 52us to 64us. Four or more 
;delays will be 67us or greater and are recognized as a low (0) half-bit.
;Again, this meets the NMRA DCC requirements of 90us to 10000us. Durations of
;~18ms in length, such as DC or when the signal is lost, will cause the
;watch dog timer to reset, reseting the decoder. 

;                               timing

Starthi call    Getval          ;3
Conthi  btfss   inport,in       ;44/0/88
        goto    Startlo         ;45/1
        btfss   m,7             ;46
        incf    m,f             ;47        
        call    Update          ;48
        goto    Conthi          ;86

Startlo call    Getval          ;3
Contlo  btfsc   inport,in       ;44/0/88
        goto    Starthi         ;45/1
        btfss   m,7             ;46
        incf    m,f             ;47       
        call    Update          ;48
        goto    Contlo          ;86

;Getval checks m for a value of 0 (reset), 1 or 2 (hi) or greater (low).
;It then checks state for a value less than or equal to 24 (18h) and then
;adds state to pc register (program counter) to offset execution to a 
;specific subroutine.

Getval  incf    n,f             ;5
        movf    m,w             ;6
        btfsc   status,zbit     ;7
        goto    Resetv          ;8
        clrwdt                  ;9
        clrf    m               ;10
        bcf     config,value    ;11
        addlw   0xFD            ;12
        btfss   status,carry    ;13
        bsf     config,value    ;14
        btfsc   status,carry    ;15
        clrf    n               ;16
        movlw   0xE7            ;17
        addwf   state,w         ;18
        btfsc   status,carry    ;19
        clrf    state           ;20
        movf    state,w         ;21
        addwf   pc,f            ;22
                                              ;state
        goto    Waitn           ;24             ;0     
        goto    Waitlo                          ;1
        goto    Testlo                          ;2

        goto    Bitset                          ;3
        goto    Lastv                           ;4
        goto    Bitset                          ;5
        goto    Lastv                           ;6
        goto    Bitset                          ;7
        goto    Lastv                           ;8
        goto    Bitset                          ;9
        goto    Lastv                           ;10
        goto    Bitset                          ;11
        goto    Lastv                           ;12
        goto    Bitset                          ;13
        goto    Lastv                           ;14
        goto    Bitset                          ;15
        goto    Lastv                           ;16
        goto    Bitset                          ;17
        goto    Endx                            ;18

        goto    End1                            ;19
        goto    End2                            ;20
        goto    End3                            ;21
        goto    End4                            ;22
        goto    End5                            ;23

;This is the last state of the packet decode sequence. It first checks for
;a high half-bit. It then XORs the five data bytes to check packet parity. 
;It then checks addcfg register flags to determine instruction address 
;and branches to CVserv or Decode.

        clrf    state           ;24        state = 24
        btfss   config,value    ;25
ret16   goto    ret14           ;26
        movf    addcfg,w        ;27
        btfsc   status,zbit     ;28
        goto    ret11           ;29
        movf    data1,w         ;30
        xorwf   data2,w         ;31
        xorwf   data3,w         ;32
        xorwf   data4,w         ;33
        xorwf   data5,w         ;34
        btfss   status,zbit     ;35	packet error
        goto    ret4            ;36
	btfsc   addcfg,service  ;37
        goto    CVserv          ;38
        clrf    n                    
        clrf    timerp
        bcf     config,service

Decode  movf    data2,w         ;Dcontrl  Spd128  CVacc   Funct   Spd28
        andlw   0xE0            ;  000     001     111     100     01D
        btfsc   status,zbit     ;xor       001     001     001     001
        goto    Dcontrl         ;equ       000     110     101     01d
        xorlw   0x20            ;xor               110     110     110
        btfsc   status,zbit     ;equ               000     011     10d
        goto    Spd128          ;xor                       011     011
        xorlw   0xC0            ;equ                       000     11D
        btfsc   status,zbit     ;and                               110
        goto    CVacc           ;equ                               110
NextD   xorlw   0x60            ;xor                               110
        btfsc   status,zbit     ;equ                               000
        goto    Funct           
        andlw   0xC0
        xorlw   0xC0    
        btfsc   status,zbit
        goto    Spd28
        return

;Nextbyt checks for multiple instructions in the packet and loops through
;the decode sequence. Only Speed and Function instructions can be 
;combined in a packet.

Nextbyt btfsc   config,byte5
        return
        btfss   config,byte4
        return
        movf    data3,w
        movwf   data2
        bcf     config,byte4    ;       Funct   Spd28
        andlw   0xE0            ;        100     01D
        xorlw   0xE0            ;xor     111     111
        goto    NextD           ;equ     011     10d

Resetv  clrf    state           ;11
        clrf    n               ;12
        goto    ret27           ;13

;Counter jumps to alternating output update routines. It is called from the
;Update routine.

Counter incf    count,f         ;55
        movf    count,w         ;56
        andlw   0x07            ;57
        addwf   pc,f            ;58

        goto    count0          ;60
        goto    count1  
        goto    count2
        goto    count0
        goto    count3
        goto    count4
        goto    count0
        goto    count5

;CVpage is for three byte service mode addressing (page addressing). It 
;uses the page register and the offset in data1 to calculate the CV number. 
;The data in data2 is moved to data3 and the calculated CV is stored in
;data2.

CVpage  movf    data2,w                
        movwf   data3
        movlw   0x07
        andwf   data1,w
        addwf   pc,f

        goto    CVfind
        goto    CVfind
        goto    CVfind
        goto    CVfind
        goto    CV29s
        goto    CVpgreg
        return
        return                                 

;MARs returns mask for mars effect on/off modulation.

MARs    swapf   light2,w        ;77
        andlw   0x0F            ;78
        addwf   pc,f            ;79

        retlw   0x0F            ;81
        retlw   0x07
        retlw   0x07
        retlw   0x03
        retlw   0x03
        retlw   0x01
        retlw   0x01
        retlw   0x00
        retlw   0x00
        retlw   0x01
        retlw   0x01
        retlw   0x03
        retlw   0x03
        retlw   0x07
        retlw   0x07
        retlw   0X0F

;Waitn waits for 20 hi half-bits (ten hi bits of the pre-amble) to start
;the decode sequence. It also reads CV1 and CV2.

Waitn   movlw   0xEC            ;26
        addwf   n,w             ;27
        btfss   status,carry    ;28
        goto    ret11           ;29	
        incf    state,f         ;30	here after 10 or more preamble cycles
        clrf    data3           ;31
        clrf    data4           ;32
        clrf    addcfg          ;33
        clrf    endval          ;34
        clrf    eeadr           ;35     EE=0    CV1
        bsf     f0,rd           ;36
        movf    eedata,w        ;37
        movwf   CV1             ;38
        incf    eeadr,f         ;39     EE=1    CV2
        bsf     f0,rd           ;40
        movf    eedata,w        ;41
        movwf   CV2             ;42
        return                  ;43



;Waitlo waits for a low bit to signal the end of the pre-amble. Also reads
;CV5 and CV29.

Waitlo  btfss   config,value    ;26
        incf    state,f         ;27
        movlw   0x02            ;28     EE=2    CV5
        movwf   eeadr           ;29
        bsf     f0,rd           ;30
        movf    eedata,w        ;31
        movwf   CV5             ;32     If CV5 = 00 or 01, then
        addlw   0xFE            ;33     complement CV5 (=FF or FE)
        btfss   status,carry    ;34
        comf    CV5,f           ;35
        movlw   0x0A            ;36     EE=A    CV29
        movwf   eeadr           ;37     
        bsf     f0,rd           ;38
        movf    eedata,w        ;39
        movwf   CV29            ;40
        nop                     ;41
        return                  ;42

;Testlo must have a low half-bit. Also reads CV9.

Testlo  incf    state,f         ;26
        btfsc   config,value    ;27
        clrf    state           ;28
        movlw   0x05            ;29     EE=5    CV9  Total PWM is [CV9+8]us.           
        movwf   eeadr           ;30                  Max is 31ms.
        bsf     f0,rd           ;31
        movf    eedata,w        ;32
        addlw   0xE8            ;33
        btfsc   status,carry    ;34
        movlw   0xFF            ;35
        addlw   0x20            ;36
        movwf   CV9             ;37
        incf    eeadr,f         ;38     EE=6    CV11  Packet Time-Out is 
        bsf     f0,rd           ;39                   [CV11]sec.
        movf    eedata,w        ;40
        movwf   CV11            ;41
        return                  ;42

;Bitset reads the value of the just finished half-bit and rotates it
;into the LSB of data5. Eight cycles through Bitset will read a 
;complete byte of data. Also reads CV19.

Bitset  incf    state,f         ;26
        bcf     status,carry    ;27
        btfsc   config,value    ;28
        bsf     status,carry    ;29
        rlf     data5,f         ;30
        movlw   0x09            ;31     EE=9    CV19   If CV19 is 00h or 88h,
        movwf   eeadr           ;32                    then consist flag is
        bsf     f0,rd           ;33                    cleared.
        movf    eedata,w        ;34
        movwf   CV19            ;35
        bcf     config,consist  ;36
        andlw   0x7F            ;37
        btfss   status,zbit     ;38
        bsf     config,consist  ;39
ret2    goto    ret0            ;40

;Lastv checks for the current half-bit to be the same as the previous
;half-bit. 

Lastv   incf    state,f         ;26
        btfss   config,value    ;27
        goto    lastv1          ;28
        btfss   data5,0         ;29
        clrf    state           ;30
 	goto    ret9            ;31	
lastv1  btfsc   data5,0         ;30
        clrf    state           ;31
ret10   goto    ret8            ;32

;Endx compares the present half-bit to the previous half-bit (same as
;lastv) and then determines the offset for the intermediate bits.

Endx    btfss   config,value    ;26
        goto    endx1           ;27
        btfss   data5,0         ;28
        comf    state,f         ;29           
        goto    endx2           ;30
endx1   btfsc   data5,0         ;29
        comf    state,f         ;30
        nop                     ;31
endx2   incf    endval,f        ;32
        movf    endval,w        ;33
        addwf   state,f         ;34
        goto    ret5            ;35

;Intermediate bit after first byte - must be low. End1 also checks for
;broadcast, idle and service mode address.

End1    movlw   0x02            ;26
        movwf   state           ;27
        movf    data5,w         ;28
        movwf   data1           ;29
        btfsc   config,value    ;30
        clrf    state           ;31
        btfsc   data1,7         ;32  if msb set, must be idle packet
        clrf    state           ;33  so start looking for preamble again
        movf    data1,w         ;34
        btfsc   status,zbit     ;35
        bsf     addcfg,brdcst   ;36
        addlw   0x90            ;37
        btfsc   status,carry    ;38
        bsf     addcfg,service  ;39
        goto    ret0            ;40

;Intermediate bit after second byte - must be low. End2 also checks for
;primary and consist address (if active).

End2    movlw   0x02            ;26
        movwf   state           ;27
        movf    data5,w         ;28
        movwf   data2           ;29
        btfsc   config,value    ;30
        clrf    state           ;31
        movf    data1,w         ;32
        xorwf   CV1,w           ;33
        btfsc   status,zbit     ;34
        bsf     addcfg,primary  ;35
        btfss   config,consist  ;36
        goto    ret3            ;37
        movf    CV19,w          ;38
        andlw   0x7F            ;39
        xorwf   data1,w         ;40
        btfsc   status,zbit     ;41
        bsf     addcfg,consist  ;42
        return                  ;43

;Intermediate bit after third byte - hi signals end of packet.

End3    btfsc   config,value    ;26
        goto    end3hi          ;27
        movlw   0x02            ;28
        movwf   state           ;29
        movf    data5,w         ;30
        movwf   data3           ;31
        goto    ret8            ;32

end3hi  movlw   0x18            ;29
        movwf   state           ;30
        bcf     config,byte4    ;31
        bcf     config,byte5    ;32
ret9    goto    ret7            ;33

;Intermediate bit after fourth byte - hi signals end of packet.

End4    btfsc   config,value    ;26
        goto    end4hi          ;27
        movlw   0x02            ;28
        movwf   state           ;29
        movf    data5,w         ;30
        movwf   data4           ;31
        goto    ret8            ;32

end4hi  movlw   0x18            ;29
        movwf   state           ;30
        bsf     config,byte4    ;31
        bcf     config,byte5    ;32
        goto    ret7            ;33

;End bit after fifth byte - must be hi.

End5    incf    state,f         ;26
        btfss   config,value    ;27
        clrf    state           ;28
        bsf     config,byte4    ;29
        bsf     config,byte5    ;30
        goto    ret9            ;31

;This subroutine is used to update the outputs of the microcontroller. It
;first checks to see if the rtcc register is >= CV9. This is the motor
;pulse-width duration CV. The pulse-width duration is calculated by
;PWD = (CV9 + 8) ms.  PWDmax = 31ms. If rtcc >= CV9 (shifted by
;32), then the ramp register is incremented. The ramp register is compared
;against the speed register to determine if the motor outputs are on or off.
;The rtcc value is added to light1 and then rtcc is reset. Light1 counts
;at the same rate as the rtcc register and rolls over every 4ms. Light2
;rolls over every 2sec and is copied to effect - the special effect output
;register. Effect is ANDed with CVs 60-64 to control the special effects
;of each function output. If the result of the AND is zero, then the 
;function is active (on). The bits of effect are as follows:
;
;        bit7    bit6    bit5    bit4     bit3    bit2    bit1    bit0
;       .5sec  .25sec  .25sec   Forward  Reverse  MARs   Strobe   Dim
;              (PhaseA)(PhaseB)
;To implement the special effects, CVs 60-64 should be set as follows:
;CV60 for output 1, CV61 for output 2, CV62 for 3, CV63 for 4, CV64 for 5.
;
;           CV Value            Effect
;           00000000            On/Off only
;           00001000            Not On when in forward direction (reverse)
;           00010000            Not On when in reverse direction (forward)
;           01000000            Phase A  .25s On/Off duration
;           00100000            Phase A complement (Phase B)  .25s duration
;           01000000            Blinking (On .25s/Off .25s)
;           00000010            Blinking (On .016s/Off .484s) Strobe
;           10000000            Blinking (On .5s/Off .5s) Beacon
;           00000100            MARs (Bright to Dim to Bright)
;           00000001            Dim light
;Effects can be ANDed together for combinations
;           01010000            Blinking in forward direction only

;Outputs 1 and 2 also have a special feature of being controlled by F1
;in addition to the other standard function setup. This allows outputs
;1 and 2 to be used for ditch lights such that when F1 is on they are
;both on and when F1 is off, they alternate. The following is an example
;of how to set up CVs for this.
;CV55 = 00010000  CV56 = 00010000  CV60 = 01010000  CV61 = 00110000
;Thus, when FL (bit 4) and F1 (bit 0) are on and the locomotive is in 
;forward direction, both output 1 and output 2 will be on. When F1 is 
;turned off, output 1 and output 2 will alternately blink.

Update  movf    CV9,w           ;50
        subwf   rtcc,w          ;51
        btfss   status,carry    ;52
        goto    Counter         ;53
        movlw   0x04            ;54
        addwf   ramp,f          ;55
        movf    CV9,w           ;56
        subwf   rtcc,f          ;57
        addwf   light1,f        ;58             light1 rolls over every
        btfss   status,carry    ;59             4ms
ret24   goto    ret22           ;60
        incf    timers,f        ;61             timers and light2 increment
        incf    light2,f        ;62             every 4ms
        btfsc   status,zbit     ;63             light2 rolls over every 1sec
        incf    timerp,f        ;64             timerp increments every 1sec
        movf    light2,w        ;65            
        andlw   0xC0            ;66             
        iorlw   0x03            ;67
        movwf   effect          ;68             
        btfss   config,reverse  ;69            
        bsf     effect,3        ;70             bit 3 is hi if forward      
        btfsc   config,reverse  ;71             (used for reverse mask)
        bsf     effect,4        ;72             bit 4 is hi if reverse  
        btfss   effect,6        ;73             bit 5 is complement of
        bsf     effect,5        ;74             bit 6 - .25sec duration 
        call    MARs            ;75
        andwf   light2,w        ;83
        btfss   status,zbit     ;84             bit 2 is mars effect
        bsf     effect,2        ;85
        return                  ;86     1/2  1/4A 1/4B  F   R   M   S   D 

;Count0 checks timing for service mode and packet timeout. It also uses
;ramp register to determine motor output pulse - on when speed > ramp.

count0  movlw   0xFB            ;62
        addwf   timers,w        ;63          
        btfsc   status,carry    ;64
        bcf     config,service  ;65
        movf    CV11,w          ;66
        btfsc   status,zbit     ;67
        goto    c0cont1         ;68
        subwf   timerp,w        ;69
        btfsc   status,carry    ;70
        clrf	speed           ;71	packet time out
c0cont2 movf    speed,w         ;72
        subwf   ramp,w          ;73
        btfsc   status,carry    ;74
        goto    off		;75
	btfss   config,reverse  ;76
	goto    forward         ;77
        bcf     mfport,fwd      ;78
        bsf     mrport,rev      ;79
	bsf	pwmprt,pwm	;80	turn on PWM
ret4    movf    light2,w        ;81
        andlw   0x78            ;82
        btfsc   status,zbit     ;83
        bcf     effect,1        ;84                     Bit 1 is Strobe
        return                  ;85

c0cont1 goto    c0cont2         ;70



forward bcf     mrport,rev      ;79
        bsf     mfport,fwd      ;80
	bsf	pwmprt,pwm	;81	turn on
	goto	ret0		;82

ret3    goto    ret1            ;81             
        






off     bcf     pwmprt,pwm      ;77	PWM off
 	movf	mask1,w		;78
 	iorwf	mfport,f	;79	short motor
 	nop  			;80
        goto	ret1       	;81
       	



;Count1 controls output1 by ANDing CV55 with functn register - on if not
;zero. It then checks output function by ANDing CV60 with effect - on if
;result is zero. Output 1 is also on if function 1 is on (functn bit 0).

count1  movlw   0x11            ;62
        movwf   eeadr           ;63
        bsf     f0,rd           ;64
        movf    eedata,w        ;65
        andwf   functn,w        ;66
        btfsc   status,zbit     ;67
        goto    off1a           ;68
        btfsc   functn,0        ;69
        goto    on1a            ;70
        movlw   0x16            ;71
        movwf   eeadr           ;72
        bsf     f0,rd           ;73
        movf    eedata,w        ;74     
        andwf   effect,w        ;75
        btfss   status,zbit     ;76
        goto    off1b           ;77
        bsf     o1port,out1     ;78
ret5    movf    light2,w        ;79
        andlw   0x06            ;80
        btfsc   status,zbit     ;81
        bcf     effect,0        ;82                     Bit 0 is Dim
ret1    nop                     ;83
ret0    return                  ;84

ret5a   movf    light2,w       	;78
        andlw   0x06            ;79
        btfsc   status,zbit     ;80
        bcf     effect,0        ;81                     Bit 0 is Dim
 	nop			;82
 	nop			;83
        return                  ;84

on1a    bsf     o1port,out1     ;72
        goto    ret9            ;73

off1a   bcf     o1port,out1     ;70
        goto    ret11           ;71

off1b   bcf     o1port,out1     ;79
        goto    ret2            ;80

;Count2 controls output2 by ANDing CV56 with functn register - on if not
;zero. It then checks output function by ANDing CV61 with effect - on if
;result is zero. Output 2 is also on if function 1 is on (functn bit 0).

count2  movlw   0x12            ;62
        movwf   eeadr           ;63
        bsf     f0,rd           ;64
        movf    eedata,w        ;65
        andwf   functn,w        ;66
        btfsc   status,zbit     ;67
        goto    off2a           ;68
        btfsc   functn,0        ;69
        goto    on2a            ;70
        movlw   0x17            ;71
        movwf   eeadr           ;72
        bsf     f0,rd           ;73
        movf    eedata,w        ;74     
        andwf   effect,w        ;75
        btfss   status,zbit     ;76
        goto    off2b           ;77
        bsf     o2port,out2     ;78
        goto    ret3            ;79

on2a    bsf     o2port,out2     ;72
ret11   btfss	CV29,6          ;73
	goto	setmot		;74
	movlw	b'00000011'	;75
	movwf	mask1		;76
	goto	ret5		;77
setmot	clrf	mask1		;76
	goto	ret5		;77

off2a   bcf     o2port,out2     ;70
        goto    ret11           ;71

off2b   bcf     o2port,out2     ;79
        goto    ret2            ;80

;Count3 controls output3 by ANDing CV57 with functn register - on if not
;zero. It then checks output function by ANDing CV62 with effect - on if
;result is zero.

count3  movlw   0x13            ;62
        movwf   eeadr           ;63
        bsf     f0,rd           ;64
        movf    eedata,w        ;65
        andwf   functn,w        ;66
        btfsc   status,zbit     ;67
        goto    off3a           ;68
        movlw   0x18            ;69
        movwf   eeadr           ;70
        bsf     f0,rd           ;71
        movf    eedata,w        ;72     
        andwf   effect,w        ;73
        btfss   status,zbit     ;74
        goto    off3b           ;75
        bsf     o3port,out3     ;76
        goto    ret5            ;77

off3a   bcf     o3port,out3     ;70
        goto    ret11           ;71

off3b   bcf     o3port,out3     ;77
        goto    ret4            ;78

;Count4 controls output 4 by ANDing CV58 with functn register - on if not
;zero. It then checks output function by ANDing CV63 with effect - on if
;result is zero.

count4  movlw   0x14            ;62
        movwf   eeadr           ;63
        bsf     f0,rd           ;64
        movf    eedata,w        ;65
        andwf   functn,w        ;66
        btfsc   status,zbit     ;67
        goto    off4a           ;68
        movlw   0x19            ;69
        movwf   eeadr           ;70
        bsf     f0,rd           ;71
        movf    eedata,w        ;72
        andwf   effect,w        ;73
        btfss   status,zbit     ;74
        goto    off4b           ;75
        bsf     o4port,out4     ;76
        goto    ret5            ;77

off4a   bcf     o4port,out4     ;70
        goto    ret11           ;71

off4b   bcf     o4port,out4     ;77
        goto    ret4            ;78

;Count5 controls output 5 by ANDing CV59 with functn register - on if not
;zero. It then checks output function by ANDing CV64 with effect - on if
;result is zero.

count5  movlw   0x15            ;62
        movwf   eeadr           ;63
        bsf     f0,rd           ;64
        movf    eedata,w        ;65
        andwf   functn,w        ;66
        btfsc   status,zbit     ;67
        goto    off5a           ;68
        movlw   0x1A            ;69
        movwf   eeadr           ;70
        bsf     f0,rd           ;71
        movf    eedata,w        ;72
        andwf   effect,w        ;73
        btfss   status,zbit     ;74
        goto    off5b           ;75
        bsf     o5port,out5     ;76     
ret7    goto    ret5            ;77        

off5a   bcf     o5port,out5     ;70 
ret13   goto    ret11           ;71

off5b   bcf     o5port,out5     ;77 
ret6    goto    ret4            ;78

;Additional goto sequences.

ret27   goto    ret25           ;15 
ret25   goto    ret23           ;17
ret23   goto    ret21           ;19
ret22   goto    ret20           ;20 62
ret21   goto    ret19           ;21 63
ret20   goto    ret18           ;22 64
ret19   goto    ret17           ;23 65
ret18   goto    ret16           ;24 66
ret17   goto    ret15           ;25 67
ret15   goto    ret13           ;27 69
ret14   goto    ret12           ;28 70
ret12   goto    ret10           ;30 72
ret8    goto    ret6            ;34 76


;CVserv checks for service mode instructions with the decoder in service
;mode. It then checks values of data1, data2, data3 and data4 with previous
;values to ensure a duplicate packet has been sent. It then checks for
;three or four byte packet to determine paged or direct CV access. 

CVserv  btfss   config,byte5    ;40
        btfss   config,service  ;41
        return                  ;42
        clrf    n
        clrf    timers
        call    Twonrow
        iorlw   0x00
        btfsc   status,zbit
        return
        btfss   config,byte4
        goto    CVpage
        movf    data1,w
        xorlw   0x74
        btfsc   status,zbit
        goto    Ver1
        xorlw   0x08
        btfss   status,zbit
        return

;Wr1 writes the data in data3 into the CV listed in data2. If the CV
;number in data2 is 06h (CV7) or 07h (CV8), then the write does not take 
;place. If the value is 1Ch (CV29), then data3 is masked to change only 
;bit 0 and bit 4 and set bit 1. If the EE register returned by Findee
;is 3Fh, then the CV is not implemented and the write does not place.

Wr1     movf    data3,w
        movwf   eedata
        movf    data2,w
        xorlw   0x06                    ;  CV7      CV8      CV29
        btfsc   status,zbit             ;00000110 00000111 00011100
        return                          ;00000110 00000110 00000110
        xorlw   0x01                    ;00000000 00000001 00011010
        btfsc   status,zbit             ;         00000001 00000001
        return                          ;         00000000 00011011
        xorlw   0x1B                    ;                  00011011
        btfss   status,zbit             ;                  00000000
        goto    wrcont
        movlw   B'01010001'		;mask CV29 bits
        andwf   eedata,f
        bsf     eedata,1
wrcont  movf    data2,w
        call    Findee
        clrf    pclath
        movwf   eeadr
        xorlw   0x3F
        btfsc   status,zbit
        return
        clrwdt
        bsf     status,rp0
        bsf     eecon1,wren
        call    EEwrite
        goto    Ackn

;Two in a row checks that the current packet is the second identical packet
;before performing a service mode instruction or Advanced programming
;function.

Twonrow movf    data1,w        
        xorwf   lastd1,w
        btfss   status,zbit
        goto    Lastpak
        movf    data2,w
        xorwf   lastd2,w
        btfss   status,zbit
        goto    Lastpak
        movf    data3,w
        xorwf   lastd3,w
        btfss   status,zbit
        goto    Lastpak
        movf    data4,w
        xorwf   lastd4,w
        btfsc   status,zbit
        retlw   0xFF

;Lastpak saves the packet byte values to check for a repeated packet,
;necessary to execute a service mode instruction.

Lastpak movf    data1,w
        movwf   lastd1
        movf    data2,w
        movwf   lastd2
        movf    data3,w
        movwf   lastd3
        movf    data4,w
        movwf   lastd4
        retlw   0x00                 

;CV29s sets data2 to 1Ch (28).    

CV29s   movlw   0x1C
        movwf   data2
        goto    CVcont

;CVfind determines the CV using the page register and the offset in the
;insruction. If the page is greater than 31 then CV13 is used. CV13 is the 
;generic register set at 00h used to compare all unused CVs.

CVfind  decf    pagereg,w
        movwf   data2
        bcf     status,carry
        rlf     data2,f
        btfsc   status,carry
        return
        rlf     data2,f
        btfsc   status,carry
        return
        movlw   0x03
        andwf   data1,w
        addwf   data2,f
CVcont  btfss   data1,3
        goto    Ver1
        goto    Wr1

;CVpgreg verifies or writes the page register with data3 (data2).

CVpgreg btfss   data1,3
        goto    Pagever
        movf    data3,w
        movwf   pagereg
        return

Pagever movf    pagereg,w                        
        xorwf   data3,w                            
        btfss   status,zbit
        return
        goto    Ackn

;CVverfy XORs the EE value at data2 with the value in data3. The subroutine
;findee is a look up table for CVs and their respective EE address.

Ver1    movf    data2,w         
        call    Findee
        clrf    pclath
        movwf   eeadr
        call    EEread
        xorwf   data3,w
        btfss   status,zbit
        return
        goto    Ackn

;This decodes the Decoder & Consist Control instructions 000XXXXX.

Dcontrl btfsc   config,byte5    ;not DContrl or Consist if there is a fifth
        return
        movf    data2,w         ;get Instruction byte ready in any case
        btfsc   config,byte4    ;DContrl if there is no fourth byte
        goto    ConCont         ;Consist Control if there is
        btfsc   status,zbit     ;Dreset   Hreset   Ackn
        goto    Dreset          ;00000000 00000001 00001111
        xorlw   0x01            ;     xor 00000001 00000001
        btfsc   status,zbit     ;     equ 00000000 00001110
        goto    Hreset          ;     xor          00001110
        xorlw   0x0E            ;     equ          00000000
        btfsc   status,zbit
        goto    Ackn
        return            

ConCont xorlw   0x12            ;Consist Instruction 0001001X
        andlw   0xFE            ;ignore bottom bit for detection
        btfss   status,zbit
        return
        call     Twonrow        ;check for two packets identical
        iorlw    0x00           ;wait for status to catch up
        btfsc    status, zbit   ;returns 00 if not equal, FF if equal
        return                  ;do nothing this time, wait for second
        btfsc    data3,7        ;check for valid baseline addresses < 128
        return
        movf     data3,w        ;get config address into w
        btfsc    status,zbit    ;check for 'de-consist' address 0
        goto     WrtCon         ;no direction to include if 0
        btfsc    data2,0        ;get direction bit from instruction
        iorlw    0x80           ;reverse direction into top bit
WrtCon  movwf    eedata         ;store data for eeprom
        movlw    0x09           ;ee address for CV19
        movwf    eeadr          ;ee code copied from other routines
        bsf      status,rp0
        bsf      eecon1,wren
        call     EEwrite
        return                  ;without annoying acknowledges

;Dreset clears speed and functions and sets decoder into service mode by
;setting service flag and clearing timers register.

Dreset  clrf    functn           
        clrf    speed          
        btfss   addcfg,brdcst   
        return            
        bsf     config,service  
        clrf    timers          
        goto    Nextbyt            

;Hreset clears speed and functions then sets CV19 to 00h and CV29 to 02h
;using EE write process.

Hreset  clrf    speed                           
        clrf    functn
        movlw   0x09
        movwf   eeadr
        clrf    eedata
        bsf     status,rp0
        bsf     eecon1,wren
        call    EEwrite
        movlw   0x0A
        movwf   eeadr
        movlw   0x02                    ;default for CV29 is 02h
        movwf   eedata
        bsf     status,rp0
        bsf     eecon1,wren
        call    EEwrite

;Ackn sets motor on for 5ms (1024us X 5). 1024us is counted by
;bit 6 of rtcc register.

Ackn    clrwdt
        bsf     mfport,fwd
        bcf     mrport,rev
 bsf	pwmprt,pwm
        bsf     o1port,out1
        bsf     o2port,out2
        clrf    rtcc
        movlw   0x05           
        movwf   temp
aloop   btfss   rtcc,6
        goto    aloop
        bcf     rtcc,6
        decfsz  temp,f
        goto    aloop
        bcf     pwmprt,pwm
        bcf     o1port,out1
        bcf     o2port,out2
        clrf    timers
        return

;This decodes the 128 speed step instuction 00111111 DDDDDDDD. It first 
;checks for a 4 byte packet with data2 being 00111111. It then checks
;whether the address (data1) was a broadcast (00000000), primary, or 
;consist. If data1 is primary address, then it checks for CV19 to be 
;clear. If CV19 is not clear, then it checks for data1 to be a consist
;address and also sets direction according to bit 7 of CV19. It then 
;checks for reverse direction in instuction (data3 bit 7) and reverse
;direction in CV29. Speed is found by taking speed step in instuction
;and multiplying it by speed range (Vhigh-Vlow).

Spd128  btfss   config,byte4            
        return                          
        movlw   0x3F
        xorwf   data2,w
        btfss   status,zbit
        return
        call    Spd_dir
        xorlw   0x00
        btfsc   status,zbit
        goto    chk5
        movlw   0x10
        btfss   data3,7
        xorwf   config,f

        movlw   0x7F
        andwf   data3,f
        btfsc   status,zbit
        goto    stop128		;speed zero
        decf    data3,f    
        btfsc   status,zbit
        goto    stop128		;speed one
        decf    data3,w
        movwf   mult1
        movf    CV2,w                                
        subwf   CV5,w                                 
        btfss   status,carry
        clrw
        movwf   mult2
        call    Multply
        rlf     multlo,f
        rlf     multhi,w
        addwf   CV2,w
        movwf   speed
        movwf   lastspd


chk5    btfss   config,byte5
        return
        bcf     config,byte5
        movf    data4,w
        movwf   data3
        goto    Nextbyt

stop128 movlw	0		;clear speeds
 movwf   speed
        movwf   lastspd


        goto    chk5

;Funct sets the functn register with the value of the function instruction.
;This is used to mask with the output control CV's.

Funct   btfsc   config,byte5
        return
        btfsc   addcfg,primary
        goto    funct1
        btfsc   addcfg,consist
        goto    Nextbyt
funct1  movf    data2,w
        movwf   functn
        goto    Nextbyt

;Spd_dir sets the direction based on CV29 and CV19 and validates operation.

Spd_dir movlw   0x10                    ;Bit 4 of config is reverse flag.
        btfsc   config,consist
        goto    spddir3
spddir1 bcf     config,reverse
spddir2 btfsc   CV29,0                  ;Bit 0 of CV29 is reverse direction.
        xorwf   config,f   
        retlw   0xFF
spddir3 btfsc   addcfg,brdcst
        goto    spddir1
        btfss   addcfg,consist
        retlw   0x00
        bcf     config,reverse
        btfsc   CV19,7
        xorwf   config,f
        goto    spddir2

;CVacc is used for operations mode programming "on the main". Two identical
;packets must be sent.

CVacc   btfss   addcfg,brdcst
        btfsc   addcfg,primary
        goto    cva1
        return
cva1    btfss   config,byte5
        return
        movf    data2,w
        movwf   data1
        andlw   0xF7
        xorlw   0xE4
        btfss   status,zbit
        return
        call    Twonrow
        iorlw   0x00
        btfsc   status,zbit
        return
        movf    data3,w
        movwf   data2
        movf    data4,w
        movwf   data3
        btfss   data1,3
        goto    Ver1
        goto    Wr1

;This decodes the 28 speed step instruction 01DSSSSS. It first checks
;for address type. If address is primary, then CV19 must be clear. If
;CV19 is not clear then consist flag must be set and it then checks for
;direction flags in CV19 bit 7, CV29 bit 0 and instruction (data2) bit 5.
;Speed step is determined by shifting data2 and setting bit 0 to equal
;bit4. The value FCh is added and the carry flag checked to determine
;if it is a stop instruction. The result is the calculated speed step.
;This speed step is then multiplied by the speed step (increment per
;speed step) and shifted to the left to get the actual speed value. 
;If speed table flag is set (CV20 bit 4) then the speed step is used to 
;find the CV value and read from the EE memory. The speed value is 
;checked against the previous speed value to determine if an intermediate 
;speed is to be used.

Spd28   btfsc   config,byte5    
        return            
        call    Spd_dir
        xorlw   0x00
        btfsc   status,zbit
        goto    Nextbyt
        movlw   0x10
        btfss   data2,5
        xorwf   config,f

        clrf    step            ;step is used in the 28 speed step 
        movlw   0x97            ;instruction to determine speed curve.
        movwf   mult1           ;step = 151 X (CV5-CV2) / 256
        movf    CV2,w                
        subwf   CV5,w           ;Speed = (### - 1)  X (CV5-CV2) / 27 + CV2
        btfss   status,carry    ;      = (### - 1)  X step / 16 + CV2
        goto    spdcont                 
        movwf   mult2           ;If CV2 >= CV5 then step = 00h
        call    Multply
        movf    multhi,w
        movwf   mult2

spdcont call    Update

        bcf     status,carry
        btfsc   data2,4
        bsf     status,carry
        rlf     data2,w
        andlw   0x1F
        movwf   mult1
        movlw   0xFC
        addwf   mult1,f
        btfss   status,carry
        goto    Stop
        btfsc   CV29,4
        goto    Spdcurv

        call    Multply
        rlf     multlo,f
        rlf     multhi,f
        rlf     multlo,f
        rlf     multhi,f
        rlf     multlo,f
        rlf     multhi,f
        rlf     multlo,f
        rlf     multhi,w
        addwf   CV2,w
        movwf   speed  
        goto    Chklast

Stop    clrf    speed
        btfss   mult1,1
        goto    Chklast
        clrf    lastspd
        goto    savspd		;Nextbyt

Spdcurv movlw   0x1B
        addwf   mult1,w
        movwf   eeadr
        call    EEread
        movwf   speed

Chklast movf    speed,w
        xorwf   lastspd,w
        btfsc   status,zbit
        goto    savspd		;Nextbyt
        movf    speed,w
        addwf   lastspd,f
        rrf     lastspd,w
        movwf   temp
        movf    speed,w
        movwf   lastspd 
        movf    temp,w
        movwf   speed
savspd	movf	speed,w


        goto    Nextbyt

;Multply is a shift and add multiplication routine. Inputs are mult1 and 
;mult2, outputs are multlo and multhi.

Multply clrf    multhi
        clrf    multlo
        clrf    temp
        movlw   0x08
        movwf   count                                   
loopm   rrf     mult1,f                               
        btfss   status,carry                            
        goto    nextm
        movf    temp,w
        addwf   multhi,f
        movf    mult2,w
        addwf   multlo,f
        btfsc   status,carry
        incf    multhi,f
nextm   bcf     status,carry
        rlf     mult2,f                         
        rlf     temp,f                          
        decfsz  count,f                 
        goto    loopm
        return

del22	movlw	.14		;short delay loop for reset
 movwf	count
del22a	decfsz	count,f
 goto	del22a
 return



;Generic EE write subroutine that writes eedata into eeadr. If the processor
;is busy with a previous write operation, the subroutine returns without
;writing. Inputs are eeadr and eedata. Write enable must be set.

EEwrite movlw   0x55
        movwf   eecon2
        movlw   0xAA
        movwf   eecon2
        bsf     eecon1,wr
eewrcon btfsc   eecon1,wr
        goto    eewrcon
        bcf     eecon1,wren
        bcf     status,rp0
        return





;EEread uses the file selct register to read the data stored in the EE
;memory location pointed to by eeadr.

EEread  bsf     f0,rd
        movf    eedata,w
        return

;Findee maps the CV value transferred in the w register to an EE memory
;address and returns this value in the w register. This value can then
;be moved to the eeadr register for EE read and write operations. If CV
;value is >97 then 3F is returned.

        org     0x3A0

Findee  movwf   temp            ;CV1-CV29  CV30-CV48  CV49-CV94  CV95+
        addlw   0xE3            ; 00  1C    1D   2F    30   5D    5E
        btfss   status,carry    ; E3  E3    E3   E3    E3   E3    E3
        goto    find1           ; E3  FF   +00  +12   +13  +40   +41
        addlw   0xBF            ;           BF   BF    BF   BF    BF
        btfsc   status,carry    ;           BF   D1    D2   FF   +00
        retlw   0x3F            ;           2E   2E    2E   2E
        addlw   0x2E            ;           ED   FF   +00  +2D
        btfss   status,carry    ;
        retlw   0x3F            ;                      30   5D
        movlw   0xED            ;                      ED   ED
        addwf   temp,f          ;                     +1D  +4A
find1   movlw   0x03
        movwf   pclath
        movf    temp,w
        addwf   pc,f

               ;EEadd    CV#   offset

        retlw   0x00    ;CV1     00
        retlw   0x01    ;CV2     01
        retlw   0x3F    ;        02
        retlw   0x3F    ;        03
        retlw   0x02    ;CV5     04
        retlw   0x3F    ;        05
        retlw   0x03    ;CV7     06
        retlw   0x04    ;CV8     07
        retlw   0x05    ;CV9     08
        retlw   0x3F    ;        09
        retlw   0x06    ;CV11    0A
        retlw   0x3F    ;        0B
        retlw   0x3F    ;        0C
        retlw   0x3F    ;        0D
        retlw   0x3F    ;        0E
        retlw   0x3F    ;        0F
        retlw   0x07    ;CV17    10
        retlw   0x08    ;CV18    11
        retlw   0x09    ;CV19    12
        retlw   0x3F    ;        13
        retlw   0x3F    ;        14
        retlw   0x3F    ;        15
        retlw   0x3F    ;        16
        retlw   0x3F    ;        17
        retlw   0x3F    ;        18
        retlw   0x3F    ;        19
        retlw   0x3F    ;        1A
        retlw   0x3F    ;        1B
        retlw   0x0A    ;CV29    1C
        retlw   0x0B    ;CV49    1D
        retlw   0X0C    ;CV50    1E
        retlw   0x0D    ;CV51    1F
        retlw   0x0E    ;CV52    20
        retlw   0x0F    ;CV53    21
        retlw   0x10    ;CV54    22
        retlw   0x11    ;CV55    23
        retlw   0x12    ;CV56    24
        retlw   0x13    ;CV57    25
        retlw   0x14    ;CV58    26
        retlw   0x15    ;CV59    27
        retlw   0x16    ;CV60    28
        retlw   0x17    ;CV61    29
        retlw   0x18    ;CV62    2A
        retlw   0x19    ;CV63    2B
        retlw   0x1A    ;CV64    2C
        retlw   0x3F    ;        2D
        retlw   0x3F    ;        2E
        retlw   0x1B    ;CV67    2F       
        retlw   0x1C    ;CV68    30
        retlw   0x1D    ;CV69    31
        retlw   0x1E    ;CV70    32
        retlw   0x1F    ;CV71    33
        retlw   0x20    ;CV72    34
        retlw   0x21    ;CV73    35
        retlw   0x22    ;CV74    36
        retlw   0x23    ;CV75    37
        retlw   0x24    ;CV76    38
        retlw   0x25    ;CV77    39
        retlw   0x26    ;CV78    3A                      
        retlw   0x27    ;CV79    3B
        retlw   0x28    ;CV80    3C                    
        retlw   0x29    ;CV81    3D
        retlw   0x2A    ;CV82    3E
        retlw   0x2B    ;CV83    3F
        retlw   0x2C    ;CV84    40
        retlw   0x2D    ;CV85    41
        retlw   0x2E    ;CV86    42
        retlw   0x2F    ;CV87    43
        retlw   0x30    ;CV88    44
        retlw   0x31    ;CV89    45
        retlw   0x32    ;CV90    46
        retlw   0x33    ;CV91    47
        retlw   0x34    ;CV92    48                      
        retlw   0x35    ;CV93    49
        retlw   0x36    ;CV94    4A
;
;	set EEPROM default values
;
 org	0x2100
CV1_E	de	3	;primary address
CV2_E	de	1	;Start voltage
CV5_E	de	0	;Hi voltage (maximum)
CV7_E	de	.102	;Version 10.2
CV8_E	de	.13	;DIY
CV9_E	de	7	;PWM time
CV11_E	de	0	;Timeout (secs)
CV17_E	de	0	;?
CV18_E	de	0	;?
CV19_E	de	0	;consist address
CV29_E	de	2	;config
CV49_E	de	0	;spare
CV50_E	de	0	;spare
CV51_E	de	0	;spare
CV52_E	de	0	;spare
CV53_E	de	0	;spare
CV54_E	de	0	;spare
CV55_E	de	B'00010000'	;out 1 controlled by F0
CV56_E	de	B'00000001'	;out 2 controlled by F1
CV57_E	de	B'00000010'	;out 3 controlled by F2
CV58_E	de	B'00000100'	;out 4 controlled by F3
CV59_E	de	B'00010000'	;out 5 controlled by F0
CV60_E	de	0	;out 1 on/off
CV61_E	de	0	;out 2 on/off
CV62_E	de	0	;out 3 on/off
CV63_E	de	0	;out 4 on/off
CV64_E	de	B'10000000'	;out 5 slow flash
CV67_E	de	1	;start of 28 step speed table
CV68_E	de	6	;based on Lenz curve
CV69_E	de	.12
CV70_E	de	.16
CV71_E	de	.20
CV72_E	de	.24
CV73_E	de	.28
CV74_E	de	.32
CV75_E	de	.36
CV76_E	de	.42
CV77_E	de	.48
CV78_E	de	.54
CV79_E	de	.60
CV80_E	de	.68
CV81_E	de	.76
CV82_E	de	.84
CV83_E	de	.92
CV84_E	de	.102
CV85_E	de	.112
CV86_E	de	.124
CV87_E	de	.136
CV88_E	de	.152
CV89_E	de	.168
CV90_E	de	.188
CV91_E	de	.208
CV92_E	de	.230	
CV93_E	de	.252
CV94_E	de	.255	;end of speed table
 end


