









; Test ADC Port A1 
.include "ATxmega384D3def.inc"
; zu finden unter: 
; ...\Atmel\Atmel Toolchain\AVR Assembler\Native\2.1.1175\avrassembler\include
.def	temp	= r16					; allgemeines Register R16 bekommt temp als Bezeichnung
.def	temp1	= r17					; allgemeines Register R17 bekommt temp1 als Bezeichnung
.CSEG
.ORG	0x0000							; Programmcode soll an Adresse 0000 beginnen
	ldi		temp, 0b11111111			; alle Bits in temp auf 1 setzen und
	sts		PORTB_DIR, temp				; alle Pins von Port B auf Ausgang einstellen
										; Port A braucht nicht eingestellt zu werden
// Initialisierung
 	ldi		temp, 0b00000001			; Enable ADC
	sts		ADCA_CTRLA, temp
	ldi		temp, 0b00000100			; 8 Bit Auflöung (rechtsbündig)
	sts		ADCA_CTRLB, temp
	ldi		temp, 0b00010000			; RefSpannung Vcc/1,6 (ca: 2,03 V)
	sts		ADCA_REFCTRL, temp			
	ldi		temp, 0b00000001			; single-endet
	sts		ADCA_CH0_CTRL, temp	
	ldi		temp, 0b00000000			; MUXPOS = ADC0, also PortA Pin 1 (der soll gemessen werden)
	sts		ADCA_CH0_MUXCTRL, temp	
// Starten
loop:
	ldi		temp, 0b00000101			; Enable ADC und Start
	sts		ADCA_CTRLA, temp
	 
	ldi	temp, 0xFF						; warten, bis ADC fertig
warte:
	dec temp
	brne warte
	
	lds		temp, ADCA_CH0_RESL  		; Low Byte lesen 
	sts		PORTB_OUT, temp				; und an Port B ausgeben
	nop
jmp loop
// Wenn Eingang auf Masse, dann leuchten Bit 2 und 3. Bei 1,9V leuchten alle LEDs









; Test ADC
 
.include "ATxmega384D3def.inc"
; zu finden unter: 
; ...\Atmel\Atmel Toolchain\AVR Assembler\Native\2.1.1175\avrassembler\include
.def	temp	= r16					; allgemeines Register R16 bekommt temp als Bezeichnung
.def	temp1	= r17					; allgemeines Register R17 bekommt temp1 als Bezeichnung
.CSEG
.ORG	0x0000							; Programmcode soll an Adresse 0000 beginnen

	ldi		temp, 0b11111111			; alle Bits in temp auf 1 setzen und
	sts		PORTB_DIR, temp				; alle Pins von Port B auf Ausgang einstellen
	sts		PORTA_DIR, temp				; alle Pins von Port A auf Ausgang einstellen

// Initialisierung
 	ldi		temp, 0b00000001			; Enable ADC
	sts		ADCA_CTRLA, temp
	ldi		temp, 0b00000100			; 8 Bit Auflöung (rechtsbündig)
	sts		ADCA_CTRLB, temp
	ldi		temp, 0b00000000			; RefSpannung 1v Bandgap
	sts		ADCA_REFCTRL, temp			
	ldi		temp, 0b00010000			; MUXPOS = Vcc/10 (das soll gemessen werden)
	sts		ADCA_CH0_MUXCTRL, temp	

// Starten
	ldi		temp, 0b00000101			; Enable ADC und Start
	sts		ADCA_CTRLA, temp
	 
	ldi	temp, 0xFF						; warten, bis ADC fertig
warte:
	dec temp
	brne warte

	lds		temp1, ADCA_INTFLAGS   		; Interruptflags lesen
	sts		PORTA_OUT, temp1			; und an Port A ausgeben 
		
	lds		temp, ADCA_CH0_RESL  		; Low Byte lesen 
	sts		PORTB_OUT, temp				; und an Port B ausgeben

loop:
	nop
jmp loop









; Test CRC-16
 
.include "ATxmega384D3def.inc"
; zu finden unter: 
; ...\Atmel\Atmel Toolchain\AVR Assembler\Native\2.1.1175\avrassembler\include
.def	temp	= r16					; allgemeines Register R16 bekommt temp als Bezeichnung
.def	temp1	= r17					; allgemeines Register R17 bekommt temp1 als Bezeichnung
.CSEG
.ORG	0x0000							; Programmcode soll an Adresse 0000 beginnen

	ldi		temp, 0b11111111			; alle Bits in temp auf 1 setzen und
	sts		PORTB_DIR, temp				; alle Pins von Port B auf Ausgang einstellen
	sts		PORTA_DIR, temp				; alle Pins von Port A auf Ausgang einstellen
