;
;.include "Header.inc"       ;Label und Werte Zuweisungen
;
;HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
; Headerdatei
;HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
;Der ATmega88PA laeuft mit einem 1,8432 MHz Quarz und wird an 3,3V betrieben.
;
;FUSES Extendet $F9, High $97, Low $EA
;debugWIRE Enable, EEPROM beim Loeschen nicht mitloeschen, 
;Sytemtakt nicht durch 8 teilen, Low-Power Quarz-Oszillator.
;
;Es wird ein schwarzer Wii Nunchuk ausgelesen und seine Werte ueber die USART
;( RS232 spaeter mittels MAX3232 jetzt MAX232 ) an ein Terminalprogramm ge-
;sendet ( Hterm ). Bei meinem TTL <-> RS232-Wandler ist es noetig dort 
;DTR & RTS einzuschalten, da ueber eine "Trickschaltung" der MAX232 hierrueber
;mit Spannung versorgt wird, welche vorher zu messen ist, bevor der MAX daran
;angeschlossen wird.
;
;FUSES $ D1 DD (ATmega8L)
;EEPROM beim Chiploeschen nicht mitloeschen.
;Externer Quarz / Keramik Ressonator
;Quarz & BOD enabled
;Start-up Timer from Powerdown & Powersave 16K CK
;
;CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
; Einbinden der Controllerspezifischen Definitionsdatei
;CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
;
.NOLIST                 ;List-Output ausschalten
.INCLUDE "m88PAdef.inc" ;AVR-Definitionsdatei einbinden
.LIST                   ;List-Output wieder einschalten
;
;RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
;RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
; Arbeitsregister umbenennen
;RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
;RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
;
;.DEF   = r0    ;
;.DEF   = r1    ;
;.DEF   = r2    ;
;.DEF   = r3    ;
;.DEF   = r4    ;
;.DEF   = r5    ;
;.DEF    = r6        ;
.DEF twi_data          = r7     ;TWI-Datenbyte 
.DEF null              = r8     ;Register mit dem Inhalt Null
.DEF twi_txd           = r9     ;TWI-Datensendezeiger
;.DEF twi_rxd           = r10    ;TWI-Datenempfangszeiger
.DEF ovf0_zaehler      = r11    ;Timer0 Overflow-Zaehler
;.DEF           = r12    ;
.DEF twi_status_check  = r13    ;Vergleichsregister f. den Status-Check
.DEF zaehler           = r14    ;Allgemeiner Zaehler fuer verschiedene Sachen 
.DEF s_sreg            = r15    ;Zum Sichern des Statusregisters ( Nur 1 Takt )

.DEF a                 = r16    ;Arbeitsregister Low- Byte
.DEF b                 = r17    ;Arbeitsregister High-Byte
;.DEF   = r18   ;
.DEF twi_rxd           = r18    ;TWI-Datenempfangszeiger       
.DEF flag_reg          = r19    ;Allgemeines Flaggenregister;
.DEF twi_ablauf_nr     = r20    ;Zeiger auf die jeweilige TWI-Aktion
.DEF key_reg           = r21    ;Fuer die Tasterentprellung
.DEF ia                = r22    ;Interrupt Arbeitsregister a ( Nur in ISR genutzt )
.DEF ib                = r23    ;Interrupt Arbeitsregister b ( Nur in ISR genutzt )
.DEF wl                = r24    ;Register 24 und 25 dienen als universelles
.DEF wh                = r25    ;Doppelregister W wie Work
;.DEF xl               = r26    ;Der X-Zeiger ist die TWI-Statusnummertabellen-.. 
;.DEF xh               = r27    ;..adresse ( twi_status_nr_tab: )
;.DEF yl= r28   ;
;.DEF yh= r29   ;
;.DEF zl             = r30   ;Verwendung als Z-Zeiger, also wie bereits in der..
;.DEF zh             = r31   ;..Definitionsdatei von ATMEL angegeben
;
;KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK
;KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK
; Konstanten als Symbole
;KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK
;KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK
;
.EQU #ovf0_zaehler	    = 4		;Wert f. Timer0 Overflowzaehler

