int spectr_fpga_update_params(int trig_imm, int trig_source, int trig_edge, float trig_delay, float trig_level, int freq_range, int enable_avg_at_dec) { /* TODO: Locking of memory map */ int fpga_trig_source = spectr_fpga_cnv_trig_source(trig_imm, trig_source, trig_edge); int fpga_dec_factor = spectr_fpga_cnv_freq_range_to_dec(freq_range); fprintf(stderr, "freq_range = %d fpga_dec_factor = %d\n", freq_range, fpga_dec_factor); int fpga_delay; int fpga_trig_thr = spectr_fpga_cnv_v_to_cnt(trig_level); /* Equalization filter coefficients */ uint32_t gain_hi_cha_filt_aa = 0x7D93; uint32_t gain_hi_cha_filt_bb = 0x437C7; uint32_t gain_hi_cha_filt_pp = 0x0; uint32_t gain_hi_cha_filt_kk = 0xffffff; uint32_t gain_hi_chb_filt_aa = 0x7D93; uint32_t gain_hi_chb_filt_bb = 0x437C7; uint32_t gain_hi_chb_filt_pp = 0x0; uint32_t gain_hi_chb_filt_kk = 0xffffff; if((fpga_trig_source < 0) || (fpga_dec_factor < 0)) { fprintf(stderr, "spectr_fpga_update_params() failed\n"); return -1; } fpga_delay = SPECTR_FPGA_SIG_LEN - 3; /* Trig source is written after ARM */ /* g_spectr_fpga_reg_mem->trig_source = fpga_trig_source;*/ if(trig_source == 0) g_spectr_fpga_reg_mem->cha_thr = fpga_trig_thr; else g_spectr_fpga_reg_mem->chb_thr = fpga_trig_thr; g_spectr_fpga_reg_mem->data_dec = fpga_dec_factor; g_spectr_fpga_reg_mem->trigger_delay = (uint32_t)fpga_delay; g_spectr_fpga_reg_mem->other = enable_avg_at_dec; g_spectr_fpga_reg_mem->cha_filt_aa = gain_hi_cha_filt_aa; g_spectr_fpga_reg_mem->cha_filt_bb = gain_hi_cha_filt_bb; g_spectr_fpga_reg_mem->cha_filt_pp = gain_hi_cha_filt_pp; g_spectr_fpga_reg_mem->cha_filt_kk = gain_hi_cha_filt_kk; g_spectr_fpga_reg_mem->chb_filt_aa = gain_hi_chb_filt_aa; g_spectr_fpga_reg_mem->chb_filt_bb = gain_hi_chb_filt_bb; g_spectr_fpga_reg_mem->chb_filt_pp = gain_hi_chb_filt_pp; g_spectr_fpga_reg_mem->chb_filt_kk = gain_hi_chb_filt_kk; return 0; }
int rp_resp_prepare_freq_vector(float **freq_out, double f_s, float freq_range, int II, int JJ, int k1, int kstp) { int i; float *f = *freq_out; float unit_div = 1e6; float freq_smpl = f_s / (float)spectr_fpga_cnv_freq_range_to_dec(freq_range); if(!f) { fprintf(stderr, "rp_spectr_prepare_freq_vector() not initialized\n"); return -1; } switch(spectr_fpga_cnv_freq_range_to_unit(freq_range)) { case 2: unit_div = 1e6; break; case 1: unit_div = 1e3; break; case 0: unit_div = 1; break; default: fprintf(stderr, "rp_spectr_prepare_freq_vector() wrong freq_range\n"); return -1; } for (i = 0;i < II*JJ; i++) { f[i] = ((float) (k1+ i *kstp )) * (float) freq_smpl / ((float) SPECTR_FPGA_SIG_LEN)/ unit_div; } if (II*JJ < SPECTR_OUT_SIG_LEN) { for (i = II*JJ; i < SPECTR_OUT_SIG_LEN; i++) f[i] = f[II*JJ - 1]; } return 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; }