// Initialisierung
	ldi		temp, 0b10000000			; Reset CRC zero
	sts		CRC_CTRL, temp
	ldi		temp, 0b00000001			;  Quelle = IO
	sts		CRC_CTRL, temp				;  Reset und Quelle geht nicht gleichzeitig!
// Schreiben von zwei Bytes
	ldi		temp, 0xAA					; Byte 1 (AA)
	sts		CRC_DATAIN, temp		
	ldi		temp, 0xBB					; Byte 2 (BB)
	sts		CRC_DATAIN, temp		
// Vorgang abschließen
	ldi		temp, 0b00000001			; eine 1 in BUSY schreiben
	sts		CRC_STATUS, temp

	lds		temp1, CRC_CHECKSUM0  		; Low Byte lesen 
	sts		PORTA_OUT, temp1			; und an Port A ausgeben 	
	lds		temp, CRC_CHECKSUM1 		; High Byte lesen 
	sts		PORTB_OUT, temp				; und an Port B ausgeben

loop:
	nop
jmp loop









; Test RTC
 
.include "ATxmega384D3def.inc"
; zu finden unter: 
; ...\Atmel\Atmel Toolchain\AVR Assembler\Native\2.1.1175\avrassembler\include

.def	temp	= r16					; allgemeines Register R16 bekommt temp als Bezeichnung
.CSEG
.ORG	0x0000							; Programmcode soll an Adresse 0000 beginnen

	ldi		temp, 0b0000100				; 32,768kHz Oszillator einschalten 
	sts		OSC_CTRL, temp				; 

	ldi		temp, 0b0000101				; 1,024kHz aus int. Oszillator als RTC Quelle auswählen und RTC enable 
	sts		CLK_RTCCTRL, temp			; 
	
	ldi		temp, 0b0000001				; Vorteiler RTC auf 1 (keine Teilung) 
	sts		RTC_CTRL, temp				; in das Controllregister schreiben, das startet den Zähler
	 
; damit man auch was sieht, wird das H-Byte des Zählers permanent an Port B ausgegeben 
	ldi		temp, 0b11111111			; alle Bits in temp auf 1 setzen und
	sts		PORTB_DIR, temp				; alle Pins von Port B auf Ausgang einstellen
loop:
	lds		temp, RTC_CNTL				; erst Low Byte des Zählers lesen 
	lds		temp, RTC_CNTH				; dann das High Byte lesen 
	sts		PORTB_OUT, temp				; und an Port B ausgeben
jmp loop








; Test Timer/Counter Typ 2 an Port C2 und C7
 
.include "ATxmega384D3def.inc"
; zu finden unter: 
; ...\Atmel\Atmel Toolchain\AVR Assembler\Native\2.1.1175\avrassembler\include
// Die Register liegen an den gleichen Adressen wie im Modus Typ 0, sie können also mit diesen
// Bezeichnungen angesprochen werden. Der Splitmodus muss zunächst eingeschaltet werden, dann
// könenn die Regsiter als normale 8 Bit Register beschrieben werden.

.def	temp	= r16					; allgemeines Register R16 bekommt temp als Bezeichnung
.CSEG
.ORG	0x0000							; Programmcode soll an Adresse 0000 beginnen

	ldi		temp, 0b11111111			; alle Bits in temp auf 1 setzen und
	sts		PORTC_DIR, temp				; alle Pins von Port C auf Ausgang einstellen

	ldi		temp, 0b00000010			; Splitmode einschalten
	sts		TCC0_CTRLE, temp			; in das Controllregister B schreiben

	ldi		temp, 0x80					; Wert für LPER Low Bye Counter
	sts		TCC0_PERL , temp			; direkt in Register schreiben

	ldi		temp, 0x40					; Wert für HPER High Bye Counter (doppelte Frequenz von Low byte Counter)
	sts		TCC0_PERH , temp			; direkt in Register schreiben

	ldi		temp, 0x20					; Wert für LCMPC (Low byte compare register C)
	sts		TCC0_CCCL, temp				; direkt in Register schreiben

	ldi		temp, 0x30					; Wert für HCMPD (High byte compare register D)
	sts		TCC0_CCDH, temp				; direkt in Register schreiben

	ldi		temp, 0b10000100			; Channel HD ud LC freigeben
	sts		TCC0_CTRLB, temp			; in das Controllregister B schreiben
	
	ldi		temp, 0b00000010			; Taktauswahl auf 1/2 = clk (CLKSEL = 0010)
	sts		TCC0_CTRLA, temp			; in das Controllregister A schreiben, das startet den Zähler, 
										; PWM Low byte wird an Pin C 2 und PWM High Byte wird an Pin C 7 ausgegeben
	 

