;+ ;Function: THM_UNPACK_HED ; thm_unpack_hed, data_type, hed_array ; ;Purpose: Unpacks data packed into HED data. ; ;Arguements: ; DATA_TYPE STRING, one of the L1 data types (eff, scp, fbk, etc.) ; HED_ARRAY BYTE[ N, 16], array of header data. ; ;keywords: ; None. ; ;Example: ; get_data, 'tha_fit_hed', data=d_hed ; hed_data = thm_unpack_hed( 'fit', d_hed.y) ; ;Notes: ; -- Returns int( 0) if requested DATA_TYPE is not implemented. ; -- Returns annonymous structure with variable elements if DATA_TYPE is recognized. ; -- Not all DATA_TYPEs are implemented; implemented data types (APIDs) listed below: ; FIT (on-board EFI and FGM spin fits, 410), ; FBK (FilterBank data, 440), ; EFI waveform (VA?, VB?, EF?; 441,442,443, 445,446,447, 449,44A,44B), ; SCM waveform (SCF, SCP, SCW; 444; 448; 44C), ; FGM waveform (FGL, FGH; 460, 461), ; FFT spectra (FFP, FFW; 44D, 44E). ; ; Modification History: ; Written by J Bonnell, 31 Jan 2007 ; Modified by ; LeContel 2007-05-24 10:39 (Wed, 24 May 2007) ; Modification for reading scm and efw headers: ; speed = reform( dh[ *, 14]/16b) ; ; $LastChangedBy: jbonnell $ ; $LastChangedDate: 2007-06-16 10:57:56 -0700 (Sat, 16 Jun 2007) $ ; $LastChangedRevision: 794 $ ; $URL $ ;- function thm_unpack_hed, data_type, dh ; some useful constants for building multi-byte values. uint_256 = uint( 256) long_256 = long( 256) ; unpack the portion of the header that doesn't change between APIDs. apid = reform( uint( ( 32b*dh[ *, 0]/32b))*uint_256 + uint( dh[ *, 1])) apid_ctr = reform( uint( ( 4b*dh[ *, 2]/2b))*uint_256 + uint( dh[ *, 3])) app_data_field_len = reform( uint( dh[ *, 4])*uint_256 + uint( dh[ *, 5])) clock_bytes = reform( dh[ *, 6:9]) subsec_bytes = reform( dh[ *, 10:11]) clock = reform( long( dh[ *, 9]) $ + long_256*( long( dh[ *, 8]) $ + long_256*( long( dh[ *, 7]) $ + long_256*( long( dh[ *, 6]))))) subsec = reform( long( dh[ *, 11]) $ + long_256*( long( dh[ *, 10]))) ; unpack the parts of the header that are different between APIDs. ; note the use of the SWITCH rather than CASE, allowing for basically identical ; header processing on many of the waveform data types. switch strlowcase( data_type) of 'fit': begin ; APID 0x410. compression = reform( dh[ *, 12]/128b) efi_config = reform( dh[ *, 12] and 127b) fgm_config = reform( dh[ *, 13] and 127b) fgm_range_x = reform( dh[ *, 14]/16b) fgm_range_y = reform( dh[ *, 14] and 15b) fgm_range_z = reform( dh[ *, 15]/16b) fgm_rate = reform( dh[ *, 15] and 7b) fgm_rate = 2.^(2+fgm_rate) hed_data = { data_type:data_type, $ apid:apid, apid_ctr:apid_ctr, app_data_field_len:app_data_field_len, $ clock_bytes:clock_bytes, subsec_bytes:subsec_bytes, $ clock:clock, subsec:subsec, $ compression:compression, $ efi_config:efi_config, fgm_config:fgm_config, $ fgm_range_x:fgm_range_x, fgm_range_y:fgm_range_y, fgm_range_z:fgm_range_z, $ fgm_rate:fgm_rate } break end ; of FIT case. 'fbk': begin ; APID 0x440. compression = reform( dh[ *, 12]/128b) config = reform( dh[ *, 12] and 127b) spare_config = reform( dh[ *, 13]) speed = reform( (dh[ *, 14]/16b) and 7b) speed = 2.^( float(speed)-4.) ; filterBank rate, spectra/s. fb1_sel = reform( dh[ *, 15]/16b) fb2_sel = reform( dh[ *, 15] and 15b) fb_sel_str = [ 'V1', 'V2', 'V3', 'V4', 'V5', 'V6', $ 'E12DC', 'E34DC', 'E56DC', $ 'SCM1', 'SCM2', 'SCM3', $ 'E12AC', 'E34AC', 'E56AC', $ 'UNDEF' ] fb1_sel_str = fb_sel_str[ fb1_sel] fb2_sel_str = fb_sel_str[ fb2_sel] hed_data = { data_type:data_type, $ apid:apid, apid_ctr:apid_ctr, app_data_field_len:app_data_field_len, $ clock_bytes:clock_bytes, subsec_bytes:subsec_bytes, $ clock:clock, subsec:subsec, $ compression:compression, $ speed:speed, $ fb1_sel:fb1_sel, fb1_sel_str:fb1_sel_str, $ fb2_sel:fb2_sel, fb2_sel_str:fb2_sel_str } break end ; of FBK (FilterBank) case. 'vaf': ; APID 0x441. 'vbf': ; APID 0x442. 'eff': ; APID 0x443. 'vap': ; APID 0x445. 'vbp': ; APID 0x446. 'efp': ; APID 0x447. 'vaw': ; APID 0x449. 'vbw': begin ; APID 0x44A. compression = reform( dh[ *, 12]/128b) config = reform( dh[ *, 12] and 127b) spare_config = reform( dh[ *, 13]) speed = reform( dh[ *, 14]/16b) speed = 2.^( float(speed) + 1.) ; waveform sample rate, samples/s. chan_sel = reform( dh[ *, 15] and 63b) hed_data = { data_type:data_type, $ apid:apid, apid_ctr:apid_ctr, app_data_field_len:app_data_field_len, $ clock_bytes:clock_bytes, subsec_bytes:subsec_bytes, $ clock:clock, subsec:subsec, $ compression:compression, $ speed:speed, $ chan_sel:chan_sel } break end ; of {VAF. VBF, EFF, VAP, VBP, EFP, VAW, VBW} case. 'scf': ; APID 0x444. 'scp': begin ; APID 0x448. compression = reform( dh[ *, 12]/128b) config = reform( dh[ *, 12] and 127b) spare_config = reform( dh[ *, 13]) speed = reform( dh[ *, 14]/16b) speed = 2.^( float(speed) + 1.) ; filterBank rate, spectra/s. chan_sel = reform( dh[ *, 15] and 7b) hed_data = { data_type:data_type, $ apid:apid, apid_ctr:apid_ctr, app_data_field_len:app_data_field_len, $ clock_bytes:clock_bytes, subsec_bytes:subsec_bytes, $ clock:clock, subsec:subsec, $ compression:compression, $ speed:speed, $ chan_sel:chan_sel } break end ; of {SCF, SCP} case. 'efw': ; APID 44B. 'scw': begin ; APID 0x44C. compression = reform( dh[ *, 12]/128b) config = reform( dh[ *, 12] and 127b) spare_config = reform( dh[ *, 13]) speed = reform(dh[ *, 14]/16b) speed = 2.^( float(speed) + 1.) ; Samples/s. chan_sel = reform( dh[ *, 15]) hed_data = { data_type:data_type, $ apid:apid, apid_ctr:apid_ctr, app_data_field_len:app_data_field_len, $ clock_bytes:clock_bytes, subsec_bytes:subsec_bytes, $ clock:clock, subsec:subsec, $ compression:compression, $ speed:speed, $ chan_sel:chan_sel } break end ; of {SCF, SCP} case. 'ffp': ; APID 0x44D. 'ffw': begin ; APID 0x44E. compression = reform( dh[ *, 12]/128b) ; speed = reform(dh[ *, 14]/16b) speed = reform( (dh[ *, 14]/16b) and 7b) speed = 2.^( float(speed)-4.) ; filterBank rate, spectra/s. ; nbins = reform( 16b*dh[ *, 14]/64b) nbins = reform( (dh[ *, 14]/4b) and 3b) nbins = 16.*2.^( float(nbins)) ; ff1_sel = reform( uint( dh[ *, 13]/32b) + uint_256*uint(64b*dh[ *, 12]/64b)) ; ff2_sel = reform( 8b*dh[ *, 13]/8b) ; ff3_sel = reform( uint( dh[ *, 15]/32b) + uint_256*uint(64b*dh[ *, 14]/64b)) ; ff4_sel = reform( 8b*dh[ *, 15]/8b) if (strlowcase( data_type) eq 'ffw') then begin ff1_sel = reform( dh[ *, 13] and 31b) ff2_sel = reform( dh[ *, 13]/32b + (dh[ *, 12] and 3b)*8b) ff3_sel = reform( dh[ *, 15] and 31b) ff4_sel = reform( dh[ *, 15]/32b + (dh[ *, 14] and 3b)*8b) endif else if (strlowcase( data_type) eq 'ffp') then begin ff1_sel = reform( dh[ *, 15] and 31b) ff2_sel = reform( dh[ *, 15]/32b + (dh[ *, 14] and 3b)*8b) ff3_sel = reform( dh[ *, 13] and 31b) ff4_sel = reform( dh[ *, 13]/32b + (dh[ *, 12] and 3b)*8b) endif else begin ; should not get here. endelse ff_sel_str = [ 'V1', 'V2', 'V3', 'V4', 'V5', 'V6', $ 'E12DC', 'E34DC', 'E56DC', $ 'SCM1', 'SCM2', 'SCM3', $ 'E12AC', 'E34AC', 'E56AC', $ 'UNDEF', $ 'EXB', 'EDOTB', 'SCMXB', 'SCMDOTB', $ 'UNDEF', 'UNDEF', 'UNDEF', 'UNDEF', 'UNDEF', 'UNDEF', $ 'UNDEF', 'UNDEF', 'UNDEF', 'UNDEF', 'UNDEF', 'UNDEF' ] ff1_sel_str = ff_sel_str[ ff1_sel] ff2_sel_str = ff_sel_str[ ff2_sel] ff3_sel_str = ff_sel_str[ ff3_sel] ff4_sel_str = ff_sel_str[ ff4_sel] hed_data = { data_type:data_type, $ apid:apid, apid_ctr:apid_ctr, app_data_field_len:app_data_field_len, $ clock_bytes:clock_bytes, subsec_bytes:subsec_bytes, $ clock:clock, subsec:subsec, $ compression:compression, $ speed:speed, $ ff1_sel:ff1_sel, ff1_sel_str:ff1_sel_str, $ ff2_sel:ff2_sel, ff2_sel_str:ff2_sel_str, $ ff3_sel:ff3_sel, ff3_sel_str:ff3_sel_str, $ ff4_sel:ff4_sel, ff4_sel_str:ff4_sel_str } break end ; of {FFP, FFW} (FFT Spectra) case. 'fgl': ; APID 0x460. 'fgh': begin ; APID 0x461. compression = reform( dh[ *, 12]/128b) fgm_config = reform( dh[ *, 12] and 127b) fgm_msg = reform( dh[ *, 13]) fgm_range_x = reform( dh[ *, 14]/16b) fgm_range_y = reform( dh[ *, 14] and 15b) fgm_range_z = reform( dh[ *, 15]/16b) fgm_rate = reform( dh[ *, 15] and 7b) if strlowcase( data_type) eq 'fgh' then $ fgm_rate = bytarr( n_elements( fgm_rate)) + 5b fgm_rate = 2.^(2+fgm_rate) hed_data = { data_type:data_type, $ apid:apid, apid_ctr:apid_ctr, app_data_field_len:app_data_field_len, $ clock_bytes:clock_bytes, subsec_bytes:subsec_bytes, $ clock:clock, subsec:subsec, $ compression:compression, $ fgm_config:fgm_config, fgm_msg:fgm_msg, $ fgm_range_x:fgm_range_x, fgm_range_y:fgm_range_y, fgm_range_z:fgm_range_z, $ fgm_rate:fgm_rate } break end ; of {FGL, FGH} (FGM Waveform) case. else: begin hed_data = 0 end ; of ELSE case. endswitch return, hed_data end