This is the mail archive of the
ecos-patches@sourceware.org
mailing list for the eCos project.
ADC device support
- From: Nick Garnett <nickg at ecoscentric dot com>
- To: ecos-patches at ecos dot sourceware dot org
- Date: 08 Aug 2008 11:56:37 +0100
- Subject: 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", &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, &sample, &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( &rd );
+
+ FD_SET( fd1, &rd );
+ FD_SET( fd2, &rd );
+ maxfd = max(fd1,fd2);
+
+ // select on available data on each channel.
+ err = select( maxfd+1, &rd, NULL, NULL, NULL );
+
+ if( err < 0 )
+ handle_error(errno);
+
+ // If channel 1 has data, handle it
+ if( FD_ISSET( fd1, &rd ) )
+ {
+ len = read( fd1, &samples, sizeof(samples) );
+
+ if( len > 0 )
+ handle_samples_chan1( &samples, len/sizeof(sample[0]) );
+ }
+
+ // If channel 2 has data, handle it
+ if( FD_ISSET( fd2, &rd ) )
+ {
+ len = read( fd2, &samples, sizeof(samples) );
+
+ if( len > 0 )
+ handle_samples_chan2( &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,
+ &info,
+ &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,
+ &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,
+ &example_adc_funs,
+ &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, \
+ &example_adc_device ); \
+ \
+DEVTAB_ENTRY( example_adc_channel##__chan##_device, \
+ CYGDAT_IO_ADC_EXAMPLE_CHANNEL##__chan##_NAME, \
+ 0, \
+ &cyg_io_adc_devio, \
+ example_adc_init, \
+ example_adc_lookup, \
+ &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