mirror of
https://github.com/slsdetectorgroup/slsDetectorPackage.git
synced 2025-04-23 06:50:02 +02:00
365 lines
11 KiB
C
365 lines
11 KiB
C
|
|
#include "mythen3.h"
|
|
#include "clogger.h"
|
|
#include "common.h"
|
|
#include "sls/ansi.h"
|
|
#include "sls/sls_detector_defs.h"
|
|
#include "slsDetectorServer_defs.h"
|
|
|
|
#include <string.h>
|
|
|
|
/*
|
|
// Common C/C++ structure to handle pattern data
|
|
typedef struct __attribute__((packed)) {
|
|
uint64_t word[MAX_PATTERN_LENGTH];
|
|
uint64_t ioctrl;
|
|
uint32_t limits[2];
|
|
// loop0 start, loop0 stop .. loop2 start, loop2 stop
|
|
uint32_t loop[6];
|
|
uint32_t nloop[3];
|
|
uint32_t wait[3];
|
|
uint64_t waittime[3];
|
|
} patternParameters;
|
|
*/
|
|
|
|
int chipStatusRegister = 0;
|
|
|
|
int setBit(int ibit, int patword) { return patword |= (1 << ibit); }
|
|
|
|
int clearBit(int ibit, int patword) { return patword &= ~(1 << ibit); }
|
|
|
|
int getChipStatusRegister() { return chipStatusRegister; }
|
|
|
|
int gainCapsToCsr(int caps) {
|
|
// Translates bit representation
|
|
int csr = 0;
|
|
if (!(caps & M3_C10pre))
|
|
csr |= 1 << _CSR_C10pre;
|
|
if (caps & M3_C15sh)
|
|
csr |= 1 << CSR_C15sh;
|
|
if (caps & M3_C30sh)
|
|
csr |= 1 << CSR_C30sh;
|
|
if (caps & M3_C50sh)
|
|
csr |= 1 << CSR_C50sh;
|
|
if (caps & M3_C225ACsh)
|
|
csr |= 1 << CSR_C225ACsh;
|
|
if (!(caps & M3_C15pre))
|
|
csr |= 1 << _CSR_C15pre;
|
|
|
|
return csr;
|
|
}
|
|
|
|
int csrToGainCaps(int csr) {
|
|
// Translates bit representation
|
|
int caps = 0;
|
|
if (!(csr & (1 << _CSR_C10pre)))
|
|
caps |= M3_C10pre;
|
|
if (csr & (1 << CSR_C15sh))
|
|
caps |= M3_C15sh;
|
|
if (csr & (1 << CSR_C30sh))
|
|
caps |= M3_C30sh;
|
|
if (csr & (1 << CSR_C50sh))
|
|
caps |= M3_C50sh;
|
|
if (csr & (1 << CSR_C225ACsh))
|
|
caps |= M3_C225ACsh;
|
|
if (!(csr & (1 << _CSR_C15pre)))
|
|
caps |= M3_C15pre;
|
|
|
|
return caps;
|
|
}
|
|
|
|
patternParameters *setChipStatusRegisterPattern(int csr) {
|
|
int iaddr = 0;
|
|
int nbits = 18;
|
|
int error = 0;
|
|
// int start=0, stop=MAX_PATTERN_LENGTH, loop=0;
|
|
int patword = 0;
|
|
|
|
patternParameters *pat = malloc(sizeof(patternParameters));
|
|
memset(pat, 0, sizeof(patternParameters));
|
|
|
|
patword = setBit(SIGNAL_STATLOAD, patword);
|
|
for (int i = 0; i < 2; i++)
|
|
pat->word[iaddr++] = patword;
|
|
patword = setBit(SIGNAL_resStorage, patword);
|
|
patword = setBit(SIGNAL_resCounter, patword);
|
|
for (int i = 0; i < 8; i++)
|
|
pat->word[iaddr++] = patword;
|
|
patword = clearBit(SIGNAL_resStorage, patword);
|
|
patword = clearBit(SIGNAL_resCounter, patword);
|
|
for (int i = 0; i < 8; i++)
|
|
pat->word[iaddr++] = patword;
|
|
//#This version of the serializer pushes in the MSB first (compatible with
|
|
//the CSR bit numbering)
|
|
for (int ib = nbits - 1; ib >= 0; ib--) {
|
|
if (csr & (1 << ib))
|
|
patword = setBit(SIGNAL_serialIN, patword);
|
|
else
|
|
patword = clearBit(SIGNAL_serialIN, patword);
|
|
for (int i = 0; i < 4; i++)
|
|
pat->word[iaddr++] = patword;
|
|
patword = setBit(SIGNAL_CHSclk, patword);
|
|
pat->word[iaddr++] = patword;
|
|
patword = clearBit(SIGNAL_CHSclk, patword);
|
|
pat->word[iaddr++] = patword;
|
|
}
|
|
|
|
patword = clearBit(SIGNAL_serialIN, patword);
|
|
for (int i = 0; i < 2; i++)
|
|
pat->word[iaddr++] = patword;
|
|
patword = setBit(SIGNAL_STO, patword);
|
|
for (int i = 0; i < 5; i++)
|
|
pat->word[iaddr++] = patword;
|
|
patword = clearBit(SIGNAL_STO, patword);
|
|
for (int i = 0; i < 5; i++)
|
|
pat->word[iaddr++] = patword;
|
|
patword = clearBit(SIGNAL_STATLOAD, patword);
|
|
for (int i = 0; i < 5; i++)
|
|
pat->word[iaddr++] = patword;
|
|
|
|
if (iaddr >= MAX_PATTERN_LENGTH) {
|
|
LOG(logERROR, ("Addr 0x%x is past max_address_length 0x%x!\n", iaddr,
|
|
MAX_PATTERN_LENGTH));
|
|
error = 1;
|
|
}
|
|
// set pattern wait address
|
|
for (int i = 0; i <= 2; i++)
|
|
pat->wait[i] = MAX_PATTERN_LENGTH - 1;
|
|
// pattern loop
|
|
for (int i = 0; i <= 2; i++) {
|
|
// int stop = MAX_PATTERN_LENGTH - 1, nloop = 0;
|
|
pat->loop[i * 2 + 0] = MAX_PATTERN_LENGTH - 1;
|
|
pat->loop[i * 2 + 1] = MAX_PATTERN_LENGTH - 1;
|
|
pat->nloop[i] = 0;
|
|
}
|
|
|
|
// pattern limits
|
|
{
|
|
pat->limits[0] = 0;
|
|
pat->limits[1] = iaddr;
|
|
}
|
|
|
|
if (error != 0) {
|
|
free(pat);
|
|
return NULL;
|
|
}
|
|
chipStatusRegister = csr;
|
|
return pat;
|
|
}
|
|
|
|
patternParameters *setInterpolation(int mask) {
|
|
int csr;
|
|
if (mask)
|
|
csr = chipStatusRegister | (1 << CSR_interp);
|
|
else
|
|
csr = chipStatusRegister & ~(1 << CSR_interp);
|
|
|
|
return setChipStatusRegisterPattern(csr);
|
|
}
|
|
|
|
patternParameters *setPumpProbe(int mask) {
|
|
int csr;
|
|
if (mask)
|
|
csr = chipStatusRegister | (1 << CSR_pumprobe);
|
|
else
|
|
csr = chipStatusRegister & ~(1 << CSR_pumprobe);
|
|
|
|
return setChipStatusRegisterPattern(csr);
|
|
}
|
|
patternParameters *setDigitalPulsing(int mask) {
|
|
|
|
int csr;
|
|
if (mask)
|
|
csr = chipStatusRegister | (1 << CSR_dpulse);
|
|
else
|
|
csr = chipStatusRegister & ~(1 << CSR_dpulse);
|
|
|
|
return setChipStatusRegisterPattern(csr);
|
|
}
|
|
patternParameters *setAnalogPulsing(int mask) {
|
|
|
|
int csr;
|
|
if (mask)
|
|
csr = chipStatusRegister | (1 << CSR_apulse);
|
|
else
|
|
csr = chipStatusRegister & ~(1 << CSR_apulse);
|
|
|
|
return setChipStatusRegisterPattern(csr);
|
|
}
|
|
patternParameters *setNegativePolarity(int mask) {
|
|
|
|
int csr;
|
|
if (mask)
|
|
csr = chipStatusRegister | (1 << CSR_invpol);
|
|
else
|
|
csr = chipStatusRegister & ~(1 << CSR_invpol);
|
|
|
|
return setChipStatusRegisterPattern(csr);
|
|
}
|
|
|
|
patternParameters *setChannelRegisterChip(int ichip, int *mask, int *trimbits) {
|
|
|
|
patternParameters *pat = malloc(sizeof(patternParameters));
|
|
memset(pat, 0, sizeof(patternParameters));
|
|
|
|
// validate
|
|
for (int ichan = ichip * NCHAN_1_COUNTER * NCOUNTERS;
|
|
ichan <
|
|
ichip * NCHAN_1_COUNTER * NCOUNTERS + NCHAN_1_COUNTER * NCOUNTERS;
|
|
ichan++) {
|
|
if (trimbits[ichan] < 0) {
|
|
LOG(logERROR, ("Trimbit value (%d) for channel %d is invalid - "
|
|
"setting it to 0\n",
|
|
trimbits[ichan], ichan));
|
|
trimbits[ichan] = 0;
|
|
}
|
|
if (trimbits[ichan] > 63) {
|
|
LOG(logERROR, ("Trimbit value (%d) for channel %d is invalid - "
|
|
"settings it to 63\n",
|
|
trimbits[ichan], ichan));
|
|
trimbits[ichan] = 63;
|
|
}
|
|
}
|
|
LOG(logINFO, ("Trimbits validated\n"));
|
|
|
|
// trimming
|
|
int error = 0;
|
|
uint64_t patword = 0;
|
|
int iaddr = 0;
|
|
|
|
LOG(logDEBUG1, (" Chip %d\n", ichip));
|
|
iaddr = 0;
|
|
patword = 0;
|
|
pat->word[iaddr++] = patword;
|
|
|
|
// chip select
|
|
patword = setBit(SIGNAL_TBLoad_1 + ichip, patword);
|
|
pat->word[iaddr++] = patword;
|
|
|
|
// reset trimbits
|
|
patword = setBit(SIGNAL_resStorage, patword);
|
|
patword = setBit(SIGNAL_resCounter, patword);
|
|
pat->word[iaddr++] = patword;
|
|
pat->word[iaddr++] = patword;
|
|
patword = clearBit(SIGNAL_resStorage, patword);
|
|
patword = clearBit(SIGNAL_resCounter, patword);
|
|
pat->word[iaddr++] = patword;
|
|
pat->word[iaddr++] = patword;
|
|
|
|
// select first channel
|
|
patword = setBit(SIGNAL_CHSserialIN, patword);
|
|
pat->word[iaddr++] = patword;
|
|
// 1 clk pulse
|
|
patword = setBit(SIGNAL_CHSclk, patword);
|
|
pat->word[iaddr++] = patword;
|
|
patword = clearBit(SIGNAL_CHSclk, patword);
|
|
// clear 1st channel
|
|
pat->word[iaddr++] = patword;
|
|
patword = clearBit(SIGNAL_CHSserialIN, patword);
|
|
// 2 clk pulses
|
|
for (int i = 0; i < 2; i++) {
|
|
patword = setBit(SIGNAL_CHSclk, patword);
|
|
pat->word[iaddr++] = patword;
|
|
patword = clearBit(SIGNAL_CHSclk, patword);
|
|
pat->word[iaddr++] = patword;
|
|
}
|
|
|
|
// for each channel (all chips)
|
|
for (int ich = 0; ich < NCHAN_1_COUNTER; ich++) {
|
|
LOG(logDEBUG1, (" Chip %d, Channel %d\n", ichip, ich));
|
|
int val =
|
|
trimbits[ichip * NCHAN_1_COUNTER * NCOUNTERS + NCOUNTERS * ich] +
|
|
trimbits[ichip * NCHAN_1_COUNTER * NCOUNTERS + NCOUNTERS * ich +
|
|
1] *
|
|
64 +
|
|
trimbits[ichip * NCHAN_1_COUNTER * NCOUNTERS + NCOUNTERS * ich +
|
|
2] *
|
|
64 * 64;
|
|
|
|
// push 6 0 bits
|
|
for (int i = 0; i < 3; i++) {
|
|
patword = clearBit(SIGNAL_serialIN, patword);
|
|
patword = clearBit(SIGNAL_clk, patword);
|
|
pat->word[iaddr++] = patword;
|
|
patword = setBit(SIGNAL_clk, patword);
|
|
pat->word[iaddr++] = patword;
|
|
}
|
|
|
|
for (int i = 0; i < 3; i++) {
|
|
if (mask[i])
|
|
patword = setBit(SIGNAL_serialIN, patword);
|
|
else
|
|
patword = clearBit(SIGNAL_serialIN, patword);
|
|
patword = clearBit(SIGNAL_clk, patword);
|
|
pat->word[iaddr++] = patword;
|
|
patword = setBit(SIGNAL_clk, patword);
|
|
pat->word[iaddr++] = patword;
|
|
}
|
|
|
|
// deserialize
|
|
for (int i = 0; i < 18; i++) {
|
|
if (val & (1 << i)) {
|
|
patword = setBit(SIGNAL_serialIN, patword);
|
|
} else {
|
|
patword = clearBit(SIGNAL_serialIN, patword);
|
|
}
|
|
patword = clearBit(SIGNAL_clk, patword);
|
|
pat->word[iaddr++] = patword;
|
|
|
|
patword = setBit(SIGNAL_clk, patword);
|
|
pat->word[iaddr++] = patword;
|
|
}
|
|
pat->word[iaddr++] = patword;
|
|
pat->word[iaddr++] = patword;
|
|
|
|
// move to next channel
|
|
for (int i = 0; i < 3; i++) {
|
|
patword = setBit(SIGNAL_CHSclk, patword);
|
|
pat->word[iaddr++] = patword;
|
|
patword = clearBit(SIGNAL_CHSclk, patword);
|
|
pat->word[iaddr++] = patword;
|
|
}
|
|
}
|
|
// chip unselect
|
|
patword = clearBit(SIGNAL_TBLoad_1 + ichip, patword);
|
|
pat->word[iaddr++] = patword;
|
|
|
|
// last iaddr check
|
|
if (iaddr >= MAX_PATTERN_LENGTH) {
|
|
LOG(logERROR, ("Addr 0x%x is past max_address_length 0x%x!\n", iaddr,
|
|
MAX_PATTERN_LENGTH));
|
|
error = 1;
|
|
}
|
|
|
|
if (iaddr >= MAX_PATTERN_LENGTH) {
|
|
LOG(logERROR, ("Addr 0x%x is past max_address_length 0x%x!\n", iaddr,
|
|
MAX_PATTERN_LENGTH));
|
|
error = 1;
|
|
}
|
|
// set pattern wait address
|
|
for (int i = 0; i <= 2; i++)
|
|
pat->wait[i] = MAX_PATTERN_LENGTH - 1;
|
|
// pattern loop
|
|
for (int i = 0; i <= 2; i++) {
|
|
// int stop = MAX_PATTERN_LENGTH - 1, nloop = 0;
|
|
pat->loop[i * 2 + 0] = MAX_PATTERN_LENGTH - 1;
|
|
pat->loop[i * 2 + 1] = MAX_PATTERN_LENGTH - 1;
|
|
pat->nloop[i] = 0;
|
|
}
|
|
|
|
// pattern limits
|
|
{
|
|
pat->limits[0] = 0;
|
|
pat->limits[1] = iaddr;
|
|
}
|
|
|
|
if (error == 0) {
|
|
|
|
LOG(logINFO, ("All trimbits have been loaded\n"));
|
|
} else {
|
|
free(pat);
|
|
return NULL;
|
|
}
|
|
return pat;
|
|
}
|