--- /dev/null
+#!/usr/bin/perl -w
+
+use English;
+use strict;
+use Getopt::Long;
+use Data::Dumper;
+use FileHandle;
+use feature "switch";
+
+###############################################################################
+## Configuration ##############################################################
+###############################################################################
+
+my $SensorHeaderLength = 7;
+
+my $file;
+my $opt_help = 0;
+my $opt_verb = 0;
+my $opt_debug = 0;
+my $totalevents = 1E9;
+my $mode = "";
+
+GetOptions ('h|help' => \$opt_help,
+ 'f|file=s' => \$file,
+ 'v|verb' => \$opt_verb,
+ 'd|debug' => \$opt_debug,
+ 'e|events=i' => \$totalevents);
+
+
+
+
+if($opt_help) {
+ printf("Usage: unpack_hld.pl \n");
+ printf("[-h|--help] Show this help\n");
+ printf("-f|--file <file> Path to hld file\n");
+ printf("[-v|--verb] Dump hld file content\n");
+ printf("[-d|--debug] More debugging output\n");
+ printf("\n");
+ exit;
+ }
+
+
+
+###############################################################################
+## HLD Reader #################################################################
+###############################################################################
+
+
+if(&checkArgs()){
+ exit(0);
+}
+
+my @evtHeader_list = ();
+my $evtHeader_aref = \@evtHeader_list;
+
+my @subEvtHeader_list = ();
+my $subEvtHeader_aref = \@subEvtHeader_list;
+
+my @data_list = ();
+my $data_aref = \@data_list;
+
+my $fh = new FileHandle("$file", "r");
+
+while(1){
+ @evtHeader_list = ();
+
+ &getEvtHeader($fh,$evtHeader_aref);
+ &printEvtHeader($evtHeader_aref) if($opt_verb);
+
+ my $evtSize = $evtHeader_aref->[0];
+ if (!defined $evtSize || $evtSize < 0x10) {last;}
+
+ #- If the size is only 32 Bytes -> goto to
+ # the next Event Header since there are no subevents
+ next unless defined $evtSize;
+ next if($evtSize == 32);
+
+ my $size_cntr = 32; # Bytes
+
+ while($evtSize > $size_cntr){
+
+ @subEvtHeader_list = ();
+
+ my $decoding = &getSubEvtHeader($fh,$subEvtHeader_aref);
+ &printSubEvtHeader($subEvtHeader_aref) if($opt_verb);
+
+ my $subEvtSize = $subEvtHeader_aref->[0];
+
+ $size_cntr = $size_cntr + $subEvtSize;
+
+ #- If the size is only 16 Bytes -> goto to
+ # the next Sub Event Header since there are no subevents
+ next if($subEvtSize == 16);
+
+ @data_list = ();
+ &getSubEvtData($fh, $data_aref, $subEvtSize, $decoding);
+ &printData($data_aref) if($opt_verb);
+
+ my $paddedSize = &padding($fh, $subEvtSize);
+
+ $size_cntr = $size_cntr + $paddedSize;
+
+ #----------> User function <---------
+ &analyzeData($evtHeader_aref, $subEvtHeader_aref, $data_aref);
+ }
+}
+
+$fh->close();
+
+exit(0);
+
+####################### END OF MAIN ###################
+
+sub printEvtHeader()
+{
+ my ($data_aref) = @_;
+
+ print "\n";
+
+ printf("size: %08x ", $data_aref->[0]);
+ printf("decoding: %08x ", $data_aref->[1]);
+ printf("id: %08x ", $data_aref->[2]);
+ printf("seqNr: %08x\n", $data_aref->[3]);
+
+ my $year = (($data_aref->[4] >> 16) & 0xff) + 1900;
+ my $mon = (($data_aref->[4] >> 8) & 0xff) + 1;
+ my $mday = ($data_aref->[4] >> 0) & 0xff;
+
+ my $hour = ($data_aref->[5] >> 16) & 0xff;
+ my $min = ($data_aref->[5] >> 8) & 0xff;
+ my $sec = ($data_aref->[5] >> 0) & 0xff;
+
+ printf("date: %04d-%02d-%02d ", $year, $mon, $mday);
+ printf("time: %02d:%02d:%02d ", $hour, $min, $sec);
+ printf("runNr: %08x ", $data_aref->[6]);
+ printf("expId: %08x\n", $data_aref->[7]);
+}
+
+sub printSubEvtHeader()
+{
+ my ($data_aref) = @_;
+
+ print "\n";
+
+ printf("size: %08x ", $data_aref->[0]);
+ printf("decoding: %08x ", $data_aref->[1]);
+ printf("id: %08x ", $data_aref->[2]);
+ printf("trigNr: %08x\n", $data_aref->[3]);
+}
+
+sub printData()
+{
+ my ($data_aref) = @_;
+
+ my $cntr = 0;
+
+ print "\n";
+
+ foreach my $word (@$data_aref){
+ printf("%08x ", $word);
+
+ $cntr++;
+
+ print "\n" if( ($cntr%4) == 0);
+ }
+}
+
+sub getEvtHeader()
+{
+ my ($fh, $data_aref) = @_;
+
+ my @tmp_list;
+
+ foreach my $i (1..8){
+ my $header;
+
+ read($fh, $header, 4);
+ &checkEndOfFile($fh, $header);
+
+ push(@tmp_list, $header);
+ }
+
+ my $decoding = unpack("V*", $tmp_list[1]);
+ unless(defined $decoding) {printf "This seems to be the end\n"; return -1;}
+
+ if($opt_debug){
+ if(&getEndianess($decoding)){
+ printf("\n Event Decoding: %08x Byte Order: Little Endian\n", $decoding);
+ }
+ else{
+ printf("\n Event Decoding: %08x Byte Order: Big Endian\n", $decoding);
+ }
+ }
+
+ foreach my $tmp (@tmp_list){
+ my $word;
+
+ if(&getEndianess($decoding)){
+ $word = unpack("V*", $tmp); # Small Endian
+ }
+ else{
+ $word = unpack("N*", $tmp); # Big Endian
+ }
+
+ push(@$data_aref, $word);
+ }
+}
+
+sub getSubEvtHeader()
+{
+ my ($fh, $data_aref) = @_;
+
+ my @tmp_list;
+
+ foreach my $i (1..4){
+ my $header;
+
+ read($fh, $header, 4);
+ &checkEndOfFile($fh, $header);
+
+ push(@tmp_list, $header);
+ }
+
+ my $decoding = unpack("V*", $tmp_list[1]);
+
+ if($opt_debug){
+ if(&getEndianess($decoding)){
+ printf("\n SubEvent Decoding: %08x Byte Order: Little Endian\n", $decoding);
+ }
+ else{
+ printf("\n SubEvent Decoding: %08x Byte Order: Big Endian\n", $decoding);
+ }
+ }
+
+ foreach my $tmp (@tmp_list){
+ my $word;
+
+ if(&getEndianess($decoding)){
+ $word = unpack("V*", $tmp); # Small Endian
+ }
+ else{
+ $word = unpack("N*", $tmp); # Big Endian
+ }
+
+ push(@$data_aref, $word);
+ }
+
+ return &getEndianess($decoding);
+}
+
+sub getEndianess()
+{
+ my ($decoding) = @_;
+
+ # Return values:
+ # 0 : Big Endian
+ # 1 : Little Endian
+ #
+ # Usually (when sent by GbE-FPGAs) Event Headers are Little Endian
+ # SubEvent Headers and data are Big Endian
+
+ my $retVal = 0;
+
+ if(defined($decoding) && ($decoding & 0x000000ff) > 0){
+ $retVal = 1; # This is Little Endian
+ }
+
+ return $retVal;
+}
+
+sub getSubEvtData()
+{
+ my ($fh, $data_aref, $size, $decoding) = @_;
+
+ #- Subtract subevent header size and devide by word size
+ my $nrOfWords = ($size - 16)/4;
+
+ foreach my $i (1..$nrOfWords){
+
+ my $tmp;
+ read($fh, $tmp, 4);
+ &checkEndOfFile($fh, $tmp);
+
+ my $word;
+
+ if(&getEndianess($decoding)){
+ $word = unpack("V*", $tmp); # Little Endian
+ }
+ else{
+ $word = unpack("N*", $tmp); # Big Endian
+ }
+
+ push(@$data_aref, $word);
+ }
+}
+
+sub padding()
+{
+ my ($fh, $size) = @_;
+
+ my $retVal = 0; # Size of the padded word
+
+ #- Check 64-bit (8-Byte) alignment
+ unless( ($size%8) == 0){
+ my $tmp;
+ read($fh, $tmp, 4);
+
+ my $word;
+ $word = unpack("V*", $tmp); # Little Endian
+
+ unless($word == 0){
+ #- Padding word is not zero
+
+ printf("\n Padding word is not zero: %08x! \n", $word) if($opt_debug);
+ #$fh->close();
+ #exit(0);
+ }
+
+ $retVal = 4; # Bytes
+ }
+
+ return $retVal;
+}
+
+sub checkEndOfFile()
+{
+ my ($fh, $tmp) = @_;
+
+ unless( defined $tmp){
+ #- The end of the file
+ print "\n End of file\n";
+ $fh->close();
+ exit(0);
+ }
+}
+
+sub checkArgs()
+{
+ my $retVal = 0;
+
+ unless( defined $file){
+ print "\n You must provide a path to the hld file!\n";
+ print " Read help.\n";
+ $retVal = 1;
+ }
+
+ return $retVal;
+}
+
+
+
+
+
+
+
+###############################################################################
+## MVD Unpacker ###############################################################
+###############################################################################
+
+
+sub analyzeData() {
+ my ($evtHeader, $subEvtHeader, $data) = @_;
+ my $EvtId = $evtHeader->[3];
+ my $pos = 0;
+ my $time = 0;
+ my $SubEvtSize = $subEvtHeader->[1]/4-6;
+
+ while(1) { #Loop over SubSubEvents
+ my $RocId = $data->[$pos] & 0xffff;
+ my $RocLength = ($data->[$pos]>>16) & 0xffff;
+ if($RocId == 0x5555) {last;}
+ my $RocEnd = $pos + $RocLength;
+ $pos++;
+
+ for(my $i = 0; $i < $SensorHeaderLength;$i++) {
+ for($i) {
+ when (1) {printf("Sensor ID: %8x\t",$data->[$pos]&0xffff);}
+ when (2) {printf("Status: %08x\t",$data->[$pos]);}
+ when (3) {printf("Error Code: %08x\t",$data->[$pos]);}
+ when (4) {printf("Debug: %08x\t",$data->[$pos]);}
+ when (5) {$time = $data->[$pos];}
+ when (6) {printf("Time: %08x%08x\n",$data->[$pos],$time);}
+ }
+
+ $pos++;
+ }
+
+ while(1) {
+ if($pos >= $RocEnd) {$pos++;last;}
+# printf("$pos %08x\n",$data->[$pos]);
+
+
+ $pos++;
+ }
+
+
+ }
+ }
+