.EQU #ubrr			    = 2		;Wert f. USART Baudrate 38400 Baud

;
;TWI Konstanten
; 
.EQU #twi_sla_w         = $A4   ;Adresse des SLAVE ( Write )
.EQU #twi_sla_r         = $A5   ;Adresse des SLAVE ( Read  )

.EQU #twbr			    =  1	;TWI SCL-Frequenz(ca.102 kHz TWBR=1,2 ca.92kHz)
.EQU #twi_status_anz    = 25    ;Anzahl der Eintraege in der TWI-Statustabelle
.EQU #twi_ablauf_nr_anz = 18    ;Anzahl der einzelnen TWI-Aktionen
.EQU #twi_rxd_anz       =  6-2    ;Anzahl der einzulesenden Wii Nunchuk Daten
.EQU #twi_txd_anz       =  5    ;Anzahl der sendenden Wii Nunchuk Daten

.EQU #twi_txd_end       =  17;9;8    ;Senden der Daten beenden
.EQU #twi_data_end      = 17    ;TWI-Ablaufnummer ab der Daten lesen endet.

.EQU #cmd_twi_start		= 1<<TWINT|1<<TWSTA|1<<TWEN|1<<TWIE ;TWI-START  Komando
.EQU #cmd_twi_stop      = 1<<TWINT|1<<TWSTO|1<<TWEN|1<<TWIE ;TWI-STOP   Komando
.EQU #cmd_twi_ack       = 1<<TWINT|1<<TWEA |1<<TWEN|1<<TWIE ;TWI-ACKNOWLEDGE 
.EQU #cmd_twi_action    = 1<<TWINT         |1<<TWEN|1<<TWIE ;TWI-Aktion 
;
;
;
;Bitbezeichner fuer das allgemeine Flaggenregister flag_reg
;
;.equ			= 0	;
;.equ			= 1	;
;.equ			= 2	;
;.equ  	= ;
.equ	pla.flg		= 4	;Programmlaufanzeige-Flagge
.equ	twi.err 	= 5	;TWI-ERROR-Flagge
;.equ		= 6	;
;.equ		= 7	; 
;
;Bitbezeichner fuer das Tasterentprellregister key_reg
;
;.equ			= 0	;
;.equ			= 1	;
.equ  key.unactuated	= 2	;Taster entprellt unbetaetigt
.equ  key.actuated		= 3	;Taster entprellt betaetigt
;.equ			= 4	;
;.equ	= 5	;
;.equ	= 6	; 
;.equ		= 7	; 
;
;.include "Hardware.inc"     ;Hardware Label  Zuweisungen
;
;*******************************************************************************
;* Hardware Zuweisungen
;*******************************************************************************
;
.EQU XTAL		  = 1843200  ;Quarzfrequenz in Hertz

.EQU PLA_PIN      = PINB     ;Eingabeport an dem die LED angeschlossen ist
.EQU PLA_DDR      = DDRB     ;Datenrichtungsregister fuer die LED
.EQU PLA_PORT     = PORTB    ;Ausgabeport fuer die Programmlaufanzeige-LED
.EQU led.pla      = PB4		 ;Pin an dem die PLA-LED angeschlossen ist
.EQU led.err      = PB5      ;Pin an dem die Error-LED angeschlossen ist

.EQU KEY_PIN	  = PIND     ;Eingabeport an dem der Taster angeschlossen ist
.EQU KEY_DDR	  = DDRD     ;Datenrichtungsregister fuer den Taster
.EQU KEY_PORT	  = PORTD    ;Port fuer die Pull-up Widerstand-Aktivierung
.EQU key.bit	  = PD5      ;Pin an dem der Taster angeschlossen ist

.EQU LED_PIN      = PIND     ;Eingabeport an dem die LED angeschlossen ist
.EQU LED_DDR      = DDRD     ;Datenrichtungsregister fuer die LED
.EQU LED_PORT     = PORTD    ;Ausgabeport fuer die LED
.EQU led.ok       = PD4      ;Pin an dem die OK-LED angeschlossen ist
;
;Programmstart nach RESET  ( Interrupt Vektoren Tabelle )
;
.CSEG                       ;Was ab hier folgt kommt in den FLASH-Speicher
.ORG $0000                  ;Programm beginnt an der FLASH-Adresse 0x0000..

 rjmp  _reset               ;..mit der RESET-Vectortabelle
