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

@ -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));
}