Send commitlog mailing list submissions to
        commitlog@lists.openmoko.org

To subscribe or unsubscribe via the World Wide Web, visit
        http://lists.openmoko.org/mailman/listinfo/commitlog
or, via email, send a message with subject or body 'help' to
        [EMAIL PROTECTED]

You can reach the person managing the list at
        [EMAIL PROTECTED]

When replying, please edit your Subject line so it is more specific
than "Re: Contents of commitlog digest..."
Today's Topics:

   1. r4679 - in developers/werner/ahrt/host/tmc: demo lib
      ([EMAIL PROTECTED])
   2. r4680 - in developers/werner: . neodog ([EMAIL PROTECTED])
--- Begin Message ---
Author: werner
Date: 2008-09-29 02:33:55 +0200 (Mon, 29 Sep 2008)
New Revision: 4679

Added:
   developers/werner/ahrt/host/tmc/demo/eye.py
   developers/werner/ahrt/host/tmc/lib/phosphor.py
Modified:
   developers/werner/ahrt/host/tmc/lib/trigger.py
   developers/werner/ahrt/host/tmc/lib/wave.py
Log:
Highlights:
- new module phosphor.py to view how often patterns repeat
- example eye.py to plot an eye diagram with phosphor.py

Details:
- lib/wave.py (analog, digital): moved binary search by time from "get_one"
  into new method "index"
- lib/trigger.py (edge.apply): returned a false trigger at the start of the
  recording when using slope.Both
- lib/phosphor.py: "phosphor" screen that remembers how often a pixel was drawn
- demo/eye.py: example for drawing an eye diagram with phosphor.py



