Overview -- eCos Support for Analog/Digital Converters
Introduction
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.
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 cyg_adc_sample_t 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.
Examples
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:
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 );
}
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.
ADC devices may also be accessed using FILEIO operations. These allow
more sophisticated usage. The following example shows
select() being used to gather samples from several devices.
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]) );
}
}
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.
Details
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.
Sample Type
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 cyg_adc_sample_t 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.
Sample Rate
The sample rate of an ADC device can be varied by calling a
set_config function, either at the device IO API
level or at the FILEIO level. The following two functions show how
this is done at each:
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) );
}
Enabling a Channel
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 set_config
function:
The ADC package defines a number of generic configuration options that
apply to all ADC implementations:
cdl_component CYGPKG_IO_ADC_DEVICES
This option enables the hardware device drivers for the current
platform. ADC devices will only be enabled if this option is itself
enabled.
cdl_option CYGNUM_IO_ADC_SAMPLE_SIZE
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. This option is usually set by the
hardware device driver.
cdl_option CYGPKG_IO_ADC_SELECT_SUPPORT
This option enables support for the select() API
function on all ADC devices. This option can be disabled if the
select() is not used, saving some code and data
space.
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.
cdl_option CYGDAT_IO_ADC_EXAMPLE_CHANNELN_NAME
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.
cdl_option CYGNUM_IO_ADC_EXAMPLE_CHANNELN_BUFSIZE
This option specifies the buffer size for an ADC channel. The value is
expressed in multiples of cyg_adc_sample_t rather than
bytes. The default value is 128.
cdl_option CYGNUM_IO_ADC_EXAMPLE_DEFAULT_RATE
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.