#include "lmx2594.h" const uint32_t lmx2594_rst[2] = { 0x00251e, 0x00251c }; uint32_t lmx2594regs[LMX_COUNT] = { 0x700000, 0x6F0000, 0x6E0000, 0x6D0000, 0x6C0000, 0x6B0000, 0x6A0000, 0x690021, 0x680000, 0x670000, 0x660000, 0x650011, 0x640000, 0x630000, 0x620000, 0x610888, 0x600000, 0x5F0000, 0x5E0000, 0x5D0000, 0x5C0000, 0x5B0000, 0x5A0000, 0x590000, 0x580000, 0x570000, 0x560000, 0x550000, 0x540000, 0x530000, 0x520000, 0x510000, 0x500000, 0x4F0000, 0x4E0105, 0x4D0000, 0x4C000C, 0x4B0C40, 0x4A0000, 0x49003F, 0x480001, 0x470081, 0x46C350, 0x450000, 0x4403E8, 0x430000, 0x4201F4, 0x410000, 0x401388, 0x3F0000, 0x3E0322, 0x3D00A8, 0x3C03E8, 0x3B0001, 0x3A9001, 0x390020, 0x380000, 0x370000, 0x360000, 0x350000, 0x340820, 0x330080, 0x320000, 0x314180, 0x300300, 0x2F0300, 0x2E07FD, 0x2DC8DF, 0x2C1F20, 0x2B0000, 0x2A0000, 0x290000, 0x280000, 0x2703E8, 0x260000, 0x250104, 0x240032, 0x230004, 0x220000, 0x211E21, 0x200393, 0x1F43EC, 0x1E318C, 0x1D318C, 0x1C0488, 0x1B0002, 0x1A0DB0, 0x190C2B, 0x18071A, 0x17007C, 0x160001, 0x150401, 0x14D848, 0x1327B7, 0x120064, 0x110130, 0x100080, 0x0F064F, 0x0E1E40, 0x0D4000, 0x0C5001, 0x0B0018, 0x0A10D8, 0x090604, 0x082000, 0x0740B2, 0x06C802, 0x0500C8, 0x041443, 0x030642, 0x020500, 0x01080B, 0x00251C }; void lmx2594_init(void *bar1) { // Header for LMX Reset uint32_t *ptr_rst = bar1 + LMX_BASE_ADDR; *ptr_rst = LMX2594_RST_HEADER; // Reset Data for (int m = 0; m < 2; m++) { uint32_t *ptr = bar1 + LMX_BASE_ADDR; *ptr = lmx2594_rst[m]; } // Header for init data uint32_t *ptr = bar1 + LMX_BASE_ADDR; *ptr = InitLMX2594Header; // Init data for (int i = 0; i < LMX_COUNT; i++) { uint32_t *ptr = bar1 + LMX_BASE_ADDR; *ptr = lmx2594regs[i]; } } /*-------------------------LMX2594 Frequency Set-------------------------*/ int lmx_freq_set_main_band(void *bar1, double freq, double f_pd) { double N_div; N_div = freq / f_pd; // divide whole part and fractional part uint32_t N = (uint32_t) N_div; // In frac part there is separate denominator and numerator // If frac part is 0 then the denominator is 1000 and numerator is 0 uint32_t frac_n = (uint32_t) ((N_div - N) * 524287); uint32_t frac_d = 524287; // If frac part is 0 then the denominator is 1000 and numerator is 0 if (frac_n == 0) { frac_n = 0; frac_d = 524287; } // Recommended sequnce for changin freq // 1. Change the N-div value // 2. Change the PLL numerator and denominator // 3. Program FCAL_EN bit // Clear the required parts of the register lmx2594regs[112-MASH_ORDER] = lmx2594regs[112-MASH_ORDER] & (~BITM_LMX2594_R44_MASH_ORDER); // Set the MASH_ORDER to 3 lmx2594regs[112-MASH_ORDER] = lmx2594regs[112-MASH_ORDER] | ENUM_LMX2594_R44_MASH_ORDER_3; // Set PF_DLY_SEL to 3 lmx2594regs[112-PFD_DLY_SEL] = lmx2594regs[112-PFD_DLY_SEL] & (~BITM_LMX2594_R37_PFD_DLY_SEL); lmx2594regs[112-PFD_DLY_SEL] = lmx2594regs[112-PFD_DLY_SEL] | (0x3 << BITP_LMX2594_R37_PFD_DLY_SEL); lmx2594regs[112-PLL_N_S] = lmx2594regs[112-PLL_N_S] &(~0xFFFF); lmx2594regs[112-PLL_N_S] = lmx2594regs[112-PLL_N_S] | (N >> 16); //CLear the lower 16 bits of the register lmx2594regs[112-PLL_N_M] = lmx2594regs[112-PLL_N_M] & (~0xFFFF); // Next 16 bits of the register lmx2594regs[112-PLL_N_M] = lmx2594regs[112-PLL_N_M] | (N & 0xFFFF); // Clear the upper 16 bits of the register lmx2594regs[PLL_NUM_S] lmx2594regs[112-PLL_NUM_S] = lmx2594regs[112-PLL_NUM_S] & (~0xFFFF); lmx2594regs[112-PLL_NUM_S] = lmx2594regs[112-PLL_NUM_S] | (frac_n >> 16); // Clear the lower 16 bits of the register lmx2594regs[PLL_NUM_M] lmx2594regs[112-PLL_NUM_M] = lmx2594regs[112-PLL_NUM_M] & (~0xFFFF); // Next 16 bits of the numerator lmx2594regs[112-PLL_NUM_M] = lmx2594regs[112-PLL_NUM_M] | (frac_n & 0xFFFF); // Clear the upper 16 bits of the register lmx2594regs[PLL_DEN_S] lmx2594regs[112-PLL_DEN_S] = lmx2594regs[112-PLL_DEN_S] & (~0xFFFF); // most significant 16 bits of the denominator lmx2594regs[112-PLL_DEN_S] = lmx2594regs[112-PLL_DEN_S] | (frac_d >> 16); // Clear the lower 16 bits of the register lmx2594regs[PLL_DEN_M] lmx2594regs[112-PLL_DEN_M] = lmx2594regs[112-PLL_DEN_M] & (~0xFFFF); // Next 16 bits of the denominator lmx2594regs[112-PLL_DEN_M] = lmx2594regs[112-PLL_DEN_M] | (frac_d & 0xFFFF); // Program the FCAL_EN bit lmx2594regs[112-FCAL_ADDR] = lmx2594regs[112-FCAL_ADDR] | (LMX2594_R0_FCAL_EN); // Show the all the upper 16 bits of the register lmx2594regs[PLL_N_S] // Determine which regs are changed and send only those uint32_t lmx_change_freq_regs[] = { lmx2594regs[112-MASH_ORDER], lmx2594regs[112-PFD_DLY_SEL], lmx2594regs[112-PLL_N_S], lmx2594regs[112-PLL_N_M], lmx2594regs[112-PLL_DEN_S], lmx2594regs[112-PLL_DEN_M], lmx2594regs[112-PLL_NUM_S], lmx2594regs[112-PLL_NUM_M], lmx2594regs[112-FCAL_ADDR] }; // Create a header for the LMX2594 with the appropriate number of words uint32_t LMX_HEADER = ((0 << 23) | (DeviceIdLmx2594 << 18) | ((sizeof(lmx_change_freq_regs)/4) << 1) | 1); uint32_t *ptr = bar1 + LMX_BASE_ADDR; *ptr = LMX_HEADER; for (int i = 0; i < sizeof(lmx_change_freq_regs)/4; i++) { uint32_t *data_ptr = bar1 + LMX_BASE_ADDR; *data_ptr = lmx_change_freq_regs[i]; } usleep(1); return 0; } int lmx_freq_set_out_of_band(void *bar1, double freq, double f_pd) { double f_vco = 2 * freq; int chan_div = 2; uint8_t ch_div_reg = 0; // 2 double vco_div = 7.5e9 / freq; double N_div; // minimum N_div value is 28 and Vco frequency can't be less than 7.5 GHz if (f_vco < 7.5e9) { if (vco_div > 2 && vco_div <= 4) chan_div = 4; // 4 f_vco = freq * chan_div; if (vco_div > 4 && vco_div <= 6) { chan_div = 6; // 6 f_vco = freq * chan_div; } if (vco_div > 6 && vco_div <= 8) { chan_div = 8; // 8 f_vco = freq * chan_div; } if (vco_div > 8 && vco_div <= 12) { chan_div = 12; // 12 f_vco = freq * chan_div; } if (vco_div > 12 && vco_div <= 16) { chan_div = 16; // 16 f_vco = freq * chan_div; } if (vco_div > 16 && vco_div <= 24) { chan_div = 24; // 24 f_vco = freq * chan_div; } if (vco_div > 24 && vco_div <= 32) { chan_div = 32; // 32 f_vco = freq * chan_div; } if (vco_div > 32 && vco_div <= 48) { chan_div = 48; // 48 f_vco = freq * chan_div; } if (vco_div > 48 && vco_div <= 64) { chan_div = 64; // 64 f_vco = freq * chan_div; } if (vco_div > 64 && vco_div <= 72) { chan_div = 72; // 72 f_vco = freq * chan_div; } if (vco_div > 72 && vco_div <= 96) { chan_div = 96; // 96 f_vco = freq * chan_div; } if (vco_div > 96 && vco_div <= 128) { chan_div = 128; // 128 f_vco = freq * chan_div; } if (vco_div > 128 && vco_div <= 192) { chan_div = 192; // 192 f_vco = freq * chan_div; } if (vco_div > 192 && vco_div <= 256) { chan_div = 256; // 256 f_vco = freq * chan_div; } if (vco_div > 256 && vco_div <= 384) { chan_div = 384; // 384 f_vco = freq * chan_div; } if (vco_div > 384 && vco_div <= 512) { chan_div = 512; // 512 f_vco = freq * chan_div; } if (vco_div > 512 && vco_div <= 768) { chan_div = 768; // 768 f_vco = freq * chan_div; } switch (chan_div) { case 2: ch_div_reg = 0; break; case 4: ch_div_reg = 1; break; case 6: ch_div_reg = 2; break; case 8: ch_div_reg = 3; break; case 12: ch_div_reg = 4; break; case 16: ch_div_reg = 5; break; case 24: ch_div_reg = 6; break; case 32: ch_div_reg = 7; break; case 48: ch_div_reg = 8; break; case 64: ch_div_reg = 9; break; case 72: ch_div_reg = 10; break; case 96: ch_div_reg = 11; break; case 128: ch_div_reg = 12; break; case 192: ch_div_reg = 13; break; case 256: ch_div_reg = 14; break; case 384: ch_div_reg = 15; break; case 512: ch_div_reg = 16; break; case 768: ch_div_reg = 17; break; } } else { ch_div_reg = 0; f_vco = freq * 2; } N_div = f_vco / f_pd; // divide whole part and fractional part uint32_t N = (uint32_t) N_div; uint32_t frac_n = (uint32_t) ((N_div - N) * 524287); uint32_t frac_d = 524287; // If frac part is 0 then the denominator is 1000 and numerator is 0 if (frac_n == 0) { frac_n = 0; frac_d = 524287; } lmx2594regs[112 - MASH_ORDER] = lmx2594regs[112 - MASH_ORDER] & (~BITM_LMX2594_R44_MASH_ORDER); // Set the MASH_ORDER to 3 lmx2594regs[112 - MASH_ORDER] = lmx2594regs[112 - MASH_ORDER] | ENUM_LMX2594_R44_MASH_ORDER_3; // Set PF_DLY_SEL to 3 lmx2594regs[112 - PFD_DLY_SEL] = lmx2594regs[112 - PFD_DLY_SEL] & (~BITM_LMX2594_R37_PFD_DLY_SEL); lmx2594regs[112 - PFD_DLY_SEL] = lmx2594regs[112 - PFD_DLY_SEL] | (0x3 << BITP_LMX2594_R37_PFD_DLY_SEL); lmx2594regs[112 - PLL_N_S] = lmx2594regs[112 - PLL_N_S] & (~0xFFFF); lmx2594regs[112 - PLL_N_S] = lmx2594regs[112 - PLL_N_S] | (N >> 16); //CLear the lower 16 bits of the register lmx2594regs[112 - PLL_N_M] = lmx2594regs[112 - PLL_N_M] & (~0xFFFF); // Next 16 bits of the register lmx2594regs[112 - PLL_N_M] = lmx2594regs[112 - PLL_N_M] | (N & 0xFFFF); // Clear the upper 16 bits of the register lmx2594regs[PLL_NUM_S] lmx2594regs[112 - PLL_NUM_S] = lmx2594regs[112 - PLL_NUM_S] & (~0xFFFF); lmx2594regs[112 - PLL_NUM_S] = lmx2594regs[112 - PLL_NUM_S] | (frac_n >> 16); // Clear the lower 16 bits of the register lmx2594regs[PLL_NUM_M] lmx2594regs[112 - PLL_NUM_M] = lmx2594regs[112 - PLL_NUM_M] & (~0xFFFF); // Next 16 bits of the numerator lmx2594regs[112 - PLL_NUM_M] = lmx2594regs[112 - PLL_NUM_M] | (frac_n & 0xFFFF); // Clear the upper 16 bits of the register lmx2594regs[PLL_DEN_S] lmx2594regs[112 - PLL_DEN_S] = lmx2594regs[112 - PLL_DEN_S] & (~0xFFFF); // most significant 16 bits of the denominator lmx2594regs[112 - PLL_DEN_S] = lmx2594regs[112 - PLL_DEN_S] | (frac_d >> 16); // Clear the lower 16 bits of the register lmx2594regs[PLL_DEN_M] lmx2594regs[112 - PLL_DEN_M] = lmx2594regs[112 - PLL_DEN_M] & (~0xFFFF); // Next 16 bits of the denominator lmx2594regs[112 - PLL_DEN_M] = lmx2594regs[112 - PLL_DEN_M] | (frac_d & 0xFFFF); // Program the CHDIV value lmx2594regs[112 - CHDIV] = lmx2594regs[112 - CHDIV] & (~BITM_LMX2594_R75_CHDIV); // Set the CHDIV value with the starting position BITP_LMX2594_R75_CHDIV lmx2594regs[112 - CHDIV] = lmx2594regs[112 - CHDIV] | (ch_div_reg << BITP_LMX2594_R75_CHDIV); // If the ch_div > 2 then set the SEG1_EN bit if (chan_div > 2) { lmx2594regs[112 - CHDIV_DIV2] = lmx2594regs[112 - CHDIV_DIV2] & (~BITM_LMX2594_R31_CHDIV_DIV2); lmx2594regs[112 - CHDIV_DIV2] = lmx2594regs[112 - CHDIV_DIV2] | (ENUM_LMX2594_R31_CHDIV_DIV2_EN); } // Set the OUTA_MUX to channel divider R45[12:11]; 0 - Channel divider, 1 - VCO; lmx2594regs[112 - OUTA_MUX] = lmx2594regs[112 - OUTA_MUX] & (~BITM_LMX2594_R45_OUTA_MUX); lmx2594regs[112 - OUTA_MUX] = lmx2594regs[112 - OUTA_MUX] | ENUM_LMX2594_R45_OUTA_MUX_CH_DIV; // Program the FCAL_EN bit lmx2594regs[112 - FCAL_ADDR] = lmx2594regs[112 - FCAL_ADDR] | (LMX2594_R0_FCAL_EN); uint32_t lmx_change_freq_regs[] = { lmx2594regs[112 - PLL_N_S], lmx2594regs[112 - PLL_N_M], lmx2594regs[112 - PLL_DEN_S], lmx2594regs[112 - PLL_DEN_M], lmx2594regs[112 - PLL_NUM_S], lmx2594regs[112 - PLL_NUM_M], lmx2594regs[112 - FCAL_ADDR], lmx2594regs[112 - CHDIV_DIV2], lmx2594regs[112 - CHDIV], lmx2594regs[112 - OUTA_MUX] }; // Create a header for the LMX2594 with the appropriate number of words uint32_t LMX_HEADER = ((0 << 23) | (DeviceIdLmx2594 << 18) | ((sizeof(lmx_change_freq_regs) / 4) << 1) | 1); uint32_t *ptr = bar1 + LMX_BASE_ADDR; *ptr = LMX_HEADER; // Send the data for (int i = 0; i < sizeof(lmx_change_freq_regs) / 4; i++) { uint32_t *data_ptr = bar1 + LMX_BASE_ADDR; *data_ptr = lmx_change_freq_regs[i]; } usleep(1); return 0; } int lmx_freq_set(void *bar1, double freq) { double f_pd = 200e6; double N_div = 0; if (freq < 10e6 || freq > 15e9) { printf("Frequency range is 10 MHz to 15 GHz\n"); return -1; } // if the frequency is in the main band - 7.5 GHz to 15 GHz if (freq >= 7.5e9 && freq <= 15e9) { lmx_freq_set_main_band(bar1, freq, f_pd); } else if (freq < 7.5e9) { lmx_freq_set_out_of_band(bar1, freq, f_pd); } return 0; }