{###########################################################################}

procedure SendSR;
//Sende MP3switchState an den 4094 oder Ausgangsport

begin
  if MP3isOn 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_SDATAOUT
    rjmp SoftDDS.dataset1
    SoftDDS.datahigh1:
    sbi  SoftDDS.DDSOutPort, SoftDDS.b_SDATAOUT
    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 }
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_SDATAOUT
    rjmp SoftDDS.ddsdataset
    SoftDDS.ddsdatahigh:
    sbi  SoftDDS.DDSOutPort, SoftDDS.b_SDATAOUT
    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_SDATAOUT
    rjmp SoftDDS.ddsdataset2
    SoftDDS.ddsdatahigh2:
    sbi  SoftDDS.DDSOutPort, SoftDDS.b_SDATAOUT
    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;

procedure SendLevel(step, channel : byte);
begin
//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_SDATAOUT;
    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_SDATAOUT;  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_SDATAOUT
    rjmp SoftDDS.leveldataset2
    SoftDDS.leveldatahigh2:
    sbi  SoftDDS.DDSOutPort, SoftDDS.b_SDATAOUT
    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_SDATAOUT;
    sbi SoftDDS.DDSOutPort, SoftDDS.b_SCLK;
  endasm;
end;

{###########################################################################}

//DDS-Funktionen

procedure Frequenz2DDS;
//DSS-Frequenz aus Absolutfrequenz ermitteln
var
  acc : LongInt;
begin
  DDSfrequ:= 0;
  FreqStr:= longtostr(AktuelleFrequenz : 8:'0'); // mit führenden Nullen
  for i := 0 to 7 do                //Einzelne Stellen aufaddieren
    k:= byte(FreqStr[i+1])-48;
    acc:= gettable(fhz, i);
    DDSfrequ:= DDSfrequ + (acc*longint(k));
  endfor;
end;

procedure SetLevelDDS(myWave:byte);
//Pegelsteller und Relais setzen, AktuelleFrequenz einstellen
var
  freqHi, freqLo : word;
begin
//Pegel einstellen, Relais und MP3-Power setzen
  SwitchState:=0;
  GainOffset:=0;
  case myWave of
    c_sinw :
        wave_cmd:= c_ddssinecmd;
      |
    c_triw :
        wave_cmd:= c_ddstrianglecmd;
      |
    c_squw :
        wave_cmd:= c_ddssquarecmd;
        b_SquareSw:= high;
      |
  else
    wave_cmd:= c_ddsresetcmd; // Aus für  c_off und Audio
  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;

// -(256-80), 80=Anzahl eigener Stufen bis Vollaussteuerung +10 dB)
  k:= -AttnStep-176;

  if OutputMode in [c_symo, c_psymo] then   // Symmetry Attn. -6 dB
//    b_SymSw:= high;  // jetzt per Software erledigt wg. DC-Offset
    b_LEDsym:=low;
    k:= k + 6; //-6 dB für 0,5 Ua
  endif;
//MP3Power wird in SendSR eingefügt

  AttnAdjIndex:= k;  // Index für Adust-Tabelle

  if AttnStep < 20 then
//Relais für Abschwächer
    b_AttnSw:= high;
    k:= k - 20; //-20dB
  endif;
  SendSR; //Relais setzen

{beim 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); // Coarse-dB-Einstellung

//Fine-Adjust-Wert an LM1972 zweiten Kanal senden
  if AttnAdjIndex>63 then //Überlauf verhindern, letzter Wert für -54 bis -70 dB
    AttnAdjIndex:=63;
  endif;
  k:=gettable(EEdBadj, AttnAdjIndex);
  SendLevel(k, 1);
  
//DSS-AktuelleFrequenz einstellen
  Frequenz2DDS;
  dss_cmd:= loword(DDSfrequ) AND %0011111111111111;
  dss_cmd:= dss_cmd OR %0100000000000000;
  SendDDS;
  DDSfrequ:= DDSfrequ shl 2;
  dss_cmd:= hiword(DDSfrequ) AND %0011111111111111;
  dss_cmd:= dss_cmd OR %0100000000000000;
  SendDDS;
  dss_cmd:= wave_cmd;
  SendDDS;
end;

