#include "ad9361_config.h"

struct ad9361_rf_phy *ad9361_phy;
struct ad9361_reg_dev *ad9361_reg_inst;

extern XGpioPs gpio;
struct spi_engine_init_param spi_engine_param = {
	.ref_clk_hz = SPI_ENGINE_REF_CLK,
	.type = SPI_ENGINE,
	.spi_engine_baseaddr = SPI_ENGINE_BASEADDR,
	.cs_delay = SPI_ENGINE_CS_DELAY,
	.data_width = SPI_ENGINE_DATA_WIDTH};

struct xil_gpio_init_param xil_gpio_param = {
	.type = GPIO_PS,
	.device_id = GPIO_DEVICE_ID};


// AD9361 configuration initialization
int ad9361_init()
{
	int status;
//	LOG_INFO("Configuration AD9361...");
#ifdef AD9361_NO_OS_CONFIG
	ad9361_init_param_config.mgc_rx1_ctrl_inp_enable = 0;
	status = ad9361_config(&ad9361_phy, &ad9361_init_param_config);
//	CEHCK_STATUS_ELSE(status, "Config AD9361 Done", "Config AD9361 Failed");
	usleep(20000);
	ad9361_set_rx_sampling_freq(ad9361_phy, 50000000);
	status |= ad9361_set_tx_fir_config(ad9361_phy, tx_fir_config2);
	status |= ad9361_set_rx_fir_config(ad9361_phy, rx_fir_config2);
	status |= ad9361_set_rx_fir_en_dis(ad9361_phy, 1);
	status |= ad9361_set_tx_fir_en_dis(ad9361_phy, 1);
	status |= ad9361_set_rx_gain_control_mode(ad9361_phy, 0, RF_GAIN_MGC);
	status |= ad9361_set_rx_rf_gain(ad9361_phy, 0, 0);			   // dB
	status |= ad9361_set_tx_attenuation(ad9361_phy, 0, 20 * 1000); // mdB

	CEHCK_STATUS_ELSE(status, "Init AD9361 Done", "Init AD9361 False");
	
	XGpioPs_SetDirectionPin(&gpio, AD9361_ENABLE, GPIO_OUTPUT);
	XGpioPs_WritePin(&gpio, AD9361_ENABLE, 1);

	int32_t gain = 0;
	uint32_t bandwidth_hz = 0;
	uint32_t sampling_rate = 0;
	uint32_t attenuation_mdb=0;
	uint64_t rx_lo_freq_hz=0;
	uint64_t tx_lo_freq_hz=0;
	ad9361_get_rx_rf_gain(ad9361_phy, 0, &gain);	// dB
	ad9361_get_tx_attenuation(ad9361_phy, 0, &attenuation_mdb);
	ad9361_get_rx_rf_bandwidth(ad9361_phy, &bandwidth_hz);
	ad9361_get_rx_sampling_freq(ad9361_phy, &sampling_rate);
	ad9361_get_rx_lo_freq(ad9361_phy, &rx_lo_freq_hz);
	ad9361_get_tx_lo_freq(ad9361_phy, &tx_lo_freq_hz);
	xil_printf(INFO_MSG("Tx atten\t%d mdB \tRx gain \t%d dB"),attenuation_mdb, gain);
	xil_printf(INFO_MSG("Tx lo freq\t%d Hz\tRx lo freq\t%d Hz"),(uint32_t)tx_lo_freq_hz,(uint32_t)rx_lo_freq_hz);
	xil_printf(INFO_MSG("Bandwidth \t%d Hz\tFsample \t%dHz"),bandwidth_hz,sampling_rate);


#endif
#ifdef AD9361_REG_CONFIG
	XGpioPs_SetDirectionPin(&gpio, AD9361_TXNRX, GPIO_OUTPUT);
	XGpioPs_SetDirectionPin(&gpio, AD9361_ENABLE, GPIO_OUTPUT);
	XGpioPs_SetDirectionPin(&gpio, AD9361_EN_AGC, GPIO_OUTPUT);
	XGpioPs_SetDirectionPin(&gpio, AD9361_RESET_B, GPIO_OUTPUT);
	ad9361_reg_init(&ad9361_reg_inst, &ad9361_reg_default_init_param);
	XGpioPs_WritePin(&gpio, AD9361_ENABLE, 0);
	status = ad9361_reg_config(ad9361_reg_inst); // config ad9361 with register table
	if (status != XST_SUCCESS)
	{
		return XST_FAILURE;
	}
	else
	{
		printf("Configurate AD9361 Completely!\n");
	}
	XGpioPs_WritePin(&gpio, AD9361_ENABLE, 1);
	// XGpioPs_WritePin(&Gpio, AD9361_TXNRX, 1);
#endif
	return XST_SUCCESS;
}

