Last active
June 26, 2021 10:45
-
-
Save kulp/50a9f357c2375f7e599583bca489a5f0 to your computer and use it in GitHub Desktop.
Generate TMDS codes (for DVI / HDMI)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env perl | |
# Generate TMDS codes (for DVI / HDMI) | |
# Takes decimal numbers 0-255 on stdin and emits ASCII binary numbers on stdout. | |
# Emits 462 unique codes where the standard expects 460; the user should reject | |
# the two zero-transition codes it produces. | |
use strict; | |
use warnings; | |
# LSb first | |
sub unbitarray ($$) { unpack "S", pack "b$_[0]", join "", @_[0 .. $#_] } | |
sub bitarray ($$) { split //, unpack "b$_[0]", pack "S", $_[1] } | |
sub ones { scalar grep /1/, @_ } | |
sub gen9 | |
{ | |
my @D = @_; | |
my @q; | |
my $N1 = ones @D; | |
push @q, $D[0]; | |
if ($N1 > 4 or ($N1 == 4 and $D[0] == 0)) { | |
push @q, 1-($q[-1] ^ int($D[$_])) for 1 .. 7; | |
push @q, 0; # XNOR is 0 | |
} else { | |
push @q, ($q[-1] ^ int($D[$_])) for 1 .. 7; | |
push @q, 1; # XOR is 1 | |
} | |
return @q; | |
} | |
sub gen10 | |
{ | |
# data enable, two bits of control (e.g., vsync, hsync), ones-count, q_m | |
my ($de, $cc, $count, $q) = @_; | |
if ($de) { | |
if ($$count == 0 or ones @$q == 4) { | |
# balanced | |
my $off = 8 - 2 * ones @$q; | |
if ($q->[8] == 0) { | |
$$count -= $off; | |
} else { | |
$$count += $off; | |
} | |
return ((map { $q->[8] ? $_ : 1-$_ } @$q[0 .. 7]), $q->[8], 1-$q->[8]); | |
} else { | |
# unbalanced | |
# TODO update $$count | |
my $flip = 0+($$count > 0 && (ones @$q) > 4 or | |
$$count < 0 && (ones @$q) < 4); | |
return ((map $flip^$_, @$q[0 .. 7]), $q->[8], $flip); | |
} | |
} else { | |
$$count = 0; | |
# TODO check bit-endianness of control words | |
# spec is unclear as to whether `q[0:9]` and `q[9:0]` are different | |
my @arr = (qw(0 0 1 0 1 0 1 0 1), 1-$cc->[1]); | |
return reverse ($cc->[0] ? map 1-$_, @arr : @arr); | |
} | |
} | |
for my $D (<>) { | |
chomp $D; | |
for my $count (-5, 5) { | |
my @q = gen10 1, [ 0, 0 ], \$count, [ gen9 bitarray 8, $D ]; | |
print((join "", reverse @q), "\n"); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env perl | |
# Decode TMDS codes (for DVI / HDMI) | |
# Takes ASCII binary numbers on stdin and emits decimal numbers 0-255 on stdout. | |
use strict; | |
use warnings; | |
while (<>) { | |
chomp; | |
my $out = 0; | |
# MSB on left of string | |
my ($inv, $mode, @q) = split //; | |
@q = reverse @q; # put MSB at highest index | |
if ($inv) { | |
@q = map 1-$_, @q; | |
} | |
my $lsb = $out = $q[0]; | |
for my $i (1 .. 7) { | |
my $bit = int($q[$i]) ^ int($q[$i-1]) ^ int($mode) ^ 1; | |
$out = $bit . $out; | |
} | |
print(unpack("C", pack "B8", $out), "\n"); | |
} | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
# Provides some functions for generating TMDS codes. | |
# Run it like this: `$0 count-codes` or `$0 dc-balanced-pairs`. | |
# Fail early and loudly. | |
set -euo pipefail | |
here=$(dirname $0) | |
unique-codes () | |
{ | |
seq 0 255 | | |
$here/tmds.pl | | |
sort --unique | | |
# I infer that ten zeros and ten ones are invalid codes, though I have not | |
# seen this explicitly stated anywhere yet. | |
grep -v -E -e '^0{10}' -e '^1{10}' | |
} | |
count-codes () | |
{ | |
unique-codes | | |
$here/untmds.pl | | |
wc -l | |
} | |
find-dc-balanced () | |
{ | |
grep -vE -e '(1.*){6}' -e '(0.*){6}' | |
} | |
dc-balanced-pairs () | |
{ | |
paste \ | |
<(unique-codes | find-dc-balanced | ./untmds.pl) \ | |
<(unique-codes | find-dc-balanced | tr 01 10 | ./untmds.pl) | | |
while read a b | |
do | |
echo -e "$a\t$b\t$(( a - b ))" | |
done | | |
sort -gk3 | |
} | |
"$@" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment