#include "project.h" #define BRIGHT 30 #define POWER 25 #define SDA 23 #define SCL 24 #define WRITE 0 #define READ 1 #define SAD (0x3C << 1) static void i2c_delay () { nrf_delay_us (1); } static void i2c_set (int c, int d) { uint32_t set = 0; uint32_t clr = 0; if (c) set |= 1 << SCL; else clr |= 1 << SCL; if (d) set |= 1 << SDA; else clr |= 1 << SDA; NRF_GPIO->OUTCLR = clr; NRF_GPIO->OUTSET = set; } static int i2c_get (void) { return ! !(NRF_GPIO->IN & (1 << SDA)); } static void i2c_start (void) { i2c_set (1, 1); i2c_delay (); i2c_set (1, 0); i2c_delay (); i2c_set (0, 0); i2c_delay (); } static void i2c_stop (void) { i2c_set (0, 0); i2c_delay (); i2c_set (1, 0); i2c_delay (); i2c_set (1, 1); i2c_delay (); } static void i2c_init (void) { NRF_GPIO->PIN_CNF[SDA] = (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos) | (GPIO_PIN_CNF_DRIVE_S0D1 << GPIO_PIN_CNF_DRIVE_Pos) | (GPIO_PIN_CNF_PULL_Pullup << GPIO_PIN_CNF_PULL_Pos) | (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) | (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos); NRF_GPIO->PIN_CNF[SCL] = (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos) | (GPIO_PIN_CNF_DRIVE_S0D1 << GPIO_PIN_CNF_DRIVE_Pos) | (GPIO_PIN_CNF_PULL_Pullup << GPIO_PIN_CNF_PULL_Pos) | (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) | (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos); NRF_GPIO->DIRSET = (1 << SDA) | (1 << SCL); i2c_set (1, 1); } static void i2c_send_byte (uint8_t v) { uint8_t c; int d; for (c = 0x80; c; c >>= 1) { d = c & v; i2c_set (0, d); i2c_delay (); i2c_set (1, d); i2c_delay (); } i2c_set (0, d); } static void i2c_handshake (int ack) { i2c_set (0, ack); i2c_delay (); i2c_set (1, ack); i2c_delay (); i2c_set (0, ack); i2c_delay (); } static void inline i2c_send_ack (void) { i2c_handshake (0); } static void inline i2c_send_nack (void) { i2c_handshake (1); } static int i2c_recv_ack (void) { int ret; i2c_set (0, 1); i2c_delay (); i2c_set (1, 1); i2c_delay (); ret = i2c_get (); i2c_set (0, 1); i2c_delay (); return ret; } static void sd_delay (void) { nrf_delay_ms (1); } static int sd_write (int dnc, uint8_t v) { int ret = 0; i2c_start (); i2c_send_byte (SAD | WRITE); ret |= i2c_recv_ack (); i2c_send_byte (dnc ? 0xc0 : 0x80); ret |= i2c_recv_ack (); i2c_send_byte (v); i2c_send_nack (); i2c_stop (); return ret; } static int sd_cmd (uint8_t c) { return sd_write (0, c); } static uint8_t cur_x; static uint8_t cur_y; static int sd_dat (uint8_t c) { cur_x++; return sd_write (1, c); } static int sd_dat0s (size_t len) { int ret = 0; i2c_start (); i2c_send_byte (SAD | WRITE); ret |= i2c_recv_ack (); i2c_send_byte (0x40); ret |= i2c_recv_ack (); while (len--) { i2c_send_byte (0); ret |= i2c_recv_ack (); cur_x++; } i2c_stop (); return ret; } static int sd_dats (uint8_t *v,size_t len) { int ret = 0; i2c_start (); i2c_send_byte (SAD | WRITE); ret |= i2c_recv_ack (); i2c_send_byte (0x40); ret |= i2c_recv_ack (); while (len--) { i2c_send_byte (*(v++)); ret |= i2c_recv_ack (); cur_x++; } i2c_stop (); return ret; } static int sd_address_mode (uint8_t m) { int ret = 0; ret |= sd_cmd (0x20); ret |= sd_cmd (m); return ret; } static int sd_cols (uint8_t s, uint8_t e) { int ret = 0; ret |= sd_cmd (0x21); ret |= sd_cmd (s); ret |= sd_cmd (e); cur_x=s; return ret; } static int sd_rows (uint8_t s, uint8_t e) { int ret = 0; ret |= sd_cmd (0x22); ret |= sd_cmd (s); ret |= sd_cmd (e); cur_y=s; return ret; } void sd_putstr(char *s,int x,int y) { static uint8_t d[8]; while (*s) { if (x!=cur_x) sd_cols (x, 127); if (y!=cur_y) sd_rows (y, 3); gt_read_8x8(*s,d,sizeof(d)); sd_dats(d,sizeof(d)); x+=8; if (x==128) { x=0; y++; } if (y==4) y=0; s++; } } void sd_cls(void) { sd_cols (0, 127); sd_rows (0, 3); sd_dat0s(128*4); } void sd_doodle (void) { //static uint8_t d[8]; sd_putstr("Fishsoup",0,0); //gt_read_8x8('f',d,sizeof(d)); //sd_dats(d,sizeof(d)); } void sd_on (void) { NRF_GPIO->OUTSET = (1 << POWER) | (1 << BRIGHT); nrf_delay_ms (10); // off sd_cmd (0xae); sd_delay (); // set clock freq sd_cmd (0xd5); sd_cmd (0xa0); sd_delay (); // set multiplex ratio sd_cmd (0xa8); sd_cmd (0x1f); sd_delay (); // set display offset sd_cmd (0xd3); sd_cmd (0x00); sd_delay (); // set display start sd_cmd (0x40); sd_delay (); // set charge pump using DC/DC sd_cmd (0x8d); sd_cmd (0x14); sd_delay (); // set segment remap sd_cmd (0xa1); sd_delay (); // set com scan direction sd_cmd (0xc8); sd_delay (); // set com pins hardware config. sd_cmd (0xda); sd_cmd (0x02); sd_delay (); // set contrast sd_cmd (0x81); sd_cmd (0x8f); sd_delay (); // set precharge period using DC/DC sd_cmd (0xd9); sd_cmd (0xf1); sd_delay (); // set deselect voltage sd_cmd (0xdb); sd_cmd (0x40); sd_delay (); // set display on/off sd_cmd (0xa4); sd_delay (); // set display on sd_cmd (0xaf); sd_delay (); sd_address_mode (0); sd_cols (0, 127); sd_rows (0, 3); sd_cls(); } void sd_init (void) { i2c_init (); NRF_GPIO->PIN_CNF[POWER] = (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos) | (GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos) | (GPIO_PIN_CNF_PULL_Pulldown << GPIO_PIN_CNF_PULL_Pos) | (GPIO_PIN_CNF_INPUT_Disconnect << GPIO_PIN_CNF_INPUT_Pos) | (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos); NRF_GPIO->PIN_CNF[BRIGHT] = (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos) | (GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos) | (GPIO_PIN_CNF_PULL_Pulldown << GPIO_PIN_CNF_PULL_Pos) | (GPIO_PIN_CNF_INPUT_Disconnect << GPIO_PIN_CNF_INPUT_Pos) | (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos); NRF_GPIO->DIRSET = (1 << POWER) | (1 << BRIGHT); NRF_GPIO->OUTCLR = (1 << POWER) | (1 << BRIGHT); } // // // #!/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); // } // // // //