#! /usr/bin/perl

use strict;
use warnings;

require("crc32.pl");

# parse eth TX log data
my @nibbles = ();
while (my $line = <>) {
  chomp $line;
  # ethernet TX log
  if ($line =~ /^ethernet TX: ([0-9]+)$/) {
    my $nibble = $1;
    push (@nibbles, $nibble & 0x0F);
  }
  # VHDL data
  elsif ($line =~ /^ *([0-9A-FXa-fx", ]+)/) {
    my $data = $1;
    for my $part (split(/,/, $data)) {
      if ($part =~ /^ *[xX]"([0-9A-Fa-f])"/) {
        my $val = $1;
        push (@nibbles, hex($val));
      }
    }
  }
}

# nibbles to bytes
my @bytes = ();
for (my $i = 0; $i < @nibbles; $i += 2) {
  my $byte = $nibbles[$i + 1] << 4 | $nibbles[$i];
  push (@bytes, $byte);
}

# remove preamble
my $pos = 0;
while ($pos < @bytes && $bytes[$pos] == 0x55) {
  $pos++;
}
if ($pos > 4 && $pos < @bytes && $bytes[$pos] == 0xD5) {
  $pos++;
  for ( ; $pos > 0; $pos--) {
    shift(@bytes);
  }
} else {
  print STDERR "warning: preamble not found -> not removed\n";
}

# remove CRC
if (@bytes >= 4) {
  my @bytes_no_crc = @bytes;
  my @crc_bytes = ();
  unshift (@crc_bytes, pop(@bytes_no_crc));
  unshift (@crc_bytes, pop(@bytes_no_crc));
  unshift (@crc_bytes, pop(@bytes_no_crc));
  unshift (@crc_bytes, pop(@bytes_no_crc));
  my $crc_calc = crc32([@bytes_no_crc]);
  my $mismatch = 0;
  for (my $i = 0; $i < 4; $i++) {
    if (shift(@crc_bytes) != shift(@{$crc_calc})) {
      $mismatch = 1;
    }
  }
  if ($mismatch) {
    print STDERR "warning: invalid CRC32 -> not removed\n";
  } else {
    @bytes = @bytes_no_crc;
  }
} else {
  print STDERR "warning: too short for detecting CRC32 -> noting removed\n";
}

# print C data
print("unsigned char c_data[] = {\n");
for (my $pos = 0; $pos < @bytes; ) {
  print(" ");
  for (my $i = 0; $i < 8 and $pos < @bytes; ++$i, ++$pos) {
    if ($pos + 1 < @bytes) {
      printf(" 0x%02X,", $bytes[$pos]);
    } else {
      printf(" 0x%02X", $bytes[$pos]);
    }
  }
  print("\n");
}
print("};\n");