/************************************************/ /* */ /* File : rockfifo.c */ /* Description : ROCK FIFO specific library */ /* */ /* Author: Sfiligoi Igor */ /* */ /* Comment: If this module is used, */ /* nobody else should access the FIFO */ /* */ /* Created : 14.02.1997 */ /* Last modified: 07.04.1997 */ /* */ /************************************************/ #include <stdlib.h> #include <Error.h> #include "rockfifo.h" #include "rockframes.h" #include "rockfifo_private.h" /**********************************************************************/ /* */ /* Initialisation routines */ /* */ /**********************************************************************/ int rock_fifo_open(ROCK_id rock_id, /* IN : standard rock id */ unsigned char fifotype, /* IN : ROCK_FIFO_EFIFO or ROCK_FIFO_DFIFO */ unsigned char cancache, /* IN : see ROCK_FIFO_CACHE_... constants */ ROCK_FIFO_id *fifo_id) /* OUT: fifo id related to the rock */ { (*fifo_id) = (ROCK_FIFO_id_base *) malloc(sizeof(ROCK_FIFO_id_base)); if ((*fifo_id)==NULL) { /* malloc error */ ErrorSet(ROCK_ERROR_UNKNOWN,"rock_fifo_open","Malloc returned NULL."); return ROCK_ERROR_UNKNOWN; } (*fifo_id)->rock_id = rock_id; (*fifo_id)->head = 0; (*fifo_id)->tail = 0; (*fifo_id)->fifotype = fifotype; (*fifo_id)->cancache = ROCK_FIFO_CACHE_OFF; return rock_fifo_set_cancache((*fifo_id),cancache); } int rock_fifo_close(ROCK_FIFO_id fifo_id, /* IN : fifo id */ ROCK_FIFO_RAW_bits *cache) /* OUT: the unused cache */ /* should be disposed by caller */ { cache->nrels=rock_fifo_cache_get_nrels(fifo_id); if (cache->nrels!=0) { cache->els = (ROCK_EDFIFO_bits *) malloc(cache->nrels*sizeof(ROCK_EDFIFO_bits)); if (cache->els==NULL) { /* malloc error */ ErrorSet(ROCK_ERROR_UNKNOWN,"rock_fifo_close","Malloc returned NULL."); return ROCK_ERROR_UNKNOWN; } rock_fifo_cache_read_bits(fifo_id,cache->nrels,cache->els); } else cache->els = NULL; free(fifo_id); return ROCK_ERROR_OK; } /**********************************************************************/ /* */ /* Settings routines */ /* */ /**********************************************************************/ int rock_fifo_set_cancache(ROCK_FIFO_id fifo_id, /* IN : fifo id */ unsigned char cancache) /* IN : new cancache value */ { fifo_id->cancache = cancache; return ROCK_ERROR_OK; } /**********************************************************************/ /* */ /* Cache routines */ /* */ /**********************************************************************/ int rock_fifo_cache_flush(ROCK_FIFO_id fifo_id, /* IN : fifo id */ ROCK_FIFO_RAW_bits *cache) /* OUT: the unused cache */ /* should be disposed by caller */ { cache->nrels=rock_fifo_cache_get_nrels(fifo_id); if (cache->nrels!=0) { cache->els = (ROCK_EDFIFO_bits *) malloc(cache->nrels*sizeof(ROCK_EDFIFO_bits)); if (cache->els==NULL) { /* malloc error */ ErrorSet(ROCK_ERROR_UNKNOWN,"rock_fifo_cache_flush","Malloc returned NULL."); return ROCK_ERROR_UNKNOWN; } rock_fifo_cache_read_bits(fifo_id,cache->nrels,cache->els); } else cache->els = NULL; return ROCK_ERROR_OK; } /* Very dangerous!!!! */ int rock_fifo_cache_refill_bits(ROCK_FIFO_id fifo_id, /* IN : fifo_id */ ROCK_FIFO_RAW_bits data) /* IN : data to be filled to the cache */ { return rock_fifo_cache_return_bits(fifo_id,data.els,data.nrels); } /**********************************************************************/ /* */ /* Raw read routines */ /* */ /**********************************************************************/ int rock_fifo_raw_read(ROCK_FIFO_id fifo_id, /* IN : fifo id */ unsigned int *data) /* OUT: one FIFO value */ { int err; err = rock_fifo_cache_read(fifo_id,1,data); if (err==ROCK_ERROR_OK) return ROCK_ERROR_OK; /* was in cache, ok */ err = rock_fifo_fillcache(fifo_id,1); if (err==ROCK_ERROR_OK) { /* data is in cache => read from cache */ rock_fifo_cache_read(fifo_id,1,data); return ROCK_ERROR_OK; } else if (err==ROCK_ERROR_FIFO_EMPTY) return err; else { /* serious error */ ErrorSetF(err,"rock_fifo_raw_read","rock_fifo_fillcache error: %s",ErrorGetMessage()); return err; } } int rock_fifo_raw_blockread(ROCK_FIFO_id fifo_id, /* IN : fifo id */ unsigned int nrels, /* IN : max number of elements */ ROCK_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(ROCK_ERROR_UNKNOWN,"rock_fifo_raw_blockread","Malloc returned NULL."); return ROCK_ERROR_UNKNOWN; } actel = data->els; data->nrels=0; while (1) { csize = rock_fifo_cache_get_nrels(fifo_id); if (csize>=nrels) { /* all needed elements are in cache */ data->nrels+=nrels; rock_fifo_cache_read(fifo_id,nrels,actel); return ROCK_ERROR_OK; } /* cache has not enough elements */ data->nrels+=csize; rock_fifo_cache_read(fifo_id,csize,actel); /* loop */ nrels-=csize; err = rock_fifo_fillcache(fifo_id,nrels); if (err!=ROCK_ERROR_OK) { if (err!=ROCK_ERROR_FIFO_EMPTY) { /* serious error, exit */ ErrorSetF(err,"rock_fifo_raw_blockread","rock_fifo_fillcache error: %s",ErrorGetMessage()); return err; } else { /* save the elements found and exit*/ csize = rock_fifo_cache_get_nrels(fifo_id); data->nrels+=csize; rock_fifo_cache_read(fifo_id,csize,actel); return ROCK_ERROR_FIFO_EMPTY; } } } } /**********************************************************************/ /* */ /* Complete raw read routines */ /* */ /**********************************************************************/ int rock_fifo_raw_read_bits(ROCK_FIFO_id fifo_id, /* IN : fifo id */ ROCK_EDFIFO_bits *data) /* OUT: one FIFO value */ { int err; err = rock_fifo_cache_read_bits(fifo_id,1,data); if (err==ROCK_ERROR_OK) return ROCK_ERROR_OK; /* was in cache, ok */ err = rock_fifo_fillcache(fifo_id,1); if (err==ROCK_ERROR_OK) { /* data is in cache => read from cache */ rock_fifo_cache_read_bits(fifo_id,1,data); return ROCK_ERROR_OK; } else if (err==ROCK_ERROR_FIFO_EMPTY) return err; else { /* serious error */ ErrorSetF(err,"rock_fifo_raw_read_bits","rock_fifo_fillcache error: %s",ErrorGetMessage()); return err; } } int rock_fifo_raw_blockread_bits(ROCK_FIFO_id fifo_id, /* IN : fifo id */ unsigned int nrels, /* IN : max number of elements */ ROCK_FIFO_RAW_bits *data) /* OUT: FIFO data */ /* should be disposed by caller */ { int csize; ROCK_EDFIFO_bits *actel; /* point to the first unused space in data->els */ int err; data->els = (ROCK_EDFIFO_bits *) malloc(nrels*sizeof(ROCK_EDFIFO_bits)); if (data->els==NULL) { /* malloc error */ ErrorSet(ROCK_ERROR_UNKNOWN,"rock_fifo_raw_blockread_bits","Malloc returned NULL."); return ROCK_ERROR_UNKNOWN; } actel = data->els; data->nrels=0; while (1) { csize = rock_fifo_cache_get_nrels(fifo_id); if (csize>=nrels) { /* all needed elements are in cache */ data->nrels+=nrels; rock_fifo_cache_read_bits(fifo_id,nrels,actel); return ROCK_ERROR_OK; } /* cache has not enough elements */ data->nrels+=csize; rock_fifo_cache_read_bits(fifo_id,csize,actel); /* loop */ nrels-=csize; err = rock_fifo_fillcache(fifo_id,nrels); if (err!=ROCK_ERROR_OK) { if (err!=ROCK_ERROR_FIFO_EMPTY) { /* serious error, exit */ ErrorSetF(err,"rock_fifo_raw_blockread_bits","rock_fifo_fillcache error: %s",ErrorGetMessage()); return err; } else { /* save the elements found and exit*/ csize = rock_fifo_cache_get_nrels(fifo_id); data->nrels+=csize; rock_fifo_cache_read_bits(fifo_id,csize,actel); return ROCK_ERROR_FIFO_EMPTY; } } } } /**********************************************************************/ /* */ /* Frame read routines */ /* */ /**********************************************************************/ int rock_fifo_frame_read(ROCK_FIFO_id fifo_id, /* IN : fifo id */ ROCK_FIFO_FRAME *data) /* OUT: one FIFO value */ { int nrels; ROCK_EDFIFO_bits rawels[ROCK_FIFO_FRAME_SIZE]; unsigned int softparity; 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 frame */ int err,whatis; /* read header */ err = rock_fifo_raw_read_bits(fifo_id,&(rawels[0])); /* exit immediatly if cannot read the header */ if (err!=ROCK_ERROR_OK) if (err==ROCK_ERROR_FIFO_EMPTY) return err; else { ErrorSetF(err,"rock_fifo_frame_read","rock_fifo_raw_read_bits error: %s",ErrorGetMessage()); return err; } whatis= rockf_whatis(rawels[0].fifodata); if (whatis==ROCKF_IS_EMPTY) { /* set the frame and exit */ ROCKF_EMPTY_bits empty; int i; rockf_nr2empty(rawels[0].fifodata,empty); data->header.sy = empty.sy; data->header.last = empty.l; data->header.cradd = empty.ca; data->header.trigger = empty.trigger; data->footer.last = empty.l; data->footer.softparity = empty.parity; data->footer.hardparity = empty.parity; for (i=0; i<16; i++) { data->slv[i].nrels = 0; data->slv[i].els = NULL; } return ROCK_ERROR_OK; } else if (whatis!=ROCKF_IS_HEADER) { /* error, return element to cache and report error */ rock_fifo_cache_return_bits(fifo_id,rawels,1); ErrorSetF(ROCK_ERROR_FIFO_FRAME_HEADER,"rock_fifo_frame_read","Header expected."); return ROCK_ERROR_FIFO_FRAME_HEADER; } /* 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; } { int i; for (i=1; i<ROCK_FIFO_FRAME_SIZE; i++) { ROCKF_SLAVE_bits slave; err = rock_fifo_raw_read_bits(fifo_id,&(rawels[i])); /* exit if cannot read the FIFO */ if (err!=ROCK_ERROR_OK) { /* error, return elements to cache and report error */ rock_fifo_cache_return_bits(fifo_id,rawels,i); if (err!=ROCK_ERROR_FIFO_EMPTY) ErrorSetF(err,"rock_fifo_frame_read","rock_fifo_raw_read_bits error: %s",ErrorGetMessage()); return err; } whatis= rockf_whatis(rawels[i].fifodata); if (whatis==ROCKF_IS_FOOTER) break; /* exit from loop and elaborate footer */ else if (whatis!=ROCKF_IS_SLAVE) { /* error, return elements to cache and report error */ rock_fifo_cache_return_bits(fifo_id,rawels,i+1); ErrorSetF(ROCK_ERROR_FIFO_FRAME_SLAVE,"rock_fifo_frame_read","A header before a footer found."); return ROCK_ERROR_FIFO_FRAME_SLAVE; } /* interpret the slave */ rockf_nr2slave(rawels[i].fifodata,slave); if (slave.slvadd>prec_addr) { /* error, return elements to cache and report error */ rock_fifo_cache_return_bits(fifo_id,rawels,i+1); ErrorSetF(ROCK_ERROR_FIFO_FRAME_SLAVE,"rock_fifo_frame_read","Addresses not in decreasing order."); return ROCK_ERROR_FIFO_FRAME_SLAVE; } prec_addr = slave.slvadd; nrslaves[slave.slvadd]++; /* data will be saved after the full frame read */ } if (i>=ROCK_FIFO_FRAME_SIZE) { /* error, return elements to cache and report error */ rock_fifo_cache_return_bits(fifo_id,rawels,ROCK_FIFO_FRAME_SIZE); ErrorSetF(ROCK_ERROR_FIFO_FRAME_OVERFLOW,"rock_fifo_frame_read","Frame too large."); return ROCK_ERROR_FIFO_FRAME_OVERFLOW; } nrels=i+1; } if (nrels==2) { /* a header followed by a footer not allowed */ rock_fifo_cache_return_bits(fifo_id,rawels,nrels); ErrorSetF(ROCK_ERROR_FIFO_FRAME_FOOTER,"rock_fifo_frame_read","Footer immediatly after header."); return ROCK_ERROR_FIFO_FRAME_FOOTER; } /* set the header */ { ROCKF_HEADER_bits header; rockf_nr2header(rawels[0].fifodata,header); data->header.sy = header.sy; data->header.last = header.l; data->header.cradd = header.ca; data->header.trigger = header.trigger; softparity = header.parity; } /* set the slaves */ { int i; /* allocate space */ for (i=0; i<16; i++) { data->slv[i].nrels = 0; if (nrslaves[i]!=0) { data->slv[i].els = (ROCK_FIFO_SLV_data *) malloc(nrslaves[i]*sizeof(ROCK_FIFO_SLV_data)); if (data->slv[i].els==NULL) { /* malloc error */ ErrorSet(ROCK_ERROR_UNKNOWN,"rock_fifo_frame_read","Malloc returned NULL."); return ROCK_ERROR_UNKNOWN; } } else data->slv[i].els = NULL; } /* save data */ for (i=1; i<(nrels-1); i++) { ROCKF_SLAVE_bits slave; int a_nrels; ROCK_FIFO_SLV_data *a_el; /* element to write in */ rockf_nr2slave(rawels[i].fifodata,slave); a_nrels = data->slv[slave.slvadd].nrels++; a_el = &(data->slv[slave.slvadd].els[a_nrels]); a_el->channel = slave.channel; a_el->reserved = slave.reserved; a_el->data = slave.data; softparity ^= slave.parity; } } /*Set footer */ { ROCKF_FOOTER_bits footer; rockf_nr2footer(rawels[nrels-1].fifodata,footer); data->footer.last = footer.l; data->footer.hardparity = footer.parity; data->footer.softparity = softparity; } if (data->footer.hardparity!=data->footer.softparity) { /* report error, but do return the frame */ ErrorSetF(ROCK_ERROR_FIFO_FRAME_PARITY,"rock_fifo_frame_read","Parity error: hard %i soft %i.", data->footer.hardparity,data->footer.softparity); return ROCK_ERROR_FIFO_FRAME_PARITY; } else return ROCK_ERROR_OK; } /* parity error is not considered an error */ int rock_fifo_frame_blockread(ROCK_FIFO_id fifo_id,/* IN : fifo id */ unsigned int nrels, /* IN : max number of raw elements */ ROCK_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 ROCK_ERROR_OK; } /* alloc space for the worst case */ data->frames = (ROCK_FIFO_FRAME *) malloc(nrels*sizeof(ROCK_FIFO_FRAME)); if (data->frames==NULL) { /* malloc error */ ErrorSet(ROCK_ERROR_UNKNOWN,"rock_fifo_frame_blockread","Malloc returned NULL."); return ROCK_ERROR_UNKNOWN; } for (i=0; i<nrels; i++) { err = rock_fifo_frame_read(fifo_id,&(data->frames[i])); if ((err!=ROCK_ERROR_OK)&&(err!=ROCK_ERROR_FIFO_FRAME_PARITY)) { if (err==ROCK_ERROR_FIFO_EMPTY) break; else { /* a serious error occured, exit */ ErrorSetF(err,"rock_fifo_frame_blockread","rock_fifo_frame_read error: %s",ErrorGetMessage()); data->nrframes=i; return err; } } ErrorClear(); /* clean any old error */ } data->nrframes=i; if (data->nrframes<nrels) return ROCK_ERROR_FIFO_EMPTY; else return ROCK_ERROR_OK; } int rock_fifo_frame_rawread(ROCK_FIFO_id fifo_id, /* IN : fifo id */ ROCK_FIFO_RAW *data) /* OUT: one FIFO value */ /* should be disposed by caller */ { int nrels; ROCK_EDFIFO_bits rawels[ROCK_FIFO_FRAME_SIZE]; unsigned int softparity; unsigned char prec_addr; /* needed to test that addresses go from highest to lower */ int err,whatis; data->nrels=0; data->els = NULL; /* read header */ err = rock_fifo_raw_read_bits(fifo_id,&(rawels[0])); /* exit immediatly if cannot read the header */ if (err!=ROCK_ERROR_OK) if (err==ROCK_ERROR_FIFO_EMPTY) return err; else { ErrorSetF(err,"rock_fifo_frame_rawread","rock_fifo_raw_read_bits error: %s",ErrorGetMessage()); return err; } whatis= rockf_whatis(rawels[0].fifodata); if (whatis==ROCKF_IS_EMPTY) { /* set the frame and exit */ data->nrels = 1; data->els = (unsigned int *) malloc(sizeof(unsigned int)); if (data->els==NULL) { /* malloc error */ ErrorSet(ROCK_ERROR_UNKNOWN,"rock_fifo_frame_rawread","Malloc returned NULL."); return ROCK_ERROR_UNKNOWN; } data->els[0] = rawels[0].fifodata; return ROCK_ERROR_OK; } else if (whatis!=ROCKF_IS_HEADER) { /* error, return element to cache and report error */ rock_fifo_cache_return_bits(fifo_id,rawels,1); ErrorSetF(ROCK_ERROR_FIFO_FRAME_HEADER,"rock_fifo_frame_rawread","Header expected."); return ROCK_ERROR_FIFO_FRAME_HEADER; } /* Now I have the header, start reading slaves */ prec_addr = 255; { int i; for (i=1; i<ROCK_FIFO_FRAME_SIZE; i++) { ROCKF_SLAVE_bits slave; err = rock_fifo_raw_read_bits(fifo_id,&(rawels[i])); /* exit if cannot read the FIFO */ if (err!=ROCK_ERROR_OK) { /* error, return elements to cache and report error */ rock_fifo_cache_return_bits(fifo_id,rawels,i); if (err!=ROCK_ERROR_FIFO_EMPTY) ErrorSetF(err,"rock_fifo_frame_rawread","rock_fifo_raw_read_bits error: %s",ErrorGetMessage()); return err; } whatis= rockf_whatis(rawels[i].fifodata); if (whatis==ROCKF_IS_FOOTER) break; /* exit from loop and elaborate footer */ else if (whatis!=ROCKF_IS_SLAVE) { /* error, return elements to cache and report error */ rock_fifo_cache_return_bits(fifo_id,rawels,i+1); ErrorSetF(ROCK_ERROR_FIFO_FRAME_SLAVE,"rock_fifo_frame_rawread","A header before a footer found."); return ROCK_ERROR_FIFO_FRAME_SLAVE; } /* interpret the slave */ rockf_nr2slave(rawels[i].fifodata,slave); if (slave.slvadd>prec_addr) { /* error, return elements to cache and report error */ rock_fifo_cache_return_bits(fifo_id,rawels,i+1); ErrorSetF(ROCK_ERROR_FIFO_FRAME_SLAVE,"rock_fifo_frame_rawread","Addresses not in decreasing order."); return ROCK_ERROR_FIFO_FRAME_SLAVE; } prec_addr = slave.slvadd; } if (i>=ROCK_FIFO_FRAME_SIZE) { /* error, return elements to cache and report error */ rock_fifo_cache_return_bits(fifo_id,rawels,ROCK_FIFO_FRAME_SIZE); ErrorSetF(ROCK_ERROR_FIFO_FRAME_OVERFLOW,"rock_fifo_frame_rawread","Frame too large."); return ROCK_ERROR_FIFO_FRAME_OVERFLOW; } nrels=i+1; } if (nrels==2) { /* a header followed by a footer not allowed */ rock_fifo_cache_return_bits(fifo_id,rawels,nrels); ErrorSetF(ROCK_ERROR_FIFO_FRAME_FOOTER,"rock_fifo_frame_rawread","Footer immediatly after header."); return ROCK_ERROR_FIFO_FRAME_FOOTER; } /* save the data */ { int i; data->nrels = nrels; data->els = (unsigned int *) malloc(nrels*sizeof(unsigned int)); if (data->els==NULL) { /* malloc error */ ErrorSet(ROCK_ERROR_UNKNOWN,"rock_fifo_frame_rawread","Malloc returned NULL."); return ROCK_ERROR_UNKNOWN; } for (i=0; i<nrels; i++) { data->els[i] = rawels[i].fifodata; } } /* calc the softparity */ /* header */ { ROCKF_HEADER_bits header; rockf_nr2header(rawels[0].fifodata,header); softparity = header.parity; } /* slaves */ { int i; for (i=1; i<(nrels-1); i++) { ROCKF_SLAVE_bits slave; rockf_nr2slave(rawels[i].fifodata,slave); softparity ^= slave.parity; } } /* footer */ { ROCKF_FOOTER_bits footer; rockf_nr2footer(rawels[nrels-1].fifodata,footer); if (footer.parity!=softparity) { /* report error, but do return the frame */ ErrorSetF(ROCK_ERROR_FIFO_FRAME_PARITY,"rock_fifo_frame_rawread","Parity error: hard %i soft %i.", footer.parity,softparity); return ROCK_ERROR_FIFO_FRAME_PARITY; } else return ROCK_ERROR_OK; } } int rock_fifo_frame_rawread_bits(ROCK_FIFO_id fifo_id, /* IN : fifo id */ ROCK_FIFO_RAW_bits *data) /* OUT: one FIFO value */ /* should be disposed by caller */ { int nrels; ROCK_EDFIFO_bits rawels[ROCK_FIFO_FRAME_SIZE]; unsigned int softparity; unsigned char prec_addr; /* needed to test that addresses go from highest to lower */ int err,whatis; data->nrels=0; data->els = NULL; /* read header */ err = rock_fifo_raw_read_bits(fifo_id,&(rawels[0])); /* exit immediatly if cannot read the header */ if (err!=ROCK_ERROR_OK) if (err==ROCK_ERROR_FIFO_EMPTY) return err; else { ErrorSetF(err,"rock_fifo_frame_rawread_bits","rock_fifo_raw_read_bits error: %s",ErrorGetMessage()); return err; } whatis= rockf_whatis(rawels[0].fifodata); if (whatis==ROCKF_IS_EMPTY) { /* set the frame and exit */ data->nrels = 1; data->els = (ROCK_EDFIFO_bits *) malloc(sizeof(ROCK_EDFIFO_bits)); if (data->els==NULL) { /* malloc error */ ErrorSet(ROCK_ERROR_UNKNOWN,"rock_fifo_frame_rawread_bits","Malloc returned NULL."); return ROCK_ERROR_UNKNOWN; } data->els[0] = rawels[0]; return ROCK_ERROR_OK; } else if (whatis!=ROCKF_IS_HEADER) { /* error, return element to cache and report error */ rock_fifo_cache_return_bits(fifo_id,rawels,1); ErrorSetF(ROCK_ERROR_FIFO_FRAME_HEADER,"rock_fifo_frame_rawread_bits","Header expected."); return ROCK_ERROR_FIFO_FRAME_HEADER; } /* Now I have the header, start reading slaves */ prec_addr = 255; { int i; for (i=1; i<ROCK_FIFO_FRAME_SIZE; i++) { ROCKF_SLAVE_bits slave; err = rock_fifo_raw_read_bits(fifo_id,&(rawels[i])); /* exit if cannot read the FIFO */ if (err!=ROCK_ERROR_OK) { /* error, return elements to cache and report error */ rock_fifo_cache_return_bits(fifo_id,rawels,i); if (err!=ROCK_ERROR_FIFO_EMPTY) ErrorSetF(err,"rock_fifo_frame_rawread_bits","rock_fifo_raw_read_bits error: %s",ErrorGetMessage()); return err; } whatis= rockf_whatis(rawels[i].fifodata); if (whatis==ROCKF_IS_FOOTER) break; /* exit from loop and elaborate footer */ else if (whatis!=ROCKF_IS_SLAVE) { /* error, return elements to cache and report error */ rock_fifo_cache_return_bits(fifo_id,rawels,i+1); ErrorSetF(ROCK_ERROR_FIFO_FRAME_SLAVE,"rock_fifo_frame_rawread_bits","A header before a footer found."); return ROCK_ERROR_FIFO_FRAME_SLAVE; } /* interpret the slave */ rockf_nr2slave(rawels[i].fifodata,slave); if (slave.slvadd>prec_addr) { /* error, return elements to cache and report error */ rock_fifo_cache_return_bits(fifo_id,rawels,i+1); ErrorSetF(ROCK_ERROR_FIFO_FRAME_SLAVE,"rock_fifo_frame_rawread_bits","Addresses not in decreasing order."); return ROCK_ERROR_FIFO_FRAME_SLAVE; } prec_addr = slave.slvadd; } if (i>=ROCK_FIFO_FRAME_SIZE) { /* error, return elements to cache and report error */ rock_fifo_cache_return_bits(fifo_id,rawels,ROCK_FIFO_FRAME_SIZE); ErrorSetF(ROCK_ERROR_FIFO_FRAME_OVERFLOW,"rock_fifo_frame_rawread_bits","Frame too large."); return ROCK_ERROR_FIFO_FRAME_OVERFLOW; } nrels=i+1; } if (nrels==2) { /* a header followed by a footer not allowed */ rock_fifo_cache_return_bits(fifo_id,rawels,nrels); ErrorSetF(ROCK_ERROR_FIFO_FRAME_FOOTER,"rock_fifo_frame_rawread_bits","Footer immediatly after header."); return ROCK_ERROR_FIFO_FRAME_FOOTER; } /* save the data */ { int i; data->nrels = nrels; data->els = (ROCK_EDFIFO_bits *) malloc(nrels*sizeof(ROCK_EDFIFO_bits)); if (data->els==NULL) { /* malloc error */ ErrorSet(ROCK_ERROR_UNKNOWN,"rock_fifo_frame_rawread_bits","Malloc returned NULL."); return ROCK_ERROR_UNKNOWN; } for (i=0; i<nrels; i++) { data->els[i] = rawels[i]; } } /* calc the softparity */ /* header */ { ROCKF_HEADER_bits header; rockf_nr2header(rawels[0].fifodata,header); softparity = header.parity; } /* slaves */ { int i; for (i=1; i<(nrels-1); i++) { ROCKF_SLAVE_bits slave; rockf_nr2slave(rawels[i].fifodata,slave); softparity ^= slave.parity; } } /* footer */ { ROCKF_FOOTER_bits footer; rockf_nr2footer(rawels[nrels-1].fifodata,footer); if (footer.parity!=softparity) { /* report error, but do return the frame */ ErrorSetF(ROCK_ERROR_FIFO_FRAME_PARITY,"rock_fifo_frame_rawread_bits","Parity error: hard %i soft %i.", footer.parity,softparity); return ROCK_ERROR_FIFO_FRAME_PARITY; } else return ROCK_ERROR_OK; } } /* block of data allocated each time */ #define ROCK_FIFO_FS_BLOCK 1024 /* Synch the FIFO to the start of the frame */ int rock_fifo_frame_synch(ROCK_FIFO_id fifo_id, /* IN : fifo id */ ROCK_FIFO_RAW *data) /* OUT: FIFO data */ /* should be disposed by caller */ { int err; int actblock; /* actual size of the buffer */ data->nrels = 0; actblock = ROCK_FIFO_FS_BLOCK; data->els = (unsigned int *) malloc(actblock*sizeof(unsigned int)); if (data->els==NULL) { /* malloc error */ ErrorSet(ROCK_ERROR_UNKNOWN,"rock_fifo_frame_synch","Malloc returned NULL."); return ROCK_ERROR_UNKNOWN; } /* read the first element without checking the type */ err = rock_fifo_raw_read(fifo_id,&(data->els[data->nrels])); if (err!=ROCK_ERROR_OK) { if (err!=ROCK_ERROR_FIFO_EMPTY) { /* serious error */ ErrorSetF(err,"rock_fifo_frame_synch","rock_fifo_raw_read error: %s",ErrorGetMessage()); return err; } else return ROCK_ERROR_FIFO_EMPTY; } data->nrels++; while (1) { int whatis; ROCK_EDFIFO_bits bits; err = rock_fifo_raw_read_bits(fifo_id,&bits); if (err!=ROCK_ERROR_OK) { if (err!=ROCK_ERROR_FIFO_EMPTY) { /* serious error */ ErrorSetF(err,"rock_fifo_frame_synch","rock_fifo_raw_read error: %s",ErrorGetMessage()); return err; } else return ROCK_ERROR_FIFO_EMPTY; } whatis = rockf_whatis(bits.fifodata); if ((whatis==ROCKF_IS_HEADER)||(whatis==ROCKF_IS_EMPTY)) { /* found, return to cache and exit */ rock_fifo_cache_return_bits(fifo_id,&bits,1); return ROCK_ERROR_OK; } /* not yet syncronised */ data->els[data->nrels] = bits.fifodata; data->nrels++; if (data->nrels>=actblock) { /* must resize the buffer */ actblock += ROCK_FIFO_FS_BLOCK; data->els = (unsigned int *) realloc(data->els,actblock*sizeof(unsigned int)); if (data->els==NULL) { /* realloc error */ ErrorSet(ROCK_ERROR_UNKNOWN,"rock_fifo_frame_synch","Realloc returned NULL."); return ROCK_ERROR_UNKNOWN; } } } } /* Synch the FIFO to the start of the frame */ int rock_fifo_frame_synch_bits(ROCK_FIFO_id fifo_id, /* IN : fifo id */ ROCK_FIFO_RAW_bits *data) /* OUT: FIFO data */ /* should be disposed by caller */ { int err; int actblock; /* actual size of the buffer */ data->nrels = 0; actblock = ROCK_FIFO_FS_BLOCK; data->els = (ROCK_EDFIFO_bits *) malloc(actblock*sizeof(ROCK_EDFIFO_bits)); if (data->els==NULL) { /* malloc error */ ErrorSet(ROCK_ERROR_UNKNOWN,"rock_fifo_frame_synch_bits","Malloc returned NULL."); return ROCK_ERROR_UNKNOWN; } /* read the first element without checking the type */ err = rock_fifo_raw_read_bits(fifo_id,&(data->els[data->nrels])); if (err!=ROCK_ERROR_OK) { if (err!=ROCK_ERROR_FIFO_EMPTY) { /* serious error */ ErrorSetF(err,"rock_fifo_frame_synch_bits","rock_fifo_raw_read_bits error: %s",ErrorGetMessage()); return err; } else return ROCK_ERROR_FIFO_EMPTY; } data->nrels++; while (1) { int whatis; err = rock_fifo_raw_read_bits(fifo_id,&(data->els[data->nrels])); if (err!=ROCK_ERROR_OK) { if (err!=ROCK_ERROR_FIFO_EMPTY) { /* serious error */ ErrorSetF(err,"rock_fifo_frame_synch_bits","rock_fifo_raw_read_bits error: %s",ErrorGetMessage()); return err; } else return ROCK_ERROR_FIFO_EMPTY; } whatis = rockf_whatis(data->els[data->nrels].fifodata); if ((whatis==ROCKF_IS_HEADER)||(whatis==ROCKF_IS_EMPTY)) { /* found, return to cache and exit */ rock_fifo_cache_return_bits(fifo_id,&(data->els[data->nrels]),1); return ROCK_ERROR_OK; } /* not yet syncronised */ data->nrels++; if (data->nrels>=actblock) { /* must resize the buffer */ actblock += ROCK_FIFO_FS_BLOCK; data->els = (ROCK_EDFIFO_bits *) realloc(data->els,actblock*sizeof(ROCK_EDFIFO_bits)); if (data->els==NULL) { /* realloc error */ ErrorSet(ROCK_ERROR_UNKNOWN,"rock_fifo_frame_synch_bits","Realloc returned NULL."); return ROCK_ERROR_UNKNOWN; } } } } /**********************************************************************/ /* */ /* Frame conversion routines */ /* */ /**********************************************************************/ int rock_fifo_conv_frame2raw(ROCK_FIFO_FRAME indata, /* IN : formatted data */ ROCK_FIFO_RAW *outdata) /* OUT: raw data */ { int nrslaves; /* find out the number of slaves */ { int i; nrslaves=0; for (i=0; i<16; i++) { nrslaves+=indata.slv[i].nrels; } } if (nrslaves==0) { /* an empty frame */ ROCKF_EMPTY_bits aempty; outdata->nrels = 1; outdata->els = (unsigned int *) malloc(sizeof(unsigned int)); if (outdata->els==NULL) { /* malloc error */ ErrorSet(ROCK_ERROR_UNKNOWN,"rock_fifo_convframe2raw","Malloc returned NULL."); return ROCK_ERROR_UNKNOWN; } aempty.sy = indata.header.sy; aempty.l = indata.header.last; aempty.ca = indata.header.cradd; aempty.trigger = indata.header.trigger; outdata->els[0] = rockf_empty2nr(aempty); return ROCK_ERROR_OK; } /* not empty */ outdata->nrels = nrslaves+2; outdata->els = (unsigned int *) malloc(outdata->nrels*sizeof(unsigned int)); if (outdata->els==NULL) { /* malloc error */ ErrorSet(ROCK_ERROR_UNKNOWN,"rock_fifo_convframe2raw","Malloc returned NULL."); return ROCK_ERROR_UNKNOWN; } { ROCKF_HEADER_bits aheader; aheader.sy = indata.header.sy; aheader.l = indata.header.last; aheader.ca = indata.header.cradd; aheader.trigger = indata.header.trigger; outdata->els[0] = rockf_header2nr(aheader); } { int slvnr; int actel; actel=1; for (slvnr=15; slvnr>=0; slvnr--) { int i; for (i=0; i<indata.slv[slvnr].nrels; i++) { ROCKF_SLAVE_bits aslave; aslave.slvadd = slvnr; aslave.channel = indata.slv[slvnr].els[i].channel; aslave.reserved = indata.slv[slvnr].els[i].reserved; aslave.data = indata.slv[slvnr].els[i].data; outdata->els[actel] = rockf_slave2nr(aslave); actel++; } } } { ROCKF_FOOTER_bits afooter; afooter.l = indata.footer.last; afooter.parity = indata.footer.hardparity; outdata->els[outdata->nrels-1] = rockf_footer2nr(afooter); } return ROCK_ERROR_OK; } int rock_fifo_conv_raw2frame(ROCK_FIFO_RAW indata, /* IN : raw data */ ROCK_FIFO_FRAME *outdata) /* OUT: formated data */ { int nrels; unsigned int *rawels; unsigned int softparity; 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 frame */ int err,whatis; if (indata.nrels==0) return ROCK_ERROR_FIFO_EMPTY; rawels = indata.els; whatis= rockf_whatis(rawels[0]); if (whatis==ROCKF_IS_EMPTY) { /* set the frame and exit */ ROCKF_EMPTY_bits empty; int i; rockf_nr2empty(rawels[0],empty); outdata->header.sy = empty.sy; outdata->header.last = empty.l; outdata->header.cradd = empty.ca; outdata->header.trigger = empty.trigger; outdata->footer.last = empty.l; outdata->footer.softparity = empty.parity; outdata->footer.hardparity = empty.parity; for (i=0; i<16; i++) { outdata->slv[i].nrels = 0; outdata->slv[i].els = NULL; } return ROCK_ERROR_OK; } else if (whatis!=ROCKF_IS_HEADER) { /* error, return element to cache and report error */ ErrorSetF(ROCK_ERROR_FIFO_FRAME_HEADER,"rock_fifo_conv_raw2frame","Header expected."); return ROCK_ERROR_FIFO_FRAME_HEADER; } /* 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; } { int i; for (i=1; i<ROCK_FIFO_FRAME_SIZE; i++) { ROCKF_SLAVE_bits slave; if (indata.nrels<=i) return ROCK_ERROR_FIFO_EMPTY; whatis= rockf_whatis(rawels[i]); if (whatis==ROCKF_IS_FOOTER) break; /* exit from loop and elaborate footer */ else if (whatis!=ROCKF_IS_SLAVE) { /* error, return elements to cache and report error */ ErrorSetF(ROCK_ERROR_FIFO_FRAME_SLAVE,"rock_fifo_conv_raw2frame","A header before a footer found."); return ROCK_ERROR_FIFO_FRAME_SLAVE; } /* interpret the slave */ rockf_nr2slave(rawels[i],slave); if (slave.slvadd>prec_addr) { /* error, return elements to cache and report error */ ErrorSetF(ROCK_ERROR_FIFO_FRAME_SLAVE,"rock_fifo_conv_raw2frame","Addresses not in decreasing order."); return ROCK_ERROR_FIFO_FRAME_SLAVE; } prec_addr = slave.slvadd; nrslaves[slave.slvadd]++; /* data will be saved after the full frame read */ } nrels=i+1; } if (nrels==2) { /* a header followed by a footer not allowed */ ErrorSetF(ROCK_ERROR_FIFO_FRAME_FOOTER,"rock_fifo_conv_raw2frame","Footer immediatly after header."); return ROCK_ERROR_FIFO_FRAME_FOOTER; } /* set the header */ { ROCKF_HEADER_bits header; rockf_nr2header(rawels[0],header); outdata->header.sy = header.sy; outdata->header.last = header.l; outdata->header.cradd = header.ca; outdata->header.trigger = header.trigger; softparity = header.parity; } /* set the slaves */ { int i; /* allocate space */ for (i=0; i<16; i++) { outdata->slv[i].nrels = 0; if (nrslaves[i]!=0) { outdata->slv[i].els = (ROCK_FIFO_SLV_data *) malloc(nrslaves[i]*sizeof(ROCK_FIFO_SLV_data)); if (outdata->slv[i].els==NULL) { /* malloc error */ ErrorSet(ROCK_ERROR_UNKNOWN,"rock_fifo_conv_raw2frame","Malloc returned NULL."); return ROCK_ERROR_UNKNOWN; } } else outdata->slv[i].els = NULL; } /* save data */ for (i=1; i<(nrels-1); i++) { ROCKF_SLAVE_bits slave; int a_nrels; ROCK_FIFO_SLV_data *a_el; /* element to write in */ rockf_nr2slave(rawels[i],slave); a_nrels = outdata->slv[slave.slvadd].nrels++; a_el = &(outdata->slv[slave.slvadd].els[a_nrels]); a_el->channel = slave.channel; a_el->reserved = slave.reserved; a_el->data = slave.data; softparity ^= slave.parity; } } /*Set footer */ { ROCKF_FOOTER_bits footer; rockf_nr2footer(rawels[nrels-1],footer); outdata->footer.last = footer.l; outdata->footer.hardparity = footer.parity; outdata->footer.softparity = softparity; } if (outdata->footer.hardparity!=outdata->footer.softparity) { /* report error, but do return the frame */ ErrorSetF(ROCK_ERROR_FIFO_FRAME_PARITY,"rock_fifo_conv_raw2frame","Parity error: hard %i soft %i.", outdata->footer.hardparity,outdata->footer.softparity); return ROCK_ERROR_FIFO_FRAME_PARITY; } else return ROCK_ERROR_OK; } int rock_fifo_conv_raw_bits2frame(ROCK_FIFO_RAW_bits indata, /* IN : raw data */ ROCK_FIFO_FRAME *outdata) /* OUT: formated data */ { int nrels; ROCK_EDFIFO_bits *rawels; unsigned int softparity; 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 frame */ int err,whatis; if (indata.nrels==0) return ROCK_ERROR_FIFO_EMPTY; rawels = indata.els; whatis= rockf_whatis(rawels[0].fifodata); if (whatis==ROCKF_IS_EMPTY) { /* set the frame and exit */ ROCKF_EMPTY_bits empty; int i; rockf_nr2empty(rawels[0].fifodata,empty); outdata->header.sy = empty.sy; outdata->header.last = empty.l; outdata->header.cradd = empty.ca; outdata->header.trigger = empty.trigger; outdata->footer.last = empty.l; outdata->footer.softparity = empty.parity; outdata->footer.hardparity = empty.parity; for (i=0; i<16; i++) { outdata->slv[i].nrels = 0; outdata->slv[i].els = NULL; } return ROCK_ERROR_OK; } else if (whatis!=ROCKF_IS_HEADER) { /* error, return element to cache and report error */ ErrorSetF(ROCK_ERROR_FIFO_FRAME_HEADER,"rock_fifo_conv_raw_bits2frame","Header expected."); return ROCK_ERROR_FIFO_FRAME_HEADER; } /* 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; } { int i; for (i=1; i<ROCK_FIFO_FRAME_SIZE; i++) { ROCKF_SLAVE_bits slave; if (indata.nrels<=i) return ROCK_ERROR_FIFO_EMPTY; whatis= rockf_whatis(rawels[i].fifodata); if (whatis==ROCKF_IS_FOOTER) break; /* exit from loop and elaborate footer */ else if (whatis!=ROCKF_IS_SLAVE) { /* error, return elements to cache and report error */ ErrorSetF(ROCK_ERROR_FIFO_FRAME_SLAVE,"rock_fifo_conv_raw_bits2frame","A header before a footer found."); return ROCK_ERROR_FIFO_FRAME_SLAVE; } /* interpret the slave */ rockf_nr2slave(rawels[i].fifodata,slave); if (slave.slvadd>prec_addr) { /* error, return elements to cache and report error */ ErrorSetF(ROCK_ERROR_FIFO_FRAME_SLAVE,"rock_fifo_conv_raw_bits2frame","Addresses not in decreasing order."); return ROCK_ERROR_FIFO_FRAME_SLAVE; } prec_addr = slave.slvadd; nrslaves[slave.slvadd]++; /* data will be saved after the full frame read */ } nrels=i+1; } if (nrels==2) { /* a header followed by a footer not allowed */ ErrorSetF(ROCK_ERROR_FIFO_FRAME_FOOTER,"rock_fifo_conv_raw_bits2frame","Footer immediatly after header."); return ROCK_ERROR_FIFO_FRAME_FOOTER; } /* set the header */ { ROCKF_HEADER_bits header; rockf_nr2header(rawels[0].fifodata,header); outdata->header.sy = header.sy; outdata->header.last = header.l; outdata->header.cradd = header.ca; outdata->header.trigger = header.trigger; softparity = header.parity; } /* set the slaves */ { int i; /* allocate space */ for (i=0; i<16; i++) { outdata->slv[i].nrels = 0; if (nrslaves[i]!=0) { outdata->slv[i].els = (ROCK_FIFO_SLV_data *) malloc(nrslaves[i]*sizeof(ROCK_FIFO_SLV_data)); if (outdata->slv[i].els==NULL) { /* malloc error */ ErrorSet(ROCK_ERROR_UNKNOWN,"rock_fifo_conv_raw_bits2frame","Malloc returned NULL."); return ROCK_ERROR_UNKNOWN; } } else outdata->slv[i].els = NULL; } /* save data */ for (i=1; i<(nrels-1); i++) { ROCKF_SLAVE_bits slave; int a_nrels; ROCK_FIFO_SLV_data *a_el; /* element to write in */ rockf_nr2slave(rawels[i].fifodata,slave); a_nrels = outdata->slv[slave.slvadd].nrels++; a_el = &(outdata->slv[slave.slvadd].els[a_nrels]); a_el->channel = slave.channel; a_el->reserved = slave.reserved; a_el->data = slave.data; softparity ^= slave.parity; } } /*Set footer */ { ROCKF_FOOTER_bits footer; rockf_nr2footer(rawels[nrels-1].fifodata,footer); outdata->footer.last = footer.l; outdata->footer.hardparity = footer.parity; outdata->footer.softparity = softparity; } if (outdata->footer.hardparity!=outdata->footer.softparity) { /* report error, but do return the frame */ ErrorSetF(ROCK_ERROR_FIFO_FRAME_PARITY,"rock_fifo_conv_raw_bits2frame","Parity error: hard %i soft %i.", outdata->footer.hardparity,outdata->footer.softparity); return ROCK_ERROR_FIFO_FRAME_PARITY; } else return ROCK_ERROR_OK; } /**********************************************************************/ /* */ /* FIFO test routines */ /* */ /**********************************************************************/ int rock_fifo_isnotempty(ROCK_FIFO_id fifo_id) /* IN : fifo id */ { ROCKB_EDFIFO_bits flags; if (rock_fifo_cache_get_nrels(fifo_id)!=0) { /* if data is in cache, not empty */ return ROCK_ERROR_OK; } rock_fifo_flags(fifo_id,&flags); if (flags.ef==0) return ROCK_ERROR_FIFO_EMPTY; else return ROCK_ERROR_OK; }