// debug
void Ad9361SetTxFreq(u64 freq_hz)
{
	ad9361_set_tx_lo_freq(ad9361_phy, freq_hz);
}

// Set the TX or RX center frequency. Unit : Hz
void ad9361_set_tx_freq(u64 freq_hz)
{
	ad9361_set_tx_lo_freq(ad9361_phy, freq_hz);
}
void ad9361_set_rx_freq(u64 freq_hz)
{
	ad9361_set_rx_lo_freq(ad9361_phy, freq_hz);
}

// Set the TX(two channels) attenuation. Unit : mdB
void ad9361_set_tx1_attenuation(int attenuation_mdb)
{
	ad9361_set_tx_attenuation(ad9361_phy, 0, attenuation_mdb);

	// debug
	u32 txAttn;
	ad9361_get_tx_attenuation(ad9361_phy, 0, &txAttn);
	xil_printf("Tx attenuation is %d", txAttn);
	// debug end
}
void ad9361_set_tx2_attenuation(int attenuation_mdb)
{
	ad9361_set_tx_attenuation(ad9361_phy, 1, attenuation_mdb);
}

// Set the Rx(two channels) gain. Unit : dB
void ad9361_set_rx1_gain(int gain_db)
{
	ad9361_set_rx_rf_gain(ad9361_phy, 0, gain_db);
}
void ad9361_set_rx2_gain(int gain_db)
{
	ad9361_set_rx_rf_gain(ad9361_phy, 1, gain_db);
}

// Set the TX & RX RF bandwidth. Unit : Hz
void ad9361_set_tx_rf_bw(int bandwidth_hz)
{
	ad9361_set_tx_rf_bandwidth(ad9361_phy, bandwidth_hz);
}
void ad9361_set_rx_rf_bw(int bandwidth_hz)
{
	ad9361_set_rx_rf_bandwidth(ad9361_phy, bandwidth_hz);
}

// Set the TX & RX sample frequency. Unit : Hz
void ad9361_set_tx_samp_freq(int freq_hz)
{
	ad9361_set_tx_sampling_freq(ad9361_phy, freq_hz);
}
void ad9361_set_rx_samp_freq(int freq_hz)
{
	ad9361_set_rx_sampling_freq(ad9361_phy, freq_hz);
}

// Set RX(two channels) gain control mode
/*
 *	RF_GAIN_MGC (manual)
 *	RF_GAIN_FASTATTACK_AGC (fast_attack)
 *	RF_GAIN_SLOWATTACK_AGC (slow_attack)
 *	RF_GAIN_HYBRID_AGC (hybrid)
 *
 */
void ad9361_set_rx1_agc_mode(int gc_mode)
{
	ad9361_set_rx_gain_control_mode(ad9361_phy, 0, gc_mode);
}
void ad9361_set_rx2_agc_mode(int gc_mode)
{
	ad9361_set_rx_gain_control_mode(ad9361_phy, 1, gc_mode);
}

// Energy management
void ad9361_power_on()
{
	XGpioPs_WritePin(&gpio, AD9361_ENABLE, 1);
}
void ad9361_power_down()
{
	XGpioPs_WritePin(&gpio, AD9361_ENABLE, 0);
}

// DEBUG
void ad9361_get_rx1_gain(int *gain_db)
{
	ad9361_get_rx_rf_gain(ad9361_phy, 0, gain_db);
}
// DEBUG END
