// pulsegen_files

procedure CheckCard;
begin
  if F16_DiskInit then
    F16_DiskReset;
    CardOK:=true;
    NoCard:=false;
  else
    CardOK:=false;
    NoCard:=true;
  endif;
end;

procedure GetDirectory;
var
SR : TSearchRec;
st : TfileName;
begin
// search for filename/directory entries, accept wildcards
  i:=0;
  CheckCard;
  FileAnzahl:=0;
  if NoCard then
    LCDxy_M(LCD_m1, 0, 3);
    Write(LCDOut_M, 'Insert Card');
    LCDclrEOL_m(LCD_m1);
    setsystimer(DisplayTimer,100);
    FileNum:=0;
    FileAnzahl:=0;
  else
    if (F16_FindFirst ('\', '*.*', [faArchive], SR)) then
      repeat
        DirectoryArray[i]:= SR.Name;
        inc(i);
      until (i=32) or (not F16_FindNext (SR));
    endif;
    FileAnzahl:= Int8(i);
    DirectoryDone:=true;
    LCDxy_M(LCD_m1, 0, 3);
    write(lcdout_m,'Select BIT/INI File');
    LCDclrEOL_m(LCD_m1);
  endif;
end;

procedure FlashActivity;
// Aktivitätsanzeige 1. Zeile, starten mit ParamDigit=8!
begin
  if isSystimerzero(DisplayTimer) then
    setsystimer(DisplayTimer,20);
    LCDxy_M(LCD_m1, 0, 2);
    Write(LCDOut_M, longtostr(byteCount shl 11));
  endif;
end;

procedure FPGAload(myBinFileName:String[12]);
// liest Datei "FPGAn.bin" von SD- oder MMC-Karte und programmiert
// Spartan-2-FPGA über SPI damit

var firstBlock, FPGAresponse:Boolean;
  BytesRead:word;
begin
  FPGAresponse:=false;
  byteCount:=0;
  ReadErr:=false;
  ConfErr:=false;
  if CardOK then
    if F16_FileExist ('\', myBinFileName, faFilesOnly) then
      LastBinFileNum:=FileNum; // Binärdateinummer merken
      F16_FileAssign (BinFile, '',myBinFileName);
      F16_FileReset (BinFile); // Datei zum Lesen öffnen
      firstBlock:=true;
      while not F16_EndOfFile (BinFile) do // read the entire file
        F16_BlockRead (BinFile, @BlockArray, 256, BytesRead);
        if firstBlock then
          FPGA_PROG:=low;
          udelay(1);
          FPGA_PROG:=high;
{$D-}
          mdelay(10);     // Setup-Zeit FPGA Spartan-3
{$D+}
          firstBlock:=false;
          if not FPGA_Done then
            FPGAresponse:=true;
          endif;
          LCDxy_M(LCD_m1, 0, 1);
          Write(LCDOut_M, 'Byte Count:');
          LCDclrEOL_m(LCD_m1);
          LCDxy_M(LCD_m1, 0, 2);
          LCDclrEOL_m(LCD_m1);
          setsystimer(DisplayTimer,10);
        endif;
        ShiftFPGAconfblock;
        inc(byteCount);
        FlashActivity;
        if FPGA_Done then break; endif;
      endwhile; // until end of file
      setsystimer(DisplayTimer,100);
      FPGAbyte:= 255;  // Wichtig: noch ein paar CCLK-Impulse nachschieben
      ShiftFPGAconf;
      F16_FileClose (BinFile);
      if (not FPGAresponse) or (not FPGA_Done) then
        LCDxy_M(LCD_m1, 0, 3);
        Write(LCDOut_M, 'Config Fail');
        LCDclrEOL_m(LCD_m1);
        setsystimer(DisplayTimer,200);
        ConfErr:=true;
      endif;
    else
      LCDxy_M(LCD_m1, 0, 3);
      Write(LCDOut_M, 'Not Found');
      LCDclrEOL_m(LCD_m1);
      setsystimer(DisplayTimer,200);
      ReadErr:=true;
    endif;
  endif;
  NoCard:=not CardOK;
end;

procedure WriteDirEntry;
//Directory-Eintrag FileNum ausgeben
begin
   SubCh:=240;
   WriteChPrefix;
   ParamStr:= ByteToStr(FileNum);
   write(SerOut, ParamStr);
   SerOut(#32);
   SerOut('[');
   ParamStr:= DirectoryArray[FileNum];
   write(SerOut, ParamStr);
   SerOut(']');
   SerCRLF;
   mdelay(10);
end;


procedure ClearDirectory;
begin
  for i:=0 to 31 do
    DirectoryArray[i]:='<empty>';
  endfor;
  FileNum:=0;
  LastBinFileNum:=0;
  DirectoryDone:=false; // einlesen des Directory beim nächsten FileSel
end;

procedure AutoIncSetup(for_read:boolean);
// AutoInc vorbereiten: Länge, Start an SPI übermitteln
begin
  FPGAreg:=AutoIncReg+1;  // Schreib-Register Core-Select
  SendFPGAreg;
  FPGAsendbyte:=AutoIncSel; // AutoIncSel-Ziel ans FPGA, resettet Auto-Increment
  SendFPGA8;
  if for_read then
    FPGAreg:=AutoIncReg+3;  // Lesen triggern, SubCh 131
    SendFPGAreg;
    FPGAsendLong:=AutoIncBlockStart; // AutoIncBlockStart ans FPGA, resettet Auto-Increment
    SendFPGA32;
  else
    FPGAreg:=AutoIncReg+2;  // Schreib-Register Startadresse, SubCh 130
    SendFPGAreg;
    FPGAsendLong:=AutoIncBlockStart; // AutoIncBlockStart ans FPGA, resettet Auto-Increment
    SendFPGA32;
  endif;
  FPGAreg:=AutoIncReg;  // Schreib-Register Daten für DAT-Files
  SendFPGAreg;
end;

procedure AutoIncReset;
// AutoInc zurücksetzen, Core freigeben
begin
  FPGAreg:=AutoIncReg+1;  // Schreib-Register Adress-Reset
  SendFPGAreg;
  FPGAsendByte:=0; // resettet Core Select
  SendFPGA8;
end;

procedure DataFileType(myTypefileName:String[12];toRegister:Boolean;myIndex:Byte);
// Anzeige der Datei seriell
var myChar:char;
begin
  ReadErr:=true;
  if CardOK then
    if F16_FileExist ('\', myTypefileName, faFilesOnly) then
      F16_FileAssign (MemFile, '',myTypefileName);
      F16_FileReset (MemFile); // Datei zum lesen öffnen
      if toRegister then
        FPGAreg:=myIndex;  // Schreib-Register Daten für DAT-Files
        SendFPGAreg;
      endif;
      while (not F16_EndOfFile(MemFile)) do // read the entire file
        Read(MemFile,myChar);
        if toRegister then
          FPGAsendByte:=byte(myChar);
          SendFPGA8;  // nur Byte-Breite
          udelay(10);
          if mychar=#13 then
            mdelay(50);  // Pause zur Verarbeitung nach CR
          endif;
        else
          Serout(mychar);
          if mychar=#13 then
            SerOut(#10);
            mdelay(10);  // Pause zur Verarbeitung nach CR
          endif;
        endif;
      endwhile;
      F16_FileClose (MemFile);
      ReadErr:=false;
    endif;
  endif;
  NoCard:=not CardOK;
end;


procedure FileLoad(myLoadfileName:String[12]);  forward;
procedure CheckSer;  forward;
procedure InitLoad(myINITfileName:String[12]); forward;

procedure MEMload(myMEMfileName:String[12]; myHEXmode:Boolean);
// liest MEM-Datei von SD- oder MMC-Karte und überträgt in SPI-Register AutoIncReg
begin
  ReadErr:=true;
  repeat
  until not ButtonPressed;
  if CardOK and F16_FileExist ('\', myMEMfileName, faFilesOnly) then
    F16_FileAssign (MemFile, '',myMEMfileName);
    F16_FileReset (MemFile); // Datei zum Lesen öffnen
    AutoIncSetup(false);
    while (not ButtonPressed) and (not F16_EndOfFile(MemFile)) do // read the entire file
      ReadLn(MemFile,SerInpStr);
      if (SerInpStr[1]<>'@') and (length(SerInpStr)>1) then
      // Hex- ode Dezimal-String lesen, wandeln und senden
        if myHEXmode then  // Hex-Zahlen
          FPGAsendLong:=hexToInt(SerInpStr);
        else
          FPGAsendLong:=StrToInt(SerInpStr);
        endif;
        SendFPGA32;
      endif;
    endwhile; // until end of file
    AutoIncReset;
    F16_FileClose (MemFile);
    ReadErr:=false;
  endif;
  NoCard:=not CardOK;
end;

{$I pulsegen_parser.pas}

procedure InitLoad(myINITfileName:String[12]);
// liest Datei von SD- oder MMC-Karte und interpretiert Befehle nach
// c't-Lab-Syntax
var
  WaitLoops:Integer; verboseSave:Boolean;
begin
  repeat
  until not ButtonPressed;
  verboseSave:=verbose;
  ReadErr:=true;
  if CardOK then
   BusyFlag:=true;
   if F16_FileExist ('\', myINITfileName, faFilesOnly) then
      F16_FileAssign (InitFile, '',myINITfileName);
      F16_FileReset (InitFile); // Datei zum Lesen öffnen
      INITfileIsOpen:=true;
      while (not ButtonPressed) and (not F16_EndOfFile(InitFile)) do // read the entire file
        ReadLn(InitFile,SerInpStr);
        if SerInpStr[1]<>'/' then
          ParseSubCh;
        endif;
        SerInpStr:='';
        if serstat then
          CheckSer;
        endif;
      endwhile; // until end of file
      F16_FileClose (InitFile);
      SerInpStr:='';
      ReadErr:=false;
    endif;
  endif;
  INITfileIsOpen:=false;
  BusyFlag:=false;
  NoCard:=not CardOK;
  verbose:=verboseSave;
end;

{###########################################################################}


procedure FileLoad(myLoadfileName:String[12]);
// lädt File je nach Extension in das FPGA oder ins AutoInc-RAM

var myFileExt:String[3]; myFileName:String[8]; myReadErr:Boolean;
begin
  LCDxy_M(LCD_m1, 0, 3);
  LCDclrEOL_M(LCD_m1);
  write(lcdout_m,'Loading ');
  myFileExt:=ExtractFileExt(myLoadfileName);
  myFileName:=ExtractFileName(myLoadfileName);
  LEDactivity:=low;
  myReadErr:=true;
  if (myFileExt='BIN') or (myFileExt='BIT') then
    write(lcdout_m,'FPGA...');
    FPGAload(myLoadfileName);
    myReadErr:=ReadErr;
  endif;
  if myFileExt='INI' then
    write(lcdout_m,'INI...');
    InitLoad(myLoadfileName);
    myReadErr:=ReadErr;
  endif;
  if myFileExt='MEM' then
    // AutoIncReg muss manuell gesetzt sein, sonst Default Register/SubCh 128
    write(lcdout_m,'MEM...');
    MEMload(myLoadfileName,true);
    myReadErr:=ReadErr;
  endif;
  if myFileExt='DEC' then
    // AutoIncReg muss manuell gesetzt sein, sonst Default Register/SubCh 128
    write(lcdout_m,'MEMDEC...');
    MEMload(myLoadfileName,false);
    myReadErr:=ReadErr;
  endif;
  ReadErr:=myReadErr;
end;


