static void calibrate (gpointer button)
{
	GtkProgressBar *calib_progress;
	double rx_phase_lpc, rx_phase_hpc, tx_phase_hpc;
	long long cal_tone, cal_freq;
	int ret, samples;

	if (!cf_ad9361_lpc || !cf_ad9361_hpc) {
		printf("could not find capture cores\n");
		ret = -ENODEV;
		auto_calibrate = -1;
		goto calibrate_fail;
	}

	if (!dev_dds_master || !dev_dds_slave) {
		printf("could not find dds cores\n");
		ret = -ENODEV;
		auto_calibrate = -1;
		goto calibrate_fail;
	}

	calib_progress = GTK_PROGRESS_BAR(gtk_builder_get_object(builder, "progress_calibration"));
	set_calibration_progress(calib_progress, 0.00);

	mcs_cb(NULL, NULL);

	/*
	 * set some logical defaults / assumptions
	 */

	ret = default_dds(get_cal_tone(), CAL_SCALE);
	if (ret < 0) {
		printf("could not set dds cores\n");
		auto_calibrate = -1;
		goto calibrate_fail;
	}

	iio_channel_attr_read_longlong(dds_out[0][0], "frequency", &cal_tone);
	iio_channel_attr_read_longlong(dds_out[0][0], "sampling_frequency", &cal_freq);

	samples = get_cal_samples(cal_tone, cal_freq);

	DBG("cal_tone %u cal_freq %u samples %d", cal_tone, cal_freq, samples);

	gdk_threads_enter();
	osc_plot_set_sample_count(plot_xcorr_4ch, samples);
	osc_plot_draw_start(plot_xcorr_4ch);
	gdk_threads_leave();


	iio_device_attr_write(dev, "in_voltage_quadrature_tracking_en", "0");
	iio_device_attr_write(dev_slave, "in_voltage_quadrature_tracking_en", "0");

	trx_phase_rotation(cf_ad9361_lpc, 0.0);
	trx_phase_rotation(cf_ad9361_hpc, 0.0);
	set_calibration_progress(calib_progress, 0.16);

	/*
	 * Calibrate RX:
	 * 1 TX1B_B (HPC) -> RX1C_B (HPC) : BIST_LOOPBACK on A
	 */
	osc_plot_xcorr_revert(plot_xcorr_4ch, true);
	__cal_switch_ports_enable_cb(1);
	rx_phase_hpc = tune_trx_phase_offset(cf_ad9361_hpc, &ret, cal_freq, cal_tone, 1.0, 0.01, trx_phase_rotation);
	if (ret < 0) {
		printf("Failed to tune phase\n");
		auto_calibrate = -1;
		goto calibrate_fail;
	}
	set_calibration_progress(calib_progress, 0.40);
	DBG("rx_phase_hpc %f", rx_phase_hpc);

	/*
	 * Calibrate RX:
	 * 3 TX1B_B (HPC) -> RX1C_A (LPC) : BIST_LOOPBACK on B
	 */

	osc_plot_xcorr_revert(plot_xcorr_4ch, false);
	trx_phase_rotation(cf_ad9361_hpc, 0.0);
	__cal_switch_ports_enable_cb(3);
	rx_phase_lpc = tune_trx_phase_offset(cf_ad9361_lpc, &ret, cal_freq, cal_tone, 1.0, 0.01, trx_phase_rotation);
	if (ret < 0) {
		printf("Failed to tune phase\n");
		auto_calibrate = -1;
		goto calibrate_fail;
	}
	set_calibration_progress(calib_progress, 0.64);
	DBG("rx_phase_lpc %f", rx_phase_lpc);

	/*
	 * Calibrate TX:
	 * 4 TX1B_A (LPC) -> RX1C_A (LPC) : BIST_LOOPBACK on B
	 */

	osc_plot_xcorr_revert(plot_xcorr_4ch, false);
	trx_phase_rotation(cf_ad9361_hpc, 0.0);
	__cal_switch_ports_enable_cb(4);
	tx_phase_hpc = tune_trx_phase_offset(dev_dds_slave, &ret, cal_freq, cal_tone, -1.0 , 0.001, trx_phase_rotation);
	if (ret < 0) {
		printf("Failed to tune phase\n");
		auto_calibrate = -1;
		goto calibrate_fail;
	}
	set_calibration_progress(calib_progress, 0.88);
	DBG("tx_phase_hpc %f", tx_phase_hpc);

	trx_phase_rotation(cf_ad9361_hpc, rx_phase_hpc);

	gtk_range_set_value(GTK_RANGE(GTK_WIDGET(gtk_builder_get_object(builder,
			"tx_phase"))), scale_phase_0_360(tx_phase_hpc));

	ret = 0;
	set_calibration_progress(calib_progress, 1.0);

calibrate_fail:

	osc_plot_xcorr_revert(plot_xcorr_4ch, false);
	__cal_switch_ports_enable_cb(0);

	iio_device_attr_write(dev, "in_voltage_quadrature_tracking_en", "1");
	iio_device_attr_write(dev_slave, "in_voltage_quadrature_tracking_en", "1");

	gdk_threads_enter();
	reload_settings();

	create_blocking_popup(GTK_MESSAGE_INFO, GTK_BUTTONS_CLOSE,
			"FMCOMMS5", "Calibration finished %s",
			ret ? "with Error" : "Successfully");
	auto_calibrate = 1;

	osc_plot_destroy(plot_xcorr_4ch);
	if (button)
		gtk_widget_show(GTK_WIDGET(button));
	gdk_threads_leave();

	g_thread_exit(NULL);
}
static void calibrate (gpointer button)
{
	GtkProgressBar *calib_progress = NULL;
	double rx_phase_lpc, rx_phase_hpc, tx_phase_hpc;
	struct iio_channel *in0, *in0_slave;
	long long cal_tone, cal_freq;
	int ret, samples;

	in0 = iio_device_find_channel(dev, "voltage0", false);
	in0_slave = iio_device_find_channel(dev_slave, "voltage0", false);
	if (!in0 || !in0_slave) {
		printf("could not find channels\n");
		ret = -ENODEV;
		goto calibrate_fail;
	}

	if (!cf_ad9361_lpc || !cf_ad9361_hpc) {
		printf("could not find capture cores\n");
		ret = -ENODEV;
		goto calibrate_fail;
	}

	if (!dev_dds_master || !dev_dds_slave) {
		printf("could not find dds cores\n");
		ret = -ENODEV;
		goto calibrate_fail;
	}

	calib_progress = GTK_PROGRESS_BAR(gtk_builder_get_object(builder, "progress_calibration"));
	set_calibration_progress(calib_progress, 0.00);

	mcs_cb(NULL, NULL);

	/*
	 * set some logical defaults / assumptions
	 */

	ret = default_dds(get_cal_tone(), CAL_SCALE);
	if (ret < 0) {
		printf("could not set dds cores\n");
		goto calibrate_fail;
	}

	iio_channel_attr_read_longlong(dds_out[0][0], "frequency", &cal_tone);
	iio_channel_attr_read_longlong(dds_out[0][0], "sampling_frequency", &cal_freq);

	samples = get_cal_samples(cal_tone, cal_freq);

	DBG("cal_tone %lld cal_freq %lld samples %d", cal_tone, cal_freq, samples);

	gdk_threads_enter();
	osc_plot_set_sample_count(plot_xcorr_4ch, samples);
	osc_plot_draw_start(plot_xcorr_4ch);
	gdk_threads_leave();

	/* Turn off quadrature tracking while the sync is going on */
	iio_channel_attr_write(in0, "quadrature_tracking_en", "0");
	iio_channel_attr_write(in0_slave, "quadrature_tracking_en", "0");

	/* reset any Tx rotation to zero */
	trx_phase_rotation(cf_ad9361_lpc, 0.0);
	trx_phase_rotation(cf_ad9361_hpc, 0.0);
	set_calibration_progress(calib_progress, 0.16);

	/*
	 * Calibrate RX:
	 * 1 TX1B_B (HPC) -> RX1C_B (HPC) : BIST_LOOPBACK on A
	 */
	osc_plot_xcorr_revert(plot_xcorr_4ch, true);
	__cal_switch_ports_enable_cb(1);
	rx_phase_hpc = tune_trx_phase_offset(cf_ad9361_hpc, &ret, cal_freq, cal_tone, 1.0, 0.01, trx_phase_rotation);
	if (ret < 0) {
		printf("Failed to tune phase : %s:%i\n", __func__, __LINE__);
		goto calibrate_fail;
	}
	set_calibration_progress(calib_progress, 0.40);
	DBG("rx_phase_hpc %f", rx_phase_hpc);

	/*
	 * Calibrate RX:
	 * 3 TX1B_B (HPC) -> RX1C_A (LPC) : BIST_LOOPBACK on B
	 */

	osc_plot_xcorr_revert(plot_xcorr_4ch, false);
	trx_phase_rotation(cf_ad9361_hpc, 0.0);
	__cal_switch_ports_enable_cb(3);
	rx_phase_lpc = tune_trx_phase_offset(cf_ad9361_lpc, &ret, cal_freq, cal_tone, 1.0, 0.01, trx_phase_rotation);
	if (ret < 0) {
		printf("Failed to tune phase : %s:%i\n", __func__, __LINE__);
		goto calibrate_fail;
	}
	set_calibration_progress(calib_progress, 0.64);

	(void) rx_phase_lpc; /* Avoid compiler warnings */
	DBG("rx_phase_lpc %f", rx_phase_lpc);

	/*
	 * Calibrate TX:
	 * 4 TX1B_A (LPC) -> RX1C_A (LPC) : BIST_LOOPBACK on B
	 */

	osc_plot_xcorr_revert(plot_xcorr_4ch, false);
	trx_phase_rotation(cf_ad9361_hpc, 0.0);
	__cal_switch_ports_enable_cb(4);
	tx_phase_hpc = tune_trx_phase_offset(dev_dds_slave, &ret, cal_freq, cal_tone, -1.0 , 0.001, trx_phase_rotation);
	if (ret < 0) {
		printf("Failed to tune phase : %s:%i\n", __func__, __LINE__);
		goto calibrate_fail;
	}
	set_calibration_progress(calib_progress, 0.88);
	DBG("tx_phase_hpc %f", tx_phase_hpc);

	trx_phase_rotation(cf_ad9361_hpc, rx_phase_hpc);

	gtk_range_set_value(GTK_RANGE(GTK_WIDGET(gtk_builder_get_object(builder,
			"tx_phase"))), scale_phase_0_360(tx_phase_hpc));

	ret = 0;
	set_calibration_progress(calib_progress, 1.0);

calibrate_fail:

	osc_plot_xcorr_revert(plot_xcorr_4ch, false);
	__cal_switch_ports_enable_cb(0);

	if (in0 && in0_slave) {
		iio_channel_attr_write(in0, "quadrature_tracking_en", "1");
		iio_channel_attr_write(in0_slave, "quadrature_tracking_en", "1");
	}

	gdk_threads_enter();
	reload_settings();

	if (ret) {
		create_blocking_popup(GTK_MESSAGE_INFO, GTK_BUTTONS_CLOSE,
			"FMCOMMS5", "Calibration failed");
		auto_calibrate = -1;
	} else {
		/* set completed flag for testing */
		auto_calibrate = 1;
	}

	osc_plot_destroy(plot_xcorr_4ch);
	if (button)
		gtk_widget_show(GTK_WIDGET(button));
	gdk_threads_leave();

	/* reset progress bar */
	gtk_progress_bar_set_fraction(calib_progress, 0.0);
	gtk_progress_bar_set_text(calib_progress, "Calibration Progress");

	/* Disable the channels that were enabled at the beginning of the calibration */
	struct iio_device *iio_dev;
	iio_dev = iio_context_find_device(get_context_from_osc(), CAP_DEVICE_ALT);
	if (iio_dev && cap_device_channels_enabled) {
		iio_channels_change_shadow_of_enabled(iio_dev, false);
		cap_device_channels_enabled = false;
	}

	g_thread_exit(NULL);
}