/* Compy: COMedi PYthon interface * A simple hack sharded object for importing into Python * to start using Comedi drivers for Digital I/O * * Extensively referenced xxmodule.c and others from python distribution * misc comedi examples. * * Blaine Lee Copyright 11/2000 Licence LGPL 2.0 * * V 0.4 Major additions to add support for more of the comedilib * functions. So far we have support for the comedi_ commands * open, close, get_n_subdevices, get_driver_name, get_board_name * get_n_channels, get_maxdata, get_n_ranges, get_range, * to_phys, from_phys, data_read. Changed the way the debug * and printstatus code works. * V 0.3 changed to tuple parsing & added version number __version__() * V 0.21 Resynced with sorce that had printstats debugging code in it * V 0.2 Added card number, so that multiple cards are supported * V 0.1 First release, only 'trig' type transfers are supported * */ #include #include /* for printf() */ #include #define Version 4 #define maxcards 4 static comedi_t *compy_it[maxcards]; #ifdef _COMEDILIB_DEPRECATED static comedi_trig trig; static int trigchan[2]; static short trigdata; #endif /****************************** * Debug flags - set with the * open call. Output is sent * to stderr. *****************************/ static int printstats=0; // if 1 prints mostly the received calling parms static int debug = 0; // if 1 print details of function calls /****************************** * compy_open() * opens the requested comedi device * args - a tuple containing * int - board number (0 to maxcards) * string - the comedi device to open * int - printstats 0-no, 1-yes, 2-also debug ******************************/ static PyObject * compy_open( PyObject *self, PyObject *args ) { const char *filen; int card; if (!PyArg_ParseTuple(args, "isi", &card, &filen, &printstats)) return NULL; if (printstats > 1) debug = 1; if ((card < 0) || (card >= maxcards)) return NULL; if(printstats) fprintf(stderr,"compy open '%s'\n",filen); compy_it[card]=comedi_open(filen); if(debug) fprintf(stderr,"open returned %p\n",compy_it[card]); return Py_BuildValue("i", 1); } /****************************** * compy_close() * close the requested comedi device * args - a tuple containing * int - board number (0 to maxcards) ******************************/ static PyObject * compy_close( PyObject *self, PyObject *args ) { int card; if (!PyArg_ParseTuple(args, "i", &card)) return NULL; if ((card < 0) || (card >= maxcards)) return NULL; if(printstats) fprintf(stderr,"compy close %d\n",card); comedi_close(compy_it[card]); return Py_BuildValue("i", 1); } /****************************** * compy_get_n_subdevices() * get the number of subdevices * args - * int - board number (0 to maxcards) * returns the number of subdevices on card ******************************/ static PyObject * compy_get_n_subdevices( PyObject *self, PyObject *args ) { int card; if (!PyArg_ParseTuple(args, "i:get_n_subdevices", &card)) return NULL; if ((card < 0) || (card >= maxcards)) return NULL; if(printstats) fprintf(stderr,"compy get_n_subdevices %d\n",card); return Py_BuildValue("i", comedi_get_n_subdevices(compy_it[card])); } /****************************** * compy_get_driver_name() * get the number of subdevices * args - * int - board number (0 to maxcards) * returns the name of the driver for the board ******************************/ static PyObject * compy_get_driver_name( PyObject *self, PyObject *args ) { int card; if (!PyArg_ParseTuple(args, "i:get_driver_name", &card)) return NULL; if ((card < 0) || (card >= maxcards)) return NULL; if(printstats) fprintf(stderr,"compy get_driver_name (%d)\n",card); return Py_BuildValue("s", comedi_get_driver_name(compy_it[card])); } /****************************** * compy_get_board_name() * get the number of subdevices * args - * int - board number (0 to maxcards) * returns the name of the driver for the board ******************************/ static PyObject * compy_get_board_name( PyObject *self, PyObject *args ) { int card; if (!PyArg_ParseTuple(args, "i:get_board_name", &card)) return NULL; if ((card < 0) || (card >= maxcards)) return NULL; if(printstats) fprintf(stderr,"compy get_board_name (%d)\n",card); return Py_BuildValue("s", comedi_get_board_name(compy_it[card])); } /****************************** * compy_get_subdevice_type() * get the number of subdevices * args - * int - board number (0 to maxcards) * returns the name of the driver for the board ******************************/ static PyObject * compy_get_subdevice_type( PyObject *self, PyObject *args ) { int card; int sub_dev; if (!PyArg_ParseTuple(args, "ii:get_subdevice_type", &card,&sub_dev)) return NULL; if ((card < 0) || (card >= maxcards)) return NULL; if(printstats) fprintf(stderr,"compy get_subdevice_type (%d)\n",card); return Py_BuildValue("i", comedi_get_subdevice_type(compy_it[card],sub_dev)); } /****************************** * compy_get_n_channels() * get the number of channels on subdevice * args - * int - board number (0 to maxcards) * int - subdevice * returns number of channels on subdevice ******************************/ static PyObject * compy_get_n_channels( PyObject *self, PyObject *args ) { int card; int sub_dev; if (!PyArg_ParseTuple(args, "ii", &card, &sub_dev)) return NULL; if ((card < 0) || (card >= maxcards)) return NULL; if(printstats) fprintf(stderr,"compy get_n_channels ( %d, %d)\n",card,sub_dev); return Py_BuildValue("i", comedi_get_n_channels(compy_it[card],sub_dev)); } /****************************** * compy_get_maxdata() * get the maxdata value for a channel * args - * int - board number (0 to maxcards) * int - subdevice number * int - channel number * returns maximum sample value for channel (0 on error) ******************************/ static PyObject * compy_get_maxdata( PyObject *self, PyObject *args ) { int card; int sub_dev; int channel; if (!PyArg_ParseTuple(args, "iii:maxdata", &card,&sub_dev,&channel)) return NULL; if ((card < 0) || (card >= maxcards)) return NULL; if(printstats) fprintf(stderr,"compy get_maxdata ( %d, %d, %d)\n",card,sub_dev,channel); return Py_BuildValue("i", comedi_get_maxdata(compy_it[card],sub_dev,channel)); } /****************************** * compy_get_n_ranges() * get the number of ranges a channel * args - * int - board number (0 to maxcards) * int - subdevice number * int - channel number * returns number of ranges for channel (-1 on error) ******************************/ static PyObject * compy_get_n_ranges( PyObject *self, PyObject *args ) { int card; int sub_dev; int channel; if (!PyArg_ParseTuple(args, "iii:get_n_ranges", &card,&sub_dev,&channel)) return NULL; if ((card < 0) || (card >= maxcards)) return NULL; if(printstats) fprintf(stderr,"compy get_n_ranges ( %d, %d, %d)\n",card,sub_dev,channel); return Py_BuildValue("i", comedi_get_n_ranges(compy_it[card],sub_dev,channel)); } /****************************** * compy_get_range() * get the number of ranges a channel * args - * int - board number (0 to maxcards) * int - subdevice number * int - channel number * returns range information on channel * tuple containing * min value * max value * units ( 0-volts, 1-mAmps, 2-none) ******************************/ static PyObject * compy_get_range( PyObject *self, PyObject *args ) { comedi_range *rng_p; int card; int sub_dev; int channel; int range; if (!PyArg_ParseTuple(args, "iiii:get_range", &card,&sub_dev,&channel,&range)) return NULL; if ((card < 0) || (card >= maxcards)) return NULL; if(printstats) fprintf(stderr,"compy get_n_ranges ( %d, %d, %d, %d)\n",card,sub_dev,channel,range); if ((rng_p = comedi_get_range(compy_it[card],sub_dev,channel,range))==NULL) return NULL; else return Py_BuildValue("ddi", rng_p->min, rng_p->max, rng_p->unit); } /****************************** * compy_to_phys() * convert sample to physical units * args - * int - data * tuple containing range information * min value * max value * units ( 0-volts, 1-mAmps, 2-none) * int - maxdata value for channel * returns physical value (volts) for input ******************************/ static PyObject * compy_to_phys( PyObject *self, PyObject *args ) { comedi_range rng; lsampl_t data; lsampl_t maxdata; if (!PyArg_ParseTuple(args, "i(ddi)i:to_phys", &data,&rng.min,&rng.max,&rng.unit,&maxdata)) return NULL; if(printstats) fprintf(stderr,"compy get_to_phys ( %d, %8.3f, %8.3f, %d, %d)\n", data,rng.min,rng.max,rng.unit,maxdata); return Py_BuildValue("d",comedi_to_phys(data,&rng, maxdata) ); } /****************************** * compy_from_phys() * convert physical units to sample * args - * int - data * tuple containing range information * min value * max value * units ( 0-volts, 1-mAmps, 2-none) * int - maxdata value for channel * returns the sample value (0-maxdata) ******************************/ static PyObject * compy_from_phys( PyObject *self, PyObject *args ) { comedi_range rng; double data; lsampl_t maxdata; if (!PyArg_ParseTuple(args, "d(ddi)i:from_phys", &data,&rng.min,&rng.max,&rng.unit,&maxdata)) return NULL; if(printstats) fprintf(stderr,"compy get_from_phys ( %8.3f, %8.3f, %8.3f, %d, %d)\n", data,rng.min,rng.max,rng.unit,maxdata); return Py_BuildValue("i",comedi_from_phys(data,&rng, maxdata) ); } /****************************** * compy_data_read() * read the requested comedi device * args - * tuple containing * int - board number (0 to maxcards) * int - subdevice number * int - channel number * int - range * int - aref ******************************/ static PyObject * compy_data_read(PyObject *self, PyObject *args) { int card; int subd, chan; unsigned int range = 0; unsigned int aref = 0; lsampl_t data; if (!PyArg_ParseTuple(args, "(ii)i|ii:data_read", &card, &subd, &chan,&range,&aref)) return NULL; if ((card < 0) || (card >= maxcards)) return NULL; if(debug) fprintf(stderr,"compy_data_read dev %d subd %d chan %d range %d aref %d\n",card,subd,chan,range,aref); comedi_data_read(compy_it[card],subd,chan,range,aref,&data); if(debug) fprintf(stderr,"comedi_data_read value %d\n",data); return Py_BuildValue("l", data); } #ifdef _COMEDILIB_DEPRECATED /****************************** * compy_trig() * read the requested comedi device * args - a tuple containing * int - board number (0 to maxcards) * int - subdevice number * int - channel number ******************************/ static PyObject * compy_trig( PyObject *self, PyObject *args ) { int dev, chan, data; int card; if (!PyArg_ParseTuple(args, "(iii)i", &card, &dev, &chan, &data)) return NULL; if ((card < 0) || (card >= maxcards)) return NULL; if(printstats) fprintf(stderr,"compy trig card %d dev %d chanel %d val %d\n",card,dev,chan,data); trig.subdev=dev; trig.chanlist[0]=chan; trig.data[0]=data; comedi_trigger(compy_it[card],&trig); return Py_BuildValue("i", trig.data[0]); } #endif static PyObject * compy_version( PyObject *self, PyObject *args ) { if(printstats) fprintf(stderr,"Compy version %d\n",Version); return Py_BuildValue("i", Version); } /* List of functions defined in the module */ static PyMethodDef comedi_methods[] = { {"open", compy_open, METH_VARARGS}, {"close", compy_close, METH_VARARGS}, {"get_n_subdevices",compy_get_n_subdevices, METH_VARARGS}, {"get_driver_name", compy_get_driver_name, METH_VARARGS}, {"get_board_name", compy_get_board_name, METH_VARARGS}, {"get_subdevice_type",compy_get_subdevice_type, METH_VARARGS}, {"get_n_channels", compy_get_n_channels, METH_VARARGS}, {"get_maxdata", compy_get_maxdata, METH_VARARGS}, {"get_n_ranges", compy_get_n_ranges, METH_VARARGS}, {"get_range", compy_get_range, METH_VARARGS}, #ifdef _COMEDILIB_DEPRECATED {"trig", compy_trig, METH_VARARGS}, #endif {"to_phys", compy_to_phys, METH_VARARGS}, {"from_phys", compy_from_phys, METH_VARARGS}, {"data_read", compy_data_read, METH_VARARGS}, {"__version__", compy_version, METH_VARARGS}, {NULL, NULL} /* sentinel */ }; static char comedi_doc[] = "Module to interface comedi library to Python\n"; /* Initialization function for the module (*must* be called initxx) */ DL_EXPORT(void) initcomedi(void) { /* Create the module and add the functions */ (void) Py_InitModule3("comedi", comedi_methods, comedi_doc); }