/************************************************/
/*                                              */
/* File        : usercalb.c                     */
/*                                              */
/* Command     : calb                           */
/* Comment     : CALB library interface         */
/*                                              */
/* Author : Sfiligoi Igor                       */
/*                                              */
/* Created       : 23.04.1997                   */
/* Last modified : 12.05.1997                   */
/*                                              */
/************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <Error.h>
#include <GeoVme.h>
#include <calb.h>

#include "usercalb.h"

/* calb ispresent data function*/
/* return TL_OK iff no error */
int calbt_tl_ispresent(calbt_t_ispresent *data)
{
  int res;

  /* a calb function should be used, but at the moment there is no such function */

  if (GeoVme_exist(data->chain,data->crate,data->slot)!=GEOVME_BOARD_EXIST)
    {
      data->result = 0;
      return TL_OK;
    }

  res = GeoVme_btype(data->chain,data->crate,data->slot);

  if (res==GEOVME_CADC_BTYPE)
    data->result = 1;
  else if (res==GEOVME_CTDC_BTYPE)
    data->result = 2;
  else
    data->result = 0;

  return TL_OK;
}

/* calb open data function*/
/* return TL_OK iff no error */
int calbt_tl_open(calbt_t_open *data)
{
  int res;

  res = calb_open(data->chain,data->crate,data->slot,(CALB_id *) &data->result);

  if (res!=CALB_ERROR_OK)
    {
      char *tmp;
      
      tmp = ErrorGetMessage();
      data->errorstr = (char *) malloc(strlen(tmp)+1);
      strcpy(data->errorstr,tmp);
      
      return TL_OK+res;
    }
  else
    return TL_OK;
}

/* calb close data function*/
/* return TL_OK iff no error */
int calbt_tl_close(calbt_t_close *data)
{
  /* Do nothing */
  /* have to be implemented */
  return TL_OK;
}


/* calb raw read creg data function*/
/* return TL_OK iff no error */
int calbt_tl_raw_read_creg(calbt_t_raw_read_creg *data)
{
  data->result = calbh_read_creg((CALB_id) data->cid);

  return TL_OK;
}

/* calb raw read sreg data function*/
/* return TL_OK iff no error */
int calbt_tl_raw_read_sreg(calbt_t_raw_read_sreg *data)
{
  data->result = calbh_read_sreg((CALB_id) data->cid);

  return TL_OK;
}

/* calb raw read rdtrg data function*/
/* return TL_OK iff no error */
int calbt_tl_raw_read_rdtrg(calbt_t_raw_read_rdtrg *data)
{
  data->result = calbh_read_rdtrg((CALB_id) data->cid);

  return TL_OK;
}

/* calb raw read dfifo data function*/
/* return TL_OK iff no error */
int calbt_tl_raw_read_dfifo(calbt_t_raw_read_dfifo *data)
{
  data->result = calbh_read_dfifo((CALB_id) data->cid);

  return TL_OK;
}

/* calb raw read hfifo data function*/
/* return TL_OK iff no error */
int calbt_tl_raw_read_hfifo(calbt_t_raw_read_hfifo *data)
{
  data->result = calbh_read_hfifo((CALB_id) data->cid);

  return TL_OK;
}

/* calb raw read latch data function*/
/* return TL_OK iff no error */
int calbt_tl_raw_read_latch(calbt_t_raw_read_latch *data)
{
  data->result = (unsigned int) calbh_readlatch_chan((CALB_id) data->cid, data->chnr);

  return TL_OK;
}

/* calb raw read pedestal data function*/
/* return TL_OK iff no error */
int calbt_tl_raw_read_pedestal(calbt_t_raw_read_pedestal *data)
{
  /* very inneficient, waiting for appropriate function in the library */

  CALBH_PEDS_val peds;
  int res;

  res = calbh_readpage_ped((CALB_id) data->cid, peds);

  if (res!=CALB_ERROR_OK)
    {
      char *tmp;
      
      tmp = ErrorGetMessage();
      data->errorstr = (char *) malloc(strlen(tmp)+1);
      strcpy(data->errorstr,tmp);
      
      return TL_OK+res;
    }
  else
    {
      if (data->pedside.nr==CALBT_Cpedside_A)
	data->result = peds.ped_a[data->pednr];
      else
	data->result = peds.ped_b[data->pednr];

      return TL_OK;
    }
}