;
;.include "IRQm88PA.inc"     ;Restliche Interrupt Vektortabelle
;
;VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
; Interruptvektortabelle des ATmega88PA Mikrocontrollers
;VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
;
reti    ;rjmp   _INT0addr	; External Interrupt Request 0
reti    ;rjmp   _INT1addr	; External Interrupt Request 1
reti    ;rjmp   _PCI0addr	; Pin Change Interrupt Request 0
reti    ;rjmp   _PCI1addr	; Pin Change Interrupt Request 0
reti    ;rjmp   _PCI2addr	; Pin Change Interrupt Request 1
reti    ;rjmp   _WDTaddr	; Watchdog Time-out Interrupt
reti    ;rjmp   _OC2Aaddr	; Timer/Counter2 Compare Match A
reti    ;rjmp   _OC2Baddr	; Timer/Counter2 Compare Match A
reti    ;rjmp   _OVF2addr	; Timer/Counter2 Overflow
reti    ;rjmp   _ICP1addr	; Timer/Counter1 Capture Event
reti    ;rjmp   _OC1Aaddr	; Timer/Counter1 Compare Match A
reti    ;rjmp   _OC1Baddr	; Timer/Counter1 Compare Match B
reti    ;rjmp   _OVF1addr	; Timer/Counter1 Overflow
reti    ;rjmp   _OC0Aaddr	; TimerCounter0 Compare Match A
reti    ;rjmp   _OC0Baddr	; TimerCounter0 Compare Match B
rjmp   _OVF0addr	; Timer/Counter0 Overflow
reti    ;rjmp   _SPIaddr	; SPI Serial Transfer Complete
reti    ;rjmp   _URXCaddr	; USART Rx Complete
reti    ;rjmp   _UDREaddr	; USART, Data Register Empty
reti    ;rjmp   _UTXCaddr	; USART Tx Complete
reti    ;rjmp   _ADCCaddr	; ADC Conversion Complete
reti    ;rjmp   _ERDYaddr	; EEPROM Ready
reti    ;rjmp   _ACIaddr	; Analog Comparator
rjmp   _TWIaddr	; Two-wire Serial Interface
reti    ;rjmp   _SPMRaddr	; Store Program Memory Read    

.ORG INT_VECTORS_SIZE       ;Programmadresse nach den ganzen IRQ-Vektoren
;
;KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK
;KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK
;K Konstanten im Flash TWI_Status bzw. Rueckmeldungen
;KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK
;KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK
;
;Hier ist der Ablauf der zu erwartenden TWSR-Rueckmeldungen eingetragen.
;Der jeweilige TWI-Status in TWSR entspricht 3x nach rechts geshiftet, der je-
;weiligem TWI-Sequenz. Auf die erste Sequenz ( START-BEDINGUNG ), erfolgt 
;richtigerweise die Rueckmeldung 08 >>3 = 1 im TWSR. Hierrauf folgt das Senden
;von SLA_W, was mit 18 >>3 = 3 richtigerweise im TWSR Rueckgemeldet wird usw.
;
_twi_status_check:
.DB 1,3,5,5,0,1,3,5,0,1,8,10,10,10,10,10,11,0 ;
;.DB $60,$68,$70,$78,$80,$88,$90,$90,$98,$A0,$A8,$B0,$B8,$C0,$C8,00 
;
;TWI zu sendende Datenbytes zur Initialisierung des Wii Nunchuk.
;
_twi_data_w:
.DB $00,$00,$FB,$55,$F0,00 
;
;IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
;IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
;I Erstinitialisierungen
;IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
;IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
;
;Stapelzeiger initialisieren (fuer Unterprogramme und / oder Interrupts)
;
_reset:
 ldi  a,High(RAMEND)        ;RAMEND, also das Ende vom SRAM, ist in der.. 
 out  SPH,a                 ;..Definitions-datei festgelegt  
 ldi  a,Low (RAMEND)
 out  SPL,a
