procedure DDSstereo;
// DDS-Frequenz in DDSH1 und DDSL1 (rechter Kanal)
// und DDSH2 und DDSL2 (linker Kanal)
// Tabellen-Adressen (ROM-Seite) in TabelleHi (MSBs) und TabelleLow (LSBs)

begin
  asm;
   ; DDS, aus Zeitgründen etwas geschachtelt
    lds  _ACCB, SinusGen.Phasenversatz
    ldi  _ACCA, $00
    mov  _ACCEHI, _ACCA ;Phasen-Akkumulator und Pointer 1. Kanal
    mov  _ACCELO, _ACCA ;Phasen-Akkumulator 1
    mov  _ACCFHI, _ACCB ;Phasen-Akkumulator und Pointer 2. Kanal
    mov  _ACCFLO, _ACCA ;Phasen-Akkumulator 2
    mov  _ACCDHI, _ACCA ; 1. Datenbyte
    mov  _ACCDLO, _ACCA ; 1. Datenbyte
    lds  _ACCCHI, SinusGen.TabellenSeite ; Seiten-Nummer (Adresse) der Sinus-MSBs
    mov  _ACCCLO, _ACCA   ;Z-Pointer nullen
    ldi  _ACCA, 01010000b ;SPI Einschaltwert in _ACCGLO vorladen
    mov  _ACCGLO, _ACCA
    mov  _ACCGHI, _ACCA
    ldi  _ACCA, 01000010b;  // CTC, Toggle OC1 on Timer1
    out  TCCR0A, _ACCA;     // CTC, Toggle OC1 on Timer1
  DDSinitLoopStereo:
    sbis TIFR0,1
    rjmp  DDSinitLoopStereo ; auf Timer OCF0A warten
    sbi TIFR0,1          ; ... Timer OCF0A Flag löschen

  SinusGen.DDSstereoLoop:
    sbis TIFR0,1
    rjmp  SinusGen.DDSstereoLoop ; auf Timer OCF0A warten
    sbi TIFR0,1          ; ... Timer OCF0A Flag löschen

    sbi PortB,5          ; I2S-Vorimpuls an
    cbi PortB,5          ; I2S-Vorimpuls aus
    out SPCR, _ACCGLO      ; SPI einschalten

    ; nächstes MSB berechnen
    sbic  PinD,6         ; LRClk Bit high?
    rjmp DDSstereoCh2    ; anderer Kanal

    out SPDR, _ACCDHI    ; vorbereitetes MSB ausgeben
    add  _ACCELO, SinusGen.DDSL1 ; add value to DDS1 accumulator
    adc  _ACCEHI, SinusGen.DDSH1 ; 1
    cpi  _ACCEHI, 192            ; Überlauf nach 192 Stützwerten
    brlo DDSNoSub1
    subi  _ACCEHI, 192
  DDSNoSub1:
    mov  _ACCCLO,_ACCEHI  ; Z=Index für Sinus-Tabelle
    lds  _ACCCHI, SinusGen.TabellenSeite ; Seiten-Nummer (Adresse) der Sinus-MSBs
    ; Z zeigt nun auf High-Byte der Sinustabelle Kanal 1
    LPM  _ACCDHI, Z       ; MSB in Data-Reg HI

  SPIstereoWaitHi1:
    in _ACCA, SPSR
    sbrs _ACCA,7 ; SPIF?
    rjmp SPIstereoWaitHi1 ; auf Ende des SPI-Transfer warten
    nop

    out SPDR, _ACCDLO     ; letztes LSB16 ausgeben
    ; nächstes LSB berechnen
    inc  _ACCCHI  ; oberes Byte Z-Register auf Low-Tabelle
    LPM  _ACCDLO, Z       ; ... neues LSB16 in Data-Reg LO

  SPIstereoWaitLow1:
    in _ACCA, SPSR
    sbrs _ACCA,7 ; SPIF?
    rjmp SPIstereoWaitLow1;  ; auf Ende des SPI-Transfer warten
    nop
    out SPDR, _ACCGHI     ; letztes LSB24 ausgeben
    ; nächstes LSB berechnen
    inc  _ACCCHI  ; oberes Byte Z-Register auf Low-Tabelle
    LPM  _ACCGHI, Z       ; ... neues LSB24 in Data-Reg LO
  SPIstereoWait24_1:
    in _ACCA, SPSR
    sbrs _ACCA,7 ; SPIF?
    rjmp SPIstereoWait24_1;  ; auf Ende des SPI-Transfer warten

    ldi _ACCA, 0
    out SPCR, _ACCA ; SPI ausschalten
    LDS _ACCA, UCSRA
    sbrs _ACCA,7
    rjmp  SinusGen.DDSstereoLoop; auf Receive warten
    ret

  DDSstereoCh2:
    out SPDR, _ACCDHI    ; vorbereitetes MSB ausgeben
    add  _ACCFLO, SinusGen.DDSL2 ; add value to DDS2 accumulator
    adc  _ACCFHI, SinusGen.DDSH2 ; 1
    cpi  _ACCFHI, 192            ; Überlauf nach 192 Stützwerten
    brlo DDSNoSub2
    subi  _ACCFHI, 192
  DDSNoSub2:
    mov  _ACCCLO,_ACCFHI  ; Z=Index für Sinus-Tabelle
    lds  _ACCCHI, SinusGen.TabellenSeite ; Seiten-Nummer (Adresse) der Sinus-MSBs
    ; Z zeigt nun auf High-Byte der Sinustabelle Kanal 1
    LPM  _ACCDHI, Z       ; MSB in Data-Reg HI

  SPIstereoWaitHi2:
    in _ACCA, SPSR
    sbrs _ACCA,7 ; SPIF?
    rjmp SPIstereoWaitHi2;  ; auf Ende des SPI-Transfer warten
    nop
    out SPDR, _ACCDLO     ; letztes LSB16 ausgeben
    ; nächstes LSB berechnen
    inc _ACCCHI           ; oberes Byte Z-Register auf Low-Tabelle
    LPM  _ACCDLO, Z       ; neues LSB16 in Data-Reg LO
    mov _ACCCHI, _ACCBHI  ; oberes Byte Z-Register auf High-Tabelle

  SPIstereoWaitLow2:
    in _ACCA, SPSR
    sbrs _ACCA,7 ; SPIF?
    rjmp SPIstereoWaitLow2;  ; auf Ende des SPI-Transfer warten
    nop

    cbi PortD,7          ; PCM56-Latch ein
    out SPDR, _ACCGHI    ; letztes LSB24 ausgeben
    ; nächstes LSB berechnen
    inc  _ACCCHI  ; oberes Byte Z-Register auf Low24-Tabelle
    LPM  _ACCGHI, Z       ; neues LSB24 in Data-Reg LO
    sbi PortD,7           ; PCM56-Latch aus

  SPIstereoWait24_2:
    in _ACCA, SPSR
    sbrs _ACCA,7 ; SPIF?
    rjmp SPIstereoWait24_2;  ; auf Ende des SPI-Transfer warten

    ldi _ACCA, 0
    out SPCR, _ACCA ; SPI ausschalten
    
    
    
    LDS _ACCA, UCSRA
    sbrs _ACCA,7
    rjmp  SinusGen.DDSstereoLoop; auf Receive warten
    
    
  endasm;
end;

