diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/.gitignore b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/.gitignore new file mode 100644 index 0000000..3ce08f3 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/.gitignore @@ -0,0 +1,35 @@ +# keep compiled libs +!*.a + +# Buid folder +build/ + +# Xilinx tools generated files +.metadata/ +.settings/ +.wsdata/ +.Xil/ +logs/ +Packages/ +*.log* + +# System generated files +# -- macOS +.DS_Store +.AppleDouble +.LSOverride +._* + +# -- Windows +Thumbs.db +ehthumbs.db +Desktop.ini + +# -- Linux +*~ + +# IDEs and editors' files +*.idea +*.vscode +*.sublime-workspace +*.sublime-project diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/Makefile b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/Makefile new file mode 100644 index 0000000..e7b8a91 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/Makefile @@ -0,0 +1,8 @@ +include ../../scripts/generic_variables.mk + +PLATFORM := xilinx +CONFIG_FILE := $(PROJECT)/config.json +XILINX_VITIS_CLASSIC = y +SCRIPT_DIR = ../../scripts + +include ../../scripts/generic.mk \ No newline at end of file diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/config.json b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/config.json new file mode 100644 index 0000000..487b93c --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/config.json @@ -0,0 +1,84 @@ +{ + "project_name": "cx9261a_demo_cmos_20240513", + "version": "20240513", + "hw_design": "../CX9261A_ZC706.xsa", + "hw_version": "20241031", + "apps": { + "cx9261a_api_app": { + "sources": ["source_cx9261a_api_1_9_0/"], + "target_cpu": "ps7_cortexa9_0", + "os": "standalone", + "language": "C++", + "mem_layout" : { + "heap_size": "0x80000", + "stack_size": "0x4000" + } + }, + "cx9261a_api_lib_app": { + "sources": ["source_cx9261a_api_lib_c/"], + "target_cpu": "ps7_cortexa9_0", + "os": "standalone", + "language": "C", + "mem_layout" : { + "heap_size": "0x80000", + "stack_size": "0x4000" + }, + "build_config": { + "debug": { + "include-path": ["source_cx9261a_api_lib_c/include"], + "libraries": ["cx9261a_c_dbg", "stdc++", "m"], + "library-search-path": ["source_cx9261a_api_lib_c/drivers/rf-transceiver/cx9261a/lib"] + }, + "release": { + "include-path": ["source_cx9261a_api_lib_c/include"], + "libraries": ["cx9261a_c", "stdc++", "m"], + "library-search-path": ["source_cx9261a_api_lib_c/drivers/rf-transceiver/cx9261a/lib"] + } + } + }, + "CX9261A_DEMO": { + "sources": ["source_CX9261A_DEMO/"], + "target_cpu": "ps7_cortexa9_0", + "os": "freertos10_xilinx", + "language": "C", + "mem_layout" : { + "heap_size": "0x80000", + "stack_size": "0x4000" + }, + "bsp_lib": { + "lwip220": { + "version": "1.0", + "config": { + "api_mode": "SOCKET_API", + "pbuf_pool_size": 2048 + } + }, + "xilffs": { + "version": "5.2" + } + } + }, + "CX9261A_HOP": { + "sources": ["source_CX9261A_HOP/"], + "target_cpu": "ps7_cortexa9_0", + "os": "freertos10_xilinx", + "language": "C", + "mem_layout" : { + "heap_size": "0x80000", + "stack_size": "0x4000" + }, + "bsp_lib": { + "lwip220": { + "version": "1.0", + "config": { + "api_mode": "SOCKET_API", + "pbuf_pool_size": 2048 + } + }, + "xilffs": { + "version": "5.2" + } + } + } + } +} diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_DEMO/cx9261a_076_config.c b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_DEMO/cx9261a_076_config.c new file mode 100644 index 0000000..64c1e10 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_DEMO/cx9261a_076_config.c @@ -0,0 +1,342 @@ +/* + * cx9261a_076_config.c + * + * Created on: 2023Äê11ÔÂ30ÈÕ + * Author: cxlab + */ + + +#include "xilinx_io.h" +#include "sleep.h" +void cx9261a_076_config(void){ +u8 rx_data; +int temp; + +//setPin(pin,value) +GpioSetPinDir(0,0x01); +GpioWritePin(0,1); +GpioSetPinDir(32,0x01); +GpioWritePin(32,1); +GpioSetPinDir(33,0x01); +GpioWritePin(33,1); +GpioSetPinDir(34,0x01); +GpioWritePin(34,0); +GpioSetPinDir(35,0x01); //tx:0-rx:1 +GpioWritePin(35,1); //tx:0-rx:1 +GpioSetPinDir(36,0x01); //fdd:0-tdd:1 +GpioWritePin(36,1); //fdd:0-tdd:1 +GpioSetPinDir(37,0x01); //1r1t:0-2r2t:1 +GpioWritePin(37,0); //1r1t:0-2r2t:1 +GpioSetPinDir(38,0x01); //dualport:0-singleport:1 +GpioWritePin(38,1); //dualport:0-singleport:1 +GpioSetPinDir(39,0x01); +GpioWritePin(39,1); +GpioSetPinDir(40,0x01); +GpioWritePin(40,1); +//Èý¸öͨµÀ¹²ͬ¿ØÖÆ +SpiPs_write_read1(0x000,0x02,&rx_data); +//µçԴ¹ÜÀí×Զ¨Òå +//¶ϵçģʽ +SpiPs_write_read1(0x031,0x00,&rx_data); +SpiPs_write_read1(0x032,0x7F,&rx_data); +SpiPs_write_read1(0x033,0xFF,&rx_data); +SpiPs_write_read1(0x034,0xFF,&rx_data); +//ÐÝÃßģʽ +SpiPs_write_read1(0x035,0x00,&rx_data); +SpiPs_write_read1(0x036,0x3D,&rx_data); +SpiPs_write_read1(0x037,0xFF,&rx_data); +SpiPs_write_read1(0x038,0xEB,&rx_data); +//¾¯½äģʽ +SpiPs_write_read1(0x039,0x00,&rx_data); +SpiPs_write_read1(0x03A,0x3D,&rx_data); +SpiPs_write_read1(0x03B,0xFF,&rx_data); +SpiPs_write_read1(0x03C,0xE0,&rx_data); +//У׼ģʽ +SpiPs_write_read1(0x03D,0x1B,&rx_data); +SpiPs_write_read1(0x03E,0x39,&rx_data); +SpiPs_write_read1(0x03F,0x27,&rx_data); +SpiPs_write_read1(0x040,0xE0,&rx_data); +//½ÓÊÕģʽ +SpiPs_write_read1(0x041,0x03,&rx_data); +SpiPs_write_read1(0x042,0x3D,&rx_data); +SpiPs_write_read1(0x043,0xE7,&rx_data); +SpiPs_write_read1(0x044,0xF8,&rx_data); +//·¢Éäģʽ +SpiPs_write_read1(0x045,0x1B,&rx_data); +SpiPs_write_read1(0x046,0x3D,&rx_data); +SpiPs_write_read1(0x047,0x26,&rx_data); +SpiPs_write_read1(0x048,0x7E,&rx_data); +//FDDģʽ +SpiPs_write_read1(0x049,0x1B,&rx_data); +SpiPs_write_read1(0x04A,0x3D,&rx_data); +SpiPs_write_read1(0x04B,0x27,&rx_data); +SpiPs_write_read1(0x04C,0xE0,&rx_data); +//¹۲âģʽ +SpiPs_write_read1(0x04D,0x04,&rx_data); +SpiPs_write_read1(0x04E,0x3D,&rx_data); +SpiPs_write_read1(0x04F,0xD9,&rx_data); +SpiPs_write_read1(0x050,0xFE,&rx_data); +//´ø϶»ù׼ +SpiPs_write_read1(0x773,0x53,&rx_data); +SpiPs_write_read1(0x774,0x86,&rx_data); +//²ο¼ʱÖÓÉèÖà +SpiPs_write_read1(0x789,0x00,&rx_data); +SpiPs_write_read1(0x785,0x49,&rx_data); +SpiPs_write_read1(0x788,0x24,&rx_data); +usleep(10000); +SpiPs_write_read1(0x788,0xA4,&rx_data); +//BBPLL +SpiPs_write_read1(0x0C0,0x50,&rx_data); +SpiPs_write_read1(0x0C1,0x50,&rx_data); +SpiPs_write_read1(0x0C2,0x50,&rx_data); +SpiPs_write_read1(0x601,0x0F,&rx_data); +SpiPs_write_read1(0x602,0x21,&rx_data); +SpiPs_write_read1(0x60D,0x0C,&rx_data); +SpiPs_write_read1(0x60E,0x66,&rx_data); +SpiPs_write_read1(0x60F,0x66,&rx_data); +SpiPs_write_read1(0x610,0x66,&rx_data); +SpiPs_write_read1(0x611,0x13,&rx_data); +SpiPs_write_read1(0x612,0x00,&rx_data); +//ADC +SpiPs_write_read1(0x70B,0x0E,&rx_data); +SpiPs_write_read1(0x727,0x0E,&rx_data); +SpiPs_write_read1(0x743,0x0E,&rx_data); +SpiPs_write_read1(0x70D,0x3F,&rx_data); +SpiPs_write_read1(0x729,0x3F,&rx_data); +SpiPs_write_read1(0x745,0x3F,&rx_data); +SpiPs_write_read1(0x70E,0x48,&rx_data); +SpiPs_write_read1(0x72A,0x48,&rx_data); +SpiPs_write_read1(0x746,0x48,&rx_data); +SpiPs_write_read1(0x70F,0xA0,&rx_data); +SpiPs_write_read1(0x72B,0xA0,&rx_data); +SpiPs_write_read1(0x747,0xA0,&rx_data); +//ͨµÀʱÖÓÀ´Դ +SpiPs_write_read1(0x77D,0xC0,&rx_data); +SpiPs_write_read1(0x775,0x24,&rx_data); +SpiPs_write_read1(0x6C3,0x00,&rx_data); +//PLL1 +SpiPs_write_read1(0x620,0x81,&rx_data); +SpiPs_write_read1(0x61D,0x00,&rx_data); +SpiPs_write_read1(0xB06,0x00,&rx_data); +SpiPs_write_read1(0xB07,0x64,&rx_data); +SpiPs_write_read1(0xB08,0x00,&rx_data); +SpiPs_write_read1(0xB09,0x00,&rx_data); +SpiPs_write_read1(0xB0A,0x00,&rx_data); +SpiPs_write_read1(0x61A,0x0B,&rx_data); +SpiPs_write_read1(0x61B,0x20,&rx_data); +SpiPs_write_read1(0x61C,0x13,&rx_data); +SpiPs_write_read1(0x624,0x11,&rx_data); +SpiPs_write_read1(0x625,0x11,&rx_data); +SpiPs_write_read1(0x62A,0x00,&rx_data); +SpiPs_write_read1(0x61E,0x30,&rx_data); +SpiPs_write_read1(0x61F,0x08,&rx_data); +SpiPs_write_read1(0x621,0x4D,&rx_data); +SpiPs_write_read1(0x622,0x19,&rx_data); +SpiPs_write_read1(0x627,0x10,&rx_data); +//RxͨµÀÉèÖà +SpiPs_write_read1(0x700,0x56,&rx_data); +SpiPs_write_read1(0x71C,0x56,&rx_data); +SpiPs_write_read1(0x738,0x56,&rx_data); +SpiPs_write_read1(0x701,0x02,&rx_data); +SpiPs_write_read1(0x702,0x35,&rx_data); +SpiPs_write_read1(0x71D,0x02,&rx_data); +SpiPs_write_read1(0x71E,0x35,&rx_data); +SpiPs_write_read1(0x739,0x02,&rx_data); +SpiPs_write_read1(0x73A,0x35,&rx_data); +SpiPs_write_read1(0x703,0xF6,&rx_data); +SpiPs_write_read1(0x71F,0xF6,&rx_data); +SpiPs_write_read1(0x73B,0xF6,&rx_data); +SpiPs_write_read1(0x704,0xC8,&rx_data); +SpiPs_write_read1(0x720,0xC8,&rx_data); +SpiPs_write_read1(0x73C,0xC8,&rx_data); +SpiPs_write_read1(0x907,0x1F,&rx_data); +SpiPs_write_read1(0x705,0xFC,&rx_data); +SpiPs_write_read1(0x721,0xFC,&rx_data); +SpiPs_write_read1(0x73D,0xFC,&rx_data); +SpiPs_write_read1(0x706,0x65,&rx_data); +SpiPs_write_read1(0x722,0x65,&rx_data); +SpiPs_write_read1(0x73E,0x65,&rx_data); +SpiPs_write_read1(0x707,0x91,&rx_data); +SpiPs_write_read1(0x723,0x91,&rx_data); +SpiPs_write_read1(0x73F,0x91,&rx_data); +SpiPs_write_read1(0x708,0x04,&rx_data); +SpiPs_write_read1(0x724,0x04,&rx_data); +SpiPs_write_read1(0x740,0x04,&rx_data); +SpiPs_write_read1(0x709,0x94,&rx_data); +SpiPs_write_read1(0x725,0x94,&rx_data); +SpiPs_write_read1(0x741,0x94,&rx_data); +SpiPs_write_read1(0x70A,0xFC,&rx_data); +SpiPs_write_read1(0x726,0xFC,&rx_data); +SpiPs_write_read1(0x742,0xFC,&rx_data); +SpiPs_write_read1(0x75A,0x83,&rx_data); +SpiPs_write_read1(0x75B,0xDA,&rx_data); +usleep(10000); +SpiPs_write_read1(0x75B,0x9A,&rx_data); +SpiPs_write_read1(0x75C,0x81,&rx_data); +SpiPs_write_read1(0x75D,0xF8,&rx_data); +SpiPs_write_read1(0x75E,0xA7,&rx_data); +SpiPs_write_read1(0x75F,0x51,&rx_data); +SpiPs_write_read1(0x760,0xFF,&rx_data); +SpiPs_write_read1(0x761,0x04,&rx_data); +SpiPs_write_read1(0x762,0x70,&rx_data); +SpiPs_write_read1(0x763,0x04,&rx_data); +SpiPs_write_read1(0x764,0x83,&rx_data); +SpiPs_write_read1(0x765,0xDA,&rx_data); +usleep(100000); +SpiPs_write_read1(0x765,0x9A,&rx_data); +SpiPs_write_read1(0x766,0x81,&rx_data); +SpiPs_write_read1(0x767,0xF8,&rx_data); +SpiPs_write_read1(0x768,0xA7,&rx_data); +SpiPs_write_read1(0x769,0x51,&rx_data); +SpiPs_write_read1(0x76A,0xFF,&rx_data); +SpiPs_write_read1(0x76B,0x04,&rx_data); +SpiPs_write_read1(0x76C,0x70,&rx_data); +SpiPs_write_read1(0x76D,0x04,&rx_data); +//RxÂ˲¨Æ÷ +SpiPs_write_read1(0x106,0x02,&rx_data); +//TxÂ˲¨Æ÷ +SpiPs_write_read1(0x107,0x00,&rx_data); +SpiPs_write_read1(0x108,0xD0,&rx_data); +//Rx NCO +SpiPs_write_read1(0x11C,0x00,&rx_data); +SpiPs_write_read1(0xA07,0x00,&rx_data); +SpiPs_write_read1(0xA08,0x00,&rx_data); +SpiPs_write_read1(0xA16,0x00,&rx_data); +SpiPs_write_read1(0xA17,0x00,&rx_data); +SpiPs_write_read1(0xA18,0x00,&rx_data); +SpiPs_write_read1(0xA19,0x00,&rx_data); +SpiPs_write_read1(0xA1A,0x00,&rx_data); +SpiPs_write_read1(0xA1B,0x00,&rx_data); +//Tx NCO +SpiPs_write_read1(0x128,0x10,&rx_data); +SpiPs_write_read1(0x11B,0x00,&rx_data); +SpiPs_write_read1(0x11E,0x00,&rx_data); +SpiPs_write_read1(0x161,0x00,&rx_data); +SpiPs_write_read1(0x162,0x00,&rx_data); +SpiPs_write_read1(0x164,0x00,&rx_data); +SpiPs_write_read1(0x165,0x00,&rx_data); +SpiPs_write_read1(0x166,0x00,&rx_data); +SpiPs_write_read1(0x167,0x00,&rx_data); +SpiPs_write_read1(0x168,0x00,&rx_data); +SpiPs_write_read1(0x169,0x00,&rx_data); +//AGCÅäÖà +SpiPs_write_read1(0x900,0x00,&rx_data); +SpiPs_write_read1(0x901,0x00,&rx_data); +SpiPs_write_read1(0x903,0x11,&rx_data); +SpiPs_write_read1(0x908,0x77,&rx_data); +SpiPs_write_read1(0x909,0x03,&rx_data); +SpiPs_write_read1(0x90A,0x32,&rx_data); +SpiPs_write_read1(0x90D,0x00,&rx_data); +SpiPs_write_read1(0x90E,0x0F,&rx_data); +SpiPs_write_read1(0x90F,0x65,&rx_data); +SpiPs_write_read1(0x910,0x32,&rx_data); +SpiPs_write_read1(0x911,0x00,&rx_data); +SpiPs_write_read1(0x912,0x0F,&rx_data); +SpiPs_write_read1(0x913,0x3A,&rx_data); +SpiPs_write_read1(0x914,0x37,&rx_data); +SpiPs_write_read1(0x915,0x34,&rx_data); +SpiPs_write_read1(0x916,0x31,&rx_data); +//½øÈëÐÝÃßģʽ +SpiPs_write_read1(0x02E,0x01,&rx_data); +usleep(1000000); +//½øÈëУ׼ģʽ +SpiPs_write_read1(0x02E,0x03,&rx_data); +//BBPLL AFC +SpiPs_write_read1(0x600,0x00,&rx_data); +usleep(100000); +SpiPs_write_read1(0x600,0x11,&rx_data); +//PLL1 AFC +SpiPs_write_read1(0x617,0x00,&rx_data); +usleep(100000); +SpiPs_write_read1(0x617,0x03,&rx_data); +//½ӿÚÅäÖà +SpiPs_write_read1(0x02E,0x06,&rx_data); +SpiPs_write_read1(0x003,0x33,&rx_data); +SpiPs_write_read1(0x200,0x00,&rx_data); +SpiPs_write_read1(0x201,0x00,&rx_data); +SpiPs_write_read1(0x202,0x03,&rx_data); +SpiPs_write_read1(0x209,0x00,&rx_data); +SpiPs_write_read1(0x780,0x11,&rx_data); +SpiPs_write_read1(0x781,0x6F,&rx_data); +SpiPs_write_read1(0x782,0x01,&rx_data); +SpiPs_write_read1(0x783,0x01,&rx_data); +SpiPs_write_read1(0x784,0x01,&rx_data); +//ADCУ׼ +SpiPs_write_read1(0x70B,0x1E,&rx_data); +SpiPs_write_read1(0x727,0x1E,&rx_data); +SpiPs_write_read1(0x743,0x1E,&rx_data); +SpiPs_write_read1(0x70F,0xA0,&rx_data); +SpiPs_write_read1(0x710,0x83,&rx_data); +SpiPs_write_read1(0x711,0xF0,&rx_data); +SpiPs_write_read1(0x72B,0xA0,&rx_data); +SpiPs_write_read1(0x72C,0x83,&rx_data); +SpiPs_write_read1(0x72D,0xF0,&rx_data); +SpiPs_write_read1(0x747,0xA0,&rx_data); +SpiPs_write_read1(0x748,0x83,&rx_data); +SpiPs_write_read1(0x749,0xF0,&rx_data); +SpiPs_write_read1(0x713,0x80,&rx_data); +SpiPs_write_read1(0x72F,0x80,&rx_data); +SpiPs_write_read1(0x74B,0x80,&rx_data); +SpiPs_write_read1(0x70B,0x9E,&rx_data); +SpiPs_write_read1(0x727,0x9E,&rx_data); +SpiPs_write_read1(0x743,0x9E,&rx_data); +SpiPs_write_read1(0x70B,0x9A,&rx_data); +SpiPs_write_read1(0x727,0x9A,&rx_data); +SpiPs_write_read1(0x743,0x9A,&rx_data); +SpiPs_write_read1(0x70B,0x9E,&rx_data); +SpiPs_write_read1(0x727,0x9E,&rx_data); +SpiPs_write_read1(0x743,0x9E,&rx_data); +usleep(100000); +SpiPs_write_read1(0x70B,0x1E,&rx_data); +SpiPs_write_read1(0x727,0x1E,&rx_data); +SpiPs_write_read1(0x743,0x1E,&rx_data); +SpiPs_write_read1(0x713,0xC0,&rx_data); +SpiPs_write_read1(0x72F,0xC0,&rx_data); +SpiPs_write_read1(0x74B,0xC0,&rx_data); +//FlashУ׼ +SpiPs_write_read1(0x70B,0x1E,&rx_data); +SpiPs_write_read1(0x727,0x1E,&rx_data); +SpiPs_write_read1(0x743,0x1E,&rx_data); +SpiPs_write_read1(0x715,0x80,&rx_data); +SpiPs_write_read1(0x731,0x80,&rx_data); +SpiPs_write_read1(0x74D,0x80,&rx_data); +SpiPs_write_read1(0x715,0xC0,&rx_data); +SpiPs_write_read1(0x731,0xC0,&rx_data); +SpiPs_write_read1(0x74D,0xC0,&rx_data); +SpiPs_write_read1(0x716,0x40,&rx_data); +SpiPs_write_read1(0x732,0x40,&rx_data); +SpiPs_write_read1(0x74E,0x40,&rx_data); +SpiPs_write_read1(0x70B,0x16,&rx_data); +SpiPs_write_read1(0x727,0x16,&rx_data); +SpiPs_write_read1(0x743,0x16,&rx_data); +usleep(100000); +SpiPs_write_read1(0x70B,0x1E,&rx_data); +SpiPs_write_read1(0x727,0x1E,&rx_data); +SpiPs_write_read1(0x743,0x1E,&rx_data); +SpiPs_write_read1(0x715,0x80,&rx_data); +SpiPs_write_read1(0x731,0x80,&rx_data); +SpiPs_write_read1(0x74D,0x80,&rx_data); +SpiPs_write_read1(0x716,0x00,&rx_data); +SpiPs_write_read1(0x732,0x00,&rx_data); +SpiPs_write_read1(0x74E,0x00,&rx_data); +SpiPs_write_read1(0x109,0x11,&rx_data); +SpiPs_write_read1(0x10A,0x70,&rx_data); +SpiPs_write_read1(0x11F,0x33,&rx_data); +usleep(1000); +SpiPs_write_read2(0x615,0x00,&rx_data); +temp=rx_data; +SpiPs_write_read2(0x635,0x00,&rx_data); +temp=rx_data; +////ÅäÖÃTx NCO BIST ON +//SpiPs_write_read1(0x11B,0x01,&rx_data); +//SpiPs_write_read1(0x11E,0x01,&rx_data); +//SpiPs_write_read1(0x161,0x01,&rx_data); +//SpiPs_write_read1(0x162,0x01,&rx_data); +////ÅäÖÃTx NCOƵÂÊ 1MHz +//SpiPs_write_read1(0x164,0x05,&rx_data); +//SpiPs_write_read1(0x165,0x55,&rx_data); +//SpiPs_write_read1(0x166,0x55,&rx_data); +//SpiPs_write_read1(0x167,0x55,&rx_data); +//SpiPs_write_read1(0x168,0x55,&rx_data); +//SpiPs_write_read1(0x169,0x55,&rx_data); +} diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_DEMO/cx9261a_151_config.c b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_DEMO/cx9261a_151_config.c new file mode 100644 index 0000000..c1e78f7 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_DEMO/cx9261a_151_config.c @@ -0,0 +1,708 @@ +/* + * cx9261_config.c + * + * Created on: 2023Äê10ÔÂ16ÈÕ + * Author: cxlab + */ + +#include "xilinx_io.h" +#include "sleep.h" +void cx9261a_151_config(void){ +u8 rx_data; +int temp; + +//setPin(pin,value) +GpioSetPinDir(0,0x01); +GpioWritePin(0,1); +GpioSetPinDir(32,0x01); +GpioWritePin(32,1); +GpioSetPinDir(33,0x01); +GpioWritePin(33,1); +GpioSetPinDir(34,0x01); +GpioWritePin(34,0); +GpioSetPinDir(35,0x01); //tx:0-rx:1 +GpioWritePin(35,1); //tx:0-rx:1 +GpioSetPinDir(36,0x01); //fdd:0-tdd:1 +GpioWritePin(36,1); //fdd:0-tdd:1 +GpioSetPinDir(37,0x01); //1r1t:0-2r2t:1 +GpioWritePin(37,0); //1r1t:0-2r2t:1 +GpioSetPinDir(38,0x01); //dualport:0-singleport:1 +GpioWritePin(38,1); //dualport:0-singleport:1 +GpioSetPinDir(39,0x01); +GpioWritePin(39,1); +GpioSetPinDir(40,0x01); +GpioWritePin(40,1); +//Èý¸öͨµÀ¹²ͬ¿ØÖÆ +SpiPs_write_read1(0x000,0x02,&rx_data); +//µçԴ¹ÜÀí×Զ¨Òå +//¶ϵçģʽ +SpiPs_write_read1(0x031,0x00,&rx_data); +SpiPs_write_read1(0x032,0x7F,&rx_data); +SpiPs_write_read1(0x033,0xFF,&rx_data); +SpiPs_write_read1(0x034,0xFF,&rx_data); +//ÐÝÃßģʽ +SpiPs_write_read1(0x035,0x00,&rx_data); +SpiPs_write_read1(0x036,0x3D,&rx_data); +SpiPs_write_read1(0x037,0xFF,&rx_data); +SpiPs_write_read1(0x038,0xEB,&rx_data); +//¾¯½äģʽ +SpiPs_write_read1(0x039,0x00,&rx_data); +SpiPs_write_read1(0x03A,0x3D,&rx_data); +SpiPs_write_read1(0x03B,0xFF,&rx_data); +SpiPs_write_read1(0x03C,0xE0,&rx_data); +//У׼ģʽ +SpiPs_write_read1(0x03D,0x1B,&rx_data); +SpiPs_write_read1(0x03E,0x39,&rx_data); +SpiPs_write_read1(0x03F,0x27,&rx_data); +SpiPs_write_read1(0x040,0xE0,&rx_data); +//½ÓÊÕģʽ +SpiPs_write_read1(0x041,0x03,&rx_data); +SpiPs_write_read1(0x042,0x3D,&rx_data); +SpiPs_write_read1(0x043,0xE7,&rx_data); +SpiPs_write_read1(0x044,0xF8,&rx_data); +//·¢Éäģʽ +SpiPs_write_read1(0x045,0x18,&rx_data); +SpiPs_write_read1(0x046,0x3D,&rx_data); +SpiPs_write_read1(0x047,0x3F,&rx_data); +SpiPs_write_read1(0x048,0xF8,&rx_data); +//FDDģʽ +SpiPs_write_read1(0x049,0x1B,&rx_data); +SpiPs_write_read1(0x04A,0x3D,&rx_data); +SpiPs_write_read1(0x04B,0x27,&rx_data); +SpiPs_write_read1(0x04C,0xE0,&rx_data); +//¹۲âģʽ +SpiPs_write_read1(0x04D,0x04,&rx_data); +SpiPs_write_read1(0x04E,0x3D,&rx_data); +SpiPs_write_read1(0x04F,0xD9,&rx_data); +SpiPs_write_read1(0x050,0xFE,&rx_data); +//´ø϶»ù׼ +SpiPs_write_read1(0x773,0x53,&rx_data); +SpiPs_write_read1(0x774,0x86,&rx_data); +//²ο¼ʱÖÓÉèÖà +SpiPs_write_read1(0x789,0x00,&rx_data); +SpiPs_write_read1(0x785,0x49,&rx_data); +SpiPs_write_read1(0x788,0x24,&rx_data); +usleep(10000); +SpiPs_write_read1(0x788,0xA4,&rx_data); +//BBPLL +SpiPs_write_read1(0x0C0,0x50,&rx_data); +SpiPs_write_read1(0x0C1,0x50,&rx_data); +SpiPs_write_read1(0x0C2,0x50,&rx_data); +SpiPs_write_read1(0x601,0x0F,&rx_data); +SpiPs_write_read1(0x602,0x21,&rx_data); +SpiPs_write_read1(0x60D,0x0C,&rx_data); +SpiPs_write_read1(0x60E,0x66,&rx_data); +SpiPs_write_read1(0x60F,0x66,&rx_data); +SpiPs_write_read1(0x610,0x66,&rx_data); +SpiPs_write_read1(0x611,0x13,&rx_data); +SpiPs_write_read1(0x612,0x00,&rx_data); +//ADC +SpiPs_write_read1(0x70B,0x0E,&rx_data); +SpiPs_write_read1(0x727,0x0E,&rx_data); +SpiPs_write_read1(0x743,0x0E,&rx_data); +SpiPs_write_read1(0x70D,0x3F,&rx_data); +SpiPs_write_read1(0x729,0x3F,&rx_data); +SpiPs_write_read1(0x745,0x3F,&rx_data); +SpiPs_write_read1(0x70E,0x48,&rx_data); +SpiPs_write_read1(0x72A,0x48,&rx_data); +SpiPs_write_read1(0x746,0x48,&rx_data); +SpiPs_write_read1(0x70F,0xA0,&rx_data); +SpiPs_write_read1(0x72B,0xA0,&rx_data); +SpiPs_write_read1(0x747,0xA0,&rx_data); +//ͨµÀʱÖÓÀ´Դ +SpiPs_write_read1(0x77D,0xCF,&rx_data); +SpiPs_write_read1(0x775,0x24,&rx_data); +SpiPs_write_read1(0x6C3,0x00,&rx_data); +//PLL1 +SpiPs_write_read1(0x620,0x81,&rx_data); +SpiPs_write_read1(0x61D,0x07,&rx_data); +SpiPs_write_read1(0xB06,0x00,&rx_data); +SpiPs_write_read1(0xB07,0x64,&rx_data); +SpiPs_write_read1(0xB08,0x00,&rx_data); +SpiPs_write_read1(0xB09,0x00,&rx_data); +SpiPs_write_read1(0xB0A,0x00,&rx_data); +SpiPs_write_read1(0x61A,0x0B,&rx_data); +SpiPs_write_read1(0x61B,0x20,&rx_data); +SpiPs_write_read1(0x61C,0x13,&rx_data); +SpiPs_write_read1(0x624,0x11,&rx_data); +SpiPs_write_read1(0x625,0x11,&rx_data); +SpiPs_write_read1(0x62A,0x00,&rx_data); +SpiPs_write_read1(0x61E,0x30,&rx_data); +SpiPs_write_read1(0x61F,0x08,&rx_data); +SpiPs_write_read1(0x621,0x4D,&rx_data); +SpiPs_write_read1(0x622,0x19,&rx_data); +SpiPs_write_read1(0x627,0x10,&rx_data); +//PLL2 +SpiPs_write_read1(0x642,0x91,&rx_data); +SpiPs_write_read1(0x63F,0x36,&rx_data); +SpiPs_write_read1(0xB14,0x00,&rx_data); +SpiPs_write_read1(0xB15,0x70,&rx_data); +SpiPs_write_read1(0xB16,0x00,&rx_data); +SpiPs_write_read1(0xB17,0x00,&rx_data); +SpiPs_write_read1(0xB18,0x00,&rx_data); +SpiPs_write_read1(0x63C,0x0C,&rx_data); +SpiPs_write_read1(0x63D,0x20,&rx_data); +SpiPs_write_read1(0x63E,0x0C,&rx_data); +SpiPs_write_read1(0x646,0x11,&rx_data); +SpiPs_write_read1(0x647,0x11,&rx_data); +SpiPs_write_read1(0x64C,0x00,&rx_data); +SpiPs_write_read1(0x640,0x30,&rx_data); +SpiPs_write_read1(0x641,0x08,&rx_data); +SpiPs_write_read1(0x643,0x4D,&rx_data); +SpiPs_write_read1(0x644,0x19,&rx_data); +SpiPs_write_read1(0x649,0x10,&rx_data); +//PLL3 +SpiPs_write_read1(0x664,0x91,&rx_data); +SpiPs_write_read1(0x661,0x36,&rx_data); +SpiPs_write_read1(0xB22,0x00,&rx_data); +SpiPs_write_read1(0xB23,0x80,&rx_data); +SpiPs_write_read1(0xB24,0x00,&rx_data); +SpiPs_write_read1(0xB25,0x00,&rx_data); +SpiPs_write_read1(0xB26,0x00,&rx_data); +SpiPs_write_read1(0x65E,0x0D,&rx_data); +SpiPs_write_read1(0x65F,0x20,&rx_data); +SpiPs_write_read1(0x660,0x0F,&rx_data); +SpiPs_write_read1(0x668,0x11,&rx_data); +SpiPs_write_read1(0x669,0x11,&rx_data); +SpiPs_write_read1(0x66E,0x00,&rx_data); +SpiPs_write_read1(0x662,0x30,&rx_data); +SpiPs_write_read1(0x663,0x08,&rx_data); +SpiPs_write_read1(0x665,0x4D,&rx_data); +SpiPs_write_read1(0x666,0x19,&rx_data); +SpiPs_write_read1(0x66B,0x10,&rx_data); +//PLL4 +SpiPs_write_read1(0x686,0x81,&rx_data); +SpiPs_write_read1(0x683,0x37,&rx_data); +SpiPs_write_read1(0xB30,0x00,&rx_data); +SpiPs_write_read1(0xB31,0x48,&rx_data); +SpiPs_write_read1(0xB32,0x00,&rx_data); +SpiPs_write_read1(0xB33,0x00,&rx_data); +SpiPs_write_read1(0xB34,0x00,&rx_data); +SpiPs_write_read1(0x680,0x0C,&rx_data); +SpiPs_write_read1(0x681,0x20,&rx_data); +SpiPs_write_read1(0x682,0x11,&rx_data); +SpiPs_write_read1(0x68A,0x11,&rx_data); +SpiPs_write_read1(0x68B,0x11,&rx_data); +SpiPs_write_read1(0x690,0x00,&rx_data); +SpiPs_write_read1(0x684,0x30,&rx_data); +SpiPs_write_read1(0x685,0x08,&rx_data); +SpiPs_write_read1(0x687,0x4D,&rx_data); +SpiPs_write_read1(0x688,0x19,&rx_data); +SpiPs_write_read1(0x68D,0x10,&rx_data); +//PLL5 +SpiPs_write_read1(0x6A8,0x81,&rx_data); +SpiPs_write_read1(0x6A5,0x37,&rx_data); +SpiPs_write_read1(0xB3E,0x00,&rx_data); +SpiPs_write_read1(0xB3F,0x50,&rx_data); +SpiPs_write_read1(0xB40,0x00,&rx_data); +SpiPs_write_read1(0xB41,0x00,&rx_data); +SpiPs_write_read1(0xB42,0x00,&rx_data); +SpiPs_write_read1(0x6A2,0x0C,&rx_data); +SpiPs_write_read1(0x6A3,0x20,&rx_data); +SpiPs_write_read1(0x6A4,0x11,&rx_data); +SpiPs_write_read1(0x6AC,0x11,&rx_data); +SpiPs_write_read1(0x6AD,0x11,&rx_data); +SpiPs_write_read1(0x6B2,0x00,&rx_data); +SpiPs_write_read1(0x6A6,0x30,&rx_data); +SpiPs_write_read1(0x6A7,0x08,&rx_data); +SpiPs_write_read1(0x6A9,0x4D,&rx_data); +SpiPs_write_read1(0x6AA,0x19,&rx_data); +SpiPs_write_read1(0x6AF,0x10,&rx_data); +//RxͨµÀÉèÖà +SpiPs_write_read1(0x700,0x56,&rx_data); +SpiPs_write_read1(0x71C,0x56,&rx_data); +SpiPs_write_read1(0x738,0x56,&rx_data); +SpiPs_write_read1(0x701,0x02,&rx_data); +SpiPs_write_read1(0x702,0x35,&rx_data); +SpiPs_write_read1(0x71D,0x02,&rx_data); +SpiPs_write_read1(0x71E,0x35,&rx_data); +SpiPs_write_read1(0x739,0x02,&rx_data); +SpiPs_write_read1(0x73A,0x35,&rx_data); +SpiPs_write_read1(0x703,0xF6,&rx_data); +SpiPs_write_read1(0x71F,0xF6,&rx_data); +SpiPs_write_read1(0x73B,0xF6,&rx_data); +SpiPs_write_read1(0x704,0xC8,&rx_data); +SpiPs_write_read1(0x720,0xC8,&rx_data); +SpiPs_write_read1(0x73C,0xC8,&rx_data); +SpiPs_write_read1(0x907,0x1F,&rx_data); +SpiPs_write_read1(0x705,0xFC,&rx_data); +SpiPs_write_read1(0x721,0xFC,&rx_data); +SpiPs_write_read1(0x73D,0xFC,&rx_data); +SpiPs_write_read1(0x706,0x65,&rx_data); +SpiPs_write_read1(0x722,0x65,&rx_data); +SpiPs_write_read1(0x73E,0x65,&rx_data); +SpiPs_write_read1(0x707,0x91,&rx_data); +SpiPs_write_read1(0x723,0x91,&rx_data); +SpiPs_write_read1(0x73F,0x91,&rx_data); +SpiPs_write_read1(0x708,0x04,&rx_data); +SpiPs_write_read1(0x724,0x04,&rx_data); +SpiPs_write_read1(0x740,0x04,&rx_data); +SpiPs_write_read1(0x709,0x94,&rx_data); +SpiPs_write_read1(0x725,0x94,&rx_data); +SpiPs_write_read1(0x741,0x94,&rx_data); +SpiPs_write_read1(0x70A,0xFC,&rx_data); +SpiPs_write_read1(0x726,0xFC,&rx_data); +SpiPs_write_read1(0x742,0xFC,&rx_data); +SpiPs_write_read1(0x75A,0x83,&rx_data); +SpiPs_write_read1(0x75B,0xDA,&rx_data); +usleep(100000); +SpiPs_write_read1(0x75B,0x9A,&rx_data); +SpiPs_write_read1(0x75C,0x81,&rx_data); +SpiPs_write_read1(0x75D,0xF8,&rx_data); +SpiPs_write_read1(0x75E,0xA7,&rx_data); +SpiPs_write_read1(0x75F,0x50,&rx_data); +SpiPs_write_read1(0x760,0xFF,&rx_data); +SpiPs_write_read1(0x761,0x07,&rx_data); +SpiPs_write_read1(0x762,0x6C,&rx_data); +SpiPs_write_read1(0x763,0x04,&rx_data); +SpiPs_write_read1(0x764,0x83,&rx_data); +SpiPs_write_read1(0x765,0xDA,&rx_data); +usleep(100000); +SpiPs_write_read1(0x765,0x9A,&rx_data); +SpiPs_write_read1(0x766,0x81,&rx_data); +SpiPs_write_read1(0x767,0xF8,&rx_data); +SpiPs_write_read1(0x768,0xA7,&rx_data); +SpiPs_write_read1(0x769,0x50,&rx_data); +SpiPs_write_read1(0x76A,0xFF,&rx_data); +SpiPs_write_read1(0x76B,0x07,&rx_data); +SpiPs_write_read1(0x76C,0x6C,&rx_data); +SpiPs_write_read1(0x76D,0x04,&rx_data); +//RxÂ˲¨Æ÷ +SpiPs_write_read1(0x106,0x02,&rx_data); +//TxÂ˲¨Æ÷ +SpiPs_write_read1(0x107,0x00,&rx_data); +SpiPs_write_read1(0x108,0xD0,&rx_data); +//Rx NCO +SpiPs_write_read1(0x11C,0x00,&rx_data); +SpiPs_write_read1(0xA07,0x00,&rx_data); +SpiPs_write_read1(0xA08,0x00,&rx_data); +SpiPs_write_read1(0xA16,0x00,&rx_data); +SpiPs_write_read1(0xA17,0x00,&rx_data); +SpiPs_write_read1(0xA18,0x00,&rx_data); +SpiPs_write_read1(0xA19,0x00,&rx_data); +SpiPs_write_read1(0xA1A,0x00,&rx_data); +SpiPs_write_read1(0xA1B,0x00,&rx_data); +//Tx NCO +SpiPs_write_read1(0x128,0x10,&rx_data); +SpiPs_write_read1(0x11B,0x01,&rx_data); +SpiPs_write_read1(0x11E,0x01,&rx_data); +SpiPs_write_read1(0x161,0x01,&rx_data); +SpiPs_write_read1(0x162,0x01,&rx_data); +SpiPs_write_read1(0x164,0x05,&rx_data); +SpiPs_write_read1(0x165,0x55,&rx_data); +SpiPs_write_read1(0x166,0x55,&rx_data); +SpiPs_write_read1(0x167,0x55,&rx_data); +SpiPs_write_read1(0x168,0x55,&rx_data); +SpiPs_write_read1(0x169,0x55,&rx_data); +//AGCÅäÖà +SpiPs_write_read1(0x900,0x00,&rx_data); +SpiPs_write_read1(0x901,0x00,&rx_data); +SpiPs_write_read1(0x903,0x11,&rx_data); +SpiPs_write_read1(0x908,0x77,&rx_data); +SpiPs_write_read1(0x909,0x03,&rx_data); +SpiPs_write_read1(0x90A,0x32,&rx_data); +SpiPs_write_read1(0x90D,0x00,&rx_data); +SpiPs_write_read1(0x90E,0x0F,&rx_data); +SpiPs_write_read1(0x90F,0x65,&rx_data); +SpiPs_write_read1(0x910,0x32,&rx_data); +SpiPs_write_read1(0x911,0x00,&rx_data); +SpiPs_write_read1(0x912,0x0F,&rx_data); +SpiPs_write_read1(0x913,0x3A,&rx_data); +SpiPs_write_read1(0x914,0x37,&rx_data); +SpiPs_write_read1(0x915,0x34,&rx_data); +SpiPs_write_read1(0x916,0x31,&rx_data); +//½øÈëÐÝÃßģʽ +SpiPs_write_read1(0x02E,0x01,&rx_data); +usleep(1000000); +//½øÈëУ׼ģʽ +SpiPs_write_read1(0x02E,0x03,&rx_data); +usleep(100000); +//BBPLL AFC +SpiPs_write_read1(0x600,0x00,&rx_data); +SpiPs_write_read1(0x600,0x11,&rx_data); +usleep(50); +//PLL1 AFC +while(temp != 48) +{ +SpiPs_write_read1(0x617,0x00,&rx_data); +SpiPs_write_read1(0x617,0x03,&rx_data); +usleep(100); +SpiPs_write_read2(0x635,0x00,&rx_data); +temp=rx_data; +} +//½ӿÚÅäÖà +SpiPs_write_read1(0x02E,0x06,&rx_data); +SpiPs_write_read1(0x003,0x33,&rx_data); +SpiPs_write_read1(0x200,0x00,&rx_data); +SpiPs_write_read1(0x201,0x00,&rx_data); +SpiPs_write_read1(0x202,0x03,&rx_data); +SpiPs_write_read1(0x208,0x00,&rx_data); +SpiPs_write_read1(0x209,0x00,&rx_data); +SpiPs_write_read1(0x780,0x11,&rx_data); +SpiPs_write_read1(0x781,0x6F,&rx_data); +SpiPs_write_read1(0x782,0x01,&rx_data); +SpiPs_write_read1(0x783,0x01,&rx_data); +SpiPs_write_read1(0x784,0x01,&rx_data); +//ADCУ׼ +SpiPs_write_read1(0x70B,0x1E,&rx_data); +SpiPs_write_read1(0x727,0x1E,&rx_data); +SpiPs_write_read1(0x743,0x1E,&rx_data); +SpiPs_write_read1(0x70F,0xA0,&rx_data); +SpiPs_write_read1(0x710,0x83,&rx_data); +SpiPs_write_read1(0x711,0xF0,&rx_data); +SpiPs_write_read1(0x72B,0xA0,&rx_data); +SpiPs_write_read1(0x72C,0x83,&rx_data); +SpiPs_write_read1(0x72D,0xF0,&rx_data); +SpiPs_write_read1(0x747,0xA0,&rx_data); +SpiPs_write_read1(0x748,0x83,&rx_data); +SpiPs_write_read1(0x749,0xF0,&rx_data); +SpiPs_write_read1(0x713,0x80,&rx_data); +SpiPs_write_read1(0x72F,0x80,&rx_data); +SpiPs_write_read1(0x74B,0x80,&rx_data); +SpiPs_write_read1(0x70B,0x9E,&rx_data); +SpiPs_write_read1(0x727,0x9E,&rx_data); +SpiPs_write_read1(0x743,0x9E,&rx_data); +SpiPs_write_read1(0x70B,0x9A,&rx_data); +SpiPs_write_read1(0x727,0x9A,&rx_data); +SpiPs_write_read1(0x743,0x9A,&rx_data); +SpiPs_write_read1(0x70B,0x9E,&rx_data); +SpiPs_write_read1(0x727,0x9E,&rx_data); +SpiPs_write_read1(0x743,0x9E,&rx_data); +usleep(100000); +SpiPs_write_read1(0x70B,0x1E,&rx_data); +SpiPs_write_read1(0x727,0x1E,&rx_data); +SpiPs_write_read1(0x743,0x1E,&rx_data); +SpiPs_write_read1(0x713,0xC0,&rx_data); +SpiPs_write_read1(0x72F,0xC0,&rx_data); +SpiPs_write_read1(0x74B,0xC0,&rx_data); +//FlashУ׼ +SpiPs_write_read1(0x70B,0x1E,&rx_data); +SpiPs_write_read1(0x727,0x1E,&rx_data); +SpiPs_write_read1(0x743,0x1E,&rx_data); +SpiPs_write_read1(0x715,0x80,&rx_data); +SpiPs_write_read1(0x731,0x80,&rx_data); +SpiPs_write_read1(0x74D,0x80,&rx_data); +SpiPs_write_read1(0x715,0xC0,&rx_data); +SpiPs_write_read1(0x731,0xC0,&rx_data); +SpiPs_write_read1(0x74D,0xC0,&rx_data); +SpiPs_write_read1(0x716,0x40,&rx_data); +SpiPs_write_read1(0x732,0x40,&rx_data); +SpiPs_write_read1(0x74E,0x40,&rx_data); +SpiPs_write_read1(0x70B,0x16,&rx_data); +SpiPs_write_read1(0x727,0x16,&rx_data); +SpiPs_write_read1(0x743,0x16,&rx_data); +usleep(100000); +SpiPs_write_read1(0x70B,0x1E,&rx_data); +SpiPs_write_read1(0x727,0x1E,&rx_data); +SpiPs_write_read1(0x743,0x1E,&rx_data); +SpiPs_write_read1(0x715,0x80,&rx_data); +SpiPs_write_read1(0x731,0x80,&rx_data); +SpiPs_write_read1(0x74D,0x80,&rx_data); +SpiPs_write_read1(0x716,0x00,&rx_data); +SpiPs_write_read1(0x732,0x00,&rx_data); +SpiPs_write_read1(0x74E,0x00,&rx_data); +SpiPs_write_read1(0x109,0x11,&rx_data); +SpiPs_write_read1(0x10A,0x70,&rx_data); +SpiPs_write_read1(0x11F,0x33,&rx_data); +//QECУ׼ +//Rx TST Calibration +SpiPs_write_read1(0x000,0x12,&rx_data); +SpiPs_write_read1(0x109,0x00,&rx_data); +SpiPs_write_read1(0x77E,0x50,&rx_data); +SpiPs_write_read1(0x14E,0x00,&rx_data); +// Ð޸ÄУ׼ģʽµçԴ¹ÜÀí +SpiPs_write_read1(0x03D,0x09,&rx_data); +SpiPs_write_read1(0x03E,0x39,&rx_data); +SpiPs_write_read1(0x03F,0xB6,&rx_data); +SpiPs_write_read1(0x040,0x78,&rx_data); +//Ð޸ĵçԴģʽ +SpiPs_write_read1(0x02E,0x03,&rx_data); +//Calibration PLL Source +// Ð޸ÄPllÀ´Դ +SpiPs_write_read1(0x77D,0x90,&rx_data); +SpiPs_write_read1(0x6C3,0x05,&rx_data); +SpiPs_write_read1(0x775,0x24,&rx_data); +//Ð޸ÄPll4ƵÂÊ +//PLL4 +SpiPs_write_read1(0x686,0x81,&rx_data); +SpiPs_write_read1(0x683,0x07,&rx_data); +SpiPs_write_read1(0xB30,0x00,&rx_data); +SpiPs_write_read1(0xB31,0x63,&rx_data); +SpiPs_write_read1(0xB32,0xEB,&rx_data); +SpiPs_write_read1(0xB33,0x85,&rx_data); +SpiPs_write_read1(0xB34,0x1E,&rx_data); +SpiPs_write_read1(0x680,0x0B,&rx_data); +SpiPs_write_read1(0x681,0x20,&rx_data); +SpiPs_write_read1(0x682,0x13,&rx_data); +SpiPs_write_read1(0x68A,0x11,&rx_data); +SpiPs_write_read1(0x68B,0x11,&rx_data); +SpiPs_write_read1(0x690,0x0B,&rx_data); +SpiPs_write_read1(0x684,0x30,&rx_data); +SpiPs_write_read1(0x685,0x08,&rx_data); +SpiPs_write_read1(0x687,0x4D,&rx_data); +SpiPs_write_read1(0x688,0x19,&rx_data); +SpiPs_write_read1(0x68D,0x10,&rx_data); +//PLL4 AFC +while(temp != 48) +{ +SpiPs_write_read1(0x67D,0x00,&rx_data); +SpiPs_write_read1(0x67D,0x03,&rx_data); +usleep(100); +SpiPs_write_read2(0x69B,0x00,&rx_data); +temp=rx_data; +} +SpiPs_write_read1(0x02A,0x00,&rx_data); +SpiPs_write_read1(0x121,0x00,&rx_data); +SpiPs_write_read1(0x11F,0x73,&rx_data); +SpiPs_write_read1(0x124,0xFF,&rx_data); +SpiPs_write_read1(0x120,0x00,&rx_data); +SpiPs_write_read1(0x122,0x03,&rx_data); +SpiPs_write_read1(0x126,0x01,&rx_data); +SpiPs_write_read1(0x02A,0x12,&rx_data); + +SpiPs_write_read2(0x14D,0x00,&rx_data); +temp=rx_data & 0x10; +while(temp != 16){ +SpiPs_write_read2(0x14D,0x00,&rx_data); +temp=rx_data & 0x10; +usleep(100000); +} + +SpiPs_write_read1(0x77E,0x00,&rx_data); +SpiPs_write_read1(0x775,0x24,&rx_data); +SpiPs_write_read1(0x77D,0xCF,&rx_data); +SpiPs_write_read1(0x6C3,0x00,&rx_data); +//Rx TST Calibration +SpiPs_write_read1(0x000,0x22,&rx_data); +SpiPs_write_read1(0x109,0x00,&rx_data); +SpiPs_write_read1(0x77E,0x0A,&rx_data); +SpiPs_write_read1(0x14E,0x00,&rx_data); +// Ð޸ÄУ׼ģʽµçԴ¹ÜÀí +SpiPs_write_read1(0x03D,0x12,&rx_data); +SpiPs_write_read1(0x03E,0x39,&rx_data); +SpiPs_write_read1(0x03F,0x6E,&rx_data); +SpiPs_write_read1(0x040,0x78,&rx_data); +//Ð޸ĵçԴģʽ +SpiPs_write_read1(0x02E,0x03,&rx_data); +//Calibration PLL Source +// Ð޸ÄPllÀ´Դ +SpiPs_write_read1(0x77D,0x60,&rx_data); +SpiPs_write_read1(0x6C3,0x0A,&rx_data); +SpiPs_write_read1(0x775,0x24,&rx_data); +//Ð޸ÄPll4ƵÂÊ +//PLL4 +SpiPs_write_read1(0x686,0x81,&rx_data); +SpiPs_write_read1(0x683,0x07,&rx_data); +SpiPs_write_read1(0xB30,0x00,&rx_data); +SpiPs_write_read1(0xB31,0x63,&rx_data); +SpiPs_write_read1(0xB32,0xEB,&rx_data); +SpiPs_write_read1(0xB33,0x85,&rx_data); +SpiPs_write_read1(0xB34,0x1E,&rx_data); +SpiPs_write_read1(0x680,0x0B,&rx_data); +SpiPs_write_read1(0x681,0x20,&rx_data); +SpiPs_write_read1(0x682,0x13,&rx_data); +SpiPs_write_read1(0x68A,0x11,&rx_data); +SpiPs_write_read1(0x68B,0x11,&rx_data); +SpiPs_write_read1(0x690,0x0B,&rx_data); +SpiPs_write_read1(0x684,0x30,&rx_data); +SpiPs_write_read1(0x685,0x08,&rx_data); +SpiPs_write_read1(0x687,0x4D,&rx_data); +SpiPs_write_read1(0x688,0x19,&rx_data); +SpiPs_write_read1(0x68D,0x10,&rx_data); +//PLL4 AFC +while(temp != 48) +{ +SpiPs_write_read1(0x67D,0x00,&rx_data); +SpiPs_write_read1(0x67D,0x03,&rx_data); +usleep(100); +SpiPs_write_read2(0x69B,0x00,&rx_data); +temp=rx_data; +} +SpiPs_write_read1(0x02B,0x00,&rx_data); +SpiPs_write_read1(0x121,0x00,&rx_data); +SpiPs_write_read1(0x11F,0x73,&rx_data); +SpiPs_write_read1(0x124,0xFF,&rx_data); +SpiPs_write_read1(0x120,0x00,&rx_data); +SpiPs_write_read1(0x122,0x03,&rx_data); +SpiPs_write_read1(0x126,0x01,&rx_data); +SpiPs_write_read1(0x02B,0x12,&rx_data); + +SpiPs_write_read2(0x14D,0x00,&rx_data); +temp=rx_data & 0x10; +while(temp != 16){ +SpiPs_write_read2(0x14D,0x00,&rx_data); +temp=rx_data & 0x10; +usleep(100000); +} + +SpiPs_write_read1(0x77E,0x00,&rx_data); +SpiPs_write_read1(0x775,0x24,&rx_data); +SpiPs_write_read1(0x77D,0xCF,&rx_data); +SpiPs_write_read1(0x6C3,0x00,&rx_data); +SpiPs_write_read1(0x02C,0x00,&rx_data); +SpiPs_write_read1(0x02B,0x00,&rx_data); +SpiPs_write_read1(0x02A,0x00,&rx_data); +//»ָ´У׼ǰÉèÖà +SpiPs_write_read1(0x000,0x02,&rx_data); +SpiPs_write_read1(0x02E,0x06,&rx_data); +SpiPs_write_read1(0x03D,0x1B,&rx_data); +SpiPs_write_read1(0x03E,0x39,&rx_data); +SpiPs_write_read1(0x03F,0x27,&rx_data); +SpiPs_write_read1(0x040,0xF8,&rx_data); +SpiPs_write_read1(0x109,0x11,&rx_data); +SpiPs_write_read1(0x10A,0x70,&rx_data); +SpiPs_write_read1(0x11B,0x01,&rx_data); +SpiPs_write_read1(0x11E,0x01,&rx_data); +SpiPs_write_read1(0x11F,0x33,&rx_data); +SpiPs_write_read1(0x128,0x10,&rx_data); +SpiPs_write_read1(0x161,0x01,&rx_data); +SpiPs_write_read1(0x162,0x01,&rx_data); +SpiPs_write_read1(0x164,0x05,&rx_data); +SpiPs_write_read1(0x165,0x55,&rx_data); +SpiPs_write_read1(0x166,0x55,&rx_data); +SpiPs_write_read1(0x167,0x55,&rx_data); +SpiPs_write_read1(0x168,0x55,&rx_data); +SpiPs_write_read1(0x169,0x55,&rx_data); +SpiPs_write_read1(0xA07,0x00,&rx_data); +SpiPs_write_read1(0xA08,0x00,&rx_data); +SpiPs_write_read1(0xA16,0x00,&rx_data); +SpiPs_write_read1(0xA17,0x00,&rx_data); +SpiPs_write_read1(0xA18,0x00,&rx_data); +SpiPs_write_read1(0xA19,0x00,&rx_data); +SpiPs_write_read1(0xA1A,0x00,&rx_data); +SpiPs_write_read1(0xA1B,0x00,&rx_data); +SpiPs_write_read1(0xA1C,0x00,&rx_data); +SpiPs_write_read1(0xA2D,0x00,&rx_data); +// TX¶þ·ַ¨У׼ +// Ð޸ÄУ׼ģʽµçԴ¹ÜÀí +SpiPs_write_read1(0x03D,0x1B,&rx_data); +SpiPs_write_read1(0x03E,0x39,&rx_data); +SpiPs_write_read1(0x03F,0x27,&rx_data); +SpiPs_write_read1(0x040,0xF8,&rx_data); +//Ð޸ĵçԴģʽ +SpiPs_write_read1(0x02E,0x03,&rx_data); +SpiPs_write_read1(0x128,0x11,&rx_data); +SpiPs_write_read1(0x11E,0x01,&rx_data); +SpiPs_write_read1(0x77E,0x24,&rx_data); +SpiPs_write_read1(0x11F,0x01,&rx_data); +SpiPs_write_read1(0x121,0x02,&rx_data); +SpiPs_write_read1(0x11B,0x01,&rx_data); +SpiPs_write_read1(0x161,0x01,&rx_data); +SpiPs_write_read1(0x162,0x01,&rx_data); +SpiPs_write_read1(0x163,0x00,&rx_data); +SpiPs_write_read1(0x164,0x05,&rx_data); +SpiPs_write_read1(0x165,0x55,&rx_data); +SpiPs_write_read1(0x166,0x55,&rx_data); +SpiPs_write_read1(0x167,0x55,&rx_data); +SpiPs_write_read1(0x168,0x55,&rx_data); +SpiPs_write_read1(0x169,0x55,&rx_data); +SpiPs_write_read1(0xA2D,0x02,&rx_data); +SpiPs_write_read1(0xA07,0x00,&rx_data); +SpiPs_write_read1(0xA08,0x0F,&rx_data); +SpiPs_write_read1(0xA1C,0x01,&rx_data); +SpiPs_write_read1(0xA16,0x2A,&rx_data); +SpiPs_write_read1(0xA17,0xAA,&rx_data); +SpiPs_write_read1(0xA18,0xAA,&rx_data); +SpiPs_write_read1(0xA19,0xAA,&rx_data); +SpiPs_write_read1(0xA1A,0xAA,&rx_data); +SpiPs_write_read1(0xA1B,0xAA,&rx_data); +SpiPs_write_read1(0x186,0x01,&rx_data); +SpiPs_write_read1(0x763,0x34,&rx_data); +SpiPs_write_read1(0x76D,0x34,&rx_data); +SpiPs_write_read1(0x101,0xEF,&rx_data); +SpiPs_write_read1(0x101,0xFF,&rx_data); +SpiPs_write_read1(0x800,0x00,&rx_data); +SpiPs_write_read1(0x81A,0xF7,&rx_data); +SpiPs_write_read1(0x81B,0x34,&rx_data); +SpiPs_write_read1(0x81C,0x33,&rx_data); +SpiPs_write_read1(0x81D,0x12,&rx_data); +SpiPs_write_read1(0x81E,0x00,&rx_data); +SpiPs_write_read1(0x81F,0xFF,&rx_data); +SpiPs_write_read1(0x820,0x00,&rx_data); +SpiPs_write_read1(0x821,0xFF,&rx_data); +SpiPs_write_read1(0x800,0x80,&rx_data); +SpiPs_write_read1(0x800,0x81,&rx_data); +//×îÉÙ0.1s +usleep(100000); +SpiPs_write_read1(0x77E,0x00,&rx_data); +SpiPs_write_read1(0x77E,0x24,&rx_data); +SpiPs_write_read1(0x11F,0x03,&rx_data); +SpiPs_write_read1(0x121,0x02,&rx_data); +SpiPs_write_read1(0x11B,0x01,&rx_data); +SpiPs_write_read1(0x11E,0x01,&rx_data); +SpiPs_write_read1(0x161,0x01,&rx_data); +SpiPs_write_read1(0x162,0x01,&rx_data); +SpiPs_write_read1(0x164,0x05,&rx_data); +SpiPs_write_read1(0x165,0x55,&rx_data); +SpiPs_write_read1(0x166,0x55,&rx_data); +SpiPs_write_read1(0x167,0x55,&rx_data); +SpiPs_write_read1(0x168,0x55,&rx_data); +SpiPs_write_read1(0x169,0x55,&rx_data); +SpiPs_write_read1(0xA2D,0x02,&rx_data); +SpiPs_write_read1(0xA07,0x00,&rx_data); +SpiPs_write_read1(0xA08,0x0F,&rx_data); +SpiPs_write_read1(0xA1C,0x01,&rx_data); +SpiPs_write_read1(0xA16,0x15,&rx_data); +SpiPs_write_read1(0xA17,0x55,&rx_data); +SpiPs_write_read1(0xA18,0x55,&rx_data); +SpiPs_write_read1(0xA19,0x55,&rx_data); +SpiPs_write_read1(0xA1A,0x55,&rx_data); +SpiPs_write_read1(0xA1B,0x55,&rx_data); +SpiPs_write_read1(0x81A,0xF7,&rx_data); +SpiPs_write_read1(0x81B,0x44,&rx_data); +SpiPs_write_read1(0x81C,0x33,&rx_data); +SpiPs_write_read1(0x81D,0x14,&rx_data); +SpiPs_write_read1(0x800,0x80,&rx_data); +SpiPs_write_read1(0x800,0x82,&rx_data); +//×îÉÙ0.1s +usleep(500000); +SpiPs_write_read1(0x77E,0x00,&rx_data); +//»ָ´У׼ǰÉèÖà +SpiPs_write_read1(0x000,0x02,&rx_data); +SpiPs_write_read1(0x02E,0x06,&rx_data); +SpiPs_write_read1(0x03D,0x1B,&rx_data); +SpiPs_write_read1(0x03E,0x39,&rx_data); +SpiPs_write_read1(0x03F,0x27,&rx_data); +SpiPs_write_read1(0x040,0xF8,&rx_data); +SpiPs_write_read1(0x109,0x11,&rx_data); +SpiPs_write_read1(0x10A,0x70,&rx_data); +SpiPs_write_read1(0x11B,0x01,&rx_data); +SpiPs_write_read1(0x11E,0x01,&rx_data); +SpiPs_write_read1(0x11F,0x33,&rx_data); +SpiPs_write_read1(0x128,0x10,&rx_data); +SpiPs_write_read1(0x161,0x01,&rx_data); +SpiPs_write_read1(0x162,0x01,&rx_data); +SpiPs_write_read1(0x164,0x05,&rx_data); +SpiPs_write_read1(0x165,0x55,&rx_data); +SpiPs_write_read1(0x166,0x55,&rx_data); +SpiPs_write_read1(0x167,0x55,&rx_data); +SpiPs_write_read1(0x168,0x55,&rx_data); +SpiPs_write_read1(0x169,0x55,&rx_data); +SpiPs_write_read1(0xA07,0x00,&rx_data); +SpiPs_write_read1(0xA08,0x00,&rx_data); +SpiPs_write_read1(0xA16,0x00,&rx_data); +SpiPs_write_read1(0xA17,0x00,&rx_data); +SpiPs_write_read1(0xA18,0x00,&rx_data); +SpiPs_write_read1(0xA19,0x00,&rx_data); +SpiPs_write_read1(0xA1A,0x00,&rx_data); +SpiPs_write_read1(0xA1B,0x00,&rx_data); +SpiPs_write_read1(0xA1C,0x00,&rx_data); +SpiPs_write_read1(0xA2D,0x00,&rx_data); +usleep(1000); +SpiPs_write_read2(0x615,0x00,&rx_data); +temp=rx_data; +SpiPs_write_read2(0x635,0x00,&rx_data); +temp=rx_data; +////ÅäÖÃTx NCO BIST ON +//SpiPs_write_read1(0x11B,0x01,&rx_data); +//SpiPs_write_read1(0x11E,0x01,&rx_data); +//SpiPs_write_read1(0x161,0x01,&rx_data); +//SpiPs_write_read1(0x162,0x01,&rx_data); +////ÅäÖÃTx NCOƵÂÊ 1MHz +//SpiPs_write_read1(0x164,0x05,&rx_data); +//SpiPs_write_read1(0x165,0x55,&rx_data); +//SpiPs_write_read1(0x166,0x55,&rx_data); +//SpiPs_write_read1(0x167,0x55,&rx_data); +//SpiPs_write_read1(0x168,0x55,&rx_data); +//SpiPs_write_read1(0x169,0x55,&rx_data); +} diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_DEMO/cx9261a_710_config.c b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_DEMO/cx9261a_710_config.c new file mode 100644 index 0000000..c8bb612 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_DEMO/cx9261a_710_config.c @@ -0,0 +1,835 @@ +/* + * cx9261a_710_config.c + * + * Created on: 2024Äê3ÔÂ21ÈÕ + * Author: cxlab + */ + + +/* + * cx9261a_076_config.c + * + * Created on: 2023Äê11ÔÂ30ÈÕ + * Author: cxlab + */ + + +#include "xilinx_io.h" +#include "sleep.h" +void cx9261a_710_config(void){ +u8 rx_data; +u8 temp,r13D,r13E; + +//setPin(pin,value) +GpioSetPinDir(0,0x01); +GpioWritePin(0,1); +GpioSetPinDir(32,0x01); +GpioWritePin(32,1); +GpioSetPinDir(33,0x01); +GpioWritePin(33,1); +GpioSetPinDir(34,0x01); +GpioWritePin(34,0); +GpioSetPinDir(35,0x01); //tx:0-rx:1 +GpioWritePin(35,1); //tx:0-rx:1 +GpioSetPinDir(36,0x01); //fdd:0-tdd:1 +GpioWritePin(36,1); //fdd:0-tdd:1 +GpioSetPinDir(37,0x01); //1r1t:0-2r2t:1 +GpioWritePin(37,1); //1r1t:0-2r2t:1 +GpioSetPinDir(38,0x01); //dualport:0-singleport:1 +GpioWritePin(38,1); //dualport:0-singleport:1 +GpioSetPinDir(39,0x01); +GpioWritePin(39,1); +GpioSetPinDir(40,0x01); +GpioWritePin(40,1); +//ÅäÖÃоƬ +//³õʼ»¯оƬ +SpiPs_write_read1(0x000,0x02,&rx_data); +SpiPs_write_read1(0x773,0x53,&rx_data); +SpiPs_write_read1(0x774,0x86,&rx_data); +SpiPs_write_read1(0x781,0x6F,&rx_data); +SpiPs_write_read1(0x70B,0x0E,&rx_data); +SpiPs_write_read1(0x727,0x0E,&rx_data); +SpiPs_write_read1(0x743,0x0E,&rx_data); +SpiPs_write_read1(0x624,0x11,&rx_data); +SpiPs_write_read1(0x625,0x11,&rx_data); +SpiPs_write_read1(0x61E,0x30,&rx_data); +SpiPs_write_read1(0x61F,0x08,&rx_data); +SpiPs_write_read1(0x621,0x4D,&rx_data); +SpiPs_write_read1(0x622,0x19,&rx_data); +SpiPs_write_read1(0x627,0x10,&rx_data); +SpiPs_write_read1(0x646,0x11,&rx_data); +SpiPs_write_read1(0x647,0x11,&rx_data); +SpiPs_write_read1(0x640,0x30,&rx_data); +SpiPs_write_read1(0x641,0x08,&rx_data); +SpiPs_write_read1(0x643,0x4D,&rx_data); +SpiPs_write_read1(0x644,0x19,&rx_data); +SpiPs_write_read1(0x649,0x10,&rx_data); +SpiPs_write_read1(0x668,0x11,&rx_data); +SpiPs_write_read1(0x669,0x11,&rx_data); +SpiPs_write_read1(0x662,0x30,&rx_data); +SpiPs_write_read1(0x663,0x08,&rx_data); +SpiPs_write_read1(0x665,0x4D,&rx_data); +SpiPs_write_read1(0x666,0x19,&rx_data); +SpiPs_write_read1(0x66B,0x10,&rx_data); +SpiPs_write_read1(0x68A,0x11,&rx_data); +SpiPs_write_read1(0x68B,0x11,&rx_data); +SpiPs_write_read1(0x684,0x30,&rx_data); +SpiPs_write_read1(0x685,0x08,&rx_data); +SpiPs_write_read1(0x687,0x4D,&rx_data); +SpiPs_write_read1(0x688,0x19,&rx_data); +SpiPs_write_read1(0x68D,0x10,&rx_data); +SpiPs_write_read1(0x6AC,0x11,&rx_data); +SpiPs_write_read1(0x6AD,0x11,&rx_data); +SpiPs_write_read1(0x6A6,0x30,&rx_data); +SpiPs_write_read1(0x6A7,0x08,&rx_data); +SpiPs_write_read1(0x6A9,0x4D,&rx_data); +SpiPs_write_read1(0x6AA,0x19,&rx_data); +SpiPs_write_read1(0x6AF,0x10,&rx_data); +SpiPs_write_read1(0x705,0xFC,&rx_data); +SpiPs_write_read1(0x706,0x6D,&rx_data); +SpiPs_write_read1(0x707,0x91,&rx_data); +SpiPs_write_read1(0x708,0x04,&rx_data); +SpiPs_write_read1(0x709,0x94,&rx_data); +SpiPs_write_read1(0x70A,0xFC,&rx_data); +SpiPs_write_read1(0x70C,0xC0,&rx_data); +SpiPs_write_read1(0x721,0xFC,&rx_data); +SpiPs_write_read1(0x722,0x6D,&rx_data); +SpiPs_write_read1(0x723,0x91,&rx_data); +SpiPs_write_read1(0x724,0x04,&rx_data); +SpiPs_write_read1(0x725,0x94,&rx_data); +SpiPs_write_read1(0x726,0xFC,&rx_data); +SpiPs_write_read1(0x728,0xC0,&rx_data); +SpiPs_write_read1(0x73D,0xFC,&rx_data); +SpiPs_write_read1(0x73E,0x6D,&rx_data); +SpiPs_write_read1(0x73F,0x91,&rx_data); +SpiPs_write_read1(0x740,0x04,&rx_data); +SpiPs_write_read1(0x741,0x94,&rx_data); +SpiPs_write_read1(0x742,0xFC,&rx_data); +SpiPs_write_read1(0x744,0xC0,&rx_data); +SpiPs_write_read1(0x75A,0x83,&rx_data); +SpiPs_write_read1(0x75B,0xDA,&rx_data); +usleep(100000); +SpiPs_write_read1(0x75B,0x9A,&rx_data); +SpiPs_write_read1(0x75C,0x81,&rx_data); +SpiPs_write_read1(0x763,0x04,&rx_data); +SpiPs_write_read1(0x764,0x83,&rx_data); +SpiPs_write_read1(0x765,0xDA,&rx_data); +usleep(100000); +SpiPs_write_read1(0x765,0x9A,&rx_data); +SpiPs_write_read1(0x766,0x81,&rx_data); +SpiPs_write_read1(0x76D,0x04,&rx_data); +//³õʼ»¯µçԴ +SpiPs_write_read1(0x031,0x00,&rx_data); +SpiPs_write_read1(0x032,0x7F,&rx_data); +SpiPs_write_read1(0x033,0xFF,&rx_data); +SpiPs_write_read1(0x034,0xFF,&rx_data); +SpiPs_write_read1(0x035,0x00,&rx_data); +SpiPs_write_read1(0x036,0x3D,&rx_data); +SpiPs_write_read1(0x037,0xFF,&rx_data); +SpiPs_write_read1(0x038,0xFB,&rx_data); +SpiPs_write_read1(0x039,0x00,&rx_data); +SpiPs_write_read1(0x03A,0x3D,&rx_data); +SpiPs_write_read1(0x03B,0xFF,&rx_data); +SpiPs_write_read1(0x03C,0xF8,&rx_data); +SpiPs_write_read1(0x03D,0x1B,&rx_data); +SpiPs_write_read1(0x03E,0x39,&rx_data); +SpiPs_write_read1(0x03F,0x26,&rx_data); +SpiPs_write_read1(0x040,0x78,&rx_data); +SpiPs_write_read1(0x041,0x03,&rx_data); +SpiPs_write_read1(0x042,0x3D,&rx_data); +SpiPs_write_read1(0x043,0xE7,&rx_data); +SpiPs_write_read1(0x044,0xF8,&rx_data); +SpiPs_write_read1(0x045,0x18,&rx_data); +SpiPs_write_read1(0x046,0x3D,&rx_data); +SpiPs_write_read1(0x047,0x3F,&rx_data); +SpiPs_write_read1(0x048,0xF8,&rx_data); +SpiPs_write_read1(0x049,0x1F,&rx_data); +SpiPs_write_read1(0x04A,0x3D,&rx_data); +SpiPs_write_read1(0x04B,0x07,&rx_data); +SpiPs_write_read1(0x04C,0xF8,&rx_data); +SpiPs_write_read1(0x04D,0x04,&rx_data); +SpiPs_write_read1(0x04E,0x3D,&rx_data); +SpiPs_write_read1(0x04F,0xD9,&rx_data); +SpiPs_write_read1(0x050,0xFE,&rx_data); +//×Զ¨Òå½ÓÊÕģʽ +SpiPs_write_read1(0x041,0x03,&rx_data); +SpiPs_write_read1(0x042,0x3D,&rx_data); +SpiPs_write_read1(0x043,0xE7,&rx_data); +SpiPs_write_read1(0x044,0xF8,&rx_data); +//×Զ¨Ò巢Éäģʽ +SpiPs_write_read1(0x045,0x18,&rx_data); +SpiPs_write_read1(0x046,0x3D,&rx_data); +SpiPs_write_read1(0x047,0x3F,&rx_data); +SpiPs_write_read1(0x048,0xF8,&rx_data); +//×Զ¨ÒåFDDģʽ +SpiPs_write_read1(0x049,0x1B,&rx_data); +SpiPs_write_read1(0x04A,0x3D,&rx_data); +SpiPs_write_read1(0x04B,0x27,&rx_data); +SpiPs_write_read1(0x04C,0xF8,&rx_data); +//ÅäÖÃBBPLL +SpiPs_write_read1(0x789,0x10,&rx_data); +SpiPs_write_read1(0x785,0x49,&rx_data); +SpiPs_write_read1(0x788,0x24,&rx_data); +usleep(100000); +SpiPs_write_read1(0x788,0xA4,&rx_data); +SpiPs_write_read1(0x0C0,0x50,&rx_data); +SpiPs_write_read1(0x0C1,0x50,&rx_data); +SpiPs_write_read1(0x0C2,0x50,&rx_data); +SpiPs_write_read1(0x601,0x0F,&rx_data); +SpiPs_write_read1(0x602,0x21,&rx_data); +SpiPs_write_read1(0x60D,0x0D,&rx_data); +SpiPs_write_read1(0x60E,0xFF,&rx_data); +SpiPs_write_read1(0x60F,0xFF,&rx_data); +SpiPs_write_read1(0x610,0xFF,&rx_data); +SpiPs_write_read1(0x611,0x2F,&rx_data); +SpiPs_write_read1(0x612,0x00,&rx_data); +SpiPs_write_read1(0x70E,0x6B,&rx_data); +SpiPs_write_read1(0x72A,0x6B,&rx_data); +SpiPs_write_read1(0x746,0x6B,&rx_data); +SpiPs_write_read1(0x70F,0xE0,&rx_data); +SpiPs_write_read1(0x72B,0xE0,&rx_data); +SpiPs_write_read1(0x747,0xE0,&rx_data); +SpiPs_write_read1(0x70D,0x43,&rx_data); +SpiPs_write_read1(0x729,0x43,&rx_data); +SpiPs_write_read1(0x745,0x43,&rx_data); +SpiPs_write_read1(0x782,0x76,&rx_data); +SpiPs_write_read1(0x783,0x76,&rx_data); +SpiPs_write_read1(0x784,0x06,&rx_data); +//ÅäÖÃPLLÀ´Դ +SpiPs_write_read1(0x77D,0xCF,&rx_data); +SpiPs_write_read1(0x775,0x24,&rx_data); +SpiPs_write_read1(0x6C3,0x00,&rx_data); +//ÅäÖÃPLL1 +SpiPs_write_read1(0x620,0x91,&rx_data); +SpiPs_write_read1(0x61D,0x37,&rx_data); +SpiPs_write_read1(0xB06,0x00,&rx_data); +SpiPs_write_read1(0xB07,0xCB,&rx_data); +SpiPs_write_read1(0xB08,0x20,&rx_data); +SpiPs_write_read1(0xB09,0x00,&rx_data); +SpiPs_write_read1(0xB0A,0x00,&rx_data); +SpiPs_write_read1(0x61A,0x0C,&rx_data); +SpiPs_write_read1(0x61B,0x30,&rx_data); +SpiPs_write_read1(0x61C,0x08,&rx_data); +SpiPs_write_read1(0x62A,0x0B,&rx_data); +//ÅäÖÃPLL2 +SpiPs_write_read1(0x642,0x91,&rx_data); +SpiPs_write_read1(0x63F,0x35,&rx_data); +SpiPs_write_read1(0xB14,0x00,&rx_data); +SpiPs_write_read1(0xB15,0xFA,&rx_data); +SpiPs_write_read1(0xB16,0x00,&rx_data); +SpiPs_write_read1(0xB17,0x00,&rx_data); +SpiPs_write_read1(0xB18,0x00,&rx_data); +SpiPs_write_read1(0x63C,0x0D,&rx_data); +SpiPs_write_read1(0x63D,0x30,&rx_data); +SpiPs_write_read1(0x63E,0x0B,&rx_data); +SpiPs_write_read1(0x64C,0x00,&rx_data); +//ÅäÖÃPLL3 +SpiPs_write_read1(0x664,0x81,&rx_data); +SpiPs_write_read1(0x661,0x36,&rx_data); +SpiPs_write_read1(0xB22,0x00,&rx_data); +SpiPs_write_read1(0xB23,0xBB,&rx_data); +SpiPs_write_read1(0xB24,0x80,&rx_data); +SpiPs_write_read1(0xB25,0x00,&rx_data); +SpiPs_write_read1(0xB26,0x00,&rx_data); +SpiPs_write_read1(0x65E,0x0B,&rx_data); +SpiPs_write_read1(0x65F,0x30,&rx_data); +SpiPs_write_read1(0x660,0x0E,&rx_data); +SpiPs_write_read1(0x66E,0x0B,&rx_data); +//ÅäÖÃPLL4 +SpiPs_write_read1(0x686,0x91,&rx_data); +SpiPs_write_read1(0x683,0x36,&rx_data); +SpiPs_write_read1(0xB30,0x00,&rx_data); +SpiPs_write_read1(0xB31,0xDA,&rx_data); +SpiPs_write_read1(0xB32,0xC0,&rx_data); +SpiPs_write_read1(0xB33,0x00,&rx_data); +SpiPs_write_read1(0xB34,0x00,&rx_data); +SpiPs_write_read1(0x680,0x0C,&rx_data); +SpiPs_write_read1(0x681,0x30,&rx_data); +SpiPs_write_read1(0x682,0x08,&rx_data); +SpiPs_write_read1(0x690,0x0B,&rx_data); +//ÅäÖÃPLL5 +SpiPs_write_read1(0x6A8,0x81,&rx_data); +SpiPs_write_read1(0x6A5,0x36,&rx_data); +SpiPs_write_read1(0xB3E,0x00,&rx_data); +SpiPs_write_read1(0xB3F,0x9C,&rx_data); +SpiPs_write_read1(0xB40,0x40,&rx_data); +SpiPs_write_read1(0xB41,0x00,&rx_data); +SpiPs_write_read1(0xB42,0x00,&rx_data); +SpiPs_write_read1(0x6A2,0x0C,&rx_data); +SpiPs_write_read1(0x6A3,0x30,&rx_data); +SpiPs_write_read1(0x6A4,0x0C,&rx_data); +SpiPs_write_read1(0x6B2,0x0B,&rx_data); +//ÅäÖÃTx1ͨµÀƵÂÊÏà¹ؼĴæÆ÷ +SpiPs_write_read1(0x75F,0x55,&rx_data); +SpiPs_write_read1(0x761,0x04,&rx_data); +SpiPs_write_read1(0x762,0x70,&rx_data); +//ÅäÖÃTx1ͨµÀƵÂÊÏà¹ؼĴæÆ÷ +SpiPs_write_read1(0x769,0x55,&rx_data); +SpiPs_write_read1(0x76B,0x04,&rx_data); +SpiPs_write_read1(0x76C,0x70,&rx_data); +//ÅäÖÃRx1ͨµÀ +SpiPs_write_read1(0x700,0x56,&rx_data); +SpiPs_write_read1(0x701,0x00,&rx_data); +SpiPs_write_read1(0x702,0xDB,&rx_data); +SpiPs_write_read1(0x703,0x45,&rx_data); +SpiPs_write_read1(0x704,0xF8,&rx_data); +SpiPs_write_read1(0x907,0x1F,&rx_data); +//ÅäÖÃRx2ͨµÀ +SpiPs_write_read1(0x71C,0x56,&rx_data); +SpiPs_write_read1(0x71D,0x00,&rx_data); +SpiPs_write_read1(0x71E,0xDB,&rx_data); +SpiPs_write_read1(0x71F,0x45,&rx_data); +SpiPs_write_read1(0x720,0xF8,&rx_data); +SpiPs_write_read1(0x907,0x1F,&rx_data); +//ÅäÖÃRx3ͨµÀ +SpiPs_write_read1(0x738,0x56,&rx_data); +SpiPs_write_read1(0x739,0x00,&rx_data); +SpiPs_write_read1(0x73A,0xDB,&rx_data); +SpiPs_write_read1(0x73B,0x45,&rx_data); +SpiPs_write_read1(0x73C,0xF8,&rx_data); +SpiPs_write_read1(0x907,0x1F,&rx_data); +//ÅäÖÃTx1ͨµÀ +SpiPs_write_read1(0x75E,0xFF,&rx_data); +SpiPs_write_read1(0x75D,0x4A,&rx_data); +SpiPs_write_read1(0x75F,0x7D,&rx_data); +SpiPs_write_read1(0x760,0xFF,&rx_data); +//ÅäÖÃTx2ͨµÀ +SpiPs_write_read1(0x768,0xFF,&rx_data); +SpiPs_write_read1(0x767,0x4A,&rx_data); +SpiPs_write_read1(0x769,0x7D,&rx_data); +SpiPs_write_read1(0x76A,0xFF,&rx_data); +//ÅäÖÃRxÂ˲¨Æ÷ +SpiPs_write_read1(0x106,0x02,&rx_data); +//ÅäÖÃTxÂ˲¨Æ÷ +SpiPs_write_read1(0x107,0x00,&rx_data); +SpiPs_write_read1(0x108,0xD0,&rx_data); +//ÅäÖÃRx»ìƵÆ÷ +SpiPs_write_read1(0x11C,0x00,&rx_data); +SpiPs_write_read1(0xA07,0x00,&rx_data); +SpiPs_write_read1(0xA08,0x00,&rx_data); +SpiPs_write_read1(0xA09,0x00,&rx_data); +SpiPs_write_read1(0xA16,0x00,&rx_data); +SpiPs_write_read1(0xA17,0x00,&rx_data); +SpiPs_write_read1(0xA18,0x00,&rx_data); +SpiPs_write_read1(0xA19,0x00,&rx_data); +SpiPs_write_read1(0xA1A,0x00,&rx_data); +SpiPs_write_read1(0xA1B,0x00,&rx_data); +//ÅäÖÃTx»ìƵÆ÷ +SpiPs_write_read1(0x128,0x10,&rx_data); +SpiPs_write_read1(0x11B,0x00,&rx_data); +SpiPs_write_read1(0x11E,0x00,&rx_data); +SpiPs_write_read1(0x161,0x00,&rx_data); +SpiPs_write_read1(0x162,0x00,&rx_data); +SpiPs_write_read1(0x164,0x00,&rx_data); +SpiPs_write_read1(0x165,0x00,&rx_data); +SpiPs_write_read1(0x166,0x00,&rx_data); +SpiPs_write_read1(0x167,0x00,&rx_data); +SpiPs_write_read1(0x168,0x00,&rx_data); +SpiPs_write_read1(0x169,0x00,&rx_data); +//ÅäÖÃAGC +SpiPs_write_read1(0x903,0x11,&rx_data); +SpiPs_write_read1(0x900,0x00,&rx_data); +SpiPs_write_read1(0x901,0x00,&rx_data); +SpiPs_write_read1(0x908,0x77,&rx_data); +SpiPs_write_read1(0x909,0x03,&rx_data); +SpiPs_write_read1(0x90A,0x32,&rx_data); +SpiPs_write_read1(0x90D,0x00,&rx_data); +SpiPs_write_read1(0x90E,0x0F,&rx_data); +SpiPs_write_read1(0x90F,0x65,&rx_data); +SpiPs_write_read1(0x910,0x32,&rx_data); +SpiPs_write_read1(0x911,0x00,&rx_data); +SpiPs_write_read1(0x912,0x0F,&rx_data); +SpiPs_write_read1(0x913,0x3A,&rx_data); +SpiPs_write_read1(0x914,0x37,&rx_data); +SpiPs_write_read1(0x915,0x34,&rx_data); +SpiPs_write_read1(0x916,0x31,&rx_data); +//Çл»µ½ÐÝÃßģʽ +SpiPs_write_read1(0x02E,0x01,&rx_data); +usleep(1000000); +//Çл»µ½У׼ģʽ +SpiPs_write_read1(0x02E,0x03,&rx_data); +usleep(100000); +//BBPllËø¶¨ +SpiPs_write_read1(0x600,0x00,&rx_data); +SpiPs_write_read1(0x600,0x11,&rx_data); +usleep(100000); +//BBPllËø¶¨ ³ɹ¦ +//ADCУ׼ +SpiPs_write_read1(0x70B,0x1E,&rx_data); +SpiPs_write_read1(0x727,0x1E,&rx_data); +SpiPs_write_read1(0x743,0x1E,&rx_data); +SpiPs_write_read1(0x70F,0xE0,&rx_data); +SpiPs_write_read1(0x710,0x83,&rx_data); +SpiPs_write_read1(0x711,0xF0,&rx_data); +SpiPs_write_read1(0x72B,0xE0,&rx_data); +SpiPs_write_read1(0x72C,0x83,&rx_data); +SpiPs_write_read1(0x72D,0xF0,&rx_data); +SpiPs_write_read1(0x747,0xE0,&rx_data); +SpiPs_write_read1(0x748,0x83,&rx_data); +SpiPs_write_read1(0x749,0xF0,&rx_data); +SpiPs_write_read1(0x713,0x80,&rx_data); +SpiPs_write_read1(0x72F,0x80,&rx_data); +SpiPs_write_read1(0x74B,0x80,&rx_data); +SpiPs_write_read1(0x70B,0x9E,&rx_data); +SpiPs_write_read1(0x727,0x9E,&rx_data); +SpiPs_write_read1(0x743,0x9E,&rx_data); +SpiPs_write_read1(0x70B,0x9A,&rx_data); +SpiPs_write_read1(0x727,0x9A,&rx_data); +SpiPs_write_read1(0x743,0x9A,&rx_data); +SpiPs_write_read1(0x70B,0x9E,&rx_data); +SpiPs_write_read1(0x727,0x9E,&rx_data); +SpiPs_write_read1(0x743,0x9E,&rx_data); +usleep(100000); +SpiPs_write_read1(0x70B,0x1E,&rx_data); +SpiPs_write_read1(0x727,0x1E,&rx_data); +SpiPs_write_read1(0x743,0x1E,&rx_data); +SpiPs_write_read1(0x713,0xC0,&rx_data); +SpiPs_write_read1(0x72F,0xC0,&rx_data); +SpiPs_write_read1(0x74B,0xC0,&rx_data); +//flashУ׼ +SpiPs_write_read1(0x70B,0x1E,&rx_data); +SpiPs_write_read1(0x727,0x1E,&rx_data); +SpiPs_write_read1(0x743,0x1E,&rx_data); +SpiPs_write_read1(0x715,0x80,&rx_data); +SpiPs_write_read1(0x731,0x80,&rx_data); +SpiPs_write_read1(0x74D,0x80,&rx_data); +SpiPs_write_read1(0x715,0xC0,&rx_data); +SpiPs_write_read1(0x731,0xC0,&rx_data); +SpiPs_write_read1(0x74D,0xC0,&rx_data); +SpiPs_write_read1(0x716,0x40,&rx_data); +SpiPs_write_read1(0x732,0x40,&rx_data); +SpiPs_write_read1(0x74E,0x40,&rx_data); +SpiPs_write_read1(0x70B,0x16,&rx_data); +SpiPs_write_read1(0x727,0x16,&rx_data); +SpiPs_write_read1(0x743,0x16,&rx_data); +usleep(100000); +SpiPs_write_read1(0x70B,0x1E,&rx_data); +SpiPs_write_read1(0x727,0x1E,&rx_data); +SpiPs_write_read1(0x743,0x1E,&rx_data); +SpiPs_write_read1(0x715,0x80,&rx_data); +SpiPs_write_read1(0x731,0x80,&rx_data); +SpiPs_write_read1(0x74D,0x80,&rx_data); +SpiPs_write_read1(0x716,0x00,&rx_data); +SpiPs_write_read1(0x732,0x00,&rx_data); +SpiPs_write_read1(0x74E,0x00,&rx_data); +//DC Tracking +SpiPs_write_read1(0x109,0x11,&rx_data); +SpiPs_write_read1(0x10A,0x70,&rx_data); +SpiPs_write_read1(0x11F,0x33,&rx_data); +//Rx1 QECУ׼ +SpiPs_write_read1(0x02E,0x03,&rx_data); +SpiPs_write_read1(0x03F,0x26,&rx_data); +SpiPs_write_read1(0x040,0x78,&rx_data); +SpiPs_write_read1(0x77D,0x90,&rx_data); +SpiPs_write_read1(0x775,0x24,&rx_data); +SpiPs_write_read1(0x6C3,0x05,&rx_data); +SpiPs_write_read1(0x61D,0x27,&rx_data); +SpiPs_write_read1(0x617,0x00,&rx_data); +SpiPs_write_read1(0x617,0x03,&rx_data); +usleep(100000); +SpiPs_write_read1(0x61D,0x37,&rx_data); +SpiPs_write_read1(0x686,0x81,&rx_data); +SpiPs_write_read1(0x683,0x36,&rx_data); +SpiPs_write_read1(0xB30,0x00,&rx_data); +SpiPs_write_read1(0xB31,0x87,&rx_data); +SpiPs_write_read1(0xB32,0x04,&rx_data); +SpiPs_write_read1(0xB33,0x44,&rx_data); +SpiPs_write_read1(0xB34,0x44,&rx_data); +SpiPs_write_read1(0x680,0x0C,&rx_data); +SpiPs_write_read1(0x681,0x30,&rx_data); +SpiPs_write_read1(0x682,0x0C,&rx_data); +SpiPs_write_read1(0x690,0x0B,&rx_data); +SpiPs_write_read1(0x683,0x26,&rx_data); +SpiPs_write_read1(0x67D,0x00,&rx_data); +SpiPs_write_read1(0x67D,0x03,&rx_data); +usleep(100000); +SpiPs_write_read1(0x683,0x36,&rx_data); +SpiPs_write_read1(0x000,0x12,&rx_data); +SpiPs_write_read1(0x77E,0x50,&rx_data); +SpiPs_write_read1(0x11B,0x01,&rx_data); +SpiPs_write_read1(0x11E,0x01,&rx_data); +SpiPs_write_read1(0x164,0x00,&rx_data); +SpiPs_write_read1(0x165,0x00,&rx_data); +SpiPs_write_read1(0x166,0x00,&rx_data); +SpiPs_write_read1(0x167,0x00,&rx_data); +SpiPs_write_read1(0x168,0x00,&rx_data); +SpiPs_write_read1(0x169,0x00,&rx_data); +SpiPs_write_read1(0x161,0x00,&rx_data); +SpiPs_write_read1(0x162,0x00,&rx_data); +SpiPs_write_read1(0x162,0x01,&rx_data); +SpiPs_write_read1(0x161,0x01,&rx_data); +SpiPs_write_read1(0x706,0x65,&rx_data); +SpiPs_write_read1(0x6C3,0x00,&rx_data); +SpiPs_write_read1(0x75F,0x7D,&rx_data); +SpiPs_write_read1(0x11F,0x73,&rx_data); +SpiPs_write_read1(0x153,0x00,&rx_data); +SpiPs_write_read1(0x708,0x24,&rx_data); +SpiPs_write_read1(0x196,0x01,&rx_data); +SpiPs_write_read1(0x02A,0x12,&rx_data); + +do{ +usleep(100); +SpiPs_write_read2(0x14D,0x00,&rx_data); +temp=rx_data&0x10; +}while (temp != 16); + +SpiPs_write_read1(0x02A,0x00,&rx_data); +SpiPs_write_read1(0x196,0x11,&rx_data); +SpiPs_write_read2(0x13D,0x00,&rx_data); +r13D = rx_data; +SpiPs_write_read2(0x13E,0x00,&rx_data); +r13E = rx_data; + +unsigned long B = r13D * 256 + r13E; +signed long B_s = B - (B >= 32768) * 65536; +unsigned long B_abs = abs(B_s); +unsigned short B_b = (unsigned short)B_abs; +unsigned short B_delay = (B_b>>6) & 0x1ff; + +if(B_s > 0) +{ + SpiPs_write_read1(0x199, ((B_delay>>8)&0x1),&rx_data); + SpiPs_write_read1(0x19A, B_delay&0xff,&rx_data); + SpiPs_write_read1(0x19B, 0,&rx_data); + SpiPs_write_read1(0x19C, 0,&rx_data); +} +else +{ + SpiPs_write_read1(0x199, 0,&rx_data); + SpiPs_write_read1(0x19A, 0,&rx_data); + SpiPs_write_read1(0x19B, ((B_delay>>8)&0x1),&rx_data); + SpiPs_write_read1(0x19C, B_delay&0xff,&rx_data); +} + +SpiPs_write_read1(0x196,0x10,&rx_data); +SpiPs_write_read1(0x153,0x00,&rx_data); +SpiPs_write_read1(0x02A,0x12,&rx_data); + +do{ +usleep(100); +SpiPs_write_read2(0x14D,0x00,&rx_data); +temp=rx_data&0x10; +}while (temp != 16); + +SpiPs_write_read1(0x02A,0x00,&rx_data); +SpiPs_write_read1(0x77E,0x00,&rx_data); +SpiPs_write_read1(0x000,0x02,&rx_data); +//Rx2 QECУ׼ +SpiPs_write_read1(0x02E,0x03,&rx_data); +SpiPs_write_read1(0x03F,0x26,&rx_data); +SpiPs_write_read1(0x040,0x78,&rx_data); +SpiPs_write_read1(0x77D,0x60,&rx_data); +SpiPs_write_read1(0x775,0x24,&rx_data); +SpiPs_write_read1(0x6C3,0x0A,&rx_data); +SpiPs_write_read1(0x61D,0x27,&rx_data); +SpiPs_write_read1(0x617,0x00,&rx_data); +SpiPs_write_read1(0x617,0x03,&rx_data); +usleep(100000); +SpiPs_write_read1(0x61D,0x37,&rx_data); +SpiPs_write_read1(0x686,0x81,&rx_data); +SpiPs_write_read1(0x683,0x36,&rx_data); +SpiPs_write_read1(0xB30,0x00,&rx_data); +SpiPs_write_read1(0xB31,0x87,&rx_data); +SpiPs_write_read1(0xB32,0x04,&rx_data); +SpiPs_write_read1(0xB33,0x44,&rx_data); +SpiPs_write_read1(0xB34,0x44,&rx_data); +SpiPs_write_read1(0x680,0x0C,&rx_data); +SpiPs_write_read1(0x681,0x30,&rx_data); +SpiPs_write_read1(0x682,0x0C,&rx_data); +SpiPs_write_read1(0x690,0x0B,&rx_data); +SpiPs_write_read1(0x683,0x26,&rx_data); +SpiPs_write_read1(0x67D,0x00,&rx_data); +SpiPs_write_read1(0x67D,0x03,&rx_data); +usleep(100000); +SpiPs_write_read1(0x683,0x36,&rx_data); +SpiPs_write_read1(0x000,0x22,&rx_data); +SpiPs_write_read1(0x77E,0x0A,&rx_data); +SpiPs_write_read1(0x11B,0x01,&rx_data); +SpiPs_write_read1(0x11E,0x01,&rx_data); +SpiPs_write_read1(0x164,0x00,&rx_data); +SpiPs_write_read1(0x165,0x00,&rx_data); +SpiPs_write_read1(0x166,0x00,&rx_data); +SpiPs_write_read1(0x167,0x00,&rx_data); +SpiPs_write_read1(0x168,0x00,&rx_data); +SpiPs_write_read1(0x169,0x00,&rx_data); +SpiPs_write_read1(0x161,0x00,&rx_data); +SpiPs_write_read1(0x162,0x00,&rx_data); +SpiPs_write_read1(0x162,0x01,&rx_data); +SpiPs_write_read1(0x161,0x01,&rx_data); +SpiPs_write_read1(0x706,0x65,&rx_data); +SpiPs_write_read1(0x6C3,0x00,&rx_data); +SpiPs_write_read1(0x75F,0x7D,&rx_data); +SpiPs_write_read1(0x11F,0x73,&rx_data); +SpiPs_write_read1(0x153,0x00,&rx_data); +SpiPs_write_read1(0x724,0x24,&rx_data); +SpiPs_write_read1(0x196,0x01,&rx_data); +SpiPs_write_read1(0x02B,0x12,&rx_data); + +do{ +usleep(100); +SpiPs_write_read2(0x14D,0x00,&rx_data); +temp=rx_data&0x10; +}while (temp != 16); + +SpiPs_write_read1(0x02B,0x00,&rx_data); +SpiPs_write_read1(0x196,0x11,&rx_data); +SpiPs_write_read2(0x13D,0x00,&rx_data); +r13D = rx_data; +SpiPs_write_read2(0x13E,0x00,&rx_data); +r13E = rx_data; + +B = r13D * 256 + r13E; +B_s = B - (B >= 32768) * 65536; +B_abs = abs(B_s); +B_b = (unsigned short)B_abs; +B_delay = (B_b>>6) & 0x1ff; + +if(B_s > 0) +{ + SpiPs_write_read1(0x199, ((B_delay>>8)&0x1),&rx_data); + SpiPs_write_read1(0x19A, B_delay&0xff,&rx_data); + SpiPs_write_read1(0x19B, 0,&rx_data); + SpiPs_write_read1(0x19C, 0,&rx_data); +} +else +{ + SpiPs_write_read1(0x199, 0,&rx_data); + SpiPs_write_read1(0x19A, 0,&rx_data); + SpiPs_write_read1(0x19B, ((B_delay>>8)&0x1),&rx_data); + SpiPs_write_read1(0x19C, B_delay&0xff,&rx_data); +} + +SpiPs_write_read1(0x196,0x10,&rx_data); +SpiPs_write_read1(0x153,0x00,&rx_data); +SpiPs_write_read1(0x02B,0x12,&rx_data); + +do{ +usleep(100); +SpiPs_write_read2(0x14D,0x00,&rx_data); +temp=rx_data&0x10; +}while (temp != 16); + +SpiPs_write_read1(0x02B,0x00,&rx_data); +SpiPs_write_read1(0x77E,0x00,&rx_data); +SpiPs_write_read1(0x000,0x02,&rx_data); +//»ָ´У׼Öб»¸ıäµÄÅäÖà +SpiPs_write_read1(0x000,0x02,&rx_data); +SpiPs_write_read1(0x02E,0x03,&rx_data); +SpiPs_write_read1(0x109,0x11,&rx_data); +SpiPs_write_read1(0x10A,0x70,&rx_data); +SpiPs_write_read1(0x11B,0x00,&rx_data); +SpiPs_write_read1(0x11E,0x00,&rx_data); +SpiPs_write_read1(0x11F,0x33,&rx_data); +SpiPs_write_read1(0x128,0x10,&rx_data); +SpiPs_write_read1(0x161,0x00,&rx_data); +SpiPs_write_read1(0x162,0x00,&rx_data); +SpiPs_write_read1(0x164,0x00,&rx_data); +SpiPs_write_read1(0x165,0x00,&rx_data); +SpiPs_write_read1(0x166,0x00,&rx_data); +SpiPs_write_read1(0x167,0x00,&rx_data); +SpiPs_write_read1(0x168,0x00,&rx_data); +SpiPs_write_read1(0x169,0x00,&rx_data); +SpiPs_write_read1(0x6C3,0x00,&rx_data); +SpiPs_write_read1(0x775,0x24,&rx_data); +SpiPs_write_read1(0x77D,0xCF,&rx_data); +SpiPs_write_read1(0xA07,0x00,&rx_data); +SpiPs_write_read1(0xA08,0x00,&rx_data); +SpiPs_write_read1(0xA16,0x00,&rx_data); +SpiPs_write_read1(0xA17,0x00,&rx_data); +SpiPs_write_read1(0xA18,0x00,&rx_data); +SpiPs_write_read1(0xA19,0x00,&rx_data); +SpiPs_write_read1(0xA1A,0x00,&rx_data); +SpiPs_write_read1(0xA1B,0x00,&rx_data); +SpiPs_write_read1(0x686,0x91,&rx_data); +SpiPs_write_read1(0x683,0x36,&rx_data); +SpiPs_write_read1(0xB30,0x00,&rx_data); +SpiPs_write_read1(0xB31,0xDA,&rx_data); +SpiPs_write_read1(0xB32,0xC0,&rx_data); +SpiPs_write_read1(0xB33,0x00,&rx_data); +SpiPs_write_read1(0xB34,0x00,&rx_data); +SpiPs_write_read1(0x680,0x0C,&rx_data); +SpiPs_write_read1(0x681,0x30,&rx_data); +SpiPs_write_read1(0x682,0x08,&rx_data); +SpiPs_write_read1(0x690,0x0B,&rx_data); +//TXУ׼ +SpiPs_write_read1(0x03F,0x27,&rx_data); +SpiPs_write_read1(0x040,0xF8,&rx_data); +SpiPs_write_read1(0x61D,0x27,&rx_data); +SpiPs_write_read1(0x617,0x00,&rx_data); +SpiPs_write_read1(0x617,0x03,&rx_data); +usleep(100000); +SpiPs_write_read1(0x61D,0x37,&rx_data); +SpiPs_write_read1(0x02E,0x03,&rx_data); +SpiPs_write_read1(0x128,0x11,&rx_data); +SpiPs_write_read1(0x11E,0x01,&rx_data); +SpiPs_write_read1(0x77E,0x24,&rx_data); +SpiPs_write_read1(0x11F,0x01,&rx_data); +SpiPs_write_read1(0x121,0x02,&rx_data); +SpiPs_write_read1(0x11B,0x01,&rx_data); +SpiPs_write_read1(0x161,0x01,&rx_data); +SpiPs_write_read1(0x162,0x01,&rx_data); +SpiPs_write_read1(0x163,0x00,&rx_data); +SpiPs_write_read1(0x164,0x04,&rx_data); +SpiPs_write_read1(0x165,0x00,&rx_data); +SpiPs_write_read1(0x166,0x00,&rx_data); +SpiPs_write_read1(0x167,0x00,&rx_data); +SpiPs_write_read1(0x168,0x00,&rx_data); +SpiPs_write_read1(0x169,0x00,&rx_data); +SpiPs_write_read1(0xA2D,0x02,&rx_data); +SpiPs_write_read1(0xA07,0x00,&rx_data); +SpiPs_write_read1(0xA08,0x0F,&rx_data); +SpiPs_write_read1(0xA1C,0x01,&rx_data); +SpiPs_write_read1(0xA16,0x20,&rx_data); +SpiPs_write_read1(0xA17,0x00,&rx_data); +SpiPs_write_read1(0xA18,0x00,&rx_data); +SpiPs_write_read1(0xA19,0x00,&rx_data); +SpiPs_write_read1(0xA1A,0x00,&rx_data); +SpiPs_write_read1(0xA1B,0x00,&rx_data); +SpiPs_write_read1(0x102,0x0F,&rx_data); +SpiPs_write_read1(0x102,0xFF,&rx_data); +SpiPs_write_read1(0x186,0x00,&rx_data); +SpiPs_write_read1(0x186,0x01,&rx_data); +SpiPs_write_read1(0x763,0x34,&rx_data); +SpiPs_write_read1(0x76D,0x34,&rx_data); +SpiPs_write_read1(0x101,0xEF,&rx_data); +SpiPs_write_read1(0x101,0xFF,&rx_data); +SpiPs_write_read1(0x800,0x00,&rx_data); +SpiPs_write_read1(0x81A,0xF7,&rx_data); +SpiPs_write_read1(0x81B,0x34,&rx_data); +SpiPs_write_read1(0x81C,0x33,&rx_data); +SpiPs_write_read1(0x81D,0x12,&rx_data); +SpiPs_write_read1(0x81E,0x00,&rx_data); +SpiPs_write_read1(0x81F,0xFF,&rx_data); +SpiPs_write_read1(0x820,0x00,&rx_data); +SpiPs_write_read1(0x821,0xFF,&rx_data); +SpiPs_write_read1(0x800,0x80,&rx_data); +usleep(100000); +SpiPs_write_read1(0x800,0x81,&rx_data); +usleep(100000); +SpiPs_write_read1(0x77E,0x00,&rx_data); +SpiPs_write_read1(0x77E,0x24,&rx_data); +SpiPs_write_read1(0x11F,0x03,&rx_data); +SpiPs_write_read1(0x121,0x02,&rx_data); +SpiPs_write_read1(0x11B,0x01,&rx_data); +SpiPs_write_read1(0x11E,0x01,&rx_data); +SpiPs_write_read1(0x161,0x01,&rx_data); +SpiPs_write_read1(0x162,0x01,&rx_data); +SpiPs_write_read1(0x164,0x04,&rx_data); +SpiPs_write_read1(0x165,0x00,&rx_data); +SpiPs_write_read1(0x166,0x00,&rx_data); +SpiPs_write_read1(0x167,0x00,&rx_data); +SpiPs_write_read1(0x168,0x00,&rx_data); +SpiPs_write_read1(0x169,0x00,&rx_data); +SpiPs_write_read1(0xA2D,0x02,&rx_data); +SpiPs_write_read1(0xA07,0x00,&rx_data); +SpiPs_write_read1(0xA08,0x0F,&rx_data); +SpiPs_write_read1(0xA1C,0x01,&rx_data); +SpiPs_write_read1(0xA16,0x10,&rx_data); +SpiPs_write_read1(0xA17,0x00,&rx_data); +SpiPs_write_read1(0xA18,0x00,&rx_data); +SpiPs_write_read1(0xA19,0x00,&rx_data); +SpiPs_write_read1(0xA1A,0x00,&rx_data); +SpiPs_write_read1(0xA1B,0x00,&rx_data); +SpiPs_write_read1(0x81A,0xF7,&rx_data); +SpiPs_write_read1(0x81B,0x44,&rx_data); +SpiPs_write_read1(0x81C,0x33,&rx_data); +SpiPs_write_read1(0x81D,0x14,&rx_data); +SpiPs_write_read1(0x800,0x80,&rx_data); +SpiPs_write_read1(0x800,0x82,&rx_data); +usleep(100000); +SpiPs_write_read1(0x77E,0x00,&rx_data); +//»ָ´У׼Öб»¸ıäµÄÅäÖà +SpiPs_write_read1(0x000,0x02,&rx_data); +SpiPs_write_read1(0x02E,0x03,&rx_data); +SpiPs_write_read1(0x109,0x11,&rx_data); +SpiPs_write_read1(0x10A,0x70,&rx_data); +SpiPs_write_read1(0x11B,0x00,&rx_data); +SpiPs_write_read1(0x11E,0x00,&rx_data); +SpiPs_write_read1(0x11F,0x33,&rx_data); +SpiPs_write_read1(0x128,0x10,&rx_data); +SpiPs_write_read1(0x161,0x00,&rx_data); +SpiPs_write_read1(0x162,0x00,&rx_data); +SpiPs_write_read1(0x164,0x00,&rx_data); +SpiPs_write_read1(0x165,0x00,&rx_data); +SpiPs_write_read1(0x166,0x00,&rx_data); +SpiPs_write_read1(0x167,0x00,&rx_data); +SpiPs_write_read1(0x168,0x00,&rx_data); +SpiPs_write_read1(0x169,0x00,&rx_data); +SpiPs_write_read1(0x6C3,0x00,&rx_data); +SpiPs_write_read1(0x775,0x24,&rx_data); +SpiPs_write_read1(0x77D,0xCF,&rx_data); +SpiPs_write_read1(0xA07,0x00,&rx_data); +SpiPs_write_read1(0xA08,0x00,&rx_data); +SpiPs_write_read1(0xA16,0x00,&rx_data); +SpiPs_write_read1(0xA17,0x00,&rx_data); +SpiPs_write_read1(0xA18,0x00,&rx_data); +SpiPs_write_read1(0xA19,0x00,&rx_data); +SpiPs_write_read1(0xA1A,0x00,&rx_data); +SpiPs_write_read1(0xA1B,0x00,&rx_data); +//Pll1Ëø¶¨ +SpiPs_write_read1(0x61D,0x27,&rx_data); +SpiPs_write_read1(0x617,0x00,&rx_data); +SpiPs_write_read1(0x617,0x03,&rx_data); +usleep(100000); +SpiPs_write_read1(0x61D,0x37,&rx_data); +//Pll1Ëø¶¨ ³ɹ¦ +//Pll2Ëø¶¨ +SpiPs_write_read1(0x63F,0x25,&rx_data); +SpiPs_write_read1(0x639,0x00,&rx_data); +SpiPs_write_read1(0x639,0x03,&rx_data); +usleep(100000); +SpiPs_write_read1(0x63F,0x35,&rx_data); +//Pll2Ëø¶¨ ³ɹ¦ +//Pll3Ëø¶¨ +SpiPs_write_read1(0x661,0x26,&rx_data); +SpiPs_write_read1(0x65B,0x00,&rx_data); +SpiPs_write_read1(0x65B,0x03,&rx_data); +usleep(100000); +SpiPs_write_read1(0x661,0x36,&rx_data); +//Pll3Ëø¶¨ ³ɹ¦ +//Pll4Ëø¶¨ +SpiPs_write_read1(0x683,0x26,&rx_data); +SpiPs_write_read1(0x67D,0x00,&rx_data); +SpiPs_write_read1(0x67D,0x03,&rx_data); +usleep(100000); +SpiPs_write_read1(0x683,0x36,&rx_data); +//Pll4Ëø¶¨ ³ɹ¦ +//Pll5Ëø¶¨ +SpiPs_write_read1(0x6A5,0x26,&rx_data); +SpiPs_write_read1(0x69F,0x00,&rx_data); +SpiPs_write_read1(0x69F,0x03,&rx_data); +usleep(100000); +SpiPs_write_read1(0x6A5,0x36,&rx_data); +//Pll5Ëø¶¨ ³ɹ¦ +//ÅäÖýӿÚ +SpiPs_write_read1(0x02E,0x05,&rx_data); +SpiPs_write_read1(0x003,0x33,&rx_data); +SpiPs_write_read1(0x200,0x01,&rx_data); +SpiPs_write_read1(0x201,0x3F,&rx_data); +SpiPs_write_read1(0x202,0x03,&rx_data); +SpiPs_write_read1(0x206,0x00,&rx_data); +SpiPs_write_read1(0x208,0x00,&rx_data); +SpiPs_write_read1(0x209,0x00,&rx_data); +SpiPs_write_read1(0x77F,0x00,&rx_data); +SpiPs_write_read1(0x780,0x33,&rx_data); +SpiPs_write_read1(0x781,0x6F,&rx_data); +//ÅäÖýáÊø + +SpiPs_write_read1(0x02E,0x04,&rx_data); +SpiPs_write_read1(0x780,0x00,&rx_data); + +SpiPs_write_read1(0x11F,0x00,&rx_data); +SpiPs_write_read1(0x11F,0x33,&rx_data); +////ÅäÖÃTx NCO BIST ON +//SpiPs_write_read1(0x11B,0x01,&rx_data); +//SpiPs_write_read1(0x11E,0x01,&rx_data); +//SpiPs_write_read1(0x161,0x01,&rx_data); +//SpiPs_write_read1(0x162,0x01,&rx_data); +////ÅäÖÃTx NCOƵÂÊ 1MHz +//SpiPs_write_read1(0x164,0x05,&rx_data); +//SpiPs_write_read1(0x165,0x55,&rx_data); +//SpiPs_write_read1(0x166,0x55,&rx_data); +//SpiPs_write_read1(0x167,0x55,&rx_data); +//SpiPs_write_read1(0x168,0x55,&rx_data); +//SpiPs_write_read1(0x169,0x55,&rx_data); +} diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_DEMO/download_bin.c b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_DEMO/download_bin.c new file mode 100644 index 0000000..53d5e8f --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_DEMO/download_bin.c @@ -0,0 +1,45 @@ +/* + * download_bin.c + * + * Created on: 2023Äê11ÔÂ23ÈÕ + * Author: cxlab + */ + +#include "xilinx_io.h" +#include "sleep.h" +void download_bin(void){ + +// int temp; + u8 rx_data; + u8 data[4]; + u32 buf; + u8 addr[2]; + int on = 1; + if (on) { + SpiPs_write_read1(0x071,0x26,&rx_data); + SpiPs_write_read1(0x236,0x0F,&rx_data); + SpiPs_write_read1(0x20A,0x01,&rx_data); + for(int i=0;i<15448;i++){ + addr[0]=(i>>8)&0xff; + addr[1]= i&0xff; + buf=rom_read((u8 *)&addr); + data[0]=buf>>24; + data[1]=(buf>>16)&0xff; + data[2]=(buf>>8)&0xff; + data[3]=buf&0xff; + for(int j=0;j<4;j++){ + SpiPs_write_read1(0x070,data[j],&rx_data); +// SpiPs_write_read2(0x070,0x00,&rx_data); +// temp=rx_data; + } + if(i==15447){ + xil_printf("bin download completely"); + } + + } + } + else { + SpiPs_write_read1(0x071,0x00,&rx_data); + } + +} diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_DEMO/echo.c b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_DEMO/echo.c new file mode 100644 index 0000000..9a5462d --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_DEMO/echo.c @@ -0,0 +1,461 @@ +/* + * Copyright (C) 2016 - 2018 Xilinx, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + */ + +#include +#include + +#include "lwip/sockets.h" +#include "netif/xadapter.h" +#include "lwipopts.h" +#include "xil_printf.h" +#include "FreeRTOS.h" +#include "task.h" +#include "xilinx_io.h" + +#define THREAD_STACKSIZE 1024 +#define ACK 0x01 +u16_t echo_port = 7; +//#define RECV_BUF_SIZE 65536*16*8 +#define RECV_BUF_SIZE 1024 +//char recv_buf[RECV_BUF_SIZE]; +char recv_buf[1024]; +char recv_buf_temp[3]; +char trans_buf[8192*5]; +struct spi_stack spistack; + + +u16 hop_cnt = 0; + +void print_echo_app_header() +{ + xil_printf("%20s %6d %s\r\n", "echo server", + echo_port, + "$ telnet 7"); + +} + + +enum { + CMD_VER = 0, + CMD_RST = 1, + CMD_SPI_WRI = 2 , + CMD_SPI_READ = 3, + CMD_DATA_CAPTURE0 = 4, + CMD_WAVE_DOWNLOAD = 5, + CMD_PIN_SET = 6, + CMD_DATA_CAPTURE1 = 8, + CMD_DATA_CAPTURE2 = 9, + CMD_STACK_OUT = 10, + CMD_hopping = 11, + CMD_qecbin = 12, + CMD_cx9261a_config = 13, + CMD_cx3e04_config = 14, + CMD_cx3e04_SPI_WRI = 15 , + CMD_cx3e04_SPI_READ = 16, + CMD_IMAGE_UPDATE = 22, +}; +/* thread spawned for each connection */ +void process_echo_request(void *p) +{ + int sd = (int)p; + int status; + int n, nwrote,send_n,total_send; + u8 rx_data; + u32 capture_length; + u8 pin; + u8 pin_value; + char FPGA_SDK_IP[]="FPGA:20240315-SDK:20231122"; + spistack.spi_write_num = 0; + while (1) { + /* read a max of RECV_BUF_SIZE bytes from socket */ + if ((n = read(sd, recv_buf, 5)) < 0) { + xil_printf("%s: error reading from socket %d, closing socket\r\n", __FUNCTION__, sd); + break; + } + + /* break if the recved message = "quit" */ + if (!strncmp(recv_buf, "quit", 4)) + break; + + /* break if client closed connection */ + if (n <= 0) + break; + + else{/* excute cmd if recved message = "cmd"*/ + n=0; + if (!strncmp(recv_buf, "cmd ", 4)){ +// xil_printf("%d %d %d %d.\r\n", recv_buf[0],recv_buf[1],recv_buf[2],recv_buf[4]); + dbg_printf("Rece %d bytes.\r\n",n); + switch(recv_buf[4]){ + case CMD_IMAGE_UPDATE: + { + + u32 offset; + u32 image_size; + recv_buf[0] = ACK; + nwrote = write(sd, recv_buf, 1); + n = read(sd, recv_buf, RECV_BUF_SIZE); + + offset = *(u32 *)recv_buf; + image_size = *(u32 *)(recv_buf + 4); + xil_printf("offset is 0x%x image_size is 0x%x.\n", offset, image_size); + + void *image_ptr = (void *)0x30000000; + u32 LengthBytes; + write(sd, recv_buf, 1); // ask for image data + //// receive flash image to ddr + LengthBytes = 0; + while (LengthBytes < image_size) + { + n = read(sd, image_ptr + LengthBytes, RECV_BUF_SIZE); + // xil_printf("read %d bytes.\n",n); + LengthBytes = LengthBytes + n; + } + + // image data sumcheck + + // program image data into flash + //QspiStore( (u32) image_ptr, offset, image_size); + //xil_printf("flash program done.\n", n); + status = FfsSdWrite(image_ptr, image_size); + write(sd, recv_buf, 1); // send done + xil_printf("sd program done.\n", n); + n = 0; + break; + } + + case CMD_VER: + dbg_printf("Version:FPGA_20240315;SDK_20231122;IP_192.168.1.99.\r\n"); + n=26; + for(int i=0;i<26;i++){ + recv_buf[i] = FPGA_SDK_IP[i]; + } + break; + case CMD_RST: + dbg_printf("Rece cmd excute rst.\r\n"); + GpioSetPinDir(NRST,GPIO_DIR_OUTPUT); + DeviceRst(); + break; + + case CMD_STACK_OUT: + dbg_printf("Rece cmd STACK OUT.\r\n"); + spi_stack_out(&spistack); + n=1; + recv_buf[0] = 0x55; + break; + case CMD_SPI_WRI: + read(sd, &recv_buf[5], 3); + dbg_printf("Rece cmd excute spi write.\r\n"); + dbg_printf("ADDR 0x%x DATA 0x%x.\r\n",recv_buf[5]*256+recv_buf[6]-32768,recv_buf[7]); +// SpiPs_write_read((u8 *)&recv_buf[5],&rx_data); + status = spi_stack_in((u8 *)&recv_buf[5],&spistack); + if(status){//when memory is near full,start spi write + spi_stack_out(&spistack); + } +// n=1; +// recv_buf[0] = rx_data; + break; + case CMD_SPI_READ: + read(sd, &recv_buf[5], 3); + dbg_printf("Rece cmd excute spi read.\r\n"); + dbg_printf("ADDR 0x%x DATA 0x%x.\r\n",recv_buf[5]*256+recv_buf[6],recv_buf[7]); + SpiPs_write_read((u8 *)&recv_buf[5],&rx_data); + n=1; + recv_buf[0] = rx_data; + break; + case CMD_DATA_CAPTURE0: + read(sd, &recv_buf[5], 4); + capture_length = *((u32 *) &recv_buf[5]);//num of sample + dbg_printf("Rece cmd excute %d sample data capture.\r\n",capture_length); + XAxiDmaCapture(xAxiDma0Get(),capture_length); + n = capture_length*8; + total_send = 0; + /* handle request */ + while(n>0){ + if(n>1024) + send_n = 1024; + else + send_n = n; + n= n-send_n; + memcpy(recv_buf,TX_BUFFER_BASE + total_send,send_n); + total_send = total_send + send_n; + if ((nwrote = write(sd, &recv_buf, send_n)) < 0) { + xil_printf("%s: ERROR responding to client echo request. received = %d, written = %d\r\n",__FUNCTION__, n, nwrote); + xil_printf("Closing socket %d\r\n", sd); + break; + } + else{ + if(send_n!=nwrote){ + xil_printf("%d Bytes Send %d.\r\n", send_n,nwrote); + } + } + } + dbg_printf("Send %d bytes.\r\n",n); + break; + case CMD_DATA_CAPTURE1: + read(sd, &recv_buf[5], 4); + capture_length = *((u32 *) &recv_buf[5]);//num of sample + dbg_printf("Rece cmd excute %d sample data capture.\r\n",capture_length); + XAxiDmaCapture(xAxiDma1Get(),capture_length); + n = capture_length*8; + total_send = 0; + /* handle request */ + while(n>0){ + if(n>1024) + send_n = 1024; + else + send_n = n; + n= n-send_n; + + memcpy(recv_buf,TX_BUFFER_BASE + total_send,send_n); + total_send = total_send + send_n; + if ((nwrote = write(sd, &recv_buf, send_n)) < 0) { + xil_printf("%s: ERROR responding to client echo request. received = %d, written = %d\r\n",__FUNCTION__, n, nwrote); + xil_printf("Closing socket %d\r\n", sd); + break; + } + else{ + if(send_n!=nwrote){ + xil_printf("%d Bytes Send %d.\r\n", send_n,nwrote); + } + } + } + dbg_printf("Send %d bytes.\r\n",n); + break; + case CMD_DATA_CAPTURE2: + read(sd, &recv_buf[5], 4); + capture_length = *((u32 *) &recv_buf[5]);//num of sample + dbg_printf("Rece cmd excute %d sample data capture.\r\n",capture_length); + XAxiDmaCapture(xAxiDma2Get(),capture_length); + n = capture_length*8; + total_send = 0; + /* handle request */ + while(n>0){ + if(n>1024) + send_n = 1024; + else + send_n = n; + n= n-send_n; + memcpy(recv_buf,TX_BUFFER_BASE + total_send,send_n); + total_send = total_send + send_n; + if ((nwrote = write(sd, &recv_buf, send_n)) < 0) { + xil_printf("%s: ERROR responding to client echo request. received = %d, written = %d\r\n",__FUNCTION__, n, nwrote); + xil_printf("Closing socket %d\r\n", sd); + break; + } + else{ + if(send_n!=nwrote){ + xil_printf("%d Bytes Send %d.\r\n", send_n,nwrote); + } + } + } + dbg_printf("Send %d bytes.\r\n",n); + break; + case CMD_WAVE_DOWNLOAD: + dbg_printf("Rece cmd excute wave download.\r\n"); + while(n0){ + if(n>1024) + send_n = 1024; + else + send_n = n; + n= n-send_n; + total_send = total_send + send_n; + memcpy(recv_buf,TX_BUFFER_BASE + total_send,send_n); + if ((nwrote = write(sd, &recv_buf, send_n)) < 0) { + xil_printf("%s: ERROR responding to client echo request. received = %d, written = %d\r\n", + __FUNCTION__, n, nwrote); + xil_printf("Closing socket %d\r\n", sd); + break; + } + else{ + if(send_n!=nwrote){ + xil_printf("%d Bytes Send %d.\r\n", send_n,nwrote); + } + } + } + dbg_printf("Send %d bytes.\r\n",n); + }*/ + + } + } + /* handle request */ + if ((nwrote = write(sd, recv_buf, n)) < 0) { + xil_printf("%s: ERROR responding to client echo request. received = %d, written = %d\r\n", + __FUNCTION__, n, nwrote); + xil_printf("Closing socket %d\r\n", sd); + break; + } + else{ + if(n!=nwrote){ + xil_printf("%d Bytes Send %d.\r\n", n,nwrote); + } + } + } + + /* close connection */ + close(sd); + vTaskDelete(NULL); +} + +void echo_application_thread() +{ + int sock, new_sd; + int size; +#if LWIP_IPV6==0 + struct sockaddr_in address, remote; + + memset(&address, 0, sizeof(address)); + + if ((sock = lwip_socket(AF_INET, SOCK_STREAM, 0)) < 0) + return; + + address.sin_family = AF_INET; + address.sin_port = htons(echo_port); + address.sin_addr.s_addr = INADDR_ANY; +#else + struct sockaddr_in6 address, remote; + + memset(&address, 0, sizeof(address)); + + address.sin6_len = sizeof(address); + address.sin6_family = AF_INET6; + address.sin6_port = htons(echo_port); + + memset(&(address.sin6_addr), 0, sizeof(address.sin6_addr)); + + if ((sock = lwip_socket(AF_INET6, SOCK_STREAM, 0)) < 0) + return; +#endif + + if (lwip_bind(sock, (struct sockaddr *)&address, sizeof (address)) < 0) + return; + + lwip_listen(sock, 0); + + size = sizeof(remote); + + while (1) { + if ((new_sd = lwip_accept(sock, (struct sockaddr *)&remote, (socklen_t *)&size)) > 0) { + sys_thread_new("echos", process_echo_request, + (void*)new_sd, + THREAD_STACKSIZE, + DEFAULT_THREAD_PRIO); + } + } +} diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_DEMO/frqhop_config.c b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_DEMO/frqhop_config.c new file mode 100644 index 0000000..2f18e03 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_DEMO/frqhop_config.c @@ -0,0 +1,58 @@ +/* + * frqhop_config.c + * + * Created on: 2023Äê11ÔÂ24ÈÕ + * Author: cxlab + */ + +#include "xilinx_io.h" +#include "sleep.h" +#include "time.h" +#include "xtime_l.h" +#include "math.h" +#include + +void frqhop_config(int hop_flag){ + XTime tCur; + XTime_GetTime(&tCur); + srand(tCur); + double hop_freq = (rand()%(800-30))+30+(rand()%(101))/(double)100;//Ëæ»ú²úÉú[30,800)doubleÀàÐ͵ÄÊý +// double hop_freq = 400.52; + double hop_freq1 = 800.25; + static int pll_index=1; + static int unlock_pll1_cnt=0,unlock_pll2_cnt=0; + if(hop_freq == hop_freq1){ + if(pll_index == 2){ + pll_index = 4; + } + else if(pll_index == 1){ + pll_index = 3; + } + } + if(hop_flag == 1){ + if(pll_index == 1 || pll_index == 3){ + //Çл»ÖÁpll2À´Դ + GpioSetPinDir(hop,GPIO_DIR_OUTPUT); + GpioWritePin(hop,0x01); + trx_ch_pll_config(2); + GpioWritePin(hop,0x00); + //ÅäÖÃpll1²ÎÊý + unlock_pll1_cnt=PLL_config(1,hop_freq)-1; + pll_index = 2; + } + else if(pll_index == 2 || pll_index == 4){ + //Çл»ÖÁpll1À´Դ + GpioSetPinDir(hop,GPIO_DIR_OUTPUT); + GpioWritePin(hop,0x01); + trx_ch_pll_config(1); + GpioWritePin(hop,0x00); + //ÅäÖÃpll2²ÎÊý + unlock_pll2_cnt=PLL_config(2,hop_freq)-1; + pll_index = 1; + } + } + hop_freq1 = hop_freq; + if(unlock_pll2_cnt!=0 || unlock_pll1_cnt !=0){ + xil_printf("pll1 unlock num: %d; pll2 unlock num: %d;.\n", unlock_pll1_cnt, unlock_pll2_cnt); + } +} diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_DEMO/iic_phyreset.c b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_DEMO/iic_phyreset.c new file mode 100644 index 0000000..9d13181 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_DEMO/iic_phyreset.c @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2016 - 2018 Xilinx, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + */ + +#include + +#include "xparameters.h" +#if defined (__arm__) || defined(__aarch64__) +#include "xil_printf.h" +#endif + +#ifdef XPS_BOARD_ZCU102 +#ifdef XPAR_XIICPS_0_DEVICE_ID +#include "xiicps.h" + +#define BUF_LEN 10U + +#define IOEXPANDER1_ADDR 0x20U + +#define IIC_SCLK_RATE_IOEXP 400000 + +#define CMD_CFG_0_REG 0x06U +#define CMD_OUTPUT_0_REG 0x02U +#define DATA_OUTPUT 0x0U + +#define DATA_COMMON_CFG 0xE0U +#define DATA_GT_0000_CFG 0x00U + +XIicPs I2c0InstancePtr; + +int IicPhyReset(void) +{ + + u8 WriteBuffer[BUF_LEN] = {0}; + XIicPs_Config *I2c0CfgPtr; + int Status = XST_SUCCESS; + + /* Initialize the IIC0 driver so that it is ready to use */ + I2c0CfgPtr = XIicPs_LookupConfig(XPAR_XIICPS_0_DEVICE_ID); + if (I2c0CfgPtr == NULL) { + Status = XST_FAILURE; + return Status; + } + + Status = XIicPs_CfgInitialize(&I2c0InstancePtr, I2c0CfgPtr, + I2c0CfgPtr->BaseAddress); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + return Status; + } + + /* Set the IIC serial clock rate */ + XIicPs_SetSClk(&I2c0InstancePtr, IIC_SCLK_RATE_IOEXP); + + /* Configure I/O pins as Output */ + WriteBuffer[0] = CMD_CFG_0_REG; + WriteBuffer[1] = DATA_OUTPUT; + Status = XIicPs_MasterSendPolled(&I2c0InstancePtr, + WriteBuffer, 2, IOEXPANDER1_ADDR); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + return Status; + } + + /* Wait until bus is idle to start another transfer */ + while (XIicPs_BusIsBusy(&I2c0InstancePtr)); + + /* + * Deasserting I2C_MUX_RESETB + * And GEM3 Resetb + * Selecting lanes based on configuration + */ + WriteBuffer[0] = CMD_OUTPUT_0_REG; + /* gt0000 or no GT configuration */ + WriteBuffer[1] = DATA_COMMON_CFG | DATA_GT_0000_CFG; + + /* Send the Data */ + Status = XIicPs_MasterSendPolled(&I2c0InstancePtr, + WriteBuffer, 2, IOEXPANDER1_ADDR); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + return Status; + } + + /* Wait until bus is idle */ + while (XIicPs_BusIsBusy(&I2c0InstancePtr)); + + xil_printf("IIC PHY reset on ZCU102 successful \n\r"); +} +#endif +#endif diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_DEMO/main.c b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_DEMO/main.c new file mode 100644 index 0000000..4b61222 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_DEMO/main.c @@ -0,0 +1,300 @@ +/* + * Copyright (C) 2016 - 2018 Xilinx, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + */ + +#include +#include "xparameters.h" +#include "netif/xadapter.h" +#include "platform_config.h" +#include "xil_printf.h" +#include "xilinx_io.h" +#include "FreeRTOS.h" +#include "queue.h" +#include "semphr.h" +#include "math.h" + +#if LWIP_IPV6==1 +#include "lwip/ip.h" +#else +#if LWIP_DHCP==1 +#include "lwip/dhcp.h" +#endif +#endif + +#ifdef XPS_BOARD_ZCU102 +#ifdef XPAR_XIICPS_0_DEVICE_ID +int IicPhyReset(void); +#endif +#endif + +int main_thread(); +void print_echo_app_header(); +void echo_application_thread(void *); + +void lwip_init(); + +#if LWIP_IPV6==0 +#if LWIP_DHCP==1 +extern volatile int dhcp_timoutcntr; +err_t dhcp_start(struct netif *netif); +#endif +#endif + +#define THREAD_STACKSIZE 1024 + +static struct netif server_netif; +struct netif *echo_netif; + +#if LWIP_IPV6==1 +void print_ip6(char *msg, ip_addr_t *ip) +{ + print(msg); + xil_printf(" %x:%x:%x:%x:%x:%x:%x:%x\n\r", + IP6_ADDR_BLOCK1(&ip->u_addr.ip6), + IP6_ADDR_BLOCK2(&ip->u_addr.ip6), + IP6_ADDR_BLOCK3(&ip->u_addr.ip6), + IP6_ADDR_BLOCK4(&ip->u_addr.ip6), + IP6_ADDR_BLOCK5(&ip->u_addr.ip6), + IP6_ADDR_BLOCK6(&ip->u_addr.ip6), + IP6_ADDR_BLOCK7(&ip->u_addr.ip6), + IP6_ADDR_BLOCK8(&ip->u_addr.ip6)); +} + +#else +void +print_ip(char *msg, ip_addr_t *ip) +{ + xil_printf(msg); + xil_printf("%d.%d.%d.%d\n\r", ip4_addr1(ip), ip4_addr2(ip), + ip4_addr3(ip), ip4_addr4(ip)); +} + +void +print_ip_settings(ip_addr_t *ip, ip_addr_t *mask, ip_addr_t *gw) +{ + + print_ip("Board IP: ", ip); + print_ip("Netmask : ", mask); + print_ip("Gateway : ", gw); +} + +#endif + +int main() +{ + xil_printf("start"); + + sys_thread_new("main_thrd", (void(*)(void*))main_thread, 0, + THREAD_STACKSIZE, + DEFAULT_THREAD_PRIO); + vTaskStartScheduler(); + + while(1); + + return 0; +} + +void network_thread(void *p) +{ + struct netif *netif; + /* the mac address of the board. this should be unique per board */ + unsigned char mac_ethernet_address[] = { 0x00, 0x0a, 0x35, 0x00, 0x01, 0x02 }; +#if LWIP_IPV6==0 + ip_addr_t ipaddr, netmask, gw; +#if LWIP_DHCP==1 + int mscnt = 0; +#endif +#endif + + netif = &server_netif; + + xil_printf("\r\n\r\n"); + xil_printf("-----lwIP Socket Mode CX9261 TEST server Application Version 2022.05.31------\r\n"); + +#if LWIP_IPV6==0 +#if LWIP_DHCP==0 + /* initliaze IP addresses to be used */ + IP4_ADDR(&ipaddr, 192, 168, 1, 99); + IP4_ADDR(&netmask, 255, 255, 255, 0); + IP4_ADDR(&gw, 192, 168, 1, 1); +#endif + + /* print out IP settings of the board */ + +#if LWIP_DHCP==0 + print_ip_settings(&ipaddr, &netmask, &gw); + /* print all application headers */ +#endif + +#if LWIP_DHCP==1 + ipaddr.addr = 0; + gw.addr = 0; + netmask.addr = 0; +#endif +#endif + +#if LWIP_IPV6==0 + /* Add network interface to the netif_list, and set it as default */ + if (!xemac_add(netif, &ipaddr, &netmask, &gw, mac_ethernet_address, PLATFORM_EMAC_BASEADDR)) { + xil_printf("Error adding N/W interface\r\n"); + return; + } +#else + /* Add network interface to the netif_list, and set it as default */ + if (!xemac_add(netif, NULL, NULL, NULL, mac_ethernet_address, PLATFORM_EMAC_BASEADDR)) { + xil_printf("Error adding N/W interface\r\n"); + return; + } + + netif->ip6_autoconfig_enabled = 1; + + netif_create_ip6_linklocal_address(netif, 1); + netif_ip6_addr_set_state(netif, 0, IP6_ADDR_VALID); + + print_ip6("\n\rBoard IPv6 address ", &netif->ip6_addr[0].u_addr.ip6); +#endif + + netif_set_default(netif); + + /* specify that the network if is up */ + netif_set_up(netif); + + /* start packet receive thread - required for lwIP operation */ + sys_thread_new("xemacif_input_thread", (void(*)(void*))xemacif_input_thread, netif, + THREAD_STACKSIZE, + DEFAULT_THREAD_PRIO); + +#if LWIP_IPV6==0 +#if LWIP_DHCP==1 + dhcp_start(netif); + while (1) { + vTaskDelay(DHCP_FINE_TIMER_MSECS / portTICK_RATE_MS); + dhcp_fine_tmr(); + mscnt += DHCP_FINE_TIMER_MSECS; + if (mscnt >= DHCP_COARSE_TIMER_SECS*1000) { + dhcp_coarse_tmr(); + mscnt = 0; + } + } +#else + xil_printf("\r\n"); + xil_printf("%20s %6s %s\r\n", "Server", "Port", "Connect With.."); + xil_printf("%20s %6s %s\r\n", "--------------------", "------", "--------------------"); + + print_echo_app_header(); + xil_printf("\r\n"); + sys_thread_new("echod", echo_application_thread, 0, + THREAD_STACKSIZE, + DEFAULT_THREAD_PRIO); + vTaskDelete(NULL); +#endif +#else + print_echo_app_header(); + xil_printf("\r\n"); + sys_thread_new("echod",echo_application_thread, 0, + THREAD_STACKSIZE, + DEFAULT_THREAD_PRIO); + vTaskDelete(NULL); +#endif + return; +} + +int main_thread() +{ +#if LWIP_DHCP==1 + int mscnt = 0; +#endif + +#ifdef XPS_BOARD_ZCU102 + IicPhyReset(); +#endif + + /* initialize lwIP before calling sys_thread_new */ + lwip_init(); + SpiPsInit(SPI_DEVICE_ID); + GpioInit(GPIO_DEVICE_ID); + AXIGpioInit(); + XScuGicInit(); + ConfigAXIGPIOIntr(); + ExceptionInit(); + + XAxiDma_Init(xAxiDma0Get(),AXI_DMA_DEVCIE_ID0); + XAxiDma_Init(xAxiDma1Get(),AXI_DMA_DEVCIE_ID1); + XAxiDma_Init(xAxiDma2Get(),AXI_DMA_DEVCIE_ID2); + PackerRst(); + + /* cx9261a configuration */ + peripheral_test(); + cx3e04_config(); +// cx9261a_710_config(); +// frqhop_config(1); + int temp = cx3e04_read(0x03A); + /* any thread using lwIP should be created using sys_thread_new */ + sys_thread_new("NW_THRD", network_thread, NULL, + THREAD_STACKSIZE, + DEFAULT_THREAD_PRIO); + +#if LWIP_IPV6==0 +#if LWIP_DHCP==1 + while (1) { + vTaskDelay(DHCP_FINE_TIMER_MSECS / portTICK_RATE_MS); + if (server_netif.ip_addr.addr) { + xil_printf("DHCP request success\r\n"); + print_ip_settings(&(server_netif.ip_addr), &(server_netif.netmask), &(server_netif.gw)); + print_echo_app_header(); + xil_printf("\r\n"); + sys_thread_new("echod", echo_application_thread, 0, + THREAD_STACKSIZE, + DEFAULT_THREAD_PRIO); + break; + } + mscnt += DHCP_FINE_TIMER_MSECS; + if (mscnt >= 10000) { + xil_printf("ERROR: DHCP request timed out\r\n"); + xil_printf("Configuring default IP of 192.168.1.100\r\n"); + IP4_ADDR(&(server_netif.ip_addr), 192, 168, 1, 100); + IP4_ADDR(&(server_netif.netmask), 255, 255, 255, 0); + IP4_ADDR(&(server_netif.gw), 192, 168, 1, 1); + print_ip_settings(&(server_netif.ip_addr), &(server_netif.netmask), &(server_netif.gw)); + /* print all application headers */ + xil_printf("\r\n"); + xil_printf("%20s %6s %s\r\n", "Server", "Port", "Connect With.."); + xil_printf("%20s %6s %s\r\n", "--------------------", "------", "--------------------"); + + print_echo_app_header(); + xil_printf("\r\n"); + sys_thread_new("echod", echo_application_thread, 0, + THREAD_STACKSIZE, + DEFAULT_THREAD_PRIO); + break; + } + } +#endif +#endif + vTaskDelete(NULL); + return 0; +} diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_DEMO/platform_config.h b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_DEMO/platform_config.h new file mode 100644 index 0000000..b84bf38 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_DEMO/platform_config.h @@ -0,0 +1,10 @@ +#ifndef __PLATFORM_CONFIG_H_ +#define __PLATFORM_CONFIG_H_ + + +#define PLATFORM_EMAC_BASEADDR XPAR_XEMACPS_0_BASEADDR + +#define PLATFORM_ZYNQ + + +#endif diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_DEMO/rx_wideband_qec.c b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_DEMO/rx_wideband_qec.c new file mode 100644 index 0000000..ec8b2f5 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_DEMO/rx_wideband_qec.c @@ -0,0 +1,61 @@ +/* + * wideband_qec.c + * + * Created on: 2023Äê11ÔÂ30ÈÕ + * Author: cxlab + */ + +#include "xilinx_io.h" +#include "sleep.h" +#include "math.h" +void rxFFTCalib(int lo, int fs,int ref, int firLength, int chan) { + u8 rx_data; + SpiPs_write_read1(0x000, chan == 1 ? 0x12 : 0x22,&rx_data); + SpiPs_write_read1(0x128, 0x00,&rx_data); + SpiPs_write_read1(0x11B, 0x01,&rx_data); + SpiPs_write_read1(0x11E, 0x01,&rx_data); + configTxNcoFreq(0, fs); + SpiPs_write_read1(0x161, 0x00,&rx_data); + SpiPs_write_read1(0x162, 0x00,&rx_data); + SpiPs_write_read1(0x162, 0x01,&rx_data); + SpiPs_write_read1(0x161, 0x01,&rx_data); + SpiPs_write_read1(0x000, chan == 1 ? 0x12 : chan == 2 ? 0x22 : 0x32,&rx_data); + SpiPs_write_read1(0x102, 0x03,&rx_data); + SpiPs_write_read1(0x102, 0xFF,&rx_data); + SpiPs_write_read1(0x15C, 0x00,&rx_data); + SpiPs_write_read1(0x160, 0x01,&rx_data); + SpiPs_write_read1(0x77E, chan == 1 ? 0x50 : chan == 2 ? 0x0A : 0x03,&rx_data); + SpiPs_write_read1(0x09B, 0x01,&rx_data); // TXPLL4 + SpiPs_write_read1(0x09D, firLength,&rx_data); + SpiPs_write_read1(0x096, ((u32)round(lo) >> 8) & 0xFF,&rx_data); + SpiPs_write_read1(0x097, (u32)round(lo) & 0xFF,&rx_data); + SpiPs_write_read1(0x098, ((u32)round(ref * 10) >> 8) & 0xFF,&rx_data); + SpiPs_write_read1(0x099, (u32)round(ref * 10) & 0xFF,&rx_data); + SpiPs_write_read1(0x09E, ((u32)round(fs * 100) >> 8) & 0xFF,&rx_data); + SpiPs_write_read1(0x09F, (u32)round(fs * 100) & 0xFF,&rx_data); + SpiPs_write_read1(0x09C, chan,&rx_data); + while (1) { + if (SpiPs_write_read2(0x0B3,0x00,&rx_data) == 5) + break; + usleep(10000); + } + SpiPs_write_read1(0x09C, 0x00,&rx_data); + SpiPs_write_read1(0x15C, 0x01,&rx_data); + SpiPs_write_read1(0x77E, 0x00,&rx_data); + + //ͨµÀʱÖÓÀ´Դ + u8 r77D=0xC0; + u8 r775=0x24; + u8 r6C3=0x00; + SpiPs_write_read1(0x77D, r77D,&rx_data); + SpiPs_write_read1(0x775, r775,&rx_data); + SpiPs_write_read1(0x6C3, r6C3,&rx_data); +} + + +void configDcCalib(int dcCalibEnable,int dcCalibLength) { + u8 rx_data; + SpiPs_write_read1(0x109, dcCalibEnable ? 0x11 : 0x00,&rx_data); + SpiPs_write_read1(0x10A, (dcCalibLength) << 4,&rx_data); + SpiPs_write_read1(0x11F, dcCalibEnable ? 0x33 : 0x73,&rx_data); +} diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_DEMO/sd.c b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_DEMO/sd.c new file mode 100644 index 0000000..111123b --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_DEMO/sd.c @@ -0,0 +1,178 @@ +#include "sd.h" +/************************** Variable Definitions *****************************/ +static FIL fil; /* File object */ +static FATFS fatfs; +/* + * To test logical drive 0, FileName should be "0:/" or + * "". For logical drive 1, FileName should be "1:/" + */ +static char FileName[32] = "BOOT.bin"; +static char *SD_File; + + +//#define BUFF_SIZE sizeof(image_data) +#define BUFF_SIZE 0x2000000 +#ifdef __ICCARM__ +#pragma data_alignment = 32 +u8 DestinationAddress[10*1024]; +#pragma data_alignment = 32 +u8 SourceAddress[10*1024]; +#else +//u8 DestinationAddress[10*1024] __attribute__ ((aligned(32))); +//u8 SourceAddress[10*1024] __attribute__ ((aligned(32))); + +u8 DestinationAddress[BUFF_SIZE] __attribute__ ((aligned(32))); +u8 SourceAddress[BUFF_SIZE] __attribute__ ((aligned(32))); +#endif + +#define TEST 7 + + + +/*****************************************************************************/ +/** +* +* File system example using SD driver to write to and read from an SD card +* in polled mode. This example creates a new file on an +* SD card (which is previously formatted with FATFS), write data to the file +* and reads the same data back to verify. +* +* @param None +* +* @return XST_SUCCESS if successful, otherwise XST_FAILURE. +* +* @note None +* +******************************************************************************/ +int FfsSdWrite(u8*image_data, u32 FileSize) +{ + int error_flag = 0; + FRESULT Res; + UINT NumBytesRead; + UINT NumBytesWritten; + u32 BuffCnt; + BYTE work[FF_MAX_SS]; +// u32 FileSize = (8*1024); +// u32 FileSize = sizeof(image_data); + /* + * To test logical drive 0, Path should be "0:/" + * For logical drive 1, Path should be "1:/" + */ + TCHAR *Path = "0:/"; + u8 checksum = 0; + + for(BuffCnt = 0; BuffCnt < FileSize; BuffCnt++){ +// SourceAddress[BuffCnt] = TEST + BuffCnt; + SourceAddress[BuffCnt] = image_data[BuffCnt]; + checksum = checksum + image_data[BuffCnt]; + } + xil_printf("checksum is 0x%x.",checksum); + + + /* + * Register volume work area, initialize device + */ + Res = f_mount(&fatfs, Path, 0); + + if (Res != FR_OK) { + return XST_FAILURE; + } + + /* + * Path - Path to logical driver, 0 - FDISK format. + * 0 - Cluster size is automatically determined based on Vol size. + */ + Res = f_mkfs(Path, FM_FAT32, 0, work, sizeof work); + if (Res != FR_OK) { + return XST_FAILURE; + } + + /* + * Open file with required permissions. + * Here - Creating new file with read/write permissions. . + * To open file with write permissions, file system should not + * be in Read Only mode. + */ + SD_File = (char *)FileName; + + Res = f_open(&fil, SD_File, FA_CREATE_ALWAYS | FA_WRITE | FA_READ); + if (Res) { + return XST_FAILURE; + } + + /* + * Pointer to beginning of file . + */ + Res = f_lseek(&fil, 0); + if (Res) { + return XST_FAILURE; + } + + /* + * Write data to file. + */ + Res = f_write(&fil, (const void*)SourceAddress, FileSize, + &NumBytesWritten); + if (Res) { + return XST_FAILURE; + } + /* + * Close file. + */ + Res = f_close(&fil); + if (Res) { + return XST_FAILURE; + } + Res = f_open(&fil, SD_File, FA_READ); + if (Res) { + return XST_FAILURE; + } + /* + * Pointer to beginning of file . + */ + Res = f_lseek(&fil, 0); + if (Res) { + return XST_FAILURE; + } + + /* + * Read data from file. + */ + Res = f_read(&fil, (void*)DestinationAddress, FileSize, + &NumBytesRead); + if (Res) { + return XST_FAILURE; + } + + /* + * Data verification + */ + for(BuffCnt = 0; BuffCnt < FileSize; BuffCnt++){ + if(SourceAddress[BuffCnt] != DestinationAddress[BuffCnt]){ +// return XST_FAILURE; + error_flag = 1; + xil_printf('Data check error.'); + } + } + + /* + * Close file. + */ + Res = f_close(&fil); + if (Res) { + return XST_FAILURE; + } + + if(error_flag){ + return XST_FAILURE; + } + +// Res = f_unmount(Path); +// if (Res) { +// return XST_FAILURE; +// } +// +// sleep(5); + + return XST_SUCCESS; +} diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_DEMO/sd.h b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_DEMO/sd.h new file mode 100644 index 0000000..91e744c --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_DEMO/sd.h @@ -0,0 +1,9 @@ +/***************************** Include Files *********************************/ +#include "xparameters.h" /* SDK generated parameters */ +#include "xsdps.h" /* SD device driver */ +#include "xil_printf.h" +#include "ff.h" +#include "xil_cache.h" +#include "xplatform_info.h" +/************************** Function Prototypes ******************************/ +int FfsSdWrite(u8*image_data, u32 FileSize); diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_DEMO/tx_bisection.c b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_DEMO/tx_bisection.c new file mode 100644 index 0000000..fd031b9 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_DEMO/tx_bisection.c @@ -0,0 +1,74 @@ +/* + * tx_bisection.c + * + * Created on: 2023Äê12ÔÂ1ÈÕ + * Author: cxlab + */ + + +#include "xilinx_io.h" +#include "sleep.h" +#include "math.h" + +void txBisectionQecCalib(int f0, int fs) { + u8 rx_data; + SpiPs_write_read1(0x02E, 0x03,&rx_data); + SpiPs_write_read1(0x128, 0x11,&rx_data); + SpiPs_write_read1(0x11E, 0x01,&rx_data); + SpiPs_write_read1(0x77E, 0x24,&rx_data); + SpiPs_write_read1(0x11F, 0x01,&rx_data); + SpiPs_write_read1(0x121, 0x02,&rx_data); + SpiPs_write_read1(0x11B, 0x01,&rx_data); + SpiPs_write_read1(0x161, 0x01,&rx_data); + SpiPs_write_read1(0x162, 0x01,&rx_data); + SpiPs_write_read1(0x163, 0x00,&rx_data); + configTxNcoFreq(f0, fs * 4); + SpiPs_write_read1(0xA2D, 0x02,&rx_data); + SpiPs_write_read1(0xA07, 0x00,&rx_data); + SpiPs_write_read1(0xA08, 0x0F,&rx_data); + SpiPs_write_read1(0xA1C, 0x01,&rx_data); + configRxNcoFreq(f0 * 2, fs); + SpiPs_write_read1(0x186, 0x01,&rx_data); + SpiPs_write_read1(0x763, 0x34,&rx_data); + SpiPs_write_read1(0x76D, 0x34,&rx_data); + SpiPs_write_read1(0x101, 0xEF,&rx_data); + SpiPs_write_read1(0x101, 0xFF,&rx_data); + SpiPs_write_read1(0x800, 0x00,&rx_data); + SpiPs_write_read1(0x81A, 0xF7,&rx_data); + SpiPs_write_read1(0x81B, 0x34,&rx_data); + SpiPs_write_read1(0x81C, 0x33,&rx_data); + SpiPs_write_read1(0x81D, 0x12,&rx_data); + SpiPs_write_read1(0x81E, 0x00,&rx_data); + SpiPs_write_read1(0x81F, 0xFF,&rx_data); + SpiPs_write_read1(0x820, 0x00,&rx_data); + SpiPs_write_read1(0x821, 0xFF,&rx_data); + SpiPs_write_read1(0x800, 0x80,&rx_data); + SpiPs_write_read1(0x800, 0x81,&rx_data); + usleep(100000); + SpiPs_write_read1(0x77E, 0x00,&rx_data); +} + +void txBisectionDcCalib(int f0, int fs) { + u8 rx_data; + SpiPs_write_read1(0x77E, 0x24,&rx_data); + SpiPs_write_read1(0x11F, 0x03,&rx_data); + SpiPs_write_read1(0x121, 0x02,&rx_data); + SpiPs_write_read1(0x11B, 0x01,&rx_data); + SpiPs_write_read1(0x11E, 0x01,&rx_data); + SpiPs_write_read1(0x161, 0x01,&rx_data); + SpiPs_write_read1(0x162, 0x01,&rx_data); + configTxNcoFreq(f0, fs * 4); + SpiPs_write_read1(0xA2D, 0x02,&rx_data); + SpiPs_write_read1(0xA07, 0x00,&rx_data); + SpiPs_write_read1(0xA08, 0x0F,&rx_data); + SpiPs_write_read1(0xA1C, 0x01,&rx_data); + configRxNcoFreq(f0, fs); + SpiPs_write_read1(0x81A, 0xF7,&rx_data); + SpiPs_write_read1(0x81B, 0x44,&rx_data); + SpiPs_write_read1(0x81C, 0x33,&rx_data); + SpiPs_write_read1(0x81D, 0x14,&rx_data); + SpiPs_write_read1(0x800, 0x80,&rx_data); + SpiPs_write_read1(0x800, 0x82,&rx_data); + usleep(500000); + SpiPs_write_read1(0x77E, 0x00,&rx_data); +} diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_DEMO/xilinx_io.c b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_DEMO/xilinx_io.c new file mode 100644 index 0000000..ef4637b --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_DEMO/xilinx_io.c @@ -0,0 +1,861 @@ +/* + * xilinx_io.c + * + * Created on: 2021Äê9ÔÂ6ÈÕ + * Author: cxlab + */ + + +#include "sleep.h" +#include "math.h" +#include "xilinx_io.h" /* SPI device driver */ + +static XSpiPs SpiInstance; +XGpioPs Gpio; /* The driver instance for GPIO Device. */ +XGpio axi_gpio_inst; //PL ¶Ë AXI GPIO Çý¶¯ʵÀý +XScuGic scugic_inst; //ÖжϿØÖÆÆ÷ Çý¶¯ʵÀý +XScuGic_Config * scugic_cfg_ptr; //ÖжϿØÖÆÆ÷ ÅäÖÃÐÅϢ +int hop_flag,hop_intr_flag; + +XAxiDma AxiDma0,AxiDma1,AxiDma2; + +XAxiDma* xAxiDma0Get(void){ + return &AxiDma0; +} + +XAxiDma* xAxiDma1Get(void){ + return &AxiDma1; +} + +XAxiDma* xAxiDma2Get(void){ + return &AxiDma2; +} +void AXIGpioInit(void){ + XGpio_Initialize(&axi_gpio_inst, AXI_GPIO_ID); + //ÅäÖà PL AXI GPIO + XGpio_SetDataDirection(&axi_gpio_inst, 1, 1); //ÉèÖà AXI GPIO ͨµÀ 1 ΪÊäÈë + XGpio_InterruptEnable(&axi_gpio_inst, KEY_MASK); //ʹÄÜͨµÀ 1 ÖжÏ + XGpio_InterruptGlobalEnable(&axi_gpio_inst); //ʹÄÜ AXI GPIO ȫ¾ÖÖжÏ +} + +void ConfigAXIGPIOIntr(void){ + //ÉèÖÃÖжÏÓÅÏȼ¶ºʹ¥·¢ÀàÐÍ(¸ߵçƽ´¥·¢) + XScuGic_SetPriorityTriggerType(&scugic_inst, GPIO_INT_ID, 0xA0, 0x1); + //¹ØÁªÖжÏ ID ºÍÖжϴ¦Àíº¯Êý + XScuGic_Connect(&scugic_inst, GPIO_INT_ID, axi_gpio_handler, &axi_gpio_inst); + //ʹÄÜ AXI GPIO ÖжÏ + XScuGic_Enable(&scugic_inst, GPIO_INT_ID); +} +void axi_gpio_handler(void *CallbackRef){ + XGpio *GpioPtr = (XGpio *)CallbackRef; + print("Interrupt Detected!\n"); + XGpio_InterruptDisable(GpioPtr, KEY_MASK); //¹رÕ AXI GPIO ÖжÏʹÄÜ + frqhop_config(hop_flag); + XGpio_InterruptClear(GpioPtr, KEY_MASK); //Çå³ýÖжÏ + XGpio_InterruptEnable(GpioPtr, KEY_MASK); //ʹÄÜ AXI GPIO ÖжÏ +} +void frqhop_flag(int frqhop_flag){ + u8 rx_data; + hop_flag = frqhop_flag; + GpioSetPinDir(hop,GPIO_DIR_OUTPUT); + GpioWritePin(hop,0x01); + SpiPs_write_read2(0x615,0x00,&rx_data); +} + +void ExceptionInit(void){ + //ÉèÖò¢´ò¿ªÖжÏÒ쳣´¦Àí¹¦ÄÜ + Xil_ExceptionInit(); + Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, (Xil_ExceptionHandler)XScuGic_InterruptHandler, &scugic_inst); + Xil_ExceptionEnable(); +} +void XScuGicInit(void){ + scugic_cfg_ptr = XScuGic_LookupConfig(SCUGIC_ID); + XScuGic_CfgInitialize(&scugic_inst, scugic_cfg_ptr, scugic_cfg_ptr->CpuBaseAddress); +} + +int SpiPsInit(u16 SpiDeviceId){ + int Status; + XSpiPs_Config *SpiConfig; + /* + * Initialize the SPI driver so that it's ready to use + */ + SpiConfig = XSpiPs_LookupConfig(SpiDeviceId); + if (NULL == SpiConfig) { + return XST_FAILURE; + } + Status = XSpiPs_CfgInitialize((&SpiInstance), SpiConfig, + SpiConfig->BaseAddress); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Perform a self-test to check hardware build + */ + Status = XSpiPs_SelfTest((&SpiInstance)); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + /* + * The SPI device is a slave by default and the clock phase + * have to be set according to its master. In this example, CPOL is set + * to quiescent high and CPHA is set to 1. + */ + + XSpiPs_SetOptions((&SpiInstance), (XSPIPS_CR_CPHA_MASK) | + XSPIPS_MASTER_OPTION | + XSPIPS_FORCE_SSELECT_OPTION); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + XSpiPs_SetClkPrescaler((&SpiInstance), XSPIPS_CLK_PRESCALE_8); + /* + * Set the Rx FIFO Threshold to the Max Data + */ +// XSpiPs_SetRXWatermark((&SpiInstance),MAX_DATA); + /* + * Enable the device. + */ + XSpiPs_Enable((&SpiInstance)); + +return XST_SUCCESS; +} + +int cx3e04_write(int addr , int value) +{ + Xil_Out32(AXI4_LITE_SPI_BASEADDR+addr*4,value); + return 1; +} + +int cx3e04_read(int addr) +{ + return Xil_In32(AXI4_LITE_SPI_BASEADDR+addr*4); +} + +void cx3e04_config(void) +{ + //³Çо¿Ƽ¼CX3E04 + //Common + cx3e04_write(0x000,0x12); + cx3e04_write(0x002,0x38); + cx3e04_write(0x038,0x01); + cx3e04_write(0x003,0x30); + cx3e04_write(0x039,0x00); + //CLK + //clk lvds en + cx3e04_write(0x011,0x7F); + cx3e04_write(0x012,0x34); + cx3e04_write(0x036,0x7F); + cx3e04_write(0x01A,0x4B); + cx3e04_write(0x013,0x04); + cx3e04_write(0x014,0x04); + cx3e04_write(0x004,0x00); + cx3e04_write(0x008,0x00); + cx3e04_write(0x009,0x00); + cx3e04_write(0x015,0x04); + cx3e04_write(0x016,0x04); + cx3e04_write(0x005,0x00); + cx3e04_write(0x00A,0x00); + cx3e04_write(0x00B,0x00); + cx3e04_write(0x017,0x04); + cx3e04_write(0x018,0x04); + cx3e04_write(0x006,0x00); + cx3e04_write(0x00C,0x00); + cx3e04_write(0x00D,0x00); + cx3e04_write(0x019,0x04); + cx3e04_write(0x007,0x00); + cx3e04_write(0x00E,0x00); + cx3e04_write(0x00F,0x00); + cx3e04_write(0x010,0x00); + cx3e04_write(0x029,0x00); + cx3e04_write(0x02A,0x00); + //SYNC + //sync lvds en + cx3e04_write(0x033,0x7F); + cx3e04_write(0x034,0x34); + cx3e04_write(0x035,0x7F); + cx3e04_write(0x032,0x03); + //sync inner div + cx3e04_write(0x03A,0x00); + cx3e04_write(0x03B,0x00); + cx3e04_write(0x03A,0x01); + cx3e04_write(0x03B,0xFF);//512·ÖƵ + cx3e04_write(0x03C,0x21); + cx3e04_write(0x03D,0x80); + cx3e04_write(0x02B,0x04); + cx3e04_write(0x02C,0x04); + cx3e04_write(0x01B,0x00); + cx3e04_write(0x01C,0x00); + cx3e04_write(0x022,0x00); + cx3e04_write(0x023,0x00); + cx3e04_write(0x02D,0x04); + cx3e04_write(0x02E,0x04); + cx3e04_write(0x01D,0x00); + cx3e04_write(0x01E,0x00); + cx3e04_write(0x024,0x00); + cx3e04_write(0x025,0x00); + cx3e04_write(0x02F,0x04); + cx3e04_write(0x030,0x04); + cx3e04_write(0x01F,0x00); + cx3e04_write(0x020,0x00); + cx3e04_write(0x026,0x00); + cx3e04_write(0x027,0x00); + cx3e04_write(0x031,0x04); + cx3e04_write(0x021,0x00); + cx3e04_write(0x028,0x00); + //ƫÖõçÁ÷ + cx3e04_write(0x040,0xFF); + cx3e04_write(0x041,0xFF); + cx3e04_write(0x042,0xFF); + cx3e04_write(0x043,0xF0); + cx3e04_write(0x044,0xFF); + cx3e04_write(0x045,0xFF); + cx3e04_write(0x046,0xFF); + cx3e04_write(0x047,0xF0); + //Others + cx3e04_write(0x037,0x07); +} + +//int SpiPs_write_read(u8 cmd, u16 addr,u8 data,u8 * rx_data){ +int SpiPs_write_read(u8 * data,u8 * rx_data){ + int Status; + + u8 rx_buffer[3]; + + XSpiPs_SetSlaveSelect((&SpiInstance),0x00); + + + Status = XSpiPs_PolledTransfer((&SpiInstance),data,rx_buffer,3); + + *rx_data = rx_buffer[2]; +return 0; +} +int SpiPs_write_read1(u16 addr,u8 data,u8 * rx_data){ + u8 rx_data1; + u16 temp; + u8 rx_buffer[3]; + + temp= addr&0xff00; + rx_buffer[0]= temp/256+128; + rx_buffer[1]= addr&0x00ff; + rx_buffer[2]= data; + + SpiPs_write_read((u8 *)&rx_buffer,&rx_data1); + + *rx_data = rx_data1; +return 0; +} +int SpiPs_write_read2(u16 addr,u8 data,u8 * rx_data){ + u8 rx_data1; + u16 temp; + u8 rx_buffer[3]; + + temp= addr&0xff00; + rx_buffer[0]= temp/256; + rx_buffer[1]= addr&0x00ff; + rx_buffer[2]= data; + + SpiPs_write_read((u8 *)&rx_buffer,&rx_data1); + + *rx_data = rx_data1; +return 0; +} + +int GpioInit(u16 DeviceId) +{ + int Status; + XGpioPs_Config *ConfigPtr; + /* Initialize the GPIO driver. */ + ConfigPtr = XGpioPs_LookupConfig(DeviceId); + Status = XGpioPs_CfgInitialize(&Gpio, ConfigPtr, + ConfigPtr->BaseAddr); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + return XST_SUCCESS; +} + +int GpioSetPinDir(u32 Pin,u32 Direction){ + XGpioPs_SetDirectionPin((&Gpio),GPIO_EMIO_OFFSET + Pin,Direction); + return 0; +} +int GpioWritePin(u32 Pin,u32 data){ + XGpioPs_SetOutputEnablePin(&Gpio, GPIO_EMIO_OFFSET + Pin, 1); + XGpioPs_WritePin((&Gpio),GPIO_EMIO_OFFSET + Pin,data); + return 0; +} + +int GpioReadPin(u32 Pin){ + return XGpioPs_ReadPin((&Gpio),GPIO_EMIO_OFFSET + Pin); +} + +void DeviceRst(void){ + GpioWritePin(NRST,0); + GpioWritePin(NRST,1); +} + +int XAxiDma_Init(XAxiDma* AxiDma,u16 DeviceId){ + + XAxiDma_Config *CfgPtr; + int Status; + /* Initialize the XAxiDma device. + */ + CfgPtr = XAxiDma_LookupConfig(DeviceId); + if (!CfgPtr) { + xil_printf("No config found for %d\r\n", DeviceId); + return XST_FAILURE; + } + + Status = XAxiDma_CfgInitialize(AxiDma, CfgPtr); + if (Status != XST_SUCCESS) { + xil_printf("Initialization failed %d\r\n", Status); + return XST_FAILURE; + } + + if(XAxiDma_HasSg(AxiDma)){ + xil_printf("Device configured as SG mode \r\n"); + return XST_FAILURE; + } + + /* Disable interrupts, we use polling mode + */ + XAxiDma_IntrDisable(AxiDma, XAXIDMA_IRQ_ALL_MASK, + XAXIDMA_DEVICE_TO_DMA); + XAxiDma_IntrDisable(AxiDma, XAXIDMA_IRQ_ALL_MASK, + XAXIDMA_DMA_TO_DEVICE); +return 0; +} + +int XAxiDmaCapture(XAxiDma* AxiDma,u32 data_length){ + int Status; + u8 *TxBufferPtr; + u32 MAX_PKT_LEN; + MAX_PKT_LEN = data_length; + TxBufferPtr = (u8 *)TX_BUFFER_BASE; + Xil_DCacheFlushRange((UINTPTR)TxBufferPtr, MAX_PKT_LEN); + Status = XAxiDma_Busy(AxiDma,XAXIDMA_DEVICE_TO_DMA); + Status = XAxiDma_Busy(AxiDma,XAXIDMA_DMA_TO_DEVICE); + XAxiDma_Reset(AxiDma); + Status = XAxiDma_ResetIsDone(AxiDma); + Status = XAxiDma_Busy(AxiDma,XAXIDMA_DEVICE_TO_DMA); + Status = XAxiDma_Busy(AxiDma,XAXIDMA_DMA_TO_DEVICE); + + Status = XAxiDma_SimpleTransfer(AxiDma,(UINTPTR) TxBufferPtr,MAX_PKT_LEN*8, XAXIDMA_DEVICE_TO_DMA); + SetPacketSize(AxiDma,MAX_PKT_LEN); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + u32 start_TickCount,current_TickCount=0; + start_TickCount = sys_now(); + u32 offset= 0; + //never come out ,reason is stream does't have tlast.Need a module to pack excatly the same length defined in para. + while ((offset< 500)&&(XAxiDma_Busy(AxiDma,XAXIDMA_DEVICE_TO_DMA))) { + Status = XAxiDma_Busy(AxiDma,XAXIDMA_DEVICE_TO_DMA); + + current_TickCount =sys_now(); + offset = current_TickCount-start_TickCount; +// xil_printf("offset: %d\r\n", offset); + } + /* + u64 offset= 0; + //never come out ,reason is stream does't have tlast.Need a module to pack excatly the same length defined in para. + while ((offset> 100000)||(XAxiDma_Busy(AxiDma,XAXIDMA_DEVICE_TO_DMA))) { + Status = XAxiDma_Busy(AxiDma,XAXIDMA_DEVICE_TO_DMA); + }*/ + return 0; +} + + + +int SetPacketSize(XAxiDma* AxiDma,u32 length){ + + UINTPTR Addr; + if(AxiDma == xAxiDma0Get()) + Addr = PACKER_BASEADDR0; + else if(AxiDma == xAxiDma1Get()) + Addr = PACKER_BASEADDR1; + else + Addr = PACKER_BASEADDR2; + xil_printf("addr %x .\n",Addr); + Xil_Out32(Addr,0); + xil_printf("PACKER_BASEADDR DATA %d .\n",Xil_In32(Addr)); + Xil_Out32(Addr+4,length); + xil_printf("PACKER_BASEADDR +4 DATA %d .\n",Xil_In32(Addr + 4)); + Xil_Out32(Addr,1); + xil_printf("PACKER_BASEADDR DATA %d .\n",Xil_In32(Addr)); + return 0; +} +int DownloadWave(u8 * data){ + u32 * buffer; + u64 addr; + int i; + buffer = (u32 *) data; + addr = BRAM_BASEADDR; + for(i=0;irecv_buf[spistack->spi_write_num * 3 + 0] = *(data + 0); + spistack->recv_buf[spistack->spi_write_num * 3 + 1] = *(data + 1); + spistack->recv_buf[spistack->spi_write_num * 3 + 2] = *(data + 2); + spistack->spi_write_num = spistack->spi_write_num + 1; + if(spistack->spi_write_num >= SPI_STACK_LENGTH-1){ + return 1; + } + else + return 0; +} + +void spi_stack_out(struct spi_stack * spistack){ + + int i; + u8 rx_data; + for(i=0;ispi_write_num;i++ ){ + SpiPs_write_read((u8 *)&(spistack->recv_buf[i * 3]),&rx_data); + } + spistack->spi_write_num = 0; +} + +int rom_read(u8 * data) +{ + int addr ; + addr = *(data + 0)*256+ *(data + 1); + return Xil_In32(BROM_BASEADDR+addr*4); +} + +void trx_ch_pll_config(u8 pll_index) +{ + u8 rx_data; + u8 recv_buf[3]={0}; + u32 trx_ch_pll_data; + + if(pll_index==1){ + trx_ch_pll_data = 0x00077DCF; + }else if(pll_index==2){ + trx_ch_pll_data = 0x00077D0C; + } + + recv_buf[0] =(trx_ch_pll_data>>16 & 0xff)|0x80 ; + recv_buf[1] = trx_ch_pll_data>>8 & 0xff; + recv_buf[2] = trx_ch_pll_data & 0xff; + SpiPs_write_read(recv_buf,&rx_data); +} + +u16 pll1_config_addr[] ={0x0620,0x061D,0x0B06,0x0B07,0x0B08,0x0B09,0x0B0A,0x061A,0x061B,0x061C,0x062A}; +u16 pll2_config_addr[] ={0x0642,0x063F,0x0B14,0x0B15,0x0B16,0x0B17,0x0B18,0x063C,0x063D,0x063E,0x064C}; +u16 pll3_config_addr[] ={0x0664,0x0661,0x0B22,0x0B23,0x0B24,0x0B25,0x0B26,0x065E,0x065F,0x0660,0x066E}; +u16 pll4_config_addr[] ={0x0686,0x0683,0x0B30,0x0B31,0x0B32,0x0B33,0x0B34,0x0680,0x0681,0x0682,0x0690}; + +int PLL_config(u8 pll_index,double pll_frq) +{ + + int i = 0,afc_cnt=0; + u16 pll_config_addr[11]; + u16 afc_addr,lock_addr; + double ref=200; + u8 pllreg_buf[11]; + u8 recv_buf[3]; + u8 rx_data,pll_div; + u16 div_addr; + + switch(pll_index){ + case 1:for (i = 0; i < 11; i++){pll_config_addr[i] = pll1_config_addr[i];} afc_addr=0x0617;lock_addr=0x0635;break; + case 2:for (i = 0; i < 11; i++){pll_config_addr[i] = pll2_config_addr[i];} afc_addr=0x0639;lock_addr=0x0657;break; + case 3:for (i = 0; i < 11; i++){pll_config_addr[i] = pll3_config_addr[i];} afc_addr=0x065B;lock_addr=0x0679;break; + case 4:for (i = 0; i < 11; i++){pll_config_addr[i] = pll4_config_addr[i];} afc_addr=0x067D;lock_addr=0x069B;break; + default :; + } + //caculate pll frequence word + pll_frq_caculation_new(ref,pll_frq,(u8 *)&pllreg_buf); + for (i = 0; i < 11; i++) + { + recv_buf[0] = (pll_config_addr[i]>>8 & 0xff)|0x80 ; + recv_buf[1] = pll_config_addr[i] & 0xff; + recv_buf[2] = pllreg_buf[i] & 0xff; + SpiPs_write_read((u8 *)&recv_buf[0],&rx_data); + } + //afc pll + pll_div = pllreg_buf[1]; + div_addr = pll_config_addr[1]; + recv_buf[0] = lock_addr>>8 & 0xff ; + recv_buf[1] = lock_addr & 0xff; + recv_buf[2] = 0x00; + while(rx_data!=48){ + PLL_afc(afc_addr,div_addr,pll_div); + SpiPs_write_read((u8 *)&recv_buf[0],&rx_data); + afc_cnt++; + } + return afc_cnt; + //xil_printf("afc lock count: %d.\r\n",afc_cnt); + +} + +void PLL_afc(u16 afc_addr,u16 div_addr,u8 pll_div){ + + u8 recv_buf[3]; + u8 rx_data; + if(pll_div>=48){ + recv_buf[0] = (div_addr>>8 & 0xff)|0x80 ; + recv_buf[1] = div_addr & 0xff; + recv_buf[2] = pll_div & 0x2f; + SpiPs_write_read((u8 *)&recv_buf[0],&rx_data); + } + recv_buf[0] = (afc_addr>>8 & 0xff)|0x80 ; + recv_buf[1] = afc_addr & 0xff; + recv_buf[2] = 0x00; + SpiPs_write_read((u8 *)&recv_buf[0],&rx_data); + recv_buf[2] = 0x03; + SpiPs_write_read((u8 *)&recv_buf[0],&rx_data); + usleep(30); + if(pll_div>=48){ + recv_buf[0] = (div_addr>>8 & 0xff)|0x80 ; + recv_buf[1] = div_addr & 0xff; + recv_buf[2] = pll_div & 0xff; + SpiPs_write_read((u8 *)&recv_buf[0],&rx_data); + } + +} + +int pll_frq_caculation(double ref,double pll_frq,u8 *reg_data){ + + u8 row,column; + int vco = pll_frq; + int div = 1; + while(vco < 7001){ + vco = vco*2; + div = div*2; + } + char coreTable[7][4][3] = {{{0x0C,0x30,0x08},{0x0B,0x30,0x09},{0x0C,0x30,0x05},{0x0D,0x30,0x08}}, + {{0x0C,0x30,0x0C},{0x0B,0x30,0x0E},{0x0C,0x30,0x08},{0x0D,0x30,0x0B}}, + {{0x0C,0x20,0x10},{0x0B,0x20,0x10},{0x0C,0x20,0x0A},{0x0D,0x20,0x0D}}, + {{0x0C,0x20,0x11},{0x0B,0x20,0x13},{0x0C,0x20,0x0C},{0x0D,0x20,0x0F}}, + {{0x0D,0x30,0x14},{0x0D,0x22,0x14},{0x0D,0x20,0x0D},{0x0D,0x15,0x0C}}, + {{0x0E,0x30,0x18},{0x0E,0x25,0x16},{0x0E,0x25,0x0F},{0x0E,0x18,0x0F}}, + {{0x0F,0x38,0x1A},{0x0F,0x32,0x1C},{0x0F,0x18,0x12},{0x0F,0x18,0x12}}}; + + if (ref >= 28 && ref < 40){ + row = 0; + }else if (ref >= 40 && ref < 60){ + row = 1; + }else if (ref >= 60 && ref < 90){ + row = 2; + }else if (ref >= 90 && ref < 110){ + row = 3; + }else if (ref >= 110 && ref < 140){ + row = 4; + }else if (ref >= 140 && ref < 180){ + row = 5; + }else if (ref >= 180 && ref <= 240){ + row = 6; + } + + if (vco >= 7001 && vco < 8400){ + column = 0; + }else if (vco >= 8400 && vco < 10500){ + column = 1; + }else if (vco >= 10500 && vco < 12000){ + column = 2; + }else if (vco >= 12000 && vco <= 14000){ + column = 3; + } + + char cp = coreTable[row][column][0]; + char c1r3 = coreTable[row][column][1]; + char r1 = coreTable[row][column][2]; + + char dither,nHigh,nLow,fHigh,fMiddle,fLow,outputDiv,core = 0x81; + if(vco > 10500){ + core = core + 0x10; + } + if (div == 2){ + outputDiv = 0+7; + }else if (div == 4){ + outputDiv = 32+7; + }else{ + outputDiv = 48 + divBin(div); + } + + double nf = 1.0*vco / ref; + int n = nf; + double f = nf - n; + if(f > 1e-10){ + dither = 11; + }else{ + dither = 0; + } + if(n >= 256){ + nHigh = 1; + }else{ + nHigh = 0; + } + nLow = n & 0xff; + int f1 = f * pow(2,24); + fHigh = f1>>16 & 0xff; + fMiddle = f1>>8 & 0xff; + fLow = f1 & 0xff; + reg_data[0]=core; + reg_data[1]=outputDiv; + reg_data[2]=nHigh; + reg_data[3]=nLow; + reg_data[4]=fHigh; + reg_data[5]=fMiddle; + reg_data[6]=fLow; + reg_data[7]=cp; + reg_data[8]=c1r3; + reg_data[9]=r1; + reg_data[10]=dither; + return 0; +} +int pll_frq_caculation_new(double ref,double pll_frq,u8 *reg_data){ + + u8 row,column; + double vco = pll_frq; + int div = 1; + while(vco < 6701){ + vco = vco*2; + div = div*2; + } + char coreTable[7][4][3] = {{{0x0C,0x30,0x08},{0x0B,0x30,0x09},{0x0C,0x30,0x05},{0x0D,0x30,0x08}}, + {{0x0C,0x30,0x0C},{0x0B,0x30,0x0E},{0x0C,0x30,0x08},{0x0D,0x30,0x0B}}, + {{0x0C,0x20,0x10},{0x0B,0x20,0x10},{0x0C,0x20,0x0A},{0x0D,0x20,0x0D}}, + {{0x0C,0x20,0x11},{0x0B,0x20,0x13},{0x0C,0x20,0x0C},{0x0D,0x20,0x0F}}, + {{0x0D,0x30,0x14},{0x0D,0x22,0x14},{0x0D,0x20,0x0D},{0x0D,0x15,0x0C}}, + {{0x0E,0x30,0x18},{0x0E,0x25,0x16},{0x0E,0x25,0x0F},{0x0E,0x18,0x0F}}, + {{0x0F,0x38,0x1A},{0x0F,0x32,0x1C},{0x0F,0x18,0x12},{0x0F,0x18,0x12}}}; + + if (ref >= 28 && ref < 40){ + row = 0; + }else if (ref >= 40 && ref < 60){ + row = 1; + }else if (ref >= 60 && ref < 90){ + row = 2; + }else if (ref >= 90 && ref < 110){ + row = 3; + }else if (ref >= 110 && ref < 140){ + row = 4; + }else if (ref >= 140 && ref < 180){ + row = 5; + }else if (ref >= 180 && ref <= 240){ + row = 6; + } + + if (vco < 8400){ + column = 0; + }else if (vco >= 8400 && vco < 10150){ + column = 1; + }else if (vco >= 10150 && vco < 12000){ + column = 2; + }else if (vco >= 12000 ){ + column = 3; + } + + char cp = coreTable[row][column][0]; + char c1r3 = coreTable[row][column][1]; + char r1 = coreTable[row][column][2]; + + char dither,nHigh,nLow,fHigh,fMiddle,fLow,outputDiv,core = 0x81; + if(vco > 10150){ + core = core + 0x10; + } + if (div == 2){ + outputDiv = 0+7; + }else if (div == 4){ + outputDiv = 32+7; + }else{ + outputDiv = 48 + divBin(div); + } + + double nf = 1.0*vco / ref; + int n = nf; + double f = nf - n; + if(f > 1e-10){ + dither = 11; + }else{ + dither = 0; + } + if(n >= 256){ + nHigh = 1; + }else{ + nHigh = 0; + } + nLow = n & 0xff; + int f1 = f * pow(2,24); + fHigh = f1>>16 & 0xff; + fMiddle = f1>>8 & 0xff; + fLow = f1 & 0xff; + reg_data[0]=core; + reg_data[1]=outputDiv; + reg_data[2]=nHigh; + reg_data[3]=nLow; + reg_data[4]=fHigh; + reg_data[5]=fMiddle; + reg_data[6]=fLow; + reg_data[7]=cp; + reg_data[8]=c1r3; + reg_data[9]=r1; + reg_data[10]=dither; + return 0; +} +char divBin(u16 div){ + + switch(div){ + case 8:return 7;break; + case 16:return 6;break; + case 32:return 5;break; + case 64:return 4;break; + case 128:return 3;break; + case 256:return 2;break; + default :return 2; + } + +} + +void configTxNcoFreq(int freq, int fs) { + u8 rx_data; + double ratio = (double) freq < 0 ? (freq + fs) / fs : freq / fs; + double bin = ratio * pow(2,48); + int bin_low = (u32) bin & 0xFFFFFF; + int bin_high = (u32)(bin / pow(2,24)) & 0xFFFFFF; + SpiPs_write_read1(0x164, (bin_high >> 16) & 0xFF,&rx_data); + SpiPs_write_read1(0x165, (bin_high >> 8) & 0xFF,&rx_data); + SpiPs_write_read1(0x166, bin_high & 0xFF,&rx_data); + SpiPs_write_read1(0x167, (bin_low >> 16) & 0xFF,&rx_data); + SpiPs_write_read1(0x168, (bin_low >> 8) & 0xFF,&rx_data); + SpiPs_write_read1(0x169, bin_low & 0xFF,&rx_data); +} +void configRxNcoFreq(int freq, int fs) { + u8 rx_data; + double ratio = (double) freq < 0 ? (freq + fs) / fs : freq / fs; + double bin = ratio * pow(2,48); + int bin_low = (u32) bin & 0xFFFFFF; + int bin_high = (u32)(bin / pow(2,24)) & 0xFFFFFF; + SpiPs_write_read1(0xA16, (bin_high >> 16) & 0xFF,&rx_data); + SpiPs_write_read1(0xA17, (bin_high >> 8) & 0xFF,&rx_data); + SpiPs_write_read1(0xA18, bin_high & 0xFF,&rx_data); + SpiPs_write_read1(0xA19, (bin_low >> 16) & 0xFF,&rx_data); + SpiPs_write_read1(0xA1A, (bin_low >> 8) & 0xFF,&rx_data); + SpiPs_write_read1(0xA1B, bin_low & 0xFF,&rx_data); +} + diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_DEMO/xilinx_io.h b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_DEMO/xilinx_io.h new file mode 100644 index 0000000..2a5b601 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_DEMO/xilinx_io.h @@ -0,0 +1,149 @@ +/* + * xilinx_io.h + * + * Created on: 2021Äê9ÔÂ6ÈÕ + * Author: cxlab + */ + +#ifndef SRC_XILINX_IO_H_ +#define SRC_XILINX_IO_H_ + + + +#endif /* SRC_XILINX_IO_H_ */ +#include "xspips.h" /* SPI device driver */ +#include "xgpiops.h" +#include "xgpio.h" +#include "xaxidma.h" +#include "xparameters.h" +#include "xscugic.h" +#include "xil_exception.h" + +//#define DBGLOG +#define MAX_DATA 100 +#define SPI_WRITE 0x80 +#define SPI_READ 0x00 +#define GPIO_DIR_INPUT 0x00 +#define GPIO_DIR_OUTPUT 0x01 +#define GPIO_EMIO_OFFSET 54 + +#define TX_EN 0x08 +#define RX_EN 0x07 +#define GPIO_1 0x06 +#define GPIO_0 0x05 + +#define NRST 0 +#define ENABLE_TRX1 1 +#define ENABLE_TRX2 2 +#define ENABLE_TRX3 3 +#define TXNRX_TRX1 4 +#define TXNRX_TRX2 5 +#define TXNRX_RX3 6 + +#define aresetn_0 33 +#define rst 34 +#define tr_sel 35 +#define tdd_fdd_sel 36 +#define r1t1_r2t2_sel 37 +#define sp_dp_sel 38 +#define aresetn_1 39 +#define aresetn_2 40 +#define hop 41 +#define cx3e04_rstn 42 +#define debug_mode 63 + +#define INTER_SIG3 0x03//dma_axis_rx_rstn +#define INTER_SIG2 0x02//frame_pattern +#define INTER_SIG1 0x01//mode_sel_async +#define INTER_SIG0 0x00//rst_async + +#define SPI_DEVICE_ID XPAR_XSPIPS_0_DEVICE_ID +#define GPIO_DEVICE_ID XPAR_PS7_GPIO_0_DEVICE_ID + +#define AXI_DMA_DEVCIE_ID0 XPAR_AXI_DMA_0_DEVICE_ID +#define AXI_DMA_DEVCIE_ID1 XPAR_AXI_DMA_1_DEVICE_ID +#define AXI_DMA_DEVCIE_ID2 XPAR_AXI_DMA_2_DEVICE_ID + +#define BROM_BASEADDR XPAR_M08_AXI_0_BASEADDR + +#define AXI4_LITE_SPI_BASEADDR XPAR_AXI4_LITE_SPI_0_BASEADDR +#define BRAM_BASEADDR XPAR_AXI_BRAM_CTRL_0_S_AXI_BASEADDR +#define BRAM_BASEADDR_1 XPAR_AXI_BRAM_CTRL_1_S_AXI_BASEADDR +#define PACKER_BASEADDR0 XPAR_AXIS_ADC_DATA_PACKER_0_S00_AXI_BASEADDR +#define PACKER_BASEADDR1 XPAR_AXIS_ADC_DATA_PACKER_1_S00_AXI_BASEADDR +#define PACKER_BASEADDR2 XPAR_AXIS_ADC_DATA_PACKER_2_S00_AXI_BASEADDR +#define WAVELENGTH 8192 +#define TX_BUFFER_BASE XPAR_MIG_7SERIES_0_BASEADDR +0x2000 +#define WAVE_LENGTH 8192*4 + +#define GPIO_INT_ID XPAR_FABRIC_GPIO_0_VEC_ID //PL ¶Ë AXI GPIO ÖжÏ ID +#define AXI_GPIO_ID XPAR_AXI_GPIO_0_DEVICE_ID //PL ¶Ë AXI GPIO Æ÷¼þ ID +#define SCUGIC_ID XPAR_SCUGIC_0_DEVICE_ID //ÖжϿØÖÆÆ÷ ID + +#define KEY_MASK XGPIO_IR_CH1_MASK //ͨµÀ 1 µÄ붨Òå + +int cx3e04_write(int addr , int value); +int cx3e04_read(int addr); +void cx3e04_config(void); +void cx9261a_710_config(void); + +void AXIGpioInit(void); +void ConfigAXIGPIOIntr(void); +void axi_gpio_handler(void *CallbackRef); +void XScuGicInit(void); +void ExceptionInit(void); + +int SpiPsInit(u16 SpiDeviceId); +//int SpiPs_write_read(u8 cmd, u16 addr,u8 data,u8 * rx_data); +int SpiPs_write_read(u8 * data,u8 * rx_data); +int SpiPs_write_read1(u16 addr,u8 data,u8 * rx_data); +int SpiPs_write_read2(u16 addr,u8 data,u8 * rx_data); +int GpioInit(u16 DeviceId); +int GpioSetPinDir(u32 Pin,u32 Direction); +int GpioWritePin(u32 Pin,u32 data); +int GpioReadPin(u32 Pin); +void DeviceRst(void); + +//У׼ +void cx9261a_151_config(void); +void cx9261a_076_config(void); +void rxFFTCalib(int lo, int fs,int ref, int firLength,int chan); +void configTxNcoFreq(int freq, int fs); +void configRxNcoFreq(int freq, int fs); +void configDcCalib(int dcCalibEnable,int dcCalibLength); +void txBisectionQecCalib(int f0, int fs); +void txBisectionDcCalib(int f0, int fs); + +extern XAxiDma* xAxiDma0Get(void); +extern XAxiDma* xAxiDma1Get(void); +extern XAxiDma* xAxiDma2Get(void); +int XAxiDma_Init(XAxiDma* AxiDma,u16 DeviceId); +int XAxiDmaCapture(XAxiDma* AxiDma,u32 data_length); +int XAxiDmaCapture2(XAxiDma* AxiDma,u32 data_length); + +int DownloadWave(u8 * data); +int SetPacketSize(XAxiDma* AxiDma,u32 length); +void dbg_printf( const char8 *ctrl1, ...); +void PackerRst(void); +int peripheral_test(void); + +#define SPI_STACK_LENGTH 65536 +struct spi_stack { + int spi_write_num; + u8 recv_buf[SPI_STACK_LENGTH*3]; +}; +int spi_stack_in(u8 * data,struct spi_stack * spistack); + +void spi_stack_out(struct spi_stack * spistack); + +int rom_read(u8 * data); +void download_bin(void); +//ÌøƵ +void frqhop_config(int hop_flag); +void frqhop_flag(int frqhop_flag); +int PLL_config(u8 pll_index,double pll_frq); +void trx_ch_pll_config(u8 pll_index); +int pll_frq_caculation(double ref,double pll_frq,u8 *reg_data); +int pll_frq_caculation_new(double ref,double pll_frq,u8 *reg_data); +void PLL_afc(u16 afc_addr,u16 div_addr,u8 pll_div); +char divBin(u16 div); diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_HOP/cx9261a_076_config.c b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_HOP/cx9261a_076_config.c new file mode 100644 index 0000000..64c1e10 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_HOP/cx9261a_076_config.c @@ -0,0 +1,342 @@ +/* + * cx9261a_076_config.c + * + * Created on: 2023Äê11ÔÂ30ÈÕ + * Author: cxlab + */ + + +#include "xilinx_io.h" +#include "sleep.h" +void cx9261a_076_config(void){ +u8 rx_data; +int temp; + +//setPin(pin,value) +GpioSetPinDir(0,0x01); +GpioWritePin(0,1); +GpioSetPinDir(32,0x01); +GpioWritePin(32,1); +GpioSetPinDir(33,0x01); +GpioWritePin(33,1); +GpioSetPinDir(34,0x01); +GpioWritePin(34,0); +GpioSetPinDir(35,0x01); //tx:0-rx:1 +GpioWritePin(35,1); //tx:0-rx:1 +GpioSetPinDir(36,0x01); //fdd:0-tdd:1 +GpioWritePin(36,1); //fdd:0-tdd:1 +GpioSetPinDir(37,0x01); //1r1t:0-2r2t:1 +GpioWritePin(37,0); //1r1t:0-2r2t:1 +GpioSetPinDir(38,0x01); //dualport:0-singleport:1 +GpioWritePin(38,1); //dualport:0-singleport:1 +GpioSetPinDir(39,0x01); +GpioWritePin(39,1); +GpioSetPinDir(40,0x01); +GpioWritePin(40,1); +//Èý¸öͨµÀ¹²ͬ¿ØÖÆ +SpiPs_write_read1(0x000,0x02,&rx_data); +//µçԴ¹ÜÀí×Զ¨Òå +//¶ϵçģʽ +SpiPs_write_read1(0x031,0x00,&rx_data); +SpiPs_write_read1(0x032,0x7F,&rx_data); +SpiPs_write_read1(0x033,0xFF,&rx_data); +SpiPs_write_read1(0x034,0xFF,&rx_data); +//ÐÝÃßģʽ +SpiPs_write_read1(0x035,0x00,&rx_data); +SpiPs_write_read1(0x036,0x3D,&rx_data); +SpiPs_write_read1(0x037,0xFF,&rx_data); +SpiPs_write_read1(0x038,0xEB,&rx_data); +//¾¯½äģʽ +SpiPs_write_read1(0x039,0x00,&rx_data); +SpiPs_write_read1(0x03A,0x3D,&rx_data); +SpiPs_write_read1(0x03B,0xFF,&rx_data); +SpiPs_write_read1(0x03C,0xE0,&rx_data); +//У׼ģʽ +SpiPs_write_read1(0x03D,0x1B,&rx_data); +SpiPs_write_read1(0x03E,0x39,&rx_data); +SpiPs_write_read1(0x03F,0x27,&rx_data); +SpiPs_write_read1(0x040,0xE0,&rx_data); +//½ÓÊÕģʽ +SpiPs_write_read1(0x041,0x03,&rx_data); +SpiPs_write_read1(0x042,0x3D,&rx_data); +SpiPs_write_read1(0x043,0xE7,&rx_data); +SpiPs_write_read1(0x044,0xF8,&rx_data); +//·¢Éäģʽ +SpiPs_write_read1(0x045,0x1B,&rx_data); +SpiPs_write_read1(0x046,0x3D,&rx_data); +SpiPs_write_read1(0x047,0x26,&rx_data); +SpiPs_write_read1(0x048,0x7E,&rx_data); +//FDDģʽ +SpiPs_write_read1(0x049,0x1B,&rx_data); +SpiPs_write_read1(0x04A,0x3D,&rx_data); +SpiPs_write_read1(0x04B,0x27,&rx_data); +SpiPs_write_read1(0x04C,0xE0,&rx_data); +//¹۲âģʽ +SpiPs_write_read1(0x04D,0x04,&rx_data); +SpiPs_write_read1(0x04E,0x3D,&rx_data); +SpiPs_write_read1(0x04F,0xD9,&rx_data); +SpiPs_write_read1(0x050,0xFE,&rx_data); +//´ø϶»ù׼ +SpiPs_write_read1(0x773,0x53,&rx_data); +SpiPs_write_read1(0x774,0x86,&rx_data); +//²ο¼ʱÖÓÉèÖà +SpiPs_write_read1(0x789,0x00,&rx_data); +SpiPs_write_read1(0x785,0x49,&rx_data); +SpiPs_write_read1(0x788,0x24,&rx_data); +usleep(10000); +SpiPs_write_read1(0x788,0xA4,&rx_data); +//BBPLL +SpiPs_write_read1(0x0C0,0x50,&rx_data); +SpiPs_write_read1(0x0C1,0x50,&rx_data); +SpiPs_write_read1(0x0C2,0x50,&rx_data); +SpiPs_write_read1(0x601,0x0F,&rx_data); +SpiPs_write_read1(0x602,0x21,&rx_data); +SpiPs_write_read1(0x60D,0x0C,&rx_data); +SpiPs_write_read1(0x60E,0x66,&rx_data); +SpiPs_write_read1(0x60F,0x66,&rx_data); +SpiPs_write_read1(0x610,0x66,&rx_data); +SpiPs_write_read1(0x611,0x13,&rx_data); +SpiPs_write_read1(0x612,0x00,&rx_data); +//ADC +SpiPs_write_read1(0x70B,0x0E,&rx_data); +SpiPs_write_read1(0x727,0x0E,&rx_data); +SpiPs_write_read1(0x743,0x0E,&rx_data); +SpiPs_write_read1(0x70D,0x3F,&rx_data); +SpiPs_write_read1(0x729,0x3F,&rx_data); +SpiPs_write_read1(0x745,0x3F,&rx_data); +SpiPs_write_read1(0x70E,0x48,&rx_data); +SpiPs_write_read1(0x72A,0x48,&rx_data); +SpiPs_write_read1(0x746,0x48,&rx_data); +SpiPs_write_read1(0x70F,0xA0,&rx_data); +SpiPs_write_read1(0x72B,0xA0,&rx_data); +SpiPs_write_read1(0x747,0xA0,&rx_data); +//ͨµÀʱÖÓÀ´Դ +SpiPs_write_read1(0x77D,0xC0,&rx_data); +SpiPs_write_read1(0x775,0x24,&rx_data); +SpiPs_write_read1(0x6C3,0x00,&rx_data); +//PLL1 +SpiPs_write_read1(0x620,0x81,&rx_data); +SpiPs_write_read1(0x61D,0x00,&rx_data); +SpiPs_write_read1(0xB06,0x00,&rx_data); +SpiPs_write_read1(0xB07,0x64,&rx_data); +SpiPs_write_read1(0xB08,0x00,&rx_data); +SpiPs_write_read1(0xB09,0x00,&rx_data); +SpiPs_write_read1(0xB0A,0x00,&rx_data); +SpiPs_write_read1(0x61A,0x0B,&rx_data); +SpiPs_write_read1(0x61B,0x20,&rx_data); +SpiPs_write_read1(0x61C,0x13,&rx_data); +SpiPs_write_read1(0x624,0x11,&rx_data); +SpiPs_write_read1(0x625,0x11,&rx_data); +SpiPs_write_read1(0x62A,0x00,&rx_data); +SpiPs_write_read1(0x61E,0x30,&rx_data); +SpiPs_write_read1(0x61F,0x08,&rx_data); +SpiPs_write_read1(0x621,0x4D,&rx_data); +SpiPs_write_read1(0x622,0x19,&rx_data); +SpiPs_write_read1(0x627,0x10,&rx_data); +//RxͨµÀÉèÖà +SpiPs_write_read1(0x700,0x56,&rx_data); +SpiPs_write_read1(0x71C,0x56,&rx_data); +SpiPs_write_read1(0x738,0x56,&rx_data); +SpiPs_write_read1(0x701,0x02,&rx_data); +SpiPs_write_read1(0x702,0x35,&rx_data); +SpiPs_write_read1(0x71D,0x02,&rx_data); +SpiPs_write_read1(0x71E,0x35,&rx_data); +SpiPs_write_read1(0x739,0x02,&rx_data); +SpiPs_write_read1(0x73A,0x35,&rx_data); +SpiPs_write_read1(0x703,0xF6,&rx_data); +SpiPs_write_read1(0x71F,0xF6,&rx_data); +SpiPs_write_read1(0x73B,0xF6,&rx_data); +SpiPs_write_read1(0x704,0xC8,&rx_data); +SpiPs_write_read1(0x720,0xC8,&rx_data); +SpiPs_write_read1(0x73C,0xC8,&rx_data); +SpiPs_write_read1(0x907,0x1F,&rx_data); +SpiPs_write_read1(0x705,0xFC,&rx_data); +SpiPs_write_read1(0x721,0xFC,&rx_data); +SpiPs_write_read1(0x73D,0xFC,&rx_data); +SpiPs_write_read1(0x706,0x65,&rx_data); +SpiPs_write_read1(0x722,0x65,&rx_data); +SpiPs_write_read1(0x73E,0x65,&rx_data); +SpiPs_write_read1(0x707,0x91,&rx_data); +SpiPs_write_read1(0x723,0x91,&rx_data); +SpiPs_write_read1(0x73F,0x91,&rx_data); +SpiPs_write_read1(0x708,0x04,&rx_data); +SpiPs_write_read1(0x724,0x04,&rx_data); +SpiPs_write_read1(0x740,0x04,&rx_data); +SpiPs_write_read1(0x709,0x94,&rx_data); +SpiPs_write_read1(0x725,0x94,&rx_data); +SpiPs_write_read1(0x741,0x94,&rx_data); +SpiPs_write_read1(0x70A,0xFC,&rx_data); +SpiPs_write_read1(0x726,0xFC,&rx_data); +SpiPs_write_read1(0x742,0xFC,&rx_data); +SpiPs_write_read1(0x75A,0x83,&rx_data); +SpiPs_write_read1(0x75B,0xDA,&rx_data); +usleep(10000); +SpiPs_write_read1(0x75B,0x9A,&rx_data); +SpiPs_write_read1(0x75C,0x81,&rx_data); +SpiPs_write_read1(0x75D,0xF8,&rx_data); +SpiPs_write_read1(0x75E,0xA7,&rx_data); +SpiPs_write_read1(0x75F,0x51,&rx_data); +SpiPs_write_read1(0x760,0xFF,&rx_data); +SpiPs_write_read1(0x761,0x04,&rx_data); +SpiPs_write_read1(0x762,0x70,&rx_data); +SpiPs_write_read1(0x763,0x04,&rx_data); +SpiPs_write_read1(0x764,0x83,&rx_data); +SpiPs_write_read1(0x765,0xDA,&rx_data); +usleep(100000); +SpiPs_write_read1(0x765,0x9A,&rx_data); +SpiPs_write_read1(0x766,0x81,&rx_data); +SpiPs_write_read1(0x767,0xF8,&rx_data); +SpiPs_write_read1(0x768,0xA7,&rx_data); +SpiPs_write_read1(0x769,0x51,&rx_data); +SpiPs_write_read1(0x76A,0xFF,&rx_data); +SpiPs_write_read1(0x76B,0x04,&rx_data); +SpiPs_write_read1(0x76C,0x70,&rx_data); +SpiPs_write_read1(0x76D,0x04,&rx_data); +//RxÂ˲¨Æ÷ +SpiPs_write_read1(0x106,0x02,&rx_data); +//TxÂ˲¨Æ÷ +SpiPs_write_read1(0x107,0x00,&rx_data); +SpiPs_write_read1(0x108,0xD0,&rx_data); +//Rx NCO +SpiPs_write_read1(0x11C,0x00,&rx_data); +SpiPs_write_read1(0xA07,0x00,&rx_data); +SpiPs_write_read1(0xA08,0x00,&rx_data); +SpiPs_write_read1(0xA16,0x00,&rx_data); +SpiPs_write_read1(0xA17,0x00,&rx_data); +SpiPs_write_read1(0xA18,0x00,&rx_data); +SpiPs_write_read1(0xA19,0x00,&rx_data); +SpiPs_write_read1(0xA1A,0x00,&rx_data); +SpiPs_write_read1(0xA1B,0x00,&rx_data); +//Tx NCO +SpiPs_write_read1(0x128,0x10,&rx_data); +SpiPs_write_read1(0x11B,0x00,&rx_data); +SpiPs_write_read1(0x11E,0x00,&rx_data); +SpiPs_write_read1(0x161,0x00,&rx_data); +SpiPs_write_read1(0x162,0x00,&rx_data); +SpiPs_write_read1(0x164,0x00,&rx_data); +SpiPs_write_read1(0x165,0x00,&rx_data); +SpiPs_write_read1(0x166,0x00,&rx_data); +SpiPs_write_read1(0x167,0x00,&rx_data); +SpiPs_write_read1(0x168,0x00,&rx_data); +SpiPs_write_read1(0x169,0x00,&rx_data); +//AGCÅäÖà +SpiPs_write_read1(0x900,0x00,&rx_data); +SpiPs_write_read1(0x901,0x00,&rx_data); +SpiPs_write_read1(0x903,0x11,&rx_data); +SpiPs_write_read1(0x908,0x77,&rx_data); +SpiPs_write_read1(0x909,0x03,&rx_data); +SpiPs_write_read1(0x90A,0x32,&rx_data); +SpiPs_write_read1(0x90D,0x00,&rx_data); +SpiPs_write_read1(0x90E,0x0F,&rx_data); +SpiPs_write_read1(0x90F,0x65,&rx_data); +SpiPs_write_read1(0x910,0x32,&rx_data); +SpiPs_write_read1(0x911,0x00,&rx_data); +SpiPs_write_read1(0x912,0x0F,&rx_data); +SpiPs_write_read1(0x913,0x3A,&rx_data); +SpiPs_write_read1(0x914,0x37,&rx_data); +SpiPs_write_read1(0x915,0x34,&rx_data); +SpiPs_write_read1(0x916,0x31,&rx_data); +//½øÈëÐÝÃßģʽ +SpiPs_write_read1(0x02E,0x01,&rx_data); +usleep(1000000); +//½øÈëУ׼ģʽ +SpiPs_write_read1(0x02E,0x03,&rx_data); +//BBPLL AFC +SpiPs_write_read1(0x600,0x00,&rx_data); +usleep(100000); +SpiPs_write_read1(0x600,0x11,&rx_data); +//PLL1 AFC +SpiPs_write_read1(0x617,0x00,&rx_data); +usleep(100000); +SpiPs_write_read1(0x617,0x03,&rx_data); +//½ӿÚÅäÖà +SpiPs_write_read1(0x02E,0x06,&rx_data); +SpiPs_write_read1(0x003,0x33,&rx_data); +SpiPs_write_read1(0x200,0x00,&rx_data); +SpiPs_write_read1(0x201,0x00,&rx_data); +SpiPs_write_read1(0x202,0x03,&rx_data); +SpiPs_write_read1(0x209,0x00,&rx_data); +SpiPs_write_read1(0x780,0x11,&rx_data); +SpiPs_write_read1(0x781,0x6F,&rx_data); +SpiPs_write_read1(0x782,0x01,&rx_data); +SpiPs_write_read1(0x783,0x01,&rx_data); +SpiPs_write_read1(0x784,0x01,&rx_data); +//ADCУ׼ +SpiPs_write_read1(0x70B,0x1E,&rx_data); +SpiPs_write_read1(0x727,0x1E,&rx_data); +SpiPs_write_read1(0x743,0x1E,&rx_data); +SpiPs_write_read1(0x70F,0xA0,&rx_data); +SpiPs_write_read1(0x710,0x83,&rx_data); +SpiPs_write_read1(0x711,0xF0,&rx_data); +SpiPs_write_read1(0x72B,0xA0,&rx_data); +SpiPs_write_read1(0x72C,0x83,&rx_data); +SpiPs_write_read1(0x72D,0xF0,&rx_data); +SpiPs_write_read1(0x747,0xA0,&rx_data); +SpiPs_write_read1(0x748,0x83,&rx_data); +SpiPs_write_read1(0x749,0xF0,&rx_data); +SpiPs_write_read1(0x713,0x80,&rx_data); +SpiPs_write_read1(0x72F,0x80,&rx_data); +SpiPs_write_read1(0x74B,0x80,&rx_data); +SpiPs_write_read1(0x70B,0x9E,&rx_data); +SpiPs_write_read1(0x727,0x9E,&rx_data); +SpiPs_write_read1(0x743,0x9E,&rx_data); +SpiPs_write_read1(0x70B,0x9A,&rx_data); +SpiPs_write_read1(0x727,0x9A,&rx_data); +SpiPs_write_read1(0x743,0x9A,&rx_data); +SpiPs_write_read1(0x70B,0x9E,&rx_data); +SpiPs_write_read1(0x727,0x9E,&rx_data); +SpiPs_write_read1(0x743,0x9E,&rx_data); +usleep(100000); +SpiPs_write_read1(0x70B,0x1E,&rx_data); +SpiPs_write_read1(0x727,0x1E,&rx_data); +SpiPs_write_read1(0x743,0x1E,&rx_data); +SpiPs_write_read1(0x713,0xC0,&rx_data); +SpiPs_write_read1(0x72F,0xC0,&rx_data); +SpiPs_write_read1(0x74B,0xC0,&rx_data); +//FlashУ׼ +SpiPs_write_read1(0x70B,0x1E,&rx_data); +SpiPs_write_read1(0x727,0x1E,&rx_data); +SpiPs_write_read1(0x743,0x1E,&rx_data); +SpiPs_write_read1(0x715,0x80,&rx_data); +SpiPs_write_read1(0x731,0x80,&rx_data); +SpiPs_write_read1(0x74D,0x80,&rx_data); +SpiPs_write_read1(0x715,0xC0,&rx_data); +SpiPs_write_read1(0x731,0xC0,&rx_data); +SpiPs_write_read1(0x74D,0xC0,&rx_data); +SpiPs_write_read1(0x716,0x40,&rx_data); +SpiPs_write_read1(0x732,0x40,&rx_data); +SpiPs_write_read1(0x74E,0x40,&rx_data); +SpiPs_write_read1(0x70B,0x16,&rx_data); +SpiPs_write_read1(0x727,0x16,&rx_data); +SpiPs_write_read1(0x743,0x16,&rx_data); +usleep(100000); +SpiPs_write_read1(0x70B,0x1E,&rx_data); +SpiPs_write_read1(0x727,0x1E,&rx_data); +SpiPs_write_read1(0x743,0x1E,&rx_data); +SpiPs_write_read1(0x715,0x80,&rx_data); +SpiPs_write_read1(0x731,0x80,&rx_data); +SpiPs_write_read1(0x74D,0x80,&rx_data); +SpiPs_write_read1(0x716,0x00,&rx_data); +SpiPs_write_read1(0x732,0x00,&rx_data); +SpiPs_write_read1(0x74E,0x00,&rx_data); +SpiPs_write_read1(0x109,0x11,&rx_data); +SpiPs_write_read1(0x10A,0x70,&rx_data); +SpiPs_write_read1(0x11F,0x33,&rx_data); +usleep(1000); +SpiPs_write_read2(0x615,0x00,&rx_data); +temp=rx_data; +SpiPs_write_read2(0x635,0x00,&rx_data); +temp=rx_data; +////ÅäÖÃTx NCO BIST ON +//SpiPs_write_read1(0x11B,0x01,&rx_data); +//SpiPs_write_read1(0x11E,0x01,&rx_data); +//SpiPs_write_read1(0x161,0x01,&rx_data); +//SpiPs_write_read1(0x162,0x01,&rx_data); +////ÅäÖÃTx NCOƵÂÊ 1MHz +//SpiPs_write_read1(0x164,0x05,&rx_data); +//SpiPs_write_read1(0x165,0x55,&rx_data); +//SpiPs_write_read1(0x166,0x55,&rx_data); +//SpiPs_write_read1(0x167,0x55,&rx_data); +//SpiPs_write_read1(0x168,0x55,&rx_data); +//SpiPs_write_read1(0x169,0x55,&rx_data); +} diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_HOP/cx9261a_151_config.c b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_HOP/cx9261a_151_config.c new file mode 100644 index 0000000..c1e78f7 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_HOP/cx9261a_151_config.c @@ -0,0 +1,708 @@ +/* + * cx9261_config.c + * + * Created on: 2023Äê10ÔÂ16ÈÕ + * Author: cxlab + */ + +#include "xilinx_io.h" +#include "sleep.h" +void cx9261a_151_config(void){ +u8 rx_data; +int temp; + +//setPin(pin,value) +GpioSetPinDir(0,0x01); +GpioWritePin(0,1); +GpioSetPinDir(32,0x01); +GpioWritePin(32,1); +GpioSetPinDir(33,0x01); +GpioWritePin(33,1); +GpioSetPinDir(34,0x01); +GpioWritePin(34,0); +GpioSetPinDir(35,0x01); //tx:0-rx:1 +GpioWritePin(35,1); //tx:0-rx:1 +GpioSetPinDir(36,0x01); //fdd:0-tdd:1 +GpioWritePin(36,1); //fdd:0-tdd:1 +GpioSetPinDir(37,0x01); //1r1t:0-2r2t:1 +GpioWritePin(37,0); //1r1t:0-2r2t:1 +GpioSetPinDir(38,0x01); //dualport:0-singleport:1 +GpioWritePin(38,1); //dualport:0-singleport:1 +GpioSetPinDir(39,0x01); +GpioWritePin(39,1); +GpioSetPinDir(40,0x01); +GpioWritePin(40,1); +//Èý¸öͨµÀ¹²ͬ¿ØÖÆ +SpiPs_write_read1(0x000,0x02,&rx_data); +//µçԴ¹ÜÀí×Զ¨Òå +//¶ϵçģʽ +SpiPs_write_read1(0x031,0x00,&rx_data); +SpiPs_write_read1(0x032,0x7F,&rx_data); +SpiPs_write_read1(0x033,0xFF,&rx_data); +SpiPs_write_read1(0x034,0xFF,&rx_data); +//ÐÝÃßģʽ +SpiPs_write_read1(0x035,0x00,&rx_data); +SpiPs_write_read1(0x036,0x3D,&rx_data); +SpiPs_write_read1(0x037,0xFF,&rx_data); +SpiPs_write_read1(0x038,0xEB,&rx_data); +//¾¯½äģʽ +SpiPs_write_read1(0x039,0x00,&rx_data); +SpiPs_write_read1(0x03A,0x3D,&rx_data); +SpiPs_write_read1(0x03B,0xFF,&rx_data); +SpiPs_write_read1(0x03C,0xE0,&rx_data); +//У׼ģʽ +SpiPs_write_read1(0x03D,0x1B,&rx_data); +SpiPs_write_read1(0x03E,0x39,&rx_data); +SpiPs_write_read1(0x03F,0x27,&rx_data); +SpiPs_write_read1(0x040,0xE0,&rx_data); +//½ÓÊÕģʽ +SpiPs_write_read1(0x041,0x03,&rx_data); +SpiPs_write_read1(0x042,0x3D,&rx_data); +SpiPs_write_read1(0x043,0xE7,&rx_data); +SpiPs_write_read1(0x044,0xF8,&rx_data); +//·¢Éäģʽ +SpiPs_write_read1(0x045,0x18,&rx_data); +SpiPs_write_read1(0x046,0x3D,&rx_data); +SpiPs_write_read1(0x047,0x3F,&rx_data); +SpiPs_write_read1(0x048,0xF8,&rx_data); +//FDDģʽ +SpiPs_write_read1(0x049,0x1B,&rx_data); +SpiPs_write_read1(0x04A,0x3D,&rx_data); +SpiPs_write_read1(0x04B,0x27,&rx_data); +SpiPs_write_read1(0x04C,0xE0,&rx_data); +//¹۲âģʽ +SpiPs_write_read1(0x04D,0x04,&rx_data); +SpiPs_write_read1(0x04E,0x3D,&rx_data); +SpiPs_write_read1(0x04F,0xD9,&rx_data); +SpiPs_write_read1(0x050,0xFE,&rx_data); +//´ø϶»ù׼ +SpiPs_write_read1(0x773,0x53,&rx_data); +SpiPs_write_read1(0x774,0x86,&rx_data); +//²ο¼ʱÖÓÉèÖà +SpiPs_write_read1(0x789,0x00,&rx_data); +SpiPs_write_read1(0x785,0x49,&rx_data); +SpiPs_write_read1(0x788,0x24,&rx_data); +usleep(10000); +SpiPs_write_read1(0x788,0xA4,&rx_data); +//BBPLL +SpiPs_write_read1(0x0C0,0x50,&rx_data); +SpiPs_write_read1(0x0C1,0x50,&rx_data); +SpiPs_write_read1(0x0C2,0x50,&rx_data); +SpiPs_write_read1(0x601,0x0F,&rx_data); +SpiPs_write_read1(0x602,0x21,&rx_data); +SpiPs_write_read1(0x60D,0x0C,&rx_data); +SpiPs_write_read1(0x60E,0x66,&rx_data); +SpiPs_write_read1(0x60F,0x66,&rx_data); +SpiPs_write_read1(0x610,0x66,&rx_data); +SpiPs_write_read1(0x611,0x13,&rx_data); +SpiPs_write_read1(0x612,0x00,&rx_data); +//ADC +SpiPs_write_read1(0x70B,0x0E,&rx_data); +SpiPs_write_read1(0x727,0x0E,&rx_data); +SpiPs_write_read1(0x743,0x0E,&rx_data); +SpiPs_write_read1(0x70D,0x3F,&rx_data); +SpiPs_write_read1(0x729,0x3F,&rx_data); +SpiPs_write_read1(0x745,0x3F,&rx_data); +SpiPs_write_read1(0x70E,0x48,&rx_data); +SpiPs_write_read1(0x72A,0x48,&rx_data); +SpiPs_write_read1(0x746,0x48,&rx_data); +SpiPs_write_read1(0x70F,0xA0,&rx_data); +SpiPs_write_read1(0x72B,0xA0,&rx_data); +SpiPs_write_read1(0x747,0xA0,&rx_data); +//ͨµÀʱÖÓÀ´Դ +SpiPs_write_read1(0x77D,0xCF,&rx_data); +SpiPs_write_read1(0x775,0x24,&rx_data); +SpiPs_write_read1(0x6C3,0x00,&rx_data); +//PLL1 +SpiPs_write_read1(0x620,0x81,&rx_data); +SpiPs_write_read1(0x61D,0x07,&rx_data); +SpiPs_write_read1(0xB06,0x00,&rx_data); +SpiPs_write_read1(0xB07,0x64,&rx_data); +SpiPs_write_read1(0xB08,0x00,&rx_data); +SpiPs_write_read1(0xB09,0x00,&rx_data); +SpiPs_write_read1(0xB0A,0x00,&rx_data); +SpiPs_write_read1(0x61A,0x0B,&rx_data); +SpiPs_write_read1(0x61B,0x20,&rx_data); +SpiPs_write_read1(0x61C,0x13,&rx_data); +SpiPs_write_read1(0x624,0x11,&rx_data); +SpiPs_write_read1(0x625,0x11,&rx_data); +SpiPs_write_read1(0x62A,0x00,&rx_data); +SpiPs_write_read1(0x61E,0x30,&rx_data); +SpiPs_write_read1(0x61F,0x08,&rx_data); +SpiPs_write_read1(0x621,0x4D,&rx_data); +SpiPs_write_read1(0x622,0x19,&rx_data); +SpiPs_write_read1(0x627,0x10,&rx_data); +//PLL2 +SpiPs_write_read1(0x642,0x91,&rx_data); +SpiPs_write_read1(0x63F,0x36,&rx_data); +SpiPs_write_read1(0xB14,0x00,&rx_data); +SpiPs_write_read1(0xB15,0x70,&rx_data); +SpiPs_write_read1(0xB16,0x00,&rx_data); +SpiPs_write_read1(0xB17,0x00,&rx_data); +SpiPs_write_read1(0xB18,0x00,&rx_data); +SpiPs_write_read1(0x63C,0x0C,&rx_data); +SpiPs_write_read1(0x63D,0x20,&rx_data); +SpiPs_write_read1(0x63E,0x0C,&rx_data); +SpiPs_write_read1(0x646,0x11,&rx_data); +SpiPs_write_read1(0x647,0x11,&rx_data); +SpiPs_write_read1(0x64C,0x00,&rx_data); +SpiPs_write_read1(0x640,0x30,&rx_data); +SpiPs_write_read1(0x641,0x08,&rx_data); +SpiPs_write_read1(0x643,0x4D,&rx_data); +SpiPs_write_read1(0x644,0x19,&rx_data); +SpiPs_write_read1(0x649,0x10,&rx_data); +//PLL3 +SpiPs_write_read1(0x664,0x91,&rx_data); +SpiPs_write_read1(0x661,0x36,&rx_data); +SpiPs_write_read1(0xB22,0x00,&rx_data); +SpiPs_write_read1(0xB23,0x80,&rx_data); +SpiPs_write_read1(0xB24,0x00,&rx_data); +SpiPs_write_read1(0xB25,0x00,&rx_data); +SpiPs_write_read1(0xB26,0x00,&rx_data); +SpiPs_write_read1(0x65E,0x0D,&rx_data); +SpiPs_write_read1(0x65F,0x20,&rx_data); +SpiPs_write_read1(0x660,0x0F,&rx_data); +SpiPs_write_read1(0x668,0x11,&rx_data); +SpiPs_write_read1(0x669,0x11,&rx_data); +SpiPs_write_read1(0x66E,0x00,&rx_data); +SpiPs_write_read1(0x662,0x30,&rx_data); +SpiPs_write_read1(0x663,0x08,&rx_data); +SpiPs_write_read1(0x665,0x4D,&rx_data); +SpiPs_write_read1(0x666,0x19,&rx_data); +SpiPs_write_read1(0x66B,0x10,&rx_data); +//PLL4 +SpiPs_write_read1(0x686,0x81,&rx_data); +SpiPs_write_read1(0x683,0x37,&rx_data); +SpiPs_write_read1(0xB30,0x00,&rx_data); +SpiPs_write_read1(0xB31,0x48,&rx_data); +SpiPs_write_read1(0xB32,0x00,&rx_data); +SpiPs_write_read1(0xB33,0x00,&rx_data); +SpiPs_write_read1(0xB34,0x00,&rx_data); +SpiPs_write_read1(0x680,0x0C,&rx_data); +SpiPs_write_read1(0x681,0x20,&rx_data); +SpiPs_write_read1(0x682,0x11,&rx_data); +SpiPs_write_read1(0x68A,0x11,&rx_data); +SpiPs_write_read1(0x68B,0x11,&rx_data); +SpiPs_write_read1(0x690,0x00,&rx_data); +SpiPs_write_read1(0x684,0x30,&rx_data); +SpiPs_write_read1(0x685,0x08,&rx_data); +SpiPs_write_read1(0x687,0x4D,&rx_data); +SpiPs_write_read1(0x688,0x19,&rx_data); +SpiPs_write_read1(0x68D,0x10,&rx_data); +//PLL5 +SpiPs_write_read1(0x6A8,0x81,&rx_data); +SpiPs_write_read1(0x6A5,0x37,&rx_data); +SpiPs_write_read1(0xB3E,0x00,&rx_data); +SpiPs_write_read1(0xB3F,0x50,&rx_data); +SpiPs_write_read1(0xB40,0x00,&rx_data); +SpiPs_write_read1(0xB41,0x00,&rx_data); +SpiPs_write_read1(0xB42,0x00,&rx_data); +SpiPs_write_read1(0x6A2,0x0C,&rx_data); +SpiPs_write_read1(0x6A3,0x20,&rx_data); +SpiPs_write_read1(0x6A4,0x11,&rx_data); +SpiPs_write_read1(0x6AC,0x11,&rx_data); +SpiPs_write_read1(0x6AD,0x11,&rx_data); +SpiPs_write_read1(0x6B2,0x00,&rx_data); +SpiPs_write_read1(0x6A6,0x30,&rx_data); +SpiPs_write_read1(0x6A7,0x08,&rx_data); +SpiPs_write_read1(0x6A9,0x4D,&rx_data); +SpiPs_write_read1(0x6AA,0x19,&rx_data); +SpiPs_write_read1(0x6AF,0x10,&rx_data); +//RxͨµÀÉèÖà +SpiPs_write_read1(0x700,0x56,&rx_data); +SpiPs_write_read1(0x71C,0x56,&rx_data); +SpiPs_write_read1(0x738,0x56,&rx_data); +SpiPs_write_read1(0x701,0x02,&rx_data); +SpiPs_write_read1(0x702,0x35,&rx_data); +SpiPs_write_read1(0x71D,0x02,&rx_data); +SpiPs_write_read1(0x71E,0x35,&rx_data); +SpiPs_write_read1(0x739,0x02,&rx_data); +SpiPs_write_read1(0x73A,0x35,&rx_data); +SpiPs_write_read1(0x703,0xF6,&rx_data); +SpiPs_write_read1(0x71F,0xF6,&rx_data); +SpiPs_write_read1(0x73B,0xF6,&rx_data); +SpiPs_write_read1(0x704,0xC8,&rx_data); +SpiPs_write_read1(0x720,0xC8,&rx_data); +SpiPs_write_read1(0x73C,0xC8,&rx_data); +SpiPs_write_read1(0x907,0x1F,&rx_data); +SpiPs_write_read1(0x705,0xFC,&rx_data); +SpiPs_write_read1(0x721,0xFC,&rx_data); +SpiPs_write_read1(0x73D,0xFC,&rx_data); +SpiPs_write_read1(0x706,0x65,&rx_data); +SpiPs_write_read1(0x722,0x65,&rx_data); +SpiPs_write_read1(0x73E,0x65,&rx_data); +SpiPs_write_read1(0x707,0x91,&rx_data); +SpiPs_write_read1(0x723,0x91,&rx_data); +SpiPs_write_read1(0x73F,0x91,&rx_data); +SpiPs_write_read1(0x708,0x04,&rx_data); +SpiPs_write_read1(0x724,0x04,&rx_data); +SpiPs_write_read1(0x740,0x04,&rx_data); +SpiPs_write_read1(0x709,0x94,&rx_data); +SpiPs_write_read1(0x725,0x94,&rx_data); +SpiPs_write_read1(0x741,0x94,&rx_data); +SpiPs_write_read1(0x70A,0xFC,&rx_data); +SpiPs_write_read1(0x726,0xFC,&rx_data); +SpiPs_write_read1(0x742,0xFC,&rx_data); +SpiPs_write_read1(0x75A,0x83,&rx_data); +SpiPs_write_read1(0x75B,0xDA,&rx_data); +usleep(100000); +SpiPs_write_read1(0x75B,0x9A,&rx_data); +SpiPs_write_read1(0x75C,0x81,&rx_data); +SpiPs_write_read1(0x75D,0xF8,&rx_data); +SpiPs_write_read1(0x75E,0xA7,&rx_data); +SpiPs_write_read1(0x75F,0x50,&rx_data); +SpiPs_write_read1(0x760,0xFF,&rx_data); +SpiPs_write_read1(0x761,0x07,&rx_data); +SpiPs_write_read1(0x762,0x6C,&rx_data); +SpiPs_write_read1(0x763,0x04,&rx_data); +SpiPs_write_read1(0x764,0x83,&rx_data); +SpiPs_write_read1(0x765,0xDA,&rx_data); +usleep(100000); +SpiPs_write_read1(0x765,0x9A,&rx_data); +SpiPs_write_read1(0x766,0x81,&rx_data); +SpiPs_write_read1(0x767,0xF8,&rx_data); +SpiPs_write_read1(0x768,0xA7,&rx_data); +SpiPs_write_read1(0x769,0x50,&rx_data); +SpiPs_write_read1(0x76A,0xFF,&rx_data); +SpiPs_write_read1(0x76B,0x07,&rx_data); +SpiPs_write_read1(0x76C,0x6C,&rx_data); +SpiPs_write_read1(0x76D,0x04,&rx_data); +//RxÂ˲¨Æ÷ +SpiPs_write_read1(0x106,0x02,&rx_data); +//TxÂ˲¨Æ÷ +SpiPs_write_read1(0x107,0x00,&rx_data); +SpiPs_write_read1(0x108,0xD0,&rx_data); +//Rx NCO +SpiPs_write_read1(0x11C,0x00,&rx_data); +SpiPs_write_read1(0xA07,0x00,&rx_data); +SpiPs_write_read1(0xA08,0x00,&rx_data); +SpiPs_write_read1(0xA16,0x00,&rx_data); +SpiPs_write_read1(0xA17,0x00,&rx_data); +SpiPs_write_read1(0xA18,0x00,&rx_data); +SpiPs_write_read1(0xA19,0x00,&rx_data); +SpiPs_write_read1(0xA1A,0x00,&rx_data); +SpiPs_write_read1(0xA1B,0x00,&rx_data); +//Tx NCO +SpiPs_write_read1(0x128,0x10,&rx_data); +SpiPs_write_read1(0x11B,0x01,&rx_data); +SpiPs_write_read1(0x11E,0x01,&rx_data); +SpiPs_write_read1(0x161,0x01,&rx_data); +SpiPs_write_read1(0x162,0x01,&rx_data); +SpiPs_write_read1(0x164,0x05,&rx_data); +SpiPs_write_read1(0x165,0x55,&rx_data); +SpiPs_write_read1(0x166,0x55,&rx_data); +SpiPs_write_read1(0x167,0x55,&rx_data); +SpiPs_write_read1(0x168,0x55,&rx_data); +SpiPs_write_read1(0x169,0x55,&rx_data); +//AGCÅäÖà +SpiPs_write_read1(0x900,0x00,&rx_data); +SpiPs_write_read1(0x901,0x00,&rx_data); +SpiPs_write_read1(0x903,0x11,&rx_data); +SpiPs_write_read1(0x908,0x77,&rx_data); +SpiPs_write_read1(0x909,0x03,&rx_data); +SpiPs_write_read1(0x90A,0x32,&rx_data); +SpiPs_write_read1(0x90D,0x00,&rx_data); +SpiPs_write_read1(0x90E,0x0F,&rx_data); +SpiPs_write_read1(0x90F,0x65,&rx_data); +SpiPs_write_read1(0x910,0x32,&rx_data); +SpiPs_write_read1(0x911,0x00,&rx_data); +SpiPs_write_read1(0x912,0x0F,&rx_data); +SpiPs_write_read1(0x913,0x3A,&rx_data); +SpiPs_write_read1(0x914,0x37,&rx_data); +SpiPs_write_read1(0x915,0x34,&rx_data); +SpiPs_write_read1(0x916,0x31,&rx_data); +//½øÈëÐÝÃßģʽ +SpiPs_write_read1(0x02E,0x01,&rx_data); +usleep(1000000); +//½øÈëУ׼ģʽ +SpiPs_write_read1(0x02E,0x03,&rx_data); +usleep(100000); +//BBPLL AFC +SpiPs_write_read1(0x600,0x00,&rx_data); +SpiPs_write_read1(0x600,0x11,&rx_data); +usleep(50); +//PLL1 AFC +while(temp != 48) +{ +SpiPs_write_read1(0x617,0x00,&rx_data); +SpiPs_write_read1(0x617,0x03,&rx_data); +usleep(100); +SpiPs_write_read2(0x635,0x00,&rx_data); +temp=rx_data; +} +//½ӿÚÅäÖà +SpiPs_write_read1(0x02E,0x06,&rx_data); +SpiPs_write_read1(0x003,0x33,&rx_data); +SpiPs_write_read1(0x200,0x00,&rx_data); +SpiPs_write_read1(0x201,0x00,&rx_data); +SpiPs_write_read1(0x202,0x03,&rx_data); +SpiPs_write_read1(0x208,0x00,&rx_data); +SpiPs_write_read1(0x209,0x00,&rx_data); +SpiPs_write_read1(0x780,0x11,&rx_data); +SpiPs_write_read1(0x781,0x6F,&rx_data); +SpiPs_write_read1(0x782,0x01,&rx_data); +SpiPs_write_read1(0x783,0x01,&rx_data); +SpiPs_write_read1(0x784,0x01,&rx_data); +//ADCУ׼ +SpiPs_write_read1(0x70B,0x1E,&rx_data); +SpiPs_write_read1(0x727,0x1E,&rx_data); +SpiPs_write_read1(0x743,0x1E,&rx_data); +SpiPs_write_read1(0x70F,0xA0,&rx_data); +SpiPs_write_read1(0x710,0x83,&rx_data); +SpiPs_write_read1(0x711,0xF0,&rx_data); +SpiPs_write_read1(0x72B,0xA0,&rx_data); +SpiPs_write_read1(0x72C,0x83,&rx_data); +SpiPs_write_read1(0x72D,0xF0,&rx_data); +SpiPs_write_read1(0x747,0xA0,&rx_data); +SpiPs_write_read1(0x748,0x83,&rx_data); +SpiPs_write_read1(0x749,0xF0,&rx_data); +SpiPs_write_read1(0x713,0x80,&rx_data); +SpiPs_write_read1(0x72F,0x80,&rx_data); +SpiPs_write_read1(0x74B,0x80,&rx_data); +SpiPs_write_read1(0x70B,0x9E,&rx_data); +SpiPs_write_read1(0x727,0x9E,&rx_data); +SpiPs_write_read1(0x743,0x9E,&rx_data); +SpiPs_write_read1(0x70B,0x9A,&rx_data); +SpiPs_write_read1(0x727,0x9A,&rx_data); +SpiPs_write_read1(0x743,0x9A,&rx_data); +SpiPs_write_read1(0x70B,0x9E,&rx_data); +SpiPs_write_read1(0x727,0x9E,&rx_data); +SpiPs_write_read1(0x743,0x9E,&rx_data); +usleep(100000); +SpiPs_write_read1(0x70B,0x1E,&rx_data); +SpiPs_write_read1(0x727,0x1E,&rx_data); +SpiPs_write_read1(0x743,0x1E,&rx_data); +SpiPs_write_read1(0x713,0xC0,&rx_data); +SpiPs_write_read1(0x72F,0xC0,&rx_data); +SpiPs_write_read1(0x74B,0xC0,&rx_data); +//FlashУ׼ +SpiPs_write_read1(0x70B,0x1E,&rx_data); +SpiPs_write_read1(0x727,0x1E,&rx_data); +SpiPs_write_read1(0x743,0x1E,&rx_data); +SpiPs_write_read1(0x715,0x80,&rx_data); +SpiPs_write_read1(0x731,0x80,&rx_data); +SpiPs_write_read1(0x74D,0x80,&rx_data); +SpiPs_write_read1(0x715,0xC0,&rx_data); +SpiPs_write_read1(0x731,0xC0,&rx_data); +SpiPs_write_read1(0x74D,0xC0,&rx_data); +SpiPs_write_read1(0x716,0x40,&rx_data); +SpiPs_write_read1(0x732,0x40,&rx_data); +SpiPs_write_read1(0x74E,0x40,&rx_data); +SpiPs_write_read1(0x70B,0x16,&rx_data); +SpiPs_write_read1(0x727,0x16,&rx_data); +SpiPs_write_read1(0x743,0x16,&rx_data); +usleep(100000); +SpiPs_write_read1(0x70B,0x1E,&rx_data); +SpiPs_write_read1(0x727,0x1E,&rx_data); +SpiPs_write_read1(0x743,0x1E,&rx_data); +SpiPs_write_read1(0x715,0x80,&rx_data); +SpiPs_write_read1(0x731,0x80,&rx_data); +SpiPs_write_read1(0x74D,0x80,&rx_data); +SpiPs_write_read1(0x716,0x00,&rx_data); +SpiPs_write_read1(0x732,0x00,&rx_data); +SpiPs_write_read1(0x74E,0x00,&rx_data); +SpiPs_write_read1(0x109,0x11,&rx_data); +SpiPs_write_read1(0x10A,0x70,&rx_data); +SpiPs_write_read1(0x11F,0x33,&rx_data); +//QECУ׼ +//Rx TST Calibration +SpiPs_write_read1(0x000,0x12,&rx_data); +SpiPs_write_read1(0x109,0x00,&rx_data); +SpiPs_write_read1(0x77E,0x50,&rx_data); +SpiPs_write_read1(0x14E,0x00,&rx_data); +// Ð޸ÄУ׼ģʽµçԴ¹ÜÀí +SpiPs_write_read1(0x03D,0x09,&rx_data); +SpiPs_write_read1(0x03E,0x39,&rx_data); +SpiPs_write_read1(0x03F,0xB6,&rx_data); +SpiPs_write_read1(0x040,0x78,&rx_data); +//Ð޸ĵçԴģʽ +SpiPs_write_read1(0x02E,0x03,&rx_data); +//Calibration PLL Source +// Ð޸ÄPllÀ´Դ +SpiPs_write_read1(0x77D,0x90,&rx_data); +SpiPs_write_read1(0x6C3,0x05,&rx_data); +SpiPs_write_read1(0x775,0x24,&rx_data); +//Ð޸ÄPll4ƵÂÊ +//PLL4 +SpiPs_write_read1(0x686,0x81,&rx_data); +SpiPs_write_read1(0x683,0x07,&rx_data); +SpiPs_write_read1(0xB30,0x00,&rx_data); +SpiPs_write_read1(0xB31,0x63,&rx_data); +SpiPs_write_read1(0xB32,0xEB,&rx_data); +SpiPs_write_read1(0xB33,0x85,&rx_data); +SpiPs_write_read1(0xB34,0x1E,&rx_data); +SpiPs_write_read1(0x680,0x0B,&rx_data); +SpiPs_write_read1(0x681,0x20,&rx_data); +SpiPs_write_read1(0x682,0x13,&rx_data); +SpiPs_write_read1(0x68A,0x11,&rx_data); +SpiPs_write_read1(0x68B,0x11,&rx_data); +SpiPs_write_read1(0x690,0x0B,&rx_data); +SpiPs_write_read1(0x684,0x30,&rx_data); +SpiPs_write_read1(0x685,0x08,&rx_data); +SpiPs_write_read1(0x687,0x4D,&rx_data); +SpiPs_write_read1(0x688,0x19,&rx_data); +SpiPs_write_read1(0x68D,0x10,&rx_data); +//PLL4 AFC +while(temp != 48) +{ +SpiPs_write_read1(0x67D,0x00,&rx_data); +SpiPs_write_read1(0x67D,0x03,&rx_data); +usleep(100); +SpiPs_write_read2(0x69B,0x00,&rx_data); +temp=rx_data; +} +SpiPs_write_read1(0x02A,0x00,&rx_data); +SpiPs_write_read1(0x121,0x00,&rx_data); +SpiPs_write_read1(0x11F,0x73,&rx_data); +SpiPs_write_read1(0x124,0xFF,&rx_data); +SpiPs_write_read1(0x120,0x00,&rx_data); +SpiPs_write_read1(0x122,0x03,&rx_data); +SpiPs_write_read1(0x126,0x01,&rx_data); +SpiPs_write_read1(0x02A,0x12,&rx_data); + +SpiPs_write_read2(0x14D,0x00,&rx_data); +temp=rx_data & 0x10; +while(temp != 16){ +SpiPs_write_read2(0x14D,0x00,&rx_data); +temp=rx_data & 0x10; +usleep(100000); +} + +SpiPs_write_read1(0x77E,0x00,&rx_data); +SpiPs_write_read1(0x775,0x24,&rx_data); +SpiPs_write_read1(0x77D,0xCF,&rx_data); +SpiPs_write_read1(0x6C3,0x00,&rx_data); +//Rx TST Calibration +SpiPs_write_read1(0x000,0x22,&rx_data); +SpiPs_write_read1(0x109,0x00,&rx_data); +SpiPs_write_read1(0x77E,0x0A,&rx_data); +SpiPs_write_read1(0x14E,0x00,&rx_data); +// Ð޸ÄУ׼ģʽµçԴ¹ÜÀí +SpiPs_write_read1(0x03D,0x12,&rx_data); +SpiPs_write_read1(0x03E,0x39,&rx_data); +SpiPs_write_read1(0x03F,0x6E,&rx_data); +SpiPs_write_read1(0x040,0x78,&rx_data); +//Ð޸ĵçԴģʽ +SpiPs_write_read1(0x02E,0x03,&rx_data); +//Calibration PLL Source +// Ð޸ÄPllÀ´Դ +SpiPs_write_read1(0x77D,0x60,&rx_data); +SpiPs_write_read1(0x6C3,0x0A,&rx_data); +SpiPs_write_read1(0x775,0x24,&rx_data); +//Ð޸ÄPll4ƵÂÊ +//PLL4 +SpiPs_write_read1(0x686,0x81,&rx_data); +SpiPs_write_read1(0x683,0x07,&rx_data); +SpiPs_write_read1(0xB30,0x00,&rx_data); +SpiPs_write_read1(0xB31,0x63,&rx_data); +SpiPs_write_read1(0xB32,0xEB,&rx_data); +SpiPs_write_read1(0xB33,0x85,&rx_data); +SpiPs_write_read1(0xB34,0x1E,&rx_data); +SpiPs_write_read1(0x680,0x0B,&rx_data); +SpiPs_write_read1(0x681,0x20,&rx_data); +SpiPs_write_read1(0x682,0x13,&rx_data); +SpiPs_write_read1(0x68A,0x11,&rx_data); +SpiPs_write_read1(0x68B,0x11,&rx_data); +SpiPs_write_read1(0x690,0x0B,&rx_data); +SpiPs_write_read1(0x684,0x30,&rx_data); +SpiPs_write_read1(0x685,0x08,&rx_data); +SpiPs_write_read1(0x687,0x4D,&rx_data); +SpiPs_write_read1(0x688,0x19,&rx_data); +SpiPs_write_read1(0x68D,0x10,&rx_data); +//PLL4 AFC +while(temp != 48) +{ +SpiPs_write_read1(0x67D,0x00,&rx_data); +SpiPs_write_read1(0x67D,0x03,&rx_data); +usleep(100); +SpiPs_write_read2(0x69B,0x00,&rx_data); +temp=rx_data; +} +SpiPs_write_read1(0x02B,0x00,&rx_data); +SpiPs_write_read1(0x121,0x00,&rx_data); +SpiPs_write_read1(0x11F,0x73,&rx_data); +SpiPs_write_read1(0x124,0xFF,&rx_data); +SpiPs_write_read1(0x120,0x00,&rx_data); +SpiPs_write_read1(0x122,0x03,&rx_data); +SpiPs_write_read1(0x126,0x01,&rx_data); +SpiPs_write_read1(0x02B,0x12,&rx_data); + +SpiPs_write_read2(0x14D,0x00,&rx_data); +temp=rx_data & 0x10; +while(temp != 16){ +SpiPs_write_read2(0x14D,0x00,&rx_data); +temp=rx_data & 0x10; +usleep(100000); +} + +SpiPs_write_read1(0x77E,0x00,&rx_data); +SpiPs_write_read1(0x775,0x24,&rx_data); +SpiPs_write_read1(0x77D,0xCF,&rx_data); +SpiPs_write_read1(0x6C3,0x00,&rx_data); +SpiPs_write_read1(0x02C,0x00,&rx_data); +SpiPs_write_read1(0x02B,0x00,&rx_data); +SpiPs_write_read1(0x02A,0x00,&rx_data); +//»ָ´У׼ǰÉèÖà +SpiPs_write_read1(0x000,0x02,&rx_data); +SpiPs_write_read1(0x02E,0x06,&rx_data); +SpiPs_write_read1(0x03D,0x1B,&rx_data); +SpiPs_write_read1(0x03E,0x39,&rx_data); +SpiPs_write_read1(0x03F,0x27,&rx_data); +SpiPs_write_read1(0x040,0xF8,&rx_data); +SpiPs_write_read1(0x109,0x11,&rx_data); +SpiPs_write_read1(0x10A,0x70,&rx_data); +SpiPs_write_read1(0x11B,0x01,&rx_data); +SpiPs_write_read1(0x11E,0x01,&rx_data); +SpiPs_write_read1(0x11F,0x33,&rx_data); +SpiPs_write_read1(0x128,0x10,&rx_data); +SpiPs_write_read1(0x161,0x01,&rx_data); +SpiPs_write_read1(0x162,0x01,&rx_data); +SpiPs_write_read1(0x164,0x05,&rx_data); +SpiPs_write_read1(0x165,0x55,&rx_data); +SpiPs_write_read1(0x166,0x55,&rx_data); +SpiPs_write_read1(0x167,0x55,&rx_data); +SpiPs_write_read1(0x168,0x55,&rx_data); +SpiPs_write_read1(0x169,0x55,&rx_data); +SpiPs_write_read1(0xA07,0x00,&rx_data); +SpiPs_write_read1(0xA08,0x00,&rx_data); +SpiPs_write_read1(0xA16,0x00,&rx_data); +SpiPs_write_read1(0xA17,0x00,&rx_data); +SpiPs_write_read1(0xA18,0x00,&rx_data); +SpiPs_write_read1(0xA19,0x00,&rx_data); +SpiPs_write_read1(0xA1A,0x00,&rx_data); +SpiPs_write_read1(0xA1B,0x00,&rx_data); +SpiPs_write_read1(0xA1C,0x00,&rx_data); +SpiPs_write_read1(0xA2D,0x00,&rx_data); +// TX¶þ·ַ¨У׼ +// Ð޸ÄУ׼ģʽµçԴ¹ÜÀí +SpiPs_write_read1(0x03D,0x1B,&rx_data); +SpiPs_write_read1(0x03E,0x39,&rx_data); +SpiPs_write_read1(0x03F,0x27,&rx_data); +SpiPs_write_read1(0x040,0xF8,&rx_data); +//Ð޸ĵçԴģʽ +SpiPs_write_read1(0x02E,0x03,&rx_data); +SpiPs_write_read1(0x128,0x11,&rx_data); +SpiPs_write_read1(0x11E,0x01,&rx_data); +SpiPs_write_read1(0x77E,0x24,&rx_data); +SpiPs_write_read1(0x11F,0x01,&rx_data); +SpiPs_write_read1(0x121,0x02,&rx_data); +SpiPs_write_read1(0x11B,0x01,&rx_data); +SpiPs_write_read1(0x161,0x01,&rx_data); +SpiPs_write_read1(0x162,0x01,&rx_data); +SpiPs_write_read1(0x163,0x00,&rx_data); +SpiPs_write_read1(0x164,0x05,&rx_data); +SpiPs_write_read1(0x165,0x55,&rx_data); +SpiPs_write_read1(0x166,0x55,&rx_data); +SpiPs_write_read1(0x167,0x55,&rx_data); +SpiPs_write_read1(0x168,0x55,&rx_data); +SpiPs_write_read1(0x169,0x55,&rx_data); +SpiPs_write_read1(0xA2D,0x02,&rx_data); +SpiPs_write_read1(0xA07,0x00,&rx_data); +SpiPs_write_read1(0xA08,0x0F,&rx_data); +SpiPs_write_read1(0xA1C,0x01,&rx_data); +SpiPs_write_read1(0xA16,0x2A,&rx_data); +SpiPs_write_read1(0xA17,0xAA,&rx_data); +SpiPs_write_read1(0xA18,0xAA,&rx_data); +SpiPs_write_read1(0xA19,0xAA,&rx_data); +SpiPs_write_read1(0xA1A,0xAA,&rx_data); +SpiPs_write_read1(0xA1B,0xAA,&rx_data); +SpiPs_write_read1(0x186,0x01,&rx_data); +SpiPs_write_read1(0x763,0x34,&rx_data); +SpiPs_write_read1(0x76D,0x34,&rx_data); +SpiPs_write_read1(0x101,0xEF,&rx_data); +SpiPs_write_read1(0x101,0xFF,&rx_data); +SpiPs_write_read1(0x800,0x00,&rx_data); +SpiPs_write_read1(0x81A,0xF7,&rx_data); +SpiPs_write_read1(0x81B,0x34,&rx_data); +SpiPs_write_read1(0x81C,0x33,&rx_data); +SpiPs_write_read1(0x81D,0x12,&rx_data); +SpiPs_write_read1(0x81E,0x00,&rx_data); +SpiPs_write_read1(0x81F,0xFF,&rx_data); +SpiPs_write_read1(0x820,0x00,&rx_data); +SpiPs_write_read1(0x821,0xFF,&rx_data); +SpiPs_write_read1(0x800,0x80,&rx_data); +SpiPs_write_read1(0x800,0x81,&rx_data); +//×îÉÙ0.1s +usleep(100000); +SpiPs_write_read1(0x77E,0x00,&rx_data); +SpiPs_write_read1(0x77E,0x24,&rx_data); +SpiPs_write_read1(0x11F,0x03,&rx_data); +SpiPs_write_read1(0x121,0x02,&rx_data); +SpiPs_write_read1(0x11B,0x01,&rx_data); +SpiPs_write_read1(0x11E,0x01,&rx_data); +SpiPs_write_read1(0x161,0x01,&rx_data); +SpiPs_write_read1(0x162,0x01,&rx_data); +SpiPs_write_read1(0x164,0x05,&rx_data); +SpiPs_write_read1(0x165,0x55,&rx_data); +SpiPs_write_read1(0x166,0x55,&rx_data); +SpiPs_write_read1(0x167,0x55,&rx_data); +SpiPs_write_read1(0x168,0x55,&rx_data); +SpiPs_write_read1(0x169,0x55,&rx_data); +SpiPs_write_read1(0xA2D,0x02,&rx_data); +SpiPs_write_read1(0xA07,0x00,&rx_data); +SpiPs_write_read1(0xA08,0x0F,&rx_data); +SpiPs_write_read1(0xA1C,0x01,&rx_data); +SpiPs_write_read1(0xA16,0x15,&rx_data); +SpiPs_write_read1(0xA17,0x55,&rx_data); +SpiPs_write_read1(0xA18,0x55,&rx_data); +SpiPs_write_read1(0xA19,0x55,&rx_data); +SpiPs_write_read1(0xA1A,0x55,&rx_data); +SpiPs_write_read1(0xA1B,0x55,&rx_data); +SpiPs_write_read1(0x81A,0xF7,&rx_data); +SpiPs_write_read1(0x81B,0x44,&rx_data); +SpiPs_write_read1(0x81C,0x33,&rx_data); +SpiPs_write_read1(0x81D,0x14,&rx_data); +SpiPs_write_read1(0x800,0x80,&rx_data); +SpiPs_write_read1(0x800,0x82,&rx_data); +//×îÉÙ0.1s +usleep(500000); +SpiPs_write_read1(0x77E,0x00,&rx_data); +//»ָ´У׼ǰÉèÖà +SpiPs_write_read1(0x000,0x02,&rx_data); +SpiPs_write_read1(0x02E,0x06,&rx_data); +SpiPs_write_read1(0x03D,0x1B,&rx_data); +SpiPs_write_read1(0x03E,0x39,&rx_data); +SpiPs_write_read1(0x03F,0x27,&rx_data); +SpiPs_write_read1(0x040,0xF8,&rx_data); +SpiPs_write_read1(0x109,0x11,&rx_data); +SpiPs_write_read1(0x10A,0x70,&rx_data); +SpiPs_write_read1(0x11B,0x01,&rx_data); +SpiPs_write_read1(0x11E,0x01,&rx_data); +SpiPs_write_read1(0x11F,0x33,&rx_data); +SpiPs_write_read1(0x128,0x10,&rx_data); +SpiPs_write_read1(0x161,0x01,&rx_data); +SpiPs_write_read1(0x162,0x01,&rx_data); +SpiPs_write_read1(0x164,0x05,&rx_data); +SpiPs_write_read1(0x165,0x55,&rx_data); +SpiPs_write_read1(0x166,0x55,&rx_data); +SpiPs_write_read1(0x167,0x55,&rx_data); +SpiPs_write_read1(0x168,0x55,&rx_data); +SpiPs_write_read1(0x169,0x55,&rx_data); +SpiPs_write_read1(0xA07,0x00,&rx_data); +SpiPs_write_read1(0xA08,0x00,&rx_data); +SpiPs_write_read1(0xA16,0x00,&rx_data); +SpiPs_write_read1(0xA17,0x00,&rx_data); +SpiPs_write_read1(0xA18,0x00,&rx_data); +SpiPs_write_read1(0xA19,0x00,&rx_data); +SpiPs_write_read1(0xA1A,0x00,&rx_data); +SpiPs_write_read1(0xA1B,0x00,&rx_data); +SpiPs_write_read1(0xA1C,0x00,&rx_data); +SpiPs_write_read1(0xA2D,0x00,&rx_data); +usleep(1000); +SpiPs_write_read2(0x615,0x00,&rx_data); +temp=rx_data; +SpiPs_write_read2(0x635,0x00,&rx_data); +temp=rx_data; +////ÅäÖÃTx NCO BIST ON +//SpiPs_write_read1(0x11B,0x01,&rx_data); +//SpiPs_write_read1(0x11E,0x01,&rx_data); +//SpiPs_write_read1(0x161,0x01,&rx_data); +//SpiPs_write_read1(0x162,0x01,&rx_data); +////ÅäÖÃTx NCOƵÂÊ 1MHz +//SpiPs_write_read1(0x164,0x05,&rx_data); +//SpiPs_write_read1(0x165,0x55,&rx_data); +//SpiPs_write_read1(0x166,0x55,&rx_data); +//SpiPs_write_read1(0x167,0x55,&rx_data); +//SpiPs_write_read1(0x168,0x55,&rx_data); +//SpiPs_write_read1(0x169,0x55,&rx_data); +} diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_HOP/cx9261a_710_config.c b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_HOP/cx9261a_710_config.c new file mode 100644 index 0000000..c8bb612 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_HOP/cx9261a_710_config.c @@ -0,0 +1,835 @@ +/* + * cx9261a_710_config.c + * + * Created on: 2024Äê3ÔÂ21ÈÕ + * Author: cxlab + */ + + +/* + * cx9261a_076_config.c + * + * Created on: 2023Äê11ÔÂ30ÈÕ + * Author: cxlab + */ + + +#include "xilinx_io.h" +#include "sleep.h" +void cx9261a_710_config(void){ +u8 rx_data; +u8 temp,r13D,r13E; + +//setPin(pin,value) +GpioSetPinDir(0,0x01); +GpioWritePin(0,1); +GpioSetPinDir(32,0x01); +GpioWritePin(32,1); +GpioSetPinDir(33,0x01); +GpioWritePin(33,1); +GpioSetPinDir(34,0x01); +GpioWritePin(34,0); +GpioSetPinDir(35,0x01); //tx:0-rx:1 +GpioWritePin(35,1); //tx:0-rx:1 +GpioSetPinDir(36,0x01); //fdd:0-tdd:1 +GpioWritePin(36,1); //fdd:0-tdd:1 +GpioSetPinDir(37,0x01); //1r1t:0-2r2t:1 +GpioWritePin(37,1); //1r1t:0-2r2t:1 +GpioSetPinDir(38,0x01); //dualport:0-singleport:1 +GpioWritePin(38,1); //dualport:0-singleport:1 +GpioSetPinDir(39,0x01); +GpioWritePin(39,1); +GpioSetPinDir(40,0x01); +GpioWritePin(40,1); +//ÅäÖÃоƬ +//³õʼ»¯оƬ +SpiPs_write_read1(0x000,0x02,&rx_data); +SpiPs_write_read1(0x773,0x53,&rx_data); +SpiPs_write_read1(0x774,0x86,&rx_data); +SpiPs_write_read1(0x781,0x6F,&rx_data); +SpiPs_write_read1(0x70B,0x0E,&rx_data); +SpiPs_write_read1(0x727,0x0E,&rx_data); +SpiPs_write_read1(0x743,0x0E,&rx_data); +SpiPs_write_read1(0x624,0x11,&rx_data); +SpiPs_write_read1(0x625,0x11,&rx_data); +SpiPs_write_read1(0x61E,0x30,&rx_data); +SpiPs_write_read1(0x61F,0x08,&rx_data); +SpiPs_write_read1(0x621,0x4D,&rx_data); +SpiPs_write_read1(0x622,0x19,&rx_data); +SpiPs_write_read1(0x627,0x10,&rx_data); +SpiPs_write_read1(0x646,0x11,&rx_data); +SpiPs_write_read1(0x647,0x11,&rx_data); +SpiPs_write_read1(0x640,0x30,&rx_data); +SpiPs_write_read1(0x641,0x08,&rx_data); +SpiPs_write_read1(0x643,0x4D,&rx_data); +SpiPs_write_read1(0x644,0x19,&rx_data); +SpiPs_write_read1(0x649,0x10,&rx_data); +SpiPs_write_read1(0x668,0x11,&rx_data); +SpiPs_write_read1(0x669,0x11,&rx_data); +SpiPs_write_read1(0x662,0x30,&rx_data); +SpiPs_write_read1(0x663,0x08,&rx_data); +SpiPs_write_read1(0x665,0x4D,&rx_data); +SpiPs_write_read1(0x666,0x19,&rx_data); +SpiPs_write_read1(0x66B,0x10,&rx_data); +SpiPs_write_read1(0x68A,0x11,&rx_data); +SpiPs_write_read1(0x68B,0x11,&rx_data); +SpiPs_write_read1(0x684,0x30,&rx_data); +SpiPs_write_read1(0x685,0x08,&rx_data); +SpiPs_write_read1(0x687,0x4D,&rx_data); +SpiPs_write_read1(0x688,0x19,&rx_data); +SpiPs_write_read1(0x68D,0x10,&rx_data); +SpiPs_write_read1(0x6AC,0x11,&rx_data); +SpiPs_write_read1(0x6AD,0x11,&rx_data); +SpiPs_write_read1(0x6A6,0x30,&rx_data); +SpiPs_write_read1(0x6A7,0x08,&rx_data); +SpiPs_write_read1(0x6A9,0x4D,&rx_data); +SpiPs_write_read1(0x6AA,0x19,&rx_data); +SpiPs_write_read1(0x6AF,0x10,&rx_data); +SpiPs_write_read1(0x705,0xFC,&rx_data); +SpiPs_write_read1(0x706,0x6D,&rx_data); +SpiPs_write_read1(0x707,0x91,&rx_data); +SpiPs_write_read1(0x708,0x04,&rx_data); +SpiPs_write_read1(0x709,0x94,&rx_data); +SpiPs_write_read1(0x70A,0xFC,&rx_data); +SpiPs_write_read1(0x70C,0xC0,&rx_data); +SpiPs_write_read1(0x721,0xFC,&rx_data); +SpiPs_write_read1(0x722,0x6D,&rx_data); +SpiPs_write_read1(0x723,0x91,&rx_data); +SpiPs_write_read1(0x724,0x04,&rx_data); +SpiPs_write_read1(0x725,0x94,&rx_data); +SpiPs_write_read1(0x726,0xFC,&rx_data); +SpiPs_write_read1(0x728,0xC0,&rx_data); +SpiPs_write_read1(0x73D,0xFC,&rx_data); +SpiPs_write_read1(0x73E,0x6D,&rx_data); +SpiPs_write_read1(0x73F,0x91,&rx_data); +SpiPs_write_read1(0x740,0x04,&rx_data); +SpiPs_write_read1(0x741,0x94,&rx_data); +SpiPs_write_read1(0x742,0xFC,&rx_data); +SpiPs_write_read1(0x744,0xC0,&rx_data); +SpiPs_write_read1(0x75A,0x83,&rx_data); +SpiPs_write_read1(0x75B,0xDA,&rx_data); +usleep(100000); +SpiPs_write_read1(0x75B,0x9A,&rx_data); +SpiPs_write_read1(0x75C,0x81,&rx_data); +SpiPs_write_read1(0x763,0x04,&rx_data); +SpiPs_write_read1(0x764,0x83,&rx_data); +SpiPs_write_read1(0x765,0xDA,&rx_data); +usleep(100000); +SpiPs_write_read1(0x765,0x9A,&rx_data); +SpiPs_write_read1(0x766,0x81,&rx_data); +SpiPs_write_read1(0x76D,0x04,&rx_data); +//³õʼ»¯µçԴ +SpiPs_write_read1(0x031,0x00,&rx_data); +SpiPs_write_read1(0x032,0x7F,&rx_data); +SpiPs_write_read1(0x033,0xFF,&rx_data); +SpiPs_write_read1(0x034,0xFF,&rx_data); +SpiPs_write_read1(0x035,0x00,&rx_data); +SpiPs_write_read1(0x036,0x3D,&rx_data); +SpiPs_write_read1(0x037,0xFF,&rx_data); +SpiPs_write_read1(0x038,0xFB,&rx_data); +SpiPs_write_read1(0x039,0x00,&rx_data); +SpiPs_write_read1(0x03A,0x3D,&rx_data); +SpiPs_write_read1(0x03B,0xFF,&rx_data); +SpiPs_write_read1(0x03C,0xF8,&rx_data); +SpiPs_write_read1(0x03D,0x1B,&rx_data); +SpiPs_write_read1(0x03E,0x39,&rx_data); +SpiPs_write_read1(0x03F,0x26,&rx_data); +SpiPs_write_read1(0x040,0x78,&rx_data); +SpiPs_write_read1(0x041,0x03,&rx_data); +SpiPs_write_read1(0x042,0x3D,&rx_data); +SpiPs_write_read1(0x043,0xE7,&rx_data); +SpiPs_write_read1(0x044,0xF8,&rx_data); +SpiPs_write_read1(0x045,0x18,&rx_data); +SpiPs_write_read1(0x046,0x3D,&rx_data); +SpiPs_write_read1(0x047,0x3F,&rx_data); +SpiPs_write_read1(0x048,0xF8,&rx_data); +SpiPs_write_read1(0x049,0x1F,&rx_data); +SpiPs_write_read1(0x04A,0x3D,&rx_data); +SpiPs_write_read1(0x04B,0x07,&rx_data); +SpiPs_write_read1(0x04C,0xF8,&rx_data); +SpiPs_write_read1(0x04D,0x04,&rx_data); +SpiPs_write_read1(0x04E,0x3D,&rx_data); +SpiPs_write_read1(0x04F,0xD9,&rx_data); +SpiPs_write_read1(0x050,0xFE,&rx_data); +//×Զ¨Òå½ÓÊÕģʽ +SpiPs_write_read1(0x041,0x03,&rx_data); +SpiPs_write_read1(0x042,0x3D,&rx_data); +SpiPs_write_read1(0x043,0xE7,&rx_data); +SpiPs_write_read1(0x044,0xF8,&rx_data); +//×Զ¨Ò巢Éäģʽ +SpiPs_write_read1(0x045,0x18,&rx_data); +SpiPs_write_read1(0x046,0x3D,&rx_data); +SpiPs_write_read1(0x047,0x3F,&rx_data); +SpiPs_write_read1(0x048,0xF8,&rx_data); +//×Զ¨ÒåFDDģʽ +SpiPs_write_read1(0x049,0x1B,&rx_data); +SpiPs_write_read1(0x04A,0x3D,&rx_data); +SpiPs_write_read1(0x04B,0x27,&rx_data); +SpiPs_write_read1(0x04C,0xF8,&rx_data); +//ÅäÖÃBBPLL +SpiPs_write_read1(0x789,0x10,&rx_data); +SpiPs_write_read1(0x785,0x49,&rx_data); +SpiPs_write_read1(0x788,0x24,&rx_data); +usleep(100000); +SpiPs_write_read1(0x788,0xA4,&rx_data); +SpiPs_write_read1(0x0C0,0x50,&rx_data); +SpiPs_write_read1(0x0C1,0x50,&rx_data); +SpiPs_write_read1(0x0C2,0x50,&rx_data); +SpiPs_write_read1(0x601,0x0F,&rx_data); +SpiPs_write_read1(0x602,0x21,&rx_data); +SpiPs_write_read1(0x60D,0x0D,&rx_data); +SpiPs_write_read1(0x60E,0xFF,&rx_data); +SpiPs_write_read1(0x60F,0xFF,&rx_data); +SpiPs_write_read1(0x610,0xFF,&rx_data); +SpiPs_write_read1(0x611,0x2F,&rx_data); +SpiPs_write_read1(0x612,0x00,&rx_data); +SpiPs_write_read1(0x70E,0x6B,&rx_data); +SpiPs_write_read1(0x72A,0x6B,&rx_data); +SpiPs_write_read1(0x746,0x6B,&rx_data); +SpiPs_write_read1(0x70F,0xE0,&rx_data); +SpiPs_write_read1(0x72B,0xE0,&rx_data); +SpiPs_write_read1(0x747,0xE0,&rx_data); +SpiPs_write_read1(0x70D,0x43,&rx_data); +SpiPs_write_read1(0x729,0x43,&rx_data); +SpiPs_write_read1(0x745,0x43,&rx_data); +SpiPs_write_read1(0x782,0x76,&rx_data); +SpiPs_write_read1(0x783,0x76,&rx_data); +SpiPs_write_read1(0x784,0x06,&rx_data); +//ÅäÖÃPLLÀ´Դ +SpiPs_write_read1(0x77D,0xCF,&rx_data); +SpiPs_write_read1(0x775,0x24,&rx_data); +SpiPs_write_read1(0x6C3,0x00,&rx_data); +//ÅäÖÃPLL1 +SpiPs_write_read1(0x620,0x91,&rx_data); +SpiPs_write_read1(0x61D,0x37,&rx_data); +SpiPs_write_read1(0xB06,0x00,&rx_data); +SpiPs_write_read1(0xB07,0xCB,&rx_data); +SpiPs_write_read1(0xB08,0x20,&rx_data); +SpiPs_write_read1(0xB09,0x00,&rx_data); +SpiPs_write_read1(0xB0A,0x00,&rx_data); +SpiPs_write_read1(0x61A,0x0C,&rx_data); +SpiPs_write_read1(0x61B,0x30,&rx_data); +SpiPs_write_read1(0x61C,0x08,&rx_data); +SpiPs_write_read1(0x62A,0x0B,&rx_data); +//ÅäÖÃPLL2 +SpiPs_write_read1(0x642,0x91,&rx_data); +SpiPs_write_read1(0x63F,0x35,&rx_data); +SpiPs_write_read1(0xB14,0x00,&rx_data); +SpiPs_write_read1(0xB15,0xFA,&rx_data); +SpiPs_write_read1(0xB16,0x00,&rx_data); +SpiPs_write_read1(0xB17,0x00,&rx_data); +SpiPs_write_read1(0xB18,0x00,&rx_data); +SpiPs_write_read1(0x63C,0x0D,&rx_data); +SpiPs_write_read1(0x63D,0x30,&rx_data); +SpiPs_write_read1(0x63E,0x0B,&rx_data); +SpiPs_write_read1(0x64C,0x00,&rx_data); +//ÅäÖÃPLL3 +SpiPs_write_read1(0x664,0x81,&rx_data); +SpiPs_write_read1(0x661,0x36,&rx_data); +SpiPs_write_read1(0xB22,0x00,&rx_data); +SpiPs_write_read1(0xB23,0xBB,&rx_data); +SpiPs_write_read1(0xB24,0x80,&rx_data); +SpiPs_write_read1(0xB25,0x00,&rx_data); +SpiPs_write_read1(0xB26,0x00,&rx_data); +SpiPs_write_read1(0x65E,0x0B,&rx_data); +SpiPs_write_read1(0x65F,0x30,&rx_data); +SpiPs_write_read1(0x660,0x0E,&rx_data); +SpiPs_write_read1(0x66E,0x0B,&rx_data); +//ÅäÖÃPLL4 +SpiPs_write_read1(0x686,0x91,&rx_data); +SpiPs_write_read1(0x683,0x36,&rx_data); +SpiPs_write_read1(0xB30,0x00,&rx_data); +SpiPs_write_read1(0xB31,0xDA,&rx_data); +SpiPs_write_read1(0xB32,0xC0,&rx_data); +SpiPs_write_read1(0xB33,0x00,&rx_data); +SpiPs_write_read1(0xB34,0x00,&rx_data); +SpiPs_write_read1(0x680,0x0C,&rx_data); +SpiPs_write_read1(0x681,0x30,&rx_data); +SpiPs_write_read1(0x682,0x08,&rx_data); +SpiPs_write_read1(0x690,0x0B,&rx_data); +//ÅäÖÃPLL5 +SpiPs_write_read1(0x6A8,0x81,&rx_data); +SpiPs_write_read1(0x6A5,0x36,&rx_data); +SpiPs_write_read1(0xB3E,0x00,&rx_data); +SpiPs_write_read1(0xB3F,0x9C,&rx_data); +SpiPs_write_read1(0xB40,0x40,&rx_data); +SpiPs_write_read1(0xB41,0x00,&rx_data); +SpiPs_write_read1(0xB42,0x00,&rx_data); +SpiPs_write_read1(0x6A2,0x0C,&rx_data); +SpiPs_write_read1(0x6A3,0x30,&rx_data); +SpiPs_write_read1(0x6A4,0x0C,&rx_data); +SpiPs_write_read1(0x6B2,0x0B,&rx_data); +//ÅäÖÃTx1ͨµÀƵÂÊÏà¹ؼĴæÆ÷ +SpiPs_write_read1(0x75F,0x55,&rx_data); +SpiPs_write_read1(0x761,0x04,&rx_data); +SpiPs_write_read1(0x762,0x70,&rx_data); +//ÅäÖÃTx1ͨµÀƵÂÊÏà¹ؼĴæÆ÷ +SpiPs_write_read1(0x769,0x55,&rx_data); +SpiPs_write_read1(0x76B,0x04,&rx_data); +SpiPs_write_read1(0x76C,0x70,&rx_data); +//ÅäÖÃRx1ͨµÀ +SpiPs_write_read1(0x700,0x56,&rx_data); +SpiPs_write_read1(0x701,0x00,&rx_data); +SpiPs_write_read1(0x702,0xDB,&rx_data); +SpiPs_write_read1(0x703,0x45,&rx_data); +SpiPs_write_read1(0x704,0xF8,&rx_data); +SpiPs_write_read1(0x907,0x1F,&rx_data); +//ÅäÖÃRx2ͨµÀ +SpiPs_write_read1(0x71C,0x56,&rx_data); +SpiPs_write_read1(0x71D,0x00,&rx_data); +SpiPs_write_read1(0x71E,0xDB,&rx_data); +SpiPs_write_read1(0x71F,0x45,&rx_data); +SpiPs_write_read1(0x720,0xF8,&rx_data); +SpiPs_write_read1(0x907,0x1F,&rx_data); +//ÅäÖÃRx3ͨµÀ +SpiPs_write_read1(0x738,0x56,&rx_data); +SpiPs_write_read1(0x739,0x00,&rx_data); +SpiPs_write_read1(0x73A,0xDB,&rx_data); +SpiPs_write_read1(0x73B,0x45,&rx_data); +SpiPs_write_read1(0x73C,0xF8,&rx_data); +SpiPs_write_read1(0x907,0x1F,&rx_data); +//ÅäÖÃTx1ͨµÀ +SpiPs_write_read1(0x75E,0xFF,&rx_data); +SpiPs_write_read1(0x75D,0x4A,&rx_data); +SpiPs_write_read1(0x75F,0x7D,&rx_data); +SpiPs_write_read1(0x760,0xFF,&rx_data); +//ÅäÖÃTx2ͨµÀ +SpiPs_write_read1(0x768,0xFF,&rx_data); +SpiPs_write_read1(0x767,0x4A,&rx_data); +SpiPs_write_read1(0x769,0x7D,&rx_data); +SpiPs_write_read1(0x76A,0xFF,&rx_data); +//ÅäÖÃRxÂ˲¨Æ÷ +SpiPs_write_read1(0x106,0x02,&rx_data); +//ÅäÖÃTxÂ˲¨Æ÷ +SpiPs_write_read1(0x107,0x00,&rx_data); +SpiPs_write_read1(0x108,0xD0,&rx_data); +//ÅäÖÃRx»ìƵÆ÷ +SpiPs_write_read1(0x11C,0x00,&rx_data); +SpiPs_write_read1(0xA07,0x00,&rx_data); +SpiPs_write_read1(0xA08,0x00,&rx_data); +SpiPs_write_read1(0xA09,0x00,&rx_data); +SpiPs_write_read1(0xA16,0x00,&rx_data); +SpiPs_write_read1(0xA17,0x00,&rx_data); +SpiPs_write_read1(0xA18,0x00,&rx_data); +SpiPs_write_read1(0xA19,0x00,&rx_data); +SpiPs_write_read1(0xA1A,0x00,&rx_data); +SpiPs_write_read1(0xA1B,0x00,&rx_data); +//ÅäÖÃTx»ìƵÆ÷ +SpiPs_write_read1(0x128,0x10,&rx_data); +SpiPs_write_read1(0x11B,0x00,&rx_data); +SpiPs_write_read1(0x11E,0x00,&rx_data); +SpiPs_write_read1(0x161,0x00,&rx_data); +SpiPs_write_read1(0x162,0x00,&rx_data); +SpiPs_write_read1(0x164,0x00,&rx_data); +SpiPs_write_read1(0x165,0x00,&rx_data); +SpiPs_write_read1(0x166,0x00,&rx_data); +SpiPs_write_read1(0x167,0x00,&rx_data); +SpiPs_write_read1(0x168,0x00,&rx_data); +SpiPs_write_read1(0x169,0x00,&rx_data); +//ÅäÖÃAGC +SpiPs_write_read1(0x903,0x11,&rx_data); +SpiPs_write_read1(0x900,0x00,&rx_data); +SpiPs_write_read1(0x901,0x00,&rx_data); +SpiPs_write_read1(0x908,0x77,&rx_data); +SpiPs_write_read1(0x909,0x03,&rx_data); +SpiPs_write_read1(0x90A,0x32,&rx_data); +SpiPs_write_read1(0x90D,0x00,&rx_data); +SpiPs_write_read1(0x90E,0x0F,&rx_data); +SpiPs_write_read1(0x90F,0x65,&rx_data); +SpiPs_write_read1(0x910,0x32,&rx_data); +SpiPs_write_read1(0x911,0x00,&rx_data); +SpiPs_write_read1(0x912,0x0F,&rx_data); +SpiPs_write_read1(0x913,0x3A,&rx_data); +SpiPs_write_read1(0x914,0x37,&rx_data); +SpiPs_write_read1(0x915,0x34,&rx_data); +SpiPs_write_read1(0x916,0x31,&rx_data); +//Çл»µ½ÐÝÃßģʽ +SpiPs_write_read1(0x02E,0x01,&rx_data); +usleep(1000000); +//Çл»µ½У׼ģʽ +SpiPs_write_read1(0x02E,0x03,&rx_data); +usleep(100000); +//BBPllËø¶¨ +SpiPs_write_read1(0x600,0x00,&rx_data); +SpiPs_write_read1(0x600,0x11,&rx_data); +usleep(100000); +//BBPllËø¶¨ ³ɹ¦ +//ADCУ׼ +SpiPs_write_read1(0x70B,0x1E,&rx_data); +SpiPs_write_read1(0x727,0x1E,&rx_data); +SpiPs_write_read1(0x743,0x1E,&rx_data); +SpiPs_write_read1(0x70F,0xE0,&rx_data); +SpiPs_write_read1(0x710,0x83,&rx_data); +SpiPs_write_read1(0x711,0xF0,&rx_data); +SpiPs_write_read1(0x72B,0xE0,&rx_data); +SpiPs_write_read1(0x72C,0x83,&rx_data); +SpiPs_write_read1(0x72D,0xF0,&rx_data); +SpiPs_write_read1(0x747,0xE0,&rx_data); +SpiPs_write_read1(0x748,0x83,&rx_data); +SpiPs_write_read1(0x749,0xF0,&rx_data); +SpiPs_write_read1(0x713,0x80,&rx_data); +SpiPs_write_read1(0x72F,0x80,&rx_data); +SpiPs_write_read1(0x74B,0x80,&rx_data); +SpiPs_write_read1(0x70B,0x9E,&rx_data); +SpiPs_write_read1(0x727,0x9E,&rx_data); +SpiPs_write_read1(0x743,0x9E,&rx_data); +SpiPs_write_read1(0x70B,0x9A,&rx_data); +SpiPs_write_read1(0x727,0x9A,&rx_data); +SpiPs_write_read1(0x743,0x9A,&rx_data); +SpiPs_write_read1(0x70B,0x9E,&rx_data); +SpiPs_write_read1(0x727,0x9E,&rx_data); +SpiPs_write_read1(0x743,0x9E,&rx_data); +usleep(100000); +SpiPs_write_read1(0x70B,0x1E,&rx_data); +SpiPs_write_read1(0x727,0x1E,&rx_data); +SpiPs_write_read1(0x743,0x1E,&rx_data); +SpiPs_write_read1(0x713,0xC0,&rx_data); +SpiPs_write_read1(0x72F,0xC0,&rx_data); +SpiPs_write_read1(0x74B,0xC0,&rx_data); +//flashУ׼ +SpiPs_write_read1(0x70B,0x1E,&rx_data); +SpiPs_write_read1(0x727,0x1E,&rx_data); +SpiPs_write_read1(0x743,0x1E,&rx_data); +SpiPs_write_read1(0x715,0x80,&rx_data); +SpiPs_write_read1(0x731,0x80,&rx_data); +SpiPs_write_read1(0x74D,0x80,&rx_data); +SpiPs_write_read1(0x715,0xC0,&rx_data); +SpiPs_write_read1(0x731,0xC0,&rx_data); +SpiPs_write_read1(0x74D,0xC0,&rx_data); +SpiPs_write_read1(0x716,0x40,&rx_data); +SpiPs_write_read1(0x732,0x40,&rx_data); +SpiPs_write_read1(0x74E,0x40,&rx_data); +SpiPs_write_read1(0x70B,0x16,&rx_data); +SpiPs_write_read1(0x727,0x16,&rx_data); +SpiPs_write_read1(0x743,0x16,&rx_data); +usleep(100000); +SpiPs_write_read1(0x70B,0x1E,&rx_data); +SpiPs_write_read1(0x727,0x1E,&rx_data); +SpiPs_write_read1(0x743,0x1E,&rx_data); +SpiPs_write_read1(0x715,0x80,&rx_data); +SpiPs_write_read1(0x731,0x80,&rx_data); +SpiPs_write_read1(0x74D,0x80,&rx_data); +SpiPs_write_read1(0x716,0x00,&rx_data); +SpiPs_write_read1(0x732,0x00,&rx_data); +SpiPs_write_read1(0x74E,0x00,&rx_data); +//DC Tracking +SpiPs_write_read1(0x109,0x11,&rx_data); +SpiPs_write_read1(0x10A,0x70,&rx_data); +SpiPs_write_read1(0x11F,0x33,&rx_data); +//Rx1 QECУ׼ +SpiPs_write_read1(0x02E,0x03,&rx_data); +SpiPs_write_read1(0x03F,0x26,&rx_data); +SpiPs_write_read1(0x040,0x78,&rx_data); +SpiPs_write_read1(0x77D,0x90,&rx_data); +SpiPs_write_read1(0x775,0x24,&rx_data); +SpiPs_write_read1(0x6C3,0x05,&rx_data); +SpiPs_write_read1(0x61D,0x27,&rx_data); +SpiPs_write_read1(0x617,0x00,&rx_data); +SpiPs_write_read1(0x617,0x03,&rx_data); +usleep(100000); +SpiPs_write_read1(0x61D,0x37,&rx_data); +SpiPs_write_read1(0x686,0x81,&rx_data); +SpiPs_write_read1(0x683,0x36,&rx_data); +SpiPs_write_read1(0xB30,0x00,&rx_data); +SpiPs_write_read1(0xB31,0x87,&rx_data); +SpiPs_write_read1(0xB32,0x04,&rx_data); +SpiPs_write_read1(0xB33,0x44,&rx_data); +SpiPs_write_read1(0xB34,0x44,&rx_data); +SpiPs_write_read1(0x680,0x0C,&rx_data); +SpiPs_write_read1(0x681,0x30,&rx_data); +SpiPs_write_read1(0x682,0x0C,&rx_data); +SpiPs_write_read1(0x690,0x0B,&rx_data); +SpiPs_write_read1(0x683,0x26,&rx_data); +SpiPs_write_read1(0x67D,0x00,&rx_data); +SpiPs_write_read1(0x67D,0x03,&rx_data); +usleep(100000); +SpiPs_write_read1(0x683,0x36,&rx_data); +SpiPs_write_read1(0x000,0x12,&rx_data); +SpiPs_write_read1(0x77E,0x50,&rx_data); +SpiPs_write_read1(0x11B,0x01,&rx_data); +SpiPs_write_read1(0x11E,0x01,&rx_data); +SpiPs_write_read1(0x164,0x00,&rx_data); +SpiPs_write_read1(0x165,0x00,&rx_data); +SpiPs_write_read1(0x166,0x00,&rx_data); +SpiPs_write_read1(0x167,0x00,&rx_data); +SpiPs_write_read1(0x168,0x00,&rx_data); +SpiPs_write_read1(0x169,0x00,&rx_data); +SpiPs_write_read1(0x161,0x00,&rx_data); +SpiPs_write_read1(0x162,0x00,&rx_data); +SpiPs_write_read1(0x162,0x01,&rx_data); +SpiPs_write_read1(0x161,0x01,&rx_data); +SpiPs_write_read1(0x706,0x65,&rx_data); +SpiPs_write_read1(0x6C3,0x00,&rx_data); +SpiPs_write_read1(0x75F,0x7D,&rx_data); +SpiPs_write_read1(0x11F,0x73,&rx_data); +SpiPs_write_read1(0x153,0x00,&rx_data); +SpiPs_write_read1(0x708,0x24,&rx_data); +SpiPs_write_read1(0x196,0x01,&rx_data); +SpiPs_write_read1(0x02A,0x12,&rx_data); + +do{ +usleep(100); +SpiPs_write_read2(0x14D,0x00,&rx_data); +temp=rx_data&0x10; +}while (temp != 16); + +SpiPs_write_read1(0x02A,0x00,&rx_data); +SpiPs_write_read1(0x196,0x11,&rx_data); +SpiPs_write_read2(0x13D,0x00,&rx_data); +r13D = rx_data; +SpiPs_write_read2(0x13E,0x00,&rx_data); +r13E = rx_data; + +unsigned long B = r13D * 256 + r13E; +signed long B_s = B - (B >= 32768) * 65536; +unsigned long B_abs = abs(B_s); +unsigned short B_b = (unsigned short)B_abs; +unsigned short B_delay = (B_b>>6) & 0x1ff; + +if(B_s > 0) +{ + SpiPs_write_read1(0x199, ((B_delay>>8)&0x1),&rx_data); + SpiPs_write_read1(0x19A, B_delay&0xff,&rx_data); + SpiPs_write_read1(0x19B, 0,&rx_data); + SpiPs_write_read1(0x19C, 0,&rx_data); +} +else +{ + SpiPs_write_read1(0x199, 0,&rx_data); + SpiPs_write_read1(0x19A, 0,&rx_data); + SpiPs_write_read1(0x19B, ((B_delay>>8)&0x1),&rx_data); + SpiPs_write_read1(0x19C, B_delay&0xff,&rx_data); +} + +SpiPs_write_read1(0x196,0x10,&rx_data); +SpiPs_write_read1(0x153,0x00,&rx_data); +SpiPs_write_read1(0x02A,0x12,&rx_data); + +do{ +usleep(100); +SpiPs_write_read2(0x14D,0x00,&rx_data); +temp=rx_data&0x10; +}while (temp != 16); + +SpiPs_write_read1(0x02A,0x00,&rx_data); +SpiPs_write_read1(0x77E,0x00,&rx_data); +SpiPs_write_read1(0x000,0x02,&rx_data); +//Rx2 QECУ׼ +SpiPs_write_read1(0x02E,0x03,&rx_data); +SpiPs_write_read1(0x03F,0x26,&rx_data); +SpiPs_write_read1(0x040,0x78,&rx_data); +SpiPs_write_read1(0x77D,0x60,&rx_data); +SpiPs_write_read1(0x775,0x24,&rx_data); +SpiPs_write_read1(0x6C3,0x0A,&rx_data); +SpiPs_write_read1(0x61D,0x27,&rx_data); +SpiPs_write_read1(0x617,0x00,&rx_data); +SpiPs_write_read1(0x617,0x03,&rx_data); +usleep(100000); +SpiPs_write_read1(0x61D,0x37,&rx_data); +SpiPs_write_read1(0x686,0x81,&rx_data); +SpiPs_write_read1(0x683,0x36,&rx_data); +SpiPs_write_read1(0xB30,0x00,&rx_data); +SpiPs_write_read1(0xB31,0x87,&rx_data); +SpiPs_write_read1(0xB32,0x04,&rx_data); +SpiPs_write_read1(0xB33,0x44,&rx_data); +SpiPs_write_read1(0xB34,0x44,&rx_data); +SpiPs_write_read1(0x680,0x0C,&rx_data); +SpiPs_write_read1(0x681,0x30,&rx_data); +SpiPs_write_read1(0x682,0x0C,&rx_data); +SpiPs_write_read1(0x690,0x0B,&rx_data); +SpiPs_write_read1(0x683,0x26,&rx_data); +SpiPs_write_read1(0x67D,0x00,&rx_data); +SpiPs_write_read1(0x67D,0x03,&rx_data); +usleep(100000); +SpiPs_write_read1(0x683,0x36,&rx_data); +SpiPs_write_read1(0x000,0x22,&rx_data); +SpiPs_write_read1(0x77E,0x0A,&rx_data); +SpiPs_write_read1(0x11B,0x01,&rx_data); +SpiPs_write_read1(0x11E,0x01,&rx_data); +SpiPs_write_read1(0x164,0x00,&rx_data); +SpiPs_write_read1(0x165,0x00,&rx_data); +SpiPs_write_read1(0x166,0x00,&rx_data); +SpiPs_write_read1(0x167,0x00,&rx_data); +SpiPs_write_read1(0x168,0x00,&rx_data); +SpiPs_write_read1(0x169,0x00,&rx_data); +SpiPs_write_read1(0x161,0x00,&rx_data); +SpiPs_write_read1(0x162,0x00,&rx_data); +SpiPs_write_read1(0x162,0x01,&rx_data); +SpiPs_write_read1(0x161,0x01,&rx_data); +SpiPs_write_read1(0x706,0x65,&rx_data); +SpiPs_write_read1(0x6C3,0x00,&rx_data); +SpiPs_write_read1(0x75F,0x7D,&rx_data); +SpiPs_write_read1(0x11F,0x73,&rx_data); +SpiPs_write_read1(0x153,0x00,&rx_data); +SpiPs_write_read1(0x724,0x24,&rx_data); +SpiPs_write_read1(0x196,0x01,&rx_data); +SpiPs_write_read1(0x02B,0x12,&rx_data); + +do{ +usleep(100); +SpiPs_write_read2(0x14D,0x00,&rx_data); +temp=rx_data&0x10; +}while (temp != 16); + +SpiPs_write_read1(0x02B,0x00,&rx_data); +SpiPs_write_read1(0x196,0x11,&rx_data); +SpiPs_write_read2(0x13D,0x00,&rx_data); +r13D = rx_data; +SpiPs_write_read2(0x13E,0x00,&rx_data); +r13E = rx_data; + +B = r13D * 256 + r13E; +B_s = B - (B >= 32768) * 65536; +B_abs = abs(B_s); +B_b = (unsigned short)B_abs; +B_delay = (B_b>>6) & 0x1ff; + +if(B_s > 0) +{ + SpiPs_write_read1(0x199, ((B_delay>>8)&0x1),&rx_data); + SpiPs_write_read1(0x19A, B_delay&0xff,&rx_data); + SpiPs_write_read1(0x19B, 0,&rx_data); + SpiPs_write_read1(0x19C, 0,&rx_data); +} +else +{ + SpiPs_write_read1(0x199, 0,&rx_data); + SpiPs_write_read1(0x19A, 0,&rx_data); + SpiPs_write_read1(0x19B, ((B_delay>>8)&0x1),&rx_data); + SpiPs_write_read1(0x19C, B_delay&0xff,&rx_data); +} + +SpiPs_write_read1(0x196,0x10,&rx_data); +SpiPs_write_read1(0x153,0x00,&rx_data); +SpiPs_write_read1(0x02B,0x12,&rx_data); + +do{ +usleep(100); +SpiPs_write_read2(0x14D,0x00,&rx_data); +temp=rx_data&0x10; +}while (temp != 16); + +SpiPs_write_read1(0x02B,0x00,&rx_data); +SpiPs_write_read1(0x77E,0x00,&rx_data); +SpiPs_write_read1(0x000,0x02,&rx_data); +//»ָ´У׼Öб»¸ıäµÄÅäÖà +SpiPs_write_read1(0x000,0x02,&rx_data); +SpiPs_write_read1(0x02E,0x03,&rx_data); +SpiPs_write_read1(0x109,0x11,&rx_data); +SpiPs_write_read1(0x10A,0x70,&rx_data); +SpiPs_write_read1(0x11B,0x00,&rx_data); +SpiPs_write_read1(0x11E,0x00,&rx_data); +SpiPs_write_read1(0x11F,0x33,&rx_data); +SpiPs_write_read1(0x128,0x10,&rx_data); +SpiPs_write_read1(0x161,0x00,&rx_data); +SpiPs_write_read1(0x162,0x00,&rx_data); +SpiPs_write_read1(0x164,0x00,&rx_data); +SpiPs_write_read1(0x165,0x00,&rx_data); +SpiPs_write_read1(0x166,0x00,&rx_data); +SpiPs_write_read1(0x167,0x00,&rx_data); +SpiPs_write_read1(0x168,0x00,&rx_data); +SpiPs_write_read1(0x169,0x00,&rx_data); +SpiPs_write_read1(0x6C3,0x00,&rx_data); +SpiPs_write_read1(0x775,0x24,&rx_data); +SpiPs_write_read1(0x77D,0xCF,&rx_data); +SpiPs_write_read1(0xA07,0x00,&rx_data); +SpiPs_write_read1(0xA08,0x00,&rx_data); +SpiPs_write_read1(0xA16,0x00,&rx_data); +SpiPs_write_read1(0xA17,0x00,&rx_data); +SpiPs_write_read1(0xA18,0x00,&rx_data); +SpiPs_write_read1(0xA19,0x00,&rx_data); +SpiPs_write_read1(0xA1A,0x00,&rx_data); +SpiPs_write_read1(0xA1B,0x00,&rx_data); +SpiPs_write_read1(0x686,0x91,&rx_data); +SpiPs_write_read1(0x683,0x36,&rx_data); +SpiPs_write_read1(0xB30,0x00,&rx_data); +SpiPs_write_read1(0xB31,0xDA,&rx_data); +SpiPs_write_read1(0xB32,0xC0,&rx_data); +SpiPs_write_read1(0xB33,0x00,&rx_data); +SpiPs_write_read1(0xB34,0x00,&rx_data); +SpiPs_write_read1(0x680,0x0C,&rx_data); +SpiPs_write_read1(0x681,0x30,&rx_data); +SpiPs_write_read1(0x682,0x08,&rx_data); +SpiPs_write_read1(0x690,0x0B,&rx_data); +//TXУ׼ +SpiPs_write_read1(0x03F,0x27,&rx_data); +SpiPs_write_read1(0x040,0xF8,&rx_data); +SpiPs_write_read1(0x61D,0x27,&rx_data); +SpiPs_write_read1(0x617,0x00,&rx_data); +SpiPs_write_read1(0x617,0x03,&rx_data); +usleep(100000); +SpiPs_write_read1(0x61D,0x37,&rx_data); +SpiPs_write_read1(0x02E,0x03,&rx_data); +SpiPs_write_read1(0x128,0x11,&rx_data); +SpiPs_write_read1(0x11E,0x01,&rx_data); +SpiPs_write_read1(0x77E,0x24,&rx_data); +SpiPs_write_read1(0x11F,0x01,&rx_data); +SpiPs_write_read1(0x121,0x02,&rx_data); +SpiPs_write_read1(0x11B,0x01,&rx_data); +SpiPs_write_read1(0x161,0x01,&rx_data); +SpiPs_write_read1(0x162,0x01,&rx_data); +SpiPs_write_read1(0x163,0x00,&rx_data); +SpiPs_write_read1(0x164,0x04,&rx_data); +SpiPs_write_read1(0x165,0x00,&rx_data); +SpiPs_write_read1(0x166,0x00,&rx_data); +SpiPs_write_read1(0x167,0x00,&rx_data); +SpiPs_write_read1(0x168,0x00,&rx_data); +SpiPs_write_read1(0x169,0x00,&rx_data); +SpiPs_write_read1(0xA2D,0x02,&rx_data); +SpiPs_write_read1(0xA07,0x00,&rx_data); +SpiPs_write_read1(0xA08,0x0F,&rx_data); +SpiPs_write_read1(0xA1C,0x01,&rx_data); +SpiPs_write_read1(0xA16,0x20,&rx_data); +SpiPs_write_read1(0xA17,0x00,&rx_data); +SpiPs_write_read1(0xA18,0x00,&rx_data); +SpiPs_write_read1(0xA19,0x00,&rx_data); +SpiPs_write_read1(0xA1A,0x00,&rx_data); +SpiPs_write_read1(0xA1B,0x00,&rx_data); +SpiPs_write_read1(0x102,0x0F,&rx_data); +SpiPs_write_read1(0x102,0xFF,&rx_data); +SpiPs_write_read1(0x186,0x00,&rx_data); +SpiPs_write_read1(0x186,0x01,&rx_data); +SpiPs_write_read1(0x763,0x34,&rx_data); +SpiPs_write_read1(0x76D,0x34,&rx_data); +SpiPs_write_read1(0x101,0xEF,&rx_data); +SpiPs_write_read1(0x101,0xFF,&rx_data); +SpiPs_write_read1(0x800,0x00,&rx_data); +SpiPs_write_read1(0x81A,0xF7,&rx_data); +SpiPs_write_read1(0x81B,0x34,&rx_data); +SpiPs_write_read1(0x81C,0x33,&rx_data); +SpiPs_write_read1(0x81D,0x12,&rx_data); +SpiPs_write_read1(0x81E,0x00,&rx_data); +SpiPs_write_read1(0x81F,0xFF,&rx_data); +SpiPs_write_read1(0x820,0x00,&rx_data); +SpiPs_write_read1(0x821,0xFF,&rx_data); +SpiPs_write_read1(0x800,0x80,&rx_data); +usleep(100000); +SpiPs_write_read1(0x800,0x81,&rx_data); +usleep(100000); +SpiPs_write_read1(0x77E,0x00,&rx_data); +SpiPs_write_read1(0x77E,0x24,&rx_data); +SpiPs_write_read1(0x11F,0x03,&rx_data); +SpiPs_write_read1(0x121,0x02,&rx_data); +SpiPs_write_read1(0x11B,0x01,&rx_data); +SpiPs_write_read1(0x11E,0x01,&rx_data); +SpiPs_write_read1(0x161,0x01,&rx_data); +SpiPs_write_read1(0x162,0x01,&rx_data); +SpiPs_write_read1(0x164,0x04,&rx_data); +SpiPs_write_read1(0x165,0x00,&rx_data); +SpiPs_write_read1(0x166,0x00,&rx_data); +SpiPs_write_read1(0x167,0x00,&rx_data); +SpiPs_write_read1(0x168,0x00,&rx_data); +SpiPs_write_read1(0x169,0x00,&rx_data); +SpiPs_write_read1(0xA2D,0x02,&rx_data); +SpiPs_write_read1(0xA07,0x00,&rx_data); +SpiPs_write_read1(0xA08,0x0F,&rx_data); +SpiPs_write_read1(0xA1C,0x01,&rx_data); +SpiPs_write_read1(0xA16,0x10,&rx_data); +SpiPs_write_read1(0xA17,0x00,&rx_data); +SpiPs_write_read1(0xA18,0x00,&rx_data); +SpiPs_write_read1(0xA19,0x00,&rx_data); +SpiPs_write_read1(0xA1A,0x00,&rx_data); +SpiPs_write_read1(0xA1B,0x00,&rx_data); +SpiPs_write_read1(0x81A,0xF7,&rx_data); +SpiPs_write_read1(0x81B,0x44,&rx_data); +SpiPs_write_read1(0x81C,0x33,&rx_data); +SpiPs_write_read1(0x81D,0x14,&rx_data); +SpiPs_write_read1(0x800,0x80,&rx_data); +SpiPs_write_read1(0x800,0x82,&rx_data); +usleep(100000); +SpiPs_write_read1(0x77E,0x00,&rx_data); +//»ָ´У׼Öб»¸ıäµÄÅäÖà +SpiPs_write_read1(0x000,0x02,&rx_data); +SpiPs_write_read1(0x02E,0x03,&rx_data); +SpiPs_write_read1(0x109,0x11,&rx_data); +SpiPs_write_read1(0x10A,0x70,&rx_data); +SpiPs_write_read1(0x11B,0x00,&rx_data); +SpiPs_write_read1(0x11E,0x00,&rx_data); +SpiPs_write_read1(0x11F,0x33,&rx_data); +SpiPs_write_read1(0x128,0x10,&rx_data); +SpiPs_write_read1(0x161,0x00,&rx_data); +SpiPs_write_read1(0x162,0x00,&rx_data); +SpiPs_write_read1(0x164,0x00,&rx_data); +SpiPs_write_read1(0x165,0x00,&rx_data); +SpiPs_write_read1(0x166,0x00,&rx_data); +SpiPs_write_read1(0x167,0x00,&rx_data); +SpiPs_write_read1(0x168,0x00,&rx_data); +SpiPs_write_read1(0x169,0x00,&rx_data); +SpiPs_write_read1(0x6C3,0x00,&rx_data); +SpiPs_write_read1(0x775,0x24,&rx_data); +SpiPs_write_read1(0x77D,0xCF,&rx_data); +SpiPs_write_read1(0xA07,0x00,&rx_data); +SpiPs_write_read1(0xA08,0x00,&rx_data); +SpiPs_write_read1(0xA16,0x00,&rx_data); +SpiPs_write_read1(0xA17,0x00,&rx_data); +SpiPs_write_read1(0xA18,0x00,&rx_data); +SpiPs_write_read1(0xA19,0x00,&rx_data); +SpiPs_write_read1(0xA1A,0x00,&rx_data); +SpiPs_write_read1(0xA1B,0x00,&rx_data); +//Pll1Ëø¶¨ +SpiPs_write_read1(0x61D,0x27,&rx_data); +SpiPs_write_read1(0x617,0x00,&rx_data); +SpiPs_write_read1(0x617,0x03,&rx_data); +usleep(100000); +SpiPs_write_read1(0x61D,0x37,&rx_data); +//Pll1Ëø¶¨ ³ɹ¦ +//Pll2Ëø¶¨ +SpiPs_write_read1(0x63F,0x25,&rx_data); +SpiPs_write_read1(0x639,0x00,&rx_data); +SpiPs_write_read1(0x639,0x03,&rx_data); +usleep(100000); +SpiPs_write_read1(0x63F,0x35,&rx_data); +//Pll2Ëø¶¨ ³ɹ¦ +//Pll3Ëø¶¨ +SpiPs_write_read1(0x661,0x26,&rx_data); +SpiPs_write_read1(0x65B,0x00,&rx_data); +SpiPs_write_read1(0x65B,0x03,&rx_data); +usleep(100000); +SpiPs_write_read1(0x661,0x36,&rx_data); +//Pll3Ëø¶¨ ³ɹ¦ +//Pll4Ëø¶¨ +SpiPs_write_read1(0x683,0x26,&rx_data); +SpiPs_write_read1(0x67D,0x00,&rx_data); +SpiPs_write_read1(0x67D,0x03,&rx_data); +usleep(100000); +SpiPs_write_read1(0x683,0x36,&rx_data); +//Pll4Ëø¶¨ ³ɹ¦ +//Pll5Ëø¶¨ +SpiPs_write_read1(0x6A5,0x26,&rx_data); +SpiPs_write_read1(0x69F,0x00,&rx_data); +SpiPs_write_read1(0x69F,0x03,&rx_data); +usleep(100000); +SpiPs_write_read1(0x6A5,0x36,&rx_data); +//Pll5Ëø¶¨ ³ɹ¦ +//ÅäÖýӿÚ +SpiPs_write_read1(0x02E,0x05,&rx_data); +SpiPs_write_read1(0x003,0x33,&rx_data); +SpiPs_write_read1(0x200,0x01,&rx_data); +SpiPs_write_read1(0x201,0x3F,&rx_data); +SpiPs_write_read1(0x202,0x03,&rx_data); +SpiPs_write_read1(0x206,0x00,&rx_data); +SpiPs_write_read1(0x208,0x00,&rx_data); +SpiPs_write_read1(0x209,0x00,&rx_data); +SpiPs_write_read1(0x77F,0x00,&rx_data); +SpiPs_write_read1(0x780,0x33,&rx_data); +SpiPs_write_read1(0x781,0x6F,&rx_data); +//ÅäÖýáÊø + +SpiPs_write_read1(0x02E,0x04,&rx_data); +SpiPs_write_read1(0x780,0x00,&rx_data); + +SpiPs_write_read1(0x11F,0x00,&rx_data); +SpiPs_write_read1(0x11F,0x33,&rx_data); +////ÅäÖÃTx NCO BIST ON +//SpiPs_write_read1(0x11B,0x01,&rx_data); +//SpiPs_write_read1(0x11E,0x01,&rx_data); +//SpiPs_write_read1(0x161,0x01,&rx_data); +//SpiPs_write_read1(0x162,0x01,&rx_data); +////ÅäÖÃTx NCOƵÂÊ 1MHz +//SpiPs_write_read1(0x164,0x05,&rx_data); +//SpiPs_write_read1(0x165,0x55,&rx_data); +//SpiPs_write_read1(0x166,0x55,&rx_data); +//SpiPs_write_read1(0x167,0x55,&rx_data); +//SpiPs_write_read1(0x168,0x55,&rx_data); +//SpiPs_write_read1(0x169,0x55,&rx_data); +} diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_HOP/download_bin.c b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_HOP/download_bin.c new file mode 100644 index 0000000..97b90e0 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_HOP/download_bin.c @@ -0,0 +1,80 @@ +/* + * download_bin.c + * + * Created on: 2023Äê11ÔÂ23ÈÕ + * Author: cxlab + */ + +#include "xilinx_io.h" +#include "sleep.h" +void download_bin(void){ + + int temp; + u8 rx_data; + u8 data[4]; + u32 buf; + u8 addr[2]; + int on = 1; + if (on) { + SpiPs_write_read1(0x079,0x00,&rx_data);//¹رÕCRCУÑé + SpiPs_write_read1(0x071,0x00,&rx_data); + SpiPs_write_read1(0x071,0x09,&rx_data); + // SpiPs_write_read1(0x236,0x0F,&rx_data); + // SpiPs_write_read1(0x20A,0x01,&rx_data); + for(int i=0;i<5507;i++){ + addr[0]=(i>>8)&0xff; + addr[1]= i&0xff; + buf=rom_read((u8 *)&addr); + data[0]=buf>>24; + data[1]=(buf>>16)&0xff; + data[2]=(buf>>8)&0xff; + data[3]=buf&0xff; + for(int j=0;j<4;j++){ + SpiPs_write_read1(0x070,data[j],&rx_data); + } + + } + + SpiPs_write_read1(0x071,0x1A,&rx_data);//¿ªÆôCRCУÑé + SpiPs_write_read1(0x079,0x08,&rx_data);//¿ªÆôCRCУÑé + usleep(1000); + SpiPs_write_read2(0x078,0x00,&rx_data); + temp=rx_data; + + if (temp == 0x01) { + xil_printf("CRC successful"); + } + else { + xil_printf("CRC unsuccessful"); + } + SpiPs_write_read1(0x071,0x06,&rx_data);//´¦ÀíÆ÷ÃſØʱÖÓʹÄÜ + usleep(10000); + SpiPs_write_read2(0x0A7,0x00,&rx_data);//´¦ÀíÆ÷ÔËÐгɹû±ê־ + temp=rx_data; + + if (temp == 0x11) { + xil_printf("core run successful"); + } + else { + xil_printf("core run unsuccessful"); + } +////////////////////dpdϵÊý¼ÓÔØ//////////////////// + SpiPs_write_read1(0x302,0xDF,&rx_data); + SpiPs_write_read1(0x0A3,0x52,&rx_data); + usleep(200000); + SpiPs_write_read2(0x0A7,0x00,&rx_data);//dpdϵÊý¼ÓÔØÍê³ɱê־ + temp=rx_data; + + if (temp == 0x61) { + xil_printf("dpd index load successful"); + } + else { + xil_printf("dpd index load unsuccessful"); + } + } + else { + SpiPs_write_read1(0x071,0x00,&rx_data); + } + + } + diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_HOP/echo.c b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_HOP/echo.c new file mode 100644 index 0000000..705e9e2 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_HOP/echo.c @@ -0,0 +1,461 @@ +/* + * Copyright (C) 2016 - 2018 Xilinx, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + */ + +#include +#include + +#include "lwip/sockets.h" +#include "netif/xadapter.h" +#include "lwipopts.h" +#include "xil_printf.h" +#include "FreeRTOS.h" +#include "task.h" +#include "xilinx_io.h" + +#define THREAD_STACKSIZE 1024 +#define ACK 0x01 +u16_t echo_port = 7; +//#define RECV_BUF_SIZE 65536*16*8 +#define RECV_BUF_SIZE 1024 +//char recv_buf[RECV_BUF_SIZE]; +char recv_buf[1024]; +char recv_buf_temp[3]; +char trans_buf[8192*5]; +struct spi_stack spistack; + + +u16 hop_cnt = 0; + +void print_echo_app_header() +{ + xil_printf("%20s %6d %s\r\n", "echo server", + echo_port, + "$ telnet 7"); + +} + + +enum { + CMD_VER = 0, + CMD_RST = 1, + CMD_SPI_WRI = 2 , + CMD_SPI_READ = 3, + CMD_DATA_CAPTURE0 = 4, + CMD_WAVE_DOWNLOAD = 5, + CMD_PIN_SET = 6, + CMD_DATA_CAPTURE1 = 8, + CMD_DATA_CAPTURE2 = 9, + CMD_STACK_OUT = 10, + CMD_hopping = 11, + CMD_qecbin = 12, + CMD_cx9261a_config = 13, + CMD_cx3e04_config = 14, + CMD_cx3e04_SPI_WRI = 15 , + CMD_cx3e04_SPI_READ = 16, + CMD_IMAGE_UPDATE = 22, +}; +/* thread spawned for each connection */ +void process_echo_request(void *p) +{ + int sd = (int)p; + int status; + int n, nwrote,send_n,total_send; + u8 rx_data; + u32 capture_length; + u8 pin; + u8 pin_value; + char FPGA_SDK_IP[]="FPGA:20240513-SDK:20240514"; + spistack.spi_write_num = 0; + while (1) { + /* read a max of RECV_BUF_SIZE bytes from socket */ + if ((n = read(sd, recv_buf, 5)) < 0) { + xil_printf("%s: error reading from socket %d, closing socket\r\n", __FUNCTION__, sd); + break; + } + + /* break if the recved message = "quit" */ + if (!strncmp(recv_buf, "quit", 4)) + break; + + /* break if client closed connection */ + if (n <= 0) + break; + + else{/* excute cmd if recved message = "cmd"*/ + n=0; + if (!strncmp(recv_buf, "cmd ", 4)){ +// xil_printf("%d %d %d %d.\r\n", recv_buf[0],recv_buf[1],recv_buf[2],recv_buf[4]); + dbg_printf("Rece %d bytes.\r\n",n); + switch(recv_buf[4]){ + case CMD_IMAGE_UPDATE: + { + + u32 offset; + u32 image_size; + recv_buf[0] = ACK; + nwrote = write(sd, recv_buf, 1); + n = read(sd, recv_buf, RECV_BUF_SIZE); + + offset = *(u32 *)recv_buf; + image_size = *(u32 *)(recv_buf + 4); + xil_printf("offset is 0x%x image_size is 0x%x.\n", offset, image_size); + + void *image_ptr = (void *)0x30000000; + u32 LengthBytes; + write(sd, recv_buf, 1); // ask for image data + //// receive flash image to ddr + LengthBytes = 0; + while (LengthBytes < image_size) + { + n = read(sd, image_ptr + LengthBytes, RECV_BUF_SIZE); + // xil_printf("read %d bytes.\n",n); + LengthBytes = LengthBytes + n; + } + + // image data sumcheck + + // program image data into flash + //QspiStore( (u32) image_ptr, offset, image_size); + //xil_printf("flash program done.\n", n); + status = FfsSdWrite(image_ptr, image_size); + write(sd, recv_buf, 1); // send done + xil_printf("sd program done.\n", n); + n = 0; + break; + } + + case CMD_VER: + dbg_printf("Version:FPGA_20240513;SDK_20240514;IP_192.168.1.99.\r\n"); + n=26; + for(int i=0;i<26;i++){ + recv_buf[i] = FPGA_SDK_IP[i]; + } + break; + case CMD_RST: + dbg_printf("Rece cmd excute rst.\r\n"); + GpioSetPinDir(NRST,GPIO_DIR_OUTPUT); + DeviceRst(); + break; + + case CMD_STACK_OUT: + dbg_printf("Rece cmd STACK OUT.\r\n"); + spi_stack_out(&spistack); + n=1; + recv_buf[0] = 0x55; + break; + case CMD_SPI_WRI: + read(sd, &recv_buf[5], 3); + dbg_printf("Rece cmd excute spi write.\r\n"); + dbg_printf("ADDR 0x%x DATA 0x%x.\r\n",recv_buf[5]*256+recv_buf[6]-32768,recv_buf[7]); +// SpiPs_write_read((u8 *)&recv_buf[5],&rx_data); + status = spi_stack_in((u8 *)&recv_buf[5],&spistack); + if(status){//when memory is near full,start spi write + spi_stack_out(&spistack); + } +// n=1; +// recv_buf[0] = rx_data; + break; + case CMD_SPI_READ: + read(sd, &recv_buf[5], 3); + dbg_printf("Rece cmd excute spi read.\r\n"); + dbg_printf("ADDR 0x%x DATA 0x%x.\r\n",recv_buf[5]*256+recv_buf[6],recv_buf[7]); + SpiPs_write_read((u8 *)&recv_buf[5],&rx_data); + n=1; + recv_buf[0] = rx_data; + break; + case CMD_DATA_CAPTURE0: + read(sd, &recv_buf[5], 4); + capture_length = *((u32 *) &recv_buf[5]);//num of sample + dbg_printf("Rece cmd excute %d sample data capture.\r\n",capture_length); + XAxiDmaCapture(xAxiDma0Get(),capture_length); + n = capture_length*8; + total_send = 0; + /* handle request */ + while(n>0){ + if(n>1024) + send_n = 1024; + else + send_n = n; + n= n-send_n; + memcpy(recv_buf,TX_BUFFER_BASE + total_send,send_n); + total_send = total_send + send_n; + if ((nwrote = write(sd, &recv_buf, send_n)) < 0) { + xil_printf("%s: ERROR responding to client echo request. received = %d, written = %d\r\n",__FUNCTION__, n, nwrote); + xil_printf("Closing socket %d\r\n", sd); + break; + } + else{ + if(send_n!=nwrote){ + xil_printf("%d Bytes Send %d.\r\n", send_n,nwrote); + } + } + } + dbg_printf("Send %d bytes.\r\n",n); + break; + case CMD_DATA_CAPTURE1: + read(sd, &recv_buf[5], 4); + capture_length = *((u32 *) &recv_buf[5]);//num of sample + dbg_printf("Rece cmd excute %d sample data capture.\r\n",capture_length); + XAxiDmaCapture(xAxiDma1Get(),capture_length); + n = capture_length*8; + total_send = 0; + /* handle request */ + while(n>0){ + if(n>1024) + send_n = 1024; + else + send_n = n; + n= n-send_n; + + memcpy(recv_buf,TX_BUFFER_BASE + total_send,send_n); + total_send = total_send + send_n; + if ((nwrote = write(sd, &recv_buf, send_n)) < 0) { + xil_printf("%s: ERROR responding to client echo request. received = %d, written = %d\r\n",__FUNCTION__, n, nwrote); + xil_printf("Closing socket %d\r\n", sd); + break; + } + else{ + if(send_n!=nwrote){ + xil_printf("%d Bytes Send %d.\r\n", send_n,nwrote); + } + } + } + dbg_printf("Send %d bytes.\r\n",n); + break; + case CMD_DATA_CAPTURE2: + read(sd, &recv_buf[5], 4); + capture_length = *((u32 *) &recv_buf[5]);//num of sample + dbg_printf("Rece cmd excute %d sample data capture.\r\n",capture_length); + XAxiDmaCapture(xAxiDma2Get(),capture_length); + n = capture_length*8; + total_send = 0; + /* handle request */ + while(n>0){ + if(n>1024) + send_n = 1024; + else + send_n = n; + n= n-send_n; + memcpy(recv_buf,TX_BUFFER_BASE + total_send,send_n); + total_send = total_send + send_n; + if ((nwrote = write(sd, &recv_buf, send_n)) < 0) { + xil_printf("%s: ERROR responding to client echo request. received = %d, written = %d\r\n",__FUNCTION__, n, nwrote); + xil_printf("Closing socket %d\r\n", sd); + break; + } + else{ + if(send_n!=nwrote){ + xil_printf("%d Bytes Send %d.\r\n", send_n,nwrote); + } + } + } + dbg_printf("Send %d bytes.\r\n",n); + break; + case CMD_WAVE_DOWNLOAD: + dbg_printf("Rece cmd excute wave download.\r\n"); + while(n0){ + if(n>1024) + send_n = 1024; + else + send_n = n; + n= n-send_n; + total_send = total_send + send_n; + memcpy(recv_buf,TX_BUFFER_BASE + total_send,send_n); + if ((nwrote = write(sd, &recv_buf, send_n)) < 0) { + xil_printf("%s: ERROR responding to client echo request. received = %d, written = %d\r\n", + __FUNCTION__, n, nwrote); + xil_printf("Closing socket %d\r\n", sd); + break; + } + else{ + if(send_n!=nwrote){ + xil_printf("%d Bytes Send %d.\r\n", send_n,nwrote); + } + } + } + dbg_printf("Send %d bytes.\r\n",n); + }*/ + + } + } + /* handle request */ + if ((nwrote = write(sd, recv_buf, n)) < 0) { + xil_printf("%s: ERROR responding to client echo request. received = %d, written = %d\r\n", + __FUNCTION__, n, nwrote); + xil_printf("Closing socket %d\r\n", sd); + break; + } + else{ + if(n!=nwrote){ + xil_printf("%d Bytes Send %d.\r\n", n,nwrote); + } + } + } + + /* close connection */ + close(sd); + vTaskDelete(NULL); +} + +void echo_application_thread() +{ + int sock, new_sd; + int size; +#if LWIP_IPV6==0 + struct sockaddr_in address, remote; + + memset(&address, 0, sizeof(address)); + + if ((sock = lwip_socket(AF_INET, SOCK_STREAM, 0)) < 0) + return; + + address.sin_family = AF_INET; + address.sin_port = htons(echo_port); + address.sin_addr.s_addr = INADDR_ANY; +#else + struct sockaddr_in6 address, remote; + + memset(&address, 0, sizeof(address)); + + address.sin6_len = sizeof(address); + address.sin6_family = AF_INET6; + address.sin6_port = htons(echo_port); + + memset(&(address.sin6_addr), 0, sizeof(address.sin6_addr)); + + if ((sock = lwip_socket(AF_INET6, SOCK_STREAM, 0)) < 0) + return; +#endif + + if (lwip_bind(sock, (struct sockaddr *)&address, sizeof (address)) < 0) + return; + + lwip_listen(sock, 0); + + size = sizeof(remote); + + while (1) { + if ((new_sd = lwip_accept(sock, (struct sockaddr *)&remote, (socklen_t *)&size)) > 0) { + sys_thread_new("echos", process_echo_request, + (void*)new_sd, + THREAD_STACKSIZE, + DEFAULT_THREAD_PRIO); + } + } +} diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_HOP/frqhop_config.c b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_HOP/frqhop_config.c new file mode 100644 index 0000000..033cd78 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_HOP/frqhop_config.c @@ -0,0 +1,52 @@ +/* + * frqhop_config.c + * + * Created on: 2023Äê11ÔÂ24ÈÕ + * Author: cxlab + */ + +#include "xilinx_io.h" +#include "sleep.h" +#include "time.h" +#include "xtime_l.h" +#include "math.h" +#include + +void frqhop_config(int hop_flag){ + XTime tCur; + XTime_GetTime(&tCur); + srand(tCur); + double hop_freq = (rand()%(800-30))+30+(rand()%(101))/(double)100;//Ëæ»ú²úÉú[30,800)doubleÀàÐ͵ÄÊý +// double hop_freq = 400.52; + double hop_freq1 = 800.25; + static int pll_index=1; + static int unlock_pll1_cnt=0,unlock_pll2_cnt=0; + if(hop_freq == hop_freq1){ + if(pll_index == 2){ + pll_index = 4; + } + else if(pll_index == 1){ + pll_index = 3; + } + } + if(hop_flag == 1){ + if(pll_index == 1 || pll_index == 3){ + //Çл»ÖÁpll2À´Դ + trx_ch_pll_config(2); + //ÅäÖÃpll1²ÎÊý + unlock_pll1_cnt=PLL_config(1,hop_freq)-1; + pll_index = 2; + } + else if(pll_index == 2 || pll_index == 4){ + //Çл»ÖÁpll1À´Դ + trx_ch_pll_config(1); + //ÅäÖÃpll2²ÎÊý + unlock_pll2_cnt=PLL_config(2,hop_freq)-1; + pll_index = 1; + } + } + hop_freq1 = hop_freq; + if(unlock_pll2_cnt!=0 || unlock_pll1_cnt !=0){ + xil_printf("pll1 unlock num: %d; pll2 unlock num: %d;.\n", unlock_pll1_cnt, unlock_pll2_cnt); + } +} diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_HOP/iic_phyreset.c b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_HOP/iic_phyreset.c new file mode 100644 index 0000000..9d13181 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_HOP/iic_phyreset.c @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2016 - 2018 Xilinx, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + */ + +#include + +#include "xparameters.h" +#if defined (__arm__) || defined(__aarch64__) +#include "xil_printf.h" +#endif + +#ifdef XPS_BOARD_ZCU102 +#ifdef XPAR_XIICPS_0_DEVICE_ID +#include "xiicps.h" + +#define BUF_LEN 10U + +#define IOEXPANDER1_ADDR 0x20U + +#define IIC_SCLK_RATE_IOEXP 400000 + +#define CMD_CFG_0_REG 0x06U +#define CMD_OUTPUT_0_REG 0x02U +#define DATA_OUTPUT 0x0U + +#define DATA_COMMON_CFG 0xE0U +#define DATA_GT_0000_CFG 0x00U + +XIicPs I2c0InstancePtr; + +int IicPhyReset(void) +{ + + u8 WriteBuffer[BUF_LEN] = {0}; + XIicPs_Config *I2c0CfgPtr; + int Status = XST_SUCCESS; + + /* Initialize the IIC0 driver so that it is ready to use */ + I2c0CfgPtr = XIicPs_LookupConfig(XPAR_XIICPS_0_DEVICE_ID); + if (I2c0CfgPtr == NULL) { + Status = XST_FAILURE; + return Status; + } + + Status = XIicPs_CfgInitialize(&I2c0InstancePtr, I2c0CfgPtr, + I2c0CfgPtr->BaseAddress); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + return Status; + } + + /* Set the IIC serial clock rate */ + XIicPs_SetSClk(&I2c0InstancePtr, IIC_SCLK_RATE_IOEXP); + + /* Configure I/O pins as Output */ + WriteBuffer[0] = CMD_CFG_0_REG; + WriteBuffer[1] = DATA_OUTPUT; + Status = XIicPs_MasterSendPolled(&I2c0InstancePtr, + WriteBuffer, 2, IOEXPANDER1_ADDR); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + return Status; + } + + /* Wait until bus is idle to start another transfer */ + while (XIicPs_BusIsBusy(&I2c0InstancePtr)); + + /* + * Deasserting I2C_MUX_RESETB + * And GEM3 Resetb + * Selecting lanes based on configuration + */ + WriteBuffer[0] = CMD_OUTPUT_0_REG; + /* gt0000 or no GT configuration */ + WriteBuffer[1] = DATA_COMMON_CFG | DATA_GT_0000_CFG; + + /* Send the Data */ + Status = XIicPs_MasterSendPolled(&I2c0InstancePtr, + WriteBuffer, 2, IOEXPANDER1_ADDR); + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + return Status; + } + + /* Wait until bus is idle */ + while (XIicPs_BusIsBusy(&I2c0InstancePtr)); + + xil_printf("IIC PHY reset on ZCU102 successful \n\r"); +} +#endif +#endif diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_HOP/main.c b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_HOP/main.c new file mode 100644 index 0000000..4b61222 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_HOP/main.c @@ -0,0 +1,300 @@ +/* + * Copyright (C) 2016 - 2018 Xilinx, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + */ + +#include +#include "xparameters.h" +#include "netif/xadapter.h" +#include "platform_config.h" +#include "xil_printf.h" +#include "xilinx_io.h" +#include "FreeRTOS.h" +#include "queue.h" +#include "semphr.h" +#include "math.h" + +#if LWIP_IPV6==1 +#include "lwip/ip.h" +#else +#if LWIP_DHCP==1 +#include "lwip/dhcp.h" +#endif +#endif + +#ifdef XPS_BOARD_ZCU102 +#ifdef XPAR_XIICPS_0_DEVICE_ID +int IicPhyReset(void); +#endif +#endif + +int main_thread(); +void print_echo_app_header(); +void echo_application_thread(void *); + +void lwip_init(); + +#if LWIP_IPV6==0 +#if LWIP_DHCP==1 +extern volatile int dhcp_timoutcntr; +err_t dhcp_start(struct netif *netif); +#endif +#endif + +#define THREAD_STACKSIZE 1024 + +static struct netif server_netif; +struct netif *echo_netif; + +#if LWIP_IPV6==1 +void print_ip6(char *msg, ip_addr_t *ip) +{ + print(msg); + xil_printf(" %x:%x:%x:%x:%x:%x:%x:%x\n\r", + IP6_ADDR_BLOCK1(&ip->u_addr.ip6), + IP6_ADDR_BLOCK2(&ip->u_addr.ip6), + IP6_ADDR_BLOCK3(&ip->u_addr.ip6), + IP6_ADDR_BLOCK4(&ip->u_addr.ip6), + IP6_ADDR_BLOCK5(&ip->u_addr.ip6), + IP6_ADDR_BLOCK6(&ip->u_addr.ip6), + IP6_ADDR_BLOCK7(&ip->u_addr.ip6), + IP6_ADDR_BLOCK8(&ip->u_addr.ip6)); +} + +#else +void +print_ip(char *msg, ip_addr_t *ip) +{ + xil_printf(msg); + xil_printf("%d.%d.%d.%d\n\r", ip4_addr1(ip), ip4_addr2(ip), + ip4_addr3(ip), ip4_addr4(ip)); +} + +void +print_ip_settings(ip_addr_t *ip, ip_addr_t *mask, ip_addr_t *gw) +{ + + print_ip("Board IP: ", ip); + print_ip("Netmask : ", mask); + print_ip("Gateway : ", gw); +} + +#endif + +int main() +{ + xil_printf("start"); + + sys_thread_new("main_thrd", (void(*)(void*))main_thread, 0, + THREAD_STACKSIZE, + DEFAULT_THREAD_PRIO); + vTaskStartScheduler(); + + while(1); + + return 0; +} + +void network_thread(void *p) +{ + struct netif *netif; + /* the mac address of the board. this should be unique per board */ + unsigned char mac_ethernet_address[] = { 0x00, 0x0a, 0x35, 0x00, 0x01, 0x02 }; +#if LWIP_IPV6==0 + ip_addr_t ipaddr, netmask, gw; +#if LWIP_DHCP==1 + int mscnt = 0; +#endif +#endif + + netif = &server_netif; + + xil_printf("\r\n\r\n"); + xil_printf("-----lwIP Socket Mode CX9261 TEST server Application Version 2022.05.31------\r\n"); + +#if LWIP_IPV6==0 +#if LWIP_DHCP==0 + /* initliaze IP addresses to be used */ + IP4_ADDR(&ipaddr, 192, 168, 1, 99); + IP4_ADDR(&netmask, 255, 255, 255, 0); + IP4_ADDR(&gw, 192, 168, 1, 1); +#endif + + /* print out IP settings of the board */ + +#if LWIP_DHCP==0 + print_ip_settings(&ipaddr, &netmask, &gw); + /* print all application headers */ +#endif + +#if LWIP_DHCP==1 + ipaddr.addr = 0; + gw.addr = 0; + netmask.addr = 0; +#endif +#endif + +#if LWIP_IPV6==0 + /* Add network interface to the netif_list, and set it as default */ + if (!xemac_add(netif, &ipaddr, &netmask, &gw, mac_ethernet_address, PLATFORM_EMAC_BASEADDR)) { + xil_printf("Error adding N/W interface\r\n"); + return; + } +#else + /* Add network interface to the netif_list, and set it as default */ + if (!xemac_add(netif, NULL, NULL, NULL, mac_ethernet_address, PLATFORM_EMAC_BASEADDR)) { + xil_printf("Error adding N/W interface\r\n"); + return; + } + + netif->ip6_autoconfig_enabled = 1; + + netif_create_ip6_linklocal_address(netif, 1); + netif_ip6_addr_set_state(netif, 0, IP6_ADDR_VALID); + + print_ip6("\n\rBoard IPv6 address ", &netif->ip6_addr[0].u_addr.ip6); +#endif + + netif_set_default(netif); + + /* specify that the network if is up */ + netif_set_up(netif); + + /* start packet receive thread - required for lwIP operation */ + sys_thread_new("xemacif_input_thread", (void(*)(void*))xemacif_input_thread, netif, + THREAD_STACKSIZE, + DEFAULT_THREAD_PRIO); + +#if LWIP_IPV6==0 +#if LWIP_DHCP==1 + dhcp_start(netif); + while (1) { + vTaskDelay(DHCP_FINE_TIMER_MSECS / portTICK_RATE_MS); + dhcp_fine_tmr(); + mscnt += DHCP_FINE_TIMER_MSECS; + if (mscnt >= DHCP_COARSE_TIMER_SECS*1000) { + dhcp_coarse_tmr(); + mscnt = 0; + } + } +#else + xil_printf("\r\n"); + xil_printf("%20s %6s %s\r\n", "Server", "Port", "Connect With.."); + xil_printf("%20s %6s %s\r\n", "--------------------", "------", "--------------------"); + + print_echo_app_header(); + xil_printf("\r\n"); + sys_thread_new("echod", echo_application_thread, 0, + THREAD_STACKSIZE, + DEFAULT_THREAD_PRIO); + vTaskDelete(NULL); +#endif +#else + print_echo_app_header(); + xil_printf("\r\n"); + sys_thread_new("echod",echo_application_thread, 0, + THREAD_STACKSIZE, + DEFAULT_THREAD_PRIO); + vTaskDelete(NULL); +#endif + return; +} + +int main_thread() +{ +#if LWIP_DHCP==1 + int mscnt = 0; +#endif + +#ifdef XPS_BOARD_ZCU102 + IicPhyReset(); +#endif + + /* initialize lwIP before calling sys_thread_new */ + lwip_init(); + SpiPsInit(SPI_DEVICE_ID); + GpioInit(GPIO_DEVICE_ID); + AXIGpioInit(); + XScuGicInit(); + ConfigAXIGPIOIntr(); + ExceptionInit(); + + XAxiDma_Init(xAxiDma0Get(),AXI_DMA_DEVCIE_ID0); + XAxiDma_Init(xAxiDma1Get(),AXI_DMA_DEVCIE_ID1); + XAxiDma_Init(xAxiDma2Get(),AXI_DMA_DEVCIE_ID2); + PackerRst(); + + /* cx9261a configuration */ + peripheral_test(); + cx3e04_config(); +// cx9261a_710_config(); +// frqhop_config(1); + int temp = cx3e04_read(0x03A); + /* any thread using lwIP should be created using sys_thread_new */ + sys_thread_new("NW_THRD", network_thread, NULL, + THREAD_STACKSIZE, + DEFAULT_THREAD_PRIO); + +#if LWIP_IPV6==0 +#if LWIP_DHCP==1 + while (1) { + vTaskDelay(DHCP_FINE_TIMER_MSECS / portTICK_RATE_MS); + if (server_netif.ip_addr.addr) { + xil_printf("DHCP request success\r\n"); + print_ip_settings(&(server_netif.ip_addr), &(server_netif.netmask), &(server_netif.gw)); + print_echo_app_header(); + xil_printf("\r\n"); + sys_thread_new("echod", echo_application_thread, 0, + THREAD_STACKSIZE, + DEFAULT_THREAD_PRIO); + break; + } + mscnt += DHCP_FINE_TIMER_MSECS; + if (mscnt >= 10000) { + xil_printf("ERROR: DHCP request timed out\r\n"); + xil_printf("Configuring default IP of 192.168.1.100\r\n"); + IP4_ADDR(&(server_netif.ip_addr), 192, 168, 1, 100); + IP4_ADDR(&(server_netif.netmask), 255, 255, 255, 0); + IP4_ADDR(&(server_netif.gw), 192, 168, 1, 1); + print_ip_settings(&(server_netif.ip_addr), &(server_netif.netmask), &(server_netif.gw)); + /* print all application headers */ + xil_printf("\r\n"); + xil_printf("%20s %6s %s\r\n", "Server", "Port", "Connect With.."); + xil_printf("%20s %6s %s\r\n", "--------------------", "------", "--------------------"); + + print_echo_app_header(); + xil_printf("\r\n"); + sys_thread_new("echod", echo_application_thread, 0, + THREAD_STACKSIZE, + DEFAULT_THREAD_PRIO); + break; + } + } +#endif +#endif + vTaskDelete(NULL); + return 0; +} diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_HOP/platform_config.h b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_HOP/platform_config.h new file mode 100644 index 0000000..b84bf38 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_HOP/platform_config.h @@ -0,0 +1,10 @@ +#ifndef __PLATFORM_CONFIG_H_ +#define __PLATFORM_CONFIG_H_ + + +#define PLATFORM_EMAC_BASEADDR XPAR_XEMACPS_0_BASEADDR + +#define PLATFORM_ZYNQ + + +#endif diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_HOP/rx_wideband_qec.c b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_HOP/rx_wideband_qec.c new file mode 100644 index 0000000..ec8b2f5 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_HOP/rx_wideband_qec.c @@ -0,0 +1,61 @@ +/* + * wideband_qec.c + * + * Created on: 2023Äê11ÔÂ30ÈÕ + * Author: cxlab + */ + +#include "xilinx_io.h" +#include "sleep.h" +#include "math.h" +void rxFFTCalib(int lo, int fs,int ref, int firLength, int chan) { + u8 rx_data; + SpiPs_write_read1(0x000, chan == 1 ? 0x12 : 0x22,&rx_data); + SpiPs_write_read1(0x128, 0x00,&rx_data); + SpiPs_write_read1(0x11B, 0x01,&rx_data); + SpiPs_write_read1(0x11E, 0x01,&rx_data); + configTxNcoFreq(0, fs); + SpiPs_write_read1(0x161, 0x00,&rx_data); + SpiPs_write_read1(0x162, 0x00,&rx_data); + SpiPs_write_read1(0x162, 0x01,&rx_data); + SpiPs_write_read1(0x161, 0x01,&rx_data); + SpiPs_write_read1(0x000, chan == 1 ? 0x12 : chan == 2 ? 0x22 : 0x32,&rx_data); + SpiPs_write_read1(0x102, 0x03,&rx_data); + SpiPs_write_read1(0x102, 0xFF,&rx_data); + SpiPs_write_read1(0x15C, 0x00,&rx_data); + SpiPs_write_read1(0x160, 0x01,&rx_data); + SpiPs_write_read1(0x77E, chan == 1 ? 0x50 : chan == 2 ? 0x0A : 0x03,&rx_data); + SpiPs_write_read1(0x09B, 0x01,&rx_data); // TXPLL4 + SpiPs_write_read1(0x09D, firLength,&rx_data); + SpiPs_write_read1(0x096, ((u32)round(lo) >> 8) & 0xFF,&rx_data); + SpiPs_write_read1(0x097, (u32)round(lo) & 0xFF,&rx_data); + SpiPs_write_read1(0x098, ((u32)round(ref * 10) >> 8) & 0xFF,&rx_data); + SpiPs_write_read1(0x099, (u32)round(ref * 10) & 0xFF,&rx_data); + SpiPs_write_read1(0x09E, ((u32)round(fs * 100) >> 8) & 0xFF,&rx_data); + SpiPs_write_read1(0x09F, (u32)round(fs * 100) & 0xFF,&rx_data); + SpiPs_write_read1(0x09C, chan,&rx_data); + while (1) { + if (SpiPs_write_read2(0x0B3,0x00,&rx_data) == 5) + break; + usleep(10000); + } + SpiPs_write_read1(0x09C, 0x00,&rx_data); + SpiPs_write_read1(0x15C, 0x01,&rx_data); + SpiPs_write_read1(0x77E, 0x00,&rx_data); + + //ͨµÀʱÖÓÀ´Դ + u8 r77D=0xC0; + u8 r775=0x24; + u8 r6C3=0x00; + SpiPs_write_read1(0x77D, r77D,&rx_data); + SpiPs_write_read1(0x775, r775,&rx_data); + SpiPs_write_read1(0x6C3, r6C3,&rx_data); +} + + +void configDcCalib(int dcCalibEnable,int dcCalibLength) { + u8 rx_data; + SpiPs_write_read1(0x109, dcCalibEnable ? 0x11 : 0x00,&rx_data); + SpiPs_write_read1(0x10A, (dcCalibLength) << 4,&rx_data); + SpiPs_write_read1(0x11F, dcCalibEnable ? 0x33 : 0x73,&rx_data); +} diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_HOP/sd.c b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_HOP/sd.c new file mode 100644 index 0000000..111123b --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_HOP/sd.c @@ -0,0 +1,178 @@ +#include "sd.h" +/************************** Variable Definitions *****************************/ +static FIL fil; /* File object */ +static FATFS fatfs; +/* + * To test logical drive 0, FileName should be "0:/" or + * "". For logical drive 1, FileName should be "1:/" + */ +static char FileName[32] = "BOOT.bin"; +static char *SD_File; + + +//#define BUFF_SIZE sizeof(image_data) +#define BUFF_SIZE 0x2000000 +#ifdef __ICCARM__ +#pragma data_alignment = 32 +u8 DestinationAddress[10*1024]; +#pragma data_alignment = 32 +u8 SourceAddress[10*1024]; +#else +//u8 DestinationAddress[10*1024] __attribute__ ((aligned(32))); +//u8 SourceAddress[10*1024] __attribute__ ((aligned(32))); + +u8 DestinationAddress[BUFF_SIZE] __attribute__ ((aligned(32))); +u8 SourceAddress[BUFF_SIZE] __attribute__ ((aligned(32))); +#endif + +#define TEST 7 + + + +/*****************************************************************************/ +/** +* +* File system example using SD driver to write to and read from an SD card +* in polled mode. This example creates a new file on an +* SD card (which is previously formatted with FATFS), write data to the file +* and reads the same data back to verify. +* +* @param None +* +* @return XST_SUCCESS if successful, otherwise XST_FAILURE. +* +* @note None +* +******************************************************************************/ +int FfsSdWrite(u8*image_data, u32 FileSize) +{ + int error_flag = 0; + FRESULT Res; + UINT NumBytesRead; + UINT NumBytesWritten; + u32 BuffCnt; + BYTE work[FF_MAX_SS]; +// u32 FileSize = (8*1024); +// u32 FileSize = sizeof(image_data); + /* + * To test logical drive 0, Path should be "0:/" + * For logical drive 1, Path should be "1:/" + */ + TCHAR *Path = "0:/"; + u8 checksum = 0; + + for(BuffCnt = 0; BuffCnt < FileSize; BuffCnt++){ +// SourceAddress[BuffCnt] = TEST + BuffCnt; + SourceAddress[BuffCnt] = image_data[BuffCnt]; + checksum = checksum + image_data[BuffCnt]; + } + xil_printf("checksum is 0x%x.",checksum); + + + /* + * Register volume work area, initialize device + */ + Res = f_mount(&fatfs, Path, 0); + + if (Res != FR_OK) { + return XST_FAILURE; + } + + /* + * Path - Path to logical driver, 0 - FDISK format. + * 0 - Cluster size is automatically determined based on Vol size. + */ + Res = f_mkfs(Path, FM_FAT32, 0, work, sizeof work); + if (Res != FR_OK) { + return XST_FAILURE; + } + + /* + * Open file with required permissions. + * Here - Creating new file with read/write permissions. . + * To open file with write permissions, file system should not + * be in Read Only mode. + */ + SD_File = (char *)FileName; + + Res = f_open(&fil, SD_File, FA_CREATE_ALWAYS | FA_WRITE | FA_READ); + if (Res) { + return XST_FAILURE; + } + + /* + * Pointer to beginning of file . + */ + Res = f_lseek(&fil, 0); + if (Res) { + return XST_FAILURE; + } + + /* + * Write data to file. + */ + Res = f_write(&fil, (const void*)SourceAddress, FileSize, + &NumBytesWritten); + if (Res) { + return XST_FAILURE; + } + /* + * Close file. + */ + Res = f_close(&fil); + if (Res) { + return XST_FAILURE; + } + Res = f_open(&fil, SD_File, FA_READ); + if (Res) { + return XST_FAILURE; + } + /* + * Pointer to beginning of file . + */ + Res = f_lseek(&fil, 0); + if (Res) { + return XST_FAILURE; + } + + /* + * Read data from file. + */ + Res = f_read(&fil, (void*)DestinationAddress, FileSize, + &NumBytesRead); + if (Res) { + return XST_FAILURE; + } + + /* + * Data verification + */ + for(BuffCnt = 0; BuffCnt < FileSize; BuffCnt++){ + if(SourceAddress[BuffCnt] != DestinationAddress[BuffCnt]){ +// return XST_FAILURE; + error_flag = 1; + xil_printf('Data check error.'); + } + } + + /* + * Close file. + */ + Res = f_close(&fil); + if (Res) { + return XST_FAILURE; + } + + if(error_flag){ + return XST_FAILURE; + } + +// Res = f_unmount(Path); +// if (Res) { +// return XST_FAILURE; +// } +// +// sleep(5); + + return XST_SUCCESS; +} diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_HOP/sd.h b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_HOP/sd.h new file mode 100644 index 0000000..91e744c --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_HOP/sd.h @@ -0,0 +1,9 @@ +/***************************** Include Files *********************************/ +#include "xparameters.h" /* SDK generated parameters */ +#include "xsdps.h" /* SD device driver */ +#include "xil_printf.h" +#include "ff.h" +#include "xil_cache.h" +#include "xplatform_info.h" +/************************** Function Prototypes ******************************/ +int FfsSdWrite(u8*image_data, u32 FileSize); diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_HOP/tx_bisection.c b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_HOP/tx_bisection.c new file mode 100644 index 0000000..fd031b9 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_HOP/tx_bisection.c @@ -0,0 +1,74 @@ +/* + * tx_bisection.c + * + * Created on: 2023Äê12ÔÂ1ÈÕ + * Author: cxlab + */ + + +#include "xilinx_io.h" +#include "sleep.h" +#include "math.h" + +void txBisectionQecCalib(int f0, int fs) { + u8 rx_data; + SpiPs_write_read1(0x02E, 0x03,&rx_data); + SpiPs_write_read1(0x128, 0x11,&rx_data); + SpiPs_write_read1(0x11E, 0x01,&rx_data); + SpiPs_write_read1(0x77E, 0x24,&rx_data); + SpiPs_write_read1(0x11F, 0x01,&rx_data); + SpiPs_write_read1(0x121, 0x02,&rx_data); + SpiPs_write_read1(0x11B, 0x01,&rx_data); + SpiPs_write_read1(0x161, 0x01,&rx_data); + SpiPs_write_read1(0x162, 0x01,&rx_data); + SpiPs_write_read1(0x163, 0x00,&rx_data); + configTxNcoFreq(f0, fs * 4); + SpiPs_write_read1(0xA2D, 0x02,&rx_data); + SpiPs_write_read1(0xA07, 0x00,&rx_data); + SpiPs_write_read1(0xA08, 0x0F,&rx_data); + SpiPs_write_read1(0xA1C, 0x01,&rx_data); + configRxNcoFreq(f0 * 2, fs); + SpiPs_write_read1(0x186, 0x01,&rx_data); + SpiPs_write_read1(0x763, 0x34,&rx_data); + SpiPs_write_read1(0x76D, 0x34,&rx_data); + SpiPs_write_read1(0x101, 0xEF,&rx_data); + SpiPs_write_read1(0x101, 0xFF,&rx_data); + SpiPs_write_read1(0x800, 0x00,&rx_data); + SpiPs_write_read1(0x81A, 0xF7,&rx_data); + SpiPs_write_read1(0x81B, 0x34,&rx_data); + SpiPs_write_read1(0x81C, 0x33,&rx_data); + SpiPs_write_read1(0x81D, 0x12,&rx_data); + SpiPs_write_read1(0x81E, 0x00,&rx_data); + SpiPs_write_read1(0x81F, 0xFF,&rx_data); + SpiPs_write_read1(0x820, 0x00,&rx_data); + SpiPs_write_read1(0x821, 0xFF,&rx_data); + SpiPs_write_read1(0x800, 0x80,&rx_data); + SpiPs_write_read1(0x800, 0x81,&rx_data); + usleep(100000); + SpiPs_write_read1(0x77E, 0x00,&rx_data); +} + +void txBisectionDcCalib(int f0, int fs) { + u8 rx_data; + SpiPs_write_read1(0x77E, 0x24,&rx_data); + SpiPs_write_read1(0x11F, 0x03,&rx_data); + SpiPs_write_read1(0x121, 0x02,&rx_data); + SpiPs_write_read1(0x11B, 0x01,&rx_data); + SpiPs_write_read1(0x11E, 0x01,&rx_data); + SpiPs_write_read1(0x161, 0x01,&rx_data); + SpiPs_write_read1(0x162, 0x01,&rx_data); + configTxNcoFreq(f0, fs * 4); + SpiPs_write_read1(0xA2D, 0x02,&rx_data); + SpiPs_write_read1(0xA07, 0x00,&rx_data); + SpiPs_write_read1(0xA08, 0x0F,&rx_data); + SpiPs_write_read1(0xA1C, 0x01,&rx_data); + configRxNcoFreq(f0, fs); + SpiPs_write_read1(0x81A, 0xF7,&rx_data); + SpiPs_write_read1(0x81B, 0x44,&rx_data); + SpiPs_write_read1(0x81C, 0x33,&rx_data); + SpiPs_write_read1(0x81D, 0x14,&rx_data); + SpiPs_write_read1(0x800, 0x80,&rx_data); + SpiPs_write_read1(0x800, 0x82,&rx_data); + usleep(500000); + SpiPs_write_read1(0x77E, 0x00,&rx_data); +} diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_HOP/xilinx_io.c b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_HOP/xilinx_io.c new file mode 100644 index 0000000..69b4d8a --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_HOP/xilinx_io.c @@ -0,0 +1,905 @@ +/* + * xilinx_io.c + * + * Created on: 2021Äê9ÔÂ6ÈÕ + * Author: cxlab + */ + + +#include "sleep.h" +#include "math.h" +#include "xilinx_io.h" /* SPI device driver */ + +static XSpiPs SpiInstance; +XGpioPs Gpio; /* The driver instance for GPIO Device. */ +XGpio axi_gpio_inst; //PL ¶Ë AXI GPIO Çý¶¯ʵÀý +XScuGic scugic_inst; //ÖжϿØÖÆÆ÷ Çý¶¯ʵÀý +XScuGic_Config * scugic_cfg_ptr; //ÖжϿØÖÆÆ÷ ÅäÖÃÐÅϢ +int hop_flag,hop_intr_flag; +static int spi_select_value=0; + +XAxiDma AxiDma0,AxiDma1,AxiDma2; + +XAxiDma* xAxiDma0Get(void){ + return &AxiDma0; +} + +XAxiDma* xAxiDma1Get(void){ + return &AxiDma1; +} + +XAxiDma* xAxiDma2Get(void){ + return &AxiDma2; +} +void AXIGpioInit(void){ + XGpio_Initialize(&axi_gpio_inst, AXI_GPIO_ID); + //ÅäÖà PL AXI GPIO + XGpio_SetDataDirection(&axi_gpio_inst, 1, 1); //ÉèÖà AXI GPIO ͨµÀ 1 ΪÊäÈë + XGpio_InterruptEnable(&axi_gpio_inst, KEY_MASK); //ʹÄÜͨµÀ 1 ÖжÏ + XGpio_InterruptGlobalEnable(&axi_gpio_inst); //ʹÄÜ AXI GPIO ȫ¾ÖÖжÏ +} + +void ConfigAXIGPIOIntr(void){ + //ÉèÖÃÖжÏÓÅÏȼ¶ºʹ¥·¢ÀàÐÍ(¸ߵçƽ´¥·¢) + XScuGic_SetPriorityTriggerType(&scugic_inst, GPIO_INT_ID, 0xA0, 0x3); + //¹ØÁªÖжÏ ID ºÍÖжϴ¦Àíº¯Êý + XScuGic_Connect(&scugic_inst, GPIO_INT_ID, axi_gpio_handler, &axi_gpio_inst); + //ʹÄÜ AXI GPIO ÖжÏ + XScuGic_Enable(&scugic_inst, GPIO_INT_ID); +} +void axi_gpio_handler(void *CallbackRef){ + XGpio *GpioPtr = (XGpio *)CallbackRef; +// print("Interrupt Detected!\n"); + GpioWritePin(hop,0x01); + XGpio_InterruptDisable(GpioPtr, KEY_MASK); //¹رÕ AXI GPIO ÖжÏʹÄÜ +// u32 r=XGpio_DiscreteRead(GpioPtr, 1); +// if(r == 1){ + frqhop_config(hop_flag); +// }else{ +// print("Interrupt unvalid!\n"); +// } + XGpio_InterruptClear(GpioPtr, KEY_MASK); //Çå³ýÖжÏ + XGpio_InterruptEnable(GpioPtr, KEY_MASK); //ʹÄÜ AXI GPIO ÖжÏ + GpioWritePin(hop,0x00); +} +void frqhop_flag(int frqhop_flag){ + u8 rx_data; + hop_flag = frqhop_flag; + GpioSetPinDir(hop,GPIO_DIR_OUTPUT); + GpioWritePin(hop,0x01); + SpiPs_write_read2(0x615,0x00,&rx_data); + GpioWritePin(hop,0x00); +} + +void ExceptionInit(void){ + //ÉèÖò¢´ò¿ªÖжÏÒ쳣´¦Àí¹¦ÄÜ + Xil_ExceptionInit(); + Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, (Xil_ExceptionHandler)XScuGic_InterruptHandler, &scugic_inst); + Xil_ExceptionEnable(); +} +void XScuGicInit(void){ + scugic_cfg_ptr = XScuGic_LookupConfig(SCUGIC_ID); + XScuGic_CfgInitialize(&scugic_inst, scugic_cfg_ptr, scugic_cfg_ptr->CpuBaseAddress); +} + +int SpiPsInit(u16 SpiDeviceId){ + int Status; + XSpiPs_Config *SpiConfig; + /* + * Initialize the SPI driver so that it's ready to use + */ + SpiConfig = XSpiPs_LookupConfig(SpiDeviceId); + if (NULL == SpiConfig) { + return XST_FAILURE; + } + Status = XSpiPs_CfgInitialize((&SpiInstance), SpiConfig, + SpiConfig->BaseAddress); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Perform a self-test to check hardware build + */ + Status = XSpiPs_SelfTest((&SpiInstance)); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + /* + * The SPI device is a slave by default and the clock phase + * have to be set according to its master. In this example, CPOL is set + * to quiescent high and CPHA is set to 1. + */ + + XSpiPs_SetOptions((&SpiInstance), (XSPIPS_CR_CPHA_MASK) | + XSPIPS_MASTER_OPTION | + XSPIPS_FORCE_SSELECT_OPTION); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + XSpiPs_SetClkPrescaler((&SpiInstance), XSPIPS_CLK_PRESCALE_8); + /* + * Set the Rx FIFO Threshold to the Max Data + */ +// XSpiPs_SetRXWatermark((&SpiInstance),MAX_DATA); + /* + * Enable the device. + */ + XSpiPs_Enable((&SpiInstance)); + +return XST_SUCCESS; +} + +int cx3e04_write(int addr , int value) +{ + Xil_Out32(AXI4_LITE0_SPI_BASEADDR+addr*4,value); + return 1; +} + +int cx3e04_read(int addr) +{ + return Xil_In32(AXI4_LITE0_SPI_BASEADDR+addr*4); +} + +int cx9261a_write(int addr , int value) +{ + Xil_Out32(AXI4_LITE1_SPI_BASEADDR+addr*4,value); + return 1; +} + +int cx9261a_read(int addr) +{ + return Xil_In32(AXI4_LITE1_SPI_BASEADDR+addr*4); +} + +void cx3e04_config(void) +{ + //³Çо¿Ƽ¼CX3E04 + //Common + cx3e04_write(0x000,0x12); + cx3e04_write(0x002,0x38); + cx3e04_write(0x038,0x01); + cx3e04_write(0x003,0x30); + cx3e04_write(0x039,0x00); + //CLK + //clk lvds en + cx3e04_write(0x011,0x7F); + cx3e04_write(0x012,0x34); + cx3e04_write(0x036,0x7F); + cx3e04_write(0x01A,0x4B); + cx3e04_write(0x013,0x04); + cx3e04_write(0x014,0x04); + cx3e04_write(0x004,0x00); + cx3e04_write(0x008,0x00); + cx3e04_write(0x009,0x00); + cx3e04_write(0x015,0x04); + cx3e04_write(0x016,0x04); + cx3e04_write(0x005,0x00); + cx3e04_write(0x00A,0x00); + cx3e04_write(0x00B,0x00); + cx3e04_write(0x017,0x04); + cx3e04_write(0x018,0x04); + cx3e04_write(0x006,0x00); + cx3e04_write(0x00C,0x00); + cx3e04_write(0x00D,0x00); + cx3e04_write(0x019,0x04); + cx3e04_write(0x007,0x00); + cx3e04_write(0x00E,0x00); + cx3e04_write(0x00F,0x00); + cx3e04_write(0x010,0x00); + cx3e04_write(0x029,0x00); + cx3e04_write(0x02A,0x00); + //SYNC + //sync lvds en + cx3e04_write(0x033,0x7F); + cx3e04_write(0x034,0x34); + cx3e04_write(0x035,0x7F); + cx3e04_write(0x032,0x03); + //sync inner div + cx3e04_write(0x03A,0x00); + cx3e04_write(0x03B,0x00); + cx3e04_write(0x03A,0x01); + cx3e04_write(0x03B,0xFF);//512·ÖƵ + cx3e04_write(0x03C,0x21); + cx3e04_write(0x03D,0x80); + cx3e04_write(0x02B,0x04); + cx3e04_write(0x02C,0x04); + cx3e04_write(0x01B,0x00); + cx3e04_write(0x01C,0x00); + cx3e04_write(0x022,0x00); + cx3e04_write(0x023,0x00); + cx3e04_write(0x02D,0x04); + cx3e04_write(0x02E,0x04); + cx3e04_write(0x01D,0x00); + cx3e04_write(0x01E,0x00); + cx3e04_write(0x024,0x00); + cx3e04_write(0x025,0x00); + cx3e04_write(0x02F,0x04); + cx3e04_write(0x030,0x04); + cx3e04_write(0x01F,0x00); + cx3e04_write(0x020,0x00); + cx3e04_write(0x026,0x00); + cx3e04_write(0x027,0x00); + cx3e04_write(0x031,0x04); + cx3e04_write(0x021,0x00); + cx3e04_write(0x028,0x00); + //ƫÖõçÁ÷ + cx3e04_write(0x040,0xFF); + cx3e04_write(0x041,0xFF); + cx3e04_write(0x042,0xFF); + cx3e04_write(0x043,0xF0); + cx3e04_write(0x044,0xFF); + cx3e04_write(0x045,0xFF); + cx3e04_write(0x046,0xFF); + cx3e04_write(0x047,0xF0); + //Others + cx3e04_write(0x037,0x07); +} + +//int SpiPs_write_read(u8 cmd, u16 addr,u8 data,u8 * rx_data){ +int SpiPs_write_read(u8 * data,u8 * rx_data){ + int Status; + u8 rx_buffer[3]; + + if(spi_select_value == 0){ + rx_buffer[0]= *data; + rx_buffer[1]= *(data+1); + rx_buffer[2]= *(data+2); + if(rx_buffer[0] >= 128){ + cx9261a_write((rx_buffer[0]-128)*256+rx_buffer[1],rx_buffer[2]); + }else{ + *rx_data=cx9261a_read(rx_buffer[0]*256+rx_buffer[1]); + } + }else{ + + XSpiPs_SetSlaveSelect((&SpiInstance),0x00); + + Status = XSpiPs_PolledTransfer((&SpiInstance),data,rx_buffer,3); + + *rx_data = rx_buffer[2]; + + } + +return 0; +} +int SpiPs_write_read1(u16 addr,u8 data,u8 * rx_data){ + u8 rx_data1; + u16 temp; + u8 rx_buffer[3]; + + temp= addr&0x00ff; + rx_buffer[0]= temp/256+128; + rx_buffer[1]= addr&0x00ff; + rx_buffer[2]= data; + + if(spi_select_value == 0){ + cx9261a_write(addr,data); + }else{ + + SpiPs_write_read((u8 *)&rx_buffer,&rx_data1); + *rx_data = rx_data1; + } + +return 0; +} +int SpiPs_write_read2(u16 addr,u8 data,u8 * rx_data){ + u8 rx_data1; + u16 temp; + u8 rx_buffer[3]; + + temp= addr&0x00ff; + rx_buffer[0]= temp/256; + rx_buffer[1]= addr&0x00ff; + rx_buffer[2]= data; + + if(spi_select_value == 0){ + *rx_data=cx9261a_read(addr); + }else{ + SpiPs_write_read((u8 *)&rx_buffer,&rx_data1); + *rx_data = rx_data1; + } + +return 0; +} + +int GpioInit(u16 DeviceId) +{ + int Status; + XGpioPs_Config *ConfigPtr; + /* Initialize the GPIO driver. */ + ConfigPtr = XGpioPs_LookupConfig(DeviceId); + Status = XGpioPs_CfgInitialize(&Gpio, ConfigPtr, + ConfigPtr->BaseAddr); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + return XST_SUCCESS; +} + +int GpioSetPinDir(u32 Pin,u32 Direction){ + XGpioPs_SetDirectionPin((&Gpio),GPIO_EMIO_OFFSET + Pin,Direction); + return 0; +} +int GpioWritePin(u32 Pin,u32 data){ + XGpioPs_SetOutputEnablePin(&Gpio, GPIO_EMIO_OFFSET + Pin, 1); + XGpioPs_WritePin((&Gpio),GPIO_EMIO_OFFSET + Pin,data); + return 0; +} + +int GpioReadPin(u32 Pin){ + return XGpioPs_ReadPin((&Gpio),GPIO_EMIO_OFFSET + Pin); +} + +void DeviceRst(void){ + GpioWritePin(NRST,0); + GpioWritePin(NRST,1); +} + +int XAxiDma_Init(XAxiDma* AxiDma,u16 DeviceId){ + + XAxiDma_Config *CfgPtr; + int Status; + /* Initialize the XAxiDma device. + */ + CfgPtr = XAxiDma_LookupConfig(DeviceId); + if (!CfgPtr) { + xil_printf("No config found for %d\r\n", DeviceId); + return XST_FAILURE; + } + + Status = XAxiDma_CfgInitialize(AxiDma, CfgPtr); + if (Status != XST_SUCCESS) { + xil_printf("Initialization failed %d\r\n", Status); + return XST_FAILURE; + } + + if(XAxiDma_HasSg(AxiDma)){ + xil_printf("Device configured as SG mode \r\n"); + return XST_FAILURE; + } + + /* Disable interrupts, we use polling mode + */ + XAxiDma_IntrDisable(AxiDma, XAXIDMA_IRQ_ALL_MASK, + XAXIDMA_DEVICE_TO_DMA); + XAxiDma_IntrDisable(AxiDma, XAXIDMA_IRQ_ALL_MASK, + XAXIDMA_DMA_TO_DEVICE); +return 0; +} + +int XAxiDmaCapture(XAxiDma* AxiDma,u32 data_length){ + int Status; + u8 *TxBufferPtr; + u32 MAX_PKT_LEN; + MAX_PKT_LEN = data_length; + TxBufferPtr = (u8 *)TX_BUFFER_BASE; + Xil_DCacheFlushRange((UINTPTR)TxBufferPtr, MAX_PKT_LEN); + Status = XAxiDma_Busy(AxiDma,XAXIDMA_DEVICE_TO_DMA); + Status = XAxiDma_Busy(AxiDma,XAXIDMA_DMA_TO_DEVICE); + XAxiDma_Reset(AxiDma); + Status = XAxiDma_ResetIsDone(AxiDma); + Status = XAxiDma_Busy(AxiDma,XAXIDMA_DEVICE_TO_DMA); + Status = XAxiDma_Busy(AxiDma,XAXIDMA_DMA_TO_DEVICE); + + Status = XAxiDma_SimpleTransfer(AxiDma,(UINTPTR) TxBufferPtr,MAX_PKT_LEN*8, XAXIDMA_DEVICE_TO_DMA); + SetPacketSize(AxiDma,MAX_PKT_LEN); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + u32 start_TickCount,current_TickCount=0; + start_TickCount = sys_now(); + u32 offset= 0; + //never come out ,reason is stream does't have tlast.Need a module to pack excatly the same length defined in para. + while ((offset< 500)&&(XAxiDma_Busy(AxiDma,XAXIDMA_DEVICE_TO_DMA))) { + Status = XAxiDma_Busy(AxiDma,XAXIDMA_DEVICE_TO_DMA); + + current_TickCount =sys_now(); + offset = current_TickCount-start_TickCount; +// xil_printf("offset: %d\r\n", offset); + } + /* + u64 offset= 0; + //never come out ,reason is stream does't have tlast.Need a module to pack excatly the same length defined in para. + while ((offset> 100000)||(XAxiDma_Busy(AxiDma,XAXIDMA_DEVICE_TO_DMA))) { + Status = XAxiDma_Busy(AxiDma,XAXIDMA_DEVICE_TO_DMA); + }*/ + return 0; +} + + + +int SetPacketSize(XAxiDma* AxiDma,u32 length){ + + UINTPTR Addr; + if(AxiDma == xAxiDma0Get()) + Addr = PACKER_BASEADDR0; + else if(AxiDma == xAxiDma1Get()) + Addr = PACKER_BASEADDR1; + else + Addr = PACKER_BASEADDR2; + xil_printf("addr %x .\n",Addr); + Xil_Out32(Addr,0); + xil_printf("PACKER_BASEADDR DATA %d .\n",Xil_In32(Addr)); + Xil_Out32(Addr+4,length); + xil_printf("PACKER_BASEADDR +4 DATA %d .\n",Xil_In32(Addr + 4)); + Xil_Out32(Addr,1); + xil_printf("PACKER_BASEADDR DATA %d .\n",Xil_In32(Addr)); + return 0; +} +int DownloadWave(u8 * data){ + u32 * buffer; + u64 addr; + int i; + buffer = (u32 *) data; + addr = BRAM_BASEADDR; + for(i=0;irecv_buf[spistack->spi_write_num * 3 + 0] = *(data + 0); + spistack->recv_buf[spistack->spi_write_num * 3 + 1] = *(data + 1); + spistack->recv_buf[spistack->spi_write_num * 3 + 2] = *(data + 2); + spistack->spi_write_num = spistack->spi_write_num + 1; + if(spistack->spi_write_num >= SPI_STACK_LENGTH-1){ + return 1; + } + else + return 0; +} + +void spi_stack_out(struct spi_stack * spistack){ + + int i; + u8 rx_data; + for(i=0;ispi_write_num;i++ ){ + SpiPs_write_read((u8 *)&(spistack->recv_buf[i * 3]),&rx_data); + } + spistack->spi_write_num = 0; +} + +int rom_read(u8 * data) +{ + int addr ; + addr = *(data + 0)*256+ *(data + 1); + return Xil_In32(BROM_BASEADDR+addr*4); +} + +void trx_ch_pll_config(u8 pll_index) +{ + u8 rx_data; + u8 recv_buf[3]={0}; + u32 trx_ch_pll_data; + + if(pll_index==1){ + trx_ch_pll_data = 0x00077DCF; + }else if(pll_index==2){ + trx_ch_pll_data = 0x00077D0C; + } + + recv_buf[0] =(trx_ch_pll_data>>16 & 0xff)|0x80 ; + recv_buf[1] = trx_ch_pll_data>>8 & 0xff; + recv_buf[2] = trx_ch_pll_data & 0xff; + SpiPs_write_read(recv_buf,&rx_data); +} + +u16 pll1_config_addr[] ={0x0620,0x061D,0x0B06,0x0B07,0x0B08,0x0B09,0x0B0A,0x061A,0x061B,0x061C,0x062A}; +u16 pll2_config_addr[] ={0x0642,0x063F,0x0B14,0x0B15,0x0B16,0x0B17,0x0B18,0x063C,0x063D,0x063E,0x064C}; +u16 pll3_config_addr[] ={0x0664,0x0661,0x0B22,0x0B23,0x0B24,0x0B25,0x0B26,0x065E,0x065F,0x0660,0x066E}; +u16 pll4_config_addr[] ={0x0686,0x0683,0x0B30,0x0B31,0x0B32,0x0B33,0x0B34,0x0680,0x0681,0x0682,0x0690}; + +int PLL_config(u8 pll_index,double pll_frq) +{ + + int i = 0,afc_cnt=0; + u16 pll_config_addr[11]; + u16 afc_addr,lock_addr; + double ref=200; + u8 pllreg_buf[11]; + u8 recv_buf[3]; + u8 rx_data,pll_div; + u16 div_addr; + + switch(pll_index){ + case 1:for (i = 0; i < 11; i++){pll_config_addr[i] = pll1_config_addr[i];} afc_addr=0x0617;lock_addr=0x0635;break; + case 2:for (i = 0; i < 11; i++){pll_config_addr[i] = pll2_config_addr[i];} afc_addr=0x0639;lock_addr=0x0657;break; + case 3:for (i = 0; i < 11; i++){pll_config_addr[i] = pll3_config_addr[i];} afc_addr=0x065B;lock_addr=0x0679;break; + case 4:for (i = 0; i < 11; i++){pll_config_addr[i] = pll4_config_addr[i];} afc_addr=0x067D;lock_addr=0x069B;break; + default :; + } + //caculate pll frequence word + pll_frq_caculation_new(ref,pll_frq,(u8 *)&pllreg_buf); + for (i = 0; i < 11; i++) + { + recv_buf[0] = (pll_config_addr[i]>>8 & 0xff)|0x80 ; + recv_buf[1] = pll_config_addr[i] & 0xff; + recv_buf[2] = pllreg_buf[i] & 0xff; + SpiPs_write_read((u8 *)&recv_buf[0],&rx_data); + } + //afc pll + pll_div = pllreg_buf[1]; + div_addr = pll_config_addr[1]; + recv_buf[0] = lock_addr>>8 & 0xff ; + recv_buf[1] = lock_addr & 0xff; + recv_buf[2] = 0x00; + rx_data = 0; + while(rx_data!=48){ + PLL_afc(afc_addr,div_addr,pll_div); + SpiPs_write_read((u8 *)&recv_buf[0],&rx_data); + afc_cnt++; + } + return afc_cnt; + //xil_printf("afc lock count: %d.\r\n",afc_cnt); + +} + +void PLL_afc(u16 afc_addr,u16 div_addr,u8 pll_div){ + + u8 recv_buf[3]; + u8 rx_data; + if(pll_div>=48){ + recv_buf[0] = (div_addr>>8 & 0xff)|0x80 ; + recv_buf[1] = div_addr & 0xff; + recv_buf[2] = pll_div & 0x2f; + SpiPs_write_read((u8 *)&recv_buf[0],&rx_data); + } + recv_buf[0] = (afc_addr>>8 & 0xff)|0x80 ; + recv_buf[1] = afc_addr & 0xff; + recv_buf[2] = 0x00; + SpiPs_write_read((u8 *)&recv_buf[0],&rx_data); + recv_buf[2] = 0x03; + SpiPs_write_read((u8 *)&recv_buf[0],&rx_data); + usleep(30); + if(pll_div>=48){ + recv_buf[0] = (div_addr>>8 & 0xff)|0x80 ; + recv_buf[1] = div_addr & 0xff; + recv_buf[2] = pll_div & 0xff; + SpiPs_write_read((u8 *)&recv_buf[0],&rx_data); + } + +} + +int pll_frq_caculation(double ref,double pll_frq,u8 *reg_data){ + + u8 row,column; + int vco = pll_frq; + int div = 1; + while(vco < 7001){ + vco = vco*2; + div = div*2; + } + char coreTable[7][4][3] = {{{0x0C,0x30,0x08},{0x0B,0x30,0x09},{0x0C,0x30,0x05},{0x0D,0x30,0x08}}, + {{0x0C,0x30,0x0C},{0x0B,0x30,0x0E},{0x0C,0x30,0x08},{0x0D,0x30,0x0B}}, + {{0x0C,0x20,0x10},{0x0B,0x20,0x10},{0x0C,0x20,0x0A},{0x0D,0x20,0x0D}}, + {{0x0C,0x20,0x11},{0x0B,0x20,0x13},{0x0C,0x20,0x0C},{0x0D,0x20,0x0F}}, + {{0x0D,0x30,0x14},{0x0D,0x22,0x14},{0x0D,0x20,0x0D},{0x0D,0x15,0x0C}}, + {{0x0E,0x30,0x18},{0x0E,0x25,0x16},{0x0E,0x25,0x0F},{0x0E,0x18,0x0F}}, + {{0x0F,0x38,0x1A},{0x0F,0x32,0x1C},{0x0F,0x18,0x12},{0x0F,0x18,0x12}}}; + + if (ref >= 28 && ref < 40){ + row = 0; + }else if (ref >= 40 && ref < 60){ + row = 1; + }else if (ref >= 60 && ref < 90){ + row = 2; + }else if (ref >= 90 && ref < 110){ + row = 3; + }else if (ref >= 110 && ref < 140){ + row = 4; + }else if (ref >= 140 && ref < 180){ + row = 5; + }else if (ref >= 180 && ref <= 240){ + row = 6; + } + + if (vco >= 7001 && vco < 8400){ + column = 0; + }else if (vco >= 8400 && vco < 10500){ + column = 1; + }else if (vco >= 10500 && vco < 12000){ + column = 2; + }else if (vco >= 12000 && vco <= 14000){ + column = 3; + } + + char cp = coreTable[row][column][0]; + char c1r3 = coreTable[row][column][1]; + char r1 = coreTable[row][column][2]; + + char dither,nHigh,nLow,fHigh,fMiddle,fLow,outputDiv,core = 0x81; + if(vco > 10500){ + core = core + 0x10; + } + if (div == 2){ + outputDiv = 0+7; + }else if (div == 4){ + outputDiv = 32+7; + }else{ + outputDiv = 48 + divBin(div); + } + + double nf = 1.0*vco / ref; + int n = nf; + double f = nf - n; + if(f > 1e-10){ + dither = 11; + }else{ + dither = 0; + } + if(n >= 256){ + nHigh = 1; + }else{ + nHigh = 0; + } + nLow = n & 0xff; + int f1 = f * pow(2,24); + fHigh = f1>>16 & 0xff; + fMiddle = f1>>8 & 0xff; + fLow = f1 & 0xff; + reg_data[0]=core; + reg_data[1]=outputDiv; + reg_data[2]=nHigh; + reg_data[3]=nLow; + reg_data[4]=fHigh; + reg_data[5]=fMiddle; + reg_data[6]=fLow; + reg_data[7]=cp; + reg_data[8]=c1r3; + reg_data[9]=r1; + reg_data[10]=dither; + return 0; +} +int pll_frq_caculation_new(double ref,double pll_frq,u8 *reg_data){ + + u8 row,column; + double vco = pll_frq; + int div = 1; + while(vco < 6701){ + vco = vco*2; + div = div*2; + } + char coreTable[7][4][3] = {{{0x0C,0x30,0x08},{0x0B,0x30,0x09},{0x0C,0x30,0x05},{0x0D,0x30,0x08}}, + {{0x0C,0x30,0x0C},{0x0B,0x30,0x0E},{0x0C,0x30,0x08},{0x0D,0x30,0x0B}}, + {{0x0C,0x20,0x10},{0x0B,0x20,0x10},{0x0C,0x20,0x0A},{0x0D,0x20,0x0D}}, + {{0x0C,0x20,0x11},{0x0B,0x20,0x13},{0x0C,0x20,0x0C},{0x0D,0x20,0x0F}}, + {{0x0D,0x30,0x14},{0x0D,0x22,0x14},{0x0D,0x20,0x0D},{0x0D,0x15,0x0C}}, + {{0x0E,0x30,0x18},{0x0E,0x25,0x16},{0x0E,0x25,0x0F},{0x0E,0x18,0x0F}}, + {{0x0F,0x38,0x1A},{0x0F,0x32,0x1C},{0x0F,0x18,0x12},{0x0F,0x18,0x12}}}; + + if (ref >= 28 && ref < 40){ + row = 0; + }else if (ref >= 40 && ref < 60){ + row = 1; + }else if (ref >= 60 && ref < 90){ + row = 2; + }else if (ref >= 90 && ref < 110){ + row = 3; + }else if (ref >= 110 && ref < 140){ + row = 4; + }else if (ref >= 140 && ref < 180){ + row = 5; + }else if (ref >= 180 && ref <= 240){ + row = 6; + } + + if (vco < 8400){ + column = 0; + }else if (vco >= 8400 && vco < 10150){ + column = 1; + }else if (vco >= 10150 && vco < 12000){ + column = 2; + }else if (vco >= 12000 ){ + column = 3; + } + + char cp = coreTable[row][column][0]; + char c1r3 = coreTable[row][column][1]; + char r1 = coreTable[row][column][2]; + + char dither,nHigh,nLow,fHigh,fMiddle,fLow,outputDiv,core = 0x81; + if(vco > 10150){ + core = core + 0x10; + } + if (div == 2){ + outputDiv = 0+7; + }else if (div == 4){ + outputDiv = 32+7; + }else{ + outputDiv = 48 + divBin(div); + } + + double nf = 1.0*vco / ref; + int n = nf; + double f = nf - n; + if(f > 1e-10){ + dither = 11; + }else{ + dither = 0; + } + if(n >= 256){ + nHigh = 1; + }else{ + nHigh = 0; + } + nLow = n & 0xff; + int f1 = f * pow(2,24); + fHigh = f1>>16 & 0xff; + fMiddle = f1>>8 & 0xff; + fLow = f1 & 0xff; + reg_data[0]=core; + reg_data[1]=outputDiv; + reg_data[2]=nHigh; + reg_data[3]=nLow; + reg_data[4]=fHigh; + reg_data[5]=fMiddle; + reg_data[6]=fLow; + reg_data[7]=cp; + reg_data[8]=c1r3; + reg_data[9]=r1; + reg_data[10]=dither; + return 0; +} +char divBin(u16 div){ + + switch(div){ + case 8:return 7;break; + case 16:return 6;break; + case 32:return 5;break; + case 64:return 4;break; + case 128:return 3;break; + case 256:return 2;break; + default :return 2; + } + +} + +void configTxNcoFreq(int freq, int fs) { + u8 rx_data; + double ratio = (double) freq < 0 ? (freq + fs) / fs : freq / fs; + double bin = ratio * pow(2,48); + int bin_low = (u32) bin & 0xFFFFFF; + int bin_high = (u32)(bin / pow(2,24)) & 0xFFFFFF; + SpiPs_write_read1(0x164, (bin_high >> 16) & 0xFF,&rx_data); + SpiPs_write_read1(0x165, (bin_high >> 8) & 0xFF,&rx_data); + SpiPs_write_read1(0x166, bin_high & 0xFF,&rx_data); + SpiPs_write_read1(0x167, (bin_low >> 16) & 0xFF,&rx_data); + SpiPs_write_read1(0x168, (bin_low >> 8) & 0xFF,&rx_data); + SpiPs_write_read1(0x169, bin_low & 0xFF,&rx_data); +} +void configRxNcoFreq(int freq, int fs) { + u8 rx_data; + double ratio = (double) freq < 0 ? (freq + fs) / fs : freq / fs; + double bin = ratio * pow(2,48); + int bin_low = (u32) bin & 0xFFFFFF; + int bin_high = (u32)(bin / pow(2,24)) & 0xFFFFFF; + SpiPs_write_read1(0xA16, (bin_high >> 16) & 0xFF,&rx_data); + SpiPs_write_read1(0xA17, (bin_high >> 8) & 0xFF,&rx_data); + SpiPs_write_read1(0xA18, bin_high & 0xFF,&rx_data); + SpiPs_write_read1(0xA19, (bin_low >> 16) & 0xFF,&rx_data); + SpiPs_write_read1(0xA1A, (bin_low >> 8) & 0xFF,&rx_data); + SpiPs_write_read1(0xA1B, bin_low & 0xFF,&rx_data); +} + diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_HOP/xilinx_io.h b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_HOP/xilinx_io.h new file mode 100644 index 0000000..7fbd767 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_CX9261A_HOP/xilinx_io.h @@ -0,0 +1,153 @@ +/* + * xilinx_io.h + * + * Created on: 2021Äê9ÔÂ6ÈÕ + * Author: cxlab + */ + +#ifndef SRC_XILINX_IO_H_ +#define SRC_XILINX_IO_H_ + + + +#endif /* SRC_XILINX_IO_H_ */ +#include "xspips.h" /* SPI device driver */ +#include "xgpiops.h" +#include "xgpio.h" +#include "xaxidma.h" +#include "xparameters.h" +#include "xscugic.h" +#include "xil_exception.h" + +//#define DBGLOG +#define MAX_DATA 100 +#define SPI_WRITE 0x80 +#define SPI_READ 0x00 +#define GPIO_DIR_INPUT 0x00 +#define GPIO_DIR_OUTPUT 0x01 +#define GPIO_EMIO_OFFSET 54 + +#define TX_EN 0x08 +#define RX_EN 0x07 +#define GPIO_1 0x06 +#define GPIO_0 0x05 + +#define NRST 0 +#define ENABLE_TRX1 1 +#define ENABLE_TRX2 2 +#define ENABLE_TRX3 3 +#define TXNRX_TRX1 4 +#define TXNRX_TRX2 5 +#define TXNRX_RX3 6 + +#define aresetn_0 33 +#define rst 34 +#define tr_sel 35 +#define tdd_fdd_sel 36 +#define r1t1_r2t2_sel 37 +#define sp_dp_sel 38 +#define aresetn_1 39 +#define aresetn_2 40 +#define hop 41 +#define cx3e04_rstn 42 +#define spi_select 46 +#define debug_mode 63 + +#define INTER_SIG3 0x03//dma_axis_rx_rstn +#define INTER_SIG2 0x02//frame_pattern +#define INTER_SIG1 0x01//mode_sel_async +#define INTER_SIG0 0x00//rst_async + +#define SPI_DEVICE_ID XPAR_XSPIPS_0_DEVICE_ID +#define GPIO_DEVICE_ID XPAR_PS7_GPIO_0_DEVICE_ID + +#define AXI_DMA_DEVCIE_ID0 XPAR_AXI_DMA_0_DEVICE_ID +#define AXI_DMA_DEVCIE_ID1 XPAR_AXI_DMA_1_DEVICE_ID +#define AXI_DMA_DEVCIE_ID2 XPAR_AXI_DMA_2_DEVICE_ID + +#define BROM_BASEADDR XPAR_M08_AXI_0_BASEADDR + +#define AXI4_LITE0_SPI_BASEADDR XPAR_AXI4_LITE_SPI_0_BASEADDR +#define AXI4_LITE1_SPI_BASEADDR XPAR_AXI4_LITE_SPI_1_BASEADDR +#define BRAM_BASEADDR XPAR_AXI_BRAM_CTRL_0_S_AXI_BASEADDR +#define BRAM_BASEADDR_1 XPAR_AXI_BRAM_CTRL_1_S_AXI_BASEADDR +#define PACKER_BASEADDR0 XPAR_AXIS_ADC_DATA_PACKER_0_S00_AXI_BASEADDR +#define PACKER_BASEADDR1 XPAR_AXIS_ADC_DATA_PACKER_1_S00_AXI_BASEADDR +#define PACKER_BASEADDR2 XPAR_AXIS_ADC_DATA_PACKER_2_S00_AXI_BASEADDR +#define WAVELENGTH 8192 +#define TX_BUFFER_BASE XPAR_MIG_7SERIES_0_BASEADDR +0x2000 +#define WAVE_LENGTH 8192*4 + +#define GPIO_INT_ID XPAR_FABRIC_GPIO_0_VEC_ID //PL ¶Ë AXI GPIO ÖжÏ ID +#define AXI_GPIO_ID XPAR_AXI_GPIO_0_DEVICE_ID //PL ¶Ë AXI GPIO Æ÷¼þ ID +#define SCUGIC_ID XPAR_SCUGIC_0_DEVICE_ID //ÖжϿØÖÆÆ÷ ID + +#define KEY_MASK XGPIO_IR_CH1_MASK //ͨµÀ 1 µÄ붨Òå + +int cx3e04_write(int addr , int value); +int cx3e04_read(int addr); +int cx9261a_write(int addr , int value); +int cx9261a_read(int addr); +void cx3e04_config(void); +void cx9261a_710_config(void); + +void AXIGpioInit(void); +void ConfigAXIGPIOIntr(void); +void axi_gpio_handler(void *CallbackRef); +void XScuGicInit(void); +void ExceptionInit(void); + +int SpiPsInit(u16 SpiDeviceId); +//int SpiPs_write_read(u8 cmd, u16 addr,u8 data,u8 * rx_data); +int SpiPs_write_read(u8 * data,u8 * rx_data); +int SpiPs_write_read1(u16 addr,u8 data,u8 * rx_data); +int SpiPs_write_read2(u16 addr,u8 data,u8 * rx_data); +int GpioInit(u16 DeviceId); +int GpioSetPinDir(u32 Pin,u32 Direction); +int GpioWritePin(u32 Pin,u32 data); +int GpioReadPin(u32 Pin); +void DeviceRst(void); + +//У׼ +void cx9261a_151_config(void); +void cx9261a_076_config(void); +void rxFFTCalib(int lo, int fs,int ref, int firLength,int chan); +void configTxNcoFreq(int freq, int fs); +void configRxNcoFreq(int freq, int fs); +void configDcCalib(int dcCalibEnable,int dcCalibLength); +void txBisectionQecCalib(int f0, int fs); +void txBisectionDcCalib(int f0, int fs); + +extern XAxiDma* xAxiDma0Get(void); +extern XAxiDma* xAxiDma1Get(void); +extern XAxiDma* xAxiDma2Get(void); +int XAxiDma_Init(XAxiDma* AxiDma,u16 DeviceId); +int XAxiDmaCapture(XAxiDma* AxiDma,u32 data_length); +int XAxiDmaCapture2(XAxiDma* AxiDma,u32 data_length); + +int DownloadWave(u8 * data); +int SetPacketSize(XAxiDma* AxiDma,u32 length); +void dbg_printf( const char8 *ctrl1, ...); +void PackerRst(void); +int peripheral_test(void); + +#define SPI_STACK_LENGTH 65536 +struct spi_stack { + int spi_write_num; + u8 recv_buf[SPI_STACK_LENGTH*3]; +}; +int spi_stack_in(u8 * data,struct spi_stack * spistack); + +void spi_stack_out(struct spi_stack * spistack); + +int rom_read(u8 * data); +void download_bin(void); +//ÌøƵ +void frqhop_config(int hop_flag); +void frqhop_flag(int frqhop_flag); +int PLL_config(u8 pll_index,double pll_frq); +void trx_ch_pll_config(u8 pll_index); +int pll_frq_caculation(double ref,double pll_frq,u8 *reg_data); +int pll_frq_caculation_new(double ref,double pll_frq,u8 *reg_data); +void PLL_afc(u16 afc_addr,u16 div_addr,u8 pll_div); +char divBin(u16 div); diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_1_9_0/cx9261adriver.cpp b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_1_9_0/cx9261adriver.cpp new file mode 100644 index 0000000..c6b7dac --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_1_9_0/cx9261adriver.cpp @@ -0,0 +1,2188 @@ +// ReSharper disable CppCompileTimeConstantCanBeReplacedWithBooleanConstant +// ReSharper disable CppUseRangeAlgorithm +// ReSharper disable CppUseStructuredBinding +// ReSharper disable CppTooWideScopeInitStatement +#include "cx9261adriver.h" +#include "utils.h" + + +namespace CX9261A { + +void logging(const std::string& msg){ + return; +} + +void writeSpi(int address, int value){ + return; +} + +int readSpi(int address){ + return 0; +} + +void pause(double ms){ + return; +} + +void setPin(int pin, int value){ + return; +} + +void initialChip() +{ + LOGGING("初始化寄存器配置"); + writeSpi(0x000, 0x02); + writeSpi(0x11F, 0x33); + writeSpi(0x773, 0x53); + writeSpi(0x774, 0x86); + writeSpi(0x781, 0x6F); + writeSpi(0x6C3, 0x00); + initialBBPLL(); + initialPLL1(); + initialPLL2(); + initialPLL3(); + initialPLL4(); + initialPLL5(); + initialRxChannel(RxChannel::Rx1); + initialRxChannel(RxChannel::Rx2); + initialRxChannel(RxChannel::Rx3); + initialTxChannel(TxChannel::Tx1); + initialTxChannel(TxChannel::Tx2); +} + +void initialPowerConfig(const CX9261AConfiguration& config) +{ + // 断电模式 + LOGGING("断电模式"); + writeSpi(0x031, 0x00); + writeSpi(0x032, 0x7F); + writeSpi(0x033, 0xFF); + writeSpi(0x034, 0xFF); + // 休眠模式 + LOGGING("休眠模式"); + writeSpi(0x035, 0x00); + writeSpi(0x036, config.pllSource.rxUseExt || config.pllSource.txUseExt ? 0x3C : 0x3D); + const bool usePll4 = !config.pllSource.txUseExt + && (config.pllSource.tx1Source == LoSource::Pll4 || config.pllSource.tx2Source == LoSource::Pll4); + const bool usePll5 = config.pllSource.rx3Source == LoSource::Pll5; + Register reg037(0xFF); + reg037[2] = !usePll5; + reg037[0] = !usePll4; + writeSpi(0x037, reg037); + const bool usePll3 = !config.pllSource.txUseExt + && (config.pllSource.tx1Source == LoSource::Pll3 || config.pllSource.tx2Source == LoSource::Pll3); + const bool usePll2 = !config.pllSource.rxUseExt + && (config.pllSource.rx1Source == LoSource::Pll2 || config.pllSource.rx2Source == LoSource::Pll2); + const bool usePll1 = !config.pllSource.rxUseExt + && (config.pllSource.rx1Source == LoSource::Pll1 || config.pllSource.rx2Source == LoSource::Pll1); + Register reg038(0xFF); + reg038[6] = !usePll3; + reg038[4] = !usePll2; + reg038[2] = !usePll1; + writeSpi(0x038, reg038); + // 警戒模式 + LOGGING("警戒模式"); + writeSpi(0x039, 0x00); + writeSpi(0x03A, config.pllSource.rxUseExt || config.pllSource.txUseExt ? 0x3C : 0x3D); + Register reg03B(0xFF); + reg03B[2] = !usePll5; + reg03B[1] = !usePll5; + reg03B[0] = !usePll4; + writeSpi(0x03B, reg03B); + Register reg03C(0xFE); + reg03C[7] = !usePll4; + reg03C[6] = !usePll3; + reg03C[5] = !usePll3; + reg03C[4] = !usePll2; + reg03C[3] = !usePll2; + reg03C[2] = !usePll1; + reg03C[1] = !usePll1; + writeSpi(0x03C, reg03C); + // 校准模式 + LOGGING("校准模式"); + Register reg03D(0x00); + reg03D[4] = config.calib.tx2CalibPll || config.calib.rx3CalibPll || config.calib.rx2CalibPll; + reg03D[3] = config.calib.tx1CalibPll || config.calib.rx1CalibPll; + reg03D[2] = config.calib.rx3CalibPll; + reg03D[1] = config.calib.tx2CalibPll || config.calib.rx2CalibPll; + reg03D[0] = config.calib.tx1CalibPll || config.calib.rx1CalibPll; + writeSpi(0x03D, reg03D); + writeSpi(0x03E, config.pllSource.rxUseExt || config.pllSource.txUseExt ? 0x38 : 0x39); + Register reg03F(0xFF); + reg03F[7] = !(config.calib.tx2CalibPll || config.calib.rx3CalibPll || config.calib.rx2CalibPll); + reg03F[6] = !(config.calib.tx1CalibPll || config.calib.rx1CalibPll); + reg03F[5] = !(config.calib.rx3CalibPll); + reg03F[4] = !(config.calib.tx2CalibPll || config.calib.rx2CalibPll); + reg03F[3] = !(config.calib.tx1CalibPll || config.calib.rx1CalibPll); + reg03F[2] = !usePll5; + reg03F[1] = !usePll5; + reg03F[0] = !(usePll4 || config.calib.rx3CalibPll || config.calib.rx2CalibPll || config.calib.rx1CalibPll); + writeSpi(0x03F, reg03F); + Register reg040(0xFE); + reg040[7] = !(usePll4 || config.calib.rx3CalibPll || config.calib.rx2CalibPll || config.calib.rx1CalibPll); + reg040[6] = !usePll3; + reg040[5] = !usePll3; + reg040[4] = !usePll2; + reg040[3] = !usePll2; + reg040[2] = !usePll1; + reg040[1] = !usePll1; + writeSpi(0x040, reg040); + // 接收模式 + LOGGING("接收模式"); + Register reg041(0x00); + reg041[2] = config.pllSource.rx3Source != LoSource::Off; + reg041[1] = config.pllSource.rxUseExt || config.pllSource.rx2Source != LoSource::Off; + reg041[0] = config.pllSource.rxUseExt || config.pllSource.rx1Source != LoSource::Off; + writeSpi(0x041, reg041); + writeSpi(0x042, config.pllSource.rxUseExt ? 0x3C : 0x3D); + Register reg043(0xFF); + reg043[5] = !reg041[2]; + reg043[4] = !reg041[1]; + reg043[3] = !reg041[0]; + reg043[2] = config.pllSource.rx3Source == LoSource::Off; + reg043[1] = config.pllSource.rx3Source == LoSource::Off; + writeSpi(0x043, reg043); + Register reg044(0xFE); + reg044[4] = !usePll2; + reg044[3] = !usePll2; + reg044[2] = !usePll1; + reg044[1] = !usePll1; + writeSpi(0x044, reg044); + // 发射模式 + LOGGING("发射模式"); + Register reg045(0x00); + reg045[4] = config.pllSource.txUseExt || config.pllSource.tx2Source != LoSource::Off; + reg045[3] = config.pllSource.txUseExt || config.pllSource.tx1Source != LoSource::Off; + writeSpi(0x045, reg045); + writeSpi(0x046, config.pllSource.txUseExt ? 0x3C : 0x3D); + Register reg047(0xFF); + reg047[7] = !reg045[4]; + reg047[6] = !reg045[3]; + reg047[0] = !usePll4; + writeSpi(0x047, reg047); + Register reg048(0xFE); + reg048[7] = !usePll4; + reg048[6] = !usePll3; + reg048[5] = !usePll3; + reg048[4] = !usePll2; + reg048[3] = !usePll2; + reg048[2] = !usePll1; + reg048[1] = !usePll1; + writeSpi(0x048, reg048); + // FDD模式 + LOGGING("FDD模式"); + Register reg049(0x00); + reg049[4] = config.pllSource.txUseExt || config.pllSource.tx2Source != LoSource::Off; + reg049[3] = config.pllSource.txUseExt || config.pllSource.tx1Source != LoSource::Off; + reg049[2] = config.pllSource.rx3Source == LoSource::Off; + reg049[1] = config.pllSource.rxUseExt || config.pllSource.rx2Source != LoSource::Off; + reg049[0] = config.pllSource.rxUseExt || config.pllSource.rx1Source != LoSource::Off; + writeSpi(0x049, reg049); + writeSpi(0x04A, config.pllSource.txUseExt || config.pllSource.rxUseExt ? 0x3C : 0x3D); + Register reg04B(0xFF); + reg04B[7] = !reg049[4]; + reg04B[6] = !reg049[3]; + reg04B[5] = !reg049[2]; + reg04B[4] = !reg049[1]; + reg04B[3] = !reg049[0]; + reg04B[2] = !usePll5; + reg04B[1] = !usePll5; + reg04B[0] = !usePll4; + writeSpi(0x04B, reg04B); + Register reg04C(0xFE); + reg04C[7] = !usePll4; + reg04C[6] = !usePll3; + reg04C[5] = !usePll3; + reg04C[4] = !usePll2; + reg04C[3] = !usePll2; + reg04C[2] = !usePll1; + reg04C[1] = !usePll1; + writeSpi(0x04C, reg04C); + // 观测模式 + LOGGING("观测模式"); + writeSpi(0x04D, 0x04); + writeSpi(0x04E, 0x3D); + writeSpi(0x04F, 0xD9); + writeSpi(0x050, 0xFE); +} + +void initialBBPLL() +{ + LOGGING("初始化BBPLL"); + writeSpi(0x70B, 0x0E); + writeSpi(0x727, 0x0E); + writeSpi(0x743, 0x0E); +} + +void initialPLL1() +{ + LOGGING("初始化PLL1"); + writeSpi(0x624, 0x00); + writeSpi(0x625, 0x11); + writeSpi(0x626, 0x02); + writeSpi(0x61E, 0x30); + writeSpi(0x61F, 0x08); + writeSpi(0x627, 0x10); +} + +void initialPLL2() +{ + LOGGING("初始化PLL2"); + writeSpi(0x646, 0x00); + writeSpi(0x647, 0x11); + writeSpi(0x648, 0x02); + writeSpi(0x640, 0x30); + writeSpi(0x641, 0x08); + writeSpi(0x649, 0x10); +} + +void initialPLL3() +{ + LOGGING("初始化PLL3"); + writeSpi(0x668, 0x00); + writeSpi(0x669, 0x11); + writeSpi(0x66A, 0x02); + writeSpi(0x662, 0x30); + writeSpi(0x663, 0x08); + writeSpi(0x66B, 0x10); +} + +void initialPLL4() +{ + LOGGING("初始化PLL4"); + writeSpi(0x68A, 0x00); + writeSpi(0x68B, 0x11); + writeSpi(0x68C, 0x02); + writeSpi(0x684, 0x30); + writeSpi(0x685, 0x08); + writeSpi(0x68D, 0x10); +} + +void initialPLL5() +{ + LOGGING("初始化PLL5"); + writeSpi(0x6AC, 0x00); + writeSpi(0x6AD, 0x11); + writeSpi(0x6AE, 0x02); + writeSpi(0x6A6, 0x30); + writeSpi(0x6A7, 0x08); + writeSpi(0x6AF, 0x10); +} + +void configRef(const double ref) +{ + LOGGING("初始化参考时钟"); + // PLL1 + writeSpi(0x621, ref <= 100 ? 0x41 : 0x49); + writeSpi(0x622, ref <= 100 ? 0x00 : ref > 150 ? 0x3F : 0x15); + // PLL2 + writeSpi(0x643, ref <= 100 ? 0x41 : 0x49); + writeSpi(0x644, ref <= 100 ? 0x00 : ref > 150 ? 0x3F : 0x15); + // PLL3 + writeSpi(0x665, ref <= 100 ? 0x41 : 0x49); + writeSpi(0x666, ref <= 100 ? 0x00 : ref > 150 ? 0x3F : 0x15); + // PLL4 + writeSpi(0x687, ref <= 100 ? 0x41 : 0x49); + writeSpi(0x688, ref <= 100 ? 0x00 : ref > 150 ? 0x3F : 0x15); + // PLL5 + writeSpi(0x6A9, ref <= 100 ? 0x41 : 0x49); + writeSpi(0x6AA, ref <= 100 ? 0x00 : ref > 150 ? 0x3F : 0x15); +} + +void configBBPLL(const CX9261AConfiguration& config) +{ + LOGGING("配置BBPLL"); + const auto& clock = config.clock; + configRefDoubler(clock.refDoubler, clock.ref); + // fclk div + const int fclkDiv = clock.adc > 64 ? 4 : 5; + Register r0C0{ 0x50 }; + r0C0[1] = fclkDiv != 5; + writeSpi(0x0C0, r0C0); + writeSpi(0x0C1, r0C0); + writeSpi(0x0C2, r0C0); + // clock + double bblo = clock.adc * fclkDiv * 4; + int bbloDiv = 1; + while (bblo <= 1350 && bbloDiv < 8) { + bblo *= 2; + bbloDiv *= 2; + } + Register r602; + r602.replace(1, 0, static_cast(std::log2(bbloDiv))); + r602[5] = fclkDiv == 5; + // ref div + Register r601{ 0x0F }; + r601.replace(1, 0, clock.refDiv == 2 ? 0b00 : clock.refDiv == 4 ? 0b01 : clock.refDiv == 8 ? 0b10 : 0b11); + writeSpi(0x601, r601); + // nf + const auto nf = bblo * clock.refDiv / (clock.ref * (clock.refDoubler ? 2 : 1)); + int n = floor(nf); + const auto f = nf - n; + r602[6] = clock.bbUseIntDiv; + writeSpi(0x602, r602); + // 整数模式 + if (clock.bbUseIntDiv) + n = round(2.0 * n / bbloDiv + 1); + const int fBin = round(std::pow(2, 25) * f); + Register r60D{ 0x0C }; + r60D[0] = f >= 0.5; + r60D[4] = clock.bbUseIntDiv; + const Register r60E = fBin >> 16 & 0xFF; + const Register r60F = fBin >> 8 & 0xFF; + const Register r610 = fBin & 0xFF; + writeSpi(0x60D, r60D); + writeSpi(0x60E, r60E); + writeSpi(0x60F, r60F); + writeSpi(0x610, r610); + writeSpi(0x611, n); + // Dither + Register r612; + r612[4] = clock.bbUseIntDiv; + writeSpi(0x612, r612); + // ADC + const auto adcClock = clock.adc * fclkDiv * 4; + Register r70E{ 0x6B }; + Register r70F{ 0xE0 }; + double adjAdc; + if (adcClock < 450) { + r70E.replace(6, 5, 0b00); + r70E.replace(4, 0, 0b00010); + r70F.replace(7, 6, 0b00); + adjAdc = 300; + } else if (adcClock < 750) { + r70E.replace(6, 5, 0b01); + r70E.replace(4, 0, 0b00101); + r70F.replace(7, 6, 0b01); + adjAdc = 600; + } else if (adcClock < 1050) { + r70E.replace(6, 5, 0b10); + r70E.replace(4, 0, 0b01000); + r70F.replace(7, 6, 0b10); + adjAdc = 900; + } else { + r70E.replace(6, 5, 0b11); + r70E.replace(4, 0, 0b01011); + r70F.replace(7, 6, 0b11); + adjAdc = 1200; + } + writeSpi(0x70E, r70E); + writeSpi(0x72A, r70E); + writeSpi(0x746, r70E); + writeSpi(0x70F, r70F); + writeSpi(0x72B, r70F); + writeSpi(0x747, r70F); + auto c = 8600 * adjAdc / adcClock; + c = (c - 3000) / 80; + const Register r70D = round(c); + writeSpi(0x70D, r70D); + writeSpi(0x729, r70D); + writeSpi(0x745, r70D); + // 时序配置 + if (config.interface.ioMode != IOMode::CMOS) { + writeSpi(0x782, 0x00); + writeSpi(0x783, 0x00); + } else if (clock.adc <= 60) { + writeSpi(0x782, 0x01); + writeSpi(0x783, 0x01); + } else { + writeSpi(0x782, 0x76); + writeSpi(0x783, 0x76); + } + writeSpi(0x784, clock.adc <= 51 ? 0x01 : 0x06); +} + +bool afcBBPll() +{ + LOGGING("BBPLL AFC"); + writeSpi(0x600, 0x00); + writeSpi(0x600, 0x11); + pause(delay); + return readSpi(0x615) & 0b00100000; +} + +std::vector configPllImpl(const double lo, const double ref) +{ + auto vco = lo; + auto div = 1; + while (vco <= 6700 && div < 256) { + vco *= 2; + div *= 2; + } + int row{}; + if (ref >= 28 && ref < 40) + row = 0; + if (ref >= 40 && ref < 60) + row = 1; + if (ref >= 60 && ref < 90) + row = 2; + if (ref >= 90 && ref < 110) + row = 3; + if (ref >= 110 && ref < 140) + row = 4; + if (ref >= 140 && ref < 180) + row = 5; + if (ref >= 180 && ref <= 240) + row = 6; + int column{}; + if (vco < 8400) + column = 0; + if (vco >= 8400 && vco < 10150) + column = 1; + if (vco >= 10150 && vco < 12000) + column = 2; + if (vco >= 12000) + column = 3; + + std::vector ret(11); + const Register core = vco > 10150 ? 0x91 : 0x81; + ret[0] = core; + const Register cp{ coreTable[row][column][0] }; + ret[7] = cp; + const Register c1r3{ coreTable[row][column][1] }; + ret[8] = c1r3; + const Register r1{ coreTable[row][column][2] }; + ret[9] = r1; + const Register outputDiv = [div]() { + switch (div) { + case 2: + return 0x07; + case 4: + return 0x27; + case 8: + return 0x37; + case 16: + return 0x36; + case 32: + return 0x35; + case 64: + return 0x34; + case 128: + return 0x33; + case 256: + return 0x32; + default: + return 0; + } + }(); + ret[1] = outputDiv; + const auto nf = static_cast(std::round(vco / ref * 1e9)) / 1.0e9; + const auto n = floor(nf); + const auto f = nf - n; + const Register nHigh = n >= 256; + ret[2] = nHigh; + const Register nLow = n & 0xFF; + ret[3] = nLow; + const int fint = round(std::pow(2, 24) * f); + ret[4] = fint >> 16 & 0xFF; + ret[5] = fint >> 8 & 0xFF; + ret[6] = fint & 0xFF; + const Register dither = f < 1e-10 ? 0x00 : 0x0B; + ret[10] = dither; + return ret; +} + +void configPll1(const double lo, const Clock& clock) +{ + LOGGING("配置PLL1"); + const auto pllMap = configPllImpl(lo, clock.ref * (clock.refDoubler ? 2 : 1)); + writeSpi(0x620, pllMap[0]); + writeSpi(0x61D, pllMap[1]); + writeSpi(0xB06, pllMap[2]); + writeSpi(0xB07, pllMap[3]); + writeSpi(0xB08, pllMap[4]); + writeSpi(0xB09, pllMap[5]); + writeSpi(0xB0A, pllMap[6]); + writeSpi(0x61A, pllMap[7]); + writeSpi(0x61B, pllMap[8]); + writeSpi(0x61C, pllMap[9]); + writeSpi(0x62A, pllMap[10]); +} + +bool afcPll1() +{ + LOGGING("PLL1 AFC"); + Register r61D = readSpi(0x61D); + const auto saved = r61D; + r61D.replace(5, 4, 0b10); + writeSpi(0x61D, r61D); + writeSpi(0x617, 0x00); + writeSpi(0x617, 0x13); + pause(delay); + writeSpi(0x61D, saved); + const auto lock = readSpi(0x635); + return 0x10 & lock; +} + +void configPll2(const double lo, const Clock& clock) +{ + LOGGING("配置PLL2"); + const auto pllMap = configPllImpl(lo, clock.ref * (clock.refDoubler ? 2 : 1)); + writeSpi(0x642, pllMap[0]); + writeSpi(0x63F, pllMap[1]); + writeSpi(0xB14, pllMap[2]); + writeSpi(0xB15, pllMap[3]); + writeSpi(0xB16, pllMap[4]); + writeSpi(0xB17, pllMap[5]); + writeSpi(0xB18, pllMap[6]); + writeSpi(0x63C, pllMap[7]); + writeSpi(0x63D, pllMap[8]); + writeSpi(0x63E, pllMap[9]); + writeSpi(0x64C, pllMap[10]); +} + +bool afcPll2() +{ + LOGGING("PLL2 AFC"); + Register r63F = readSpi(0x63F); + const auto saved = r63F; + r63F.replace(5, 4, 0b10); + writeSpi(0x63F, r63F); + writeSpi(0x639, 0x00); + writeSpi(0x639, 0x13); + pause(delay); + writeSpi(0x63F, saved); + const auto lock = readSpi(0x657); + return 0x10 & lock; +} + +void configPll3(const double lo, const Clock& clock) +{ + LOGGING("配置PLL3"); + const auto pllMap = configPllImpl(lo, clock.ref * (clock.refDoubler ? 2 : 1)); + writeSpi(0x664, pllMap[0]); + writeSpi(0x661, pllMap[1]); + writeSpi(0xB22, pllMap[2]); + writeSpi(0xB23, pllMap[3]); + writeSpi(0xB24, pllMap[4]); + writeSpi(0xB25, pllMap[5]); + writeSpi(0xB26, pllMap[6]); + writeSpi(0x65E, pllMap[7]); + writeSpi(0x65F, pllMap[8]); + writeSpi(0x660, pllMap[9]); + writeSpi(0x66E, pllMap[10]); +} + +bool afcPll3() +{ + LOGGING("PLL3 AFC"); + Register r661 = readSpi(0x661); + const auto saved = r661; + r661.replace(5, 4, 0b10); + writeSpi(0x661, r661); + writeSpi(0x65B, 0x00); + writeSpi(0x65B, 0x13); + pause(delay); + writeSpi(0x661, saved); + const auto lock = readSpi(0x679); + return 0x10 & lock; +} + +void configPll4(const double lo, const Clock& clock) +{ + LOGGING("配置PLL4"); + const auto pllMap = configPllImpl(lo, clock.ref * (clock.refDoubler ? 2 : 1)); + writeSpi(0x686, pllMap[0]); + writeSpi(0x683, pllMap[1]); + writeSpi(0xB30, pllMap[2]); + writeSpi(0xB31, pllMap[3]); + writeSpi(0xB32, pllMap[4]); + writeSpi(0xB33, pllMap[5]); + writeSpi(0xB34, pllMap[6]); + writeSpi(0x680, pllMap[7]); + writeSpi(0x681, pllMap[8]); + writeSpi(0x682, pllMap[9]); + writeSpi(0x690, pllMap[10]); +} + +bool afcPll4() +{ + LOGGING("PLL4 AFC"); + Register r683 = readSpi(0x683); + const auto saved = r683; + r683.replace(5, 4, 0b10); + writeSpi(0x683, r683); + writeSpi(0x67D, 0x00); + writeSpi(0x67D, 0x13); + pause(delay); + writeSpi(0x683, saved); + const auto lock = readSpi(0x69B); + return 0x10 & lock; +} + +void configPll5(const double lo, const Clock& clock) +{ + LOGGING("配置PLL5"); + const auto pllMap = configPllImpl(lo, clock.ref * (clock.refDoubler ? 2 : 1)); + writeSpi(0x6A8, pllMap[0]); + writeSpi(0x6A5, pllMap[1]); + writeSpi(0xB3E, pllMap[2]); + writeSpi(0xB3F, pllMap[3]); + writeSpi(0xB40, pllMap[4]); + writeSpi(0xB41, pllMap[5]); + writeSpi(0xB42, pllMap[6]); + writeSpi(0x6A2, pllMap[7]); + writeSpi(0x6A3, pllMap[8]); + writeSpi(0x6A4, pllMap[9]); + writeSpi(0x6B2, pllMap[10]); +} + +bool afcPll5() +{ + LOGGING("PLL5 AFC"); + Register r6A5 = readSpi(0x6A5); + const auto saved = r6A5; + r6A5.replace(5, 4, 0b10); + writeSpi(0x6A5, r6A5); + writeSpi(0x69F, 0x00); + writeSpi(0x69F, 0x13); + pause(delay); + writeSpi(0x6A5, saved); + const auto lock = readSpi(0x6BD); + return 0x10 & lock; +} + +void configAGCMode(const int mode) +{ + LOGGING("配置AGC模式"); + writeSpi(0x900, mode == 0 ? 0x00 : 0x11); + writeSpi(0x901, mode == 3 || mode == 4 ? mode + 0x80 : mode); +} + +void configAGCPDT(const AGCPDT& pdt) +{ + LOGGING("配置AGC PDT"); + writeSpi(0x908, (pdt.pdtN << 4) + pdt.pdtM); + writeSpi(0x909, pdt.pdtN < 3 && pdt.pdtM < 4 ? 0x00 : 0x03); + writeSpi(0x90A, pdt.pdtN < 3 && pdt.pdtM < 4 ? 0x02 : 0x32); +} + +void configAGCLMT(const AGCLMT& lmt) +{ + LOGGING("配置AGC LMT"); + writeSpi(0x90D, lmt.count >> 8); + writeSpi(0x90E, lmt.count & 0xFF); + writeSpi(0x90F, (lmt.threshold1 << 4) + lmt.threshold2); + writeSpi(0x910, (lmt.threshold3 << 4) + lmt.threshold4); +} + +void configAGCDIG(const AGCDIG& dig) +{ + LOGGING("配置AGC DIG"); + writeSpi(0x911, dig.count >> 8); + writeSpi(0x912, dig.count & 0xFF); + writeSpi(0x913, dig.threshold1 + 60); + writeSpi(0x914, dig.threshold2 + 60); + writeSpi(0x915, dig.threshold3 + 60); + writeSpi(0x916, dig.threshold4 + 60); +} + +void configAGC(const AGC& agc) +{ + LOGGING("配置AGC"); + writeSpi(0x903, 0x11); + configAGCMode(agc.mode); + configAGCPDT(agc.pdt); + configAGCLMT(agc.lmt); + configAGCDIG(agc.dig); +} + +void configRISCV(const bool on) +{ + LOGGING("配置处理器"); + if (on) { + writeSpi(0x071, 0x00); + writeSpi(0x071, 0x29); + writeSpi(0x236, 0x0F); + writeSpi(0x20A, 0x01); + writeSpi(0x071, 0x26); + } else { + writeSpi(0x071, 0x00); + } +} + +void configTemperatureCompensation(const TemperatureComp mode) +{ + LOGGING("配置温补"); + // BBPLL + writeSpi(0x613, 0x9F); + writeSpi(0x614, mode == TemperatureComp::Band ? 0xB4 : 0xA4); + Register r6C3 = readSpi(0x6C3); + r6C3[4] = true; + writeSpi(0x6C3, r6C3); + // PLL1 + writeSpi(0x632, 0x9F); + writeSpi(0x633, mode == TemperatureComp::Band ? 0x1C : 0x14); + // PLL2 + writeSpi(0x654, 0x9F); + writeSpi(0x655, mode == TemperatureComp::Band ? 0x1C : 0x14); + // PLL3 + writeSpi(0x676, 0x9F); + writeSpi(0x677, mode == TemperatureComp::Band ? 0x1C : 0x14); + // PLL4 + writeSpi(0x698, 0x9F); + writeSpi(0x699, mode == TemperatureComp::Band ? 0x1C : 0x14); + // PLL5 + writeSpi(0x6BA, 0x9F); + writeSpi(0x6BB, mode == TemperatureComp::Band ? 0x1C : 0x14); +} + +void configADCCalib(const double adc) +{ + LOGGING("配置ADC校准"); + writeSpi(0x70B, 0x1E); + writeSpi(0x727, 0x1E); + writeSpi(0x743, 0x1E); + const auto adcClk = adc <= 64 ? adc * 20 : adc * 16; + if (adcClk < 450) { + writeSpi(0x70F, 0x08); + writeSpi(0x710, 0x23); + writeSpi(0x711, 0x10); + + writeSpi(0x72B, 0x08); + writeSpi(0x72C, 0x23); + writeSpi(0x72D, 0x10); + + writeSpi(0x747, 0x08); + writeSpi(0x748, 0x23); + writeSpi(0x749, 0x10); + } else if (adcClk < 750) { + writeSpi(0x70F, 0x50); + writeSpi(0x710, 0x43); + writeSpi(0x711, 0x30); + + writeSpi(0x72B, 0x50); + writeSpi(0x72C, 0x43); + writeSpi(0x72D, 0x30); + + writeSpi(0x747, 0x50); + writeSpi(0x748, 0x43); + writeSpi(0x749, 0x30); + } else if (adcClk < 1050) { + writeSpi(0x70F, 0xA0); + writeSpi(0x710, 0x83); + writeSpi(0x711, 0xF0); + + writeSpi(0x72B, 0xA0); + writeSpi(0x72C, 0x83); + writeSpi(0x72D, 0xF0); + + writeSpi(0x747, 0xA0); + writeSpi(0x748, 0x83); + writeSpi(0x749, 0xF0); + } else { + writeSpi(0x70F, 0xE0); + writeSpi(0x710, 0x83); + writeSpi(0x711, 0xF0); + + writeSpi(0x72B, 0xE0); + writeSpi(0x72C, 0x83); + writeSpi(0x72D, 0xF0); + + writeSpi(0x747, 0xE0); + writeSpi(0x748, 0x83); + writeSpi(0x749, 0xF0); + } + writeSpi(0x713, 0x80); + writeSpi(0x72F, 0x80); + writeSpi(0x74B, 0x80); + writeSpi(0x70B, 0x9E); + writeSpi(0x727, 0x9E); + writeSpi(0x743, 0x9E); + writeSpi(0x70B, 0x9A); + writeSpi(0x727, 0x9A); + writeSpi(0x743, 0x9A); + writeSpi(0x70B, 0x9E); + writeSpi(0x727, 0x9E); + writeSpi(0x743, 0x9E); + pause(delay); + writeSpi(0x70B, 0x1E); + writeSpi(0x727, 0x1E); + writeSpi(0x743, 0x1E); + writeSpi(0x713, 0xC0); + writeSpi(0x72F, 0xC0); + writeSpi(0x74B, 0xC0); +} + +void configFlashCalib() +{ + LOGGING("配置Flash校准"); + writeSpi(0x70B, 0x1E); + writeSpi(0x727, 0x1E); + writeSpi(0x743, 0x1E); + writeSpi(0x715, 0x80); + writeSpi(0x731, 0x80); + writeSpi(0x74D, 0x80); + writeSpi(0x715, 0xC0); + writeSpi(0x731, 0xC0); + writeSpi(0x74D, 0xC0); + writeSpi(0x716, 0x40); + writeSpi(0x732, 0x40); + writeSpi(0x74E, 0x40); + writeSpi(0x70B, 0x16); + writeSpi(0x727, 0x16); + writeSpi(0x743, 0x16); + pause(delay); + writeSpi(0x70B, 0x1E); + writeSpi(0x727, 0x1E); + writeSpi(0x743, 0x1E); + writeSpi(0x715, 0x80); + writeSpi(0x731, 0x80); + writeSpi(0x74D, 0x80); + writeSpi(0x716, 0x00); + writeSpi(0x732, 0x00); + writeSpi(0x74E, 0x00); +} + +std::map beforeQecState() +{ + std::map state; + // SPI模式 + state[0x000] = 0x02; + // 电源模式 + state[0x02E] = readSpi(0x02E); + // DC Tracking + state[0x109] = readSpi(0x109); + state[0x10A] = readSpi(0x10A); + state[0x11F] = readSpi(0x11F); + // RX NCO + state[0xA07] = readSpi(0xA07); + state[0xA08] = readSpi(0xA08); + state[0xA16] = readSpi(0xA16); + state[0xA17] = readSpi(0xA17); + state[0xA18] = readSpi(0xA18); + state[0xA19] = readSpi(0xA19); + state[0xA1A] = readSpi(0xA1A); + state[0xA1B] = readSpi(0xA1B); + // TX NCO + state[0x11B] = readSpi(0x11B); + state[0x11E] = readSpi(0x11E); + state[0x128] = readSpi(0x128); + state[0x161] = readSpi(0x161); + state[0x162] = readSpi(0x162); + state[0x164] = readSpi(0x164); + state[0x165] = readSpi(0x165); + state[0x166] = readSpi(0x166); + state[0x167] = readSpi(0x167); + state[0x168] = readSpi(0x168); + state[0x169] = readSpi(0x169); + // PLL Source + state[0x775] = readSpi(0x775); + state[0x77D] = readSpi(0x77D); + state[0x6C3] = readSpi(0x6C3); + return state; +} + +void restoreQecState(const std::map& state) +{ + LOGGING("恢复校准前寄存器配置"); + for (const auto i : state) { + writeSpi(i.first, i.second); + } +} + +void preparePowerForRxCalib(const PllSource& pllSource) +{ + LOGGING("为Rx校准配置电源管理"); + writeSpi(0x02E, 0x03); + Register r03F = readSpi(0x03F); + r03F[2] = pllSource.rx3Source != LoSource::Pll5; + r03F[1] = pllSource.rx3Source != LoSource::Pll5; + r03F[0] = 0; + Register r040 = readSpi(0x040); + r040[7] = 0; + r040[6] = 1; + r040[5] = 1; + r040[4] = !(pllSource.rx1Source == LoSource::Pll2 || pllSource.rx2Source == LoSource::Pll2); + r040[3] = !(pllSource.rx1Source == LoSource::Pll2 || pllSource.rx2Source == LoSource::Pll2); + r040[2] = !(pllSource.rx1Source == LoSource::Pll1 || pllSource.rx2Source == LoSource::Pll1); + r040[1] = !(pllSource.rx1Source == LoSource::Pll1 || pllSource.rx2Source == LoSource::Pll1); + writeSpi(0x03F, r03F); + writeSpi(0x040, r040); +} + +void preparePllForRxCalib(const CX9261AConfiguration& config, const RxChannel chan) +{ + LOGGING("为" + toString(chan) + "校准配置PLL"); + auto pllSource = config.pllSource; + if (chan == RxChannel::Rx1) { + pllSource.rx2Source = LoSource::Off; + pllSource.tx1Source = LoSource::Pll4; + pllSource.tx2Source = LoSource::Off; + pllSource.txUseExt = false; + configPllSource(pllSource); + const auto rx1Freq = config.pllSource.rxUseExt ? config.pllFreq.rxExtFreq + : config.pllSource.rx1Source == LoSource::Pll1 ? config.pllFreq.pll1Freq + : config.pllFreq.pll2Freq; + if (config.pllSource.rx1Source == LoSource::Pll1) + afcPll1(); + if (config.pllSource.rx1Source == LoSource::Pll2) + afcPll2(); + configPll4(rx1Freq >= 3500 ? (rx1Freq + config.calib.f0) / 3 : (rx1Freq + config.calib.f0), config.clock); + } + if (chan == RxChannel::Rx2) { + pllSource.rx1Source = LoSource::Off; + pllSource.tx1Source = LoSource::Off; + pllSource.tx2Source = LoSource::Pll4; + pllSource.txUseExt = false; + configPllSource(pllSource); + const auto rx2Freq = config.pllSource.rxUseExt ? config.pllFreq.rxExtFreq + : config.pllSource.rx2Source == LoSource::Pll1 ? config.pllFreq.pll1Freq + : config.pllFreq.pll2Freq; + if (config.pllSource.rx2Source == LoSource::Pll1) + afcPll1(); + if (config.pllSource.rx2Source == LoSource::Pll2) + afcPll2(); + configPll4(rx2Freq >= 3500 ? (rx2Freq + config.calib.f0) / 3 : (rx2Freq + config.calib.f0), config.clock); + } + if (chan == RxChannel::Rx3) { + pllSource.tx1Source = LoSource::Off; + pllSource.tx2Source = LoSource::Pll4; + pllSource.txUseExt = false; + configPllSource(pllSource); + afcPll5(); + configPll4(config.pllFreq.pll5Freq >= 3500 ? (config.pllFreq.pll5Freq + config.calib.f0) / 3 + : (config.pllFreq.pll5Freq + config.calib.f0), + config.clock); + } + afcPll4(); +} + +bool waitRxTSTFinished() +{ + LOGGING("等待Rx时域校准结束"); + int cnt = 0; + pause(qecDelay); + while (cnt <= 10) { + if ((readSpi(0x14D) & 16) == 16) + return true; + cnt++; + pause(100); + } + return false; +} + +void rxTSTCalib(const RxChannel chan) +{ + LOGGING(toString(chan) + "时域校准"); + writeSpi(0x000, chan == RxChannel::Rx1 ? 0x12 : chan == RxChannel::Rx2 ? 0x22 : 0x32); + writeSpi(0x109, 0x00); + writeSpi(0x77E, chan == RxChannel::Rx1 ? 0x50 : chan == RxChannel::Rx2 ? 0x0A : 0x03); + writeSpi(0x153, 0x01); + writeSpi(0x14E, 0x00); + writeSpi(0x121, 0x00); + writeSpi(0x11F, 0x73); + writeSpi(0x124, 0xFF); + writeSpi(0x120, 0x00); + writeSpi(0x122, 0x03); + writeSpi(0x126, 0x01); + const auto qecAddr = chan == RxChannel::Rx1 ? 0x02A : chan == RxChannel::Rx2 ? 0x02B : 0x02C; + writeSpi(qecAddr, 0x00); + writeSpi(qecAddr, chan == RxChannel::Rx3 ? 0X11 : 0X12); + waitRxTSTFinished(); + if (chan == RxChannel::Rx3) + writeSpi(qecAddr, 0x00); + writeSpi(0x77E, 0x00); +} + +void rxDelayCalib(const double fs, const RxChannel chan) +{ + LOGGING(toString(chan) + "延时线校准"); + writeSpi(0x000, chan == RxChannel::Rx1 ? 0x12 : chan == RxChannel::Rx2 ? 0x22 : 0x32); + writeSpi(0x77E, chan == RxChannel::Rx1 ? 0x50 : chan == RxChannel::Rx2 ? 0x0A : 0x03); + writeSpi(0x11B, 0x01); + writeSpi(0x11E, 0x01); + configTxNcoFreq(0, fs); + writeSpi(0x161, 0x00); + writeSpi(0x162, 0x00); + writeSpi(0x162, 0x01); + writeSpi(0x161, 0x01); + writeSpi(chan == RxChannel::Rx1 ? 0x706 : chan == RxChannel::Rx2 ? 0x722 : 0x73E, 0x6D); + writeSpi(0x6C3, 0x00); + writeSpi(0x11F, 0x73); + writeSpi(0x153, 0x00); + writeSpi(chan == RxChannel::Rx2 ? 0x724 : 0x708, 0x24); + writeSpi(0x196, 0x01); + const auto qecAddr = chan == RxChannel::Rx1 ? 0x02A : chan == RxChannel::Rx2 ? 0x02B : 0x02C; + writeSpi(qecAddr, chan == RxChannel::Rx3 ? 0x11 : 0x12); + waitRxTSTFinished(); + writeSpi(qecAddr, 0x00); + writeSpi(0x196, 0x11); + const auto r13D = readSpi(0x13D); + const auto r13E = readSpi(0x13E); + const auto B = r13D * std::pow(2, 8) + r13E; + const auto B_s = B >= 32768 ? B - 65536 : B; + const auto B_abs = static_cast(std::abs(B_s)); + const auto B_delay = (B_abs & 0b0111111111000000) >> 6; + if (B_s > 0) { + writeSpi(0x199, B_delay >> 8); + writeSpi(0x19A, B_delay & 0xFF); + writeSpi(0x19B, 0); + writeSpi(0x19C, 0); + } else { + writeSpi(0x199, 0); + writeSpi(0x19A, 0); + writeSpi(0x19B, B_delay >> 8); + writeSpi(0x19C, B_delay & 0xFF); + } + writeSpi(0x196, 0x10); + writeSpi(0x153, 0x00); + writeSpi(qecAddr, chan == RxChannel::Rx3 ? 0x11 : 0x12); + waitRxTSTFinished(); + writeSpi(qecAddr, 0x00); + writeSpi(0x77E, 0x00); +} + +void configDcCalib(const Calib& config) +{ + LOGGING("配置DC校准"); + configDcCalibMethod(config.dcCalibMethod); + configDcTrackingLength(config.dcTrackingLength); + configDcHighPassFactor(config.dcHighPassFactor); +} + +void configDcCalibMethod(const DCCalibMethod method) +{ + LOGGING("配置校准方法") + writeSpi(0x109, method == DCCalibMethod::Tracking ? 0x11 : 0x00); + Register r11F = readSpi(0x11F); + r11F[6] = method != DCCalibMethod::Tracking; + writeSpi(0x11F, r11F); + writeSpi(0x155, method == DCCalibMethod::HighPass ? 0x01 : 0x00); +} + +void configDcTrackingLength(const int length) +{ + LOGGING("配置Tracking统计长度") + writeSpi(0x10A, static_cast(std::log2(std::max(1, length / 128))) << 4); +} + +void configDcHighPassFactor(const int factor) +{ + LOGGING("配置高通滤波器系数") + writeSpi(0x157, (factor & 0xFF00) >> 8); + writeSpi(0x156, factor & 0xFF); +} + +void rxCalib(const CX9261AConfiguration& config, const RxChannel chan) +{ + LOGGING(toString(chan) + "校准"); + if (config.calib.rxMethod == CalibMethod::TST) { + if (chan == RxChannel::Rx1 && config.pllSource.rx1Source == LoSource::Off) { + LOGGING(toString(chan) + " OFF") + return; + } + if (chan == RxChannel::Rx2 && config.pllSource.rx2Source == LoSource::Off) { + LOGGING(toString(chan) + " OFF") + return; + } + if (chan == RxChannel::Rx3 && config.pllSource.rx3Source == LoSource::Off) { + LOGGING(toString(chan) + " OFF") + return; + } + preparePowerForRxCalib(config.pllSource); + preparePllForRxCalib(config, chan); + rxTSTCalib(chan); + } + if (config.calib.rxMethod == CalibMethod::MultiPoints) + configRxMultiPointsQec(config, config.calib.rxMultiPoints, chan); + if (config.calib.rxMethod == CalibMethod::Tracking) { + preparePowerForRxCalib(config.pllSource); + preparePllForRxCalib(config, chan); + } +} + +void configCalibMethod(const Calib& calib) +{ + LOGGING("切换校准方法") + Register r11F = readSpi(0x11F); + r11F.replace(5, 4, calib.rxMethod == CalibMethod::Tracking ? 0b00 : 0b11); + writeSpi(0x11F, r11F); + writeSpi(0x15C, 0x00); + if (calib.rxMethod == CalibMethod::Tracking) { + writeSpi(0x102, 0xF1); + writeSpi(0xA07, 0x00); + writeSpi(0xA08, 0x00); + writeSpi(0x096, 0x00); + // TODO 此处默认开启RX1和RX2的Tracking,后续需要对通道进一步处理 + writeSpi(0x07A, 0x00); + writeSpi(0x080, 0x00); + writeSpi(0x09C, 0x03); + + writeSpi(0x102, 0xFF); + writeSpi(0x160, 0x01); + writeSpi(0x09D, 0x08); + writeSpi(0x09E, 0x03); + writeSpi(0x09F, 0xE8); + writeSpi(0x0A4, 0x00); + writeSpi(0x0A5, 0x01); + writeSpi(0x094, 0x02); + pause(100); + writeSpi(0x15C, 0x11); + } else { + writeSpi(0x094, + calib.rxMethod == CalibMethod::MultiPoints || calib.txMethod == CalibMethod::MultiPoints ? 0x01 + : 0x00); + } +} + +CalibPredis readRxCalibPredis(const RxChannel chan) +{ + LOGGING(std::string("读取") + toString(chan) + "校准值"); + writeSpi(0x000, chan == RxChannel::Rx1 ? 0x12 : chan == RxChannel::Rx2 ? 0x22 : 0x32); + writeSpi(0x121, 0x00); + const CalibPredis predis{ .bHigh = readSpi(0x13D), + .bLow = readSpi(0x13E), + .cHigh = readSpi(0x13F), + .cLow = readSpi(0x140), + .dciHigh = readSpi(0x141), + .dciLow = readSpi(0x142), + .dcqHigh = readSpi(0x143), + .dcqLow = readSpi(0x144) }; + writeSpi(0x000, 02); + return predis; +} + +void saveRxCalibPredis(const unsigned char index, const RxChannel chan, const LoSource pll) +{ + LOGGING(std::string("保存") + toString(chan) + " " + toString(pll) + " index: " + std::to_string(index) + + " 校准值"); + writeSpi(0x0A0, 0x00); + writeSpi(0x0A1, pll == LoSource::Pll1 ? 0x00 : pll == LoSource::Pll2 ? 0x01 : 0x04); + writeSpi(0x0A2, chan == RxChannel::Rx1 ? 0x00 : chan == RxChannel::Rx2 ? 0x01 : 0x02); + writeSpi(0x0A3, index); + writeSpi(0x0A0, 0x01); +} + +void loadRxCalibPredis(const unsigned char index, const RxChannel chan, const LoSource pll) +{ + LOGGING("加载: " + toString(chan) + " " + toString(pll) + " " + std::to_string(index) + " 校准值") + writeSpi(0x0A0, 0x00); + writeSpi(0x0A1, pll == LoSource::Pll1 ? 0x00 : pll == LoSource::Pll2 ? 0x01 : 0x04); + writeSpi(0x0A2, chan == RxChannel::Rx1 ? 0x00 : chan == RxChannel::Rx2 ? 0x01 : 0x02); + writeSpi(0x0A3, index); + writeSpi(0x0A0, 0x02); +} + +void configRxMultiPointsQecImpl(const CX9261AConfiguration& config, const std::vector& points, + const RxChannel chan) +{ + auto mutConfig = config; + for (auto i = 0; i < points.size(); ++i) { + LOGGING("频点: " + std::to_string(points[i])); + const auto source = chan == RxChannel::Rx1 ? config.pllSource.rx1Source + : chan == RxChannel::Rx2 ? config.pllSource.rx2Source + : config.pllSource.rx3Source; + if (source == LoSource::Pll1) { + mutConfig.pllFreq.pll1Freq = points[i]; + configPll1(points[i], config.clock); + } + if (source == LoSource::Pll2) { + mutConfig.pllFreq.pll2Freq = points[i]; + configPll2(points[i], config.clock); + } + if (source == LoSource::Pll5) { + mutConfig.pllFreq.pll5Freq = points[i]; + configPll5(points[i], config.clock); + } + preparePllForRxCalib(mutConfig, chan); + rxTSTCalib(chan); + saveRxCalibPredis(i, chan, source); + } +} + +void configRxMultiPointsQec(const CX9261AConfiguration& config, const std::vector& points, const RxChannel chan) +{ + LOGGING(toString(chan) + "多点校准"); + auto mutConfig = config; + for (int i = chan == RxChannel::Rx3 ? 4 : 0; i < 5; ++i) { + auto& source = chan == RxChannel::Rx1 ? mutConfig.pllSource.rx1Source + : chan == RxChannel::Rx2 ? mutConfig.pllSource.rx2Source + : mutConfig.pllSource.rx3Source; + const auto& calibPll = chan == RxChannel::Rx1 ? mutConfig.calib.rx1CalibPll + : chan == RxChannel::Rx2 ? mutConfig.calib.rx2CalibPll + : mutConfig.calib.rx3CalibPll; + if (calibPll & (0b1 << i)) { + source = static_cast(calibPll & (0b1 << i)); + preparePowerForRxCalib(mutConfig.pllSource); + configRxMultiPointsQecImpl(mutConfig, points, chan); + } + } +} + +void preparePowerForTxCalib(const PllSource& pllSource) +{ + LOGGING("为Tx校准配置电源管理"); + writeSpi(0x02E, 0x03); + Register r03F = readSpi(0x03F); + r03F[2] = 1; + r03F[1] = 1; + r03F[0] = !(pllSource.tx1Source == LoSource::Pll4 || pllSource.tx2Source == LoSource::Pll4); + Register r040 = readSpi(0x040); + r040[7] = !(pllSource.tx1Source == LoSource::Pll4 || pllSource.tx2Source == LoSource::Pll4); + r040[6] = !(pllSource.tx1Source == LoSource::Pll3 || pllSource.tx2Source == LoSource::Pll3); + r040[5] = !(pllSource.tx1Source == LoSource::Pll3 || pllSource.tx2Source == LoSource::Pll3); + r040[4] = !(pllSource.tx1Source == LoSource::Pll2 || pllSource.tx2Source == LoSource::Pll2); + r040[3] = !(pllSource.tx1Source == LoSource::Pll2 || pllSource.tx2Source == LoSource::Pll2); + r040[2] = !(pllSource.tx1Source == LoSource::Pll1 || pllSource.tx2Source == LoSource::Pll1); + r040[1] = !(pllSource.tx1Source == LoSource::Pll1 || pllSource.tx2Source == LoSource::Pll1); + writeSpi(0x03F, r03F); + writeSpi(0x040, r040); +} + +void preparePllForTxCalib(const CX9261AConfiguration& config) +{ + LOGGING("为Tx校准配置PLL"); + configPllSource(config.pllSource); + if (config.pllSource.tx1Source == LoSource::Pll4 || config.pllSource.tx2Source == LoSource::Pll4) + afcPll4(); + if (config.pllSource.tx1Source == LoSource::Pll3 || config.pllSource.tx2Source == LoSource::Pll3) + afcPll3(); + if (config.pllSource.tx1Source == LoSource::Pll2 || config.pllSource.tx2Source == LoSource::Pll2) + afcPll2(); + if (config.pllSource.tx1Source == LoSource::Pll1 || config.pllSource.tx2Source == LoSource::Pll1) + afcPll1(); +} + +void txBisectionQecCalib(const double f0, const double fs) +{ + LOGGING("Tx二分法校准"); + writeSpi(0x02E, 0x03); + writeSpi(0x128, 0x11); + writeSpi(0x11E, 0x01); + writeSpi(0x77E, 0x24); + writeSpi(0x11F, 0x01); + writeSpi(0x121, 0x02); + writeSpi(0x11B, 0x01); + writeSpi(0x161, 0x01); + writeSpi(0x162, 0x01); + writeSpi(0x163, 0x00); + configTxNcoFreq(f0, fs * 4); + writeSpi(0xA2D, 0x02); + writeSpi(0xA07, 0x00); + writeSpi(0xA08, 0x0F); + writeSpi(0xA1C, 0x01); + configRxNcoFreq(f0 * 2, fs); + writeSpi(0x102, 0x0F); + writeSpi(0x102, 0xFF); + writeSpi(0x186, 0x00); + writeSpi(0x186, 0x01); + writeSpi(0x763, 0x34); + writeSpi(0x76D, 0x34); + writeSpi(0x101, 0xEF); + writeSpi(0x101, 0xFF); + writeSpi(0x800, 0x00); + writeSpi(0x81A, 0xF7); + writeSpi(0x81B, 0x34); + writeSpi(0x81C, 0x33); + writeSpi(0x81D, 0x12); + writeSpi(0x81E, 0x00); + writeSpi(0x81F, 0xFF); + writeSpi(0x820, 0x00); + writeSpi(0x821, 0xFF); + writeSpi(0x800, 0x80); + pause(100); + writeSpi(0x800, 0x81); + pause(100); + writeSpi(0x77E, 0x00); +} + +void txTSTCalib(const CX9261AConfiguration& config, const TxChannel chan) +{ + LOGGING(toString(chan) + "时域校准"); + // writeSpi(chan == TxChannel::Tx1 ? 0x763 : 0x76D, 0x04); + writeSpi(0x000, chan == TxChannel::Tx1 ? 0x12 : 0x22); + writeSpi(0x109, 0x00); + writeSpi(0x101, 0xFF); + writeSpi(0x120, 0x10); + writeSpi(0x122, 0x03); + writeSpi(0x124, 0xFF); + writeSpi(0x11B, 0x01); + writeSpi(0x128, 0x11); + configTxNcoFreq(config.calib.f0, config.clock.adc * 4); + writeSpi(0x161, 0x00); + writeSpi(0x162, 0x00); + writeSpi(0x162, 0x01); + writeSpi(0x161, 0x01); + writeSpi(0x11F, 0x73); + writeSpi(0x121, 0x00); + writeSpi(0x14E, 0x00); + writeSpi(0x126, 0x03); + writeSpi(0x77E, chan == TxChannel::Tx1 ? 0x40 : 0x08); + writeSpi(chan == TxChannel::Tx1 ? 0x02A : 0x02B, 0x11); + pause(qecDelay); + while (true) { + if ((readSpi(0x14D) & 0x30) == 0x30) + break; + pause(100); + } + writeSpi(chan == TxChannel::Tx1 ? 0x02A : 0x02B, 0x00); + writeSpi(0x77E, 0x00); + writeSpi(0x128, 0x00); + writeSpi(0x11B, 0x00); +} + +void txBisectionDcCalib(const double f0, const double fs) +{ + LOGGING("Tx二分法DC校准"); + writeSpi(0x77E, 0x24); + writeSpi(0x11F, 0x03); + writeSpi(0x121, 0x02); + writeSpi(0x11B, 0x01); + writeSpi(0x11E, 0x01); + writeSpi(0x161, 0x01); + writeSpi(0x162, 0x01); + configTxNcoFreq(f0, fs * 4); + writeSpi(0xA2D, 0x02); + writeSpi(0xA07, 0x00); + writeSpi(0xA08, 0x0F); + writeSpi(0xA1C, 0x01); + configRxNcoFreq(f0, fs); + writeSpi(0x81A, 0xF7); + writeSpi(0x81B, 0x44); + writeSpi(0x81C, 0x33); + writeSpi(0x81D, 0x14); + writeSpi(0x800, 0x80); + writeSpi(0x800, 0x82); + pause(100); + writeSpi(0x77E, 0x00); +} + +void configTxMultiPointsQecImpl(const CX9261AConfiguration& config, const std::vector& points) +{ + LOGGING("Tx多点校准"); + for (auto i = 0; i < points.size(); ++i) { + LOGGING("频点: " + std::to_string(points[i])); + configTxChannelFrequency(points[i], TxChannel::Tx1); + configTxChannelFrequency(points[i], TxChannel::Tx2); + if (config.pllSource.tx1Source == LoSource::Pll1 || config.pllSource.tx2Source == LoSource::Pll1) { + configPll1(points[i], config.clock); + afcPll1(); + } + if (config.pllSource.tx1Source == LoSource::Pll2 || config.pllSource.tx2Source == LoSource::Pll2) { + configPll2(points[i], config.clock); + afcPll2(); + } + if (config.pllSource.tx1Source == LoSource::Pll3 || config.pllSource.tx2Source == LoSource::Pll3) { + configPll3(points[i], config.clock); + afcPll3(); + } + if (config.pllSource.tx1Source == LoSource::Pll4 || config.pllSource.tx2Source == LoSource::Pll4) { + configPll4(points[i], config.clock); + afcPll4(); + } + writeSpi(0x101, 0xEF); + writeSpi(0x101, 0xFF); + txBisectionQecCalib(config.calib.f0, config.clock.adc); + txBisectionDcCalib(config.calib.f0, config.clock.adc); + writeSpi(0x000, 0x12); + saveTxCalibPredis(i, TxChannel::Tx1, config.pllSource.tx1Source); + writeSpi(0x000, 0x22); + saveTxCalibPredis(i, TxChannel::Tx2, config.pllSource.tx2Source); + writeSpi(0x000, 0x02); + } +} + +void configTxMultiPointsQec(const CX9261AConfiguration& config, const std::vector& points) +{ + auto mutConfig = config; + for (int i = 0; i < 5; ++i) { + const auto& calibPll = mutConfig.calib.tx1CalibPll; + if (calibPll & (0b1 << i)) { + mutConfig.pllSource.tx1Source = static_cast(calibPll & (0b1 << i)); + mutConfig.pllSource.tx2Source = static_cast(calibPll & (0b1 << i)); + preparePowerForTxCalib(mutConfig.pllSource); + preparePllForTxCalib(mutConfig); + configTxMultiPointsQecImpl(mutConfig, points); + } + } +} + +void txCalib(const CX9261AConfiguration& config) +{ + LOGGING("Tx校准"); + preparePowerForTxCalib(config.pllSource); + preparePllForTxCalib(config); + if (config.calib.txMethod == CalibMethod::Bisec) { + txBisectionQecCalib(config.calib.f0, config.clock.adc); + txBisectionDcCalib(config.calib.f0, config.clock.adc); + } + if (config.calib.txMethod == CalibMethod::TST) { + txTSTCalib(config, TxChannel::Tx1); + txTSTCalib(config, TxChannel::Tx2); + } + if (config.calib.txMethod == CalibMethod::MultiPoints) { + configTxMultiPointsQec(config, config.calib.txMultiPoints); + } +} + +void saveTxCalibPredis(const unsigned char index, const TxChannel chan, const LoSource pll) +{ + LOGGING(std::string("保存") + toString(chan) + " " + "pll: " + toString(pll) + " " + + " index: " + std::to_string(index) + " 校准值"); + writeSpi(0x0A0, 0x00); + writeSpi(0x0A1, pll == LoSource::Pll1 ? 0x00 : pll == LoSource::Pll2 ? 0x01 : pll == LoSource::Pll3 ? 0x02 : 0x03); + writeSpi(0x0A2, chan == TxChannel::Tx1 ? 0x03 : 0x04); + writeSpi(0x0A3, index); + writeSpi(0x0A0, 0x01); +} + +void loadTxCalibPredis(const unsigned char index, const TxChannel chan, const LoSource pll) +{ + LOGGING("加载: " + toString(chan) + toString(pll) + " " + " " + std::to_string(index) + " 校准值") + writeSpi(0x0A0, 0x00); + writeSpi(0x0A1, pll == LoSource::Pll1 ? 0x00 : pll == LoSource::Pll2 ? 0x01 : pll == LoSource::Pll3 ? 0x02 : 0x03); + writeSpi(0x0A2, chan == TxChannel::Tx1 ? 0x03 : 0x04); + writeSpi(0x0A3, index); + writeSpi(0x0A0, 0x02); +} + +void configQecCalib(const CX9261AConfiguration& config) +{ + LOGGING("配置QEC校准"); + const auto regsState = beforeQecState(); + if (config.calib.rxMethod == CalibMethod::MultiPoints || config.calib.rxMethod == CalibMethod::Tracking + || config.calib.txMethod == CalibMethod::MultiPoints) { + configRISCV(true); + } + // Rx使用跟踪校准时,Tx无法使用多点校准,且此时配置校准模式应置于校准结束之后 + if (config.calib.rxMethod != CalibMethod::Tracking) + configCalibMethod(config.calib); + // Rx校准只在有任意Rx通道不是Off时发生 + const bool calibRx = config.pllSource.rx1Source != LoSource::Off || config.pllSource.rx2Source != LoSource::Off + || config.pllSource.rx3Source != LoSource::Off; + if (calibRx) { + rxCalib(config, RxChannel::Rx1); + rxCalib(config, RxChannel::Rx2); + rxCalib(config, RxChannel::Rx3); + // 恢复校准前配置 + restoreQecState(regsState); + configPll4(config.pllFreq.pll4Freq, config.clock); + if ((config.pllSource.tx1Source == LoSource::Pll4 || config.pllSource.tx2Source == LoSource::Pll4) + && config.interface.workMode != WorkMode::Rx) + afcPll4(); + } + // 如果Rx使用了多点校准模式,则需要在校准结束后切换回初始化频点 + if (calibRx && config.calib.rxMethod == CalibMethod::MultiPoints) { + LOGGING("Rx通道切换到初始化频点"); + if (config.pllSource.rx1Source == LoSource::Pll1 || config.pllSource.rx2Source == LoSource::Pll1) { + configPll1(config.pllFreq.pll1Freq, config.clock); + afcPll1(); + } + if (config.pllSource.rx1Source == LoSource::Pll2 || config.pllSource.rx2Source == LoSource::Pll2) { + configPll2(config.pllFreq.pll2Freq, config.clock); + afcPll2(); + } + if (config.pllSource.rx3Source == LoSource::Pll5) { + configPll5(config.pllFreq.pll5Freq, config.clock); + afcPll5(); + } + auto loadRxDefault = [&config](const RxChannel chan, const LoSource source, const double freq) { + auto points = config.calib.rxMultiPoints; + std::sort(points.begin(), points.end()); + const auto location = std::lower_bound(points.begin(), points.end(), freq); + if (location != points.end()) { + const auto fundFreq = *location; + const auto it = + std::find(config.calib.rxMultiPoints.begin(), config.calib.rxMultiPoints.end(), fundFreq); + if (it != config.calib.rxMultiPoints.end()) { + loadRxCalibPredis(it - config.calib.rxMultiPoints.begin(), chan, source); + } + } + }; + if (config.pllSource.rx1Source != LoSource::Off) { + LOGGING("Rx1加载初始化系数"); + const auto rx1Freq = config.pllSource.rxUseExt ? config.pllFreq.rxExtFreq + : config.pllSource.rx1Source == LoSource::Pll1 ? config.pllFreq.pll1Freq + : config.pllFreq.pll2Freq; + loadRxDefault(RxChannel::Rx1, config.pllSource.rx1Source, rx1Freq); + } + if (config.pllSource.rx2Source != LoSource::Off) { + LOGGING("Rx2加载初始化系数"); + const auto rx2Freq = config.pllSource.rxUseExt ? config.pllFreq.rxExtFreq + : config.pllSource.rx2Source == LoSource::Pll1 ? config.pllFreq.pll1Freq + : config.pllFreq.pll2Freq; + loadRxDefault(RxChannel::Rx2, config.pllSource.rx2Source, rx2Freq); + } + if (config.pllSource.rx3Source != LoSource::Off) { + LOGGING("Rx3加载初始化系数"); + const auto rx3Freq = config.pllSource.rxUseExt ? config.pllFreq.rxExtFreq : config.pllFreq.pll5Freq; + loadRxDefault(RxChannel::Rx3, config.pllSource.rx3Source, rx3Freq); + } + } + // Tx校准只在任意Tx通道不是Off时发生 + const bool calibTx = config.pllSource.tx1Source != LoSource::Off || config.pllSource.tx2Source != LoSource::Off; + if (calibTx) { + txCalib(config); + restoreQecState(regsState); + } + // 如果Tx使用了多点校准模式,则需要在校准结束后切换回初始化频点 + if (calibTx && config.calib.txMethod == CalibMethod::MultiPoints) { + LOGGING("Tx通道切换到初始化频点"); + if (config.pllSource.tx1Source == LoSource::Pll1 || config.pllSource.tx2Source == LoSource::Pll1) { + configPll1(config.pllFreq.pll1Freq, config.clock); + afcPll1(); + } + if (config.pllSource.tx1Source == LoSource::Pll2 || config.pllSource.tx2Source == LoSource::Pll2) { + configPll2(config.pllFreq.pll2Freq, config.clock); + afcPll2(); + } + if (config.pllSource.tx1Source == LoSource::Pll3 || config.pllSource.tx2Source == LoSource::Pll3) { + configPll3(config.pllFreq.pll3Freq, config.clock); + afcPll3(); + } + if (config.pllSource.tx1Source == LoSource::Pll4 || config.pllSource.tx2Source == LoSource::Pll4) { + configPll4(config.pllFreq.pll4Freq, config.clock); + afcPll4(); + } + auto loadTxDefault = [&config](const TxChannel chan, const LoSource source, const double freq) { + auto points = config.calib.txMultiPoints; + std::sort(points.begin(), points.end()); + const auto location = std::lower_bound(points.begin(), points.end(), freq); + if (location != points.end()) { + const auto fundFreq = *location; + const auto it = + std::find(config.calib.txMultiPoints.begin(), config.calib.txMultiPoints.end(), fundFreq); + if (it != config.calib.txMultiPoints.end()) { + loadTxCalibPredis(it - config.calib.txMultiPoints.begin(), chan, source); + } + } + }; + if (config.pllSource.tx1Source != LoSource::Off) { + const auto tx1Freq = config.pllSource.txUseExt ? config.pllFreq.txExtFreq + : config.pllSource.tx1Source == LoSource::Pll1 ? config.pllFreq.pll1Freq + : config.pllSource.tx1Source == LoSource::Pll2 ? config.pllFreq.pll2Freq + : config.pllSource.tx1Source == LoSource::Pll3 ? config.pllFreq.pll3Freq + : config.pllFreq.pll4Freq; + loadTxDefault(TxChannel::Tx1, config.pllSource.tx1Source, tx1Freq); + } + if (config.pllSource.tx2Source != LoSource::Off) { + const auto tx2Freq = config.pllSource.txUseExt ? config.pllFreq.txExtFreq + : config.pllSource.tx2Source == LoSource::Pll1 ? config.pllFreq.pll1Freq + : config.pllSource.tx2Source == LoSource::Pll2 ? config.pllFreq.pll2Freq + : config.pllSource.tx2Source == LoSource::Pll3 ? config.pllFreq.pll3Freq + : config.pllFreq.pll4Freq; + loadTxDefault(TxChannel::Tx2, config.pllSource.tx2Source, tx2Freq); + } + } + // 仅在rx使用Tracking校准时在此处配置 + if (config.calib.rxMethod == CalibMethod::Tracking) + configCalibMethod(config.calib); + + Register r121 = 0x00; + r121[0] = config.calib.rxMethod == CalibMethod::Bisec; + r121[1] = config.calib.txMethod == CalibMethod::Bisec; + r121.replace(5, 4, config.calib.rxMethod == CalibMethod::MultiPoints ? 0b10 : 0b00); + r121.replace(7, 6, config.calib.txMethod == CalibMethod::MultiPoints ? 0b10 : 0b00); + writeSpi(0x121, r121); +} + +void configTxNco(const TxNCO& nco, const double fs) +{ + LOGGING("配置Tx NCO"); + configTxBIST(nco.txUseBist); + configTxNcoFreq(nco.txNCOFreq, fs); +} + +void configTxBIST(const bool bist) +{ + LOGGING("配置Tx BIST"); + writeSpi(0x128, 0x10); + writeSpi(0x11B, bist); + writeSpi(0x11E, bist); + writeSpi(0x161, bist); + writeSpi(0x162, bist); +} + +void configTxNcoFreq(const double freq, const double fs) +{ + LOGGING("配置Tx NCO频率"); + const auto ratio = freq < 0 ? (freq + fs) / fs : freq / fs; + const auto bin = round64(ratio * std::pow(2, 48)); + writeSpi(0x164, bin >> 40 & 0xFF); + writeSpi(0x165, bin >> 32 & 0xFF); + writeSpi(0x166, bin >> 24 & 0xFF); + writeSpi(0x167, bin >> 16 & 0xFF); + writeSpi(0x168, bin >> 8 & 0xFF); + writeSpi(0x169, bin & 0xFF); +} + +void configRxNco(const RxNCO& nco, const double fs) +{ + LOGGING("配置Rx NCO"); + configRxNcoMode(nco.rxUseBist ? NCOMode::BIST + : nco.rxNCOBypass ? NCOMode::Bypass + : nco.rxNCOUpward ? NCOMode::Up + : NCOMode::Down); + configRxNcoMS(nco.rxNCOMaster ? NCOMode::Master : NCOMode::Slaver); + configRxNcoFreq(nco.rxNCOFreq, fs); +} + +void configRxNcoMode(const NCOMode mode) +{ + LOGGING("配置Rx NCO模式"); + writeSpi(0x11C, mode == NCOMode::BIST ? 0x3F : 0x00); + writeSpi(0xA07, mode == NCOMode::BIST ? 0x01 : 0x00); + writeSpi(0xA08, mode == NCOMode::Bypass ? 0x00 : mode == NCOMode::Up ? 0X07 : 0X87); +} + +void configRxNcoMS(const NCOMode mode) +{ + LOGGING("配置Rx NCO主从模式"); + writeSpi(0xA09, mode != NCOMode::Master); +} + +void configRxNcoFreq(const double freq, const double fs) +{ + LOGGING("配置Rx NCO频率"); + const auto ratio = freq < 0 ? (freq + fs) / fs : freq / fs; + const auto bin = round64(ratio * std::pow(2, 48)); + writeSpi(0xA16, bin >> 40 & 0xFF); + writeSpi(0xA17, bin >> 32 & 0xFF); + writeSpi(0xA18, bin >> 24 & 0xFF); + writeSpi(0xA19, bin >> 16 & 0xFF); + writeSpi(0xA1A, bin >> 8 & 0xFF); + writeSpi(0xA1B, bin & 0xFF); +} + +void configInterface(const Interface& interface) +{ + LOGGING("配置接口"); + writeSpi(0x02E, interface.workMode == WorkMode::Rx ? 0x04 : interface.workMode == WorkMode::Tx ? 0x05 : 0x06); + writeSpi(0x003, 0x33); + Register r200{ 0x00 }; + // 0x200 + if (interface.ioMode != IOMode::CMOS) + r200 = 0x0F; + else if (interface.trMode == TrMode::R1T1 && interface.portMode == PortMode::Single) + r200 = 0x00; + else + r200 = 0x01; + writeSpi(0x200, r200); + // 0x201 + if (interface.workMode == WorkMode::FDD) + writeSpi(0x201, 0x00); + else if (interface.portMode == PortMode::Single && interface.trMode == TrMode::R2T2) + writeSpi(0x201, 0x3F); + else + writeSpi(0x201, 0x15); + // 0x202 + writeSpi(0x202, interface.portMode == PortMode::Single ? 0x03 : 0x00); + // 0x206 + Register r206{ 0x00 }; + if (interface.ioMode == IOMode::LVDS_S) + r206 = 0x1F; + if (interface.ioMode == IOMode::LVDS_E) + r206 = 0x0F; + writeSpi(0x206, r206); + // 0x208 + if (interface.trMode == TrMode::R1T1 + && ((interface.workMode == WorkMode::FDD && interface.portMode == PortMode::Dual) + || (interface.workMode != WorkMode::FDD && interface.portMode == PortMode::Single))) + writeSpi(0x208, 0x0F); + else + writeSpi(0x208, 0x00); + // 0x209 + if (interface.portMode == PortMode::Dual && interface.trMode == TrMode::R1T1) + writeSpi(0x209, 0x80); + else + writeSpi(0x209, 0x00); + // 0x77F + if (interface.ioMode != IOMode::CMOS) + writeSpi(0x77F, 0x0F); + else + writeSpi(0x77F, 0x00); + // 0x780 + if (interface.portMode == PortMode::Dual && interface.workMode == WorkMode::FDD) + writeSpi(0x780, 0x30); + else + writeSpi(0x780, interface.workMode == WorkMode::FDD ? 0x11 : interface.workMode == WorkMode::Rx ? 0x00 : 0x33); + // 0x781 + writeSpi(0x781, interface.ioMode == IOMode::CMOS ? 0x6F : 0x01); +} + +void configPllSource(const PllSource& pllSource) +{ + LOGGING("配置PLL来源"); + // PLL Source + Register r77D; + r77D[7] = rxSrcMap.at({ pllSource.rx1Source, pllSource.rx2Source })[6]; + r77D[6] = rxSrcMap.at({ pllSource.rx1Source, pllSource.rx2Source })[5]; + r77D[5] = txSrcMap.at({ pllSource.tx1Source, pllSource.tx2Source })[6]; + r77D[4] = txSrcMap.at({ pllSource.tx1Source, pllSource.tx2Source })[5]; + r77D[3] = !pllSource.txUseExt && txSrcMap.at({ pllSource.tx1Source, pllSource.tx2Source })[10]; + r77D[2] = !pllSource.txUseExt && txSrcMap.at({ pllSource.tx1Source, pllSource.tx2Source })[9]; + r77D[1] = txSrcMap.at({ pllSource.tx1Source, pllSource.tx2Source })[8]; + r77D[0] = txSrcMap.at({ pllSource.tx1Source, pllSource.tx2Source })[7]; + + // MUX + Register r6C3 = readSpi(0x6C3); + r6C3[3] = !pllSource.rxUseExt && pllSource.rx1Source == LoSource::Off; + r6C3[2] = !pllSource.rxUseExt && pllSource.rx2Source == LoSource::Off; + r6C3[1] = !pllSource.txUseExt && pllSource.tx1Source == LoSource::Off; + r6C3[0] = !pllSource.txUseExt && pllSource.tx2Source == LoSource::Off; + + // External + Register r775{ 0x24 }; + r775[7] = pllSource.rxUseExt; + r775[6] = pllSource.txUseExt; + + writeSpi(0x77D, r77D); + writeSpi(0x775, r775); + writeSpi(0x6C3, r6C3); +} + +void configPowerMode(const PowerMode pm) +{ + LOGGING("配置电源模式"); + writeSpi(0x02E, static_cast(pm)); +} + +void configPowerPins(const Power& power, const PowerMode pm) +{ + Register reg1 = 0x00; + reg1[0] = power.dig_rx1; + reg1[1] = power.dig_rx2; + reg1[2] = power.dig_rx3; + reg1[3] = power.dig_tx1; + reg1[4] = power.dig_tx2; + Register reg2 = 0x00; + reg2[0] = !power.exlo; + reg2[1] = !power.bgr; + reg2[2] = !power.temp_sensor; + reg2[3] = !power.auxdac; + reg2[4] = !power.auxadc1; + reg2[5] = !power.auxadc2; + reg2[6] = !power.fref1_rx; + Register reg3 = 0x00; + reg3[0] = !power.pll4_ldo; + reg3[1] = !power.pll5; + reg3[2] = !power.pll5_ldo; + reg3[3] = !power.rx1; + reg3[4] = !power.rx2; + reg3[5] = !power.rx3; + reg3[6] = !power.tx1; + reg3[7] = !power.tx2; + Register reg4 = 0x00; + reg4[0] = !power.bbpll; + reg4[1] = !power.pll1; + reg4[2] = !power.pll1_ldo; + reg4[3] = !power.pll2; + reg4[4] = !power.pll2_ldo; + reg4[5] = !power.pll3; + reg4[6] = !power.pll3_ldo; + reg4[7] = !power.pll4; + const int initAddr = 0x031 + static_cast(pm) * 4; + writeSpi(initAddr, reg1); + writeSpi(initAddr + 1, reg2); + writeSpi(initAddr + 2, reg3); + writeSpi(initAddr + 3, reg4); +} + +void configRefDoubler(const bool doubler, const double ref) +{ + LOGGING("配置参考倍频"); + writeSpi(0x789, ref <= 75 ? 0x10 : 0x00); + writeSpi(0x785, doubler ? 0xC9 : 0x49); + writeSpi(0x788, 0x24); + pause(1); + writeSpi(0x788, 0xA4); +} + +void initialRxChannel(const RxChannel chan) +{ + LOGGING("初始化通道" + toString(chan)); + writeSpi(chan == RxChannel::Rx1 ? 0x705 : chan == RxChannel::Rx2 ? 0x721 : 0x73D, 0xFC); + writeSpi(chan == RxChannel::Rx1 ? 0x706 : chan == RxChannel::Rx2 ? 0x722 : 0x73E, 0x6D); + writeSpi(chan == RxChannel::Rx1 ? 0x707 : chan == RxChannel::Rx2 ? 0x723 : 0x73F, 0x91); + writeSpi(chan == RxChannel::Rx1 ? 0x708 : chan == RxChannel::Rx2 ? 0x724 : 0x740, 0x04); + writeSpi(chan == RxChannel::Rx1 ? 0x709 : chan == RxChannel::Rx2 ? 0x725 : 0x741, 0x94); + writeSpi(chan == RxChannel::Rx1 ? 0x70A : chan == RxChannel::Rx2 ? 0x726 : 0x742, 0xFC); + writeSpi(chan == RxChannel::Rx1 ? 0x70C : chan == RxChannel::Rx2 ? 0x728 : 0x744, 0xC0); +} + +std::pair configBandwidthImpl(const double bandwidth) +{ + const auto x = bandwidth / 172.8; + auto c = 255; + auto r = 0; + for (; c > 0; --c) { + r = floor(c * x + 128 * x - 1); + if (r <= 31 && r >= 0) + break; + } + r = clamp(r, 0, 31); + c = round((r + 1) / x) - 128; + return { r, c }; +} + +void configRxBandwidth(const double bandwidth, const RxChannel chan) +{ + LOGGING("配置带宽" + toString(chan)); + const auto rc = configBandwidthImpl(bandwidth); + const auto r = rc.first; + const auto c = rc.second; + Register rReg = 0xF8; + rReg.replace(7, 3, r); + writeSpi(chan == RxChannel::Rx1 ? 0x703 : chan == RxChannel::Rx2 ? 0x71F : 0x73B, c); + writeSpi(chan == RxChannel::Rx1 ? 0x704 : chan == RxChannel::Rx2 ? 0x720 : 0x73C, rReg); +} + +void configRxTIA(const int tia, const RxChannel chan) +{ + LOGGING("配置TIA" + toString(chan)); + Register tiaReg = 0x50; + tiaReg.replace(2, 0, tia); + writeSpi(chan == RxChannel::Rx1 ? 0x700 : chan == RxChannel::Rx2 ? 0x71C : 0x738, tiaReg); +} + +void configRxMixer(const int mixer) +{ + LOGGING("配置Mixer"); + writeSpi(0x907, mixer); +} + +void configRxChannel(const RxConfig& config, const RxChannel chan) +{ + LOGGING("配置通道" + toString(chan)); + configRxTIA(config.tia, chan); + int tiaCSel = round(1036.4364 * (config.tia + 1) / config.bandwidth - 40); + tiaCSel = clamp(tiaCSel, 0, 8191); + const Register c1 = tiaCSel >> 8; + const Register c2 = tiaCSel & 0xFF; + writeSpi(chan == RxChannel::Rx1 ? 0x701 : chan == RxChannel::Rx2 ? 0x71D : 0x739, c1); + writeSpi(chan == RxChannel::Rx1 ? 0x702 : chan == RxChannel::Rx2 ? 0x71E : 0x73A, c2); + configRxBandwidth(config.bandwidth, chan); + configRxMixer(config.mixer); +} + +void configRxFIR(const int fir) +{ + LOGGING("配置Rx FIR"); + Register firReg = readSpi(0x106); + firReg.replace(7, 5, fir == 8 ? 5 : fir); + writeSpi(0x106, firReg); +} + +void configRxHBF1(const int hbf) +{ + LOGGING("配置Rx HBF1"); + Register hbfReg = readSpi(0x106); + hbfReg[4] = hbf == 2; + writeSpi(0x106, hbfReg); +} + +void configRxHBF2(const int hbf) +{ + LOGGING("配置Rx HBF2"); + Register hbfReg = readSpi(0x106); + hbfReg[3] = hbf == 2; + writeSpi(0x106, hbfReg); +} + +void configRxHBF3(const int hbf) +{ + LOGGING("配置Rx HBF3"); + Register hbfReg = readSpi(0x106); + hbfReg.replace(2, 1, hbf == 0 ? 1 : hbf); + writeSpi(0x106, hbfReg); +} + +void configRxCIC(const int cic) +{ + LOGGING("配置Rx CIC"); + Register cicReg = readSpi(0x106); + cicReg[0] = cic == 20; + writeSpi(0x106, cicReg); +} + +void configRxFilters(const Filters& filters) +{ + LOGGING("配置Rx 滤波器"); + Register filtersReg; + filtersReg.replace(7, 5, filters.fir == 8 ? 5 : filters.fir); + filtersReg[4] = filters.hbf1 == 2; + filtersReg[3] = filters.hbf2 == 2; + filtersReg.replace(2, 1, filters.hbf3 == 0 ? 1 : filters.hbf3); + filtersReg[0] = filters.cic == 20; + writeSpi(0x106, filtersReg); +} + +void configRxFIRCoe(const std::vector& coe) +{ + LOGGING("配置Rx FIR系数"); + for (auto i = 0; i < coe.size(); ++i) { + const auto value = round(coe[i] * std::pow(2, 15)) + (coe[i] < 0 ? 65536 : 0); + writeSpi(0x401, i); + writeSpi(0x402, value >> 8 & 0xFF); + writeSpi(0x403, value & 0xFF); + writeSpi(0x401, 0x80 + i); + pause(1); + } + writeSpi(0x400, ceil(coe.size() / 16) - 1); + writeSpi(0x404, 00); + writeSpi(0x404, 01); +} + +std::pair configTxBandwidthImpl(const double bandwidth) +{ + const auto x = bandwidth / 144; + auto c = 127; + auto r = 0; + for (; c > 0; --c) { + r = floor(c * x + 128 * x - 1); + if (r <= 31 && r >= 0) + break; + } + r = clamp(r, 0, 31); + c = round((r + 1) / x) - 128; + return { r, c }; +} + +void configTxBandwidth(const double bandwidth, const TxChannel chan) +{ + LOGGING("配置通道" + toString(chan)); + const auto rc = configTxBandwidthImpl(bandwidth); + const auto r = rc.first; + const auto c = rc.second; + Register rReg = 0xAF; + rReg.replace(7, 3, r); + writeSpi(chan == TxChannel::Tx1 ? 0x75E : 0x768, rReg); + const Register cReg = c << 1; + writeSpi(chan == TxChannel::Tx1 ? 0x75D : 0x767, cReg); + Register lpfReg = readSpi(chan == TxChannel::Tx1 ? 0x75F : 0x769); + lpfReg.replace(7, 2, r); + writeSpi(chan == TxChannel::Tx1 ? 0x75F : 0x769, lpfReg); +} + +void configTxMixer(const int mixer, const TxChannel chan) +{ + LOGGING("配置Mixer" + toString(chan)); + Register mixerReg = 0xFF; + mixerReg.replace(7, 2, mixer); + writeSpi(chan == TxChannel::Tx1 ? 0x760 : 0x76A, mixerReg); +} + +void initialTxChannel(const TxChannel chan) +{ + LOGGING("初始化通道" + toString(chan)); + writeSpi(chan == TxChannel::Tx1 ? 0x75A : 0x764, 0x83); + writeSpi(chan == TxChannel::Tx1 ? 0x75B : 0x765, 0xDA); + pause(delay); + writeSpi(chan == TxChannel::Tx1 ? 0x75B : 0x765, 0x9A); + writeSpi(chan == TxChannel::Tx1 ? 0x75C : 0x766, 0x81); + writeSpi(chan == TxChannel::Tx1 ? 0x763 : 0x76D, 0x04); +} + +void configTxChannelFrequency(const double lo, const TxChannel chan) +{ + LOGGING("根据本振频率配置发射通道: " + toString(chan)); + Register r75F = readSpi(chan == TxChannel::Tx1 ? 0x75F : 0x769); + r75F.replace(1, 0, lo <= 3500 ? 0x01 : 0x00); + writeSpi(chan == TxChannel::Tx1 ? 0x75F : 0x769, r75F); + writeSpi(chan == TxChannel::Tx1 ? 0x761 : 0x76B, lo <= 3500 ? 0x04 : 0x07); + writeSpi(chan == TxChannel::Tx1 ? 0x762 : 0x76C, lo <= 3500 ? 0x70 : 0x6C); +} + +void configTxChannel(const TxConfig& config, const TxChannel chan) +{ + LOGGING("配置通道" + toString(chan)); + configTxBandwidth(config.bandwidth, chan); + configTxMixer(config.mixer, chan); +} + +void configTxFIR(const int fir) +{ + LOGGING("配置Tx FIR"); + const Register firReg = fir == 8 ? 5 : fir; + writeSpi(0x107, firReg); +} + +void configTxHBF1(const int hbf) +{ + LOGGING("配置Tx HBF1"); + Register hbfReg = readSpi(0x108); + hbfReg[7] = hbf == 2; + writeSpi(0x108, hbfReg); +} + +void configTxHBF2(const int hbf) +{ + LOGGING("配置Tx HBF2"); + Register hbfReg = readSpi(0x108); + hbfReg[6] = hbf == 2; + writeSpi(0x108, hbfReg); +} + +void configTxHBF3(const int hbf) +{ + LOGGING("配置Tx HBF3"); + Register hbfReg = readSpi(0x108); + hbfReg.replace(5, 4, hbf == 0 ? 1 : hbf); + writeSpi(0x108, hbfReg); +} + +void configTxCIC(const int cic) +{ + LOGGING("配置Tx CIC"); + Register cicReg = readSpi(0x108); + cicReg.replace(2, 0, cic == 20 ? 4 : cic == 8 ? 3 : cic == 80 ? 2 : cic == 32 ? 1 : 0); + writeSpi(0x108, cicReg); +} + +void configTxFilters(const Filters& filters) +{ + LOGGING("配置Tx 滤波器"); + const Register firReg = filters.fir == 8 ? 5 : filters.fir; + Register filtersReg; + filtersReg[7] = filters.hbf1 == 2; + filtersReg[6] = filters.hbf2 == 2; + filtersReg.replace(5, 4, filters.hbf3 == 0 ? 1 : filters.hbf3); + filtersReg.replace(2, 0, + filters.cic == 20 ? 4 + : filters.cic == 8 ? 3 + : filters.cic == 80 ? 2 + : filters.cic == 32 ? 1 + : 0); + writeSpi(0x107, firReg); + writeSpi(0x108, filtersReg); +} + +void configTxFIRCoe(const std::vector& coe) +{ + LOGGING("配置Tx FIR系数"); + for (auto i = 0; i < coe.size(); ++i) { + const auto value = round(coe[i] * std::pow(2, 15)) + (coe[i] < 0 ? 65536 : 0); + writeSpi(0x501, i); + writeSpi(0x502, value >> 8 & 0xFF); + writeSpi(0x503, value & 0xFF); + writeSpi(0x501, 0x80 + i); + pause(1); + } + writeSpi(0x500, ceil(coe.size() / 16) - 1); + writeSpi(0x504, 00); + writeSpi(0x504, 01); +} + +CalibPredis readTxCalibPredis(const TxChannel chan) +{ + LOGGING("读取校准系数: " + toString(chan)); + writeSpi(0x000, chan == TxChannel::Tx1 ? 0x12 : 0x22); + writeSpi(0x121, 0x00); + const CalibPredis predis{ .bHigh = readSpi(0x145), + .bLow = readSpi(0x146), + .cHigh = readSpi(0x147), + .cLow = readSpi(0x148), + .dciHigh = readSpi(0x149), + .dciLow = readSpi(0x14A), + .dcqHigh = readSpi(0x14B), + .dcqLow = readSpi(0x14C) }; + writeSpi(0x000, 02); + return predis; +} + +void configFPGA(const Interface& interface) +{ + setPin(33, 1); + setPin(39, 1); + setPin(40, 1); + + setPin(32, 1); + setPin(7, interface.ioMode == IOMode::CMOS ? 0 : 1); + setPin(34, 1); + setPin(34, 0); + + setPin(38, interface.portMode == PortMode::Single); + setPin(37, interface.trMode == TrMode::R2T2); + setPin(36, interface.workMode != WorkMode::FDD); + setPin(35, interface.workMode == WorkMode::Rx); + + setPin(34, 1); + setPin(34, 0); + + setPin(43, 0); + setPin(43, 1); +} + +void rxFFTCalib(const double lo, const double fs, const int firLength, const CX9261AConfiguration& config, + RxChannel chan) +{ + writeSpi(0x000, chan == RxChannel::Rx1 ? 0x12 : 0x22); + writeSpi(0x128, 0x00); + writeSpi(0x11B, 0x01); + writeSpi(0x11E, 0x01); + configTxNcoFreq(0, fs); + writeSpi(0x161, 0x00); + writeSpi(0x162, 0x00); + writeSpi(0x162, 0x01); + writeSpi(0x161, 0x01); + writeSpi(0x000, chan == RxChannel::Rx1 ? 0x12 : chan == RxChannel::Rx2 ? 0x22 : 0x32); + writeSpi(0x102, 0x03); + writeSpi(0x102, 0xFF); + writeSpi(0x15C, 0x00); + writeSpi(0x160, 0x01); + writeSpi(0x77E, chan == RxChannel::Rx1 ? 0x50 : chan == RxChannel::Rx2 ? 0x0A : 0x03); + writeSpi(0x09B, 0x01); // TXPLL4 + writeSpi(0x09D, firLength); + writeSpi(0x096, (round(lo) >> 8) & 0xFF); + writeSpi(0x097, round(lo) & 0xFF); + const double ref = config.clock.ref * (config.clock.refDoubler ? 2 : 1); + writeSpi(0x098, (round(ref * 10) >> 8) & 0xFF); + writeSpi(0x099, round(ref * 10) & 0xFF); + writeSpi(0x09E, (round(fs * 100) >> 8) & 0xFF); + writeSpi(0x09F, round(fs * 100) & 0xFF); + writeSpi(0x09C, static_cast(chan)); + pause(qecDelay); + while (true) { + if (readSpi(0x0B3) == 5) + break; + pause(100); + } + writeSpi(0x09C, 0x00); + writeSpi(0x15C, 0x01); + writeSpi(0x77E, 0x00); + configPllSource(config.pllSource); +} + +void txTSTPhaseDelay(const Clock& clock, const double lo, const double fs, const double f0, const TxChannel chan) +{ + writeSpi(0x000, chan == TxChannel::Tx1 ? 0x12 : 0x22); + writeSpi(0x02E, 0x03); + writeSpi(0x109, 0x00); + writeSpi(0x120, 0x10); + writeSpi(0x122, 0x03); + writeSpi(0x124, 0xFF); + writeSpi(0x11B, 0x01); + writeSpi(0x128, 0x11); + configPll4(lo + 200, clock); + configTxNcoFreq(f0, fs * 4); + writeSpi(0x161, 0x00); + writeSpi(0x162, 0x00); + writeSpi(0x162, 0x01); + writeSpi(0x161, 0x01); + writeSpi(0x11F, 0x73); + writeSpi(0x121, 0x80); + writeSpi(0x126, 0x03); + writeSpi(0x77E, chan == TxChannel::Tx1 ? 0x40 : 0x08); + writeSpi(0x186, 0x10); + writeSpi(0x189, 0x00); + writeSpi(0x18A, 0x00); + writeSpi(0x18B, 0x00); + writeSpi(0x18C, 0x00); + writeSpi(chan == TxChannel::Tx1 ? 0x763 : 0x76D, 0x14); + writeSpi(0x095, 0x00); + writeSpi(0x096, (round(lo) >> 8) & 0xFF); + writeSpi(0x097, round(lo) & 0xFF); + writeSpi(0x09C, chan == TxChannel::Tx1 ? 6 : 7); + pause(qecDelay); + while (true) { + if (readSpi(0x0B3) == 7) + break; + pause(100); + } + writeSpi(0x09C, 0x00); + writeSpi(0x77E, 0x00); + writeSpi(0x128, 0x00); +} + +} // namespace CX9261A diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_1_9_0/cx9261adriver.h b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_1_9_0/cx9261adriver.h new file mode 100644 index 0000000..ef332a0 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_1_9_0/cx9261adriver.h @@ -0,0 +1,546 @@ +/** + * @file cx9261adriver.h + */ + +#ifndef CX9261ADRIVER_CX9261ADRIVER_H +#define CX9261ADRIVER_CX9261ADRIVER_H + +#define VERSION 1.9.0 + +#include "defs.h" +// 如果不需要输出日志内容,注释掉下面的宏定义 +#define USE_LOGGING + +#ifdef USE_LOGGING +# define LOGGING(x) logging(x); +#else +# define LOGGING(x) +#endif + +namespace CX9261A { +#ifdef USE_LOGGING +/** + * @brief 输出日志的函数 + * @param msg 要输出的内容 + */ +void logging(const std::string& msg); +#endif +/** + * @brief 需要实现的函数,实现SPI写入寄存器功能 + * @param address 要写入的寄存器地址 + * @param value 要写入的寄存器值 + */ +void writeSpi(int address, int value); +/** + * @brief 需要实现的函数,实现SPI读取寄存器功能 + * @param address 要读取的寄存器地址 + * @return 返回的寄存器值 + */ +int readSpi(int address); +/** + * @brief 需要实现的函数,实现等待功能 + * @param ms 等待时间,单位毫秒 + */ +void pause(double ms); +/** + * @brief 需要实现的函数,实现配置FPGA对应寄存器功能 + * @param pin 寄存器地址 + * @param value 寄存器值 + */ +void setPin(int pin, int value); +/** + * @brief 初始化芯片状态,写入与具体配置无关的寄存器值 + */ +void initialChip(); +/** + * @brief 初始化电源配置,如果只自定义配置部分模式下的电源管理,在自定义配置之前需要先调用此函数 + */ +void initialPowerConfig(const CX9261AConfiguration& config); +/** + * @brief 初始化BBPLL相关寄存器,如果调用了initialChip,则无需单独调用此函数 + */ +void initialBBPLL(); +/** + * @brief 初始化PLL1相关寄存器,如果调用了initialChip,则无需单独调用此函数 + */ +void initialPLL1(); +/** + * @brief 初始化PLL2相关寄存器,如果调用了initialChip,则无需单独调用此函数 + */ +void initialPLL2(); +/** + * @brief 初始化PLL3相关寄存器,如果调用了initialChip,则无需单独调用此函数 + */ +void initialPLL3(); +/** + * @brief 初始化PLL4相关寄存器,如果调用了initialChip,则无需单独调用此函数 + */ +void initialPLL4(); +/** + * @brief 初始化PLL5相关寄存器,如果调用了initialChip,则无需单独调用此函数 + */ +void initialPLL5(); +/** + * @brief 配置受参考时钟频率影响的寄存器 + * @param ref 参考时钟频率,单位MHz + */ +void configRef(double ref); +/** + * @brief 配置时钟相关寄存器,包括ADC和BBPLL + * @param config CX9261A参数结构体 + */ +void configBBPLL(const CX9261AConfiguration& config); +/** + * @brief BBPLL AFC + * @return 是否锁定 + */ +bool afcBBPll(); +/** + * @brief 配置PLL1频率 + * @param lo 目标频率 + * @param clock 时钟结构体,使用其中的ref和refDoubler属性 + */ +void configPll1(double lo, const Clock& clock); +/** + * @brief Pll1 AFC + * @return 是否锁定 + */ +bool afcPll1(); +/** + * @brief 配置PLL2频率 + * @param lo 目标频率 + * @param clock 时钟结构体,使用其中的ref和refDoubler属性 + */ +void configPll2(double lo, const Clock& clock); +/** + * @brief Pll2 AFC + * @return 是否锁定 + */ +bool afcPll2(); +/** + * @brief 配置PLL3频率 + * @param lo 目标频率 + * @param clock 时钟结构体,使用其中的ref和refDoubler属性 + */ +void configPll3(double lo, const Clock& clock); +/** + * @brief Pll3 AFC + * @return 是否锁定 + */ +bool afcPll3(); +/** + * @brief 配置PLL4频率 + * @param lo 目标频率 + * @param clock 时钟结构体,使用其中的ref和refDoubler属性 + */ +void configPll4(double lo, const Clock& clock); +/** + * @brief Pll4 AFC + * @return 是否锁定 + */ +bool afcPll4(); +/** + * @brief 配置PLL5频率 + * @param lo 目标频率 + * @param clock 时钟结构体,使用其中的ref和refDoubler属性 + */ +void configPll5(double lo, const Clock& clock); +/** + * @brief Pll5 AFC + * @return 是否锁定 + */ +bool afcPll5(); +/** + * @brief 配置AGC模式 + * @param mode 模式0~13 + */ +void configAGCMode(int mode); +/** + * @brief 配置AGC PDT + * @param pdt AGCPDT结构体 + */ +void configAGCPDT(const AGCPDT& pdt); +/** + * @brief 配置AGC LMT + * @param lmt AGCLMT结构体 + */ +void configAGCLMT(const AGCLMT& lmt); +/** + * @brief 配置AGC DIG + * @param dig AGCDIG结构体 + */ +void configAGCDIG(const AGCDIG& dig); +/** + * @brief 配置AGC + * @param agc AGC结构体 + */ +void configAGC(const AGC& agc); +/** + * @brief 配置片内处理器,仅在使用需要处理器辅助的校准方法时需要开启处理器 + * @param on 开启/关闭 + */ +void configRISCV(bool on); +/** + * @brief 配置温补 + * @param mode 温补模式 DAC/Band + */ +void configTemperatureCompensation(TemperatureComp mode); +/** + * @brief ADC校准 + * @param adc ADC速率 + */ +void configADCCalib(double adc); +/** + * @brief Flash校准 + */ +void configFlashCalib(); +/** + * @brief QEC校准会改变部分寄存器配置,在进行校准之前需要保存这部分寄存器,校准后恢复 + * @return 包含寄存器地址和值的map + */ +std::map beforeQecState(); +/** + * @brief 恢复QEC校准过程中改变的寄存器 + * @param state beforeQecState函数返回的map + */ +void restoreQecState(const std::map& state); +/** + * @brief 根据pll来源配置校准模式下的电源管理 + * @param pllSource PllSource结构体 + */ +void preparePowerForRxCalib(const PllSource& pllSource); +/** + * @brief 调整校准时Pll的配置 + * @param config CX9261A配置结构体 + * @param chan 要进行校准的通道 + */ +void preparePllForRxCalib(const CX9261AConfiguration& config, RxChannel chan); +/** + * @brief 等待RxTST窄带校准结束,可重写 + * @return 校准是否结束 + */ +bool waitRxTSTFinished(); +/** + * @brief RX时域统计校准 + * @param chan 校准的RX通道 + */ +void rxTSTCalib(RxChannel chan); +/** + * @brief RX延时线校准 + * @param fs ADC采样率 + * @param chan 校准的RX通道 + */ +void rxDelayCalib(double fs, RxChannel chan); +/** + * @brief DC Tracking + * @param config CX9261A配置结构体 + */ +void configDcCalib(const Calib& config); +void configDcCalibMethod(DCCalibMethod method); +void configDcTrackingLength(int length); +void configDcHighPassFactor(int factor); +/** + * @brief Rx校准 + * @param config CX9261A配置结构体 + * @param chan 要进行校准的通道 + */ +void rxCalib(const CX9261AConfiguration& config, RxChannel chan); +/** + * @brief 选择校准方法 + * @param calib 校准结构体 + */ +void configCalibMethod(const Calib& calib); +/** + * @brief 读取当前Rx chan通道的校准值 + * @param chan Rx通道 + * @return 校准值结构体 + */ +CalibPredis readRxCalibPredis(RxChannel chan); +/** + * @brief 储存校准值 + * @param index 第index组校准值 + * @param chan 接收通道 + * @param pll 使用的PLL + */ +void saveRxCalibPredis(unsigned char index, RxChannel chan, LoSource pll); +/** + * @brief 加载保存的校准值 + * @param index 第index组校准值 + * @param chan 指定加载校准值的通道 + * @param pll 使用的PLL + */ +void loadRxCalibPredis(unsigned char index, RxChannel chan, LoSource pll); +/** + * @brief Rx窄带多点校准 + * @param config CX9261A配置结构体 + * @param points 校准点 + * @param chan 接收通道 + */ +void configRxMultiPointsQec(const CX9261AConfiguration& config, const std::vector& points, RxChannel chan); +/** + * @brief 根据pll来源配置校准模式下的电源管理 + * @param pllSource PllSource结构体 + */ +void preparePowerForTxCalib(const PllSource& pllSource); +/** + * @brief 调整校准时Pll的配置 + * @param config CX9261A配置结构体 + */ +void preparePllForTxCalib(const CX9261AConfiguration& config); +/** + * @brief TX二分法QEC校准 + * @param f0 校准音频率 + * @param fs adc频率 + */ +void txBisectionQecCalib(double f0, double fs); +/** + * @brief TX时域统计法校准 + * @param config CX9261A配置结构体 + * @param chan 要校准的通道 + */ +void txTSTCalib(const CX9261AConfiguration& config, TxChannel chan); +/** + * @brief TX二分法DC校准 + * @param f0 校准音频率 + * @param fs adc频率 + */ +void txBisectionDcCalib(double f0, double fs); +/** + * @brief Tx多点校准 + * @param config CX9261A配置结构体 + * @param points 校准点 + */ +void configTxMultiPointsQec(const CX9261AConfiguration& config, const std::vector& points); +/** + * @brief Tx通道校准 + * @param config CX9261A配置结构体 + */ +void txCalib(const CX9261AConfiguration& config); +/** + * @brief 储存校准值 + * @param index 第index组校准值 + * @param chan 发射通道 + * @param pll pll + */ +void saveTxCalibPredis(unsigned char index, TxChannel chan, LoSource pll); +/** + * @brief 加载保存的校准值 + * @param index 第index组校准值 + * @param chan 指定加载校准值的通道 + * @param pll 指定加载校准值对应的PLL + */ +void loadTxCalibPredis(unsigned char index, TxChannel chan, LoSource pll); +/** + * @brief Qec校准顶层函数,内部根据配置选择使用对应方法进行校准 + * @param config CX9261A配置结构体 + */ +void configQecCalib(const CX9261AConfiguration& config); +/** + * @brief 配置TX NCO相关寄存器 + * @param nco TX NCO配置结构体 + * @param fs adc速率 + */ +void configTxNco(const TxNCO& nco, double fs); +/** + * @brief 配置TX NCO BIST模式 + * @param bist 开启/关闭BIST + */ +void configTxBIST(bool bist); +/** + * @brief 配置TX NCO频率 + * @param freq 混频频率 + * @param fs adc抽取后速率 + */ +void configTxNcoFreq(double freq, double fs); +/** + * @brief 配置RX NCO相关寄存器 + * @param nco RX NCO配置结构体 + * @param fs adc速率 + */ +void configRxNco(const RxNCO& nco, double fs); +/** + * @brief 配置Rx NCO模式 + * @param mode NCO模式:Bypass/BIST/Up/Down + */ +void configRxNcoMode(NCOMode mode); +/** + * @brief 配置Rx NCO模式 + * @param mode NCO模式:Master/Slaver + */ +void configRxNcoMS(NCOMode mode); +/** + * @brief 配置Rx NCO频率 + * @param freq 混频频率 + * @param fs adc速率 + */ +void configRxNcoFreq(double freq, double fs); +/** + * @brief 配置接口相关寄存器 + * @param interface Interface配置结构体 + */ +void configInterface(const Interface& interface); +/** + * @brief 配置PLL来源 + * @param pllSource PLlSource结构体 + */ +void configPllSource(const PllSource& pllSource); +/** + * @brief 切换电源模式 + * @param pm 电源模式 + */ +void configPowerMode(PowerMode pm); +/** + * @brief 配置电源管理 + * @param power 电源配置结构体 + * @param pm 电源模式 + */ +void configPowerPins(const Power& power, PowerMode pm); +/** + * @brief 配置参考倍频器 + * @param doubler 倍频器开关 + * @param ref 参考时钟频率,单位MHz + */ +void configRefDoubler(bool doubler, double ref); +/** + * @brief 初始化通道,调用initialChip函数会初始化RX1,RX2,RX3三个通道 + * @param chan 通道 RX1/RX2/RX3 + */ +void initialRxChannel(RxChannel chan); +/** + * @brief 配置Rx带宽 + * @note 只改变Rx带宽会导致通道增益改变,建议使用configRxChannel函数进行带宽调整 + * @param bandwidth 带宽,单位(MHz) + * @param chan 通道 Rx1/Rx2/Rx3 + */ +void configRxBandwidth(double bandwidth, RxChannel chan); +/** + * @brief 配置Rx TIA + * @note 只改变TIA会导致通道带宽改变,建议使用configRxChannel函数进行TIA调整 + * @param tia tia档位 + * @param chan 通道 Rx1/Rx2/Rx3 + */ +void configRxTIA(int tia, RxChannel chan); +/** + * @brief 配置Rx Mixer + * @param mixer mixer档位 + */ +void configRxMixer(int mixer); +/** + * @brief 配置Rx通道,包含TIA,Mixer以及Bandwidth + * @param config RxConfig结构体 + * @param chan Rx1/Rx2/Rx3 + */ +void configRxChannel(const RxConfig& config, RxChannel chan); +/** + * @brief 配置Rx FIR滤波器抽取倍数 + * @param fir 抽取倍数 0(Bypass)/1/2/3/4/8 + */ +void configRxFIR(int fir); +/** + * @brief 配置Rx HBF1滤波器抽取倍数 + * @param hbf 抽取倍数 0(Bypass)/2 + */ +void configRxHBF1(int hbf); +/** + * @brief 配置Rx HBF2滤波器抽取倍数 + * @param hbf 抽取倍数 0(Bypass)/2 + */ +void configRxHBF2(int hbf); +/** + * @brief 配置Rx HBF3滤波器抽取倍数 + * @param hbf 抽取倍数 0(Bypass)/2/3 + */ +void configRxHBF3(int hbf); +/** + * @brief 配置Rx CIC滤波器 + * @param cic 抽取倍数 0(Bypass)/20 + */ +void configRxCIC(int cic); +/** + * @brief 配置Rx滤波器 + * @param filters Filters结构体 + */ +void configRxFilters(const Filters& filters); +/** + * @brief 配置Rx FIR滤波器系数 + * @param coe 滤波器系数,长度为16的整倍数,最大128 + */ +void configRxFIRCoe(const std::vector& coe); +/** + * @brief 配置Tx带宽 + * @param bandwidth 带宽,单位(MHz) + * @param chan 通道 TX1/TX2 + */ +void configTxBandwidth(double bandwidth, TxChannel chan); +/** + * @brief 配置Tx Mixer + * @param mixer 混频器值 + * @param chan TX1/TX2 + */ +void configTxMixer(int mixer, TxChannel chan); +/** + * @brief 初始化Tx通道 + * @param chan 通道 TX1/TX2 + */ +void initialTxChannel(TxChannel chan); +/** + * @brief 根据Tx通道的本振频率,配置对应的参数 + * @param lo 本振频率,单位(MHz) + * @param chan 通道(Tx1/Tx2) + */ +void configTxChannelFrequency(double lo, TxChannel chan); +/** + * @brief 配置Tx通道,Mixer以及Bandwidth + * @param config TxConfig结构体 + * @param chan Tx1/Tx2 + */ +void configTxChannel(const TxConfig& config, TxChannel chan); +/** + * @brief 配置Tx FIR滤波器插值倍数 + * @param fir 插值倍数 0(Bypass)/1/2/3/4/8 + */ +void configTxFIR(int fir); +/** + * @brief 配置Tx HBF1滤波器插值倍数 + * @param hbf 插值倍数 0(Bypass)/2 + */ +void configTxHBF1(int hbf); +/** + * @brief 配置Tx HBF2滤波器插值倍数 + * @param hbf 插值倍数 0(Bypass)/2 + */ +void configTxHBF2(int hbf); +/** + * @brief 配置Tx HBF3滤波器插值倍数 + * @param hbf 插值倍数 0(Bypass)/2/3 + */ +void configTxHBF3(int hbf); +/** + * @brief 配置Tx CIC滤波器 + * @param cic 插值倍数 0(Bypass)/8/20/32/80 + */ +void configTxCIC(int cic); +/** + * @brief 配置Tx滤波器 + * @param filters Filters结构体 + */ +void configTxFilters(const Filters& filters); +/** + * @brief 配置Tx FIR滤波器系数 + * @param coe 滤波器系数,长度为16的整倍数,最大128 + */ +void configTxFIRCoe(const std::vector& coe); +/** + * @brief 读取当前Tx chan通道的校准值 + * @param chan Tx通道 + * @return 校准值结构体 + */ +CalibPredis readTxCalibPredis(TxChannel chan); +/** + * @brief 此函数为Demo板配套配置函数,用于配置FPGA接口,用户开发自己的程序时应重写对应功能 + * @param interface Interface结构体 + */ +void configFPGA(const Interface& interface); +} // namespace CX9261A + +#endif // CX9261ADRIVER_CX9261ADRIVER_H diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_1_9_0/defs.h b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_1_9_0/defs.h new file mode 100644 index 0000000..5d187df --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_1_9_0/defs.h @@ -0,0 +1,424 @@ +/** + * @file defs.h + */ + +#ifndef CX9261ADRIVER_DEFS_H +#define CX9261ADRIVER_DEFS_H + +#include +#include +#include + +#ifdef interface +# undef interface +#endif + +namespace CX9261A { +/** + * @brief 芯片工作模式 + */ +enum class WorkMode : std::uint8_t { Rx, Tx, FDD }; +/** + * @brief 收发数据通道数量 + * @note 此模式并不代表使用几个通道进行收发 + */ +enum class TrMode : std::uint8_t { R1T1, R2T2 }; +/** + * @brief 收发接口通道数量 + */ +enum class PortMode : std::uint8_t { Single, Dual }; +/** + * @brief 接口模式: + * CMOS CMOS接口模式, + * LVDS_S LVDS顺序模式, + * LVDS_E LVDS奇偶模式 + */ +enum class IOMode : std::uint8_t { CMOS, LVDS_S, LVDS_E }; +/** + * @brief 本振来源 + */ +enum class LoSource : std::uint8_t { + Pll1 = 0b00001, + Pll2 = 0b00010, + Pll3 = 0b00100, + Pll4 = 0b01000, + Pll5 = 0b10000, + Off = 0 +}; + +inline std::string toString(const LoSource source) +{ + switch (source) { + case LoSource::Pll1: + return "Pll1"; + case LoSource::Pll2: + return "Pll2"; + case LoSource::Pll3: + return "Pll3"; + case LoSource::Pll4: + return "Pll4"; + case LoSource::Pll5: + return "Pll5"; + default: + return "Off"; + } +} +/** + * @brief 接收通道 + */ +enum class RxChannel : std::uint8_t { Rx1 = 1, Rx2, Rx3 }; + +inline std::string toString(const RxChannel chan) +{ + switch (chan) { + case RxChannel::Rx1: + return "Rx1"; + case RxChannel::Rx2: + return "Rx2"; + case RxChannel::Rx3: + return "Rx3"; + default: + return "Unknown Channel"; + } +} +/** + * @brief 发射通道 + */ +enum class TxChannel : std::uint8_t { Tx1 = 1, Tx2 }; + +inline std::string toString(const TxChannel chan) +{ + switch (chan) { + case TxChannel::Tx1: + return "Tx1"; + case TxChannel::Tx2: + return "Tx2"; + default: + return "Unknown Channel"; + } +} +/** + * @brief 电源模式 + */ +enum class PowerMode : std::uint8_t { Shutdown = 0, Sleep, Alert, Calib, Receive, Transmit, Duplex, Obs }; +/** + * @brief NCO模式 + */ +enum class NCOMode : std::uint8_t { Bypass = 0, Up, Down, BIST, Master, Slaver }; +/** + * @brief 温补模式 DAC: DAC模式 Band: 跳子带模式 + */ +enum class TemperatureComp : std::uint8_t { DAC = 0, Band }; +/** + * @brief 校准方法 TST: 时域统计 Rx通道使用, Bisec: 二分法 Tx通道使用, MultiPoints: 多点校准 + */ +enum class CalibMethod : std::uint8_t { TST = 0, Bisec, MultiPoints, Tracking }; +/** + * @brief DC校准方法 Tracking: 跟踪校准 HighPass: 高通滤波器滤掉直流 + */ +enum class DCCalibMethod : std::uint8_t { Tracking = 0, HighPass }; +/** + * @brief AFC等待延时,单位ms + */ +constexpr double delay = 100; +/** + * @brief QEC等待延时,单位ms + */ +constexpr double qecDelay = 500; +/** + * @brief 接收通道本振来源映射表 + */ +static const std::map, std::bitset<7>> rxSrcMap = { + { { LoSource::Pll2, LoSource::Pll2 }, 0b0010000 }, { { LoSource::Pll1, LoSource::Pll1 }, 0b1101000 }, + { { LoSource::Pll2, LoSource::Pll1 }, 0b0100000 }, { { LoSource::Pll1, LoSource::Pll2 }, 0b1000000 }, + { { LoSource::Off, LoSource::Pll1 }, 0b0101010 }, { { LoSource::Off, LoSource::Pll2 }, 0b1010010 }, + { { LoSource::Pll1, LoSource::Off }, 0b1001001 }, { { LoSource::Pll2, LoSource::Off }, 0b0110001 }, + { { LoSource::Off, LoSource::Off }, 0b0011011 } +}; +/** + * @brief 发射通道本振来源映射表 + */ +static const std::map, std::bitset<11>> txSrcMap = { + { { LoSource::Pll4, LoSource::Pll4 }, 16 }, { { LoSource::Pll3, LoSource::Pll3 }, 104 }, + { { LoSource::Pll4, LoSource::Pll3 }, 32 }, { { LoSource::Pll3, LoSource::Pll4 }, 64 }, + { { LoSource::Pll2, LoSource::Pll2 }, 1560 }, { { LoSource::Pll1, LoSource::Pll1 }, 1944 }, + { { LoSource::Pll2, LoSource::Pll1 }, 1688 }, { { LoSource::Pll1, LoSource::Pll2 }, 1816 }, + { { LoSource::Off, LoSource::Pll3 }, 42 }, { { LoSource::Off, LoSource::Pll4 }, 82 }, + { { LoSource::Off, LoSource::Pll2 }, 794 }, { { LoSource::Off, LoSource::Pll1 }, 666 }, + { { LoSource::Pll3, LoSource::Off }, 73 }, { { LoSource::Pll4, LoSource::Off }, 49 }, + { { LoSource::Pll2, LoSource::Off }, 1177 }, { { LoSource::Pll1, LoSource::Off }, 1305 }, + { { LoSource::Off, LoSource::Off }, 27 }, { { LoSource::Pll1, LoSource::Pll3 }, 1320 }, + { { LoSource::Pll1, LoSource::Pll4 }, 1360 }, { { LoSource::Pll2, LoSource::Pll3 }, 1064 }, + { { LoSource::Pll2, LoSource::Pll4 }, 1104 }, { { LoSource::Pll3, LoSource::Pll1 }, 712 }, + { { LoSource::Pll4, LoSource::Pll1 }, 688 }, { { LoSource::Pll3, LoSource::Pll2 }, 584 }, + { { LoSource::Pll4, LoSource::Pll2 }, 560 } +}; +/** + * @brief 环路参数选择表 + */ +static const std::vector>> coreTable = { + { { 0x0C, 0x30, 0x08 }, { 0x0B, 0x30, 0x09 }, { 0x0C, 0x30, 0x05 }, { 0x0D, 0x30, 0x08 } }, + { { 0x0C, 0x30, 0x0C }, { 0x0B, 0x30, 0x0E }, { 0x0C, 0x30, 0x08 }, { 0x0D, 0x30, 0x0B } }, + { { 0x0C, 0x20, 0x10 }, { 0x0B, 0x20, 0x10 }, { 0x0C, 0x20, 0x0A }, { 0x0D, 0x20, 0x0D } }, + { { 0x0C, 0x20, 0x11 }, { 0x0B, 0x20, 0x13 }, { 0x0C, 0x20, 0x0C }, { 0x0D, 0x20, 0x0F } }, + { { 0x0D, 0x30, 0x14 }, { 0x0D, 0x22, 0x14 }, { 0x0D, 0x20, 0x0D }, { 0x0D, 0x15, 0x0C } }, + { { 0x0E, 0x30, 0x18 }, { 0x0E, 0x25, 0x16 }, { 0x0E, 0x25, 0x0F }, { 0x0E, 0x18, 0x0F } }, + { { 0x0F, 0x38, 0x1A }, { 0x0F, 0x32, 0x1C }, { 0x0F, 0x18, 0x12 }, { 0x0F, 0x18, 0x12 } } +}; + +/** + * @brief AGC PDT模式的结构体 + */ +struct AGCPDT +{ + int pdtN; + int pdtM; +}; + +/** + * @brief AGC LMT模式的结构体 + */ +struct AGCLMT +{ + int count; /**< LMT统计次数阈值*/ + int threshold1; /**< LMT阈值第一档*/ + int threshold2; /**< LMT阈值第二档*/ + int threshold3; /**< LMT阈值第三档*/ + int threshold4; /**< LMT阈值第四档*/ +}; + +/** + * @brief AGC DIG模式的结构体 + */ +struct AGCDIG +{ + int count; /**< DIG统计次数阈值*/ + int threshold1; /**< DIG阈值第一档*/ + int threshold2; /**< DIG阈值第二档*/ + int threshold3; /**< DIG阈值第三档*/ + int threshold4; /**< DIG阈值第四档*/ +}; + +/** + * @brief AGC模式的结构体 + */ +struct AGC +{ + int mode; /**< AGC模式选择*/ + AGCPDT pdt; /**< AGC PDT模式的结构体*/ + AGCLMT lmt; /**< AGC LMT模式的结构体*/ + AGCDIG dig; /**< AGC DIG模式的结构体*/ +}; + +/** + * @brief 时钟相关参数结构体 + */ +struct Clock +{ + double ref; /**< 参考时钟频率,单位MHz*/ + double adc; /**< ADC频率,单位MHz*/ + int refDiv; /**< 参考时钟分频比*/ + bool bbUseIntDiv; /**< 是否使用整数分频模式*/ + bool refDoubler; /**< 是否使用参考时钟倍频器*/ +}; + +/** + * @brief 校准相关参数结构体 + */ +struct Calib +{ + bool calibDC; /**< 是否开启DC Tracking*/ + DCCalibMethod dcCalibMethod; + int dcTrackingLength; /**< DC Tracking长度*/ + int dcHighPassFactor; /**< DC高通滤波系数,越大代表滤波器阶数越高,滤波范围越窄*/ + std::uint8_t rx1CalibPll; /**< rx1校准的pll选择,Pll1 | Pll2*/ + std::uint8_t rx2CalibPll; /**< rx2校准的pll选择,Pll1 | Pll2*/ + std::uint8_t rx3CalibPll; /**< rx3校准的pll选择,Pll5*/ + std::uint8_t tx1CalibPll; /**< tx1校准的pll选择,Pll1 | Pll2 | Pll3 | Pll4*/ + std::uint8_t tx2CalibPll; /**< tx2校准的pll选择,Pll1 | Pll2 | Pll3 | Pll4*/ + CalibMethod rxMethod; + CalibMethod txMethod; + double f0; /**< 校准音频率*/ + std::vector rxMultiPoints; /**< Rx多点校准的频率*/ + std::vector txMultiPoints; /**< Tx多点校准的频率*/ +}; + +/** + * @brief 配置PLL来源相关参数结构体 + */ +struct PllSource +{ + bool rxUseExt; /**< 接收通道是否使用外本振*/ + bool txUseExt; /**< 发射通道是否使用外本振*/ + LoSource rx1Source; /**< Rx1通道本振来源*/ + LoSource rx2Source; /**< Rx2通道本振来源*/ + LoSource rx3Source; /**< Rx3通道本振来源*/ + LoSource tx1Source; /**< Tx1通道本振来源*/ + LoSource tx2Source; /**< Tx2通道本振来源*/ +}; + +/** + * @brief 配置PLL频率相关参数结构体 + */ +struct PllFreq +{ + double pll1Freq; /**< PLL1本振时钟,单位MHz*/ + double pll2Freq; /**< PLL2本振时钟,单位MHz*/ + double pll3Freq; /**< PLL3本振时钟,单位MHz*/ + double pll4Freq; /**< PLL4本振时钟,单位MHz*/ + double pll5Freq; /**< PLL5本振时钟,单位MHz*/ + double rxExtFreq; /**< 接收通道使用外本振时,外本振频率,单位MHz*/ + double txExtFreq; /**< 发射通道使用外本振时,外本振频率,单位MHz*/ +}; + +/** + * @brief 配置接口相关参数结构体 + */ +struct Interface +{ + WorkMode workMode; /**< 芯片工作模式*/ + TrMode trMode; /**< 收发数据通道模式*/ + PortMode portMode; /**< 收发接口通道模式*/ + IOMode ioMode; /**< 接口电平模式*/ +}; + +/** + * @brief 配置TX NCO相关参数结构体 + */ +struct TxNCO +{ + bool txUseBist; /**< 是否开启BIST模式*/ + double txNCOFreq; /**< NCO频率*/ +}; + +/** + * @brief 配置RX NCO相关参数结构体 + */ +struct RxNCO +{ + bool rxUseBist; /**< 是否开启BIST模式*/ + bool rxNCOBypass; /**< 是否Bypass NCO*/ + bool rxNCOUpward; /**< 开启上/下混频模式*/ + bool rxNCOMaster; /**< 使用Master/Slaver模式*/ + double rxNCOFreq; /**< NCO频率*/ +}; + +/** + * @brief 配置接收通道相关参数结构体 + */ +struct RxConfig +{ + double bandwidth; /**< 接收通道1dB带宽,单位MHz*/ + int tia; /**< 接收通道TIA增益配置,推荐配置6*/ + int mixer; /**< 接收通道Mixer增益配置*/ +}; + +/** + * @brief 配置发射通道相关参数结构体 + */ +struct TxConfig +{ + double bandwidth; /**< 发射通道1dB带宽,单位MHz*/ + int mixer; /**< 发射通道Mixer增益配置*/ +}; + +/** + * @brief 配置滤波器相关参数结构体,0代表bypass + */ +struct Filters +{ + int fir; /**< FIR滤波器抽取/插值倍数*/ + int hbf1; /**< HBF1滤波器抽取/插值倍数*/ + int hbf2; /**< HBF2滤波器抽取/插值倍数*/ + int hbf3; /**< HBF3滤波器抽取/插值倍数*/ + int cic; /**< CIC滤波器抽取/插值倍数*/ +}; + +/** + * @brief 配置电源模式结构体,1代表该模块上电 + */ +struct Power +{ + bool dig_tx2; + bool dig_tx1; + bool dig_rx3; + bool dig_rx2; + bool dig_rx1; + bool fref1_rx; + bool auxadc2; + bool auxadc1; + bool auxdac; + bool temp_sensor; + bool bgr; + bool exlo; + bool tx2; + bool tx1; + bool rx3; + bool rx2; + bool rx1; + bool pll5_ldo; + bool pll5; + bool pll4_ldo; + bool pll4; + bool pll3_ldo; + bool pll3; + bool pll2_ldo; + bool pll2; + bool pll1_ldo; + bool pll1; + bool bbpll; +}; + +/** + * @brief 配置电源模式管理,包含模式选择,接收模式,发射模式,FDD模式 + */ +struct PowerManagement +{ + PowerMode powerMode; + Power rxPower; + Power txPower; + Power fddPower; +}; + +/** + * @brief 储存窄带校准结果的结构体 + */ +struct CalibPredis +{ + int bHigh; + int bLow; + int cHigh; + int cLow; + int dciHigh; + int dciLow; + int dcqHigh; + int dcqLow; +}; + +/** + * @brief CX9261A结构体 + */ +struct CX9261AConfiguration +{ + TemperatureComp tempComp; /**< 温度补偿*/ + AGC agc; /**< AGC结构体*/ + Interface interface; /**< Interface结构体*/ + Clock clock; /**< Clock结构体*/ + PllSource pllSource; /**< PllSource结构体*/ + Calib calib; /**< Calib结构体*/ + PllFreq pllFreq; /**< PllFreq结构体*/ + TxNCO txNco; /**< TxNCO结构体*/ + RxNCO rxNco; /**< RxNCO结构体*/ + RxConfig rx1Config; /**< RxConfig结构体*/ + RxConfig rx2Config; /**< RxConfig结构体*/ + RxConfig rx3Config; /**< RxConfig结构体*/ + TxConfig tx1Config; /**< TxConfig结构体*/ + TxConfig tx2Config; /**< TxConfig结构体*/ + Filters rxFilters; /**< Filters结构体*/ + Filters txFilters; /**< Filters结构体*/ + PowerManagement powerManagement; /**< PowerManagement结构体*/ + std::vector rxFIRCoe; /**< Rx FIR滤波器系数*/ + std::vector txFIRCoe; /**< Tx FIR滤波器系数*/ +}; +} // namespace CX9261A +#endif // CX9261ADRIVER_DEFS_H diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_1_9_0/main.cpp b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_1_9_0/main.cpp new file mode 100644 index 0000000..820a7a8 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_1_9_0/main.cpp @@ -0,0 +1,138 @@ +#include "cx9261adriver.h" +#include "defs.h" + +int main() { + + // 芯片配置结构体 + CX9261A::CX9261AConfiguration configuration; + // 电源管理 + // 接收模式电源管理 + configuration.powerManagement.rxPower = {0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1}; + // 发射模式电源管理 + configuration.powerManagement.txPower = {1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1}; + // FDD模式电源管理 + configuration.powerManagement.fddPower = {1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, + 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1}; + // 电源模式 即配置结束后的电源模式 + configuration.powerManagement.powerMode = CX9261A::PowerMode::Receive; + // 接口模式 + configuration.interface = {.workMode = CX9261A::WorkMode::Rx, + .trMode = CX9261A::TrMode::R1T1, + .portMode = CX9261A::PortMode::Single, + .ioMode = CX9261A::IOMode::CMOS}; + // 时钟相关 + configuration.clock = {.ref = 125, .adc = 64, .refDiv = 2, .bbUseIntDiv = false, .refDoubler = false}; + // 本振相关 + using LoSource = CX9261A::LoSource; + // 本振来源 + configuration.pllSource = {.rxUseExt = false, + .txUseExt = false, + .rx1Source = LoSource::Pll1, + .rx2Source = LoSource::Pll1, + .rx3Source = LoSource::Off, + .tx1Source = LoSource::Off, + .tx2Source = LoSource::Off}; + // 本振频率 注意:使用的所有PLL,频率必须设为正数 + configuration.pllFreq = { + .pll1Freq = 5800, .pll2Freq = 5800, .pll3Freq = 800, .pll4Freq = 900, .pll5Freq = 1000}; + // Rx通道 注意:tia推荐配置为6 Mixer为三个通道共用同一个寄存器 + configuration.rx1Config = {.bandwidth = 32, .tia = 6, .mixer = 31}; + configuration.rx2Config = {.bandwidth = 32, .tia = 6, .mixer = 31}; + configuration.rx3Config = {.bandwidth = 32, .tia = 6, .mixer = 31}; + // Tx通道 + configuration.tx1Config = {.bandwidth = 20, .mixer = 63}; + configuration.tx2Config = {.bandwidth = 20, .mixer = 63}; + // 接收滤波器 + configuration.rxFilters = {.fir = 0, .hbf1 = 0, .hbf2 = 0, .hbf3 = 0, .cic = 0}; + // 发射滤波器 + configuration.txFilters = {.fir = 0, .hbf1 = 2, .hbf2 = 2, .hbf3 = 0, .cic = 0}; + // Rx NCO + configuration.rxNco = { + .rxUseBist = false, .rxNCOBypass = true, .rxNCOUpward = true, .rxNCOMaster = true, .rxNCOFreq = 0}; + // Tx NCO + configuration.txNco = {.txUseBist = false, .txNCOFreq = 0}; + // AGC 注意:mode = 0表示关闭AGC,此时其他的参数可以不配置 + configuration.calib = { + .calibDC = true, + .dcCalibMethod = CX9261A::DCCalibMethod::Tracking, + .dcTrackingLength = 16384, + .dcHighPassFactor = 8191, + .rx1CalibPll = int(LoSource::Pll1) | int(LoSource::Pll2), + .rx2CalibPll = int(LoSource::Pll1) | int(LoSource::Pll2), + .rx3CalibPll = int(LoSource::Pll5), + .tx1CalibPll = 0, + .tx2CalibPll = 0, + .rxMethod = CX9261A::CalibMethod::MultiPoints, + .txMethod = CX9261A::CalibMethod::Bisec, + .f0 = 4 + }; + configuration.agc = {.mode = 0}; + // 校准 + configuration.calib.rxMultiPoints = {2200, 2400, 2600, 2800, 3000, 3200, 3400, 3600, 3800, 4000, 4200, + 4400, 4600, 4800, 5000, 5200, 5400, 5600, 5800, 6000}; + // 配置温补模式为跳子带温补 + configuration.tempComp = CX9261A::TemperatureComp::Band; + + // 开始配置芯片 + CX9261A::initialChip(); // 最开始需要调用此函数 + CX9261A::initialPowerConfig(configuration); + // 配置温补 + configTemperatureCompensation(configuration.tempComp); + using PowerMode = CX9261A::PowerMode; + // 不需要自定义电源管理时,这部分代码可以省略 + CX9261A::configPowerPins(configuration.powerManagement.rxPower, PowerMode::Receive); + CX9261A::configPowerPins(configuration.powerManagement.txPower, PowerMode::Transmit); + CX9261A::configPowerPins(configuration.powerManagement.fddPower, PowerMode::Duplex); + // 配置pll + CX9261A::configBBPLL(configuration); + CX9261A::configPllSource(configuration.pllSource); + CX9261A::configPll1(configuration.pllFreq.pll1Freq, configuration.clock); + CX9261A::configPll2(configuration.pllFreq.pll2Freq, configuration.clock); + // 配置Rx通道 + CX9261A::configRxChannel(configuration.rx1Config, CX9261A::RxChannel::Rx1); + CX9261A::configRxChannel(configuration.rx2Config, CX9261A::RxChannel::Rx2); + CX9261A::configRxChannel(configuration.rx3Config, CX9261A::RxChannel::Rx3); + // 配置Tx通道 + using TxChannel = CX9261A::TxChannel; + CX9261A::configTxChannelFrequency(configuration.pllFreq.pll1Freq, TxChannel::Tx1); + CX9261A::configTxChannelFrequency(configuration.pllFreq.pll2Freq, TxChannel::Tx2); + CX9261A::configTxChannel(configuration.tx1Config, TxChannel::Tx1); + CX9261A::configTxChannel(configuration.tx2Config, TxChannel::Tx2); + // 配置滤波器 + CX9261A::configRxFilters(configuration.rxFilters); + CX9261A::configTxFilters(configuration.txFilters); + // 配置NCO + CX9261A::configRxNco(configuration.rxNco, configuration.clock.adc); + const int filters = std::max(configuration.rxFilters.fir, 1) * std::max(configuration.rxFilters.hbf3, 1) * + std::max(configuration.rxFilters.hbf2, 1) * + std::max(configuration.rxFilters.hbf1, 1) * std::max(configuration.rxFilters.cic, 1); + CX9261A::configTxNco(configuration.txNco, configuration.clock.adc / filters); + // 配置AGC + CX9261A::configAGC(configuration.agc); + // 切换到休眠模式 + CX9261A::configPowerMode(PowerMode::Sleep); + CX9261A::pause(1000); + // 切换到校准模式 + CX9261A::configPowerMode(PowerMode::Calib); + CX9261A::pause(100); + // 锁定BBPLL + CX9261A::afcBBPll(); + // 配置校准 + CX9261A::configADCCalib(configuration.clock.adc); + CX9261A::configFlashCalib(); + configDcCalib(configuration.calib); + configQecCalib(configuration); + CX9261A::loadRxCalibPredis(0, CX9261A::RxChannel::Rx1, LoSource::Pll1); + CX9261A::loadRxCalibPredis(0, CX9261A::RxChannel::Rx2, LoSource::Pll1); + // 配置接口 + CX9261A::configInterface(configuration.interface); + // 配置FPGA接口相关 此为示例,仅适用于Demo工程,用户应根据实际情况进行配置 + CX9261A::configFPGA(configuration.interface); + // 锁定PLL1 + CX9261A::afcPll1(); + // 锁定PLL2 + CX9261A::afcPll2(); + return 0; +} \ No newline at end of file diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_1_9_0/utils.h b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_1_9_0/utils.h new file mode 100644 index 0000000..58058f7 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_1_9_0/utils.h @@ -0,0 +1,99 @@ +/** + * @file utils.h + */ + +#ifndef CX9261ADRIVER_UTILS_H +#define CX9261ADRIVER_UTILS_H +#include +#include +#include +#include +namespace CX9261A { +#if __cplusplus >= 201703L +template +constexpr const T& clamp(const T& v, const T& lo, const T& hi) { + return std::clamp(v, lo, hi); +} +#else +template +constexpr const T& clamp(const T& v, const T& lo, const T& hi) { + return std::max(std::min(hi, v), lo); +} +#endif + +template +int round(Float f) { + return static_cast(std::round(f)); +} + +template +long long round64(Float f) { + return static_cast(std::round(f)); +} + +template +int floor(Float f) { + return static_cast(std::floor(f)); +} + +template +long long floor64(Float f) { + return static_cast(std::floor(f)); +} + +template +int ceil(Float f) { + return static_cast(std::ceil(f)); +} + +template +long long ceil64(Float f) { + return static_cast(std::ceil(f)); +} +/** +* @brief Register类,提供方便的位操作函数 +*/ +class Register { +public: + template + constexpr Register(const T value = 0) { + static_assert(std::is_integral_v, "Register value must be integral!"); + m_value = static_cast(value); + } + /** + * 以十进制返回寄存器值 + */ + unsigned char value() const { return static_cast(m_value.to_ulong()); } + /** + * 对寄存器值进行部分值的替换操作 + * 例:replace(7, 4, 0b1111); 使寄存器的高四位为1 + * @param start 起始位 + * @param end 中止位 + * @param after 要替换的值 + */ + void replace(const unsigned int start, const unsigned int end, unsigned char after) { + for (auto i = end; i <= start; ++i) { + m_value[i] = (after >> (i - end)) & 0b1; + } + } + + auto operator[](const size_t position) { return m_value[position]; } + + template + operator Type() const { + static_assert(std::is_integral_v, "Type must be an integral"); + return static_cast(m_value.to_ulong()); + } + +private: + std::bitset<8> m_value{}; +}; + +template +std::string frac2bin(const double frac) { + const long double num = frac * (pow(2.0, N)); + std::string ret = std::bitset(std::floor(num)).to_string(); + return ret; +} +} // namespace CX9261A +#endif // CX9261ADRIVER_UTILS_H diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/config/app_config.h b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/config/app_config.h new file mode 100644 index 0000000..1334d12 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/config/app_config.h @@ -0,0 +1,331 @@ +/*****************************************************************************/ +/** + * Description: Global configurations. + * + * Date: 2021-04-28 13:19 + * Last Editors: Fan Hao + * Last Edit Time: [2022-05-23 20:32] + * + * Revisions: Rev 0.0 + * History: + * [2021-04-28]: Initial edition. + * + * Copyright(c) 2024 Beijing Institute of Technology. + * Lab of Communication and Networking + * + ******************************************************************************/ + +#ifndef __APP_CONFIG_H_ +#define __APP_CONFIG_H_ + +#define XILINX_PLATFORM + +#include "xparameters.h" + +/******** Software Version ********/ +#define _APP_VER 0x00010008 + +#define _APP_VER_MAIN ((_APP_VER & 0xFF000000) >> 24) +#define _APP_VER_MINOR ((_APP_VER & 0x00FF0000) >> 16) +#define _APP_VER_PATCH (_APP_VER & 0x0000FFFF) + +/*********** Debug Info Level ************/ +// #define _DEBUG_LEVEL 1 +// 3 - print all debug info +// 2 - print warnings and errors +// 1 - print only errors +// other - print nothing + +#define DATALINK_ENABLE_AUTORECONNECT +#define DATALINK_ENABLE_AUTOTIMESYNC +// #define DATALINK_ENABLE_BERTEST + +/************ Hardware Configs ************/ +#ifdef __aarch64__ // Zynq MPSoC (Zynq UltraScale+) +#define CPU_CLK_HZ XPAR_CPU_CORTEXA53_0_CPU_CLK_FREQ_HZ +#define FCLK_CLK0_HZ 100000000 +#define APP_TIMER_CLK_HZ FCLK_CLK0_HZ +#else // Zynq-7000 +#define CPU_CLK_HZ XPAR_CPU_CORTEXA9_0_CPU_CLK_FREQ_HZ +#define APP_TIMER_CLK_HZ (CPU_CLK_HZ / 2) +#define FCLK_CLK0_HZ 100000000 +#endif +/********* Zynq Platform Configs **********/ +// APP Timer (for logging) +#ifdef __aarch64__ // Zynq MPSoC (Zynq UltraScale+) +#define APPTIMER_DEVICE_ID XPAR_AXI_TIMER_DEVICE_ID +#define APPTIMER_INTR_ID XPAR_FABRIC_AXI_TIMER_INTERRUPT_INTR +#else +#define APPTIMER_DEVICE_ID XPAR_PS7_SCUTIMER_0_DEVICE_ID +#define APPTIMER_INTR_ID XPAR_SCUTIMER_INTR +#endif +// Physical Layer Configs +#define PHY_DEVICE_ID (0x01 | 0x00) +#define PHY_BASEADDR XPAR_PHYC_BASEADDR +#define PHY_BEAM_FORMING_ENABLE +// -- Antenna Bram Configs +#define PHY_ANTCONFIG_BRAM_DEVICE_ID XPAR_PHY_DATA_INTERFACE_ANT_CONFIG_BRAM_CTRL_DEVICE_ID +#define PHY_ANTINFO_BRAM_DEVICE_ID XPAR_PHY_DATA_INTERFACE_ANT_BEAM_BRAM_CTRL_DEVICE_ID +// -- Buffers +#define PHY_TXBUFF_BRAM_DEVICE_ID XPAR_PHY_DATA_INTERFACE_TX_FRAME_BRAM_CTRL_DEVICE_ID +#define PHY_RXBUFF_BRAM_DEVICE_ID XPAR_PHY_DATA_INTERFACE_RX_FRAME_BRAM_CTRL_DEVICE_ID +// -- Xadc +#define PHY_HW_SYSMON_DEVICE_ID XPAR_SYSTEM_MANAGEMENT_DEVICE_ID +// -- Interrupt id +#define PHY_INTR_ID XPAR_FABRIC_PHY_IRQ_INTR +#define PERIODIC_5MS_INTR_ID XPAR_FABRIC_PHY_5MS_DELAY_2MS_INTR + +// Time Controller Configs +#define TIME_CONTROLLER_BASEADDR XPAR_TMC_BASEADDR + +// System Bus Configs +#define SYSBUS_BASE_ADDR XPAR_SYSTEMBUS_BASEADDR +#define SYSBUS_TX_INTR_ID XPAR_FABRIC_SYSTEMBUS_TX_DONE_INTR +#define SYSBUS_RX_INTR_ID XPAR_FABRIC_SYSTEMBUS_RX_DONE_INTR + +// INTC configis +#define INTC_DEVICE_ID XPAR_SCUGIC_0_DEVICE_ID + +/********* Hardware Configurations **********/ + +// Clock Management Configuration +//#define HMC7044 +//#define AD9528 +//#define LMK04828 +//#define LMX2594_ADC +//#define LMX2594_DAC + +// RF Transceiver Configuration +//#define AD9361_REG +//#define AD9361_API +//#define RFSOC +#define CX9261A + +// ADC Configuration +//#define AD9653 +//#define AD9694 + +// RFSoC Configuration +#ifdef RFSOC +#define RFDC_DEVICE_ID XPAR_XRFDC_0_DEVICE_ID +#endif + +// AD9361 Configuration +#define SPI_INTERFACE_SPI_ENGINE +#define HAVE_SPLIT_GAIN_TABLE 1 /* only set to 0 in case split_gain_table_mode_enable = 0*/ +#define HAVE_TDD_SYNTH_TABLE 1 /* only set to 0 in case split_gain_table_mode_enable = 0*/ +#define AD9361_DEVICE 1 /* set it 1 if AD9361 device is used, 0 otherwise */ +#define AD9364_DEVICE 0 /* set it 1 if AD9364 device is used, 0 otherwise */ +#define AD9363A_DEVICE 0 /* set it 1 if AD9363A device is used, 0 otherwise */ +#define HAVE_VERBOSE_MESSAGES /* Recommended during development prints errors and warnings */ +// #define HAVE_DEBUG_MESSAGES /* For Debug purposes only */ +// -- AD9361 SPI Engine Configuration +#define AD9361_SPI_DEVICE_ID 0 +#define AD9361_SPI_ENGINE_REF_CLK FCLK_CLK0_HZ +#define AD9361_SPI_ENGINE_MAX_SPEED 5000000 +//#define AD9361_SPI_ENGINE_BASEADDR 0 +#define AD9361_SPI_ENGINE_BASEADDR 0 +#define AD9361_SPI_ENGINE_DATA_WIDTH 8 +#define AD9361_SPI_ENGINE_CS_DELAY 3 +#define AD9361_1_SPI_CS 0x01 +#define AD9361_2_SPI_CS 0x02 +#define AD9361_TIMEOUT_TH 2000 +// -- AD9361 GPIO Configurations +#define AD9361_GPIO_DEVICE_ID 0 +#define AD9361_GPIO_OFFSET 54 +#define AD9361_GPIO_INPUT 0 +#define AD9361_GPIO_OUTPUT 1 +#define AD9361_GPIO_DISABLE 0 +#define AD9361_GPIO_ENABLE 1 +// -- AD9361-1 +#define AD9361_1_TXNRX (AD9361_GPIO_OFFSET + 6) +#define AD9361_1_ENABLE (AD9361_GPIO_OFFSET + 7) +#define AD9361_1_EN_AGC (AD9361_GPIO_OFFSET + 8) +#define AD9361_1_RESET_B (AD9361_GPIO_OFFSET + 9) +#define AD9361_1_CTRL_OUT0 (AD9361_GPIO_OFFSET + 10) +#define AD9361_1_CTRL_OUT1 (AD9361_GPIO_OFFSET + 11) +#define AD9361_1_CTRL_OUT2 (AD9361_GPIO_OFFSET + 12) +#define AD9361_1_CTRL_OUT3 (AD9361_GPIO_OFFSET + 13) +#define AD9361_1_CTRL_OUT4 (AD9361_GPIO_OFFSET + 14) +#define AD9361_1_CTRL_OUT5 (AD9361_GPIO_OFFSET + 15) +#define AD9361_1_CTRL_OUT6 (AD9361_GPIO_OFFSET + 16) +#define AD9361_1_CTRL_OUT7 (AD9361_GPIO_OFFSET + 17) +#define AD9361_1_CTRL_IN0 (AD9361_GPIO_OFFSET + 18) +#define AD9361_1_CTRL_IN1 (AD9361_GPIO_OFFSET + 19) +#define AD9361_1_CTRL_IN2 (AD9361_GPIO_OFFSET + 20) +#define AD9361_1_CTRL_IN3 (AD9361_GPIO_OFFSET + 21) +// AD9361-2 +#define AD9361_2_TXNRX (AD9361_GPIO_OFFSET + 22) +#define AD9361_2_ENABLE (AD9361_GPIO_OFFSET + 23) +#define AD9361_2_EN_AGC (AD9361_GPIO_OFFSET + 24) +#define AD9361_2_RESET_B (AD9361_GPIO_OFFSET + 25) +#define AD9361_2_CTRL_OUT0 (AD9361_GPIO_OFFSET + 26) +#define AD9361_2_CTRL_OUT1 (AD9361_GPIO_OFFSET + 27) +#define AD9361_2_CTRL_OUT2 (AD9361_GPIO_OFFSET + 28) +#define AD9361_2_CTRL_OUT3 (AD9361_GPIO_OFFSET + 29) +#define AD9361_2_CTRL_OUT4 (AD9361_GPIO_OFFSET + 30) +#define AD9361_2_CTRL_OUT5 (AD9361_GPIO_OFFSET + 31) +#define AD9361_2_CTRL_OUT6 (AD9361_GPIO_OFFSET + 32) +#define AD9361_2_CTRL_OUT7 (AD9361_GPIO_OFFSET + 33) +#define AD9361_2_CTRL_IN0 (AD9361_GPIO_OFFSET + 34) +#define AD9361_2_CTRL_IN1 (AD9361_GPIO_OFFSET + 35) +#define AD9361_2_CTRL_IN2 (AD9361_GPIO_OFFSET + 36) +#define AD9361_2_CTRL_IN3 (AD9361_GPIO_OFFSET + 37) +// AD9361-Status Code +#define AD9361_SYNC (AD9361_GPIO_OFFSET + 38) +#define AD9361_RX_FIFO_RST (AD9361_GPIO_OFFSET + 39) +#define AD9361_1_CAL_START (AD9361_GPIO_OFFSET + 40) +#define AD9361_2_CAL_START (AD9361_GPIO_OFFSET + 41) +#define AD9361_RECAL (AD9361_GPIO_OFFSET + 42) +#define AD9361_TX_SWITCH (AD9361_GPIO_OFFSET + 43) +#define AD9361_1_CAL_DONE (AD9361_GPIO_OFFSET + 44) +#define AD9361_2_CAL_DONE (AD9361_GPIO_OFFSET + 45) +#define AD9361_CAL_RESULT (AD9361_GPIO_OFFSET + 46) + +typedef enum +{ + TX_FREQ_125, + TX_FREQ_126, + TX_FREQ_4125 +} ad9361TxFreq; + +// CX9261A Configurations +#define CX9261A_GPIO_DEVICE_ID 0 +#define CX9261A_GPIO_OFFSET 54 +#define CX9261A_NRST (CX9261A_GPIO_OFFSET+0) +#define CX9261A_TXNRX_TRX1 (CX9261A_GPIO_OFFSET+1) +#define CX9261A_TXNRX_TRX2 (CX9261A_GPIO_OFFSET+2) +#define CX9261A_TXNRX_RXFB (CX9261A_GPIO_OFFSET+3) +#define CX9261A_ENABLE_TRX1 (CX9261A_GPIO_OFFSET+4) +#define CX9261A_ENABLE_TRX2 (CX9261A_GPIO_OFFSET+5) +#define CX9261A_ENABLE_RXFB (CX9261A_GPIO_OFFSET+6) +#define CX9261A_PL_RST (CX9261A_GPIO_OFFSET+7) +#define CX9261A_TR_SEL (CX9261A_GPIO_OFFSET+8) +#define CX9261A_TDD_FDD_SEL (CX9261A_GPIO_OFFSET+9) +#define CX9261A_R1T1_R2T2_SEL (CX9261A_GPIO_OFFSET+10) +#define CX9261A_SP_DP_SEL (CX9261A_GPIO_OFFSET+11) +#define CX9261A_MCLK_DELAY_CTRL0 (CX9261A_GPIO_OFFSET+12) +#define CX9261A_MCLK_DELAY_CTRL1 (CX9261A_GPIO_OFFSET+13) +#define CX9261A_MCLK_DELAY_CTRL2 (CX9261A_GPIO_OFFSET+14) +#define CX9261A_HOP_FLAG (CX9261A_GPIO_OFFSET+15) +// -- CX9261A SPI Engine Configuration +#define CX9261A_SPI_DEVICE_ID 0 +#define CX9261A_SPI_ENGINE_REF_CLK FCLK_CLK0_HZ +#define CX9261A_SPI_ENGINE_MAX_SPEED 5000000 +//#define CX9261A_SPI_ENGINE_BASEADDR 0 +#define CX9261A_SPI_ENGINE_BASEADDR 0 +#define CX9261A_SPI_ENGINE_DATA_WIDTH 8 +#define CX9261A_SPI_ENGINE_CS_DELAY 3 +#define CX9261A_SPI_CS 0x00 + +// HMC7044 Configurations +#define HMC7044_GPIO_DEVICE_ID 0 +#define HMC7044_GPIO_OFFSET 54 +#define HMC7044_RESET (HMC7044_GPIO_OFFSET + 0) +#define HMC7044_SYNC (HMC7044_GPIO_OFFSET + 1) +#define HMC7044_GPIO_0 (HMC7044_GPIO_OFFSET + 2) +#define HMC7044_GPIO_1 (HMC7044_GPIO_OFFSET + 3) +#define HMC7044_GPIO_2 (HMC7044_GPIO_OFFSET + 4) +#define HMC7044_GPIO_3 (HMC7044_GPIO_OFFSET + 5) +// -- HMC7044 SPI Engine Configuration +#define HMC7044_SPI_DEVICE_ID 0 +#define HMC7044_SPI_ENGINE_REF_CLK FCLK_CLK0_HZ +#define HMC7044_SPI_ENGINE_MAX_SPEED 5000000 +#define HMC7044_SPI_ENGINE_BASEADDR 0 +#define HMC7044_SPI_ENGINE_DATA_WIDTH 8 +#define HMC7044_SPI_ENGINE_CS_DELAY 3 +#define HMC7044_SPI_CS 0x00 + +// AD9528 Configurations +#define AD9528_GPIO_DEVICE_ID 0 +#define AD9528_GPIO_OFFSET 54 +#define AD9528_RESETB (AD9528_GPIO_OFFSET+0) +#define AD9528_SYSREF_REQ (AD9528_GPIO_OFFSET+1) +#define AD9528_STATUS_0 (AD9528_GPIO_OFFSET+2) +#define AD9528_STATUS_1 (AD9528_GPIO_OFFSET+3) +// -- AD9528 SPI Engine Configuration +#define AD9528_SPI_DEVICE_ID 0 +#define AD9528_SPI_ENGINE_REF_CLK FCLK_CLK0_HZ +#define AD9528_SPI_ENGINE_MAX_SPEED 5000000 +//#define AD9528_SPI_ENGINE_BASEADDR 0 +#define AD9528_SPI_ENGINE_BASEADDR 0 +#define AD9528_SPI_ENGINE_DATA_WIDTH 8 +#define AD9528_SPI_ENGINE_CS_DELAY 3 +#define AD9528_SPI_CS 0x00 + +// LMK04828 Configurations +#define LMK04828_GPIO_DEVICE_ID 0 +#define LMK04828_GPIO_OFFSET 54 +// -- LMK04828 SPI Engine Configuration +#define LMK04828_SPI_DEVICE_ID 0 +#define LMK04828_SPI_ENGINE_REF_CLK FCLK_CLK0_HZ +#define LMK04828_SPI_ENGINE_MAX_SPEED 5000000 +#define LMK04828_SPI_ENGINE_BASEADDR 0 +#define LMK04828_SPI_ENGINE_DATA_WIDTH 8 +#define LMK04828_SPI_ENGINE_CS_DELAY 3 +#define LMK04828_SPI_CS 0x00 + +// LMX2594_ADC Configurations +#define LMX2594_ADC_GPIO_DEVICE_ID 0 +#define LMX2594_ADC_GPIO_OFFSET 54 +// -- LMX2594_ADC SPI Engine Configuration +#define LMX2594_ADC_SPI_DEVICE_ID 0 +#define LMX2594_ADC_SPI_ENGINE_REF_CLK FCLK_CLK0_HZ +#define LMX2594_ADC_SPI_ENGINE_MAX_SPEED 5000000 +#define LMX2594_ADC_SPI_ENGINE_BASEADDR 0 +#define LMX2594_ADC_SPI_ENGINE_DATA_WIDTH 8 +#define LMX2594_ADC_SPI_ENGINE_CS_DELAY 3 +#define LMX2594_ADC_SPI_CS 0x01 + +// LMX2594_DAC Configurations +#define LMX2594_DAC_GPIO_DEVICE_ID 0 +#define LMX2594_DAC_GPIO_OFFSET 54 +// -- LMX2594_DAC SPI Engine Configuration +#define LMX2594_DAC_SPI_DEVICE_ID 0 +#define LMX2594_DAC_SPI_ENGINE_REF_CLK FCLK_CLK0_HZ +#define LMX2594_DAC_SPI_ENGINE_MAX_SPEED 5000000 +#define LMX2594_DAC_SPI_ENGINE_BASEADDR 0 +#define LMX2594_DAC_SPI_ENGINE_DATA_WIDTH 8 +#define LMX2594_DAC_SPI_ENGINE_CS_DELAY 3 +#define LMX2594_DAC_SPI_CS 0x02 + +// AD9653 Configurations +#define AD9653_GPIO_DEVICE_ID 0 +#define AD9653_GPIO_OFFSET 54 +#define AD9653_POWR_DOWN (AD9653_GPIO_OFFSET+0) +// -- AD9653 SPI Engine Configuration +#define AD9653_SPI_DEVICE_ID 0 +#define AD9653_SPI_ENGINE_REF_CLK FCLK_CLK0_HZ +#define AD9653_SPI_ENGINE_MAX_SPEED 5000000 +//#define AD9653_SPI_ENGINE_BASEADDR 0 +#define AD9653_SPI_ENGINE_BASEADDR 0 +#define AD9653_SPI_ENGINE_DATA_WIDTH 8 +#define AD9653_SPI_ENGINE_CS_DELAY 3 +#define AD9653_SPI_CS 0x03 + +// AD9694 Configurations +#define AD9694_GPIO_DEVICE_ID 0 +#define AD9694_GPIO_OFFSET 54 +// -- AD9694 SPI Engine Configuration +#define AD9694_SPI_DEVICE_ID 0 +#define AD9694_SPI_ENGINE_REF_CLK FCLK_CLK0_HZ +#define AD9694_SPI_ENGINE_MAX_SPEED 5000000 +//#define AD9694_SPI_ENGINE_BASEADDR 0 +#define AD9694_SPI_ENGINE_BASEADDR 0 +#define AD9694_SPI_ENGINE_DATA_WIDTH 8 +#define AD9694_SPI_ENGINE_CS_DELAY 3 +#define AD9694_SPI_CS 0x03 + +// Configuration Check +#if defined(PHY_BEAM_SET_PRESET) && !defined(PHY_BEAM_FORMING_ENABLE) +#define PHY_BEAM_FORMING_ENABLE +#warning To impliment beam scan must enable beam forming... +#endif + +#if defined(DATALINK_ENABLE_BERTEST) +#if !defined(DATALINK_ENABLE_AUTOTIMESYNC) +#warning To enbale bit error rate test, auto time-sync should be enabled... +#endif +#endif + +#endif //__APP_CONFIG_H_ diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/dev_profile/ad9361_profile.c b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/dev_profile/ad9361_profile.c new file mode 100644 index 0000000..a5d6817 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/dev_profile/ad9361_profile.c @@ -0,0 +1,340 @@ +#include "dev_profile.h" +#include "../config/app_config.h" +#include "../drivers/rf-transceiver/ad9361/ad9361_api.h" +#include "../drivers/axi_core/spi_engine/spi_engine.h" +#include "../drivers/platform/xilinx_gpio.h" + +struct spi_engine_init_param spi_engine_param = { + .ref_clk_hz = AD9361_SPI_ENGINE_REF_CLK, + .type = SPI_ENGINE, + .spi_engine_baseaddr = AD9361_SPI_ENGINE_BASEADDR, + .cs_delay = AD9361_SPI_ENGINE_CS_DELAY, + .data_width = AD9361_SPI_ENGINE_DATA_WIDTH +}; + +struct xil_gpio_init_param xil_gpio_param = { + .type = GPIO_PS, + .device_id = AD9361_GPIO_DEVICE_ID +}; + +AD9361_InitParam ad9361_default_init_param = { + /* Device selection */ + ID_AD9361, // dev_sel + /* Reference Clock */ + 48000000UL, //reference_clk_rate + /* Base Configuration */ + 1, //two_rx_two_tx_mode_enable *** adi,2rx-2tx-mode-enable + 1, //one_rx_one_tx_mode_use_rx_num *** adi,1rx-1tx-mode-use-rx-num + 1, //one_rx_one_tx_mode_use_tx_num *** adi,1rx-1tx-mode-use-tx-num + 1, //frequency_division_duplex_mode_enable *** adi,frequency-division-duplex-mode-enable + 0, //frequency_division_duplex_independent_mode_enable *** adi,frequency-division-duplex-independent-mode-enable + 0, //tdd_use_dual_synth_mode_enable *** adi,tdd-use-dual-synth-mode-enable + 0, //tdd_skip_vco_cal_enable *** adi,tdd-skip-vco-cal-enable + 0, //tx_fastlock_delay_ns *** adi,tx-fastlock-delay-ns + 0, //rx_fastlock_delay_ns *** adi,rx-fastlock-delay-ns + 0, //rx_fastlock_pincontrol_enable *** adi,rx-fastlock-pincontrol-enable + 0, //tx_fastlock_pincontrol_enable *** adi,tx-fastlock-pincontrol-enable + 0, //external_rx_lo_enable *** adi,external-rx-lo-enable + 0, //external_tx_lo_enable *** adi,external-tx-lo-enable + 5, //dc_offset_tracking_update_event_mask *** adi,dc-offset-tracking-update-event-mask + 6, //dc_offset_attenuation_high_range *** adi,dc-offset-attenuation-high-range + 5, //dc_offset_attenuation_low_range *** adi,dc-offset-attenuation-low-range + 0x28, //dc_offset_count_high_range *** adi,dc-offset-count-high-range + 0x32, //dc_offset_count_low_range *** adi,dc-offset-count-low-range + 0, //split_gain_table_mode_enable *** adi,split-gain-table-mode-enable + MAX_SYNTH_FREF, //trx_synthesizer_target_fref_overwrite_hz *** adi,trx-synthesizer-target-fref-overwrite-hz + 0, // qec_tracking_slow_mode_enable *** adi,qec-tracking-slow-mode-enable + /* ENSM Control */ + 0, //ensm_enable_pin_pulse_mode_enable *** adi,ensm-enable-pin-pulse-mode-enable + 0, //ensm_enable_txnrx_control_enable *** adi,ensm-enable-txnrx-control-enable + /* LO Control */ + 4125000000UL, //rx_synthesizer_frequency_hz *** adi,rx-synthesizer-frequency-hz + 4126000000UL, //tx_synthesizer_frequency_hz *** adi,tx-synthesizer-frequency-hz + 1, //tx_lo_powerdown_managed_enable *** adi,tx-lo-powerdown-managed-enable + /* Rate & BW Control */ + {768000000, 192000000, 96000000, 48000000, 24000000, 24000000},// rx_path_clock_frequencies[6] *** adi,rx-path-clock-frequencies + {768000000, 192000000, 96000000, 48000000, 24000000, 24000000},// tx_path_clock_frequencies[6] *** adi,tx-path-clock-frequencies + 18000000,//rf_rx_bandwidth_hz *** adi,rf-rx-bandwidth-hz + 18000000,//rf_tx_bandwidth_hz *** adi,rf-tx-bandwidth-hz + /* RF Port Control */ + 0, //rx_rf_port_input_select *** adi,rx-rf-port-input-select + 0, //tx_rf_port_input_select *** adi,tx-rf-port-input-select + /* TX Attenuation Control */ + 10000, //tx_attenuation_mdB *** adi,tx-attenuation-mdB + 0, //update_tx_gain_in_alert_enable *** adi,update-tx-gain-in-alert-enable + /* Reference Clock Control */ + 0, //xo_disable_use_ext_refclk_enable *** adi,xo-disable-use-ext-refclk-enable + {8, 5920}, //dcxo_coarse_and_fine_tune[2] *** adi,dcxo-coarse-and-fine-tune + CLKOUT_DISABLE, //clk_output_mode_select *** adi,clk-output-mode-select + /* Gain Control */ + 2, //gc_rx1_mode *** adi,gc-rx1-mode + 2, //gc_rx2_mode *** adi,gc-rx2-mode + 58, //gc_adc_large_overload_thresh *** adi,gc-adc-large-overload-thresh + 4, //gc_adc_ovr_sample_size *** adi,gc-adc-ovr-sample-size + 47, //gc_adc_small_overload_thresh *** adi,gc-adc-small-overload-thresh + 8192, //gc_dec_pow_measurement_duration *** adi,gc-dec-pow-measurement-duration + 0, //gc_dig_gain_enable *** adi,gc-dig-gain-enable + 800, //gc_lmt_overload_high_thresh *** adi,gc-lmt-overload-high-thresh + 704, //gc_lmt_overload_low_thresh *** adi,gc-lmt-overload-low-thresh + 24, //gc_low_power_thresh *** adi,gc-low-power-thresh + 15, //gc_max_dig_gain *** adi,gc-max-dig-gain + 0, //gc_use_rx_fir_out_for_dec_pwr_meas_enable *** adi,gc-use-rx-fir-out-for-dec-pwr-meas-enable + /* Gain MGC Control */ + 2, //mgc_dec_gain_step *** adi,mgc-dec-gain-step + 2, //mgc_inc_gain_step *** adi,mgc-inc-gain-step + 0, //mgc_rx1_ctrl_inp_enable *** adi,mgc-rx1-ctrl-inp-enable + 0, //mgc_rx2_ctrl_inp_enable *** adi,mgc-rx2-ctrl-inp-enable + 0, //mgc_split_table_ctrl_inp_gain_mode *** adi,mgc-split-table-ctrl-inp-gain-mode + /* Gain AGC Control */ + 10, //agc_adc_large_overload_exceed_counter *** adi,agc-adc-large-overload-exceed-counter + 2, //agc_adc_large_overload_inc_steps *** adi,agc-adc-large-overload-inc-steps + 0, //agc_adc_lmt_small_overload_prevent_gain_inc_enable *** adi,agc-adc-lmt-small-overload-prevent-gain-inc-enable + 10, //agc_adc_small_overload_exceed_counter *** adi,agc-adc-small-overload-exceed-counter + 4, //agc_dig_gain_step_size *** adi,agc-dig-gain-step-size + 3, //agc_dig_saturation_exceed_counter *** adi,agc-dig-saturation-exceed-counter + 1000, // agc_gain_update_interval_us *** adi,agc-gain-update-interval-us + 0, //agc_immed_gain_change_if_large_adc_overload_enable *** adi,agc-immed-gain-change-if-large-adc-overload-enable + 0, //agc_immed_gain_change_if_large_lmt_overload_enable *** adi,agc-immed-gain-change-if-large-lmt-overload-enable + 10, //agc_inner_thresh_high *** adi,agc-inner-thresh-high + 1, //agc_inner_thresh_high_dec_steps *** adi,agc-inner-thresh-high-dec-steps + 12, //agc_inner_thresh_low *** adi,agc-inner-thresh-low + 1, //agc_inner_thresh_low_inc_steps *** adi,agc-inner-thresh-low-inc-steps + 10, //agc_lmt_overload_large_exceed_counter *** adi,agc-lmt-overload-large-exceed-counter + 2, //agc_lmt_overload_large_inc_steps *** adi,agc-lmt-overload-large-inc-steps + 10, //agc_lmt_overload_small_exceed_counter *** adi,agc-lmt-overload-small-exceed-counter + 5, //agc_outer_thresh_high *** adi,agc-outer-thresh-high + 2, //agc_outer_thresh_high_dec_steps *** adi,agc-outer-thresh-high-dec-steps + 18, //agc_outer_thresh_low *** adi,agc-outer-thresh-low + 2, //agc_outer_thresh_low_inc_steps *** adi,agc-outer-thresh-low-inc-steps + 1, //agc_attack_delay_extra_margin_us; *** adi,agc-attack-delay-extra-margin-us + 0, //agc_sync_for_gain_counter_enable *** adi,agc-sync-for-gain-counter-enable + /* Fast AGC */ + 64, //fagc_dec_pow_measuremnt_duration *** adi,fagc-dec-pow-measurement-duration + 260, //fagc_state_wait_time_ns *** adi,fagc-state-wait-time-ns + /* Fast AGC - Low Power */ + 0, //fagc_allow_agc_gain_increase *** adi,fagc-allow-agc-gain-increase-enable + 5, //fagc_lp_thresh_increment_time *** adi,fagc-lp-thresh-increment-time + 1, //fagc_lp_thresh_increment_steps *** adi,fagc-lp-thresh-increment-steps + /* Fast AGC - Lock Level (Lock Level is set via slow AGC inner high threshold) */ + 1, //fagc_lock_level_lmt_gain_increase_en *** adi,fagc-lock-level-lmt-gain-increase-enable + 5, //fagc_lock_level_gain_increase_upper_limit *** adi,fagc-lock-level-gain-increase-upper-limit + /* Fast AGC - Peak Detectors and Final Settling */ + 1, //fagc_lpf_final_settling_steps *** adi,fagc-lpf-final-settling-steps + 1, //fagc_lmt_final_settling_steps *** adi,fagc-lmt-final-settling-steps + 3, //fagc_final_overrange_count *** adi,fagc-final-overrange-count + /* Fast AGC - Final Power Test */ + 0, //fagc_gain_increase_after_gain_lock_en *** adi,fagc-gain-increase-after-gain-lock-enable + /* Fast AGC - Unlocking the Gain */ + 0, //fagc_gain_index_type_after_exit_rx_mode *** adi,fagc-gain-index-type-after-exit-rx-mode + 1, //fagc_use_last_lock_level_for_set_gain_en *** adi,fagc-use-last-lock-level-for-set-gain-enable + 1, //fagc_rst_gla_stronger_sig_thresh_exceeded_en *** adi,fagc-rst-gla-stronger-sig-thresh-exceeded-enable + 5, //fagc_optimized_gain_offset *** adi,fagc-optimized-gain-offset + 10, //fagc_rst_gla_stronger_sig_thresh_above_ll *** adi,fagc-rst-gla-stronger-sig-thresh-above-ll + 1, //fagc_rst_gla_engergy_lost_sig_thresh_exceeded_en *** adi,fagc-rst-gla-engergy-lost-sig-thresh-exceeded-enable + 1, //fagc_rst_gla_engergy_lost_goto_optim_gain_en *** adi,fagc-rst-gla-engergy-lost-goto-optim-gain-enable + 10, //fagc_rst_gla_engergy_lost_sig_thresh_below_ll *** adi,fagc-rst-gla-engergy-lost-sig-thresh-below-ll + 8, //fagc_energy_lost_stronger_sig_gain_lock_exit_cnt *** adi,fagc-energy-lost-stronger-sig-gain-lock-exit-cnt + 1, //fagc_rst_gla_large_adc_overload_en *** adi,fagc-rst-gla-large-adc-overload-enable + 1, //fagc_rst_gla_large_lmt_overload_en *** adi,fagc-rst-gla-large-lmt-overload-enable + 0, //fagc_rst_gla_en_agc_pulled_high_en *** adi,fagc-rst-gla-en-agc-pulled-high-enable + 0, //fagc_rst_gla_if_en_agc_pulled_high_mode *** adi,fagc-rst-gla-if-en-agc-pulled-high-mode + 64, //fagc_power_measurement_duration_in_state5 *** adi,fagc-power-measurement-duration-in-state5 + 2, //fagc_large_overload_inc_steps *** adi,fagc-adc-large-overload-inc-steps + /* RSSI Control */ + 1, //rssi_delay *** adi,rssi-delay + 1000, //rssi_duration *** adi,rssi-duration + 3, //rssi_restart_mode *** adi,rssi-restart-mode + 0, //rssi_unit_is_rx_samples_enable *** adi,rssi-unit-is-rx-samples-enable + 1, //rssi_wait *** adi,rssi-wait + /* Aux ADC Control */ + 256, //aux_adc_decimation *** adi,aux-adc-decimation + 48000000UL, //aux_adc_rate *** adi,aux-adc-rate + /* AuxDAC Control */ + 1, //aux_dac_manual_mode_enable *** adi,aux-dac-manual-mode-enable + 0, //aux_dac1_default_value_mV *** adi,aux-dac1-default-value-mV + 0, //aux_dac1_active_in_rx_enable *** adi,aux-dac1-active-in-rx-enable + 0, //aux_dac1_active_in_tx_enable *** adi,aux-dac1-active-in-tx-enable + 0, //aux_dac1_active_in_alert_enable *** adi,aux-dac1-active-in-alert-enable + 0, //aux_dac1_rx_delay_us *** adi,aux-dac1-rx-delay-us + 0, //aux_dac1_tx_delay_us *** adi,aux-dac1-tx-delay-us + 0, //aux_dac2_default_value_mV *** adi,aux-dac2-default-value-mV + 0, //aux_dac2_active_in_rx_enable *** adi,aux-dac2-active-in-rx-enable + 0, //aux_dac2_active_in_tx_enable *** adi,aux-dac2-active-in-tx-enable + 0, //aux_dac2_active_in_alert_enable *** adi,aux-dac2-active-in-alert-enable + 0, //aux_dac2_rx_delay_us *** adi,aux-dac2-rx-delay-us + 0, //aux_dac2_tx_delay_us *** adi,aux-dac2-tx-delay-us + /* Temperature Sensor Control */ + 256, //temp_sense_decimation *** adi,temp-sense-decimation + 1000, //temp_sense_measurement_interval_ms *** adi,temp-sense-measurement-interval-ms + 0xCE, //temp_sense_offset_signed *** adi,temp-sense-offset-signed + 1, //temp_sense_periodic_measurement_enable *** adi,temp-sense-periodic-measurement-enable + /* Control Out Setup */ + 0xFF, //ctrl_outs_enable_mask *** adi,ctrl-outs-enable-mask + 0, //ctrl_outs_index *** adi,ctrl-outs-index + /* External LNA Control */ + 0, //elna_settling_delay_ns *** adi,elna-settling-delay-ns + 0, //elna_gain_mdB *** adi,elna-gain-mdB + 0, //elna_bypass_loss_mdB *** adi,elna-bypass-loss-mdB + 0, //elna_rx1_gpo0_control_enable *** adi,elna-rx1-gpo0-control-enable + 0, //elna_rx2_gpo1_control_enable *** adi,elna-rx2-gpo1-control-enable + 0, //elna_gaintable_all_index_enable *** adi,elna-gaintable-all-index-enable + /* Digital Interface Control */ + 0, //digital_interface_tune_skip_mode *** adi,digital-interface-tune-skip-mode + 0, //digital_interface_tune_fir_disable *** adi,digital-interface-tune-fir-disable + 1, //pp_tx_swap_enable *** adi,pp-tx-swap-enable + 1, //pp_rx_swap_enable *** adi,pp-rx-swap-enable + 0, //tx_channel_swap_enable *** adi,tx-channel-swap-enable + 0, //rx_channel_swap_enable *** adi,rx-channel-swap-enable + 1, //rx_frame_pulse_mode_enable *** adi,rx-frame-pulse-mode-enable + 0, //two_t_two_r_timing_enable *** adi,2t2r-timing-enable + 0, //invert_data_bus_enable *** adi,invert-data-bus-enable + 0, //invert_data_clk_enable *** adi,invert-data-clk-enable + 0, //fdd_alt_word_order_enable *** adi,fdd-alt-word-order-enable + 0, //invert_rx_frame_enable *** adi,invert-rx-frame-enable + 0, //fdd_rx_rate_2tx_enable *** adi,fdd-rx-rate-2tx-enable + 0, //swap_ports_enable *** adi,swap-ports-enable + 0, //single_data_rate_enable *** adi,single-data-rate-enable + 1, //lvds_mode_enable *** adi,lvds-mode-enable + 0, //half_duplex_mode_enable *** adi,half-duplex-mode-enable + 0, //single_port_mode_enable *** adi,single-port-mode-enable + 0, //full_port_enable *** adi,full-port-enable + 0, //full_duplex_swap_bits_enable *** adi,full-duplex-swap-bits-enable + 0, //delay_rx_data *** adi,delay-rx-data + 0, //rx_data_clock_delay *** adi,rx-data-clock-delay + 4, //rx_data_delay *** adi,rx-data-delay + 7, //tx_fb_clock_delay *** adi,tx-fb-clock-delay + 0, //tx_data_delay *** adi,tx-data-delay + 150, //lvds_bias_mV *** adi,lvds-bias-mV + 1, //lvds_rx_onchip_termination_enable *** adi,lvds-rx-onchip-termination-enable + 0, //rx1rx2_phase_inversion_en *** adi,rx1-rx2-phase-inversion-enable + 0xFF, //lvds_invert1_control *** adi,lvds-invert1-control + 0x0F, //lvds_invert2_control *** adi,lvds-invert2-control + /* GPO Control */ + 0, //gpo_manual_mode_enable *** adi,gpo-manual-mode-enable + 0, //gpo_manual_mode_enable_mask *** adi,gpo-manual-mode-enable-mask + 0, //gpo0_inactive_state_high_enable *** adi,gpo0-inactive-state-high-enable + 0, //gpo1_inactive_state_high_enable *** adi,gpo1-inactive-state-high-enable + 0, //gpo2_inactive_state_high_enable *** adi,gpo2-inactive-state-high-enable + 0, //gpo3_inactive_state_high_enable *** adi,gpo3-inactive-state-high-enable + 0, //gpo0_slave_rx_enable *** adi,gpo0-slave-rx-enable + 0, //gpo0_slave_tx_enable *** adi,gpo0-slave-tx-enable + 0, //gpo1_slave_rx_enable *** adi,gpo1-slave-rx-enable + 0, //gpo1_slave_tx_enable *** adi,gpo1-slave-tx-enable + 0, //gpo2_slave_rx_enable *** adi,gpo2-slave-rx-enable + 0, //gpo2_slave_tx_enable *** adi,gpo2-slave-tx-enable + 0, //gpo3_slave_rx_enable *** adi,gpo3-slave-rx-enable + 0, //gpo3_slave_tx_enable *** adi,gpo3-slave-tx-enable + 0, //gpo0_rx_delay_us *** adi,gpo0-rx-delay-us + 0, //gpo0_tx_delay_us *** adi,gpo0-tx-delay-us + 0, //gpo1_rx_delay_us *** adi,gpo1-rx-delay-us + 0, //gpo1_tx_delay_us *** adi,gpo1-tx-delay-us + 0, //gpo2_rx_delay_us *** adi,gpo2-rx-delay-us + 0, //gpo2_tx_delay_us *** adi,gpo2-tx-delay-us + 0, //gpo3_rx_delay_us *** adi,gpo3-rx-delay-us + 0, //gpo3_tx_delay_us *** adi,gpo3-tx-delay-us + /* Tx Monitor Control */ + 37000, //low_high_gain_threshold_mdB *** adi,txmon-low-high-thresh + 0, //low_gain_dB *** adi,txmon-low-gain + 24, //high_gain_dB *** adi,txmon-high-gain + 0, //tx_mon_track_en *** adi,txmon-dc-tracking-enable + 0, //one_shot_mode_en *** adi,txmon-one-shot-mode-enable + 511, //tx_mon_delay *** adi,txmon-delay + 8192, //tx_mon_duration *** adi,txmon-duration + 2, //tx1_mon_front_end_gain *** adi,txmon-1-front-end-gain + 2, //tx2_mon_front_end_gain *** adi,txmon-2-front-end-gain + 48, //tx1_mon_lo_cm *** adi,txmon-1-lo-cm + 48, //tx2_mon_lo_cm *** adi,txmon-2-lo-cm + /* GPIO definitions */ + /* Reset_b */ + { + .number = AD9361_1_RESET_B, + .platform_ops = &xil_gpio_ops, + .extra = &xil_gpio_param + }, //gpio_resetb *** reset-gpios + /* MCS Sync */ + { + .number = -1, + .platform_ops = &xil_gpio_ops, + .extra = &xil_gpio_param + }, //gpio_sync *** sync-gpios + /* Cal-SW1 */ + { + .number = -1, + .platform_ops = &xil_gpio_ops, + .extra = &xil_gpio_param + }, //gpio_cal_sw1 *** cal-sw1-gpios + /* Cal-SW2 */ + { + .number = -1, + .platform_ops = &xil_gpio_ops, + .extra = &xil_gpio_param + }, //gpio_cal_sw2 *** cal-sw2-gpios + + { + .device_id = AD9361_SPI_DEVICE_ID, + .mode = SPI_MODE_1, + .chip_select = AD9361_1_SPI_CS, + .platform_ops = &spi_eng_platform_ops, + .extra = &spi_engine_param + }, + + /* External LO clocks */ + NULL, //(*ad9361_rfpll_ext_recalc_rate)() + NULL, //(*ad9361_rfpll_ext_round_rate)() + NULL, //(*ad9361_rfpll_ext_set_rate)() +}; + +AD9361_RXFIRConfig rx_fir_config = { // BPF PASSBAND 3/20 fs to 1/4 fs + 3, // rx + 0, // rx_gain + 1, // rx_dec + { + -4, -6, -37, 35, 186, 86, -284, -315, + 107, 219, -4, 271, 558, -307, -1182, -356, + 658, 157, 207, 1648, 790, -2525, -2553, 748, + 865, -476, 3737, 6560, -3583, -14731, -5278, 14819, + 14819, -5278, -14731, -3583, 6560, 3737, -476, 865, + 748, -2553, -2525, 790, 1648, 207, 157, 658, + -356, -1182, -307, 558, 271, -4, 219, 107, + -315, -284, 86, 186, 35, -37, -6, -4, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 + }, // rx_coef[128] + 64, // rx_coef_size + {0, 0, 0, 0, 0, 0}, //rx_path_clks[6] + 0 // rx_bandwidth +}; + +AD9361_TXFIRConfig tx_fir_config = { // BPF PASSBAND 3/20 fs to 1/4 fs + 3, // tx + -6, // tx_gain + 1, // tx_int + { + -4, -6, -37, 35, 186, 86, -284, -315, + 107, 219, -4, 271, 558, -307, -1182, -356, + 658, 157, 207, 1648, 790, -2525, -2553, 748, + 865, -476, 3737, 6560, -3583, -14731, -5278, 14819, + 14819, -5278, -14731, -3583, 6560, 3737, -476, 865, + 748, -2553, -2525, 790, 1648, 207, 157, 658, + -356, -1182, -307, 558, 271, -4, 219, 107, + -315, -284, 86, 186, 35, -37, -6, -4, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 + }, // tx_coef[128] + 64, // tx_coef_size + {0, 0, 0, 0, 0, 0}, // tx_path_clks[6] + 0 // tx_bandwidth +}; + diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/dev_profile/ad9361_reg_profile.c b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/dev_profile/ad9361_reg_profile.c new file mode 100644 index 0000000..9edecb9 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/dev_profile/ad9361_reg_profile.c @@ -0,0 +1,1746 @@ +#include "dev_profile.h" +#include "spi.h" +#include "../config/app_config.h" +#include "../drivers/rf-transceiver/ad9361_reg/ad9361_reg.h" +#include "../drivers/axi_core/spi_engine/spi_engine.h" +#include "../drivers/platform/xilinx_gpio.h" + +#define TIMEOUT_TH AD9361_TIMEOUT_TH + +static struct spi_engine_init_param spi_engine_param = { + .ref_clk_hz = AD9361_SPI_ENGINE_REF_CLK, + .type = SPI_ENGINE, + .spi_engine_baseaddr = AD9361_SPI_ENGINE_BASEADDR, + .cs_delay = AD9361_SPI_ENGINE_CS_DELAY, + .data_width = AD9361_SPI_ENGINE_DATA_WIDTH +}; + +static struct xil_gpio_init_param xil_gpio_param = { + .type = GPIO_PS, + .device_id = AD9361_GPIO_DEVICE_ID +}; + +// ad9361-1 +static struct spi_init_param ad9361_1_reg_spi_init = { + .device_id = AD9361_SPI_DEVICE_ID, + .max_speed_hz = AD9361_SPI_ENGINE_MAX_SPEED, + .mode = SPI_MODE_1, + .chip_select = AD9361_1_SPI_CS, + .platform_ops = &spi_eng_platform_ops, + .extra = &spi_engine_param +}; + +static struct gpio_init_param ad9361_1_reg_gpio_resetb_init = { + .number = AD9361_1_RESET_B, + .platform_ops = &xil_gpio_ops, + .extra = &xil_gpio_param +}; +struct ad9361_reg_init_param ad9361_1_reg_default_init_param = { + /* SPI */ + .spi_init = &ad9361_1_reg_spi_init, + .gpio_resetb = &ad9361_1_reg_gpio_resetb_init +}; + +// ad9361-2 +static struct spi_init_param ad9361_2_reg_spi_init = { + .device_id = AD9361_SPI_DEVICE_ID, + .max_speed_hz = AD9361_SPI_ENGINE_MAX_SPEED, + .mode = SPI_MODE_1, + .chip_select = AD9361_2_SPI_CS, + .platform_ops = &spi_eng_platform_ops, + .extra = &spi_engine_param +}; + +static struct gpio_init_param ad9361_2_reg_gpio_resetb_init = { + .number = AD9361_2_RESET_B, + .platform_ops = &xil_gpio_ops, + .extra = &xil_gpio_param +}; +struct ad9361_reg_init_param ad9361_2_reg_default_init_param = { + /* SPI */ + .spi_init = &ad9361_2_reg_spi_init, + .gpio_resetb = &ad9361_2_reg_gpio_resetb_init +}; + +uint32_t ad9361_reg_config(struct ad9361_reg_dev *dev){ + int32_t status = 0; + uint8_t value = 0; + int32_t time_out_cnt = 0; + +//************************************************************ +// AD9361 R2 Auto Generated Initialization Script: This script was +// generated using the AD9361 Customer software Version 2.1.3 +//************************************************************ +// Profile: Custom +// REFCLK_IN: 25.000 MHz + + + status = ad9361_reg_write(dev, 0x03DF, 0x01); // Required for proper operation + status = ad9361_reg_write(dev, 0x02A6, 0x0E); // Enable Master Bias + status = ad9361_reg_write(dev, 0x02A8, 0x0E); // Set Bandgap Trim + status = ad9361_reg_write(dev, 0x02AB, 0x07); // Set RF PLL reflclk scale to REFCLK * 2 + status = ad9361_reg_write(dev, 0x02AC, 0xFF); // Set RF PLL reflclk scale to REFCLK * 2 + status = ad9361_reg_write(dev, 0x0009, 0x17); // Enable Clocks + mdelay(20) ;// waits 20 ms + +//************************************************************ +// Set BBPLL Frequency: 1152.000000 +//************************************************************ + status = ad9361_reg_write(dev, 0x0045, 0x03); // Set BBPLL reflclk scale to REFCLK * 2 + status = ad9361_reg_write(dev, 0x0046, 0x03); // Set BBPLL Loop Filter Charge Pump current + status = ad9361_reg_write(dev, 0x0048, 0xE8); // Set BBPLL Loop Filter C1, R1 + status = ad9361_reg_write(dev, 0x0049, 0x5B); // Set BBPLL Loop Filter R2, C2, C1 + status = ad9361_reg_write(dev, 0x004A, 0x35); // Set BBPLL Loop Filter C3,R2 + status = ad9361_reg_write(dev, 0x004B, 0xE0); // Allow calibration to occur and set cal count to 1024 for max accuracy + status = ad9361_reg_write(dev, 0x004E, 0x10); // Set calibration clock to REFCLK/4 for more accuracy + status = ad9361_reg_write(dev, 0x0043, 0x66); // BBPLL Freq Word (Fractional[7:0]) + status = ad9361_reg_write(dev, 0x0042, 0x46); // BBPLL Freq Word (Fractional[15:8]) + status = ad9361_reg_write(dev, 0x0041, 0x01); // BBPLL Freq Word (Fractional[23:16]) + status = ad9361_reg_write(dev, 0x0044, 0x17); // BBPLL Freq Word (Integer[7:0]) + status = ad9361_reg_write(dev, 0x003F, 0x05); // Start BBPLL Calibration + status = ad9361_reg_write(dev, 0x003F, 0x01); // Clear BBPLL start calibration bit + status = ad9361_reg_write(dev, 0x004C, 0x86); // Increase BBPLL KV and phase margin + status = ad9361_reg_write(dev, 0x004D, 0x01); // Increase BBPLL KV and phase margin + status = ad9361_reg_write(dev, 0x004D, 0x05); // Increase BBPLL KV and phase margin + + // Wait for BBPLL to lock, Timeout 2sec, Max BBPLL VCO Cal Time: 276.480 us (Done when 0x05E[7]==1) + time_out_cnt = 0; + do{ + status |= ad9361_reg_read(dev, 0x005E, &value); + mdelay(1);// Wait 1ms + time_out_cnt++; + } while((value & 0x80) != 0x80 && time_out_cnt <= AD9361_TIMEOUT_TH); + + + status = ad9361_reg_write(dev, 0x0002, 0xA4); // Setup Tx Digital Filters/ Channels + status = ad9361_reg_write(dev, 0x0003, 0xE5); // Setup Rx Digital Filters/ Channels + status = ad9361_reg_write(dev, 0x0004, 0x03); // Select Rx input pin(A,B,C)/ Tx out pin (A,B) + status = ad9361_reg_write(dev, 0x000A, 0x12); // Set BBPLL post divide rate + +//************************************************************ +// Program Rx FIR: C:\Users\josh\Desktop\Config\rx64.txt +//************************************************************ + status = ad9361_reg_write(dev, 0x00F5, 0x9A); // Enable clock to Rx FIR Filter + status = ad9361_reg_write(dev, 0x00F6, 0x02); // Write Filter Gain setting + status = ad9361_reg_write(dev, 0x00F0, 0x00); // Write FIR coefficient address + status = ad9361_reg_write(dev, 0x00F1, 0x00); // Write FIR coefficient data[7:0] + status = ad9361_reg_write(dev, 0x00F2, 0x00); // Write FIR coefficient data[15:8] + status = ad9361_reg_write(dev, 0x00F5, 0x9E); // Set Write EN to push data into FIR filter register map + status = ad9361_reg_write(dev, 0x00F4, 0x00); // Dummy Write to Read only register to delay ~1us + status = ad9361_reg_write(dev, 0x00F4, 0x00); // Dummy Write to Read only register to delay ~1us + status = ad9361_reg_write(dev, 0x00F0, 0x01); + status = ad9361_reg_write(dev, 0x00F1, 0xB6); + status = ad9361_reg_write(dev, 0x00F2, 0xFF); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x02); + status = ad9361_reg_write(dev, 0x00F1, 0xA5); + status = ad9361_reg_write(dev, 0x00F2, 0xFF); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x03); + status = ad9361_reg_write(dev, 0x00F1, 0xEA); + status = ad9361_reg_write(dev, 0x00F2, 0xFF); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x04); + status = ad9361_reg_write(dev, 0x00F1, 0x61); + status = ad9361_reg_write(dev, 0x00F2, 0x00); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x05); + status = ad9361_reg_write(dev, 0x00F1, 0xA3); + status = ad9361_reg_write(dev, 0x00F2, 0x00); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x06); + status = ad9361_reg_write(dev, 0x00F1, 0x4D); + status = ad9361_reg_write(dev, 0x00F2, 0x00); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x07); + status = ad9361_reg_write(dev, 0x00F1, 0x77); + status = ad9361_reg_write(dev, 0x00F2, 0xFF); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x08); + status = ad9361_reg_write(dev, 0x00F1, 0xD5); + status = ad9361_reg_write(dev, 0x00F2, 0xFE); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x09); + status = ad9361_reg_write(dev, 0x00F1, 0x38); + status = ad9361_reg_write(dev, 0x00F2, 0xFF); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x0A); + status = ad9361_reg_write(dev, 0x00F1, 0xA5); + status = ad9361_reg_write(dev, 0x00F2, 0x00); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x0B); + status = ad9361_reg_write(dev, 0x00F1, 0xF8); + status = ad9361_reg_write(dev, 0x00F2, 0x01); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x0C); + status = ad9361_reg_write(dev, 0x00F1, 0xAD); + status = ad9361_reg_write(dev, 0x00F2, 0x01); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x0D); + status = ad9361_reg_write(dev, 0x00F1, 0x75); + status = ad9361_reg_write(dev, 0x00F2, 0xFF); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x0E); + status = ad9361_reg_write(dev, 0x00F1, 0xFD); + status = ad9361_reg_write(dev, 0x00F2, 0xFC); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x0F); + status = ad9361_reg_write(dev, 0x00F1, 0xD8); + status = ad9361_reg_write(dev, 0x00F2, 0xFC); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x10); + status = ad9361_reg_write(dev, 0x00F1, 0x00); + status = ad9361_reg_write(dev, 0x00F2, 0x00); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x11); + status = ad9361_reg_write(dev, 0x00F1, 0x3A); + status = ad9361_reg_write(dev, 0x00F2, 0x04); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x12); + status = ad9361_reg_write(dev, 0x00F1, 0x6B); + status = ad9361_reg_write(dev, 0x00F2, 0x05); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x13); + status = ad9361_reg_write(dev, 0x00F1, 0x51); + status = ad9361_reg_write(dev, 0x00F2, 0x01); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x14); + status = ad9361_reg_write(dev, 0x00F1, 0x80); + status = ad9361_reg_write(dev, 0x00F2, 0xFA); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x15); + status = ad9361_reg_write(dev, 0x00F1, 0x34); + status = ad9361_reg_write(dev, 0x00F2, 0xF7); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x16); + status = ad9361_reg_write(dev, 0x00F1, 0x08); + status = ad9361_reg_write(dev, 0x00F2, 0xFC); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x17); + status = ad9361_reg_write(dev, 0x00F1, 0xB2); + status = ad9361_reg_write(dev, 0x00F2, 0x06); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x18); + status = ad9361_reg_write(dev, 0x00F1, 0x1A); + status = ad9361_reg_write(dev, 0x00F2, 0x0E); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x19); + status = ad9361_reg_write(dev, 0x00F1, 0x44); + status = ad9361_reg_write(dev, 0x00F2, 0x09); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x1A); + status = ad9361_reg_write(dev, 0x00F1, 0x54); + status = ad9361_reg_write(dev, 0x00F2, 0xF8); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x1B); + status = ad9361_reg_write(dev, 0x00F1, 0xD1); + status = ad9361_reg_write(dev, 0x00F2, 0xE7); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x1C); + status = ad9361_reg_write(dev, 0x00F1, 0xC2); + status = ad9361_reg_write(dev, 0x00F2, 0xE9); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x1D); + status = ad9361_reg_write(dev, 0x00F1, 0x4F); + status = ad9361_reg_write(dev, 0x00F2, 0x08); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x1E); + status = ad9361_reg_write(dev, 0x00F1, 0xB2); + status = ad9361_reg_write(dev, 0x00F2, 0x3B); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x1F); + status = ad9361_reg_write(dev, 0x00F1, 0x2A); + status = ad9361_reg_write(dev, 0x00F2, 0x6C); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x20); + status = ad9361_reg_write(dev, 0x00F1, 0xFF); + status = ad9361_reg_write(dev, 0x00F2, 0x7F); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x21); + status = ad9361_reg_write(dev, 0x00F1, 0x2A); + status = ad9361_reg_write(dev, 0x00F2, 0x6C); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x22); + status = ad9361_reg_write(dev, 0x00F1, 0xB2); + status = ad9361_reg_write(dev, 0x00F2, 0x3B); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x23); + status = ad9361_reg_write(dev, 0x00F1, 0x4F); + status = ad9361_reg_write(dev, 0x00F2, 0x08); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x24); + status = ad9361_reg_write(dev, 0x00F1, 0xC2); + status = ad9361_reg_write(dev, 0x00F2, 0xE9); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x25); + status = ad9361_reg_write(dev, 0x00F1, 0xD1); + status = ad9361_reg_write(dev, 0x00F2, 0xE7); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x26); + status = ad9361_reg_write(dev, 0x00F1, 0x54); + status = ad9361_reg_write(dev, 0x00F2, 0xF8); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x27); + status = ad9361_reg_write(dev, 0x00F1, 0x44); + status = ad9361_reg_write(dev, 0x00F2, 0x09); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x28); + status = ad9361_reg_write(dev, 0x00F1, 0x1A); + status = ad9361_reg_write(dev, 0x00F2, 0x0E); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x29); + status = ad9361_reg_write(dev, 0x00F1, 0xB2); + status = ad9361_reg_write(dev, 0x00F2, 0x06); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x2A); + status = ad9361_reg_write(dev, 0x00F1, 0x08); + status = ad9361_reg_write(dev, 0x00F2, 0xFC); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x2B); + status = ad9361_reg_write(dev, 0x00F1, 0x34); + status = ad9361_reg_write(dev, 0x00F2, 0xF7); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x2C); + status = ad9361_reg_write(dev, 0x00F1, 0x80); + status = ad9361_reg_write(dev, 0x00F2, 0xFA); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x2D); + status = ad9361_reg_write(dev, 0x00F1, 0x51); + status = ad9361_reg_write(dev, 0x00F2, 0x01); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x2E); + status = ad9361_reg_write(dev, 0x00F1, 0x6B); + status = ad9361_reg_write(dev, 0x00F2, 0x05); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x2F); + status = ad9361_reg_write(dev, 0x00F1, 0x3A); + status = ad9361_reg_write(dev, 0x00F2, 0x04); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x30); + status = ad9361_reg_write(dev, 0x00F1, 0x00); + status = ad9361_reg_write(dev, 0x00F2, 0x00); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x31); + status = ad9361_reg_write(dev, 0x00F1, 0xD8); + status = ad9361_reg_write(dev, 0x00F2, 0xFC); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x32); + status = ad9361_reg_write(dev, 0x00F1, 0xFD); + status = ad9361_reg_write(dev, 0x00F2, 0xFC); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x33); + status = ad9361_reg_write(dev, 0x00F1, 0x75); + status = ad9361_reg_write(dev, 0x00F2, 0xFF); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x34); + status = ad9361_reg_write(dev, 0x00F1, 0xAD); + status = ad9361_reg_write(dev, 0x00F2, 0x01); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x35); + status = ad9361_reg_write(dev, 0x00F1, 0xF8); + status = ad9361_reg_write(dev, 0x00F2, 0x01); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x36); + status = ad9361_reg_write(dev, 0x00F1, 0xA5); + status = ad9361_reg_write(dev, 0x00F2, 0x00); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x37); + status = ad9361_reg_write(dev, 0x00F1, 0x38); + status = ad9361_reg_write(dev, 0x00F2, 0xFF); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x38); + status = ad9361_reg_write(dev, 0x00F1, 0xD5); + status = ad9361_reg_write(dev, 0x00F2, 0xFE); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x39); + status = ad9361_reg_write(dev, 0x00F1, 0x77); + status = ad9361_reg_write(dev, 0x00F2, 0xFF); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x3A); + status = ad9361_reg_write(dev, 0x00F1, 0x4D); + status = ad9361_reg_write(dev, 0x00F2, 0x00); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x3B); + status = ad9361_reg_write(dev, 0x00F1, 0xA3); + status = ad9361_reg_write(dev, 0x00F2, 0x00); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x3C); + status = ad9361_reg_write(dev, 0x00F1, 0x61); + status = ad9361_reg_write(dev, 0x00F2, 0x00); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x3D); + status = ad9361_reg_write(dev, 0x00F1, 0xEA); + status = ad9361_reg_write(dev, 0x00F2, 0xFF); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x3E); + status = ad9361_reg_write(dev, 0x00F1, 0xA5); + status = ad9361_reg_write(dev, 0x00F2, 0xFF); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x3F); + status = ad9361_reg_write(dev, 0x00F1, 0xB6); + status = ad9361_reg_write(dev, 0x00F2, 0xFF); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x40); + status = ad9361_reg_write(dev, 0x00F1, 0x00); + status = ad9361_reg_write(dev, 0x00F2, 0x00); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x41); + status = ad9361_reg_write(dev, 0x00F1, 0x00); + status = ad9361_reg_write(dev, 0x00F2, 0x00); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x42); + status = ad9361_reg_write(dev, 0x00F1, 0x00); + status = ad9361_reg_write(dev, 0x00F2, 0x00); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x43); + status = ad9361_reg_write(dev, 0x00F1, 0x00); + status = ad9361_reg_write(dev, 0x00F2, 0x00); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x44); + status = ad9361_reg_write(dev, 0x00F1, 0x00); + status = ad9361_reg_write(dev, 0x00F2, 0x00); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x45); + status = ad9361_reg_write(dev, 0x00F1, 0x00); + status = ad9361_reg_write(dev, 0x00F2, 0x00); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x46); + status = ad9361_reg_write(dev, 0x00F1, 0x00); + status = ad9361_reg_write(dev, 0x00F2, 0x00); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x47); + status = ad9361_reg_write(dev, 0x00F1, 0x00); + status = ad9361_reg_write(dev, 0x00F2, 0x00); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x48); + status = ad9361_reg_write(dev, 0x00F1, 0x00); + status = ad9361_reg_write(dev, 0x00F2, 0x00); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x49); + status = ad9361_reg_write(dev, 0x00F1, 0x00); + status = ad9361_reg_write(dev, 0x00F2, 0x00); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x4A); + status = ad9361_reg_write(dev, 0x00F1, 0x00); + status = ad9361_reg_write(dev, 0x00F2, 0x00); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x4B); + status = ad9361_reg_write(dev, 0x00F1, 0x00); + status = ad9361_reg_write(dev, 0x00F2, 0x00); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x4C); + status = ad9361_reg_write(dev, 0x00F1, 0x00); + status = ad9361_reg_write(dev, 0x00F2, 0x00); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x4D); + status = ad9361_reg_write(dev, 0x00F1, 0x00); + status = ad9361_reg_write(dev, 0x00F2, 0x00); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x4E); + status = ad9361_reg_write(dev, 0x00F1, 0x00); + status = ad9361_reg_write(dev, 0x00F2, 0x00); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F0, 0x4F); + status = ad9361_reg_write(dev, 0x00F1, 0x00); + status = ad9361_reg_write(dev, 0x00F2, 0x00); + status = ad9361_reg_write(dev, 0x00F5, 0x9E); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F4, 0x00); + status = ad9361_reg_write(dev, 0x00F5, 0x98); // Disable clock to Rx Filter + +//************************************************************ +// Setup the Parallel Port (Digital Data Interface) +//************************************************************ + status = ad9361_reg_write(dev, 0x0010, 0xC8); // I/O Config. Tx Swap IQ; Rx Swap IQ; Tx CH Swap, Rx CH Swap; Rx Frame Mode; 2R2T bit; Invert data bus; Invert DATA_CLK + status = ad9361_reg_write(dev, 0x0011, 0x00); // I/O Config. Alt Word Order; -Rx1; -Rx2; -Tx1; -Tx2; Invert Rx Frame; Delay Rx Data + status = ad9361_reg_write(dev, 0x0012, 0x02); // I/O Config. Rx=2*Tx; Swap Ports; SDR; LVDS; Half Duplex; Single Port; Full Port; Swap Bits + status = ad9361_reg_write(dev, 0x0006, 0x00); // PPORT Rx Delay (adjusts Tco Dataclk->Data) + status = ad9361_reg_write(dev, 0x0007, 0x0F); // PPORT TX Delay (adjusts setup/hold FBCLK->Data) + +//************************************************************ +// Setup AuxDAC +//************************************************************ + status = ad9361_reg_write(dev, 0x0018, 0x00); // AuxDAC1 Word[9:2] + status = ad9361_reg_write(dev, 0x0019, 0x00); // AuxDAC2 Word[9:2] + status = ad9361_reg_write(dev, 0x001A, 0x00); // AuxDAC1 Config and Word[1:0] + status = ad9361_reg_write(dev, 0x001B, 0x00); // AuxDAC2 Config and Word[1:0] + status = ad9361_reg_write(dev, 0x0023, 0xFF); // AuxDAC Manaul/Auto Control + status = ad9361_reg_write(dev, 0x0026, 0x00); // AuxDAC Manual Select Bit/GPO Manual Select + status = ad9361_reg_write(dev, 0x0030, 0x00); // AuxDAC1 Rx Delay + status = ad9361_reg_write(dev, 0x0031, 0x00); // AuxDAC1 Tx Delay + status = ad9361_reg_write(dev, 0x0032, 0x00); // AuxDAC2 Rx Delay + status = ad9361_reg_write(dev, 0x0033, 0x00); // AuxDAC2 Tx Delay + +//************************************************************ +// Setup AuxADC +//************************************************************ + status = ad9361_reg_write(dev, 0x000B, 0x00); // Temp Sensor Setup (Offset) + status = ad9361_reg_write(dev, 0x000C, 0x00); // Temp Sensor Setup (Temp Window) + status = ad9361_reg_write(dev, 0x000D, 0x03); // Temp Sensor Setup (Periodic Measure) + status = ad9361_reg_write(dev, 0x000F, 0x04); // Temp Sensor Setup (Decimation) + status = ad9361_reg_write(dev, 0x001C, 0x00); // AuxADC Setup (Clock Div) + status = ad9361_reg_write(dev, 0x001D, 0x01); // AuxADC Setup (Decimation/Enable) + +//************************************************************ +// Setup Control Outs +//************************************************************ + status = ad9361_reg_write(dev, 0x0035, 0x00); // Ctrl Out index + status = ad9361_reg_write(dev, 0x0036, 0xFF); // Ctrl Out [7:0] output enable + +//************************************************************ +// Setup GPO +//************************************************************ + status = ad9361_reg_write(dev, 0x003A, 0x18); // Set number of REFCLK cycles for 1us delay timer + status = ad9361_reg_write(dev, 0x0020, 0x00); // GPO Auto Enable Setup in RX and TX + status = ad9361_reg_write(dev, 0x0027, 0x00); // GPO Manual and GPO auto value in ALERT + status = ad9361_reg_write(dev, 0x0028, 0x00); // GPO_0 RX Delay + status = ad9361_reg_write(dev, 0x0029, 0x00); // GPO_1 RX Delay + status = ad9361_reg_write(dev, 0x002A, 0x00); // GPO_2 RX Delay + status = ad9361_reg_write(dev, 0x002B, 0x00); // GPO_3 RX Delay + status = ad9361_reg_write(dev, 0x002C, 0x00); // GPO_0 TX Delay + status = ad9361_reg_write(dev, 0x002D, 0x00); // GPO_1 TX Delay + status = ad9361_reg_write(dev, 0x002E, 0x00); // GPO_2 TX Delay + status = ad9361_reg_write(dev, 0x002F, 0x00); // GPO_3 TX Delay + +//************************************************************ +// Setup RF PLL non-frequency-dependent registers +//************************************************************ + status = ad9361_reg_write(dev, 0x0261, 0x00); // Set Rx LO Power mode + status = ad9361_reg_write(dev, 0x02A1, 0x00); // Set Tx LO Power mode + status = ad9361_reg_write(dev, 0x0248, 0x0B); // Enable Rx VCO LDO + status = ad9361_reg_write(dev, 0x0288, 0x0B); // Enable Tx VCO LDO + status = ad9361_reg_write(dev, 0x0246, 0x02); // Set VCO Power down TCF bits + status = ad9361_reg_write(dev, 0x0286, 0x02); // Set VCO Power down TCF bits + status = ad9361_reg_write(dev, 0x0249, 0x8E); // Set VCO cal length + status = ad9361_reg_write(dev, 0x0289, 0x8E); // Set VCO cal length + status = ad9361_reg_write(dev, 0x023B, 0x80); // Enable Rx VCO cal + status = ad9361_reg_write(dev, 0x027B, 0x80); // Enable Tx VCO cal + status = ad9361_reg_write(dev, 0x0243, 0x0D); // Set Rx prescaler bias + status = ad9361_reg_write(dev, 0x0283, 0x0D); // Set Tx prescaler bias + status = ad9361_reg_write(dev, 0x023D, 0x00); // Clear Half VCO cal clock setting + status = ad9361_reg_write(dev, 0x027D, 0x00); // Clear Half VCO cal clock setting + + status = ad9361_reg_write(dev, 0x0015, 0x0C); // Set Dual Synth mode bit + status = ad9361_reg_write(dev, 0x0014, 0x1D); // Set Force ALERT State bit + status = ad9361_reg_write(dev, 0x0013, 0x01); // Set ENSM FDD mode + mdelay(1); // waits 1 ms + + status = ad9361_reg_write(dev, 0x023D, 0x04); // Start RX CP cal + + // Wait for CP cal to complete, Max RXCP Cal time: 737.280 (us)(Done when 0x244[7]==1) + time_out_cnt = 0; + do{ + status |= ad9361_reg_read(dev, 0x0244, &value); + mdelay(1);// Wait 1ms + time_out_cnt++; + } while((value & 0x80) != 0x80 && time_out_cnt <= AD9361_TIMEOUT_TH); + + status = ad9361_reg_write(dev, 0x027D, 0x04); // Start TX CP cal + + // Wait for CP cal to complete, Max TXCP Cal time: 737.280 (us)(Done when 0x284[7]==1) + time_out_cnt = 0; + do{ + status |= ad9361_reg_read(dev, 0x0284, &value); + mdelay(1);// Wait 1ms + time_out_cnt++; + } while((value & 0x80) != 0x80 && time_out_cnt <= AD9361_TIMEOUT_TH); + + status = ad9361_reg_write(dev, 0x023D, 0x00); // Disable RX CP Calibration since the CP Cal start bit is not self-clearing. Only important if the script is run again without restting the DUT + status = ad9361_reg_write(dev, 0x027D, 0x00); // Disable TX CP Calibration since the CP Cal start bit is not self-clearing. Only important if the script is run again without restting the DUT +//************************************************************ +// FDD RX,TX Synth Frequency: 125.000000,4125.000000 MHz +//************************************************************ +//************************************************************ +// Setup Rx Frequency-Dependent Syntheisizer Registers +//************************************************************ + status = ad9361_reg_write(dev, 0x023A, 0x4A); // Set VCO Output level[3:0] + status = ad9361_reg_write(dev, 0x0239, 0xC1); // Set Init ALC Value[3:0] and VCO Varactor[3:0] + status = ad9361_reg_write(dev, 0x0242, 0x0E); // Set VCO Bias Tcf[1:0] and VCO Bias Ref[2:0] + status = ad9361_reg_write(dev, 0x0238, 0x78); // Set VCO Cal Offset[3:0] + status = ad9361_reg_write(dev, 0x0245, 0x00); // Set VCO Cal Ref Tcf[2:0] + status = ad9361_reg_write(dev, 0x0251, 0x0B); // Set VCO Varactor Reference[3:0] + status = ad9361_reg_write(dev, 0x0250, 0x70); // Set VCO Varactor Ref Tcf[2:0] and VCO Varactor Offset[3:0] + status = ad9361_reg_write(dev, 0x023B, 0x94); // Set Synth Loop Filter charge pump current (Icp) + status = ad9361_reg_write(dev, 0x023E, 0xF4); // Set Synth Loop Filter C2 and C1 + status = ad9361_reg_write(dev, 0x023F, 0xDF); // Set Synth Loop Filter R1 and C3 + status = ad9361_reg_write(dev, 0x0240, 0x0A); // Set Synth Loop Filter R3 + +//************************************************************ +// Setup Tx Frequency-Dependent Syntheisizer Registers +//************************************************************ + status = ad9361_reg_write(dev, 0x027A, 0x4A); // Set VCO Output level[3:0] + status = ad9361_reg_write(dev, 0x0279, 0xC1); // Set Init ALC Value[3:0] and VCO Varactor[3:0] + status = ad9361_reg_write(dev, 0x0282, 0x0E); // Set VCO Bias Tcf[1:0] and VCO Bias Ref[2:0] + status = ad9361_reg_write(dev, 0x0278, 0x78); // Set VCO Cal Offset[3:0] + status = ad9361_reg_write(dev, 0x0285, 0x00); // Set VCO Cal Ref Tcf[2:0] + status = ad9361_reg_write(dev, 0x0291, 0x0B); // Set VCO Varactor Reference[3:0] + status = ad9361_reg_write(dev, 0x0290, 0x70); // Set VCO Varactor Ref Tcf[2:0] and VCO Varactor Offset[3:0] + status = ad9361_reg_write(dev, 0x027B, 0x93); // Set Synth Loop Filter charge pump current (Icp) + status = ad9361_reg_write(dev, 0x027E, 0xF4); // Set Synth Loop Filter C2 and C1 + status = ad9361_reg_write(dev, 0x027F, 0xDF); // Set Synth Loop Filter R1 and C3 + status = ad9361_reg_write(dev, 0x0280, 0x0A); // Set Synth Loop Filter R3 + +//************************************************************ +// Write Rx and Tx Frequency Words +//************************************************************ + status = ad9361_reg_write(dev, 0x0233, 0x00); // Write Rx Synth Fractional Freq Word[7:0] + status = ad9361_reg_write(dev, 0x0234, 0x00); // Write Rx Synth Fractional Freq Word[15:8] + status = ad9361_reg_write(dev, 0x0235, 0x00); // Write Rx Synth Fractional Freq Word[22:16] + status = ad9361_reg_write(dev, 0x0232, 0x00); // Write Rx Synth Integer Freq Word[10:8] + status = ad9361_reg_write(dev, 0x0231, 0xA0); // Write Rx Synth Integer Freq Word[7:0] + status = ad9361_reg_write(dev, 0x0005, 0x05); // Set LO divider setting + status = ad9361_reg_write(dev, 0x0273, 0x00); // Write Tx Synth Fractional Freq Word[7:0] + status = ad9361_reg_write(dev, 0x0274, 0x00); // Write Tx Synth Fractional Freq Word[15:8] + status = ad9361_reg_write(dev, 0x0275, 0x00); // Write Tx Synth Fractional Freq Word[22:16] + status = ad9361_reg_write(dev, 0x0272, 0x00); // Write Tx Synth Integer Freq Word[10:8] + status = ad9361_reg_write(dev, 0x0271, 0xA5); // Write Tx Synth Integer Freq Word[7:0] (starts VCO cal) + status = ad9361_reg_write(dev, 0x0005, 0x05); // Set LO divider setting + +//************************************************************ +// Program Mixer GM Sub-table +//************************************************************ + status = ad9361_reg_write(dev, 0x013F, 0x02); // Start Clock + status = ad9361_reg_write(dev, 0x0138, 0x0F); // Addr Table Index + status = ad9361_reg_write(dev, 0x0139, 0x78); // Gain + status = ad9361_reg_write(dev, 0x013A, 0x00); // Bias + status = ad9361_reg_write(dev, 0x013B, 0x00); // GM + status = ad9361_reg_write(dev, 0x013F, 0x06); // Write Words + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay for 3 ADCCLK/16 clock cycles (Dummy Write) + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay ~1us (Dummy Write) + status = ad9361_reg_write(dev, 0x0138, 0x0E); // Addr Table Index + status = ad9361_reg_write(dev, 0x0139, 0x74); // Gain + status = ad9361_reg_write(dev, 0x013A, 0x00); // Bias + status = ad9361_reg_write(dev, 0x013B, 0x0D); // GM + status = ad9361_reg_write(dev, 0x013F, 0x06); // Write Words + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay for 3 ADCCLK/16 clock cycles (Dummy Write) + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay ~1us (Dummy Write) + status = ad9361_reg_write(dev, 0x0138, 0x0D); // Addr Table Index + status = ad9361_reg_write(dev, 0x0139, 0x70); // Gain + status = ad9361_reg_write(dev, 0x013A, 0x00); // Bias + status = ad9361_reg_write(dev, 0x013B, 0x15); // GM + status = ad9361_reg_write(dev, 0x013F, 0x06); // Write Words + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay for 3 ADCCLK/16 clock cycles (Dummy Write) + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay ~1us (Dummy Write) + status = ad9361_reg_write(dev, 0x0138, 0x0C); // Addr Table Index + status = ad9361_reg_write(dev, 0x0139, 0x6C); // Gain + status = ad9361_reg_write(dev, 0x013A, 0x00); // Bias + status = ad9361_reg_write(dev, 0x013B, 0x1B); // GM + status = ad9361_reg_write(dev, 0x013F, 0x06); // Write Words + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay for 3 ADCCLK/16 clock cycles (Dummy Write) + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay ~1us (Dummy Write) + status = ad9361_reg_write(dev, 0x0138, 0x0B); // Addr Table Index + status = ad9361_reg_write(dev, 0x0139, 0x68); // Gain + status = ad9361_reg_write(dev, 0x013A, 0x00); // Bias + status = ad9361_reg_write(dev, 0x013B, 0x21); // GM + status = ad9361_reg_write(dev, 0x013F, 0x06); // Write Words + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay for 3 ADCCLK/16 clock cycles (Dummy Write) + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay ~1us (Dummy Write) + status = ad9361_reg_write(dev, 0x0138, 0x0A); // Addr Table Index + status = ad9361_reg_write(dev, 0x0139, 0x64); // Gain + status = ad9361_reg_write(dev, 0x013A, 0x00); // Bias + status = ad9361_reg_write(dev, 0x013B, 0x25); // GM + status = ad9361_reg_write(dev, 0x013F, 0x06); // Write Words + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay for 3 ADCCLK/16 clock cycles (Dummy Write) + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay ~1us (Dummy Write) + status = ad9361_reg_write(dev, 0x0138, 0x09); // Addr Table Index + status = ad9361_reg_write(dev, 0x0139, 0x60); // Gain + status = ad9361_reg_write(dev, 0x013A, 0x00); // Bias + status = ad9361_reg_write(dev, 0x013B, 0x29); // GM + status = ad9361_reg_write(dev, 0x013F, 0x06); // Write Words + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay for 3 ADCCLK/16 clock cycles (Dummy Write) + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay ~1us (Dummy Write) + status = ad9361_reg_write(dev, 0x0138, 0x08); // Addr Table Index + status = ad9361_reg_write(dev, 0x0139, 0x5C); // Gain + status = ad9361_reg_write(dev, 0x013A, 0x00); // Bias + status = ad9361_reg_write(dev, 0x013B, 0x2C); // GM + status = ad9361_reg_write(dev, 0x013F, 0x06); // Write Words + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay for 3 ADCCLK/16 clock cycles (Dummy Write) + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay ~1us (Dummy Write) + status = ad9361_reg_write(dev, 0x0138, 0x07); // Addr Table Index + status = ad9361_reg_write(dev, 0x0139, 0x58); // Gain + status = ad9361_reg_write(dev, 0x013A, 0x00); // Bias + status = ad9361_reg_write(dev, 0x013B, 0x2F); // GM + status = ad9361_reg_write(dev, 0x013F, 0x06); // Write Words + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay for 3 ADCCLK/16 clock cycles (Dummy Write) + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay ~1us (Dummy Write) + status = ad9361_reg_write(dev, 0x0138, 0x06); // Addr Table Index + status = ad9361_reg_write(dev, 0x0139, 0x54); // Gain + status = ad9361_reg_write(dev, 0x013A, 0x00); // Bias + status = ad9361_reg_write(dev, 0x013B, 0x31); // GM + status = ad9361_reg_write(dev, 0x013F, 0x06); // Write Words + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay for 3 ADCCLK/16 clock cycles (Dummy Write) + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay ~1us (Dummy Write) + status = ad9361_reg_write(dev, 0x0138, 0x05); // Addr Table Index + status = ad9361_reg_write(dev, 0x0139, 0x50); // Gain + status = ad9361_reg_write(dev, 0x013A, 0x00); // Bias + status = ad9361_reg_write(dev, 0x013B, 0x33); // GM + status = ad9361_reg_write(dev, 0x013F, 0x06); // Write Words + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay for 3 ADCCLK/16 clock cycles (Dummy Write) + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay ~1us (Dummy Write) + status = ad9361_reg_write(dev, 0x0138, 0x04); // Addr Table Index + status = ad9361_reg_write(dev, 0x0139, 0x4C); // Gain + status = ad9361_reg_write(dev, 0x013A, 0x00); // Bias + status = ad9361_reg_write(dev, 0x013B, 0x34); // GM + status = ad9361_reg_write(dev, 0x013F, 0x06); // Write Words + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay for 3 ADCCLK/16 clock cycles (Dummy Write) + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay ~1us (Dummy Write) + status = ad9361_reg_write(dev, 0x0138, 0x03); // Addr Table Index + status = ad9361_reg_write(dev, 0x0139, 0x48); // Gain + status = ad9361_reg_write(dev, 0x013A, 0x00); // Bias + status = ad9361_reg_write(dev, 0x013B, 0x35); // GM + status = ad9361_reg_write(dev, 0x013F, 0x06); // Write Words + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay for 3 ADCCLK/16 clock cycles (Dummy Write) + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay ~1us (Dummy Write) + status = ad9361_reg_write(dev, 0x0138, 0x02); // Addr Table Index + status = ad9361_reg_write(dev, 0x0139, 0x30); // Gain + status = ad9361_reg_write(dev, 0x013A, 0x00); // Bias + status = ad9361_reg_write(dev, 0x013B, 0x3A); // GM + status = ad9361_reg_write(dev, 0x013F, 0x06); // Write Words + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay for 3 ADCCLK/16 clock cycles (Dummy Write) + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay ~1us (Dummy Write) + status = ad9361_reg_write(dev, 0x0138, 0x01); // Addr Table Index + status = ad9361_reg_write(dev, 0x0139, 0x18); // Gain + status = ad9361_reg_write(dev, 0x013A, 0x00); // Bias + status = ad9361_reg_write(dev, 0x013B, 0x3D); // GM + status = ad9361_reg_write(dev, 0x013F, 0x06); // Write Words + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay for 3 ADCCLK/16 clock cycles (Dummy Write) + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay ~1us (Dummy Write) + status = ad9361_reg_write(dev, 0x0138, 0x00); // Addr Table Index + status = ad9361_reg_write(dev, 0x0139, 0x00); // Gain + status = ad9361_reg_write(dev, 0x013A, 0x00); // Bias + status = ad9361_reg_write(dev, 0x013B, 0x3E); // GM + status = ad9361_reg_write(dev, 0x013F, 0x06); // Write Words + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay for 3 ADCCLK/16 clock cycles (Dummy Write) + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay ~1us (Dummy Write) + status = ad9361_reg_write(dev, 0x013F, 0x02); // Clear Write Bit + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay for 3 ADCCLK/16 clock cycles (Dummy Write) + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay ~1us (Dummy Write) + status = ad9361_reg_write(dev, 0x013F, 0x00); // Stop Clock + +//************************************************************ +// Program Rx Gain Tables with GainTable800MHz.csv +//************************************************************ + + status = ad9361_reg_write(dev, 0x0137, 0x1A); // Start Gain Table Clock + status = ad9361_reg_write(dev, 0x0130, 0x00); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x00); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x00); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x20); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x01); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x00); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x00); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x02); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x00); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x00); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x03); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x00); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x01); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x04); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x00); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x02); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x05); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x00); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x03); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x06); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x00); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x04); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x07); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x00); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x05); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x08); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x01); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x03); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x20); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x09); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x01); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x04); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x0A); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x01); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x05); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x0B); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x01); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x06); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x0C); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x01); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x07); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x0D); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x01); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x08); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x0E); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x01); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x09); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x0F); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x01); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x0A); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x10); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x01); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x0B); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x11); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x01); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x0C); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x12); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x01); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x0D); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x13); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x01); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x0E); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x14); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x02); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x09); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x20); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x15); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x02); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x0A); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x16); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x02); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x0B); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x17); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x02); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x0C); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x18); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x02); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x0D); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x19); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x02); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x0E); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x1A); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x02); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x0F); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x1B); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x02); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x10); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x1C); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x02); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x2B); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x20); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x1D); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x02); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x2C); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x1E); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x04); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x28); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x20); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x1F); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x04); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x29); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x20); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x04); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x2A); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x21); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x04); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x2B); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x22); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x24); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x20); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x20); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x23); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x24); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x21); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x24); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x44); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x20); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x20); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x25); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x44); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x21); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x26); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x44); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x22); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x27); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x44); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x23); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x28); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x44); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x24); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x29); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x44); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x25); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x2A); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x44); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x26); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x2B); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x44); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x27); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x2C); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x44); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x28); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x2D); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x44); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x29); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x2E); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x44); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x2A); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x2F); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x44); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x2B); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x30); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x44); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x2C); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x31); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x44); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x2D); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x32); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x44); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x2E); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x33); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x44); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x2F); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x34); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x44); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x30); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x35); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x44); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x31); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x36); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x44); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x32); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x37); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x64); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x2E); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x20); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x38); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x64); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x2F); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x39); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x64); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x30); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x3A); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x64); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x31); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x3B); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x64); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x32); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x3C); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x64); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x33); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x3D); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x64); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x34); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x3E); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x64); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x35); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x3F); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x64); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x36); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x40); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x64); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x37); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x41); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x64); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x38); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x42); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x65); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x38); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x20); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x43); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x66); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x38); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x20); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x44); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x67); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x38); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x20); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x45); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x68); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x38); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x20); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x46); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x69); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x38); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x20); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x47); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x6A); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x38); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x20); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x48); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x6B); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x38); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x20); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x49); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x6C); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x38); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x20); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x4A); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x6D); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x38); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x20); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x4B); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x6E); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x38); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x20); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x4C); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x6F); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x38); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x20); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x4D); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x00); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x00); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x4E); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x00); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x00); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x4F); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x00); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x00); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x50); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x00); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x00); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x51); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x00); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x00); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x52); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x00); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x00); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x53); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x00); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x00); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x54); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x00); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x00); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x55); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x00); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x00); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x56); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x00); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x00); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x57); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x00); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x00); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x58); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x00); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x00); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x59); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x00); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x00); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x5A); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x00); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x00); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0137, 0x1A); // Clear Write Bit + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0137, 0x00); // Stop Gain Table Clock +//************************************************************ +// Setup Rx Manual Gain Registers +//************************************************************ + status = ad9361_reg_write(dev, 0x00FA, 0xE0); // Gain Control Mode Select + status = ad9361_reg_write(dev, 0x00FB, 0x08); // Table, Digital Gain, Man Gain Ctrl + status = ad9361_reg_write(dev, 0x00FC, 0x23); // Incr Step Size, ADC Overrange Size + status = ad9361_reg_write(dev, 0x00FD, 0x4C); // Max Full/LMT Gain Table Index + status = ad9361_reg_write(dev, 0x00FE, 0x44); // Decr Step Size, Peak Overload Time + status = ad9361_reg_write(dev, 0x0100, 0x6F); // Max Digital Gain + status = ad9361_reg_write(dev, 0x0104, 0x2F); // ADC Small Overload Threshold + status = ad9361_reg_write(dev, 0x0105, 0x3A); // ADC Large Overload Threshold + status = ad9361_reg_write(dev, 0x0107, 0x2B); // Small LMT Overload Threshold + status = ad9361_reg_write(dev, 0x0108, 0x31); // Large LMT Overload Threshold + status = ad9361_reg_write(dev, 0x0109, 0x00); // Rx1 Full/LMT Gain Index + status = ad9361_reg_write(dev, 0x010A, 0x58); // Rx1 LPF Gain Index + status = ad9361_reg_write(dev, 0x010B, 0x00); // Rx1 Digital Gain Index + status = ad9361_reg_write(dev, 0x010C, 0x00); // Rx2 Full/LMT Gain Index + status = ad9361_reg_write(dev, 0x010D, 0x18); // Rx2 LPF Gain Index + status = ad9361_reg_write(dev, 0x010E, 0x00); // Rx2 Digital Gain Index + status = ad9361_reg_write(dev, 0x0114, 0x30); // Low Power Threshold + status = ad9361_reg_write(dev, 0x011A, 0x27); // Initial LMT Gain Limit + status = ad9361_reg_write(dev, 0x0081, 0x00); // Tx Symbol Gain Control +//************************************************************ +// RX Baseband Filter Tuning (Real BW: 7.500000 MHz) 3dB Filter +// Corner @ 10.500000 MHz) +//************************************************************ + status = ad9361_reg_write(dev, 0x01FB, 0x07); // RX Freq Corner (MHz) + status = ad9361_reg_write(dev, 0x01FC, 0x40); // RX Freq Corner (Khz) + status = ad9361_reg_write(dev, 0x01F8, 0x0D); // Rx BBF Tune Divider[7:0] + status = ad9361_reg_write(dev, 0x01F9, 0x1E); // RX BBF Tune Divider[8] + + status = ad9361_reg_write(dev, 0x01D5, 0x3F); // Set Rx Mix LO CM + status = ad9361_reg_write(dev, 0x01C0, 0x03); // Set GM common mode + status = ad9361_reg_write(dev, 0x01E2, 0x02); // Enable Rx1 Filter Tuner + status = ad9361_reg_write(dev, 0x01E3, 0x02); // Enable Rx2 Filter Tuner + status = ad9361_reg_write(dev, 0x0016, 0x80); // Start RX Filter Tune + + // Wait for RX filter to tune, Max Cal Time: 6.884 us (Done when 0x016[7]==0) + time_out_cnt = 0; + do{ + status |= ad9361_reg_read(dev, 0x0016, &value); + mdelay(1);// Wait 1ms + time_out_cnt++; + } while((value & 0x80) != 0x00 && time_out_cnt <= AD9361_TIMEOUT_TH); + + status = ad9361_reg_write(dev, 0x01E2, 0x03); // Disable Rx Filter Tuner (Rx1) + status = ad9361_reg_write(dev, 0x01E3, 0x03); // Disable Rx Filter Tuner (Rx2) +//************************************************************ +// TX Baseband Filter Tuning (Real BW: 7.500000 MHz) 3dB Filter +// Corner @ 12.000000 MHz) +//************************************************************ + status = ad9361_reg_write(dev, 0x00D6, 0x0B); // TX BBF Tune Divider[7:0] + status = ad9361_reg_write(dev, 0x00D7, 0x1E); // TX BBF Tune Divider[8] + + status = ad9361_reg_write(dev, 0x00CA, 0x22); // Enable Tx Filter Tuner + status = ad9361_reg_write(dev, 0x0016, 0x40); // Start Tx Filter Tune + + // Wait for TX filter to tune, Max Cal Time: 3.390 us (Done when 0x016[6]==0) + time_out_cnt = 0; + do{ + status |= ad9361_reg_read(dev, 0x0016, &value); + mdelay(1);// Wait 1ms + time_out_cnt++; + } while((value & 0x40) != 0x00 && time_out_cnt <= AD9361_TIMEOUT_TH); + + status = ad9361_reg_write(dev, 0x00CA, 0x26); // Disable Tx Filter Tuner (Both Channels) +//************************************************************ +// RX TIA Setup: Setup values scale based on RxBBF calibration +// results. See information in Calibration Guide. +//************************************************************ + status = ad9361_reg_write(dev, 0x01DB, 0x60); // Set TIA selcc[2:0] + status = ad9361_reg_write(dev, 0x01DD, 0x00); // Set RX TIA1 C MSB[6:0] + status = ad9361_reg_write(dev, 0x01DF, 0x00); // Set RX TIA2 C MSB[6:0] + status = ad9361_reg_write(dev, 0x01DC, 0x72); // Set RX TIA1 C LSB[5:0] + status = ad9361_reg_write(dev, 0x01DE, 0x72); // Set RX TIA2 C LSB[5:0] + +//************************************************************ +// TX Secondary Filter Calibration Setup: Real Bandwidth +// 7.500000MHz, 3dB Corner @ 37.500000MHz +//************************************************************ + status = ad9361_reg_write(dev, 0x00D2, 0x1E); // TX Secondary Filter PDF Cap cal[5:0] + status = ad9361_reg_write(dev, 0x00D1, 0x0C); // TX Secondary Filter PDF Res cal[3:0] + status = ad9361_reg_write(dev, 0x00D0, 0x56); // Pdampbias + +//************************************************************ +// ADC Setup: Tune ADC Performance based on RX analog filter tune +// corner. Real Bandwidth: 6.982753 MHz, ADC Clock Frequency: +// 288.000000 MHz. The values in registers 0x200 - 0x227 need to be +// calculated using the equations in the Calibration Guide. +//************************************************************ + + status = ad9361_reg_write(dev, 0x0200, 0x00); + status = ad9361_reg_write(dev, 0x0201, 0x00); + status = ad9361_reg_write(dev, 0x0202, 0x00); + status = ad9361_reg_write(dev, 0x0203, 0x24); + status = ad9361_reg_write(dev, 0x0204, 0x24); + status = ad9361_reg_write(dev, 0x0205, 0x00); + status = ad9361_reg_write(dev, 0x0206, 0x00); + status = ad9361_reg_write(dev, 0x0207, 0x7C); + status = ad9361_reg_write(dev, 0x0208, 0x46); + status = ad9361_reg_write(dev, 0x0209, 0x3C); + status = ad9361_reg_write(dev, 0x020A, 0x4C); + status = ad9361_reg_write(dev, 0x020B, 0x2C); + status = ad9361_reg_write(dev, 0x020C, 0x4F); + status = ad9361_reg_write(dev, 0x020D, 0x2A); + status = ad9361_reg_write(dev, 0x020E, 0x00); + status = ad9361_reg_write(dev, 0x020F, 0x7F); + status = ad9361_reg_write(dev, 0x0210, 0x7F); + status = ad9361_reg_write(dev, 0x0211, 0x7F); + status = ad9361_reg_write(dev, 0x0212, 0x4A); + status = ad9361_reg_write(dev, 0x0213, 0x4A); + status = ad9361_reg_write(dev, 0x0214, 0x4A); + status = ad9361_reg_write(dev, 0x0215, 0x4D); + status = ad9361_reg_write(dev, 0x0216, 0x4D); + status = ad9361_reg_write(dev, 0x0217, 0x4D); + status = ad9361_reg_write(dev, 0x0218, 0x2E); + status = ad9361_reg_write(dev, 0x0219, 0x9C); + status = ad9361_reg_write(dev, 0x021A, 0x1F); + status = ad9361_reg_write(dev, 0x021B, 0x15); + status = ad9361_reg_write(dev, 0x021C, 0x9C); + status = ad9361_reg_write(dev, 0x021D, 0x1F); + status = ad9361_reg_write(dev, 0x021E, 0x15); + status = ad9361_reg_write(dev, 0x021F, 0x9C); + status = ad9361_reg_write(dev, 0x0220, 0x1F); + status = ad9361_reg_write(dev, 0x0221, 0x2A); + status = ad9361_reg_write(dev, 0x0222, 0x2A); + status = ad9361_reg_write(dev, 0x0223, 0x40); + status = ad9361_reg_write(dev, 0x0224, 0x40); + status = ad9361_reg_write(dev, 0x0225, 0x2C); + status = ad9361_reg_write(dev, 0x0226, 0x00); + status = ad9361_reg_write(dev, 0x0227, 0x00); +//************************************************************ +// Setup and Run BB DC and RF DC Offset Calibrations +//************************************************************ + status = ad9361_reg_write(dev, 0x0193, 0x3F); + status = ad9361_reg_write(dev, 0x0190, 0x0F); // Set BBDC tracking shift M value, only applies when BB DC tracking enabled + status = ad9361_reg_write(dev, 0x0194, 0x01); // BBDC Cal setting + status = ad9361_reg_write(dev, 0x0016, 0x01); // Start BBDC offset cal + + // BBDC Max Cal Time: 8416.667 us. Cal done when 0x016[0]==0 + time_out_cnt = 0; + do{ + status |= ad9361_reg_read(dev, 0x0016, &value); + mdelay(1);// Wait 1ms + time_out_cnt++; + } while((value & 0x01) != 0x00 && time_out_cnt <= AD9361_TIMEOUT_TH); + + status = ad9361_reg_write(dev, 0x0185, 0x20); // Set RF DC offset Wait Count + status = ad9361_reg_write(dev, 0x0186, 0x32); // Set RF DC Offset Count[7:0] + status = ad9361_reg_write(dev, 0x0187, 0x24); // Settings for RF DC cal + status = ad9361_reg_write(dev, 0x018B, 0x83); // Settings for RF DC cal + status = ad9361_reg_write(dev, 0x0188, 0x05); // Settings for RF DC cal + status = ad9361_reg_write(dev, 0x0189, 0x30); // Settings for RF DC cal + status = ad9361_reg_write(dev, 0x0016, 0x02); // Start RFDC offset cal + + // RFDC Max Cal Time: 114511.250 us + time_out_cnt = 0; + do{ + status |= ad9361_reg_read(dev, 0x0016, &value); + mdelay(1);// Wait 1ms + time_out_cnt++; + } while((value & 0x01) != 0x00 && time_out_cnt <= AD9361_TIMEOUT_TH); + +//************************************************************ +// Tx Quadrature Calibration Settings +//************************************************************ + status = ad9361_reg_write(dev, 0x00A0, 0x15); // Set TxQuadcal NCO frequency + status = ad9361_reg_write(dev, 0x00A3, 0x00); // Set TxQuadcal NCO frequency (Only update bits [7:6]) + status = ad9361_reg_write(dev, 0x00A1, 0x7B); // Tx Quad Cal Configuration, Phase and Gain Cal Enable + status = ad9361_reg_write(dev, 0x00A9, 0xFF); // Set Tx Quad Cal Count + status = ad9361_reg_write(dev, 0x00A2, 0x7F); // Set Tx Quad Cal Kexp + status = ad9361_reg_write(dev, 0x00A5, 0x01); // Set Tx Quad Cal Magnitude Threshhold + status = ad9361_reg_write(dev, 0x00A6, 0x01); // Set Tx Quad Cal Magnitude Threshhold + status = ad9361_reg_write(dev, 0x00AA, 0x28); // Set Tx Quad Cal Gain Table index + status = ad9361_reg_write(dev, 0x00A4, 0xF0); // Set Tx Quad Cal Settle Count + status = ad9361_reg_write(dev, 0x00AE, 0x04); // Set Tx Quad Cal LPF Gain index incase Split table mode used + + status = ad9361_reg_write(dev, 0x0169, 0xC0); // Disable Rx Quadrature Calibration before Running Tx Quadrature Calibration + status = ad9361_reg_write(dev, 0x0016, 0x10); // Start Tx Quad cal + + // Wait for cal to complete (Done when 0x016[4]==0) + time_out_cnt = 0; + do{ + status |= ad9361_reg_read(dev, 0x0016, &value); + mdelay(1);// Wait 1ms + time_out_cnt++; + } while((value & 0x10) != 0x00 && time_out_cnt <= AD9361_TIMEOUT_TH); + + status = ad9361_reg_write(dev, 0x016A, 0x75); // Set Kexp Phase + status = ad9361_reg_write(dev, 0x016B, 0x95); // Set Kexp Amplitude & Prevent Positive Gain Bit + status = ad9361_reg_write(dev, 0x0169, 0xCF); // Enable Rx Quadrature Calibration Tracking + status = ad9361_reg_write(dev, 0x018B, 0xAD); // Enable BB and RF DC Tracking Calibrations + status = ad9361_reg_write(dev, 0x0012, 0x02); // Cals done, Set PPORT Config + status = ad9361_reg_write(dev, 0x0013, 0x01); // Set ENSM FDD/TDD bit + status = ad9361_reg_write(dev, 0x0015, 0x0C); // Set Dual Synth Mode, FDD External Control bits properly + +//************************************************************ +// Set Tx Attenuation: Tx1: 0.00 dB, Tx2: 0.00 dB +//************************************************************ + status = ad9361_reg_write(dev, 0x0073, 0x00); + status = ad9361_reg_write(dev, 0x0074, 0x00); + status = ad9361_reg_write(dev, 0x0075, 0x00); + status = ad9361_reg_write(dev, 0x0076, 0x00); +//************************************************************ +// Setup RSSI and Power Measurement Duration Registers +//************************************************************ + status = ad9361_reg_write(dev, 0x0150, 0x0E); // RSSI Measurement Duration 0, 1 + status = ad9361_reg_write(dev, 0x0151, 0x00); // RSSI Measurement Duration 2, 3 + status = ad9361_reg_write(dev, 0x0152, 0xFF); // RSSI Weighted Multiplier 0 + status = ad9361_reg_write(dev, 0x0153, 0x00); // RSSI Weighted Multiplier 1 + status = ad9361_reg_write(dev, 0x0154, 0x00); // RSSI Weighted Multiplier 2 + status = ad9361_reg_write(dev, 0x0155, 0x00); // RSSI Weighted Multiplier 3 + status = ad9361_reg_write(dev, 0x0156, 0x00); // RSSI Delay + status = ad9361_reg_write(dev, 0x0157, 0x00); // RSSI Wait + status = ad9361_reg_write(dev, 0x0158, 0x0D); // RSSI Mode Select + status = ad9361_reg_write(dev, 0x015C, 0x67); // Power Measurement Duration + +//************************************************************ +// Enable External LO & External VCO Buffer +//************************************************************ + status |= ad9361_reg_write(dev, 0x0005, 0x07); + status |= ad9361_reg_write(dev, 0x0057, 0x1C); + + return status; +} diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/dev_profile/ad9528_profile.c b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/dev_profile/ad9528_profile.c new file mode 100644 index 0000000..adf8693 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/dev_profile/ad9528_profile.c @@ -0,0 +1,134 @@ +#include "dev_profile.h" +#include "../config/app_config.h" +#include "../drivers/platform/xilinx_gpio.h" +#include "../drivers/axi_core/spi_engine/spi_engine.h" +#include "../drivers/frequency/ad9528/ad9528.h" + +static struct spi_engine_init_param spi_engine_param = { + .ref_clk_hz = AD9528_SPI_ENGINE_REF_CLK, + .type = SPI_ENGINE, + .spi_engine_baseaddr = AD9528_SPI_ENGINE_BASEADDR, + .cs_delay = AD9528_SPI_ENGINE_CS_DELAY, + .data_width = AD9528_SPI_ENGINE_DATA_WIDTH +}; + +static struct xil_gpio_init_param xil_gpio_param = { + .type = GPIO_PS, + .device_id = AD9528_GPIO_DEVICE_ID +}; + +static struct spi_init_param ad9528_spi_init = { + .device_id = AD9528_SPI_DEVICE_ID, + .max_speed_hz = AD9528_SPI_ENGINE_MAX_SPEED, + .mode = SPI_MODE_0, + .chip_select = AD9528_SPI_CS, + .platform_ops = &spi_eng_platform_ops, + .extra = &spi_engine_param +}; + +static struct gpio_init_param ad9528_gpio_resetb_init = { + .number = AD9528_RESETB, + .platform_ops = &xil_gpio_ops, + .extra = &xil_gpio_param +}; + +static struct gpio_init_param ad9528_gpio_sysref_req_init = { + .number = AD9528_SYSREF_REQ, + .platform_ops = &xil_gpio_ops, + .extra = &xil_gpio_param +}; + +static ad9528pll1Settings_t clockPll1Settings = { + .refA_Frequency_Hz = 50000000, + .refA_Divider = 1, + .refA_bufferCtrl = SINGLE_ENDED, + .refB_Frequency_Hz = 0, + .refB_Divider = 1, + .refB_bufferCtrl = DISABLED, + .vcxo_Frequency_Hz = 50000000, + .vcxoBufferCtrl = SINGLE_ENDED, + .nDivider = 1 +}; + +static ad9528pll2Settings_t clockPll2Settings = { + .rfDivider = 4, + .n2Divider = 20, + .totalNdiv = 80 +}; + +/******************************************************************* + * Output Distribution Settings + * 9369CE02A uses the following clock outputs + * OUT 1: FPGA REFCLK + * OUT 3: FPGA SYSREF + * OUT 12: DUT SYSREF + * OUT 13: DUT REFCLK + ******************************************************************* + */ +static ad9528outputSettings_t clockOutputSettings = { + .outPowerDown = 0xE001, + .outSource = { + AD9528_CHANNEL_DIV, AD9528_CHANNEL_DIV, AD9528_CHANNEL_DIV, AD9528_CHANNEL_DIV, AD9528_CHANNEL_DIV, + AD9528_CHANNEL_DIV, AD9528_CHANNEL_DIV, AD9528_CHANNEL_DIV, AD9528_CHANNEL_DIV, AD9528_CHANNEL_DIV, + AD9528_CHANNEL_DIV, AD9528_CHANNEL_DIV, AD9528_CHANNEL_DIV, AD9528_CHANNEL_DIV + }, + .outBufferCtrl = { + 0,0,0,0,0, + 0,0,0,0,0, + 0,0,0,0 + }, + .outAnalogDelay = { + 0,0,0,0,0, + 0,0,0,0,0, + 0,0,0,0 + }, + .outDigitalDelay = { + 0,0,0,0,0, + 0,0,0,0,0, + 0,0,0,0 + }, + .outChannelDiv = { + 5,25,25,5,5, + 5,5,5,5,5, + 5,5,10,5 + }, + .outFrequency_Hz = { + 200e6, 40e6, 40e6, 200e6, 200e6, + 200e6, 200e6, 200e6, 200e6, 200e6, + 200e6, 200e6, 100e6, 200e6 + } +}; + +static ad9528sysrefSettings_t clockSysrefSettings = { + .sysrefRequestMethod = PIN, + .sysrefSource = INTERNAL, + .sysrefPinEdgeMode = LEVEL_ACTIVE_HIGH, + .sysrefPinBufferMode = DISABLED, + .sysrefPatternMode = CONTINUOUS, + .sysrefNshotMode = FOUR_PULSES, + .sysrefDivide = 256 +}; + +static ad9528spiSettings_t clockSpiSettings = { + .chipSelectIndex = AD9528_SPI_CS, //chip select Index, not used + .writeBitPolarity = 0, //Write bit polarity + .longInstructionWord = 1, //16bit instruction word + .MSBFirst = 1, //MSB first + .CPHA = 0, //Clock phase + .CPOL = 0, //Clock polarity + .enSpiStreaming = 0, //uint8_t enSpiStreaming; + .autoIncAddrUp = 1, //uint8_t autoIncAddrUp; + .fourWireMode = 1 //uint8_t fourWireMode; +}; + +ad9528Init_t ad9528_default_init_param = { + /* SPI */ + .spi_init = &ad9528_spi_init, + .gpio_init_resetb = &ad9528_gpio_resetb_init, + .gpio_init_sysref_req = &ad9528_gpio_sysref_req_init, + .spiSettings = &clockSpiSettings, + .pll1Settings = &clockPll1Settings, + .pll2Settings = &clockPll2Settings, + .outputSettings = &clockOutputSettings, + .sysrefSettings = &clockSysrefSettings +}; diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/dev_profile/ad9653_profile.c b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/dev_profile/ad9653_profile.c new file mode 100644 index 0000000..8f6ba89 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/dev_profile/ad9653_profile.c @@ -0,0 +1,46 @@ +#include "dev_profile.h" +#include "spi.h" +#include "../config/app_config.h" +#include "../drivers/adc/ad9653/ad9653.h" +#include "../drivers/axi_core/spi_engine/spi_engine.h" +#include "../drivers/platform/xilinx_gpio.h" + +static struct spi_engine_init_param spi_engine_param = { + .ref_clk_hz = AD9653_SPI_ENGINE_REF_CLK, + .type = SPI_ENGINE, + .spi_engine_baseaddr = AD9653_SPI_ENGINE_BASEADDR, + .cs_delay = AD9653_SPI_ENGINE_CS_DELAY, + .data_width = AD9653_SPI_ENGINE_DATA_WIDTH +}; + +static struct xil_gpio_init_param xil_gpio_param = { + .type = GPIO_PS, + .device_id = AD9653_GPIO_DEVICE_ID +}; + +static struct spi_init_param ad9653_spi_init = { + .device_id = AD9653_SPI_DEVICE_ID, + .max_speed_hz = AD9653_SPI_ENGINE_MAX_SPEED, + .mode = SPI_MODE_4, + .chip_select = AD9653_SPI_CS, + .platform_ops = &spi_eng_platform_ops, + .extra = &spi_engine_param +}; + +static struct gpio_init_param ad9653_gpio_resetb_init = { + .number = AD9653_POWR_DOWN, + .platform_ops = &xil_gpio_ops, + .extra = &xil_gpio_param +}; + +struct ad9653_init_param ad9653_default_init_param = { + /* SPI */ + .spi_init = &ad9653_spi_init, + .gpio_pdwn = &ad9653_gpio_resetb_init +}; + +const uint32_t ad9653_default_config_len = 36; +const struct ad9653_config ad9653_default_config[] = { + // configuration + +}; diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/dev_profile/ad9694_profile.c b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/dev_profile/ad9694_profile.c new file mode 100644 index 0000000..cf08bfa --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/dev_profile/ad9694_profile.c @@ -0,0 +1,72 @@ +#include "dev_profile.h" +#include "spi.h" +#include "../config/app_config.h" +#include "../drivers/adc/ad9694/ad9694.h" +#include "../drivers/axi_core/spi_engine/spi_engine.h" +#include "../drivers/platform/xilinx_gpio.h" + +static struct spi_engine_init_param spi_engine_param = { + .ref_clk_hz = AD9694_SPI_ENGINE_REF_CLK, + .type = SPI_ENGINE, + .spi_engine_baseaddr = AD9694_SPI_ENGINE_BASEADDR, + .cs_delay = AD9694_SPI_ENGINE_CS_DELAY, + .data_width = AD9694_SPI_ENGINE_DATA_WIDTH +}; + +//static struct xil_gpio_init_param xil_gpio_param = { +// .type = GPIO_PS, +// .device_id = AD9694_GPIO_DEVICE_ID +//}; + +static struct spi_init_param ad9694_spi_init = { + .device_id = AD9694_SPI_DEVICE_ID, + .max_speed_hz = AD9694_SPI_ENGINE_MAX_SPEED, + .mode = SPI_MODE_4, + .chip_select = AD9694_SPI_CS, + .platform_ops = &spi_eng_platform_ops, + .extra = &spi_engine_param +}; + +struct ad9694_init_param ad9694_default_init_param = { + /* SPI */ + .spi_init = &ad9694_spi_init +}; + +const uint32_t ad9694_default_config_len = 36; +const struct ad9694_config ad9694_default_config[] = { + // reset + {0x0000, 0x81}, + {0x1228, 0x4F}, // JESD204B start-up circuit reset + {0x1228, 0x0F}, // JESD204B start-up normal operation + {0x1222, 0x04}, // PLL calibration + {0x1222, 0x00}, // PLL normal operation + {0x1262, 0x08}, // PLL loss of lock control - Clear loss of lock + {0x1262, 0x00}, // PLL loss of lock control - Normal operation + + // system clock + {0x0108, 0x00}, // Clock divider = 1 -> device clock = 368.64MHz + {0x0201, 0x00}, // Chip decimation ration = 1 -> full sample rate + + // channel configuration + {0x0009, 0x03}, // ADC Pair AB & CD receive all spi command + {0x0571, 0x15}, // JESD204B map JTX Link Control 1 + {0x056E, 0x00}, // JESD204B map PLL control, lane rate 6.75~13.5Gbps, actual = 7.3728Gbps + {0x0570, 0x49}, // JESD204B map JTX quick config: L=2 M=2 F=2 + {0x058B, 0x01}, // JESD204B map JTX SCR L config: scrambler disabled, L=2 + {0x0590, 0x2F}, // JESD204B map JTX Subclass & NP config: subclass 1, N' = 16 + {0x058D, 0x1F}, // JESD204B map JTX K config: K = 32 + {0x058F, 0x2D}, // JESD204B map JTX N config: CS = 0, N = 14 + {0x0571, 0x14}, // JESD204B map JTX Link Control 1 + {0x05B0, 0x00}, // SERDOUTx0, SERDOUTx1 power on + {0x0120, 0x0A}, // SYSREF COntrol: continuous mode, captured on falling edge + + // fast detect control + {0x0040, 0x00}, // FD_B/FD_D, FD_A/FD_C function as Fast Detect B/D, A/C output + {0x0245, 0x01}, // Fine fast detect enabled + {0x0247, 0xFE}, // Channel map fast detect upper threshold LSB + {0x0248, 0x1F}, // Channel map fast detect upper threshold MSB, -> 8190 + {0x0249, 0xA4}, // Channel map fast detect lower threshold LSB + {0x024A, 0x1F}, // Channel map fast detect lower threshold MSB, -> 8100 + {0x024B, 0x80}, // Channel map fast detect dwell time LSB + {0x024C, 0x00} // Channel map fast detect dwell time MSB, -> 128 +}; diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/dev_profile/cx9261a_profile.c b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/dev_profile/cx9261a_profile.c new file mode 100644 index 0000000..3005573 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/dev_profile/cx9261a_profile.c @@ -0,0 +1,228 @@ +#include "dev_profile.h" +#include "spi.h" +#include "../config/app_config.h" +#include "../drivers/rf-transceiver/cx9261a/cx9261a.h" +#include "../drivers/axi_core/spi_engine/spi_engine.h" +#include "../drivers/platform/xilinx_gpio.h" + +static struct spi_engine_init_param spi_engine_param = { + .ref_clk_hz = CX9261A_SPI_ENGINE_REF_CLK, + .type = SPI_ENGINE, + .spi_engine_baseaddr = CX9261A_SPI_ENGINE_BASEADDR, + .cs_delay = CX9261A_SPI_ENGINE_CS_DELAY, + .data_width = CX9261A_SPI_ENGINE_DATA_WIDTH +}; + +static struct xil_gpio_init_param xil_gpio_param = { + .type = GPIO_PS, + .device_id = CX9261A_GPIO_DEVICE_ID +}; + +static struct spi_init_param cx9261a_spi_init = { + .device_id = CX9261A_SPI_DEVICE_ID, + .max_speed_hz = CX9261A_SPI_ENGINE_MAX_SPEED, + .mode = SPI_MODE_1, + .chip_select = CX9261A_SPI_CS, + .platform_ops = &spi_eng_platform_ops, + .extra = &spi_engine_param +}; + +static struct gpio_init_param cx9261a_gpio_nrst_init = { + .number = CX9261A_NRST, + .platform_ops = &xil_gpio_ops, + .extra = &xil_gpio_param +}; + +static struct gpio_init_param cx9261a_gpio_txnrx_trx1_init = { + .number = CX9261A_TXNRX_TRX1, + .platform_ops = &xil_gpio_ops, + .extra = &xil_gpio_param +}; + +static struct gpio_init_param cx9261a_gpio_txnrx_trx2_init = { + .number = CX9261A_TXNRX_TRX2, + .platform_ops = &xil_gpio_ops, + .extra = &xil_gpio_param +}; + +static struct gpio_init_param cx9261a_gpio_txnrx_rxfb_init = { + .number = CX9261A_TXNRX_RXFB, + .platform_ops = &xil_gpio_ops, + .extra = &xil_gpio_param +}; + +static struct gpio_init_param cx9261a_gpio_enable_trx1_init = { + .number = CX9261A_ENABLE_TRX1, + .platform_ops = &xil_gpio_ops, + .extra = &xil_gpio_param +}; + +static struct gpio_init_param cx9261a_gpio_enable_trx2_init = { + .number = CX9261A_ENABLE_TRX2, + .platform_ops = &xil_gpio_ops, + .extra = &xil_gpio_param +}; + +static struct gpio_init_param cx9261a_gpio_enable_rxfb_init = { + .number = CX9261A_ENABLE_RXFB, + .platform_ops = &xil_gpio_ops, + .extra = &xil_gpio_param +}; + +static struct gpio_init_param cx9261a_gpio_pl_rst_init = { + .number = CX9261A_PL_RST, + .platform_ops = &xil_gpio_ops, + .extra = &xil_gpio_param +}; + +static struct gpio_init_param cx9261a_gpio_tr_sel_init = { + .number = CX9261A_TR_SEL, + .platform_ops = &xil_gpio_ops, + .extra = &xil_gpio_param +}; + +static struct gpio_init_param cx9261a_gpio_tdd_fdd_sel_init = { + .number = CX9261A_TDD_FDD_SEL, + .platform_ops = &xil_gpio_ops, + .extra = &xil_gpio_param +}; + +static struct gpio_init_param cx9261a_gpio_r1t1_r2t2_sel_init = { + .number = CX9261A_R1T1_R2T2_SEL, + .platform_ops = &xil_gpio_ops, + .extra = &xil_gpio_param +}; + +static struct gpio_init_param cx9261a_gpio_sp_dp_sel_init = { + .number = CX9261A_SP_DP_SEL, + .platform_ops = &xil_gpio_ops, + .extra = &xil_gpio_param +}; + +static struct gpio_init_param cx9261a_gpio_mclk_delay_ctrl0_init = { + .number = CX9261A_MCLK_DELAY_CTRL0, + .platform_ops = &xil_gpio_ops, + .extra = &xil_gpio_param +}; + +static struct gpio_init_param cx9261a_gpio_mclk_delay_ctrl1_init = { + .number = CX9261A_MCLK_DELAY_CTRL1, + .platform_ops = &xil_gpio_ops, + .extra = &xil_gpio_param +}; + +static struct gpio_init_param cx9261a_gpio_mclk_delay_ctrl2_init = { + .number = CX9261A_MCLK_DELAY_CTRL2, + .platform_ops = &xil_gpio_ops, + .extra = &xil_gpio_param +}; + +static struct gpio_init_param cx9261a_gpio_hop_flag_init = { + .number = CX9261A_HOP_FLAG, + .platform_ops = &xil_gpio_ops, + .extra = &xil_gpio_param +}; + +struct cx9261a_init_param cx9261a_default_init_param = { + /* SPI */ + .spi_init = &cx9261a_spi_init, + .gpio_nrst = &cx9261a_gpio_nrst_init, + .gpio_txnrx_trx1 = &cx9261a_gpio_txnrx_trx1_init, + .gpio_txnrx_trx2 = &cx9261a_gpio_txnrx_trx2_init, + .gpio_txnrx_rxfb = &cx9261a_gpio_txnrx_rxfb_init, + .gpio_enable_trx1 = &cx9261a_gpio_enable_trx1_init, + .gpio_enable_trx2 = &cx9261a_gpio_enable_trx2_init, + .gpio_enable_rxfb = &cx9261a_gpio_enable_rxfb_init, + .gpio_pl_rst = &cx9261a_gpio_pl_rst_init, + .gpio_tr_sel = &cx9261a_gpio_tr_sel_init, + .gpio_tdd_fdd_sel = &cx9261a_gpio_tdd_fdd_sel_init, + .gpio_r1t1_r2t2_sel = &cx9261a_gpio_r1t1_r2t2_sel_init, + .gpio_sp_dp_sel = &cx9261a_gpio_sp_dp_sel_init, + .gpio_mclk_delay_ctrl0 = &cx9261a_gpio_mclk_delay_ctrl0_init, + .gpio_mclk_delay_ctrl1 = &cx9261a_gpio_mclk_delay_ctrl1_init, + .gpio_mclk_delay_ctrl2 = &cx9261a_gpio_mclk_delay_ctrl2_init, + .gpio_hop_flag = &cx9261a_gpio_hop_flag_init +}; + +CX9261A_CX9261AConfiguration cx9261a_configuration = { + // 电源管理 (与评估软件电源管理自定义电源里面勾选项相对应,先左再右,从上往下) + .powerManagement = + { + // 接收模式电源管理 + .rxPower = {0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1}, + // 发射模式电源管理 + .txPower = {1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1}, + // FDD模式电源管理 + .fddPower = {1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, + 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1}, + .powerMode = CX9261A_PWM_Duplex, + }, + // 接口模式 + .interface = {.workMode = CX9261A_WKM_FDD, + .trMode = CX9261A_TRM_R1T1, + .portMode = CX9261A_PORTM_Single, + .ioMode = CX9261A_IOM_CMOS}, + // 时钟相关 + .clock = {.ref = 100, + .adc = 64, + .refDiv = 1, + .bbUseIntDiv = false, + .refDoubler = false}, + // 本振相关 + // 本振来源 + .pllSource = {.rxUseExt = false, + .txUseExt = false, + .rx1Source = CX9261A_LOSRC_Pll1, + .rx2Source = CX9261A_LOSRC_Pll2, + .rx3Source = CX9261A_LOSRC_Off, + .tx1Source = CX9261A_LOSRC_Pll1, + .tx2Source = CX9261A_LOSRC_Pll2}, + // 本振频率 注意:使用的所有PLL,频率必须设为正数 + .pllFreq = {.pll1Freq = 121.88, + .pll2Freq = 5000, + .pll3Freq = 800, + .pll4Freq = 900, + .pll5Freq = 1000}, + // Rx通道 注意:tia推荐配置为6 Mixer为三个通道共用同一个寄存器 + .rx1Config = {.bandwidth = 32, .tia = 6, .mixer = 31}, + .rx2Config = {.bandwidth = 32, .tia = 6, .mixer = 31}, + .rx3Config = {.bandwidth = 32, .tia = 6, .mixer = 31}, + // Tx通道 + .tx1Config = {.bandwidth = 20, .mixer = 63}, + .tx2Config = {.bandwidth = 20, .mixer = 63}, + // 接收滤波器 + .rxFilters = {.fir = 0, .hbf1 = 0, .hbf2 = 0, .hbf3 = 0, .cic = 0}, + // 发射滤波器 + .txFilters = {.fir = 0, .hbf1 = 2, .hbf2 = 2, .hbf3 = 0, .cic = 0}, + // Rx NCO + .rxNco = {.rxUseBist = false, + .rxNCOBypass = true, + .rxNCOUpward = true, + .rxNCOMaster = true, + .rxNCOFreq = 0}, + // Tx NCO + .txNco = {.txUseBist = false, .txNCOFreq = 0}, + // AGC 注意:mode = 0表示关闭AGC,此时其他的参数可以不配置 + // 校准 + .calib = {.calibDC = true, + .dcCalibMethod = CX9261A_DCCALM_Tracking, + .dcTrackingLength = 16384, + .dcHighPassFactor = 8191, + .rx1CalibPll = CX9261A_LOSRC_Pll1 | CX9261A_LOSRC_Pll2, + .rx2CalibPll = CX9261A_LOSRC_Pll1 | CX9261A_LOSRC_Pll2, + .rx3CalibPll = CX9261A_LOSRC_Pll5, + .tx1CalibPll = 0, + .tx2CalibPll = 0, + .rxMethod = CX9261A_CALM_Tracking, + .txMethod = CX9261A_CALM_Bisec, + .f0 = 4, +// .rxMultiPoints = {2200, 2400, 2600, 2800, 3000, 3200, 3400, +// 3600, 3800, 4000, 4200, 4400, 4600, 4800, +// 5000, 5200, 5400, 5600, 5800, 6000} + }, + .agc = {.mode = 0}, + .tempComp = CX9261A_TEMPCP_Band +}; + diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/dev_profile/dev_profile.h b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/dev_profile/dev_profile.h new file mode 100644 index 0000000..c4835bf --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/dev_profile/dev_profile.h @@ -0,0 +1,62 @@ +#ifndef _DEV_PROFILE_H_ +#define _DEV_PROFILE_H_ + +#include "irq.h" +#include "error.h" +#include "../drivers/frequency/hmc7044/hmc7044.h" +#include "../drivers/frequency/ad9528/ad9528.h" +#include "../drivers/frequency/lmk04828/lmk04828.h" +#include "../drivers/frequency/lmx2594/lmx2594.h" +#include "../drivers/rf-transceiver/ad9361_reg/ad9361_reg.h" +#include "../drivers/rf-transceiver/ad9361/ad9361_api.h" +#include "../drivers/rf-transceiver/cx9261a/cx9261a.h" +#include "../drivers/rf-transceiver/cx9261a/cx9261adriver_c.h" +#include "../drivers/adc/ad9694/ad9694.h" +#include "../drivers/adc/ad9653/ad9653.h" +#include "../config/app_config.h" + +// device parameters +extern struct irq_init_param intc_init_param; +extern struct timer_init_param apptimer_init_param; + +// HMC7044 +extern struct hmc7044_init_param hmc7044_default_init_param; + +// AD9528 +extern ad9528Init_t ad9528_default_init_param; + +// LMK04828 +extern struct lmk04828_init_param lmk04828_default_init_param; +extern const struct lmk04828_config lmk04828_default_config[]; +extern const uint32_t lmk04828_default_config_len; + +// LMX2594 +extern struct lmx2594_init_param lmx2594_adc_init_param; +extern struct lmx2594_init_param lmx2594_dac_init_param; +extern const struct lmx2594_config lmx2594_default_config[]; +extern const uint32_t lmx2594_default_config_len; + +// AD9361 +extern AD9361_InitParam ad9361_default_init_param; +extern AD9361_RXFIRConfig rx_fir_config; +extern AD9361_TXFIRConfig tx_fir_config; +extern struct ad9361_reg_init_param ad9361_1_reg_default_init_param; +extern struct ad9361_reg_init_param ad9361_2_reg_default_init_param; +uint32_t ad9361_reg_config(struct ad9361_reg_dev *dev); + +// CX9261A +extern struct cx9261a_init_param cx9261a_default_init_param; +extern CX9261A_CX9261AConfiguration cx9261a_configuration; + +// AD9653 +extern struct ad9653_init_param ad9653_default_init_param; +extern const struct ad9653_config ad9653_default_config[]; +extern const uint32_t ad9653_default_config_len; + +// AD9694 +extern struct ad9694_init_param ad9694_default_init_param; +extern const struct ad9694_config ad9694_default_config[]; +extern const uint32_t ad9694_default_config_len; + + +#endif /* SRC_DEV_PROFILE_H_ */ diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/dev_profile/hmc7044_profile.c b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/dev_profile/hmc7044_profile.c new file mode 100644 index 0000000..a091b5f --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/dev_profile/hmc7044_profile.c @@ -0,0 +1,132 @@ +#include "dev_profile.h" +#include "../config/app_config.h" +#include "../drivers/platform/xilinx_gpio.h" +#include "../drivers/axi_core/spi_engine/spi_engine.h" +#include "../drivers/frequency/hmc7044/hmc7044.h" + + +static struct spi_engine_init_param spi_engine_param = { + .ref_clk_hz = HMC7044_SPI_ENGINE_REF_CLK, + .type = SPI_ENGINE, + .spi_engine_baseaddr = HMC7044_SPI_ENGINE_BASEADDR, + .cs_delay = HMC7044_SPI_ENGINE_CS_DELAY, + .data_width = HMC7044_SPI_ENGINE_DATA_WIDTH +}; + +//static struct xil_gpio_init_param xil_gpio_param = { +// .type = GPIO_PS, +// .device_id = AD9361_GPIO_DEVICE_ID +//}; + +// hmc7044 spi settings +static struct spi_init_param hmc7044_spi_init_param = { + .device_id = HMC7044_SPI_DEVICE_ID, + .max_speed_hz = HMC7044_SPI_ENGINE_MAX_SPEED, + .mode = SPI_MODE_4, + .chip_select = HMC7044_SPI_CS, + .platform_ops = &spi_eng_platform_ops, + .extra = &spi_engine_param +}; + +// hmc7044 channel specifications +struct hmc7044_chan_spec hmc7044_chan_spec[4] = { + /* AD9361_XTAL */ + { + .disable = 0, + .num = 3, + .divider = 100, + .coarse_delay = 0, + .fine_delay = 0, + .high_performance_mode_dis = true, + .start_up_mode_dynamic_enable = false, + .dynamic_driver_enable = false, + .output_control0_rb4_enable = true, + .force_mute_enable = false, + .driver_mode = CML, + .driver_impedance = INTERNAL_100OHM_PER_PIN, + .out_mux_mode = CHANNEL_DIV + }, + /* FPGA_DAC_LOGIC_CLK */ + { + .disable = 0, + .num = 4, + .divider = 10, + .coarse_delay = 0, + .fine_delay = 0, + .high_performance_mode_dis = true, + .start_up_mode_dynamic_enable = false, + .dynamic_driver_enable = false, + .output_control0_rb4_enable = true, + .force_mute_enable = false, + .driver_mode = CML, + .driver_impedance = INTERNAL_100OHM_PER_PIN, + .out_mux_mode = CHANNEL_DIV + }, + /* B_AD9361_XTAL */ + { + .disable = 0, + .num = 12, + .divider = 100, + .coarse_delay = 0, + .fine_delay = 0, + .high_performance_mode_dis = false, + .start_up_mode_dynamic_enable = false, + .dynamic_driver_enable = false, + .output_control0_rb4_enable = true, + .force_mute_enable = false, + .driver_mode = CML, + .driver_impedance = INTERNAL_100OHM_PER_PIN, + .out_mux_mode = CHANNEL_DIV + }, + /* AD9361_RX_EXT_LO */ + { + .disable = 0, + .num = 13, + .divider = 10, + .coarse_delay = 0, + .fine_delay = 0, + .high_performance_mode_dis = false, + .start_up_mode_dynamic_enable = false, + .dynamic_driver_enable = false, + .output_control0_rb4_enable = true, + .force_mute_enable = false, + .driver_mode = CML, + .driver_impedance = INTERNAL_100OHM_PER_PIN, + .out_mux_mode = CHANNEL_DIV + }, +}; + +// hmc7044 default configurations +struct hmc7044_init_param hmc7044_default_init_param = { + .spi_init = &hmc7044_spi_init_param, + .clkin_freq = {0, 100000000, 0, 0}, + .vcxo_freq = 100000000, + .pll2_freq = 2500000000, + .pll1_loop_bw = 200, + .sysref_timer_div = 1536, + .in_buf_mode = { + BUFFER_DISABLE, + ENABLE_AC_COUPLE | ENABLE_INTERNAL_TERM | BUFFER_ENABLE, + BUFFER_DISABLE, + BUFFER_DISABLE, + ENABLE_AC_COUPLE | ENABLE_INTERNAL_TERM | BUFFER_ENABLE + }, + .gpi_ctrl = { + GPI_DISABLE, + GPI_DISABLE, + CHIP_SLEEP_MODE, + PULSE_GEN_REQUSET + }, + .gpo_ctrl = { + PLL1_LOCK_DETECT | GPO_CMOS_MODE, + PLL2_LOCK_DETECT | GPO_CMOS_MODE, + GPO_DISABLE, + GPO_DISABLE + }, + .num_channels = 4, + .pll1_ref_prio_ctrl = 0xE4, + .sync_pin_mode = SYNC_MULTICHIP, + .high_performance_mode_clock_dist_en = false, + .pulse_gen_mode = PULSE_ONE, + .channels = hmc7044_chan_spec +}; diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/dev_profile/intc_profile.c b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/dev_profile/intc_profile.c new file mode 100644 index 0000000..ae8990e --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/dev_profile/intc_profile.c @@ -0,0 +1,14 @@ +#include "dev_profile.h" +#include "irq.h" +#include "../config/app_config.h" +#include "../drivers/platform/xilinx_irq.h" + +struct xil_irq_init_param xil_intc_init_param = { + .type = IRQ_PS +}; + +struct irq_init_param intc_init_param = { + .irq_ctrl_id = INTC_DEVICE_ID, + .platform_ops = &xil_irq_ops, + .extra = &xil_intc_init_param +}; diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/dev_profile/lmk04828_profile.c b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/dev_profile/lmk04828_profile.c new file mode 100644 index 0000000..3965fac --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/dev_profile/lmk04828_profile.c @@ -0,0 +1,182 @@ +#include "dev_profile.h" +#include "spi.h" +#include "../config/app_config.h" +#include "../drivers/frequency/lmk04828/lmk04828.h" +#include "../drivers/axi_core/spi_engine/spi_engine.h" +#include "../drivers/platform/xilinx_gpio.h" + +static struct spi_engine_init_param spi_engine_param = { + .ref_clk_hz = LMK04828_SPI_ENGINE_REF_CLK, + .type = SPI_ENGINE, + .spi_engine_baseaddr = LMK04828_SPI_ENGINE_BASEADDR, + .cs_delay = LMK04828_SPI_ENGINE_CS_DELAY, + .data_width = LMK04828_SPI_ENGINE_DATA_WIDTH +}; + +//static struct xil_gpio_init_param xil_gpio_param = { +// .type = GPIO_PS, +// .device_id = LMK04828_GPIO_DEVICE_ID +//}; + +static struct spi_init_param lmk04828_spi_init = { + .device_id = LMK04828_SPI_DEVICE_ID, + .max_speed_hz = LMK04828_SPI_ENGINE_MAX_SPEED, + .mode = SPI_MODE_0, + .chip_select = LMK04828_SPI_CS, + .platform_ops = &spi_eng_platform_ops, + .extra = &spi_engine_param +}; + +struct lmk04828_init_param lmk04828_default_init_param = { + /* SPI */ + .spi_init = &lmk04828_spi_init +}; + +const uint32_t lmk04828_default_config_len = 137; +const struct lmk04828_config lmk04828_default_config[] = { + // 192MHz + {0x0000, 0x90}, // [7] reset; [4] 3-wire mode disabled + {0x0000, 0x10}, // [7] normal operation; [4] 3-wire mode disabled + {0x0002, 0x00}, // [0] normal operation + {0x0003, 0x06}, // [7-0] product device type, read only, default: 6 + {0x0004, 0xD0}, // [7-0] msb of product identifier, read only, default: 208 + {0x0005, 0x5B}, // [7-0] lsb of product identifier, read only, default: 91 + {0x0006, 0x00}, // [7-0] ic version identifier, read only, default: 32 + {0x000C, 0x51}, // [7-0] msb of vendor identifier, read only, default: 81 + {0x000D, 0x04}, // [7-0] lsb of vendor identifier, read only, default: 4 + // device clock 0 + {0x0100, 0x10}, // [6] output drive level (ODL); [5] input drive level (IDL); [4-0] device clock (DCLK) output divider + {0x0101, 0x55}, // DCLK: [7-4] output digital delay (DDLY) high count; [3-0] DDLY low count + {0x0102, 0x55}, + {0x0103, 0x01}, // DCLK: [7-3] analog delay (ADLY) value, 25 ps per lsb; [2] ADLY input mux; [1-0] DCLK input mux + {0x0104, 0x22}, // [6] DCLK half step value; [5] SDCLK output MUX; [4-1] SDCLK DDLY; [0] SYSREF half step value + {0x0105, 0x00}, // SYSREF: [4] ADLY enable; [3:0] ADLY value, 600 ps + 150 ps per lsb + {0x0106, 0xF0}, // [7] DCLK DDLY enable; [6] DCLK glitchless half step enable; [5] DCLK glitchless ADLY enable; [4] DCLK ADLY enable; [3]: clock group enable; [2-1] SYSREF disable mode; [0]: SYSREF disable + {0x0107, 0x11}, // [7] SDCLK output polarity; [6-4] SDCLK output format; [3] DCLK output polarity; [2:0] DCLK output format + // device clock 2 + {0x0108, 0x10}, // [6] output drive level (ODL); [5] input drive level (IDL); [4-0] device clock (DCLK) output divider + {0x0109, 0x55}, // DCLK: [7-4] output digital delay (DDLY) high count; [3-0] DDLY low count + {0x010A, 0x55}, + {0x010B, 0x00}, // DCLK: [7-3] analog delay (ADLY) value, 25 ps per lsb; [2] ADLY input mux; [1-0] DCLK input mux + {0x010C, 0x22}, // [6] DCLK half step value; [5] SDCLK output MUX; [4-1] SDCLK DDLY; [0] SYSREF half step value + {0x010D, 0x00}, // SYSREF: [4] ADLY enable; [3:0] ADLY value, 600 ps + 150 ps per lsb + {0x010E, 0xF0}, // [7] DCLK DDLY enable; [6] DCLK glitchless half step enable; [5] DCLK glitchless ADLY enable; [4] DCLK ADLY enable; [3]: clock group enable; [2-1] SYSREF disable mode; [0]: SYSREF disable + {0x010F, 0x10}, // [7] SDCLK output polarity; [6-4] SDCLK output format; [3] DCLK output polarity; [2:0] DCLK output format + // device clock 4 + {0x0110, 0x10}, // [6] output drive level (ODL); [5] input drive level (IDL); [4-0] device clock (DCLK) output divider + {0x0111, 0x55}, // DCLK: [7-4] output digital delay (DDLY) high count; [3-0] DDLY low count + {0x0112, 0x55}, + {0x0113, 0x00}, // DCLK: [7-3] analog delay (ADLY) value, 25 ps per lsb; [2] ADLY input mux; [1-0] DCLK input mux + {0x0114, 0x22}, // [6] DCLK half step value; [5] SDCLK output MUX; [4-1] SDCLK DDLY; [0] SYSREF half step value + {0x0115, 0x00}, // SYSREF: [4] ADLY enable; [3:0] ADLY value, 600 ps + 150 ps per lsb + {0x0116, 0xF0}, // [7] DCLK DDLY enable; [6] DCLK glitchless half step enable; [5] DCLK glitchless ADLY enable; [4] DCLK ADLY enable; [3]: clock group enable; [2-1] SYSREF disable mode; [0]: SYSREF disable + {0x0117, 0x11}, // [7] SDCLK output polarity; [6-4] SDCLK output format; [3] DCLK output polarity; [2:0] DCLK output format + // device clock 6 + {0x0118, 0x10}, // [6] output drive level (ODL); [5] input drive level (IDL); [4-0] device clock (DCLK) output divider + {0x0119, 0x55}, // DCLK: [7-4] output digital delay (DDLY) high count; [3-0] DDLY low count + {0x011A, 0x55}, + {0x011B, 0x00}, // DCLK: [7-3] analog delay (ADLY) value, 25 ps per lsb; [2] ADLY input mux; [1-0] DCLK input mux + {0x011C, 0x02}, // [6] DCLK half step value; [5] SDCLK output MUX; [4-1] SDCLK DDLY; [0] SYSREF half step value + {0x011D, 0x00}, // SYSREF: [4] ADLY enable; [3:0] ADLY value, 600 ps + 150 ps per lsb + {0x011E, 0xF0}, // [7] DCLK DDLY enable; [6] DCLK glitchless half step enable; [5] DCLK glitchless ADLY enable; [4] DCLK ADLY enable; [3]: clock group enable; [2-1] SYSREF disable mode; [0]: SYSREF disable + {0x011F, 0x55}, // [7] SDCLK output polarity; [6-4] SDCLK output format; [3] DCLK output polarity; [2:0] DCLK output format + // device clock 8 + {0x0120, 0x10}, // [6] output drive level (ODL); [5] input drive level (IDL); [4-0] device clock (DCLK) output divider + {0x0121, 0x55}, // DCLK: [7-4] output digital delay (DDLY) high count; [3-0] DDLY low count + {0x0122, 0x55}, + {0x0123, 0x00}, // DCLK: [7-3] analog delay (ADLY) value, 25 ps per lsb; [2] ADLY input mux; [1-0] DCLK input mux + {0x0124, 0x22}, // [6] DCLK half step value; [5] SDCLK output MUX; [4-1] SDCLK DDLY; [0] SYSREF half step value + {0x0125, 0x00}, // SYSREF: [4] ADLY enable; [3:0] ADLY value, 600 ps + 150 ps per lsb + {0x0126, 0xF0}, // [7] DCLK DDLY enable; [6] DCLK glitchless half step enable; [5] DCLK glitchless ADLY enable; [4] DCLK ADLY enable; [3]: clock group enable; [2-1] SYSREF disable mode; [0]: SYSREF disable + {0x0127, 0x55}, // [7] SDCLK output polarity; [6-4] SDCLK output format; [3] DCLK output polarity; [2:0] DCLK output format + // device clock 10 + {0x0128, 0x10}, // [6] output drive level (ODL); [5] input drive level (IDL); [4-0] device clock (DCLK) output divider + {0x0129, 0x55}, // DCLK: [7-4] output digital delay (DDLY) high count; [3-0] DDLY low count + {0x012A, 0x55}, + {0x012B, 0x00}, // DCLK: [7-3] analog delay (ADLY) value, 25 ps per lsb; [2] ADLY input mux; [1-0] DCLK input mux + {0x012C, 0x22}, // [6] DCLK half step value; [5] SDCLK output MUX; [4-1] SDCLK DDLY; [0] SYSREF half step value + {0x012D, 0x00}, // SYSREF: [4] ADLY enable; [3:0] ADLY value, 600 ps + 150 ps per lsb + {0x012E, 0xF0}, // [7] DCLK DDLY enable; [6] DCLK glitchless half step enable; [5] DCLK glitchless ADLY enable; [4] DCLK ADLY enable; [3]: clock group enable; [2-1] SYSREF disable mode; [0]: SYSREF disable + {0x012F, 0x51}, // [7] SDCLK output polarity; [6-4] SDCLK output format; [3] DCLK output polarity; [2:0] DCLK output format + // device clock 12 + {0x0130, 0x10}, // [6] output drive level (ODL); [5] input drive level (IDL); [4-0] device clock (DCLK) output divider + {0x0131, 0x55}, // DCLK: [7-4] output digital delay (DDLY) high count; [3-0] DDLY low count + {0x0132, 0x55}, + {0x0133, 0x00}, // DCLK: [7-3] analog delay (ADLY) value, 25 ps per lsb; [2] ADLY input mux; [1-0] DCLK input mux + {0x0134, 0x22}, // [6] DCLK half step value; [5] SDCLK output MUX; [4-1] SDCLK DDLY; [0] SYSREF half step value + {0x0135, 0x00}, // SYSREF: [4] ADLY enable; [3:0] ADLY value, 600 ps + 150 ps per lsb + {0x0136, 0xF0}, // [7] DCLK DDLY enable; [6] DCLK glitchless half step enable; [5] DCLK glitchless ADLY enable; [4] DCLK ADLY enable; [3]: clock group enable; [2-1] SYSREF disable mode; [0]: SYSREF disable + {0x0137, 0x55}, // [7] SDCLK output polarity; [6-4] SDCLK output format; [3] DCLK output polarity; [2:0] DCLK output format + // clock distribution source + {0x0138, 0x20}, // [6-5] VCO mux; [4] OSCout mux; [3:0] OSCout format + {0x0139, 0x03}, // [2] SYSREF output mux; [1-0] SYSREF source + {0x013A, 0x0C}, // [4-0] SYSREF divider [12:8] + {0x013B, 0x00}, // [7-0] SYSREF divider [7:0] + {0x013C, 0x00}, // [4-0] SYSREF DDLY [12:8] + {0x013D, 0x08}, // [7-0] SYSREF DDLY [7:0] + {0x013E, 0x03}, // [1-0] SYSREF pulse count + {0x013F, 0x00}, // [4] pll2 mux; [3] pll1 mux; [2-1] feedback mux; [0] feedback mux enable + {0x0140, 0x0B}, // power-down control: [7] pll1; [6] vco_ldo; [5] vco; [4] OSCin; [3] individual SYSREF; [2] SYSREF; [1] SYSREF DDLY; [0] SYSREF pluse generator + {0x0141, 0x00}, // dynamic DDLY control + {0x0142, 0x00}, // dynamic DDLY step control + {0x0143, 0x10}, + {0x0144, 0xFF}, + {0x0145, 0x7F}, + {0x0146, 0x12}, + {0x0147, 0x1A}, + {0x0148, 0x03}, + {0x0149, 0x05}, + {0x014A, 0x1B}, + {0x014B, 0x16}, + {0x014C, 0x00}, + {0x014D, 0x00}, + {0x014E, 0xC0}, + {0x014F, 0x7F}, + {0x0150, 0x03}, + {0x0151, 0x02}, + {0x0152, 0x00}, + {0x0153, 0x00}, + {0x0154, 0x78}, + {0x0155, 0x00}, + {0x0156, 0x7D}, + {0x0157, 0x00}, + {0x0158, 0x96}, + {0x0159, 0x06}, + {0x015A, 0x00}, + {0x015B, 0xD4}, + {0x015C, 0x20}, + {0x015D, 0x00}, + {0x015E, 0x00}, + {0x015F, 0x3B}, + {0x0160, 0x00}, + {0x0161, 0x02}, + {0x0162, 0x44}, + {0x0163, 0x00}, + {0x0164, 0x00}, + {0x0165, 0x0C}, + {0x0171, 0xAA}, + {0x0172, 0x02}, + {0x017C, 0x15}, + {0x017D, 0x33}, + {0x0166, 0x00}, + {0x0167, 0x00}, + {0x0168, 0x19}, + {0x0169, 0x59}, + {0x016A, 0x20}, + {0x016B, 0x00}, + {0x016C, 0x00}, + {0x016D, 0x00}, + {0x016E, 0x1B}, + {0x0173, 0x00}, + {0x0182, 0x00}, + {0x0183, 0x00}, + {0x0184, 0x00}, + {0x0185, 0x00}, + {0x0188, 0x00}, + {0x0189, 0x00}, + {0x018A, 0x00}, + {0x018B, 0x00}, + {0x1FFD, 0x00}, + {0x1FFE, 0x00}, + {0x1FFF, 0x53} +}; diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/dev_profile/lmx2594_profile.c b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/dev_profile/lmx2594_profile.c new file mode 100644 index 0000000..6238ebb --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/dev_profile/lmx2594_profile.c @@ -0,0 +1,181 @@ +#include "dev_profile.h" +#include "spi.h" +#include "../config/app_config.h" +#include "../drivers/frequency/lmx2594/lmx2594.h" +#include "../drivers/axi_core/spi_engine/spi_engine.h" +#include "../drivers/platform/xilinx_gpio.h" + +static struct spi_engine_init_param spi_engine_param = { + .ref_clk_hz = AD9653_SPI_ENGINE_REF_CLK, + .type = SPI_ENGINE, + .spi_engine_baseaddr = AD9653_SPI_ENGINE_BASEADDR, + .cs_delay = AD9653_SPI_ENGINE_CS_DELAY, + .data_width = AD9653_SPI_ENGINE_DATA_WIDTH +}; + +//static struct xil_gpio_init_param xil_gpio_param = { +// .type = GPIO_PS, +// .device_id = AD9653_GPIO_DEVICE_ID +//}; + +static struct spi_init_param lmx2594_adc_spi_init = { + .device_id = LMX2594_ADC_SPI_DEVICE_ID, + .max_speed_hz = LMX2594_ADC_SPI_ENGINE_MAX_SPEED, + .mode = SPI_MODE_0, + .chip_select = LMX2594_ADC_SPI_CS, + .platform_ops = &spi_eng_platform_ops, + .extra = &spi_engine_param +}; + +static struct spi_init_param lmx2594_dac_spi_init = { + .device_id = LMX2594_DAC_SPI_DEVICE_ID, + .max_speed_hz = LMX2594_DAC_SPI_ENGINE_MAX_SPEED, + .mode = SPI_MODE_0, + .chip_select = LMX2594_DAC_SPI_CS, + .platform_ops = &spi_eng_platform_ops, + .extra = &spi_engine_param +}; + +struct lmx2594_init_param lmx2594_adc_init_param = { + /* SPI */ + .spi_init = &lmx2594_adc_spi_init +}; + +struct lmx2594_init_param lmx2594_dac_init_param = { + /* SPI */ + .spi_init = &lmx2594_dac_spi_init +}; + +const uint32_t lmx2594_default_config_len = 110; +const struct lmx2594_config lmx2594_default_config[] = { + // 0 ~ 78: General configuration + // 79 ~ 106: Ramping configuration + // 107 ~ 112: Readback registers + + // Recommended Initial Power-Up Sequence + // For the most reliable programming, TI recommends this procedure:: + // 1. Apply power to device. + // 2. Program RESET = 1 to reset registers. + // 3. Program RESET = 0 to remove reset. + // 4. Program registers as shown in the register map in REVERSE order from highest to lowest. + // 5. Wait 10 ms. + // 6. Program register R0 one additional time with FCAL_EN = 1 to ensure that the VCO calibration runs from a stable state. + + // Reset + { 0, 0x0002}, + + // Remove Reset + { 0, 0x0000}, + + // Reverse order programming + {106, 0x0000}, + {105, 0x0021}, + {104, 0x0000}, + {103, 0xD555}, + {102, 0x3F97}, + {101, 0x0011}, + {100, 0x0000}, + { 99, 0x2AAB}, + { 98, 0x01A0}, + { 97, 0x0888}, + { 96, 0x0000}, + { 95, 0x0000}, // fixed + { 94, 0x0000}, // fixed + { 93, 0x0000}, // fixed + { 92, 0x0000}, // fixed + { 91, 0x0000}, // fixed + { 90, 0x0000}, // fixed + { 89, 0x0000}, // fixed + { 88, 0x0000}, // fixed + { 87, 0x0000}, // fixed + { 86, 0x5879}, + { 85, 0xEC58}, + { 84, 0x0001}, + { 83, 0x54C9}, + { 82, 0x2961}, + { 81, 0x0000}, + { 80, 0x4000}, + { 79, 0x001F}, + { 78, 0x0003}, // [8:1] VCO_CAPCTRL_STRT + { 77, 0x0000}, // fixed + { 76, 0x000C}, // fixed + { 75, 0x0800}, // [10:6] CHDIV + { 74, 0x0000}, // [11:6] JESD_DAC4_CTRL; [5:0] JESD_DAC3_CTRL + { 73, 0x003F}, // [11:6] JESD_DAC2_CTRL; [5:0] JESD_DAC1_CTRL + { 72, 0x0001}, // [10:0] SYSREF_DIV + { 71, 0x0081}, // [7:5] SYSREF_DIV_PRE; [4] SYSREF_PULSE; [3] SYSREF_EN; [2] SYSREF_REPEAT + { 70, 0xC350}, // [15:0] MASH_RST_COUNT + { 69, 0x0000}, // [15:0] MASH_RST_COUNT + { 68, 0x03E8}, // fixed + { 67, 0x0000}, // fixed + { 66, 0x01F4}, // fixed + { 65, 0x0000}, // fixed + { 64, 0x1388}, // fixed + { 63, 0x0000}, // fixed + { 62, 0x0322}, // fixed + { 61, 0x00A8}, // fixed + { 60, 0x0000}, // [15:0] LD_DLY + { 59, 0x0001}, // [0] LD_TYPE + { 58, 0x9001}, // [15] INPIN_IGNORE; [14] INPIN_HYST; [13:12] INPIN_LVL; [11:9] INPIN_FMT + { 57, 0x0020}, // fixed + { 56, 0x0000}, // fixed + { 55, 0x0000}, // fixed + { 54, 0x0000}, // fixed + { 53, 0x0000}, // fixed + { 52, 0x0820}, // fixed + { 51, 0x0080}, // fixed + { 50, 0x0000}, // fixed + { 49, 0x4180}, // fixed + { 48, 0x0300}, // fixed + { 47, 0x0300}, // fixed + { 46, 0x07FC}, // [1:0] OUTB_MUX + { 45, 0xC0DF}, // [12:11] OUTA_MUX; [10:9] OUT_ISET; [5:0] OUTB_PWR + { 44, 0x1AA3}, // [13:8] OUTA_PWR; [7] OUTB_PD; [6] OUTA_PD; [5] MASH_RESET_N; [2:0] MASH_ORDER + { 43, 0x0000}, // [15:0] PLL_NUM + { 42, 0x0000}, // [15:0] PLL_NUM + { 41, 0x0000}, // [15:0] MASH_SEE + { 40, 0x0000}, // [15:0] MASH_SEE + { 39, 0x03E8}, // [15:0] PLL_DEN + { 38, 0x0000}, // [15:0] PLL_DEN + { 37, 0x0304}, // [37] MASH_SEED_EN; [13:8] PFD_DLY_SEL + { 36, 0x0028}, // [15:0] PLL_N + { 35, 0x0004}, // fixed + { 34, 0x0000}, // [2:0] PLL_N + { 33, 0x1E21}, // fixed + { 32, 0x0393}, // fixed + { 31, 0x43EC}, // [14] SEG1_EN + { 30, 0x318C}, // fixed + { 29, 0x318C}, // fixed + { 28, 0x0488}, // fixed + { 27, 0x0002}, // fixed + { 26, 0x0DB0}, // fixed + { 25, 0x0C2B}, // fixed + { 24, 0x071A}, // fixed + { 23, 0x007C}, // fixed + { 22, 0x0001}, // fixed + { 21, 0x0401}, // fixed + { 20, 0xE048}, // [13:11] VCO_SEL. [10] VCO_SEL_FORCE + { 19, 0x27B7}, // [7:0] VCO_CAPCTRL + { 18, 0x0064}, // fixed + { 17, 0x012C}, // [8:0] VCO_DACISET_STRT + { 16, 0x0080}, // [8:0] VCO_DACISET + { 15, 0x064F}, // fixed + { 14, 0x1E70}, // [6:4] CPG + { 13, 0x4000}, // fixed + { 12, 0x5001}, // [11:0] PLL_R_PR + { 11, 0x0018}, // [11:4] PLL_R + { 10, 0x10D8}, // [11:7] MULT + { 9, 0x0604}, // [12] OSC_2X + { 8, 0x2000}, // [14] VCO_DACISET_FORCE; [11] VCO_CAPCTRL_FORCE + { 7, 0x40B2}, // [14] OUT_FORCE + { 6, 0xC802}, // fixed + { 5, 0x00C8}, // fixed + { 4, 0x0C43}, // [15:8] ACAL_CMP_DLY + { 3, 0x0642}, // fixed + { 2, 0x0500}, // fixed + { 1, 0x0809}, // [2:0] CAL_CLK_DIV + { 0, 0x2598}, // [15] RAMP_EN; [14] VCO_PHASE_SYNC; [9] OUT_MUTE; [8:7] FCAL_HPFD_ADJ; [6:5] FCAL_LPFD_ADJ; [3] FCAL_EN; [2] MUXOUT_LD_SEL; [1] RESET; [0] POWERDOWN + + // one more time + { 0, 0x2598} +}; diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/dev_profile/timer_profile.c b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/dev_profile/timer_profile.c new file mode 100644 index 0000000..1f82c10 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/dev_profile/timer_profile.c @@ -0,0 +1,21 @@ +#include "dev_profile.h" +#include "timer.h" +#include "../config/app_config.h" +#include "../drivers/platform/xilinx_timer.h" + +struct xil_timer_init_param xil_apptimer_init_param = { + .active_tmr = 0, +#ifdef __aarch64__ + .type = TIMER_PL +#else + .type = TIMER_PS +#endif +}; + +struct timer_init_param apptimer_init_param = { + .id = APPTIMER_DEVICE_ID, + .freq_hz = APP_TIMER_CLK_HZ, + .ticks_count = (APP_TIMER_CLK_HZ/10), //update log every 100ms + .platform_ops = &xil_timer_ops, + .extra = &xil_apptimer_init_param +}; diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/adc/ad9653/ad9653.c b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/adc/ad9653/ad9653.c new file mode 100644 index 0000000..688458d --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/adc/ad9653/ad9653.c @@ -0,0 +1,129 @@ +/***************************************************************************//** + * @file ad9653.c + * @brief Implementation of AD9653 Driver. + * @author DBogdan (dragos.bogdan@analog.com) + ******************************************************************************** + * Copyright 2014-2016(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *******************************************************************************/ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ +#include "ad9653.h" + +#include +#include +#include "../../../include/error.h" + +/***************************************************************************//** + * @brief ad9653_read + *******************************************************************************/ +int32_t ad9653_read(struct ad9653_dev *dev, + uint16_t reg_addr, + uint8_t *reg_data) +{ + uint8_t tx_buf[2]; + uint8_t rx_buf[1]; + int32_t ret; + + tx_buf[0] = 0x80 | (reg_addr >> 8); + tx_buf[1] = reg_addr & 0xFF; + + + ret = spi_write_and_read_3wire(dev->spi_desc, + tx_buf, rx_buf, 2, 1); + + *reg_data = rx_buf[0]; + + return ret; +} + +/***************************************************************************//** + * @brief ad9653_write + *******************************************************************************/ +int32_t ad9653_write(struct ad9653_dev *dev, + uint16_t reg_addr, + uint8_t reg_data) +{ + uint8_t buf[3]; + + int32_t ret; + + buf[0] = reg_addr >> 8; + buf[1] = reg_addr & 0xFF; + buf[2] = reg_data; + + ret = spi_write_and_read_3wire(dev->spi_desc, + buf, NULL, 3, 0); + return ret; +} + +/***************************************************************************//** + * @brief ad9653_init + *******************************************************************************/ +int32_t ad9653_init(struct ad9653_dev **device, + const struct ad9653_init_param *init_param) +{ + int ret = SUCCESS; + struct ad9653_dev *dev; + + dev = (struct ad9653_dev *)malloc(sizeof(*dev)); + if (!dev) + return FAILURE; + + /* SPI */ + ret = spi_init(&dev->spi_desc, init_param->spi_init); + + *device = dev; + + return ret; +} + +/***************************************************************************//** + * @brief Free the resources allocated by ad9653_setup(). + * + * @param dev - The device structure. + * + * @return SUCCESS in case of success, negative error code otherwise. +*******************************************************************************/ +int32_t ad9653_remove(struct ad9653_dev *dev) +{ + int32_t ret; + + ret = spi_remove(dev->spi_desc); + + free(dev); + + return ret; +} diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/adc/ad9653/ad9653.h b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/adc/ad9653/ad9653.h new file mode 100644 index 0000000..8271886 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/adc/ad9653/ad9653.h @@ -0,0 +1,233 @@ +/***************************************************************************//** + * @file ad9653.h + * @brief Header file of AD9653 Driver. + * @author DBogdan (dragos.bogdan@analog.com) + ******************************************************************************** + * Copyright 2014-2016(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *******************************************************************************/ +#ifndef AD9653_H_ +#define AD9653_H_ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ +#include +#include "delay.h" +#include "spi.h" + +/******************************************************************************/ +/********************** Macros and Constants Definitions **********************/ +/******************************************************************************/ +#define AD9694_REG_GLOBAL_MAP_SPI_CONF_A 0x0000 +#define AD9694_REG_GLOBAL_MAP_SPI_CONF_B 0x0001 +#define AD9694_REG_CH_MAP_CHIP_CONF 0x0002 +#define AD9694_REG_PAIR_MAP_CHIP_TYPE 0x0003 +#define AD9694_REG_PAIR_MAP_CHIP_ID_LSB 0x0004 +#define AD9694_REG_PAIR_MAP_CHIP_GRADE 0x0006 +#define AD9694_REG_PAIR_MAP_DEV_INDEX 0x0008 +#define AD9694_REG_GLOBAL_MAP_PAIR_INDEX 0x0009 +#define AD9694_REG_PAIR_MAP_SCRATCH_PAD 0x000A +#define AD9694_REG_PAIR_MAP_SPI_REVISION 0x000B +#define AD9694_REG_PAIR_MAP_VENDOR_ID_LSB 0x000C +#define AD9694_REG_PAIR_MAP_VENDOR_ID_MSB 0x000D +#define AD9694_REG_CH_MAP_CHIP_PD_PIN 0x003F +#define AD9694_REG_PAIR_MAP_CHIP_PIN_CTRL_1 0x0040 +#define AD9694_REG_PAIR_MAP_CLK_DIV_CTRL 0x0108 +#define AD9694_REG_CH_MAP_CLK_DIV_PHASE 0x0109 +#define AD9694_REG_PAIR_MAP_CLK_DIV_SYSREF_CTRL 0x010A +#define AD9694_REG_PAIR_MAP_CLK_DELAY_CTRL 0x0110 +#define AD9694_REG_CH_MAP_CLK_SUPER_FINE_DELAY 0x0111 +#define AD9694_REG_CH_MAP_CLK_FINE_DELAY 0x0112 +#define AD9694_REG_CLK_DETN_CTRL 0x011A +#define AD9694_REG_PAIR_MAP_CLK_STAT 0x011B +#define AD9694_REG_CLK_DCS_CTRL_1 0x011C +#define AD9694_REG_CLK_DCS_CTRL_2 0x011E +#define AD9694_REG_CLK_DCS_CTRL_3 0x011F +#define AD9694_REG_PAIR_MAP_SYSREF_CTRL_1 0x0120 +#define AD9694_REG_PAIR_MAP_SYSREF_CTRL_2 0x0121 +#define AD9694_REG_PAIR_MAP_SYSREF_CTRL_4 0x0123 +#define AD9694_REG_PAIR_MAP_SYSREF_STAT_1 0x0128 +#define AD9694_REG_PAIR_MAP_SYSREF_STAT_2 0x0129 +#define AD9694_REG_PAIR_MAP_SYSREF_STAT_3 0x012A +#define AD9694_REG_PAIR_MAP_CHIP_SYNC 0x01FF +#define AD9694_REG_PAIR_MAP_CHIP_MODE 0x0200 +#define AD9694_REG_PAIR_MAP_CHIP_DEC_RATIO 0x0201 +#define AD9694_REG_CH_MAP_CUSTOM_OFFSET 0x0228 +#define AD9694_REG_CH_MAP_FD_CTRL 0x0245 +#define AD9694_REG_CH_MAP_FD_UT_LSB 0x0247 +#define AD9694_REG_CH_MAP_FD_UT_MSB 0x0248 +#define AD9694_REG_CH_MAP_FD_LT_LSB 0x0249 +#define AD9694_REG_CH_MAP_FD_LT_MSB 0x024A +#define AD9694_REG_CH_MAP_FD_DWELL_TIME_LSB 0x024B +#define AD9694_REG_CH_MAP_FD_DWELL_TIME_MSB 0x024C +#define AD9694_REG_PAIR_MAP_SIG_MON_SYNC_CTRL 0x026F +#define AD9694_REG_CH_MAP_SIG_MON_CTRL 0x0270 +#define AD9694_REG_CH_MAP_SIG_MON_PERIOD_0 0x0271 +#define AD9694_REG_CH_MAP_SIG_MON_PERIOD_1 0x0272 +#define AD9694_REG_CH_MAP_SIG_MON_PERIOD_2 0x0273 +#define AD9694_REG_CH_MAP_SIG_MON_STAT_CTRL 0x0274 +#define AD9694_REG_CH_MAP_SIG_MON_STAT_0 0x0275 +#define AD9694_REG_CH_MAP_SIG_MON_STAT_1 0x0276 +#define AD9694_REG_CH_MAP_SIG_MON_STAT_2 0x0277 +#define AD9694_REG_CH_MAP_SIG_MON_STAT_FRAME_CNT 0x0278 +#define AD9694_REG_CH_MAP_SIG_MON_SERIAL_FRAMER_CTRL 0x0279 +#define AD9694_REG_SPORT_OVER_JESD204B_INPUT_SEL 0x027A +#define AD9694_REG_PAIR_MAP_DDC_SYNC_CTRL 0x0300 +#define AD9694_REG_PAIR_MAP_DDC_0_CTRL 0x0310 +#define AD9694_REG_PAIR_MAP_DDC_0_INPUT_SEL 0x0311 +#define AD9694_REG_PAIR_MAP_DDC_0_PHASE_INC_0 0x0314 +#define AD9694_REG_PAIR_MAP_DDC_0_PHASE_INC_1 0x0315 +#define AD9694_REG_PAIR_MAP_DDC_0_PHASE_INC_2 0x0316 +#define AD9694_REG_PAIR_MAP_DDC_0_PHASE_INC_3 0x0317 +#define AD9694_REG_PAIR_MAP_DDC_0_PHASE_INC_4 0x0318 +#define AD9694_REG_PAIR_MAP_DDC_0_PHASE_INC_5 0x031A +#define AD9694_REG_PAIR_MAP_DDC_0_PHASE_OFFSET_0 0x031D +#define AD9694_REG_PAIR_MAP_DDC_0_PHASE_OFFSET_1 0x031E +#define AD9694_REG_PAIR_MAP_DDC_0_PHASE_OFFSET_2 0x031F +#define AD9694_REG_PAIR_MAP_DDC_0_PHASE_OFFSET_3 0x0320 +#define AD9694_REG_PAIR_MAP_DDC_0_PHASE_OFFSET_4 0x0321 +#define AD9694_REG_PAIR_MAP_DDC_0_PHASE_OFFSET_5 0x0322 +#define AD9694_REG_PAIR_MAP_DDC_0_TEST_ENABLE 0x0327 +#define AD9694_REG_PAIR_MAP_DDC_1_CTRL 0x0330 +#define AD9694_REG_PAIR_MAP_DDC_1_INPUT_SEL 0x0331 +#define AD9694_REG_PAIR_MAP_DDC_1_PHASE_INC_0 0x0334 +#define AD9694_REG_PAIR_MAP_DDC_1_PHASE_INC_1 0x0335 +#define AD9694_REG_PAIR_MAP_DDC_1_PHASE_INC_2 0x0336 +#define AD9694_REG_PAIR_MAP_DDC_1_PHASE_INC_3 0x0337 +#define AD9694_REG_PAIR_MAP_DDC_1_PHASE_INC_4 0x0338 +#define AD9694_REG_PAIR_MAP_DDC_1_PHASE_INC_5 0x033A +#define AD9694_REG_PAIR_MAP_DDC_1_PHASE_OFFSET_0 0x033D +#define AD9694_REG_PAIR_MAP_DDC_1_PHASE_OFFSET_1 0x033E +#define AD9694_REG_PAIR_MAP_DDC_1_PHASE_OFFSET_2 0x033F +#define AD9694_REG_PAIR_MAP_DDC_1_PHASE_OFFSET_3 0x0340 +#define AD9694_REG_PAIR_MAP_DDC_1_PHASE_OFFSET_4 0x0341 +#define AD9694_REG_PAIR_MAP_DDC_1_PHASE_OFFSET_5 0x0342 +#define AD9694_REG_PAIR_MAP_DDC_1_TEST_ENABLE 0x0347 +#define AD9694_REG_CH_MAP_TEST_MODE_CTRL 0x0550 +#define AD9694_REG_PAIR_MAP_USER_PATTERN_1_LSB 0x0551 +#define AD9694_REG_PAIR_MAP_USER_PATTERN_1_MSB 0x0552 +#define AD9694_REG_PAIR_MAP_USER_PATTERN_2_LSB 0x0553 +#define AD9694_REG_PAIR_MAP_USER_PATTERN_2_MSB 0x0554 +#define AD9694_REG_PAIR_MAP_USER_PATTERN_3_LSB 0x0555 +#define AD9694_REG_PAIR_MAP_USER_PATTERN_3_MSB 0x0556 +#define AD9694_REG_PAIR_MAP_USER_PATTERN_4_LSB 0x0557 +#define AD9694_REG_PAIR_MAP_USER_PATTERN_4_MSB 0x0558 +#define AD9694_REG_PAIR_MAP_OUTPUT_CTRL_MODE_0 0x0559 +#define AD9694_REG_PAIR_MAP_OUTPUT_CTRL_MODE_1 0x055A +#define AD9694_REG_PAIR_MAP_OUTPUT_SAMPLE_MODE 0x0561 +#define AD9694_REG_PAIR_MAP_OUTPUT_CH_SEL 0x0564 +#define AD9694_REG_JESD204B_MAP_PLL_CTRL 0x056E +#define AD9694_REG_JESD204B_MAP_PLL_STAT 0x056F +#define AD9694_REG_JESD204B_MAP_JTX_QUICK_CONF 0x0570 +#define AD9694_REG_JESD204B_MAP_JTX_LINK_CTRL_1 0x0571 +#define AD9694_REG_JESD204B_MAP_JTX_LINK_CTRL_2 0x0572 +#define AD9694_REG_JESD204B_MAP_JTX_LINK_CTRL_3 0x0573 +#define AD9694_REG_JESD204B_MAP_JTX_LINK_CTRL_4 0x0574 +#define AD9694_REG_JESD204B_MAP_JTX_LMFC_OFFSET 0x0578 +#define AD9694_REG_JESD204B_MAP_JTX_DID_CONF 0x0580 +#define AD9694_REG_JESD204B_MAP_JTX_BID_CONF 0x0581 +#define AD9694_REG_JESD204B_MAP_JTX_LID_0_CONF 0x0583 +#define AD9694_REG_JESD204B_MAP_JTX_LID_1_CONF 0x0585 +#define AD9694_REG_JESD204B_MAP_JTX_SCR_L_CONF 0x058B +#define AD9694_REG_JESD204B_MAP_JTX_F_CONF 0x058C +#define AD9694_REG_JESD204B_MAP_JTX_K_CONF 0x058D +#define AD9694_REG_JESD204B_MAP_JTX_M_CONF 0x058E +#define AD9694_REG_JESD204B_MAP_JTX_CS_N_CONF 0x058F +#define AD9694_REG_JESD204B_MAP_JTX_SUBCLASS_CONF 0x0590 +#define AD9694_REG_JESD204B_MAP_JTX_S_CONF 0x0591 +#define AD9694_REG_JESD204B_MAP_JTX_HD_CF_CONF 0x0592 +#define AD9694_REG_JESD204B_MAP_JTX_CHECKSUM_0_CONF 0x05A0 +#define AD9694_REG_JESD204B_MAP_JTX_CHECKSUM_1_CONF 0x05A1 +#define AD9694_REG_SERDOUTX0_SERDOUTX1_LANE_PD 0x05B0 +#define AD9694_REG_JESD204B_MAP_JTX_LANE_ASSIGN_1 0x05B2 +#define AD9694_REG_JESD204B_MAP_JTX_LANE_ASSIGN_2 0x05B3 +#define AD9694_REG_JESD204B_MAP_SERD_ADJUST_0 0x05C0 +#define AD9694_REG_JESD204B_MAP_SERD_ADJUST_1 0x05C1 +#define AD9694_REG_JESD204B_SER_PE_SEL_LANE_0 0x05C4 +#define AD9694_REG_JESD204B_SER_PE_SEL_LANE_1 0x05C6 +#define AD9694_REG_LARGE_DITHER_CTRL 0x0922 +#define AD9694_REG_PLL_CAL 0x1222 +#define AD9694_REG_JESD204B_STARTUP_CIRCUIT_RST 0x1228 +#define AD9694_REG_PLL_LOSS_OF_LOCK_CTRL 0x1262 +#define AD9694_REG_DC_OFFSET_CAL_CTRL 0x0701 +#define AD9694_REG_DC_OFFSET_CAL_CTRL_2 0x073B +#define AD9694_REG_PAIR_MAP_VREF_CTRL 0x18A6 +#define AD9694_REG_EXT_VCM_BUF_CTRL_1 0x18E0 +#define AD9694_REG_EXT_VCM_BUF_CTRL_2 0x18E1 +#define AD9694_REG_EXT_VCM_BUF_CTRL_3 0x18E2 +#define AD9694_REG_EXT_VCM_BUF_CTRL 0x18E3 +#define AD9694_REG_TEMP_DIODE_EXPORT 0x18E6 +#define AD9694_REG_CH_MAP_ANALOG_INPUT_CTRL 0x1908 +#define AD9694_REG_CH_MAP_INPUT_FULLSCALE_RANGE 0x1910 +#define AD9694_REG_CH_MAP_BUF_CTRL_1 0x1A4C +#define AD9694_REG_CH_MAP_BUF_CTRL_2 0x1A4D + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ +struct ad9653_dev { + /* SPI */ + struct spi_desc *spi_desc; + struct gpio_desc *gpio_desc_pdwn; +}; + +struct ad9653_init_param { + /* SPI */ + struct spi_init_param *spi_init; + struct gpio_init_param *gpio_pdwn; +}; + +struct ad9653_config { + uint16_t addr; + uint8_t value; +}; + +/******************************************************************************/ +/************************ Functions Declarations ******************************/ +/******************************************************************************/ + +int32_t ad9653_read(struct ad9653_dev *dev, + uint16_t reg_addr, + uint8_t *reg_data); + +int32_t ad9653_write(struct ad9653_dev *dev, + uint16_t reg_addr, + uint8_t reg_data); + +int32_t ad9653_init(struct ad9653_dev **device, + const struct ad9653_init_param *init_param); + +int32_t ad9653_remove(struct ad9653_dev *dev); + +#endif diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/adc/ad9694/ad9694.c b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/adc/ad9694/ad9694.c new file mode 100644 index 0000000..a928a49 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/adc/ad9694/ad9694.c @@ -0,0 +1,128 @@ +/***************************************************************************//** + * @file ad9694.c + * @brief Implementation of AD9680 Driver. + * @author DBogdan (dragos.bogdan@analog.com) + ******************************************************************************** + * Copyright 2014-2016(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *******************************************************************************/ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ +#include +#include +#include "ad9694.h" +#include "../../../include/error.h" + +/***************************************************************************//** + * @brief ad9694_read + *******************************************************************************/ +int32_t ad9694_read(struct ad9694_dev *dev, + uint16_t reg_addr, + uint8_t *reg_data) +{ + uint8_t tx_buf[2]; + uint8_t rx_buf[1]; + int32_t ret; + + tx_buf[0] = 0x80 | (reg_addr >> 8); + tx_buf[1] = reg_addr & 0xFF; + + + ret = spi_write_and_read_3wire(dev->spi_desc, + tx_buf, rx_buf, 2, 1); + + *reg_data = rx_buf[0]; + + return ret; +} + +/***************************************************************************//** + * @brief ad9694_write + *******************************************************************************/ +int32_t ad9694_write(struct ad9694_dev *dev, + uint16_t reg_addr, + uint8_t reg_data) +{ + uint8_t buf[3]; + + int32_t ret; + + buf[0] = reg_addr >> 8; + buf[1] = reg_addr & 0xFF; + buf[2] = reg_data; + + ret = spi_write_and_read_3wire(dev->spi_desc, + buf, NULL, 3, 0); + return ret; +} + +/***************************************************************************//** + * @brief ad9694_init + *******************************************************************************/ +int32_t ad9694_init(struct ad9694_dev **device, + const struct ad9694_init_param *init_param) +{ + int ret = SUCCESS; + struct ad9694_dev *dev; + + dev = (struct ad9694_dev *)malloc(sizeof(*dev)); + if (!dev) + return FAILURE; + + /* SPI */ + ret = spi_init(&dev->spi_desc, init_param->spi_init); + + *device = dev; + + return ret; +} + +/***************************************************************************//** + * @brief Free the resources allocated by ad9694_setup(). + * + * @param dev - The device structure. + * + * @return SUCCESS in case of success, negative error code otherwise. +*******************************************************************************/ +int32_t ad9694_remove(struct ad9694_dev *dev) +{ + int32_t ret; + + ret = spi_remove(dev->spi_desc); + + free(dev); + + return ret; +} diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/adc/ad9694/ad9694.h b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/adc/ad9694/ad9694.h new file mode 100644 index 0000000..9622c55 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/adc/ad9694/ad9694.h @@ -0,0 +1,231 @@ +/***************************************************************************//** + * @file ad9694.h + * @brief Header file of AD9694 Driver. + * @author DBogdan (dragos.bogdan@analog.com) + ******************************************************************************** + * Copyright 2014-2016(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *******************************************************************************/ +#ifndef AD9694_H_ +#define AD9694_H_ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ +#include +#include "delay.h" +#include "spi.h" + +/******************************************************************************/ +/********************** Macros and Constants Definitions **********************/ +/******************************************************************************/ +#define AD9694_REG_GLOBAL_MAP_SPI_CONF_A 0x0000 +#define AD9694_REG_GLOBAL_MAP_SPI_CONF_B 0x0001 +#define AD9694_REG_CH_MAP_CHIP_CONF 0x0002 +#define AD9694_REG_PAIR_MAP_CHIP_TYPE 0x0003 +#define AD9694_REG_PAIR_MAP_CHIP_ID_LSB 0x0004 +#define AD9694_REG_PAIR_MAP_CHIP_GRADE 0x0006 +#define AD9694_REG_PAIR_MAP_DEV_INDEX 0x0008 +#define AD9694_REG_GLOBAL_MAP_PAIR_INDEX 0x0009 +#define AD9694_REG_PAIR_MAP_SCRATCH_PAD 0x000A +#define AD9694_REG_PAIR_MAP_SPI_REVISION 0x000B +#define AD9694_REG_PAIR_MAP_VENDOR_ID_LSB 0x000C +#define AD9694_REG_PAIR_MAP_VENDOR_ID_MSB 0x000D +#define AD9694_REG_CH_MAP_CHIP_PD_PIN 0x003F +#define AD9694_REG_PAIR_MAP_CHIP_PIN_CTRL_1 0x0040 +#define AD9694_REG_PAIR_MAP_CLK_DIV_CTRL 0x0108 +#define AD9694_REG_CH_MAP_CLK_DIV_PHASE 0x0109 +#define AD9694_REG_PAIR_MAP_CLK_DIV_SYSREF_CTRL 0x010A +#define AD9694_REG_PAIR_MAP_CLK_DELAY_CTRL 0x0110 +#define AD9694_REG_CH_MAP_CLK_SUPER_FINE_DELAY 0x0111 +#define AD9694_REG_CH_MAP_CLK_FINE_DELAY 0x0112 +#define AD9694_REG_CLK_DETN_CTRL 0x011A +#define AD9694_REG_PAIR_MAP_CLK_STAT 0x011B +#define AD9694_REG_CLK_DCS_CTRL_1 0x011C +#define AD9694_REG_CLK_DCS_CTRL_2 0x011E +#define AD9694_REG_CLK_DCS_CTRL_3 0x011F +#define AD9694_REG_PAIR_MAP_SYSREF_CTRL_1 0x0120 +#define AD9694_REG_PAIR_MAP_SYSREF_CTRL_2 0x0121 +#define AD9694_REG_PAIR_MAP_SYSREF_CTRL_4 0x0123 +#define AD9694_REG_PAIR_MAP_SYSREF_STAT_1 0x0128 +#define AD9694_REG_PAIR_MAP_SYSREF_STAT_2 0x0129 +#define AD9694_REG_PAIR_MAP_SYSREF_STAT_3 0x012A +#define AD9694_REG_PAIR_MAP_CHIP_SYNC 0x01FF +#define AD9694_REG_PAIR_MAP_CHIP_MODE 0x0200 +#define AD9694_REG_PAIR_MAP_CHIP_DEC_RATIO 0x0201 +#define AD9694_REG_CH_MAP_CUSTOM_OFFSET 0x0228 +#define AD9694_REG_CH_MAP_FD_CTRL 0x0245 +#define AD9694_REG_CH_MAP_FD_UT_LSB 0x0247 +#define AD9694_REG_CH_MAP_FD_UT_MSB 0x0248 +#define AD9694_REG_CH_MAP_FD_LT_LSB 0x0249 +#define AD9694_REG_CH_MAP_FD_LT_MSB 0x024A +#define AD9694_REG_CH_MAP_FD_DWELL_TIME_LSB 0x024B +#define AD9694_REG_CH_MAP_FD_DWELL_TIME_MSB 0x024C +#define AD9694_REG_PAIR_MAP_SIG_MON_SYNC_CTRL 0x026F +#define AD9694_REG_CH_MAP_SIG_MON_CTRL 0x0270 +#define AD9694_REG_CH_MAP_SIG_MON_PERIOD_0 0x0271 +#define AD9694_REG_CH_MAP_SIG_MON_PERIOD_1 0x0272 +#define AD9694_REG_CH_MAP_SIG_MON_PERIOD_2 0x0273 +#define AD9694_REG_CH_MAP_SIG_MON_STAT_CTRL 0x0274 +#define AD9694_REG_CH_MAP_SIG_MON_STAT_0 0x0275 +#define AD9694_REG_CH_MAP_SIG_MON_STAT_1 0x0276 +#define AD9694_REG_CH_MAP_SIG_MON_STAT_2 0x0277 +#define AD9694_REG_CH_MAP_SIG_MON_STAT_FRAME_CNT 0x0278 +#define AD9694_REG_CH_MAP_SIG_MON_SERIAL_FRAMER_CTRL 0x0279 +#define AD9694_REG_SPORT_OVER_JESD204B_INPUT_SEL 0x027A +#define AD9694_REG_PAIR_MAP_DDC_SYNC_CTRL 0x0300 +#define AD9694_REG_PAIR_MAP_DDC_0_CTRL 0x0310 +#define AD9694_REG_PAIR_MAP_DDC_0_INPUT_SEL 0x0311 +#define AD9694_REG_PAIR_MAP_DDC_0_PHASE_INC_0 0x0314 +#define AD9694_REG_PAIR_MAP_DDC_0_PHASE_INC_1 0x0315 +#define AD9694_REG_PAIR_MAP_DDC_0_PHASE_INC_2 0x0316 +#define AD9694_REG_PAIR_MAP_DDC_0_PHASE_INC_3 0x0317 +#define AD9694_REG_PAIR_MAP_DDC_0_PHASE_INC_4 0x0318 +#define AD9694_REG_PAIR_MAP_DDC_0_PHASE_INC_5 0x031A +#define AD9694_REG_PAIR_MAP_DDC_0_PHASE_OFFSET_0 0x031D +#define AD9694_REG_PAIR_MAP_DDC_0_PHASE_OFFSET_1 0x031E +#define AD9694_REG_PAIR_MAP_DDC_0_PHASE_OFFSET_2 0x031F +#define AD9694_REG_PAIR_MAP_DDC_0_PHASE_OFFSET_3 0x0320 +#define AD9694_REG_PAIR_MAP_DDC_0_PHASE_OFFSET_4 0x0321 +#define AD9694_REG_PAIR_MAP_DDC_0_PHASE_OFFSET_5 0x0322 +#define AD9694_REG_PAIR_MAP_DDC_0_TEST_ENABLE 0x0327 +#define AD9694_REG_PAIR_MAP_DDC_1_CTRL 0x0330 +#define AD9694_REG_PAIR_MAP_DDC_1_INPUT_SEL 0x0331 +#define AD9694_REG_PAIR_MAP_DDC_1_PHASE_INC_0 0x0334 +#define AD9694_REG_PAIR_MAP_DDC_1_PHASE_INC_1 0x0335 +#define AD9694_REG_PAIR_MAP_DDC_1_PHASE_INC_2 0x0336 +#define AD9694_REG_PAIR_MAP_DDC_1_PHASE_INC_3 0x0337 +#define AD9694_REG_PAIR_MAP_DDC_1_PHASE_INC_4 0x0338 +#define AD9694_REG_PAIR_MAP_DDC_1_PHASE_INC_5 0x033A +#define AD9694_REG_PAIR_MAP_DDC_1_PHASE_OFFSET_0 0x033D +#define AD9694_REG_PAIR_MAP_DDC_1_PHASE_OFFSET_1 0x033E +#define AD9694_REG_PAIR_MAP_DDC_1_PHASE_OFFSET_2 0x033F +#define AD9694_REG_PAIR_MAP_DDC_1_PHASE_OFFSET_3 0x0340 +#define AD9694_REG_PAIR_MAP_DDC_1_PHASE_OFFSET_4 0x0341 +#define AD9694_REG_PAIR_MAP_DDC_1_PHASE_OFFSET_5 0x0342 +#define AD9694_REG_PAIR_MAP_DDC_1_TEST_ENABLE 0x0347 +#define AD9694_REG_CH_MAP_TEST_MODE_CTRL 0x0550 +#define AD9694_REG_PAIR_MAP_USER_PATTERN_1_LSB 0x0551 +#define AD9694_REG_PAIR_MAP_USER_PATTERN_1_MSB 0x0552 +#define AD9694_REG_PAIR_MAP_USER_PATTERN_2_LSB 0x0553 +#define AD9694_REG_PAIR_MAP_USER_PATTERN_2_MSB 0x0554 +#define AD9694_REG_PAIR_MAP_USER_PATTERN_3_LSB 0x0555 +#define AD9694_REG_PAIR_MAP_USER_PATTERN_3_MSB 0x0556 +#define AD9694_REG_PAIR_MAP_USER_PATTERN_4_LSB 0x0557 +#define AD9694_REG_PAIR_MAP_USER_PATTERN_4_MSB 0x0558 +#define AD9694_REG_PAIR_MAP_OUTPUT_CTRL_MODE_0 0x0559 +#define AD9694_REG_PAIR_MAP_OUTPUT_CTRL_MODE_1 0x055A +#define AD9694_REG_PAIR_MAP_OUTPUT_SAMPLE_MODE 0x0561 +#define AD9694_REG_PAIR_MAP_OUTPUT_CH_SEL 0x0564 +#define AD9694_REG_JESD204B_MAP_PLL_CTRL 0x056E +#define AD9694_REG_JESD204B_MAP_PLL_STAT 0x056F +#define AD9694_REG_JESD204B_MAP_JTX_QUICK_CONF 0x0570 +#define AD9694_REG_JESD204B_MAP_JTX_LINK_CTRL_1 0x0571 +#define AD9694_REG_JESD204B_MAP_JTX_LINK_CTRL_2 0x0572 +#define AD9694_REG_JESD204B_MAP_JTX_LINK_CTRL_3 0x0573 +#define AD9694_REG_JESD204B_MAP_JTX_LINK_CTRL_4 0x0574 +#define AD9694_REG_JESD204B_MAP_JTX_LMFC_OFFSET 0x0578 +#define AD9694_REG_JESD204B_MAP_JTX_DID_CONF 0x0580 +#define AD9694_REG_JESD204B_MAP_JTX_BID_CONF 0x0581 +#define AD9694_REG_JESD204B_MAP_JTX_LID_0_CONF 0x0583 +#define AD9694_REG_JESD204B_MAP_JTX_LID_1_CONF 0x0585 +#define AD9694_REG_JESD204B_MAP_JTX_SCR_L_CONF 0x058B +#define AD9694_REG_JESD204B_MAP_JTX_F_CONF 0x058C +#define AD9694_REG_JESD204B_MAP_JTX_K_CONF 0x058D +#define AD9694_REG_JESD204B_MAP_JTX_M_CONF 0x058E +#define AD9694_REG_JESD204B_MAP_JTX_CS_N_CONF 0x058F +#define AD9694_REG_JESD204B_MAP_JTX_SUBCLASS_CONF 0x0590 +#define AD9694_REG_JESD204B_MAP_JTX_S_CONF 0x0591 +#define AD9694_REG_JESD204B_MAP_JTX_HD_CF_CONF 0x0592 +#define AD9694_REG_JESD204B_MAP_JTX_CHECKSUM_0_CONF 0x05A0 +#define AD9694_REG_JESD204B_MAP_JTX_CHECKSUM_1_CONF 0x05A1 +#define AD9694_REG_SERDOUTX0_SERDOUTX1_LANE_PD 0x05B0 +#define AD9694_REG_JESD204B_MAP_JTX_LANE_ASSIGN_1 0x05B2 +#define AD9694_REG_JESD204B_MAP_JTX_LANE_ASSIGN_2 0x05B3 +#define AD9694_REG_JESD204B_MAP_SERD_ADJUST_0 0x05C0 +#define AD9694_REG_JESD204B_MAP_SERD_ADJUST_1 0x05C1 +#define AD9694_REG_JESD204B_SER_PE_SEL_LANE_0 0x05C4 +#define AD9694_REG_JESD204B_SER_PE_SEL_LANE_1 0x05C6 +#define AD9694_REG_LARGE_DITHER_CTRL 0x0922 +#define AD9694_REG_PLL_CAL 0x1222 +#define AD9694_REG_JESD204B_STARTUP_CIRCUIT_RST 0x1228 +#define AD9694_REG_PLL_LOSS_OF_LOCK_CTRL 0x1262 +#define AD9694_REG_DC_OFFSET_CAL_CTRL 0x0701 +#define AD9694_REG_DC_OFFSET_CAL_CTRL_2 0x073B +#define AD9694_REG_PAIR_MAP_VREF_CTRL 0x18A6 +#define AD9694_REG_EXT_VCM_BUF_CTRL_1 0x18E0 +#define AD9694_REG_EXT_VCM_BUF_CTRL_2 0x18E1 +#define AD9694_REG_EXT_VCM_BUF_CTRL_3 0x18E2 +#define AD9694_REG_EXT_VCM_BUF_CTRL 0x18E3 +#define AD9694_REG_TEMP_DIODE_EXPORT 0x18E6 +#define AD9694_REG_CH_MAP_ANALOG_INPUT_CTRL 0x1908 +#define AD9694_REG_CH_MAP_INPUT_FULLSCALE_RANGE 0x1910 +#define AD9694_REG_CH_MAP_BUF_CTRL_1 0x1A4C +#define AD9694_REG_CH_MAP_BUF_CTRL_2 0x1A4D + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ +struct ad9694_dev { + /* SPI */ + struct spi_desc *spi_desc; +}; + +struct ad9694_init_param { + /* SPI */ + struct spi_init_param *spi_init; +}; + +struct ad9694_config { + uint16_t addr; + uint8_t value; +}; + +/******************************************************************************/ +/************************ Functions Declarations ******************************/ +/******************************************************************************/ + +int32_t ad9694_read(struct ad9694_dev *dev, + uint16_t reg_addr, + uint8_t *reg_data); + +int32_t ad9694_write(struct ad9694_dev *dev, + uint16_t reg_addr, + uint8_t reg_data); + +int32_t ad9694_init(struct ad9694_dev **device, + const struct ad9694_init_param *init_param); + +int32_t ad9694_remove(struct ad9694_dev *dev); + +#endif diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/api/gpio.c b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/api/gpio.c new file mode 100644 index 0000000..587a461 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/api/gpio.c @@ -0,0 +1,241 @@ +/***************************************************************************//** + * @file gpio.c + * @brief Implementation of the GPIO Interface + * @author Antoniu Miclaus (antoniu.miclaus@analog.com) +******************************************************************************** + * Copyright 2020(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +#include +#include "gpio.h" +#include +#include "error.h" + +/******************************************************************************/ +/************************ Functions Definitions *******************************/ +/******************************************************************************/ + +/** + * @brief Obtain the GPIO decriptor. + * @param desc - The GPIO descriptor. + * @param param - GPIO Initialization parameters. + * @return 0 in case of success, -1 otherwise. + */ +int32_t gpio_get(struct gpio_desc **desc, + const struct gpio_init_param *param) +{ + int32_t ret; + + if (!param || !param->platform_ops) + return -EINVAL; + + if (!param->platform_ops->gpio_ops_get) + return -ENOSYS; + + ret = param->platform_ops->gpio_ops_get(desc, param); + if (ret) + return ret; + + (*desc)->platform_ops = param->platform_ops; + + return 0; +} + +/** + * @brief Get the value of an optional GPIO. + * @param desc - The GPIO descriptor. + * @param param - GPIO Initialization parameters. + * @return 0 in case of success, -1 otherwise. + */ +int32_t gpio_get_optional(struct gpio_desc **desc, + const struct gpio_init_param *param) +{ + int32_t ret; + + if (!param || (param->number == -1)) { + *desc = NULL; + return 0; + } + + if (!param->platform_ops) + return -EINVAL; + + if (!param->platform_ops->gpio_ops_get_optional) + return -ENOSYS; + + ret = param->platform_ops->gpio_ops_get_optional(desc, param); + if (ret) + return ret; + + (*desc)->platform_ops = param->platform_ops; + + return 0; +} +/** + * @brief Free the resources allocated by gpio_get(). + * @param desc - The GPIO descriptor. + * @return 0 in case of success, -1 otherwise. + */ +int32_t gpio_remove(struct gpio_desc *desc) +{ + if (desc) { + if (!desc->platform_ops) + return -EINVAL; + + if (!desc->platform_ops->gpio_ops_remove) + return -ENOSYS; + + return desc->platform_ops->gpio_ops_remove(desc); + } + + return 0; +} + +/** + * @brief Enable the input direction of the specified GPIO. + * @param desc - The GPIO descriptor. + * @return 0 in case of success, -1 otherwise. + */ +int32_t gpio_direction_input(struct gpio_desc *desc) +{ + if (desc) { + if (!desc->platform_ops) + return -EINVAL; + + if (!desc->platform_ops->gpio_ops_direction_input) + return -ENOSYS; + + return desc->platform_ops->gpio_ops_direction_input(desc); + } + + return 0; +} + +/** + * @brief Enable the output direction of the specified GPIO. + * @param desc - The GPIO descriptor. + * @param value - The value. + * Example: GPIO_HIGH + * GPIO_LOW + * @return 0 in case of success, -1 otherwise. + */ +int32_t gpio_direction_output(struct gpio_desc *desc, + uint8_t value) +{ + if (desc) { + if (!desc->platform_ops) + return -EINVAL; + + if (!desc->platform_ops->gpio_ops_direction_output) + return -ENOSYS; + + return desc->platform_ops-> + gpio_ops_direction_output(desc, value); + } + + return 0; +} + +/** + * @brief Get the direction of the specified GPIO. + * @param desc - The GPIO descriptor. + * @param direction - The direction. + * Example: GPIO_OUT + * GPIO_IN + * @return 0 in case of success, -1 otherwise. + */ +int32_t gpio_get_direction(struct gpio_desc *desc, + uint8_t *direction) +{ + if (desc) { + if (!desc->platform_ops) + return -EINVAL; + + if (!desc->platform_ops->gpio_ops_get_direction) + return -ENOSYS; + + return desc->platform_ops-> + gpio_ops_get_direction(desc, direction); + } + + return 0; +} + +/** + * @brief Set the value of the specified GPIO. + * @param desc - The GPIO descriptor. + * @param value - The value. + * Example: GPIO_HIGH + * GPIO_LOW + * @return 0 in case of success, -1 otherwise. + */ +int32_t gpio_set_value(struct gpio_desc *desc, + uint8_t value) +{ + if (desc) { + if (!desc->platform_ops) + return -EINVAL; + + if (!desc->platform_ops->gpio_ops_set_value) + return -ENOSYS; + + return desc->platform_ops->gpio_ops_set_value(desc, value); + } + + return 0; +} + +/** + * @brief Get the value of the specified GPIO. + * @param desc - The GPIO descriptor. + * @param value - The value. + * Example: GPIO_HIGH + * GPIO_LOW + * @return 0 in case of success, -1 otherwise. + */ +int32_t gpio_get_value(struct gpio_desc *desc, + uint8_t *value) +{ + if (desc) { + if (!desc->platform_ops) + return -EINVAL; + + if (!desc->platform_ops->gpio_ops_set_value) + return -ENOSYS; + + return desc->platform_ops->gpio_ops_get_value(desc, value); + } + + return 0; +} diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/api/i2c.c b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/api/i2c.c new file mode 100644 index 0000000..0ad78e0 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/api/i2c.c @@ -0,0 +1,135 @@ +/***************************************************************************//** + * @file i2c.c + * @brief Implementation of the I2C Interface + * @author Antoniu Miclaus (antoniu.miclaus@analog.com) +******************************************************************************** + * Copyright 2020(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +#include +#include "i2c.h" +#include +#include "error.h" + +/** + * @brief Initialize the I2C communication peripheral. + * @param desc - The I2C descriptor. + * @param param - The structure that contains the I2C parameters. + * @return 0 in case of success, -1 otherwise. + */ +int32_t i2c_init(struct i2c_desc **desc, + const struct i2c_init_param *param) +{ + int32_t ret; + + if (!param || !param->platform_ops) + return -EINVAL; + + if (!param->platform_ops->i2c_ops_init) + return -ENOSYS; + + ret = param->platform_ops->i2c_ops_init(desc, param); + if (ret) + return ret; + + (*desc)->platform_ops = param->platform_ops; + + return 0; +} + +/** + * @brief Free the resources allocated by i2c_init(). + * @param desc - The I2C descriptor. + * @return 0 in case of success, -1 otherwise. + */ +int32_t i2c_remove(struct i2c_desc *desc) +{ + if (!desc || !desc->platform_ops) + return -EINVAL; + + if (!desc->platform_ops->i2c_ops_remove) + return -ENOSYS; + + return desc->platform_ops->i2c_ops_remove(desc); +} + +/** + * @brief I2C Write data to slave device. + * @param desc - The I2C descriptor. + * @param data - The buffer with the transmitted/received data. + * @param bytes_number - Number of bytes to write. + * @param stop_bit - Stop conditional control. + * Example: 0 - A stop condition will not be generated. + * 1 - A stop condition will be generated. + * @return 0 in case of success, -1 otherwise. + */ +int32_t i2c_write(struct i2c_desc *desc, + uint8_t *data, + uint8_t bytes_number, + uint8_t stop_bit) +{ + if (!desc || !desc->platform_ops) + return -EINVAL; + + if (!desc->platform_ops->i2c_ops_write) + return -ENOSYS; + + return desc->platform_ops->i2c_ops_write(desc, data, bytes_number, + stop_bit); +} + +/** + * @brief I2C Read data from slave device. + * @param desc - The i2c descriptor. + * @param data - The buffer with the transmitted/received data. + * @param bytes_number - Number of bytes to read. + * @param stop_bit - Stop conditional control. + * Example: 0 - A stop condition will not be generated. + * 1 - A stop condition will be generated. + * @return 0 in case of success, -1 otherwise. + */ +int32_t i2c_read(struct i2c_desc *desc, + uint8_t *data, + uint8_t bytes_number, + uint8_t stop_bit) +{ + if (!desc || !desc->platform_ops) + return -EINVAL; + + if (!desc->platform_ops->i2c_ops_read) + return -ENOSYS; + + return desc->platform_ops->i2c_ops_read(desc, data, bytes_number, + stop_bit); +} diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/api/irq.c b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/api/irq.c new file mode 100644 index 0000000..6a962c4 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/api/irq.c @@ -0,0 +1,229 @@ +/***************************************************************************//** + * @file irq.c + * @brief Implementation of the IRQ Interface + * @author Andrei Porumb (andrei.porumb@analog.com) +******************************************************************************** + * Copyright 2021(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +#include +#include +#include "irq.h" +#include "error.h" + +/** + * @brief Initialize the IRQ interrupts. + * @param desc - The IRQ descriptor. + * @param param - The structure that contains the IRQ parameters. + * @return 0 in case of success, -1 otherwise. + */ +int32_t irq_ctrl_init(struct irq_ctrl_desc **desc, + const struct irq_init_param *param) +{ + int32_t ret; + + if (!param || !param->platform_ops) + return -EINVAL; + + if (!param->platform_ops->init) + return -ENOSYS; + + ret = param->platform_ops->init(desc, param); + if (ret) + return ret; + + (*desc)->platform_ops = param->platform_ops; + + return 0; +} + +/** + * @brief Free the resources allocated by irq_ctrl_init(). + * @param desc - The SPI descriptor. + * @return 0 in case of success, -1 otherwise. + */ +int32_t irq_ctrl_remove(struct irq_ctrl_desc *desc) +{ + if (!desc || !desc->platform_ops) + return -EINVAL; + + if (!desc->platform_ops->remove) + return -ENOSYS; + + return desc->platform_ops->remove(desc); +} + +/** + * @brief Register a callback to handle the irq events. + * @param desc - The IRQ controller descriptor. + * @param irq_id - Interrupt identifier. + * @param callback - Callback descriptor - platform specific type. + * @return SUCCESS in case of success, FAILURE otherwise. + */ +int32_t irq_register_callback(struct irq_ctrl_desc *desc, + uint32_t irq_id, + struct callback_desc *callback) +{ + if (!desc || !desc->platform_ops) + return -EINVAL; + + if (!desc->platform_ops->register_callback) + return -ENOSYS; + + return desc->platform_ops->register_callback(desc, irq_id, callback); +} + +/** + * @brief Unregisters a generic IRQ handling function. + * @param desc - The IRQ controller descriptor. + * @param irq_id - Interrupt identifier. + * @param callback - Callback descriptor - platform specific type. + * @return SUCCESS in case of success, FAILURE otherwise. + */ +int32_t irq_unregister_callback(struct irq_ctrl_desc *desc, + uint32_t irq_id, + struct callback_desc *callback) +{ + if (!desc || !desc->platform_ops) + return -EINVAL; + + if (!desc->platform_ops->unregister_callback) + return -ENOSYS; + + return desc->platform_ops->unregister_callback(desc, irq_id, callback); +} + +/** + * @brief Enable global interrupts. + * @return 0 in case of success, -1 otherwise. + */ +int32_t irq_global_enable(struct irq_ctrl_desc *desc) +{ + if (!desc || !desc->platform_ops) + return -EINVAL; + + if (!desc->platform_ops->global_enable) + return -ENOSYS; + + return desc->platform_ops->global_enable(desc); +} + +/** + * @brief Disable global interrupts. + * @return 0 in case of success, -1 otherwise. + */ +int32_t irq_global_disable(struct irq_ctrl_desc *desc) +{ + if (!desc || !desc->platform_ops) + return -EINVAL; + + if (!desc->platform_ops->global_disable) + return -ENOSYS; + + return desc->platform_ops->global_disable(desc); +} + +/** + * @brief Set interrupt trigger level. + * @param desc - The IRQ controller descriptor. + * @param irq_id - Interrupt identifier. + * @param trig - New trigger level for the interrupt. + * @return 0 in case of success, -1 otherwise. + */ +int32_t irq_trigger_level_set(struct irq_ctrl_desc *desc, + uint32_t irq_id, + enum irq_trig_level trig) +{ + if (!desc || !desc->platform_ops) + return -EINVAL; + + if(!desc->platform_ops->trigger_level_set) + return -ENOSYS; + + return desc->platform_ops->trigger_level_set(desc, irq_id, trig); +} + +/** + * @brief Enable specific interrupt. + * @param desc - The IRQ controller descriptor. + * @param irq_id - Interrupt identifier. + * @return 0 in case of success, -1 otherwise. + */ +int32_t irq_enable(struct irq_ctrl_desc *desc, uint32_t irq_id) +{ + if (!desc || !desc->platform_ops) + return -EINVAL; + + if (!desc->platform_ops->enable) + return -ENOSYS; + + return desc->platform_ops->enable(desc, irq_id); +} + +/** + * @brief Disable specific interrupt. + * @param desc - The IRQ controller descriptor. + * @param irq_id - Interrupt identifier. + * @return 0 in case of success, -1 otherwise. + */ +int32_t irq_disable(struct irq_ctrl_desc *desc, uint32_t irq_id) +{ + if (!desc || !desc->platform_ops) + return -EINVAL; + + if (!desc->platform_ops->disable) + return -ENOSYS; + + return desc->platform_ops->disable(desc, irq_id); +} + +/** + * @brief Set the priority for an interrupt. + * @param desc - The IRQ controller descriptor. + * @param irq_id - Interrupt identifier. + * @param priority_level - The priority level of the interrupt. + * @return 0 in case of success, negative errno error codes. + */ +int32_t irq_set_priority(struct irq_ctrl_desc *desc, + uint32_t irq_id, + uint32_t priority_level) +{ + if (!desc || !desc->platform_ops) + return -EINVAL; + + if (!desc->platform_ops->set_priority) + return -ENOSYS; + + return desc->platform_ops->set_priority(desc, irq_id, priority_level); +} diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/api/spi.c b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/api/spi.c new file mode 100644 index 0000000..bddea5d --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/api/spi.c @@ -0,0 +1,161 @@ +/***************************************************************************//** + * @file spi.c + * @brief Implementation of the SPI Interface + * @author Antoniu Miclaus (antoniu.miclaus@analog.com) +******************************************************************************** + * Copyright 2020(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +#include +#include "spi.h" +#include +#include "error.h" + +/** + * @brief Initialize the SPI communication peripheral. + * @param desc - The SPI descriptor. + * @param param - The structure that contains the SPI parameters. + * @return 0 in case of success, -1 otherwise. + */ +int32_t spi_init(struct spi_desc **desc, + const struct spi_init_param *param) +{ + int32_t ret; + + if (!param || !param->platform_ops) + return -EINVAL; + + if (!param->platform_ops->init) + return -ENOSYS; + + ret = param->platform_ops->init(desc, param); + if (ret) + return ret; + + (*desc)->platform_ops = param->platform_ops; + (*desc)->parent = param->parent; + + return 0; +} + +/** + * @brief Free the resources allocated by spi_init(). + * @param desc - The SPI descriptor. + * @return 0 in case of success, -1 otherwise. + */ +int32_t spi_remove(struct spi_desc *desc) +{ + if (!desc || !desc->platform_ops) + return -EINVAL; + + if (!desc->platform_ops->remove) + return -ENOSYS; + + return desc->platform_ops->remove(desc); +} + +/** + * @brief Write and read data to/from SPI. + * @param desc - The SPI descriptor. + * @param data - The buffer with the transmitted/received data. + * @param bytes_number - Number of bytes to write/read. + * @return 0 in case of success, -1 otherwise. + */ +int32_t spi_write_and_read(struct spi_desc *desc, + uint8_t *data, + uint16_t bytes_number) +{ + if (!desc || !desc->platform_ops) + return -EINVAL; + + if (!desc->platform_ops->write_and_read) + return -ENOSYS; + + return desc->platform_ops->write_and_read(desc, data, bytes_number); +} + +/** + * @brief Write and read data to/from SPI in 3 wire mode. + * @param desc - The SPI descriptor. + * @param write_data - The buffer with the transmitted data. + * @param read_data - The buffer with the received data. + * @param write_bytes_number - Number of bytes to write. + * @param read_bytes_number - Number of bytes to read. + * @return SUCCESS in case of success, FAILURE otherwise. + */ +int32_t spi_write_and_read_3wire(struct spi_desc *desc, + uint8_t *write_data, + uint8_t *read_data, + uint16_t write_bytes_number, + uint16_t read_bytes_number) +{ + if (!desc || !desc->platform_ops) + return -EINVAL; + + if (!desc->platform_ops->write_and_read_3wire) + return -ENOSYS; + return desc->platform_ops->write_and_read_3wire(desc, write_data, read_data, + write_bytes_number, read_bytes_number); +} +/** + * @brief Iterate over head list and send all spi messages + * @param desc - The SPI descriptor. + * @param msgs - Array of messages. + * @param len - Number of messages in the array. + * @return 0 in case of success, negativ error code otherwise. + */ +int32_t spi_transfer(struct spi_desc *desc, + struct spi_msg *msgs, + uint32_t len) +{ + int32_t ret; + uint32_t i; + + if (!desc || !desc->platform_ops) + return -EINVAL; + + if (desc->platform_ops->transfer) + return desc->platform_ops->transfer(desc, msgs, len); + + for (i = 0; i < len; i++) { + if (msgs[i].rx_buff != msgs[i].tx_buff || !msgs[i].tx_buff) + return -EINVAL; + ret = spi_write_and_read(desc, msgs[i].rx_buff, + msgs[i].bytes_number); + if (IS_ERR_VALUE(ret)) + return ret; + } + + return 0; +} diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/api/timer.c b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/api/timer.c new file mode 100644 index 0000000..b33d88d --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/api/timer.c @@ -0,0 +1,211 @@ +/***************************************************************************//** +* @file timer.c +* @brief Implementation of the timer Interface +* @author RBolboac (ramona.bolboaca@analog.com) +******************************************************************************** +* Copyright 2022(c) Analog Devices, Inc. +* +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* - Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* - Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* - Neither the name of Analog Devices, Inc. nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* - The use of this software may or may not infringe the patent rights +* of one or more patent holders. This license does not release you +* from the requirement that you obtain separate licenses from these +* patent holders to use this software. +* - Use of the software either in source or binary form, must be run +* on or directly connected to an Analog Devices Inc. component. +* +* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, MERCHANTABILITY +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +* IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ +#include "error.h" +#include "timer.h" + +/******************************************************************************/ +/************************ Functions Definitions *******************************/ +/******************************************************************************/ +/** + * @brief Initialize hardware timer and the handler structure associated with + * it. + * @param [out] desc - Pointer to the reference of the device handler. + * @param [in] param - Initialization structure. + * @return 0 in case of success, negative error code otherwise + */ +int32_t timer_init(struct timer_desc **desc, + struct timer_init_param *param) +{ + int32_t ret; + + if (!param || !param->platform_ops) + return -EINVAL; + + if (!param->platform_ops->init) + return -ENOSYS; + + ret = param->platform_ops->init(desc, param); + if (ret) + return ret; + + (*desc)->platform_ops = param->platform_ops; + + return 0; +} + +/** + * @brief Free the memory allocated by timer_init(). + * @param [in] desc - Pointer to the device handler. + * @return 0 in case of success, negative error code otherwise + */ +int32_t timer_remove(struct timer_desc *desc) +{ + if (!desc || !desc->platform_ops) + return -EINVAL; + + if (!desc->platform_ops->remove) + return -ENOSYS; + + return desc->platform_ops->remove(desc); +} + +/** + * @brief Start a timer. + * @param [in] desc - Pointer to the device handler. + * @return 0 in case of success, negative error code otherwise + */ +int32_t timer_start(struct timer_desc *desc) +{ + if (!desc || !desc->platform_ops) + return -EINVAL; + + if (!desc->platform_ops->start) + return -ENOSYS; + + return desc->platform_ops->start(desc); +} + +/** + * @brief Stop a timer from counting. + * @param [in] desc - Pointer to the device handler. + * @return 0 in case of success, negative error code otherwise + */ +int32_t timer_stop(struct timer_desc *desc) +{ + if (!desc || !desc->platform_ops) + return -EINVAL; + + if (!desc->platform_ops->stop) + return -ENOSYS; + + return desc->platform_ops->stop(desc); +} + +/** + * @brief Get the value of the counter register for the timer. + * @param [in] desc - Pointer to the device handler. + * @param [out] counter - Pointer to the counter value. + * @return 0 in case of success, error code otherwise. + */ +int32_t timer_counter_get(struct timer_desc *desc, + uint32_t *counter) +{ + if (!desc || !desc->platform_ops || !counter) + return -EINVAL; + + if (!desc->platform_ops->counter_get) + return -ENOSYS; + + return desc->platform_ops->counter_get(desc, counter); +} + +/** + * @brief Set the timer counter register value. + * @param [in] desc - Pointer to the device handler. + * @param [in] new_val - The new value of the counter register. + * @return 0 in case of success, error code otherwise. + */ +int32_t timer_counter_set(struct timer_desc *desc, uint32_t new_val) +{ + if (!desc || !desc->platform_ops) + return -EINVAL; + + if (!desc->platform_ops->counter_set) + return -ENOSYS; + + return desc->platform_ops->counter_set(desc, new_val); +} + +/** + * @brief Get the timer clock frequency. + * @param [in] desc - Pointer to the device handler. + * @param [out] freq_hz - The value in Hz of the timer clock. + * @return 0 in case of success, error code otherwise. + */ +int32_t timer_count_clk_get(struct timer_desc *desc, + uint32_t *freq_hz) +{ + if (!desc || !desc->platform_ops || !freq_hz) + return -EINVAL; + + if (!desc->platform_ops->count_clk_get) + return -ENOSYS; + + return desc->platform_ops->count_clk_get(desc, freq_hz); +} + +/** + * @brief Set the timer clock frequency. + * @param [in] desc - Pointer to the device handler. + * @param [in] freq_hz - The value in Hz of the new timer clock. + * @return 0 in case of success, error code otherwise. + */ +int32_t timer_count_clk_set(struct timer_desc *desc, + uint32_t freq_hz) +{ + if (!desc || !desc->platform_ops) + return -EINVAL; + + if (!desc->platform_ops->count_clk_set) + return -ENOSYS; + + return desc->platform_ops->count_clk_set(desc, freq_hz); +} + +/** + * @brief Get the elapsed time in nsec for the timer. + * @param [in] desc - Pointer to the device handler. + * @param [in] elapsed_time - The elapsed time in nsec. + * @return 0 in case of success, error code otherwise. + */ +int32_t timer_get_elapsed_time_nsec(struct timer_desc *desc, + uint64_t *elapsed_time) +{ + if (!desc || !desc->platform_ops) + return -EINVAL; + + if (!desc->platform_ops->get_elapsed_time_nsec) + return -ENOSYS; + + return desc->platform_ops->get_elapsed_time_nsec(desc, elapsed_time); +} diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/api/trng.c b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/api/trng.c new file mode 100644 index 0000000..de093c3 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/api/trng.c @@ -0,0 +1,111 @@ +/***************************************************************************//** + * @file trng.c + * @brief Implementation of the TRNG Interface + * @author Antoniu Miclaus (antoniu.miclaus@analog.com) +******************************************************************************** + * Copyright 2023(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ +#include +#include "trng.h" +#include +#include "error.h" + +/******************************************************************************/ +/************************ Functions Definitions *******************************/ +/******************************************************************************/ + +/** + * @brief Initialize the TRNG. + * @param desc - The TRNG descriptor. + * @param param - The structure that contains the TRNG parameters. + * @return 0 in case of success, -1 otherwise. + */ +int trng_init(struct trng_desc **desc, + const struct trng_init_param *param) +{ + int ret; + + if (!param || !param->platform_ops) + return -EINVAL; + + if (!param->platform_ops->init) + return -ENOSYS; + + ret = param->platform_ops->init(desc, param); + if (ret) + return ret; + + (*desc)->platform_ops = param->platform_ops; + + return 0; +} + +/** + * @brief Free the resources allocated by trng_init(). + * @param desc - The TRNG descriptor. + * @return 0 in case of success, -1 otherwise. + */ +int trng_remove(struct trng_desc *desc) +{ + if (!desc || !desc->platform_ops) + return -EINVAL; + + if (!desc->platform_ops->remove) + return -ENOSYS; + + return desc->platform_ops->remove(desc); +} + +/** + * @brief Fill buffer with rng data. + * @param desc - The TRNG descriptor. + * @param buff - Buffer to be filled + * @param len - Size of the buffer + * @return 0 in case of success, -1 otherwise. + */ +int trng_fill_buffer(struct trng_desc *desc, uint8_t *buff, + uint32_t len) +{ + if (!desc || !desc->platform_ops) + return -EINVAL; + + if (!desc->platform_ops->fill_buffer) + return -ENOSYS; + + return desc->platform_ops->fill_buffer(desc, buff, len); +} diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/axi_core/axi_dmac/axi_dmac.c b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/axi_core/axi_dmac/axi_dmac.c new file mode 100644 index 0000000..32388ae --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/axi_core/axi_dmac/axi_dmac.c @@ -0,0 +1,547 @@ +/******************************************************************************* + * @file axi_dmac.c + * @brief Driver for the Analog Devices AXI-DMAC core. + * @author DBogdan (dragos.bogdan@analog.com) +******************************************************************************** + * Copyright 2018(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ +#include +#include +#include +#include +#include "axi_io.h" +#include "error.h" +#include "delay.h" +#include "axi_dmac.h" + +/******************************************************************************* + * @brief ISR for dev to mem DMA transfer. It computes the next transfer params, + * if any, and sets the transfer structure fields accordingly. + * + * @param instance - the instance that triggered the ISR. + * + * @return None. +*******************************************************************************/ +void axi_dmac_dev_to_mem_isr(void *instance) +{ + struct axi_dmac *dmac = (struct axi_dmac *)instance; + uint32_t burst_size; + uint32_t reg_val; + + /* Get interrupt sources and clear interrupts. */ + axi_dmac_read(dmac, AXI_DMAC_REG_IRQ_PENDING, ®_val); + axi_dmac_write(dmac, AXI_DMAC_REG_IRQ_PENDING, reg_val); + + if (reg_val & AXI_DMAC_IRQ_SOT) { + if (dmac->remaining_size) { + /* See if remaining size is bigger than max transfer size and + * set burst size. */ + if (dmac->remaining_size > dmac->max_length) { + burst_size = dmac->max_length; + } else { + burst_size = dmac->remaining_size - 1; + } + + /* The current transfer was started; set up the new one. */ + axi_dmac_write(dmac, AXI_DMAC_REG_DEST_ADDRESS, dmac->next_dest_addr); + axi_dmac_write(dmac, AXI_DMAC_REG_DEST_STRIDE, 0x0); + axi_dmac_write(dmac, AXI_DMAC_REG_X_LENGTH, burst_size); + axi_dmac_write(dmac, AXI_DMAC_REG_Y_LENGTH, 0x0); + + /* Compute size of the next transfer. */ + dmac->remaining_size = dmac->remaining_size - (burst_size + 1); + /* Address must advance with +1 since the DMAC writes X_LENGTH+1. */ + dmac->next_dest_addr = dmac->next_dest_addr + (burst_size + 1); + + /* Trigger the next transfer. */ + axi_dmac_write(dmac, AXI_DMAC_REG_TRANSFER_SUBMIT, AXI_DMAC_TRANSFER_SUBMIT); + } + } + if (reg_val & AXI_DMAC_IRQ_EOT) { + if (!dmac->remaining_size) { + dmac->transfer.transfer_done = true; + dmac->next_dest_addr = 0; + } + } +} + +/******************************************************************************* + * @brief ISR for mem DMA to dev transfer. It computes the next transfer params, + * if any, and sets the transfer structure fields accordingly. + * + * @param instance - the instance that triggered the ISR. + * + * @return None. +*******************************************************************************/ +void axi_dmac_mem_to_dev_isr(void *instance) +{ + struct axi_dmac *dmac = (struct axi_dmac *)instance; + uint32_t burst_size; + uint32_t reg_val; + + /* Get interrupt sources and clear interrupts. */ + axi_dmac_read(dmac, AXI_DMAC_REG_IRQ_PENDING, ®_val); + axi_dmac_write(dmac, AXI_DMAC_REG_IRQ_PENDING, reg_val); + + if (reg_val & AXI_DMAC_IRQ_SOT) { + if ((dmac->transfer.cyclic == CYCLIC) && + (dmac->next_src_addr >= (dmac->init_addr + dmac->transfer.size - 1))) { + dmac->remaining_size = dmac->transfer.size; + dmac->next_src_addr = dmac->init_addr; + } + + if (dmac->remaining_size) { + /** See if remaining size is bigger than max transfer size and + * set burst size. */ + if (dmac->remaining_size > dmac->max_length) { + burst_size = dmac->max_length; + } else { + burst_size = dmac->remaining_size - 1; + } + + /* The current transfer was started; set up the new one. */ + axi_dmac_write(dmac, AXI_DMAC_REG_SRC_ADDRESS, dmac->next_src_addr); + axi_dmac_write(dmac, AXI_DMAC_REG_SRC_STRIDE, 0x0); + axi_dmac_write(dmac, AXI_DMAC_REG_X_LENGTH, burst_size); + axi_dmac_write(dmac, AXI_DMAC_REG_Y_LENGTH, 0x0); + + /* Compute parameters for the next transfer. */ + dmac->remaining_size = dmac->remaining_size - (burst_size + 1); + /* Address must advance with +1 since the DMAC writes X_LENGTH+1. */ + dmac->next_src_addr = dmac->next_src_addr + (burst_size + 1); + + /* Trigger the current transfer */ + axi_dmac_write(dmac, AXI_DMAC_REG_TRANSFER_SUBMIT, AXI_DMAC_TRANSFER_SUBMIT); + } + } + if (reg_val & AXI_DMAC_IRQ_EOT) { + if ((!dmac->remaining_size) && (dmac->transfer.cyclic != CYCLIC)) { + dmac->transfer.transfer_done = true; + dmac->next_src_addr = 0; + } + } +} + +/******************************************************************************* + * @brief ISR for mem DMA to mem DMA transfer. It computes the next transfer + * params, if any, and sets the transfer structure fields accordingly. + * + * @param instance - the instance that triggered the ISR. + * + * @return None. +*******************************************************************************/ +void axi_dmac_mem_to_mem_isr(void *instance) +{ + struct axi_dmac *dmac = (struct axi_dmac *)instance; + uint32_t burst_size; + uint32_t reg_val; + + /* Get interrupt sources and clear interrupts. */ + axi_dmac_read(dmac, AXI_DMAC_REG_IRQ_PENDING, ®_val); + axi_dmac_write(dmac, AXI_DMAC_REG_IRQ_PENDING, reg_val); + + if (reg_val & AXI_DMAC_IRQ_SOT) { + if (dmac->remaining_size) { + /** See if remaining size is bigger than max transfer size and + * set burst size. */ + if (dmac->remaining_size > dmac->max_length) { + burst_size = dmac->max_length; + } else { + burst_size = dmac->remaining_size - 1; + } + + /* The current transfer was started; set up the new one. */ + axi_dmac_write(dmac, AXI_DMAC_REG_SRC_ADDRESS, dmac->next_src_addr); + axi_dmac_write(dmac, AXI_DMAC_REG_SRC_STRIDE, 0x0); + axi_dmac_write(dmac, AXI_DMAC_REG_DEST_ADDRESS, dmac->next_dest_addr); + axi_dmac_write(dmac, AXI_DMAC_REG_DEST_STRIDE, 0x0); + axi_dmac_write(dmac, AXI_DMAC_REG_X_LENGTH, burst_size); + axi_dmac_write(dmac, AXI_DMAC_REG_Y_LENGTH, 0x0); + + /* Compute parameters for the next transfer. */ + dmac->remaining_size = dmac->remaining_size - (burst_size + 1); + /* Address must advance with +1 since the DMAC writes X_LENGTH+1. */ + dmac->next_src_addr = dmac->next_src_addr + (burst_size + 1); + dmac->next_dest_addr = dmac->next_dest_addr + (burst_size + 1); + + /* If transfer finished advance src address so that transfer_done can be set*/ + if (!dmac->remaining_size) { + dmac->next_src_addr = dmac->next_src_addr + (burst_size + 1); + } + + /* Trigger the current transfer */ + axi_dmac_write(dmac, AXI_DMAC_REG_TRANSFER_SUBMIT, AXI_DMAC_TRANSFER_SUBMIT); + } + } + if (reg_val & AXI_DMAC_IRQ_EOT) { + if (!dmac->remaining_size) { + if(dmac->next_src_addr > (dmac->init_addr + dmac->transfer.size)) { + dmac->transfer.transfer_done = true; + dmac->next_src_addr = 0; + dmac->next_dest_addr = 0; + } + } + } +} + +/******************************************************************************* + * @brief Wrapper for AXI IO through UIO/devmem read function. + * + * @param dmac - DMAC istance containing UIO index (/dev/uioX)/base address. + * @param reg_addr - Address to read from. + * @param reg_data - Location where read data will be stored. + * + * @return 0 - success. +*******************************************************************************/ +int32_t axi_dmac_read(struct axi_dmac *dmac, + uint32_t reg_addr, + uint32_t *reg_data) +{ + axi_io_read(dmac->base, reg_addr, reg_data); + + return 0; +} + +/******************************************************************************* + * @brief Wrapper for AXI IO through UIO/devmem wrrite function. + * + * @param dmac - DMAC istance containing UIO index (/dev/uioX)/base address. + * @param reg_addr - Address to write to. + * @param reg_data - Data to be written. + * + * @return 0 - success. +*******************************************************************************/ +int32_t axi_dmac_write(struct axi_dmac *dmac, + uint32_t reg_addr, + uint32_t reg_data) +{ + axi_io_write(dmac->base, reg_addr, reg_data); + + return 0; +} + +/******************************************************************************* + * @brief Get transfer status (value of dmac->transfer.transfer_done flag). + * + * @note This function should not be used if DMA IRQ is not used. + * + * @param dmac - DMAC istance. + * @param rdy - Transfer status (0 - not ready, 1 - ready). + * + * @return 0 - success. +*******************************************************************************/ +int32_t axi_dmac_is_transfer_ready(struct axi_dmac *dmac, bool *rdy) +{ + *rdy = dmac->transfer.transfer_done; + + return 0; +} + +/******************************************************************************* + * @brief Get DMAC capabilities. + * + * @param dmac - DMAC istance. + * + * @return 0 for success, -1 in case of failure. +*******************************************************************************/ +static int32_t axi_dmac_detect_caps(struct axi_dmac *dmac) +{ + uint32_t reg_val, initial_reg_val = 0; + uint32_t src_mem_mapped = 0; + uint32_t dest_mem_mapped = 0; + + dmac->max_length = -1; + dmac->direction = INVALID_DIR; + + /* Check if HW cyclic possible */ + axi_dmac_read(dmac, AXI_DMAC_REG_FLAGS, &initial_reg_val); + axi_dmac_write(dmac, AXI_DMAC_REG_FLAGS, DMA_CYCLIC); + axi_dmac_read(dmac, AXI_DMAC_REG_FLAGS, ®_val); + if (reg_val == DMA_CYCLIC) + dmac->hw_cyclic = true; + /* Restore initial value for AXI_DMAC_REG_FLAGS register */ + axi_dmac_write(dmac, AXI_DMAC_REG_FLAGS, initial_reg_val); + + /* Get maximum burst size and set value. */ + axi_dmac_write(dmac, AXI_DMAC_REG_X_LENGTH, dmac->max_length); + axi_dmac_read(dmac, AXI_DMAC_REG_X_LENGTH, &dmac->max_length); + + /* Get transfer direction and set value. */ + axi_dmac_write(dmac, AXI_DMAC_REG_DEST_ADDRESS, 0xffffffff); + axi_dmac_read(dmac, AXI_DMAC_REG_DEST_ADDRESS, &dest_mem_mapped); + axi_dmac_write(dmac, AXI_DMAC_REG_SRC_ADDRESS, 0xffffffff); + axi_dmac_read(dmac, AXI_DMAC_REG_SRC_ADDRESS, &src_mem_mapped); + + if (dest_mem_mapped && !src_mem_mapped) { + dmac->direction = DMA_DEV_TO_MEM; + } else if (!dest_mem_mapped && src_mem_mapped) { + dmac->direction = DMA_MEM_TO_DEV; + } else if (dest_mem_mapped && src_mem_mapped) { + dmac->direction = DMA_MEM_TO_MEM; + } else { + printf("Destination and source memory-mapped interfaces not supported.\n"); + return -1; + } + return 0; +} + +/******************************************************************************* + * @brief Get transfer status (value of dmac->transfer.transfer_done flag). + * + * @param dmac_core - DMAC istance. + * @param init - Structure containing initializing data. + * + * @return 0 for success, -1 in case of failure. +*******************************************************************************/ +int32_t axi_dmac_init(struct axi_dmac **dmac_core, + const struct axi_dmac_init *init) +{ + struct axi_dmac *dmac; + + dmac = (struct axi_dmac *)calloc(1, sizeof(*dmac)); + if (!dmac) + return -1; + + dmac->name = init->name; + dmac->base = init->base; + dmac->irq_option = init->irq_option; + + *dmac_core = dmac; + + int32_t status = axi_dmac_detect_caps(*dmac_core); + if (status < 0) + return -1; + + return 0; +} + +/******************************************************************************* + * @brief Remove the DMAC instance. + * + * @param dmac - DMAC istance. + * + * @return 0 for success, -1 in case of failure. +*******************************************************************************/ +int32_t axi_dmac_remove(struct axi_dmac *dmac) +{ + if (!dmac) + return -1; + + free(dmac); + + return 0; +} + +/******************************************************************************* + * @brief Start a DMA transfer. + * + * @param dmac - DMAC istance. + * @param dma_transfer - Structure containing transfer details. + * + * @return 0 for success, -1 in case of failure. +*******************************************************************************/ +int32_t axi_dmac_transfer_start(struct axi_dmac *dmac, + struct axi_dma_transfer *dma_transfer) +{ + uint32_t reg_val, burst_size; + + if (dma_transfer->size == 0) + return 0; /* Nothing to do. */ + + /* Set current transfer parameters. */ + dmac->transfer.size = dma_transfer->size; + dmac->transfer.cyclic = dma_transfer->cyclic; + dmac->transfer.dest_addr = dma_transfer->dest_addr; + dmac->transfer.src_addr = dma_transfer->src_addr; + + dmac->remaining_size = dma_transfer->size; + dmac->next_dest_addr = dma_transfer->dest_addr; + dmac->next_src_addr = dma_transfer->src_addr; + + /* If HW cyclic transfer selected and not available, show error */ + /* HW cyclic transfer available only for MEM to DEV transfers. */ + if ((!dmac->hw_cyclic) && (dma_transfer->cyclic == CYCLIC)) { + printf("Transfer mode not supported!\n"); + return -1; + } + + /* Cyclic transfers not possible for DEV_TO_MEM and MEM_TO_MEM transmissions. */ + if ((dmac->direction == DMA_DEV_TO_MEM) + || (dmac->direction == DMA_MEM_TO_MEM)) { + if (dma_transfer->cyclic == CYCLIC) { + printf("Transfer mode not supported!\n"); + return -1; + } + } + + /* Cyclic transfers set to HW or SW depending on size for MEM to DEV. */ + if ((dmac->direction == DMA_MEM_TO_DEV) && (dmac->transfer.cyclic == CYCLIC)) { + if ((dmac->remaining_size - 1) <= dmac->max_length) { + if (dmac->hw_cyclic) { + axi_dmac_read(dmac, AXI_DMAC_REG_FLAGS, ®_val); + reg_val = reg_val | DMA_CYCLIC; + axi_dmac_write(dmac, AXI_DMAC_REG_FLAGS, reg_val); + } + } else { + axi_dmac_read(dmac, AXI_DMAC_REG_FLAGS, ®_val); + reg_val = reg_val & ~DMA_CYCLIC; + axi_dmac_write(dmac, AXI_DMAC_REG_FLAGS, reg_val); + } + } + + /* Enable DMA if not already enabled. */ + axi_dmac_read(dmac, AXI_DMAC_REG_CTRL, ®_val); + if (!(reg_val & AXI_DMAC_CTRL_ENABLE)) { + axi_dmac_write(dmac, AXI_DMAC_REG_CTRL, 0x0); + axi_dmac_write(dmac, AXI_DMAC_REG_CTRL, AXI_DMAC_CTRL_ENABLE); + axi_dmac_write(dmac, AXI_DMAC_REG_IRQ_MASK, 0x0); + } + + axi_dmac_read(dmac, AXI_DMAC_REG_TRANSFER_SUBMIT, ®_val); + /* If we don't have a start of transfer then start compute + * values and trigger next transfer. */ + if (!(reg_val & AXI_DMAC_QUEUE_FULL)) { + switch (dmac->direction) { + case DMA_DEV_TO_MEM: + dmac->init_addr = dmac->next_dest_addr; + axi_dmac_write(dmac, AXI_DMAC_REG_DEST_ADDRESS, dmac->next_dest_addr); + axi_dmac_write(dmac, AXI_DMAC_REG_DEST_STRIDE, 0x0); + break; + case DMA_MEM_TO_DEV: + dmac->init_addr = dmac->next_src_addr; + axi_dmac_write(dmac, AXI_DMAC_REG_SRC_ADDRESS, dmac->next_src_addr); + axi_dmac_write(dmac, AXI_DMAC_REG_SRC_STRIDE, 0x0); + break; + case DMA_MEM_TO_MEM: + dmac->init_addr = dmac->next_src_addr; + axi_dmac_write(dmac, AXI_DMAC_REG_DEST_ADDRESS, dmac->next_dest_addr); + axi_dmac_write(dmac, AXI_DMAC_REG_DEST_STRIDE, 0x0); + axi_dmac_write(dmac, AXI_DMAC_REG_SRC_ADDRESS, dmac->next_src_addr); + axi_dmac_write(dmac, AXI_DMAC_REG_SRC_STRIDE, 0x0); + break; + default: + return -1; /* Other directions are not supported yet. */ + } + + /* Compute the burst size. */ + if (dmac->remaining_size > dmac->max_length) { + burst_size = dmac->max_length; + } else { + burst_size = dmac->remaining_size - 1; + } + + /* Compute next address (src or dest, or both, depending on type of transfer). */ + switch (dmac->direction) { + case DMA_DEV_TO_MEM: + dmac->next_dest_addr = dmac->next_dest_addr + (burst_size + 1); + break; + case DMA_MEM_TO_DEV: + dmac->next_src_addr = dmac->next_src_addr + (burst_size + 1); + break; + case DMA_MEM_TO_MEM: + dmac->next_dest_addr = dmac->next_dest_addr + (burst_size + 1); + dmac->next_src_addr = dmac->next_src_addr + (burst_size + 1); + break; + default: + return -1; + } + + /* Compute remaining size. */ + dmac->remaining_size = dmac->remaining_size - (burst_size + 1); + + /* Specify the length of the transfer and trigger transfer. */ + axi_dmac_write(dmac, AXI_DMAC_REG_X_LENGTH, burst_size); + axi_dmac_write(dmac, AXI_DMAC_REG_Y_LENGTH, 0x0); + axi_dmac_write(dmac, AXI_DMAC_REG_TRANSFER_SUBMIT, AXI_DMAC_TRANSFER_SUBMIT); + } else { + return -1; + } + + return 0; +} + +/******************************************************************************* + * @brief Wait for DMA transfer to be completed. + * + * @param dmac - DMAC istance. + * @param timeout_ms - Number of ms to wait for completion of transfer. + * + * @return 0 for success, -1 in case trasnfer not completed in specified time. +*******************************************************************************/ +int32_t axi_dmac_transfer_wait_completion(struct axi_dmac *dmac, + uint32_t timeout_ms) +{ + uint32_t timeout = 0; + uint32_t reg_val = 0; + + if (dmac->irq_option == IRQ_ENABLED) { + while (!dmac->transfer.transfer_done) { + timeout++; + mdelay(1); + if (timeout == timeout_ms) { + printf("Error transferring data using DMA.\n"); + return -1; + } + } + } else if (dmac->irq_option == IRQ_DISABLED) { + axi_dmac_read(dmac, AXI_DMAC_REG_IRQ_PENDING, ®_val); + while (reg_val != (AXI_DMAC_IRQ_SOT | AXI_DMAC_IRQ_EOT)) { + timeout++; + mdelay(1); + if (timeout == timeout_ms) { + printf("Error transferring data using DMA.\n"); + return -1; + } + axi_dmac_read(dmac, AXI_DMAC_REG_IRQ_PENDING, ®_val); + } + } + + return 0; +} + +/******************************************************************************* + * @brief Stop a DMA transfer. + * + * @param dmac - DMAC istance. + * + * @return None +*******************************************************************************/ +void axi_dmac_transfer_stop(struct axi_dmac *dmac) +{ + axi_dmac_write(dmac, AXI_DMAC_REG_CTRL, AXI_DMAC_CTRL_DISABLE); +} diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/axi_core/axi_dmac/axi_dmac.h b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/axi_core/axi_dmac/axi_dmac.h new file mode 100644 index 0000000..d47d1cd --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/axi_core/axi_dmac/axi_dmac.h @@ -0,0 +1,156 @@ +/***************************************************************************//** + * @file axi_dmac.h + * @brief Driver for the Analog Devices AXI-DMAC core. + * @author DBogdan (dragos.bogdan@analog.com) +******************************************************************************** + * Copyright 2018(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ +#ifndef AXI_DMAC_H_ +#define AXI_DMAC_H_ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ +#include +#include "util.h" + +/******************************************************************************/ +/********************** Macros and Constants Definitions **********************/ +/******************************************************************************/ +#define AXI_DMAC_REG_IRQ_MASK 0x80 +#define AXI_DMAC_REG_IRQ_PENDING 0x84 +#define AXI_DMAC_IRQ_SOT BIT(0) +#define AXI_DMAC_IRQ_EOT BIT(1) + +#define AXI_DMAC_REG_INTF_DESC 0x010 +#define AXI_DMAC_DMA_TYPE_DEST GENMASK(5,4) +#define AXI_DMAC_DMA_TYPE_SRC GENMASK(13,12) +//Define macro for src and dest + +#define AXI_DMAC_REG_CTRL 0x400 +#define AXI_DMAC_CTRL_ENABLE BIT(0) +#define AXI_DMAC_CTRL_DISABLE 0u +#define AXI_DMAC_CTRL_PAUSE BIT(1) + +#define AXI_DMAC_REG_TRANSFER_ID 0x404 +#define AXI_DMAC_REG_TRANSFER_SUBMIT 0x408 +#define AXI_DMAC_TRANSFER_SUBMIT BIT(0) +#define AXI_DMAC_QUEUE_FULL BIT(0) +#define AXI_DMAC_REG_FLAGS 0x40c +#define AXI_DMAC_REG_DEST_ADDRESS 0x410 +#define AXI_DMAC_REG_SRC_ADDRESS 0x414 +#define AXI_DMAC_REG_X_LENGTH 0x418 +#define AXI_DMAC_REG_Y_LENGTH 0x41c +#define AXI_DMAC_REG_DEST_STRIDE 0x420 +#define AXI_DMAC_REG_SRC_STRIDE 0x424 +#define AXI_DMAC_REG_TRANSFER_DONE 0x428 + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ +enum use_irq { + IRQ_DISABLED = 0, + IRQ_ENABLED = 1 +}; + +enum dma_direction { + INVALID_DIR = 0, + DMA_DEV_TO_MEM = 1, + DMA_MEM_TO_DEV = 2, + DMA_MEM_TO_MEM = 3 +}; + +enum dma_flags { + DMA_CYCLIC = 1, + DMA_LAST = 2, + DMA_PARTIAL_REPORTING_EN = 4 +}; + +// Could be transformed to a bool +enum cyclic_transfer { + NO = 0, + CYCLIC = 1 +}; + +struct axi_dma_transfer { + uint32_t size; + volatile bool transfer_done; + enum cyclic_transfer cyclic; + uint32_t src_addr; + uint32_t dest_addr; +}; + +struct axi_dmac { + const char *name; + uint32_t base; + enum use_irq irq_option; + enum dma_direction direction; + bool hw_cyclic; + uint32_t max_length; + volatile struct axi_dma_transfer transfer; + //Current sub-transfer properties + uint32_t init_addr; + uint32_t remaining_size; + uint32_t next_src_addr; + uint32_t next_dest_addr; +}; + +struct axi_dmac_init { + const char *name; + uint32_t base; + enum use_irq irq_option; +}; + +/******************************************************************************/ +/************************ Functions Declarations ******************************/ +/******************************************************************************/ +void axi_dmac_dev_to_mem_isr(void *instance); +void axi_dmac_mem_to_dev_isr(void *instance); +void axi_dmac_mem_to_mem_isr(void *instance); +void axi_dmac_write_isr(void *instance); +int32_t axi_dmac_read(struct axi_dmac *dmac, uint32_t reg_addr, + uint32_t *reg_data); +int32_t axi_dmac_write(struct axi_dmac *dmac, uint32_t reg_addr, + uint32_t reg_data); +int32_t axi_dmac_is_transfer_ready(struct axi_dmac *dmac, bool *rdy); +int32_t axi_dmac_init(struct axi_dmac **adc_core, + const struct axi_dmac_init *init); +int32_t axi_dmac_remove(struct axi_dmac *dmac); +int32_t axi_dmac_transfer_start(struct axi_dmac *dmac, + struct axi_dma_transfer *dma_transfer); +int32_t axi_dmac_transfer_wait_completion(struct axi_dmac *dmac, + uint32_t timeout_ms); +void axi_dmac_transfer_stop(struct axi_dmac *dmac); + +#endif diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/axi_core/spi_engine/spi_engine.c b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/axi_core/spi_engine/spi_engine.c new file mode 100644 index 0000000..82cd1e6 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/axi_core/spi_engine/spi_engine.c @@ -0,0 +1,996 @@ +/******************************************************************************* + * @file spi_engine.c + * @brief Core implementation of the SPI Engine Driver. + * @author Sergiu Cuciurean (sergiu.cuciurean@analog.com) +******************************************************************************** + * Copyright 2019(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ******************************************************************************/ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ + +/* In debug mode the printf function used in displaying the messages is causing +significant delays */ +//#define DEBUG_LEVEL 2 + +#include +#include +#include +#include +#include +#include + +#include "axi_io.h" +#include "error.h" +#include "spi_engine.h" + +/** + * @brief Spi engine platform specific SPI platform ops structure + */ +const struct spi_platform_ops spi_eng_platform_ops = { + .init = &spi_engine_init, + .write_and_read = &spi_engine_write_and_read, + .write_and_read_3wire = &spi_engine_write_and_read_3wire, + .remove = &spi_engine_remove +}; + +/******************************************************************************/ +/***************************** Static variables *******************************/ +/******************************************************************************/ + +/** + * @brief Static variable used to sync transfers + * + */ +static uint8_t _sync_id = 0x01; + +/******************************************************************************/ +/************************** Functions Implementation **************************/ +/******************************************************************************/ + +/** + * @brief Write SPI Engine's axi registers + * + * @param desc Decriptor containing SPI Engine's parameters + * @param reg_addr The address of the SPI Engine's axi register where the data + * will be written + * @param reg_data Data that will be written + * @return int32_t This function allways returns SUCCESS + */ +int32_t spi_engine_write(struct spi_engine_desc *desc, + uint32_t reg_addr, + uint32_t reg_data) +{ + axi_io_write(desc->spi_engine_baseaddr, reg_addr, reg_data); + + return SUCCESS; +} + +/** + * @brief Read SPI Engine's axi registers + * + * @param desc Decriptor containing SPI Engine's parameters + * @param reg_addr The address of the SPI Engine's axi register from where the + * data where the data will be read + * @param reg_data Pointer where the read that will be stored + * @return int32_t This function allways returns SUCCESS + */ +int32_t spi_engine_read(struct spi_engine_desc *desc, + uint32_t reg_addr, + uint32_t *reg_data) +{ + axi_io_read(desc->spi_engine_baseaddr, reg_addr, reg_data); + return SUCCESS; +} + +/** + * @brief Set width of the transferred word over SPI + * + * @param desc Decriptor containing SPI interface parameters + * @param data_width The desired data width + * The supported values are: + * - 8 + * - 16 + * - 24 + * - 32 + */ +int32_t spi_engine_set_transfer_width(struct spi_desc *desc, + uint8_t data_width) +{ + struct spi_engine_desc *desc_extra; + + desc_extra = desc->extra; + + if (data_width > desc_extra->max_data_width) + desc_extra->data_width = desc_extra->max_data_width; + else + desc_extra->data_width = data_width; + + return SUCCESS; +} + +/** + * @brief Set SPI engine clock frequency + * + * @param desc Decriptor containing SPI Engine's parameters + * @param speed_hz SPI engine transfer speed + */ +void spi_engine_set_speed(struct spi_desc *desc, + uint32_t speed_hz) +{ + struct spi_engine_desc *desc_extra; + + desc_extra = desc->extra; + + desc_extra->clk_div = desc_extra->ref_clk_hz / + (2 * speed_hz) - 1; +} + +/** + * @brief Set the number of words transferred in a single transaction + * + * @param desc Decriptor containing SPI Engine's parameters + * @param bytes_number The number of bytes to be converted + * @return uint8_t A number of words in which bytes_number can be grouped + */ +static uint8_t spi_get_words_number(struct spi_engine_desc *desc, + uint8_t bytes_number) +{ + uint8_t xfer_word_len; + uint8_t words_number; + + xfer_word_len = desc->data_width / 8; + words_number = bytes_number / xfer_word_len; + + if ((bytes_number % xfer_word_len) != 0) + words_number++; + + return words_number; +} + +/** + * @brief Get the word length in bytes + * + * @param desc Decriptor containing SPI Engine's parameters + * @return uint8_t Number of bytes that fit in one word + */ +static uint8_t spi_get_word_length(struct spi_engine_desc *desc) +{ + uint8_t word_length; + + word_length = desc->data_width / 8; + + return word_length; +} + +/** + * @brief Compute the prescaler used to set the sleep period. + * + * @param desc Decriptor containing SPI interface parameters + * @param sleep_time_ns The amount of time where the transfer hangs + * @param sleep_div Clock prescaler + * @return int32_t This function allways returns SUCCESS + */ +static int32_t spi_get_sleep_div(struct spi_desc *desc, + uint32_t sleep_time_ns, + uint32_t *sleep_div) +{ + struct spi_engine_desc *eng_desc; + + eng_desc = desc->extra; + + /* + * Engine Wiki: + * + * The frequency of the SCLK signal is derived from the + * module clock frequency using the following formula: + * f_sclk = f_clk / ((div + 1) * 2) + */ + + *sleep_div = (desc->max_speed_hz / 1000000 * sleep_time_ns / 1000) / + ((eng_desc->clk_div + 1) * 2) - 1; + + return SUCCESS; +} + +/** + * @brief Create a new commands queue used in a spi transfer + * + * @param fifo Command buffer, usually used in fifo mode + * @param cmd Command with which the buffer will be initiated + * @return int32_t Failure if the memory allocation failed + */ +static int32_t spi_engine_queue_new_cmd(struct spi_engine_cmd_queue **fifo, + uint32_t cmd) +{ + struct spi_engine_cmd_queue *local_fifo; + + local_fifo = (spi_engine_cmd_queue*)malloc(sizeof(*local_fifo)); + + if(!local_fifo) + return FAILURE; + + local_fifo->cmd = cmd; + local_fifo->next = NULL; + *fifo = local_fifo; + + return SUCCESS; +} + +/** + * @brief Add a command at the end of an existing queue + * + * @param fifo Command buffer, usually used in fifo mode + * @param cmd Command to be added + */ +static void spi_engine_queue_add_cmd(struct spi_engine_cmd_queue **fifo, + uint32_t cmd) +{ + struct spi_engine_cmd_queue *to_add = NULL; + struct spi_engine_cmd_queue *local_fifo; + + local_fifo = *fifo; + while (local_fifo->next != NULL) { + // Get the last element + local_fifo = local_fifo->next; + } + + // Create a new element + spi_engine_queue_new_cmd(&to_add, cmd); + // Add as the next element + local_fifo->next = to_add; +} + +/** + * @brief Add a command at the beginning of an existing queue + * + * @param fifo Command buffer, usually used in fifo mode + * @param cmd Command to be added + */ +static void spi_engine_queue_append_cmd(struct spi_engine_cmd_queue **fifo, + uint32_t cmd) +{ + struct spi_engine_cmd_queue *to_add = NULL; + + // Create a new element + spi_engine_queue_new_cmd(&to_add, cmd); + // Interchange the addresses + to_add->next = *fifo; + *fifo = to_add; +} + + +/** + * @brief Get the command from the beginning of the queue + * + * @param fifo Command buffer, usually used in fifo mode + * @param cmd Value of the command that was extracted + * @return int32_t Return FAILURE if the queue is empty + */ +static int32_t spi_engine_queue_get_cmd(struct spi_engine_cmd_queue **fifo, + uint32_t *cmd) +{ + struct spi_engine_cmd_queue *local_fifo; + + if (!*fifo) + return FAILURE; + + local_fifo = *fifo; + *cmd = local_fifo->cmd; + if ((*fifo)->next) { + *fifo = local_fifo->next; + free(local_fifo); + } else { + free(*fifo); + *fifo = NULL; + } + + return SUCCESS; +} + +/** + * @brief Free the memory allocated by a queue + * + * @param fifo The queue that needs it's memory freed + * @return int32_t This function always returns SUCCESS + */ +static int32_t spi_engine_queue_free(struct spi_engine_cmd_queue **fifo) +{ + if(*fifo && (*fifo)->next) + spi_engine_queue_free(&(*fifo)->next); + if((*fifo) != NULL) { + free(*fifo); + *fifo = NULL; + } + + return SUCCESS; +} + +/** + * @brief Write the SPI engine's command fifo + * + * @param desc Decriptor containing SPI Engine's parameters + * @param cmd The command that will be written + * @return int32_t Returns FAILURE if the the axi transfer failed + */ +static int32_t spi_engine_write_cmd_reg(struct spi_engine_desc *desc, + uint32_t cmd) +{ + int32_t ret; + + /* Check if offload is enabled */ + if(desc->offload_config & (OFFLOAD_TX_EN | OFFLOAD_RX_EN)) { + ret = spi_engine_write(desc, + SPI_ENGINE_REG_OFFLOAD_CMD_MEM(0), + cmd); + + } else { + ret = spi_engine_write(desc, + SPI_ENGINE_REG_CMD_FIFO, + cmd); + } + + return ret; +} + +/** + * @brief Write a transfer command to the SPI engine's command fifo + * + * @param desc Decriptor containing SPI Engine's parameters + * @param read_write Read/Write operation flag + * @param bytes_number Number of bytes to transfer + * @return int32_t This function always returns SUCCESS + */ +static int32_t spi_engine_transfer(struct spi_engine_desc *desc, + uint8_t read_write, + uint8_t bytes_number) +{ + uint8_t words_number; + + words_number = spi_get_words_number(desc, bytes_number); + + desc->offload_tx_len += words_number; + + /* + * Engine Wiki: + * + * https://wiki.analog.com/resources/fpga/peripherals/spi_engine + * + * The words number is zero based + */ + + spi_engine_write_cmd_reg(desc, + SPI_ENGINE_CMD_TRANSFER(read_write, + words_number - 1)); + + return SUCCESS; +} + +/** + * @brief Change the state of the chip select port + * + * @param desc Decriptor containing SPI interface parameters + * @param assert Chip select state. + * The supported values are : + * -true (HIGH) + * -false (LOW) + */ +static void spi_engine_set_cs(struct spi_desc *desc, + bool assert) +{ + uint8_t mask; + struct spi_engine_desc *eng_desc; + + eng_desc = desc->extra; + + mask = 0xFF; + /* Switch the state only of the selected chip select */ + if (!assert) + mask ^= BIT(desc->chip_select); + + spi_engine_write_cmd_reg(eng_desc, + SPI_ENGINE_CMD_ASSERT(eng_desc->cs_delay, + mask)); +} + +/** + * @brief Add a delay between the engine commands + * + * @param desc Decriptor containing SPI interface parameters + * @param sleep_time_ns Number of nanoseconds to sleep between commands + */ +static void spi_gen_sleep_ns(struct spi_desc *desc, + uint32_t sleep_time_ns) +{ + uint32_t sleep_div; + struct spi_engine_desc *eng_desc; + + eng_desc = desc->extra; + + spi_get_sleep_div(desc, sleep_time_ns, &sleep_div); + + spi_engine_write_cmd_reg(eng_desc, SPI_ENGINE_CMD_SLEEP(sleep_div)); +} + +/** + * @brief Spi engine command interpreter + * + * @param desc Decriptor containing SPI interface parameters + * @param cmd Command to send to the engine + * @return int32_t - SUCCESS if the command is transferred + * - FAILURE if the command format is invalid + */ +static int32_t spi_engine_write_cmd(struct spi_desc *desc, + uint32_t cmd) +{ + uint8_t engine_command; + uint8_t parameter; + uint8_t modifier; + struct spi_engine_desc *desc_extra; + + desc_extra = desc->extra; + + engine_command = (cmd >> 12) & 0x0F; + modifier = (cmd >> 8) & 0x0F; + parameter = cmd & 0xFF; + + switch(engine_command) { + case SPI_ENGINE_INST_TRANSFER: + spi_engine_transfer(desc_extra, modifier, parameter); + break; + + case SPI_ENGINE_INST_ASSERT: + if(parameter == 0xFF) { + /* Set the CS HIGH */ + spi_engine_set_cs(desc, true); + } else if(parameter == 0x00) { + /* Set the CS LOW */ + spi_engine_set_cs(desc, false); + } + break; + + /* The SYNC and SLEEP commands got the same value but different + modifier */ + case SPI_ENGINE_INST_SYNC_SLEEP: + /* SYNC instruction */ + if(modifier == 0x00) { + spi_engine_write_cmd_reg(desc_extra, cmd); + } else if(modifier == 0x01) { + spi_gen_sleep_ns(desc, parameter); + } + break; + case SPI_ENGINE_INST_CONFIG: + spi_engine_write_cmd_reg(desc_extra, cmd); + + break; + + default: + + return FAILURE; + } + + return SUCCESS; +} + +/** + * @brief Prepare the command queue before sending it to the engine + * + * @param desc Decriptor containing SPI interface parameters + * @param msg Structure used to store the transfer messages + * @return int32_t This function always returns SUCCESS + */ +static int32_t spi_engine_compile_message(struct spi_desc *desc, + struct spi_engine_msg *msg) +{ + struct spi_engine_desc *desc_extra; + + desc_extra = desc->extra; + + /* Configure the prescaler */ + spi_engine_queue_append_cmd(&msg->cmds, + SPI_ENGINE_CMD_CONFIG( + SPI_ENGINE_CMD_REG_CLK_DIV, + desc_extra->clk_div)); + + /* Set the data transfer length */ + spi_engine_queue_append_cmd(&msg->cmds, + SPI_ENGINE_CMD_CONFIG( + SPI_ENGINE_CMD_DATA_TRANSFER_LEN, + desc_extra->data_width)); + /* + * Configure the spi mode : + * - 3 wire + * - CPOL + * - CPHA + */ + spi_engine_queue_append_cmd(&msg->cmds, + SPI_ENGINE_CMD_CONFIG( + SPI_ENGINE_CMD_REG_CONFIG, + desc->mode)); + + /* Add a sync command to signal that the transfer has finished */ + spi_engine_queue_add_cmd(&msg->cmds, SPI_ENGINE_CMD_SYNC(_sync_id)); + + return SUCCESS; +} + +/** + * @brief Initiate a spi transfer (Blocking) + * + * @param desc Decriptor containing SPI interface parameters + * @param msg Structure used to store the transfer messages + * @return int32_t - SUCCESS if the transfer finished + * - FAILURE if the memory allocation failed + */ +static int32_t spi_engine_transfer_message(struct spi_desc *desc, + struct spi_engine_msg *msg) +{ + uint32_t i; + uint32_t data; + uint32_t sync_id; + bool offload_en; + struct spi_engine_desc *desc_extra; + + desc_extra = desc->extra; + + spi_engine_compile_message(desc, msg); + + offload_en = (desc_extra->offload_config & OFFLOAD_TX_EN) | + (desc_extra->offload_config & OFFLOAD_RX_EN); + + /* Write the command fifo buffer */ + while(msg->cmds != NULL) { + spi_engine_queue_get_cmd(&msg->cmds, &data); + spi_engine_write_cmd(desc, data); + } + + /* Write a number of tx_length WORDS on the SDO line */ + if(offload_en) { + for(i = 0; i < desc_extra->offload_tx_len; i++) + spi_engine_write(desc_extra, + SPI_ENGINE_REG_OFFLOAD_SDO_MEM(0), + msg->tx_buf[i]); + + } else { + if(msg->tx_buf != NULL){ + for(i = 0; i < msg->tx_length; i++) + spi_engine_write(desc_extra, + SPI_ENGINE_REG_SDO_DATA_FIFO, + msg->tx_buf[i]); + } + do { + spi_engine_read(desc_extra, + SPI_ENGINE_REG_SYNC_ID, + &sync_id); + } + /* Wait for the end sync signal */ + while(sync_id != _sync_id); + _sync_id++; + + /* Read a number of rx_length WORDS from the SDI line and store + them */ + for(i = 0; i < msg->rx_length; i++) { + spi_engine_read(desc_extra, + SPI_ENGINE_REG_SDI_DATA_FIFO, + &data); + /* Store the rx data if rx buffer valid, flush sdi_fifo if + rx buffer is invalid.*/ + if(msg->rx_buf != NULL){ + msg->rx_buf[i] = data; + } + } + } + + return SUCCESS; +} + +/** + * @brief Initialize the spi engine + * + * @param desc Decriptor containing SPI interface parameters + * @param param Structure containing the spi init parameters + * @return int32_t - SUCCESS if the transfer finished + * - FAILURE if the memory allocation failed + */ +int32_t spi_engine_init(struct spi_desc **desc, + const struct spi_init_param *param) +{ + uint32_t data_width; + uint32_t spi_engine_version; + struct spi_engine_desc *eng_desc; + struct spi_engine_init_param *spi_engine_init; + + if (!param) { + return FAILURE; + } + + *desc = malloc(sizeof(**desc)); + if(! *desc) { + free(*desc); + return FAILURE; + } + + eng_desc = (struct spi_engine_desc*)malloc(sizeof(*eng_desc)); + + if (!eng_desc) + return FAILURE; + + spi_engine_init = param->extra; + + (*desc)->max_speed_hz = param->max_speed_hz; + (*desc)->chip_select = param->chip_select; + (*desc)->mode = param->mode; + (*desc)->extra = eng_desc; + + eng_desc->offload_config = OFFLOAD_DISABLED; + eng_desc->spi_engine_baseaddr = spi_engine_init->spi_engine_baseaddr; + eng_desc->type = spi_engine_init->type; + eng_desc->cs_delay = spi_engine_init->cs_delay; + eng_desc->ref_clk_hz = spi_engine_init->ref_clk_hz; + eng_desc->clk_div = eng_desc->ref_clk_hz / + (2 * param->max_speed_hz) - 1; + + /* Perform a reset */ + spi_engine_write(eng_desc, SPI_ENGINE_REG_RESET, 0x01); + usleep(1000); + spi_engine_write(eng_desc, SPI_ENGINE_REG_RESET, 0x00); + + /* Get current data width */ + spi_engine_read(eng_desc, SPI_ENGINE_REG_DATA_WIDTH, &data_width); + eng_desc->max_data_width = data_width; + + spi_engine_set_transfer_width(*desc, spi_engine_init->data_width); + + /* Get spi engine version */ + spi_engine_read(eng_desc, SPI_ENGINE_REG_VERSION, &spi_engine_version); + + printf("Spi engine v%"PRIu32".%"PRIu32".%"PRIu32" successfully initialized.\n", + (spi_engine_version >> 16), + ((spi_engine_version >> 8) & 0xFF), + (spi_engine_version & 0xFF)); + + return SUCCESS; +} + +/** + * @brief Write/read on the spi interface in 4-wire mode (full-duplex) + * + * @param desc Decriptor containing SPI interface parameters + * @param data Pointer to data buffer + * @param bytes_number Number of bytes to transfer + * @return int32_t - SUCCESS if the transfer finished + * - FAILURE if the memory allocation or transfer failed + */ +int32_t spi_engine_write_and_read(struct spi_desc *desc, + uint8_t *data, + uint16_t bytes_number) +{ + uint8_t word_len; + uint8_t words_number; + int32_t ret; + struct spi_engine_msg msg; + struct spi_engine_desc *desc_extra; + + desc_extra = desc->extra; + + /* If we want to access SPI interface and SPI engine offload module was + * activated, we need to disable it + * This is set in spi_engine_offload_init() */ + desc_extra->offload_config = OFFLOAD_DISABLED; + /* This is set in spi_engine_offload_transfer() */ + spi_engine_write(desc_extra, SPI_ENGINE_REG_OFFLOAD_CTRL(0), 0); + + words_number = spi_get_words_number(desc_extra, bytes_number); + + msg.cmds = (spi_engine_cmd_queue*)malloc(sizeof(*msg.cmds)); + if (!msg.cmds) + return FAILURE; + + msg.tx_buf =(uint32_t*)calloc(words_number, sizeof(msg.tx_buf[0])); + msg.rx_buf =(uint32_t*)calloc(words_number, sizeof(msg.rx_buf[0])); + msg.tx_length = words_number; + msg.rx_length = words_number; + + /* Get the length of transferred word */ + word_len = spi_get_word_length(desc_extra); + + /* Make sure the CS is HIGH before starting a transaction */ + msg.cmds->next = NULL; + msg.cmds->cmd = CS_HIGH; + // Assert select. + spi_engine_queue_add_cmd(&msg.cmds, CS_LOW); + // add read/write command + spi_engine_queue_add_cmd(&msg.cmds, WRITE_READ(bytes_number)); + // Disable select. + spi_engine_queue_add_cmd(&msg.cmds, CS_HIGH); + + /* Pack the bytes into engine WORDS */ + for (int i = 0; i < bytes_number; i++) + msg.tx_buf[i / word_len] |= data[i] << (desc_extra->data_width- + (i % word_len + 1) * 8); + + ret = spi_engine_transfer_message(desc, &msg); + + for (int i = 0; i < bytes_number; i++) + data[i] = msg.rx_buf[(i) / word_len] >> + (desc_extra->data_width - + ((i) % word_len + 1) * 8); + + spi_engine_queue_free(&msg.cmds); + free(msg.tx_buf); + free(msg.rx_buf); + + return ret; +} + +/** + * @brief Write and read on the spi interface in 3-wire mode (half-duplex) + * + * @param desc Decriptor containing SPI interface parameters + * @param data Pointer to data buffer + * @param bytes_number Number of bytes to transfer + * @return int32_t - SUCCESS if the transfer finished + * - FAILURE if the memory allocation or transfer failed + */ +int32_t spi_engine_write_and_read_3wire(struct spi_desc *desc, + uint8_t *write_data, + uint8_t *read_data, + uint16_t write_bytes_number, + uint16_t read_bytes_number) +{ + uint8_t word_len; + uint8_t wr_words_number; + uint8_t rd_words_number; + int32_t ret; + struct spi_engine_msg msg; + struct spi_engine_desc *desc_extra; + + desc_extra = desc->extra; + + /* If we want to access SPI interface and SPI engine offload module was + * activated, we need to disable it + * This is set in spi_engine_offload_init() */ + desc_extra->offload_config = OFFLOAD_DISABLED; + /* This is set in spi_engine_offload_transfer() */ + spi_engine_write(desc_extra, SPI_ENGINE_REG_OFFLOAD_CTRL(0), 0); + + wr_words_number = spi_get_words_number(desc_extra, write_bytes_number); + rd_words_number = spi_get_words_number(desc_extra, read_bytes_number); + + msg.cmds = (spi_engine_cmd_queue*)malloc(sizeof(*msg.cmds)); + if (!msg.cmds) + return FAILURE; + + msg.tx_buf =(wr_words_number>0)?(uint32_t*)calloc(wr_words_number, sizeof(msg.tx_buf[0])):NULL; + msg.rx_buf =(rd_words_number>0)?(uint32_t*)calloc(rd_words_number, sizeof(msg.rx_buf[0])):NULL; + msg.tx_length = wr_words_number; + msg.rx_length = rd_words_number; + + /* Get the length of transferred word */ + word_len = spi_get_word_length(desc_extra); + + /* Make sure the CS is HIGH before starting a transaction */ + msg.cmds->next = NULL; + msg.cmds->cmd = CS_HIGH; + + // Assert select. + spi_engine_queue_add_cmd(&msg.cmds, CS_LOW); + + // add read/write command + if(write_bytes_number > 0) + spi_engine_queue_add_cmd(&msg.cmds, WRITE(write_bytes_number)); + if(read_bytes_number > 0) + spi_engine_queue_add_cmd(&msg.cmds, READ(read_bytes_number)); + + // Disable select. + spi_engine_queue_add_cmd(&msg.cmds, CS_HIGH); + + /* Pack the bytes into engine WORDS */ + for (int i = 0; i < write_bytes_number; i++) + msg.tx_buf[i / word_len] |= write_data[i] << (desc_extra->data_width- + (i % word_len + 1) * 8); + + ret = spi_engine_transfer_message(desc, &msg); + + for (int i = 0; i < read_bytes_number; i++) + read_data[i] = msg.rx_buf[(i) / word_len] >> + (desc_extra->data_width - + ((i) % word_len + 1) * 8); + + spi_engine_queue_free(&msg.cmds); + free(msg.tx_buf); + free(msg.rx_buf); + + return ret; +} + +/** + * @brief Initialize the SPI engine's offload module + * + * @param desc Decriptor containing SPI interface parameters + * @param param Structure containing the offload init parameters + * @return int32_t This function always returns SUCCESS + */ +int32_t spi_engine_offload_init(struct spi_desc *desc, + const struct spi_engine_offload_init_param *param) +{ + struct spi_engine_desc *eng_desc; + struct axi_dmac_init dmac_init; + + eng_desc = desc->extra; + + eng_desc->offload_config = param->offload_config; + + if(!(param->dma_flags)) { + eng_desc->cyclic = CYCLIC; + } else { + if((*(param->dma_flags)) & DMA_CYCLIC) + eng_desc->cyclic = CYCLIC; + else + eng_desc->cyclic = NO; + } + + + if(param->offload_config & OFFLOAD_TX_EN) { + dmac_init.name = "DAC DMAC"; + dmac_init.base = param->tx_dma_baseaddr; + axi_dmac_init(&eng_desc->offload_tx_dma, &dmac_init); + if(!eng_desc->offload_tx_dma) + return FAILURE; + } + if(param->offload_config & OFFLOAD_RX_EN) { + dmac_init.name = "ADC DMAC"; + dmac_init.base = param->rx_dma_baseaddr; + axi_dmac_init(&eng_desc->offload_rx_dma, &dmac_init); + if(!eng_desc->offload_rx_dma) + return FAILURE; + } + + return SUCCESS; +} + +/** + * @brief Initiate a SPI transfer in offload mode + * + * @param desc Decriptor containing SPI interface parameters + * @param msg Offload message that get's to be transferred + * @param no_samples Number of time the messages will be transferred + * @return int32_t This function always returns SUCCESS + */ +int32_t spi_engine_offload_transfer(struct spi_desc *desc, + struct spi_engine_offload_message msg, + uint32_t no_samples) +{ + struct spi_engine_msg transfer; + struct spi_engine_desc *eng_desc; + uint32_t i; + uint8_t word_length; + + eng_desc = desc->extra; + + /* Check if offload is disabled */ + if(!((eng_desc->offload_config & OFFLOAD_TX_EN) | + (eng_desc->offload_config & OFFLOAD_RX_EN))) + return FAILURE; + + spi_engine_write(eng_desc, SPI_ENGINE_REG_OFFLOAD_RESET(0), 1); + spi_engine_write(eng_desc, SPI_ENGINE_REG_OFFLOAD_RESET(0), 0); + + eng_desc->offload_tx_len = 0; + eng_desc->offload_rx_len = 0; + + transfer.cmds = (spi_engine_cmd_queue*)malloc(sizeof(*transfer.cmds)); + + if (!transfer.cmds) + return -1; + + transfer.tx_buf = msg.commands_data; + + /* Load the commands into the message */ + transfer.cmds->next = NULL; + transfer.cmds->cmd = msg.commands[0]; + i = 1; + while(i < msg.no_commands) { + spi_engine_queue_add_cmd(&transfer.cmds, msg.commands[i++]); + + } + + spi_engine_transfer_message(desc, &transfer); + + /* Start transfer */ + spi_engine_write(eng_desc, SPI_ENGINE_REG_OFFLOAD_CTRL(0), 0x0001); + + word_length = spi_get_word_length(eng_desc); + if(eng_desc->offload_config & OFFLOAD_TX_EN) { + struct axi_dma_transfer tx_transfer = { + // Number of bytes to write/read + .size = word_length * eng_desc->offload_tx_len * no_samples, + // Transfer done flag + .transfer_done = 0, + // Signal transfer mode + .cyclic = eng_desc->cyclic, + // Address of data source + .src_addr = (uintptr_t)msg.tx_addr, + // Address of data destination + .dest_addr = 0 + }; + axi_dmac_transfer_start(eng_desc->offload_tx_dma, &tx_transfer); + } + + if(eng_desc->offload_config & OFFLOAD_RX_EN) { + struct axi_dma_transfer rx_transfer = { + // Number of bytes to write/read + .size = word_length * eng_desc->offload_tx_len * no_samples, + // Transfer done flag + .transfer_done = 0, + // Signal transfer mode + .cyclic = NO, + // Address of data source + .src_addr = 0, + // Address of data destination + .dest_addr = (uintptr_t)msg.rx_addr + }; + axi_dmac_transfer_start(eng_desc->offload_rx_dma, &rx_transfer); + axi_dmac_transfer_wait_completion(eng_desc->offload_rx_dma, 500); + } + + usleep(1000); + + spi_engine_queue_free(&transfer.cmds); + + return SUCCESS; +} + +/** + * @brief Free the resources allocated by spi_init(). + * + * @param desc Decriptor containing SPI interface parameters + * @return int32_t This function allways returns SUCCESS + */ +int32_t spi_engine_remove(struct spi_desc *desc) +{ + struct spi_engine_desc *eng_desc; + + eng_desc = desc->extra; + + if(eng_desc->offload_config & OFFLOAD_TX_EN) + axi_dmac_remove(eng_desc->offload_tx_dma); + if(eng_desc->offload_config & OFFLOAD_RX_EN) + axi_dmac_remove(eng_desc->offload_rx_dma); + free(desc->extra); + free(desc); + + return SUCCESS; +} diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/axi_core/spi_engine/spi_engine.h b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/axi_core/spi_engine/spi_engine.h new file mode 100644 index 0000000..8ae7af8 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/axi_core/spi_engine/spi_engine.h @@ -0,0 +1,229 @@ +/******************************************************************************* + * @file spi_engine.h + * @brief Header file of SPI Engine core features. + * @author Sergiu Cuciurean (sergiu.cuciurean@analog.com) +******************************************************************************** + * Copyright 2019(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +#ifndef SPI_ENGINE_H +#define SPI_ENGINE_H + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ + +#include + +#include "spi_engine_private.h" +#include "../axi_dmac/axi_dmac.h" +#include "../../platform/xilinx_spi.h" + +/******************************************************************************/ +/********************** Macros and Constants Definitions **********************/ +/******************************************************************************/ + +#define OFFLOAD_DISABLED 0x00 +#define OFFLOAD_TX_EN BIT(0) +#define OFFLOAD_RX_EN BIT(1) +#define OFFLOAD_TX_RX_EN OFFLOAD_TX_EN | OFFLOAD_RX_EN + +#define SPI_ENGINE_MSG_QUEUE_END 0xFFFFFFFF + +/* Spi engine commands */ +#define WRITE(no_bytes) ((SPI_ENGINE_INST_TRANSFER << 12) |\ + (SPI_ENGINE_INSTRUCTION_TRANSFER_W << 8) | no_bytes) + +#define READ(no_bytes) ((SPI_ENGINE_INST_TRANSFER << 12) |\ + (SPI_ENGINE_INSTRUCTION_TRANSFER_R << 8) | no_bytes) + +#define WRITE_READ(no_bytes) ((SPI_ENGINE_INST_TRANSFER << 12) |\ + (SPI_ENGINE_INSTRUCTION_TRANSFER_RW << 8) | no_bytes) + +#define SLEEP(time) SPI_ENGINE_CMD_SLEEP(time & 0xF) + +/* The delay and chip select parmeters are passed over the engine descriptor +and will be used inside the function call */ +#define CS_HIGH SPI_ENGINE_CMD_ASSERT(0x01, 0xFF) +#define CS_LOW SPI_ENGINE_CMD_ASSERT(0x01, 0x00) + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ + +/** + * @struct spi_engine_init_param + * @brief Structure containing the init parameters needed by the SPI engine + */ +struct spi_engine_init_param { + /** SPI engine reference clock */ + uint32_t ref_clk_hz; + /** Type of implementation */ + enum xil_spi_type type; + /** Base address where the HDL core is situated */ + uint32_t spi_engine_baseaddr; + /** Delay between the CS toggle and the start of SCLK */ + uint32_t cs_delay; + /** Data with of one SPI transfer ( in bits ) */ + uint8_t data_width; +}; + + +/** + * @struct spi_engine_desc + * @brief Structure representing an SPI engine device + */ +struct spi_engine_desc { + /** SPI engine reference clock */ + uint32_t ref_clk_hz; + /** Type of implementation */ + enum xil_spi_type type; + /** Pointer to a DMAC used in transmission */ + struct axi_dmac *offload_tx_dma; + /** Pointer to a DMAC used in reception */ + struct axi_dmac *offload_rx_dma; + /** Transfer mode for Tx DMAC */ + enum cyclic_transfer cyclic; + /** Offload's module transfer direction : TX, RX or both */ + uint8_t offload_config; + /** Number of words that the module has to send */ + uint8_t offload_tx_len; + /** Number of words that the module has to receive */ + uint8_t offload_rx_len; + /** Base address where the HDL core is situated */ + uint32_t spi_engine_baseaddr; + /** Base address where the RX DMAC core is situated */ + uint32_t rx_dma_baseaddr; + /** Base address where the TX DMAC core is situated */ + uint32_t tx_dma_baseaddr; + /** Delay between the CS toggle and the start of SCLK */ + uint8_t cs_delay; + /** Clock divider used in transmission delays */ + uint32_t clk_div; + /** Data with of one SPI transfer ( in bits ) */ + uint8_t data_width; + /** The maximum data width supported by the engine */ + uint8_t max_data_width; +}; + + +/** + * @struct spi_engine_offload_init_param + * @brief Structure containing the init parameters needed by the offload module + */ +struct spi_engine_offload_init_param { + /** Base address where the RX DMAC core is situated */ + uint32_t rx_dma_baseaddr; + /** Base address where the TX DMAC core is situated */ + uint32_t tx_dma_baseaddr; + /** DMAC flags - if not initialized, the default value is DMA_CYCLIC */ + uint32_t *dma_flags; + /** Offload's module transfer direction : TX, RX or both */ + uint8_t offload_config; +}; + +/** + * @struct spi_engine_offload_message + * @brief Structure representing an offload message + */ +struct spi_engine_offload_message { + /** Pointer to the SPI engine commands buffer that will be sent. + * The available commands can be found at: + * https://wiki.analog.com/resources/fpga/peripherals/spi_engine/ + */ + uint32_t *commands; + /** Length of the SPI engine commands buffer */ + uint32_t no_commands; + /** Pointer of the data that will be sent over spi */ + uint32_t *commands_data; + /** The address where the data that will be transmitted is situated */ + uint32_t tx_addr; + /** The address where the data that will be received is situated */ + uint32_t rx_addr; +}; + +/******************************************************************************/ +/************************ Functions Declarations ******************************/ +/******************************************************************************/ + +/** + * @brief Spi engine platform specific SPI platform ops structure + */ +extern const struct spi_platform_ops xil_spi_ops; + +/* Write SPI Engine's axi registers */ +int32_t spi_engine_write(struct spi_engine_desc *desc, + uint32_t reg_addr, + uint32_t reg_data); + +/* Read SPI Engine's axi registers */ +int32_t spi_engine_read(struct spi_engine_desc *desc, + uint32_t reg_addr, + uint32_t *reg_data); +/* Initialize the SPI engine device */ +int32_t spi_engine_init(struct spi_desc **desc, + const struct spi_init_param *param); + +/* Write and read data over SPI using the SPI engine */ +int32_t spi_engine_write_and_read(struct spi_desc *desc, + uint8_t *data, + uint16_t bytes_number); + +/* Write and read data over SPI using the SPI engine in 3-wire mode */ +int32_t spi_engine_write_and_read_3wire(struct spi_desc *desc, + uint8_t *write_data, + uint8_t *read_data, + uint16_t write_bytes_number, + uint16_t read_bytes_number); +/* Free the resources used by the SPI engine device */ +int32_t spi_engine_remove(struct spi_desc *desc); + +/* Initialize the SPI engine offload module */ +int32_t spi_engine_offload_init(struct spi_desc *desc, + const struct spi_engine_offload_init_param *param); + +/* Write and read data over SPI using the offload module */ +int32_t spi_engine_offload_transfer(struct spi_desc *desc, + struct spi_engine_offload_message msg, + uint32_t no_samples); + +/* Set SPI transfer width */ +int32_t spi_engine_set_transfer_width(struct spi_desc *desc, + uint8_t data_wdith); + +/* Set SPI transfer speed */ +void spi_engine_set_speed(struct spi_desc *desc, + uint32_t speed_hz); + +#endif // SPI_ENGINE_H diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/axi_core/spi_engine/spi_engine_private.h b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/axi_core/spi_engine/spi_engine_private.h new file mode 100644 index 0000000..2d46906 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/axi_core/spi_engine/spi_engine_private.h @@ -0,0 +1,154 @@ +/******************************************************************************* + * @file spi_engine_private.h + * @brief Private definitions of the SPI Engine + * @author Sergiu Cuciurean (sergiu.cuciurean@analog.com) +******************************************************************************** + * Copyright 2019(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +#ifndef SPI_ENGINE_PRIVATE_H +#define SPI_ENGINE_PRIVATE_H + +#include +#include + +#include "spi.h" +#include "util.h" + +/******************************************************************************/ +/*************************** Spi Engine registers *****************************/ +/******************************************************************************/ + +#define SPI_ENGINE_REG_VERSION 0x00 +#define SPI_ENGINE_REG_DATA_WIDTH 0x0C +#define SPI_ENGINE_REG_RESET 0x40 +#define SPI_ENGINE_REG_INT_ENABLE 0x80 +#define SPI_ENGINE_REG_INT_PENDING 0x84 +#define SPI_ENGINE_REG_INT_SOURCE 0x88 +#define SPI_ENGINE_REG_SYNC_ID 0xC0 +#define SPI_ENGINE_REG_CMD_FIFO_ROOM 0xD0 +#define SPI_ENGINE_REG_SDO_FIFO_ROOM 0xD4 +#define SPI_ENGINE_REG_SDI_FIFO_LEVEL 0xD8 +#define SPI_ENGINE_REG_CMD_FIFO 0xE0 +#define SPI_ENGINE_REG_SDO_DATA_FIFO 0xE4 +#define SPI_ENGINE_REG_SDI_DATA_FIFO 0xE8 +#define SPI_ENGINE_REG_SDI_DATA_FIFO_PEEK 0xEC + +/******************************************************************************/ +/************************ Spi Engine register parameters **********************/ +/******************************************************************************/ + +#define SPI_ENGINE_INST_TRANSFER 0x00 +#define SPI_ENGINE_INST_ASSERT 0x01 +#define SPI_ENGINE_INST_CONFIG 0x02 +#define SPI_ENGINE_INST_SYNC_SLEEP 0x03 +#define SPI_ENGINE_INST_MISC 0x03 +#define SPI_ENGINE_CMD_REG_CLK_DIV 0x00 +#define SPI_ENGINE_CMD_REG_CONFIG 0x01 +#define SPI_ENGINE_CMD_DATA_TRANSFER_LEN 0x02 +#define SPI_ENGINE_MISC_SYNC 0x00 +#define SPI_ENGINE_MISC_SLEEP 0x01 +#define SPI_ENGINE_SYNC_TRANSFER_BEGIN BIT(1) +#define SPI_ENGINE_SYNC_TRANSFER_END BIT(2) +#define SPI_ENGINE_INT_CMD_ALMOST_EMPTY BIT(0) +#define SPI_ENGINE_INT_SDO_ALMOST_EMPTY BIT(1) +#define SPI_ENGINE_INT_SDI_ALMOST_FULL BIT(2) +#define SPI_ENGINE_INT_SYNC BIT(3) +#define SPI_ENGINE_OFFLOAD_CTRL_ENABLE BIT(0) +#define SPI_ENGINE_OFFLOAD_STATUS_ENABLED BIT(0) +#define SPI_ENGINE_CONFIG_CPHA BIT(0) +#define SPI_ENGINE_CONFIG_CPOL BIT(1) +#define SPI_ENGINE_CONFIG_3WIRE BIT(2) +#define SPI_ENGINE_VERSION_MAJOR(x) ((x >> 16) & 0xff) +#define SPI_ENGINE_VERSION_MINOR(x) ((x >> 8) & 0xff) +#define SPI_ENGINE_VERSION_PATCH(x) (x & 0xff) + +/******************************************************************************/ +/**************************** Spi Engine commands *****************************/ +/******************************************************************************/ + +#define SPI_ENGINE_INSTRUCTION_TRANSFER_W 0x01 +#define SPI_ENGINE_INSTRUCTION_TRANSFER_R 0x02 +#define SPI_ENGINE_INSTRUCTION_TRANSFER_RW 0x03 + +#define SPI_ENGINE_REG_OFFLOAD_CTRL(x) (0x100 + (0x20 * x)) +#define SPI_ENGINE_REG_OFFLOAD_STATUS(x) (0x104 + (0x20 * x)) +#define SPI_ENGINE_REG_OFFLOAD_RESET(x) (0x108 + (0x20 * x)) +#define SPI_ENGINE_REG_OFFLOAD_CMD_MEM(x) (0x110 + (0x20 * x)) +#define SPI_ENGINE_REG_OFFLOAD_SDO_MEM(x) (0x114 + (0x20 * x)) + +#define SPI_ENGINE_CMD(inst, arg1, arg2) \ + (((inst & 0x03) << 12) | \ + ((arg1 & 0x03) << 8) | arg2 ) + +#define SPI_ENGINE_CMD_TRANSFER(readwrite, n) \ + SPI_ENGINE_CMD(SPI_ENGINE_INST_TRANSFER, \ + (readwrite), (n)) + +#define SPI_ENGINE_CMD_ASSERT(delay, cs) \ + SPI_ENGINE_CMD(SPI_ENGINE_INST_ASSERT, \ + (delay), (cs)) + +#define SPI_ENGINE_CMD_CONFIG(reg, val) \ + SPI_ENGINE_CMD(SPI_ENGINE_INST_CONFIG, \ + (reg), (val)) + +#define SPI_ENGINE_CMD_SLEEP(delay) \ + SPI_ENGINE_CMD(SPI_ENGINE_INST_MISC, \ + SPI_ENGINE_MISC_SLEEP, \ + (delay)) + +#define SPI_ENGINE_CMD_SYNC(id) \ + SPI_ENGINE_CMD(SPI_ENGINE_INST_MISC, \ + SPI_ENGINE_MISC_SYNC, \ + (id)) + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ + +typedef struct spi_engine_cmd_queue { + uint32_t cmd; + struct spi_engine_cmd_queue *next; +} spi_engine_cmd_queue; + +typedef struct spi_engine_msg { + uint32_t *tx_buf; + uint32_t *rx_buf; + uint32_t tx_length; + uint32_t rx_length; + struct spi_engine_cmd_queue *cmds; +} spi_engine_msg; + +#endif // SPI_ENGINE_PRIVATE_H diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/frequency/ad9528/ad9528.c b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/frequency/ad9528/ad9528.c new file mode 100644 index 0000000..7894fd6 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/frequency/ad9528/ad9528.c @@ -0,0 +1,783 @@ +/** + * \file ad9528.c + * \brief Contains source code for configuring and initializing AD9528 clock device + */ + +/** +* \page Disclaimer Legal Disclaimer +* Copyright 2015-2017 Analog Devices Inc. +* Released under the AD9371 API license. +* +*/ + +#include +#include +#include "ad9528.h" +#include "../../../include/error.h" + +static uint32_t _desired_time_to_elapse_ms = 0; + +/** + * \brief Write data to a register + */ +int32_t AD9528_spiWriteByte(ad9528Device_t *device, uint16_t addr, + uint8_t data) +{ + uint8_t buf[3]; + int32_t status; + + buf[0] = (addr >> 8) & 0x7F; + buf[1] = addr & 0xFF; + buf[2] = data; + status = spi_write_and_read_3wire(device->spi_desc, + buf, NULL, 3, 0); + + return status; +} + +/** + * \brief Read data from a register + */ +int32_t AD9528_spiReadByte(ad9528Device_t *device, uint16_t addr, + uint8_t *readdata) +{ + uint8_t tx_buf[2]; + uint8_t rx_buf[1]; + int32_t status; + + tx_buf[0] = 0x80 | addr >> 8; + tx_buf[1] = addr & 0xFF; + + status = spi_write_and_read_3wire(device->spi_desc, + tx_buf, rx_buf, 2, 1); + + *readdata = rx_buf[0]; + + return status; +} + +/** + * \brief Modify a field of bits from a register + */ +int32_t AD9528_spiWriteField(ad9528Device_t *device, + uint16_t addr, uint8_t fieldVal, uint8_t mask, uint8_t startBit) +{ + int32_t errVal; + uint8_t readVal; + + errVal = AD9528_spiReadByte(device, addr, &readVal); + if (errVal < 0) + return errVal; + + readVal = (readVal & ~mask) | ((fieldVal << startBit) & mask); + + return AD9528_spiWriteByte(device, addr, readVal); +} + +/** + * \brief Set the desired timeout value + */ +int32_t AD9528_setTimeout_ms(uint32_t timeOut_ms) +{ + _desired_time_to_elapse_ms = timeOut_ms; + + return SUCCESS; +} + +/** + * \brief Verify if the desired time has elapsed + */ +int32_t AD9528_hasTimeoutExpired() +{ + udelay(1000); + + _desired_time_to_elapse_ms--; + if (_desired_time_to_elapse_ms > 0) + return SUCCESS; + + return FAILURE; +} + +/** + * \brief Performs a hard reset on the AD9528 DUT + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * + * \param device is structure pointer to the AD9528 data structure containing settings + * \return Returns enum ADI_ERR, ADIERR_OK=pass, !ADIERR_OK=fail + */ +int32_t AD9528_resetDevice(ad9528Device_t *device) +{ + gpio_direction_output(device->gpio_resetb, 0); + mdelay(100); + gpio_direction_output(device->gpio_resetb, 1); + mdelay(100); + + AD9528_spiWriteByte(device, AD9528_ADDR_ADI_SPI_CONFIG_A, 0x81); + mdelay(100); + AD9528_spiWriteByte(device, AD9528_ADDR_ADI_SPI_CONFIG_A, 0x00); + mdelay(100); + + return SUCCESS; +} + +/** + * \brief Sets the AD9528 device SPI settings (3wire/4wire, MSBFirst, etc). + * + * This function will use the settings in the device->spiSettings structure + * to set SPI stream mode, address auto increment direction, MSBFirst/LSBfirst, + * and 3wire/4wire mode. The AD9528 device always uses SPI MODE 0 (CPHA=0, CPOL=0). + * This function will update your device->spiSettings to set CHPA=0 and CPOL=0 and + * longInstructionWord =1 to use a 16bit instruction word. + * + * Dependencies + * - writes device->spiSettings->CPHA = 0 + * - writes device->spiSettings->CPOL = 0 + * - writes device->spiSettings->longInstructionWord = 1 + * + * - device->spiSettings->MSBFirst + * - device->spiSettings->enSpiStreaming + * - device->spiSettings->autoIncAddrUp + * - device->spiSettings->fourWireMode + * + * \param device is structure pointer to the AD9528 data structure containing settings + * + * \return Returns enum ADI_ERR, ADIERR_OK=pass, !ADIERR_OK=fail + */ +int32_t AD9528_setSpiSettings(ad9528Device_t *device) +{ + uint8_t spiReg = 0; + + device->spiSettings->CPHA = 0; + device->spiSettings->CPOL = 0; + device->spiSettings->longInstructionWord = 1; + + if (device->spiSettings->MSBFirst == 0) { + spiReg |= 0x42; /* SPI bit is 1=LSB first */ + } + + if (device->spiSettings->autoIncAddrUp > 0) { + spiReg |= 0x24; + } + + if (device->spiSettings->fourWireMode > 0) { + spiReg |= 0x18; + } + + AD9528_spiWriteByte(device, AD9528_ADDR_ADI_SPI_CONFIG_A, spiReg); + + if (device->spiSettings->enSpiStreaming > 0) { + /* Allow SPI streaming mode: SPI message ends when chip select deasserts */ + AD9528_spiWriteByte(device, AD9528_ADDR_ADI_SPI_CONFIG_B, 0x00); + } else { + /* Force single instruction mode */ + AD9528_spiWriteByte(device, AD9528_ADDR_ADI_SPI_CONFIG_B, 0x80); + } + + return SUCCESS; +} + +/** + * \brief Helper function for ADI transceiver eval boards to init the AD9528 data structure + * + * This function inits the AD9528 device data structure with defaults that + * are known to work with the ADI AD9369 and AD9371 evaluation boards. NOTE: This function will + * modify the contents of the AD9528 device data structure. + * + * Dependencies + * - spi->chipSelectIndex + * - spi + * + * \param device Pointer to the AD9528 device data structure to initialize + * \param vcxoFrequency_Hz The VCXO frequency that is connected to the AD9528 + * \param refAFrequency_Hz The reference clock frequency being input into the AD9528 REFCLK A input + * \param outputDeviceClock_Hz Desired output clock frequency to the FPGA and transceiver device + * + * \return Returns enum ADI_ERR, 0=pass, >0 = fail +*/ +int32_t AD9528_initDeviceDataStruct(ad9528Device_t *device, + uint32_t vcxoFrequency_Hz, uint32_t refAFrequency_Hz, + uint32_t outputDeviceClock_Hz) +{ +// uint16_t chDiv; +// uint8_t i = 0; +// +// uint32_t pll1PfdFreq_Hz = 0; +// uint8_t pll1Ndiv = 0; +// uint8_t validPll1DivSetting = 0; +// uint8_t refAdiv = 1; +// +// +// uint8_t pll2RfDiv = 3; /* Valid values 3,4,5 */ +// uint16_t pll2Ndiv = 1; /* Valid values 1-256 */ +// uint32_t pll2InputFreq_Hz = 0; +// uint64_t pll2VcoFreq_Hz = 0; +// uint16_t pll2NdivStart = 0; +// uint8_t validPll2DivSetting = 0; +// uint64_t chDivU64 = 0; +// +// static const uint64_t PLL2_MIN_VCO_FREQ_HZ = 3450000000ULL; +// static const uint64_t PLL2_MAX_VCO_FREQ_HZ = 4025000000ULL; + +// struct spi_init_param spi_param; +// int32_t status; +// +// status = gpio_get(&device->gpio_resetb, CLK_RESETB); +// status |= gpio_get(&device->gpio_sysref_req, ADRV_SYSREF_REQ); +// +// spi_param.id = 0; +// spi_param.mode = SPI_MODE_0; +// spi_param.chip_select = CLK_CS; +// status |= spi_init(&device->spi_desc, &spi_param); +// +// if (status != SUCCESS) +// return FAILURE; + + /******************************************************************* + * PLL1 Settings + ******************************************************************* + */ + + /* find valid PLL1 Ndiv and REFA div */ +// for (pll1Ndiv = 1; pll1Ndiv < 20; pll1Ndiv++) { +// pll1PfdFreq_Hz = vcxoFrequency_Hz / pll1Ndiv; +// +// if ((pll1PfdFreq_Hz <= 110000000) && (pll1PfdFreq_Hz >= 1000000) && +// (pll1PfdFreq_Hz <= refAFrequency_Hz) && +// (refAFrequency_Hz % pll1PfdFreq_Hz == 0) +// ) { +// validPll1DivSetting = 1; +// refAdiv = refAFrequency_Hz / pll1PfdFreq_Hz ; +// break; +// } +// } +// +// if (validPll1DivSetting == 0) { +// return FAILURE; +// } + +// device->pll1Settings->nDivider = +// pll1Ndiv; //This init function always runs PLL1 at 30.72MHz Pfd rate +// device->pll1Settings->refA_bufferCtrl = +// DIFFERENTIAL; //DISABLED = 0, SINGLE_ENDED, NEG_SINGLE_ENDED, DIFFERENTIAL +// device->pll1Settings->refA_Divider = refAdiv; +// device->pll1Settings->refA_Frequency_Hz = refAFrequency_Hz; +// device->pll1Settings->refB_bufferCtrl = +// DISABLED; //DISABLED = 0, SINGLE_ENDED, NEG_SINGLE_ENDED, DIFFERENTIAL +// device->pll1Settings->refB_Divider = 1; +// device->pll1Settings->refB_Frequency_Hz = 0; +// device->pll1Settings->vcxoBufferCtrl = +// NEG_SINGLE_ENDED; //DISABLED = 0, SINGLE_ENDED, NEG_SINGLE_ENDED, DIFFERENTIAL +// device->pll1Settings->vcxo_Frequency_Hz = vcxoFrequency_Hz; + + /******************************************************************* + * PLL2 Settings + ******************************************************************* + */ + + /******************************************************************* + * Output Distribution Settings + * 9369CE02A uses the following clock outputs + * OUT 1: FPGA REFCLK + * OUT 3: FPGA SYSREF + * OUT 12: DUT SYSREF + * OUT 13: DUT REFCLK + ******************************************************************* + */ + + /* PLL 2 input clock can be several different things. Currently hard coded by this init funciton to use + * PLL 1 output (VCXO Frequency) with no scaling + */ +// pll2InputFreq_Hz = device->pll1Settings->vcxo_Frequency_Hz; +// validPll2DivSetting = 0; + + /* Sweep PLL2 Divider settings to find something that has a valid integer divide (3,4,5)*/ +// for (pll2RfDiv = 3; pll2RfDiv <= 5; pll2RfDiv++) { +// +// pll2NdivStart = (PLL2_MIN_VCO_FREQ_HZ / pll2RfDiv / pll2InputFreq_Hz); +// /* find valid PLL2 Ndiv (1-256) */ +// for (pll2Ndiv = pll2NdivStart; pll2Ndiv <= 256; pll2Ndiv++) { +// pll2VcoFreq_Hz = (pll2InputFreq_Hz * pll2RfDiv * pll2Ndiv); +// +// if (pll2VcoFreq_Hz < PLL2_MIN_VCO_FREQ_HZ) { +// /* Continue to next PLL2 N div */ +// continue; +// } else if (pll2VcoFreq_Hz > PLL2_MAX_VCO_FREQ_HZ) { +// /* Break to next PLL2 RF div */ +// break; +// } +// +// if (((pll2VcoFreq_Hz / pll2RfDiv) % outputDeviceClock_Hz) == 0) { +// +// device->pll2Settings->rfDivider = pll2RfDiv; +// device->pll2Settings->n2Divider = pll2Ndiv; +// device->pll2Settings->totalNdiv = pll2RfDiv * pll2Ndiv; +// chDivU64 = ((pll2VcoFreq_Hz / pll2RfDiv) / outputDeviceClock_Hz); +// +// if ((chDivU64 < 1) || (chDivU64 > 256)) { +// return FAILURE; +// } else { +// chDiv = (uint16_t)(chDivU64); +// } +// +// validPll2DivSetting = 1; +// break; +// } +// } +// +// if (validPll2DivSetting == 1) { +// break; +// } +// } +// +// if (validPll2DivSetting == 0) { +// return FAILURE; +// } +// +// device->outputSettings->outPowerDown = (uint16_t)( +// ~0x318A); //enable outputs 13,12,8,7,3 and 1 +// +// for (i=0; i<14; i++) { +// device->outputSettings->outSource[i] = +// CHANNEL_DIV; //CHANNEL_DIV , PLL1_OUTPUT, SYSREF, INV_PLL1_OUTPUT +// device->outputSettings->outBufferCtrl[i] = LVDS; //LVDS, LVDS_BOOST, HSTL +// device->outputSettings->outChannelDiv[i] = chDiv; +// device->outputSettings->outFrequency_Hz[i] = outputDeviceClock_Hz; +// device->outputSettings->outAnalogDelay[i] = 0; +// device->outputSettings->outDigitalDelay[i] = 0; +// } +// +// +// device->outputSettings->outSource[3] = SYSREF; +// device->outputSettings->outSource[7] = SYSREF; +// device->outputSettings->outSource[12] = SYSREF; +// +// +// device->sysrefSettings->sysrefDivide = +// 512; //SYSREF frequency = VCXO / 2 / sysrefDivde +// device->sysrefSettings->sysrefNshotMode = +// ONE_PULSE; //ONE_PULSE=0, TWO_PULSES=2, FOUR_PULSES=3, SIX_PULSES=4, EIGHT_PULSES=5 +// device->sysrefSettings->sysrefPatternMode = +// CONTINUOUS; //NSHOT=0, CONTINUOUS=1, PRBS=2, STOP=3 +// device->sysrefSettings->sysrefPinBufferMode = +// DISABLED; //DISABLED = 0, SINGLE_ENDED, NEG_SINGLE_ENDED, DIFFERENTIAL +// device->sysrefSettings->sysrefPinEdgeMode = +// LEVEL_ACTIVE_HIGH; //LEVEL_ACTIVE_HIGH=0, LEVEL_ACTIVE_LOW=1, RISING_EDGE=2, FALLING_EDGE=3 +// device->sysrefSettings->sysrefRequestMethod = PIN; //SPI=0,PIN=1 +// device->sysrefSettings->sysrefSource = +// INTERNAL; //EXTERNAL=0, EXT_RESAMPLED=1, INTERNAL=2 + + return SUCCESS; +} + +int32_t AD9528_init(ad9528Device_t **device, const ad9528Init_t *init_device) +{ + int ret = SUCCESS; + ad9528Device_t *dev; + + dev = (ad9528Device_t *)malloc(sizeof(*dev)); + if (!dev) + return FAILURE; + + /* SPI */ + ret = spi_init(&dev->spi_desc, init_device->spi_init); + ret |= gpio_get(&dev->gpio_resetb, init_device->gpio_init_resetb); + ret |= gpio_get(&dev->gpio_sysref_req, init_device->gpio_init_sysref_req); + + gpio_direction_output(dev->gpio_resetb, 0); + gpio_direction_output(dev->gpio_sysref_req, 0); + + AD9528_resetDevice(dev); + + dev->spiSettings = init_device->spiSettings; + dev->pll1Settings = init_device->pll1Settings; + dev->pll2Settings = init_device->pll2Settings; + dev->outputSettings = init_device->outputSettings; + dev->sysrefSettings = init_device->sysrefSettings; + + *device = dev; + + return ret; +} + +/** + * \brief Initializes the AD9528 by writing all SPI registers + * + * Initializes the AD9528 for use with the AD9369 transceiver. Designed to work with + * a reference clock of 122.88MHz. Reference clock is expected to be 30.72MHz. + * The output clocks from the AD9528 can run at 122.88M, 153.6M, 184.32M, 245.76M, or 307.2M. + * Typical setup: REFA frequency = 30.72, VCXO = 122.88MHz + * SYNC(SYSREF) pulses output at rate of 120kHz + * + * Dependencies + * - All parameters in device structure + * + * \param device is structure pointer to AD9528 clock device structure + * + * \return Returns enum ADI_ERR, 0=pass, >0 = fail + */ +int32_t AD9528_config(ad9528Device_t + *device) //writes all registers to desired values, leaves clock outputs off, SYSREF output disabled. +{ + uint8_t pll2_Adiv=0; + uint8_t pll2_Bdiv=0; + uint8_t reg108=0; + uint8_t reg109=0x4; + uint8_t i = 0; + uint8_t j = 0; + uint8_t reg508; + int32_t retval = SUCCESS; + + retval = AD9528_setSpiSettings(device); + if (retval != SUCCESS) { + return retval; + } + + /********************************************************************** + * Configure PLL1 + ********************************************************************** + */ + + AD9528_spiWriteByte(device, AD9528_ADDR_REF_A_DIVIDER_LSB, + device->pll1Settings->refA_Divider & 0xFF); //REF A div[7:0] + AD9528_spiWriteByte(device, AD9528_ADDR_REF_A_DIVIDER_MSB, + (device->pll1Settings->refA_Divider >> 8) & 0x03); //REF A div[9:8] + AD9528_spiWriteByte(device, AD9528_ADDR_REF_B_DIVIDER_LSB, + device->pll1Settings->refB_Divider & 0xFF); //REF B div[7:0] + AD9528_spiWriteByte(device, AD9528_ADDR_REF_B_DIVIDER_MSB, + (device->pll1Settings->refB_Divider >> 8) & 0x03); //REF B div[9:8] + AD9528_spiWriteByte(device, AD9528_ADDR_PLL1_N_DIV_LSB, + device->pll1Settings->nDivider & 0xFF); //PLL1 N div[7:0] + AD9528_spiWriteByte(device, AD9528_ADDR_PLL1_N_DIV_MSB, + (device->pll1Settings->nDivider >> 8) & 0x03); //PLL1 N div[9:8] + AD9528_spiWriteByte(device, AD9528_ADDR_PLL1_CHARGEPUMP, + 0x0A); //PLL1 Charge Pump control 1 + AD9528_spiWriteByte(device, AD9528_ADDR_PLL1_CP_CTRL2, + 0x03); //PLL1 Charge Pump control 2 + + switch (device->pll1Settings->refA_bufferCtrl) { + case DISABLED: + reg108 &= ~0x28; + reg109 &= ~0x01; + break; //clear all REFA enable bits + case SINGLE_ENDED: + reg108 |= 0x08; + reg109 &= ~0x01; + break; //Set REFA receiver enable, clear REFA SE negative input enable + case NEG_SINGLE_ENDED: + reg108 |= 0x08; + reg108 &= ~0x10; + reg109 |= 0x01; + break; //Disable REFA diff receiver, enable REFA receiver and use negative REFA input + case DIFFERENTIAL: + reg108 |= 0x28; + reg109 &= ~0x01; + break; + default: + reg108 |= 0x08; + reg109 &= ~0x01; + break; //default to single ended case + } + switch (device->pll1Settings->refB_bufferCtrl) { + case DISABLED: + reg108 &= ~0x50; + reg109 &= ~0x02; + break; //clear all REFB enable bits + case SINGLE_ENDED: + reg108 |= 0x10; + reg109 &= ~0x02; + break; //Set REFB receiver enable, clear REFB SE negative input enable + case NEG_SINGLE_ENDED: + reg108 |= 0x10; + reg108 &= ~0x40; + reg109 |= 0x02; + break; //Disable REFB diff receiver, enable REFB receiver and use negative REFB input + case DIFFERENTIAL: + reg108 |= 0x50; + reg109 &= ~0x02; + break; + default: + reg108 |= 0x10; + reg109 &= ~0x02; + break; //default to single ended case + } + switch (device->pll1Settings->vcxoBufferCtrl) { + case DISABLED: + reg108 &= ~0x03; + reg108 |= 0x04; + break; //power down VCXO input + case SINGLE_ENDED: + reg108 &= ~0x07; + break; //Clear VCXO receiver power down, defaults to Single ended mode + case NEG_SINGLE_ENDED: + reg108 &= ~0x07; + reg108 |= 0x02; + break; //Clear VCXO power down, enable Negative single ended mode[1] + case DIFFERENTIAL: + reg108 &= ~0x07; + reg108 |= 0x01; + break; //Clear VCXO power down, enable differential input buffer[0] + default: + reg108 &= ~0x07; + break; //default to positive single ended case + } + + + AD9528_spiWriteByte(device, AD9528_ADDR_INPUT_RECEIVERS1, + reg108); //Input receiver settings (single ended or differential clock inputs) + AD9528_spiWriteByte(device, AD9528_ADDR_INPUT_RECEIVERS2, + reg109); //Input receiver settings + AD9528_spiWriteByte(device, AD9528_ADDR_INPUT_RECEIVERS3, + 0x0A); //Reference selection mode + AD9528_spiWriteByte(device, AD9528_ADDR_PLL1_FASTLOCK, + 0x00); //Disable Fast lock + + /********************************************************************** + * Configure PLL2 + ********************************************************************** + */ + pll2_Bdiv = device->pll2Settings->totalNdiv / 4; + pll2_Adiv = device->pll2Settings->totalNdiv % 4; + + if (pll2_Adiv > 3) { //A div valid range (0 to 3) + return FAILURE; + } + if (pll2_Bdiv < 3 || pll2_Bdiv > 63) { + return FAILURE; + } + AD9528_spiWriteByte(device, AD9528_ADDR_PLL2_CHARGEPUMP, + 0xE6); //PLL2 Charge Pump[7:0] + AD9528_spiWriteByte(device, AD9528_ADDR_PLL2_N_DIV, + ((pll2_Adiv & 0x3) << 6) | (pll2_Bdiv & 0x3F)); //PLL2 A and B divider + AD9528_spiWriteByte(device, AD9528_ADDR_PLL2_CTRL, 0x03); //PLL2 control + AD9528_spiWriteByte(device, AD9528_ADDR_PLL2_VCO_CTRL, 0x01); //Manual VCO CAL + + if (device->pll2Settings->rfDivider < 3 + || device->pll2Settings->rfDivider > 5) { + return FAILURE; + } + + AD9528_spiWriteByte(device, AD9528_ADDR_PLL2_VCO_DIV, + device->pll2Settings->rfDivider); //VCO divider + AD9528_spiWriteByte(device, AD9528_ADDR_PLL2_LF_CTRL1, + 0x3A); //PLL2 Loop filter [7:0] + AD9528_spiWriteByte(device, AD9528_ADDR_PLL2_LF_CTRL2, + 0x00); //PLL2 Loop filter [8] + AD9528_spiWriteByte(device, AD9528_ADDR_PLL2_RDIV, 0x01); //R divider + AD9528_spiWriteByte(device, AD9528_ADDR_PLL2_REPLICA_CHDIV, + (device->pll2Settings->totalNdiv / device->pll2Settings->rfDivider) + -1 ); //Replica channel divider: Ndivider = rfDivider * R divider + AD9528_spiWriteByte(device, AD9528_ADDR_PLL2_REPLICA_DIV_PHASE, + 0x00); //Replica Channel Divider phase + + /********************************************************************** + * Configure Output Distribution + ********************************************************************** + */ + for (i=0; i<14; i=i+1) { + AD9528_spiWriteByte(device, AD9528_ADDR_CH_OUT0_CTRL1 + j, + ((device->outputSettings->outSource[i] & 0x7) << 5) | + (device->outputSettings->outAnalogDelay[i] & 0x1F)); + AD9528_spiWriteByte(device, AD9528_ADDR_CH_OUT0_CTRL2 + j, + ((device->outputSettings->outBufferCtrl[i] & 0x3) << 6) | + (device->outputSettings->outDigitalDelay[i] & 0x3F)); + AD9528_spiWriteByte(device, AD9528_ADDR_CH_OUT0_CHDIV + j, + device->outputSettings->outChannelDiv[i]-1); + j = j+3; + } + + AD9528_spiWriteByte(device, AD9528_ADDR_OUTPUT_SYNC, 0x00); //Sync outputs + AD9528_spiWriteByte(device, AD9528_ADDR_MASK_SYNC1, 0x00); //Mask SYNC[7:0] + AD9528_spiWriteByte(device, AD9528_ADDR_MASK_SYNC2, 0x00); //Mask SYNC[13:8] + AD9528_spiWriteByte(device, AD9528_ADDR_EN_OUTPUT_PATH_SEL1, + 0x00); //Bypass SYSREF resample [6:0], bit0:Enable VCXO to feed output distrubution + AD9528_spiWriteByte(device, AD9528_ADDR_EN_OUTPUT_PATH_SEL2, + 0x00); //Bypass SYSREF resample [13:7] + + /********************************************************************** + * Configure SYSREF operation + ********************************************************************** + */ + AD9528_spiWriteByte(device, AD9528_ADDR_SYSERF_DIV_LSB, + device->sysrefSettings->sysrefDivide & 0xFF); //SYSREF divider [7:0] + AD9528_spiWriteByte(device, AD9528_ADDR_SYSERF_DIV_MSB, + (device->sysrefSettings->sysrefDivide >> 8) & 0xFF); //SYSREF divider [7:0] + + AD9528_spiWriteByte(device, AD9528_ADDR_SYSREF_CTRL3, + ((device->sysrefSettings->sysrefRequestMethod & 0x1) << 7) | + ((device->sysrefSettings->sysrefPinEdgeMode & 0x3) << 5) ); + + AD9528_spiWriteByte(device, AD9528_ADDR_SYSREF_CTRL4, + ((device->sysrefSettings->sysrefSource & 0x03) << 6) | + ((device->sysrefSettings->sysrefPatternMode & 0x3) << 4 ) | + ((device->sysrefSettings->sysrefNshotMode & 0x7) << 1) ); + + if(device->sysrefSettings->sysrefPinBufferMode == DISABLED) { + AD9528_spiWriteByte(device, AD9528_ADDR_SYSREF_CTRL5, + 0x04); //power down input buffer for external SYSREF + } else if(device->sysrefSettings->sysrefPinBufferMode == SINGLE_ENDED) { + AD9528_spiWriteByte(device, AD9528_ADDR_SYSREF_CTRL5, + 0x00); //enable positive singled ended input + } else if(device->sysrefSettings->sysrefPinBufferMode == NEG_SINGLE_ENDED) { + AD9528_spiWriteByte(device, AD9528_ADDR_SYSREF_CTRL5, + 0x02); //enable negative singled ended input + } else if(device->sysrefSettings->sysrefPinBufferMode == DIFFERENTIAL) { + AD9528_spiWriteByte(device, AD9528_ADDR_SYSREF_CTRL5, + 0x01); //enable differential input buffer + } else { + AD9528_spiWriteByte(device, AD9528_ADDR_SYSREF_CTRL5, + 0x04); //power down input buffer for external SYSREF + } + + /********************************************************************** + * Power down control + ********************************************************************** + */ + + if (device->pll1Settings->bypassPll1 > 0) { + AD9528_spiWriteByte(device, AD9528_ADDR_POWERDOWN_CTRL, + 0x14);// power up PLL2 and output distribution, power down PLL1 + } else { + AD9528_spiWriteByte(device, AD9528_ADDR_POWERDOWN_CTRL, + 0x10);// power up PLL1, PLL2 and output distribution + } + + AD9528_spiWriteByte(device, AD9528_ADDR_CH_POWERDOWN1, + device->outputSettings->outPowerDown & 0xFF); //power down out[7:0] + AD9528_spiWriteByte(device, AD9528_ADDR_CH_POWERDOWN2, + ((device->outputSettings->outPowerDown >> 8) & 0x3F)); //power down out[13:8] + AD9528_spiWriteByte(device, AD9528_ADDR_LDO_ENABLES1, + 0xFF); //LDO enable per output channel [7:0] + AD9528_spiWriteByte(device, AD9528_ADDR_LDO_ENABLES2, + 0xFF); //LDO enable per output channel [15:8] + AD9528_spiWriteByte(device, AD9528_ADDR_STATUS0_CTRL, + 0x07); //STATUS 0 outputs REFA present + AD9528_spiWriteByte(device, AD9528_ADDR_STATUS1_CTRL, + 0x01); //STATUS 1 outputs PLL1 and PLL2 locked + AD9528_spiWriteByte(device, AD9528_ADDR_STATUS_OE, + 0x0C);// Make Status0 and Status1 outputs after reset. + + AD9528_spiWriteByte(device, AD9528_ADDR_IO_UPDATE, + 0x01); //IO update to make all these settings valid in the 9528 + + AD9528_setTimeout_ms(1000); + + do { + AD9528_spiReadByte(device, AD9528_ADDR_STATUS_READBACK0, ®508); + if(AD9528_hasTimeoutExpired() > 0) { + return FAILURE; + } + } while((reg508 & 0x26) != 0x26); + + return SUCCESS; +} + + +/// Send a SPI message to request a SYSREF pulse or continuous SYSREF from the AD9528. +/*******************************************************************************//** + * Requests a SYSREF from the AD9528. It will use whatever settings for SYSREF + * that are current configured in the AD9528. This could be a single pulse, + * multiple pulses, or continuous pulses. + * Dependencies + * - device->spiSettings + * - device->sysrefSettings->sysrefPatternMode + * + * \param device is structure pointer to AD9528 clock device structure + * \param enableSYSREF If NSHOT SYSREF mode, this parameter is ignored. If PRBS/CONTINUOUS SYSREF mode, 1= enable SYSREF, 0= disable SYSREF. + * + * \return Returns enum ADI_ERR, 0=pass, >0 = fail + ***********************************************************************************/ +int32_t AD9528_requestSysref(ad9528Device_t *device, uint8_t enableSYSREF) +{ + uint8_t _enableSYSREF=0; + + if (device->sysrefSettings->sysrefPatternMode == NSHOT || enableSYSREF > 0) { + _enableSYSREF = 1; + } else { + _enableSYSREF = 0; + } + + AD9528_spiWriteField(device, AD9528_ADDR_SYSREF_CTRL4, _enableSYSREF, 0x01, + 0x00); //Set SPI SYSREF request bit + AD9528_spiWriteByte(device, AD9528_ADDR_IO_UPDATE, + 0x01); //IO update to make all these settings valid in the 9528 + + return SUCCESS; +} + +/// Allow changing the 9528 SYSREF frequency and pattern mode(CONTINUOUS, PRBS vs NSHOT mode) +/*******************************************************************************//** + * NOTE: this function will update the device structure with the parameter values passed + * into this function. The device->sysrefSettings->sysrefPatternMode, device->sysrefSettings->sysrefNshotMode, + * and device->sysrefSettings->sysrefDivide values will be updated in the device structure. + * + * Dependencies + * - device->spiSettings + * + * \param device is structure pointer to AD9528 clock device structure + * \param divideFromPll1Out Sets the SYSREF pulse frequency. SYSREF frequency = PLL1_VCXO frequency/divideFromPll1Out + * \param sysrefPatternMode Valid settings: NSHOT, CONTINUOUS, PRBS, STOP + * \param nShotPulses Valid settings: ONE_PULSE=0, TWO_PULSES=2, FOUR_PULSES=3, SIX_PULSES=4, EIGHT_PULSES=5 + * + * \return Returns enum ADI_ERR, 0=pass, >0 = fail + ***********************************************************************************/ +int32_t AD9528_setupSYSREF(ad9528Device_t *device, + uint16_t divideFromPll1Out, sysrefPatternMode_t sysrefPatternMode, + sysrefNshotMode_t nShotPulses) +{ + uint8_t reg403=0; + + device->sysrefSettings->sysrefPatternMode = sysrefPatternMode; + device->sysrefSettings->sysrefNshotMode = nShotPulses; + device->sysrefSettings->sysrefDivide = divideFromPll1Out >> + 1; //SYSREF frequency is (PLL1)VCXO frequency / 2 / device->sysrefSettings->sysrefDivide + + AD9528_spiReadByte(device, AD9528_ADDR_SYSREF_CTRL4, ®403); + + reg403 = reg403 & ~0x01; //clear bit 0 to stop a continuous sysref if it is on. + AD9528_spiWriteByte(device, AD9528_ADDR_SYSREF_CTRL4, reg403); + + reg403 = reg403 & ~0x3E; //clear bits for pattern mode and Nshot mode bitfields + reg403 = reg403 | ((sysrefPatternMode & 0x3) << 4) | ((nShotPulses & 0x7) << 1); + AD9528_spiWriteByte(device, AD9528_ADDR_SYSREF_CTRL4, + reg403); //update internal sysref pattern mode and Nshot mode (number of pulses) + + //SYSREF request bit x403[0] is left 0. The next call to AD9528_requestSysref will start the SYSREF + AD9528_spiWriteByte(device, AD9528_ADDR_IO_UPDATE, + 0x01); //IO update to make all these settings valid in the 9528 + + + return SUCCESS; +} + +int32_t AD9528_sysrefReq(ad9528Device_t *device, + ad9528SysrefReqMode_t mode) +{ + if (mode == SYSREF_CONT_ON) + gpio_direction_output(device->gpio_sysref_req, 1); + else if (mode == SYSREF_CONT_OFF) + gpio_direction_output(device->gpio_sysref_req, 0); + else if (mode == SYSREF_PULSE) { + gpio_direction_output(device->gpio_sysref_req, 1); + mdelay(1); + gpio_direction_output(device->gpio_sysref_req, 0); + } else + return FAILURE; + + return SUCCESS; +} + +/** + * \brief Free the allocated resources + */ +int32_t AD9528_remove(ad9528Device_t *device) +{ + int32_t status; + + status = gpio_remove(device->gpio_resetb); + status |= gpio_remove(device->gpio_sysref_req); + status |= spi_remove(device->spi_desc); + + return SUCCESS; +} diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/frequency/ad9528/ad9528.h b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/frequency/ad9528/ad9528.h new file mode 100644 index 0000000..9f89655 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/frequency/ad9528/ad9528.h @@ -0,0 +1,245 @@ +/** + * \file ad9528.h + * \brief Contains function declarations and ad9528Device_t structure typedef for ad9528.c + */ + +/** +* \page Disclaimer Legal Disclaimer +* Copyright 2015-2017 Analog Devices Inc. +* Released under the AD9371 API license. +* +*/ + +#ifndef _AD9528_H_ +#define _AD9528_H_ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ +#include +#include "delay.h" +#include "spi.h" +#include "gpio.h" + +/******************************************************************************/ +/********************** Macros and Constants Definitions **********************/ +/******************************************************************************/ + +/* AD9528 SPI Address defines */ +#define AD9528_ADDR_ADI_SPI_CONFIG_A 0x000 +#define AD9528_ADDR_ADI_SPI_CONFIG_B 0x001 +#define AD9528_ADDR_IO_UPDATE 0x00F + +#define AD9528_ADDR_REF_A_DIVIDER_LSB 0x100 +#define AD9528_ADDR_REF_A_DIVIDER_MSB 0x101 +#define AD9528_ADDR_REF_B_DIVIDER_LSB 0x102 +#define AD9528_ADDR_REF_B_DIVIDER_MSB 0x103 +#define AD9528_ADDR_PLL1_N_DIV_LSB 0x104 +#define AD9528_ADDR_PLL1_N_DIV_MSB 0x105 +#define AD9528_ADDR_PLL1_CHARGEPUMP 0x106 +#define AD9528_ADDR_PLL1_CP_CTRL2 0x107 +#define AD9528_ADDR_INPUT_RECEIVERS1 0x108 +#define AD9528_ADDR_INPUT_RECEIVERS2 0x109 +#define AD9528_ADDR_INPUT_RECEIVERS3 0x10A +#define AD9528_ADDR_PLL1_FASTLOCK 0x10B + +#define AD9528_ADDR_PLL2_CHARGEPUMP 0x200 +#define AD9528_ADDR_PLL2_N_DIV 0x201 +#define AD9528_ADDR_PLL2_CTRL 0x202 +#define AD9528_ADDR_PLL2_VCO_CTRL 0x203 +#define AD9528_ADDR_PLL2_VCO_DIV 0x204 +#define AD9528_ADDR_PLL2_LF_CTRL1 0x205 +#define AD9528_ADDR_PLL2_LF_CTRL2 0x206 +#define AD9528_ADDR_PLL2_RDIV 0x207 +#define AD9528_ADDR_PLL2_REPLICA_CHDIV 0x208 +#define AD9528_ADDR_PLL2_REPLICA_DIV_PHASE 0x209 + +#define AD9528_ADDR_CH_OUT0_CTRL1 0x300 +#define AD9528_ADDR_CH_OUT0_CTRL2 0x301 +#define AD9528_ADDR_CH_OUT0_CHDIV 0x302 +#define AD9528_ADDR_OUTPUT_SYNC 0x32A +#define AD9528_ADDR_MASK_SYNC1 0x32B +#define AD9528_ADDR_MASK_SYNC2 0x32C +#define AD9528_ADDR_EN_OUTPUT_PATH_SEL1 0x32D +#define AD9528_ADDR_EN_OUTPUT_PATH_SEL2 0x32E + +#define AD9528_ADDR_SYSERF_DIV_LSB 0x400 +#define AD9528_ADDR_SYSERF_DIV_MSB 0x401 +#define AD9528_ADDR_SYSREF_CTRL3 0x402 +#define AD9528_ADDR_SYSREF_CTRL4 0x403 +#define AD9528_ADDR_SYSREF_CTRL5 0x404 + +#define AD9528_ADDR_POWERDOWN_CTRL 0x500 +#define AD9528_ADDR_CH_POWERDOWN1 0x501 +#define AD9528_ADDR_CH_POWERDOWN2 0x502 +#define AD9528_ADDR_LDO_ENABLES1 0x503 +#define AD9528_ADDR_LDO_ENABLES2 0x504 +#define AD9528_ADDR_STATUS0_CTRL 0x505 +#define AD9528_ADDR_STATUS1_CTRL 0x506 +#define AD9528_ADDR_STATUS_OE 0x507 +#define AD9528_ADDR_STATUS_READBACK0 0x508 +#define AD9528_ADDR_STATUS_READBACK1 0x509 + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ + +///Enum to select what source outputs from each AD9528 output channel +typedef enum { + AD9528_CHANNEL_DIV = 0, PLL1_OUTPUT = 1, //VCXO frequency + SYSREF = 2, + INV_PLL1_OUTPUT = 5 //VCXO inverted +} ad9528outSourceSel_t; + +///Enum to select what output buffer standard is used for the clock outputs +typedef enum { + AD9528_LVDS = 0, AD9528_LVDS_BOOST = 1, AD9528_HSTL = 2 +} ad9528outBufferControl_t; + +///Enum to select the clock input buffer mode. +typedef enum { + DISABLED = 0, SINGLE_ENDED, NEG_SINGLE_ENDED, DIFFERENTIAL +} ad9528RefBuffer_t; + +/// Structure to hold AD9528 PLL1 settings +typedef struct { + uint32_t refA_Frequency_Hz; + uint16_t refA_Divider; + ad9528RefBuffer_t refA_bufferCtrl; + + uint32_t refB_Frequency_Hz; + uint16_t refB_Divider; + ad9528RefBuffer_t refB_bufferCtrl; + + uint32_t vcxo_Frequency_Hz; + ad9528RefBuffer_t vcxoBufferCtrl; + + uint16_t nDivider; + uint8_t bypassPll1; +} ad9528pll1Settings_t; + +/// Structure to hold AD9528 PLL2 settings +typedef struct { + uint8_t rfDivider; //VCO divider: Valid range (3,4,5) + uint8_t n2Divider; //PLL2 N2 Divider + uint8_t totalNdiv; //NDiv = 4*Bdiv + Adiv //Bdiv valid range (3 to 63), Adiv valid range (0-3) +} ad9528pll2Settings_t; + +/// Structure to hold AD9528 Output Clock settings +typedef struct { + uint16_t outPowerDown; //bit per output, if 1 power down that output. + ad9528outSourceSel_t + outSource[14]; //CHANNEL_DIV, PLL1_OUTPUT, SYSREF, INV_PLL1_OUTPUT + ad9528outBufferControl_t outBufferCtrl[14]; //LVDS, LVDS_BOOST, HSTL + uint8_t outAnalogDelay[14]; //5 bits + uint8_t outDigitalDelay[14]; //6 bits, 1/2 clock resolution @ channel div input frequency + uint8_t outChannelDiv[14]; //8 bit channel divider + uint32_t outFrequency_Hz[14]; //output clock frequency per clock output +} ad9528outputSettings_t; + +///Enum to select the SYSREF output source +typedef enum { + EXTERNAL = 0, EXT_RESAMPLED = 1, INTERNAL = 2 +} sysrefSourceSelection_t; + +///Enum to choose the SYSREF pattern mode. +typedef enum { + NSHOT = 0, CONTINUOUS = 1, PRBS = 2, STOP = 3 +} sysrefPatternMode_t; + +///Enum to select the SYSREF input pin mode. +typedef enum { + LEVEL_ACTIVE_HIGH = 0, LEVEL_ACTIVE_LOW = 1, RISING_EDGE = 2, FALLING_EDGE = 3 +} sysrefPinEdgeMode_t; + +///Enum to select the SYSREF output # of pulses for NSHOT mode. +typedef enum { + ONE_PULSE = 0, TWO_PULSES = 2, FOUR_PULSES = 3, SIX_PULSES = 4, EIGHT_PULSES = 5 +} sysrefNshotMode_t; + +//Enum to select how a SYSREF is requested. +typedef enum { + SPI = 0, PIN = 1 +} sysrefRequestMethod_t; + +/// Structure to hold AD9528 SYSREF output settings +typedef struct { + sysrefRequestMethod_t sysrefRequestMethod; + sysrefSourceSelection_t sysrefSource; + sysrefPinEdgeMode_t sysrefPinEdgeMode; + ad9528RefBuffer_t sysrefPinBufferMode; + sysrefPatternMode_t sysrefPatternMode; + sysrefNshotMode_t sysrefNshotMode; + uint16_t sysrefDivide; + +} ad9528sysrefSettings_t; + +/// Structure to hold AD9528 SPI settings +typedef struct { + uint8_t chipSelectIndex; ///< valid 1~8 + uint8_t writeBitPolarity; ///< the level of the write bit of a SPI write instruction word, value is inverted for SPI read operation + uint8_t longInstructionWord; ///< 1 = 16bit instruction word, 0 = 8bit instruction word + uint8_t MSBFirst; ///< 1 = MSBFirst, 0 = LSBFirst + uint8_t CPHA; ///< clock phase, sets which clock edge the data updates (valid 0 or 1) + uint8_t CPOL; ///< clock polarity 0 = clock starts low, 1 = clock starts high + uint8_t enSpiStreaming; ///< Not implemented. SW feature to improve SPI throughput. + uint8_t autoIncAddrUp; ///< Not implemented. For SPI Streaming, set address increment direction. 1= next addr = addr+1, 0:addr = addr-1 + uint8_t fourWireMode; ///< 1: Use 4-wire SPI, 0: 3-wire SPI (SDIO pin is bidirectional). NOTE: ADI's FPGA platform always uses 4-wire mode. + uint32_t spiClkFreq_Hz; ///< SPI Clk frequency in Hz (default 25000000), platform will use next lowest frequency that it's baud rate generator can create */ +} ad9528spiSettings_t; + +/// Structure to hold AD9528 settings +typedef struct { + struct gpio_desc *gpio_resetb; + struct gpio_desc *gpio_sysref_req; + struct spi_desc *spi_desc; + ad9528spiSettings_t *spiSettings; + ad9528pll1Settings_t *pll1Settings; + ad9528pll2Settings_t *pll2Settings; + ad9528outputSettings_t *outputSettings; + ad9528sysrefSettings_t *sysrefSettings; +} ad9528Device_t; + +typedef struct { + struct gpio_init_param *gpio_init_resetb; + struct gpio_init_param *gpio_init_sysref_req; + struct spi_init_param *spi_init; + ad9528spiSettings_t *spiSettings; + ad9528pll1Settings_t *pll1Settings; + ad9528pll2Settings_t *pll2Settings; + ad9528outputSettings_t *outputSettings; + ad9528sysrefSettings_t *sysrefSettings; +} ad9528Init_t; + +typedef enum { + SYSREF_CONT_ON, + SYSREF_CONT_OFF, + SYSREF_PULSE, +} ad9528SysrefReqMode_t; + +/******************************************************************************/ +/************************ Functions Declarations ******************************/ +/******************************************************************************/ + +//Helper function to setup the 9528 device data structure specifically for the ADI transceiver evaluation cards +int32_t AD9528_initDeviceDataStruct(ad9528Device_t *device, + uint32_t vcxoFrequency_Hz, uint32_t refAFrequency_Hz, + uint32_t outputDeviceClock_Hz); +int32_t AD9528_spiReadByte(ad9528Device_t *device, uint16_t addr, + uint8_t *readdata); + +//AD9528 API functions +int32_t AD9528_hasTimeoutExpired(); +int32_t AD9528_resetDevice(ad9528Device_t *device); +int32_t AD9528_init(ad9528Device_t **device, const ad9528Init_t *init_device); +int32_t AD9528_config(ad9528Device_t + *device); //writes all registers to desired values, leaves clock outputs off. +int32_t AD9528_setupSYSREF(ad9528Device_t *device, + uint16_t divideFromPll1Out, sysrefPatternMode_t sysrefPatternMode, + sysrefNshotMode_t nShotPulses); +int32_t AD9528_requestSysref(ad9528Device_t *device, uint8_t enableSYSREF); +int32_t AD9528_sysrefReq(ad9528Device_t *device, + ad9528SysrefReqMode_t mode); +int32_t AD9528_remove(ad9528Device_t *device); + +#endif diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/frequency/hmc7044/hmc7044.c b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/frequency/hmc7044/hmc7044.c new file mode 100644 index 0000000..711d18b --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/frequency/hmc7044/hmc7044.c @@ -0,0 +1,927 @@ +/***************************************************************************//** + * @file hmc7044.c + * @brief Implementation of HMC7044, HMC7043 Driver. + * @author DBogdan (dragos.bogdan@analog.com) +******************************************************************************** + * Copyright 2018-2020(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ +#include +#include +#include "hmc7044.h" +#include "../../../include/error.h" +#include "../../../include/util.h" + +/******************************************************************************/ +/********************** Macros and Constants Definitions **********************/ +/******************************************************************************/ +#define HMC7044_WRITE (0 << 15) +#define HMC7044_READ (1 << 15) +#define HMC7044_CNT(x) (((x) - 1) << 13) +#define HMC7044_ADDR(x) ((x) & 0xFFF) + +/* Global Control */ +#define HMC7044_REG_SOFT_RESET 0x0000 +#define HMC7044_SOFT_RESET BIT(0) + +#define HMC7044_REG_REQ_MODE_0 0x0001 +#define HMC7044_RESEED_REQ BIT(7) +#define HMC7044_HIGH_PERF_DISTRIB_PATH BIT(6) +#define HMC7044_HIGH_PERF_PLL_VCO BIT(5) +#define HMC7044_FORCE_HOLDOVER BIT(4) +#define HMC7044_MUTE_OUT_DIV BIT(3) +#define HMC7044_PULSE_GEN_REQ BIT(2) +#define HMC7044_RESTART_DIV_FSM BIT(1) +#define HMC7044_SLEEP_MODE BIT(0) + +#define HMC7044_REG_REQ_MODE_1 0x0002 +#define HMC7044_PLL2_AUTOTUNE_TRIG BIT(2) +#define HMC7044_SLIP_REQ BIT(1) + +#define HMC7044_REG_EN_CTRL_0 0x0003 +#define HMC7044_RF_RESEEDER_EN BIT(5) +#define HMC7044_VCO_SEL(x) (((x) & 0x3) << 3) +#define HMC7044_VCO_EXT 0 +#define HMC7044_VCO_HIGH 1 +#define HMC7044_VCO_LOW 2 +#define HMC7044_SYSREF_TIMER_EN BIT(2) +#define HMC7044_PLL2_EN BIT(1) +#define HMC7044_PLL1_EN BIT(0) + +#define HMC7044_REG_EN_CTRL_1 0x0004 +#define HMC7044_SEVEN_PAIRS(x) ((x) & 0x7f) + +#define HMC7044_REG_GLOB_MODE 0x0005 +#define HMC7044_REF_PATH_EN(x) ((x) & 0xf) +#define HMC7044_RFSYNC_EN BIT(4) +#define HMC7044_VCOIN_MODE_EN BIT(5) +#define HMC7044_SYNC_PIN_MODE(x) (((x) & 0x3) << 6) + +/* PLL1 */ +#define HMC7044_REG_CLKIN0_BUF_CTRL 0x000A +#define HMC7044_REG_CLKIN1_BUF_CTRL 0x000B +#define HMC7044_REG_CLKIN2_BUF_CTRL 0x000C +#define HMC7044_REG_CLKIN3_BUF_CTRL 0x000D +#define HMC7044_REG_OSCIN_BUF_CTRL 0x000E + +#define HMC7044_REG_PLL1_REF_PRIO_CTRL 0x0014 + +#define HMC7044_HIGH_Z_EN BIT(4) +#define HMC7044_LVPECL_EN BIT(3) +#define HMC7044_AC_COUPLING_EN BIT(2) +#define HMC7044_100_OHM_EN BIT(1) +#define HMC7044_BUF_EN BIT(0) + +#define HMC7044_REG_CLKIN_PRESCALER(x) (0x001C + (x)) +#define HMC7044_REG_OSCIN_PRESCALER 0x0020 + +#define HMC7044_REG_PLL1_R_LSB 0x0021 +#define HMC7044_R1_LSB(x) ((x) & 0xff) + +#define HMC7044_REG_PLL1_R_MSB 0x0022 +#define HMC7044_R1_MSB(x) (((x) & 0xff00) >> 8) + +#define HMC7044_REG_PLL1_N_LSB 0x0026 +#define HMC7044_N1_LSB(x) ((x) & 0xff) + +#define HMC7044_REG_PLL1_N_MSB 0x0027 +#define HMC7044_N1_MSB(x) (((x) & 0xff00) >> 8) + +#define HMC7044_REG_PLL1_LOCK_DETECT 0x0028 +#define HMC7044_LOCK_DETECT_SLIP BIT(5) +#define HMC7044_LOCK_DETECT_TIMER(x) ((x) & 0x1f) + +/* PLL2 */ +#define HMC7044_REG_PLL2_FREQ_DOUBLER 0x0032 +#define HMC7044_PLL2_FREQ_DOUBLER_DIS BIT(0) + +#define HMC7044_REG_PLL2_R_LSB 0x0033 +#define HMC7044_R2_LSB(x) ((x) & 0xff) + +#define HMC7044_REG_PLL2_R_MSB 0x0034 +#define HMC7044_R2_MSB(x) (((x) & 0xf00) >> 8) + +#define HMC7044_REG_PLL2_N_LSB 0x0035 +#define HMC7044_N2_LSB(x) ((x) & 0xff) + +#define HMC7044_REG_PLL2_N_MSB 0x0036 +#define HMC7044_N2_MSB(x) (((x) & 0xff00) >> 8) + +#define HMC7044_REG_OSCOUT_PATH 0x0039 +#define HMC7044_REG_OSCOUT_DRIVER_0 0x003A +#define HMC7044_REG_OSCOUT_DRIVER_1 0x003B + +/* GPIO/SDATA Control */ +#define HMC7044_REG_GPI_CTRL(x) (0x0046 + (x)) +#define HMC7044_REG_GPI_SEL(x) ((x) & 0xf) + +#define HMC7044_REG_GPO_CTRL(x) (0x0050 + (x)) +#define HMC7044_GPO_SEL(x) (((x) & 0x3f) << 2) +#define HMC7044_GPO_MODE BIT(1) +#define HMC7044_GPO_EN BIT(0) + +/* SYSREF/SYNC Control */ +#define HMC7044_REG_PULSE_GEN 0x005A +#define HMC7044_PULSE_GEN_MODE(x) ((x) & 0x7) + +#define HMC7044_REG_SYNC 0x005B +#define HMC7044_SYNC_RETIME BIT(2) +#define HMC7044_SYNC_THROUGH_PLL2 BIT(1) +#define HMC7044_SYNC_POLARITY BIT(0) + +#define HMC7044_REG_SYSREF_TIMER_LSB 0x005C +#define HMC7044_SYSREF_TIMER_LSB(x) ((x) & 0xff) + +#define HMC7044_REG_SYSREF_TIMER_MSB 0x005D +#define HMC7044_SYSREF_TIMER_MSB(x) (((x) & 0xf00) >> 8) + +#define HMC7044_CLK_INPUT_CTRL 0x0064 +#define HMC7044_LOW_FREQ_INPUT_MODE BIT(0) +#define HMC7044_DIV_2_INPUT_MODE BIT(1) + +/* Status and Alarm readback */ +#define HMC7044_REG_ALARM_READBACK 0x007D +#define HMC7044_REG_PLL1_STATUS 0x0082 + +#define HMC7044_PLL1_FSM_STATE(x) ((x) & 0x7) +#define HMC7044_PLL1_ACTIVE_CLKIN(x) (((x) >> 3) & 0x3) + +#define HMC7044_PLL2_LOCK_DETECT(x) ((x) & 0x1) +#define HMC7044_SYSREF_SYNC_STAT(x) ((x) & 0x2) +#define HMC7044_CLK_OUT_PH_STATUS(x) ((x) & 0x4) +#define HMC7044_PLL1_PLL2_LOCK_STAT(x) ((x) & 0x8) +#define HMC7044_SYNC_REQ_STATUS(x) ((x) & 0x10) + +/* Other Controls */ +#define HMC7044_REG_CLK_OUT_DRV_LOW_PW 0x009F +#define HMC7044_REG_CLK_OUT_DRV_HIGH_PW 0x00A0 +#define HMC7044_REG_PLL1_DELAY 0x00A5 +#define HMC7044_REG_PLL1_HOLDOVER 0x00A8 +#define HMC7044_REG_VTUNE_PRESET 0x00B0 + +/* Clock Distribution */ +#define HMC7044_REG_CH_OUT_CRTL_0(ch) (0x00C8 + 0xA * (ch)) +#define HMC7044_HI_PERF_MODE BIT(7) +#define HMC7044_SYNC_EN BIT(6) +#define HMC7044_CH_EN BIT(0) +#define HMC7044_START_UP_MODE_DYN_EN (BIT(3) | BIT(2)) + +#define HMC7044_REG_CH_OUT_CRTL_1(ch) (0x00C9 + 0xA * (ch)) +#define HMC7044_DIV_LSB(x) ((x) & 0xFF) + +#define HMC7044_REG_CH_OUT_CRTL_2(ch) (0x00CA + 0xA * (ch)) +#define HMC7044_DIV_MSB(x) (((x) >> 8) & 0xFF) + +#define HMC7044_REG_CH_OUT_CRTL_3(ch) (0x00CB + 0xA * (ch)) +#define HMC7044_REG_CH_OUT_CRTL_4(ch) (0x00CC + 0xA * (ch)) +#define HMC7044_REG_CH_OUT_CRTL_5(ch) (0x00CD + 0xA * (ch)) +#define HMC7044_REG_CH_OUT_CRTL_6(ch) (0x00CE + 0xA * (ch)) +#define HMC7044_REG_CH_OUT_CRTL_7(ch) (0x00CF + 0xA * (ch)) + +#define HMC7044_REG_CH_OUT_CRTL_8(ch) (0x00D0 + 0xA * (ch)) +#define HMC7044_DRIVER_MODE(x) (((x) & 0x3) << 3) +#define HMC7044_DRIVER_Z_MODE(x) (((x) & 0x3) << 0) +#define HMC7044_DYN_DRIVER_EN BIT(5) +#define HMC7044_FORCE_MUTE_EN BIT(7) + +#define HMC7044_NUM_CHAN 14 + +#define HMC7044_LOW_VCO_MIN 2150000 +#define HMC7044_LOW_VCO_MAX 2880000 +#define HMC7044_HIGH_VCO_MIN 2650000 +#define HMC7044_HIGH_VCO_MAX 3200000 + +#define HMC7044_RECOMM_LCM_MIN 30000 +#define HMC7044_RECOMM_LCM_MAX 70000 +#define HMC7044_RECOMM_FPD1 10000 + +#define HMC7044_R1_MAX 65535 +#define HMC7044_N1_MAX 65535 + +#define HMC7044_R2_MIN 1 +#define HMC7044_R2_MAX 4095 +#define HMC7044_N2_MIN 8 +#define HMC7044_N2_MAX 65535 + +#define HMC7044_OUT_DIV_MIN 1 +#define HMC7044_OUT_DIV_MAX 4094 + +/******************************************************************************/ +/************************** Functions Implementation **************************/ +/******************************************************************************/ + +/** + * SPI register write to device. + * @param dev - The device structure. + * @param reg - The register address. + * @param val - The register data. + * @return SUCCESS in case of success, negative error code otherwise. + */ +int32_t hmc7044_write(struct hmc7044_dev *dev, + uint16_t reg, + uint8_t val) +{ + uint8_t buf[3]; + uint16_t cmd; + + cmd = HMC7044_WRITE | HMC7044_CNT(1) | HMC7044_ADDR(reg); + buf[0] = cmd >> 8; + buf[1] = cmd & 0xFF; + buf[2] = val; + return spi_write_and_read_3wire(dev->spi_desc, buf, NULL, + ARRAY_SIZE(buf), 0); +} + +/** + * SPI register read from device. + * @param dev - The device structure. + * @param reg - The register address. + * @param val - The register data. + * @return SUCCESS in case of success, negative error code otherwise. + */ + +int32_t hmc7044_read(struct hmc7044_dev *dev, uint16_t reg, uint8_t *val) +{ + uint8_t wr_buf[2]; + uint8_t rd_data[1]; + uint16_t cmd; + int ret; + + cmd = HMC7044_READ | HMC7044_CNT(1) | HMC7044_ADDR(reg); + wr_buf[0] = cmd >> 8; + wr_buf[1] = cmd & 0xFF; + + ret = spi_write_and_read_3wire(dev->spi_desc, wr_buf, rd_data, + ARRAY_SIZE(wr_buf), ARRAY_SIZE(rd_data)); + if (ret != SUCCESS) + return ret; + + *val = rd_data[0]; + + return SUCCESS; +} + +/** + * Calculate the output channel divider. + * @param rate - The desired rate. + * @param parent_rate - The parent rate. + * @return The output divider. + */ +uint32_t hmc7044_calc_out_div(uint32_t rate, + uint32_t parent_rate) +{ + uint32_t div; + + div = DIV_ROUND_CLOSEST(parent_rate, rate); + + /* Supported odd divide ratios are 1, 3, and 5 */ + if ((div != 1) && (div != 3) && (div != 5) && (div % 2)) + div = DIV_ROUND_CLOSEST(parent_rate, rate * 2) * 2; + + div = clamp_t(unsigned int, + div, + HMC7044_OUT_DIV_MIN, + HMC7044_OUT_DIV_MAX); + + return div; +} + +/** + * Recalculate rate corresponding to a channel. + * @param dev - The device structure. + * @param chan_num - Channel number. + * @param rate - Channel rate. + * @return SUCCESS in case of success, negative error code otherwise. + */ +int32_t hmc7044_clk_recalc_rate(struct hmc7044_dev *dev, uint32_t chan_num, + uint64_t *rate) +{ + int i; + struct hmc7044_chan_spec *chan = NULL; + + /* Find the reqested channel number */ + for (i = 0; i < dev->num_channels; i++) { + if (dev->channels[i].num == chan_num) { + chan = &dev->channels[i]; + break; + } + } + if (chan == NULL ) + return FAILURE; + + *rate = dev->pll2_freq / chan->divider; + + return SUCCESS; +} + +/** + * Calculate closest possible rate + * @param dev - The device structure + * @param rate - The desired rate. + * @param rounded_rate - The closest possible rate of desired rate. + * @return SUCCESS in case of success, negative error code otherwise. + */ +int32_t hmc7044_clk_round_rate(struct hmc7044_dev *dev, uint32_t rate, + uint64_t *rounded_rate) +{ + uint32_t div = hmc7044_calc_out_div(rate, dev->pll2_freq); + + *rounded_rate = DIV_ROUND_CLOSEST(dev->pll2_freq, div); + + return SUCCESS; +} + +/** + * Set channel rate. + * @param dev - The device structure. + * @param chan_num - Channel number. + * @param rate - Channel rate. + * @return SUCCESS in case of success, negative error code otherwise. + */ +int32_t hmc7044_clk_set_rate(struct hmc7044_dev *dev, uint32_t chan_num, + uint64_t rate) +{ + uint32_t div; + int32_t ret; + int i; + struct hmc7044_chan_spec *chan = NULL; + + /* Find the reqested channel number */ + for (i = 0; i < dev->num_channels; i++) { + if (dev->channels[i].num == chan_num) { + chan = &dev->channels[i]; + break; + } + } + if (chan == NULL ) + return FAILURE; + + div = hmc7044_calc_out_div(rate, dev->pll2_freq); + chan->divider = div; + + ret = hmc7044_write(dev, HMC7044_REG_CH_OUT_CRTL_1(chan->num), + HMC7044_DIV_LSB(div)); + if(ret < 0) + return ret; + + return hmc7044_write(dev, HMC7044_REG_CH_OUT_CRTL_2(chan->num), + HMC7044_DIV_MSB(div)); +} + +/** + * Setup the device. + * @param dev - The device structure. + * @return SUCCESS in case of success, negative error code otherwise. + */ +static int32_t hmc7044_setup(struct hmc7044_dev *dev) +{ + struct hmc7044_chan_spec *chan; + bool high_vco_en; + bool pll2_freq_doubler_en; + uint32_t vcxo_freq, pll2_freq; + uint32_t clkin_freq[4]; + uint32_t lcm_freq; + uint32_t in_prescaler[5]; + uint32_t pll1_lock_detect; + uint32_t n1, r1; + uint32_t pfd1_freq; + uint32_t vco_limit; + uint32_t n2[2], r2[2]; + uint32_t i, ref_en = 0; + + vcxo_freq = dev->vcxo_freq / 1000; + pll2_freq = dev->pll2_freq / 1000; + + lcm_freq = vcxo_freq; + for (i = 0; i < ARRAY_SIZE(clkin_freq); i++) { + if (dev->clkin_freq_ccf[i]) + clkin_freq[i] = dev->clkin_freq_ccf[i] / 1000; + else + clkin_freq[i] = dev->clkin_freq[i] / 1000; + + if (clkin_freq[i]) { + lcm_freq = greatest_common_divisor(clkin_freq[i], lcm_freq); + ref_en |= BIT(i); + } + } + + while (lcm_freq > HMC7044_RECOMM_LCM_MAX) + lcm_freq /= 2; + + for (i = 0; i < ARRAY_SIZE(clkin_freq); i++) { + if (clkin_freq[i]) + in_prescaler[i] = clkin_freq[i] / lcm_freq; + else + in_prescaler[i] = 1; + } + in_prescaler[4] = vcxo_freq / lcm_freq; + + pll1_lock_detect = log_base_2((lcm_freq * 4000) / dev->pll1_loop_bw); + + /* fVCXO / N1 = fLCM / R1 */ + rational_best_approximation(vcxo_freq, lcm_freq, + HMC7044_N1_MAX, HMC7044_R1_MAX, + &n1, &r1); + + pfd1_freq = vcxo_freq / n1; + while ((pfd1_freq > HMC7044_RECOMM_FPD1) && + (n1 <= HMC7044_N1_MAX / 2) && + (r1 <= HMC7044_R1_MAX / 2)) { + pfd1_freq /= 2; + n1 *= 2; + r1 *= 2; + } + + dev->pll1_pfd = pfd1_freq; + + if (pll2_freq < HMC7044_LOW_VCO_MIN || + pll2_freq > HMC7044_HIGH_VCO_MAX) + return FAILURE; + + vco_limit = (HMC7044_LOW_VCO_MAX + HMC7044_HIGH_VCO_MIN) / 2; + if (pll2_freq >= vco_limit) + high_vco_en = true; + else + high_vco_en = false; + + /* fVCO / N2 = fVCXO * doubler / R2 */ + pll2_freq_doubler_en = true; + rational_best_approximation(pll2_freq, vcxo_freq * 2, + HMC7044_N2_MAX, HMC7044_R2_MAX, + &n2[0], &r2[0]); + + if (pll2_freq != vcxo_freq * n2[0] / r2[0]) { + rational_best_approximation(pll2_freq, vcxo_freq, + HMC7044_N2_MAX, HMC7044_R2_MAX, + &n2[1], &r2[1]); + + if (abs((int)pll2_freq - (int)(vcxo_freq * 2 * n2[0] / r2[0])) > + abs((int)pll2_freq - (int)(vcxo_freq * n2[1] / r2[1]))) { + n2[0] = n2[1]; + r2[0] = r2[1]; + pll2_freq_doubler_en = false; + } + } + + while ((n2[0] < HMC7044_N2_MIN) && (r2[0] <= HMC7044_R2_MAX / 2)) { + n2[0] *= 2; + r2[0] *= 2; + } + if (n2[0] < HMC7044_N2_MIN) + return -FAILURE; + + /* Resets all registers to default values */ + hmc7044_write(dev, HMC7044_REG_SOFT_RESET, HMC7044_SOFT_RESET); + mdelay(10); + hmc7044_write(dev, HMC7044_REG_SOFT_RESET, 0); + mdelay(10); + + /* Disable all channels */ + for (i = 0; i < HMC7044_NUM_CHAN; i++) + hmc7044_write(dev, HMC7044_REG_CH_OUT_CRTL_0(i), 0); + + /* Load the configuration updates (provided by Analog Devices) */ + hmc7044_write(dev, HMC7044_REG_CLK_OUT_DRV_LOW_PW, 0x4d); + hmc7044_write(dev, HMC7044_REG_CLK_OUT_DRV_HIGH_PW, 0xdf); + hmc7044_write(dev, HMC7044_REG_PLL1_DELAY, 0x06); + hmc7044_write(dev, HMC7044_REG_PLL1_HOLDOVER, 0x06); + hmc7044_write(dev, HMC7044_REG_VTUNE_PRESET, 0x04); + + uint8_t rd_back; + hmc7044_read(dev, HMC7044_REG_CLK_OUT_DRV_LOW_PW, &rd_back); + hmc7044_read(dev, HMC7044_REG_CLK_OUT_DRV_HIGH_PW, &rd_back); + hmc7044_read(dev, HMC7044_REG_PLL1_DELAY, &rd_back); + hmc7044_read(dev, HMC7044_REG_PLL1_HOLDOVER, &rd_back); + hmc7044_read(dev, HMC7044_REG_VTUNE_PRESET, &rd_back); + + hmc7044_write(dev, HMC7044_REG_GLOB_MODE, + HMC7044_SYNC_PIN_MODE(dev->sync_pin_mode) | + (dev->clkin0_rfsync_en ? HMC7044_RFSYNC_EN : 0) | + (dev->clkin1_vcoin_en ? HMC7044_VCOIN_MODE_EN : 0) | + HMC7044_REF_PATH_EN(ref_en)); + + /* Program PLL2 */ + + /* Select the VCO range */ + hmc7044_write(dev, HMC7044_REG_EN_CTRL_0, + (dev->rf_reseeder_en ? HMC7044_RF_RESEEDER_EN : 0) | + HMC7044_VCO_SEL(high_vco_en ? + HMC7044_VCO_HIGH : + HMC7044_VCO_LOW) | + HMC7044_SYSREF_TIMER_EN | HMC7044_PLL2_EN | + HMC7044_PLL1_EN); + + /* Program the dividers */ + hmc7044_write(dev, HMC7044_REG_PLL2_R_LSB, + HMC7044_R2_LSB(r2[0])); + hmc7044_write(dev, HMC7044_REG_PLL2_R_MSB, + HMC7044_R2_MSB(r2[0])); + hmc7044_write(dev, HMC7044_REG_PLL2_N_LSB, + HMC7044_N2_LSB(n2[0])); + hmc7044_write(dev, HMC7044_REG_PLL2_N_MSB, + HMC7044_N2_MSB(n2[0])); + + /* Program the reference doubler */ + hmc7044_write(dev, HMC7044_REG_PLL2_FREQ_DOUBLER, + pll2_freq_doubler_en ? 0 : HMC7044_PLL2_FREQ_DOUBLER_DIS); + + /* Program PLL1 */ + + /* Set the lock detect timer threshold */ + hmc7044_write(dev, HMC7044_REG_PLL1_LOCK_DETECT, + HMC7044_LOCK_DETECT_TIMER(pll1_lock_detect)); + + /* Set the LCM */ + for (i = 0; i < ARRAY_SIZE(clkin_freq); i++) { + hmc7044_write(dev, HMC7044_REG_CLKIN_PRESCALER(i), + in_prescaler[i]); + } + hmc7044_write(dev, HMC7044_REG_OSCIN_PRESCALER, + in_prescaler[4]); + + /* Program the dividers */ + hmc7044_write(dev, HMC7044_REG_PLL1_R_LSB, + HMC7044_R2_LSB(r1)); + hmc7044_write(dev, HMC7044_REG_PLL1_R_MSB, + HMC7044_R2_MSB(r1)); + hmc7044_write(dev, HMC7044_REG_PLL1_N_LSB, + HMC7044_N2_LSB(n1)); + hmc7044_write(dev, HMC7044_REG_PLL1_N_MSB, + HMC7044_N2_MSB(n1)); + + hmc7044_write(dev, HMC7044_REG_PLL1_REF_PRIO_CTRL, + dev->pll1_ref_prio_ctrl); + + /* Program the SYSREF timer */ + + /* Set the divide ratio */ + hmc7044_write(dev, HMC7044_REG_SYSREF_TIMER_LSB, + HMC7044_SYSREF_TIMER_LSB(dev->sysref_timer_div)); + hmc7044_write(dev, HMC7044_REG_SYSREF_TIMER_MSB, + HMC7044_SYSREF_TIMER_MSB(dev->sysref_timer_div)); + + /* Set the pulse generator mode configuration */ + hmc7044_write(dev, HMC7044_REG_PULSE_GEN, + HMC7044_PULSE_GEN_MODE(dev->pulse_gen_mode)); + + /* Enable the input buffers */ + hmc7044_write(dev, HMC7044_REG_CLKIN0_BUF_CTRL, + dev->in_buf_mode[0]); + hmc7044_write(dev, HMC7044_REG_CLKIN1_BUF_CTRL, + dev->in_buf_mode[1]); + hmc7044_write(dev, HMC7044_REG_CLKIN2_BUF_CTRL, + dev->in_buf_mode[2]); + hmc7044_write(dev, HMC7044_REG_CLKIN3_BUF_CTRL, + dev->in_buf_mode[3]); + hmc7044_write(dev, HMC7044_REG_OSCIN_BUF_CTRL, + dev->in_buf_mode[4]); + + /* Set GPIOs */ + for (i = 0; i < ARRAY_SIZE(dev->gpi_ctrl); i++) { + hmc7044_write(dev, HMC7044_REG_GPI_CTRL(i), + dev->gpi_ctrl[i]); + } + + for (i = 0; i < ARRAY_SIZE(dev->gpo_ctrl); i++) { + hmc7044_write(dev, HMC7044_REG_GPO_CTRL(i), + dev->gpo_ctrl[i]); + } + + mdelay(10); + + /* Program the output channels */ + for (i = 0; i < dev->num_channels; i++) { + chan = &dev->channels[i]; + if (chan->num >= HMC7044_NUM_CHAN || chan->disable) + continue; + + hmc7044_write(dev, HMC7044_REG_CH_OUT_CRTL_1(chan->num), + HMC7044_DIV_LSB(chan->divider)); + hmc7044_write(dev, HMC7044_REG_CH_OUT_CRTL_2(chan->num), + HMC7044_DIV_MSB(chan->divider)); + hmc7044_write(dev, HMC7044_REG_CH_OUT_CRTL_8(chan->num), + HMC7044_DRIVER_MODE(chan->driver_mode) | + HMC7044_DRIVER_Z_MODE(chan->driver_impedance) | + (chan->dynamic_driver_enable ? + HMC7044_DYN_DRIVER_EN : 0) | + (chan->force_mute_enable ? + HMC7044_FORCE_MUTE_EN : 0)); + + hmc7044_write(dev, HMC7044_REG_CH_OUT_CRTL_3(chan->num), + chan->fine_delay & 0x1F); + hmc7044_write(dev, HMC7044_REG_CH_OUT_CRTL_4(chan->num), + chan->coarse_delay & 0x1F); + hmc7044_write(dev, HMC7044_REG_CH_OUT_CRTL_7(chan->num), + chan->out_mux_mode & 0x3); + + hmc7044_write(dev, HMC7044_REG_CH_OUT_CRTL_0(chan->num), + (chan->start_up_mode_dynamic_enable ? + HMC7044_START_UP_MODE_DYN_EN : 0) | + (chan->output_control0_rb4_enable ? BIT(4) : 0) | + (chan->high_performance_mode_dis ? + 0 : HMC7044_HI_PERF_MODE) | HMC7044_SYNC_EN | + HMC7044_CH_EN); + } + mdelay(10); + + /* Do a restart to reset the system and initiate calibration */ + hmc7044_write(dev, HMC7044_REG_REQ_MODE_0, + HMC7044_RESTART_DIV_FSM); + mdelay(1); + hmc7044_write(dev, HMC7044_REG_REQ_MODE_0, + (dev->high_performance_mode_clock_dist_en ? + HMC7044_HIGH_PERF_DISTRIB_PATH : 0)); + mdelay(1); + + return SUCCESS; +} + +/** + * Setup the device. + * @param dev - The device structure. + * @return SUCCESS in case of success, negative error code otherwise. + */ +static int32_t hmc7043_setup(struct hmc7044_dev *dev) +{ + struct hmc7044_chan_spec *chan; + uint32_t i; + + if (dev->clkin_freq_ccf[0]) + dev->pll2_freq = dev->clkin_freq_ccf[0]; + else + dev->pll2_freq = dev->clkin_freq[0]; + + if (!dev->pll2_freq) { + printf("%s: Failed to get valid parent rate\n", __func__); + return FAILURE; + } + + /* Resets all registers to default values */ + hmc7044_write(dev, HMC7044_REG_SOFT_RESET, HMC7044_SOFT_RESET); + mdelay(10); + hmc7044_write(dev, HMC7044_REG_SOFT_RESET, 0); + mdelay(10); + + /* Load the configuration updates (provided by Analog Devices) */ + hmc7044_write(dev, HMC7044_REG_CLK_OUT_DRV_LOW_PW, 0x4d); + hmc7044_write(dev, HMC7044_REG_CLK_OUT_DRV_HIGH_PW, 0xdf); + + /* Disable all channels */ + for (i = 0; i < HMC7044_NUM_CHAN; i++) + hmc7044_write(dev, HMC7044_REG_CH_OUT_CRTL_0(i), 0); + + if (dev->pll2_freq < 1000000000U) + hmc7044_write(dev, HMC7044_CLK_INPUT_CTRL, + HMC7044_LOW_FREQ_INPUT_MODE); + + hmc7044_write(dev, HMC7044_REG_EN_CTRL_0, + (dev->rf_reseeder_en ? HMC7044_RF_RESEEDER_EN : 0) | + HMC7044_SYSREF_TIMER_EN); + + /* Program the SYSREF timer */ + + /* Set the divide ratio */ + hmc7044_write(dev, HMC7044_REG_SYSREF_TIMER_LSB, + HMC7044_SYSREF_TIMER_LSB(dev->sysref_timer_div)); + hmc7044_write(dev, HMC7044_REG_SYSREF_TIMER_MSB, + HMC7044_SYSREF_TIMER_MSB(dev->sysref_timer_div)); + + /* Set the pulse generator mode configuration */ + hmc7044_write(dev, HMC7044_REG_PULSE_GEN, + HMC7044_PULSE_GEN_MODE(dev->pulse_gen_mode)); + + /* Enable the input buffers */ + hmc7044_write(dev, HMC7044_REG_CLKIN0_BUF_CTRL, + dev->in_buf_mode[0]); + hmc7044_write(dev, HMC7044_REG_CLKIN1_BUF_CTRL, + dev->in_buf_mode[1]); + + /* Set GPIOs */ + hmc7044_write(dev, HMC7044_REG_GPI_CTRL(0), + dev->gpi_ctrl[0]); + + hmc7044_write(dev, HMC7044_REG_GPO_CTRL(0), + dev->gpo_ctrl[0]); + + /* Program the output channels */ + for (i = 0; i < dev->num_channels; i++) { + chan = &dev->channels[i]; + + if (chan->num >= HMC7044_NUM_CHAN || chan->disable) + continue; + + hmc7044_write(dev, HMC7044_REG_CH_OUT_CRTL_1(chan->num), + HMC7044_DIV_LSB(chan->divider)); + hmc7044_write(dev, HMC7044_REG_CH_OUT_CRTL_2(chan->num), + HMC7044_DIV_MSB(chan->divider)); + hmc7044_write(dev, HMC7044_REG_CH_OUT_CRTL_8(chan->num), + HMC7044_DRIVER_MODE(chan->driver_mode) | + HMC7044_DRIVER_Z_MODE(chan->driver_impedance) | + (chan->dynamic_driver_enable ? + HMC7044_DYN_DRIVER_EN : 0) | + (chan->force_mute_enable ? + HMC7044_FORCE_MUTE_EN : 0)); + + hmc7044_write(dev, HMC7044_REG_CH_OUT_CRTL_3(chan->num), + chan->fine_delay & 0x1F); + hmc7044_write(dev, HMC7044_REG_CH_OUT_CRTL_4(chan->num), + chan->coarse_delay & 0x1F); + hmc7044_write(dev, HMC7044_REG_CH_OUT_CRTL_7(chan->num), + chan->out_mux_mode & 0x3); + + hmc7044_write(dev, HMC7044_REG_CH_OUT_CRTL_0(chan->num), + (chan->start_up_mode_dynamic_enable ? + HMC7044_START_UP_MODE_DYN_EN : 0) | + (chan->output_control0_rb4_enable ? BIT(4) : 0) | + (chan->high_performance_mode_dis ? + 0 : HMC7044_HI_PERF_MODE) | HMC7044_SYNC_EN | + HMC7044_CH_EN); + } + mdelay(10); + + + /* Do a restart to reset the system and initiate calibration */ + hmc7044_write(dev, HMC7044_REG_REQ_MODE_0, + HMC7044_RESTART_DIV_FSM); + mdelay(1); + hmc7044_write(dev, HMC7044_REG_REQ_MODE_0, + (dev->high_performance_mode_clock_dist_en ? + HMC7044_HIGH_PERF_DISTRIB_PATH : 0)); + mdelay(1); + + return SUCCESS; +} + +/***************************************************************************//** + * @brief hmc7044_reg_init + *******************************************************************************/ +int32_t hmc7044_reg_init(struct hmc7044_dev **device, + const struct hmc7044_init_param *init_param) +{ + int ret = SUCCESS; + struct hmc7044_dev *dev; + + dev = (struct hmc7044_dev *)malloc(sizeof(*dev)); + if (!dev) + return FAILURE; + + /* SPI */ + ret = spi_init(&dev->spi_desc, init_param->spi_init); + + *device = dev; + + return ret; +} + +/** + * Initialize the device. + * @param device - The device structure. + * @param init_param - The structure that contains the device initial + * parameters. + * @return SUCCESS in case of success, negative error code otherwise. + */ +int32_t hmc7044_init(struct hmc7044_dev **device, + const struct hmc7044_init_param *init_param) +{ + struct hmc7044_dev *dev; + int32_t ret; + unsigned int i; + + dev = (struct hmc7044_dev *)malloc(sizeof(*dev)); + if (!dev) + return FAILURE; + + ret = spi_init(&dev->spi_desc, init_param->spi_init); + if (ret < 0) + return ret; + + dev->is_hmc7043 = init_param->is_hmc7043; + + dev->clkin_freq[0] = init_param->clkin_freq[0]; + dev->clkin_freq[1] = init_param->clkin_freq[1]; + dev->clkin_freq[2] = init_param->clkin_freq[2]; + dev->clkin_freq[3] = init_param->clkin_freq[3]; + + dev->clkin_freq_ccf[0] = init_param->clkin_freq_ccf[0]; + dev->clkin_freq_ccf[1] = init_param->clkin_freq_ccf[1]; + dev->clkin_freq_ccf[2] = init_param->clkin_freq_ccf[2]; + dev->clkin_freq_ccf[3] = init_param->clkin_freq_ccf[3]; + + dev->vcxo_freq = init_param->vcxo_freq; + dev->pll1_pfd = init_param->pll1_pfd; + dev->pll2_freq = init_param->pll2_freq; + dev->pll1_loop_bw = init_param->pll1_loop_bw; + + dev->sysref_timer_div = init_param->sysref_timer_div; + dev->pll1_ref_prio_ctrl = init_param->pll1_ref_prio_ctrl; + dev->clkin0_rfsync_en = init_param->clkin0_rfsync_en; + dev->clkin1_vcoin_en = init_param->clkin1_vcoin_en; + dev->high_performance_mode_clock_dist_en = + init_param->high_performance_mode_clock_dist_en; + dev->rf_reseeder_en = !init_param->rf_reseeder_disable; + dev->sync_pin_mode = init_param->sync_pin_mode; + dev->pulse_gen_mode = init_param->pulse_gen_mode; + + dev->in_buf_mode[0] = init_param->in_buf_mode[0]; + dev->in_buf_mode[1] = init_param->in_buf_mode[1]; + dev->in_buf_mode[2] = init_param->in_buf_mode[2]; + dev->in_buf_mode[3] = init_param->in_buf_mode[3]; + dev->in_buf_mode[4] = init_param->in_buf_mode[4]; + + dev->gpi_ctrl[0] = init_param->gpi_ctrl[0]; + dev->gpi_ctrl[1] = init_param->gpi_ctrl[1]; + dev->gpi_ctrl[2] = init_param->gpi_ctrl[2]; + dev->gpi_ctrl[3] = init_param->gpi_ctrl[3]; + + dev->gpo_ctrl[0] = init_param->gpo_ctrl[0]; + dev->gpo_ctrl[1] = init_param->gpo_ctrl[1]; + dev->gpo_ctrl[2] = init_param->gpo_ctrl[2]; + dev->gpo_ctrl[3] = init_param->gpo_ctrl[3]; + + dev->num_channels = init_param->num_channels; + dev->channels = (struct hmc7044_chan_spec *) + malloc(sizeof(*dev->channels) * dev->num_channels); + + for (i = 0; i < dev->num_channels; i++) { + dev->channels[i].num = init_param->channels[i].num; + dev->channels[i].disable = init_param->channels[i].disable; + dev->channels[i].divider = init_param->channels[i].divider; + dev->channels[i].driver_mode = + init_param->channels[i].driver_mode; + dev->channels[i].high_performance_mode_dis = + init_param->channels[i].high_performance_mode_dis; + dev->channels[i].start_up_mode_dynamic_enable = + init_param->channels[i].start_up_mode_dynamic_enable; + dev->channels[i].dynamic_driver_enable = + init_param->channels[i].dynamic_driver_enable; + dev->channels[i].output_control0_rb4_enable = + init_param->channels[i].output_control0_rb4_enable; + dev->channels[i].force_mute_enable = + init_param->channels[i].force_mute_enable; + dev->channels[i].driver_impedance = + init_param->channels[i].driver_impedance; + dev->channels[i].coarse_delay = + init_param->channels[i].coarse_delay; + dev->channels[i].fine_delay = + init_param->channels[i].fine_delay; + dev->channels[i].out_mux_mode = + init_param->channels[i].out_mux_mode; + } + + *device = dev; + + if (!dev->is_hmc7043) + return hmc7044_setup(dev); + else + return hmc7043_setup(dev); +} + +/** + * Remove the device - release resources. + * @param device - The device structure. + * @return SUCCESS in case of success, negative error code otherwise. + */ +int32_t hmc7044_remove(struct hmc7044_dev *device) +{ + int32_t ret; + + ret = spi_remove(device->spi_desc); + free(device->channels); + free(device); + + return ret; +} diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/frequency/hmc7044/hmc7044.h b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/frequency/hmc7044/hmc7044.h new file mode 100644 index 0000000..b3916c7 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/frequency/hmc7044/hmc7044.h @@ -0,0 +1,276 @@ +/***************************************************************************//** + * @file hmc7044.h + * @brief Header file of HMC7044, HMC7043 Driver. + * @author DBogdan (dragos.bogdan@analog.com) +******************************************************************************** + * Copyright 2018-2020(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ +#ifndef HMC7044_H_ +#define HMC7044_H_ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ +#include +#include +#include "delay.h" +#include "spi.h" + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ +// Enum to select SYNC pin configuration with respect to PLL2 (0x0005) +typedef enum +{ + SYNC_DISABLED = 0, + SYNC_MULTICHIP = 1, + SYNC_PULSE_GEN = 2, + SYNC_ALARM = 3 +} hmc7044SyncPinModeSelect_t; + +// Enum to select input buffer mode (0x000A, 0x000B, 0x000C, 0x000D, 0x000E) +typedef enum +{ + BUFFER_ENABLE = (1) << 0, + BUFFER_DISABLE = (0) << 0, + ENABLE_INTERNAL_TERM = (1) << 1, + ENABLE_AC_COUPLE = (1) << 2, + ENABLE_LVPECL = (1) << 3, + ENABLE_HIGH_Z = (1) << 4 +} hmc7044InputBufferMode_t; + +// Enum to select output driver mode (0x003A, 0x003B, 0x00D0, 0x00DA, 0x00E4, +// 0x00EE, 0x00F8, 0x0102, 0x010C, 0x0116, 0x0120, 0x012A, 0x0134, 0x013E, +// 0x0148, 0x0152) +typedef enum +{ + CML = 0, + LVPECL = 1, + LVDS = 2, + CMOS = 3 +} hmc7044DriverMode_t; + +// Enum to select the GPIx functionality. (0x0046, 0x0047, 0x0048, 0x0049) +typedef enum +{ + GPI_ENABLE = (1) << 0, + GPI_DISABLE = (0) << 0, + FORCE_PLL1_HOLDOVER = (0x01) << 1 | GPI_ENABLE, + SELECT_PLL1_REF_BIT1 = (0x02) << 1 | GPI_ENABLE, + SELECT_PLL1_REF_BIT2 = (0x03) << 1 | GPI_ENABLE, + CHIP_SLEEP_MODE = (0x04) << 1 | GPI_ENABLE, + MUTE_REQUSET = (0x05) << 1 | GPI_ENABLE, + SELECT_INTERNAL_VCO_TYPE = (0x06) << 1 | GPI_ENABLE, + SELECT_HI_PERF_MODE = (0x07) << 1 | GPI_ENABLE, + PULSE_GEN_REQUSET = (0x08) << 1 | GPI_ENABLE, + RESEED_REQUEST = (0x09) << 1 | GPI_ENABLE, + RESTART_REQUSET = (0x0A) << 1 | GPI_ENABLE, + FORCE_FANOUT_MODE = (0x0B) << 1 | GPI_ENABLE, + SLIP_REQUEST = (0x0D) << 1 | GPI_ENABLE, +} hmc7044GPIControl_t; + +// Enum to select the GPOx functionality. (0x0050, 0x0051, 0x0052, 0x0053) +typedef enum +{ + GPO_ENABLE = (1) << 0, + GPO_DISABLE = (0) << 0, + GPO_CMOS_MODE = (1) << 1, + GPO_OPEN_DRAIN_MODE = (0) << 1, + ALARM_SIGNAL = (0x00) << 3 | GPO_ENABLE, + SPI_SDATA = (0x01) << 3 | GPO_ENABLE, + CLKIN3_SIGNAL_LOSS = (0x02) << 3 | GPO_ENABLE, + CLKIN2_SIGNAL_LOSS = (0x03) << 3 | GPO_ENABLE, + CLKIN1_SIGNAL_LOSS = (0x04) << 3 | GPO_ENABLE, + CLKIN0_SIGNAL_LOSS = (0x05) << 3 | GPO_ENABLE, + PLL1_HOLDOVER_ENABLE = (0x06) << 3 | GPO_ENABLE, + PLL1_LOCK_DETECT = (0x07) << 3 | GPO_ENABLE, + PLL1_ACQUIRING_LOCK = (0x08) << 3 | GPO_ENABLE, + PLL1_NEAR_CLOCK_ACQ_STAT = (0x09) << 3 | GPO_ENABLE, + PLL2_LOCK_DETECT = (0x0A) << 3 | GPO_ENABLE, + PLL2_SYSREF_SYNC = (0x0B) << 3 | GPO_ENABLE, + CLOCK_OUTPUT_PHASE_STAT = (0x0C) << 3 | GPO_ENABLE, + PLL1_PLL2_LOCKED = (0x0D) << 3 | GPO_ENABLE, + SYNC_REQUSRT_STAT = (0x0E) << 3 | GPO_ENABLE, + PLL1_ACTIVE_CLKIN0 = (0x0F) << 3 | GPO_ENABLE, + PLL1_ACTIVE_CLKIN1 = (0x10) << 3 | GPO_ENABLE, + PLL1_HOLDOVER_IN_RANGE_STAT = (0x11) << 3 | GPO_ENABLE, + PLL1_HOLDOVER_IN_STAT = (0x12) << 3 | GPO_ENABLE, + PLL1_VCXO_STAT = (0x13) << 3 | GPO_ENABLE, + PLL1_ACTIVE_CLKINx_STAT = (0x14) << 3 | GPO_ENABLE, + PLL1_FSM_BIT0 = (0x15) << 3 | GPO_ENABLE, + PLL1_FSM_BIT1 = (0x16) << 3 | GPO_ENABLE, + PLL1_FSM_BIT2 = (0x17) << 3 | GPO_ENABLE, + PLL1_HOLDOVER_EXIT_PHASE_BIT0 = (0x18) << 3 | GPO_ENABLE, + PLL1_HOLDOVER_EXIT_PHASE_BIT1 = (0x19) << 3 | GPO_ENABLE, + CHANNEL_OUTPUT_FSM_BUSY = (0x1A) << 3 | GPO_ENABLE, + SYSREF_FSM_STAT_BIT0 = (0x1B) << 3 | GPO_ENABLE, + SYSREF_FSM_STAT_BIT1 = (0x1C) << 3 | GPO_ENABLE, + SYSREF_FSM_STAT_BIT2 = (0x1D) << 3 | GPO_ENABLE, + SYSREF_FSM_STAT_BIT3 = (0x1E) << 3 | GPO_ENABLE, + FORCE_LOGIC_1 = (0x1F) << 3 | GPO_ENABLE, + FORCE_LOGIC_0 = (0x20) << 3 | GPO_ENABLE, + PLL1_HOLDOVER_AVG_VALUE_BIT0 = (0x27) << 3 | GPO_ENABLE, + PLL1_HOLDOVER_AVG_VALUE_BIT1 = (0x28) << 3 | GPO_ENABLE, + PLL1_HOLDOVER_AVG_VALUE_BIT2 = (0x29) << 3 | GPO_ENABLE, + PLL1_HOLDOVER_AVG_VALUE_BIT3 = (0x2A) << 3 | GPO_ENABLE, + PLL1_HOLDOVER_CURR_VALUE_BIT0 = (0x2B) << 3 | GPO_ENABLE, + PLL1_HOLDOVER_CURR_VALUE_BIT1 = (0x2C) << 3 | GPO_ENABLE, + PLL1_HOLDOVER_CURR_VALUE_BIT2 = (0x2D) << 3 | GPO_ENABLE, + PLL1_HOLDOVER_CURR_VALUE_BIT3 = (0x2E) << 3 | GPO_ENABLE +} hmc7044GPOControl_t; + +// Enum to select output channel (0x00CF, 0x00D9, 0x00E3, 0x00ED, 0x00F7, +// 0x0101, 0x010B, 0x0115, 0x011F, 0x0129, 0x0133, 0x013D, 0x0147, 0x0151 +typedef enum +{ + CHANNEL_DIV = 0, + ANALOG_DELAY = 1, + OTHER_CHANNEL = 2, + VCO_CLOCK = 3 +} hmc7044OutputMuxSelect_t; + +// Enum to select output driver impedance selection for CML mode (0x00D0, +// 0x00DA, 0x00E4, 0x00EE, 0x00F8, 0x0102, 0x010C, 0x0116, 0x0120, 0x012A, +// 0x0134, 0x013E, 0x0148, 0x0152) +typedef enum +{ + INTERNAL_RES_DISABLE = 0, + INTERNAL_100OHM_PER_PIN = 1, +// INTERNAL_RES_RESERVED = 2, + INTERNAL_50OHM_PER_PIN = 3 +} hmc7044DriverImpedance_t; + +// Enum to select pulse generator mode (0x005A) +typedef enum +{ + PULSE_LEVEL_SENSITIVE = 0, + PULSE_ONE = 1, + PULSE_TWO = 2, + PULSE_FOUR = 3, + PULSE_EIGHT = 4, + PULSE_SIXTEEN = 5, +// PULSE_SIXTEEN = 6, + PULSE_CONTINOUS = 7 +} hmc7044SyncPulseGenControl_t; + +struct hmc7044_chan_spec { + unsigned int num; + bool disable; + bool high_performance_mode_dis; + bool start_up_mode_dynamic_enable; + bool dynamic_driver_enable; + bool output_control0_rb4_enable; + bool force_mute_enable; + unsigned int divider; + unsigned int coarse_delay; + unsigned int fine_delay; + hmc7044DriverMode_t driver_mode; + hmc7044DriverImpedance_t driver_impedance; + hmc7044OutputMuxSelect_t out_mux_mode; +}; + +struct hmc7044_config { + uint16_t addr; + uint8_t value; +}; + +struct hmc7044_dev { + struct spi_desc *spi_desc; + bool is_hmc7043; + uint32_t clkin_freq[4]; + uint32_t clkin_freq_ccf[4]; + uint32_t vcxo_freq; + uint32_t pll1_pfd; + uint32_t pll2_freq; + uint32_t pll1_loop_bw; + uint32_t sysref_timer_div; + unsigned int pll1_ref_prio_ctrl; + bool clkin0_rfsync_en; + bool clkin1_vcoin_en; + bool high_performance_mode_clock_dist_en; + bool rf_reseeder_en; + hmc7044SyncPinModeSelect_t sync_pin_mode; + hmc7044SyncPulseGenControl_t pulse_gen_mode; + uint32_t in_buf_mode[5]; + uint32_t gpi_ctrl[4]; + uint32_t gpo_ctrl[4]; + uint32_t num_channels; + struct hmc7044_chan_spec *channels; +}; + +struct hmc7044_init_param { + struct spi_init_param *spi_init; + bool is_hmc7043; + uint32_t clkin_freq[4]; + uint32_t clkin_freq_ccf[4]; + uint32_t vcxo_freq; + uint32_t pll1_pfd; + uint32_t pll2_freq; + uint32_t pll1_loop_bw; + uint32_t sysref_timer_div; + unsigned int pll1_ref_prio_ctrl; + bool clkin0_rfsync_en; + bool clkin1_vcoin_en; + bool high_performance_mode_clock_dist_en; + bool rf_reseeder_disable; + hmc7044SyncPinModeSelect_t sync_pin_mode; + hmc7044SyncPulseGenControl_t pulse_gen_mode; + uint32_t in_buf_mode[5]; + uint32_t gpi_ctrl[4]; + uint32_t gpo_ctrl[4]; + uint32_t num_channels; + struct hmc7044_chan_spec *channels; +}; + +/******************************************************************************/ +/************************ Functions Declarations ******************************/ +/******************************************************************************/ +/* Initialize the device. */ +int32_t hmc7044_reg_init(struct hmc7044_dev **device, + const struct hmc7044_init_param *init_param); +int32_t hmc7044_init(struct hmc7044_dev **device, + const struct hmc7044_init_param *init_param); +/* Remove the device. */ +int32_t hmc7044_remove(struct hmc7044_dev *device); +int32_t hmc7044_write(struct hmc7044_dev *dev, + uint16_t reg, uint8_t val); +int32_t hmc7044_read(struct hmc7044_dev *dev, uint16_t reg, uint8_t *val); +int32_t hmc7044_clk_recalc_rate(struct hmc7044_dev *dev, uint32_t chan_num, + uint64_t *rate); +int32_t hmc7044_clk_round_rate(struct hmc7044_dev *dev, uint32_t rate, + uint64_t *rounded_rate); +int32_t hmc7044_clk_set_rate(struct hmc7044_dev *dev, uint32_t chan_num, + uint64_t rate); + +#endif // HMC7044_H_ diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/frequency/lmk04828/lmk04828.c b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/frequency/lmk04828/lmk04828.c new file mode 100644 index 0000000..c76fb10 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/frequency/lmk04828/lmk04828.c @@ -0,0 +1,128 @@ +/***************************************************************************//** + * @file lmk04828.c + * @brief Implementation of AD9680 Driver. + * @author DBogdan (dragos.bogdan@analog.com) + ******************************************************************************** + * Copyright 2014-2016(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *******************************************************************************/ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ +#include +#include +#include "lmk04828.h" +#include "../../../include/error.h" + +/***************************************************************************//** + * @brief lmk04828_read + *******************************************************************************/ +int32_t lmk04828_read(struct lmk04828_dev *dev, + uint16_t reg_addr, + uint8_t *reg_data) +{ + uint8_t tx_buf[2]; + uint8_t rx_buf[1]; + int32_t ret; + + tx_buf[0] = 0x80 | (reg_addr >> 8); + tx_buf[1] = reg_addr & 0xFF; + + + ret = spi_write_and_read_3wire(dev->spi_desc, + tx_buf, rx_buf, 2, 1); + + *reg_data = rx_buf[0]; + + return ret; +} + +/***************************************************************************//** + * @brief lmk04828_write + *******************************************************************************/ +int32_t lmk04828_write(struct lmk04828_dev *dev, + uint16_t reg_addr, + uint8_t reg_data) +{ + uint8_t buf[3]; + + int32_t ret; + + buf[0] = reg_addr >> 8; + buf[1] = reg_addr & 0xFF; + buf[2] = reg_data; + + ret = spi_write_and_read_3wire(dev->spi_desc, + buf, NULL, 3, 0); + return ret; +} + +/***************************************************************************//** + * @brief lmk04828_init + *******************************************************************************/ +int32_t lmk04828_init(struct lmk04828_dev **device, + const struct lmk04828_init_param *init_param) +{ + int ret = SUCCESS; + struct lmk04828_dev *dev; + + dev = (struct lmk04828_dev *)malloc(sizeof(*dev)); + if (!dev) + return FAILURE; + + /* SPI */ + ret = spi_init(&dev->spi_desc, init_param->spi_init); + + *device = dev; + + return ret; +} + +/***************************************************************************//** + * @brief Free the resources allocated by lmk04828_setup(). + * + * @param dev - The device structure. + * + * @return SUCCESS in case of success, negative error code otherwise. +*******************************************************************************/ +int32_t lmk04828_remove(struct lmk04828_dev *dev) +{ + int32_t ret; + + ret = spi_remove(dev->spi_desc); + + free(dev); + + return ret; +} diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/frequency/lmk04828/lmk04828.h b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/frequency/lmk04828/lmk04828.h new file mode 100644 index 0000000..7c16aca --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/frequency/lmk04828/lmk04828.h @@ -0,0 +1,90 @@ +/***************************************************************************//** + * @file lmk04828.h + * @brief Header file of lmk04828 Driver. + * @author DBogdan (dragos.bogdan@analog.com) + ******************************************************************************** + * Copyright 2014-2016(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *******************************************************************************/ +#ifndef LMK04828_H_ +#define LMK04828_H_ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ +#include +#include "delay.h" +#include "spi.h" +#include "gpio.h" + +/******************************************************************************/ +/********************** Macros and Constants Definitions **********************/ +/******************************************************************************/ + + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ +struct lmk04828_dev { + /* SPI */ + struct spi_desc *spi_desc; +}; + +struct lmk04828_init_param { + /* SPI */ + struct spi_init_param *spi_init; +}; + +struct lmk04828_config { + uint16_t addr; + uint8_t value; +}; + +/******************************************************************************/ +/************************ Functions Declarations ******************************/ +/******************************************************************************/ + +int32_t lmk04828_read(struct lmk04828_dev *dev, + uint16_t reg_addr, + uint8_t *reg_data); + +int32_t lmk04828_write(struct lmk04828_dev *dev, + uint16_t reg_addr, + uint8_t reg_data); + +int32_t lmk04828_init(struct lmk04828_dev **device, + const struct lmk04828_init_param *init_param); + +int32_t lmk04828_remove(struct lmk04828_dev *dev); + +#endif diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/frequency/lmx2594/lmx2594.c b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/frequency/lmx2594/lmx2594.c new file mode 100644 index 0000000..b305b86 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/frequency/lmx2594/lmx2594.c @@ -0,0 +1,129 @@ +/***************************************************************************//** + * @file lmx2594.c + * @brief Implementation of AD9680 Driver. + * @author DBogdan (dragos.bogdan@analog.com) + ******************************************************************************** + * Copyright 2014-2016(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *******************************************************************************/ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ +#include "../lmx2594/lmx2594.h" + +#include +#include +#include "../../../include/error.h" + +/***************************************************************************//** + * @brief lmx2594_read + *******************************************************************************/ +int32_t lmx2594_read(struct lmx2594_dev *dev, + uint8_t reg_addr, + uint16_t *reg_data) +{ + uint8_t tx_buf[1]; + uint8_t rx_buf[2]; + int32_t ret; + + tx_buf[0] = 0x80 | reg_addr; + + + ret = spi_write_and_read_3wire(dev->spi_desc, + tx_buf, rx_buf, 1, 2); + + *reg_data = rx_buf[1]; + *reg_data |= ((uint16_t)rx_buf[0]) << 8; + + return ret; +} + +/***************************************************************************//** + * @brief lmx2594_write + *******************************************************************************/ +int32_t lmx2594_write(struct lmx2594_dev *dev, + uint8_t reg_addr, + uint16_t reg_data) +{ + uint8_t buf[3]; + + int32_t ret; + + buf[0] = reg_addr; + buf[1] = reg_data >> 8; + buf[2] = reg_data & 0xFF; + + ret = spi_write_and_read_3wire(dev->spi_desc, + buf, NULL, 3, 0); + return ret; +} + +/***************************************************************************//** + * @brief lmx2594_init + *******************************************************************************/ +int32_t lmx2594_init(struct lmx2594_dev **device, + const struct lmx2594_init_param *init_param) +{ + int ret = SUCCESS; + struct lmx2594_dev *dev; + + dev = (struct lmx2594_dev *)malloc(sizeof(*dev)); + if (!dev) + return FAILURE; + + /* SPI */ + ret = spi_init(&dev->spi_desc, init_param->spi_init); + + *device = dev; + + return ret; +} + +/***************************************************************************//** + * @brief Free the resources allocated by lmx2594_setup(). + * + * @param dev - The device structure. + * + * @return SUCCESS in case of success, negative error code otherwise. +*******************************************************************************/ +int32_t lmx2594_remove(struct lmx2594_dev *dev) +{ + int32_t ret; + + ret = spi_remove(dev->spi_desc); + + free(dev); + + return ret; +} diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/frequency/lmx2594/lmx2594.h b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/frequency/lmx2594/lmx2594.h new file mode 100644 index 0000000..eeb5caf --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/frequency/lmx2594/lmx2594.h @@ -0,0 +1,90 @@ +/***************************************************************************//** + * @file lmx2594.h + * @brief Header file of lmx2594 Driver. + * @author DBogdan (dragos.bogdan@analog.com) + ******************************************************************************** + * Copyright 2014-2016(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *******************************************************************************/ +#ifndef LMX2594_H_ +#define LMX2594_H_ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ +#include +#include "delay.h" +#include "spi.h" +#include "gpio.h" + +/******************************************************************************/ +/********************** Macros and Constants Definitions **********************/ +/******************************************************************************/ + + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ +struct lmx2594_dev { + /* SPI */ + struct spi_desc *spi_desc; +}; + +struct lmx2594_init_param { + /* SPI */ + struct spi_init_param *spi_init; +}; + +struct lmx2594_config { + uint8_t addr; + uint16_t value; +}; + +/******************************************************************************/ +/************************ Functions Declarations ******************************/ +/******************************************************************************/ + +int32_t lmx2594_read(struct lmx2594_dev *dev, + uint8_t reg_addr, + uint16_t *reg_data); + +int32_t lmx2594_write(struct lmx2594_dev *dev, + uint8_t reg_addr, + uint16_t reg_data); + +int32_t lmx2594_init(struct lmx2594_dev **device, + const struct lmx2594_init_param *init_param); + +int32_t lmx2594_remove(struct lmx2594_dev *dev); + +#endif diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/platform/xilinx_axi_io.c b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/platform/xilinx_axi_io.c new file mode 100644 index 0000000..b900a68 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/platform/xilinx_axi_io.c @@ -0,0 +1,79 @@ +/***************************************************************************//** + * @file xilinx/xilinx_axi_io.c + * @brief Implementation of Xilinx AXI IO. + * @author Antoniu Miclaus (antoniu.miclaus@analog.com) +******************************************************************************** + * Copyright 2019(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ + +#include +#include "error.h" +#include "axi_io.h" + +/******************************************************************************/ +/************************ Functions Definitions *******************************/ +/******************************************************************************/ + +/** + * @brief AXI IO Xilinx specific read function. + * @param base - Base address + * @param offset - Address offset + * @param data - variable where returned data is stored + * @return 0 in case of success, -1 otherwise. + */ +int32_t axi_io_read(uint32_t base, uint32_t offset, uint32_t *data) +{ + *data = Xil_In32(base + offset); + + return 0; +} + +/** + * @brief AXI IO Xilinx specific write function. + * @param base - Base address + * @param offset - Address offset + * @param data - data to be written. + * @return 0 in case of success, -1 otherwise. + */ +int32_t axi_io_write(uint32_t base, uint32_t offset, uint32_t data) +{ + Xil_Out32(base + offset, data); + + return 0; +} + diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/platform/xilinx_delay.c b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/platform/xilinx_delay.c new file mode 100644 index 0000000..d7e8640 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/platform/xilinx_delay.c @@ -0,0 +1,100 @@ +/***************************************************************************//** + * @file xilinx/xilinx_delay.c + * @brief Implementation of Xilinx Delay Functions. + * @author Antoniu Miclaus (antoniu.miclaus@analog.com) +******************************************************************************** + * Copyright 2019(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ + +#include "delay.h" +#include +#ifdef _XPARAMETERS_PS_H_ +#include "util.h" +#include "xtime_l.h" +#endif + +/******************************************************************************/ +/************************ Functions Definitions *******************************/ +/******************************************************************************/ + +/** + * @brief Generate microseconds delay. + * @param usecs - Delay in microseconds. + * @return None. + */ +void udelay(uint32_t usecs) +{ +#ifdef _XPARAMETERS_PS_H_ + usleep(usecs); +#else + usleep_MB(usecs); +#endif +} + +/** + * @brief Generate miliseconds delay. + * @param msecs - Delay in miliseconds. + * @return None. + */ +void mdelay(uint32_t msecs) +{ +#ifdef _XPARAMETERS_PS_H_ + usleep(msecs * 1000); +#else + usleep_MB(msecs * 1000); +#endif +} + +/** + * @brief Get current time. + * @return Current time structure from system start (seconds, microseconds). + */ +struct time get_time(void) +{ + struct time t = {0, 0}; +#ifdef _XPARAMETERS_PS_H_ + unsigned long long Xtime_Global; + uint32_t rem; + + XTime_GetTime(&Xtime_Global); + t.s = div_u64_rem(Xtime_Global, COUNTS_PER_SECOND, &rem); + t.us = div_u64((uint64_t)rem * 1000000, COUNTS_PER_SECOND); +#endif + + return t; +} diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/platform/xilinx_gpio.c b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/platform/xilinx_gpio.c new file mode 100644 index 0000000..abcab51 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/platform/xilinx_gpio.c @@ -0,0 +1,464 @@ +/***************************************************************************//** + * @file xilinx/xilinx_gpio.c + * @brief Implementation of Xilinx GPIO Generic Driver. + * @author Antoniu Miclaus (antoniu.miclaus@analog.com) +******************************************************************************** + * Copyright 2019(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ + +#include + +#include +#ifdef XPAR_XGPIO_NUM_INSTANCES +#include +#endif +#ifdef XPAR_XGPIOPS_NUM_INSTANCES +#include +#endif + +#include "error.h" +#include "gpio.h" +#include "xilinx_gpio.h" + +/******************************************************************************/ +/************************ Functions Definitions *******************************/ +/******************************************************************************/ + +/** + * @brief Prepare the GPIO decriptor. + * @param desc - The GPIO descriptor. + * @param param - The structure that contains the GPIO parameters. + * @return 0 in case of success, -1 otherwise. + */ +int32_t _gpio_init(struct gpio_desc *desc, + const struct gpio_init_param *param) +{ + int32_t ret; + struct xil_gpio_desc *xdesc; + struct xil_gpio_init_param *xinit; + + ret = -1; + + xdesc = desc->extra; + xinit = param->extra; + + xdesc->type = xinit->type; + desc->number = param->number; + + switch (xinit->type) { + case GPIO_PL: +#ifdef XGPIO_H + xdesc->instance = (XGpio *)malloc(sizeof(XGpio)); + if(!xdesc->instance) + goto pl_error; + + xdesc->config = XGpio_LookupConfig(xinit->device_id); + if(xdesc->config == NULL) + goto pl_error; + + ret = XGpio_CfgInitialize(xdesc->instance, + xdesc->config, + ((XGpio_Config*)xdesc->config) + ->BaseAddress); + if(ret < 0) + goto pl_error; + + break; +pl_error: + free(xdesc->instance); +#endif + goto error; + case GPIO_PS: +#ifdef XGPIOPS_H + xdesc->instance = (XGpioPs *)malloc(sizeof(XGpioPs)); + if(!xdesc->instance) + goto ps_error; + + xdesc->config = XGpioPs_LookupConfig(xinit->device_id); + if(xdesc->config == NULL) + goto ps_error; + + ret = XGpioPs_CfgInitialize(xdesc->instance, + xdesc->config, + ((XGpioPs_Config*)xdesc->config)->BaseAddr); + if(ret < 0) + goto ps_error; + break; +ps_error: + free(xdesc->instance); +#endif + goto error; +error: + default: + return -1; + } + + return 0; +} + +/** + * @brief Obtain the GPIO decriptor. + * @param desc - The GPIO descriptor. + * @param param - GPIO initialization parameters + * @return 0 in case of success, -1 otherwise. + */ +int32_t xil_gpio_get(struct gpio_desc **desc, + const struct gpio_init_param *param) +{ + struct gpio_desc *descriptor; + struct xil_gpio_desc *extra; + int32_t ret; + + descriptor = (struct gpio_desc *)malloc(sizeof(*descriptor)); + extra = (struct xil_gpio_desc*)malloc(sizeof(*extra)); + + if (!descriptor || !extra) + return -1; + + descriptor->extra = extra; + ret = _gpio_init(descriptor, param); + + if(ret != 0) + goto error; + + *desc = descriptor; + + return 0; +error: + free(extra); + free(descriptor); + + return -1; +} + +/** + * @brief Get the value of an optional GPIO. + * @param desc - The GPIO descriptor. + * @param param - GPIO Initialization parameters. + * @return 0 in case of success, -1 otherwise. + */ +int32_t xil_gpio_get_optional(struct gpio_desc **desc, + const struct gpio_init_param *param) +{ + if(param == NULL) { + *desc = NULL; + return 0; + } + + return xil_gpio_get(desc, param); +} + +/** + * @brief Free the resources allocated by gpio_get(). + * @param desc - The GPIO descriptor. + * @return 0 in case of success, -1 otherwise. + */ +int32_t xil_gpio_remove(struct gpio_desc *desc) +{ + if (desc != NULL) { + free(((struct xil_gpio_desc *)(desc->extra))->instance); + free(desc->extra); + free(desc); + } + + return 0; +} + +/** + * @brief Enable the input direction of the specified GPIO. + * @param desc - The GPIO descriptor. + * @return 0 in case of success, -1 otherwise. + */ +int32_t xil_gpio_direction_input(struct gpio_desc *desc) +{ + struct xil_gpio_desc *extra; +#ifdef XGPIO_H + uint8_t pin = desc->number; + uint32_t channel = 1; + uint32_t config = 0; +#endif + extra = desc->extra; + + switch (extra->type) { + case GPIO_PL: +#ifdef XGPIO_H + /* We assume that pin 32 is the first pin from channel 2 */ + if (pin >= 32) { + channel = 2; + pin -= 32; + } + + config = XGpio_GetDataDirection((XGpio *)extra->instance, + channel); + config |= (1 << pin); + XGpio_SetDataDirection((XGpio *)extra->instance, + channel, + config); +#endif + break; + case GPIO_PS: +#ifdef XGPIOPS_H + XGpioPs_SetDirectionPin(extra->instance, + desc->number, + GPIO_IN); +#endif + break; + default: + return -1; + } + + return 0; +} + +/** + * @brief Enable the output direction of the specified GPIO. + * @param desc - The GPIO descriptor. + * @param value - The value. + * Example: GPIO_HIGH + * GPIO_LOW + * @return 0 in case of success, -1 otherwise. + */ +int32_t xil_gpio_direction_output(struct gpio_desc *desc, + uint8_t value) +{ + struct xil_gpio_desc *extra; +#ifdef XGPIO_H + uint8_t pin = desc->number; + uint8_t channel; + uint32_t reg_val; +#endif + extra = desc->extra; + + switch (extra->type) { + case GPIO_PL: +#ifdef XGPIO_H + if (pin >= 32) { + channel = 2; + pin -= 32; + } else + channel = 1; + + reg_val = XGpio_GetDataDirection(extra->instance, + channel); + reg_val &= ~(1 << pin); + XGpio_SetDataDirection(extra->instance, + channel, + reg_val); + reg_val = XGpio_DiscreteRead(extra->instance, + channel); + if(value) + reg_val |= (1 << pin); + else + reg_val &= ~(1 << pin); + XGpio_DiscreteWrite(extra->instance, + channel, + reg_val); +#endif + break; + case GPIO_PS: +#ifdef XGPIOPS_H + XGpioPs_SetDirectionPin(extra->instance, + desc->number, + GPIO_OUT); + XGpioPs_SetOutputEnablePin(extra->instance, + desc->number, + GPIO_OUT); + XGpioPs_WritePin(extra->instance, + desc->number, + value); +#endif + break; + default: + return -1; + } + + return 0; +} + +/** + * @brief Get the direction of the specified GPIO. + * @param desc - The GPIO descriptor. + * @param direction - The direction. + * Example: GPIO_OUT + * GPIO_IN + * @return 0 in case of success, -1 otherwise. + */ +int32_t xil_gpio_get_direction(struct gpio_desc *desc, + uint8_t *direction) +{ + if (!desc) + return -1; + + struct xil_gpio_desc *extra; + uint8_t pin = desc->number; + +#ifdef XGPIO_H + uint8_t channel; +#endif + extra = desc->extra; + + switch (extra->type) { + case GPIO_PL: +#ifdef XGPIO_H + if (pin >= 32) { + channel = 2; + pin -= 32; + } else + channel = 1; + *direction = ((XGpio_GetDataDirection(extra->instance, + channel) >> pin) & 0x1) ^ 0x1; +#endif + break; + case GPIO_PS: +#ifdef XGPIOPS_H + *direction = XGpioPs_GetDirectionPin(extra->instance, pin); +#endif + break; + default: + return -1; + } + + return 0; +} + +/** + * @brief Set the value of the specified GPIO. + * @param desc - The GPIO descriptor. + * @param value - The value. + * Example: GPIO_HIGH + * GPIO_LOW + * @return 0 in case of success, -1 otherwise. + */ +int32_t xil_gpio_set_value(struct gpio_desc *desc, + uint8_t value) +{ + struct xil_gpio_desc *extra; +#ifdef XGPIO_H + uint8_t pin = desc->number; + uint8_t channel; + uint32_t reg_val; +#endif + extra = desc->extra; + + switch (extra->type) { + case GPIO_PL: +#ifdef XGPIO_H + if (pin >= 32) { + channel = 2; + pin -= 32; + } else + channel = 1; + + reg_val = XGpio_DiscreteRead(extra->instance, channel); + if(value) + reg_val |= (1 << pin); + else + reg_val &= ~(1 << pin); + XGpio_DiscreteWrite(extra->instance, channel, reg_val); +#endif + break; + case GPIO_PS: +#ifdef XGPIOPS_H + XGpioPs_WritePin(extra->instance, desc->number, value); +#endif + break; + default: + return -1; + } + + return 0; +} + +/** + * @brief Get the value of the specified GPIO. + * @param desc - The GPIO descriptor. + * @param value - The value. + * Example: GPIO_HIGH + * GPIO_LOW + * @return 0 in case of success, -1 otherwise. + */ +int32_t xil_gpio_get_value(struct gpio_desc *desc, + uint8_t *value) +{ + if (!desc) + return -1; + + struct xil_gpio_desc *extra; + uint8_t pin = desc->number; + +#ifdef XGPIO_H + uint8_t channel; +#endif + extra = desc->extra; + + switch (extra->type) { + case GPIO_PL: +#ifdef XGPIO_H + if (pin >= 32) { + channel = 2; + pin -= 32; + } else + channel = 1; + *value = (XGpio_DiscreteRead(extra->instance, channel) >> pin) & 0x01; +#endif + break; + case GPIO_PS: +#ifdef XGPIOPS_H + *value = XGpioPs_ReadPin(extra->instance, pin); +#endif + break; + default: + return -1; + } + + return 0; +} + +/** + * @brief Xilinx platform specific GPIO platform ops structure + */ +const struct gpio_platform_ops xil_gpio_ops = { + .gpio_ops_get = &xil_gpio_get, + .gpio_ops_get_optional = &xil_gpio_get_optional, + .gpio_ops_remove = &xil_gpio_remove, + .gpio_ops_direction_input = &xil_gpio_direction_input, + .gpio_ops_direction_output = &xil_gpio_direction_output, + .gpio_ops_get_direction = &xil_gpio_get_direction, + .gpio_ops_set_value = &xil_gpio_set_value, + .gpio_ops_get_value = &xil_gpio_get_value, +}; diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/platform/xilinx_gpio.h b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/platform/xilinx_gpio.h new file mode 100644 index 0000000..2cf61e6 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/platform/xilinx_gpio.h @@ -0,0 +1,95 @@ +/******************************************************************************* + * @file xilinx/xilinx_gpio.h + * @brief Header containing extra types used in the gpio driver + * @author scuciurean (sergiu.cuciurean@analog.com) +******************************************************************************** + * Copyright 2019(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +#ifndef XILINX_GPIO_H_ +#define XILINX_GPIO_H_ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ + +#include +#include + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ + +/** + * @enum xil_gpio_type + * @brief Xilinx platform architecture sections + */ +enum xil_gpio_type { + /** Programmable Logic */ + GPIO_PL, + /** Processing System */ + GPIO_PS +}; + +/** + * @struct xil_gpio_init_param + * @brief Structure holding the initialization parameters for Xilinx platform + * specific GPIO parameters. + */ +struct xil_gpio_init_param { + /** Xilinx architecture */ + enum xil_gpio_type type; + /** Device ID */ + uint32_t device_id; +}; + +/** + * @struct xil_gpio_desc + * @brief Xilinx platform specific GPIO descriptor + */ +struct xil_gpio_desc { + /** Xilinx architecture */ + enum xil_gpio_type type; + /** Xilinx GPIO configuration */ + void *config; + /** Xilinx GPIO Instance */ + void *instance; +}; + +/** + * @brief Xilinx platform specific gpio platform ops structure + */ +extern const struct gpio_platform_ops xil_gpio_ops; + +#endif diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/platform/xilinx_gpio_irq.c b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/platform/xilinx_gpio_irq.c new file mode 100644 index 0000000..f210f84 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/platform/xilinx_gpio_irq.c @@ -0,0 +1,360 @@ +/***************************************************************************//** + * @file xilinx/xilinx_gpio_irq.c + * @brief Implementation of Xilinx GPIO IRQ Generic Driver. + * @author Porumb Andrei (andrei.porumb@analog.com) +******************************************************************************** + * Copyright 2021(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ + +#include +#include "xparameters.h" +#include "error.h" +#include "xilinx_gpio_irq.h" +#include "util.h" +#include "list.h" +#include "irq.h" + +/******************************************************************************/ +/************************ Functions Definitions *******************************/ +/******************************************************************************/ + +/** + * @brief Comparing function used by list. + * @param desc_a - Compared item + * @param desc_b - Reference item + * @return - 0 if items match + */ +static int32_t call_cmp(struct xil_callback_desc *desc_a, + struct xil_callback_desc *desc_b) +{ + return desc_a->pin_nb - desc_b->pin_nb; +} + +/** + * @brief Function called when GPIO IRQ occurs. + * @param param - GPIO IRQ desc's extra field + * @return - None. + */ +static void xil_gpio_irq_handler(struct xil_gpio_irq_desc *param) +{ + int32_t status = 0; + int32_t pin_nb; + struct xil_callback_desc *callback_desc; + + status = iterator_move_to_idx(param->it, 0); + while(!status) { + iterator_read(param->it, &callback_desc); + status = iterator_move(param->it, 1); + if(XGpioPs_IntrGetStatusPin(¶m->my_Gpio, callback_desc->pin_nb)) + callback_desc->triggered = true; + } + + status = iterator_move_to_idx(param->it, 0); + while(!status) { + iterator_read(param->it, &callback_desc); + status = iterator_move(param->it, 1); + if(callback_desc->triggered == true) { + callback_desc->triggered = false; + XGpioPs_IntrDisablePin(¶m->my_Gpio, callback_desc->pin_nb); + XGpioPs_IntrClearPin(¶m->my_Gpio, callback_desc->pin_nb); + callback_desc->callback.legacy_callback(callback_desc->callback.ctx, 0U, NULL); + if(callback_desc->enabled) + XGpioPs_IntrEnablePin(¶m->my_Gpio, callback_desc->pin_nb); + } + } +} + +/** + * @brief Disable specific GPIO IRQ pin. + * @param desc - The GPIO IRQ controller descriptor. + * @param irq_id - Pin number. + * @return 0 in case of success, -1 otherwise. + */ +int32_t xil_gpio_irq_disable(struct irq_ctrl_desc *desc, uint32_t irq_id) +{ + int32_t status; + struct xil_gpio_irq_desc *extra; + struct xil_callback_desc *callback_desc; + + extra = desc->extra; + + status = iterator_move_to_idx(extra->it, 0); + while(!status) { + iterator_read(extra->it, &callback_desc); + status = iterator_move(extra->it, 1); + if(callback_desc->pin_nb == irq_id) { + callback_desc->enabled = false; + break; + } + } + + XGpioPs_IntrDisablePin(&extra->my_Gpio, irq_id); + + return 0; +} + +/** + * @brief Initialize the GPIO IRQ controller. + * @param desc - The GPIO IRQ controller descriptor. + * @param param - The GPIO IRQ controller initial parameters. + * irq_ctrl_id from irq_init_param is the interrupt id for the parent controller + * @return 0 in case of success, -1 otherwise. + */ +int32_t xil_gpio_irq_ctrl_init(struct irq_ctrl_desc **desc, + const struct irq_init_param *param) +{ + int32_t i; + int32_t status; + struct irq_ctrl_desc *ldesc; + static XGpioPs_Config *GPIO_Config; + struct xil_gpio_irq_desc *xil_desc; + struct xil_gpio_irq_init_param *xil_ip; + struct callback_desc callback; + + xil_desc = (struct xil_gpio_irq_desc *)calloc(1, sizeof(*xil_desc)); + if(!xil_desc) + return -ENOMEM; + + ldesc = (struct irq_ctrl_desc *)calloc(1, sizeof(*ldesc)); + if(!ldesc) { + free(xil_desc); + return -ENOMEM; + } + + xil_ip = param->extra; + GPIO_Config = XGpioPs_LookupConfig(xil_ip->gpio_device_id); + status = XGpioPs_CfgInitialize(&xil_desc->my_Gpio, GPIO_Config, + GPIO_Config->BaseAddr); + if(status) + goto error_desc; + + ldesc->extra = xil_desc; + xil_desc->parent_desc = xil_ip->parent_desc; + + status = list_init(&xil_desc->callback_list, LIST_DEFAULT, + call_cmp); + if(status) + goto error_list; + + status = iterator_init(&xil_desc->it, xil_desc->callback_list, 0); + if(status) { + iterator_remove(xil_desc->it); + goto error_list; + } + + ldesc->irq_ctrl_id = param->irq_ctrl_id; + status = irq_trigger_level_set(xil_desc->parent_desc, ldesc->irq_ctrl_id, + IRQ_EDGE_RISING); + if(status) + goto error_op; + + status = irq_enable(xil_desc->parent_desc, ldesc->irq_ctrl_id); + if(status) + goto error_op; + + callback.legacy_callback = &xil_gpio_irq_handler; + callback.ctx = ldesc->extra; + status = irq_register_callback(xil_desc->parent_desc, ldesc->irq_ctrl_id, + &callback); + if(status) + goto error_op; + + *desc = ldesc; + + return 0; + +error_op: + iterator_remove(xil_desc->it); +error_list: + list_remove(xil_desc->callback_list); +error_desc: + free(xil_desc); + free(ldesc); + return status; +} + +/** + * @brief Set GPIO interrupt trigger level. + * @param desc - The GPIO IRQ controller descriptor. + * @param irq_id - Pin number. + * @param trig - New trigger level for the GPIO interrupt. + * @return 0 in case of success, -1 otherwise. + */ +int32_t xil_gpio_irq_trigger_level_set(struct irq_ctrl_desc *desc, + uint32_t irq_id, + enum irq_trig_level trig) +{ + static const int32_t trig_level[5] = {XGPIOPS_IRQ_TYPE_LEVEL_LOW, + XGPIOPS_IRQ_TYPE_LEVEL_HIGH, + XGPIOPS_IRQ_TYPE_EDGE_FALLING, + XGPIOPS_IRQ_TYPE_EDGE_RISING, + XGPIOPS_IRQ_TYPE_EDGE_BOTH + }; + struct xil_gpio_irq_desc *extra; + + extra = desc->extra; + XGpioPs_SetIntrTypePin(&extra->my_Gpio, irq_id, trig_level[trig]); + + return 0; +} + +/** + * @brief Register pin specific GPIO interrupt. + * @param desc - The GPIO IRQ controller descriptor. + * @param irq_id - Pin number. + * @param callback_desc - Callback. + * @return 0 in case of success, -1 otherwise. + */ +int32_t xil_gpio_irq_register_callback(struct irq_ctrl_desc *desc, + uint32_t irq_id, + struct callback_desc *callback_desc) +{ + struct xil_callback_desc *dev_callback; + struct xil_gpio_irq_desc *extra; + + dev_callback = (struct xil_callback_desc *)calloc(1, + sizeof(*dev_callback)); + if(!dev_callback) + return -1; + + dev_callback->pin_nb = irq_id; + dev_callback->callback.legacy_callback = callback_desc->legacy_callback; + dev_callback->callback.ctx = callback_desc->ctx; + dev_callback->triggered = false; + + extra = desc->extra; + XGpioPs_SetDirectionPin(&extra->my_Gpio, irq_id, 0); + list_add_last(extra->callback_list, dev_callback); + + return 0; +} + +/** + * @brief Unregister pin specific GPIO interrupt. + * @param desc - The GPIO IRQ controller descriptor. + * @param irq_id - Pin number. + * @param cb - Callback descriptor. + * @return 0 in case of success, -1 otherwise. + */ +int32_t xil_gpio_irq_unregister_callback(struct irq_ctrl_desc *desc, + uint32_t irq_id, struct callback_desc *cb) +{ + int32_t status; + struct xil_gpio_irq_desc *extra; + struct xil_callback_desc *dev_callback; + struct xil_callback_desc search_callback; + + extra = desc->extra; + search_callback.pin_nb = irq_id; + status = list_get_find(extra->callback_list, &dev_callback, + &search_callback); + if(status) + return -ENXIO; + + free(dev_callback); + + return 0; +} + +/** + * @brief Enable specific GPIO IRQ pin. + * @param desc - The GPIO IRQ controller descriptor. + * @param irq_id - Pin number. + * @return 0 in case of success, -1 otherwise. + */ +int32_t xil_gpio_irq_enable(struct irq_ctrl_desc *desc, uint32_t irq_id) +{ + int32_t status; + struct xil_gpio_irq_desc *extra; + struct xil_callback_desc *callback_desc; + + extra = desc->extra; + + status = iterator_move_to_idx(extra->it, 0); + while(!status) { + iterator_read(extra->it, &callback_desc); + status = iterator_move(extra->it, 1); + if(callback_desc->pin_nb == irq_id) { + callback_desc->enabled = true; + XGpioPs_IntrClearPin(&extra->my_Gpio, irq_id); + break; + } + } + + XGpioPs_IntrEnablePin(&extra->my_Gpio, irq_id); + + return 0; +} + +/** + * @brief Remove the GPIO IRQ controller. + * @param desc - The GPIO IRQ controller descriptor. + * @return 0 in case of success, -1 otherwise. + */ +int32_t xil_gpio_irq_ctrl_remove(struct irq_ctrl_desc *desc) +{ + struct xil_gpio_irq_desc *extra; + struct xil_callback_desc *callback_desc; + + if (!desc) + return -EINVAL; + + extra = desc->extra; + while (0 == list_get_first(extra->callback_list, &callback_desc)) + free(callback_desc); + + iterator_remove(extra->it); + list_remove(extra->callback_list); + free(extra); + free(desc); + + return 0; +} + +/** + * @brief Xilinx platform specific GPIO IRQ platform ops structure + */ +const struct irq_platform_ops xil_gpio_irq_ops = { + .init = &xil_gpio_irq_ctrl_init, + .enable = &xil_gpio_irq_enable, + .disable = &xil_gpio_irq_disable, + .trigger_level_set = &xil_gpio_irq_trigger_level_set, + .register_callback = &xil_gpio_irq_register_callback, + .unregister_callback = xil_gpio_irq_unregister_callback, + .remove = &xil_gpio_irq_ctrl_remove +}; diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/platform/xilinx_gpio_irq.h b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/platform/xilinx_gpio_irq.h new file mode 100644 index 0000000..7c1e3f3 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/platform/xilinx_gpio_irq.h @@ -0,0 +1,92 @@ +/***************************************************************************//** + * @file xilinx_gpio_irq.h + * @brief Implementation of Xilinx GPIO IRQ Generic Driver. + * @author Porumb Andrei (andrei.porumb@analog.com) +******************************************************************************** + * Copyright 2021(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +#ifndef XILINX_GPIO_IRQ_H_ +#define XILINX_GPIO_IRQ_H_ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ + +#include "stdbool.h" +#include "list.h" +#include "xgpiops.h" +#include "irq.h" + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ +/** + * @struct xil_callback_desc + * @brief Structure holding callback parameters for each pin + */ +struct xil_callback_desc { + int32_t pin_nb; + struct callback_desc callback; + bool triggered; + bool enabled; +}; + +/** + * @struct xil_gpio_irq_init_param + * @brief Structure holding the initialization parameters for Xilinx platform + * specific GPIO IRQ parameters. + */ +struct xil_gpio_irq_init_param { + struct irq_ctrl_desc *parent_desc; + int32_t gpio_device_id; +}; + +/** + * @struct xil_gpio_irq_desc + * @brief Xilinx platform specific GPIO IRQ descriptor + */ +struct xil_gpio_irq_desc { + struct irq_ctrl_desc *parent_desc; + XGpioPs my_Gpio; + struct list_desc *callback_list; + struct iterator *it; +}; + +/** + * @brief Xilinx specific GPIO IRQ platform ops structure + */ +extern const struct irq_platform_ops xil_gpio_irq_ops; + +#endif diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/platform/xilinx_i2c.c b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/platform/xilinx_i2c.c new file mode 100644 index 0000000..bfd7d99 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/platform/xilinx_i2c.c @@ -0,0 +1,514 @@ +/***************************************************************************//** + * @file xilinx/xilinx_i2c.c + * @brief Implementation of Xilinx I2C Generic Driver. + * @author Antoniu Miclaus (antoniu.miclaus@analog.com) +******************************************************************************** + * Copyright 2019(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ + +#include + +#include +#ifdef XPAR_XIIC_NUM_INSTANCES +#include +#endif +#ifdef XPAR_XIICPS_NUM_INSTANCES +#include +#endif + +#include "error.h" +#include "i2c.h" +#include "xilinx_i2c.h" +#include "list.h" + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ + +static struct list_desc *pl_list = NULL; +static struct iterator *pl_it = NULL; + +#ifdef XIICPS_H +static struct list_desc *ps_list = NULL; +static struct iterator *ps_it = NULL; +#endif /* XIICPS_H */ + +/** + * @struct inst_table_item + * @brief Table item for I2C cores already started. + */ +struct inst_table_item { + /** Instance the BSP driver uses for this core. */ + void *instance; + /** Core ID in BSP. */ + uint32_t device_id; + /** Number of ADI driver instances running on this core. */ + uint32_t inst_no; +}; + +#ifdef XPAR_XIICPS_NUM_INSTANCES +/** Save the current state of the bitrate to not change it each time */ +static uint32_t ps_last_bitrate = 0; +#endif + +/** + * @brief Xilinx platform specific I2C platform ops structure + */ +const struct i2c_platform_ops xil_i2c_ops = { + .i2c_ops_init = &xil_i2c_init, + .i2c_ops_write = &xil_i2c_write, + .i2c_ops_read = &xil_i2c_read, + .i2c_ops_remove = &xil_i2c_remove +}; + +/******************************************************************************/ +/************************ Functions Definitions *******************************/ +/******************************************************************************/ + +/** + * @brief Compare two I2C cores by ID. + * @param el1 - First I2C core to compare. + * @param el2 - Second I2C core to compare. + * @return \ref 0 if the two cores have the same ID, + * \ref difference between the first and the second IDs otherwise. + */ +static int32_t xil_i2c_cmp(void *el1, void *el2) +{ + struct inst_table_item *sel1 = el1, *sel2 = el2; + + return (sel1->device_id - sel2->device_id); +} + +/** + * @brief Configure slave address and bitrate if needed + * @param desc - Descriptor of the I2C device + * @return 0 in case of success, -1 otherwise. + */ +static int32_t xil_i2c_set_transmission_config(struct i2c_desc *desc) +{ + struct xil_i2c_desc *xil_i2c_desc = desc->extra; +#ifdef XIICPS_H + int32_t ret; +#endif + + switch (xil_i2c_desc->type) { + case IIC_PL: +#ifdef XIIC_H + break; +#endif + return -1; + case IIC_PS: +#ifdef XIICPS_H + if (desc->max_speed_hz != ps_last_bitrate) { + ret = XIicPs_SetSClk(xil_i2c_desc->instance, desc->max_speed_hz); + if (ret != XST_SUCCESS) + return -1; + ps_last_bitrate = desc->max_speed_hz; + } + break; +#endif + return -1; + default: + + return -1; + } + + return 0; +} + +/** + * @brief Initialize the I2C communication peripheral. + * @param desc - The I2C descriptor. + * @param param - The structure that contains the I2C parameters. + * @return 0 in case of success, -1 otherwise. + */ +int32_t xil_i2c_init(struct i2c_desc **desc, + const struct i2c_init_param *param) +{ + int32_t ret; + struct i2c_desc *idesc; + struct xil_i2c_desc *xdesc; + struct xil_i2c_init_param *xinit; + + idesc = (struct i2c_desc *)malloc(sizeof(*idesc)); + xdesc = (struct xil_i2c_desc *)malloc(sizeof(*xdesc)); + + if(!idesc || !xdesc) + goto error; + + idesc->max_speed_hz = param->max_speed_hz; + idesc->slave_address = param->slave_address; + xinit = param->extra; + + idesc->extra = xdesc; + xdesc->type = xinit->type; + xdesc->device_id = xinit->device_id; + switch (xinit->type) { + case IIC_PL: +#ifdef XIIC_H + ; /** Intentional empty statement */ + struct inst_table_item tab_check_pl; + struct inst_table_item *temp_el_pl; + + if (!pl_list) + list_init(&pl_list, LIST_DEFAULT, xil_i2c_cmp); + if (!pl_it) + iterator_init(&pl_it, pl_list, true); + + tab_check_pl.device_id = xdesc->device_id; + + if (!IS_ERR_VALUE(list_read_find(pl_list, (void **)&temp_el_pl, + &tab_check_pl))) { + xdesc->instance = temp_el_pl->instance; + temp_el_pl->inst_no++; + break; + } + + xdesc->instance = (XIic *)malloc(sizeof(XIic)); + if(!xdesc->instance) + goto pl_error; + + xdesc->config = XIic_LookupConfig(xinit->device_id); + if(xdesc->config == NULL) + goto pl_error; + + ret = XIic_CfgInitialize(xdesc->instance, + xdesc->config, + ((XIic_Config*)xdesc->config) + ->BaseAddress); + if(ret != 0) + goto pl_error; + + ret = XIic_Start(xdesc->instance); + if(ret != 0) + goto pl_error; + + ret = XIic_SetAddress(xdesc->instance, + XII_ADDR_TO_SEND_TYPE, + param->slave_address); + if(ret != 0) + goto pl_error; + + ret = XIic_SelfTest(xdesc->instance); + if(ret < 0) + goto pl_error; + + ret = XIic_SetGpOutput(xdesc->instance, 1); + if(ret < 0) + goto pl_error; + + temp_el_pl = (struct inst_table_item*)calloc(1, sizeof(*temp_el_pl)); + temp_el_pl->device_id = xinit->device_id; + temp_el_pl->inst_no = 1; + temp_el_pl->instance = xdesc->instance; + pl_list->push(pl_list, temp_el_pl); + + break; +pl_error: + free(xdesc->instance); +#endif + goto error; + case IIC_PS: +#ifdef XIICPS_H + ; /** Intentional empty statement */ + struct inst_table_item tab_check_ps; + struct inst_table_item *temp_el_ps; + + if (!pl_list) + list_init(&ps_list, LIST_DEFAULT, xil_i2c_cmp); + if (!pl_it) + iterator_init(&ps_it, ps_list, true); + + tab_check_ps.device_id = xdesc->device_id; + + if (!IS_ERR_VALUE(list_read_find(ps_list, + (void **)&temp_el_ps, + &tab_check_ps))) { + xdesc->instance = temp_el_ps->instance; + temp_el_ps->inst_no++; + break; + } + + xdesc->instance = (XIicPs *)malloc(sizeof(XIicPs)); + if(!xdesc->instance) + goto ps_error; + + xdesc->config = XIicPs_LookupConfig(xinit->device_id); + if(xdesc->config == NULL) + goto ps_error; + + ret = XIicPs_CfgInitialize(xdesc->instance, + xdesc->config, + ((XIicPs_Config*)xdesc->config) + ->BaseAddress); + if(ret != 0) + goto ps_error; + + XIicPs_SetSClk(xdesc->instance, param->max_speed_hz); + + temp_el_ps = (struct inst_table_item*)calloc(1, sizeof(*temp_el_ps)); + temp_el_ps->device_id = xinit->device_id; + temp_el_ps->inst_no = 1; + temp_el_ps->instance = xdesc->instance; + ps_list->push(ps_list, temp_el_ps); + + break; +ps_error: + free(xdesc->instance); +#endif + goto error; + + default: + goto error; + break; + } + + *desc = idesc; + + return 0; + +error: + free(idesc); + free(xdesc); + + return -1; +} + +/** + * @brief Free the resources allocated by i2c_init(). + * @param desc - The I2C descriptor. + * @return 0 in case of success, -1 otherwise. + */ +int32_t xil_i2c_remove(struct i2c_desc *desc) +{ + struct xil_i2c_desc *xdesc; + int32_t ret; + + xdesc = desc->extra; + + switch (xdesc->type) { + case IIC_PL: +#ifdef XIIC_H + ; /** Intentional empty statement */ + struct inst_table_item tab_check_pl; + struct inst_table_item *temp_el_pl; + tab_check_pl.device_id = xdesc->device_id; + ret = iterator_find(pl_it, &tab_check_pl); + if (ret != 0) + goto error; + iterator_read(pl_it, (void **)&temp_el_pl); + temp_el_pl->inst_no--; + if (temp_el_pl->inst_no != 0) + break; + + ret = XIic_Stop(((XIic *)xdesc->instance)); + + if(ret != 0) + goto error; + + /** Remove list element */ + iterator_get(pl_it, (void **)&temp_el_pl); + free(temp_el_pl); + break; +#endif + goto error; + case IIC_PS: +#ifdef XIICPS_H + ; /** Intentional empty statement */ + struct inst_table_item tab_check_ps; + struct inst_table_item *temp_el_ps; + tab_check_ps.device_id = xdesc->device_id; + ret = iterator_find(ps_it, &tab_check_ps); + if (ret != 0) + goto error; + iterator_read(ps_it, (void **)&temp_el_ps); + temp_el_ps->inst_no--; + if (temp_el_ps->inst_no != 0) + break; + + /** Remove list element */ + iterator_get(ps_it, (void **)&temp_el_ps); + free(temp_el_ps); + break; +#endif + /* Intended fallthrough */ +error: + default: + + return -1; + } + + free(desc->extra); + free(desc); + + return 0; +} + +/** + * @brief Write data to a slave device. + * @param desc - The I2C descriptor. + * @param data - Buffer that stores the transmission data. + * @param bytes_number - Number of bytes to write. + * @param stop_bit - Stop condition control. + * Example: 0 - A stop condition will not be generated; + * 1 - A stop condition will be generated. + * @return 0 in case of success, -1 otherwise. + */ +int32_t xil_i2c_write(struct i2c_desc *desc, + uint8_t *data, + uint8_t bytes_number, + uint8_t stop_bit) +{ + struct xil_i2c_desc *xdesc; + int32_t ret; + + xdesc = desc->extra; + + switch (xdesc->type) { + case IIC_PL: +#ifdef XIIC_H + ret = xil_i2c_set_transmission_config(desc); + if (ret != 0) + return -1; + + XIic_Send(((XIic*)xdesc->instance)->BaseAddress, + desc->slave_address, + data, + bytes_number, + stop_bit ? XIIC_STOP : XIIC_REPEATED_START); + break; +#endif + goto error; + case IIC_PS: +#ifdef XIICPS_H + ret = xil_i2c_set_transmission_config(desc); + if (ret != 0) + return -1; + + ret = XIicPs_SetOptions(xdesc->instance, + stop_bit ? 0 : XIICPS_REP_START_OPTION); + if(ret != 0) + goto error; + + XIicPs_MasterSend(xdesc->instance, + data, + bytes_number, + desc->slave_address); + if(ret != 0) + goto error; + + break; +#endif + /* Intended fallthrough */ +error: + default: + + return -1; + } + + return 0; +} + +/** + * @brief Read data from a slave device. + * @param desc - The I2C descriptor. + * @param data - Buffer that will store the received data. + * @param bytes_number - Number of bytes to read. + * @param stop_bit - Stop condition control. + * Example: 0 - A stop condition will not be generated; + * 1 - A stop condition will be generated. + * @return 0 in case of success, -1 otherwise. + */ +int32_t xil_i2c_read(struct i2c_desc *desc, + uint8_t *data, + uint8_t bytes_number, + uint8_t stop_bit) +{ + struct xil_i2c_desc *xdesc; + int32_t ret; + + xdesc = desc->extra; + + switch (xdesc->type) { + case IIC_PL: +#ifdef XIIC_H + ret = xil_i2c_set_transmission_config(desc); + if (ret != 0) + return -1; + + ret = XIic_Recv(((XIic*)xdesc->instance)->BaseAddress, + desc->slave_address, + data, + bytes_number, + stop_bit ? XIIC_STOP : XIIC_REPEATED_START); + if(ret != bytes_number) + goto error; + + break; +#endif + goto error; + case IIC_PS: +#ifdef XIICPS_H + ret = xil_i2c_set_transmission_config(desc); + if (ret != 0) + return -1; + + ret = XIicPs_SetOptions(xdesc->instance, + stop_bit ? 0 : XIICPS_REP_START_OPTION); + if(ret != 0) + goto error; + + XIicPs_MasterRecv(xdesc->instance, + data, + bytes_number, + desc->slave_address); + if(ret != 0) + goto error; + + break; +#endif + /* Intended fallthrough */ +error: + default: + return -1; + + break; + } + + return 0; +} diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/platform/xilinx_i2c.h b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/platform/xilinx_i2c.h new file mode 100644 index 0000000..250db84 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/platform/xilinx_i2c.h @@ -0,0 +1,115 @@ +/******************************************************************************* + * @file xilinx/xilinx_i2c.h + * @brief Header containing types used in the i2c driver. + * @author scuciurean (sergiu.cuciurean@analog.com) +******************************************************************************** + * Copyright 2019(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +#ifndef XILINX_I2C_H_ +#define XILINX_I2C_H_ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ + +#include + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ + +/** + * @enum xil_i2c_type + * @brief Xilinx platform architecture sections + */ +enum xil_i2c_type { + /** Programmable Logic */ + IIC_PL, + /** Processing System */ + IIC_PS +}; + +/** + * @struct xil_i2c_init + * @brief Structure holding the initialization parameters for Xilinx platform + * specific I2C parameters. + */ +struct xil_i2c_init_param { + /** Xilinx architecture */ + enum xil_i2c_type type; + /** Device ID */ + uint32_t device_id; +}; + +/** + * @struct xil_i2c_desc + * @brief Xilinx platform specific I2C descriptor + */ +struct xil_i2c_desc { + /** Xilinx architecture */ + enum xil_i2c_type type; + /** Device ID */ + uint32_t device_id; + /** Xilinx I2C configuration */ + void *config; + /** Xilinx I2C Instance */ + void *instance; +}; + +/** + * @brief Xilinx platform specific i2c platform ops structure + */ +extern const struct i2c_platform_ops xil_i2c_ops; + +/******************************************************************************/ +/************************ Functions Declarations ******************************/ +/******************************************************************************/ + +/* Initialize the I2C communication peripheral. */ +int32_t xil_i2c_init(struct i2c_desc **desc, + const struct i2c_init_param *param); + +/* Free the resources allocated by i2c_init(). */ +int32_t xil_i2c_remove(struct i2c_desc *desc); + +/* I2C Write data */ +int32_t xil_i2c_write(struct i2c_desc *desc, uint8_t *data, + uint8_t bytes_number, uint8_t stop_bit); + +/* I2C Read data. */ +int32_t xil_i2c_read(struct i2c_desc *desc, uint8_t *data, + uint8_t bytes_number, uint8_t stop_bit); + +#endif // XILINX_I2C_H_ diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/platform/xilinx_irq.c b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/platform/xilinx_irq.c new file mode 100644 index 0000000..02f965c --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/platform/xilinx_irq.c @@ -0,0 +1,433 @@ +/***************************************************************************//** + * @file xilinx/xilinx_irq.c + * @brief Implementation of Xilinx IRQ Generic Driver. + * @author Cristian Pop (cristian.pop@analog.com) +******************************************************************************** + * Copyright 2019(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ + +#include +#include +#include "error.h" +#include "irq.h" +#include "xilinx_irq.h" +#ifdef XPAR_XSCUGIC_NUM_INSTANCES +#include +#endif +#ifdef XPAR_XINTC_NUM_INSTANCES +#include +#endif +#ifdef XPAR_XTMRCTR_NUM_INSTANCES +#include +#endif + +/******************************************************************************/ +/************************ Functions Definitions *******************************/ +/******************************************************************************/ + +/** + * @brief Initialize the IRQ interrupts. + * @param desc - The IRQ controller descriptor. + * @param param - The structure that contains the IRQ parameters. + * @return 0 in case of success, -1 otherwise. + */ +int32_t xil_irq_ctrl_init(struct irq_ctrl_desc **desc, + const struct irq_init_param *param) +{ + int32_t status; + struct irq_ctrl_desc *descriptor; + struct xil_irq_desc *xil_dev; +#ifdef XSCUGIC_H + void *config; +#endif + + descriptor = (struct irq_ctrl_desc *)calloc(1, sizeof *descriptor); + if(!descriptor) + return -1; + xil_dev = (struct xil_irq_desc *)calloc(1, sizeof *xil_dev); + if(!xil_dev) { + free(descriptor); + return -1; + } + + Xil_ExceptionInit(); + + descriptor->irq_ctrl_id = param->irq_ctrl_id; + descriptor->extra = xil_dev; + xil_dev->type = ((struct xil_irq_init_param *)param->extra)->type; + + switch(xil_dev->type) { + case IRQ_PS: +#ifdef XSCUGIC_H + xil_dev->instance = calloc(1, sizeof(XScuGic)); + if(!xil_dev->instance) + goto error; + + config = XScuGic_LookupConfig(descriptor->irq_ctrl_id); + if(!config) + goto ps_error; + + status = XScuGic_CfgInitialize(xil_dev->instance, config, + ((XScuGic_Config *)config)->CpuBaseAddress); + if (status != 0) + goto ps_error; + + Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, + (Xil_ExceptionHandler)XScuGic_InterruptHandler, + xil_dev->instance); + + break; +ps_error: + free(xil_dev->instance); +#endif + goto error; + case IRQ_PL: +#ifdef XINTC_H + xil_dev->instance = calloc(1, sizeof(XIntc)); + if(!xil_dev->instance) + goto error; + + status = XIntc_Initialize(xil_dev->instance, descriptor->irq_ctrl_id); + if(status != 0) + goto pl_error; + + status = XIntc_Start(xil_dev->instance, XIN_REAL_MODE); + if(status != 0) + goto pl_error; + + break; +pl_error: + free(xil_dev->instance); +#endif + goto error; + default: + goto error; + + break; + } + + *desc = descriptor; + + return 0; + +error: + free(xil_dev); + free(descriptor); + + return -1; +} + +/** + * @brief Enable global interrupts. + * @return 0 in case of success, -1 otherwise. + */ +int32_t xil_irq_global_enable(struct irq_ctrl_desc *desc) +{ + /* Enable interrupts */ + Xil_ExceptionEnable(); + + return 0; +} + +/** + * @brief Disable global interrupts. + * @return 0 in case of success, -1 otherwise. + */ +int32_t xil_irq_global_disable(struct irq_ctrl_desc *desc) +{ + /* Disable interrupts */ + Xil_ExceptionDisable(); + + return 0; +} + +/** + * @brief Enable specific interrupt. + * @param desc - The IRQ controller descriptor. + * @param irq_id - Interrupt identifier. + * @return 0 in case of success, -1 otherwise. + */ +int32_t xil_irq_enable(struct irq_ctrl_desc *desc, uint32_t irq_id) +{ + struct xil_irq_desc *xil_dev = desc->extra; + + switch(xil_dev->type) { + case IRQ_PS: +#ifdef XSCUGIC_H + XScuGic_Enable(xil_dev->instance, irq_id); +#endif + break; + case IRQ_PL: +#ifdef XINTC_H + XIntc_Enable(xil_dev->instance, irq_id); +#endif + break; + default: + + return -1; + } + + return 0; +} + +/** + * @brief Disable specific interrupt. + * @param desc - The IRQ controller descriptor. + * @param irq_id - Interrupt identifier. + * @return 0 in case of success, -1 otherwise. + */ +int32_t xil_irq_disable(struct irq_ctrl_desc *desc, uint32_t irq_id) +{ + struct xil_irq_desc *xil_dev = desc->extra; + + switch(xil_dev->type) { + case IRQ_PS: +#ifdef XSCUGIC_H + XScuGic_Disable(xil_dev->instance, irq_id); +#endif + break; + case IRQ_PL: +#ifdef XINTC_H + XIntc_Disable(xil_dev->instance, irq_id); +#endif + break; + default: + + return -1; + } + + return 0; +} + +/** + * @brief Register a callback to handle the irq events. + * @param desc - The IRQ controller descriptor. + * @param irq_id - Interrupt identifier. + * @param callback_desc - Callback descriptor + * @return 0 in case of success, -1 otherwise. + */ +int32_t xil_irq_register_callback(struct irq_ctrl_desc *desc, + uint32_t irq_id, + struct callback_desc *callback_desc) +{ + struct xil_irq_desc *xil_dev = desc->extra; + + switch(xil_dev->type) { + case IRQ_PS: +#ifdef XSCUGIC_H + return XScuGic_Connect(xil_dev->instance, irq_id, + (Xil_InterruptHandler) callback_desc->callback, + callback_desc->ctx); +#endif + break; + case IRQ_PL: +#ifdef XINTC_H + if (irq_id == XPAR_AXI_INTC_AXI_TIMER_INTERRUPT_INTR) { + int32_t ret; + + ret = XIntc_Connect(xil_dev->instance, irq_id, + XTmrCtr_InterruptHandler, callback_desc->legacy_config); + if (IS_ERR_VALUE(ret)) + return -1; + XTmrCtr_SetHandler(callback_desc->legacy_config, + (XTmrCtr_Handler)callback_desc->callback, + callback_desc->ctx); + + return 0; + } + return XIntc_Connect(xil_dev->instance, irq_id, + (XInterruptHandler) callback_desc->callback, + callback_desc->ctx); +#endif + break; + default: + break; + } + + return -1; +} + +/** + * @brief Set interrupt trigger level. + * @param desc - The IRQ controller descriptor. + * @param irq_id - Interrupt identifier. + * @param trig - New trigger level for the interrupt. + * @return 0 in case of success, -1 otherwise. + */ +int32_t xil_irq_trigger_level_set(struct irq_ctrl_desc *desc, + uint32_t irq_id, + enum irq_trig_level trig) +{ + struct xil_irq_desc *xil_dev = desc->extra; + + if(trig == IRQ_EDGE_BOTH) + return -EINVAL; + + switch(xil_dev->type) { + case IRQ_PS: +#ifdef XSCUGIC_H + ; + uint8_t priority, trigger; + + XScuGic_GetPriorityTriggerType(xil_dev->instance, irq_id, &priority, + &trigger); + trigger = trig; + XScuGic_SetPriorityTriggerType(xil_dev->instance, irq_id, priority, + trigger); + + return 0; +#endif + break; + case IRQ_PL: +#ifdef XINTC_H + /* Interrupt trigger determined in hardware. TODO: verify */ + return 0; +#endif + break; + default: + break; + } + + return -1; +} + +/** + * @brief Set interrupt trigger level. + * @param desc - The IRQ controller descriptor. + * @param irq_id - Interrupt identifier. + * @param priority_level - New priority level for the interrupt. + * @return 0 in case of success, -1 otherwise. + */ +int32_t xil_irq_set_priority(struct irq_ctrl_desc *desc, + uint32_t irq_id, + uint32_t priority_level) +{ + struct xil_irq_desc *xil_dev = desc->extra; + + if(priority_level % 8 != 0) + return -EINVAL; + + switch(xil_dev->type) { + case IRQ_PS: +#ifdef XSCUGIC_H + ; + uint8_t priority, trigger; + + XScuGic_GetPriorityTriggerType(xil_dev->instance, irq_id, &priority, + &trigger); + priority = priority_level; + XScuGic_SetPriorityTriggerType(xil_dev->instance, irq_id, priority, + trigger); + + return 0; +#endif + break; + case IRQ_PL: +#ifdef XINTC_H + /* Interrupt priority level determined in hardware. TODO: verify */ + return 0; +#endif + break; + default: + break; + } + + return -1; +} + +/** + * @brief Unregisters a generic IRQ handling function. + * @param desc - The IRQ controller descriptor. + * @param irq_id - Interrupt identifier. + * @param cb - Callback descriptor. + * @return 0 in case of success, -1 otherwise. + */ +int32_t xil_irq_unregister_callback(struct irq_ctrl_desc *desc, + uint32_t irq_id, struct callback_desc *cb) +{ + struct xil_irq_desc *xil_dev = desc->extra; + + switch(xil_dev->type) { + case IRQ_PS: +#ifdef XSCUGIC_H + XScuGic_Disconnect(xil_dev->instance, irq_id); +#endif + break; + case IRQ_PL: +#ifdef XINTC_H + XIntc_Disconnect(xil_dev->instance, irq_id); +#endif + break; + default: + + return -1; + } + + return 0; +} + +/** + * @brief Free the resources allocated by irq_ctrl_init(). + * @param desc - The IRQ control descriptor. + * @return 0 in case of success, -1 otherwise. + */ +int32_t xil_irq_ctrl_remove(struct irq_ctrl_desc *desc) +{ + struct xil_irq_desc *xil_dev = desc->extra; + free(xil_dev->instance); + free(desc->extra); + free(desc); + + return 0; +} + +/** + * @brief Xilinx platform specific IRQ platform ops structure + */ +const struct irq_platform_ops xil_irq_ops = { + .init = &xil_irq_ctrl_init, + .register_callback = &xil_irq_register_callback, + .unregister_callback = &xil_irq_unregister_callback, + .global_enable = &xil_irq_global_enable, + .global_disable = &xil_irq_global_disable, + .trigger_level_set = &xil_irq_trigger_level_set, + .set_priority = &xil_irq_set_priority, + .enable = &xil_irq_enable, + .disable = &xil_irq_disable, + .remove = &xil_irq_ctrl_remove +}; diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/platform/xilinx_irq.h b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/platform/xilinx_irq.h new file mode 100644 index 0000000..7e0f771 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/platform/xilinx_irq.h @@ -0,0 +1,91 @@ +/******************************************************************************* + * @file xilinx_irq.h + * @brief Header containing types used in the irq driver. + * @author Cristian Pop (cristian.pop@analog.com) +******************************************************************************** + * Copyright 2019(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +#ifndef XILINX_IRQ_H_ +#define XILINX_IRQ_H_ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ + +#include +#include "irq.h" + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ + +/** + * @enum xil_irq_type + * @brief Xilinx platform architecture sections + */ +enum xil_irq_type { + /** Programmable Logic */ + IRQ_PL, + /** Processing System */ + IRQ_PS +}; + +/** + * @struct xil_irq_init_param + * @brief Structure holding the initialization parameters for Xilinx platform + * specific IRQ parameters. + */ +struct xil_irq_init_param { + /** Xilinx architecture */ + enum xil_irq_type type; +}; + +/** + * @struct xil_irq_desc + * @brief Xilinx platform specific IRQ descriptor + */ +struct xil_irq_desc { + /** Xilinx architecture */ + enum xil_irq_type type; + /** Xilinx IRQ Instance */ + void *instance; +}; + +/** + * @brief Xilinx specific IRQ platform ops structure + */ +extern const struct irq_platform_ops xil_irq_ops; + +#endif diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/platform/xilinx_spi.c b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/platform/xilinx_spi.c new file mode 100644 index 0000000..8a73a7b --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/platform/xilinx_spi.c @@ -0,0 +1,462 @@ +/***************************************************************************//** + * @file xilinx/xilinx_spi.c + * @brief Implementation of Xilinx SPI Generic Driver. + * @author Antoniu Miclaus (antoniu.miclaus@analog.com) +******************************************************************************** + * Copyright 2019(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ + +#include + +#include +#ifdef XPAR_XSPI_NUM_INSTANCES +#include +#endif +#ifdef XPAR_XSPIPS_NUM_INSTANCES +#include +#endif + +#include "error.h" +#include "spi.h" +#include "xilinx_spi.h" + +#if defined(PLATFORM_ZYNQ) +#define SPI_CLK_FREQ_HZ(dev) (XPAR_PS7_SPI_ ## dev ## _SPI_CLK_FREQ_HZ) +#define SPI_NUM_INSTANCES XPAR_XSPIPS_NUM_INSTANCES +#elif defined(PLATFORM_ZYNQMP) +#define SPI_CLK_FREQ_HZ(dev) (XPAR_PSU_SPI_ ## dev ## _SPI_CLK_FREQ_HZ) +#define SPI_NUM_INSTANCES XPAR_XSPIPS_NUM_INSTANCES +#else +#define SPI_NUM_INSTANCES 0 +#endif + +#warning SPI delays are not supported on the xilinx platform + +/******************************************************************************/ +/************************ Functions Definitions *******************************/ +/******************************************************************************/ + +/** + * @brief Initialize the hardware SPI peripherial + * + * @param xdesc Platform specific SPI descriptor + * @param xinit Platform specific SPI init param + * @return int32_t -1 if the device couldn't be found or configured + */ +static int32_t spi_init_pl(struct spi_desc *desc, + const struct spi_init_param *param) +{ +#ifdef XSPI_H + int32_t ret; + struct xil_spi_desc *xdesc; + struct xil_spi_init_param *xinit; + + xdesc = (struct xil_spi_desc*)malloc(sizeof(struct xil_spi_desc)); + if(!xdesc) { + free(xdesc); + return -1; + } + + desc->extra = xdesc; + xinit = param->extra; + xdesc->type = xinit->type; + xdesc->flags = xinit->flags; + + xdesc->instance = (XSpi*)calloc(1, sizeof(XSpi)); + if(!xdesc->instance) + goto pl_error; + + xdesc->config = XSpi_LookupConfig(param->device_id); + if(xdesc->config == NULL) + goto pl_error; + + ret = XSpi_CfgInitialize(xdesc->instance, + xdesc->config, + ((XSpi_Config*)xdesc->config) + ->BaseAddress); + if(ret != 0) + goto pl_error; + + ret = XSpi_Initialize(xdesc->instance, param->device_id); + if (ret != 0) + goto pl_error; + + ret = XSpi_SetOptions(xdesc->instance, + XSP_MASTER_OPTION | + ((desc->mode & SPI_CPOL) ? + XSP_CLK_ACTIVE_LOW_OPTION : 0) | + ((desc->mode & SPI_CPHA) ? + XSP_CLK_PHASE_1_OPTION : 0)); + if (ret != 0) + goto pl_error; + + ret = XSpi_Start(xdesc->instance); + if (ret != 0) + goto pl_error; + + XSpi_IntrGlobalDisable((XSpi *)(xdesc->instance)); + + return 0; + +pl_error: + free(xdesc->instance); + free(xdesc); +#endif + return -1; +} + +/** + * @brief Initialize the hardware SPI peripherial + * + * @param xdesc Platform specific SPI descriptor + * @param xinit Platform specific SPI init param + * @return int32_t -1 if the device couldn't be found or configured + */ +static int32_t spi_init_ps(struct spi_desc *desc, + const struct spi_init_param *param) +{ +#ifdef XSPIPS_H + int32_t ret; + struct xil_spi_desc *xdesc; + struct xil_spi_init_param *xinit; + const uint32_t prescaler_default = XSPIPS_CLK_PRESCALE_64; + const uint32_t prescaler_min = XSPIPS_CLK_PRESCALE_4; + const uint32_t prescaler_max = XSPIPS_CLK_PRESCALE_256; + uint32_t prescaler = 0u; + uint32_t input_clock = 0u; + + xdesc = (struct xil_spi_desc*)malloc(sizeof(struct xil_spi_desc)); + if(!xdesc) { + free(xdesc); + return -1; + } + + desc->extra = xdesc; + xinit = param->extra; + xdesc->type = xinit->type; + xdesc->flags = xinit->flags; + + xdesc->instance = (XSpiPs*)malloc(sizeof(XSpiPs)); + if(!xdesc->instance) + goto ps_error; + + xdesc->config = XSpiPs_LookupConfig(param->device_id); + if(xdesc->config == NULL) + goto ps_error; + + ret = XSpiPs_CfgInitialize(xdesc->instance, + xdesc->config, + ((XSpiPs_Config*)xdesc->config) + ->BaseAddress); + if(ret != 0) + goto ps_error; + + switch (param->device_id) { +#if (SPI_NUM_INSTANCES >= 1) + case 0: + input_clock = SPI_CLK_FREQ_HZ(0); + break; +#endif +#if (SPI_NUM_INSTANCES >= 2) + case 1: + input_clock = SPI_CLK_FREQ_HZ(1); + break; +#endif + default: + goto ps_error; + }; + + if (desc->max_speed_hz != 0u) { + uint32_t div = input_clock / desc->max_speed_hz; + uint32_t rem = input_clock % desc->max_speed_hz; + uint32_t po2 = !(div & (div - 1)) && !rem; + + // find the power of two just higher than div and + // store the exponent in prescaler + while(div) { + prescaler += 1; + div >>= 1u; + } + + // this exponent - 1 is needed because of the way + // xilinx stores it into registers + if (prescaler) + prescaler -= 1; + + // this exponent - 1 is needed when initial div was + // precisely a power of two + if (prescaler && po2) + prescaler -= 1; + + if (prescaler < prescaler_min) + prescaler = prescaler_min; + + if (prescaler > prescaler_max) + prescaler = prescaler_max; + } else + prescaler = prescaler_default; + + ret = XSpiPs_SetClkPrescaler(xdesc->instance, prescaler); + + if(ret != 0) + goto ps_error; + + return 0; + +ps_error: + free(xdesc->instance); + free(xdesc); +#endif + return -1; +} + +/** + * @brief Initialize the SPI communication peripheral. + * @param desc - The SPI descriptor. + * @param param - The structure that contains the SPI parameters. + * @return 0 in case of success, -1 otherwise. + */ +int32_t xil_spi_init(struct spi_desc **desc, + const struct spi_init_param *param) +{ + int32_t ret; + enum xil_spi_type *spi_type; + + if (!param) { + return -1; + } + + *desc = malloc(sizeof(**desc)); + if(! *desc) { + free(*desc); + return -1; + } + + spi_type = param->extra; + + if(!spi_type) + goto init_error; + + (*desc)->max_speed_hz = param->max_speed_hz; + (*desc)->mode = param->mode; + (*desc)->bit_order = param->bit_order; + (*desc)->chip_select = param->chip_select; + + switch (*spi_type) { + case SPI_PL: + ret = spi_init_pl(*desc, param); + break; + case SPI_PS: + ret = spi_init_ps(*desc, param); + break; + + default: + goto init_error; + break; + } + + if (ret != 0) { +init_error: + free(*desc); + + return -1; + } + + return ret; +} + +/** + * @brief Free the resources allocated by spi_init(). + * @param desc - The SPI descriptor. + * @return 0 in case of success, -1 otherwise. + */ +int32_t xil_spi_remove(struct spi_desc *desc) +{ +#ifdef XSPI_H + int32_t ret; +#endif + struct xil_spi_desc *xdesc = NULL; + enum xil_spi_type *spi_type; + + spi_type = desc->extra; + + if(!spi_type) + return -1; + + switch (*spi_type ) { + case SPI_PL: +#ifdef XSPI_H + xdesc = desc->extra; + + if(!xdesc) + return -1; + + ret = XSpi_Stop((XSpi *)(xdesc->instance)); + if(ret != 0) + goto error; +#endif + break; + case SPI_PS: +#ifdef XSPIPS_H + xdesc = desc->extra; + + if(!xdesc) + return -1; +#endif + break; + + /* Intended fallthrough */ +#ifdef XSPI_H +error: +#endif + default: + return -1; + } + + if(xdesc) + free(xdesc->instance); + free(desc->extra); + free(desc); + + return 0; +} + +/** + * @brief Write and read data to/from SPI. + * @param desc - The SPI descriptor. + * @param data - The buffer with the transmitted/received data. + * @param bytes_number - Number of bytes to write/read. + * @return 0 in case of success, -1 otherwise. + */ +int32_t xil_spi_write_and_read(struct spi_desc *desc, + uint8_t *data, + uint16_t bytes_number) +{ + int32_t ret; +#ifdef XSPI_H + uint32_t ctrl_reg; +#endif + struct xil_spi_desc *xdesc; + enum xil_spi_type *spi_type; + + ret = -1; + + spi_type = desc->extra; + + if(!spi_type) + return -1; + + xdesc = desc->extra; + + switch (*spi_type) { + case SPI_PL: +#ifdef XSPI_H + ret = XSpi_SetOptions(xdesc->instance, + XSP_MASTER_OPTION | + ((desc->mode & SPI_CPOL) ? + XSP_CLK_ACTIVE_LOW_OPTION : 0) | + ((desc->mode & SPI_CPHA) ? + XSP_CLK_PHASE_1_OPTION : 0)); + if (ret != 0) + goto error; + + ctrl_reg = XSpi_GetControlReg(((XSpi*)xdesc->instance)); + if (desc->bit_order == SPI_BIT_ORDER_LSB_FIRST) + ctrl_reg |= XSP_CR_LSB_MSB_FIRST_MASK; + else + ctrl_reg &= ~ XSP_CR_LSB_MSB_FIRST_MASK; + XSpi_SetControlReg(((XSpi*)xdesc->instance), ctrl_reg); + + ret = XSpi_SetSlaveSelect(xdesc->instance, + 0x01 << desc->chip_select); + if (ret != 0) + goto error; + + ret = XSpi_Transfer(xdesc->instance, + data, + data, + bytes_number); + if (ret != 0) + goto error; +#endif + break; + case SPI_PS: +#ifdef XSPIPS_H + ret = XSpiPs_SetOptions(xdesc->instance, + XSPIPS_MASTER_OPTION | + ((xdesc->flags & SPI_CS_DECODE) ? + XSPIPS_DECODE_SSELECT_OPTION : 0) | + XSPIPS_FORCE_SSELECT_OPTION | + ((desc->mode & SPI_CPOL) ? + XSPIPS_CLK_ACTIVE_LOW_OPTION : 0) | + ((desc->mode & SPI_CPHA) ? + XSPIPS_CLK_PHASE_1_OPTION : 0)); + if (ret != 0) + goto error; + + ret = XSpiPs_SetSlaveSelect(xdesc->instance, + desc->chip_select); + if (ret != 0) + goto error; + ret = XSpiPs_PolledTransfer(xdesc->instance, + data, + data, + bytes_number); + if (ret != 0) + goto error; + ret = XSpiPs_SetSlaveSelect(xdesc->instance, SPI_DEASSERT_CURRENT_SS); + if (ret != 0) + goto error; +#endif + break; +error: + default: + return -1; + } + + return ret; +} + +/** + * @brief Xilinx platform specific SPI platform ops structure + */ +const struct spi_platform_ops xil_spi_ops = { + .init = &xil_spi_init, + .write_and_read = &xil_spi_write_and_read, + .remove = &xil_spi_remove +}; diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/platform/xilinx_spi.h b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/platform/xilinx_spi.h new file mode 100644 index 0000000..b0c4681 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/platform/xilinx_spi.h @@ -0,0 +1,115 @@ +/******************************************************************************* + * @file xilinx/xilinx_spi.h + * @brief Header containing extra types used in the spi driver. + * @author scuciurean (sergiu.cuciurean@analog.com) +******************************************************************************** + * Copyright 2019(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ +#ifndef XILINX_SPI_H_ +#define XILINX_SPI_H_ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ + +#include +#include "spi.h" + +/******************************************************************************/ +/********************** Macros and Constants Definitions **********************/ +/******************************************************************************/ + +#define SPI_CS_DECODE 0x01 +#define SPI_DEASSERT_CURRENT_SS 0x0F + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ + +/** + * @enum xil_spi_type + * @brief Xilinx platform architecture sections + */ +enum xil_spi_type { + /** Programmable Logic */ + SPI_PL, + /** Processing System */ + SPI_PS, + /** SPI Engine */ + SPI_ENGINE +}; + +/** + * @struct xil_spi_init_param + * @brief Structure holding the initialization parameters for Xilinx platform + * specific SPI parameters when using xil_spi_ops. + */ +struct xil_spi_init_param { + /** Xilinx architecture */ + enum xil_spi_type type; + /** SPI flags */ + uint32_t flags; +}; + +/** + * @struct xil_spi_desc + * @brief Xilinx platform specific SPI descriptor + */ +struct xil_spi_desc { + /** Xilinx architecture */ + enum xil_spi_type type; + /** SPI flags */ + uint32_t flags; + /** SPI configuration */ + void *config; + /** SPI instance */ + void *instance; +}; + +/** + * @brief SPI engine platform ops structure + */ +extern const struct spi_platform_ops spi_eng_platform_ops; + +/** + * @brief Xilinx specific SPI platform ops structure + */ +extern const struct spi_platform_ops xil_spi_ops; + +/** + * @brief Xilinx SPI PS register functions. No extra param needed + */ +extern const struct spi_platform_ops xil_spi_pl_ops; + +#endif // XILINX_SPI_H_ diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/platform/xilinx_spi_pl.c b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/platform/xilinx_spi_pl.c new file mode 100644 index 0000000..bef2cf4 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/platform/xilinx_spi_pl.c @@ -0,0 +1,533 @@ +/******************************************************************************* + * @file xilinx/xilinx_spi_pl.c + * @brief Driver for spi pl device using registers + * @author Mihail Chindris (mihail.chindris@analog.com) +******************************************************************************** + * Copyright 2021(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +#include + +#ifdef XPAR_XSPI_NUM_INSTANCES + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ + +#include +#include +#include +#include "spi.h" +#include "error.h" +#include "delay.h" +#include "util.h" +#include "alloc.h" + +/******************************************************************************/ +/********************** Macros and Constants Definitions **********************/ +/******************************************************************************/ + +#define XPS_TYPE_WRITE 0x1 +#define XPS_TYPE_READ 0x2 +#define XSP_DEFAULT_SR_VALUE 0x25 +#define XSP_DUMMY_DATA 0xFF + +/* + * Used to store current spi device configuration in order to not update it for + * each spi transaction if not needed. + */ +static struct spi_desc g_spi_desc[XPAR_XSPI_NUM_INSTANCES]; + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ + +/* Xilinx PL spi specific data */ +struct xspi_desc { + uint32_t base_addr; + uint32_t disable_slaves_mask; + uint32_t fifo_depth; + uint8_t cs_asserted; +}; + +/* Structure used to iterate over SPI messages */ +struct msg_iter { + struct spi_msg *msgs; + uint32_t len; + uint32_t i; + uint32_t buff_i; + uint8_t is_wr; +}; + +/******************************************************************************/ +/************************ Functions Definitions *******************************/ +/******************************************************************************/ + +/* Read device register */ +static inline uint32_t _read(struct xspi_desc *xdesc, uint32_t reg) +{ + return Xil_In32(xdesc->base_addr + reg); +} + +/* Write device register */ +static inline void _write(struct xspi_desc *xdesc, uint32_t reg, uint32_t val) +{ + Xil_Out32(xdesc->base_addr + reg, val); +} + +/* Update device register. Only bits set to 1 in mask will be modified */ +static inline void _wr_mask(struct xspi_desc *xdesc, uint32_t reg, + uint32_t val, uint32_t mask) +{ + uint32_t tmp; + + tmp = _read(xdesc, reg); + tmp &= ~mask; + tmp |= val & mask; + _write(xdesc, reg, tmp); +} + +/* Update spi device configuration if needed */ +static void _update_mode(struct spi_desc *desc) +{ + uint32_t val; + uint32_t mask; + + if (desc->mode == g_spi_desc[desc->device_id].mode && + desc->bit_order == g_spi_desc[desc->device_id].bit_order) + return ; + + /* Update mode */ + val = desc->mode | SPI_CPOL ? XSP_CR_CLK_POLARITY_MASK : 0; + val |= desc->mode | SPI_CPHA ? XSP_CR_CLK_PHASE_MASK : 0; + mask = XSP_CR_CLK_POLARITY_MASK | XSP_CR_CLK_PHASE_MASK; + + val |= desc->bit_order == SPI_BIT_ORDER_LSB_FIRST ? + XSP_CR_LSB_MSB_FIRST_MASK : 0; + mask |= XSP_CR_LSB_MSB_FIRST_MASK; + + _wr_mask(desc->extra, XSP_CR_OFFSET, val, mask); + g_spi_desc[desc->device_id] = *desc; +} + +/* Configure SPI PL device */ +static int32_t _xil_spi_init_dev(struct xspi_desc *xdesc) +{ + uint32_t val; + + /* Software reset */ + _write(xdesc, XSP_SRR_OFFSET, XSP_SRR_RESET_MASK); + mdelay(1); + + /* Check if success reset */ + val = _read(xdesc, XSP_SR_OFFSET); + if (val != XSP_DEFAULT_SR_VALUE) + return -ENODEV; + + /* Disable interrupts. Drivers only works with pooled mode */ + _write(xdesc, XSP_IIER_OFFSET, 0); + + /* Deasert chip selects */ + _write(xdesc, XSP_SSR_OFFSET, 0xFFFFFFFF); + + /* Get fifo depth */ + while (!(_read(xdesc, XSP_SR_OFFSET) & XSP_SR_TX_FULL_MASK)) + _write(xdesc, XSP_DTR_OFFSET, XSP_DUMMY_DATA); + xdesc->fifo_depth = _read(xdesc, XSP_TFO_OFFSET) + 1; + + /* Configure spi device */ + val = XSP_CR_ENABLE_MASK | + XSP_CR_MANUAL_SS_MASK | + XSP_CR_TXFIFO_RESET_MASK | + XSP_CR_RXFIFO_RESET_MASK | + XSP_CR_MASTER_MODE_MASK | + XSP_CR_TRANS_INHIBIT_MASK; + + _write(xdesc, XSP_CR_OFFSET, val); + + return 0; +} + +/* Initialize spi_desc structure and device */ +static int32_t xil_spi_init_pl(struct spi_desc **desc, + const struct spi_init_param *param) +{ + struct spi_desc *ldesc; + struct xspi_desc *xdesc; + int32_t err; + XSpi_Config *cfg; + + if (!desc || !param || param->device_id >= XPAR_XSPI_NUM_INSTANCES) + return -EINVAL; + + cfg = XSpi_LookupConfig(param->device_id); + if (!cfg) + return -EINVAL; + + if (param->chip_select > cfg->NumSlaveBits) + return -EINVAL; + + ldesc = (struct spi_desc *)calloc(1, sizeof(*ldesc)); + if (!ldesc) + return -ENOMEM; + + xdesc = (struct xspi_desc *)calloc(1, sizeof(*xdesc)); + if (!xdesc) { + err = -ENOMEM; + goto error; + } + + ldesc->bit_order = param->bit_order; + ldesc->chip_select = param->chip_select; + ldesc->mode = param->mode; + xdesc->base_addr = cfg->BaseAddress; + xdesc->disable_slaves_mask = (1 << cfg->NumSlaveBits) - 1; + xdesc->cs_asserted = 0; + + err = _xil_spi_init_dev(xdesc); + if (IS_ERR_VALUE(err)) + goto error; + + ldesc->extra = xdesc; + *desc = ldesc; + + return 0; + +error: + free(xdesc); + free(ldesc); + + return err; +} + +/* Remove allocated resources */ +static int32_t xil_spi_remove_pl(struct spi_desc *desc) +{ + if (!desc) + return -EINVAL; + + free(desc->extra); + free(desc); + + return 0; +} + +/* + * Fill fifo until fifo is full or no more data available. + * Return the number of written bytes. + */ +static uint32_t _wr_fifo(struct xspi_desc *xdesc, uint8_t *data, + uint32_t len) +{ + uint32_t i; + uint32_t to_write; + uint32_t tx_available; + + tx_available = xdesc->fifo_depth - _read(xdesc, XSP_TFO_OFFSET); + to_write = min(tx_available, len); + for (i = 0; i < to_write; ++i) + if (data) + _write(xdesc, XSP_DTR_OFFSET, data[i]); + else + _write(xdesc, XSP_DTR_OFFSET, XSP_DUMMY_DATA); + + return to_write; +} + +/* + * Read fifo until fifo is empty or no more buffer available to read into + * Returns the number of read bytes + */ +static uint32_t _rd_fifo(struct xspi_desc *xdesc, uint8_t *data, + uint32_t len) +{ + uint32_t rx_available; + uint32_t to_read; + uint32_t tmp; + uint32_t i; + + tmp = _read(xdesc, XSP_SR_OFFSET); + if (tmp & XSP_SR_RX_EMPTY_MASK) + return 0; + + rx_available = _read(xdesc, XSP_RFO_OFFSET) + 1; + to_read = min(rx_available, len); + for (i = 0; i < to_read; ++i) { + tmp = _read(xdesc, XSP_DRR_OFFSET); + if (data) + data[i] = tmp; + } + + return to_read; +} + +/* If start is 0 stop transfer, else start it. + * CS will be asserted if needed. If different CS othere than the one needed + * is asserted. Deassert it and assert correct one */ +static void _xil_spi_start_transfer(struct spi_desc *desc, uint8_t start) +{ + struct xspi_desc *xdesc; + + xdesc = desc->extra; + if (start) { + if (xdesc->cs_asserted) { + if (desc->chip_select == + g_spi_desc[desc->device_id].chip_select) + return ; + else + /* Stop transfer to start again with new CS */ + _xil_spi_start_transfer(desc, 0); + } + _write(xdesc, XSP_SSR_OFFSET, ~(1 << desc->chip_select)); + _wr_mask(xdesc, XSP_CR_OFFSET, 0, XSP_CR_TRANS_INHIBIT_MASK); + } else { + _wr_mask(xdesc, XSP_CR_OFFSET, XSP_CR_TRANS_INHIBIT_MASK, + XSP_CR_TRANS_INHIBIT_MASK); + _write(xdesc, XSP_SSR_OFFSET, xdesc->disable_slaves_mask); + } + xdesc->cs_asserted = start; +} + + +/* SPI polled transfer */ +static int32_t xil_spi_write_and_read_pl(struct spi_desc *desc, + uint8_t *data, + uint16_t bytes_number) +{ + struct xspi_desc *xdesc; + uint32_t rx; + uint32_t tx; + + if (!desc || !desc->extra) + return -EINVAL; + + xdesc = desc->extra; + _update_mode(desc); + + _xil_spi_start_transfer(desc, 1); + rx = 0; + tx = 0; + while (rx < bytes_number) { + if (tx < bytes_number) + tx += _wr_fifo(xdesc, data + tx, bytes_number - tx); + rx += _rd_fifo(xdesc, data + rx, bytes_number - rx); + } + _xil_spi_start_transfer(desc, 0); + + return 0; +} + +/* Get type of message. It can be READ, WRITE or both */ +static uint32_t _get_msg_type(struct spi_msg *msg) +{ + uint32_t type; + + type = 0; + if (msg->tx_buff) + type |= XPS_TYPE_WRITE; + if (msg->rx_buff) + type |= XPS_TYPE_READ; + + return type; +} + +/* Get information based on current iterator position */ +static void _get_data(struct msg_iter *it, uint8_t **buff, uint32_t *len, + uint32_t *type) +{ + struct spi_msg *msg; + + if (it->i == it->len) { + *len = 0; + return ; + } + + msg = it->msgs + it->i; + if (it->is_wr) + *buff = msg->tx_buff; + else + *buff = msg->rx_buff; + + if (*buff) + *buff += it->buff_i; + + *len = msg->bytes_number - it->buff_i; + if (type) + *type = _get_msg_type(msg); +} + +/* + * Increment iterator position with desired length. + * If the new position has a different message type, new_type will be set to 1 + * If a CS change is needed, cs_change is set + */ +static void _increment_iter(struct msg_iter *it, uint32_t len, + uint8_t *cs_change, uint8_t *new_type) +{ + struct spi_msg *msg; + uint32_t type; + uint32_t extra_len; + + if (!len) + return ; + + *cs_change = 0; + *new_type = 0; + msg = it->msgs + it->i; + if (it->buff_i + len > msg->bytes_number) + extra_len = it->buff_i + len - msg->bytes_number; + else + extra_len = 0; + len -= extra_len; + it->buff_i += len; + if (it->buff_i == msg->bytes_number) { + type = _get_msg_type(msg); + ++it->i; + it->buff_i = 0; + if (cs_change && msg->cs_change) + *cs_change = 1; + if (new_type) + if (it->i == it->len || + type != _get_msg_type(it->msgs + it->i)) + *new_type = 1; + } + if (extra_len) + _increment_iter(it, extra_len, cs_change, new_type); +} + +/* + * SPI polling transfer of multiple messages. + */ +static int32_t xil_spi_transfer_pl(struct spi_desc *desc, + struct spi_msg *msgs, + uint32_t len) + +{ + struct xspi_desc *xdesc; + uint8_t cs_change; + uint8_t new_type; + struct msg_iter rx = {.msgs = msgs, .len = len, .is_wr = 0}; + struct msg_iter tx = {.msgs = msgs, .len = len, .is_wr = 1}; + uint8_t *buff; + uint32_t bytes; + uint32_t type; + /* Bytes to increment rx when only a write transaction is executed */ + uint32_t to_inc_rx; + /* Difference between rx and tx iterators in bytes */ + uint32_t tx_advance; + /* Save bytes sent during a write loop */ + uint32_t tx_sent; + /* Used to loop if need to empty the RX FIFO */ + uint32_t loop; + + if (!desc || !desc->extra) + return -EINVAL; + + xdesc = desc->extra; + _update_mode(desc); + + tx_advance = 0; + to_inc_rx = 0; + buff = NULL; + type = 0; + do { + _xil_spi_start_transfer(desc, 1); + + tx_sent = 0; + /* Writing loop */ + do { + _get_data(&tx, &buff, &bytes, &type); + if (type & XPS_TYPE_READ) + /* + * Do not write more bytes than fifo_depth if + * they haven't been read. + */ + bytes = min(bytes, + xdesc->fifo_depth - tx_advance); + bytes = _wr_fifo(xdesc, buff, bytes); + tx_sent += bytes; + _increment_iter(&tx, bytes, &cs_change, &new_type); + tx_advance += bytes; + } while (!cs_change && !new_type && bytes); + + if (type & XPS_TYPE_READ) { + loop = 1; + /* + * Loop only when no more data to write otherwise read + * only available data. + */ + while (loop) { + if (!new_type) + loop = 0; + _get_data(&rx, &buff, &bytes, NULL); + bytes = _rd_fifo(xdesc, buff, bytes); + _increment_iter(&rx, bytes, &cs_change, &new_type); + tx_advance -= bytes; + if (loop && new_type) + break; + } + } else { + /* Clean RX FIFO if it was only a WRITE message */ + to_inc_rx += tx_sent; + if (new_type) { + /* Wait for TX to be sent */ + while (!(_read(xdesc, XSP_SR_OFFSET) & + XSP_SR_TX_EMPTY_MASK)) + ; + /* Reset fifo. Only write was performed */ + _wr_mask(xdesc, XSP_CR_OFFSET, + XSP_CR_RXFIFO_RESET_MASK, + XSP_CR_RXFIFO_RESET_MASK); + + _increment_iter(&rx, to_inc_rx, NULL, NULL); + tx_advance -= to_inc_rx; + to_inc_rx = 0; + } + } + + if ((cs_change && rx.i != len) || (!cs_change && rx.i == len)) + _xil_spi_start_transfer(desc, 0); + } while (rx.i < len); + + return 0; +} + +const struct spi_platform_ops xil_spi_pl_ops = { + .init = xil_spi_init_pl, + .remove = xil_spi_remove_pl, + .write_and_read = xil_spi_write_and_read_pl, + .transfer = xil_spi_transfer_pl +}; + +#endif // XPAR_XSPI_NUM_INSTANCES diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/platform/xilinx_timer.c b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/platform/xilinx_timer.c new file mode 100644 index 0000000..af83aa2 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/platform/xilinx_timer.c @@ -0,0 +1,456 @@ +/***************************************************************************//** +* @file xilinx/xilinx_timer.c +* @brief Timer and GIC control module source. +* @author Andrei Drimbarean (andrei.drimbarean@analog.com) +******************************************************************************** +* Copyright 2020(c) Analog Devices, Inc. +* +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* - Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* - Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* - Neither the name of Analog Devices, Inc. nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* - The use of this software may or may not infringe the patent rights +* of one or more patent holders. This license does not release you +* from the requirement that you obtain separate licenses from these +* patent holders to use this software. +* - Use of the software either in source or binary form, must be run +* on or directly connected to an Analog Devices Inc. component. +* +* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, MERCHANTABILITY +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +* IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ + +#include +#include +#include "timer.h" +#include "xilinx_timer.h" +#include "error.h" + +/******************************************************************************/ +/********************** Macros and Constants Definitions **********************/ +/******************************************************************************/ + +#if defined(_XPARAMETERS_PS_H_) +#define CORE_PRIVATE_TIMER_CLOCK (XPAR_CPU_CORTEXA9_CORE_CLOCK_FREQ_HZ / 2) +#endif + +/******************************************************************************/ +/************************ Functions Definitions *******************************/ +/******************************************************************************/ + +/** + * @brief Set the current counter value of the timer. + * @param [in] desc - Pointer to the device handler. + * @param [in] new_val - New value for the timer counter. + * @return 0 in case of success, -1 otherwise + */ +int32_t xilinx_timer_counter_set(struct timer_desc *desc, + uint32_t new_val) +{ + struct xil_timer_desc *xdesc; + + if (!desc) + return -1; + + xdesc = desc->extra; + + switch (xdesc->type) { + case TIMER_PS: +#ifdef XSCUTIMER_H + XScuTimer_LoadTimer((XScuTimer *)xdesc->instance, new_val - 1); + break; +#endif + return -1; + case TIMER_PL: +#ifdef XTMRCTR_H + XTmrCtr_SetResetValue(xdesc->instance, xdesc->active_tmr, new_val); + XTmrCtr_Reset(xdesc->instance, xdesc->active_tmr); + break; +#endif + return -1; + default: + return -1; + } + + return 0; +} + +/** + * @brief Set the timer clock frequency. + * @param [in] desc - Pointer to the device handler. + * @param [in] freq_hz - New timer frequency in hertz. + * @return 0 in case of success, -1 otherwise + */ +int32_t xilinx_timer_count_clk_set(struct timer_desc *desc, + uint32_t freq_hz) +{ + struct xil_timer_desc *xdesc; + + if (!desc || !freq_hz) + return -1; + + xdesc = desc->extra; + + switch (xdesc->type) { + case TIMER_PS: +#ifdef XSCUTIMER_H + ; + uint32_t prescaler = CORE_PRIVATE_TIMER_CLOCK / freq_hz; + if (prescaler == 0 || prescaler >= 256) + return -1; + XScuTimer_SetPrescaler(xdesc->instance, prescaler - 1); + desc->freq_hz = CORE_PRIVATE_TIMER_CLOCK / prescaler; + break; +#endif + return -1; + case TIMER_PL: +#ifdef XTMRCTR_H + (void *)xdesc; + /** Cannot be done. */ +#endif + return -1; + default: + return -1; + } + + return 0; +} + +/** + * @brief Initialize hardware timer and the handler structure associated with + * it. + * @param [out] desc - Pointer to the reference of the device handler. + * @param [in] param - Initialization structure. + * @return 0 in case of success, -1 otherwise + */ +int32_t xilinx_timer_init(struct timer_desc **desc, + const struct timer_init_param *param) +{ + int32_t ret; + struct timer_desc *dev; + struct xil_timer_desc *xdesc; + struct xil_timer_init_param *xinit; + + if (!desc || !param) + return -1; + + xinit = param->extra; + + dev = (struct timer_desc *)calloc(1, sizeof(*dev)); + if(!dev) + return -1; + xdesc = (struct xil_timer_desc *)calloc(1, sizeof(*xdesc)); + if(!xdesc) + goto error_desc; + + dev->id = param->id; + dev->freq_hz = param->freq_hz; + dev->ticks_count = param->ticks_count; + dev->extra = xdesc; + xdesc->active_tmr = xinit->active_tmr; + xdesc->type = xinit->type; + + switch (xdesc->type) { + case TIMER_PS: +#ifdef XSCUTIMER_H + xdesc->config = XScuTimer_LookupConfig(dev->id); + xdesc->instance = calloc(1, sizeof(XScuTimer)); + if (!xdesc->instance) + goto error_xdesc; + ret = XScuTimer_CfgInitialize(xdesc->instance, xdesc->config, + ((XScuTimer_Config *)xdesc->config)->BaseAddr); + if (ret != XST_SUCCESS) { + free(xdesc->instance); + goto error_xdesc; + } + ret = xilinx_timer_count_clk_set(dev, param->freq_hz); + if (IS_ERR_VALUE(ret)) + goto error_xdesc; + + ret = xilinx_timer_counter_set(dev, dev->ticks_count); + if (IS_ERR_VALUE(ret)) + goto error_xdesc; + + XScuTimer_EnableAutoReload((XScuTimer *)xdesc->instance); + XScuTimer_EnableInterrupt((XScuTimer *)xdesc->instance); + break; +#endif + goto error_xdesc; + case TIMER_PL: +#ifdef XTMRCTR_H + xdesc->instance = (XTmrCtr *)calloc(1, sizeof(XTmrCtr)); + if (!xdesc->instance) + return -1; + + xdesc->config = XTmrCtr_LookupConfig(dev->id); + if (!xdesc->config) { + free(xdesc->instance); + goto error_desc; + } + XTmrCtr_CfgInitialize(xdesc->instance, xdesc->config, + ((XTmrCtr_Config *)xdesc->config)->BaseAddress); + ret = XTmrCtr_InitHw(xdesc->instance); + if (ret != 0) { + free(xdesc->instance); + goto error_desc; + } + dev->freq_hz = ((XTmrCtr_Config *)xdesc->config)->SysClockFreqHz; + + ret = XTmrCtr_SelfTest(xdesc->instance, dev->id); + if(ret != 0) + goto error_desc; + XTmrCtr_SetOptions(xdesc->instance, xdesc->active_tmr, + XTC_DOWN_COUNT_OPTION | XTC_INT_MODE_OPTION | + XTC_AUTO_RELOAD_OPTION); + XTmrCtr_SetResetValue(xdesc->instance, xdesc->active_tmr, + dev->ticks_count); + break; +#endif + goto error_xdesc; + default: + goto error_xdesc; + } + + *desc = dev; + + return 0; + +error_xdesc: + free(xdesc); +error_desc: + free(dev); + + return -1; +} + +/** + * @brief Free the memory allocated by timer_setup(). + * @param [in] desc - Pointer to the device handler. + * @return 0 in case of success, -1 otherwise + */ +int32_t xilinx_timer_remove(struct timer_desc *desc) +{ + struct xil_timer_desc *xdesc; + + if(!desc) + return -1; + + xdesc = desc->extra; + + switch (xdesc->type) { + case TIMER_PS: +#ifdef XSCUTIMER_H + XScuTimer_Stop(xdesc->instance); + free(xdesc->instance); + break; +#endif + return -1; + case TIMER_PL: +#ifdef XTMRCTR_H + XTmrCtr_Stop(xdesc->instance, xdesc->active_tmr); + break; +#endif + return -1; + default: + return -1; + } + + free(xdesc); + free(desc); + + return 0; +} + +/** + * @brief Start a timer. + * @param [in] desc - Pointer to the device handler. + * @return 0 in case of success, -1 otherwise + */ +int32_t xilinx_timer_start(struct timer_desc *desc) +{ + struct xil_timer_desc *xdesc; + + if (!desc) + return -1; + + xdesc = desc->extra; + + switch (xdesc->type) { + case TIMER_PS: +#ifdef XSCUTIMER_H + XScuTimer_Start(xdesc->instance); + break; +#endif + return -1; + case TIMER_PL: +#ifdef XTMRCTR_H + XTmrCtr_Start(xdesc->instance, xdesc->active_tmr); + break; +#endif + return -1; + } + + return 0; +} + +/** + * @brief Stop a timer from counting. + * @param [in] desc - Pointer to the device handler. + * @return 0 in case of success, -1 otherwise + */ +int32_t xilinx_timer_stop(struct timer_desc *desc) +{ + struct xil_timer_desc *xdesc; + + if (!desc) + return -1; + + xdesc = desc->extra; + + switch (xdesc->type) { + case TIMER_PS: +#ifdef XSCUTIMER_H + XScuTimer_Stop(xdesc->instance); + break; +#endif + return -1; + case TIMER_PL: +#ifdef XTMRCTR_H + XTmrCtr_Stop(xdesc->instance, xdesc->active_tmr); + break; +#endif + return -1; + default: + return -1; + } + + return 0; +} + +/** + * @brief Get the current counter value of the timer. + * @param [in] desc - Pointer to the device handler. + * @param [out] counter - Pointer to the current counter value. + * @return 0 in case of success, -1 otherwise + */ +int32_t xilinx_timer_counter_get(struct timer_desc *desc, + uint32_t *counter) +{ + struct xil_timer_desc *xdesc; + + if (!desc || !counter) + return -1; + + xdesc = desc->extra; + + switch (xdesc->type) { + case TIMER_PS: +#ifdef XSCUTIMER_H + *counter = XScuTimer_GetCounterValue((XScuTimer *)xdesc->instance); + ++(*counter); + break; +#endif + return -1; + case TIMER_PL: +#ifdef XTMRCTR_H + *counter = XTmrCtr_GetValue(xdesc->instance, xdesc->active_tmr); + break; +#endif + return -1; + default: + *counter = 0; + + return -1; + } + + return 0; +} + + +/** + * @brief Get the timer clock frequency. + * @param [in] desc - Pointer to the device handler. + * @param [out] freq_hz - Pointer to the returned frequency. + * @return 0 in case of success, -1 otherwise + */ +int32_t xilinx_timer_count_clk_get(struct timer_desc *desc, + uint32_t *freq_hz) +{ + struct xil_timer_desc *xdesc; + + if (!desc || !freq_hz) + return -1; + + xdesc = desc->extra; + + switch (xdesc->type) { + case TIMER_PS: +#ifdef XSCUTIMER_H + *freq_hz = desc->freq_hz; + break; +#endif + return -1; + case TIMER_PL: +#ifdef XTMRCTR_H + *freq_hz = ((XTmrCtr_Config *)xdesc->config)->SysClockFreqHz; + break; +#endif + return -1; + default: + *freq_hz = 0; + + return -1; + } + + return 0; +} + + +/** + * @brief Get the elapsed time in nsec for the timer. + * @param [in] desc - Pointer to the device handler. + * @param [in] elapsed_time - The elapsed time in nsec. + * @return -ENOSYS. + */ +int32_t xilinx_timer_get_elapsed_time_nsec(struct timer_desc *desc, + uint64_t *elapsed_time) +{ + /* Function not implemented */ + return -ENOSYS; +} + +/** + * @brief Xilinx platform specific timer platform ops structure + */ +const struct timer_platform_ops xil_timer_ops = { + .init = &xilinx_timer_init, + .start = &xilinx_timer_start, + .stop = &xilinx_timer_stop, + .counter_get = &xilinx_timer_counter_get, + .counter_set = &xilinx_timer_counter_set, + .count_clk_get = &xilinx_timer_count_clk_get, + .count_clk_set = &xilinx_timer_count_clk_set, + .get_elapsed_time_nsec = &xilinx_timer_get_elapsed_time_nsec, + .remove = &xilinx_timer_remove +}; diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/platform/xilinx_timer.h b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/platform/xilinx_timer.h new file mode 100644 index 0000000..17b0d5a --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/platform/xilinx_timer.h @@ -0,0 +1,101 @@ +/***************************************************************************//** +* @file xilinx_timer.h +* @brief Timer control module header. +* @author Andrei Drimbarean (andrei.drimbarean@analog.com) +******************************************************************************** +* Copyright 2020(c) Analog Devices, Inc. +* +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* - Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* - Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* - Neither the name of Analog Devices, Inc. nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* - The use of this software may or may not infringe the patent rights +* of one or more patent holders. This license does not release you +* from the requirement that you obtain separate licenses from these +* patent holders to use this software. +* - Use of the software either in source or binary form, must be run +* on or directly connected to an Analog Devices Inc. component. +* +* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, MERCHANTABILITY +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +* IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +#ifndef XILINX_TIMER_H_ +#define XILINX_TIMER_H_ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ + +#include +#ifdef XPAR_XSCUTIMER_NUM_INSTANCES +#include +#endif +#ifdef XPAR_XTMRCTR_NUM_INSTANCES +#include +#endif + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ + +/** + * @enum xil_timer_type + * @brief Xilinx platform architecture sections + */ +enum xil_timer_type { + /** Programmable Logic */ + TIMER_PL, + /** Processing System */ + TIMER_PS +}; + +/** + * @struct xil_timer_desc + * @brief Xilinx specific timer descriptor + */ +struct xil_timer_desc { + /** Pointer to the BSP driver handler */ + void *instance; + /** Pointer to the BSP driver configuration handler */ + void *config; + /** Timer used from the PL 3-timer core */ + uint8_t active_tmr; + /** Platform selection parameter */ + enum xil_timer_type type; +}; + +/** + * @struct xil_timer_init_param + * @brief Xilinx specific timer initialization structure + */ +struct xil_timer_init_param { + /** Timer used from the PL 3-timer core */ + uint8_t active_tmr; + /** Platform selection parameter */ + enum xil_timer_type type; +}; + +/** + * @brief Xilinx platform specific timer platform ops structure + */ +extern const struct timer_platform_ops xil_timer_ops; + +#endif /* XILINX_TIMER_H_ */ diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/rf-transceiver/ad9361/ad9361.c b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/rf-transceiver/ad9361/ad9361.c new file mode 100644 index 0000000..7a47535 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/rf-transceiver/ad9361/ad9361.c @@ -0,0 +1,7475 @@ +/***************************************************************************//** + * @file ad9361.c + * @brief Implementation of AD9361 Driver. +******************************************************************************** + * Copyright 2014-2015(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ +#include +#include +#include +#include +#include +#include +#include "ad9361.h" +#include "ad9361_util.h" +#include "spi.h" +#include "gpio.h" +#include "delay.h" +#include "util.h" +#include "../../../config/app_config.h" + +#define diff_abs(x, y) ((x) > (y) ? (x - y) : (y - x)) + +#define NO_GAIN_TABLE ((uint32_t)-1) + +/* Used for static code size optimization: please see app_config.h */ +const bool has_split_gt = HAVE_SPLIT_GAIN_TABLE; +const bool have_tdd_tables = HAVE_TDD_SYNTH_TABLE; + +#define SYNTH_LUT_SIZE 53 + +static const struct SynthLUT SynthLUT_FDD[LUT_FTDD_ENT][SYNTH_LUT_SIZE] = { + { + {12605, 13, 1, 4, 2, 15, 12, 7, 14, 6, 14, 5, 15}, /* 40 MHz */ + {12245, 13, 1, 4, 2, 15, 12, 7, 14, 6, 14, 5, 15}, + {11906, 13, 1, 4, 2, 15, 12, 7, 15, 6, 14, 5, 15}, + {11588, 13, 1, 4, 2, 15, 12, 8, 15, 6, 14, 5, 15}, + {11288, 13, 1, 4, 2, 15, 12, 8, 15, 6, 14, 5, 15}, + {11007, 13, 1, 4, 2, 15, 12, 9, 15, 6, 14, 5, 15}, + {10742, 13, 1, 4, 2, 15, 12, 9, 15, 6, 14, 5, 15}, + {10492, 13, 1, 6, 2, 15, 12, 10, 15, 6, 14, 5, 15}, + {10258, 13, 1, 6, 2, 15, 12, 10, 15, 6, 14, 5, 15}, + {10036, 13, 1, 6, 2, 15, 12, 11, 15, 6, 14, 5, 15}, + {9827, 13, 1, 6, 2, 14, 12, 11, 15, 6, 14, 5, 15}, + {9631, 13, 1, 6, 2, 13, 12, 12, 15, 6, 14, 5, 15}, + {9445, 13, 1, 6, 2, 12, 12, 12, 15, 6, 14, 5, 15}, + {9269, 13, 1, 6, 2, 12, 12, 13, 15, 6, 14, 5, 15}, + {9103, 13, 1, 6, 2, 12, 12, 13, 15, 6, 14, 5, 15}, + {8946, 13, 1, 6, 2, 12, 12, 14, 15, 6, 14, 5, 15}, + {8797, 12, 1, 7, 2, 12, 12, 13, 15, 6, 14, 5, 15}, + {8655, 12, 1, 7, 2, 12, 12, 14, 15, 6, 14, 5, 15}, + {8520, 12, 1, 7, 2, 12, 12, 14, 15, 6, 14, 5, 15}, + {8392, 12, 1, 7, 2, 12, 12, 15, 15, 6, 14, 5, 15}, + {8269, 12, 1, 7, 2, 12, 12, 15, 15, 6, 14, 5, 15}, + {8153, 12, 1, 7, 2, 12, 12, 16, 15, 6, 14, 5, 15}, + {8041, 12, 1, 7, 2, 13, 12, 16, 15, 6, 14, 5, 15}, + {7934, 11, 1, 7, 2, 12, 12, 16, 15, 6, 14, 5, 15}, + {7831, 11, 1, 7, 2, 12, 12, 16, 15, 6, 14, 5, 15}, + {7733, 10, 1, 7, 3, 13, 12, 16, 15, 6, 14, 5, 15}, + {7638, 10, 1, 7, 2, 12, 12, 16, 15, 6, 14, 5, 15}, + {7547, 10, 1, 7, 2, 12, 12, 17, 15, 6, 14, 5, 15}, + {7459, 10, 1, 7, 2, 12, 12, 17, 15, 6, 14, 5, 15}, + {7374, 10, 2, 7, 3, 14, 13, 14, 15, 6, 14, 5, 15}, + {7291, 10, 2, 7, 3, 14, 13, 14, 15, 6, 14, 5, 15}, + {7212, 10, 2, 7, 3, 14, 13, 14, 15, 6, 14, 5, 15}, + {7135, 10, 2, 7, 3, 14, 13, 15, 15, 7, 14, 5, 15}, + {7061, 10, 2, 7, 3, 14, 13, 15, 15, 6, 14, 5, 15}, + {6988, 10, 1, 7, 3, 12, 14, 20, 15, 6, 14, 5, 15}, + {6918, 9, 2, 7, 3, 14, 13, 15, 15, 6, 14, 5, 15}, + {6850, 9, 2, 7, 3, 14, 13, 15, 15, 6, 14, 5, 15}, + {6784, 9, 2, 7, 2, 13, 13, 15, 15, 6, 14, 5, 15}, + {6720, 9, 2, 7, 2, 13, 13, 16, 15, 6, 14, 5, 15}, + {6658, 8, 2, 7, 3, 14, 13, 15, 15, 6, 14, 5, 15}, + {6597, 8, 2, 7, 2, 13, 13, 15, 15, 6, 14, 5, 15}, + {6539, 8, 2, 7, 2, 13, 13, 15, 15, 6, 14, 5, 15}, + {6482, 8, 2, 7, 2, 13, 13, 16, 15, 6, 14, 5, 15}, + {6427, 7, 2, 7, 3, 14, 13, 15, 15, 6, 14, 5, 15}, + {6373, 7, 2, 7, 3, 15, 13, 15, 15, 6, 14, 5, 15}, + {6321, 7, 2, 7, 3, 15, 13, 15, 15, 6, 14, 5, 15}, + {6270, 7, 2, 7, 3, 15, 13, 16, 15, 6, 14, 5, 15}, + {6222, 7, 2, 7, 3, 15, 13, 16, 15, 6, 14, 5, 15}, + {6174, 6, 2, 7, 3, 15, 13, 15, 15, 6, 14, 5, 15}, + {6128, 6, 2, 7, 3, 15, 13, 15, 15, 6, 14, 5, 15}, + {6083, 6, 2, 7, 3, 15, 13, 16, 15, 6, 14, 5, 15}, + {6040, 6, 2, 7, 3, 15, 13, 16, 15, 6, 14, 5, 15}, + {5997, 6, 2, 7, 3, 15, 13, 16, 15, 6, 14, 5, 15}, + }, { + {12605, 13, 1, 4, 2, 15, 12, 13, 15, 12, 12, 5, 14}, /* 60 MHz */ + {12245, 13, 1, 4, 2, 15, 12, 13, 15, 12, 12, 5, 14}, + {11906, 13, 1, 4, 2, 15, 12, 13, 15, 13, 12, 5, 13}, + {11588, 13, 1, 4, 2, 15, 12, 14, 15, 13, 12, 5, 13}, + {11288, 13, 1, 5, 2, 15, 12, 15, 15, 13, 12, 5, 13}, + {11007, 13, 1, 5, 2, 15, 12, 16, 15, 13, 12, 5, 13}, + {10742, 13, 1, 5, 2, 15, 12, 16, 15, 12, 12, 5, 14}, + {10492, 13, 1, 6, 2, 15, 12, 17, 15, 12, 12, 5, 14}, + {10258, 13, 1, 6, 2, 15, 12, 18, 15, 13, 12, 5, 13}, + {10036, 13, 1, 6, 2, 15, 12, 19, 15, 13, 12, 5, 13}, + {9827, 13, 1, 6, 2, 14, 12, 20, 15, 13, 12, 5, 13}, + {9631, 13, 1, 6, 2, 13, 12, 21, 15, 13, 12, 5, 13}, + {9445, 13, 1, 6, 2, 12, 12, 22, 15, 13, 12, 5, 13}, + {9269, 13, 1, 6, 2, 12, 12, 22, 15, 12, 12, 5, 14}, + {9103, 13, 1, 6, 2, 12, 12, 23, 15, 13, 12, 5, 13}, + {8946, 13, 1, 6, 2, 12, 12, 24, 15, 13, 12, 5, 13}, + {8797, 12, 1, 7, 2, 12, 12, 24, 15, 13, 12, 5, 13}, + {8655, 12, 1, 7, 2, 12, 12, 25, 15, 13, 12, 5, 13}, + {8520, 12, 1, 7, 2, 12, 12, 25, 15, 13, 12, 5, 13}, + {8392, 12, 1, 7, 2, 12, 12, 26, 15, 13, 12, 5, 13}, + {8269, 12, 1, 7, 2, 12, 12, 27, 15, 13, 12, 5, 13}, + {8153, 12, 1, 7, 2, 12, 12, 28, 15, 13, 12, 5, 13}, + {8041, 12, 1, 7, 2, 13, 12, 29, 15, 13, 12, 5, 13}, + {7934, 11, 1, 7, 2, 12, 12, 28, 15, 13, 12, 5, 13}, + {7831, 11, 1, 7, 2, 12, 12, 29, 15, 13, 12, 5, 13}, + {7733, 10, 1, 7, 3, 13, 12, 28, 15, 13, 12, 5, 13}, + {7638, 10, 1, 7, 2, 12, 12, 29, 15, 13, 12, 5, 13}, + {7547, 10, 1, 7, 2, 12, 12, 29, 15, 13, 12, 5, 13}, + {7459, 10, 1, 7, 2, 12, 12, 30, 15, 13, 12, 5, 13}, + {7374, 10, 2, 7, 3, 14, 13, 24, 15, 13, 12, 5, 13}, + {7291, 10, 2, 7, 3, 14, 13, 25, 15, 13, 12, 5, 13}, + {7212, 10, 2, 7, 3, 14, 13, 25, 15, 13, 12, 5, 13}, + {7135, 10, 2, 7, 3, 14, 13, 26, 15, 13, 12, 5, 13}, + {7061, 10, 2, 7, 3, 14, 13, 26, 15, 13, 12, 5, 13}, + {6988, 10, 1, 7, 3, 12, 14, 35, 15, 13, 12, 5, 13}, + {6918, 9, 1, 7, 3, 12, 14, 33, 15, 13, 12, 5, 13}, + {6850, 9, 1, 7, 3, 12, 14, 34, 15, 13, 12, 5, 13}, + {6784, 9, 1, 7, 2, 11, 14, 35, 15, 13, 12, 5, 13}, + {6720, 9, 1, 7, 2, 11, 14, 35, 15, 13, 12, 5, 13}, + {6658, 8, 2, 7, 3, 15, 13, 26, 15, 13, 12, 5, 13}, + {6597, 8, 2, 7, 2, 15, 13, 27, 15, 13, 12, 5, 13}, + {6539, 8, 2, 7, 2, 15, 13, 27, 15, 13, 12, 5, 13}, + {6482, 8, 2, 7, 2, 15, 13, 28, 15, 13, 12, 5, 13}, + {6427, 7, 2, 7, 3, 14, 13, 27, 15, 13, 12, 5, 13}, + {6373, 7, 2, 7, 3, 15, 13, 27, 15, 13, 12, 5, 13}, + {6321, 7, 2, 7, 3, 15, 13, 27, 15, 13, 12, 5, 13}, + {6270, 7, 2, 7, 3, 15, 13, 28, 15, 13, 12, 5, 13}, + {6222, 7, 2, 7, 3, 15, 13, 28, 15, 13, 12, 5, 13}, + {6174, 6, 2, 7, 3, 15, 13, 27, 15, 13, 12, 5, 13}, + {6128, 6, 2, 7, 3, 15, 13, 27, 15, 13, 12, 5, 13}, + {6083, 6, 2, 7, 3, 15, 13, 28, 15, 13, 12, 5, 13}, + {6040, 6, 2, 7, 3, 15, 13, 28, 15, 13, 12, 5, 13}, + {5997, 6, 2, 7, 3, 15, 13, 29, 15, 13, 12, 5, 13}, + }, { + {12605, 13, 1, 4, 2, 15, 12, 7, 15, 6, 13, 5, 14}, /* 80 MHz */ + {12245, 13, 1, 4, 2, 15, 12, 7, 15, 6, 13, 5, 14}, + {11906, 13, 1, 4, 2, 15, 12, 7, 15, 6, 13, 5, 14}, + {11588, 13, 1, 4, 2, 15, 12, 7, 14, 6, 14, 4, 14}, + {11288, 13, 1, 4, 2, 15, 12, 8, 15, 6, 13, 5, 14}, + {11007, 13, 1, 4, 2, 15, 12, 8, 14, 6, 13, 5, 14}, + {10742, 13, 1, 4, 2, 15, 12, 9, 15, 6, 13, 5, 14}, + {10492, 13, 1, 6, 2, 15, 12, 9, 14, 6, 13, 5, 14}, + {10258, 13, 1, 6, 2, 15, 12, 10, 15, 6, 13, 5, 14}, + {10036, 13, 1, 6, 2, 15, 12, 10, 15, 6, 13, 5, 14}, + {9827, 13, 1, 6, 2, 14, 12, 11, 15, 6, 13, 5, 14}, + {9631, 13, 1, 6, 2, 13, 12, 11, 15, 6, 13, 5, 14}, + {9445, 13, 1, 6, 2, 12, 12, 12, 15, 6, 13, 5, 14}, + {9269, 13, 1, 6, 2, 12, 12, 12, 15, 6, 13, 5, 14}, + {9103, 13, 1, 6, 2, 12, 12, 13, 15, 6, 13, 5, 14}, + {8946, 13, 1, 6, 2, 12, 12, 13, 15, 6, 13, 5, 14}, + {8797, 12, 1, 7, 2, 12, 12, 13, 15, 6, 13, 5, 14}, + {8655, 12, 1, 7, 2, 12, 12, 14, 15, 6, 13, 5, 14}, + {8520, 12, 1, 7, 2, 12, 12, 14, 15, 6, 13, 5, 14}, + {8392, 12, 1, 7, 2, 12, 12, 15, 15, 7, 13, 5, 14}, + {8269, 12, 1, 7, 2, 12, 12, 15, 15, 6, 13, 5, 14}, + {8153, 12, 1, 7, 2, 12, 12, 15, 15, 6, 13, 5, 14}, + {8041, 12, 1, 7, 2, 13, 12, 16, 15, 6, 13, 5, 14}, + {7934, 11, 1, 7, 2, 12, 12, 15, 15, 6, 13, 5, 14}, + {7831, 11, 1, 7, 2, 12, 12, 16, 15, 6, 13, 5, 14}, + {7733, 10, 1, 7, 3, 13, 12, 15, 15, 6, 13, 5, 14}, + {7638, 10, 1, 7, 2, 12, 12, 16, 15, 6, 13, 5, 14}, + {7547, 10, 1, 7, 2, 12, 12, 16, 15, 6, 13, 5, 14}, + {7459, 10, 1, 7, 2, 12, 12, 17, 15, 6, 13, 5, 14}, + {7374, 10, 2, 7, 3, 14, 13, 13, 15, 6, 13, 5, 14}, + {7291, 10, 2, 7, 3, 14, 13, 14, 15, 6, 13, 5, 14}, + {7212, 10, 2, 7, 3, 14, 13, 14, 15, 6, 13, 5, 14}, + {7135, 10, 2, 7, 3, 14, 13, 14, 15, 6, 13, 5, 14}, + {7061, 10, 2, 7, 3, 14, 13, 15, 15, 6, 13, 5, 14}, + {6988, 10, 1, 7, 3, 12, 14, 19, 15, 6, 13, 5, 14}, + {6918, 9, 2, 7, 3, 14, 13, 14, 15, 6, 13, 5, 14}, + {6850, 9, 2, 7, 3, 14, 13, 15, 15, 6, 13, 5, 14}, + {6784, 9, 2, 7, 2, 13, 13, 15, 15, 6, 13, 5, 14}, + {6720, 9, 2, 7, 2, 13, 13, 15, 15, 6, 13, 5, 14}, + {6658, 8, 2, 7, 3, 14, 13, 15, 15, 6, 13, 5, 14}, + {6597, 8, 2, 7, 2, 13, 13, 15, 15, 6, 13, 5, 14}, + {6539, 8, 2, 7, 2, 13, 13, 15, 15, 6, 13, 5, 14}, + {6482, 8, 2, 7, 2, 13, 13, 15, 15, 6, 13, 5, 14}, + {6427, 7, 2, 7, 3, 14, 13, 15, 15, 6, 13, 5, 14}, + {6373, 7, 2, 7, 3, 15, 13, 15, 15, 6, 13, 5, 14}, + {6321, 7, 2, 7, 3, 15, 13, 15, 15, 6, 13, 5, 14}, + {6270, 7, 2, 7, 3, 15, 13, 15, 15, 6, 13, 5, 14}, + {6222, 7, 2, 7, 3, 15, 13, 16, 15, 6, 13, 5, 14}, + {6174, 6, 2, 7, 3, 15, 13, 15, 15, 6, 13, 5, 14}, + {6128, 6, 2, 7, 3, 15, 13, 15, 15, 6, 13, 5, 14}, + {6083, 6, 2, 7, 3, 15, 13, 15, 15, 6, 13, 5, 14}, + {6040, 6, 2, 7, 3, 15, 13, 16, 15, 6, 13, 5, 14}, + {5997, 6, 2, 7, 3, 15, 13, 16, 15, 6, 13, 5, 14}, + } +}; + +static const struct SynthLUT SynthLUT_TDD[LUT_FTDD_ENT][SYNTH_LUT_SIZE] = { + { + {12605, 13, 1, 4, 2, 15, 12, 27, 12, 15, 12, 4, 13}, /* 40 MHz */ + {12245, 13, 1, 4, 2, 15, 12, 27, 12, 15, 12, 4, 13}, + {11906, 13, 1, 4, 2, 15, 12, 26, 11, 15, 12, 4, 13}, + {11588, 13, 1, 4, 2, 15, 12, 28, 12, 15, 12, 4, 13}, + {11288, 13, 1, 4, 2, 15, 12, 30, 12, 15, 12, 4, 13}, + {11007, 13, 1, 4, 2, 15, 12, 32, 12, 15, 12, 4, 13}, + {10742, 13, 1, 4, 2, 15, 12, 33, 12, 15, 12, 4, 13}, + {10492, 13, 1, 6, 2, 15, 12, 35, 12, 15, 12, 4, 13}, + {10258, 13, 1, 6, 2, 15, 12, 37, 12, 15, 12, 4, 13}, + {10036, 13, 1, 6, 2, 15, 12, 38, 12, 15, 12, 4, 13}, + {9827, 13, 1, 6, 2, 14, 12, 40, 12, 15, 12, 4, 13}, + {9631, 13, 1, 6, 2, 13, 12, 42, 12, 15, 12, 4, 13}, + {9445, 13, 1, 6, 2, 12, 12, 44, 12, 15, 12, 4, 13}, + {9269, 13, 1, 6, 2, 12, 12, 45, 12, 15, 12, 4, 13}, + {9103, 13, 1, 6, 2, 12, 12, 47, 12, 15, 12, 4, 13}, + {8946, 13, 1, 6, 2, 12, 12, 49, 12, 15, 12, 4, 13}, + {8797, 12, 1, 7, 2, 12, 12, 48, 12, 15, 12, 4, 13}, + {8655, 12, 1, 7, 2, 12, 12, 50, 12, 15, 12, 4, 13}, + {8520, 12, 1, 7, 2, 12, 12, 51, 12, 15, 12, 4, 13}, + {8392, 12, 1, 7, 2, 12, 12, 53, 12, 15, 12, 4, 13}, + {8269, 12, 1, 7, 2, 12, 12, 55, 12, 15, 12, 4, 13}, + {8153, 12, 1, 7, 2, 12, 12, 56, 12, 15, 12, 4, 13}, + {8041, 12, 1, 7, 2, 13, 12, 58, 12, 15, 12, 4, 13}, + {7934, 11, 1, 7, 2, 12, 12, 57, 12, 15, 12, 4, 13}, + {7831, 11, 1, 7, 2, 12, 12, 58, 12, 15, 12, 4, 13}, + {7733, 10, 1, 7, 3, 13, 12, 56, 12, 15, 12, 4, 13}, + {7638, 10, 1, 7, 2, 12, 12, 58, 12, 15, 12, 4, 13}, + {7547, 10, 1, 7, 2, 12, 12, 59, 12, 15, 12, 4, 13}, + {7459, 10, 1, 7, 2, 12, 12, 61, 12, 15, 12, 4, 13}, + {7374, 10, 2, 7, 3, 14, 13, 49, 12, 15, 12, 4, 13}, + {7291, 10, 2, 7, 3, 14, 13, 50, 12, 15, 12, 4, 13}, + {7212, 10, 2, 7, 3, 14, 13, 51, 12, 15, 12, 4, 13}, + {7135, 10, 2, 7, 3, 14, 13, 52, 12, 15, 12, 4, 13}, + {7061, 10, 2, 7, 3, 14, 13, 53, 12, 15, 12, 4, 13}, + {6988, 10, 1, 7, 3, 12, 14, 63, 11, 14, 12, 3, 13}, + {6918, 9, 2, 7, 3, 14, 13, 52, 12, 15, 12, 4, 13}, + {6850, 9, 2, 7, 3, 14, 13, 53, 12, 15, 12, 4, 13}, + {6784, 9, 2, 7, 2, 13, 13, 54, 12, 15, 12, 4, 13}, + {6720, 9, 2, 7, 2, 13, 13, 56, 12, 15, 12, 4, 13}, + {6658, 8, 2, 7, 3, 14, 13, 53, 12, 15, 12, 4, 13}, + {6597, 8, 2, 7, 2, 13, 13, 54, 12, 15, 12, 4, 13}, + {6539, 8, 2, 7, 2, 13, 13, 55, 12, 15, 12, 4, 13}, + {6482, 8, 2, 7, 2, 13, 13, 56, 12, 15, 12, 4, 13}, + {6427, 7, 2, 7, 3, 14, 13, 54, 12, 15, 12, 4, 13}, + {6373, 7, 2, 7, 3, 15, 13, 54, 12, 15, 12, 4, 13}, + {6321, 7, 2, 7, 3, 15, 13, 55, 12, 15, 12, 4, 13}, + {6270, 7, 2, 7, 3, 15, 13, 56, 12, 15, 12, 4, 13}, + {6222, 7, 2, 7, 3, 15, 13, 57, 12, 15, 12, 4, 13}, + {6174, 6, 2, 7, 3, 15, 13, 54, 12, 15, 12, 4, 13}, + {6128, 6, 2, 7, 3, 15, 13, 55, 12, 15, 12, 4, 13}, + {6083, 6, 2, 7, 3, 15, 13, 56, 12, 15, 12, 4, 13}, + {6040, 6, 2, 7, 3, 15, 13, 57, 12, 15, 12, 4, 13}, + {5997, 6, 2, 7, 3, 15, 13, 58, 12, 15, 12, 4, 13}, + }, { + {12605, 13, 1, 4, 2, 15, 12, 26, 11, 15, 11, 4, 13}, /* 60 MHz */ + {12245, 13, 1, 4, 2, 15, 12, 26, 11, 15, 11, 4, 13}, + {11906, 13, 1, 4, 2, 15, 12, 26, 12, 15, 11, 4, 12}, + {11588, 13, 1, 4, 2, 15, 12, 30, 12, 15, 11, 4, 12}, + {11288, 13, 1, 4, 2, 15, 12, 32, 12, 15, 10, 4, 12}, + {11007, 13, 1, 4, 2, 15, 12, 31, 12, 15, 11, 4, 12}, + {10742, 13, 1, 4, 2, 15, 12, 33, 12, 15, 10, 4, 12}, + {10492, 13, 1, 6, 2, 15, 12, 37, 12, 15, 10, 4, 12}, + {10258, 13, 1, 6, 2, 15, 12, 38, 12, 15, 11, 4, 13}, + {10036, 13, 1, 6, 2, 15, 12, 38, 12, 15, 10, 4, 12}, + {9827, 13, 1, 6, 2, 14, 12, 42, 12, 15, 11, 4, 12}, + {9631, 13, 1, 6, 2, 13, 12, 41, 12, 15, 11, 4, 12}, + {9445, 13, 1, 6, 2, 12, 12, 45, 12, 15, 11, 4, 12}, + {9269, 13, 1, 6, 2, 12, 12, 47, 12, 15, 11, 4, 12}, + {9103, 13, 1, 6, 2, 12, 12, 46, 12, 15, 11, 4, 12}, + {8946, 13, 1, 6, 2, 12, 12, 48, 12, 15, 10, 4, 12}, + {8797, 12, 1, 7, 2, 12, 12, 49, 12, 15, 11, 4, 13}, + {8655, 12, 1, 7, 2, 12, 12, 51, 12, 15, 11, 4, 12}, + {8520, 12, 1, 7, 2, 12, 12, 50, 12, 15, 11, 4, 12}, + {8392, 12, 1, 7, 2, 12, 12, 52, 12, 15, 10, 4, 12}, + {8269, 12, 1, 7, 2, 12, 12, 56, 12, 15, 10, 4, 12}, + {8153, 12, 1, 7, 2, 12, 12, 55, 12, 15, 11, 4, 12}, + {8041, 12, 1, 7, 2, 13, 12, 57, 12, 15, 10, 4, 12}, + {7934, 11, 1, 7, 2, 12, 12, 55, 12, 15, 11, 4, 12}, + {7831, 11, 1, 7, 2, 12, 12, 57, 12, 15, 10, 4, 12}, + {7733, 10, 1, 7, 3, 13, 12, 55, 12, 15, 11, 4, 12}, + {7638, 10, 1, 7, 2, 12, 12, 59, 12, 15, 10, 4, 12}, + {7547, 10, 1, 7, 2, 12, 12, 60, 12, 15, 11, 4, 12}, + {7459, 10, 1, 7, 2, 12, 12, 48, 12, 15, 11, 4, 12}, + {7374, 10, 2, 7, 3, 14, 13, 47, 12, 15, 11, 4, 13}, + {7291, 10, 2, 7, 3, 14, 13, 49, 12, 15, 10, 4, 12}, + {7212, 10, 2, 7, 3, 14, 13, 50, 12, 15, 10, 4, 12}, + {7135, 10, 2, 7, 3, 14, 13, 52, 12, 15, 11, 4, 13}, + {7061, 10, 2, 7, 3, 14, 13, 52, 12, 15, 11, 4, 12}, + {6988, 10, 1, 7, 3, 12, 14, 63, 11, 15, 11, 4, 13}, + {6918, 9, 1, 7, 3, 12, 14, 63, 11, 15, 11, 4, 13}, + {6850, 9, 1, 7, 3, 12, 14, 63, 11, 15, 11, 4, 13}, + {6784, 9, 1, 7, 2, 11, 14, 63, 11, 15, 11, 4, 13}, + {6720, 9, 1, 7, 2, 11, 14, 63, 11, 14, 11, 3, 13}, + {6658, 8, 1, 7, 3, 12, 14, 63, 11, 15, 11, 4, 13}, + {6597, 8, 1, 7, 2, 11, 14, 63, 11, 14, 11, 3, 13}, + {6539, 8, 1, 7, 2, 11, 14, 63, 10, 14, 11, 3, 13}, + {6482, 8, 1, 7, 2, 11, 14, 63, 10, 14, 11, 3, 13}, + {6427, 7, 2, 7, 3, 14, 13, 54, 12, 15, 10, 4, 12}, + {6373, 7, 2, 7, 3, 15, 13, 53, 12, 15, 11, 4, 12}, + {6321, 7, 2, 7, 3, 15, 13, 54, 12, 15, 11, 4, 12}, + {6270, 7, 2, 7, 3, 15, 13, 55, 12, 15, 11, 4, 12}, + {6222, 7, 2, 7, 3, 15, 13, 56, 12, 15, 11, 4, 12}, + {6174, 6, 2, 7, 3, 15, 13, 53, 12, 15, 11, 4, 12}, + {6128, 6, 2, 7, 3, 15, 13, 55, 12, 15, 11, 4, 12}, + {6083, 6, 2, 7, 3, 15, 13, 55, 12, 15, 10, 4, 12}, + {6040, 6, 2, 7, 3, 15, 13, 56, 12, 15, 10, 4, 12}, + {5997, 6, 2, 7, 3, 15, 13, 57, 12, 15, 10, 4, 12}, + }, { + {12605, 13, 1, 4, 2, 15, 12, 21, 12, 15, 11, 4, 13}, /* 80 MHz */ + {12245, 13, 1, 4, 2, 15, 12, 21, 12, 15, 11, 4, 13}, + {11906, 13, 1, 4, 2, 15, 12, 20, 11, 15, 11, 4, 13}, + {11588, 13, 1, 4, 2, 15, 12, 22, 12, 15, 11, 4, 12}, + {11288, 13, 1, 5, 2, 15, 12, 23, 12, 15, 11, 4, 13}, + {11007, 13, 1, 5, 2, 15, 12, 25, 12, 15, 10, 4, 12}, + {10742, 13, 1, 5, 2, 15, 12, 26, 12, 15, 11, 4, 13}, + {10492, 13, 1, 6, 2, 15, 12, 27, 11, 15, 11, 4, 13}, + {10258, 13, 1, 6, 2, 15, 12, 29, 12, 15, 10, 4, 12}, + {10036, 13, 1, 6, 2, 15, 12, 30, 12, 15, 11, 4, 12}, + {9827, 13, 1, 6, 2, 14, 12, 31, 12, 15, 11, 4, 13}, + {9631, 13, 1, 6, 2, 13, 12, 33, 12, 15, 10, 4, 12}, + {9445, 13, 1, 6, 2, 12, 12, 34, 12, 15, 11, 4, 12}, + {9269, 13, 1, 6, 2, 12, 12, 35, 12, 15, 11, 4, 13}, + {9103, 13, 1, 6, 2, 12, 12, 37, 12, 15, 10, 4, 12}, + {8946, 13, 1, 6, 2, 12, 12, 38, 12, 15, 11, 4, 12}, + {8797, 12, 1, 7, 2, 12, 12, 37, 12, 15, 11, 4, 13}, + {8655, 12, 1, 7, 2, 12, 12, 39, 12, 15, 11, 4, 12}, + {8520, 12, 1, 7, 2, 12, 12, 40, 12, 15, 11, 4, 12}, + {8392, 12, 1, 7, 2, 12, 12, 41, 12, 15, 11, 4, 13}, + {8269, 12, 1, 7, 2, 12, 12, 43, 12, 15, 10, 4, 12}, + {8153, 12, 1, 7, 2, 12, 12, 44, 12, 15, 11, 4, 12}, + {8041, 12, 1, 7, 2, 13, 12, 45, 12, 15, 11, 4, 12}, + {7934, 11, 1, 7, 2, 12, 12, 44, 12, 15, 11, 4, 12}, + {7831, 11, 1, 7, 2, 12, 12, 45, 12, 15, 11, 4, 13}, + {7733, 10, 1, 7, 3, 13, 12, 44, 12, 15, 11, 4, 12}, + {7638, 10, 1, 7, 2, 12, 12, 45, 12, 15, 11, 4, 12}, + {7547, 10, 1, 7, 2, 12, 12, 46, 12, 15, 11, 4, 12}, + {7459, 10, 1, 7, 2, 12, 12, 47, 12, 15, 11, 4, 13}, + {7374, 10, 2, 7, 3, 14, 13, 38, 12, 15, 11, 4, 12}, + {7291, 10, 2, 7, 3, 14, 13, 39, 12, 15, 10, 4, 12}, + {7212, 10, 2, 7, 3, 14, 13, 40, 12, 15, 10, 4, 12}, + {7135, 10, 2, 7, 3, 14, 13, 41, 12, 15, 10, 4, 12}, + {7061, 10, 2, 7, 3, 14, 13, 41, 12, 15, 11, 4, 13}, + {6988, 10, 1, 7, 3, 12, 14, 54, 12, 15, 11, 4, 12}, + {6918, 9, 2, 7, 3, 14, 13, 41, 12, 15, 10, 4, 12}, + {6850, 9, 2, 7, 3, 14, 13, 42, 12, 15, 10, 4, 12}, + {6784, 9, 2, 7, 2, 13, 13, 42, 12, 15, 11, 4, 13}, + {6720, 9, 2, 7, 2, 13, 13, 43, 12, 15, 11, 4, 13}, + {6658, 8, 2, 7, 3, 14, 13, 41, 12, 15, 11, 4, 13}, + {6597, 8, 2, 7, 2, 13, 13, 42, 12, 15, 11, 4, 12}, + {6539, 8, 2, 7, 2, 13, 13, 43, 12, 15, 11, 4, 12}, + {6482, 8, 2, 7, 2, 13, 13, 44, 12, 15, 11, 4, 12}, + {6427, 7, 2, 7, 3, 14, 13, 42, 12, 15, 10, 4, 12}, + {6373, 7, 2, 7, 3, 15, 13, 42, 12, 15, 11, 4, 13}, + {6321, 7, 2, 7, 3, 15, 13, 43, 12, 15, 11, 4, 12}, + {6270, 7, 2, 7, 3, 15, 13, 44, 12, 15, 11, 4, 12}, + {6222, 7, 2, 7, 3, 15, 13, 45, 12, 15, 10, 4, 12}, + {6174, 6, 2, 7, 3, 15, 13, 42, 12, 15, 11, 4, 13}, + {6128, 6, 2, 7, 3, 15, 13, 43, 12, 15, 11, 4, 12}, + {6083, 6, 2, 7, 3, 15, 13, 44, 12, 15, 10, 4, 12}, + {6040, 6, 2, 7, 3, 15, 13, 44, 12, 15, 11, 4, 13}, + {5997, 6, 2, 7, 3, 15, 13, 45, 12, 15, 11, 4, 12}, + } +}; + +/* Rx Gain Tables */ + +#define SIZE_FULL_TABLE 77 + +static const uint8_t full_gain_table[RXGAIN_TBLS_END][SIZE_FULL_TABLE][3] = { + { /* 800 MHz */ + {0x00, 0x00, 0x20}, {0x00, 0x00, 0x00}, {0x00, 0x00, 0x00}, + {0x00, 0x01, 0x00}, {0x00, 0x02, 0x00}, {0x00, 0x03, 0x00}, + {0x00, 0x04, 0x00}, {0x00, 0x05, 0x00}, {0x01, 0x03, 0x20}, + {0x01, 0x04, 0x00}, {0x01, 0x05, 0x00}, {0x01, 0x06, 0x00}, + {0x01, 0x07, 0x00}, {0x01, 0x08, 0x00}, {0x01, 0x09, 0x00}, + {0x01, 0x0A, 0x00}, {0x01, 0x0B, 0x00}, {0x01, 0x0C, 0x00}, + {0x01, 0x0D, 0x00}, {0x01, 0x0E, 0x00}, {0x02, 0x09, 0x20}, + {0x02, 0x0A, 0x00}, {0x02, 0x0B, 0x00}, {0x02, 0x0C, 0x00}, + {0x02, 0x0D, 0x00}, {0x02, 0x0E, 0x00}, {0x02, 0x0F, 0x00}, + {0x02, 0x10, 0x00}, {0x02, 0x2B, 0x20}, {0x02, 0x2C, 0x00}, + {0x04, 0x28, 0x20}, {0x04, 0x29, 0x00}, {0x04, 0x2A, 0x00}, + {0x04, 0x2B, 0x00}, {0x24, 0x20, 0x20}, {0x24, 0x21, 0x00}, + {0x44, 0x20, 0x20}, {0x44, 0x21, 0x00}, {0x44, 0x22, 0x00}, + {0x44, 0x23, 0x00}, {0x44, 0x24, 0x00}, {0x44, 0x25, 0x00}, + {0x44, 0x26, 0x00}, {0x44, 0x27, 0x00}, {0x44, 0x28, 0x00}, + {0x44, 0x29, 0x00}, {0x44, 0x2A, 0x00}, {0x44, 0x2B, 0x00}, + {0x44, 0x2C, 0x00}, {0x44, 0x2D, 0x00}, {0x44, 0x2E, 0x00}, + {0x44, 0x2F, 0x00}, {0x44, 0x30, 0x00}, {0x44, 0x31, 0x00}, + {0x44, 0x32, 0x00}, {0x64, 0x2E, 0x20}, {0x64, 0x2F, 0x00}, + {0x64, 0x30, 0x00}, {0x64, 0x31, 0x00}, {0x64, 0x32, 0x00}, + {0x64, 0x33, 0x00}, {0x64, 0x34, 0x00}, {0x64, 0x35, 0x00}, + {0x64, 0x36, 0x00}, {0x64, 0x37, 0x00}, {0x64, 0x38, 0x00}, + {0x65, 0x38, 0x20}, {0x66, 0x38, 0x20}, {0x67, 0x38, 0x20}, + {0x68, 0x38, 0x20}, {0x69, 0x38, 0x20}, {0x6A, 0x38, 0x20}, + {0x6B, 0x38, 0x20}, {0x6C, 0x38, 0x20}, {0x6D, 0x38, 0x20}, + {0x6E, 0x38, 0x20}, {0x6F, 0x38, 0x20} + },{ /* 2300 MHz */ + {0x00, 0x00, 0x20}, {0x00, 0x00, 0x00}, {0x00, 0x00, 0x00}, + {0x00, 0x01, 0x00}, {0x00, 0x02, 0x00}, {0x00, 0x03, 0x00}, + {0x00, 0x04, 0x00}, {0x00, 0x05, 0x00}, {0x01, 0x03, 0x20}, + {0x01, 0x04, 0x00}, {0x01, 0x05, 0x00}, {0x01, 0x06, 0x00}, + {0x01, 0x07, 0x00}, {0x01, 0x08, 0x00}, {0x01, 0x09, 0x00}, + {0x01, 0x0A, 0x00}, {0x01, 0x0B, 0x00}, {0x01, 0x0C, 0x00}, + {0x01, 0x0D, 0x00}, {0x01, 0x0E, 0x00}, {0x02, 0x09, 0x20}, + {0x02, 0x0A, 0x00}, {0x02, 0x0B, 0x00}, {0x02, 0x0C, 0x00}, + {0x02, 0x0D, 0x00}, {0x02, 0x0E, 0x00}, {0x02, 0x0F, 0x00}, + {0x02, 0x10, 0x00}, {0x02, 0x2B, 0x20}, {0x02, 0x2C, 0x00}, + {0x04, 0x27, 0x20}, {0x04, 0x28, 0x00}, {0x04, 0x29, 0x00}, + {0x04, 0x2A, 0x00}, {0x04, 0x2B, 0x00}, {0x24, 0x21, 0x20}, + {0x24, 0x22, 0x00}, {0x44, 0x20, 0x20}, {0x44, 0x21, 0x00}, + {0x44, 0x22, 0x00}, {0x44, 0x23, 0x00}, {0x44, 0x24, 0x00}, + {0x44, 0x25, 0x00}, {0x44, 0x26, 0x00}, {0x44, 0x27, 0x00}, + {0x44, 0x28, 0x00}, {0x44, 0x29, 0x00}, {0x44, 0x2A, 0x00}, + {0x44, 0x2B, 0x00}, {0x44, 0x2C, 0x00}, {0x44, 0x2D, 0x00}, + {0x44, 0x2E, 0x00}, {0x44, 0x2F, 0x00}, {0x44, 0x30, 0x00}, + {0x44, 0x31, 0x00}, {0x64, 0x2E, 0x20}, {0x64, 0x2F, 0x00}, + {0x64, 0x30, 0x00}, {0x64, 0x31, 0x00}, {0x64, 0x32, 0x00}, + {0x64, 0x33, 0x00}, {0x64, 0x34, 0x00}, {0x64, 0x35, 0x00}, + {0x64, 0x36, 0x00}, {0x64, 0x37, 0x00}, {0x64, 0x38, 0x00}, + {0x65, 0x38, 0x20}, {0x66, 0x38, 0x20}, {0x67, 0x38, 0x20}, + {0x68, 0x38, 0x20}, {0x69, 0x38, 0x20}, {0x6A, 0x38, 0x20}, + {0x6B, 0x38, 0x20}, {0x6C, 0x38, 0x20}, {0x6D, 0x38, 0x20}, + {0x6E, 0x38, 0x20}, {0x6F, 0x38, 0x20}, + },{ /* 5500 MHz */ + {0x00, 0x00, 0x20}, {0x00, 0x00, 0x00}, {0x00, 0x00, 0x00}, + {0x00, 0x00, 0x00}, {0x00, 0x00, 0x00}, {0x00, 0x01, 0x00}, + {0x00, 0x02, 0x00}, {0x00, 0x03, 0x00}, {0x01, 0x01, 0x20}, + {0x01, 0x02, 0x00}, {0x01, 0x03, 0x00}, {0x01, 0x04, 0x20}, + {0x01, 0x05, 0x00}, {0x01, 0x06, 0x00}, {0x01, 0x07, 0x00}, + {0x01, 0x08, 0x00}, {0x01, 0x09, 0x00}, {0x01, 0x0A, 0x00}, + {0x01, 0x0B, 0x00}, {0x01, 0x0C, 0x00}, {0x02, 0x08, 0x20}, + {0x02, 0x09, 0x00}, {0x02, 0x0A, 0x00}, {0x02, 0x0B, 0x20}, + {0x02, 0x0C, 0x00}, {0x02, 0x0D, 0x00}, {0x02, 0x0E, 0x00}, + {0x02, 0x0F, 0x00}, {0x02, 0x2A, 0x20}, {0x02, 0x2B, 0x00}, + {0x04, 0x27, 0x20}, {0x04, 0x28, 0x00}, {0x04, 0x29, 0x00}, + {0x04, 0x2A, 0x00}, {0x04, 0x2B, 0x00}, {0x04, 0x2C, 0x00}, + {0x04, 0x2D, 0x00}, {0x24, 0x20, 0x20}, {0x24, 0x21, 0x00}, + {0x24, 0x22, 0x00}, {0x44, 0x20, 0x20}, {0x44, 0x21, 0x00}, + {0x44, 0x22, 0x00}, {0x44, 0x23, 0x00}, {0x44, 0x24, 0x00}, + {0x44, 0x25, 0x00}, {0x44, 0x26, 0x00}, {0x44, 0x27, 0x00}, + {0x44, 0x28, 0x00}, {0x44, 0x29, 0x00}, {0x44, 0x2A, 0x00}, + {0x44, 0x2B, 0x00}, {0x44, 0x2C, 0x00}, {0x44, 0x2D, 0x00}, + {0x44, 0x2E, 0x00}, {0x64, 0x2E, 0x20}, {0x64, 0x2F, 0x00}, + {0x64, 0x30, 0x00}, {0x64, 0x31, 0x00}, {0x64, 0x32, 0x00}, + {0x64, 0x33, 0x00}, {0x64, 0x34, 0x00}, {0x64, 0x35, 0x00}, + {0x64, 0x36, 0x00}, {0x64, 0x37, 0x00}, {0x64, 0x38, 0x00}, + {0x65, 0x38, 0x20}, {0x66, 0x38, 0x20}, {0x67, 0x38, 0x20}, + {0x68, 0x38, 0x20}, {0x69, 0x38, 0x20}, {0x6A, 0x38, 0x20}, + {0x6B, 0x38, 0x20}, {0x6C, 0x38, 0x20}, {0x6D, 0x38, 0x20}, + {0x6E, 0x38, 0x20}, {0x6F, 0x38, 0x20} + } +}; + +static const int8_t full_gain_table_abs_gain[RXGAIN_TBLS_END][SIZE_FULL_TABLE] = { + { /* 800 MHz */ + -1, -1, -1, 0, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, + 13, 14, 15, 16, 17, 18, 19, 20, + 21, 22, 23, 24, 25, 26, 27, 28, + 29, 30, 31, 32, 33, 34, 35, 36, + 37, 38, 39, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, + 53, 54, 55, 56, 57, 58, 59, 60, + 61, 62, 63, 64, 65, 66, 67, 68, + 69, 70, 71, 72, 73 + }, { /* 2300 MHz */ + -3, -3, -3, -2, -1, 0, 1, 2, + 3, 4, 5, 6, 7, 8, 9, 10, + 11, 12, 13, 14, 15, 16, 17, 18, + 19, 20, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 30, 31, 32, 33, 34, + 35, 36, 37, 38, 39, 40, 41, 42, + 43, 44, 45, 46, 47, 48, 49, 50, + 51, 52, 53, 54, 55, 56, 57, 58, + 59, 60, 61, 62, 63, 64, 65, 66, + 67, 68, 69, 70, 71 + }, { /* 5500 MHz */ + -10, -10, -10, -10, -10, -9, -8, -7, + -6, -5, -4, -3, -2, -1, 0, 1, + 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, + 18, 19, 20, 21, 22, 23, 24, 25, + 26, 27, 28, 29, 30, 31, 32, 33, + 34, 35, 36, 37, 38, 39, 40, 41, + 42, 43, 44, 45, 46, 47, 48, 49, + 50, 51, 52, 53, 54, 55, 56, 57, + 58, 59, 60, 61, 62 + } +}; + +#define SIZE_SPLIT_TABLE 41 + +#if HAVE_SPLIT_GAIN_TABLE +static const uint8_t split_gain_table[RXGAIN_TBLS_END][SIZE_SPLIT_TABLE][3] = { + { /* 800 MHz */ + {0x00, 0x18, 0x20}, {0x00, 0x18, 0x00}, {0x00, 0x18, 0x00}, + {0x00, 0x18, 0x00}, {0x00, 0x18, 0x00}, {0x00, 0x18, 0x00}, + {0x00, 0x18, 0x20}, {0x01, 0x18, 0x20}, {0x02, 0x18, 0x20}, + {0x04, 0x18, 0x20}, {0x04, 0x38, 0x20}, {0x05, 0x38, 0x20}, + {0x06, 0x38, 0x20}, {0x07, 0x38, 0x20}, {0x08, 0x38, 0x20}, + {0x09, 0x38, 0x20}, {0x0A, 0x38, 0x20}, {0x0B, 0x38, 0x20}, + {0x0C, 0x38, 0x20}, {0x0D, 0x38, 0x20}, {0x0E, 0x38, 0x20}, + {0x0F, 0x38, 0x20}, {0x24, 0x38, 0x20}, {0x25, 0x38, 0x20}, + {0x44, 0x38, 0x20}, {0x45, 0x38, 0x20}, {0x46, 0x38, 0x20}, + {0x47, 0x38, 0x20}, {0x48, 0x38, 0x20}, {0x64, 0x38, 0x20}, + {0x65, 0x38, 0x20}, {0x66, 0x38, 0x20}, {0x67, 0x38, 0x20}, + {0x68, 0x38, 0x20}, {0x69, 0x38, 0x20}, {0x6A, 0x38, 0x20}, + {0x6B, 0x38, 0x20}, {0x6C, 0x38, 0x20}, {0x6D, 0x38, 0x20}, + {0x6E, 0x38, 0x20}, {0x6F, 0x38, 0x20}, + },{ /* 2300 MHz */ + {0x00, 0x18, 0x20}, {0x00, 0x18, 0x00}, {0x00, 0x18, 0x00}, + {0x00, 0x18, 0x00}, {0x00, 0x18, 0x00}, {0x00, 0x18, 0x00}, + {0x00, 0x18, 0x00}, {0x00, 0x18, 0x20}, {0x01, 0x18, 0x20}, + {0x02, 0x18, 0x20}, {0x04, 0x18, 0x20}, {0x04, 0x38, 0x20}, + {0x05, 0x38, 0x20}, {0x06, 0x38, 0x20}, {0x07, 0x38, 0x20}, + {0x08, 0x38, 0x20}, {0x09, 0x38, 0x20}, {0x0A, 0x38, 0x20}, + {0x0B, 0x38, 0x20}, {0x0C, 0x38, 0x20}, {0x0D, 0x38, 0x20}, + {0x0E, 0x38, 0x20}, {0x0F, 0x38, 0x20}, {0x25, 0x38, 0x20}, + {0x26, 0x38, 0x20}, {0x44, 0x38, 0x20}, {0x45, 0x38, 0x20}, + {0x46, 0x38, 0x20}, {0x47, 0x38, 0x20}, {0x64, 0x38, 0x20}, + {0x65, 0x38, 0x20}, {0x66, 0x38, 0x20}, {0x67, 0x38, 0x20}, + {0x68, 0x38, 0x20}, {0x69, 0x38, 0x20}, {0x6A, 0x38, 0x20}, + {0x6B, 0x38, 0x20}, {0x6C, 0x38, 0x20}, {0x6D, 0x38, 0x20}, + {0x6E, 0x38, 0x20}, {0x6F, 0x38, 0x20}, + },{ /* 5500 MHz */ + {0x00, 0x18, 0x20}, {0x00, 0x18, 0x00}, {0x00, 0x18, 0x00}, + {0x00, 0x18, 0x00}, {0x00, 0x18, 0x00}, {0x00, 0x18, 0x00}, + {0x00, 0x18, 0x00}, {0x00, 0x18, 0x00}, {0x00, 0x18, 0x00}, + {0x00, 0x18, 0x00}, {0x01, 0x18, 0x20}, {0x02, 0x18, 0x20}, + {0x04, 0x18, 0x20}, {0x04, 0x38, 0x20}, {0x05, 0x38, 0x20}, + {0x06, 0x38, 0x20}, {0x07, 0x38, 0x20}, {0x08, 0x38, 0x20}, + {0x09, 0x38, 0x20}, {0x0A, 0x38, 0x20}, {0x0B, 0x38, 0x20}, + {0x0C, 0x38, 0x20}, {0x0D, 0x38, 0x20}, {0x0E, 0x38, 0x20}, + {0x0F, 0x38, 0x20}, {0x62, 0x38, 0x20}, {0x25, 0x38, 0x20}, + {0x26, 0x38, 0x20}, {0x44, 0x38, 0x20}, {0x64, 0x38, 0x20}, + {0x65, 0x38, 0x20}, {0x66, 0x38, 0x20}, {0x67, 0x38, 0x20}, + {0x68, 0x38, 0x20}, {0x69, 0x38, 0x20}, {0x6A, 0x38, 0x20}, + {0x6B, 0x38, 0x20}, {0x6C, 0x38, 0x20}, {0x6D, 0x38, 0x20}, + {0x6E, 0x38, 0x20}, {0x6F, 0x38, 0x20}, + } +}; + +static const uint8_t +split_gain_table_abs_gain[RXGAIN_TBLS_END][SIZE_SPLIT_TABLE] = { + { /* 800 MHz */ + -1, -1, -1, -1, -1, -1, -1, 2, + 8, 13, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, 32, + 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, + 49 + }, { /* 2300 MHz */ + -3, -3, -3, -3, -3, -3, -3, -3, + 0, 6, 12, 18, 19, 20, 21, 22, + 23, 24, 25, 26, 27, 28, 29, 30, + 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 43, 44, 45, 46, + 47 + }, { /* 5500 MHz */ + -10, -10, -10, -10, -10, -10, -10, -10, + -10, -10, -7, -2, 3, 9, 10, 11, + 12, 13, 14, 15, 16, 17, 18, 19, + 20, 22, 24, 25, 26, 27, 28, 29, + 30, 31, 32, 33, 34, 35, 36, 37, + 38 + } +}; +#endif + +struct gain_table_info ad9361_adi_gt_info[] = { + { + .start = 0, + .end = 1300000000ULL, + .max_index = SIZE_FULL_TABLE, + .abs_gain_tbl = (int8_t *) &full_gain_table_abs_gain[TBL_200_1300_MHZ], + .tab = (uint8_t (*)[3]) full_gain_table[TBL_200_1300_MHZ], + },{ + .start = 1300000000ULL, + .end = 4000000000ULL, + .max_index = SIZE_FULL_TABLE, + .abs_gain_tbl = (int8_t *) &full_gain_table_abs_gain[TBL_1300_4000_MHZ], + .tab = (uint8_t (*)[3]) full_gain_table[TBL_1300_4000_MHZ], + },{ + .start = 4000000000ULL, + .end = 6000000000ULL, + .max_index = SIZE_FULL_TABLE, + .abs_gain_tbl = (int8_t *) &full_gain_table_abs_gain[TBL_4000_6000_MHZ], + .tab = (uint8_t (*)[3]) full_gain_table[TBL_4000_6000_MHZ], +#if HAVE_SPLIT_GAIN_TABLE + },{ + .start = 0, + .end = 1300000000ULL, + .max_index = SIZE_SPLIT_TABLE, + .split_table = 1, + .abs_gain_tbl = (int8_t *) &split_gain_table_abs_gain[TBL_200_1300_MHZ], + .tab = (uint8_t (*)[3]) split_gain_table[TBL_200_1300_MHZ], + },{ + .start = 1300000000ULL, + .end = 4000000000ULL, + .max_index = SIZE_SPLIT_TABLE, + .split_table = 1, + .abs_gain_tbl = (int8_t *) &split_gain_table_abs_gain[TBL_1300_4000_MHZ], + .tab = (uint8_t (*)[3]) split_gain_table[TBL_1300_4000_MHZ], + },{ + .start = 4000000000ULL, + .end = 6000000000ULL, + .max_index = SIZE_SPLIT_TABLE, + .split_table = 1, + .abs_gain_tbl = (int8_t *) &split_gain_table_abs_gain[TBL_4000_6000_MHZ], + .tab = (uint8_t (*)[3]) split_gain_table[TBL_4000_6000_MHZ], +#endif + },{ + .start = 0, + .end = 0, + .max_index = 0, + .split_table = 0, + .abs_gain_tbl = NULL, + .tab = NULL, + }, /* Don't Remove */ +}; + +/* Mixer GM Sub-table */ + +static const uint8_t gm_st_gain[16]= {0x78, 0x74, 0x70, 0x6C, 0x68, 0x64, 0x60, + 0x5C, 0x58, 0x54, 0x50, 0x4C, 0x48, 0x30, 0x18, 0x0}; +static const uint8_t gm_st_ctrl[16]= {0x0, 0xD, 0x15, 0x1B, 0x21, 0x25, 0x29, + 0x2C, 0x2F, 0x31, 0x33, 0x34, 0x35, 0x3A, 0x3D, 0x3E}; + + +static const int8_t lna_table[RXGAIN_TBLS_END][4] = { + {5, 17, 19, 24}, {3, 14, 17, 21}, {-4, 10, 13, 14}}; +static const int8_t tia_table[] = {-6, 0}; +static const int8_t mixer_table[RXGAIN_TBLS_END][16] = { + {0, 3, 9, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25}, + {0, 3, 9, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26}, + {0, 3, 8, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24} +}; + +static const uint32_t gain_step_calib_reg_val[4][5] = { + {0xC0, 0x2E, 0x10, 0x06, 0x00}, // LO Frequency Range: 600 to 1300 MHz + {0xC0, 0x2C, 0x10, 0x06, 0x00}, // LO Frequency Range: 1300 to 3300 MHz + {0xB8, 0x2C, 0x10, 0x06, 0x00}, // LO Frequency Range: 2700 to 4100 MHz + {0xA0, 0x24, 0x10, 0x06, 0x00}, // LO Frequency Range: 4000 to 6000 MHz +}; + +/******************************************************************************/ +/********************** Macros and Constants Definitions **********************/ +/******************************************************************************/ +const char *ad9361_ensm_states[] = { + "sleep", "", "", "", "", "alert", "tx", "tx flush", + "rx", "rx_flush", "fdd", "fdd_flush" +}; + +/** + * SPI multiple bytes register read. + * @param spi + * @param reg The register address. + * @param rbuf The data buffer. + * @param num The number of bytes to read. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_spi_readm(struct spi_desc *spi, uint32_t reg, + uint8_t *rbuf, uint32_t num) +{ + int32_t ret = 0; + uint16_t cmd; + uint8_t *rbuffer; + if (num > MAX_MBYTE_SPI) + return -EINVAL; + + cmd = AD_READ | AD_CNT(num) | AD_ADDR(reg); + rbuffer = malloc(num + 2); + if(!rbuffer) + return -ENOMEM; + rbuffer[0] = cmd >> 8; + rbuffer[1] = cmd & 0xFF; + ret = spi_write_and_read(spi, &rbuffer[0], 2 + num); + + if (ret < 0) + dev_err(&spi->dev, "Read Error %"PRId32, ret); + else + memcpy(rbuf, &rbuffer[2], num); + + free(rbuffer); +#ifdef _DEBUG + { + int32_t i; + for (i = 0; i < num; i++) + dev_dbg(&spi->dev, "%s: reg 0x%"PRIX32" val 0x%X", + __func__, reg--, rbuf[i]); + } +#endif + + return ret; +} + +/** + * SPI register read. + * @param spi + * @param reg The register address. + * @return The register value or negative error code in case of failure. + */ +int32_t ad9361_spi_read(struct spi_desc *spi, uint32_t reg) +{ + uint8_t buf; + int32_t ret; + + ret = ad9361_spi_readm(spi, reg, &buf, 1); + if (ret < 0) + return ret; + + return buf; +} + +/** + * SPI register bits read. + * @param spi + * @param reg The register address. + * @param mask The bits mask. + * @param offset The mask offset. + * @return The bits value or negative error code in case of failure. + */ +static int32_t __ad9361_spi_readf(struct spi_desc *spi, uint32_t reg, + uint32_t mask, uint32_t offset) +{ + uint8_t buf; + int32_t ret; + + if (!mask) + return -EINVAL; + + ret = ad9361_spi_readm(spi, reg, &buf, 1); + if (ret < 0) + return ret; + + buf &= mask; + buf >>= offset; + + return buf; +} + +/** + * SPI register bits read. + * @param spi + * @param reg The register address. + * @param mask The bits mask. + * @return The bits value or negative error code in case of failure. + */ +#define ad9361_spi_readf(spi, reg, mask) \ + __ad9361_spi_readf(spi, reg, mask, find_first_bit(mask)) + +/** + * SPI register write. + * @param spi + * @param reg The register address. + * @param val The value of the register. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_spi_write(struct spi_desc *spi, + uint32_t reg, uint32_t val) +{ + uint8_t buf[3]; + int32_t ret; + uint16_t cmd; + + cmd = AD_WRITE | AD_CNT(1) | AD_ADDR(reg); + buf[0] = cmd >> 8; + buf[1] = cmd & 0xFF; + buf[2] = val; + + ret = spi_write_and_read(spi, buf, 3); + if (ret < 0) { + dev_err(&spi->dev, "Write Error %"PRId32, ret); + return ret; + } + +#ifdef _DEBUG + dev_dbg(&spi->dev, "%s: reg 0x%"PRIX32" val 0x%X", __func__, reg, buf[2]); +#endif + + return 0; +} + +/** + * SPI register bits write. + * @param spi + * @param reg The register address. + * @param mask The bits mask. + * @param offset The mask offset. + * @param val The bits value. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t __ad9361_spi_writef(struct spi_desc *spi, uint32_t reg, + uint32_t mask, uint32_t offset, uint32_t val) +{ + uint8_t buf; + int32_t ret; + + if (!mask) + return -EINVAL; + + ret = ad9361_spi_readm(spi, reg, &buf, 1); + if (ret < 0) + return ret; + + buf &= ~mask; + buf |= ((val << offset) & mask); + + return ad9361_spi_write(spi, reg, buf); +} + +/** + * SPI register bits write. + * @param spi + * @param reg The register address. + * @param mask The bits mask. + * @param val The bits value. + * @return 0 in case of success, negative error code otherwise. + */ +#define ad9361_spi_writef(spi, reg, mask, val) \ + __ad9361_spi_writef(spi, reg, mask, find_first_bit(mask), val) + +/** + * SPI multiple bytes register write. + * @param spi + * @param reg The register address. + * @param tbuf The data buffer. + * @param num The number of bytes to read. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_spi_writem(struct spi_desc *spi, + uint32_t reg, uint8_t *tbuf, uint32_t num) +{ + uint8_t buf[10]; + int32_t ret; + uint16_t cmd; + + if (num > MAX_MBYTE_SPI) + return -EINVAL; + + cmd = AD_WRITE | AD_CNT(num) | AD_ADDR(reg); + buf[0] = cmd >> 8; + buf[1] = cmd & 0xFF; + +#ifndef ALTERA_PLATFORM + memcpy(&buf[2], tbuf, num); +#else + int32_t i; + for (i = 0; i < num; i++) + buf[2 + i] = tbuf[i]; +#endif + ret = spi_write_and_read(spi, buf, num + 2); + if (ret < 0) { + dev_err(&spi->dev, "Write Error %"PRId32, ret); + return ret; + } + +#ifdef _DEBUG + { + int32_t i; + for (i = 0; i < num; i++) + dev_dbg(&spi->dev, "Reg 0x%"PRIX32" val 0x%X", reg--, tbuf[i]); + } +#endif + + return 0; +} + +/** + * Validate RF BW frequency. + * @param phy The AD9361 state structure. + * @param bw The RF BW frequency. + * @return The validated RF BW frequency. + */ +uint32_t ad9361_validate_rf_bw(struct ad9361_rf_phy *phy, uint32_t bw) +{ + switch (phy->dev_sel) { + case ID_AD9363A: + return clamp_t(uint32_t, bw, 200000UL, 20000000UL); + default: + return clamp_t(uint32_t, bw, 200000UL, 56000000UL); + } +} + +/** + * Validate RF PLL frequency. + * @param phy The AD9361 state structure. + * @param is_tx TX enabled. + * @param freq The RF PLL frequency. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_validate_rfpll(struct ad9361_rf_phy *phy, bool is_tx, + uint64_t freq) +{ + switch (phy->dev_sel) { + case ID_AD9363A: + if (freq > AD9363A_MAX_CARRIER_FREQ_HZ || + freq < AD9363A_MIN_CARRIER_FREQ_HZ) + return -EINVAL; + break; + default: + if (freq > MAX_CARRIER_FREQ_HZ || freq < (is_tx ? + MIN_TX_CARRIER_FREQ_HZ : MIN_RX_CARRIER_FREQ_HZ)) + return -EINVAL; + } + + return 0; +} + +/** + * Find optimal value. + * @param field + * @param size + * @param ret_start + * @return The optimal delay in case of success, negative error code otherwise. + */ +int32_t ad9361_find_opt(uint8_t *field, uint32_t size, uint32_t *ret_start) +{ + int32_t i, cnt = 0, max_cnt = 0, start, max_start = 0; + + for(i = 0, start = -1; i < (int64_t)size; i++) { + if (field[i] == 0) { + if (start == -1) + start = i; + cnt++; + } else { + if (cnt > max_cnt) { + max_cnt = cnt; + max_start = start; + } + start = -1; + cnt = 0; + } + } + + if (cnt > max_cnt) { + max_cnt = cnt; + max_start = start; + } + + *ret_start = max_start; + + return max_cnt; +} + +/** + * Select the channel mapping in 1rx1tx mode. + * @param phy The AD9361 state structure. + * @param tx TX + * @param channel Channel + * @return The channel number. + */ +int32_t ad9361_1rx1tx_channel_map(struct ad9361_rf_phy *phy, bool tx, + int32_t channel) +{ + uint32_t map; + + if (phy->pdata->rx2tx2) + return channel; + + if (tx) + map = phy->pdata->rx1tx1_mode_use_tx_num; + else + map = phy->pdata->rx1tx1_mode_use_rx_num; + + if (map == 2) + return channel + 1; + + return channel; +} + +/** + * AD9361 Device Reset + * @param phy The AD9361 state structure. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_reset(struct ad9361_rf_phy *phy) +{ + if (phy->gpio_desc_resetb) { + gpio_set_value(phy->gpio_desc_resetb, 0); + mdelay(1); + gpio_set_value(phy->gpio_desc_resetb, 1); + mdelay(1); + dev_dbg(&phy->spi->dev, "%s: by GPIO", __func__); + return 0; + } + + /* SPI Soft Reset was removed from the register map, since it doesn't + * work reliably. Without a prober HW reset randomness may happen. + * Please specify a RESET GPIO. + */ + + ad9361_spi_write(phy->spi, REG_SPI_CONF, SOFT_RESET | _SOFT_RESET); + ad9361_spi_write(phy->spi, REG_SPI_CONF, 0x0); + dev_err(&phy->spi->dev, + "%s: by SPI, this may cause unpredicted behavior!", __func__); + + return -ENODEV; +} + +/** + * Enable/disable the desired TX channel. + * @param phy The AD9361 state structure. + * @param tx_if The desired channel number [1, 2]. + * @param enable Enable/disable option. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_en_dis_tx(struct ad9361_rf_phy *phy, uint32_t tx_if, + uint32_t enable) +{ + if ((tx_if & enable) > 1 && AD9364_DEVICE && enable) + return -EINVAL; + + return ad9361_spi_writef(phy->spi, REG_TX_ENABLE_FILTER_CTRL, + TX_CHANNEL_ENABLE(tx_if), enable); +} + +/** + * Enable/disable the desired RX channel. + * @param phy The AD9361 state structure. + * @param rx_if The desired channel number [1, 2]. + * @param enable Enable/disable option. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_en_dis_rx(struct ad9361_rf_phy *phy, uint32_t rx_if, + uint32_t enable) +{ + if ((rx_if & enable) > 1 && AD9364_DEVICE && enable) + return -EINVAL; + + return ad9361_spi_writef(phy->spi, REG_RX_ENABLE_FILTER_CTRL, + RX_CHANNEL_ENABLE(rx_if), enable); +} + +/** + * Loopback works only TX1->RX1 or RX2->RX2. + * @param phy The AD9361 state structure. + * @param enable Enable. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_int_loopback_fix_ch_cross(struct ad9361_rf_phy *phy, + bool enable) +{ + /* Loopback works only TX1->RX1 or RX2->RX2 */ + if (!phy->pdata->rx2tx2 && phy->pdata->rx1tx1_mode_use_rx_num != + phy->pdata->rx1tx1_mode_use_tx_num) + return ad9361_en_dis_tx(phy, TX_1 | TX_2, + enable ? phy->pdata->rx1tx1_mode_use_rx_num : + phy->pdata->rx1tx1_mode_use_tx_num); + + return 0; +} + +/** + * BIST loopback mode. + * @param phy The AD9361 state structure. + * @param mode BIST loopback mode. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_bist_loopback(struct ad9361_rf_phy *phy, int32_t mode) +{ + uint32_t sp_hd, reg; + + dev_dbg(&phy->spi->dev, "%s: mode %"PRId32, __func__, mode); + + reg = ad9361_spi_read(phy->spi, REG_OBSERVE_CONFIG); + + phy->bist_loopback_mode = mode; + + switch (mode) { + case 0: + ad9361_hdl_loopback(phy, false); + ad9361_int_loopback_fix_ch_cross(phy, false); + reg &= ~(DATA_PORT_SP_HD_LOOP_TEST_OE | + DATA_PORT_LOOP_TEST_ENABLE); + return ad9361_spi_write(phy->spi, REG_OBSERVE_CONFIG, reg); + case 1: + /* loopback (AD9361 internal) TX->RX */ + ad9361_hdl_loopback(phy, false); + ad9361_int_loopback_fix_ch_cross(phy, true); + sp_hd = ad9361_spi_read(phy->spi, REG_PARALLEL_PORT_CONF_3); + if ((sp_hd & SINGLE_PORT_MODE) && (sp_hd & HALF_DUPLEX_MODE)) + reg |= DATA_PORT_SP_HD_LOOP_TEST_OE; + else + reg &= ~DATA_PORT_SP_HD_LOOP_TEST_OE; + + reg |= DATA_PORT_LOOP_TEST_ENABLE; + + return ad9361_spi_write(phy->spi, REG_OBSERVE_CONFIG, reg); + case 2: + /* loopback (FPGA internal) RX->TX */ + ad9361_hdl_loopback(phy, true); + ad9361_int_loopback_fix_ch_cross(phy, false); + reg &= ~(DATA_PORT_SP_HD_LOOP_TEST_OE | + DATA_PORT_LOOP_TEST_ENABLE); + return ad9361_spi_write(phy->spi, REG_OBSERVE_CONFIG, reg); + default: + return -EINVAL; + } +} + +/** + * Get BIST loopback mode. + * @param phy The AD9361 state structure. + * @param mode BIST loopback mode. + * @return 0 in case of success, negative error code otherwise. + */ +void ad9361_get_bist_loopback(struct ad9361_rf_phy *phy, int32_t *mode) +{ + *mode = phy->bist_loopback_mode; +} + +/** + * BIST mode. + * @param phy The AD9361 state structure. + * @param mode Bist mode. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_bist_prbs(struct ad9361_rf_phy *phy, enum ad9361_bist_mode mode) +{ + uint32_t reg = 0; + + dev_dbg(&phy->spi->dev, "%s: mode %d", __func__, mode); + + phy->bist_prbs_mode = mode; + + switch (mode) { + case BIST_DISABLE: + reg = 0; + break; + case BIST_INJ_TX: + reg = BIST_CTRL_POINT(0) | BIST_ENABLE; + break; + case BIST_INJ_RX: + reg = BIST_CTRL_POINT(2) | BIST_ENABLE; + break; + }; + + phy->bist_config = reg; + + return ad9361_spi_write(phy->spi, REG_BIST_CONFIG, reg); +} + +/** + * Get BIST mode settings. + * @param phy The AD9361 state structure. + * @param mode Bist mode. + * @return 0 in case of success, negative error code otherwise. + */ +void ad9361_get_bist_prbs(struct ad9361_rf_phy *phy, + enum ad9361_bist_mode *mode) +{ + *mode = phy->bist_prbs_mode; +} + +/** + * BIST tone. + * @param phy The AD9361 state structure. + * @param mode Bist tone mode. + * @param freq_Hz Bist tone frequency. + * @param level_dB Bist tone level. + * @param mask Bist reg mask. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_bist_tone(struct ad9361_rf_phy *phy, + enum ad9361_bist_mode mode, uint32_t freq_Hz, + uint32_t level_dB, uint32_t mask) +{ + uint32_t clk = 0; + uint32_t reg = 0, reg1, reg_mask; + + dev_dbg(&phy->spi->dev, "%s: mode %d", __func__, mode); + + phy->bist_tone_mode = mode; + phy->bist_tone_freq_Hz = freq_Hz; + phy->bist_tone_level_dB = level_dB; + phy->bist_tone_mask = mask; + + switch (mode) { + case BIST_DISABLE: + reg = 0; + break; + case BIST_INJ_TX: + clk = clk_get_rate(phy, phy->ref_clk_scale[TX_SAMPL_CLK]); + reg = BIST_CTRL_POINT(0) | BIST_ENABLE; + break; + case BIST_INJ_RX: + clk = clk_get_rate(phy, phy->ref_clk_scale[RX_SAMPL_CLK]); + reg = BIST_CTRL_POINT(2) | BIST_ENABLE; + break; + }; + + reg |= TONE_PRBS; + reg |= TONE_LEVEL(level_dB / 6); + + if (freq_Hz < 4) { + reg |= TONE_FREQ(freq_Hz); + } else { + if (clk) + reg |= TONE_FREQ(DIV_ROUND_CLOSEST(freq_Hz * 32, clk) - 1); + } + + reg_mask = BIST_MASK_CHANNEL_1_I_DATA | BIST_MASK_CHANNEL_1_Q_DATA | + BIST_MASK_CHANNEL_2_I_DATA | BIST_MASK_CHANNEL_2_Q_DATA; + + reg1 = ((mask << 2) & reg_mask); + ad9361_spi_write(phy->spi, REG_BIST_AND_DATA_PORT_TEST_CONFIG, reg1); + + phy->bist_config = reg; + + return ad9361_spi_write(phy->spi, REG_BIST_CONFIG, reg); +} + +/** + * Get BIST tone settings. + * @param phy The AD9361 state structure. + * @param mode Bist tone mode. + * @param freq_Hz Bist tone frequency. + * @param level_dB Bist tone level. + * @param mask Bist reg mask. + * @return 0 in case of success, negative error code otherwise. + */ +void ad9361_get_bist_tone(struct ad9361_rf_phy *phy, + enum ad9361_bist_mode *mode, uint32_t *freq_Hz, + uint32_t *level_dB, uint32_t *mask) +{ + *mode = phy->bist_tone_mode; + *freq_Hz = phy->bist_tone_freq_Hz; + *level_dB = phy->bist_tone_level_dB; + *mask = phy->bist_tone_mask; +} + +/** + * Check the calibration done bit. + * @param phy The AD9361 state structure. + * @param reg The register address. + * @param mask The bit mask. + * @param done_state The done state [0,1]. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_check_cal_done(struct ad9361_rf_phy *phy, uint32_t reg, + uint32_t mask, uint32_t done_state) +{ + uint32_t timeout = 20000; /* RFDC_CAL can take long */ + uint32_t state; + + do { + state = ad9361_spi_readf(phy->spi, reg, mask); + if (state == done_state) + return 0; + + if (reg == REG_CALIBRATION_CTRL) + udelay(1200); + else + udelay(120); + } while (timeout--); + + dev_err(&phy->spi->dev, "Calibration TIMEOUT (0x%"PRIX32", 0x%"PRIX32")", reg, + mask); + + return -ETIMEDOUT; +} + +/** + * Run an AD9361 calibration and check the calibration done bit. + * @param phy The AD9361 state structure. + * @param mask The calibration bit mask[RX_BB_TUNE_CAL, TX_BB_TUNE_CAL, + * RX_QUAD_CAL, TX_QUAD_CAL, RX_GAIN_STEP_CAL, TXMON_CAL, + * RFDC_CAL, BBDC_CAL]. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_run_calibration(struct ad9361_rf_phy *phy, uint32_t mask) +{ + int32_t ret = ad9361_spi_write(phy->spi, REG_CALIBRATION_CTRL, mask); + if (ret < 0) + return ret; + + dev_dbg(&phy->spi->dev, "%s: CAL Mask 0x%"PRIx32, __func__, mask); + + return ad9361_check_cal_done(phy, REG_CALIBRATION_CTRL, mask, 0); +} + +/** + * Choose the right RX gain table index for the selected frequency. + * @param freq The frequency value [Hz]. + * @return The index to the RX gain table. + */ +static int32_t ad9361_gt_tableindex(struct ad9361_rf_phy *phy, uint64_t freq) +{ + int32_t i; + + for (i = 0; phy->gt_info[i].tab != NULL; i++) { + if ((phy->pdata->split_gt == phy->gt_info[i].split_table) && + (phy->gt_info[i].start < freq) && + (freq <= phy->gt_info[i].end)) { + return i; + } + } + + dev_err(&phy->spi->dev, + "%s: Failed to find suitable gain table (%"PRIu64")", __func__, freq); + + return 0; +} + +/** + * Return the current gain table index. + * @param phy The AD9361 state structure. + * @return The current gain table index or 0 if the table was not chosen. + */ +uint32_t ad9361_gt(struct ad9361_rf_phy *phy) +{ + if (phy->current_table == NO_GAIN_TABLE) { + dev_err(&phy->spi->dev, "%s: ERROR", __func__); + return 0; + } + + return phy->current_table; +} + +/** + * Shift the real frequency value, so it fits type unsigned long + * Note: PLL operates between 47 .. 6000 MHz which is > 2^32. + * @param freq The frequency value [Hz]. + * @return The shifted frequency value. + */ +uint32_t ad9361_to_clk(uint64_t freq) +{ + return (uint32_t)(freq >> 1); +} + +/** + * Shift back the frequency value, so it reflects the real value. + * Note: PLL operates between 47 .. 6000 MHz which is > 2^32. + * @param freq The frequency value [Hz]. + * @return The shifted frequency value. + */ +uint64_t ad9361_from_clk(uint32_t freq) +{ + return ((uint64_t)freq << 1); +} + +/** + * Find the corresponding table index for a specific gain value. + * @param phy The AD9361 state structure. + * @param gain The gain value. + * @return The table index. + */ +static int find_table_index(struct ad9361_rf_phy *phy, int gain) +{ + uint32_t i, nm1, n; + + for (i = 0; i < phy->gt_info[ad9361_gt(phy)].max_index; i++) { + if (phy->gt_info[ad9361_gt(phy)].abs_gain_tbl[i] >= gain) { + nm1 = abs(phy->gt_info[ad9361_gt(phy)].abs_gain_tbl[ + (i > 0) ? i - 1 : i] - gain); + n = abs(phy->gt_info[ad9361_gt(phy)].abs_gain_tbl[i] + - gain); + if (nm1 < n) + return (i > 0) ? i - 1 : i; + else + return i; + } + } + + return -EINVAL; +} + +/** + * Load the gain table for the selected frequency range and receiver. + * @param phy The AD9361 state structure. + * @param freq The frequency value [Hz]. + * @param dest The destination [GT_RX1, GT_RX2]. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_load_gt(struct ad9361_rf_phy *phy, uint64_t freq, + uint32_t dest) +{ + struct spi_desc *spi = phy->spi; + uint8_t (*tab)[3]; + uint32_t band, index_max, i, lna, lpf_tia_mask, set_gain; + int32_t ret, rx1_gain, rx2_gain; + + dev_dbg(&phy->spi->dev, "%s: frequency %"PRIu64, __func__, freq); + + band = ad9361_gt_tableindex(phy, freq); + + dev_dbg(&phy->spi->dev, "%s: frequency %"PRIu64" (band %"PRIu32")", + __func__, freq, band); + + /* check if table is present */ + if (phy->current_table == band) + return 0; + + tab = phy->gt_info[band].tab; + index_max = phy->gt_info[band].max_index; + + ad9361_spi_writef(spi, REG_AGC_CONFIG_2, + AGC_USE_FULL_GAIN_TABLE, !phy->pdata->split_gt); + + ad9361_spi_write(spi, REG_MAX_LMT_FULL_GAIN, + index_max - 1); /* Max Full/LMT Gain Table Index */ + + set_gain = ad9361_spi_readf(spi, REG_RX1_MANUAL_LMT_FULL_GAIN, + RX_FULL_TBL_IDX_MASK); + + if (phy->current_table != NO_GAIN_TABLE) { + rx1_gain = phy->gt_info[phy->current_table].abs_gain_tbl[set_gain]; + } else { + if (set_gain > (index_max - 1)) + set_gain = index_max - 1; + + rx1_gain = phy->gt_info[band].abs_gain_tbl[set_gain]; + } + + set_gain = ad9361_spi_readf(spi, REG_RX2_MANUAL_LMT_FULL_GAIN, + RX_FULL_TBL_IDX_MASK); + + if (phy->current_table != NO_GAIN_TABLE) { + rx2_gain = phy->gt_info[phy->current_table].abs_gain_tbl[set_gain]; + } else { + if (set_gain > (index_max - 1)) + set_gain = index_max - 1; + + rx2_gain = phy->gt_info[band].abs_gain_tbl[set_gain]; + } + + lna = phy->pdata->elna_ctrl.elna_in_gaintable_all_index_en ? + EXT_LNA_CTRL : 0; + + ad9361_spi_write(spi, REG_GAIN_TABLE_CONFIG, START_GAIN_TABLE_CLOCK | + RECEIVER_SELECT(dest)); /* Start Gain Table Clock */ + + /* TX QUAD Calibration */ + if (phy->pdata->split_gt) + lpf_tia_mask = 0x20; + else + lpf_tia_mask = 0x3F; + + phy->tx_quad_lpf_tia_match = -EINVAL; + + for (i = 0; i < index_max; i++) { + ad9361_spi_write(spi, REG_GAIN_TABLE_ADDRESS, i); /* Gain Table Index */ + ad9361_spi_write(spi, REG_GAIN_TABLE_WRITE_DATA1, + tab[i][0] | lna); /* Ext LNA, Int LNA, & Mixer Gain Word */ + ad9361_spi_write(spi, REG_GAIN_TABLE_WRITE_DATA2, + tab[i][1]); /* TIA & LPF Word */ + ad9361_spi_write(spi, REG_GAIN_TABLE_WRITE_DATA3, + tab[i][2]); /* DC Cal bit & Dig Gain Word */ + ad9361_spi_write(spi, REG_GAIN_TABLE_CONFIG, + START_GAIN_TABLE_CLOCK | + WRITE_GAIN_TABLE | + RECEIVER_SELECT(dest)); /* Gain Table Index */ + ad9361_spi_write(spi, REG_GAIN_TABLE_READ_DATA1, + 0); /* Dummy Write to delay 3 ADCCLK/16 cycles */ + ad9361_spi_write(spi, REG_GAIN_TABLE_READ_DATA1, + 0); /* Dummy Write to delay ~1u */ + + if ((tab[i][1] & lpf_tia_mask) == 0x20) + phy->tx_quad_lpf_tia_match = i; + + } + + ad9361_spi_write(spi, REG_GAIN_TABLE_CONFIG, START_GAIN_TABLE_CLOCK | + RECEIVER_SELECT(dest)); /* Clear Write Bit */ + ad9361_spi_write(spi, REG_GAIN_TABLE_READ_DATA1, + 0); /* Dummy Write to delay ~1u */ + ad9361_spi_write(spi, REG_GAIN_TABLE_READ_DATA1, + 0); /* Dummy Write to delay ~1u */ + ad9361_spi_write(spi, REG_GAIN_TABLE_CONFIG, 0); /* Stop Gain Table Clock */ + + phy->current_table = band; + + ret = find_table_index(phy, rx1_gain); + if (ret < 0) + ret = phy->gt_info[band].max_index - 1; + + ad9361_spi_writef(spi, REG_RX1_MANUAL_LMT_FULL_GAIN, + RX_FULL_TBL_IDX_MASK, ret); /* Rx1 Full/LMT Gain Index */ + + ret = find_table_index(phy, rx2_gain); + if (ret < 0) + ret = phy->gt_info[band].max_index - 1; + + ad9361_spi_write(spi, REG_RX2_MANUAL_LMT_FULL_GAIN, + ret); /* Rx2 Full/LMT Gain Index */ + + return 0; +} + +/** + * Setup the external low-noise amplifier (LNA). + * @param phy The AD9361 state structure. + * @param ctrl Pointer to eLNA control structure. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_setup_ext_lna(struct ad9361_rf_phy *phy, + struct elna_control *ctrl) +{ + ad9361_spi_writef(phy->spi, REG_EXTERNAL_LNA_CTRL, EXTERNAL_LNA1_CTRL, + ctrl->elna_1_control_en); + + ad9361_spi_writef(phy->spi, REG_EXTERNAL_LNA_CTRL, EXTERNAL_LNA2_CTRL, + ctrl->elna_2_control_en); + + ad9361_spi_write(phy->spi, REG_EXT_LNA_HIGH_GAIN, + EXT_LNA_HIGH_GAIN(ctrl->gain_mdB / 500)); + + return ad9361_spi_write(phy->spi, REG_EXT_LNA_LOW_GAIN, + EXT_LNA_LOW_GAIN(ctrl->bypass_loss_mdB / 500)); +} + +/** + * Set the clock output mode. + * @param phy The AD9361 state structure. + * @param mode The clock output mode []. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_clkout_control(struct ad9361_rf_phy *phy, + enum ad9361_clkout mode) +{ + if (mode == CLKOUT_DISABLE) + return ad9361_spi_writef(phy->spi, REG_BBPLL, CLKOUT_ENABLE, 0); + + return ad9361_spi_writef(phy->spi, REG_BBPLL, + CLKOUT_ENABLE | CLKOUT_SELECT(~0), + ((mode - 1) << 1) | 0x1); +} + +/** + * Load the Gm Sub Table. + * @param phy The AD9361 state structure. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_load_mixer_gm_subtable(struct ad9361_rf_phy *phy) +{ + int32_t i, addr; + dev_dbg(&phy->spi->dev, "%s", __func__); + + ad9361_spi_write(phy->spi, REG_GM_SUB_TABLE_CONFIG, + START_GM_SUB_TABLE_CLOCK); /* Start Clock */ + + for (i = 0, addr = ARRAY_SIZE(gm_st_ctrl); i < (int64_t)ARRAY_SIZE(gm_st_ctrl); + i++) { + ad9361_spi_write(phy->spi, REG_GM_SUB_TABLE_ADDRESS, + --addr); /* Gain Table Index */ + ad9361_spi_write(phy->spi, REG_GM_SUB_TABLE_BIAS_WRITE, 0); /* Bias */ + ad9361_spi_write(phy->spi, REG_GM_SUB_TABLE_GAIN_WRITE, + gm_st_gain[i]); /* Gain */ + ad9361_spi_write(phy->spi, REG_GM_SUB_TABLE_CTRL_WRITE, + gm_st_ctrl[i]); /* Control */ + ad9361_spi_write(phy->spi, REG_GM_SUB_TABLE_CONFIG, + WRITE_GM_SUB_TABLE | START_GM_SUB_TABLE_CLOCK); /* Write Words */ + ad9361_spi_write(phy->spi, REG_GM_SUB_TABLE_GAIN_READ, 0); /* Dummy Delay */ + ad9361_spi_write(phy->spi, REG_GM_SUB_TABLE_GAIN_READ, 0); /* Dummy Delay */ + } + + ad9361_spi_write(phy->spi, REG_GM_SUB_TABLE_CONFIG, + START_GM_SUB_TABLE_CLOCK); /* Clear Write */ + ad9361_spi_write(phy->spi, REG_GM_SUB_TABLE_GAIN_READ, 0); /* Dummy Delay */ + ad9361_spi_write(phy->spi, REG_GM_SUB_TABLE_GAIN_READ, 0); /* Dummy Delay */ + ad9361_spi_write(phy->spi, REG_GM_SUB_TABLE_CONFIG, 0); /* Stop Clock */ + + return 0; +} + +/** + * Set the attenuation for the selected TX channels. + * @param phy The AD9361 state structure. + * @param atten_mdb Attenuation value [mdB]. + * @param tx1 Set true, the attenuation of the TX1 will be affected. + * @param tx2 Set true, the attenuation of the TX2 will be affected. + * @param immed Set true, an immediate update will take place. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_set_tx_atten(struct ad9361_rf_phy *phy, uint32_t atten_mdb, + bool tx1, bool tx2, bool immed) +{ + uint8_t buf[2]; + int32_t ret = 0; + + dev_dbg(&phy->spi->dev, "%s : attenuation %"PRIu32" mdB tx1=%d tx2=%d", + __func__, atten_mdb, tx1, tx2); + + if (atten_mdb > MAX_TX_ATTENUATION_DB) /* 89.75 dB */ + return -EINVAL; + + atten_mdb /= 250; /* Scale to 0.25dB / LSB */ + + buf[0] = atten_mdb >> 8; + buf[1] = atten_mdb & 0xFF; + + ad9361_spi_writef(phy->spi, REG_TX2_DIG_ATTEN, + IMMEDIATELY_UPDATE_TPC_ATTEN, 0); + + if (tx1) + ret = ad9361_spi_writem(phy->spi, REG_TX1_ATTEN_1, buf, 2); + + if (tx2) + ret = ad9361_spi_writem(phy->spi, REG_TX2_ATTEN_1, buf, 2); + + if (immed) + ad9361_spi_writef(phy->spi, REG_TX2_DIG_ATTEN, + IMMEDIATELY_UPDATE_TPC_ATTEN, 1); + + return ret; +} + +/** + * Get the attenuation for the selected TX channel. + * @param phy The AD9361 state structure. + * @param tx_num The selected channel [1, 2]. + * @return The attenuation value [mdB] or negative error code in case of failure. + */ +int32_t ad9361_get_tx_atten(struct ad9361_rf_phy *phy, uint32_t tx_num) +{ + uint8_t buf[2]; + int32_t ret = 0; + uint32_t code; + + ret = ad9361_spi_readm(phy->spi, (tx_num == 1) ? + REG_TX1_ATTEN_1 : REG_TX2_ATTEN_1, buf, 2); + + if (ret < 0) + return ret; + + code = (buf[0] << 8) | buf[1]; + + code *= 250; + + return code; +} + +/** + * Mute TX. + * @param phy The AD9361 state structure. + * @param state The state - 0 mute; 1 - unmute. + * @return 0 in case of success + */ +int32_t ad9361_tx_mute(struct ad9361_rf_phy *phy, uint32_t state) +{ + int32_t ret; + + if (state) { + phy->tx1_atten_cached = ad9361_get_tx_atten(phy, 1); + phy->tx2_atten_cached = ad9361_get_tx_atten(phy, 2); + + return ad9361_set_tx_atten(phy, 89750, true, true, true); + } else { + if (phy->tx1_atten_cached == phy->tx2_atten_cached) + return ad9361_set_tx_atten(phy, phy->tx1_atten_cached, + true, true, true); + + ret = ad9361_set_tx_atten(phy, phy->tx1_atten_cached, + true, false, true); + ret |= ad9361_set_tx_atten(phy, phy->tx2_atten_cached, + false, true, true); + + return ret; + } +} + +/** + * Choose the right RF VCO table index for the selected frequency. + * @param freq The frequency value [Hz]. + * @return The index from the RF VCO table. + */ +static uint32_t ad9361_rfvco_tableindex(uint32_t freq) +{ + if (freq < 50000000UL) + return LUT_FTDD_40; + + if (freq <= 70000000UL) + return LUT_FTDD_60; + + return LUT_FTDD_80; +} + +/** + * Initialize the RFPLL VCO. + * @param phy The AD9361 state structure. + * @param tx Set true for TX_RFPLL. + * @param vco_freq The VCO frequency [Hz]. + * @param ref_clk The reference clock frequency [Hz]. + * @return 0 in case of success + */ +static int32_t ad9361_rfpll_vco_init(struct ad9361_rf_phy *phy, + bool tx, uint64_t vco_freq, + uint32_t ref_clk) +{ + struct spi_desc *spi = phy->spi; + const struct SynthLUT(*tab); + int32_t i = 0; + uint32_t range, offs = 0; + + range = ad9361_rfvco_tableindex(ref_clk); + + dev_dbg(&phy->spi->dev, + "%s : vco_freq %"PRIu64" : ref_clk %"PRIu32" : range %"PRIu32, + __func__, vco_freq, ref_clk, range); + + do_div(&vco_freq, 1000000UL); /* vco_freq in MHz */ + + if ((phy->pdata->fdd && !phy->pdata->fdd_independent_mode) + && (phy->current_tx_lo_freq != phy->current_rx_lo_freq)) { + tab = &SynthLUT_FDD[range][0]; + if (tx) + phy->current_tx_use_tdd_table = false; + else + phy->current_rx_use_tdd_table = false; + } else { + if (have_tdd_tables) { + tab = &SynthLUT_TDD[range][0]; + if (tx) + phy->current_tx_use_tdd_table = true; + else + phy->current_rx_use_tdd_table = true; + } + } + + if (tx) + offs = REG_TX_VCO_OUTPUT - REG_RX_VCO_OUTPUT; + + while (i < SYNTH_LUT_SIZE && tab[i].VCO_MHz > vco_freq) + i++; + + dev_dbg(&phy->spi->dev, "%s : freq %d MHz : index %"PRId32, + __func__, tab[i].VCO_MHz, i); + + ad9361_spi_write(spi, REG_RX_VCO_OUTPUT + offs, + VCO_OUTPUT_LEVEL(tab[i].VCO_Output_Level) | + PORB_VCO_LOGIC); + ad9361_spi_writef(spi, REG_RX_ALC_VARACTOR + offs, + VCO_VARACTOR(~0), tab[i].VCO_Varactor); + ad9361_spi_write(spi, REG_RX_VCO_BIAS_1 + offs, + VCO_BIAS_REF(tab[i].VCO_Bias_Ref) | + VCO_BIAS_TCF(tab[i].VCO_Bias_Tcf)); + + ad9361_spi_write(spi, REG_RX_FORCE_VCO_TUNE_1 + offs, + VCO_CAL_OFFSET(tab[i].VCO_Cal_Offset)); + ad9361_spi_write(spi, REG_RX_VCO_VARACTOR_CTRL_1 + offs, + VCO_VARACTOR_REFERENCE( + tab[i].VCO_Varactor_Reference)); + + ad9361_spi_write(spi, REG_RX_VCO_CAL_REF + offs, VCO_CAL_REF_TCF(0)); + + ad9361_spi_write(spi, REG_RX_VCO_VARACTOR_CTRL_0 + offs, + VCO_VARACTOR_OFFSET(0) | + VCO_VARACTOR_REFERENCE_TCF(7)); + + ad9361_spi_writef(spi, REG_RX_CP_CURRENT + offs, CHARGE_PUMP_CURRENT(~0), + tab[i].Charge_Pump_Current); + ad9361_spi_write(spi, REG_RX_LOOP_FILTER_1 + offs, + LOOP_FILTER_C2(tab[i].LF_C2) | + LOOP_FILTER_C1(tab[i].LF_C1)); + ad9361_spi_write(spi, REG_RX_LOOP_FILTER_2 + offs, + LOOP_FILTER_R1(tab[i].LF_R1) | + LOOP_FILTER_C3(tab[i].LF_C3)); + ad9361_spi_write(spi, REG_RX_LOOP_FILTER_3 + offs, + LOOP_FILTER_R3(tab[i].LF_R3)); + + return 0; +} + +/** + * Get the current gain in Split Gain Table Mode + * @param phy The AD9361 state structure. + * @param idx_reg Register base address for the selected receiver + * @param rx_gain A rf_rx_gain struct to store the RF gain. + * @return 0 in case of success, + */ +static int32_t ad9361_get_split_table_gain(struct ad9361_rf_phy *phy, + uint32_t idx_reg, + struct rf_rx_gain *rx_gain) +{ + struct spi_desc *spi = phy->spi; + uint32_t val, tbl_addr; + int32_t rc = 0; + + + rx_gain->fgt_lmt_index = ad9361_spi_readf(spi, idx_reg, + FULL_TABLE_GAIN_INDEX(~0)); + tbl_addr = ad9361_spi_read(spi, REG_GAIN_TABLE_ADDRESS); + + ad9361_spi_write(spi, REG_GAIN_TABLE_ADDRESS, rx_gain->fgt_lmt_index); + + val = ad9361_spi_read(spi, REG_GAIN_TABLE_READ_DATA1); + rx_gain->lna_index = TO_LNA_GAIN(val); + rx_gain->mixer_index = TO_MIXER_GM_GAIN(val); + + rx_gain->tia_index = ad9361_spi_readf(spi, REG_GAIN_TABLE_READ_DATA2, TIA_GAIN); + + rx_gain->lmt_gain = lna_table[ad9361_gt(phy) - RXGAIN_TBLS_END][rx_gain->lna_index] + + mixer_table[ad9361_gt(phy) - RXGAIN_TBLS_END][rx_gain->mixer_index] + + tia_table[rx_gain->tia_index]; + + ad9361_spi_write(spi, REG_GAIN_TABLE_ADDRESS, tbl_addr); + + /* Read LPF Index */ + rx_gain->lpf_gain = ad9361_spi_readf(spi, idx_reg + 1, LPF_GAIN_RX(~0)); + + /* Read Digital Gain */ + rx_gain->digital_gain = ad9361_spi_readf(spi, idx_reg + 2, + DIGITAL_GAIN_RX(~0)); + + rx_gain->gain_db = rx_gain->lmt_gain + rx_gain->lpf_gain + + rx_gain->digital_gain; + return rc; +} + +/** + * Get the current gain in Full Gain Table Mode + * @param phy The AD9361 state structure. + * @param idx_reg Register base address for the selected receiver + * @param rx_gain A rf_rx_gain struct to store the RF gain. + * @return 0 in case of success + */ +static int32_t ad9361_get_full_table_gain(struct ad9361_rf_phy *phy, + uint32_t idx_reg, + struct rf_rx_gain *rx_gain) +{ + struct spi_desc *spi = phy->spi; + uint32_t val; + + rx_gain->fgt_lmt_index = val = ad9361_spi_readf(spi, idx_reg, + FULL_TABLE_GAIN_INDEX(~0)); + /* Read Digital Gain */ + rx_gain->digital_gain = ad9361_spi_readf(spi, idx_reg + 2, + DIGITAL_GAIN_RX(~0)); + + rx_gain->gain_db = phy->gt_info[ad9361_gt(phy)].abs_gain_tbl[val]; + + return 0; +} + +/** + * Get current RX gain for the selected channel. + * @param phy The AD9361 state structure. + * @param rx_id The desired channel number (0, 1). + * @param rx_gain A rf_rx_gain struct to store the RF gain. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_get_rx_gain(struct ad9361_rf_phy *phy, + uint32_t rx_id, struct rf_rx_gain *rx_gain) +{ + struct spi_desc *spi = phy->spi; + uint32_t val, idx_reg; + uint8_t gain_ctl_shift, rx_enable_mask; + uint8_t fast_atk_shift; + int32_t rc = 0; + + if (rx_id == 1) { + gain_ctl_shift = RX1_GAIN_CTRL_SHIFT; + idx_reg = REG_GAIN_RX1; + rx_enable_mask = RX_CHANNEL_ENABLE(RX_1); + fast_atk_shift = RX1_FAST_ATK_SHIFT; + + } else if (rx_id == 2) { + gain_ctl_shift = RX2_GAIN_CTRL_SHIFT; + idx_reg = REG_GAIN_RX2; + rx_enable_mask = RX_CHANNEL_ENABLE(RX_2); + fast_atk_shift = RX2_FAST_ATK_SHIFT; + } else { + dev_err(dev, "Unknown Rx path %"PRIu32, rx_id); + rc = -EINVAL; + goto out; + } + + val = ad9361_spi_readf(spi, REG_RX_ENABLE_FILTER_CTRL, rx_enable_mask); + + if (!val) { + dev_dbg(dev, "Rx%"PRIu32" is not enabled", rx_gain->ant); + rc = -EAGAIN; + goto out; + } + + val = ad9361_spi_read(spi, REG_AGC_CONFIG_1); + + val = (val >> gain_ctl_shift) & RX_GAIN_CTL_MASK; + + if (val == RX_GAIN_CTL_AGC_FAST_ATK) { + /* In fast attack mode check whether Fast attack state machine + * has locked gain, if not then we can not read gain. + */ + val = ad9361_spi_read(spi, REG_FAST_ATTACK_STATE); + val = (val >> fast_atk_shift) & FAST_ATK_MASK; + if (val != FAST_ATK_GAIN_LOCKED) { + dev_warn(dev, "Failed to read gain, state m/c at %"PRIx32, + val); + rc = -EAGAIN; + goto out; + } + } + + if (has_split_gt && phy->pdata->split_gt) + rc = ad9361_get_split_table_gain(phy, idx_reg, rx_gain); + else + rc = ad9361_get_full_table_gain(phy, idx_reg, rx_gain); + +out: + return rc; +} + +/** + * Get Enable State Machine (ENSM) state. + * @param phy The AD9361 state structure. + * @return The state. + */ +uint8_t ad9361_ensm_get_state(struct ad9361_rf_phy *phy) +{ + return ad9361_spi_readf(phy->spi, REG_STATE, ENSM_STATE(~0)); +} + +/** + * Force Enable State Machine (ENSM) to the desired state (internally used only). + * @param phy The AD9361 state structure. + * @param ensm_state The ENSM state [ENSM_STATE_SLEEP_WAIT, ENSM_STATE_ALERT, + * ENSM_STATE_TX, ENSM_STATE_TX_FLUSH, ENSM_STATE_RX, + * ENSM_STATE_RX_FLUSH, ENSM_STATE_FDD, ENSM_STATE_FDD_FLUSH]. + * @return None. + */ +void ad9361_ensm_force_state(struct ad9361_rf_phy *phy, uint8_t ensm_state) +{ + struct spi_desc *spi = phy->spi; + uint8_t dev_ensm_state; + int32_t rc, timeout = 10; + uint32_t val; + + dev_ensm_state = ad9361_spi_readf(spi, REG_STATE, ENSM_STATE(~0)); + + phy->prev_ensm_state = dev_ensm_state; + + if (dev_ensm_state == ensm_state) { + dev_dbg(dev, "Nothing to do, device is already in %d state", + ensm_state); + goto out; + } + + dev_dbg(dev, "Device is in %x state, forcing to %x", dev_ensm_state, + ensm_state); + + val = ad9361_spi_read(spi, REG_ENSM_CONFIG_1); + + /* Enable control through SPI writes, and take out from + * Alert + */ + if (val & ENABLE_ENSM_PIN_CTRL) { + val &= ~ENABLE_ENSM_PIN_CTRL; + phy->ensm_pin_ctl_en = true; + } else { + phy->ensm_pin_ctl_en = false; + } + + if (dev_ensm_state) + val &= ~(TO_ALERT); + + switch (ensm_state) { + + case ENSM_STATE_TX: + case ENSM_STATE_FDD: + val |= FORCE_TX_ON; + break; + case ENSM_STATE_RX: + val |= FORCE_RX_ON; + break; + case ENSM_STATE_ALERT: + val &= ~(FORCE_TX_ON | FORCE_RX_ON); + val |= TO_ALERT | FORCE_ALERT_STATE; + break; + default: + dev_err(dev, "No handling for forcing %d ensm state", + ensm_state); + goto out; + } + + ad9361_spi_write(spi, REG_ENSM_CONFIG_1, TO_ALERT | FORCE_ALERT_STATE); + + rc = ad9361_spi_write(spi, REG_ENSM_CONFIG_1, val); + if (rc) { + dev_err(dev, "Failed to write ENSM_CONFIG_1\n"); + goto out; + } + + while (ad9361_ensm_get_state(phy) != ensm_state && --timeout) { + mdelay(1); + } + + if (timeout == 0) + dev_err(dev, "Failed to restore state"); + +out: + return; + +} + +/** + * Restore an Enable State Machine (ENSM) state. + * @param phy The AD9361 state structure. + * @param ensm_state The state. + * @return None. + */ +void ad9361_ensm_restore_state(struct ad9361_rf_phy *phy, uint8_t ensm_state) +{ + struct spi_desc *spi = phy->spi; + int32_t rc; + uint32_t val; + + val = ad9361_spi_read(spi, REG_ENSM_CONFIG_1); + + /* We are restoring state only, so clear State bits first + * which might have set while forcing a particular state + */ + val &= ~(FORCE_TX_ON | FORCE_RX_ON | FORCE_ALERT_STATE); + val |= TO_ALERT; + + switch (ensm_state) { + case ENSM_STATE_TX: + case ENSM_STATE_FDD: + val |= FORCE_TX_ON; + break; + case ENSM_STATE_RX: + val |= FORCE_RX_ON; + break; + case ENSM_STATE_ALERT: + val |= TO_ALERT; + break; + case ENSM_STATE_INVALID: + dev_dbg(dev, "No need to restore, ENSM state wasn't saved"); + return; + default: + dev_dbg(dev, "Could not restore to %d ENSM state", + ensm_state); + return; + } + + ad9361_spi_write(spi, REG_ENSM_CONFIG_1, TO_ALERT | FORCE_ALERT_STATE); + + rc = ad9361_spi_write(spi, REG_ENSM_CONFIG_1, val); + if (rc) { + dev_err(dev, "Failed to write ENSM_CONFIG_1"); + return; + } + + if (phy->ensm_pin_ctl_en) { + val |= ENABLE_ENSM_PIN_CTRL; + rc = ad9361_spi_write(spi, REG_ENSM_CONFIG_1, val); + if (rc) + dev_err(dev, "Failed to write ENSM_CONFIG_1"); + } +} + +/** + * Restore the previous Enable State Machine (ENSM) state. + * @param phy The AD9361 state structure. + * @return None. + */ +void ad9361_ensm_restore_prev_state(struct ad9361_rf_phy *phy) +{ + return ad9361_ensm_restore_state(phy, phy->prev_ensm_state); +} + +/** + * Set gain in Split Gain Table Mode (used only in Manual Gain Control Mode). + * @param phy The AD9361 state structure. + * @param idx_reg Register base address for the selected receiver + * @param rx_gain The rf_rx_gain struct containing the RF gain. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t set_split_table_gain(struct ad9361_rf_phy *phy, uint32_t idx_reg, + struct rf_rx_gain *rx_gain) +{ + struct spi_desc *spi = phy->spi; + int32_t rc = 0; + + if ((rx_gain->fgt_lmt_index > MAX_LMT_INDEX) || + (rx_gain->lpf_gain > MAX_LPF_GAIN) || + (rx_gain->digital_gain > MAX_DIG_GAIN)) { + dev_err(dev, "LMT_INDEX missing or greater than max value %d", + MAX_LMT_INDEX); + dev_err(dev, "LPF_GAIN missing or greater than max value %d", + MAX_LPF_GAIN); + dev_err(dev, "DIGITAL_GAIN cannot be more than %d", + MAX_DIG_GAIN); + rc = -EINVAL; + goto out; + } + + rc = find_table_index(phy, rx_gain->gain_db); + if (rc < 0) { + dev_err(dev, "Invalid gain %"PRId32", supported range [%d - %d]\n", + rx_gain->gain_db, phy->gt_info[ad9361_gt(phy)]. + abs_gain_tbl[0], + phy->gt_info[ad9361_gt(phy)].abs_gain_tbl + [phy->gt_info[ad9361_gt(phy)].max_index - 1]); + goto out; + } + + rx_gain->fgt_lmt_index = rc; + + rc = ad9361_spi_writef(spi, idx_reg, RX_FULL_TBL_IDX_MASK, + rx_gain->fgt_lmt_index); + if (rc < 0) + goto out; + rc = ad9361_spi_writef(spi, idx_reg + 1, RX_LPF_IDX_MASK, rx_gain->lpf_gain); + if (rc < 0) + goto out; + if (phy->pdata->gain_ctrl.dig_gain_en) { + rc = ad9361_spi_writef(spi, idx_reg + 2, RX_DIGITAL_IDX_MASK, + rx_gain->digital_gain); + } else if (rx_gain->digital_gain > 0) { + dev_err(dev, "Digital gain is disabled and cannot be set"); + } +out: + return rc; +} + +/** + * Set gain in Full Gain Table Mode (used only in Manual Gain Control Mode). + * @param phy The AD9361 state structure. + * @param idx_reg Register base address for the selected receiver + * @param rx_gain The rf_rx_gain struct containing the RF gain. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t set_full_table_gain(struct ad9361_rf_phy *phy, uint32_t idx_reg, + struct rf_rx_gain *rx_gain) +{ + struct spi_desc *spi = phy->spi; + int rc = 0; + + if (rx_gain->fgt_lmt_index != ((uint32_t)~0) || + rx_gain->lpf_gain != ((uint32_t)~0) || + rx_gain->digital_gain > 0) + dev_dbg(dev, + "Ignoring lmt/lpf/digital gains in Single Table mode"); + + rc = find_table_index(phy, rx_gain->gain_db); + if (rc < 0) { + dev_err(dev, "Invalid gain %"PRId32", supported range [%d - %d]\n", + rx_gain->gain_db, phy->gt_info[ad9361_gt(phy)]. + abs_gain_tbl[0], + phy->gt_info[ad9361_gt(phy)].abs_gain_tbl + [phy->gt_info[ad9361_gt(phy)].max_index - 1]); + goto out; + } + + rc = ad9361_spi_writef(spi, idx_reg, RX_FULL_TBL_IDX_MASK, rc); +out: + return rc; +} + +/** + * Set the RX gain for the selected channel. + * @param phy The AD9361 state structure. + * @param rx_id The desired channel number (0, 1). + * @param rx_gain The rf_rx_gain struct containing the RF gain. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_set_rx_gain(struct ad9361_rf_phy *phy, + uint32_t rx_id, struct rf_rx_gain *rx_gain) +{ + struct spi_desc *spi = phy->spi; + uint32_t val, idx_reg; + uint8_t gain_ctl_shift; + int32_t rc = 0; + + if (rx_id == 1) { + gain_ctl_shift = RX1_GAIN_CTRL_SHIFT; + idx_reg = REG_RX1_MANUAL_LMT_FULL_GAIN; + + } else if (rx_id == 2) { + gain_ctl_shift = RX2_GAIN_CTRL_SHIFT; + idx_reg = REG_RX2_MANUAL_LMT_FULL_GAIN; + } else { + dev_err(dev, "Unknown Rx path %"PRIu32, rx_id); + rc = -EINVAL; + goto out; + + } + + val = ad9361_spi_read(spi, REG_AGC_CONFIG_1); + val = (val >> gain_ctl_shift) & RX_GAIN_CTL_MASK; + + if (val != RX_GAIN_CTL_MGC) { + dev_dbg(dev, "Rx gain can be set in MGC mode only"); + rc = -EOPNOTSUPP; + goto out; + } + + if (has_split_gt && phy->pdata->split_gt) + rc = set_split_table_gain(phy, idx_reg, rx_gain); + else + rc = set_full_table_gain(phy, idx_reg, rx_gain); + + if (rc) { + dev_err(dev, "Unable to write gain tbl idx reg: %"PRIu32, idx_reg); + goto out; + } + +out: + return rc; + +} + +/** + * Update the Gain Control. + * @param phy The AD9361 state structure. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_gc_update(struct ad9361_rf_phy *phy) +{ + struct spi_desc *spi = phy->spi; + uint32_t clkrf; + uint32_t reg, delay_lna, settling_delay, dec_pow_meas_dur; + int32_t ret; + uint32_t fir_div; + + clkrf = clk_get_rate(phy, phy->ref_clk_scale[CLKRF_CLK]); + delay_lna = phy->pdata->elna_ctrl.settling_delay_ns; + + /* + * AGC Attack Delay (us)=ceiling((((0.2+Delay_LNA)*ClkRF+14))/(2*ClkRF))+1 + * ClkRF in MHz, delay in us + */ + + reg = (200 + delay_lna) / 2 + (14000000UL / (clkrf / 500U)); + reg = DIV_ROUND_UP(reg, 1000UL) + + phy->pdata->gain_ctrl.agc_attack_delay_extra_margin_us; + reg = clamp_t(uint8_t, reg, 0U, 31U); + ret = ad9361_spi_writef(spi, REG_AGC_ATTACK_DELAY, + AGC_ATTACK_DELAY(~0), reg); + + /* + * Peak Overload Wait Time (ClkRF cycles)=ceiling((0.1+Delay_LNA) *clkRF+1) + */ + + reg = (delay_lna + 100UL) * (clkrf / 1000UL); + reg = DIV_ROUND_UP(reg, 1000000UL) + 1; + reg = clamp_t(uint8_t, reg, 0U, 31U); + ret |= ad9361_spi_writef(spi, REG_PEAK_WAIT_TIME, + PEAK_OVERLOAD_WAIT_TIME(~0), reg); + + /* + * Settling Delay in 0x111. Applies to all gain control modes: + * 0x111[D4:D0]= ceiling(((0.2+Delay_LNA)*clkRF + dodebug = false;+14)/2) + */ + + reg = (delay_lna + 200UL) * (clkrf / 2000UL); + reg = DIV_ROUND_UP(reg, 1000000UL) + 7; + reg = settling_delay = clamp_t(uint8_t, reg, 0U, 31U); + ret |= ad9361_spi_writef(spi, REG_FAST_CONFIG_2_SETTLING_DELAY, + SETTLING_DELAY(~0), reg); + + /* + * Gain Update Counter [15:0]= round((((time*ClkRF-0x111[D4:D0]*2)-2))/2) + */ + reg = phy->pdata->gain_ctrl.gain_update_interval_us * (clkrf / 1000UL) - + settling_delay * 2000UL - 2000UL; + + reg = DIV_ROUND_CLOSEST(reg, 2000UL); + reg = clamp_t(uint32_t, reg, 0U, 131071UL); + + if (phy->agc_mode[0] == RF_GAIN_FASTATTACK_AGC || + phy->agc_mode[1] == RF_GAIN_FASTATTACK_AGC) { + dec_pow_meas_dur = + phy->pdata->gain_ctrl.f_agc_dec_pow_measuremnt_duration; + } else { + fir_div = DIV_ROUND_CLOSEST(clkrf, + clk_get_rate(phy, phy->ref_clk_scale[RX_SAMPL_CLK])); + dec_pow_meas_dur = phy->pdata->gain_ctrl.dec_pow_measuremnt_duration; + + if (((reg * 2 / fir_div) / dec_pow_meas_dur) < 2) { + dec_pow_meas_dur = reg / fir_div; + } + } + + /* Power Measurement Duration */ + ad9361_spi_writef(spi, REG_DEC_POWER_MEASURE_DURATION_0, + DEC_POWER_MEASUREMENT_DURATION(~0), + ilog2(dec_pow_meas_dur / 16)); + + + ret |= ad9361_spi_writef(spi, REG_DIGITAL_SAT_COUNTER, + DOUBLE_GAIN_COUNTER, reg > 65535); + + if (reg > 65535) + reg /= 2; + + ret |= ad9361_spi_write(spi, REG_GAIN_UPDATE_COUNTER1, reg & 0xFF); + ret |= ad9361_spi_write(spi, REG_GAIN_UPDATE_COUNTER2, reg >> 8); + + /* + * Fast AGC State Wait Time - Energy Detect Count + */ + + reg = DIV_ROUND_CLOSEST(phy->pdata->gain_ctrl.f_agc_state_wait_time_ns * + (clkrf / 1000UL), 1000000UL); + reg = clamp_t(uint32_t, reg, 0U, 31U); + ret |= ad9361_spi_writef(spi, REG_FAST_ENERGY_DETECT_COUNT, + ENERGY_DETECT_COUNT(~0), reg); + + return ret; +} + +/** + * Set the gain control mode. + * @param phy The AD9361 state structure. + * @param gain_ctrl A rf_gain_ctrl struct that contains the the desired + * channel information and the gain control mode. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_set_gain_ctrl_mode(struct ad9361_rf_phy *phy, + struct rf_gain_ctrl *gain_ctrl) +{ + struct spi_desc *spi = phy->spi; + int32_t rc = 0; + uint32_t gain_ctl_shift, mode; + uint8_t val; + + rc = ad9361_spi_readm(spi, REG_AGC_CONFIG_1, &val, 1); + if (rc) { + dev_err(dev, "Unable to read AGC config1 register: %x", + REG_AGC_CONFIG_1); + goto out; + } + + switch (gain_ctrl->mode) { + case RF_GAIN_MGC: + mode = RX_GAIN_CTL_MGC; + break; + case RF_GAIN_FASTATTACK_AGC: + mode = RX_GAIN_CTL_AGC_FAST_ATK; + break; + case RF_GAIN_SLOWATTACK_AGC: + mode = RX_GAIN_CTL_AGC_SLOW_ATK; + break; + case RF_GAIN_HYBRID_AGC: + mode = RX_GAIN_CTL_AGC_SLOW_ATK_HYBD; + break; + default: + rc = -EINVAL; + goto out; + } + + if (gain_ctrl->ant == 1) { + gain_ctl_shift = RX1_GAIN_CTRL_SHIFT; + } else if (gain_ctrl->ant == 2) { + gain_ctl_shift = RX2_GAIN_CTRL_SHIFT; + } else { + dev_err(dev, "Unknown Rx path %"PRIu32, gain_ctrl->ant); + rc = -EINVAL; + goto out; + } + + rc = ad9361_en_dis_rx(phy, gain_ctrl->ant, RX_DISABLE); + if (rc) { + dev_err(dev, "Unable to disable rx%"PRIu32, gain_ctrl->ant); + goto out; + } + + val &= ~(RX_GAIN_CTL_MASK << gain_ctl_shift); + val |= mode << gain_ctl_shift; + if (mode == RX_GAIN_CTL_AGC_SLOW_ATK_HYBD) + val |= SLOW_ATTACK_HYBRID_MODE; + else + val &= ~SLOW_ATTACK_HYBRID_MODE; + + rc = ad9361_spi_write(spi, REG_AGC_CONFIG_1, val); + if (rc) { + dev_err(dev, "Unable to write AGC config1 register: %x", + REG_AGC_CONFIG_1); + goto out; + } + + ad9361_en_dis_rx(phy, gain_ctrl->ant, RX_ENABLE); + rc = ad9361_gc_update(phy); +out: + return rc; +} + +/** + * Get the RSSI. + * @param phy The AD9361 state structure. + * @param rssi A rf_rssi struct to store the RSSI. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_read_rssi(struct ad9361_rf_phy *phy, struct rf_rssi *rssi) +{ + struct spi_desc *spi = phy->spi; + uint8_t reg_val_buf[6]; + int32_t rc; + + rc = ad9361_spi_readm(spi, REG_PREAMBLE_LSB, + reg_val_buf, ARRAY_SIZE(reg_val_buf)); + if (rssi->ant == 1) { + rssi->symbol = RSSI_RESOLUTION * + ((reg_val_buf[5] << RSSI_LSB_SHIFT) + + (reg_val_buf[1] & RSSI_LSB_MASK1)); + rssi->preamble = RSSI_RESOLUTION * + ((reg_val_buf[4] << RSSI_LSB_SHIFT) + + (reg_val_buf[0] & RSSI_LSB_MASK1)); + } else if (rssi->ant == 2) { + rssi->symbol = RSSI_RESOLUTION * + ((reg_val_buf[3] << RSSI_LSB_SHIFT) + + ((reg_val_buf[1] & RSSI_LSB_MASK2) >> 1)); + rssi->preamble = RSSI_RESOLUTION * + ((reg_val_buf[2] << RSSI_LSB_SHIFT) + + ((reg_val_buf[0] & RSSI_LSB_MASK2) >> 1)); + } else + rc = -EFAULT; + + rssi->multiplier = RSSI_MULTIPLIER; + + return rc; +} + +/** + * Setup the RX ADC. + * @param phy The AD9361 state structure. + * @param bbpll_freq The BBPLL frequency [Hz]. + * @param adc_sampl_freq_Hz The ADC sampling frequency [Hz]. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_rx_adc_setup(struct ad9361_rf_phy *phy, + uint32_t bbpll_freq, + uint32_t adc_sampl_freq_Hz) +{ + + uint32_t scale_snr_1e3, maxsnr, sqrt_inv_rc_tconst_1e3, tmp_1e3, + scaled_adc_clk_1e6, inv_scaled_adc_clk_1e3, sqrt_term_1e3, + min_sqrt_term_1e3, bb_bw_Hz; + uint64_t tmp, invrc_tconst_1e6; + uint8_t data[40]; + uint32_t i; + int32_t ret; + + uint8_t c3_msb = ad9361_spi_read(phy->spi, REG_RX_BBF_C3_MSB); + uint8_t c3_lsb = ad9361_spi_read(phy->spi, REG_RX_BBF_C3_LSB); + uint8_t r2346 = ad9361_spi_read(phy->spi, REG_RX_BBF_R2346); + + /* + * BBBW = (BBPLL / RxTuneDiv) * ln(2) / (1.4 * 2PI ) + * We assume ad9361_rx_bb_analog_filter_calib() is always run prior + */ + + tmp = bbpll_freq * 10000ULL; + do_div(&tmp, 126906UL * phy->rxbbf_div); + bb_bw_Hz = tmp; + + dev_dbg(&phy->spi->dev, "%s : BBBW %"PRIu32" : ADCfreq %"PRIu32, + __func__, bb_bw_Hz, adc_sampl_freq_Hz); + + dev_dbg(&phy->spi->dev, "c3_msb 0x%X : c3_lsb 0x%X : r2346 0x%X : ", + c3_msb, c3_lsb, r2346); + + bb_bw_Hz = clamp(bb_bw_Hz, 200000UL, 28000000UL); + + if (adc_sampl_freq_Hz < 80000000) + scale_snr_1e3 = 1000; + else + scale_snr_1e3 = 1585; /* pow(10, scale_snr_dB/10); */ + + if (bb_bw_Hz >= 18000000) { + invrc_tconst_1e6 = (160975ULL * r2346 * + (160 * c3_msb + 10 * c3_lsb + 140) * + (bb_bw_Hz)* (1000 + (10 * (bb_bw_Hz - 18000000) / 1000000))); + + do_div(&invrc_tconst_1e6, 1000UL); + + } else { + invrc_tconst_1e6 = (160975ULL * r2346 * + (160 * c3_msb + 10 * c3_lsb + 140) * + (bb_bw_Hz)); + } + + do_div(&invrc_tconst_1e6, 1000000000UL); + + if (invrc_tconst_1e6 > ULONG_MAX) + dev_err(&phy->spi->dev, "invrc_tconst_1e6 > ULONG_MAX"); + + sqrt_inv_rc_tconst_1e3 = int_sqrt((uint32_t)invrc_tconst_1e6); + maxsnr = 640 / 160; + scaled_adc_clk_1e6 = DIV_ROUND_CLOSEST(adc_sampl_freq_Hz, 640); + inv_scaled_adc_clk_1e3 = DIV_ROUND_CLOSEST(640000000, + DIV_ROUND_CLOSEST(adc_sampl_freq_Hz, 1000)); + tmp_1e3 = DIV_ROUND_CLOSEST(980000 + 20 * max_t(uint32_t, 1000U, + DIV_ROUND_CLOSEST(inv_scaled_adc_clk_1e3, maxsnr)), 1000); + sqrt_term_1e3 = int_sqrt(scaled_adc_clk_1e6); + min_sqrt_term_1e3 = min_t(uint32_t, 1000U, + int_sqrt(maxsnr * scaled_adc_clk_1e6)); + + dev_dbg(&phy->spi->dev, + "invrc_tconst_1e6 %"PRIu64", sqrt_inv_rc_tconst_1e3 %"PRIu32, + invrc_tconst_1e6, sqrt_inv_rc_tconst_1e3); + dev_dbg(&phy->spi->dev, + "scaled_adc_clk_1e6 %"PRIu32", inv_scaled_adc_clk_1e3 %"PRIu32, + scaled_adc_clk_1e6, inv_scaled_adc_clk_1e3); + dev_dbg(&phy->spi->dev, + "tmp_1e3 %"PRIu32", sqrt_term_1e3 %"PRIu32", min_sqrt_term_1e3 %"PRIu32, + tmp_1e3, sqrt_term_1e3, min_sqrt_term_1e3); + + data[0] = 0; + data[1] = 0; + data[2] = 0; + data[3] = 0x24; + data[4] = 0x24; + data[5] = 0; + data[6] = 0; + + tmp = -50000000 + 8ULL * scale_snr_1e3 * sqrt_inv_rc_tconst_1e3 * + min_sqrt_term_1e3; + do_div(&tmp, 100000000UL); + data[7] = min_t(uint64_t, 124U, tmp); + + tmp = (invrc_tconst_1e6 >> 1) + 20 * inv_scaled_adc_clk_1e3 * + data[7] / 80 * 1000ULL; + do_div(&tmp, invrc_tconst_1e6); + data[8] = min_t(uint64_t, 255U, tmp); + + tmp = (-500000 + 77ULL * sqrt_inv_rc_tconst_1e3 * min_sqrt_term_1e3); + do_div(&tmp, 1000000UL); + data[10] = min_t(uint64_t, 127U, tmp); + + data[9] = min_t(uint32_t, 127U, ((800 * data[10]) / 1000)); + tmp = ((invrc_tconst_1e6 >> 1) + (20 * inv_scaled_adc_clk_1e3 * + data[10] * 1000ULL)); + do_div(&tmp, invrc_tconst_1e6 * 77); + data[11] = min_t(uint64_t, 255U, tmp); + data[12] = min_t(uint32_t, 127U, (-500000 + 80 * sqrt_inv_rc_tconst_1e3 * + min_sqrt_term_1e3) / 1000000UL); + + tmp = -3 * (long)(invrc_tconst_1e6 >> 1) + inv_scaled_adc_clk_1e3 * + data[12] * (1000ULL * 20 / 80); + do_div(&tmp, invrc_tconst_1e6); + data[13] = min_t(uint64_t, 255, tmp); + + data[14] = 21 * (inv_scaled_adc_clk_1e3 / 10000); + data[15] = min_t(uint32_t, 127U, (500 + 1025 * data[7]) / 1000); + data[16] = min_t(uint32_t, 127U, (data[15] * tmp_1e3) / 1000); + data[17] = data[15]; + data[18] = min_t(uint32_t, 127U, (500 + 975 * data[10]) / 1000); + data[19] = min_t(uint32_t, 127U, (data[18] * tmp_1e3) / 1000); + data[20] = data[18]; + data[21] = min_t(uint32_t, 127U, (500 + 975 * data[12]) / 1000); + data[22] = min_t(uint32_t, 127, (data[21] * tmp_1e3) / 1000); + data[23] = data[21]; + data[24] = 0x2E; + data[25] = (128 + min_t(uint32_t, 63000U, DIV_ROUND_CLOSEST(63 * + scaled_adc_clk_1e6, 1000)) / 1000); + data[26] = min_t(uint32_t, 63U, 63 * scaled_adc_clk_1e6 / 1000000 * + (920 + 80 * inv_scaled_adc_clk_1e3 / 1000) / 1000); + data[27] = min_t(uint32_t, 63, (32 * sqrt_term_1e3) / 1000); + data[28] = data[25]; + data[29] = data[26]; + data[30] = data[27]; + data[31] = data[25]; + data[32] = data[26]; + data[33] = min_t(uint32_t, 63U, 63 * sqrt_term_1e3 / 1000); + data[34] = min_t(uint32_t, 127U, 64 * sqrt_term_1e3 / 1000); + data[35] = 0x40; + data[36] = 0x40; + data[37] = 0x2C; + data[38] = 0x00; + data[39] = 0x00; + + for (i = 0; i < 40; i++) { + ret = ad9361_spi_write(phy->spi, 0x200 + i, data[i]); + if (ret < 0) + return ret; + } + + return 0; +} + +/** + * Perform a RX TIA calibration. + * @param phy The AD9361 state structure. + * @param bb_bw_Hz The baseband bandwidth [Hz]. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_rx_tia_calib(struct ad9361_rf_phy *phy, uint32_t bb_bw_Hz) +{ + uint32_t Cbbf, R2346; + uint64_t CTIA_fF; + + uint8_t reg1EB = ad9361_spi_read(phy->spi, REG_RX_BBF_C3_MSB); + uint8_t reg1EC = ad9361_spi_read(phy->spi, REG_RX_BBF_C3_LSB); + uint8_t reg1E6 = ad9361_spi_read(phy->spi, REG_RX_BBF_R2346); + uint8_t reg1DB, reg1DF, reg1DD, reg1DC, reg1DE, temp; + + dev_dbg(&phy->spi->dev, "%s : bb_bw_Hz %"PRIu32, + __func__, bb_bw_Hz); + + bb_bw_Hz = clamp(bb_bw_Hz, 200000UL, 20000000UL); + + Cbbf = (reg1EB * 160) + (reg1EC * 10) + 140; /* fF */ + R2346 = 18300 * RX_BBF_R2346(reg1E6); + + CTIA_fF = Cbbf * R2346 * 560ULL; + do_div(&CTIA_fF, 3500000UL); + + if (bb_bw_Hz <= 3000000UL) + reg1DB = 0xE0; + else if (bb_bw_Hz <= 10000000UL) + reg1DB = 0x60; + else + reg1DB = 0x20; + + if (CTIA_fF > 2920ULL) { + reg1DC = 0x40; + reg1DE = 0x40; + temp = min(127U, DIV_ROUND_CLOSEST((uint32_t)CTIA_fF - 400, 320U)); + reg1DD = temp; + reg1DF = temp; + } else { + temp = DIV_ROUND_CLOSEST((uint32_t)CTIA_fF - 400, 40U) + 0x40; + reg1DC = temp; + reg1DE = temp; + reg1DD = 0; + reg1DF = 0; + } + + ad9361_spi_write(phy->spi, REG_RX_TIA_CONFIG, reg1DB); + ad9361_spi_write(phy->spi, REG_TIA1_C_LSB, reg1DC); + ad9361_spi_write(phy->spi, REG_TIA1_C_MSB, reg1DD); + ad9361_spi_write(phy->spi, REG_TIA2_C_LSB, reg1DE); + ad9361_spi_write(phy->spi, REG_TIA2_C_MSB, reg1DF); + + return 0; +} + +/** + * Perform a baseband RX analog filter calibration. + * @param phy The AD9361 state structure. + * @param rx_bb_bw The baseband bandwidth [Hz]. + * @param bbpll_freq The BBPLL frequency [Hz]. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_rx_bb_analog_filter_calib(struct ad9361_rf_phy *phy, + uint32_t rx_bb_bw, + uint32_t bbpll_freq) +{ + uint32_t target; + uint8_t tmp; + int32_t ret; + + dev_dbg(&phy->spi->dev, "%s : rx_bb_bw %"PRIu32" bbpll_freq %"PRIu32, + __func__, rx_bb_bw, bbpll_freq); + + rx_bb_bw = clamp(rx_bb_bw, 200000UL, 28000000UL); + + /* 1.4 * BBBW * 2PI / ln(2) */ + target = 126906UL * (rx_bb_bw / 10000UL); + phy->rxbbf_div = min_t(uint32_t, 511UL, DIV_ROUND_UP(bbpll_freq, target)); + + /* Set RX baseband filter divide value */ + ad9361_spi_write(phy->spi, REG_RX_BBF_TUNE_DIVIDE, phy->rxbbf_div); + ad9361_spi_writef(phy->spi, REG_RX_BBF_TUNE_CONFIG, BIT(0), + phy->rxbbf_div >> 8); + + /* Write the BBBW into registers 0x1FB and 0x1FC */ + ad9361_spi_write(phy->spi, REG_RX_BBBW_MHZ, rx_bb_bw / 1000000UL); + + tmp = DIV_ROUND_CLOSEST((rx_bb_bw % 1000000UL) * 128, 1000000UL); + ad9361_spi_write(phy->spi, REG_RX_BBBW_KHZ, min_t(uint8_t, 127, tmp)); + + ad9361_spi_write(phy->spi, REG_RX_MIX_LO_CM, + RX_MIX_LO_CM(0x3F)); /* Set Rx Mix LO CM */ + ad9361_spi_write(phy->spi, REG_RX_MIX_GM_CONFIG, + RX_MIX_GM_PLOAD(3)); /* Set GM common mode */ + + /* Enable the RX BBF tune circuit by writing 0x1E2=0x02 and 0x1E3=0x02 */ + ad9361_spi_write(phy->spi, REG_RX1_TUNE_CTRL, RX1_TUNE_RESAMPLE); + ad9361_spi_write(phy->spi, REG_RX2_TUNE_CTRL, RX2_TUNE_RESAMPLE); + + /* Start the RX Baseband Filter calibration in register 0x016[7] */ + /* Calibration is complete when register 0x016[7] self clears */ + ret = ad9361_run_calibration(phy, RX_BB_TUNE_CAL); + + /* Disable the RX baseband filter tune circuit, write 0x1E2=3, 0x1E3=3 */ + ad9361_spi_write(phy->spi, REG_RX1_TUNE_CTRL, + RX1_TUNE_RESAMPLE | RX1_PD_TUNE); + ad9361_spi_write(phy->spi, REG_RX2_TUNE_CTRL, + RX2_TUNE_RESAMPLE | RX2_PD_TUNE); + + return ret; +} + +/** + * Perform a baseband TX analog filter calibration. + * @param phy The AD9361 state structure. + * @param tx_bb_bw The baseband bandwidth [Hz]. + * @param bbpll_freq The BBPLL frequency [Hz]. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_tx_bb_analog_filter_calib(struct ad9361_rf_phy *phy, + uint32_t tx_bb_bw, + uint32_t bbpll_freq) +{ + uint32_t target, txbbf_div; + int32_t ret; + + dev_dbg(&phy->spi->dev, "%s : tx_bb_bw %"PRIu32" bbpll_freq %"PRIu32, + __func__, tx_bb_bw, bbpll_freq); + + tx_bb_bw = clamp(tx_bb_bw, 625000UL, 20000000UL); + + /* 1.6 * BBBW * 2PI / ln(2) */ + target = 145036 * (tx_bb_bw / 10000UL); + txbbf_div = min_t(uint32_t, 511UL, DIV_ROUND_UP(bbpll_freq, target)); + + /* Set TX baseband filter divide value */ + ad9361_spi_write(phy->spi, REG_TX_BBF_TUNE_DIVIDER, txbbf_div); + ad9361_spi_writef(phy->spi, REG_TX_BBF_TUNE_MODE, + TX_BBF_TUNE_DIVIDER, txbbf_div >> 8); + + /* Enable the TX baseband filter tune circuit by setting 0x0CA=0x22. */ + ad9361_spi_write(phy->spi, REG_TX_TUNE_CTRL, TUNER_RESAMPLE | TUNE_CTRL(1)); + + /* Start the TX Baseband Filter calibration in register 0x016[6] */ + /* Calibration is complete when register 0x016[] self clears */ + ret = ad9361_run_calibration(phy, TX_BB_TUNE_CAL); + + /* Disable the TX baseband filter tune circuit by writing 0x0CA=0x26. */ + ad9361_spi_write(phy->spi, REG_TX_TUNE_CTRL, + TUNER_RESAMPLE | TUNE_CTRL(1) | PD_TUNE); + + return ret; +} + +/** + * Perform a baseband TX secondary filter calibration. + * @param phy The AD9361 state structure. + * @param tx_rf_bw The RF bandwidth [Hz]. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_tx_bb_second_filter_calib(struct ad9361_rf_phy *phy, + uint32_t tx_bb_bw) +{ + uint64_t cap; + uint32_t corner, res, div; + uint32_t reg_conf, reg_res; + int32_t ret, i; + + dev_dbg(&phy->spi->dev, "%s : tx_bb_bw %"PRIu32, + __func__, tx_bb_bw); + + tx_bb_bw = clamp(tx_bb_bw, 530000UL, 20000000UL); + + /* BBBW * 5PI */ + corner = 15708 * (tx_bb_bw / 10000UL); + + for (i = 0, res = 1; i < 4; i++) { + div = corner * res; + cap = (500000000ULL) + (div >> 1); + do_div(&cap, div); + cap -= 12ULL; + if (cap < 64ULL) + break; + + res <<= 1; + } + + if (cap > 63ULL) + cap = 63ULL; + + if (tx_bb_bw <= 4500000UL) + reg_conf = 0x59; + else if (tx_bb_bw <= 12000000UL) + reg_conf = 0x56; + else + reg_conf = 0x57; + + switch (res) { + case 1: + reg_res = 0x0C; + break; + case 2: + reg_res = 0x04; + break; + case 4: + reg_res = 0x03; + break; + case 8: + reg_res = 0x01; + break; + default: + reg_res = 0x01; + } + + ret = ad9361_spi_write(phy->spi, REG_CONFIG0, reg_conf); + ret |= ad9361_spi_write(phy->spi, REG_RESISTOR, reg_res); + ret |= ad9361_spi_write(phy->spi, REG_CAPACITOR, (uint8_t)cap); + + return ret; +} + +/** + * Perform a RF synthesizer charge pump calibration. + * @param phy The AD9361 state structure. + * @param ref_clk_hz The reference clock rate [Hz]. + * @param tx The Synthesizer TX = 1, RX = 0. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_txrx_synth_cp_calib(struct ad9361_rf_phy *phy, + uint32_t ref_clk_hz, bool tx) +{ + uint32_t offs = tx ? 0x40 : 0; + uint32_t vco_cal_cnt; + dev_dbg(&phy->spi->dev, "%s : ref_clk_hz %"PRIu32" : is_tx %d", + __func__, ref_clk_hz, tx); + + /* REVIST: */ + ad9361_spi_write(phy->spi, REG_RX_CP_LEVEL_DETECT + offs, 0x17); + + ad9361_spi_write(phy->spi, REG_RX_DSM_SETUP_1 + offs, 0x0); + + ad9361_spi_write(phy->spi, REG_RX_LO_GEN_POWER_MODE + offs, 0x00); + ad9361_spi_write(phy->spi, REG_RX_VCO_LDO + offs, 0x0B); + ad9361_spi_write(phy->spi, REG_RX_VCO_PD_OVERRIDES + offs, 0x02); + ad9361_spi_write(phy->spi, REG_RX_CP_CURRENT + offs, 0x80); + ad9361_spi_write(phy->spi, REG_RX_CP_CONFIG + offs, CP_OFFSET_OFF); + + /* see Table 70 Example Calibration Times for RF VCO Cal */ + if (phy->pdata->fdd) { + vco_cal_cnt = VCO_CAL_EN | VCO_CAL_COUNT(3) | FB_CLOCK_ADV(2); + } else { + if (ref_clk_hz > 40000000UL) + vco_cal_cnt = VCO_CAL_EN | VCO_CAL_COUNT(1) | + FB_CLOCK_ADV(2); + else + vco_cal_cnt = VCO_CAL_EN | VCO_CAL_COUNT(0) | + FB_CLOCK_ADV(2); + } + + ad9361_spi_write(phy->spi, REG_RX_VCO_CAL + offs, vco_cal_cnt); + + /* Enable FDD mode during calibrations */ + + if (!phy->pdata->fdd) { + ad9361_spi_writef(phy->spi, REG_PARALLEL_PORT_CONF_3, + HALF_DUPLEX_MODE, 0); + } + + ad9361_spi_write(phy->spi, REG_ENSM_CONFIG_2, DUAL_SYNTH_MODE); + ad9361_spi_write(phy->spi, REG_ENSM_CONFIG_1, + FORCE_ALERT_STATE | + TO_ALERT); + ad9361_spi_write(phy->spi, REG_ENSM_MODE, FDD_MODE); + + ad9361_spi_write(phy->spi, REG_RX_CP_CONFIG + offs, + CP_OFFSET_OFF | CP_CAL_ENABLE); + + return ad9361_check_cal_done(phy, REG_RX_CAL_STATUS + offs, + CP_CAL_VALID, 1); +} + +/** + * Perform a baseband DC offset calibration. + * @param phy The AD9361 state structure. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_bb_dc_offset_calib(struct ad9361_rf_phy *phy) +{ + dev_dbg(&phy->spi->dev, "%s", __func__); + + ad9361_spi_write(phy->spi, REG_BB_DC_OFFSET_COUNT, 0x3F); + ad9361_spi_write(phy->spi, REG_BB_DC_OFFSET_SHIFT, BB_DC_M_SHIFT(0xF)); + ad9361_spi_write(phy->spi, REG_BB_DC_OFFSET_ATTEN, BB_DC_OFFSET_ATTEN(1)); + + return ad9361_run_calibration(phy, BBDC_CAL); +} + +/** + * Perform a RF DC offset calibration. + * @param phy The AD9361 state structure. + * @param ref_clk_hz The RX LO frequency [Hz]. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_rf_dc_offset_calib(struct ad9361_rf_phy *phy, + uint64_t rx_freq) +{ + struct spi_desc *spi = phy->spi; + + dev_dbg(&phy->spi->dev, "%s : rx_freq %"PRIu64, + __func__, rx_freq); + + ad9361_spi_write(spi, REG_WAIT_COUNT, 0x20); + + if (rx_freq <= 4000000000ULL) { + ad9361_spi_write(spi, REG_RF_DC_OFFSET_COUNT, + phy->pdata->rf_dc_offset_count_low); + ad9361_spi_write(spi, REG_RF_DC_OFFSET_CONFIG_1, + RF_DC_CALIBRATION_COUNT(4) | DAC_FS(2)); + ad9361_spi_write(spi, REG_RF_DC_OFFSET_ATTEN, + RF_DC_OFFSET_ATTEN( + phy->pdata->dc_offset_attenuation_low)); + } else { + ad9361_spi_write(spi, REG_RF_DC_OFFSET_COUNT, + phy->pdata->rf_dc_offset_count_high); + ad9361_spi_write(spi, REG_RF_DC_OFFSET_CONFIG_1, + RF_DC_CALIBRATION_COUNT(4) | DAC_FS(3)); + ad9361_spi_write(spi, REG_RF_DC_OFFSET_ATTEN, + RF_DC_OFFSET_ATTEN( + phy->pdata->dc_offset_attenuation_high)); + } + + ad9361_spi_write(spi, REG_DC_OFFSET_CONFIG2, + USE_WAIT_COUNTER_FOR_RF_DC_INIT_CAL | + DC_OFFSET_UPDATE(3)); + + if (phy->pdata->rx1rx2_phase_inversion_en || + (phy->pdata->port_ctrl.pp_conf[1] & INVERT_RX2)) { + ad9361_spi_write(spi, REG_INVERT_BITS, + INVERT_RX1_RF_DC_CGOUT_WORD); + } else { + ad9361_spi_write(spi, REG_INVERT_BITS, + INVERT_RX1_RF_DC_CGOUT_WORD | + INVERT_RX2_RF_DC_CGOUT_WORD); + } + + return ad9361_run_calibration(phy, RFDC_CAL); +} + +/** + * Update RF bandwidth. + * @param phy The AD9361 state structure. + * @param rf_rx_bw RF RX bandwidth [Hz]. + * @param rf_tx_bw RF TX bandwidth [Hz]. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t __ad9361_update_rf_bandwidth(struct ad9361_rf_phy *phy, + uint32_t rf_rx_bw, uint32_t rf_tx_bw) +{ + uint32_t real_rx_bandwidth = rf_rx_bw / 2; + uint32_t real_tx_bandwidth = rf_tx_bw / 2; + uint32_t bbpll_freq; + int32_t ret; + + dev_dbg(&phy->spi->dev, "%s: %"PRIu32" %"PRIu32, + __func__, rf_rx_bw, rf_tx_bw); + + bbpll_freq = clk_get_rate(phy, phy->ref_clk_scale[BBPLL_CLK]); + + ret = ad9361_rx_bb_analog_filter_calib(phy, + real_rx_bandwidth, + bbpll_freq); + if (ret < 0) + return ret; + + ret = ad9361_tx_bb_analog_filter_calib(phy, + real_tx_bandwidth, + bbpll_freq); + if (ret < 0) + return ret; + + ret = ad9361_rx_tia_calib(phy, real_rx_bandwidth); + if (ret < 0) + return ret; + + ret = ad9361_tx_bb_second_filter_calib(phy, real_tx_bandwidth); + if (ret < 0) + return ret; + + ret = ad9361_rx_adc_setup(phy, + bbpll_freq, + clk_get_rate(phy, phy->ref_clk_scale[ADC_CLK])); + if (ret < 0) + return ret; + + return 0; +} + +/** + * TX Quad Calib. + * @param phy The AD9361 state structure. + * @param phase phase + * @param rxnco_word Rx NCO word. + * @param decim decim + * @param res res + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t __ad9361_tx_quad_calib(struct ad9361_rf_phy *phy, uint32_t phase, + uint32_t rxnco_word, uint32_t decim, uint8_t *res) +{ + int32_t ret; + + ad9361_spi_write(phy->spi, REG_QUAD_CAL_NCO_FREQ_PHASE_OFFSET, + RX_NCO_FREQ(rxnco_word) | RX_NCO_PHASE_OFFSET(phase)); + ad9361_spi_write(phy->spi, REG_QUAD_CAL_CTRL, + SETTLE_MAIN_ENABLE | DC_OFFSET_ENABLE | QUAD_CAL_SOFT_RESET | + GAIN_ENABLE | PHASE_ENABLE | M_DECIM(decim)); + ad9361_spi_write(phy->spi, REG_QUAD_CAL_CTRL, + SETTLE_MAIN_ENABLE | DC_OFFSET_ENABLE | + GAIN_ENABLE | PHASE_ENABLE | M_DECIM(decim)); + + ret = ad9361_run_calibration(phy, TX_QUAD_CAL); + if (ret < 0) + return ret; + + if (res) { + *res = ad9361_spi_read(phy->spi, + (phy->pdata->rx1tx1_mode_use_tx_num == 2) ? + REG_QUAD_CAL_STATUS_TX2 : REG_QUAD_CAL_STATUS_TX1) & + (TX1_LO_CONV | TX1_SSB_CONV); + if (phy->pdata->rx2tx2) + *res &= ad9361_spi_read(phy->spi, REG_QUAD_CAL_STATUS_TX2) & + (TX2_LO_CONV | TX2_SSB_CONV); + } + + return 0; +} + +/** + * Loop through all possible phase offsets in case the QUAD CAL doesn't converge. + * @param phy The AD9361 state structure. + * @param rxnco_word Rx NCO word. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_tx_quad_phase_search(struct ad9361_rf_phy *phy, + uint32_t rxnco_word, uint8_t decim) +{ + int32_t i, ret; + uint8_t field[64], val; + uint32_t start; + + dev_dbg(&phy->spi->dev, "%s", __func__); + + for (i = 0; i < (int64_t)(ARRAY_SIZE(field) / 2); i++) { + ret = __ad9361_tx_quad_calib(phy, i, rxnco_word, decim, &val); + if (ret < 0) + return ret; + + /* Handle 360/0 wrap around */ + field[i] = field[i + 32] = !((val & TX1_LO_CONV) && (val & TX1_SSB_CONV)); + } + + ret = ad9361_find_opt(field, ARRAY_SIZE(field), &start); + + phy->last_tx_quad_cal_phase = (start + ret / 2) & 0x1F; + +#ifdef _DEBUG + for (i = 0; i < 64; i++) { + printk("%c", (field[i] ? '#' : 'o')); + } +#ifdef WIN32 + printk(" RX_NCO_PHASE_OFFSET(%d, 0x%X) \n", phy->last_tx_quad_cal_phase, + phy->last_tx_quad_cal_phase); +#else + printk(" RX_NCO_PHASE_OFFSET(%"PRIu32", 0x%"PRIX32") \n", + phy->last_tx_quad_cal_phase, + phy->last_tx_quad_cal_phase); +#endif +#endif + + ret = __ad9361_tx_quad_calib(phy, phy->last_tx_quad_cal_phase, rxnco_word, + decim, NULL); + if (ret < 0) + return ret; + + return 0; +} + +/** + * Perform a TX quadrature calibration. + * @param phy The AD9361 state structure. + * @param bw The bandwidth [Hz]. + * @param rx_phase The optional RX phase value overwrite (set to zero). + * @return 0 in case of success, negative error code otherwise. + */ + +static int ad9361_tx_quad_calib(struct ad9361_rf_phy *phy, + uint32_t bw_rx, uint32_t bw_tx, + int32_t rx_phase) +{ + struct spi_desc *spi = phy->spi; + uint32_t clktf, clkrf; + int32_t txnco_word, rxnco_word, txnco_freq, ret; + uint8_t __rx_phase = 0, reg_inv_bits = 0, val, decim; + bool phase_inversion_en; + + ret = 0; + if (phy->cached_synth_pd[0] & TX_LO_POWER_DOWN) { + if (phy->pdata->lo_powerdown_managed_en) { + ad9361_spi_writef(spi, REG_TX_SYNTH_POWER_DOWN_OVERRIDE, + TX_LO_POWER_DOWN, 0); + } else { + dev_err(dev, + "%s : Tx QUAD Cal abort due to TX LO in powerdown\n", + __func__); + return -EFAULT; + } + } + /* + * Find NCO frequency that matches this equation: + * BW / 4 = Rx NCO freq = Tx NCO freq: + * Rx NCO = ClkRF * (rxNCO <1:0> + 1) / 32 + * Tx NCO = ClkTF * (txNCO <1:0> + 1) / 32 + */ + + clkrf = clk_get_rate(phy, phy->ref_clk_scale[CLKRF_CLK]); + clktf = clk_get_rate(phy, phy->ref_clk_scale[CLKTF_CLK]); + + dev_dbg(&phy->spi->dev, "%s : bw_tx %"PRIu32" clkrf %"PRIu32" clktf %"PRIu32, + __func__, bw_tx, clkrf, clktf); + + txnco_word = DIV_ROUND_CLOSEST(bw_tx * 8, clktf) - 1; + txnco_word = clamp_t(int, txnco_word, 0, 3); + rxnco_word = txnco_word; + + dev_dbg(dev, "Tx NCO frequency: %"PRIu32" (BW/4: %"PRIu32") txnco_word %"PRId32, + clktf * (txnco_word + 1) / 32, bw_tx / 4, txnco_word); + + if (clktf <= 4000000UL) + decim = 2; + else + decim = 3; + + if (clkrf == (2 * clktf)) { + __rx_phase = 0x0E; + switch (txnco_word) { + case 0: + txnco_word++; + break; + case 1: + rxnco_word--; + break; + case 2: + rxnco_word -= 2; + txnco_word--; + break; + case 3: + rxnco_word -= 2; /* REVISIT */ + __rx_phase = 0x08; + break; + } + } else if (clkrf == clktf) { + switch (txnco_word) { + case 0: + case 3: + __rx_phase = 0x15; + break; + case 2: + __rx_phase = 0x1F; + break; + case 1: + if (ad9361_spi_readf(spi, + REG_TX_ENABLE_FILTER_CTRL, 0x3F) == 0x22) + __rx_phase = 0x15; /* REVISIT */ + else + __rx_phase = 0x1A; + break; + } + } else + dev_err(dev, "Unhandled case in %s line %d clkrf %"PRIu32" clktf %"PRIu32, + __func__, __LINE__, clkrf, clktf); + + if (rx_phase >= 0) + __rx_phase = rx_phase; + + txnco_freq = clktf * (txnco_word + 1) / 32; + + if (txnco_freq > (int64_t)(bw_rx / 4) || txnco_freq > (int64_t)(bw_tx / 4)) { + /* Make sure the BW during calibration is wide enough */ + ret = __ad9361_update_rf_bandwidth(phy, txnco_freq * 8, txnco_freq * 8); + if (ret < 0) + goto out_restore; + } + + phase_inversion_en = phy->pdata->rx1rx2_phase_inversion_en || + (phy->pdata->port_ctrl.pp_conf[1] & INVERT_RX2); + + if (phase_inversion_en) { + ad9361_spi_writef(spi, REG_PARALLEL_PORT_CONF_2, INVERT_RX2, 0); + + reg_inv_bits = ad9361_spi_read(spi, REG_INVERT_BITS); + + ad9361_spi_write(spi, REG_INVERT_BITS, + INVERT_RX1_RF_DC_CGOUT_WORD | + INVERT_RX2_RF_DC_CGOUT_WORD); + } + + ad9361_spi_writef(spi, REG_KEXP_2, TX_NCO_FREQ(~0), txnco_word); + ad9361_spi_write(spi, REG_QUAD_CAL_COUNT, 0xFF); + ad9361_spi_write(spi, REG_KEXP_1, KEXP_TX(1) | KEXP_TX_COMP(3) | + KEXP_DC_I(3) | KEXP_DC_Q(3)); + ad9361_spi_write(spi, REG_MAG_FTEST_THRESH, 0x03); + ad9361_spi_write(spi, REG_MAG_FTEST_THRESH_2, 0x03); + + if (phy->tx_quad_lpf_tia_match < 0) /* set in ad9361_load_gt() */ + dev_err(dev, "failed to find suitable LPF TIA value in gain table\n"); + else + ad9361_spi_write(spi, REG_TX_QUAD_FULL_LMT_GAIN, + phy->tx_quad_lpf_tia_match); + + ad9361_spi_write(spi, REG_QUAD_SETTLE_COUNT, 0xF0); + ad9361_spi_write(spi, REG_TX_QUAD_LPF_GAIN, 0x00); + + if (rx_phase != -2) { + ret = __ad9361_tx_quad_calib(phy, __rx_phase, rxnco_word, decim, &val); + + dev_dbg(dev, "LO leakage: %d Quadrature Calibration: %d : rx_phase %d\n", + !!(val & TX1_LO_CONV), !!(val & TX1_SSB_CONV), __rx_phase); + + /* Calibration failed -> try last phase offset */ + if (val != (TX1_LO_CONV | TX1_SSB_CONV)) { + if (phy->last_tx_quad_cal_phase < 31) + ret = __ad9361_tx_quad_calib(phy, phy->last_tx_quad_cal_phase, + rxnco_word, decim, &val); + } else { + phy->last_tx_quad_cal_phase = __rx_phase; + } + } else { + /* force phase search */ + val = 0; + } + /* Calibration failed -> loop through all 32 phase offsets */ + if (val != (TX1_LO_CONV | TX1_SSB_CONV)) + ret = ad9361_tx_quad_phase_search(phy, rxnco_word, decim); + + if (phase_inversion_en) { + ad9361_spi_writef(spi, REG_PARALLEL_PORT_CONF_2, INVERT_RX2, 1); + ad9361_spi_write(spi, REG_INVERT_BITS, reg_inv_bits); + } + + if (txnco_freq > (int64_t)(bw_rx / 4) || txnco_freq > (int64_t)(bw_tx / 4)) { + __ad9361_update_rf_bandwidth(phy, + phy->current_rx_bw_Hz, + phy->current_tx_bw_Hz); + } + +out_restore: + /* Restore synthesizer powerdown configuration */ + if (phy->pdata->lo_powerdown_managed_en && + (phy->cached_synth_pd[0] & TX_LO_POWER_DOWN)) + ad9361_synth_lo_powerdown(phy, LO_DONTCARE, LO_DONTCARE); + + return ret; +} + +/** + * Setup RX tracking calibrations. + * @param phy The AD9361 state structure. + * @param bbdc_track Set true, will enable the BBDC tracking. + * @param rfdc_track Set true, will enable the RFDC tracking. + * @param rxquad_track Set true, will enable the RXQUAD tracking. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_tracking_control(struct ad9361_rf_phy *phy, bool bbdc_track, + bool rfdc_track, bool rxquad_track) +{ + struct spi_desc *spi = phy->spi; + uint32_t qtrack = 0; + + dev_dbg(&spi->dev, "%s : bbdc_track=%d, rfdc_track=%d, rxquad_track=%d", + __func__, bbdc_track, rfdc_track, rxquad_track); + + ad9361_spi_write(spi, REG_CALIBRATION_CONFIG_2, + CALIBRATION_CONFIG2_DFLT | K_EXP_PHASE(0x15)); + ad9361_spi_write(spi, REG_CALIBRATION_CONFIG_3, + PREVENT_POS_LOOP_GAIN | K_EXP_AMPLITUDE(0x15)); + + ad9361_spi_write(spi, REG_DC_OFFSET_CONFIG2, + USE_WAIT_COUNTER_FOR_RF_DC_INIT_CAL | + DC_OFFSET_UPDATE(phy->pdata->dc_offset_update_events) | + (bbdc_track ? ENABLE_BB_DC_OFFSET_TRACKING : 0) | + (rfdc_track ? ENABLE_RF_OFFSET_TRACKING : 0)); + + ad9361_spi_writef(spi, REG_RX_QUAD_GAIN2, + CORRECTION_WORD_DECIMATION_M(~0), + phy->pdata->qec_tracking_slow_mode_en ? 4 : 0); + + if (rxquad_track) { + if (phy->pdata->rx2tx2) + qtrack = ENABLE_TRACKING_MODE_CH1 | ENABLE_TRACKING_MODE_CH2; + else + qtrack = (phy->pdata->rx1tx1_mode_use_rx_num == 1) ? + ENABLE_TRACKING_MODE_CH1 : ENABLE_TRACKING_MODE_CH2; + } + + ad9361_spi_write(spi, REG_CALIBRATION_CONFIG_1, + ENABLE_PHASE_CORR | ENABLE_GAIN_CORR | + FREE_RUN_MODE | ENABLE_CORR_WORD_DECIMATION | + qtrack); + + return 0; +} + +/** + * Enable/disable the VCO cal. + * @param phy The AD9361 state structure. + * @param rx Set true for rx. + * @param enable Set true to enable. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_trx_vco_cal_control(struct ad9361_rf_phy *phy, + bool tx, bool enable) +{ + dev_dbg(&phy->spi->dev, "%s : state %d", + __func__, enable); + + return ad9361_spi_writef(phy->spi, + tx ? REG_TX_PFD_CONFIG : REG_RX_PFD_CONFIG, + BYPASS_LD_SYNTH, !enable); +} + +/** + * Enable/disable the ext. LO. + * @param phy The AD9361 state structure. + * @param rx Set true for rx. + * @param enable Set true to enable. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_trx_ext_lo_control(struct ad9361_rf_phy *phy, + bool tx, bool enable) +{ + uint32_t val = enable ? ~0 : 0; + int32_t ret; + + /* REVIST: + * POWER_DOWN_TRX_SYNTH and MCS_RF_ENABLE somehow conflict + */ + + bool mcs_rf_enable = ad9361_spi_readf(phy->spi, + REG_MULTICHIP_SYNC_AND_TX_MON_CTRL, + MCS_RF_ENABLE); + + dev_dbg(&phy->spi->dev, "%s : %s state %d", __func__, + tx ? "TX" : "RX", enable); + + if (tx) { + ret = ad9361_spi_writef(phy->spi, REG_ENSM_CONFIG_2, + POWER_DOWN_TX_SYNTH, mcs_rf_enable ? 0 : enable); + + ret = ad9361_spi_writef(phy->spi, REG_ENSM_CONFIG_2, + TX_SYNTH_READY_MASK, enable); + + ret |= ad9361_spi_writef(phy->spi, REG_RFPLL_DIVIDERS, + TX_VCO_DIVIDER(~0), enable ? 7 : + phy->cached_tx_rfpll_div); + + if (enable) + phy->cached_synth_pd[0] |= TX_SYNTH_VCO_ALC_POWER_DOWN | + TX_SYNTH_PTAT_POWER_DOWN | + TX_SYNTH_VCO_POWER_DOWN; + else + phy->cached_synth_pd[0] &= ~(TX_SYNTH_VCO_ALC_POWER_DOWN | + TX_SYNTH_PTAT_POWER_DOWN | + TX_SYNTH_VCO_POWER_DOWN); + + + ret |= ad9361_spi_write(phy->spi, REG_TX_SYNTH_POWER_DOWN_OVERRIDE, + phy->cached_synth_pd[0]); + + ret |= ad9361_spi_writef(phy->spi, REG_ANALOG_POWER_DOWN_OVERRIDE, + TX_EXT_VCO_BUFFER_POWER_DOWN, !enable); + + ret |= ad9361_spi_write(phy->spi, REG_TX_LO_GEN_POWER_MODE, + TX_LO_GEN_POWER_MODE(val)); + } else { + ret = ad9361_spi_writef(phy->spi, REG_ENSM_CONFIG_2, + POWER_DOWN_RX_SYNTH, mcs_rf_enable ? 0 : enable); + + ret = ad9361_spi_writef(phy->spi, REG_ENSM_CONFIG_2, + RX_SYNTH_READY_MASK, enable); + + ret |= ad9361_spi_writef(phy->spi, REG_RFPLL_DIVIDERS, + RX_VCO_DIVIDER(~0), enable ? 7 : + phy->cached_rx_rfpll_div); + + if (enable) + phy->cached_synth_pd[1] |= RX_SYNTH_VCO_ALC_POWER_DOWN | + RX_SYNTH_PTAT_POWER_DOWN | + RX_SYNTH_VCO_POWER_DOWN; + else + phy->cached_synth_pd[1] &= ~(TX_SYNTH_VCO_ALC_POWER_DOWN | + RX_SYNTH_PTAT_POWER_DOWN | + RX_SYNTH_VCO_POWER_DOWN); + + ret |= ad9361_spi_write(phy->spi, REG_RX_SYNTH_POWER_DOWN_OVERRIDE, + phy->cached_synth_pd[1]); + + ret |= ad9361_spi_writef(phy->spi, REG_ANALOG_POWER_DOWN_OVERRIDE, + RX_EXT_VCO_BUFFER_POWER_DOWN, !enable); + + ret |= ad9361_spi_write(phy->spi, REG_RX_LO_GEN_POWER_MODE, + RX_LO_GEN_POWER_MODE(val)); + } + + return ret; +} + +/** + * Power down the TX and/or RX Local Oscillators. + * @param phy The AD9361 state structure. + * @param rx The RX LO setting. + * @param tx The TX LO setting. + * @return 0 in case of success, negative error code otherwise. + */ +int ad9361_synth_lo_powerdown(struct ad9361_rf_phy *phy, + enum synth_pd_ctrl rx, + enum synth_pd_ctrl tx) +{ + dev_dbg(&phy->spi->dev, "%s : RX(%d) TX(%d)", __func__, rx, tx); + + switch (rx) { + case LO_OFF: + phy->cached_synth_pd[1] |= RX_LO_POWER_DOWN; + break; + case LO_ON: + phy->cached_synth_pd[1] &= ~RX_LO_POWER_DOWN; + break; + case LO_DONTCARE: + break; + } + + switch (tx) { + case LO_OFF: + phy->cached_synth_pd[0] |= TX_LO_POWER_DOWN; + break; + case LO_ON: + phy->cached_synth_pd[0] &= ~TX_LO_POWER_DOWN; + break; + case LO_DONTCARE: + break; + } + + return ad9361_spi_writem(phy->spi, REG_TX_SYNTH_POWER_DOWN_OVERRIDE, + phy->cached_synth_pd, 2); +} + +/** + * Setup the reference clock delay unit counter register. + * @param phy The AD9361 state structure. + * @param ref_clk_hz The reference clock frequency [Hz]. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_set_ref_clk_cycles(struct ad9361_rf_phy *phy, + uint32_t ref_clk_hz) +{ + dev_dbg(&phy->spi->dev, "%s : ref_clk_hz %"PRIu32, + __func__, ref_clk_hz); + + return ad9361_spi_write(phy->spi, REG_REFERENCE_CLOCK_CYCLES, + REFERENCE_CLOCK_CYCLES_PER_US((ref_clk_hz / 1000000UL) - 1)); +} + +/** + * Setup the DCXO tune. + * @param phy The AD9361 state structure. + * @param coarse The DCXO tune coarse. + * @param fine The DCXO tune fine. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_set_dcxo_tune(struct ad9361_rf_phy *phy, + uint32_t coarse, uint32_t fine) +{ + dev_dbg(&phy->spi->dev, "%s : coarse %"PRIu32" fine %"PRIu32, + __func__, coarse, fine); + + if (phy->pdata->use_extclk) + return -ENODEV; + + ad9361_spi_write(phy->spi, REG_DCXO_COARSE_TUNE, + DCXO_TUNE_COARSE(coarse)); + ad9361_spi_write(phy->spi, REG_DCXO_FINE_TUNE_LOW, + DCXO_TUNE_FINE_LOW(fine)); + return ad9361_spi_write(phy->spi, REG_DCXO_FINE_TUNE_HIGH, + DCXO_TUNE_FINE_HIGH(fine)); +} + +/** + * Setup TXMON. + * @param phy The AD9361 state structure. + * @param ctrl The TXMON settings. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_txmon_setup(struct ad9361_rf_phy *phy, + struct tx_monitor_control *ctrl) +{ + struct spi_desc *spi = phy->spi; + + dev_dbg(&phy->spi->dev, "%s", __func__); + + ad9361_spi_write(spi, REG_TPM_MODE_ENABLE, + (ctrl->one_shot_mode_en ? ONE_SHOT_MODE : 0) | + TX_MON_DURATION(ilog2(ctrl->tx_mon_duration / 16))); + + ad9361_spi_write(spi, REG_TX_MON_DELAY, ctrl->tx_mon_delay & 0xFF); + ad9361_spi_writef(spi, REG_TX_LEVEL_THRESH, + TX_MON_DELAY_COUNTER(~0), ctrl->tx_mon_delay >> 8); + + ad9361_spi_write(spi, REG_TX_MON_1_CONFIG, + TX_MON_1_LO_CM(ctrl->tx1_mon_lo_cm) | + TX_MON_1_GAIN(ctrl->tx1_mon_front_end_gain)); + ad9361_spi_write(spi, REG_TX_MON_2_CONFIG, + TX_MON_2_LO_CM(ctrl->tx2_mon_lo_cm) | + TX_MON_2_GAIN(ctrl->tx2_mon_front_end_gain)); + + ad9361_spi_write(spi, REG_TX_ATTEN_THRESH, + ctrl->low_high_gain_threshold_mdB / 250); + + ad9361_spi_write(spi, REG_TX_MON_HIGH_GAIN, + TX_MON_HIGH_GAIN(ctrl->high_gain_dB)); + + ad9361_spi_write(spi, REG_TX_MON_LOW_GAIN, + (ctrl->tx_mon_track_en ? TX_MON_TRACK : 0) | + TX_MON_LOW_GAIN(ctrl->low_gain_dB)); + + return 0; +} + +/** + * Enable TXMON. + * @param phy The AD9361 state structure. + * @param en_mask The enable mask. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_txmon_control(struct ad9361_rf_phy *phy, + int32_t en_mask) +{ + dev_dbg(&phy->spi->dev, "%s: mask 0x%"PRIx32, __func__, en_mask); + +#if 0 + if (!phy->pdata->fdd && en_mask) { + ad9361_spi_writef(phy->spi, REG_ENSM_CONFIG_1, + ENABLE_RX_DATA_PORT_FOR_CAL, 1); + phy->txmon_tdd_en = true; + } else { + ad9361_spi_writef(phy->spi, REG_ENSM_CONFIG_1, + ENABLE_RX_DATA_PORT_FOR_CAL, 0); + phy->txmon_tdd_en = false; + } +#endif + + ad9361_spi_writef(phy->spi, REG_ANALOG_POWER_DOWN_OVERRIDE, + TX_MONITOR_POWER_DOWN(~0), ~en_mask); + + ad9361_spi_writef(phy->spi, REG_TPM_MODE_ENABLE, + TX1_MON_ENABLE, !!(en_mask & TX_1)); + + return ad9361_spi_writef(phy->spi, REG_TPM_MODE_ENABLE, + TX2_MON_ENABLE, !!(en_mask & TX_2)); +} + +/** +* Setup the RF port. +* Note: +* val +* 0 (RX1A_N & RX1A_P) and (RX2A_N & RX2A_P) enabled; balanced +* 1 (RX1B_N & RX1B_P) and (RX2B_N & RX2B_P) enabled; balanced +* 2 (RX1C_N & RX1C_P) and (RX2C_N & RX2C_P) enabled; balanced +* +* 3 RX1A_N and RX2A_N enabled; unbalanced +* 4 RX1A_P and RX2A_P enabled; unbalanced +* 5 RX1B_N and RX2B_N enabled; unbalanced +* 6 RX1B_P and RX2B_P enabled; unbalanced +* 7 RX1C_N and RX2C_N enabled; unbalanced +* 8 RX1C_P and RX2C_P enabled; unbalanced +* 9 TX_MON1 +* 10 TX_MON2 +* 11 TX_MON1 & TX_MON2 +* @param phy The AD9361 state structure. +* @param is_out TX RF output port enabled. +* @param rx_inputs RX input option identifier +* @param txb TX output option identifier +* @return 0 in case of success, negative error code otherwise. +*/ +int32_t ad9361_rf_port_setup(struct ad9361_rf_phy *phy, bool is_out, + uint32_t rx_inputs, uint32_t txb) +{ + uint32_t val; + + if (rx_inputs > 11) + return -EINVAL; + + if (!is_out) { + if (rx_inputs > 8) + return ad9361_txmon_control(phy, rx_inputs & (TX_1 | TX_2)); + else + ad9361_txmon_control(phy, 0); + } + + if (rx_inputs < 3) + val = 3 << (rx_inputs * 2); + else + val = 1 << (rx_inputs - 3); + + if (txb) + val |= TX_OUTPUT; /* Select TX1B, TX2B */ + + dev_dbg(&phy->spi->dev, "%s : INPUT_SELECT 0x%"PRIx32, + __func__, val); + + return ad9361_spi_write(phy->spi, REG_INPUT_SELECT, val); +} + +/** + * Setup the Parallel Port (Digital Data Interface). + * @param phy The AD9361 state structure. + * @param restore_c3 Set true, will restore the Parallel Port Configuration 3 + * register. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_pp_port_setup(struct ad9361_rf_phy *phy, bool restore_c3) +{ + struct spi_desc *spi = phy->spi; + struct ad9361_phy_platform_data *pd = phy->pdata; + + dev_dbg(&phy->spi->dev, "%s", __func__); + + if (restore_c3) { + return ad9361_spi_write(spi, REG_PARALLEL_PORT_CONF_3, + pd->port_ctrl.pp_conf[2]); + } + + /* Sanity check */ + if (pd->port_ctrl.pp_conf[2] & LVDS_MODE) + pd->port_ctrl.pp_conf[2] &= + ~(HALF_DUPLEX_MODE | SINGLE_DATA_RATE | SINGLE_PORT_MODE); + + if (pd->port_ctrl.pp_conf[2] & FULL_PORT) + pd->port_ctrl.pp_conf[2] &= ~(HALF_DUPLEX_MODE | SINGLE_PORT_MODE); + + ad9361_spi_write(spi, REG_PARALLEL_PORT_CONF_1, pd->port_ctrl.pp_conf[0]); + ad9361_spi_write(spi, REG_PARALLEL_PORT_CONF_2, pd->port_ctrl.pp_conf[1]); + ad9361_spi_write(spi, REG_PARALLEL_PORT_CONF_3, pd->port_ctrl.pp_conf[2]); + ad9361_spi_write(spi, REG_RX_CLOCK_DATA_DELAY, pd->port_ctrl.rx_clk_data_delay); + ad9361_spi_write(spi, REG_TX_CLOCK_DATA_DELAY, pd->port_ctrl.tx_clk_data_delay); + + ad9361_spi_write(spi, REG_LVDS_BIAS_CTRL, pd->port_ctrl.lvds_bias_ctrl); + // ad9361_spi_write(spi, REG_DIGITAL_IO_CTRL, pd->port_ctrl.digital_io_ctrl); + ad9361_spi_write(spi, REG_LVDS_INVERT_CTRL1, pd->port_ctrl.lvds_invert[0]); + ad9361_spi_write(spi, REG_LVDS_INVERT_CTRL2, pd->port_ctrl.lvds_invert[1]); + + if (pd->rx1rx2_phase_inversion_en || + (pd->port_ctrl.pp_conf[1] & INVERT_RX2)) { + + ad9361_spi_writef(spi, REG_PARALLEL_PORT_CONF_2, INVERT_RX2, 1); + ad9361_spi_writef(spi, REG_INVERT_BITS, + INVERT_RX2_RF_DC_CGOUT_WORD, 0); + } + + return 0; +} + +/** + * Setup the Gain Control Blocks (common function for MGC, AGC modes) + * @param phy The AD9361 state structure. + * @param ctrl The gain control settings. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_gc_setup(struct ad9361_rf_phy *phy, + struct gain_control *ctrl) +{ + struct spi_desc *spi = phy->spi; + uint32_t reg, tmp1, tmp2; + + dev_dbg(&phy->spi->dev, "%s", __func__); + + reg = DEC_PWR_FOR_GAIN_LOCK_EXIT | DEC_PWR_FOR_LOCK_LEVEL | + DEC_PWR_FOR_LOW_PWR; + + if (ctrl->rx1_mode == RF_GAIN_HYBRID_AGC || + ctrl->rx2_mode == RF_GAIN_HYBRID_AGC) + reg |= SLOW_ATTACK_HYBRID_MODE; + + reg |= RX1_GAIN_CTRL_SETUP(ctrl->rx1_mode) | + RX2_GAIN_CTRL_SETUP(ctrl->rx2_mode); + + phy->agc_mode[0] = ctrl->rx1_mode; + phy->agc_mode[1] = ctrl->rx2_mode; + + ad9361_spi_write(spi, REG_AGC_CONFIG_1, reg); // Gain Control Mode Select + + /* AGC_USE_FULL_GAIN_TABLE handled in ad9361_load_gt() */ + ad9361_spi_writef(spi, REG_AGC_CONFIG_2, MAN_GAIN_CTRL_RX1, + ctrl->mgc_rx1_ctrl_inp_en); + ad9361_spi_writef(spi, REG_AGC_CONFIG_2, MAN_GAIN_CTRL_RX2, + ctrl->mgc_rx2_ctrl_inp_en); + ad9361_spi_writef(spi, REG_AGC_CONFIG_2, DIG_GAIN_EN, + ctrl->dig_gain_en); + + ctrl->adc_ovr_sample_size = clamp_t(uint8_t, ctrl->adc_ovr_sample_size, 1U, 8U); + reg = ADC_OVERRANGE_SAMPLE_SIZE(ctrl->adc_ovr_sample_size - 1); + + if (has_split_gt && phy->pdata->split_gt && + (ctrl->mgc_rx1_ctrl_inp_en || ctrl->mgc_rx2_ctrl_inp_en)) { + switch (ctrl->mgc_split_table_ctrl_inp_gain_mode) { + case 1: + reg &= ~INCDEC_LMT_GAIN; + break; + case 2: + reg |= INCDEC_LMT_GAIN; + break; + default: + case 0: + reg |= USE_AGC_FOR_LMTLPF_GAIN; + break; + } + } + + ctrl->mgc_inc_gain_step = clamp_t(uint8_t, ctrl->mgc_inc_gain_step, 1U, 8U); + reg |= MANUAL_INCR_STEP_SIZE(ctrl->mgc_inc_gain_step - 1); + ad9361_spi_write(spi, REG_AGC_CONFIG_3, + reg); // Incr Step Size, ADC Overrange Size + + ctrl->mgc_dec_gain_step = clamp_t(uint8_t, ctrl->mgc_dec_gain_step, 1U, 8U); + reg = MANUAL_CTRL_IN_DECR_GAIN_STP_SIZE(ctrl->mgc_dec_gain_step - 1); + ad9361_spi_write(spi, REG_PEAK_WAIT_TIME, + reg); // Decr Step Size, Peak Overload Time + + if (ctrl->dig_gain_en) + ad9361_spi_write(spi, REG_DIGITAL_GAIN, + MAXIMUM_DIGITAL_GAIN(ctrl->max_dig_gain) | + DIG_GAIN_STP_SIZE(ctrl->dig_gain_step_size)); + + if (ctrl->adc_large_overload_thresh >= ctrl->adc_small_overload_thresh) { + ad9361_spi_write(spi, REG_ADC_SMALL_OVERLOAD_THRESH, + ctrl->adc_small_overload_thresh); // ADC Small Overload Threshold + ad9361_spi_write(spi, REG_ADC_LARGE_OVERLOAD_THRESH, + ctrl->adc_large_overload_thresh); // ADC Large Overload Threshold + } else { + ad9361_spi_write(spi, REG_ADC_SMALL_OVERLOAD_THRESH, + ctrl->adc_large_overload_thresh); // ADC Small Overload Threshold + ad9361_spi_write(spi, REG_ADC_LARGE_OVERLOAD_THRESH, + ctrl->adc_small_overload_thresh); // ADC Large Overload Threshold + } + + reg = (ctrl->lmt_overload_high_thresh / 16) - 1; + reg = clamp(reg, 0U, 63U); + ad9361_spi_write(spi, REG_LARGE_LMT_OVERLOAD_THRESH, reg); + reg = (ctrl->lmt_overload_low_thresh / 16) - 1; + reg = clamp(reg, 0U, 63U); + ad9361_spi_writef(spi, REG_SMALL_LMT_OVERLOAD_THRESH, + SMALL_LMT_OVERLOAD_THRESH(~0), reg); + + if (has_split_gt && phy->pdata->split_gt) { + /* REVIST */ + ad9361_spi_write(spi, REG_RX1_MANUAL_LPF_GAIN, 0x58); // Rx1 LPF Gain Index + ad9361_spi_write(spi, REG_RX2_MANUAL_LPF_GAIN, 0x18); // Rx2 LPF Gain Index + ad9361_spi_write(spi, REG_FAST_INITIAL_LMT_GAIN_LIMIT, + 0x27); // Initial LMT Gain Limit + } + + ad9361_spi_write(spi, REG_RX1_MANUAL_DIGITALFORCED_GAIN, + 0x00); // Rx1 Digital Gain Index + ad9361_spi_write(spi, REG_RX2_MANUAL_DIGITALFORCED_GAIN, + 0x00); // Rx2 Digital Gain Index + + reg = clamp_t(uint8_t, ctrl->low_power_thresh, 0U, 64U) * 2; + ad9361_spi_write(spi, REG_FAST_LOW_POWER_THRESH, reg); // Low Power Threshold + ad9361_spi_write(spi, REG_TX_SYMBOL_ATTEN_CONFIG, + 0x00); // Tx Symbol Gain Control + + ad9361_spi_writef(spi, REG_DEC_POWER_MEASURE_DURATION_0, + USE_HB1_OUT_FOR_DEC_PWR_MEAS, + !ctrl->use_rx_fir_out_for_dec_pwr_meas); // USE HB1 or FIR output for power measurements + + ad9361_spi_writef(spi, REG_DEC_POWER_MEASURE_DURATION_0, + ENABLE_DEC_PWR_MEAS, 1); // Power Measurement Duration + + if (ctrl->rx1_mode == RF_GAIN_FASTATTACK_AGC || + ctrl->rx2_mode == RF_GAIN_FASTATTACK_AGC) + reg = ilog2(ctrl->f_agc_dec_pow_measuremnt_duration / 16); + else + reg = ilog2(ctrl->dec_pow_measuremnt_duration / 16); + + ad9361_spi_writef(spi, REG_DEC_POWER_MEASURE_DURATION_0, + DEC_POWER_MEASUREMENT_DURATION(~0), reg); // Power Measurement Duration + + /* AGC */ + + tmp1 = reg = clamp_t(uint8_t, ctrl->agc_inner_thresh_high, 0U, 127U); + ad9361_spi_writef(spi, REG_AGC_LOCK_LEVEL, + AGC_LOCK_LEVEL_FAST_AGC_INNER_HIGH_THRESH_SLOW(~0), + reg); + + tmp2 = reg = clamp_t(uint8_t, ctrl->agc_inner_thresh_low, 0U, 127U); + reg |= (ctrl->adc_lmt_small_overload_prevent_gain_inc ? + PREVENT_GAIN_INC : 0); + ad9361_spi_write(spi, REG_AGC_INNER_LOW_THRESH, reg); + + reg = AGC_OUTER_HIGH_THRESH(tmp1 - ctrl->agc_outer_thresh_high) | + AGC_OUTER_LOW_THRESH(ctrl->agc_outer_thresh_low - tmp2); + ad9361_spi_write(spi, REG_OUTER_POWER_THRESHS, reg); + + reg = AGC_OUTER_HIGH_THRESH_EXED_STP_SIZE(ctrl->agc_outer_thresh_high_dec_steps) + | + AGC_OUTER_LOW_THRESH_EXED_STP_SIZE(ctrl->agc_outer_thresh_low_inc_steps); + ad9361_spi_write(spi, REG_GAIN_STP_2, reg); + + reg = ((ctrl->immed_gain_change_if_large_adc_overload) ? + IMMED_GAIN_CHANGE_IF_LG_ADC_OVERLOAD : 0) | + ((ctrl->immed_gain_change_if_large_lmt_overload) ? + IMMED_GAIN_CHANGE_IF_LG_LMT_OVERLOAD : 0) | + AGC_INNER_HIGH_THRESH_EXED_STP_SIZE(ctrl->agc_inner_thresh_high_dec_steps) | + AGC_INNER_LOW_THRESH_EXED_STP_SIZE(ctrl->agc_inner_thresh_low_inc_steps); + ad9361_spi_write(spi, REG_GAIN_STP1, reg); + + reg = LARGE_ADC_OVERLOAD_EXED_COUNTER(ctrl->adc_large_overload_exceed_counter) | + SMALL_ADC_OVERLOAD_EXED_COUNTER(ctrl->adc_small_overload_exceed_counter); + ad9361_spi_write(spi, REG_ADC_OVERLOAD_COUNTERS, reg); + + reg = DECREMENT_STP_SIZE_FOR_SMALL_LPF_GAIN_CHANGE( + ctrl->f_agc_large_overload_inc_steps) | + LARGE_LPF_GAIN_STEP(ctrl->adc_large_overload_inc_steps); + ad9361_spi_write(spi, REG_GAIN_STP_CONFIG_2, reg); + + reg = LARGE_LMT_OVERLOAD_EXED_COUNTER(ctrl->lmt_overload_large_exceed_counter) | + SMALL_LMT_OVERLOAD_EXED_COUNTER(ctrl->lmt_overload_small_exceed_counter); + ad9361_spi_write(spi, REG_LMT_OVERLOAD_COUNTERS, reg); + + ad9361_spi_writef(spi, REG_GAIN_STP_CONFIG1, + DEC_STP_SIZE_FOR_LARGE_LMT_OVERLOAD(~0), + ctrl->lmt_overload_large_inc_steps); + + reg = DIG_SATURATION_EXED_COUNTER(ctrl->dig_saturation_exceed_counter) | + (ctrl->sync_for_gain_counter_en ? + ENABLE_SYNC_FOR_GAIN_COUNTER : 0); + ad9361_spi_write(spi, REG_DIGITAL_SAT_COUNTER, reg); + + /* + * Fast AGC + */ + + /* Fast AGC - Low Power */ + ad9361_spi_writef(spi, REG_FAST_CONFIG_1, + ENABLE_INCR_GAIN, + ctrl->f_agc_allow_agc_gain_increase); + + ad9361_spi_write(spi, REG_FAST_INCREMENT_TIME, + ctrl->f_agc_lp_thresh_increment_time); + + reg = ctrl->f_agc_lp_thresh_increment_steps - 1; + reg = clamp_t(uint32_t, reg, 0U, 7U); + ad9361_spi_writef(spi, REG_FAST_ENERGY_DETECT_COUNT, + INCREMENT_GAIN_STP_LPFLMT(~0), reg); + + /* Fast AGC - Lock Level */ + /* Dual use see also agc_inner_thresh_high */ + ad9361_spi_writef(spi, REG_FAST_CONFIG_2_SETTLING_DELAY, + ENABLE_LMT_GAIN_INC_FOR_LOCK_LEVEL, + ctrl->f_agc_lock_level_lmt_gain_increase_en); + + reg = ctrl->f_agc_lock_level_gain_increase_upper_limit; + reg = clamp_t(uint32_t, reg, 0U, 63U); + ad9361_spi_writef(spi, REG_FAST_AGCLL_UPPER_LIMIT, + AGCLL_MAX_INCREASE(~0), reg); + + /* Fast AGC - Peak Detectors and Final Settling */ + reg = ctrl->f_agc_lpf_final_settling_steps; + reg = clamp_t(uint32_t, reg, 0U, 3U); + ad9361_spi_writef(spi, REG_FAST_ENERGY_LOST_THRESH, + POST_LOCK_LEVEL_STP_SIZE_FOR_LPF_TABLE_FULL_TABLE(~0), + reg); + + reg = ctrl->f_agc_lmt_final_settling_steps; + reg = clamp_t(uint32_t, reg, 0U, 3U); + ad9361_spi_writef(spi, REG_FAST_STRONGER_SIGNAL_THRESH, + POST_LOCK_LEVEL_STP_FOR_LMT_TABLE(~0), reg); + + reg = ctrl->f_agc_final_overrange_count; + reg = clamp_t(uint32_t, reg, 0U, 7U); + ad9361_spi_writef(spi, REG_FAST_FINAL_OVER_RANGE_AND_OPT_GAIN, + FINAL_OVER_RANGE_COUNT(~0), reg); + + /* Fast AGC - Final Power Test */ + ad9361_spi_writef(spi, REG_FAST_CONFIG_1, + ENABLE_GAIN_INC_AFTER_GAIN_LOCK, + ctrl->f_agc_gain_increase_after_gain_lock_en); + + /* Fast AGC - Unlocking the Gain */ + /* 0 = MAX Gain, 1 = Optimized Gain, 2 = Set Gain */ + + reg = ctrl->f_agc_gain_index_type_after_exit_rx_mode; + ad9361_spi_writef(spi, REG_FAST_CONFIG_1, + GOTO_SET_GAIN_IF_EXIT_RX_STATE, reg == SET_GAIN); + ad9361_spi_writef(spi, REG_FAST_CONFIG_1, + GOTO_OPTIMIZED_GAIN_IF_EXIT_RX_STATE, + reg == OPTIMIZED_GAIN); + + ad9361_spi_writef(spi, REG_FAST_CONFIG_2_SETTLING_DELAY, + USE_LAST_LOCK_LEVEL_FOR_SET_GAIN, + ctrl->f_agc_use_last_lock_level_for_set_gain_en); + + reg = ctrl->f_agc_optimized_gain_offset; + reg = clamp_t(uint32_t, reg, 0U, 15U); + ad9361_spi_writef(spi, REG_FAST_FINAL_OVER_RANGE_AND_OPT_GAIN, + OPTIMIZE_GAIN_OFFSET(~0), reg); + + tmp1 = !ctrl->f_agc_rst_gla_stronger_sig_thresh_exceeded_en || + !ctrl->f_agc_rst_gla_engergy_lost_sig_thresh_exceeded_en || + !ctrl->f_agc_rst_gla_large_adc_overload_en || + !ctrl->f_agc_rst_gla_large_lmt_overload_en || + ctrl->f_agc_rst_gla_en_agc_pulled_high_en; + + ad9361_spi_writef(spi, REG_AGC_CONFIG_2, + AGC_GAIN_UNLOCK_CTRL, tmp1); + + reg = !ctrl->f_agc_rst_gla_stronger_sig_thresh_exceeded_en; + ad9361_spi_writef(spi, REG_FAST_STRONG_SIGNAL_FREEZE, + DONT_UNLOCK_GAIN_IF_STRONGER_SIGNAL, reg); + + reg = ctrl->f_agc_rst_gla_stronger_sig_thresh_above_ll; + reg = clamp_t(uint32_t, reg, 0U, 63U); + ad9361_spi_writef(spi, REG_FAST_STRONGER_SIGNAL_THRESH, + STRONGER_SIGNAL_THRESH(~0), reg); + + reg = ctrl->f_agc_rst_gla_engergy_lost_sig_thresh_below_ll; + reg = clamp_t(uint32_t, reg, 0U, 63U); + ad9361_spi_writef(spi, REG_FAST_ENERGY_LOST_THRESH, + ENERGY_LOST_THRESH(~0), reg); + + reg = ctrl->f_agc_rst_gla_engergy_lost_goto_optim_gain_en; + ad9361_spi_writef(spi, REG_FAST_CONFIG_1, + GOTO_OPT_GAIN_IF_ENERGY_LOST_OR_EN_AGC_HIGH, reg); + + reg = !ctrl->f_agc_rst_gla_engergy_lost_sig_thresh_exceeded_en; + ad9361_spi_writef(spi, REG_FAST_CONFIG_1, + DONT_UNLOCK_GAIN_IF_ENERGY_LOST, reg); + + reg = ctrl->f_agc_energy_lost_stronger_sig_gain_lock_exit_cnt; + reg = clamp_t(uint32_t, reg, 0U, 63U); + ad9361_spi_writef(spi, REG_FAST_GAIN_LOCK_EXIT_COUNT, + GAIN_LOCK_EXIT_COUNT(~0), reg); + + reg = !ctrl->f_agc_rst_gla_large_adc_overload_en || + !ctrl->f_agc_rst_gla_large_lmt_overload_en; + ad9361_spi_writef(spi, REG_FAST_CONFIG_1, + DONT_UNLOCK_GAIN_IF_LG_ADC_OR_LMT_OVRG, reg); + + reg = !ctrl->f_agc_rst_gla_large_adc_overload_en; + ad9361_spi_writef(spi, REG_FAST_LOW_POWER_THRESH, + DONT_UNLOCK_GAIN_IF_ADC_OVRG, reg); + + /* 0 = Max Gain, 1 = Set Gain, 2 = Optimized Gain, 3 = No Gain Change */ + + if (ctrl->f_agc_rst_gla_en_agc_pulled_high_en) { + switch (ctrl->f_agc_rst_gla_if_en_agc_pulled_high_mode) { + case MAX_GAIN: + ad9361_spi_writef(spi, REG_FAST_CONFIG_2_SETTLING_DELAY, + GOTO_MAX_GAIN_OR_OPT_GAIN_IF_EN_AGC_HIGH, 1); + + ad9361_spi_writef(spi, REG_FAST_CONFIG_1, + GOTO_SET_GAIN_IF_EN_AGC_HIGH, 0); + + ad9361_spi_writef(spi, REG_FAST_CONFIG_1, + GOTO_OPT_GAIN_IF_ENERGY_LOST_OR_EN_AGC_HIGH, 0); + break; + case SET_GAIN: + ad9361_spi_writef(spi, REG_FAST_CONFIG_2_SETTLING_DELAY, + GOTO_MAX_GAIN_OR_OPT_GAIN_IF_EN_AGC_HIGH, 0); + + ad9361_spi_writef(spi, REG_FAST_CONFIG_1, + GOTO_SET_GAIN_IF_EN_AGC_HIGH, 1); + break; + case OPTIMIZED_GAIN: + ad9361_spi_writef(spi, REG_FAST_CONFIG_2_SETTLING_DELAY, + GOTO_MAX_GAIN_OR_OPT_GAIN_IF_EN_AGC_HIGH, 1); + + ad9361_spi_writef(spi, REG_FAST_CONFIG_1, + GOTO_SET_GAIN_IF_EN_AGC_HIGH, 0); + + ad9361_spi_writef(spi, REG_FAST_CONFIG_1, + GOTO_OPT_GAIN_IF_ENERGY_LOST_OR_EN_AGC_HIGH, 1); + break; + case NO_GAIN_CHANGE: + ad9361_spi_writef(spi, REG_FAST_CONFIG_1, + GOTO_SET_GAIN_IF_EN_AGC_HIGH, 0); + ad9361_spi_writef(spi, REG_FAST_CONFIG_2_SETTLING_DELAY, + GOTO_MAX_GAIN_OR_OPT_GAIN_IF_EN_AGC_HIGH, 0); + break; + } + } else { + ad9361_spi_writef(spi, REG_FAST_CONFIG_1, + GOTO_SET_GAIN_IF_EN_AGC_HIGH, 0); + ad9361_spi_writef(spi, REG_FAST_CONFIG_2_SETTLING_DELAY, + GOTO_MAX_GAIN_OR_OPT_GAIN_IF_EN_AGC_HIGH, 0); + } + + reg = ilog2(ctrl->f_agc_power_measurement_duration_in_state5 / 16); + reg = clamp_t(uint32_t, reg, 0U, 15U); + ad9361_spi_writef(spi, REG_RX1_MANUAL_LPF_GAIN, + POWER_MEAS_IN_STATE_5(~0), reg); + ad9361_spi_writef(spi, REG_RX1_MANUAL_LMT_FULL_GAIN, + POWER_MEAS_IN_STATE_5_MSB, reg >> 3); + + return ad9361_gc_update(phy); +} + +/** + * Set the Aux DAC. + * @param phy The AD9361 state structure. + * @param dac The DAC. + * @param val_mV The value. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_auxdac_set(struct ad9361_rf_phy *phy, int32_t dac, + int32_t val_mV) +{ + struct spi_desc *spi = phy->spi; + uint32_t val, tmp; + + dev_dbg(&phy->spi->dev, "%s DAC%"PRId32" = %"PRId32" mV", __func__, dac, + val_mV); + + /* Disable DAC if val == 0, Ignored in ENSM Auto Mode */ + ad9361_spi_writef(spi, REG_AUXDAC_ENABLE_CTRL, + AUXDAC_MANUAL_BAR(dac), val_mV ? 0 : 1); + + if (val_mV < 306) + val_mV = 306; + + if (val_mV < 1888) { + val = ((val_mV - 306) * 1000) / 1469; /* Vref = 1V, Step = 2 */ + tmp = AUXDAC_1_VREF(0); + } else { + val = ((val_mV - 1761) * 1000) / 1512; /* Vref = 2.5V, Step = 2 */ + tmp = AUXDAC_1_VREF(3); + } + + val = clamp_t(uint32_t, val, 0, 1023); + + switch (dac) { + case 1: + ad9361_spi_write(spi, REG_AUXDAC_1_WORD, val >> 2); + ad9361_spi_write(spi, REG_AUXDAC_1_CONFIG, AUXDAC_1_WORD_LSB(val) | tmp); + phy->auxdac1_value = val_mV; + break; + case 2: + ad9361_spi_write(spi, REG_AUXDAC_2_WORD, val >> 2); + ad9361_spi_write(spi, REG_AUXDAC_2_CONFIG, AUXDAC_2_WORD_LSB(val) | tmp); + phy->auxdac2_value = val_mV; + break; + default: + return -EINVAL; + } + + return 0; +} + +/** + * Get the Aux DAC value. + * @param phy The AD9361 state structure. + * @param dac The DAC. + * @return The value in case of success, negative error code otherwise. + */ +int32_t ad9361_auxdac_get(struct ad9361_rf_phy *phy, int32_t dac) +{ + + switch (dac) { + case 1: + return phy->auxdac1_value; + case 2: + return phy->auxdac2_value; + default: + return -EINVAL; + } + + return 0; +} + +/** + * Setup the AuxDAC. + * @param phy The AD9361 state structure. + * @param ctrl Pointer to auxdac_control structure. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_auxdac_setup(struct ad9361_rf_phy *phy, + struct auxdac_control *ctrl) +{ + struct spi_desc *spi = phy->spi; + uint8_t tmp; + + dev_dbg(&phy->spi->dev, "%s", __func__); + + ad9361_auxdac_set(phy, 1, ctrl->dac1_default_value); + ad9361_auxdac_set(phy, 2, ctrl->dac2_default_value); + + tmp = ~(AUXDAC_AUTO_TX_BAR(ctrl->dac2_in_tx_en << 1 | ctrl->dac1_in_tx_en) | + AUXDAC_AUTO_RX_BAR(ctrl->dac2_in_rx_en << 1 | ctrl->dac1_in_rx_en) | + AUXDAC_INIT_BAR(ctrl->dac2_in_alert_en << 1 | ctrl->dac1_in_alert_en)); + + ad9361_spi_writef(spi, REG_AUXDAC_ENABLE_CTRL, + AUXDAC_AUTO_TX_BAR(~0) | + AUXDAC_AUTO_RX_BAR(~0) | + AUXDAC_INIT_BAR(~0), + tmp); /* Auto Control */ + + ad9361_spi_writef(spi, REG_EXTERNAL_LNA_CTRL, + AUXDAC_MANUAL_SELECT, ctrl->auxdac_manual_mode_en); + ad9361_spi_write(spi, REG_AUXDAC1_RX_DELAY, ctrl->dac1_rx_delay_us); + ad9361_spi_write(spi, REG_AUXDAC1_TX_DELAY, ctrl->dac1_tx_delay_us); + ad9361_spi_write(spi, REG_AUXDAC2_RX_DELAY, ctrl->dac2_rx_delay_us); + ad9361_spi_write(spi, REG_AUXDAC2_TX_DELAY, ctrl->dac2_tx_delay_us); + + return 0; +} + +/** + * Setup the AuxADC. + * @param phy The AD9361 state structure. + * @param ctrl The AuxADC settings. + * @param bbpll_freq The BBPLL frequency [Hz]. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_auxadc_setup(struct ad9361_rf_phy *phy, + struct auxadc_control *ctrl, + uint32_t bbpll_freq) +{ + struct spi_desc *spi = phy->spi; + uint32_t val; + + dev_dbg(&phy->spi->dev, "%s", __func__); + + val = DIV_ROUND_CLOSEST(ctrl->temp_time_inteval_ms * + (bbpll_freq / 1000UL), (1 << 29)); + + ad9361_spi_write(spi, REG_TEMP_OFFSET, ctrl->offset); + ad9361_spi_write(spi, REG_START_TEMP_READING, 0x00); + ad9361_spi_write(spi, REG_TEMP_SENSE2, + MEASUREMENT_TIME_INTERVAL(val) | + (ctrl->periodic_temp_measuremnt ? + TEMP_SENSE_PERIODIC_ENABLE : 0)); + ad9361_spi_write(spi, REG_TEMP_SENSOR_CONFIG, + TEMP_SENSOR_DECIMATION( + ilog2(ctrl->temp_sensor_decimation) - 8)); + ad9361_spi_write(spi, REG_AUXADC_CLOCK_DIVIDER, + bbpll_freq / ctrl->auxadc_clock_rate); + ad9361_spi_write(spi, REG_AUXADC_CONFIG, + AUX_ADC_DECIMATION( + ilog2(ctrl->auxadc_decimation) - 8)); + + return 0; +} + +/** + * Get the measured temperature of the device. + * @param phy The AD9361 state structure. + * @return The measured temperature of the device. + */ +int32_t ad9361_get_temp(struct ad9361_rf_phy *phy) +{ + uint32_t val; + + ad9361_spi_writef(phy->spi, REG_AUXADC_CONFIG, AUXADC_POWER_DOWN, 1); + val = ad9361_spi_read(phy->spi, REG_TEMPERATURE); + ad9361_spi_writef(phy->spi, REG_AUXADC_CONFIG, AUXADC_POWER_DOWN, 0); + + return DIV_ROUND_CLOSEST(val * 1000000, 1140); +} + +/** + * Get the Aux ADC value. + * @param phy The AD9361 state structure. + * @return The value in case of success, negative error code otherwise. + */ +int32_t ad9361_get_auxadc(struct ad9361_rf_phy *phy) +{ + uint8_t buf[2]; + + ad9361_spi_writef(phy->spi, REG_AUXADC_CONFIG, AUXADC_POWER_DOWN, 1); + ad9361_spi_readm(phy->spi, REG_AUXADC_LSB, buf, 2); + ad9361_spi_writef(phy->spi, REG_AUXADC_CONFIG, AUXADC_POWER_DOWN, 0); + + return (buf[1] << 4) | AUXADC_WORD_LSB(buf[0]); +} + +/** + * Setup the Control Output pins. + * @param phy The AD9361 state structure. + * @param ctrl The Control Output pins settings. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_ctrl_outs_setup(struct ad9361_rf_phy *phy, + struct ctrl_outs_control *ctrl) +{ + struct spi_desc *spi = phy->spi; + + dev_dbg(&phy->spi->dev, "%s", __func__); + + ad9361_spi_write(spi, REG_CTRL_OUTPUT_POINTER, ctrl->index); // Ctrl Out index + return ad9361_spi_write(spi, REG_CTRL_OUTPUT_ENABLE, + ctrl->en_mask); // Ctrl Out [7:0] output enable +} + +/** + * Setup the GPO pins. + * @param phy The AD9361 state structure. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_gpo_setup(struct ad9361_rf_phy *phy, + struct gpo_control *ctrl) +{ + struct spi_desc *spi = phy->spi; + + dev_dbg(&phy->spi->dev, "%s", __func__); + + ad9361_spi_write(spi, REG_AUTO_GPO, + GPO_ENABLE_AUTO_RX(ctrl->gpo0_slave_rx_en | + (ctrl->gpo1_slave_rx_en << 1) | + (ctrl->gpo2_slave_rx_en << 2) | + (ctrl->gpo3_slave_rx_en << 3)) | + GPO_ENABLE_AUTO_TX(ctrl->gpo0_slave_tx_en | + (ctrl->gpo1_slave_tx_en << 1) | + (ctrl->gpo2_slave_tx_en << 2) | + (ctrl->gpo3_slave_tx_en << 3))); + + ad9361_spi_write(spi, REG_GPO_FORCE_AND_INIT, + GPO_MANUAL_CTRL(ctrl->gpo_manual_mode_enable_mask) | + GPO_INIT_STATE(ctrl->gpo0_inactive_state_high_en | + (ctrl->gpo1_inactive_state_high_en << 1) | + (ctrl->gpo2_inactive_state_high_en << 2) | + (ctrl->gpo3_inactive_state_high_en << 3))); + + ad9361_spi_write(spi, REG_GPO0_RX_DELAY, ctrl->gpo0_rx_delay_us); + ad9361_spi_write(spi, REG_GPO0_TX_DELAY, ctrl->gpo0_tx_delay_us); + ad9361_spi_write(spi, REG_GPO1_RX_DELAY, ctrl->gpo1_rx_delay_us); + ad9361_spi_write(spi, REG_GPO1_TX_DELAY, ctrl->gpo1_tx_delay_us); + ad9361_spi_write(spi, REG_GPO2_RX_DELAY, ctrl->gpo2_rx_delay_us); + ad9361_spi_write(spi, REG_GPO2_TX_DELAY, ctrl->gpo2_tx_delay_us); + ad9361_spi_write(spi, REG_GPO3_RX_DELAY, ctrl->gpo3_rx_delay_us); + ad9361_spi_write(spi, REG_GPO3_TX_DELAY, ctrl->gpo3_tx_delay_us); + + /* + * GPO manual mode conflicts with automatic ENSM slave and eLNA mode + */ + ad9361_spi_writef(phy->spi, REG_EXTERNAL_LNA_CTRL, GPO_MANUAL_SELECT, + ctrl->gpo_manual_mode_en); + + return 0; +} + +/** + * Setup the RSSI. + * @param phy The AD9361 state structure. + * @param ctrl The RSSI settings. + * @param is_update True if update + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_rssi_setup(struct ad9361_rf_phy *phy, + struct rssi_control *ctrl, + bool is_update) +{ + struct spi_desc *spi = phy->spi; + uint32_t total_weight, weight[4], total_dur = 0, temp; + uint8_t dur_buf[4] = { 0 }; + int32_t val, ret, i, j = 0; + uint32_t rssi_delay; + uint32_t rssi_wait; + int32_t rssi_duration; + uint32_t rate; + + dev_dbg(&phy->spi->dev, "%s", __func__); + + if (ctrl->rssi_unit_is_rx_samples) { + if (is_update) + return 0; /* no update required */ + + rssi_delay = ctrl->rssi_delay; + rssi_wait = ctrl->rssi_wait; + rssi_duration = ctrl->rssi_duration; + } else { + /* update sample based on RX rate */ + rate = DIV_ROUND_CLOSEST( + clk_get_rate(phy, phy->ref_clk_scale[RX_SAMPL_CLK]), 1000); + /* units are in us */ + rssi_delay = DIV_ROUND_CLOSEST(ctrl->rssi_delay * rate, 1000); + rssi_wait = DIV_ROUND_CLOSEST(ctrl->rssi_wait * rate, 1000); + rssi_duration = DIV_ROUND_CLOSEST( + ctrl->rssi_duration * rate, 1000); + } + + if (ctrl->restart_mode == EN_AGC_PIN_IS_PULLED_HIGH) + rssi_delay = 0; + + rssi_delay = clamp(rssi_delay / 8, 0U, 255U); + rssi_wait = clamp(rssi_wait / 4, 0U, 255U); + + do { + for (i = 14; rssi_duration > 0 && i >= 0; i--) { + val = 1 << i; + if ((int64_t)rssi_duration >= val) { + dur_buf[j++] = i; + total_dur += val; + rssi_duration -= val; + break; + } + } + + } while (j < 4 && rssi_duration > 0); + + for (i = 0, total_weight = 0; i < 4; i++) { + if (i < j) + total_weight += weight[i] = + DIV_ROUND_CLOSEST(RSSI_MAX_WEIGHT * + (1 << dur_buf[i]), total_dur); + else + total_weight += weight[i] = 0; + } + + /* total of all weights must be 0xFF */ + val = total_weight - 0xFF; + weight[j - 1] -= val; + + ad9361_spi_write(spi, REG_MEASURE_DURATION_01, + (dur_buf[1] << 4) | dur_buf[0]); // RSSI Measurement Duration 0, 1 + ad9361_spi_write(spi, REG_MEASURE_DURATION_23, + (dur_buf[3] << 4) | dur_buf[2]); // RSSI Measurement Duration 2, 3 + ad9361_spi_write(spi, REG_RSSI_WEIGHT_0, + weight[0]); // RSSI Weighted Multiplier 0 + ad9361_spi_write(spi, REG_RSSI_WEIGHT_1, + weight[1]); // RSSI Weighted Multiplier 1 + ad9361_spi_write(spi, REG_RSSI_WEIGHT_2, + weight[2]); // RSSI Weighted Multiplier 2 + ad9361_spi_write(spi, REG_RSSI_WEIGHT_3, + weight[3]); // RSSI Weighted Multiplier 3 + ad9361_spi_write(spi, REG_RSSI_DELAY, rssi_delay); // RSSI Delay + ad9361_spi_write(spi, REG_RSSI_WAIT_TIME, rssi_wait); // RSSI Wait + + temp = RSSI_MODE_SELECT(ctrl->restart_mode); + if (ctrl->restart_mode == SPI_WRITE_TO_REGISTER) + temp |= START_RSSI_MEAS; + + if (rssi_duration == 0 && j == 1) /* Power of two */ + temp |= DEFAULT_RSSI_MEAS_MODE; + + ret = ad9361_spi_write(spi, REG_RSSI_CONFIG, temp); // RSSI Mode Select + + if (ret < 0) + dev_err(&phy->spi->dev, "Unable to write rssi config"); + + return 0; +} + +/** + * This function needs to be called whenever BBPLL changes. + * @param phy The AD9361 state structure. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_bb_clk_change_handler(struct ad9361_rf_phy *phy) +{ + int32_t ret; + + ret = ad9361_gc_update(phy); + ret |= ad9361_rssi_setup(phy, &phy->pdata->rssi_ctrl, true); + ret |= ad9361_auxadc_setup(phy, &phy->pdata->auxadc_ctrl, + clk_get_rate(phy, phy->ref_clk_scale[BBPLL_CLK])); + + return ret; +} + +/** + * Set the desired Enable State Machine (ENSM) state. + * @param phy The AD9361 state structure. + * @param ensm_state The ENSM state [ENSM_STATE_SLEEP_WAIT, ENSM_STATE_ALERT, + * ENSM_STATE_TX, ENSM_STATE_TX_FLUSH, ENSM_STATE_RX, + * ENSM_STATE_RX_FLUSH, ENSM_STATE_FDD, ENSM_STATE_FDD_FLUSH]. + * @param pinctrl Set true, will enable the ENSM pin control. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_ensm_set_state(struct ad9361_rf_phy *phy, uint8_t ensm_state, + bool pinctrl) +{ + struct spi_desc *spi = phy->spi; + int32_t rc = 0; + uint32_t val; + uint32_t tmp; + + dev_dbg(dev, "Device is in %x state, moving to %x", phy->curr_ensm_state, + ensm_state); + + + if (phy->curr_ensm_state == ENSM_STATE_SLEEP) { + ad9361_spi_write(spi, REG_CLOCK_ENABLE, + DIGITAL_POWER_UP | CLOCK_ENABLE_DFLT | BBPLL_ENABLE | + (phy->pdata->use_extclk ? XO_BYPASS : 0)); /* Enable Clocks */ + udelay(20); + ad9361_spi_write(spi, REG_ENSM_CONFIG_1, TO_ALERT | FORCE_ALERT_STATE); + ad9361_trx_vco_cal_control(phy, false, true); /* Enable VCO Cal */ + ad9361_trx_vco_cal_control(phy, true, true); + } + + val = (phy->pdata->ensm_pin_pulse_mode ? 0 : LEVEL_MODE) | + (pinctrl ? ENABLE_ENSM_PIN_CTRL : 0) | + (phy->txmon_tdd_en ? ENABLE_RX_DATA_PORT_FOR_CAL : 0) | + TO_ALERT; + + switch (ensm_state) { + case ENSM_STATE_TX: + val |= FORCE_TX_ON; + if (phy->pdata->fdd) + rc = -EINVAL; + else if (phy->curr_ensm_state != ENSM_STATE_ALERT) + rc = -EINVAL; + break; + case ENSM_STATE_RX: + val |= FORCE_RX_ON; + if (phy->pdata->fdd) + rc = -EINVAL; + else if (phy->curr_ensm_state != ENSM_STATE_ALERT) + rc = -EINVAL; + break; + case ENSM_STATE_FDD: + val |= FORCE_TX_ON; + if (!phy->pdata->fdd) + rc = -EINVAL; + break; + case ENSM_STATE_ALERT: + val &= ~(FORCE_TX_ON | FORCE_RX_ON); + val |= TO_ALERT | FORCE_ALERT_STATE; + break; + case ENSM_STATE_SLEEP_WAIT: + break; + case ENSM_STATE_SLEEP: + ad9361_trx_vco_cal_control(phy, false, false); /* Disable VCO Cal */ + ad9361_trx_vco_cal_control(phy, true, false); + ad9361_spi_write(spi, REG_ENSM_CONFIG_1, 0); /* Clear To Alert */ + ad9361_spi_write(spi, REG_ENSM_CONFIG_1, + phy->pdata->fdd ? FORCE_TX_ON : FORCE_RX_ON); + /* Delay Flush Time 384 ADC clock cycles */ + udelay(384000000UL / clk_get_rate(phy, phy->ref_clk_scale[ADC_CLK])); + ad9361_spi_write(spi, REG_ENSM_CONFIG_1, 0); /* Move to Wait*/ + udelay(1); /* Wait for ENSM settle */ + ad9361_spi_write(spi, REG_CLOCK_ENABLE, + (phy->pdata->use_extclk ? XO_BYPASS : 0)); /* Turn off all clocks */ + phy->curr_ensm_state = ensm_state; + return 0; + + default: + dev_err(dev, "No handling for forcing %d ensm state", + ensm_state); + goto out; + } + + if (rc) { + if ((phy->curr_ensm_state != ENSM_STATE_ALERT) + && (val & (FORCE_RX_ON | FORCE_TX_ON))) { + uint32_t val2 = val; + + val2 &= ~(FORCE_TX_ON | FORCE_RX_ON); + val2 |= TO_ALERT | FORCE_ALERT_STATE; + ad9361_spi_write(spi, REG_ENSM_CONFIG_1, val2); + + ad9361_check_cal_done(phy, REG_STATE, ENSM_STATE(~0), ENSM_STATE_ALERT); + } else { + dev_err(dev, "Invalid ENSM state transition in %s mode", + phy->pdata->fdd ? "FDD" : "TDD"); + goto out; + } + } + + if (!phy->pdata->fdd && !pinctrl && !phy->pdata->tdd_use_dual_synth && + (ensm_state == ENSM_STATE_TX || ensm_state == ENSM_STATE_RX)) { + uint32_t reg, check; + + if (ensm_state == ENSM_STATE_TX) { + reg = REG_TX_CP_OVERRANGE_VCO_LOCK; + check = !(phy->cached_synth_pd[0] & + TX_SYNTH_VCO_POWER_DOWN); + } else { + reg = REG_RX_CP_OVERRANGE_VCO_LOCK; + check = !(phy->cached_synth_pd[1] & + RX_SYNTH_VCO_POWER_DOWN); + } + + ad9361_spi_writef(phy->spi, REG_ENSM_CONFIG_2, + TXNRX_SPI_CTRL, ensm_state == ENSM_STATE_TX); + + if (check) + ad9361_check_cal_done(phy, reg, VCO_LOCK, 1); + } + + rc = ad9361_spi_write(spi, REG_ENSM_CONFIG_1, val); + if (rc) + dev_err(dev, "Failed to restore state"); + + if ((val & FORCE_RX_ON) && + (phy->agc_mode[0] == RF_GAIN_MGC || + phy->agc_mode[1] == RF_GAIN_MGC)) { + tmp = ad9361_spi_read(spi, REG_SMALL_LMT_OVERLOAD_THRESH); + ad9361_spi_write(spi, REG_SMALL_LMT_OVERLOAD_THRESH, + (tmp & SMALL_LMT_OVERLOAD_THRESH(~0)) | + (phy->agc_mode[0] == RF_GAIN_MGC ? FORCE_PD_RESET_RX1 : 0) | + (phy->agc_mode[1] == RF_GAIN_MGC ? FORCE_PD_RESET_RX2 : 0)); + ad9361_spi_write(spi, REG_SMALL_LMT_OVERLOAD_THRESH, + tmp & SMALL_LMT_OVERLOAD_THRESH(~0)); + } + + phy->curr_ensm_state = ensm_state; + +out: + return rc; + +} + +/** + * Check if at least one of the clock rates is equal to the DATA_CLK (lvds) rate. + * @param phy The AD9361 state structure. + * @param rx_path_clks RX path rates buffer. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_validate_trx_clock_chain(struct ad9361_rf_phy *phy, + uint32_t *rx_path_clks, uint32_t *tx_path_clks) +{ + static const uint32_t max_rx_rates[] = {MAX_BBPLL_FREQ, MAX_ADC_CLK, + MAX_RX_HB3, MAX_RX_HB2, MAX_RX_HB1, MAX_BASEBAND_RATE + }; + static const uint32_t max_tx_rates[] = {MAX_BBPLL_FREQ, MAX_DAC_CLK, + MAX_TX_HB3, MAX_TX_HB2, MAX_TX_HB1, MAX_BASEBAND_RATE + }; + uint32_t i; + uint32_t data_clk; + + data_clk = (phy->pdata->rx2tx2 ? 4 : 2) / + ((phy->pdata->port_ctrl.pp_conf[2] & LVDS_MODE) ? 1 : 2) * + rx_path_clks[RX_SAMPL_FREQ]; + + /* CMOS Mode */ + if (!(phy->pdata->port_ctrl.pp_conf[2] & LVDS_MODE) && + (data_clk > MAX_BASEBAND_RATE)) { + dev_err(&phy->spi->dev, + "%s: Failed CMOS MODE DATA_CLK > 61.44MSPS", __func__); + return -EINVAL; + } + + /* Validate MAX PLL, ADC, DAC and HB filter rates */ + for (i = 0; i < ARRAY_SIZE(max_rx_rates); i++) { + if (rx_path_clks[i] > max_rx_rates[i]) { + dev_err(&phy->spi->dev, + "%s: Failed RX max rate check (%"PRIu32" > %"PRIu32")", + __func__, rx_path_clks[i], max_rx_rates[i]); + return -EINVAL; + } + + if (tx_path_clks[i] > max_tx_rates[i]) { + dev_err(&phy->spi->dev, + "%s: Failed TX max rate check (%"PRIu32" > %"PRIu32")", + __func__, tx_path_clks[i], max_tx_rates[i]); + return -EINVAL; + } + } + + /* Validate that DATA_CLK exist within the clock chain */ + for (i = 1; i <= 3; i++) { + if (diff_abs(rx_path_clks[ADC_FREQ] / i, data_clk) < 4) + return 0; + } + + for (i = 1; i <= 4; i++) { + if (diff_abs((rx_path_clks[R2_FREQ] >> i), data_clk) < 4) + return 0; + } + + dev_err(&phy->spi->dev, "%s: Failed - at least one of the clock rates" + " must be equal to the DATA_CLK (lvds) rate", __func__); + + return -EINVAL; +} + +/** + * Set the RX and TX path rates. + * @param phy The AD9361 state structure. + * @param rx_path_clks RX path rates buffer. + * @param tx_path_clks TX path rates buffer. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_set_trx_clock_chain(struct ad9361_rf_phy *phy, + uint32_t *rx_path_clks, + uint32_t *tx_path_clks) +{ + int32_t ret, i, j, n; + + dev_dbg(&phy->spi->dev, "%s", __func__); + + if (!rx_path_clks || !tx_path_clks) + return -EINVAL; + + dev_dbg(&phy->spi->dev, + "%s: %"PRIu32" %"PRIu32" %"PRIu32" %"PRIu32" %"PRIu32" %"PRIu32, + __func__, rx_path_clks[BBPLL_FREQ], rx_path_clks[ADC_FREQ], + rx_path_clks[R2_FREQ], rx_path_clks[R1_FREQ], + rx_path_clks[CLKRF_FREQ], rx_path_clks[RX_SAMPL_FREQ]); + + dev_dbg(&phy->spi->dev, + "%s: %"PRIu32" %"PRIu32" %"PRIu32" %"PRIu32" %"PRIu32" %"PRIu32, + __func__, tx_path_clks[BBPLL_FREQ], tx_path_clks[ADC_FREQ], + tx_path_clks[R2_FREQ], tx_path_clks[R1_FREQ], + tx_path_clks[CLKRF_FREQ], tx_path_clks[RX_SAMPL_FREQ]); + + ret = ad9361_validate_trx_clock_chain(phy, rx_path_clks, tx_path_clks); + if (ret < 0) + return ret; + + ret = clk_set_rate(phy, phy->ref_clk_scale[BBPLL_CLK], + rx_path_clks[BBPLL_FREQ]); + if (ret < 0) + return ret; + + phy->current_rx_path_clks[BBPLL_FREQ] = rx_path_clks[BBPLL_FREQ]; + + for (i = ADC_CLK, j = DAC_CLK, n = ADC_FREQ; + i <= RX_SAMPL_CLK; i++, j++, n++) { + ret = clk_set_rate(phy, phy->ref_clk_scale[i], rx_path_clks[n]); + if (ret < 0) { + dev_err(dev, "Failed to set BB ref clock rate (%"PRId32")", + ret); + return ret; + } + phy->current_rx_path_clks[n] = rx_path_clks[n]; + ret = clk_set_rate(phy, phy->ref_clk_scale[j], tx_path_clks[n]); + if (ret < 0) { + dev_err(dev, "Failed to set BB ref clock rate (%"PRId32")", + ret); + return ret; + } + phy->current_tx_path_clks[n] = tx_path_clks[n]; + } + + /* + * Workaround for clock framework since clocks don't change we + * manually need to enable the filter + */ + + if (phy->rx_fir_dec == 1 || phy->bypass_rx_fir) { + ad9361_spi_writef(phy->spi, REG_RX_ENABLE_FILTER_CTRL, + RX_FIR_ENABLE_DECIMATION(~0), !phy->bypass_rx_fir); + } + + if (phy->tx_fir_int == 1 || phy->bypass_tx_fir) { + ad9361_spi_writef(phy->spi, REG_TX_ENABLE_FILTER_CTRL, + TX_FIR_ENABLE_INTERPOLATION(~0), !phy->bypass_tx_fir); + } + + /* The FIR filter once enabled causes the interface timing to change. + * It's typically not a problem if the timing margin is big enough. + * However at 61.44 MSPS it causes problems on some systems. + * So we always run the digital tune in case the filter is enabled. + * If it is disabled we restore the values from the initial calibration. + */ + + if (!phy->pdata->dig_interface_tune_fir_disable && + !(phy->bypass_tx_fir && phy->bypass_rx_fir)) + ret = ad9361_dig_tune(phy, 0, SKIP_STORE_RESULT); + + return ad9361_bb_clk_change_handler(phy); +} + +/** + * Get the RX and TX path rates. + * @param phy The AD9361 state structure. + * @param rx_path_clks RX path rates buffer. + * @param tx_path_clks TX path rates buffer. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_get_trx_clock_chain(struct ad9361_rf_phy *phy, + uint32_t *rx_path_clks, + uint32_t *tx_path_clks) +{ + int32_t i, j, n; + uint32_t bbpll_freq; + + if (!rx_path_clks && !tx_path_clks) + return -EINVAL; + + bbpll_freq = clk_get_rate(phy, phy->ref_clk_scale[BBPLL_CLK]); + + if (rx_path_clks) + rx_path_clks[BBPLL_FREQ] = bbpll_freq; + + if (tx_path_clks) + tx_path_clks[BBPLL_FREQ] = bbpll_freq; + + for (i = ADC_CLK, j = DAC_CLK, n = ADC_FREQ; + i <= RX_SAMPL_CLK; i++, j++, n++) { + if (rx_path_clks) + rx_path_clks[n] = clk_get_rate(phy, phy->ref_clk_scale[i]); + if (tx_path_clks) + tx_path_clks[n] = clk_get_rate(phy, phy->ref_clk_scale[j]); + } + + return 0; +} + +/** + * Calculate the RX and TX path rates to obtain the desired sample rate. + * @param phy The AD9361 state structure. + * @param tx_sample_rate The desired sample rate. + * @param rate_gov The rate governor option. + * @param rx_path_clks RX path rates buffer. + * @param tx_path_clks TX path rates buffer. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_calculate_rf_clock_chain(struct ad9361_rf_phy *phy, + uint32_t tx_sample_rate, + uint32_t rate_gov, + uint32_t *rx_path_clks, + uint32_t *tx_path_clks) +{ + uint32_t clktf, clkrf, adc_rate = 0, dac_rate = 0; + uint64_t bbpll_rate; + int32_t i, index_rx = -1, index_tx = -1, tmp; + uint32_t div, tx_intdec, rx_intdec, recursion = 1; + const int8_t clk_dividers[][4] = { + { 12, 3, 2, 2 }, + { 8, 2, 2, 2 }, + { 6, 3, 1, 2 }, + { 4, 2, 2, 1 }, + { 3, 3, 1, 1 }, + { 2, 2, 1, 1 }, + { 1, 1, 1, 1 }, + }; + + if (phy->bypass_rx_fir) + rx_intdec = 1; + else + rx_intdec = phy->rx_fir_dec; + + if (phy->bypass_tx_fir) + tx_intdec = 1; + else + tx_intdec = phy->tx_fir_int; + + if ((rate_gov == 1) && ((rx_intdec * tx_sample_rate * 8) < MIN_ADC_CLK)) { + recursion = 0; + rate_gov = 0; + } + + dev_dbg(&phy->spi->dev, + "%s: requested rate %"PRIu32" TXFIR int %"PRIu32" RXFIR dec %"PRIu32" mode %s", + __func__, tx_sample_rate, tx_intdec, rx_intdec, + rate_gov ? "Nominal" : "Highest OSR"); + + if (tx_sample_rate > MAX_BASEBAND_RATE) + return -EINVAL; + + clktf = tx_sample_rate * tx_intdec; + clkrf = tx_sample_rate * rx_intdec * (phy->rx_eq_2tx ? 2 : 1); + + for (i = rate_gov; i < 7; i++) { + adc_rate = clkrf * clk_dividers[i][0]; + dac_rate = clktf * clk_dividers[i][0]; + + if ((adc_rate <= MAX_ADC_CLK) && (adc_rate >= MIN_ADC_CLK)) { + + + if (dac_rate > adc_rate) + tmp = (dac_rate / adc_rate) * -1; + else + tmp = adc_rate / dac_rate; + + if (adc_rate <= MAX_DAC_CLK) { + index_rx = i; + index_tx = i - ((tmp == 1) ? 0 : tmp); + dac_rate = adc_rate; /* ADC_CLK */ + break; + } else { + dac_rate = adc_rate / 2; /* ADC_CLK/2 */ + index_rx = i; + + if (i == 4 && tmp >= 0) + index_tx = 7; /* STOP: 3/2 != 1 */ + else + index_tx = i + ((i == 5 && tmp >= 0) ? 1 : 2) - + ((tmp == 1) ? 0 : tmp); + + break; + } + } + } + + if ((index_tx < 0 || index_tx > 6 || index_rx < 0 || index_rx > 6) + && rate_gov < 7 && recursion) { + return ad9361_calculate_rf_clock_chain(phy, tx_sample_rate, + ++rate_gov, rx_path_clks, tx_path_clks); + } else if ((index_tx < 0 || index_tx > 6 || index_rx < 0 || index_rx > 6)) { + dev_err(&phy->spi->dev, "%s: Failed to find suitable dividers: %s", + __func__, (adc_rate < MIN_ADC_CLK) ? "ADC clock below limit" : + "BBPLL rate above limit"); + + return -EINVAL; + } + + /* Calculate target BBPLL rate */ + div = MAX_BBPLL_DIV; + + do { + bbpll_rate = (uint64_t)adc_rate * div; + div >>= 1; + + } while ((bbpll_rate > MAX_BBPLL_FREQ) && (div >= MIN_BBPLL_DIV)); + + rx_path_clks[BBPLL_FREQ] = bbpll_rate; + rx_path_clks[ADC_FREQ] = adc_rate; + rx_path_clks[R2_FREQ] = rx_path_clks[ADC_FREQ] / clk_dividers[index_rx][1]; + rx_path_clks[R1_FREQ] = rx_path_clks[R2_FREQ] / clk_dividers[index_rx][2]; + rx_path_clks[CLKRF_FREQ] = rx_path_clks[R1_FREQ] / clk_dividers[index_rx][3]; + rx_path_clks[RX_SAMPL_FREQ] = rx_path_clks[CLKRF_FREQ] / rx_intdec; + + tx_path_clks[BBPLL_FREQ] = bbpll_rate; + tx_path_clks[DAC_FREQ] = dac_rate; + tx_path_clks[T2_FREQ] = tx_path_clks[DAC_FREQ] / clk_dividers[index_tx][1]; + tx_path_clks[T1_FREQ] = tx_path_clks[T2_FREQ] / clk_dividers[index_tx][2]; + tx_path_clks[CLKTF_FREQ] = tx_path_clks[T1_FREQ] / clk_dividers[index_tx][3]; + tx_path_clks[TX_SAMPL_FREQ] = tx_path_clks[CLKTF_FREQ] / tx_intdec; + + return 0; +} + +/** + * Set the desired sample rate. + * @param phy The AD9361 state structure. + * @param freq The desired sample rate. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_set_trx_clock_chain_freq(struct ad9361_rf_phy *phy, + uint32_t freq) +{ + uint32_t rx[6], tx[6]; + int32_t ret; + + ret = ad9361_calculate_rf_clock_chain(phy, freq, + phy->rate_governor, rx, tx); + if (ret < 0) + return ret; + return ad9361_set_trx_clock_chain(phy, rx, tx); +} + +/** + * Internal ENSM mode options helper function. + * @param phy The AD9361 state structure. + * @param fdd + * @param pinctrl + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_set_ensm_mode(struct ad9361_rf_phy *phy, bool fdd, bool pinctrl) +{ + struct ad9361_phy_platform_data *pd = phy->pdata; + int32_t ret; + uint32_t val = 0; + + ad9361_spi_write(phy->spi, REG_ENSM_MODE, fdd ? FDD_MODE : 0); + + val = ad9361_spi_read(phy->spi, REG_ENSM_CONFIG_2); + val &= POWER_DOWN_RX_SYNTH | POWER_DOWN_TX_SYNTH | + RX_SYNTH_READY_MASK | TX_SYNTH_READY_MASK; + + if (fdd) + ret = ad9361_spi_write(phy->spi, REG_ENSM_CONFIG_2, + val | DUAL_SYNTH_MODE | + (pd->fdd_independent_mode ? FDD_EXTERNAL_CTRL_ENABLE : 0)); + else + ret = ad9361_spi_write(phy->spi, REG_ENSM_CONFIG_2, val | + (pd->tdd_use_dual_synth ? DUAL_SYNTH_MODE : 0) | + (pd->tdd_use_dual_synth ? 0 : + (pinctrl ? SYNTH_ENABLE_PIN_CTRL_MODE : 0))); + + return ret; +} + +/** + * Fastlock read value. + * @param spi + * @param tx + * @param profile + * @param word + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_fastlock_readval(struct spi_desc *spi, bool tx, + uint32_t profile, uint32_t word) +{ + uint32_t offs = 0; + + if (tx) + offs = REG_TX_FAST_LOCK_SETUP - REG_RX_FAST_LOCK_SETUP; + + ad9361_spi_write(spi, REG_RX_FAST_LOCK_PROGRAM_ADDR + offs, + RX_FAST_LOCK_PROFILE_ADDR(profile) | + RX_FAST_LOCK_PROFILE_WORD(word)); + + return ad9361_spi_read(spi, REG_RX_FAST_LOCK_PROGRAM_READ + offs); +} + +/** + * Fastlock write value. + * @param spi + * @param tx + * @param profile + * @param word + * @param val + * @param last + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_fastlock_writeval(struct spi_desc *spi, bool tx, + uint32_t profile, uint32_t word, uint8_t val, bool last) +{ + uint32_t offs = 0; + int32_t ret; + + if (tx) + offs = REG_TX_FAST_LOCK_SETUP - REG_RX_FAST_LOCK_SETUP; + + ret = ad9361_spi_write(spi, REG_RX_FAST_LOCK_PROGRAM_ADDR + offs, + RX_FAST_LOCK_PROFILE_ADDR(profile) | + RX_FAST_LOCK_PROFILE_WORD(word)); + ret |= ad9361_spi_write(spi, REG_RX_FAST_LOCK_PROGRAM_DATA + offs, val); + ret |= ad9361_spi_write(spi, REG_RX_FAST_LOCK_PROGRAM_CTRL + offs, + RX_FAST_LOCK_PROGRAM_WRITE | + RX_FAST_LOCK_PROGRAM_CLOCK_ENABLE); + + if (last) /* Stop Clocks */ + ret |= ad9361_spi_write(spi, + REG_RX_FAST_LOCK_PROGRAM_CTRL + offs, 0); + + return ret; +} + +/** + * Fastlock load values. + * @param phy The AD9361 state structure. + * @param tx + * @param profile + * @param values + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_fastlock_load(struct ad9361_rf_phy *phy, bool tx, + uint32_t profile, uint8_t *values) +{ + uint32_t offs = 0; + int32_t i, ret = 0; + uint8_t buf[4]; + + dev_dbg(&phy->spi->dev, "%s: %s Profile %"PRIu32":", + __func__, tx ? "TX" : "RX", profile); + + if (tx) + offs = REG_TX_FAST_LOCK_SETUP - REG_RX_FAST_LOCK_SETUP; + + buf[0] = values[0]; + buf[1] = RX_FAST_LOCK_PROFILE_ADDR(profile) | RX_FAST_LOCK_PROFILE_WORD(0); + ad9361_spi_writem(phy->spi, REG_RX_FAST_LOCK_PROGRAM_DATA + offs, buf, 2); + + for (i = 1; i < RX_FAST_LOCK_CONFIG_WORD_NUM; i++) { + buf[0] = RX_FAST_LOCK_PROGRAM_WRITE | RX_FAST_LOCK_PROGRAM_CLOCK_ENABLE; + buf[1] = 0; + buf[2] = values[i]; + buf[3] = RX_FAST_LOCK_PROFILE_ADDR(profile) | RX_FAST_LOCK_PROFILE_WORD(i); + ad9361_spi_writem(phy->spi, REG_RX_FAST_LOCK_PROGRAM_CTRL + offs, buf, 4); + } + + ad9361_spi_write(phy->spi, REG_RX_FAST_LOCK_PROGRAM_CTRL + offs, + RX_FAST_LOCK_PROGRAM_WRITE | RX_FAST_LOCK_PROGRAM_CLOCK_ENABLE); + ad9361_spi_write(phy->spi, REG_RX_FAST_LOCK_PROGRAM_CTRL + offs, 0); + + phy->fastlock.entry[tx][profile].flags = FASTLOOK_INIT; + phy->fastlock.entry[tx][profile].alc_orig = values[15]; + phy->fastlock.entry[tx][profile].alc_written = values[15]; + + return ret; +} + +/** + * Fastlock store. + * @param phy The AD9361 state structure. + * @param tx + * @param profile + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_fastlock_store(struct ad9361_rf_phy *phy, bool tx, + uint32_t profile) +{ + struct spi_desc *spi = phy->spi; + uint8_t val[16]; + uint32_t offs = 0, x, y; + + dev_dbg(&phy->spi->dev, "%s: %s Profile %"PRIu32":", + __func__, tx ? "TX" : "RX", profile); + + if (tx) + offs = REG_TX_FAST_LOCK_SETUP - REG_RX_FAST_LOCK_SETUP; + + val[0] = ad9361_spi_read(spi, REG_RX_INTEGER_BYTE_0 + offs); + val[1] = ad9361_spi_read(spi, REG_RX_INTEGER_BYTE_1 + offs); + val[2] = ad9361_spi_read(spi, REG_RX_FRACT_BYTE_0 + offs); + val[3] = ad9361_spi_read(spi, REG_RX_FRACT_BYTE_1 + offs); + val[4] = ad9361_spi_read(spi, REG_RX_FRACT_BYTE_2 + offs); + + x = ad9361_spi_readf(spi, REG_RX_VCO_BIAS_1 + offs, VCO_BIAS_REF(~0)); + y = ad9361_spi_readf(spi, REG_RX_ALC_VARACTOR + offs, VCO_VARACTOR(~0)); + val[5] = (x << 4) | y; + + x = ad9361_spi_readf(spi, REG_RX_VCO_BIAS_1 + offs, VCO_BIAS_TCF(~0)); + y = ad9361_spi_readf(spi, REG_RX_CP_CURRENT + offs, CHARGE_PUMP_CURRENT(~0)); + /* Wide BW option: N = 1 + * Set init and steady state values to the same - let user space handle it + */ + val[6] = (x << 3) | y; + val[7] = y; + + x = ad9361_spi_readf(spi, REG_RX_LOOP_FILTER_3 + offs, LOOP_FILTER_R3(~0)); + val[8] = (x << 4) | x; + + x = ad9361_spi_readf(spi, REG_RX_LOOP_FILTER_2 + offs, LOOP_FILTER_C3(~0)); + val[9] = (x << 4) | x; + + x = ad9361_spi_readf(spi, REG_RX_LOOP_FILTER_1 + offs, LOOP_FILTER_C1(~0)); + y = ad9361_spi_readf(spi, REG_RX_LOOP_FILTER_1 + offs, LOOP_FILTER_C2(~0)); + val[10] = (x << 4) | y; + + x = ad9361_spi_readf(spi, REG_RX_LOOP_FILTER_2 + offs, LOOP_FILTER_R1(~0)); + val[11] = (x << 4) | x; + + x = ad9361_spi_readf(spi, REG_RX_VCO_VARACTOR_CTRL_0 + offs, + VCO_VARACTOR_REFERENCE_TCF(~0)); + y = ad9361_spi_readf(spi, REG_RFPLL_DIVIDERS, + tx ? TX_VCO_DIVIDER(~0) : RX_VCO_DIVIDER(~0)); + val[12] = (x << 4) | y; + + x = ad9361_spi_readf(spi, REG_RX_FORCE_VCO_TUNE_1 + offs, VCO_CAL_OFFSET(~0)); + y = ad9361_spi_readf(spi, REG_RX_VCO_VARACTOR_CTRL_1 + offs, + VCO_VARACTOR_REFERENCE(~0)); + val[13] = (x << 4) | y; + + val[14] = ad9361_spi_read(spi, REG_RX_FORCE_VCO_TUNE_0 + offs); + + x = ad9361_spi_readf(spi, REG_RX_FORCE_ALC + offs, FORCE_ALC_WORD(~0)); + y = ad9361_spi_readf(spi, REG_RX_FORCE_VCO_TUNE_1 + offs, FORCE_VCO_TUNE); + val[15] = (x << 1) | y; + + return ad9361_fastlock_load(phy, tx, profile, val); +} + +/** + * Fastlock prepare. + * @param phy The AD9361 state structure. + * @param tx + * @param profile + * @param prepare + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_fastlock_prepare(struct ad9361_rf_phy *phy, bool tx, + uint32_t profile, bool prepare) +{ + uint32_t offs, ready_mask; + bool is_prepared; + + dev_dbg(&phy->spi->dev, "%s: %s Profile %"PRIu32": %s", + __func__, tx ? "TX" : "RX", profile, + prepare ? "Prepare" : "Un-Prepare"); + + if (tx) { + offs = REG_TX_FAST_LOCK_SETUP - REG_RX_FAST_LOCK_SETUP; + ready_mask = TX_SYNTH_READY_MASK; + } else { + offs = 0; + ready_mask = RX_SYNTH_READY_MASK; + } + + is_prepared = !!phy->fastlock.current_profile[tx]; + + if (prepare && !is_prepared) { + ad9361_spi_write(phy->spi, + REG_RX_FAST_LOCK_SETUP_INIT_DELAY + offs, + (tx ? phy->pdata->tx_fastlock_delay_ns : + phy->pdata->rx_fastlock_delay_ns) / 250); + ad9361_spi_write(phy->spi, REG_RX_FAST_LOCK_SETUP + offs, + RX_FAST_LOCK_PROFILE(profile) | + RX_FAST_LOCK_MODE_ENABLE); + ad9361_spi_write(phy->spi, REG_RX_FAST_LOCK_PROGRAM_CTRL + offs, + 0); + + ad9361_spi_writef(phy->spi, REG_ENSM_CONFIG_2, ready_mask, 1); + ad9361_trx_vco_cal_control(phy, tx, false); + } else if (!prepare && is_prepared) { + ad9361_spi_write(phy->spi, REG_RX_FAST_LOCK_SETUP + offs, 0); + + /* Workaround: Exiting Fastlock Mode */ + ad9361_spi_writef(phy->spi, REG_RX_FORCE_ALC + offs, FORCE_ALC_ENABLE, 1); + ad9361_spi_writef(phy->spi, REG_RX_FORCE_VCO_TUNE_1 + offs, FORCE_VCO_TUNE, 1); + ad9361_spi_writef(phy->spi, REG_RX_FORCE_ALC + offs, FORCE_ALC_ENABLE, 0); + ad9361_spi_writef(phy->spi, REG_RX_FORCE_VCO_TUNE_1 + offs, FORCE_VCO_TUNE, 0); + + ad9361_trx_vco_cal_control(phy, tx, true); + ad9361_spi_writef(phy->spi, REG_ENSM_CONFIG_2, ready_mask, 0); + + phy->fastlock.current_profile[tx] = 0; + } + + return 0; +} + +/** + * Fastlock recall. + * @param phy The AD9361 state structure. + * @param tx + * @param profile + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_fastlock_recall(struct ad9361_rf_phy *phy, bool tx, + uint32_t profile) +{ + uint32_t offs = 0; + uint8_t curr, _new, orig, current_profile; + + dev_dbg(&phy->spi->dev, "%s: %s Profile %"PRIu32":", + __func__, tx ? "TX" : "RX", profile); + + if (tx) + offs = REG_TX_FAST_LOCK_SETUP - REG_RX_FAST_LOCK_SETUP; + + if (phy->fastlock.entry[tx][profile].flags != FASTLOOK_INIT) + return -EINVAL; + + /* Workaround: Lock problem with same ALC word */ + + current_profile = phy->fastlock.current_profile[tx]; + _new = phy->fastlock.entry[tx][profile].alc_written; + + if (current_profile == 0) + curr = ad9361_spi_readf(phy->spi, REG_RX_FORCE_ALC + offs, + FORCE_ALC_WORD(~0)) << 1; + else + curr = phy->fastlock.entry[tx][current_profile - 1].alc_written; + + if ((curr >> 1) == (_new >> 1)) { + orig = phy->fastlock.entry[tx][profile].alc_orig; + + if ((orig >> 1) == (_new >> 1)) + phy->fastlock.entry[tx][profile].alc_written += 2; + else + phy->fastlock.entry[tx][profile].alc_written = orig; + + ad9361_fastlock_writeval(phy->spi, tx, profile, 0xF, + phy->fastlock.entry[tx][profile].alc_written, true); + } + + ad9361_fastlock_prepare(phy, tx, profile, true); + phy->fastlock.current_profile[tx] = profile + 1; + + return ad9361_spi_write(phy->spi, REG_RX_FAST_LOCK_SETUP + offs, + RX_FAST_LOCK_PROFILE(profile) | + (phy->pdata->trx_fastlock_pinctrl_en[tx] ? + RX_FAST_LOCK_PROFILE_PIN_SELECT : 0) | + RX_FAST_LOCK_MODE_ENABLE); +} + +/** + * Fastlock save. + * @param phy The AD9361 state structure. + * @param tx + * @param profile + * @param values + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_fastlock_save(struct ad9361_rf_phy *phy, bool tx, + uint32_t profile, uint8_t *values) +{ + int32_t i; + + dev_dbg(&phy->spi->dev, "%s: %s Profile %"PRIu32":", + __func__, tx ? "TX" : "RX", profile); + + for (i = 0; i < RX_FAST_LOCK_CONFIG_WORD_NUM; i++) + values[i] = ad9361_fastlock_readval(phy->spi, tx, profile, i); + + return 0; +} + +/** + * Multi Chip Sync (MCS) config. + * @param phy The AD9361 state structure. + * @param step MCS step. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_mcs(struct ad9361_rf_phy *phy, int32_t step) +{ + int32_t mcs_mask = MCS_RF_ENABLE | MCS_BBPLL_ENABLE | + MCS_DIGITAL_CLK_ENABLE | MCS_BB_ENABLE; + + dev_dbg(&phy->spi->dev, "%s: MCS step %"PRId32, __func__, step); + + switch (step) { + case 1: + /* REVIST: + * POWER_DOWN_TRX_SYNTH and MCS_RF_ENABLE somehow conflict + */ + ad9361_spi_writef(phy->spi, REG_ENSM_CONFIG_2, + POWER_DOWN_TX_SYNTH | POWER_DOWN_RX_SYNTH, 0); + + ad9361_spi_writef(phy->spi, REG_MULTICHIP_SYNC_AND_TX_MON_CTRL, + mcs_mask, MCS_BB_ENABLE | MCS_BBPLL_ENABLE | MCS_RF_ENABLE); + ad9361_spi_writef(phy->spi, REG_CP_BLEED_CURRENT, + MCS_REFCLK_SCALE_EN, 1); + break; + case 2: + if(!phy->gpio_desc_sync) + break; + /* + * NOTE: This is not a regular GPIO - + * HDL ensures Multi-chip Synchronization SYNC_IN Pulse Timing + * relative to rising and falling edge of REF_CLK + */ + gpio_set_value(phy->gpio_desc_sync, 1); + gpio_set_value(phy->gpio_desc_sync, 0); + break; + case 3: + ad9361_spi_writef(phy->spi, REG_MULTICHIP_SYNC_AND_TX_MON_CTRL, + mcs_mask, MCS_BB_ENABLE | MCS_DIGITAL_CLK_ENABLE | MCS_RF_ENABLE); + break; + case 4: + if(!phy->gpio_desc_sync) + break; + gpio_set_value(phy->gpio_desc_sync, 1); + gpio_set_value(phy->gpio_desc_sync, 0); + break; + case 5: + ad9361_spi_writef(phy->spi, REG_MULTICHIP_SYNC_AND_TX_MON_CTRL, + mcs_mask, MCS_RF_ENABLE); + break; + } + + return 0; +} + +/** + * Clear state. + * @param phy The AD9361 state structure. + * @return None. + */ +void ad9361_clear_state(struct ad9361_rf_phy *phy) +{ + phy->current_table = NO_GAIN_TABLE; + phy->bypass_tx_fir = true; + phy->bypass_rx_fir = true; + phy->rate_governor = 1; + phy->rfdc_track_en = true; + phy->bbdc_track_en = true; + phy->quad_track_en = true; + phy->prev_ensm_state = 0; + phy->curr_ensm_state = 0; + phy->auto_cal_en = false; + phy->manual_tx_quad_cal_en = false; + phy->last_tx_quad_cal_freq = 0; + phy->flags = 0; + phy->current_rx_bw_Hz = 0; + phy->current_tx_bw_Hz = 0; + phy->rxbbf_div = 0; + phy->tx_fir_int = 0; + phy->tx_fir_ntaps = 0; + phy->rx_fir_dec = 0; + phy->rx_fir_ntaps = 0; + phy->ensm_pin_ctl_en = false; + phy->txmon_tdd_en = 0; + phy->current_tx_lo_freq = 0; + phy->current_rx_lo_freq = 0; + phy->current_tx_use_tdd_table = false; + phy->current_rx_use_tdd_table = false; + phy->cached_synth_pd[0] = 0; + phy->cached_synth_pd[1] = 0; + + memset(&phy->fastlock, 0, sizeof(phy->fastlock)); +} + +/** + * Determine the reference frequency value. + * @param refin_Hz Maximum allowed frequency. + * @param max Reference in frequency value. + * @return Reference frequency value. + */ +static uint32_t ad9361_ref_div_sel(uint32_t refin_Hz, uint32_t max) +{ + if (refin_Hz <= (max / 2)) + return 2 * refin_Hz; + else if (refin_Hz <= max) + return refin_Hz; + else if (refin_Hz <= (max * 2)) + return refin_Hz / 2; + else if (refin_Hz <= (max * 4)) + return refin_Hz / 4; + else + return 0; +} + +/** + * Setup the AD9361 device. + * @param phy The AD9361 state structure. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_setup(struct ad9361_rf_phy *phy) +{ + uint32_t refin_Hz, ref_freq, bbpll_freq; + struct spi_desc *spi = phy->spi; + struct ad9361_phy_platform_data *pd = phy->pdata; + int32_t ret; + uint32_t real_rx_bandwidth, real_tx_bandwidth; + bool tmp_use_ext_rx_lo = pd->use_ext_rx_lo; + bool tmp_use_ext_tx_lo = pd->use_ext_tx_lo; + + dev_dbg(dev, "%s", __func__); + + pd->rf_rx_bandwidth_Hz = ad9361_validate_rf_bw(phy, pd->rf_rx_bandwidth_Hz); + pd->rf_tx_bandwidth_Hz = ad9361_validate_rf_bw(phy, pd->rf_tx_bandwidth_Hz); + + real_rx_bandwidth = pd->rf_rx_bandwidth_Hz / 2; + real_tx_bandwidth = pd->rf_tx_bandwidth_Hz / 2; + + if (pd->fdd) { + pd->tdd_skip_vco_cal = false; + if (pd->ensm_pin_ctrl && pd->fdd_independent_mode) { + dev_warn(dev, + "%s: Either set ENSM PINCTRL or FDD Independent Mode", + __func__); + pd->ensm_pin_ctrl = false; + } + } + + ret = ad9361_auxdac_setup(phy, &pd->auxdac_ctrl); + if (ret < 0) + return ret; + + ret = ad9361_gpo_setup(phy, &pd->gpo_ctrl); + if (ret < 0) + return ret; + + if (pd->port_ctrl.pp_conf[2] & FDD_RX_RATE_2TX_RATE) + phy->rx_eq_2tx = true; + + ad9361_spi_write(spi, REG_CTRL, CTRL_ENABLE); + ad9361_spi_write(spi, REG_BANDGAP_CONFIG0, + MASTER_BIAS_TRIM(0x0E)); /* Enable Master Bias */ + ad9361_spi_write(spi, REG_BANDGAP_CONFIG1, + BANDGAP_TEMP_TRIM(0x0E)); /* Set Bandgap Trim */ + + ad9361_set_dcxo_tune(phy, pd->dcxo_coarse, pd->dcxo_fine); + + refin_Hz = phy->clk_refin->rate; + + ref_freq = ad9361_ref_div_sel(refin_Hz, MAX_BBPLL_FREF); + if (!ref_freq) + return -EINVAL; + + ad9361_spi_writef(spi, REG_REF_DIVIDE_CONFIG_1, RX_REF_RESET_BAR, 1); + ad9361_spi_writef(spi, REG_REF_DIVIDE_CONFIG_2, TX_REF_RESET_BAR, 1); + ad9361_spi_writef(spi, REG_REF_DIVIDE_CONFIG_2, + TX_REF_DOUBLER_FB_DELAY(~0), 3); /* FB DELAY */ + ad9361_spi_writef(spi, REG_REF_DIVIDE_CONFIG_2, + RX_REF_DOUBLER_FB_DELAY(~0), 3); /* FB DELAY */ + + ad9361_spi_write(spi, REG_CLOCK_ENABLE, + DIGITAL_POWER_UP | CLOCK_ENABLE_DFLT | BBPLL_ENABLE | + (pd->use_extclk ? XO_BYPASS : 0)); /* Enable Clocks */ + + ret = clk_set_rate(phy, phy->ref_clk_scale[BB_REFCLK], ref_freq); + if (ret < 0) { + dev_err(dev, "Failed to set BB ref clock rate (%"PRId32")", + ret); + return ret; + } + + ret = clk_prepare_enable(phy->clks[BB_REFCLK]); + if (ret < 0) { + dev_err(dev, "Failed to enable BB ref clock rate (%"PRId32")", + ret); + return ret; + } + + ad9361_spi_write(spi, REG_FRACT_BB_FREQ_WORD_2, 0x12); + ad9361_spi_write(spi, REG_FRACT_BB_FREQ_WORD_3, 0x34); + + ret = ad9361_set_trx_clock_chain(phy, pd->rx_path_clks, + pd->tx_path_clks); + if (ret < 0) + return ret; + + if (!pd->rx2tx2) { + pd->rx1tx1_mode_use_tx_num = + clamp_t(uint32_t, pd->rx1tx1_mode_use_tx_num, TX_1, TX_2); + pd->rx1tx1_mode_use_rx_num = + clamp_t(uint32_t, pd->rx1tx1_mode_use_rx_num, RX_1, RX_2); + + ad9361_en_dis_tx(phy, TX_1 | TX_2, pd->rx1tx1_mode_use_tx_num); + ad9361_en_dis_rx(phy, TX_1 | TX_2, pd->rx1tx1_mode_use_rx_num); + } else { + ad9361_en_dis_tx(phy, TX_1 | TX_2, TX_1 | TX_2); + ad9361_en_dis_rx(phy, RX_1 | RX_2, RX_1 | RX_2); + } + + ret = ad9361_rf_port_setup(phy, true, pd->rf_rx_input_sel, + pd->rf_tx_output_sel); + if (ret < 0) + return ret; + + ret = ad9361_pp_port_setup(phy, false); + if (ret < 0) + return ret; + + bbpll_freq = clk_get_rate(phy, phy->ref_clk_scale[BBPLL_CLK]); + ret = ad9361_auxadc_setup(phy, &pd->auxadc_ctrl, bbpll_freq); + if (ret < 0) + return ret; + + ret = ad9361_ctrl_outs_setup(phy, &pd->ctrl_outs_ctrl); + if (ret < 0) + return ret; + + ret = ad9361_set_ref_clk_cycles(phy, refin_Hz); + if (ret < 0) + return ret; + + ret = ad9361_setup_ext_lna(phy, &pd->elna_ctrl); + if (ret < 0) + return ret; + + /* + * This allows forcing a lower F_REF window + * (worse phase noise, better fractional spurs) + */ + pd->trx_synth_max_fref = clamp_t(uint32_t, pd->trx_synth_max_fref, + MIN_SYNTH_FREF, MAX_SYNTH_FREF); + + ref_freq = ad9361_ref_div_sel(refin_Hz, pd->trx_synth_max_fref); + if (!ref_freq) + return -EINVAL; + + ret = clk_set_rate(phy, phy->ref_clk_scale[RX_REFCLK], ref_freq); + if (ret < 0) { + dev_err(dev, "Failed to set RX Synth ref clock rate (%"PRId32")", ret); + return ret; + } + + ret = clk_set_rate(phy, phy->ref_clk_scale[TX_REFCLK], ref_freq); + if (ret < 0) { + dev_err(dev, "Failed to set TX Synth ref clock rate (%"PRId32")", ret); + return ret; + } + + ret = ad9361_txrx_synth_cp_calib(phy, ref_freq, false); /* RXCP */ + if (ret < 0) + return ret; + + ret = ad9361_txrx_synth_cp_calib(phy, ref_freq, true); /* TXCP */ + if (ret < 0) + return ret; + + phy->pdata->use_ext_rx_lo = 0; + phy->pdata->use_ext_tx_lo = 0; + + ret = clk_set_rate(phy, phy->ref_clk_scale[RX_RFPLL], + ad9361_to_clk(pd->rx_synth_freq)); + if (ret < 0) { + dev_err(dev, "Failed to set RX Synth rate (%"PRId32")", + ret); + return ret; + } + + ret = clk_prepare_enable(phy->clks[RX_REFCLK]); + if (ret < 0) { + dev_err(dev, "Failed to enable RX Synth ref clock (%"PRId32")", ret); + return ret; + } + + ret = clk_prepare_enable(phy->clks[RX_RFPLL]); + if (ret < 0) + return ret; + + /* Skip quad cal here we do it later again */ + phy->last_tx_quad_cal_freq = pd->tx_synth_freq; + ret = clk_set_rate(phy, phy->ref_clk_scale[TX_RFPLL], + ad9361_to_clk(pd->tx_synth_freq)); + if (ret < 0) { + dev_err(dev, "Failed to set TX Synth rate (%"PRId32")", + ret); + return ret; + } + + ret = clk_prepare_enable(phy->clks[TX_REFCLK]); + if (ret < 0) { + dev_err(dev, "Failed to enable TX Synth ref clock (%"PRId32")", ret); + return ret; + } + + ret = clk_prepare_enable(phy->clks[TX_RFPLL]); + if (ret < 0) + return ret; + + phy->pdata->use_ext_rx_lo = tmp_use_ext_rx_lo; + phy->pdata->use_ext_tx_lo = tmp_use_ext_tx_lo; + + ad9361_clk_mux_set_parent(phy->ref_clk_scale[RX_RFPLL], + pd->use_ext_rx_lo); + + ad9361_clk_mux_set_parent(phy->ref_clk_scale[TX_RFPLL], + pd->use_ext_tx_lo); + + ret = ad9361_load_mixer_gm_subtable(phy); + if (ret < 0) + return ret; + + ret = ad9361_gc_setup(phy, &pd->gain_ctrl); + if (ret < 0) + return ret; + + ret = ad9361_rx_bb_analog_filter_calib(phy, + real_rx_bandwidth, + bbpll_freq); + if (ret < 0) + return ret; + + ret = ad9361_tx_bb_analog_filter_calib(phy, + real_tx_bandwidth, + bbpll_freq); + if (ret < 0) + return ret; + + ret = ad9361_rx_tia_calib(phy, real_rx_bandwidth); + if (ret < 0) + return ret; + + ret = ad9361_tx_bb_second_filter_calib(phy, real_tx_bandwidth); + if (ret < 0) + return ret; + + ret = ad9361_rx_adc_setup(phy, + bbpll_freq, + clk_get_rate(phy, phy->ref_clk_scale[ADC_CLK])); + if (ret < 0) + return ret; + + ret = ad9361_bb_dc_offset_calib(phy); + if (ret < 0) + return ret; + + ret = ad9361_rf_dc_offset_calib(phy, + ad9361_from_clk(clk_get_rate(phy, phy->ref_clk_scale[RX_RFPLL]))); + if (ret < 0) + return ret; + + phy->current_rx_bw_Hz = pd->rf_rx_bandwidth_Hz; + phy->current_tx_bw_Hz = pd->rf_tx_bandwidth_Hz; + phy->last_tx_quad_cal_phase = ~0; + ret = ad9361_tx_quad_calib(phy, real_rx_bandwidth, real_tx_bandwidth, -1); + if (ret < 0) + return ret; + + ret = ad9361_tracking_control(phy, phy->bbdc_track_en, + phy->rfdc_track_en, phy->quad_track_en); + if (ret < 0) + return ret; + + ad9361_pp_port_setup(phy, true); + + ret = ad9361_set_ensm_mode(phy, pd->fdd, pd->ensm_pin_ctrl); + if (ret < 0) + return ret; + + ad9361_spi_writef(phy->spi, REG_TX_ATTEN_OFFSET, + MASK_CLR_ATTEN_UPDATE, 0); + + ret = ad9361_set_tx_atten(phy, pd->tx_atten, + pd->rx2tx2 ? true : pd->rx1tx1_mode_use_tx_num == 1, + pd->rx2tx2 ? true : pd->rx1tx1_mode_use_tx_num == 2, true); + if (ret < 0) + return ret; + + if (!pd->rx2tx2) { + ret = ad9361_set_tx_atten(phy, 89750, + pd->rx1tx1_mode_use_tx_num == 2, + pd->rx1tx1_mode_use_tx_num == 1, true); + if (ret < 0) + return ret; + } + + ret = ad9361_rssi_setup(phy, &pd->rssi_ctrl, false); + if (ret < 0) + return ret; + + ret = ad9361_clkout_control(phy, pd->ad9361_clkout_mode); + if (ret < 0) + return ret; + + ret = ad9361_txmon_setup(phy, &pd->txmon_ctrl); + if (ret < 0) + return ret; + + phy->curr_ensm_state = ad9361_spi_readf(spi, REG_STATE, ENSM_STATE(~0)); + ad9361_ensm_set_state(phy, pd->fdd ? ENSM_STATE_FDD : ENSM_STATE_RX, + pd->ensm_pin_ctrl); + + phy->auto_cal_en = true; + phy->cal_threshold_freq = 100000000ULL; /* 100 MHz */ + + return 0; + +} + +/** + * Perform the selected calibration + * @param phy The AD9361 state structure. + * @param cal The selected calibration. + * @param arg The argument of the calibration. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_do_calib_run(struct ad9361_rf_phy *phy, uint32_t cal, + int32_t arg) +{ + int32_t ret; + + dev_dbg(&phy->spi->dev, "%s: CAL %"PRIu32" ARG %"PRId32, __func__, cal, arg); + + ret = ad9361_tracking_control(phy, false, false, false); + if (ret < 0) + return ret; + + ad9361_ensm_force_state(phy, ENSM_STATE_ALERT); + + switch (cal) { + case TX_QUAD_CAL: + ret = ad9361_tx_quad_calib(phy, phy->current_rx_bw_Hz / 2, + phy->current_tx_bw_Hz / 2, arg); + break; + case RFDC_CAL: + ret = ad9361_rf_dc_offset_calib(phy, + ad9361_from_clk(clk_get_rate(phy, phy->ref_clk_scale[RX_RFPLL]))); + break; + default: + ret = -EINVAL; + break; + } + + ret = ad9361_tracking_control(phy, phy->bbdc_track_en, + phy->rfdc_track_en, phy->quad_track_en); + ad9361_ensm_restore_prev_state(phy); + + return ret; +} + +/** + * Set the RF bandwidth. + * @param phy The AD9361 state structure. + * @param rf_rx_bw The desired RX bandwidth [Hz]. + * @param rf_tx_bw The desired TX bandwidth [Hz]. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_update_rf_bandwidth(struct ad9361_rf_phy *phy, + uint32_t rf_rx_bw, uint32_t rf_tx_bw) +{ + int32_t ret; + + ret = ad9361_tracking_control(phy, false, false, false); + if (ret < 0) + return ret; + + ad9361_ensm_force_state(phy, ENSM_STATE_ALERT); + + ret = __ad9361_update_rf_bandwidth(phy, rf_rx_bw, rf_tx_bw); + if (ret < 0) + return ret; + + phy->current_rx_bw_Hz = rf_rx_bw; + phy->current_tx_bw_Hz = rf_tx_bw; + + if (phy->manual_tx_quad_cal_en == false) { + ret = ad9361_tx_quad_calib(phy, rf_rx_bw / 2, rf_tx_bw / 2, -1); + if (ret < 0) + return ret; + } + + ret = ad9361_tracking_control(phy, phy->bbdc_track_en, + phy->rfdc_track_en, phy->quad_track_en); + if (ret < 0) + return ret; + + ad9361_ensm_restore_prev_state(phy); + + return 0; +} + +/** + * Verify the FIR filter coefficients. + * @param phy The AD9361 state structure. + * @param dest Destination identifier (RX1,2 / TX1,2). + * @param ntaps Number of filter Taps. + * @param coef Pointer to filter coefficients. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_verify_fir_filter_coef(struct ad9361_rf_phy *phy, + enum fir_dest dest, + uint32_t ntaps, short *coef) +{ + struct spi_desc *spi = phy->spi; + uint32_t val, offs = 0, gain = 0, conf, sel, cnt; + int32_t ret = 0; + +#ifndef DEBUG + return 0; +#endif + dev_dbg(&phy->spi->dev, "%s: TAPS %"PRIu32", dest %d", + __func__, ntaps, dest); + + if (dest & FIR_IS_RX) { + gain = ad9361_spi_read(spi, REG_RX_FILTER_GAIN); + offs = REG_RX_FILTER_COEF_ADDR - REG_TX_FILTER_COEF_ADDR; + ad9361_spi_write(spi, REG_RX_FILTER_GAIN, 0); + } + + conf = ad9361_spi_read(spi, REG_TX_FILTER_CONF + offs); + + if ((dest & 3) == 3) { + sel = 1; + cnt = 2; + } else { + sel = (dest & 3); + cnt = 1; + } + + for (; cnt > 0; cnt--, sel++) { + + ad9361_spi_write(spi, REG_TX_FILTER_CONF + offs, + FIR_NUM_TAPS(ntaps / 16 - 1) | + FIR_SELECT(sel) | FIR_START_CLK); + for (val = 0; val < ntaps; val++) { + short tmp; + ad9361_spi_write(spi, REG_TX_FILTER_COEF_ADDR + offs, val); + + tmp = (ad9361_spi_read(spi, REG_TX_FILTER_COEF_READ_DATA_1 + offs) & 0xFF) | + (ad9361_spi_read(spi, REG_TX_FILTER_COEF_READ_DATA_2 + offs) << 8); + + if (tmp != coef[val]) { + dev_err(&phy->spi->dev,"%s%"PRIu32" read verify failed TAP%"PRIu32" %d =! %d", + (dest & FIR_IS_RX) ? "RX" : "TX", sel, + val, tmp, coef[val]); + ret = -EIO; + } + } + } + + if (dest & FIR_IS_RX) { + ad9361_spi_write(spi, REG_RX_FILTER_GAIN, gain); + } + + ad9361_spi_write(spi, REG_TX_FILTER_CONF + offs, conf); + + return ret; +} + +/** + * Load the FIR filter coefficients. + * @param phy The AD9361 state structure. + * @param dest Destination identifier (RX1,2 / TX1,2). + * @param gain_dB Gain option. + * @param ntaps Number of filter Taps. + * @param coef Pointer to filter coefficients. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_load_fir_filter_coef(struct ad9361_rf_phy *phy, + enum fir_dest dest, int32_t gain_dB, + uint32_t ntaps, int16_t *coef) +{ + struct spi_desc *spi = phy->spi; + uint32_t val, offs = 0, fir_conf = 0, fir_enable = 0; + int32_t ret; + + dev_dbg(&phy->spi->dev, "%s: TAPS %"PRIu32", gain %"PRId32", dest %d", + __func__, ntaps, gain_dB, dest); + + if (coef == NULL || !ntaps || ntaps > 128 || ntaps % 16) { + dev_err(&phy->spi->dev, + "%s: Invalid parameters: TAPS %"PRIu32", gain %"PRId32", dest 0x%X", + __func__, ntaps, gain_dB, dest); + + return -EINVAL; + } + + ad9361_ensm_force_state(phy, ENSM_STATE_ALERT); + + if (dest & FIR_IS_RX) { + val = 3 - (gain_dB + 12) / 6; + ad9361_spi_write(spi, REG_RX_FILTER_GAIN, val & 0x3); + offs = REG_RX_FILTER_COEF_ADDR - REG_TX_FILTER_COEF_ADDR; + phy->rx_fir_ntaps = ntaps; + fir_enable = ad9361_spi_readf(phy->spi, + REG_RX_ENABLE_FILTER_CTRL, RX_FIR_ENABLE_DECIMATION(~0)); + ad9361_spi_writef(phy->spi, REG_RX_ENABLE_FILTER_CTRL, + RX_FIR_ENABLE_DECIMATION(~0), + (phy->rx_fir_dec == 4) ? 3 : phy->rx_fir_dec); + } else { + if (gain_dB == -6) + fir_conf = TX_FIR_GAIN_6DB; + phy->tx_fir_ntaps = ntaps; + fir_enable = ad9361_spi_readf(phy->spi, + REG_TX_ENABLE_FILTER_CTRL, TX_FIR_ENABLE_INTERPOLATION(~0)); + ad9361_spi_writef(phy->spi, REG_TX_ENABLE_FILTER_CTRL, + TX_FIR_ENABLE_INTERPOLATION(~0), + (phy->tx_fir_int == 4) ? 3 : phy->tx_fir_int); + } + + val = ntaps / 16 - 1; + + fir_conf |= FIR_NUM_TAPS(val) | FIR_SELECT(dest) | FIR_START_CLK; + + ad9361_spi_write(spi, REG_TX_FILTER_CONF + offs, fir_conf); + + for (val = 0; val < ntaps; val++) { + ad9361_spi_write(spi, REG_TX_FILTER_COEF_ADDR + offs, val); + ad9361_spi_write(spi, REG_TX_FILTER_COEF_WRITE_DATA_1 + offs, + coef[val] & 0xFF); + ad9361_spi_write(spi, REG_TX_FILTER_COEF_WRITE_DATA_2 + offs, + coef[val] >> 8); + ad9361_spi_write(spi, REG_TX_FILTER_CONF + offs, + fir_conf | FIR_WRITE); + ad9361_spi_write(spi, REG_TX_FILTER_COEF_READ_DATA_2 + offs, 0); + ad9361_spi_write(spi, REG_TX_FILTER_COEF_READ_DATA_2 + offs, 0); + } + + ad9361_spi_write(spi, REG_TX_FILTER_CONF + offs, fir_conf); + fir_conf &= ~FIR_START_CLK; + ad9361_spi_write(spi, REG_TX_FILTER_CONF + offs, fir_conf); + + ret = ad9361_verify_fir_filter_coef(phy, dest, ntaps, coef); + + if (dest & FIR_IS_RX) + ad9361_spi_writef(phy->spi, REG_RX_ENABLE_FILTER_CTRL, + RX_FIR_ENABLE_DECIMATION(~0), fir_enable); + else + ad9361_spi_writef(phy->spi, REG_TX_ENABLE_FILTER_CTRL, + TX_FIR_ENABLE_INTERPOLATION(~0), fir_enable); + + ad9361_ensm_restore_prev_state(phy); + + return ret; +} + +/** + * Parse the FIR filter file/buffer. + * @param phy The AD9361 state structure. + * @param data Pointer to buffer. + * @param size Buffer size. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_parse_fir(struct ad9361_rf_phy *phy, + char *data, uint32_t size) +{ + char *line; + int32_t i = 0, ret, txc, rxc; + int32_t tx = -1, tx_gain = 0, tx_int = 0; + int32_t rx = -1, rx_gain = 0, rx_dec = 0; + int32_t rtx = -1, rrx = -1; + int16_t coef_tx[128]; + int16_t coef_rx[128]; + char *ptr = data; + + phy->filt_rx_bw_Hz = 0; + phy->filt_tx_bw_Hz = 0; + phy->filt_valid = false; + + while ((line = strsep(&ptr, "\n"))) { + if (line >= data + size) { + break; + } + + if (line[0] == '#') + continue; + + if (tx < 0) { +#ifdef WIN32 + ret = sscanf_s(line, "TX %d GAIN %d INT %d", + &tx, &tx_gain, &tx_int); +#else + ret = sscanf(line, "TX %"PRId32" GAIN %"PRId32" INT %"PRId32, + &tx, &tx_gain, &tx_int); +#endif + if (ret == 3) + continue; + else + tx = -1; + } + if (rx < 0) { +#ifdef WIN32 + ret = sscanf_s(line, "RX %d GAIN %d DEC %d", + &rx, &rx_gain, &rx_dec); +#else + ret = sscanf(line, "RX %"PRId32" GAIN %"PRId32" DEC %"PRId32, + &rx, &rx_gain, &rx_dec); +#endif + if (ret == 3) + continue; + else + tx = -1; + } + + if (rtx < 0) { +#ifdef WIN32 + ret = sscanf(line, "RTX %lu %lu %lu %lu %lu %lu", +#else + ret = sscanf(line, + "RTX %"PRIu32" %"PRIu32" %"PRIu32" %"PRIu32" %"PRIu32" %"PRIu32, +#endif + &phy->filt_tx_path_clks[0], + &phy->filt_tx_path_clks[1], + &phy->filt_tx_path_clks[2], + &phy->filt_tx_path_clks[3], + &phy->filt_tx_path_clks[4], + &phy->filt_tx_path_clks[5]); + if (ret == 6) { + rtx = 0; + continue; + } else { + rtx = -1; + } + } + + if (rrx < 0) { +#ifdef WIN32 + ret = sscanf(line, "RRX %lu %lu %lu %lu %lu %lu", +#else + ret = sscanf(line, + "RRX %"PRIu32" %"PRIu32" %"PRIu32" %"PRIu32" %"PRIu32" %"PRIu32, +#endif + &phy->filt_rx_path_clks[0], + &phy->filt_rx_path_clks[1], + &phy->filt_rx_path_clks[2], + &phy->filt_rx_path_clks[3], + &phy->filt_rx_path_clks[4], + &phy->filt_rx_path_clks[5]); + if (ret == 6) { + rrx = 0; + continue; + } else { + rrx = -1; + } + } + + if (!phy->filt_rx_bw_Hz) { +#ifdef WIN32 + ret = sscanf(line, "BWRX %d", &phy->filt_rx_bw_Hz); +#else + ret = sscanf(line, "BWRX %"PRId32, &phy->filt_rx_bw_Hz); +#endif + if (ret == 1) + continue; + else + phy->filt_rx_bw_Hz = 0; + } + + if (!phy->filt_tx_bw_Hz) { +#ifdef WIN32 + ret = sscanf(line, "BWTX %d", &phy->filt_tx_bw_Hz); +#else + ret = sscanf(line, "BWTX %"PRId32, &phy->filt_tx_bw_Hz); +#endif + if (ret == 1) + continue; + else + phy->filt_tx_bw_Hz = 0; + } + +#ifdef WIN32 + ret = sscanf_s(line, "%d,%d", &txc, &rxc); +#else + ret = sscanf(line, "%"PRId32",%"PRId32, &txc, &rxc); +#endif + if (ret == 1) { + coef_tx[i] = coef_rx[i] = (int16_t)txc; + i++; + continue; + } else if (ret == 2) { + coef_tx[i] = (int16_t)txc; + coef_rx[i] = (int16_t)rxc; + i++; + continue; + } + } + + switch (tx) { + case FIR_TX1: + case FIR_TX2: + case FIR_TX1_TX2: + phy->tx_fir_int = tx_int; + ret = ad9361_load_fir_filter_coef(phy, (enum fir_dest)tx, tx_gain, i, coef_tx); + break; + default: + ret = -EINVAL; + } + + switch (rx | FIR_IS_RX) { + case FIR_RX1: + case FIR_RX2: + case FIR_RX1_RX2: + phy->rx_fir_dec = rx_dec; + ret = ad9361_load_fir_filter_coef(phy, (enum fir_dest)(rx | FIR_IS_RX), + rx_gain, i, coef_rx); + break; + default: + ret = -EINVAL; + } + + if (ret < 0) + return ret; + + if (!(rrx | rtx)) + phy->filt_valid = true; + + return size; +} + +/** + * Validate FIR filter configuration - on pass enable. + * @param phy The AD9361 state structure. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_validate_enable_fir(struct ad9361_rf_phy *phy) +{ + int32_t ret; + uint32_t rx[6], tx[6]; + uint32_t max, min, valid; + + dev_dbg(dev, "%s: TX FIR EN=%d/TAPS%d/INT%d, RX FIR EN=%d/TAPS%d/DEC%d", + __func__, !phy->bypass_tx_fir, phy->tx_fir_ntaps, phy->tx_fir_int, + !phy->bypass_rx_fir, phy->rx_fir_ntaps, phy->rx_fir_dec); + + if (!phy->bypass_tx_fir) { + if (!(phy->tx_fir_int == 1 || phy->tx_fir_int == 2 || + phy->tx_fir_int == 4)) { + dev_err(dev, + "%s: Invalid: Interpolation %d in filter config", + __func__, phy->tx_fir_int); + return -EINVAL; + } + + + if (phy->tx_fir_int == 1 && phy->tx_fir_ntaps > 64) { + dev_err(dev, + "%s: Invalid: TAPS > 64 and Interpolation = 1", + __func__); + return -EINVAL; + } + } + + if (!phy->bypass_rx_fir) { + if (!(phy->rx_fir_dec == 1 || phy->rx_fir_dec == 2 || + phy->rx_fir_dec == 4)) { + dev_err(dev, + "%s: Invalid: Decimation %d in filter config", + __func__, phy->rx_fir_dec); + + return -EINVAL; + } + } + + if (!phy->filt_valid || phy->bypass_rx_fir || phy->bypass_tx_fir) { + ret = ad9361_calculate_rf_clock_chain(phy, + clk_get_rate(phy, phy->ref_clk_scale[TX_SAMPL_CLK]), + phy->rate_governor, rx, tx); + if (ret < 0) { + min = phy->rate_governor ? 1500000U : 1000000U; + dev_err(dev, + "%s: Calculating filter rates failed %"PRId32 + " using min frequency",__func__, ret); + ret = ad9361_calculate_rf_clock_chain(phy, min, + phy->rate_governor, rx, tx); + if (ret < 0) { + return ret; + } + } + valid = false; + } else { +#ifndef ALTERA_PLATFORM + memcpy(rx, phy->filt_rx_path_clks, sizeof(rx)); + memcpy(tx, phy->filt_tx_path_clks, sizeof(tx)); +#else + int32_t i; + uint32_t num; + num = sizeof(rx) / sizeof(rx[0]); + for (i = 0; i < num; i++) + rx[i] = phy->filt_rx_path_clks[i]; + num = sizeof(tx) / sizeof(rx[0]); + for (i = 0; i < num; i++) + tx[i] = phy->filt_tx_path_clks[i]; +#endif + valid = true; + + } + +#ifdef _DEBUG + dev_dbg(&phy->spi->dev, + "%s:RX %"PRIu32" %"PRIu32" %"PRIu32" %"PRIu32" %"PRIu32" %"PRIu32, + __func__, rx[BBPLL_FREQ], rx[ADC_FREQ], + rx[R2_FREQ], rx[R1_FREQ], + rx[CLKRF_FREQ], rx[RX_SAMPL_FREQ]); + + dev_dbg(&phy->spi->dev, + "%s:TX %"PRIu32" %"PRIu32" %"PRIu32" %"PRIu32" %"PRIu32" %"PRIu32, + __func__, tx[BBPLL_FREQ], tx[ADC_FREQ], + tx[R2_FREQ], tx[R1_FREQ], + tx[CLKRF_FREQ], tx[RX_SAMPL_FREQ]); +#endif + + if (!phy->bypass_tx_fir) { + max = (tx[DAC_FREQ] / tx[TX_SAMPL_FREQ]) * 16; + if (phy->tx_fir_ntaps > max) { + dev_err(dev, + "%s: Invalid: ratio DAC / TX_SAMPL * 16 > TAPS" + "(max %"PRIu32", adc %"PRIu32", tx %"PRIu32")", + __func__, max, tx[DAC_FREQ], tx[TX_SAMPL_FREQ]); + return -EINVAL; + } + } + + if (!phy->bypass_rx_fir) { + max = ((rx[ADC_FREQ] / ((rx[ADC_FREQ] == rx[R2_FREQ]) ? 1 : 2)) / + rx[RX_SAMPL_FREQ]) * 16; + if (phy->rx_fir_ntaps > max) { + dev_err(dev, + "%s: Invalid: ratio ADC/2 / RX_SAMPL * 16 > TAPS (max %"PRIu32")", + __func__, max); + return -EINVAL; + } + } + + ret = ad9361_set_trx_clock_chain(phy, rx, tx); + if (ret < 0) + return ret; + + /* See also: ad9361_set_trx_clock_chain() */ + if (!phy->pdata->dig_interface_tune_fir_disable && + phy->bypass_tx_fir && phy->bypass_rx_fir) + ad9361_dig_tune(phy, 0, RESTORE_DEFAULT); + + return ad9361_update_rf_bandwidth(phy, + valid ? phy->filt_rx_bw_Hz : phy->current_rx_bw_Hz, + valid ? phy->filt_tx_bw_Hz : phy->current_tx_bw_Hz); +} + +/* +* AD9361 Clocks +*/ + +/** +* Set the multiplier and the divider for the selected refclk_scale structure. +* @param priv The selected refclk_scale structure. +* @param mul The multiplier value. +* @param div The divider value. +* @return 0 in case of success, negative error code otherwise. +*/ +static inline int32_t ad9361_set_muldiv(struct refclk_scale *priv, uint32_t mul, + uint32_t div) +{ + priv->mult = mul; + priv->div = div; + return 0; +} + +/** + * Get the clk scaler for the selected refclk_scale structure. + * @param priv The selected refclk_scale structure. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_get_clk_scaler(struct refclk_scale *clk_priv) +{ + struct spi_desc *spi = clk_priv->spi; + uint32_t tmp, tmp1; + + switch (clk_priv->source) { + case BB_REFCLK: + tmp = ad9361_spi_read(spi, REG_CLOCK_CTRL); + tmp &= 0x3; + break; + case RX_REFCLK: + tmp = ad9361_spi_readf(spi, REG_REF_DIVIDE_CONFIG_1, + RX_REF_DIVIDER_MSB); + tmp1 = ad9361_spi_readf(spi, REG_REF_DIVIDE_CONFIG_2, + RX_REF_DIVIDER_LSB); + tmp = (tmp << 1) | tmp1; + break; + case TX_REFCLK: + tmp = ad9361_spi_readf(spi, REG_REF_DIVIDE_CONFIG_2, + TX_REF_DIVIDER(~0)); + break; + case ADC_CLK: + tmp = ad9361_spi_read(spi, REG_BBPLL); + return ad9361_set_muldiv(clk_priv, 1, 1 << (tmp & 0x7)); + case R2_CLK: + tmp = ad9361_spi_readf(spi, REG_RX_ENABLE_FILTER_CTRL, + DEC3_ENABLE_DECIMATION(~0)); + return ad9361_set_muldiv(clk_priv, 1, tmp + 1); + case R1_CLK: + tmp = ad9361_spi_readf(spi, REG_RX_ENABLE_FILTER_CTRL, RHB2_EN); + return ad9361_set_muldiv(clk_priv, 1, tmp + 1); + case CLKRF_CLK: + tmp = ad9361_spi_readf(spi, REG_RX_ENABLE_FILTER_CTRL, RHB1_EN); + return ad9361_set_muldiv(clk_priv, 1, tmp + 1); + case RX_SAMPL_CLK: + tmp = ad9361_spi_readf(spi, REG_RX_ENABLE_FILTER_CTRL, + RX_FIR_ENABLE_DECIMATION(~0)); + + if (!tmp) + tmp = 1; /* bypass filter */ + else + tmp = (1 << (tmp - 1)); + + return ad9361_set_muldiv(clk_priv, 1, tmp); + case DAC_CLK: + tmp = ad9361_spi_readf(spi, REG_BBPLL, BIT(3)); + return ad9361_set_muldiv(clk_priv, 1, tmp + 1); + case T2_CLK: + tmp = ad9361_spi_readf(spi, REG_TX_ENABLE_FILTER_CTRL, + THB3_ENABLE_INTERP(~0)); + return ad9361_set_muldiv(clk_priv, 1, tmp + 1); + case T1_CLK: + tmp = ad9361_spi_readf(spi, REG_TX_ENABLE_FILTER_CTRL, THB2_EN); + return ad9361_set_muldiv(clk_priv, 1, tmp + 1); + case CLKTF_CLK: + tmp = ad9361_spi_readf(spi, REG_TX_ENABLE_FILTER_CTRL, THB1_EN); + return ad9361_set_muldiv(clk_priv, 1, tmp + 1); + case TX_SAMPL_CLK: + tmp = ad9361_spi_readf(spi, REG_TX_ENABLE_FILTER_CTRL, + TX_FIR_ENABLE_INTERPOLATION(~0)); + + if (!tmp) + tmp = 1; /* bypass filter */ + else + tmp = (1 << (tmp - 1)); + + return ad9361_set_muldiv(clk_priv, 1, tmp); + default: + return -EINVAL; + } + + /* REFCLK Scaler */ + switch (tmp) { + case 0: + ad9361_set_muldiv(clk_priv, 1, 1); + break; + case 1: + ad9361_set_muldiv(clk_priv, 1, 2); + break; + case 2: + ad9361_set_muldiv(clk_priv, 1, 4); + break; + case 3: + ad9361_set_muldiv(clk_priv, 2, 1); + break; + default: + return -EINVAL; + + } + + return 0; +} + +/** + * Calculate the REFCLK Scaler for the selected refclk_scale structure. + * Note: REFCLK Scaler values - 00: x1; 01: x½; 10: x¼; 11: x2. + * @param clk_priv The selected refclk_scale structure. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_to_refclk_scaler(struct refclk_scale *clk_priv) +{ + /* REFCLK Scaler */ + switch (((clk_priv->mult & 0xF) << 4) | (clk_priv->div & 0xF)) { + case 0x11: + return 0; + case 0x12: + return 1; + case 0x14: + return 2; + case 0x21: + return 3; + default: + return -EINVAL; + } +}; + +/** + * Set clk scaler for the selected refclk_scale structure. + * @param clk_priv The selected refclk_scale structure. + * @param set Set true, the reference clock frequency will be scaled before + * it enters the BBPLL. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_set_clk_scaler(struct refclk_scale *clk_priv, bool set) +{ + struct spi_desc *spi = clk_priv->spi; + uint32_t tmp; + int32_t ret; + + switch (clk_priv->source) { + case BB_REFCLK: + ret = ad9361_to_refclk_scaler(clk_priv); + if (ret < 0) + return ret; + if (set) + return ad9361_spi_writef(spi, REG_CLOCK_CTRL, + REF_FREQ_SCALER(~0), ret); + break; + + case RX_REFCLK: + ret = ad9361_to_refclk_scaler(clk_priv); + if (ret < 0) + return ret; + if (set) { + tmp = ret; + ret = ad9361_spi_writef(spi, REG_REF_DIVIDE_CONFIG_1, + RX_REF_DIVIDER_MSB, tmp >> 1); + ret |= ad9361_spi_writef(spi, REG_REF_DIVIDE_CONFIG_2, + RX_REF_DIVIDER_LSB, tmp & 1); + return ret; + } + break; + case TX_REFCLK: + ret = ad9361_to_refclk_scaler(clk_priv); + if (ret < 0) + return ret; + if (set) + return ad9361_spi_writef(spi, REG_REF_DIVIDE_CONFIG_2, + TX_REF_DIVIDER(~0), ret); + break; + case ADC_CLK: + tmp = ilog2((uint8_t)clk_priv->div); + if (clk_priv->mult != 1 || tmp > 6 || tmp < 1) + return -EINVAL; + + if (set) + return ad9361_spi_writef(spi, REG_BBPLL, 0x7, tmp); + break; + case R2_CLK: + if (clk_priv->mult != 1 || clk_priv->div > 3 || clk_priv->div < 1) + return -EINVAL; + if (set) + return ad9361_spi_writef(spi, REG_RX_ENABLE_FILTER_CTRL, + DEC3_ENABLE_DECIMATION(~0), + clk_priv->div - 1); + break; + case R1_CLK: + if (clk_priv->mult != 1 || clk_priv->div > 2 || clk_priv->div < 1) + return -EINVAL; + if (set) + return ad9361_spi_writef(spi, REG_RX_ENABLE_FILTER_CTRL, + RHB2_EN, clk_priv->div - 1); + break; + case CLKRF_CLK: + if (clk_priv->mult != 1 || clk_priv->div > 2 || clk_priv->div < 1) + return -EINVAL; + if (set) + return ad9361_spi_writef(spi, REG_RX_ENABLE_FILTER_CTRL, + RHB1_EN, clk_priv->div - 1); + break; + case RX_SAMPL_CLK: + if (clk_priv->mult != 1 || clk_priv->div > 4 || + clk_priv->div < 1 || clk_priv->div == 3) + return -EINVAL; + + if (clk_priv->phy->bypass_rx_fir) + tmp = 0; + else + tmp = ilog2(clk_priv->div) + 1; + + if (set) + return ad9361_spi_writef(spi, REG_RX_ENABLE_FILTER_CTRL, + RX_FIR_ENABLE_DECIMATION(~0), tmp); + break; + case DAC_CLK: + if (clk_priv->mult != 1 || clk_priv->div > 2 || clk_priv->div < 1) + return -EINVAL; + if (set) + return ad9361_spi_writef(spi, REG_BBPLL, + BIT(3), clk_priv->div - 1); + break; + case T2_CLK: + if (clk_priv->mult != 1 || clk_priv->div > 3 || clk_priv->div < 1) + return -EINVAL; + if (set) + return ad9361_spi_writef(spi, REG_TX_ENABLE_FILTER_CTRL, + THB3_ENABLE_INTERP(~0), + clk_priv->div - 1); + break; + case T1_CLK: + if (clk_priv->mult != 1 || clk_priv->div > 2 || clk_priv->div < 1) + return -EINVAL; + if (set) + return ad9361_spi_writef(spi, REG_TX_ENABLE_FILTER_CTRL, + THB2_EN, clk_priv->div - 1); + break; + case CLKTF_CLK: + if (clk_priv->mult != 1 || clk_priv->div > 2 || clk_priv->div < 1) + return -EINVAL; + if (set) + return ad9361_spi_writef(spi, REG_TX_ENABLE_FILTER_CTRL, + THB1_EN, clk_priv->div - 1); + break; + case TX_SAMPL_CLK: + if (clk_priv->mult != 1 || clk_priv->div > 4 || + clk_priv->div < 1 || clk_priv->div == 3) + return -EINVAL; + + if (clk_priv->phy->bypass_tx_fir) + tmp = 0; + else + tmp = ilog2(clk_priv->div) + 1; + + if (set) + return ad9361_spi_writef(spi, REG_TX_ENABLE_FILTER_CTRL, + TX_FIR_ENABLE_INTERPOLATION(~0), tmp); + break; + default: + return -EINVAL; + } + + return 0; +} + +/** + * Recalculate the clock rate. + * @param clk_priv The refclk_scale structure. + * @param parent_rate The parent clock rate. + * @return The clock rate. + */ +uint32_t ad9361_clk_factor_recalc_rate(struct refclk_scale *clk_priv, + uint32_t parent_rate) +{ + uint64_t rate; + + ad9361_get_clk_scaler(clk_priv); + rate = (parent_rate * clk_priv->mult) / clk_priv->div; + + return (uint32_t)rate; +} + +/** + * Calculate the closest possible clock rate that can be set. + * @param clk_priv The refclk_scale structure. + * @param rate The clock rate. + * @param prate The parent clock rate. + * @return The closest possible clock rate that can be set. + */ +int32_t ad9361_clk_factor_round_rate(struct refclk_scale *clk_priv, + uint32_t rate, + uint32_t *prate) +{ + int32_t ret; + + if (rate >= *prate) { + clk_priv->mult = DIV_ROUND_CLOSEST(rate, *prate); + clk_priv->div = 1; + + } else { + clk_priv->div = DIV_ROUND_CLOSEST(*prate, rate); + clk_priv->mult = 1; + if (!clk_priv->div) { + dev_err(&clk_priv->spi->dev, "%s: divide by zero", + __func__); + clk_priv->div = 1; + } + } + + ret = ad9361_set_clk_scaler(clk_priv, false); + if (ret < 0) + return ret; + + return (*prate / clk_priv->div) * clk_priv->mult; +} + +/** + * Set the clock rate. + * @param clk_priv The refclk_scale structure. + * @param rate The clock rate. + * @param parent_rate The parent clock rate. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_clk_factor_set_rate(struct refclk_scale *clk_priv, uint32_t rate, + uint32_t parent_rate) +{ + dev_dbg(&clk_priv->spi->dev, "%s: Rate %"PRIu32" Hz Parent Rate %"PRIu32" Hz", + __func__, rate, parent_rate); + + if (rate >= parent_rate) { + clk_priv->mult = DIV_ROUND_CLOSEST(rate, parent_rate); + clk_priv->div = 1; + } else { + clk_priv->div = DIV_ROUND_CLOSEST(parent_rate, rate); + clk_priv->mult = 1; + if (!clk_priv->div) { + dev_err(&clk_priv->spi->dev, "%s: divide by zero", + __func__); + clk_priv->div = 1; + } + } + + return ad9361_set_clk_scaler(clk_priv, true); +} + +/* + * BBPLL + */ +/** + * Recalculate the clock rate. + * @param clk_priv The refclk_scale structure. + * @param parent_rate The parent clock rate. + * @return The clock rate. + */ +uint32_t ad9361_bbpll_recalc_rate(struct refclk_scale *clk_priv, + uint32_t parent_rate) +{ + uint64_t rate; + uint32_t fract, integer; + uint8_t buf[4]; + + ad9361_spi_readm(clk_priv->spi, REG_INTEGER_BB_FREQ_WORD, &buf[0], + REG_INTEGER_BB_FREQ_WORD - REG_FRACT_BB_FREQ_WORD_1 + 1); + + fract = (buf[3] << 16) | (buf[2] << 8) | buf[1]; + integer = buf[0]; + + rate = ((uint64_t)parent_rate * fract); + do_div(&rate, BBPLL_MODULUS); + rate += (uint64_t)parent_rate * integer; + + return (uint32_t)rate; +} + +/** + * Calculate the closest possible clock rate that can be set. + * @param clk_priv The refclk_scale structure. + * @param rate The clock rate. + * @param prate The parent clock rate. + * @return The closest possible clock rate that can be set. + */ +int32_t ad9361_bbpll_round_rate(struct refclk_scale *clk_priv, uint32_t rate, + uint32_t *prate) +{ + uint64_t tmp; + uint32_t fract, integer; + uint64_t temp; + + if (clk_priv) { + // Unused variable - fix compiler warning + } + + if (rate > MAX_BBPLL_FREQ) + return MAX_BBPLL_FREQ; + + if (rate < MIN_BBPLL_FREQ) + return MIN_BBPLL_FREQ; + + temp = rate; + tmp = do_div(&temp, *prate); + rate = temp; + tmp = tmp * BBPLL_MODULUS + (*prate >> 1); + do_div(&tmp, *prate); + + integer = rate; + fract = tmp; + + tmp = *prate * (uint64_t)fract; + do_div(&tmp, BBPLL_MODULUS); + tmp += *prate * integer; + + return tmp; +} + +/** + * Set the clock rate. + * @param clk_priv The refclk_scale structure. + * @param rate The clock rate. + * @param parent_rate The parent clock rate. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_bbpll_set_rate(struct refclk_scale *clk_priv, uint32_t rate, + uint32_t parent_rate) +{ + struct spi_desc *spi = clk_priv->spi; + uint64_t tmp; + uint32_t fract, integer; + int32_t icp_val; + uint8_t lf_defaults[3] = { 0x35, 0x5B, 0xE8 }; + uint64_t temp; + + dev_dbg(&spi->dev, "%s: Rate %"PRIu32" Hz Parent Rate %"PRIu32" Hz", + __func__, rate, parent_rate); + + /* + * Setup Loop Filter and CP Current + * Scale is 150uA @ (1280MHz BBPLL, 40MHz REFCLK) + */ + tmp = (rate >> 7) * 150ULL; + do_div(&tmp, (parent_rate >> 7) * 32UL); + + /* 25uA/LSB, Offset 25uA */ + icp_val = DIV_ROUND_CLOSEST((uint32_t)tmp, 25U) - 1; + + icp_val = clamp(icp_val, 1, 64); + + ad9361_spi_write(spi, REG_CP_CURRENT, icp_val); + ad9361_spi_writem(spi, REG_LOOP_FILTER_3, lf_defaults, + ARRAY_SIZE(lf_defaults)); + + /* Allow calibration to occur and set cal count to 1024 for max accuracy */ + ad9361_spi_write(spi, REG_VCO_CTRL, + FREQ_CAL_ENABLE | FREQ_CAL_COUNT_LENGTH(3)); + /* Set calibration clock to REFCLK/4 for more accuracy */ + ad9361_spi_write(spi, REG_SDM_CTRL, 0x10); + + /* Calculate and set BBPLL frequency word */ + temp = rate; + tmp = do_div(&temp, parent_rate); + rate = temp; + tmp = tmp *(uint64_t)BBPLL_MODULUS + (parent_rate >> 1); + do_div(&tmp, parent_rate); + + integer = rate; + fract = tmp; + + ad9361_spi_write(spi, REG_INTEGER_BB_FREQ_WORD, integer); + ad9361_spi_write(spi, REG_FRACT_BB_FREQ_WORD_3, fract); + ad9361_spi_write(spi, REG_FRACT_BB_FREQ_WORD_2, fract >> 8); + ad9361_spi_write(spi, REG_FRACT_BB_FREQ_WORD_1, fract >> 16); + + ad9361_spi_write(spi, REG_SDM_CTRL_1, + INIT_BB_FO_CAL | BBPLL_RESET_BAR); /* Start BBPLL Calibration */ + ad9361_spi_write(spi, REG_SDM_CTRL_1, + BBPLL_RESET_BAR); /* Clear BBPLL start calibration bit */ + + ad9361_spi_write(spi, REG_VCO_PROGRAM_1, + 0x86); /* Increase BBPLL KV and phase margin */ + ad9361_spi_write(spi, REG_VCO_PROGRAM_2, + 0x01); /* Increase BBPLL KV and phase margin */ + ad9361_spi_write(spi, REG_VCO_PROGRAM_2, + 0x05); /* Increase BBPLL KV and phase margin */ + + return ad9361_check_cal_done(clk_priv->phy, REG_CH_1_OVERFLOW, + BBPLL_LOCK, 1); +} + +/* + * RFPLL + */ + +/** + * Calculate the RFPLL frequency. + * @param parent_rate The parent clock rate. + * @param integer The integer value. + * @param fract The fractional value. + * @param vco_div The VCO divider. + * @return The RFPLL frequency. + */ +static uint64_t ad9361_calc_rfpll_int_freq(uint64_t parent_rate, + uint64_t integer, + uint64_t fract, uint32_t vco_div) +{ + uint64_t rate; + + rate = parent_rate * fract; + do_div(&rate, RFPLL_MODULUS); + rate += parent_rate * integer; + + return rate >> (vco_div + 1); +} + +/** + * Calculate the RFPLL dividers. + * @param phy The AD9361 state structure. + * @param clk_priv The refclk_scale structure. + * @param freq The RFPLL frequency. + * @param parent_rate The parent clock rate. + * @param integer The integer value. + * @param fract The fractional value. + * @param vco_div The VCO divider. + * @param vco_freq The VCO frequency. + * @return The RFPLL frequency. + */ +static int32_t ad9361_calc_rfpll_int_divder(struct ad9361_rf_phy *phy, + struct refclk_scale *clk_priv, uint64_t freq, + uint64_t parent_rate, uint32_t *integer, + uint32_t *fract, int32_t *vco_div, uint64_t *vco_freq) +{ + uint64_t tmp; + int32_t div, ret; + + ret = ad9361_validate_rfpll(phy, clk_priv->source == TX_RFPLL_INT, freq); + if (ret) + return ret; + + div = -1; + + while (freq <= MIN_VCO_FREQ_HZ) { + freq <<= 1; + div++; + } + + *vco_div = div; + *vco_freq = freq; + tmp = do_div(&freq, parent_rate); + tmp = tmp * RFPLL_MODULUS + (parent_rate >> 1); + do_div(&tmp, parent_rate); + *integer = freq; + *fract = tmp; + + return 0; +} + +/** + * Recalculate the clock rate. + * @param clk_priv The refclk_scale structure. + * @param parent_rate The parent clock rate. + * @return The clock rate. + */ +uint32_t ad9361_rfpll_int_recalc_rate(struct refclk_scale *clk_priv, + uint32_t parent_rate) +{ + struct ad9361_rf_phy *phy = clk_priv->phy; + uint32_t fract, integer; + uint8_t buf[5]; + uint32_t reg, div_mask, vco_div, profile; + + dev_dbg(&clk_priv->spi->dev, "%s: Parent Rate %"PRIu32" Hz", + __func__, parent_rate); + + switch (clk_priv->source) { + case RX_RFPLL_INT: + reg = REG_RX_FRACT_BYTE_2; + div_mask = RX_VCO_DIVIDER(~0); + profile = phy->fastlock.current_profile[0]; + break; + case TX_RFPLL_INT: + reg = REG_TX_FRACT_BYTE_2; + div_mask = TX_VCO_DIVIDER(~0); + profile = phy->fastlock.current_profile[1]; + break; + default: + return -EINVAL; + } + + if (profile) { + bool tx = clk_priv->source == TX_RFPLL_INT; + profile = profile - 1; + + buf[0] = ad9361_fastlock_readval(phy->spi, tx, profile, 4); + buf[1] = ad9361_fastlock_readval(phy->spi, tx, profile, 3); + buf[2] = ad9361_fastlock_readval(phy->spi, tx, profile, 2); + buf[3] = ad9361_fastlock_readval(phy->spi, tx, profile, 1); + buf[4] = ad9361_fastlock_readval(phy->spi, tx, profile, 0); + vco_div = ad9361_fastlock_readval(phy->spi, tx, profile, 12) & 0xF; + + } else { + ad9361_spi_readm(clk_priv->spi, reg, &buf[0], ARRAY_SIZE(buf)); + vco_div = ad9361_spi_readf(clk_priv->spi, REG_RFPLL_DIVIDERS, div_mask); + } + + fract = (SYNTH_FRACT_WORD(buf[0]) << 16) | (buf[1] << 8) | buf[2]; + integer = (SYNTH_INTEGER_WORD(buf[3]) << 8) | buf[4]; + + return ad9361_to_clk(ad9361_calc_rfpll_int_freq(parent_rate, integer, + fract, vco_div)); +} + +/** + * Calculate the closest possible clock rate that can be set. + * @param clk_priv The refclk_scale structure. + * @param rate The clock rate. + * @param prate The parent clock rate. + * @return The closest possible clock rate that can be set. + */ +int32_t ad9361_rfpll_int_round_rate(struct refclk_scale *clk_priv, + uint32_t rate, + uint32_t *prate) +{ + dev_dbg(&clk_priv->spi->dev, "%s: Rate %"PRIu32" Hz", __func__, rate); + + if (prate) { + // Unused variable - fix compiler warning + } + + if (clk_priv) { + // Unused variable - fix compiler warning + } + + if (ad9361_from_clk(rate) > MAX_CARRIER_FREQ_HZ || + ad9361_from_clk(rate) < ((clk_priv->source == TX_RFPLL_INT) ? + MIN_TX_CARRIER_FREQ_HZ : MIN_RX_CARRIER_FREQ_HZ)) + return -EINVAL; + + return rate; +} + +/** + * Set the clock rate. + * @param clk_priv The refclk_scale structure. + * @param rate The clock rate. + * @param parent_rate The parent clock rate. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_rfpll_int_set_rate(struct refclk_scale *clk_priv, uint32_t rate, + uint32_t parent_rate) +{ + struct ad9361_rf_phy *phy = clk_priv->phy; + uint64_t vco = 0; + uint8_t buf[5]; + uint32_t reg, div_mask, lock_reg, fract = 0, integer = 0; + int32_t vco_div, ret, fixup_other; + + dev_dbg(&clk_priv->spi->dev, + "%s: %s Rate %"PRIu32" Hz Parent Rate %"PRIu32" Hz", + __func__, clk_priv->source == TX_RFPLL_INT ? "TX" : "RX", + rate, parent_rate); + + ad9361_fastlock_prepare(phy, clk_priv->source == TX_RFPLL_INT, 0, false); + + ret = ad9361_calc_rfpll_int_divder(phy, clk_priv, ad9361_from_clk(rate), + parent_rate, + &integer, &fract, &vco_div, &vco); + if (ret < 0) + return ret; + + switch (clk_priv->source) { + case RX_RFPLL_INT: + reg = REG_RX_FRACT_BYTE_2; + lock_reg = REG_RX_CP_OVERRANGE_VCO_LOCK; + div_mask = RX_VCO_DIVIDER(~0); + phy->cached_rx_rfpll_div = vco_div; + phy->current_rx_lo_freq = rate; + break; + case TX_RFPLL_INT: + reg = REG_TX_FRACT_BYTE_2; + lock_reg = REG_TX_CP_OVERRANGE_VCO_LOCK; + div_mask = TX_VCO_DIVIDER(~0); + phy->cached_tx_rfpll_div = vco_div; + phy->current_tx_lo_freq = rate; + break; + default: + return -EINVAL; + + } + + /* Option to skip VCO cal in TDD mode when moving from TX/RX to Alert */ + if (phy->pdata->tdd_skip_vco_cal) + ad9361_trx_vco_cal_control(phy, clk_priv->source == TX_RFPLL_INT, + true); + + do { + fixup_other = 0; + ad9361_rfpll_vco_init(phy, div_mask == TX_VCO_DIVIDER(~0), + vco, parent_rate); + + buf[0] = SYNTH_FRACT_WORD(fract >> 16); + buf[1] = fract >> 8; + buf[2] = fract & 0xFF; + buf[3] = SYNTH_INTEGER_WORD(integer >> 8) | + (~SYNTH_INTEGER_WORD(~0) & + ad9361_spi_read(clk_priv->spi, reg - 3)); + buf[4] = integer & 0xFF; + + ad9361_spi_writem(clk_priv->spi, reg, buf, 5); + ad9361_spi_writef(clk_priv->spi, REG_RFPLL_DIVIDERS, div_mask, vco_div); + + ret = ad9361_check_cal_done(phy, lock_reg, VCO_LOCK, 1); + + /* In FDD mode with RX LO == TX LO frequency we use TDD tables to + * reduce VCO pulling + */ + + if (((phy->pdata->fdd && !phy->pdata->fdd_independent_mode) && + (phy->current_tx_lo_freq == phy->current_rx_lo_freq) && + (phy->current_tx_use_tdd_table != phy->current_rx_use_tdd_table)) || + ((phy->pdata->fdd && !phy->pdata->fdd_independent_mode) && + (phy->current_tx_lo_freq != phy->current_rx_lo_freq) && + (phy->current_tx_use_tdd_table || phy->current_rx_use_tdd_table))) { + unsigned long _rate; + + switch (clk_priv->source) { + case RX_RFPLL_INT: + reg = REG_TX_FRACT_BYTE_2; + lock_reg = REG_TX_CP_OVERRANGE_VCO_LOCK; + div_mask = TX_VCO_DIVIDER(~0); + _rate = phy->current_tx_lo_freq; + break; + case TX_RFPLL_INT: + reg = REG_RX_FRACT_BYTE_2; + lock_reg = REG_RX_CP_OVERRANGE_VCO_LOCK; + div_mask = RX_VCO_DIVIDER(~0); + _rate = phy->current_rx_lo_freq; + break; + default: + return -EINVAL; + + } + + if (phy->current_tx_lo_freq != phy->current_rx_lo_freq) { + ad9361_calc_rfpll_int_divder(phy, clk_priv, ad9361_from_clk(_rate), + parent_rate, &integer, &fract, &vco_div, &vco); + + ad9361_fastlock_prepare(phy, clk_priv->source == RX_RFPLL_INT, 0, false); + } + + fixup_other = 1; + } + + } while (fixup_other); + + if (phy->pdata->tdd_skip_vco_cal) + ad9361_trx_vco_cal_control(phy, clk_priv->source == TX_RFPLL_INT, + false); + + return ret; +} + +/** + * Recalculate the clock rate. + * @param clk_priv The refclk_scale structure. + * @return The clock rate. + */ +uint32_t ad9361_rfpll_dummy_recalc_rate(struct refclk_scale *clk_priv) +{ + struct ad9361_rf_phy *phy = clk_priv->phy; + + return phy->clks[clk_priv->source]->rate; +} + +/** + * Set the clock rate. + * @param clk_priv The refclk_scale structure. + * @param rate The clock rate. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_rfpll_dummy_set_rate(struct refclk_scale *clk_priv, + uint32_t rate) +{ + struct ad9361_rf_phy *phy = clk_priv->phy; + + phy->clks[clk_priv->source]->rate = rate; + + return 0; +} + +/** + * Recalculate the clock rate. + * @param clk_priv The refclk_scale structure. + * @return The clock rate. + */ +uint32_t ad9361_rfpll_recalc_rate(struct refclk_scale *clk_priv) +{ + struct ad9361_rf_phy *phy = clk_priv->phy; + uint32_t rate; + + switch (clk_priv->source) { + case RX_RFPLL: + if (phy->pdata->use_ext_rx_lo) { + if (phy->ad9361_rfpll_ext_recalc_rate) + rate = phy->ad9361_rfpll_ext_recalc_rate(clk_priv); + else + rate = ad9361_rfpll_dummy_recalc_rate(phy->ref_clk_scale[RX_RFPLL_DUMMY]); + } else { + rate = ad9361_rfpll_int_recalc_rate(phy->ref_clk_scale[RX_RFPLL_INT], + phy->clks[RX_REFCLK]->rate); + } + break; + case TX_RFPLL: + if (phy->pdata->use_ext_tx_lo) { + if (phy->ad9361_rfpll_ext_recalc_rate) + rate = phy->ad9361_rfpll_ext_recalc_rate(clk_priv); + else + rate = ad9361_rfpll_dummy_recalc_rate(phy->ref_clk_scale[TX_RFPLL_DUMMY]); + } else { + rate = ad9361_rfpll_int_recalc_rate(phy->ref_clk_scale[TX_RFPLL_INT], + phy->clks[TX_REFCLK]->rate); + } + break; + default: + rate = 0; + break; + } + + return rate; +} + +/** + * Calculate the closest possible clock rate that can be set. + * @param clk_priv The refclk_scale structure. + * @param rate The clock rate. + * @return The closest possible clock rate that can be set. + */ +int32_t ad9361_rfpll_round_rate(struct refclk_scale *clk_priv, uint32_t rate) +{ + struct ad9361_rf_phy *phy = clk_priv->phy; + int32_t round_rate; + + switch (clk_priv->source) { + case RX_RFPLL: + if (phy->pdata->use_ext_rx_lo) { + if (phy->ad9361_rfpll_ext_round_rate) + round_rate = phy->ad9361_rfpll_ext_round_rate(clk_priv, rate); + else + round_rate = rate; + } else { + round_rate = ad9361_rfpll_int_round_rate(phy->ref_clk_scale[RX_RFPLL_INT], rate, + &phy->clks[phy->ref_clk_scale[RX_RFPLL_INT]->parent_source]->rate); + } + break; + case TX_RFPLL: + if (phy->pdata->use_ext_tx_lo) { + if (phy->ad9361_rfpll_ext_round_rate) + round_rate = phy->ad9361_rfpll_ext_round_rate(clk_priv, rate); + else + round_rate = rate; + } else { + round_rate = ad9361_rfpll_int_round_rate(phy->ref_clk_scale[TX_RFPLL_INT], rate, + &phy->clks[phy->ref_clk_scale[TX_RFPLL_INT]->parent_source]->rate); + } + break; + default: + round_rate = 0; + break; + } + + return round_rate; +} + +/** + * Set the clock rate. + * @param clk_priv The refclk_scale structure. + * @param rate The clock rate. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_rfpll_set_rate(struct refclk_scale *clk_priv, uint32_t rate) +{ + struct ad9361_rf_phy *phy = clk_priv->phy; + int32_t ret; + + switch (clk_priv->source) { + case RX_RFPLL: + if (phy->pdata->use_ext_rx_lo) { + if (phy->ad9361_rfpll_ext_set_rate) + phy->ad9361_rfpll_ext_set_rate(clk_priv, rate); + else + ad9361_rfpll_dummy_set_rate(phy->ref_clk_scale[RX_RFPLL_DUMMY], rate); + } else { + ad9361_rfpll_int_set_rate(phy->ref_clk_scale[RX_RFPLL_INT], rate, + phy->clks[phy->ref_clk_scale[RX_RFPLL_INT]->parent_source]->rate); + } + /* Load Gain Table */ + ret = ad9361_load_gt(phy, ad9361_from_clk(rate), GT_RX1 + GT_RX2); + if (ret < 0) + return ret; + break; + case TX_RFPLL: + if (phy->pdata->use_ext_tx_lo) { + if (phy->ad9361_rfpll_ext_set_rate) + phy->ad9361_rfpll_ext_set_rate(clk_priv, rate); + else + ad9361_rfpll_dummy_set_rate(phy->ref_clk_scale[TX_RFPLL_DUMMY], rate); + } else { + ad9361_rfpll_int_set_rate(phy->ref_clk_scale[TX_RFPLL_INT], rate, + phy->clks[phy->ref_clk_scale[TX_RFPLL_INT]->parent_source]->rate); + } + /* For RX LO we typically have the tracking option enabled + * so for now do nothing here. + */ + if (phy->auto_cal_en && !phy->pdata->use_ext_tx_lo) + if ((diff_abs(phy->last_tx_quad_cal_freq, ad9361_from_clk(rate))) > + phy->cal_threshold_freq) { + ret = ad9361_do_calib_run(phy, TX_QUAD_CAL, -1); + if (ret < 0) + dev_err(&phy->spi->dev, + "%s: TX QUAD cal failed", __func__); + phy->last_tx_quad_cal_freq = ad9361_from_clk(rate); + } + break; + default: + break; + } + + return 0; +} + +/** + * Set clock mux parent. + * @param clk_priv The refclk_scale structure. + * @param index Index - Enable (1), disable (0) ext lo. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_clk_mux_set_parent(struct refclk_scale *clk_priv, uint8_t index) +{ + struct ad9361_rf_phy *phy = clk_priv->phy; + int32_t ret; + + dev_dbg(&clk_priv->spi->dev, "%s: index %d", __func__, index); + + ad9361_ensm_force_state(phy, ENSM_STATE_ALERT); + + ret = ad9361_trx_ext_lo_control(phy, clk_priv->source == TX_RFPLL, index == 1); + if (ret >= 0) + clk_priv->mult = index; + + ad9361_ensm_restore_prev_state(phy); + + return ret; +} + +/** + * Register and initialize a new clock. + * @param phy The AD9361 state structure. + * @param name The name of the new clock. + * @param parent_name The name of the parent clock. + * @param flags The flags. + * @param source The source of the new clock. + * @param parent_source The source of the parent clock. + * @return A struct clk for the new clock or a negative error code. + */ +static struct clk *ad9361_clk_register(struct ad9361_rf_phy *phy, + const char *name, + const char *parent_name, uint32_t flags, + uint32_t source, uint32_t parent_source) +{ + struct refclk_scale *clk_priv; + struct clk *clk; + + if (name) { + // Unused variable - fix compiler warning + } + if (parent_name) { + // Unused variable - fix compiler warning + } + if (flags) { + // Unused variable - fix compiler warning + } + + clk_priv = (struct refclk_scale *)malloc(sizeof(*clk_priv)); + if (!clk_priv) { + dev_err(&phy->spi->dev, + "ad9361_clk_register: could not allocate fixed factor clk"); + return (struct clk *)ERR_PTR(-ENOMEM); + } + + /* struct refclk_scale assignments */ + clk_priv->source = (enum ad9361_clocks)source; + clk_priv->parent_source = (enum ad9361_clocks)parent_source; + clk_priv->spi = phy->spi; + clk_priv->phy = phy; + + phy->ref_clk_scale[source] = clk_priv; + + clk = (struct clk *)malloc(sizeof(*clk)); + if (!clk) { + free(clk_priv); + return (struct clk *)ERR_PTR(-ENOMEM); + } + + switch (source) { + case TX_REFCLK: + clk->rate = ad9361_clk_factor_recalc_rate(clk_priv, phy->clk_refin->rate); + break; + case RX_REFCLK: + clk->rate = ad9361_clk_factor_recalc_rate(clk_priv, phy->clk_refin->rate); + break; + case BB_REFCLK: + clk->rate = ad9361_clk_factor_recalc_rate(clk_priv, phy->clk_refin->rate); + break; + case BBPLL_CLK: + clk->rate = ad9361_bbpll_recalc_rate(clk_priv, phy->clks[BB_REFCLK]->rate); + break; + case ADC_CLK: + clk->rate = ad9361_clk_factor_recalc_rate(clk_priv, phy->clks[BBPLL_CLK]->rate); + break; + case R2_CLK: + clk->rate = ad9361_clk_factor_recalc_rate(clk_priv, phy->clks[ADC_CLK]->rate); + break; + case R1_CLK: + clk->rate = ad9361_clk_factor_recalc_rate(clk_priv, phy->clks[R2_CLK]->rate); + break; + case CLKRF_CLK: + clk->rate = ad9361_clk_factor_recalc_rate(clk_priv, phy->clks[R1_CLK]->rate); + break; + case RX_SAMPL_CLK: + clk->rate = ad9361_clk_factor_recalc_rate(clk_priv, phy->clks[CLKRF_CLK]->rate); + break; + case DAC_CLK: + clk->rate = ad9361_clk_factor_recalc_rate(clk_priv, phy->clks[ADC_CLK]->rate); + break; + case T2_CLK: + clk->rate = ad9361_clk_factor_recalc_rate(clk_priv, phy->clks[DAC_CLK]->rate); + break; + case T1_CLK: + clk->rate = ad9361_clk_factor_recalc_rate(clk_priv, phy->clks[T2_CLK]->rate); + break; + case CLKTF_CLK: + clk->rate = ad9361_clk_factor_recalc_rate(clk_priv, phy->clks[T1_CLK]->rate); + break; + case TX_SAMPL_CLK: + clk->rate = ad9361_clk_factor_recalc_rate(clk_priv, phy->clks[CLKTF_CLK]->rate); + break; + case RX_RFPLL_INT: + clk->rate = ad9361_rfpll_int_recalc_rate(clk_priv, phy->clks[RX_REFCLK]->rate); + break; + case TX_RFPLL_INT: + clk->rate = ad9361_rfpll_int_recalc_rate(clk_priv, phy->clks[TX_REFCLK]->rate); + break; + case RX_RFPLL_DUMMY: + clk->rate = phy->pdata->rx_synth_freq; + break; + case TX_RFPLL_DUMMY: + clk->rate = phy->pdata->tx_synth_freq; + break; + case RX_RFPLL: + clk->rate = ad9361_rfpll_recalc_rate(clk_priv); + break; + case TX_RFPLL: + clk->rate = ad9361_rfpll_recalc_rate(clk_priv); + } + + return clk; +} + +/** + * Register and initialize all the system clocks. + * @param phy The AD9361 state structure. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_register_clocks(struct ad9361_rf_phy *phy) +{ + uint32_t flags = CLK_GET_RATE_NOCACHE; + + /* Scaled Reference Clocks */ + phy->clks[TX_REFCLK] = ad9361_clk_register(phy, + "tx_refclk", "ad9361_ext_refclk", + flags | CLK_IGNORE_UNUSED, + TX_REFCLK, EXT_REF_CLK); + + phy->clks[RX_REFCLK] = ad9361_clk_register(phy, + "rx_refclk", "ad9361_ext_refclk", + flags | CLK_IGNORE_UNUSED, + RX_REFCLK, EXT_REF_CLK); + + phy->clks[BB_REFCLK] = ad9361_clk_register(phy, + "bb_refclk", "ad9361_ext_refclk", + flags | CLK_IGNORE_UNUSED, + BB_REFCLK, EXT_REF_CLK); + + /* Base Band PLL Clock */ + phy->clks[BBPLL_CLK] = ad9361_clk_register(phy, + "bbpll_clk", "bb_refclk", + flags | CLK_IGNORE_UNUSED, + BBPLL_CLK, BB_REFCLK); + + phy->clks[ADC_CLK] = ad9361_clk_register(phy, + "adc_clk", "bbpll_clk", + flags | CLK_IGNORE_UNUSED, + ADC_CLK, BBPLL_CLK); + + phy->clks[R2_CLK] = ad9361_clk_register(phy, + "r2_clk", "adc_clk", + flags | CLK_IGNORE_UNUSED, + R2_CLK, ADC_CLK); + + phy->clks[R1_CLK] = ad9361_clk_register(phy, + "r1_clk", "r2_clk", + flags | CLK_IGNORE_UNUSED, + R1_CLK, R2_CLK); + + phy->clks[CLKRF_CLK] = ad9361_clk_register(phy, + "clkrf_clk", "r1_clk", + flags | CLK_IGNORE_UNUSED, + CLKRF_CLK, R1_CLK); + + phy->clks[RX_SAMPL_CLK] = ad9361_clk_register(phy, + "rx_sampl_clk", "clkrf_clk", + flags | CLK_IGNORE_UNUSED, + RX_SAMPL_CLK, CLKRF_CLK); + + + phy->clks[DAC_CLK] = ad9361_clk_register(phy, + "dac_clk", "adc_clk", + flags | CLK_IGNORE_UNUSED, + DAC_CLK, ADC_CLK); + + phy->clks[T2_CLK] = ad9361_clk_register(phy, + "t2_clk", "dac_clk", + flags | CLK_IGNORE_UNUSED, + T2_CLK, DAC_CLK); + + phy->clks[T1_CLK] = ad9361_clk_register(phy, + "t1_clk", "t2_clk", + flags | CLK_IGNORE_UNUSED, + T1_CLK, T2_CLK); + + phy->clks[CLKTF_CLK] = ad9361_clk_register(phy, + "clktf_clk", "t1_clk", + flags | CLK_IGNORE_UNUSED, + CLKTF_CLK, T1_CLK); + + phy->clks[TX_SAMPL_CLK] = ad9361_clk_register(phy, + "tx_sampl_clk", "clktf_clk", + flags | CLK_IGNORE_UNUSED, + TX_SAMPL_CLK, CLKTF_CLK); + + phy->clks[RX_RFPLL_INT] = ad9361_clk_register(phy, + "rx_rfpll", "rx_refclk", + flags | CLK_IGNORE_UNUSED, + RX_RFPLL_INT, RX_REFCLK); + + phy->clks[TX_RFPLL_INT] = ad9361_clk_register(phy, + "tx_rfpll", "tx_refclk", + flags | CLK_IGNORE_UNUSED, + TX_RFPLL_INT, TX_REFCLK); + + phy->clks[RX_RFPLL_DUMMY] = ad9361_clk_register(phy, + "rx_rfpll_dummy", NULL, + flags | CLK_IGNORE_UNUSED, + RX_RFPLL_DUMMY, 0); + + phy->clks[TX_RFPLL_DUMMY] = ad9361_clk_register(phy, + "tx_rfpll_dummy", NULL, + flags | CLK_IGNORE_UNUSED, + TX_RFPLL_DUMMY, 0); + + phy->clks[RX_RFPLL] = ad9361_clk_register(phy, + "rx_rfpll", NULL, + flags | CLK_IGNORE_UNUSED, + RX_RFPLL, 0); + + phy->clks[TX_RFPLL] = ad9361_clk_register(phy, + "tx_rfpll", NULL, + flags | CLK_IGNORE_UNUSED, + TX_RFPLL, 0); + + return 0; +} + +/** + * Unregister all the system clocks. + * @param phy The AD9361 state structure. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_unregister_clocks(struct ad9361_rf_phy *phy) +{ + int32_t i; + + for (i = 0; i < NUM_AD9361_CLKS; i++) { + free(phy->clks[i]); + free(phy->ref_clk_scale[i]); + } + + return 0; +} + +/** + * Perform an RSSI gain step calibration. + * Note: Before running the function, provide a single tone within the channel + * bandwidth and monitor the received data. Adjust the tone amplitude until + * the received data is within a few dB of full scale but not overloading. + * @param phy The AD9361 state structure. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_rssi_gain_step_calib(struct ad9361_rf_phy *phy) +{ + uint32_t lna_error[4]; + uint32_t mixer_error[15]; + uint64_t lo_freq_hz; + uint8_t lo_index; + uint8_t i; + + lo_freq_hz = ad9361_from_clk(clk_get_rate(phy, + phy->ref_clk_scale[RX_RFPLL])); + if (lo_freq_hz < 1300000000ULL) + lo_index = 0; + else if (lo_freq_hz < 3300000000ULL) + lo_index = 1; + else if (lo_freq_hz < 4100000000ULL) + lo_index = 2; + else + lo_index = 3; + + /* Put the AD9361 into the Alert state. */ + ad9361_ensm_force_state(phy, ENSM_STATE_ALERT); + + /* Program the directly-addressable register values. */ + ad9361_spi_write(phy->spi, REG_MAX_MIXER_CALIBRATION_GAIN_INDEX, + MAX_MIXER_CALIBRATION_GAIN_INDEX(0x0F)); + ad9361_spi_write(phy->spi, REG_MEASURE_DURATION, + GAIN_CAL_MEAS_DURATION(0x0E)); + ad9361_spi_write(phy->spi, REG_SETTLE_TIME, + SETTLE_TIME(0x3F)); + ad9361_spi_write(phy->spi, REG_RSSI_CONFIG, + RSSI_MODE_SELECT(0x3) | DEFAULT_RSSI_MEAS_MODE); + ad9361_spi_write(phy->spi, REG_MEASURE_DURATION_01, + MEASUREMENT_DURATION_0(0x0E)); + ad9361_spi_write(phy->spi, REG_LNA_GAIN, + gain_step_calib_reg_val[lo_index][0]); + + /* Program the LNA gain step words into the internal table. */ + ad9361_spi_write(phy->spi, REG_CONFIG, + CALIB_TABLE_SELECT(0x3) | START_CALIB_TABLE_CLOCK); + for(i = 0; i < 4; i++) { + ad9361_spi_write(phy->spi, REG_WORD_ADDRESS, i); + ad9361_spi_write(phy->spi, REG_GAIN_DIFF_WORDERROR_WRITE, + gain_step_calib_reg_val[lo_index][i+1]); + ad9361_spi_write(phy->spi, REG_CONFIG, + CALIB_TABLE_SELECT(0x3) | WRITE_LNA_GAIN_DIFF | START_CALIB_TABLE_CLOCK); + udelay(3); //Wait for data to fully write to internal table + } + + ad9361_spi_write(phy->spi, REG_CONFIG, START_CALIB_TABLE_CLOCK); + ad9361_spi_write(phy->spi, REG_CONFIG, 0x00); + + /* Run and wait until the calibration completes. */ + ad9361_run_calibration(phy, RX_GAIN_STEP_CAL); + + /* Read the LNA and Mixer error terms into nonvolatile memory. */ + ad9361_spi_write(phy->spi, REG_CONFIG, CALIB_TABLE_SELECT(0x1) | READ_SELECT); + for(i = 0; i < 4; i++) { + ad9361_spi_write(phy->spi, REG_WORD_ADDRESS, i); + lna_error[i] = ad9361_spi_read(phy->spi, REG_GAIN_ERROR_READ); + } + ad9361_spi_write(phy->spi, REG_CONFIG, CALIB_TABLE_SELECT(0x1)); + for(i = 0; i < 15; i++) { + ad9361_spi_write(phy->spi, REG_WORD_ADDRESS, i); + mixer_error[i] = ad9361_spi_read(phy->spi, REG_GAIN_ERROR_READ); + } + ad9361_spi_write(phy->spi, REG_CONFIG, 0x00); + + /* Programming gain step errors into the AD9361 in the field */ + ad9361_spi_write(phy->spi, + REG_CONFIG, CALIB_TABLE_SELECT(0x3) | START_CALIB_TABLE_CLOCK); + for(i = 0; i < 4; i++) { + ad9361_spi_write(phy->spi, REG_WORD_ADDRESS, i); + ad9361_spi_write(phy->spi, REG_GAIN_DIFF_WORDERROR_WRITE, lna_error[i]); + ad9361_spi_write(phy->spi, REG_CONFIG, + CALIB_TABLE_SELECT(0x3) | WRITE_LNA_ERROR_TABLE | START_CALIB_TABLE_CLOCK); + } + ad9361_spi_write(phy->spi, REG_CONFIG, + CALIB_TABLE_SELECT(0x3) | START_CALIB_TABLE_CLOCK); + for(i = 0; i < 15; i++) { + ad9361_spi_write(phy->spi, REG_WORD_ADDRESS, i); + ad9361_spi_write(phy->spi, REG_GAIN_DIFF_WORDERROR_WRITE, mixer_error[i]); + ad9361_spi_write(phy->spi, REG_CONFIG, + CALIB_TABLE_SELECT(0x3) | WRITE_MIXER_ERROR_TABLE | START_CALIB_TABLE_CLOCK); + } + ad9361_spi_write(phy->spi, REG_CONFIG, 0x00); + + ad9361_ensm_restore_prev_state(phy); + + return 0; +} diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/rf-transceiver/ad9361/ad9361.h b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/rf-transceiver/ad9361/ad9361.h new file mode 100644 index 0000000..33eb527 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/rf-transceiver/ad9361/ad9361.h @@ -0,0 +1,3568 @@ +/***************************************************************************//** + * @file ad9361.h + * @brief Header file of AD9361 Driver. +******************************************************************************** + * Copyright 2014(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ +#ifndef IIO_FREQUENCY_AD9361_H_ +#define IIO_FREQUENCY_AD9361_H_ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ +#include +#include "common.h" +#include "../../../include/gpio.h" + +/******************************************************************************/ +/********************** Macros and Constants Definitions **********************/ +/******************************************************************************/ +#define REG_SPI_CONF 0x000 /* SPI Configuration */ +#define REG_MULTICHIP_SYNC_AND_TX_MON_CTRL 0x001 /* Multi-Chip Sync and Tx Mon Control */ +#define REG_TX_ENABLE_FILTER_CTRL 0x002 /* Tx Enable & Filter Control */ +#define REG_RX_ENABLE_FILTER_CTRL 0x003 /* Rx Enable & Filter Control */ +#define REG_INPUT_SELECT 0x004 /* Input Select */ +#define REG_RFPLL_DIVIDERS 0x005 /* RFPLL Dividers */ +#define REG_RX_CLOCK_DATA_DELAY 0x006 /* Rx Clock & Data Delay */ +#define REG_TX_CLOCK_DATA_DELAY 0x007 /* Tx Clock & Data Delay */ +#define REG_CLOCK_ENABLE 0x009 /* Clock Enable */ +#define REG_BBPLL 0x00A /* BBPLL */ +#define REG_TEMP_OFFSET 0x00B /* Offset */ +#define REG_START_TEMP_READING 0x00C /* Start Temp Reading */ +#define REG_TEMP_SENSE2 0x00D /* Temp Sense2 */ +#define REG_TEMPERATURE 0x00E /* Temperature */ +#define REG_TEMP_SENSOR_CONFIG 0x00F /* Temp Sensor Config */ +#define REG_PARALLEL_PORT_CONF_1 0x010 /* Parallel Port Configuration 1 */ +#define REG_PARALLEL_PORT_CONF_2 0x011 /* Parallel Port Configuration 2 */ +#define REG_PARALLEL_PORT_CONF_3 0x012 /* Parallel Port Configuration 3 */ +#define REG_ENSM_MODE 0x013 /* ENSM Mode */ +#define REG_ENSM_CONFIG_1 0x014 /* ENSM Config 1 */ +#define REG_ENSM_CONFIG_2 0x015 /* ENSM Config 2 */ +#define REG_CALIBRATION_CTRL 0x016 /* Calibration Control */ +#define REG_STATE 0x017 /* State */ +#define REG_AUXDAC_1_WORD 0x018 /* AuxDAC 1 Word */ +#define REG_AUXDAC_2_WORD 0x019 /* AuxDAC 2 Word */ +#define REG_AUXDAC_1_CONFIG 0x01A /* AuxDAC 1 Config */ +#define REG_AUXDAC_2_CONFIG 0x01B /* AuxDAC 2 Config */ +#define REG_AUXADC_CLOCK_DIVIDER 0x01C /* AuxADC Clock Divider */ +#define REG_AUXADC_CONFIG 0x01D /* Aux ADC Config */ +#define REG_AUXADC_WORD_MSB 0x01E /* AuxADC Word MSB */ +#define REG_AUXADC_LSB 0x01F /* AuxADC LSB */ +#define REG_AUTO_GPO 0x020 /* Auto GPO */ +#define REG_AGC_GAIN_LOCK_DELAY 0x021 /* AGC Gain Lock Delay */ +#define REG_AGC_ATTACK_DELAY 0x022 /* AGC Attack Delay */ +#define REG_AUXDAC_ENABLE_CTRL 0x023 /* AuxDAC Enable Control */ +#define REG_RX_LOAD_SYNTH_DELAY 0x024 /* RX Load Synth Delay */ +#define REG_TX_LOAD_SYNTH_DELAY 0x025 /* TX Load Synth Delay */ +#define REG_EXTERNAL_LNA_CTRL 0x026 /* External LNA control */ +#define REG_GPO_FORCE_AND_INIT 0x027 /* GPO Force and Init */ +#define REG_GPO0_RX_DELAY 0x028 /* GPO0 Rx delay */ +#define REG_GPO1_RX_DELAY 0x029 /* GPO1 Rx delay */ +#define REG_GPO2_RX_DELAY 0x02A /* GPO2 Rx delay */ +#define REG_GPO3_RX_DELAY 0x02B /* GPO3 Rx delay */ +#define REG_GPO0_TX_DELAY 0x02C /* GPO0 Tx Delay */ +#define REG_GPO1_TX_DELAY 0x02D /* GPO1 Tx Delay */ +#define REG_GPO2_TX_DELAY 0x02E /* GPO2 Tx Delay */ +#define REG_GPO3_TX_DELAY 0x02F /* GPO3 Tx Delay */ +#define REG_AUXDAC1_RX_DELAY 0x030 /* AuxDAC1 Rx Delay */ +#define REG_AUXDAC1_TX_DELAY 0x031 /* AuxDAC1 Tx Delay */ +#define REG_AUXDAC2_RX_DELAY 0x032 /* AuxDAC2 Rx Delay */ +#define REG_AUXDAC2_TX_DELAY 0x033 /* AuxDAC2 Tx Delay */ +#define REG_CTRL_OUTPUT_POINTER 0x035 /* Control Output Pointer */ +#define REG_CTRL_OUTPUT_ENABLE 0x036 /* Control Output Enable */ +#define REG_PRODUCT_ID 0x037 /* Product ID */ +#define REG_REFERENCE_CLOCK_CYCLES 0x03A /* Reference Clock Cycles */ +#define REG_DIGITAL_IO_CTRL 0x03B /* Digital I/O Control */ +#define REG_LVDS_BIAS_CTRL 0x03C /* LVDS Bias control */ +#define REG_LVDS_INVERT_CTRL1 0x03D /* LVDS Invert control1 */ +#define REG_LVDS_INVERT_CTRL2 0x03E /* LVDS Invert control2 */ +#define REG_SDM_CTRL_1 0x03F /* SDM Control 1 */ +#define REG_FRACT_BB_FREQ_WORD_1 0x041 /* Fractional BB Freq Word 1 */ +#define REG_FRACT_BB_FREQ_WORD_2 0x042 /* Fractional BB Freq Word 2 */ +#define REG_FRACT_BB_FREQ_WORD_3 0x043 /* Fractional BB Freq Word 3 */ +#define REG_INTEGER_BB_FREQ_WORD 0x044 /* Integer BB Freq Word */ +#define REG_CLOCK_CTRL 0x045 /* Clock Control */ +#define REG_CP_CURRENT 0x046 /* CP Current */ +#define REG_CP_BLEED_CURRENT 0x047 /* CP Bleed Current */ +#define REG_LOOP_FILTER_1 0x048 /* Loop Filter 1 */ +#define REG_LOOP_FILTER_2 0x049 /* Loop Filter 2 */ +#define REG_LOOP_FILTER_3 0x04A /* Loop Filter 3 */ +#define REG_VCO_CTRL 0x04B /* VCO Control */ +#define REG_VCO_PROGRAM_1 0x04C +#define REG_VCO_PROGRAM_2 0x04D +#define REG_SDM_CTRL 0x04E /* SDM Control */ +#define REG_RX_SYNTH_POWER_DOWN_OVERRIDE 0x050 /* Rx Synth Power Down Override */ +#define REG_TX_SYNTH_POWER_DOWN_OVERRIDE 0x051 /* TX Synth Power Down Override */ +#define REG_RX_ANALOG_POWER_DOWN_OVERRIDE_1 0x052 /* Rx Analog Power Down Override 1 */ +#define REG_RX_ANALOG_POWER_DOWN_OVERRIDE_2 0x053 /* Rx Analog Power Down Override 2 */ +#define REG_RX1_ADC_POWER_DOWN_OVERRIDE 0x054 /* Rx1 ADC Power Down Override */ +#define REG_RX2_ADC_POWER_DOWN_OVERRIDE 0x055 /* Rx2 ADC Power Down Override */ +#define REG_TX_ANALOG_POWER_DOWN_OVERRIDE_1 0x056 /* Tx Analog Power Down Override 1 */ +#define REG_ANALOG_POWER_DOWN_OVERRIDE 0x057 /* Analog Power Down Override */ +#define REG_MISC_POWER_DOWN_OVERRIDE 0x058 /* Misc Power Down Override */ +#define REG_CH_1_OVERFLOW 0x05E /* CH 1 Overflow */ +#define REG_CH_2_OVERFLOW 0x05F /* CH 2 Overflow */ +#define REG_TX_FILTER_COEF_ADDR 0x060 /* TX Filter Coefficient Address */ +#define REG_TX_FILTER_COEF_WRITE_DATA_1 0x061 /* TX Filter Coefficient Write Data 1 */ +#define REG_TX_FILTER_COEF_WRITE_DATA_2 0x062 /* TX Filter Coefficient Write Data 2 */ +#define REG_TX_FILTER_COEF_READ_DATA_1 0x063 /* TX Filter Coefficient Read Data 1 */ +#define REG_TX_FILTER_COEF_READ_DATA_2 0x064 /* TX Filter Coefficient Read Data 2 */ +#define REG_TX_FILTER_CONF 0x065 /* TX Filter Configuration */ +#define REG_TX_MON_LOW_GAIN 0x067 /* Tx Mon Low Gain */ +#define REG_TX_MON_HIGH_GAIN 0x068 /* Tx Mon High Gain */ +#define REG_TX_MON_DELAY 0x069 /* Tx Mon Delay */ +#define REG_TX_LEVEL_THRESH 0x06A /* Tx Level Threshold */ +#define REG_TX_RSSI1 0x06B /* TX RSSI1 */ +#define REG_TX_RSSI2 0x06C /* TX RSSI2 */ +#define REG_TX_RSSI_LSB 0x06D /* TX RSSI LSB */ +#define REG_TPM_MODE_ENABLE 0x06E /* TPM Mode Enable */ +#define REG_TX_MON_TEMP_GAIN_COEF 0x06F /* Temp Gain Coefficient */ +#define REG_TX_MON_1_CONFIG 0x070 /* Tx Mon 1 Config */ +#define REG_TX_MON_2_CONFIG 0x071 /* Tx Mon 2 Config */ +#define REG_TX1_ATTEN_0 0x073 /* Tx1 Atten 0 */ +#define REG_TX1_ATTEN_1 0x074 /* Tx1 Atten 1 */ +#define REG_TX2_ATTEN_0 0x075 /* Tx2 Atten 0 */ +#define REG_TX2_ATTEN_1 0x076 /* Tx2 Atten 1 */ +#define REG_TX_ATTEN_OFFSET 0x077 /* Tx Atten Offset */ +#define REG_TX_ATTEN_THRESH 0x078 /* Tx Atten Threshold */ +#define REG_TX1_DIG_ATTEN 0x079 /* Tx1 Dig Attenuation */ +#define REG_TX2_DIG_ATTEN 0x07C /* Tx2 Dig Attenuation */ +#define REG_TX1_SYMBOL_ATTEN 0x07F /* TX1 Symbol Attenuation */ +#define REG_TX2_SYMBOL_ATTEN 0x080 /* TX2 Symbol Attenuation */ +#define REG_TX_SYMBOL_ATTEN_CONFIG 0x081 /* TX Symbol Atten Config */ +#define REG_TX1_OUT_1_PHASE_CORR 0x08E /* Tx1 Out 1 Phase Corr */ +#define REG_TX1_OUT_1_GAIN_CORR 0x08F /* Tx1 Out 1 Gain Corr */ +#define REG_TX2_OUT_1_PHASE_CORR 0x090 /* Tx2 Out 1 Phase Corr */ +#define REG_TX2_OUT_1_GAIN_CORR 0x091 /* Tx2 Out 1 Gain Corr */ +#define REG_TX1_OUT_1_OFFSET_I 0x092 /* Tx1 Out 1 Offset I */ +#define REG_TX1_OUT_1_OFFSET_Q 0x093 /* Tx1 Out 1 Offset Q */ +#define REG_TX2_OUT_1_OFFSET_I 0x094 /* Tx2 Out 1 Offset I */ +#define REG_TX2_OUT_1_OFFSET_Q 0x095 /* Tx2 Out 1 Offset Q */ +#define REG_TX1_OUT_2_PHASE_CORR 0x096 /* Tx1 Out 2 Phase Corr */ +#define REG_TX1_OUT_2_GAIN_CORR 0x097 /* Tx1 Out 2 Gain Corr */ +#define REG_TX2_OUT_2_PHASE_CORR 0x098 /* Tx2 Out 2 Phase Corr */ +#define REG_TX2_OUT_2_GAIN_CORR 0x099 /* Tx2 Out 2 Gain Corr */ +#define REG_TX1_OUT_2_OFFSET_I 0x09A /* Tx1 Out 2 Offset I */ +#define REG_TX1_OUT_2_OFFSET_Q 0x09B /* Tx1 Out 2 Offset Q */ +#define REG_TX2_OUT_2_OFFSET_I 0x09C /* Tx2 Out 2 Offset I */ +#define REG_TX2_OUT_2_OFFSET_Q 0x09D /* Tx2 Out 2 Offset Q */ +#define REG_TX_FORCE_BITS 0x09F /* Force Bits */ +#define REG_QUAD_CAL_NCO_FREQ_PHASE_OFFSET 0x0A0 /* Quad Cal NCO Freq & Phase Offset */ +#define REG_QUAD_CAL_CTRL 0x0A1 /* Quad Cal Control */ +#define REG_KEXP_1 0x0A2 /* Kexp 1 */ +#define REG_KEXP_2 0x0A3 /* Kexp 2 */ +#define REG_QUAD_SETTLE_COUNT 0x0A4 /* QUAD Settle count */ +#define REG_MAG_FTEST_THRESH 0x0A5 /* Mag. Ftest Thresh */ +#define REG_MAG_FTEST_THRESH_2 0x0A6 /* Mag. Ftest Thresh 2 */ +#define REG_QUAD_CAL_STATUS_TX1 0x0A7 /* Quad cal status Tx1 */ +#define REG_QUAD_CAL_STATUS_TX2 0x0A8 /* Quad cal status Tx2 */ +#define REG_QUAD_CAL_COUNT 0x0A9 /* Quad cal Count */ +#define REG_TX_QUAD_FULL_LMT_GAIN 0x0AA /* Tx Quad Full/LMT Gain */ +#define REG_SQUARER_CONFIG 0x0AB /* Squarer Config */ +#define REG_TX_QUAD_CAL_ATTEN 0x0AC /* TX Quad Cal Atten */ +#define REG_THRESH_ACCUM 0x0AD /* Thresh Accum */ +#define REG_TX_QUAD_LPF_GAIN 0x0AE /* Tx Quad LPF Gain */ +#define REG_TXDAC_VDS_I 0x0B0 /* TxDAC Vds I */ +#define REG_TXDAC_VDS_Q 0x0B1 /* TxDAC Vds Q */ +#define REG_TXDAC_GN_I 0x0B2 /* TxDAC gn I */ +#define REG_TXDAC_GN_Q 0x0B3 /* TxDAC gn Q */ +#define REG_TXBBF_OPAMP_A 0x0C0 /* TxBBF OpAmp A */ +#define REG_TXBBF_OPAMP_B 0x0C1 /* TxBBF OpAmp B */ +#define REG_TX_BBF_R1 0x0C2 /* Tx BBF R1 */ +#define REG_TX_BBF_R2 0x0C3 /* Tx BBF R2 */ +#define REG_TX_BBF_R3 0x0C4 /* Tx BBF R3 */ +#define REG_TX_BBF_R4 0x0C5 /* Tx BBF R4 */ +#define REG_TX_BBF_RP 0x0C6 /* Tx BBF RP */ +#define REG_TX_BBF_C1 0x0C7 /* Tx BBF C1 */ +#define REG_TX_BBF_C2 0x0C8 /* Tx BBF C2 */ +#define REG_TX_BBF_CP 0x0C9 /* Tx BBF Cp */ +#define REG_TX_TUNE_CTRL 0x0CA /* Tx Tune Control */ +#define REG_TX_BBF_R2B 0x0CB /* Tx BBF R2b */ +#define REG_TX_BBF_TUNE 0x0CC /* Tx BBF Tune */ +#define REG_CONFIG0 0x0D0 /* Config0 */ +#define REG_RESISTOR 0x0D1 /* Resistor */ +#define REG_CAPACITOR 0x0D2 /* Capacitor */ +#define REG_LO_CM 0x0D3 /* LO CM */ +#define REG_TX_BBF_TUNE_DIVIDER 0x0D6 /* TX BBF Tune Divider */ +#define REG_TX_BBF_TUNE_MODE 0x0D7 /* TX BBF Tune Mode */ +#define REG_RX_FILTER_COEF_ADDR 0x0F0 /* Rx Filter Coeff Addr */ +#define REG_RX_FILTER_COEF_DATA_1 0x0F1 /* Rx Filter Coeff Data 1 */ +#define REG_RX_FILTER_COEF_DATA_2 0x0F2 /* Rx Filter Coeff Data 2 */ +#define REG_RX_FILTER_COEF_READ_DATA_1 0x0F3 /* Rx Filter Coeff Read Data 1 */ +#define REG_RX_FILTER_COEF_READ_DATA_2 0x0F4 /* Rx Filter Coeff Read Data 2 */ +#define REG_RX_FILTER_CONFIG 0x0F5 /* Rx Filter Config */ +#define REG_RX_FILTER_GAIN 0x0F6 /* Rx Filter Gain */ +#define REG_AGC_CONFIG_1 0x0FA /* AGC Config1 */ +#define REG_AGC_CONFIG_2 0x0FB /* AGC config2 */ +#define REG_AGC_CONFIG_3 0x0FC /* AGC Config3 */ +#define REG_MAX_LMT_FULL_GAIN 0x0FD /* Max LMT/Full Gain */ +#define REG_PEAK_WAIT_TIME 0x0FE /* Peak Wait Time */ +#define REG_DIGITAL_GAIN 0x100 /* Digital Gain */ +#define REG_AGC_LOCK_LEVEL 0x101 /* AGC Lock Level */ +#define REG_ADC_NOISE_CORRECTION_FACTOR 0x102 /* ADC noise Correction Factor */ +#define REG_GAIN_STP_CONFIG1 0x103 /* Gain Step Config1 */ +#define REG_ADC_SMALL_OVERLOAD_THRESH 0x104 /* ADC Small Overload Threshold */ +#define REG_ADC_LARGE_OVERLOAD_THRESH 0x105 /* ADC Large Overload Threshold */ +#define REG_GAIN_STP_CONFIG_2 0x106 /* Gain Step Config 2 */ +#define REG_SMALL_LMT_OVERLOAD_THRESH 0x107 /* Small LMT Overload Threshold */ +#define REG_LARGE_LMT_OVERLOAD_THRESH 0x108 /* Large LMT Overload Threshold */ +#define REG_RX1_MANUAL_LMT_FULL_GAIN 0x109 /* Rx1 Manual LMT/Full Gain */ +#define REG_RX1_MANUAL_LPF_GAIN 0x10A /* Rx1 Manual LPF gain */ +#define REG_RX1_MANUAL_DIGITALFORCED_GAIN 0x10B /* Rx1 Manual Digital/Forced Gain */ +#define REG_RX2_MANUAL_LMT_FULL_GAIN 0x10C /* Rx2 Manual LMT/Full Gain */ +#define REG_RX2_MANUAL_LPF_GAIN 0x10D /* Rx2 Manual LPF Gain */ +#define REG_RX2_MANUAL_DIGITALFORCED_GAIN 0x10E /* Rx2 Manual Digital/Forced Gain */ +#define REG_FAST_CONFIG_1 0x110 /* Config 1 */ +#define REG_FAST_CONFIG_2_SETTLING_DELAY 0x111 /* Config 2 & Settling Delay */ +#define REG_FAST_ENERGY_LOST_THRESH 0x112 /* Energy Lost Threshold */ +#define REG_FAST_STRONGER_SIGNAL_THRESH 0x113 /* Stronger Signal Threshold */ +#define REG_FAST_LOW_POWER_THRESH 0x114 /* Low Power Threshold */ +#define REG_FAST_STRONG_SIGNAL_FREEZE 0x115 /* Strong Signal Freeze */ +#define REG_FAST_FINAL_OVER_RANGE_AND_OPT_GAIN 0x116 /* Final Over Range and Opt Gain */ +#define REG_FAST_ENERGY_DETECT_COUNT 0x117 /* Energy Detect Count */ +#define REG_FAST_AGCLL_UPPER_LIMIT 0x118 /* AGCLL Upper Limit */ +#define REG_FAST_GAIN_LOCK_EXIT_COUNT 0x119 /* Gain Lock Exit Count */ +#define REG_FAST_INITIAL_LMT_GAIN_LIMIT 0x11A /* Initial LMT Gain Limit */ +#define REG_FAST_INCREMENT_TIME 0x11B /* Increment Time */ +#define REG_AGC_INNER_LOW_THRESH 0x120 /* AGC Inner Low Threshold */ +#define REG_LMT_OVERLOAD_COUNTERS 0x121 /* LMT Overload Counters */ +#define REG_ADC_OVERLOAD_COUNTERS 0x122 /* ADC Overload Counters */ +#define REG_GAIN_STP1 0x123 /* Gain Step1 */ +#define REG_GAIN_UPDATE_COUNTER1 0x124 /* Gain Update Counter1 */ +#define REG_GAIN_UPDATE_COUNTER2 0x125 /* Gain Update Counter2 */ +#define REG_DIGITAL_SAT_COUNTER 0x128 /* Digital Sat Counter */ +#define REG_OUTER_POWER_THRESHS 0x129 /* Outer Power Thresholds */ +#define REG_GAIN_STP_2 0x12A /* Gain Step 2 */ +#define REG_EXT_LNA_HIGH_GAIN 0x12C /* Ext LNA High Gain */ +#define REG_EXT_LNA_LOW_GAIN 0x12D /* Ext LNA Low Gain */ +#define REG_GAIN_TABLE_ADDRESS 0x130 /* Gain Table Address */ +#define REG_GAIN_TABLE_WRITE_DATA1 0x131 /* Gain Table Write Data1 */ +#define REG_GAIN_TABLE_WRITE_DATA2 0x132 /* Gain Table Write Data2 */ +#define REG_GAIN_TABLE_WRITE_DATA3 0x133 /* Gain Table Write Data 3 */ +#define REG_GAIN_TABLE_READ_DATA1 0x134 /* Gain Table Read Data 1 */ +#define REG_GAIN_TABLE_READ_DATA2 0x135 /* Gain Table Read Data 2 */ +#define REG_GAIN_TABLE_READ_DATA3 0x136 /* Gain Table Read Data 3 */ +#define REG_GAIN_TABLE_CONFIG 0x137 /* Gain Table Config */ +#define REG_GM_SUB_TABLE_ADDRESS 0x138 /* Gm Sub Table Address */ +#define REG_GM_SUB_TABLE_GAIN_WRITE 0x139 /* Gm Sub Table Gain Word Write */ +#define REG_GM_SUB_TABLE_BIAS_WRITE 0x13A /* Gm Sub Table Bias Word Write */ +#define REG_GM_SUB_TABLE_CTRL_WRITE 0x13B /* Gm Sub Table Control Word Write */ +#define REG_GM_SUB_TABLE_GAIN_READ 0x13C /* Gm Sub Table Gain Word Read */ +#define REG_GM_SUB_TABLE_BIAS_READ 0x13D /* Gm Sub Table Bias Word Read */ +#define REG_GM_SUB_TABLE_CTRL_READ 0x13E /* Gm Sub Table Control Word Read */ +#define REG_GM_SUB_TABLE_CONFIG 0x13F /* Gm Sub Table Config */ +#define REG_WORD_ADDRESS 0x140 /* Word Address */ +#define REG_GAIN_DIFF_WORDERROR_WRITE 0x141 /* Gain Diff Word/Error Write */ +#define REG_GAIN_ERROR_READ 0x142 /* Gain Error Read */ +#define REG_CONFIG 0x143 /* Config */ +#define REG_LNA_GAIN_DIFF_READ_BACK 0x144 /* LNA Gain Diff Read Back */ +#define REG_MAX_MIXER_CALIBRATION_GAIN_INDEX 0x145 /* Max Mixer Calibration Gain Index */ +#define REG_TEMP_GAIN_COEF 0x146 /* Temp Gain Coefficient */ +#define REG_SETTLE_TIME 0x147 /* Settle Time */ +#define REG_MEASURE_DURATION 0x148 /* Measure Duration */ +#define REG_CAL_TEMP_SENSOR_WORD 0x149 /* Cal Temp sensor word */ +#define REG_MEASURE_DURATION_01 0x150 /* Measure Duration 0&1 */ +#define REG_MEASURE_DURATION_23 0x151 /* Measure Duration 2&3 */ +#define REG_RSSI_WEIGHT_0 0x152 /* RSSI Weight 0 */ +#define REG_RSSI_WEIGHT_1 0x153 /* RSSI Weight 1 */ +#define REG_RSSI_WEIGHT_2 0x154 /* RSSI Weight 2 */ +#define REG_RSSI_WEIGHT_3 0x155 /* RSSI Weight 3 */ +#define REG_RSSI_DELAY 0x156 /* RSSI delay */ +#define REG_RSSI_WAIT_TIME 0x157 /* RSSI wait time */ +#define REG_RSSI_CONFIG 0x158 /* RSSI Config */ +#define REG_ADC_MEASURE_DURATION_01 0x159 /* ADC Measure Duration 0&1 */ +#define REG_ADC_WEIGHT_0 0x15A /* ADC Weight 0 */ +#define REG_ADC_WEIGHT_1 0x15B /* ADC Weight 1 */ +#define REG_DEC_POWER_MEASURE_DURATION_0 0x15C /* Dec Power Measure Duration 0 */ +#define REG_LNA_GAIN 0x15D /* LNA Gain */ +#define REG_CH1_ADC_POWER 0x160 /* CH1 ADC Power */ +#define REG_CH1_RX_FILTER_POWER 0x161 /* CH1 Rx filter Power */ +#define REG_CH2_ADC_POWER 0x162 /* CH2 ADC Power */ +#define REG_CH2_RX_FILTER_POWER 0x163 /* CH2 Rx filter Power */ +#define REG_RX_QUAD_CAL_LEVEL 0x168 /* Rx Quad Cal Level */ +#define REG_CALIBRATION_CONFIG_1 0x169 /* Calibration Config 1 */ +#define REG_CALIBRATION_CONFIG_2 0x16A /* Calibration config2 */ +#define REG_CALIBRATION_CONFIG_3 0x16B /* Calibration config3 */ +#define REG_CALIB_COUNT 0x16C /* Calib count */ +#define REG_SETTLE_COUNT 0x16D /* Settle count */ +#define REG_RX_QUAD_GAIN1 0x16E /* Rx Quad gain1 */ +#define REG_RX_QUAD_GAIN2 0x16F /* Rx Quad gain2 */ +#define REG_RX1_INPUT_A_PHASE_CORR 0x170 /* Rx1 Input A Phase Corr */ +#define REG_RX1_INPUT_A_GAIN_CORR 0x171 /* Rx1 Input A Gain Corr */ +#define REG_RX2_INPUT_A_PHASE_CORR 0x172 /* Rx2 Input A Phase Corr */ +#define REG_RX2_INPUT_A_GAIN_CORR 0x173 /* Rx2 Input A Gain Corr */ +#define REG_RX1_INPUT_A_Q_OFFSET 0x174 /* Rx1 Input A Q" Offset */ +#define REG_RX1_INPUT_A_OFFSETS 0x175 /* Rx1 Input A Offsets */ +#define REG_INPUT_A_OFFSETS_1 0x176 /* Input A Offsets 1 */ +#define REG_RX2_INPUT_A_OFFSETS 0x177 /* Rx2 Input A Offsets */ +#define REG_RX2_INPUT_A_I_OFFSET 0x178 /* Rx2 Input A "I" Offset */ +#define REG_RX1_INPUT_BC_PHASE_CORR 0x179 /* Rx1 Input B&C Phase Corr */ +#define REG_RX1_INPUT_BC_GAIN_CORR 0x17A /* Rx1 Input B&C Gain Corr */ +#define REG_RX2_INPUT_BC_PHASE_CORR 0x17B /* Rx2 Input B&C Phase Corr */ +#define REG_RX2_INPUT_BC_GAIN_CORR 0x17C /* Rx2 Input B&C Gain Corr */ +#define REG_RX1_INPUT_BC_Q_OFFSET 0x17D /* Rx1 Input B&C "Q" Offset */ +#define REG_RX1_INPUT_BC_OFFSETS 0x17E /* Rx1 Input B&C Offsets */ +#define REG_INPUT_BC_OFFSETS_1 0x17F /* Input B&C Offsets 1 */ +#define REG_RX2_INPUT_BC_OFFSETS 0x180 /* Rx2 Input B&C Offsets */ +#define REG_RX2_INPUT_BC_I_OFFSET 0x181 /* Rx2 Input B&C "I" Offset */ +#define REG_FORCE_BITS 0x182 /* Force Bits */ +#define REG_WAIT_COUNT 0x185 /* Wait Count */ +#define REG_RF_DC_OFFSET_COUNT 0x186 /* RF DC Offset Count */ +#define REG_RF_DC_OFFSET_CONFIG_1 0x187 /* RF DC Offset Config1 */ +#define REG_RF_DC_OFFSET_ATTEN 0x188 /* RF DC Offset Attenuation */ +#define REG_INVERT_BITS 0x189 /* Invert Bits */ +#define REG_DC_OFFSET_CONFIG2 0x18B /* DC Offset Config2 */ +#define REG_RF_CAL_GAIN_INDEX 0x18C /* RF Cal Gain Index */ +#define REG_SOI_THRESH 0x18D /* SOI Threshold */ +#define REG_BB_DC_OFFSET_SHIFT 0x190 /* BB DC Offset Shift */ +#define REG_BB_DC_OFFSET_FAST_SETTLE_SHIFT 0x191 /* BB DC Offset Fast Settle Shift */ +#define REG_BB_FAST_SETTLE_DUR 0x192 /* BB Fast Settle Dur */ +#define REG_BB_DC_OFFSET_COUNT 0x193 /* BB DC Offset Count */ +#define REG_BB_DC_OFFSET_ATTEN 0x194 /* BB DC Offset Attenuation */ +#define REG_RX1_BB_DC_WORD_I_MSB 0x19A /* RX1 BB DC word I MSB */ +#define REG_RX1_BB_DC_WORD_I_LSB 0x19B /* RX1 BB DC word I LSB */ +#define REG_RX1_BB_DC_WORD_Q_MSB 0x19C /* RX1 BB DC word Q MSB */ +#define REG_RX1_BB_DC_WORD_Q_LSB 0x19D /* RX1 BB DC word Q LSB */ +#define REG_RX2_BB_DC_WORD_I_MSB 0x19E /* RX2 BB DC word I MSB */ +#define REG_RX2_BB_DC_WORD_I_LSB 0x19F /* RX2 BB DC word I LSB */ +#define REG_RX2_BB_DC_WORD_Q_MSB 0x1A0 /* RX2 BB DC word Q MSB */ +#define REG_RX2_BB_DC_WORD_Q_LSB 0x1A1 /* RX2 BB DC word Q LSB */ +#define REG_BB_TRACK_CORR_WORD_I_MSB 0x1A2 /* BB Track corr word I MSB */ +#define REG_BB_TRACK_CORR_WORD_I_LSB 0x1A3 /* BB Track corr word I LSB */ +#define REG_BB_TRACK_CORR_WORD_Q_MSB 0x1A4 /* BB Track corr word Q MSB */ +#define REG_BB_TRACK_CORR_WORD_Q_LSB 0x1A5 /* BB Track corr word Q LSB */ +#define REG_RX1_RSSI_SYMBOL 0x1A7 /* Rx1 RSSI Symbol */ +#define REG_RX1_RSSI_PREAMBLE 0x1A8 /* Rx1 RSSI preamble */ +#define REG_RX2_RSSI_SYMBOL 0x1A9 /* Rx2 RSSI symbol */ +#define REG_RX2_RSSI_PREAMBLE 0x1AA /* Rx2 RSSI preamble */ +#define REG_SYMBOL_LSB 0x1AB /* Symbol LSB */ +#define REG_PREAMBLE_LSB 0x1AC /* Preamble LSB */ +#define REG_RX_PATH_GAIN_MSB 0x1AD /* Rx Path Gain */ +#define REG_RX_PATH_GAIN_LSB 0x1AE /* Rx Path Gain */ +#define REG_RX_DIFF_LNA_FORCE 0x1B0 /* Rx Diff LNA Force */ +#define REG_RX_LNA_BIAS_COARSE 0x1B1 /* Rx LNA Bias Coarse */ +#define REG_RX_LNA_BIAS_FINE_0 0x1B2 /* Rx LNA Bias Fine 0 */ +#define REG_RX_LNA_BIAS_FINE_1 0x1B3 /* Rx LNA Bias Fine 1 */ +#define REG_RX_MIX_GM_CONFIG 0x1C0 /* Rx Mix Gm Config */ +#define REG_RX1_MIX_GM_FORCE 0x1C1 /* Rx1 Mix Gm Force */ +#define REG_RX1_MIX_GM_BIAS_FORCE 0x1C2 /* Rx1 Mix Gm Bias (Force) */ +#define REG_RX2_MIX_GM_FORCE 0x1C3 /* Rx2 Mix Gm Force */ +#define REG_RX2_MIX_GM_BIAS_FORCE 0x1C4 /* Rx2 Mix Gm Bias (Force) */ +#define REG_INPUT_A_MSBS 0x1C8 /* Input A MSBs */ +#define REG_INPUT_A_RX1_I 0x1C9 /* Input A RX1 I */ +#define REG_INPUT_A_RX1_Q 0x1CA /* Input A RX1 Q */ +#define REG_INPUT_A_RX2_I 0x1CB /* Input A RX2 I */ +#define REG_INPUT_A_RX2_Q 0x1CC /* Input A RX2 Q */ +#define REG_INPUTS_BC_RX1_I 0x1CD /* Inputs B&C RX1 I */ +#define REG_BAND1_RX1_Q 0x1CE /* Band1 RX1 Q */ +#define REG_INPUTS_BC_RX2_I 0x1CF /* Inputs B&C RX2 I */ +#define REG_INPUTS_BC_RX2_Q 0x1D0 /* Inputs B&C RX2 Q */ +#define REG_INPUTS_BC_MSBS 0x1D1 /* Inputs B&C MSBs */ +#define REG_FORCE_OS_DAC 0x1D2 /* Force OS DAC */ +#define REG_RX_MIX_LO_CM 0x1D5 /* Rx Mix LO CM */ +#define REG_RX_CGB_SEG_ENABLE 0x1D6 /* Rx CGB Seg Enable */ +#define REG_RX_MIX_INPUTBIAS 0x1D7 /* Rx Mix Input/Bias */ +#define REG_RX_TIA_CONFIG 0x1DB /* Rx TIA Config */ +#define REG_TIA1_C_LSB 0x1DC /* TIA1 C LSB */ +#define REG_TIA1_C_MSB 0x1DD /* TIA1 C MSB */ +#define REG_TIA2_C_LSB 0x1DE /* TIA2 C LSB */ +#define REG_TIA2_C_MSB 0x1DF /* TIA2 C MSB */ +#define REG_RX1_BBF_R1A 0x1E0 /* Rx1 BBF R1A */ +#define REG_RX2_BBF_R1A 0x1E1 /* Rx2 BBF R1A */ +#define REG_RX1_TUNE_CTRL 0x1E2 /* Rx1 Tune Control */ +#define REG_RX2_TUNE_CTRL 0x1E3 /* Rx2 Tune Control */ +#define REG_RX1_BBF_R5 0x1E4 /* Rx1 BBF R5 */ +#define REG_RX2_BBF_R5 0x1E5 /* Rx2 BBF R5 */ +#define REG_RX_BBF_R2346 0x1E6 /* Rx BBF R2346 */ +#define REG_RX_BBF_C1_MSB 0x1E7 /* Rx BBF C1 MSB */ +#define REG_RX_BBF_C1_LSB 0x1E8 /* Rx BBF C1 LSB */ +#define REG_RX_BBF_C2_MSB 0x1E9 /* Rx BBF C2 MSB */ +#define REG_RX_BBF_C2_LSB 0x1EA /* Rx BBF C2 LSB */ +#define REG_RX_BBF_C3_MSB 0x1EB /* Rx BBF C3 MSB */ +#define REG_RX_BBF_C3_LSB 0x1EC /* Rx BBF C3 LSB */ +#define REG_RX_BBF_CC1_CTR 0x1ED /* Rx BBF CC1 Ctr */ +#define REG_RX_BBF_POW_RZ_BYTE0 0x1EE /* Rx BBF Pow Rz Byte0 */ +#define REG_RX_BBF_CC2_CTR 0x1EF /* Rx BBF CC2 Ctr */ +#define REG_RX_BBF_POW_RZ_BYTE1 0x1F0 /* Rx BBF Pow Rz Byte1 */ +#define REG_RX_BBF_CC3_CTR 0x1F1 /* Rx BBF CC3 Ctr */ +#define REG_RX_BBF_R5_TUNE 0x1F2 /* Rx BBF R5 Tune */ +#define REG_RX_BBF_TUNE 0x1F3 /* Rx BBF Tune */ +#define REG_RX1_BBF_MAN_GAIN 0x1F4 /* Rx1 BBF Man Gain */ +#define REG_RX2_BBF_MAN_GAIN 0x1F5 /* Rx2 BBF Man Gain */ +#define REG_RX_BBF_TUNE_DIVIDE 0x1F8 /* RX BBF Tune Divide */ +#define REG_RX_BBF_TUNE_CONFIG 0x1F9 /* RX BBF Tune Config */ +#define REG_POLE_GAIN 0x1FA /* Pole gain */ +#define REG_RX_BBBW_MHZ 0x1FB /* Rx BBBW MHz */ +#define REG_RX_BBBW_KHZ 0x1FC /* Rx BBBW kHz */ +#define REG_FB_DAC_CLK_DELAY1 0x201 /* FB DAC Clk Delay1 */ +#define REG_FB_DAC_CLK_DELAY2 0x202 /* FB DAC Clk Delay2 */ +#define REG_FLASH_SAMPLE_CLK_DELAY_3P 0x203 /* Flash Sample Clk Delay 3p */ +#define REG_FLASH_SAMPLE_CLK_DELAY_3N 0x204 /* Flash Sample Clk Delay 3n */ +#define REG_TEST_MUX_2I 0x205 /* Test MUX 2i */ +#define REG_TEST_MUX_2Q 0x206 /* Test MUX 2q */ +#define REG_INTEGRATOR_1_RESISTANCE 0x207 /* Integrator 1 Resistance */ +#define REG_INTEGRATOR_1_CAPACITANCE 0x208 /* Integrator 1 Capacitance */ +#define REG_INTEGRATOR_23_RESISTANCE 0x209 /* Integrator 23 Resistance */ +#define REG_INTEGRATOR_2_RESISTANCE 0x20A /* Integrator 2 Resistance */ +#define REG_INTEGRATOR_2_CAPACITANCE 0x20B /* Integrator 2 Capacitance */ +#define REG_INTEGRATOR_3_RESISTANCE 0x20C /* Integrator 3 Resistance */ +#define REG_INTEGRATOR_3_CAPACITANCE 0x20D /* Integrator 3 Capacitance */ +#define REG_INTEGRATOR_AMP_CC 0x20E /* Integrator Amp Cc */ +#define REG_INT_1_FB_DAC_NMOS_CURRENT_SOURCE 0x20F /* Int 1 FB DAC NMOS Current Source */ +#define REG_INT_1_FB_DAC_NMOS_CASOADE_BIAS_CURRENT 0x210 /* Int 1 FB DAC NMOS Casoade Bias Current */ +#define REG_INT_1_FB_DAC_PMOS_CURRENT_SOURCE 0x211 /* Int 1 FB DAC PMOS Current Source */ +#define REG_INT_2_FB_DAC_NMOS_CURRENT_SOURCE 0x212 /* Int 2 FB DAC NMOS Current Source */ +#define REG_INT_2_FB_DAC_NMOS_CASCODE_BIAS_CURRENT 0x213 /* Int 2 FB DAC NMOS Cascode Bias Current */ +#define REG_INT_2_FB_DAC_PMOS_CURRENT_SOURCE 0x214 /* Int 2 FB DAC PMOS Current Source */ +#define REG_INT_3_FB_DAC_NMOS_CURRENT_SOURCE 0x215 /* Int 3 FB DAC NMOS Current Source */ +#define REG_INT_3_FB_DAC_NMOS_CASCODE_BIAS_CURRENT 0x216 /* Int 3 FB DAC NMOS Cascode Bias Current */ +#define REG_INT_3_FB_DAC_PMOS_CURRENT_SOURCE 0x217 /* Int 3 FB DAC PMOS Current Source */ +#define REG_FB_DAC_BIAS_CURRENT 0x218 /* FB DAC Bias Current */ +#define REG_INT_1_1ST_STAGE_CURRENT 0x219 /* Int 1 1st Stage Current */ +#define REG_INT_1_1ST_STAGE_CASCODE_CURRENT 0x21A /* Int 1 1st Stage Cascode Current */ +#define REG_INT_1_2ND_STAGE_CURRENT 0x21B /* Int 1 2nd Stage Current */ +#define REG_INTEGRATOR_2_1ST_STAGE_CURRENT 0x21C /* Integrator 2 1st Stage Current */ +#define REG_INT_2_1ST_STAGE_CASCODE_CURRENT 0x21D /* Int 2 1st Stage Cascode Current */ +#define REG_INT_2_2ND_STAGE_CURRENT 0x21E /* Int 2 2nd Stage Current */ +#define REG_INT_3_1ST_STAGE_CURRENT 0x21F /* Int 3 1st Stage Current */ +#define REG_INT_3_1ST_STAGE_CASCODE_CURRENT 0x220 /* Int 3 1st Stage Cascode Current */ +#define REG_INT_3_2ND_STAGE_CURRENT 0x221 /* Int 3 2nd Stage Current */ +#define REG_FLASH_BIAS_CURRENT 0x222 /* Flash Bias Current */ +#define REG_FLASH_LADDER_BIAS 0x223 /* Flash Ladder Bias */ +#define REG_FLASH_LADDER_CASCODE_CURRENT 0x224 /* Flash Ladder Cascode Current */ +#define REG_FLASH_LADDER_BIAS2 0x225 /* Flash Ladder Bias2 */ +#define REG_RESET 0x226 /* Reset */ +#define REG_RX_PFD_CONFIG 0x230 /* RX PFD Config */ +#define REG_RX_INTEGER_BYTE_0 0x231 /* RX Integer Byte 0 */ +#define REG_RX_INTEGER_BYTE_1 0x232 /* RX Integer Byte 1 */ +#define REG_RX_FRACT_BYTE_0 0x233 /* RX Fractional Byte 0 */ +#define REG_RX_FRACT_BYTE_1 0x234 /* RX Fractional Byte 1 */ +#define REG_RX_FRACT_BYTE_2 0x235 /* RX Fractional Byte 2 */ +#define REG_RX_FORCE_ALC 0x236 /* RX Force ALC */ +#define REG_RX_FORCE_VCO_TUNE_0 0x237 /* RX Force VCO Tune 0 */ +#define REG_RX_FORCE_VCO_TUNE_1 0x238 /* RX Force VCO Tune 1 */ +#define REG_RX_ALC_VARACTOR 0x239 /* RX ALC/Varactor */ +#define REG_RX_VCO_OUTPUT 0x23A /* RX VCO Output */ +#define REG_RX_CP_CURRENT 0x23B /* RX CP Current */ +#define REG_RX_CP_OFFSET 0x23C /* RX CP Offset */ +#define REG_RX_CP_CONFIG 0x23D /* RX CP Config */ +#define REG_RX_LOOP_FILTER_1 0x23E /* RX Loop Filter 1 */ +#define REG_RX_LOOP_FILTER_2 0x23F /* RX Loop Filter 2 */ +#define REG_RX_LOOP_FILTER_3 0x240 /* RX Loop Filter 3 */ +#define REG_RX_DITHERCP_CAL 0x241 /* RX Dither/CP Cal */ +#define REG_RX_VCO_BIAS_1 0x242 /* RX VCO Bias 1 */ +#define REG_RX_CAL_STATUS 0x244 /* RX Cal Status */ +#define REG_RX_VCO_CAL_REF 0x245 /* RX VCO Cal Ref */ +#define REG_RX_VCO_PD_OVERRIDES 0x246 /* RX VCO Pd Overrides */ +#define REG_RX_CP_OVERRANGE_VCO_LOCK 0x247 /* RX CP Over Range/VCO Lock */ +#define REG_RX_VCO_LDO 0x248 /* RX VCO LDO */ +#define REG_RX_VCO_CAL 0x249 /* RX VCO Cal */ +#define REG_RX_LOCK_DETECT_CONFIG 0x24A /* RX Lock Detect Config */ +#define REG_RX_CP_LEVEL_DETECT 0x24B /* RX CP Level Detect */ +#define REG_RX_DSM_SETUP_0 0x24C /* RX DSM Setup 0 */ +#define REG_RX_DSM_SETUP_1 0x24D /* RX DSM Setup 1 */ +#define REG_RX_CORRECTION_WORD0 0x24E /* RX Correction Word0 */ +#define REG_RX_CORRECTION_WORD1 0x24F /* RX Correction Word1 */ +#define REG_RX_VCO_VARACTOR_CTRL_0 0x250 /* RX VCO Varactor Control 0 */ +#define REG_RX_VCO_VARACTOR_CTRL_1 0x251 /* RX VCO Varactor Control 1 */ +#define REG_RX_FAST_LOCK_SETUP 0x25A /* Rx Fast Lock Setup */ +#define REG_RX_FAST_LOCK_SETUP_INIT_DELAY 0x25B /* Rx Fast Lock Setup Init Delay */ +#define REG_RX_FAST_LOCK_PROGRAM_ADDR 0x25C /* Rx Fast Lock Program Addr */ +#define REG_RX_FAST_LOCK_PROGRAM_DATA 0x25D /* Rx Fast Lock Program Data */ +#define REG_RX_FAST_LOCK_PROGRAM_READ 0x25E /* Rx Fast Lock Program Read */ +#define REG_RX_FAST_LOCK_PROGRAM_CTRL 0x25F /* Rx Fast Lock Program Control */ +#define REG_RX_LO_GEN_POWER_MODE 0x261 /* Rx LO Gen Power Mode */ +#define REG_TX_PFD_CONFIG 0x270 /* TX PFD Config */ +#define REG_TX_INTEGER_BYTE_0 0x271 /* TX Integer Byte 0 */ +#define REG_TX_INTEGER_BYTE_1 0x272 /* TX Integer Byte 1 */ +#define REG_TX_FRACT_BYTE_0 0x273 /* TX Fractional Byte 0 */ +#define REG_TX_FRACT_BYTE_1 0x274 /* TX Fractional Byte 1 */ +#define REG_TX_FRACT_BYTE_2 0x275 /* TX Fractional Byte 2 */ +#define REG_TX_FORCE_ALC 0x276 /* TX Force ALC */ +#define REG_TX_FORCE_VCO_TUNE_0 0x277 /* TX Force VCO Tune 0 */ +#define REG_TX_FORCE_VCO_TUNE_1 0x278 /* TX Force VCO Tune 1 */ +#define REG_TX_ALCVARACT_OR 0x279 /* TX ALC/Varact or */ +#define REG_TX_VCO_OUTPUT 0x27A /* TX VCO Output */ +#define REG_TX_CP_CURRENT 0x27B /* TX CP Current */ +#define REG_TX_CP_OFFSET 0x27C /* TX CP Offset */ +#define REG_TX_CP_CONFIG 0x27D /* TX CP Config */ +#define REG_TX_LOOP_FILTER_1 0x27E /* TX Loop Filter 1 */ +#define REG_TX_LOOP_FILTER_2 0x27F /* TX Loop Filter 2 */ +#define REG_TX_LOOP_FILTER_3 0x280 /* TX Loop Filter 3 */ +#define REG_TX_DITHERCP_CAL 0x281 /* TX Dither/CP Cal */ +#define REG_TX_VCO_BIAS_1 0x282 /* TX VCO Bias 1 */ +#define REG_TX_VCO_BIAS_2 0x283 /* TX VCO Bias 2 */ +#define REG_TX_CAL_STATUS 0x284 /* TX Cal Status */ +#define REG_TX_VCO_CAL_REF 0x285 /* TX VCO Cal Ref */ +#define REG_TX_VCO_PD_OVERRIDES 0x286 /* TX VCO Pd Overrides */ +#define REG_TX_CP_OVERRANGE_VCO_LOCK 0x287 /* TX CP Over Range/VCO Lock */ +#define REG_TX_VCO_LDO 0x288 /* TX VCO LDO */ +#define REG_TX_VCO_CAL 0x289 /* TX VCO Cal */ +#define REG_TX_LOCK_DETECT_CONFIG 0x28A /* TX Lock Detect Config */ +#define REG_TX_CP_LEVEL_DETECT 0x28B /* TX CP Level Detect */ +#define REG_TX_DSM_SETUP_0 0x28C /* TX DSM Setup 0 */ +#define REG_TX_DSM_SETUP_1 0x28D /* TX DSM Setup 1 */ +#define REG_TX_CORRECTION_WORD0 0x28E /* TX Correction Word0 */ +#define REG_TX_CORRECTION_WORD1 0x28F /* TX Correction Word1 */ +#define REG_TX_VCO_VARACTOR_CTRL_0 0x290 /* TX VCO Varactor Control 0 */ +#define REG_TX_VCO_VARACTOR_CTRL_1 0x291 /* TX VCO Varactor Control 1 */ +#define REG_DCXO_COARSE_TUNE 0x292 /* DCXO Coarse Tune */ +#define REG_DCXO_FINE_TUNE_HIGH 0x293 /* DCXO Fine Tune2 */ +#define REG_DCXO_FINE_TUNE_LOW 0x294 /* DCXO Fine Tune1 */ +#define REG_DCXO_CONFIG 0x295 /* DCXO Config */ +#define REG_DCXO_TEMPCO_WRITE 0x296 /* DCXO Tempco Write */ +#define REG_DCXO_TEMPCO_READ 0x297 /* DCXO Tempco Read */ +#define REG_DCXO_TEMPCO_ADDR 0x298 /* DCXO Tempco Addr */ +#define REG_DELTA_T_READ 0x299 /* Delta T Read */ +#define REG_TX_FAST_LOCK_SETUP 0x29A /* Tx Fast Lock Setup */ +#define REG_TX_FAST_LOCK_SETUP_INIT_DELAY 0x29B /* Tx Fast Lock Setup Init Delay */ +#define REG_TX_FAST_LOCK_PROGRAM_ADDR 0x29C /* Tx Fast Lock Program Addr */ +#define REG_TX_FAST_LOCK_PROGRAM_DATA 0x29D /* Tx Fast Lock Program Data */ +#define REG_TX_FAST_LOCK_PROGRAM_READ 0x29E /* Tx Fast Lock Program Read */ +#define REG_TX_FAST_LOCK_PROGRAM_CTRL 0x29F /* Tx Fast Lock Program Ctrl */ +#define REG_TX_LO_GEN_POWER_MODE 0x2A1 /* Tx LO Gen Power Mode */ +#define REG_BANDGAP_CONFIG0 0x2A6 /* Bandgap Config0 */ +#define REG_BANDGAP_CONFIG1 0x2A8 /* Bandgap Config1 */ +#define REG_REF_DIVIDE_CONFIG_1 0x2AB /* Ref Divide Config 1 */ +#define REG_REF_DIVIDE_CONFIG_2 0x2AC /* Ref Divide Config 2 */ +#define REG_GAIN_RX1 0x2B0 /* Gain Rx1 */ +#define REG_LPF_GAIN_RX1 0x2B1 /* LPF Gain Rx1 */ +#define REG_DIG_GAIN_RX1 0x2B2 /* Dig gain Rx1 */ +#define REG_FAST_ATTACK_STATE 0x2B3 /* Fast Attack State */ +#define REG_SLOW_LOOP_STATE 0x2B4 /* Slow Loop State */ +#define REG_GAIN_RX2 0x2B5 /* Gain Rx2 */ +#define REG_LPF_GAIN_RX2 0x2B6 /* LPF Gain Rx2 */ +#define REG_DIG_GAIN_RX2 0x2B7 /* Dig Gain Rx2 */ +#define REG_OVRG_SIGS_RX1 0x2B8 /* Ovrg Sigs Rx1 */ +#define REG_OVRG_SIGS_RX2 0x2B9 /* Ovrg Sigs Rx2 */ +#define REG_CTRL 0x3DF /* Control */ +#define REG_BIST_CONFIG 0x3F4 /* BIST Config */ +#define REG_OBSERVE_CONFIG 0x3F5 /* Observe Config */ +#define REG_BIST_AND_DATA_PORT_TEST_CONFIG 0x3F6 /* BIST and Data Port Test Config */ +#define REG_DAC_TEST_0 0x3FC /* DAC Test 0 */ +#define REG_DAC_TEST_1 0x3FD /* DAC Test 1 */ +#define REG_DAC_TEST_2 0x3FE /* DAC Test 2 */ + +/* +* REG_SPI_CONF +*/ +#define SOFT_RESET (1 << 7) /* Soft Reset */ +#define WIRE3_SPI (1 << 6) /* 3-Wire SPI */ +#define LSB_FIRST (1 << 5) /* LSB First */ +#define _LSB_FIRST (1 << 2) /* LSB First */ +#define _WIRE3_SPI (1 << 1) /* 3-Wire SPI */ +#define _SOFT_RESET (1 << 0) /* Soft reset */ + +/* +* REG_MULTICHIP_SYNC_AND_TX_MON_CTRL +*/ +#define TX2_MONITOR_ENABLE (1 << 6) /* Tx2 Monitor Enable */ +#define TX1_MONITOR_ENABLE (1 << 5) /* Tx1 Monitor Enable */ +#define MCS_RF_ENABLE (1 << 3) /* MCS RF Enable */ +#define MCS_BBPLL_ENABLE (1 << 2) /* MCS BBPLL enable */ +#define MCS_DIGITAL_CLK_ENABLE (1 << 1) /* MCS Digital CLK Enable */ +#define MCS_BB_ENABLE (1 << 0) /* MCS BB Enable */ + +/* +* REG_TX_ENABLE_FILTER_CTRL +*/ +#define THB2_EN (1 << 3) /* THB2 Enable */ +#define THB1_EN (1 << 2) /* THB1 Enable */ +#define TX_CHANNEL_ENABLE(x) (((x) & 0x3) << 6) /* Tx channel Enable<1:0> */ +#define THB3_ENABLE_INTERP(x) (((x) & 0x3) << 4) /* THB3 Enable & Interp<1:0> */ +#define TX_FIR_ENABLE_INTERPOLATION(x) (((x) & 0x3) << 0) /* Tx FIR Enable & Interpolation<1:0> */ +#define TX_1 1 +#define TX_2 2 +#define TX_ENABLE 1 +#define TX_DISABLE 0 + +/* +* REG_RX_ENABLE_FILTER_CTRL +*/ +#define RHB2_EN (1 << 3) /* RHB2 Enable */ +#define RHB1_EN (1 << 2) /* RHB1 Enable */ +#define RX_CHANNEL_ENABLE(x) (((x) & 0x3) << 6) /* Rx channel Enable<1:0> */ +#define DEC3_ENABLE_DECIMATION(x) (((x) & 0x3) << 4) /* DEC3 Enable & Decimation<1:0> */ +#define RX_FIR_ENABLE_DECIMATION(x) (((x) & 0x3) << 0) /* Rx FIR Enable & Decimation<1:0> */ +#define RX_1 1 +#define RX_2 2 +#define RX_ENABLE 1 +#define RX_DISABLE 0 + +/* +* REG_INPUT_SELECT +*/ +#define TX_OUTPUT (1 << 6) /* TX Output */ +#define RX_INPUT(x) (((x) & 0x3F) << 0) /* RX Input <5:0> */ + +/* +* REG_RFPLL_DIVIDERS +*/ +#define TX_VCO_DIVIDER(x) (((x) & 0xF) << 4) /* TX VCO Divider<3:0> */ +#define RX_VCO_DIVIDER(x) (((x) & 0xF) << 0) /* RX VCO Divider<3:0> */ + +/* +* REG_RX_CLOCK_DATA_DELAY +*/ +#define DATA_CLK_DELAY(x) (((x) & 0xF) << 4) /* DATA_CLK Delay<3:0> */ +#define RX_DATA_DELAY(x) (((x) & 0xF) << 0) /* Rx Data Delay <3:0> */ + +/* +* REG_TX_CLOCK_DATA_DELAY +*/ +#define FB_CLK_DELAY(x) (((x) & 0xF) << 4) /* FB_CLK Delay<3:0> */ +#define TX_DATA_DELAY(x) (((x) & 0xF) << 0) /* Tx Data Delay <3:0> */ + +/* +* REG_CLOCK_ENABLE +*/ +#define XO_BYPASS (1 << 4) /* XO Bypass */ +#define DIGITAL_POWER_UP (1 << 2) /* Digital Power Up */ +#define CLOCK_ENABLE_DFLT (1 << 1) /* Set to 1 */ +#define BBPLL_ENABLE (1 << 0) /* BBPLL Enable */ + +/* +* REG_BBPLL +*/ +#define CLKOUT_ENABLE (1 << 4) /* CLKOUT Enable */ +#define DAC_CLK_DIV2 (1 << 3) /* DAC Clk div2 */ +#define CLKOUT_SELECT(x) (((x) & 0x7) << 5) /* CLKOUT Select<2:0> */ +#define BBPLL_DIVIDER(x) (((x) & 0x7) << 0) /* BBPLL Divider <2:0> */ + +/* +* REG_START_TEMP_READING +*/ +#define START_TEMP_READING (1 << 0) /* Start Temp Reading */ + +/* +* REG_TEMP_SENSE2 +*/ +#define TEMP_SENSE_PERIODIC_ENABLE (1 << 0) /* Temp Sense Periodic Enable */ +#define MEASUREMENT_TIME_INTERVAL(x) (((x) & 0x7F) << 1) /* Measurement Time Interval<6:0> */ + +/* +* REG_TEMP_SENSOR_CONFIG +*/ +#define TEMP_SENSOR_DECIMATION(x) (((x) & 0x7) << 0) /* Temp Sensor Decimation<2:0> */ + +/* +* REG_PARALLEL_PORT_CONF_1 +*/ +#define PP_TX_SWAP_IQ (1 << 7) /* PP Tx Swap IQ */ +#define PP_RX_SWAP_IQ (1 << 6) /* PP Rx Swap IQ */ +#define TX_CHANNEL_SWAP (1 << 5) /* Tx Channel swap */ +#define RX_CHANNEL_SWAP (1 << 4) /* Rx Channel swap */ +#define RX_FRAME_PULSE_MODE (1 << 3) /* Rx Frame Pulse Mode */ +#define R2T2_TIMING (1 << 2) /* 2R2T Timing */ +#define INVERT_DATA_BUS (1 << 1) /* Invert data bus */ +#define INVERT_DATA_CLK (1 << 0) /* Invert DATA CLK */ + +/* +* REG_PARALLEL_PORT_CONF_2 +*/ +#define FDD_ALT_WORD_ORDER (1 << 7) /* FDD Alt Word Order */ +#define INVERT_RX1 (1 << 6) /* Invert Rx1 */ +#define INVERT_RX2 (1 << 5) /* Invert Rx2 */ +#define INVERT_TX1 (1 << 4) /* Invert Tx1 */ +#define INVERT_TX2 (1 << 3) /* Invert Tx2 */ +#define INVERT_RX_FRAME (1 << 2) /* Invert Rx Frame */ +#define DELAY_RX_DATA(x) (((x) & 0x3) << 0) /* Delay Rx Data<1:0> */ + +/* +* REG_PARALLEL_PORT_CONF_3 +*/ +#define FDD_RX_RATE_2TX_RATE (1 << 7) /* FDD Rx Rate = 2*Tx Rate */ +#define SWAP_PORTS (1 << 6) /* Swap Ports */ +#define SINGLE_DATA_RATE (1 << 5) /* Single Data Rate */ +#define LVDS_MODE (1 << 4) /* LVDS Mode */ +#define HALF_DUPLEX_MODE (1 << 3) /* Half Duplex Mode */ +#define SINGLE_PORT_MODE (1 << 2) /* Single Port Mode */ +#define FULL_PORT (1 << 1) /* Full Port */ +#define FULL_DUPLEX_SWAP_BITS (1 << 0) /* Full Duplex Swap Bits */ + +/* +* REG_ENSM_MODE +*/ +#define FDD_MODE (1 << 0) /* FDD Mode */ + +/* +* REG_ENSM_CONFIG_1 +*/ +#define ENABLE_RX_DATA_PORT_FOR_CAL (1 << 7) /* Enable Rx Data Port for Cal */ +#define FORCE_RX_ON (1 << 6) /* Force Rx On */ +#define FORCE_TX_ON (1 << 5) /* Force Tx On */ +#define ENABLE_ENSM_PIN_CTRL (1 << 4) /* Enable ENSM Pin Control */ +#define LEVEL_MODE (1 << 3) /* Level Mode */ +#define FORCE_ALERT_STATE (1 << 2) /* Force Alert State */ +#define AUTO_GAIN_LOCK (1 << 1) /* Auto Gain Lock */ +#define TO_ALERT (1 << 0) /* To Alert */ + +/* +* REG_ENSM_CONFIG_2 +*/ +#define FDD_EXTERNAL_CTRL_ENABLE (1 << 7) /* FDD External Control Enable */ +#define POWER_DOWN_RX_SYNTH (1 << 6) /* Power Down Rx Synth */ +#define POWER_DOWN_TX_SYNTH (1 << 5) /* Power Down Tx Synth */ +#define TXNRX_SPI_CTRL (1 << 4) /* TXNRX SPI Control */ +#define SYNTH_ENABLE_PIN_CTRL_MODE (1 << 3) /* Synth Enable Pin Control Mode */ +#define DUAL_SYNTH_MODE (1 << 2) /* Dual Synth Mode */ +#define RX_SYNTH_READY_MASK (1 << 1) /* Rx Synth Ready Mask */ +#define TX_SYNTH_READY_MASK (1 << 0) /* Tx Synth Ready Mask */ + +/* +* REG_CALIBRATION_CTRL +*/ +#define RX_BB_TUNE_CAL (1 << 7) /* Rx BB Tune */ +#define TX_BB_TUNE_CAL (1 << 6) /* Tx BB Tune */ +#define RX_QUAD_CAL (1 << 5) /* Rx Quad Cal */ +#define TX_QUAD_CAL (1 << 4) /* Tx Quad Cal */ +#define RX_GAIN_STEP_CAL (1 << 3) /* Rx Gain Step Cal */ +#define TXMON_CAL (1 << 2) +#define RFDC_CAL (1 << 1) /* DC Cal RF Start */ +#define BBDC_CAL (1 << 0) /* DC cal BB Start */ + + +/* +* REG_STATE +*/ +#define CALIBRATION_SEQUENCE_STATE(x) (((x) & 0xF) << 4) /* Calibration Sequence State<3:0> */ +#define ENSM_STATE(x) (((x) & 0xF) << 0) /* ENSM State<3:0> */ +#define ENSM_STATE_SLEEP_WAIT 0x0 +#define ENSM_STATE_ALERT 0x5 +#define ENSM_STATE_TX 0x6 +#define ENSM_STATE_TX_FLUSH 0x7 +#define ENSM_STATE_RX 0x8 +#define ENSM_STATE_RX_FLUSH 0x9 +#define ENSM_STATE_FDD 0xA +#define ENSM_STATE_FDD_FLUSH 0xB +#define ENSM_STATE_INVALID 0xFF +#define ENSM_STATE_SLEEP 0x80 + +/* +* REG_AUXDAC_2_WORD +*/ +#define AUXDAC_2_WORD_MSB(x) (((x) & 0x3F) << 2) /* AuxDAC 2 Word<9:2> */ +#define AUXDAC_1_WORD(x) (((x) & 0x3) << 0) /* AuxDAC 1 Word <1:0> */ + +/* +* REG_AUXDAC_1_CONFIG +*/ +#define COMP_CTRL_1 (1 << 5) /* Comp Ctrl 1 */ +#define AUXDAC1_STP_FACTOR (1 << 4) /* AuxDAC1 Step Factor */ +#define AUXDAC_1_VREF(x) (((x) & 0x3) << 2) /* AuxDAC 1 Vref<1:0> */ +#define AUXDAC_1_WORD_LSB(x) (((x) & 0x3) << 0) /* AuxDAC 2 Word <1:0> */ + +/* +* REG_AUXDAC_2_CONFIG +*/ +#define COMP_CTRL_2 (1 << 5) /* Comp Ctrl 2 */ +#define AUXDAC2_STP_FACTOR (1 << 4) /* AuxDAC2 Step Factor */ +#define AUXDAC_2_VREF(x) (((x) & 0xF) << 2) /* AuxDAC 2 Vref<1:0> */ +#define AUXDAC_2_WORD_LSB(x) (((x) & 0x3) << 0) /* AuxDAC 2 Word <1:0> */ + +/* +* REG_AUXADC_CLOCK_DIVIDER +*/ +#define AUXADC_CLOCK_DIVIDER(x) (((x) & 0x3F) << 0) /* AuxADC Clock Divider<5:0> */ + +/* +* REG_AUXADC_CONFIG +*/ +#define AUXADC_POWER_DOWN (1 << 0) /* AuxADC Power Down */ +#define AUX_ADC_DECIMATION(x) (((x) & 0x7) << 1) /* Aux ADC Decimation<2:0> */ + +/* +* REG_AUXADC_LSB +*/ +#define AUXADC_WORD_LSB(x) (((x) & 0xF) << 0) /* AuxADC Word LSB<3:0> */ + +/* +* REG_AUTO_GPO +*/ +#define GPO_ENABLE_AUTO_RX(x) (((x) & 0xF) << 4) /* GPO Enable Auto Rx<3:0> */ +#define GPO_ENABLE_AUTO_TX(x) (((x) & 0xF) << 0) /* GPO Enable Auto Tx<3:0> */ + +/* +* REG_AGC_ATTACK_DELAY +*/ +#define INVERT_BYPASSED_LNA_POLARITY (1 << 6) /* Invert Bypassed LNA Polarity */ +#define AGC_ATTACK_DELAY(x) (((x) & 0x3F) << 0) /* AGC Attack Delay<5:0> */ + +/* +* REG_AUXDAC_ENABLE_CTRL +*/ +#define AUXDAC_MANUAL_BAR(x) (((x) & 0x3) << 6) /* AuxDac Manual Bar<1:0> */ +#define AUXDAC_AUTO_TX_BAR(x) (((x) & 0x3) << 4) /* AuxDAC Auto Tx Bar<1:0> */ +#define AUXDAC_AUTO_RX_BAR(x) (((x) & 0x3) << 2) /* AuxDAC Auto Rx Bar<1:0> */ +#define AUXDAC_INIT_BAR(x) (((x) & 0x3) << 0) /* AuxDAC Init Bar<1:0> */ + +/* +* REG_EXTERNAL_LNA_CTRL +*/ +#define AUXDAC_MANUAL_SELECT (1 << 7) /* AuxDAC Manual Select */ +#define EXTERNAL_LNA2_CTRL (1 << 6) /* External LNA2 control */ +#define EXTERNAL_LNA1_CTRL (1 << 5) /* External LNA1 control */ +#define GPO_MANUAL_SELECT (1 << 4) /* GPO manual select */ +#define OPEN(x) (((x) & 0xF) << 0) /* Open<3:0> */ + +/* +* REG_GPO_FORCE_AND_INIT +*/ +#define GPO_MANUAL_CTRL(x) (((x) & 0xF) << 4) /* GPO Manual Control<3:0> */ +#define GPO_INIT_STATE(x) (((x) & 0xF) << 0) /* GPO Init State<3:0> */ + +/* +* REG_CTRL_OUTPUT_ENABLE +*/ +#define EN_CTRL7 (1 << 7) /* En ctrl7 */ +#define EN_CTRL6 (1 << 6) /* En ctrl6 */ +#define EN_CTRL5 (1 << 5) /* En ctrl5 */ +#define EN_CTRL4 (1 << 4) /* En ctrl4 */ +#define EN_CTRL3 (1 << 3) /* En ctrl3 */ +#define EN_CTRL2 (1 << 2) /* En ctrl2 */ +#define EN_CTRL1 (1 << 1) /* En ctrl1 */ +#define EN_CTRL0 (1 << 0) /* En ctrl0 */ + +/* +* REG_PRODUCT_ID +*/ +#define PRODUCT_ID_MASK 0xF8 +#define PRODUCT_ID_9361 0x08 +#define REV_MASK 0x07 + +/* +* REG_REFERENCE_CLOCK_CYCLES +*/ +#define REFERENCE_CLOCK_CYCLES_PER_US(x) (((x) & 0x7F) << 0) /* Reference Clock Cycles per us<6:0> */ + +/* +* REG_DIGITAL_IO_CTRL +*/ +#define CLK_OUT_DRIVE (1 << 7) /* CLK Out Drive */ +#define DATACLK_DRIVE (1 << 6) /* DATACLK drive */ +#define DATA_PORT_DRIVE (1 << 2) /* Data Port Drive */ +#define DATACLK_SLEW(x) (((x) & 0x3) << 4) /* DATACLK slew <1:0> */ +#define DATA_PORT_SLEW(x) (((x) & 0x3) << 0) /* Data Port Slew<1:0> */ + +/* +* REG_LVDS_BIAS_CTRL +*/ +#define RX_ON_CHIP_TERM (1 << 5) /* Rx On Chip Term */ +#define LVDS_BYPASS_BIAS_R (1 << 4) /* Bypass Bias R */ +#define LVDS_TX_LO_VCM (1 << 3) /* LVDS Tx LO VCM */ +#define CLK_OUT_SLEW(x) (((x) & 0x3) << 6) /* CLK Out Slew<1:0> */ +#define LVDS_BIAS(x) (((x) & 0x7) << 0) /* LVDS Bias <2:0> */ + +/* +* REG_SDM_CTRL_1 +*/ +#define INIT_BB_FO_CAL (1 << 2) /* Init BB FO CAL */ +#define BBPLL_RESET_BAR (1 << 0) /* BBPLL Reset Bar */ + +/* +* REG_CLOCK_CTRL +*/ +#define REF_FREQ_SCALER(x) (((x) & 0x3) << 0) /* Ref Frequency Scaler */ + +/* +* REG_CP_CURRENT +*/ +#define CHARGE_PUMP_CURRENT(x) (((x) & 0x3F) << 0) /* Charge Pump Current<5:0> */ + +/* +* REG_CP_BLEED_CURRENT +*/ +#define MCS_REFCLK_SCALE_EN (1 << 7) /* MCS refclk Scale En */ + +/* +* REG_LOOP_FILTER_1 +*/ +#define C1_WORD(x) (((x) & 0x7) << 5) /* C1 Word<2:0> */ +#define R1_WORD(x) (((x) & 0x1F) << 0) /* R1 Word<4:0> */ + +/* +* REG_LOOP_FILTER_2 +*/ +#define R2_WORD (1 << 7) /* R2 Word<0> */ +#define C2_WORD(x) (((x) & 0x1F) << 2) /* C2 Word<4:0> */ +#define C1_WORD_LSB(x) (((x) & 0x3) << 0) /* C1 Word<4:3> */ + +/* +* REG_LOOP_FILTER_3 +*/ +#define BYPASS_C3 (1 << 7) /* Bypass C3 */ +#define BYPASS_R2 (1 << 6) /* Bypass R2 */ +#define C3_WORD(x) (((x) & 0xF) << 2) /* C3 Word<3:0> */ +#define R2_WORD_LSB(x) (((x) & 0x3) << 0) /* R2 Word<2:1> */ + +/* +* REG_VCO_CTRL +*/ +#define FREQ_CAL_ENABLE (1 << 7) /* Freq Cal Enable */ +#define FREQ_CAL_RESET (1 << 4) /* Freq Cal Reset */ +#define FREQ_CAL_COUNT_LENGTH(x) (((x) & 0x3) << 5) /* Freq Cal Count Length<1:0> */ + +/* +* REG_SDM_CTRL +*/ +#define CAL_CLOCK_DIV_4 (1 << 4) /* Cal Clock div 4 */ + +/* +* REG_RX_SYNTH_POWER_DOWN_OVERRIDE +*/ +#define RX_LO_POWER_DOWN (1 << 4) /* Rx LO Power Down */ +#define RX_SYNTH_VCO_ALC_POWER_DOWN (1 << 3) /* Rx Synth VCO ALC Power Down */ +#define RX_SYNTH_PTAT_POWER_DOWN (1 << 2) /* Rx Synth PTAT Power Down */ +#define RX_SYNTH_VCO_POWER_DOWN (1 << 1) /* Rx Synth VCO Power Down */ +#define RX_SYNTH_VCO_LDO_POWER_DOWN (1 << 0) /* Rx Synth VCO LDO Power Down */ + +/* +* REG_TX_SYNTH_POWER_DOWN_OVERRIDE +*/ +#define TX_LO_POWER_DOWN (1 << 4) /* Tx LO Power Down */ +#define TX_SYNTH_VCO_ALC_POWER_DOWN (1 << 3) /* Tx Synth VCO ALC Power Down */ +#define TX_SYNTH_PTAT_POWER_DOWN (1 << 2) /* Tx Synth PTAT Power Down */ +#define TX_SYNTH_VCO_POWER_DOWN (1 << 1) /* Tx Synth VCO Power Down */ +#define TX_SYNTH_VCO_LDO_POWER_DOWN (1 << 0) /* Tx Synth VCO LDO Power Down */ + +/* +* REG_RX_ANALOG_POWER_DOWN_OVERRIDE_1 +*/ +#define RX_OFFSET_DAC_CGIN_POWER_DOWN(x) (((x) & 0x3) << 6) /* Rx Offset DAC CGin Power Down<1:0> */ +#define RX_LMT_OVERLOAD_POWER_DOWN(x) (((x) & 0x3) << 4) /* Rx LMT Overload Power Down<1:0> */ +#define RX_MIXER_GM_POWER_DOWN(x) (((x) & 0x3) << 2) /* Rx Mixer Gm Power Down<1:0> */ +#define RX_CGB_POWER_DOWN(x) (((x) & 0x3) << 0) /* Rx CGB Power Down<1:0> */ + +/* +* REG_RX_ANALOG_POWER_DOWN_OVERRIDE_2 +*/ +#define RX_BBF_POWER_DOWN(x) (((x) & 0x3) << 6) /* Rx BBF Power Down<1:0> */ +#define RX_TIA_POWER_DOWN(x) (((x) & 0x3) << 4) /* Rx TIA Power Down<1:0> */ +#define RX_MIXER_POWER_DOWN(x) (((x) & 0x3) << 2) /* Rx Mixer Power Down<1:0> */ +#define RX_OFFSET_DAC_CGOUT_POWER_DOWN(x) (((x) & 0x3) << 0) /* Rx Offset DAC CGOut Power Down<1:0> */ + +/* +* REG_TX_ANALOG_POWER_DOWN_OVERRIDE_1 +*/ +#define TX_SECONDARY_FILTER_POWER_DOWN(x) (((x) & 0x3) << 6) /* Tx Secondary Filter Power Down<1:0> */ +#define TX_BBF_POWER_DOWN(x) (((x) & 0x3) << 4) /* Tx BBF Power Down<1:0> */ +#define TX_DAC_POWER_DOWN(x) (((x) & 0x3) << 2) /* Tx DAC Power Down<1:0> */ +#define TX_DAC_BIAS_POWER_DOWN(x) (((x) & 0x3) << 0) /* Tx DAC Bias Power Down<1:0> */ + +/* +* REG_ANALOG_POWER_DOWN_OVERRIDE +*/ +#define RX_EXT_VCO_BUFFER_POWER_DOWN (1 << 5) /* Rx Ext VCO Buffer Power Down */ +#define TX_EXT_VCO_BUFFER_POWER_DOWN (1 << 4) /* Tx Ext VCO Buffer Power Down */ +#define TX_MONITOR_POWER_DOWN(x) (((x) & 0x3) << 2) /* Tx Monitor Power Down<1:0> */ +#define TX_UPCONVERTER_POWER_DOWN(x) (((x) & 0x3) << 0) /* Tx Upconverter Power Down<1:0> */ + +/* +* REG_MISC_POWER_DOWN_OVERRIDE +*/ +#define RX_LNA_POWER_DOWN (1 << 6) /* Rx LNA Power Down */ +#define DCXO_POWER_DOWN (1 << 1) /* DCXO Power Down */ +#define MASTER_BIAS_POWER_DOWN (1 << 0) /* Master Bias Power Down */ +#define RX_CALIBRATION_POWER_DOWN(x) (((x) & 0x3) << 2) /* Rx Calibration Power Down<1:0> */ + +/* +* REG_CH_1_OVERFLOW +*/ +#define BBPLL_LOCK (1 << 7) /* BBPLL Lock */ +#define CH_1_INT3 (1 << 6) /* CH 1 INT3 */ +#define CH1_HB3 (1 << 5) /* CH1 HB3 */ +#define CH1_HB2 (1 << 4) /* CH1 HB2 */ +#define CH1_QEC (1 << 3) /* CH1 QEC */ +#define CH1_HB1 (1 << 2) /* CH1 HB1 */ +#define CH1_TFIR (1 << 1) /* CH1 TFIR */ +#define CH1_RFIR (1 << 0) /* CH1 RFIR */ + +/* +* REG_CH_2_OVERFLOW +*/ +#define CH2_INT3 (1 << 6) /* CH2 INT3 */ +#define CH2_HB3 (1 << 5) /* CH2 HB3 */ +#define CH2_HB2 (1 << 4) /* CH2 HB2 */ +#define CH2_QEC (1 << 3) /* CH2 QEC */ +#define CH2_HB1 (1 << 2) /* CH2 HB1 */ +#define CH2_TFIR (1 << 1) /* CH2 TFIR */ +#define CH2_RFIR (1 << 0) /* CH2 RFIR */ + +/* +* REG_TX_FILTER_CONF +*/ +#define TX_FIR_GAIN_6DB (1 << 0) /* Filter Gain */ +#define FIR_START_CLK (1 << 1) /* Start Tx/Rx Clock */ +#define FIR_WRITE (1 << 2) /* Write Tx/Rx */ +#define FIR_SELECT(x) (((x) & 0x3) << 3) /* Select Tx/Rx CH<1:0> */ +#define FIR_NUM_TAPS(x) (((x) & 0x7) << 5) /* Number of Taps<2:0> */ + +/* +* REG_TX_MON_LOW_GAIN +*/ +#define TX_MON_TRACK (1 << 5) /* Tx Mon Track */ +#define TX_MON_LOW_GAIN(x) (((x) & 0x1F) << 0) /* Tx Mon Low Gain<4:0> */ + +/* +* REG_TX_MON_HIGH_GAIN +*/ +#define TX_MON_HIGH_GAIN(x) (((x) & 0x1F) << 0) /* Tx Mon High Gain<4:0> */ + +/* +* REG_TX_LEVEL_THRESH +*/ +#define TX_LEVEL_THRESH(x) (((x) & 0x3F) << 2) /* Tx Level Threshold<5:0> */ +#define TX_MON_DELAY_COUNTER(x) (((x) & 0x3) << 0) /* Tx Mon Delay Counter<9:8> */ + +/* +* REG_TX_RSSI_LSB +*/ +#define TX_RSSI_2 (1 << 1) /* Tx RSSI 2<0> */ +#define TX_RSSI_1 (1 << 0) /* TX RSSI 1<0> */ + +/* +* REG_TPM_MODE_ENABLE +*/ +#define TX2_MON_ENABLE (1 << 7) /* Tx2 Monitor Enable */ +#define TX1_MON_ENABLE (1 << 5) /* Tx1 Monitor Enable */ +#define ONE_SHOT_MODE (1 << 6) /* One Shot Mode */ +#define TX_MON_DURATION(x) (((x) & 0xF) << 0) /* Tx Mon Duration<3:0> */ + +/* +* REG_TX_MON_1_CONFIG +*/ +#define TX_MON_1_LO_CM(x) (((x) & 0x3F) << 2) /* Tx Mon 1 LO CM<5:0> */ +#define TX_MON_1_GAIN(x) (((x) & 0x3) << 0) /* Tx Mon 1 Gain<1:0> */ + +/* +* REG_TX_MON_2_CONFIG +*/ +#define TX_MON_2_LO_CM(x) (((x) & 0x3F) << 2) /* Tx Mon 2 LO CM<5:0> */ +#define TX_MON_2_GAIN(x) (((x) & 0x3) << 0) /* Tx Mon 2 Gain<1:0> */ + +/* +* REG_TX1_ATTEN_1 +*/ +#define TX_1_ATTEN (1 << 0) /* Tx 1 Atten <8> */ + +/* +* REG_TX2_ATTEN_1 +*/ +#define TX_2_ATTEN (1 << 0) /* Tx 2 Atten <8> */ + +/* +* REG_TX_ATTEN_OFFSET +*/ +#define MASK_CLR_ATTEN_UPDATE (1 << 6) /* Mask Clr Atten Update */ +#define TX_ATTEN_OFFSET(x) (((x) & 0x3F) << 0) /* Tx Atten Offset<5:0> */ + +/* +* REG_TX1_DIG_ATTEN +*/ +#define SEL_TX1_TX2 (1 << 6) /* Sel Tx1 & Ttx2 */ + +/* +* REG_TX2_DIG_ATTEN +*/ +#define IMMEDIATELY_UPDATE_TPC_ATTEN (1 << 6) /* Immediately Update TPC Atten */ + +/* +* REG_TX1_SYMBOL_ATTEN +*/ +#define TX_1_SYMBOL_ATTEN(x) (((x) & 0x7F) << 0) /* Tx 1 Symbol Attenuation<6:0> */ + +/* +* REG_TX2_SYMBOL_ATTEN +*/ +#define TX_2_SYMBOL_ATTEN(x) (((x) & 0x7F) << 0) /* Tx 2 Symbol Attenuation<6:0> */ + +/* +* REG_TX_SYMBOL_ATTEN_CONFIG +*/ +#define USE_TX1_PIN_SYMBOL_ATTEN (1 << 3) /* Use Tx1 Pin & Symbol Atten */ +#define USE_CTRL_IN_FOR_SYMBOL_ATTEN (1 << 1) /* Use CTRL IN for symbol Atten */ +#define ENABLE_SYMBOL_ATTEN (1 << 0) /* Enable Symbol Atten */ + +/* +* REG_TX_FORCE_BITS +*/ +#define FORCE_OUT_2_TX2_OFFSET (1 << 7) /* Force Out 2 Tx2 Offset */ +#define FORCE_OUT_2_TX1_OFFSET (1 << 6) /* Force Out 2 Tx1 Offset */ +#define FORCE_OUT_2_TX2_PHASE_GAIN (1 << 5) /* Force Out 2 Tx2 Phase & Gain */ +#define FORCE_OUT_2_TX1_PHASE_GAIN (1 << 4) /* Force Out 2 Tx1 Phase & Gain */ +#define FORCE_OUT_1_TX2_OFFSET (1 << 3) /* Force Out 1 Tx2 Offset */ +#define FORCE_OUT_1_TX1_OFFSET (1 << 2) /* Force Out 1 Tx1 Offset */ +#define FORCE_OUT_1_TX2_PHASE_GAIN (1 << 1) /* Force Out 1 Tx2 Phase & Gain */ +#define FORCE_OUT_1_TX1_PHASE_GAIN (1 << 0) /* Force Out 1 Tx1 Phase & Gain */ + +/* +* REG_QUAD_CAL_NCO_FREQ_PHASE_OFFSET +*/ +#define RX_NCO_FREQ(x) (((x) & 0x3) << 5) /* Rx NCO Frequency<1:0> */ +#define RX_NCO_PHASE_OFFSET(x) (((x) & 0x1F) << 0) /* Rx NCO Phase Offset<4:0> */ + +/* +* REG_QUAD_CAL_CTRL +*/ +#define FREE_RUN_ENABLE (1 << 7) /* Free Run Enable */ +#define SETTLE_MAIN_ENABLE (1 << 6) /* Settle Main Enable */ +#define DC_OFFSET_ENABLE (1 << 5) /* DC Offset Enable */ +#define GAIN_ENABLE (1 << 4) /* Gain Enable */ +#define PHASE_ENABLE (1 << 3) /* Phase Enable */ +#define QUAD_CAL_SOFT_RESET (1 << 2) /* Quad Cal Soft Reset */ +#define M_DECIM(x) (((x) & 0x3) << 0) /* M<1:0> */ + +/* +* REG_KEXP_1 +*/ +#define KEXP_TX(x) (((x) & 0x3) << 6) /* Kexp Tx<1:0> */ +#define KEXP_TX_COMP(x) (((x) & 0x3) << 4) /* Kexp Tx_comp <1:0> */ +#define KEXP_DC_I(x) (((x) & 0x3) << 2) /* Kexp DC I <1:0> */ +#define KEXP_DC_Q(x) (((x) & 0x3) << 0) /* Kexp DC Q <1:0> */ + +/* +* REG_KEXP_2 +*/ +#define INVERT_I_DATA (1 << 5) /* Invert I data */ +#define INVERT_Q_DATA (1 << 4) /* Invert Q data */ +#define TX_NCO_FREQ(x) (((x) & 0x3) << 6) /* Tx NCO frequency<1:0> */ +#define KEXP_PHASE(x) (((x) & 0x3) << 2) /* Kexp Phase <1:0> */ +#define KEXP_AMP(x) (((x) & 0x3) << 0) /* Kexp Amp <1:0> */ + +/* +* REG_QUAD_CAL_STATUS_TX1 +*/ +#define TX1_LO_CONV (1 << 1) /* Tx1 LO Conv */ +#define TX1_SSB_CONV (1 << 0) /* Tx1 SSB Conv */ +#define TX1_CONVERGENCE_COUNT(x) (((x) & 0x3F) << 2) /* Tx1 Convergence Count<5:0> */ + +/* +* REG_QUAD_CAL_STATUS_TX2 +*/ +#define TX2_LO_CONV (1 << 1) /* Tx2 LO Conv */ +#define TX2_SSB_CONV (1 << 0) /* Tx2 SSB Conv */ +#define TX2_CONVERGENCE_COUNT(x) (((x) & 0x3F) << 2) /* Tx2 Convergence Count<5:0> */ + +/* +* REG_TX_QUAD_FULL_LMT_GAIN +*/ +#define RX_FULL_TABLELMT_TABLE_GAIN(x) (((x) & 0x7F) << 0) /* RX Full table/LMT table gain<6:0> */ + +/* +* REG_SQUARER_CONFIG +*/ +#define GM_STAGE_TIME_CON_OVERRIDE (1 << 5) /* Gm Stage Time Con Override */ +#define GM_STAGE_MV_HP_POLE (1 << 4) /* Gm Stage MV HP Pole */ +#define GM_STAGE_LOWER_CM (1 << 3) /* Gm Stage Lower CM */ +#define BYPASS_BIAS_R (1 << 0) /* Bypass Bias R */ +#define VBIAS_CTRL(x) (((x) & 0x3) << 1) /* Vbias Control<1:0> */ + +/* +* REG_THRESH_ACCUM +*/ +#define THRESH_ACCUMULATOR(x) (((x) & 0xF) << 0) /* Threshold Accumulator<3:0> */ + +/* +* REG_TX_QUAD_LPF_GAIN +*/ +#define RX_LPF_GAIN(x) (((x) & 0x1F) << 0) /* RX LPF gain<4:0> */ + +/* +* REG_TXDAC_VDS_I +*/ +#define TXDAC_VDS_I(x) (((x) & 0x3F) << 0) /* TxDAC Vds I<5:0> */ + +/* +* REG_TXDAC_VDS_Q +*/ +#define TXDAC_VDS_Q(x) (((x) & 0x3F) << 0) /* TxDAC Vds Q<5:0> */ + +/* +* REG_TXDAC_GN_I +*/ +#define TXDAC_GN_I(x) (((x) & 0x3F) << 0) /* txDAC_gn_I<5:0> */ + +/* +* REG_TXDAC_GN_Q +*/ +#define TXDAC_GN_Q(x) (((x) & 0x3F) << 0) /* txDAC_gn_Q<5:0> */ + +/* +* REG_TXBBF_OPAMP_A +*/ +#define OPAMPA_OUTPUT_BIAS(x) (((x) & 0x3) << 5) /* OpAmpA Output Bias<1:0> */ +#define OPAMPA_RZ(x) (((x) & 0x3) << 3) /* OpAmpA RZ<1:0> */ +#define OPAMP_A_CC(x) (((x) & 0x7) << 0) /* OpAmp A CC<2:0> */ + +/* +* REG_TXBBF_OPAMP_B +*/ +#define OPAMPB_OUTPUT_BIAS(x) (((x) & 0x3) << 5) /* OpAmpB Output Bias<1:0> */ +#define OPAMPB_RZ(x) (((x) & 0x3) << 3) /* OpAmpB RZ<1:0> */ +#define OPAMP_B_CC(x) (((x) & 0x7) << 0) /* OpAmp B CC<2:0> */ + +/* +* REG_TX_BBF_R1 +*/ +#define OVERRIDE_ENABLE (1 << 7) /* Override enable */ +#define R1(x) (((x) & 0x1F) << 0) /* R1<4:0> */ + +/* +* REG_TX_BBF_R2 +*/ +#define R2(x) (((x) & 0x1F) << 0) /* R2<4:0> */ + +/* +* REG_TX_BBF_R3 +*/ +#define R3(x) (((x) & 0x1F) << 0) /* R3<4:0> */ + +/* +* REG_TX_BBF_R4 +*/ +#define R4(x) (((x) & 0x1F) << 0) /* R4<4:0> */ + +/* +* REG_TX_BBF_RP +*/ +#define RP(x) (((x) & 0x1F) << 0) /* Rp<4:0> */ + +/* +* REG_TX_BBF_C1 +*/ +#define C1(x) (((x) & 0x3F) << 0) /* C1<5:0> */ + +/* +* REG_TX_BBF_C2 +*/ +#define C2(x) (((x) & 0x3F) << 0) /* C2<5:0> */ + +/* +* REG_TX_BBF_CP +*/ +#define CP(x) (((x) & 0x3F) << 0) /* Cp<5:0> */ + +/* +* REG_TX_TUNE_CTRL +*/ +#define PD_TUNE (1 << 2) /* PD Tune */ +#define TUNER_RESAMPLE (1 << 1) /* Tuner Resample */ +#define TUNER_RESAMPLE_PHASE (1 << 0) /* Tuner Resample Phase */ +#define TUNE_CTRL(x) (((x) & 0x3) << 5) /* Tune Control<1:0> */ + +/* +* REG_TX_BBF_R2B +*/ +#define TX_BBF_BYPASS_BIAS_R (1 << 7) /* Bypass Bias R */ +#define R2B_OVR (1 << 5) /* R2b Ovr */ +#define R2B(x) (((x) & 0x1F) << 0) /* R2b<4:0> */ + +/* +* REG_TX_BBF_TUNE +*/ +#define BBF1_COMP_I (1 << 3) /* BBF1 Comp I */ +#define BBF1_COMP_Q (1 << 2) /* BBF1 Comp Q */ +#define BBF2_COMP_I (1 << 1) /* BBF2 Comp I */ +#define BBF2_COMP_Q (1 << 0) /* BBF2 Comp Q */ + +/* +* REG_CONFIG0 +*/ +#define BIAS(x) (((x) & 0x3) << 6) /* Bias<1:0> */ +#define RGM(x) (((x) & 0x3) << 4) /* Rgm<1:0> */ +#define CC(x) (((x) & 0x3) << 2) /* Cc<1:0> */ +#define AMPBIAS(x) (((x) & 0x3) << 0) /* AmpBias<1:0> */ + +/* +* REG_RESISTOR +*/ +#define RESISTOR(x) (((x) & 0xF) << 0) /* Resistor<3:0> */ + +/* +* REG_CAPACITOR +*/ +#define CAPACITOR(x) (((x) & 0x3F) << 0) /* Capacitor<5:0> */ + +/* +* REG_LO_CM +*/ +#define LO_COMMON_MODE(x) (((x) & 0x3) << 5) /* LO Common Mode<1:0> */ + +/* +* REG_TX_BBF_TUNE_MODE +*/ +#define EVALTIME (1 << 4) /* EvalTime */ +#define TX_BBF_TUNE_DIVIDER (1 << 0) /* TX BBF Tune Divider<8> */ +#define TUNE_COMP_MASK(x) (((x) & 0x3) << 5) /* Tune Comp Mask<1:0> */ +#define TUNER_MODE(x) (((x) & 0x7) << 1) /* Tuner Mode<2:0> */ + +/* +* REG_RX_FILTER_CONFIG +*/ +#define WRITE_RX (1 << 2) /* Write Rx */ +#define START_RX_CLOCK (1 << 1) /* Start Rx Clock */ +#define NUMBER_OF_TAPS(x) (((x) & 0x7) << 5) /* Number of Taps */ +#define SELECT_RX_CH(x) (((x) & 0x3) << 3) /* Select Rx Ch<1:0> */ + +/* +* REG_RX_FILTER_GAIN +*/ +#define FILTER_GAIN(x) (((x) & 0x3) << 0) /* Filter gain<1:0> */ + +/* +* REG_AGC_CONFIG_1 +*/ +#define DEC_PWR_FOR_LOW_PWR (1 << 7) /* Dec Pwr for Low Pwr */ +#define DEC_PWR_FOR_LOCK_LEVEL (1 << 6) /* Dec Pwr for Lock Level */ +#define DEC_PWR_FOR_GAIN_LOCK_EXIT (1 << 5) /* Dec Pwr for Gain Lock Exit */ +#define SLOW_ATTACK_HYBRID_MODE (1 << 4) /* Slow Attack Hybrid Mode */ +#define RX2_GAIN_CTRL_SETUP(x) (((x) & 0x3) << 2) /* Rx 2 Gain Control Setup<1:0> */ +#define RX1_GAIN_CTRL_SETUP(x) (((x) & 0x3) << 0) /* Rx 1 Gain Control Setup<1:0> */ +#define RX_GAIN_CTL_MASK 0x03 +#define RX2_GAIN_CTRL_SHIFT 2 +#define RX1_GAIN_CTRL_SHIFT 0 +#define RX_GAIN_CTL_MGC 0x00 +#define RX_GAIN_CTL_AGC_FAST_ATK 0x01 +#define RX_GAIN_CTL_AGC_SLOW_ATK 0x02 +#define RX_GAIN_CTL_AGC_SLOW_ATK_HYBD 0x03 + +/* +* REG_AGC_CONFIG_2 +*/ +#define AGC_SOFT_RESET (1 << 7) /* Soft Reset */ +#define AGC_GAIN_UNLOCK_CTRL (1 << 6) /* Gain Unlock Control */ +#define AGC_USE_FULL_GAIN_TABLE (1 << 3) /* Use Full Gain Table */ +#define DIG_GAIN_EN (1 << 2) /* Enable Digital Gain */ +#define MAN_GAIN_CTRL_RX2 (1 << 1) /* Manual Gain Control Rx 2 */ +#define MAN_GAIN_CTRL_RX1 (1 << 0) /* Manual Gain Control Rx 1 */ + +/* +* REG_AGC_CONFIG_3 +*/ +#define INCDEC_LMT_GAIN (1 << 4) /* Inc/Dec LMT Gain */ +#define USE_AGC_FOR_LMTLPF_GAIN (1 << 3) /* Use AGC for LMT/LPF Gain */ +#define MANUAL_INCR_STEP_SIZE(x) (((x) & 0x7) << 5) /* Manual (CTRL_IN) Incr Gain Step Size<2:0> */ +#define ADC_OVERRANGE_SAMPLE_SIZE(x) (((x) & 0x7) << 0) /* ADC Overrange Sample Size<2:0> */ + +/* +* REG_MAX_LMT_FULL_GAIN +*/ +#define MAXIMUM_FULL_TABLELMT_TABLE_INDEX(x) (((x) & 0x7F) << 0) /* Maximum Full Table/LMT Table Index<6:0> */ + +/* +* REG_PEAK_WAIT_TIME +*/ +#define MANUAL_CTRL_IN_DECR_GAIN_STP_SIZE(x) (((x) & 0x7) << 5) /* Manual (CTRL_IN) Decr Gain Step Size<2:0> */ +#define PEAK_OVERLOAD_WAIT_TIME(x) (((x) & 0x1F) << 0) /* Peak Overload Wait Time<4:0> */ + +/* +* REG_DIGITAL_GAIN +*/ +#define DIG_GAIN_STP_SIZE(x) (((x) & 0x7) << 5) /* Dig Gain Step Size<2:0> */ +#define MAXIMUM_DIGITAL_GAIN(x) (((x) & 0x1F) << 0) /* Maximum Digital Gain<4:0> */ + +/* +* REG_AGC_LOCK_LEVEL +*/ +#define ENABLE_DIG_SAT_OVRG (1 << 7) /* Enable Dig Sat Ovrg */ +#define AGC_LOCK_LEVEL_FAST_AGC_INNER_HIGH_THRESH_SLOW(x) (((x) & 0x7F) << 0) /* AGC Lock Level (Fast)/ AGC Inner High Threshold (Slow) <6:0> */ + +/* +* REG_GAIN_STP_CONFIG1 +*/ +#define LMT_DETECTOR_SETTLING_TIME(x) (((x) & 0x7) << 5) /* LMT Detector Settling Time<2:0> */ +#define DEC_STP_SIZE_FOR_LARGE_LMT_OVERLOAD(x) (((x) & 0x7) << 2) /* Dec Step Size for: Large LMT Overload/ Full Table Case #3 <2:0> */ +#define ADC_NOISE_CORRECTION_FACTOR(x) (((x) & 0x3) << 0) /* ADC Noise Correction Factor<1:0> */ + +/* +* REG_GAIN_STP_CONFIG_2 +*/ +#define DECREMENT_STP_SIZE_FOR_SMALL_LPF_GAIN_CHANGE(x) (((x) & 0x7) << 4) /* Fast Attack Only. Decrement Step Size for: Small LPF Gain Change / Full Table Case #2 <2:0> */ +#define LARGE_LPF_GAIN_STEP(x) (((x) & 0xF) << 0) /* Decrement Step Size for: Large LPF Gain Change / Full Table Case #1<3:0> */ + +/* +* REG_SMALL_LMT_OVERLOAD_THRESH +*/ +#define FORCE_PD_RESET_RX2 (1 << 7) /* Force PD Reset Rx2 */ +#define FORCE_PD_RESET_RX1 (1 << 6) /* Force PD Reset Rx1 */ +#define SMALL_LMT_OVERLOAD_THRESH(x) (((x) & 0x3F) << 0) /* Small LMT Overload Threshold<5:0> */ + +/* +* REG_LARGE_LMT_OVERLOAD_THRESH +*/ +#define LARGE_LMT_OVERLOAD_THRESH(x) (((x) & 0x3F) << 0) /* Large LMT Overload Threshold<5:0> */ + +/* +* REG_RX1_MANUAL_LMT_FULL_GAIN +*/ +#define POWER_MEAS_IN_STATE_5_MSB (1 << 7) /* Power Meas in State 5 <3> */ +#define RX1_MANUAL_FULL_TABLE_LMT_TABLE_GAIN_INDEX(x) (((x) & 0x7F) << 0) /* Rx1 Manual Full table/LMT table Gain Index<6:0> */ +#define RX_FULL_TBL_IDX_MASK RX1_MANUAL_FULL_TABLE_LMT_TABLE_GAIN_INDEX(~0) + +/* +* REG_RX1_MANUAL_LPF_GAIN +*/ +#define POWER_MEAS_IN_STATE_5(x) (((x) & 0x7) << 5) /* Power Meas in State 5<2:0> */ +#define RX1_MANUAL_LPF_GAIN(x) (((x) & 0x1F) << 0) /* Rx1 Manual LPF Gain <4:0> */ +#define RX_LPF_IDX_MASK RX1_MANUAL_LPF_GAIN(~0) + +/* +* REG_RX1_MANUAL_DIGITALFORCED_GAIN +*/ +#define FORCE_RX1_DIGITAL_GAIN (1 << 5) /* Force Rx1 Digital Gain */ +#define RX1_MANUALFORCED_DIGITAL_GAIN(x) (((x) & 0x1F) << 0) /* Rx1 Manual/Forced Digital Gain<4:0> */ +#define RX_DIGITAL_IDX_MASK RX1_MANUALFORCED_DIGITAL_GAIN(~0) +/* +* REG_RX2_MANUAL_LMT_FULL_GAIN +*/ +#define RX2_MANUAL_FULL_TABLE_LMT_TABLE_GAIN_INDEX(x) (((x) & 0x7F) << 0) /* Rx2 Manual Full table/ LMT table Gain Index<6:0> */ + +/* +* REG_RX2_MANUAL_LPF_GAIN +*/ +#define RX2_MANUAL_LPF_GAIN(x) (((x) & 0x1F) << 0) /* Rx2 Manual LPF Gain<4:0> */ + +/* +* REG_RX2_MANUAL_DIGITALFORCED_GAIN +*/ +#define FORCE_RX2_DIGITAL_GAIN (1 << 5) /* Force Rx2 Digital Gain */ +#define RX2_MANUALFORCED_DIGITAL_GAIN(x) (((x) & 0x1F) << 0) /* Rx2 Manual/Forced Digital Gain<4:0> */ + +/* +* REG_FAST_CONFIG_1 +*/ +#define ENABLE_GAIN_INC_AFTER_GAIN_LOCK (1 << 7) /* Enable Gain Inc after Gain Lock */ +#define GOTO_OPT_GAIN_IF_ENERGY_LOST_OR_EN_AGC_HIGH (1 << 6) /* Goto Opt Gain if Energy Lost or EN_AGC High */ +#define GOTO_SET_GAIN_IF_EN_AGC_HIGH (1 << 5) /* Goto Set Gain if EN_AGC High */ +#define GOTO_SET_GAIN_IF_EXIT_RX_STATE (1 << 4) /* Goto Set Gain if Exit Rx State */ +#define DONT_UNLOCK_GAIN_IF_ENERGY_LOST (1 << 3) /* Don't Unlock Gain if Energy Lost */ +#define GOTO_OPTIMIZED_GAIN_IF_EXIT_RX_STATE (1 << 2) /* Goto Optimized Gain if Exit Rx State */ +#define DONT_UNLOCK_GAIN_IF_LG_ADC_OR_LMT_OVRG (1 << 1) /* Don't Unlock Gain If Lg ADC or LMT Ovrg */ +#define ENABLE_INCR_GAIN (1 << 0) /* Enable Incr Gain */ + +/* +* REG_FAST_CONFIG_2_SETTLING_DELAY +*/ +#define USE_LAST_LOCK_LEVEL_FOR_SET_GAIN (1 << 7) /* Use Last Lock Level for Set Gain */ +#define ENABLE_LMT_GAIN_INC_FOR_LOCK_LEVEL (1 << 6) /* Enable LMT Gain Inc for Lock Level */ +#define GOTO_MAX_GAIN_OR_OPT_GAIN_IF_EN_AGC_HIGH (1 << 5) /* Goto Max Gain or Opt Gain if EN_AGC High */ +#define SETTLING_DELAY(x) (((x) & 0x1F) << 0) /* Settling Delay<4:0> */ + +/* +* REG_FAST_ENERGY_LOST_THRESH +*/ +#define POST_LOCK_LEVEL_STP_SIZE_FOR_LPF_TABLE_FULL_TABLE(x) (((x) & 0x3) << 6) /* Post Lock Level Step Size for: LPF Table/ Full Table <1:0> */ +#define ENERGY_LOST_THRESH(x) (((x) & 0x3F) << 0) /* Energy lost threshold<5:0> */ + +/* +* REG_FAST_STRONGER_SIGNAL_THRESH +*/ +#define POST_LOCK_LEVEL_STP_FOR_LMT_TABLE(x) (((x) & 0x3) << 6) /* Post Lock Level Step for LMT Table <1:0> */ +#define STRONGER_SIGNAL_THRESH(x) (((x) & 0x3F) << 0) /* Stronger Signal Threshold<5:0> */ + +/* +* REG_FAST_LOW_POWER_THRESH +*/ +#define DONT_UNLOCK_GAIN_IF_ADC_OVRG (1 << 7) /* Don't unlock gain if ADC Ovrg */ +#define LOW_POWER_THRESH(x) (((x) & 0x7F) << 0) /* Low Power Threshold<6:0> */ + +/* +* REG_FAST_STRONG_SIGNAL_FREEZE +*/ +#define DONT_UNLOCK_GAIN_IF_STRONGER_SIGNAL (1 << 7) /* Don't unlock gain if Stronger Signal */ + +/* +* REG_FAST_FINAL_OVER_RANGE_AND_OPT_GAIN +*/ +#define FINAL_OVER_RANGE_COUNT(x) (((x) & 0x7) << 5) /* Final Over Range Count<2:0> */ +#define OPTIMIZE_GAIN_OFFSET(x) (((x) & 0xF) << 0) /* Optimize Gain Offset<3:0> */ + +/* +* REG_FAST_ENERGY_DETECT_COUNT +*/ +#define INCREMENT_GAIN_STP_LPFLMT(x) (((x) & 0x7) << 5) /* Increment Gain Step (LPF/LMT)<2:0> */ +#define ENERGY_DETECT_COUNT(x) (((x) & 0x1F) << 0) /* Energy Detect count<4:0> */ + +/* +* REG_FAST_AGCLL_UPPER_LIMIT +*/ +#define AGCLL_MAX_INCREASE(x) (((x) & 0x3F) << 0) /* AGCLL Max Increase<5:0> */ + +/* +* REG_FAST_GAIN_LOCK_EXIT_COUNT +*/ +#define GAIN_LOCK_EXIT_COUNT(x) (((x) & 0x3F) << 0) /* Gain Lock Exit Count<5:0> */ + +/* +* REG_FAST_INITIAL_LMT_GAIN_LIMIT +*/ +#define INITIAL_LMT_GAIN_LIMIT(x) (((x) & 0x7F) << 0) /* Initial LMT Gain Limit<6:0> */ + +/* +* REG_AGC_INNER_LOW_THRESH +*/ +#define PREVENT_GAIN_INC (1 << 7) /* Prevent Gain Inc */ +#define AGC_INNER_LOW_THRESH(x) (((x) & 0x7F) << 0) /* AGC Inner Low Threshold<6:0> */ + +/* +* REG_LMT_OVERLOAD_COUNTERS +*/ +#define LARGE_LMT_OVERLOAD_EXED_COUNTER(x) (((x) & 0xF) << 4) /* Large LMT Overload Exceeded Counter<3:0> */ +#define SMALL_LMT_OVERLOAD_EXED_COUNTER(x) (((x) & 0xF) << 0) /* Small LMT Overload Exceeded Counter<3:0> */ + +/* +* REG_ADC_OVERLOAD_COUNTERS +*/ +#define LARGE_ADC_OVERLOAD_EXED_COUNTER(x) (((x) & 0xF) << 4) /* Large ADC Overload Exceeded Counter<3:0> */ +#define SMALL_ADC_OVERLOAD_EXED_COUNTER(x) (((x) & 0xF) << 0) /* Small ADC Overload Exceeded Counter<3:0> */ + +/* +* REG_GAIN_STP1 +*/ +#define IMMED_GAIN_CHANGE_IF_LG_LMT_OVERLOAD (1 << 7) /* Immed. Gain Change if Lg LMT Overload */ +#define IMMED_GAIN_CHANGE_IF_LG_ADC_OVERLOAD (1 << 3) /* Immed. Gain Change if Lg ADC Overload */ +#define AGC_INNER_HIGH_THRESH_EXED_STP_SIZE(x) (((x) & 0x7) << 4) /* AGC Inner High Threshold Exceeded Step Size<2:0> */ +#define AGC_INNER_LOW_THRESH_EXED_STP_SIZE(x) (((x) & 0x7) << 0) /* AGC Inner Low Threshold Exceeded Step Size<2:0> */ + +/* +* REG_DIGITAL_SAT_COUNTER +*/ +#define DOUBLE_GAIN_COUNTER (1 << 5) /* Double Gain Counter */ +#define ENABLE_SYNC_FOR_GAIN_COUNTER (1 << 4) /* Enable Sync for Gain Counter */ +#define DIG_SATURATION_EXED_COUNTER(x) (((x) & 0xF) << 0) /* Dig Saturation Exceeded Counter<3:0> */ + +/* +* REG_OUTER_POWER_THRESHS +*/ +#define AGC_OUTER_HIGH_THRESH(x) (((x) & 0xF) << 4) /* AGC Outer High Threshold<3:0> */ +#define AGC_OUTER_LOW_THRESH(x) (((x) & 0xF) << 0) /* AGC Outer Low Threshold<3:0> */ + +/* +* REG_GAIN_STP_2 +*/ +#define AGC_OUTER_HIGH_THRESH_EXED_STP_SIZE(x) (((x) & 0xF) << 4) /* AGC outer High Threshold Exceeded Step Size<3:0> */ +#define AGC_OUTER_LOW_THRESH_EXED_STP_SIZE(x) (((x) & 0xF) << 0) /* AGC Outer Low Threshold Exceeded Step Size<3:0> */ + +/* +* REG_EXT_LNA_HIGH_GAIN +*/ +#define EXT_LNA_HIGH_GAIN(x) (((x) & 0x3F) << 0) /* Ext LNA High Gain<5:0> */ + +/* +* REG_EXT_LNA_LOW_GAIN +*/ +#define EXT_LNA_LOW_GAIN(x) (((x) & 0x3F) << 0) /* Ext LNA Low Gain<5:0> */ + +/* +* REG_GAIN_TABLE_ADDRESS +*/ +#define GAIN_TABLE_ADDRESS(x) (((x) & 0x7F) << 0) /* Gain Table Address<6:0> */ + +/* +* REG_GAIN_TABLE_WRITE_DATA1 +*/ +#define EXT_LNA_CTRL (1 << 7) /* Ext LNA Ctrl */ +#define LNA_GAIN(x) (((x) & 0x3) << 5) /* LNA Gain <1:0> */ +#define MIXER_GM_GAIN(x) (((x) & 0x1F) << 0) /* Mixer Gm Gain <4:0> */ + +/* +* REG_GAIN_TABLE_WRITE_DATA2 +*/ +#define TIA_GAIN (1 << 5) /* TIA Gain */ +#define LPF_GAIN(x) (((x) & 0x1F) << 0) /* LPF Gain <4:0> */ + +/* +* REG_GAIN_TABLE_WRITE_DATA_3 +*/ +#define RF_DC_CAL (1 << 5) /* RF DC Cal */ +#define DIGITAL_GAIN(x) (((x) & 0x1F) << 0) /* Digital Gain <4:0> */ + +/* +* REG_GAIN_TABLE_READ_DATA_1 +*/ +#define TO_LNA_GAIN(x) (((x) >> 5) & 0x3) /* LNA Gain <1:0> */ +#define TO_MIXER_GM_GAIN(x) (((x) >> 0) & 0x1F) /* Mixer Gm Gain <4:0> */ + +/* +* REG_GAIN_TABLE_READ_DATA_2 +*/ +#define TO_LPF_GAIN(x) (((x) >> 0) & 0x1F) /* LPF Gain <4:0> */ + +/* +* REG_GAIN_TABLE_READ_DATA_3 +*/ +#define TO_DIGITAL_GAIN(x) (((x) >> 0) & 0x1F) /* Digital Gain <4:0> */ + +/* +* REG_GAIN_TABLE_CONFIG +*/ +#define WRITE_GAIN_TABLE (1 << 2) /* Write Gain Table */ +#define START_GAIN_TABLE_CLOCK (1 << 1) /* Start Gain Table Clock */ +#define RECEIVER_SELECT(x) (((x) & 0x3) << 3) /* Receiver Select<1:0> */ +#define GT_RX1 1 +#define GT_RX2 2 + + +/* +* REG_GM_SUB_TABLE_GAIN_WRITE +*/ +#define GM_SUB_TABLE_GAIN_WRITE(x) (((x) & 0x7F) << 0) /* Gm Sub Table Gain Word Write<6:0> */ + +/* +* REG_GM_SUB_TABLE_BIAS_WRITE +*/ +#define GM_SUB_TABLE_BIAS_WRITE(x) (((x) & 0x1F) << 0) /* Gm Sub Table Bias Word Write<4:0> */ + +/* +* REG_GM_SUB_TABLE_CTRL_WRITE +*/ +#define GM_SUB_TABLE_CTRL_WRITE(x) (((x) & 0x3F) << 0) /* Gm Sub Table Control Word Write<5:0> */ + +/* +* REG_GM_SUB_TABLE_GAIN_READ +*/ +#define GM_SUB_TABLE_GAIN_READ(x) (((x) & 0x7F) << 0) /* Gm Sub Table Gain Word Read<6:0> */ + +/* +* REG_GM_SUB_TABLE_BIAS_READ +*/ +#define GM_SUB_TABLE_BIAS_READ(x) (((x) & 0x1F) << 0) /* Gm Sub Table Bias Word Read<4:0> */ + +/* +* REG_GM_SUB_TABLE_CTRL_READ +*/ +#define GM_SUB_TABLE_CTRL_READ(x) (((x) & 0x3F) << 0) /* Gm Sub Table Control Word Read<5:0> */ + +/* +* REG_GM_SUB_TABLE_CONFIG +*/ +#define WRITE_GM_SUB_TABLE (1 << 2) /* Write Gm Sub Table */ +#define START_GM_SUB_TABLE_CLOCK (1 << 1) /* Start Gm Sub Table Clock */ + +/* +* REG_GAIN_DIFF_WORDERROR_WRITE +*/ +#define CALIB_TABLE_GAIN_DIFFERROR_WORD(x) (((x) & 0x3F) << 0) /* Calib Table Gain Diff/Error Word<5:0> */ + +/* +* REG_GAIN_ERROR_READ +*/ +#define CALIB_TABLE_GAIN_ERROR(x) (((x) & 0x1F) << 0) /* Calib Table Gain Error<4:0> */ + +/* +* REG_CONFIG +*/ +#define READ_SELECT (1 << 4) /* Read Select */ +#define WRITE_MIXER_ERROR_TABLE (1 << 3) /* Write Mixer Error Table */ +#define WRITE_LNA_ERROR_TABLE (1 << 2) /* Write LNA Error Table */ +#define WRITE_LNA_GAIN_DIFF (1 << 1) /* Write LNA Gain Diff */ +#define START_CALIB_TABLE_CLOCK (1 << 0) /* Start Calib Table Clock */ +#define CALIB_TABLE_SELECT(x) (((x) & 0x3) << 5) /* Calib Table Select<1:0> */ + +/* +* REG_LNA_GAIN_DIFF_READ_BACK +*/ +#define LNA_CALIB_TABLE_GAIN_DIFFERENCE_WORD(x) (((x) & 0x3F) << 0) /* LNA Calib Table Gain Difference Word<5:0> */ + +/* +* REG_MAX_MIXER_CALIBRATION_GAIN_INDEX +*/ +#define MAX_MIXER_CALIBRATION_GAIN_INDEX(x) (((x) & 0x1F) << 0) /* Max Mixer Calibration Gain Index<4:0> */ + +/* +* REG_SETTLE_TIME +*/ +#define ENABLE_DIG_GAIN_CORR (1 << 7) /* Enable Dig Gain Corr */ +#define FORCE_TEMP_SENSOR_FOR_CAL (1 << 6) /* Force Temp Sensor for Cal */ +#define SETTLE_TIME(x) (((x) & 0x3F) << 0) /* Settle Time<5:0> */ + +/* +* REG_MEASURE_DURATION +*/ +#define GAIN_CAL_MEAS_DURATION(x) (((x) & 0xF) << 0) /* Gain Cal Meas Duration<3:0> */ + +/* +* REG_MEASURE_DURATION_01 +*/ +#define MEASUREMENT_DURATION_1(x) (((x) & 0xF) << 4) /* Measurement duration 1 <3:0> */ +#define MEASUREMENT_DURATION_0(x) (((x) & 0xF) << 0) /* Measurement duration 0 <3:0> */ + +/* +* REG_MEASURE_DURATION_23 +*/ +#define MEASUREMENT_DURATION_3(x) (((x) & 0xF) << 4) /* Measurement duration 3 <3:0> */ +#define MEASUREMENT_DURATION_2(x) (((x) & 0xF) << 0) /* Measurement duration 2 <3:0> */ + +/* +* REG_RSSI_CONFIG +*/ +#define START_RSSI_MEAS (1 << 5) /* Start RSSI Meas (Mode 4) */ +#define ENABLE_ADC_POWER_MEAS (1 << 1) /* Enable ADC Power Meas. */ +#define DEFAULT_RSSI_MEAS_MODE (1 << 0) /* Default RSSI Meas Mode */ +#define RFIR_FOR_RSSI_MEASUREMENT(x) (((x) & 0x3) << 6) /* RFIR for RSSI measurement<1:0> */ +#define RSSI_MODE_SELECT(x) (((x) & 0x7) << 2) /* RSSI Mode Select<2:0> */ + +/* +* REG_ADC_MEASURE_DURATION_01 +*/ +#define ADC_POWER_MEASUREMENT_DURATION_1(x) (((x) & 0xF) << 4) /* ADC Power Measurement Duration 1<3:0> */ +#define ADC_POWER_MEASUREMENT_DURATION_0(x) (((x) & 0xF) << 0) /* ADC Power Measurement Duration 0 <3:0> */ + +/* +* REG_DEC_POWER_MEASURE_DURATION_0 +*/ +#define USE_HB3_OUT_FOR_ADC_PWR_MEAS (1 << 7) /* Use HB3 Out for ADC Pwr Meas */ +#define USE_HB1_OUT_FOR_DEC_PWR_MEAS (1 << 6) /* Use HB1 Out for Dec pwr Meas */ +#define ENABLE_DEC_PWR_MEAS (1 << 5) /* Enable Dec Pwr Meas */ +#define DEFAULT_MODE_ADC_POWER (1 << 4) /* Default Mode ADC Power */ +#define DEC_POWER_MEASUREMENT_DURATION(x) (((x) & 0xF) << 0) /* Dec Power Measurement Duration <3:0> */ + +/* +* REG_LNA_GAIN +*/ +#define DB_GAIN_READBACK_CHANNEL (1 << 0) /* dB Gain Read-back Channel */ +#define MAX_LNA_GAIN(x) (((x) & 0x7F) << 1) /* Max LNA Gain<6:0> */ + +/* +* REG_RX_QUAD_CAL_LEVEL +*/ +#define RX_QUAD_CAL_LEVEL(x) (((x) & 0xF) << 0) /* Rx Quad Cal Level <3 :0> */ + +/* +* REG_CALIBRATION_CONFIG_1 +*/ +#define ENABLE_PHASE_CORR (1 << 7) /* Enable Phase Corr */ +#define ENABLE_GAIN_CORR (1 << 6) /* Enable Gain Corr */ +#define USE_SETTLE_COUNT_FOR_DC_CAL_WAIT (1 << 5) /* Use Settle Count for DC Cal Wait */ +#define FIXED_DC_CAL_WAIT_TIME (1 << 4) /* Fixed DC Cal Wait Time */ +#define FREE_RUN_MODE (1 << 3) /* Free Run Mode */ +#define ENABLE_CORR_WORD_DECIMATION (1 << 2) /* Enable Corr Word Decimation */ +#define ENABLE_TRACKING_MODE_CH2 (1 << 1) /* Enable Tracking Mode CH2 */ +#define ENABLE_TRACKING_MODE_CH1 (1 << 0) /* Enable Tracking Mode CH1 */ + +/* +* REG_CALIBRATION_CONFIG_2 +*/ +#define SOFT_RESET (1 << 7) /* Soft Reset */ +#define CALIBRATION_CONFIG2_DFLT (0x3 << 5) /* Must be 2'b11 */ +#define K_EXP_PHASE(x) (((x) & 0x1F) << 0) /* K exp Phase<4:0> */ + +/* +* REG_CALIBRATION_CONFIG_3 +*/ +#define PREVENT_POS_LOOP_GAIN (1 << 7) /* Prevent Pos Loop Gain */ +#define K_EXP_AMPLITUDE(x) (((x) & 0x1F) << 0) /* K exp Amplitude<4:0> */ + +/* +* REG_RX_QUAD_GAIN1 +*/ +#define RX_FULL_TABLELMT_TABLE_GAIN(x) (((x) & 0x7F) << 0) /* Rx Full table/LMT table gain<6:0> */ + +/* +* REG_RX_QUAD_GAIN2 +*/ +#define CORRECTION_WORD_DECIMATION_M(x) (((x) & 0x7) << 5) /* Correction Word Decimation M<2:0> */ +#define RX_LPF_GAIN(x) (((x) & 0x1F) << 0) /* Rx LPF gain<4:0> */ + +/* +* REG_RX1_INPUT_A_OFFSETS +*/ +#define RX1_INPUT_A_I_DC_OFFSET_LSB(x) (((x) & 0x3F) << 2) /* Rx1 Input A "I" DC Offset<5:0> */ +#define RX1_INPUT_A_Q_DC_OFFSET(x) (((x) & 0x3) << 0) /* Rx1 Input A "Q" DC Offset<9:8> */ + +/* +* REG_INPUT_A_OFFSETS_1 +*/ +#define RX2_INPUT_A_Q_DC_OFFSET_LSB(x) (((x) & 0xF) << 4) /* Rx2 Input A "Q" DC Offset<3:0> */ +#define RX1_INPUT_A_I_DC_OFFSET_MSB(x) (((x) & 0xF) << 0) /* Rx1 Input A "I" DC Offset<9:6> */ + +/* +* REG_RX2_INPUT_A_OFFSETS +*/ +#define RX2_INPUT_A_I_DC_OFFSET(x) (((x) & 0x3) << 6) /* Rx2 Input A "I" DC Offset<1:0> */ +#define RX2_INPUT_A_Q_DC_OFFSET_MSB(x) (((x) & 0x3F) << 0) /* Rx2 Input A "Q" DC Offset<9:4> */ + +/* +* REG_RX1_INPUT_BC_OFFSETS +*/ +#define RX1_INPUT_BC_I_DC_OFFSET_LSB(x) (((x) & 0x3F) << 2) /* Rx1 Input B&C "I" DC Offset<5:0> */ +#define RX1_INPUT_BC_Q_DC_OFFSET(x) (((x) & 0x3) << 0) /* Rx1 Input B&C "Q" DC Offset<9:8> */ + +/* +* REG_INPUT_BC_OFFSETS_1 +*/ +#define RX2_INPUT_BC_Q_DC_OFFSET_LSB(x) (((x) & 0xF) << 4) /* Rx2 Input B&C "Q" DC Offset<3:0> */ +#define RX1_INPUT_BC_I_DC_OFFSET_MSB(x) (((x) & 0xF) << 0) /* Rx1 Input B&C "I" DC Offset<9:6> */ + +/* +* REG_RX2_INPUT_BC_OFFSETS +*/ +#define RX2_INPUT_BC_I_DC_OFFSET(x) (((x) & 0x3) << 6) /* Rx2 Input B&C "I" DC Offset<1:0> */ +#define RX2_INPUT_BC_Q_DC_OFFSET_MSB(x) (((x) & 0x3F) << 0) /* Rx2 Input B&C "Q" DC Offset<9:4> */ + +/* +* REG_FORCE_BITS +*/ +#define RX2_INPUT_BC_FORCE_OFFSET (1 << 7) /* Rx2 Input B&C Force offset */ +#define RX1_INPUT_BC_FORCE_OFFSET (1 << 6) /* Rx1 Input B&C Force offset */ +#define RX2_INPUT_BC_FORCE_PHGAIN (1 << 5) /* Rx2 Input B&C Force Ph/Gain */ +#define RX1_INPUT_BC_FORCE_PHGAIN (1 << 4) /* Rx1 Input B&C Force Ph/Gain */ +#define RX2_INPUT_A_FORCE_OFFSET (1 << 3) /* Rx2 Input A Force offset */ +#define RX1_INPUT_A_FORCE_OFFSET (1 << 2) /* Rx1 Input A Force offset */ +#define RX2_INPUT_A_FORCE_PHGAIN (1 << 1) /* Rx2 Input A Force Ph/Gain */ +#define RX1_INPUT_A_FORCE_PHGAIN (1 << 0) /* Rx1 Input A Force Ph/Gain */ + +/* +* REG_RF_DC_OFFSET_CONFIG_1 +*/ +#define DAC_FS(x) (((x) & 0x3) << 4) /* DAC FS<1:0> */ +#define RF_DC_CALIBRATION_COUNT(x) (((x) & 0xF) << 0) /* RF DC Calibration Count<3:0> */ + +/* +* REG_RF_DC_OFFSET_ATTEN +*/ +#define RF_DC_OFFSET_TABLE_UPDATE_COUNT(x) (((x) & 0x7) << 5) /* RF DC Offset Table Update Count<2:0> */ +#define RF_DC_OFFSET_ATTEN(x) (((x) & 0x1F) << 0) /* RF DC Offset Attenuation<4:0> */ + +/* +* REG_INVERT_BITS +*/ +#define INVERT_RX2_RF_DC_CGIN_WORD (1 << 7) /* Invert Rx2 RF DC CGin Word */ +#define INVERT_RX1_RF_DC_CGIN_WORD (1 << 6) /* Invert Rx1 RF DC CGin Word */ +#define INVERT_RX2_RF_DC_CGOUT_WORD (1 << 5) /* Invert Rx2 RF DC CGout Word */ +#define INVERT_RX1_RF_DC_CGOUT_WORD (1 << 4) /* Invert Rx1 RF DC CGout Word */ + +/* +* REG_DC_OFFSET_CONFIG2 +*/ +#define USE_WAIT_COUNTER_FOR_RF_DC_INIT_CAL (1 << 7) /* Use Wait Counter for RF DC Init Cal */ +#define ENABLE_FAST_SETTLE_MODE (1 << 6) /* Enable Fast Settle Mode */ +#define ENABLE_BB_DC_OFFSET_TRACKING (1 << 5) /* Enable BB DC Offset Tracking */ +#define RESET_ACC_ON_GAIN_CHANGE (1 << 4) /* Reset Acc on Gain Change */ +#define ENABLE_RF_OFFSET_TRACKING (1 << 3) /* Enable RF Offset Tracking */ +#define DC_OFFSET_UPDATE(x) (((x) & 0x7) << 0) /* DC Offset Update<2:0> */ + +/* +* REG_RF_CAL_GAIN_INDEX +*/ +#define RF_MINIMUM_CALIBRATION_GAIN_INDEX(x) (((x) & 0x7F) << 0) /* RF Minimum Calibration Gain Index<6:0> */ + +/* +* REG_SOI_THRESH +*/ +#define RF_SOI_THRESH(x) (((x) & 0x7F) << 0) /* RF SOI Threshold<6:0> */ + +/* +* REG_BB_DC_OFFSET_SHIFT +*/ +#define INCREASE_COUNT_DURATION (1 << 7) /* Increase Count Duration */ +#define BB_TRACKING_DECIMATE(x) (((x) & 0x3) << 5) /* BB Tracking Decimate<1:0> */ +#define BB_DC_M_SHIFT(x) (((x) & 0x1F) << 0) /* BB DC M Shift<4:0> */ + +/* +* REG_BB_DC_OFFSET_FAST_SETTLE_SHIFT +*/ +#define READ_BACK_CH_SEL (1 << 7) /* Read Back CH Sel */ +#define UPDATE_TRACKING_WORD (1 << 6) /* Update Tracking Word */ +#define FORCE_RX_NULL (1 << 5) /* Force Rx Null */ +#define BB_DC_TRACKING_FAST_SETTLE_M_SHIFT(x) (((x) & 0x1F) << 0) /* BB DC Tracking Fast Settle M Shift<4:0> */ + +/* +* REG_BB_DC_OFFSET_ATTEN +*/ +#define BB_DC_OFFSET_ATTEN(x) (((x) & 0xF) << 0) /* BB DC Offset Atten<3:0> */ + +/* +* REG_RX1_BB_DC_WORD_I_MSB +*/ +#define RX1_BB_DC_OFFSET_CORRECTION_WORD_I(x) (((x) & 0x7F) << 0) /* RX1 BB DC Offset Correction word I<14:8> */ + +/* +* REG_RX1_BB_DC_WORD_Q_MSB +*/ +#define RX1_BB_DC_OFFSET_CORRECTION_WORD_Q(x) (((x) & 0x7F) << 0) /* RX1 BB DC Offset Correction word Q<14:8> */ + +/* +* REG_RX2_BB_DC_WORD_I_MSB +*/ +#define RX2_BB_DC_OFFSET_CORRECTION_WORD_I(x) (((x) & 0x7F) << 0) /* RX2 BB DC Offset Correction word I<14:8> */ + +/* +* REG_RX2_BB_DC_WORD_Q_MSB +*/ +#define RX2_BB_DC_OFFSET_CORRECTION_WORD_Q(x) (((x) & 0x7F) << 0) /* RX2 BB DC Offset Correction word Q<14:8> */ + +/* +* REG_BB_TRACK_CORR_WORD_I_MSB +*/ +#define RX1RX2_BB_DC_OFFSET_TRACKING_CORRECTION_WORD_I(x) (((x) & 0x7F) << 0) /* RX1/RX2 BB DC Offset Tracking correction word I<14:8> */ + +/* +* REG_BB_TRACK_CORR_WORD_Q_MSB +*/ +#define RX1RX2_BB_DC_OFFSET_TRACKING_CORRECTION_WORD_Q(x) (((x) & 0x7F) << 0) /* RX1/RX2 BB DC Offset Tracking correction word Q<14:8> */ + +/* +* REG_SYMBOL_LSB +*/ +#define RX2_RSSI_SYMBOL (1 << 1) /* Rx2 RSSI symbol <0> */ +#define RX1_RSSI_SYMBOL (1 << 0) /* Rx1 RSSI symbol <0> */ + +/* +* REG_PREAMBLE_LSB +*/ +#define RX2_RSSI_PREAMBLE (1 << 1) /* Rx2 RSSI preamble <0> */ +#define RX1_RSSI_PREAMBLE (1 << 0) /* Rx1 RSSI preamble <0> */ + +/* +* REG_RX1_RSSI_SYMBOL, REG_RX1_RSSI_PREAMBLE, +* REG_RX2_RSSI_SYMBOL, REG_RX2_RSSI_PREAMBLE +*/ +#define RSSI_LSB_SHIFT 1 +#define RSSI_LSB_MASK1 0x01 +#define RSSI_LSB_MASK2 0x02 + +/* +* REG_RX_PATH_GAIN_LSB +*/ +#define RX_PATH_GAIN (1 << 0) /* Rx Path Gain<0> */ + +/* +* REG_RX_DIFF_LNA_FORCE +*/ +#define FORCE_RX2_LNA_GAIN (1 << 7) /* Force Rx2 LNA Gain */ +#define RX2_LNA_BYPASS (1 << 6) /* Rx2 LNA Bypass */ +#define FORCE_RX1_LNA_GAIN (1 << 3) /* Force Rx1 LNA Gain */ +#define RX1_LNA_BYPASS (1 << 2) /* Rx1 LNA Bypass */ +#define RX2_LNA_GAIN(x) (((x) & 0x3) << 4) /* Rx2 LNA Gain<1:0> */ +#define RX1_LNA_GAIN(x) (((x) & 0x3) << 0) /* Rx1 LNA Gain<1:0> */ + +/* +* REG_RX_LNA_BIAS_COARSE +*/ +#define RX_LNA_BIAS_COARSE(x) (((x) & 0xF) << 0) /* Rx LNA Bias Coarse<3:0> */ + +/* +* REG_RX_LNA_BIAS_FINE_0 +*/ +#define RX_LNA_PCASCODE_BIAS(x) (((x) & 0x7) << 5) /* Rx LNA p-Cascode Bias<2:0> */ +#define RX_LNA_BIAS(x) (((x) & 0x1F) << 0) /* Rx LNA Bias<4:0> */ + +/* +* REG_RX_LNA_BIAS_FINE_1 +*/ +#define RX_LNA_P_CASCODE_BIAS_FINE(x) (((x) & 0x3) << 0) /* Rx LNA p- Cascode Bias Fine<4:3> */ + +/* +* REG_RX_MIX_GM_CONFIG +*/ +#define RX_MIX_GM_CM_OUT(x) (((x) & 0x7) << 5) /* Rx Mix Gm CM Out<2:0> */ +#define RX_MIX_GM_PLOAD(x) (((x) & 0x3) << 0) /* Rx Mix Gm pload <1:0> */ + +/* +* REG_RX1_MIX_GM_FORCE +*/ +#define FORCE_RX1_MIX_GM (1 << 6) /* Force Rx1 Mix Gm */ +#define RX1_MIX_GM_GAIN(x) (((x) & 0x3F) << 0) /* Rx1 Mix Gm Gain<5:0> */ + +/* +* REG_RX1_MIX_GM_BIAS_FORCE +*/ +#define RX1_MIX_GM_BIAS(x) (((x) & 0x1F) << 0) /* Rx1 Mix Gm Bias<4:0> */ + +/* +* REG_RX2_MIX_GM_FORCE +*/ +#define FORCE_RX2_MIX_GM (1 << 6) /* Force Rx2 Mix Gm */ +#define RX2_MIX_GM_GAIN(x) (((x) & 0x3F) << 0) /* Rx2 Mix Gm Gain<5:0> */ + +/* +* REG_RX2_MIX_GM_BIAS_FORCE +*/ +#define RX2_MIX_GM_BIAS(x) (((x) & 0x1F) << 0) /* Rx2 Mix Gm Bias<4:0> */ + +/* +* REG_INPUT_A_MSBS +*/ +#define INPUT_A_RX1_Q(x) (((x) & 0x3) << 6) /* Input A RX1 Q<9:8> */ +#define INPUT_A_RX1_I(x) (((x) & 0x3) << 4) /* Input A RX1 I<9:8> */ +#define INPUT_A_RX2_I(x) (((x) & 0x3) << 2) /* Input A RX2 I<9:8> */ +#define INPUT_A_RX2_Q(x) (((x) & 0x3) << 0) /* Input A RX2 Q<9:8> */ + +/* +* REG_INPUTS_BC_MSBS +*/ +#define INPUTS_BC_RX1_Q(x) (((x) & 0x3) << 6) /* Inputs B&C RX1 Q<9:8> */ +#define INPUTS_BC_RX1_I(x) (((x) & 0x3) << 4) /* Inputs B&C RX1 I<9:8> */ +#define INPUTS_BC_RX2_I(x) (((x) & 0x3) << 2) /* Inputs B&C RX2 I<9:8> */ +#define INPUTS_BC_RX2_Q(x) (((x) & 0x3) << 0) /* Inputs B&C RX2 Q<9:8> */ + +/* +* REG_FORCE_OS_DAC +*/ +#define FORCE_CGIN_DAC (1 << 2) /* Force CGin DAC */ + +/* +* REG_RX_MIX_LO_CM +*/ +#define RX_MIX_LO_CM(x) (((x) & 0x3F) << 0) /* Rx Mix LO CM<5:0> */ + +/* +* REG_RX_CGB_SEG_ENABLE +*/ +#define RX_CGB_SEG_ENABLE(x) (((x) & 0x3F) << 0) /* Rx CGB Seg Enable<5:0> */ + +/* +* REG_RX_MIX_INPUTBIAS +*/ +#define RX_CGB_INPUT_CM_SEL(x) (((x) & 0x3) << 4) /* Rx CGB Input CM Sel<1:0> */ +#define RX_CGB_BIAS(x) (((x) & 0xF) << 0) /* Rx CGB Bias<3:0> */ + +/* +* REG_RX_TIA_CONFIG +*/ +#define TIA2_OVERRIDE_C (1 << 3) /* TIA2 Override C */ +#define TIA2_OVERRIDE_R (1 << 2) /* TIA2 Override R */ +#define TIA1_OVERRIDE_C (1 << 1) /* TIA1 Override C */ +#define TIA1_OVERRIDE_R (1 << 0) /* TIA1 Override R */ +#define TIA_SEL_CC(x) (((x) & 0x7) << 5) /* TIA Sel CC<2:0> */ + +/* +* REG_TIA1_C_LSB +*/ +#define TIA1_RF(x) (((x) & 0x3) << 6) /* TIA1 RF<1:0> */ +#define TIA1_C_LSB(x) (((x) & 0x3F) << 0) /* TIA1 C LSB<5:0> */ + +/* +* REG_TIA1_C_MSB +*/ +#define TIA1_C_MSB(x) (((x) & 0x7F) << 0) /* TIA1 C MSB<6:0> */ + +/* +* REG_TIA2_C_LSB +*/ +#define TIA2_RF(x) (((x) & 0x3) << 6) /* TIA2 RF<1:0> */ +#define TIA2_C_LSB(x) (((x) & 0x3F) << 0) /* TIA2 C LSB<5:0> */ + +/* +* REG_TIA2_C_MSB +*/ +#define TIA2_C_MSB(x) (((x) & 0x7F) << 0) /* TIA2 C MSB<6:0> */ + +/* +* REG_RX1_BBF_R1A +*/ +#define FORCE_RX1_RESISTORS (1 << 7) /* Force Rx1 Resistors */ +#define RX1_BBF_R1A(x) (((x) & 0x3F) << 0) /* Rx1 BBF R1A<5:0> */ + +/* +* REG_RX2_BBF_R1A +*/ +#define FORCE_RX2_RESISTORS (1 << 7) /* Force Rx2 Resistors */ +#define RX2_BBF_R1A(x) (((x) & 0x3F) << 0) /* Rx2 BBF R1A<5:0> */ + +/* +* REG_RX1_TUNE_CTRL +*/ +#define RX1_TUNE_RESAMPLE_PHASE (1 << 2) /* Rx1 Tune Resample Phase */ +#define RX1_TUNE_RESAMPLE (1 << 1) /* Rx1 Tune Resample */ +#define RX1_PD_TUNE (1 << 0) /* Rx1 PD Tune */ + +/* +* REG_RX2_TUNE_CTRL +*/ +#define RX2_TUNE_RESAMPLE_PHASE (1 << 2) /* Rx2 Tune Resam ple Phase */ +#define RX2_TUNE_RESAMPLE (1 << 1) /* Rx2 Tune Resample */ +#define RX2_PD_TUNE (1 << 0) /* Rx2 PD Tune */ + +/* +* REG_RX_BBF_R2346 +*/ +#define TUNE_OVERRIDE (1 << 7) /* Tune Override */ +#define RX_BBF_R2346(x) (((x) & 0x7) << 0) /* Rx BBF R2346<2:0> */ + +/* +* REG_RX_BBF_C1_MSB +*/ +#define RX_BBF_C1_MSB(x) (((x) & 0x3F) << 0) /* Rx BBF C1 MSB<5:0> */ + +/* +* REG_RX_BBF_C1_LSB +*/ +#define RX_BBF_C1_LSB(x) (((x) & 0x7F) << 0) /* Rx BBF C1 LSB<6:0> */ + +/* +* REG_RX_BBF_C2_MSB +*/ +#define RX_BBF_C2_MSB(x) (((x) & 0x3F) << 0) /* Rx BBF C2 MSB<5:0> */ + +/* +* REG_RX_BBF_C2_LSB +*/ +#define RX_BBF_C2_LSB(x) (((x) & 0x7F) << 0) /* Rx BBF C2 LSB<6:0> */ + +/* +* REG_RX_BBF_C3_MSB +*/ +#define RX_BBF_C3_MSB(x) (((x) & 0x3F) << 0) /* Rx BBF C3 MSB<5:0> */ + +/* +* REG_RX_BBF_C3_LSB +*/ +#define RX_BBF_C3_LSB(x) (((x) & 0x7F) << 0) /* Rx BBF C3 LSB<6:0> */ + +/* +* REG_RX_BBF_CC1_CTR +*/ +#define RX_BBF_CC1_CTR(x) (((x) & 0x7F) << 0) /* Rx BBF CC1 Ctr<6:0> */ + +/* +* REG_RX_BBF_POW_RZ_BYTE0 +*/ +#define MUST_BE_ZERO (1 << 7) /* Must be zero */ +#define RX1_BBF_POW_CTR(x) (((x) & 0x3) << 5) /* Rx1 BBF Pow Ctr<1:0> */ +#define RX_BBF_RZ1_CTR(x) (((x) & 0x3) << 3) /* Rx BBF Rz1 Ctr<1:0> */ + +/* +* REG_RX_BBF_CC2_CTR +*/ +#define RX_BBF_CC2_CTR(x) (((x) & 0x7F) << 0) /* Rx BBF CC2 Ctr<6:0> */ + +/* +* REG_RX_BBF_POW_RZ_BYTE1 +*/ +#define RX_BBF_POW3_CTR(x) (((x) & 0x3) << 6) /* Rx BBF Pow3 Ctr<1:0> */ +#define RX_BBF_RZ3_CTR(x) (((x) & 0x3) << 4) /* Rx BBF RZ3 Ctr<1:0> */ +#define RX_BBF_POW2_CTR(x) (((x) & 0x3) << 2) /* Rx BBF Pow2 Ctr<1:0> */ +#define RX_BBF_RZ2_CTR(x) (((x) & 0x3) << 0) /* Rx BBF Rz2 Ctr<1:0> */ + +/* +* REG_RX_BBF_CC3_CTR +*/ +#define RX_BBF_CC3_CTR(x) (((x) & 0x7F) << 0) /* Rx BBF CC3 Ctr<6:0> */ + +/* +* REG_RX_BBF_TUNE +*/ +#define RXBBF_BYPASS_BIAS_R (1 << 7) /* RxBBF Bypass Bias R */ +#define RX_BBF_R5_TUNE (1 << 4) /* Rx BBF R5 Tune */ +#define RX1_BBF_TUNE_COMP_I (1 << 3) /* Rx1 BBF Tune Comp I */ +#define RX1_BBF_TUNE_COMP_Q (1 << 2) /* Rx1 BBF Tune Comp Q */ +#define RX2_BBF_TUNE_COMP_I (1 << 1) /* Rx2 BBF Tune Comp I */ +#define RX2_BBF_TUNE_COMP_Q (1 << 0) /* Rx2 BBF Tune Comp Q */ +#define RX_BBF_TUNE_CTR(x) (((x) & 0x3) << 5) /* Rx BBF Tune Ctr<1:0> */ + +/* +* REG_RX1_BBF_MAN_GAIN +*/ +#define RX1_BBF_FORCE_GAIN (1 << 5) /* Rx1 BBF Force Gain */ +#define RX1_BBF_BQ_GAIN(x) (((x) & 0x3) << 3) /* Rx1 BBF BQ Gain<1:0> */ +#define RX1_BBF_POLE_GAIN(x) (((x) & 0x7) << 0) /* Rx1 BBF Pole Gain<2:0> */ + +/* +* REG_RX2_BBF_MAN_GAIN +*/ +#define RX2_BBF_FORCE_GAIN (1 << 5) /* Rx2 BBF Force Gain */ +#define RX2_BBF_BQ_GAIN(x) (((x) & 0x3) << 3) /* Rx2 BBF BQ Gain<1:0> */ +#define RX2_BBF_POLE_GAIN(x) (((x) & 0x7) << 0) /* Rx2 BBF Pole Gain<2:0> */ + +/* +* REG_RX_BBF_TUNE_CONFIG +*/ +#define RX_TUNE_EVALTIME (1 << 4) /* Rx Tune Evaltime */ +#define RX_BBF_TUNE_DIVIDE (1 << 0) /* RX BBF Tune Divide<8> */ +#define TUNE_COMP_MASK(x) (((x) & 0x3) << 5) /* Tune Comp Mask <1:0> */ +#define RX_TUNE_MODE(x) (((x) & 0x7) << 1) /* Rx Tune Mode<2:0> */ + +/* +* REG_POLE_GAIN +*/ +#define POLE_GAIN_TUNE(x) (((x) & 0x3) << 0) /* Pole Gain Tune<1:0> */ + +/* +* REG_RX_BBBW_MHZ +*/ +#define RX_TUNE_BBBW_MHZ(x) (((x) & 0x1F) << 0) /* Rx Tune BBBW MHz<4::0> */ + +/* +* REG_RX_BBBW_KHZ +*/ +#define RX_TUNE_BBBW_KHZ(x) (((x) & 0x7F) << 0) /* Rx Tune BBBW kHz<6:0> */ + +/* +* REG_RX_PFD_CONFIG +*/ +#define BYPASS_LD_SYNTH (1 << 0) /* Bypass Ld Synth */ + +/* +* REG_RX_INTEGER_BYTE_1 +*/ +#define SYNTH_INTEGER_WORD(x) (((x) & 0x7) << 0) /* Synthesizer Integer Word<10:8> */ + +/* +* REG_RX_FRACT_BYTE_2 +*/ +#define SYNTH_FRACT_WORD(x) (((x) & 0x7F) << 0) /* Synthesizer Fractional Word <22:16> */ + +/* +* REG_RX_FORCE_VCO_TUNE_1 +*/ +#define VCO_CAL_OFFSET(x) (((x) & 0xF) << 3) /* VCO Cal Offset<3:0> */ + +/* +* REG_RX_ALC_VARACTOR +*/ +#define INIT_ALC_VALUE(x) (((x) & 0xF) << 4) /* Init ALC Value<3:0> */ +#define VCO_VARACTOR(x) (((x) & 0xF) << 0) /* VCO Varactor<3:0> */ + +/* +* REG_RX_VCO_OUTPUT +*/ +#define PORB_VCO_LOGIC (1 << 6) /* PORb VCO Logic */ +#define VCO_OUTPUT_LEVEL(x) (((x) & 0xF) << 0) /* VCO Output Level<3:0> */ + +/* +* REG_RX_CP_CURRENT +*/ +#define CHARGE_PUMP_CURRENT(x) (((x) & 0x3F) << 0) /* Charge Pump Current<5:0> */ + +/* +* REG_RX_CP_OFFSET +*/ +#define SYNTH_RECAL (1 << 7) /* Synth Re-Cal */ + +/* +* REG_RX_CP_CONFIG +*/ +#define HALF_VCO_CAL_CLK (1 << 7) /* Half Vco Cal Clk */ +#define CP_OFFSET_OFF (1 << 4) /* CP Offset Off */ +#define F_CPCAL (1 << 3) /* F Cpcal */ +#define CP_CAL_ENABLE (1 << 2) /* Cp Cal Enable */ + +/* +* REG_RX_LOOP_FILTER_1 +*/ +#define LOOP_FILTER_C2(x) (((x) & 0xF) << 4) /* Loop Filter C2<3:0> */ +#define LOOP_FILTER_C1(x) (((x) & 0xF) << 0) /* Loop Filter C1<3:0> */ + +/* +* REG_RX_LOOP_FILTER_2 +*/ +#define LOOP_FILTER_R1(x) (((x) & 0xF) << 4) /* Loop Filter R1<3:0> */ +#define LOOP_FILTER_C3(x) (((x) & 0xF) << 0) /* Loop Filter C3<3:0> */ + +/* +* REG_RX_LOOP_FILTER_3 +*/ +#define LOOP_FILTER_BYPASS_R3 (1 << 7) /* Loop Filter Bypass R3 */ +#define LOOP_FILTER_BYPASS_R1 (1 << 6) /* Loop Filter Bypass R1 */ +#define LOOP_FILTER_BYPASS_C2 (1 << 5) /* Loop Filter Bypass C2 */ +#define LOOP_FILTER_BYPASS_C1 (1 << 4) /* Loop Filter Bypass C1 */ +#define LOOP_FILTER_R3(x) (((x) & 0xF) << 0) /* Loop Filter R3<3:0> */ + +/* +* REG_RX_DITHERCP_CAL +*/ +#define FORCED_CP_CAL_WORD(x) (((x) & 0xF) << 0) /* Forced CP Cal Word<3:0> */ + +/* +* REG_RX_VCO_BIAS_1 +*/ +#define VCO_BIAS_TCF(x) (((x) & 0x3) << 3) /* VCO Bias Tcf<1:0> */ +#define VCO_BIAS_REF(x) (((x) & 0x7) << 0) /* VCO Bias Ref<2:0> */ + +/* +* REG_RX_CAL_STATUS +*/ +#define CP_CAL_VALID (1 << 7) /* CP Cal Valid */ +#define CP_CAL_DONE (1 << 5) /* CP Cal Done */ +#define VCO_CAL_BUSY (1 << 4) /* VCO Cal Busy */ +#define CP_CAL_WORD(x) (((x) & 0xF) << 0) /* CP Cal Word<3:0> */ + +/* +* REG_RX_VCO_CAL_REF +*/ +#define VCO_CAL_REF_TCF(x) (((x) & 0x7) << 0) /* VCO Cal Ref Tcf<2:0> */ + +/* +* REG_RX_VCO_PD_OVERRIDES +*/ +#define POWER_DOWN_VARACTOR_REF (1 << 3) /* Power Down Varactor Ref */ +#define PWR_DOWN_VARACT_REF_TCF (1 << 2) /* Pwr Down Varact Ref Tcf */ +#define POWER_DOWN_CAL_TCF (1 << 1) /* Power Down Cal Tcf */ +#define POWER_DOWN_VCO_BUFFFER (1 << 0) /* Power Down VCO Bufffer */ + +/* +* REG_RX_CP_OVERRANGE_VCO_LOCK +*/ +#define CP_OVRG_HIGH (1 << 7) /* CP Ovrg High */ +#define CP_OVRG_LOW (1 << 6) /* CP Ovrg Low */ +#define VCO_LOCK (1 << 1) /* Lock */ + +/* +* REG_RX_VCO_LDO +*/ +#define VCO_LDO_BYPASS (1 << 7) /* VCO LDO Bypass */ +#define VCO_LDO_INRUSH(x) (((x) & 0x3) << 5) /* VCO LDO Inrush<1:0> */ +#define VCO_LDO_SEL(x) (((x) & 0x7) << 2) /* VCO LDO Sel<2:0> */ +#define VCO_LDO_VDROP_SEL(x) (((x) & 0x3) << 0) /* VCO LDO Vdrop Sel<1:0> */ + +/* +* REG_RX_VCO_CAL +*/ +#define VCO_CAL_EN (1 << 7) /* VCO Cal En */ +#define VCO_CAL_ALC_WAIT(x) (((x) & 0x7) << 4) /* VCO Cal ALC Wait <2:0> */ +#define VCO_CAL_COUNT(x) (((x) & 0x3) << 2) /* VCO Cal Count <1:0> */ + +/* +* REG_RX_LOCK_DETECT_CONFIG +*/ +#define LOCK_DETECT_COUNT(x) (((x) & 0x3) << 2) /* Lock Detect Count<1:0> */ +#define LOCK_DETECT_MODE(x) (((x) & 0x3) << 0) /* Lock Detect Mode<1:0> */ + +/* +* REG_RX_CP_LEVEL_DETECT +*/ +#define CP_LEVEL_DETECT_POWER_DOWN (1 << 6) /* CP Level Detect Power Down */ +#define CP_LEVEL_THRESH_LOW(x) (((x) & 0x7) << 3) /* CP Level Threshold Low<2:0> */ +#define CP_LEVEL_THRESH_HIGH(x) (((x) & 0x7) << 0) /* CP Level Threshold High<2:0> */ + +/* +* REG_RX_DSM_SETUP_0 +*/ +#define DSM_PROG(x) (((x) & 0xF) << 0) /* DSM Prog<3:0> */ + +/* +* REG_RX_DSM_SETUP_1 +*/ +#define SIF_CLOCK (1 << 6) /* SIF clock */ +#define SIF_RESET_BAR (1 << 5) /* SIF Reset Bar */ +#define SIF_ADDR(x) (((x) & 0x1F) << 0) /* SIF Addr<4:0> */ + +/* +* REG_RX_CORRECTION_WORD0 +*/ +#define UPDATE_FREQ_WORD (1 << 7) /* Update Freq Word */ +#define READ_EFFECTIVE_TUNING_WORD (1 << 5) /* Read Effective Tuning Word */ +#define FREQ_CORRECTION_WORD_MSB(x) (((x) & 0x1F) << 0) /* Frequency Correction Word<11:7> */ + +/* +* REG_RX_CORRECTION_WORD1 +*/ +#define UPDATE_FREQ_WORD (1 << 7) /* Update Freq Word */ +#define FREQ_CORRECTION_WORD_LSB(x) (((x) & 0x7F) << 0) /* Frequency Correction Word<6:0> */ + +/* +* REG_RX_VCO_VARACTOR_CTRL_0 +*/ +#define VCO_VARACTOR_REFERENCE_TCF(x) (((x) & 0x7) << 4) /* VCO Varactor Reference Tcf<2:0> */ +#define VCO_VARACTOR_OFFSET(x) (((x) & 0xF) << 0) /* VCO Varactor Offset<3:0> */ + +/* +* REG_RX_VCO_VARACTOR_CTRL_1 +*/ +#define VCO_VARACTOR_REFERENCE(x) (((x) & 0xF) << 0) /* VCO Varactor Reference<3:0> */ + +/* +* REG_RX_FAST_LOCK_SETUP +*/ +#define RX_FAST_LOCK_LOAD_SYNTH (1 << 3) /* Rx Fast Lock Load Synth */ +#define RX_FAST_LOCK_PROFILE_INIT (1 << 2) /* Rx Fast Lock Profile Init */ +#define RX_FAST_LOCK_PROFILE_PIN_SELECT (1 << 1) /* Rx Fast Lock Profile Pin Select */ +#define RX_FAST_LOCK_MODE_ENABLE (1 << 0) /* Rx Fast Lock Mode Enable */ +#define RX_FAST_LOCK_PROFILE(x) (((x) & 0x7) << 5) /* Rx Fast Lock Profile<2:0> */ + +/* +* REG_RX_FAST_LOCK_PROGRAM_ADDR +*/ +#define RX_FAST_LOCK_PROFILE_ADDR(x) (((x) & 0x7) << 4) /* Rx Fast Lock Profile<2:0> */ +#define RX_FAST_LOCK_PROFILE_WORD(x) (((x) & 0xF) << 0) /* Configuration Word <3:0> */ + + +/* +* REG_RX_FAST_LOCK_PROGRAM_CTRL +*/ +#define RX_FAST_LOCK_PROGRAM_WRITE (1 << 1) /* Rx Fast Lock Program Write */ +#define RX_FAST_LOCK_PROGRAM_CLOCK_ENABLE (1 << 0) /* Rx Fast Lock Program Clock Enable */ + +#define RX_FAST_LOCK_CONFIG_WORD_NUM 16 + +/* +* REG_RX_LO_GEN_POWER_MODE +*/ +#define RX_LO_GEN_POWER_MODE(x) (((x) & 0x3) << 4) /* Power Mode<3:0> */ + +/* +* REG_TX_PFD_CONFIG +*/ +#define DIV_TEST_EN (1 << 5) /* Div Test En */ +#define PFD_CLK_EDGE (1 << 1) /* PFD Clk Edge */ +#define BYPASS_LD_SYNTH (1 << 0) /* Bypass Ld Synth */ +#define PFD_WIDTH(x) (((x) & 0x3) << 2) /* PFD Width <1:0> */ + +/* +* REG_TX_INTEGER_BYTE_1 +*/ +#define SDM_BYPASS (1 << 7) /* SDM Bypass */ +#define SDM_POWER_DOWN (1 << 6) /* SDM Power Down */ +#define SYNTH_INTEGER_WORD(x) (((x) & 0x7) << 0) /* Synthesizer Integer Word<10:8> */ + +/* +* REG_TX_FRACT_BYTE_2 +*/ +#define SYNTH_FRACT_WORD(x) (((x) & 0x7F) << 0) /* Synthesizer Fractional Word <22:16> */ + +/* +* REG_TX_FORCE_ALC +*/ +#define FORCE_ALC_ENABLE (1 << 7) /* Force ALC Enable */ +#define FORCE_ALC_WORD(x) (((x) & 0x7F) << 0) /* Force ALC Word<6:0> */ + +/* +* REG_TX_FORCE_VCO_TUNE_1 +*/ +#define BYPASS_LOAD_DELAY (1 << 7) /* Bypass Load Delay */ +#define FORCE_VCO_TUNE_ENABLE (1 << 1) /* Force VCO Tune Enable */ +#define FORCE_VCO_TUNE (1 << 0) /* Force VCO Tune */ +#define VCO_CAL_OFFSET(x) (((x) & 0xF) << 3) /* VCO Cal Offset<3:0> */ + +/* +* REG_TX_ALCVARACT_OR +*/ +#define INIT_ALC_VALUE(x) (((x) & 0xF) << 4) /* Init ALC Value<3:0> */ +#define VCO_VARACTOR(x) (((x) & 0xF) << 0) /* VCO Varactor<3:0> */ + +/* +* REG_TX_VCO_OUTPUT +*/ +#define PORB_VCO_LOGIC (1 << 6) /* PORb VCO Logic */ +#define VCO_OUTPUT_LEVEL(x) (((x) & 0xF) << 0) /* VCO Output Level<3:0> */ + +/* +* REG_TX_CP_CURRENT +*/ +#define TX_CP_CURRENT_DFLT (1 << 7) /* Set to 1 */ +#define VTUNE_FORCE (1 << 6) /* Vtune Force */ +#define CHARGE_PUMP_CURRENT(x) (((x) & 0x3F) << 0) /* Charge Pump Current<5:0> */ + +/* +* REG_TX_CP_OFFSET +*/ +#define SYNTH_RECAL (1 << 7) /* Synth Re-Cal */ +#define CHARGE_PUMP_OFFSET(x) (((x) & 0x3F) << 0) /* Charge Pump Offset<5:0> */ + +/* +* REG_TX_CP_CONFIG +*/ +#define HALF_VCO_CAL_CLK (1 << 7) /* Half Vco Cal Clk */ +#define DITHER_MODE (1 << 6) /* Dither Mode */ +#define CP_OFFSET_OFF (1 << 4) /* Cp Offset Off */ +#define F_CPCAL (1 << 3) /* F Cpcal */ +#define CP_CAL_ENABLE (1 << 2) /* Cp Cal Enable */ +#define CP_TEST(x) (((x) & 0x3) << 0) /* Cp Test <1:0> */ + +/* +* REG_TX_LOOP_FILTER_1 +*/ +#define LOOP_FILTER_C2(x) (((x) & 0xF) << 4) /* Loop Filter C2<3:0> */ +#define LOOP_FILTER_C1(x) (((x) & 0xF) << 0) /* Loop Filter C1<3:0> */ + +/* +* REG_TX_LOOP_FILTER_2 +*/ +#define LOOP_FILTER_R1(x) (((x) & 0xF) << 4) /* Loop Filter R1<3:0> */ +#define LOOP_FILTER_C3(x) (((x) & 0xF) << 0) /* Loop Filter C3<3:0> */ + +/* +* REG_TX_LOOP_FILTER_3 +*/ +#define LOOP_FILTER_BYPASS_R3 (1 << 7) /* Loop Filter Bypass R3 */ +#define LOOP_FILTER_BYPASS_R1 (1 << 6) /* Loop Filter Bypass R1 */ +#define LOOP_FILTER_BYPASS_C2 (1 << 5) /* Loop Filter Bypass C2 */ +#define LOOP_FILTER_BYPASS_C1 (1 << 4) /* Loop Filter Bypass C1 */ +#define LOOP_FILTER_R3(x) (((x) & 0xF) << 0) /* Loop Filter R3<3:0> */ + +/* +* REG_TX_DITHERCP_CAL +*/ +#define NUMBER_SDM_DITHER_BITS(x) (((x) & 0xF) << 4) /* Number SDM Dither Bits<3:0> */ +#define FORCED_CP_CAL_WORD(x) (((x) & 0xF) << 0) /* Forced CP Cal Word<3:0> */ + +/* +* REG_TX_VCO_BIAS_1 +*/ +#define MUST_BE_ZEROS(x) (((x) & 0x3) << 5) /* Must be zeros */ +#define VCO_BIAS_TCF(x) (((x) & 0x3) << 3) /* VCO Bias Tcf<1:0> */ +#define VCO_BIAS_REF(x) (((x) & 0x7) << 0) /* VCO Bias Ref<2:0> */ + +/* +* REG_TX_VCO_BIAS_2 +*/ +#define VCO_BYPASS_BIAS_DAC_R (1 << 7) /* VCO Bypass Bias DAC R */ +#define VCO_COMP_BYPASS_BIAS_R (1 << 4) /* VCO Comp Bypass Bias R */ +#define BYPASS_PRESCALE_R (1 << 3) /* Bypass Prescale R */ +#define LAST_ALC_ENABLE (1 << 2) /* Last ALC Enable */ +#define PRESCALE_BIAS(x) (((x) & 0x3) << 0) /* Prescale Bias <1:0> */ + +/* +* REG_TX_CAL_STATUS +*/ +#define CP_CAL_VALID (1 << 7) /* CP Cal Valid */ +#define COMP_OUT (1 << 6) /* Comp Out */ +#define CP_CAL_DONE (1 << 5) /* CP Cal Done */ +#define VCO_CAL_BUSY (1 << 4) /* VCO Cal Busy */ +#define CP_CAL_WORD(x) (((x) & 0xF) << 0) /* CP Cal Word<3:0> */ + +/* +* REG_TX_VCO_CAL_REF +*/ +#define VCO_CAL_REF_MONITOR (1 << 3) /* VCO Cal Ref Monitor */ +#define VCO_CAL_REF_TCF(x) (((x) & 0x7) << 0) /* VCO Cal Ref Tcf<2:0> */ + +/* +* REG_TX_VCO_PD_OVERRIDES +*/ +#define POWER_DOWN_VARACTOR_REF (1 << 3) /* Power Down Varactor Ref */ +#define POWER_DOWN_VARACT_REF_TCF (1 << 2) /* Power Down Varact Ref Tcf */ +#define POWER_DOWN_CAL_TCF (1 << 1) /* Power Down Cal Tcf */ +#define POWER_DOWN_VCO_BUFFFER (1 << 0) /* Power Down VCO Bufffer */ + +/* +* REG_TX_CP_OVERRANGE_VCO_LOCK +*/ +#define CP_OVRG_HIGH (1 << 7) /* CP Ovrg High */ +#define CP_OVRG_LOW (1 << 6) /* CP Ovrg Low */ +#define VCO_LOCK (1 << 1) /* Lock */ + +/* +* REG_TX_VCO_LDO +*/ +#define VCO_LDO_BYPASS (1 << 7) /* VCO LDO Bypass */ +#define VCO_LDO_INRUSH(x) (((x) & 0x3) << 5) /* VCO LDO Inrush<1:0> */ +#define VCO_LDO_VOUT_SEL(x) (((x) & 0x7) << 2) /* VCO LDO Vout Sel<2:0> */ +#define VCO_LDO_VDROP_SEL(x) (((x) & 0x3) << 0) /* VCO LDO Vdrop Sel<1:0> */ + +/* +* REG_TX_VCO_CAL +*/ +#define VCO_CAL_EN (1 << 7) /* VCO Cal En */ +#define VCO_CAL_ALC_WAIT(x) (((x) & 0x7) << 4) /* VCO Cal ALC Wait<2:0) */ +#define VCO_CAL_COUNT(x) (((x) & 0x3) << 2) /* VCO Cal Count<1:0> */ +#define FB_CLOCK_ADV(x) (((x) & 0x3) << 0) /* FB Clock Adv<1:0> */ + +/* +* REG_TX_LOCK_DETECT_CONFIG +*/ +#define LOCK_DETECT_COUNT(x) (((x) & 0x3) << 2) /* Lock Detect Count<1:0> */ +#define LOCK_DETECT_MODE(x) (((x) & 0x3) << 0) /* Lock Detect Mode<1:0> */ + +/* +* REG_TX_CP_LEVEL_DETECT +*/ +#define CP_LEVEL_DETECT_POWER_DOWN (1 << 6) /* CP Level Detect Power Down */ +#define CP_LEVEL_DETECT_THRESH_LOW(x) (((x) & 0x7) << 3) /* CP Level Detect Threshold Low<2:0> */ +#define CP_LEVEL_DETECT_THRESH_HIGH(x) (((x) & 0x7) << 0) /* CP Level Detect Threshold High<2:0> */ + +/* +* REG_TX_DSM_SETUP_0 +*/ +#define DSM_PROG(x) (((x) & 0xF) << 0) /* DSM Prog<3:0> */ + +/* +* REG_TX_DSM_SETUP_1 +*/ +#define SIF_CLOCK (1 << 6) /* SIF clock */ +#define SIF_RESET_BAR (1 << 5) /* SIF Reset Bar */ +#define SIF_ADDR(x) (((x) & 0x1F) << 0) /* SIF Addr<4:0> */ + +/* +* REG_TX_CORRECTION_WORD0 +*/ +#define UPDATE_FREQ_WORD (1 << 7) /* Update Freq Word */ +#define READ_EFFECTIVE_TUNING_WORD (1 << 5) /* Read Effective Tuning Word */ +#define FREQ_CORRECTION_WORD_MSB(x) (((x) & 0x1F) << 0) /* Frequency Correction Word<11:7> */ + +/* +* REG_TX_CORRECTION_WORD1 +*/ +#define UPDATE_FREQ_WORD (1 << 7) /* Update Freq Word */ +#define FREQ_CORRECTION_WORD_LSB(x) (((x) & 0x7F) << 0) /* Frequency Correction Word<6:0> */ + +/* +* REG_TX_VCO_VARACTOR_CTRL_0 +*/ +#define VCO_VARACTOR_REFERENCE_TCF(x) (((x) & 0x7) << 4) /* VCO Varactor Reference Tcf<2:0> */ +#define VCO_VARACTOR_OFFSET(x) (((x) & 0xF) << 0) /* VCO Varactor Offset<3:0> */ + +/* +* REG_TX_VCO_VARACTOR_CTRL_1 +*/ +#define VCO_VARACTOR_REFERENCE(x) (((x) & 0xF) << 0) /* VCO Varactor Reference<3:0> */ + +/* +* REG_DCXO_COARSE_TUNE +*/ +#define DCXO_TUNE_COARSE(x) (((x) & 0x3F) << 0) /* DCXO Tune Coarse<5:0> */ + +/* +* REG_DCXO_FINE_TUNE_LOW +*/ +#define DCXO_TUNE_FINE_LOW(x) (((x) & 0x1F) << 3) /* DCXO Tune Fine<4:0> */ + +/* +* REG_DCXO_FINE_TUNE_HIGH +*/ +#define DCXO_TUNE_FINE_HIGH(x) ((x) >> 5) /* DCXO Tune Fine<12:5> */ + +/* +* REG_DCXO_CONFIG +*/ +#define MUST_BE_ZERO (1 << 7) /* Must be zero */ +#define DCXO_RTAIL(x) (((x) & 0x7) << 4) /* DCXO Rtail<2:0> */ +#define DCXO_RD(x) (((x) & 0x3) << 2) /* DCXO Rd<1:0> */ + +/* +* REG_DCXO_TEMPCO_ADDR +*/ +#define DCXO_TEMPCO_EN (1 << 7) /* DCXO Tempco En */ +#define DCXO_TEMPCO_CLK (1 << 6) /* DCXO Tempco Clk */ +#define DCXO_TEMPERATURE_COEF_ADDRESS(x) (((x) & 0x3F) << 0) /* DCXO Temperature Coefficient Address<5:0> */ + +/* +* REG_TX_FAST_LOCK_SETUP +*/ +#define TX_FAST_LOCK_LOAD_SYNTH (1 << 3) /* Tx Fast Lock Load Synth */ +#define TX_FAST_LOCK_PROFILE_INIT (1 << 2) /* Tx Fast Lock Profile Init */ +#define TX_FAST_LOCK_PROFILE_PIN_SELECT (1 << 1) /* Tx Fast Lock Profile Pin Select */ +#define TX_FAST_LOCK_MODE_ENABLE (1 << 0) /* Tx Fast Lock Mode Enable */ +#define TX_FAST_LOCK_PROFILE(x) (((x) & 0x7) << 5) /* Tx Fast Lock Profile<2:0> */ + +/* +* REG_TX_FAST_LOCK_PROGRAM_CTRL +*/ +#define TX_FAST_LOCK_PROGRAM_WRITE (1 << 1) /* Tx Fast Lock Program Write */ +#define TX_FAST_LOCK_PROGRAM_CLOCK_ENABLE (1 << 0) /* Tx Fast Lock Program Clock Enable */ + +/* +* REG_TX_LO_GEN_POWER_MODE +*/ +#define TX_LO_GEN_POWER_MODE(x) (((x) & 0xF) << 4) /* Power Mode<3:0> */ + +/* +* REG_BANDGAP_CONFIG0 +*/ +#define POWER_DOWN_BANDGAP_REF (1 << 7) /* Power Down Bandgap Ref */ +#define MASTER_BIAS_FILTER_BYPASS (1 << 6) /* Master Bias Filter Bypass */ +#define MASTER_BIAS_REF_SEL (1 << 5) /* Master Bias Ref Sel */ +#define MASTER_BIAS_TRIM(x) (((x) & 0x1F) << 0) /* Master Bias Trim<4:0> */ + +/* +* REG_BANDGAP_CONFIG1 +*/ +#define VCO_LDO_FILTER_BYPASS (1 << 7) /* VCO LDO Filter Bypass */ +#define VCO_LDO_REF_SEL (1 << 6) /* VCO LDO Ref Sel */ +#define BANDGAP_REF_RESET (1 << 5) /* Bandgap Ref Reset */ +#define BANDGAP_TEMP_TRIM(x) (((x) & 0x1F) << 0) /* Bandgap Temp Trim<4:0> */ + +/* +* REG_REF_DIVIDE_CONFIG_1 +*/ +#define REF_DIVIDE_CONFIG_1_DFLT (1 << 2) /* Set to 1 */ +#define RX_REF_RESET_BAR (1 << 1) /* Rx Ref Reset Bar */ +#define RX_REF_DIVIDER_MSB (1 << 0) /* Rx Ref Divider<1> */ + +/* +* REG_REF_DIVIDE_CONFIG_2 +*/ +#define RX_REF_DIVIDER_LSB (1 << 7) /* Rx Ref Divider< 0> */ +#define TX_REF_RESET_BAR (1 << 4) /* Tx Ref Reset Bar */ +#define RX_REF_DOUBLER_FB_DELAY(x) (((x) & 0x3) << 5) /* Rx Ref Doubler FB Delay<1:0> */ +#define TX_REF_DIVIDER(x) (((x) & 0x3) << 2) /* Tx Ref Divider<1:0> */ +#define TX_REF_DOUBLER_FB_DELAY(x) (((x) & 0x3) << 0) /* Tx Ref Doubler FB Delay<1:0> */ + +/* +* REG_GAIN_RX1,2 +*/ +#define FULL_TABLE_GAIN_INDEX(x) (((x) & 0x7F) << 0) /* Full Table Gain Index Rx1/LMT Gain Rx1<6:0> */ + +/* +* REG_LPF_GAIN_RX1,2 +*/ +#define LPF_GAIN_RX(x) (((x) & 0x1F) << 0) /* LPF gain Rx1<4:0> */ + +/* +* REG_DIG_GAIN_RX1,2 +*/ +#define DIGITAL_GAIN_RX(x) (((x) & 0x1F) << 0) /* Digital gain Rx1<4:0> */ + +/* +* REG_FAST_ATTACK_STATE +*/ +#define FAST_ATTACK_STATE_RX2(x) (((x) & 0x7) << 4) /* Fast Attack State Rx2<2:0> */ +#define FAST_ATTACK_STATE_RX1(x) (((x) & 0x7) << 0) /* Fast Attack State Rx1<2:0> */ +#define FAST_ATK_MASK 0x7 +#define RX1_FAST_ATK_SHIFT 0 +#define RX2_FAST_ATK_SHIFT 4 +#define FAST_ATK_RESET 0 +#define FAST_ATK_PEAK_DETECT 1 +#define FAST_ATK_PWR_MEASURE 2 +#define FAST_ATK_FINAL_SETTELING 3 +#define FAST_ATK_FINAL_OVER 4 +#define FAST_ATK_GAIN_LOCKED 5 + +/* +* REG_SLOW_LOOP_STATE +*/ +#define SLOW_LOOP_STATE_RX2(x) (((x) & 0x7) << 4) /* Slow Loop State Rx2<2:0> */ +#define SLOW_LOOP_STATE_RX1(x) (((x) & 0x7) << 0) /* Slow Loop State Rx1<2:0> */ + + +/* +* REG_OVRG_SIGS_RX1,2 +*/ +#define GAIN_LOCK_1 (1 << 6) /* Gain Lock 1 */ +#define LOW_POWER_1 (1 << 5) /* Low Power 1 */ +#define LARGE_LMT_OL (1 << 4) /* Large LMT OL */ +#define SMALL_LMT_OL (1 << 3) /* Small LMT OL */ +#define LARGE_ADC_OL (1 << 2) /* Large ADC OL */ +#define SMALL_ADC_OL (1 << 1) /* Small ADC OL */ +#define DIG_SAT (1 << 0) /* Dig Sat */ +/* +* REG_CTRL +*/ +#define CTRL_ENABLE (1 << 0) /* Set to 1 */ + +/* +* REG_BIST_CONFIG +*/ +#define TONE_PRBS (1 << 1) /* Tone/ PRBS */ +#define BIST_ENABLE (1 << 0) /* BIST Enable */ +#define TONE_FREQ(x) (((x) & 0x3) << 6) /* Tone Frequency<1:0> */ +#define TONE_LEVEL(x) (((x) & 0x3) << 4) /* Tone Level<1:0> */ +#define BIST_CTRL_POINT(x) (((x) & 0x3) << 2) /* BIST Control Point <1:0> */ + +/* +* REG_OBSERVE_CONFIG +*/ +#define DATA_PORT_SP_HD_LOOP_TEST_OE (1 << 7) /* Data Port SP, HD Loop Test OE */ +#define RX_MASK (1 << 6) /* Rx Mask */ +#define CHANNEL (1 << 5) /* Channel */ +#define DATA_PORT_LOOP_TEST_ENABLE (1 << 0) /* Data Port Loop Test Enable */ +#define OBSERVATION_POINT(x) (((x) & 0xF) << 1) /* Observation Point<2:0> */ + +/* +* REG_BIST_AND_DATA_PORT_TEST_CONFIG +*/ +#define BIST_MASK_CHANNEL_2_Q_DATA (1 << 5) /* BIST Mask Channel 2 Q data */ +#define BIST_MASK_CHANNEL_2_I_DATA (1 << 4) /* BIST Mask Channel 2 I data */ +#define BIST_MASK_CHANNEL_1_Q_DATA (1 << 3) /* BIST Mask Channel 1 Q data */ +#define BIST_MASK_CHANNEL_1_I_DATA (1 << 2) /* BIST Mask Channel 1 I data */ +#define DATA_PORT_HILOW (1 << 1) /* Data Port Hi/Low */ +#define USE_DATA_PORT (1 << 0) /* Use Data Port */ +#define TEMP_SENSE_VBE_TEST(x) (((x) & 0x3) << 6) /* Temp Sense Vbe Test<1:0> */ + +/* +* REG_DAC_TEST_2 +*/ +#define DAC_TEST_ENABLE (1 << 7) /* DAC Test Enable */ +#define DAC_TEST_WORD(x) (((x) & 0x7F) << 0) /* DAC test Word <22:16> */ + +/* +* SPI Comm Helpers +*/ +#define AD_READ (0 << 15) +#define AD_WRITE (1 << 15) +#define AD_CNT(x) ((((x) - 1) & 0x7) << 12) +#define AD_ADDR(x) ((x) & 0x3FF) + + +/* +* AD9361 Limits +*/ + +#define RSSI_MULTIPLIER 100 +#define RSSI_RESOLUTION ((int) (0.25 * RSSI_MULTIPLIER)) +#define RSSI_MAX_WEIGHT 255 + +#define MAX_LMT_INDEX 40 +#define MAX_LPF_GAIN 24 +#define MAX_DIG_GAIN 31 + +#define MAX_BBPLL_FREF 70007000UL /* 70 MHz + 100ppm */ +#define MIN_BBPLL_FREQ 714928500UL /* 715 MHz - 100ppm */ +#define MAX_BBPLL_FREQ 1430143000UL /* 1430 MHz + 100ppm */ +#define MAX_BBPLL_DIV 64 +#define MIN_BBPLL_DIV 2 + +/* + * The ADC minimum and maximum operating output data rates + * are 25MHz and 640MHz respectively. + * For more information see here: https://ez.analog.com/docs/DOC-12763 + */ + +#define MIN_ADC_CLK 25000000UL /* 25 MHz */ +//#define MIN_ADC_CLK (MIN_BBPLL_FREQ / MAX_BBPLL_DIV) /* 11.17MHz */ +#define MAX_ADC_CLK 640000000UL /* 640 MHz */ +#define MAX_DAC_CLK (MAX_ADC_CLK / 2) + +/* Associated with outputs of stage */ +#define MAX_RX_HB1 245760000UL +#define MAX_RX_HB2 320000000UL +#define MAX_RX_HB3 640000000UL +/* Associated with inputs of stage */ +#define MAX_TX_HB1 160000000UL +#define MAX_TX_HB2 320000000UL +#define MAX_TX_HB3 320000000UL + +#define MAX_BASEBAND_RATE 61440000UL + +#define MAX_MBYTE_SPI 8 + +#define RFPLL_MODULUS 8388593UL +#define BBPLL_MODULUS 2088960UL + +#define MAX_SYNTH_FREF 80008000UL /* 80 MHz + 100ppm */ +#define MIN_SYNTH_FREF 9999000UL /* 10 MHz - 100ppm */ +#define MIN_VCO_FREQ_HZ 6000000000ULL +#define MAX_CARRIER_FREQ_HZ 6000000000ULL +#define MIN_RX_CARRIER_FREQ_HZ 70000000ULL +#define MIN_TX_CARRIER_FREQ_HZ 46875001ULL + +#define AD9363A_MAX_CARRIER_FREQ_HZ 3800000000ULL +#define AD9363A_MIN_CARRIER_FREQ_HZ 325000000ULL + +#define MAX_TX_ATTENUATION_DB 89750 + +/* +* Driver +*/ + +enum rx_gain_table_type { + RXGAIN_FULL_TBL, + RXGAIN_SPLIT_TBL, +}; + +enum rx_gain_table_name { + TBL_200_1300_MHZ, + TBL_1300_4000_MHZ, + TBL_4000_6000_MHZ, + RXGAIN_TBLS_END, +}; + +struct gain_table_info { + uint64_t start; + uint64_t end; + uint8_t max_index; + uint8_t split_table; + int8_t *abs_gain_tbl; + uint8_t (*tab)[3]; +}; + +enum fir_dest { + FIR_TX1 = 0x01, + FIR_TX2 = 0x02, + FIR_TX1_TX2 = 0x03, + FIR_RX1 = 0x81, + FIR_RX2 = 0x82, + FIR_RX1_RX2 = 0x83, + FIR_IS_RX = 0x80, +}; + +struct rf_gain_ctrl { + uint32_t ant; + uint8_t mode; +}; + +enum rf_gain_ctrl_mode { + RF_GAIN_MGC, + RF_GAIN_FASTATTACK_AGC, + RF_GAIN_SLOWATTACK_AGC, + RF_GAIN_HYBRID_AGC +}; + +enum f_agc_target_gain_index_type { + MAX_GAIN, + SET_GAIN, + OPTIMIZED_GAIN, + NO_GAIN_CHANGE, +}; + +struct gain_control { + enum rf_gain_ctrl_mode rx1_mode; + enum rf_gain_ctrl_mode rx2_mode; + + /* Common */ + uint8_t adc_ovr_sample_size; /* 1..8 Sum x samples, AGC_CONFIG_3 */ + uint8_t adc_small_overload_thresh; /* 0..255, 0x105 */ + uint8_t adc_large_overload_thresh; /* 0..255, 0x104 */ + + uint16_t lmt_overload_high_thresh; /* 16..800 mV, 0x107 */ + uint16_t lmt_overload_low_thresh; /* 16..800 mV, 0x108 */ + uint16_t dec_pow_measuremnt_duration; /* Samples, 0x15C */ + uint8_t low_power_thresh; /* -64..0 dBFS, 0x114 */ + bool use_rx_fir_out_for_dec_pwr_meas; /* clears 0x15C:6 USE_HB1_OUT_FOR_DEC_PWR_MEAS */ + + bool dig_gain_en; /* should be turned off, since ADI GT doesn't use dig gain */ + uint8_t max_dig_gain; /* 0..31 */ + + /* MGC */ + bool mgc_rx1_ctrl_inp_en; /* Enables Pin control on RX1 default SPI ctrl */ + bool mgc_rx2_ctrl_inp_en; /* Enables Pin control on RX2 default SPI ctrl */ + + uint8_t mgc_inc_gain_step; /* 1..8 */ + uint8_t mgc_dec_gain_step; /* 1..8 */ + uint8_t mgc_split_table_ctrl_inp_gain_mode; /* 0=AGC determine this, 1=only in LPF, 2=only in LMT */ + + /* AGC */ + uint8_t agc_attack_delay_extra_margin_us; /* 0..31 us */ + + uint8_t agc_outer_thresh_high; + uint8_t agc_outer_thresh_high_dec_steps; + uint8_t agc_inner_thresh_high; + uint8_t agc_inner_thresh_high_dec_steps; + uint8_t agc_inner_thresh_low; + uint8_t agc_inner_thresh_low_inc_steps; + uint8_t agc_outer_thresh_low; + uint8_t agc_outer_thresh_low_inc_steps; + + uint8_t adc_small_overload_exceed_counter; /* 0..15, 0x122 */ + uint8_t adc_large_overload_exceed_counter; /* 0..15, 0x122 */ + uint8_t adc_large_overload_inc_steps; /* 0..15, 0x106 */ + + bool adc_lmt_small_overload_prevent_gain_inc; /* 0x120 */ + + uint8_t lmt_overload_large_exceed_counter; /* 0..15, 0x121 */ + uint8_t lmt_overload_small_exceed_counter; /* 0..15, 0x121 */ + uint8_t lmt_overload_large_inc_steps; /* 0..7, 0x121 */ + + uint8_t dig_saturation_exceed_counter; /* 0..15, 0x128 */ + uint8_t dig_gain_step_size; /* 1..8, 0x100 */ + bool sync_for_gain_counter_en; /* 0x128:4 !Hybrid */ + + uint32_t gain_update_interval_us; /* in us */ + bool immed_gain_change_if_large_adc_overload; /* 0x123:3 */ + bool immed_gain_change_if_large_lmt_overload; /* 0x123:7 */ + + /* + * Fast AGC + */ + uint32_t f_agc_dec_pow_measuremnt_duration; /* Samples, 0x15C */ + uint32_t f_agc_state_wait_time_ns; /* 0x117 0..31 RX samples -> time_ns */ + /* Fast AGC - Low Power */ + bool f_agc_allow_agc_gain_increase; /* 0x110:1 */ + uint8_t f_agc_lp_thresh_increment_time; /* 0x11B RX samples */ + uint8_t f_agc_lp_thresh_increment_steps; /* 0x117 1..8 */ + + /* Fast AGC - Lock Level */ + uint8_t f_agc_lock_level; /* NOT USED: 0x101 0..-127 dBFS same as agc_inner_thresh_high */ + bool f_agc_lock_level_lmt_gain_increase_en; /* 0x111:6 */ + uint8_t f_agc_lock_level_gain_increase_upper_limit; /* 0x118 0..63 */ + /* Fast AGC - Peak Detectors and Final Settling */ + uint8_t f_agc_lpf_final_settling_steps; /* 0x112:6 0..3 (Post Lock Level Step)*/ + uint8_t f_agc_lmt_final_settling_steps; /* 0x113:6 0..3 (Post Lock Level Step)*/ + uint8_t f_agc_final_overrange_count; /* 0x116:5 0..7 */ + /* Fast AGC - Final Power Test */ + bool f_agc_gain_increase_after_gain_lock_en; /* 0x110:7 */ + /* Fast AGC - Unlocking the Gain */ + /* 0 = MAX Gain, 1 = Set Gain, 2 = Optimized Gain */ + enum f_agc_target_gain_index_type + f_agc_gain_index_type_after_exit_rx_mode; /* 0x110:[4,2] */ + bool f_agc_use_last_lock_level_for_set_gain_en; /* 0x111:7 */ + uint8_t f_agc_optimized_gain_offset; /*0x116 0..15 steps */ + bool f_agc_rst_gla_stronger_sig_thresh_exceeded_en; /* 0x110:~6 */ + uint8_t f_agc_rst_gla_stronger_sig_thresh_above_ll; /*0x113 0..63 dbFS */ + bool f_agc_rst_gla_engergy_lost_sig_thresh_exceeded_en; /* 0x110:6 */ + bool f_agc_rst_gla_engergy_lost_goto_optim_gain_en; /* 0x110:6 */ + uint8_t f_agc_rst_gla_engergy_lost_sig_thresh_below_ll; /* 0x112:6 */ + uint8_t f_agc_energy_lost_stronger_sig_gain_lock_exit_cnt; /* 0x119 0..63 RX samples */ + bool f_agc_rst_gla_large_adc_overload_en; /*0x110:~1 and 0x114:~7 */ + bool f_agc_rst_gla_large_lmt_overload_en; /*0x110:~1 */ + bool f_agc_rst_gla_en_agc_pulled_high_en; + /* 0 = Max Gain, 1 = Set Gain, 2 = Optimized Gain, 3 = No Gain Change */ + + enum f_agc_target_gain_index_type + f_agc_rst_gla_if_en_agc_pulled_high_mode; /* 0x0FB, 0x111 */ + uint8_t f_agc_power_measurement_duration_in_state5; /* 0x109, 0x10a RX samples 0..524288*/ + uint8_t f_agc_large_overload_inc_steps; /* 0x106 [D6:D4] 0..7 */ +}; + +struct auxdac_control { + uint16_t dac1_default_value; + uint16_t dac2_default_value; + + bool auxdac_manual_mode_en; + + bool dac1_in_rx_en; + bool dac1_in_tx_en; + bool dac1_in_alert_en; + + bool dac2_in_rx_en; + bool dac2_in_tx_en; + bool dac2_in_alert_en; + + uint8_t dac1_rx_delay_us; + uint8_t dac1_tx_delay_us; + uint8_t dac2_rx_delay_us; + uint8_t dac2_tx_delay_us; +}; + +enum rssi_restart_mode { + AGC_IN_FAST_ATTACK_MODE_LOCKS_THE_GAIN, + EN_AGC_PIN_IS_PULLED_HIGH, + ENTERS_RX_MODE, + GAIN_CHANGE_OCCURS, + SPI_WRITE_TO_REGISTER, + GAIN_CHANGE_OCCURS_OR_EN_AGC_PIN_PULLED_HIGH, +}; + +struct rssi_control { + enum rssi_restart_mode restart_mode; + bool rssi_unit_is_rx_samples; /* default unit is time */ + uint32_t rssi_delay; + uint32_t rssi_wait; + uint32_t rssi_duration; +}; + +struct rx_gain_info { + enum rx_gain_table_type tbl_type; + int32_t starting_gain_db; + int32_t max_gain_db; + int32_t gain_step_db; + int32_t max_idx; + int32_t idx_step_offset; +}; + +struct port_control { + uint8_t pp_conf[3]; + uint8_t rx_clk_data_delay; + uint8_t tx_clk_data_delay; + uint8_t digital_io_ctrl; + uint8_t lvds_bias_ctrl; + uint8_t lvds_invert[2]; +}; + +struct ctrl_outs_control { + uint8_t index; + uint8_t en_mask; +}; + +struct elna_control { + uint16_t gain_mdB; + uint16_t bypass_loss_mdB; + uint32_t settling_delay_ns; + bool elna_1_control_en; /* GPO0 */ + bool elna_2_control_en; /* GPO1 */ + bool elna_in_gaintable_all_index_en; +}; + +struct auxadc_control { + int8_t offset; + uint32_t temp_time_inteval_ms; + uint32_t temp_sensor_decimation; + bool periodic_temp_measuremnt; + uint32_t auxadc_clock_rate; + uint32_t auxadc_decimation; +}; + +struct gpo_control { + uint32_t gpo_manual_mode_enable_mask; + bool gpo_manual_mode_en; + bool gpo0_inactive_state_high_en; + bool gpo1_inactive_state_high_en; + bool gpo2_inactive_state_high_en; + bool gpo3_inactive_state_high_en; + bool gpo0_slave_rx_en; + bool gpo0_slave_tx_en; + bool gpo1_slave_rx_en; + bool gpo1_slave_tx_en; + bool gpo2_slave_rx_en; + bool gpo2_slave_tx_en; + bool gpo3_slave_rx_en; + bool gpo3_slave_tx_en; + uint8_t gpo0_rx_delay_us; + uint8_t gpo0_tx_delay_us; + uint8_t gpo1_rx_delay_us; + uint8_t gpo1_tx_delay_us; + uint8_t gpo2_rx_delay_us; + uint8_t gpo2_tx_delay_us; + uint8_t gpo3_rx_delay_us; + uint8_t gpo3_tx_delay_us; +}; + +struct tx_monitor_control { + bool tx_mon_track_en; + bool one_shot_mode_en; + uint32_t low_high_gain_threshold_mdB; + uint8_t low_gain_dB; + uint8_t high_gain_dB; + uint16_t tx_mon_delay; + uint16_t tx_mon_duration; + uint8_t tx1_mon_front_end_gain; + uint8_t tx2_mon_front_end_gain; + uint8_t tx1_mon_lo_cm; + uint8_t tx2_mon_lo_cm; +}; + +enum ad9361_pdata_rx_freq { + BBPLL_FREQ, + ADC_FREQ, + R2_FREQ, + R1_FREQ, + CLKRF_FREQ, + RX_SAMPL_FREQ, + NUM_RX_CLOCKS, +}; + +enum ad9361_pdata_tx_freq { + IGNORE, + DAC_FREQ, + T2_FREQ, + T1_FREQ, + CLKTF_FREQ, + TX_SAMPL_FREQ, + NUM_TX_CLOCKS, +}; + +enum ad9361_clkout { + CLKOUT_DISABLE, + BUFFERED_XTALN_DCXO, + ADC_CLK_DIV_2, + ADC_CLK_DIV_3, + ADC_CLK_DIV_4, + ADC_CLK_DIV_8, + ADC_CLK_DIV_16, +}; + +struct ad9361_phy_platform_data { + bool rx2tx2; + bool fdd; + bool fdd_independent_mode; + bool split_gt; + bool use_extclk; + bool ensm_pin_pulse_mode; + bool ensm_pin_ctrl; + bool debug_mode; + bool tdd_use_dual_synth; + bool tdd_skip_vco_cal; + bool use_ext_rx_lo; + bool use_ext_tx_lo; + bool rx1rx2_phase_inversion_en; + bool qec_tracking_slow_mode_en; + uint8_t dc_offset_update_events; + uint8_t dc_offset_attenuation_high; + uint8_t dc_offset_attenuation_low; + uint8_t rf_dc_offset_count_high; + uint8_t rf_dc_offset_count_low; + uint8_t dig_interface_tune_skipmode; + uint8_t dig_interface_tune_fir_disable; + uint8_t lo_powerdown_managed_en; + uint32_t dcxo_coarse; + uint32_t dcxo_fine; + uint32_t rf_rx_input_sel; + uint32_t rf_tx_output_sel; + uint32_t rx1tx1_mode_use_rx_num; + uint32_t rx1tx1_mode_use_tx_num; + uint32_t rx_path_clks[NUM_RX_CLOCKS]; + uint32_t tx_path_clks[NUM_TX_CLOCKS]; + uint32_t trx_synth_max_fref; + uint64_t rx_synth_freq; + uint64_t tx_synth_freq; + uint32_t rf_rx_bandwidth_Hz; + uint32_t rf_tx_bandwidth_Hz; + int32_t tx_atten; + bool update_tx_gain_via_alert; + uint32_t rx_fastlock_delay_ns; + uint32_t tx_fastlock_delay_ns; + bool trx_fastlock_pinctrl_en[2]; + + enum ad9361_clkout ad9361_clkout_mode; + + struct gain_control gain_ctrl; + struct rssi_control rssi_ctrl; + struct port_control port_ctrl; + struct ctrl_outs_control ctrl_outs_ctrl; + struct elna_control elna_ctrl; + struct auxadc_control auxadc_ctrl; + struct auxdac_control auxdac_ctrl; + struct gpo_control gpo_ctrl; + struct tx_monitor_control txmon_ctrl; +}; + +struct rf_rx_gain { + uint32_t ant; /* Antenna number to read gain */ + int32_t gain_db; /* gain value in dB */ + uint32_t fgt_lmt_index; /* Full Gain Table / LNA-MIXER-TIA gain index */ + uint32_t lmt_gain; /* LNA-MIXER-TIA gain in dB (Split GT mode only)*/ + uint32_t lpf_gain; /* Low pass filter gain in dB / index (Split GT mode only)*/ + uint32_t digital_gain; /* Digital gain in dB / index */ + /* Debug only */ + uint32_t lna_index; /* LNA Index (Split GT mode only) */ + uint32_t tia_index; /* TIA Index (Split GT mode only) */ + uint32_t mixer_index; /* MIXER Index (Split GT mode only) */ + +}; +struct rf_rssi { + uint32_t ant; /* Antenna number for which RSSI is reported */ + uint32_t symbol; /* Runtime RSSI */ + uint32_t preamble; /* Initial RSSI */ + int32_t multiplier; /* Multiplier to convert reported RSSI */ + uint8_t duration; /* Duration to be considered for measuring */ +}; + +struct SynthLUT { + uint16_t VCO_MHz; + uint8_t VCO_Output_Level; + uint8_t VCO_Varactor; + uint8_t VCO_Bias_Ref; + uint8_t VCO_Bias_Tcf; + uint8_t VCO_Cal_Offset; + uint8_t VCO_Varactor_Reference; + uint8_t Charge_Pump_Current; + uint8_t LF_C2; + uint8_t LF_C1; + uint8_t LF_R1; + uint8_t LF_C3; + uint8_t LF_R3; +}; + +enum { + LUT_FTDD_40, + LUT_FTDD_60, + LUT_FTDD_80, + LUT_FTDD_ENT, +}; + +enum ad9361_clocks { + BB_REFCLK, + RX_REFCLK, + TX_REFCLK, + BBPLL_CLK, + ADC_CLK, + R2_CLK, + R1_CLK, + CLKRF_CLK, + RX_SAMPL_CLK, + DAC_CLK, + T2_CLK, + T1_CLK, + CLKTF_CLK, + TX_SAMPL_CLK, + RX_RFPLL_INT, + TX_RFPLL_INT, + RX_RFPLL_DUMMY, + TX_RFPLL_DUMMY, + RX_RFPLL, + TX_RFPLL, + NUM_AD9361_CLKS, + EXT_REF_CLK, +}; + +struct ad9361_debugfs_entry { + struct ad9361_rf_phy *phy; + const char *propname; + void *out_value; + uint32_t val; + uint8_t size; + uint8_t cmd; +}; + +struct ad9361_fastlock_entry { +#define FASTLOOK_INIT 1 + uint8_t flags; + uint8_t alc_orig; + uint8_t alc_written; +}; + +struct ad9361_fastlock { + uint8_t save_profile; + uint8_t current_profile[2]; + struct ad9361_fastlock_entry entry[2][8]; +}; + +enum dig_tune_flags { + BE_VERBOSE = 1, + BE_MOREVERBOSE = 2, + DO_IDELAY = 4, + DO_ODELAY = 8, + SKIP_STORE_RESULT = 16, + RESTORE_DEFAULT = 32, +}; + +enum ad9361_bist_mode { + BIST_DISABLE, + BIST_INJ_TX, + BIST_INJ_RX, +}; + +enum synth_pd_ctrl { + LO_DONTCARE, + LO_OFF, + LO_ON, +}; + +enum dev_id { + ID_AD9361, + ID_AD9364, + ID_AD9363A +}; + +struct ad9361_rf_phy { + enum dev_id dev_sel; + struct spi_desc *spi; + struct gpio_desc *gpio_desc_resetb; + struct gpio_desc *gpio_desc_sync; + struct gpio_desc *gpio_desc_cal_sw1; + struct gpio_desc *gpio_desc_cal_sw2; +#ifndef AXI_ADC_NOT_PRESENT + struct axi_adc *rx_adc; + struct axi_dac *tx_dac; +#endif + struct clk *clk_refin; + struct clk *clks[NUM_AD9361_CLKS]; + struct refclk_scale *ref_clk_scale[NUM_AD9361_CLKS]; + uint32_t (*ad9361_rfpll_ext_recalc_rate)(struct refclk_scale *clk_priv); + int32_t (*ad9361_rfpll_ext_round_rate)(struct refclk_scale *clk_priv, + uint32_t rate); + int32_t (*ad9361_rfpll_ext_set_rate)(struct refclk_scale *clk_priv, + uint32_t rate); + struct ad9361_phy_platform_data *pdata; + uint8_t prev_ensm_state; + uint8_t curr_ensm_state; + uint8_t cached_rx_rfpll_div; + uint8_t cached_tx_rfpll_div; + uint8_t cached_synth_pd[2]; + int32_t tx_quad_lpf_tia_match; + uint32_t current_table; + struct gain_table_info *gt_info; + bool ensm_pin_ctl_en; + + bool auto_cal_en; + bool manual_tx_quad_cal_en; + uint64_t last_tx_quad_cal_freq; + uint32_t last_tx_quad_cal_phase; + uint64_t current_tx_lo_freq; + uint64_t current_rx_lo_freq; + bool current_tx_use_tdd_table; + bool current_rx_use_tdd_table; + uint32_t current_rx_path_clks[NUM_RX_CLOCKS]; + uint32_t current_tx_path_clks[NUM_TX_CLOCKS]; + uint32_t flags; + uint32_t cal_threshold_freq; + uint32_t current_rx_bw_Hz; + uint32_t current_tx_bw_Hz; + uint32_t rxbbf_div; + uint32_t rate_governor; + bool bypass_rx_fir; + bool bypass_tx_fir; + bool rx_eq_2tx; + bool filt_valid; + uint32_t filt_rx_path_clks[NUM_RX_CLOCKS]; + uint32_t filt_tx_path_clks[NUM_TX_CLOCKS]; + uint32_t filt_rx_bw_Hz; + uint32_t filt_tx_bw_Hz; + uint8_t tx_fir_int; + uint8_t tx_fir_ntaps; + uint8_t rx_fir_dec; + uint8_t rx_fir_ntaps; + uint8_t agc_mode[2]; + bool rfdc_track_en; + bool bbdc_track_en; + bool quad_track_en; + bool txmon_tdd_en; + uint16_t auxdac1_value; + uint16_t auxdac2_value; + uint32_t tx1_atten_cached; + uint32_t tx2_atten_cached; + struct ad9361_fastlock fastlock; + struct axiadc_converter *adc_conv; + struct axiadc_state *adc_state; + int32_t bist_loopback_mode; + int32_t bist_config; + enum ad9361_bist_mode bist_prbs_mode; + enum ad9361_bist_mode bist_tone_mode; + uint32_t bist_tone_freq_Hz; + uint32_t bist_tone_level_dB; + uint32_t bist_tone_mask; + bool bbpll_initialized; +}; + +struct refclk_scale { + struct spi_desc *spi; + struct ad9361_rf_phy *phy; + uint32_t mult; + uint32_t div; + enum ad9361_clocks source; + enum ad9361_clocks parent_source; +}; + +enum debugfs_cmd { + DBGFS_NONE, + DBGFS_INIT, + DBGFS_LOOPBACK, + DBGFS_BIST_PRBS, + DBGFS_BIST_TONE, + DBGFS_BIST_DT_ANALYSIS, + DBGFS_RXGAIN_1, + DBGFS_RXGAIN_2, +}; + +/******************************************************************************/ +/************************ Functions Declarations ******************************/ +/******************************************************************************/ +int32_t ad9361_spi_readm(struct spi_desc *spi, uint32_t reg, + uint8_t *rbuf, uint32_t num); +int32_t ad9361_spi_read(struct spi_desc *spi, uint32_t reg); +int32_t ad9361_spi_write(struct spi_desc *spi, + uint32_t reg, uint32_t val); +int32_t ad9361_reset(struct ad9361_rf_phy *phy); +int32_t ad9361_register_clocks(struct ad9361_rf_phy *phy); +int32_t ad9361_unregister_clocks(struct ad9361_rf_phy *phy); +uint32_t ad9361_gt(struct ad9361_rf_phy *phy); +int32_t ad9361_init_gain_tables(struct ad9361_rf_phy *phy); +int32_t ad9361_setup(struct ad9361_rf_phy *phy); +int32_t ad9361_post_setup(struct ad9361_rf_phy *phy); +int32_t ad9361_set_ensm_mode(struct ad9361_rf_phy *phy, bool fdd, bool pinctrl); +int32_t ad9361_ensm_set_state(struct ad9361_rf_phy *phy, uint8_t ensm_state, + bool pinctrl); +int32_t ad9361_set_rx_gain(struct ad9361_rf_phy *phy, + uint32_t rx_id, struct rf_rx_gain *rx_gain); +int32_t ad9361_get_rx_gain(struct ad9361_rf_phy *phy, + uint32_t rx_id, struct rf_rx_gain *rx_gain); +int32_t ad9361_update_rf_bandwidth(struct ad9361_rf_phy *phy, + uint32_t rf_rx_bw, uint32_t rf_tx_bw); +int32_t ad9361_calculate_rf_clock_chain(struct ad9361_rf_phy *phy, + uint32_t tx_sample_rate, + uint32_t rate_gov, + uint32_t *rx_path_clks, + uint32_t *tx_path_clks); +int32_t ad9361_set_trx_clock_chain(struct ad9361_rf_phy *phy, + uint32_t *rx_path_clks, + uint32_t *tx_path_clks); +int32_t ad9361_get_trx_clock_chain(struct ad9361_rf_phy *phy, + uint32_t *rx_path_clks, + uint32_t *tx_path_clks); +uint32_t ad9361_to_clk(uint64_t freq); +uint64_t ad9361_from_clk(uint32_t freq); +int32_t ad9361_read_rssi(struct ad9361_rf_phy *phy, struct rf_rssi *rssi); +int32_t ad9361_set_gain_ctrl_mode(struct ad9361_rf_phy *phy, + struct rf_gain_ctrl *gain_ctrl); +int32_t ad9361_load_fir_filter_coef(struct ad9361_rf_phy *phy, + enum fir_dest dest, int32_t gain_dB, + uint32_t ntaps, short *coef); +int32_t ad9361_validate_enable_fir(struct ad9361_rf_phy *phy); +int32_t ad9361_set_tx_atten(struct ad9361_rf_phy *phy, uint32_t atten_mdb, + bool tx1, bool tx2, bool immed); +int32_t ad9361_get_tx_atten(struct ad9361_rf_phy *phy, uint32_t tx_num); +uint32_t ad9361_clk_factor_recalc_rate(struct refclk_scale *clk_priv, + uint32_t parent_rate); +int32_t ad9361_clk_factor_round_rate(struct refclk_scale *clk_priv, + uint32_t rate, + uint32_t *prate); +int32_t ad9361_clk_factor_set_rate(struct refclk_scale *clk_priv, uint32_t rate, + uint32_t parent_rate); +uint32_t ad9361_bbpll_recalc_rate(struct refclk_scale *clk_priv, + uint32_t parent_rate); +int32_t ad9361_bbpll_round_rate(struct refclk_scale *clk_priv, uint32_t rate, + uint32_t *prate); +int32_t ad9361_bbpll_set_rate(struct refclk_scale *clk_priv, uint32_t rate, + uint32_t parent_rate); +uint32_t ad9361_rfpll_int_recalc_rate(struct refclk_scale *clk_priv, + uint32_t parent_rate); +int32_t ad9361_rfpll_int_round_rate(struct refclk_scale *clk_priv, + uint32_t rate, + uint32_t *prate); +int32_t ad9361_rfpll_int_set_rate(struct refclk_scale *clk_priv, uint32_t rate, + uint32_t parent_rate); +uint32_t ad9361_rfpll_dummy_recalc_rate(struct refclk_scale *clk_priv); +int32_t ad9361_rfpll_dummy_set_rate(struct refclk_scale *clk_priv, + uint32_t rate); +uint32_t ad9361_rfpll_recalc_rate(struct refclk_scale *clk_priv); +int32_t ad9361_rfpll_round_rate(struct refclk_scale *clk_priv, uint32_t rate); +int32_t ad9361_rfpll_set_rate(struct refclk_scale *clk_priv, uint32_t rate); +int32_t ad9361_clk_mux_set_parent(struct refclk_scale *clk_priv, uint8_t index); +int32_t ad9361_tracking_control(struct ad9361_rf_phy *phy, bool bbdc_track, + bool rfdc_track, bool rxquad_track); +int32_t ad9361_bist_loopback(struct ad9361_rf_phy *phy, int32_t mode); +void ad9361_get_bist_loopback(struct ad9361_rf_phy *phy, int32_t *mode); +int32_t ad9361_bist_prbs(struct ad9361_rf_phy *phy, enum ad9361_bist_mode mode); +void ad9361_get_bist_prbs(struct ad9361_rf_phy *phy, + enum ad9361_bist_mode *mode); +int32_t ad9361_bist_tone(struct ad9361_rf_phy *phy, + enum ad9361_bist_mode mode, uint32_t freq_Hz, + uint32_t level_dB, uint32_t mask); +void ad9361_get_bist_tone(struct ad9361_rf_phy *phy, + enum ad9361_bist_mode *mode, uint32_t *freq_Hz, + uint32_t *level_dB, uint32_t *mask); +int32_t ad9361_rf_port_setup(struct ad9361_rf_phy *phy, bool is_out, + uint32_t rx_inputs, uint32_t txb); +int32_t ad9361_mcs(struct ad9361_rf_phy *phy, int32_t step); +int32_t ad9361_do_calib_run(struct ad9361_rf_phy *phy, uint32_t cal, + int32_t arg); +int32_t ad9361_fastlock_store(struct ad9361_rf_phy *phy, bool tx, + uint32_t profile); +int32_t ad9361_fastlock_recall(struct ad9361_rf_phy *phy, bool tx, + uint32_t profile); +int32_t ad9361_fastlock_load(struct ad9361_rf_phy *phy, bool tx, + uint32_t profile, uint8_t *values); +int32_t ad9361_fastlock_save(struct ad9361_rf_phy *phy, bool tx, + uint32_t profile, uint8_t *values); +void ad9361_ensm_force_state(struct ad9361_rf_phy *phy, uint8_t ensm_state); +uint8_t ad9361_ensm_get_state(struct ad9361_rf_phy *phy); +void ad9361_ensm_restore_state(struct ad9361_rf_phy *phy, uint8_t ensm_state); +void ad9361_ensm_restore_prev_state(struct ad9361_rf_phy *phy); +int32_t ad9361_set_trx_clock_chain_freq(struct ad9361_rf_phy *phy, + uint32_t freq); +int32_t ad9361_find_opt(uint8_t *field, uint32_t size, uint32_t *ret_start); +int32_t ad9361_hdl_loopback(struct ad9361_rf_phy *phy, bool enable); +int32_t ad9361_dig_interface_timing_analysis(struct ad9361_rf_phy *phy, + char *buf, int32_t buflen); +int32_t ad9361_dig_tune(struct ad9361_rf_phy *phy, uint32_t max_freq, + enum dig_tune_flags flags); +int32_t ad9361_en_dis_tx(struct ad9361_rf_phy *phy, uint32_t tx_if, + uint32_t enable); +int32_t ad9361_en_dis_rx(struct ad9361_rf_phy *phy, uint32_t rx_if, + uint32_t enable); +int32_t ad9361_1rx1tx_channel_map(struct ad9361_rf_phy *phy, bool tx, + int32_t channel); +int32_t ad9361_rssi_gain_step_calib(struct ad9361_rf_phy *phy); +int32_t ad9361_set_dcxo_tune(struct ad9361_rf_phy *phy, + uint32_t coarse, uint32_t fine); +int32_t ad9361_tx_mute(struct ad9361_rf_phy *phy, uint32_t state); +uint32_t ad9361_validate_rf_bw(struct ad9361_rf_phy *phy, uint32_t bw); +int32_t ad9361_get_temp(struct ad9361_rf_phy *phy); +int ad9361_synth_lo_powerdown(struct ad9361_rf_phy *phy, + enum synth_pd_ctrl rx, + enum synth_pd_ctrl tx); +void ad9361_clear_state(struct ad9361_rf_phy *phy); +#endif diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/rf-transceiver/ad9361/ad9361_api.c b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/rf-transceiver/ad9361/ad9361_api.c new file mode 100644 index 0000000..1befc57 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/rf-transceiver/ad9361/ad9361_api.c @@ -0,0 +1,2157 @@ +/***************************************************************************//** + * @file ad9361_api.c + * @brief Implementation of AD9361 API Driver. + * @author DBogdan (dragos.bogdan@analog.com) +******************************************************************************** + * Copyright 2013(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ +#include +#include "ad9361.h" +#include "ad9361_api.h" +#include "delay.h" +#include "spi.h" +#include "util.h" +#include "../../../config/app_config.h" + +/******************************************************************************/ +/************************ Constants Definitions *******************************/ +/******************************************************************************/ + +extern struct gain_table_info ad9361_adi_gt_info[]; + +/** + * Initialize the AD9361 part. + * @param ad9361_phy The AD9361 device structure. + * @param init_param The structure that contains the AD9361 initial parameters. + * @return 0 in case of success, negative error code otherwise. + * + * Note: This function will/may affect the data path. + */ +int32_t ad9361_init (struct ad9361_rf_phy **ad9361_phy, + AD9361_InitParam *init_param) +{ + struct ad9361_rf_phy *phy; + int32_t ret = 0; + int32_t rev = 0; + int32_t i = 0; + + phy = (struct ad9361_rf_phy *)zmalloc(sizeof(*phy)); + if (!phy) { + return -ENOMEM; + } + + phy->clk_refin = (struct clk *)zmalloc(sizeof(*phy->clk_refin)); + if (!phy->clk_refin) { + return -ENOMEM; + } + + phy->pdata = (struct ad9361_phy_platform_data *)zmalloc(sizeof(*phy->pdata)); + if (!phy->pdata) { + return -ENOMEM; + } + + /* Device selection */ + phy->dev_sel = init_param->dev_sel; + + /* Reference Clock */ + phy->clk_refin->rate = init_param->reference_clk_rate; + + /* Base Configuration */ + phy->pdata->fdd = init_param->frequency_division_duplex_mode_enable; + phy->pdata->fdd_independent_mode = + init_param->frequency_division_duplex_independent_mode_enable; + phy->pdata->rx2tx2 = init_param->two_rx_two_tx_mode_enable; + phy->pdata->rx1tx1_mode_use_rx_num = init_param->one_rx_one_tx_mode_use_rx_num; + phy->pdata->rx1tx1_mode_use_tx_num = init_param->one_rx_one_tx_mode_use_tx_num; + phy->pdata->tdd_use_dual_synth = init_param->tdd_use_dual_synth_mode_enable; + phy->pdata->tdd_skip_vco_cal = init_param->tdd_skip_vco_cal_enable; + phy->pdata->rx_fastlock_delay_ns = init_param->rx_fastlock_delay_ns; + phy->pdata->tx_fastlock_delay_ns = init_param->tx_fastlock_delay_ns; + phy->pdata->trx_fastlock_pinctrl_en[0] = + init_param->rx_fastlock_pincontrol_enable; + phy->pdata->trx_fastlock_pinctrl_en[1] = + init_param->tx_fastlock_pincontrol_enable; + if (phy->dev_sel == ID_AD9363A) { + phy->pdata->use_ext_rx_lo = false; + phy->pdata->use_ext_tx_lo = false; + } else { + phy->pdata->use_ext_rx_lo = init_param->external_rx_lo_enable; + phy->pdata->use_ext_tx_lo = init_param->external_tx_lo_enable; + } + phy->pdata->dc_offset_update_events = + init_param->dc_offset_tracking_update_event_mask; + phy->pdata->dc_offset_attenuation_high = + init_param->dc_offset_attenuation_high_range; + phy->pdata->dc_offset_attenuation_low = + init_param->dc_offset_attenuation_low_range; + phy->pdata->rf_dc_offset_count_high = init_param->dc_offset_count_high_range; + phy->pdata->rf_dc_offset_count_low = init_param->dc_offset_count_low_range; + phy->pdata->split_gt = init_param->split_gain_table_mode_enable; + phy->pdata->trx_synth_max_fref = + init_param->trx_synthesizer_target_fref_overwrite_hz; + phy->pdata->qec_tracking_slow_mode_en = + init_param->qec_tracking_slow_mode_enable; + + /* ENSM Control */ + phy->pdata->ensm_pin_pulse_mode = init_param->ensm_enable_pin_pulse_mode_enable; + phy->pdata->ensm_pin_ctrl = init_param->ensm_enable_txnrx_control_enable; + + /* LO Control */ + phy->pdata->rx_synth_freq = init_param->rx_synthesizer_frequency_hz; + phy->pdata->tx_synth_freq = init_param->tx_synthesizer_frequency_hz; + phy->pdata->lo_powerdown_managed_en = + init_param->tx_lo_powerdown_managed_enable; + + /* Rate & BW Control */ + for(i = 0; i < 6; i++) { + phy->pdata->rx_path_clks[i] = init_param->rx_path_clock_frequencies[i]; + } + for(i = 0; i < 6; i++) { + phy->pdata->tx_path_clks[i] = init_param->tx_path_clock_frequencies[i]; + } + phy->pdata->rf_rx_bandwidth_Hz = init_param->rf_rx_bandwidth_hz; + phy->pdata->rf_tx_bandwidth_Hz = init_param->rf_tx_bandwidth_hz; + + /* RF Port Control */ + phy->pdata->rf_rx_input_sel = init_param->rx_rf_port_input_select; + phy->pdata->rf_tx_output_sel = init_param->tx_rf_port_input_select; + + /* TX Attenuation Control */ + phy->pdata->tx_atten = init_param->tx_attenuation_mdB; + phy->pdata->update_tx_gain_via_alert = + init_param->update_tx_gain_in_alert_enable; + + /* Reference Clock Control */ + switch (phy->dev_sel) { + case ID_AD9363A: + phy->pdata->use_extclk = true; + break; + default: + phy->pdata->use_extclk = init_param->xo_disable_use_ext_refclk_enable; + } + phy->pdata->dcxo_coarse = init_param->dcxo_coarse_and_fine_tune[0]; + phy->pdata->dcxo_fine = init_param->dcxo_coarse_and_fine_tune[1]; + phy->pdata->ad9361_clkout_mode = (enum ad9361_clkout) + init_param->clk_output_mode_select; + + /* Gain Control */ + phy->pdata->gain_ctrl.rx1_mode = (enum rf_gain_ctrl_mode) + init_param->gc_rx1_mode; + phy->pdata->gain_ctrl.rx2_mode = (enum rf_gain_ctrl_mode) + init_param->gc_rx2_mode; + phy->pdata->gain_ctrl.adc_large_overload_thresh = + init_param->gc_adc_large_overload_thresh; + phy->pdata->gain_ctrl.adc_ovr_sample_size = init_param->gc_adc_ovr_sample_size; + phy->pdata->gain_ctrl.adc_small_overload_thresh = + init_param->gc_adc_small_overload_thresh; + phy->pdata->gain_ctrl.dec_pow_measuremnt_duration = + init_param->gc_dec_pow_measurement_duration; + phy->pdata->gain_ctrl.dig_gain_en = init_param->gc_dig_gain_enable; + phy->pdata->gain_ctrl.lmt_overload_high_thresh = + init_param->gc_lmt_overload_high_thresh; + phy->pdata->gain_ctrl.lmt_overload_low_thresh = + init_param->gc_lmt_overload_low_thresh; + phy->pdata->gain_ctrl.low_power_thresh = init_param->gc_low_power_thresh; + phy->pdata->gain_ctrl.max_dig_gain = init_param->gc_max_dig_gain; + phy->pdata->gain_ctrl.use_rx_fir_out_for_dec_pwr_meas = + init_param->gc_use_rx_fir_out_for_dec_pwr_meas_enable; + + /* Gain MGC Control */ + phy->pdata->gain_ctrl.mgc_dec_gain_step = init_param->mgc_dec_gain_step; + phy->pdata->gain_ctrl.mgc_inc_gain_step = init_param->mgc_inc_gain_step; + phy->pdata->gain_ctrl.mgc_rx1_ctrl_inp_en = init_param->mgc_rx1_ctrl_inp_enable; + phy->pdata->gain_ctrl.mgc_rx2_ctrl_inp_en = init_param->mgc_rx2_ctrl_inp_enable; + phy->pdata->gain_ctrl.mgc_split_table_ctrl_inp_gain_mode = + init_param->mgc_split_table_ctrl_inp_gain_mode; + + /* Gain AGC Control */ + phy->pdata->gain_ctrl.adc_large_overload_exceed_counter = + init_param->agc_adc_large_overload_exceed_counter; + phy->pdata->gain_ctrl.adc_large_overload_inc_steps = + init_param->agc_adc_large_overload_inc_steps; + phy->pdata->gain_ctrl.adc_lmt_small_overload_prevent_gain_inc = + init_param->agc_adc_lmt_small_overload_prevent_gain_inc_enable; + phy->pdata->gain_ctrl.adc_small_overload_exceed_counter = + init_param->agc_adc_small_overload_exceed_counter; + phy->pdata->gain_ctrl.dig_gain_step_size = init_param->agc_dig_gain_step_size; + phy->pdata->gain_ctrl.dig_saturation_exceed_counter = + init_param->agc_dig_saturation_exceed_counter; + phy->pdata->gain_ctrl.gain_update_interval_us = + init_param->agc_gain_update_interval_us; + phy->pdata->gain_ctrl.immed_gain_change_if_large_adc_overload = + init_param->agc_immed_gain_change_if_large_adc_overload_enable; + phy->pdata->gain_ctrl.immed_gain_change_if_large_lmt_overload = + init_param->agc_immed_gain_change_if_large_lmt_overload_enable; + phy->pdata->gain_ctrl.agc_inner_thresh_high = init_param->agc_inner_thresh_high; + phy->pdata->gain_ctrl.agc_inner_thresh_high_dec_steps = + init_param->agc_inner_thresh_high_dec_steps; + phy->pdata->gain_ctrl.agc_inner_thresh_low = init_param->agc_inner_thresh_low; + phy->pdata->gain_ctrl.agc_inner_thresh_low_inc_steps = + init_param->agc_inner_thresh_low_inc_steps; + phy->pdata->gain_ctrl.lmt_overload_large_exceed_counter = + init_param->agc_lmt_overload_large_exceed_counter; + phy->pdata->gain_ctrl.lmt_overload_large_inc_steps = + init_param->agc_lmt_overload_large_inc_steps; + phy->pdata->gain_ctrl.lmt_overload_small_exceed_counter = + init_param->agc_lmt_overload_small_exceed_counter; + phy->pdata->gain_ctrl.agc_outer_thresh_high = init_param->agc_outer_thresh_high; + phy->pdata->gain_ctrl.agc_outer_thresh_high_dec_steps = + init_param->agc_outer_thresh_high_dec_steps; + phy->pdata->gain_ctrl.agc_outer_thresh_low = init_param->agc_outer_thresh_low; + phy->pdata->gain_ctrl.agc_outer_thresh_low_inc_steps = + init_param->agc_outer_thresh_low_inc_steps; + phy->pdata->gain_ctrl.agc_attack_delay_extra_margin_us = + init_param->agc_attack_delay_extra_margin_us; + phy->pdata->gain_ctrl.sync_for_gain_counter_en = + init_param->agc_sync_for_gain_counter_enable; + + /* Fast AGC */ + phy->pdata->gain_ctrl.f_agc_dec_pow_measuremnt_duration = + init_param->fagc_dec_pow_measuremnt_duration; + phy->pdata->gain_ctrl.f_agc_state_wait_time_ns = + init_param->fagc_state_wait_time_ns; + /* Fast AGC - Low Power */ + phy->pdata->gain_ctrl.f_agc_allow_agc_gain_increase = + init_param->fagc_allow_agc_gain_increase; + phy->pdata->gain_ctrl.f_agc_lp_thresh_increment_time = + init_param->fagc_lp_thresh_increment_time; + phy->pdata->gain_ctrl.f_agc_lp_thresh_increment_steps = + init_param->fagc_lp_thresh_increment_steps; + /* Fast AGC - Lock Level (Lock Level is set via slow AGC inner high threshold) */ + phy->pdata->gain_ctrl.f_agc_lock_level_lmt_gain_increase_en = + init_param->fagc_lock_level_lmt_gain_increase_en; + phy->pdata->gain_ctrl.f_agc_lock_level_gain_increase_upper_limit = + init_param->fagc_lock_level_gain_increase_upper_limit; + /* Fast AGC - Peak Detectors and Final Settling */ + phy->pdata->gain_ctrl.f_agc_lpf_final_settling_steps = + init_param->fagc_lpf_final_settling_steps; + phy->pdata->gain_ctrl.f_agc_lmt_final_settling_steps = + init_param->fagc_lmt_final_settling_steps; + phy->pdata->gain_ctrl.f_agc_final_overrange_count = + init_param->fagc_final_overrange_count; + /* Fast AGC - Final Power Test */ + phy->pdata->gain_ctrl.f_agc_gain_increase_after_gain_lock_en = + init_param->fagc_gain_increase_after_gain_lock_en; + /* Fast AGC - Unlocking the Gain */ + phy->pdata->gain_ctrl.f_agc_gain_index_type_after_exit_rx_mode = + (enum f_agc_target_gain_index_type) + init_param->fagc_gain_index_type_after_exit_rx_mode; + phy->pdata->gain_ctrl.f_agc_use_last_lock_level_for_set_gain_en = + init_param->fagc_use_last_lock_level_for_set_gain_en; + phy->pdata->gain_ctrl.f_agc_rst_gla_stronger_sig_thresh_exceeded_en = + init_param->fagc_rst_gla_stronger_sig_thresh_exceeded_en; + phy->pdata->gain_ctrl.f_agc_optimized_gain_offset = + init_param->fagc_optimized_gain_offset; + phy->pdata->gain_ctrl.f_agc_rst_gla_stronger_sig_thresh_above_ll = + init_param->fagc_rst_gla_stronger_sig_thresh_above_ll; + phy->pdata->gain_ctrl.f_agc_rst_gla_engergy_lost_sig_thresh_exceeded_en = + init_param->fagc_rst_gla_engergy_lost_sig_thresh_exceeded_en; + phy->pdata->gain_ctrl.f_agc_rst_gla_engergy_lost_goto_optim_gain_en = + init_param->fagc_rst_gla_engergy_lost_goto_optim_gain_en; + phy->pdata->gain_ctrl.f_agc_rst_gla_engergy_lost_sig_thresh_below_ll = + init_param->fagc_rst_gla_engergy_lost_sig_thresh_below_ll; + phy->pdata->gain_ctrl.f_agc_energy_lost_stronger_sig_gain_lock_exit_cnt = + init_param->fagc_energy_lost_stronger_sig_gain_lock_exit_cnt; + phy->pdata->gain_ctrl.f_agc_rst_gla_large_adc_overload_en = + init_param->fagc_rst_gla_large_adc_overload_en; + phy->pdata->gain_ctrl.f_agc_rst_gla_large_lmt_overload_en = + init_param->fagc_rst_gla_large_lmt_overload_en; + phy->pdata->gain_ctrl.f_agc_rst_gla_en_agc_pulled_high_en = + init_param->fagc_rst_gla_en_agc_pulled_high_en; + phy->pdata->gain_ctrl.f_agc_rst_gla_if_en_agc_pulled_high_mode = + (enum f_agc_target_gain_index_type) + init_param->fagc_rst_gla_if_en_agc_pulled_high_mode; + phy->pdata->gain_ctrl.f_agc_power_measurement_duration_in_state5 = + init_param->fagc_power_measurement_duration_in_state5; + phy->pdata->gain_ctrl.f_agc_large_overload_inc_steps = + init_param->fagc_large_overload_inc_steps; + + /* RSSI Control */ + phy->pdata->rssi_ctrl.rssi_delay = init_param->rssi_delay; + phy->pdata->rssi_ctrl.rssi_duration = init_param->rssi_duration; + phy->pdata->rssi_ctrl.restart_mode = (enum rssi_restart_mode) + init_param->rssi_restart_mode; + phy->pdata->rssi_ctrl.rssi_unit_is_rx_samples = + init_param->rssi_unit_is_rx_samples_enable; + phy->pdata->rssi_ctrl.rssi_wait = init_param->rssi_wait; + + /* Aux ADC Control */ + phy->pdata->auxadc_ctrl.auxadc_decimation = init_param->aux_adc_decimation; + phy->pdata->auxadc_ctrl.auxadc_clock_rate = init_param->aux_adc_rate; + + /* AuxDAC Control */ + phy->pdata->auxdac_ctrl.auxdac_manual_mode_en = + init_param->aux_dac_manual_mode_enable; + phy->pdata->auxdac_ctrl.dac1_default_value = + init_param->aux_dac1_default_value_mV; + phy->pdata->auxdac_ctrl.dac1_in_rx_en = + init_param->aux_dac1_active_in_rx_enable; + phy->pdata->auxdac_ctrl.dac1_in_tx_en = + init_param->aux_dac1_active_in_tx_enable; + phy->pdata->auxdac_ctrl.dac1_in_alert_en = + init_param->aux_dac1_active_in_alert_enable; + phy->pdata->auxdac_ctrl.dac1_rx_delay_us = init_param->aux_dac1_rx_delay_us; + phy->pdata->auxdac_ctrl.dac1_tx_delay_us = init_param->aux_dac1_tx_delay_us; + phy->pdata->auxdac_ctrl.dac2_default_value = + init_param->aux_dac2_default_value_mV; + phy->pdata->auxdac_ctrl.dac2_in_rx_en = + init_param->aux_dac2_active_in_rx_enable; + phy->pdata->auxdac_ctrl.dac2_in_tx_en = + init_param->aux_dac2_active_in_tx_enable; + phy->pdata->auxdac_ctrl.dac2_in_alert_en = + init_param->aux_dac2_active_in_alert_enable; + phy->pdata->auxdac_ctrl.dac2_rx_delay_us = init_param->aux_dac2_rx_delay_us; + phy->pdata->auxdac_ctrl.dac2_tx_delay_us = init_param->aux_dac2_tx_delay_us; + + /* Temperature Sensor Control */ + phy->pdata->auxadc_ctrl.temp_sensor_decimation = + init_param->temp_sense_decimation; + phy->pdata->auxadc_ctrl.temp_time_inteval_ms = + init_param->temp_sense_measurement_interval_ms; + phy->pdata->auxadc_ctrl.offset = init_param->temp_sense_offset_signed; + phy->pdata->auxadc_ctrl.periodic_temp_measuremnt = + init_param->temp_sense_periodic_measurement_enable; + + /* Control Out Setup */ + phy->pdata->ctrl_outs_ctrl.en_mask = init_param->ctrl_outs_enable_mask; + phy->pdata->ctrl_outs_ctrl.index = init_param->ctrl_outs_index; + + /* External LNA Control */ + phy->pdata->elna_ctrl.settling_delay_ns = init_param->elna_settling_delay_ns; + phy->pdata->elna_ctrl.gain_mdB = init_param->elna_gain_mdB; + phy->pdata->elna_ctrl.bypass_loss_mdB = init_param->elna_bypass_loss_mdB; + phy->pdata->elna_ctrl.elna_1_control_en = + init_param->elna_rx1_gpo0_control_enable; + phy->pdata->elna_ctrl.elna_2_control_en = + init_param->elna_rx2_gpo1_control_enable; + phy->pdata->elna_ctrl.elna_in_gaintable_all_index_en = + init_param->elna_gaintable_all_index_enable; + + /* Digital Interface Control */ + phy->pdata->dig_interface_tune_skipmode = + (init_param->digital_interface_tune_skip_mode); + phy->pdata->dig_interface_tune_fir_disable = + (init_param->digital_interface_tune_fir_disable); + phy->pdata->port_ctrl.pp_conf[0] = (init_param->pp_tx_swap_enable << 7); + phy->pdata->port_ctrl.pp_conf[0] |= (init_param->pp_rx_swap_enable << 6); + phy->pdata->port_ctrl.pp_conf[0] |= (init_param->tx_channel_swap_enable << 5); + phy->pdata->port_ctrl.pp_conf[0] |= (init_param->rx_channel_swap_enable << 4); + phy->pdata->port_ctrl.pp_conf[0] |= (init_param->rx_frame_pulse_mode_enable << + 3); + phy->pdata->port_ctrl.pp_conf[0] |= (init_param->two_t_two_r_timing_enable << + 2); + phy->pdata->port_ctrl.pp_conf[0] |= (init_param->invert_data_bus_enable << 1); + phy->pdata->port_ctrl.pp_conf[0] |= (init_param->invert_data_clk_enable << 0); + phy->pdata->port_ctrl.pp_conf[1] = (init_param->fdd_alt_word_order_enable << 7); + phy->pdata->port_ctrl.pp_conf[1] |= (init_param->invert_rx_frame_enable << 2); + phy->pdata->port_ctrl.pp_conf[2] = (init_param->fdd_rx_rate_2tx_enable << 7); + phy->pdata->port_ctrl.pp_conf[2] |= (init_param->swap_ports_enable << 6); + phy->pdata->port_ctrl.pp_conf[2] |= (init_param->single_data_rate_enable << 5); + phy->pdata->port_ctrl.pp_conf[2] |= (init_param->lvds_mode_enable << 4); + phy->pdata->port_ctrl.pp_conf[2] |= (init_param->half_duplex_mode_enable << 3); + phy->pdata->port_ctrl.pp_conf[2] |= (init_param->single_port_mode_enable << 2); + phy->pdata->port_ctrl.pp_conf[2] |= (init_param->full_port_enable << 1); + phy->pdata->port_ctrl.pp_conf[2] |= (init_param->full_duplex_swap_bits_enable << + 0); + phy->pdata->port_ctrl.pp_conf[1] |= (init_param->delay_rx_data & 0x3); + phy->pdata->port_ctrl.rx_clk_data_delay = DATA_CLK_DELAY( + init_param->rx_data_clock_delay); + phy->pdata->port_ctrl.rx_clk_data_delay |= RX_DATA_DELAY( + init_param->rx_data_delay); + phy->pdata->port_ctrl.tx_clk_data_delay = FB_CLK_DELAY( + init_param->tx_fb_clock_delay); + phy->pdata->port_ctrl.tx_clk_data_delay |= TX_DATA_DELAY( + init_param->tx_data_delay); + phy->pdata->port_ctrl.lvds_bias_ctrl = ((init_param->lvds_bias_mV - 75) / 75) & + 0x7; + phy->pdata->port_ctrl.lvds_bias_ctrl |= + (init_param->lvds_rx_onchip_termination_enable << 5); + phy->pdata->rx1rx2_phase_inversion_en = init_param->rx1rx2_phase_inversion_en; + + /* GPO Control */ + phy->pdata->gpo_ctrl.gpo_manual_mode_en = + init_param->gpo_manual_mode_enable; + phy->pdata->gpo_ctrl.gpo_manual_mode_enable_mask = + init_param->gpo_manual_mode_enable_mask; + phy->pdata->gpo_ctrl.gpo0_inactive_state_high_en = + init_param->gpo0_inactive_state_high_enable; + phy->pdata->gpo_ctrl.gpo1_inactive_state_high_en = + init_param->gpo1_inactive_state_high_enable; + phy->pdata->gpo_ctrl.gpo2_inactive_state_high_en = + init_param->gpo2_inactive_state_high_enable; + phy->pdata->gpo_ctrl.gpo3_inactive_state_high_en = + init_param->gpo3_inactive_state_high_enable; + + phy->pdata->gpo_ctrl.gpo0_slave_rx_en = init_param->gpo0_slave_rx_enable; + phy->pdata->gpo_ctrl.gpo0_slave_tx_en = init_param->gpo0_slave_tx_enable; + phy->pdata->gpo_ctrl.gpo1_slave_rx_en = init_param->gpo1_slave_rx_enable; + phy->pdata->gpo_ctrl.gpo1_slave_tx_en = init_param->gpo1_slave_tx_enable; + phy->pdata->gpo_ctrl.gpo2_slave_rx_en = init_param->gpo2_slave_rx_enable; + phy->pdata->gpo_ctrl.gpo2_slave_tx_en = init_param->gpo2_slave_tx_enable; + phy->pdata->gpo_ctrl.gpo3_slave_rx_en = init_param->gpo3_slave_rx_enable; + phy->pdata->gpo_ctrl.gpo3_slave_tx_en = init_param->gpo3_slave_tx_enable; + + phy->pdata->gpo_ctrl.gpo0_rx_delay_us = init_param->gpo0_rx_delay_us; + phy->pdata->gpo_ctrl.gpo0_tx_delay_us = init_param->gpo0_tx_delay_us; + phy->pdata->gpo_ctrl.gpo1_rx_delay_us = init_param->gpo1_rx_delay_us; + phy->pdata->gpo_ctrl.gpo1_tx_delay_us = init_param->gpo1_tx_delay_us; + phy->pdata->gpo_ctrl.gpo2_rx_delay_us = init_param->gpo2_rx_delay_us; + phy->pdata->gpo_ctrl.gpo2_tx_delay_us = init_param->gpo2_tx_delay_us; + phy->pdata->gpo_ctrl.gpo3_rx_delay_us = init_param->gpo3_rx_delay_us; + phy->pdata->gpo_ctrl.gpo3_tx_delay_us = init_param->gpo3_tx_delay_us; + + /* Tx Monitor Control */ + phy->pdata->txmon_ctrl.low_high_gain_threshold_mdB = + init_param->low_high_gain_threshold_mdB; + phy->pdata->txmon_ctrl.low_gain_dB = init_param->low_gain_dB; + phy->pdata->txmon_ctrl.high_gain_dB = init_param->high_gain_dB; + phy->pdata->txmon_ctrl.tx_mon_track_en = init_param->tx_mon_track_en; + phy->pdata->txmon_ctrl.one_shot_mode_en = init_param->one_shot_mode_en; + phy->pdata->txmon_ctrl.tx_mon_delay = init_param->tx_mon_delay; + phy->pdata->txmon_ctrl.tx_mon_duration = init_param->tx_mon_duration; + phy->pdata->txmon_ctrl.tx1_mon_front_end_gain = + init_param->tx1_mon_front_end_gain; + phy->pdata->txmon_ctrl.tx2_mon_front_end_gain = + init_param->tx2_mon_front_end_gain; + phy->pdata->txmon_ctrl.tx1_mon_lo_cm = init_param->tx1_mon_lo_cm; + phy->pdata->txmon_ctrl.tx2_mon_lo_cm = init_param->tx2_mon_lo_cm; + + phy->pdata->debug_mode = true; + + gpio_get(&phy->gpio_desc_resetb, &init_param->gpio_resetb); + /* Optional: next three GPIOs are used for MCS synchronization */ + gpio_get_optional(&phy->gpio_desc_sync, &init_param->gpio_sync); + gpio_get_optional(&phy->gpio_desc_cal_sw1, &init_param->gpio_cal_sw1); + gpio_get_optional(&phy->gpio_desc_cal_sw2, &init_param->gpio_cal_sw2); + + gpio_direction_output(phy->gpio_desc_resetb, 0); + + spi_init(&phy->spi, &init_param->spi_param); + + phy->pdata->port_ctrl.digital_io_ctrl = 0; + phy->pdata->port_ctrl.lvds_invert[0] = init_param->lvds_invert1_control; + phy->pdata->port_ctrl.lvds_invert[1] = init_param->lvds_invert2_control; + + if (AD9364_DEVICE) { + phy->pdata->rx2tx2 = false; + phy->pdata->rx1tx1_mode_use_rx_num = 1; + phy->pdata->rx1tx1_mode_use_tx_num = 1; + } + + phy->rx_eq_2tx = false; + + phy->current_table = -1; + phy->bypass_tx_fir = true; + phy->bypass_rx_fir = true; + phy->rate_governor = 1; + phy->rfdc_track_en = true; + phy->bbdc_track_en = true; + phy->quad_track_en = true; + + phy->gt_info = ad9361_adi_gt_info; + + phy->bist_loopback_mode = 0; + phy->bist_config = 0; + phy->bist_prbs_mode = BIST_DISABLE; + phy->bist_tone_mode = BIST_DISABLE; + phy->bist_tone_freq_Hz = 0; + phy->bist_tone_level_dB = 0; + phy->bist_tone_mask = 0; + + ad9361_reset(phy); + + ret = ad9361_spi_read(phy->spi, REG_PRODUCT_ID); + if ((ret & PRODUCT_ID_MASK) != PRODUCT_ID_9361) { + printf("%s : Unsupported PRODUCT_ID 0x%X", __func__, (unsigned int)ret); + ret = -ENODEV; + goto out; + } + rev = ret & REV_MASK; + + phy->ad9361_rfpll_ext_recalc_rate = init_param->ad9361_rfpll_ext_recalc_rate; + phy->ad9361_rfpll_ext_round_rate = init_param->ad9361_rfpll_ext_round_rate; + phy->ad9361_rfpll_ext_set_rate = init_param->ad9361_rfpll_ext_set_rate; + + ret = ad9361_register_clocks(phy); + if (ret < 0) + goto out; + + ret = ad9361_setup(phy); + if (ret < 0) + goto out_clk; + + printf("%s : AD936x Rev %d successfully initialized\n", __func__, (int)rev); + + *ad9361_phy = phy; + + return 0; + +out_clk: + ad9361_unregister_clocks(phy); +out: + free(phy->clk_refin); + free(phy->pdata); + free(phy); + printf("%s : AD936x initialization error\n", __func__); + + return -ENODEV; +} + +/** + * Free the allocated resources. + * @param phy The AD9361 current state structure. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_remove(struct ad9361_rf_phy *phy) +{ + ad9361_unregister_clocks(phy); + spi_remove(phy->spi); + gpio_remove(phy->gpio_desc_resetb); + gpio_remove(phy->gpio_desc_sync); + gpio_remove(phy->gpio_desc_cal_sw1); + gpio_remove(phy->gpio_desc_cal_sw2); + free(phy->clk_refin); + free(phy->pdata); + free(phy); + + return 0; +} + +/** + * Set the Enable State Machine (ENSM) mode. + * @param phy The AD9361 current state structure. + * @param mode The ENSM mode. + * Accepted values: + * ENSM_MODE_TX + * ENSM_MODE_RX + * ENSM_MODE_ALERT + * ENSM_MODE_FDD + * ENSM_MODE_WAIT + * ENSM_MODE_SLEEP + * ENSM_MODE_PINCTRL + * ENSM_MODE_PINCTRL_FDD_INDEP + * @return 0 in case of success, negative error code otherwise. + * + * Note: This function will/may affect the data path. + */ +int32_t ad9361_set_en_state_machine_mode (struct ad9361_rf_phy *phy, + uint32_t mode) +{ + int32_t ret; + uint8_t ensm_state; + bool pinctrl = false; + + phy->pdata->fdd_independent_mode = false; + + switch (mode) { + case ENSM_MODE_TX: + ensm_state = ENSM_STATE_TX; + break; + case ENSM_MODE_RX: + ensm_state = ENSM_STATE_RX; + break; + case ENSM_MODE_ALERT: + ensm_state = ENSM_STATE_ALERT; + break; + case ENSM_MODE_FDD: + ensm_state = ENSM_STATE_FDD; + break; + case ENSM_MODE_WAIT: + ensm_state = ENSM_STATE_SLEEP_WAIT; + break; + case ENSM_MODE_SLEEP: + ensm_state = ENSM_STATE_SLEEP; + break; + case ENSM_MODE_PINCTRL: + ensm_state = ENSM_STATE_SLEEP_WAIT; + pinctrl = true; + break; + case ENSM_MODE_PINCTRL_FDD_INDEP: + ensm_state = ENSM_STATE_FDD; + phy->pdata->fdd_independent_mode = true; + break; + default: + return -EINVAL; + } + + ad9361_set_ensm_mode(phy, phy->pdata->fdd, pinctrl); + ret = ad9361_ensm_set_state(phy, ensm_state, pinctrl); + + return ret; +} + +/** + * Get the Enable State Machine (ENSM) mode. + * @param phy The AD9361 current state structure. + * @param mode A variable to store the selected ENSM mode. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_get_en_state_machine_mode (struct ad9361_rf_phy *phy, + uint32_t *mode) +{ + uint8_t ensm_state; + bool pinctrl = false; + int32_t ret; + + ensm_state = ad9361_spi_read(phy->spi, REG_STATE); + ensm_state &= ENSM_STATE(~0); + ret = ad9361_spi_read(phy->spi, REG_ENSM_CONFIG_1); + if ((ret & ENABLE_ENSM_PIN_CTRL) == ENABLE_ENSM_PIN_CTRL) + pinctrl = true; + + switch (ensm_state) { + case ENSM_STATE_TX: + *mode = ENSM_MODE_TX; + break; + case ENSM_STATE_RX: + *mode = ENSM_MODE_RX; + break; + case ENSM_STATE_ALERT: + *mode = ENSM_MODE_ALERT; + break; + case ENSM_STATE_FDD: + if (phy->pdata->fdd_independent_mode) + *mode = ENSM_MODE_PINCTRL_FDD_INDEP; + else + *mode = ENSM_MODE_FDD; + break; + case ENSM_STATE_SLEEP_WAIT: + if (pinctrl) + *mode = ENSM_MODE_PINCTRL; + else + *mode = ENSM_MODE_WAIT; + break; + case ENSM_STATE_SLEEP: + *mode = ENSM_MODE_SLEEP; + break; + default: + return -EINVAL; + } + + return 0; +} + +/** + * Set the receive RF gain for the selected channel. + * @param phy The AD9361 current state structure. + * @param ch The desired channel number (RX1, RX2). + * Accepted values in 2x2 mode: + * RX1 (0) + * RX2 (1) + * Accepted values in 1x1 mode: + * RX1 (0) + * @param gain_db The RF gain (dB). + * Example: + * 10 (10 dB) + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_set_rx_rf_gain (struct ad9361_rf_phy *phy, + uint8_t ch, int32_t gain_db) +{ + struct rf_rx_gain rx_gain = {0, 0, 0, 0, 0, 0, 0, 0, 0}; + int32_t ret = 0; + + rx_gain.gain_db = gain_db; + ret = ad9361_set_rx_gain(phy, + ad9361_1rx1tx_channel_map(phy, false, + ch + 1), &rx_gain); + + return ret; +} + +/** + * Get current receive RF gain for the selected channel. + * @param phy The AD9361 current state structure. + * @param ch The desired channel number (RX1, RX2). + * Accepted values in 2x2 mode: + * RX1 (0) + * RX2 (1) + * Accepted values in 1x1 mode: + * RX1 (0) + * @param gain_db A variable to store the RF gain (dB). + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_get_rx_rf_gain (struct ad9361_rf_phy *phy, + uint8_t ch, int32_t *gain_db) +{ + struct rf_rx_gain rx_gain = {0, 0, 0, 0, 0, 0, 0, 0, 0}; + int32_t ret = 0; + + ret = ad9361_get_rx_gain(phy, ad9361_1rx1tx_channel_map(phy, + false, ch + 1), &rx_gain); + + *gain_db = rx_gain.gain_db; + + return ret; +} + +/** + * Set the RX RF bandwidth. + * @param phy The AD9361 current state structure. + * @param bandwidth_hz The desired bandwidth (Hz). + * Example: + * 18000000 (18 MHz) + * @return 0 in case of success, negative error code otherwise. + * + * Note: This function will/may affect the data path. + */ +int32_t ad9361_set_rx_rf_bandwidth (struct ad9361_rf_phy *phy, + uint32_t bandwidth_hz) +{ + int32_t ret = 0; + + bandwidth_hz = ad9361_validate_rf_bw(phy, bandwidth_hz); + + if (phy->current_rx_bw_Hz != bandwidth_hz) + ret = ad9361_update_rf_bandwidth(phy, bandwidth_hz, + phy->current_tx_bw_Hz); + else + ret = 0; + + return ret; +} + +/** + * Get the RX RF bandwidth. + * @param phy The AD9361 current state structure. + * @param bandwidth_hz A variable to store the bandwidth value (Hz). + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_get_rx_rf_bandwidth (struct ad9361_rf_phy *phy, + uint32_t *bandwidth_hz) +{ + *bandwidth_hz = phy->current_rx_bw_Hz; + + return 0; +} + +/** + * Set the RX sampling frequency. + * @param phy The AD9361 current state structure. + * @param sampling_freq_hz The desired frequency (Hz). + * Example: + * 30720000 (30.72 MHz) + * @return 0 in case of success, negative error code otherwise. + * + * Note: This function will/may affect the data path. + */ +int32_t ad9361_set_rx_sampling_freq (struct ad9361_rf_phy *phy, + uint32_t sampling_freq_hz) +{ + int32_t ret; + uint32_t rx[6], tx[6]; + + ret = ad9361_calculate_rf_clock_chain(phy, sampling_freq_hz, + phy->rate_governor, rx, tx); + if (ret < 0) + return ret; + + ad9361_set_trx_clock_chain(phy, rx, tx); + + ret = ad9361_update_rf_bandwidth(phy, phy->current_rx_bw_Hz, + phy->current_tx_bw_Hz); + + return ret; +} + +/** + * Get current RX sampling frequency. + * @param phy The AD9361 current state structure. + * @param sampling_freq_hz A variable to store the frequency value (Hz). + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_get_rx_sampling_freq (struct ad9361_rf_phy *phy, + uint32_t *sampling_freq_hz) +{ + *sampling_freq_hz = (uint32_t)clk_get_rate(phy, + phy->ref_clk_scale[RX_SAMPL_CLK]); + + return 0; +} + +/** + * Set the RX LO frequency. + * @param phy The AD9361 current state structure. + * @param lo_freq_hz The desired frequency (Hz). + * Example: + * 2400000000 (2.4 GHz) + * @return 0 in case of success, negative error code otherwise. + * + * Note: This function will/may affect the data path. + */ +int32_t ad9361_set_rx_lo_freq (struct ad9361_rf_phy *phy, + uint64_t lo_freq_hz) +{ + int32_t ret; + + ret = clk_set_rate(phy, phy->ref_clk_scale[RX_RFPLL], + ad9361_to_clk(lo_freq_hz)); + + return ret; +} + +/** + * Get current RX LO frequency. + * @param phy The AD9361 current state structure. + * @param lo_freq_hz A variable to store the frequency value (Hz). + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_get_rx_lo_freq (struct ad9361_rf_phy *phy, + uint64_t *lo_freq_hz) +{ + *lo_freq_hz = ad9361_from_clk(clk_get_rate(phy, + phy->ref_clk_scale[RX_RFPLL])); + + return 0; +} + +/** + * Switch between internal and external LO. + * @param phy The AD9361 state structure. + * @param int_ext The selected lo (INT_LO, EXT_LO). + * Accepted values: + * INT_LO + * EXT_LO + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_set_rx_lo_int_ext(struct ad9361_rf_phy *phy, uint8_t int_ext) +{ + if ((phy->dev_sel == ID_AD9363A) && (int_ext == EXT_LO)) { + printf("%s : EXT_LO is not supported by AD9363!\n", __func__); + return -1; + } + + phy->pdata->use_ext_rx_lo = int_ext; + + return ad9361_clk_mux_set_parent(phy->ref_clk_scale[RX_RFPLL], int_ext); +} + +/** + * Get the RSSI for the selected channel. + * @param phy The AD9361 current state structure. + * @param ch The desired channel (RX1, RX2). + * Accepted values in 2x2 mode: + * RX1 (0) + * RX2 (1) + * Accepted values in 1x1 mode: + * RX1 (0) + * @param rssi A variable to store the RSSI. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_get_rx_rssi (struct ad9361_rf_phy *phy, + uint8_t ch, struct rf_rssi *rssi) +{ + int32_t ret; + + rssi->ant = ad9361_1rx1tx_channel_map(phy, false, ch + 1); + rssi->duration = 1; + ret = ad9361_read_rssi(phy, rssi); + + return ret; +} + +/** + * Set the gain control mode for the selected channel. + * @param phy The AD9361 current state structure. + * @param ch The desired channel (RX1, RX2). + * Accepted values in 2x2 mode: + * RX1 (0) + * RX2 (1) + * Accepted values in 1x1 mode: + * RX1 (0) + * @param gc_mode The gain control mode (manual, fast_attack, slow_attack, + * hybrid). + * Accepted values: + * RF_GAIN_MGC (manual) + * RF_GAIN_FASTATTACK_AGC (fast_attack) + * RF_GAIN_SLOWATTACK_AGC (slow_attack) + * RF_GAIN_HYBRID_AGC (hybrid) + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_set_rx_gain_control_mode (struct ad9361_rf_phy *phy, + uint8_t ch, uint8_t gc_mode) +{ + struct rf_gain_ctrl gc = {0, 0}; + + gc.ant = ad9361_1rx1tx_channel_map(phy, false, ch + 1); + gc.mode = phy->agc_mode[ch] = gc_mode; + + ad9361_set_gain_ctrl_mode(phy, &gc); + + return 0; +} + +/** + * Get the gain control mode for the selected channel. + * @param phy The AD9361 current state structure. + * @param ch The desired channel (RX1, RX2). + * Accepted values: + * RX1 (0) + * RX2 (1) + * @param gc_mode A variable to store the gain control mode. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_get_rx_gain_control_mode (struct ad9361_rf_phy *phy, + uint8_t ch, uint8_t *gc_mode) +{ + *gc_mode = phy->agc_mode[ch]; + + return 0; +} + +/** + * Set the RX FIR filter configuration. + * @param phy The AD9361 current state structure. + * @param fir_cfg FIR filter configuration. + * @return 0 in case of success, negative error code otherwise. + * + * Note: This function will/may affect the data path. + */ +int32_t ad9361_set_rx_fir_config (struct ad9361_rf_phy *phy, + AD9361_RXFIRConfig fir_cfg) +{ + int32_t ret; + + phy->rx_fir_dec = fir_cfg.rx_dec; + ret = ad9361_load_fir_filter_coef(phy, (enum fir_dest)(fir_cfg.rx | FIR_IS_RX), + fir_cfg.rx_gain, fir_cfg.rx_coef_size, fir_cfg.rx_coef); + + return ret; +} + +/** + * Get the RX FIR filter configuration. + * @param phy The AD9361 current state structure. + * @param rx_ch The selected RX channel (RX1, RX2). + * Accepted values: + * RX1 (0) + * RX2 (1) + * @param fir_cfg FIR filter configuration output file. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_get_rx_fir_config(struct ad9361_rf_phy *phy, uint8_t rx_ch, + AD9361_RXFIRConfig *fir_cfg) +{ + int32_t ret; + uint32_t fir_conf; + uint8_t index; + + rx_ch += 1; + + ret = ad9361_spi_read(phy->spi, REG_RX_FILTER_CONFIG); + if(ret < 0) + return ret; + fir_conf = ret; + + fir_cfg->rx_coef_size = (((fir_conf & FIR_NUM_TAPS(7)) >> 5) + 1) * 16; + + ret = ad9361_spi_read(phy->spi, REG_RX_FILTER_GAIN); + if(ret < 0) + return ret; + fir_cfg->rx_gain = -6 * (ret & FILTER_GAIN(3)) + 6; + fir_cfg->rx = rx_ch; + + fir_conf &= ~FIR_SELECT(3); + fir_conf |= FIR_SELECT(rx_ch) | FIR_START_CLK; + ad9361_spi_write(phy->spi, REG_RX_FILTER_CONFIG, fir_conf); + + for(index = 0; index < 128; index++) { + ad9361_spi_write(phy->spi, REG_RX_FILTER_COEF_ADDR, index); + ret = ad9361_spi_read(phy->spi, REG_RX_FILTER_COEF_READ_DATA_1); + if(ret < 0) + return ret; + fir_cfg->rx_coef[index] = ret; + ret = ad9361_spi_read(phy->spi, REG_RX_FILTER_COEF_READ_DATA_2); + if(ret < 0) + return ret; + fir_cfg->rx_coef[index] |= (ret << 8); + } + + fir_conf &= ~FIR_START_CLK; + ad9361_spi_write(phy->spi, REG_RX_FILTER_CONFIG, fir_conf); + + fir_cfg->rx_dec = phy->rx_fir_dec; + + return 0; +} + +/** + * Enable/disable the RX FIR filter. + * @param phy The AD9361 current state structure. + * @param en_dis The option (ENABLE, DISABLE). + * Accepted values: + * ENABLE (1) + * DISABLE (0) + * @return 0 in case of success, negative error code otherwise. + * + * Note: This function will/may affect the data path. + */ +int32_t ad9361_set_rx_fir_en_dis (struct ad9361_rf_phy *phy, + uint8_t en_dis) +{ + int32_t ret = 0; + + if(phy->bypass_rx_fir == !en_dis) + return ret; + + phy->bypass_rx_fir = !en_dis; + ret = ad9361_validate_enable_fir(phy); + if (ret < 0) { + phy->bypass_rx_fir = true; + } + + return ret; +} + +/** + * Get the status of the RX FIR filter. + * @param phy The AD9361 current state structure. + * @param en_dis The enable/disable status buffer. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_get_rx_fir_en_dis (struct ad9361_rf_phy *phy, + uint8_t *en_dis) +{ + *en_dis = !phy->bypass_rx_fir; + + return 0; +} + +/** + * Enable/disable the RX RFDC Tracking. + * @param phy The AD9361 current state structure. + * @param en_dis The option (ENABLE, DISABLE). + * Accepted values: + * ENABLE (1) + * DISABLE (0) + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_set_rx_rfdc_track_en_dis (struct ad9361_rf_phy *phy, + uint8_t en_dis) +{ + int32_t ret = 0; + + if(phy->rfdc_track_en == en_dis) + return ret; + + phy->rfdc_track_en = en_dis; + ret = ad9361_tracking_control(phy, phy->bbdc_track_en, + phy->rfdc_track_en, phy->quad_track_en); + + return ret; +} + +/** + * Get the status of the RX RFDC Tracking. + * @param phy The AD9361 current state structure. + * @param en_dis The enable/disable status buffer. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_get_rx_rfdc_track_en_dis (struct ad9361_rf_phy *phy, + uint8_t *en_dis) +{ + *en_dis = phy->rfdc_track_en; + + return 0; +} + +/** + * Enable/disable the RX BasebandDC Tracking. + * @param phy The AD9361 current state structure. + * @param en_dis The option (ENABLE, DISABLE). + * Accepted values: + * ENABLE (1) + * DISABLE (0) + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_set_rx_bbdc_track_en_dis (struct ad9361_rf_phy *phy, + uint8_t en_dis) +{ + int32_t ret = 0; + + if(phy->bbdc_track_en == en_dis) + return ret; + + phy->bbdc_track_en = en_dis; + ret = ad9361_tracking_control(phy, phy->bbdc_track_en, + phy->rfdc_track_en, phy->quad_track_en); + + return ret; +} + +/** + * Get the status of the RX BasebandDC Tracking. + * @param phy The AD9361 current state structure. + * @param en_dis The enable/disable status buffer. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_get_rx_bbdc_track_en_dis (struct ad9361_rf_phy *phy, + uint8_t *en_dis) +{ + *en_dis = phy->bbdc_track_en; + + return 0; +} + +/** + * Enable/disable the RX Quadrature Tracking. + * @param phy The AD9361 current state structure. + * @param en_dis The option (ENABLE, DISABLE). + * Accepted values: + * ENABLE (1) + * DISABLE (0) + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_set_rx_quad_track_en_dis (struct ad9361_rf_phy *phy, + uint8_t en_dis) +{ + int32_t ret = 0; + + if(phy->quad_track_en == en_dis) + return ret; + + phy->quad_track_en = en_dis; + ret = ad9361_tracking_control(phy, phy->bbdc_track_en, + phy->rfdc_track_en, phy->quad_track_en); + + return ret; +} + +/** + * Get the status of the RX Quadrature Tracking. + * @param phy The AD9361 current state structure. + * @param en_dis The enable/disable status buffer. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_get_rx_quad_track_en_dis (struct ad9361_rf_phy *phy, + uint8_t *en_dis) +{ + *en_dis = phy->quad_track_en; + + return 0; +} + +/** + * Set the RX RF input port. + * @param phy The AD9361 current state structure. + * @param mode The RF port. + * Accepted values: + * A_BALANCED (0 - (RX1A_N & RX1A_P) and (RX2A_N & RX2A_P) enabled; balanced) + * B_BALANCED (1 - (RX1B_N & RX1B_P) and (RX2B_N & RX2B_P) enabled; balanced) + * C_BALANCED (2 - (RX1C_N & RX1C_P) and (RX2C_N & RX2C_P) enabled; balanced) + * A_N (3 - RX1A_N and RX2A_N enabled; unbalanced) + * A_P (4 - RX1A_P and RX2A_P enabled; unbalanced) + * B_N (5 - RX1B_N and RX2B_N enabled; unbalanced) + * B_P (6 - RX1B_P and RX2B_P enabled; unbalanced) + * C_N (7 - RX1C_N and RX2C_N enabled; unbalanced) + * C_P (8 - RX1C_P and RX2C_P enabled; unbalanced) + * TX_MON1 (9 - TX_MONITOR1) + * TX_MON2 (10 - TX_MONITOR2) + * TX_MON1_2 (11 - TX_MONITOR1 & TX_MONITOR2) + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_set_rx_rf_port_input (struct ad9361_rf_phy *phy, + uint32_t mode) +{ + int32_t ret; + + phy->pdata->rf_rx_input_sel = mode; + + ret = ad9361_rf_port_setup(phy, false, + phy->pdata->rf_rx_input_sel, + phy->pdata->rf_tx_output_sel); + + return ret; +} + +/** + * Get the selected RX RF input port. + * @param phy The AD9361 current state structure. + * @param mode The RF port. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_get_rx_rf_port_input (struct ad9361_rf_phy *phy, + uint32_t *mode) +{ + *mode = phy->pdata->rf_rx_input_sel; + + return 0; +} + +/** + * Store RX fastlock profile. + * To create a profile tune the synthesizer (ad9361_set_rx_lo_freq()) and then + * call this function specifying the target profile number. + * @param phy The AD9361 state structure. + * @param profile The profile number (0 - 7). + * Accepted values: + * 0 - 7 + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_rx_fastlock_store(struct ad9361_rf_phy *phy, uint32_t profile) +{ + return ad9361_fastlock_store(phy, 0, profile); +} + +/** + * Recall specified RX fastlock profile. + * When in fastlock pin select mode (init_param->rx_fastlock_pincontrol_enable), + * the function needs to be called before then the pin-control can be used. + * @param phy The AD9361 state structure. + * @param profile The profile number (0 - 7). + * Accepted values: + * 0 - 7 + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_rx_fastlock_recall(struct ad9361_rf_phy *phy, uint32_t profile) +{ + return ad9361_fastlock_recall(phy, 0, profile); +} + +/** + * Load RX fastlock profile. A previously saved profile can be loaded in any + * of the 8 available slots. + * @param phy The AD9361 state structure. + * @param profile The profile number (0 - 7). + * Accepted values: + * 0 - 7 + * @param values Fastlock profile program data. + * Example: + * val0,val1,val2,…,val15 + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_rx_fastlock_load(struct ad9361_rf_phy *phy, uint32_t profile, + uint8_t *values) +{ + return ad9361_fastlock_load(phy, 0, profile, values); +} + +/** + * Save RX fastlock profile. In order to use more than 8 Profiles, an existing + * profile can be read back and stored by the user application. + * @param phy The AD9361 state structure. + * @param profile The profile number (0 - 7). + * Accepted values: + * 0 - 7 + * @param values Fastlock profile program data. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_rx_fastlock_save(struct ad9361_rf_phy *phy, uint32_t profile, + uint8_t *values) +{ + return ad9361_fastlock_save(phy, 0, profile, values); +} + +/** + * Power down the RX Local Oscillator. + * @param phy The AD9361 state structure. + * @param option The option (ON, OFF). + * Accepted values: + * ON (0) + * OFF (1) + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_rx_lo_powerdown(struct ad9361_rf_phy *phy, uint8_t option) +{ + return ad9361_synth_lo_powerdown(phy, option ? LO_OFF : LO_ON, LO_DONTCARE); +} + +/** + * Get the RX Local Oscillator power status. + * @param phy The AD9361 state structure. + * @param option Store the option (ON, OFF). + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_get_rx_lo_power(struct ad9361_rf_phy *phy, uint8_t *option) +{ + *option = !(phy->cached_synth_pd[1] & RX_LO_POWER_DOWN) ? OFF : ON; + + return 0; +} + +/** + * Set the transmit attenuation for the selected channel. + * @param phy The AD9361 current state structure. + * @param ch The desired channel number (TX1, TX2). + * Accepted values in 2x2 mode: + * TX1 (0) + * TX2 (1) + * Accepted values in 1x1 mode: + * TX1 (0) + * @param attenuation_mdb The attenuation (mdB). + * Example: + * 10000 (10 dB) + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_set_tx_attenuation (struct ad9361_rf_phy *phy, + uint8_t ch, uint32_t attenuation_mdb) +{ + int32_t ret; + int32_t channel; + + channel = ad9361_1rx1tx_channel_map(phy, true, ch); + ret = ad9361_set_tx_atten(phy, attenuation_mdb, + channel == 0, channel == 1, + !phy->pdata->update_tx_gain_via_alert); + + return ret; +} + +/** + * Get current transmit attenuation for the selected channel. + * @param phy The AD9361 current state structure. + * @param ch The desired channel number (TX1, TX2). + * Accepted values in 2x2 mode: + * TX1 (0) + * TX2 (1) + * Accepted values in 1x1 mode: + * TX1 (0) + * @param attenuation_mdb A variable to store the attenuation value (mdB). + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_get_tx_attenuation (struct ad9361_rf_phy *phy, + uint8_t ch, uint32_t *attenuation_mdb) +{ + int32_t ret; + + ret = ad9361_get_tx_atten(phy, + ad9361_1rx1tx_channel_map(phy, true, + ch + 1)); + + if(ret < 0) + return ret; + *attenuation_mdb = ret; + + return 0; +} + +/** + * Set the TX RF bandwidth. + * @param phy The AD9361 current state structure. + * @param bandwidth_hz The desired bandwidth (Hz). + * Example: + * 18000000 (18 MHz) + * @return 0 in case of success, negative error code otherwise. + * + * Note: This function will/may affect the data path. + */ +int32_t ad9361_set_tx_rf_bandwidth (struct ad9361_rf_phy *phy, + uint32_t bandwidth_hz) +{ + int32_t ret = 0; + + bandwidth_hz = ad9361_validate_rf_bw(phy, bandwidth_hz); + + if (phy->current_tx_bw_Hz != bandwidth_hz) + ret = ad9361_update_rf_bandwidth(phy, + phy->current_rx_bw_Hz, bandwidth_hz); + else + ret = 0; + + return ret; +} + +/** + * Get the TX RF bandwidth. + * @param phy The AD9361 current state structure. + * @param bandwidth_hz A variable to store the bandwidth value (Hz). + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_get_tx_rf_bandwidth (struct ad9361_rf_phy *phy, + uint32_t *bandwidth_hz) +{ + *bandwidth_hz = phy->current_tx_bw_Hz; + + return 0; +} + +/** + * Set the TX sampling frequency. + * @param phy The AD9361 current state structure. + * @param sampling_freq_hz The desired frequency (Hz). + * Example: + * 30720000 (30.72 MHz) + * @return 0 in case of success, negative error code otherwise. + * + * Note: This function will/may affect the data path. + */ +int32_t ad9361_set_tx_sampling_freq (struct ad9361_rf_phy *phy, + uint32_t sampling_freq_hz) +{ + int32_t ret; + uint32_t rx[6], tx[6]; + + ret = ad9361_calculate_rf_clock_chain(phy, sampling_freq_hz, + phy->rate_governor, rx, tx); + if (ret < 0) + return ret; + + ad9361_set_trx_clock_chain(phy, rx, tx); + + ret = ad9361_update_rf_bandwidth(phy, phy->current_rx_bw_Hz, + phy->current_tx_bw_Hz); + + return ret; +} + +/** + * Get current TX sampling frequency. + * @param phy The AD9361 current state structure. + * @param sampling_freq_hz A variable to store the frequency value (Hz). + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_get_tx_sampling_freq (struct ad9361_rf_phy *phy, + uint32_t *sampling_freq_hz) +{ + *sampling_freq_hz = (uint32_t)clk_get_rate(phy, + phy->ref_clk_scale[TX_SAMPL_CLK]); + + return 0; +} + +/** + * Set the TX LO frequency. + * @param phy The AD9361 current state structure. + * @param lo_freq_hz The desired frequency (Hz). + * Example: + * 2400000000 (2.4 GHz) + * @return 0 in case of success, negative error code otherwise. + * + * Note: This function will/may affect the data path. + */ +int32_t ad9361_set_tx_lo_freq (struct ad9361_rf_phy *phy, + uint64_t lo_freq_hz) +{ + int32_t ret; + + ret = clk_set_rate(phy, phy->ref_clk_scale[TX_RFPLL], + ad9361_to_clk(lo_freq_hz)); + + return ret; +} + +/** + * Get current TX LO frequency. + * @param phy The AD9361 current state structure. + * @param lo_freq_hz A variable to store the frequency value (Hz). + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_get_tx_lo_freq (struct ad9361_rf_phy *phy, + uint64_t *lo_freq_hz) +{ + *lo_freq_hz = ad9361_from_clk(clk_get_rate(phy, + phy->ref_clk_scale[TX_RFPLL])); + + return 0; +} + +/** + * Switch between internal and external LO. + * @param phy The AD9361 state structure. + * @param int_ext The selected lo (INT_LO, EXT_LO). + * Accepted values: + * INT_LO + * EXT_LO + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_set_tx_lo_int_ext(struct ad9361_rf_phy *phy, uint8_t int_ext) +{ + if ((phy->dev_sel == ID_AD9363A) && (int_ext == EXT_LO)) { + printf("%s : EXT_LO is not supported by AD9363!\n", __func__); + return -1; + } + + phy->pdata->use_ext_tx_lo = int_ext; + + return ad9361_clk_mux_set_parent(phy->ref_clk_scale[TX_RFPLL], int_ext); +} + +/** + * Set the TX FIR filter configuration. + * @param phy The AD9361 current state structure. + * @param fir_cfg FIR filter configuration. + * @return 0 in case of success, negative error code otherwise. + * + * Note: This function will/may affect the data path. + */ +int32_t ad9361_set_tx_fir_config (struct ad9361_rf_phy *phy, + AD9361_TXFIRConfig fir_cfg) +{ + int32_t ret; + + phy->tx_fir_int = fir_cfg.tx_int; + ret = ad9361_load_fir_filter_coef(phy, (enum fir_dest)fir_cfg.tx, + fir_cfg.tx_gain, fir_cfg.tx_coef_size, fir_cfg.tx_coef); + + return ret; +} + +/** + * Get the TX FIR filter configuration. + * @param phy The AD9361 current state structure. + * @param tx_ch The selected TX channel (TX1, TX2). + * Accepted values: + * TX1 (0) + * TX2 (1) + * @param fir_cfg FIR filter configuration output file. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_get_tx_fir_config(struct ad9361_rf_phy *phy, uint8_t tx_ch, + AD9361_TXFIRConfig *fir_cfg) +{ + int32_t ret; + uint32_t fir_conf; + uint8_t index; + + tx_ch += 1; + + ret = ad9361_spi_read(phy->spi, REG_TX_FILTER_CONF); + if(ret < 0) + return ret; + fir_conf = ret; + fir_cfg->tx_coef_size = (((fir_conf & FIR_NUM_TAPS(7)) >> 5) + 1) * 16; + fir_cfg->tx_gain = -6 * (fir_conf & TX_FIR_GAIN_6DB); + fir_cfg->tx = tx_ch; + + fir_conf &= ~FIR_SELECT(3); + fir_conf |= FIR_SELECT(tx_ch) | FIR_START_CLK; + ad9361_spi_write(phy->spi, REG_TX_FILTER_CONF, fir_conf); + + for(index = 0; index < 128; index++) { + ad9361_spi_write(phy->spi, REG_TX_FILTER_COEF_ADDR, index); + ret = ad9361_spi_read(phy->spi, REG_TX_FILTER_COEF_READ_DATA_1); + if(ret < 0) + return ret; + fir_cfg->tx_coef[index] = ret; + ret = ad9361_spi_read(phy->spi, REG_TX_FILTER_COEF_READ_DATA_2); + if(ret < 0) + return ret; + fir_cfg->tx_coef[index] |= (ret << 8); + } + + fir_conf &= ~FIR_START_CLK; + ad9361_spi_write(phy->spi, REG_TX_FILTER_CONF, fir_conf); + + fir_cfg->tx_int = phy->tx_fir_int; + + return 0; +} + +/** + * Enable/disable the TX FIR filter. + * @param phy The AD9361 current state structure. + * @param en_dis The option (ENABLE, DISABLE). + * Accepted values: + * ENABLE (1) + * DISABLE (0) + * @return 0 in case of success, negative error code otherwise. + * + * Note: This function will/may affect the data path. + */ +int32_t ad9361_set_tx_fir_en_dis (struct ad9361_rf_phy *phy, + uint8_t en_dis) +{ + int32_t ret = 0; + + if(phy->bypass_tx_fir == !en_dis) + return ret; + + phy->bypass_tx_fir = !en_dis; + ret = ad9361_validate_enable_fir(phy); + if (ret < 0) { + phy->bypass_tx_fir = true; + } + + return ret; +} + +/** + * Get the status of the TX FIR filter. + * @param phy The AD9361 current state structure. + * @param en_dis The enable/disable status buffer. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_get_tx_fir_en_dis (struct ad9361_rf_phy *phy, + uint8_t *en_dis) +{ + *en_dis = !phy->bypass_tx_fir; + + return 0; +} + +/** + * Get the TX RSSI for the selected channel (TX_MON should be enabled). + * @param phy The AD9361 current state structure. + * @param ch The desired channel (TX1, TX2). + * Accepted values: + * TX1 (0) + * TX2 (1) + * @param rssi_db_x_1000 A variable to store the RSSI. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_get_tx_rssi (struct ad9361_rf_phy *phy, + uint8_t ch, + uint32_t *rssi_db_x_1000) +{ + uint8_t reg_val_buf[3]; + uint32_t val; + int32_t ret; + + ret = ad9361_spi_readm(phy->spi, REG_TX_RSSI_LSB, + reg_val_buf, ARRAY_SIZE(reg_val_buf)); + if (ret < 0) { + return ret; + } + + switch (ch) { + case 0: + val = (reg_val_buf[2] << 1) | (reg_val_buf[0] & TX_RSSI_1); + break; + case 1: + val = (reg_val_buf[1] << 1) | ((reg_val_buf[0] & TX_RSSI_2) >> 1); + break; + default: + return -EINVAL; + } + + val *= RSSI_RESOLUTION; + + *rssi_db_x_1000 = ((val / RSSI_MULTIPLIER) * 1000) + + (val % RSSI_MULTIPLIER); + + return 0; +} + +/** + * Set the TX RF output port. + * @param phy The AD9361 current state structure. + * @param mode The RF port. + * Accepted values: + * TXA (0) + * TXB (1) + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_set_tx_rf_port_output (struct ad9361_rf_phy *phy, + uint32_t mode) +{ + int32_t ret; + + phy->pdata->rf_tx_output_sel = mode; + + ret = ad9361_rf_port_setup(phy, true, + phy->pdata->rf_rx_input_sel, + phy->pdata->rf_tx_output_sel); + + return ret; +} + +/** + * Get the selected TX RF output port. + * @param phy The AD9361 current state structure. + * @param mode The RF port. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_get_tx_rf_port_output (struct ad9361_rf_phy *phy, + uint32_t *mode) +{ + *mode = phy->pdata->rf_tx_output_sel; + + return 0; +} + +/** + * Enable/disable the auto calibration. + * @param phy The AD9361 current state structure. + * @param en_dis The option (ENABLE, DISABLE). + * Accepted values: + * ENABLE (1) + * DISABLE (0) + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_set_tx_auto_cal_en_dis (struct ad9361_rf_phy *phy, + uint8_t en_dis) +{ + if (en_dis == 0) + phy->auto_cal_en = 0; + else + phy->auto_cal_en = 1; + + return 0; +} + +/** + * Get the status of the auto calibration flag. + * @param phy The AD9361 current state structure. + * @param en_dis The enable/disable status buffer. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_get_tx_auto_cal_en_dis (struct ad9361_rf_phy *phy, + uint8_t *en_dis) +{ + *en_dis = phy->auto_cal_en; + + return 0; +} + +/** + * Store TX fastlock profile. + * To create a profile tune the synthesizer (ad9361_set_tx_lo_freq()) and then + * call this function specifying the target profile number. + * @param phy The AD9361 state structure. + * @param profile The profile number (0 - 7). + * Accepted values: + * 0 - 7 + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_tx_fastlock_store(struct ad9361_rf_phy *phy, uint32_t profile) +{ + return ad9361_fastlock_store(phy, 1, profile); +} + +/** + * Recall specified TX fastlock profile. + * When in fastlock pin select mode (init_param->tx_fastlock_pincontrol_enable), + * the function needs to be called before then the pin-control can be used. + * @param phy The AD9361 state structure. + * @param profile The profile number (0 - 7). + * Accepted values: + * 0 - 7 + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_tx_fastlock_recall(struct ad9361_rf_phy *phy, uint32_t profile) +{ + return ad9361_fastlock_recall(phy, 1, profile); +} + +/** + * Load TX fastlock profile. A previously saved profile can be loaded in any + * of the 8 available slots. + * @param phy The AD9361 state structure. + * @param profile The profile number (0 - 7). + * Accepted values: + * 0 - 7 + * @param values Fastlock profile program data. + * Example: + * val0,val1,val2,…,val15 + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_tx_fastlock_load(struct ad9361_rf_phy *phy, uint32_t profile, + uint8_t *values) +{ + return ad9361_fastlock_load(phy, 1, profile, values); +} + +/** + * Save TX fastlock profile. In order to use more than 8 Profiles, an existing + * profile can be read back and stored by the user application. + * @param phy The AD9361 state structure. + * @param profile The profile number (0 - 7). + * Accepted values: + * 0 - 7 + * @param values Fastlock profile program data. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_tx_fastlock_save(struct ad9361_rf_phy *phy, uint32_t profile, + uint8_t *values) +{ + return ad9361_fastlock_save(phy, 1, profile, values); +} + +/** + * Power down the TX Local Oscillator. + * @param phy The AD9361 state structure. + * @param option The option (ON, OFF). + * Accepted values: + * ON (0) + * OFF (1) + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_tx_lo_powerdown(struct ad9361_rf_phy *phy, uint8_t option) +{ + return ad9361_synth_lo_powerdown(phy, LO_DONTCARE, option ? LO_OFF : LO_ON); +} + +/** + * Get the TX Local Oscillator power status. + * @param phy The AD9361 state structure. + * @param option Store the option (ON, OFF). + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_get_tx_lo_power(struct ad9361_rf_phy *phy, uint8_t *option) +{ + *option = !(phy->cached_synth_pd[0] & TX_LO_POWER_DOWN) ? OFF : ON; + + return 0; +} + +/** + * Set the RX and TX path rates. + * @param phy The AD9361 state structure. + * @param rx_path_clks RX path rates buffer. + * @param tx_path_clks TX path rates buffer. + * @return 0 in case of success, negative error code otherwise. + * + * Note: This function will/may affect the data path. + */ +int32_t ad9361_set_trx_path_clks(struct ad9361_rf_phy *phy, + uint32_t *rx_path_clks, + uint32_t *tx_path_clks) +{ + int32_t ret; + + ret = ad9361_set_trx_clock_chain(phy, rx_path_clks, tx_path_clks); + if (ret < 0) + return ret; + + ret = ad9361_update_rf_bandwidth(phy, phy->current_rx_bw_Hz, + phy->current_tx_bw_Hz); + + return ret; +} + +/** + * Get the RX and TX path rates. + * @param phy The AD9361 state structure. + * @param rx_path_clks RX path rates buffer. + * @param tx_path_clks TX path rates buffer. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_get_trx_path_clks(struct ad9361_rf_phy *phy, + uint32_t *rx_path_clks, + uint32_t *tx_path_clks) +{ + return ad9361_get_trx_clock_chain(phy, rx_path_clks, tx_path_clks); +} + +/** + * Set the number of channels mode. + * @param phy The AD9361 state structure. + * Note: This function also resets the device, some additional + * configurations might be necessary + * @param no_ch_mode Number of channels mode (MODE_1x1, MODE_2x2). + * Accepted values: + * MODE_1x1 (1) + * MODE_2x2 (2) + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_set_no_ch_mode(struct ad9361_rf_phy *phy, uint8_t no_ch_mode) +{ + switch (no_ch_mode) { + case 1: + phy->pdata->rx2tx2 = 0; + break; + case 2: + phy->pdata->rx2tx2 = 1; + break; + default: + return -EINVAL; + } + + ad9361_reset(phy); + ad9361_spi_write(phy->spi, REG_SPI_CONF, SOFT_RESET | _SOFT_RESET); + ad9361_spi_write(phy->spi, REG_SPI_CONF, 0x0); + + ad9361_clear_state(phy); + + phy->clks[TX_REFCLK]->rate = ad9361_clk_factor_recalc_rate( + phy->ref_clk_scale[TX_REFCLK], phy->clk_refin->rate); + phy->clks[TX_REFCLK]->rate = ad9361_clk_factor_recalc_rate( + phy->ref_clk_scale[TX_REFCLK], phy->clk_refin->rate); + phy->clks[RX_REFCLK]->rate = ad9361_clk_factor_recalc_rate( + phy->ref_clk_scale[RX_REFCLK], phy->clk_refin->rate); + phy->clks[BB_REFCLK]->rate = ad9361_clk_factor_recalc_rate( + phy->ref_clk_scale[BB_REFCLK], phy->clk_refin->rate); + phy->clks[BBPLL_CLK]->rate = ad9361_bbpll_recalc_rate( + phy->ref_clk_scale[BBPLL_CLK], phy->clks[BB_REFCLK]->rate); + phy->clks[ADC_CLK]->rate = ad9361_clk_factor_recalc_rate( + phy->ref_clk_scale[ADC_CLK], phy->clks[BBPLL_CLK]->rate); + phy->clks[R2_CLK]->rate = ad9361_clk_factor_recalc_rate( + phy->ref_clk_scale[R2_CLK], phy->clks[ADC_CLK]->rate); + phy->clks[R1_CLK]->rate = ad9361_clk_factor_recalc_rate( + phy->ref_clk_scale[R1_CLK], phy->clks[R2_CLK]->rate); + phy->clks[CLKRF_CLK]->rate = ad9361_clk_factor_recalc_rate( + phy->ref_clk_scale[CLKRF_CLK], phy->clks[R1_CLK]->rate); + phy->clks[RX_SAMPL_CLK]->rate = ad9361_clk_factor_recalc_rate( + phy->ref_clk_scale[RX_SAMPL_CLK], phy->clks[CLKRF_CLK]->rate); + phy->clks[DAC_CLK]->rate = ad9361_clk_factor_recalc_rate( + phy->ref_clk_scale[DAC_CLK], phy->clks[ADC_CLK]->rate); + phy->clks[T2_CLK]->rate = ad9361_clk_factor_recalc_rate( + phy->ref_clk_scale[T2_CLK], phy->clks[DAC_CLK]->rate); + phy->clks[T1_CLK]->rate = ad9361_clk_factor_recalc_rate( + phy->ref_clk_scale[T1_CLK], phy->clks[T2_CLK]->rate); + phy->clks[CLKTF_CLK]->rate = ad9361_clk_factor_recalc_rate( + phy->ref_clk_scale[CLKTF_CLK], phy->clks[T1_CLK]->rate); + phy->clks[TX_SAMPL_CLK]->rate = ad9361_clk_factor_recalc_rate( + phy->ref_clk_scale[TX_SAMPL_CLK], phy->clks[CLKTF_CLK]->rate); + phy->clks[RX_RFPLL_INT]->rate = ad9361_rfpll_int_recalc_rate( + phy->ref_clk_scale[RX_RFPLL_INT], phy->clks[RX_REFCLK]->rate); + phy->clks[TX_RFPLL_INT]->rate = ad9361_rfpll_int_recalc_rate( + phy->ref_clk_scale[TX_RFPLL_INT], phy->clks[TX_REFCLK]->rate); + phy->clks[RX_RFPLL_DUMMY]->rate = ad9361_rfpll_dummy_recalc_rate( + phy->ref_clk_scale[RX_RFPLL_DUMMY]); + phy->clks[TX_RFPLL_DUMMY]->rate = ad9361_rfpll_dummy_recalc_rate( + phy->ref_clk_scale[TX_RFPLL_DUMMY]); + phy->clks[RX_RFPLL]->rate = ad9361_rfpll_recalc_rate( + phy->ref_clk_scale[RX_RFPLL]); + phy->clks[TX_RFPLL]->rate = ad9361_rfpll_recalc_rate( + phy->ref_clk_scale[TX_RFPLL]); + + ad9361_setup(phy); +#ifndef AXI_ADC_NOT_PRESENT + /* platform specific wrapper to call ad9361_post_setup() */ + ad9361_post_setup(phy); +#endif + + return 0; +} + +/** + * Do multi chip synchronization. + * @param phy_master The AD9361 Master state structure. + * @param phy_slave The AD9361 Slave state structure. + * @return 0 in case of success, negative error code otherwise. + * + * Note: This function will/may affect the data path. + */ +int32_t ad9361_do_mcs(struct ad9361_rf_phy *phy_master, + struct ad9361_rf_phy *phy_slave) +{ + uint32_t ensm_mode; + int32_t step; + int32_t reg; + + if ((phy_master->dev_sel == ID_AD9363A) || + (phy_slave->dev_sel == ID_AD9363A)) { + printf("%s : MCS is not supported by AD9363!\n", __func__); + return -1; + } + + reg = ad9361_spi_read(phy_master->spi, REG_RX_CLOCK_DATA_DELAY); + ad9361_spi_write(phy_slave->spi, REG_RX_CLOCK_DATA_DELAY, reg); + reg = ad9361_spi_read(phy_master->spi, REG_TX_CLOCK_DATA_DELAY); + ad9361_spi_write(phy_slave->spi, REG_TX_CLOCK_DATA_DELAY, reg); + + ad9361_get_en_state_machine_mode(phy_master, &ensm_mode); + + ad9361_set_en_state_machine_mode(phy_master, ENSM_MODE_ALERT); + ad9361_set_en_state_machine_mode(phy_slave, ENSM_MODE_ALERT); + + for (step = 0; step <= 5; step++) { + ad9361_mcs(phy_slave, step); + ad9361_mcs(phy_master, step); + mdelay(100); + } + + ad9361_set_en_state_machine_mode(phy_master, ensm_mode); + ad9361_set_en_state_machine_mode(phy_slave, ensm_mode); + + return 0; +} + +/** + * Enable/disable the TRX FIR filters. + * @param phy The AD9361 current state structure. + * @param en_dis The option (ENABLE, DISABLE). + * Accepted values: + * ENABLE (1) + * DISABLE (0) + * @return 0 in case of success, negative error code otherwise. + * + * Note: This function will/may affect the data path. + */ +int32_t ad9361_set_trx_fir_en_dis (struct ad9361_rf_phy *phy, + uint8_t en_dis) +{ + int32_t ret = 0; + + if ((phy->bypass_rx_fir == phy->bypass_tx_fir) && + (phy->bypass_rx_fir == !en_dis)) + return ret; + + phy->bypass_rx_fir = !en_dis; + phy->bypass_tx_fir = !en_dis; + ret = ad9361_validate_enable_fir(phy); + if (ret < 0) { + phy->bypass_rx_fir = true; + phy->bypass_tx_fir = true; + } + + return ret; +} + +/** + * Set the OSR rate governor. + * @param phy The AD9361 current state structure. + * @param rate_gov OSR rate governor (highest, nominal). + * Accepted values: + * HIGHEST_OSR (0 - highest OSR) + * NOMINAL_OSR (1 - nominal) + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_set_trx_rate_gov (struct ad9361_rf_phy *phy, uint32_t rate_gov) +{ + if (rate_gov == 0) + phy->rate_governor = 0; + else + phy->rate_governor = 1; + + return 0; +} + +/** + * Get the OSR rate governor. + * @param phy The AD9361 current state structure. + * @param rate_gov Option buffer. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_get_trx_rate_gov (struct ad9361_rf_phy *phy, uint32_t *rate_gov) +{ + *rate_gov = phy->rate_governor; + + return 0; +} + +/** + * Perform the selected calibration. + * @param phy The AD9361 state structure. + * @param cal The selected calibration (TX_QUAD_CAL, RFDC_CAL). + * Accepted values: + * TX_QUAD_CAL + * RFDC_CAL + * @param arg For TX_QUAD_CAL - the optional RX phase value overwrite (set to zero). + * @return 0 in case of success, negative error code otherwise. + * + * Note: This function will/may affect the data path. + */ +int32_t ad9361_do_calib(struct ad9361_rf_phy *phy, uint32_t cal, int32_t arg) +{ + return ad9361_do_calib_run(phy, cal, arg); +} + +/** + * Load and enable TRX FIR filters configurations. + * @param phy The AD9361 current state structure. + * @param rx_fir_cfg RX FIR filter configuration. + * @param tx_fir_cfg TX FIR filter configuration. + * @return 0 in case of success, negative error code otherwise. + * + * Note: This function will/may affect the data path. + */ +int32_t ad9361_trx_load_enable_fir(struct ad9361_rf_phy *phy, + AD9361_RXFIRConfig rx_fir_cfg, + AD9361_TXFIRConfig tx_fir_cfg) +{ + int32_t rtx = -1, rrx = -1; + + phy->filt_rx_bw_Hz = 0; + phy->filt_tx_bw_Hz = 0; + phy->filt_valid = false; + + if (tx_fir_cfg.tx_path_clks[TX_SAMPL_FREQ]) { + memcpy(phy->filt_tx_path_clks, tx_fir_cfg.tx_path_clks, + sizeof(phy->filt_tx_path_clks)); + rtx = 0; + } + + if (rx_fir_cfg.rx_path_clks[RX_SAMPL_FREQ]) { + memcpy(phy->filt_rx_path_clks, rx_fir_cfg.rx_path_clks, + sizeof(phy->filt_rx_path_clks)); + rrx = 0; + } + + if (tx_fir_cfg.tx_bandwidth) { + phy->filt_tx_bw_Hz = tx_fir_cfg.tx_bandwidth; + } + + if (rx_fir_cfg.rx_bandwidth) { + phy->filt_rx_bw_Hz = rx_fir_cfg.rx_bandwidth; + } + + ad9361_set_tx_fir_config(phy, tx_fir_cfg); + ad9361_set_rx_fir_config(phy, rx_fir_cfg); + + if (!(rrx | rtx)) + phy->filt_valid = true; + + ad9361_set_trx_fir_en_dis(phy, 1); + + return 0; +} + +/** + * Do DCXO coarse tuning. + * @param phy The AD9361 current state structure. + * @param coarse The DCXO coarse tuning value. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_do_dcxo_tune_coarse(struct ad9361_rf_phy *phy, + uint32_t coarse) +{ + phy->pdata->dcxo_coarse = coarse; + + return ad9361_set_dcxo_tune(phy, phy->pdata->dcxo_coarse, + phy->pdata->dcxo_fine); +} + +/** + * Do DCXO fine tuning. + * @param phy The AD9361 current state structure. + * @param fine The DCXO fine tuning value. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_do_dcxo_tune_fine(struct ad9361_rf_phy *phy, + uint32_t fine) +{ + phy->pdata->dcxo_fine = fine; + + return ad9361_set_dcxo_tune(phy, phy->pdata->dcxo_coarse, + phy->pdata->dcxo_fine); +} + +/** + * Get the temperature. + * @param phy The AD9361 current state structure. + * @param temp The temperature (degrees C * 1000). + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_get_temperature(struct ad9361_rf_phy *phy, + int32_t *temp) +{ + *temp = ad9361_get_temp(phy); + return 0; +} diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/rf-transceiver/ad9361/ad9361_api.h b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/rf-transceiver/ad9361/ad9361_api.h new file mode 100644 index 0000000..6227bc8 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/rf-transceiver/ad9361/ad9361_api.h @@ -0,0 +1,552 @@ +/***************************************************************************//** + * @file ad9361_api.h + * @brief Header file of AD9361 API Driver. + * @author DBogdan (dragos.bogdan@analog.com) +******************************************************************************** + * Copyright 2013(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ +#ifndef AD9361_API_H_ +#define AD9361_API_H_ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ +#include "ad9361_util.h" +#include "gpio.h" +#include "spi.h" + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ +typedef struct { + /* Device selection */ + enum dev_id dev_sel; + /* Reference Clock */ + uint32_t reference_clk_rate; + /* Base Configuration */ + uint8_t two_rx_two_tx_mode_enable; /* adi,2rx-2tx-mode-enable */ + uint8_t one_rx_one_tx_mode_use_rx_num; /* adi,1rx-1tx-mode-use-rx-num */ + uint8_t one_rx_one_tx_mode_use_tx_num; /* adi,1rx-1tx-mode-use-tx-num */ + uint8_t frequency_division_duplex_mode_enable; /* adi,frequency-division-duplex-mode-enable */ + uint8_t frequency_division_duplex_independent_mode_enable; /* adi,frequency-division-duplex-independent-mode-enable */ + uint8_t tdd_use_dual_synth_mode_enable; /* adi,tdd-use-dual-synth-mode-enable */ + uint8_t tdd_skip_vco_cal_enable; /* adi,tdd-skip-vco-cal-enable */ + uint32_t tx_fastlock_delay_ns; /* adi,tx-fastlock-delay-ns */ + uint32_t rx_fastlock_delay_ns; /* adi,rx-fastlock-delay-ns */ + uint8_t rx_fastlock_pincontrol_enable; /* adi,rx-fastlock-pincontrol-enable */ + uint8_t tx_fastlock_pincontrol_enable; /* adi,tx-fastlock-pincontrol-enable */ + uint8_t external_rx_lo_enable; /* adi,external-rx-lo-enable */ + uint8_t external_tx_lo_enable; /* adi,external-tx-lo-enable */ + uint8_t dc_offset_tracking_update_event_mask; /* adi,dc-offset-tracking-update-event-mask */ + uint8_t dc_offset_attenuation_high_range; /* adi,dc-offset-attenuation-high-range */ + uint8_t dc_offset_attenuation_low_range; /* adi,dc-offset-attenuation-low-range */ + uint8_t dc_offset_count_high_range; /* adi,dc-offset-count-high-range */ + uint8_t dc_offset_count_low_range; /* adi,dc-offset-count-low-range */ + uint8_t split_gain_table_mode_enable; /* adi,split-gain-table-mode-enable */ + uint32_t trx_synthesizer_target_fref_overwrite_hz; /* adi,trx-synthesizer-target-fref-overwrite-hz */ + uint8_t qec_tracking_slow_mode_enable; /* adi,qec-tracking-slow-mode-enable */ + /* ENSM Control */ + uint8_t ensm_enable_pin_pulse_mode_enable; /* adi,ensm-enable-pin-pulse-mode-enable */ + uint8_t ensm_enable_txnrx_control_enable; /* adi,ensm-enable-txnrx-control-enable */ + /* LO Control */ + uint64_t rx_synthesizer_frequency_hz; /* adi,rx-synthesizer-frequency-hz */ + uint64_t tx_synthesizer_frequency_hz; /* adi,tx-synthesizer-frequency-hz */ + uint8_t tx_lo_powerdown_managed_enable; /* adi,tx-lo-powerdown-managed-enable */ + /* Rate & BW Control */ + uint32_t rx_path_clock_frequencies[6]; /* adi,rx-path-clock-frequencies */ + uint32_t tx_path_clock_frequencies[6]; /* adi,tx-path-clock-frequencies */ + uint32_t rf_rx_bandwidth_hz; /* adi,rf-rx-bandwidth-hz */ + uint32_t rf_tx_bandwidth_hz; /* adi,rf-tx-bandwidth-hz */ + /* RF Port Control */ + uint32_t rx_rf_port_input_select; /* adi,rx-rf-port-input-select */ + uint32_t tx_rf_port_input_select; /* adi,tx-rf-port-input-select */ + /* TX Attenuation Control */ + int32_t tx_attenuation_mdB; /* adi,tx-attenuation-mdB */ + uint8_t update_tx_gain_in_alert_enable; /* adi,update-tx-gain-in-alert-enable */ + /* Reference Clock Control */ + uint8_t xo_disable_use_ext_refclk_enable; /* adi,xo-disable-use-ext-refclk-enable */ + uint32_t dcxo_coarse_and_fine_tune[2]; /* adi,dcxo-coarse-and-fine-tune */ + uint32_t clk_output_mode_select; /* adi,clk-output-mode-select */ + /* Gain Control */ + uint8_t gc_rx1_mode; /* adi,gc-rx1-mode */ + uint8_t gc_rx2_mode; /* adi,gc-rx2-mode */ + uint8_t gc_adc_large_overload_thresh; /* adi,gc-adc-large-overload-thresh */ + uint8_t gc_adc_ovr_sample_size; /* adi,gc-adc-ovr-sample-size */ + uint8_t gc_adc_small_overload_thresh; /* adi,gc-adc-small-overload-thresh */ + uint16_t gc_dec_pow_measurement_duration; /* adi,gc-dec-pow-measurement-duration */ + uint8_t gc_dig_gain_enable; /* adi,gc-dig-gain-enable */ + uint16_t gc_lmt_overload_high_thresh; /* adi,gc-lmt-overload-high-thresh */ + uint16_t gc_lmt_overload_low_thresh; /* adi,gc-lmt-overload-low-thresh */ + uint8_t gc_low_power_thresh; /* adi,gc-low-power-thresh */ + uint8_t gc_max_dig_gain; /* adi,gc-max-dig-gain */ + uint8_t gc_use_rx_fir_out_for_dec_pwr_meas_enable; /* adi,gc-use-rx-fir-out-for-dec-pwr-meas-enable */ + /* Gain MGC Control */ + uint8_t mgc_dec_gain_step; /* adi,mgc-dec-gain-step */ + uint8_t mgc_inc_gain_step; /* adi,mgc-inc-gain-step */ + uint8_t mgc_rx1_ctrl_inp_enable; /* adi,mgc-rx1-ctrl-inp-enable */ + uint8_t mgc_rx2_ctrl_inp_enable; /* adi,mgc-rx2-ctrl-inp-enable */ + uint8_t mgc_split_table_ctrl_inp_gain_mode; /* adi,mgc-split-table-ctrl-inp-gain-mode */ + /* Gain AGC Control */ + uint8_t agc_adc_large_overload_exceed_counter; /* adi,agc-adc-large-overload-exceed-counter */ + uint8_t agc_adc_large_overload_inc_steps; /* adi,agc-adc-large-overload-inc-steps - Name is misleading should be dec-steps*/ + uint8_t agc_adc_lmt_small_overload_prevent_gain_inc_enable; /* adi,agc-adc-lmt-small-overload-prevent-gain-inc-enable */ + uint8_t agc_adc_small_overload_exceed_counter; /* adi,agc-adc-small-overload-exceed-counter */ + uint8_t agc_dig_gain_step_size; /* adi,agc-dig-gain-step-size */ + uint8_t agc_dig_saturation_exceed_counter; /* adi,agc-dig-saturation-exceed-counter */ + uint32_t agc_gain_update_interval_us; /* adi,agc-gain-update-interval-us */ + uint8_t agc_immed_gain_change_if_large_adc_overload_enable; /* adi,agc-immed-gain-change-if-large-adc-overload-enable */ + uint8_t agc_immed_gain_change_if_large_lmt_overload_enable; /* adi,agc-immed-gain-change-if-large-lmt-overload-enable */ + uint8_t agc_inner_thresh_high; /* adi,agc-inner-thresh-high */ + uint8_t agc_inner_thresh_high_dec_steps; /* adi,agc-inner-thresh-high-dec-steps */ + uint8_t agc_inner_thresh_low; /* adi,agc-inner-thresh-low */ + uint8_t agc_inner_thresh_low_inc_steps; /* adi,agc-inner-thresh-low-inc-steps */ + uint8_t agc_lmt_overload_large_exceed_counter; /* adi,agc-lmt-overload-large-exceed-counter */ + uint8_t agc_lmt_overload_large_inc_steps; /* adi,agc-lmt-overload-large-inc-steps */ + uint8_t agc_lmt_overload_small_exceed_counter; /* adi,agc-lmt-overload-small-exceed-counter */ + uint8_t agc_outer_thresh_high; /* adi,agc-outer-thresh-high */ + uint8_t agc_outer_thresh_high_dec_steps; /* adi,agc-outer-thresh-high-dec-steps */ + uint8_t agc_outer_thresh_low; /* adi,agc-outer-thresh-low */ + uint8_t agc_outer_thresh_low_inc_steps; /* adi,agc-outer-thresh-low-inc-steps */ + uint32_t agc_attack_delay_extra_margin_us; /* adi,agc-attack-delay-extra-margin-us */ + uint8_t agc_sync_for_gain_counter_enable; /* adi,agc-sync-for-gain-counter-enable */ + /* Fast AGC */ + uint32_t fagc_dec_pow_measuremnt_duration; /* adi,fagc-dec-pow-measurement-duration */ + uint32_t fagc_state_wait_time_ns; /* adi,fagc-state-wait-time-ns */ + /* Fast AGC - Low Power */ + uint8_t fagc_allow_agc_gain_increase; /* adi,fagc-allow-agc-gain-increase-enable */ + uint32_t fagc_lp_thresh_increment_time; /* adi,fagc-lp-thresh-increment-time */ + uint32_t fagc_lp_thresh_increment_steps; /* adi,fagc-lp-thresh-increment-steps */ + /* Fast AGC - Lock Level (Lock Level is set via slow AGC inner high threshold) */ + uint8_t fagc_lock_level_lmt_gain_increase_en; /* adi,fagc-lock-level-lmt-gain-increase-enable */ + uint32_t fagc_lock_level_gain_increase_upper_limit; /* adi,fagc-lock-level-gain-increase-upper-limit */ + /* Fast AGC - Peak Detectors and Final Settling */ + uint32_t fagc_lpf_final_settling_steps; /* adi,fagc-lpf-final-settling-steps */ + uint32_t fagc_lmt_final_settling_steps; /* adi,fagc-lmt-final-settling-steps */ + uint32_t fagc_final_overrange_count; /* adi,fagc-final-overrange-count */ + /* Fast AGC - Final Power Test */ + uint8_t fagc_gain_increase_after_gain_lock_en; /* adi,fagc-gain-increase-after-gain-lock-enable */ + /* Fast AGC - Unlocking the Gain */ + uint32_t fagc_gain_index_type_after_exit_rx_mode; /* adi,fagc-gain-index-type-after-exit-rx-mode */ + uint8_t fagc_use_last_lock_level_for_set_gain_en; /* adi,fagc-use-last-lock-level-for-set-gain-enable */ + uint8_t fagc_rst_gla_stronger_sig_thresh_exceeded_en; /* adi,fagc-rst-gla-stronger-sig-thresh-exceeded-enable */ + uint32_t fagc_optimized_gain_offset; /* adi,fagc-optimized-gain-offset */ + uint32_t fagc_rst_gla_stronger_sig_thresh_above_ll; /* adi,fagc-rst-gla-stronger-sig-thresh-above-ll */ + uint8_t fagc_rst_gla_engergy_lost_sig_thresh_exceeded_en; /* adi,fagc-rst-gla-engergy-lost-sig-thresh-exceeded-enable */ + uint8_t fagc_rst_gla_engergy_lost_goto_optim_gain_en; /* adi,fagc-rst-gla-engergy-lost-goto-optim-gain-enable */ + uint32_t fagc_rst_gla_engergy_lost_sig_thresh_below_ll; /* adi,fagc-rst-gla-engergy-lost-sig-thresh-below-ll */ + uint32_t fagc_energy_lost_stronger_sig_gain_lock_exit_cnt; /* adi,fagc-energy-lost-stronger-sig-gain-lock-exit-cnt */ + uint8_t fagc_rst_gla_large_adc_overload_en; /* adi,fagc-rst-gla-large-adc-overload-enable */ + uint8_t fagc_rst_gla_large_lmt_overload_en; /* adi,fagc-rst-gla-large-lmt-overload-enable */ + uint8_t fagc_rst_gla_en_agc_pulled_high_en; /* adi,fagc-rst-gla-en-agc-pulled-high-enable */ + uint32_t fagc_rst_gla_if_en_agc_pulled_high_mode; /* adi,fagc-rst-gla-if-en-agc-pulled-high-mode */ + uint32_t fagc_power_measurement_duration_in_state5; /* adi,fagc-power-measurement-duration-in-state5 */ + uint32_t fagc_large_overload_inc_steps; /* adi,fagc-adc-large-overload-inc-steps - Name is misleading should be dec-steps */ + /* RSSI Control */ + uint32_t rssi_delay; /* adi,rssi-delay */ + uint32_t rssi_duration; /* adi,rssi-duration */ + uint8_t rssi_restart_mode; /* adi,rssi-restart-mode */ + uint8_t rssi_unit_is_rx_samples_enable; /* adi,rssi-unit-is-rx-samples-enable */ + uint32_t rssi_wait; /* adi,rssi-wait */ + /* Aux ADC Control */ + uint32_t aux_adc_decimation; /* adi,aux-adc-decimation */ + uint32_t aux_adc_rate; /* adi,aux-adc-rate */ + /* AuxDAC Control */ + uint8_t aux_dac_manual_mode_enable; /* adi,aux-dac-manual-mode-enable */ + uint32_t aux_dac1_default_value_mV; /* adi,aux-dac1-default-value-mV */ + uint8_t aux_dac1_active_in_rx_enable; /* adi,aux-dac1-active-in-rx-enable */ + uint8_t aux_dac1_active_in_tx_enable; /* adi,aux-dac1-active-in-tx-enable */ + uint8_t aux_dac1_active_in_alert_enable; /* adi,aux-dac1-active-in-alert-enable */ + uint32_t aux_dac1_rx_delay_us; /* adi,aux-dac1-rx-delay-us */ + uint32_t aux_dac1_tx_delay_us; /* adi,aux-dac1-tx-delay-us */ + uint32_t aux_dac2_default_value_mV; /* adi,aux-dac2-default-value-mV */ + uint8_t aux_dac2_active_in_rx_enable; /* adi,aux-dac2-active-in-rx-enable */ + uint8_t aux_dac2_active_in_tx_enable; /* adi,aux-dac2-active-in-tx-enable */ + uint8_t aux_dac2_active_in_alert_enable; /* adi,aux-dac2-active-in-alert-enable */ + uint32_t aux_dac2_rx_delay_us; /* adi,aux-dac2-rx-delay-us */ + uint32_t aux_dac2_tx_delay_us; /* adi,aux-dac2-tx-delay-us */ + /* Temperature Sensor Control */ + uint32_t temp_sense_decimation; /* adi,temp-sense-decimation */ + uint16_t temp_sense_measurement_interval_ms; /* adi,temp-sense-measurement-interval-ms */ + int8_t temp_sense_offset_signed; /* adi,temp-sense-offset-signed */ + uint8_t temp_sense_periodic_measurement_enable; /* adi,temp-sense-periodic-measurement-enable */ + /* Control Out Setup */ + uint8_t ctrl_outs_enable_mask; /* adi,ctrl-outs-enable-mask */ + uint8_t ctrl_outs_index; /* adi,ctrl-outs-index */ + /* External LNA Control */ + uint32_t elna_settling_delay_ns; /* adi,elna-settling-delay-ns */ + uint32_t elna_gain_mdB; /* adi,elna-gain-mdB */ + uint32_t elna_bypass_loss_mdB; /* adi,elna-bypass-loss-mdB */ + uint8_t elna_rx1_gpo0_control_enable; /* adi,elna-rx1-gpo0-control-enable */ + uint8_t elna_rx2_gpo1_control_enable; /* adi,elna-rx2-gpo1-control-enable */ + uint8_t elna_gaintable_all_index_enable; /* adi,elna-gaintable-all-index-enable */ + /* Digital Interface Control */ + uint8_t digital_interface_tune_skip_mode; /* adi,digital-interface-tune-skip-mode */ + uint8_t digital_interface_tune_fir_disable; /* adi,digital-interface-tune-fir-disable */ + uint8_t pp_tx_swap_enable; /* adi,pp-tx-swap-enable */ + uint8_t pp_rx_swap_enable; /* adi,pp-rx-swap-enable */ + uint8_t tx_channel_swap_enable; /* adi,tx-channel-swap-enable */ + uint8_t rx_channel_swap_enable; /* adi,rx-channel-swap-enable */ + uint8_t rx_frame_pulse_mode_enable; /* adi,rx-frame-pulse-mode-enable */ + uint8_t two_t_two_r_timing_enable; /* adi,2t2r-timing-enable */ + uint8_t invert_data_bus_enable; /* adi,invert-data-bus-enable */ + uint8_t invert_data_clk_enable; /* adi,invert-data-clk-enable */ + uint8_t fdd_alt_word_order_enable; /* adi,fdd-alt-word-order-enable */ + uint8_t invert_rx_frame_enable; /* adi,invert-rx-frame-enable */ + uint8_t fdd_rx_rate_2tx_enable; /* adi,fdd-rx-rate-2tx-enable */ + uint8_t swap_ports_enable; /* adi,swap-ports-enable */ + uint8_t single_data_rate_enable; /* adi,single-data-rate-enable */ + uint8_t lvds_mode_enable; /* adi,lvds-mode-enable */ + uint8_t half_duplex_mode_enable; /* adi,half-duplex-mode-enable */ + uint8_t single_port_mode_enable; /* adi,single-port-mode-enable */ + uint8_t full_port_enable; /* adi,full-port-enable */ + uint8_t full_duplex_swap_bits_enable; /* adi,full-duplex-swap-bits-enable */ + uint32_t delay_rx_data; /* adi,delay-rx-data */ + uint32_t rx_data_clock_delay; /* adi,rx-data-clock-delay */ + uint32_t rx_data_delay; /* adi,rx-data-delay */ + uint32_t tx_fb_clock_delay; /* adi,tx-fb-clock-delay */ + uint32_t tx_data_delay; /* adi,tx-data-delay */ + uint32_t lvds_bias_mV; /* adi,lvds-bias-mV */ + uint8_t lvds_rx_onchip_termination_enable; /* adi,lvds-rx-onchip-termination-enable */ + uint8_t rx1rx2_phase_inversion_en; /* adi,rx1-rx2-phase-inversion-enable */ + uint8_t lvds_invert1_control; /* adi,lvds-invert1-control */ + uint8_t lvds_invert2_control; /* adi,lvds-invert2-control */ + /* GPO Control */ + uint8_t gpo_manual_mode_enable; /* adi,gpo-manual-mode-enable */ + uint32_t gpo_manual_mode_enable_mask; /* adi,gpo-manual-mode-enable-mask */ + uint8_t gpo0_inactive_state_high_enable; /* adi,gpo0-inactive-state-high-enable */ + uint8_t gpo1_inactive_state_high_enable; /* adi,gpo1-inactive-state-high-enable */ + uint8_t gpo2_inactive_state_high_enable; /* adi,gpo2-inactive-state-high-enable */ + uint8_t gpo3_inactive_state_high_enable; /* adi,gpo3-inactive-state-high-enable */ + uint8_t gpo0_slave_rx_enable; /* adi,gpo0-slave-rx-enable */ + uint8_t gpo0_slave_tx_enable; /* adi,gpo0-slave-tx-enable */ + uint8_t gpo1_slave_rx_enable; /* adi,gpo1-slave-rx-enable */ + uint8_t gpo1_slave_tx_enable; /* adi,gpo1-slave-tx-enable */ + uint8_t gpo2_slave_rx_enable; /* adi,gpo2-slave-rx-enable */ + uint8_t gpo2_slave_tx_enable; /* adi,gpo2-slave-tx-enable */ + uint8_t gpo3_slave_rx_enable; /* adi,gpo3-slave-rx-enable */ + uint8_t gpo3_slave_tx_enable; /* adi,gpo3-slave-tx-enable */ + uint8_t gpo0_rx_delay_us; /* adi,gpo0-rx-delay-us */ + uint8_t gpo0_tx_delay_us; /* adi,gpo0-tx-delay-us */ + uint8_t gpo1_rx_delay_us; /* adi,gpo1-rx-delay-us */ + uint8_t gpo1_tx_delay_us; /* adi,gpo1-tx-delay-us */ + uint8_t gpo2_rx_delay_us; /* adi,gpo2-rx-delay-us */ + uint8_t gpo2_tx_delay_us; /* adi,gpo2-tx-delay-us */ + uint8_t gpo3_rx_delay_us; /* adi,gpo3-rx-delay-us */ + uint8_t gpo3_tx_delay_us; /* adi,gpo3-tx-delay-us */ + /* Tx Monitor Control */ + uint32_t low_high_gain_threshold_mdB; /* adi,txmon-low-high-thresh */ + uint32_t low_gain_dB; /* adi,txmon-low-gain */ + uint32_t high_gain_dB; /* adi,txmon-high-gain */ + uint8_t tx_mon_track_en; /* adi,txmon-dc-tracking-enable */ + uint8_t one_shot_mode_en; /* adi,txmon-one-shot-mode-enable */ + uint32_t tx_mon_delay; /* adi,txmon-delay */ + uint32_t tx_mon_duration; /* adi,txmon-duration */ + uint32_t tx1_mon_front_end_gain; /* adi,txmon-1-front-end-gain */ + uint32_t tx2_mon_front_end_gain; /* adi,txmon-2-front-end-gain */ + uint32_t tx1_mon_lo_cm; /* adi,txmon-1-lo-cm */ + uint32_t tx2_mon_lo_cm; /* adi,txmon-2-lo-cm */ + /* GPIO definitions */ + struct gpio_init_param gpio_resetb; /* reset-gpios */ + /* MCS Sync */ + struct gpio_init_param gpio_sync; /* sync-gpios */ + struct gpio_init_param gpio_cal_sw1; /* cal-sw1-gpios */ + struct gpio_init_param gpio_cal_sw2; /* cal-sw2-gpios */ + + struct spi_init_param spi_param; + + /* External LO clocks */ + uint32_t (*ad9361_rfpll_ext_recalc_rate)(struct refclk_scale *clk_priv); + int32_t (*ad9361_rfpll_ext_round_rate)(struct refclk_scale *clk_priv, + uint32_t rate); + int32_t (*ad9361_rfpll_ext_set_rate)(struct refclk_scale *clk_priv, + uint32_t rate); + +} AD9361_InitParam; + +typedef struct { + uint32_t rx; /* 1, 2, 3(both) */ + int32_t rx_gain; /* -12, -6, 0, 6 */ + uint32_t rx_dec; /* 1, 2, 4 */ + int16_t rx_coef[128]; + uint8_t rx_coef_size; + uint32_t rx_path_clks[6]; + uint32_t rx_bandwidth; +} AD9361_RXFIRConfig; + +typedef struct { + uint32_t tx; /* 1, 2, 3(both) */ + int32_t tx_gain; /* -6, 0 */ + uint32_t tx_int; /* 1, 2, 4 */ + int16_t tx_coef[128]; + uint8_t tx_coef_size; + uint32_t tx_path_clks[6]; + uint32_t tx_bandwidth; +} AD9361_TXFIRConfig; + +enum ad9361_ensm_mode { + ENSM_MODE_TX, + ENSM_MODE_RX, + ENSM_MODE_ALERT, + ENSM_MODE_FDD, + ENSM_MODE_WAIT, + ENSM_MODE_SLEEP, + ENSM_MODE_PINCTRL, + ENSM_MODE_PINCTRL_FDD_INDEP, +}; + +#define ENABLE 1 +#define DISABLE 0 + +#define RX1 0 +#define RX2 1 + +#define TX1 0 +#define TX2 1 + +#define A_BALANCED 0 +#define B_BALANCED 1 +#define C_BALANCED 2 +#define A_N 3 +#define A_P 4 +#define B_N 5 +#define B_P 6 +#define C_N 7 +#define C_P 8 +#define TX_MON1 9 +#define TX_MON2 10 +#define TX_MON1_2 11 + +#define TXA 0 +#define TXB 1 + +#define MODE_1x1 1 +#define MODE_2x2 2 + +#define HIGHEST_OSR 0 +#define NOMINAL_OSR 1 + +#define INT_LO 0 +#define EXT_LO 1 + +#define ON 0 +#define OFF 1 + +/******************************************************************************/ +/************************ Functions Declarations ******************************/ +/******************************************************************************/ +/* Initialize the AD9361 part. */ +int32_t ad9361_init (struct ad9361_rf_phy **ad9361_phy, + AD9361_InitParam *init_param); +/* Free the allocated resources. */ +int32_t ad9361_remove(struct ad9361_rf_phy *phy); +/* Set the Enable State Machine (ENSM) mode. */ +int32_t ad9361_set_en_state_machine_mode (struct ad9361_rf_phy *phy, + uint32_t mode); +/* Get the Enable State Machine (ENSM) mode. */ +int32_t ad9361_get_en_state_machine_mode (struct ad9361_rf_phy *phy, + uint32_t *mode); +/* Set the receive RF gain for the selected channel. */ +int32_t ad9361_set_rx_rf_gain (struct ad9361_rf_phy *phy, uint8_t ch, + int32_t gain_db); +/* Get current receive RF gain for the selected channel. */ +int32_t ad9361_get_rx_rf_gain (struct ad9361_rf_phy *phy, uint8_t ch, + int32_t *gain_db); +/* Set the RX RF bandwidth. */ +int32_t ad9361_set_rx_rf_bandwidth (struct ad9361_rf_phy *phy, + uint32_t bandwidth_hz); +/* Get the RX RF bandwidth. */ +int32_t ad9361_get_rx_rf_bandwidth (struct ad9361_rf_phy *phy, + uint32_t *bandwidth_hz); +/* Set the RX sampling frequency. */ +int32_t ad9361_set_rx_sampling_freq (struct ad9361_rf_phy *phy, + uint32_t sampling_freq_hz); +/* Get current RX sampling frequency. */ +int32_t ad9361_get_rx_sampling_freq (struct ad9361_rf_phy *phy, + uint32_t *sampling_freq_hz); +/* Set the RX LO frequency. */ +int32_t ad9361_set_rx_lo_freq (struct ad9361_rf_phy *phy, uint64_t lo_freq_hz); +/* Get current RX LO frequency. */ +int32_t ad9361_get_rx_lo_freq (struct ad9361_rf_phy *phy, uint64_t *lo_freq_hz); +/* Switch between internal and external LO. */ +int32_t ad9361_set_rx_lo_int_ext(struct ad9361_rf_phy *phy, uint8_t int_ext); +/* Get the RSSI for the selected channel. */ +int32_t ad9361_get_rx_rssi (struct ad9361_rf_phy *phy, uint8_t ch, + struct rf_rssi *rssi); +/* Set the gain control mode for the selected channel. */ +int32_t ad9361_set_rx_gain_control_mode (struct ad9361_rf_phy *phy, uint8_t ch, + uint8_t gc_mode); +/* Get the gain control mode for the selected channel. */ +int32_t ad9361_get_rx_gain_control_mode (struct ad9361_rf_phy *phy, uint8_t ch, + uint8_t *gc_mode); +/* Set the RX FIR filter configuration. */ +int32_t ad9361_set_rx_fir_config (struct ad9361_rf_phy *phy, + AD9361_RXFIRConfig fir_cfg); +/* Get the RX FIR filter configuration. */ +int32_t ad9361_get_rx_fir_config(struct ad9361_rf_phy *phy, uint8_t rx_ch, + AD9361_RXFIRConfig *fir_cfg); +/* Enable/disable the RX FIR filter. */ +int32_t ad9361_set_rx_fir_en_dis (struct ad9361_rf_phy *phy, uint8_t en_dis); +/* Get the status of the RX FIR filter. */ +int32_t ad9361_get_rx_fir_en_dis (struct ad9361_rf_phy *phy, uint8_t *en_dis); +/* Enable/disable the RX RFDC Tracking. */ +int32_t ad9361_set_rx_rfdc_track_en_dis (struct ad9361_rf_phy *phy, + uint8_t en_dis); +/* Get the status of the RX RFDC Tracking. */ +int32_t ad9361_get_rx_rfdc_track_en_dis (struct ad9361_rf_phy *phy, + uint8_t *en_dis); +/* Enable/disable the RX BasebandDC Tracking. */ +int32_t ad9361_set_rx_bbdc_track_en_dis (struct ad9361_rf_phy *phy, + uint8_t en_dis); +/* Get the status of the RX BasebandDC Tracking. */ +int32_t ad9361_get_rx_bbdc_track_en_dis (struct ad9361_rf_phy *phy, + uint8_t *en_dis); +/* Enable/disable the RX Quadrature Tracking. */ +int32_t ad9361_set_rx_quad_track_en_dis (struct ad9361_rf_phy *phy, + uint8_t en_dis); +/* Get the status of the RX Quadrature Tracking. */ +int32_t ad9361_get_rx_quad_track_en_dis (struct ad9361_rf_phy *phy, + uint8_t *en_dis); +/* Set the RX RF input port. */ +int32_t ad9361_set_rx_rf_port_input (struct ad9361_rf_phy *phy, uint32_t mode); +/* Get the selected RX RF input port. */ +int32_t ad9361_get_rx_rf_port_input (struct ad9361_rf_phy *phy, uint32_t *mode); +/* Store RX fastlock profile. */ +int32_t ad9361_rx_fastlock_store(struct ad9361_rf_phy *phy, uint32_t profile); +/* Recall RX fastlock profile. */ +int32_t ad9361_rx_fastlock_recall(struct ad9361_rf_phy *phy, uint32_t profile); +/* Load RX fastlock profile. */ +int32_t ad9361_rx_fastlock_load(struct ad9361_rf_phy *phy, uint32_t profile, + uint8_t *values); +/* Save RX fastlock profile. */ +int32_t ad9361_rx_fastlock_save(struct ad9361_rf_phy *phy, uint32_t profile, + uint8_t *values); +/* Power down the RX Local Oscillator. */ +int32_t ad9361_rx_lo_powerdown(struct ad9361_rf_phy *phy, uint8_t option); +/* Get the RX Local Oscillator power status. */ +int32_t ad9361_get_rx_lo_power(struct ad9361_rf_phy *phy, uint8_t *option); +/* Set the transmit attenuation for the selected channel. */ +int32_t ad9361_set_tx_attenuation (struct ad9361_rf_phy *phy, uint8_t ch, + uint32_t attenuation_mdb); +/* Get current transmit attenuation for the selected channel. */ +int32_t ad9361_get_tx_attenuation (struct ad9361_rf_phy *phy, uint8_t ch, + uint32_t *attenuation_mdb); +/* Set the TX RF bandwidth. */ +int32_t ad9361_set_tx_rf_bandwidth (struct ad9361_rf_phy *phy, + uint32_t bandwidth_hz); +/* Get the TX RF bandwidth. */ +int32_t ad9361_get_tx_rf_bandwidth (struct ad9361_rf_phy *phy, + uint32_t *bandwidth_hz); +/* Set the TX sampling frequency. */ +int32_t ad9361_set_tx_sampling_freq (struct ad9361_rf_phy *phy, + uint32_t sampling_freq_hz); +/* Get current TX sampling frequency. */ +int32_t ad9361_get_tx_sampling_freq (struct ad9361_rf_phy *phy, + uint32_t *sampling_freq_hz); +/* Set the TX LO frequency. */ +int32_t ad9361_set_tx_lo_freq (struct ad9361_rf_phy *phy, uint64_t lo_freq_hz); +/* Get current TX LO frequency. */ +int32_t ad9361_get_tx_lo_freq (struct ad9361_rf_phy *phy, uint64_t *lo_freq_hz); +/* Switch between internal and external LO. */ +int32_t ad9361_set_tx_lo_int_ext(struct ad9361_rf_phy *phy, uint8_t int_ext); +/* Set the TX FIR filter configuration. */ +int32_t ad9361_set_tx_fir_config (struct ad9361_rf_phy *phy, + AD9361_TXFIRConfig fir_cfg); +/* Get the TX FIR filter configuration. */ +int32_t ad9361_get_tx_fir_config(struct ad9361_rf_phy *phy, uint8_t tx_ch, + AD9361_TXFIRConfig *fir_cfg); +/* Enable/disable the TX FIR filter. */ +int32_t ad9361_set_tx_fir_en_dis (struct ad9361_rf_phy *phy, uint8_t en_dis); +/* Get the status of the TX FIR filter. */ +int32_t ad9361_get_tx_fir_en_dis (struct ad9361_rf_phy *phy, uint8_t *en_dis); +/* Get the TX RSSI for the selected channel. */ +int32_t ad9361_get_tx_rssi (struct ad9361_rf_phy *phy, uint8_t ch, + uint32_t *rssi_db_x_1000); +/* Set the TX RF output port. */ +int32_t ad9361_set_tx_rf_port_output (struct ad9361_rf_phy *phy, uint32_t mode); +/* Get the selected TX RF output port. */ +int32_t ad9361_get_tx_rf_port_output (struct ad9361_rf_phy *phy, + uint32_t *mode); +/* Enable/disable the auto calibration. */ +int32_t ad9361_set_tx_auto_cal_en_dis (struct ad9361_rf_phy *phy, + uint8_t en_dis); +/* Get the status of the auto calibration flag. */ +int32_t ad9361_get_tx_auto_cal_en_dis (struct ad9361_rf_phy *phy, + uint8_t *en_dis); +/* Store TX fastlock profile. */ +int32_t ad9361_tx_fastlock_store(struct ad9361_rf_phy *phy, uint32_t profile); +/* Recall TX fastlock profile. */ +int32_t ad9361_tx_fastlock_recall(struct ad9361_rf_phy *phy, uint32_t profile); +/* Load TX fastlock profile. */ +int32_t ad9361_tx_fastlock_load(struct ad9361_rf_phy *phy, uint32_t profile, + uint8_t *values); +/* Save TX fastlock profile. */ +int32_t ad9361_tx_fastlock_save(struct ad9361_rf_phy *phy, uint32_t profile, + uint8_t *values); +/* Power down the TX Local Oscillator. */ +int32_t ad9361_tx_lo_powerdown(struct ad9361_rf_phy *phy, uint8_t option); +/* Get the TX Local Oscillator power status. */ +int32_t ad9361_get_tx_lo_power(struct ad9361_rf_phy *phy, uint8_t *option); +/* Set the RX and TX path rates. */ +int32_t ad9361_set_trx_path_clks(struct ad9361_rf_phy *phy, + uint32_t *rx_path_clks, uint32_t *tx_path_clks); +/* Get the RX and TX path rates. */ +int32_t ad9361_get_trx_path_clks(struct ad9361_rf_phy *phy, + uint32_t *rx_path_clks, uint32_t *tx_path_clks); +/* Set the number of channels mode. */ +int32_t ad9361_set_no_ch_mode(struct ad9361_rf_phy *phy, uint8_t no_ch_mode); +/* Do multi chip synchronization. */ +int32_t ad9361_do_mcs(struct ad9361_rf_phy *phy_master, + struct ad9361_rf_phy *phy_slave); +/* Enable/disable the TRX FIR filters. */ +int32_t ad9361_set_trx_fir_en_dis (struct ad9361_rf_phy *phy, uint8_t en_dis); +/* Set the OSR rate governor. */ +int32_t ad9361_set_trx_rate_gov (struct ad9361_rf_phy *phy, uint32_t rate_gov); +/* Get the OSR rate governor. */ +int32_t ad9361_get_trx_rate_gov (struct ad9361_rf_phy *phy, uint32_t *rate_gov); +/* Perform the selected calibration. */ +int32_t ad9361_do_calib(struct ad9361_rf_phy *phy, uint32_t cal, int32_t arg); +/* Load and enable TRX FIR filters configurations. */ +int32_t ad9361_trx_load_enable_fir(struct ad9361_rf_phy *phy, + AD9361_RXFIRConfig rx_fir_cfg, + AD9361_TXFIRConfig tx_fir_cfg); +/* Do DCXO coarse tuning. */ +int32_t ad9361_do_dcxo_tune_coarse(struct ad9361_rf_phy *phy, + uint32_t coarse); +/* Do DCXO fine tuning. */ +int32_t ad9361_do_dcxo_tune_fine(struct ad9361_rf_phy *phy, + uint32_t fine); +/* Get the temperature. */ +int32_t ad9361_get_temperature(struct ad9361_rf_phy *phy, + int32_t *temp); +#endif diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/rf-transceiver/ad9361/ad9361_conv.c b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/rf-transceiver/ad9361/ad9361_conv.c new file mode 100644 index 0000000..7ce74b7 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/rf-transceiver/ad9361/ad9361_conv.c @@ -0,0 +1,86 @@ + +/***************************************************************************//** + * @file ad9361_conv.c + * @brief Implementation of AD9361 Conv Driver. +******************************************************************************** + * Copyright 2014-2015(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ +#include +#include +#include "ad9361.h" +#include "ad9361_util.h" +#include "delay.h" +#include "../../../config/app_config.h" + +/******************************************************************************/ +/********************** Macros and Constants Definitions **********************/ +/******************************************************************************/ + +/** + * HDL loopback enable/disable. + * @param phy The AD9361 state structure. + * @param enable Enable/disable option. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_hdl_loopback(struct ad9361_rf_phy *phy, bool enable) +{ + return -ENODEV; +} + +/** + * Digital tune. + * @param phy The AD9361 state structure. + * @param max_freq Maximum frequency. + * @param flags Flags: BE_VERBOSE, BE_MOREVERBOSE, DO_IDELAY, DO_ODELAY. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_dig_tune(struct ad9361_rf_phy *phy, uint32_t max_freq, + enum dig_tune_flags flags) +{ + return 0; +} + +/** +* Setup the AD9361 device. +* @param phy The AD9361 state structure. +* @return 0 in case of success, negative error code otherwise. +*/ +int32_t ad9361_post_setup(struct ad9361_rf_phy *phy) +{ + return 0; +} diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/rf-transceiver/ad9361/ad9361_util.c b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/rf-transceiver/ad9361/ad9361_util.c new file mode 100644 index 0000000..dac33d0 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/rf-transceiver/ad9361/ad9361_util.c @@ -0,0 +1,335 @@ +/***************************************************************************//** + * @file ad9361_util.c + * @brief AD9361 Implementation of Util Driver. + * @author DBogdan (dragos.bogdan@analog.com) +******************************************************************************** + * Copyright 2013(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ +#include +#include "ad9361_util.h" +#include "../../../include/delay.h" + +/******************************************************************************/ +/*************************** Macros Definitions *******************************/ +/******************************************************************************/ +#define BITS_PER_LONG 32 + +/***************************************************************************//** + * @brief clk_prepare_enable +*******************************************************************************/ +int32_t clk_prepare_enable(struct clk *clk) +{ + if (clk) { + // Unused variable - fix compiler warning + } + + return 0; +} + +/***************************************************************************//** + * @brief clk_get_rate +*******************************************************************************/ +uint32_t clk_get_rate(struct ad9361_rf_phy *phy, + struct refclk_scale *clk_priv) +{ + uint32_t rate = 0; + uint32_t source; + + source = clk_priv->source; + + switch (source) { + case TX_REFCLK: + case RX_REFCLK: + case BB_REFCLK: + rate = ad9361_clk_factor_recalc_rate(clk_priv, + phy->clk_refin->rate); + break; + case TX_RFPLL_INT: + case RX_RFPLL_INT: + rate = ad9361_rfpll_int_recalc_rate(clk_priv, + phy->clks[clk_priv->parent_source]->rate); + break; + case RX_RFPLL_DUMMY: + case TX_RFPLL_DUMMY: + rate = ad9361_rfpll_dummy_recalc_rate(clk_priv); + break; + case TX_RFPLL: + case RX_RFPLL: + rate = ad9361_rfpll_recalc_rate(clk_priv); + break; + case BBPLL_CLK: + rate = ad9361_bbpll_recalc_rate(clk_priv, + phy->clks[clk_priv->parent_source]->rate); + break; + case ADC_CLK: + case R2_CLK: + case R1_CLK: + case CLKRF_CLK: + case RX_SAMPL_CLK: + case DAC_CLK: + case T2_CLK: + case T1_CLK: + case CLKTF_CLK: + case TX_SAMPL_CLK: + rate = ad9361_clk_factor_recalc_rate(clk_priv, + phy->clks[clk_priv->parent_source]->rate); + break; + default: + break; + } + + return rate; +} + +/***************************************************************************//** + * @brief clk_set_rate +*******************************************************************************/ +int32_t clk_set_rate(struct ad9361_rf_phy *phy, + struct refclk_scale *clk_priv, + uint32_t rate) +{ + uint32_t source; + int32_t i; + uint32_t round_rate; + + source = clk_priv->source; + if(phy->clks[source]->rate != rate) + { + switch (source) { + case TX_REFCLK: + case RX_REFCLK: + case BB_REFCLK: + round_rate = ad9361_clk_factor_round_rate(clk_priv, rate, + &phy->clk_refin->rate); + ad9361_clk_factor_set_rate(clk_priv, round_rate, + phy->clk_refin->rate); + phy->clks[source]->rate = ad9361_clk_factor_recalc_rate(clk_priv, + phy->clk_refin->rate); + break; + case TX_RFPLL_INT: + case RX_RFPLL_INT: + round_rate = ad9361_rfpll_int_round_rate(clk_priv, rate, + &phy->clks[clk_priv->parent_source]->rate); + ad9361_rfpll_int_set_rate(clk_priv, round_rate, + phy->clks[clk_priv->parent_source]->rate); + phy->clks[source]->rate = ad9361_rfpll_int_recalc_rate(clk_priv, + phy->clks[clk_priv->parent_source]->rate); + break; + case RX_RFPLL_DUMMY: + case TX_RFPLL_DUMMY: + ad9361_rfpll_dummy_set_rate(clk_priv, rate); + break; + case TX_RFPLL: + case RX_RFPLL: + round_rate = ad9361_rfpll_round_rate(clk_priv, rate); + ad9361_rfpll_set_rate(clk_priv, round_rate); + phy->clks[source]->rate = ad9361_rfpll_recalc_rate(clk_priv); + break; + case BBPLL_CLK: + round_rate = ad9361_bbpll_round_rate(clk_priv, rate, + &phy->clks[clk_priv->parent_source]->rate); + ad9361_bbpll_set_rate(clk_priv, round_rate, + phy->clks[clk_priv->parent_source]->rate); + phy->clks[source]->rate = ad9361_bbpll_recalc_rate(clk_priv, + phy->clks[clk_priv->parent_source]->rate); + phy->bbpll_initialized = true; + break; + case ADC_CLK: + case R2_CLK: + case R1_CLK: + case CLKRF_CLK: + case RX_SAMPL_CLK: + case DAC_CLK: + case T2_CLK: + case T1_CLK: + case CLKTF_CLK: + case TX_SAMPL_CLK: + round_rate = ad9361_clk_factor_round_rate(clk_priv, rate, + &phy->clks[clk_priv->parent_source]->rate); + ad9361_clk_factor_set_rate(clk_priv, round_rate, + phy->clks[clk_priv->parent_source]->rate); + phy->clks[source]->rate = ad9361_clk_factor_recalc_rate(clk_priv, + phy->clks[clk_priv->parent_source]->rate); + break; + default: + break; + } + for(i = BB_REFCLK; i < BBPLL_CLK; i++) + { + phy->clks[i]->rate = ad9361_clk_factor_recalc_rate(phy->ref_clk_scale[i], + phy->clk_refin->rate); + } + phy->clks[BBPLL_CLK]->rate = ad9361_bbpll_recalc_rate(phy->ref_clk_scale[BBPLL_CLK], + phy->clks[phy->ref_clk_scale[BBPLL_CLK]->parent_source]->rate); + for(i = ADC_CLK; i < RX_RFPLL_INT; i++) + { + phy->clks[i]->rate = ad9361_clk_factor_recalc_rate(phy->ref_clk_scale[i], + phy->clks[phy->ref_clk_scale[i]->parent_source]->rate); + } + for(i = RX_RFPLL_INT; i < RX_RFPLL_DUMMY; i++) + { + phy->clks[i]->rate = ad9361_rfpll_int_recalc_rate(phy->ref_clk_scale[i], + phy->clks[phy->ref_clk_scale[i]->parent_source]->rate); + } + for(i = RX_RFPLL_DUMMY; i < RX_RFPLL; i++) + { + phy->clks[i]->rate = ad9361_rfpll_dummy_recalc_rate(phy->ref_clk_scale[i]); + } + for(i = RX_RFPLL; i < NUM_AD9361_CLKS; i++) + { + phy->clks[i]->rate = ad9361_rfpll_recalc_rate(phy->ref_clk_scale[i]); + } + } else { + if ((source == BBPLL_CLK) && !phy->bbpll_initialized) { + round_rate = ad9361_bbpll_round_rate(clk_priv, rate, + &phy->clks[clk_priv->parent_source]->rate); + ad9361_bbpll_set_rate(clk_priv, round_rate, + phy->clks[clk_priv->parent_source]->rate); + phy->clks[source]->rate = ad9361_bbpll_recalc_rate(clk_priv, + phy->clks[clk_priv->parent_source]->rate); + phy->bbpll_initialized = true; + } + } + + return 0; +} + +/***************************************************************************//** + * @brief int_sqrt +*******************************************************************************/ +uint32_t int_sqrt(uint32_t x) +{ + uint32_t b, m, y = 0; + + if (x <= 1) + return x; + + m = 1UL << (BITS_PER_LONG - 2); + while (m != 0) { + b = y + m; + y >>= 1; + + if (x >= b) { + x -= b; + y += m; + } + m >>= 2; + } + + return y; +} + +/***************************************************************************//** + * @brief ilog2 +*******************************************************************************/ +int32_t ilog2(int32_t x) +{ + int32_t A = !(!(x >> 16)); + int32_t count = 0; + int32_t x_copy = x; + + count = count + (A << 4); + + x_copy = (((~A + 1) & (x >> 16)) + (~(~A + 1) & x)); + + A = !(!(x_copy >> 8)); + count = count + (A << 3); + x_copy = (((~A + 1) & (x_copy >> 8)) + (~(~A + 1) & x_copy)); + + A = !(!(x_copy >> 4)); + count = count + (A << 2); + x_copy = (((~A + 1) & (x_copy >> 4)) + (~(~A + 1) & x_copy)); + + A = !(!(x_copy >> 2)); + count = count + (A << 1); + x_copy = (((~A + 1) & (x_copy >> 2)) + (~(~A + 1) & x_copy)); + + A = !(!(x_copy >> 1)); + count = count + A; + + return count; +} + +/***************************************************************************//** + * @brief find_first_bit +*******************************************************************************/ +uint32_t find_first_bit(uint32_t word) +{ + int32_t num = 0; + + if ((word & 0xffff) == 0) { + num += 16; + word >>= 16; + } + if ((word & 0xff) == 0) { + num += 8; + word >>= 8; + } + if ((word & 0xf) == 0) { + num += 4; + word >>= 4; + } + if ((word & 0x3) == 0) { + num += 2; + word >>= 2; + } + if ((word & 0x1) == 0) + num += 1; + return num; +} + +/***************************************************************************//** + * @brief ERR_PTR +*******************************************************************************/ +void * ERR_PTR(long error) +{ + return (void *) error; +} + +/***************************************************************************//** + * @brief zmalloc +*******************************************************************************/ +void *zmalloc(size_t size) +{ + void *ptr = malloc(size); + if (ptr) + memset(ptr, 0, size); + mdelay(1); + + return ptr; +} diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/rf-transceiver/ad9361/ad9361_util.h b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/rf-transceiver/ad9361/ad9361_util.h new file mode 100644 index 0000000..85eb78f --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/rf-transceiver/ad9361/ad9361_util.h @@ -0,0 +1,120 @@ +/***************************************************************************//** + * @file ad9361_util.h + * @brief AD9361 Header file of Util driver. + * @author DBogdan (dragos.bogdan@analog.com) +******************************************************************************** + * Copyright 2013(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ +#ifndef __AD9361_UTIL_H__ +#define __AD9361_UTIL_H__ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ +#include +#include +#include +#include +#include "ad9361.h" +#include "common.h" + +/******************************************************************************/ +/********************** Macros and Constants Definitions **********************/ +/******************************************************************************/ +#define CLK_IGNORE_UNUSED BIT(3) +#define CLK_GET_RATE_NOCACHE BIT(6) + +#if defined(HAVE_VERBOSE_MESSAGES) +#define dev_err(dev, format, ...) ({printf(format, ## __VA_ARGS__);printf("\n"); }) +#define dev_warn(dev, format, ...) ({printf(format, ## __VA_ARGS__);printf("\n"); }) +#if defined(HAVE_DEBUG_MESSAGES) +#define dev_dbg(dev, format, ...) ({printf(format, ## __VA_ARGS__);printf("\n"); }) +#else +#define dev_dbg(dev, format, ...) ({ if (0) printf(format, ## __VA_ARGS__); }) +#endif +#define printk(format, ...) printf(format, ## __VA_ARGS__) +#else +#define dev_err(dev, format, ...) ({ if (0) printf(format, ## __VA_ARGS__); }) +#define dev_warn(dev, format, ...) ({ if (0) printf(format, ## __VA_ARGS__); }) +#define dev_dbg(dev, format, ...) ({ if (0) printf(format, ## __VA_ARGS__); }) +#define printk(format, ...) ({ if (0) printf(format, ## __VA_ARGS__); }) +#endif + +struct device { +}; + +struct spi_device { + struct device dev; + uint8_t id_no; +}; + +struct axiadc_state { + struct ad9361_rf_phy *phy; + uint32_t pcore_version; +}; + +struct axiadc_chip_info { + char *name; + int32_t num_channels; +}; + +struct axiadc_converter { + struct axiadc_chip_info *chip_info; + uint32_t scratch_reg[16]; +}; + +#ifdef WIN32 +#include "basetsd.h" +typedef SSIZE_T ssize_t; +#define strsep(s, ct) 0 +#define snprintf(s, n, format, ...) 0 +#define __func__ __FUNCTION__ +#endif + +/******************************************************************************/ +/************************ Functions Declarations ******************************/ +/******************************************************************************/ +int32_t clk_prepare_enable(struct clk *clk); +uint32_t clk_get_rate(struct ad9361_rf_phy *phy, + struct refclk_scale *clk_priv); +int32_t clk_set_rate(struct ad9361_rf_phy *phy, + struct refclk_scale *clk_priv, + uint32_t rate); +uint32_t int_sqrt(uint32_t x); +int32_t ilog2(int32_t x); +uint32_t find_first_bit(uint32_t word); +void * ERR_PTR(long error); +void *zmalloc(size_t size); + +#endif diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/rf-transceiver/ad9361/common.h b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/rf-transceiver/ad9361/common.h new file mode 100644 index 0000000..7cc2627 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/rf-transceiver/ad9361/common.h @@ -0,0 +1,66 @@ +/***************************************************************************//** + * @file common.h + * @brief Header file of Common Driver. + * @author DBogdan (dragos.bogdan@analog.com) +******************************************************************************** + * Copyright 2013(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ +#ifndef __AD9361_COMMON_H_ +#define __AD9361_COMMON_H_ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ +#include +#include "../../../include/error.h" + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ +#if defined (__STDC__) && (__STDC_VERSION__ >= 199901L) +#include +#else +typedef enum { false, true } bool; +#endif + +struct clk { + const char *name; + uint32_t rate; +}; + +struct clk_hw { + struct clk *clk; +}; + +#endif // __AD9361_COMMON_H_ diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/rf-transceiver/ad9361_reg/ad9361_reg.c b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/rf-transceiver/ad9361_reg/ad9361_reg.c new file mode 100644 index 0000000..b6806e2 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/rf-transceiver/ad9361_reg/ad9361_reg.c @@ -0,0 +1,151 @@ +/***************************************************************************//** + * @file ad9361_reg.c + * @brief Implementation of AD9680 Driver. + * @author DBogdan (dragos.bogdan@analog.com) + ******************************************************************************** + * Copyright 2014-2016(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *******************************************************************************/ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ +#include "ad9361_reg.h" + +#include +#include +#include "../../../include/error.h" + +/***************************************************************************//** + * @brief ad9361_reg_read + *******************************************************************************/ +int32_t ad9361_reg_read(struct ad9361_reg_dev *dev, + uint16_t reg_addr, + uint8_t *reg_data) +{ + uint8_t tx_buf[2]; + uint8_t rx_buf[1]; + int32_t ret; + + tx_buf[0] = reg_addr >> 8; + tx_buf[1] = reg_addr & 0xFF; + + + ret = spi_write_and_read_3wire(dev->spi_desc, + tx_buf, rx_buf, 2, 1); + + *reg_data = rx_buf[0]; + + return ret; +} + +/***************************************************************************//** + * @brief ad9361_reg_write + *******************************************************************************/ +int32_t ad9361_reg_write(struct ad9361_reg_dev *dev, + uint16_t reg_addr, + uint8_t reg_data) +{ + uint8_t buf[3]; + + int32_t ret; + + buf[0] = 0x80 | reg_addr >> 8; + buf[1] = reg_addr & 0xFF; + buf[2] = reg_data; + + ret = spi_write_and_read_3wire(dev->spi_desc, + buf, NULL, 3, 0); + return ret; +} + +/***************************************************************************//** + * @brief ad9361_reg_init + *******************************************************************************/ +int32_t ad9361_reg_init(struct ad9361_reg_dev **device, + const struct ad9361_reg_init_param *init_param) +{ + int ret = SUCCESS; + struct ad9361_reg_dev *dev; + + dev = (struct ad9361_reg_dev *)malloc(sizeof(*dev)); + if (!dev) + return FAILURE; + + /* SPI */ + ret = spi_init(&dev->spi_desc, init_param->spi_init); + ret |= gpio_get(&dev->gpio_desc_resetb, init_param->gpio_resetb); + + gpio_direction_output(dev->gpio_desc_resetb, 0); + + ad9361_reg_reset(dev); + + *device = dev; + + return ret; +} + +/** + * AD9361 Device Reset + * @param phy The AD9361 state structure. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_reg_reset(struct ad9361_reg_dev *dev) +{ + if (dev->gpio_desc_resetb) { + gpio_set_value(dev->gpio_desc_resetb, 0); + mdelay(10); + gpio_set_value(dev->gpio_desc_resetb, 1); + mdelay(10); + return 0; + } + return 0; +} + +/***************************************************************************//** + * @brief Free the resources allocated by ad9361_reg_setup(). + * + * @param dev - The device structure. + * + * @return SUCCESS in case of success, negative error code otherwise. +*******************************************************************************/ +int32_t ad9361_reg_remove(struct ad9361_reg_dev *dev) +{ + int32_t ret; + + ret = spi_remove(dev->spi_desc); + + free(dev); + + return ret; +} diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/rf-transceiver/ad9361_reg/ad9361_reg.h b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/rf-transceiver/ad9361_reg/ad9361_reg.h new file mode 100644 index 0000000..102df4b --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/rf-transceiver/ad9361_reg/ad9361_reg.h @@ -0,0 +1,104 @@ +/***************************************************************************//** + * @file ad9361_reg.h + * @brief Header file of ad9361_reg Driver. + * @author DBogdan (dragos.bogdan@analog.com) + ******************************************************************************** + * Copyright 2014-2016(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *******************************************************************************/ +#ifndef ad9361_reg_H_ +#define ad9361_reg_H_ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ +#include +#include "delay.h" +#include "spi.h" +#include "gpio.h" + +/******************************************************************************/ +/********************** Macros and Constants Definitions **********************/ +/******************************************************************************/ + + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ +struct ad9361_reg_dev { + /* SPI */ + struct spi_desc *spi_desc; + struct gpio_desc *gpio_desc_resetb; +}; + +struct ad9361_reg_init_param { + /* SPI */ + struct spi_init_param *spi_init; + struct gpio_init_param *gpio_resetb; +}; + +enum Operation_Type{ + AD9361_WRITE, + AD9361_READ, + AD9361_WAIT, + AD9361_WHEN +}; + +struct ad9361_reg_config { + int operation; + uint16_t val1; + uint16_t val2; +}; + + + +/******************************************************************************/ +/************************ Functions Declarations ******************************/ +/******************************************************************************/ + +int32_t ad9361_reg_read(struct ad9361_reg_dev *dev, + uint16_t reg_addr, + uint8_t *reg_data); + +int32_t ad9361_reg_write(struct ad9361_reg_dev *dev, + uint16_t reg_addr, + uint8_t reg_data); + +int32_t ad9361_reg_init(struct ad9361_reg_dev **device, + const struct ad9361_reg_init_param *init_param); + +int32_t ad9361_reg_reset(struct ad9361_reg_dev *dev); + +int32_t ad9361_reg_remove(struct ad9361_reg_dev *dev); + +#endif diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/rf-transceiver/cx9261a/cx9261a.c b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/rf-transceiver/cx9261a/cx9261a.c new file mode 100644 index 0000000..f0bfcde --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/rf-transceiver/cx9261a/cx9261a.c @@ -0,0 +1,147 @@ +/***************************************************************************//** + * @file cx9261a.c + * @brief Implementation of CX9261A Driver. + *******************************************************************************/ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ +#include +#include +#include "../../../include/error.h" + +#include "cx9261a.h" + +/***************************************************************************//** + * @brief cx9261a_read + *******************************************************************************/ +int32_t cx9261a_read(struct cx9261a_dev *dev, + uint16_t reg_addr, + uint8_t *reg_data) +{ + uint8_t tx_buf[2]; + uint8_t rx_buf[1]; + int32_t ret; + + tx_buf[0] = reg_addr >> 8; + tx_buf[1] = reg_addr & 0xFF; + + + ret = spi_write_and_read_3wire(dev->spi_desc, + tx_buf, rx_buf, 2, 1); + + *reg_data = rx_buf[0]; + + return ret; +} + +/***************************************************************************//** + * @brief cx9261a_write + *******************************************************************************/ +int32_t cx9261a_write(struct cx9261a_dev *dev, + uint16_t reg_addr, + uint8_t reg_data) +{ + uint8_t buf[3]; + + int32_t ret; + + buf[0] = 0x80 | reg_addr >> 8; + buf[1] = reg_addr & 0xFF; + buf[2] = reg_data; + + ret = spi_write_and_read_3wire(dev->spi_desc, + buf, NULL, 3, 0); + return ret; +} + +/***************************************************************************//** + * @brief cx9261a_init + *******************************************************************************/ +int32_t cx9261a_init(struct cx9261a_dev **device, + const struct cx9261a_init_param *init_param) +{ + int ret = SUCCESS; + struct cx9261a_dev *dev; + + dev = (struct cx9261a_dev *)malloc(sizeof(*dev)); + if (!dev) + return FAILURE; + + /* SPI */ + ret = spi_init(&dev->spi_desc, init_param->spi_init); + ret |= gpio_get(&dev->gpio_desc_nrst, init_param->gpio_nrst); + ret |= gpio_get(&dev->gpio_desc_txnrx_trx1, init_param->gpio_txnrx_trx1); + ret |= gpio_get(&dev->gpio_desc_txnrx_trx2, init_param->gpio_txnrx_trx2); + ret |= gpio_get(&dev->gpio_desc_txnrx_rxfb, init_param->gpio_txnrx_rxfb); + ret |= gpio_get(&dev->gpio_desc_enable_trx1, init_param->gpio_enable_trx1); + ret |= gpio_get(&dev->gpio_desc_enable_trx2, init_param->gpio_enable_trx2); + ret |= gpio_get(&dev->gpio_desc_enable_rxfb, init_param->gpio_enable_rxfb); + ret |= gpio_get(&dev->gpio_desc_pl_rst, init_param->gpio_pl_rst); + ret |= gpio_get(&dev->gpio_desc_tr_sel, init_param->gpio_tr_sel); + ret |= gpio_get(&dev->gpio_desc_tdd_fdd_sel, init_param->gpio_tdd_fdd_sel); + ret |= gpio_get(&dev->gpio_desc_r1t1_r2t2_sel, init_param->gpio_r1t1_r2t2_sel); + ret |= gpio_get(&dev->gpio_desc_sp_dp_sel, init_param->gpio_sp_dp_sel); + ret |= gpio_get(&dev->gpio_desc_mclk_delay_ctrl0, init_param->gpio_mclk_delay_ctrl0); + ret |= gpio_get(&dev->gpio_desc_mclk_delay_ctrl1, init_param->gpio_mclk_delay_ctrl1); + ret |= gpio_get(&dev->gpio_desc_mclk_delay_ctrl2, init_param->gpio_mclk_delay_ctrl2); + ret |= gpio_get(&dev->gpio_desc_hop_flag, init_param->gpio_hop_flag); + + gpio_direction_output(dev->gpio_desc_nrst, 0); + gpio_direction_output(dev->gpio_desc_txnrx_trx1, 0); + gpio_direction_output(dev->gpio_desc_txnrx_trx2, 0); + gpio_direction_output(dev->gpio_desc_txnrx_rxfb, 0); + gpio_direction_output(dev->gpio_desc_enable_trx1, 0); + gpio_direction_output(dev->gpio_desc_enable_trx2, 0); + gpio_direction_output(dev->gpio_desc_enable_rxfb, 0); + gpio_direction_output(dev->gpio_desc_pl_rst, 0); + gpio_direction_output(dev->gpio_desc_tr_sel, 0); + gpio_direction_output(dev->gpio_desc_tdd_fdd_sel, 0); + gpio_direction_output(dev->gpio_desc_r1t1_r2t2_sel, 0); + gpio_direction_output(dev->gpio_desc_sp_dp_sel, 0); + gpio_direction_output(dev->gpio_desc_mclk_delay_ctrl0, 0); + gpio_direction_output(dev->gpio_desc_mclk_delay_ctrl1, 0); + gpio_direction_output(dev->gpio_desc_mclk_delay_ctrl2, 0); + gpio_direction_input(dev->gpio_desc_hop_flag); + + cx9261a_reset(dev); + + *device = dev; + + return ret; +} + +/** + * AD9361 Device Reset + * @param phy The AD9361 state structure. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t cx9261a_reset(struct cx9261a_dev *dev) +{ + if (dev->gpio_desc_nrst) { + gpio_set_value(dev->gpio_desc_nrst, 0); + mdelay(10); + gpio_set_value(dev->gpio_desc_nrst, 1); + mdelay(10); + return 0; + } + return 0; +} + +/***************************************************************************//** + * @brief Free the resources allocated by cx9261a_setup(). + * + * @param dev - The device structure. + * + * @return SUCCESS in case of success, negative error code otherwise. +*******************************************************************************/ +int32_t cx9261a_remove(struct cx9261a_dev *dev) +{ + int32_t ret; + + ret = spi_remove(dev->spi_desc); + + free(dev); + + return ret; +} diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/rf-transceiver/cx9261a/cx9261a.h b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/rf-transceiver/cx9261a/cx9261a.h new file mode 100644 index 0000000..ca38551 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/rf-transceiver/cx9261a/cx9261a.h @@ -0,0 +1,85 @@ +/***************************************************************************//** + * @file cx9261a.h + * @brief Header file of cx9261a Driver. + *******************************************************************************/ +#ifndef CX9261A_H_ +#define CX9261A_H_ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ +#include +#include "delay.h" +#include "spi.h" +#include "gpio.h" + +/******************************************************************************/ +/********************** Macros and Constants Definitions **********************/ +/******************************************************************************/ + + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ +struct cx9261a_dev { + /* SPI */ + struct spi_desc *spi_desc; + struct gpio_desc *gpio_desc_nrst; + struct gpio_desc *gpio_desc_txnrx_trx1; + struct gpio_desc *gpio_desc_txnrx_trx2; + struct gpio_desc *gpio_desc_txnrx_rxfb; + struct gpio_desc *gpio_desc_enable_trx1; + struct gpio_desc *gpio_desc_enable_trx2; + struct gpio_desc *gpio_desc_enable_rxfb; + struct gpio_desc *gpio_desc_pl_rst; + struct gpio_desc *gpio_desc_tr_sel; + struct gpio_desc *gpio_desc_tdd_fdd_sel; + struct gpio_desc *gpio_desc_r1t1_r2t2_sel; + struct gpio_desc *gpio_desc_sp_dp_sel; + struct gpio_desc *gpio_desc_mclk_delay_ctrl0; + struct gpio_desc *gpio_desc_mclk_delay_ctrl1; + struct gpio_desc *gpio_desc_mclk_delay_ctrl2; + struct gpio_desc *gpio_desc_hop_flag; +}; + +struct cx9261a_init_param { + /* SPI */ + struct spi_init_param *spi_init; + struct gpio_init_param *gpio_nrst; + struct gpio_init_param *gpio_txnrx_trx1; + struct gpio_init_param *gpio_txnrx_trx2; + struct gpio_init_param *gpio_txnrx_rxfb; + struct gpio_init_param *gpio_enable_trx1; + struct gpio_init_param *gpio_enable_trx2; + struct gpio_init_param *gpio_enable_rxfb; + struct gpio_init_param *gpio_pl_rst; + struct gpio_init_param *gpio_tr_sel; + struct gpio_init_param *gpio_tdd_fdd_sel; + struct gpio_init_param *gpio_r1t1_r2t2_sel; + struct gpio_init_param *gpio_sp_dp_sel; + struct gpio_init_param *gpio_mclk_delay_ctrl0; + struct gpio_init_param *gpio_mclk_delay_ctrl1; + struct gpio_init_param *gpio_mclk_delay_ctrl2; + struct gpio_init_param *gpio_hop_flag; +}; + +/******************************************************************************/ +/************************ Functions Declarations ******************************/ +/******************************************************************************/ + +int32_t cx9261a_read(struct cx9261a_dev *dev, + uint16_t reg_addr, + uint8_t *reg_data); + +int32_t cx9261a_write(struct cx9261a_dev *dev, + uint16_t reg_addr, + uint8_t reg_data); + +int32_t cx9261a_init(struct cx9261a_dev **device, + const struct cx9261a_init_param *init_param); + +int32_t cx9261a_reset(struct cx9261a_dev *dev); + +int32_t cx9261a_remove(struct cx9261a_dev *dev); + +#endif diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/rf-transceiver/cx9261a/cx9261adriver_c.h b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/rf-transceiver/cx9261a/cx9261adriver_c.h new file mode 100644 index 0000000..aac0d07 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/rf-transceiver/cx9261a/cx9261adriver_c.h @@ -0,0 +1,982 @@ +#ifndef __CX9261ADRIVER_C_H +#define __CX9261ADRIVER_C_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef __cplusplus +#include +#include +#include +#endif + +#define MAX_NUM_FIR 64 +#define MAX_MULTI_POINTS 64 + +typedef enum { + CX9261A_WKM_Rx, + CX9261A_WKM_Tx, + CX9261A_WKM_FDD +} CX9261A_WorkMode; + +/** + * @brief 收发数据通道数量 + * @note 此模式并不代表使用几个通道进行收发 + */ +typedef enum { + CX9261A_TRM_R1T1, + CX9261A_TRM_R2T2 +} CX9261A_TrMode; + +/** + * @brief 收发接口通道数量 + */ +typedef enum { + CX9261A_PORTM_Single, + CX9261A_PORTM_Dual +} CX9261A_PortMode; + +/** + * @brief 接口模式: + * CMOS CMOS接口模式, + * LVDS_S LVDS顺序模式, + * LVDS_E LVDS奇偶模式 + */ +typedef enum { + CX9261A_IOM_CMOS, + CX9261A_IOM_LVDS_S, + CX9261A_IOM_LVDS_E +} CX9261A_IOMode; + +/** + * @brief 本振来源 + */ +typedef enum { + CX9261A_LOSRC_Pll1 = 0b00001, + CX9261A_LOSRC_Pll2 = 0b00010, + CX9261A_LOSRC_Pll3 = 0b00100, + CX9261A_LOSRC_Pll4 = 0b01000, + CX9261A_LOSRC_Pll5 = 0b10000, + CX9261A_LOSRC_Off = 0 +} CX9261A_LoSource; + +/** + * @brief 接收通道 + */ +typedef enum { + CX9261A_RXCH_Rx1 = 1, + CX9261A_RXCH_Rx2, + CX9261A_RXCH_Rx3 +} CX9261A_RxChannel; + +/** + * @brief 发射通道 + */ +typedef enum { + CX9261A_TXCH_Tx1 = 1, + CX9261A_TXCH_Tx2 +} CX9261A_TxChannel; + +/** + * @brief 电源模式 + */ +typedef enum { + CX9261A_PWM_Shutdown = 0, + CX9261A_PWM_Sleep, + CX9261A_PWM_Alert, + CX9261A_PWM_Calib, + CX9261A_PWM_Receive, + CX9261A_PWM_Transmit, + CX9261A_PWM_Duplex, + CX9261A_PWM_Obs +} CX9261A_PowerMode; + +/** + * @brief NCO模式 + */ +typedef enum { + CX9261A_NCOM_Bypass = 0, + CX9261A_NCOM_Up, + CX9261A_NCOM_Down, + CX9261A_NCOM_BIST, + CX9261A_NCOM_Master, + CX9261A_NCOM_Slaver +} CX9261A_NCOMode; + +/** + * @brief 温补模式 DAC: DAC模式 Band: 跳子带模式 + */ +typedef enum { + CX9261A_TEMPCP_DAC = 0, + CX9261A_TEMPCP_Band +} CX9261A_TemperatureComp; + +/** + * @brief 校准方法 TST: 时域统计 Rx通道使用, Bisec: 二分法 Tx通道使用, MultiPoints: 多点校准 + */ +typedef enum { + CX9261A_CALM_TST = 0, + CX9261A_CALM_Bisec, + CX9261A_CALM_MultiPoints, + CX9261A_CALM_Tracking +} CX9261A_CalibMethod; + +/** + * @brief DC校准方法 Tracking: 跟踪校准 HighPass: 高通滤波器滤掉直流 + */ +typedef enum { + CX9261A_DCCALM_Tracking=0, + CX9261A_DCCALM_HighPass +} CX9261A_DCCalibMethod; + + +typedef struct { + CX9261A_LoSource first; + CX9261A_LoSource second; +} CX9261A_LoSourcePair; + +typedef struct { + CX9261A_LoSourcePair key; + uint16_t value; +} CX9261A_SrcMapEntry; + +/** + * @brief 接收通道本振来源映射表 + */ +static const CX9261A_SrcMapEntry CX9261A_rxSrcMap[] = { + { { CX9261A_LOSRC_Pll2, CX9261A_LOSRC_Pll2 }, 0b0010000 }, + { { CX9261A_LOSRC_Pll1, CX9261A_LOSRC_Pll1 }, 0b1101000 }, + { { CX9261A_LOSRC_Pll2, CX9261A_LOSRC_Pll1 }, 0b0100000 }, + { { CX9261A_LOSRC_Pll1, CX9261A_LOSRC_Pll2 }, 0b1000000 }, + { { CX9261A_LOSRC_Off, CX9261A_LOSRC_Pll1 }, 0b0101010 }, + { { CX9261A_LOSRC_Off, CX9261A_LOSRC_Pll2 }, 0b1010010 }, + { { CX9261A_LOSRC_Pll1, CX9261A_LOSRC_Off }, 0b1001001 }, + { { CX9261A_LOSRC_Pll2, CX9261A_LOSRC_Off }, 0b0110001 }, + { { CX9261A_LOSRC_Off, CX9261A_LOSRC_Off }, 0b0011011 } +}; +/** + * @brief 发射通道本振来源映射表 + */ +static const CX9261A_SrcMapEntry CX9261A_txSrcMap[] = { + { { CX9261A_LOSRC_Pll4, CX9261A_LOSRC_Pll4 }, 16 }, { { CX9261A_LOSRC_Pll3, CX9261A_LOSRC_Pll3 }, 104 }, + { { CX9261A_LOSRC_Pll4, CX9261A_LOSRC_Pll3 }, 32 }, { { CX9261A_LOSRC_Pll3, CX9261A_LOSRC_Pll4 }, 64 }, + { { CX9261A_LOSRC_Pll2, CX9261A_LOSRC_Pll2 }, 1560 }, { { CX9261A_LOSRC_Pll1, CX9261A_LOSRC_Pll1 }, 1944 }, + { { CX9261A_LOSRC_Pll2, CX9261A_LOSRC_Pll1 }, 1688 }, { { CX9261A_LOSRC_Pll1, CX9261A_LOSRC_Pll2 }, 1816 }, + { { CX9261A_LOSRC_Off, CX9261A_LOSRC_Pll3 }, 42 }, { { CX9261A_LOSRC_Off, CX9261A_LOSRC_Pll4 }, 82 }, + { { CX9261A_LOSRC_Off, CX9261A_LOSRC_Pll2 }, 794 }, { { CX9261A_LOSRC_Off, CX9261A_LOSRC_Pll1 }, 666 }, + { { CX9261A_LOSRC_Pll3, CX9261A_LOSRC_Off }, 73 }, { { CX9261A_LOSRC_Pll4, CX9261A_LOSRC_Off }, 49 }, + { { CX9261A_LOSRC_Pll2, CX9261A_LOSRC_Off }, 1177 }, { { CX9261A_LOSRC_Pll1, CX9261A_LOSRC_Off }, 1305 }, + { { CX9261A_LOSRC_Off, CX9261A_LOSRC_Off }, 27 }, { { CX9261A_LOSRC_Pll1, CX9261A_LOSRC_Pll3 }, 1320 }, + { { CX9261A_LOSRC_Pll1, CX9261A_LOSRC_Pll4 }, 1360 }, { { CX9261A_LOSRC_Pll2, CX9261A_LOSRC_Pll3 }, 1064 }, + { { CX9261A_LOSRC_Pll2, CX9261A_LOSRC_Pll4 }, 1104 }, { { CX9261A_LOSRC_Pll3, CX9261A_LOSRC_Pll1 }, 712 }, + { { CX9261A_LOSRC_Pll4, CX9261A_LOSRC_Pll1 }, 688 }, { { CX9261A_LOSRC_Pll3, CX9261A_LOSRC_Pll2 }, 584 }, + { { CX9261A_LOSRC_Pll4, CX9261A_LOSRC_Pll2 }, 560 } +}; +/** + * @brief 环路参数选择表 + */ +static const uint8_t CX9261A_coreTable[7][4][3] = { + { { 0x0C, 0x30, 0x08 }, { 0x0B, 0x30, 0x09 }, { 0x0C, 0x30, 0x05 }, { 0x0D, 0x30, 0x08 } }, + { { 0x0C, 0x30, 0x0C }, { 0x0B, 0x30, 0x0E }, { 0x0C, 0x30, 0x08 }, { 0x0D, 0x30, 0x0B } }, + { { 0x0C, 0x20, 0x10 }, { 0x0B, 0x20, 0x10 }, { 0x0C, 0x20, 0x0A }, { 0x0D, 0x20, 0x0D } }, + { { 0x0C, 0x20, 0x11 }, { 0x0B, 0x20, 0x13 }, { 0x0C, 0x20, 0x0C }, { 0x0D, 0x20, 0x0F } }, + { { 0x0D, 0x30, 0x14 }, { 0x0D, 0x22, 0x14 }, { 0x0D, 0x20, 0x0D }, { 0x0D, 0x15, 0x0C } }, + { { 0x0E, 0x30, 0x18 }, { 0x0E, 0x25, 0x16 }, { 0x0E, 0x25, 0x0F }, { 0x0E, 0x18, 0x0F } }, + { { 0x0F, 0x38, 0x1A }, { 0x0F, 0x32, 0x1C }, { 0x0F, 0x18, 0x12 }, { 0x0F, 0x18, 0x12 } } +}; + + +/** + * @brief AGC PDT模式的结构体 + */ +typedef struct +{ + int pdtN; + int pdtM; +} CX9261A_AGCPDT; + +/** + * @brief AGC LMT模式的结构体 + */ +typedef struct +{ + int count; /**< LMT统计次数阈值*/ + int threshold1; /**< LMT阈值第一档*/ + int threshold2; /**< LMT阈值第二档*/ + int threshold3; /**< LMT阈值第三档*/ + int threshold4; /**< LMT阈值第四档*/ +} CX9261A_AGCLMT; + +/** + * @brief AGC DIG模式的结构体 + */ +typedef struct +{ + int count; /**< DIG统计次数阈值*/ + int threshold1; /**< DIG阈值第一档*/ + int threshold2; /**< DIG阈值第二档*/ + int threshold3; /**< DIG阈值第三档*/ + int threshold4; /**< DIG阈值第四档*/ +} CX9261A_AGCDIG; + +/** + * @brief AGC模式的结构体 + */ +typedef struct +{ + int mode; /**< AGC模式选择*/ + CX9261A_AGCPDT pdt; /**< AGC PDT模式的结构体*/ + CX9261A_AGCLMT lmt; /**< AGC LMT模式的结构体*/ + CX9261A_AGCDIG dig; /**< AGC DIG模式的结构体*/ +} CX9261A_AGC; + +/** + * @brief 时钟相关参数结构体 + */ +typedef struct +{ + double ref; /**< 参考时钟频率,单位MHz*/ + double adc; /**< ADC频率,单位MHz*/ + int refDiv; /**< 参考时钟分频比*/ + bool bbUseIntDiv; /**< 是否使用整数分频模式*/ + bool refDoubler; /**< 是否使用参考时钟倍频器*/ +} CX9261A_Clock; + +/** + * @brief 校准相关参数结构体 + */ +typedef struct +{ + bool calibDC; /**< 是否开启DC Tracking*/ + CX9261A_DCCalibMethod dcCalibMethod; + int dcTrackingLength; /**< DC Tracking长度*/ + int dcHighPassFactor; /**< DC高通滤波系数,越大代表滤波器阶数越高,滤波范围越窄*/ + uint8_t rx1CalibPll; /**< rx1校准的pll选择,Pll1 | Pll2*/ + uint8_t rx2CalibPll; /**< rx2校准的pll选择,Pll1 | Pll2*/ + uint8_t rx3CalibPll; /**< rx3校准的pll选择,Pll5*/ + uint8_t tx1CalibPll; /**< tx1校准的pll选择,Pll1 | Pll2 | Pll3 | Pll4*/ + uint8_t tx2CalibPll; /**< tx2校准的pll选择,Pll1 | Pll2 | Pll3 | Pll4*/ + CX9261A_CalibMethod rxMethod; + CX9261A_CalibMethod txMethod; + double f0; /**< 校准音频率*/ + uint32_t numRxPoint; /**< Rx多点校准的频率个数*/ + uint32_t numTxPoint; /**< Tx多点校准的频率个数*/ + double rxMultiPoints[MAX_MULTI_POINTS]; /**< Rx多点校准的频率*/ + double txMultiPoints[MAX_MULTI_POINTS]; /**< Tx多点校准的频率*/ +} CX9261A_Calib; + +/** + * @brief 配置PLL来源相关参数结构体 + */ +typedef struct +{ + bool rxUseExt; /**< 接收通道是否使用外本振*/ + bool txUseExt; /**< 发射通道是否使用外本振*/ + CX9261A_LoSource rx1Source; /**< Rx1通道本振来源*/ + CX9261A_LoSource rx2Source; /**< Rx2通道本振来源*/ + CX9261A_LoSource rx3Source; /**< Rx3通道本振来源*/ + CX9261A_LoSource tx1Source; /**< Tx1通道本振来源*/ + CX9261A_LoSource tx2Source; /**< Tx2通道本振来源*/ +} CX9261A_PllSource; + +/** + * @brief 配置PLL频率相关参数结构体 + */ +typedef struct +{ + double pll1Freq; /**< PLL1本振时钟,单位MHz*/ + double pll2Freq; /**< PLL2本振时钟,单位MHz*/ + double pll3Freq; /**< PLL3本振时钟,单位MHz*/ + double pll4Freq; /**< PLL4本振时钟,单位MHz*/ + double pll5Freq; /**< PLL5本振时钟,单位MHz*/ + double rxExtFreq; /**< 接收通道使用外本振时,外本振频率,单位MHz*/ + double txExtFreq; /**< 发射通道使用外本振时,外本振频率,单位MHz*/ +} CX9261A_PllFreq; + +/** + * @brief 配置接口相关参数结构体 + */ +typedef struct +{ + CX9261A_WorkMode workMode; /**< 芯片工作模式*/ + CX9261A_TrMode trMode; /**< 收发数据通道模式*/ + CX9261A_PortMode portMode; /**< 收发接口通道模式*/ + CX9261A_IOMode ioMode; /**< 接口电平模式*/ +} CX9261A_Interface; + +/** + * @brief 配置TX NCO相关参数结构体 + */ +typedef struct +{ + bool txUseBist; /**< 是否开启BIST模式*/ + double txNCOFreq; /**< NCO频率*/ +} CX9261A_TxNCO; + +/** + * @brief 配置RX NCO相关参数结构体 + */ +typedef struct +{ + bool rxUseBist; /**< 是否开启BIST模式*/ + bool rxNCOBypass; /**< 是否Bypass NCO*/ + bool rxNCOUpward; /**< 开启上/下混频模式*/ + bool rxNCOMaster; /**< 使用Master/Slaver模式*/ + double rxNCOFreq; /**< NCO频率*/ +} CX9261A_RxNCO; + +/** + * @brief 配置接收通道相关参数结构体 + */ +typedef struct { + double bandwidth; /**< 接收通道1dB带宽,单位MHz*/ + int tia; /**< 接收通道TIA增益配置,推荐配置6*/ + int mixer; /**< 接收通道Mixer增益配置*/ +} CX9261A_RxConfig; + +/** + * @brief 配置发射通道相关参数结构体 + */ +typedef struct { + double bandwidth; /**< 发射通道1dB带宽,单位MHz*/ + int mixer; /**< 发射通道Mixer增益配置*/ +} CX9261A_TxConfig; + +/** + * @brief 配置滤波器相关参数结构体,0代表bypass + */ +typedef struct { + int fir; /**< FIR滤波器抽取/插值倍数*/ + int hbf1; /**< HBF1滤波器抽取/插值倍数*/ + int hbf2; /**< HBF2滤波器抽取/插值倍数*/ + int hbf3; /**< HBF3滤波器抽取/插值倍数*/ + int cic; /**< CIC滤波器抽取/插值倍数*/ +} CX9261A_Filters; + +/** + * @brief 配置电源模式结构体,1代表该模块上电 + */ +typedef struct { + bool dig_tx2; + bool dig_tx1; + bool dig_rx3; + bool dig_rx2; + bool dig_rx1; + bool fref1_rx; + bool auxadc2; + bool auxadc1; + bool auxdac; + bool temp_sensor; + bool bgr; + bool exlo; + bool tx2; + bool tx1; + bool rx3; + bool rx2; + bool rx1; + bool pll5_ldo; + bool pll5; + bool pll4_ldo; + bool pll4; + bool pll3_ldo; + bool pll3; + bool pll2_ldo; + bool pll2; + bool pll1_ldo; + bool pll1; + bool bbpll; +} CX9261A_Power; + +/** + * @brief 配置电源模式管理,包含模式选择,接收模式,发射模式,FDD模式 + */ +typedef struct { + CX9261A_PowerMode powerMode; + CX9261A_Power rxPower; + CX9261A_Power txPower; + CX9261A_Power fddPower; +} CX9261A_PowerManagement; + +/** + * @brief 储存窄带校准结果的结构体 + */ +typedef struct { + int bHigh; + int bLow; + int cHigh; + int cLow; + int dciHigh; + int dciLow; + int dcqHigh; + int dcqLow; +} CX9261A_CalibPredis; + +/** + * @brief CX9261A结构体 + */ +typedef struct { + CX9261A_TemperatureComp tempComp; /**< 温度补偿*/ + CX9261A_AGC agc; /**< AGC结构体*/ + CX9261A_Interface interface; /**< Interface结构体*/ + CX9261A_Clock clock; /**< Clock结构体*/ + CX9261A_PllSource pllSource; /**< PllSource结构体*/ + CX9261A_Calib calib; /**< Calib结构体*/ + CX9261A_PllFreq pllFreq; /**< PllFreq结构体*/ + CX9261A_TxNCO txNco; /**< TxNCO结构体*/ + CX9261A_RxNCO rxNco; /**< RxNCO结构体*/ + CX9261A_RxConfig rx1Config; /**< RxConfig结构体*/ + CX9261A_RxConfig rx2Config; /**< RxConfig结构体*/ + CX9261A_RxConfig rx3Config; /**< RxConfig结构体*/ + CX9261A_TxConfig tx1Config; /**< TxConfig结构体*/ + CX9261A_TxConfig tx2Config; /**< TxConfig结构体*/ + CX9261A_Filters rxFilters; /**< Filters结构体*/ + CX9261A_Filters txFilters; /**< Filters结构体*/ + CX9261A_PowerManagement powerManagement; /**< PowerManagement结构体*/ + uint32_t numRxFIR; + uint32_t numTxFIR; + double rxFIRCoe[MAX_NUM_FIR]; /**< Rx FIR滤波器系数*/ + double txFIRCoe[MAX_NUM_FIR]; /**< Tx FIR滤波器系数*/ +} CX9261A_CX9261AConfiguration; + +typedef struct { + int first; + int second; +}QecStatePair; + + +// 定义函数指针类型 +typedef void (*CX9261A_LoggingFunc)(const char* msg); +typedef void (*CX9261A_WriteSpiFunc)(int address, int value); +typedef int (*CX9261A_ReadSpiFunc)(int address); +typedef void (*CX9261A_PauseFunc)(double ms); +typedef void (*CX9261A_SetPinFunc)(int pin, int value); + +/** + * @brief 绑定日志函数 + * @param msg 要输出的内容 + */ +void CX9261A_setLoggingFunc(CX9261A_LoggingFunc func); +/** + * @brief 绑定SPI写入寄存器函数 + * @param address 要写入的寄存器地址 + * @param value 要写入的寄存器值 + */ +void CX9261A_setWriteSpiFunc(CX9261A_WriteSpiFunc func); +/** + * @brief 绑定等待函数 + * @param ms 等待时间,单位毫秒 + */ +void CX9261A_setReadSpiFunc(CX9261A_ReadSpiFunc func); +/** + * @brief 绑定SPI读取寄存器函数 + * @param address 要读取的寄存器地址 + * @return 返回的寄存器值 + */ +void CX9261A_setPauseFunc(CX9261A_PauseFunc func); +/** + * @brief 绑定配置FPGA对应寄存器函数 + * @param pin 寄存器地址 + * @param value 寄存器值 + */ +void CX9261A_setSetPinFunc(CX9261A_SetPinFunc func); + +/** + * @brief 初始化芯片状态,写入与具体配置无关的寄存器值 + */ +void CX9261A_initialChip(); +/** + * @brief 初始化电源配置,如果只自定义配置部分模式下的电源管理,在自定义配置之前需要先调用此函数 + */ +void CX9261A_initialPowerConfig(const CX9261A_CX9261AConfiguration *config); +/** + * @brief 初始化BBPLL相关寄存器,如果调用了initialChip,则无需单独调用此函数 + */ +void CX9261A_initialBBPLL(); +/** + * @brief 初始化PLL1相关寄存器,如果调用了initialChip,则无需单独调用此函数 + */ +void CX9261A_initialPLL1(); +/** + * @brief 初始化PLL2相关寄存器,如果调用了initialChip,则无需单独调用此函数 + */ +void CX9261A_initialPLL2(); +/** + * @brief 初始化PLL3相关寄存器,如果调用了initialChip,则无需单独调用此函数 + */ +void CX9261A_initialPLL3(); +/** + * @brief 初始化PLL4相关寄存器,如果调用了initialChip,则无需单独调用此函数 + */ +void CX9261A_initialPLL4(); +/** + * @brief 初始化PLL5相关寄存器,如果调用了initialChip,则无需单独调用此函数 + */ +void CX9261A_initialPLL5(); +/** + * @brief 配置受参考时钟频率影响的寄存器 + * @param ref 参考时钟频率,单位MHz + */ +void CX9261A_configRef(double ref); +/** + * @brief 配置时钟相关寄存器,包括ADC和BBPLL + * @param config CX9261A参数结构体 + */ +void CX9261A_configBBPLL(const CX9261A_CX9261AConfiguration *config); +/** + * @brief BBPLL AFC + * @return 是否锁定 + */ +bool CX9261A_afcBBPll(); +/** + * @brief 配置PLL1频率 + * @param lo 目标频率 + * @param clock 时钟结构体,使用其中的ref和refDoubler属性 + */ +void CX9261A_configPll1(double lo, const CX9261A_Clock *clock); +/** + * @brief Pll1 AFC + * @return 是否锁定 + */ +bool CX9261A_afcPll1(); +/** + * @brief 配置PLL2频率 + * @param lo 目标频率 + * @param clock 时钟结构体,使用其中的ref和refDoubler属性 + */ +void CX9261A_configPll2(double lo, const CX9261A_Clock *clock); +/** + * @brief Pll2 AFC + * @return 是否锁定 + */ +bool CX9261A_afcPll2(); +/** + * @brief 配置PLL3频率 + * @param lo 目标频率 + * @param clock 时钟结构体,使用其中的ref和refDoubler属性 + */ +void CX9261A_configPll3(double lo, const CX9261A_Clock *clock); +/** + * @brief Pll3 AFC + * @return 是否锁定 + */ +bool CX9261A_afcPll3(); +/** + * @brief 配置PLL4频率 + * @param lo 目标频率 + * @param clock 时钟结构体,使用其中的ref和refDoubler属性 + */ +void CX9261A_configPll4(double lo, const CX9261A_Clock *clock); +/** + * @brief Pll4 AFC + * @return 是否锁定 + */ +bool CX9261A_afcPll4(); +/** + * @brief 配置PLL5频率 + * @param lo 目标频率 + * @param clock 时钟结构体,使用其中的ref和refDoubler属性 + */ +void CX9261A_configPll5(double lo, const CX9261A_Clock *clock); +/** + * @brief Pll5 AFC + * @return 是否锁定 + */ +bool CX9261A_afcPll5(); +/** + * @brief 配置AGC模式 + * @param mode 模式0~13 + */ +void CX9261A_configAGCMode(int mode); +/** + * @brief 配置AGC PDT + * @param pdt AGCPDT结构体 + */ +void CX9261A_configAGCPDT(const CX9261A_AGCPDT *pdt); +/** + * @brief 配置AGC LMT + * @param lmt AGCLMT结构体 + */ +void CX9261A_configAGCLMT(const CX9261A_AGCLMT *lmt); +/** + * @brief 配置AGC DIG + * @param dig AGCDIG结构体 + */ +void CX9261A_configAGCDIG(const CX9261A_AGCDIG *dig); +/** + * @brief 配置AGC + * @param agc AGC结构体 + */ +void CX9261A_configAGC(const CX9261A_AGC *agc); +/** + * @brief 配置片内处理器,仅在使用需要处理器辅助的校准方法时需要开启处理器 + * @param on 开启/关闭 + */ +void CX9261A_configRISCV(bool on); +/** + * @brief 配置温补 + * @param mode 温补模式 DAC/Band + */ +void CX9261A_configTemperatureCompensation(CX9261A_TemperatureComp mode); +/** + * @brief ADC校准 + * @param adc ADC速率 + */ +void CX9261A_configADCCalib(double adc); +/** + * @brief Flash校准 + */ +void CX9261A_configFlashCalib(); +/** + * @brief QEC校准会改变部分寄存器配置,在进行校准之前需要保存这部分寄存器,校准后恢复 + * @return 包含寄存器地址和值的map + */ +void CX9261A_beforeQecState(QecStatePair* buff, size_t *len); +/** + * @brief 恢复QEC校准过程中改变的寄存器 + * @param state beforeQecState函数返回的map + */ +void CX9261A_restoreQecState(QecStatePair* buff, size_t len); +/** + * @brief 根据pll来源配置校准模式下的电源管理 + * @param pllSource PllSource结构体 + */ +void CX9261A_preparePowerForRxCalib(const CX9261A_PllSource *pllSource); +/** + * @brief 调整校准时Pll的配置 + * @param config CX9261A配置结构体 + * @param chan 要进行校准的通道 + */ +void CX9261A_preparePllForRxCalib(const CX9261A_CX9261AConfiguration *config, CX9261A_RxChannel chan); +/** + * @brief 等待RxTST窄带校准结束,可重写 + * @return 校准是否结束 + */ +bool CX9261A_waitRxTSTFinished(); +/** + * @brief RX时域统计校准 + * @param chan 校准的RX通道 + */ +void CX9261A_rxTSTCalib(CX9261A_RxChannel chan); +/** + * @brief RX延时线校准 + * @param fs ADC采样率 + * @param chan 校准的RX通道 + */ +void CX9261A_rxDelayCalib(double fs, CX9261A_RxChannel chan); +/** + * @brief DC Tracking + * @param config CX9261A配置结构体 + */ +void CX9261A_configDcCalib(const CX9261A_Calib *config); +void CX9261A_configDcCalibMethod(CX9261A_DCCalibMethod method); +void CX9261A_configDcTrackingLength(int length); +void CX9261A_configDcHighPassFactor(int factor); +/** + * @brief Rx校准 + * @param config CX9261A配置结构体 + * @param chan 要进行校准的通道 + */ +void CX9261A_rxCalib(const CX9261A_CX9261AConfiguration *config, CX9261A_RxChannel chan); +/** + * @brief 选择校准方法 + * @param calib 校准结构体 + */ +void CX9261A_configCalibMethod(const CX9261A_Calib *calib); +/** + * @brief 读取当前Rx chan通道的校准值 + * @param chan Rx通道 + * @return 校准值结构体 + */ +CX9261A_CalibPredis CX9261A_readRxCalibPredis(CX9261A_RxChannel chan); +/** + * @brief 储存校准值 + * @param index 第index组校准值 + * @param chan 接收通道 + * @param pll 使用的PLL + */ +void CX9261A_saveRxCalibPredis(unsigned char index, CX9261A_RxChannel chan, CX9261A_LoSource pll); +/** + * @brief 加载保存的校准值 + * @param index 第index组校准值 + * @param chan 指定加载校准值的通道 + * @param pll 使用的PLL + */ +void CX9261A_loadRxCalibPredis(unsigned char index, CX9261A_RxChannel chan, CX9261A_LoSource pll); +/** + * @brief Rx窄带多点校准 + * @param config CX9261A配置结构体 + * @param points 校准点 + * @param chan 接收通道 + */ +void CX9261A_configRxMultiPointsQec(const CX9261A_CX9261AConfiguration *config, CX9261A_RxChannel chan, const double *points, size_t len); +/** + * @brief 根据pll来源配置校准模式下的电源管理 + * @param pllSource PllSource结构体 + */ +void CX9261A_preparePowerForTxCalib(const CX9261A_PllSource *pllSource); +/** + * @brief 调整校准时Pll的配置 + * @param config CX9261A配置结构体 + */ +void CX9261A_preparePllForTxCalib(const CX9261A_CX9261AConfiguration *config); +/** + * @brief TX二分法QEC校准 + * @param f0 校准音频率 + * @param fs adc频率 + */ +void CX9261A_txBisectionQecCalib(double f0, double fs); +/** + * @brief TX时域统计法校准 + * @param config CX9261A配置结构体 + * @param chan 要校准的通道 + */ +void CX9261A_txTSTCalib(const CX9261A_CX9261AConfiguration *config, CX9261A_TxChannel chan); +/** + * @brief TX二分法DC校准 + * @param f0 校准音频率 + * @param fs adc频率 + */ +void CX9261A_txBisectionDcCalib(double f0, double fs); +/** + * @brief Tx多点校准 + * @param config CX9261A配置结构体 + * @param points 校准点 + */ +void CX9261A_configTxMultiPointsQec(const CX9261A_CX9261AConfiguration *config, const double *points, size_t len); +/** + * @brief Tx通道校准 + * @param config CX9261A配置结构体 + */ +void CX9261A_txCalib(const CX9261A_CX9261AConfiguration *config); +/** + * @brief 储存校准值 + * @param index 第index组校准值 + * @param chan 发射通道 + * @param pll pll + */ +void CX9261A_saveTxCalibPredis(unsigned char index, CX9261A_TxChannel chan, CX9261A_LoSource pll); +/** + * @brief 加载保存的校准值 + * @param index 第index组校准值 + * @param chan 指定加载校准值的通道 + * @param pll 指定加载校准值对应的PLL + */ +void CX9261A_loadTxCalibPredis(unsigned char index, CX9261A_TxChannel chan, CX9261A_LoSource pll); +/** + * @brief Qec校准顶层函数,内部根据配置选择使用对应方法进行校准 + * @param config CX9261A配置结构体 + */ +void CX9261A_configQecCalib(const CX9261A_CX9261AConfiguration *config); +/** + * @brief 配置TX NCO相关寄存器 + * @param nco TX NCO配置结构体 + * @param fs adc速率 + */ +void CX9261A_configTxNco(const CX9261A_TxNCO *nco, double fs); +/** + * @brief 配置TX NCO BIST模式 + * @param bist 开启/关闭BIST + */ +void CX9261A_configTxBIST(bool bist); +/** + * @brief 配置TX NCO频率 + * @param freq 混频频率 + * @param fs adc抽取后速率 + */ +void CX9261A_configTxNcoFreq(double freq, double fs); +/** + * @brief 配置RX NCO相关寄存器 + * @param nco RX NCO配置结构体 + * @param fs adc速率 + */ +void CX9261A_configRxNco(const CX9261A_RxNCO *nco, double fs); +/** + * @brief 配置Rx NCO模式 + * @param mode NCO模式:Bypass/BIST/Up/Down + */ +void CX9261A_configRxNcoMode(CX9261A_NCOMode mode); +/** + * @brief 配置Rx NCO模式 + * @param mode NCO模式:Master/Slaver + */ +void CX9261A_configRxNcoMS(CX9261A_NCOMode mode); +/** + * @brief 配置Rx NCO频率 + * @param freq 混频频率 + * @param fs adc速率 + */ +void CX9261A_configRxNcoFreq(double freq, double fs); +/** + * @brief 配置接口相关寄存器 + * @param interface Interface配置结构体 + */ +void CX9261A_configInterface(const CX9261A_Interface *interface); +/** + * @brief 配置PLL来源 + * @param pllSource PLlSource结构体 + */ +void CX9261A_configPllSource(const CX9261A_PllSource *pllSource); +/** + * @brief 切换电源模式 + * @param pm 电源模式 + */ +void CX9261A_configPowerMode(CX9261A_PowerMode pm); +/** + * @brief 配置电源管理 + * @param power 电源配置结构体 + * @param pm 电源模式 + */ +void CX9261A_configPowerPins(const CX9261A_Power *power, CX9261A_PowerMode pm); +/** + * @brief 配置参考倍频器 + * @param doubler 倍频器开关 + * @param ref 参考时钟频率,单位MHz + */ +void CX9261A_configRefDoubler(bool doubler, double ref); +/** + * @brief 初始化通道,调用initialChip函数会初始化RX1,RX2,RX3三个通道 + * @param chan 通道 RX1/RX2/RX3 + */ +void CX9261A_initialRxChannel(CX9261A_RxChannel chan); +/** + * @brief 配置Rx带宽 + * @note 只改变Rx带宽会导致通道增益改变,建议使用configRxChannel函数进行带宽调整 + * @param bandwidth 带宽,单位(MHz) + * @param chan 通道 Rx1/Rx2/Rx3 + */ +void CX9261A_configRxBandwidth(double bandwidth, CX9261A_RxChannel chan); +/** + * @brief 配置Rx TIA + * @note 只改变TIA会导致通道带宽改变,建议使用configRxChannel函数进行TIA调整 + * @param tia tia档位 + * @param chan 通道 Rx1/Rx2/Rx3 + */ +void CX9261A_configRxTIA(int tia, CX9261A_RxChannel chan); +/** + * @brief 配置Rx Mixer + * @param mixer mixer档位 + */ +void CX9261A_configRxMixer(int mixer); +/** + * @brief 配置Rx通道,包含TIA,Mixer以及Bandwidth + * @param config RxConfig结构体 + * @param chan Rx1/Rx2/Rx3 + */ +void CX9261A_configRxChannel(const CX9261A_RxConfig *config, CX9261A_RxChannel chan); +/** + * @brief 配置Rx FIR滤波器抽取倍数 + * @param fir 抽取倍数 0(Bypass)/1/2/3/4/8 + */ +void CX9261A_configRxFIR(int fir); +/** + * @brief 配置Rx HBF1滤波器抽取倍数 + * @param hbf 抽取倍数 0(Bypass)/2 + */ +void CX9261A_configRxHBF1(int hbf); +/** + * @brief 配置Rx HBF2滤波器抽取倍数 + * @param hbf 抽取倍数 0(Bypass)/2 + */ +void CX9261A_configRxHBF2(int hbf); +/** + * @brief 配置Rx HBF3滤波器抽取倍数 + * @param hbf 抽取倍数 0(Bypass)/2/3 + */ +void CX9261A_configRxHBF3(int hbf); +/** + * @brief 配置Rx CIC滤波器 + * @param cic 抽取倍数 0(Bypass)/20 + */ +void CX9261A_configRxCIC(int cic); +/** + * @brief 配置Rx滤波器 + * @param filters Filters结构体 + */ +void CX9261A_configRxFilters(const CX9261A_Filters *filters); +/** + * @brief 配置Rx FIR滤波器系数 + * @param coe 滤波器系数,长度为16的整倍数,最大128 + */ +void CX9261A_configRxFIRCoe(const double *coe, size_t len); +/** + * @brief 配置Tx带宽 + * @param bandwidth 带宽,单位(MHz) + * @param chan 通道 TX1/TX2 + */ +void CX9261A_configTxBandwidth(double bandwidth, CX9261A_TxChannel chan); +/** + * @brief 配置Tx Mixer + * @param mixer 混频器值 + * @param chan TX1/TX2 + */ +void CX9261A_configTxMixer(int mixer, CX9261A_TxChannel chan); +/** + * @brief 初始化Tx通道 + * @param chan 通道 TX1/TX2 + */ +void CX9261A_initialTxChannel(CX9261A_TxChannel chan); +/** + * @brief 根据Tx通道的本振频率,配置对应的参数 + * @param lo 本振频率,单位(MHz) + * @param chan 通道(Tx1/Tx2) + */ +void CX9261A_configTxChannelFrequency(double lo, CX9261A_TxChannel chan); +/** + * @brief 配置Tx通道,Mixer以及Bandwidth + * @param config TxConfig结构体 + * @param chan Tx1/Tx2 + */ +void CX9261A_configTxChannel(const CX9261A_TxConfig *config, CX9261A_TxChannel chan); +/** + * @brief 配置Tx FIR滤波器插值倍数 + * @param fir 插值倍数 0(Bypass)/1/2/3/4/8 + */ +void CX9261A_configTxFIR(int fir); +/** + * @brief 配置Tx HBF1滤波器插值倍数 + * @param hbf 插值倍数 0(Bypass)/2 + */ +void CX9261A_configTxHBF1(int hbf); +/** + * @brief 配置Tx HBF2滤波器插值倍数 + * @param hbf 插值倍数 0(Bypass)/2 + */ +void CX9261A_configTxHBF2(int hbf); +/** + * @brief 配置Tx HBF3滤波器插值倍数 + * @param hbf 插值倍数 0(Bypass)/2/3 + */ +void CX9261A_configTxHBF3(int hbf); +/** + * @brief 配置Tx CIC滤波器 + * @param cic 插值倍数 0(Bypass)/8/20/32/80 + */ +void CX9261A_configTxCIC(int cic); +/** + * @brief 配置Tx滤波器 + * @param filters Filters结构体 + */ +void CX9261A_configTxFilters(const CX9261A_Filters *filters); +/** + * @brief 配置Tx FIR滤波器系数 + * @param coe 滤波器系数,长度为16的整倍数,最大128 + */ +void CX9261A_configTxFIRCoe(const double *coe, size_t len); +/** + * @brief 读取当前Tx chan通道的校准值 + * @param chan Tx通道 + * @return 校准值结构体 + */ +CX9261A_CalibPredis CX9261A_readTxCalibPredis(CX9261A_TxChannel chan); +/** + * @brief 此函数为Demo板配套配置函数,用于配置FPGA接口,用户开发自己的程序时应重写对应功能 + * @param interface Interface结构体 + */ +void CX9261A_configFPGA(const CX9261A_Interface *interface); + +#ifdef __cplusplus +} +#endif + +#endif // __CX9261ADRIVER_C_H diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/rf-transceiver/cx9261a/lib/.project b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/rf-transceiver/cx9261a/lib/.project new file mode 100644 index 0000000..5b82956 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/rf-transceiver/cx9261a/lib/.project @@ -0,0 +1,26 @@ + + + link_test + Created by SDK v2019.1. standalone_ps7_cortexa9_0 - ps7_cortexa9_0 + + standalone_ps7_cortexa9_0 + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + full,incremental, + + + + + + org.eclipse.cdt.core.cnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + + diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/rf-transceiver/cx9261a/lib/libcx9261a_c.a b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/rf-transceiver/cx9261a/lib/libcx9261a_c.a new file mode 100644 index 0000000..c177de7 Binary files /dev/null and b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/rf-transceiver/cx9261a/lib/libcx9261a_c.a differ diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/rf-transceiver/cx9261a/lib/libcx9261a_c_dbg.a b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/rf-transceiver/cx9261a/lib/libcx9261a_c_dbg.a new file mode 100644 index 0000000..be70caa Binary files /dev/null and b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/drivers/rf-transceiver/cx9261a/lib/libcx9261a_c_dbg.a differ diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/hwconfig.c b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/hwconfig.c new file mode 100644 index 0000000..75588b9 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/hwconfig.c @@ -0,0 +1,927 @@ +/*****************************************************************************/ +/** + * Description: hwconfig.h + * + + * Date: 2024-02-20 13:19 + * Last Edit Time: [2024-02-20 13:19] + * + * Revisions: Rev 0.0 + * History: + * [2023-05-07]: Initial edition. + * + * Copyright(c) 2024 Beijing Institute of Technology. + * + ******************************************************************************/ + +/***************************** Include Files *********************************/ +// Standard +#include +#include +// Xilinx +#include "xgpiops.h" +#include "xilinx_io.h" +#include "drivers/axi_core/spi_engine/spi_engine.h" +// App +#include "common.h" +#include "error.h" +#include "delay.h" +#include "system_monitor.h" +#include "hwconfig.h" +#include "config/app_config.h" +#include "dev_profile/dev_profile.h" + +#ifdef RFSOC +#include "xrfdc.h" +#endif + +/************************** Function Prototypes ******************************/ +/*********************** Driver Instance Definitions **************************/ +static struct hmc7044_dev *hmc7044_inst; +ad9528Device_t *ad9528_inst; +static struct lmk04828_dev *lmk04828_inst; +static struct lmx2594_dev *lmx2594_adc_inst; +static struct lmx2594_dev *lmx2594_dac_inst; +static struct ad9361_reg_dev *ad9361_1_reg_inst; +static struct ad9361_reg_dev *ad9361_2_reg_inst; +static struct cx9261a_dev *cx9261a_inst; +static struct ad9361_rf_phy *ad9361_phy; +static struct ad9653_dev *ad9653_inst; +static struct ad9694_dev *ad9694_inst; + +XGpioPs Gpio; +#ifdef RFSOC +XRFdc RFdc; +#endif + +/*****************************************************************************/ +/** + * @brief Hardware_SwitchFreq + * + * @param devSysMonitor_UpdateHardwareStatus(newHwState); + * @param freq + * + * @return None. + * + ******************************************************************************/ +int32_t Hardware_SwitchFreq(struct ad9361_reg_dev *dev, ad9361TxFreq freq) +{ + int32_t status = 0; + uint8_t value = 0; + int32_t time_out_cnt = 0; + + switch (freq) + { + case TX_FREQ_125: + { + //************************************************************ + // Setup Tx Frequency-Dependent Syntheisizer Registers + //************************************************************ + status = ad9361_reg_write(dev, 0x027A, 0x4A); // Set VCO Output level[3:0] + status = ad9361_reg_write(dev, 0x0279, 0xC1); // Set Init ALC Value[3:0] and VCO Varactor[3:0] + status = ad9361_reg_write(dev, 0x0282, 0x0E); // Set VCO Bias Tcf[1:0] and VCO Bias Ref[2:0] + status = ad9361_reg_write(dev, 0x0278, 0x78); // Set VCO Cal Offset[3:0] + status = ad9361_reg_write(dev, 0x0285, 0x00); // Set VCO Cal Ref Tcf[2:0] + status = ad9361_reg_write(dev, 0x0291, 0x0B); // Set VCO Varactor Reference[3:0] + status = ad9361_reg_write(dev, 0x0290, 0x70); // Set VCO Varactor Ref Tcf[2:0] and VCO Varactor Offset[3:0] + status = ad9361_reg_write(dev, 0x027B, 0x94); // Set Synth Loop Filter charge pump current (Icp) + status = ad9361_reg_write(dev, 0x027E, 0xF4); // Set Synth Loop Filter C2 and C1 + status = ad9361_reg_write(dev, 0x027F, 0xDF); // Set Synth Loop Filter R1 and C3 + status = ad9361_reg_write(dev, 0x0280, 0x0A); // Set Synth Loop Filter R3 + + //************************************************************ + // Write Tx Frequency Words + //************************************************************ + status = ad9361_reg_write(dev, 0x0273, 0x00); // Write Tx Synth Fractional Freq Word[7:0] + status = ad9361_reg_write(dev, 0x0274, 0x00); // Write Tx Synth Fractional Freq Word[15:8] + status = ad9361_reg_write(dev, 0x0275, 0x00); // Write Tx Synth Fractional Freq Word[22:16] + status = ad9361_reg_write(dev, 0x0272, 0x00); // Write Tx Synth Integer Freq Word[10:8] + status = ad9361_reg_write(dev, 0x0271, 0xA0); // Write Tx Synth Integer Freq Word[7:0] (starts VCO cal) + status = ad9361_reg_write(dev, 0x0005, 0x57); // Set LO divider setting + + //************************************************************ + // Tx Quadrature Calibration Settings + //************************************************************ + status = ad9361_reg_write(dev, 0x00A0, 0x75); // Set TxQuadcal NCO frequency + status = ad9361_reg_write(dev, 0x00A3, 0xC0); // Set TxQuadcal NCO frequency (Only update bits [7:6]) + status = ad9361_reg_write(dev, 0x00A1, 0x7B); // Tx Quad Cal Configuration, Phase and Gain Cal Enable + status = ad9361_reg_write(dev, 0x00A9, 0xFF); // Set Tx Quad Cal Count + status = ad9361_reg_write(dev, 0x00A2, 0x7F); // Set Tx Quad Cal Kexp + status = ad9361_reg_write(dev, 0x00A5, 0x01); // Set Tx Quad Cal Magnitude Threshhold + status = ad9361_reg_write(dev, 0x00A6, 0x01); // Set Tx Quad Cal Magnitude Threshhold + status = ad9361_reg_write(dev, 0x00AA, 0x22); // Set Tx Quad Cal Gain Table index + status = ad9361_reg_write(dev, 0x00A4, 0xF0); // Set Tx Quad Cal Settle Count + status = ad9361_reg_write(dev, 0x00AE, 0x00); // Set Tx Quad Cal LPF Gain index incase Split table mode used + + status = ad9361_reg_write(dev, 0x0169, 0xC0); // Disable Rx Quadrature Calibration before Running Tx Quadrature Calibration + status = ad9361_reg_write(dev, 0x0016, 0x10); // Start Tx Quad cal + + break; + } + case TX_FREQ_126: + { + //************************************************************ + // Setup Tx Frequency-Dependent Syntheisizer Registers + //************************************************************ + status = ad9361_reg_write(dev, 0x027A, 0x4A); // Set VCO Output level[3:0] + status = ad9361_reg_write(dev, 0x0279, 0xC1); // Set Init ALC Value[3:0] and VCO Varactor[3:0] + status = ad9361_reg_write(dev, 0x0282, 0x0E); // Set VCO Bias Tcf[1:0] and VCO Bias Ref[2:0] + status = ad9361_reg_write(dev, 0x0278, 0x78); // Set VCO Cal Offset[3:0] + status = ad9361_reg_write(dev, 0x0285, 0x00); // Set VCO Cal Ref Tcf[2:0] + status = ad9361_reg_write(dev, 0x0291, 0x0B); // Set VCO Varactor Reference[3:0] + status = ad9361_reg_write(dev, 0x0290, 0x70); // Set VCO Varactor Ref Tcf[2:0] and VCO Varactor Offset[3:0] + status = ad9361_reg_write(dev, 0x027B, 0x93); // Set Synth Loop Filter charge pump current (Icp) + status = ad9361_reg_write(dev, 0x027E, 0xF4); // Set Synth Loop Filter C2 and C1 + status = ad9361_reg_write(dev, 0x027F, 0xDF); // Set Synth Loop Filter R1 and C3 + status = ad9361_reg_write(dev, 0x0280, 0x0A); // Set Synth Loop Filter R3 + + //************************************************************ + // Write Tx Frequency Words + //************************************************************ + status = ad9361_reg_write(dev, 0x0273, 0x06); // Write Tx Synth Fractional Freq Word[7:0] + status = ad9361_reg_write(dev, 0x0274, 0xD7); // Write Tx Synth Fractional Freq Word[15:8] + status = ad9361_reg_write(dev, 0x0275, 0x23); // Write Tx Synth Fractional Freq Word[22:16] + status = ad9361_reg_write(dev, 0x0272, 0x00); // Write Tx Synth Integer Freq Word[10:8] + status = ad9361_reg_write(dev, 0x0271, 0xA1); // Write Tx Synth Integer Freq Word[7:0] (starts VCO cal) + status = ad9361_reg_write(dev, 0x0005, 0x57); // Set LO divider setting + + //************************************************************ + // Tx Quadrature Calibration Settings + //************************************************************ + status = ad9361_reg_write(dev, 0x00A0, 0x75); // Set TxQuadcal NCO frequency + status = ad9361_reg_write(dev, 0x00A3, 0xC0); // Set TxQuadcal NCO frequency (Only update bits [7:6]) + status = ad9361_reg_write(dev, 0x00A1, 0x7B); // Tx Quad Cal Configuration, Phase and Gain Cal Enable + status = ad9361_reg_write(dev, 0x00A9, 0xFF); // Set Tx Quad Cal Count + status = ad9361_reg_write(dev, 0x00A2, 0x7F); // Set Tx Quad Cal Kexp + status = ad9361_reg_write(dev, 0x00A5, 0x01); // Set Tx Quad Cal Magnitude Threshhold + status = ad9361_reg_write(dev, 0x00A6, 0x01); // Set Tx Quad Cal Magnitude Threshhold + status = ad9361_reg_write(dev, 0x00AA, 0x22); // Set Tx Quad Cal Gain Table index + status = ad9361_reg_write(dev, 0x00A4, 0xF0); // Set Tx Quad Cal Settle Count + status = ad9361_reg_write(dev, 0x00AE, 0x00); // Set Tx Quad Cal LPF Gain index incase Split table mode used + + status = ad9361_reg_write(dev, 0x0169, 0xC0); // Disable Rx Quadrature Calibration before Running Tx Quadrature Calibration + status = ad9361_reg_write(dev, 0x0016, 0x10); // Start Tx Quad cal + + break; + } + case TX_FREQ_4125: + { + //************************************************************ + // Setup Tx Frequency-Dependent Syntheisizer Registers + //************************************************************ + status = ad9361_reg_write(dev, 0x027A, 0x4A); // Set VCO Output level[3:0] + status = ad9361_reg_write(dev, 0x0279, 0xC1); // Set Init ALC Value[3:0] and VCO Varactor[3:0] + status = ad9361_reg_write(dev, 0x0282, 0x0E); // Set VCO Bias Tcf[1:0] and VCO Bias Ref[2:0] + status = ad9361_reg_write(dev, 0x0278, 0x78); // Set VCO Cal Offset[3:0] + status = ad9361_reg_write(dev, 0x0285, 0x00); // Set VCO Cal Ref Tcf[2:0] + status = ad9361_reg_write(dev, 0x0291, 0x0B); // Set VCO Varactor Reference[3:0] + status = ad9361_reg_write(dev, 0x0290, 0x70); // Set VCO Varactor Ref Tcf[2:0] and VCO Varactor Offset[3:0] + status = ad9361_reg_write(dev, 0x027B, 0x93); // Set Synth Loop Filter charge pump current (Icp) + status = ad9361_reg_write(dev, 0x027E, 0xF4); // Set Synth Loop Filter C2 and C1 + status = ad9361_reg_write(dev, 0x027F, 0xDF); // Set Synth Loop Filter R1 and C3 + status = ad9361_reg_write(dev, 0x0280, 0x0A); // Set Synth Loop Filter R3 + + //************************************************************ + // Write Rx Frequency Words + //************************************************************ + status = ad9361_reg_write(dev, 0x0273, 0x00); // Write Tx Synth Fractional Freq Word[7:0] + status = ad9361_reg_write(dev, 0x0274, 0x00); // Write Tx Synth Fractional Freq Word[15:8] + status = ad9361_reg_write(dev, 0x0275, 0x00); // Write Tx Synth Fractional Freq Word[22:16] + status = ad9361_reg_write(dev, 0x0272, 0x00); // Write Tx Synth Integer Freq Word[10:8] + status = ad9361_reg_write(dev, 0x0271, 0xA5); // Write Tx Synth Integer Freq Word[7:0] (starts VCO cal) + status = ad9361_reg_write(dev, 0x0005, 0x07); // Set LO divider setting + + //************************************************************ + // Tx Quadrature Calibration Settings + //************************************************************ + status = ad9361_reg_write(dev, 0x00A0, 0x75); // Set TxQuadcal NCO frequency + status = ad9361_reg_write(dev, 0x00A3, 0xC0); // Set TxQuadcal NCO frequency (Only update bits [7:6]) + status = ad9361_reg_write(dev, 0x00A1, 0x7B); // Tx Quad Cal Configuration, Phase and Gain Cal Enable + status = ad9361_reg_write(dev, 0x00A9, 0xFF); // Set Tx Quad Cal Count + status = ad9361_reg_write(dev, 0x00A2, 0x7F); // Set Tx Quad Cal Kexp + status = ad9361_reg_write(dev, 0x00A5, 0x01); // Set Tx Quad Cal Magnitude Threshhold + status = ad9361_reg_write(dev, 0x00A6, 0x01); // Set Tx Quad Cal Magnitude Threshhold + status = ad9361_reg_write(dev, 0x00AA, 0x28); // Set Tx Quad Cal Gain Table index + status = ad9361_reg_write(dev, 0x00A4, 0xF0); // Set Tx Quad Cal Settle Count + status = ad9361_reg_write(dev, 0x00AE, 0x04); // Set Tx Quad Cal LPF Gain index incase Split table mode used + + status = ad9361_reg_write(dev, 0x0169, 0xC0); // Disable Rx Quadrature Calibration before Running Tx Quadrature Calibration + status = ad9361_reg_write(dev, 0x0016, 0x10); // Start Tx Quad cal + + break; + } + + // Wait for cal to complete (Done when 0x016[4]==0) + time_out_cnt = 0; + do + { + status |= ad9361_reg_read(dev, 0x0016, &value); + mdelay(1); // Wait 1ms + time_out_cnt++; + } while ((value & 0x10) != 0x00 && time_out_cnt <= AD9361_TIMEOUT_TH); + } + + return status; +} + +// @ Get AD9361 - 1 temperature (Celsius Degree) +/** + * Read corresponding register to get AD9361 - 1 current temperature. + */ +int8_t Hardware_GetAD9361Temp_1(void) +{ + int8_t scaleTemp; + double temp; + + ad9361_reg_write(ad9361_1_reg_inst, 0x000B, -64); + ad9361_reg_write(ad9361_1_reg_inst, 0x001D, 0x01); // disable aux adc + ad9361_reg_read(ad9361_1_reg_inst, 0x000E, (uint8_t*)&scaleTemp); + ad9361_reg_write(ad9361_1_reg_inst, 0x001D, 0x00); // enable aux adc + + temp = ((double)scaleTemp + 64)/1.16; + return ((temp > INT8_MAX) ? INT8_MAX : (int8_t)temp); +} + +// @ Get AD9361 - 2 temperature (Celsius Degree) +/** + * Read corresponding register to get AD9361 - 2 current temperature. + */ +int8_t Hardware_GetAD9361Temp_2(void) +{ + int8_t scaleTemp; + double temp; + + ad9361_reg_write(ad9361_2_reg_inst, 0x000B, -64); + ad9361_reg_write(ad9361_2_reg_inst, 0x001D, 0x01); // disable aux adc + ad9361_reg_read(ad9361_2_reg_inst, 0x000E, (uint8_t*)&scaleTemp); + ad9361_reg_write(ad9361_2_reg_inst, 0x001D, 0x00); // enable aux adc + temp = ((double)scaleTemp + 64)/1.16; + return ((temp > INT8_MAX) ? INT8_MAX : (int8_t)temp); +} + +// @ Determine AD9361 lock state +/** + * Read corresponding register to determine AD9361(both) lock state. + */ +uint8_t Hardware_GetAD9361LockStatus(void) +{ + uint8_t ret = 0; + uint8_t regVal; + + // bbpll + ad9361_reg_read(ad9361_1_reg_inst, 0x005E, ®Val); // [D7] is lock indicator + ret |= ((regVal & 0x80) == 0x80) ? CLK_AD0_BBPLL_LOCK : 0; + ad9361_reg_read(ad9361_2_reg_inst, 0x005E, ®Val); // [D7] is lock indicator + ret |= ((regVal & 0x80) == 0x80) ? CLK_AD1_BBPLL_LOCK : 0; + + // rfpll + ad9361_reg_read(ad9361_1_reg_inst, 0x0287, ®Val); // [D1] is lock indicator + ret |= ((regVal & 0x02) == 0x02) ? CLK_AD0_RFPLL_LOCK : 0; + ad9361_reg_read(ad9361_2_reg_inst, 0x0287, ®Val); // [D1] is lock indicator + ret |= ((regVal & 0x02) == 0x02) ? CLK_AD1_RFPLL_LOCK : 0; + + return ret; +} + +// @ Determine HMC7044 lock state +/** + * Read corresponding register to determine clock lock state. + */ +uint8_t Hardware_GetHMC7044LockStatus(void) +{ + uint8_t ret = 0; + uint8_t regVal; + + // pll1 + hmc7044_read(hmc7044_inst, 0x007C, ®Val); // [D5] is lock indicator + ret |= ((regVal & 0xE0) != 0x00) ? CLK_SP_PLL0_LOCK : 0; + + // pll2 + hmc7044_read(hmc7044_inst, 0x007D, ®Val); // [D0] is lock indicator + ret |= ((regVal & 0x01) == 0x01) ? CLK_SP_PLL1_LOCK : 0; + + return ret; +} + +void CX9261A_Log(const char *msg) +{ + DBG_INFO("[CX9261A] %s\n", msg); +} +//void CX9261A_spiWrite(int address, int value) +//{ +// int32_t Status; +// +// Status = cx9261a_write(cx9261a_inst,address,value); +// if (Status != SUCCESS) +// { +// DBG_ERROR("HW: CX9261A_spiWrite() failed!"); +// } +// +//} +//int CX9261A_spiRead(int address) +//{ +// int32_t Status; +// uint8_t reg = 0; +// +// Status = cx9261a_read(cx9261a_inst,address,®); +// if (Status != SUCCESS) +// { +// DBG_ERROR("HW: CX9261A_spiRead() failed!"); +// } +// +// return reg; +//} +//void CX9261A_mdelay(double ms) +//{ +// mdelay((uint32_t)(ms)); +//} +//void CX9261A_setPin(int pin, int value) +//{ +// switch(pin){ +// case 0: +// gpio_set_value(cx9261a_inst->gpio_desc_nrst, value); +// break; +// case 1: +// gpio_set_value(cx9261a_inst->gpio_desc_enable_trx1, value); +// break; +// case 2: +// gpio_set_value(cx9261a_inst->gpio_desc_enable_trx2, value); +// break; +// case 3: +// gpio_set_value(cx9261a_inst->gpio_desc_enable_rxfb, value); +// break; +// case 4: +// gpio_set_value(cx9261a_inst->gpio_desc_txnrx_trx1, value); +// break; +// case 5: +// gpio_set_value(cx9261a_inst->gpio_desc_txnrx_trx2, value); +// break; +// case 6: +// gpio_set_value(cx9261a_inst->gpio_desc_txnrx_rxfb, value); +// break; +// case 34: +// gpio_set_value(cx9261a_inst->gpio_desc_pl_rst, value); +// break; +// case 35: +// gpio_set_value(cx9261a_inst->gpio_desc_tr_sel, value); +// break; +// case 36: +// gpio_set_value(cx9261a_inst->gpio_desc_tdd_fdd_sel, value); +// break; +// case 37: +// gpio_set_value(cx9261a_inst->gpio_desc_r1t1_r2t2_sel, value); +// break; +// case 38: +// gpio_set_value(cx9261a_inst->gpio_desc_sp_dp_sel, value); +// break; +// case 43: +// gpio_set_value(cx9261a_inst->gpio_desc_mclk_delay_ctrl0, value); +// break; +// case 44: +// gpio_set_value(cx9261a_inst->gpio_desc_mclk_delay_ctrl1, value); +// break; +// case 45: +// gpio_set_value(cx9261a_inst->gpio_desc_mclk_delay_ctrl2, value); +// break; +// default: +// break; +// } +// +// return; +//} + +void CX9261A_spiWrite(const int address, const int value) { + u8 rx_data1; + SpiPs_write_read1(address,value,(u8 *)&rx_data1); +} + +int CX9261A_spiRead(const int address) { + u8 rx_data1; + SpiPs_write_read2(address,0,(u8 *)&rx_data1); +return rx_data1; + +} + +void CX9261A_mdelay(const double ms) { + mdelay((uint32_t)(ms)); +} + +void CX9261A_setPin(const int pin, const int value) { + GpioSetPinDir(pin,GPIO_DIR_OUTPUT); + GpioWritePin(pin,value); +} + + +void cx9261a_trx_ch_pll_config(u8 pll_index) +{ + u8 rx_data; + u8 recv_buf[3]={0}; + u32 trx_ch_pll_data; + + if(pll_index==1){ + trx_ch_pll_data = 0x00077DCF; + }else if(pll_index==2){ + trx_ch_pll_data = 0x00077D0C; + } + + cx9261a_write(cx9261a_inst,trx_ch_pll_data >> 8, trx_ch_pll_data); +} + +/*****************************************************************************/ +/** + * @brief Hardware_Init + * + * @param none. + * + * @return None. + * + ******************************************************************************/ +int32_t Hardware_Init(void) +{ + int32_t Status; + + // gpio initialization + XGpioPs_Config *ConfigPtr; + ConfigPtr = XGpioPs_LookupConfig(AD9361_GPIO_DEVICE_ID); + Status = XGpioPs_CfgInitialize(&Gpio, ConfigPtr, ConfigPtr->BaseAddr); + if (Status != SUCCESS) + { + return FAILURE; + } + + SpiPsInit(SPI_DEVICE_ID); + GpioInit(GPIO_DEVICE_ID); + +#ifdef RFSOC + /**********************************************************/ + /************* RF Data Converter Configuration ************/ + /**********************************************************/ + // rf data converter initialization + XRFdc_Config *RFdc_ConfigPtr; + RFdc_ConfigPtr = XRFdc_LookupConfig(RFDC_DEVICE_ID); + Status = XRFdc_CfgInitialize(&RFdc, RFdc_ConfigPtr); + if (Status != XST_SUCCESS) + { + return XST_FAILURE; + } +#endif + +#ifdef HMC7044 + /**********************************************************/ + /****************** HMC7044 Configuration *****************/ + /**********************************************************/ + Status = hmc7044_init(&hmc7044_inst, &hmc7044_default_init_param); + if (Status != SUCCESS) + { + DBG_ERROR("HDWR: hmc7044_init() error: %" PRId32 "\n", Status); + return FAILURE; + } +#endif + +#ifdef AD9528 + /**********************************************************/ + /****************** AD9528 Configuration ******************/ + /**********************************************************/ + Status = AD9528_init(&ad9528_inst, &ad9528_default_init_param); + if (Status != SUCCESS) { + DBG_ERROR("HDWR: AD9528_init() error: %" PRId32 "\n", Status); + return FAILURE; + } + + Status = AD9528_config(ad9528_inst); + if (Status != SUCCESS) { + return FAILURE; + DBG_ERROR("HDWR: AD9528_config() error: %" PRId32 "\n", Status); + } +#endif + +#ifdef LMK04828 + /**********************************************************/ + /***************** LMK04828 Configuration *****************/ + /**********************************************************/ + Status = lmk04828_init(&lmk04828_inst, &lmk04828_default_init_param); + for(int i = 0; i < lmk04828_default_config_len; i++) + { + Status = lmk04828_write(lmk04828_inst, + lmk04828_default_config[i].addr, lmk04828_default_config[i].value); + if (lmk04828_default_config[i].addr == 0x0000) + { + mdelay(500); + } + } + + uint8_t Lmk04828Read; + + // check pll1 lock status + Status = lmk04828_read(lmk04828_inst, 0x0182, &Lmk04828Read); + if ((Lmk04828Read & 0x02) == 0x02) { + DBG_INFO("HDWR: [LMK04828] PLL1 Locked.\r\n"); + } + else { + DBG_ERROR("HDWR: [LMK04828] PLL1 NOT lock. It takes a while " + "for PLL1 to lock. Lock status is shown on LED.\r\n"); + } + + // check pll2 lock status + Status = lmk04828_read(lmk04828_inst, 0x0183, &Lmk04828Read); + if ((Lmk04828Read & 0x02) == 0x02) { + DBG_INFO("HDWR: [LMK04828] PLL2 Locked.\r\n"); + } + else { + DBG_INFO("HDWR: [LMK04828] PLL2 NOT lock!\r\n"); + } +#endif + +#ifdef LMX2594_ADC + /**********************************************************/ + /************* LMX2594 for ADC Configuration **************/ + /**********************************************************/ + Status = lmx2594_init(&lmx2594_adc_inst, &lmx2594_adc_init_param); + for(int i = 0; i < lmx2594_default_config_len; i++) + { + Status = lmx2594_write(lmx2594_adc_inst, + lmx2594_default_config[i].addr, lmx2594_default_config[i].value); + if (lmx2594_default_config[i].addr == 0) + { + mdelay(500); + } + } + + uint16_t Lmx2594AdcRead; + + // check vco lock status + Status = lmx2594_read(lmx2594_adc_inst, 110, &Lmx2594AdcRead); + if (((Lmx2594AdcRead >> 9) & 0x0003) == 0x0002) { + DBG_INFO("HDWR: [ADC LMX2594] Config Done.\r\n"); + } + else { + DBG_INFO("HDWR: [ADC LMX2594] not lock!\r\n"); + } + + // set mux out to lock status + Status = lmx2594_write(lmx2594_adc_inst, 0x00, 0x259C); + DBG_INFO("HDWR: [ADC LMX2594] SPI readback disabled, " + "lock status is shown on LED.\r\n"); +#endif + +#ifdef LMX2594_DAC + /**********************************************************/ + /************* LMX2594 for DAC Configuration **************/ + /**********************************************************/ + Status = lmx2594_init(&lmx2594_dac_inst, &lmx2594_dac_init_param); + for(int i = 0; i < lmx2594_default_config_len; i++) + { + Status = lmx2594_write(lmx2594_dac_inst, + lmx2594_default_config[i].addr, lmx2594_default_config[i].value); + if (lmx2594_default_config[i].addr == 0) + { + mdelay(500); + } + } + + uint16_t Lmx2594DacRead; + + // check vco lock status + Status = lmx2594_read(lmx2594_dac_inst, 110, &Lmx2594DacRead); + if (((Lmx2594DacRead >> 9) & 0x0003) == 0x0002) { + DBG_INFO("HDWR: [DAC LMX2594] Config Done.\r\n"); + } + else { + DBG_INFO("HDWR: [DAC LMX2594] not lock!\r\n"); + } + + // set mux out to lock status + Status = lmx2594_write(lmx2594_dac_inst, 0x00, 0x259C); + DBG_INFO("HDWR: [DAC LMX2594] SPI readback disabled, " + "lock status is shown on LED.\r\n"); +#endif + +#if defined(AD9361_API) || defined(AD9361_REG) + /**********************************************************/ + /***************** AD9361-1 Configuration *****************/ + /**********************************************************/ + XGpioPs_SetDirectionPin(&Gpio, AD9361_1_TXNRX, AD9361_GPIO_OUTPUT); + XGpioPs_SetDirectionPin(&Gpio, AD9361_1_ENABLE, AD9361_GPIO_OUTPUT); + XGpioPs_SetDirectionPin(&Gpio, AD9361_1_EN_AGC, AD9361_GPIO_OUTPUT); + XGpioPs_SetDirectionPin(&Gpio, AD9361_1_RESET_B, AD9361_GPIO_OUTPUT); + +#ifdef AD9361_REG + ad9361_reg_init(&ad9361_1_reg_inst, &ad9361_1_reg_default_init_param); + XGpioPs_WritePin(&Gpio, AD9361_1_ENABLE, 0); + ad9361_reg_config(ad9361_1_reg_inst); + XGpioPs_WritePin(&Gpio, AD9361_1_ENABLE, 1); +#endif +#ifdef AD9361_API + Status = ad9361_init(&ad9361_phy, &ad9361_default_init_param); + if (Status != XST_SUCCESS){ + DBG_ERROR("HDWR: ad9361_init() error: %" PRId32 "\n", Status); + return XST_FAILURE; + } + ad9361_set_tx_fir_config(ad9361_phy, tx_fir_config); + ad9361_set_rx_fir_config(ad9361_phy, rx_fir_config); +#endif + /**********************************************************/ + /***************** AD9361-2 Configuration *****************/ + /**********************************************************/ + XGpioPs_SetDirectionPin(&Gpio, AD9361_2_TXNRX, AD9361_GPIO_OUTPUT); + XGpioPs_SetDirectionPin(&Gpio, AD9361_2_ENABLE, AD9361_GPIO_OUTPUT); + XGpioPs_SetDirectionPin(&Gpio, AD9361_2_EN_AGC, AD9361_GPIO_OUTPUT); + XGpioPs_SetDirectionPin(&Gpio, AD9361_2_RESET_B, AD9361_GPIO_OUTPUT); + + ad9361_reg_init(&ad9361_2_reg_inst, &ad9361_2_reg_default_init_param); + XGpioPs_WritePin(&Gpio, AD9361_2_ENABLE, 0); + ad9361_reg_config(ad9361_2_reg_inst); + XGpioPs_WritePin(&Gpio, AD9361_2_ENABLE, 1); + + // uint8_t rd_back; + // Status = ad9361_reg_read(ad9361_1_reg_inst, 0x0002, &rd_back); + // Status = ad9361_reg_read(ad9361_2_reg_inst, 0x0002, &rd_back); + + /**********************************************************/ + /******* AD9361 Baseband Multichip Synchronization ********/ + /**********************************************************/ + XGpioPs_SetDirectionPin(&Gpio, AD9361_SYNC, AD9361_GPIO_OUTPUT); + XGpioPs_SetDirectionPin(&Gpio, AD9361_RX_FIFO_RST, AD9361_GPIO_OUTPUT); + + // SYNC BBPLL and DIGITAL SAMPLING CLOCKS + ad9361_reg_write(ad9361_1_reg_inst, 0x0001, 0x0D); // MCS RF Enable; MCS BBPLL Enable; MCS BB Enable + ad9361_reg_write(ad9361_2_reg_inst, 0x0001, 0x0D); + ad9361_reg_write(ad9361_1_reg_inst, 0x0047, 0x80); // MCS refclk Scale Enable + ad9361_reg_write(ad9361_2_reg_inst, 0x0047, 0x80); + XGpioPs_WritePin(&Gpio, AD9361_SYNC, 0); + mdelay(20); + XGpioPs_WritePin(&Gpio, AD9361_SYNC, 1); // Input a rising-edge pulse to the SYNC_IN pin + mdelay(500); + XGpioPs_WritePin(&Gpio, AD9361_SYNC, 0); + mdelay(2000); + ad9361_reg_write(ad9361_1_reg_inst, 0x0001, 0x0B); // MCS RF Enable; MCS Digital CLK Enable ; MCS BB Enable + ad9361_reg_write(ad9361_2_reg_inst, 0x0001, 0x0B); + XGpioPs_WritePin(&Gpio, AD9361_SYNC, 1); // Input another rising-edge pulse to the SYNC_IN pin + mdelay(500); + XGpioPs_WritePin(&Gpio, AD9361_SYNC, 0); + ad9361_reg_write(ad9361_1_reg_inst, 0x0001, 0x08); // clear MCS bits + ad9361_reg_write(ad9361_2_reg_inst, 0x0001, 0x08); + + XGpioPs_WritePin(&Gpio, AD9361_RX_FIFO_RST, 0); + mdelay(20); + XGpioPs_WritePin(&Gpio, AD9361_RX_FIFO_RST, 1); + mdelay(20); + XGpioPs_WritePin(&Gpio, AD9361_RX_FIFO_RST, 0); + + /**********************************************************/ + /********* AD9361 Multichip Rx Phase Calibration **********/ + /**********************************************************/ + XGpioPs_SetDirectionPin(&Gpio, AD9361_TX_SWITCH, AD9361_GPIO_OUTPUT); + XGpioPs_SetDirectionPin(&Gpio, AD9361_1_CAL_START, AD9361_GPIO_OUTPUT); + XGpioPs_SetDirectionPin(&Gpio, AD9361_1_CAL_DONE, AD9361_GPIO_INPUT); + XGpioPs_SetDirectionPin(&Gpio, AD9361_2_CAL_START, AD9361_GPIO_OUTPUT); + XGpioPs_SetDirectionPin(&Gpio, AD9361_2_CAL_DONE, AD9361_GPIO_INPUT); + + // switch to lower frequency + Status = Hardware_SwitchFreq(ad9361_1_reg_inst, TX_FREQ_126); + XGpioPs_WritePin(&Gpio, AD9361_TX_SWITCH, 1); + mdelay(20); + + // switch rx channel + Status = ad9361_reg_write(ad9361_1_reg_inst, 0x0004, 0x30); + Status = ad9361_reg_write(ad9361_2_reg_inst, 0x0004, 0x30); + + // enable dual ad9361 tx channels + Status = ad9361_reg_write(ad9361_1_reg_inst, 0x0002, 0xE4); // Setup Tx Digital Filters/ Channels + + // switch ad9361 tx channel + Status = ad9361_reg_write(ad9361_1_reg_inst, 0x0004, 0x70); // Select Rx input pin(A,B,C)/ Tx out pin (A,B) + mdelay(20); + + // begin to calibrate the 1st ad9361 + XGpioPs_WritePin(&Gpio, AD9361_1_CAL_START, 0); + XGpioPs_WritePin(&Gpio, AD9361_1_CAL_START, 1); + mdelay(1); + XGpioPs_WritePin(&Gpio, AD9361_1_CAL_START, 0); + + // read calibration status + int32_t time_out_cnt = 0; + do + { + mdelay(1); // Wait 1ms + time_out_cnt++; + } while (((XGpioPs_ReadPin(&Gpio, AD9361_1_CAL_DONE) == 0) && time_out_cnt <= AD9361_TIMEOUT_TH)); + + if (time_out_cnt == AD9361_TIMEOUT_TH) + { + return FAILURE; + } + + // begin to calibrate the 2nd ad9361 + XGpioPs_WritePin(&Gpio, AD9361_2_CAL_START, 1); + mdelay(1); + XGpioPs_WritePin(&Gpio, AD9361_2_CAL_START, 0); + + // read calibration status + time_out_cnt = 0; + do + { + mdelay(1); // Wait 1ms + time_out_cnt++; + } while (((XGpioPs_ReadPin(&Gpio, AD9361_2_CAL_DONE) == 0) && time_out_cnt <= AD9361_TIMEOUT_TH)); + + if (time_out_cnt == AD9361_TIMEOUT_TH) + { + return FAILURE; + } + + // enable single ad9361 tx channels + Status = ad9361_reg_write(ad9361_1_reg_inst, 0x0002, 0xA4); // Setup Tx Digital Filters/ Channels + + // switch ad9361 tx & rx channel + Status = ad9361_reg_write(ad9361_1_reg_inst, 0x0004, 0x03); + Status = ad9361_reg_write(ad9361_2_reg_inst, 0x0004, 0x03); + + // switch to higher frequency + Status = Hardware_SwitchFreq(ad9361_1_reg_inst, TX_FREQ_4125); + XGpioPs_WritePin(&Gpio, AD9361_TX_SWITCH, 0); + + Status = ad9361_reg_write(ad9361_1_reg_inst, 0x0109, 0x00); // Rx Gain + Status = ad9361_reg_write(ad9361_1_reg_inst, 0x010C, 0x00); // Rx Gain + Status = ad9361_reg_write(ad9361_2_reg_inst, 0x0109, 0x00); // Rx Gain + Status = ad9361_reg_write(ad9361_2_reg_inst, 0x010C, 0x00); // Rx Gain +#endif + +#ifdef AD9653 + /**********************************************************/ + /****************** AD9653 Configuration ******************/ + /**********************************************************/ + Status = ad9653_init(&ad9653_inst, &ad9653_default_init_param); + for(int i = 0; i < ad9653_default_config_len; i++){ + Status = ad9653_write(ad9653_inst, ad9653_default_config[i].addr, + ad9653_default_config[i].value); + if (ad9653_default_config[i].addr == 0x0000){ + mdelay(500); + } + } +#endif + +#ifdef AD9694 + /**********************************************************/ + /****************** AD9694 Configuration ******************/ + /**********************************************************/ + Status = ad9694_init(&ad9694_inst, &ad9694_default_init_param); + for(int i = 0; i < ad9694_default_config_len; i++){ + Status = ad9694_write(ad9694_inst, ad9694_default_config[i].addr, ad9694_default_config[i].value); + if (ad9694_default_config[i].addr == 0x0000){ + mdelay(500); + } + } + +// uint8_t reg0008; +// uint8_t reg056F; +// uint8_t reg0571; +// +// ad9694_read(ad9694_inst,0x008,®0008); +// ad9694_read(ad9694_inst,0x56F,®056F); +// ad9694_read(ad9694_inst,0x571,®0571); +#endif + +#ifdef CX9261A + /**********************************************************/ + /***************** CX9261A Configuration ******************/ + /**********************************************************/ + cx9261a_init(&cx9261a_inst, &cx9261a_default_init_param); + + // 缂佹垵鐣鹃崙鑺ユ殶 + CX9261A_setLoggingFunc(CX9261A_Log); + CX9261A_setWriteSpiFunc(CX9261A_spiWrite); + CX9261A_setReadSpiFunc(CX9261A_spiRead); + CX9261A_setPauseFunc(CX9261A_mdelay); + CX9261A_setSetPinFunc(CX9261A_setPin); + + // 瀵拷婵鍘ょ純顔垮П閻楋拷 + CX9261A_initialChip(); // 閺堬拷瀵拷婵娓剁憰浣界殶閻€劍顒濋崙鑺ユ殶 + int reg; + reg = CX9261A_spiRead(0x000); + CX9261A_initialPowerConfig(&cx9261a_configuration); + // 闁板秶鐤嗗〒鈺勊� + CX9261A_configTemperatureCompensation(cx9261a_configuration.tempComp); + // 娑撳秹娓剁憰浣藉殰鐎规矮绠熼悽鍨爱缁狅紕鎮婇弮璁圭礉鏉╂瑩鍎撮崚鍡曞敩閻礁褰叉禒銉ф阜閻o拷 + CX9261A_configPowerPins(&(cx9261a_configuration.powerManagement.rxPower), CX9261A_PWM_Receive); + CX9261A_configPowerPins(&(cx9261a_configuration.powerManagement.txPower), CX9261A_PWM_Transmit); + CX9261A_configPowerPins(&(cx9261a_configuration.powerManagement.fddPower), CX9261A_PWM_Duplex); + // 闁板秶鐤唒ll + CX9261A_configBBPLL(&cx9261a_configuration); + CX9261A_configPllSource(&(cx9261a_configuration.pllSource)); + CX9261A_configPll1(cx9261a_configuration.pllFreq.pll1Freq, &(cx9261a_configuration.clock)); + CX9261A_configPll2(cx9261a_configuration.pllFreq.pll2Freq, &(cx9261a_configuration.clock)); + // 闁板秶鐤哛x闁岸浜� + CX9261A_configRxChannel(&(cx9261a_configuration.rx1Config), CX9261A_RXCH_Rx1); + CX9261A_configRxChannel(&(cx9261a_configuration.rx2Config), CX9261A_RXCH_Rx2); + CX9261A_configRxChannel(&(cx9261a_configuration.rx3Config), CX9261A_RXCH_Rx3); + // 闁板秶鐤員x闁岸浜� + CX9261A_configTxChannelFrequency(cx9261a_configuration.pllFreq.pll1Freq, CX9261A_TXCH_Tx1); + CX9261A_configTxChannelFrequency(cx9261a_configuration.pllFreq.pll2Freq, CX9261A_TXCH_Tx2); + CX9261A_configTxChannel(&(cx9261a_configuration.tx1Config), CX9261A_TXCH_Tx1); + CX9261A_configTxChannel(&(cx9261a_configuration.tx2Config), CX9261A_TXCH_Tx2); + // 闁板秶鐤嗗銈嗗皾閸o拷 + CX9261A_configRxFilters(&(cx9261a_configuration.rxFilters)); + CX9261A_configTxFilters(&(cx9261a_configuration.txFilters)); + // 闁板秶鐤哊CO + CX9261A_configRxNco(&(cx9261a_configuration.rxNco), cx9261a_configuration.clock.adc); + int filters = max(cx9261a_configuration.rxFilters.fir, 1) * max(cx9261a_configuration.rxFilters.hbf3, 1) * + max(cx9261a_configuration.rxFilters.hbf2, 1) * + max(cx9261a_configuration.rxFilters.hbf1, 1) * max(cx9261a_configuration.rxFilters.cic, 1); + CX9261A_configTxNco(&(cx9261a_configuration.txNco), cx9261a_configuration.clock.adc / filters); + // 闁板秶鐤咥GC + CX9261A_configAGC(&(cx9261a_configuration.agc)); + // 閸掑洦宕查崚棰佺搐閻姵膩瀵拷 + CX9261A_configPowerMode(CX9261A_PWM_Sleep); + CX9261A_mdelay(1000); + // 閸掑洦宕查崚鐗堢墡閸戝棙膩瀵拷 + CX9261A_configPowerMode(CX9261A_PWM_Calib); + CX9261A_mdelay(100); + // 闁夸礁鐣綛BPLL + while (!CX9261A_afcBBPll()); + // 闁夸礁鐣綪LL1 + while(!CX9261A_afcPll1()); + // 闁夸礁鐣綪LL2 + while(!CX9261A_afcPll2()); + // 闁板秶鐤嗛幒銉ュ經 + CX9261A_configInterface(&(cx9261a_configuration.interface)); + // 闁板秶鐤咶PGA閹恒儱褰涢惄绋垮彠 濮濄倓璐熺粈杞扮伐閿涘奔绮庨柅鍌滄暏娴滃顶emo瀹搞儳鈻奸敍宀�鏁ら幋宄扮安閺嶈宓佺�圭偤妾幆鍛枌鏉╂稖顢戦柊宥囩枂 + CX9261A_configFPGA(&(cx9261a_configuration.interface)); + // 闁板秶鐤嗛弽鈥冲櫙 + CX9261A_configADCCalib(cx9261a_configuration.clock.adc); + CX9261A_configFlashCalib(); + CX9261A_configDcCalib(&(cx9261a_configuration.calib)); +// CX9261A_configQecCalib(&cx9261a_configuration); +// CX9261A_loadRxCalibPredis(0, CX9261A_RXCH_Rx1, CX9261A_LOSRC_Pll1); +// CX9261A_loadRxCalibPredis(0, CX9261A_RXCH_Rx2, CX9261A_LOSRC_Pll1); + // 閸掑洦宕查崚鏉夸紣娴f粍膩瀵拷 + CX9261A_configPowerMode(CX9261A_PWM_Receive); + // 鐠烘娊顣� + + uint8_t hop_flag = 0; + uint8_t hop_flag_new = 0; + double hop_freq; + +// while (true) +// { +// gpio_get_value(cx9261a_inst->gpio_desc_hop_flag, &hop_flag_new); +// if (hop_flag != hop_flag_new) +// { +// hop_flag = hop_flag_new; +// +// double hop_freq; +// double hop_freq1 = 800.25; +// int pll_index=1; +// int unlock_pll1_cnt=0,unlock_pll2_cnt=0; +// +// hop_freq = (rand()%(800-30))+30+(rand()%(101))/(double)100; +// +// if(hop_freq == hop_freq1){ +// if(pll_index == 2){ +// pll_index = 4; +// } +// else if(pll_index == 1){ +// pll_index = 3; +// } +// } +// +// if(hop_flag_new == 1) +// { +// if(pll_index == 1 || pll_index == 3) +// { +// //閸掑洦宕查懛纭僱l2閺夈儲绨� +// cx9261a_trx_ch_pll_config(2); +// //闁板秶鐤唒ll1閸欏倹鏆� +// CX9261A_configPll1(hop_freq,&(cx9261a_configuration.clock)); +// // unlock_pll1_cnt=PLL_config(1,hop_freq,ref)-1; +// while (!CX9261A_afcPll1()) { +// unlock_pll1_cnt++; +// } +// pll_index = 2; +// } +// else if(pll_index == 2 || pll_index == 4) +// { +// //閸掑洦宕查懛纭僱l1閺夈儲绨� +// cx9261a_trx_ch_pll_config(1); +// //闁板秶鐤唒ll2閸欏倹鏆� +// CX9261A_configPll2(hop_freq,&(cx9261a_configuration.clock)); +// // unlock_pll2_cnt=PLL_config(2,hop_freq,ref)-1; +// while (!CX9261A_afcPll2()) { +// unlock_pll2_cnt++; +// } +// pll_index = 1; +// } +// } +// hop_freq1 = hop_freq; +// if(unlock_pll2_cnt!=0 || unlock_pll1_cnt !=0){ +// DBG_ERROR("pll1 unlock num: %d; pll2 unlock num: %d;.\n", unlock_pll1_cnt, unlock_pll2_cnt); +// } +// } +// } +#endif + DBG_INFO("HDWR: configuration Done.\n"); + + return SUCCESS; +} + + diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/hwconfig.h b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/hwconfig.h new file mode 100644 index 0000000..b457b50 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/hwconfig.h @@ -0,0 +1,32 @@ +/*****************************************************************************/ +/** + * Description: hwconfig.h + * + + * Date: 2024-02-20 13:19 + * Last Edit Time: [2024-02-20 13:19] + * + * Revisions: Rev 0.0 + * History: + * [2023-05-07]: Initial edition. + * + * Copyright(c) 2024 Beijing Institute of Technology. + * + ******************************************************************************/ + +/***************************** Include Files *********************************/ +// Standard +#include +#include "config/app_config.h" +#include "drivers/rf-transceiver/ad9361_reg/ad9361_reg.h" +#include "drivers/rf-transceiver/ad9361/ad9361_api.h" + +/************************** Function Prototypes ******************************/ +int32_t Hardware_Init(void); +int32_t Hardware_SwitchFreq(struct ad9361_reg_dev *dev, ad9361TxFreq freq); +int8_t Hardware_GetAD9361Temp_1(void); +int8_t Hardware_GetAD9361Temp_2(void); +uint8_t Hardware_GetAD9361LockStatus(void); +uint8_t Hardware_GetHMC7044LockStatus(void); + + diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/include/axi_io.h b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/include/axi_io.h new file mode 100644 index 0000000..f804042 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/include/axi_io.h @@ -0,0 +1,59 @@ +/***************************************************************************//** + * @file axi_io.h + * @brief Header file of AXI IO. + * @author Antoniu Miclaus (antoniu.miclaus@analog.com) +******************************************************************************** + * Copyright 2019(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +#ifndef _AXI_IO_H_ +#define _AXI_IO_H_ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ + +#include + +/******************************************************************************/ +/************************ Functions Declarations ******************************/ +/******************************************************************************/ + +/* AXI IO Read data */ +int32_t axi_io_read(uint32_t base, uint32_t offset, uint32_t *data); + +/* AXI IO Write data */ +int32_t axi_io_write(uint32_t base, uint32_t offset, uint32_t data); + +#endif // _AXI_IO_H_ diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/include/circ_queue.h b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/include/circ_queue.h new file mode 100644 index 0000000..312b125 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/include/circ_queue.h @@ -0,0 +1,100 @@ +/*****************************************************************************/ +/** + * @file circ_queue.h + * @author FanHao (hao_fan_bit_ee@163.com) + * @brief A simple circular FIFO bounded queue + * @version 0.1 + * @date 2023-02-23 + * @note Forked from https://github.com/chrismerck/rpa_queue.git + * @copyright Copyright(c) 2024 Beijing Institute of Technology.\n + * Lab of Communication and Network + * + ******************************************************************************/ + +/** + * @addtogroup Utility + * @{ + */ + +/** + * @defgroup CircularQueue + * @{ + */ + +#ifndef CIRC_QUEUE_H +#define CIRC_QUEUE_H + +#include +#include +#include + +/** + * @struct CIRC_QUEUE + * @brief Circular queue Instance + */ +typedef struct +{ + void **data; + volatile uint32_t nelts; ///< number of elements + uint32_t in; ///< next empty location + uint32_t out; ///< next filled location + uint32_t bounds; ///< max size of queue +} CIRC_QUEUE; + +/** + * @brief create a FIFO queue + * @param queue The new queue + * @param queue_capacity maximum size of the queue + */ +bool CircQueueCreate(CIRC_QUEUE **queue, uint32_t queue_capacity); + +/** + * @brief free queue memory -- call after destroy + */ +void CircQueueFree(CIRC_QUEUE *queue); + +/** + * @brief Detects when the CIRC_QUEUE is full. This utility function is expected + * to be called from within critical sections, and is not threadsafe. + */ +bool isCircQueueFull(CIRC_QUEUE *queue); + +/** + * @brief Detects when the CIRC_QUEUE is empty. This utility function is expected + * to be called from within critical sections, and is not threadsafe. + */ +bool isCircQueueEmpty(CIRC_QUEUE *queue); + +/** + * @brief push/add an object to the queue, blocking if the queue is already full + * + * @param queue the queue + * @param data the data + * @return True on a successful push + * @return False push failed + */ +bool CircQueuePush(CIRC_QUEUE *queue, void *data); + +/** + * @brief pop/get an object from the queue, blocking if the queue is already empty + * + * @param queue the queue + * @param data the data + * @return false pop failed + * @return true on a successful pop + */ +bool CircQueuePop(CIRC_QUEUE *queue, void **data); + +/** + * @brief returns the size of the queue. + * + * @param queue the queue + * @return the size of the queue + */ +uint32_t CircQueueSize(CIRC_QUEUE *queue); + +#endif /* CIRC_QUEUE_H */ + +/** @} CircularQueue*/ + +/** @} Utility*/ \ No newline at end of file diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/include/clist.h b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/include/clist.h new file mode 100644 index 0000000..47e6702 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/include/clist.h @@ -0,0 +1,138 @@ +/*****************************************************************************/ +/** + * @file clist.h + * @author FanHao (hao_fan_bit_ee@163.com) + * @brief A basic list data structure + * @version 0.1 + * @date 2023-02-23 + * @note Forked from https://github.com/clibs/list + * @copyright Copyright(c) 2024 Beijing Institute of Technology.\n + * Lab of Communication and Network + * + ******************************************************************************/ + +/** + * @addtogroup Utility + * @{ + */ + +/** + * @defgroup cList + * @{ + */ + +#ifndef __CLIST_H__ +#define __CLIST_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include +#include + + /** + * @enum clist_direction_t + * @brief clist_t iterator direction. + */ + typedef enum + { + LIST_HEAD, + LIST_TAIL + } clist_direction_t; + + /** + * @struct clist_node_t + * @brief clist_t node struct. + */ + typedef struct clist_node + { + struct clist_node *prev; ///< previous node + struct clist_node *next; ///< next node + void *val; + } clist_node_t; + + /** + * @struct clist_t + * @brief clist_t struct. + */ + typedef struct + { + clist_node_t *head; ///< first node + clist_node_t *tail; ///< last node + uint32_t len; ///< list length + void (*free)(void *val); ///< node free function handle + int8_t (*compare)(void *a, void *b); ///< node compare function handle + } clist_t; + + /** + * @struct clist_iterator_t + * @brief clist_t iterator struct. + */ + typedef struct + { + clist_node_t *next; ///< next element + clist_direction_t direction; ///< iter direction + } clist_iterator_t; + + // Node prototypes. + + clist_node_t * + clist_node_new(void *val); + + // clist_t prototypes. + + clist_t * + clist_new(void); + + clist_node_t * + clist_rpush(clist_t *self, clist_node_t *node); + + clist_node_t * + clist_lpush(clist_t *self, clist_node_t *node); + + clist_node_t * + clist_find(clist_t *self, void *val); + + clist_node_t * + clist_at(clist_t *self, int index); + + clist_node_t * + clist_rpop(clist_t *self); + + clist_node_t * + clist_lpop(clist_t *self); + + void + clist_remove(clist_t *self, clist_node_t *node); + + void + clist_clear(clist_t *self); + + void + clist_destroy(clist_t *self); + + // clist_t iterator prototypes. + + clist_iterator_t * + clist_iterator_new(clist_t *list, clist_direction_t direction); + + clist_iterator_t * + clist_iterator_new_from_node(clist_node_t *node, clist_direction_t direction); + + clist_node_t * + clist_iterator_next(clist_iterator_t *self); + + void + clist_iterator_destroy(clist_iterator_t *self); + +#ifdef __cplusplus +} +#endif + +#endif /* __CLIBS_LIST_H__ */ + +/** @} cList*/ + +/** @} Utility*/ \ No newline at end of file diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/include/common.h b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/include/common.h new file mode 100644 index 0000000..c13de59 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/include/common.h @@ -0,0 +1,93 @@ +/*****************************************************************************/ +/** + * @file common.h + * @author FanHao (hao_fan_bit_ee@163.com) + * @brief Common macros + * @version 0.0 + * @date 2022-07-16 + * @copyright Copyright(c) 2024 Beijing Institute of Technology.\n + * Lab of Communication and Network + * + ******************************************************************************/ +/** + * @defgroup COMMON_MACRO + * @{ + */ + +/***************************** Include Files *********************************/ +#ifndef __COMMON_H_ +#define __COMMON_H_ +#include +#include +#include +#include +#include +#include "util.h" +#include "error.h" + +/************************** Constant Definitions *****************************/ +/***************** Macros (Inline Functions) Definitions *********************/ +#define __PRINT_BLOCK(block) \ + do \ + { \ + block \ + } while (0) + +#define ASSERT(exp) ((exp) ? (void)0 : AppAssert(__FILE__, __LINE__)) +#define _nop_() __asm__("nop") + +/* Stringify */ +#define STR(x) #x + +// #define _DEBUG_LEVEL 3 + +#if _DEBUG_LEVEL > 0 +#define DBG_PRINT(...) printf(__VA_ARGS__) +#endif +#if _DEBUG_LEVEL >= 1 +#define DBG_ERROR(...) __PRINT_BLOCK( \ + printf("in "__FILE__ \ + ":%d [error]\t", \ + __LINE__); \ + printf(__VA_ARGS__);) +#endif +#if _DEBUG_LEVEL >= 2 +#define DBG_WARNING(...) __PRINT_BLOCK( \ + printf("[warning]\t"); \ + printf(__VA_ARGS__);) +#endif +#if _DEBUG_LEVEL >= 3 +#define DBG_INFO(...) __PRINT_BLOCK( \ + printf("[Info]\t"); \ + printf(__VA_ARGS__);) +#endif + +#ifndef DBG_ERROR +#define DBG_ERROR(...) \ + { \ + } +#endif +#ifndef DBG_WARNING +#define DBG_WARNING(...) \ + { \ + } +#endif +#ifndef DBG_INFO +#define DBG_INFO(...) \ + { \ + } +#endif +#ifndef DBG_PRINT +#define DBG_PRINT(...) \ + { \ + } +#endif +/**************************** Type Definitions *******************************/ + +/************************** Variable Definitions *****************************/ + +/************************** Function Prototypes ******************************/ +void AppAssert(const char *file, int line); +#endif /* __COMMON_H_ */ + +/** @} */ \ No newline at end of file diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/include/delay.h b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/include/delay.h new file mode 100644 index 0000000..b6907dc --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/include/delay.h @@ -0,0 +1,70 @@ +/***************************************************************************//** + * @file delay.h + * @brief Header file of Delay functions + * @author DBogdan (dragos.bogdan@analog.com) +******************************************************************************** + * Copyright 2019(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +#ifndef _DELAY_H_ +#define _DELAY_H_ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ + +#include + +/** + * @struct time + * @brief Structure holding time data (seconds, microseconds). + */ +struct time { + unsigned int s, us; +}; + +/******************************************************************************/ +/************************ Functions Declarations ******************************/ +/******************************************************************************/ + +/* Generate microseconds delay. */ +void udelay(uint32_t usecs); + +/* Generate miliseconds delay. */ +void mdelay(uint32_t msecs); + +/* Get current time */ +struct time get_time(void); + +#endif // _DELAY_H_ diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/include/error.h b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/include/error.h new file mode 100644 index 0000000..bbd4b1b --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/include/error.h @@ -0,0 +1,56 @@ +/*****************************************************************************/ +/** + * @file common.h + * @author FanHao (hao_fan_bit_ee@163.com) + * @brief Common error numbers + * @version 0.0 + * @date 2022-06-18 + * @copyright Copyright(c) 2024 Beijing Institute of Technology.\n + * Lab of Communication and Network + * + ******************************************************************************/ + +/** + * @addtogroup COMMON_MACRO + * @{ + */ + +#ifndef SRC_ERROR_H_ +#define SRC_ERROR_H_ + +#include + +/******************************************************************************/ +/********************** Macros and Constants Definitions **********************/ +/******************************************************************************/ + +/** + * @name ERRORNO + * @{ + */ + +#ifdef SUCCESS +#undef SUCCESS +#endif +#define SUCCESS 0 +#ifdef FAILURE +#undef FAILURE +#endif +#define FAILURE -1 + +#define EPARAM -2 /*!< Data crc check failed */ +#define ECRC -3 /*!< Data crc check failed */ +#define EDINVAL -4 /*!< Device is invalid (sleep or power off) */ +#define EDCONF -5 /*!< Device confugure error */ +#define ETIMEOUT -6 /*!< Timeout error */ +#define EIGNORE -7 /*!< Received an unsupported command, and ignore it */ +#define EQUEUE -8 /*!< Queue overflow */ +#define EUNEXP -9 /*!< Encounter an unexpected error */ + +#define IS_ERR_VALUE(x) ((x) != SUCCESS) + +#endif // ERROR_H_ + +/** @} ERRORNO*/ + +/** @} COMMON_MACRO*/ \ No newline at end of file diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/include/global_timer.h b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/include/global_timer.h new file mode 100644 index 0000000..a58f41c --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/include/global_timer.h @@ -0,0 +1,95 @@ +#ifndef SRC_GLOBAL_TIMER_H_ +#define SRC_GLOBAL_TIMER_H_ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ + +#include + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ + +/** + * @struct timer_init_param + * @brief Structure holding the parameters for timer initialization + */ +struct global_timer_init_param { + /** timer ID */ + uintptr_t base_addr; + /** timer ID */ + uint16_t id; + /** timer count frequency (Hz) */ + uint32_t freq_hz; + /** counter start value */ + uint64_t load_value; +}; + +/** + * @struct timer_desc + * @brief Structure holding timer descriptor + */ +struct global_timer_desc { + /** timer ID */ + uintptr_t base_addr; + /** timer ID */ + uint16_t id; + /** timer count frequency (Hz) */ + uint32_t freq_hz; + /** counter start value */ + uint64_t load_value; +}; + +/******************************************************************************/ +/************************ Functions Declarations ******************************/ +/******************************************************************************/ + +/* Initialize hardware timer and the handler structure associated with it. */ +int32_t global_timer_init(struct global_timer_desc **desc, + struct global_timer_init_param *param); + +/* Free the memory allocated by timer_setup(). */ +int32_t global_timer_remove(struct global_timer_desc *desc); + +/* Start a timer. */ +int32_t global_timer_start(struct global_timer_desc *desc); + +/* Stop a timer from counting. */ +int32_t global_timer_stop(struct global_timer_desc *desc); + +/* Get the value of the counter register for the timer. */ +int32_t global_timer_counter_get(struct global_timer_desc *desc, uint64_t *counter); + +/* Set the timer counter register value. */ +int32_t global_timer_counter_set(struct global_timer_desc *desc, uint64_t new_val); + +/* Get the timer clock frequency. */ +int32_t global_timer_count_clk_get(struct global_timer_desc *desc, uint32_t *freq_hz); + +/* Set the timer clock frequency. */ +int32_t global_timer_count_clk_set(struct global_timer_desc *desc, uint32_t freq_hz); + +/* Enable global timer interrupt. */ +int32_t global_timer_irq_enable(struct global_timer_desc *desc); + +/* Disable global timer interrupt. */ +int32_t global_timer_irq_disable(struct global_timer_desc *desc); + +/* Implement a acknowledgment global timer interrupt. */ +int32_t global_timer_irq_ack(struct global_timer_desc *desc); + +/* Set comparator register. */ +int32_t global_timer_compara_set(struct global_timer_desc *desc, uint64_t com_val); + +/* Set auto increment register . */ +int32_t global_timer_auto_inc_set(struct global_timer_desc *desc, uint32_t inc_val); + +/* Enable global timer auto increment mode. */ +int32_t global_timer_auto_inc_enable(struct global_timer_desc *desc); + +/* Disable global timer auto increment mode. */ +int32_t global_timer_auto_inc_disable(struct global_timer_desc *desc); + +#endif /* SRC_TIMER_H_ */ + diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/include/gpio.h b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/include/gpio.h new file mode 100644 index 0000000..5771659 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/include/gpio.h @@ -0,0 +1,188 @@ +/***************************************************************************//** + * @file gpio.h + * @brief Header file of GPIO Interface + * @author DBogdan (dragos.bogdan@analog.com) +******************************************************************************** + * Copyright 2019(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +#ifndef _GPIO_H_ +#define _GPIO_H_ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ + +#include + +/******************************************************************************/ +/********************** Macros and Constants Definitions **********************/ +/******************************************************************************/ + +#define GPIO_OUT 0x01 +#define GPIO_IN 0x00 + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ + +/** + * @struct gpio_platform_ops + * @brief Structure holding gpio function pointers that point to the platform + * specific function + */ +struct gpio_platform_ops ; + +/** + * @enum gpio_pull_up + * @brief Enum that holds the possible pull up/ pull down resistor configuration. + */ +enum gpio_pull_up { + PULL_NONE, + /** Strong pull up */ + PULL_UP, + /** Strong pull down */ + PULL_DOWN, + PULL_UP_WEAK, + PULL_DOWN_WEAK +}; + +/** + * @struct gpio_init_param + * @brief Structure holding the parameters for GPIO initialization. + */ +struct gpio_init_param { + /** Port number */ + int32_t port; + /** GPIO number */ + int32_t number; + /** Pull up/down resistor configuration */ + enum gpio_pull_up pull; + /** GPIO platform specific functions */ + const struct gpio_platform_ops *platform_ops; + /** GPIO extra parameters (device specific) */ + void *extra; +}; + +/** + * @struct gpio_desc + * @brief Structure holding the GPIO descriptor. + */ +struct gpio_desc { + /** Port number */ + int32_t port; + /** GPIO number */ + int32_t number; + /** Pull up/down resistor configuration */ + enum gpio_pull_up pull; + /** GPIO platform specific functions */ + const struct gpio_platform_ops *platform_ops; + /** GPIO extra parameters (device specific) */ + void *extra; +}; + +/** + * @enum gpio_values + * @brief Enum that holds the possible output states of a GPIO. + */ +enum gpio_values { + /** GPIO logic low */ + GPIO_LOW, + /** GPIO logic high */ + GPIO_HIGH, + /** GPIO high impedance */ + GPIO_HIGH_Z +}; + +/** + * @struct gpio_platform_ops + * @brief Structure holding gpio function pointers that point to the platform + * specific function + */ +struct gpio_platform_ops { + /** gpio initialization function pointer */ + int32_t (*gpio_ops_get)(struct gpio_desc **, + const struct gpio_init_param *); + /** gpio optional descriptor function pointer */ + int32_t (*gpio_ops_get_optional)(struct gpio_desc **, + const struct gpio_init_param *); + /** gpio remove function pointer */ + int32_t (*gpio_ops_remove)(struct gpio_desc *); + /** gpio direction input function pointer */ + int32_t (*gpio_ops_direction_input)(struct gpio_desc *); + /** gpio direction output function pointer */ + int32_t (*gpio_ops_direction_output)(struct gpio_desc *, uint8_t); + /** gpio get direction function pointer */ + int32_t (*gpio_ops_get_direction)(struct gpio_desc *, uint8_t *); + /** gpio set value function pointer */ + int32_t (*gpio_ops_set_value)(struct gpio_desc *, uint8_t); + /** gpio get value function pointer */ + int32_t (*gpio_ops_get_value)(struct gpio_desc *, uint8_t *); +}; + +/******************************************************************************/ +/************************ Functions Declarations ******************************/ +/******************************************************************************/ + +/* Obtain the GPIO decriptor. */ +int32_t gpio_get(struct gpio_desc **desc, + const struct gpio_init_param *param); + +/* Obtain optional GPIO descriptor. */ +int32_t gpio_get_optional(struct gpio_desc **desc, + const struct gpio_init_param *param); + +/* Free the resources allocated by gpio_get(). */ +int32_t gpio_remove(struct gpio_desc *desc); + +/* Enable the input direction of the specified GPIO. */ +int32_t gpio_direction_input(struct gpio_desc *desc); + +/* Enable the output direction of the specified GPIO. */ +int32_t gpio_direction_output(struct gpio_desc *desc, + uint8_t value); + +/* Get the direction of the specified GPIO. */ +int32_t gpio_get_direction(struct gpio_desc *desc, + uint8_t *direction); + +/* Set the value of the specified GPIO. */ +int32_t gpio_set_value(struct gpio_desc *desc, + uint8_t value); + +/* Get the value of the specified GPIO. */ +int32_t gpio_get_value(struct gpio_desc *desc, + uint8_t *value); + +#endif // _GPIO_H_ diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/include/i2c.h b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/include/i2c.h new file mode 100644 index 0000000..e3ca53e --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/include/i2c.h @@ -0,0 +1,134 @@ +/***************************************************************************//** + * @file i2c.h + * @brief Header file of I2C Interface + * @author DBogdan (dragos.bogdan@analog.com) +******************************************************************************** + * Copyright 2019(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +#ifndef _I2C_H_ +#define _I2C_H_ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ + +#include + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ + +/** + * @struct i2c_platform_ops + * @brief Structure holding I2C function pointers that point to the platform + * specific function + */ +struct i2c_platform_ops ; + +/** + * @struct i2c_init_param + * @brief Structure holding the parameters for I2C initialization. + */ +struct i2c_init_param { + /** Device ID */ + uint32_t device_id; + /** I2C maximum transfer speed supported */ + uint32_t max_speed_hz; + /** Slave address */ + uint8_t slave_address; + /** I2C platform specific functions */ + const struct i2c_platform_ops *platform_ops; + /** I2C extra parameters (device specific parameters) */ + void *extra; +}; + +/** + * @struct i2c_desc + * @brief Structure holding I2C descriptor + */ +struct i2c_desc { + /** Device ID */ + uint32_t device_id; + /** I2C maximum transfer speed supported */ + uint32_t max_speed_hz; + /** Slave address */ + uint8_t slave_address; + /** I2C platform specific functions */ + const struct i2c_platform_ops *platform_ops; + /** I2C extra parameters (device specific parameters) */ + void *extra; +}; + +/** + * @struct i2c_platform_ops + * @brief Structure holding i2c function pointers that point to the platform + * specific function + */ +struct i2c_platform_ops { + /** i2c initialization function pointer */ + int32_t (*i2c_ops_init)(struct i2c_desc **, + const struct i2c_init_param *); + /** i2c write function pointer */ + int32_t (*i2c_ops_write)(struct i2c_desc *, uint8_t *, uint8_t, uint8_t); + /** i2c write function pointer */ + int32_t (*i2c_ops_read)(struct i2c_desc *, uint8_t *, uint8_t, uint8_t); + /** i2c remove function pointer */ + int32_t (*i2c_ops_remove)(struct i2c_desc *); +}; + +/******************************************************************************/ +/************************ Functions Declarations ******************************/ +/******************************************************************************/ + +/* Initialize the I2C communication peripheral. */ +int32_t i2c_init(struct i2c_desc **desc, + const struct i2c_init_param *param); + +/* Free the resources allocated by i2c_init(). */ +int32_t i2c_remove(struct i2c_desc *desc); + +/* Write data to a slave device. */ +int32_t i2c_write(struct i2c_desc *desc, + uint8_t *data, + uint8_t bytes_number, + uint8_t stop_bit); + +/* Read data from a slave device. */ +int32_t i2c_read(struct i2c_desc *desc, + uint8_t *data, + uint8_t bytes_number, + uint8_t stop_bit); + +#endif // _I2C_H_ diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/include/irq.h b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/include/irq.h new file mode 100644 index 0000000..e8e0b6b --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/include/irq.h @@ -0,0 +1,235 @@ +/***************************************************************************//** + * @file irq.h + * @brief Header file of IRQ interface. + * @author Cristian Pop (cristian.pop@analog.com) +******************************************************************************** + * Copyright 2019(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +#ifndef _IRQ_H_ +#define _IRQ_H_ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ + +#include + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ + +/** + * @enum irq_uart_event_e + * @brief Possible events for uart interrupt + * @todo replace this with enum irq_event + */ +enum irq_uart_event_e { + /** Write operation finalized */ + IRQ_WRITE_DONE, + /** Read operation finalized */ + IRQ_READ_DONE, + /** An error occurred */ + IRQ_ERROR +}; + +enum irq_event { + EVT_GPIO, + EVT_UART_TX_COMPLETE, + EVT_UART_RX_COMPLETE, + EVT_UART_ERROR, + EVT_RTC, + EVT_XINT, + EVT_TIM_ELAPSED +}; + +enum irq_trig_level { + IRQ_LEVEL_LOW, + IRQ_LEVEL_HIGH, + IRQ_EDGE_FALLING, + IRQ_EDGE_RISING, + IRQ_EDGE_BOTH +}; + +enum irq_peripheral { + GPIO_IRQ, + UART_IRQ, + RTC_IRQ, + TIM_IRQ +}; + +/** + * @struct irq_platform_ops + * @brief Structure holding IRQ function pointers that point to the platform + * specific function + */ +struct irq_platform_ops ; + +/** + * @struct irq_init_param + * @brief Structure holding the initial parameters for Interrupt Request. + */ +struct irq_init_param { + /** Interrupt request controller ID. */ + uint32_t irq_ctrl_id; + /** Platform specific IRQ platform ops structure. */ + const struct irq_platform_ops *platform_ops; + /** + * This is intended to store irq controller specific configurations, + * it should not be a reference to any peripheral descriptor. + */ + void *extra; +}; + +/** + * @struct irq_desc + * @brief Structure for Interrupt Request descriptor. + */ +struct irq_ctrl_desc { + /** Interrupt request controller ID. */ + uint32_t irq_ctrl_id; + /** Platform specific IRQ platform ops structure. */ + const struct irq_platform_ops *platform_ops; + /** + * This is intended to store irq controller specific configurations, + * it should not be a reference to any peripheral descriptor. + */ + void *extra; +}; + +/** + * @struct callback_desc + * @brief Structure describing a callback to be registered + * @todo: remove this, use struct irq_callback instead. + */ +struct callback_desc { + /** Callback to be called when the event an event occurs. */ + void (*callback)(void *context); + /** + * Callback to be called when the event an event occurs + * @param ctx - Same as \ref callback_desc.ctx + * @param event - Event that generated the callback + * @param extra - Platform specific data + */ + void (*legacy_callback)(void *ctx, uint32_t event, + void *extra); /* TODO: remove this. */ + /** Parameter to be passed when the callback is called */ + void *ctx; + /** Platform specific configuration for a callback */ + void *legacy_config; /* TODO: remove this. */ + /** Platform specific event that triggers the calling of the callback. */ + enum irq_event event; + /** Interrupt source peripheral specifier. */ + enum irq_peripheral peripheral; + /** This will be used to store HAL specific descriptors */ + void *handle; +}; + +/** + * @struct irq_platform_ops + * @brief Structure holding IRQ function pointers that point to the platform + * specific function + */ +struct irq_platform_ops { + /** Initialize a interrupt controller peripheral. */ + int32_t (*init)(struct irq_ctrl_desc **desc, + const struct irq_init_param *param); + /** Register a legacy_callback to handle the irq events */ + int32_t (*register_callback)(struct irq_ctrl_desc *desc, uint32_t irq_id, + struct callback_desc *callback); + /** Unregisters a generic IRQ handling function */ + int32_t (*unregister_callback)(struct irq_ctrl_desc *desc, + uint32_t irq_id, + struct callback_desc *callback); + /** Global interrupt enable */ + int32_t (*global_enable)(struct irq_ctrl_desc *desc); + /** Global interrupt disable */ + int32_t (*global_disable)(struct irq_ctrl_desc *desc); + /** Set interrupt trigger level. */ + int32_t (*trigger_level_set)(struct irq_ctrl_desc *desc, uint32_t irq_id, + enum irq_trig_level trig); + /** Enable specific interrupt */ + int32_t (*enable)(struct irq_ctrl_desc *desc, uint32_t irq_id); + /** Disable specific interrupt */ + int32_t (*disable)(struct irq_ctrl_desc *desc, uint32_t irq_id); + /** Set the priority level for a specific interrupt */ + int32_t (*set_priority)(struct irq_ctrl_desc *desc, uint32_t irq_id, + uint32_t priority_level); + /** IRQ remove function pointer */ + int32_t (*remove)(struct irq_ctrl_desc *desc); +}; + +/******************************************************************************/ +/************************ Functions Declarations ******************************/ +/******************************************************************************/ + +/* Initialize a interrupt controller peripheral. */ +int32_t irq_ctrl_init(struct irq_ctrl_desc **desc, + const struct irq_init_param *param); + +/* Free the resources allocated by irq_ctrl_init(). */ +int32_t irq_ctrl_remove(struct irq_ctrl_desc *desc); + +/* Register a callback to handle the irq events */ +int32_t irq_register_callback(struct irq_ctrl_desc *desc, + uint32_t irq_id, + struct callback_desc *callback_desc); + +/* Unregisters a generic IRQ handling function */ +int32_t irq_unregister_callback(struct irq_ctrl_desc *desc, + uint32_t irq_id, + struct callback_desc *callback_desc); + +/* Global interrupt enable */ +int32_t irq_global_enable(struct irq_ctrl_desc *desc); + +/* Global interrupt disable */ +int32_t irq_global_disable(struct irq_ctrl_desc *desc); + +/* Set interrupt trigger level. */ +int32_t irq_trigger_level_set(struct irq_ctrl_desc *desc, + uint32_t irq_id, + enum irq_trig_level trig); + +/* Enable specific interrupt */ +int32_t irq_enable(struct irq_ctrl_desc *desc, uint32_t irq_id); + +/* Disable specific interrupt */ +int32_t irq_disable(struct irq_ctrl_desc *desc, uint32_t irq_id); + +/** Set the priority level for a specific interrupt */ +int32_t irq_set_priority(struct irq_ctrl_desc *desc, + uint32_t irq_id, + uint32_t priority_level); +#endif // _IRQ_H_ diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/include/list.h b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/include/list.h new file mode 100644 index 0000000..d2e70f3 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/include/list.h @@ -0,0 +1,327 @@ +/***************************************************************************//** + * @file list.h + * @brief List library header + * @author Mihail Chindris (mihail.chindris@analog.com) +******************************************************************************** + * @copyright + * Copyright 2020(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +******************************************************************************** + * + * @section list_details Library description + * This library handles double linked lists and it expose inseart, + * read, get and delete functions. \n + * It also can be accesed using it member functions which wrapp function for + * usual list types.\n + * @subsection example Sample code + * @code{.c} + * // -- Use a generic list + * struct list_desc *list1; + * struct iterator *it; + * uint32_t a; + * // Create list list1 + * list_init(&list1, LIST_DEFAULT, NULL); + * // Add items to the list + * list_add_last(list1, 1); + * list_add_last(list1, 2); + * list_add_last(list1, 3); + * // Here the list will be: 1 -> 2 - > 3 + * + * list_read_last(list1, &a); + * printf("Last: %d\n", a); + * // 3 will be printed + * // Create an iterator on the end of the list + * iterator_init(&it, list1, 0); + * // Move the iterator backword with one position + * iterator_move(it, -1); + * // Read the data at the current position + * iterator_read(it, &a); + * printf("Current: %d\n", a); + * // 2 will be printed + * iterator_remove(it); + * list_remove(list1); + * + * // -- Use a popular list + * struct list_desc *stack; + * // Create a FIFO list + * list_init(&stack, LIST_STACK, NULL); + * // Put elements in the list + * stack->push(stack, 1); + * stack->push(stack, 2); + * stack->push(stack, 3); + * // Read from the stack + * stack->pop(stack, &a); + * printf("Last: %d\n", a); + * // 3 will be printed + * list_remove(stack); + * @endcode +*******************************************************************************/ + +#ifndef _LIST_H_ +#define _LIST_H_ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ + +#include +#include + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ + +/** + * @struct list_desc + * @brief Structure storing the list and function wrapper for usual list types + * + * With this structure the funtionalities of usual list types + * ( \ref adapter_type ) can be accesed with the functions referenced in this + * structure. + * For example: + * @code{.c} + * my_queue->push(my_queue, my_data); + * @endcode + */ +struct list_desc; + +/** + * @struct list_iterator + * @brief Structure used to iterate through the list using Iterator functions. + */ +struct iterator; + +/** + * @brief Prototype of the compare function. + * + * The function used to compare the elements of the liste when doing + * operations on an ordered list. + * @param data1 - First element to be compared + * @param data2 - Second element to be compared + * @return + * - -1 - If data1 < data2 + * - 0 - If data1 == data2 + * - 1 - If data1 > data2 + */ +typedef int32_t (*f_cmp)(void *data1, void *data2); + +/** + * @name Generic functions + * Each function interacting with the list have one of the following formats.\n + * Aditionaly they may have one more parametere for specific functionalities.\n + * In the Iterator functions, the list reference is replaced by the iterator's + * one. + * @{ + */ + +/** + * @brief Add an element in the list. + * + * The element of the list is created and the data field is stored in it. + * @param list_desc - Reference to the list. Created by \ref list_init. + * @param data - Data to store in a list element + * @return + * - 0 : On success + * - -1 : Otherwise + */ +typedef int32_t (*f_add)(struct list_desc *list_desc, void *data); + +/** + * @brief Edit an element in the list. The content is replaced by new_data. + * @param list_desc - Reference to the list. Created by \ref list_init. + * @param new_data - New data to replace the old one + * @return + * - 0 : On success + * - -1 : Otherwise + */ +typedef int32_t (*f_edit)(struct list_desc *list_desc, void *new_data); + +/** + * @brief Read an element from the list. + * @param list_desc - Reference to the list. Created by \ref list_init. + * @param result - If not null, result is filled with: + * @param data - Content of the list element, NULL if some error occur. + * @return \n + * - 0 : On success + * - -1 : Otherwise + * @note If the content of an element can be 0 then the result must be checked + * to see if the functions has succeded + */ +typedef int32_t (*f_read)(struct list_desc *list_desc, void **data); + +/** + * @brief Read and remove an element from the list. + * @param list_desc - Reference to the list. Created by \ref list_init. + * @param result - If not null, result is filled with: + * @param data - Content of the list element, NULL if some error occur. + * @return + * - 0 : On success + * - -1 : Otherwise + */ +typedef int32_t (*f_get)(struct list_desc *list_desc, void **data); + +/** @} */ + +/** + * @enum adapter_type + * @brief Selects functionalities for functions in \ref list_desc + */ +enum adapter_type { + /** Default type is LIST_STACK */ + LIST_DEFAULT, + /** + * Functions for a FIFO list (First-in first-out). Elements are inserted + * in one end and extracted from the other end. + * - \e Push: Insert element + * - \e Pop: Get next element (Read and remove) + * - \e Top_next: Read next element + * - \e Back: Read first element + * - \e Swap: Edit the content of the next element + */ + LIST_QUEUE, + /** + * Functions for a LIFO list (Last-in first-out). Elements are inserted + * and extracted only from the same end. + * - \e Push: Insert element + * - \e Pop: Get top element (Read and remove) + * - \e Top_next: Read top element + * - \e Back: Read bottom element + * - \e Swap: Edit the content of the top element + */ + LIST_STACK, + /** + * Functions for ordered list. The order of element is determinated + * usinge the \ref f_cmp. + * - \e Push: Insert element + * - \e Pop: Get lowest element (Read and remove) + * - \e Top_next: Read lowest element + * - \e Back: Read the biggest element + * - \e Swap: Edit the lowest element + */ + LIST_PRIORITY_LIST +}; + +struct list_desc { + /** Refer to \ref adapter_type */ + f_add push; + /** Refer to \ref adapter_type */ + f_get pop; + /** Refer to \ref adapter_type */ + f_read top_next; + /** Refer to \ref adapter_type */ + f_read back; + /** Refer to \ref adapter_type */ + f_edit swap; + /** Structure storing the list internal parameters */ + void *priv_desc; +}; + +/******************************************************************************/ +/************************ Functions Declarations ******************************/ +/******************************************************************************/ + +int32_t list_init(struct list_desc **list_desc, + enum adapter_type type, + f_cmp comparator); +int32_t list_remove(struct list_desc *list_desc); +int32_t list_get_size(struct list_desc *list_desc, + uint32_t *out_size); + +/** + * @name Iterator functions + * An iterator is used to iterate through the list. For a list, any number of + * iterators can be created. All must be removed before removing a list. + * @{ + */ +int32_t iterator_init(struct iterator **iter, + struct list_desc *list_desc, + bool start); +int32_t iterator_remove(struct iterator *iter); +int32_t iterator_move(struct iterator *iter, int32_t steps); +int32_t iterator_move_to_idx(struct iterator *iter, int32_t idx); +int32_t iterator_find(struct iterator *iter, void *cmp_data); +int32_t iterator_insert(struct iterator *iter, void *data, + bool after); +int32_t iterator_edit(struct iterator *iter, void *new_data); +int32_t iterator_read(struct iterator *iter, void **data); +int32_t iterator_get(struct iterator *iter, void **data); +/** @}*/ + +/** + * @name Operations on the ends of the list + * These functions will operate on the first or last element of the list + * @{ + */ +int32_t list_add_first(struct list_desc *list_desc, void *data); +int32_t list_edit_first(struct list_desc *list_desc, + void *new_data); +int32_t list_read_first(struct list_desc *list_desc, void **data); +int32_t list_get_first(struct list_desc *list_desc, void **data); + +int32_t list_add_last(struct list_desc *list_desc, void *data); +int32_t list_edit_last(struct list_desc *list_desc, void *new_data); +int32_t list_read_last(struct list_desc *list_desc, void **data); +int32_t list_get_last(struct list_desc *list_desc, void **data); +/** @}*/ + +/** + * @name Operations by index + * These functions use an index to identify the element in the list. + * @{ + */ +int32_t list_add_idx(struct list_desc *list_desc, void *data, + uint32_t idx); +int32_t list_edit_idx(struct list_desc *list_desc, void *new_data, + uint32_t idx); +int32_t list_read_idx(struct list_desc *list_desc, void **data, + uint32_t idx); +int32_t list_get_idx(struct list_desc *list_desc, void **data, + uint32_t idx); +/** @}*/ + +/** + * @name Operations by comparation + * These functions use the specified \ref f_cmp at \ref list_init to identify + * the element this will operate on. + * @{ + */ +int32_t list_add_find(struct list_desc *list_desc, void *data); +int32_t list_edit_find(struct list_desc *list_desc, void *new_data, + void *cmp_data); +int32_t list_read_find(struct list_desc *list_desc, void **data, + void *cmp_data); +int32_t list_get_find(struct list_desc *list_desc, void **data, + void *cmp_data); +/** @}*/ + +#endif // _LIST_H_ diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/include/spi.h b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/include/spi.h new file mode 100644 index 0000000..b415fe2 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/include/spi.h @@ -0,0 +1,209 @@ +/***************************************************************************//** + * @file spi.h + * @brief Header file of SPI Interface + * @author DBogdan (dragos.bogdan@analog.com) +******************************************************************************** + * Copyright 2019(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +#ifndef _SPI_H_ +#define _SPI_H_ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ + +#include + +/******************************************************************************/ +/********************** Macros and Constants Definitions **********************/ +/******************************************************************************/ + +#define SPI_CPHA 0x01 +#define SPI_CPOL 0x02 +#define SPI_3WIRE 0x04 + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ + +/** + * @enum spi_mode + * @brief SPI configuration for clock phase and polarity. + */ +enum spi_mode { + /** Data on rising, shift out on falling */ + SPI_MODE_0 = (0 | 0), + /** Data on falling, shift out on rising */ + SPI_MODE_1 = (0 | SPI_CPHA), + /** Data on rising, shift out on falling */ + SPI_MODE_2 = (SPI_CPOL | 0), + /** Data on falling, shift out on rising */ + SPI_MODE_3 = (SPI_CPOL | SPI_CPHA), + /** Data on rising, shift out on falling */ + SPI_MODE_4 = SPI_3WIRE +}; + +/** + * @enum spi_bit_order + * @brief SPI configuration for bit order (MSB/LSB). + */ +enum spi_bit_order { + /** Most-significant bit (MSB) first */ + SPI_BIT_ORDER_MSB_FIRST = 0, + /** Least-significant bit (LSB) first */ + SPI_BIT_ORDER_LSB_FIRST = 1, +}; + +/** + * @struct spi_msg_list + * @brief List item describing a SPI transfer + */ +struct spi_msg { + /** Buffer with data to send. If NULL, 0x00 will be sent */ + uint8_t *tx_buff; + /** Buffer where to store data. If NULL, incoming data won't be saved */ + uint8_t *rx_buff; + /** Length of buffers. Must have equal size. */ + uint32_t bytes_number; + /** If set, CS will be deasserted after the transfer */ + uint8_t cs_change; + /** + * Minimum delay (in us) between the CS de-assert event of the current message + * and the assert of the next one. + */ + uint32_t cs_change_delay; + /** Delay (in us) between the CS assert and the first SCLK edge. */ + uint32_t cs_delay_first; + /** Delay (in us) between the last SCLK edge and the CS deassert */ + uint32_t cs_delay_last; +}; + +/** + * @struct spi_platform_ops + * @brief Structure holding SPI function pointers that point to the platform + * specific function + */ +struct spi_platform_ops ; + +/** + * @struct spi_init_param + * @brief Structure holding the parameters for SPI initialization + */ +struct spi_init_param { + /** Device ID */ + uint32_t device_id; + /** maximum transfer speed */ + uint32_t max_speed_hz; + /** SPI chip select */ + uint8_t chip_select; + /** SPI mode */ + enum spi_mode mode; + /** SPI bit order */ + enum spi_bit_order bit_order; + const struct spi_platform_ops *platform_ops; + /** SPI extra parameters (device specific) */ + void *extra; + /** Parent of the device */ + struct spi_desc *parent; +}; + +/** + * @struct spi_desc + * @brief Structure holding SPI descriptor. + */ +struct spi_desc { + /** Device ID */ + uint32_t device_id; + /** maximum transfer speed */ + uint32_t max_speed_hz; + /** SPI chip select */ + uint8_t chip_select; + /** SPI mode */ + enum spi_mode mode; + /** SPI bit order */ + enum spi_bit_order bit_order; + const struct spi_platform_ops *platform_ops; + /** SPI extra parameters (device specific) */ + void *extra; + /** Parent of the device */ + struct spi_desc *parent; +}; + +/** + * @struct spi_platform_ops + * @brief Structure holding SPI function pointers that point to the platform + * specific function + */ +struct spi_platform_ops { + /** SPI initialization function pointer */ + int32_t (*init)(struct spi_desc **, const struct spi_init_param *); + /** SPI write/read function pointer */ + int32_t (*write_and_read)(struct spi_desc *, uint8_t *, uint16_t); + /** SPI write function pointer */ + int32_t (*write_and_read_3wire)(struct spi_desc *, uint8_t *,uint8_t *,uint16_t, uint16_t); + /** Iterate over the spi_msg array and send all messages at once */ + int32_t (*transfer)(struct spi_desc *, struct spi_msg *, uint32_t); + /** SPI remove function pointer */ + int32_t (*remove)(struct spi_desc *); +}; + +/******************************************************************************/ +/************************ Functions Declarations ******************************/ +/******************************************************************************/ + +/* Initialize the SPI communication peripheral. */ +int32_t spi_init(struct spi_desc **desc, + const struct spi_init_param *param); + +/* Free the resources allocated by spi_init(). */ +int32_t spi_remove(struct spi_desc *desc); + +/* Write and read data to/from SPI. */ +int32_t spi_write_and_read(struct spi_desc *desc, + uint8_t *data, + uint16_t bytes_number); +int32_t spi_write_and_read_3wire(struct spi_desc *desc, + uint8_t *write_data, + uint8_t *read_data, + uint16_t write_bytes_number, + uint16_t read_bytes_number); + +/* Iterate over the spi_msg array and send all messages at once */ +int32_t spi_transfer(struct spi_desc *desc, + struct spi_msg *msgs, + uint32_t len); + + +#endif // _SPI_H_ diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/include/timer.h b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/include/timer.h new file mode 100644 index 0000000..d1a9284 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/include/timer.h @@ -0,0 +1,159 @@ +/***************************************************************************//** +* @file timer.h +* @brief Timer control module header. +* @author Andrei Drimbarean (andrei.drimbarean@analog.com) +******************************************************************************** +* Copyright 2019(c) Analog Devices, Inc. +* +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* - Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* - Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* - Neither the name of Analog Devices, Inc. nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* - The use of this software may or may not infringe the patent rights +* of one or more patent holders. This license does not release you +* from the requirement that you obtain separate licenses from these +* patent holders to use this software. +* - Use of the software either in source or binary form, must be run +* on or directly connected to an Analog Devices Inc. component. +* +* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, MERCHANTABILITY +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +* IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +#ifndef _SRC_TIMER_H_ +#define _SRC_TIMER_H_ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ + +#include + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ + +/** + * @struct timer_desc + * @brief Structure holding timer descriptor + */ +struct timer_desc { + /** timer ID */ + uint16_t id; + /** timer count frequency (Hz) */ + uint32_t freq_hz; + /** the number of ticks the timer counts until it resets */ + uint32_t ticks_count; + /** Timer platform operations */ + const struct timer_platform_ops *platform_ops; + /** timer extra parameters (device specific) */ + void *extra; +}; + +/** + * @struct timer_platform_ops + * @brief Structure holding timer function pointers that point to the platform + * specific function + */ +struct timer_platform_ops ; + +/** + * @struct timer_init_param + * @brief Structure holding the parameters for timer initialization + */ +struct timer_init_param { + /** timer ID */ + uint16_t id; + /** timer count frequency (Hz) */ + uint32_t freq_hz; + /** the number of ticks the timer counts until it resets */ + uint32_t ticks_count; + /** Timer platform operations */ + const struct timer_platform_ops *platform_ops; + /** timer extra parameters (device specific) */ + void *extra; +}; + +/** + * @struct timer_platform_ops + * @brief Structure holding timer function pointers that point to the platform + * specific function + */ +struct timer_platform_ops { + /** timer initialization function pointer */ + int32_t (*init)(struct timer_desc **, + const struct timer_init_param *); + /** timer start function pointer */ + int32_t (*start)(struct timer_desc *); + /** timer stop function pointer */ + int32_t (*stop)(struct timer_desc *); + /** timer get counter function pointer */ + int32_t (*counter_get)(struct timer_desc *, uint32_t *counter); + /** timer set counter function pointer */ + int32_t (*counter_set)(struct timer_desc *, uint32_t new_val); + /** timer get clock frequency function pointer */ + int32_t (*count_clk_get)(struct timer_desc *, uint32_t *freq_hz); + /** timer set clock frequency function pointer */ + int32_t (*count_clk_set)(struct timer_desc *, uint32_t freq_hz); + /** timer get elapsed time in nsec */ + int32_t (*get_elapsed_time_nsec)(struct timer_desc *, + uint64_t *elapsed_time); + /** timer remove function pointer */ + int32_t (*remove)(struct timer_desc *); +}; + +/******************************************************************************/ +/************************ Functions Declarations ******************************/ +/******************************************************************************/ + +/* Initialize hardware timer and the handler structure associated with it. */ +int32_t timer_init(struct timer_desc **desc, + struct timer_init_param *param); + +/* Free the memory allocated by timer_setup(). */ +int32_t timer_remove(struct timer_desc *desc); + +/* Start a timer. */ +int32_t timer_start(struct timer_desc *desc); + +/* Stop a timer from counting. */ +int32_t timer_stop(struct timer_desc *desc); + +/* Get the value of the counter register for the timer. */ +int32_t timer_counter_get(struct timer_desc *desc, + uint32_t *counter); + +/* Set the timer counter register value. */ +int32_t timer_counter_set(struct timer_desc *desc, + uint32_t new_val); + +/* Get the timer clock frequency. */ +int32_t timer_count_clk_get(struct timer_desc *desc, + uint32_t *freq_hz); + +/* Set the timer clock frequency. */ +int32_t timer_count_clk_set(struct timer_desc *desc, + uint32_t freq_hz); + +/* Get the elapsed time in nsec for the timer. */ +int32_t timer_get_elapsed_time_nsec(struct timer_desc *desc, + uint64_t *elapsed_time); + +#endif // _SRC_TIMER_H_ diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/include/trng.h b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/include/trng.h new file mode 100644 index 0000000..5698032 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/include/trng.h @@ -0,0 +1,115 @@ +/***************************************************************************//** + * @file trng.h + * @brief Header file of true random number generator + * @author Mihail Chindris (mihail.chindris@analog.com) +******************************************************************************** + * @copyright + * Copyright 2020(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +#ifndef _TRNG_H_ +#define _TRNG_H_ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ + +#include + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ + +/** + * @struct trng_platform_ops + * @brief Structure holding TRNG function pointers that point to the platform + * specific function + */ +struct trng_platform_ops; + +/** + * @struct trng_desc + * @brief TRNG Descriptor + */ +struct trng_desc { + /** Platform ops */ + const struct trng_platform_ops *platform_ops; + /** Platform specific parameters */ + void *extra; +}; + +/** + * @struct trng_init_param + * @brief Init parameter for TRNG + */ +struct trng_init_param { + /** Device id */ + uint32_t dev_id; + /** Platform specific parameter */ + void *extra; + /** Platform ops */ + const struct trng_platform_ops *platform_ops; +}; + +/** + * @struct trng_platform_ops + * @brief Structure holding TRNG function pointers that point to the platform + * specific function + */ +struct trng_platform_ops { + /** TRNG initialization function pointer */ + int (*init)(struct trng_desc **, + const struct trng_init_param *); + /** Fill buffer with random numbers */ + int (*fill_buffer)(struct trng_desc *, uint8_t *, uint32_t); + /** TRNG remove function pointer */ + int (*remove)(struct trng_desc *); +}; + +/******************************************************************************/ +/************************ Functions Declarations ******************************/ +/******************************************************************************/ + +/* Initialize descriptor */ +int trng_init(struct trng_desc **desc, + const struct trng_init_param *param); + +/* Free resources allocated in descriptor */ +int trng_remove(struct trng_desc *desc); + +/* Fill buffer with random numbers */ +int trng_fill_buffer(struct trng_desc *desc, uint8_t *buff, + uint32_t len); + +#endif // _TRNG_H_ diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/include/util.h b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/include/util.h new file mode 100644 index 0000000..baad7b6 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/include/util.h @@ -0,0 +1,177 @@ +/*****************************************************************************/ +/** + * @file util.h + * @author FanHao (hao_fan_bit_ee@163.com) + * @brief Utility functions header file + * @version 0.0 + * @date 2023-05-06 + * + * @copyright Copyright(c) 2024 Beijing Institute of Technology.\n + * Lab of Communication and Network + * + ******************************************************************************/ + +/** + * @defgroup Utility + * @{ + */ + +#ifndef __UTIL_H_ +#define __UTIL_H_ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ +#include +#include +#include +/******************************************************************************/ +/********************** Macros and Constants Definitions **********************/ +/******************************************************************************/ +// #define __CRC_LSB +#define __BITSWAP_TABLE +#define __CRC_LSB +#define CRC16_INIT 0x0000 +#define CRC8_INIT 0x00 + +#define BIT(x) (1 << (x)) + +#define ARRAY_SIZE(x) \ + (sizeof(x) / sizeof((x)[0])) + +#define DIV_ROUND_UP(x, y) \ + (((x) + (y)-1) / (y)) +#define DIV_ROUND_CLOSEST(x, y) \ + (((x) + (y) / 2) / (y)) +#define DIV_ROUND_CLOSEST_ULL(x, y) \ + DIV_ROUND_CLOSEST(x, y) + +#define min(x, y) \ + (((x) < (y)) ? (x) : (y)) +#define min_t(type, x, y) \ + (type) min((type)(x), (type)(y)) + +#define max(x, y) \ + (((x) > (y)) ? (x) : (y)) +#define max_t(type, x, y) \ + (type) max((type)(x), (type)(y)) + +#define clamp(val, min_val, max_val) \ + (max(min((val), (max_val)), (min_val))) +#define clamp_t(type, val, min_val, max_val) \ + (type) clamp((type)(val), (type)(min_val), (type)(max_val)) + +#define swap(x, y) \ + { \ + typeof(x) _tmp_ = (x); \ + (x) = (y); \ + (y) = _tmp_; \ + } + +#define round_up(x, y) \ + (((x) + (y)-1) / (y)) + +#define BITS_PER_LONG 32 + +#define GENMASK(h, l) ({ \ + uint32_t t = (uint32_t)(~0UL); \ + t = t << (BITS_PER_LONG - (h - l + 1)); \ + t = t >> (BITS_PER_LONG - (h + 1)); \ + t; \ +}) + +#define bswap_constant_32(x) \ + ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \ + (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24)) + +#define bswap_constant_16(x) ((((x) & (uint16_t)0xff00) >> 8) | \ + (((x) & (uint16_t)0x00ff) << 8)) + +#define bit_swap_constant_8(x) \ + ((((x) & 0x80) >> 7) | \ + (((x) & 0x40) >> 5) | \ + (((x) & 0x20) >> 3) | \ + (((x) & 0x10) >> 1) | \ + (((x) & 0x08) << 1) | \ + (((x) & 0x04) << 3) | \ + (((x) & 0x02) << 5) | \ + (((x) & 0x01) << 7)) + +#define U16_MAX ((uint16_t)~0U) +#define S16_MAX ((int16_t)(U16_MAX >> 1)) + +#define DIV_U64(x, y) (x / y) + +#define UNUSED_PARAM(x) ((void)x) + +#define shift_right(x, s) ((x) < 0 ? -(-(x) >> (s)) : (x) >> (s)) + +/******************************************************************************/ +/************************ Functions Declarations ******************************/ +/******************************************************************************/ + +void IO_Out32(uintptr_t addr, uint32_t value); +uint32_t IO_In32(uintptr_t addr); + +/* flip a byte left to right*/ +uint8_t byte_bit_swap(uint8_t byte); + +/* flip a 32bit word left to right */ +uint32_t word_bit_swap(uint32_t word); + +/* Returns the number of 1-bits in digit. */ +uint32_t count_ones(uint32_t word); + +/* convert a fixed number to a double. */ +double fix2double(int32_t val, uint8_t frac_bits); + +/* Find first set bit in word. */ +uint32_t find_first_set_bit(uint32_t word); +/* Find last set bit in word. */ +uint32_t find_last_set_bit(uint32_t word); +/* Locate the closest element in an array. */ +uint32_t find_closest(int32_t val, + const int32_t *array, + uint32_t size); +/* Shift the value and apply the specified mask. */ +uint32_t field_prep(uint32_t mask, uint32_t val); +/* Get a field specified by a mask from a word. */ +uint32_t field_get(uint32_t mask, uint32_t word); +/* Log base 2 of the given number. */ +int32_t log_base_2(uint32_t x); +/* Find greatest common divisor of the given two numbers. */ +uint32_t greatest_common_divisor(uint32_t a, + uint32_t b); +/* Calculate best rational approximation for a given fraction. */ +void rational_best_approximation(uint32_t given_numerator, + uint32_t given_denominator, + uint32_t max_numerator, + uint32_t max_denominator, + uint32_t *best_numerator, + uint32_t *best_denominator); +/* Calculate the number of set bits. */ +uint32_t hweight8(uint32_t word); +/* Calculate the quotient and the remainder of an integer division. */ +uint64_t do_div(uint64_t *n, + uint64_t base); +/* Unsigned 64bit divide with 64bit divisor and remainder */ +uint64_t div64_u64_rem(uint64_t dividend, uint64_t divisor, + uint64_t *remainder); +/* Unsigned 64bit divide with 32bit divisor with remainder */ +uint64_t div_u64_rem(uint64_t dividend, uint32_t divisor, uint32_t *remainder); +int64_t div_s64_rem(int64_t dividend, int32_t divisor, int32_t *remainder); +/* Unsigned 64bit divide with 32bit divisor */ +uint64_t div_u64(uint64_t dividend, uint32_t divisor); +int64_t div_s64(int64_t dividend, int32_t divisor); +/* Converts from string to int32_t */ +int32_t str_to_int32(const char *str); +/* Converts from string to uint32_t */ +uint32_t srt_to_uint32(const char *str); + +int crc16_gen(uint8_t *buffPtr, uint32_t dataLen, uint16_t poly, uint16_t *crcVal); +bool crc16_check(uint8_t *buffPtr, uint32_t dataLen, uint32_t crcOffset, uint16_t poly); +int crc8_gen(uint8_t *buffPtr, uint32_t dataLen, uint16_t poly, uint8_t *crcVal); +bool crc8_check(uint8_t *buffPtr, uint32_t dataLen, uint32_t crcOffset, uint16_t poly); +#endif // __UTIL_H_ + +/** @} */ \ No newline at end of file diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/main.c b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/main.c new file mode 100644 index 0000000..d8db2f6 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/main.c @@ -0,0 +1,524 @@ +/*****************************************************************************/ +/** + * Description: main.c + * + + * Date: 2023-05-07 13:19 + * Last Edit Time: [2023-05-07 20:32] + * + * Revisions: Rev 0.0 + * History: + * [2023-05-07]: Initial edition. + * + * Copyright(c) 2024 Beijing Institute of Technology. + * + ******************************************************************************/ + +/***************************** Include Files *********************************/ +// Standard +#include +#include +#include +// Xilinx +#include "xscugic.h" +#include "drivers/platform/xilinx_irq.h" +#include "drivers/platform/xilinx_timer.h" +// App +#include "common.h" +#include "error.h" +#include "timer.h" +#include "hwconfig.h" +#include "system_monitor.h" +#include "config/app_config.h" +#include "dev_profile/dev_profile.h" +//#include "systembus/systembus.h" +//#include "networking/phy_layer/phy_layer.h" +//#include "networking/link_layer/link_layer.h" +/************************** Function Prototypes ******************************/ +//int32_t SetupInterruptSystem(struct irq_ctrl_desc *descPtr); +//void Phy_IntrHandler(void *context); +//void PeriodicPull_Handler(void *callBackRef); +//void AppTimer_IntrHandler(void *context); +//void Systembus_RxIntrHandler(void *context); +//void Systembus_TxIntrHandler(void *context); + +/************************** Constant Definitions *****************************/ +//struct callback_desc phy_callback_desc = { +// .callback = Phy_IntrHandler, +// .ctx = NULL +//}; +// +//struct callback_desc periodicpull_callback_desc = { +// .callback = PeriodicPull_Handler, +// .ctx = NULL +//}; +// +// +//struct callback_desc sysbus_rx_callback_desc = { +// .callback = Systembus_RxIntrHandler, +// .ctx = NULL +//}; +// +//struct callback_desc sysbus_tx_callback_desc = { +// .callback = Systembus_TxIntrHandler, +// .ctx = NULL +//}; +// +//struct callback_desc apptimer_callback_desc = { +// .callback = AppTimer_IntrHandler, +// .ctx = NULL +//}; +// +//L2_CONFIG linkConfig = { +// .myType = L2_NODE_HEAD, +// .clustId = 1, +// .myId = 1, +// .headId = 1, +// .netScale = 2, +// .phyInstPtr = NULL, // physical layer reference +// .tmcInstPtr = NULL +//}; +// +//// L2_CONFIG linkConfig = { +//// .myType = L2_NODE_MEMBER, +//// .clustId = 1, +//// .myId = 2, +//// .headId = 1, +//// .netScale = 2, +//// .phyInstPtr = NULL, // physical layer reference +//// .tmcInstPtr = NULL +//// }; +// +//static PHY_CONFIG phyConfig = { +// .devId = PHY_DEVICE_ID, +// .baseAddr = PHY_BASEADDR, +// .antBramId = PHY_ANTCONFIG_BRAM_DEVICE_ID, +// .antInfoBramId = PHY_ANTINFO_BRAM_DEVICE_ID, +// .txBramId = PHY_TXBUFF_BRAM_DEVICE_ID, +// .rxBramId = PHY_RXBUFF_BRAM_DEVICE_ID, +// .hwSysmonId = PHY_HW_SYSMON_DEVICE_ID, +// .get_clk_state = Hardware_GetHMC7044LockStatus, +// .get_ad_lock_state = Hardware_GetAD9361LockStatus, +// .get_ad0_temp = Hardware_GetAD9361Temp_1, +// .get_ad1_temp = Hardware_GetAD9361Temp_2 +//}; +// +//TMC_CONFIG tmcConfig = { +// .baseAddr = TIME_CONTROLLER_BASEADDR, +// .reset = 10 +//}; +// +//static SYSBUS_CONFIG sysbusConfig = { +// .baseAddr = SYSBUS_BASE_ADDR, +// .txQueueMax = 16, +// .rxQueueMax = 16 +//}; +///*********************** Driver Instance Definitions **************************/ +//static struct irq_ctrl_desc *intcDescPtr; // General interrupt controller descriptor +//static struct timer_desc *logTmPtr; +//static SYSBUS *sysbusDescPtr; +//static PHY_INST *phyInstPtr; +//static TMC_INST *tmcInstPtr = NULL; +//L2_INST *linkInstPtr; +// +// +///****************************************************************************/ +///** +// * This function is responsible for initializing the SCUGIC instance, looking +// * for the device configuration based on the unique device ID, initializing a +// * SCUGIC instance, and initialize the interrupt at IRQ_F2P[0:0] +// * +// * @param intcDesc A pointer to INTC descriptor +// * +// * @return SUCCESS if initialize successful. +// * FAILURE if initialization failed. +// * +// *****************************************************************************/ +//int32_t SetupInterruptSystem(struct irq_ctrl_desc *descPtr) +//{ +// int32_t Status; +// struct xil_irq_desc *xil_dev; +// +// Status = irq_ctrl_init(&descPtr, &intc_init_param); +// if (Status != SUCCESS) +// { +// DBG_ERROR("Intc Init FAILED, ErrorCode: %" PRId32 ".\n", Status); +// return Status; +// } +// +// xil_dev = (struct xil_irq_desc *)(descPtr->extra); +// +// // Clear any pending interrupt flags +// uint32_t intrState = XScuGic_CPUReadReg((XScuGic *)(xil_dev->instance), XSCUGIC_INT_ACK_OFFSET); +// XScuGic_CPUWriteReg((XScuGic *)(xil_dev->instance), XSCUGIC_EOI_OFFSET, intrState); +// +// /* Initialize physical layer interrupt. */ +// Status = irq_trigger_level_set(descPtr, PHY_INTR_ID, IRQ_EDGE_RISING); +// if (Status != SUCCESS) +// { +// DBG_ERROR("PHY_INTR trigger level set FAILED, ErrorCode: %" PRId32 ".\n", Status); +// return Status; +// } +// // Set highest interrupt priority +// Status = irq_set_priority(descPtr, PHY_INTR_ID, 0x08); +// if (Status != SUCCESS) +// { +// DBG_ERROR("PHY_INTR priority level set FAILED, ErrorCode: %" PRId32 ".\n", Status); +// return Status; +// } +// // Connect the interrupt service routine isr1 to the interrupt controller +// Status = irq_register_callback(descPtr, PHY_INTR_ID, &phy_callback_desc); +// if (Status != SUCCESS) +// { +// DBG_ERROR("PHY_INTR register callback FAILED, ErrorCode: %" PRId32 ".\n", Status); +// return Status; +// } +// +// /* Initialize linklayer layer interrupt. */ +// Status = irq_trigger_level_set(descPtr, PERIODIC_5MS_INTR_ID, IRQ_EDGE_RISING); +// if (Status != SUCCESS) +// { +// DBG_ERROR("PERIODIC_5MS_INTR_ID trigger level set FAILED, ErrorCode: %" PRId32 ".\n", Status); +// return Status; +// } +// // Set highest interrupt priority +// Status = irq_set_priority(descPtr, PERIODIC_5MS_INTR_ID, 0x00); +// if (Status != SUCCESS) +// { +// DBG_ERROR("PERIODIC_5MS_INTR_ID priority level set FAILED, ErrorCode: %" PRId32 ".\n", Status); +// return Status; +// } +// // Connect the interrupt service routine isr1 to the interrupt controller +// Status = irq_register_callback(descPtr, PERIODIC_5MS_INTR_ID, &periodicpull_callback_desc); +// if (Status != SUCCESS) +// { +// DBG_ERROR("PHY_INTR register callback FAILED, ErrorCode: %" PRId32 ".\n", Status); +// return Status; +// } +// +// /* Initialize system bus interrupt. */ +// Status = irq_trigger_level_set(descPtr, SYSBUS_TX_INTR_ID, IRQ_EDGE_RISING); +// if (Status != SUCCESS) +// { +// DBG_ERROR("PHY_INTR trigger level set FAILED, ErrorCode: %" PRId32 ".\n", Status); +// return Status; +// } +// // Set interrupt priority +// Status = irq_set_priority(descPtr, SYSBUS_TX_INTR_ID, 0x10); +// if (Status != SUCCESS) +// { +// DBG_ERROR("PHY_INTR priority level set FAILED, ErrorCode: %" PRId32 ".\n", Status); +// return Status; +// } +// +// // Connect the interrupt service routine isr1 to the interrupt controller +// Status = irq_register_callback(descPtr, SYSBUS_TX_INTR_ID, &sysbus_tx_callback_desc); +// if (Status != SUCCESS) +// { +// DBG_ERROR("PHY_INTR register callback FAILED, ErrorCode: %" PRId32 ".\n", Status); +// return Status; +// } +// Status = irq_trigger_level_set(descPtr, SYSBUS_RX_INTR_ID, IRQ_EDGE_RISING); +// if (Status != SUCCESS) +// { +// DBG_ERROR("PHY_INTR trigger level set FAILED, ErrorCode: %" PRId32 ".\n", Status); +// return Status; +// } +// // Set interrupt priority +// Status = irq_set_priority(descPtr, SYSBUS_RX_INTR_ID, 0x18); +// if (Status != SUCCESS) +// { +// DBG_ERROR("PHY_INTR priority level set FAILED, ErrorCode: %" PRId32 ".\n", Status); +// return Status; +// } +// +// // Connect the interrupt service routine isr1 to the interrupt controller +// Status = irq_register_callback(descPtr, SYSBUS_RX_INTR_ID, &sysbus_rx_callback_desc); +// if (Status != SUCCESS) +// { +// DBG_ERROR("PHY_INTR register callback FAILED, ErrorCode: %" PRId32 ".\n", Status); +// return Status; +// } +// +// /* Initialize Scu timer interrupt. */ +// // Connect the interrupt service routine isr1 to the interrupt controller +// Status = irq_register_callback(descPtr, APPTIMER_INTR_ID, &apptimer_callback_desc); +// if (Status != SUCCESS) +// { +// DBG_ERROR("PHY_INTR register callback FAILED, ErrorCode: %" PRId32 ".\n", Status); +// return Status; +// } +// +// // Enable interrupts +// irq_enable(descPtr, PHY_INTR_ID); +// irq_enable(descPtr, PERIODIC_5MS_INTR_ID); +// irq_enable(descPtr, SYSBUS_RX_INTR_ID); +// irq_enable(descPtr, SYSBUS_TX_INTR_ID); +// irq_enable(descPtr, APPTIMER_INTR_ID); +// +// // Enable Exceptions +// Status = irq_global_enable(descPtr); +// if (Status != SUCCESS) +// { +// DBG_ERROR("IRQ global enable FAILED, ErrorCode: %" PRId32 ".\n", Status); +// return Status; +// } +// return SUCCESS; +//} // SetupInterruptSystem +// +///****************************************************************************/ +///** +// * This function is a interrupt service routine for IRQ_F2P[1:1], IRQ_F2P[1:1] +// * tells CPU that the data in OCM is ready! +// * +// * @param context +// * +// * @return None. +// * +// *****************************************************************************/ +//void Phy_IntrHandler(void *context) +//{ +// Phy_UpdateState(phyInstPtr); +//} // PhyIntr_Handler +// +// +///****************************************************************************/ +///** +// * Handler of periodic 5ms interrupt +// * +// * @param callBackRef is the linklayer instance pointer. +// * +// * @return None. +// * +// *****************************************************************************/ +//void PeriodicPull_Handler(void *callBackRef) +//{ +// int32_t Status; +// Status = Linklayer_Proc(linkInstPtr); +// if (Status != SUCCESS) +// { +// DBG_ERROR("Link layer runs failed, with error code: %" PRId32 "\n", Status); +// _nop_(); +// } +//} // PeriodicPull_Handler +// +///*****************************************************************************/ +///** +// * @brief Handler of System Bus RX done interrupt. +// * +// * @param context +// * +// * @return None. +// * +// ******************************************************************************/ +//void Systembus_RxIntrHandler(void *context) +//{ +// int32_t Status; +// Status = SystemBus_RxIntrHandler(sysbusDescPtr); +// if (Status != SUCCESS) +// { +// DBG_ERROR("SystemBus_RxIntrHandler exit with error code %" PRId32 ",\n", Status); +// } +//} +// +///*****************************************************************************/ +///** +// * @brief Handler of System Bus TX done interrupt. +// * +// * @param context +// * +// * @return None. +// * +// ******************************************************************************/ +//void Systembus_TxIntrHandler(void *context) +//{ +// int32_t Status; +// Status = SystemBus_TxIntrHandler(sysbusDescPtr); +// if (Status != SUCCESS) +// { +// DBG_ERROR("SystemBus_TxIntrHandler exit with error code %" PRId32 ",\n", Status); +// } +//} +// +///*****************************************************************************/ +///** +// * @brief Handler of AppTimer interrupt. +// * +// * @param context +// * +// * @return None. +// * +// ******************************************************************************/ +//void AppTimer_IntrHandler(void *context) +//{ +// struct xil_timer_desc *xdesc; +// xdesc = (struct xil_timer_desc *)(logTmPtr->extra); +//#ifdef XPAR_XSCUTIMER_NUM_INSTANCES +// if (XScuTimer_IsExpired((XScuTimer *)xdesc->instance)) +// { +// // Refresh log +// Phy_RefreshHwSate(phyInstPtr); +// if (TimeCtrl_GetIntCnt(tmcInstPtr) - phyInstPtr->lastLogTime >= PHY_LOG_EXPIRE) +// { +// Phy_UpdateLogging(phyInstPtr); +// } +// +// XScuTimer_ClearInterruptStatus((XScuTimer *)xdesc->instance); +// } +//#elif defined(XPAR_XTMRCTR_NUM_INSTANCES) +// if (XTmrCtr_IsExpired((XTmrCtr *)xdesc->instance, 0)) +// { +// // Refresh log +// Phy_RefreshHwSate(phyInstPtr); +// if (TimeCtrl_GetIntCnt(tmcInstPtr) - phyInstPtr->lastLogTime >= PHY_LOG_EXPIRE) +// { +// Phy_UpdateLogging(phyInstPtr); +// } +// +// XTmrCtr_ClearStats((XTmrCtr *)xdesc->instance); +// } +//#else +//#error No timer implementation! +//#endif +// else +// { +// DBG_WARNING("UNEXPECTED CALL of AppTimer_IntrHandler\n"); +// } +//} + +/*****************************************************************************/ +/** + * @brief Main function, initialize all the device needed, initialize + * interrupt system, halt in while(1) wait for event interrupt. + * + * @param none. + * + * @return + * + ******************************************************************************/ +int main(void) +{ + int32_t Status; + DBG_PRINT("Application Version: %2d.%2d.%4d.\n", _APP_VER_MAIN, _APP_VER_MINOR, _APP_VER_PATCH); + + /* System Monitor Initialize */ + Status = SysMonitor_Init(); + if (Status == SUCCESS) + { + DBG_PRINT("System monitor Init SUCCESS! \n"); + } + else + { + DBG_PRINT("System monitor Init FAILED! \n"); + return Status; + } + + /* Hardware Initialize */ + Status = Hardware_Init(); + if (Status == SUCCESS) + { + DBG_PRINT("Hardware Init SUCCESS! \n"); + } + else + { + DBG_PRINT("Hardware Init FAILED! \n"); + return Status; + } + +// /* Time controller Initialize */ +// Status = TimeCtrl_Init(&tmcInstPtr, &tmcConfig); +// if (Status == SUCCESS) +// { +// DBG_PRINT("TmcCtrl Init SUCCESS! \n"); +// } +// else +// { +// DBG_PRINT("TmcCtrl Init FAILED! \n"); +// return Status; +// } +// +// /* Physical Layer Initialize */ +// Status = Phy_Init(&phyInstPtr, &phyConfig); +// if (Status == SUCCESS) +// { +// DBG_PRINT("Physical layer Init SUCCESS! \n"); +// } +// else +// { +// DBG_PRINT("Physical layer FAILED! \n"); +// return Status; +// } +// +// /* Link Layer Initialize */ +// linkConfig.phyInstPtr = phyInstPtr; +// linkConfig.tmcInstPtr = tmcInstPtr; +// Status = Linklayer_Init(&linkInstPtr, &linkConfig); +// if (Status == SUCCESS) +// { +// DBG_PRINT("LinkLayer Init SUCCESS! \n"); +// } +// else +// { +// DBG_PRINT("Linklayer Init FAILED! \n"); +// return Status; +// } +// +// /* System Bus Initialize */ +// Status = SystemBus_Init(&sysbusDescPtr, &sysbusConfig); +// if (Status != SUCCESS) +// { +// DBG_ERROR("Systembus init FAILED, with error code: %" PRId32 "\n", Status); +// return Status; +// } +// +// /* System Monitor log timer Initialize */ +// Status = timer_init(&logTmPtr, &apptimer_init_param); +// if (Status != SUCCESS) +// { +// DBG_ERROR("APP Timer init FAILED, with error code: %" PRId32 "\n", Status); +// return Status; +// } +// +// /* interrupts Initialize */ +// Status = SetupInterruptSystem(intcDescPtr); +// if (Status == SUCCESS) +// { +// DBG_INFO("Interrupt system setup SUCCESS!\n"); +// } +// else +// { +// DBG_ERROR("Interrupt system setup FAILED, ErrorCode: %" PRId32 ".\n", Status); +// return Status; +// } +// +// // Start System Monitor logging. +// timer_start(logTmPtr); +// +// DBG_PRINT("Physical started...\n"); +// Phy_Start(phyInstPtr); +// +// // Linklayer_Start(linkInstPtr); + + while (true) + { +// // System bus handler +// if (SystemBus_IsReqPending(sysbusDescPtr)) +// { +// Status = SystemBus_HandleCmd(sysbusDescPtr); +// if (Status != SUCCESS) +// { +// DBG_ERROR("SystemBus_HandleCmd exit with ErrorCode: %" PRId32 ".\n", Status); +// } +// } +// if (SystemBus_IsRsqPending(sysbusDescPtr) && (!SystemBus_IsTxBusy(sysbusDescPtr))) +// { +// // FIXME: Required by 12 (CASC) +// udelay(4000); +// Status = SystemBus_MakeResp(sysbusDescPtr); +// if (Status != SUCCESS) +// { +// DBG_ERROR("SystemBus_HandleCmd exit with ErrorCode: %" PRId32 ".\n", Status); +// } +// } + } +} // main diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/system_monitor.c b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/system_monitor.c new file mode 100644 index 0000000..beddcc0 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/system_monitor.c @@ -0,0 +1,402 @@ +/** + * @addtogroup SystemMonitor + * @{ + */ + +/***************************** Include Files *********************************/ +#include +#include +#include +#include "common.h" +#include "system_monitor.h" +/************************** Constant Definitions *****************************/ +/** + * @name SystemMonitor_Private_Constants + * @{ + */ +#define BUFF_A 0x00 +#define BUFF_B 0x01 +#define BUFF_NONE 0xFF + +#define SYSINFO_PACK_LEN 54 // bytes +#define PAYLOAD_PACK_LEN 46 // bytes +#define SLOTLOG_PACK_LEN 88 // bytes +#define PRTCLLOG_PACK_ELN 24 // bytes +#define HWSTATE_PACK_ELN 12 // bytes +/** @} SystemMonitor_Private_Constants*/ +/************************** Data Type Definitions ****************************/ +/** + * @struct PINGPONG + * @brief PingPing Control + */ +typedef struct +{ + uint8_t latest; ///< latest available index + uint8_t rBusy; ///< current read busy index + uint8_t wBusy; ///< current write busy index +} PINGPONG; + +/** + * @struct SYSMONITOR + * @brief System Monitor struct holds all the system log info + */ +typedef struct +{ + PINGPONG recvCtrl; + PAYLOAD recv[2]; + PINGPONG sendCtrl; + PAYLOAD send[2]; + PINGPONG sysInfoCtrl; + SYSINFO sysInfo[2]; + PINGPONG linkLogCtrl; + LINKLOG linkLog[2]; + PINGPONG phyLogCtrl; + PHYLOG phyLog[2]; + PINGPONG hwStateCtrl; + HWSTATE hwState[2]; +} SYSMONITOR; + +/************************** Function Prototypes ******************************/ +static uint8_t GetWritable(PINGPONG ctrllor); +static uint8_t GetReadable(PINGPONG ctrllor); +/************************** Variable Definitions *****************************/ +static SYSMONITOR *sysMonitorInst; + +/*********************** Function Implementations ***************************/ +inline static uint8_t GetWritable(PINGPONG ctrllor) +{ + // Allow only one write. + ASSERT(ctrllor.wBusy == BUFF_NONE); + if (ctrllor.rBusy == BUFF_NONE) + return ((ctrllor.latest == BUFF_B) ? BUFF_A : BUFF_B); + else + return ((ctrllor.rBusy == BUFF_B) ? BUFF_A : BUFF_B); +} + +inline static uint8_t GetReadable(PINGPONG ctrllor) +{ + if (ctrllor.wBusy == BUFF_NONE || ctrllor.wBusy != ctrllor.latest) + return ((ctrllor.latest == BUFF_NONE) ? BUFF_A : BUFF_B); + else + return ((ctrllor.wBusy == BUFF_B) ? BUFF_A : BUFF_B); +} + +/** + * @brief Initialize System monitor + * + * @return SUCCESS + */ +int32_t SysMonitor_Init(void) +{ + sysMonitorInst = calloc(1, sizeof(SYSMONITOR)); + if (sysMonitorInst == NULL) + { + return ENOMEM; + } + memset(&(sysMonitorInst->recvCtrl), BUFF_NONE, sizeof(PINGPONG)); + memset(&(sysMonitorInst->sendCtrl), BUFF_NONE, sizeof(PINGPONG)); + memset(&(sysMonitorInst->sysInfoCtrl), BUFF_NONE, sizeof(PINGPONG)); + memset(&(sysMonitorInst->linkLogCtrl), BUFF_NONE, sizeof(PINGPONG)); + memset(&(sysMonitorInst->phyLogCtrl), BUFF_NONE, sizeof(PINGPONG)); + memset(&(sysMonitorInst->hwStateCtrl), BUFF_NONE, sizeof(PINGPONG)); + + sysMonitorInst->recv[0].dataId = DATA_ID_NONE; + sysMonitorInst->recv[1].dataId = DATA_ID_NONE; + sysMonitorInst->send[0].dataId = DATA_ID_NONE; + sysMonitorInst->send[1].dataId = DATA_ID_NONE; + return SUCCESS; +} + +/** + * @brief Destroy system monitor release all allocated memory + */ +void SysMonitor_Destroy(void) +{ + free(sysMonitorInst); +} + +/** + * @name SystemInfo_API + * @{ + */ + +/** + * @brief Update system info. + * + * @param info + */ +void SysMonitor_UpdateSysinfo(const SYSINFO *info) +{ + uint8_t buffIndx; + buffIndx = GetWritable(sysMonitorInst->sysInfoCtrl); + sysMonitorInst->sysInfoCtrl.wBusy = buffIndx; + memcpy(&(sysMonitorInst->sysInfo[buffIndx]), info, sizeof(SYSINFO)); + sysMonitorInst->sysInfoCtrl.latest = buffIndx; + sysMonitorInst->sysInfoCtrl.wBusy = BUFF_NONE; +} + +/** + * @brief Get system info. + * + * @param info + */ +void SysMonitor_GetSysinfo(SYSINFO *info) +{ + ASSERT(sysMonitorInst != NULL); + uint8_t buffIndx, buffIndex_old; + buffIndex_old = sysMonitorInst->sysInfoCtrl.rBusy; + if (buffIndex_old != BUFF_NONE) + buffIndx = buffIndex_old; // Keep it busy + else + buffIndx = GetReadable(sysMonitorInst->sysInfoCtrl); + sysMonitorInst->sysInfoCtrl.rBusy = buffIndx; + memcpy(info, &(sysMonitorInst->sysInfo[buffIndx]), sizeof(SYSINFO)); + sysMonitorInst->sysInfoCtrl.rBusy = buffIndex_old; +} +/** @} SystemInfo_API*/ + +/** + * @name ServicePayload_API + * @{ + */ + +/** + * @brief Update send payload by + * + * @param buff + * @param len + */ +void SysMonitor_UpdateSendPayload(const uint8_t *buff, size_t len) +{ + ASSERT(sysMonitorInst != NULL); + if (len > PAYLOAD_LEN_MAX) + { + return; + } + uint8_t buffIndx; + buffIndx = GetWritable(sysMonitorInst->sendCtrl); + sysMonitorInst->sendCtrl.wBusy = buffIndx; + memcpy(sysMonitorInst->send[buffIndx].data, buff, len); + sysMonitorInst->send[buffIndx].dataId++; + sysMonitorInst->sendCtrl.latest = buffIndx; + sysMonitorInst->sendCtrl.wBusy = BUFF_NONE; +} + +/** + * @brief Get the latest send payload. + * + * @param buff + * @param id + * @param len + */ +void SysMonitor_GetSendPayload(uint8_t *buff, uint32_t *id, size_t len) +{ + ASSERT(sysMonitorInst != NULL); + ASSERT(buff != NULL); + ASSERT(id != NULL); + if (len > PAYLOAD_LEN_MAX) + { + return; + } + uint8_t buffIndx, buffIndex_old; + buffIndex_old = sysMonitorInst->sendCtrl.rBusy; + if (buffIndex_old != BUFF_NONE) + buffIndx = buffIndex_old; // Keep it busy + else + buffIndx = GetReadable(sysMonitorInst->sendCtrl); + sysMonitorInst->sendCtrl.rBusy = buffIndx; + if (sysMonitorInst->send[buffIndx].dataId != DATA_ID_NONE) + { + memcpy(buff, sysMonitorInst->send[buffIndx].data, len); + } + *id = sysMonitorInst->send[buffIndx].dataId; + sysMonitorInst->sendCtrl.rBusy = buffIndex_old; +} + +/** + * @brief Update receive payload. + * + * @param buff + * @param id + * @param len + */ +void SysMonitor_UpdateRecvPayload(const uint8_t *buff, uint32_t id, size_t len) +{ + ASSERT(sysMonitorInst != NULL); + ASSERT(buff != NULL); + if (id == DATA_ID_NONE || len > PAYLOAD_LEN_MAX) + { + return; + } + uint8_t buffIndx; + buffIndx = GetWritable(sysMonitorInst->recvCtrl); + sysMonitorInst->recvCtrl.wBusy = buffIndx; + memcpy(sysMonitorInst->recv[buffIndx].data, buff, len); + sysMonitorInst->recv[buffIndx].dataId = id; + sysMonitorInst->recvCtrl.latest = buffIndx; + sysMonitorInst->recvCtrl.wBusy = BUFF_NONE; +} + +/** + * @brief Get the latest receive payload. + * + * @param buff + * @param id + * @param len + */ +void SysMonitor_GetRecvPayload(uint8_t *buff, uint32_t *id, size_t len) +{ + ASSERT(sysMonitorInst != NULL); + ASSERT(buff != NULL); + ASSERT(id != NULL); + if (len > PAYLOAD_LEN_MAX) + { + return; + } + uint8_t buffIndx, buffIndex_old; + buffIndex_old = sysMonitorInst->recvCtrl.rBusy; + if (buffIndex_old != BUFF_NONE) + buffIndx = buffIndex_old; // Keep it busy + else + buffIndx = GetReadable(sysMonitorInst->recvCtrl); + sysMonitorInst->recvCtrl.rBusy = buffIndx; + if (sysMonitorInst->recv[buffIndx].dataId != DATA_ID_NONE) + { + memcpy(buff, sysMonitorInst->recv[buffIndx].data, len); + } + *id = sysMonitorInst->recv[buffIndx].dataId; + sysMonitorInst->recvCtrl.rBusy = buffIndex_old; +} +/** @} ServicePayload_API*/ + +/** + * @name Linklayer_Log_API + * @{ + */ + +/** + * @brief Update link layer log + * + * @param log + */ +void SysMonitor_UpdateLinklayerLog(const LINKLOG *log) +{ + ASSERT(sysMonitorInst != NULL); + ASSERT(log != NULL); + uint8_t buffIndx; + buffIndx = GetWritable(sysMonitorInst->linkLogCtrl); + sysMonitorInst->linkLogCtrl.wBusy = buffIndx; + memcpy(&(sysMonitorInst->linkLog[buffIndx]), log, sizeof(LINKLOG)); + sysMonitorInst->linkLogCtrl.latest = buffIndx; + sysMonitorInst->linkLogCtrl.wBusy = BUFF_NONE; +} + +/** + * @brief Get the latest link layer log + * + * @param log + */ +void SysMonitor_GetLinklayerLog(LINKLOG *log) +{ + ASSERT(sysMonitorInst != NULL); + ASSERT(log != NULL); + uint8_t buffIndx, buffIndex_old; + buffIndex_old = sysMonitorInst->linkLogCtrl.rBusy; + if (buffIndex_old != BUFF_NONE) + buffIndx = buffIndex_old; // Keep it busy + else + buffIndx = GetReadable(sysMonitorInst->linkLogCtrl); + sysMonitorInst->linkLogCtrl.rBusy = buffIndx; + memcpy(log, &(sysMonitorInst->linkLog[buffIndx]), sizeof(LINKLOG)); + sysMonitorInst->linkLogCtrl.rBusy = buffIndex_old; +} +/** @} Linklayer_Log_API*/ + +/** + * @name PhysicalLayer_Log_API + * @{ + */ + +/** + * @brief Update physical layer log + * + * @param log + */ +void SysMonitor_UpdatePhysicalLayerLog(const PHYLOG *log) +{ + ASSERT(sysMonitorInst != NULL); + ASSERT(log != NULL); + uint8_t buffIndx; + buffIndx = GetWritable(sysMonitorInst->phyLogCtrl); + sysMonitorInst->phyLogCtrl.wBusy = buffIndx; + memcpy(&(sysMonitorInst->phyLog[buffIndx]), log, sizeof(PHYLOG)); + sysMonitorInst->phyLogCtrl.latest = buffIndx; + sysMonitorInst->phyLogCtrl.wBusy = BUFF_NONE; +} + +/** + * @brief Get the latest physical layer log + * + * @param log + */ +void SysMonitor_GetPhysicalLayerLog(PHYLOG *log) +{ + ASSERT(sysMonitorInst != NULL); + ASSERT(log != NULL); + uint8_t buffIndx, buffIndex_old; + buffIndex_old = sysMonitorInst->phyLogCtrl.rBusy; + if (buffIndex_old != BUFF_NONE) + buffIndx = buffIndex_old; // Keep it busy + else + buffIndx = GetReadable(sysMonitorInst->phyLogCtrl); + sysMonitorInst->phyLogCtrl.rBusy = buffIndx; + memcpy(log, &(sysMonitorInst->phyLog[buffIndx]), sizeof(PHYLOG)); + sysMonitorInst->phyLogCtrl.rBusy = buffIndex_old; +} +/** @} */ + +/** + * @name HardwareState_Log_API + * @{ + */ + +/** + * @brief Log hardware running status. + * + * @param state + */ +void SysMonitor_UpdateHardwareStatus(const HWSTATE *state) +{ + ASSERT(sysMonitorInst != NULL); + ASSERT(state != NULL); + uint8_t buffIndx; + buffIndx = GetWritable(sysMonitorInst->hwStateCtrl); + sysMonitorInst->hwStateCtrl.wBusy = buffIndx; + memcpy(&(sysMonitorInst->hwState[buffIndx]), state, sizeof(HWSTATE)); + sysMonitorInst->hwStateCtrl.latest = buffIndx; + sysMonitorInst->hwStateCtrl.wBusy = BUFF_NONE; +} + +/** + * @brief Get the latest hardware running status. + * + * @param state + */ +void SysMonitor_GetHardwareStatus(HWSTATE *state) +{ + ASSERT(sysMonitorInst != NULL); + ASSERT(state != NULL); + uint8_t buffIndx, buffIndex_old; + buffIndex_old = sysMonitorInst->hwStateCtrl.rBusy; + if (buffIndex_old != BUFF_NONE) + buffIndx = buffIndex_old; // Keep it busy + else + buffIndx = GetReadable(sysMonitorInst->hwStateCtrl); + sysMonitorInst->hwStateCtrl.rBusy = buffIndx; + memcpy(state, &(sysMonitorInst->hwState[buffIndx]), sizeof(HWSTATE)); + sysMonitorInst->hwStateCtrl.rBusy = buffIndex_old; +} + +/** @} HardwareState_Log_API */ + +/** @} SystemMonitor*/ \ No newline at end of file diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/system_monitor.h b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/system_monitor.h new file mode 100644 index 0000000..f5be369 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/system_monitor.h @@ -0,0 +1,241 @@ +/** + * @defgroup SystemMonitor + * @{ + */ + +#ifndef __SYSTEM_MONITOR_H_ +#define __SYSTEM_MONITOR_H_ + +/***************************** Include Files *********************************/ +#include +#include +#include "util.h" + +/************************* Constant Definitions ******************************/ +/** + * @name SystemMonitor_Constants + * @{ + */ +#define PAYLOAD_LEN_MAX 256 +#define PAYLOAD_LEN_FLJ_RX 168 +#define PAYLOAD_LEN_FLJ_TX 66 +#define PAYLOAD_LEN_LJ_RX 66 +#define PAYLOAD_LEN_LJ_TX 168 + +#define DATA_ID_NONE UINT32_MAX +#define DATA_ID_TEST 0x02030203 + +#define VOLTAGE_LSB 0.01 // volt +#define VOLTAGE_MAX 2.55 // volt + +#define VOLT_PS_STD 1.0 +#define VOLT_PSAUX_STD 1.8 +#define VOLT_DDR_STD 1.5 +#define VOLT_PL_STD 1.0 +#define VOLT_PLAUX_STD 1.8 +#define VOLT_BRAM_STD 1.0 + +#define VOLT_PS_OK BIT(0) +#define VOLT_PSAUX_OK BIT(1) +#define VOLT_DDR_OK BIT(2) +#define VOLT_PL_OK BIT(3) +#define VOLT_PLAUX_OK BIT(4) +#define VOLT_BRAM_OK BIT(5) + +#define VOLT_ANT_PROC_OK BIT(0) +#define VOLT_ANT_RF_OK BIT(2) +#define VOLT_ANT_NIL_OK BIT(4) +#define ANT_STATE_OK BIT(6) + +// Xilinx Recommended +// #define IS_PS_VALID(x) (x <= 1.05 && x >= 0.95) +// #define IS_PSAUX_VALID(x) (x <= 1.89 && x >= 1.71) +// #define IS_DDR_VALID(x) (x <= 1.89 && x >= 1.14) +// #define IS_PL_VALID(x) (x <= 1.03 && x >= 0.97) +// #define IS_PLAUX_VALID(x) (x <= 1.89 && x >= 1.71) +// #define IS_BRAM_VALID(x) (x <= 1.03 && x >= 0.97) +#define IS_PS_VALID(x) (x <= 1.1 && x >= 0.9) +#define IS_PSAUX_VALID(x) (x <= 2.0 && x >= 1.6) +#define IS_DDR_VALID(x) (x <= 1.7 && x >= 1.3) +#define IS_PL_VALID(x) (x <= 1.1 && x >= 0.9) +#define IS_PLAUX_VALID(x) (x <= 2.0 && x >= 1.6) +#define IS_BRAM_VALID(x) (x <= 1.1 && x >= 0.9) + +#define CLK_SP_PLL0_LOCK BIT(0) +#define CLK_SP_PLL1_LOCK BIT(2) + +#define CLK_AD0_BBPLL_LOCK BIT(0) +#define CLK_AD0_RFPLL_LOCK BIT(2) +#define CLK_AD1_BBPLL_LOCK BIT(4) +#define CLK_AD1_RFPLL_LOCK BIT(6) + +#define CLK_ANT_BBPLL_LOCK BIT(0) +#define CLK_ANT_RFPLL0_LOCK BIT(2) +#define CLK_ANT_RFPLL1_LOCK BIT(4) + +#define TEMPERATURE_LSB 1.0 // Celsius degree +#define TEMPERATURE_MAX 127.0 // Celsius degree +#define TEMPERATURE_MIN -128.0 // Celsius degree +/** @} SystemMonitor_Constants */ + +/************************* Data Type Definitions ****************************/ + +/** + * @struct SYSINFO + * @brief System Infomation log + */ +typedef struct __attribute__((packed)) +{ + uint32_t psBDS; ///< -- unit: ms, 0~604799999 + uint16_t pBDS; ///< -- unit: week, 0~0~8191 + uint32_t psGPS; ///< -- unit: ms, 0~604799999 + uint16_t pGPS; ///< -- unit: week, 0~0~8191 + uint8_t tmInd; ///< Time validation indicator \n + // -- [0] GPS\n + // -- [1] reserve.\n + // -- [2] UTC\n + // -- [3] BDS\n + float tmFly; ///< Time of flying uint: s + uint8_t stFly; ///< Status of flying \n + // [7:6] departure status 11 - departed/00 - not departed \n + // [5:4] ready status 11 - ready/00 - not ready \n + // [3:2] attitude status 11 - attitude ok/00 - attitude not ok \n + // [1:0] attitude adjust status 11 - adjusted/00 - not adjusted + float posX; ///< coord X Position in launch coordinate system + float posY; ///< coord Y Position in launch coordinate system + float posZ; ///< coord Z Position in launch coordinate system + float vX; ///< Speed X in launch coordinate system + float vY; ///< Speed Y in launch coordinate system + float vZ; ///< Speed Z in launch coordinate system + float pitch; ///< Pitch Attitude in launch inertia coordinate system + float yaw; ///< Yaw Attitude in launch inertia coordinate system + float roll; ///< Roll Attitude in launch inertia coordinate system +} SYSINFO; + +/** + * @struct SYSBUSLOG + * @brief System Info holds the system bus log + */ +typedef struct __attribute__((packed)) +{ + // SystemBus log + + uint8_t lastConfig[2]; ///< Last valid config \n + // byte 0: 0x11 FLJ, 0x00 LJ \n + // byte 1: 0x66 Full Power, 0x88 Low Power + uint32_t pollCnt; ///< number of poll commands + uint32_t svcCnt; ///< number of service commands + uint32_t remoteCnt; ///< number of remote check commands +} SYSBUSLOG; + +/** + * @struct LINKLOG + * @brief Linklayer Log struct holds the Linklayer log + */ +typedef struct __attribute__((packed)) +{ + // Network log + uint32_t tuNum; ///< current time unite number + uint8_t slotNum; ///< current slot number + uint8_t nodeType; ///< current node type + uint8_t cxnStatus; ///< current connection status + uint8_t linkStage; ///< current linklayer working stage + uint32_t recxnCnt; ///< reconnect trial count + uint8_t beamNo; ///< current working beam number + uint8_t beamWidth; ///< current working beam width + uint16_t beamAz; ///< current working beam angle Az + uint16_t beamEl; ///< current working beam angle Ez + uint16_t advTxCnt; ///< adv frame send count + uint16_t advRecvCnt; ///< adv frame received count + uint16_t advCorrectCnt; ///< adv frame received correctly count + uint32_t cfmTxCnt; ///< cfm frame send count + uint32_t cfmRecvCnt; ///< cfm frame received count + uint32_t cfmCorrectCnt; ///< adv frame received correctly count + uint32_t svcTxCnt; ///< svc frame send count + uint32_t svcRecvCnt; ///< svc frame received count + uint32_t svcCorrectCnt; ///< svc frame received correctly count + int32_t timeDev; ///< last time deviation result + uint32_t sendId; ///< last send data id + uint32_t recvId; ///< last received data id + uint8_t reserve[4]; ///< reserved data +} LINKLOG; + +/** + * @struct PHYLOG + * @brief Physical Layer Log struct holds the Linklayer log + */ +typedef struct __attribute__((packed)) +{ + uint32_t acqCnt; ///< aquisition count + uint32_t fsyncCnt; ///< frame sync count + uint32_t decodeCnt; ///< decode count + uint32_t crcCnt; ///< crc valid count + double doppler; ///< last doppler estimation result + uint64_t recvStamp; ///< last frame arrival time + double acqPAPR; ///< last acquisition peak-average ration + uint8_t acqPhase; ///< last acquisition phase estimation + uint8_t acqFreqCh; ///< last acquisition frequency deviation estimation + double fsyncPAPR; ///< last frame sync peak-average ration + uint8_t fsyncFreqCh; ///< last frame sync frequency estimation + uint16_t deintlvAmpEst; ///< de-interleave amplitude estimation + uint8_t antMode; ///< current antenna working mode + uint8_t reserve[3]; ///< reserved data +} PHYLOG; + +/** + * @struct HWSTATE + * @brief Hardware Status Log struct holds all hardware status + */ +typedef struct __attribute__((packed)) +{ + bool isSpOk; ///< signal processor state + bool isAntOk; ///< antenna state + // -- Signal processor status + uint8_t spFpgaVolt; ///< Signal processor voltage state indicator + uint8_t spClkState; ///< Signal processor clock state indicator + uint8_t spAdLockState; ///< Signal processor adc lock state indicator + uint8_t spAdTemp_0; ///< Signal processor adc0 temperature + uint8_t spAdTemp_1; ///< Signal processor adc1 temperature + uint8_t spFpgaTemp; ///< Signal processor FPGA temperature + // -- Antenna status + uint8_t antVolt; ///< Antenna voltage state indicator + uint8_t antTemp; ///< Antenna rf temperature + uint8_t antPll; ///< Antenna rf lock state indicator + uint8_t antMgc0; ///< Antenna rf mgc0~1 indicator + uint8_t antMgc1; ///< Antenna rf mgc2~3 indicator + uint8_t phyId; + uint8_t reserve[1]; +} HWSTATE; + +/** + * @struct PAYLOAD + * @brief Payload struct holds the service payload + */ +typedef struct +{ + uint32_t dataId; + uint8_t data[PAYLOAD_LEN_MAX]; +} PAYLOAD; + +/************************** Function Prototypes ******************************/ +int32_t SysMonitor_Init(void); +void SysMonitor_Destroy(void); + +void SysMonitor_UpdateSysinfo(const SYSINFO *info); +void SysMonitor_GetSysinfo(SYSINFO *info); + +void SysMonitor_UpdateSendPayload(const uint8_t *buff, size_t len); +void SysMonitor_UpdateRecvPayload(const uint8_t *buff, uint32_t id, size_t len); +void SysMonitor_GetSendPayload(uint8_t *buff, uint32_t *id, size_t len); +void SysMonitor_GetRecvPayload(uint8_t *buff, uint32_t *id, size_t len); + +void SysMonitor_UpdateLinklayerLog(const LINKLOG *log); +void SysMonitor_UpdatePhysicalLayerLog(const PHYLOG *log); +void SysMonitor_UpdateHardwareStatus(const HWSTATE *state); +void SysMonitor_GetLinklayerLog(LINKLOG *log); +void SysMonitor_GetPhysicalLayerLog(PHYLOG *log); +void SysMonitor_GetHardwareStatus(HWSTATE *state); + +#endif //__SYSTEM_MONITOR_H_ + +/** @} */ \ No newline at end of file diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/util/circ_queue.c b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/util/circ_queue.c new file mode 100644 index 0000000..11270f3 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/util/circ_queue.c @@ -0,0 +1,134 @@ +/*****************************************************************************/ +/** + * @file circ_queue.c + * @author FanHao (hao_fan_bit_ee@163.com) + * @brief A simple circular FIFO bounded queue + * @version 0.1 + * @date 2023-02-23 + * @note Forked from https://github.com/chrismerck/rpa_queue.git + * @copyright Copyright(c) 2024 Beijing Institute of Technology.\n + * Lab of Communication and Network + * + ******************************************************************************/ + +/** + * @addtogroup Utility + * @{ + */ + +/** + * @addtogroup CircularQueue + * @{ + */ +#include "circ_queue.h" +#include "common.h" +#include +#include +#include + +inline bool isCircQueueFull(CIRC_QUEUE *queue) +{ + ASSERT(queue != NULL); + return ((queue)->nelts == (queue)->bounds); +} + +inline bool isCircQueueEmpty(CIRC_QUEUE *queue) +{ + ASSERT(queue != NULL); + return ((queue)->nelts == 0); +} + +void CircQueueFree(CIRC_QUEUE *queue) +{ + ASSERT(queue != NULL); + if (queue->data) + free(queue->data); + free(queue); +} + +/** + * @brief Initialize the CIRC_QUEUE. + */ +bool CircQueueCreate(CIRC_QUEUE **q, uint32_t queueCapacity) +{ + ASSERT(q != NULL); + CIRC_QUEUE *queue; + queue = malloc(sizeof(CIRC_QUEUE)); + if (!queue) + { + return false; + } + *q = queue; + memset(queue, 0, sizeof(CIRC_QUEUE)); + + /* Set all the data in the queue to NULL */ + queue->data = malloc(queueCapacity * sizeof(void *)); + if (queue->data == NULL) + { + goto error; + } + queue->bounds = queueCapacity; + queue->nelts = 0; + queue->in = 0; + queue->out = 0; + return true; +error: + free(queue); + return false; +} + +/** + * @brief Push new data onto the queue. + */ +bool CircQueuePush(CIRC_QUEUE *queue, void *data) +{ + ASSERT(queue != NULL); + + if (isCircQueueFull(queue)) + { + return false; + } + + queue->data[queue->in] = data; + queue->in++; + if (queue->in >= queue->bounds) + { + queue->in -= queue->bounds; + } + queue->nelts++; + + return true; +} + +/** + * @brief Return current number of element in queue. + */ +inline uint32_t CircQueueSize(CIRC_QUEUE *queue) +{ + return queue->nelts; +} + +/** + * @brief Retrieves the next item from the queue. + */ +bool CircQueuePop(CIRC_QUEUE *queue, void **data) +{ + ASSERT(queue != NULL); + + if (isCircQueueEmpty(queue)) + { + return false; + } + + *data = queue->data[queue->out]; + queue->nelts--; + + queue->out++; + if (queue->out >= queue->bounds) + { + queue->out -= queue->bounds; + } + return true; +} +/** @} CircularQueue*/ +/** @} Utility*/ \ No newline at end of file diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/util/clist.c b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/util/clist.c new file mode 100644 index 0000000..2ed467e --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/util/clist.c @@ -0,0 +1,353 @@ +/*****************************************************************************/ +/** + * @file clist.c + * @author FanHao (hao_fan_bit_ee@163.com) + * @brief A basic list data structure + * @version 0.1 + * @date 2023-02-23 + * @note Forked from https://github.com/clibs/list + * @copyright Copyright(c) 2024 Beijing Institute of Technology.\n + * Lab of Communication and Network + * + ******************************************************************************/ + +/** + * @addtogroup Utility + * @{ + */ + +/** + * @addtogroup cList + * @{ + */ +#ifndef LIST_MALLOC +#define LIST_MALLOC malloc +#endif + +#ifndef LIST_FREE +#define LIST_FREE free +#endif + +#include +#include "clist.h" + +/** + * @brief a new clist_node_t. NULL on failure. + */ +clist_node_t * +clist_node_new(void *val) +{ + clist_node_t *self; + if (!(self = LIST_MALLOC(sizeof(clist_node_t)))) + return NULL; + self->prev = NULL; + self->next = NULL; + self->val = val; + return self; +} + +/** + * @brief Allocate a new clist_t. NULL on failure. + */ +clist_t * +clist_new(void) +{ + clist_t *self; + if (!(self = LIST_MALLOC(sizeof(clist_t)))) + return NULL; + self->head = NULL; + self->tail = NULL; + self->free = NULL; + self->compare = NULL; + self->len = 0; + return self; +} + +/** + * @brief Remove all the node in list. + * @param self: Pointer to the list + */ +void clist_clear(clist_t *self) +{ + clist_node_t *next; + clist_node_t *curr = self->head; + + while (curr != NULL) + { + next = curr->next; + if (self->free) + self->free(curr->val); + LIST_FREE(curr); + curr = next; + } + self->len = 0; + self->head = NULL; +} + +/** + * @brief Free the list. + * @param self: Pointer to the list + */ +void clist_destroy(clist_t *self) +{ + clist_clear(self); + LIST_FREE(self); +} + +/** + * @brief Append the given node to the list and return the node, NULL on failure. + * @param self: Pointer to the list for popping node + * @param node: the node to push + */ +clist_node_t * +clist_rpush(clist_t *self, clist_node_t *node) +{ + if (!node) + return NULL; + + if (self->len) + { + node->prev = self->tail; + node->next = NULL; + self->tail->next = node; + self->tail = node; + } + else + { + self->head = self->tail = node; + node->prev = node->next = NULL; + } + + ++self->len; + return node; +} + +/** + * @brief Return / detach the last node in the list, or NULL. + * @param self: Pointer to the list for popping node + */ + +clist_node_t * +clist_rpop(clist_t *self) +{ + if (!self->len) + return NULL; + + clist_node_t *node = self->tail; + + if (--self->len) + { + (self->tail = node->prev)->next = NULL; + } + else + { + self->tail = self->head = NULL; + } + + node->next = node->prev = NULL; + return node; +} + +/** + * @brief Return / detach the first node in the list, or NULL. + * @param self: Pointer to the list for popping node + */ + +clist_node_t * +clist_lpop(clist_t *self) +{ + if (!self->len) + return NULL; + + clist_node_t *node = self->head; + + if (--self->len) + { + (self->head = node->next)->prev = NULL; + } + else + { + self->head = self->tail = NULL; + } + + node->next = node->prev = NULL; + return node; +} + +/** + * @brief Prepend the given node to the list and return the node, NULL on failure. + * @param self: Pointer to the list for pushing node + * @param node: the node to push + */ + +clist_node_t * +clist_lpush(clist_t *self, clist_node_t *node) +{ + if (!node) + return NULL; + + if (self->len) + { + node->next = self->head; + node->prev = NULL; + self->head->prev = node; + self->head = node; + } + else + { + self->head = self->tail = node; + node->prev = node->next = NULL; + } + + ++self->len; + return node; +} + +/** + * @brief Return the node associated to val or NULL. + * @param self: Pointer to the list for finding given value + * @param val: Value to find + */ + +clist_node_t * +clist_find(clist_t *self, void *val) +{ + clist_iterator_t *it = clist_iterator_new(self, LIST_HEAD); + clist_node_t *node; + + while ((node = clist_iterator_next(it))) + { + if (self->compare) + { + if (self->compare(val, node->val) == 0) + { + clist_iterator_destroy(it); + return node; + } + } + else + { + if (val == node->val) + { + clist_iterator_destroy(it); + return node; + } + } + } + + clist_iterator_destroy(it); + return NULL; +} + +/** + * @brief Return the node at the given index or NULL. + * @param self: Pointer to the list for finding given index + * @param index: the index of node in the list + */ + +clist_node_t * +clist_at(clist_t *self, int index) +{ + clist_direction_t direction = LIST_HEAD; + + if (index < 0) + { + direction = LIST_TAIL; + index = ~index; + } + + if ((unsigned)index < self->len) + { + clist_iterator_t *it = clist_iterator_new(self, direction); + clist_node_t *node = clist_iterator_next(it); + while (index--) + node = clist_iterator_next(it); + clist_iterator_destroy(it); + return node; + } + + return NULL; +} + +/** + * @brief Remove the given node from the list, freeing it and it's value. + * @param self: Pointer to the list to delete a node + * @param node: Pointer the node to be deleted + */ + +void clist_remove(clist_t *self, clist_node_t *node) +{ + node->prev + ? (node->prev->next = node->next) + : (self->head = node->next); + + node->next + ? (node->next->prev = node->prev) + : (self->tail = node->prev); + + if (self->free) + self->free(node->val); + + LIST_FREE(node); + --self->len; +} + +/** + * @brief Allocate a new clist_iterator_t. NULL on failure.\n + * Accepts a direction, which may be LIST_HEAD or LIST_TAIL. + */ + +clist_iterator_t * +clist_iterator_new(clist_t *list, clist_direction_t direction) +{ + clist_node_t *node = direction == LIST_HEAD + ? list->head + : list->tail; + return clist_iterator_new_from_node(node, direction); +} + +/** + * @brief Allocate a new clist_iterator_t with the given start + * node. NULL on failure. + */ + +clist_iterator_t * +clist_iterator_new_from_node(clist_node_t *node, clist_direction_t direction) +{ + clist_iterator_t *self; + if (!(self = LIST_MALLOC(sizeof(clist_iterator_t)))) + return NULL; + self->next = node; + self->direction = direction; + return self; +} + +/** + * @brief Return the next clist_node_t or NULL when no more + * nodes remain in the list. + */ + +clist_node_t * +clist_iterator_next(clist_iterator_t *self) +{ + clist_node_t *curr = self->next; + if (curr) + { + self->next = self->direction == LIST_HEAD + ? curr->next + : curr->prev; + } + return curr; +} + +/** + * @brief Free the list iterator. + */ + +void clist_iterator_destroy(clist_iterator_t *self) +{ + LIST_FREE(self); + self = NULL; +} +/** @} cList*/ +/** @} Utility*/ \ No newline at end of file diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/util/common.c b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/util/common.c new file mode 100644 index 0000000..e42bf68 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/util/common.c @@ -0,0 +1,51 @@ +/*****************************************************************************/ +/** + * Description: Common functions + * + * Date: 2021-11-16 00:08 + * LastEditors: Fan Hao + * LastEditTime: 2022-07-16 17:13 + * Revisions: Rev 0.1 + * History: + * [2022-07-16]: New branch for Dijian. + * [2021-11-16]: Initial version. + * + * Copyright(c) 2024 Beijing Institute of Technology. + * Lab of Communication and Networking + * + ******************************************************************************/ +/** + * @addtogroup COMMON_MACRO + * @{ + */ +/***************************** Include Files *********************************/ +#include "common.h" +#include "error.h" +#include "util.h" + +/************************** Constant Definitions *****************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/**************************** Type Definitions *******************************/ + +/************************** Variable Definitions *****************************/ + +/*****************************************************************************/ +/** + * @brief Throw an assert. + * + * @param file indicate the filename of the assertion + * @param line indicate which line the assertion occurs + * + * @return NONE. + * + ******************************************************************************/ +void AppAssert(const char *file, int line) +{ + DBG_PRINT("in %s:%d [assert] .\n", file, line); + while (1) + ; +} + +/** @} */ \ No newline at end of file diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/util/crc.c b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/util/crc.c new file mode 100644 index 0000000..5d88b23 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/util/crc.c @@ -0,0 +1,444 @@ +/*****************************************************************************/ +/** + * Description: CRC implementation file + * + * Author: Hao Fan + * Date: 2021-11-16 00:50 + * LastEditors: Hao Fan + * LastEditTime: 2022-07-17 20:53 + * Revisions: Rev 0.0 + * History: + * [2022-07-17]: Add CRC16_0x8005 CRC8_0x31. + * [2022-01-06]: Initial verion (Basic CRC-16). + * + * Copyright(c) 2024 Beijing Institute of Technology. + * Lab of Communication and Networking + * + ******************************************************************************/ +/** + * @addtogroup Utility + * @{ + */ +#include "util.h" +#include "error.h" + +#ifdef __CRC_LSB +// CRC-16-CCITT G(X)=X16+X12+X5+1 +// Reversed +static const uint16_t crc16_1021_lsb_lut[256] = +{ + 0x0000, 0x1189, 0x2312, 0x329B, 0x4624, 0x57AD, 0x6536, 0x74BF, + 0x8C48, 0x9DC1, 0xAF5A, 0xBED3, 0xCA6C, 0xDBE5, 0xE97E, 0xF8F7, + 0x1081, 0x0108, 0x3393, 0x221A, 0x56A5, 0x472C, 0x75B7, 0x643E, + 0x9CC9, 0x8D40, 0xBFDB, 0xAE52, 0xDAED, 0xCB64, 0xF9FF, 0xE876, + 0x2102, 0x308B, 0x0210, 0x1399, 0x6726, 0x76AF, 0x4434, 0x55BD, + 0xAD4A, 0xBCC3, 0x8E58, 0x9FD1, 0xEB6E, 0xFAE7, 0xC87C, 0xD9F5, + 0x3183, 0x200A, 0x1291, 0x0318, 0x77A7, 0x662E, 0x54B5, 0x453C, + 0xBDCB, 0xAC42, 0x9ED9, 0x8F50, 0xFBEF, 0xEA66, 0xD8FD, 0xC974, + 0x4204, 0x538D, 0x6116, 0x709F, 0x0420, 0x15A9, 0x2732, 0x36BB, + 0xCE4C, 0xDFC5, 0xED5E, 0xFCD7, 0x8868, 0x99E1, 0xAB7A, 0xBAF3, + 0x5285, 0x430C, 0x7197, 0x601E, 0x14A1, 0x0528, 0x37B3, 0x263A, + 0xDECD, 0xCF44, 0xFDDF, 0xEC56, 0x98E9, 0x8960, 0xBBFB, 0xAA72, + 0x6306, 0x728F, 0x4014, 0x519D, 0x2522, 0x34AB, 0x0630, 0x17B9, + 0xEF4E, 0xFEC7, 0xCC5C, 0xDDD5, 0xA96A, 0xB8E3, 0x8A78, 0x9BF1, + 0x7387, 0x620E, 0x5095, 0x411C, 0x35A3, 0x242A, 0x16B1, 0x0738, + 0xFFCF, 0xEE46, 0xDCDD, 0xCD54, 0xB9EB, 0xA862, 0x9AF9, 0x8B70, + 0x8408, 0x9581, 0xA71A, 0xB693, 0xC22C, 0xD3A5, 0xE13E, 0xF0B7, + 0x0840, 0x19C9, 0x2B52, 0x3ADB, 0x4E64, 0x5FED, 0x6D76, 0x7CFF, + 0x9489, 0x8500, 0xB79B, 0xA612, 0xD2AD, 0xC324, 0xF1BF, 0xE036, + 0x18C1, 0x0948, 0x3BD3, 0x2A5A, 0x5EE5, 0x4F6C, 0x7DF7, 0x6C7E, + 0xA50A, 0xB483, 0x8618, 0x9791, 0xE32E, 0xF2A7, 0xC03C, 0xD1B5, + 0x2942, 0x38CB, 0x0A50, 0x1BD9, 0x6F66, 0x7EEF, 0x4C74, 0x5DFD, + 0xB58B, 0xA402, 0x9699, 0x8710, 0xF3AF, 0xE226, 0xD0BD, 0xC134, + 0x39C3, 0x284A, 0x1AD1, 0x0B58, 0x7FE7, 0x6E6E, 0x5CF5, 0x4D7C, + 0xC60C, 0xD785, 0xE51E, 0xF497, 0x8028, 0x91A1, 0xA33A, 0xB2B3, + 0x4A44, 0x5BCD, 0x6956, 0x78DF, 0x0C60, 0x1DE9, 0x2F72, 0x3EFB, + 0xD68D, 0xC704, 0xF59F, 0xE416, 0x90A9, 0x8120, 0xB3BB, 0xA232, + 0x5AC5, 0x4B4C, 0x79D7, 0x685E, 0x1CE1, 0x0D68, 0x3FF3, 0x2E7A, + 0xE70E, 0xF687, 0xC41C, 0xD595, 0xA12A, 0xB0A3, 0x8238, 0x93B1, + 0x6B46, 0x7ACF, 0x4854, 0x59DD, 0x2D62, 0x3CEB, 0x0E70, 0x1FF9, + 0xF78F, 0xE606, 0xD49D, 0xC514, 0xB1AB, 0xA022, 0x92B9, 0x8330, + 0x7BC7, 0x6A4E, 0x58D5, 0x495C, 0x3DE3, 0x2C6A, 0x1EF1, 0x0F78 +}; + +// CRC-16-MAXIM G(X)=X16+X15+X2+1 +const uint16_t crc16_8005_lsb_lut[256] = +{ + 0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241, + 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440, + 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40, + 0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841, + 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40, + 0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41, + 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641, + 0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040, + 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240, + 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441, + 0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41, + 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840, + 0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41, + 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40, + 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640, + 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041, + 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240, + 0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441, + 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41, + 0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840, + 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41, + 0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40, + 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640, + 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041, + 0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241, + 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440, + 0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40, + 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841, + 0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40, + 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41, + 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641, + 0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040 +}; + +// CRC-8-MAXIM G(X)=X8+X5+X4+1 +const uint8_t crc8_31_lsb_lut[256] = +{ + 0x00, 0x5E, 0xBC, 0xE2, 0x61, 0x3F, 0xDD, 0x83, + 0xC2, 0x9C, 0x7E, 0x20, 0xA3, 0xFD, 0x1F, 0x41, + 0x9D, 0xC3, 0x21, 0x7F, 0xFC, 0xA2, 0x40, 0x1E, + 0x5F, 0x01, 0xE3, 0xBD, 0x3E, 0x60, 0x82, 0xDC, + 0x23, 0x7D, 0x9F, 0xC1, 0x42, 0x1C, 0xFE, 0xA0, + 0xE1, 0xBF, 0x5D, 0x03, 0x80, 0xDE, 0x3C, 0x62, + 0xBE, 0xE0, 0x02, 0x5C, 0xDF, 0x81, 0x63, 0x3D, + 0x7C, 0x22, 0xC0, 0x9E, 0x1D, 0x43, 0xA1, 0xFF, + 0x46, 0x18, 0xFA, 0xA4, 0x27, 0x79, 0x9B, 0xC5, + 0x84, 0xDA, 0x38, 0x66, 0xE5, 0xBB, 0x59, 0x07, + 0xDB, 0x85, 0x67, 0x39, 0xBA, 0xE4, 0x06, 0x58, + 0x19, 0x47, 0xA5, 0xFB, 0x78, 0x26, 0xC4, 0x9A, + 0x65, 0x3B, 0xD9, 0x87, 0x04, 0x5A, 0xB8, 0xE6, + 0xA7, 0xF9, 0x1B, 0x45, 0xC6, 0x98, 0x7A, 0x24, + 0xF8, 0xA6, 0x44, 0x1A, 0x99, 0xC7, 0x25, 0x7B, + 0x3A, 0x64, 0x86, 0xD8, 0x5B, 0x05, 0xE7, 0xB9, + 0x8C, 0xD2, 0x30, 0x6E, 0xED, 0xB3, 0x51, 0x0F, + 0x4E, 0x10, 0xF2, 0xAC, 0x2F, 0x71, 0x93, 0xCD, + 0x11, 0x4F, 0xAD, 0xF3, 0x70, 0x2E, 0xCC, 0x92, + 0xD3, 0x8D, 0x6F, 0x31, 0xB2, 0xEC, 0x0E, 0x50, + 0xAF, 0xF1, 0x13, 0x4D, 0xCE, 0x90, 0x72, 0x2C, + 0x6D, 0x33, 0xD1, 0x8F, 0x0C, 0x52, 0xB0, 0xEE, + 0x32, 0x6C, 0x8E, 0xD0, 0x53, 0x0D, 0xEF, 0xB1, + 0xF0, 0xAE, 0x4C, 0x12, 0x91, 0xCF, 0x2D, 0x73, + 0xCA, 0x94, 0x76, 0x28, 0xAB, 0xF5, 0x17, 0x49, + 0x08, 0x56, 0xB4, 0xEA, 0x69, 0x37, 0xD5, 0x8B, + 0x57, 0x09, 0xEB, 0xB5, 0x36, 0x68, 0x8A, 0xD4, + 0x95, 0xCB, 0x29, 0x77, 0xF4, 0xAA, 0x48, 0x16, + 0xE9, 0xB7, 0x55, 0x0B, 0x88, 0xD6, 0x34, 0x6A, + 0x2B, 0x75, 0x97, 0xC9, 0x4A, 0x14, 0xF6, 0xA8, + 0x74, 0x2A, 0xC8, 0x96, 0x15, 0x4B, 0xA9, 0xF7, + 0xB6, 0xE8, 0x0A, 0x54, 0xD7, 0x89, 0x6B, 0x35 +}; +#else +// CRC-16-CCITT G(X)=X16+X12+X5+1 +static const uint16_t crc16_1021_msb_lut[256] = +{ + 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7, + 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF, + 0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6, + 0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE, + 0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485, + 0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D, + 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4, + 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC, + 0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823, + 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B, + 0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12, + 0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A, + 0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41, + 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49, + 0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70, + 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78, + 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F, + 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067, + 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E, + 0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256, + 0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D, + 0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, + 0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C, + 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634, + 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB, + 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3, + 0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A, + 0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92, + 0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9, + 0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1, + 0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8, + 0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0 +}; + +// CRC-16-MAXIM G(X)=X16+X15+X2+1 +const uint16_t crc16_8005_msb_lut[256] = +{ + 0x0000, 0x8005, 0x800F, 0x000A, 0x801B, 0x001E, 0x0014, 0x8011, + 0x8033, 0x0036, 0x003C, 0x8039, 0x0028, 0x802D, 0x8027, 0x0022, + 0x8063, 0x0066, 0x006C, 0x8069, 0x0078, 0x807D, 0x8077, 0x0072, + 0x0050, 0x8055, 0x805F, 0x005A, 0x804B, 0x004E, 0x0044, 0x8041, + 0x80C3, 0x00C6, 0x00CC, 0x80C9, 0x00D8, 0x80DD, 0x80D7, 0x00D2, + 0x00F0, 0x80F5, 0x80FF, 0x00FA, 0x80EB, 0x00EE, 0x00E4, 0x80E1, + 0x00A0, 0x80A5, 0x80AF, 0x00AA, 0x80BB, 0x00BE, 0x00B4, 0x80B1, + 0x8093, 0x0096, 0x009C, 0x8099, 0x0088, 0x808D, 0x8087, 0x0082, + 0x8183, 0x0186, 0x018C, 0x8189, 0x0198, 0x819D, 0x8197, 0x0192, + 0x01B0, 0x81B5, 0x81BF, 0x01BA, 0x81AB, 0x01AE, 0x01A4, 0x81A1, + 0x01E0, 0x81E5, 0x81EF, 0x01EA, 0x81FB, 0x01FE, 0x01F4, 0x81F1, + 0x81D3, 0x01D6, 0x01DC, 0x81D9, 0x01C8, 0x81CD, 0x81C7, 0x01C2, + 0x0140, 0x8145, 0x814F, 0x014A, 0x815B, 0x015E, 0x0154, 0x8151, + 0x8173, 0x0176, 0x017C, 0x8179, 0x0168, 0x816D, 0x8167, 0x0162, + 0x8123, 0x0126, 0x012C, 0x8129, 0x0138, 0x813D, 0x8137, 0x0132, + 0x0110, 0x8115, 0x811F, 0x011A, 0x810B, 0x010E, 0x0104, 0x8101, + 0x8303, 0x0306, 0x030C, 0x8309, 0x0318, 0x831D, 0x8317, 0x0312, + 0x0330, 0x8335, 0x833F, 0x033A, 0x832B, 0x032E, 0x0324, 0x8321, + 0x0360, 0x8365, 0x836F, 0x036A, 0x837B, 0x037E, 0x0374, 0x8371, + 0x8353, 0x0356, 0x035C, 0x8359, 0x0348, 0x834D, 0x8347, 0x0342, + 0x03C0, 0x83C5, 0x83CF, 0x03CA, 0x83DB, 0x03DE, 0x03D4, 0x83D1, + 0x83F3, 0x03F6, 0x03FC, 0x83F9, 0x03E8, 0x83ED, 0x83E7, 0x03E2, + 0x83A3, 0x03A6, 0x03AC, 0x83A9, 0x03B8, 0x83BD, 0x83B7, 0x03B2, + 0x0390, 0x8395, 0x839F, 0x039A, 0x838B, 0x038E, 0x0384, 0x8381, + 0x0280, 0x8285, 0x828F, 0x028A, 0x829B, 0x029E, 0x0294, 0x8291, + 0x82B3, 0x02B6, 0x02BC, 0x82B9, 0x02A8, 0x82AD, 0x82A7, 0x02A2, + 0x82E3, 0x02E6, 0x02EC, 0x82E9, 0x02F8, 0x82FD, 0x82F7, 0x02F2, + 0x02D0, 0x82D5, 0x82DF, 0x02DA, 0x82CB, 0x02CE, 0x02C4, 0x82C1, + 0x8243, 0x0246, 0x024C, 0x8249, 0x0258, 0x825D, 0x8257, 0x0252, + 0x0270, 0x8275, 0x827F, 0x027A, 0x826B, 0x026E, 0x0264, 0x8261, + 0x0220, 0x8225, 0x822F, 0x022A, 0x823B, 0x023E, 0x0234, 0x8231, + 0x8213, 0x0216, 0x021C, 0x8219, 0x0208, 0x820D, 0x8207, 0x0202 +}; + +// CRC-8-MAXIM G(X)=X8+X5+X4+1 +const uint8_t crc8_31_msb_lut[256] = +{ + 0x00, 0x31, 0x62, 0x53, 0xC4, 0xF5, 0xA6, 0x97, + 0xB9, 0x88, 0xDB, 0xEA, 0x7D, 0x4C, 0x1F, 0x2E, + 0x43, 0x72, 0x21, 0x10, 0x87, 0xB6, 0xE5, 0xD4, + 0xFA, 0xCB, 0x98, 0xA9, 0x3E, 0x0F, 0x5C, 0x6D, + 0x86, 0xB7, 0xE4, 0xD5, 0x42, 0x73, 0x20, 0x11, + 0x3F, 0x0E, 0x5D, 0x6C, 0xFB, 0xCA, 0x99, 0xA8, + 0xC5, 0xF4, 0xA7, 0x96, 0x01, 0x30, 0x63, 0x52, + 0x7C, 0x4D, 0x1E, 0x2F, 0xB8, 0x89, 0xDA, 0xEB, + 0x3D, 0x0C, 0x5F, 0x6E, 0xF9, 0xC8, 0x9B, 0xAA, + 0x84, 0xB5, 0xE6, 0xD7, 0x40, 0x71, 0x22, 0x13, + 0x7E, 0x4F, 0x1C, 0x2D, 0xBA, 0x8B, 0xD8, 0xE9, + 0xC7, 0xF6, 0xA5, 0x94, 0x03, 0x32, 0x61, 0x50, + 0xBB, 0x8A, 0xD9, 0xE8, 0x7F, 0x4E, 0x1D, 0x2C, + 0x02, 0x33, 0x60, 0x51, 0xC6, 0xF7, 0xA4, 0x95, + 0xF8, 0xC9, 0x9A, 0xAB, 0x3C, 0x0D, 0x5E, 0x6F, + 0x41, 0x70, 0x23, 0x12, 0x85, 0xB4, 0xE7, 0xD6, + 0x7A, 0x4B, 0x18, 0x29, 0xBE, 0x8F, 0xDC, 0xED, + 0xC3, 0xF2, 0xA1, 0x90, 0x07, 0x36, 0x65, 0x54, + 0x39, 0x08, 0x5B, 0x6A, 0xFD, 0xCC, 0x9F, 0xAE, + 0x80, 0xB1, 0xE2, 0xD3, 0x44, 0x75, 0x26, 0x17, + 0xFC, 0xCD, 0x9E, 0xAF, 0x38, 0x09, 0x5A, 0x6B, + 0x45, 0x74, 0x27, 0x16, 0x81, 0xB0, 0xE3, 0xD2, + 0xBF, 0x8E, 0xDD, 0xEC, 0x7B, 0x4A, 0x19, 0x28, + 0x06, 0x37, 0x64, 0x55, 0xC2, 0xF3, 0xA0, 0x91, + 0x47, 0x76, 0x25, 0x14, 0x83, 0xB2, 0xE1, 0xD0, + 0xFE, 0xCF, 0x9C, 0xAD, 0x3A, 0x0B, 0x58, 0x69, + 0x04, 0x35, 0x66, 0x57, 0xC0, 0xF1, 0xA2, 0x93, + 0xBD, 0x8C, 0xDF, 0xEE, 0x79, 0x48, 0x1B, 0x2A, + 0xC1, 0xF0, 0xA3, 0x92, 0x05, 0x34, 0x67, 0x56, + 0x78, 0x49, 0x1A, 0x2B, 0xBC, 0x8D, 0xDE, 0xEF, + 0x82, 0xB3, 0xE0, 0xD1, 0x46, 0x77, 0x24, 0x15, + 0x3B, 0x0A, 0x59, 0x68, 0xFF, 0xCE, 0x9D, 0xAC +}; +#endif + +/* CRC lookup table algorithm +#define CRC_BIT_NUM 8u/16u/32u/64u +#define BITS_IN_BYTE 8u +uint8_t dataBuff[ARRAY_SIZE] = { 0x32, 0x33, …}; +uint8_t/uint16_t/uint32_t crc_val = 0x0; +// LSB +for(int i = 0; i < sizeof(dataBuff); i++) +{ + crc_val = (crc_val >> BITS_IN_BYTE) ^ crc_lsb_lut[(uint8)(crc_val^dataBuff[i])]; +} +// MSB +for(int i = 0; i < sizeof(dataBuff); i++) +{ + crc_val = (crc_val << BITS_IN_BYTE) ^ crc_msb_lut[(uint8)((crc_val>>8)^dataBuff[i])]; +} +*/ + +/*****************************************************************************/ +/** + * @brief CRC8 generator + * + * @param buffPtr data buffer pointer. + * @param dataLen data length + * @param poly polynomials of crc + * @param crcVal a pointer to store generated crc value + * + * @return SUCCESS + * FAILURE + * + ******************************************************************************/ +int crc8_gen(uint8_t *buffPtr, uint32_t dataLen, uint16_t poly, uint8_t *crcVal) +{ + uint8_t crc = CRC8_INIT; + const uint8_t *crc_lut = NULL; + + switch (poly) + { +#ifdef __CRC_LSB + case 0x31: + crc_lut = crc8_31_lsb_lut; + break; + default: + return FAILURE; +#else + case 0x31: + crc_lut = crc8_31_msb_lut; + break; + default: + return FAILURE; +#endif + } + + for (int i = 0; i < dataLen; i++) + { + crc = crc_lut[(uint8_t)(crc ^ buffPtr[i])]; + } + *crcVal = crc; + return SUCCESS; +} + +/*****************************************************************************/ +/** + * @brief CRC16 generator + * + * @param buffPtr data buffer pointer. + * @param dataLen data length + * @param poly polynomials of crc + * @param crcVal a pointer to store generated crc value + * + * @return SUCCESS + * FAILURE + * + ******************************************************************************/ +int crc16_gen(uint8_t *buffPtr, uint32_t dataLen, uint16_t poly, uint16_t *crcVal) +{ + uint16_t crc = CRC16_INIT; + const uint16_t *crc_lut = NULL; + switch (poly) + { +#ifdef __CRC_LSB + case 0x8005: + crc_lut = crc16_8005_lsb_lut; + break; + case 0x1021: + crc_lut = crc16_1021_lsb_lut; + break; + default: + return FAILURE; +#else + case 0x8005: + crc_lut = crc16_8005_msb_lut; + break; + case 0x1021: + crc_lut = crc16_1021_msb_lut; + break; + default: + return FAILURE; +#endif + } + for (int i = 0; i < dataLen; i++) + { +#ifdef __CRC_LSB + crc = (crc >> 8) ^ crc_lut[(uint8_t)(crc ^ buffPtr[i])]; +#else + crc = (crc << 8) ^ crc_lut[(uint8_t)((crc >> 8) ^ buffPtr[i])]; +#endif + } + *crcVal = crc; + return SUCCESS; +} + +/*****************************************************************************/ +/** + * @brief CRC8 compare cheker + * + * @param buffPtr data buffer pointer. + * @param dataLen data length + * @param crcOffset byte offset of crc stored position. + * @param poly polynomials of crc + * + * @return true + * false + * + ******************************************************************************/ +bool crc8_check(uint8_t *buffPtr, uint32_t dataLen, uint32_t crcOffset, uint16_t poly) +{ + int Status = SUCCESS; + uint8_t crc_comp; + uint8_t crc; + if (dataLen == 0) + { + return false; + } + crc_comp = (uint8_t)(*(buffPtr + crcOffset)); + Status = crc8_gen(buffPtr, dataLen, poly, &crc); + if (Status == SUCCESS) + { + if (crc == crc_comp) + { + return true; + } + else + { + return false; + } + } + else + { + return false; + } +} + +/*****************************************************************************/ +/** + * @brief CRC16 compare cheker + * + * @param buffPtr data buffer pointer. + * @param dataLen data length + * @param crcOffset byte offset of crc stored position. + * @param poly polynomials of crc + * + * @return true + * fasle + * + ******************************************************************************/ +bool crc16_check(uint8_t *buffPtr, uint32_t dataLen, uint32_t crcOffset, uint16_t poly) +{ + int Status = SUCCESS; + uint16_t crc_comp; + uint16_t crc; + if (dataLen == 0) + { + return false; + } + crc_comp = (uint16_t)(*(buffPtr + crcOffset)); + crc_comp |= (uint16_t)((*(buffPtr + crcOffset + 1)) << 8); + Status = crc16_gen(buffPtr, dataLen, poly, &crc); + if (Status == SUCCESS) + { + if (crc == crc_comp) + { + return true; + } + else + { + return false; + } + } + else + { + return false; + } +} + +/** @}*/ \ No newline at end of file diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/util/list.c b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/util/list.c new file mode 100644 index 0000000..46a57ba --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/util/list.c @@ -0,0 +1,886 @@ +/******************************************************************************* + * @file list.c + * @brief List library implementation + * @author Mihail Chindris (mihail.chindris@analog.com) +******************************************************************************** + * Copyright 2020(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ + +#include "list.h" +#include "error.h" +#include + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ + +/** + * @struct list_elem + * @brief Format of each element of the list + */ +struct list_elem +{ + /** User data */ + void *data; + /** Reference to previous element */ + struct list_elem *prev; + /** Reference to next element */ + struct list_elem *next; +}; + +/** + * @struct list_iterator + * @brief Structure used to iterate through the list + */ +struct iterator +{ + /** List reference */ + struct _list_desc *list; + /** Current element reference */ + struct list_elem *elem; +}; + +/** + * @struct _list_desc + * @brief List descriptor + */ +struct _list_desc +{ + /** Reference to first element in the list */ + struct list_elem *first; + /** Reference to last element in the list*/ + struct list_elem *last; + /** Number of elements in the list */ + uint32_t nb_elements; + /** Function used to compare elements */ + f_cmp comparator; + /** Number of current active iterators */ + uint32_t nb_iterators; + /** Internal list iterator */ + struct iterator l_it; +}; + +/** @brief Default function used to compare element in the list ( \ref f_cmp) */ +static int32_t default_comparator(void *data1, void *data2) +{ + return (int32_t)((int32_t *)data1 - (int32_t *)data2); +} + +/** + * @brief Creates a new list elements an configure its value + * @param data - To set list_elem.data + * @param prev - To set list_elem.prev + * @param next - To set list_elem.next + * @return Address of the new element or NULL if allocation fails. + */ +static inline struct list_elem *create_element(void *data, + struct list_elem *prev, + struct list_elem *next) +{ + struct list_elem *elem; + + elem = (struct list_elem *)calloc(1, sizeof(*elem)); + if (!elem) + return NULL; + elem->data = data; + elem->prev = prev; + elem->next = next; + + return (elem); +} + +/** + * @brief Updates the necesary link on the list elements to add or remove one + * @param prev - Low element + * @param elem - Middle element + * @param next - High element + */ +static inline void update_links(struct list_elem *prev, struct list_elem *elem, + struct list_elem *next) +{ + if (prev) + prev->next = elem ? elem : next; + if (elem) + { + elem->prev = prev; + elem->next = next; + } + if (next) + next->prev = elem ? elem : prev; +} + +/** + * @brief Update according to modification the list descriptor + * @param list - List reference + * @param new_first - New first element + * @param new_last - New last element + */ +static inline void update_desc(struct _list_desc *list, + struct list_elem *new_first, + struct list_elem *new_last) +{ + if (new_first == list->first) + { + list->last = new_last; + if (new_first == NULL || new_last == NULL) + list->first = new_last; + } + else + { /* if (new_last == list->last) */ + list->first = new_first; + if (new_last == NULL || new_first == NULL) + list->last = new_first; + } +} + +/** + * @brief Set the adapter functions acording to the adapter type + * @param ad - Reference of the adapter + * @param type - Type of the adapter + */ +static inline void set_adapter(struct list_desc *ad, enum adapter_type type) +{ + switch (type) + { + case LIST_PRIORITY_LIST: + ad->push = list_add_find; + ad->pop = list_get_first; + ad->top_next = list_read_first; + ad->back = list_read_last; + ad->swap = list_edit_first; + break; + case LIST_QUEUE: + ad->push = list_add_last; + ad->pop = list_get_first; + ad->top_next = list_read_first; + ad->back = list_read_last; + ad->swap = list_edit_first; + break; + case LIST_DEFAULT: + case LIST_STACK: + default: + ad->push = list_add_last; + ad->pop = list_get_last; + ad->top_next = list_read_last; + ad->back = list_read_first; + ad->swap = list_edit_last; + break; + } +} + +/** + * @brief Create a new empty list + * @param list_desc - Where to store the reference of the new created list + * @param type - Type of adapter to use. + * @param comparator - Used to compare item when using an ordered list or when + * using the \em find functions. + * @return + * - \ref SUCCESS : On success + * - \ref FAILURE : Otherwise + */ +int32_t list_init(struct list_desc **list_desc, enum adapter_type type, + f_cmp comparator) +{ + struct list_desc *l_desc; + struct _list_desc *list; + + if (!list_desc) + return FAILURE; + l_desc = (struct list_desc *)calloc(1, sizeof(*l_desc)); + if (!l_desc) + return FAILURE; + list = (struct _list_desc *)calloc(1, sizeof(*list)); + if (!list) + { + free(l_desc); + return FAILURE; + } + + *list_desc = l_desc; + l_desc->priv_desc = list; + list->comparator = comparator ? comparator : default_comparator; + + /* Configure wrapper */ + set_adapter(l_desc, type); + list->l_it.list = list; + + return SUCCESS; +} + +/** + * @brief Remove the created list. + * + * All its elements will be cleared and the data inside each will be lost. If + * not all iterators have been removed, the list will not be removed. + * @param list_desc - Reference to the list + * @return + * - \ref SUCCESS : On success + * - \ref FAILURE : Otherwise + */ +int32_t list_remove(struct list_desc *list_desc) +{ + void *data; + struct _list_desc *list; + + if (!list_desc) + return FAILURE; + + list = list_desc->priv_desc; + if (list->nb_iterators != 0) + return FAILURE; + + /* Remove all the elements */ + while (SUCCESS == list_get_first(list_desc, &data)) + ; + free(list_desc->priv_desc); + free(list_desc); + + return SUCCESS; +} + +/** + * @brief Get the number of elements inside the list + * @param list_desc - List reference + * @param out_size - Where to store the number of elements + * @return + * - \ref SUCCESS : On success + * - \ref FAILURE : Otherwise + */ +int32_t list_get_size(struct list_desc *list_desc, uint32_t *out_size) +{ + struct _list_desc *list; + + if (!list_desc || !out_size) + return FAILURE; + + list = list_desc->priv_desc; + *out_size = list->nb_elements; + + return SUCCESS; +} + +/** @brief Add element at the begining of the list. Refer to \ref f_add */ +int32_t list_add_first(struct list_desc *list_desc, void *data) +{ + struct list_elem *prev; + struct list_elem *next; + struct list_elem *elem; + struct _list_desc *list; + + if (!list_desc) + return FAILURE; + + list = list_desc->priv_desc; + + prev = NULL; + next = list->first; + elem = create_element(data, prev, next); + if (!elem) + return FAILURE; + + update_links(prev, elem, next); + + update_desc(list, elem, list->last); + + list->nb_elements++; + + return SUCCESS; +} + +/** @brief Add element at the end of the list. Refer to \ref f_add */ +int32_t list_add_last(struct list_desc *list_desc, void *data) +{ + struct list_elem *prev; + struct list_elem *next; + struct list_elem *elem; + struct _list_desc *list; + + if (!list_desc) + return FAILURE; + list = list_desc->priv_desc; + + prev = list->last; + next = NULL; + elem = create_element(data, prev, next); + if (!elem) + return FAILURE; + + update_links(prev, elem, next); + + update_desc(list, list->first, elem); + + list->nb_elements++; + + return SUCCESS; +} + +/** @brief Add element at the specified idx. Refer to \ref f_add */ +int32_t list_add_idx(struct list_desc *list_desc, void *data, uint32_t idx) +{ + struct _list_desc *list; + + if (!list_desc) + return FAILURE; + list = list_desc->priv_desc; + + /* If there are no elements the creation of an iterator will fail */ + if (list->nb_elements == 0 || idx == 0) + return list_add_first(list_desc, data); + if (list->nb_elements == idx) + return list_add_last(list_desc, data); + + list->l_it.elem = list->first; + if (SUCCESS != iterator_move(&(list->l_it), idx)) + return FAILURE; + + return iterator_insert(&(list->l_it), data, 0); +} + +/** @brief Add element in ascending order. Refer to \ref f_add */ +int32_t list_add_find(struct list_desc *list_desc, void *data) +{ + struct list_elem *elem; + struct _list_desc *list; + + if (!list_desc) + return FAILURE; + list = list_desc->priv_desc; + + /* Based on place iterator */ + elem = list->first; + while (elem) + { + if (0 < list->comparator(elem->data, data)) + break; + elem = elem->next; + } + if (elem == NULL) + { + list->l_it.elem = list->last; + return iterator_insert(&(list->l_it), data, 1); + } + else + { + list->l_it.elem = elem; + return iterator_insert(&(list->l_it), data, 0); + } +} + +/** @brief Edit the first element of the list. Refer to \ref f_edit */ +int32_t list_edit_first(struct list_desc *list_desc, void *new_data) +{ + struct _list_desc *list; + + if (!list_desc) + return FAILURE; + + list = list_desc->priv_desc; + list->first->data = new_data; + + return SUCCESS; +} + +/** @brief Edit the last element of the list. Refer to \ref f_edit */ +int32_t list_edit_last(struct list_desc *list_desc, void *new_data) +{ + struct _list_desc *list; + + if (!list_desc) + return FAILURE; + + list = list_desc->priv_desc; + list->last->data = new_data; + + return SUCCESS; +} + +/** @brief Edit the element at the specified idx. Refer to \ref f_edit */ +int32_t list_edit_idx(struct list_desc *list_desc, void *new_data, uint32_t idx) +{ + struct _list_desc *list; + + if (!list_desc) + return FAILURE; + list = list_desc->priv_desc; + + list->l_it.elem = list->first; + if (SUCCESS != iterator_move(&(list->l_it), idx)) + return FAILURE; + + return iterator_edit(&(list->l_it), new_data); +} + +/** @brief Edit the element which match with cmp_data. Refer to \ref f_edit */ +int32_t list_edit_find(struct list_desc *list_desc, void *new_data, + void *cmp_data) +{ + struct _list_desc *list; + + if (!list_desc) + return FAILURE; + list = list_desc->priv_desc; + + list->l_it.elem = list->first; + if (SUCCESS != iterator_find(&(list->l_it), cmp_data)) + return FAILURE; + + return iterator_edit(&(list->l_it), new_data); +} + +/** @brief Read the first element of the list. Refer to \ref f_read */ +int32_t list_read_first(struct list_desc *list_desc, void **data) +{ + struct _list_desc *list; + + if (!list_desc || !data) + return FAILURE; + + *data = NULL; + list = list_desc->priv_desc; + if (!list->first) + return FAILURE; + + *data = list->first->data; + + return SUCCESS; +} + +/** @brief Read the last element of the list. Refer to \ref f_read */ +int32_t list_read_last(struct list_desc *list_desc, void **data) +{ + struct _list_desc *list; + + if (!list_desc || !data) + return FAILURE; + + *data = NULL; + list = list_desc->priv_desc; + if (!list->last) + return FAILURE; + + *data = list->last->data; + + return SUCCESS; +} + +/** @brief Read the element at the specified idx. Refer to \ref f_read */ +int32_t list_read_idx(struct list_desc *list_desc, void **data, uint32_t idx) +{ + struct _list_desc *list; + + if (!list_desc || !data) + return FAILURE; + + *data = NULL; + list = list_desc->priv_desc; + if (!list) + return FAILURE; + + if (idx >= list->nb_elements) + return FAILURE; + + list->l_it.elem = list->first; + if (SUCCESS != iterator_move(&(list->l_it), idx)) + return FAILURE; + + return iterator_read(&(list->l_it), data); +} + +/** @brief Read the element which match with cmp_data. Refer to \ref f_read */ +int32_t list_read_find(struct list_desc *list_desc, void **data, + void *cmp_data) +{ + struct _list_desc *list; + + if (!list_desc || !data) + return FAILURE; + + *data = NULL; + list = list_desc->priv_desc; + if (!list) + return FAILURE; + + list = list_desc->priv_desc; + list->l_it.elem = list->first; + if (SUCCESS != iterator_find(&(list->l_it), cmp_data)) + return FAILURE; + + return iterator_read(&(list->l_it), data); +} + +/** @brief Read and delete the first element of the list. Refer to \ref f_get */ +int32_t list_get_first(struct list_desc *list_desc, void **data) +{ + struct list_elem *prev; + struct list_elem *next; + struct list_elem *elem; + struct _list_desc *list; + + if (!list_desc || !data) + return FAILURE; + + *data = NULL; + list = list_desc->priv_desc; + if (!list->nb_elements) + return FAILURE; + + elem = list->first; + prev = elem->prev; + next = elem->next; + + update_links(prev, NULL, next); + update_desc(list, next, list->last); + list->nb_elements--; + + *data = elem->data; + free(elem); + + return SUCCESS; +} + +/** @brief Read and delete the last element of the list. Refer to \ref f_get */ +int32_t list_get_last(struct list_desc *list_desc, void **data) +{ + struct list_elem *prev; + struct list_elem *next; + struct list_elem *elem; + struct _list_desc *list; + + if (!list_desc || !data) + return FAILURE; + + *data = NULL; + list = list_desc->priv_desc; + if (!list->nb_elements) + return FAILURE; + + elem = list->last; + prev = elem->prev; + next = elem->next; + + update_links(prev, NULL, next); + update_desc(list, list->first, prev); + list->nb_elements--; + + *data = elem->data; + free(elem); + + return SUCCESS; +} + +/** @brief Read and delete the element at idx. Refer to \ref f_get */ +int32_t list_get_idx(struct list_desc *list_desc, void **data, uint32_t idx) +{ + struct _list_desc *list; + + if (!list_desc || !data) + return FAILURE; + + *data = NULL; + list = list_desc->priv_desc; + list->l_it.elem = list->first; + if (SUCCESS != iterator_move(&(list->l_it), idx)) + return FAILURE; + + return iterator_get(&(list->l_it), data); +} + +/** + * @brief Read and delete the element which match with cmp_data. + * Refer to \ref f_get + */ +int32_t list_get_find(struct list_desc *list_desc, void **data, void *cmp_data) +{ + struct _list_desc *list; + + if (!list_desc || !data) + return FAILURE; + + *data = NULL; + list = list_desc->priv_desc; + list->l_it.elem = list->first; + if (SUCCESS != iterator_find(&(list->l_it), cmp_data)) + return FAILURE; + + return iterator_get(&(list->l_it), data); +} + +/** + * @brief Create a new iterator + * @param iter - Where to store the reference for the new iterator + * @param list_desc - Reference of the list the iterator will be used for + * @param start - If it is true the iterator will be positioned at the first + * element of the list, else it will be positioned at the last. + * @return + * - \ref SUCCESS : On success + * - \ref FAILURE : Otherwise + */ +int32_t iterator_init(struct iterator **iter, struct list_desc *list_desc, + bool start) +{ + struct iterator *it; + + if (!list_desc) + return FAILURE; + + it = (struct iterator *)calloc(1, sizeof(*it)); + if (!it) + return FAILURE; + it->list = list_desc->priv_desc; + it->list->nb_iterators++; + it->elem = start ? it->list->first : it->list->last; + *iter = it; + + return SUCCESS; +} + +/** + * @brief Remove the created iterator + * @param iter - Reference of the iterator + * @return + * - \ref SUCCESS : On success + * - \ref FAILURE : Otherwise + */ +int32_t iterator_remove(struct iterator *iter) +{ + struct iterator *it = iter; + + if (!it) + return FAILURE; + + it->list->nb_iterators--; + free(it); + + return SUCCESS; +} + +/** + * @brief Move the position of the iteration through the list. + * + * If the required position is outside the list, the call will fail and the + * iterator will keep its position. + * @param iter - Reference of the iterator + * @param steps - Number of positions to be move. If positive, it will be moved + * forward, otherwise backwords. + * @return + * - \ref SUCCESS : On success + * - \ref FAILURE : Otherwise + */ +int32_t iterator_move(struct iterator *iter, int32_t steps) +{ + struct iterator *it = iter; + struct list_elem *elem; + int32_t dir = (steps < 0) ? -1 : 1; + + if (!it) + return FAILURE; + + steps = abs(steps); + elem = it->elem; + while (steps > 0 && elem) + { + elem = dir > 0 ? elem->next : elem->prev; + steps--; + } + if (!elem) + return FAILURE; + + it->elem = elem; + + return SUCCESS; +} + +/** + * @brief Move the position of the iterator at the specified index of the list. + * + * @param iter - Reference of the iterator + * @param idx - Position in the list. If negative start counting backwords + * @return + * - \ref SUCCESS : On success + * - \ref FAILURE : Otherwise + */ +int32_t iterator_move_to_idx(struct iterator *iter, int32_t idx) +{ + struct list_elem *elem; + int32_t dir = (idx < 0) ? -1 : 1; + + if (!iter) + return FAILURE; + + idx = abs(idx); + elem = dir > 0 ? iter->list->first : iter->list->last; + while (idx > 0 && elem) + { + elem = dir > 0 ? elem->next : elem->prev; + idx--; + } + if (!elem) + return FAILURE; + + iter->elem = elem; + + return SUCCESS; +} + +/** + * @brief Place the iterator where cmp_data if found. + * @param iter - Reference to the iterator + * @param cmp_data - Data to be found + * @return + * - \ref SUCCESS : On success + * - \ref FAILURE : Otherwise + */ +int32_t iterator_find(struct iterator *iter, void *cmp_data) +{ + struct iterator *it = iter; + struct list_elem *elem; + + if (!it) + return FAILURE; + + elem = it->list->first; + while (elem) + { + if (0 == it->list->comparator(elem->data, cmp_data)) + { + it->elem = elem; + return SUCCESS; + } + elem = elem->next; + } + + return FAILURE; +} + +/** + * @brief Replace the data at the current position. Refer to \ref f_edit + */ +int32_t iterator_edit(struct iterator *iter, void *new_data) +{ + struct iterator *it = iter; + + if (!it) + return FAILURE; + + it->elem->data = new_data; + + return SUCCESS; +} + +/** + * @brief Read and remove the data at the current position. Refer to \ref f_get. + * + * If the current item is the last one, the iterator will be moved to the + * previous one. + */ +int32_t iterator_get(struct iterator *iter, void **data) +{ + struct iterator *it = iter; + struct list_elem *next; + + if (!it || !it->elem || !data) + return FAILURE; + + update_links(it->elem->prev, NULL, it->elem->next); + if (it->elem == it->list->first) + update_desc(it->list, it->elem->next, it->list->last); + else if (it->elem == it->list->last) + update_desc(it->list, it->list->first, it->elem->prev); + it->list->nb_elements--; + + *data = it->elem->data; + if (it->elem == it->list->last) + next = it->elem->prev; + else + next = it->elem->next; + free(it->elem); + it->elem = next; + + return SUCCESS; +} + +/** + * @brief Read the data at the current position. Refer to \ref f_read + */ +int32_t iterator_read(struct iterator *iter, void **data) +{ + struct iterator *it = iter; + + if (!it || !it->elem || !data) + return FAILURE; + + *data = it->elem->data; + + return SUCCESS; +} + +/** + * @brief Insert an item in the list. Refer to \ref f_add + * @param iter + * @param data + * @param after - If true, the item will be inserted after the current position. + * Otherwise it will be inserted before. + */ +int32_t iterator_insert(struct iterator *iter, void *data, bool after) +{ + struct iterator *it = iter; + struct list_elem *elem; + struct list_desc list_desc; + + if (!it) + return FAILURE; + + list_desc.priv_desc = iter->list; + if (after && it->elem == it->list->last) + return list_add_last(&list_desc, data); + if (!after && it->elem == it->list->first) + return list_add_first(&list_desc, data); + + if (after) + elem = create_element(data, it->elem, it->elem->next); + else + elem = create_element(data, it->elem->prev, it->elem); + if (!elem) + return FAILURE; + + update_links(elem->prev, elem, elem->next); + + it->list->nb_elements++; + + return SUCCESS; +} diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/util/tables.txt b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/util/tables.txt new file mode 100644 index 0000000..b3bff8c --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/util/tables.txt @@ -0,0 +1,231 @@ +Generating CRC table for crc8-31-lsb + +0x00, 0x5E, 0xBC, 0xE2, 0x61, 0x3F, 0xDD, 0x83, +0xC2, 0x9C, 0x7E, 0x20, 0xA3, 0xFD, 0x1F, 0x41, +0x9D, 0xC3, 0x21, 0x7F, 0xFC, 0xA2, 0x40, 0x1E, +0x5F, 0x01, 0xE3, 0xBD, 0x3E, 0x60, 0x82, 0xDC, +0x23, 0x7D, 0x9F, 0xC1, 0x42, 0x1C, 0xFE, 0xA0, +0xE1, 0xBF, 0x5D, 0x03, 0x80, 0xDE, 0x3C, 0x62, +0xBE, 0xE0, 0x02, 0x5C, 0xDF, 0x81, 0x63, 0x3D, +0x7C, 0x22, 0xC0, 0x9E, 0x1D, 0x43, 0xA1, 0xFF, +0x46, 0x18, 0xFA, 0xA4, 0x27, 0x79, 0x9B, 0xC5, +0x84, 0xDA, 0x38, 0x66, 0xE5, 0xBB, 0x59, 0x07, +0xDB, 0x85, 0x67, 0x39, 0xBA, 0xE4, 0x06, 0x58, +0x19, 0x47, 0xA5, 0xFB, 0x78, 0x26, 0xC4, 0x9A, +0x65, 0x3B, 0xD9, 0x87, 0x04, 0x5A, 0xB8, 0xE6, +0xA7, 0xF9, 0x1B, 0x45, 0xC6, 0x98, 0x7A, 0x24, +0xF8, 0xA6, 0x44, 0x1A, 0x99, 0xC7, 0x25, 0x7B, +0x3A, 0x64, 0x86, 0xD8, 0x5B, 0x05, 0xE7, 0xB9, +0x8C, 0xD2, 0x30, 0x6E, 0xED, 0xB3, 0x51, 0x0F, +0x4E, 0x10, 0xF2, 0xAC, 0x2F, 0x71, 0x93, 0xCD, +0x11, 0x4F, 0xAD, 0xF3, 0x70, 0x2E, 0xCC, 0x92, +0xD3, 0x8D, 0x6F, 0x31, 0xB2, 0xEC, 0x0E, 0x50, +0xAF, 0xF1, 0x13, 0x4D, 0xCE, 0x90, 0x72, 0x2C, +0x6D, 0x33, 0xD1, 0x8F, 0x0C, 0x52, 0xB0, 0xEE, +0x32, 0x6C, 0x8E, 0xD0, 0x53, 0x0D, 0xEF, 0xB1, +0xF0, 0xAE, 0x4C, 0x12, 0x91, 0xCF, 0x2D, 0x73, +0xCA, 0x94, 0x76, 0x28, 0xAB, 0xF5, 0x17, 0x49, +0x08, 0x56, 0xB4, 0xEA, 0x69, 0x37, 0xD5, 0x8B, +0x57, 0x09, 0xEB, 0xB5, 0x36, 0x68, 0x8A, 0xD4, +0x95, 0xCB, 0x29, 0x77, 0xF4, 0xAA, 0x48, 0x16, +0xE9, 0xB7, 0x55, 0x0B, 0x88, 0xD6, 0x34, 0x6A, +0x2B, 0x75, 0x97, 0xC9, 0x4A, 0x14, 0xF6, 0xA8, +0x74, 0x2A, 0xC8, 0x96, 0x15, 0x4B, 0xA9, 0xF7, +0xB6, 0xE8, 0x0A, 0x54, 0xD7, 0x89, 0x6B, 0x35, + + +Generating CRC table for crc8-31-msb + +0x00, 0x31, 0x62, 0x53, 0xC4, 0xF5, 0xA6, 0x97, +0xB9, 0x88, 0xDB, 0xEA, 0x7D, 0x4C, 0x1F, 0x2E, +0x43, 0x72, 0x21, 0x10, 0x87, 0xB6, 0xE5, 0xD4, +0xFA, 0xCB, 0x98, 0xA9, 0x3E, 0x0F, 0x5C, 0x6D, +0x86, 0xB7, 0xE4, 0xD5, 0x42, 0x73, 0x20, 0x11, +0x3F, 0x0E, 0x5D, 0x6C, 0xFB, 0xCA, 0x99, 0xA8, +0xC5, 0xF4, 0xA7, 0x96, 0x01, 0x30, 0x63, 0x52, +0x7C, 0x4D, 0x1E, 0x2F, 0xB8, 0x89, 0xDA, 0xEB, +0x3D, 0x0C, 0x5F, 0x6E, 0xF9, 0xC8, 0x9B, 0xAA, +0x84, 0xB5, 0xE6, 0xD7, 0x40, 0x71, 0x22, 0x13, +0x7E, 0x4F, 0x1C, 0x2D, 0xBA, 0x8B, 0xD8, 0xE9, +0xC7, 0xF6, 0xA5, 0x94, 0x03, 0x32, 0x61, 0x50, +0xBB, 0x8A, 0xD9, 0xE8, 0x7F, 0x4E, 0x1D, 0x2C, +0x02, 0x33, 0x60, 0x51, 0xC6, 0xF7, 0xA4, 0x95, +0xF8, 0xC9, 0x9A, 0xAB, 0x3C, 0x0D, 0x5E, 0x6F, +0x41, 0x70, 0x23, 0x12, 0x85, 0xB4, 0xE7, 0xD6, +0x7A, 0x4B, 0x18, 0x29, 0xBE, 0x8F, 0xDC, 0xED, +0xC3, 0xF2, 0xA1, 0x90, 0x07, 0x36, 0x65, 0x54, +0x39, 0x08, 0x5B, 0x6A, 0xFD, 0xCC, 0x9F, 0xAE, +0x80, 0xB1, 0xE2, 0xD3, 0x44, 0x75, 0x26, 0x17, +0xFC, 0xCD, 0x9E, 0xAF, 0x38, 0x09, 0x5A, 0x6B, +0x45, 0x74, 0x27, 0x16, 0x81, 0xB0, 0xE3, 0xD2, +0xBF, 0x8E, 0xDD, 0xEC, 0x7B, 0x4A, 0x19, 0x28, +0x06, 0x37, 0x64, 0x55, 0xC2, 0xF3, 0xA0, 0x91, +0x47, 0x76, 0x25, 0x14, 0x83, 0xB2, 0xE1, 0xD0, +0xFE, 0xCF, 0x9C, 0xAD, 0x3A, 0x0B, 0x58, 0x69, +0x04, 0x35, 0x66, 0x57, 0xC0, 0xF1, 0xA2, 0x93, +0xBD, 0x8C, 0xDF, 0xEE, 0x79, 0x48, 0x1B, 0x2A, +0xC1, 0xF0, 0xA3, 0x92, 0x05, 0x34, 0x67, 0x56, +0x78, 0x49, 0x1A, 0x2B, 0xBC, 0x8D, 0xDE, 0xEF, +0x82, 0xB3, 0xE0, 0xD1, 0x46, 0x77, 0x24, 0x15, +0x3B, 0x0A, 0x59, 0x68, 0xFF, 0xCE, 0x9D, 0xAC, + + +Generating CRC table for crc16-8005-lsb + +0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241, +0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440, +0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40, +0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841, +0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40, +0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41, +0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641, +0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040, +0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240, +0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441, +0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41, +0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840, +0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41, +0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40, +0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640, +0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041, +0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240, +0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441, +0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41, +0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840, +0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41, +0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40, +0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640, +0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041, +0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241, +0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440, +0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40, +0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841, +0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40, +0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41, +0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641, +0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040, + + +Generating CRC table for crc16-8005-msb + +0x0000, 0x8005, 0x800F, 0x000A, 0x801B, 0x001E, 0x0014, 0x8011, +0x8033, 0x0036, 0x003C, 0x8039, 0x0028, 0x802D, 0x8027, 0x0022, +0x8063, 0x0066, 0x006C, 0x8069, 0x0078, 0x807D, 0x8077, 0x0072, +0x0050, 0x8055, 0x805F, 0x005A, 0x804B, 0x004E, 0x0044, 0x8041, +0x80C3, 0x00C6, 0x00CC, 0x80C9, 0x00D8, 0x80DD, 0x80D7, 0x00D2, +0x00F0, 0x80F5, 0x80FF, 0x00FA, 0x80EB, 0x00EE, 0x00E4, 0x80E1, +0x00A0, 0x80A5, 0x80AF, 0x00AA, 0x80BB, 0x00BE, 0x00B4, 0x80B1, +0x8093, 0x0096, 0x009C, 0x8099, 0x0088, 0x808D, 0x8087, 0x0082, +0x8183, 0x0186, 0x018C, 0x8189, 0x0198, 0x819D, 0x8197, 0x0192, +0x01B0, 0x81B5, 0x81BF, 0x01BA, 0x81AB, 0x01AE, 0x01A4, 0x81A1, +0x01E0, 0x81E5, 0x81EF, 0x01EA, 0x81FB, 0x01FE, 0x01F4, 0x81F1, +0x81D3, 0x01D6, 0x01DC, 0x81D9, 0x01C8, 0x81CD, 0x81C7, 0x01C2, +0x0140, 0x8145, 0x814F, 0x014A, 0x815B, 0x015E, 0x0154, 0x8151, +0x8173, 0x0176, 0x017C, 0x8179, 0x0168, 0x816D, 0x8167, 0x0162, +0x8123, 0x0126, 0x012C, 0x8129, 0x0138, 0x813D, 0x8137, 0x0132, +0x0110, 0x8115, 0x811F, 0x011A, 0x810B, 0x010E, 0x0104, 0x8101, +0x8303, 0x0306, 0x030C, 0x8309, 0x0318, 0x831D, 0x8317, 0x0312, +0x0330, 0x8335, 0x833F, 0x033A, 0x832B, 0x032E, 0x0324, 0x8321, +0x0360, 0x8365, 0x836F, 0x036A, 0x837B, 0x037E, 0x0374, 0x8371, +0x8353, 0x0356, 0x035C, 0x8359, 0x0348, 0x834D, 0x8347, 0x0342, +0x03C0, 0x83C5, 0x83CF, 0x03CA, 0x83DB, 0x03DE, 0x03D4, 0x83D1, +0x83F3, 0x03F6, 0x03FC, 0x83F9, 0x03E8, 0x83ED, 0x83E7, 0x03E2, +0x83A3, 0x03A6, 0x03AC, 0x83A9, 0x03B8, 0x83BD, 0x83B7, 0x03B2, +0x0390, 0x8395, 0x839F, 0x039A, 0x838B, 0x038E, 0x0384, 0x8381, +0x0280, 0x8285, 0x828F, 0x028A, 0x829B, 0x029E, 0x0294, 0x8291, +0x82B3, 0x02B6, 0x02BC, 0x82B9, 0x02A8, 0x82AD, 0x82A7, 0x02A2, +0x82E3, 0x02E6, 0x02EC, 0x82E9, 0x02F8, 0x82FD, 0x82F7, 0x02F2, +0x02D0, 0x82D5, 0x82DF, 0x02DA, 0x82CB, 0x02CE, 0x02C4, 0x82C1, +0x8243, 0x0246, 0x024C, 0x8249, 0x0258, 0x825D, 0x8257, 0x0252, +0x0270, 0x8275, 0x827F, 0x027A, 0x826B, 0x026E, 0x0264, 0x8261, +0x0220, 0x8225, 0x822F, 0x022A, 0x823B, 0x023E, 0x0234, 0x8231, +0x8213, 0x0216, 0x021C, 0x8219, 0x0208, 0x820D, 0x8207, 0x0202, + + +Generating CRC table for crc16-1021-lsb + +0x0000, 0x1189, 0x2312, 0x329B, 0x4624, 0x57AD, 0x6536, 0x74BF, +0x8C48, 0x9DC1, 0xAF5A, 0xBED3, 0xCA6C, 0xDBE5, 0xE97E, 0xF8F7, +0x1081, 0x0108, 0x3393, 0x221A, 0x56A5, 0x472C, 0x75B7, 0x643E, +0x9CC9, 0x8D40, 0xBFDB, 0xAE52, 0xDAED, 0xCB64, 0xF9FF, 0xE876, +0x2102, 0x308B, 0x0210, 0x1399, 0x6726, 0x76AF, 0x4434, 0x55BD, +0xAD4A, 0xBCC3, 0x8E58, 0x9FD1, 0xEB6E, 0xFAE7, 0xC87C, 0xD9F5, +0x3183, 0x200A, 0x1291, 0x0318, 0x77A7, 0x662E, 0x54B5, 0x453C, +0xBDCB, 0xAC42, 0x9ED9, 0x8F50, 0xFBEF, 0xEA66, 0xD8FD, 0xC974, +0x4204, 0x538D, 0x6116, 0x709F, 0x0420, 0x15A9, 0x2732, 0x36BB, +0xCE4C, 0xDFC5, 0xED5E, 0xFCD7, 0x8868, 0x99E1, 0xAB7A, 0xBAF3, +0x5285, 0x430C, 0x7197, 0x601E, 0x14A1, 0x0528, 0x37B3, 0x263A, +0xDECD, 0xCF44, 0xFDDF, 0xEC56, 0x98E9, 0x8960, 0xBBFB, 0xAA72, +0x6306, 0x728F, 0x4014, 0x519D, 0x2522, 0x34AB, 0x0630, 0x17B9, +0xEF4E, 0xFEC7, 0xCC5C, 0xDDD5, 0xA96A, 0xB8E3, 0x8A78, 0x9BF1, +0x7387, 0x620E, 0x5095, 0x411C, 0x35A3, 0x242A, 0x16B1, 0x0738, +0xFFCF, 0xEE46, 0xDCDD, 0xCD54, 0xB9EB, 0xA862, 0x9AF9, 0x8B70, +0x8408, 0x9581, 0xA71A, 0xB693, 0xC22C, 0xD3A5, 0xE13E, 0xF0B7, +0x0840, 0x19C9, 0x2B52, 0x3ADB, 0x4E64, 0x5FED, 0x6D76, 0x7CFF, +0x9489, 0x8500, 0xB79B, 0xA612, 0xD2AD, 0xC324, 0xF1BF, 0xE036, +0x18C1, 0x0948, 0x3BD3, 0x2A5A, 0x5EE5, 0x4F6C, 0x7DF7, 0x6C7E, +0xA50A, 0xB483, 0x8618, 0x9791, 0xE32E, 0xF2A7, 0xC03C, 0xD1B5, +0x2942, 0x38CB, 0x0A50, 0x1BD9, 0x6F66, 0x7EEF, 0x4C74, 0x5DFD, +0xB58B, 0xA402, 0x9699, 0x8710, 0xF3AF, 0xE226, 0xD0BD, 0xC134, +0x39C3, 0x284A, 0x1AD1, 0x0B58, 0x7FE7, 0x6E6E, 0x5CF5, 0x4D7C, +0xC60C, 0xD785, 0xE51E, 0xF497, 0x8028, 0x91A1, 0xA33A, 0xB2B3, +0x4A44, 0x5BCD, 0x6956, 0x78DF, 0x0C60, 0x1DE9, 0x2F72, 0x3EFB, +0xD68D, 0xC704, 0xF59F, 0xE416, 0x90A9, 0x8120, 0xB3BB, 0xA232, +0x5AC5, 0x4B4C, 0x79D7, 0x685E, 0x1CE1, 0x0D68, 0x3FF3, 0x2E7A, +0xE70E, 0xF687, 0xC41C, 0xD595, 0xA12A, 0xB0A3, 0x8238, 0x93B1, +0x6B46, 0x7ACF, 0x4854, 0x59DD, 0x2D62, 0x3CEB, 0x0E70, 0x1FF9, +0xF78F, 0xE606, 0xD49D, 0xC514, 0xB1AB, 0xA022, 0x92B9, 0x8330, +0x7BC7, 0x6A4E, 0x58D5, 0x495C, 0x3DE3, 0x2C6A, 0x1EF1, 0x0F78, + + +Generating CRC table for crc16-1021-msb + +0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7, +0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF, +0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6, +0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE, +0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485, +0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D, +0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4, +0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC, +0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823, +0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B, +0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12, +0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A, +0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41, +0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49, +0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70, +0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78, +0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F, +0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067, +0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E, +0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256, +0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D, +0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, +0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C, +0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634, +0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB, +0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3, +0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A, +0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92, +0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9, +0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1, +0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8, +0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0, + + + +#define CRC_BIT_NUM 8u/16u/32u/64u +#define BITS_IN_BYTE 8u +uint8_t dataBuff[ARRAY_SIZE] = { 0x32, 0x33, ...; +uint8_t/uint16_t/uint32_t crc_val = 0x0; +// LSB +for(int i = 0; i < sizeof(dataBuff); i++) +{ + crc_val = (crc_val >> BITS_IN_BYTE) ^ crc_lsb_lut[(uint8)(crc_val^dataBuff[i])]; +} +// MSB +for(int i = 0; i < sizeof(dataBuff); i++) +{ + crc_val = (crc_val << BITS_IN_BYTE) ^ crc_msb_lut[(uint8)((crc_val>>8)^dataBuff[i])]; +} \ No newline at end of file diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/util/util.c b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/util/util.c new file mode 100644 index 0000000..87c8961 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/util/util.c @@ -0,0 +1,403 @@ +/*****************************************************************************/ +/** + * @file util.c + * @author FanHao (hao_fan_bit_ee@163.com) + * @brief Utility functions implementation file + * @version 0.0 + * @date 2023-05-06 + * + * @copyright Copyright(c) 2024 Beijing Institute of Technology.\n + * Lab of Communication and Network + * + ******************************************************************************/ + +/***************************** Include Files **********************************/ + +/** + * @addtogroup Utility + * @{ + */ + +#include +#include +// #include +#include "util.h" +#include "error.h" + +/************************** Functions Implementation **************************/ +#ifdef __BITSWAP_TABLE +static uint8_t byte_flipLR[256] = +{ + 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, + 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0, + 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, + 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8, + 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4, + 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4, + 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, + 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC, + 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2, + 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2, + 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, + 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA, + 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, + 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6, + 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE, + 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE, + 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1, + 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1, + 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, + 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9, + 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5, + 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5, + 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED, + 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD, + 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3, + 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3, + 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, + 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB, + 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7, + 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7, + 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, + 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF +}; +#endif + +/** + * @brief Write a 32bit word to specific memory address + */ +inline void IO_Out32(uintptr_t addr, uint32_t value) +{ + volatile uint32_t *localAddr = (volatile uint32_t *)addr; + *localAddr = value; +} + +/** + * @brief Read a 32bit word from specific memory address + */ +inline uint32_t IO_In32(uintptr_t addr) +{ + return *(volatile uint32_t *)addr; +} + +/** + * @brief Swap a byte word bit-wise + */ +uint8_t byte_bit_swap(uint8_t byte) +{ +#ifdef __BITSWAP_TABLE + return byte_flipLR[byte]; +#else + return bit_swap_constant_8(byte); +#endif +} + +/** + * @brief Swap 32bit word bit-wise + */ +uint32_t word_bit_swap(uint32_t word) +{ +#ifdef __BITSWAP_TABLE + uint32_t rv_word = (byte_flipLR[word & 0xff] << 24) | + (byte_flipLR[(word >> 8) & 0xff] << 16) | + (byte_flipLR[(word >> 16) & 0xff] << 8) | + (byte_flipLR[(word >> 24) & 0xff]); + return rv_word; +#else + word = (((word & 0xaaaaaaaa) >> 1) | ((word & 0x55555555) << 1)); + word = (((word & 0xcccccccc) >> 2) | ((word & 0x33333333) << 2)); + word = (((word & 0xf0f0f0f0) >> 4) | ((word & 0x0f0f0f0f) << 4)); + word = (((word & 0xff00ff00) >> 8) | ((word & 0x00ff00ff) << 8)); + return ((word >> 16) | (word << 16)); +#endif +} + +/** + * @brief Count ones in an 32bit word + */ +uint32_t count_ones(uint32_t word) +{ +#ifdef __GNUC__ + return __builtin_popcount(word); +#else + uint32_t one_count = 0; + while (word) + { + if (word & 0x00000001) + one_count++; + word >>= 1; + } + return one_count; +#endif +} + +/** + * @brief Convert fix ;oint number to float number + */ +double fix2double(int32_t val, uint8_t frac_bits) +{ + return (((double)val) / (BIT(frac_bits))); +} + +/** + * @brief Find first set bit in word. + */ +uint32_t find_first_set_bit(uint32_t word) +{ +#ifdef __GNUC__ + if (word != 0) + { + return __builtin_ctz(word); + } + else + { + return 32; + } +#else + uint32_t first_set_bit = 0; + + while (word) + { + if (word & 0x1) + return first_set_bit; + word >>= 1; + first_set_bit++; + } + + return 32; +#endif +} + +/** + * @brief Find last set bit in word. + */ +uint32_t find_last_set_bit(uint32_t word) +{ +#ifdef __GNUC__ + if (word != 0) + { + return (31 - __builtin_clz(word)); + } + else + { + return 32; + } +#else + uint32_t bit = 0; + uint32_t last_set_bit = 32; + + while (word) + { + if (word & 0x1) + last_set_bit = bit; + word >>= 1; + bit++; + } + + return last_set_bit; +#endif +} + +/** + * @brief Locate the closest element in an array. + */ +uint32_t find_closest(int32_t val, + const int32_t *array, + uint32_t size) +{ + int32_t diff = abs(array[0] - val); + uint32_t ret = 0; + uint32_t i; + + for (i = 1; i < size; i++) + { + if (abs(array[i] - val) < diff) + { + diff = abs(array[i] - val); + ret = i; + } + } + + return ret; +} + +/** + * @brief Shift the value and apply the specified mask. + */ +uint32_t field_prep(uint32_t mask, uint32_t val) +{ + return (val << find_first_set_bit(mask)) & mask; +} + +/** + * @brief Get a field specified by a mask from a word. + */ +uint32_t field_get(uint32_t mask, uint32_t word) +{ + return (word & mask) >> find_first_set_bit(mask); +} + +/** + * @brief Log base 2 of the given number. + */ +int32_t log_base_2(uint32_t x) +{ + return find_last_set_bit(x); +} + +/** + * @brief Find greatest common divisor of the given two numbers. + */ +uint32_t greatest_common_divisor(uint32_t a, + uint32_t b) +{ + uint32_t div; + uint32_t common_div = 1; + + if ((a == 0) || (b == 0)) + return max(a, b); + + for (div = 1; (div <= a) && (div <= b); div++) + if (!(a % div) && !(b % div)) + common_div = div; + + return common_div; +} + +/** + * @brief Calculate best rational approximation for a given fraction. + */ +void rational_best_approximation(uint32_t given_numerator, + uint32_t given_denominator, + uint32_t max_numerator, + uint32_t max_denominator, + uint32_t *best_numerator, + uint32_t *best_denominator) +{ + uint32_t gcd; + + gcd = greatest_common_divisor(given_numerator, given_denominator); + + *best_numerator = given_numerator / gcd; + *best_denominator = given_denominator / gcd; + + if ((*best_numerator > max_numerator) || + (*best_denominator > max_denominator)) + { + *best_numerator = 0; + *best_denominator = 0; + } +} + +/** + * @brief Calculate the number of set bits. + */ +uint32_t hweight8(uint32_t word) +{ + uint32_t count = 0; + + while (word) + { + if (word & 0x1) + count++; + word >>= 1; + } + + return count; +} + +/** + * @brief Calculate the quotient and the remainder of an integer division. + */ +uint64_t do_div(uint64_t *n, + uint64_t base) +{ + uint64_t mod = 0; + + mod = *n % base; + *n = *n / base; + + return mod; +} + +/** + * @brief Unsigned 64bit divide with 64bit divisor and remainder + */ +uint64_t div64_u64_rem(uint64_t dividend, uint64_t divisor, uint64_t *remainder) +{ + *remainder = dividend % divisor; + + return dividend / divisor; +} + +/** + * @brief Unsigned 64bit divide with 32bit divisor with remainder + */ +uint64_t div_u64_rem(uint64_t dividend, uint32_t divisor, uint32_t *remainder) +{ + *remainder = do_div(÷nd, divisor); + + return dividend; +} + +/** + * @brief Signed 64bit divide with 32bit divisor with remainder + */ +int64_t div_s64_rem(int64_t dividend, int32_t divisor, int32_t *remainder) +{ + *remainder = dividend % divisor; + return dividend / divisor; +} + +/** + * @brief Unsigned 64bit divide with 32bit divisor + */ +uint64_t div_u64(uint64_t dividend, uint32_t divisor) +{ + uint32_t remainder; + + return div_u64_rem(dividend, divisor, &remainder); +} + +/** + * @brief Signed 64bit divide with 32bit divisor + */ +int64_t div_s64(int64_t dividend, int32_t divisor) +{ + int32_t remainder; + return div_s64_rem(dividend, divisor, &remainder); +} + +/** + * @brief Converts from string to int32_t + * @param *str + * @return int32_t + */ +int32_t str_to_int32(const char *str) +{ + char *end; + int32_t value = strtol(str, &end, 0); + + if (end == str) + return FAILURE; + else + return value; +} + +/** + * @brief Converts from string to uint32_t + * @param *str + * @return uint32_t + */ +uint32_t srt_to_uint32(const char *str) +{ + char *end; + uint32_t value = strtoul(str, &end, 0); + + if (end == str) + return FAILURE; + else + return value; +} + +/** @} */ \ No newline at end of file diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/xilinx_io.c b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/xilinx_io.c new file mode 100644 index 0000000..da948cd --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/xilinx_io.c @@ -0,0 +1,160 @@ + +#include "xilinx_io.h" + +static XSpiPs SpiInstance; +static XGpioPs Gpio; /* The driver instance for GPIO Device. */ +static int spi_select_value=0; + +int SpiPsInit(u16 SpiDeviceId){ + int Status; + XSpiPs_Config *SpiConfig; + /* + * Initialize the SPI driver so that it's ready to use + */ + SpiConfig = XSpiPs_LookupConfig(SpiDeviceId); + if (NULL == SpiConfig) { + return XST_FAILURE; + } + Status = XSpiPs_CfgInitialize((&SpiInstance), SpiConfig, + SpiConfig->BaseAddress); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Perform a self-test to check hardware build + */ + Status = XSpiPs_SelfTest((&SpiInstance)); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + /* + * The SPI device is a slave by default and the clock phase + * have to be set according to its master. In this example, CPOL is set + * to quiescent high and CPHA is set to 1. + */ + + XSpiPs_SetOptions((&SpiInstance), (XSPIPS_CR_CPHA_MASK) | + XSPIPS_MASTER_OPTION | + XSPIPS_FORCE_SSELECT_OPTION); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + XSpiPs_SetClkPrescaler((&SpiInstance), XSPIPS_CLK_PRESCALE_8); + /* + * Set the Rx FIFO Threshold to the Max Data + */ +// XSpiPs_SetRXWatermark((&SpiInstance),MAX_DATA); + /* + * Enable the device. + */ + XSpiPs_Enable((&SpiInstance)); + +return XST_SUCCESS; +} + +int cx9261a_write_cx(int addr , int value) +{ + Xil_Out32(AXI4_LITE1_SPI_BASEADDR+addr*4,value); + return 1; +} + +int cx9261a_read_cx(int addr) +{ + return Xil_In32(AXI4_LITE1_SPI_BASEADDR+addr*4); +} + +//int SpiPs_write_read(u8 cmd, u16 addr,u8 data,u8 * rx_data){ +int SpiPs_write_read(u8 * data,u8 * rx_data){ + int Status; + u8 rx_buffer[3]; + + if(spi_select_value == 0){ + rx_buffer[0]= *data; + rx_buffer[1]= *(data+1); + rx_buffer[2]= *(data+2); + if(rx_buffer[0] >= 128){ + cx9261a_write_cx((rx_buffer[0]-128)*256+rx_buffer[1],rx_buffer[2]); + }else{ + *rx_data=cx9261a_read_cx(rx_buffer[0]*256+rx_buffer[1]); + } + }else{ + + XSpiPs_SetSlaveSelect((&SpiInstance),0x00); + + Status = XSpiPs_PolledTransfer((&SpiInstance),data,rx_buffer,3); + + *rx_data = rx_buffer[2]; + + } + +return 0; +} + +int SpiPs_write_read1(u16 addr,u8 data,u8 * rx_data){ + u8 rx_data1; + u16 temp; + u8 rx_buffer[3]; + + temp= addr&0x00ff; + rx_buffer[0]= temp/256+128; + rx_buffer[1]= addr&0x00ff; + rx_buffer[2]= data; + + if(spi_select_value == 0){ + cx9261a_write_cx(addr,data); + }else{ + + SpiPs_write_read((u8 *)&rx_buffer,&rx_data1); + *rx_data = rx_data1; + } + +return 0; +} +int SpiPs_write_read2(u16 addr,u8 data,u8 * rx_data){ + u8 rx_data1; + u16 temp; + u8 rx_buffer[3]; + + temp= addr&0x00ff; + rx_buffer[0]= temp/256; + rx_buffer[1]= addr&0x00ff; + rx_buffer[2]= data; + + if(spi_select_value == 0){ + *rx_data=cx9261a_read_cx(addr); + }else{ + SpiPs_write_read((u8 *)&rx_buffer,&rx_data1); + *rx_data = rx_data1; + } + +return 0; +} +int GpioInit(u16 DeviceId) +{ + int Status; + XGpioPs_Config *ConfigPtr; + /* Initialize the GPIO driver. */ + ConfigPtr = XGpioPs_LookupConfig(DeviceId); + Status = XGpioPs_CfgInitialize(&Gpio, ConfigPtr, + ConfigPtr->BaseAddr); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + return XST_SUCCESS; +} + +int GpioSetPinDir(u32 Pin,u32 Direction){ + XGpioPs_SetDirectionPin((&Gpio),GPIO_EMIO_OFFSET + Pin,Direction); + return 0; +} +int GpioWritePin(u32 Pin,u32 data){ + XGpioPs_SetOutputEnablePin(&Gpio, GPIO_EMIO_OFFSET + Pin, 1); + XGpioPs_WritePin((&Gpio),GPIO_EMIO_OFFSET + Pin,data); + return 0; +} + +int GpioReadPin(u32 Pin){ + return XGpioPs_ReadPin((&Gpio),GPIO_EMIO_OFFSET + Pin); +} + diff --git a/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/xilinx_io.h b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/xilinx_io.h new file mode 100644 index 0000000..91a84d8 --- /dev/null +++ b/cx9261a_demo_cmos_20240513/vitis_classic_autobuild/source_cx9261a_api_lib_c/xilinx_io.h @@ -0,0 +1,92 @@ +/* + * xilinx_io.h + * + * Created on: 2021Äê9ÔÂ6ÈÕ + * Author: cxlab + */ + +#ifndef SRC_XILINX_IO_H_ +#define SRC_XILINX_IO_H_ + + +#include "xspips.h" /* SPI device driver */ +#include "xgpiops.h" +#include "xparameters.h" + +//#define DBGLOG +#define MAX_DATA 100 +#define SPI_WRITE 0x80 +#define SPI_READ 0x00 +#define GPIO_DIR_INPUT 0x00 +#define GPIO_DIR_OUTPUT 0x01 +#define GPIO_EMIO_OFFSET 54 + +#define TX_EN 0x08 +#define RX_EN 0x07 +#define GPIO_1 0x06 +#define GPIO_0 0x05 + +#define NRST 0 +#define ENABLE_TRX1 1 +#define ENABLE_TRX2 2 +#define ENABLE_TRX3 3 +#define TXNRX_TRX1 4 +#define TXNRX_TRX2 5 +#define TXNRX_RX3 6 + +#define aresetn_0 33 +#define rst 34 +#define tr_sel 35 +#define tdd_fdd_sel 36 +#define r1t1_r2t2_sel 37 +#define sp_dp_sel 38 +#define aresetn_1 39 +#define aresetn_2 40 +#define hop 41 +#define cx3e04_rstn 42 +#define spi_select 46 +//#define debug_mode 63 + +#define INTER_SIG3 0x03//dma_axis_rx_rstn +#define INTER_SIG2 0x02//frame_pattern +#define INTER_SIG1 0x01//mode_sel_async +#define INTER_SIG0 0x00//rst_async + +#define SPI_DEVICE_ID XPAR_XQSPIPS_0_DEVICE_ID +#define GPIO_DEVICE_ID XPAR_PS7_GPIO_0_DEVICE_ID + +#define AXI_DMA_DEVCIE_ID0 XPAR_AXI_DMA_0_DEVICE_ID +#define AXI_DMA_DEVCIE_ID1 XPAR_AXI_DMA_1_DEVICE_ID +#define AXI_DMA_DEVCIE_ID2 XPAR_AXI_DMA_2_DEVICE_ID + +#define BROM_BASEADDR XPAR_M08_AXI_0_BASEADDR + +#define AXI4_LITE0_SPI_BASEADDR XPAR_AXI4_LITE_SPI_0_BASEADDR +#define AXI4_LITE1_SPI_BASEADDR XPAR_AXI4_LITE_SPI_1_BASEADDR +#define BRAM_BASEADDR XPAR_AXI_BRAM_CTRL_0_S_AXI_BASEADDR +#define BRAM_BASEADDR_1 XPAR_AXI_BRAM_CTRL_1_S_AXI_BASEADDR +#define PACKER_BASEADDR0 XPAR_AXIS_ADC_DATA_PACKER_0_S00_AXI_BASEADDR +#define PACKER_BASEADDR1 XPAR_AXIS_ADC_DATA_PACKER_1_S00_AXI_BASEADDR +#define PACKER_BASEADDR2 XPAR_AXIS_ADC_DATA_PACKER_2_S00_AXI_BASEADDR +#define WAVELENGTH 8192 +#define TX_BUFFER_BASE XPAR_MIG_7SERIES_0_BASEADDR +0x2000 +#define WAVE_LENGTH 8192*4 + +#define GPIO_INT_ID XPAR_FABRIC_GPIO_0_VEC_ID //PL ¶Ë AXI GPIO ÖжÏ ID +#define AXI_GPIO_ID XPAR_AXI_GPIO_0_DEVICE_ID //PL ¶Ë AXI GPIO Æ÷¼þ ID +#define SCUGIC_ID XPAR_SCUGIC_0_DEVICE_ID //ÖжϿØÖÆÆ÷ ID + +#define KEY_MASK XGPIO_IR_CH1_MASK //ͨµÀ 1 µÄ붨Òå + + +int SpiPsInit(u16 SpiDeviceId); +//int SpiPs_write_read(u8 cmd, u16 addr,u8 data,u8 * rx_data); +int SpiPs_write_read(u8 * data,u8 * rx_data); +int SpiPs_write_read1(u16 addr,u8 data,u8 * rx_data); +int SpiPs_write_read2(u16 addr,u8 data,u8 * rx_data); +int GpioInit(u16 DeviceId); +int GpioSetPinDir(u32 Pin,u32 Direction); +int GpioWritePin(u32 Pin,u32 data); +int GpioReadPin(u32 Pin); + +#endif