From: W. Trevor King Date: Tue, 13 Mar 2012 12:36:39 +0000 (-0400) Subject: Add `demo/python/insn.py`, a Python clone of `demo/insn.c`. X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=70eca906628c1562022e1878ea20f1fe11a0e24e;p=comedilib.git Add `demo/python/insn.py`, a Python clone of `demo/insn.c`. --- diff --git a/demo/python/insn.py b/demo/python/insn.py new file mode 100755 index 0000000..3a9a4ab --- /dev/null +++ b/demo/python/insn.py @@ -0,0 +1,180 @@ +#!/usr/bin/env python +# +# Copyright (C) May 2012 W. Trevor King +# +# This program 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 +# of the License, or (at your option) any later version. +# +# This program 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. + +"""Emulate the C demo `insn.c` + +This example does 3 instructions in one system call. It does a +`gettimeofday()` call, then reads `N_SAMPLES` samples from an analog +input, and the another `gettimeofday()` call. +""" + +import logging as _logging + +import comedi as _comedi + + +MAX_SAMPLES = 128 +LOG = _logging.getLogger('comedi-insn') +LOG.addHandler(_logging.StreamHandler()) +LOG.setLevel(_logging.ERROR) + + +def insn_str(insn): + return ', '.join([ + 'insn: {}'.format(insn.insn), + 'subdev: {}'.format(insn.subdev), + 'n: {}'.format(insn.n), + 'data: {!r}'.format(insn.data), + 'chanspec: {}'.format(insn.chanspec), + ]) + +def setup_gtod_insn(device, insn): + insn.insn = _comedi.INSN_GTOD + insn.subdev = 0 + insn.n = 2 + data = _comedi.lsampl_array(2) + data[0] = 0 + data[1] = 0 + data.thisown = False + insn.data = data.cast() + insn.chanspec = 0 + return insn + +def get_time_of_day(insn): + assert insn.insn == _comedi.INSN_GTOD, insn.insn + data = _comedi.lsampl_array.frompointer(insn.data) + seconds = data[0] + microseconds = data[1] + return seconds + microseconds/1e6 + +class SetupReadInsn (object): + def __init__(self, subdevice, channel, range, aref, n_scan): + self.subdevice = subdevice + self.channel = channel + self.range = range + self.aref = getattr(_comedi, 'AREF_{}'.format(aref.upper())) + self.n_scan = n_scan + + def __call__(self, device, insn): + insn.insn = _comedi.INSN_READ + insn.n = self.n_scan + data = _comedi.lsampl_array(self.n_scan) + data.thisown = False + insn.data = data.cast() + insn.subdev = self._get_subdevice(device) + insn.chanspec = _comedi.cr_pack(self.channel, self.range, self.aref) + return insn + + def _get_subdevice(self, device): + if self.subdevice is None: + return _comedi.comedi_find_subdevice_by_type( + device, _comedi.COMEDI_SUBD_AI, 0); + return self.subdevice + + +def setup_insns(device, insn_setup_functions): + n = len(insn_setup_functions) + insns = _comedi.comedi_insnlist_struct() + insns.n_insns = n + array = _comedi.insn_array(n) + array.thisown = False + for i,setup in enumerate(insn_setup_functions): + array[i] = setup(device, array[i]) + insns.insns = array.cast() + return insns + +def free_insns(insns): + array = _comedi.insn_array.frompointer(insns.insns) + array.thisown = True + for i in range(insns.n_insns): + insn = array[i] + data = _comedi.lsampl_array.frompointer(insn.data) + data.thisown = True + + +if __name__ == '__main__': + import argparse + + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument( + '-f', '--filename', default='/dev/comedi0', + help='path to comedi device file') + parser.add_argument( + '-s', '--subdevice', type=int, help='subdevice for analog input') + parser.add_argument( + '-c', '--channel', type=int, default=0, + help='channel for analog input') + parser.add_argument( + '-a', '--analog-reference', dest='aref', default='ground', + choices=['diff', 'ground', 'other', 'common'], + help='reference for analog input') + parser.add_argument( + '-r', '--range', type=int, default=0, help='range for analog input') + parser.add_argument( + '-N', '--num-scans', type=int, default=10, + help='number of analog input scans') + parser.add_argument( + '-v', '--verbose', default=0, action='count') + + args = parser.parse_args() + + if args.verbose >= 3: + LOG.setLevel(_logging.DEBUG) + elif args.verbose >= 2: + LOG.setLevel(_logging.INFO) + elif args.verbose >= 1: + LOG.setLevel(_logging.WARN) + + if args.num_scans > MAX_SAMPLES: + LOG.warn('requested too many samples, reducing to {}'.format( + MAX_SAMPLES)) + args.num_scans = MAX_SAMPLES + + LOG.info(('measuring device={0.filename} subdevice={0.subdevice} ' + 'channel={0.channel} range={0.range} analog reference={0.aref}' + ).format(args)) + + device = _comedi.comedi_open(args.filename) + if not device: + raise Exception('error opening Comedi device {}'.format( + args.filename)) + + setup_read_insn = SetupReadInsn( + subdevice=args.subdevice, channel=args.channel, + aref=args.aref, range=args.range, n_scan=args.num_scans) + + insns = setup_insns( + device, [setup_gtod_insn, setup_read_insn, setup_gtod_insn]) + + ret = _comedi.comedi_do_insnlist(device, insns) + if ret != insns.n_insns: + raise Exception('error running instructions ({})'.format(ret)) + + ret = _comedi.comedi_close(device) + if ret != 0: + raise Exception('error closing Comedi device {} ({})'.format( + args.filename, ret)) + + array = _comedi.insn_array.frompointer(insns.insns) + t1 = get_time_of_day(array[0]) + t2 = get_time_of_day(array[2]) + print('initial time: {}'.format(t1)) + print('final time: {}'.format(t2)) + print('difference: {}'.format(t2-t1)) + print('data:') + data = _comedi.lsampl_array.frompointer(array[1].data) + for i in range(array[1].n): + print(data[i]) + + free_insns(insns)