nidas v1.2.3
dmd_mmat.h
Go to the documentation of this file.
1/* -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 8; tab-width: 8; -*- */
2/* vim: set shiftwidth=8 softtabstop=8 expandtab: */
3/*
4 ********************************************************************
5 ** NIDAS: NCAR In-situ Data Acquistion Software
6 **
7 ** 2007, Copyright University Corporation for Atmospheric Research
8 **
9 ** This program is free software; you can redistribute it and/or modify
10 ** it under the terms of the GNU General Public License as published by
11 ** the Free Software Foundation; either version 2 of the License, or
12 ** (at your option) any later version.
13 **
14 ** This program is distributed in the hope that it will be useful,
15 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
16 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 ** GNU General Public License for more details.
18 **
19 ** The LICENSE.txt file accompanying this software contains
20 ** a copy of the GNU General Public License. If it is not found,
21 ** write to the Free Software Foundation, Inc.,
22 ** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 **
24 ********************************************************************
25*/
26/*
27
28 Driver for Diamond Systems Corp MM AT series of Analog IO boards
29
30 Original Author: Gordon Maclean
31
32*/
33
34#ifndef NIDAS_DIAMOND_DMD_MMAT_H
35#define NIDAS_DIAMOND_DMD_MMAT_H
36
37#include <nidas/linux/util.h>
38#include <nidas/linux/a2d.h>
39
40#ifndef __KERNEL__
41/* User programs need this for the _IO macros, but kernel
42 * modules get their's elsewhere.
43 */
44#include <sys/ioctl.h>
45#include <sys/types.h>
46#endif
47
48/* This header is also included from user-side code that
49 * wants to get the values of the ioctl commands, and
50 * the definition of the structures.
51 */
52
53#define MAX_DMMAT_BOARDS 4 // number of boards supported by driver
54#define MAX_DMMAT_A2D_CHANNELS 32 // max num A/D channels per card
55#define DMMAT_D2A_OUTPUTS_PER_BRD 4
56#define MAX_DMMAT_D2A_OUTPUTS (MAX_DMMAT_BOARDS * DMMAT_D2A_OUTPUTS_PER_BRD)
57
59{
60 unsigned int missedSamples;
61 unsigned int fifoOverflows; // A2D FIFO has overflowed (error)
62 unsigned int fifoUnderflows; // A2D FIFO less than expected level (error)
63 unsigned int fifoEmpty; // A2D FIFO empty (error)
64};
65
66/* Supported board types */
67/*
68 * Warning: the code for DMM16AT has not been tested in many years, and
69 * much has changed in this driver since then. Until it is tested,
70 * assume it is broken.
71 */
72#define DMM16AT_BOARD 0
73#define DMM32AT_BOARD 1
74#define DMM32XAT_BOARD 2
75/* The 32DXAT version of the board has a 16 bit D2A. According to the manual
76 * it is supposed to have jumpers called DAC_SZ0/1, which allow one to configure
77 * it to behave like a DMM32XAT with a 12 bit D2A. However, they are soldered
78 * 0 ohm resistors, not jumpers, and so there is no way for the user to force
79 * the card to behave like a 32XAT. In the user forum at diamondsystems.com ,
80 * Diamond says, as of Aug 2009, that they are working on a FPGA fix to allow
81 * the user to control the D2A behaviour. This FPGA change isn't in the 2 cards
82 * that we have on the GV CVI system. There is no easy way for the driver to
83 * detect which card is present, so the user must pass this board type integer
84 * to the driver.
85 */
86#define DMM32DXAT_BOARD 3
87
88/* Pick a character as the magic number of your driver.
89 * It isn't strictly necessary that it be distinct between
90 * all modules on the system, but is a good idea. With
91 * distinct magic numbers one can catch a user sending
92 * an ioctl to the wrong device.
93 */
94#define DMMAT_IOC_MAGIC 'd'
95
96/*
97 * The enumeration of IOCTLs that this driver supports.
98 * See pages 130-132 of Linux Device Driver's Manual
99 */
100
102#define DMMAT_A2D_GET_STATUS \
103 _IOR(DMMAT_IOC_MAGIC,0,struct DMMAT_A2D_Status)
104#define DMMAT_START _IO(DMMAT_IOC_MAGIC,1)
105#define DMMAT_STOP _IO(DMMAT_IOC_MAGIC,2)
106#define DMMAT_A2D_DO_AUTOCAL _IO(DMMAT_IOC_MAGIC,3)
107
109#define DMMAT_CNTR_START \
110 _IOW(DMMAT_IOC_MAGIC,4,struct DMMAT_CNTR_Config)
111#define DMMAT_CNTR_STOP _IO(DMMAT_IOC_MAGIC,5)
112#define DMMAT_CNTR_GET_STATUS \
113 _IOR(DMMAT_IOC_MAGIC,6,struct DMMAT_CNTR_Status)
114
121#define DMMAT_D2A_GET_NOUTPUTS \
122 _IO(DMMAT_IOC_MAGIC,7)
123#define DMMAT_D2A_GET_CONVERSION \
124 _IOR(DMMAT_IOC_MAGIC,8,struct DMMAT_D2A_Conversion)
125#define DMMAT_D2A_SET \
126 _IOW(DMMAT_IOC_MAGIC,9,struct DMMAT_D2A_Outputs)
127#define DMMAT_D2A_GET \
128 _IOR(DMMAT_IOC_MAGIC,10,struct DMMAT_D2A_Outputs)
129#define DMMAT_ADD_WAVEFORM \
130 _IOW(DMMAT_IOC_MAGIC, 11, struct D2A_Waveform)
131#define DMMAT_D2A_SET_CONFIG \
132 _IOW(DMMAT_IOC_MAGIC, 12, struct D2A_Config)
133
134#define DMMAT_IOC_MAXNR 12
135
139#define DMMAT_STATUS_A2D_BUSY 0x80 // 1=conv or scan in progress
140#define DMMAT_STATUS_TIMER_INT 0x40 // interrupt from timer 0
141#define DMMAT_STATUS_SINGLE_ENDED 0x20 // 1=SE jumpered, else diff.
142#define DMMAT_STATUS_A2D_INT 0x10 // interrupt from A2D
143#define DMMAT_STATUS_CHAN_MASK 0x0f // current channel
144
150{
151 DMMAT_D2A_UNI_5, // unipolar, 0-5V
152 DMMAT_D2A_UNI_10, // unipolar, 0-10V
153 DMMAT_D2A_BI_5, // bipolar, -5-5V
154 DMMAT_D2A_BI_10, // bipolar, -10-10V
155 DMMAT_D2A_BI_2P5 // bipolar, -2.5-2.5V
157
158
160{
161 int msecPeriod; // how long to count for
162};
163
165{
166 unsigned int lostSamples;
167 unsigned int irqsReceived;
168};
169
185
187{
188 int active[MAX_DMMAT_D2A_OUTPUTS]; // 1=set, 0=ignore
189 int counts[MAX_DMMAT_D2A_OUTPUTS]; // counts value
190 int nout;
191};
192
197{
200};
201
203{
206
208 int size;
209
211 int point[0];
212};
213
214#ifdef __cplusplus
215
216#include <cstdlib>
222class D2A_WaveformWrapper {
223public:
224 D2A_WaveformWrapper(int channel, int size): _waveform(0),
225 _csize(sizeof(struct D2A_Waveform) + sizeof(_waveform->point[0]) * size)
226 {
227 _waveform = (struct D2A_Waveform*) ::malloc(_csize);
228 _waveform->channel = channel;
229 _waveform->size = size;
230 }
231
232 ~D2A_WaveformWrapper() { ::free(_waveform); }
233
235 D2A_Waveform* c_ptr() { return _waveform; }
236
240 int c_size() const { return _csize; }
241private:
242 struct D2A_Waveform* _waveform;
243 int _csize;
245 D2A_WaveformWrapper(const D2A_WaveformWrapper&);
247 D2A_WaveformWrapper& operator=(const D2A_WaveformWrapper&);
248};
249
250#endif
251
252#ifdef __KERNEL__
253/******** Start of definitions used by the driver module only **********/
254
255#include <linux/version.h>
256
257#include <linux/cdev.h>
258#include <linux/device.h>
259// #include <linux/timer.h>
260
261#include <linux/workqueue.h>
262
263#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
264#define STRUCT_MUTEX struct mutex
265#else
266#define STRUCT_MUTEX struct semaphore
267#endif
268
269/* Size of ISA I/O space (both MM16AT and MM32XAT) */
270#define DMMAT_IOPORT_WIDTH 16
271
272/*
273 * Board #0
274 * A2D: 1 device, minor number 0, /dev/dmmat_a2d0
275 * CNTR: 1 device, minor number 1 /dev/dmmat_cntr0
276 * D2A: 1 device, minor number 2, /dev/dmmat_d2a0
277 * D2D: 1 device, minor number 3, /dev/dmmat_d2d0
278 *
279 * Board #1
280 * A2D: 1 device, minor number 4, /dev/dmmat_a2d1
281 * CNTR: 1 device, minor number 5 /dev/dmmat_cntr1
282 * D2A: 1 device, minor number 6, /dev/dmmat_d2a1
283 * D2D: 1 device, minor number 7, /dev/dmmat_d2d1
284 */
285#define DMMAT_DEVICES_PER_BOARD 4 // See the next entries
286#define DMMAT_DEVICES_A2D_MINOR 0
287#define DMMAT_DEVICES_CNTR_MINOR 1
288#define DMMAT_DEVICES_D2A_MINOR 2
289#define DMMAT_DEVICES_D2D_MINOR 3
290
291/* Max size of D2A waveform on DMM32XAT and DMM32DXAT */
292#define DMMAT_D2A_WAVEFORM_SIZE 1024
293
294/* Number of samples in the output circular buffer for
295 * the pulse counter device. Size of the circular
296 * TODO: make this dynamic, dependent on the
297 * requested sample rate.
298 */
299#define DMMAT_CNTR_QUEUE_SIZE 16
300
301/* defines for analog config. These values are common to MM16AT and MM32XAT */
302#define DMMAT_UNIPOLAR 0x04
303#define DMMAT_BIPOLAR 0x00
304#define DMMAT_RANGE_10V 0x08
305#define DMMAT_RANGE_5V 0x00
306
307#define DMMAT_GAIN_1 0x00
308#define DMMAT_GAIN_2 0x01
309#define DMMAT_GAIN_4 0x02
310#define DMMAT_GAIN_8 0x03
311
312/* all boards support this rate for the input to counter 1 */
313#define DMMAT_CNTR1_INPUT_RATE 10000000
314
315/* defines for 8254 clock */
316#define DMMAT_8254_CNTR_0 0x00 // select counter 0
317#define DMMAT_8254_CNTR_1 0x40 // select counter 1
318#define DMMAT_8254_CNTR_2 0x80 // select counter 2
319#define DMMAT_8254_RWCMD 0xc0 // read-back command
320
321#define DMMAT_8254_LATCH 0x00 // latch the counter
322#define DMMAT_8254_RW_LS 0x10 // next r/w is least signif byte
323#define DMMAT_8254_RW_MS 0x20 // next r/w is most signif byte
324#define DMMAT_8254_RW_LS_MS 0x30 // next r/w is least followed by most
325
326#define DMMAT_8254_MODE_0 0x00
327#define DMMAT_8254_MODE_1 0x02
328#define DMMAT_8254_MODE_2 0x04
329#define DMMAT_8254_MODE_3 0x06
330#define DMMAT_8254_MODE_4 0x08
331#define DMMAT_8254_MODE_5 0x0a
332
333struct a2d_sample
334{
335 dsm_sample_time_t timetag; // timetag of sample
336 dsm_sample_length_t length; // number of bytes in data
339};
340
347struct counter12
348{
349 int inputRate;
350 int outputRate;
351 atomic_t userCount;
352 spinlock_t lock;
353};
354
358struct DMMAT
359{
361 int num;
362
364 unsigned int ioport;
365
367 unsigned long addr;
368
369 unsigned long addr16;
370
372 int irq;
373
375 int irq_users[2];
376
378 int type;
379
381 unsigned long itr_status_reg;
382
384 unsigned long itr_ack_reg;
385
387 unsigned char itr_mask;
388
390 unsigned char ad_itr_mask;
391
393 unsigned char cntr_itr_mask;
394
396 unsigned char itr_ack_val;
397
399 unsigned char itr_ctrl_val;
400
401 struct counter12 clock12; // counter/timer 1/2
402 struct DMMAT_A2D* a2d; // pointer to A2D device struct
403 struct DMMAT_CNTR* cntr; // pointer to CNTR device struct
404 struct DMMAT_D2A* d2a; // pointer to D2A device struct
405 struct DMMAT_D2D* d2d; // pointer to D2D device struct
406
411 int (*setClock1InputRate)(struct DMMAT* brd,int rate);
412
417 spinlock_t reglock;
418
419 STRUCT_MUTEX irqreq_mutex; // when setting up irq handler
420};
421
423struct a2d_bh_data
424{
425 struct a2d_sample saveSample;
426};
427
429struct waveform_bh_data
430{
434 struct short_sample* owsamp[MAX_DMMAT_A2D_CHANNELS];
435
439 int waveSampCntr;
440
441};
442
446struct DMMAT_A2D
447{
448 struct DMMAT* brd;
449
450 struct device* device;
451
452 struct DMMAT_A2D_Status status;
453
455 enum a2dmode { A2D_NORMAL, A2D_WAVEFORM } mode;
456
458 char deviceName[2][32];
459
460 struct cdev cdev;
461
462 STRUCT_MUTEX mutex;
463
464 atomic_t num_opened; // number of times opened
465 atomic_t running; // a2d is running
466
471 int overflow;
472
474 void (*start)(struct DMMAT_A2D* a2d); // a2d start method
475 void (*stop)(struct DMMAT_A2D* a2d); // a2d stop method
476 int (*getFifoLevel)(struct DMMAT_A2D* a2d);
477
484 int (*getA2DThreshold)(struct DMMAT_A2D* a2d);
485
486 int (*getNumA2DChannels)(struct DMMAT_A2D* a2d);
487 int (*selectA2DChannels)(struct DMMAT_A2D* a2d);
488 int (*getConvRateSetting)(struct DMMAT_A2D* a2d, unsigned char* val);
489 int (*getGainSetting)(struct DMMAT_A2D* a2d,int gain, int bipolar,
490 unsigned char* val);
491 void (*resetFifo)(struct DMMAT_A2D* a2d);
492 void (*waitForA2DSettle)(struct DMMAT_A2D* a2d);
493
511 int gain;
512
516 int bipolar;
517
521 int lowChan;
522
528 int highChan;
529
533 int nchanScanned;
534
538 unsigned char gainConvSetting;
539
543 int scanRate;
544
548 int scanDeltaT;
549
553 int maxFifoThreshold;
554
558 int fifoThreshold;
559
563 int totalOutputRate;
564
566 struct work_struct worker;
567
569 struct work_struct waveform_worker;
570
572 struct a2d_bh_data bh_data;
573
575 struct waveform_bh_data waveform_bh_data;
576
581 struct dsm_sample_circ_buf fifo_samples;
582
586 struct dsm_sample_circ_buf samples;
587
591 wait_queue_head_t read_queue;
592
596 struct sample_read_state read_state;
597
601 int nfilters;
602
606 struct short_filter_info* filters;
607
611 int waveformChannels[MAX_DMMAT_A2D_CHANNELS];
612
616 int nwaveformChannels;
617
621 int wavesize;
622
628 int latencyMsecs;
629
633 int latencyJiffies;
634
639 unsigned long lastWakeup;
640
641 struct screen_timetag_data ttdata;
642
646 unsigned int nLargeTimeAdj;
647
648};
649
654struct cntr_sample
655{
656 dsm_sample_time_t timetag;
657 dsm_sample_length_t length;
658 unsigned int data;
659};
660
664struct DMMAT_CNTR
665{
666 struct DMMAT* brd;
667
668 struct device* device;
669
670 struct cdev cdev;
671
672 char deviceName[32];
673
674 atomic_t running;
675
676 atomic_t num_opened;
677
678 STRUCT_MUTEX mutex;
679
680 struct DMMAT_CNTR_Status status;
681
682 struct timer_list timer;
683
684 int (*start)(struct DMMAT_CNTR* cntr); // cntr start method
685
686 void (*stop)(struct DMMAT_CNTR* cntr); // cntr stop method
687
688 unsigned int rolloverSum; // current counter sum
689
690 int jiffiePeriod; // how often to wake up
691 // and create an output
692
693 int firstTime; // first count is bad
694
695 atomic_t shutdownTimer; // set to 1 to stop counting
696
697 int lastVal; // previous value in the
698 // counter register
699
700 struct dsm_sample_circ_buf samples; // samples for read method
701
702 struct sample_read_state read_state;
703
704 wait_queue_head_t read_queue; // user read & poll methods
705 // wait on this queue
706
707};
708
717struct DMMAT_D2A
718{
719 struct DMMAT* brd;
720
721 struct device* device;
722
723 struct cdev cdev;
724
725 char deviceName[32];
726
727 atomic_t num_opened; // number of times opened
728
729 atomic_t waveform_running;
730
731 STRUCT_MUTEX waveform_mutex;
732
733 struct DMMAT_D2A_Outputs outputs;
734
735 int (*setD2A)(struct DMMAT_D2A* d2a,struct DMMAT_D2A_Outputs* set,int i);
736
737 int (*addWaveform)(struct DMMAT_D2A* d2a, struct D2A_Waveform* waveform);
738
739 int (*loadWaveforms)(struct DMMAT_D2A* d2a);
740
741 void (*startWaveforms)(struct DMMAT_D2A* d2a);
742
743 void (*stopWaveforms)(struct DMMAT_D2A* d2a);
744
746 int vmin;
747
749 int vmax;
750
752 int cmin;
753
755 int cmax;
756
760 int waveformRate;
761
765 struct D2A_Waveform *waveforms[DMMAT_D2A_OUTPUTS_PER_BRD];
766
770 int nWaveforms;
771
776 int wavesize;
777
778};
779
784struct DMMAT_D2D
785{
786 struct DMMAT* brd;
787
788 struct device* device;
789
790 struct cdev cdev;
791
792 char deviceName[32];
793
794 void (*start)(struct DMMAT_D2D* d2d);
795 void (*stop)(struct DMMAT_D2D* d2d);
796
797 STRUCT_MUTEX mutex;
798
799 atomic_t num_opened;
800};
801
802#endif
803
804#endif
int running
Definition ck_mesa.cc:61
static void stopWaveforms(struct DMMAT_D2A *d2a)
General function to stop the D2A waveform.
Definition dmd_mmat.c:2587
static int startWaveforms(struct DMMAT_D2A *d2a)
Definition dmd_mmat.c:2673
#define MAX_DMMAT_D2A_OUTPUTS
Definition dmd_mmat.h:56
#define MAX_DMMAT_A2D_CHANNELS
Definition dmd_mmat.h:54
#define DMMAT_D2A_OUTPUTS_PER_BRD
Definition dmd_mmat.h:55
dmmat_d2a_jumpers
Enumeration of supported jumper configurations for the D2A.
Definition dmd_mmat.h:150
@ DMMAT_D2A_UNI_10
Definition dmd_mmat.h:152
@ DMMAT_D2A_BI_5
Definition dmd_mmat.h:153
@ DMMAT_D2A_BI_2P5
Definition dmd_mmat.h:155
@ DMMAT_D2A_UNI_5
Definition dmd_mmat.h:151
@ DMMAT_D2A_BI_10
Definition dmd_mmat.h:154
static unsigned int ioport[MESA_4I34_MAX_NR_DEVS]
Definition mesa.c:72
static float rate
Definition sing.cc:53
static string device
Definition sing.cc:60
Structures used by D2A device to set up sending a repeated waveform.
Definition dmd_mmat.h:197
int waveformRate
D2A output rate in Hz: waveforms/sec.
Definition dmd_mmat.h:199
Definition dmd_mmat.h:203
int point[0]
waveform D2A values, for the channel
Definition dmd_mmat.h:211
int channel
output D2A channel number, starting at 0.
Definition dmd_mmat.h:205
int size
number of values in points array
Definition dmd_mmat.h:208
Definition dmd_mmat.h:59
unsigned int fifoOverflows
Definition dmd_mmat.h:61
unsigned int fifoEmpty
Definition dmd_mmat.h:63
unsigned int fifoUnderflows
Definition dmd_mmat.h:62
unsigned int missedSamples
Definition dmd_mmat.h:60
Definition dmd_mmat.h:160
int msecPeriod
Definition dmd_mmat.h:161
Definition dmd_mmat.h:165
unsigned int irqsReceived
Definition dmd_mmat.h:167
unsigned int lostSamples
Definition dmd_mmat.h:166
Structure describing the linear relation of counts and D2A voltage.
Definition dmd_mmat.h:179
int vmax[MAX_DMMAT_D2A_OUTPUTS]
Definition dmd_mmat.h:181
int cmin[MAX_DMMAT_D2A_OUTPUTS]
Definition dmd_mmat.h:182
int cmax[MAX_DMMAT_D2A_OUTPUTS]
Definition dmd_mmat.h:183
int vmin[MAX_DMMAT_D2A_OUTPUTS]
Definition dmd_mmat.h:180
Definition dmd_mmat.h:187
int active[MAX_DMMAT_D2A_OUTPUTS]
Definition dmd_mmat.h:188
int nout
Definition dmd_mmat.h:190
int counts[MAX_DMMAT_D2A_OUTPUTS]
Definition dmd_mmat.h:189
Definition ncar_a2d_priv.h:166
dsm_sample_time_t timetag
Definition ncar_a2d_priv.h:167
short data[NUM_NCAR_A2D_CHANNELS]
Definition ncar_a2d_priv.h:170
dsm_sample_length_t length
Definition ncar_a2d_priv.h:168
Definition lamsx.c:160
unsigned int dsm_sample_length_t
length of data portion of sample.
Definition types.h:51
int dsm_sample_time_t
Depending on the module, either tenths of milliseconds, or milliseconds since 00:00 UTC today.
Definition types.h:48