From 472ebcbfaccd62adc0c4ab1c59a967c1d7034385 Mon Sep 17 00:00:00 2001 From: root Date: Mon, 7 Sep 2015 11:52:14 +0100 Subject: fish --- reverse_engineering/screen.pl | 429 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 429 insertions(+) create mode 100755 reverse_engineering/screen.pl (limited to 'reverse_engineering/screen.pl') diff --git a/reverse_engineering/screen.pl b/reverse_engineering/screen.pl new file mode 100755 index 0000000..f78bbdf --- /dev/null +++ b/reverse_engineering/screen.pl @@ -0,0 +1,429 @@ +#!/usr/bin/env perl +use strict; + +use GD::Image; + +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); + $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 << 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 ); +} + +sub sd_address_mode($$) { + my ( $ocd, $m ) = @_; + + sd_cmd( $ocd, 0x20 ); + sd_cmd( $ocd, $m ); +} + +sub sd_cols($$$) { + my ( $ocd, $s, $e ) = @_; + + sd_cmd( $ocd, 0x21 ); + sd_cmd( $ocd, $s ); + sd_cmd( $ocd, $e ); +} + +sub sd_rows($$$) { + my ( $ocd, $s, $e ) = @_; + + sd_cmd( $ocd, 0x22 ); + sd_cmd( $ocd, $s ); + sd_cmd( $ocd, $e ); +} + +sub sd_init($) { + my $ocd = shift; + + # off + sd_cmd( $ocd, 0xae ); + + # set clock freq + sd_cmd( $ocd, 0xd5 ); + sd_cmd( $ocd, 0xa0 ); + + #set multiplex ratio + sd_cmd( $ocd, 0xa8 ); + sd_cmd( $ocd, 0x1f ); + + #set display offset + sd_cmd( $ocd, 0xd3 ); + sd_cmd( $ocd, 0x00 ); + + #set display start + sd_cmd( $ocd, 0x40 ); + + #set charge pump using DC/DC + sd_cmd( $ocd, 0x8d ); + sd_cmd( $ocd, 0x14 ); + + #set segment remap + sd_cmd( $ocd, 0xa1 ); + + #set com scan direction + sd_cmd( $ocd, 0xc8 ); + + # set com pins hardware config. + sd_cmd( $ocd, 0xda ); + sd_cmd( $ocd, 0x02 ); + + #set contrast + sd_cmd( $ocd, 0x81 ); + sd_cmd( $ocd, 0x8f ); + + #set precharge period using DC/DC + sd_cmd( $ocd, 0xd9 ); + sd_cmd( $ocd, 0xf1 ); + + #set deselect voltage + sd_cmd( $ocd, 0xdb ); + sd_cmd( $ocd, 0x40 ); + + #set display on/off + sd_cmd( $ocd, 0xa4 ); + + #set display on + sd_cmd( $ocd, 0xaf ); +} + +sub sd_display($$) { + my ( $ocd, $fn ) = @_; + +my $ack; + + my $file=GD::Image->new($fn); + + my $img=GD::Image->new(128,32,1); + + $img->copy($file,0,0,0,0,128,32); + + sd_cols($ocd,0,127); + sd_rows($ocd,0,63); + + + for (my $y=0;$y<32;$y+=8) { + + print "y=$y\n"; + i2c_startaddr( $ocd, $SDADDR ); + i2c_sendbyte( $ocd, 0x40 ); + + i2c_set( $ocd, 0, 1 ); + i2c_set( $ocd, 1, 1 ); + + $ack = i2c_get($ocd); + i2c_set( $ocd, 0, 1 ); + print " "; + + + for (my $x=0;$x<128;++$x) { + + my $v=0; + my $c=0x1; + + for (my $i=0;$i<8;++$i) { + my $w=$img->getPixel($x,$i+$y); + +# print "r=$r,g=$g,b=$b\n"; + + $v|=$c if $w>8388607; + + $c<<=1; + } + + + i2c_sendbyte( $ocd, $v ); + + i2c_set( $ocd, 0, 1 ); + i2c_set( $ocd, 1, 1 ); + + $ack = i2c_get($ocd); + i2c_set( $ocd, 0, 1 ); + + print " "; + + + } + i2c_stop($ocd); + } + + + +} + +my $ocd = open_ocd('127.0.0.1:4444'); + +my $LED = 1 << 22; +my $SCREEN_PWR = 1 << 25; +my $SCREEN_BRIGHT = 1 << 30; + +sub quit +{ + io_clr( $ocd, $SCREEN_PWR ); + io_clr( $ocd, $SCREEN_BRIGHT ); + io_set( $ocd, $LED ); + kill 9, $$; +} + +dir_set( $ocd, $LED | $SCREEN_PWR | $SCREEN_BRIGHT ); +io_clr( $ocd, $SCLBIT | $SDABIT ); +io_clr( $ocd, $LED ); + +i2c_start($ocd); +i2c_stop($ocd); + +#for (my $a=0;$a<0x100;$a++) { +#printf "a=0x%02x ",$a; +#i2c_ping($ocd,$a); +#} +# + +#Power down screen +io_clr( $ocd, $SCREEN_PWR | $SCREEN_BRIGHT ); + +#power up screen +io_set( $ocd, $SCREEN_PWR | $SCREEN_BRIGHT ); +sd_init($ocd); + +sd_address_mode( $ocd, 0x0 ); + +sd_display($ocd,"fish.png"); + +while (1) { + sd_cmd( $ocd, 0xa7 ); + sleep(1); + sd_cmd( $ocd, 0xa6 ); + sleep(1); +} + -- cgit v1.2.3