;Dbacc5; Merg-AuroTrains accessory decoder with PIC16F628. ; Based on original loco decoder program by D Probst ; Porting to PIC16F628 by Stefano Curtarolo (10NOV01) ; web: http://nietzsche.mit.edu/auro/trains/tech/DCC/ ; Developed with GNU LINUX FREE SOFTWARE: www.gnupic.org ; Modifications by M. Bolton (2DEC98) and G.Ising (16OCT00) ; MERG-DCC http://home.freeuk.net/merg/resources/dcc.htm ; Modified by Stefano Curtarolo (1NOV01) ; Accessory decoder configuration variable access istruction ; http://www.tttrains.com/nmradcc/rp921.html#accessory_packets ; was added. NCE and SYS1 systems uses that protocol in accessory ; OPS mode (prog-7-enter). ; For other DCC projects of Stefano Curtarolo pleas look @ MIT ; web: http://nietzsche.mit.edu/auro/trains/tech/DCC/ ; Program is intended to be used with the accessory decoder design ; by M Bolton. The decoder is opto isolated so the ack function is a LED ; on the decoder board itself. No power booster is required but the signals ; can be taken from the track if desired. ; A separate 20v AC power supply is needed. ; Decoder includes circuitry to drive solenoid ; point motors using a capacitor discharge technique. ; ; Tested with one set of four switches, with all addresses. ; Seems OK so far. ; ; Schematic, PCB layout and source listing (+ HEX file) available. Contact ; Mike Bolton at bolton@fs1.with.man.ac.uk. ; ; Details of a matching accessory encoder are also available. ; ; ;This is code for a PIC16F628. This program will read three, four, ;and five byte packets and supports paged ;and direct CV servTRK mode access of CV data. ; ;The decoder follows the NMRA standard for an Accessory Decoder. It controls ;four pairs of outputs with on times set by the CVs in increments of ;10 millisecs. Range is 10 ms to 2.54 sec.or continuous. ; ;Supports 9 bit addressing.(3 byte packets) at present. ;The processor is configured to operate at 8MHz. ;When programming,the fuses should be set with HS clock, WDT On. ; ;The following NMRA defined CV's and ranges are supported... ;CV513 Lower 6 address bits 00h - 3Fh ;CV514 Auxiliary activation 00h - FFh Bits 0 to 7.Each bit sets an output. ; 1 is active, 0 is inactive ;CV515 F1 function 'on' time 00h - FFh Time in 10ms steps. 0 is continuous. ;CV516 F2 ;CV517 F3 ;CV518 F4 ;CV519 Version Number 00h -FFh Cannot be changed (same as CV8) ;CV520 Manufacturers ID 00h -FFh Cannot be changed (same as CV9) ; ;CV521 Upper 3 bits of 00h -07h ; address ;CV541 Configuration Bit 7 = 1 Cannot be changed (same as CV29) ; No other CVs are supported. processor 16F628 __CONFIG h'3F26' ; PUTimer on, WDT on, HS clock ;Variable definition - I/O Port assignments ;F1a equ PORTA,0 ;pin 17 ;F1b equ PORTA,1 ;pin 18 ;F2a equ PORTA,2 ;pin 1 ;F2b equ PORTA,3 ;pin 2 ;F3a equ PORTB,0 ;pin 6 ;F3b equ PORTB,1 ;pin 7 ;F4a equ PORTB,2 ;pin 8 ;F4b equ PORTB,3 ;pin 9 ;ackout equ PORTB,6 ;pin 12 (acknowledge) ;dat equ PORTB,7 ;DCC data in ; Variable definition - PIC16F628 control registers. ; Updated bu Stefano Curtarolo. Note the EEDATA and ; EEADR are in bank1, but the addresses ; 70h-7Fh, F0h-FFh, 170h-17Fh,1F0h-1FFh are in common ; between banks. f equ 1 W equ 0 TMR0 equ 01h PC equ 02h STATUS equ 03h ; STATUS Carry equ 0 ; STATUS Zbit equ 2 ; STATUS RP0 equ 5 ; STATUS RP1 equ 6 ; STATUS FSR equ 04h PORTA equ 05h PORTB equ 06h PCLATH equ 0Ah INTCON equ 0Bh ; INTCON GIE equ 7 PIR1 equ 0Ch TMR1L equ 0Eh TMR1H equ 0Fh T1CON equ 10h TMR2 equ 11h T2CON equ 12h CCPR1L equ 15h CCPR1H equ 16h CCP1CON equ 17h RCSTA equ 18h TXREG equ 19h RCREG equ 1Ah CMCON equ 1Fh f equ 1 W equ 0 EEDATA0 equ 7Eh EEADR0 equ 7Fh OPTIONR equ 81h ;page 1 TRISA equ 85h ;page 1 TRISB equ 86h ;page 1 PIE1 equ 8Ch PCON equ 8Eh PR2 equ 92h TXSTA equ 98h SPBRG equ 99h EEDATA equ 9Ah EEADR equ 9Bh EECON1 equ 9Ch RD equ 0 WR equ 1 WREN equ 2 WRERR equ 3 EECON2 equ 9Dh EEDATA1 equ 0xFE EEADR1 equ 0xFF ;Varible definition - User RAM. addcfg equ 0x20 ;address configuration primary equ 0 ;accessory address match reset equ 1 ;reset packet brdcst equ 2 ;accessory broadcast servTRK equ 3 servOPS equ 4 idle equ 5 config equ 0x21 value equ 0 byte4 equ 1 ;not used yet byte5 equ 2 ;not used yet ;registers count equ 0x22 ;counts which output CV513a equ 0x23 ;holds CV513 low address bits CV521a equ 0x24 ;holds CV521 high address bits CV514a equ 0x25 ;which outputs to activate CV541a equ 0x26 ;config CV data1 equ 0x27 ;first packet byte data2 equ 0x28 ;se8cond packet byte data3 equ 0x29 data4 equ 0x2A data5 equ 0x2B endval equ 0x2C lastd1 equ 0x2D lastd2 equ 0x2E lastd3 equ 0x2F lastd4 equ 0x30 action equ 0x31 ;4 bits of accessory command tick1 equ 0x32 ;counts 10 millisec intervals time1 equ 0x33 ;on time for output 1 etc. time2 equ 0x34 time3 equ 0x35 time4 equ 0x36 time5 equ 0x37 time6 equ 0x38 time7 equ 0x39 time8 equ 0x30 pagereg equ 0x3A m equ 0x3B ;as in Dean Probst's decode n equ 0x3C state equ 0x3D temp equ 0x3E ;Init sets as all outputs, pin b7 as input and the rest of PORTB as ;outputs and sets the TMR0 counter to divide by 32 (16us at 8MHz clock). ;FSR is set to 88h for indirect access to EECON register from page 00. Init bcf STATUS,RP1 ;set off banks2,3 bsf STATUS,RP0 ;set to page 1 ; movlw B'00010000' ;port a0-3 outputs a4input STEFANO-MERG movlw B'00000000' ;port a outputs MERG-STEFANO movwf TRISA ; movlw B'00000000' ;port b0-8 outputs STEFANO-MERG movlw B'10000000' ;port b 7 is data in MERG-STEFANO movwf TRISB movlw B'10000100' ;set option reg TMR0 /32 movwf OPTIONR bcf STATUS,RP0 ; set to page 0 movlw B'00000111' ; movwf CMCON ; turn comparstors OFF clrf PORTA clrf PORTB clrf INTCON movlw 0x88 movwf FSR clrf state clrf m clrf n clrf config clrf action ; call reset ;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 ;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 PORTB,7 ;44/0/88 MERG-STEFANO ;Conthi btfss PORTA,4 ;44/0/88 STEFANO-MERG goto Startlo ;45/1 btfss m,7 ;46 incf m,f ;47 call Update ;48 goto Conthi ;86 Startlo call Getval ;3 Contlo btfsc PORTB,7 ;44/0/88 MERG-STEFANO ;Contlo btfsc PORTA,4 ;44/0/88 STEFANO-MERG 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 CVservTRK 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 goto ret4 ;36 btfsc addcfg,servOPS goto CVservOPS ; if(SERVOPS_MODE) goto CVservOPS btfsc addcfg,servTRK ;37 goto CVservTRK ;38 clrf n ;39 bcf config,servTRK ;40 bcf config,servOPS ;40 Decode ;btfsc addcfg,primary ;nop movf data2,w ;Dcontrl action andlw 0xE0 ;000 btfsc STATUS,Zbit ;reset packet goto Dcontrl btfss data2,7 ;accessory instruction? goto noacc movf data2,w ;recover byte andlw B'00001111' ;mask movwf action ;decoder instruction (four bits) bsf action,7 ;set new action noacc return Nextbyt return 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 movlw B'00000111' ;56 andwf count,w ;57 addwf PC,f ;58 goto count1 ;60 goto count2 goto count3 goto count4 goto count5 goto count6 goto count7 goto count8 ;CVpage is for three byte servTRK 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 CV541s goto CVpgreg return return ; ;Waitn waits for 20 hi half-bits (ten hi bits of the pre-amble) to start ;the decode sequence. Also reads CV514 Waitn movlw 0xEC ;26 addwf n,w ;27 btfss STATUS,Carry ;28 goto ret11 ;29 incf state,f ;30 clrf data3 ;31 clrf data4 ;32 clrf addcfg ;33 clrf endval ;34 movlw 0x01 ;35 EE=1 CV514 call EEreadW ; movwf CV514a ;39 nop ;40 nop ;41 nop ;42 return ;Waitlo waits for a low bit to signal the end of the pre-amble. Also reads ;CV513 Waitlo btfss config,value ; incf state,f ; movlw 0x00 ; EE=0 CV513 call EEreadW ; movwf CV513a ; lower 6 address bits bsf CV513a,7 ; 10AAAAAA to match 1st byte goto ret6 ;34 ;Testlo must have a low half-bit. Also reads CV521. Testlo incf state,f ;26 btfsc config,value ;27 clrf state ;28 movlw 0x08 ;29 get CV521 (00000AAA) call EEreadW ; movwf CV521a ;33 upper 3 address bits rlf CV521a,f ;34 rlf CV521a,f ;35 rlf CV521a,f ;36 rlf CV521a,f ;37 now 0AAA0000 comf CV521a,f ;38 top address is complemeted movlw B'01110000' ;39 mask other bits andwf CV521a,f ;40 nop ;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. Bitset incf state,f ;26 bcf STATUS,Carry ;27 btfsc config,value ;28 bsf STATUS,Carry ;29 rlf data5,f ;30 goto ret9 ;31 ret2 goto ret0 ;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 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 and servTRK mode address. End1 movlw 0x02 ;26 movwf state ;27 movf data5,w ;28 movwf data1 ;29 btfsc config,value ;30 clrf state ;31 movf data1,w ;32 get first byte ; RESET PACKET CHECK btfsc STATUS,Zbit ;33 bsf addcfg,reset ;34 yes so set bit ; BROADCAST PACKET CHECK xorlw B'10111111' ;35 accessory broadcast low bits? btfsc STATUS,Zbit ;36 bsf addcfg,brdcst ;37 set broadcast bit ; IDLE PACKET CHECK movf data1,W ;32 GET 1st byte in W xorlw B'11111111' ;35 IDLE ? btfsc STATUS,Zbit ;36 bsf addcfg,idle ;37 if B'11111111' set IDLE bit ; OUT OF CYCLE movf data1,w ;38 andlw B'01111111' ;39 ;acc address has top bit set addlw 0x90 ;40 btfsc STATUS,Carry ;41 bsf addcfg,servTRK ;42 servTRK so set bit return ;43 ;Intermediate bit after second byte - must be low. End2 also checks for ;primary address (9 bits)and rest of broadcast. End2 movlw 0x02 ;26 movwf state ;27 movf data5,w ;28 movwf data2 ;29 btfsc config,value ;30 clrf state ;31 ; SERVICE-OPS CHECK ; 0 10AAAAAA 0 0AAACCaa 0 aaaaaaaa 0 DDDDDDDD 0 EEEEEEEE 1 movf data2,W ;32 2nd byte andlw B'10001100' ;33 mask about 0AAA11aa xorlw B'00001100' ;34 mask to get 0xxx11xx btfsc STATUS,Zbit ;36 bsf addcfg,servOPS ;37 ; IDLE CHECK btfss addcfg,idle goto End2b movf data2,W ;38 2nd byte btfss STATUS,Zbit ;40 all zeros? bcf addcfg,idle ;41 IDLE only if we had idle before ; BROADCAST CHECK End2b movf data2,W ;38 2nd byte andlw B'01110000' ;33 mask except hi address bits btfss STATUS,Zbit ;34 all zeros? bcf addcfg,brdcst ;35 not broadcast ; ADDRESSES CHECK BANK0 513a 512a bsf addcfg,primary ;43 movf data2,W ; 2nd byte andlw B'01110000' ; mask except hi addr xorwf CV521a,w ;36 hi bits match? btfsc STATUS,Zbit ;37 bsf addcfg,primary ;38 yes movf data1,w ;39 get first byte xorwf CV513a,w ;40 match? btfsc STATUS,Zbit ;41 return End2c bcf addcfg,primary ;42 n bcf addcfg,servOPS ;59 if dont match clear SERVICE-OPS 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. ;The TMR0 is compared with the value 63. As TMR0 increments every 16 ;microsecs, count will match at about 1 millisec.A match condition (=>) ;will increment tick1 and reset the TMR0. Tick1 is compared with 10 and ;if => then all channel timers, (time1 to time8) are incremented.This ;sets the fundamental time interval at 10 millisec. ;Between tick1 updates, routine switches to 'Counter' which accesses each ;output routine in turn to see if the outputs should be on or off. Update movlw .63 ;50 one millisec approx subwf TMR0,w ;51 btfss STATUS,Carry ;52 goto Counter ;53 incf tick1,f ;54 clrf TMR0 ;55 reset TMR0 nop ;56 movlw .10 ;57 subwf tick1,w ;58 btfss STATUS,Carry ;59 10ms ret22 goto ret20 ;60 clrf tick1 ;61 incf time1,f ;62 increment channel timers incf time2,f ;63 incf time3,f ;64 incf time4,f ;65 incf time5,f ;66 incf time6,f ;67 incf time7,f ;68 incf time8,f ;69 goto ret12 ;70 ;Count1 controls output1 count1 btfss action,7 ;62 new action goto t1a ;63 no movf action,w ;64 andlw B'00000111' ;65 mask xorlw B'00000000' ;66 is it output 1? btfss STATUS,Zbit ;67 yes goto t1b ;68 btfss CV514a,0 ;69 is this bit enabled? goto t1c ;70 no btfss action,3 ;71 on or off goto off1 ;72 bsf PORTA,0 ;73 F1a on clrf tick1 ;74 clrf time1 ;75 start timer bcf action,7 ;76 action done goto ret5 ;77 off1 bcf PORTA,0 ;74 F1a off bcf action,7 ;75 goto ret6 ;76 t1a nop ;65 nop ;66 nop ;67 nop ;68 nop ;69 t1b nop ;70 nop ;71 t1c movlw 2 ;72 get CV515 time on call EEreadW movf EEDATA0,w ;75 btfsc STATUS,Zbit ;76 if zero then always on goto ret5 ;77 subwf time1,w ;78 compare time btfsc STATUS,Carry ;79 bcf PORTA,0 ;80 time out so put off goto ret2 ret13 goto ret11 ret11 goto ret9 ret5 goto ret3 ret3 goto ret1 ret1 nop ;83 ret0 return ;84 ;Count2 controls F1b count2 btfss action,7 ;62 new action goto t2a ;63 no movf action,w ;64 andlw B'00000111' ;65 mask xorlw B'00000001' ;66 is it output 1b? btfss STATUS,Zbit ;67 yes goto t2b ;68 btfss CV514a,1 ;69 is this bit enabled? goto t2c ;70 no btfss action,3 ;71 on or off goto off2 ;72 bsf PORTA,1 ;73 F1b on clrf tick1 ;74 clrf time2 ;75 start timer bcf action,7 ;76 action done goto ret5 ;77 off2 bcf PORTA,1 ;74 F1b off bcf action,7 ;75 goto ret6 ;76 t2a nop ;65 nop ;66 nop ;67 nop ;68 nop ;69 t2b nop ;70 nop ;71 t2c movlw 2 ;72 get CV515 time on call EEreadW movf EEDATA0,w ;75 btfsc STATUS,Zbit ;76 if zero then always on goto ret5 ;77 subwf time2,w ;78 compare time btfsc STATUS,Carry ;79 bcf PORTA,1 ;80 time out so put off goto ret2 ;Count3 controls F2a count3 btfss action,7 ;62 new action goto t3a ;63 no movf action,w ;64 andlw B'00000111' ;65 mask xorlw B'00000010' ;66 is it output 2a? btfss STATUS,Zbit ;67 yes goto t3b ;68 btfss CV514a,2 ;69 is this bit enabled? goto t3c ;70 no btfss action,3 ;71 on or off goto off3 ;72 bsf PORTA,2 ;73 F2a on clrf tick1 ;74 clrf time3 ;75 start timer bcf action,7 ;76 action done goto ret5 ;77 off3 bcf PORTA,2 ;74 F2a off bcf action,7 ;75 goto ret6 ;76 t3a nop ;65 nop ;66 nop ;67 nop ;68 nop ;69 t3b nop ;70 nop ;71 t3c movlw 3 ;72 get CV516 time on call EEreadW movf EEDATA0,w ;75 btfsc STATUS,Zbit ;76 if zero then always on goto ret5 ;77 subwf time3,w ;78 compare time btfsc STATUS,Carry ;79 bcf PORTA,2 ;80 time out so put off goto ret2 ;Count4 controls F2b count4 btfss action,7 ;62 new action goto t4a ;63 no movf action,w ;64 andlw B'00000111' ;65 mask xorlw B'00000011' ;66 is it output F2b? btfss STATUS,Zbit ;67 yes goto t4b ;68 btfss CV514a,3 ;69 is this bit enabled? goto t4c ;70 no btfss action,3 ;71 on or off goto off4 ;72 bsf PORTA,3 ;73 F2b on clrf tick1 ;74 clrf time4 ;75 start timer bcf action,7 ;76 action done goto ret5 ;77 off4 bcf PORTA,3 ;74 F2b off bcf action,7 ;75 goto ret6 ;76 t4a nop ;65 nop ;66 nop ;67 nop ;68 nop ;69 t4b nop ;70 nop ;71 t4c movlw 3 ;72 get CV516 time on call EEreadW movf EEDATA0,w ;75 btfsc STATUS,Zbit ;76 if zero then always on goto ret5 ;77 subwf time4,w ;78 compare time btfsc STATUS,Carry ;79 bcf PORTA,3 ;80 time out so put off goto ret2 ;Count5 controls output F3a count5 btfss action,7 ;62 new action goto t5a ;63 no movf action,w ;64 andlw B'00000111' ;65 mask xorlw B'00000100' ;66 is it output F3a? btfss STATUS,Zbit ;67 yes goto t5b ;68 btfss CV514a,4 ;69 is this bit enabled? goto t5c ;70 no btfss action,3 ;71 on or off goto off5 ;72 bsf PORTB,0 ;73 F3a on clrf tick1 ;74 clrf time5 ;75 start timer bcf action,7 ;76 action done goto ret5 ;77 off5 bcf PORTB,0 ;74 F3a off bcf action,7 ;75 goto ret6 ;76 t5a nop ;65 nop ;66 nop ;67 nop ;68 nop ;69 t5b nop ;70 nop ;71 t5c movlw 4 ;72 get CV517 time on call EEreadW movf EEDATA0,w ;75 btfsc STATUS,Zbit ;76 if zero then always on goto ret5 ;77 subwf time5,w ;78 compare time btfsc STATUS,Carry ;79 bcf PORTB,0 ;80 time out so put off goto ret2 ;Count6 controls the output F3b count6 btfss action,7 ;62 new action goto t6a ;63 no movf action,w ;64 andlw B'00000111' ;65 mask xorlw B'00000101' ;66 is it output F3b? btfss STATUS,Zbit ;67 yes goto t6b ;68 btfss CV514a,5 ;69 is this bit enabled? goto t6c ;70 no btfss action,3 ;71 on or off goto off6 ;72 bsf PORTB,1 ;73 F3b on clrf tick1 ;74 clrf time6 ;75 start timer bcf action,7 ;76 action done goto ret5 ;77 off6 bcf PORTB,1 ;74 F3b off bcf action,7 ;75 goto ret6 ;76 t6a nop ;65 nop ;66 nop ;67 nop ;68 nop ;69 t6b nop ;70 nop ;71 t6c movlw 4 ;72 get CV517 time on call EEreadW movf EEDATA0,w ;75 btfsc STATUS,Zbit ;76 if zero then always on goto ret5 ;77 subwf time6,w ;78 compare time btfsc STATUS,Carry ;79 bcf PORTB,1 ;80 time out so put off goto ret2 ;Count7 controls output F4a count7 btfss action,7 ;62 new action goto t7a ;63 no movf action,w ;64 andlw B'00000111' ;65 mask xorlw B'00000110' ;66 is it output F4a? btfss STATUS,Zbit ;67 yes goto t7b ;68 btfss CV514a,6 ;69 is this bit enabled? goto t7c ;70 no btfss action,3 ;71 on or off goto off7 ;72 bsf PORTB,2 ;73 F4a on clrf tick1 ;74 clrf time7 ;75 start timer bcf action,7 ;76 action done goto ret5 ;77 off7 bcf PORTB,2 ;74 F4a off bcf action,7 ;75 goto ret6 ;76 t7a nop ;65 nop ;66 nop ;67 nop ;68 nop ;69 t7b nop ;70 nop ;71 t7c movlw 5 ;72 get CV518 time on call EEreadW movf EEDATA0,w ;75 btfsc STATUS,Zbit ;76 if zero then always on goto ret5 ;77 subwf time7,w ;78 compare time btfsc STATUS,Carry ;79 bcf PORTB,2 ;80 time out so put off goto ret2 ;Count8 controls output F4b count8 btfss action,7 ;62 new action goto t8a ;63 no movf action,w ;64 andlw B'00000111' ;65 mask xorlw B'00000111' ;66 is it output F4b? btfss STATUS,Zbit ;67 yes goto t8b ;68 btfss CV514a,7 ;69 is this bit enabled? goto t8c ;70 no btfss action,3 ;71 on or off goto off8 ;72 bsf PORTB,3 ;73 F4b on clrf tick1 ;74 clrf time8 ;75 start timer bcf action,7 ;76 action done goto ret5 ;77 off8 bcf PORTB,3 ;74 F4b off bcf action,7 ;75 goto ret6 ;76 t8a nop ;65 nop ;66 nop ;67 nop ;68 nop ;69 t8b nop ;70 nop ;71 t8c movlw 5 ;72 get CV518 time on call EEreadW movf EEDATA0,w ;75 btfsc STATUS,Zbit ;76 if zero then always on goto ret5 ;77 subwf time8,w ;78 compare time btfsc STATUS,Carry ;79 bcf PORTB,3 ;80 time out so put off goto ret2 ret7 goto ret5 ;77 ret6 goto ret4 ;78 ;Additional goto sequences. ret27 goto ret25 ;15 ret25 goto ret23 ;17 ret24 goto ret22 ret23 goto ret21 ;19 ;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 ret4 goto ret2 ; ******************************************************************************** ; ******************************************************************************** ; ******************************************************************************** ; ******************************************************************************** ;CVservOPS checks/WRites for servOPS mode instructions with the decoder in ;servOPS mode. If the CV number in data2 is 06h (CV519), 07h (CV520)or ;1Ch (CV541), then the WRite does not take place. CVservOPS ; btfss config,byte5 ; return btfss addcfg,servOPS ; return ; clrf n ; call Twonrow ; check two identical packets ; iorlw 0x00 ; check two identical packets ; btfsc STATUS,Zbit ; check two identical packets ; return ; check two identical packets ; call Ackn ; DEBUG movf data2,W andlw B'00000011' ; at least CV513 ! xorlw B'00000010' ; at least CV513 ! btfss STATUS,Zbit ; at least CV513 ! return ; nothing done movf data3,W ;addresses start at 0 xorlw 0x06 ; CV519 CV520 CV541 btfsc STATUS,Zbit ;00000110 00000111 00011100 return ; got 519 ;00000110 00000110 00000110 XOR 0x06=00000110 xorlw 0x01 ;00000000 00000001 00011010 btfsc STATUS,Zbit ; 00000001 00000001 XOR 0x01=00000010 return ; got 520 ; 00000000 00011011 xorlw 0x1B ; 00011011 XOR 0x1B=00011011 btfsc STATUS,Zbit ; 00000000 return ; got 541 ; movf data3,W ;addresses start at 0 sublw 0x1F ;only CVs 513(0x00) to 542(0x1D) btfss STATUS,Carry return ; all ok, now WRite EEADR0 as data3 EEDATA0 as data4 movfw data3 ; movwf EEADR0 ; movfw data4 ; movwf EEDATA0 ; call EEwrite ; bcf addcfg,servOPS ; call Ackn ; return ; WRITTEN OPS !!!! ;CVservTRK checks for servTRK mode instructions with the decoder in servTRK ;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. CVservTRK btfss config,byte5 ;40 btfss config,servTRK ;41 return ;42 clrf n nop call Twonrow iorlw 0x00 btfsc STATUS,Zbit return btfss config,byte4 goto CVpage movf data1,w xorlw 0x76 ; [gi] DIR Mode cmd: 0111CCAA where AA=10 for CV >512 btfsc STATUS,Zbit goto Ver1dir ; [gi] data2 contains offset in EEDATA0 xorlw 0x08 btfss STATUS,Zbit return goto WR1dir ; [gi] data2 contains offset in EEDATA0 ;WR1 WRites the data in data3 into the CV listed in data2. If the CV ;number in data2 is 06h (CV519), 07h (CV520)or 1Ch (CV541), then the WRite ;does not take place. WR1 decf data2,f ; [gi] Jump Target for PageMode (data2=CV#) WR1dir movf data3,w ; [gi] data2 now contains offset in EEDATA0. movwf EEDATA0 movf data2,w ;addresses start at 0 xorlw 0x06 ; CV519 CV520 CV521 CV541 btfsc STATUS,Zbit ;00000110 00000111 00001000 00011100 return ;00000110 00000110 00000110 00000110 xorlw 0x01 ;00000000 00000001 00001111 00011010 btfsc STATUS,Zbit ; 00000001 00000001 00000001 return ; 00000000 00001110 00011011 xorlw 0x1B ; 00011011 btfsc STATUS,Zbit ; 00000000 goto WRcon1 WRcont movlw 09h ;only CVs 513(1) to 521(9) subwf data2,w btfsc STATUS,Carry return WRcon1 movf data2,w movwf EEADR0 clrwdt call EEwrite goto Ackn ;Two in a row checks that the current packet is the second identical packet ;before performing a servTRK 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 servTRK 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 ;CV541s sets data2 to 1Ch (28). CV541s movlw 0x1C movwf data2 goto CVcont ;CVfind determines the CV using the page register and the offset in the ;instruction. If the page is less than 128 then no action is taken as it ;is not an accessory CV. CVfind decf pagereg,w movwf data2 bcf STATUS,Carry rlf data2,f btfss STATUS,Carry ;page must be 80h or more return rlf data2,f 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. ;only CV 513 to 521 and 541 will verify. Ver1 decf data2,f ; [gi] Jump Target for PageMode (data2=CV#) ; [gi] data2 now contains offset in EEDATA0 Ver1dir movlw 1Ch ;is it CV541 xorwf data2,w btfsc STATUS,Zbit goto ver2 movlw 09h ;only CVs 513(1) to 521(9) subwf data2,w btfsc STATUS,Carry return ver2 movf data2,w ;CVs address directly movwf EEADR0 call EEread xorwf data3,w btfss STATUS,Zbit return goto Ackn Dcontrl btfss config,byte5 btfsc config,byte4 return movf data2,w btfsc STATUS,Zbit goto Dreset xorlw 0x0E btfsc STATUS,Zbit goto Ackn return Dreset clrf action ;clear action btfss addcfg,reset return bsf config,servTRK goto Nextbyt ;Ackn sets ack output for 250ms (1024us X 5). 1024us is counted by ;bit 6 of TMR0 register.Ack is used to flash the ack LED Ackn clrwdt bsf PORTB,6 ;set ack line high ; comf PORTB ; DEBUG STEFANO-MERG clrf TMR0 movlw .250 movwf temp aloop btfss TMR0,6 goto aloop bcf TMR0,6 decfsz temp,f goto aloop ; comf PORTB ; DEBUG STEFANO-MERG bcf PORTB,6 ;set ack line low return ;Generic EE WRite subroutine that WRites EEDATA into EEARD. If the processor ;is busy with a previous WRite operation, the subroutine returns without ;WRiting. Inputs are EEARD and eeread. ;EEread uses the file selct register to read the data stored in the EE ;memory location pointed to by EEARD. EEwrite bsf STATUS,RP0 ; bank1 movf EEADR1,W ; get from copy of bank0 movwf EEADR ; movf EEDATA1,W ; get from copy of bank0 movwf EEDATA ; bsf EECON1,WREN ; enable write EEPROM capability bcf INTCON,GIE ; movlw 0x55 ; movwf EECON2 ; write 55h movlw 0xAA ; movwf EECON2 ; write AAh bsf EECON1,WR ; set WE bit enable write, start writing EEWRcon btfsc EECON1,WR ; wait until WRITE is over goto EEWRcon ; wait until WRITE is over bcf EECON1,WREN ; disable write EEPROM capability bcf STATUS,RP0 ; bank0 return ; EEreadW movwf EEADR0 ; read what is in W EEread bsf STATUS,RP0 ; Bank 1 movf EEADR1,W ; get from copy of bank0 movwf EEADR ; Address to read bsf EECON1,RD ; EE Read movf EEDATA,W ; W = EEDATA movwf EEDATA1 ; EEDATA1 = EEDATA bcf STATUS,RP0 ; Bank 0 return ; ; **************************************************** ; extra DEBUG STUFF ; ******************************************************************************** ; STANDARD RESET CONFIGURATION CVS resetCV call reset513 ; call reset514 ; call reset515 ; call reset521 ; return ; reset513 movlw 0x01 ; CV513a DEFAULT movwf EEDATA0 ; movlw 0x00 ; movwf EEADR0 ; goto EEwrite ; reset514 movlw 0xFF ; CV514 DEFAULT movwf EEDATA0 ; movlw 0x01 ; movwf EEADR0 ; goto EEwrite ; reset515 movlw 0x0A ; CV514 DEFAULT movwf EEDATA0 ; movlw 0x02 ; movwf EEADR0 ; call EEwrite ; incf EEADR0 ; call EEwrite ; incf EEADR0 ; call EEwrite ; incf EEADR0 ; call EEwrite ; return reset521 movlw 0x00 ; CV521a DEFAULT movwf EEDATA0 ; movlw 0x08 ; movwf EEADR0 ; goto EEwrite ; fakeaddresses movlw B'10000001' ; movwf CV513a ; movlw B'01110000' ; movwf CV521a ; return ; ; ******************************************************************************** ORG 0x2100 DATA 0x01 ;513 DATA 0xFF ;514 DATA 0x0A ;515 DATA 0x0A ;516 DATA 0x0A ;517 DATA 0x0A ;518 DATA 0x00 ;519 DATA 0x00 ;520 DATA 0x00 ;521 DATA 0x00 DATA 0x00 DATA 0x00 DATA 0x00 DATA 0x00 DATA 0x00 DATA 0x00 DATA 0x00 DATA 0x00 DATA 0x00 DATA 0x00 DATA 0x00 DATA 0x00 DATA 0x00 DATA 0x00 DATA 0x00 DATA 0x00 DATA 0x00 DATA 0x00 DATA 0x80 DATA 0x00 DATA 0x00 DATA 0x00 END