コード例 #1
0
ファイル: worker.c プロジェクト: PitayaDT/RedPitaya
/*----------------------------------------------------------------------------------*/
int rp_osc_auto_set(rp_app_params_t *orig_params, 
                    float ch1_max_adc_v, float ch2_max_adc_v,
                    float ch1_user_dc_off, float ch2_user_dc_off,
                    int ch1_probe_att, int ch2_probe_att, int ch1_gain, int ch2_gain, int en_avg_at_dec)
{
    const int c_noise_thr = 500; /* noise threshold */
    rp_osc_worker_state_t old_state, state;
    int params_dirty;
    /* Min/maxes from both channel */
    int max_cha = INT_MIN;
    int max_chb = INT_MIN;
    int min_cha = INT_MAX;
    int min_chb = INT_MAX;
    /* Y axis deltas, 0 - ChA, 1 - Chb */
    int dy[2]     = { 0, 0 };
    int old_dy[2] = { 0, 0 };

    /* Channel to be used for auto-algorithm:
     * 0 - Channel A 
     * 1 - Channel B 
     */
    int channel; 
    int smpl_cnt;
    int iter;
    int time_range = 0;

    for (iter=0; iter < 10; iter++) {
        /* 10 auto-trigger acquisitions */
        pthread_mutex_lock(&rp_osc_ctrl_mutex);
        old_state = state = rp_osc_ctrl;
        pthread_mutex_unlock(&rp_osc_ctrl_mutex);

        osc_fpga_reset();
        osc_fpga_update_params(1, 0, 0, 0, 0, time_range, ch1_max_adc_v, ch2_max_adc_v,
                   rp_calib_params->fe_ch1_dc_offs,
                   0,
                   rp_calib_params->fe_ch2_dc_offs,
                   0,
                   ch1_probe_att, ch2_probe_att, ch1_gain, ch2_gain, 0);

        /* ARM & Trigger */
        osc_fpga_arm_trigger();
        osc_fpga_set_trigger(1);

        /* Wait for trigger to finish */
        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) {
                return -1;
            }
            if(osc_fpga_triggered()) {
                break;
            }
            usleep(500);
        }

        /* Get the signals - available at rp_fpga_chX_signal vectors */
        for(smpl_cnt = 0; smpl_cnt < OSC_FPGA_SIG_LEN; smpl_cnt++) {
            int cha_smpl = rp_fpga_cha_signal[smpl_cnt];
            int chb_smpl = rp_fpga_chb_signal[smpl_cnt];

            // TWO'S COMPLEMENT
            if(cha_smpl & (1<<(c_osc_fpga_adc_bits-1)))
                cha_smpl = -1 * ((cha_smpl ^ ((1<<c_osc_fpga_adc_bits)-1))+1);
            if(chb_smpl & (1<<(c_osc_fpga_adc_bits-1)))
                chb_smpl = -1 * ((chb_smpl ^ ((1<<c_osc_fpga_adc_bits)-1))+1);

            cha_smpl = cha_smpl + rp_calib_params->fe_ch1_dc_offs;
            chb_smpl = chb_smpl + rp_calib_params->fe_ch2_dc_offs;

            /* Get min/maxes */
            max_cha = (max_cha < cha_smpl) ? cha_smpl : max_cha;
            min_cha = (min_cha > cha_smpl) ? cha_smpl : min_cha;
            max_chb = (max_chb < chb_smpl) ? chb_smpl : max_chb;
            min_chb = (min_chb > chb_smpl) ? chb_smpl : min_chb;
        }

        dy[0] = max_cha - min_cha;
        dy[1] = max_chb - min_chb;

        /* Calculate ratios of last amplitude increase for both channels */
        const float c_inc_thr = 1.1;
        float ratio[2] = { 1e6, 1e6 };
        int i;
        for(i = 0; i < 2; i++) {
            if (old_dy[i] != 0) {
                ratio[i] = (float)dy[i] / (float)old_dy[i];
            }
        }
        old_dy[0] = dy[0];
        old_dy[1] = dy[1];

        /* Signal amplitude found & stable? */
        if ( ((ratio[0] < c_inc_thr) && (dy[0] > c_noise_thr)) ||
             ((ratio[1] < c_inc_thr) && (dy[1] > c_noise_thr)) ) {
            /* This is meant for optimizing the time it takes for AUTO to complete,
             * and is a compromise between the speed and robustness of the AUTO
             * algorithm.
             * Since it is fast enough, it is safer to search for amplitude through
             * all the iterations instead of bailing out sooner.
             */
            //break;
        }

        /* Still searching? - Increase time range up to 130 ms (D = 1024). */
        if ((iter % 3) == 2) {
            time_range++;
            if (time_range > 3) {
                time_range = 3;
            }
        }
    }

    /* Check the Y axis amplitude on both channels and select the channel with 
     * the larger one.
     */
    channel = (dy[0] > dy[1]) ? 0 : 1;

    if(dy[channel] < c_noise_thr) {
        /* No signal detected, set the parameters to:
         * - no decimation (time range 130 [us])
         * - trigger mode - auto
         * - X axis - full, from 0 to 130 [us]
         * - Y axis - Min/Max + adding extra 200% to average
         */
        TRACE("AUTO: No signal detected.\n");
        int min_y, max_y, ave_y;

        orig_params[TRIG_MODE_PARAM].value  = 0;
        orig_params[MIN_GUI_PARAM].value    = 0;      
        orig_params[MAX_GUI_PARAM].value    = 130;
        orig_params[TIME_RANGE_PARAM].value = 0;
        orig_params[TRIG_SRC_PARAM].value   = 0;
        orig_params[TRIG_LEVEL_PARAM].value = 0;
        orig_params[AUTO_FLAG_PARAM].value  = 0;
        orig_params[TIME_UNIT_PARAM].value  = 0;
        orig_params[TRIG_DLY_PARAM].value   = 0;

        min_y = (min_cha < min_chb) ? min_cha : min_chb;
        max_y = (max_cha > max_chb) ? max_cha : max_chb;

        ave_y = (min_y + max_y) >> 1;
        min_y = (min_y - ave_y) * 2 + ave_y;
        max_y = (max_y - ave_y) * 2 + ave_y;

        orig_params[MIN_Y_NORM].value = min_y / (float)(1 << (c_osc_fpga_adc_bits - 1));
        orig_params[MAX_Y_NORM].value = max_y / (float)(1 << (c_osc_fpga_adc_bits - 1));

        // For POST response ...
        transform_to_iface_units(orig_params);
        return 0;

    } else {
コード例 #2
0
ファイル: worker.c プロジェクト: alexrault/RedPitaya
/** @brief Main worker thread function.
 *
 * This is main worker thread function which implements continuous loop. This
 * loop is controlled with the state variable. This function should not be called
 * directly but with POSIX thread functions.
 * 
 * @param [in] args Optinal arguments as defined by pthread API functions.
 *
*/
void *rp_osc_worker_thread(void *args)
{
    rp_osc_worker_state_t old_state, state;
    rp_osc_params_t       curr_params[PARAMS_NUM];
    int                   fpga_update = 0;
    int                   dec_factor = 0;
    int                   time_vect_update = 0;
    uint32_t              trig_source = 0;
    int                   params_dirty = 0;

    rp_osc_meas_res_t ch1_meas, ch2_meas;
    float ch1_max_adc_v = 1, ch2_max_adc_v = 1;
    if (wrkr_rp_calib_params != NULL) {
        ch1_max_adc_v = osc_fpga_calc_adc_max_v(wrkr_rp_calib_params->fe_ch1_fs_g_hi, 0);
        ch2_max_adc_v = osc_fpga_calc_adc_max_v(wrkr_rp_calib_params->fe_ch2_fs_g_hi, 0);
    }

    pthread_mutex_lock(&rp_osc_ctrl_mutex);
    old_state = state = rp_osc_ctrl;
    pthread_mutex_unlock(&rp_osc_ctrl_mutex);

    /* Continuous thread loop (exited only with 'quit' state) */
    while(1) {
        /* update states - we save also old state to see if we need to reset
         * FPGA 
         */
        old_state = state;
        pthread_mutex_lock(&rp_osc_ctrl_mutex);
        state = rp_osc_ctrl;
        if(rp_osc_params_dirty) {
            memcpy(&curr_params, &rp_osc_params, 
                   sizeof(rp_osc_params_t)*PARAMS_NUM);
            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;
        }
        pthread_mutex_unlock(&rp_osc_ctrl_mutex);

        /* request to stop worker thread, we will shut down */

        if(state == rp_osc_quit_state) {
            return 0;
        }

        if(fpga_update) {
            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 becuase 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,
                                      curr_params[EQUAL_FILT_PARAM].value,
                                      curr_params[SHAPE_FILT_PARAM].value,
                                      curr_params[GAIN1_PARAM].value,
                                      curr_params[GAIN2_PARAM].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;
        }

        if(time_vect_update) {            

            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;

         
	    
	   
        }

       
        
        /* Start new acquisition only if it is the index 0 (new acquisition) */
      
            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 {
                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;
        }

       
            /* 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(osc_fpga_triggered()) {
                    
                    break;
                } 
                usleep(1000);
            }
        

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

        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;

	
	
		
        
            /* Triggered, decimate & convert the values */
            if (wrkr_rp_calib_params != NULL) {
            rp_osc_meas_clear(&ch1_meas);
            rp_osc_meas_clear(&ch2_meas);
            //printf("ch1_max_adc_v=%f\n", ch1_max_adc_v);
            //printf("curr_params[GEN_DC_OFFS_1].value=%f\n", curr_params[GEN_DC_OFFS_1].value);
            rp_osc_decimate_with_calib((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], dec_factor, 
                            curr_params[MIN_GUI_PARAM].value,
                            curr_params[MAX_GUI_PARAM].value,
                            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);
            } else {
            rp_osc_decimate((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], dec_factor, 
                            curr_params[MIN_GUI_PARAM].value,
                            curr_params[MAX_GUI_PARAM].value,
                            curr_params[TIME_UNIT_PARAM].value);
            }

        /* 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) ) {

            rp_osc_worker_change_state(rp_osc_idle_state);
        }

      
            rp_osc_set_signals(rp_tmp_signals, SIGNAL_LENGTH-1);
        
        /* do not loop too fast */
        usleep(10000);
    }

    return 0;
}
コード例 #3
0
ファイル: worker.c プロジェクト: PitayaDT/RedPitaya
/* 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;
}