#!/bin/bash ######################################################################## ### Dump raw REX Output Frame from packet, stored in PDU of FITS file ### - byte-interleaved 5088-byte stream of bytes ### Reads label to get data offsets in FITS ### Read FITS data to make table ### Usage: newrex_dump_rof.bash __rawdata/rex_003031500?_0x7b3_eng_*.lbl ######################################################################## ### Extract ordinal-1 of 2880-byte FITS record from PDS label file ### e.g. extract the "13" from a line like this: ### ### ^EXTENSION_IQVALS_TABLE = ("REX_0030315000_0X7B3_ENG_1.FIT", 13) function getifitrec() { line=( `head -1 | tr '\" (),\r' ' '` ) echo "${line[3]}-1" } ######################################################################## ### Usage: headfit file.fit 12880 10000 ### - output 10000 bytes, starting at an offset of 2880 bytes past the ### 1st byte (ordinal byte 2881), from file file.fit start function headfit() { fit="$1" headbytes="$2" bytes="$3" head -${headbytes}c $fit \ | tail -c -$bytes } ### Main function while [ $# -gt 0 ] ; do ### Get and consume first command-line argument lbl="$1" ; shift ### Ensure end in .lbl [ "${lbl%.lbl}" == "$lbl" ] && ( echo "### Skipping $lbl" 1>&2 || true ) && continue ### Build FITS pathname from PDS label path name fit="${lbl%lbl}fit" ### Get 2880-byte FITS record offsets to PDU data let imgoffset=`grep '^ *[\^]IMAGE *= *(' "$lbl" | getifitrec` ### Calculate byte offsets let imgbyteoffset=2880*$imgoffset ### Determine IMAGE data lengths and other parameters ### - imgbytes: ROF: 5088 bytes let imgbytes=5088 ### Calculate total number of bytes from start of file to end of ### each BINTABLE let imgheadbytes=$imgbyteoffset+$imgbytes ### Set up local variables for assigning a description to each byte in stream ### - ID: Identifier byte ### - Status: status byte, 3 bits of which identify FPGA source stream ### - R[n][hi:lo]: hi to lo bits of 40-bit Radiometry; n is ordinal, 1-10 ### - T[n][hi:lo]: hi to lo bits of 24-bit Time Tag; n is ordinal, 1-10 ### - I[n][MSB], I[n][LSB] Q[n][MSB], Q[n][LSB]: ### MSBytes and LSBytes of 16-bit IQ Values; n is ordinal of value, 1-1250 ### MSBytes and LSBytes of IQ Values ### - Spare: spares; last six bytes of strem iqpfx=( I I Q Q ) iqsfx=( MSB LSB MSB LSB ) rtpfx=( R R R R R T T T ) rtsfx=( 39:32 31:24 23:16 15:08 07:00 23:16 15:08 07:00 ) iqlen=${#iqsfx[*]} rtlen=${#rtpfx[*]} ### Maintain count of IQ and RT (Radiometry or Time Tag) bytes encountered let nextIQ0=0 let nextRT0=0 ### Maintain count of bytes (rows of data) encountered nextrow0=0 ### Pipe 5088 raw bytes from FITS file ### - to od to convert to ASCII unsigned 1-byte integers one per line, then ### - to while-read loop to add a description to each line, then ### - to GAWK for formatting headfit $fit $imgheadbytes $imgbytes \ | od -v -w1 -t u1 \ | while read pfx u1 xxx ; do ### while-read loop parses and print out data from od command above ### - pfx is the octal offset from od ### - u1 is the bytes ### - row0 is the offset from the first byte ### If no second item, do nothing [ "$u1" ] || continue ### print out -t u1 (unsigned 1-byte decimals) from echo -n "$u1 " let row0=$nextrow0 let ++nextrow0 ### Deal with first six and last six bytes: ID, Status, first IQ pair, spares case $row0 in 0) echo "ID" ; continue ;; 1) echo "I[1][MSB]" ; continue ;; 2) echo "I[1][LSB]" ; continue ;; 3) echo "$u1" | gawk '{printf "Status [0x%02x => ", $1}' ### Parse bits 6:4 of u1 value to identify FPGS source stream let status=($u1/16)\&7 case $status in 0) echo "ADC output from NH receiver]" ;; 1) echo "Impulse]" ;; 2) echo "Low-f square wave]" ;; 3) echo "Mid-f square wave]" ;; 4) echo "PRN +/-1]" ;; 5) echo "PRN full scale]" ;; 6) echo "High-f square wave]" ;; 7) echo "All zeroes]" ;; *) echo "Unknown]" ;; esac continue ;; 4) echo "Q[1][MSB]" ; continue ;; 5) echo "Q[1][LSB]" ; let nextIQ0=4 ; continue ;; 508[2-7]) echo "Spare" ; continue ;; ### This is not one of the first or last six bytes; drop through *) true ;; esac ### After the sixth byte, the interleaving repeats on 508-byte periods let rowm6=($row0-6)%508 ### If this is within the first 21 bytes, then this row's byte may ### be RT (Radiometry or Time Tag) if [ $rowm6 -lt 21 ] ; then ### if rowm6 is a multiple of 3, it is RT let rowm6mod3=$rowm6%3 if [ $rowm6mod3 -eq 0 ] ; then ### step through 8-element RT prefix array rtpfx=(R R R R R T T T T) ### and suffix array=(39:32 31:24, ...) i.e. bit boundaries ### - rtidx is index within rtpfx and rtsfx ### - rtord is the ordinal of this RT value (not byte) within ### the entire 5088-byte stream let rtidx=$nextRT0%8 let rtord=($nextRT0/8)+1 ### output Radiometry or Time Tag description e.g. R[5][23:15] echo "${rtpfx[$rtidx]}[$rtord][${rtsfx[$rtidx]}]" ### Increment count of RT bytes encountered so far let ++nextRT0 continue fi fi ### To here this is an I or Q value; step through 4-element prefix and ### suffix arrays let iqidx=$nextIQ0%4 let iqord=($nextIQ0/4)+1 ### output IQ description e.g. Q[1234][LSB] echo "${iqpfx[$iqidx]}[$iqord][${iqsfx[$iqidx]}]" ### Increment count of IQ bytes encountered so far let ++nextIQ0 ### Pipe while-read loop to gawk to format first two columns and append ### description for each row done \ | gawk '{s="";for(i=2;i<=NF;++i){ s=s " " $i}printf "%5d%5d %s\n", FNR, $1, s }' done exit 0