loop:
	nop
jmp loop








; Test single-slope PWM mit Timer 0 an Port C2
 
.include "ATxmega384D3def.inc"
; zu finden unter: 
; ...\Atmel\Atmel Toolchain\AVR Assembler\Native\2.1.1175\avrassembler\include
// Die Datei ATxmega384D3def.inc unterscheidet nicht zwischen L und H Byte sondern kennt nur TCC0_CNT = 2080
// Muss geändert werden in 
// .equ TCC0_CNTL = 2080	// Count  L
// .equ TCC0_CNTH = 2081	// Count  H
// Das gilt bei allen Timer/Couter oder sogar bei allen 16 Bit Registern

.def	temp	= r16					; allgemeines Register R16 bekommt temp als Bezeichnung
.CSEG
.ORG	0x0000							; Programmcode soll an Adresse 0000 beginnen

	ldi		temp, 0b11111111			; alle Bits in temp auf 1 setzen und
	sts		PORTC_DIR, temp				; alle Pins von Port C auf Ausgang einstellen

	ldi		temp, 0x00					; Wert für PER L-Byte
	sts		TCC0_PERL , temp			; direkt in Register schreiben
	ldi		temp, 0x90					; Wert für PER H-Byte
	sts		TCC0_PERH , temp			; direkt in Register schreiben (PER ist die gesamt Periodendauer)

	ldi		temp, 0x00					; Wert für PER L-Byte
	sts		TCC0_CCCL, temp				; direkt in Register schreiben
	ldi		temp, 0x30					; Wert für PER H-Byte
	sts		TCC0_CCCH, temp				; direkt in Register schreiben (CCC ist die Pulsdauer, hier etwa 1/3)

	ldi		temp, 0b01000011			; Waveform single-slope PWM(WGMODE = 011) und Channel C freigeben (CCCEN)
	sts		TCC0_CTRLB, temp			; in das Controllregister B schreiben

	ldi		temp, 0b00000001			; Taktauswahl auf 1/1 = clk (CLKSEL = 0001)
	sts		TCC0_CTRLA, temp			; in das Controllregister A schreiben, das startet den Zähler, 
										; PWM wird an Pin C 2 ausgegeben
	 

loop:
	nop
jmp loop






; Test 1 Timer 0 an Port C
 
.include "ATxmega384D3def.inc"
; zu finden unter: 
; ...\Atmel\Atmel Toolchain\AVR Assembler\Native\2.1.1175\avrassembler\include
// Die Datei ATxmega384D3def.inc unterscheidet nicht zwischen L und H Byte sondern kennt nur TCC0_CNT = 2080
// Muss geändert werden in 
// .equ TCC0_CNTL = 2080	// Count  L
// .equ TCC0_CNTH = 2081	// Count  H
// Das gilt bei allen Timer/Couter oder sogar bei allen 16 Bit Registern

.def	temp	= r16					; allgemeines Register R16 bekommt temp als Bezeichnung
.CSEG
.ORG	0x0000							; Programmcode soll an Adresse 0000 beginnen
	
	ldi		temp, 0b0000111				; Taktauswahl auf 1/1024 (CLKSEL = 0111)
	sts		TCC0_CTRLA , temp			; in das Controllregister A schreiben, das startet den Zähler
	 
; damit man auch was sieht, wird das H-Byte des Zählers permanent an Port C ausgegeben 
	ldi		temp, 0b11111111			; alle Bits in temp auf 1 setzen und
	sts		PORTC_DIR, temp				; alle Pins von Port C auf Ausgang einstellen
