Beispiel #1
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 */
    double 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 */
    double freq = strtod(argv[3], NULL);

    /* Signal type argument parsing */
    signal_e 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;
        }
    }

    /* Check frequency limits */
    if ( (freq < c_min_frequency) || (freq > c_max_frequency ) ) {
        fprintf(stderr, "Invalid frequency: %s\n", argv[3]);
        usage();
        return -1;
    }

    awg_param_t params;
    /* Prepare data buffer (calculate from input arguments) */
    synthesize_signal(ampl, freq, type, data, &params);

    /* Write the data to the FPGA and set FPGA AWG state machine */
    write_data_fpga(ch, data, &params);
}
Beispiel #2
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);
}
Beispiel #3
0
/**
 * @brief Update Arbitrary Signal Generator module towards actual settings.
 *
 * A function is intended to be called whenever one of the following settings on each channel
 * is modified
 *    - enable
 *    - signal type
 *    - amplitude
 *    - frequency
 *    - DC offset
 *    - trigger mode
 *
 * @param[in] params  Pointer to overall configuration parameters
 * @retval -1 failure, error message is repoted on standard error device
 * @retval  0 succesful update
 */
int generate_update(rp_app_params_t *params)
{
    awg_param_t ch1_param, ch2_param;
    awg_signal_t ch1_type;
    awg_signal_t ch2_type;
    int ch1_enable = params[GEN_ENABLE_CH1].value;
    int ch2_enable = params[GEN_ENABLE_CH2].value;
    
    //float time_vect[AWG_SIG_LEN], ch1_amp[AWG_SIG_LEN], ch2_amp[AWG_SIG_LEN];
    
    float ch1_arb[AWG_SIG_LEN];
    float ch2_arb[AWG_SIG_LEN];
    
    int wrap;
    
    //int invalid_file=0;
    
    int in_smpl_len1 = 0;
    int in_smpl_len2 = 0;

    ch1_type = (awg_signal_t)params[GEN_SIG_TYPE_CH1].value;
    ch2_type = (awg_signal_t)params[GEN_SIG_TYPE_CH2].value;

    if( (ch1_type == eSignalFile) || (params[GEN_AWG_REFRESH].value == 1) ) {
        if((in_smpl_len1 = read_in_file(1, ch1_arb)) < 0) {
            // Invalid file
            params[GEN_ENABLE_CH1].value = 0;
            params[GEN_SIG_TYPE_CH1].value = eSignalSine;
            ch1_type = params[GEN_SIG_TYPE_CH1].value;
            ch1_enable = params[GEN_ENABLE_CH1].value;
            //invalid_file=1;
        }
    }

    if( (ch2_type == eSignalFile) || (params[GEN_AWG_REFRESH].value == 2) ) {
        if((in_smpl_len2 = read_in_file(2, ch2_arb)) < 0) {
            // Invalid file
            params[GEN_ENABLE_CH2].value = 0;
            params[GEN_SIG_TYPE_CH2].value = eSignalSine;
            ch2_type = params[GEN_SIG_TYPE_CH2].value;
            ch2_enable = params[GEN_ENABLE_CH2].value;
            // invalid_file=1;
        }
    }
    params[GEN_AWG_REFRESH].value = 0;

    /* Waveform from signal gets treated differently then others */
    if(ch1_enable > 0) {
        if(ch1_type < eSignalFile) {
            synthesize_signal(params[GEN_SIG_AMP_CH1].value,
                              params[GEN_SIG_FREQ_CH1].value,
                              gen_calib_params->be_ch1_dc_offs,
                              gen_calib_params->be_ch1_fs,
                              ch1_max_dac_v,
                              params[GEN_SIG_DCOFF_CH1].value,
                              ch1_type, ch1_data, &ch1_param);
            wrap = 0;  // whole buffer used
        } else {
            /* Signal file */
            calculate_data(ch1_arb,  in_smpl_len1,
                           params[GEN_SIG_AMP_CH1].value, params[GEN_SIG_FREQ_CH1].value,
                           gen_calib_params->be_ch1_dc_offs,
                           gen_calib_params->be_ch1_fs,
                           ch1_max_dac_v, params[GEN_SIG_DCOFF_CH1].value,
                           ch1_data, &ch1_param);
            wrap = 0;
            if (in_smpl_len1<AWG_SIG_LEN)
                wrap = 1; // wrapping after (in_smpl_lenx) samples
        }
    } else {
        clear_signal(gen_calib_params->be_ch1_dc_offs, ch1_data, &ch1_param);
    }
    write_data_fpga(0, params[GEN_TRIG_MODE_CH1].value,
                    params[GEN_SINGLE_CH1].value,
                    ch1_data, &ch1_param, wrap);

    /* Waveform from signal gets treated differently then others */
    if(ch2_enable > 0) {
        if(ch2_type < eSignalFile) {
            synthesize_signal(params[GEN_SIG_AMP_CH2].value,
                              params[GEN_SIG_FREQ_CH2].value,
                              gen_calib_params->be_ch2_dc_offs,
                              gen_calib_params->be_ch2_fs,
                              ch2_max_dac_v,
                              params[GEN_SIG_DCOFF_CH2].value,
                              ch2_type, ch2_data, &ch2_param);
            wrap = 0; // whole buffer used
        } else {
            /* Signal file */
            calculate_data(ch2_arb, in_smpl_len2,
                    params[GEN_SIG_AMP_CH2].value, params[GEN_SIG_FREQ_CH2].value,
                    gen_calib_params->be_ch2_dc_offs,
                    gen_calib_params->be_ch2_fs,
                    ch2_max_dac_v, params[GEN_SIG_DCOFF_CH2].value,
                    ch2_data, &ch2_param);
            wrap = 0;
            if (in_smpl_len2<AWG_SIG_LEN)
                wrap = 1; // wrapping after (in_smpl_lenx) samples
        }
    } else {
        clear_signal(gen_calib_params->be_ch2_dc_offs, ch2_data, &ch2_param);
    }
    write_data_fpga(1, params[GEN_TRIG_MODE_CH2].value,
                    params[GEN_SINGLE_CH2].value,
                    ch2_data, &ch2_param, wrap);

    /* Always return singles to 0 */
    params[GEN_SINGLE_CH1].value = 0;
    params[GEN_SINGLE_CH2].value = 0;

    
    //if (invalid_file==1)
    //  return -1;  // Use this return value to notify the GUI user about invalid file. 
    
    return 0;
}
Beispiel #4
0
void *rp_spectr_worker_thread(void *args)
{
    rp_spectr_worker_state_t old_state, state;
    rp_app_params_t          curr_params[PARAMS_NUM];
    int                      fpga_update = 1;
    int                      params_dirty = 1;

    // TODO: Name these
    int jj_state = 0;
    int iix, iix2;
    int cal_butt1_old, cal_butt2_old;
    int start_state = 1;
    awg_param_t awg_par;

    pthread_mutex_lock(&rp_spectr_ctrl_mutex);
    old_state = state = rp_spectr_ctrl;
    pthread_mutex_unlock(&rp_spectr_ctrl_mutex);

    while(1) {
        /* update states - we save also old state to see if we need to reset
         * FPGA 
         */
        old_state = state;
        pthread_mutex_lock(&rp_spectr_ctrl_mutex);
        state = rp_spectr_ctrl;
        if(rp_spectr_params_dirty) {
            memcpy(&curr_params, &rp_spectr_params, 
                   sizeof(rp_app_params_t)*PARAMS_NUM);
            fpga_update = rp_spectr_params_fpga_update;
            rp_spectr_params_dirty = 0;
        }
        pthread_mutex_unlock(&rp_spectr_ctrl_mutex);

        /* request to stop worker thread, we will shut down */
        if(state == rp_spectr_quit_state) {
            return 0;
        }

        if(fpga_update) {
            spectr_fpga_reset();
            //cal_ready1 = 0; // Resets calibration
            //cal_ready2 = 0; // Resets calibration
            jj_state = 0;

            if(spectr_fpga_update_params(0, 0, 0, 0, 0, 
                    (int)curr_params[FREQ_RANGE_PARAM].value, 0) < 0) {
                rp_spectr_worker_change_state(rp_spectr_auto_state);
            }

            fpga_update = 0;
        }

        if(state == rp_spectr_idle_state) {
            usleep(10000);
            continue;
        }

        /* Prepare AWG data buffer  */
        // Buffer prepared only once in order to save CPU resources
        if (synth_ready == 0) {
            // Before preparing buffer visualize some constant signal
            rp_resp_init_sigs(&rp_tmp_signals[0], (float **)&rp_tmp_signals[1], (float **)&rp_tmp_signals[2]);
            rp_spectr_set_signals(rp_tmp_signals);

            for (iix2 = 0; iix2 < JJ; iix2++) {
                synthesize_fra_sig(dacamp,  iix2*II*kstp, kstp, II, ch1_data, iix2*NN, &tmpdouble, &awg_par);
                scale[iix2] = tmpdouble;
            }
            synth_ready = 1;
        }

        if (start_state == 0) {
            if (round(curr_params[EN_CAL_1].value) != cal_butt1_old) {
                cal_ready1 = 0;
            }
            if (round(curr_params[EN_CAL_2].value) != cal_butt2_old) {
                cal_ready2 = 0;
            }
        } else {
            start_state = 0;
            // The calibration consists in coping the current response data to reference cal. vectors
            for (iix = 0; iix < SPECTR_OUT_SIG_LEN; iix++) {
                rp_cha_resp_cal[iix] = 56e6;
                rp_chb_resp_cal[iix] = 56e6;
            }
        }

        cal_butt1_old = round(curr_params[EN_CAL_1].value);
        cal_butt2_old = round(curr_params[EN_CAL_2].value);

        // TODO: Implement signal generator part as a separate module

        /* Write the data to the FPGA and set FPGA AWG state machine for current pattern*/
        write_data_fpga(0, 1, 0,
                ch1_data, jj_state*NN,
                &awg_par, round(65536 /
                        ((float)spectr_fpga_cnv_freq_range_to_dec(curr_params[FREQ_RANGE_PARAM].value))));

        write_data_fpga(1, 1, 0,
                ch1_data, jj_state*NN,
                &awg_par, round(65536 /
                        ((float)spectr_fpga_cnv_freq_range_to_dec(curr_params[FREQ_RANGE_PARAM].value))));

        /* Start the writing machine: DATA ACQUISITION */
        spectr_fpga_arm_trigger();
        
        usleep(10);

        spectr_fpga_set_trigger(1);

        /* start working */
        pthread_mutex_lock(&rp_spectr_ctrl_mutex);
        old_state = state = rp_spectr_ctrl;
        pthread_mutex_unlock(&rp_spectr_ctrl_mutex);
        if((state == rp_spectr_idle_state) || (state == rp_spectr_abort_state)) {
            continue;
        } else if(state == rp_spectr_quit_state) {
            break;
        }

        /* polling until data is ready */
        while(1) {
            pthread_mutex_lock(&rp_spectr_ctrl_mutex);
            state = rp_spectr_ctrl;
            params_dirty = rp_spectr_params_dirty;
            pthread_mutex_unlock(&rp_spectr_ctrl_mutex);
            /* change in state, abort polling */
            if((state != old_state) || params_dirty) {
                break;
            }
                
            if(spectr_fpga_triggered()) {
                break;
            }
        }

        if((state != old_state) || params_dirty) {
            params_dirty = 0;
            continue;
        }

        /* retrieve data and process it*/
        spectr_fpga_get_signal(&rp_cha_in, &rp_chb_in);

        /* Calculate response at frequency components for each excitation pattern*/
        rp_resp_calc(&rp_cha_in[0], &rp_chb_in[0], jj_state*II, scale[jj_state], kstp, II, (double **)&rp_cha_resp, (double **)&rp_chb_resp);

        // Continue acquiring and processing until all the pattern sequence completed
        if (jj_state < JJ) {
            jj_state++;
        } else {
            // Response characterization completed
            jj_state = 0;

            /* Perform calibration at startup or parameter update.
             * TODO: add a GUI Calibration button for individual channels
             */
            if (cal_ready1 == 0)
            {																		// Provide calibration vector initialization since calibration
                cal_ready1 = 1;													    // executed on demand
                // The calibration consists in coping the current response data to reference cal. vectors
                for (iix = 0; iix < SPECTR_OUT_SIG_LEN; iix++) {
                    rp_cha_resp_cal[iix] = rp_cha_resp[iix];
                }
            }
            /* Perform calibration at startup or parameter update
             * TODO: add a GUI Calibration button for individual channels
             */
            if (cal_ready2 == 0)
            {																		// Provide calibration vector initialization since calibration
                cal_ready2 = 1;													    // executed on demand
                // The calibration consists in coping the current response data to reverence cal. vectors
                for (iix = 0; iix < SPECTR_OUT_SIG_LEN; iix++) {
                    rp_chb_resp_cal[iix] = rp_chb_resp[iix];
                }
            }

            // Calculate frequency vector for the frequencies where response measured
            rp_resp_prepare_freq_vector(&rp_tmp_signals[0],
                    c_spectr_fpga_smpl_freq,
                    curr_params[FREQ_RANGE_PARAM].value, II, JJ, k1, kstp);


            // Calculate frequency response in dB and implement calibration
            rp_resp_cnv_to_dB(&rp_cha_resp[0], &rp_chb_resp[0],
                    &rp_cha_resp_cal[0], &rp_chb_resp_cal[0],
                    (float **)&rp_tmp_signals[1],
                    (float **)&rp_tmp_signals[2], II*JJ);

            rp_spectr_set_signals(rp_tmp_signals);

            usleep(10000);

        }
    }

    return 0;
}