示例#1
0
int generate_init(rp_calib_params_t *calib_params)
{
    gen_calib_params = calib_params;

    if(fpga_awg_init() < 0) {
        return -1;
    }

    ch1_max_dac_v = fpga_awg_calc_dac_max_v(gen_calib_params->be_ch1_fs);
    ch2_max_dac_v = fpga_awg_calc_dac_max_v(gen_calib_params->be_ch2_fs);
    return 0;
}
示例#2
0
/**
 * Synthesize a desired signal.
 *
 * Generates/synthesizes a signal, based on three predefined signal
 * types/shapes, signal amplitude & frequency. The data[] vector of 
 * samples at 125 MHz is generated to be re-played by the FPGA AWG module.
 *
 * @param[in]  ampl           Signal amplitude [Vpp].
 * @param[in]  freq           Signal frequency [Hz].
 * @param[in]  calib_dc_offs  Calibrated Instrument DC offset
 * @param[in]  max_dac_v      Maximum DAC voltage in [V]
 * @param[in]  user_dc_offs   User defined DC offset
 * @param[in]  type           Signal type/shape [Sine, Square, Triangle].
 * @param[in]  data           Returned synthesized AWG data vector.
 * @param[out] awg            Returned AWG parameters.
 */
void synthesize_signal(float ampl, float freq, int calib_dc_offs, int calib_fs,
                       float max_dac_v, float user_dc_offs, awg_signal_t type, 
                       int32_t *data, awg_param_t *awg) 
{
    uint32_t i;

    /* Various locally used constants - HW specific parameters */
    const int trans0 = 30;
    const int trans1 = 300;
    const float tt2 = 0.249;
    const int c_dac_max =  (1 << (c_awg_fpga_dac_bits - 1)) - 1;
    const int c_dac_min = -(1 << (c_awg_fpga_dac_bits - 1));

    int trans = round(freq / 1e6 * ((float) trans1)); /* 300 samples at 1 MHz */
    int user_dc_off_cnt = 
        round((1<<(c_awg_fpga_dac_bits-1)) * user_dc_offs / max_dac_v);
    uint32_t amp; 

    /* Saturate offset - depending on calibration offset, it could overflow */
    int offsgain = calib_dc_offs + user_dc_off_cnt;
    offsgain = (offsgain > c_dac_max) ? c_dac_max : offsgain;
    offsgain = (offsgain < c_dac_min) ? c_dac_min : offsgain;

    awg->offsgain = (offsgain << 16) | 0x2000;
    awg->step = round(65536.0 * freq/c_awg_smpl_freq * ((float) AWG_SIG_LEN));
    awg->wrap = round(65536 * (AWG_SIG_LEN - 1));
    
    //= (ampl) * (1<<(c_awg_fpga_dac_bits-2));
    //fpga_awg_calc_dac_max_v(calib_fs)
    
    amp= round(ampl/2/fpga_awg_calc_dac_max_v(calib_fs)* c_dac_max );
    
    /* Truncate to max value */
    amp = (amp > c_dac_max) ? c_dac_max : amp;

    if (trans <= 10) {
        trans = trans0;
    }

    /* Fill data[] with appropriate buffer samples */
    for(i = 0; i < AWG_SIG_LEN; i++) {
        /* Sine */
        if (type == eSignalSine) {
            data[i] = round(amp * cos(2*M_PI*(float)i/(float)AWG_SIG_LEN));
        }
 
        /* Square */
        if (type == eSignalSquare) {
            data[i] = round(amp * cos(2*M_PI*(float)i/(float)AWG_SIG_LEN));
            data[i] = (data[i] > 0) ? amp : -amp;

            /* Soft linear transitions */
            float mm, qq, xx, xm;
            float x1, x2, y1, y2;    

            xx = i;
            xm = AWG_SIG_LEN;
            mm = -2.0*(float)amp/(float)trans; 
            qq = (float)amp * (2 + xm/(2.0*(float)trans));

            x1 = xm * tt2;
            x2 = xm * tt2 + (float)trans;

            if ( (xx > x1) && (xx <= x2) ) {

                y1 = (float)amp;
                y2 = -(float)amp;

                mm = (y2 - y1) / (x2 - x1);
                qq = y1 - mm * x1;

                data[i] = round(mm * xx + qq); 
            }

            x1 = xm * 0.75;
            x2 = xm * 0.75 + trans;

            if ( (xx > x1) && (xx <= x2)) {  

                y1 = -(float)amp;
                y2 = (float)amp;

                mm = (y2 - y1) / (x2 - x1);
                qq = y1 - mm * x1;

                data[i] = round(mm * xx + qq); 
            }
        }

        /* Triangle */
        if (type == eSignalTriangle) {
            data[i] = round(-1.0 * (float)amp *
                     (acos(cos(2*M_PI*(float)i/(float)AWG_SIG_LEN))/M_PI*2-1));
        }
    }
}
示例#3
0
/** Signal generator main */
int main(int argc, char *argv[])
{
    g_argv0 = argv[0];    

    if ( argc < 4 ) {

        usage();
        return -1;
    }

    /* Channel argument parsing */
    uint32_t ch = atoi(argv[1]) - 1; /* Zero based internally */
    if (ch > 1) {
        fprintf(stderr, "Invalid channel: %s\n", argv[1]);
        usage();
        return -1;
    }

    /* Signal amplitude argument parsing */
    float ampl = strtod(argv[2], NULL);
    if ( (ampl < 0.0) || (ampl > c_max_amplitude) ) {
        fprintf(stderr, "Invalid amplitude: %s\n", argv[2]);
        usage();
        return -1;
    }

    /* Signal frequency argument parsing */
    float freq = strtod(argv[3], NULL);
    if ( (freq < 0.0) || (freq > c_max_frequency ) ) {
        fprintf(stderr, "Invalid frequency: %s\n", argv[3]);
        usage();
        return -1;
    }

    /* Signal type argument parsing */
    awg_signal_t type = eSignalSine;
    if (argc > 4) {
        if ( strcmp(argv[4], "sine") == 0) {
            type = eSignalSine;
        } else if ( strcmp(argv[4], "sqr") == 0) {
            type = eSignalSquare;
        } else if ( strcmp(argv[4], "tri") == 0) {
            type = eSignalTriangle;
        } else {
            fprintf(stderr, "Invalid signal type: %s\n", argv[4]);
            usage();
            return -1;
        }
    }

    //Added by Marko
    float offsetVolts = 0.0;
    if(argc > 5){
        offsetVolts = strtod(argv[5], NULL);
        //fprintf(stderr, "Using offset: %f\n", offsetVolts);
    } 

    rp_default_calib_params(&rp_calib_params);
    gen_calib_params = &rp_calib_params;
    if(rp_read_calib_params(gen_calib_params) < 0) {
        fprintf(stderr, "rp_read_calib_params() failed, using default"
            " parameters\n");
    }
    ch1_max_dac_v = fpga_awg_calc_dac_max_v(gen_calib_params->be_ch1_fs);
    ch2_max_dac_v = fpga_awg_calc_dac_max_v(gen_calib_params->be_ch2_fs);

    awg_param_t params;
    /* Prepare data buffer (calculate from input arguments) */
    synthesize_signal(ampl,//Amplitude
                      freq,//Frequency
                      (ch == 0) ? gen_calib_params->be_ch1_dc_offs : gen_calib_params->be_ch2_dc_offs,//Calibrated Instrument DC offset
                      (ch == 0) ? gen_calib_params->be_ch1_fs : gen_calib_params->be_ch2_fs,//Calibrated Back-End full scale coefficient
                      (ch == 0) ? ch1_max_dac_v : ch2_max_dac_v,//Maximum DAC voltage
                      offsetVolts,//DC offset voltage
                      type,//Signal type/shape
                      data,//Returned synthesized AWG data vector
                      &params);//Returned AWG parameters

    /* Write the data to the FPGA and set FPGA AWG state machine */
    write_data_fpga(ch, data, &params);
}
示例#4
0
/**
 * @brief Calculate Signal Shape based on Time Based Signal definition

 * Function is intended to calculate the shape of utput Signal for the individual channel,
 * i.e. a function must be called separatelly for each signal.
 * Time Based Signal definition is taken from input parameters in_data. time_vect and
 * in_data_len arguments. The output signal shape is additionally parameterized with
 * amp, calib_dc_offs, max_dac_v and user_dc_offs arguments, which depict properties of
 * referenced channel. Calculated Signal Shape is returned in the specified out_data buffer.
 * Beside of shape calculation the apparent AWG settings for referenced channel are calculated.
 *
 * @param[in]  in_data        Array of signal values, applied at apparent time from Time Based vector
 * @param[in]  time_vect      Array, specifying Time Based values
 * @param[in]  in_data_len    Number of valid entries in the specified buffers
 * @param[in]  amp            Maximal amplitude of calculated Signal
 * @param[in]  calib_dc_offs  Calibrated DC offset, specified in ADC counts
 * @param[in]  max_dac_v      Maximal Voltage on DAC outputs, expressed in [V]
 * @param[in]  user_dc_offs   Configurable DC offset, expressed in [V]
 * @param[out] out_data       Output Signal Shape data buffer
 * @param[out] awg            Modified AWG settings with updated offsgain, step and wrap parameters

 * @retval -1  Failure, error message is output on standard error
 * @retval  0  Success
 */
