; ********************************************************************** ; * Lichtdecoder-DCC * ; * Version 1.00 * ; * Last change: 01/01/2005 * ; * Microcontroller: PIC12F629 * ; * Status: Tested * ; ********************************************************************** ; ********************************************************************** ; * (C) Copyright Gorden Griem, 2004 * ; * parts copyright by Dean Probst, Ingo Schroeter * ; ********************************************************************** ; ********************************************************************** ; * Diese Software ist freie Software, sofern es sich um den privaten * ; * Gebrauch handelt. Kommerzieller Gebrauch erst nach expliziter, * ; * schriftlicher Genehmigung des Autors erlaubt. * ; * Dieses Programm wird trotz erfolgreicher Tests ohne Garantie ver- * ; * teilt. Insbesondere existiert KEINE implizite Garante für irgend- * ; * eine Funktion. * ; ********************************************************************** ; ********************************************************************** ; * Funktionsbeschreibung: * ; * Dieser Decoder steuert vier Ausgänge, die dauerhaft an oder dauer- * ; * haft aus sind. Jeder Eingang hat eine eigene Adresse und wird * ; * eingeschaltet, indem "+" (Abzweig) an die Adresse gesendet wird * ; * und ausgeschaltet indem "-" (gerade) an die Adresse gesendet wird. * ; * Der aktuelle Zustand wird im EEPROM gespeichert, so dass der Zu- * ; * stand auch nach einem Stromverlust noch gespeichert ist. Im EEPROM * ; * werden außerdem die Adressen für die Ausgänge gespeichert. Die * ; * Ausgänge können sowohl verschiedene als auch gleiche Adressen ver- * ; * verwenden. * ; * Jeder Ausgang verwendet eine eigene Adresse. Für jeden Ausgang be- * ; * steht die Adresse aus zwei Teilen: ADRESSEH und ADRESSEL. * ; * Die tatsächliche Adresse errechnet sich aus der Formel * ; * ADRESSEH*256 + ADRESSEL * ; * Zustätzliche Features: * ; * - Überschreibschutz der Adresse im EEPROM in writeEE-Routine * ; * - internes Umrechnen von Adresse auf zu empfangendes Paket * ; ********************************************************************** ;----- Processor Definition------------------------------------------------ LIST p=12F629 ; target processor ;----- Configuration Bits ------------------------------------------------- #define _CPD_ON H'30FF' #define _CPD_OFF H'31FF' #define _CP_ON H'317F' #define _CP_OFF H'31FF' #define _BOD_EN_ON H'31FF' #define _BOD_EN_OFF H'31BF' #define _MCLRE_ON H'31FF' #define _MCLRE_OFF H'31DF' #define _PWRTE_ON H'31EF' #define _PWRTE_OFF H'31FF' #define _WDT_ON H'31FF' #define _WDT_OFF H'31F7' #define _IntRC_OSC H'31FC' ; ----- 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 & _BOD_EN_ON & _PWRTE_ON & _WDT_OFF & _MCLRE_OFF & _IntRC_OSC ; ********************************************************************** ; IO-Belegung #define gp0 0 ; Ausgang 1: Lampenausgang 1; Adresse ADRESSEH1 und ADRESSEL1 werden als Adresse verwendet #define gp1 1 ; Ausgang 2: Lampenausgang 2; Adresse ADRESSEH2 und ADRESSEL2 werden als Adresse verwendet #define gp2 2 ; unused #define gp3 3 ; data in #define gp4 4 ; Ausgang 3: Lampenausgang 3; Adresse ADRESSEH3 und ADRESSEL3 werden als Adresse verwendet #define gp5 5 ; Ausgang 4: Lampenausgang 4; Adresse ADRESSEH4 und ADRESSEL4 werden als Adresse verwendet #define nopreamb D'17' ; No. of preamble bits = 20; aber es kann ja nicht schaden, schon vorher zu reagieren ; RAM locations. EEPROM routine uses 0x1A to 0x1F ! ; ********************************************************************** ; User Variables / Benutzervariablen ; contains unused variables cblock 0x20 CONFIG ; 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 DATA1 ; First transm. byte DATA2 ; Second trans. byte DATA3 ; Third transm. byte DATA4 ; Fourth transm. byte DATA5 ; Scratch Register SAMPLES ; How many samples taken for one or zero TEMP ; Temporarly scratch reg ; the following are for EEPROM routines PC_OFFSET ; PC offset register (low order 4 bits), ; value based on operating mode of EEPROM. ; Also, bit 7 used for EE_OK flag TIMEOUTCOUNT WHOIS ; Welcher Ausgang wird beim Timer kontrolliert? EOFFS1 ; Adreßoffset Licht 1 EOFFS2 ; Adreßoffset Licht 2 EOFFS3 ; Adreßoffset Licht 3 EOFFS4 ; Adreßoffset Licht 4 EADR1 ; untere Adressbits Licht 1 EADR2 ; untere Adressbits Licht 2 EADR3 ; untere Adressbits Licht 3 EADR4 ; untere Adressbits Licht 4 EETADR ; Adresse, wenn ins EEPROM geschrieben oder daraus gelesen werden soll OUTZUS ; Zustand der Lichtausgänge: "1" bedeutet "Licht an", "0" beduetet "Licht aus" endc ; Defintion der Adressen im EEPROM ; Bit Positions in config #define bitrec 0 ; What value has just rec. bit #define CVaccessBit 1 ; Two consecutive packets to be send #define resetflag 6 ; Signal reset for service mode ;========================================================================== ; ; Register Definitions ; ;========================================================================== #define W H'0000' #define F H'0001' ;----- Register Files ----------------------------------------------------- INDF EQU H'0000' TMR0 EQU H'0001' PCL EQU H'0002' STATUS EQU H'0003' FSR EQU H'0004' GPIO EQU H'0005' OPTION_REG EQU H'0081' TRISIO EQU H'0085' OSCCAL EQU H'0090' EEDAT EQU H'009A' EEADR EQU H'009B' EECON1 EQU H'009C' EECON2 EQU H'009D' ;----- STATUS Bits -------------------------------------------------------- #define GPWUF H'0007' #define RP0 H'0005' #define NOT_TO H'0004' #define NOT_PD H'0003' #define Z H'0002' #define DC H'0001' #define C H'0000' ;----- OPTION Bits -------------------------------------------------------- #define NOT_GPPU H'0007' #define INTEDG H'0006' #define T0CS H'0005' #define T0SE H'0004' #define PSA H'0003' #define PS2 H'0002' #define PS1 H'0001' #define PS0 H'0000' ;----- OSCCAL Bits -------------------------------------------------------- #define OSCFST H'0003' #define OSCSLW H'0002' ;----- EECON1 Bits -------------------------------------------------------- #define WRERR H'0003' #define WREN H'0002' #define WR H'0001' #define RD H'0000' ;************* Hier geht es los! +********************** ; org 0 bsf STATUS,RP0 call 3FFh ; load calibration value movwf OSCCAL ;put calibration value into OSCCAL bcf STATUS,RP0 goto dccsetup ;jump over EEPROM routine adn 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 ; Platz für Updates org 80 ; TimerInc wird von Value aus etwa alle 4 ms aufgerufen. Dann wird ; je nachdem, wer dran ist, einer der Ausgänge oder die "Löschprozedur" ; aufgerufen. TimerInc: clrf TMR0 ; "04" incf WHOIS,F movf WHOIS,W addwf PCL,F ; "07" nop ; Darf nicht auftauchen goto TimEnde ; "09" goto TimEnde ; "09" TimEnde: clrf WHOIS ; "11" goto TimE12 ; "12" TimE12: goto TiDon ; "14" ; Die Routine, die ein neues Bit bearbeitet Value: ; movf SAMPLES,W ;use only when needed to check for 0 samples ; btfsc STATUS,Z ; goto nosample ; nop nop nop btfsc TMR0,6 ; Wenn Bit 6 gesetzt ist, ist etwa 4ms vergangen goto TimerInc ; "00" nop ;26us sample nop nop nop nop nop nop nop nop nop nop nop nop TiDon: clrf SAMPLES movf STATE,W addwf PCL,F ;cycl to here ;Jump table to routines from where we do a RETURN ! goto waitn ;cycl. to here -> cycl for rout. goto waitlo goto testlo ; First byte goto bitset goto lastv goto bitset goto lastv goto bitset goto lastv goto bitset goto lastv goto bitset goto lastv goto bitset goto lastv goto bitset goto lastv goto bitset goto lastx ; Byte received goto end11 ; Check first half bit of byte goto end12 ; Check second half bit of byte goto end21 goto end22 goto end31 goto end32 goto end41 goto end42 goto end51 goto end52 ;****************************************************** ;************* setup sets all what is ness. *********** dccsetup: movlw EEZUSTAND movwf EETADR call readEE movwf OUTZUS movlw B'00000000' movwf GPIO ; Turn all lights off. bsf STATUS,RP0 movlw B'00001100' movwf TRISIO ; All except gp3 are outputs (gp2 unused, so input!) bcf STATUS,RP0 movf OUTZUS,w ; Load the current on/off state into the GPIOs movwf GPIO ; Turn all lights off. ;****************************************************** ;*** Einlesen der Adresse. Wenn die Adresse folgendermaßen gegeben ist ;*** High: 00000abc Low: defghikm ;*** dann muss dies in zwei Bytes folgendermaßen umgestellt werden: ;*** EOFFS: 10defghi ;*** EADRx: 1abc1kmx wobei abc invertiert sind ;*** Hinweis: Adresse "x" dient der Unterscheidung ob gerade (=0) oder Abzweig (=1) ;*** Außerdem ist Adresse "1" nicht, wie man schätzen würde, die mit defghi=0, sondern es ;*** sind bereits defghi=000001. Daher muss "3" zur im EEPROM gespeicherten Adresse hinzu- ;*** addiert werden, damit die korrekt Adresse angesprochen wird. Für Adresse 257 etc hingegen ;*** ist dann defghi=000000 erlaubt. movlw ADRESSEH1 ; Einlesen der oberen drei Adressbits für Licht 1 movwf EETADR call readEE ; Aus dem EEPROM lesen movwf TEMP rlf TEMP,f ; Die Bits viermal nach links verschieben rlf TEMP,f rlf TEMP,f rlf TEMP,w andlw B'01110000' ; andere Bits (Müll) ausblenden xorlw B'01110000' ; Bits umdrehen, weil die oberen drei Adreßbits invertiert sind iorlw B'10001000' ; Diese Bits sind Standard movwf EADR1 ; Obere 3 Bits für Licht 1 speichern movlw ADRESSEH2 ; Einlesen der oberen drei Adressbits für Licht 2 movwf EETADR call readEE ; Aus dem EEPROM lesen movwf TEMP rlf TEMP,f ; Die Bits viermal nach links verschieben rlf TEMP,f rlf TEMP,f rlf TEMP,w andlw B'01110000' ; andere Bits (Müll) ausblenden xorlw B'01110000' ; Bits umdrehen, weil die oberen drei Adreßbits invertiert sind iorlw B'10001000' ; Diese Bits sind Standard movwf EADR2 ; Obere 3 Bits für Licht 2 speichern movlw ADRESSEH3 ; Einlesen der oberen drei Adressbits für Licht 3 movwf EETADR call readEE ; Aus dem EEPROM lesen movwf TEMP rlf TEMP,f ; Die Bits viermal nach links verschieben rlf TEMP,f rlf TEMP,f rlf TEMP,w andlw B'01110000' ; andere Bits (Müll) ausblenden xorlw B'01110000' ; Bits umdrehen, weil die oberen drei Adreßbits invertiert sind iorlw B'10001000' ; Diese Bits sind Standard movwf EADR3 ; Obere 3 Bits für Licht 3 speichern movlw ADRESSEH4 ; Einlesen der oberen drei Adressbits für Licht 4 movwf EETADR call readEE ; Aus dem EEPROM lesen movwf TEMP rlf TEMP,f ; Die Bits viermal nach links verschieben rlf TEMP,f rlf TEMP,f rlf TEMP,w andlw B'01110000' ; andere Bits (Müll) ausblenden xorlw B'01110000' ; Bits umdrehen, weil die oberen drei Adreßbits invertiert sind iorlw B'10001000' ; Diese Bits sind Standard movwf EADR4 ; Obere 3 Bits für Licht 4 speichern movlw ADRESSEL1 ; Einlesen der unteren 8 Adressbits für Licht 1 movwf EETADR call readEE ; aus dem EEPROM lesen 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 rlf TEMP,w ; nach links schieben andlw B'00000110' ; nur die untersten 2 Adressbits speichern iorwf EADR1,f rrf TEMP,f ; die unteren zwei Adreßbits rausschieben rrf TEMP,w andlw B'00111111' ; ggf. hereingeschobene Bits löschen iorlw B'10000000' ; oben eine "1" setzen movwf EOFFS1 ; dies ist der zu empfangende Offset für Licht 1 movlw ADRESSEL2 ; Einlesen der unteren 8 Adressbits für Licht 2 movwf EETADR call readEE ; aus dem EEPROM lesen 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 rlf TEMP,w ; nach links schieben andlw B'00000110' ; nur die untersten 2 Adressbits speichern iorwf EADR2,f rrf TEMP,f ; die unteren zwei Adreßbits rausschieben rrf TEMP,w andlw B'00111111' ; ggf. hereingeschobene Bits löschen iorlw B'10000000' ; oben eine "1" setzen movwf EOFFS2 ; dies ist der zu empfangende Offset für Licht 2 movlw ADRESSEL3 ; Einlesen der unteren 8 Adressbits für Licht 3 movwf EETADR call readEE ; aus dem EEPROM lesen 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 rlf TEMP,w ; nach links schieben andlw B'00000110' ; nur die untersten 2 Adressbits speichern iorwf EADR3,f rrf TEMP,f ; die unteren zwei Adreßbits rausschieben rrf TEMP,w andlw B'00111111' ; ggf. hereingeschobene Bits löschen iorlw B'10000000' ; oben eine "1" setzen movwf EOFFS3 ; dies ist der zu empfangende Offset für Licht 3 movlw ADRESSEL4 ; Einlesen der unteren 8 Adressbits für Licht 4 movwf EETADR call readEE ; aus dem EEPROM lesen 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 rlf TEMP,w ; nach links schieben andlw B'00000110' ; nur die untersten 2 Adressbits speichern iorwf EADR4,f rrf TEMP,f ; die unteren zwei Adreßbits rausschieben rrf TEMP,w andlw B'00111111' ; ggf. hereingeschobene Bits löschen iorlw B'10000000' ; oben eine "1" setzen movwf EOFFS4 ; dies ist der zu empfangende Offset für Licht 4 ; clear RAM now movlw 0x7 ; bottom of RAM movwf FSR movlw nopreamb ; Preamble = 20 half bits movwf PRECOUNT clrf TIMEOUTCOUNT ; clear packet time out ;****************************************************** ; call master init ; Laden der default-Werte MasterInit: hard_reset_jump: clrf STATE clrf ENDVAL clrf DATA1 clrf DATA2 clrf DATA3 clrf DATA4 clrf DATA5 clrf WHOIS ; call setadr ; den Timer so setzen, daß er alle 64us inkrementiert movlw B'11000101' bsf STATUS,RP0 movwf OPTION_REG bcf STATUS,RP0 goto starthi ; Setzen der Adresse. Soll die Adresse im Nachhinein geändert werden, so kann man hier einfach 9x NOP schreiben und dann was hier steht ; erneut hinschreiben, dann wird die neue Adresse verwendet. setadr: ; movlw EMPFBYTE1 ; movwf EOFFS ; movlw EMPFBYTE2O1 ; movwf EADR1 ; movlw EMPFBYTE2O2 ; movwf EADR2 ; movlw EMPFBYTE2O3 ; movwf EADR3 ; movlw EMPFBYTE2O4 ; movwf EADR4 retlw 0 org 0x230 ;****************************************************** ; 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: btfss GPIO,gp3 goto startlo btfss SAMPLES,7 incf SAMPLES,F bcf CONFIG,bitrec bcf STATUS,C movlw 0xFC addwf SAMPLES,W btfss STATUS,C bsf CONFIG,bitrec nop nop goto conthi startlo: call Value contlo: btfsc GPIO,gp3 goto starthi btfss SAMPLES,7 incf SAMPLES,F bcf CONFIG,bitrec bcf STATUS,C movlw 0xFC addwf SAMPLES,W btfss STATUS,C bsf CONFIG,bitrec nop nop goto contlo ;****************************************************** nosample: ; movlw nopreamb ; movwf PRECOUNT ; clrf STATE ; clrf SAMPLES ; clrf ENDVAL ; return ;****************************************************** ; Frame error in packet frameerr: movlw nopreamb movwf PRECOUNT clrf STATE clrf ENDVAL clrf DATA1 clrf DATA2 clrf DATA3 clrf DATA4 clrf DATA5 clrf SAMPLES movlw 0xF0 ; cut of low nibble andwf CONFIG,F retlw 0 ;****************************************************** ; waitn waits for 20 half bits of the preamble waitn: nop nop nop btfss CONFIG,bitrec ; there are only ones in preamble goto waitn1 decfsz PRECOUNT,F goto ret4 movlw nopreamb movwf PRECOUNT incf STATE,F retlw 0 ; 9 cycl. ret4: nop nop retlw 0 ; 9 cycl. waitn1: movlw nopreamb movwf PRECOUNT nop nop retlw 0 ;****************************************************** ; waitlo waits for low half bit after preamble waitlo: decfsz TIMEOUTCOUNT,F goto waitlo1 goto dccsetup waitlo1: nop nop nop nop btfsc CONFIG,bitrec ; must be a zero goto ret5 ; might be long preamble incf STATE,F ret5: retlw 0 ; 9 cycl ;****************************************************** ; testlo test second half bit of start bit testlo: nop nop nop nop nop nop nop btfsc CONFIG,bitrec ; must be a zero goto frameerr incf STATE,F retlw 0 ; 9 cycl ;****************************************************** ; bitset takes first half bit of a bit in the byte bitset: incf STATE,F bcf STATUS,C btfsc CONFIG,bitrec bsf STATUS,C rlf DATA5,F nop nop nop nop nop retlw 0 ; 9 cycl. ;****************************************************** ; lastv checks that first half bit = second half bit lastv: nop nop nop nop incf STATE,F btfss CONFIG,bitrec goto lastv1 btfss DATA5,0 goto frameerr ; error if not equal nop retlw 0 ; 9 cycl. lastv1: btfsc DATA5,0 goto frameerr ; error if not equal retlw 0 ; 9 cycl. ;****************************************************** ; lastx checks that first half bit = second half bit ; and sets offset to byte check routine lastx: incf ENDVAL,F movf ENDVAL,W addwf STATE,F nop nop btfss CONFIG,bitrec goto lastx1 btfss DATA5,0 goto frameerr ; error if not equal nop retlw 0 ; 9 cycl. lastx1: btfsc DATA5,0 goto frameerr ; error if not equal retlw 0 ; 9 cycl. ;****************************************************** ; end11 end of first byte there must be zero ; end11 first half bit. end12 second half bit end11: btfsc CONFIG,bitrec goto frameerr incf STATE,F incf ENDVAL,F nop nop nop nop nop nop retlw 0 ; 9 cycl. end12: btfsc CONFIG,bitrec goto frameerr movf DATA5,W movwf DATA1 movlw 0x03 ; point STATE to beginning of jump table movwf STATE 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 end21: btfsc CONFIG,bitrec goto frameerr incf STATE,F incf ENDVAL,F nop nop nop nop nop nop retlw 0 ; 9 cycl. end22: btfsc CONFIG,bitrec goto frameerr movf DATA5,W movwf DATA2 movlw 0x03 ; point STATE 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 end31: incf STATE,F incf ENDVAL,F nop nop nop nop nop nop nop nop retlw 0 ; 9 cycl. end32: movf DATA5,W movwf DATA3 btfsc CONFIG,bitrec ; if 0 other bytes will follow goto end32x movlw 0x03 ; point STATE to beginning of jump table movwf STATE nop nop nop nop retlw 0 end32x: clrf STATE ; reset STATE for next preamble clrf ENDVAL clrf DATA4 clrf DATA5 goto decode ;****************************************************** ; end41 end of third byte there must be a one ; end42 first half bit. end42 second half bit end41: incf STATE,F incf ENDVAL,F nop nop nop nop nop nop nop nop retlw 0 ; 9 cycl. end42: movf DATA5,W movwf DATA4 btfsc CONFIG,bitrec ; 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 DATA5 goto decode ;****************************************************** ; end51 end of third byte there must be a one ; end52 first half bit. end52 second half bit end51: btfss CONFIG,bitrec goto frameerr incf STATE,F incf ENDVAL,F nop nop nop nop nop nop retlw 0 ; 9 cycl. end52: btfss CONFIG,bitrec goto frameerr clrf STATE ; reset STATE for next preamble clrf ENDVAL ;****************************************************** ; now we can start decoding the package ;***************************************************************** ; Consist Group ConsistGroup: bcf CONFIG,CVaccessBit ; clear CVaccess flag bcf CONFIG,resetflag ; Clear resetflag movf DATA1,W btfsc STATUS,Z ; If not zero then hard reset packet goto soft_reset hard_reset: goto hard_reset_jump soft_reset: bsf CONFIG,resetflag ; set resetflag for SM mode detection ; clrf PWM ; clrf SPEEDNEW ; bsf GPIO,gp1 ; turn off motor ; bsf GPIO,gp4 exit_consist: goto exit_bank1 ;***************************************************************** exit_bank1: clrf TEMP clrf DATA1 clrf DATA2 clrf DATA3 clrf DATA4 clrf DATA5 clrf ENDVAL goto starthi ; we dont return, we goto decode: ;*************DECODING******************************* decodebank1: xorlw 0xFF movf DATA1,W ; Exclusive or check xorwf DATA2,W xorwf DATA3,W xorwf DATA4,W xorwf DATA5,W btfss STATUS,Z goto exit_bank1 ; error in packet clrf TIMEOUTCOUNT ; reset packet time out adressdecode: btfss DATA2,7 ; Wenn das oberste Bit gesetzt ist, dann handelt es sich um einen Schaltbefehl... goto DecodeSteuer; ... sonst um einen Befehl zum Setzen von CVs movf OUTZUS,w ; Save the current light status in TEMP movwf TEMP movf EADR1,W xorwf DATA2,W andlw B'11111110' btfsc STATUS,Z call DecLi1 movf EADR2,W xorwf DATA2,W andlw B'11111110' btfsc STATUS,Z call DecLi2 movf EADR3,W xorwf DATA2,W andlw B'11111110' btfsc STATUS,Z call DecLi3 movf EADR4,W xorwf DATA2,W andlw B'11111110' btfsc STATUS,Z call DecLi4 movf OUTZUS,w ; Test whether any light has been turned on or off xorwf TEMP,w btfsc STATUS,Z goto exit_bank1 ; OUTZUS and TEMP are equal, so no light has been changed movf OUTZUS,w ; Some light (possible several) changed, so set outputs to new state movwf GPIO movlw EEZUSTAND ; The address to write to is... movwf EETADR ; ... EEZUSTAND (state of lights) movf OUTZUS,w ; Put the value that needs to be written into W call writeEE goto exit_bank1 ; All tested ; Decode status of light 1 DecLi1: movf EOFFS1,W xorwf DATA1,W btfss STATUS,Z return ; upper address bits and received do not agreee ; Now set the light as it is btfsc DATA2,0 ; Bit 0 is set if light is turned on bsf OUTZUS,gp0 ; Bit is set, so turn light on btfss DATA2,0 ; Bit 0 is cleared if light is turned off bcf OUTZUS,gp0 ; Bit is cleared, so turn light off return ; Decode status of light 2 DecLi2: movf EOFFS2,W xorwf DATA1,W btfss STATUS,Z return ; upper address bits and received do not agreee ; Now set the light as it is btfsc DATA2,0 ; Bit 0 is set if light is turned on bsf OUTZUS,gp1 ; Bit is set, so turn light on btfss DATA2,0 ; Bit 0 is cleared if light is turned off bcf OUTZUS,gp1 ; Bit is cleared, so turn light off return ; Decode status of light 3 DecLi3: movf EOFFS3,W xorwf DATA1,W btfss STATUS,Z return ; upper address bits and received do not agreee ; Now set the light as it is btfsc DATA2,0 ; Bit 0 is set if light is turned on bsf OUTZUS,gp4 ; Bit is set, so turn light on btfss DATA2,0 ; Bit 0 is cleared if light is turned off bcf OUTZUS,gp4 ; Bit is cleared, so turn light off return ; Decode status of light 4 DecLi4: movf EOFFS4,W xorwf DATA1,W btfss STATUS,Z return ; upper address bits and received do not agreee ; Now set the light as it is btfsc DATA2,0 ; Bit 0 is set if light is turned on bsf OUTZUS,gp5 ; Bit is set, so turn light on btfss DATA2,0 ; Bit 0 is cleared if light is turned off bcf OUTZUS,gp5 ; Bit is cleared, so turn light off return ; Wir haben keinen Schaltbefehl erhalten, aber es sieht nach einem CV-Setzen-Befehl aus ; THIS NEEDS TO BE CHANGED! DecodeSteuer: movf DATA2,w ; Testen, ob der Befehl wirklich "CV 512 Setzen lautet" xorlw B'00001010' andlw B'00001111' btfss STATUS,Z goto exit_bank1 ; Nein, lautet er nicht movf DATA3,w btfss STATUS,Z goto exit_bank1 ; Data 3 muss lauter Nullen sein, damit Daten geschrieben werden movf DATA2,w xorwf EADR2,W andlw B'01110000' ; XOR mit anderen Adreßbits (Hinweis: Dann irgendein EADR nehmen, weil die Bits alle gleich sind btfss STATUS,Z goto exit_bank1 ; Leider falsche Adresse ; So, richtige Adresse und alles liegt vor, nun heisst es: CV schreiben! movlw H'2' ; So, die Adresse bitte an Position 2 schreiben movwf EETADR movf DATA4,w ; Daten nach W, damit sie geschrieben werden call writeEE ; Schreiben! ; Nun warten, bis Schreiben vorbei, dann Reset bsf STATUS,RP0 wp: btfsc EECON1,WR goto wp bcf STATUS,RP0 goto hard_reset_jump ; 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 EETADR if EETADR < 1 ; (ensures no errenous writes can occur) writeEE: bsf STATUS,RP0 movwf EEDAT bcf STATUS,RP0 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 bsf EECON1,WREN movlw 0x55 movwf EECON2 movlw 0xAA movwf EECON2 bsf EECON1,WR bcf STATUS,RP0 return ; Hier kommt an eine der letzten Stellen ein Sprung an die Setup-Adresse. ; Nur für den Fall, daß sich der Program Counter verlaufen hat org 0x3FC bcf STATUS,5 ; Auf Bank 0 wechseln goto dccsetup ; zur Initialisierung ;#include 12c7.eep ; load eeprom routines ; /** org 0x2100 EEZUSTAND de B'00000011' ; this state means: two outputs on, two outputs off ADRESSEH1 de 1 ADRESSEL1 de D'1' ADRESSEH2 de 1 ADRESSEL2 de D'2' ADRESSEH3 de 1 ADRESSEL3 de D'3' ADRESSEH4 de 1 ADRESSEL4 de D'4' END