256 lines
7.4 KiB
C
256 lines
7.4 KiB
C
/*
|
|
calibration support for NI labpc and compatible boards
|
|
|
|
copyright (C) 2003 by Frank Mori Hess
|
|
|
|
*/
|
|
|
|
/***************************************************************************
|
|
* *
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
* it under the terms of the GNU Lesser General Public License as *
|
|
* published by *
|
|
* the Free Software Foundation; either version 2.1 of the License, or *
|
|
* (at your option) any later version. *
|
|
* *
|
|
***************************************************************************/
|
|
|
|
#define _GNU_SOURCE
|
|
|
|
#include <stdio.h>
|
|
#include <fcntl.h>
|
|
#include <unistd.h>
|
|
#include <errno.h>
|
|
#include <getopt.h>
|
|
#include <ctype.h>
|
|
#include <math.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <assert.h>
|
|
|
|
#include "calib.h"
|
|
|
|
char ni_labpc_id[] = "$Id$";
|
|
|
|
int ni_labpc_setup( calibration_setup_t *setup , const char *device_name );
|
|
static int cal_ni_labpc( calibration_setup_t *setup );
|
|
|
|
enum labpc_caldacs
|
|
{
|
|
DAC0_GAIN = 1,
|
|
ADC_OFFSET_FINE = 2,
|
|
DAC1_GAIN = 5,
|
|
ADC_GAIN = 6,
|
|
ADC_OFFSET_COARSE_ALT = 7,
|
|
DAC1_OFFSET = 9,
|
|
ADC_POSTGAIN_OFFSET = 10,
|
|
DAC0_OFFSET_ALT = 11,
|
|
ADC_OFFSET_COARSE = 12,
|
|
DAC0_OFFSET = 13,
|
|
};
|
|
static inline unsigned int DAC_OFFSET( unsigned int channel )
|
|
{
|
|
if( channel ) return DAC1_OFFSET;
|
|
else return DAC0_OFFSET;
|
|
}
|
|
static inline unsigned int DAC_GAIN( unsigned int channel )
|
|
{
|
|
if( channel ) return DAC1_GAIN;
|
|
else return DAC0_GAIN;
|
|
}
|
|
|
|
int ni_labpc_setup( calibration_setup_t *setup , const char *device_name )
|
|
{
|
|
if( setup->caldac_subdev < 0 )
|
|
{
|
|
fprintf( stderr, "no caldac subdevice found\n");
|
|
return -1;
|
|
}
|
|
setup->status = STATUS_DONE;
|
|
setup->do_cal = cal_ni_labpc;
|
|
setup_caldacs( setup, setup->caldac_subdev );
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/* load analog input caldacs from eeprom values (depend on range used) */
|
|
static void labpc_grab_ai_calibration( calibration_setup_t *setup, unsigned int range )
|
|
{
|
|
comedi_calibration_setting_t *current_cal;
|
|
/* points to (end of) analog input bipolar calibration values */
|
|
const int ai_bip_frame = read_eeprom( setup, 127 );
|
|
enum offset_indices
|
|
{
|
|
coarse_offset_index = 0,
|
|
fine_offset_index = -1,
|
|
};
|
|
/* points to (end of) analog input unipolar calibration values */
|
|
const int ai_unip_frame = read_eeprom( setup, 126 );
|
|
/* points to (end of) analog input bipolar calibration values */
|
|
const int bip_gain_frame = read_eeprom( setup, 123 );
|
|
/* points to (end of) analog input bipolar calibration values */
|
|
const int unip_gain_frame = read_eeprom( setup, 122 );
|
|
/* points to (end of) analog input bipolar calibration values */
|
|
const int bip_offset_frame = read_eeprom( setup, 121 );
|
|
/* points to (end of) analog input bipolar calibration values */
|
|
const int unip_offset_frame = read_eeprom( setup, 120 );
|
|
int ai_frame, gain_frame, offset_frame;
|
|
/* eeprom offsets by range */
|
|
int range_to_index[ 14 ] =
|
|
{
|
|
0,
|
|
-2,
|
|
-3,
|
|
-4,
|
|
-5,
|
|
-6,
|
|
-7,
|
|
0,
|
|
-2,
|
|
-3,
|
|
-4,
|
|
-5,
|
|
-6,
|
|
-7,
|
|
};
|
|
int value;
|
|
|
|
if( is_unipolar( setup->dev, setup->ad_subdev, 0, range ) )
|
|
{
|
|
ai_frame = ai_unip_frame;
|
|
gain_frame = unip_gain_frame;
|
|
offset_frame = unip_offset_frame;
|
|
}else
|
|
{
|
|
ai_frame = ai_bip_frame;
|
|
gain_frame = bip_gain_frame;
|
|
offset_frame = bip_offset_frame;
|
|
}
|
|
assert( ai_frame >=0 && gain_frame >= 0 && offset_frame >= 0 );
|
|
|
|
current_cal = sc_alloc_calibration_setting( setup );
|
|
|
|
/* load coarse offset */
|
|
value = read_eeprom( setup, ai_frame + coarse_offset_index );
|
|
assert( value >= 0 );
|
|
update_caldac( setup, ADC_OFFSET_COARSE, value );
|
|
sc_push_caldac( current_cal, setup->caldacs[ ADC_OFFSET_COARSE ] );
|
|
update_caldac( setup, ADC_OFFSET_COARSE_ALT, value );
|
|
sc_push_caldac( current_cal, setup->caldacs[ ADC_OFFSET_COARSE_ALT ] );
|
|
|
|
/* load fine offset */
|
|
value = read_eeprom( setup, ai_frame + fine_offset_index );
|
|
assert( value >= 0 );
|
|
update_caldac( setup, ADC_OFFSET_FINE, value );
|
|
sc_push_caldac( current_cal, setup->caldacs[ ADC_OFFSET_FINE ] );
|
|
|
|
/* load postgain offset */
|
|
value = read_eeprom( setup, offset_frame + range_to_index[ range ] );
|
|
assert( value >= 0 );
|
|
update_caldac( setup, ADC_POSTGAIN_OFFSET, value );
|
|
sc_push_caldac( current_cal, setup->caldacs[ ADC_POSTGAIN_OFFSET ] );
|
|
|
|
/* load gain */
|
|
value = read_eeprom( setup, gain_frame + range_to_index[ range ] );
|
|
assert( value >= 0 );
|
|
update_caldac( setup, ADC_GAIN, value );
|
|
sc_push_caldac( current_cal, setup->caldacs[ ADC_GAIN ] );
|
|
|
|
current_cal->subdevice = setup->ad_subdev;
|
|
sc_push_channel( current_cal, SC_ALL_CHANNELS );
|
|
sc_push_range( current_cal, range );
|
|
sc_push_aref( current_cal, SC_ALL_AREFS );
|
|
|
|
DPRINT( 0, "loaded adc range %i calibration from eeprom\n", range );
|
|
}
|
|
|
|
static int ao_offset_index( unsigned int channel )
|
|
{
|
|
if( channel ) return -2;
|
|
else return 0;
|
|
}
|
|
|
|
static int ao_gain_index( unsigned int channel )
|
|
{
|
|
if( channel ) return -3;
|
|
else return -1;
|
|
}
|
|
|
|
/* load analog output caldacs from eeprom values (depend on range used) */
|
|
static void labpc_grab_ao_calibration( calibration_setup_t *setup,
|
|
unsigned int channel, unsigned int range)
|
|
{
|
|
comedi_calibration_setting_t *current_cal;
|
|
/* points to (end of) analog output bipolar calibration values */
|
|
int ao_bip_frame = read_eeprom( setup, 125 );
|
|
/* points to (end of) analog output bipolar calibration values */
|
|
int ao_unip_frame = read_eeprom( setup, 124 );
|
|
int ao_frame;
|
|
int value;
|
|
|
|
current_cal = sc_alloc_calibration_setting( setup );
|
|
|
|
if( is_unipolar( setup->dev, setup->da_subdev, 0, range ) )
|
|
ao_frame = ao_unip_frame;
|
|
else
|
|
ao_frame = ao_bip_frame;
|
|
assert( ao_frame >= 0 );
|
|
|
|
/* load offset */
|
|
value = read_eeprom( setup, ao_frame + ao_offset_index( channel ) );
|
|
assert( value >= 0 );
|
|
update_caldac( setup, DAC_OFFSET( channel ), value );
|
|
sc_push_caldac( current_cal, setup->caldacs[ DAC_OFFSET( channel ) ] );
|
|
if( channel == 0 )
|
|
{
|
|
update_caldac( setup, DAC0_OFFSET_ALT, value );
|
|
sc_push_caldac( current_cal, setup->caldacs[ DAC0_OFFSET_ALT ] );
|
|
}
|
|
|
|
// load gain calibration
|
|
value = read_eeprom( setup, ao_frame + ao_gain_index( channel ) );
|
|
assert( value >= 0 );
|
|
update_caldac( setup, DAC_GAIN( channel ), value );
|
|
sc_push_caldac( current_cal, setup->caldacs[ DAC_GAIN( channel ) ] );
|
|
|
|
current_cal->subdevice = setup->da_subdev;
|
|
sc_push_channel( current_cal, channel );
|
|
sc_push_range( current_cal, range );
|
|
sc_push_aref( current_cal, SC_ALL_AREFS );
|
|
|
|
DPRINT( 0, "loaded dac channel %i range %i calibration from eeprom\n",
|
|
channel, range );
|
|
}
|
|
|
|
|
|
static int cal_ni_labpc( calibration_setup_t *setup )
|
|
{
|
|
int range, channel, num_ai_ranges, num_ao_ranges;
|
|
|
|
if( comedi_get_version_code( setup->dev ) <= COMEDI_VERSION_CODE( 0, 7, 66 ) )
|
|
{
|
|
DPRINT(0, "WARNING: you need comedi driver version 0.7.67 or later\n"
|
|
"for this calibration to work properly\n" );
|
|
}
|
|
|
|
num_ai_ranges = comedi_get_n_ranges( setup->dev, setup->ad_subdev, 0 );
|
|
assert( num_ai_ranges > 0 );
|
|
num_ao_ranges = comedi_get_n_ranges( setup->dev, setup->da_subdev, 0 );
|
|
assert( num_ao_ranges > 0 );
|
|
|
|
for( range = 0; range < num_ai_ranges; range++ )
|
|
labpc_grab_ai_calibration( setup, range );
|
|
|
|
if( setup->da_subdev >= 0 && setup->do_output )
|
|
{
|
|
for( channel = 0; channel < 2; channel++ )
|
|
{
|
|
for( range = 0; range < num_ao_ranges; range++ )
|
|
labpc_grab_ao_calibration( setup, channel, range );
|
|
}
|
|
}
|
|
|
|
return write_calibration_file( setup );
|
|
}
|
|
|