Quelltext /~heha/basteln/m/Kram/dccrail-avrgcc.zip/binärgleich/Programmierung.S

/********************************************************************************
 * DCC Wagen Decoder Software V1.0						*
 * Copyright 2011 Toralf Wilhelm						*
 *										*
 * private Nutzung erwünscht, gewerbliche Nutzung erfordert zwingend meine Zustimmung! *
 * Datei:	Programmierung.S						*
 * Kontakt:	toralfwilhelm@web.de						*
 * Webseite:	www.toralfwilhelm.de						*
 * Version:	04/2012 Version 1 Start						*
 * Beschreibung: programmiert die CV Register der DCC Wagen Decoder Software	*
 ********************************************************************************/
#include "definitionen.h"

CV_edit:
	mov	w,byteB		// w mit Befehlsbyte laden
	mov	w2,byteC	// w2 mit CV Nummer laden
	mov	w3,byteD	// w3 mit CV Daten laden
	mov	w4,byteE	// w4 mit Prüfbyte laden
	cbr	flag,(1<<neuerBefehl)	// Daten gesichert Empfangsspeicher wieder freigeben

	cbr	w,0b00000011	// adressbits ausblenden nur die ersten 256 CV werden verwendet/benötigt
	cpi	w,0b11101100	// Befehlsbyte auf CV Byte schreiben testen
	breq	CV_schreibe_Byte	// gehe zu CV Byte schreiben
	cpi	w,0b11100100
	breq	CV_vergleiche_Byte	// gehe zu CV Byte vergleichen
	cpi	w,0b11101000
	breq	CV_manipuliere_Bit	// gehe zu CV Bit Manipulation
	ret			// wenn nicht zurück

CV_schreibe_Byte:
	lds	w,ProgTest	// vergleiche mit vorherigen Daten (XOR-Byte)
	cp	w,w4		// mit Prüfbyte vergleichen
	breq	ProgTest_ok	// springe wenn gleich
	sts	ProgTest,w4	// ansonsten merke letzte Daten zum vergleich auf 2x Gleiche Daten
	ret			// und zurück
ProgTest_ok:
	ldi	ZL,lo8(CVtest)	// zl/h auf CVmin setzen
	ldi	ZH,hi8(CVtest)
 	mov	w,w2		// zu schreibendes Cv (steht in w2) auf min/max testen
	clc
	rol	w
	add	ZL,w
	clr	w
	adc	ZH,w
	lpm	w,z+		// CVmin holen
	cp	w3,w		// neue Daten (sind in w3) mit minimal Wert vergleichen
	brsh	3f		// wenn größer oder gleich
	ret			// ansonsten Fehler -> zurück
3:	lpm	w,z		// CVmax holen
	cp	w,w3		// maxWert mit neuen Daten vergleichen
	brsh	3f		// wenn größer oder gleich
	ret			// ansonsten Fehler -> zurück
3:	sts	EE_Adresse,w2	// setzte EEprom Adresse (w2)
	mov	w,w3		// setze Daten (w3)
	rcall	eepromschreiben	// sichere neue Daten im EEprom
	rcall	PROG_BEST	// jetzt erst bestätigen (damit schreibvorgang nicht gestört wird)
	rcall	DATEN_NEU_EINLESEN	// und Dekoderdaten neu einlesen
	ret			// und fertig

CV_vergleiche_Byte:
	sts	EE_Adresse,w2	// setzte EEprom Adresse (CV-Nr steht in w2)
	rcall	eepromlesen	// hole aktuellen Wert der CV
	cp	w,w3		// Vergleiche
	brne	1f
	rcall	PROG_BEST	// wenn gleich bestätige
1:	ret

CV_manipuliere_Bit:
	sts	EE_Adresse,w2	// setzte EEprom Adresse (CV-Nr steht in w2)
	rcall	eepromlesen	// hole aktuellen Wert der CV
	sbrc	w3,4		// wenn Bit = 0 -> Bit vergleichen 1x springen
	rjmp	Bit_schreiben