loop:
	lds		temp, TCC0_CNTL				; erst Low Byte des Zählers lesen 
	lds		temp, TCC0_CNTH				; dann das High Byte lesen 
	sts		PORTC_OUT, temp				; und an Port C ausgeben
jmp loop




; Test Watchdog Normalmodus
 
.include "ATxmega384D3def.inc"
; zu finden unter: 
; ...\Atmel\Atmel Toolchain\AVR Assembler\Native\2.1.1175\avrassembler\include
.def	temp	= r16					; allgemeines Register R16 bekommt temp als Bezeichnung

.CSEG
.ORG	0x0000							; Programmcode soll an Adresse 0000 beginnen

	ldi		temp, 0xD8					; Signatur um geschützte I/O Register zu ändern
	sts		CPU_CCP, temp				; in CCP Register schreiben

	ldi		temp, 0b00100011			; PER=1000(2sek), ENABLE=1, CEN=1
	sts		WDT_CTRL, temp				; Bitkombination in Controlregister schreiben

	ldi		temp, 0b11111111			; alle Bits in temp auf 1 setzen und
	sts		PORTB_DIR, temp				; alle Pins von Port B auf Ausgang einstellen

	lds		temp, RST_STATUS			; Rest Flags lesen 
	sts		PORTB_OUT, temp				; und an Port B ausgeben

loop:


jmp loop









; Test Restflags
 
.include "ATxmega384D3def.inc"
; zu finden unter: 
; ...\Atmel\Atmel Toolchain\AVR Assembler\Native\2.1.1175\avrassembler\include
.def	temp	= r16					; allgemeines Register R16 bekommt temp als Bezeichnung

.CSEG
.ORG	0x0000							; Programmcode soll an Adresse 0000 beginnen

	ldi		temp, 0b11111111			; alle Bits in temp auf 1 setzen und
	sts		PORTB_DIR, temp				; alle Pins von Port B auf Ausgang einstellen

	lds		temp, RST_STATUS			; Rest Flags lesen 
	sts		PORTB_OUT, temp				; und an Port B ausgeben

	sts		RST_STATUS, temp			; durch Zurückschreiben die Flags löschen

loop:
jmp loop







; Test Bitmanipulation in GPIOR
 
.include "ATxmega384D3def.inc"
; zu finden unter: 
; ...\Atmel\Atmel Toolchain\AVR Assembler\Native\2.1.1175\avrassembler\include
.def	temp	= r16					; allgemeines Register R16 bekommt temp als Bezeichnung
.equ FLAG0 = 0							; General Purpose IO Register 0
.equ FLAG1 = 1							; General Purpose IO Register 1
.equ FLAG2 = 2							; General Purpose IO Register 2
.equ FLAG3 = 3							; General Purpose IO Register 3

.equ Senden = 0							; Sendenflag
.equ Empfang = 1						; Empfangflag

.CSEG
.ORG	0x0000							; Programmcode soll an Adresse 0000 beginnen


	sbi		FLAG0, Empfang				; Empfangsflag in Flag 0 setzen

	ldi		temp, 0b11111111			; alle Bits in temp auf 1 setzen und
	sts		PORTB_DIR, temp				; alle Pins von Port C auf Ausgang einstellen

	lds		temp, 0x0000				; Adresse 0000 lesen 
	sts		PORTB_OUT, temp				; und an Port B ausgeben


loop:
jmp loop










; Test Byte in EEPROM schreiben
 
.include "ATxmega384D3def.inc"
; zu finden unter: 
; ...\Atmel\Atmel Toolchain\AVR Assembler\Native\2.1.1175\avrassembler\include
.def	temp	= r16					; allgemeines Register R16 bekommt temp als Bezeichnung
.def	temp1	= r17					; allgemeines Register R17 bekommt temp1 als Bezeichnung

.CSEG
.ORG	0x0000							; Programmcode soll an Adresse 0000 beginnen

	ldi		ZH, 0x00					; Adresse im EEPROM in Z-Pointer ablegen
	ldi		ZL, 0x01					; nur die unteren drei Nibble sind relevant (000 bis FFF)
	ldi		temp, 0xFE					; zu schreibendes Byte

; Schreiben