int  calculate_data(float *in_data, int in_data_len, 
                    float amp, float freq, int calib_dc_offs, uint32_t calib_fs, float max_dac_v, 
                    float user_dc_offs, int32_t *out_data, awg_param_t *awg)
{
    const int c_dac_max =  (1 << (c_awg_fpga_dac_bits - 1)) - 1;
    const int c_dac_min = -(1 << (c_awg_fpga_dac_bits - 1));

    float max_amp, min_amp;
    float k_norm;
    int i, j;

    /* calculate configurable DC offset, expressed in ADC counts */
    int user_dc_off_cnt = 
        round((1<<(c_awg_fpga_dac_bits-1)) * user_dc_offs / max_dac_v);

    /* partial check for validity of input parameters */
    if((in_data == NULL) || 
       (out_data == NULL) || (awg == NULL) || (in_data_len >= AWG_SIG_LEN)) {
        fprintf(stderr, "Internal error, the Time Based signal definition is not correctly specified.\n");
        return -1;
    }

    /* Saturate offset - depending on calibration offset, it could overflow */
    int offsgain = calib_dc_offs + user_dc_off_cnt;
    offsgain = (offsgain > c_dac_max) ? c_dac_max : offsgain;
    offsgain = (offsgain < c_dac_min) ? c_dac_min : offsgain;

    /* modify AWG settings  */
    awg->offsgain = (offsgain << 16) | 0x2000;
    awg->step = round(65536 * freq/c_awg_smpl_freq * in_data_len); 
    awg->wrap = round(65536 * (in_data_len - 1));
    
    /* Retrieve max amplitude of the specified Signal Definition, it is used for the normalization */
    max_amp = -1e30;
    min_amp = +1e30;
    
    for(i = 0; i < in_data_len; i++) {
        max_amp = (in_data[i] > max_amp) ? in_data[i] : max_amp;
        min_amp = (in_data[i] < min_amp) ? in_data[i] : min_amp;
    }
    
    /* Calculate normalization factor */
    if ((max_amp - min_amp) == 0) {
        k_norm = (max_amp == 0) ? 0 : (float)(c_dac_max) * amp /(max_amp*2) / fpga_awg_calc_dac_max_v(calib_fs);
    } 
    else {
        k_norm = (float)(c_dac_max) * amp /(max_amp - min_amp) / fpga_awg_calc_dac_max_v(calib_fs);
    }

    /* Normalize Signal values */
    for(i = 0; i < in_data_len; i++) {

        out_data[i] = round(k_norm * (in_data[i] - (max_amp + min_amp)/2));

        /* Clipping */
        if (out_data[i] > c_dac_max)
            out_data[i] = c_dac_max;
        if (out_data[i] < c_dac_min)
            out_data[i] = c_dac_min;
    }

    /* ...and pad it with zeros */
    // TODO: Really from j = i+1 ??? Should be from j = i IMHO.
    for(j = i+1; j < AWG_SIG_LEN; j++) {
        out_data[j] = 0;
    }

    return 0;
}
示例#5
0
/**
 * @brief Calculate Signal Shape based on Time Based Signal definition

 * Function is intended to calculate the shape of utput Signal for the individual channel,
 * i.e. a function must be called separatelly for each signal.
 * Time Based Signal definition is taken from input parameters in_data. time_vect and
 * in_data_len arguments. The output signal shape is additionally parameterized with
 * amp, calib_dc_offs, max_dac_v and user_dc_offs arguments, which depict properties of
 * referenced channel. Calculated Signal Shape is returned in the specified out_data buffer.
 * Beside of shape calculation the apparent AWG settings for referenced channel are calculated.
 *
 * @param[in]  in_data        Array of signal values, applied at apparent time from Time Based vector
 * @param[in]  time_vect      Array, specifying Time Based values
 * @param[in]  in_data_len    Number of valid entries in the specified buffers
 * @param[in]  amp            Maximal amplitude of calculated Signal
 * @param[in]  calib_dc_offs  Calibrated DC offset, specified in ADC counts
 * @param[in]  max_dac_v      Maximal Voltage on DAC outputs, expressed in [V]
 * @param[in]  user_dc_offs   Configurable DC offset, expressed in [V]
 * @param[out] out_data       Output Signal Shape data buffer
 * @param[out] awg            Modified AWG settings with updated offsgain, step and wrap parameters

 * @retval -1  Failure, error message is output on standard error
 * @retval  0  Success
 */