Bit_vergleichen:		// einzelnes Bit vergleichen
	sbrs	w3,3		// je nach bit w4 komplett setzen oder löschen
	clr	w4		// wenn bit auf Low getestet werden soll w4 löschen
	sbrc	w3,3
	ldi	w4,0xFF		// wenn bit auf High getestet werden soll w4 setzen
	eor	w,w4		// vergleiche CV mit w4 (einfach CV xor mit bit)
	cbr	w3,0b11111000	// Befehlsteil löschen nur Bitnummer stehen lassen
	tst	w3		// bit0 angefragt ?
	brne	bit_1_vgl	// wenn nicht weiter mit bit1
	sbrs	w,0		// wenn bit0 ungleich 1x springen -> fertig
	rcall	PROG_BEST	// wenn gleich zu PROG_BEST
	ret
bit_1_vgl:
	cpi	w3,1		// bit1 angefragt ?
	brne	bit_2_vgl	// wenn nicht weiter mit bit2
	sbrs	w,1		// wenn bit1 ungleich 1x springen -> fertig
	rcall	PROG_BEST	// wenn gleich zu PROG_BEST
	ret
bit_2_vgl:
	cpi	w3,2
	brne	bit_3_vgl
	sbrs	w,2		// wenn bit2 ungleich 1x springen -> fertig
	rcall	PROG_BEST	// wenn gleich zu PROG_BEST
	ret
bit_3_vgl:
	cpi	w3,3
	brne	bit_4_vgl
	sbrs	w,3		// wenn bit3 ungleich 1x springen -> fertig
	rcall	PROG_BEST	// wenn gleich zu PROG_BEST
	ret
bit_4_vgl:
	cpi	w3,4
	brne	bit_5_vgl
	sbrs	w,4		// wenn bit4 ungleich 1x springen -> fertig
	rcall	PROG_BEST	// wenn gleich zu PROG_BEST
	ret
bit_5_vgl:
	cpi	w3,5
	brne	bit_6_vgl
	sbrs	w,5		// wenn bit5 ungleich 1x springen -> fertig
	rcall	PROG_BEST	// wenn gleich zu PROG_BEST
	ret
bit_6_vgl:
	cpi	w3,6
	brne	bit_7_vgl
	sbrs	w,6		// wenn bit6 ungleich 1x springen -> fertig
	rcall	PROG_BEST	// wenn gleich zu PROG_BEST
	ret
bit_7_vgl:
	sbrs	w,7		// wenn bit7 ungleich 1x springen -> fertig
	rcall	PROG_BEST	// wenn gleich zu PROG_BEST
	ret

Bit_schreiben:			// einzelnes Bit schreiben
	bst	w3,3		// das zu schreibene Bit sichern
	cbr	w3,0b11111000	// Befehlsbits löschen
	tst	w3		// auf bit0 testen
	brne	bit_1		// wenn ungleich weiter mit bit 1
	bld	w,0		// bit ablegen
	rjmp	CV_sichern	// und CV wieder speichern
bit_1:	cpi	w3,1		// auf bit1 testen
	brne	bit_2
	bld	w,1
	rjmp	CV_sichern	// und CV wieder speichern
bit_2:	cpi	w3,2
	brne	bit_3
	bld	w,2
	rjmp	CV_sichern	// und CV wieder speichern
bit_3:	cpi	w3,3
	brne	bit_4
	bld	w,3
	rjmp	CV_sichern	// und CV wieder speichern
bit_4:	cpi	w3,4
	brne	bit_5
	bld	w,4
	rjmp	CV_sichern	// und CV wieder speichern
bit_5:	cpi	w3,5
	brne	bit_6
	bld	w,5
	rjmp	CV_sichern	// und CV wieder speichern
bit_6:	cpi	w3,6
	brne	bit_7
	bld	w,6
	rjmp	CV_sichern	// und CV wieder speichern
