/************************************************************/
/* */
/* File : rockfifo.c */
/* Description : ROCK FIFO specific library */
/* */
/* Author: Sfiligoi Igor */
/* */
/* Comment: If this module is used to manipulate a FIFO, */
/* nobody else should access that FIFO */
/* */
/* Created : 16.06.1997 */
/* Last modified: 20.10.1997 */
/* */
/************************************************************/
#include <stdlib.h>
#include <Error.h>
#include <bits.h>
#include "RockM.h"
#include "rockmfifo.h"
#include "rockmfifo_private.h"
/**********************************************************************/
/* */
/* Initialisation routines */
/* */
/**********************************************************************/
int rockm_fifo_open(ROCKM_id rockm_id, /* IN : standard rockm id */
unsigned char cancache, /* IN : see ROCKM_FIFO_CACHE_... constants */
ROCKM_FIFO_id *fifo_id) /* OUT: fifo id related to the rock */
{
(*fifo_id) = (ROCKM_FIFO_id_base *) malloc(sizeof(ROCKM_FIFO_id_base));
if ((*fifo_id)==NULL)
{ /* malloc error */
ErrorSet(ROCKM_ERROR_UNKNOWN,"rockm_fifo_open","Malloc returned NULL.");
return ROCKM_ERROR_UNKNOWN;
}
(*fifo_id)->rockm_id = rockm_id;
(*fifo_id)->head = 0;
(*fifo_id)->tail = 0;
(*fifo_id)->cancache = ROCKM_FIFO_CACHE_OFF;
return rockm_fifo_set_cancache((*fifo_id),cancache);
}
int rockm_fifo_close(ROCKM_FIFO_id fifo_id, /* IN : fifo id */
ROCKM_FIFO_RAW *cache) /* OUT: the unused cache */
/* should be disposed by caller */
{
cache->nrels=rockm_fifo_cache_get_nrels(fifo_id);
if (cache->nrels!=0)
{
cache->els = (unsigned int *) malloc(cache->nrels*sizeof(unsigned int));
if (cache->els==NULL)
{ /* malloc error */
ErrorSet(ROCKM_ERROR_UNKNOWN,"rockm_fifo_close","Malloc returned NULL.");
return ROCKM_ERROR_UNKNOWN;
}
rockm_fifo_cache_read(fifo_id,cache->nrels,cache->els);
}
else
cache->els = NULL;
free(fifo_id);
return ROCKM_ERROR_OK;
}
/**********************************************************************/
/* */
/* Settings routines */
/* */
/**********************************************************************/
int rockm_fifo_set_cancache(ROCKM_FIFO_id fifo_id, /* IN : fifo id */
unsigned char cancache) /* IN : new cancache value */
{
fifo_id->cancache = cancache;
return ROCKM_ERROR_OK;
}
/**********************************************************************/
/* */
/* Cache routines */
/* */
/**********************************************************************/
int rockm_fifo_cache_flush(ROCKM_FIFO_id fifo_id, /* IN : fifo id */
ROCKM_FIFO_RAW *cache) /* OUT: the unused cache */
/* should be disposed by caller */
{
cache->nrels=rockm_fifo_cache_get_nrels(fifo_id);
if (cache->nrels!=0)
{
cache->els = (unsigned int *) malloc(cache->nrels*sizeof(unsigned int));
if (cache->els==NULL)
{ /* malloc error */
ErrorSet(ROCKM_ERROR_UNKNOWN,"rockm_fifo_cache_flush","Malloc returned NULL.");
return ROCKM_ERROR_UNKNOWN;
}
rockm_fifo_cache_read(fifo_id,cache->nrels,cache->els);
}
else
cache->els = NULL;
return ROCKM_ERROR_OK;
}
/* Very dangerous!!!! */
int rockm_fifo_cache_refill(ROCKM_FIFO_id fifo_id, /* IN : fifo_id */
ROCKM_FIFO_RAW data) /* IN : data to be filled to the cache */
{
return rockm_fifo_cache_return(fifo_id,data.els,data.nrels);
}
/**********************************************************************/
/* */
/* Raw read routines */
/* */
/**********************************************************************/
int rockm_fifo_raw_read(ROCKM_FIFO_id fifo_id, /* IN : fifo id */
unsigned int *data) /* OUT: one FIFO value */
{
int err;
err = rockm_fifo_cache_read(fifo_id,1,data);
if (err==ROCKM_ERROR_OK)
return ROCKM_ERROR_OK; /* was in cache, ok */
err = rockm_fifo_fillcache(fifo_id,1);
if (err==ROCKM_ERROR_OK)
{ /* data is in cache => read from cache */
rockm_fifo_cache_read(fifo_id,1,data);
return ROCKM_ERROR_OK;
}
else if (err==ROCKM_ERROR_FIFO_EMPTY)
return err;
else
{ /* serious error */
ErrorSetF(err,"rockm_fifo_raw_read","rockm_fifo_fillcache error: %s",ErrorGetMessage());
return err;
}
}
int rockm_fifo_raw_blockread(ROCKM_FIFO_id fifo_id, /* IN : fifo id */
unsigned int nrels, /* IN : max number of elements */
ROCKM_FIFO_RAW *data) /* OUT: FIFO data */
/* should be disposed by caller */
{
int csize;
unsigned int *actel; /* point to the first unused space in data->els */
int err;
data->els = (unsigned int *) malloc(nrels*sizeof(unsigned int));
if (data->els==NULL)
{ /* malloc error */
ErrorSet(ROCKM_ERROR_UNKNOWN,"rockm_fifo_raw_blockread","Malloc returned NULL.");
return ROCKM_ERROR_UNKNOWN;
}
actel = data->els;
data->nrels=0;
while (1)
{
csize = rockm_fifo_cache_get_nrels(fifo_id);
if (csize>=nrels)
{ /* all needed elements are in cache */
data->nrels+=nrels;
rockm_fifo_cache_read(fifo_id,nrels,actel);
return ROCKM_ERROR_OK;
}
/* cache has not enough elements */
data->nrels+=csize;
rockm_fifo_cache_read(fifo_id,csize,actel);
/* loop */
nrels-=csize;
err = rockm_fifo_fillcache(fifo_id,nrels);
if (err!=ROCKM_ERROR_OK)
{
if (err!=ROCKM_ERROR_FIFO_EMPTY)
{ /* serious error, exit */
ErrorSetF(err,"rockm_fifo_raw_blockread","rockm_fifo_fillcache error: %s",ErrorGetMessage());
return err;
}
else
{ /* save the elements found and exit*/
csize = rockm_fifo_cache_get_nrels(fifo_id);
data->nrels+=csize;
rockm_fifo_cache_read(fifo_id,csize,actel);
return ROCKM_ERROR_FIFO_EMPTY;
}
}
}
}
/**********************************************************************/
/* */
/* Frame read routines */
/* */
/**********************************************************************/
int rockm_fifo_frame_read(ROCKM_FIFO_id fifo_id, /* IN : fifo id */
ROCKM_FIFO_FRAME *data) /* OUT: one FIFO value */
{
RockM_reg_declaration;
int nrels;
unsigned int rawels[ROCKM_FIFO_FRAME_SIZE];
unsigned int softparity;
unsigned int softparity_fail;
unsigned int trigger_err;
unsigned int last_bits; /* count nr. of bits set on */
unsigned char prec_addr; /* needed to test that addresses go from highest to lower */
unsigned int nrslaves[16]; /* nr of slaves with a address are in the subframe */
int err,whatis;
/* read super header */
err = rockm_fifo_raw_read(fifo_id,&(rawels[0]));
/* exit immediatly if cannot read the super header */
if (err!=ROCKM_ERROR_OK)
if (err==ROCKM_ERROR_FIFO_EMPTY)
return err;
else
{
ErrorSetF(err,"rockm_fifo_frame_read","rockm_fifo_raw_read_bits error: %s",ErrorGetMessage());
return err;
}
whatis= rockm_fifo_whatis(rawels[0]);
if (whatis!=ROCKM_FIFO_IS_SUPER_HEADER)
{ /* error, return element to cache and report error */
rockm_fifo_cache_return(fifo_id,rawels,1);
ErrorSetF(ROCKM_ERROR_FIFO_FRAME_SUPER_HEADER,"rockm_fifo_frame_read","Super header expected.");
return ROCKM_ERROR_FIFO_FRAME_SUPER_HEADER;
}
SUPER_HEADER = rawels[0];
data->header.ring = RING;
data->header.chadd = CHAIN;
data->header.trigger = T_WORD_H;
if (RING==0)
{ /* ring test */
{ /* initialize */
int i;
nrels = 2;
softparity_fail = 0xff; /* for test only */
trigger_err = 0; /* for test only */
last_bits = 0;
for (i=0; i<8; i++)
{
data->subfr[i].ispresent = 0;
}
}
err = rockm_fifo_raw_read(fifo_id,&(rawels[1]));
/* exit if cannot read the FIFO */
if (err!=ROCKM_ERROR_OK)
{ /* error, return elements to cache and report error */
rockm_fifo_cache_return(fifo_id,rawels,2);
if (err!=ROCKM_ERROR_FIFO_EMPTY)
ErrorSetF(err,"rockm_fifo_frame_read","rockm_fifo_raw_read error: %s",ErrorGetMessage());
return err;
}
whatis= rockm_fifo_whatis(rawels[1]);
while (whatis!=ROCKM_FIFO_IS_SUPER_FOOTER)
{ /* loop until end of super-frame */
if (whatis!=ROCKM_FIFO_IS_SLAVE)
{ /* error, return element to cache and report error */
rockm_fifo_cache_return(fifo_id,rawels,nrels);
ErrorSetF(ROCKM_ERROR_FIFO_FRAME_SUB_HEADER,"rockm_fifo_frame_read","Ringtest word expected.");
return ROCKM_ERROR_FIFO_FRAME_SUB_HEADER;
}
SUB_HEADER = rawels[nrels-1];
if (CRT_ADD_h!=CRATE)
{/* error, return element to cache and report error */
rockm_fifo_cache_return(fifo_id,rawels,nrels);
ErrorSetF(ROCKM_ERROR_FIFO_FRAME_SUB_HEADER,"rockm_fifo_frame_read","Crt_add different from crate! (%i,%i).",CRT_ADD_h,CRATE);
return ROCKM_ERROR_FIFO_FRAME_SUB_HEADER;
}
/* test if duplicated and set */
if (data->subfr[CRATE].ispresent!=0)
{/* error, return element to cache and report error */
rockm_fifo_cache_return(fifo_id,rawels,nrels);
ErrorSetF(ROCKM_ERROR_FIFO_FRAME_SUB_HEADER,"rockm_fifo_frame_read","Duplicated crate %i.",CRATE);
return ROCKM_ERROR_FIFO_FRAME_SUB_HEADER;
}
data->subfr[CRATE].ispresent = 1;
if (LAST==0)
{
last_bits++;
}
data->subfr[CRATE].header.last = LAST;
data->subfr[CRATE].header.trigger = T_WORD_h;
{
int i;
for (i=0; i<16; i++)
{
data->subfr[CRATE].slv[i].nrels = 0;
data->subfr[CRATE].slv[i].els = NULL;
}
}
data->subfr[CRATE].footer.softparity = PARITY_h;
data->subfr[CRATE].footer.hardparity = PARITY_h;
/*************************/
/* Prepare for next loop */
/*************************/
err = rockm_fifo_raw_read(fifo_id,&(rawels[nrels]));
nrels++;
/* exit if cannot read the FIFO */
if (err!=ROCKM_ERROR_OK)
{ /* error, return elements to cache and report error */
rockm_fifo_cache_return(fifo_id,rawels,nrels);
if (err!=ROCKM_ERROR_FIFO_EMPTY)
ErrorSetF(err,"rockm_fifo_frame_read","rockm_fifo_raw_read error: %s",ErrorGetMessage());
return err;
}
whatis= rockm_fifo_whatis(rawels[nrels-1]);
}
SUPER_FOOTER = rawels[nrels-1];
data->footer.softparity_fail = softparity_fail;
data->footer.hardparity_fail = ((PARITY_CRATE_7*0x80) +
(PARITY_CRATE_6*0x40) +
(PARITY_CRATE_5*0x20) +
(PARITY_CRATE_4*0x10) +
(PARITY_CRATE_3*0x8) +
(PARITY_CRATE_2*0x4) +
(PARITY_CRATE_1*0x2) +
PARITY_CRATE_0);
data->footer.overflow = OVERFLOW;
data->footer.softcounter = nrels-2;
data->footer.hardcounter = COUNTER;
}
else
{ /* no ring test, standard superframe */
{ /* initialize */
int i;
nrels = 2;
softparity_fail = 0xff; /* no error yet */
trigger_err = 0; /* no error yet */
last_bits = 0;
for (i=0; i<8; i++)
{
data->subfr[i].ispresent = 0;
}
}
err = rockm_fifo_raw_read(fifo_id,&(rawels[1]));
/* exit if cannot read the FIFO */
if (err!=ROCKM_ERROR_OK)
{ /* error, return elements to cache and report error */
rockm_fifo_cache_return(fifo_id,rawels,2);
if (err!=ROCKM_ERROR_FIFO_EMPTY)
ErrorSetF(err,"rockm_fifo_frame_read","rockm_fifo_raw_read error: %s",ErrorGetMessage());
return err;
}
whatis= rockm_fifo_whatis(rawels[1]);
while (whatis!=ROCKM_FIFO_IS_SUPER_FOOTER)
{ /* loop until end of super-frame */
int start_nrels;
start_nrels = nrels;
if (whatis!=ROCKM_FIFO_IS_SUB_HEADER)
{ /* error, return element to cache and report error */
rockm_fifo_cache_return(fifo_id,rawels,nrels);
ErrorSetF(ROCKM_ERROR_FIFO_FRAME_SUB_HEADER,"rockm_fifo_frame_read","Sub header expected.");
return ROCKM_ERROR_FIFO_FRAME_SUB_HEADER;
}
SUB_HEADER = rawels[start_nrels-1];
if (CRT_ADD_h!=CRATE)
{/* error, return element to cache and report error */
rockm_fifo_cache_return(fifo_id,rawels,nrels);
ErrorSetF(ROCKM_ERROR_FIFO_FRAME_SUB_HEADER,"rockm_fifo_frame_read","Crt_add different from crate! (%i,%i).",CRT_ADD_h,CRATE);
return ROCKM_ERROR_FIFO_FRAME_SUB_HEADER;
}
/* test if duplicated and set */
if (data->subfr[CRATE].ispresent!=0)
{/* error, return element to cache and report error */
rockm_fifo_cache_return(fifo_id,rawels,nrels);
ErrorSetF(ROCKM_ERROR_FIFO_FRAME_SUB_HEADER,"rockm_fifo_frame_read","Duplicated crate %i.",CRATE);
return ROCKM_ERROR_FIFO_FRAME_SUB_HEADER;
}
data->subfr[CRATE].ispresent = 1;
if (T_WORD_H!=T_WORD_h)
{
trigger_err = 1;
}
if (LAST==0)
{
last_bits++;
}
/* header data will be saved after the full frame read */
/* Now I have the header, start reading slaves */
prec_addr = 255;
{
int i;
for (i=0; i<16; i++)
nrslaves[i]=0;
}
for (; nrels<ROCKM_FIFO_FRAME_SIZE; nrels++)
{
err = rockm_fifo_raw_read(fifo_id,&(rawels[nrels]));
/* exit if cannot read the FIFO */
if (err!=ROCKM_ERROR_OK)
{ /* error, return elements to cache and report error */
rockm_fifo_cache_return(fifo_id,rawels,nrels);
if (err!=ROCKM_ERROR_FIFO_EMPTY)
ErrorSetF(err,"rockm_fifo_frame_read","rockm_fifo_raw_read error: %s",ErrorGetMessage());
return err;
}
whatis= rockm_fifo_whatis(rawels[nrels]);
if (whatis==ROCKM_FIFO_IS_SUB_FOOTER)
break; /* exit from loop and elaborate footer */
else if (whatis==ROCKM_FIFO_IS_SUPER_FOOTER)
{ /* error, return elements to cache and report error */
rockm_fifo_cache_return(fifo_id,rawels,nrels+1);
ErrorSetF(ROCKM_ERROR_FIFO_FRAME_SUPER_FOOTER,"rockm_fifo_frame_read","A super footer before a sub footer found.");
return ROCKM_ERROR_FIFO_FRAME_SUPER_FOOTER;
}
else if (whatis!=ROCKM_FIFO_IS_SLAVE)
{ /* error, return elements to cache and report error */
rockm_fifo_cache_return(fifo_id,rawels,nrels+1);
ErrorSetF(ROCKM_ERROR_FIFO_FRAME_SLAVE,"rockm_fifo_frame_read","Invalid type found: %i (slave expected).",whatis);
return ROCKM_ERROR_FIFO_FRAME_SLAVE;
}
/* interpret the slave */
DATA_HEADER = rawels[nrels];
if (CRT_ADD_D!=CRT_ADD_h)
{ /* error, return elements to cache and report error */
rockm_fifo_cache_return(fifo_id,rawels,nrels+1);
ErrorSetF(ROCKM_ERROR_FIFO_FRAME_SLAVE,"rockm_fifo_frame_read","Crate address different from subheader.");
return ROCKM_ERROR_FIFO_FRAME_SLAVE;
}
if (SLV_ADD>prec_addr)
{ /* error, return elements to cache and report error */
rockm_fifo_cache_return(fifo_id,rawels,nrels+1);
ErrorSetF(ROCKM_ERROR_FIFO_FRAME_SLAVE,"rockm_fifo_frame_read","Slave addresses not in decreasing order.");
return ROCKM_ERROR_FIFO_FRAME_SLAVE;
}
prec_addr = SLV_ADD;
nrslaves[SLV_ADD]++;
/* data will be saved after the full frame read */
}
if (nrels>=ROCKM_FIFO_FRAME_SIZE)
{ /* error, return elements to cache and report error */
rockm_fifo_cache_return(fifo_id,rawels,ROCKM_FIFO_FRAME_SIZE);
ErrorSetF(ROCKM_ERROR_FIFO_FRAME_OVERFLOW,"rockm_fifo_frame_read","Frame too large.");
return ROCKM_ERROR_FIFO_FRAME_OVERFLOW;
}
SUB_FOOTER = rawels[nrels];
if (CRT_ADD_f!=CRT_ADD_h)
{ /* error, return elements to cache and report error */
rockm_fifo_cache_return(fifo_id,rawels,nrels+1);
ErrorSetF(ROCKM_ERROR_FIFO_FRAME_SUB_FOOTER,"rockm_fifo_frame_read","Subframe address different from subheader.");
return ROCKM_ERROR_FIFO_FRAME_SUB_FOOTER;
}
nrels++;
if ((nrels-start_nrels)==1)
{ /* a sub header followed by a sub footer not allowed */
rockm_fifo_cache_return(fifo_id,rawels,nrels);
ErrorSetF(ROCKM_ERROR_FIFO_FRAME_SUB_FOOTER,"rockm_fifo_frame_read","Subfooter immediatly after subheader.");
return ROCKM_ERROR_FIFO_FRAME_SUB_FOOTER;
}
/* set the header */
{
data->subfr[CRATE].header.last = LAST;
data->subfr[CRATE].header.trigger = T_WORD_h;
softparity = PARITY_h;
}
/* set the slaves */
{
int i;
/* allocate space */
for (i=0; i<16; i++)
{
data->subfr[CRATE].slv[i].nrels = 0;
if (nrslaves[i]!=0)
{
data->subfr[CRATE].slv[i].els = (ROCKM_FIFO_SLV_data *) malloc(nrslaves[i]*sizeof(ROCKM_FIFO_SLV_data));
if (data->subfr[CRATE].slv[i].els==NULL)
{ /* malloc error */
ErrorSet(ROCKM_ERROR_UNKNOWN,"rockm_fifo_frame_read","Malloc returned NULL.");
return ROCKM_ERROR_UNKNOWN;
}
}
else
data->subfr[CRATE].slv[i].els = NULL;
}
/* save data */
for (i=start_nrels; i<(nrels-1); i++)
{
int a_nrels;
ROCKM_FIFO_SLV_data *a_el; /* element to write in */
DATA_HEADER = rawels[i];
a_nrels = data->subfr[CRATE].slv[SLV_ADD].nrels++;
a_el = &(data->subfr[CRATE].slv[SLV_ADD].els[a_nrels]);
a_el->channel = CHAIN_DATA;
a_el->reserved = RSV;
a_el->data = SLAVE_DATA;
softparity ^= PARITY_D;
}
}
/*Set footer */
{
SUB_FOOTER = rawels[nrels-1];
data->subfr[CRATE].footer.hardparity = PARITY_f;
data->subfr[CRATE].footer.softparity = softparity;
if (PARITY_f!=softparity)
softparity_fail = bits_set_bit(softparity_fail,CRATE,0);
}
/*************************/
/* Prepare for next loop */
/*************************/
err = rockm_fifo_raw_read(fifo_id,&(rawels[nrels]));
nrels++;
/* exit if cannot read the FIFO */
if (err!=ROCKM_ERROR_OK)
{ /* error, return elements to cache and report error */
rockm_fifo_cache_return(fifo_id,rawels,nrels);
if (err!=ROCKM_ERROR_FIFO_EMPTY)
ErrorSetF(err,"rockm_fifo_frame_read","rockm_fifo_raw_read error: %s",ErrorGetMessage());
return err;
}
whatis= rockm_fifo_whatis(rawels[nrels-1]);
}
SUPER_FOOTER = rawels[nrels-1];
data->footer.softparity_fail = softparity_fail;
data->footer.hardparity_fail = ((PARITY_CRATE_7*0x80) +
(PARITY_CRATE_6*0x40) +
(PARITY_CRATE_5*0x20) +
(PARITY_CRATE_4*0x10) +
(PARITY_CRATE_3*0x8) +
(PARITY_CRATE_2*0x4) +
(PARITY_CRATE_1*0x2) +
PARITY_CRATE_0);
data->footer.overflow = OVERFLOW;
data->footer.softcounter = nrels-2;
data->footer.hardcounter = COUNTER;
} /* end if RING */
if (data->footer.hardparity_fail!=data->footer.softparity_fail)
{ /* report error, but do return the frame */
ErrorSetF(ROCKM_ERROR_FIFO_FRAME_PARITY,"rockm_fifo_frame_read","Parity fail error: hard %i soft %i.",
data->footer.hardparity_fail,data->footer.softparity_fail);
return ROCKM_ERROR_FIFO_FRAME_PARITY;
}
if (data->footer.hardparity_fail!=0xff)
{ /* report error, but do return the frame */
char tmp[128];
int i;
strcpy(tmp,"");
if (data->subfr[7].ispresent)
{
char tmp1[32];
sprintf(tmp1," 7: %i",PARITY_CRATE_7);
strcat(tmp,tmp1);
}
if (data->subfr[6].ispresent)
{
char tmp1[32];
sprintf(tmp1," 6: %i",PARITY_CRATE_6);
strcat(tmp,tmp1);
}
if (data->subfr[5].ispresent)
{
char tmp1[32];
sprintf(tmp1," 5: %i",PARITY_CRATE_5);
strcat(tmp,tmp1);
}
if (data->subfr[4].ispresent)
{
char tmp1[32];
sprintf(tmp1," 4: %i",PARITY_CRATE_4);
strcat(tmp,tmp1);
}
if (data->subfr[3].ispresent)
{
char tmp1[32];
sprintf(tmp1," 3: %i",PARITY_CRATE_3);
strcat(tmp,tmp1);
}
if (data->subfr[2].ispresent)
{
char tmp1[32];
sprintf(tmp1," 2: %i",PARITY_CRATE_2);
strcat(tmp,tmp1);
}
if (data->subfr[1].ispresent)
{
char tmp1[32];
sprintf(tmp1," 1: %i",PARITY_CRATE_1);
strcat(tmp,tmp1);
}
if (data->subfr[0].ispresent)
{
char tmp1[32];
sprintf(tmp1," 0: %i",PARITY_CRATE_0);
strcat(tmp,tmp1);
}
ErrorSetF(ROCKM_ERROR_FIFO_FRAME_PARITY,"rockm_fifo_frame_read",
"Hard parity error: (%s).",tmp);
return ROCKM_ERROR_FIFO_FRAME_PARITY;
}
if (data->footer.overflow==0)
{ /* report error, but do return the frame */
ErrorSetF(ROCKM_ERROR_FIFO_FRAME_COUNTER,"rockm_fifo_frame_read","Counter overflow!.");
return ROCKM_ERROR_FIFO_FRAME_COUNTER;
}
if (data->footer.hardcounter!=data->footer.softcounter)
{ /* report error, but do return the frame */
ErrorSetF(ROCKM_ERROR_FIFO_FRAME_COUNTER,"rockm_fifo_frame_read","Counter error: hard %i soft %i.",
data->footer.hardcounter,data->footer.softcounter);
return ROCKM_ERROR_FIFO_FRAME_COUNTER;
}
if (trigger_err)
{/* report error, but do return the frame */
ErrorSetF(ROCKM_ERROR_FIFO_FRAME_TRIGGER,"rockm_fifo_frame_read","Trigger word error.");
return ROCKM_ERROR_FIFO_FRAME_TRIGGER;
}
if (last_bits>1)
{/* report error, but do return the frame */
ErrorSetF(ROCKM_ERROR_FIFO_FRAME_LAST,"rockm_fifo_frame_read","Last bit error.");
return ROCKM_ERROR_FIFO_FRAME_LAST;
}
return ROCKM_ERROR_OK;
}
/* non fatal errors are not considered */
int rockm_fifo_frame_blockread(ROCKM_FIFO_id fifo_id, /* IN : fifo id */
unsigned int nrels, /* IN : max number of raw elements */
ROCKM_FIFO_FRAMEs *data) /* OUT: FIFO data */
/* should be disposed by caller */
{
int i;
int err;
if (nrels==0)
{ /* nothing to do */
data->nrframes = 0;
data->frames = NULL;
return ROCKM_ERROR_OK;
}
/* alloc space for the worst case */
data->frames = (ROCKM_FIFO_FRAME *) malloc(nrels*sizeof(ROCKM_FIFO_FRAME));
if (data->frames==NULL)
{ /* malloc error */
ErrorSet(ROCKM_ERROR_UNKNOWN,"rockm_fifo_frame_blockread","Malloc returned NULL.");
return ROCKM_ERROR_UNKNOWN;
}
for (i=0; i<nrels; i++)
{
err = rockm_fifo_frame_read(fifo_id,&(data->frames[i]));
if ((err!=ROCKM_ERROR_OK)&&
(err!=ROCKM_ERROR_FIFO_FRAME_PARITY)&&
(err!=ROCKM_ERROR_FIFO_FRAME_TRIGGER)&&
(err!=ROCKM_ERROR_FIFO_FRAME_LAST)&&
(err!=ROCKM_ERROR_FIFO_FRAME_COUNTER))
{
if (err==ROCKM_ERROR_FIFO_EMPTY)
break;
else
{ /* a serious error occured, exit */
ErrorSetF(err,"rockm_fifo_frame_blockread","rockm_fifo_frame_read error: %s",ErrorGetMessage());
data->nrframes=i;
return err;
}
}
ErrorClear(); /* clean any old error */
}
data->nrframes=i;
if (data->nrframes<nrels)
return ROCKM_ERROR_FIFO_EMPTY;
else
return ROCKM_ERROR_OK;
}
int rockm_fifo_frame_rawread(ROCKM_FIFO_id fifo_id, /* IN : fifo id */
ROCKM_FIFO_RAW *data) /* OUT: one FIFO value */
/* should be disposed by caller */
{
RockM_reg_declaration;
int nrels;
unsigned char subfr[8];
unsigned int rawels[ROCKM_FIFO_FRAME_SIZE];
unsigned int softparity;
unsigned int softparity_fail;
unsigned int hardparity_fail;
unsigned int trigger_err;
unsigned int last_bits; /* count nr. of bits set on */
unsigned char prec_addr; /* needed to test that addresses go from highest to lower */
unsigned int nrslaves[16]; /* nr of slaves with a address are in the subframe */
int err,whatis;
/* read super header */
err = rockm_fifo_raw_read(fifo_id,&(rawels[0]));
/* exit immediatly if cannot read the super header */
if (err!=ROCKM_ERROR_OK)
if (err==ROCKM_ERROR_FIFO_EMPTY)
return err;
else
{
ErrorSetF(err,"rockm_fifo_frame_rawread","rockm_fifo_raw_read error: %s",ErrorGetMessage());
return err;
}
whatis= rockm_fifo_whatis(rawels[0]);
if (whatis!=ROCKM_FIFO_IS_SUPER_HEADER)
{ /* error, return element to cache and report error */
rockm_fifo_cache_return(fifo_id,rawels,1);
ErrorSetF(ROCKM_ERROR_FIFO_FRAME_SUPER_HEADER,"rockm_fifo_frame_rawread","Super header expected.");
return ROCKM_ERROR_FIFO_FRAME_SUPER_HEADER;
}
SUPER_HEADER = rawels[0];
if (RING==0)
{ /* ring test */
{ /* initialize */
int i;
nrels = 2;
softparity_fail = 0xff; /* no error yet */
trigger_err = 0; /* for test only */
last_bits = 0;
for (i=0; i<8; i++)
subfr[i]=0;
}
err = rockm_fifo_raw_read(fifo_id,&(rawels[1]));
/* exit if cannot read the FIFO */
if (err!=ROCKM_ERROR_OK)
{ /* error, return elements to cache and report error */
rockm_fifo_cache_return(fifo_id,rawels,2);
if (err!=ROCKM_ERROR_FIFO_EMPTY)
ErrorSetF(err,"rockm_fifo_frame_rawread","rockm_fifo_raw_read error: %s",ErrorGetMessage());
return err;
}
whatis= rockm_fifo_whatis(rawels[1]);
while (whatis!=ROCKM_FIFO_IS_SUPER_FOOTER)
{ /* loop until end of super-frame */
if (whatis!=ROCKM_FIFO_IS_SLAVE)
{ /* error, return element to cache and report error */
rockm_fifo_cache_return(fifo_id,rawels,nrels);
ErrorSetF(ROCKM_ERROR_FIFO_FRAME_SUB_HEADER,"rockm_fifo_frame_rawread","Ringtest word expected.");
return ROCKM_ERROR_FIFO_FRAME_SUB_HEADER;
}
SUB_HEADER = rawels[nrels-1];
if (CRT_ADD_h!=CRATE)
{/* error, return element to cache and report error */
rockm_fifo_cache_return(fifo_id,rawels,nrels);
ErrorSetF(ROCKM_ERROR_FIFO_FRAME_SUB_HEADER,"rockm_fifo_frame_rawread","Crt_add different from crate! (%i,%i).",CRT_ADD_h,CRATE);
return ROCKM_ERROR_FIFO_FRAME_SUB_HEADER;
}
/* test if duplicated and set */
if (subfr[CRATE]!=0)
{/* error, return element to cache and report error */
rockm_fifo_cache_return(fifo_id,rawels,nrels);
ErrorSetF(ROCKM_ERROR_FIFO_FRAME_SUB_HEADER,"rockm_fifo_frame_rawread","Duplicated crate %i.",CRATE);
return ROCKM_ERROR_FIFO_FRAME_SUB_HEADER;
}
subfr[CRATE] = 1;
if (LAST==0)
{
last_bits++;
}
/*************************/
/* Prepare for next loop */
/*************************/
err = rockm_fifo_raw_read(fifo_id,&(rawels[nrels]));
nrels++;
/* exit if cannot read the FIFO */
if (err!=ROCKM_ERROR_OK)
{ /* error, return elements to cache and report error */
rockm_fifo_cache_return(fifo_id,rawels,nrels);
if (err!=ROCKM_ERROR_FIFO_EMPTY)
ErrorSetF(err,"rockm_fifo_frame_rawread","rockm_fifo_raw_read error: %s",ErrorGetMessage());
return err;
}
whatis= rockm_fifo_whatis(rawels[nrels-1]);
}
SUPER_FOOTER = rawels[nrels-1];
hardparity_fail = ((PARITY_CRATE_7*0x80) +
(PARITY_CRATE_6*0x40) +
(PARITY_CRATE_5*0x20) +
(PARITY_CRATE_4*0x10) +
(PARITY_CRATE_3*0x8) +
(PARITY_CRATE_2*0x4) +
(PARITY_CRATE_1*0x2) +
PARITY_CRATE_0);
}
else
{ /* no ring test, standard superframe */
{ /* initialize */
int i;
nrels = 2;
softparity_fail = 0xff; /* no error yet */
trigger_err = 0; /* no error yet */
last_bits = 0;
for (i=0; i<8; i++)
subfr[i]=0;
}
err = rockm_fifo_raw_read(fifo_id,&(rawels[1]));
/* exit if cannot read the FIFO */
if (err!=ROCKM_ERROR_OK)
{ /* error, return elements to cache and report error */
rockm_fifo_cache_return(fifo_id,rawels,2);
if (err!=ROCKM_ERROR_FIFO_EMPTY)
ErrorSetF(err,"rockm_fifo_frame_rawread","rockm_fifo_raw_read error: %s",ErrorGetMessage());
return err;
}
whatis= rockm_fifo_whatis(rawels[1]);
while (whatis!=ROCKM_FIFO_IS_SUPER_FOOTER)
{ /* loop until end of super-frame */
int start_nrels;
start_nrels = nrels;
if (whatis!=ROCKM_FIFO_IS_SUB_HEADER)
{ /* error, return element to cache and report error */
rockm_fifo_cache_return(fifo_id,rawels,nrels);
ErrorSetF(ROCKM_ERROR_FIFO_FRAME_SUB_HEADER,"rockm_fifo_frame_rawread","Sub header expected.");
return ROCKM_ERROR_FIFO_FRAME_SUB_HEADER;
}
SUB_HEADER = rawels[start_nrels-1];
if (CRT_ADD_h!=CRATE)
{/* error, return element to cache and report error */
rockm_fifo_cache_return(fifo_id,rawels,nrels);
ErrorSetF(ROCKM_ERROR_FIFO_FRAME_SUB_HEADER,"rockm_fifo_frame_rawread","Crt_add different from crate! (%i,%i).",CRT_ADD_h,CRATE);
return ROCKM_ERROR_FIFO_FRAME_SUB_HEADER;
}
/* test if duplicated and set */
if (subfr[CRATE]!=0)
{/* error, return element to cache and report error */
rockm_fifo_cache_return(fifo_id,rawels,nrels);
ErrorSetF(ROCKM_ERROR_FIFO_FRAME_SUB_HEADER,"rockm_fifo_frame_rawread","Duplicated crate %i.",CRATE);
return ROCKM_ERROR_FIFO_FRAME_SUB_HEADER;
}
subfr[CRATE] = 1;
if (T_WORD_H!=T_WORD_h)
{
trigger_err = 1;
}
if (LAST==0)
{
last_bits++;
}
/* header data will be saved after the full frame read */
/* Now I have the header, start reading slaves */
prec_addr = 255;
{
int i;
for (i=0; i<16; i++)
nrslaves[i]=0;
}
for (; nrels<ROCKM_FIFO_FRAME_SIZE; nrels++)
{
err = rockm_fifo_raw_read(fifo_id,&(rawels[nrels]));
/* exit if cannot read the FIFO */
if (err!=ROCKM_ERROR_OK)
{ /* error, return elements to cache and report error */
rockm_fifo_cache_return(fifo_id,rawels,nrels);
if (err!=ROCKM_ERROR_FIFO_EMPTY)
ErrorSetF(err,"rockm_fifo_frame_rawread","rockm_fifo_raw_read error: %s",ErrorGetMessage());
return err;
}
whatis= rockm_fifo_whatis(rawels[nrels]);
if (whatis==ROCKM_FIFO_IS_SUB_FOOTER)
break; /* exit from loop and elaborate footer */
else if (whatis==ROCKM_FIFO_IS_SUPER_FOOTER)
{ /* error, return elements to cache and report error */
rockm_fifo_cache_return(fifo_id,rawels,nrels+1);
ErrorSetF(ROCKM_ERROR_FIFO_FRAME_SUPER_FOOTER,"rockm_fifo_frame_rawread","A super footer before a sub footer found.");
return ROCKM_ERROR_FIFO_FRAME_SUPER_FOOTER;
}
else if (whatis!=ROCKM_FIFO_IS_SLAVE)
{ /* error, return elements to cache and report error */
rockm_fifo_cache_return(fifo_id,rawels,nrels+1);
ErrorSetF(ROCKM_ERROR_FIFO_FRAME_SLAVE,"rockm_fifo_frame_rawread","Invalid type found: %i (slave expected).",whatis);
return ROCKM_ERROR_FIFO_FRAME_SLAVE;
}
/* interpret the slave */
DATA_HEADER = rawels[nrels];
if (CRT_ADD_D!=CRT_ADD_h)
{ /* error, return elements to cache and report error */
rockm_fifo_cache_return(fifo_id,rawels,nrels+1);
ErrorSetF(ROCKM_ERROR_FIFO_FRAME_SLAVE,"rockm_fifo_frame_rawread","Crate address different from subheader.");
return ROCKM_ERROR_FIFO_FRAME_SLAVE;
}
if (SLV_ADD>prec_addr)
{ /* error, return elements to cache and report error */
rockm_fifo_cache_return(fifo_id,rawels,nrels+1);
ErrorSetF(ROCKM_ERROR_FIFO_FRAME_SLAVE,"rockm_fifo_frame_rawread","Slave addresses not in decreasing order.");
return ROCKM_ERROR_FIFO_FRAME_SLAVE;
}
prec_addr = SLV_ADD;
nrslaves[SLV_ADD]++;
}
if (nrels>=ROCKM_FIFO_FRAME_SIZE)
{ /* error, return elements to cache and report error */
rockm_fifo_cache_return(fifo_id,rawels,ROCKM_FIFO_FRAME_SIZE);
ErrorSetF(ROCKM_ERROR_FIFO_FRAME_OVERFLOW,"rockm_fifo_frame_rawread","Frame too large.");
return ROCKM_ERROR_FIFO_FRAME_OVERFLOW;
}
SUB_FOOTER = rawels[nrels];
if (CRT_ADD_f!=CRT_ADD_h)
{ /* error, return elements to cache and report error */
rockm_fifo_cache_return(fifo_id,rawels,nrels+1);
ErrorSetF(ROCKM_ERROR_FIFO_FRAME_SUB_FOOTER,"rockm_fifo_frame_rawread","Subframe address different from subheader.");
return ROCKM_ERROR_FIFO_FRAME_SUB_FOOTER;
}
nrels++;
if ((nrels-start_nrels)==1)
{ /* a sub header followed by a sub footer not allowed */
rockm_fifo_cache_return(fifo_id,rawels,nrels);
ErrorSetF(ROCKM_ERROR_FIFO_FRAME_SUB_FOOTER,"rockm_fifo_frame_rawread","Subfooter immediatly after subheader.");
return ROCKM_ERROR_FIFO_FRAME_SUB_FOOTER;
}
/* set the header */
{
softparity = PARITY_h;
}
/* set the slaves */
{
int i;
/* save data */
for (i=start_nrels; i<(nrels-1); i++)
{
DATA_HEADER = rawels[i];
softparity ^= PARITY_D;
}
}
/*Set footer */
{
SUB_FOOTER = rawels[nrels-1];
if (PARITY_f!=softparity)
softparity_fail = bits_set_bit(softparity_fail,CRATE,0);
}
/*************************/
/* Prepare for next loop */
/*************************/
err = rockm_fifo_raw_read(fifo_id,&(rawels[nrels]));
nrels++;
/* exit if cannot read the FIFO */
if (err!=ROCKM_ERROR_OK)
{ /* error, return elements to cache and report error */
rockm_fifo_cache_return(fifo_id,rawels,nrels);
if (err!=ROCKM_ERROR_FIFO_EMPTY)
ErrorSetF(err,"rockm_fifo_frame_rawread","rockm_fifo_raw_read error: %s",ErrorGetMessage());
return err;
}
whatis= rockm_fifo_whatis(rawels[nrels-1]);
}
SUPER_FOOTER = rawels[nrels-1];
hardparity_fail = ((PARITY_CRATE_7*0x80) +
(PARITY_CRATE_6*0x40) +
(PARITY_CRATE_5*0x20) +
(PARITY_CRATE_4*0x10) +
(PARITY_CRATE_3*0x8) +
(PARITY_CRATE_2*0x4) +
(PARITY_CRATE_1*0x2) +
PARITY_CRATE_0);
}
/* copy the buffer */
data->nrels = nrels;
data->els = (unsigned int *) malloc(nrels*sizeof(unsigned int));
if (data->els==NULL)
{ /* malloc error */
ErrorSet(ROCKM_ERROR_UNKNOWN,"rockm_fifo_frame_rawread","Malloc returned NULL.");
return ROCKM_ERROR_UNKNOWN;
}
memcpy(data->els,rawels,nrels*sizeof(unsigned int));
/* check errors */
if (hardparity_fail!=softparity_fail)
{ /* report error, but do return the frame */
ErrorSetF(ROCKM_ERROR_FIFO_FRAME_PARITY,"rockm_fifo_frame_rawread","Parity fail error: hard %i soft %i.",
hardparity_fail,softparity_fail);
return ROCKM_ERROR_FIFO_FRAME_PARITY;
}
if (hardparity_fail!=0xff)
{ /* report error, but do return the frame */
char tmp[128];
int i;
strcpy(tmp,"");
if (subfr[7])
{
char tmp1[32];
sprintf(tmp1," 7: %i",PARITY_CRATE_7);
strcat(tmp,tmp1);
}
if (subfr[6])
{
char tmp1[32];
sprintf(tmp1," 6: %i",PARITY_CRATE_6);
strcat(tmp,tmp1);
}
if (subfr[5])
{
char tmp1[32];
sprintf(tmp1," 5: %i",PARITY_CRATE_5);
strcat(tmp,tmp1);
}
if (subfr[4])
{
char tmp1[32];
sprintf(tmp1," 4: %i",PARITY_CRATE_4);
strcat(tmp,tmp1);
}
if (subfr[3])
{
char tmp1[32];
sprintf(tmp1," 3: %i",PARITY_CRATE_3);
strcat(tmp,tmp1);
}
if (subfr[2])
{
char tmp1[32];
sprintf(tmp1," 2: %i",PARITY_CRATE_2);
strcat(tmp,tmp1);
}
if (subfr[1])
{
char tmp1[32];
sprintf(tmp1," 1: %i",PARITY_CRATE_1);
strcat(tmp,tmp1);
}
if (subfr[0])
{
char tmp1[32];
sprintf(tmp1," 0: %i",PARITY_CRATE_0);
strcat(tmp,tmp1);
}
ErrorSetF(ROCKM_ERROR_FIFO_FRAME_PARITY,"rockm_fifo_frame_rawread",
"Hard parity error: (%s).",tmp);
return ROCKM_ERROR_FIFO_FRAME_PARITY;
}
if (OVERFLOW==0)
{ /* report error, but do return the frame */
ErrorSetF(ROCKM_ERROR_FIFO_FRAME_COUNTER,"rockm_fifo_frame_rawread","Counter overflow!.");
return ROCKM_ERROR_FIFO_FRAME_COUNTER;
}
if (COUNTER!=(nrels-2))
{ /* report error, but do return the frame */
ErrorSetF(ROCKM_ERROR_FIFO_FRAME_COUNTER,"rockm_fifo_frame_rawread","Counter error: hard %i soft %i.",
COUNTER,(nrels-2));
return ROCKM_ERROR_FIFO_FRAME_COUNTER;
}
if (trigger_err)
{/* report error, but do return the frame */
ErrorSetF(ROCKM_ERROR_FIFO_FRAME_TRIGGER,"rockm_fifo_frame_rawread","Trigger word error.");
return ROCKM_ERROR_FIFO_FRAME_TRIGGER;
}
if (last_bits>1)
{/* report error, but do return the frame */
ErrorSetF(ROCKM_ERROR_FIFO_FRAME_LAST,"rockm_fifo_frame_rawread","Last bit error.");
return ROCKM_ERROR_FIFO_FRAME_LAST;
}
return ROCKM_ERROR_OK;
}
/* block of data allocated each time */
#define ROCKM_FIFO_FS_BLOCK 1024
/* Synch the FIFO to the start of the frame */
int rockm_fifo_frame_synch(ROCKM_FIFO_id fifo_id, /* IN : fifo id */
ROCKM_FIFO_RAW *data) /* OUT: FIFO data */
/* should be disposed by caller */
{
int err;
int actblock; /* actual size of the buffer */
data->nrels = 0;
actblock = ROCKM_FIFO_FS_BLOCK;
data->els = (unsigned int *) malloc(actblock*sizeof(unsigned int));
if (data->els==NULL)
{ /* malloc error */
ErrorSet(ROCKM_ERROR_UNKNOWN,"rockm_fifo_frame_synch","Malloc returned NULL.");
return ROCKM_ERROR_UNKNOWN;
}
/* read the first element without checking the type */
err = rockm_fifo_raw_read(fifo_id,&(data->els[data->nrels]));
if (err!=ROCKM_ERROR_OK)
{
if (err!=ROCKM_ERROR_FIFO_EMPTY)
{ /* serious error */
ErrorSetF(err,"rockm_fifo_frame_synch","rockm_fifo_raw_read error: %s",ErrorGetMessage());
return err;
}
else
return ROCKM_ERROR_FIFO_EMPTY;
}
data->nrels++;
while (1)
{
int whatis;
err = rockm_fifo_raw_read(fifo_id,&(data->els[data->nrels]));
if (err!=ROCKM_ERROR_OK)
{
if (err!=ROCKM_ERROR_FIFO_EMPTY)
{ /* serious error */
ErrorSetF(err,"rockm_fifo_frame_synch","rockm_fifo_raw_read error: %s",ErrorGetMessage());
return err;
}
else
return ROCKM_ERROR_FIFO_EMPTY;
}
whatis = rockm_fifo_whatis(data->els[data->nrels]);
if (whatis==ROCKM_FIFO_IS_SUPER_HEADER)
{ /* found, return to cache and exit */
rockm_fifo_cache_return(fifo_id,&(data->els[data->nrels]),1);
return ROCKM_ERROR_OK;
}
/* not yet syncronised */
data->nrels++;
if (data->nrels>=actblock)
{ /* must resize the buffer */
actblock += ROCKM_FIFO_FS_BLOCK;
data->els = (unsigned int *) realloc(data->els,actblock*sizeof(unsigned int));
if (data->els==NULL)
{ /* realloc error */
ErrorSet(ROCKM_ERROR_UNKNOWN,"rockm_fifo_frame_synch","Realloc returned NULL.");
return ROCKM_ERROR_UNKNOWN;
}
}
}
}
/**********************************************************************/
/* */
/* FIFO test routines */
/* */
/**********************************************************************/
int rockm_fifo_isnotempty(ROCKM_FIFO_id fifo_id) /* IN : fifo id */
{
RockM_reg_declaration;
if (rockm_fifo_cache_get_nrels(fifo_id)!=0)
{ /* if data is in cache, not empty */
return ROCKM_ERROR_OK;
}
if (RockM_get_d_e(fifo_id->rockm_id)==0)
return ROCKM_ERROR_FIFO_EMPTY;
else
return ROCKM_ERROR_OK;
}
/**********************************************************************/
/* */
/* Frame conversion routines */
/* */
/**********************************************************************/
int rockm_fifo_conv_frame2raw(ROCKM_FIFO_FRAME indata, /* IN : formatted data */
ROCKM_FIFO_RAW *outdata) /* OUT: raw data */
{
RockM_reg_declaration;
int actel;
/* not empty */
outdata->nrels = indata.footer.hardcounter+2;
outdata->els = (unsigned int *) malloc(outdata->nrels*sizeof(unsigned int));
if (outdata->els==NULL)
{ /* malloc error */
ErrorSet(ROCKM_ERROR_UNKNOWN,"rockm_fifo_conv_frame2raw","Malloc returned NULL.");
return ROCKM_ERROR_UNKNOWN;
}
{ /* convert superheader */
SUPER_HEADER = 0xE00000;
TYPE_H = 1;
RING = indata.header.ring;
CHAIN = indata.header.chadd;
T_WORD_H = indata.header.trigger;
outdata->els[0] = SUPER_HEADER;
}
actel=1;
if (indata.header.ring==0)
{ /* convert ring test */
int subfrnr;
for (subfrnr=7; subfrnr>=0; subfrnr--)
if (indata.subfr[subfrnr].ispresent)
{
SUB_HEADER = 0x40000;
TYPE_h = 7;
CRT_ADD_h = subfrnr;
CRATE = subfrnr;
LAST = indata.subfr[subfrnr].header.last;
T_WORD_h = indata.subfr[subfrnr].header.trigger;
outdata->els[actel] = SUB_HEADER;
actel++;
}
}
else
{ /* convert subframes */
int subfrnr;
for (subfrnr=7; subfrnr>=0; subfrnr--)
if (indata.subfr[subfrnr].ispresent)
{
{ /* convert subheader */
SUB_HEADER = 0x40000;
TYPE_h = 5;
CRT_ADD_h = subfrnr;
CRATE = subfrnr;
LAST = indata.subfr[subfrnr].header.last;
T_WORD_h = indata.subfr[subfrnr].header.trigger;
outdata->els[actel] = SUB_HEADER;
actel++;
}
{ /* convert slaves */
int slvnr;
for (slvnr=15; slvnr>=0; slvnr--)
{
int i;
for (i=0; i<indata.subfr[subfrnr].slv[slvnr].nrels; i++)
{
DATA_HEADER = 0;
TYPE_D = 7;
SLV_ADD = slvnr;
CRT_ADD_D = subfrnr;
CHAIN_DATA = indata.subfr[subfrnr].slv[slvnr].els[i].channel;
RSV = indata.subfr[subfrnr].slv[slvnr].els[i].reserved;
SLAVE_DATA = indata.subfr[subfrnr].slv[slvnr].els[i].data;
outdata->els[actel] = DATA_HEADER;
actel++;
}
}
}
{ /* convert subfooter */
SUB_FOOTER = 0;
TYPE_f = 6;
CRT_ADD_f = subfrnr;
PARITY_f = indata.subfr[subfrnr].footer.hardparity;
outdata->els[actel] = SUB_FOOTER;
actel++;
}
}
} /* end if RING */
{ /* convert super footer */
SUPER_FOOTER = 0;
TYPE_F = 2;
OVERFLOW = indata.footer.overflow;
COUNTER = indata.footer.hardcounter;
PARITY_CRATE_0 = bits_get_bit(indata.footer.hardparity_fail,0);
PARITY_CRATE_1 = bits_get_bit(indata.footer.hardparity_fail,1);
PARITY_CRATE_2 = bits_get_bit(indata.footer.hardparity_fail,2);
PARITY_CRATE_3 = bits_get_bit(indata.footer.hardparity_fail,3);
PARITY_CRATE_4 = bits_get_bit(indata.footer.hardparity_fail,4);
PARITY_CRATE_5 = bits_get_bit(indata.footer.hardparity_fail,5);
PARITY_CRATE_6 = bits_get_bit(indata.footer.hardparity_fail,6);
PARITY_CRATE_7 = bits_get_bit(indata.footer.hardparity_fail,7);
outdata->els[actel] = SUPER_FOOTER;
actel++;
}
return ROCKM_ERROR_OK;
}
int rockm_fifo_conv_raw2frame(ROCKM_FIFO_RAW indata, /* IN : raw data */
ROCKM_FIFO_FRAME *outdata) /* OUT: formated data */
{
RockM_reg_declaration;
int nrels;
unsigned int *rawels = indata.els;
unsigned int softparity;
unsigned int softparity_fail;
unsigned int trigger_err;
unsigned int last_bits; /* count nr. of bits set on */
unsigned char prec_addr; /* needed to test that addresses go from highest to lower */
unsigned int nrslaves[16]; /* nr of slaves with a address are in the subframe */
int err,whatis;
if (indata.nrels<1)
{
ErrorClear();
return ROCKM_ERROR_FIFO_EMPTY;
}
whatis= rockm_fifo_whatis(rawels[0]);
if (whatis!=ROCKM_FIFO_IS_SUPER_HEADER)
{ /* error, return element to cache and report error */
ErrorSetF(ROCKM_ERROR_FIFO_FRAME_SUPER_HEADER,"rockm_fifo_conv_raw2frame","Super header expected.");
return ROCKM_ERROR_FIFO_FRAME_SUPER_HEADER;
}
if (indata.nrels<2)
{ /* not enough data to contain a valid frame */
ErrorClear();
return ROCKM_ERROR_FIFO_EMPTY;
}
SUPER_HEADER = rawels[0];
outdata->header.ring = RING;
outdata->header.chadd = CHAIN;
outdata->header.trigger = T_WORD_H;
if (RING==0)
{ /* ring test */
{ /* initialize */
int i;
nrels = 2;
last_bits = 0;
trigger_err = 0; /* needed for the error checking */
for (i=0; i<8; i++)
{
outdata->subfr[i].ispresent = 0;
}
}
whatis= rockm_fifo_whatis(rawels[1]);
while (whatis!=ROCKM_FIFO_IS_SUPER_FOOTER)
{ /* loop until end of super-frame */
if (whatis!=ROCKM_FIFO_IS_SLAVE)
{ /* error, return element to cache and report error */
ErrorSetF(ROCKM_ERROR_FIFO_FRAME_SUB_HEADER,"rockm_fifo_conv_raw2frame","Ringtest word expected.");
return ROCKM_ERROR_FIFO_FRAME_SUB_HEADER;
}
SUB_HEADER = rawels[nrels-1];
if (CRT_ADD_h!=CRATE)
{/* error, return element to cache and report error */
ErrorSetF(ROCKM_ERROR_FIFO_FRAME_SUB_HEADER,"rockm_fifo_conv_raw2frame","Crt_add different from crate! (%i,%i).",CRT_ADD_h,CRATE);
return ROCKM_ERROR_FIFO_FRAME_SUB_HEADER;
}
/* test if duplicated and set */
if (outdata->subfr[CRATE].ispresent!=0)
{/* error, return element to cache and report error */
ErrorSetF(ROCKM_ERROR_FIFO_FRAME_SUB_HEADER,"rockm_fifo_conv_raw2frame","Duplicated crate %i.",CRATE);
return ROCKM_ERROR_FIFO_FRAME_SUB_HEADER;
}
outdata->subfr[CRATE].ispresent = 1;
if (LAST==0)
{
last_bits++;
}
outdata->subfr[CRATE].header.last = LAST;
outdata->subfr[CRATE].header.trigger = T_WORD_h;
{
int i;
for (i=0; i<16; i++)
{
outdata->subfr[CRATE].slv[i].nrels = 0;
outdata->subfr[CRATE].slv[i].els = NULL;
}
}
outdata->subfr[CRATE].footer.softparity = PARITY_h;
outdata->subfr[CRATE].footer.hardparity = PARITY_h;
/*************************/
/* Prepare for next loop */
/*************************/
nrels++;
if (nrels>indata.nrels)
{ /* end of data before the superfooter */
ErrorClear();
return ROCKM_ERROR_FIFO_EMPTY;
}
whatis= rockm_fifo_whatis(rawels[nrels-1]);
}
SUPER_FOOTER = rawels[nrels-1];
outdata->footer.softparity_fail = 0xff;
outdata->footer.hardparity_fail = ((PARITY_CRATE_7*0x80) +
(PARITY_CRATE_6*0x40) +
(PARITY_CRATE_5*0x20) +
(PARITY_CRATE_4*0x10) +
(PARITY_CRATE_3*0x8) +
(PARITY_CRATE_2*0x4) +
(PARITY_CRATE_1*0x2) +
PARITY_CRATE_0);
outdata->footer.overflow = OVERFLOW;
outdata->footer.softcounter = nrels-2;
outdata->footer.hardcounter = COUNTER;
}
else /* RING!=0 */
{ /* no ring test, standard superframe */
{ /* initialize */
int i;
nrels = 2;
softparity_fail = 0xff; /* no error yet */
trigger_err = 0; /* no error yet */
last_bits = 0;
for (i=0; i<8; i++)
{
outdata->subfr[i].ispresent = 0;
}
}
whatis= rockm_fifo_whatis(rawels[1]);
while (whatis!=ROCKM_FIFO_IS_SUPER_FOOTER)
{ /* loop until end of super-frame */
int start_nrels;
start_nrels = nrels;
if (whatis!=ROCKM_FIFO_IS_SUB_HEADER)
{ /* error, return element to cache and report error */
ErrorSetF(ROCKM_ERROR_FIFO_FRAME_SUB_HEADER,"rockm_fifo_conv_raw2frame","Sub header expected.");
return ROCKM_ERROR_FIFO_FRAME_SUB_HEADER;
}
SUB_HEADER = rawels[start_nrels-1];
if (CRT_ADD_h!=CRATE)
{/* error, return element to cache and report error */
ErrorSetF(ROCKM_ERROR_FIFO_FRAME_SUB_HEADER,"rockm_fifo_conv_raw2frame","Crt_add different from crate! (%i,%i).",CRT_ADD_h,CRATE);
return ROCKM_ERROR_FIFO_FRAME_SUB_HEADER;
}
/* test if duplicated and set */
if (outdata->subfr[CRATE].ispresent!=0)
{/* error, return element to cache and report error */
ErrorSetF(ROCKM_ERROR_FIFO_FRAME_SUB_HEADER,"rockm_fifo_conv_raw2frame","Duplicated crate %i.",CRATE);
return ROCKM_ERROR_FIFO_FRAME_SUB_HEADER;
}
outdata->subfr[CRATE].ispresent = 1;
if (T_WORD_H!=T_WORD_h)
{
trigger_err = 1;
}
if (LAST==0)
{
last_bits++;
}
/* header data will be saved after the full frame read */
/* Now I have the header, start reading slaves */
prec_addr = 255;
{
int i;
for (i=0; i<16; i++)
nrslaves[i]=0;
}
for (; nrels<indata.nrels; nrels++)
{
whatis= rockm_fifo_whatis(rawels[nrels]);
if (whatis==ROCKM_FIFO_IS_SUB_FOOTER)
break; /* exit from loop and elaborate footer */
else if (whatis==ROCKM_FIFO_IS_SUPER_FOOTER)
{ /* error, return elements to cache and report error */
ErrorSetF(ROCKM_ERROR_FIFO_FRAME_SUPER_FOOTER,"rockm_fifo_conv_raw2frame","A super footer before a sub footer found.");
return ROCKM_ERROR_FIFO_FRAME_SUPER_FOOTER;
}
else if (whatis!=ROCKM_FIFO_IS_SLAVE)
{ /* error, return elements to cache and report error */
ErrorSetF(ROCKM_ERROR_FIFO_FRAME_SLAVE,"rockm_fifo_conv_raw2frame","Invalid type found: %i (slave expected).",whatis);
return ROCKM_ERROR_FIFO_FRAME_SLAVE;
}
/* interpret the slave */
DATA_HEADER = rawels[nrels];
if (CRT_ADD_D!=CRT_ADD_h)
{ /* error, return elements to cache and report error */
ErrorSetF(ROCKM_ERROR_FIFO_FRAME_SLAVE,"rockm_fifo_conv_raw2frame","Crate address different from subheader.");
return ROCKM_ERROR_FIFO_FRAME_SLAVE;
}
if (SLV_ADD>prec_addr)
{ /* error, return elements to cache and report error */
ErrorSetF(ROCKM_ERROR_FIFO_FRAME_SLAVE,"rockm_fifo_conv_raw2frame","Slave addresses not in decreasing order.");
return ROCKM_ERROR_FIFO_FRAME_SLAVE;
}
prec_addr = SLV_ADD;
nrslaves[SLV_ADD]++;
/* data will be saved after the full frame read */
}
if (nrels>=indata.nrels)
{
ErrorClear();
return ROCKM_ERROR_FIFO_EMPTY;
}
SUB_FOOTER = rawels[nrels];
if (CRT_ADD_f!=CRT_ADD_h)
{ /* error, return elements to cache and report error */
ErrorSetF(ROCKM_ERROR_FIFO_FRAME_SUB_FOOTER,"rockm_fifo_conv_raw2frame","Subframe address different from subheader.");
return ROCKM_ERROR_FIFO_FRAME_SUB_FOOTER;
}
nrels++;
if ((nrels-start_nrels)==1)
{ /* a sub header followed by a sub footer not allowed */
ErrorSetF(ROCKM_ERROR_FIFO_FRAME_SUB_FOOTER,"rockm_fifo_conv_raw2frame","Subfooter immediatly after subheader.");
return ROCKM_ERROR_FIFO_FRAME_SUB_FOOTER;
}
/* set the header */
{
outdata->subfr[CRATE].header.last = LAST;
outdata->subfr[CRATE].header.trigger = T_WORD_h;
softparity = PARITY_h;
}
/* set the slaves */
{
int i;
/* allocate space */
for (i=0; i<16; i++)
{
outdata->subfr[CRATE].slv[i].nrels = 0;
if (nrslaves[i]!=0)
{
outdata->subfr[CRATE].slv[i].els = (ROCKM_FIFO_SLV_data *) malloc(nrslaves[i]*sizeof(ROCKM_FIFO_SLV_data));
if (outdata->subfr[CRATE].slv[i].els==NULL)
{ /* malloc error */
ErrorSet(ROCKM_ERROR_UNKNOWN,"rockm_fifo_conv_raw2frame","Malloc returned NULL.");
return ROCKM_ERROR_UNKNOWN;
}
}
else
outdata->subfr[CRATE].slv[i].els = NULL;
}
/* save data */
for (i=start_nrels; i<(nrels-1); i++)
{
int a_nrels;
ROCKM_FIFO_SLV_data *a_el; /* element to write in */
DATA_HEADER = rawels[i];
a_nrels = outdata->subfr[CRATE].slv[SLV_ADD].nrels++;
a_el = &(outdata->subfr[CRATE].slv[SLV_ADD].els[a_nrels]);
a_el->channel = CHAIN_DATA;
a_el->reserved = RSV;
a_el->data = SLAVE_DATA;
softparity ^= PARITY_D;
}
}
/*Set footer */
{
SUB_FOOTER = rawels[nrels-1];
outdata->subfr[CRATE].footer.hardparity = PARITY_f;
outdata->subfr[CRATE].footer.softparity = softparity;
if (PARITY_f!=softparity)
softparity_fail = bits_set_bit(softparity_fail,CRATE,0);
}
/*************************/
/* Prepare for next loop */
/*************************/
nrels++;
if (nrels>indata.nrels)
{ /* end of data before the superfooter */
ErrorClear();
return ROCKM_ERROR_FIFO_EMPTY;
}
whatis= rockm_fifo_whatis(rawels[nrels-1]);
}
SUPER_FOOTER = rawels[nrels-1];
outdata->footer.softparity_fail = softparity_fail;
outdata->footer.hardparity_fail = ((PARITY_CRATE_7*0x80) +
(PARITY_CRATE_6*0x40) +
(PARITY_CRATE_5*0x20) +
(PARITY_CRATE_4*0x10) +
(PARITY_CRATE_3*0x8) +
(PARITY_CRATE_2*0x4) +
(PARITY_CRATE_1*0x2) +
PARITY_CRATE_0);
outdata->footer.overflow = OVERFLOW;
outdata->footer.softcounter = nrels-2;
outdata->footer.hardcounter = COUNTER;
} /* end if RING */
if (outdata->footer.hardparity_fail!=outdata->footer.softparity_fail)
{ /* report error, but do return the frame */
ErrorSetF(ROCKM_ERROR_FIFO_FRAME_PARITY,"rockm_fifo_conv_raw2frame","Parity fail error: hard %i soft %i.",
outdata->footer.hardparity_fail,outdata->footer.softparity_fail);
return ROCKM_ERROR_FIFO_FRAME_PARITY;
}
if (outdata->footer.hardparity_fail!=0xff)
{ /* report error, but do return the frame */
char tmp[128];
int i;
strcpy(tmp,"");
if (outdata->subfr[7].ispresent)
{
char tmp1[32];
sprintf(tmp1," 7: %i",PARITY_CRATE_7);
strcat(tmp,tmp1);
}
if (outdata->subfr[6].ispresent)
{
char tmp1[32];
sprintf(tmp1," 6: %i",PARITY_CRATE_6);
strcat(tmp,tmp1);
}
if (outdata->subfr[5].ispresent)
{
char tmp1[32];
sprintf(tmp1," 5: %i",PARITY_CRATE_5);
strcat(tmp,tmp1);
}
if (outdata->subfr[4].ispresent)
{
char tmp1[32];
sprintf(tmp1," 4: %i",PARITY_CRATE_4);
strcat(tmp,tmp1);
}
if (outdata->subfr[3].ispresent)
{
char tmp1[32];
sprintf(tmp1," 3: %i",PARITY_CRATE_3);
strcat(tmp,tmp1);
}
if (outdata->subfr[2].ispresent)
{
char tmp1[32];
sprintf(tmp1," 2: %i",PARITY_CRATE_2);
strcat(tmp,tmp1);
}
if (outdata->subfr[1].ispresent)
{
char tmp1[32];
sprintf(tmp1," 1: %i",PARITY_CRATE_1);
strcat(tmp,tmp1);
}
if (outdata->subfr[0].ispresent)
{
char tmp1[32];
sprintf(tmp1," 0: %i",PARITY_CRATE_0);
strcat(tmp,tmp1);
}
ErrorSetF(ROCKM_ERROR_FIFO_FRAME_PARITY,"rockm_fifo_conv_raw2frame",
"Hard parity error: (%s).",tmp);
return ROCKM_ERROR_FIFO_FRAME_PARITY;
}
if (outdata->footer.overflow==0)
{ /* report error, but do return the frame */
ErrorSetF(ROCKM_ERROR_FIFO_FRAME_COUNTER,"rockm_fifo_conv_raw2frame","Counter overflow!.");
return ROCKM_ERROR_FIFO_FRAME_COUNTER;
}
if (outdata->footer.hardcounter!=outdata->footer.softcounter)
{ /* report error, but do return the frame */
ErrorSetF(ROCKM_ERROR_FIFO_FRAME_COUNTER,"rockm_fifo_conv_raw2frame","Counter error: hard %i soft %i.",
outdata->footer.hardcounter,outdata->footer.softcounter);
return ROCKM_ERROR_FIFO_FRAME_COUNTER;
}
if (trigger_err)
{/* report error, but do return the frame */
ErrorSetF(ROCKM_ERROR_FIFO_FRAME_TRIGGER,"rockm_fifo_conv_raw2frame","Trigger word error.");
return ROCKM_ERROR_FIFO_FRAME_TRIGGER;
}
if (last_bits>1)
{/* report error, but do return the frame */
ErrorSetF(ROCKM_ERROR_FIFO_FRAME_LAST,"rockm_fifo_conv_raw2frame","Last bit error.");
return ROCKM_ERROR_FIFO_FRAME_LAST;
}
return ROCKM_ERROR_OK;
}
/* return one of the ROCKM_FIFO_IS_... consts */
int rockm_fifo_whatis(unsigned int el)
{
unsigned int el_type;
el_type = bits_get_bits(el,24,3);
switch (el_type)
{
case 1:
return ROCKM_FIFO_IS_SUPER_HEADER;
break;
case 5:
return ROCKM_FIFO_IS_SUB_HEADER;
break;
case 7:
return ROCKM_FIFO_IS_SLAVE;
break;
case 6:
return ROCKM_FIFO_IS_SUB_FOOTER;
break;
case 2:
return ROCKM_FIFO_IS_SUPER_FOOTER;
break;
default:
return ROCKM_FIFO_IS_ERROR;
break;
}
return -99; /* dummy, never reach this point */
}