#ifndef FACT_FAD_H
#define FACT_FAD_H

//---------------------------------------------------------------
//
// FAD internal structures
//
//---------------------------------------------------------------

    //
// Other definitions
//
#define MAX_ADDR 0xFF           // highest address in Config-RAM
#define BADDR_ROI 0x00          // Baseaddress ROI-Values
#define BADDR_DAC 0x24          // Baseaddress DAC-Values
#define BADDR_CONT_TRIGGER_TIME 0x2C // Baseaddress for the continouus trigger timing.
#define ADDR_RUNNUMBER 0x2D //
#define MAX_VAL 65535
#define MAX_ROIVAL 1024
#define MAX_DACVAL 65535

#define NChannels      9
#define NBins       1024
#define NChips         4
#define NTemp          4
#define NDAC           8

//
// Data structures
//

typedef struct{
  int hardID ;       //hardware ID
  int pos_i ;        //geometrical positon row 
  int pos_j ;        //                    column
  int G_APD ;        //G-APD identifier
  double V_op ;      //operation voltage
  int HV_B ;         //HV Board
  int HV_C ;         //HV Channel
  double pos_X ;     //geometrical position in pixel units
  double pos_Y ;     //
} PIX_MAP ;


typedef struct {

  uint16_t start_package_flag;
  uint16_t package_length;
  uint16_t version_no;
  uint16_t PLLLCK;

  uint16_t trigger_crc;
  uint16_t trigger_type;
  uint32_t trigger_id;

  uint32_t fad_evt_counter;
  uint32_t REFCLK_frequency;

  uint16_t board_id;
  uint8_t  zeroes;
  int8_t   adc_clock_phase_shift;
  uint16_t number_of_triggers_to_generate;
  uint16_t trigger_generator_prescaler;

  uint64_t DNA;

  uint32_t time;
  uint32_t runnumber;

  int16_t  drs_temperature[NTemp];

  uint16_t dac[NDAC];

} __attribute__((__packed__)) PEVNT_HEADER;

typedef struct {
uint16_t id;
uint16_t start_cell;
uint16_t roi;
uint16_t filling;
uint16_t adc_data[];
} __attribute__((__packed__)) PCHANNEL;


typedef struct {
uint16_t package_crc;
uint16_t end_package_flag;
} __attribute__((__packed__)) PEVNT_FOOTER;

#define NBOARDS      40      // max. number of boards
#define NPIX       1440      // max. number of pixels
#define NTMARK      160      // max. number of timeMarker signals
#define MAX_SOCK    280      // NBOARDS * 7


typedef union {
  uint8_t   B[8] ;        //8 bytes
  uint16_t  S[4] ;        //4 short
  uint32_t  I[2] ;        //2 int
  uint64_t  L    ;        //1 long
} L_WORD ;

typedef union {
  uint8_t   B[4] ;        //4 bytes
  uint16_t  S[2] ;        //2 short
  uint32_t  I    ;        //1 int
} I_WORD ;


//---------------------------------------------------------------
//
// Data structures
//
//---------------------------------------------------------------

typedef struct {
  uint16_t Roi ;            // #slices per pixel (same for all pixels and tmarks)
  uint32_t EventNum ;       // EventNumber as from FTM
  uint16_t TriggerType ;    // Trigger Type from FTM

  uint32_t SoftTrig ;       // SoftTrigger Info (TBD)
  uint32_t PCTime ;         // when did event start to arrive at PC

  uint32_t BoardTime[NBOARDS];//

   int16_t StartPix[NPIX];  // First Channel per Pixel (Pixels sorted according Software ID)  ; -1 if not filled

   int16_t StartTM[NTMARK]; // First Channel for TimeMark (sorted Hardware ID) ; -1 if not filled

   int16_t Adc_Data[];     // final length defined by malloc ....

} EVENT ;



//---------------------------------------------------------------




typedef struct {
  uint32_t Version ;
  uint32_t RunType ;
  uint16_t NBoard  ;
  uint16_t NPix ;
  uint16_t NTm  ;
  uint16_t Nroi ;

//headers of all FAD-boards for first event ==> all FAD configs
  PEVNT_HEADER *FADhead;    // [ NBoards ] sorted Board Headers (according Hardware ID)

//do we also have info about FTM config we want to add here ???
} RUN_HEAD ;


//---------------------------------------------------------------


typedef struct {
  uint32_t nEventsOk ;  //how many events were written
  uint32_t nEventsRej;  //how many events were rejected by SW-trig
  uint32_t nEventsBad;  //how many events were rejected by Error

  uint32_t PCtime0 ;    //time when first event received
  uint32_t PCtimeX ;    //time when last  event received

 
//probably more to come ...
} RUN_TAIL ;



//---------------------------------------------------------------

#define MAX_RUN   256
#define MAX_EVT   32768  //don't worry, for events is MAX_RUN*MAX_EVT

typedef void* FileHandle_t ;

typedef struct {
  uint32_t runId ;       //run number
  uint32_t lastTime ;    //time when last event written so far
  uint32_t closeTime ;   //time when run should be closed
  uint32_t nextEvt ;     //next event number to be written
  uint32_t waitEvt ;     //event that would be ready to be written
   int32_t fileId  ;     //<0 never opened, 0=open, >0 closed
  FileHandle_t fileHd ;   //fileHandle (NULL if not open)
   int16_t ctrlId[MAX_EVT] ; //index to buffId (sorted list; -1 =end)
  uint16_t buffId[MAX_EVT] ; //index to mBuffer(buffered raw data)
} RUN_CTRL ;



//---------------------------------------------------------------


typedef struct {
  int32_t evNum ;
  int32_t runNum ;
  int32_t fadLen ;
  int32_t nBoard ;
  int16_t board[ NBOARDS ];
  int32_t nRoi   ;
  int32_t pcTime ;
  int32_t evtLen ;
  EVENT   *fEvent  ;
  PEVNT_HEADER *FADhead; //

} WRK_DATA ;             //internal to eventbuilder


//---------------------------------------------------------------


typedef struct {
  int frstPtr ;             //first used index
  int lastPtr ;             //last  used index 
  int evtBuf[MAX_EVT*MAX_RUN] ;     //index of event in mBuffer
  int evtStat[MAX_EVT*MAX_RUN] ;    //status of event:
                                      // -1=empty
                                      //  1..NBoards reading #Boards
                                      // 90-99 : end reading
                                      //128-255: processing
                                      //256-
                                      //201=start processing
                                      //299=end processing
                                      //901=start writing
                                      //999=finished writing
                                //(TO BE REVISED)

  int pcTime[MAX_EVT*MAX_RUN] ;     //time when last action happened
} EVT_CTRL ;

//---------------------------------------------------------------


typedef struct {
   struct sockaddr_in sockAddr ;
   int    sockDef ; //<0 not defined/ ==0 not to be used/ >0 used
} FACT_SOCK ; 


#endif
