; buffer should contain bytes for a single ccsds packet, header is ; contained in first 3 words (6 bytes) ; $LastChangedBy: davin-mac $ ; $LastChangedDate: 2024-10-27 01:24:49 -0700 (Sun, 27 Oct 2024) $ ; $LastChangedRevision: 32908 $ ; $URL: svn+ssh://thmsvn@ambrosia.ssl.berkeley.edu/repos/spdsoft/trunk/projects/SWFO/STIS/swfo_ccsds_decom.pro $ ; ; This routine still needs to be modified to conform to the SWFO standard. function swfo_ccsds_decom_mettime,header,apid,day=day,millisec=millisec,microsec=microsec ; header assumed to be bytes at this point n = n_elements(header) if n lt 5 then return, !values.d_nan if apid lt '350'x then begin ;spacecraft packets day = ((header[6]*256UL+header[7])) millisec = ((header[8]*256UL+header[9])*256+header[10])*256+header[11] microsec = header[12] *256u + header[13] endif else begin ;instrument packets if header[6] ne 0 then begin dprint,'Time out of range, header[6]= ',header[6],dwait=2. ;hexprint,header endif ;header[6] = 0 day = ((header[6]*256UL+header[7])*256)+header[8] millisec = ((header[9]*256UL+header[10])*256+header[11])*256+header[12] microsec = header[13] *256u + header[14] endelse MET = day*24d*3600d + millisec/1000d + microsec/1d6 ;MET = (header[3]*2UL^16 + header[4] + (header[5] and 'fffc'x) / 2d^16) + ( (header[5] ) mod 4) * 2d^15/150000 ; SPANS return,met end function swfo_ccsds_decom,buffer,source_dict=source_dict,wrap_ccsds=wrap_ccsds,offset,buffer_length,remainder=remainder,error=error,verbose=verbose,dlevel=dlevel error = 0b if not keyword_set(offset) then offset = 0 if not keyword_set(buffer_length) then buffer_length = n_elements(buffer) remainder = !null d_nan = !values.d_nan f_nan = !values.f_nan ccsds = { swfo_ccsds_format, $ time: d_nan, $ ; unixtime MET: d_nan, $ GRtime: d_nan, $ delaytime: d_nan, $ apid: 0u , $ seqn: 0u , $ seqn_delta: 0u, $ seqn_group: 0b , $ pkt_size: 0ul, $ day: 0UL, $ millisec: 0ul, $ microsec: 0u, $ source_apid: 0u , $ ; an indicator of where this packet came from: 0: unknown, apid of wrapper_packet: 0x348 - 0x34f source_hash: 0UL, $ ; hashcode() of source_name compr_ratio: 0. , $ aggregate: 0u, $ ; number of data samples aggregated - determined from outer wrapper header time_delta : d_nan, $ ptp_time: d_nan, $ ; unixtime from ptp packet error : 0b, $ version : 0b , $ ; this could be eliminated since it is useless pdata: ptr_new(), $ ; pointer to full packet data including header content_compressed: 0b, $ ;counter: 0ul, $ ; packet counter as received - future use ;proc_time: d_nan, $ ; unixtime when it was processed ;source_name: '' , $ ; file name of source ;content_id: 0u , $ ; used by wrapper packets to define the apid of the inner packet ;content_nsamples: 0u , $ ; number of packets that were aggregated (composed) gap : 1b } if buffer_length-offset lt 15 then begin if debug(2) then begin dprint,'CCSDS Buffer length too short to include full header: ',buffer_length-offset,dlevel=2,offset;,dwait=20 ;hexprint,buffer endif error = 1b return, !null endif header = swap_endian(uint(buffer[offset+0:offset+5],0,3) ,/swap_if_little_endian ) ; ??? error here % Illegal subscript range: BUFFER. ccsds.version = byte(ishft(header[0],-11) ) ; Corrected - but includes 2 extra bits ccsds.apid = header[0] and '7FF'x if n_elements(subsec) eq 0 then subsec= ccsds.apid ge '350'x apid = ccsds.apid MET = swfo_ccsds_decom_mettime(buffer[offset+0:offset+15],apid,day=day,millisec=millisec,microsec=microsec) ccsds.met = met ccsds.day = day ccsds.millisec = millisec ccsds.microsec = microsec ccsds.time = swfo_spc_met_to_unixtime(ccsds.MET) if isa(source_dict) && source_dict.haskey('parent_dict') then begin grtime = source_dict.parent_dict.headerstr.time ;printdat,time_string(grtime) ;printdat,ccsds ccsds.grtime = GRtime ccsds.delaytime = grtime- ccsds.time endif ccsds.pkt_size = header[2] + 7 if buffer_length-offset lt ccsds.pkt_size then begin error=2b remainder = buffer[offset:*] if debug(dlevel,verbose) then begin dprint,'Not enough bytes: pkt_size, buffer_length= ',ccsds.pkt_size,buffer_length-offset,dlevel=dlevel,verbose=verbose ;hexprint,buffer ;pktbuffer = 0 endif return ,0 endif else begin if ccsds.pkt_size lt 10 then begin dprint,ccsds.apid,ccsds.seqn,' Invalid Packet size:' , ccsds.pkt_size,dlevel=3 return,0 endif if ccsds.pkt_size ne buffer_length-offset then begin dprint,'buffer and CCSDS size mismatch',dlevel=3 endif pktbuffer = buffer[offset+0:offset+ccsds.pkt_size-1] ccsds.pdata = ptr_new(pktbuffer,/no_copy) endelse ccsds.seqn_group = ishft(header[1] ,-14) ccsds.seqn = header[1] and '3FFF'x ; if (ccsds.MET lt 1e5) && (ccsds.apid ne '734'x) then begin ;0x734 is the ground SWEAP ApID (MET=0) tells us when we send command files to the MOC ; dprint,dlevel=dlevel,verbose=verbose,'Invalid MET: ',MET,' For packet type: ',ccsds.apid ; ccsds.time = d_nan ; endif ; ; if ccsds.MET gt 'FFFFFFF0'x then begin ; dprint,dlevel=dlevel,verbose=verbose,'MAX MET: ',MET,' For packet type: ',ccsds.apid ; ccsds.time = d_nan ; endif if isa(wrap_ccsds) then begin ccsds.source_apid = wrap_ccsds.apid ccsds.aggregate = wrap_ccsds.content_aggregate ccsds.compr_ratio = wrap_ccsds.compr_ratio endif if isa(source_dict) then begin if source_dict.haskey('source_info') then ccsds.source_hash = source_dict.source_info.input_sourcehash if 0 then begin if source_dict.haskey('ptp_header') && isa(source_dict.ptp_header) then begin ptp_header = source_dict.ptp_header if isa(ptp_header) && ptp_header.ptp_size ne ccsds.pkt_size + 17 then begin dprint,dlevel=2,format='("APID: ",Z03," ccsds PKT size: ",i5," does not match ptp size:",i5,a)',ccsds.apid,ccsds.pkt_size+17, ptp_header.ptp_size,' '+time_string(ccsds.time) endif if isa(source_dict.ptp_header) then ccsds.ptp_time = ptp_header.ptp_time endif else begin source_dict.ptp_header2 ={ ptp_time:systime(1), ptp_scid: 0, ptp_source:0, ptp_spare:0, ptp_path:0, ptp_size: 17 + ccsds.pkt_size } endelse endif endif return,ccsds end