From f639d65c67b7c0d89c28bc1de65b4225abedaf96 Mon Sep 17 00:00:00 2001 From: Frank Mori Hess Date: Sun, 8 Jan 2006 16:37:27 +0000 Subject: [PATCH] Added support for calibration pwm output used for nonlinearity calibration of m-series boards. --- Documentation/comedi/insn_config | 13 +++++-- comedi/drivers/ni_mio_common.c | 66 +++++++++++++++++++++++++++++--- comedi/drivers/ni_stc.h | 10 +++++ include/linux/comedi.h | 1 + 4 files changed, 82 insertions(+), 8 deletions(-) diff --git a/Documentation/comedi/insn_config b/Documentation/comedi/insn_config index 5c2103fc..9a2b60e3 100644 --- a/Documentation/comedi/insn_config +++ b/Documentation/comedi/insn_config @@ -85,8 +85,6 @@ ID=xxx: set software gate [1] - set/clear gate - - Applications: - Pulse counting: @@ -167,13 +165,13 @@ Applications: 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. @@ -183,3 +181,12 @@ ID=INSN_CONFIG_TIMER_1: Configure an external master clock and divisor [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) diff --git a/comedi/drivers/ni_mio_common.c b/comedi/drivers/ni_mio_common.c index 7e05e3a0..5eebad0b 100644 --- a/comedi/drivers/ni_mio_common.c +++ b/comedi/drivers/ni_mio_common.c @@ -274,6 +274,9 @@ static int cs5529_ai_insn_read(comedi_device *dev,comedi_subdevice *s,comedi_ins 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, @@ -2975,11 +2978,22 @@ static int ni_E_init(comedi_device *dev,comedi_devconfig *it) /* 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; @@ -3155,6 +3169,48 @@ static int ni_m_series_eeprom_insn_read(comedi_device *dev,comedi_subdevice *s, 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 diff --git a/comedi/drivers/ni_stc.h b/comedi/drivers/ni_stc.h index f8776777..b63b229b 100644 --- a/comedi/drivers/ni_stc.h +++ b/comedi/drivers/ni_stc.h @@ -1005,6 +1005,16 @@ enum MSeries_AO_Reference_Attenuation_Bits MSeries_Attenuate_x5_Bit = 0x1 }; +static inline unsigned MSeries_Cal_PWM_High_Time_Bits(unsigned count) +{ + return (count << 16) & 0xffff0000; +} + +static inline unsigned MSeries_Cal_PWM_Low_Time_Bits(unsigned count) +{ + return count & 0xffff; +} + #define M_SERIES_EEPROM_SIZE 1024 typedef struct ni_board_struct{ diff --git a/include/linux/comedi.h b/include/linux/comedi.h index 991c794e..3a69261f 100644 --- a/include/linux/comedi.h +++ b/include/linux/comedi.h @@ -237,6 +237,7 @@ enum configuration_ids 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 -- 2.26.2