#!/usr/bin/env perl use strict; use IO::Socket::INET; use Data::Dumper; 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); $sock->printf( "reset halt\n"); 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 << 9; my $SCLBIT = 1 << 8; 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_recvbyte($) { my ($ocd) = @_; my $byte = 0; for ( my $c = 0x80 ; $c ; $c >>= 1 ) { my $v; i2c_set( $ocd, 0, 1 ); i2c_set( $ocd, 1, 1 ); $v = i2c_get($ocd); #print $v; $byte |= $c if $v; i2c_set( $ocd, 0, 1 ); } return $byte; } 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 $EE_ADDR = 0xa0; #sub lis_write($$$) { # my ( $ocd, $reg, $v ) = @_; # # my $ret; # # i2c_startaddr( $ocd, $LIS_ADDR ); # # i2c_sendbyte( $ocd, $reg ); # # i2c_set( $ocd, 0, 1 ); # i2c_set( $ocd, 1, 1 ); # $ret = i2c_get($ocd); # i2c_set( $ocd, 0, 1 ); # # i2c_sendbyte( $ocd, $v ); # # i2c_set( $ocd, 0, 1 ); # i2c_set( $ocd, 1, 1 ); # i2c_set( $ocd, 0, 1 ); # # i2c_stop($ocd); #} # sub ee_read($$) { my ( $ocd, $a ) = @_; my $ret; i2c_startaddr( $ocd, $EE_ADDR ); i2c_sendbyte( $ocd, ($a >> 8 ) & 0xff ); i2c_set( $ocd, 0, 1 ); i2c_set( $ocd, 1, 1 ); i2c_set( $ocd, 0, 1 ); i2c_sendbyte( $ocd, $a & 0xff ); i2c_set( $ocd, 0, 1 ); i2c_set( $ocd, 1, 1 ); i2c_set( $ocd, 0, 1 ); # mad repeated start i2c_set( $ocd, 0, 1 ); i2c_set( $ocd, 1, 1 ); i2c_startaddr( $ocd, $EE_ADDR | 1 ); $ret = i2c_recvbyte($ocd); i2c_set( $ocd, 0, 1 ); i2c_set( $ocd, 1, 1 ); i2c_set( $ocd, 0, 1 ); i2c_stop($ocd); return $ret; } my $ocd = open_ocd('127.0.0.1:4444'); io_clr( $ocd, $SCLBIT | $SDABIT ); i2c_start($ocd); i2c_stop($ocd); $|=1; for (my $i=0;$i<0x100;$i+=0x10) { printf "%04x ",$i; for (my $j=0;$j<0x10;$j++) { printf " %02x",ee_read($ocd,$i+$j); } printf "\n"; } die;