/************************************************/
/*                                              */
/* File        : usercalbzsup.c                 */
/*                                              */
/* Command     : calb                           */
/* Comment     : CALB library interface         */
/*               Zero suppression               */
/*                                              */
/* Author : Sfiligoi Igor                       */
/*                                              */
/* Created       : 02.05.1997                   */
/* Last modified : 02.05.1997                   */
/*                                              */
/************************************************/

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

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

#include "usercalbzsup.h"

typedef struct
        {
	  CALBH_id cid;

	  unsigned int zsup_a[4096];
	  unsigned int zsup_b[4096];
        } CALBZS_id;

/* calbzsup new data function*/
/* return TL_OK iff no error */
int calbzst_tl_new(calbzst_t_new *data)
{
  CALBZS_id *id;

  id = (CALBZS_id *) malloc(sizeof(CALBZS_id));

  if (id==NULL)
    {
      data->errorstr = (char *) malloc(64);
      strcpy(data->errorstr,"Malloc returned NULL!");

      return TL_OK-1;
    }

  id->cid = (CALBH_id) data->cid;

  data->result = id;

  return TL_OK;
}

/* calbzsup dispose data function*/
/* return TL_OK iff no error */
int calbzst_tl_dispose(calbzst_t_dispose *data)
{
  free(data->czsid);

  return TL_OK;
}

/* calbzsup load data function*/
/* return TL_OK iff no error */
int calbzst_tl_load(calbzst_t_load *data)
{
  CALBZS_id *id = data->czsid;
  unsigned int i;

  if (!data->range_present)
    {
      data->range.start_bit = 0;
      data->range.end_bit = 4095;
    }

  for (i=data->range.start_bit; i<=data->range.end_bit; i++)
    {
      id->zsup_a[i] = calbh_read_zsup_a(id->cid,i);
      id->zsup_b[i] = calbh_read_zsup_b(id->cid,i);
    }

  return TL_OK;
}

/* calbzsup save data function*/
/* return TL_OK iff no error */
int calbzst_tl_save(calbzst_t_save *data)
{
  CALBZS_id *id = data->czsid;
  int i;

  if (!data->range_present)
    {
      data->range.start_bit = 0;
      data->range.end_bit = 4095;
    }

  for (i=data->range.start_bit; i<=data->range.end_bit; i++)
    {
      calbh_write_zsup_a(id->cid,i,id->zsup_a[i]);
      calbh_write_zsup_b(id->cid,i,id->zsup_b[i]);
    }


  return TL_OK;
}

/* calbzsup getbit data function*/
/* return TL_OK iff no error */
int calbzst_tl_getbit(calbzst_t_getbit *data)
{
  CALBZS_id *id = data->czsid;

  if (data->chanside.nr==CALBZST_Cchanside_A)
    data->result = bits_get_bit(id->zsup_a[data->bitnr],data->channr);
  else
    data->result = bits_get_bit(id->zsup_b[data->bitnr],data->channr);

  return TL_OK;
}

/* calbzsup setbit data function*/
/* return TL_OK iff no error */
int calbzst_tl_setbit(calbzst_t_setbit *data)
{
  CALBZS_id *id = data->czsid;

  if (data->chanside.nr==CALBZST_Cchanside_A)
    id->zsup_a[data->bitnr] = bits_set_bit(id->zsup_a[data->bitnr],data->channr,data->value);
  else
    id->zsup_b[data->bitnr] = bits_set_bit(id->zsup_b[data->bitnr],data->channr,data->value);


  return TL_OK;
}

/* calbzsup setrange data function*/
/* return TL_OK iff no error */
int calbzst_tl_setrange(calbzst_t_setrange *data)
{
  CALBZS_id *id = data->czsid;
  int i;

  if (!data->range_present)
    {
      data->range.start_bit = 0;
      data->range.end_bit = 4095;
    }

  if (data->chanside.nr==CALBZST_Cchanside_A)
    {
      for (i=data->range.start_bit; i<=data->range.end_bit; i++)
	id->zsup_a[i] = bits_set_bit(id->zsup_a[i],data->channr,data->value);
    }
  else
    {
      for (i=data->range.start_bit; i<=data->range.end_bit; i++)
	id->zsup_b[i] = bits_set_bit(id->zsup_b[i],data->channr,data->value);
    }

  return TL_OK;
}

/* calbzsup find data function*/
/* return TL_OK iff no error */
int calbzst_tl_find(calbzst_t_find *data)
{
  CALBZS_id *id = data->czsid;
  int i;
  int bitval;

  if (!data->direction_present)
    data->direction.nr = CALBZST_Cfind_succ;

  if (!data->from_present)
    {
      if (data->direction.nr == CALBZST_Cfind_succ)
	data->from=0;
      else
	data->from=4095;
    }

  if (data->direction.nr == CALBZST_Cfind_succ)
    {
      if (data->chanside.nr==CALBZST_Cchanside_A)
	{
	  for (i=data->from; i<4096; i++)
	    {
	      if (bits_get_bit(id->zsup_a[i],data->channr)==data->value)
		{ /* found */
		  data->result = i;
		  return TL_OK;
		}
	    }
	}
      else
	{
	  for (i=data->from; i<4096; i++)
	    {
	      if (bits_get_bit(id->zsup_b[i],data->channr)==data->value)
		{ /* found */
		  data->result = i;
		  return TL_OK;
		}
	    }
	}
    }
  else
    {
      if (data->chanside.nr==CALBZST_Cchanside_A)
	{
	  for (i=data->from; i>=0; i--)
	    {
	      if (bits_get_bit(id->zsup_a[i],data->channr)==data->value)
		{ /* found */
		  data->result = i;
		  return TL_OK;
		}
	    }
	}
      else
	{
	  for (i=data->from; i>=0; i--)
	    {
	      if (bits_get_bit(id->zsup_b[i],data->channr)==data->value)
		{ /* found */
		  data->result = i;
		  return TL_OK;
		}
	    }
	}
    }

  /* not found */
  data->result = -1;
  return TL_OK;
}