;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