/* calb raw write data function*/
/* return TL_OK iff no error */
int calbt_tl_raw_write_creg(calbt_t_raw_write_creg *data)
{
  int res;

  res = calbh_write_creg((CALBH_id) data->cid, data->value, 1);

  if (res!=CALB_ERROR_OK)
    {
      char *tmp;
      
      tmp = ErrorGetMessage();
      data->errorstr = (char *) malloc(strlen(tmp)+1);
      strcpy(data->errorstr,tmp);
      
      return TL_OK+res;
    }
  else
    return TL_OK;
}

/* calb raw write pedestal data function*/
/* return TL_OK iff no error */
int calbt_tl_raw_write_pedestal(calbt_t_raw_write_pedestal *data)
{
  /* very inneficient, waiting for appropriate function in the library */

  CALBH_PEDS_val peds;

  calbh_readpage_ped((CALB_id) data->cid, peds);

  if (data->pedside.nr==CALBT_Cpedside_A)
    peds.ped_a[data->pednr] = data->value & 0xfff;
  else
    peds.ped_b[data->pednr] = data->value & 0xfff;


  calbh_writepage_ped((CALB_id) data->cid, peds);

  return TL_OK;
}

/* calb read creg data function*/
/* return TL_OK iff no error */
int calbt_tl_read_creg(calbt_t_read_creg *data)
{
  CALB_CREG_bits bits;

  calb_read_creg((CALB_id) data->cid, bits);

  data->result.xresen = bits.xresen;
  data->result.d12force = bits.d12force;
  data->result.sel = bits.alu;
  data->result.berren = bits.berren;
  data->result.zsen = bits.zsen;
  data->result.acqen = bits.acqen;

  return TL_OK;
}

/* calb read sreg data function*/
/* return TL_OK iff no error */
int calbt_tl_read_sreg(calbt_t_read_sreg *data)
{
  CALB_SREG_bits bits;

  calb_read_sreg((CALB_id) data->cid, bits);

  data->result.xberr = bits.xberr;
  data->result.ffhd = bits.ffhd;
  data->result.hfhd = bits.hfhd;
  data->result.efhd = bits.efhd;
  data->result.ffd = bits.ffd;
  data->result.hfd = bits.hfd;
  data->result.efd = bits.efd;

  return TL_OK;
}

/* calb read rdtrg data function*/
/* return TL_OK iff no error */
int calbt_tl_read_rdtrg(calbt_t_read_rdtrg *data)
{
  data->result = calb_read_rdtrg((CALB_id) data->cid);

  return TL_OK;
}

/* calb read dfifo data function*/
/* return TL_OK iff no error */
int calbt_tl_read_dfifo(calbt_t_read_dfifo *data)
{
  CALB_DFIFO_bits bits;
  CALBB_DFIFO_unpack unpack;

  calb_read_dfifo((CALB_id) data->cid,bits);

  data->result.nvd = bits.nvd;
  calbb_dfifo_unpack(bits.fifodata,unpack);

  data->result.chan = unpack.chan;
  /* questo dovrebbe essere parte della libreria, ma.... */
  data->result.ab = unpack.data >>12;
  data->result.dato = unpack.data & 0xfff;

  return TL_OK;
}


/* calb read hfifo data function*/
/* return TL_OK iff no error */
int calbt_tl_read_hfifo(calbt_t_read_hfifo *data)
{
  CALB_HFIFO_bits bits;
  CALBB_HFIFO_unpack unpack;

  calb_read_hfifo((CALB_id) data->cid,bits);

  data->result.nvd = bits.nvd;
  calbb_hfifo_unpack(bits.fifodata,unpack);

  data->result.ntrig = unpack.ntrig;
  data->result.nword = unpack.nword;

  return TL_OK;
}

/* calb read latch data function*/
/* return TL_OK iff no error */
int calbt_tl_read_latch(calbt_t_read_latch *data)
{
  unsigned int ldata;

  ldata = (unsigned int) calbh_readlatch_chan((CALB_id) data->cid, data->chnr);

  /* This is done by hand for now */
  /* Should be done by the library */
  data->result.ab = bits_get_bit(ldata,12);
  data->result.ldata = ldata & 0xfff;

  return TL_OK;
}

/* calb read pedestal data function*/
/* return TL_OK iff no error */
int calbt_tl_read_pedestal(calbt_t_read_pedestal *data)
{
  /* very inneficient, waiting for appropriate function in the library */

  CALBH_PEDS_val peds;

  calbh_readpage_ped((CALB_id) data->cid, peds);

  if (data->pedside.nr==CALBT_Cpedside_A)
    data->result = peds.ped_a[data->pednr];
  else
    data->result = peds.ped_b[data->pednr];
  
  return TL_OK;
}

/* calb write creg data function*/
/* return TL_OK iff no error */
int calbt_tl_write_creg(calbt_t_write_creg *data)
{
  CALB_CREG_bits bits;
  int res;
  
  bits.xresen = data->rec.xresen;
  bits.d12force = data->rec.d12force;
  bits.alu = data->rec.sel;
  bits.berren = data->rec.berren;
  bits.zsen = data->rec.zsen;
  bits.acqen = data->rec.acqen;

  res = calb_write_creg((CALB_id) data->cid, bits);

  if (res!=CALB_ERROR_OK)
    {
      char *tmp;
      
      tmp = ErrorGetMessage();
      data->errorstr = (char *) malloc(strlen(tmp)+1);
      strcpy(data->errorstr,tmp);
      
      return TL_OK+res;
    }
  else
    return TL_OK;
}

/* calb write reset data function*/
/* return TL_OK iff no error */
int calbt_tl_write_reset(calbt_t_write_reset *data)
{
  int res;

  res = calb_write_reset((CALB_id) data->cid);

  if (res!=CALB_ERROR_OK)
    {
      char *tmp;
      
      tmp = ErrorGetMessage();
      data->errorstr = (char *) malloc(strlen(tmp)+1);
      strcpy(data->errorstr,tmp);
      
      return TL_OK+res;
    }
  else
    return TL_OK;
}


/* calb write clrtrg data function*/
/* return TL_OK iff no error */
int calbt_tl_write_clrtrg(calbt_t_write_clrtrg *data)
{
  int res;

  res = calb_write_clrtrg((CALB_id) data->cid);

  if (res!=CALB_ERROR_OK)
    {
      char *tmp;
      
      tmp = ErrorGetMessage();
      data->errorstr = (char *) malloc(strlen(tmp)+1);
      strcpy(data->errorstr,tmp);
      
      return TL_OK+res;
    }
  else
    return TL_OK;
}


/* calb write swtrg data function*/
/* return TL_OK iff no error */
int calbt_tl_write_swtrg(calbt_t_write_swtrg *data)
{
  int res;

  res = calb_write_swtrg((CALB_id) data->cid);

  if (res!=CALB_ERROR_OK)
    {
      char *tmp;
      
      tmp = ErrorGetMessage();
      data->errorstr = (char *) malloc(strlen(tmp)+1);
      strcpy(data->errorstr,tmp);
      
      return TL_OK+res;
    }
  else
    return TL_OK;
}

/* calb write pedestal data function*/
/* return TL_OK iff no error */
int calbt_tl_write_pedestal(calbt_t_write_pedestal *data)
{
  /* very inneficient, waiting for appropriate function in the library */

  CALBH_PEDS_val peds;
  int res;

  res = calbh_readpage_ped((CALB_id) data->cid, peds);

  if (res!=CALB_ERROR_OK)
    {
      char *tmp;
      
      tmp = ErrorGetMessage();
      data->errorstr = (char *) malloc(strlen(tmp)+32);
      sprintf(data->errorstr,"readpage_ped: %s",tmp);
      
      return TL_OK+res;
    }

  if (data->pedside.nr==CALBT_Cpedside_A)
    peds.ped_a[data->pednr] = data->value;
  else
    peds.ped_b[data->pednr] = data->value;


  res = calbh_writepage_ped((CALB_id) data->cid, peds);

  if (res!=CALB_ERROR_OK)
    {
      char *tmp;
      
      tmp = ErrorGetMessage();
      data->errorstr = (char *) malloc(strlen(tmp)+32);
      sprintf(data->errorstr,"writepage_ped: %s",tmp);
      
      return TL_OK+res;
    }
  else
    return TL_OK;
}

