![]() |
downloads | documentation | HowTo | reporting bugs | links | Recent Changes |
What is a Wiki?See WikiWikiWeb If you don't know how to use a wiki see the WikiHowto ErfurtWiki is maintained by a loosely knit group of developers. Quick LinksRelated sitesContactPlease submit website bugs in the BugReports Contribute!Please file any wishes on UserSuggestions. Hosted By |
This script will control a DirecTV model D10 receiver via the serial port. Place the following script on your myth box, and simply designate it as the "external command" when setting up your capture card. Be sure to use the full path, and make the script executable (chmod +x). Mythblasterz for IRblasters. To test the script from the command line, simply call the script with the desired channel as the sole argument. For example, if the script is /myth/directv.pl, then call /myth/directv.pl 245 to change the channel to 245. If the script doesn't seem to be working, and you've just installed your cables, it is recommended that you power-cycle both the DirecTV box and the myth box, in that order. Tested WithRCA DRD435RH (2/14/2005) OK Modification Required for D10-200It seems the D10-200 receiver requires an 0x0D to be sent after every command. Replace the sendbytes subroutine with this one to accomodate.
sub sendbytes {
(@send)=@_;
push @send,"0x0d";
foreach (@send) { s/^0x//g; $_=hex($_); }
print "SEND: " if ($verbose);
foreach $num (@send) {
$str=pack('C',$num);
printf("0x%X [%s] ", $num, $str) if ($verbose);
syswrite($serial,$str,length($str));
}
print "\n" if ($verbose);
}
My D10-200 wasn't reliable with the changes and the script below. The box would lockup sometimes on channel changes so I modified the script to work better for me. I also added a bunch more commands to the script. See my version at http://www.pdp8online.com/directv/directv.shtml. (Script also posted directly to the KnoppMythWiki as the DtenSerialControlScriptTwo. See the website for more usage notes, as well as additional D10 monitoring scripts.) This script should also work with the RCA box but I don't have one to test with. It also should work with the new firmware version 0x101B for the D10-100 which broke changing channels below 100 with the old script. The script:
$|=1; use POSIX qw(:termios_h); use Time::HiRes? qw(usleep ualarm gettimeofday tv_interval ); use FileHandle?; $version = "1.7";
$verbose=0;
$retry_count=4;
$baudrate = "9600"; $serport = "/dev/ttyS0";
$box_type = "RCA";
$clear_osd_delay = .2; %pkt_decode=("0xF0" => "START PKT", "0xF1" => "ERR 1",
"0xF2" => "GOT EXTENDED",
"0xF4" => "END PKT",
"0xF5" => "ERR 2",
"0xFB" => "PROMPT");
%terminal=("0xF1" => -1, "0xF4" => 1,
"0xF5" => -1);
%cmds=("on" => \&on, "off" => \&off,
"reboot" => \&reboot,
"text" => \&text,
"show" => \&show,
"hide" => \&hide,
"get_channel" => \&get_channel,
"get_signal" => \&get_signal,
"get_datetime" => \&get_datetime,
"set_system_datetime" => \&set_system_datetime,
"key" => \&key,
"delay" => \&delay,
"port" => \&port,
"baudrate" => \&baudrate,
"box_type" => \&box_type,
"retries" => \&retries,
"channel_change_type" => \&channel_change_type,
"setup_channel" => \&setup_channel,
"version" => \&version,
"verbose" => \&set_verbose,
"quiet" => \&clear_verbose
);
%keymap=(right => "0xa8", left => "0xa9",
favorite => "0x9e?",
up => "0xa6",
down => "0xa7",
select => "0xc3",
enter => "0xc3", # Doesn't have separate enter?
exit => "0xc5",
antenna => "0xfa",
9 => "0xc6",
8 => "0xc7",
7 => "0xc8",
6 => "0xc9",
5 => "0xca",
4 => "0xcb",
3 => "0xcc",
2 => "0xcd",
1 => "0xce",
0 => "0xcf",
ch_up => "0xd2",
ch_dn => "0xd3",
power => "0xd5",
jump => "0xd8",
guide => "0xe5",
menu => "0xf7",
clear => "0xf9",
play => "0xea",
record => "0xe8",
pause => "0xe6",
forward => "0xe3",
reverse => "0xe2",
stop => "0xe0",
dss => "0xc5",
off => "0xc4",
skip => "0xac",
%keymap_200 = (right => "0x9a?",
left => "0x9b?",
up => "0x9c?",
down => "0x9d?",
select => "0xc3",
enter => "0xa0",
exit => "0xd4",
9 => "0xe9",
8 => "0xe8",
7 => "0xe7",
6 => "0xe6",
5 => "0xe5",
4 => "0xe4",
3 => "0xe3",
2 => "0xe2",
1 => "0xe1",
0 => "0xe0",
dash => "0xa5",
"-" => "0xa5",
ch_up => "0xd1",
ch_dn => "0xd2",
power => "0xd5",
jump => "0xd6", # Name from other set
prev => "0xd6", # Key label on -200
guide => "0xd3",
menu => "0xf7",
info => "0xa1",
active => "0xa2",
list => "0xa3",
back => "0xa4"
);
%boxes=("RCA" => \%keymap, "RCA_OLD" => \%keymap,
"D10-100" => \%keymap_200,
"D10-200" => \%keymap_200,
"D11" => \%keymap_200,
%keymap_extra=("RCA" => ["0x00", "0x00"], "RCA_OLD" => ["0x00", "0x00"],
"D10-100" => ["0x00", "0x01"],
"D10-200" => ["0x00", "0x01"],
"D11" => ["0x00", "0x01"]
%cmd_extra=("RCA" => undef, "RCA_OLD" => undef,
"D10-100" => undef,
"D10-200" => "0x0d?",
"D11" => "0x00"
%chan_change_key=("RCA" => 0, "RCA_OLD" => 0,
"D10-100" => 1,
"D10-200" => 1,
"D11" => 1
my $chan_change_key_param; my $serial; my $i;
for ($i = 0; $i < $#ARGV; $i++) { }if ($#ARGV < 0) { usage();
}
while ($#ARGV >= 0) { if (defined($sub = $cmds{$ARGV0?})) {
}
shift @ARGV;
&$sub;
} else {
}
exit(0); sub usage { print "Usage: $0 command ...\n";
print "Commands:\n";
print " box_type RCA|RCA_OLD|D10-100|D10-200|D11 - select set top box type\n";
print " delay number - wait for number seconds. Floating point is valid \n";
print " key string - send remote key string. See source for supported keys\n";
print " last_param - execute last parameter on command line at current location\n";
print " number{-number} - change to specified channel-subchannel\n";
print " off - turn box off\n";
print " on - turn box on\n";
print " reboot - hard reboot (reset)\n";
print " port string - select port to send commands on, currently $serport\n";
print " should be first on command line\n";
print " setup_channel number - send on, channel change command and OSD off command\n";
print " also retries if channel change not sucessful\n";
print " version - display program version\n";
print "\n";
print " baudrate number - select serial port baudrate, currently $baudrate\n";
print " channel_change_type key|command - select channel change method\n";
print " get_channel - print current channel\n";
print " get_datetime - print date and time\n";
print " get_signal - print signal strength\n";
print " hide - hide text, will also prevent info button from working\n";
print " show - show text, will also allow info button to work\n";
print " retries number - set maximum number of retries on error\n";
print " set_system_datetime - set PC clock from box. ntp is more accurate\n";
print " text string - display string on screen, \"\" to clear\n";
print " verbose|quiet - select how much information printed\n";
print "\n";
print "Mythtv command for normal RCA box: directv.pl setup_channel\n";
print "Complex Mythtv command for D10-200 box doing same as setup_channel:\n";
print " directv.pl box_type D10-200 on last_param delay .2 key exit\n";
print "Mythtv adds channel number at end of command\n";
}
sub setup_channel { my $tries = $retry_count;
my $cmd_chan = shift(@ARGV);
my @in, $sub, $chan;
while ($tries-- > 0) {
}
on();
change_channel($cmd_chan);
select(undef, undef, undef, $clear_osd_delay);
send_key("exit");
$chan = get_channel_str();
last if ($cmd_chan eq $chan);
}
die "Excessive channel change retries, commanded $cmd_chan got $chan\n" if $tries < 0;
sub version { print "Version $version\n";
}
sub retries { $retry_count = shift(@ARGV);
}
sub channel_change_type { my $type = shift(@ARGV);
if ($type eq "key") {
}
$chan_change_key_param = 1;
} elsif ($type eq "command") {
$chan_change_key_param = 0;
} else {
die "Unkown channel_change_type $type\n";
}
sub key { send_key(shift(@ARGV));
}
sub send_key { my $map = $boxes{$box_type};
my $key = $$map{shift(@_)};
die "Unknown key $ARGV0?\n" if (!defined($key));
simple_command(map_code("0xA5"),@{$keymap_extra{$box_type}}, "0x$key");
}
sub box_type { my ($tmp) = uc(shift(@ARGV));
die "Unknown box_type $tmp\n" if (!defined($boxes{$tmp}));
$box_type = $tmp;
}
sub port { $serport = $ARGV0?;
shift @ARGV;
}
sub baudrate { $baudrate = $ARGV0?;
shift @ARGV;
}
sub delay { select(undef, undef, undef, $ARGV0?);
shift @ARGV;
}
sub set_verbose { $verbose = 1;
}
sub clear_verbose { $verbose = 0;
}
sub on { simple_command(map_code("0x82")); } sub off { simple_command(map_code("0x81")); } sub reboot { #Have to use sendbytes - reboot doesn't wait to reply sendbytes("0xFA","0x96"); } sub get_channel_str { my $chan; if ($box_type eq "RCA_OLD") { } else { my @in = dss_command(4, map_code("0x87"));
return undef if($#in != 3);
my $sub = $in2? * 256 + $in3?;
$chan = $in0?*256+$in1;
$chan = $chan . "-$sub" if $sub != 65535;
}
return $chan;
}
sub get_channel { my $channel = get_channel_str();
if (defined($channel)) {
}
print "channel " . $channel . "\n";
}
sub get_signal { my @in = dss_command(1, map_code("0x90")); return if($#in != 0); print "signal $in0?\n"; } sub get_datetime { my @in = dss_command(7, map_code("0x91"));
return if($#in != 6);
$strTime = "$in1/$in2? $in3?:$in4?:$in5?";
print("Date $strTime\n")# if ($verbose);
}
sub set_system_datetime { my @in = dss_command(7, map_code("0x91"));
return if($#in != 6);
my $strTime = "$in1/$in2? $in3?:$in4?:$in5?";
print("Setting system time to $strTime\n") if ($verbose);
$cmd = "echo date -s \"$strTime\"";
`$cmd`;
}
sub text { my @tmp = unpack("H2" x length($ARGV0?) ,$ARGV0?); shift @ARGV; simple_command(map_code("0xaa"), sprintf("%x",$#tmp+1), @tmp); } sub hide { simple_command(map_code("0x86")); } sub show { simple_command(map_code("0x85")); } sub simple_command { if (defined(dss_command(0, @_))) {
}
return(1);
return(undef);
sub dss_command { my $reply_size = shift(@_);
for (my $i = 0; $i < $retry_count; $i++) {
}
sendbytes("0xFA",@_);
my $rc = get_reply($reply_size);
if (defined($rc)) {
}
die "Error excessive retries\n";
return @{$rc};
}
# Clear any extra junk received on error
sysread($serial,$buf,100);
#print STDERR "Retry " , scalar localtime(time()) , "\n";
sub change_channel { my $change_key;
if (defined($chan_change_key_param)) {
$change_key = $chan_change_key_param;
} else {
$change_key = $chan_change_key{$box_type};
}
if ($change_key) {
foreach $ch (split //,@_0?) {
} else {
send_key($ch);
}
send_key("enter");
my ($channel,$sub)= split /-/,@_0?;
my $s1,$s2,$n1,$n2;
$_=sprintf("%4.4x",$channel);
($n1,$n2)=/(..)(..)/;
if (defined($sub)) {
}
$_=sprintf("%4.4x",$sub);
($s1,$s2)=/(..)(..)/;
} else {
$s1 = "0xff";
$s2 = "0xff";
}
simple_command(map_code("0xA6"),$n1,$n2,$s1,$s2);
sub sendbytes { my (@send)=@_;
my $fullstr = "";
if (!$serial) {
}
$serial=init_serial($serport,$baudrate);
}
if (defined($cmd_extra{$box_type})) {
push @send,$cmd_extra{$box_type};
}
foreach (@send) { s/^0x//g; $_=hex($_); }
print "SEND: " if ($verbose);
foreach $num (@send) {
$str = pack('C',$num);
$fullstr = $fullstr . $str;
printf("0x%X %s? ", $num, $str) if ($verbose);
sub map_code() { my ($key) = (@_);
if ($box_type eq "RCA_OLD") {
}
if ($key ge "0xA0") {
}
return $key;
$key = "0x4" . substr($key,3,1);
} elsif ($key ge "0x90") {
$key = "0x1" . substr($key,3,1);
} else {
$key = "0x0" . substr($key,3,1);
}
sub get_reply() { my ($reply_size) = @_;
#my $starttime=time();
my $starttime=gettimeofday?;
my $found_start = 0;
my ($last,$ok,@ret,$rc);
@ret=();
print "RECV: " if ($verbose);
while (1) {
$rc=sysread($serial,$buf,1);
if ($rc < 0) {
print STDERR "Read Error ($rc)\n" if ($verbose);
last;
}
if ($rc == 0) {
if (tv_interval($starttime) > .8) {
#if (time() - ($starttime) > 2) {
}
print STDERR "Timeout Error\n" if ($verbose);
last;
}
next;
$str=sprintf("0x%2.2X", ord($buf));
if ((!$found_start || $reply_size <= 0) && $pkt_decode{$str}) {
print $str if ($verbose);
print "$pkt_decode{$str}? " if ($verbose);
$_=$str; s/^0x//g; $_=hex($_);
printf("$str(%3.3s) ",$_) if ($verbose);
push (@ret,$_);
if ($found_start && $reply_size-- <= 0) {
}
print "\n\n" if ($verbose);
$ok=1 if ($terminal{$str} > 0);
last if ($terminal{$str});
last if ($last eq "0xFB" && $str eq "0xFB");
}
$found_start = 1 if ($str eq "0xF0");
$last=$str;
return \@ret if ($ok);
return undef;
}
sub init_serial { my($port,$baud)=@_;
my($termios,$cflag,$lflag,$iflag,$oflag);
my($voice);
my $serial=new FileHandle?("+>$port") || die "Could not open $port: $!\n";
binmode($serial);
$termios = POSIX::Termios->new();
$termios->getattr($serial->fileno()) || die "getattr: $!\n";
$cflag= 0 | CS8 | HUPCL | CREAD | CLOCAL;
$lflag= 0;
$iflag= 0 | IGNBRK | IGNPAR;
$oflag= 0;
$termios->setcflag($cflag);
$termios->setlflag($lflag);
$termios->setiflag($iflag);
$termios->setoflag($oflag);
$termios->setattr($serial->fileno(),TCSANOW) || die "setattr: $!\n";
if ($baud "57600" || $baud "115200") {
if ($baud == "115200") {
}
else
{
#perl's implementation of POSIX doesn't have B57600 (or higher)
#terios.h shows 10001 and 10002 for 57600 and 115200 respectively
$termios->setospeed(0010002) || die "setospeed(115200): $!\n";
$termios->setispeed(0010002) || die "setispeed(115200): $!\n";
}
else
{
$termios->setospeed(0010001) || die "setospeed(57600): $!\n";
$termios->setispeed(0010001) || die "setispeed(57600): $!\n";
}
eval qq[
die $@ if $@;
}
$termios->setattr($serial->fileno(),TCSANOW) || die "setattr: $!\n";
\$termios->setospeed(POSIX::B$baud) || die "setospeed: $!\n";
\$termios->setispeed(POSIX::B$baud) || die "setispeed: $!\n";
];
# Make reads wait up to 200ms for a character
$termios->getattr($serial->fileno()) || die "getattr: $!\n";
$termios->setcc(VMIN,0);
$termios->setcc(VTIME,2);
$termios->setattr($serial->fileno(),TCSANOW) || die "setattr: $!\n";
return $serial;
}
EditThisPage BackLinks PageInfo Pages like this Attachments RSS/Atom last changed on Tue Mar 3 21:42:06 2009 |
UpdatedPages· WakeOnLANRouter last changed on Sun Feb 7 05:04:09 2010· KnoppMythWiki last changed on Sat Feb 6 14:22:21 2010 · KnoppMythInstall last changed on Tue Feb 2 04:58:54 2010 · StaticIPConfig last changed on Sun Jan 24 11:02:40 2010 · LinuxTips last changed on Tue Jan 12 05:11:08 2010 · TroubleShooting last changed on Tue Jan 12 05:09:39 2010 · HowTo last changed on Tue Jan 12 05:05:53 2010 · RarFiles last changed on Sun Jan 10 06:13:35 2010 · TinnyAudioPVR150 last changed on Thu Jan 7 19:21:53 2010 · MediaMVP_LinuxHOWTO last changed on Mon Jan 4 07:23:41 2010 · StorageGroups last changed on Mon Dec 14 18:38:15 2009 · SandBox last changed on Mon Nov 30 10:04:30 2009 · NZMythConfig last changed on Fri Nov 27 01:32:05 2009 · webminhowto last changed on Wed Nov 25 16:02:59 2009 · UpgradeHowTo last changed on Tue Nov 24 00:09:52 2009 · MythVodkaHuluFixR6 last changed on Mon Nov 23 18:09:38 2009 · Change Channels with Serial Cable last changed on Sat Nov 21 06:22:23 2009 · x11vncHowTo last changed on Wed Nov 18 09:15:23 2009 · GeForce4 last changed on Sun Nov 15 06:13:50 2009 · WhatCardYouUse last changed on Thu Nov 12 22:54:17 2009 · tv_grab_au last changed on Wed Nov 11 16:58:37 2009 · kworld115HowTo last changed on Sat Nov 7 18:18:53 2009 · AutomatedBackup last changed on Mon Oct 12 11:01:34 2009 · MythBackupAndRestoreHowTo last changed on Mon Oct 12 09:59:40 2009 · HardwareAcceleratedVideo last changed on Mon Oct 5 23:03:26 2009 · RepairingMythConvergDB last changed on Thu Oct 1 18:51:12 2009 |
| sitemap | | |