[1] - set/clear gate
-
-
Applications:
- Pulse counting:
invert output on gate?primary:secondary source trigger
- -
ID=INSN_CONFIG_ALT_SOURCE: select alternate input source (internal calibration reference)
[0] - ID
[1] - source
+
ID=INSN_CONFIG_TIMER_1: Configure an external master clock and divisor
to divide clock by. Used with commands by setting scan_begin_src or
convert_src set to TRIG_OTHER.
[2] - primary input chanspec (also specifies polarity and edge/level )
[3] - primary combining machine configuration (should always be 0x04)
[4] - divisor
+
+
+ID=INSN_CONFIG_PWM_OUTPUT: Configure a pulse-width-modulation output. Returns
+ EAGAIN error with modified values if exact timing is not achievable.
+
+ [0] - ID
+ [1] - flags (rounding mode for up/down times: TRIG_ROUND_NEAREST, etc.)
+ [2] - up time (nanoseconds)
+ [3] - down time (nanoseconds)
static unsigned int cs5529_config_read(comedi_device *dev, unsigned int reg_select_bits);
static void cs5529_config_write(comedi_device *dev, unsigned int value, unsigned int reg_select_bits);
+static int ni_m_series_pwm_config(comedi_device *dev, comedi_subdevice *s,
+ comedi_insn *insn,lsampl_t *data);
+
enum aimodes
{
AIMODE_NONE = 0,
/* calibration subdevice -- ai and ao */
s=dev->subdevices+5;
s->type=COMEDI_SUBD_CALIB;
- s->subdev_flags=SDF_WRITABLE|SDF_INTERNAL;
- s->insn_read=ni_calib_insn_read;
- s->insn_write=ni_calib_insn_write;
- caldac_setup(dev,s);
-
+ if(boardtype.reg_type == ni_reg_m_series)
+ {
+ // internal PWM analog output used for AI nonlinearity calibration
+ s->subdev_flags = SDF_INTERNAL;
+ s->insn_config = &ni_m_series_pwm_config;
+ s->n_chan = 1;
+ s->maxdata = 0;
+ ni_writel(0x0, M_Offset_Cal_PWM);
+ }else
+ {
+ s->subdev_flags = SDF_WRITABLE | SDF_INTERNAL;
+ s->insn_read = &ni_calib_insn_read;
+ s->insn_write = &ni_calib_insn_write;
+ caldac_setup(dev, s);
+ }
+
/* EEPROM */
s=dev->subdevices+6;
s->type=COMEDI_SUBD_MEMORY;
return 1;
}
+static int ni_m_series_pwm_config(comedi_device *dev, comedi_subdevice *s,
+ comedi_insn *insn, lsampl_t *data)
+{
+ unsigned up_count, down_count;
+ switch(data[0])
+ {
+ case INSN_CONFIG_PWM_OUTPUT:
+ switch(data[1])
+ {
+ case TRIG_ROUND_NEAREST:
+ up_count = (data[2] + TIMER_BASE / 2) / TIMER_BASE;
+ down_count = (data[3] + TIMER_BASE / 2) / TIMER_BASE;
+ break;
+ case TRIG_ROUND_DOWN:
+ up_count = data[2] / TIMER_BASE;
+ down_count = data[3] / TIMER_BASE;
+ break;
+ case TRIG_ROUND_UP:
+ up_count = (data[2] + TIMER_BASE - 1) / TIMER_BASE;
+ down_count = (data[3] + TIMER_BASE - 1) / TIMER_BASE;
+ break;
+ default:
+ return -EINVAL;
+ break;
+ }
+ if(up_count * TIMER_BASE != data[2] ||
+ down_count * TIMER_BASE != data[3])
+ {
+ data[2] = up_count * TIMER_BASE;
+ data[3] = down_count * TIMER_BASE;
+ return -EAGAIN;
+ }
+ ni_writel(MSeries_Cal_PWM_High_Time_Bits(up_count) | MSeries_Cal_PWM_Low_Time_Bits(down_count), M_Offset_Cal_PWM);
+ return 4;
+ break;
+ default:
+ return -EINVAL;
+ break;
+ }
+ return 0;
+}
+
static void ni_write_caldac(comedi_device *dev,int addr,int val);
/*
calibration subdevice
INSN_CONFIG_SERIAL_CLOCK = 26,
INSN_CONFIG_BIDIRECTIONAL_DATA = 27,
INSN_CONFIG_DIO_QUERY = 28,
+ INSN_CONFIG_PWM_OUTPUT = 29,
INSN_CONFIG_GPCT_SINGLE_PULSE_GENERATOR = 1001, // Use CTR as single pulsegenerator
INSN_CONFIG_GPCT_PULSE_TRAIN_GENERATOR = 1002, // Use CTR as pulsetraingenerator
INSN_CONFIG_GPCT_QUADRATURE_ENCODER = 1003, // Use the counter as encoder