;
;Variablen initialisieren ( r0-r31 haben unbestimmten Inhalt )
;
 clr  flag_reg              ;Allgemeines Flaggenregister
 clr  ovf0_zaehler          ;Timer0 Overflowzaehler
 clr  key_reg               ;Tasterentprellregister
 clr  null                  ;Register mit dem Inhalt Null
 clr  twi_ablauf_nr         ;Zeiger auf die jeweilige TWI-Aktion ( START )

 ldi  a,#twi_txd_anz        ;Datensendezeiger..
 mov  twi_txd,a             ;..initialisieren
 ldi  a,#twi_rxd_anz        ;Datenempfangszeiger..
 mov  twi_rxd,a             ;..initialisieren
;
;Ports Erstkonfiguration
; 
 sbi  PLA_PORT,led.pla      ;PraogrammLaufAnzeige-LED aus ( Vorerst Pullup )
 sbi  PLA_DDR, led.pla      ;PORT-Bit als Ausgang f. PLA-LED
 
 sbi  PLA_PORT,led.err      ;Error-LED ausschalten ( Vorerst Pullup )
 sbi  PLA_DDR, led.err      ;PORT-Bit als Ausgang f. Error-LED
  
 sbi  LED_PORT,led.ok       ;OK-LED ausschalten ( Vorerst Pullup )
 sbi  LED_DDR, led.ok       ;PORT-Bit als Ausgang f. OK-LED

 sbi  KEY_PORT,key.bit      ;Pullup f. Taster einschalten
;
; USART Baudrate einstellen
;
 ldi  a,#ubrr               ;f. UBRRH bei 38400 Baud mit 1,8432Hz Quarz
 clr  b                     ;f. UBBRL bei 38400 Baud mit 1,8432Hz Quarz
 sts  UBRR0H,b              ;Baudrate 38400 mit einem...
 sts  UBRR0L,a              ;...1,8432Hz Quarz
;
;USART Sendeschieberegisterinterrupt und Sender ( Transmitter ) freigeben
;
 ldi  a,1<<TXCIE0|1<<TXEN0  ;USART Sendeschieberegisterinterrupt freigeben...
 sts  UCSR0B,a              ;...und USART-Sendeeinheit einschalten
;
;USART Format ( 8,N,1 ) ist bereits nach dem Reset voreingestellt
;
;
;Timer0 Overflow Interrupt initialisieren
;
 ldi  a,1<<TOIE0            ;Timer0 Overflow Interrupt freigeben...
 sts  TIMSK0,a              ;...
 ldi  a,1<<CS02             ;Timer0 Vorteiler => 256...
 out  TCCR0B,a              ;...
;
;TWI SCL Frequenz einstellen ( ca. 102 kHz TWBR=1, mit TWBR=2 ca. 92kHz )
;
 ldi  a,#twbr               ;Ergibt zusammen mit den Vorteilerbits...
 sts  TWBR,a                ;...TWPS=0 im TWSR ca. 102 kHz

 sei                        ;Globale Interruptfreigabe im CPU-Statusregister
;
;HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
;HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
;H Hauptprogrammschleife
;HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
;HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
;
;Bei Tasterbetaetigung oder TWCR.TWINT=1   => TWI-Sequenzen durchlaufen lassen
;
_main:
 sbrc  flag_reg,twi.err     ;TWI-Ablauf in Ordnung?..
 rjmp _twi_fail             ;..NEIN => Fehlerbehandlung
 lds  a,TWCR                ;TWI Controllregister laden
 sbrs key_reg,key.actuated  ;..oder der Taster betaetigt und entprellt?..
 sbrc a,TWINT               ;..TWI-IRQ angefordert?..
 rjmp _twi                  ;..JA => TWI-Sequenzen erzeugen
 rjmp _idle                 ;TWI Abhandlung ueberspringen
