{###########################################################################}


{FPGA functions }

procedure SendFPGA8;
//Sende und empfange ein Daten-Byte an den FPGA-Chip über SPI
begin
  asm;
    cli ; Disable interrupts
    lds  _ACCA, FPGA.FPGAsendByte
    cbi  FPGA.FPGAport, FPGA.b_DATASEL
    out SPDR, _ACCA    ; SPI wurde von FAT16-Treiber eingeschaltet!
  SPIwait8_1:
    in _ACCA, SPSR
    sbrs _ACCA,7
    rjmp SPIwait8_1
    in _ACCA, SPDR
    sts  FPGA.FPGAreceiveByte, _ACCA  ;Lesewert zurück ins Datenbyte
    sbi  FPGA.FPGAport, FPGA.b_DATASEL
    sei ; Enable interrupts
  endasm;
end;

procedure SendFPGA16;
//Sende und empfange ein Daten-Wort (16 Bit-Register) an den FPGA-Chip über SPI
begin
  asm;
    cli ; Disable interrupts
    lds  _ACCA, FPGA.FPGAsendWord+1
    cbi  FPGA.FPGAport, FPGA.b_DATASEL
    out SPDR, _ACCA    ; SPI wurde von FAT16-Treiber eingeschaltet!
  SPIwait16_3:
    in _ACCA, SPSR
    sbrs _ACCA,7
    rjmp SPIwait16_3
    in _ACCA, SPDR
    sts  FPGA.FPGAreceiveWord+1, _ACCA

    lds  _ACCA, FPGA.FPGAsendWord+0
    out SPDR, _ACCA
  SPIwait16_4:
    in _ACCA, SPSR
    sbrs _ACCA,7
    rjmp SPIwait16_4
    in _ACCA, SPDR
    sts  FPGA.FPGAreceiveWord+0, _ACCA

    sbi  FPGA.FPGAport, FPGA.b_DATASEL
    sei ; Enable interrupts
  endasm;
end;

procedure SendFPGA32;
//Sende und empfange ein Daten-Langwort (32 Bit-Register) an den FPGA-Chip über SPI
begin
  asm;
    cli ; Disable interrupts
    lds  _ACCA, FPGA.FPGAsendLong+3
    cbi  FPGA.FPGAport, FPGA.b_DATASEL
    out SPDR, _ACCA    ; SPI wurde von FAT16-Treiber eingeschaltet!
  SPIwait32_1:
    in _ACCA, SPSR
    sbrs _ACCA,7       ; SPIF gesetzt?
    rjmp SPIwait32_1   ; auf Ende des SPI-Transfer warten
    in _ACCA, SPDR     ; und empfangenes Byte wieder in FPGAsendLong ablegen
    sts  FPGA.FPGAreceiveLong+3, _ACCA

    lds  _ACCA, FPGA.FPGAsendLong+2
    out SPDR, _ACCA     ; SPI von FAT16-Treiber eingeschaltet!
  SPIwait32_2:
    in _ACCA, SPSR
    sbrs _ACCA,7
    rjmp SPIwait32_2
    in _ACCA, SPDR
    sts  FPGA.FPGAreceiveLong+2, _ACCA

    lds  _ACCA, FPGA.FPGAsendLong+1
    out SPDR, _ACCA
  SPIwait32_3:
    in _ACCA, SPSR
    sbrs _ACCA,7
    rjmp SPIwait32_3
    in _ACCA, SPDR
    sts  FPGA.FPGAreceiveLong+1, _ACCA

    lds  _ACCA, FPGA.FPGAsendLong+0
    out SPDR, _ACCA
  SPIwait32_4:
    in _ACCA, SPSR
    sbrs _ACCA,7
    rjmp SPIwait32_4
    in _ACCA, SPDR
    sts  FPGA.FPGAreceiveLong+0, _ACCA

    sbi  FPGA.FPGAport, FPGA.b_DATASEL
    sei ; Enable interrupts
  endasm;
end;


procedure SendFPGAreg;
//Sende ein Byte (Registeradresse) an den FPGA-Chip
begin
  asm;
    cli ; Disable interrupts
    lds  _ACCA, FPGA.FPGAreg
    cbi  FPGA.FPGAport, FPGA.b_REGSEL
    out SPDR, _ACCA     ; SPI von FAT16-Treiber eingeschaltet!
  SPIwaitReg:
    in _ACCA, SPSR
    sbrs _ACCA,7 ; SPIF?
    rjmp SPIwaitReg     ;  auf Ende des SPI-Transfer warten
    sbi  FPGA.FPGAport, FPGA.b_REGSEL
    sei ; Enable interrupts
  endasm;
end;

procedure ShiftFPGAconf;  //Sende ein Byte an FPGA-Configuration
begin
  asm;
    lds  _ACCA, FPGA.FPGAbyte
    ldi  _ACCB, 8
    FPGA.confloop1:    ; höherwertiges Byte rausschieben
    cbi  FPGA.ConFPGABitPort, FPGA.c_DATA
    sbrc _ACCA,7 // Bit high?
    sbi  FPGA.ConFPGABitPort, FPGA.c_DATA
    sbi  FPGA.ConFPGABitPort, FPGA.c_CCLK
    LSL  _ACCA
    cbi  FPGA.ConFPGABitPort, FPGA.c_CCLK
    dec _ACCB
    brne  FPGA.confloop1
  endasm;
end;


procedure ShiftFPGAconfblock;  //Sende einen Block an FPGA-Configuration
begin
  asm;
    LDI       _ACCCLO, FPGA.BlockTable AND 0FFh  ;Z-Register
    LDI       _ACCCHI, FPGA.BlockTable SHRB 8

    FPGA.shiftFPGAbyte:
   ; Z-Pointer auf Array-Eintrag
    ld   _ACCA, Z
    cbi  FPGA.ConFPGABitPort, FPGA.c_CCLK
    in   _ACCB, FPGA.ConFPGABitPort
   ; schleifenloses, auf Schnelligkeit optimiertes Ausschieben eines Bytes
   ; DATA  __--__--__
   ; CCLK  _---_---_-
   
    bst   _ACCA,7  ; MSBit in T Flag
    bld  _ACCB, FPGA.c_DATA  ; T Flag in Register speichern
    out  FPGA.ConFPGABitPort, _ACCB ; mit CCLK auf low
    sbi  FPGA.ConFPGABitPort, FPGA.c_CCLK  ; CCLK high
    bst   _ACCA,6
    bld  _ACCB, FPGA.c_DATA  ; T Flag in Register speichern
    out  FPGA.ConFPGABitPort, _ACCB ; mit CCLK auf low
    sbi  FPGA.ConFPGABitPort, FPGA.c_CCLK  ; CCLK high
    bst   _ACCA,5
    bld  _ACCB, FPGA.c_DATA  ; T Flag in Register speichern
    out  FPGA.ConFPGABitPort, _ACCB ; mit CCLK auf low
    sbi  FPGA.ConFPGABitPort, FPGA.c_CCLK  ; CCLK high
    bst   _ACCA,4
    bld  _ACCB, FPGA.c_DATA  ; T Flag in Register speichern
    out  FPGA.ConFPGABitPort, _ACCB ; mit CCLK auf low
    sbi  FPGA.ConFPGABitPort, FPGA.c_CCLK  ; CCLK high
    bst   _ACCA,3
    bld  _ACCB, FPGA.c_DATA  ; T Flag in Register speichern
    out  FPGA.ConFPGABitPort, _ACCB ; mit CCLK auf low
    sbi  FPGA.ConFPGABitPort, FPGA.c_CCLK  ; CCLK high
    bst   _ACCA,2
    bld  _ACCB, FPGA.c_DATA  ; T Flag in Register speichern
    out  FPGA.ConFPGABitPort, _ACCB ; mit CCLK auf low
    sbi  FPGA.ConFPGABitPort, FPGA.c_CCLK  ; CCLK high
    bst   _ACCA,1
    bld  _ACCB, FPGA.c_DATA  ; T Flag in Register speichern
    out  FPGA.ConFPGABitPort, _ACCB ; mit CCLK auf low
    sbi  FPGA.ConFPGABitPort, FPGA.c_CCLK  ; CCLK high
    bst   _ACCA,0
    bld  _ACCB, FPGA.c_DATA  ; T Flag in Register speichern
    out  FPGA.ConFPGABitPort, _ACCB ; mit CCLK auf low
    sbi  FPGA.ConFPGABitPort, FPGA.c_CCLK  ; CCLK high

    cbi  FPGA.ConFPGABitPort, FPGA.c_CCLK  ; CCLK wieder low
    inc   _ACCCLO
    brne  FPGA.shiftFPGAbyte  ; wenn 0 => 256 Durchläufe
  endasm;
end;

{###########################################################################}

//FPGA-Funktionen

procedure ExchangeFPGA(myreg:byte);
// Kompketter Datenaustauch von vier 32-Bit-Registern über SPI
begin
    FPGAreg:=myreg;     // Schreib-Register
    SendFPGAreg;
    FPGAsendLong:=ParamLongArray[myreg]; // ans FPGA
    SendFPGA32;
    InputLongArray[myreg]:=FPGAreceiveLong; // kommt ohnehin gleichzeitig an
end;



