#!/usr/bin/perl ############################################################################### # # # ---=== softDVB-T ===--- # # (software generated DVB-T transmitter) # # # ############################################################################### # # # Authors: Marcin Szelest SQ9DJJ Marcin.Szelest@gmail.com # # Slawomir Lyszkowski slyszkowski@yahoo.pl # # # # File contents: # # Behaviaral model of Reed-Solomon encoder. # # # # File purpose: # # Verification of gnuradio Reed-Solomon encoder block. # ############################################################################### # RS(204,188, t=8) is derived from RS(255,239,t=8) by adding 51bytes of zeros before message. # Added zeros must be removed from the output stream! $PARITY_BYTES = 204-188; # For calculation purposes we are using GNU Octave 3.2.3 with octave-communication-common package # Let's generate Galois fied with use of p(x) polynominal # according ETSI EN 300 744: # # 8 4 3 2 # p(x) = x + x + x + x + 1 , so p(x) = 0x11D # # Octave command which generates Galois field for p(x): # galois_field = gf(0:255, 8, 0x11D); # # # Let's calculate g(x) now: # # 0 1 2 15 # g(x) = (x + a )(x + a )(x + a )...(x + a ) , where a = 0x02 # # Octave command which simplify polynominal above: # g_x_ = rsgenpoly(255, 239, 0x11D, 0) #@g_x_ = (1, 59, 13, 104, 189, 68, 209, 30, 8, 163, 65, 41, 229, 98, 50, 36, 59); @g_x_ = reverse (59, 13, 104, 189, 68, 209, 30, 8, 163, 65, 41, 229, 98, 50, 36, 59); # we need two arithmetic opperation on Galois field: addition and multiplication sub gf_add ($$) { return (($_[0]^$_[1]) & 0xff) } # Algorithm according http://en.wikipedia.org/wiki/Finite_field_arithmetic sub gf_mult ($$) { $l = $_[0]; $m = $_[1]; $p = 0; for (1..8) { if ($m & 0x01) { $p = $p ^ $l } $hi = $l & 0x80; $l = $l << 1; if ($hi) { $l = $l ^ 0x11d } $m = $m >> 1; } return ($p & 0xff) } # RS(204,188, t=8) is derived from RS(255,239,t=8) sub encoder_RS_204 ($) { @in_msg = ( $_[0] =~ m/../g ); if (scalar(@in_msg) != 188) { print "Error: Insuficient number of bytes (should be 188, is ".scalar(@in_msg).")\nExiting...\n"; exit } @tab = split(" ",encoder_RS_255(("00" x 51).(join "",@in_msg))); return (join " ",@tab[51..255]) } # Algorithm according RSCODE version 1.3 (Henry Minsky) sub encoder_RS_255 ($) { @in_msg = ( $_[0] =~ m/../g ); for ($i=0; $i<(scalar @in_msg); $i++) { @in_msg[$i] = sprintf("%d",hex @in_msg[$i]) } if (scalar(@in_msg) != 239) { print "Error: Insuficient number of bytes (should be 239, is ".scalar(@in_msg).")\nExiting...\n"; exit } # RS endode starts here @lsfr[15] = 0; for ($i=0; $i<239; $i++) { $fdbk = gf_add(@in_msg[$i], @lsfr[15]); for ($j = $PARITY_BYTES-1; $j > 0; $j--) { @lsfr[$j] = gf_add(@lsfr[$j-1], gf_mult(@g_x_[$j], $fdbk)); } @lsfr[0] = gf_mult(@g_x_[0], $fdbk); } return (join " ",@in_msg)." ".(join " ",reverse @lsfr[0..$PARITY_BYTES-1]) } $msg = "fa" x 188; $res = encoder_RS_204($msg); # print results print "\tsrc_data = ("; @arr = ( $msg =~ m/../g ); for ($i=0; $i<(scalar @arr)-1; $i++) { printf("0x%02x, ", hex @arr[$i]) } printf("0x%02x)\n\n", hex @arr[$i]); print "\texpected_result = ("; @arr = split(" ", $res); for ($i=0; $i<(scalar @arr)-1; $i++) { printf("0x%02x, ", @arr[$i]) } printf("0x%02x)\n\n", @arr[$i]);