![]() |
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· WhatRemoteYouUse last changed on Sat Jul 31 10:46:47 2010· WhatCardYouUse last changed on Sat Jul 31 10:45:00 2010 · TinnyAudioPVR150 last changed on Fri Jul 30 03:20:30 2010 · KnoppMythWiki last changed on Thu Jul 29 04:35:17 2010 · HowTo last changed on Wed Jul 28 09:27:02 2010 · HardwareAcceleratedVideo last changed on Tue Jul 27 09:15:10 2010 · MythVodkaHowTo last changed on Tue Jul 27 09:14:04 2010 · DisklessFrontend last changed on Tue Jul 27 09:13:29 2010 · CompileMythTVFromSVN last changed on Tue Jul 27 07:39:28 2010 · MythMusic last changed on Tue Jul 27 07:38:00 2010 · RRD Disk Partition Usage last changed on Sun Jul 25 21:34:12 2010 · UserSuggestions last changed on Sun Jul 25 16:25:51 2010 · Links last changed on Sun Jul 25 16:21:33 2010 · KnoppmythDownloads last changed on Sun Jul 25 14:02:11 2010 · KnoppMythInstall last changed on Sun Jul 25 14:00:46 2010 · TroubleShooting last changed on Wed Jul 21 07:03:13 2010 · webminhowto last changed on Mon Jul 19 07:34:28 2010 · PickingComponents last changed on Wed Jul 14 17:27:40 2010 · mplayerResume last changed on Mon Jul 12 22:54:24 2010 · R5A12DvdRipping last changed on Mon Jul 12 14:44:04 2010 · Additional Software last changed on Mon Jul 12 14:42:31 2010 · HowToUseMyth last changed on Mon Jul 12 14:41:09 2010 · x11vncHowTo last changed on Sun Jul 11 00:06:20 2010 · CountrySpecific last changed on Thu Jul 1 14:48:40 2010 · RepairingMythConvergDB last changed on Thu Jul 1 14:42:58 2010 · tv_grab_au last changed on Tue Jun 29 15:44:05 2010 |
| sitemap | | |