From 1bbb3527431ee1363698757ac36b383cf15fb13c Mon Sep 17 00:00:00 2001 From: Dhanya Thattil Date: Fri, 11 Jan 2019 14:48:58 +0100 Subject: [PATCH] jungfrau server: pll moved out to remove redundancy --- .../ctbDetectorServer/ALTERA_PLL.h | 1 + .../slsDetectorFunctionList.c | 83 +------ .../slsDetectorServer_defs.h | 64 ----- .../jungfrauDetectorServer/ALTERA_PLL.h | 1 + .../jungfrauDetectorServer/RegisterDefs.h | 18 +- .../bin/jungfrauDetectorServer_refactor | Bin 106004 -> 107360 bytes .../jungfrauDetectorServer/gitInfo.txt | 8 +- .../jungfrauDetectorServer/gitInfoJungfrau.h | 6 +- .../slsDetectorFunctionList.c | 55 +---- .../slsDetectorServer_defs.h | 44 ---- .../moenchDetectorServer/ALTERA_PLL.h | 1 + .../slsDetectorFunctionList.c | 80 +------ .../slsDetectorServer_defs.h | 64 ----- .../slsDetectorServer/ALTERA_PLL.h | 218 ++++++++++++++++++ slsSupportLib/include/versionAPI.h | 2 +- 15 files changed, 269 insertions(+), 376 deletions(-) create mode 120000 slsDetectorServers/ctbDetectorServer/ALTERA_PLL.h create mode 120000 slsDetectorServers/jungfrauDetectorServer/ALTERA_PLL.h create mode 120000 slsDetectorServers/moenchDetectorServer/ALTERA_PLL.h create mode 100755 slsDetectorServers/slsDetectorServer/ALTERA_PLL.h diff --git a/slsDetectorServers/ctbDetectorServer/ALTERA_PLL.h b/slsDetectorServers/ctbDetectorServer/ALTERA_PLL.h new file mode 120000 index 000000000..e665f009d --- /dev/null +++ b/slsDetectorServers/ctbDetectorServer/ALTERA_PLL.h @@ -0,0 +1 @@ +../slsDetectorServer/ALTERA_PLL.h \ No newline at end of file diff --git a/slsDetectorServers/ctbDetectorServer/slsDetectorFunctionList.c b/slsDetectorServers/ctbDetectorServer/slsDetectorFunctionList.c index 0f78a2534..b855dbce4 100644 --- a/slsDetectorServers/ctbDetectorServer/slsDetectorFunctionList.c +++ b/slsDetectorServers/ctbDetectorServer/slsDetectorFunctionList.c @@ -3,12 +3,14 @@ #include "versionAPI.h" #include "logger.h" -#ifndef VIRTUAL + #include "AD9257.h" // commonServerFunctions.h, blackfin.h, ansi.h #include "AD7689.h" // slow adcs #include "LTC2620.h" // dacs #include "MAX1932.h" // hv #include "INA226.h" // i2c +#include "ALTERA_PLL.h" // pll +#ifndef VIRTUAL #include "programfpga.h" #else #include "blackfin.h" @@ -473,7 +475,7 @@ void setupDetector() { now_ptr = 0; - resetPLL(); + ALTERA_PLL_ResetPLLAndReconfiguration(); resetCore(); resetPeripheral(); cleanFifos(); @@ -518,6 +520,9 @@ void setupDetector() { } } + // altera pll + ALTERA_PLL_SetDefines(PLL_CNTRL_REG, PLL_PARAM_REG, PLL_CNTRL_RCNFG_PRMTR_RST_MSK, PLL_CNTRL_WR_PRMTR_MSK, PLL_CNTRL_PLL_RST_MSK, PLL_CNTRL_ADDR_MSK, PLL_CNTRL_ADDR_OFST); + bus_w(ADC_PORT_INVERT_REG, ADC_PORT_INVERT_VAL);//FIXME: got from moench config file FILE_LOG(logINFOBLUE, ("Setting Default parameters\n")); @@ -1561,35 +1566,6 @@ int sendUDP(int enable) { return ((bus_r(addr) & CONFIG_GB10_SND_UDP_MSK) >> CONFIG_GB10_SND_UDP_OFST); } -void resetPLL() { -#ifdef VIRTUAL - return; -#endif - FILE_LOG(logINFO, ("Resetting PLL\n")); - // reset PLL Reconfiguration and PLL - bus_w(PLL_CNTRL_REG, bus_r(PLL_CNTRL_REG) | PLL_CNTRL_RCNFG_PRMTR_RST_MSK | PLL_CNTRL_PLL_RST_MSK); - usleep(WAIT_TIME_US_PLL); - bus_w(PLL_CNTRL_REG, bus_r(PLL_CNTRL_REG) & ~PLL_CNTRL_RCNFG_PRMTR_RST_MSK & ~PLL_CNTRL_PLL_RST_MSK); -} - -void setPllReconfigReg(uint32_t reg, uint32_t val) { -#ifdef VIRTUAL - return val; -#endif - FILE_LOG(logINFO, ("Setting PLL Reconfig Reg\n")); - // set parameter - bus_w(PLL_PARAM_REG, val); - - // set address - bus_w(PLL_CNTRL_REG, (reg << PLL_CNTRL_ADDR_OFST) & PLL_CNTRL_ADDR_MSK); - usleep(WAIT_TIME_US_PLL); - - //write parameter - bus_w(PLL_CNTRL_REG, bus_r(PLL_CNTRL_REG) | PLL_CNTRL_WR_PRMTR_MSK); - bus_w(PLL_CNTRL_REG, bus_r(PLL_CNTRL_REG) & ~PLL_CNTRL_WR_PRMTR_MSK); - usleep(WAIT_TIME_US_PLL); -} - // ind can only be ADC_CLK or DBIT_CLK void configurePhase(CLKINDEX ind, int val) { if (st > 65535 || st < -65535) { @@ -1600,12 +1576,10 @@ void configurePhase(CLKINDEX ind, int val) { FILE_LOG(logINFO, ("Configuring Phase of C%d to %d\n", ind, val)); // reset only pll - bus_w(PLL_CNTRL_REG, bus_r(PLL_CNTRL_REG) | PLL_CNTRL_PLL_RST_MSK); - usleep(WAIT_TIME_US_PLL); - bus_w(PLL_CNTRL_REG, bus_r(PLL_CNTRL_REG) & ~PLL_CNTRL_PLL_RST_MSK); + ALTERA_PLL_ResetPLL(); // set mode register to polling mode - setPllReconfigReg(PLL_MODE_REG, PLL_MODE_PLLNG_MD_VAL); + ALTERA_PLL_SetModePolling(); int phase = 0, inv = 0; if (val > 0) { @@ -1618,13 +1592,7 @@ void configurePhase(CLKINDEX ind, int val) { } FILE_LOG(logINFO, ("\tphase out %d (0x%08x), inv:%d\n", phase, phase, inv)); - uint32_t value = (((phase << PLL_SHIFT_NUM_SHIFTS_OFST) & PLL_SHIFT_NUM_SHIFTS_MSK) | - (((int)ind << PLL_SHIFT_CNT_SELECT_OFST) & PLL_SHIFT_CNT_SELECT_MSK)); - FILE_LOG(logDEBUG1, ("\tC%d phase word:0x%08x\n", ind, value)); - - // write phase shift - setPllReconfigReg(PLL_PHASE_SHIFT_REG, value); - usleep(WAIT_TIME_US_PLL); + ALTERA_PLL_SetPhaseShift(phase, (int)ind, 0); clkPhase[ind] = val; } @@ -1645,35 +1613,8 @@ void configureFrequency(CLKINDEX ind, int val) { return getPhase(ind); } - // calculate output frequency - uint32_t total_div = PLL_VCO_FREQ_MHZ / val; - - // assume 50% duty cycle - uint32_t low_count = total_div / 2; - uint32_t high_count = low_count; - uint32_t odd_division = 0; - - // odd division - if (total_div > (2 * low_count)) { - ++high_count; - odd_division = 1; - } - FILE_LOG(logINFO, ("\tC%d: Low:%d, High:%d, Odd:%d\n", ind, low_count, high_count, odd_division)); - - uint32_t val = (((low_count << PLL_C_COUNTER_LW_CNT_OFST) & PLL_C_COUNTER_LW_CNT_MSK) | - ((high_count << PLL_C_COUNTER_HGH_CNT_OFST) & PLL_C_COUNTER_HGH_CNT_MSK) | - ((odd_division << PLL_C_COUNTER_ODD_DVSN_OFST) & PLL_C_COUNTER_ODD_DVSN_MSK) | - (((int)ind << PLL_C_COUNTER_SLCT_OFST) & PLL_C_COUNTER_SLCT_MSK)); - FILE_LOG(logDEBUG1, ("\tC%d word:0x%08x\n", ind, val)); - - // write frequency (post-scale output counter C) - setPllReconfigReg(PLL_C_COUNTER_REG, val); - usleep(WAIT_TIME_US_PLL); - - // reset only PLL - bus_w(PLL_CNTRL_REG, bus_r(PLL_CNTRL_REG) | PLL_CNTRL_PLL_RST_MSK); - usleep(WAIT_TIME_US_PLL); - bus_w(PLL_CNTRL_REG, bus_r(PLL_CNTRL_REG) & ~PLL_CNTRL_PLL_RST_MSK); + // Calculate and set output frequency + ALTERA_PLL_SetOuputFrequency (ind, PLL_VCO_FREQ_MHZ); clkDivider[ind] = PLL_VCO_FREQ_MHZ / (low_count + high_count); FILE_LOG(logINFO, ("\tC%d: Frequency set to %d MHz\n", ind, clkDivider[ind])); diff --git a/slsDetectorServers/ctbDetectorServer/slsDetectorServer_defs.h b/slsDetectorServers/ctbDetectorServer/slsDetectorServer_defs.h index 772795859..77a0364d5 100644 --- a/slsDetectorServers/ctbDetectorServer/slsDetectorServer_defs.h +++ b/slsDetectorServers/ctbDetectorServer/slsDetectorServer_defs.h @@ -87,67 +87,3 @@ enum DACINDEX {D0, D1, D2, D3, D4, D5, D6, D7, D8, D9, #define MAXIMUM_ADC_CLK (40) #define PLL_VCO_FREQ_MHZ (400) -/** PLL Reconfiguration Registers */ -//https://www.altera.com/documentation/mcn1424769382940.html -#define PLL_MODE_REG (0x00) - -#define PLL_MODE_WT_RQUST_VAL (0) -#define PLL_MODE_PLLNG_MD_VAL (1) - -#define PLL_STATUS_REG (0x01) -#define PLL_START_REG (0x02) -#define PLL_N_COUNTER_REG (0x03) -#define PLL_M_COUNTER_REG (0x04) -#define PLL_C_COUNTER_REG (0x05) - -#define PLL_C_COUNTER_LW_CNT_OFST (0) -#define PLL_C_COUNTER_LW_CNT_MSK (0x000000FF << PLL_C_COUNTER_LW_CNT_OFST) -#define PLL_C_COUNTER_HGH_CNT_OFST (8) -#define PLL_C_COUNTER_HGH_CNT_MSK (0x000000FF << PLL_C_COUNTER_HGH_CNT_OFST) -/* total_div = lw_cnt + hgh_cnt */ -#define PLL_C_COUNTER_BYPSS_ENBL_OFST (16) -#define PLL_C_COUNTER_BYPSS_ENBL_MSK (0x00000001 << PLL_C_COUNTER_BYPSS_ENBL_OFST) -/* if bypss_enbl = 0, fout = f(vco)/total_div; else fout = f(vco) (c counter is bypassed) */ -#define PLL_C_COUNTER_ODD_DVSN_OFST (17) -#define PLL_C_COUNTER_ODD_DVSN_MSK (0x00000001 << PLL_C_COUNTER_ODD_DVSN_OFST) -/** if odd_dvsn = 0 (even), duty cycle = hgh_cnt/ total_div; else duty cycle = (hgh_cnt - 0.5) / total_div */ -#define PLL_C_COUNTER_SLCT_OFST (18) -#define PLL_C_COUNTER_SLCT_MSK (0x0000001F << PLL_C_COUNTER_SLCT_OFST) - -#define PLL_PHASE_SHIFT_REG (0x06) - -#define PLL_SHIFT_NUM_SHIFTS_OFST (0) -#define PLL_SHIFT_NUM_SHIFTS_MSK (0x0000FFFF << PLL_SHIFT_NUM_SHIFTS_OFST) - -#define PLL_SHIFT_CNT_SELECT_OFST (16) -#define PLL_SHIFT_CNT_SELECT_MSK (0x0000001F << PLL_SHIFT_CNT_SELECT_OFST) -#define PLL_SHIFT_CNT_SLCT_C0_VAL ((0x0 << PLL_SHIFT_CNT_SELECT_OFST) & PLL_SHIFT_CNT_SELECT_MSK) -#define PLL_SHIFT_CNT_SLCT_C1_VAL ((0x1 << PLL_SHIFT_CNT_SELECT_OFST) & PLL_SHIFT_CNT_SELECT_MSK) -#define PLL_SHIFT_CNT_SLCT_C2_VAL ((0x2 << PLL_SHIFT_CNT_SELECT_OFST) & PLL_SHIFT_CNT_SELECT_MSK) -#define PLL_SHIFT_CNT_SLCT_C3_VAL ((0x3 << PLL_SHIFT_CNT_SELECT_OFST) & PLL_SHIFT_CNT_SELECT_MSK) -#define PLL_SHIFT_CNT_SLCT_C4_VAL ((0x4 << PLL_SHIFT_CNT_SELECT_OFST) & PLL_SHIFT_CNT_SELECT_MSK) -#define PLL_SHIFT_CNT_SLCT_C5_VAL ((0x5 << PLL_SHIFT_CNT_SELECT_OFST) & PLL_SHIFT_CNT_SELECT_MSK) -#define PLL_SHIFT_CNT_SLCT_C6_VAL ((0x6 << PLL_SHIFT_CNT_SELECT_OFST) & PLL_SHIFT_CNT_SELECT_MSK) -#define PLL_SHIFT_CNT_SLCT_C7_VAL ((0x7 << PLL_SHIFT_CNT_SELECT_OFST) & PLL_SHIFT_CNT_SELECT_MSK) -#define PLL_SHIFT_CNT_SLCT_C8_VAL ((0x8 << PLL_SHIFT_CNT_SELECT_OFST) & PLL_SHIFT_CNT_SELECT_MSK) -#define PLL_SHIFT_CNT_SLCT_C9_VAL ((0x9 << PLL_SHIFT_CNT_SELECT_OFST) & PLL_SHIFT_CNT_SELECT_MSK) -#define PLL_SHIFT_CNT_SLCT_C10_VAL ((0x10 << PLL_SHIFT_CNT_SELECT_OFST) & PLL_SHIFT_CNT_SELECT_MSK) -#define PLL_SHIFT_CNT_SLCT_C11_VAL ((0x11 << PLL_SHIFT_CNT_SELECT_OFST) & PLL_SHIFT_CNT_SELECT_MSK) -#define PLL_SHIFT_CNT_SLCT_C12_VAL ((0x12 << PLL_SHIFT_CNT_SELECT_OFST) & PLL_SHIFT_CNT_SELECT_MSK) -#define PLL_SHIFT_CNT_SLCT_C13_VAL ((0x13 << PLL_SHIFT_CNT_SELECT_OFST) & PLL_SHIFT_CNT_SELECT_MSK) -#define PLL_SHIFT_CNT_SLCT_C14_VAL ((0x14 << PLL_SHIFT_CNT_SELECT_OFST) & PLL_SHIFT_CNT_SELECT_MSK) -#define PLL_SHIFT_CNT_SLCT_C15_VAL ((0x15 << PLL_SHIFT_CNT_SELECT_OFST) & PLL_SHIFT_CNT_SELECT_MSK) -#define PLL_SHIFT_CNT_SLCT_C16_VAL ((0x16 << PLL_SHIFT_CNT_SELECT_OFST) & PLL_SHIFT_CNT_SELECT_MSK) -#define PLL_SHIFT_CNT_SLCT_C17_VAL ((0x17 << PLL_SHIFT_CNT_SELECT_OFST) & PLL_SHIFT_CNT_SELECT_MSK) - -#define PLL_SHIFT_UP_DOWN_OFST (21) -#define PLL_SHIFT_UP_DOWN_MSK (0x00000001 << PLL_SHIFT_UP_DOWN_OFST) -#define PLL_SHIFT_UP_DOWN_NEG_VAL ((0x0 << PLL_SHIFT_UP_DOWN_OFST) & PLL_SHIFT_UP_DOWN_MSK) -#define PLL_SHIFT_UP_DOWN_POS_VAL ((0x1 << PLL_SHIFT_UP_DOWN_OFST) & PLL_SHIFT_UP_DOWN_MSK) - -#define PLL_K_COUNTER_REG (0x07) -#define PLL_BANDWIDTH_REG (0x08) -#define PLL_CHARGEPUMP_REG (0x09) -#define PLL_VCO_DIV_REG (0x1c) -#define PLL_MIF_REG (0x1f) - diff --git a/slsDetectorServers/jungfrauDetectorServer/ALTERA_PLL.h b/slsDetectorServers/jungfrauDetectorServer/ALTERA_PLL.h new file mode 120000 index 000000000..e665f009d --- /dev/null +++ b/slsDetectorServers/jungfrauDetectorServer/ALTERA_PLL.h @@ -0,0 +1 @@ +../slsDetectorServer/ALTERA_PLL.h \ No newline at end of file diff --git a/slsDetectorServers/jungfrauDetectorServer/RegisterDefs.h b/slsDetectorServers/jungfrauDetectorServer/RegisterDefs.h index 562f065f8..1862e68ca 100644 --- a/slsDetectorServers/jungfrauDetectorServer/RegisterDefs.h +++ b/slsDetectorServers/jungfrauDetectorServer/RegisterDefs.h @@ -239,16 +239,16 @@ #define PLL_PARAM_REG (0x50 << MEM_MAP_SHIFT) /* Reconfiguratble PLL Control Regiser */ -#define PLL_CONTROL_REG (0x51 << MEM_MAP_SHIFT) +#define PLL_CNTRL_REG (0x51 << MEM_MAP_SHIFT) -#define PLL_CTRL_RECONFIG_RST_OFST (0) //parameter reset -#define PLL_CTRL_RECONFIG_RST_MSK (0x00000001 << PLL_CTRL_RECONFIG_RST_OFST) //parameter reset -#define PLL_CTRL_WR_PARAMETER_OFST (2) -#define PLL_CTRL_WR_PARAMETER_MSK (0x00000001 << PLL_CTRL_WR_PARAMETER_OFST) -#define PLL_CTRL_RST_OFST (3) -#define PLL_CTRL_RST_MSK (0x00000001 << PLL_CTRL_RST_OFST) -#define PLL_CTRL_ADDR_OFST (16) -#define PLL_CTRL_ADDR_MSK (0x0000003F << PLL_CTRL_ADDR_OFST) +#define PLL_CNTRL_RCNFG_PRMTR_RST_OFST (0) //parameter reset +#define PLL_CNTRL_RCNFG_PRMTR_RST_MSK (0x00000001 << PLL_CNTRL_RCNFG_PRMTR_RST_OFST) //parameter reset +#define PLL_CNTRL_WR_PRMTR_OFST (2) +#define PLL_CNTRL_WR_PRMTR_MSK (0x00000001 << PLL_CNTRL_WR_PRMTR_OFST) +#define PLL_CNTRL_PLL_RST_OFST (3) +#define PLL_CNTRL_PLL_RST_MSK (0x00000001 << PLL_CNTRL_PLL_RST_OFST) +#define PLL_CNTRL_ADDR_OFST (16) +#define PLL_CNTRL_ADDR_MSK (0x0000003F << PLL_CNTRL_ADDR_OFST) /* Sample Register (Obsolete) */ #define SAMPLE_REG (0x59 << MEM_MAP_SHIFT) diff --git a/slsDetectorServers/jungfrauDetectorServer/bin/jungfrauDetectorServer_refactor b/slsDetectorServers/jungfrauDetectorServer/bin/jungfrauDetectorServer_refactor index bc9469f9d72d487a67a6172bf84738a61d2e1519..b5d37dcd8afba67dba88f687a6aff9f6dd8e36a3 100755 GIT binary patch delta 38080 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 delta 36746 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 diff --git a/slsDetectorServers/jungfrauDetectorServer/gitInfo.txt b/slsDetectorServers/jungfrauDetectorServer/gitInfo.txt index 620a09911..380e64312 100644 --- a/slsDetectorServers/jungfrauDetectorServer/gitInfo.txt +++ b/slsDetectorServers/jungfrauDetectorServer/gitInfo.txt @@ -1,9 +1,9 @@ Path: slsDetectorPackage/slsDetectorServers/jungfrauDetectorServer URL: origin git@github.com:slsdetectorgroup/slsDetectorPackage.git Repository Root: origin git@github.com:slsdetectorgroup/slsDetectorPackage.git -Repsitory UUID: b5b5ce5c3782a201b449141448ebe99c69515c18 -Revision: 21 +Repsitory UUID: de2ebad2ed07a85f70b40490b4e07d46b3ac1ff6 +Revision: 22 Branch: refactor Last Changed Author: Dhanya_Thattil -Last Changed Rev: 4214 -Last Changed Date: 2019-01-10 11:46:27.000000002 +0100 ./RegisterDefs.h +Last Changed Rev: 4228 +Last Changed Date: 2019-01-11 11:59:57.000000002 +0100 ./RegisterDefs.h diff --git a/slsDetectorServers/jungfrauDetectorServer/gitInfoJungfrau.h b/slsDetectorServers/jungfrauDetectorServer/gitInfoJungfrau.h index a11ead5e1..1bcb6652d 100644 --- a/slsDetectorServers/jungfrauDetectorServer/gitInfoJungfrau.h +++ b/slsDetectorServers/jungfrauDetectorServer/gitInfoJungfrau.h @@ -1,6 +1,6 @@ #define GITURL "git@github.com:slsdetectorgroup/slsDetectorPackage.git" -#define GITREPUUID "b5b5ce5c3782a201b449141448ebe99c69515c18" +#define GITREPUUID "de2ebad2ed07a85f70b40490b4e07d46b3ac1ff6" #define GITAUTH "Dhanya_Thattil" -#define GITREV 0x4214 -#define GITDATE 0x20190110 +#define GITREV 0x4228 +#define GITDATE 0x20190111 #define GITBRANCH "refactor" diff --git a/slsDetectorServers/jungfrauDetectorServer/slsDetectorFunctionList.c b/slsDetectorServers/jungfrauDetectorServer/slsDetectorFunctionList.c index bddf781ac..f01d22752 100644 --- a/slsDetectorServers/jungfrauDetectorServer/slsDetectorFunctionList.c +++ b/slsDetectorServers/jungfrauDetectorServer/slsDetectorFunctionList.c @@ -3,10 +3,11 @@ #include "versionAPI.h" #include "logger.h" -#ifndef VIRTUAL #include "AD9257.h" // commonServerFunctions.h, blackfin.h, ansi.h #include "LTC2620.h" // dacs #include "MAX1932.h" // hv +#include "ALTERA_PLL.h" // pll +#ifndef VIRTUAL #include "programfpga.h" #else #include "blackfin.h" @@ -392,7 +393,7 @@ void initStopServer() { void setupDetector() { FILE_LOG(logINFO, ("This Server is for 1 Jungfrau module (500k)\n")); - resetPLL(); + ALTERA_PLL_ResetPLL(); resetCore(); resetPeripheral(); cleanFifos(); @@ -413,6 +414,9 @@ void setupDetector() { LTC2620_Configure(); setDefaultDacs(); + // altera pll + ALTERA_PLL_SetDefines(PLL_CNTRL_REG, PLL_PARAM_REG, PLL_CNTRL_RCNFG_PRMTR_RST_MSK, PLL_CNTRL_WR_PRMTR_MSK, PLL_CNTRL_PLL_RST_MSK, PLL_CNTRL_ADDR_MSK, PLL_CNTRL_ADDR_OFST); + bus_w(DAQ_REG, 0x0); /* Only once at server startup */ FILE_LOG(logINFOBLUE, ("Setting Default parameters\n")); @@ -1223,41 +1227,6 @@ int getPhase() { } -void resetPLL() { -#ifdef VIRTUAL - return; -#endif - FILE_LOG(logINFO, ("Resetting PLL\n")); - // reset PLL Reconfiguration and PLL - bus_w(PLL_CONTROL_REG, bus_r(PLL_CONTROL_REG) | PLL_CTRL_RECONFIG_RST_MSK | PLL_CTRL_RST_MSK); - usleep(100); - bus_w(PLL_CONTROL_REG, bus_r(PLL_CONTROL_REG) & ~PLL_CTRL_RECONFIG_RST_MSK & ~PLL_CTRL_RST_MSK); -} - - -u_int32_t setPllReconfigReg(u_int32_t reg, u_int32_t val) { -#ifdef VIRTUAL - return val; -#endif - FILE_LOG(logINFO, ("Setting PLL Reconfig Reg\n")); - // set parameter - bus_w(PLL_PARAM_REG, val); - - // set address - bus_w(PLL_CONTROL_REG, (reg << PLL_CTRL_ADDR_OFST) & PLL_CTRL_ADDR_MSK); - usleep(10*1000); - - //write parameter - bus_w(PLL_CONTROL_REG, bus_r(PLL_CONTROL_REG) | PLL_CTRL_WR_PARAMETER_MSK); - bus_w(PLL_CONTROL_REG, bus_r(PLL_CONTROL_REG) & ~PLL_CTRL_WR_PARAMETER_MSK); - usleep(10*1000); - - return val; -} - - - - void configurePll() { #ifdef VIRTUAL return; @@ -1280,17 +1249,11 @@ void configurePll() { FILE_LOG(logDEBUG1, ("\tphase out %d (0x%08x)\n", phase, phase)); if (inv) { - val = ((phase << PLL_SHIFT_NUM_SHIFTS_OFST) & PLL_SHIFT_NUM_SHIFTS_MSK) + PLL_SHIFT_CNT_SLCT_C1_VAL + PLL_SHIFT_UP_DOWN_NEG_VAL; - FILE_LOG(logDEBUG1, ("\tphase word 0x%08x\n", val)); - setPllReconfigReg(PLL_PHASE_SHIFT_REG, val); + ALTERA_PLL_SetPhaseShift(phase, 1, 0); } else { - val = ((phase << PLL_SHIFT_NUM_SHIFTS_OFST) & PLL_SHIFT_NUM_SHIFTS_MSK) + PLL_SHIFT_CNT_SLCT_C0_VAL + PLL_SHIFT_UP_DOWN_NEG_VAL; - FILE_LOG(logDEBUG1, ("\tphase word 0x%08x\n", val)); - setPllReconfigReg(PLL_PHASE_SHIFT_REG, val); + ALTERA_PLL_SetPhaseShift(phase, 0, 0); - FILE_LOG(logDEBUG1, ("\tphase word 0x%08x\n", val)); - val = ((phase << PLL_SHIFT_NUM_SHIFTS_OFST) & PLL_SHIFT_NUM_SHIFTS_MSK) + PLL_SHIFT_CNT_SLCT_C2_VAL; - setPllReconfigReg(PLL_PHASE_SHIFT_REG, val); + ALTERA_PLL_SetPhaseShift(phase, 2, 0); } usleep(10000); } diff --git a/slsDetectorServers/jungfrauDetectorServer/slsDetectorServer_defs.h b/slsDetectorServers/jungfrauDetectorServer/slsDetectorServer_defs.h index 067239d7f..9d829a0fa 100644 --- a/slsDetectorServers/jungfrauDetectorServer/slsDetectorServer_defs.h +++ b/slsDetectorServers/jungfrauDetectorServer/slsDetectorServer_defs.h @@ -92,47 +92,3 @@ enum NETWORKINDEX { TXN_FRAME }; #define LSB_OF_64_BIT_REG_OFST (0) #define BIT_32_MSK (0xFFFFFFFF) -/** PLL Reconfiguration Registers */ -//https://www.altera.com/documentation/mcn1424769382940.html -#define PLL_MODE_REG (0x00) -#define PLL_STATUS_REG (0x01) -#define PLL_START_REG (0x02) -#define PLL_N_COUNTER_REG (0x03) -#define PLL_M_COUNTER_REG (0x04) -#define PLL_C_COUNTER_REG (0x05) -#define PLL_PHASE_SHIFT_REG (0x06) - -#define PLL_SHIFT_NUM_SHIFTS_OFST (0) -#define PLL_SHIFT_NUM_SHIFTS_MSK (0x0000FFFF << PLL_SHIFT_NUM_SHIFTS_OFST) - -#define PLL_SHIFT_CNT_SELECT_OFST (16) -#define PLL_SHIFT_CNT_SELECT_MSK (0x0000001F << PLL_SHIFT_CNT_SELECT_OFST) -#define PLL_SHIFT_CNT_SLCT_C0_VAL ((0x0 << PLL_SHIFT_CNT_SELECT_OFST) & PLL_SHIFT_CNT_SELECT_MSK) -#define PLL_SHIFT_CNT_SLCT_C1_VAL ((0x1 << PLL_SHIFT_CNT_SELECT_OFST) & PLL_SHIFT_CNT_SELECT_MSK) -#define PLL_SHIFT_CNT_SLCT_C2_VAL ((0x2 << PLL_SHIFT_CNT_SELECT_OFST) & PLL_SHIFT_CNT_SELECT_MSK) -#define PLL_SHIFT_CNT_SLCT_C3_VAL ((0x3 << PLL_SHIFT_CNT_SELECT_OFST) & PLL_SHIFT_CNT_SELECT_MSK) -#define PLL_SHIFT_CNT_SLCT_C4_VAL ((0x4 << PLL_SHIFT_CNT_SELECT_OFST) & PLL_SHIFT_CNT_SELECT_MSK) -#define PLL_SHIFT_CNT_SLCT_C5_VAL ((0x5 << PLL_SHIFT_CNT_SELECT_OFST) & PLL_SHIFT_CNT_SELECT_MSK) -#define PLL_SHIFT_CNT_SLCT_C6_VAL ((0x6 << PLL_SHIFT_CNT_SELECT_OFST) & PLL_SHIFT_CNT_SELECT_MSK) -#define PLL_SHIFT_CNT_SLCT_C7_VAL ((0x7 << PLL_SHIFT_CNT_SELECT_OFST) & PLL_SHIFT_CNT_SELECT_MSK) -#define PLL_SHIFT_CNT_SLCT_C8_VAL ((0x8 << PLL_SHIFT_CNT_SELECT_OFST) & PLL_SHIFT_CNT_SELECT_MSK) -#define PLL_SHIFT_CNT_SLCT_C9_VAL ((0x9 << PLL_SHIFT_CNT_SELECT_OFST) & PLL_SHIFT_CNT_SELECT_MSK) -#define PLL_SHIFT_CNT_SLCT_C10_VAL ((0x10 << PLL_SHIFT_CNT_SELECT_OFST) & PLL_SHIFT_CNT_SELECT_MSK) -#define PLL_SHIFT_CNT_SLCT_C11_VAL ((0x11 << PLL_SHIFT_CNT_SELECT_OFST) & PLL_SHIFT_CNT_SELECT_MSK) -#define PLL_SHIFT_CNT_SLCT_C12_VAL ((0x12 << PLL_SHIFT_CNT_SELECT_OFST) & PLL_SHIFT_CNT_SELECT_MSK) -#define PLL_SHIFT_CNT_SLCT_C13_VAL ((0x13 << PLL_SHIFT_CNT_SELECT_OFST) & PLL_SHIFT_CNT_SELECT_MSK) -#define PLL_SHIFT_CNT_SLCT_C14_VAL ((0x14 << PLL_SHIFT_CNT_SELECT_OFST) & PLL_SHIFT_CNT_SELECT_MSK) -#define PLL_SHIFT_CNT_SLCT_C15_VAL ((0x15 << PLL_SHIFT_CNT_SELECT_OFST) & PLL_SHIFT_CNT_SELECT_MSK) -#define PLL_SHIFT_CNT_SLCT_C16_VAL ((0x16 << PLL_SHIFT_CNT_SELECT_OFST) & PLL_SHIFT_CNT_SELECT_MSK) -#define PLL_SHIFT_CNT_SLCT_C17_VAL ((0x17 << PLL_SHIFT_CNT_SELECT_OFST) & PLL_SHIFT_CNT_SELECT_MSK) - -#define PLL_SHIFT_UP_DOWN_OFST (21) -#define PLL_SHIFT_UP_DOWN_MSK (0x00000001 << PLL_SHIFT_UP_DOWN_OFST) -#define PLL_SHIFT_UP_DOWN_NEG_VAL ((0x0 << PLL_SHIFT_UP_DOWN_OFST) & PLL_SHIFT_UP_DOWN_MSK) -#define PLL_SHIFT_UP_DOWN_POS_VAL ((0x1 << PLL_SHIFT_UP_DOWN_OFST) & PLL_SHIFT_UP_DOWN_MSK) - -#define PLL_K_COUNTER_REG (0x07) -#define PLL_BANDWIDTH_REG (0x08) -#define PLL_CHARGEPUMP_REG (0x09) -#define PLL_VCO_DIV_REG (0x1c) -#define PLL_MIF_REG (0x1f) diff --git a/slsDetectorServers/moenchDetectorServer/ALTERA_PLL.h b/slsDetectorServers/moenchDetectorServer/ALTERA_PLL.h new file mode 120000 index 000000000..e665f009d --- /dev/null +++ b/slsDetectorServers/moenchDetectorServer/ALTERA_PLL.h @@ -0,0 +1 @@ +../slsDetectorServer/ALTERA_PLL.h \ No newline at end of file diff --git a/slsDetectorServers/moenchDetectorServer/slsDetectorFunctionList.c b/slsDetectorServers/moenchDetectorServer/slsDetectorFunctionList.c index 676a800e4..dd206f9c6 100644 --- a/slsDetectorServers/moenchDetectorServer/slsDetectorFunctionList.c +++ b/slsDetectorServers/moenchDetectorServer/slsDetectorFunctionList.c @@ -3,10 +3,11 @@ #include "versionAPI.h" #include "logger.h" -#ifndef VIRTUAL #include "AD9257.h" // commonServerFunctions.h, blackfin.h, ansi.h #include "LTC2620.h" // dacs #include "MAX1932.h" // hv +#include "ALTERA_PLL.h" // pll +#ifndef VIRTUAL #include "programfpga.h" #else #include "blackfin.h" @@ -471,7 +472,7 @@ void setupDetector() { now_ptr = 0; - resetPLL(); + ALTERA_PLL_ResetPLLAndReconfiguration(); resetCore(); resetPeripheral(); cleanFifos(); @@ -500,6 +501,8 @@ void setupDetector() { } } + // altera pll + ALTERA_PLL_SetDefines(PLL_CNTRL_REG, PLL_PARAM_REG, PLL_CNTRL_RCNFG_PRMTR_RST_MSK, PLL_CNTRL_WR_PRMTR_MSK, PLL_CNTRL_PLL_RST_MSK, PLL_CNTRL_ADDR_MSK, PLL_CNTRL_ADDR_OFST); bus_w(ADC_PORT_INVERT_REG, ADC_PORT_INVERT_VAL);//FIXME: got from moench config file @@ -1288,34 +1291,6 @@ int sendUDP(int enable) { return ((bus_r(addr) & CONFIG_GB10_SND_UDP_MSK) >> CONFIG_GB10_SND_UDP_OFST); } -void resetPLL() { -#ifdef VIRTUAL - return; -#endif - FILE_LOG(logINFO, ("Resetting PLL\n")); - // reset PLL Reconfiguration and PLL - bus_w(PLL_CNTRL_REG, bus_r(PLL_CNTRL_REG) | PLL_CNTRL_RCNFG_PRMTR_RST_MSK | PLL_CNTRL_PLL_RST_MSK); - usleep(WAIT_TIME_US_PLL); - bus_w(PLL_CNTRL_REG, bus_r(PLL_CNTRL_REG) & ~PLL_CNTRL_RCNFG_PRMTR_RST_MSK & ~PLL_CNTRL_PLL_RST_MSK); -} - -void setPllReconfigReg(uint32_t reg, uint32_t val) { -#ifdef VIRTUAL - return val; -#endif - FILE_LOG(logINFO, ("Setting PLL Reconfig Reg\n")); - // set parameter - bus_w(PLL_PARAM_REG, val); - - // set address - bus_w(PLL_CNTRL_REG, (reg << PLL_CNTRL_ADDR_OFST) & PLL_CNTRL_ADDR_MSK); - usleep(WAIT_TIME_US_PLL); - - //write parameter - bus_w(PLL_CNTRL_REG, bus_r(PLL_CNTRL_REG) | PLL_CNTRL_WR_PRMTR_MSK); - bus_w(PLL_CNTRL_REG, bus_r(PLL_CNTRL_REG) & ~PLL_CNTRL_WR_PRMTR_MSK); - usleep(WAIT_TIME_US_PLL); -} // ind can only be ADC_CLK or DBIT_CLK void configurePhase(CLKINDEX ind, int val) { @@ -1327,12 +1302,10 @@ void configurePhase(CLKINDEX ind, int val) { FILE_LOG(logINFO, ("Configuring Phase of C%d to %d\n", ind, val)); // reset only pll - bus_w(PLL_CNTRL_REG, bus_r(PLL_CNTRL_REG) | PLL_CNTRL_PLL_RST_MSK); - usleep(WAIT_TIME_US_PLL); - bus_w(PLL_CNTRL_REG, bus_r(PLL_CNTRL_REG) & ~PLL_CNTRL_PLL_RST_MSK); + ALTERA_PLL_ResetPLL(); // set mode register to polling mode - setPllReconfigReg(PLL_MODE_REG, PLL_MODE_PLLNG_MD_VAL); + ALTERA_PLL_SetModePolling(); int phase = 0, inv = 0; if (val > 0) { @@ -1345,13 +1318,7 @@ void configurePhase(CLKINDEX ind, int val) { } FILE_LOG(logINFO, ("\tphase out %d (0x%08x), inv:%d\n", phase, phase, inv)); - uint32_t value = (((phase << PLL_SHIFT_NUM_SHIFTS_OFST) & PLL_SHIFT_NUM_SHIFTS_MSK) | - (((int)ind << PLL_SHIFT_CNT_SELECT_OFST) & PLL_SHIFT_CNT_SELECT_MSK)); - FILE_LOG(logDEBUG1, ("\tC%d phase word:0x%08x\n", ind, value)); - - // write phase shift - setPllReconfigReg(PLL_PHASE_SHIFT_REG, value); - usleep(WAIT_TIME_US_PLL); + ALTERA_PLL_SetPhaseShift(phase, (int)ind, 0); clkPhase[ind] = val; } @@ -1372,35 +1339,8 @@ void configureFrequency(CLKINDEX ind, int val) { return getPhase(ind); } - // calculate output frequency - uint32_t total_div = PLL_VCO_FREQ_MHZ / val; - - // assume 50% duty cycle - uint32_t low_count = total_div / 2; - uint32_t high_count = low_count; - uint32_t odd_division = 0; - - // odd division - if (total_div > (2 * low_count)) { - ++high_count; - odd_division = 1; - } - FILE_LOG(logINFO, ("\tC%d: Low:%d, High:%d, Odd:%d\n", ind, low_count, high_count, odd_division)); - - uint32_t val = (((low_count << PLL_C_COUNTER_LW_CNT_OFST) & PLL_C_COUNTER_LW_CNT_MSK) | - ((high_count << PLL_C_COUNTER_HGH_CNT_OFST) & PLL_C_COUNTER_HGH_CNT_MSK) | - ((odd_division << PLL_C_COUNTER_ODD_DVSN_OFST) & PLL_C_COUNTER_ODD_DVSN_MSK) | - (((int)ind << PLL_C_COUNTER_SLCT_OFST) & PLL_C_COUNTER_SLCT_MSK)); - FILE_LOG(logDEBUG1, ("\tC%d word:0x%08x\n", ind, val)); - - // write frequency (post-scale output counter C) - setPllReconfigReg(PLL_C_COUNTER_REG, val); - usleep(WAIT_TIME_US_PLL); - - // reset only PLL - bus_w(PLL_CNTRL_REG, bus_r(PLL_CNTRL_REG) | PLL_CNTRL_PLL_RST_MSK); - usleep(WAIT_TIME_US_PLL); - bus_w(PLL_CNTRL_REG, bus_r(PLL_CNTRL_REG) & ~PLL_CNTRL_PLL_RST_MSK); + // Calculate and set output frequency + ALTERA_PLL_SetOuputFrequency (ind, PLL_VCO_FREQ_MHZ, val); clkDivider[ind] = PLL_VCO_FREQ_MHZ / (low_count + high_count); FILE_LOG(logINFO, ("\tC%d: Frequency set to %d MHz\n", ind, clkDivider[ind])); diff --git a/slsDetectorServers/moenchDetectorServer/slsDetectorServer_defs.h b/slsDetectorServers/moenchDetectorServer/slsDetectorServer_defs.h index a7cd843d2..6b19324cd 100644 --- a/slsDetectorServers/moenchDetectorServer/slsDetectorServer_defs.h +++ b/slsDetectorServers/moenchDetectorServer/slsDetectorServer_defs.h @@ -74,67 +74,3 @@ enum DACINDEX {D0, D1, D2, D3, D4, D5, D6, D7, D8, D9, #define MAXIMUM_ADC_CLK (40) #define PLL_VCO_FREQ_MHZ (400) -/** PLL Reconfiguration Registers */ -//https://www.altera.com/documentation/mcn1424769382940.html -#define PLL_MODE_REG (0x00) - -#define PLL_MODE_WT_RQUST_VAL (0) -#define PLL_MODE_PLLNG_MD_VAL (1) - -#define PLL_STATUS_REG (0x01) -#define PLL_START_REG (0x02) -#define PLL_N_COUNTER_REG (0x03) -#define PLL_M_COUNTER_REG (0x04) -#define PLL_C_COUNTER_REG (0x05) - -#define PLL_C_COUNTER_LW_CNT_OFST (0) -#define PLL_C_COUNTER_LW_CNT_MSK (0x000000FF << PLL_C_COUNTER_LW_CNT_OFST) -#define PLL_C_COUNTER_HGH_CNT_OFST (8) -#define PLL_C_COUNTER_HGH_CNT_MSK (0x000000FF << PLL_C_COUNTER_HGH_CNT_OFST) -/* total_div = lw_cnt + hgh_cnt */ -#define PLL_C_COUNTER_BYPSS_ENBL_OFST (16) -#define PLL_C_COUNTER_BYPSS_ENBL_MSK (0x00000001 << PLL_C_COUNTER_BYPSS_ENBL_OFST) -/* if bypss_enbl = 0, fout = f(vco)/total_div; else fout = f(vco) (c counter is bypassed) */ -#define PLL_C_COUNTER_ODD_DVSN_OFST (17) -#define PLL_C_COUNTER_ODD_DVSN_MSK (0x00000001 << PLL_C_COUNTER_ODD_DVSN_OFST) -/** if odd_dvsn = 0 (even), duty cycle = hgh_cnt/ total_div; else duty cycle = (hgh_cnt - 0.5) / total_div */ -#define PLL_C_COUNTER_SLCT_OFST (18) -#define PLL_C_COUNTER_SLCT_MSK (0x0000001F << PLL_C_COUNTER_SLCT_OFST) - -#define PLL_PHASE_SHIFT_REG (0x06) - -#define PLL_SHIFT_NUM_SHIFTS_OFST (0) -#define PLL_SHIFT_NUM_SHIFTS_MSK (0x0000FFFF << PLL_SHIFT_NUM_SHIFTS_OFST) - -#define PLL_SHIFT_CNT_SELECT_OFST (16) -#define PLL_SHIFT_CNT_SELECT_MSK (0x0000001F << PLL_SHIFT_CNT_SELECT_OFST) -#define PLL_SHIFT_CNT_SLCT_C0_VAL ((0x0 << PLL_SHIFT_CNT_SELECT_OFST) & PLL_SHIFT_CNT_SELECT_MSK) -#define PLL_SHIFT_CNT_SLCT_C1_VAL ((0x1 << PLL_SHIFT_CNT_SELECT_OFST) & PLL_SHIFT_CNT_SELECT_MSK) -#define PLL_SHIFT_CNT_SLCT_C2_VAL ((0x2 << PLL_SHIFT_CNT_SELECT_OFST) & PLL_SHIFT_CNT_SELECT_MSK) -#define PLL_SHIFT_CNT_SLCT_C3_VAL ((0x3 << PLL_SHIFT_CNT_SELECT_OFST) & PLL_SHIFT_CNT_SELECT_MSK) -#define PLL_SHIFT_CNT_SLCT_C4_VAL ((0x4 << PLL_SHIFT_CNT_SELECT_OFST) & PLL_SHIFT_CNT_SELECT_MSK) -#define PLL_SHIFT_CNT_SLCT_C5_VAL ((0x5 << PLL_SHIFT_CNT_SELECT_OFST) & PLL_SHIFT_CNT_SELECT_MSK) -#define PLL_SHIFT_CNT_SLCT_C6_VAL ((0x6 << PLL_SHIFT_CNT_SELECT_OFST) & PLL_SHIFT_CNT_SELECT_MSK) -#define PLL_SHIFT_CNT_SLCT_C7_VAL ((0x7 << PLL_SHIFT_CNT_SELECT_OFST) & PLL_SHIFT_CNT_SELECT_MSK) -#define PLL_SHIFT_CNT_SLCT_C8_VAL ((0x8 << PLL_SHIFT_CNT_SELECT_OFST) & PLL_SHIFT_CNT_SELECT_MSK) -#define PLL_SHIFT_CNT_SLCT_C9_VAL ((0x9 << PLL_SHIFT_CNT_SELECT_OFST) & PLL_SHIFT_CNT_SELECT_MSK) -#define PLL_SHIFT_CNT_SLCT_C10_VAL ((0x10 << PLL_SHIFT_CNT_SELECT_OFST) & PLL_SHIFT_CNT_SELECT_MSK) -#define PLL_SHIFT_CNT_SLCT_C11_VAL ((0x11 << PLL_SHIFT_CNT_SELECT_OFST) & PLL_SHIFT_CNT_SELECT_MSK) -#define PLL_SHIFT_CNT_SLCT_C12_VAL ((0x12 << PLL_SHIFT_CNT_SELECT_OFST) & PLL_SHIFT_CNT_SELECT_MSK) -#define PLL_SHIFT_CNT_SLCT_C13_VAL ((0x13 << PLL_SHIFT_CNT_SELECT_OFST) & PLL_SHIFT_CNT_SELECT_MSK) -#define PLL_SHIFT_CNT_SLCT_C14_VAL ((0x14 << PLL_SHIFT_CNT_SELECT_OFST) & PLL_SHIFT_CNT_SELECT_MSK) -#define PLL_SHIFT_CNT_SLCT_C15_VAL ((0x15 << PLL_SHIFT_CNT_SELECT_OFST) & PLL_SHIFT_CNT_SELECT_MSK) -#define PLL_SHIFT_CNT_SLCT_C16_VAL ((0x16 << PLL_SHIFT_CNT_SELECT_OFST) & PLL_SHIFT_CNT_SELECT_MSK) -#define PLL_SHIFT_CNT_SLCT_C17_VAL ((0x17 << PLL_SHIFT_CNT_SELECT_OFST) & PLL_SHIFT_CNT_SELECT_MSK) - -#define PLL_SHIFT_UP_DOWN_OFST (21) -#define PLL_SHIFT_UP_DOWN_MSK (0x00000001 << PLL_SHIFT_UP_DOWN_OFST) -#define PLL_SHIFT_UP_DOWN_NEG_VAL ((0x0 << PLL_SHIFT_UP_DOWN_OFST) & PLL_SHIFT_UP_DOWN_MSK) -#define PLL_SHIFT_UP_DOWN_POS_VAL ((0x1 << PLL_SHIFT_UP_DOWN_OFST) & PLL_SHIFT_UP_DOWN_MSK) - -#define PLL_K_COUNTER_REG (0x07) -#define PLL_BANDWIDTH_REG (0x08) -#define PLL_CHARGEPUMP_REG (0x09) -#define PLL_VCO_DIV_REG (0x1c) -#define PLL_MIF_REG (0x1f) - diff --git a/slsDetectorServers/slsDetectorServer/ALTERA_PLL.h b/slsDetectorServers/slsDetectorServer/ALTERA_PLL.h new file mode 100755 index 000000000..20ec6d3ec --- /dev/null +++ b/slsDetectorServers/slsDetectorServer/ALTERA_PLL.h @@ -0,0 +1,218 @@ +#pragma once + +#include // usleep + +/* Altera PLL DEFINES */ + +/** PLL Reconfiguration Registers */ +//https://www.altera.com/documentation/mcn1424769382940.html +#define ALTERA_PLL_MODE_REG (0x00) + +#define ALTERA_PLL_MODE_WT_RQUST_VAL (0) +#define ALTERA_PLL_MODE_PLLNG_MD_VAL (1) + +#define ALTERA_PLL_STATUS_REG (0x01) +#define ALTERA_PLL_START_REG (0x02) +#define ALTERA_PLL_N_COUNTER_REG (0x03) +#define ALTERA_PLL_M_COUNTER_REG (0x04) +#define ALTERA_PLL_C_COUNTER_REG (0x05) + +#define ALTERA_PLL_C_COUNTER_LW_CNT_OFST (0) +#define ALTERA_PLL_C_COUNTER_LW_CNT_MSK (0x000000FF << ALTERA_PLL_C_COUNTER_LW_CNT_OFST) +#define ALTERA_PLL_C_COUNTER_HGH_CNT_OFST (8) +#define ALTERA_PLL_C_COUNTER_HGH_CNT_MSK (0x000000FF << ALTERA_PLL_C_COUNTER_HGH_CNT_OFST) +/* total_div = lw_cnt + hgh_cnt */ +#define ALTERA_PLL_C_COUNTER_BYPSS_ENBL_OFST (16) +#define ALTERA_PLL_C_COUNTER_BYPSS_ENBL_MSK (0x00000001 << ALTERA_PLL_C_COUNTER_BYPSS_ENBL_OFST) +/* if bypss_enbl = 0, fout = f(vco)/total_div; else fout = f(vco) (c counter is bypassed) */ +#define ALTERA_PLL_C_COUNTER_ODD_DVSN_OFST (17) +#define ALTERA_PLL_C_COUNTER_ODD_DVSN_MSK (0x00000001 << ALTERA_PLL_C_COUNTER_ODD_DVSN_OFST) +/** if odd_dvsn = 0 (even), duty cycle = hgh_cnt/ total_div; else duty cycle = (hgh_cnt - 0.5) / total_div */ +#define ALTERA_PLL_C_COUNTER_SLCT_OFST (18) +#define ALTERA_PLL_C_COUNTER_SLCT_MSK (0x0000001F << ALTERA_PLL_C_COUNTER_SLCT_OFST) + +#define ALTERA_PLL_PHASE_SHIFT_REG (0x06) + +#define ALTERA_PLL_SHIFT_NUM_SHIFTS_OFST (0) +#define ALTERA_PLL_SHIFT_NUM_SHIFTS_MSK (0x0000FFFF << ALTERA_PLL_SHIFT_NUM_SHIFTS_OFST) + +#define ALTERA_PLL_SHIFT_CNT_SELECT_OFST (16) +#define ALTERA_PLL_SHIFT_CNT_SELECT_MSK (0x0000001F << ALTERA_PLL_SHIFT_CNT_SELECT_OFST) +#define ALTERA_PLL_SHIFT_CNT_SLCT_C0_VAL ((0x0 << ALTERA_PLL_SHIFT_CNT_SELECT_OFST) & ALTERA_PLL_SHIFT_CNT_SELECT_MSK) +#define ALTERA_PLL_SHIFT_CNT_SLCT_C1_VAL ((0x1 << ALTERA_PLL_SHIFT_CNT_SELECT_OFST) & ALTERA_PLL_SHIFT_CNT_SELECT_MSK) +#define ALTERA_PLL_SHIFT_CNT_SLCT_C2_VAL ((0x2 << ALTERA_PLL_SHIFT_CNT_SELECT_OFST) & ALTERA_PLL_SHIFT_CNT_SELECT_MSK) +#define ALTERA_PLL_SHIFT_CNT_SLCT_C3_VAL ((0x3 << ALTERA_PLL_SHIFT_CNT_SELECT_OFST) & ALTERA_PLL_SHIFT_CNT_SELECT_MSK) +#define ALTERA_PLL_SHIFT_CNT_SLCT_C4_VAL ((0x4 << ALTERA_PLL_SHIFT_CNT_SELECT_OFST) & ALTERA_PLL_SHIFT_CNT_SELECT_MSK) +#define ALTERA_PLL_SHIFT_CNT_SLCT_C5_VAL ((0x5 << ALTERA_PLL_SHIFT_CNT_SELECT_OFST) & ALTERA_PLL_SHIFT_CNT_SELECT_MSK) +#define ALTERA_PLL_SHIFT_CNT_SLCT_C6_VAL ((0x6 << ALTERA_PLL_SHIFT_CNT_SELECT_OFST) & ALTERA_PLL_SHIFT_CNT_SELECT_MSK) +#define ALTERA_PLL_SHIFT_CNT_SLCT_C7_VAL ((0x7 << ALTERA_PLL_SHIFT_CNT_SELECT_OFST) & ALTERA_PLL_SHIFT_CNT_SELECT_MSK) +#define ALTERA_PLL_SHIFT_CNT_SLCT_C8_VAL ((0x8 << ALTERA_PLL_SHIFT_CNT_SELECT_OFST) & ALTERA_PLL_SHIFT_CNT_SELECT_MSK) +#define ALTERA_PLL_SHIFT_CNT_SLCT_C9_VAL ((0x9 << ALTERA_PLL_SHIFT_CNT_SELECT_OFST) & ALTERA_PLL_SHIFT_CNT_SELECT_MSK) +#define ALTERA_PLL_SHIFT_CNT_SLCT_C10_VAL ((0x10 << ALTERA_PLL_SHIFT_CNT_SELECT_OFST) & ALTERA_PLL_SHIFT_CNT_SELECT_MSK) +#define ALTERA_PLL_SHIFT_CNT_SLCT_C11_VAL ((0x11 << ALTERA_PLL_SHIFT_CNT_SELECT_OFST) & ALTERA_PLL_SHIFT_CNT_SELECT_MSK) +#define ALTERA_PLL_SHIFT_CNT_SLCT_C12_VAL ((0x12 << ALTERA_PLL_SHIFT_CNT_SELECT_OFST) & ALTERA_PLL_SHIFT_CNT_SELECT_MSK) +#define ALTERA_PLL_SHIFT_CNT_SLCT_C13_VAL ((0x13 << ALTERA_PLL_SHIFT_CNT_SELECT_OFST) & ALTERA_PLL_SHIFT_CNT_SELECT_MSK) +#define ALTERA_PLL_SHIFT_CNT_SLCT_C14_VAL ((0x14 << ALTERA_PLL_SHIFT_CNT_SELECT_OFST) & ALTERA_PLL_SHIFT_CNT_SELECT_MSK) +#define ALTERA_PLL_SHIFT_CNT_SLCT_C15_VAL ((0x15 << ALTERA_PLL_SHIFT_CNT_SELECT_OFST) & ALTERA_PLL_SHIFT_CNT_SELECT_MSK) +#define ALTERA_PLL_SHIFT_CNT_SLCT_C16_VAL ((0x16 << ALTERA_PLL_SHIFT_CNT_SELECT_OFST) & ALTERA_PLL_SHIFT_CNT_SELECT_MSK) +#define ALTERA_PLL_SHIFT_CNT_SLCT_C17_VAL ((0x17 << ALTERA_PLL_SHIFT_CNT_SELECT_OFST) & ALTERA_PLL_SHIFT_CNT_SELECT_MSK) + +#define ALTERA_PLL_SHIFT_UP_DOWN_OFST (21) +#define ALTERA_PLL_SHIFT_UP_DOWN_MSK (0x00000001 << ALTERA_PLL_SHIFT_UP_DOWN_OFST) +#define ALTERA_PLL_SHIFT_UP_DOWN_NEG_VAL ((0x0 << ALTERA_PLL_SHIFT_UP_DOWN_OFST) & ALTERA_PLL_SHIFT_UP_DOWN_MSK) +#define ALTERA_PLL_SHIFT_UP_DOWN_POS_VAL ((0x1 << ALTERA_PLL_SHIFT_UP_DOWN_OFST) & ALTERA_PLL_SHIFT_UP_DOWN_MSK) + +#define ALTERA_PLL_K_COUNTER_REG (0x07) +#define ALTERA_PLL_BANDWIDTH_REG (0x08) +#define ALTERA_PLL_CHARGEPUMP_REG (0x09) +#define ALTERA_PLL_VCO_DIV_REG (0x1c) +#define ALTERA_PLL_MIF_REG (0x1f) + + +#define ALTERA_PLL_WAIT_TIME_US (10 * 1000) + + +uint32_t ALTERA_PLL_Cntrl_Reg = 0x0; +uint32_t ALTERA_PLL_Param_Reg = 0x0; +uint32_t ALTERA_PLL_Cntrl_RcnfgPrmtrRstMask = 0x0; +uint32_t ALTERA_PLL_Cntrl_WrPrmtrMask = 0x0; +uint32_t ALTERA_PLL_Cntrl_PLLRstMask = 0x0; +uint32_t ALTERA_PLL_Cntrl_AddrMask = 0x0; +int ALTERA_PLL_Cntrl_AddrOfst = 0; + + +/** + * Set Defines + * @param creg control register + * @param preg parameter register + * @param rprmsk reconfig parameter reset mask + * @param wpmsk write parameter mask + * @param prmsk pll reset mask + * @param amsk address mask + * @param aofst address offset + */ +void ALTERA_PLL_SetDefines(uint32_t creg, uint32_t preg, uint32_t rprmsk, uint32_t wpmsk, uint32_t prmsk, uint32_t amsk, int aofst) { + ALTERA_PLL_Cntrl_Reg = creg; + ALTERA_PLL_Param_Reg = preg; + ALTERA_PLL_Cntrl_RcnfgPrmtrRstMask = rprmsk; + ALTERA_PLL_Cntrl_WrPrmtrMask = wpmsk; + ALTERA_PLL_Cntrl_PLLRstMask = prmsk; + ALTERA_PLL_Cntrl_AddrMask = amsk; + ALTERA_PLL_Cntrl_AddrOfst = aofst; +} + +/** + * Reset only PLL + */ +void ALTERA_PLL_ResetPLL () { + FILE_LOG(logINFO, ("Resetting only PLL\n")); + + bus_w(ALTERA_PLL_Cntrl_Reg, bus_r(ALTERA_PLL_Cntrl_Reg) | ALTERA_PLL_Cntrl_PLLRstMask); + usleep(ALTERA_PLL_WAIT_TIME_US); + bus_w(ALTERA_PLL_Cntrl_Reg, bus_r(ALTERA_PLL_Cntrl_Reg) & ~ALTERA_PLL_Cntrl_PLLRstMask); + +} + +/** + * Reset PLL Reconfiguration and PLL + */ +void ALTERA_PLL_ResetPLLAndReconfiguration () { + FILE_LOG(logINFO, ("Resetting PLL and Reconfiguration\n")); + + bus_w(ALTERA_PLL_Cntrl_Reg, bus_r(ALTERA_PLL_Cntrl_Reg) | ALTERA_PLL_Cntrl_RcnfgPrmtrRstMask | ALTERA_PLL_Cntrl_PLLRstMask); + usleep(ALTERA_PLL_WAIT_TIME_US); + bus_w(ALTERA_PLL_Cntrl_Reg, bus_r(ALTERA_PLL_Cntrl_Reg) & ~ALTERA_PLL_Cntrl_RcnfgPrmtrRstMask & ~ALTERA_PLL_Cntrl_PLLRstMask); +} + + +/** + * Set PLL Reconfig register + * @param reg register + * @param val value + */ +void ALTERA_PLL_SetPllReconfigReg(uint32_t reg, uint32_t val) { + FILE_LOG(logINFO, ("Setting PLL Reconfig Reg\n")); + + // set parameter + bus_w(ALTERA_PLL_Param_Reg, val); + + // set address + bus_w(ALTERA_PLL_Cntrl_Reg, (reg << ALTERA_PLL_Cntrl_AddrOfst) & ALTERA_PLL_Cntrl_AddrMask); + usleep(ALTERA_PLL_WAIT_TIME_US); + + //write parameter + bus_w(ALTERA_PLL_Cntrl_Reg, bus_r(ALTERA_PLL_Cntrl_Reg) | ALTERA_PLL_Cntrl_WrPrmtrMask); + bus_w(ALTERA_PLL_Cntrl_Reg, bus_r(ALTERA_PLL_Cntrl_Reg) & ~ALTERA_PLL_Cntrl_WrPrmtrMask); + usleep(ALTERA_PLL_WAIT_TIME_US); +} + +/** + * Write Phase Shift + * @param phase phase shift + * @param clkIndex clock index + * @param pos 1 if up down direction of shift is positive, else 0 + */ +void ALTERA_PLL_SetPhaseShift(int32_t phase, int clkIndex, int pos) { + FILE_LOG(logINFO, ("\tWriting PLL Phase Shift\n")); + uint32_t value = (((phase << ALTERA_PLL_SHIFT_NUM_SHIFTS_OFST) & ALTERA_PLL_SHIFT_NUM_SHIFTS_MSK) | + ((clkIndex << ALTERA_PLL_SHIFT_CNT_SELECT_OFST) & ALTERA_PLL_SHIFT_CNT_SELECT_MSK) | + (pos ? ALTERA_PLL_SHIFT_UP_DOWN_POS_VAL : ALTERA_PLL_SHIFT_UP_DOWN_NEG_VAL)); + + FILE_LOG(logDEBUG1, ("\tC%d phase word:0x%08x\n", clkIndex, value)); + + // write phase shift + ALTERA_PLL_SetPllReconfigReg(ALTERA_PLL_PHASE_SHIFT_REG, value); + usleep(ALTERA_PLL_WAIT_TIME_US); +} + +/** + * Set PLL mode register to polling mode + */ +void ALTERA_PLL_SetModePolling() { + FILE_LOG(logINFO, ("\tSetting Polling Mode\n")); + ALTERA_PLL_SetPllReconfigReg(ALTERA_PLL_MODE_REG, ALTERA_PLL_MODE_PLLNG_MD_VAL); + usleep(ALTERA_PLL_WAIT_TIME_US); +} + +/** + * Calculate and write output frequency + * @param clkIndex clock index + * @param pllVCOFreqMhz PLL VCO Frequency in Mhz + * @param value frequency to set to + */ +void ALTERA_PLL_SetOuputFrequency (int clkIndex, int pllVCOFreqMhz, int value) { + FILE_LOG(logINFO, ("\tC%d: Setting output frequency\n")); + + // calculate output frequency + uint32_t total_div = pllVCOFreqMhz / value; + + // assume 50% duty cycle + uint32_t low_count = total_div / 2; + uint32_t high_count = low_count; + uint32_t odd_division = 0; + + // odd division + if (total_div > (2 * low_count)) { + ++high_count; + odd_division = 1; + } + FILE_LOG(logINFO, ("\tC%d: Low:%d, High:%d, Odd:%d\n", clkIndex, low_count, high_count, odd_division)); + + // command to set output frequency + uint32_t val = (((low_count << ALTERA_PLL_C_COUNTER_LW_CNT_OFST) & ALTERA_PLL_C_COUNTER_LW_CNT_MSK) | + ((high_count << ALTERA_PLL_C_COUNTER_HGH_CNT_OFST) & ALTERA_PLL_C_COUNTER_HGH_CNT_MSK) | + ((odd_division << ALTERA_PLL_C_COUNTER_ODD_DVSN_OFST) & ALTERA_PLL_C_COUNTER_ODD_DVSN_MSK) | + ((clkIndex << ALTERA_PLL_C_COUNTER_SLCT_OFST) & ALTERA_PLL_C_COUNTER_SLCT_MSK)); + FILE_LOG(logDEBUG1, ("\tC%d word:0x%08x\n", clkIndex, val)); + + // write frequency (post-scale output counter C) + ALTERA_PLL_SetPllReconfigReg(ALTERA_PLL_C_COUNTER_REG, val); + usleep(ALTERA_PLL_WAIT_TIME_US); + + // reset only PLL + bus_w(ALTERA_PLL_Cntrl_Reg, bus_r(ALTERA_PLL_Cntrl_Reg) | ALTERA_PLL_Cntrl_PLLRstMask); + usleep(ALTERA_PLL_WAIT_TIME_US); + bus_w(ALTERA_PLL_Cntrl_Reg, bus_r(ALTERA_PLL_Cntrl_Reg) & ~ALTERA_PLL_Cntrl_PLLRstMask); +} + + diff --git a/slsSupportLib/include/versionAPI.h b/slsSupportLib/include/versionAPI.h index d46621ea6..db4a4581f 100644 --- a/slsSupportLib/include/versionAPI.h +++ b/slsSupportLib/include/versionAPI.h @@ -1,7 +1,7 @@ /** API versions */ #define APIRECEIVER 0x180927 #define APIEIGER 0x181031 -#define APIJUNGFRAU 0x181102 +#define APIJUNGFRAU 0x190111 #define APIGOTTHARD 0x190108 #define APICTB 0x180101 #define APIMOENCH 0x181108