diff --git a/RELEASE.txt b/RELEASE.txt index 23e0e1ade..035deeca5 100755 --- a/RELEASE.txt +++ b/RELEASE.txt @@ -39,6 +39,7 @@ This document describes the differences between v7.0.0 and v6.x.x - current frame index points to listened frame index (not processed index) - when in discard partial frames or empty mode, the frame number doesnt increase by 1, it increases to that number (so its faster) - file write disabled by default +- eiger 12 bit mode - start non blocking acquisition at modular level - hostname cmd failed when connecting to servers in update mode (ctb, moench, jungfrau, eiger) - missingpackets signed (negative => extra packets) diff --git a/python/slsdet/detector.py b/python/slsdet/detector.py index 1d2ec6218..6c4b200db 100755 --- a/python/slsdet/detector.py +++ b/python/slsdet/detector.py @@ -287,7 +287,7 @@ class Detector(CppDetectorApi): Note ----- - [Eiger] Options: 4, 8, 16, 32. If set to 32, also sets clkdivider to 2 (quarter speed), else to 0 (full speed)\n + [Eiger] Options: 4, 8, 12, 16, 32. If set to 32, also sets clkdivider to 2 (quarter speed), else to 0 (full speed)\n [Mythen3] Options: 8, 16, 32 \n [Jungfrau][Gotthard][Ctb][Moench][Mythen3][Gotthard2] 16 """ diff --git a/slsDetectorGui/forms/form_tab_settings.ui b/slsDetectorGui/forms/form_tab_settings.ui index 32890e2d0..d99e9d9ba 100755 --- a/slsDetectorGui/forms/form_tab_settings.ui +++ b/slsDetectorGui/forms/form_tab_settings.ui @@ -97,6 +97,11 @@ 65535 + + + 4095 + + 255 diff --git a/slsDetectorGui/include/qTabSettings.h b/slsDetectorGui/include/qTabSettings.h index 2a2a2c8af..a2a6ad73e 100644 --- a/slsDetectorGui/include/qTabSettings.h +++ b/slsDetectorGui/include/qTabSettings.h @@ -69,5 +69,11 @@ class qTabSettings : public QWidget, private Ui::TabSettingsObject { enum { DYNAMIC, FORCE_SWITCH_G1, FORCE_SWITCH_G2, FIX_G1, FIX_G2, FIX_G0 }; bool isVisibleFixG0{false}; - enum { DYNAMICRANGE_32, DYNAMICRANGE_16, DYNAMICRANGE_8, DYNAMICRANGE_4 }; + enum { + DYNAMICRANGE_32, + DYNAMICRANGE_16, + DYNAMICRANGE_12, + DYNAMICRANGE_8, + DYNAMICRANGE_4 + }; }; diff --git a/slsDetectorGui/src/qDrawPlot.cpp b/slsDetectorGui/src/qDrawPlot.cpp index 40edc1538..a95c9efcd 100644 --- a/slsDetectorGui/src/qDrawPlot.cpp +++ b/slsDetectorGui/src/qDrawPlot.cpp @@ -1064,6 +1064,8 @@ void qDrawPlot::toDoublePixelData(double *dest, char *source, int size, // mythen3 / gotthard2 debugging int discardBits = numDiscardBits; + uint16_t temp = 0; + uint8_t *src = (uint8_t *)source; switch (dr) { case 4: @@ -1083,6 +1085,19 @@ void qDrawPlot::toDoublePixelData(double *dest, char *source, int size, } break; + case 12: + for (ichan = 0; ichan < size; ++ichan) { + temp = (*src++ & 0xFF); + temp |= ((*src & 0xF) << 8u); + dest[ichan] = (double)temp; + ++ichan; + + temp = ((*src++ & 0xF0) >> 4u); + temp |= ((*src++ & 0xFF) << 4u); + dest[ichan] = (double)temp; + } + break; + case 16: if (detType == slsDetectorDefs::JUNGFRAU || detType == slsDetectorDefs::GOTTHARD2) { diff --git a/slsDetectorGui/src/qTabSettings.cpp b/slsDetectorGui/src/qTabSettings.cpp index dcee0a450..9a3d97132 100644 --- a/slsDetectorGui/src/qTabSettings.cpp +++ b/slsDetectorGui/src/qTabSettings.cpp @@ -60,13 +60,19 @@ void qTabSettings::SetupWidgetWindow() { QStandardItemModel *model = qobject_cast(comboDynamicRange->model()); if (model) { - QModelIndex index; QStandardItem *item; - index = - model->index(DYNAMICRANGE_4, comboDynamicRange->modelColumn(), - comboDynamicRange->rootModelIndex()); - item = model->itemFromIndex(index); - item->setEnabled(false); + int dr = DYNAMICRANGE_4; + for (int i = 0; i != 2; ++i) { + // disable dr 4 + QModelIndex index = + model->index(dr, comboDynamicRange->modelColumn(), + comboDynamicRange->rootModelIndex()); + item = model->itemFromIndex(index); + item->setEnabled(false); + + // disable dr 12 + dr = DYNAMICRANGE_12; + } } } else if (detType == slsDetectorDefs::EIGER) { lblDynamicRange->setEnabled(true); @@ -305,6 +311,9 @@ void qTabSettings::GetDynamicRange() { case 16: comboDynamicRange->setCurrentIndex(DYNAMICRANGE_16); break; + case 12: + comboDynamicRange->setCurrentIndex(DYNAMICRANGE_12); + break; case 8: comboDynamicRange->setCurrentIndex(DYNAMICRANGE_8); break; @@ -333,6 +342,9 @@ void qTabSettings::SetDynamicRange(int index) { case DYNAMICRANGE_16: det->setDynamicRange(16); break; + case DYNAMICRANGE_12: + det->setDynamicRange(12); + break; case DYNAMICRANGE_8: det->setDynamicRange(8); break; diff --git a/slsDetectorServers/ctbDetectorServer/bin/ctbDetectorServer_developer b/slsDetectorServers/ctbDetectorServer/bin/ctbDetectorServer_developer index 044bb0569..cc425b2bb 100755 Binary files a/slsDetectorServers/ctbDetectorServer/bin/ctbDetectorServer_developer and b/slsDetectorServers/ctbDetectorServer/bin/ctbDetectorServer_developer differ diff --git a/slsDetectorServers/ctbDetectorServer/slsDetectorFunctionList.c b/slsDetectorServers/ctbDetectorServer/slsDetectorFunctionList.c index 06999e54d..40217eb41 100644 --- a/slsDetectorServers/ctbDetectorServer/slsDetectorFunctionList.c +++ b/slsDetectorServers/ctbDetectorServer/slsDetectorFunctionList.c @@ -702,8 +702,16 @@ void resetPeripheral() { } /* set parameters - dr, adcenablemask */ +int setDynamicRange(int dr) { + if (dr == 16) + return OK; + return FAIL; +} -int setDynamicRange(int dr) { return DYNAMIC_RANGE; } +int getDynamicRange(int *retval) { + *retval = DYNAMIC_RANGE; + return OK; +} int setADCEnableMask(uint32_t mask) { if (mask == 0u) { diff --git a/slsDetectorServers/eigerDetectorServer/Beb.c b/slsDetectorServers/eigerDetectorServer/Beb.c index 90512c7b1..e9f1ad42c 100644 --- a/slsDetectorServers/eigerDetectorServer/Beb.c +++ b/slsDetectorServers/eigerDetectorServer/Beb.c @@ -862,11 +862,17 @@ void Beb_ResetFrameNumber() { } int Beb_SetUpTransferParameters(short the_bit_mode) { - if (the_bit_mode != 4 && the_bit_mode != 8 && the_bit_mode != 16 && - the_bit_mode != 32) + switch (the_bit_mode) { + case 4: + case 8: + case 12: + case 16: + case 32: + Beb_bit_mode = the_bit_mode; + return 1; + default: return 0; - Beb_bit_mode = the_bit_mode; - return 1; + } } int Beb_StopAcquisition() { diff --git a/slsDetectorServers/eigerDetectorServer/FebControl.c b/slsDetectorServers/eigerDetectorServer/FebControl.c index 27d98a30a..5aba2ecf7 100644 --- a/slsDetectorServers/eigerDetectorServer/FebControl.c +++ b/slsDetectorServers/eigerDetectorServer/FebControl.c @@ -931,7 +931,10 @@ unsigned int Feb_Control_ConvertTimeToRegister(float time_in_sec) { int Feb_Control_PrepareForAcquisition() { LOG(logINFOBLUE, ("Preparing for Acquisition\n")); - Feb_Control_PrintAcquisitionSetup(); + if (!Feb_Control_PrintAcquisitionSetup()) { + LOG(logERROR, ("Could not prepare acquisition\n")); + return 0; + } if (Feb_Control_Reset() == STATUS_ERROR) { LOG(logERROR, ("Trouble reseting daq or data stream\n")); @@ -988,20 +991,26 @@ int Feb_Control_PrepareForAcquisition() { return 1; } -void Feb_Control_PrintAcquisitionSetup() { +int Feb_Control_PrintAcquisitionSetup() { time_t rawtime; time(&rawtime); struct tm *timeinfo = localtime(&rawtime); - LOG(logINFO, - ("Starting an exposure: (%s)" - "\t Dynamic range nbits: %d\n" - "\t Trigger mode: 0x%x\n" - "\t Number of exposures: %d\n" - "\t Exsposure time (if used): %f seconds.\n" - "\t Exsposure period (if used): %f seconds.\n\n", - asctime(timeinfo), Feb_Control_GetDynamicRange(), - Feb_Control_triggerMode, Feb_Control_GetNExposures(), - Feb_Control_exposure_time_in_sec, Feb_Control_exposure_period_in_sec)); + int dr = 0; + if (!Feb_Control_GetDynamicRange(&dr)) { + LOG(logERROR, ("Could not print acquisition set up\n")); + return 0; + } + LOG(logINFO, ("Starting an exposure: (%s)" + "\t Dynamic range nbits: %d\n" + "\t Trigger mode: 0x%x\n" + "\t Number of exposures: %d\n" + "\t Exsposure time (if used): %f seconds.\n" + "\t Exsposure period (if used): %f seconds.\n\n", + asctime(timeinfo), dr, Feb_Control_triggerMode, + Feb_Control_GetNExposures(), Feb_Control_exposure_time_in_sec, + Feb_Control_exposure_period_in_sec)); + + return 1; } int Feb_Control_StartAcquisition() { @@ -1169,49 +1178,106 @@ int Feb_Control_SoftwareTrigger(int block) { } // parameters -int Feb_Control_SetDynamicRange(unsigned int four_eight_sixteen_or_thirtytwo) { +int Feb_Control_SetDynamicRange(int dr) { static unsigned int everything_but_bit_mode = DAQ_STATIC_BIT_PROGRAM | DAQ_STATIC_BIT_CHIP_TEST | DAQ_STATIC_BIT_ROTEST; - if (four_eight_sixteen_or_thirtytwo == 4) { + switch (dr) { + case 4: Feb_Control_staticBits = DAQ_STATIC_BIT_M4 | (Feb_Control_staticBits & everything_but_bit_mode); // leave test bits in currernt state Feb_Control_subFrameMode &= ~DAQ_NEXPOSURERS_ACTIVATE_AUTO_SUBIMAGING; - } else if (four_eight_sixteen_or_thirtytwo == 8) { + break; + case 8: Feb_Control_staticBits = DAQ_STATIC_BIT_M8 | (Feb_Control_staticBits & everything_but_bit_mode); Feb_Control_subFrameMode &= ~DAQ_NEXPOSURERS_ACTIVATE_AUTO_SUBIMAGING; - } else if (four_eight_sixteen_or_thirtytwo == 16) { + break; + case 12: + case 16: Feb_Control_staticBits = DAQ_STATIC_BIT_M12 | (Feb_Control_staticBits & everything_but_bit_mode); Feb_Control_subFrameMode &= ~DAQ_NEXPOSURERS_ACTIVATE_AUTO_SUBIMAGING; - } else if (four_eight_sixteen_or_thirtytwo == 32) { + + // disable 16 bit conversion if 12 bit mode (enable if 16 bit) + if (!Feb_Control_Disable16bitConversion(dr == 12)) + return 0; + break; + case 32: Feb_Control_staticBits = DAQ_STATIC_BIT_M12 | (Feb_Control_staticBits & everything_but_bit_mode); Feb_Control_subFrameMode |= DAQ_NEXPOSURERS_ACTIVATE_AUTO_SUBIMAGING; - } else { - LOG(logERROR, ("dynamic range (%d) not valid, not setting bit mode.\n", - four_eight_sixteen_or_thirtytwo)); + break; + default: + LOG(logERROR, + ("dynamic range (%d) not valid, not setting bit mode.\n", dr)); LOG(logINFO, ("Set dynamic range int must equal 4,8 16, or 32.\n")); return 0; } - LOG(logINFO, - ("Dynamic range set to %d\n", four_eight_sixteen_or_thirtytwo)); + LOG(logINFO, ("Dynamic range set to %d\n", dr)); return 1; } -unsigned int Feb_Control_GetDynamicRange() { - if (Feb_Control_subFrameMode & DAQ_NEXPOSURERS_ACTIVATE_AUTO_SUBIMAGING) - return 32; - else if (DAQ_STATIC_BIT_M4 & Feb_Control_staticBits) - return 4; - else if (DAQ_STATIC_BIT_M8 & Feb_Control_staticBits) - return 8; +int Feb_Control_GetDynamicRange(int *retval) { + if (Feb_Control_subFrameMode & DAQ_NEXPOSURERS_ACTIVATE_AUTO_SUBIMAGING) { + *retval = 32; + } else if (DAQ_STATIC_BIT_M4 & Feb_Control_staticBits) { + *retval = 4; + } else if (DAQ_STATIC_BIT_M8 & Feb_Control_staticBits) { + *retval = 8; + } else { + int disable16 = 0; + if (!Feb_Control_Get16bitConversionDisabled(&disable16)) { + LOG(logERROR, ("Could not get dynamic range (12 or 16 bit)\n")); + return 0; + } + if (disable16) { + *retval = 12; + } else { + *retval = 16; + } + } - return 16; + return 1; +} + +int Feb_Control_Disable16bitConversion(int disable) { + LOG(logINFO, ("%s 16 bit expansion\n", disable ? "Disabling" : "Enabling")); + unsigned int regval = 0; + if (!Feb_Control_ReadRegister(DAQ_REG_HRDWRE, ®val)) { + LOG(logERROR, ("Could not %s 16 bit expansion (bit mode)\n", + (disable ? "disable" : "enable"))); + return 0; + } + if (disable) { + regval |= DAQ_REG_HRDWRE_DSBL_16BIT_MSK; + } else { + regval &= ~DAQ_REG_HRDWRE_DSBL_16BIT_MSK; + } + + if (!Feb_Control_WriteRegister(DAQ_REG_HRDWRE, regval)) { + LOG(logERROR, ("Could not %s 16 bit expansion (bit mode)\n", + (disable ? "disable" : "enable"))); + return 0; + } + return 1; +} + +int Feb_Control_Get16bitConversionDisabled(int *ret) { + unsigned int regval = 0; + if (!Feb_Control_ReadRegister(DAQ_REG_HRDWRE, ®val)) { + LOG(logERROR, ("Could not get 16 bit expansion (bit mode)\n")); + return 0; + } + if (regval & DAQ_REG_HRDWRE_DSBL_16BIT_MSK) { + *ret = 1; + } else { + *ret = 0; + } + return 1; } int Feb_Control_SetReadoutSpeed(unsigned int readout_speed) { @@ -1554,7 +1620,10 @@ int Feb_Control_SetChipSignalsToTrimQuad(int enable) { regval &= ~(DAQ_REG_HRDWRE_PROGRAM_MSK | DAQ_REG_HRDWRE_M8_MSK); } - return Feb_Control_WriteRegister(DAQ_REG_HRDWRE, regval); + if (!Feb_Control_WriteRegister(DAQ_REG_HRDWRE, regval)) { + LOG(logERROR, ("Could not set chip signals to trim quad\n")); + return 0; + } } return 1; } @@ -1604,7 +1673,7 @@ int Feb_Control_WriteRegister(uint32_t offset, uint32_t data) { for (int iloop = 0; iloop < 2; ++iloop) { if (run[iloop]) { - LOG(logINFO, + LOG(logDEBUG1, ("Writing 0x%x to %s 0x%x\n", data, side[iloop], actualOffset)); if (!Feb_Interface_WriteRegister(addr[iloop], actualOffset, data, 0, 0)) { @@ -1612,6 +1681,18 @@ int Feb_Control_WriteRegister(uint32_t offset, uint32_t data) { side[iloop], actualOffset)); return 0; } + uint32_t regVal = 0; + if (!Feb_Interface_ReadRegister(addr[iloop], actualOffset, + ®Val)) { + LOG(logERROR, ("Could not read %s register\n", addr[iloop])); + return 0; + } + if (regVal != data) { + LOG(logERROR, + ("Could not write %s register. Write 0x%x, read 0x%x\n", + addr[iloop], data, regVal)); + return 0; + } } } @@ -1648,8 +1729,8 @@ int Feb_Control_ReadRegister(uint32_t offset, uint32_t *retval) { side[iloop], actualOffset)); return 0; } - LOG(logINFO, ("Read 0x%x from %s 0x%x\n", value[iloop], side[iloop], - actualOffset)); + LOG(logDEBUG1, ("Read 0x%x from %s 0x%x\n", value[iloop], + side[iloop], actualOffset)); *retval = value[iloop]; // if not the other (left, not right OR right, not left), return the // value @@ -1824,7 +1905,11 @@ int64_t Feb_Control_Get_RateTable_Period_in_nsec() { int Feb_Control_SetRateCorrectionTau(int64_t tau_in_Nsec) { // period = exptime if 16bit, period = subexptime if 32 bit - int dr = Feb_Control_GetDynamicRange(); + int dr = 0; + if (!Feb_Control_GetDynamicRange(&dr)) { + LOG(logERROR, ("Could not set rate correction tau\n")); + return 0; + } double period_in_sec = (double)(Feb_Control_GetSubFrameExposureTime()) / (double)1e9; if (dr == 16) diff --git a/slsDetectorServers/eigerDetectorServer/FebControl.h b/slsDetectorServers/eigerDetectorServer/FebControl.h index 7ede407ad..56a68024b 100644 --- a/slsDetectorServers/eigerDetectorServer/FebControl.h +++ b/slsDetectorServers/eigerDetectorServer/FebControl.h @@ -55,7 +55,7 @@ int Feb_Control_ResetChipPartially(); int Feb_Control_SendBitModeToBebServer(); unsigned int Feb_Control_ConvertTimeToRegister(float time_in_sec); int Feb_Control_PrepareForAcquisition(); -void Feb_Control_PrintAcquisitionSetup(); +int Feb_Control_PrintAcquisitionSetup(); int Feb_Control_StartAcquisition(); int Feb_Control_StopAcquisition(); int Feb_Control_IsReadyForTrigger(int *readyForTrigger); @@ -63,8 +63,10 @@ int Feb_Control_SendSoftwareTrigger(); int Feb_Control_SoftwareTrigger(int block); // parameters -int Feb_Control_SetDynamicRange(unsigned int four_eight_sixteen_or_thirtytwo); -unsigned int Feb_Control_GetDynamicRange(); +int Feb_Control_SetDynamicRange(int dr); +int Feb_Control_GetDynamicRange(int *retval); +int Feb_Control_Disable16bitConversion(int disable); +int Feb_Control_Get16bitConversionDisabled(); int Feb_Control_SetReadoutSpeed(unsigned int readout_speed); int Feb_Control_SetReadoutMode(unsigned int readout_mode); int Feb_Control_SetTriggerMode(unsigned int trigger_mode); diff --git a/slsDetectorServers/eigerDetectorServer/FebRegisterDefs.h b/slsDetectorServers/eigerDetectorServer/FebRegisterDefs.h index db2627181..1ec86f834 100644 --- a/slsDetectorServers/eigerDetectorServer/FebRegisterDefs.h +++ b/slsDetectorServers/eigerDetectorServer/FebRegisterDefs.h @@ -29,6 +29,8 @@ #define DAQ_REG_HRDWRE_OW_MASTER_MSK (0x00000001 << DAQ_REG_HRDWRE_OW_MASTER_OFST) #define DAQ_REG_HRDWRE_MASTER_OFST (4) #define DAQ_REG_HRDWRE_MASTER_MSK (0x00000001 << DAQ_REG_HRDWRE_MASTER_OFST) +#define DAQ_REG_HRDWRE_DSBL_16BIT_OFST (5) +#define DAQ_REG_HRDWRE_DSBL_16BIT_MSK (0x00000001 << DAQ_REG_HRDWRE_DSBL_16BIT_OFST) #define DAQ_REG_HRDWRE_PROGRAM_OFST (30) #define DAQ_REG_HRDWRE_PROGRAM_MSK (0x00000001 << DAQ_REG_HRDWRE_PROGRAM_OFST) #define DAQ_REG_HRDWRE_M8_OFST (31) diff --git a/slsDetectorServers/eigerDetectorServer/bin/eigerDetectorServer_developer b/slsDetectorServers/eigerDetectorServer/bin/eigerDetectorServer_developer index 8f791e4b0..e2f73123c 100755 Binary files a/slsDetectorServers/eigerDetectorServer/bin/eigerDetectorServer_developer and b/slsDetectorServers/eigerDetectorServer/bin/eigerDetectorServer_developer differ diff --git a/slsDetectorServers/eigerDetectorServer/slsDetectorFunctionList.c b/slsDetectorServers/eigerDetectorServer/slsDetectorFunctionList.c index 0955523a1..11e72443f 100644 --- a/slsDetectorServers/eigerDetectorServer/slsDetectorFunctionList.c +++ b/slsDetectorServers/eigerDetectorServer/slsDetectorFunctionList.c @@ -821,29 +821,38 @@ int readRegister(uint32_t offset, uint32_t *retval) { /* set parameters - dr, roi */ int setDynamicRange(int dr) { - // setting dr - if (dr > 0) { - LOG(logDEBUG1, ("Setting dynamic range: %d\n", dr)); -#ifndef VIRTUAL - sharedMemory_lockLocalLink(); - if (Feb_Control_SetDynamicRange(dr)) { - if (!Beb_SetUpTransferParameters(dr)) { - LOG(logERROR, ("Could not set bit mode in the back end\n")); - sharedMemory_unlockLocalLink(); - return eiger_dynamicrange; - } - } - sharedMemory_unlockLocalLink(); -#endif - eiger_dynamicrange = dr; + if (dr <= 0) { + return FAIL; } - // getting dr -#ifndef VIRTUAL +#ifdef VIRTUAL + LOG(logINFO, ("Setting dynamic range: %d\n", dr)); +#else sharedMemory_lockLocalLink(); - eiger_dynamicrange = Feb_Control_GetDynamicRange(); + if (Feb_Control_SetDynamicRange(dr)) { + if (!Beb_SetUpTransferParameters(dr)) { + LOG(logERROR, ("Could not set bit mode in the back end\n")); + sharedMemory_unlockLocalLink(); + return eiger_dynamicrange; + } + } sharedMemory_unlockLocalLink(); #endif - return eiger_dynamicrange; + eiger_dynamicrange = dr; + return OK; +} + +int getDynamicRange(int *retval) { +#ifdef VIRTUAL + *retval = eiger_dynamicrange; +#else + sharedMemory_lockLocalLink(); + if (!Feb_Control_GetDynamicRange(retval)) { + sharedMemory_unlockLocalLink(); + return FAIL; + } + sharedMemory_unlockLocalLink(); +#endif + return OK; } /* parameters - readout */ @@ -1158,6 +1167,7 @@ int setModule(sls_detector_module myMod, char *mess) { // if quad, set M8 and PROGRAM manually if (!Feb_Control_SetChipSignalsToTrimQuad(1)) { + sharedMemory_unlockLocalLink(); return FAIL; } @@ -1170,6 +1180,7 @@ int setModule(sls_detector_module myMod, char *mess) { // if quad, reset M8 and PROGRAM manually if (!Feb_Control_SetChipSignalsToTrimQuad(0)) { + sharedMemory_unlockLocalLink(); return FAIL; } @@ -1179,6 +1190,7 @@ int setModule(sls_detector_module myMod, char *mess) { // if quad, reset M8 and PROGRAM manually if (!Feb_Control_SetChipSignalsToTrimQuad(0)) { + sharedMemory_unlockLocalLink(); return FAIL; } @@ -1923,7 +1935,8 @@ int setRateCorrection( else if (custom_tau_in_nsec == -1) custom_tau_in_nsec = Feb_Control_Get_RateTable_Tau_in_nsec(); - int dr = Feb_Control_GetDynamicRange(); + int dr = eiger_dynamicrange; + // get period = subexptime if 32bit , else period = exptime if 16 bit int64_t actual_period = Feb_Control_GetSubFrameExposureTime(); // already in nsec @@ -2321,7 +2334,7 @@ void *start_timer(void *arg) { const int maxRows = MAX_ROWS_PER_READOUT; const int packetsPerFrame = (maxPacketsPerFrame * readNRows) / maxRows; - LOG(logDEBUG1, + LOG(logDEBUG, (" dr:%d\n bytesperpixel:%f\n tgenable:%d\n datasize:%d\n " "packetsize:%d\n maxnumpackes:%d\n npixelsx:%d\n databytes:%d\n", dr, bytesPerPixel, tgEnable, datasize, packetsize, maxPacketsPerFrame, @@ -2338,11 +2351,13 @@ void *start_timer(void *arg) { npixels /= 2; } LOG(logDEBUG1, - ("pixels:%d pixelsperpacket:%d\n", npixels, pixelsPerPacket)); + ("npixels:%d pixelsperpacket:%d\n", npixels, pixelsPerPacket)); + uint8_t *src = (uint8_t *)imageData; for (int i = 0; i < npixels; ++i) { if (i > 0 && i % pixelsPerPacket == 0) { ++pixelVal; } + switch (dr) { case 4: *((uint8_t *)(imageData + i)) = @@ -2357,6 +2372,30 @@ void *start_timer(void *arg) { *((uint8_t *)(imageData + i)) = eiger_virtual_test_mode ? 0xFE : (uint8_t)pixelVal; break; + case 12: + if (eiger_virtual_test_mode) { + // first 12 bit pixel + // first 8 byte + *src++ = 0xFE; + // second 12bit pixel + ++i; + // second 8 byte + *src++ = 0xEF; + // third byte + *src++ = 0xFF; + } else { + // first 12 bit pixel + // first 8 byte + *src++ = (uint8_t)(i & 0xFF); + // second 8 byte (first nibble) + *src = (uint8_t)((i++ >> 8u) & 0xF); + // second 12bit pixel + // second 8 byte (second nibble) + *src++ |= ((uint8_t)(i & 0xF) << 4u); + // third byte + *src++ = (uint8_t)((i >> 4u) & 0xFF); + } + break; case 16: *((uint16_t *)(imageData + i * sizeof(uint16_t))) = eiger_virtual_test_mode ? 0xFFE : (uint16_t)pixelVal; @@ -2433,9 +2472,27 @@ void *start_timer(void *arg) { // fill data int dstOffset = sizeof(sls_detector_header); int dstOffset2 = sizeof(sls_detector_header); - { - for (int psize = 0; psize < datasize; psize += npixelsx) { + if (dr == 12) { + // multiple of 768,1024,4096 + int copysize = 256; + for (int psize = 0; psize < datasize; psize += copysize) { + memcpy(packetData + dstOffset, imageData + srcOffset, + copysize); + memcpy(packetData2 + dstOffset2, imageData + srcOffset2, + copysize); + srcOffset += copysize; + srcOffset2 += copysize; + dstOffset += copysize; + dstOffset2 += copysize; + // reached 1 row (quarter module) + if ((srcOffset % npixelsx) == 0) { + srcOffset += npixelsx; + srcOffset2 += npixelsx; + } + } + } else { + for (int psize = 0; psize < datasize; psize += npixelsx) { if (dr == 32 && tgEnable == 0) { memcpy(packetData + dstOffset, imageData + srcOffset, npixelsx / 2); @@ -2733,9 +2790,9 @@ int copyModule(sls_detector_module *destMod, sls_detector_module *srcMod) { int calculateDataBytes() { if (send_to_ten_gig) - return setDynamicRange(-1) * ONE_GIGA_CONSTANT * TEN_GIGA_BUFFER_SIZE; + return eiger_dynamicrange * ONE_GIGA_CONSTANT * TEN_GIGA_BUFFER_SIZE; else - return setDynamicRange(-1) * TEN_GIGA_CONSTANT * ONE_GIGA_BUFFER_SIZE; + return eiger_dynamicrange * TEN_GIGA_CONSTANT * ONE_GIGA_BUFFER_SIZE; } int getTotalNumberOfChannels() { diff --git a/slsDetectorServers/eigerDetectorServer/slsDetectorServer_defs.h b/slsDetectorServers/eigerDetectorServer/slsDetectorServer_defs.h index 95a1590b1..cca94c3fd 100644 --- a/slsDetectorServers/eigerDetectorServer/slsDetectorServer_defs.h +++ b/slsDetectorServers/eigerDetectorServer/slsDetectorServer_defs.h @@ -5,7 +5,7 @@ #define LINKED_SERVER_NAME "eigerDetectorServer" -#define REQUIRED_FIRMWARE_VERSION (29) +#define REQUIRED_FIRMWARE_VERSION (30) // virtual ones renamed for consistency // real ones keep previous name for compatibility (already in production) #ifdef VIRTUAL diff --git a/slsDetectorServers/gotthard2DetectorServer/bin/gotthard2DetectorServer_developer b/slsDetectorServers/gotthard2DetectorServer/bin/gotthard2DetectorServer_developer index c107dc4e9..b3ebdf0cc 100755 Binary files a/slsDetectorServers/gotthard2DetectorServer/bin/gotthard2DetectorServer_developer and b/slsDetectorServers/gotthard2DetectorServer/bin/gotthard2DetectorServer_developer differ diff --git a/slsDetectorServers/gotthard2DetectorServer/slsDetectorFunctionList.c b/slsDetectorServers/gotthard2DetectorServer/slsDetectorFunctionList.c index da7576ef8..0816cfa05 100644 --- a/slsDetectorServers/gotthard2DetectorServer/slsDetectorFunctionList.c +++ b/slsDetectorServers/gotthard2DetectorServer/slsDetectorFunctionList.c @@ -952,7 +952,16 @@ void resetPeripheral() { /* set parameters - dr, roi */ -int setDynamicRange(int dr) { return DYNAMIC_RANGE; } +int setDynamicRange(int dr) { + if (dr == 16) + return OK; + return FAIL; +} + +int getDynamicRange(int *retval) { + *retval = DYNAMIC_RANGE; + return OK; +} /* parameters - timer */ void setNumFrames(int64_t val) { diff --git a/slsDetectorServers/gotthardDetectorServer/bin/gotthardDetectorServer_developer b/slsDetectorServers/gotthardDetectorServer/bin/gotthardDetectorServer_developer index 2c7fa59a7..3e8b3eecf 100755 Binary files a/slsDetectorServers/gotthardDetectorServer/bin/gotthardDetectorServer_developer and b/slsDetectorServers/gotthardDetectorServer/bin/gotthardDetectorServer_developer differ diff --git a/slsDetectorServers/gotthardDetectorServer/slsDetectorFunctionList.c b/slsDetectorServers/gotthardDetectorServer/slsDetectorFunctionList.c index 362bf2079..ca415eeba 100644 --- a/slsDetectorServers/gotthardDetectorServer/slsDetectorFunctionList.c +++ b/slsDetectorServers/gotthardDetectorServer/slsDetectorFunctionList.c @@ -788,7 +788,16 @@ void setMasterSlaveConfiguration() { /* set parameters - dr, roi */ -int setDynamicRange(int dr) { return DYNAMIC_RANGE; } +int setDynamicRange(int dr) { + if (dr == 16) + return OK; + return FAIL; +} + +int getDynamicRange(int *retval) { + *retval = DYNAMIC_RANGE; + return OK; +} int setROI(ROI arg) { diff --git a/slsDetectorServers/jungfrauDetectorServer/bin/jungfrauDetectorServer_developer b/slsDetectorServers/jungfrauDetectorServer/bin/jungfrauDetectorServer_developer index 7c35d3cb0..eec1da2d9 100755 Binary files a/slsDetectorServers/jungfrauDetectorServer/bin/jungfrauDetectorServer_developer and b/slsDetectorServers/jungfrauDetectorServer/bin/jungfrauDetectorServer_developer differ diff --git a/slsDetectorServers/jungfrauDetectorServer/slsDetectorFunctionList.c b/slsDetectorServers/jungfrauDetectorServer/slsDetectorFunctionList.c index dc8e1ea28..4a8bebcfd 100644 --- a/slsDetectorServers/jungfrauDetectorServer/slsDetectorFunctionList.c +++ b/slsDetectorServers/jungfrauDetectorServer/slsDetectorFunctionList.c @@ -796,7 +796,16 @@ void resetPeripheral() { /* set parameters - dr, roi */ -int setDynamicRange(int dr) { return DYNAMIC_RANGE; } +int setDynamicRange(int dr) { + if (dr == 16) + return OK; + return FAIL; +} + +int getDynamicRange(int *retval) { + *retval = DYNAMIC_RANGE; + return OK; +} void setADCInvertRegister(uint32_t val) { LOG(logINFO, ("Setting ADC Port Invert Reg to 0x%x\n", val)); diff --git a/slsDetectorServers/moenchDetectorServer/bin/moenchDetectorServer_developer b/slsDetectorServers/moenchDetectorServer/bin/moenchDetectorServer_developer index c3e6c2e41..8c99f07dc 100755 Binary files a/slsDetectorServers/moenchDetectorServer/bin/moenchDetectorServer_developer and b/slsDetectorServers/moenchDetectorServer/bin/moenchDetectorServer_developer differ diff --git a/slsDetectorServers/moenchDetectorServer/slsDetectorFunctionList.c b/slsDetectorServers/moenchDetectorServer/slsDetectorFunctionList.c index 05bd7e62d..1bf765a99 100644 --- a/slsDetectorServers/moenchDetectorServer/slsDetectorFunctionList.c +++ b/slsDetectorServers/moenchDetectorServer/slsDetectorFunctionList.c @@ -706,7 +706,16 @@ void resetPeripheral() { /* set parameters - dr, adcenablemask */ -int setDynamicRange(int dr) { return DYNAMIC_RANGE; } +int setDynamicRange(int dr) { + if (dr == 16) + return OK; + return FAIL; +} + +int getDynamicRange(int *retval) { + *retval = DYNAMIC_RANGE; + return OK; +} int setADCEnableMask(uint32_t mask) { if (mask == 0u) { diff --git a/slsDetectorServers/mythen3DetectorServer/bin/mythen3DetectorServer_developer b/slsDetectorServers/mythen3DetectorServer/bin/mythen3DetectorServer_developer index 4b4c158f1..046003d62 100755 Binary files a/slsDetectorServers/mythen3DetectorServer/bin/mythen3DetectorServer_developer and b/slsDetectorServers/mythen3DetectorServer/bin/mythen3DetectorServer_developer differ diff --git a/slsDetectorServers/mythen3DetectorServer/slsDetectorFunctionList.c b/slsDetectorServers/mythen3DetectorServer/slsDetectorFunctionList.c index f4b40499e..9179549fb 100644 --- a/slsDetectorServers/mythen3DetectorServer/slsDetectorFunctionList.c +++ b/slsDetectorServers/mythen3DetectorServer/slsDetectorFunctionList.c @@ -729,46 +729,54 @@ void resetPeripheral() { /* set parameters - dr, roi */ int setDynamicRange(int dr) { - if (dr > 0) { - uint32_t regval = 0; - switch (dr) { - /*case 1: TODO:Not implemented in firmware yet - regval = CONFIG_DYNAMIC_RANGE_1_VAL; - break;*/ - case 8: - regval = CONFIG_DYNAMIC_RANGE_8_VAL; - break; - case 16: - regval = CONFIG_DYNAMIC_RANGE_16_VAL; - break; - case 32: - regval = CONFIG_DYNAMIC_RANGE_24_VAL; - break; - default: - LOG(logERROR, ("Invalid dynamic range %d\n", dr)); - return -1; - } - // set it - bus_w(CONFIG_REG, bus_r(CONFIG_REG) & ~CONFIG_DYNAMIC_RANGE_MSK); - bus_w(CONFIG_REG, bus_r(CONFIG_REG) | regval); - updatePacketizing(); + if (dr <= 0) { + return FAIL; } + uint32_t regval = 0; + switch (dr) { + /*case 1: TODO:Not implemented in firmware yet + regval = CONFIG_DYNAMIC_RANGE_1_VAL; + break;*/ + case 8: + regval = CONFIG_DYNAMIC_RANGE_8_VAL; + break; + case 16: + regval = CONFIG_DYNAMIC_RANGE_16_VAL; + break; + case 32: + regval = CONFIG_DYNAMIC_RANGE_24_VAL; + break; + default: + LOG(logERROR, ("Invalid dynamic range %d\n", dr)); + return -1; + } + // set it + bus_w(CONFIG_REG, bus_r(CONFIG_REG) & ~CONFIG_DYNAMIC_RANGE_MSK); + bus_w(CONFIG_REG, bus_r(CONFIG_REG) | regval); + updatePacketizing(); + return OK; +} +int getDynamicRange(int *retval) { uint32_t regval = bus_r(CONFIG_REG) & CONFIG_DYNAMIC_RANGE_MSK; switch (regval) { /*case CONFIG_DYNAMIC_RANGE_1_VAL: TODO:Not implemented in firmware yet return 1;*/ case CONFIG_DYNAMIC_RANGE_8_VAL: - return 8; + *retval = 8; + break; case CONFIG_DYNAMIC_RANGE_16_VAL: - return 16; + *retval = 16; + break; case CONFIG_DYNAMIC_RANGE_24_VAL: - return 32; + *retval = 32; + break; default: LOG(logERROR, ("Invalid dynamic range %d read back\n", regval >> CONFIG_DYNAMIC_RANGE_OFST)); - return -1; + return FAIL; } + return OK; } /* set parameters - readout */ @@ -1091,7 +1099,8 @@ void updatePacketizing() { // 10g if (tgEnable) { - const int dr = setDynamicRange(-1); + int dr = 0; + getDynamicRange(&dr); packetsPerFrame = 1; if (dr == 32 && ncounters > 1) { packetsPerFrame = 2; @@ -2202,7 +2211,8 @@ void *start_timer(void *arg) { const int imageSize = calculateDataBytes(); const int tgEnable = enableTenGigabitEthernet(-1); - const int dr = setDynamicRange(-1); + int dr = 0; + getDynamicRange(&dr); int ncounters = __builtin_popcount(getCounterMask()); int dataSize = 0; int packetsPerFrame = 0; @@ -2523,7 +2533,8 @@ int copyModule(sls_detector_module *destMod, sls_detector_module *srcMod) { int calculateDataBytes() { int numCounters = __builtin_popcount(getCounterMask()); - int dr = setDynamicRange(-1); + int dr = 0; + getDynamicRange(&dr); return (NCHAN_1_COUNTER * NCHIP * numCounters * ((double)dr / 8.00)); } diff --git a/slsDetectorServers/slsDetectorServer/include/slsDetectorFunctionList.h b/slsDetectorServers/slsDetectorServer/include/slsDetectorFunctionList.h index 955f35e6b..efc671d39 100644 --- a/slsDetectorServers/slsDetectorServer/include/slsDetectorFunctionList.h +++ b/slsDetectorServers/slsDetectorServer/include/slsDetectorFunctionList.h @@ -173,6 +173,7 @@ void setMasterSlaveConfiguration(); // parameters - dr, roi int setDynamicRange(int dr); +int getDynamicRange(int *retval); #ifdef GOTTHARDD int setROI(ROI arg); ROI getROI(); diff --git a/slsDetectorServers/slsDetectorServer/src/slsDetectorServer_funcs.c b/slsDetectorServers/slsDetectorServer/src/slsDetectorServer_funcs.c index f94b2345a..956591314 100644 --- a/slsDetectorServers/slsDetectorServer/src/slsDetectorServer_funcs.c +++ b/slsDetectorServers/slsDetectorServer/src/slsDetectorServer_funcs.c @@ -2815,6 +2815,9 @@ int set_dynamic_range(int file_des) { #endif #if defined(EIGERD) || defined(MYTHEN3D) case 8: +#ifdef EIGERD + case 12: +#endif case 16: case 32: #endif @@ -2822,14 +2825,25 @@ int set_dynamic_range(int file_des) { defined(MOENCHD) || defined(GOTTHARD2D) case 16: #endif - retval = setDynamicRange(dr); - LOG(logDEBUG1, ("Dynamic range: %d\n", retval)); - if (retval == -1) { - ret = FAIL; - sprintf(mess, "Could not get dynamic range.\n"); - LOG(logERROR, (mess)); + if (dr >= 0) { + ret = setDynamicRange(dr); + if (ret == FAIL) { + sprintf(mess, "Could not set dynamic range to %d\n", dr); + LOG(logERROR, (mess)); + } + } + + // get + if (ret == OK) { + ret = getDynamicRange(&retval); + if (ret == FAIL) { + strcpy(mess, "Could not get dynamic range\n"); + LOG(logERROR, (mess)); + } else { + LOG(logDEBUG1, ("Dynamic range: %d\n", retval)); + validate(&ret, mess, dr, retval, "set dynamic range", DEC); + } } - validate(&ret, mess, dr, retval, "set dynamic range", DEC); break; default: modeNotImplemented("Dynamic range", dr); @@ -4650,11 +4664,17 @@ int set_read_n_rows(int file_des) { LOG(logERROR, (mess)); } else { #ifdef EIGERD - int dr = setDynamicRange(GET_FLAG); + int dr = 0; + ret = getDynamicRange(&dr); int isTenGiga = enableTenGigabitEthernet(GET_FLAG); unsigned int maxnl = MAX_ROWS_PER_READOUT; unsigned int maxnp = (isTenGiga ? 4 : 16) * dr; - if ((arg * maxnp) % maxnl) { + // get dr fail + if (ret == FAIL) { + strcpy(mess, + "Could not read n rows (failed to get dynamic range)\n"); + LOG(logERROR, (mess)); + } else if ((arg * maxnp) % maxnl) { ret = FAIL; sprintf(mess, "Could not set number of rows to %d. For %d bit " @@ -4862,6 +4882,7 @@ int is_udp_configured() { LOG(logWARNING, ("%s", configureMessage)); return FAIL; } + // virtual: no check (can be eth name: lo, ip: 127.0.0.1) #ifndef VIRTUAL if (udpDetails[i].dstmac == 0) { sprintf(configureMessage, @@ -7111,7 +7132,10 @@ int get_receiver_parameters(int file_des) { } // dynamic range - i32 = setDynamicRange(GET_FLAG); + ret = getDynamicRange(&i32); + if (ret == FAIL) { + i32 = 0; + } n += sendData(file_des, &i32, sizeof(i32), INT32); if (n < 0) return printSocketReadError(); diff --git a/slsDetectorSoftware/include/sls/Detector.h b/slsDetectorSoftware/include/sls/Detector.h index ba10ac797..c7e091dbc 100644 --- a/slsDetectorSoftware/include/sls/Detector.h +++ b/slsDetectorSoftware/include/sls/Detector.h @@ -284,7 +284,7 @@ class Detector { Result getDynamicRange(Positions pos = {}) const; /** - * [Eiger] Options: 4, 8, 16, 32. If i is 32, also sets clkdivider to 2, + * [Eiger] Options: 4, 8, 12, 16, 32. If i is 32, also sets clkdivider to 2, * else sets clkdivider to 1 \n [Mythen3] Options: 8, 16, 32 \n * [Jungfrau][Gotthard][Ctb][Moench][Mythen3][Gotthard2] 16 */ diff --git a/slsDetectorSoftware/src/CmdProxy.h b/slsDetectorSoftware/src/CmdProxy.h index b0c8ee303..95155b1b2 100644 --- a/slsDetectorSoftware/src/CmdProxy.h +++ b/slsDetectorSoftware/src/CmdProxy.h @@ -1109,7 +1109,6 @@ class CmdProxy { /* acquisition parameters */ std::string Acquire(int action); std::string Exptime(int action); - std::string DynamicRange(int action); std::string ReadoutSpeed(int action); std::string Adcphase(int action); std::string Dbitphase(int action); @@ -1328,7 +1327,7 @@ class CmdProxy { dr, getDynamicRange, setDynamicRange, StringTo, "[value]\n\tDynamic Range or number of bits per " "pixel in detector.\n\t" - "[Eiger] Options: 4, 8, 16, 32. If set to 32, also sets " + "[Eiger] Options: 4, 8, 12, 16, 32. If set to 32, also sets " "clkdivider to 2, else to 0.\n\t" "[Mythen3] Options: 8, 16, 32\n\t" "[Jungfrau][Gotthard][Ctb][Moench][Mythen3][Gotthard2] 16"); diff --git a/slsDetectorSoftware/src/Detector.cpp b/slsDetectorSoftware/src/Detector.cpp index 025370bf7..74337c281 100644 --- a/slsDetectorSoftware/src/Detector.cpp +++ b/slsDetectorSoftware/src/Detector.cpp @@ -387,7 +387,7 @@ void Detector::setDynamicRange(int value) { std::vector Detector::getDynamicRangeList() const { switch (getDetectorType().squash()) { case defs::EIGER: - return std::vector{4, 8, 16, 32}; + return std::vector{4, 8, 12, 16, 32}; case defs::MYTHEN3: return std::vector{8, 16, 32}; default: diff --git a/slsReceiverSoftware/src/ClientInterface.cpp b/slsReceiverSoftware/src/ClientInterface.cpp index 9fa919359..5c3e8af36 100644 --- a/slsReceiverSoftware/src/ClientInterface.cpp +++ b/slsReceiverSoftware/src/ClientInterface.cpp @@ -716,6 +716,7 @@ int ClientInterface::set_dynamic_range(Interface &socket) { break; */ case 4: + case 12: if (detType == EIGER) { exists = true; } diff --git a/slsReceiverSoftware/src/HDF5DataFile.cpp b/slsReceiverSoftware/src/HDF5DataFile.cpp index 758d70d7b..0ffe0d525 100644 --- a/slsReceiverSoftware/src/HDF5DataFile.cpp +++ b/slsReceiverSoftware/src/HDF5DataFile.cpp @@ -112,6 +112,7 @@ void HDF5DataFile::CreateFirstHDF5DataFile( udpPortNumber_ = udpPortNumber; switch (dynamicRange_) { + case 12: case 16: dataType_ = PredType::STD_U16LE; break; @@ -248,8 +249,30 @@ void HDF5DataFile::WriteToFile(char *buffer, const int buffersize, WriteParameterDatasets(currentFrameNumber, (sls_receiver_header *)(buffer)); } +void HDF5DataFile::Convert12to16Bit(uint16_t *dst, uint8_t *src) { + for (int i = 0; i < EIGER_NUM_PIXELS; ++i) { + *dst = (uint16_t)(*src++ & 0xFF); + *dst++ |= (uint16_t)((*src & 0xF) << 8u); + ++i; + *dst = (uint16_t)((*src++ & 0xF0) >> 4u); + *dst++ |= (uint16_t)((*src++ & 0xFF) << 4u); + } +} + void HDF5DataFile::WriteDataFile(const uint64_t currentFrameNumber, char *buffer) { + // expand 12 bit to 16 bits + char *revBuffer = buffer; + if (dynamicRange_ == 12) { + revBuffer = (char *)malloc(EIGER_16_BIT_IMAGE_SIZE); + if (revBuffer == nullptr) { + throw sls::RuntimeError("Could not allocate memory for 12 bit to " + "16 bit conversion in object " + + std::to_string(index_)); + } + Convert12to16Bit((uint16_t *)revBuffer, (uint8_t *)buffer); + } + std::lock_guard lock(*hdf5Lib_); uint64_t nDimx = @@ -266,9 +289,15 @@ void HDF5DataFile::WriteDataFile(const uint64_t currentFrameNumber, dataSpace_->selectHyperslab(H5S_SELECT_SET, count, start); DataSpace memspace(2, dims2); - dataSet_->write(buffer, dataType_, memspace, *dataSpace_); + dataSet_->write(revBuffer, dataType_, memspace, *dataSpace_); memspace.close(); + if (dynamicRange_ == 12) { + free(revBuffer); + } } catch (const Exception &error) { + if (dynamicRange_ == 12) { + free(revBuffer); + } LOG(logERROR) << "Could not write to file in object " << index_; error.printErrorStack(); throw sls::RuntimeError("Could not write to file in object " + diff --git a/slsReceiverSoftware/src/HDF5DataFile.h b/slsReceiverSoftware/src/HDF5DataFile.h index a2e2aa78a..dc1c2ae5e 100644 --- a/slsReceiverSoftware/src/HDF5DataFile.h +++ b/slsReceiverSoftware/src/HDF5DataFile.h @@ -35,6 +35,7 @@ class HDF5DataFile : private virtual slsDetectorDefs, public File { private: void CreateFile(); + void Convert12to16Bit(uint16_t *dst, uint8_t *src); void WriteDataFile(const uint64_t currentFrameNumber, char *buffer); void WriteParameterDatasets(const uint64_t currentFrameNumber, sls_receiver_header *rheader); @@ -72,4 +73,7 @@ class HDF5DataFile : private virtual slsDetectorDefs, public File { int detIndex_{0}; int numUnitsPerReadout_{0}; uint32_t udpPortNumber_{0}; + + static const int EIGER_NUM_PIXELS{256 * 2 * 256}; + static const int EIGER_16_BIT_IMAGE_SIZE{EIGER_NUM_PIXELS * 2}; }; \ No newline at end of file