summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorroot <root@no.no.james.local>2015-09-07 18:43:44 +0100
committerroot <root@no.no.james.local>2015-09-07 18:43:44 +0100
commitb83365010e8338a41988426f879243208714c44f (patch)
tree1ac6607b4910bef7f3fb5768100779a3ce0639e2
parentad7ab5552e41094bb8344e3e0fceef8c1dee90a7 (diff)
downloadbracelet-b83365010e8338a41988426f879243208714c44f.tar.gz
bracelet-b83365010e8338a41988426f879243208714c44f.tar.bz2
bracelet-b83365010e8338a41988426f879243208714c44f.zip
fish
-rw-r--r--crypto/Makefile12
-rw-r--r--crypto/main.c47
-rw-r--r--crypto/project.h32
-rw-r--r--crypto/prototypes.h7
-rw-r--r--crypto/ssd1306.c782
5 files changed, 852 insertions, 28 deletions
diff --git a/crypto/Makefile b/crypto/Makefile
index 0d73725..5494a9f 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -50,11 +50,16 @@ SDKCSRCS= \
SDKSSRCS = toolchain/gcc/gcc_startup_nrf51.s
+PROTOSRCS= \
+ ssd1306.c \
+ main.c
CSRCS = \
bsp/bsp.c \
bsp/bsp_btn_ble.c \
- main.c
+ ${PROTOSRCS}
+
+
SOFTDEVICE=${SDK}/sdk/softdevice/s110/hex/s110_softdevice.hex
@@ -83,6 +88,7 @@ OBJDUMP := $(CROSS)objdump
OBJCOPY := $(CROSS)objcopy
SIZE := $(CROSS)size
GDB := $(CROSS)gdb
+CPROTO := cproto
NRFUTIL := nrfutil
CFLAGS += -mcpu=cortex-m0
@@ -185,6 +191,10 @@ flash_softdevice: ${SOFTDEVICE}
dfu: ${PROG}.zip
nrfdfu -b ${BDADDR} -p ${PROG}.zip
+protos:
+ echo -n > prototypes.h
+ ${CPROTO} -v -e ${CPPFLAGS} ${PROTOSRCS} > prototypes.h.new
+ mv -f prototypes.h.new prototypes.h
#flash: $(MAKECMDGOALS)
# @echo Flashing: $(OUTPUT_BINARY_DIRECTORY)/$<.hex
diff --git a/crypto/main.c b/crypto/main.c
index 2a1c05c..4f15694 100644
--- a/crypto/main.c
+++ b/crypto/main.c
@@ -26,33 +26,7 @@
* Also it would accept pairing requests from any peer device.
*/
-#include <stdint.h>
-#include <string.h>
-#include <sdk/libraries/util/nordic_common.h>
-#include <sdk/device/nrf.h>
-#include <sdk/libraries/util/nrf_assert.h>
-#include <sdk/libraries/util/app_error.h>
-#include <sdk/drivers_nrf/hal/nrf_gpio.h>
-#include <sdk/device/nrf51_bitfields.h>
-#include <sdk/softdevice/s130/headers/ble.h>
-#include <sdk/softdevice/s130/headers/ble_hci.h>
-#include <sdk/ble/common/ble_srv_common.h>
-#include <sdk/ble/ble_advertising/ble_advertising.h>
-#include <sdk/ble/common/ble_advdata.h>
-#include <sdk/ble/ble_services/ble_hids/ble_hids.h>
-#include <sdk/ble/ble_services/ble_bas/ble_bas.h>
-#include <sdk/ble/ble_services/ble_dis/ble_dis.h>
-#include <sdk/ble/common/ble_conn_params.h>
-#include "bsp/bsp.h"
-#include <sdk/libraries/sensorsim/sensorsim.h>
-#include "bsp/bsp_btn_ble.h"
-#include <sdk/libraries/scheduler/app_scheduler.h>
-#include <sdk/softdevice/common/softdevice_handler/softdevice_handler_appsh.h>
-#include <sdk/libraries/timer/app_timer_appsh.h>
-#include <sdk/ble/device_manager/device_manager.h>
-#include <sdk/libraries/button/app_button.h>
-#include <sdk/drivers_nrf/pstorage/pstorage.h>
-#include <sdk/libraries/trace/app_trace.h>
+#include "project.h"
#if BUTTONS_NUMBER <2
#error "Not enough resources on board"
@@ -203,6 +177,8 @@ static sensorsim_state_t m_battery_sim_state;
static app_timer_id_t m_battery_timer_id; /**< Battery timer. */
+static app_timer_id_t sd_timer_id;
+
static dm_application_instance_t m_app_handle; /**< Application identifier allocated by device manager. */
static dm_handle_t m_bonded_peer_handle; /**< Device reference handle to the current bonded central. */
static bool m_caps_on = false; /**< Variable to indicate if Caps Lock is turned on. */
@@ -305,6 +281,12 @@ static void battery_level_update(void)
}
}
+static void sd_timeout_handler(void * p_context)
+{
+ UNUSED_PARAMETER(p_context);
+ sd_doodle();
+}
+
/**@brief Function for handling the Battery measurement timer timeout.
*
@@ -335,6 +317,11 @@ static void timers_init(void)
APP_TIMER_MODE_REPEATED,
battery_level_meas_timeout_handler);
APP_ERROR_CHECK(err_code);
+
+ err_code = app_timer_create(&sd_timer_id,
+ APP_TIMER_MODE_REPEATED,
+ sd_timeout_handler);
+ APP_ERROR_CHECK(err_code);
}
@@ -610,6 +597,9 @@ static void timers_start(void)
err_code = app_timer_start(m_battery_timer_id, BATTERY_LEVEL_MEAS_INTERVAL, NULL);
APP_ERROR_CHECK(err_code);
+
+ err_code = app_timer_start(sd_timer_id, APP_TIMER_TICKS(10,APP_TIMER_PRESCALER),NULL);
+ APP_ERROR_CHECK(err_code);
}
@@ -1486,6 +1476,9 @@ int main(void)
conn_params_init();
buffer_init();
+ sd_init();
+ sd_on();
+
// Start execution.
timers_start();
err_code = ble_advertising_start(BLE_ADV_MODE_FAST);
diff --git a/crypto/project.h b/crypto/project.h
new file mode 100644
index 0000000..cf6fac0
--- /dev/null
+++ b/crypto/project.h
@@ -0,0 +1,32 @@
+#include <stdint.h>
+#include <string.h>
+#include <sdk/libraries/util/nordic_common.h>
+#include <sdk/device/nrf.h>
+#include <sdk/libraries/util/nrf_assert.h>
+#include <sdk/libraries/util/app_error.h>
+#include <sdk/drivers_nrf/hal/nrf_gpio.h>
+#include <sdk/device/nrf51_bitfields.h>
+#include <sdk/softdevice/s130/headers/ble.h>
+#include <sdk/softdevice/s130/headers/ble_hci.h>
+#include <sdk/ble/common/ble_srv_common.h>
+#include <sdk/ble/ble_advertising/ble_advertising.h>
+#include <sdk/ble/common/ble_advdata.h>
+#include <sdk/ble/ble_services/ble_hids/ble_hids.h>
+#include <sdk/ble/ble_services/ble_bas/ble_bas.h>
+#include <sdk/ble/ble_services/ble_dis/ble_dis.h>
+#include <sdk/ble/common/ble_conn_params.h>
+#include "bsp/bsp.h"
+#include <sdk/libraries/sensorsim/sensorsim.h>
+#include "bsp/bsp_btn_ble.h"
+#include <sdk/libraries/scheduler/app_scheduler.h>
+#include <sdk/softdevice/common/softdevice_handler/softdevice_handler_appsh.h>
+#include <sdk/libraries/timer/app_timer_appsh.h>
+#include <sdk/ble/device_manager/device_manager.h>
+#include <sdk/libraries/button/app_button.h>
+#include <sdk/drivers_nrf/pstorage/pstorage.h>
+#include <sdk/libraries/trace/app_trace.h>
+#include <sdk/drivers_nrf/hal/nrf_delay.h>
+
+
+
+#include "prototypes.h"
diff --git a/crypto/prototypes.h b/crypto/prototypes.h
new file mode 100644
index 0000000..35c8abe
--- /dev/null
+++ b/crypto/prototypes.h
@@ -0,0 +1,7 @@
+/* ssd1306.c */
+extern void sd_on(void);
+extern void sd_doodle(void);
+extern void sd_init(void);
+/* main.c */
+extern void assert_nrf_callback(uint16_t line_num, const uint8_t *p_file_name);
+extern int main(void);
diff --git a/crypto/ssd1306.c b/crypto/ssd1306.c
new file mode 100644
index 0000000..95cab2d
--- /dev/null
+++ b/crypto/ssd1306.c
@@ -0,0 +1,782 @@
+#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 (10000);
+}
+
+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 int
+sd_dat (uint8_t c)
+{
+ return sd_write (1, c);
+}
+
+
+
+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);
+
+ 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);
+
+ return ret;
+}
+
+
+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, 63);
+}
+
+void
+sd_doodle (void)
+{
+ static uint8_t i;
+
+ sd_dat (i++);
+}
+
+
+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);
+// }
+//
+//
+//
+//