Analysis‎ > ‎

Mode3 Unpack

Sample GRETINA Mode3 (Raw Data) Unpacking Code

This is a sample bit of code that properly unpacks raw GRETINA data, with the format as described for GEB header type = 2 (see GEB Headers). Obviously not the only way to code this, but it does the job.


#define MAX_TRACE_LENGTH 2048

struct mode3DataPacket {
	unsigned short aahdr[2]; 
	unsigned short hdr[14]; 
	unsigned short waveform[MAX_TRACE_LENGTH]; 
};

struct GEBHeader {
	int32_t type; 
	int32_t length;  /* length of payload following the header, in bytes */
	int 64_t timestamp; 
}

GEBHeader gHeader;
mode3DataPacket *dp;

unsigned char gBuf[32*32*1024] = {0};
unsigned char *tmp;

unsigned int mode3i = 0;


Included below is the code snippet using the structures/variables defined above to unpack GRETINA Mode3 data. This assumes a global header has been read into the gHeader structure, and will result in unpacking all GRETINA channel events following a single global header.


int siz = fread(gBuf, gHeader.length, 1, inputFile);
if (siz != 1) {
	cerr << "Error reading GRETINA data.  Aborting now... " << endl;
	exit;
}

for (int j=0; j<gHeader.length; j++) { swap(*(gBuf + j), *(gBuf + j + 1)); }

mode3i = 0;
while( (int)(mode3i*2) < gHeader.length ) {

	tmp = (gBuf + mode3i*2);

	if !(dp = (mode3DataPacket*)malloc(sizeof(dp->aahdr) + sizeof(dp->hdr) +
	            sizeof(dp->waveform))) ) { exit(-1); }
	memset(dp->waveform, 1, gMode3.tracelength*sizeof(unsigned short));

	memmove(&dp->aahdr[0], tmp, (sizeof(dp->hdr) + sizeof(dp->aahdr)));
	if ((dp->aahdr[0] != 43690) || (dp->aahdr[1] != 43690)) {
		cerr << "Didn't find 'AAAA' header as expected!" << endl;
	}

	mode3i += (sizeof(dp->aahdr) + sizeof(dp->hdr))/2;
	gMode3->tracelength = (((dp->hdr[0] & 0x7ff))*2) - 14;
	tmp = (gBuf + mode3i*2);
	memmove(&dp->waveform[0], tmp, gMode3->tracelength*sizeof(unsigned short));

	mode3i += (gMode3->tracelength*sizeof(unsigned short))/2;
	tmp = (gBuf + mode3i*2);
    
	/* Interpret the header information... */
	gMode3->board_id = (dp->hdr[0] >> 11);
	gMode3->chan_id = (dp->hdr[1] & 0xf);
	gMode3->module = (dp->hdr[1] >> 4);
    
	if (gMode3->module/16 == Q1) {
		gMode3->id = (gMode3->module - (Q1-Q1E)*4*4)*10 + gMode3->chan_id;
	} else if (gMode3->module/16 == Q2) {
		gMode3->id = (gMode3->module - (Q2-Q2E)*4*4)*10 + gMode3->chan_id;
	} else if (gMode3->module/16 == Q3) {
		gMode3->id = (gMode3->module - (Q3-Q3E)*4*4)*10 + gMode3->chan_id;
	} else if (gMode3->module/16 == Q4) {
		gMode3->id = (gMode3->module - (Q4-Q4E)*4*4)*10 + gMode3->chan_id;
	} else if (gMode3->module/16 == Q5) {
		gMode3->id = (gMode3->module - (Q5-Q5E)*4*4)*10 + gMode3->chan_id;
	} else if (gMode3->module/16 == Q6) {
		gMode3->id = (gMode3->module - (Q6-Q6E)*4*4)*10 + gMode3->chan_id;
	} else if (gMode3->module/16 == Q7) {
		gMode3->id = (gMode3->module - (Q7-Q7E)*4*4)*10 + gMode3->chan_id;
	} else {
		gMode3->id = (gMode3->module)*10 + gMode3->chan_id;
	}
    
	int hienergy = 0;
	hienergy = (dp->hdr[7] & 0x00ff);
	bool sign = 0;
	sign = (dp->hdr[7] & 0x0100);
    
	assert( (((hienergy) << 16) & (uint)(0xff000000)) == 0);
	uint tmp_energy = 0;
	int tmp_int_energy = 0;
	tmp_energy = ((uint)(hienergy) << 16);
	tmp_energy += dp->hdr[4];
	assert((tmp_energy & 0xff000000) == 0);
    
	tmp_int_energy = (int)(tmp_energy);
	assert((tmp_int_energy & 0xff000000) == 0);
    
	if (sign) {
		if ( (((int)(gMode3->id)%10) == 9) ) { /* CC */
			tmp_int_energy = (int)(tmp_int_energy - (int)0x01000000);
		} else {
			tmp_int_energy = (int)(tmp_int_energy - (int)0x01000000);
			tmp_int_energy = -(int)(tmp_int_energy);
		}
	} else {
		if ( (((int)(gMode3->id)%10) == 9) ) { /* CC */
			tmp_int_energy = (int)(tmp_int_energy);
		} else {
			tmp_int_energy = -(int)(tmp_int_energy);
		}
	}
    
	gMode3->mask |= 0x0001;
	gMode3->mask |= 0x0002;
	gMode3->energy = (tmp_int_energy/32);
   
	gMode3->mask |= 0x0004;
	gMode3->cfd_timestamp = 0;
	gMode3->led_timestamp = 0;
	gMode3->cfd_timestamp = (ULong64_t)((ULong64_t)(dp->hdr[6]) +
											((ULong64_t)(dp->hdr[9]) << 16) +
											((ULong64_t)(dp->hdr[8]) << 32));
	gMode3->mask |= 0x0008;
	gMode3->led_timestamp = (ULong64_t)((ULong64_t)(dp->hdr[3]) +
											((ULong64_t)(dp->hdr[2]) << 16) +
											((ULong64_t)(dp->hdr[5]) << 32));

	gMode3->waveform.clear();
	for (int j=0; j<gMode3->tracelength; j++) {
		if (dp->waveform[j] & 0x8000) {
			if (gMode3->id%10 == 9) {
				gMode3->waveform.push_back(dp->waveform[j] -
																std::numeric_limits<unsigned int>::max());
			} else {
				gMode3->waveform.push_back((-(dp->waveform[j] -
																std::numeric_limits<unsigned int>::max())));
			}	
		} else {
			if (gMode3->id%10 == 9) {
				gMode3->waveform.push_back(dp->waveform[j]);
			} else {
				gMode3->waveform.push_back((-(dp->waveform[j])));
			}
		}
	}
	for (int j=0; j<(gMode3->tracelength+1); j+=2) {
		swap(gMode3->waveform[j], gMode3->waveform[j+1]);
	}

	free(dp);

} /* End of while( (int)(mode3i*2) < gHeader.length ) */

Comments