flag0:
	lds		temp1, NVM_STATUS  			; Status NMV Controller lesen
	sbrc	temp1, 7					; prüfen, ob NVMBUSY gelöscht ist
	rjmp	flag0						; Schleife, wenn NVMBUSY noch gesetzt ist

	ldi		temp1, 0x33					; Commando Load EEPROM Buffer für NVM-Controller
	sts		NVM_CMD, temp1
	sts		NVM_ADDR1, ZH				; Adresse in NVM-Controller laden
	sts		NVM_ADDR0, ZL
	sts		NVM_DATA0, temp				; Byte in Datenregister schreiben, dadurch wird Commando getriggert
										; und das Byte in den Buffer geschrieben
flag1:
	lds		temp1, NVM_STATUS  			; Status NMV Controller lesen
	sbrc	temp1, 7					; prüfen, ob NVMBUSY gelöscht ist
	rjmp	flag1						; Schleife, wenn NVMBUSY noch gesetzt ist
	  
	ldi		temp1, 0x35					; Commando Erase_Write_EEPROM_Page für NVM-Controller
	sts		NVM_CMD, temp1	
	ldi		temp, 0xD8					; Signatur um geschützte I/O Register zu ändern
	sts		CPU_CCP, temp				; in CCP Register schreiben
	ldi		temp1, 0b00000001			; Command Execute Bit setzen
	sts		NVM_CTRLA, temp1	

flag2:
	lds		temp1, NVM_STATUS  			; Status NMV Controller lesen
	sbrc	temp1, 7					; prüfen, ob NVMBUSY gelöscht ist
	rjmp	flag2						; Schleife, wenn NVMBUSY noch gesetzt ist



; Lesen
	ldi		temp, 0b00001000			; Bit EEMAPEN setzen, damit EEPROM in den Speicher gemappt wird
	sts		NVM_CTRLB, temp				; und in NMV-Controllregister schreiben

	ldi		temp, 0b11111111			; alle Bits in temp auf 1 setzen und
	sts		PORTB_DIR, temp				; alle Pins von Port C auf Ausgang einstellen

	lds		temp, 0x1001				; Adresse 1001 (d.h. 0001 aus EEPROM) lesen 
	sts		PORTB_OUT, temp				; und an Port B ausgeben


loop:
jmp loop








; Test Systemtakt auf 32MHz einstellen
 
.include "ATxmega384D3def.inc"
; zu finden unter: 
; ...\Atmel\Atmel Toolchain\AVR Assembler\Native\2.1.1175\avrassembler\include
.def	temp	= r16					; allgemeines Register R16 bekommt temp als Bezeichnung
.CSEG
.ORG	0x0000							; Programmcode soll an Adresse 0000 beginnen

	ldi		temp, 0b00000010			; Bit 1 setzen (RC32MEN = 1), 2MHz Oszillator bleibt trotz 0 eingeschaltet
										; da er default als aktuelle Taktquelle ausgewählt ist und dann nicht ausgeschaltet werden kann
	sts		OSC_CTRL, temp				; 32MHz Oszillator freigeben

status32MHz:
	lds		temp, OSC_STATUS 			; Oszillator Status lesen
	andi	temp, 0b00000010			; alle Bits außer für 32MHz Oszillator ausblenden
	cpi		temp, 0b00000010			; Prüfen, ob Flag gesetzt ist
	brne	status32MHz					; Schleife, wenn Flag noch nicht gesetzt ist

	ldi		temp, 0xD8					; Signatur um geschützte I/O Register zu ändern
	sts		CPU_CCP, temp				; in CCP Register schreiben

	ldi		temp, 0b00000001			; Bit 0 setzen (SCLKSEL = 001)
	sts		CLK_CTRL, temp				; 32MHz Oszillator als Taktquelle auswählen


	; damit man die 32MHz auch sieht, wird der Takt an Pin7 von Port C ausgegeben
	ldi		temp, 0b11111111			; alle Bits in temp auf 1 setzen
	sts		PORTC_DIR, temp				; alle Pins von Port C auf Ausgang einstellen

	ldi		temp, 0b00000001			; Bitkombination für CLKOUTSEL (CLK1X) und CLKOUT (Port C)
	sts		PORTCFG_CLKEVOUT, temp		; Clock and Event Out Register einstellen damit CLK_Per an Port C/7 ausgegeben wird

loop:

jmp loop








; Test User Signatur auslesen
 
