/*----------------------------------------------------------------------------------*/ int rp_osc_prepare_time_vector(float **out_signal, int dec_factor, float t_start, float t_stop, int time_unit) { float smpl_period = c_osc_fpga_smpl_period * dec_factor; float t_step, t_curr; int out_idx, in_idx; int idx_step; int t_unit_factor = rp_osc_get_time_unit_factor(time_unit);; float *s = *out_signal; if(t_stop <= t_start) { t_start = 0; t_stop = OSC_FPGA_SIG_LEN * smpl_period; } t_step = (t_stop - t_start) / (((int)rp_get_params_bode(5))-1); idx_step = (int)(ceil(t_step/smpl_period)); if(idx_step > 8) idx_step = 8; for(out_idx = 0, in_idx = 0, t_curr=t_start; out_idx < ((int)rp_get_params_bode(5)); out_idx++, t_curr += t_step, in_idx += idx_step) { s[out_idx] = t_curr * t_unit_factor; } return 0; }
/* Copies source to rp_osc_signals */ int rp_osc_set_signals(float **source, int index) { pthread_mutex_lock(&rp_osc_sig_mutex); memcpy(&rp_osc_signals[0][0], &source[0][0], sizeof(float)*((int)rp_get_params_bode(5))); memcpy(&rp_osc_signals[1][0], &source[1][0], sizeof(float)*((int)rp_get_params_bode(5))); memcpy(&rp_osc_signals[2][0], &source[2][0], sizeof(float)*((int)rp_get_params_bode(5))); rp_osc_sig_last_idx = index; rp_osc_signals_dirty = 1; pthread_mutex_unlock(&rp_osc_sig_mutex); return 0; }
int rp_osc_get_signals(float ***signals, int *sig_idx) { float **s = *signals; pthread_mutex_lock(&rp_osc_sig_mutex); /* If new signals are avaliable */ if(rp_osc_signals_dirty == 0) { *sig_idx = rp_osc_sig_last_idx; pthread_mutex_unlock(&rp_osc_sig_mutex); return -1; } memcpy(&s[0][0], &rp_osc_signals[0][0], sizeof(float)*((int)rp_get_params_bode(5))); memcpy(&s[1][0], &rp_osc_signals[1][0], sizeof(float)*((int)rp_get_params_bode(5))); memcpy(&s[2][0], &rp_osc_signals[2][0], sizeof(float)*((int)rp_get_params_bode(5))); /* Index of newly copied params */ *sig_idx = rp_osc_sig_last_idx; rp_osc_signals_dirty = 0; pthread_mutex_unlock(&rp_osc_sig_mutex); return 0; }
int rp_create_signals(float ***a_signals) { int i; float **s; s = (float **)malloc(SIGNALS_NUM * sizeof(float *)); if(s == NULL) { return -1; } for(i = 0; i < SIGNALS_NUM; i++) s[i] = NULL; for(i = 0; i < SIGNALS_NUM; i++) { s[i] = (float *)malloc(((int)rp_get_params_bode(5)) * sizeof(float)); if(s[i] == NULL) { rp_cleanup_signals(a_signals); return -1; } memset(&s[i][0], 0, ((int)rp_get_params_bode(5)) * sizeof(float)); } *a_signals = s; return 0; }
int rp_get_signals(float ***s, int *sig_num, int *sig_len) { int ret_val; int sig_idx; if(*s == NULL) return -1; *sig_num = SIGNALS_NUM; *sig_len = ((int)rp_get_params_bode(5)); ret_val = rp_osc_get_signals(s, &sig_idx); /* Not finished signal */ if((ret_val != -1) && sig_idx != ((int)rp_get_params_bode(5))-1) { return -2; } /* Old signal */ if(ret_val < 0) { return -1; } return 0; }
/*----------------------------------------------------------------------------------*/ int rp_osc_decimate_partial(float **cha_out_signal, int *cha_in_signal, float **chb_out_signal, int *chb_in_signal, float **time_out_signal, int *next_wr_ptr, int last_wr_ptr, int step_wr_ptr, int next_out_idx, float t_start, int dec_factor, int time_unit, rp_osc_meas_res_t *ch1_meas, rp_osc_meas_res_t *ch2_meas, float ch1_max_adc_v, float ch2_max_adc_v, float ch1_user_dc_off, float ch2_user_dc_off) { float *cha_out = *cha_out_signal; float *chb_out = *chb_out_signal; float *t_out = *time_out_signal; int in_idx = *next_wr_ptr; float smpl_period = c_osc_fpga_smpl_period * dec_factor; int t_unit_factor = rp_osc_get_time_unit_factor(time_unit); int curr_ptr; /* check if we have reached currently acquired signals in FPGA */ osc_fpga_get_wr_ptr(&curr_ptr, NULL); for(; in_idx < curr_ptr; in_idx++) { if(in_idx >= OSC_FPGA_SIG_LEN) in_idx = in_idx % OSC_FPGA_SIG_LEN; rp_osc_meas_min_max(ch1_meas, cha_in_signal[in_idx]); rp_osc_meas_min_max(ch2_meas, chb_in_signal[in_idx]); } in_idx = *next_wr_ptr; for(; (next_out_idx < ((int)rp_get_params_bode(5))); next_out_idx++, in_idx += step_wr_ptr) { int curr_ptr; int diff_ptr; /* check if we have reached currently acquired signals in FPGA */ osc_fpga_get_wr_ptr(&curr_ptr, NULL); if(in_idx >= OSC_FPGA_SIG_LEN) in_idx = in_idx % OSC_FPGA_SIG_LEN; diff_ptr = (in_idx-curr_ptr); /* Check that we did not hit the curr ptr (and that pointer is not * wrapped */ if((in_idx >= curr_ptr) && (diff_ptr > 0) && (diff_ptr < 100)) break; cha_out[next_out_idx] = osc_fpga_cnv_cnt_to_v(cha_in_signal[in_idx], ch1_max_adc_v, rp_calib_params->fe_ch1_dc_offs, ch1_user_dc_off); chb_out[next_out_idx] = osc_fpga_cnv_cnt_to_v(chb_in_signal[in_idx], ch2_max_adc_v, rp_calib_params->fe_ch1_dc_offs, ch2_user_dc_off); t_out[next_out_idx] = (t_start + ((next_out_idx*step_wr_ptr)*smpl_period))*t_unit_factor; /* A bug in FPGA? - Trig & write pointers not sample-accurate. */ if ( (dec_factor > 64) && (next_out_idx == 2) ) { int i; for (i=0; i < next_out_idx; i++) { cha_out[i] = cha_out[next_out_idx]; chb_out[i] = chb_out[next_out_idx]; } } } *next_wr_ptr = in_idx; return next_out_idx; }
/*----------------------------------------------------------------------------------*/ int bode_start_measure(float **cha_signal, int *in_cha_signal, float **chb_signal, int *in_chb_signal, float **time_signal) { int out_idx; float *cha_s = *cha_signal; float *chb_s = *chb_signal; float *t = *time_signal; float *frequency = *time_signal; //FILE *file_phase = fopen("/tmp/bode_data/data_phase", "r"); /* We have data aquisition */ if(rp_get_params_bode(0) != 0){ for(out_idx = 0; out_idx < ((int)rp_get_params_bode(5)); out_idx++){ t[out_idx] = out_idx; cha_s[out_idx] = 1; chb_s[out_idx] = -1; } } else{ counter = 0; /* Opening files */ FILE *file_frequency = fopen("/tmp/bode_data/data_frequency", "r"); FILE *file_amplitude = fopen("/tmp/bode_data/data_amplitude", "r"); FILE *file_phase = fopen("/tmp/bode_data/data_phase", "r"); while(!feof(file_frequency)){ fscanf(file_frequency, "%f", &frequency[counter]); counter++; } /* Allocation memory */ float *amplitude = malloc(counter * sizeof(float)); float *phase = malloc(counter * sizeof(float)); int amp_counter = 0; while(!feof(file_amplitude)){ fscanf(file_amplitude, "%f", &litude[amp_counter]); amp_counter++; } int p_counter = 0; while(!feof(file_phase)){ fscanf(file_phase, "%f", &phase[p_counter]); p_counter++; } for(out_idx = 0; out_idx < counter; out_idx++){ t[out_idx] = frequency[out_idx]; if(rp_get_params_bode(8) == 0){ cha_s[out_idx] = amplitude[out_idx]; }else{ cha_s[out_idx] = phase[out_idx]; } chb_s[out_idx] = -1; } /* Closing files */ fclose(file_frequency); fclose(file_amplitude); fclose(file_phase); } return 0; }
/* Main worker thread */ void *rp_osc_worker_thread(void *args) { rp_osc_worker_state_t old_state, state; rp_app_params_t *curr_params = NULL; int fpga_update = 0; int dec_factor = 0; int time_vect_update = 0; uint32_t trig_source = 0; int params_dirty = 0; /* Long acquisition special function */ int long_acq = 0; /* long_acq if acq_time > 1 [s] */ int long_acq_idx = 0; int long_acq_first_wr_ptr = 0; int long_acq_last_wr_ptr = 0; int long_acq_step = 0; int long_acq_init_trig_ptr; rp_osc_meas_res_t ch1_meas, ch2_meas; float ch1_max_adc_v = 1, ch2_max_adc_v = 1; float max_adc_norm = osc_fpga_calc_adc_max_v(rp_calib_params->fe_ch1_fs_g_hi, 0); pthread_mutex_lock(&rp_osc_ctrl_mutex); old_state = state = rp_osc_ctrl; pthread_mutex_unlock(&rp_osc_ctrl_mutex); while(1) { /* update states - we also save old state to see if we need to reset * FPGA */ int start_measure = rp_get_params_bode(0); if(start_measure == 1){ char command[100]; float read_amp = rp_get_params_bode(1); float read_avg = rp_get_params_bode(2); float read_dc_bias = rp_get_params_bode(3); float read_start_freq = rp_get_params_bode(4); float read_counts = rp_get_params_bode(5); float read_scale = rp_get_params_bode(6); float read_end_freq = rp_get_params_bode(9); char amp[5]; char avg[5]; char dc_bias[5]; char s_freq[20]; char e_freq[20]; char scale[5]; char counts[5]; snprintf(amp, 5, "%f", read_amp); snprintf(avg, 5, "%f", read_avg); snprintf(dc_bias, 5, "%f", read_dc_bias); snprintf(s_freq, 20, "%f", read_start_freq); snprintf(e_freq,20, "%f", read_end_freq); snprintf(scale, 5, "%f", read_scale); snprintf(counts, 5, "%f", read_counts); strcpy(command, "/opt/www/apps/bode_plotter/bode 1 "); strcat(command, amp); strcat(command, " "); strcat(command, dc_bias); strcat(command, " "); strcat(command, avg); strcat(command, " "); strcat(command, counts); strcat(command, " "); strcat(command, s_freq); strcat(command, " "); strcat(command, e_freq); strcat(command, " "); strcat(command, scale); system(command); rp_set_params_bode(0, 0); } old_state = state; pthread_mutex_lock(&rp_osc_ctrl_mutex); state = rp_osc_ctrl; /* If there are no new params */ if(rp_osc_params_dirty) { rp_copy_params(rp_osc_params, (rp_app_params_t **)&curr_params); fpga_update = rp_osc_params_fpga_update; rp_osc_params_dirty = 0; dec_factor = osc_fpga_cnv_time_range_to_dec(curr_params[TIME_RANGE_PARAM].value); time_vect_update = 1; uint32_t fe_fsg1 = (curr_params[GAIN_CH1].value == 0) ? rp_calib_params->fe_ch1_fs_g_hi : rp_calib_params->fe_ch1_fs_g_lo; ch1_max_adc_v = osc_fpga_calc_adc_max_v(fe_fsg1, (int)curr_params[PRB_ATT_CH1].value); uint32_t fe_fsg2 = (curr_params[GAIN_CH2].value == 0) ? rp_calib_params->fe_ch2_fs_g_hi : rp_calib_params->fe_ch2_fs_g_lo; ch2_max_adc_v = osc_fpga_calc_adc_max_v(fe_fsg2, (int)curr_params[PRB_ATT_CH2].value); } pthread_mutex_unlock(&rp_osc_ctrl_mutex); /* request to stop worker thread, we will shut down */ if(state == rp_osc_quit_state) { rp_clean_params(curr_params); return 0; } if(state == rp_osc_auto_set_state) { /* Auto-set algorithm was selected - run it */ rp_osc_auto_set(curr_params, ch1_max_adc_v, ch2_max_adc_v, curr_params[GEN_DC_OFFS_1].value, curr_params[GEN_DC_OFFS_2].value, curr_params[PRB_ATT_CH1].value, curr_params[PRB_ATT_CH2].value, curr_params[GAIN_CH1].value, curr_params[GAIN_CH2].value, curr_params[EN_AVG_AT_DEC].value); /* Return calculated parameters to main module */ rp_update_main_params(curr_params); /* while(1) - loop until break */ continue; } if(fpga_update) { /* Reset write state machine? LG */ osc_fpga_reset(); if(osc_fpga_update_params((curr_params[TRIG_MODE_PARAM].value == 0), curr_params[TRIG_SRC_PARAM].value, curr_params[TRIG_EDGE_PARAM].value, /* Here we could use trigger, but it is safer * to use start GUI value (it was recalculated * correctly already in rp_osc_main() so we * can use it and be sure that all signal * (even if extended because of decimation * will be covered in the acquisition */ /*curr_params[TRIG_DLY_PARAM].value,*/ curr_params[MIN_GUI_PARAM].value, curr_params[TRIG_LEVEL_PARAM].value, curr_params[TIME_RANGE_PARAM].value, max_adc_norm, max_adc_norm, rp_calib_params->fe_ch1_dc_offs, curr_params[GEN_DC_OFFS_1].value, rp_calib_params->fe_ch2_dc_offs, curr_params[GEN_DC_OFFS_2].value, curr_params[PRB_ATT_CH1].value, curr_params[PRB_ATT_CH2].value, curr_params[GAIN_CH1].value, curr_params[GAIN_CH2].value, curr_params[EN_AVG_AT_DEC].value) < 0) { fprintf(stderr, "Setting of FPGA registers failed\n"); rp_osc_worker_change_state(rp_osc_idle_state); } trig_source = osc_fpga_cnv_trig_source( (curr_params[TRIG_MODE_PARAM].value == 0), curr_params[TRIG_SRC_PARAM].value, curr_params[TRIG_EDGE_PARAM].value); fpga_update = 0; } if(state == rp_osc_idle_state) { usleep(10000); continue; } /* Time vector update? */ if(time_vect_update) { float unit_factor = rp_osc_get_time_unit_factor(curr_params[TIME_UNIT_PARAM].value); float t_acq = (curr_params[MAX_GUI_PARAM].value - curr_params[MIN_GUI_PARAM].value) / unit_factor; rp_osc_prepare_time_vector((float **)&rp_tmp_signals[0], dec_factor, curr_params[MIN_GUI_PARAM].value, curr_params[MAX_GUI_PARAM].value, curr_params[TIME_UNIT_PARAM].value); time_vect_update = 0; /* check if we have long acquisition - if yes the algorithm * (wait for pre-defined time and return partial signal) */ /* TODO: Make it programmable */ if(t_acq >= 1.5) { long_acq = 1; /* Catch initial trigger - we will poll trigger pointer, * when it changes we will act like official 'trigger' * came */ rp_osc_meas_clear(&ch1_meas); rp_osc_meas_clear(&ch2_meas); osc_fpga_get_wr_ptr(NULL, &long_acq_init_trig_ptr); } else { long_acq_first_wr_ptr = 0; long_acq_last_wr_ptr = 0; long_acq = 0; } long_acq_idx = 0; } /* Start new acquisition only if it is the index 0 (new acquisition) */ if(long_acq_idx == 0) { float time_delay = curr_params[TRIG_DLY_PARAM].value; /* Start the writting machine */ osc_fpga_arm_trigger(); /* Be sure to have enough time to load necessary history - wait */ if(time_delay < 0) { /* time delay is always in seconds - convert to [us] and * sleep */ usleep(round(-1 * time_delay * 1e6)); } else { if(curr_params[TIME_RANGE_PARAM].value > 4) usleep(5000); else usleep(1); } /* Start the trigger */ osc_fpga_set_trigger(trig_source); } /* start working */ pthread_mutex_lock(&rp_osc_ctrl_mutex); old_state = state = rp_osc_ctrl; pthread_mutex_unlock(&rp_osc_ctrl_mutex); if((state == rp_osc_idle_state) || (state == rp_osc_abort_state)) { continue; } else if(state == rp_osc_quit_state) { break; } if(long_acq_idx == 0) { /* polling until data is ready */ while(1) { pthread_mutex_lock(&rp_osc_ctrl_mutex); state = rp_osc_ctrl; params_dirty = rp_osc_params_dirty; pthread_mutex_unlock(&rp_osc_ctrl_mutex); /* change in state, abort polling */ if((state != old_state) || params_dirty) { break; } if(!long_acq && osc_fpga_triggered()) { /* for non-long acquisition wait for trigger */ break; } else if(long_acq) { int trig_ptr, curr_ptr; osc_fpga_get_wr_ptr(&curr_ptr, &trig_ptr); if((long_acq_init_trig_ptr != trig_ptr) || osc_fpga_triggered()) { /* FPGA wrote new trigger pointer - which means * new trigger happened */ break; } } usleep(1000); } } if((state != old_state) || params_dirty) { params_dirty = 0; continue; } if(long_acq) { /* Long acquisition - after trigger wait for a while to collect some * data */ /* TODO: Make it programmable - Sleep for 200 [ms] */ const int long_acq_part_delay = 1000 * 200; if(long_acq_idx == 0) { /* Trigger - so let's arrange all the needed pointers & stuff */ int wr_ptr_curr, wr_ptr_trig; float smpl_period = c_osc_fpga_smpl_period * dec_factor; int t_start_idx = round(curr_params[MIN_GUI_PARAM].value / smpl_period); float unit_factor = rp_osc_get_time_unit_factor( curr_params[TIME_UNIT_PARAM].value); float t_acq = (curr_params[MAX_GUI_PARAM].value - curr_params[MIN_GUI_PARAM].value) / unit_factor; osc_fpga_get_wr_ptr(&wr_ptr_curr, &wr_ptr_trig); long_acq_first_wr_ptr = wr_ptr_trig + t_start_idx - 3; if(long_acq_first_wr_ptr < 0) long_acq_first_wr_ptr = OSC_FPGA_SIG_LEN + long_acq_first_wr_ptr; long_acq_last_wr_ptr = long_acq_first_wr_ptr + (t_acq / (c_osc_fpga_smpl_period * dec_factor)); long_acq_last_wr_ptr = long_acq_last_wr_ptr % OSC_FPGA_SIG_LEN; if(round((t_acq / (c_osc_fpga_smpl_period * dec_factor) / (((int)rp_get_params_bode(5))-1))) < 0) long_acq_step = 1; else long_acq_step = round((t_acq / (c_osc_fpga_smpl_period * dec_factor)) / (((int)rp_get_params_bode(5))-1)); rp_osc_meas_clear(&ch1_meas); rp_osc_meas_clear(&ch2_meas); } /* we are after trigger - so let's wait a while to collect some * samples */ usleep(long_acq_part_delay); /* Sleep for 200 [ms] */ } pthread_mutex_lock(&rp_osc_ctrl_mutex); state = rp_osc_ctrl; params_dirty = rp_osc_params_dirty; pthread_mutex_unlock(&rp_osc_ctrl_mutex); if((state != old_state) || params_dirty) continue; if(!long_acq) { /* Triggered, decimate & convert the values */ rp_osc_meas_clear(&ch1_meas); rp_osc_meas_clear(&ch2_meas); bode_start_measure((float **)&rp_tmp_signals[1], &rp_fpga_cha_signal[0], (float **)&rp_tmp_signals[2], &rp_fpga_chb_signal[0], (float **)&rp_tmp_signals[0]); } else { long_acq_idx = rp_osc_decimate_partial((float **)&rp_tmp_signals[1], &rp_fpga_cha_signal[0], (float **)&rp_tmp_signals[2], &rp_fpga_chb_signal[0], (float **)&rp_tmp_signals[0], &long_acq_first_wr_ptr, long_acq_last_wr_ptr, long_acq_step, long_acq_idx, curr_params[MIN_GUI_PARAM].value, dec_factor, curr_params[TIME_UNIT_PARAM].value, &ch1_meas, &ch2_meas, ch1_max_adc_v, ch2_max_adc_v, curr_params[GEN_DC_OFFS_1].value, curr_params[GEN_DC_OFFS_2].value); /* Acquisition over, start one more! */ if(long_acq_idx >= ((int)rp_get_params_bode(5))-1) { long_acq_idx = 0; osc_fpga_get_wr_ptr(NULL, &long_acq_init_trig_ptr); if(state == rp_osc_single_state) { rp_osc_worker_change_state(rp_osc_idle_state); } } } /* check again for change of state */ pthread_mutex_lock(&rp_osc_ctrl_mutex); state = rp_osc_ctrl; pthread_mutex_unlock(&rp_osc_ctrl_mutex); /* We have acquisition - if we are in single put state machine * to idle */ if((state == rp_osc_single_state) && (!long_acq)) { rp_osc_worker_change_state(rp_osc_idle_state); } /* copy the results to the user buffer - if we are finished or not */ if(!long_acq || long_acq_idx == 0) { /* Finish the measurement */ rp_osc_meas_avg_amp(&ch1_meas, OSC_FPGA_SIG_LEN); rp_osc_meas_avg_amp(&ch2_meas, OSC_FPGA_SIG_LEN); rp_osc_meas_period(&ch1_meas, &ch2_meas, &rp_fpga_cha_signal[0], &rp_fpga_chb_signal[0], dec_factor); rp_osc_meas_convert(&ch1_meas, ch1_max_adc_v, rp_calib_params->fe_ch1_dc_offs); rp_osc_meas_convert(&ch2_meas, ch2_max_adc_v, rp_calib_params->fe_ch2_dc_offs); rp_osc_set_meas_data(ch1_meas, ch2_meas); rp_osc_set_signals(rp_tmp_signals, ((int)rp_get_params_bode(5))-1); } else { rp_osc_set_signals(rp_tmp_signals, long_acq_idx); } /* do not loop too fast */ usleep(10000); } rp_clean_params(curr_params); return 0; }
int rp_set_params(rp_app_params_t *p, int len) { int i; int fpga_update = 1; int params_change = 0; int awg_params_change = 0; int pid_params_change = 0; TRACE("%s()\n", __FUNCTION__); if(len > PARAMS_NUM) { fprintf(stderr, "Too many parameters, max=%d\n", PARAMS_NUM); return -1; } pthread_mutex_lock(&rp_main_params_mutex); for(i = 0; i < len || p[i].name != NULL; i++) { int p_idx = -1; int j = 0; /* Search for correct parameter name in defined parameters */ while(rp_main_params[j].name != NULL) { int p_strlen = strlen(p[i].name); if(p_strlen != strlen(rp_main_params[j].name)) { j++; continue; } if(!strncmp(p[i].name, rp_main_params[j].name, p_strlen)) { p_idx = j; break; } j++; } if(p_idx == -1) { fprintf(stderr, "Parameter %s not found, ignoring it\n", p[i].name); continue; } if(rp_main_params[p_idx].read_only) continue; if(rp_main_params[p_idx].value != p[i].value) { if(p_idx < PARAMS_AWG_PARAMS) params_change = 1; if ( (p_idx >= PARAMS_AWG_PARAMS) && (p_idx < PARAMS_PID_PARAMS) ) awg_params_change = 1; if(p_idx >= PARAMS_PID_PARAMS) pid_params_change = 1; if(rp_main_params[p_idx].fpga_update) fpga_update = 1; } if(rp_main_params[p_idx].min_val > p[i].value) { fprintf(stderr, "Incorrect parameters value: %f (min:%f), " " correcting it\n", p[i].value, rp_main_params[p_idx].min_val); p[i].value = rp_main_params[p_idx].min_val; } else if(rp_main_params[p_idx].max_val < p[i].value) { fprintf(stderr, "Incorrect parameters value: %f (max:%f), " " correcting it\n", p[i].value, rp_main_params[p_idx].max_val); p[i].value = rp_main_params[p_idx].max_val; } rp_main_params[p_idx].value = p[i].value; } transform_from_iface_units(&rp_main_params[0]); pthread_mutex_unlock(&rp_main_params_mutex); /* Set parameters in HW/FPGA only if they have changed */ if(params_change || (params_init == 0)) { pthread_mutex_lock(&rp_main_params_mutex); /* Xmin & Xmax public copy to be served to clients */ rp_main_params[GUI_XMIN].value = p[MIN_GUI_PARAM].value; rp_main_params[GUI_XMAX].value = p[MAX_GUI_PARAM].value; transform_acq_params(rp_main_params); pthread_mutex_unlock(&rp_main_params_mutex); /* First do health check and then send it to the worker! */ int mode = rp_main_params[TRIG_MODE_PARAM].value; int time_range = rp_main_params[TIME_RANGE_PARAM].value; int time_unit = 2; /* Get info from FPGA module about clocks/decimation, ...*/ int dec_factor = osc_fpga_cnv_time_range_to_dec(time_range); float smpl_period = c_osc_fpga_smpl_period * dec_factor; /* t_delay - trigger delay in seconds */ float t_delay = rp_main_params[TRIG_DLY_PARAM].value; float t_unit_factor = 1; /* to convert to seconds */ /* Our time window with current settings: * - time_delay is added later, when we check if it is correct * setting */ float t_min = 0; float t_max = ((OSC_FPGA_SIG_LEN-1) * smpl_period); float t_max_minus = ((OSC_FPGA_SIG_LEN-6) * smpl_period); params_init = 1; /* in time units time_unit, needs to be converted */ float t_start = rp_main_params[MIN_GUI_PARAM].value; float t_stop = rp_main_params[MAX_GUI_PARAM].value; int t_start_idx; int t_stop_idx; int t_step_idx = 0; /* If auto-set algorithm was requested do not set other parameters */ if(rp_main_params[AUTO_FLAG_PARAM].value == 1) { auto_in_progress = 1; forcex_state = 0; rp_osc_clean_signals(); rp_osc_worker_change_state(rp_osc_auto_set_state); /* AUTO_FLAG_PARAM is cleared when Auto-set algorithm finishes */ /* Wait for auto-set algorithm to finish or timeout */ int timeout = 10000000; // [us] const int step = 50000; // [us] rp_osc_worker_state_t state; while (timeout > 0) { rp_osc_worker_get_state(&state); if (state != rp_osc_auto_set_state) { break; } usleep(step); timeout -= step; } if (timeout <= 0) { fprintf(stderr, "AUTO: Timeout waiting for AUTO-set algorithm to finish.\n"); } auto_in_progress = 0; return 0; } /* If AUTO trigger mode, reset trigger delay */ if(mode == 0) t_delay = 0; if(dec_factor < 0) { fprintf(stderr, "Incorrect time range: %d\n", time_range); return -1; } /* Pick time unit and unit factor corresponding to current time range. */ if((time_range == 0) || (time_range == 1)) { time_unit = 0; t_unit_factor = 1e6; } else if((time_range == 2) || (time_range == 3)) { time_unit = 1; t_unit_factor = 1e3; } rp_main_params[TIME_UNIT_PARAM].value = time_unit; TRACE("PC: time_(R,U) = (%d, %d)\n", time_range, time_unit); /* Check if trigger delay in correct range, otherwise correct it * Correct trigger delay is: * t_delay >= -t_max_minus * t_delay <= OSC_FPGA_MAX_TRIG_DELAY */ if(t_delay < -t_max_minus) { t_delay = -t_max_minus; } else if(t_delay > (OSC_FPGA_TRIG_DLY_MASK * smpl_period)) { t_delay = OSC_FPGA_TRIG_DLY_MASK * smpl_period; } else { t_delay = round(t_delay / smpl_period) * smpl_period; } t_min = t_min + t_delay; t_max = t_max + t_delay; rp_main_params[TRIG_DLY_PARAM].value = t_delay; /* Convert to seconds */ t_start = t_start / t_unit_factor; t_stop = t_stop / t_unit_factor; TRACE("PC: t_stop = %.9f\n", t_stop); /* Select correct time window with this settings: * time window is defined from: * ([ 0 - 16k ] * smpl_period) + trig_delay */ /* round to correct/possible values - convert to nearest index * and back */ t_start_idx = round(t_start / smpl_period); t_stop_idx = round(t_stop / smpl_period); t_start = (t_start_idx * smpl_period); t_stop = (t_stop_idx * smpl_period); if(t_start < t_min) t_start = t_min; if(t_stop > t_max) t_stop = t_max; if(t_stop <= t_start ) t_stop = t_max; /* Correct the window according to possible decimations - always * provide at least the data demanded by the user (ceil() instead * of round()) */ t_start_idx = round(t_start / smpl_period); t_stop_idx = round(t_stop / smpl_period); if((((t_stop_idx-t_start_idx)/(float)(((int)rp_get_params_bode(5))-1))) >= 1) { t_step_idx = ceil((t_stop_idx-t_start_idx)/(float)(((int)rp_get_params_bode(5))-1)); int max_step = OSC_FPGA_SIG_LEN/((int)rp_get_params_bode(5)); if(t_step_idx > max_step) t_step_idx = max_step; t_stop = t_start + ((int)rp_get_params_bode(5)) * t_step_idx * smpl_period; } TRACE("PC: t_stop (rounded) = %.9f\n", t_stop); /* write back and convert to set units */ rp_main_params[MIN_GUI_PARAM].value = t_start; rp_main_params[MAX_GUI_PARAM].value = t_stop; rp_osc_worker_update_params((rp_app_params_t *)&rp_main_params[0], fpga_update); /* check if we need to change state */ switch(mode) { case 0: /* auto */ rp_osc_worker_change_state(rp_osc_auto_state); break; case 1: /* normal */ rp_osc_worker_change_state(rp_osc_normal_state); break; case 2: /* single - clear last ok buffer */ rp_osc_worker_change_state(rp_osc_idle_state); rp_osc_clean_signals(); break; default: return -1; } if(rp_main_params[SINGLE_BUT_PARAM].value == 1) { rp_main_params[SINGLE_BUT_PARAM].value = 0; rp_osc_clean_signals(); rp_osc_worker_change_state(rp_osc_single_state); } } if(awg_params_change) { /* Correct frequencies if needed */ rp_main_params[GEN_SIG_FREQ_CH1].value = rp_gen_limit_freq(rp_main_params[GEN_SIG_FREQ_CH1].value, rp_main_params[GEN_SIG_TYPE_CH1].value); rp_main_params[GEN_SIG_FREQ_CH2].value = rp_gen_limit_freq(rp_main_params[GEN_SIG_FREQ_CH2].value, rp_main_params[GEN_SIG_TYPE_CH2].value); if(generate_update(&rp_main_params[0]) < 0) { return -1; } } if (pid_params_change) { if(pid_update(&rp_main_params[0]) < 0) { return -1; } } return 0; }