;
;Dem TWI-Ablauf entsprechend zur TWI-Aktion springen.
;
_twi: 
 cbr  key_reg,1<<key.actuated;Taster wieder aktivieren

 cpi  twi_ablauf_nr,#twi_ablauf_nr_anz +1;Anzahl der TWI-Aktionen zu hoch?
 brcc _twi_ablauf_nr_fail   ;..JA => Error-LED einschalten 
;
;Vorbereitung fuer den Statuscheck in der TWI-ISR 
;
 ldi  zl, LOW(_twi_status_check*2);Zur TWI-Aktion..
 ldi  zh,HIGH(_twi_status_check*2);..den zugehoerigen..
 add  zl,twi_ablauf_nr      ;..Status-Check holen und f. den Vergleich..
 adc  zh,null               ;..in der TWI-ISR ( _TWIaddr: )..
 lpm  twi_status_check,z    ;..abspeichern
;
;TWI-Ablauf. Anhand der TWI-Ablaufnummer zur jeweiligen TWI-Aktion bzw. 
;Schritt springen.
;
 ldi  zl, LOW(_twi_ablauf)  ;Den TWI-Ablaufschritt..
 ldi  zh,HIGH(_twi_ablauf)  ;..holen und..
 add  zl,twi_ablauf_nr      ;..zur entsprechenden..
 adc  zh,null               ;..TWI-Aktion..
 ijmp                       ;..springen.
;
;Wii Nunchuk initalisieren ( Initialize start Nunchuk command )
;
_twi_ablauf:
 rjmp _twi_start            ;Schritt  0 => TWI-STARTBEDINGUNG erzeugen
 rjmp _twi_sla_w            ;Schritt  1 => $A4
 rjmp _twi_data_write       ;Schritt  2 => $F0
 rjmp _twi_data_write       ;Schritt  3 => $55
 rjmp _twi_stop             ;Schritt  4 => TWI-STOPPBEDINGUNG erzeugen
 rjmp _twi_start            ;Schritt  5 => TWI-STARTBEDINGUNG erzeugen
 rjmp _twi_sla_w            ;Schritt  6 => $A4
 rjmp _twi_data_write       ;Schritt  7 => $FB
 rjmp _twi_data_write       ;Schritt  8 => $00
 rjmp _twi_stop             ;Schritt  9 => TWI-STOPPBEDINGUNG erzeugen 
;
;Wii Nunchuk Vorbereiten fuer den Datenaustausch ( Conversion command (0x00) )
;
 rjmp _twi_start            ;Schritt 10 => TWI-STARTBEDINGUNG erzeugen
 rjmp _twi_sla_w            ;Schritt 11 => $A4
 rjmp _twi_data_write       ;Schritt 12 => $00
 rjmp _twi_stop             ;Schritt 13 => TWI-STOPPBEDINGUNG erzeugen 
;
;Wii Nunchuk Daten auslesen
;
 rjmp _twi_start            ;Schritt 14 => TWI-Repeated STARTBEDINGUNG erzeugen
 rjmp _twi_sla_r            ;Schritt 15 => $A5
 rjmp _twi_data_ack         ;Schritt 16 => Acknowlegde-Puls erzeugen
 rjmp _twi_data_read        ;Schritt 17 => TWI-DATA lesen
 rjmp _twi_stop             ;Schritt 18 => TWI-STOPPBEDINGUNG erzeugen 
 
 rjmp _twi_read_loop        ;Schritt 19 => Schritte 14 bis 17 wiederholen
;
;Die TWI-Ablaufnummer ist groesser als die Anzahl der Spruenge bei
;TWI-Ablauf (_twi_ablauf:). 
;
_twi_ablauf_nr_fail:
 cbi  PLA_PORT,led.err      ;Testweise Error-LED einschalten#################################################

 rjmp _idle                 ;TWI-Abhandlung ueberspringen
;
;In der TWI-ISR wurde in einer der beiden ERROR-Faelle im Flag-Register
;( flag_reg ) das TWI-ERROR-Flag (twi.err) gesetzt.
;
_twi_fail:
 cbi  PLA_PORT,led.err      ;Testweise Error-LED einschalten#################################################

 rjmp _idle                 ;TWI-Abhandlung ueberspringen