.include "ATxmega384D3def.inc"
; zu finden unter: 
; ...\Atmel\Atmel Toolchain\AVR Assembler\Native\2.1.1175\avrassembler\include
.def	temp	= r16					; allgemeines Register R16 bekommt temp als Bezeichnung
.CSEG
.ORG	0x0000							; Programmcode soll an Adresse 0000 beginnen

 
	ldi		temp, 0b11111111			; alle Bits in temp auf 1 setzen
	sts		PORTA_DIR, temp				; alle Pins von Port A auf Ausgang einstellen
	
	ldi		ZH, 0x01					; Z-Pointer auf Adresse
	ldi		ZL, 0xFF					; des letzten Byte einstellen (0000 bis 01FF = 512 Byte)

	ldi		temp, 0x01					; Kommando für READ_USER_SIG_ROW
	sts		NVM_CMD, temp				; in das NVM_CMD Register schreiben

	lpm		temp, Z						; Byte lesen
		
	sts		PORTA_OUT,temp				; Byte auf PortA ausgeben


	

loop:


jmp loop







; Test Production Signatur auslesen
 
.include "ATxmega384D3def.inc"
; zu finden unter: 
; ...\Atmel\Atmel Toolchain\AVR Assembler\Native\2.1.1175\avrassembler\include
.def	temp	= r16					; allgemeines Register R16 bekommt temp als Bezeichnung
.CSEG
.ORG	0x0000							; Programmcode soll an Adresse 0000 beginnen

 
	ldi		temp, 0b11111111			; alle Bits in temp auf 1 setzen
	sts		PORTA_DIR, temp				; alle Pins von Port A auf Ausgang einstellen
	
	ldi		ZH, 0x00					; Z-Pointer auf Adresse
	ldi		ZL, 0x00					; für RCOSC2M Byte einstellen

	ldi		temp, 0x02					; Kommando für READ_CALIB_ROW
	sts		NVM_CMD, temp				; in das NVM_CMD Register schreiben

	lpm		temp, Z						; Byte lesen
		
	sts		PORTA_OUT,temp				; Byte auf PortA ausgeben









; Test CLK_PER an Pin ausgeben
 
.include "ATxmega384D3def.inc"
; zu finden unter: 
; ...\Atmel\Atmel Toolchain\AVR Assembler\Native\2.1.1175\avrassembler\include
.def	temp	= r16					; allgemeines Register R16 bekommt temp als Bezeichnung
.CSEG
.ORG	0x0000							; Programmcode soll an Adresse 0000 beginnen

 
	ldi		temp, 0b11111111			; alle Bits in temp auf 1 setzen
	sts		PORTC_DIR, temp				; alle Pins von Port C auf Ausgang einstellen

	ldi		temp, 0b00000001			; Bitkombination für CLKOUTSEL (CLK1X) und CLKOUT (Port C)
	sts		PORTCFG_CLKEVOUT, temp		; Clock and Event Out Register einstellen
	

loop:


jmp loop






; Test Port als Eingang mit pull up und pull down
 
.include "ATxmega384D3def.inc"
; zu finden unter: 
; ...\Atmel\Atmel Toolchain\AVR Assembler\Native\2.1.1175\avrassembler\include
.def	temp	= r16					; allgemeines Register R16 bekommt temp als Bezeichnung
.CSEG
.ORG	0x0000							; Programmcode soll an Adresse 0000 beginnen


	ldi		temp, 0b00111111			; Bits 6 und 7 in temp auf 0, andere auf 1 setzen
	sts		PORTE_DIR, temp				; Pins 6 und 7 von Port E als Eingang, andere als Ausgang einstellen

	ldi		temp, 0b00010000			; Bitkombination für pull down (OPC 010)
	sts		PORTE_PIN6CTRL, temp		; Pull Down für Pin 6 einschalten

	ldi		temp, 0b00011000			; Bitkombination für pull up (OPC 011)
	sts		PORTE_PIN7CTRL, temp		; Pull Up für Pin 7 einschalten

loop:
	lds		temp, PORTE_IN				; Pins von Port E einlesen
	andi	temp, 0b11000000			; unteren 6 Pins löschen

	swap	temp						; Nibbles wechseln so dass 6/7 jetzt auf 3/2 sind
	sts		PORTE_OUT, temp				; Zustand von 6/7 auf 3/2 ausgeben

jmp loop





; Test Ports als Ausgang
 
