ComediAnalogOutputSoftCal::ComediAnalogOutputSoftCal(const char *deviceFile, uint outputSubdevice, uint writeChannel, double outputConversionFactor, uint aref, bool resetOutput) : ComediAnalogIOSoftCal(deviceFile, outputSubdevice, &writeChannel, 1, PLUS_MINUS_TEN, aref), m_outputConversionFactor(outputConversionFactor), m_resetOutput(resetOutput) { Logger(Debug, "ComediAnalogOutputSoftCal::ComediAnalogOutputSoftCal()\n"); int flag = comedi_get_softcal_converter(m_subdevice, m_channels[0], m_range, COMEDI_FROM_PHYSICAL, m_calibration, &m_converter); if (flag != 0) { Logger(Critical, "comedi_get_softcal_converter: %s.\n", comedi_strerror(comedi_errno())); throw "Error in comedi_get_softcal_converter()"; } #ifdef TRIM_ANALOG_OUTPUT // get physical data range for subdevice (min, max, phys. units) m_dataRange = comedi_get_range(m_device, m_subdevice, m_channels[0], m_range); Logger(Debug, "Range for 0x%x (%s):\n\tmin = %g\n\tmax = %g\n", m_dataRange, (m_dataRange->unit == UNIT_volt ? "volts" : "milliamps"), m_dataRange->min, m_dataRange->max); if(m_dataRange == NULL) { Logger(Critical, "comedi_get_range: %s.\n", comedi_strerror(comedi_errno())); throw "Error in comedi_get_range()"; } #endif }
/** * facq_comedi_misc_test_period: * @dev: A comedi_t device. * @subindex: The subdevice index. * @n_channels: The number of channels in the chanlist. * @period: The sampling period in nanoseconds. * @err: a #GError. * * Checks if the sampling period is supported by the subdevice. * * Returns: %TRUE if the period is supported %FALSE in other case. */ gboolean facq_comedi_misc_test_period(comedi_t *dev,guint subindex,guint n_channels,guint period,GError **err) { comedi_cmd *cmd = facq_comedi_misc_cmd_new(subindex); if( comedi_get_cmd_generic_timed(dev, subindex, cmd, n_channels, period) < 0){ g_set_error_literal(err,FACQ_COMEDI_MISC_ERROR, FACQ_COMEDI_MISC_ERROR_FAILED, comedi_strerror(comedi_errno())); g_free(cmd); return FALSE; } if(cmd->scan_begin_arg != period){ g_set_error(err,FACQ_COMEDI_MISC_ERROR, FACQ_COMEDI_MISC_ERROR_FAILED, "Period not supported try %u instead", cmd->scan_begin_arg); g_free(cmd); return FALSE; } g_free(cmd); return TRUE; }
static comedi_polynomial_t *facq_comedi_misc_get_polynomial_hard(comedi_t *dev,guint subindex,const FacqChanlist *chanlist,GError **err) { comedi_polynomial_t *p = NULL; guint iochans_n = 0, i = 0; guint chanspec = 0, chan = 0, range = 0; enum comedi_conversion_direction *dir = NULL; iochans_n = facq_chanlist_get_io_chans_n(chanlist); p = g_new0(comedi_polynomial_t,iochans_n); dir = facq_chanlist_get_comedi_conversion_direction_list(chanlist,NULL); for(i = 0;i < iochans_n;i++) chanspec = facq_chanlist_get_io_chanspec(chanlist,i); facq_chanlist_chanspec_to_src_values(chanspec, &chan,&range, NULL,NULL); if( comedi_get_hardcal_converter(dev, subindex, chan, range, dir[i], &p[i]) < 0 ){ g_set_error_literal(err,FACQ_COMEDI_MISC_ERROR, FACQ_COMEDI_MISC_ERROR_FAILED, comedi_strerror(comedi_errno())); g_free(dir); return NULL; } g_free(dir); return p; }
/** * facq_comedi_misc_can_calibrate * @dev: A comedi_t device. * @subindex: The subdevice index. * @err: A #GError. * * Checks if a subdevice can be calibrated, in affirmative case returns * the supported calibration type. * * Returns: -1 in case of error, 0 if device can't be calibrated, 1 if * device can be soft-calibrated, 2 if device is hard-calibrated. */ gint facq_comedi_misc_can_calibrate(comedi_t *dev,guint subindex,GError **err) { guint subd_flags = 0; GError *local_err = NULL; const gchar *driver_name = NULL; guint i = 0, drivers_len = 6; const gchar * const drivers[] = { "ni_pcimio", "ni_atmio", "ni_mio_cs", "cb_pcidas", "cb_pcidas64", "ni_labpc" }; subd_flags = comedi_get_subdevice_flags(dev,subindex); if(subd_flags < 0){ g_set_error_literal(&local_err,FACQ_COMEDI_MISC_ERROR, FACQ_COMEDI_MISC_ERROR_FAILED, comedi_strerror(comedi_errno())); goto error; } if(subd_flags & SDF_SOFT_CALIBRATED) return 1; else { driver_name = comedi_get_driver_name(dev); if(!driver_name){ g_set_error_literal(&local_err,FACQ_COMEDI_MISC_ERROR, FACQ_COMEDI_MISC_ERROR_FAILED, comedi_strerror(comedi_errno())); goto error; } for(i = 0;i < drivers_len;i++) if(g_strcmp0(driver_name,drivers[i]) == 0) return 2; } return 0; error: if(local_err) g_propagate_error(err,local_err); return -1; }
/** * facq_comedi_misc_get_bps: * @dev:A comedi_t device. * @subindex: The subdevice index. * @err: A #GError. * * Checks the subdevice flags to get the number of bytes per sample * used by the subdevice. * * Returns: The number of bytes per sample, or 0 in case of error. */ guint facq_comedi_misc_get_bps(comedi_t *dev,guint subindex,GError **err) { guint subd_flags = 0; subd_flags = comedi_get_subdevice_flags(dev,subindex); if(subd_flags < 0){ g_set_error_literal(err,FACQ_COMEDI_MISC_ERROR, FACQ_COMEDI_MISC_ERROR_FAILED, comedi_strerror(comedi_errno())); return 0; } if(subd_flags & SDF_LSAMPL) return sizeof(lsampl_t); else return sizeof(sampl_t); }
/** * facq_comedi_misc_test_calibrated: * @dev: A comedi_t device. * @err: A #GError. * * Checks if the comedi device @dev, has been calibrated or not. * If a device was calibrated, a file with the calibration data * should exist. This function checks for this file. * * Returns: %TRUE if calibrated, %FALSE in other case. * * <para> * <note> * A malicious user can delete the file after the check is done, * but the comedi functions can deal with that. This is a simple * check. * </note> * </para> */ gboolean facq_comedi_misc_test_calibrated(comedi_t *dev,GError **err) { gchar *cal_filename = NULL; gboolean ret = FALSE; cal_filename = comedi_get_default_calibration_path(dev); if(!cal_filename){ g_set_error_literal(err,FACQ_COMEDI_MISC_ERROR, FACQ_COMEDI_MISC_ERROR_FAILED, comedi_strerror(comedi_errno())); g_free(cal_filename); return FALSE; } ret = g_file_test(cal_filename,G_FILE_TEST_EXISTS); g_free(cal_filename); return ret; }
/** * facq_comedi_misc_get_min: * @dev: A comedi_t device. * @subindex: The subdevice index. * @chanlist: A #FacqChanlist object. * @err: A #GError. * * It's equal to facq_comedi_misc_get_max() but instead of returning the * maximum values, returns the minimum expected real values. * * Returns: A gdouble array. Free it with g_free(): */ gdouble *facq_comedi_misc_get_min(comedi_t *dev,guint subindex,const FacqChanlist *chanlist,GError **err) { guint iochans_n = 0, i = 0, chanspec = 0, chan = 0,range = 0; GError *local_err = NULL; gdouble *min = NULL; comedi_range *rng = NULL; g_return_val_if_fail(FACQ_IS_CHANLIST(chanlist),NULL); iochans_n = facq_chanlist_get_io_chans_n(chanlist); if(!iochans_n){ g_set_error_literal(&local_err, FACQ_COMEDI_MISC_ERROR, FACQ_COMEDI_MISC_ERROR_FAILED, "The chanlist is empty"); goto error; } min = g_new0(gdouble,iochans_n); for(i = 0;i < iochans_n;i++){ chanspec = facq_chanlist_get_io_chanspec(chanlist,i); facq_chanlist_chanspec_to_src_values(chanspec,&chan, &range,NULL,NULL); rng = comedi_get_range(dev,subindex,chan,range); if(!rng){ g_set_error_literal(&local_err, FACQ_COMEDI_MISC_ERROR, FACQ_COMEDI_MISC_ERROR_FAILED, comedi_strerror(comedi_errno())); } min[i] = rng->min; } return min; error: if(min) g_free(min); if(local_err) g_propagate_error(err,local_err); return NULL; }
/* * facq_comedi_misc_can_poll: * @dev: A comedi_t device. * @err: A #GError NOT optional, check it. * * Some drivers can make the kernel crash when using poll() * with them, we blacklist them here to know if we can do * poll() or not. * * Returns: %TRUE if you can do poll() or %FALSE in the other case. */ gboolean facq_comedi_misc_can_poll(comedi_t *dev,GError **err) { const gchar * const drivers[] = { "comedi_test" }; guint drivers_len = 1, i = 0; const gchar *driver_name = NULL; driver_name = comedi_get_driver_name(dev); if(!driver_name){ g_set_error_literal(err,FACQ_COMEDI_MISC_ERROR, FACQ_COMEDI_MISC_ERROR_FAILED, comedi_strerror(comedi_errno())); return FALSE; } for(i = 0;i < drivers_len;i++) if(g_strcmp0(driver_name,drivers[i]) == 0) return FALSE; return TRUE; }
bool ComediDigitalInput::initialise() { // set as input channel if(!(comedi_dio_config(m_device,m_subdevice,m_channels[0],COMEDI_INPUT))==0) Logger(Critical, "ComediDigitalInput::initialise() - Config error: %s.\n",comedi_strerror(comedi_errno())); return true; }
bool ComediDigitalOutput::initialise() { // set as output if(!(comedi_dio_config(m_device, m_subdevice, m_channels[0],COMEDI_OUTPUT))==0) { Logger(Critical, "ComediDigitalOutput::initialise() - Config error: %s.\n",comedi_strerror(comedi_errno())); return false; } if(!(comedi_set_routing(m_device, m_subdevice, m_channels[0], NI_PFI_OUTPUT_PFI_DO))==0) { Logger(Critical, "ComediDigitalOutput::initialise() - Routing error: %s.\n",comedi_strerror(comedi_errno())); return false; } return true; }
ComediAnalogInputSoftCal::ComediAnalogInputSoftCal(const char *deviceFile, uint inputSubdevice, uint readChannel, double inputConversionFactor, uint range, uint aref) : ComediAnalogIOSoftCal(deviceFile, inputSubdevice, &readChannel, 1, range, aref), m_inputConversionFactor(inputConversionFactor) { Logger(Debug, "ComediAnalogInputSoftCal::ComediAnalogInputSoftCal()\n"); int flag = comedi_get_softcal_converter(m_subdevice, m_channels[0], m_range, COMEDI_TO_PHYSICAL, m_calibration, &m_converter); if (flag != 0) { Logger(Critical, "comedi_get_softcal_converter: %s.\n", comedi_strerror(comedi_errno())); throw "Error in comedi_get_softcal_converter()"; } }
bool ComediAnalogIOSoftCal::readCalibration() { Logger(Debug, "ComediAnalogIOSoftCal::readCalibration()\n"); m_calibrationFile = comedi_get_default_calibration_path(m_device); if (m_calibrationFile == NULL) { Logger(Critical, "comedi_get_default_calibration_path: %s.\n", comedi_strerror(comedi_errno())); return false; } else { Logger(Debug, "Using calibration file [%s].\n", m_calibrationFile); } m_calibration = comedi_parse_calibration_file(m_calibrationFile); if (m_calibration == NULL) { Logger(Critical, "comedi_parse_calibration_file: %s.\n", comedi_strerror(comedi_errno())); return false; } else { Logger(Debug, "Successfully parsed calibration file [%s].\n", m_calibrationFile); } return true; }
/** * facq_comedi_misc_get_polynomial: * @dev: A comedi_t device. * @subindex: The subdevice index. * @chanlist: A #FacqChanlist object. * @err: A #GError. * * The functions makes some magic to obtain a per channel, * comedi_polynomial_t array. Each polynomial can be used * to convert from comedi data to physical samples. * See <function>comedi_to_physical()</function> for more * info. * * Returns: An array of comedi_polynomial_t members. Free it * when it's no longer needed. %NULL in case of error. * The array length equals the number of I/O Channels in the * chanlist. */ comedi_polynomial_t *facq_comedi_misc_get_polynomial(comedi_t *dev,guint subindex,const FacqChanlist *chanlist,GError **err) { guint subd_flags = 0; guint i = 0, chan = 0, range = 0, aref = 0, iochans_n = 0; guint chanspec = 0; gchar *cal_filename = NULL; comedi_calibration_t *cc = NULL; GError *local_err = NULL; comedi_polynomial_t *p = NULL; g_return_val_if_fail(FACQ_IS_CHANLIST(chanlist),NULL); iochans_n = facq_chanlist_get_io_chans_n(chanlist); if(iochans_n < 1){ g_set_error_literal(&local_err,FACQ_COMEDI_MISC_ERROR, FACQ_COMEDI_MISC_ERROR_FAILED, "Chanlist is empty"); goto error; } cal_filename = comedi_get_default_calibration_path(dev); if(!cal_filename){ g_set_error_literal(&local_err,FACQ_COMEDI_MISC_ERROR, FACQ_COMEDI_MISC_ERROR_FAILED, comedi_strerror(comedi_errno())); goto error; } cc = comedi_parse_calibration_file(cal_filename); if(!cc){ g_set_error_literal(&local_err,FACQ_COMEDI_MISC_ERROR, FACQ_COMEDI_MISC_ERROR_FAILED, comedi_strerror(comedi_errno())); goto error; } g_free(cal_filename); subd_flags = comedi_get_subdevice_flags(dev,subindex); if(subd_flags < 0){ g_set_error_literal(&local_err,FACQ_COMEDI_MISC_ERROR, FACQ_COMEDI_MISC_ERROR_FAILED, comedi_strerror(comedi_errno())); goto error; } for(i = 0;i < iochans_n;i++){ chanspec = facq_chanlist_get_io_chanspec(chanlist,i); facq_chanlist_chanspec_to_src_values(chanspec, &chan, &range, &aref, NULL); if( comedi_apply_parsed_calibration(dev,subindex, chan, range, aref, cc) < 0){ g_set_error_literal(&local_err,FACQ_COMEDI_MISC_ERROR, FACQ_COMEDI_MISC_ERROR_FAILED, comedi_strerror(comedi_errno())); goto error; } } if(subd_flags & SDF_SOFT_CALIBRATED){ p = facq_comedi_misc_get_polynomial_soft(dev, subindex, chanlist, cc, &local_err); comedi_cleanup_calibration(cc); } else { comedi_cleanup_calibration(cc); p = facq_comedi_misc_get_polynomial_hard(dev, subindex, chanlist, &local_err); } if(!p) goto error; return p; error: if(cal_filename) g_free(cal_filename); if(cc) comedi_cleanup_calibration(cc); if(local_err) g_propagate_error(err,local_err); return NULL; }
/** * facq_comedi_misc_test_chanlist: * @dev: A comedi_t device. * @subindex: A subdevice index. * @chanlist: A #FacqChanlist object. * @err: A #GError. * * Checks if the provided #FacqChanlist, @chanlist, can be used with * the subdevice @subindex, in the device @dev. * * Returns: %TRUE if supported %FALSE in other case. */ gboolean facq_comedi_misc_test_chanlist(comedi_t *dev,guint subindex,const FacqChanlist *chanlist,GError **err) { GError *local_err = NULL; guint i = 0, len = 0, iochans_n = 0; guint n_channels = 0, n_ranges = 0, subd_flags = 0; guint chanspec = 0, chan = 0, range = 0, aref = 0, flags = 0; FacqChanDir dir = 0; gint subdevice_type = 0; g_return_val_if_fail(FACQ_IS_CHANLIST(chanlist),FALSE); len = facq_chanlist_get_length(chanlist); iochans_n = facq_chanlist_get_io_chans_n(chanlist); if(len < 1 || iochans_n == 0){ g_set_error(&local_err,FACQ_COMEDI_MISC_ERROR, FACQ_COMEDI_MISC_ERROR_FAILED, "Chanlist needs at least one I/O channel"); goto error; } subdevice_type = comedi_get_subdevice_type(dev,subindex); if(subdevice_type < 0){ g_set_error_literal(&local_err,FACQ_COMEDI_MISC_ERROR, FACQ_COMEDI_MISC_ERROR_FAILED, comedi_strerror(comedi_errno())); goto error; } subd_flags = comedi_get_subdevice_flags(dev,subindex); if(subd_flags < 0){ g_set_error_literal(&local_err,FACQ_COMEDI_MISC_ERROR, FACQ_COMEDI_MISC_ERROR_FAILED, comedi_strerror(comedi_errno())); goto error; } n_channels = comedi_get_n_channels(dev,subindex); if(n_channels < 0){ g_set_error_literal(&local_err,FACQ_COMEDI_MISC_ERROR, FACQ_COMEDI_MISC_ERROR_FAILED, comedi_strerror(comedi_errno())); goto error; } for(i = 0;i < len;i++){ chanspec = facq_chanlist_get_io_chanspec(chanlist,i); facq_chanlist_chanspec_to_src_values(chanspec, &chan,&range, &aref,&flags); dir = facq_chanlist_get_io_chan_direction(chanlist,i); n_ranges = comedi_get_n_ranges(dev,subindex,chan); if(n_ranges < 0){ g_set_error_literal(&local_err,FACQ_COMEDI_MISC_ERROR, FACQ_COMEDI_MISC_ERROR_FAILED, comedi_strerror(comedi_errno())); goto error; } if(!facq_comedi_misc_test_chanspec(n_channels,n_ranges, subd_flags,chan,range, aref,flags,dir, subdevice_type, &local_err)) goto error; } return TRUE; error: if(local_err) g_propagate_error(err,local_err); return FALSE; }