added analog output calibration for measurement computing 60xx series
authorFrank Mori Hess <fmhess@speakeasy.net>
Sat, 19 Apr 2003 04:56:05 +0000 (04:56 +0000)
committerFrank Mori Hess <fmhess@speakeasy.net>
Sat, 19 Apr 2003 04:56:05 +0000 (04:56 +0000)
comedi_calibrate/calib.h
comedi_calibrate/cb.c
comedi_calibrate/comedi_calibrate.c

index 39c1afa9c54bb2abf1ce7de3fe9120cca325a99f..b3888afae22b22bf1a65d9aa729cd91ae62f9955 100644 (file)
@@ -83,6 +83,7 @@ void observe( calibration_setup_t *setup );
 int preobserve( calibration_setup_t *setup, int obs);
 void observable_dependence( calibration_setup_t *setup, int obs);
 void measure_observable( calibration_setup_t *setup, int obs);
+void reset_caldac( calibration_setup_t *setup, unsigned int caldac_index );
 void reset_caldacs( calibration_setup_t *setup);
 
 /* drivers */
@@ -96,7 +97,7 @@ int cb_setup( calibration_setup_t*, const char *device_name );
 /* low level */
 
 void set_target( calibration_setup_t *setup, int obs,double target);
-void update_caldac( calibration_setup_t *setup, unsigned int caldac_index );
+void update_caldac( calibration_setup_t *setup, unsigned int caldac_index, int value );
 void setup_caldacs( calibration_setup_t *setup, int caldac_subdev);
 void postgain_cal( calibration_setup_t *setup, int obs1, int obs2, int dac);
 void cal1( calibration_setup_t *setup, int obs, int dac);
index 8cebc2583b25ad94bc98f0a1cb54520fdf3d7211..71c29118cb40eaee0940e8c5d99dd0757c5363cc 100644 (file)
@@ -269,16 +269,38 @@ int init_observables_64xx( calibration_setup_t *setup )
        return 0;
 }
 
-unsigned int high_observable_index_60xx( unsigned int ai_range )
+unsigned int ai_high_observable_index_60xx( unsigned int ai_range )
 {
        return ai_range * 2 + 1;
 }
 
-unsigned int ground_observable_index_60xx( unsigned int ai_range )
+unsigned int ai_ground_observable_index_60xx( unsigned int ai_range )
 {
        return ai_range * 2;
 }
 
+unsigned int ao_high_observable_index_60xx( const calibration_setup_t *setup,
+       unsigned int channel, unsigned int ao_range )
+{
+       int num_ai_ranges;
+
+       num_ai_ranges = comedi_get_n_ranges( setup->dev, setup->ad_subdev, 0 );
+       assert( num_ai_ranges >= 0 );
+
+       return 2 * num_ai_ranges + 2 * channel + 4 * ao_range + 1;
+}
+
+unsigned int ao_low_observable_index_60xx( const calibration_setup_t *setup,
+       unsigned int channel, unsigned int ao_range )
+{
+       int num_ai_ranges;
+
+       num_ai_ranges = comedi_get_n_ranges( setup->dev, setup->ad_subdev, 0 );
+       assert( num_ai_ranges >= 0 );
+
+       return 2 * num_ai_ranges + 2 * channel + 4 * ao_range;
+}
+
 int ai_cal_src_voltage_60xx( calibration_setup_t *setup,
        unsigned int calibration_source, float *voltage )
 {
@@ -341,23 +363,38 @@ int high_ai_cal_src_60xx( calibration_setup_t *setup, unsigned int ai_range )
        return -1;
 }
 