/* calb get data function*/
/* return TL_OK iff no error */
int calbt_tl_get(calbt_t_get *data)
{
  switch(data->fieldname.nr)
    {
    case CALBT_Cget_xresen:
      data->result = calb_get_xresen((CALB_id) data->cid);
      break;
    case CALBT_Cget_d12force:
      data->result = calb_get_d12force((CALB_id) data->cid);
      break;
    case CALBT_Cget_sel:
      data->result = calb_get_alu((CALB_id) data->cid);
      break;
    case CALBT_Cget_berren:
      data->result = calb_get_berren((CALB_id) data->cid);
      break;
    case CALBT_Cget_zsen:
      data->result = calb_get_zsen((CALB_id) data->cid);
      break;
    case CALBT_Cget_acqen:
      data->result = calb_get_acqen((CALB_id) data->cid);
      break;
    case CALBT_Cget_xberr:
      data->result = calb_get_xberr((CALB_id) data->cid);
      break;
    case CALBT_Cget_ffhd:
      data->result = calb_get_ffhd((CALB_id) data->cid);
      break;
    case CALBT_Cget_hfhd:
      data->result = calb_get_hfhd((CALB_id) data->cid);
      break;
    case CALBT_Cget_efhd:
      data->result = calb_get_efhd((CALB_id) data->cid);
      break;
    case CALBT_Cget_ffd:
      data->result = calb_get_ffd((CALB_id) data->cid);
      break;
    case CALBT_Cget_hfd:
      data->result = calb_get_hfd((CALB_id) data->cid);
      break;
    case CALBT_Cget_efd:
      data->result = calb_get_efd((CALB_id) data->cid);
      break;
    }

  return TL_OK;
}

/* calb set data function*/
/* return TL_OK iff no error */
int calbt_tl_set(calbt_t_set *data)
{
  int res;

  switch(data->fieldname.nr)
    {
    case CALBT_Cset_xresen:
      res = calb_set_xresen((CALB_id) data->cid,data->value);
      break;
    case CALBT_Cset_d12force:
      res = calb_set_d12force((CALB_id) data->cid,data->value);
      break;
    case CALBT_Cset_sel:
      res = calb_set_alu((CALB_id) data->cid,data->value);
      break;
    case CALBT_Cset_berren:
      res = calb_set_berren((CALB_id) data->cid,data->value);
      break;
    case CALBT_Cset_zsen:
      res = calb_set_zsen((CALB_id) data->cid,data->value);
      break;
    case CALBT_Cset_acqen:
      res = calb_set_acqen((CALB_id) data->cid,data->value);
      break;
    default:
      {
	char *tmp;
	
	data->errorstr = (char *) malloc(64);
	sprintf(data->errorstr,"Invalid field: %i",data->fieldname.nr);
	
	return TL_OK+1;
      }
      break;
    }

  if (res!=CALB_ERROR_OK)
    {
      char *tmp;
      
      tmp = ErrorGetMessage();
      data->errorstr = (char *) malloc(strlen(tmp)+1);
      strcpy(data->errorstr,tmp);
      
      return TL_OK+res;
    }
  else
    return TL_OK;
}

/* calb readpage csreg data function*/
/* return TL_OK iff no error */
int calbt_tl_readpage_csreg(calbt_t_readpage_csreg *data)
{
  CALB_PAGE_CSR_bits bits;

  calb_readpage_csr((CALB_id) data->cid, bits);

  data->result.xresen = bits.xresen;
  data->result.d12force = bits.d12force;
  data->result.sel = bits.alu;
  data->result.berren = bits.berren;
  data->result.zsen = bits.zsen;
  data->result.acqen = bits.acqen;
  data->result.xberr = bits.xberr;
  data->result.ffhd = bits.ffhd;
  data->result.hfhd = bits.hfhd;
  data->result.efhd = bits.efhd;
  data->result.ffd = bits.ffd;
  data->result.hfd = bits.hfd;
  data->result.efd = bits.efd;

  return TL_OK;
}

/* calb readpage pedestal data function*/
/* return TL_OK iff no error */
int calbt_tl_readpage_pedestal(calbt_t_readpage_pedestal *data)
{
  CALBH_PEDS_val peds;
  int i;

  calbh_readpage_ped((CALB_id) data->cid, peds);

  for (i=0; i<30; i++)
    {
      data->result.ped_a[i] = peds.ped_a[i];
      data->result.ped_b[i] = peds.ped_b[i];
    }

  return TL_OK;
}