This is the mail archive of the ecos-patches@sourceware.org mailing list for the eCos project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

ADC device support


In preparation for V3.0 I have just checked in a new package that
provides the generic layers for Analog/Digital Convertors. At present
is is fairly simple and straightforward, supporting basic settings for
sample rates and channel enable/disable. Features of more advance
devices (e.g. variable sample rates, triggers) are not currently
supported, but could easily be added.

In addition to this package, a hardware-level driver is required to
support a specific ADC device. An example device is not currently
present, the only instances of these we have are for customer boards
with special hardware. However, the documentation should allow a
driver to be written fairly easily.


Below is the entire patch...


Index: doc/ChangeLog
===================================================================
RCS file: /cvs/ecos/ecos/doc/ChangeLog,v
retrieving revision 1.32
diff -u -5 -r1.32 ChangeLog
--- doc/ChangeLog	12 Jul 2008 10:51:53 -0000	1.32
+++ doc/ChangeLog	8 Aug 2008 10:36:26 -0000
@@ -1,5 +1,9 @@
+2008-08-08  Nick Garnett  <nickg@ecoscentric.com>
+
+	* sgml/doclist: Added ADC documentation.
+
 2008-07-12  Andrew Lunn  <andrew.lunn@ascom.ch>
 
 	* sgml/doclist: added USB Serial documentation
 	
 2006-12-16 Uwe.Kindler <uwe.kindler@cetoni.de>
Index: doc/sgml/doclist
===================================================================
RCS file: /cvs/ecos/ecos/doc/sgml/doclist,v
retrieving revision 1.22
diff -u -5 -r1.22 doclist
--- doc/sgml/doclist	12 Jul 2008 10:51:54 -0000	1.22
+++ doc/sgml/doclist	8 Aug 2008 10:36:26 -0000
@@ -7,10 +7,11 @@
 io/pci/current/doc/pci.sgml
 io/flash/current/doc/flash.sgml
 io/spi/current/doc/spi.sgml
 io/i2c/current/doc/i2c.sgml
 io/can/current/doc/can.sgml
+io/adc/current/doc/adc.sgml
 compat/posix/current/doc/posix.sgml
 compat/uitron/current/doc/uitron.sgml
 net/common/current/doc/tcpip.sgml
 net/common/current/doc/tcpip-manpages.sgml
 net/bsd_tcpip/current/doc/freebsd.sgml
Index: packages/ChangeLog
===================================================================
RCS file: /cvs/ecos/ecos/packages/ChangeLog,v
retrieving revision 1.185
diff -u -5 -r1.185 ChangeLog
--- packages/ChangeLog	12 Jul 2008 14:33:02 -0000	1.185
+++ packages/ChangeLog	8 Aug 2008 10:36:27 -0000
@@ -1,5 +1,10 @@
+2008-08-08  Nick Garnett  <nickg@ecoscentric.com>
+
+	* NEWS: 
+	* ecos.db: Add generic ADC package.
+
 2008-07-08   Uwe Kindler <uwe_kindler@web.de>
  
  	* NEWS:
 	* ecos.db: Add EA LPC2468 OEM board, target, flash driver,
  	LPC24XXX variant + serial driver
Index: packages/NEWS
===================================================================
RCS file: /cvs/ecos/ecos/packages/NEWS,v
retrieving revision 1.109
diff -u -5 -r1.109 NEWS
--- packages/NEWS	12 Jul 2008 14:33:02 -0000	1.109
+++ packages/NEWS	8 Aug 2008 10:36:27 -0000
@@ -1,5 +1,6 @@
+* Generic ADC support contributed by eCosCentric Ltd.
 * Port to Embedded Artists LPC2468 OEM board by Uwe Kindler.
 * USB serial class driver by Frank Pagliughi.
 * FR30 arch, mb91301 variant and skmb91302 platform by Lars Poeschel.
 * phyCORE-LPC2294/92 port including flash and CAN by Uwe Kindler.
 * AT91 CAN driver by Uwe Kindler.
Index: packages/ecos.db
===================================================================
RCS file: /cvs/ecos/ecos/packages/ecos.db,v
retrieving revision 1.172
diff -u -5 -r1.172 ecos.db
--- packages/ecos.db	12 Jul 2008 14:33:02 -0000	1.172
+++ packages/ecos.db	8 Aug 2008 10:36:28 -0000
@@ -2274,10 +2274,19 @@
 	description "
             This packages provides an I2C driver for the on-chip
 	        device provided by the MCF52xx coldfire processor family."
 }
 
