#!/usr/bin/env perl use strict; use IO::Socket::INET; use Data::Dumper; #use IO::Socket::Timeout; # # $SIG{INT}=\&quit; my $prompt= '> '; sub my_readline_worker($) { my $sock=shift; my $ret=""; my $d=""; while (1) { return $ret if $sock->read($d,1)!=1; next if $d eq "\n"; $ret.=$d; return $ret if $d eq "\r"; return $ret if $ret =~ /> $/; } } sub my_readline($) { my $sock=shift; my $ret=my_readline_worker($sock); #print $ret."\n"; return $ret; } sub wait_for_prompt($) { my $ocd=shift; 1 while (my_readline($ocd) ne $prompt); } sub open_ocd($) { my $addr=shift; my $sock = IO::Socket::INET->new( $addr); wait_for_prompt($sock); return $sock; } sub write_reg($$$) { my ($ocd,$r,$v)=@_; $ocd->printf("mww 0x%08x 0x%08x\n",$r,$v); wait_for_prompt($ocd); } sub read_reg($$) { my ($ocd,$r)=@_; my $ret; $ocd->printf("mdw 0x%08x\n",$r); $ret=my_readline($ocd); $ret=my_readline($ocd); wait_for_prompt($ocd); $ret =~ s/[\r\n\s]//g; if ($ret =~ /0x[0-9A-Fa-f]+:([0-9a-fA-F]+)/) { return hex($1); } return undef; } sub dir_set($$) { my ($ocd,$v)=@_; write_reg($ocd,0x50000518,$v); } sub dir_clr($$) { my ($ocd,$v)=@_; write_reg($ocd,0x5000051c,$v); } sub io_set($$) { my ($ocd,$v)=@_; write_reg($ocd,0x50000508,$v); } sub io_clr($$) { my ($ocd,$v)=@_; write_reg($ocd,0x5000050c,$v); } sub io_get($) { my $ocd=shift; return read_reg($ocd,0x50000510); } my $SDABIT=1<<23; my $SCLBIT=1<<24; sub i2c_set($$$) { my ($ocd,$scl,$sda) =@_; my $clr=0; my $set=0; if ($scl) { $clr|=$SCLBIT; } else { $set|=$SCLBIT; } if ($sda) { $clr|=$SDABIT; } else { $set|=$SDABIT; } dir_set($ocd,$set); dir_clr($ocd,$clr); } sub i2c_get($) { my $ocd=shift; return (io_get($ocd) & $SDABIT ) ? 1:0; } sub i2c_start($) { my $ocd=shift; i2c_set($ocd,1,1); i2c_set($ocd,1,0); i2c_set($ocd,0,0); print "S"; } sub i2c_stop($) { my $ocd=shift; i2c_set($ocd,0,0); i2c_set($ocd,1,0); i2c_set($ocd,1,1); print "T\n"; } sub i2c_sendbyte($$) { my ($ocd,$byte) =@_; for ( my $c=0x80; $c; $c>>=1) { my $v=($c & $byte) ? 1:0; print $v; i2c_set($ocd,0,$v); i2c_set($ocd,1,$v); i2c_set($ocd,0,$v); } } sub i2c_startaddr($$) { my ($ocd,$addr) =@_; my $ret; i2c_start($ocd); i2c_sendbyte($ocd,$addr); print " "; i2c_set($ocd,0,1); i2c_set($ocd,1,1); $ret=i2c_get($ocd); i2c_set($ocd,0,1); print $ret; return $ret; } sub i2c_ping($$) { my ($ocd,$addr) =@_; my $ret; $ret=i2c_startaddr($ocd,$addr); i2c_stop($ocd); return $ret; } my $SDADDR=0x78; sub sd_write($$$) { my ($ocd,$dnc,$v)=@_; my $ack1; my $ack2; i2c_startaddr($ocd,$SDADDR); i2c_sendbyte($ocd,0x80| ($dnc ? 0x40:0x00)); i2c_set($ocd,0,1); i2c_set($ocd,1,1); $ack1=i2c_get($ocd); i2c_set($ocd,0,1); i2c_sendbyte($ocd,$v); i2c_set($ocd,0,1); i2c_set($ocd,1,1); $ack2=i2c_get($ocd); i2c_set($ocd,0,1); i2c_stop($ocd); return $ack1 | $ack2; } sub sd_cmd($$) { my ($ocd,$c)=@_; return sd_write($ocd,0,$c); } sub sd_dat($$) { my ($ocd,$d)=@_; return sd_write($ocd,1,$d); } my $LED=1<<22; my $SCREEN_PWR=1<<25; my $SCREEN_NRESET=1<<30; my $ocd=open_ocd('127.0.0.1:4444' ); sub quit { io_clr($ocd,$SCREEN_PWR); io_set($ocd,$LED); kill 9,$$; } io_clr($ocd,$SCLBIT | $SDABIT); dir_set($ocd,$LED | $SCREEN_PWR); io_clr($ocd,$LED); io_clr($ocd,$SCREEN_PWR); i2c_start($ocd); i2c_stop($ocd); for (my $a=0;$a<0x100;$a++) { printf "a=0x%02x ",$a; i2c_ping($ocd,$a); }