;
;TWI-START-Aktion ausfuehren 
;
_twi_start:
 ldi  a,#cmd_twi_start      ;START-BEDINGUNG.. 
 sts  TWCR,a	            ;..ausfuehren
  
 rjmp _twi_takten           ;Den TWI-Ablauf weitertakten
;
;TWI-ADDRESS-WRITE-Aktion ausfuehren 
;
_twi_sla_w:
 ldi  a,#twi_sla_w          ;Slave-Write-Adresse laden..
 sts  TWDR,a                ;..und ins TWI-Data-Register schreiben 
   
 ldi  a,#cmd_twi_action     ;TWI-Aktion..
 sts  TWCR,a	            ;..ausfuehren 
 
 rjmp _twi_takten           ;Den TWI-Ablauf weitertakten
;
;TWI-ADDRESS-READ-Aktion ausfuehren 
;
_twi_sla_r:
 ldi  a,#twi_sla_r          ;Slave-Read-Adresse laden..
 sts  TWDR,a	            ;..und ins TWI-Data-Register schreiben 
 
 ldi  a,#cmd_twi_action     ;TWI-Aktion..
 sts  TWCR,a	            ;..ausfuehren 
 
 rjmp _twi_takten           ;Den TWI-Ablauf weitertakten
;
;TWI-DATA-Write ausfuehren
;
_twi_data_write:
 dec  twi_txd               ;Datensendezeiger einen weniger

 clr  zh                    ;Basisadresse der zu senden Bytes..
 ldi  zl, LOW(_twi_data_w*2);..laden und den..
 add  zl,twi_txd            ;..Datensendezeiger hinzuaddieren und aus dieser..
 lpm  twi_data,z            ;..nun gebildeten Addresse das zu sendende Byte..
 sts  TWDR,twi_data         ;..laden und ins TWI-Datenregister kopieren

 ldi  a,#cmd_twi_action     ;TWI-Aktion.. 
 sts  TWCR,a	            ;..ausfuehren 

 rjmp _twi_takten           ;Den TWI-Ablauf weitertakten
;
;TWI-Daten lesen
; 
_twi_data_ack: 
 ldi  a,#cmd_twi_ack        ;Acknowlegde-Puls..
 sts  TWCR,a                ;..generieren

 rjmp _twi_takten           ;Den TWI-Ablauf weitertakten
;
;TWI Daten lesen und im SRAM speichern
; 
_twi_data_read:
 ldi  zh,HIGH(_twi_data_r)  ;..SRAM-Basisadresse.. 
 ldi  zl,LOW (_twi_data_r)  ;..laden..
 add  zl,twi_rxd            ;..und Datenempfangszeiger..
 adc  zh,null               ;..hinzuaddieren

 lds  twi_data,TWDR         ;TWI-Datenbyte einlesen..
 st   z,twi_data            ;..und ins SRAM kopieren

 rcall _warte_udre          ;TESTZWECKE ####################################################################
 ld   twi_data,z            ;TESTZWECKE ####################################################################
 sts  UDR0,twi_data         ;TESTZWECKE ####################################################################

 tst  twi_rxd               ;Daten empfangen fertig?
 breq _twi_nack             ;JA => springen

 dec  twi_rxd               ;Datenempfangszeiger einen weniger
 
 dec  twi_ablauf_nr         ;Acknowlegde-Puls erzeugen
 
 rjmp _idle                 ;Weiter im Programmlauf
_twi_nack: 
 ldi   twi_rxd,#twi_rxd_anz ;Datenempfangszeiger erneut initialisieren

 ldi  a,#cmd_twi_action     ;TWI-Aktion ausfuehren und somit ein..
 sts  TWCR,a	            ;..NOT Acknowlede erzeugen 

 rjmp _twi_takten           ;Den TWI-Ablauf weitertakten
;
;TWI-STOP-Aktion ausfuehren.
;  
_twi_stop:
 sbr  key_reg,1<<key.actuated;Taster als gedrueckt & entprellt simulieren

 ldi  a,#cmd_twi_stop       ;STOP-BEDINGUNG..
 sts  TWCR,a                ;..ausfuehren

 rjmp _twi_takten           ;Den TWI-Ablauf weitertakten
