/* 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 <stdio.h> #include <stdlib.h> #include <string.h> #include <math.h> #include <assert.h> #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<arHdr[i])&&(arHdr[i]<0x7F)) ? arHdr[i] : '.'); fprintf(stdout,"\n"); for(i=16;i<32;i++) fprintf(stdout,"%02X ",arHdr[i]); fprintf(stdout," "); for(i=16;i<32;i++) fprintf(stdout,"%c",((0x1F<arHdr[i])&&(arHdr[i]<0x7F)) ? arHdr[i] : '.'); fprintf(stdout,"\n"); for(i=32;i<48;i++) fprintf(stdout,"%02X ",arHdr[i]); fprintf(stdout," "); for(i=32;i<48;i++) fprintf(stdout,"%c",((0x1F<arHdr[i])&&(arHdr[i]<0x7F)) ? arHdr[i] : '.'); fprintf(stdout,"\n"); for(i=48;i<64;i++) fprintf(stdout,"%02X ",arHdr[i]); fprintf(stdout," "); for(i=48;i<64;i++) fprintf(stdout,"%c",((0x1F<arHdr[i])&&(arHdr[i]<0x7F)) ? arHdr[i] : '.'); fprintf(stdout,"\n"); for(i=64;i<80;i++) fprintf(stdout,"%02X ",arHdr[i]); fprintf(stdout," "); for(i=64;i<80;i++) fprintf(stdout,"%c",((0x1F<arHdr[i])&&(arHdr[i]<0x7F)) ? arHdr[i] : '.'); fprintf(stdout,"\n"); } /* move to the beginning of the second record, time record */ fseek(hFile,(int)nRecLen,SEEK_SET); if( fread(pBuf,sizeof(Uchar),nRecLen,hFile) != nRecLen ){ fprintf(stderr,"Error reading %s\n",sFileName); exit(1); } assert( (arTime=calloc(nItems,sizeof(float))) != NULL ); if(Lil_Indian==True){ /* reorder the IEEE Float so the LSB is first */ Uchar *p=pBuf; /* b4 b3 b2 b1 becomes b1 b2 b3 b4 */ for(i=0;i<nRecLen;i+=4,p+=4){ *(p+0)^=*(p+3); *(p+3)^=*(p+0); *(p+0)^=*(p+3); *(p+1)^=*(p+2); *(p+2)^=*(p+1); *(p+1)^=*(p+2); } } /* skip the first 16 bytes of information, sclk, scet, etc and put the time offset from beginning of capture in an array */ memcpy(arTime,pBuf+16,nRecLen-16); /* read the third record, frequency */ if( fread(pBuf,sizeof(Uchar),nRecLen,hFile) != nRecLen ){ fprintf(stderr,"Error reading %s\n",sFileName); exit(1); } assert( (arFreq=calloc(nItems,sizeof(float))) != NULL ); if(Lil_Indian==True){ /* reorder the IEEE Float so the LSB is first */ Uchar *p=pBuf; /* b4 b3 b2 b1 becomes b1 b2 b3 b4 */ for(i=0;i<nRecLen;i+=4,p+=4){ *(p+0)^=*(p+3); *(p+3)^=*(p+0); *(p+0)^=*(p+3); *(p+1)^=*(p+2); *(p+2)^=*(p+1); *(p+1)^=*(p+2); } } memcpy(arFreq,pBuf+16,nRecLen-16); assert( (arDens=calloc(nItems,sizeof(float))) != NULL ); while( (nRead=fread(pBuf,sizeof(Uchar),nRecLen,hFile)) == nRecLen ){ if(Lil_Indian==True){ /* reorder the IEEE Float so the LSB is first */ Uchar *p=pBuf; /* b4 b3 b2 b1 becomes b1 b2 b3 b4 */ for(i=0;i<nRecLen;i+=4,p+=4){ *(p+0)^=*(p+3); *(p+3)^=*(p+0); *(p+0)^=*(p+3); *(p+1)^=*(p+2); *(p+2)^=*(p+1); *(p+1)^=*(p+2); } } /* the beginning of each record contains the time information */ pDword=(Uint*)pBuf; nSclkSec=*pDword++; nSclkFine=((*pDword)>>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<nItems;i++) /* divide by the impedance of free space */ arDens[i]/=377.0; } }/* fi power flux */ else if(nUnits==2){ /* Electric and Magnetic Field Strength */ for(i=0;i<nItems;i++){ if(arDens[i]<0.0){/* negative data indicates interference present */ arDens[i]*=-1.0; arDens[i]=sqrt(arDens[i]*arBandWidth[i]); arDens[i]*=-1.0; } else{ arDens[i]=sqrt(arDens[i]*arBandWidth[i]); } } } else{ /* spectral density */ ; /* do nothing */ } if(nDataFormat==1){ /* time is seconds from beg. of capture */ for(i=0;i<nItems;i++){ fprintf(stdout,sDataFormat1,arTime[i],arFreq[i],arDens[i]); } } else if(nDataFormat==2){ /* time is scet, include bandwidths */ for(i=0;i<nItems;i++){ nMsec=nScetMils+(Uint)(arTime[i]*1000); fprintf(stdout,sDataFormat2,nScet_to_sScet(nScetDays,nMsec), arFreq[i],arDens[i],arBandWidth[i]); } } else if(nDataFormat==3){ /* time is second, include bandwidths */ for(i=0;i<nItems;i++){ fprintf(stdout,sDataFormat3,arTime[i],arFreq[i],arDens[i], arBandWidth[i]); } } else{ /* time is scet, include bandwidths */ for(i=0;i<nItems;i++){ nMsec=nScetMils+(Uint)(arTime[i]*1000); fprintf(stdout,sDataFormat0,nScet_to_sScet(nScetDays,nMsec), arFreq[i],arDens[i]); } } }/* fi data */ }/* end of while reading records */ /* check nRead for errors here */ return 0; } /* check to see if the byte order is lsb or msb first */ Bool Little_End_In_First(void) { Bool bStatus; Uchar buf[4]={0x0C,0x00,0x00,0x00}; Uint *p; p=(Uint*)buf; if(*p==0x0C) bStatus=True; /* Lsb first */ else bStatus=False; /* Msb first */ return bStatus; } /* Converts the standard JPL binary scet into a string. nDoy - is the number of days since Jan. 1, 2958 nMsec - is the milliseconds since the beginning of the day pSin - is a pointer to the return string. If pSin is a NULL pointer, the string is statically stored in the function. Returns: A pointer to the standard JPL spacecraft event time format. year-doyThh:mm:ss.mil */ char* nScet_to_sScet(Uint nDoy,Uint nMsec) { int nYear,nHour,nMin,nSec; int nDays,nTotal; static char arStr[32]; /* normalize the incomming data */ while(nMsec>= 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<nItems;i++){ /* B 16585.23 - 71206.73 */ fUpper=fLower=log10(arFreq[i]); /* C 74633.53 - 320430.31 */ fLower-=fBandWidth/2.0; fUpper+=fBandWidth/2.0; arBandWidth[i]=pow(10.0,fUpper)-pow(10.0,fLower); } } else if(nMode&HFR_BandHf1){ /* 25KHz/filters */ for(i=0;i<nItems;i++) /* 100KHz - 4.xMHz */ arBandWidth[i]=get_hfr_HF1_bandwidth(arMiniPkt); } else if(nMode&HFR_BandHf2){ /* 25KHz/filters */ for(i=0;i<nItems;i++) /* 100KHz - 16.xMHz */ arBandWidth[i]=get_hfr_HF2_bandwidth(arMiniPkt); } else{ for(i=0;i<nItems;i++) arBandWidth[i]=1.0; /* this should never be executed */ } } else if(HFR_Millisecond==(nMode&RECEIVER_MASK)){ for(i=0;i<nItems;i++) /* 25KHz/filters */ arBandWidth[i]=25.0E3; } else{ for(i=0;i<nItems;i++) arBandWidth[i]=1.0; /* this should never be executed */ } return arBandWidth; } float get_hfr_ABC_bandwidth(Uchar *arMiniPkt) { int i; static int first_time; static float bandA[3][32]; static float bandB[3][32]; static float bandC[3][32]; float fBandWidth; if(!first_time){ /* generate the hfr band ABC frequencies */ ++first_time; for(i=0;i<8;i++){ /* hfr band ABC frequencies, 8 filters */ bandA[0][i]=3.6*pow(4.5,(0.5+i)/8)*1.0E3; bandB[0][i]=3.6*pow(4.5,(0.5+i+8)/8)*1.0E3; bandC[0][i]=3.6*pow(4.5,(0.5+i+16)/8)*1.0E3; } for(i=0;i<16;i++){ /* hfr band ABC freqencies, 16 filters */ bandA[1][i]=3.6*pow(4.5,(0.5+i)/16)*1.0E3; bandB[1][i]=3.6*pow(4.5,(0.5+i+16)/16)*1.0E3; bandC[1][i]=3.6*pow(4.5,(0.5+i+32)/16)*1.0E3; } for(i=0;i<32;i++){ /* hfr band ABC frequencies 32 filters */ bandA[2][i]=3.6*pow(4.5,(0.5+i)/32)*1.0E3; bandB[2][i]=3.6*pow(4.5,(0.5+i+32)/32)*1.0E3; bandC[2][i]=3.6*pow(4.5,(0.5+i+64)/32)*1.0E3; } }/* fi not first time */ /* the hfr band A,B,C consists of N logrithmicly spaced channels */ /* for lots of details of decoding the mini-packet header, refer */ /* to the RPWS Users Guide. All that we are interested is wheither */ /* the hfr was in 8, 16, or 32 filter mode */ if(!(arMiniPkt[9]&0x07)){ /* sanity check: Band A, B, or C selected */ return 0; } if((arMiniPkt[14]&0x03)==0x00){ /* 8 filters per band */ fBandWidth=log10(bandA[0][1])-log10(bandA[0][0]); /* ~0.08165 */ } else if((arMiniPkt[14]&0x03)==0x01){ /* 16 filters per band */ fBandWidth=log10(bandA[1][1])-log10(bandA[1][0]); /* ~0.04083 */ } else{ /* bit patterns 0x03 and 0x02 imply 32 filters per band */ fBandWidth=log10(bandA[2][1])-log10(bandA[2][0]); /* ~0.02041 */ } /* since Bands A,B,C are log spaced, it doesn't matter which we choose. The calculation for bandwidth of a frequency of ABC becomes is a constant delta, in log space. */ return fBandWidth; } float get_hfr_HF1_bandwidth(Uchar *arMiniPkt) { int nFilters=0; if(!(arMiniPkt[9]&0x08)){ /* sanity check: Band Hf1 selected */ return 0.0; } if((arMiniPkt[15]&0x03)==0x00) /* 1 filters per band */ nFilters=1; else if((arMiniPkt[15]&0x03)==0x01) /* 2 filters per band */ nFilters=2; else if((arMiniPkt[15]&0x03)==0x02) /* 4 filters per band */ nFilters=4; else if((arMiniPkt[15]&0x03)==0x03) /* 8 filters per band */ nFilters=8; return 25.0E3/nFilters; /* Bandwidth in KHz */ } float get_hfr_HF2_bandwidth(Uchar *arMiniPkt) { int nFilters=0; if(!(arMiniPkt[9]&0x10)){ /* sanity check: Band Hf2 selected */ return 0.0; } if((arMiniPkt[16]&0x03)==0x00) /* 1 filters per band */ nFilters=1; else if((arMiniPkt[16]&0x03)==0x01) /* 2 filters per band */ nFilters=2; else if((arMiniPkt[16]&0x03)==0x02) /* 4 filters per band */ nFilters=4; else if((arMiniPkt[16]&0x03)==0x03) /* 8 filters per band */ nFilters=8; return 25.0E3/nFilters; /* Bandwidth in KHz */ } void show_help(FILE *h) { if(h==NULL) h=stdout; fprintf(stdout,"usage: %s [OPTIONS] [FILENAME]\n",sVersion); fprintf(stdout, " lrf_list() reads RPWS Cassini Low Rate Full Calibration PDS Archive files " "*.DATk. If FILENAME is not supplied on the command line, then stdin is " "assumed." ); fprintf(stdout, "OPTIONS:\n" " -d don't output data samples\n" " -h don't output header information\n" " -f NNN output format, default NNN=0\n" " 0 s/c event time (utc) in the form 2003-175T12:45:59.246\n" " 1 offset from beginning of capture, 5.345 seconds\n" ); fprintf(stdout, " -u NNN units for the data samples, default NNN=0\n" " 0 spectral density [V^2/m^2/Hz] and [nT^2/Hz]\n" " 1 power flux [W/m^2/Hz] and [nT^2/Hz]\n" " 2 field [V/m] and [nT]\n" " -s silent operation, don't output error mesasges\n" " -v verbose operation, be verbose in the output\n" ); return; }