nidas  v1.2-1520
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
156 };
157 
158 
160 {
161  int msecPeriod; // how long to count for
162 };
163 
165 {
166  unsigned int lostSamples;
167  unsigned int irqsReceived;
168 };
169 
179 {
184 };
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 {
205  int channel;
206 
208  int size;
209 
211  int point[0];
212 };
213 
214 #ifdef __cplusplus
215 
216 #include <cstdlib>
222 class D2A_WaveformWrapper {
223 public:
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; }
241 private:
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 
333 struct a2d_sample
334 {
335  dsm_sample_time_t timetag; // timetag of sample
336  dsm_sample_length_t length; // number of bytes in data
338  short data[MAX_DMMAT_A2D_CHANNELS+1];
339 };
340 
347 struct counter12
348 {
349  int inputRate;
350  int outputRate;
351  atomic_t userCount;
352  spinlock_t lock;
353 };
354 
358 struct 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 
423 struct a2d_bh_data
424 {
425  struct a2d_sample saveSample;
426 };
427 
429 struct waveform_bh_data
430 {
434  struct short_sample* owsamp[MAX_DMMAT_A2D_CHANNELS];
435 
439  int waveSampCntr;
440 
441 };
442 
446 struct 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 
654 struct cntr_sample
655 {
656  dsm_sample_time_t timetag;
657  dsm_sample_length_t length;
658  unsigned int data;
659 };
660 
664 struct 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 
717 struct 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 
784 struct 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
static string device
Definition: sing.cc:60
unsigned int lostSamples
Definition: dmd_mmat.h:166
int point[0]
waveform D2A values, for the channel
Definition: dmd_mmat.h:211
unsigned int fifoOverflows
Definition: dmd_mmat.h:61
Definition: dmd_mmat.h:159
dsm_sample_length_t length
Definition: ncar_a2d_priv.h:168
int counts[MAX_DMMAT_D2A_OUTPUTS]
Definition: dmd_mmat.h:189
int dsm_sample_time_t
Depending on the module, either tenths of milliseconds, or milliseconds since 00:00 UTC today...
Definition: types.h:48
static int startWaveforms(struct DMMAT_D2A *d2a)
Definition: dmd_mmat.c:2674
Definition: dmd_mmat.h:202
unsigned int fifoEmpty
Definition: dmd_mmat.h:63
Structures used by D2A device to set up sending a repeated waveform.
Definition: dmd_mmat.h:196
Definition: ncar_a2d_priv.h:165
int running
Definition: ck_mesa.cc:61
dsm_sample_time_t timetag
Definition: ncar_a2d_priv.h:167
unsigned int irqsReceived
Definition: dmd_mmat.h:167
Definition: dmd_mmat.h:58
dmmat_d2a_jumpers
Enumeration of supported jumper configurations for the D2A.
Definition: dmd_mmat.h:149
int waveformRate
D2A output rate in Hz: waveforms/sec.
Definition: dmd_mmat.h:199
int vmax[MAX_DMMAT_D2A_OUTPUTS]
Definition: dmd_mmat.h:181
int size
number of values in points array
Definition: dmd_mmat.h:208
int cmin[MAX_DMMAT_D2A_OUTPUTS]
Definition: dmd_mmat.h:182
int channel
output D2A channel number, starting at 0.
Definition: dmd_mmat.h:205
#define MAX_DMMAT_D2A_OUTPUTS
Definition: dmd_mmat.h:56
static float rate
Definition: sing.cc:53
static unsigned int ioport[MESA_4I34_MAX_NR_DEVS]
Definition: mesa.c:72
Definition: lamsx.c:165
Structure describing the linear relation of counts and D2A voltage.
Definition: dmd_mmat.h:178
Definition: dmd_mmat.h:186
int vmin[MAX_DMMAT_D2A_OUTPUTS]
Definition: dmd_mmat.h:180
int cmax[MAX_DMMAT_D2A_OUTPUTS]
Definition: dmd_mmat.h:183
Definition: dmd_mmat.h:153
Definition: dmd_mmat.h:152
unsigned int missedSamples
Definition: dmd_mmat.h:60
int msecPeriod
Definition: dmd_mmat.h:161
#define MAX_DMMAT_A2D_CHANNELS
Definition: dmd_mmat.h:54
#define DMMAT_D2A_OUTPUTS_PER_BRD
Definition: dmd_mmat.h:55
unsigned int fifoUnderflows
Definition: dmd_mmat.h:62
static void stopWaveforms(struct DMMAT_D2A *d2a)
General function to stop the D2A waveform.
Definition: dmd_mmat.c:2588
short data[NUM_NCAR_A2D_CHANNELS]
Definition: ncar_a2d_priv.h:170
unsigned int dsm_sample_length_t
length of data portion of sample.
Definition: types.h:51
int nout
Definition: dmd_mmat.h:190
Definition: dmd_mmat.h:151
int active[MAX_DMMAT_D2A_OUTPUTS]
Definition: dmd_mmat.h:188
Definition: dmd_mmat.h:155
Definition: dmd_mmat.h:164
Definition: dmd_mmat.h:154