Scanning different channels in continuous mode

Hallo,

I am trying to read 6 channels in continuous scan mode, with the 
ni_mio_common dirver. I'm using the CVS version of comedi form one week 
ago. My test program runs in kernel space on a x86 machine, 2.4.18 kernel.

First I initialise a continuous scan (0.5 Hz). I registered a callback 
function (CB_EOF) so an interrupt occures after each scan. In the 
callback function I read the comedi buffer using the 
cfc_read_array_from_buffer(..) function.

I am having the following problems:
1) The first scan only contains 5 samples instead of 6. All the next 
scans contain 6 samples
2) All the 6 samples I get are samples from channel 0, and none from the
5 other channels.

See also the test.c file in attachment.

Thanks,

Wim
// include
// ------------------------------------------------
#include <linux/comedilib.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <comedi_fc.h>

MODULE_LICENSE("GPL");

EXPORT_NO_SYMBOLS;

// define
// ------------------------------------------------
#define sec_to_nsec(x)  ((x)*1000000000)
#define sec_to_usec(x)  ((x)*1000000)
#define sec_to_msec(x)  ((x)*1000)
#define msec_to_nsec(x) ((x)*1000000)
#define msec_to_usec(x) ((x)*1000)
#define usec_to_nsec(x) ((x)*1000)
#define N_CHANS 	6
#define N_SCANS		20

static int          n_chans = N_CHANS;
static int          n_scans = N_SCANS;
unsigned int chanlist[N_CHANS];
static comedi_t*    device;
static int			 aref;
static int			 range;
static int 		 channel;
static int 		 subdevice;

// forward declaration
// ------------------------------------------------
void prepare_cmd(comedi_t* dev,comedi_cmd* cmd);
void do_cmd(comedi_t* dev,comedi_cmd* cmd);
int  callback(unsigned int i, void* arg);

// init module
// ------------------------------------------------
int init_module(void)
{
	comedi_cmd    cmd;
	int           i;
	unsigned int  chanlist[n_scans];

	printk("test_module: init_module()\n");
	
	// open device
	device = comedi_open("/dev/comedi0");

	// lock device
	comedi_lock(device,0);

	// register callback function
	comedi_register_callback(device,0,COMEDI_CB_EOS,callback,NULL);
	
	// make make chanlist
	for ( i=0; i < n_chans; i++ )
		chanlist[i]=CR_PACK(channel+i,range,aref);

	prepare_cmd(device,&cmd);

	do_cmd(device,&cmd);

	return 0;
}


// cleanup module
// --------------------------------------------------
int cleanup_module(void)
{
	printk("test_module: cleanup_module()\n");
	comedi_unlock(device,0);
	comedi_cancel(device,0);
	comedi_close(device);
	return 1;
}



// callback function
// --------------------------------------------------
static sampl_t     	data[N_CHANS];
static unsigned int 	ret;
static unsigned int	size;

int callback(unsigned int i, void* arg)
{
	comedi_subdevice* s;
	s = ( (comedi_device*) device )->subdevices;
	
	// read data form comedi buffer
	size = sizeof(sampl_t)*N_CHANS;
	ret = cfc_read_array_from_buffer( s, data, size );
	
	printk("test -- cb -- read form buffer: %d/%d\n",ret,size);
	printk("test -- cb -- data --> %d/%d/%d//%d/%d/%d\n",data[0],data[1],data[2],data[3],data[4],data[5]);
	
	return 0;
}	



void do_cmd(comedi_t *dev,comedi_cmd *cmd)
{
	int ret;

	// check validity of command
	ret = comedi_command_test(dev,cmd);

	// print validity check return values
	printk("command test ret: %d\n",ret);
	
	// execute command
	ret = comedi_command(dev,cmd);

	// print command return values
	printk("execute ret %d\n",ret);

}

void prepare_cmd(comedi_t* dev,comedi_cmd* cmd)
{
	// set whole command to 0
	memset(cmd,0,sizeof(*cmd));

	/* the subdevice that the command is sent to */
	cmd->subdev =	subdevice;

	/* flags */
	cmd->flags =	0; //TRIG_WAKE_EOS;

	/* each event requires a trigger, which is specified
	   by a source and an argument.  For example, to specify
	   an external digital line 3 as a source, you would use
	   src=TRIG_EXT and arg=3. */

	/* In this case, we specify using TRIG_NOW to start
	 * acquisition immediately when the command is issued.  
	 * The argument of TRIG_NOW is "number of nsec after
	 * NOW", but no driver supports it yet.  Also, no driver
	 * currently supports using a start_src other than
	 * TRIG_NOW.  */
	cmd->start_src =		TRIG_NOW;
	cmd->start_arg =		0;

	/* The timing of the beginning of each scan is controlled
	 * by scan_begin.  TRIG_TIMER specifies that scan_start
	 * events occur periodically at a rate of scan_begin_arg
	 * nanoseconds between scans. */
	cmd->scan_begin_src =	TRIG_TIMER;
	cmd->scan_begin_arg =	msec_to_nsec(500);

	/* The timing between each sample in a scan is controlled
	 * by convert.  Like above, TRIG_TIMER specifies that
	 * convert events occur periodically at a rate of convert_arg
	 * nanoseconds between scans. */
	cmd->convert_src =	TRIG_TIMER;
	cmd->convert_arg =	usec_to_nsec(50);

	/* The end of each scan is almost always specified using
	 * TRIG_COUNT, with the argument being the same as the
	 * number of channels in the chanlist.  You could probably
	 * find a device that allows something else, but it would
	 * be strange. */
	cmd->scan_end_src =	TRIG_COUNT;
	cmd->scan_end_arg =	n_chans;  // number of items in chan_list

	/* The end of acquisition is controlled by stop_src and
	 * stop_arg.  The src will typically be TRIG_COUNT or
	 * TRIG_NONE.  Specifying TRIG_COUNT will stop acquisition
	 * after stop_arg number of scans, or TRIG_NONE will
	 * cause acquisition to continue until stopped using
	 * comedi_cancel(). */
	cmd->stop_src =		TRIG_NONE; 
	cmd->stop_arg =		0;

	/* the channel list determined which channels are sampled.
	   In general, chanlist_len is the same as scan_end_arg.  Most
	   boards require this.  */
	cmd->chanlist =		chanlist;
	cmd->chanlist_len =	n_chans;
}

Received on 2003-02-05Z13:19:53