; *************************************************************** ; * Einfahrsignal-DCC-Decoder ; * Version 1.01 ; * Last change: 12/30/2004 ; ; --- dekooderi_01a --- ; ; korjattu 2.9.2019 KG ; Ohjaus invertoitu ; HUOM. LEDIT + -> PIC, - -> GND ; ============================== ; OSOITE D'82' ; Esimerkkiosoite ADDRESS_LO = 82 ; ; HUOM. ; ROCO (MULTIMAUS) käyttää osoitetta 82+4 = 86 ; ESU ECOS käyttää osoitetta 82 ; ; * Microcontroller: PIC12F629 ; * Status: Tested ; *************************************************************** ; ********************************************************************** ; * (C) Copyright Gorden Griem, 2004 ; * parts copyright by Dean Probst, Ingo Schroeter ; ********************************************************************** ; ********************************************************************** ; Saksankielestä vapaasti suom. KG ; Ohjelma on vapaasti käytettävissä yksityiskäyttöön. ; Kaupalliseen käyttöä varten on hankittava tekijältä kirjallinen lupa. ; Ohjelma on testattu perusteellisesti. Tästä huolimatta ; ei tekijä anna minkäänlaista takuuta ohjelman toimivuudesta. ; ********************************************************************** ; ********************************************************************** ; Toimintaselostus: ; ; Dekooderi toimii kulkutieopastin/vaihtotyöopastimena. ; (LEDien miinusnapa on kytketty suoraan prosessoriin.) ; HUOM. ; Ohjaukset invertoitu: ; LEDien + -napa prosessoriin, - -napa maahan. ; Dekooderilla on kolme (neljä) toimintotilaa: ; Hp0 (seis), Hp1 (aja), Hp2 (aja varovasti) ; SEIS: vaihdekomento (perusosoite) "+" (poikkeava raide) ; AJA: vaihdekomento (perusosoite)"-" (suoraan) ; AJA VAROVASTI: vaihdekomento (perusosoite+1) "-" (suoraan) ; Viimeksi annettu komento tallentuu EEPROM-muistiin. ; Siten DCC-katkon jälkeen opastin näyttää edellistä tilaa. ; ; Osoite tallennetaan EEPROM-muistiin muodossa ; ADDRESS_LO & ADDRESS_HI. ; Todellinen osoite lasketaan: ; Perusosoite (Hp0/Hp1) = ADRESSEH*256 + ADRESSEL ; Perusosoite+1 (Hp2) = ADRESSEH*256 + ADRESSEL + 1 ; ; Perusosoitteen suurin arvo saa olla 254. ; ********************************************************************** ;----- Processor Definition-------------------- LIST P=12F629, n=76 ; target processor errorlevel -302 #include ; ----- Current configuration: ; ----- Code Protect Data : Off ; ----- Code Protect : Off ; ----- Brown Out Detect : On ; ----- Power Up Timer : On ; ----- Watchdog Timer : Off ; ----- Master-Clear : Internal ; ----- Oscillator : Internal RC, no clock to outside __CONFIG _CPD_OFF & _CP_OFF & _BODEN_ON & _PWRTE_ON & _WDT_OFF & _MCLRE_OFF & _FOSC_INTRCCLK ; *************************************************** ; IO-PINS ; #define gp0 0 ;Output 1: RED LED #define gp1 1 ;Output 2: GREEN LED #define gp2 2 ;Output 3: YELLOW LED #define gp3 3 ;data in #define gp4 4 ;not used #define gp5 5 ;not used #define no_of_preamb D'17' ; No. of preamble bits = 20; ; but it does not matter ; to react earlier ; *************************************************** ; User Variables, contains unused variables ; cblock 0x20 CONFBITS ; Contains various bits to test ; MOTMASK ; Motormask for direction ; PWM ; How long is motor on ENDVAL ; Offset to byte check routines PRECOUNT ; Preamble counter STATE ; Where are we in the DCC package DATA_1 ; 1. transmitted byte DATA_2 ; 2. transmitted byte DATA_3 ; 3. transmitted byte DATA_4 ; 4. transmitted byte DATA_X ; Scratch Register SAMPLES ; How many samples taken for one or zero TEMP ; Temporarly scratch reg ; the following are for EEPROM routines ; PC_OFFSET (not used) ; PC offset register (low order 4 bits), ; value based on operating mode of EEPROM. ; Also, bit 7 used for EE_OK flag TIMEOUTCOUNT WHOIS ; Which output supervised by Timer? ADR_OFFSET ; Adress offset EADR1 ; Adress of Hp0 RED EADR2 ; Adress of Hp1 GREEN EADR3 ; Adress 0f Hp2 YELLOW EETADR ; Adress for writing or reading EEPROM OUT_STATE ; output state: ; "1" -- pin connecting ; "0" -- pin not connecting endc ; EEPROM DATA #define EE_STATE 0x0 ; EEPROM ADDRESS 00 #define ADDRESS_HI 0x1 ; EEPROM ADDRESS 01 #define ADDRESS_LO 0x2 ; EEPROM ADDRESS 02 ; Bit Positions in CONFBITS #define bit_rec 0x0 ; CONFBITS(0:0) ; What value has the just received bit ; These definitions not needed ****** ; #define CVaccessBit 1 ; Two consecutive packets to be send ; #define resetflag 6 ; Signal reset for service mode ;----- Register Files --------------------------- OSCCAL EQU H'0090' ;----- OSCCAL Bits ------------------------------ #define OSCFST H'0003' #define OSCSLW H'0002' page ;************* ACTUAL CODE BEGINS HERE ********************** ; org 0x0 ; reset-vector goto start org 0x4 goto start ; interrupt vector org 0x5 ; the actual code begins here ***** start: bsf STATUS,RP0 ; BANK 1 call 3FFh ; load calibration value movwf OSCCAL ; put calibration value into OSCCAL bcf STATUS,RP0 ; BANK 0 goto dcc_setup ; jump over EEPROM routine and other stuff ;****************************************************** ;Value checks for correct bit and jumps ;----- ;to where we are in DCC package ;Computed goto has to reside in lower half of page, ;that's why it is here. ; ; ; **Place for updates** ; ; TimerInc is called from Value every 4 ms. ; ----- ; Then the output is set accordingly or "clearing procedure" executed. TimerInc: clrf TMR0 ; "02" -- clear timer incf WHOIS,F ; "03" WHOIS=WHOIS+1 movf WHOIS,W ; addwf PCL,F ; "05" Jump accoding to WHOIS nop ; "06" must be here (If WHOIS=0) goto TimTi1 ; "07" WHOIS=1 goto TimEnd ; "07" WHOIS=2 TimTi1: ; WHOIS = 0 or 1 nop ; "08" add 7 us nop ; "09" nop ; "10" nop ; "11" nop ; "12" goto Ti_Done ; "13","14" TimTa1: ; you never come here ?? nop ; "13" goto Ti_Done ; "14","15" TimEnd: ; now WHOIS=2 clrf WHOIS ; "09" WHOIS=0 goto TimE11 ; "10","11" TimE11: goto TimE12 ; "12","13" TimE12: goto Ti_Done ; "14","15" ; Routine to handle new bit ******* ;Value: ; movf SAMPLES,W ;use only when needed ; ;to check for 0 samples ; btfsc STATUS,Z ; goto nosample ; nop Value: btfsc TMR0,6 ; If bit 6 is set, then it's about 4 ms gone ; 64 x 64us = 4096 us goto TimerInc ; bit 6 is set ; --> back to spend 15 us and then to Ti_Done nop ; bit 6 is clear -> 26us sample nop nop nop nop nop nop nop nop nop nop nop nop nop nop ; 15 us Ti_Done: clrf SAMPLES ; clear SAMPLES movf STATE,W ; Get STATE (where are we) addwf PCL,F ; cycl to here ; Jump table to routines ; from where we do a RETURN ! ; Wait for preamble goto waitn ; STATE=0 --cycl. to here -> cycl for rout. ; wait for 20 half bits of preamble goto waitlo ; STATE=1 --wait for low half bit after preamble ; must be zero goto testlo ; STATE=2 --test second half bit of start bit ; must be zero ; First byte ; 1. bit goto bitset ; STATE=3 --takes first half bit ; of a bit in the byte goto lastv ; STATE=4 --checks that first half bit ; is the same as second half bit ; 2. bit goto bitset ; STATE=5 --takes first half bit ; of a bit in the byte goto lastv ; STATE=6 --checks that first half bit ; is the same as second half bit ; 3. bit goto bitset ; STATE=7 --takes first half bit ; of a bit in the byte goto lastv ; STATE=8 --checks that first half bit ; is the same as second half bit ; 4. bit goto bitset ; STATE=9 --takes first half bit ; of a bit in the byte goto lastv ; STATE=10 --checks that first half bit ; is the same as second half bit ; 5. bit goto bitset ; STATE=11 --takes first half bit ; of a bit in the byte goto lastv ; STATE=12 --checks that first half bit ; is the same as second half bit ; 6. bit goto bitset ; STATE=13 --takes first half bit ; of a bit in the byte goto lastv ; STATE=14 --checks that first half bit ; is the same as second half bit ; 7. bit goto bitset ; STATE=15 --takes first half bit ; of a bit in the byte goto lastv ; STATE=16 --checks that first half bit ; is the same as second half bit ; 8. bit goto bitset ; STATE=17 --takes first half bit ; of a bit in the byte goto lastx ; STATE=18 --checks that first half bit is ; the same as second half bit ; and sets offset (ENDVAL) ; to byte check routine ; ; Byte received ; ; after address byte (1)must follow '0' bit goto end11 ; STATE=19 --first half bit goto end12 ; STATE=20 --second half bit ; after address/command (2) byte must follow '0' bit goto end21 ; STATE=21 --first half bit goto end22 ; STATE=22 --second half bit ; after checksum byte (3) must follow '1' bit goto end31 ; STATE=23 --first half bit. goto end32 ; STATE=24 --second half bit ; not sure if this is needed ; end of fourth byte (4) there must be '1' goto end41 ; STATE=25 --first half bit. goto end42 ; STATE=26 --second half bit ; not sure if this is needed ; end of fifth byte (5) there must be '1' goto end51 ; STATE=27 --first half bit. goto end52 ; STATE=28 --second half bit page ;****************************************************** ;********** setup sets all what is necessary ********** dcc_setup: movlw EE_STATE ; EEPROM address 0x00 movwf EETADR call readEE ; previous (initial) state from EEPROM movwf OUT_STATE ; gp0,gp1,gp2 are outputs iorlw B'00001000' bsf STATUS,RP0 movwf TRISIO bcf STATUS,RP0 ; invertoidaan lähdöt comf W,0 ; ohjaus invertoidaan movwf GPIO ; set leds ;****************************************************** ;* Read the address. ;* If the address is given in the following way: ;* High: 00000abc Low: defghikm ;* then it has to be reorganised ;* ADR_OFFSET: 10defghi ;* EADRx: 1abc1kmx ;* where abc is inverted ;* and "x" acts as the informetion between "straight" (0) or "turn" (1) ;* ;* Please note that address "1" as expexted not with ;* defghi=0 but defghi=000001. ;* That is why we must add "3" to the address stored ;* in EEPROM in order to define the real correct address. ;* For address 257 etc is defghi=000000 allowed movlw ADDRESS_HI ; Read the three high bits from EEPROM (01) movwf EETADR call readEE ; ADDRESSHI default = b'00000000' movwf TEMP rlf TEMP,f ; four times left shift rlf TEMP,f rlf TEMP,f rlf TEMP,w ; w=B'00000000' andlw B'01110000' ; mask other bits out xorlw B'01110000' ; xor -- invert bits iorlw B'10001000' ; these bits are standard movwf TEMP ; TEMP=B'11111000' movf TEMP,w movwf EADR1 ; EADR1=1abc1---=B'11111---' movf TEMP,w movwf EADR2 ; EADR2=1abc1---=B'11111---' bsf EADR2,0 ; EADR2=1abc1--1=B'11111--1' movf TEMP,w movwf EADR3 ; EADR3=1abc1--1=B'11111--1' movlw ADDRESS_LO ; Read the lower eight address bits from EEPROM movwf EETADR call readEE ; ADDRESSLO=defghjkm=B'00000011' ; (default=D'3') addlw D'3' ; Add 3 to the address as according to NMRA, ; you need to send a "4" for address 1 ; (block with only "000000" ; as lower address bits is not allowed) movwf TEMP ; TEMP=B'00000011'+B'00000011'=B'00000110' rlf TEMP,w ; shift left w=B'00001100' andlw B'00000110' ; mask out other bits w=B'00000100' movwf TEMP ; and store result TEMP=B'00000100' iorwf EADR1,f ; EADR1=B'11111---'+B'00000100'=B'11111100' movf TEMP,w ; TEMP=B'11111100' iorwf EADR2,f ; EADR2=B'11111001' ; xor B'11111100'=B'00000101' incf TEMP,f ; TEMP=B'11111101' ; incremented twice incf TEMP,w ; w= B'11111110' andlw B'00000110' ; w= B'00000110' movwf TEMP ; TEMP=B'00000110' movf TEMP,w ; w= B'00000110' iorwf EADR3,f ; EADR3=B'11111001'orB'00000110'= ; B'11111110' movlw ADDRESS_LO ; Read the lower eight bits from EEPROM movwf EETADR call readEE ; ADDRESSLO (default) = D'3' addlw D'3' ; Add 3 to the address as according to NMRA, ; you need to send a "4" for address 1 ; (block with only "000000" as lower address bits ; is not allowed) movwf TEMP ; TEMP=B'00000110' (D'6') rrf TEMP,f ; mask the lowest two bits out rrf TEMP,w ; w= B'00000001' andlw B'00111111' ; w= B'00000001' iorlw B'10000000' ; w= B'10000001' set high one "1" bit movwf ADR_OFFSET ; ADR_OFFSET=B'10000001' movlw 0x7 ; bottom of RAM movwf FSR ; indirect address set movlw no_of_preamb ; Preamble = 20 half bits movwf PRECOUNT ; store it to PRECOUNT(er) clrf TIMEOUTCOUNT ; clear packet time out ;****************************************************** ; Now do Master_init and load default values MasterInit: hard_reset_jump: clrf STATE clrf ENDVAL clrf DATA_1 clrf DATA_2 clrf DATA_3 clrf DATA_4 clrf DATA_X clrf WHOIS ; set Timer to be incremented every 64us movlw B'11000101' ; OPTION_REG ; bit7 - GPIO pull-ups disabled, ; bit6 - INTEDG Interrupt on rising edge of GP2/INT pin ; bit5 - T0CS TMR0 clock source internal (CLKOUT) ; bit4 - T0SE TMR0 increment on low-to-high ; transition on GP2 pin ; bit3 - PSA Prescaler asiigned to the TIMER0 module ; bit2 - PS2:PS0 Prescaler TMR0 rate 1:64 bsf STATUS,RP0 movwf OPTION_REG bcf STATUS,RP0 goto starthi ; continue to main loop page org 0xA0 ;****************************************************** ; Main loop is here. ; Track is sampled every 40us the first time and then ; every 14us. Therefore: ; 0-2 samples (26-81) -> one received ; > 2 samples (69-...) -> zero received starthi: call Value conthi: ; this round takes about 14 us btfss GPIO,gp3 ;1-2-Read DCC signal, skip if '1' goto startlo ;DCC changed state from '1' to '0' ;now check what to do with the bit received ; DCC = '1' btfss SAMPLES,7 ;2-Skip if 128 SAMPLES has been '1' incf SAMPLES,F ;2-not 128 yet, increment SAMPLES bcf CONFBITS,bit_rec ;1-CONFBITS(bit0)=0 bcf STATUS,C ;1-Clear Carry ; check if 4 samples received ? movlw 0xFC ;1-W=0xFC (D252) addwf SAMPLES,W ;1-W=0xFC+SAMPLES btfss STATUS,C ;2-skip if carry=1, that is 4 samples '1' received bsf CONFBITS,bit_rec ;1-CONFBITS(bit0) set flag nop ;1 nop ;1 goto conthi ;2-back to see if DCC is still '1' startlo: call Value contlo: btfsc GPIO,gp3 ;1-2-Read DCC signal, skip if '0' goto starthi ;DCC changed state from '0' to '1' ;now check what to do with the bit received ; DCC = '0' btfss SAMPLES,7 ;2- Skip if 128 samples has been '0' incf SAMPLES,F ;1- not 128 yet, increment SAMPLES bcf CONFBITS,bit_rec ;1- CONFBITS(bit0)=0, set bit to '0' bcf STATUS,C ;1-Clear Carry ; check if 4 samples received ? movlw 0xFC ;1-W=0xFC (D252) addwf SAMPLES,W ;1-W=0xFC+SAMPLES btfss STATUS,C ;2-skip if carry=1, that is 4 samples '0' received bsf CONFBITS,bit_rec ;1-CONFBITS(bit0) set flag nop ;1 nop ;1 goto contlo ;2-back to see if DCC is still '0' ;****************************************************** nosample: ; movlw no_of_preamb ; movwf PRECOUNT ; clrf STATE ; clrf SAMPLES ; clrf ENDVAL ; return ;****************************************************** ; Frame error in packet frameerr: movlw no_of_preamb movwf PRECOUNT clrf STATE clrf ENDVAL clrf DATA_1 clrf DATA_2 clrf DATA_3 clrf DATA_4 clrf DATA_X clrf SAMPLES movlw 0xF0 ; cut of low nibble andwf CONFBITS,F retlw 0 page ;****************************************************** ; waitn ; waits for 20 half bits of the preamble ; STATE = 0 waitn: nop ;1 nop ;1 nop ;1 btfss CONFBITS,bit_rec ;1-2-skip if CONFBITS(bit0)="1" ;there are only ones in preamble goto waitn1 ; decfsz PRECOUNT,F ;1-2-PRECOUNT=PRECOUNT-1, skip if "0" goto ret4 ;still counting... wait 2 us more and RET movlw no_of_preamb ;1-no of preamb bits = D'17' movwf PRECOUNT ;1-store into PRECOUNTER incf STATE,F ;1-next state ... STATE=STATE+1 retlw 0 ; 9 cycl. ret4: nop nop retlw 0 ; 9 cycl. waitn1: movlw no_of_preamb ;1-no of preamb bits = D'17' movwf PRECOUNT ;1-store into PRECOUNTER nop ;wait 2 us more and RET nop ;1 retlw 0 ;1 ;****************************************************** ; waitlo ; waits for low half bit after preamble ; STATE = 1 waitlo: ; decfsz TIMEOUTCOUNT,F nop goto waitlo1 ; goto dcc_setup ;?? never here waitlo1: nop nop nop nop btfsc CONFBITS,bit_rec ; CONFBITS(bit0) - must be a zero goto ret5 ; still=1 ... we stay in this STATE ; might be long preamble incf STATE,F ; STATE=STATE+1 (next state) ret5: retlw 0 ; 9 cycl ;****************************************************** ; testlo ; test second half bit of start bit ; STATE = 2 testlo: nop nop nop nop nop nop nop btfsc CONFBITS,bit_rec ; CONFBITS(bit0) - must be a zero goto frameerr incf STATE,F retlw 0 ; 9 cycl ;****************************************************** ; bitset ; takes first half bit of a bit in the byte ; ; STATE = 3,5,7,9,11,13,15,17 bitset: incf STATE,F ; STATE=STATE+1 bcf STATUS,C ; clear carry btfsc CONFBITS,bit_rec ; if CONFBITS(bit0)=not set bsf STATUS,C ; no -> set carry rlf DATA_X,F ; shift left -> carry(0/1)-> bit0 nop nop nop nop nop retlw 0 ; 9 cycl. ;****************************************************** ; lastv ; checks that first half bit = second half bit ; ; STATE = 4,6,8,10,12,14,16,18 lastv: nop nop nop nop incf STATE,F ; STATE=STATE+1 btfss CONFBITS,bit_rec ; if CONFBITS(bit0)=set goto lastv1 ; no btfss DATA_X,0 ; if last bit set? goto frameerr ; error if not equal nop retlw 0 ; 9 cycl. lastv1: btfsc DATA_X,0 ; clear bit(0) goto frameerr ; error if not equal retlw 0 ; 9 cycl. ;****************************************************** ;lastx ; last bit of a byte... ; checks that first half bit = second half bit ; and sets offset to byte check routine lastx: incf ENDVAL,F ; ENDVAL=ENDVAL+1 ; byte check offset movf ENDVAL,W addwf STATE,F ; STATE=STATE+ENDVAL ; ENDVAL = new jump table nop nop btfss CONFBITS,bit_rec ; CONFBITS(bit0)=set? goto lastx1 ; no, check DATA_X btfss DATA_X,0 ; last bit of DATA_X=1? goto frameerr ; no -> error if not equal nop retlw 0 ; 9 cycl. lastx1: btfsc DATA_X,0 ; last bit of DATA_X=0? goto frameerr ; no -> error if not equal retlw 0 ; 9 cycl. ;****************************************************** ; end11 ; ; end of first byte (address) there must be zero ; ; end11 first half bit ; end12 second half bit ; STATE = 19 (ENDVAL=1) end11: btfsc CONFBITS,bit_rec ; CONFBITS(bit0)=0? goto frameerr ; not zero -> frame error incf STATE,F ; OK. -> next STATE=20 incf ENDVAL,F ; get ready for new ; jump table nop nop nop nop nop nop retlw 0 ; 9 cycl. ; STATE = 20 (ENDVAL=1) end12: btfsc CONFBITS,bit_rec ; CONFBITS(bit0)=0? goto frameerr ; not zero -> frame error movf DATA_X,W ; DATA_X -> DATA_1 (first byte) movwf DATA_1 movlw 0x03 ; set STATE=3 ; now back to beginning of jump table ; and wait for next byte movwf STATE ; next STATE = 3 nop nop nop nop retlw 0 ; 9 cycl. ;****************************************************** ; end21 ; end of second byte there must be zero ; ; end22 first half bit ; end22 second half bit ; STATE = 21 (ENDVAL=2) end21: btfsc CONFBITS,bit_rec ; CONFBITS(bit0)=0? goto frameerr ; no -> frame error incf STATE,F ; STATE=STATE+1 incf ENDVAL,F ; ENDVAL=ENDVAL+1 nop nop nop nop nop nop retlw 0 ; 9 cycl. ; STATE = 22 (ENDVAL=2) end22: btfsc CONFBITS,bit_rec ; CONFBITS(bit0)=0? goto frameerr ; no -> frame error movf DATA_X,W ; DATA_X -> DATA_2 (second byte) movwf DATA_2 movlw 0x03 ; set STATE=3 ; now back to beginning of jump table movwf STATE nop nop nop nop retlw 0 ; 9 cycl. ;****************************************************** ; end31 ; end of third byte there must be a one ; ; end32 first half bit ; end32 second half bit ; STATE = 23 (ENDVAL=3) end31: incf STATE,F ; STATE=STATE+1 incf ENDVAL,F ; ENDVAL= ENDVAL+1 nop nop nop nop nop nop nop nop retlw 0 ; 9 cycl. ; STATE = 24 (ENDVAL=3) end32: movf DATA_X,W ; DATA_X -> DATA_3 (third byte) movwf DATA_3 btfsc CONFBITS,bit_rec ; CONFBITS(bit0)=0? ; if 0 then other bytes will follow ; but we do not read them goto end32x ; if 1 then this was the last byte ; go to decode ; movlw 0x03 ; STATE=3 ; now back to beginning of jump table ; and wait for next preamble movwf STATE nop nop nop nop retlw 0 end32x: clrf STATE ; reset STATE for next preamble clrf ENDVAL clrf DATA_4 clrf DATA_X goto decode ; let's see what we got ;***************************************************** ; This section is not used because we only ; accept three byte commands !! ; ;****************************************************** ; end41 ; end of third byte there must be a one ; ; end42 first half bit ; end42 second half bit ; STATE = 25 (ENDVAL=4) end41: incf STATE,F incf ENDVAL,F nop nop nop nop nop nop nop nop retlw 0 ; 9 cycl. ; STATE = 26 (ENDVAL=4) end42: movf DATA_X,W movwf DATA_4 btfsc CONFBITS,bit_rec ; CONFBITS(bit0) ; - if 0 other bytes will follow goto end42x movlw 0x03 ; point STATE to beginning of jump table movwf STATE nop nop nop nop retlw 0 end42x: clrf STATE ; reset STATE for next preamble clrf ENDVAL clrf DATA_X goto decode ;****************************************************** ; end51 ; end of third byte there must be a one ; ; end52 first half bit ; end52 second half bit ; STATE = 27 (ENDVAL=5) end51: btfss CONFBITS,bit_rec ; CONFBITS(bit0) goto frameerr incf STATE,F incf ENDVAL,F nop nop nop nop nop nop retlw 0 ; 9 cycl. ; STATE = 28 (ENDVAL=5) end52: btfss CONFBITS,bit_rec ; CONFBITS(bit0) goto frameerr clrf STATE ; reset STATE for next preamble clrf ENDVAL ;****************************************************** ; now we can start decoding the package decode: ;*************DECODING******************************* decodebank1: movf DATA_1,W ; Exclusive or check xorwf DATA_2,W xorwf DATA_3,W xorwf DATA_4,W xorwf DATA_X,W btfss STATUS,Z ; result = 0? goto exit_bank1 ; no -> error in packet clrf TIMEOUTCOUNT ; yes -> reset packet time out adressdecode: movf ADR_OFFSET,W ; check address received xorwf DATA_1,W ; xor with our address (DATA_1) btfsc STATUS,Z ; result=0? goto DecodeAcc ; yes -> It's for us! goto exit_bank1 ; Not for us ; Clear data and goto starthi ;************************************* ; Now decode the accessory instruction ; DecodeAcc: movf EADR1,W xorwf DATA_2,W btfss STATUS,Z goto DecAcc1 ; is not the first output, ; maybe the second? ; Set signal to red movlw B'11111110' bsf STATUS,RP0 movwf TRISIO bcf STATUS,RP0 call writeEE movlw B'00000001' ;invertoitu movwf GPIO goto exit_bank1 ; Clear data and goto starthi ; second output? DecAcc1: movf EADR2,W ; compare data with the second byte xorwf DATA_2,W btfss STATUS,Z goto DecAcc2 ; not even second?? ; Set signal to green movlw B'11111101' bsf STATUS,RP0 movwf TRISIO bcf STATUS,RP0 call writeEE movlw B'00000010' ;invertoitu movwf GPIO goto exit_bank1 ; Clear data and goto starthi DecAcc2: movf EADR3,W ; Compare with third byte xorwf DATA_2,W btfss STATUS,Z goto exit_bank1 ; also not equal ; Clear data and goto starthi ; Set signal to green/yellow movlw B'11111001' bsf STATUS,RP0 movwf TRISIO bcf STATUS,RP0 call writeEE movlw B'00000110' ;invertoitu movwf GPIO goto exit_bank1 ;**** NOT NEEDED *********************************************************** ; Consist Group ;ConsistGroup: ; bcf CONFBITS,CVaccessBit ; clear CVaccess flag ; bcf CONFBITS,resetflag ; Clear resetflag ; movf DATA_1,W ; btfsc STATUS,Z ; If not zero then hard reset packet ; goto soft_reset ;hard_reset: ; goto hard_reset_jump ;soft_reset: ; bsf CONFBITS,resetflag ; set resetflag for SM mode detection ; clrf PWM ; clrf SPEEDNEW ; bsf GPIO,gp1 ; turn off motor ; bsf GPIO,gp2 ;exit_consist: ; goto exit_bank1 ; ;***************************************************************** ; Now clear everything and go back to wait DCC command exit_bank1: clrf TEMP clrf DATA_1 clrf DATA_2 clrf DATA_3 clrf DATA_4 clrf DATA_X clrf ENDVAL goto starthi ; we dont return, we goto ;************************************ ; EEPROM READ AND WRITE OPERATIONS ; ; ; Read from the EEPROM into W from EEPROM address readEE: movf EETADR,W bsf STATUS,RP0 movwf EEADR bsf EECON1,RD movf EEDAT,W bcf STATUS,RP0 return ; Writing whatever is in the W to the EEPROM at address writeEE: bsf STATUS,RP0 movwf EEDATA ; W holds data to be written bcf STATUS,RP0 movf EE_STATE,w ; ADDRESS = 0x00 ; movf EETADR,w ; sublw D'1' ; btfss STATUS,C ; Carry is set if no borrow, ; i.e. if EETADR greater than 0 ; return ; Address is equal to or greater 1, ; DO NOT WRITE! ; movf EETADR,w bsf STATUS,RP0 movwf EEADR ; EEPROM ADDRESS set bsf EECON1,WREN ; Enable write movlw 0x55 ; Write sequence movwf EECON2 ; ... movlw 0xAA ; ... movwf EECON2 ; ... bsf EECON1,WR ; ... bcf STATUS,RP0 return ;************************************************************* ; Here we have jump to beginning if program counter has messed ; org 0x3FC bcf STATUS,5 ; Bank 0 goto dcc_setup ; jump to init ;************ ; EEPROM DATA org 0x2100 ; EEPROM DATA is located at 0x2100 de B'11111110' ; EE_STATE ; initial state is GP0 low = RED de 0 ; ADDRESS_HI de D'82' ; ADDRESS_LO OSOITE 82 de "2019-09-02-A82-inv", 0 ; 2019-09-02-A82, invertoitu END