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

This commit is contained in:
maliakal_d 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 {

View File

@ -0,0 +1,72 @@
#pragma once
#include <inttypes.h>
/**
* Set defines
* @param regofst register offset
* @param baseaddr0 base address of pll 0
* @param baseaddr1 base address of pll 1
* @param resetreg0 reset register of pll 0
* @param resetreg1 reset register of pll 1
* @param resetmsk reset mask of pll 0
* @param resetms1 reset mask of pll 1
* @param waitreg0 wait register of pll 0
* @param waitreg1 wait register of pll 1
* @param waitmsk0 wait mask of pll 0
* @param waitmsk1 wait mask of pll 1
* @param vcofreq0 vco frequency of pll 0
* @param vcofreq1 vco frequency of pll 1
*/
void ALTERA_PLL_C10_SetDefines(int regofst, uint32_t baseaddr0, uint32_t baseaddr1, uint32_t resetreg0, uint32_t resetreg1, uint32_t resetmsk0, uint32_t resetmsk1, uint32_t waitreg0, uint32_t waitreg1, uint32_t waitmsk0, uint32_t waitmsk1, int vcofreq0, int vcofreq1);
/**
* Get Max Clock Divider
*/
int ALTERA_PLL_C10_GetMaxClockDivider();
/**
* Get VCO frequency based on pll Index
* @param pllIndex pll index
* @returns VCO frequency
*/
int ALTERA_PLL_C10_GetVCOFrequency(int pllIndex);
/**
* Get maximum phase shift steps of vco frequency
* @returns max phase shift steps of vco
*/
int ALTERA_PLL_C10_GetMaxPhaseShiftStepsofVCO();
/**
* Start reconfiguration and wait till its complete
* @param pllIndex pll index
* @returns FAIL if wait request signal took too long to deassert, else OK
*/
int ALTERA_PLL_C10_Reconfigure(int pllIndex);
/**
* Reset pll
* @param pllIndex pll index
*/
void ALTERA_PLL_C10_ResetPLL (int pllIndex);
/**
* Set Phase Shift
* @param pllIndex pll index
* @param clkIndex clock index
* @param phase phase shift
* @param pos 1 if up down direction of shift is positive, else 0
* @returns OK or FAIL or reconfigure
*/
int ALTERA_PLL_C10_SetPhaseShift(int pllIndex, int clkIndex, int phase, int pos);
/**
* Calculate and write output frequency
* @param pllIndex pll index
* @param clkIndex clock index
* @param value frequency in Hz to set to
* @returns OK or FAIL of reconfigure
*/
int ALTERA_PLL_C10_SetOuputFrequency (int pllIndex, int clkIndex, int value);

View File

@ -3,6 +3,19 @@
#include <sys/types.h>
#include <inttypes.h>
/**
* Write into a 32 bit register for cspbase 1
* @param offset address offset
* @param data 32 bit data
*/
void bus_w_csp1(u_int32_t offset, u_int32_t data);
/**
* Read from a 32 bit register for cspbase 1
* @param offset address offset
* @retuns 32 bit data read
*/
u_int32_t bus_r_csp1(u_int32_t offset);
/**
* Write into a 32 bit register

View File

@ -380,8 +380,25 @@ uint64_t writePatternWord(int addr, uint64_t word);
int setPatternWaitAddress(int level, int addr);
uint64_t setPatternWaitTime(int level, uint64_t t);
void setPatternLoop(int level, int *startAddr, int *stopAddr, int *nLoop);
#elif GOTTHARD2D
int setPhase(enum CLKINDEX ind, int val, int degrees);
int getPhase(enum CLKINDEX ind, int degrees);
int getMaxPhase(enum CLKINDEX ind);
int validatePhaseinDegrees(enum CLKINDEX ind, int val, int retval);
//int setFrequency(enum CLKINDEX ind, int val);
int getFrequency(enum CLKINDEX ind);
int getVCOFrequency(enum CLKINDEX ind);
int getMaxClockDivider();
int setClockDivider(enum CLKINDEX ind, int val);
int getClockDivider(enum CLKINDEX ind);
#endif
#if defined(JUNGFRAUD) || defined(EIGERD)
int setNetworkParameter(enum NETWORKINDEX mode, int value);
#endif

View File

@ -144,3 +144,10 @@ int set_storeinram(int);
int get_storeinram(int);
int set_readout_mode(int);
int get_readout_mode(int);
int set_clock_frequency(int);
int get_clock_frequency(int);
int set_clock_phase(int);
int get_clock_phase(int);
int get_max_clock_phase_shift(int);
int set_clock_divider(int);
int get_clock_divider(int);

View File

@ -0,0 +1,195 @@
#include "ALTERA_PLL_CYCLONE10.h"
#include "clogger.h"
#include "nios.h"
#include "sls_detector_defs.h"
#include <unistd.h> // usleep
/* Altera PLL CYCLONE 10 DEFINES */
/** PLL Reconfiguration Registers */
// https://www.intel.com/content/dam/www/programmable/us/en/pdfs/literature/an/an728.pdf
// c counter (C0-C8 (+1 to base address))
#define ALTERA_PLL_C10_C_COUNTER_BASE_REG (0x0C0)
#define ALTERA_PLL_C10_C_COUNTER_MAX_DIVIDER_VAL (0xFF)
#define ALTERA_PLL_C10_C_COUNTER_LW_CNT_OFST (0)
#define ALTERA_PLL_C10_C_COUNTER_LW_CNT_MSK (0x000000FF << ALTERA_PLL_C10_C_COUNTER_LW_CNT_OFST)
#define ALTERA_PLL_C10_C_COUNTER_HGH_CNT_OFST (8)
#define ALTERA_PLL_C10_C_COUNTER_HGH_CNT_MSK (0x000000FF << ALTERA_PLL_C10_C_COUNTER_HGH_CNT_OFST)
/* total_div = lw_cnt + hgh_cnt */
#define ALTERA_PLL_C10_C_COUNTER_BYPSS_ENBL_OFST (16)
#define ALTERA_PLL_C10_C_COUNTER_BYPSS_ENBL_MSK (0x00000001 << ALTERA_PLL_C10_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_C10_C_COUNTER_ODD_DVSN_OFST (17)
#define ALTERA_PLL_C10_C_COUNTER_ODD_DVSN_MSK (0x00000001 << ALTERA_PLL_C10_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 */
// dynamic phase shift (C0-C8 (+1 to base address), 0xF for all counters)
#define ALTERA_PLL_C10_PHASE_SHIFT_BASE_REG (0x100)
#define ALTERA_PLL_C10_MAX_SHIFTS_PER_OPERATION (7)
#define ALTERA_PLL_C10_SHIFT_NUM_SHIFTS_OFST (0)
#define ALTERA_PLL_C10_SHIFT_NUM_SHIFTS_MSK (0x00000007 << ALTERA_PLL_C10_SHIFT_NUM_SHIFTS_OFST)
#define ALTERA_PLL_C10_SHIFT_UP_DOWN_OFST (3)
#define ALTERA_PLL_C10_SHIFT_UP_DOWN_MSK (0x00000001 << ALTERA_PLL_C10_SHIFT_UP_DOWN_OFST)
#define ALTERA_PLL_C10_SHIFT_UP_DOWN_NEG_VAL ((0x0 << ALTERA_PLL_C10_SHIFT_UP_DOWN_OFST) & ALTERA_PLL_C10_SHIFT_UP_DOWN_MSK)
#define ALTERA_PLL_C10_SHIFT_UP_DOWN_POS_VAL ((0x1 << ALTERA_PLL_C10_SHIFT_UP_DOWN_OFST) & ALTERA_PLL_C10_SHIFT_UP_DOWN_MSK)
#define ALTERA_PLL_C10_PHASE_SHIFT_STEP_OF_VCO (8)
#define ALTERA_PLL_C10_WAIT_TIME_US (10 * 1000)
int ALTERA_PLL_C10_Reg_offset = 0x0;
const int ALTERA_PLL_C10_NUM = 2;
uint32_t ALTERA_PLL_C10_BaseAddress[2] = {0x0, 0x0};
uint32_t ALTERA_PLL_C10_Reset_Reg[2] = {0x0, 0x0};
uint32_t ALTERA_PLL_C10_Reset_Msk[2] = {0x0, 0x0};
uint32_t ALTERA_PLL_C10_Wait_Reg[2] = {0x0, 0x0};
uint32_t ALTERA_PLL_C10_Wait_Msk[2] = {0x0, 0x0};
int ALTERA_PLL_C10_VCO_FREQ[2] = {0, 0};
void ALTERA_PLL_C10_SetDefines(int regofst, uint32_t baseaddr0, uint32_t baseaddr1, uint32_t resetreg0, uint32_t resetreg1, uint32_t resetmsk0, uint32_t resetmsk1, uint32_t waitreg0, uint32_t waitreg1, uint32_t waitmsk0, uint32_t waitmsk1, int vcofreq0, int vcofreq1) {
ALTERA_PLL_C10_Reg_offset = regofst;
ALTERA_PLL_C10_BaseAddress[0] = baseaddr0;
ALTERA_PLL_C10_BaseAddress[1] = baseaddr1;
ALTERA_PLL_C10_Reset_Reg[0] = resetreg0;
ALTERA_PLL_C10_Reset_Reg[1] = resetreg1;
ALTERA_PLL_C10_Reset_Msk[0] = resetmsk0;
ALTERA_PLL_C10_Reset_Msk[1] = resetmsk1;
ALTERA_PLL_C10_Wait_Reg[0] = waitreg0;
ALTERA_PLL_C10_Wait_Reg[1] = waitreg1;
ALTERA_PLL_C10_Wait_Msk[0] = waitmsk0;
ALTERA_PLL_C10_Wait_Msk[1] = waitmsk1;
ALTERA_PLL_C10_VCO_FREQ[0] = vcofreq0;
ALTERA_PLL_C10_VCO_FREQ[1] = vcofreq1;
}
int ALTERA_PLL_C10_GetMaxClockDivider() {
return ALTERA_PLL_C10_C_COUNTER_MAX_DIVIDER_VAL;
}
int ALTERA_PLL_C10_GetVCOFrequency(int pllIndex) {
return ALTERA_PLL_C10_VCO_FREQ[pllIndex];
}
int ALTERA_PLL_C10_GetMaxPhaseShiftStepsofVCO() {
return ALTERA_PLL_C10_PHASE_SHIFT_STEP_OF_VCO;
}
int ALTERA_PLL_C10_Reconfigure(int pllIndex) {
FILE_LOG(logINFO, ("\tReconfiguring PLL %d\n", pllIndex));
uint32_t waitreg = ALTERA_PLL_C10_Wait_Reg[pllIndex];
uint32_t waitmsk = ALTERA_PLL_C10_Wait_Msk[pllIndex];
// write anything to base address to start reconfiguring
FILE_LOG(logDEBUG1, ("\tWriting 1 to base address 0x%x to start reconfiguring\n", ALTERA_PLL_C10_BaseAddress[pllIndex]));
//bus_w_csp1(ALTERA_PLL_C10_BaseAddress[pllIndex], 0x1);
// wait for write operation to be completed by polling wait request bit
int ret = OK;
FILE_LOG(logDEBUG1, ("\tWaiting a second (instead of wait request bit in fw)\n"));
usleep(1 * 1000 * 1000);
/* TODO wait reg and wait mask to be done in firware, so wait instead (above)
int counter = 0;
while (bus_r_csp1(waitreg) & waitmsk) {
usleep(ALTERA_PLL_C10_WAIT_TIME_US);
++counter;
if (counter >= 100) {
FILE_LOG(logERROR, ("Waited for the pll wait request for 1 s. Not waiting anymore."));
ret = FAIL;
break;
}
}
FILE_LOG(logINFO, ("\tReconfiguring PLL %d done with %s\n", pllIndex, ret == FAIL ? "failure" : "success"));
*/
FILE_LOG(logDEBUG1, ("\tWaiting done\n"));
return ret;
}
void ALTERA_PLL_C10_ResetPLL (int pllIndex) {
FILE_LOG(logINFO, ("Resetting PLL %d\n", pllIndex));
uint32_t resetreg = ALTERA_PLL_C10_Reset_Reg[pllIndex];
uint32_t resetmsk = ALTERA_PLL_C10_Reset_Msk[pllIndex];
FILE_LOG(logERROR, ("Reset not implemented yet!\n"));
/* TODO reset reg and reset mask to be done in firware, so wait instead (above)
bus_w_csp1(resetreg, bus_r_csp1(resetreg) | resetmsk);
usleep(ALTERA_PLL_C10_WAIT_TIME_US); //FIXME
bus_w_csp1(resetreg, bus_r_csp1(resetreg) & ~resetmsk);//FIXME
*/
}
int ALTERA_PLL_C10_SetPhaseShift(int pllIndex, int clkIndex, int phase, int pos) {
FILE_LOG(logINFO, ("\tC%d: Writing PLL %d Phase Shift [phase:%d, pos:%d]\n", clkIndex, pllIndex, phase, pos));
FILE_LOG(logDEBUG1, ("\tBase address: 0x%x phasebasereg:0x%x\n", ALTERA_PLL_C10_BaseAddress[pllIndex], ALTERA_PLL_C10_PHASE_SHIFT_BASE_REG));
uint32_t addr = ALTERA_PLL_C10_BaseAddress[pllIndex] + (ALTERA_PLL_C10_PHASE_SHIFT_BASE_REG + (int)clkIndex) * ALTERA_PLL_C10_Reg_offset;
int maxshifts = ALTERA_PLL_C10_MAX_SHIFTS_PER_OPERATION;
// only 7 shifts at a time
int ret = OK;
while (phase > 0) {
int phaseToDo = (phase > maxshifts) ? maxshifts : phase;
uint32_t value = (((phaseToDo << ALTERA_PLL_C10_SHIFT_NUM_SHIFTS_OFST) & ALTERA_PLL_C10_SHIFT_NUM_SHIFTS_MSK) |
(pos ? ALTERA_PLL_C10_SHIFT_UP_DOWN_POS_VAL : ALTERA_PLL_C10_SHIFT_UP_DOWN_NEG_VAL));
FILE_LOG(logDEBUG1, ("\t[addr:0x%x, phaseTodo:%d phaseleft:%d phase word:0x%08x]\n", addr, phaseToDo, phase, value));
//bus_w_csp1(addr, value);
if (ALTERA_PLL_C10_Reconfigure(pllIndex) == FAIL) {
ret = FAIL;
}
phase -= phaseToDo;
}
return ret;
}
int ALTERA_PLL_C10_SetOuputFrequency (int pllIndex, int clkIndex, int value) {
int pllVCOFreqHz = ALTERA_PLL_C10_VCO_FREQ[pllIndex];
FILE_LOG(logDEBUG1, ("\tC%d: Setting output frequency for pll %d to %d (pllvcofreq: %dHz)\n", clkIndex, pllIndex, value, pllVCOFreqHz));
// calculate output frequency
float total_div = (float)pllVCOFreqHz / (float)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 > (float)(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 addr = ALTERA_PLL_C10_BaseAddress[pllIndex] + (ALTERA_PLL_C10_C_COUNTER_BASE_REG + (int)clkIndex) * ALTERA_PLL_C10_Reg_offset;
uint32_t val = (((low_count << ALTERA_PLL_C10_C_COUNTER_LW_CNT_OFST) & ALTERA_PLL_C10_C_COUNTER_LW_CNT_MSK) |
((high_count << ALTERA_PLL_C10_C_COUNTER_HGH_CNT_OFST) & ALTERA_PLL_C10_C_COUNTER_HGH_CNT_MSK) |
((odd_division << ALTERA_PLL_C10_C_COUNTER_ODD_DVSN_OFST) & ALTERA_PLL_C10_C_COUNTER_ODD_DVSN_MSK));
FILE_LOG(logDEBUG1, ("\t[addr:0x%x, word:0x%08x]\n", addr, val));
// write frequency
//bus_w_csp1(addr, val);
int ret = ALTERA_PLL_C10_Reconfigure(pllIndex);
// reset required to keep the phase relationships (must reconfigure adcs again after this as adc clock is stopped temporarily when resetting pll)
ALTERA_PLL_C10_ResetPLL (pllIndex);
return ret;
}

View File

@ -12,6 +12,20 @@ u_int32_t* csp0base = 0;
#define CSP0 0x18060000
#define MEM_SIZE 0x100000
u_int32_t* csp1base = 0;
#define CSP1 0x18040000
void bus_w_csp1(u_int32_t offset, u_int32_t data) {
volatile u_int32_t *ptr1;
ptr1=(u_int32_t*)(csp1base + offset/(sizeof(u_int32_t)));
*ptr1=data;
}
u_int32_t bus_r_csp1(u_int32_t offset) {
volatile u_int32_t *ptr1;
ptr1=(u_int32_t*)(csp1base + offset/(sizeof(u_int32_t)));
return *ptr1;
}
void bus_w(u_int32_t offset, u_int32_t data) {
volatile u_int32_t *ptr1;
@ -72,38 +86,46 @@ u_int32_t writeRegister(u_int32_t offset, u_int32_t data) {
int mapCSP0(void) {
// if not mapped
if (csp0base == 0) {
FILE_LOG(logINFO, ("Mapping memory\n"));
u_int32_t csps[2] = {CSP0, CSP1};
u_int32_t** cspbases[2] = {&csp0base, &csp1base};
char names[2][10]={"csp0base","csp1base"};
int i = 0;
for (i = 0; i < 2; ++i) {
// if not mapped
if (*cspbases[i] == 0) {
FILE_LOG(logINFO, ("Mapping memory for %s\n", names[i]));
#ifdef VIRTUAL
csp0base = malloc(MEM_SIZE);
if (csp0base == NULL) {
FILE_LOG(logERROR, ("Could not allocate virtual memory.\n"));
return FAIL;
}
FILE_LOG(logINFO, ("memory allocated\n"));
*cspbases[i] = malloc(MEM_SIZE);
if (*cspbases[i] == NULL) {
FILE_LOG(logERROR, ("Could not allocate virtual memory for %s.\n", names[i]));
return FAIL;
}
FILE_LOG(logINFO, ("memory allocated for %s\n", names[i]));
#else
int fd = open("/dev/mem", O_RDWR | O_SYNC, 0);
if (fd == -1) {
FILE_LOG(logERROR, ("Can't find /dev/mem\n"));
return FAIL;
}
FILE_LOG(logDEBUG1, ("/dev/mem opened\n"));
csp0base = (u_int32_t*)mmap(0, MEM_SIZE, PROT_READ|PROT_WRITE, MAP_FILE|MAP_SHARED, fd, CSP0);
if (csp0base == MAP_FAILED) {
FILE_LOG(logERROR, ("Can't map memmory area\n"));
return FAIL;
}
int fd = open("/dev/mem", O_RDWR | O_SYNC, 0);
if (fd == -1) {
FILE_LOG(logERROR, ("Can't find /dev/mem for %s\n", names[i]));
return FAIL;
}
FILE_LOG(logDEBUG1, ("/dev/mem opened for %s, (CSP:0x%x)\n", names[i], csps[i]));
*cspbases[i] = (u_int32_t*)mmap(0, MEM_SIZE, PROT_READ|PROT_WRITE, MAP_FILE|MAP_SHARED, fd, csps[i]);
if (*cspbases[i] == MAP_FAILED) {
FILE_LOG(logERROR, ("Can't map memmory area for %s\n", names[i]));
return FAIL;
}
#endif
FILE_LOG(logINFO, ("CSPOBASE mapped from 0x%p to 0x%p\n",
csp0base, csp0base+MEM_SIZE));
//FILE_LOG(logINFO, ("Status Register: %08x\n", bus_r(STATUS_REG)));
}else
FILE_LOG(logINFO, ("Memory already mapped before\n"));
FILE_LOG(logINFO, ("%s mapped from %p to %p,(CSP:0x%x) \n",
names[i], *cspbases[i], *cspbases[i]+MEM_SIZE, csps[i]));
//FILE_LOG(logINFO, ("Status Register: %08x\n", bus_r(STATUS_REG)));
} else
FILE_LOG(logINFO, ("Memory %s already mapped before\n", names[i]));
}
return OK;
}
u_int32_t* Nios_getBaseAddress() {
return csp0base;
}

View File

@ -284,6 +284,15 @@ const char* getFunctionName(enum detFuncs func) {
case F_GET_STOREINRAM_MODE: return "F_GET_STOREINRAM_MODE";
case F_SET_READOUT_MODE: return "F_SET_READOUT_MODE";
case F_GET_READOUT_MODE: return "F_GET_READOUT_MODE";
case F_SET_CLOCK_FREQUENCY: return "F_SET_CLOCK_FREQUENCY";
case F_GET_CLOCK_FREQUENCY: return "F_GET_CLOCK_FREQUENCY";
case F_SET_CLOCK_PHASE: return "F_SET_CLOCK_PHASE";
case F_GET_CLOCK_PHASE: return "F_GET_CLOCK_PHASE";
case F_GET_MAX_CLOCK_PHASE_SHIFT: return "F_GET_MAX_CLOCK_PHASE_SHIFT";
case F_SET_CLOCK_DIVIDER: return "F_SET_CLOCK_DIVIDER";
case F_GET_CLOCK_DIVIDER: return "F_GET_CLOCK_DIVIDER";
default: return "Unknown Function";
}
}
@ -403,6 +412,13 @@ void function_table() {
flist[F_GET_STOREINRAM_MODE] = &get_storeinram;
flist[F_SET_READOUT_MODE] = &set_readout_mode;
flist[F_GET_READOUT_MODE] = &get_readout_mode;
flist[F_SET_CLOCK_FREQUENCY] = &set_clock_frequency;
flist[F_GET_CLOCK_FREQUENCY] = &get_clock_frequency;
flist[F_SET_CLOCK_PHASE] = &set_clock_phase;
flist[F_GET_CLOCK_PHASE] = &get_clock_phase;
flist[F_GET_MAX_CLOCK_PHASE_SHIFT] = &get_max_clock_phase_shift;
flist[F_SET_CLOCK_DIVIDER] = &set_clock_divider;
flist[F_GET_CLOCK_DIVIDER] = &get_clock_divider;
// check
if (NUM_DET_FUNCTIONS >= RECEIVER_ENUM_START) {
@ -4830,11 +4846,11 @@ int get_dest_udp_port(int file_des) {
ret = OK;
memset(mess, 0, sizeof(mess));
int retval = -1;
FILE_LOG(logDEBUG1, ("Getting destination port\n"));
FILE_LOG(logDEBUG1, ("Getting destination porstore in ram moden"));
// get only
retval = udpDetails.dstport;
FILE_LOG(logDEBUG, ("udp destination port retval: %u\n", retval));
FILE_LOG(logDEBUG, ("udp destination port retstore in ram model: %u\n", retval));
return Server_SendResult(file_des, INT32, UPDATE, &retval, sizeof(retval));
}
@ -5184,3 +5200,267 @@ int get_readout_mode(int file_des) {
return Server_SendResult(file_des, INT32, UPDATE, &retval, sizeof(retval));
}
int set_clock_frequency(int file_des) {
ret = OK;
memset(mess, 0, sizeof(mess));
int args[2] = {-1, -1};
if (receiveData(file_des, args, sizeof(args), INT32) < 0)
return printSocketReadError();
FILE_LOG(logINFO, ("Setting frequency of clock %d: %u\n", args[0], args[1]));
functionNotImplemented();
/*
// only set
if (Server_VerifyLock() == OK) {
enum CLKINDEX c = (enum CLKINDEX)args[0];
if (c >= NUM_CLOCKS) {
ret = FAIL;
sprintf(mess, "Cannot set frequency of clock %d. Max number of clocks is %d.\n", (int)c, NUM_CLOCKS - 1);
FILE_LOG(logERROR, (mess));
} else {
ret = setFrequency(c, args[1]);
if (ret == FAIL) {
strcpy(mess, "Set frequency in unknown state. Reconfigure did not return.\n");
FILE_LOG(logERROR, (mess));
} else {
int retval = getFrequency(c);
FILE_LOG(logDEBUG1, ("retval frequency of clock %d: %d\n", (int)c, retval));
char cval[100];
memset(cval, 0, 100);
sprintf(cval, "set frequency of clock %d Hz", (int)c);
validate(args[1], retval, cval, DEC);
}
}
}
*/
return Server_SendResult(file_des, INT32, UPDATE, NULL, 0);
}
int get_clock_frequency(int file_des) {
ret = OK;
memset(mess, 0, sizeof(mess));
int arg = -1;
int retval = -1;
if (receiveData(file_des, &arg, sizeof(arg), INT32) < 0)
return printSocketReadError();
FILE_LOG(logDEBUG1, ("Getting frequency of clock %d\n", arg));
#ifndef GOTTHARD2D
functionNotImplemented();
#else
// get only
enum CLKINDEX c = (enum CLKINDEX)arg;
if (c >= NUM_CLOCKS) {
ret = FAIL;
sprintf(mess, "Cannot get frequency of clock %d. Max number of clocks is %d.\n", (int)c, NUM_CLOCKS - 1);
FILE_LOG(logERROR, (mess));
} else {
retval = getFrequency(c);
FILE_LOG(logDEBUG1, ("retval frequency of clock %d Hz: %d\n", (int)c, retval));
}
#endif
return Server_SendResult(file_des, INT32, UPDATE, &retval, sizeof(retval));
}
int set_clock_phase(int file_des) {
ret = OK;
memset(mess, 0, sizeof(mess));
int args[3] = {-1, -1, -1};
if (receiveData(file_des, args, sizeof(args), INT32) < 0)
return printSocketReadError();
FILE_LOG(logINFO, ("Setting phase of clock %d: %u %s\n", args[0], args[1], (args[2] == 0 ? "" : "degrees")));
#ifndef GOTTHARD2D
functionNotImplemented();
#else
// only set
if (Server_VerifyLock() == OK) {
enum CLKINDEX c = (enum CLKINDEX)args[0];
if (c >= NUM_CLOCKS) {
ret = FAIL;
sprintf(mess, "Cannot set phase for clock %d. Max number of clocks is %d.\n", (int)c, NUM_CLOCKS - 1);
FILE_LOG(logERROR, (mess));
} else {
int val = args[1];
int degrees = args[2];
if (degrees && (val < 0 || val > 359)) {
ret = FAIL;
sprintf(mess, "Cannot set phase. Phase provided for C%d outside limits (0 - 359°C)\n", (int)c);
FILE_LOG(logERROR, (mess));
} else if (!degrees && (val < 0 || val > getMaxPhase(c) - 1)) {
ret = FAIL;
sprintf(mess, "Cannot set phase. Phase provided for C%d outside limits (0 - %d phase shifts)\n", (int)c, getMaxPhase(c) - 1);
FILE_LOG(logERROR, (mess));
} else {
ret = setPhase(c, val, degrees);
if (ret == FAIL) {
strcpy(mess, "Set phase in unknown state. Reconfigure did not return.\n");
FILE_LOG(logERROR, (mess));
} else {
int retval = getPhase(c, degrees);
FILE_LOG(logDEBUG1, ("retval phase for clock %d: %d %s \n", (int)c, retval, (degrees == 0 ? "" : "degrees")));
char cval[100];
memset(cval, 0, 100);
sprintf(cval, "set phase for clock %d",(int)c);
if (!degrees) {
validate(val, retval, cval, DEC);
} else {
ret = validatePhaseinDegrees(c, val, retval);
if (ret == FAIL) {
sprintf(mess, "Could not set %s. Set %d degrees, got %d degrees\n", cval, val, retval);
FILE_LOG(logERROR,(mess));
}
}
}
}
}
}
#endif
return Server_SendResult(file_des, INT32, UPDATE, NULL, 0);
}
int get_clock_phase(int file_des) {
ret = OK;
memset(mess, 0, sizeof(mess));
int args[2] = {-1, -1};
int retval = -1;
if (receiveData(file_des, args, sizeof(args), INT32) < 0)
return printSocketReadError();
FILE_LOG(logDEBUG1, ("Getting phase for clock %d %s \n", args[0], (args[1] == 0 ? "" : "in degrees")));
#ifndef GOTTHARD2D
functionNotImplemented();
#else
// get only
enum CLKINDEX c = (enum CLKINDEX)args[0];
if (c >= NUM_CLOCKS) {
ret = FAIL;
sprintf(mess, "Cannot get phase of clock %d. Max number of clocks is %d.\n", (int)c, NUM_CLOCKS - 1);
FILE_LOG(logERROR, (mess));
} else {
retval = getPhase(c, args[1]);
FILE_LOG(logDEBUG1, ("retval phase for clock %d: %d %s\n", (int)c, retval, (args[1] == 0 ? "" : "degrees")));
}
#endif
return Server_SendResult(file_des, INT32, UPDATE, &retval, sizeof(retval));
}
int get_max_clock_phase_shift(int file_des) {
ret = OK;
memset(mess, 0, sizeof(mess));
int arg = -1;
int retval = -1;
if (receiveData(file_des, &arg, sizeof(arg), INT32) < 0)
return printSocketReadError();
FILE_LOG(logDEBUG1, ("Getting max phase shift of clock %d\n", arg));
#ifndef GOTTHARD2D
functionNotImplemented();
#else
// get only
enum CLKINDEX c = (enum CLKINDEX)arg;
if (c >= NUM_CLOCKS) {
ret = FAIL;
sprintf(mess, "Cannot get frequency of clock %d. Max number of clocks is %d.\n", (int)c, NUM_CLOCKS - 1);
FILE_LOG(logERROR, (mess));
} else {
retval = getMaxPhase(c);
FILE_LOG(logDEBUG1, ("retval max phase shift of clock %d: %d\n", (int)c, retval));
}
#endif
return Server_SendResult(file_des, INT32, UPDATE, &retval, sizeof(retval));
}
int set_clock_divider(int file_des) {
ret = OK;
memset(mess, 0, sizeof(mess));
int args[2] = {-1, -1};
if (receiveData(file_des, args, sizeof(args), INT32) < 0)
return printSocketReadError();
FILE_LOG(logINFO, ("Setting divider of clock %d: %u\n", args[0], args[1]));
#ifndef GOTTHARD2D
functionNotImplemented();
#else
// only set
if (Server_VerifyLock() == OK) {
enum CLKINDEX c = (enum CLKINDEX)args[0];
int val = args[1];
if (c >= NUM_CLOCKS) {
ret = FAIL;
sprintf(mess, "Cannot set divider of clock %d. Max number of clocks is %d.\n", (int)c, NUM_CLOCKS - 1);
FILE_LOG(logERROR, (mess));
} else if (getClockDivider(c) == val) {
FILE_LOG(logINFO, ("Same clock divider %d\n"));
} else if (val < 2 || val > getMaxClockDivider()) {
ret = FAIL;
sprintf(mess, "Cannot set divider of clock %d to %d. Value should be in range [2-%d]\n", (int)c, val, getMaxClockDivider());
FILE_LOG(logERROR, (mess));
} else {
ret = setClockDivider(c, val);
if (ret == FAIL) {
strcpy(mess, "Set divider in unknown state. Reconfigure did not return.\n");
FILE_LOG(logERROR, (mess));
} else {
int retval = getClockDivider(c);
FILE_LOG(logDEBUG1, ("retval divider of clock %d: %d\n", (int)c, retval));
char cval[100];
memset(cval, 0, 100);
sprintf(cval, "set divider of clock %d Hz", (int)c);
validate(val, retval, cval, DEC);
}
}
}
#endif
return Server_SendResult(file_des, INT32, UPDATE, NULL, 0);
}
int get_clock_divider(int file_des) {
ret = OK;
memset(mess, 0, sizeof(mess));
int arg = -1;
int retval = -1;
if (receiveData(file_des, &arg, sizeof(arg), INT32) < 0)
return printSocketReadError();
FILE_LOG(logDEBUG1, ("Getting divider of clock %d\n", arg));
#ifndef GOTTHARD2D
functionNotImplemented();
#else
// get only
enum CLKINDEX c = (enum CLKINDEX)arg;
if (c >= NUM_CLOCKS) {
ret = FAIL;
sprintf(mess, "Cannot get divider of clock %d. Max number of clocks is %d.\n", (int)c, NUM_CLOCKS - 1);
FILE_LOG(logERROR, (mess));
} else {
retval = getClockDivider(c);
FILE_LOG(logDEBUG1, ("retval divider of clock %d Hz: %d\n", (int)c, retval));
}
#endif
return Server_SendResult(file_des, INT32, UPDATE, &retval, sizeof(retval));
}

View File

@ -141,7 +141,11 @@ class CmdProxy {
{"rx_udpport", &CmdProxy::rx_udpport},
{"rx_udpport2", &CmdProxy::rx_udpport2},
{"numinterfaces", &CmdProxy::numinterfaces},
{"selinterface", &CmdProxy::selinterface}};
{"selinterface", &CmdProxy::selinterface},
{"clkfreq", &CmdProxy::ClockFrequency},
{"clkphase", &CmdProxy::ClockPhase},
{"maxclkphaseshift", &CmdProxy::MaxClockPhaseShift},
{"clkdiv", &CmdProxy::ClockDivider}};
StringMap depreciated_functions{{"r_readfreq", "rx_readfreq"},
{"r_padding", "rx_padding"},
@ -171,6 +175,10 @@ class CmdProxy {
std::string Period(int action);
std::string Exptime(int action);
std::string SubExptime(int action);
std::string ClockFrequency(int action);
std::string ClockPhase(int action);
std::string MaxClockPhaseShift(int action);
std::string ClockDivider(int action);
INTEGER_COMMAND(
rx_fifodepth, getRxFifoDepth, setRxFifoDepth, std::stoi,

View File

@ -1196,6 +1196,33 @@ class Detector {
Result<uint64_t> getRxCurrentFrameIndex(Positions pos = {}) const;
/** [Gotthard2] Hz */
Result<int> getClockFrequency(int clkIndex, Positions pos = {});
/** [unknown] Hz */
void setClockFrequency(int clkIndex, int value, Positions pos = {});
/** [Gotthard2] */
Result<int> getClockPhase(int clkIndex, Positions pos = {});
/** [Gotthard2] */
void setClockPhase(int clkIndex, int value, Positions pos = {});
/** [Gotthard2] */
Result<int> getMaxClockPhaseShift(int clkIndex, Positions pos = {});
/** [Gotthard2] */
Result<int> getClockPhaseinDegrees(int clkIndex, Positions pos = {});
/** [Gotthard2] */
void setClockPhaseinDegrees(int clkIndex, int value, Positions pos = {});
/** [Gotthard2] */
Result<int> getClockDivider(int clkIndex, Positions pos = {});
/** [Gotthard2] */
void setClockDivider(int clkIndex, int value, Positions pos = {});
private:
std::vector<int> getPortNumbers(int start_port);
};

View File

@ -1679,6 +1679,27 @@ class slsDetector : public virtual slsDetectorDefs {
*/
void setDigitalIODelay(uint64_t pinMask, int delay);
/** [Gotthard2] */
int getClockFrequency(int clkIndex);
/** [Gotthard2] */
void setClockFrequency(int clkIndex, int value);
/** [Gotthard2] */
int getClockPhase(int clkIndex, bool inDegrees);
/** [Gotthard2] */
void setClockPhase(int clkIndex, int value, bool inDegrees);
/** [Gotthard2] */
int getMaxClockPhaseShift(int clkIndex);
/** [Gotthard2] */
int getClockDivider(int clkIndex);
/** [Gotthard2] */
void setClockDivider(int clkIndex, int value);
private:
/**
* Send function parameters to detector (control server)

View File

@ -181,4 +181,110 @@ std::string CmdProxy::ListCommands(int action) {
}
}
std::string CmdProxy::ClockFrequency(int action) {
std::ostringstream os;
os << cmd << ' ';
if (action == defs::HELP_ACTION) {
os << "[n_clock (0-8)] [freq_in_Hz]\n\t[Gotthard2] Frequency of clock n_clock in Hz. Use clkdiv to set frequency." << '\n';
} else if (action == defs::GET_ACTION) {
if (args.size() != 1) {
WrongNumberOfParameters(1);
}
auto t = det->getClockFrequency(std::stoi(args[0]), {det_id});
os << OutString(t) << '\n';
} else if (action == defs::PUT_ACTION) {
if (args.size() != 2) {
WrongNumberOfParameters(2);
}
det->setClockFrequency(std::stoi(args[0]), std::stoi(args[1]));
//TODO print args
os << std::stoi(args[1]) << '\n';
} else {
throw sls::RuntimeError("Unknown action");
}
return os.str();
}
std::string CmdProxy::ClockPhase(int action) {
std::ostringstream os;
os << cmd << ' ';
if (action == defs::HELP_ACTION) {
os << "[n_clock (0-8)] [phase] [deg (optional)]\n\t[Gotthard2] Phase of clock n_clock. If deg, then phase shift in degrees, else absolute phase shift values." << '\n';
} else if (action == defs::GET_ACTION) {
if (args.size() == 1) {
auto t = det->getClockPhase(std::stoi(args[0]), {det_id});
os << OutString(t) << '\n';
} else if (args.size() == 2) {
if (args[1] != "deg") {
throw sls::RuntimeError("Cannot scan argument" + args[1] + ". Did you mean deg?");
}
auto t = det->getClockPhaseinDegrees(std::stoi(args[0]), {det_id});
os << OutString(t) << '\n';
} else {
WrongNumberOfParameters(1);
}
} else if (action == defs::PUT_ACTION) {
if (args.size() == 2) {
det->setClockPhase(std::stoi(args[0]), std::stoi(args[1]), {det_id});
os << args[1] << '\n';
} else if (args.size() == 3) {
if (args[2] != "deg") {
throw sls::RuntimeError("Cannot scan argument" + args[2] + ". Did you mean deg?");
}
det->setClockPhaseinDegrees(std::stoi(args[0]), std::stoi(args[1]), {det_id});
os << std::stoi(args[1]) << '\n';
} else {
WrongNumberOfParameters(1);
}
} else {
throw sls::RuntimeError("Unknown action");
}
return os.str();
}
std::string CmdProxy::MaxClockPhaseShift(int action) {
std::ostringstream os;
os << cmd << ' ';
if (action == defs::HELP_ACTION) {
os << "[n_clock (0-8)]\n\t[Gotthard2] Absolute Maximum Phase shift of clock n_clock." << '\n';
} else if (action == defs::GET_ACTION) {
if (args.size() != 1) {
WrongNumberOfParameters(1);
}
auto t = det->getMaxClockPhaseShift(std::stoi(args[0]), {det_id});
os << OutString(t) << '\n';
} else if (action == defs::PUT_ACTION) {
throw sls::RuntimeError("Cannot put");
} else {
throw sls::RuntimeError("Unknown action");
}
return os.str();
}
std::string CmdProxy::ClockDivider(int action) {
std::ostringstream os;
os << cmd << ' ';
if (action == defs::HELP_ACTION) {
os << "[n_clock (0-8)] [n_divider]\n\t[Gotthard2] Clock Divider of clock n_clock. Must be greater than 1." << '\n';
} else if (action == defs::GET_ACTION) {
if (args.size() != 1) {
WrongNumberOfParameters(1);
}
auto t = det->getClockDivider(std::stoi(args[0]), {det_id});
os << OutString(t) << '\n';
} else if (action == defs::PUT_ACTION) {
if (args.size() != 2) {
WrongNumberOfParameters(2);
}
det->setClockDivider(std::stoi(args[0]), std::stoi(args[1]));
//TODO print args
os << std::stoi(args[1]) << '\n';
} else {
throw sls::RuntimeError("Unknown action");
}
return os.str();
}
} // namespace sls

View File

@ -1544,6 +1544,42 @@ Result<uint64_t> Detector::getRxCurrentFrameIndex(Positions pos) const {
return pimpl->Parallel(&slsDetector::getReceiverCurrentFrameIndex, pos);
}
Result<int> Detector::getClockFrequency(int clkIndex, Positions pos) {
return pimpl->Parallel(&slsDetector::getClockFrequency, pos, clkIndex);
}
void Detector::setClockFrequency(int clkIndex, int value, Positions pos) {
pimpl->Parallel(&slsDetector::setClockFrequency, pos, clkIndex, value);
}
Result<int> Detector::getClockPhase(int clkIndex, Positions pos) {
return pimpl->Parallel(&slsDetector::getClockPhase, pos, clkIndex, false);
}
void Detector::setClockPhase(int clkIndex, int value, Positions pos) {
pimpl->Parallel(&slsDetector::setClockPhase, pos, clkIndex, value, false);
}
Result<int> Detector::getMaxClockPhaseShift(int clkIndex, Positions pos) {
return pimpl->Parallel(&slsDetector::getMaxClockPhaseShift, pos, clkIndex);
}
Result<int> Detector::getClockPhaseinDegrees(int clkIndex, Positions pos) {
return pimpl->Parallel(&slsDetector::getClockPhase, pos, clkIndex, true);
}
void Detector::setClockPhaseinDegrees(int clkIndex, int value, Positions pos) {
pimpl->Parallel(&slsDetector::setClockPhase, pos, clkIndex, value, true);
}
Result<int> Detector::getClockDivider(int clkIndex, Positions pos) {
return pimpl->Parallel(&slsDetector::getClockDivider, pos, clkIndex);
}
void Detector::setClockDivider(int clkIndex, int value, Positions pos) {
pimpl->Parallel(&slsDetector::setClockDivider, pos, clkIndex, value);
}
std::vector<int> Detector::getPortNumbers(int start_port) {
int num_sockets_per_detector = 1;
switch (getDetectorType({}).squash()) {

View File

@ -3425,6 +3425,57 @@ void slsDetector::setDigitalIODelay(uint64_t pinMask, int delay) {
FILE_LOG(logDEBUG1) << "Digital IO Delay successful";
}
int slsDetector::getClockFrequency(int clkIndex) {
int retval = -1;
FILE_LOG(logDEBUG1) << "Getting Clock " << clkIndex << " frequency";
sendToDetector(F_GET_CLOCK_FREQUENCY, clkIndex, retval);
FILE_LOG(logDEBUG1) << "Clock " << clkIndex << " frequency: " << retval;
return retval;
}
void slsDetector::setClockFrequency(int clkIndex, int value) {
int args[]{clkIndex, value};
FILE_LOG(logDEBUG1) << "Setting Clock " << clkIndex << " frequency to " << value;
sendToDetector(F_SET_CLOCK_FREQUENCY, args, nullptr);
}
int slsDetector::getClockPhase(int clkIndex, bool inDegrees) {
int args[]{clkIndex, static_cast<int>(inDegrees)};
int retval = -1;
FILE_LOG(logDEBUG1) << "Getting Clock " << clkIndex << " phase " << (inDegrees ? "in degrees" : "");
sendToDetector(F_GET_CLOCK_PHASE, args, retval);
FILE_LOG(logDEBUG1) << "Clock " << clkIndex << " frequency: " << retval << (inDegrees ? "degrees" : "");
return retval;
}
void slsDetector::setClockPhase(int clkIndex, int value, bool inDegrees) {
int args[]{clkIndex, value, static_cast<int>(inDegrees)};
FILE_LOG(logDEBUG1) << "Setting Clock " << clkIndex << " phase to " << value << (inDegrees ? "degrees" : "");
sendToDetector(F_SET_CLOCK_PHASE, args, nullptr);
}
int slsDetector::getMaxClockPhaseShift(int clkIndex) {
int retval = -1;
FILE_LOG(logDEBUG1) << "Getting Max Phase Shift for Clock " << clkIndex;
sendToDetector(F_GET_MAX_CLOCK_PHASE_SHIFT, clkIndex, retval);
FILE_LOG(logDEBUG1) << "Max Phase Shift for Clock " << clkIndex << ": " << retval;
return retval;
}
int slsDetector::getClockDivider(int clkIndex) {
int retval = -1;
FILE_LOG(logDEBUG1) << "Getting Clock " << clkIndex << " divider";
sendToDetector(F_GET_CLOCK_DIVIDER, clkIndex, retval);
FILE_LOG(logDEBUG1) << "Clock " << clkIndex << " divider: " << retval;
return retval;
}
void slsDetector::setClockDivider(int clkIndex, int value) {
int args[]{clkIndex, value};
FILE_LOG(logDEBUG1) << "Setting Clock " << clkIndex << " divider to " << value;
sendToDetector(F_SET_CLOCK_DIVIDER, args, nullptr);
}
sls_detector_module slsDetector::interpolateTrim(sls_detector_module *a,
sls_detector_module *b,
const int energy, const int e1,

View File

@ -9,6 +9,7 @@
auto GET = slsDetectorDefs::GET_ACTION;
auto PUT = slsDetectorDefs::PUT_ACTION;
TEST_CASE("rx_fifodepth", "[.cmd]") {
{

View File

@ -124,6 +124,13 @@ enum detFuncs{
F_GET_STOREINRAM_MODE,
F_SET_READOUT_MODE,
F_GET_READOUT_MODE,
F_SET_CLOCK_FREQUENCY,
F_GET_CLOCK_FREQUENCY,
F_SET_CLOCK_PHASE,
F_GET_CLOCK_PHASE,
F_GET_MAX_CLOCK_PHASE_SHIFT,
F_SET_CLOCK_DIVIDER,
F_GET_CLOCK_DIVIDER,
NUM_DET_FUNCTIONS,
RECEIVER_ENUM_START = 128, /**< detector function should not exceed this (detector server should not compile anyway) */
@ -307,6 +314,14 @@ static const char* getFunctionNameFromEnum(enum detFuncs func) {
case F_GET_STOREINRAM_MODE: return "F_GET_STOREINRAM_MODE";
case F_SET_READOUT_MODE: return "F_SET_READOUT_MODE";
case F_GET_READOUT_MODE: return "F_GET_READOUT_MODE";
case F_SET_CLOCK_FREQUENCY: return "F_SET_CLOCK_FREQUENCY";
case F_GET_CLOCK_FREQUENCY: return "F_GET_CLOCK_FREQUENCY";
case F_SET_CLOCK_PHASE: return "F_SET_CLOCK_PHASE";
case F_GET_CLOCK_PHASE: return "F_GET_CLOCK_PHASE";
case F_GET_MAX_CLOCK_PHASE_SHIFT: return "F_GET_MAX_CLOCK_PHASE_SHIFT";
case F_SET_CLOCK_DIVIDER: return "F_SET_CLOCK_DIVIDER";
case F_GET_CLOCK_DIVIDER: return "F_GET_CLOCK_DIVIDER";
case NUM_DET_FUNCTIONS: return "NUM_DET_FUNCTIONS";
case RECEIVER_ENUM_START: return "RECEIVER_ENUM_START";

View File

@ -7,6 +7,6 @@
#define APICTB 0x190930
#define APIGOTTHARD 0x190930
#define APIEIGER 0x190930
#define APIGOTTHARD2 0x191008
#define APIMYTHEN3 0x191008
#define APIJUNGFRAU 0x191008
#define APIGOTTHARD2 0x191017