;
;TWI-Empfangsdaten lesen als Dauerschleife
;
_twi_read_loop:
 ldi  twi_ablauf_nr,9       ;TWI-Sequenz Daten lesen ( wird in der naechsten..
                             ;..Zeile inkrementiert )
 sbr  key_reg,1<<key.actuated;Taster als gedrueckt & entprellt simulieren

;
;TWI-Ablauf weitertakten
;
_twi_takten:
 inc  twi_ablauf_nr         ;TWI-Ablauf einen Schritt weiterschalten 
;
;ProgrammAblaufAnzeige (PLA) in Gang halten
;
_idle: 
 sbr  flag_reg,1<<pla.flg   ;Programmlaufanzeige-Flag quitieren
 
 rjmp _main                 ;Sprung zum Anfang des Hauptprogramms ( Mainloop )
; 
;UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU
;UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU
;U Beginn der verwendeten Unterprogramme
;UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU
;UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU
;
;.include "UP.inc";Unterprogramme
;
;Auf das Freiwerden des USART-Datenregisters warten
;
_warte_udre:                 ;TESTZWECKE #####################################################################
 push a
_warte_udre1:
 lds  a,UCSR0A
 sbrs a,UDRE0              
 rjmp _warte_udre1 
 pop  a          
 ret                        ;TESTZWECKE ############################################################################
;
;.include "ISR_2.inc";Interrupt Service Routinen
;
; 
;QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
;QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
;Q Beginn der verwendeten Interrupt Service Routinen ( ISR )
;QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
;QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
;
;
;QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
;Q USART Transmit Complete Interrupt
;QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
;
; Mit RETI in der Vektorsprungtabelle ist es auch getan
;
;
_UTXCaddr:
; in   s_sreg,SREG           ;Statusregister sichern 

; out  SREG,s_sreg            ;Statusregister wiederherstellen
; reti                       ;Ruecksprung aus der Interrupt Service Routine     
;
;QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
;Q Timer0 Overflow ISR ( Interrupt Service Routine )
;QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
;
_OVF0addr:
 in   s_sreg,SREG           ;CPU-Statusregister sichern 
;
;Tasterentprellung. Das Bit key.actuated ( Taster betaetigt & entprellt )
;wird nach dem Auswerten in der Hauptprogrammschleife rueckgesetzt.
;
 bst  key_reg,key.unactuated;Taster betaetigt & entprellt im T-Flag speichern 
 sbis KEY_PIN,key.bit       ;Taster unbetaetigt?
 rjmp _actuated             ;Nein => Taster betaetigt
 brts _counterrestore       ;Zaehler auf 4 ruecksetzen
 rjmp _count                ;Bis 3 Zaehlen
_actuated:
 brts _count                ;Weiter von 5 bis 8 zaehlen
_counterrestore:
 cbr  key_reg,$03           ;Zaehlerbits 1&0 ruecksetzen
_count:
 sbrs key_reg,key.actuated  ;Taster betaetigt entprellt?
 inc  key_reg   
;
;ProgrammLaufAnzeige-LED ( PLA-LED ) blinken lassen 
;
 sbrs flag_reg,pla.flg      ;PLA-Flag in der Mainschleife quitiert?...
 rjmp _exit_OVF0addr        ;...Nein => ISR verlassen

 inc  ovf0_zaehler          ;Overflowzaehler inkrementieren...
 sbrs ovf0_zaehler,#ovf0_zaehler;...bis 16 gezaehlt...
 rjmp _exit_OVF0addr        ;...Nein => ISR verlassen
 clr  ovf0_zaehler          ;Overflowzaehler ruecksetzen

 sbi  PLA_PIN, led.pla      ;Programmlaufanzeige LED toggeln
;
;Timer0 Overflow ISR verlassen
; 
_exit_OVF0addr:             ;Timer0 Overflow Interrupt verlassen
 cbr flag_reg,1<<pla.flg    ;Programmlaufanzeige-Flag quitieren

 out  SREG,s_sreg           ;Statusregister wiederherstellen

 reti                       ;Ruecksprung aus der Interrupt Service Routine