Added: developers/werner/ahrt/host/tmc/demo/eye.py
===================================================================
--- developers/werner/ahrt/host/tmc/demo/eye.py                         (rev 0)
+++ developers/werner/ahrt/host/tmc/demo/eye.py 2008-09-29 00:33:55 UTC (rev 
4679)
@@ -0,0 +1,156 @@
+#!/usr/bin/python
+
+#
+# @@@ WORK IN PROGRESS.
+#
+# What's missing:
+#
+# - there's no way to display the color bar for reference
+# - there's no easy way to add axis and ticks
+# - the data processing to produce the eye diagram is complex enough that it
+#   deserves to be packaged as one high-level operation in the library
+#
+
+import time
+from tmc.scope import *
+from tmc.trigger import *
+from tmc.phosphor import phosphor
+from math import ceil, floor
+
+#
+# This experiment captures a signal and draws an eye diagram. The eye diagram
+# allows examination of signal integrity and timing violations.
+#
+# Note that this is still a bit primitive. A proper eye diagram would also show
+# the "forbidden" areas.
+#
+# Our test setup is a function generator connected to the channel 2 ("B") of a
+# Rigol DS1000. The function generator emits a 1MHz square wave with slowly
+# (100ns) rising and falling edges.
+#
+# The parameters below:
+#
+# width: the nominal width of a pulse
+# overlap: the time we capture before and after each pulse
+# waveforms: how many waveforms we include in the output
+#
+
+width = 0.5e-6
+overlap = 0.2e-6
+waveforms = 1000
+
+# Open the scope
+
+s = rigol_ds1000c()
+s.debug = False
+
+# Set the horizontal system to have the trigger at the center and the scale
+# set to 10ns/div. We pick this scale because it gives us a 200MSa/s
+# resolution.
+
+s.hor.pos = 0
+s.hor.scale = 10e-9
+#s.hor.scale = 100e-6
+
+# We capture channel "B". Our input has a peak-to-peak voltage of 3.3V, so we
+# set the vertical system such that the screen center is at 1.5V and the scale
+# is 1V/div.
+
+ch = s.ch[1]
+ch.pos = 1.5
+ch.scale = 1
+
+# Define an edge trigger that triggers on the rising edge at 1.65V.
+
+t = edge(slope = slope.Rising, level = 1.65)
+
+# Apply the trigger to channel "B".
+
+t.source(ch)
+
+# Set the horizontal system to single sweep, stop the scope, then start it.
+
+s.hor.sweep = sweep.Single
+s.hor.stop()
+s.hor.run()
+
+# Wait until the scope has triggered and finished the acquisition.
+
+while s.hor.state() != state.Stop:
+    time.sleep(0.1)
+
+# With the above settings, the scope captures about 1.3ms left and right of the
+# trigger. We extract 1ms of the captured waveform.
+
+w = s.wave(ch, start = 0, end = width*waveforms)
+
+# Digitize the waveform and find the rising and falling edges. We construct the
+# trigger to extract the waveforms on the fly.
+
+d = w.digitize(0.8, 2.0)
+e = edge(slope = slope.Both, level = 0.5).apply(d)
+
+# Print what we got.
+
+print len(w), "samples,", len(e), "edges"
+
+# The "phosphor" display operates on a discrete pixel matrix. We therefore
+# obtain a list of the sample values, stripping the time.
+
+samples = map(lambda p: p[1], w)
+
+# Autoscale the y-axis: vcenter is the value at the center of the display. vres
+# is the peak to peak maximum. yres is the arbitrary y resolution we choose.
+# (260 is slightly larger than 256, the typical ADC resolution, so we should
+# get the full dynamic range of the ADC.)
+
+low = min(samples)
+high = max(samples)
+
+vcenter = (high+low)/2
+vres = high-low
+yres = 260
+
+# Autoscale the x-axis: tres is the time interval we want to see. 1/sr is the
+# sample rate. xres is the number of horizontal pixels we give to have each
+# sample its own column.
+
+tres = width+2*overlap
+sr = w.data[1][0]-w.data[0][0]
+xres = tres/sr
+
+# Create a phosphor "screen" with the desired resolution. We add some extra
+# pixels compensate for rounding errors.
+
+ph = phosphor(int(ceil(xres)), yres+2)
+
+# Calculate at which x-offset we put the trigger point.
+
+offset = int(overlap/sr)
+
+# Convert the samples to the y-coordinates on the "screen".
+
+values = map(lambda s: int(round((s-vcenter)/vres*yres+yres/2)), samples)
+
+# Convert all triggers from time to sample indices.
+
+starts = map(lambda t: w.index(t), e)
+
+# Draw the waveform in the window around each trigger index.
+
+for s in starts:
+    ph.draw_window(values, s, offset)
+
+# Generate a PNM image of the screen with the following characteristics:
+#
+# - each screen pixel is represented by a 2x1 rectangle in the image
+# - the frequency is normalized on a logarithmic scale
+# - the frequency of events is indicated with a color spectrum
+
+s = ph.pnm(2, 1, normalize = ph.logarithmic, colors = ph.color_spectrum)
+
+# Write the image to a file called "out.pnm".
+
+f = open("out.pnm", "w")
+print >>f, s
+f.close()


Property changes on: developers/werner/ahrt/host/tmc/demo/eye.py
___________________________________________________________________
Name: svn:executable
   + *

