{###########################################################################}
{$IFDEF miniDDS}
procedure miniDDS;
begin
  disableints;
  m:= byte(wave);
  asm;
    mov  _ACCA, SoftDDS.m
    ldi  _ACCDLO, $FF; kein Taster gedrückt-Vergleich
    mov  SoftDDS.m, _ACCDLO
   ; set sinewave output as default
    ldi  _ACCCHI, SoftDDS.sinus SHRB 8; setup Z pointer hi
    ldi  _ACCCLO, SoftDDS.sinus AND $FF; setup Z pointer lo
    ldi  _ACCDHI, $00; clear accumulator
    ldi  _ACCDLO, $00
    mov  _ACCFLO, SoftDDS.DDSL; setup adder registers
    mov  _ACCFHI, SoftDDS.DDSM
    mov  _ACCBLO, SoftDDS.DDSH;
    tst  _ACCA
    breq  SoftDDS.SinLoop
    dec  _ACCA
    breq  SoftDDS.TriLoop
    dec  _ACCA
    breq  SoftDDS.SquLoop
    rjmp  SoftDDS.myExit

   ; _ACCDLO, _ACCDHI, _ACCCLO is the phase accumulator
   ; _ACCFLO, _ACCFHI, _ACCBLO is the adder value determining frequency

   ; Sinus:
    SoftDDS.SinLoop:
    add _ACCDLO, _ACCFLO; 1  add value to accumulator
    adc _ACCDHI, _ACCFHI; 1
    adc _ACCCLO, _ACCBLO; 1
    lpm; 3, ROM Zugriff Sinustabelle
    out PORTA, _ACCGLO; 1  output byte to port
    in        _ACCA, PIND; 1
    CPSE      _ACCA, SoftDDS.m; 2, bei Änderung an Taster-Port abbrechen
    rjmp SoftDDS.myExit; bei Abbruch
    rjmp SoftDDS.SinLoop; 2 = > 12 cycles

   ; Rechteck:
    SoftDDS.SquLoop:
    add _ACCDLO, _ACCFLO; 1
    adc _ACCDHI, _ACCFHI; 1
    adc _ACCCLO, _ACCBLO; 1
    ldi  _ACCA, $00; 1
    brmi  SoftDDS.setsqu; 1 / 2
    ldi  _ACCA, $FF; 0 / 1
    SoftDDS.setsqu:
    out PORTA, _ACCA; 1
    in        _ACCA, PIND; 1
    CPSE      _ACCA, SoftDDS.m; 2, bei Änderung an Taster-Port abbrechen
    rjmp SoftDDS.myExit; bei Abbruch
    rjmp SoftDDS.SquLoop; 2 = > 12 cycles

    in          SoftDDS.m, PIND;  m:= PinD;
    ldi  _ACCDHI, $00; clear accumulator
    ldi  _ACCDLO, $00
    mov  _ACCFLO, SoftDDS.DDSL; setup adder registers
    mov  _ACCFHI, SoftDDS.DDSM
    mov  _ACCBLO, SoftDDS.DDSH;

   ; Sägezahn:
    SoftDDS.TriLoop:
    add _ACCDLO, _ACCFLO; 1
    adc _ACCDHI, _ACCFHI; 1
    adc _ACCCLO, _ACCBLO; 1

    mov _ACCA, _ACCCLO; Zählerstand LSB
    nop
    nop

    out PORTA, _ACCA; 1
    in        _ACCA, PIND; 1
    CPSE      _ACCA, SoftDDS.m; 2, bei Änderung an Taster-Port abbrechen
    rjmp SoftDDS.myExit; bei Abbruch
    rjmp SoftDDS.TriLoop; 2 = > 12 cycles

    SoftDDS.myExit:
    ldi  _ACCA, 128; Ausgang auf 8-Bit-Mittelwert
    out PORTA, _ACCA
  endasm;
  enableints;
end;
{$ENDIF}
{###########################################################################}


procedure SendSR;  //Sende MP3switchState an den 4094 oder Ausgangsport

begin
  if Wave=c_audio then
    b_ExtOnMP3Power:= high;
  else
    b_ExtOnMP3Power:= low;
  endif;
  MP3switchTemp := MP3State OR SwitchState;
  asm;
    LDS _ACCA, SoftDDS.MP3switchTemp;
    sbi  SoftDDS.DDSOutPort, SoftDDS.b_STROBE
    cbi  SoftDDS.DDSOutPort, SoftDDS.b_SCLK
    ldi  _ACCB, 8

    SoftDDS.srloop:
    LSL  _ACCA
    brcs SoftDDS.datahigh1
    cbi  SoftDDS.DDSOutPort, SoftDDS.b_SDATA
    rjmp SoftDDS.dataset1
    SoftDDS.datahigh1:
    sbi  SoftDDS.DDSOutPort, SoftDDS.b_SDATA
    SoftDDS.dataset1:
    nop
    sbi  SoftDDS.DDSOutPort, SoftDDS.b_SCLK
    nop
    cbi  SoftDDS.DDSOutPort, SoftDDS.b_SCLK
    dec _ACCB
    BRNE  SoftDDS.srloop

    cbi  SoftDDS.DDSOutPort, SoftDDS.b_STROBE
    sbi  SoftDDS.DDSOutPort, SoftDDS.b_SCLK
  endasm;
end;

{AD9833 DDS functions }
{$IFNDEF miniDDS}
procedure SendDDS;  //Sende ein Wort an den DDS-Chip

begin
  asm;
    lds  _ACCDLO, SoftDDS.dss_cmd
    lds  _ACCDHI, SoftDDS.dss_cmd+1
    cbi  SoftDDS.DDSOutPort, SoftDDS.b_FSYNC

    ldi  _ACCB, 8

    SoftDDS.ddsloop1:    ; höherwertiges Byte rausschieben
    lsl  _ACCDHI
    brcs SoftDDS.ddsdatahigh
    cbi  SoftDDS.DDSOutPort, SoftDDS.b_SDATA
    rjmp SoftDDS.ddsdataset
    SoftDDS.ddsdatahigh:
    sbi  SoftDDS.DDSOutPort, SoftDDS.b_SDATA
    SoftDDS.ddsdataset:
    cbi  SoftDDS.DDSOutPort, SoftDDS.b_SCLK
    nop
    sbi  SoftDDS.DDSOutPort, SoftDDS.b_SCLK
    dec _ACCB
    brne  SoftDDS.ddsloop1

    ldi  _ACCB, 8

    SoftDDS.dssloop2:    ; niederwertiges Byte rausschieben
    lsl  _ACCDLO
    brcs SoftDDS.ddsdatahigh2
    cbi  SoftDDS.DDSOutPort, SoftDDS.b_SDATA
    rjmp SoftDDS.ddsdataset2
    SoftDDS.ddsdatahigh2:
    sbi  SoftDDS.DDSOutPort, SoftDDS.b_SDATA
    SoftDDS.ddsdataset2:
    cbi  SoftDDS.DDSOutPort, SoftDDS.b_SCLK
    nop
    sbi  SoftDDS.DDSOutPort, SoftDDS.b_SCLK
    dec _ACCB
    brne  SoftDDS.dssloop2

    sbi  SoftDDS.DDSOutPort, SoftDDS.b_FSYNC
  endasm;
end;
{$ENDIF}


procedure SendLevel(step, channel : byte);
begin
{$IFNDEF miniDDS}
//Sende Adresse 0 und ein Byte an den Poti-Chip LM1972
  _ACCDLO:=channel;
  _ACCDHI:=step;
  asm;
    sbi SoftDDS.DDSOutPort, SoftDDS.b_FSYNC;
    cbi SoftDDS.DDSOutPort, SoftDDS.b_SDATA;
    cbi SoftDDS.DDSOutPort, SoftDDS.b_SCLK;
    cbi SoftDDS.DDSOutPort, SoftDDS.b_LOADPOT;
    ldi  _ACCB, 7
    SoftDDS.levelloop1:    ; 6 Nullen rausschieben
    sbi SoftDDS.DDSOutPort, SoftDDS.b_SCLK;
    nop
    cbi SoftDDS.DDSOutPort, SoftDDS.b_SCLK
    dec _ACCB
    brne  SoftDDS.levelloop1
    dec _ACCDLO
    brne  SoftDDS.channelset; wenn 0 gewesen, überspringen
    sbi SoftDDS.DDSOutPort, SoftDDS.b_SDATA;  1 rausschieben
    nop
    SoftDDS.channelset:
    sbi SoftDDS.DDSOutPort, SoftDDS.b_SCLK;
    nop
    cbi SoftDDS.DDSOutPort, SoftDDS.b_SCLK;

    ldi  _ACCB, 8
    SoftDDS.levelloop2:    ; Byte Step rausschieben
    lsl  _ACCDHI; step shiften
    brcs SoftDDS.leveldatahigh2
    cbi  SoftDDS.DDSOutPort, SoftDDS.b_SDATA
    rjmp SoftDDS.leveldataset2
    SoftDDS.leveldatahigh2:
    sbi  SoftDDS.DDSOutPort, SoftDDS.b_SDATA
    SoftDDS.leveldataset2:
    nop;
    sbi SoftDDS.DDSOutPort, SoftDDS.b_SCLK;
    nop;
    nop;
    cbi SoftDDS.DDSOutPort, SoftDDS.b_SCLK;
    dec _ACCB
    brne  SoftDDS.levelloop2
    sbi SoftDDS.DDSOutPort, SoftDDS.b_LOADPOT;
    sbi SoftDDS.DDSOutPort, SoftDDS.b_SDATA;
    sbi SoftDDS.DDSOutPort, SoftDDS.b_SCLK;
  endasm;
{$ENDIF}
end;

procedure SetLevelDDS;
//Pegelsteller und Relais setzen, Frequenz einstellen
var j: byte;
  freq, fac, acc : LongInt;
  freqHi, freqLo : word;
begin
//Pegel einstellen
{$IFDEF miniDDS}
  SwitchState:= 7 - LeveldB;
//MP3Power wird in SendSR eingefügt, SoftDDS-Routine berücksichtigt Wave,
//deshalb nur:
  SendSR;
{$ELSE}

//Relais und MP3-Power setzen
  SwitchState:=0;
  GainOffset:=0;
  case Wave of
    c_sinw :
        wave_cmd:= c_ddssinecmd;
      |
    c_triw :
        wave_cmd:= c_ddstrianglecmd;
      |
    c_squw :
        wave_cmd:= c_ddssquarecmd;
        b_SquareSw:= high;
      |
    c_audio : //externe Quelle, DSS abschalten
        wave_cmd:= c_ddsresetcmd;
      |
  endcase;
//  b_LEDpwr:=high;  // zusätzliche LEDs default aus
//  b_LEDsym:=high;
//  if OutputMode > c_symo then   // PowerAmp On
//    b_PwrSw:= high;
//    b_LEDpwr:=low;  // zusätzliche LED an
//    GainOffset:=PwrGain;
//  endif;
//MP3Power wird in SendSR eingefügt

// - (256-80, 80=Anzahl eigener Stufen bis Vollaussteuerung +10 dB)
  k:= - LeveldB - 176;
  j:= k;

  if LeveldB < 20 then
//Relais für Abschwächer
    b_AttnSw:= high;
    k:= k - 20; //-20dB
  endif;

//Relais setzen
  SendSR;

{wenn LM1972,  bis -48 dB 0,5-dB-Sprünge}
  if k < 48 then
    k := k shl 1;      // *2
  else
    k:= k + 48;
  endif;
  SendLevel(k, 0);

  if OutputMode = c_symo then   // Symmetry Attn. -6 dB Hardware
    b_SymSw:= high;
//    b_LEDsym:=low;
  endif;
  k:= Adj+ (Frequ2 shl 4); // Frequenzgangkorrektur
  k:= k + gettable(dBadj, j);

  SendLevel(k, 1);

{$ENDIF}

//DSS-Frequenz einstellen
  freq:= 0;
  for i := 0 to 6 do                //Einzelne Stellen aufaddieren
    fac:= LongInt(gettable(EditArray, (i)));
    acc:= gettable(fhz, i);
    freq:= freq + (acc*fac);
  endfor;
  acc:= LongInt(gettable(fdhz, FrequDez)); //Dezihertz
  freq:= freq + acc;
{$IFDEF miniDDS}
  freqHi:= hiword(freq);
  freqLo:= Loword(freq);
  DDSL:= Lo(freqLo);
  DDSM:= Hi(freqLo);
  DDSH:= Lo(freqHi);
{$ELSE}
  dss_cmd:= loword(freq) AND %0011111111111111;
  dss_cmd:= dss_cmd OR %0100000000000000;
  SendDDS;
  freq:= freq shl 2;
  dss_cmd:= hiword(freq) AND %0011111111111111;
  dss_cmd:= dss_cmd OR %0100000000000000;
  SendDDS;
  dss_cmd:= wave_cmd;
  SendDDS;
{$ENDIF}
end;