;
;QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
;Two-wire Serial Interface ISR ( TWI Interrupt Service Routine )
;QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
;
_TWIaddr:
 in   s_sreg,SREG           ;CPU-Statusregister sichern 
 push zh                    ;Z-Zeiger..
 push zl                    ;..sichern
;
;TWI-Schritt ueberpruefen
;
/* lds  ia,TWSR               ;TWI-Statusregister laden,..
 andi ia,$FC                ;..nichtrelevante Bits ausmaskieren..
 lsr  ia                    ;..und in eine.. 
 lsr  ia                    ;..TWI-Statusnummer..
 lsr  ia                    ;..konvertieren..
 cpi  ia,#twi_status_anz    ;..pruefen ob im Zulaessigen Bereich..
 brcc _twi_error_anz        ;..NEIN => Fehlerbehandlung noetig
 cpse ia,twi_status_check   ;..passt TWI-Status zur jeweiligen TWI-Aktion?
 rjmp _twi_error_seq        ;NEIN => Fehlerbehandlung noetig

 cpi  twi_ablauf_nr, 9
 brne _twi_irq_sperren      ;TWI-IRQ sperren und ISR verlassen
 cbi  LED_PORT,led.ok     ;Testweise Error-LED einschalten#################################################
 lds  ia,TWCR             ;TESTWEISE TWI-Ablauf stoppen   #################################################
 cbr  ia,TWINT
 sts  TWCR,ia             ;################################################################################
*/
rjmp _twi_irq_sperren      ;TWI-IRQ sperren und ISR verlassen
;
;Der TWI-Status passt nicht zur TWI-Aktion.
;
_twi_error_seq:
 sbr  flag_reg,1<<twi.err   ;TWI-ERROR-Flag  f. das Hauptprogramm setzen
 
 rcall _warte_udre          ;TESTZWECKE ############################################################################ 
 ldi  ia,'S'                ;Testweise ######################################################################
 sts  UDR0,ia               ;Testweise ######################################################################

 rcall _warte_udre          ;TESTZWECKE ############################################################################ 
 lds  ia,TWSR
 sts  UDR0,ia               ;TESTZWECKE ############################################################################ 

 rjmp _twi_irq_sperren      ;TWI-IRQ sperren und ISR verlassen
;
;Die Anzahl der maximalen TWI-Status wurde ueberschritten
;
_twi_error_anz:
 sbr  flag_reg,1<<twi.err   ;TWI-ERROR-Flag  f. das Hauptprogramm setzen

 rcall _warte_udre          ;TESTZWECKE ############################################################################ 
 ldi  ia,'A'                ;Testweise ######################################################################
 sts  UDR0,ia                ;Testweise ######################################################################
 
 rcall _warte_udre          ;TESTZWECKE ############################################################################ 
 lds  ia,TWSR               ;TESTWEISE ######################################################################
 sts  UDR0,ia               ;TESTWEISE ######################################################################
;
;Ruecksprung aus der TWI-ISR mit TWI-Interrupt sperren ( TWCR.TWIE=0 ) und 
;dem Wiederherstellen von Registern
;
_twi_irq_sperren:
 lds   ia,TWCR              ;..TWI Kontrollregister laden und..
 andi ia,$7E                ;..nur TWCR.TWIE loeschen, also die TWI-Interrupt..
 sts TWCR,ia                ;..sperren, aber TWINT bleibt f. die Main gesetzt !

 pop  zl                    ;Z-Zeiger..
 pop  zh                    ;..wiederherstellen
 out  SREG,s_sreg           ;CPU-Statusregister wiederherstellen

 reti                       ;Ruecksprung aus der Interrupt Service Routine 
;    
;DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
;DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
;D Daten im SRAM ablegen
;DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
;DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
;
.DSEG

_twi_data_r:
.BYTE #twi_rxd_anz          ;Eingelesenen Wii Nunchuk Bytes ab hier ablegen
 
.EXIT                       ;Ende des Quelltextes