Added: developers/werner/ahrt/host/tmc/lib/phosphor.py
===================================================================
--- developers/werner/ahrt/host/tmc/lib/phosphor.py                             
(rev 0)
+++ developers/werner/ahrt/host/tmc/lib/phosphor.py     2008-09-29 00:33:55 UTC 
(rev 4679)
@@ -0,0 +1,182 @@
+#
+# phosphor.py - "Phosphor" screen that remembers how often a pixel was drawn
+#
+# Copyright (C) 2008 by OpenMoko, Inc.
+# Written by Werner Almesberger <[EMAIL PROTECTED]>
+# All Rights Reserved
+#  
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+
+# @@@ EXPERIMENTAL !
+
+#
+# The screen width is in samples. Lines can only go from one sample to the
+# next, i.e., from x to x+1. Lines don't include their final point, the
+# assumption being that this point will be part of the next line drawn.
+#
+# There are several line algorithms:
+#
+# - "saturated" adds one to each pixel visited
+#
+# - "beam" mimicks the beam on an oscilloscope's CRT by decreasing the
+#    intensity linearly with the length of the line, such that the sum of all
+#    the pixels drawn for that line is one.
+#
+# "saturated" produces good-looking images, but makes areas with a high noise
+# look more intense than they are. "beam" is more accurate, but has the small
+# disadvantage that a lone outlier does not just use a single color.
+#
+# Colors are encoded as RGB tuples, where each component is in the range 0 to
+# 1. The color conversion function is given the value of the pixel, normalized
+# into the range 0 to 1.
+#
+# The following conversion functions are available:
+#
+# - "linear": this is just a linear greyscale from black to white
+#
+# - "default": similar to "linear", but the minimum value is 10% and a mild
+#   fake gamma correction is applied, so that infrequent events are more
+#   visible
+#
+# - "spectrum": uses a simple color spectrum going from blue to green to red
+#
+# Finally also the normalization is configurable:
+#
+# - linear: linear mapping of the range [0, max] to [0, 1]
+#
+# - logarithmic: logarithmic mapping of the range [ln(min), ln(max)] to [0, 1].
+#   Black pixels are excluded from the minimum.
+#
+
+
+from math import log
+
+
+class norm_linear:
+
+    def __init__(self, min, max):
+       self.f = 1.0/max
+
+    def norm(self, v):
+       return self.f*v
+
+
+class norm_logarithmic:
+
+    def __init__(self, min, max):
+       self.offset = -log(min)
+       self.f = 1.0/(log(max)+self.offset)
+
+    def norm(self, v):
+       return self.f*(log(v)+self.offset)
+
+
+class phosphor(object):
+
+    linear = norm_linear
+    logarithmic = norm_logarithmic
+
+    def __init__(self, x, y):
+       self.m = []
+       for i in range(0, x):
+           self.m.append([0.0]*y)
+       self.x = x
+       self.y = y
+
+    def saturated_line(self, x, y0, y1):
+       if y0 == y1:
+           self.m[x][y0] += 1.0
+       elif y0 < y1:
+           for i in range(0, y1-y0):
+               self.m[x][y0+i] += 1.0
+       else:
+           for i in range(0, y0-y1):
+               self.m[x][y0-i] += 1.0
+
+    def beam_line(self, x, y0, y1):
+       if y0 == y1:
+           self.m[x][y0] += 1.0
+       elif y0 < y1:
+           f = 1.0/(y1-y0)
+           for i in range(0, y1-y0):
+               self.m[x][y0+i] += f
+       else:
+           f = 1.0/(y0-y1)
+           for i in range(0, y0-y1):
+               self.m[x][y0-i] += f
+
+    draw_line = beam_line
+
+    #
+    # "draw_window" is where really all the magic happens. It differs from a
+    # simple iteration over a subset of the samples by allowing the reference
+    # point of the waveform and the reference point on the screen to bet set
+    # independently.
+    # 
+    # "samples" is the list of sample values.
+    # "start" is the reference point in the sample list.
+    # "offset" is the on-screen position of the reference point. If "offset" is
+    # positive, samples before "start" are drawn.
+    # 
+
+    def draw_window(self, samples, start = 0, offset = 0):
+       for x in range(max(0, offset-start),
+         min(self.x, len(samples)-start+offset)-1):
+           pos = start+x-offset
+           self.draw_line(x, samples[pos], samples[pos+1])
+
+    def color_default(self, v):
+       return [0.1+0.9*v*(2.0-v)]*3
+
+    def color_linear(self, v):
+       return (v, v, v)
+
+    def color_spectrum(self, v):
+       return (
+         max(0.0, (4.0*v-4.0)*(1.0-v)+1.0),
+         max(0.0, 8.0*v*(1.0-v)-1.0),
+         max(0.0, 4.0*v*-v+1.0))
+       return (
+         min(1.0, max(0.0, (2.0*v-2.0)*(v+0.5)+1.0)),
+         max(0.0, 16.0*v*(1.0-v)-1.0),
+         min(1.0, 8.0*v*v))
+
+    def max(self):
+       return reduce(lambda a, b: max(a, max(b)), self.m, 0)
+
+    def min(self):
+       return reduce(lambda a, b: min(a,
+         reduce(lambda a, b: [a, min(a, b)][b != 0], b, 1)),
+          self.m, 1)
+
+    def pnm(self, px = 1, py = 1, colors = None, normalize = norm_linear):
+       if colors is None:
+           fn = self.color_default
+       elif isinstance(colors, list):
+           fn = lambda v: colors[min(len(colors)-1, int(v*len(colors)))]
+       else:
+           fn = colors
+
+       s = "P6 %d %d 255\n" % (self.x*px, self.y*py)
+
+       norm = normalize(self.min(), self.max())
+
+       for y in range(self.y-1, -1, -1):
+           row = ""
+           for x in range(0, self.x):
+               if self.m[x][y] == 0:
+                   t = (0, 0, 0)
+               else:
+                   t = fn(norm.norm(self.m[x][y]))
+               t = chr(min(int(t[0]*256), 255))+ \
+                 chr(min(int(t[1]*256), 255))+ \
+                 chr(min(int(t[2]*256), 255))
+               for i in range(0, px):
+                   row += t
+           for i in range(0, py):
+               s += row
+       return s


