confadc added to client, removed conf adc depending on burst mode

This commit is contained in:
maliakal_d 2020-07-15 13:30:30 +02:00
parent 7752b86d97
commit d7f490701b
12 changed files with 335 additions and 73 deletions

View File

@ -503,7 +503,7 @@ int readConfigFile() {
memset(line, 0, LZ); memset(line, 0, LZ);
char command[LZ]; char command[LZ];
int nadcRead = 0; int nAdcTotal = 0;
// keep reading a line // keep reading a line
while (fgets(line, LZ, fd)) { while (fgets(line, LZ, fd)) {
@ -617,7 +617,7 @@ int readConfigFile() {
break; break;
} }
// validations // validations
if (value > ASIC_ADC_MAX_VAL) { if (value < 0 || value > ASIC_ADC_MAX_VAL) {
sprintf(initErrorMessage, sprintf(initErrorMessage,
"Could not configure adc from on-board server config " "Could not configure adc from on-board server config "
"file. Invalid value (max 0x%x). Line:[%s].\n", "file. Invalid value (max 0x%x). Line:[%s].\n",
@ -625,28 +625,23 @@ int readConfigFile() {
break; break;
} }
int chipmin = 0; if (setADCConfiguration(ichip, iadc, value) == FAIL) {
int chipmax = NCHIP; sprintf(initErrorMessage,
int adcmin = 0; "Could not configure adc from on-board server "
int adcmax = NADC; "config file. Line:[%s].\n",
line);
// specific chip break;
if (ichip != -1) {
chipmin = ichip;
chipmax = ichip + 1;
}
// specific adc
if (iadc != -1) {
adcmin = iadc;
adcmax = iadc + 1;
} }
for (int i = chipmin; i < chipmax; ++i) { // to ensure all adcs are configured at start up
for (int j = adcmin; j < adcmax; ++j) { int nadc = 1;
adcConfiguration[i][j] = (uint8_t)value; if (iadc == -1) {
++nadcRead; nadc = NADC;
}
} }
if (ichip == -1) {
nadc *= NCHIP;
}
nAdcTotal += nadc;
} }
// vchip command // vchip command
@ -762,17 +757,11 @@ int readConfigFile() {
fclose(fd); fclose(fd);
if (!strlen(initErrorMessage)) { if (!strlen(initErrorMessage)) {
if (nadcRead != NADC * NCHIP) { if (nAdcTotal != NADC * NCHIP) {
sprintf(initErrorMessage, sprintf(initErrorMessage,
"Could not configure adc from on-board server config file. " "Could not configure adc from on-board server config file. "
"Insufficient adcconf commands. Read %d, expected %d\n", "Insufficient adcconf commands. Read %d, expected %d\n",
nadcRead, NADC * NCHIP); nAdcTotal, NADC * NCHIP);
}
}
for (int i = 0; i < NCHIP; ++i) {
for (int j = 0; j < NADC; ++j) {
LOG(logDEBUG2,
("adc read %d %d: 0x%02hhx\n", i, j, adcConfiguration[i][j]));
} }
} }
@ -1934,24 +1923,52 @@ int setVetoFile(int chipIndex, int *gainIndices, int *values) {
return configureASICVetoReference(chipIndex, values); return configureASICVetoReference(chipIndex, values);
} }
int configureSingleADCDriver(int chipIndex) { int setADCConfiguration(int chipIndex, int adcIndex, int value) {
LOG(logINFO, ("Configuring ADC for %s chips [chipIndex:%d Burst Mode:%d]\n", LOG(logINFO, ("Configuring ADC [chipIndex:%d, adcIndex:%d, value:0x%x]\n",
chipIndex == -1 ? "All" : "Single", chipIndex, burstMode)); chipIndex, adcIndex, value));
// validations
if (chipIndex < -1 || chipIndex >= NCHIP) {
LOG(logERROR, ("Invalid chip index %d\n", chipIndex));
return FAIL;
}
if (adcIndex < -1 || adcIndex >= NADC) {
LOG(logERROR, ("Invalid adc index %d\n", adcIndex));
return FAIL;
}
// validations
if (value < 0 || value > ASIC_ADC_MAX_VAL) {
LOG(logERROR, ("Invalid value 0x%x\n", value));
return FAIL;
}
int chipmin = 0;
int chipmax = NCHIP;
int adcmin = 0;
int adcmax = NADC;
// specific chip
if (chipIndex != -1) {
chipmin = chipIndex;
chipmax = chipIndex + 1;
}
// specific adc
if (adcIndex != -1) {
adcmin = adcIndex;
adcmax = adcIndex + 1;
}
// update values
for (int i = chipmin; i < chipmax; ++i) {
for (int j = adcmin; j < adcmax; ++j) {
adcConfiguration[i][j] = (uint8_t)value;
LOG(logDEBUG1,
("Value [%d][%d]: 0x%02hhx\n", i, j, adcConfiguration[i][j]));
}
}
// single chip configuration
int ind = chipIndex; int ind = chipIndex;
// all chips, take the first one as all equal
if (ind == -1) { if (ind == -1) {
ind = 0; ind = 0;
} }
uint8_t values[NADC];
memcpy(values, adcConfiguration + ind * NADC, NADC);
// change adc values if continuous mode
for (int i = 0; i < NADC; ++i) {
if (burstMode == BURST_OFF) {
values[i] |= ASIC_CONTINUOUS_MODE_MSK;
}
LOG(logDEBUG2, ("Value %d: 0x%02hhx\n", i, values[i]));
}
const int lenDataBitsPerADC = ASIC_ADC_MAX_BITS; // 7 const int lenDataBitsPerADC = ASIC_ADC_MAX_BITS; // 7
const int lenBits = lenDataBitsPerADC * NADC; // 224 const int lenBits = lenDataBitsPerADC * NADC; // 224
@ -1966,8 +1983,9 @@ int configureSingleADCDriver(int chipIndex) {
for (int ich = 0; ich < NADC; ++ich) { for (int ich = 0; ich < NADC; ++ich) {
// loop through all bits in a value // loop through all bits in a value
for (int iBit = 0; iBit < lenDataBitsPerADC; ++iBit) { for (int iBit = 0; iBit < lenDataBitsPerADC; ++iBit) {
commandBytes[offset++] = commandBytes[offset++] = ((adcConfiguration[ind][ich] >>
((values[ich] >> (lenDataBitsPerADC - 1 - iBit)) & 0x1); (lenDataBitsPerADC - 1 - iBit)) &
0x1);
} }
} }
@ -1994,29 +2012,46 @@ int configureSingleADCDriver(int chipIndex) {
return OK; return OK;
} }
int configureADC() { int getADCConfiguration(int chipIndex, int adcIndex) {
LOG(logINFO, ("Configuring ADC \n")); // already validated at tcp interface
if (chipIndex < -1 || chipIndex >= NCHIP) {
LOG(logERROR, ("Invalid chip index %d\n", chipIndex));
return -1;
}
if (adcIndex < -1 || adcIndex >= NADC) {
LOG(logERROR, ("Invalid adc index %d\n", adcIndex));
return -1;
}
int chipmin = 0;
int chipmax = NCHIP;
int adcmin = 0;
int adcmax = NADC;
// specific chip
if (chipIndex != -1) {
chipmin = chipIndex;
chipmax = chipIndex + 1;
}
// specific adc
if (adcIndex != -1) {
adcmin = adcIndex;
adcmax = adcIndex + 1;
}
int val = adcConfiguration[chipmin][adcmin];
int equal = 1; // ensure same values for chip and adc in question
for (int i = 0; i < NADC; ++i) { for (int i = chipmin; i < chipmax; ++i) {
int val = adcConfiguration[0][i]; for (int j = adcmin; j < adcmax; ++j) {
for (int j = 1; j < NCHIP; ++j) { if (adcConfiguration[i][j] != val) {
if (adcConfiguration[j][i] != val) { LOG(logINFO,
equal = 0; ("\tADC configuration 0x%x at [%d][%d] differs from 0x%x "
break; "at "
"[%d][%d], returning -1\n",
adcConfiguration[i][j], i, j, val, chipmin, adcmin));
return -1;
} }
} }
} }
if (equal) { return val;
return configureSingleADCDriver(-1);
} else {
for (int i = 0; i < NCHIP; ++i) {
if (configureSingleADCDriver(i) == FAIL) {
return FAIL;
}
}
}
return OK;
} }
int setBurstModeinFPGA(enum burstMode value) { int setBurstModeinFPGA(enum burstMode value) {
@ -2121,20 +2156,20 @@ int setBurstMode(enum burstMode burst) {
} }
} }
LOG(logINFO, ("\tDone Updating registers\n")) LOG(logINFO, ("\tDone Updating registers\n"))
return configureASICGlobalSettings(); return configureASICGlobalSettings();
} }
int configureASICGlobalSettings() { int configureASICGlobalSettings() {
LOG(logINFO, ("\tSetting %s Mode in Chip\n",
burstMode == BURST_OFF ? "Continuous" : "Burst"));
int modeValue = int modeValue =
burstMode ? ASIC_GLOBAL_BURST_VALUE : ASIC_GLOBAL_CONT_VALUE; burstMode ? ASIC_GLOBAL_BURST_VALUE : ASIC_GLOBAL_CONT_VALUE;
int value = ((modeValue << ASIC_GLOBAL_MODE_OFST) & ASIC_GLOBAL_MODE_MSK) | int value = ((modeValue << ASIC_GLOBAL_MODE_OFST) & ASIC_GLOBAL_MODE_MSK) |
((filter << ASIC_FILTER_OFST) & ASIC_FILTER_MSK) | ((filter << ASIC_FILTER_OFST) & ASIC_FILTER_MSK) |
((cdsGain << ASIC_CDS_GAIN_OFST) & ASIC_CDS_GAIN_MSK); ((cdsGain << ASIC_CDS_GAIN_OFST) & ASIC_CDS_GAIN_MSK);
LOG(logINFO, ("\tsetting value:0x%x (mode:%d, filter:%d, cdsgain:%d)\n", LOG(logINFO,
value, modeValue, filter, cdsGain)); ("\tSending Global Chip settings:0x%x (mode:%d(%s), filter:%d, "
"cdsgain:%d)\n",
value, modeValue, (burstMode == BURST_OFF ? "Continuous" : "Burst"),
filter, cdsGain));
const int padding = 6; // due to address (4) to make it byte aligned const int padding = 6; // due to address (4) to make it byte aligned
const int lenTotalBits = padding + ASIC_GLOBAL_SETT_MAX_BITS + const int lenTotalBits = padding + ASIC_GLOBAL_SETT_MAX_BITS +
@ -2172,7 +2207,7 @@ int configureASICGlobalSettings() {
return FAIL; return FAIL;
} }
return configureADC(); return OK;
} }
enum burstMode getBurstMode() { enum burstMode getBurstMode() {

View File

@ -507,8 +507,8 @@ int setVetoPhoton(int chipIndex, int gainIndex, int *values);
int configureASICVetoReference(int chipIndex, int *values); int configureASICVetoReference(int chipIndex, int *values);
int getVetoPhoton(int chipIndex, int *retvals); int getVetoPhoton(int chipIndex, int *retvals);
int setVetoFile(int chipIndex, int *gainIndices, int *values); int setVetoFile(int chipIndex, int *gainIndices, int *values);
int configureSingleADCDriver(int chipIndex); int setADCConfiguration(int chipIndex, int adcIndex, int value);
int configureADC(); int getADCConfiguration(int chipIndex, int adcIndex);
int setBurstModeinFPGA(enum burstMode value); int setBurstModeinFPGA(enum burstMode value);
int setBurstMode(enum burstMode burst); int setBurstMode(enum burstMode burst);
int configureASICGlobalSettings(); int configureASICGlobalSettings();

View File

@ -234,3 +234,5 @@ int set_cds_gain(int);
int get_filter(int); int get_filter(int);
int set_filter(int); int set_filter(int);
int set_veto_file(int); int set_veto_file(int);
int get_adc_config(int);
int set_adc_config(int);

View File

@ -351,6 +351,8 @@ void function_table() {
flist[F_GET_FILTER] = &get_filter; flist[F_GET_FILTER] = &get_filter;
flist[F_SET_FILTER] = &set_filter; flist[F_SET_FILTER] = &set_filter;
flist[F_SET_VETO_FILE] = &set_veto_file; flist[F_SET_VETO_FILE] = &set_veto_file;
flist[F_GET_ADC_CONFIGURATION] = &get_adc_config;
flist[F_SET_ADC_CONFIGURATION] = &set_adc_config;
// check // check
if (NUM_DET_FUNCTIONS >= RECEIVER_ENUM_START) { if (NUM_DET_FUNCTIONS >= RECEIVER_ENUM_START) {
@ -7820,3 +7822,107 @@ int set_veto_file(int file_des) {
#endif #endif
return Server_SendResult(file_des, INT32, NULL, 0); return Server_SendResult(file_des, INT32, NULL, 0);
} }
int get_adc_config(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();
LOG(logDEBUG1, ("Getting adc configuration [chipIndex:%d, adcIndex:%d]\n",
args[0], args[1]));
#ifndef GOTTHARD2D
functionNotImplemented();
#else
// get only
int chipIndex = args[0];
int adcIndex = args[1];
if (chipIndex < -1 || chipIndex >= NCHIP) {
ret = FAIL;
sprintf(mess,
"Could not get adc configuration. Invalid chip index %d\n",
chipIndex);
LOG(logERROR, (mess));
} else if (adcIndex < -1 || adcIndex >= NADC) {
ret = FAIL;
sprintf(mess, "Could not get adc configuration. Invalid adc index %d\n",
adcIndex);
LOG(logERROR, (mess));
} else {
retval = getADCConfiguration(chipIndex, adcIndex);
LOG(logDEBUG1, ("adc config retval: %u\n", retval));
if (retval == -1) {
ret = FAIL;
sprintf(mess,
"Could not get a single adc configuration. Different "
"values for "
"selected adc (%d) and chip (%d) range.\n",
chipIndex, adcIndex);
LOG(logERROR, (mess));
}
}
#endif
return Server_SendResult(file_des, INT32, &retval, sizeof(retval));
}
int set_adc_config(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();
LOG(logDEBUG1,
("Setting adc configuration [chipIndex:%d, adcIndex:%d, value:0x%x]\n",
args[0], args[1], args[2]));
#ifndef GOTTHARD2D
functionNotImplemented();
#else
// only set
if (Server_VerifyLock() == OK) {
int chipIndex = args[0];
int adcIndex = args[1];
int value = args[2];
if (chipIndex < -1 || chipIndex >= NCHIP) {
ret = FAIL;
sprintf(mess,
"Could not get adc configuration. Invalid chip index %d. "
"Options: [-1 to %d]\n",
chipIndex, NCHIP);
LOG(logERROR, (mess));
} else if (adcIndex < -1 || adcIndex >= NADC) {
ret = FAIL;
sprintf(mess,
"Could not get adc configuration. Invalid adc index %d. "
"Options: [-1 to %d]\n",
adcIndex, NADC);
LOG(logERROR, (mess));
} else if (value < 0 || value > ASIC_ADC_MAX_VAL) {
ret = FAIL;
sprintf(mess,
"Could not get adc configuration. Invalid value 0x%x. "
"Options: [0 to 0x%x]\n",
value, ASIC_ADC_MAX_VAL);
LOG(logERROR, (mess));
} else {
ret = setADCConfiguration(chipIndex, adcIndex, value);
if (ret == FAIL) {
sprintf(mess,
"Could not set adc configuration in chip (chipIndex: "
"%d, adcIndex: %d, value:0x%x).\n",
chipIndex, adcIndex, value);
LOG(logERROR, (mess));
} else {
int retval = getADCConfiguration(chipIndex, adcIndex);
LOG(logDEBUG1, ("adc config retval: %u\n", retval));
validate(value, retval, "configure adc", HEX);
}
}
}
#endif
return Server_SendResult(file_des, INT32, NULL, 0);
}

View File

@ -1023,6 +1023,14 @@ class Detector {
/** [Gotthard2] */ /** [Gotthard2] */
void setVeto(const bool enable, Positions pos = {}); void setVeto(const bool enable, Positions pos = {});
/** [Gotthard2] */
Result<int> getADCConfiguration(const int chipIndex, const int adcIndex,
Positions pos = {}) const;
/** [Gotthard2] */
void setADCConfiguration(const int chipIndex, const int adcIndex,
const int value, Positions pos = {});
/************************************************** /**************************************************
* * * *
* Mythen3 Specific * * Mythen3 Specific *

View File

@ -1738,6 +1738,37 @@ std::string CmdProxy::BurstMode(int action) {
return os.str(); return os.str();
} }
std::string CmdProxy::ConfigureADC(int action) {
std::ostringstream os;
os << cmd << ' ';
if (action == defs::HELP_ACTION) {
os << "[chip index 0-10, -1 for all] [adc index 0-31, -1 for all] [12 "
"bit configuration value in hex]\n\t[Gotthard2] Sets "
"configuration for specific chip and adc, but configures 1 chip "
"(all adcs for that chip) at a time."
<< '\n';
} else if (action == defs::GET_ACTION) {
if (args.size() != 2) {
WrongNumberOfParameters(2);
}
auto t = det->getADCConfiguration(StringTo<int>(args[0]),
StringTo<int>(args[1]));
os << OutStringHex(t) << '\n';
} else if (action == defs::PUT_ACTION) {
if (args.size() != 3) {
WrongNumberOfParameters(3);
}
int value = StringTo<int>(args[2]);
det->setADCConfiguration(StringTo<int>(args[0]), StringTo<int>(args[1]),
value, {det_id});
os << '[' << args[0] << ", " << args[1] << ", " << ToStringHex(value)
<< "]\n";
} else {
throw sls::RuntimeError("Unknown action");
}
return os.str();
}
/* Mythen3 Specific */ /* Mythen3 Specific */
std::string CmdProxy::Counters(int action) { std::string CmdProxy::Counters(int action) {

View File

@ -841,6 +841,7 @@ class CmdProxy {
{"currentsource", &CmdProxy::currentsource}, {"currentsource", &CmdProxy::currentsource},
{"timingsource", &CmdProxy::timingsource}, {"timingsource", &CmdProxy::timingsource},
{"veto", &CmdProxy::veto}, {"veto", &CmdProxy::veto},
{"confadc", &CmdProxy::ConfigureADC},
/* Mythen3 Specific */ /* Mythen3 Specific */
{"counters", &CmdProxy::Counters}, {"counters", &CmdProxy::Counters},
@ -1018,6 +1019,7 @@ class CmdProxy {
std::string VetoReference(int action); std::string VetoReference(int action);
std::string VetoFile(int action); std::string VetoFile(int action);
std::string BurstMode(int action); std::string BurstMode(int action);
std::string ConfigureADC(int action);
/* Mythen3 Specific */ /* Mythen3 Specific */
std::string Counters(int action); std::string Counters(int action);
std::string GateDelay(int action); std::string GateDelay(int action);

View File

@ -1350,6 +1350,19 @@ void Detector::setVeto(bool enable, Positions pos) {
pimpl->Parallel(&Module::setVeto, pos, enable); pimpl->Parallel(&Module::setVeto, pos, enable);
} }
Result<int> Detector::getADCConfiguration(const int chipIndex,
const int adcIndex,
Positions pos) const {
return pimpl->Parallel(&Module::getADCConfiguration, pos, chipIndex,
adcIndex);
}
void Detector::setADCConfiguration(const int chipIndex, const int adcIndex,
const int value, Positions pos) {
pimpl->Parallel(&Module::setADCConfiguration, pos, chipIndex, adcIndex,
value);
}
// Mythen3 Specific // Mythen3 Specific
Result<uint32_t> Detector::getCounterMask(Positions pos) const { Result<uint32_t> Detector::getCounterMask(Positions pos) const {

View File

@ -1645,6 +1645,17 @@ void Module::setVeto(bool enable) {
sendToDetector(F_SET_VETO, static_cast<int>(enable), nullptr); sendToDetector(F_SET_VETO, static_cast<int>(enable), nullptr);
} }
int Module::getADCConfiguration(const int chipIndex, const int adcIndex) {
int args[]{chipIndex, adcIndex};
return sendToDetector<int>(F_GET_ADC_CONFIGURATION, args);
}
void Module::setADCConfiguration(const int chipIndex, const int adcIndex,
int value) {
int args[]{chipIndex, adcIndex, value};
sendToDetector(F_SET_ADC_CONFIGURATION, args, nullptr);
}
// Mythen3 Specific // Mythen3 Specific
uint32_t Module::getCounterMask() { uint32_t Module::getCounterMask() {

View File

@ -386,6 +386,9 @@ class Module : public virtual slsDetectorDefs {
void setTimingSource(slsDetectorDefs::timingSourceType value); void setTimingSource(slsDetectorDefs::timingSourceType value);
bool getVeto(); bool getVeto();
void setVeto(bool enable); void setVeto(bool enable);
int getADCConfiguration(const int chipIndex, const int adcIndex);
void setADCConfiguration(const int chipIndex, const int adcIndex,
int value);
/************************************************** /**************************************************
* * * *

View File

@ -537,3 +537,50 @@ TEST_CASE("veto", "[.cmd][.new]") {
REQUIRE_THROWS(proxy.Call("veto", {}, -1, GET)); REQUIRE_THROWS(proxy.Call("veto", {}, -1, GET));
} }
} }
TEST_CASE("confadc", "[.cmd][.new]") {
Detector det;
CmdProxy proxy(&det);
auto det_type = det.getDetectorType().squash();
if (det_type == defs::GOTTHARD2) {
int ndet = det.size();
int nchip = 10;
int nadc = 32;
int prev_val[ndet][nchip][nadc];
for (int i = 0; i != ndet; ++i) {
for (int j = 0; j != nchip; ++j) {
for (int k = 0; k != nadc; ++k) {
prev_val[i][j][k] =
det.getADCConfiguration(j, k, {i}).squash();
}
}
}
REQUIRE_THROWS(proxy.Call("confadc", {"11", "2", "0x3ff"}, -1,
PUT)); // invalid chip index
REQUIRE_THROWS(proxy.Call("confadc", {"-1", "10", "0x3ff"}, -1,
PUT)); // invalid adc index
REQUIRE_THROWS(proxy.Call("confadc", {"-1", "10", "0x1fff"}, -1,
PUT)); // invalid value
{
std::ostringstream oss;
proxy.Call("confadc", {"-1", "-1", "0x11"}, -1, PUT, oss);
REQUIRE(oss.str() == "confadc [-1, -1, 0x11]\n");
}
{
std::ostringstream oss;
proxy.Call("confadc", {"2", "3"}, -1, GET, oss);
REQUIRE(oss.str() == "confadc 0x11\n");
}
for (int i = 0; i != ndet; ++i) {
for (int j = 0; j != nchip; ++j) {
for (int k = 0; k != nadc; ++k) {
det.setADCConfiguration(j, k, prev_val[i][j][k], {i});
}
}
}
} else {
REQUIRE_THROWS(proxy.Call("confadc", {}, -1, GET));
}
}

View File

@ -208,6 +208,8 @@ enum detFuncs {
F_GET_FILTER, F_GET_FILTER,
F_SET_FILTER, F_SET_FILTER,
F_SET_VETO_FILE, F_SET_VETO_FILE,
F_GET_ADC_CONFIGURATION,
F_SET_ADC_CONFIGURATION,
NUM_DET_FUNCTIONS, NUM_DET_FUNCTIONS,
RECEIVER_ENUM_START = 256, /**< detector function should not exceed this RECEIVER_ENUM_START = 256, /**< detector function should not exceed this
@ -514,6 +516,8 @@ const char* getFunctionNameFromEnum(enum detFuncs func) {
case F_GET_FILTER: return "F_GET_FILTER"; case F_GET_FILTER: return "F_GET_FILTER";
case F_SET_FILTER: return "F_SET_FILTER"; case F_SET_FILTER: return "F_SET_FILTER";
case F_SET_VETO_FILE: return "F_SET_VETO_FILE"; case F_SET_VETO_FILE: return "F_SET_VETO_FILE";
case F_SET_ADC_CONFIGURATION: return "F_SET_ADC_CONFIGURATION";
case F_GET_ADC_CONFIGURATION: return "F_GET_ADC_CONFIGURATION";
case NUM_DET_FUNCTIONS: return "NUM_DET_FUNCTIONS"; case NUM_DET_FUNCTIONS: return "NUM_DET_FUNCTIONS";
case RECEIVER_ENUM_START: return "RECEIVER_ENUM_START"; case RECEIVER_ENUM_START: return "RECEIVER_ENUM_START";