+package CYGPKG_IO_ADC {
+	alias 		{ "Genric ADC support" adc io_adc }
+	directory	io/adc
+	script		io_adc.cdl
+        description "
+           This package contains drivers for basic I/O services on
+           adc devices."
+}
+
 package CYGPKG_KERNEL {
 	alias		{ "eCos kernel" kernel }
 	directory	kernel
 	script		kernel.cdl
      	description "
Index: packages/io/adc/current/ChangeLog
===================================================================
RCS file: packages/io/adc/current/ChangeLog
diff -N packages/io/adc/current/ChangeLog
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ packages/io/adc/current/ChangeLog	8 Aug 2008 10:36:30 -0000
@@ -0,0 +1,39 @@
+2008-08-08  Nick Garnett  <nickg@ecoscentric.com>
+
+	* cdl/io_adc.cdl:
+	* doc/adc.sgml:
+	* include/adc.h: 
+	* src/adc.c:
+	New package -- ADC generic driver support.
+
+##==========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 2008 eCosCentric Limited
+//
+// eCos 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 or (at your option) any later version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+##==========================================================================
Index: packages/io/adc/current/cdl/io_adc.cdl
===================================================================
RCS file: packages/io/adc/current/cdl/io_adc.cdl
diff -N packages/io/adc/current/cdl/io_adc.cdl
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ packages/io/adc/current/cdl/io_adc.cdl	8 Aug 2008 10:36:30 -0000
@@ -0,0 +1,92 @@
+##==========================================================================
+##
+##      io_adc.cdl
+##
+##      Generic ADC driver layer
+##
+##==========================================================================
+#####ECOSGPLCOPYRIGHTBEGIN####
+## -------------------------------------------
+## This file is part of eCos, the Embedded Configurable Operating System.
+## Copyright (C) 2008 eCosCentric Limited
+##
+## eCos 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 or (at your option) any later version.
+##
+## eCos is distributed in the hope that it will be useful, but WITHOUT ANY
+## WARRANTY; without even the implied warranty of MERCHANTABILITY or
+## FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+## for more details.
+##
+## You should have received a copy of the GNU General Public License along
+## with eCos; if not, write to the Free Software Foundation, Inc.,
+## 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+##
+## As a special exception, if other files instantiate templates or use macros
+## or inline functions from this file, or you compile this file and link it
+## with other works to produce a work based on this file, this file does not
+## by itself cause the resulting work to be covered by the GNU General Public
+## License. However the source code for this file must still be made available
+## in accordance with section (3) of the GNU General Public License.
+##
+## This exception does not invalidate any other reasons why a work based on
+## this file might be covered by the GNU General Public License.
+## -------------------------------------------
+#####ECOSGPLCOPYRIGHTEND####
+##==========================================================================
+#######DESCRIPTIONBEGIN####
+##
+## Author(s):    nickg
+## Date:         2008-03-31
+## Description:  Implements generic layer of ADC drivers.
+##
+######DESCRIPTIONEND####
+##
+##========================================================================*/
+
+
+cdl_package CYGPKG_IO_ADC {
+    display       "ADC device drivers"
+    parent        CYGPKG_IO
+    active_if     CYGPKG_IO
+    requires      CYGPKG_ERROR
+    include_dir   cyg/io
+    description   "
+        This option enables drivers for basic I/O services on
+        ADC devices."
+
+    compile       -library=libextras.a adc.c
+
+    cdl_component CYGPKG_IO_ADC_DEVICES {
+        display       "Hardware ADC device drivers"
+        flavor        bool
+        default_value 0
+        description   "
+            This option enables the hardware device drivers
+	    for the current platform."
+    }
+
+    cdl_option CYGNUM_IO_ADC_SAMPLE_SIZE {
+        display       "Sample size"
+        flavor        data
+        default_value 16
+        legal_values  0 to 32
+
+        description   "This option defines the sample size for the ADC devices.
+                       Given in bits, it will be rounded up to 8, 16 or 32 to define
+                       the cyg_adc_sample_t type."
+    }
+    
+    cdl_option CYGPKG_IO_ADC_SELECT_SUPPORT {
+	display "Enable ADC device select support"
+	flavor bool
+	active_if CYGPKG_IO_FILEIO
+	requires  { CYGFUN_IO_FILEIO_SELECT == 1 }
+	default_value 1
+	description "
+	    This option enables support for the select() API function on all
+	    ADC devices."
+    }
+    
+}    
Index: packages/io/adc/current/doc/adc.sgml
===================================================================
RCS file: packages/io/adc/current/doc/adc.sgml
diff -N packages/io/adc/current/doc/adc.sgml
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ packages/io/adc/current/doc/adc.sgml	8 Aug 2008 10:36:30 -0000
@@ -0,0 +1,692 @@
+<!-- DOCTYPE part  PUBLIC "-//OASIS//DTD DocBook V3.1//EN" -->
+
+<!-- {{{ Banner                         -->
+
+<!-- =============================================================== -->
+<!--                                                                 -->
+<!--     adc.sgml                                                    -->
+<!--                                                                 -->
+<!--     Generic ADC documentation.                                  -->
+<!--                                                                 -->
+<!-- =============================================================== -->
+<!-- ####COPYRIGHTBEGIN####                                          -->
+<!--                                                                 -->
+<!-- =============================================================== -->
+<!-- Copyright (C) 2008 eCosCentric Limited                          -->
+<!-- This material may be distributed only subject to the terms      -->
+<!-- and conditions set forth in the Open Publication License, v1.0  -->
+<!-- or later (the latest version is presently available at          -->
+<!-- http://www.opencontent.org/openpub/)                            -->
+<!-- Distribution of the work or derivative of the work in any       -->
+<!-- standard (paper) book form is prohibited unless prior           -->
+<!-- permission obtained from the copyright holder                   -->
+<!-- =============================================================== -->
+<!--                                                                 -->      
+<!-- ####COPYRIGHTEND####                                            -->
+<!-- =============================================================== -->
+<!-- #####DESCRIPTIONBEGIN####                                       -->
+<!--                                                                 -->
+<!-- Author(s):   nickg                                              -->
+<!-- Date:        2008/05/12                                         -->
+<!--                                                                 -->
+<!-- ####DESCRIPTIONEND####                                          -->
+<!-- =============================================================== -->
+
+<!-- }}} -->
+
+<part id="io-adc"><title>ADC Support</title>
+
+<refentry id="adc">
+  <refmeta>
+    <refentrytitle>Overview</refentrytitle>
+  </refmeta>
+  <refnamediv>
+    <refname>Overview</refname>
+    <refpurpose>eCos Support for Analog/Digital Converters</refpurpose>
+  </refnamediv>
+
+  <refsect1 id="adc-intro"><title>Introduction</title>
+
+<para>
+ADC support in eCos is based around the standard character device
+interface. Hence all device IO function, or file IO functions may be
+used to access ADC devices.
+</para>
+
+<para>
+ADC devices are presented as read-only serial channels that generate
+samples at a given rate. The size of each sample is hardware specific
+and is defined by the <type>cyg_adc_sample_t</type> type. The sample
+rate may be set at runtime by the application. Most ADC devices
+support several channels which are all sampled at the same
+rate. Therefore setting the rate for one channel will usually change
+the rate for all channels on that device.
+</para>
+
+
+</refsect1>
+
+<refsect1 id="adc-examples"><title>Examples</title>
+
+<para>
+The use of the ADC devices is best shown by example.  The following is
+a simple example of using the eCos device interface to access the ADC:
+</para>
+
+<programlisting width=72>
+
+        int res;
+        cyg_io_handle_t handle;
+
+        // Get a handle for ADC device 0 channel 0
+        res = cyg_io_lookup( "/dev/adc00", &amp;handle );
+
+        if( res != ENOERR )
+            handle_error(err);
+
+        for(;;)
+        {
+            cyg_adc_sample_t sample;
+            cyg_uint32 len = sizeof(sample);
+
+            // read a sample from the channel
+            res = cyg_io_read( handle, &amp;sample, &amp;len );
+
+            if( res != ENOERR )
+                handle_error(err);
+
+            use_sample( sample );
+        }
+
+</programlisting>
+
+<para>
+In this example, the required channel is looked up and a handle on it
+acquired. Conventionally ADC devices are named "/dev/adcXY" where X is
+the device number and Y the channel within that device. Following
+this, samples are read from the device sequentially.
+</para>
+
+<para>
+ADC devices may also be accessed using FILEIO operations. These allow
+more sophisticated usage. The following example shows
+<function>select()</function> being used to gather samples from several devices.
+</para>
+
+
+<programlisting width=72>
+
+        int fd1, fd2;
+
+        // open channels, non-blocking
+        fd1 = open( "/dev/adc01", O_RDONLY|O_NONBLOCK );
+        fd2 = open( "/dev/adc02", O_RDONLY|O_NONBLOCK );
+
+        if( fd1 < 0 || fd2 < 0 )
+            handle_error( errno );
+
+        for(;;)
+        {
+            fd_set rd;
+            int maxfd = 0;
+            int err;
+            cyg_adc_sample_t samples[128];
+            int len;
+
+            FD_ZERO( &amp;rd );
+
+            FD_SET( fd1, &amp;rd );
+            FD_SET( fd2, &amp;rd );
+            maxfd = max(fd1,fd2);
+
+            // select on available data on each channel.
+            err = select( maxfd+1, &amp;rd, NULL, NULL, NULL );
+
+            if( err < 0 )
+                handle_error(errno);
+
+            // If channel 1 has data, handle it
+            if( FD_ISSET( fd1, &amp;rd ) )
+            {
+                len = read( fd1, &amp;samples, sizeof(samples) );
+
+                if( len > 0 )
+                    handle_samples_chan1( &amp;samples, len/sizeof(sample[0]) );
+            }
+
+            // If channel 2 has data, handle it
+            if( FD_ISSET( fd2, &amp;rd ) )
+            {
+                len = read( fd2, &amp;samples, sizeof(samples) );
+
+                if( len > 0 )
+                    handle_samples_chan2( &amp;samples, len/sizeof(sample[0]) );
+            }
+
+        }
+
+</programlisting>
+
+<para>
+This test uses FILEIO operations to access ADC channels. It starts by
+opening two channels for reading only and with blocking disabled. It
+then falls into a loop using select to wake up whenever either channel
+has samples available.
+</para>
+
+</refsect1>
+
+
+<refsect1 id="adc-details"><title>Details</title>
+
+<para>
+As indicated, the main interface to ADC devices is via the standard
+character device interface. However, there are a number of aspects
+that are ADC specific.
+</para>
+
+<refsect2 id="adc-details-sample-t"><title>Sample Type</title>
+
+<para>
+Samples can vary in size depending on the underlying hardware and is
+often a non-standard number of bits. The actual number of bits is
+defined by the hardware driver package, and the generic ADC package
+uses this to define a type <type>cyg_adc_sample_t</type> which can
+contain at least the required number of bits. All reads from an ADC
+channel should be expressed in multiples of this type, and actual
+bytes read will also always be a multiple.
+</para>
+
+</refsect2>
+
+<refsect2 id="adc-details-rate"><title>Sample Rate</title>
+
+<para>
+The sample rate of an ADC device can be varied by calling a
+<function>set_config</function> function, either at the device IO API
+level or at the FILEIO level. The following two functions show how
+this is done at each:
+</para>
+<programlisting width=72>
+
+int set_rate_io( cyg_io_handle_t handle, int rate )
+{
+    cyg_adc_info_t info;
+    cyg_uint32 len = sizeof(info);
+
+    info.rate = rate;
+
+    return cyg_io_set_config( handle,
+                              CYG_IO_SET_CONFIG_ADC_RATE,
+                              &amp;info,
+                              &amp;len);
+}
+
+int set_rate_fileio( int fd, int rate )
+{
+    cyg_adc_info_t info;
+
+    info.rate = rate;
+
+    return cyg_fs_fsetinfo( fd,
+                            CYG_IO_SET_CONFIG_ADC_RATE,
+                            &amp;info,
+                            sizeof(info) );
+}
+</programlisting>
+
+</refsect2>
+
+<refsect2 id="adc-details-enable"><title>Enabling a Channel</title>
+
+<para>
+Channels are initialized in a disabled state and generate no
+samples. When a channel is first looked up or opened, then it is
+automatically enabled and samples start to accumulate. A channel may
+then be disable or re-enabled via a <function>set_config</function>
+function:
+</para>
+
+<programlisting width=72>
+int disable_io( cyg_io_handle_t handle )
+{
+    return cyg_io_set_config( handle,
+                              CYG_IO_SET_CONFIG_ADC_DISABLE,
+                              NULL,
+                              NULL);
+}
+
+int enable_io( cyg_io_handle_t handle )
+{
+    return cyg_io_set_config( handle,
+                              CYG_IO_SET_CONFIG_ADC_DISABLE,
+                              NULL,
+                              NULL);
+}
+</programlisting>
+
+</refsect2>
+
+</refsect1>
+
+
+<refsect1 id="adc-config"><title>Configuration</title>
+
+<para>
+The ADC package defines a number of generic configuration options that
+apply to all ADC implementations:
+</para>
+
+<variablelist>
+
+<varlistentry><term>cdl_component CYGPKG_IO_ADC_DEVICES</term>
+<listitem><para>
+This option enables the hardware device drivers for the current
+platform. ADC devices will only be enabled if this option is itself
+enabled.
+</para></listitem>
+</varlistentry>
+
+<varlistentry><term>cdl_option CYGNUM_IO_ADC_SAMPLE_SIZE</term>
+<listitem><para>
+This option defines the sample size for the ADC devices.  Given in
+bits, it will be rounded up to 8, 16 or 32 to define the
+<type>cyg_adc_sample_t</type> type. This option is usually set by the
+hardware device driver.
+</para></listitem>
+</varlistentry>
+
+<varlistentry><term>cdl_option CYGPKG_IO_ADC_SELECT_SUPPORT</term>
+<listitem><para>
+
+This option enables support for the <function>select()</function> API
+function on all ADC devices. This option can be disabled if the
+<function>select()</function> is not used, saving some code and data
+space.
+</para></listitem>
+</varlistentry>
+
+</variablelist>
+
+<para>
+In addition to the generic options, each hardware device driver
+defines some parameters for each device and channel. The exact names
+of the following option depends on the hardware device driver, but
+options of this form should be available in all drivers.
+</para>
+
+
+<variablelist>
+
+<varlistentry><term>cdl_option CYGDAT_IO_ADC_EXAMPLE_CHANNELN_NAME</term>
+<listitem><para>
+This option specifies the name of the device for an ADC
+channel. Channel names should be of the form "/dev/adcXY" where X is
+the device number and Y the channel within that device.
+</para></listitem>
+</varlistentry>
+
+<varlistentry><term>cdl_option CYGNUM_IO_ADC_EXAMPLE_CHANNELN_BUFSIZE</term>
+<listitem><para>
+This option specifies the buffer size for an ADC channel. The value is
+expressed in multiples of <type>cyg_adc_sample_t</type> rather than
+bytes. The default value is 128.
+</para></listitem>
+</varlistentry>
+
+<varlistentry><term>cdl_option CYGNUM_IO_ADC_EXAMPLE_DEFAULT_RATE</term>
+<listitem><para>
+This option defines the initial default sample rate for all
+channels. The hardware driver may place constraints on the range of
+values this option may take.
+</para></listitem>
+</varlistentry>
+
+</variablelist>
+
+</refsect1>
+
+</refentry>
+
+<refentry id="adcdev">
+  <refmeta>
+    <refentrytitle>ADC Device Drivers</refentrytitle>
+  </refmeta>
+  <refnamediv>
+    <refname>Overview</refname>
+    <refpurpose>ADC Device Drivers</refpurpose>
+  </refnamediv>
+
+<refsect1 id="adcdev-intro"><title>Introduction</title>
+
+<para>
+This section describes how to write an ADC hardware device. While
+users of ADC devices do not need to read it, it may provide added
+insight into how the devices work.
+</para>
+
+</refsect1>
+
+
+<refsect1 id="adcdev-data"><title>Data Structures</title>
+
+<para>
+An ADC hardware driver is represented by a number of data
+structures. These are generic <literal>device</literal> and
+<literal>channel</literal> data structures, a driver private device
+data structure, a generic character device table entry and a driver
+function table. Most of these structures are instantiated using
+macros, which will be described here.
+</para>
+
+<para>
+The data structure instantiation for a typical single device, four
+channel ADC would look like this:
+</para>
+
+<programlisting width=72>
+//==========================================================================
+// Instantiate data structures
+
+// -------------------------------------------------------------------------
+// Driver functions:
+
+CYG_ADC_FUNCTIONS( example_adc_funs,
+                   example_adc_enable,
+                   example_adc_disable,
+                   example_adc_set_rate );
+
+// -------------------------------------------------------------------------
+// Device instance:
+
+static example_adc_info example_adc_info0 =
+{
+    .base               = CYGARC_HAL_EXAMPLE_ADC_BASE,
+    .vector             = CYGNUM_HAL_INTERRUPT_ADC
+};
+
+CYG_ADC_DEVICE( example_adc_device,
+                &amp;example_adc_funs,
+                &amp;example_adc_info0,
+                CYGNUM_IO_ADC_EXAMPLE_DEFAULT_RATE );
+
+// -------------------------------------------------------------------------
+// Channel instances:
+
+#define EXAMPLE_ADC_CHANNEL( __chan )                                    \
+CYG_ADC_CHANNEL( example_adc_channel##__chan,                            \
+                 __chan,                                                 \
+                 CYGNUM_IO_ADC_EXAMPLE_CHANNEL##__chan##_BUFSIZE,        \
+                 &amp;example_adc_device );                                  \
+                                                                         \
+DEVTAB_ENTRY( example_adc_channel##__chan##_device,                      \
+              CYGDAT_IO_ADC_EXAMPLE_CHANNEL##__chan##_NAME,              \
+              0,                                                         \
+              &amp;cyg_io_adc_devio,                                         \
+              example_adc_init,                                          \
+              example_adc_lookup,                                        \
+              &amp;example_adc_channel##__chan );
+
+EXAMPLE_ADC_CHANNEL( 0 );
+EXAMPLE_ADC_CHANNEL( 1 );
+EXAMPLE_ADC_CHANNEL( 2 );
+EXAMPLE_ADC_CHANNEL( 3 );
+</programlisting>
+
+<para>
+The macro <literal>CYG_ADC_FUNCTIONS()</literal> instantiates a
+function table called <varname>example_adc_funs</varname> and
+populates it with the ADC driver functions (see later for details).
+</para>
+
+<para>
+Then an instance of the driver private device data structure is
+instantiated. In addition to the device base address and interrupt
+vector shown here, this stucture should contain the interrupt object
+and handle for attaching to the vector. It may also contain any other
+variables needed to manage the device.
+</para>
+
+<para>
+The macro <literal>CYG_ADC_DEVICE()</literal> instantiates a
+<structname>cyg_adc_device</structname> structure, named
+<varname>example_adc_device</varname> which will contain pointers to
+the function table and private data structure. The initial sample rate
+is also supplied here.
+</para>
+
+<para>
+For each channel, an ADC channel structure and a device table entry
+must be created. The macro <literal>EXAMPLE_ADC_CHANNEL()</literal> is
+defined to simplify this process. The macro
+<literal>CYG_ADC_CHANNEL</literal> defines a
+<structname>cyg_adc_channel</structname> structure, which contains the
+channel number, the buffer size, and a pointer to the device object
+defined earlier. The call to <literal>DEVTAB_ENTRY()</literal>
+generates a device table entry containing the configured channel name,
+a pointer to a device function table defined in the generic ADC
+driver, pointers to init and lookup functions implemented here, and a
+pointer to the channel data structure just defined.
+</para>
+
+<para>
+Finally, four channels, numbered 0 to 3 are created.
+</para>
+
+
+</refsect1>
+
+<refsect1 id="adcdev-functions"><title>Functions</title>
+
+<para>
+There are several classes of function that need to be defined in an
+ADC driver. These are those function that go into the channel's device
+table, those that go into the ADC device's function table, calls that
+the driver makes into the generic ADC package, and interrupt handling
+functions.
+</para>
+
+<refsect2 id="adcdev-functions-devtab"><title>Device Table Functions</title>
+
+<para>
+These functions are placed in the standard device table entry for each
+channel and handle initialization and location of the device within
+the generic driver infrastructure.
+</para>
+
+<para>
+<function>static bool example_adc_init(struct cyg_devtab_entry *tab)</function>
+
+This function is called from the device IO infrastructure to
+initialize the device. It should perform any work needed to start up
+the device, short of actually starting the generation of samples. This
+function will be called for each channel, so if there is
+initialization that only needs to be done once, such as creating an
+interrupt object, then care should be taken to do this. This function
+should also call <function>cyg_adc_device_init()</function> to
+initialize the generic parts of the driver.
+</para>
+
+<para>
+<function>static Cyg_ErrNo example_adc_lookup(struct cyg_devtab_entry **tab, struct cyg_devtab_entry *sub_tab, const char *name)</function>
+
+This function is called when a client looks up or opens a channel. It
+should call <function>cyg_adc_channel_init()</function> to initialize
+the generic part of the channel. It should also perform any operations
+needed to start the channel generating samples.
+</para>
+
+</refsect2>
+
+<refsect2 id="adcdev-functions-driver"><title>Driver Functions</title>
+
+<para>
+These are the functions installed into the driver function table by
+the <literal>CYG_ADC_FUNCTIONS()</literal> macro.
+</para>
+
+<para>
+<function>static void example_adc_enable( cyg_adc_channel *chan )</function>
+
+This function is called from the generic ADC package to enable the
+channel in response to a
+<literal>CYG_IO_SET_CONFIG_ADC_ENABLE</literal> config operation. It
+should take any steps needed to start the channel generating samples.
+</para>
+
+<para>
+<function>static void example_adc_disable( cyg_adc_channel *chan )</function>
+
+This function is called from the generic ADC package to enable the
+channel in response to a
+<literal>CYG_IO_SET_CONFIG_ADC_DISABLE</literal> config operation. It
+should take any steps needed to stop the channel generating samples.
+</para>
+
+<para>
+<function>static void example_adc_set_rate( cyg_adc_channel *chan, cyg_uint32 rate )</function>
+
+This function is called from the generic ADC package to enable the
+channel in response to a <literal>CYG_IO_SET_CONFIG_ADC_RATE</literal>
+config operation. It should take any steps needed to change the sample
+rate of the channel, or of the entire device.
+</para>
+
+
+</refsect2>
+
+<refsect2 id="adcdev-functions-generic"><title>Generic Package Functions</title>
+
+<para>
+These functions are called by a hardware ADC device driver to perform
+operations in the generic ADC package.
+</para>
+
+<para>
+<function>__externC void cyg_adc_device_init( cyg_adc_device *device )</function>
+
+This function is called from the driver's init function and is used to
+initialize the <type>cyg_adc_device</type> object.
+</para>
+
+<para>
+<function>__externC void cyg_adc_channel_init(cyg_adc_channel *chan)</function>
+
+This function is called from the driver's lookup function and is used
+to initialize the <type>cyg_adc_channel</type> object.
+</para>
+
+<para>
+<function>__externC cyg_uint32 cyg_adc_receive_sample(cyg_adc_channel *chan, cyg_adc_sample_t sample)</function>
+
+This function is called from the driver's ISR to add a new sample to
+the buffer. The return value will be either zero, or
+<literal>CYG_ISR_CALL_DSR</literal> and should be ORed with the return
+value of the ISR.
+</para>
+
+<para>
+<function>__externC void cyg_adc_wakeup(cyg_adc_channel *chan )</function>
+
+This function is called from the driver's DSR to cause any threads
+waiting for data to wake up when a new sample is available. It should
+only be called if the <structfield>wakeup</structfield> field of the
+channel object is <literal>true</literal>.
+</para>
+
+
+
+</refsect2>
+
+<refsect2 id="adcdev-functions-interrupt"><title>Interrupt Functions</title>
+
+<para>
+These functions are internal to the driver, but make calls on generic
+package functions. Typically an ADC device will have a single
+interrupt vector with which it signals available samples on the
+channels and any error conditions such as overruns.
+</para>
+
+<para>
+<function>static cyg_uint32 example_adc_isr(cyg_vector_t vector, cyg_addrword_t data)</function>
+
+This function is the ISR attached to the ADC device's interrupt
+vector. It is responsible for reading samples from the channels and
+passing them on to the generic layer. It needs to check each channel
+for data, and call <function>cyg_adc_receive_sample()</function> for
+each new sample available, and then ready the device for the next
+interrupt.  It's activities are best explained by example:
+</para>
+
+<programlisting width=72>
+static cyg_uint32 example_adc_isr(cyg_vector_t vector, cyg_addrword_t data)
+{
+    cyg_adc_device *example_device = (cyg_adc_device *) data;
+    example_adc_info *example_info = example_device->dev_priv;
+    cyg_uint32 res = 0;
+    int i;
+
+    // Deal with errors if necessary
+    DEVICE_CHECK_ERRORS( example_info );
+
+    // Look for all channels with data available
+    for( i = 0; i < CHANNEL_COUNT; i++ )
+    {
+        if( CHANNEL_SAMPLE_AVALIABLE(i) )
+        {
+            // Fetch data from this channel and pass up to higher
+            // level.
+
+            cyg_adc_sample_t data = CHANNEL_GET_SAMPLE(i);
+            
+            res |= CYG_ISR_HANDLED | cyg_adc_receive_sample( example_info->channel[i], data );
+        }
+    }
+
+   // Clear any interrupt conditions
+    DEVICE_CLEAR_INTERRUPTS( example_info );
+
+    cyg_drv_interrupt_acknowledge(example_info->vector);
+    
+    return res;
+}
+</programlisting>
+
+<para>
+<function>static void example_adc_dsr(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)</function>
+
+This function is the DSR attached to the ADC device's interrupt
+vector. It is called by the kernel if the ISR return value contains
+the <literal>CYG_ISR_HANDLED</literal> bit. It needs to call
+<function>cyg_adc_wakeup()</function> for each channel that has its
+<structfield>wakeup</structfield> field set. Again, and example should
+make it all clear:
+</para>
+
+<programlisting width=72>
+static void example_adc_dsr(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
+{
+    cyg_adc_device *example_device = (cyg_adc_device *) data;
+    example_adc_info *example_info = example_device->dev_priv;
+    int i;
+
+    // Look for all channels with pending wakeups
+    for( i = 0; i < CHANNEL_COUNT; i++ )
+    {
+        if( example_info->channel[i]->wakeup )
+            cyg_adc_wakeup( example_info->channel[i] );
+    }
+}
+
+</programlisting>
+
+
+</refsect2>
+
+
+</refsect1>
+
+
+</refentry>
+
+</part>
Index: packages/io/adc/current/include/adc.h
===================================================================
RCS file: packages/io/adc/current/include/adc.h
diff -N packages/io/adc/current/include/adc.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ packages/io/adc/current/include/adc.h	8 Aug 2008 10:36:30 -0000
@@ -0,0 +1,203 @@
+#ifndef CYGONCE_ADC_H
+#define CYGONCE_ADC_H
+/*==========================================================================
+//
+//      adc.h
+//
+//      Generic ADC driver layer header
+//
+//==========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 2008 eCosCentric Limited
+//
+// eCos 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 or (at your option) any later version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):    nickg
+// Date:         2008-03-31
+// Description:  Implements generic layer of ADC drivers.
+//
+//####DESCRIPTIONEND####
+//
+//========================================================================*/
+
+#include <pkgconf/system.h>
+#include <pkgconf/io_adc.h>
+
+#include <cyg/infra/cyg_type.h>
+#include <cyg/io/io.h>
+#include <cyg/io/devtab.h>
+#include <cyg/io/config_keys.h>
+#include <cyg/hal/drv_api.h>
+
+
+#ifdef CYGPKG_IO_ADC_SELECT_SUPPORT
+#include <cyg/fileio/fileio.h>
+#endif
+
+//==========================================================================
+// Configuration information structure
+
+typedef struct
+{
+    cyg_uint32          rate;           // Sample rate
+} cyg_adc_info_t;
+
+//==========================================================================
+// Sample size type.
+//
+// Define sample size type depending on hardware capability.
+
+#if CYGNUM_IO_ADC_SAMPLE_SIZE > 16
+typedef cyg_int32 cyg_adc_sample_t;
+#elif CYGNUM_IO_ADC_SAMPLE_SIZE > 8
+typedef cyg_int16 cyg_adc_sample_t;
+#else
+typedef cyg_int8 cyg_adc_sample_t;
+#endif
+
+//==========================================================================
+// Forward type definitions.
+
+typedef struct cyg_adc_device cyg_adc_device;
+typedef struct cyg_adc_channel cyg_adc_channel;
+typedef struct cyg_adc_functions cyg_adc_functions;
+
+//==========================================================================
+// Callbacks from hardware drivers to generic driver.
+
+__externC void cyg_adc_device_init( cyg_adc_device *device );
+
+__externC void cyg_adc_channel_init(cyg_adc_channel *chan);
+
+__externC cyg_uint32 cyg_adc_receive_sample(cyg_adc_channel *chan, cyg_adc_sample_t sample);
+
+__externC void cyg_adc_wakeup(cyg_adc_channel *chan );
+
+//==========================================================================
+// Device table functions
+
+__externC cyg_devio_table_t cyg_io_adc_devio;
+
+//==========================================================================
+// ADC device
+//
+// A single device may support several channels which share interrupt
+// vectors and sample rate settings.
+
+struct cyg_adc_device
+{
+    cyg_adc_functions   *funs;          // Hardware device functions
+    void                *dev_priv;      // Hardware device private data
+    cyg_adc_info_t      config;         // Current configuration
+
+    cyg_bool            init;           // Initialized ?
+    cyg_drv_mutex_t     lock;           // Device lock
+};
+
+#define CYG_ADC_DEVICE(__name, __funs, __dev_priv, __rate )     \
+cyg_adc_device __name =                                         \
+{                                                               \
+    .funs               = __funs,                               \
+    .dev_priv           = __dev_priv,                           \
+    .config.rate        = __rate,                               \
+    .init               = false                                 \
+};
+
+
+//==========================================================================
+// ADC channel
+//
+// Each device may support several channels, each providing a separate
+// stream of samples.
+
+struct  cyg_adc_channel
+{
+    int                 channel;        // Channel number
+    
+    cyg_adc_sample_t    *buf;           // Sample data buffer
+    int                 len;            // Buffer length in samples
+    volatile int        put;            // Sample insert index
+    volatile int        get;            // Sample extract index
+
+    cyg_adc_device      *device;        // Controlling device
+    
+    cyg_bool            init;           // Initialized ?
+    cyg_drv_cond_t      wait;           // Readers wait here for data
+    cyg_bool            waiting;        // True if any threads waiting
+    cyg_bool            wakeup;         // True if wakeup needed
+    
+    cyg_bool            enabled;        // Channel enabled?
+    cyg_bool            blocking;       // Blocking IO
+    int                 overflow;       // Overflow counter
+    
+#ifdef CYGPKG_IO_ADC_SELECT_SUPPORT    
+    struct CYG_SELINFO_TAG   selinfo;   // Select info
+#endif
+
+};
+
+#define CYG_ADC_CHANNEL( __name, __channel, __bufsize, __device )       \
+static cyg_adc_sample_t __name##_buf[__bufsize];                        \
+cyg_adc_channel __name =                                                \
+{                                                                       \
+    .channel            = __channel,                                    \
+    .buf                = __name##_buf,                                 \
+    .len                = __bufsize,                                    \
+    .put                = 0,                                            \
+    .get                = 0,                                            \
+    .device             = __device,                                     \
+    .init               = false                                         \
+};
+              
+//==========================================================================
+// Device functions
+//
+// These are the functions exported by the hardware device to the
+// generic layer.
+
+struct cyg_adc_functions
+{
+    void (*enable)( cyg_adc_channel *chan );
+    void (*disable)( cyg_adc_channel *chan );
+
+    void (*set_rate)( cyg_adc_channel *chan, cyg_uint32 rate );
+};
+
+#define CYG_ADC_FUNCTIONS( __name, __enable, __disable, __set_rate )    \
+cyg_adc_functions __name =                                              \
+{                                                                       \
+    .enable             = __enable,                                     \
+    .disable            = __disable,                                    \
+    .set_rate           = __set_rate                                    \
+};
+
+//==========================================================================
+#endif // CYGONCE_ADC_H
+
Index: packages/io/adc/current/src/adc.c
===================================================================
RCS file: packages/io/adc/current/src/adc.c
diff -N packages/io/adc/current/src/adc.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ packages/io/adc/current/src/adc.c	8 Aug 2008 10:36:30 -0000
@@ -0,0 +1,421 @@
+/*==========================================================================
+//
+//      adc.c
+//
+//      Generic ADC driver layer
+//
+//==========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 2008 eCosCentric Limited
+//
+// eCos 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 or (at your option) any later version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):    nickg
+// Date:         2008-03-31
+// Description:  Implements generic layer of ADC drivers.
+//
+//####DESCRIPTIONEND####
+//
+//========================================================================*/
+
+#include <cyg/io/adc.h>
+
+//==========================================================================
+// Diagnostic support
+//
+// Switch the #if to 1 to generate some diagnostic messages.
+
+#if 0
+
+#include <cyg/infra/diag.h>
+
+#define adc_diag( __fmt, ... ) diag_printf("ADC: %30s[%4d]: " __fmt, __FUNCTION__, __LINE__, ## __VA_ARGS__ );
+#define adc_dump_buf( __buf, __size )  diag_dump_buf( __buf, __size )
+#else
+#define adc_diag( __fmt, ... ) 
+#define adc_dump_buf( __buf, __size )
+#endif
+
+//==========================================================================
+// Main device table entry functions
+
+static Cyg_ErrNo adc_write(cyg_io_handle_t handle, const void *buf, cyg_uint32 *len);
+static Cyg_ErrNo adc_read(cyg_io_handle_t handle, void *buf, cyg_uint32 *len);
+static cyg_bool adc_select(cyg_io_handle_t handle, cyg_uint32 which, CYG_ADDRWORD info);
+static Cyg_ErrNo adc_get_config(cyg_io_handle_t handle, cyg_uint32 key, void *buf, cyg_uint32 *len);
+static Cyg_ErrNo adc_set_config(cyg_io_handle_t handle, cyg_uint32 key, const void *buf, cyg_uint32 *len);
+
+DEVIO_TABLE(cyg_io_adc_devio,
+            adc_write,
+            adc_read,
+            adc_select,
+            adc_get_config,
+            adc_set_config
+    );
+
+//==========================================================================
+// Device interface functions
+
+//--------------------------------------------------------------------------
+// Device write
+//
+// Not supported
+
+static Cyg_ErrNo adc_write(cyg_io_handle_t handle, const void *buf, cyg_uint32 *len)
+{
+    adc_diag("write not supported\n");
+    return -EDEVNOSUPP;
+}
+
+//--------------------------------------------------------------------------
+// Device Read
+//
+// Returns a whole number of samples from a channel
+
+static Cyg_ErrNo adc_read(cyg_io_handle_t handle, void *abuf, cyg_uint32 *len)
+{
+    Cyg_ErrNo res = ENOERR;
+    cyg_devtab_entry_t *t = (cyg_devtab_entry_t *)handle;
+    cyg_adc_channel *chan = (cyg_adc_channel *)t->priv;
+    cyg_adc_device *dev = chan->device;
+    
+    cyg_adc_sample_t *buf = (cyg_adc_sample_t *)abuf;
+    cyg_uint32 size = 0;
+
+    adc_diag("chan %d buf %p len %u\n", chan->channel, abuf, *len);
+    
+    // Check that supplied buffer address is aligned to sample size.
+    if( (((CYG_ADDRESS)buf) & (sizeof(cyg_adc_sample_t)-1)) != 0 )
+        return -EIO;
+
+    // Check that channel is enabled
+    if( !chan->enabled )
+        return -EIO;
+    
+    cyg_drv_mutex_lock( &dev->lock );
+    cyg_drv_dsr_lock();
+    {
+        while( (*len-size) >= sizeof(cyg_adc_sample_t) )
+        {
+            if( chan->put != chan->get )
+            {
+                // A sample is available, transfer it to the buffer.
+                
+                int next = chan->get+1;
+                cyg_drv_isr_lock();
+                {
+                    *buf++ = chan->buf[chan->get];
+                    if( next == chan->len )
+                        next = 0;
+                    chan->get = next;
+                }
+                cyg_drv_isr_unlock();
+                size += sizeof(cyg_adc_sample_t);
+
+                adc_diag("chan %d sample %d -> %04x\n", chan->channel, size, buf[-1] );
+            }
+            else
+            {
+                // If there is no data available, either wait or
+                // return EAGAIN.
+                
+                if( !chan->blocking )
+                {
+                    // If non-blocking, return what we have. If
+                    // nothing, return EAGAIN.
+                    *len = size;
+                    if( size == 0 )
+                        res = -EAGAIN;
+                    break;
+                }
+                // Otherwise, we must wait for data to arrive.
+
+                adc_diag("wait for sample\n");
+                chan->waiting = true;
+                if( !cyg_drv_cond_wait( &chan->wait ) )
+                {
+                    // Abort the wait, return EINTR
+                    adc_diag("abort\n");
+                    *len = size;
+                    res = -EINTR;
+                    break;
+                }
+
+                adc_diag("wake up\n");
+                // Loop back round to pick up any samples now
+                // available.
+            }
+        }
+    }
+    cyg_drv_dsr_unlock();    
+    cyg_drv_mutex_unlock( &dev->lock );
+    
+    return res;
+}
+
+//--------------------------------------------------------------------------
+// Select support
+//
+// If select support is enabled, check for pending samples.
+
+static cyg_bool adc_select(cyg_io_handle_t handle, cyg_uint32 which, CYG_ADDRWORD info)
+{
+#ifdef CYGPKG_IO_ADC_SELECT_SUPPORT
+    
+    cyg_bool res = false;
+    cyg_devtab_entry_t *t = (cyg_devtab_entry_t *)handle;
+    cyg_adc_channel *chan = (cyg_adc_channel *)t->priv;
+    cyg_adc_device *dev = chan->device;
+
+    // Check that channel is enabled. If not, return false.
+    if( !chan->enabled )
+        return false;
+    
+    // Only read select is supported
+    if( which == CYG_FREAD )
+    {
+        cyg_drv_mutex_lock( &dev->lock );
+        cyg_drv_dsr_lock();
+        {
+            cyg_drv_isr_lock();            
+            if( chan->put == chan->get )
+            {
+                // There is no data in the buffer, register the select.
+
+                cyg_selrecord( info, &chan->selinfo );
+            }
+            else
+            {
+                res = true;
+            }
+            cyg_drv_isr_unlock();            
+        }
+        cyg_drv_dsr_unlock();
+        cyg_drv_mutex_unlock( &dev->lock );
+        
+    }
+
+    return res;
+    
+#else
+    
+    return true;
+
+#endif
+}
+
+//--------------------------------------------------------------------------
+// Get config
+//
+// Return various configuration options.
+
+static Cyg_ErrNo adc_get_config(cyg_io_handle_t handle, cyg_uint32 key, void *xbuf, cyg_uint32 *len)
+{
+    cyg_devtab_entry_t *t = (cyg_devtab_entry_t *)handle;
+    cyg_adc_channel *chan = (cyg_adc_channel *)t->priv;
+    cyg_adc_info_t *buf = (cyg_adc_info_t *)xbuf;
+    Cyg_ErrNo res = ENOERR;
+
+    adc_diag("chan %d\n", chan->channel );
+    switch( key )
+    {
+    case CYG_IO_GET_CONFIG_ADC_RATE:
+        *buf = chan->device->config;
+        break;
+
+    case CYG_IO_GET_CONFIG_READ_BLOCKING:
+        if (*len < sizeof(cyg_uint32))
+            return -EINVAL;
+        *(cyg_uint32*)xbuf = (chan->blocking) ? 1 : 0;
+        break;
+
+        
+    default:
+        res = -EINVAL;
+    }
+
+    return res;
+}
+
+//--------------------------------------------------------------------------
+// Set config
+//
+// Set configuration options.
+
+static Cyg_ErrNo adc_set_config(cyg_io_handle_t handle, cyg_uint32 key, const void *xbuf, cyg_uint32 *len)
+{
+
+    cyg_devtab_entry_t *t = (cyg_devtab_entry_t *)handle;
+    cyg_adc_channel *chan = (cyg_adc_channel *)t->priv;
+    cyg_adc_info_t *buf = (cyg_adc_info_t *)xbuf;
+    Cyg_ErrNo res = ENOERR;
+
+    adc_diag("chan %d\n", chan->channel );
+    
+    switch( key )
+    {
+    case CYG_IO_SET_CONFIG_ADC_RATE:
+        chan->device->config = *buf;
+        chan->device->funs->set_rate( chan, buf->rate );
+        break;
+
+    case CYG_IO_SET_CONFIG_ADC_ENABLE:
+        chan->enabled = true;
+        chan->device->funs->enable( chan );
+        break;        
+
+    case CYG_IO_SET_CONFIG_ADC_DISABLE:
+        chan->enabled = false;        
+        chan->device->funs->disable( chan );
+        break;        
+
+    case CYG_IO_SET_CONFIG_READ_BLOCKING:
+        if (*len < sizeof(cyg_uint32))
+            return -EINVAL;
+
+        chan->blocking = (1 == *(cyg_uint32*)xbuf) ? true : false;
+        break;
+        
+    default:
+        res = -EINVAL;
+    }
+
+    return res;
+}
+
+//==========================================================================
+// Callbacks from hardware driver to generic layer
+
+//--------------------------------------------------------------------------
+// Initialize generic device structure
+
+__externC void cyg_adc_device_init( cyg_adc_device *device )
+{
+    if( device->init )
+        return;
+
+    adc_diag("\n");
+    
+    device->init = true;
+    cyg_drv_mutex_init( &device->lock );
+}
+
+//--------------------------------------------------------------------------
+// Initialize generic channel structure
+
+__externC void cyg_adc_channel_init(cyg_adc_channel *chan)
+{
+    if( chan->init )
+        return;
+
+    adc_diag("chan %d\n", chan->channel );
+    
+    chan->init = true;
+    cyg_drv_cond_init( &chan->wait, &chan->device->lock );
+    chan->enabled = false;
+    chan->waiting = false;
+    chan->wakeup = false;
+    chan->blocking = true;
+    chan->overflow = 0;
+    
+#ifdef CYGPKG_IO_ADC_SELECT_SUPPORT
+        cyg_selinit( &chan->selinfo );
+#endif        
+    
+}
+
+//--------------------------------------------------------------------------
+// Add a new sample to the buffer
+//
+// This function is called from the ISR to store a sample in the
+// buffer.
+
+__externC cyg_uint32 cyg_adc_receive_sample(cyg_adc_channel *chan, cyg_adc_sample_t sample)
+{
+    cyg_uint32 res = 0;
+    int next = chan->put+1;
+
+    adc_diag("chan %d sample %04x\n", chan->channel, sample );
+
+    // Ignore this sample if the channel is not enabled.
+    if( !chan->enabled )
+        return 0;
+    
+    if( next == chan->len )
+        next = 0;
+
+    if( next == chan->get )
+    {
+        // The buffer is full. Record an overflow and arrange to
+        // replace the oldest sample with the new one.
+        
+        adc_diag("chan %d overflow\n", chan->channel);
+        chan->overflow++;
+
+        chan->get++;
+        if( chan->get == chan->len )
+            chan->get = 0;
+    }
+
+    // If this is the first sample into the buffer, wake any waiting
+    // selectors. Also do this if there are any threads waiting for
+    // data.
+    if( chan->put == chan->get || chan->waiting )
+        res |= CYG_ISR_CALL_DSR, chan->wakeup = true;
+
+    // Store the new sample
+    chan->buf[chan->put] = sample;
+    chan->put = next;
+
+    return res;
+}
+
+//--------------------------------------------------------------------------
+// Wakeup a channel
+//
+// This function is called from the DSR if the channel wakeup field is
+// set. It satisfies any select operations or any waiting readers.
+
+__externC void cyg_adc_wakeup(cyg_adc_channel *chan )
+{
+    adc_diag("chan %d\n", chan->channel );
+    
+#ifdef CYGPKG_IO_ADC_SELECT_SUPPORT
+    cyg_selwakeup( &chan->selinfo );
+#endif
+
+    chan->waiting = false;
+    cyg_drv_cond_signal( &chan->wait );
+
+    chan->wakeup = false;    
+}
+
+//==========================================================================
+// End of adc.c
Index: packages/io/common/current/ChangeLog
===================================================================
RCS file: /cvs/ecos/ecos/packages/io/common/current/ChangeLog,v
retrieving revision 1.29
diff -u -5 -r1.29 ChangeLog
--- packages/io/common/current/ChangeLog	13 Aug 2007 07:38:57 -0000	1.29
+++ packages/io/common/current/ChangeLog	8 Aug 2008 10:53:38 -0000
@@ -1,5 +1,9 @@
+2008-08-08  Nick Garnett  <nickg@ecoscentric.com>
+
+	* include/config_keys.h: Add keys for ADC devices.
+
 2007-08-13  Alexey Shusharin <mrfinch@mail.ru>
 
 	* include/config_keys.h: Added key set setting CAN callback
 	configuration.
 	
Index: packages/io/common/current/include/config_keys.h
===================================================================
RCS file: /cvs/ecos/ecos/packages/io/common/current/include/config_keys.h,v
retrieving revision 1.15
diff -u -5 -r1.15 config_keys.h
--- packages/io/common/current/include/config_keys.h	13 Aug 2007 07:38:57 -0000	1.15
+++ packages/io/common/current/include/config_keys.h	8 Aug 2008 10:53:38 -0000
@@ -149,10 +149,19 @@
 #define CYG_IO_SET_CONFIG_CAN_MSGBUF                0x0886
 #define CYG_IO_SET_CONFIG_CAN_MODE                  0x0887
 #define CYG_IO_SET_CONFIG_CAN_ABORT                 0x0888
 #define CYG_IO_SET_CONFIG_CAN_CALLBACK              0x0889
 
+// ======== 0x900 ADC ========================================================
+// Get/Set configuration 'key' values for ADC I/O
+
+#define CYG_IO_GET_CONFIG_ADC_RATE                  0x0901
+
+#define CYG_IO_SET_CONFIG_ADC_RATE                  0x0981
+#define CYG_IO_SET_CONFIG_ADC_ENABLE                0x0982
+#define CYG_IO_SET_CONFIG_ADC_DISABLE               0x0983
+
 // ======== 0x1000 Generic ===================================================
 // Get/Set configuration 'key' values that can apply to more than one
 // class of device.
 
 #define CYG_IO_GET_CONFIG_READ_BLOCKING         0x1001



-- 
Nick Garnett                                      eCos Kernel Architect
eCosCentric Limited    http://www.eCosCentric.com      The eCos experts
Barnwell House, Barnwell Drive, Cambridge, UK.     Tel: +44 1223 245571
Registered in England and Wales:                        Reg No: 4422071


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]