Property changes on: developers/werner/ahrt/host/tmc/lib/phosphor.py
___________________________________________________________________
Name: svn:executable
   + *

Modified: developers/werner/ahrt/host/tmc/lib/trigger.py
===================================================================
--- developers/werner/ahrt/host/tmc/lib/trigger.py      2008-09-28 02:12:36 UTC 
(rev 4678)
+++ developers/werner/ahrt/host/tmc/lib/trigger.py      2008-09-29 00:33:55 UTC 
(rev 4679)
@@ -109,7 +109,7 @@
        if self.level <= 0 or self.level >= 1:
            return []
        if self.slope == slope.Both:
-           return wave.data[:]
+           return wave.data[1:]
        res = []
        i = int(wave.initial ^ self.slope == slope.Falling)+1
        while i < len(wave.data):

Modified: developers/werner/ahrt/host/tmc/lib/wave.py
===================================================================
--- developers/werner/ahrt/host/tmc/lib/wave.py 2008-09-28 02:12:36 UTC (rev 
4678)
+++ developers/werner/ahrt/host/tmc/lib/wave.py 2008-09-29 00:33:55 UTC (rev 
4679)
@@ -344,11 +344,14 @@
            raise hell
        self.data.extend(wave.data)
 
-    def get_one(self, t):
+    def index(self, t):
        if len(self.data) == 0 or t < self.data[0][0] or t > self.data[-1][0]:
            raise hell
-       return self.data[binary(self.data, lambda x: x[0], t)]
+       return binary(self.data, lambda x: x[0], t)
 
+    def get_one(self, t):
+       return self.data[self.index(t)]
+
     def __iter__(self):
        return analog_iter(self)
 
@@ -434,11 +437,15 @@
            self.data.extend(wave.data[1:])
        self.t_end = wave.t_end
 
+    def index(self, t):
+       if len(self.data) == 0 or t < self.data[0] or t > self.t_end:
+           raise hell
+       return binary(self.data, lambda x: x, t)
+
     def get_one(self, t):
        if len(self.data) == 0 or t < self.data[0] or t > self.t_end:
            raise hell
-       return int(self.initial ^
-         (binary(self.data, lambda x: x, t) & 1))
+       return int(self.initial ^ (self.index(t) & 1))
 
     # experimental
 




--- End Message ---
--- Begin Message ---
Author: werner
Date: 2008-09-29 08:07:38 +0200 (Mon, 29 Sep 2008)
New Revision: 4680

Added:
   developers/werner/neodog/
   developers/werner/neodog/Makefile
   developers/werner/neodog/event.c
   developers/werner/neodog/neodog.c
   developers/werner/neodog/neodog.h
   developers/werner/neodog/pmu.c
Log:
Tough watchdog daemon.



Added: developers/werner/neodog/Makefile
===================================================================
--- developers/werner/neodog/Makefile                           (rev 0)
+++ developers/werner/neodog/Makefile   2008-09-29 06:07:38 UTC (rev 4680)
@@ -0,0 +1,25 @@
+CC=arm-angstrom-linux-gnueabi-gcc
+
+CFLAGS=-Wall -Wshadow -g -O
+
+OBJS=neodog.o event.o pmu.o
+
+.PHONY:                all clean depend spotless
+
+all:           neodog
+
+neodog:                $(OBJS)
+
+depend:
+               $(CPP) $(CFLAGS) -MM -MG *.c >.depend || \
+                 { rm -f .depend; exit 1; }
+
+ifeq (.depend,$(wildcard .depend))
+include .depend
+endif
+
+clean:
+               rm -f $(OBJS) .depend
+
+spotless:      clean
+               rm -f neodog

