#include "common.h" #include "message.h" #include #include #include #include #ifdef UNIX #include #include #include #include #include #include #include #include #include #endif #include // taken from transfer.h typedef struct block_header { /* format of data block */ unsigned short hdr_flags; /* see below */ unsigned short hdr_stream; /* =0 for forced ack request or 1=>MAX_STREAM */ unsigned short hdr_endian; /* data byte order */ unsigned short hdr_spare; unsigned int hdr_sequence; /* for this stream */ unsigned int hdr_blocklength; /* total length of this block including the header */ unsigned int hdr_datalength; /* length of user data in the block */ unsigned int hdr_offset; /* very large blocks may be fragmented */ unsigned int hdr_id1; /* for spy to locate header =0x19062002 */ unsigned int hdr_id2; /* for spy to locate header =0x09592400 */ } HEADER; #define HDR_ID1 0x19062002 #define HDR_ID2 0x09592400 // format of the data buffer area header #define NBLOCKS 64 /* current number of buffers used - must be 2**n */ #define MAX_BUFFERS 128 /* unchangeable maximum because of header structure */ typedef struct s_buffer_header { int buffer_offset; // offset to first buffer int buffer_number; // number of buffers int buffer_length; // length of buffers int buffer_next; // next buffer to be written int buffer_max; // MAX_BUFFERS int buffer_spare1; int buffer_spare2; int buffer_spare3; #ifdef WIN32 long buffer_currentage; long padding1; long buffer_age[MAX_BUFFERS]; long padding2[MAX_BUFFERS]; #else long long buffer_currentage; long long buffer_age[MAX_BUFFERS]; #endif int buffer_status[MAX_BUFFERS]; } BUFFER_HEADER; #include "alloc_data_area.h" #define MAXSTREAMS 32 // address of shared buffer area void * shm_bufferarea; int shmkey = 110205; extern int TransferSize[]; int tape_block_size = 0; extern int Tcp_Port[]; extern int OutFlag; extern FILE* OutStream; char spinner[4]; int spin = 0; int traceflag = 1; int BlockSequence[MAXSTREAMS] = {0,0,0,0,0,0,0,0}; int EventSequence[MAXSTREAMS] = {0,0,0,0,0,0,0,0}; unsigned long long TimeStampF = 0; void checkDATAbuffer(int, char*, int); void printbufferL(char*, int); void delay(int DelayTicks) { struct timespec time_request; time_request.tv_sec = DelayTicks/1000; time_request.tv_nsec = (DelayTicks - (time_request.tv_sec * 1000)) * 1000000; (void) nanosleep(&time_request, NULL); } void initialise_buffer_area() { int i; BUFFER_HEADER * baseaddress; if (tape_block_size < TransferSize[0]) { shm_bufferarea = alloc_data_area(shmkey, (TransferSize[0] * NBLOCKS) + sizeof(BUFFER_HEADER)); tape_block_size = TransferSize[0]; } baseaddress = (BUFFER_HEADER *) shm_bufferarea; baseaddress->buffer_offset = sizeof(BUFFER_HEADER); baseaddress->buffer_number = NBLOCKS; baseaddress->buffer_length = tape_block_size; baseaddress->buffer_next = 0; baseaddress->buffer_max = MAX_BUFFERS; baseaddress->buffer_currentage = 0; for (i = 0; i < MAX_BUFFERS; i++) baseaddress->buffer_status[i] = 0; for (i = 0; i < MAX_BUFFERS; i++) baseaddress->buffer_age[i] = 0; spinner[0] = '-'; // Note - initialised like this because of problems with GNU compiler spinner[1] = '\\'; spinner[2] = '|'; spinner[3] = '/'; } void store_buffer (int stream, int endian, char * p, int l) { DATA_HEADER data_header; BUFFER_HEADER * baseaddress; char * bufferaddress; int offset, length; int i; int block_len = tape_block_size; if ( (unsigned int)(l + sizeof(DATA_HEADER)) > (unsigned int) block_len ) { l = block_len - sizeof(DATA_HEADER); } // construct 24 byte block header memcpy (data_header.header_id,"EBYEDATA",8); data_header.header_sequence = 0; data_header.header_stream = stream; data_header.header_tape = 0; data_header.header_MyEndian = 1; data_header.header_DataEndian = endian; data_header.header_dataLen = l; // copy the buffer into the data buffer area in shared memory baseaddress = (BUFFER_HEADER *) shm_bufferarea; // set the age of the buffer to be written as zero i = baseaddress->buffer_next; baseaddress->buffer_age[i] = 0; // calculate the address of the buffer to use and copy the data offset = baseaddress->buffer_offset; length = baseaddress->buffer_length; bufferaddress = (char *) ((char *)shm_bufferarea + offset + (length * i)); memcpy (bufferaddress, data_header.header_id, sizeof(DATA_HEADER)); memcpy (bufferaddress + sizeof(DATA_HEADER), p, l); // set the age of the buffer and increment the age and the next buffer baseaddress->buffer_age[i] = baseaddress->buffer_currentage; baseaddress->buffer_currentage++; baseaddress->buffer_next = ((baseaddress->buffer_next + 1) & (NBLOCKS - 1)); if (OutFlag != 0) fwrite(bufferaddress, 1, block_len, OutStream); } int ts_data_transfer(int /*stream*/, int endian, char * ptr, int len) { HEADER* p; int stream; if (tape_block_size != TransferSize[0]) {initialise_buffer_area();} // check block sequence number p = (HEADER*) (ptr-sizeof(HEADER)); stream = p->hdr_spare; if (ntohl(p->hdr_sequence) == BlockSequence[stream]) { BlockSequence[stream]++; // good } else { printf ("%d: block sequence error: expected %d; received %d\n", stream, BlockSequence[stream], ntohl(p->hdr_sequence)); BlockSequence[stream] = ntohl(p->hdr_sequence)+1; } if (ntohl(p->hdr_datalength) != len) {printf("check#1: %d %d\n",ntohl(p->hdr_datalength),len);} if (len + 32 > ntohl(p->hdr_blocklength)) {printf("check#2: %d %d\n",ntohl(p->hdr_blocklength),len);} if (ntohl(p->hdr_id1) != HDR_ID1) {printf("check#3: 0x%x\n",ntohl(p->hdr_id1));} if (ntohl(p->hdr_id2) != HDR_ID2) {printf("check#4: 0x%x\n",ntohl(p->hdr_id2));} if (len > ((64*1024)-32)) {printf("%d: Unexpected block length %d\n",stream,len); return(0);} printbufferL((char *)ptr, len); checkDATAbuffer(stream, ptr, len); store_buffer(stream, 1, ptr, len); printf ("%c\b", spinner[spin]); fflush(NULL); if (++spin == 4) spin=0; return (0); } void checkDATAbuffer(int stream, char* p, int l) { int len; int module, channel, dataID; int group, item; int traceflag; int trace_data , trace_sync , trace_wave; unsigned int chan; unsigned int * eventbuffer; unsigned int data; unsigned short adc; unsigned short samplelength; unsigned short icode; unsigned int ifield; unsigned int timestamp; int i; int count; unsigned long long timestampf; unsigned long long timemark; traceflag = 1; trace_data = 1 ; trace_sync = 1 ; trace_wave = 1; len = l/4; eventbuffer = (unsigned int *)p; if (trace_data) { printf("buffer len=%d\n",len); printf(">"); for (i = 0; i < 32; i++) { printf("0x%08lx ", eventbuffer[i]); } printf("\n"); } len = l/4; /* len in units of int */ eventbuffer = (unsigned int *)p; if(traceflag) printf("%d: Block received length %d\n", stream, len ); while (len >= 2) { data = *eventbuffer++; len--; timestamp = *eventbuffer++; len--; switch ((data >> 30 ) & 3) { case 3: /* ADC data word */ module = (data >> 24) & 31; dataID = (data >> 22) & 3; channel = (data >> 16) & 63; adc = (unsigned short) (data & 0x0000ffff); timestampf = ((unsigned long long) timemark & 0xfffffffff0000000) | (unsigned long long) (timestamp & 0x0fffffff); if (traceflag && trace_data ) printf("%d: adc data: 0x%04x module %d; channel %d; ID %d: 0x%08lx 0x%016llx\n",stream, adc, module, channel, dataID, timestamp, timestampf); break; case 2: /* information data word */ icode = (data >> 20) & 0x0f; /* information code */ ifield = data & 0x000fffff; /* information field */ module = (data >> 24) & 0x3f; switch (icode) { case 2: /* PAUSE timestamp */ if (traceflag && trace_sync ) printf("%d: received PAUSE: m=%d, ts=0x%08lx 0x%08lx\n",stream, module, ifield, timestamp); break; case 3: /* RESUME timestamp */ if (traceflag && trace_sync) printf("%d: received RESUME: m=%d, ts=0x%08lx 0x%08lx\n",stream, module, ifield, timestamp); break; case 4: /* SYNC100 timestamp */ timemark = ((unsigned long long) ifield << 28) | (unsigned long long) timestamp; if (traceflag && trace_sync) printf("%d: received TIMEMARK: m=%d, ts=0x%08lx 0x%08lx 0x%016llx\n",stream, module, ifield, timestamp, timemark); break; default: /* undefined code */ printf("%d: received undefined information code: %d\n",stream, icode); break; } break; case 1: /* sample data */ samplelength = (unsigned short) (data & 0x0000ffff); if (samplelength > (len * 2)) { printf("%d: bad wave data buffer (%d > %d)\n",module, samplelength, len*2); len = 0; break; } if (samplelength & 3 != 0) { printf("%d: bad wave data buffer (%d)\n",module, samplelength); len = 0; break; } printf("%d: wave data buffer len = %d\n",module, samplelength); for (i=0; i<(samplelength/2); i++) {len--; eventbuffer++;} break; case 0: /* bad format */ default: printf("%d: bad event data (%d %d) - (0x%08lx 0x%08lx)\n", stream, l/4, len, data, timestamp); len = 0; break; } } /* end of while */ } void printbufferL(char* p, int l) { int len; int i, j; unsigned int * eventbuffer; len = l/4; /* len in units of int */ eventbuffer = (unsigned int *)p; printf("buffer len=%d bytes\n",l); printf(">\n"); for (j=0;j<16;j++) { for (i=0;i<8;i++) {printf("0x%08lx ", *eventbuffer++);} printf("\n"); } }