From 7cde371fd4ce2d3dad7dc9721f9e22463ea573aa Mon Sep 17 00:00:00 2001 From: David Schleef Date: Sat, 25 Nov 2000 04:19:59 +0000 Subject: [PATCH] mmap demo and testing --- demo/mmap.c | 332 +++++++++++++++++++++++++++++++++++++++++++++++++ testing/mmap.c | 146 ++++++++++++++++++++++ 2 files changed, 478 insertions(+) create mode 100644 demo/mmap.c create mode 100644 testing/mmap.c diff --git a/demo/mmap.c b/demo/mmap.c new file mode 100644 index 0000000..db67cc1 --- /dev/null +++ b/demo/mmap.c @@ -0,0 +1,332 @@ +/* + * Example of using commands - asynchronous input + * Part of Comedilib + * + * Copyright (c) 1999,2000 David A. Schleef + * + * This file may be freely modified, distributed, and combined with + * other software, as long as proper attribution is given in the + * source code. + */ + +/* + * An example for directly using Comedi commands. Comedi commands + * are used for asynchronous acquisition, with the timing controlled + * by on-board timers or external events. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "examples.h" + +#define N_SCANS 10 +#define N_CHANS 16 + +int subdevice = 0; +int chan=0; +int range = 0; +int aref = AREF_GROUND; +double freq = 1000; + +#define BUFSZ 1000 +char buf[BUFSZ]; + +sampl_t *map; + +void do_cmd_1(comedi_t *dev); +void do_cmd_2(comedi_t *dev); +void do_cmd(comedi_t *dev,comedi_cmd *cmd); +void dump_cmd(comedi_cmd *cmd); + +int main(int argc, char *argv[]) +{ + char *fn = NULL; + comedi_t *dev; + + fn = "/dev/comedi0"; + + dev = comedi_open(fn); + if(!dev){ + perror(fn); + exit(1); + } + + fcntl(comedi_fileno(dev),F_SETFL,O_NONBLOCK); + + map=mmap(NULL,0x1000,PROT_READ,MAP_SHARED,comedi_fileno(dev),0); + printf("map=%p\n",map); + + do_cmd_1(dev); + + return 0; +} + +void do_cmd(comedi_t *dev,comedi_cmd *cmd) +{ + unsigned int *chanlist; + int n_chans; + int total=0; + int ret; + int go; + int i; + + chanlist = cmd->chanlist; + n_chans = cmd->chanlist_len; + + ret=ioctl(comedi_fileno(dev),COMEDI_CMDTEST,cmd); + + printf("test ret=%d\n",ret); + if(ret<0){ + printf("errno=%d\n",errno); + perror("ioctl"); + return; + } + + dump_cmd(cmd); + + cmd->chanlist = chanlist; + cmd->chanlist_len = n_chans; + + ret=ioctl(comedi_fileno(dev),COMEDI_CMDTEST,cmd); + + printf("test ret=%d\n",ret); + if(ret<0){ + printf("errno=%d\n",errno); + comedi_perror("ioctl"); + return; + } + + dump_cmd(cmd); + + cmd->chanlist = chanlist; + cmd->chanlist_len = n_chans; + + ret=ioctl(comedi_fileno(dev),COMEDI_CMD,cmd); + + printf("ret=%d\n",ret); + if(ret<0){ + printf("errno=%d\n",errno); + comedi_perror("ioctl"); + return; + } + + go=1; + while(go){ + ret=read(comedi_fileno(dev),buf,BUFSZ); + if(ret<0){ + if(errno==EAGAIN){ + usleep(10000); + }else{ + go = 0; + perror("read"); + } + }else if(ret==0){ + go = 0; + }else{ + total+=ret; + printf("read %d %d\n",ret,total); + } + } + + {char s[10]; gets(s); } + munmap(map,0x1000); + //close(comedi_fileno(dev)); + + {char s[10]; gets(s); } + for(i=0;i<100;i++){ + printf("%d\n",map[i]); + } +} + +/* + * This part of the demo measures channels 1, 2, 3, 4 at a rate of + * 10 khz, with the inter-sample time at 10 us (100 khz). The number + * of scans measured is 10. This is analogous to the old mode2 + * acquisition. + */ +void do_cmd_1(comedi_t *dev) +{ + comedi_cmd cmd; + unsigned int chanlist[4]; + + memset(&cmd,0,sizeof(cmd)); + + /* the subdevice that the command is sent to */ + cmd.subdev = subdevice; + + /* flags */ + cmd.flags = 0; + + /* 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 = 100000; /* in ns */ + + /* 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 = 10000; /* in ns */ + + /* 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 = 4; /* number of channels */ + + /* 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(). */ +#if 1 + cmd.stop_src = TRIG_COUNT; + cmd.stop_arg = 100; +#else + cmd.stop_src = TRIG_NONE; + cmd.stop_arg = 0; +#endif + + /* 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 = 4; + + chanlist[0]=CR_PACK(0,range,aref); + chanlist[1]=CR_PACK(1,range,aref); + chanlist[2]=CR_PACK(2,range,aref); + chanlist[3]=CR_PACK(3,range,aref); + + do_cmd(dev,&cmd); +} + +void do_cmd_2(comedi_t *dev) +{ + comedi_cmd cmd; + unsigned int chanlist[4]; + + memset(&cmd,0,sizeof(cmd)); + + /* the subdevice that the command is sent to */ + cmd.subdev = subdevice; + + /* flags */ + cmd.flags = 0; + + /* 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. */ + + cmd.start_src = TRIG_NOW; + cmd.start_arg = 0; + + cmd.scan_begin_src = TRIG_TIMER; + cmd.scan_begin_arg = 1; /* in ns */ + + cmd.convert_src = TRIG_TIMER; + cmd.convert_arg = 1; /* in ns */ + + cmd.scan_end_src = TRIG_COUNT; + cmd.scan_end_arg = 4; /* number of channels */ + +#if 1 + cmd.stop_src = TRIG_COUNT; + cmd.stop_arg = 100; +#else + cmd.stop_src = TRIG_NONE; + cmd.stop_arg = 0; +#endif + + /* 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 = 4; + + chanlist[0]=CR_PACK(0,range,aref); + chanlist[1]=CR_PACK(1,range,aref); + chanlist[2]=CR_PACK(2,range,aref); + chanlist[3]=CR_PACK(3,range,aref); + + do_cmd(dev,&cmd); +} + +char *cmd_src(int src,char *buf) +{ + buf[0]=0; + + if(src&TRIG_NONE)strcat(buf,"none|"); + if(src&TRIG_NOW)strcat(buf,"now|"); + if(src&TRIG_FOLLOW)strcat(buf, "follow|"); + if(src&TRIG_TIME)strcat(buf, "time|"); + if(src&TRIG_TIMER)strcat(buf, "timer|"); + if(src&TRIG_COUNT)strcat(buf, "count|"); + if(src&TRIG_EXT)strcat(buf, "ext|"); + if(src&TRIG_INT)strcat(buf, "int|"); + + if(strlen(buf)==0){ + sprintf(buf,"unknown(0x%02x)",src); + }else{ + buf[strlen(buf)-1]=0; + } + + return buf; +} + + +void dump_cmd(comedi_cmd *cmd) +{ + char buf[100]; + + printf("start: %s %d\n", + cmd_src(cmd->start_src,buf), + cmd->start_arg); + + printf("scan_begin: %s %d\n", + cmd_src(cmd->scan_begin_src,buf), + cmd->scan_begin_arg); + + printf("convert: %s %d\n", + cmd_src(cmd->convert_src,buf), + cmd->convert_arg); + + printf("scan_end: %s %d\n", + cmd_src(cmd->scan_end_src,buf), + cmd->scan_end_arg); + + printf("stop: %s %d\n", + cmd_src(cmd->stop_src,buf), + cmd->stop_arg); +} + diff --git a/testing/mmap.c b/testing/mmap.c new file mode 100644 index 0000000..0aaab15 --- /dev/null +++ b/testing/mmap.c @@ -0,0 +1,146 @@ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "comedi_test.h" + +static int comedi_get_cmd_fast_1chan(comedi_t *it,unsigned int s,comedi_cmd *cmd); + +#define N_SAMPLES 10000 + +#define BUFSZ N_SAMPLES*sizeof(sampl_t) + +#define MAPLEN 20480 + +int test_mmap(void) +{ + comedi_cmd cmd; + char buf[BUFSZ]; + unsigned int chanlist[1]; + int go; + int total=0; + int ret; + void *b; + sampl_t *map; + + if(comedi_get_cmd_fast_1chan(device,subdevice,&cmd)<0){ + printf(" not supported\n"); + return 0; + } + + map=mmap(NULL,MAPLEN,PROT_READ,MAP_SHARED,comedi_fileno(device),0); + if(!map){ + printf("E: mmap() failed\n"); + return 0; + } + + cmd.chanlist = chanlist; + cmd.scan_end_arg = 1; + cmd.stop_arg = N_SAMPLES; + cmd.chanlist_len = 1; + chanlist[0] = CR_PACK(0,0,0); + + comedi_command(device,&cmd); + + go=1; + b=buf; + while(go){ + ret = read(comedi_fileno(device),b,BUFSZ); + if(ret<0){ + if(errno==EAGAIN){ + usleep(10000); + }else{ + go = 0; + perror("read"); + } + }else if(ret==0){ + go = 0; + }else{ + total += ret; + b += ret; + printf("read %d %d\n",ret,total); + } + } + if(memcmp(buf,map,total)){ + printf("E: mmap compare failed\n"); + }else{ + printf("compare ok\n"); + } + munmap(map,MAPLEN); + + return 0; +} + +static int comedi_get_cmd_src_mask(comedi_t *it,unsigned int s,comedi_cmd *cmd) +{ + memset(cmd,0,sizeof(*cmd)); + + cmd->subdev = s; + + cmd->flags = 0; + + cmd->start_src = TRIG_ANY; + cmd->scan_begin_src = TRIG_ANY; + cmd->convert_src = TRIG_ANY; + cmd->scan_end_src = TRIG_ANY; + cmd->stop_src = TRIG_ANY; + + return comedi_command_test(it,cmd); +} + + +static int comedi_get_cmd_fast_1chan(comedi_t *it,unsigned int s,comedi_cmd *cmd) +{ + int ret; + + ret = comedi_get_cmd_src_mask(it,s,cmd); + if(ret<0)return ret; + + cmd->chanlist_len = 1; + + cmd->scan_end_src = TRIG_COUNT; + cmd->scan_end_arg = 1; + + if(cmd->convert_src&TRIG_TIMER){ + if(cmd->scan_begin_src&TRIG_FOLLOW){ + cmd->convert_src = TRIG_TIMER; + cmd->scan_begin_src = TRIG_FOLLOW; + }else{ + cmd->convert_src = TRIG_TIMER; + cmd->scan_begin_src = TRIG_TIMER; + } + }else{ + printf("can't do timed?!?\n"); + return -1; + } + if(cmd->stop_src&TRIG_COUNT){ + cmd->stop_src=TRIG_COUNT; + cmd->stop_arg=2; + }else if(cmd->stop_src&TRIG_NONE){ + cmd->stop_src=TRIG_NONE; + cmd->stop_arg=0; + }else{ + printf("can't find a good stop_src\n"); + return -1; + } + + ret=comedi_command_test(it,cmd); + if(ret==3){ + /* good */ + ret=comedi_command_test(it,cmd); + } + if(ret==4 || ret==0){ + return 0; + } + return -1; +} + -- 2.26.2