Added: developers/werner/neodog/event.c
===================================================================
--- developers/werner/neodog/event.c                            (rev 0)
+++ developers/werner/neodog/event.c    2008-09-29 06:07:38 UTC (rev 4680)
@@ -0,0 +1,58 @@
+/*
+ * event.c - Direct I2C polling in case events are lost
+ *
+ * Copyright (C) 2008 by OpenMoko, Inc.
+ * Written by Werner Almesberger <[EMAIL PROTECTED]>
+ * All Rights Reserved
+ *  
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/types.h>
+
+#include <linux/input.h>
+
+#include "neodog.h"
+
+
+#define        EVENT_DEVICE    "/dev/input/event2"
+
+
+int process_event(int fd)
+{
+       struct input_event ev;
+       ssize_t got;
+
+       got = read(fd, &ev, sizeof(ev));
+       if (got < 0) {
+               perror("read");
+               return 0;
+       }
+       if (got != sizeof(ev))
+               return 0;
+       if (ev.type != EV_KEY)
+               return 0;
+       if (ev.code != KEY_POWER)
+               return 0;
+       return ev.value ? 1 : -1;
+}
+
+
+int open_event(void)
+{
+       int fd;
+
+       fd = open(EVENT_DEVICE, O_RDONLY);
+       if (fd < 0) {
+               perror(EVENT_DEVICE);
+               exit(1);
+       }
+       return fd;
+}

Added: developers/werner/neodog/neodog.c
===================================================================
--- developers/werner/neodog/neodog.c                           (rev 0)
+++ developers/werner/neodog/neodog.c   2008-09-29 06:07:38 UTC (rev 4680)
@@ -0,0 +1,133 @@
+/*
+ * neodog.c - Tough watchdog daemon
+ *
+ * Copyright (C) 2008 by OpenMoko, Inc.
+ * Written by Werner Almesberger <[EMAIL PROTECTED]>
+ * All Rights Reserved
+ *  
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <signal.h>
+#include <time.h>
+#include <sched.h>
+#include <poll.h>
+#include <sys/mman.h>
+
+#include <linux/unistd.h>
+#include <linux/reboot.h>
+
+#include "neodog.h"
+
+
+#define TIMEOUT        8       /* power down if ONKEY is held for 8 seconds */
+
+
+static void invulnerabilize(void)
+{
+       struct sched_param prm;
+
+       if (mlockall(MCL_CURRENT | MCL_FUTURE) < 0) {
+               perror("mlockall");
+               exit(1);
+       }
+       prm.sched_priority = sched_get_priority_max(SCHED_FIFO);
+       if (prm.sched_priority < 0) {
+               perror("sched_get_priority_max SCHED_FIFO");
+               exit(1);
+       }
+       if (sched_setscheduler(0,SCHED_FIFO,&prm) < 0) {
+               perror("sched_setscheduler SCHED_FIFO");
+               exit(1);
+       }
+       signal(SIGHUP, SIG_IGN);
+       signal(SIGINT, SIG_IGN);
+       signal(SIGQUIT, SIG_IGN);
+       signal(SIGTERM, SIG_IGN);
+       signal(SIGUSR1, SIG_IGN);
+       signal(SIGUSR2, SIG_IGN);
+}
+
+
+static void power_off(int sig)
+{
+#ifdef DEBUG
+       fprintf(stderr, "***ALARM***\n");
+       return;
+#endif
+       syscall(__NR_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
+           LINUX_REBOOT_CMD_POWER_OFF);
+}
+
+
+static void set_alarm(int on)
+{
+       static int is_on = 0;
+
+#ifdef DEBUG
+       fprintf(stderr, "set_alarm(%d)\n", on);
+#endif
+       if (on == is_on)
+               return;
+       is_on = on;
+       if (on)
+               alarm(TIMEOUT);
+       else
+               alarm(0);
+}
+
+
+int main(void)
+{
+       struct pollfd event = {
+               .fd = open_event(),
+               .events = POLLIN,
+       };
+       time_t next = 0;
+       int pmu;
+
+       /*
+        * It's a bit overkill to listen to events and to pull the PMU.
+        * The events give us better response granularity, but we also need to
+        * poll in case something overruns the event buffer.
+        */
+       pmu = open_pmu();
+       invulnerabilize();
+       signal(SIGALRM, power_off);
+       while (1) {
+               int fds;
+               time_t now;
+
+               fds = poll(&event, 1, 1000);
+               if (fds < 0) {
+                       perror("poll");
+                       return 1;
+               }
+               time(&now);
+               if (fds) {
+                       switch (process_event(event.fd)) {
+                       case 0:
+                               break;
+                       case 1:
+                               set_alarm(0);
+                               break;
+                       case -1:
+                               set_alarm(0);
+                               break;
+                       default:
+                               abort();
+                       }
+               }
+               if (!fds || now >= next) {
+                       set_alarm(get_onkey(pmu));
+                       next = now+1;
+               }
+       }
+}

