/* lrf_list() - reads Cassini RPWS Low Rate Full Calibration Data sets and produces an ASCII text fields of the data. Written by Robert Johnson Date: December 20, 2003 */ #include #include #include #include #include #ifndef _Bool #define _Bool typedef enum {False,True} Bool; #endif #ifndef _Uchar #define _Uchar typedef unsigned char Uchar; /* char is assumed to be 8 bits */ #endif #ifndef _Uint #define _Uint typedef unsigned int Uint; /* int is assumed to be 32 bits, msb first */ #endif /* Bit patterns need to decode the 'nMode' field in the header */ #define RECEIVER_MASK 0xFF000000 /* */ #define MODE_MASK 0x00FFF000 /* */ #define ANT_MASK 0x00000FFF /* */ #define LFDR_Normal 0x71000000 /* low frequency digital receiver */ #define MFDR_Normal 0x72000000 /* medium frequency digital receiver */ #define MFR_Normal 0x11000000 /* medium frequency receiver */ #define MFR_FastToggle 0x12000000 /* medium frequency receiver */ #define HFR_Analysis 0x21000000 /* high frequency receiver */ #define HFR_Millisecond 0x28000000 /* high frequency receiver */ #define HFR_BandABC 0x00007000 /* high frequency receiver */ #define HFR_BandHf1 0x00008000 /* high frequency receiver */ #define HFR_BandHf2 0x00010000 /* high frequency receiver */ static Bool Lil_Indian; /* lsb first for intel machines */ static const char *sVersion="lrf_list(), version 1.2"; static const char *sHeaderFormat1="%21s %15s %17s\n"; static const char *sHeaderFormat2="%21s %15s %17s\n"; static const char *sDataFormat0="%21s %15.2f %#17.5G\n"; static const char *sDataFormat1="%21.3f %15.2f %#17.5G\n"; static const char *sDataFormat2="%21s %15.2f %#17.5G (bandwidth=%9.3f)\n"; static const char *sDataFormat3="%21.3f %15.2f %#17.5G (bandwidth=%9.3f)\n"; static float Lfdr_Bandwidth[32]={ /* in Hertz */ 0.2045, 0.2045, 0.2045, 0.2045, 0.2045, 0.2045, 0.2045, 0.2045, 0.2045, 0.2045, 0.2045, 0.2045, 0.2045, 0.2045, 0.2045, 0.2045, 0.2045, 0.2045, 0.2045, 0.2871, 0.5719, 0.5719, 0.7373, 0.7373, 1.0429, 1.0429, 1.3182, 1.4466, 1.8386, 2.0797, 2.5488, 2.6172 }; static float Mfdr_Bandwidth[32]={ /* in Hertz */ 14.6071, 14.6071, 14.6071, 14.6071, 14.6071, 14.6071, 14.6071, 14.6071, 14.6071, 14.6071, 14.6071, 14.6071, 14.6071, 14.6071, 14.6071, 14.6071, 14.6071, 14.6071, 14.6071, 20.5071, 40.8500, 40.8500, 52.6643, 52.6643, 74.4929, 74.4929, 94.1571, 103.3286, 131.3286, 148.5500, 182.0571, 186.9429 }; Bool Little_End_In_First(void); char* nScet_to_sScet(Uint nDoy,Uint nMsec); float *get_bandwidth(float *arFreq,Uint nItems,Uint nMode,Uchar *arMiniPkt); float get_hfr_ABC_bandwidth(Uchar *arMiniPkt); float get_hfr_HF1_bandwidth(Uchar *arMiniPkt); float get_hfr_HF2_bandwidth(Uchar *arMiniPkt); void show_help(FILE *h); int main(int argc,char *argv[]) { Bool bHeader=True,bData=True,bSilent=False,bVerbose=False; char *sFileName,sReceiver[32],sSensor[32],sDataQuality[128]; char sUnits[32],sUnitsName[32]; Uchar *pBuf,sTmp[128],*arHdr; int i,nUnits,nDataFormat; Uint *pDword; Uchar arMiniPkt[32]; Uint nRecLen,nNumRec,nItems,nMode,nDataQuality,nSensor; Uint nSclkSec,nSclkFine,nScetDays,nScetMils,nSclkPart; Uint nMsec; float *arFreq,*arTime,*arDens,*arBandWidth; FILE *hFile; size_t nRead; /* Initialize variables */ sFileName=NULL; nUnits=nDataFormat=0; while(--argc){ ++argv; if(!strcmp("-d",*argv)) bData=False; /* don't output data values */ else if(!strcmp("-h",*argv)) bHeader=False; /* don't output headers */ else if(!strcmp("-f",*argv)){ --argc; ++argv; nDataFormat=atoi(*argv); } else if(!strcmp("-u",*argv)){ --argc; ++argv; nUnits=atoi(*argv); } else if(!strcmp("-s",*argv)) bSilent=True; else if(!strcmp("-v",*argv)) bVerbose=True; else if(!strcmp("-help",*argv)){ show_help(stdout); exit(0); } else{ sFileName=*argv++; } } if(bVerbose==True) bSilent=False; /* check the byte order of the machine */ Lil_Indian=Little_End_In_First(); /* check to see if the sizes are what we think they are */ if( sizeof(Uchar) != 1 ){ fprintf(stderr,"unsigned char not one byte\n"); exit(1); } if( sizeof(Uint) != 4 ){ fprintf(stderr,"unsigned int not four byte\n"); exit(1); } if(bSilent==False) fprintf(stdout,"%s\n",sVersion); if(bVerbose==True) fprintf(stdout,"%s first machine\n",Lil_Indian==True?"Lsb":"Msb"); if(sFileName==NULL){ sFileName=calloc(strlen("stdin")+1,sizeof(char)); strcpy(sFileName,"stdin"); hFile=stdin; } else if( (hFile=fopen(sFileName,"rb"))==NULL ){ fprintf(stderr,"Unable to open %s.\n",sFileName); exit(1); } if(bVerbose==True) fprintf(stdout,"reading %s\n",sFileName); /* determine, the length and number of each record in the file */ if( fread(sTmp,sizeof(Uchar),16,hFile) != 16 ){ fprintf(stderr,"Error reading %s\n",sFileName); exit(1); } nRecLen=sTmp[8]; nRecLen<<=24; nRecLen|=((Uint)sTmp[9])<<16; /* explicitly promote to an 32 bit unsigned */ nRecLen|=((Uint)sTmp[10])<<8; /* quanity for non-ansi C compiliers. */ nRecLen|=((Uint)sTmp[11]); nNumRec=sTmp[12]; nNumRec<<=24; nNumRec|=((Uint)sTmp[13])<<16; nNumRec|=((Uint)sTmp[14])<<8; nNumRec|=((Uint)sTmp[15]); nItems=(nRecLen-16)/4; /* rewind file pointer to the beginning and read the entire header record */ fseek(hFile,(int)0,SEEK_SET); assert( (arHdr=calloc(nRecLen,sizeof(Uchar))) != NULL ); if( fread(arHdr,sizeof(Uchar),nRecLen,hFile) != nRecLen ){ fprintf(stderr,"Error reading %s\n",sFileName); exit(1); } nMode=arHdr[16]; nMode<<=24; /* receiver type and mode */ nMode|=((Uint)arHdr[17])<<16; nMode|=((Uint)arHdr[18])<<8; nMode|=((Uint)arHdr[19]); for(i=0;i<24;i++) /* mini-packet header, contains instrument mode */ arMiniPkt[i]=arHdr[24+i];/* information, see RPWS Users Guide for details */ switch(nMode&RECEIVER_MASK){ case LFDR_Normal: sprintf(sReceiver,"Lfdr"); break; case MFDR_Normal: sprintf(sReceiver,"Mfdr"); break; case MFR_Normal: sprintf(sReceiver,"Mfr Normal"); break; case MFR_FastToggle: sprintf(sReceiver,"Mfr Fast Toggle"); break; case HFR_Analysis: sprintf(sReceiver,"Hfr Analysis"); break; case HFR_Millisecond: sprintf(sReceiver,"Hfr Millisecond"); break; default: sprintf(sReceiver,"%08X",nMode); break; } /* sanity check */ assert( (pBuf=calloc(nRecLen,sizeof(Uchar))) != NULL ); if(bVerbose==True){ fprintf(stdout,"Record Length = %d (bytes), Number of Records = %d, " "and nItems = %d\n",nRecLen,nNumRec,nItems); fprintf(stdout,"first 80 bytes of the archive\n"); for(i=0;i<16;i++) fprintf(stdout,"%02X ",arHdr[i]); fprintf(stdout," "); for(i=0;i<16;i++) fprintf(stdout,"%c",((0x1F>16)&0x0FF; nSclkPart=((*pDword)>>24)&0x0FF; nScetDays=(*pDword++)&0x0FFFF; nScetMils=*pDword++; nDataQuality=*pDword++; nSensor=nDataQuality; nDataQuality&=0xFFFFFFF0; nSensor&= 0x0000000F; memcpy(arDens,pBuf+16,nRecLen-16); sDataQuality[0]='\0'; if(nDataQuality&0x80000000) strcat(sDataQuality,"Packet Errors "); if(nDataQuality&0x40000000) strcat(sDataQuality,"Hfr Sounder Active "); if(nDataQuality&0x20000000) strcat(sDataQuality,"Lp Raw Sweep Active "); if(nDataQuality&0x10000000) strcat(sDataQuality,"Ground Generated Data "); if(nSensor<=3){ /* Eu,Ev,Ex,Ew */ switch(nUnits){ case 1: strcpy(sUnitsName,"Power Flux"); strcpy(sUnits,"W/m**2/hz"); break; case 2: strcpy(sUnitsName,"Electric Field"); strcpy(sUnits,"V/m"); break; default: strcpy(sUnitsName,"Spectral Density"); strcpy(sUnits,"V**2/m**2/hz"); break; }/* hctiws */ } else if((4<=nSensor) && (nSensor<=6)){ /* Bx,ByBz */ switch(nUnits){ case 1: strcpy(sUnitsName,"Power Flux"); strcpy(sUnits,"nT**2/hz"); break; case 2: strcpy(sUnitsName,"Magnetic Field"); strcpy(sUnits,"nT"); break; default: strcpy(sUnitsName,"Spectral Density"); strcpy(sUnits,"nT**2/hz"); break; }/* hctiws */ } else{ strcpy(sUnits,"TBD"); switch(nUnits){ case 1: strcpy(sUnitsName,"Power Flux"); break; case 2: strcpy(sUnitsName,"Magnetic Field"); break; default: strcpy(sUnitsName,"Spectral Density"); break; }/* hctiws */ } switch(nSensor){ case 0: strcpy(sSensor,"Ex"); break; case 1: strcpy(sSensor,"Eu"); break; case 2: strcpy(sSensor,"Ev"); break; case 3: strcpy(sSensor,"Ew"); break; case 4: strcpy(sSensor,"Bx"); break; case 5: strcpy(sSensor,"By"); break; case 6: strcpy(sSensor,"Bz"); break; case 8: strcpy(sSensor,"Hf"); break; case 11: strcpy(sSensor,"Lp"); break; default: strcpy(sSensor,"unknown"); break; } if(nSclkPart==0) nSclkPart=1; if(bHeader==True){ fprintf(stdout,"%s %s %s 0x%08X.%02X\n",sSensor,sReceiver, nScet_to_sScet(nScetDays,nScetMils),nSclkSec,nSclkFine); if(sDataQuality[0]!='\0') fprintf(stdout," %s\n",sDataQuality); } if(bData==True){ if(bHeader==True){ fprintf(stdout,sHeaderFormat1,"S/C Event Time","Frequency",sUnitsName); fprintf(stdout,sHeaderFormat2,"UTC","hertz",sUnits); } arBandWidth=get_bandwidth(arFreq,nItems,nMode,arMiniPkt); if(nUnits==1){ /* Power Flux */ if(nSensor<=3){ /* Eu,Ev,Ex,Ew */ for(i=0;i= 24*60*60*1000){ nMsec-=(24*60*60*1000); ++nDoy; } ++nDoy; /* convert days since Jan. 1, 1958 [0-356] to day of year [1-366] */ nDays=365; nYear=1959; /* initial conditions 365 days in 1958 */ nTotal=nDays; while(nDoy>nTotal){ if(nYear%100) /* Year is NOT a century year */ nDays=(nYear%4)?365:366; /* if evenly divisible by 4, leap year */ else /* Year is a century year */ nDays=(nYear%400)?365:366; /* if evenly divisible by 400, leap year */ nTotal+=nDays; ++nYear; } nYear-=1; nTotal-=nDays; nDoy-=nTotal; /* days since jan 1 [0-365] */ nHour=nMsec/(1000*60*60); nMsec-=(nHour*1000*60*60); nMin= nMsec/(1000*60); nMsec-=(nMin*1000*60); nSec= nMsec/(1000); nMsec-=(nSec*1000); /* yyyy-doy T hh : mm : ss .mil */ sprintf(arStr,"%04d-%03dT%02d:%02d:%02d.%03d",nYear,nDoy, nHour,nMin,nSec,nMsec); return arStr; } /* float *get_bandwidth(float *arFreq,Uint nItems,Uint nMode,Uchar *arMiniPkt) This function takes calculates the bandwidth of the individual spectral density measurements. *arFreq array containing the frequencies of the measurements nItems number of elements in the frequency array nMode instrument id from the archive file header arMiniPkt engineering status of the receiver from the archive file header Returns: an array, nItems long, of bandwidths corresponding to the frequencies in arFreq. The units are in hertz. */ float *get_bandwidth(float *arFreq,Uint nItems,Uint nMode,Uchar *arMiniPkt) { int i; float *arBandWidth,fBandWidth,fUpper,fLower; assert((arBandWidth=calloc(nItems,sizeof(float))) !=NULL); if(LFDR_Normal==(nMode&RECEIVER_MASK)){ assert(nItems==32); for(i=0;i<32;i++) /* 32 log spaced channels */ arBandWidth[i]=Lfdr_Bandwidth[i]; /* center freq. range 0.19Hz-24.3Hz */ } else if(MFDR_Normal==(nMode&RECEIVER_MASK)){ assert(nItems==32); for(i=0;i<32;i++) /* 32 log spaced channels */ arBandWidth[i]=Mfdr_Bandwidth[i]; /* center freq. range 13.9Hz-1.7KHz */ } else if(MFR_Normal==(nMode&RECEIVER_MASK)){ assert(nItems==224); /* Normal Sweep Mode */ for(i=0;i<32;i++) /* band 1 sweeps 1 and 2 (16+16=32) */ arBandWidth[i]=5.6; /* center freq. range from 23.80Hz to 169.0Hz */ for(i=32;i<96;i++) /* band 2 sweeps 1 and 2 (32+32=64) */ arBandWidth[i]=19.4; /* center freq. range from 192.11Hz to 1.470KHz */ for(i=96;i<224;i++) /* band 3 sweeps 1,2,3, and 4 (32+32+32+32=128) */ arBandWidth[i]=139.0;/* center freq. range from 1.536KHz to 11.799KHz */ } else if(MFR_FastToggle==(nMode&RECEIVER_MASK)){ assert(nItems==112); /* Fast Toggle Mode */ for(i=0;i<16;i++) /* band 1 sweeps 1 (16) ) */ arBandWidth[i]=5.6; /* center freq. range from 23.80Hz to 169.0Hz */ for(i=16;i<48;i++) /* band 2 sweeps 1 (32) */ arBandWidth[i]=19.4; /* center freq. range from 192.11Hz to 1.470KHz */ for(i=48;i<112;i++) /* band 3 sweeps 1 and 2 (32+32=64) */ arBandWidth[i]=139.0;/* center freq. range from 1.536KHz to 11.799KHz */ } else if(HFR_Analysis==(nMode&RECEIVER_MASK)){ if(nMode&HFR_BandABC){ /* log spaced bandwidths */ fBandWidth=get_hfr_ABC_bandwidth(arMiniPkt);/* A 3685.61 - 15823.72 */ for(i=0;i