.include "ATxmega384D3def.inc"
; zu finden unter: 
; ...\Atmel\Atmel Toolchain\AVR Assembler\Native\2.1.1175\avrassembler\include
.def	temp	= r16					; allgemeines Register R16 bekommt temp als Bezeichnung
.CSEG
.ORG	0x0000							; Programmcode soll an Adresse 0000 beginnen


	ldi		temp, 0b11111111			; alle Bits in temp auf 1 setzen
	sts		PORTA_DIR, temp				; alle Pins von Port A als Ausgang einstellen

	ldi		temp, 0b10101010			; Bits wechselnd auf 1 und 0 stellen
	sts		PORTA_OUT, temp				; und an Port A ausgeben

	ldi		temp, 0b11111111			; alle Bits in temp auf 1 setzen
	sts		PORTB_DIR, temp				; alle Pins von Port B als Ausgang einstellen

	lds		temp, PORTA_IN				; Pins von Port A einlesen (auch ein Ausgang kann gelesen werden)
	sts		PORTB_OUT, temp				; Pins von Port A auf Port B ausgeben






	

; Test TWI Master write und Master read
 
.include "ATxmega384D3def.inc"
; zu finden unter: 
; ...\Atmel\Atmel Toolchain\AVR Assembler\Native\2.1.1175\avrassembler\include

.def	temp	= r16					; allgemeines Register R16 bekommt temp als Bezeichnung
.def	temp1	= r17					; allgemeines Register R17 bekommt temp1 als Bezeichnung

.CSEG
.ORG	0x0000							; Programmcode soll an Adresse 0000 beginnen


// Port A und B werden hier nur als Ausgang gesetzt, weil auf den daran angeschlossenen LEDs
// der Status des TWI und das ausgelesende Byte angezeigt werden sollen
// für die eigentliche TWI Funktion nicht notwendig, nur zur Sichtkontrolle...
	ldi		temp, 0b11111111			; alle Bits in temp auf 1 setzen und
	sts		PORTB_DIR, temp				; alle Pins von Port B auf Ausgang einstellen
	sts		PORTA_DIR, temp				; alle Pins von Port A auf Ausgang einstellen



// An TWI C ist ein serielles EEPROM (24AA32A) angeschlossen, Adresse 10100000, externe pull up von 2,2k
// Portpins SDA und SCL brauchen offensichtlich nicht extra eingestellt werden (stehen auf default: Eingang)

// Initialisierung
	ldi		temp, 0x0A					; Wert für Baud = 35dez bei 32MHz (400 kHz), 10dez bei 2MHz (100 kHz)
	sts		TWIC_MASTER_BAUD, temp

	ldi		temp, 0b00000001			; Bus Status auf idle setzen (ist nach Reset auf unbekannt)
	sts		TWIC_MASTER_STATUS, temp

	ldi		temp, 0b00001000			; Master freigeben
	sts		TWIC_MASTER_CTRLA, temp		


// Speichern eines Bytes im EEPROM geht so: 
// Erst Controllbyte senden (das ist die klassische 7 Bit Adresse + R/W Bit)
// 2 Byte der Adresse im Speicher senden, dann das eine Byte, das gespeichert werden soll
// Nach dem STOP beginnt der eigentliche Speichervorgang im EEPROM, er dauert eine Weile...

	ldi		temp, 0b10100000			; Controllbyte (7 Bit Adresse + write) des EEPROM ausgeben
	sts		TWIC_MASTER_ADDR , temp		; (START wird automatisch erzeugt)

adresse_wait:
	lds		temp, TWIC_MASTER_STATUS 	; Status lesen 
	sts		PORTB_OUT, temp				; und an Port B ausgeben
	cpi		temp, 0b01100010			; WIF, CLKHOLD und owner
	brne	adresse_wait
	sts		TWIC_MASTER_STATUS, temp	; Flags löschen durch Zurückschreiben

	ldi		temp, 0b00000000			; Data 1 ausgeben (oberes Byte der Speicheradresse im EEPROM)
	sts		TWIC_MASTER_DATA, temp
data1_wait:
	lds		temp, TWIC_MASTER_STATUS 	; Status lesen 
	sts		PORTB_OUT, temp				; und an Port B ausgeben
	cpi		temp, 0b01100010			; WIF, CLKHOLD und owner
	brne	data1_wait
	sts		TWIC_MASTER_STATUS, temp	; Flags löschen durch Zurückschreiben

	ldi		temp, 0b00000000			; Data 2 ausgeben (unteres Byte der Speicheradresse im EEPROM)
	sts		TWIC_MASTER_DATA, temp			