bit_7:	bld	w,7

CV_sichern:
	rcall	eepromschreiben	// sichere neue Daten im EEprom
	rcall	DATEN_NEU_EINLESEN	// und Dekoderdaten neu einlesen
	rcall	PROG_BEST	// und PROG_BEST
	ret

/****************************
 * CV Progmodus-ServiceMode *
 ****************************
Format Dekoder Service Mode
wenn Reset/Grundstellungspaket empfangen wurde, dann wird automatisch danach hierher verzweigt
		byteA      byteB      byteC      byteD
long-preamble 0 0111CCAA 0 AAAAAAAA 0 DDDDDDDD 0 EEEEEEEE 1
		0111-> Direct CV Addressing
		    CC-> 10 Bit Manipulation
		    CC-> 01 Verify byte
		    CC-> 11 Write byte
		      AA   AAAAAAAA-> 10 bit Adresse plus 1 CV #1 is defined by the address 00 00000000
			   DDDDDDDD-> Datenbyte
			   EEEEEEEE-> EOR Prüfbyte
		    CC-> 10 Bit manipulation
		      AA   AAAAAAAA-> 10 bit Adresse plus 1 CV #1 is defined by the address 00 00000000
				1110Daaa-> Vergleich in der CV aus Adresse Bit aaa mit Wert in D
				1111Daaa-> Schreiben des Wertes in D in das Bit aaa innerhalb der CV aus Adresse
*/

SERVICE_MODE:
	tst	byteA		// auf DekoderReset testen
	brne	SM_machen	// wenn nicht 1x springen
	rjmp	DCCreset	// wenn ja Reset machen
SM_machen:
	mov	w,byteA		// w mit Befehlsbyte laden
	mov	w2,byteB	// w2 mit CV Nummer laden
	mov	w3,byteC	// w3 mit CV Daten laden
	mov	w4,byteD	// w4 mit Prüfbyte laden
	cbr	flag,(1<<neuerBefehl)	// Daten gesichert Empfangsspeicher wieder freigeben

	cbr	w,0b00000011	// adressbits ausblenden nur die ersten 256 CV werden verwendet/benötigt
	cpi	w,0b01111100	// prüfe Funktionscode auf CV Write Byte Schreiben
	breq	SM_schreibe_Byte	// gehe zu CV Byte schreiben
	cpi	w,0b01110100
	breq	SM_vergleiche_Byte	// gehe zu CV Byte vergleichen
	cpi	w,0b01111000
	breq	SM_manipuliere_Bit	// gehe zu CV Bit Manipulation
	cbr	flag,(1<<resetbit)	// lösche Reset und dann zurück
	ret

SM_schreibe_Byte:	// Reset hier nicht löschen, weil Daten erst 2x gleich angekommen sein müssen
	rcall	CV_schreibe_Byte
	ret

SM_vergleiche_Byte:
	rcall	CV_vergleiche_Byte
	cbr	flag,(1<<resetbit)	// lösche Reset und dann normal weiter
	ret

SM_manipuliere_Bit:
	rcall	CV_manipuliere_Bit
	cbr	flag,(1<<resetbit)	// lösche Reset und dann normal weiter
	ret

/**************************
 * Programmierbestätigung *
 **************************/
PROG_BEST:
	sbrs	flag,resetbit	// wenn 1 war reset da als ServiceMode -> Fahrzeug steht ACK durch Stromerhöhung
	ret	// sonst fertig (hier kann mal Ack über RailCom gemacht werden)
	cbr	flag,(1<<resetbit)	// lösche Reset

	sbi	Ack_port,Ack_pin
	// Timer0 ist frei -> dafür nutzen
	in	w,TIFR		// zuerst Int-Flag löschen
	sbr	w,(1<<TOV0)
	out	TIFR,w
	ldi	w,209		// Zähler auf 209 -> noch 47x bis Überlauf
	out	TCNT0,w		// setze Zeit für Bestätigung
	ldi	w,0b00000101	// 1 0 1 CK/1024 für Resetzeit
	out	TCCR0,w