+int ao_cal_src_60xx( unsigned int channel )
+{
+       switch( channel )
+       {
+       case 0:
+               return 6;
+               break;
+       case 1:
+               return 7;
+               break;
+       default:
+               return -1;
+               break;
+       }
+}
+
 int init_observables_60xx( calibration_setup_t *setup )
 {
-       comedi_insn tmpl;//, po_tmpl;
+       comedi_insn tmpl;
        observable *o;
        int retval, num_ranges, i;
        float target;
-       static const int CAL_SRC_GROUND = 0;
-#if 0
-       memset( &po_tmpl, 0, sizeof(po_tmpl) );
-       po_tmpl.insn = INSN_CONFIG;
-       po_tmpl.n = 2;
-       po_tmpl.subdev = setup->ad_subdev;
-#endif
+       enum
+       {
+               CAL_SRC_GROUND = 0,
+       };
+
        memset( &tmpl, 0, sizeof(tmpl) );
        tmpl.insn = INSN_READ;
        tmpl.n = 1;
        tmpl.subdev = setup->ad_subdev;
+
        setup->n_observables = 0;
 
        num_ranges = comedi_get_n_ranges( setup->dev, setup->ad_subdev, 0 );
@@ -365,7 +402,7 @@ int init_observables_60xx( calibration_setup_t *setup )
 
        for( i = 0; i < num_ranges; i++ )
        {
-               o = setup->observables + ground_observable_index_60xx( i );
+               o = setup->observables + ai_ground_observable_index_60xx( i );
                o->reference_source = CAL_SRC_GROUND;
                assert( o->name == NULL );
                asprintf( &o->name, "calibration source %i, range %i, ground referenced",
@@ -374,10 +411,8 @@ int init_observables_60xx( calibration_setup_t *setup )
                o->observe_insn.chanspec = CR_PACK( 0, 0, AREF_GROUND) | CR_ALT_SOURCE | CR_ALT_FILTER;
                o->target = 0.0;
                setup->n_observables++;
-               DPRINT( 0, "cal src %i, range %i, target %g\n",
-                       o->reference_source, i, o->target );
 
-               o = setup->observables + high_observable_index_60xx( i );
+               o = setup->observables + ai_high_observable_index_60xx( i );
                retval = high_ai_cal_src_60xx( setup, i );
                if( retval < 0 ) return -1;
                o->reference_source = retval;
@@ -390,8 +425,51 @@ int init_observables_60xx( calibration_setup_t *setup )
                if( retval < 0 ) return -1;
                o->target = target;
                setup->n_observables++;
-               DPRINT( 0, "cal src %i, range %i, target %g\n",
-                       o->reference_source, i, o->target );
+       }
+
+       if( setup->da_subdev >= 0 )
+       {
+               comedi_insn po_tmpl;
+
+               memset( &po_tmpl, 0, sizeof(po_tmpl) );
+               po_tmpl.insn = INSN_WRITE;
+               po_tmpl.n = 1;
+               po_tmpl.subdev = setup->da_subdev;
+
+               num_ranges = comedi_get_n_ranges( setup->dev, setup->da_subdev, 0 );
+               if( num_ranges < 0 ) return -1;
+
+               for( i = 0; i < num_ranges; i++ )
+               {
+                       int dac_chan;
+                       for( dac_chan = 0; dac_chan < 2; dac_chan++ )
+                       {
+                               o = setup->observables + ao_low_observable_index_60xx( setup,
+                                       dac_chan, i );
+                               o->reference_source = ao_cal_src_60xx( dac_chan );
+                               assert( o->name == NULL );
+                               asprintf( &o->name, "dac%i low, range %i, ground referenced", dac_chan, i );
+                               o->preobserve_insn = po_tmpl;
+                               o->preobserve_insn.chanspec = CR_PACK( dac_chan, i, AREF_GROUND );
+                               o->preobserve_insn.data = o->preobserve_data;
+                               o->observe_insn = tmpl;
+                               o->observe_insn.chanspec = CR_PACK( 0, 0, AREF_GROUND) | CR_ALT_SOURCE | CR_ALT_FILTER;
+                               set_target( setup, ao_low_observable_index_60xx( setup, dac_chan, i ), 0.0 );
+                               setup->n_observables++;
+
+                               o = setup->observables + ao_high_observable_index_60xx( setup, dac_chan, i );
+                               o->reference_source = ao_cal_src_60xx( dac_chan );
+                               assert( o->name == NULL );
+                               asprintf( &o->name, "dac%i high, range %i, ground referenced", dac_chan, i );
+                               o->preobserve_insn = po_tmpl;
+                               o->preobserve_insn.chanspec = CR_PACK( dac_chan, i, AREF_GROUND );
+                               o->preobserve_insn.data = o->preobserve_data;
+                               o->observe_insn = tmpl;
+                               o->observe_insn.chanspec = CR_PACK( 0, 0, AREF_GROUND) | CR_ALT_SOURCE | CR_ALT_FILTER;
+                               set_target( setup, ao_high_observable_index_60xx( setup, dac_chan, i ), 9.0 );
+                               setup->n_observables++;
+                       }
+               }
        }
 
        return 0;
@@ -828,7 +906,7 @@ int cal_cb_pci_64xx( calibration_setup_t *setup )
 
 int cal_cb_pci_60xx( calibration_setup_t *setup )
 {
-       saved_calibration_t *saved_cals;
+       saved_calibration_t *saved_cals, *current_cal;
        enum cal_knobs_60xx
        {
                DAC0_OFFSET = 0,
@@ -840,38 +918,102 @@ int cal_cb_pci_60xx( calibration_setup_t *setup )
                ADC_GAIN_COARSE,
                ADC_GAIN_FINE,
        };
-       int i, num_ranges, retval;
+       int i, num_ai_ranges, num_ao_ranges, num_calibrations, retval;
+       int adc_offset_fine_for_ao = -1, adc_offset_coarse_for_ao = -1,
+               adc_gain_fine_for_ao = -1, adc_gain_coarse_for_ao = -1;
+       static const int ai_range_for_ao = 0;
 
        comedi_set_global_oor_behavior( COMEDI_OOR_NUMBER );
 
-       num_ranges = comedi_get_n_ranges( setup->dev, setup->ad_subdev, 0 );
-       if( num_ranges < 1 ) return -1;
+       num_ai_ranges = comedi_get_n_ranges( setup->dev, setup->ad_subdev, 0 );
+       if( num_ai_ranges < 1 ) return -1;
+       if( setup->da_subdev >= 0 )
+       {
+               num_ao_ranges = comedi_get_n_ranges( setup->dev, setup->da_subdev, 0 );
+               if( num_ai_ranges < 1 ) return -1;
+       }else
+               num_ao_ranges = 0;
+
+       num_calibrations = num_ai_ranges + 2 * num_ao_ranges;
 
-       saved_cals = malloc( num_ranges * sizeof( saved_calibration_t ) );
+       saved_cals = malloc( num_calibrations * sizeof( saved_calibration_t ) );
        if( saved_cals == NULL ) return -1;
 
-       for( i = num_ranges - 1; i >= 0; i-- )
+       current_cal = saved_cals;
+       for( i = 0; i < num_ai_ranges ; i++ )
        {
-               reset_caldacs( setup );
-
-               cal_binary( setup, ground_observable_index_60xx( i ), ADC_OFFSET_COARSE );
-               cal_binary( setup, ground_observable_index_60xx( i ), ADC_OFFSET_FINE );
-               cal_binary( setup, high_observable_index_60xx( i ), ADC_GAIN_COARSE );
-               cal_binary( setup, high_observable_index_60xx( i ), ADC_GAIN_FINE );
-
-               memset( &saved_cals[ i ], 0, sizeof( saved_calibration_t ) );
-               saved_cals[ i ].subdevice = setup->ad_subdev;
-               sc_push_caldac( &saved_cals[ i ], setup->caldacs[ ADC_OFFSET_FINE ] );
-               sc_push_caldac( &saved_cals[ i ], setup->caldacs[ ADC_OFFSET_COARSE ] );
-               sc_push_caldac( &saved_cals[ i ], setup->caldacs[ ADC_GAIN_FINE ] );
-               sc_push_caldac( &saved_cals[ i ], setup->caldacs[ ADC_GAIN_COARSE ] );
-               sc_push_channel( &saved_cals[ i ], SC_ALL_CHANNELS );
-               sc_push_range( &saved_cals[ i ], i );
-               sc_push_aref( &saved_cals[ i ], SC_ALL_AREFS );
+               reset_caldac( setup, ADC_OFFSET_COARSE );
+               reset_caldac( setup, ADC_OFFSET_FINE );
+               reset_caldac( setup, ADC_GAIN_COARSE );
+               reset_caldac( setup, ADC_GAIN_FINE );
+
+               cal_binary( setup, ai_ground_observable_index_60xx( i ), ADC_OFFSET_COARSE );
+               cal_binary( setup, ai_ground_observable_index_60xx( i ), ADC_OFFSET_FINE );
+               cal_binary( setup, ai_high_observable_index_60xx( i ), ADC_GAIN_COARSE );
+               cal_binary( setup, ai_high_observable_index_60xx( i ), ADC_GAIN_FINE );
+
+               memset( current_cal, 0, sizeof( saved_calibration_t ) );
+               current_cal->subdevice = setup->ad_subdev;
+               sc_push_caldac( current_cal, setup->caldacs[ ADC_OFFSET_FINE ] );
+               sc_push_caldac( current_cal, setup->caldacs[ ADC_OFFSET_COARSE ] );
+               sc_push_caldac( current_cal, setup->caldacs[ ADC_GAIN_FINE ] );
+               sc_push_caldac( current_cal, setup->caldacs[ ADC_GAIN_COARSE ] );
+               sc_push_channel( current_cal, SC_ALL_CHANNELS );
+               sc_push_range( current_cal, i );
+               sc_push_aref( current_cal, SC_ALL_AREFS );
+
+               current_cal++;
+
+               if( i == ai_range_for_ao )
+               {
+                       adc_offset_fine_for_ao = setup->caldacs[ ADC_OFFSET_FINE ].current;
+                       adc_offset_coarse_for_ao = setup->caldacs[ ADC_OFFSET_COARSE ].current;
+                       adc_gain_fine_for_ao = setup->caldacs[ ADC_GAIN_FINE ].current;
+                       adc_gain_coarse_for_ao = setup->caldacs[ ADC_GAIN_COARSE ].current;
+               }
        }
 
-       retval = write_calibration_file( setup, saved_cals, num_ranges );
-       for( i = 0; i < num_ranges; i++ )
+       update_caldac( setup, ADC_OFFSET_FINE, adc_offset_fine_for_ao );
+       update_caldac( setup, ADC_OFFSET_COARSE, adc_offset_coarse_for_ao );
+       update_caldac( setup, ADC_GAIN_FINE, adc_gain_fine_for_ao );
+       update_caldac( setup, ADC_GAIN_COARSE, adc_gain_coarse_for_ao );
+       for( i = 0; i < num_ao_ranges ; i++ )
+       {
+               reset_caldac( setup, DAC0_OFFSET );
+               reset_caldac( setup, DAC0_GAIN );
+
+               cal_binary( setup, ao_low_observable_index_60xx( setup, 0, i ), DAC0_OFFSET );
+               cal_binary( setup, ao_high_observable_index_60xx( setup, 0, i ), DAC0_GAIN );
+
+               memset( current_cal, 0, sizeof( saved_calibration_t ) );
+               current_cal->subdevice = setup->da_subdev;
+               sc_push_caldac( current_cal, setup->caldacs[ DAC0_OFFSET ] );
+               sc_push_caldac( current_cal, setup->caldacs[ DAC0_GAIN ] );
+               sc_push_channel( current_cal, 0 );
+               sc_push_range( current_cal, i );
+               sc_push_aref( current_cal, SC_ALL_AREFS );
+
+               current_cal++;
+
+               reset_caldac( setup, DAC1_OFFSET );
+               reset_caldac( setup, DAC1_GAIN );
+
+               cal_binary( setup, ao_low_observable_index_60xx( setup, 1, i ), DAC1_OFFSET );
+               cal_binary( setup, ao_high_observable_index_60xx( setup, 1, i ), DAC1_GAIN );
+
+               memset( current_cal, 0, sizeof( saved_calibration_t ) );
+               current_cal->subdevice = setup->da_subdev;
+               sc_push_caldac( current_cal, setup->caldacs[ DAC1_OFFSET ] );
+               sc_push_caldac( current_cal, setup->caldacs[ DAC1_GAIN ] );
+               sc_push_channel( current_cal, 1 );
+               sc_push_range( current_cal, i );
+               sc_push_aref( current_cal, SC_ALL_AREFS );
+
+               current_cal++;
+       }
+
+       retval = write_calibration_file( setup, saved_cals, num_calibrations);
+       for( i = 0; i < num_calibrations; i++ )
                clear_saved_calibration( &saved_cals[ i ] );
        free( saved_cals );
        return retval;
index 373eccb17d7d079ec76d3469c583b806cc82860d..5380e004591fb95d1d7d8fb1b3e999122108ae0c 100644 (file)
@@ -32,6 +32,7 @@
 #include <math.h>
 #include <stdlib.h>
 #include <string.h>
+#include <assert.h>
 
 #include "calib.h"
 
@@ -375,8 +376,7 @@ void postgain_cal( calibration_setup_t *setup, int obs1, int obs2, int dac)
        a = (offset1-offset2)/(slope1-slope2);
        a=setup->caldacs[dac].current-a;
 
-       setup->caldacs[dac].current=rint(a);
-       update_caldac( setup, dac );
+       update_caldac( setup, dac, rint(a) );
        usleep(100000);
 
        DPRINT(0,"caldac[%d] set to %g (%g)\n",dac,rint(a),a);
@@ -399,8 +399,7 @@ void cal1( calibration_setup_t *setup, int obs, int dac)
        check_gain_chan_x( setup, &l, setup->observables[obs].observe_insn.chanspec,dac);
        a=linear_fit_func_x(&l, setup->observables[obs].target);
 
-       setup->caldacs[dac].current=rint(a);
-       update_caldac( setup, dac );
+       update_caldac( setup, dac, rint(a) );
        usleep(100000);
 
        DPRINT(0,"caldac[%d] set to %g (%g)\n",dac,rint(a),a);
@@ -419,8 +418,7 @@ void cal1_fine( calibration_setup_t *setup, int obs, int dac )
        check_gain_chan_fine( setup, &l, setup->observables[obs].observe_insn.chanspec,dac);
        a=linear_fit_func_x(&l,setup->observables[obs].target);
 
-       setup->caldacs[dac].current=rint(a);
-       update_caldac( setup, dac );
+       update_caldac( setup, dac, rint(a) );
        usleep(100000);
 
        DPRINT(0,"caldac[%d] set to %g (%g)\n",dac,rint(a),a);
@@ -445,16 +443,14 @@ void cal_binary( calibration_setup_t *setup, int obs, int dac)
 
        new_sv_init(&sv, setup->dev,0,chanspec);
        sv.settling_time_ns = setup->settling_time_ns;
-       setup->caldacs[dac].current = x1;
-       update_caldac( setup, dac );
+       update_caldac( setup, dac, x1 );
        usleep(100000);
        new_sv_measure( setup->dev, &sv);
        y1 = sv.average;
 
        new_sv_init(&sv, setup->dev,0,chanspec);
        sv.settling_time_ns = setup->settling_time_ns;
-       setup->caldacs[dac].current = x2;
-       update_caldac( setup, dac );
+       update_caldac( setup, dac, x2 );
        usleep(100000);
        new_sv_measure( setup->dev, &sv);
        y2 = sv.average;
@@ -466,8 +462,7 @@ void cal_binary( calibration_setup_t *setup, int obs, int dac)
 
                new_sv_init(&sv, setup->dev,0,chanspec);
                sv.settling_time_ns = setup->settling_time_ns;
-               setup->caldacs[dac].current = x;
-               update_caldac( setup, dac );
+               update_caldac( setup, dac, x );
                usleep(100000);
 
                new_sv_measure( setup->dev, &sv);
@@ -507,8 +502,7 @@ void cal_postgain_binary( calibration_setup_t *setup, int obs1, int obs2, int da
        x1 = 0;
        x2 = setup->caldacs[dac].maxdata;
 
-       setup->caldacs[dac].current = x1;
-       update_caldac( setup, dac );
+       update_caldac( setup, dac, x1 );
        usleep(100000);
        preobserve( setup, obs1);
        new_sv_init(&sv1, setup->dev,0,chanspec1);
@@ -521,8 +515,7 @@ void cal_postgain_binary( calibration_setup_t *setup, int obs1, int obs2, int da
        new_sv_measure( setup->dev, &sv2);
        y1 -= sv2.average;
 
-       setup->caldacs[dac].current = x2;
-       update_caldac( setup, dac );
+       update_caldac( setup, dac, x2 );
        usleep(100000);
        preobserve( setup, obs1);
        new_sv_init(&sv1, setup->dev,0,chanspec1);
@@ -540,8 +533,7 @@ void cal_postgain_binary( calibration_setup_t *setup, int obs1, int obs2, int da
                x = (x1 + x2 + 1)/2;
                DPRINT(3,"trying %d\n",x);
 
-               setup->caldacs[dac].current = x;
-               update_caldac( setup, dac );
+               update_caldac( setup, dac, x );
                usleep(100000);
 
                preobserve( setup, obs1);
@@ -595,8 +587,7 @@ void chan_cal(int adc,int cdac,int range,double target)
        
        a=caldacs[cdac].current+(target-offset)/gain;
 
-       caldacs[cdac].current=rint(a);
-       update_caldac( setup, cdac);
+       update_caldac( setup, cdac, rint(a));
 
        read_chan2(s,adc,range);
        DPRINT(1,"caldac[%d] set to %g, offset=%s\n",cdac,a,s);
@@ -653,26 +644,34 @@ void setup_caldacs( calibration_setup_t *setup, int caldac_subdev )
        setup->n_caldacs += n_chan;
 }
 
+void reset_caldac( calibration_setup_t *setup, unsigned int caldac_index )
+{
+       assert( caldac_index < setup->n_caldacs );
+       update_caldac( setup, caldac_index, setup->caldacs[ caldac_index ].maxdata / 2 );
+}
+
 void reset_caldacs( calibration_setup_t *setup )
 {
        int i;
 
        for( i = 0; i < setup->n_caldacs; i++){
-               setup->caldacs[i].current = setup->caldacs[i].maxdata / 2;
-               update_caldac( setup, i );
+               reset_caldac( setup, i );
        }
 }
 
-void update_caldac( calibration_setup_t *setup, unsigned int caldac_index )
+void update_caldac( calibration_setup_t *setup, unsigned int caldac_index,
+       int value )
 {
        int ret;
-       caldac_t *dac = &setup->caldacs[ caldac_index ];
+       caldac_t *dac;
 
        if( caldac_index > setup->n_caldacs )
        {
                fprintf( stderr, "invalid caldac index\n" );
                return;
        }
+       dac = &setup->caldacs[ caldac_index ];
+       dac->current = value;
        DPRINT(4,"update %d %d %d\n", dac->subdev, dac->chan, dac->current);
        if( dac->current < 0 ){
                DPRINT(1,"caldac set out of range (%d<0)\n", dac->current);
@@ -738,16 +737,14 @@ double check_gain_chan_x( calibration_setup_t *setup, linear_fit_t *l,unsigned i
        new_sv_init(&sv, setup->dev,0,ad_chanspec);
        sv.settling_time_ns = setup->settling_time_ns;
 
-       setup->caldacs[cdac].current=0;
-       update_caldac( setup, cdac );
+       update_caldac( setup, cdac, 0 );
        usleep(100000);
 
        new_sv_measure( setup->dev, &sv);
 
        sum_err=0;
        for(i=0;i*step<n;i++){
-               setup->caldacs[cdac].current=i*step;
-               update_caldac( setup, cdac );
+               update_caldac( setup, cdac, i*step );
                //usleep(100000);
 
                new_sv_measure( setup->dev, &sv);
@@ -760,8 +757,7 @@ double check_gain_chan_x( calibration_setup_t *setup, linear_fit_t *l,unsigned i
                l->n++;
        }
 
-       setup->caldacs[cdac].current=orig;
-       update_caldac( setup, cdac );
+       update_caldac( setup, cdac, orig );
 
        l->yerr=sum_err/sum_err_count;
        l->dx=step;
@@ -812,16 +808,14 @@ double check_gain_chan_fine( calibration_setup_t *setup, linear_fit_t *l,unsigne
        new_sv_init(&sv, setup->dev,0,ad_chanspec);
        sv.settling_time_ns = setup->settling_time_ns;
 
-       setup->caldacs[cdac].current=0;
-       update_caldac( setup, cdac );
+       update_caldac( setup, cdac, 0 );
        usleep(100000);
 
        new_sv_measure( setup->dev, &sv);
 
        sum_err=0;
        for(i=0;i<n;i++){
-               setup->caldacs[cdac].current=i+orig-fine_size;
-               update_caldac( setup, cdac );
+               update_caldac( setup, cdac, i+orig-fine_size );
                usleep(100000);
 
                new_sv_measure( setup->dev, &sv);
@@ -834,8 +828,7 @@ double check_gain_chan_fine( calibration_setup_t *setup, linear_fit_t *l,unsigne
                l->n++;
        }
 
-       setup->caldacs[cdac].current=orig;
-       update_caldac( setup, cdac );
+       update_caldac( setup, cdac, orig );
 
        l->yerr=sum_err/sum_err_count;
        l->dx=1;