set clock divider, phase and get clock freq for gotthard2, priliminary

This commit is contained in:
2019-10-17 16:39:41 +02:00
parent 0a3905802f
commit be50344b45
21 changed files with 1119 additions and 54 deletions

View File

@ -8,6 +8,7 @@ add_executable(gotthard2DetectorServer_virtual
../slsDetectorServer/src/DAC6571.c
../slsDetectorServer/src/common.c
../slsDetectorServer/src/LTC2620_Driver.c
../slsDetectorServer/src/ALTERA_PLL_CYCLONE10.c
)
include_directories(

View File

@ -5,14 +5,14 @@ support_lib = ../../slsSupportLib/include/
CROSS = nios2-buildroot-linux-gnu-
CC = $(CROSS)gcc
CFLAGS += -Wall -DGOTTHARD2D -DSTOP_SERVER -I$(main_inc) -I$(support_lib) -I$(current_dir)#-DVERBOSEI #-DVERBOSE
CFLAGS += -Wall -DGOTTHARD2D -DSTOP_SERVER -I$(main_inc) -I$(support_lib) -I$(current_dir) -DDEBUG1 #-DVERBOSEI #-DVERBOSE
LDLIBS += -lm
PROGS = gotthard2DetectorServer
DESTDIR ?= bin
INSTMODE = 0777
SRCS = slsDetectorFunctionList.c
SRCS += $(main_src)slsDetectorServer.c $(main_src)slsDetectorServer_funcs.c $(main_src)communication_funcs.c $(main_src)nios.c $(main_src)common.c $(main_src)DAC6571.c $(main_src)LTC2620_Driver.c
SRCS += $(main_src)slsDetectorServer.c $(main_src)slsDetectorServer_funcs.c $(main_src)communication_funcs.c $(main_src)nios.c $(main_src)common.c $(main_src)DAC6571.c $(main_src)LTC2620_Driver.c $(main_src)ALTERA_PLL_CYCLONE10.c
OBJS = $(SRCS:.c=.o)

View File

@ -2,8 +2,35 @@
/* Definitions for FPGA*/
#define REG_OFFSET (4)
/* cspbase 0x1804 0000 */
#define BASE_READOUT_PLL (0x000)
#define BASE_SYSTEM_PLL (0x800)
#define READOUT_PLL_RESET_REG (0x1 * REG_OFFSET + BASE_READOUT_PLL) //TODO
#define READOUT_PLL_RESET_OFST (0)
#define READOUT_PLL_RESET_MSK (0x00000001 << READOUT_PLL_RESET_OFST)
#define SYSTEM_PLL_RESET_REG (0x1 * REG_OFFSET + BASE_SYSTEM_PLL) //TODO
#define SYSTEM_PLL_RESET_OFST (0)
#define SYSTEM_PLL_RESET_MSK (0x00000001 << SYSTEM_PLL_RESET_OFST)
#define READOUT_PLL_WAIT_REG (0x2 * REG_OFFSET + BASE_READOUT_PLL) //TODO
#define READOUT_PLL_WAIT_OFST (0)
#define READOUT_PLL_WAIT_MSK (0x00000001 << READOUT_PLL_WAIT_OFST)
#define SYSTEM_PLL_WAIT_REG (0x2 * REG_OFFSET + BASE_SYSTEM_PLL) //TODO
#define SYSTEM_PLL_WAIT_OFST (0)
#define SYSTEM_PLL_WAIT_MSK (0x00000001 << SYSTEM_PLL_WAIT_OFST)
/* cspbase 0x1806 0000 */
#define BASE_CONTROL (0x000)
#define BASE_ACQUISITION (0x200)
#define BASE_ACQUISITION (0x200) //???TODO
#define BASE_UDP_RAM (0x1000)
/* Module Control Board Serial Number register */
@ -44,7 +71,9 @@
#define DTA_OFFSET_REG (0x104 * REG_OFFSET + BASE_CONTROL)
/* Pattern Control FPGA registers TODO --------------------------------------------------*/
/* BASE_ACQUISITION FPGA registers TODO --------------------------------------------------*/
/* Cycles left 64bit Register */
#define GET_CYCLES_LSB_REG (0x10 + BASE_ACQUISITION)

View File

@ -6,6 +6,7 @@
#include "DAC6571.h"
#include "LTC2620_Driver.h"
#include "common.h"
#include "ALTERA_PLL_CYCLONE10.h" // pll
#ifdef VIRTUAL
#include "communication_funcs_UDP.h"
#endif
@ -17,7 +18,7 @@
#include <time.h>
#endif
enum {READOUT_PLL, SYSTEM_PLL};
// Global variable from slsDetectorServer_funcs
@ -34,8 +35,8 @@ int virtual_status = 0;
int virtual_stop = 0;
#endif
uint32_t clkDivider[NUM_CLOCKS] = {125, 20, 80};
int32_t clkPhase[NUM_CLOCKS] = {0, 0, 0, 0, 0, 0};
uint32_t clkDivider[NUM_CLOCKS] = {0, 0, 0, 0, 0, 0};
int highvoltage = 0;
int dacValues[NDAC] = {0};
int detPos[2] = {0, 0};
@ -338,12 +339,20 @@ void initStopServer() {
void setupDetector() {
FILE_LOG(logINFO, ("This Server is for 1 Gotthard2 module \n"));
clkDivider[RUN_CLK] = DEFAULT_RUN_CLK;
clkDivider[TICK_CLK] = DEFAULT_TICK_CLK;
clkDivider[SAMPLING_CLK] = DEFAULT_SAMPLING_CLK;
clkDivider[READOUT_C0] = DEFAULT_READOUT_C0;
clkDivider[READOUT_C1] = DEFAULT_READOUT_C1;
clkDivider[SYSTEM_C0] = DEFAULT_SYSTEM_C0;
clkDivider[SYSTEM_C1] = DEFAULT_SYSTEM_C1;
clkDivider[SYSTEM_C2] = DEFAULT_SYSTEM_C2;
clkDivider[SYSTEM_C3] = DEFAULT_SYSTEM_C3;
highvoltage = 0;
{
int i;
for (i = 0; i < NUM_CLOCKS; ++i) {
clkPhase[i] = 0;
}
for (i = 0; i < NDAC; ++i) {
dacValues[i] = 0;
}
@ -351,6 +360,10 @@ void setupDetector() {
#ifndef VIRTUAL
// pll defines
ALTERA_PLL_C10_SetDefines(REG_OFFSET, BASE_READOUT_PLL, BASE_SYSTEM_PLL, READOUT_PLL_RESET_REG, SYSTEM_PLL_RESET_REG, READOUT_PLL_RESET_MSK, SYSTEM_PLL_RESET_MSK, READOUT_PLL_WAIT_REG, SYSTEM_PLL_WAIT_REG, READOUT_PLL_WAIT_MSK, SYSTEM_PLL_WAIT_MSK, READOUT_PLL_VCO_FREQ_HZ, SYSTEM_PLL_VCO_FREQ_HZ);
ALTERA_PLL_C10_ResetPLL(READOUT_PLL);
ALTERA_PLL_C10_ResetPLL(SYSTEM_PLL);
// hv
DAC6571_SetDefines(HV_HARD_MAX_VOLTAGE, HV_DRIVER_FILE_NAME);
// dacs
@ -396,7 +409,7 @@ int64_t setTimer(enum timerIndex ind, int64_t val) {
int64_t retval = -1;
switch(ind){
switch(ind) {
case FRAME_NUMBER: // defined in sls_detector_defs.h (general)
if(val >= 0) {
@ -407,20 +420,20 @@ int64_t setTimer(enum timerIndex ind, int64_t val) {
break;
case ACQUISITION_TIME:
if(val >= 0){
if(val >= 0) {
FILE_LOG(logINFO, ("Setting exptime: %lldns\n", (long long int)val));
val *= (1E-3 * RUN_CLK);
val *= (1E-9 * READOUT_C0); //TODO
}
retval = set64BitReg(val, SET_EXPTIME_LSB_REG, SET_EXPTIME_MSB_REG) / (1E-3 * RUN_CLK); // CLK defined in slsDetectorServer_defs.h
retval = set64BitReg(val, SET_EXPTIME_LSB_REG, SET_EXPTIME_MSB_REG) / (1E-9 * READOUT_C0); //TODO
FILE_LOG(logDEBUG1, ("Getting exptime: %lldns\n", (long long int)retval));
break;
case FRAME_PERIOD:
if(val >= 0){
FILE_LOG(logINFO, ("Setting period: %lldns\n",(long long int)val));
val *= (1E-3 * TICK_CLK);
val *= (1E-9 * SYSTEM_C0);//TODO
}
retval = set64BitReg(val, SET_PERIOD_LSB_REG, SET_PERIOD_MSB_REG )/ (1E-3 * TICK_CLK);
retval = set64BitReg(val, SET_PERIOD_LSB_REG, SET_PERIOD_MSB_REG )/ (1E-9 * SYSTEM_C0); //TODO
FILE_LOG(logDEBUG1, ("Getting period: %lldns\n", (long long int)retval));
break;
case CYCLES_NUMBER:
@ -445,17 +458,17 @@ int validateTimer(enum timerIndex ind, int64_t val, int64_t retval) {
switch(ind) {
case ACQUISITION_TIME:
// convert to freq
val *= (1E-3 * RUN_CLK);
val *= (1E-9 * READOUT_C0);//TODO
// convert back to timer
val = (val) / (1E-3 * RUN_CLK);
val = (val) / (1E-9 * READOUT_C0);//TODO
if (val != retval)
return FAIL;
break;
case FRAME_PERIOD:
// convert to freq
val *= (1E-3 * TICK_CLK);
val *= (1E-9 * SYSTEM_C0);//TODO
// convert back to timer
val = (val) / (1E-3 * TICK_CLK);
val = (val) / (1E-9 * SYSTEM_C0);//TODO
if (val != retval)
return FAIL;
break;
@ -675,6 +688,152 @@ void calcChecksum(udp_header* udp) {
udp->ip_checksum = checksum;
}
// Detector Specific
int setPhase(enum CLKINDEX ind, int val, int degrees) {
char clock_names[6][15]={"Readout_c0", "Readout_c1", "System_c0", "System_c1", "System_c2", "System_c3"};
FILE_LOG(logDEBUG1, ("\tConfiguring Phase of C%d(%s) to %d (degree mode: %d)\n", ind, clock_names[ind], val, degrees));
int maxShift = getMaxPhase(ind);
int valShift = val;
// convert to phase shift
if (degrees) {
ConvertToDifferentRange(0, 359, 0, maxShift - 1, val, &valShift);
}
FILE_LOG(logDEBUG1, ("\tphase shift: %d (degrees/shift: %d)\n", valShift, val));
int relativePhase = valShift - clkPhase[ind];
FILE_LOG(logDEBUG1, ("\trelative phase shift: %d (Current phase: %d)\n", relativePhase, clkPhase[ind]));
// same phase
if (!relativePhase) {
FILE_LOG(logINFO, ("\tNothing to do in Phase Shift\n"));
return OK;
}
FILE_LOG(logINFOBLUE, ("\tConfiguring Phase of C%d(%s) to %d (degree mode: %d)\n", ind, clock_names[ind], val, degrees));
int phase = 0;
if (relativePhase > 0) {
phase = (maxShift - relativePhase);
} else {
phase = (-1) * relativePhase;
}
FILE_LOG(logDEBUG1, ("\t[Single Direction] Phase:%d (0x%x). Max Phase shifts:%d\n", phase, phase, maxShift));
int pllIndex = ind >= SYSTEM_C0 ? SYSTEM_PLL : READOUT_PLL;
int clkIndex = ind >= SYSTEM_C0 ? ind - SYSTEM_C0 : ind;
int ret = ALTERA_PLL_C10_SetPhaseShift(pllIndex, clkIndex, phase, 0);
clkPhase[ind] = valShift;
return ret;
}
int getPhase(enum CLKINDEX ind, int degrees) {
if (!degrees)
return clkPhase[ind];
// convert back to degrees
int val = 0;
ConvertToDifferentRange(0, getMaxPhase(ind) - 1, 0, 359, clkPhase[ind], &val);
return val;
}
int getMaxPhase(enum CLKINDEX ind) {
int vcofreq = getVCOFrequency(ind);
int maxshiftstep = ALTERA_PLL_C10_GetMaxPhaseShiftStepsofVCO();
int ret = ((double)vcofreq / (double)clkDivider[ind]) * maxshiftstep;
char clock_names[6][15]={"Readout_c0", "Readout_c1", "System_c0", "System_c1", "System_c2", "System_c3"};
FILE_LOG(logDEBUG1, ("\tMax Phase Shift (%s): %d (Clock: %d Hz, VCO:%d Hz)\n",
clock_names[ind], ret, clkDivider[ind], vcofreq));
return ret;
}
int validatePhaseinDegrees(enum CLKINDEX ind, int val, int retval) {
if (val == -1)
return OK;
FILE_LOG(logDEBUG1, ("validating phase in degrees for clk %d\n", (int)ind));
int maxShift = getMaxPhase(ind);
// convert degrees to shift
// convert degrees to shift
int valShift = 0;
ConvertToDifferentRange(0, 359, 0, maxShift - 1, val, &valShift);
// convert back to degrees
ConvertToDifferentRange(0, maxShift - 1, 0, 359, valShift, &val);
if (val == retval)
return OK;
return FAIL;
}
int getFrequency(enum CLKINDEX ind) {
return clkDivider[ind];
}
int getVCOFrequency(enum CLKINDEX ind) {
int pllIndex = ind >= SYSTEM_C0 ? SYSTEM_PLL : READOUT_PLL;
return ALTERA_PLL_C10_GetVCOFrequency(pllIndex);
}
int getMaxClockDivider() {
return ALTERA_PLL_C10_GetMaxClockDivider();
}
int setClockDivider(enum CLKINDEX ind, int val) {
char clock_names[6][15]={"Readout_c0", "Readout_c1", "System_c0", "System_c1", "System_c2", "System_c3"};
int vcofreq = getVCOFrequency(ind);
int currentdiv = vcofreq / clkDivider[ind];
int newfreq = vcofreq / val;
FILE_LOG(logINFO, ("\tConfiguring Click Divider of C%d(%s) from %d (%d Hz) to %d (%d Hz). \n\t(Vcofreq: %d Hz)\n", ind, clock_names[ind], currentdiv, clkDivider[ind], val, newfreq, vcofreq));
// Remembering old phases
int oldPhases[NUM_CLOCKS];
{
int i = 0;
for (i = 0; i < NUM_CLOCKS; ++i) {
oldPhases [i] = getPhase(i, 0);
FILE_LOG(logDEBUG1, ("\tRemembering C%d (%s) phase: %d\n", ind, clock_names, oldPhases[i]));
}
}
// Calculate and set output frequency
int pllIndex = ind >= SYSTEM_C0 ? SYSTEM_PLL : READOUT_PLL;
int clkIndex = ind >= SYSTEM_C0 ? ind - SYSTEM_C0 : ind;
int ret = ALTERA_PLL_C10_SetOuputFrequency (pllIndex, clkIndex, newfreq);
clkDivider[ind] = newfreq;
FILE_LOG(logINFO, ("\tC%d(%s): Clock Divider set to %d (%d Hz)\n", ind, clock_names[ind], val, clkDivider[ind]));
// phase is reset by pll (when setting output frequency)
if (ind >= READOUT_C0) {
clkPhase[READOUT_C0] = 0;
clkPhase[READOUT_C1] = 0;
} else {
clkPhase[SYSTEM_C0] = 0;
clkPhase[SYSTEM_C1] = 0;
clkPhase[SYSTEM_C2] = 0;
clkPhase[SYSTEM_C3] = 0;
}
// set the phase if custom set
{
int i = 0;
for (i = 0; i < NUM_CLOCKS; ++i) {
if (clkPhase[i] != oldPhases[i]) {
FILE_LOG(logINFO, ("\tPhase reset by PLL\n\tCorrecting C%d(%s) to %d\n", i, clock_names[i], oldPhases[i]));
setPhase(i, oldPhases[i], 0);
}
}
}
return ret;
}
int getClockDivider(enum CLKINDEX ind) {
return (getVCOFrequency(ind) / clkDivider[ind]);
}
/* aquisition */

View File

@ -23,14 +23,19 @@
#define DEFAULT_EXPTIME (1 * 1000 * 1000) // 1 ms
#define DEFAULT_PERIOD (1 * 1000 * 1000 * 1000) // 1 s
#define DEFAULT_HIGH_VOLTAGE (0)
#define DEFAULT_RUN_CLK (125)
#define DEFAULT_TICK_CLK (20) // will be fixed later. Not configurable
#define DEFAULT_SAMPLING_CLK (80)
#define DEFAULT_READOUT_C0 (144444448) // rdo_clk, 144 MHz
#define DEFAULT_READOUT_C1 (288888896) // rdo_x2_clk, 288 MHz
#define DEFAULT_SYSTEM_C0 (144444448) // run_clk, 144 MHz
#define DEFAULT_SYSTEM_C1 (72222224) // chip_clk, 72 MHz
#define DEFAULT_SYSTEM_C2 (18055556) // sync_clk, 18 MHz
#define DEFAULT_SYSTEM_C3 (144444448) // str_clk, 144 MHz
#define DEFAULT_TX_UDP_PORT (0x7e9a)
/* Firmware Definitions */
#define IP_HEADER_SIZE (20)
#define READOUT_PLL_VCO_FREQ_HZ (866666688) // Hz
#define SYSTEM_PLL_VCO_FREQ_HZ (722222240) // Hz
/** Other Definitions */
#define BIT16_MASK (0xFFFF)
@ -71,7 +76,7 @@ enum DACINDEX {G_VREF_H_ADC, /* 0 */ \
0, /* 14 (0 mV) DAC_UNUSED2*/ \
1400 /* 15 (700 mV) VCOM_ADC2*/ \
};
enum CLKINDEX {RUN_CLK, TICK_CLK, SAMPLING_CLK, NUM_CLOCKS};
enum CLKINDEX {READOUT_C0, READOUT_C1, SYSTEM_C0, SYSTEM_C1, SYSTEM_C2, SYSTEM_C3, NUM_CLOCKS};
/* Struct Definitions */
typedef struct udp_header_struct {