0:	in	w,TIFR		// hole Timer Interuptflag
	sbrs	w,TOV0		// auf Überlauf warten (1/8MHZ=125µs*1024*56=7,168ms)
	 rjmp	0b		// Schleife
	clr	w		// wenn Ackzeit abgelaufen Timer wieder anhalten
	out	TCCR0,w

	cbi	Ack_port,Ack_pin

	ret

// min/max für CVs
.type CVtest,@common	// nicht disassemblieren
CVtest:
.byte 1,127	//CV1 Dekoderaddresse 1-127
.byte 0xFF,0xFF
.byte 0xFF,0xFF
.byte 0xFF,0xFF
.byte 0xFF,0xFF
.byte 0xFF,0xFF	//CV6
.byte 42,42	//CV7 Software-Version
.byte 0x0D,0x0D	//CV8 Herstellerkennung
.byte 0xFF,0xFF
.byte 0xFF,0xFF
.byte 0xFF,0xFF
.byte 0xFF,0xFF
.byte 0,0xFF	//CV13 Analogmodus aktive Funktionen 1 = F0 ein 2 = F1 ein bis 255 = F7 ein
.byte 0xFF,0xFF
.byte 0xFF,0xFF
.byte 0xFF,0xFF
.byte 192,231	//CV17 Erweiterte Adresse Höherwertiges Byte der langen Adresse plus 192
.byte 0,0xFF	//CV18 Erweiterte Adresse Niederwertiges Byte der langen Adresse
.byte 0xFF,0xFF
.byte 0xFF,0xFF
.byte 0xFF,0xFF
.byte 0xFF,0xFF
.byte 0xFF,0xFF
.byte 0xFF,0xFF
.byte 0xFF,0xFF
.byte 0xFF,0xFF
.byte 0xFF,0xFF
.byte 0xFF,0xFF
.byte 0,0xFF	//CV29 Konfiguration nach DCC-Norm
.byte 0,1	//CV30 Softwareupdate
.byte 190,230	//CV31 U_LED 205 ca. 4,2V (je nach interner Reverenz)
.byte 0,1	//CV32 1 = Lipobetrieb
.byte 0,0xFF	//CV33 AUX_1_FKT
.byte 0,0xFF	//CV34 
.byte 0,0xFF	//CV35 
.byte 0,0xFF	//CV36 
.byte 0,0xFF	//CV37 
.byte 0,0xFF	//CV38 
.byte 0,0xFF	//CV39 
.byte 0,0xFF	//CV40 
.byte 0,0xFF	//CV41 
.byte 0,0xFF	//CV42 
.byte 0,0xFF	//CV43 
.byte 0,0xFF	//CV44 
.byte 0,0xFF	//CV45 
.byte 0,0xFF	//CV46 
.byte 0,0xFF	//CV47 
.byte 0,0xFF	//CV48 
.byte 0,0xFF	//CV49 
.byte 0,0xFF	//CV50 AUX_18_FKT
.byte 0,0xFF	//CV51 AUX_1_EFF
.byte 0,0xFF	//CV52 
.byte 0,0xFF	//CV53 
.byte 0,0xFF	//CV54 
.byte 0,0xFF	//CV55 
.byte 0,0xFF	//CV56 
.byte 0,0xFF	//CV57 
.byte 0,0xFF	//CV58 
.byte 0,0xFF	//CV59 
.byte 0,0xFF	//CV60 
.byte 0,0xFF	//CV61 
.byte 0,0xFF	//CV62 
.byte 0,0xFF	//CV63 
.byte 0,0xFF	//CV64 
.byte 0,0xFF	//CV65 
.byte 0,0xFF	//CV66 
.byte 0,0xFF	//CV67 
.byte 0,0xFF	//CV68 AUX_18_EFF
Vorgefundene Kodierung: UTF-80