Added: developers/werner/neodog/neodog.h
===================================================================
--- developers/werner/neodog/neodog.h                           (rev 0)
+++ developers/werner/neodog/neodog.h   2008-09-29 06:07:38 UTC (rev 4680)
@@ -0,0 +1,23 @@
+/*
+ * neodog.h - Tough watchdog daemon
+ *
+ * Copyright (C) 2008 by OpenMoko, Inc.
+ * Written by Werner Almesberger <[EMAIL PROTECTED]>
+ * All Rights Reserved
+ *  
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef NEODOG_H
+#define NEODOG_H
+
+int get_onkey(int fd);
+int open_pmu(void);
+
+int process_event(int fd);
+int open_event(void);
+
+#endif /* !NEODOG_H */

Added: developers/werner/neodog/pmu.c
===================================================================
--- developers/werner/neodog/pmu.c                              (rev 0)
+++ developers/werner/neodog/pmu.c      2008-09-29 06:07:38 UTC (rev 4680)
@@ -0,0 +1,65 @@
+/*
+ * pmu.c - Direct I2C polling in case events are lost
+ *
+ * Copyright (C) 2008 by OpenMoko, Inc.
+ * Written by Werner Almesberger <[EMAIL PROTECTED]>
+ * All Rights Reserved
+ *  
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+
+#include <linux/i2c.h>
+#include <linux/i2c-dev.h>
+
+#include "neodog.h"
+
+
+#define I2C_DEVICE     "/dev/i2c-0"
+#define I2C_ADDRESS    0x73
+
+#define OOCSTAT                0x12
+#define        OOCSTAT_ONKEY   1
+
+
+int get_onkey(int fd)
+{
+       uint8_t oocstat;
+       struct i2c_smbus_ioctl_data msg = {
+               .read_write     = I2C_SMBUS_READ,
+               .command        = OOCSTAT,
+               .size           = I2C_SMBUS_BYTE_DATA,
+               .data           = (void *) &oocstat,
+       };
+
+       if (ioctl(fd, I2C_SMBUS, (void *) &msg) < 0) {
+               perror("ioctl(I2C_RDWR)");
+               exit(1);
+       }
+       return !(oocstat & OOCSTAT_ONKEY);
+}
+
+
+int open_pmu(void)
+{
+       int fd;
+
+       fd = open(I2C_DEVICE, O_RDWR);
+       if (fd < 0) {
+               perror(I2C_DEVICE);
+               exit(1);
+       }
+       if (ioctl(fd, I2C_SLAVE_FORCE, I2C_ADDRESS) < 0) {
+               perror("ioctl(I2C_SLAVE_FORCE)");
+               exit(1);
+       }
+       return fd;
+}




--- End Message ---
_______________________________________________
commitlog mailing list
commitlog@lists.openmoko.org
http://lists.openmoko.org/mailman/listinfo/commitlog

Reply via email to