Add `demo/python/insn.py`, a Python clone of `demo/insn.c`.
authorW. Trevor King <wking@drexel.edu>
Tue, 13 Mar 2012 12:36:39 +0000 (08:36 -0400)
committerW. Trevor King <wking@drexel.edu>
Tue, 13 Mar 2012 12:36:39 +0000 (08:36 -0400)
demo/python/insn.py [new file with mode: 0755]

diff --git a/demo/python/insn.py b/demo/python/insn.py
new file mode 100755 (executable)
index 0000000..3a9a4ab
--- /dev/null
@@ -0,0 +1,180 @@
+#!/usr/bin/env python
+#
+# Copyright (C) May 2012  W. Trevor King <wking@drexel.edu>
+#
+# 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)