int  calculate_data(float *in_data, int in_data_len, 
                    float amp, float freq, int calib_dc_offs, uint32_t calib_fs, float max_dac_v, 
                    float user_dc_offs, int32_t *out_data, awg_param_t *awg)
{
    float max_amp,min_amp;
    float k_norm;
    int i;

    /* calculate configurable DC offset, expressed in ADC counts */
    int user_dc_off_cnt = 
        round((1<<(c_awg_fpga_dac_bits-1)) * user_dc_offs / max_dac_v);

    /* partial check for validity of input parameters */
    if((in_data == NULL) || 
       (out_data == NULL) || (awg == NULL) || (in_data_len >= AWG_SIG_LEN)) {
        fprintf(stderr, "Internal error, the Time Based signal definition is not correctly specified.\n");
        return -1;
    }

    /* modify AWG settings  */
    awg->offsgain = ((calib_dc_offs+user_dc_off_cnt) << 16) | 0x2000;
    awg->step = round(65536 * freq/c_awg_smpl_freq * in_data_len); 
    awg->wrap = round(65536 * (in_data_len-1));

    
   
    
    

    
    
    /* retrieve max amplitude of the specified Signal Definition, it is used for the normalization */
    max_amp = -1e30;
    min_amp = +1e30;
    
    for(i = 0; i < in_data_len; i++) {
        if((in_data[i]) > max_amp)
            max_amp = in_data[i];
	
        if((in_data[i]) < min_amp)
            min_amp = in_data[i];
	
    }

     
    
    /* calculate normalization factor */
    
    
   
    
    if (max_amp-min_amp==0)      
    {
      if (max_amp==0)
	
	k_norm=0;
      
      else
	
	k_norm=  (float)((1<<(c_awg_fpga_dac_bits-1))-1) * amp /(max_amp*2) /fpga_awg_calc_dac_max_v(calib_fs);
    } 
    else
      
      k_norm = (float)((1<<(c_awg_fpga_dac_bits-1))-1) * amp /(max_amp-min_amp) /fpga_awg_calc_dac_max_v(calib_fs);
    
    
    
    
    
    
    
    /* normalize Signal values */
    for(i = 0; i < in_data_len; i++) {
        out_data[i] = round(k_norm * (in_data[i]-(max_amp+min_amp)/2));
	
	// clipping
	if(out_data[i]>(1<<(c_awg_fpga_dac_bits-1))-1)
	  out_data[i]=(1<<(c_awg_fpga_dac_bits-1))-1;
	if(out_data[i]<(-(1<<(c_awg_fpga_dac_bits-1))))
	  out_data[i]=(-(1<<(c_awg_fpga_dac_bits-1)));
	
	
        if(out_data[i] < 0)
            out_data[i] += (1 << 14);
    }
    /* ...and pad it with zero */
    for(i = i+1; i < AWG_SIG_LEN; i++) {
        out_data[i] = 0;
    }
    
    
   
    
    
    return 0;
}