data2_wait:
	lds		temp, TWIC_MASTER_STATUS 	; Status lesen 
	sts		PORTB_OUT, temp				; und an Port B ausgeben
	cpi		temp, 0b01100010			; WIF, CLKHOLD und owner
	brne	data2_wait	
	sts		TWIC_MASTER_STATUS, temp	; Flags löschen durch Zurückschreiben

	ldi		temp, 0b10101010			; Data 3 ausgeben (eigentliches Datenbyte für EEPROM)
	sts		TWIC_MASTER_DATA, temp		
data3_wait:
	lds		temp, TWIC_MASTER_STATUS 	; Status lesen 
	sts		PORTB_OUT, temp				; und an Port B ausgeben
	cpi		temp, 0b01100010			; WIF, CLKHOLD und owner
	brne	data3_wait	

	ldi		temp, 0b00000011			;
	sts		TWIC_MASTER_CTRLC, temp		;STOP Bedingung erzeugen (Bus geht wieder auf idle)


	
	ldi	temp, 0xFF						; warten, bis EEPROM das Byte gespeichert hat
warte:
	dec temp
	brne warte



// Jetzt Auslesen des Bytes aus dem EEPROM. Dazu erst mal die Adresse im EEPROM setzen (Master write Operation)
// Anschließend das Byte lesen (Master read Operation)

adresse_wait2:
	ldi		temp, 0b10100000			; Controllbyte für EEPROM ausgeben, als write-Befehl, da erst die auszulesende 
	sts		TWIC_MASTER_ADDR , temp		; Adresse im EEPROM eingestellt werden muss.
	lds		temp, TWIC_MASTER_STATUS 	; Status lesen 
	sts		PORTB_OUT, temp				; und an Port B ausgeben
	cpi		temp, 0b01100010			; WIF, CLKHOLD und owner
	brne	adresse_wait2				; hier wird die Adresse so lange ausgegeben, bis das EEPROM ACK sendet
										; die Warteschleife oben ist zu kurz, also nicht nur warten bis Statusflag stehen
	sts		TWIC_MASTER_STATUS, temp	; Flags löschen durch Zurückschreiben

	ldi		temp, 0b00000000			; Data 1 ausgeben (oberes Byte der Speicheradresse im EEPROM)
	sts		TWIC_MASTER_DATA, temp
data1_wait2:
	lds		temp, TWIC_MASTER_STATUS	; Status lesen 
	sts		PORTB_OUT, temp				; und an Port B ausgeben
	cpi		temp, 0b01100010			; WIF, CLKHOLD und owner
	brne	data1_wait2
	sts		TWIC_MASTER_STATUS, temp	; Flags löschen durch Zurückschreiben

	ldi		temp, 0b00000000			; Data 2 ausgeben (unteres Byte der Speicheradresse im EEPROM)
	sts		TWIC_MASTER_DATA, temp		
data2_wait2:
	lds		temp, TWIC_MASTER_STATUS 	; Status lesen 
	sts		PORTB_OUT, temp				; und an Port B ausgeben
	cpi		temp, 0b01100010			; WIF, CLKHOLD und owner
	brne	data2_wait2

	ldi		temp, 0b10100001			; Controllbyte für EEPROM ausgeben, diesmal als Read (Neustart!)
	sts		TWIC_MASTER_ADDR , temp	
adresse_wait3:
	lds		temp, TWIC_MASTER_STATUS 	; Status lesen 
	sts		PORTB_OUT, temp				; und an Port B ausgeben
	cpi		temp, 0b10100010			; RIF, CLKHOLD und owner (erscheint, wenn erstes DATA empfangen ist)
	brne	adresse_wait3

	ldi		temp, 0b00000111			; es wird nur ein Byte gelesen, daher jetzt direkt
	sts		TWIC_MASTER_CTRLC, temp		; NACK und STOP ausgeben.

	lds		temp1, TWIC_MASTER_DATA 	; Data lesen 
	sts		PORTA_OUT, temp1			; und an Port A ausgeben 	

loop:
	lds		temp, TWIC_MASTER_STATUS 	; Status lesen (idle)
	sts		PORTB_OUT, temp				; und an Port B ausgeben
	nop
jmp loop

// Nicht sehr elegant aber als reiner Test ausreichend