diff --git a/slsDetectorGui/forms/form_cloneplot.ui b/slsDetectorGui/forms/form_cloneplot.ui index 0965e65f2..5184ce500 100644 --- a/slsDetectorGui/forms/form_cloneplot.ui +++ b/slsDetectorGui/forms/form_cloneplot.ui @@ -55,6 +55,149 @@ + + + + 0 + 0 + + + + + 40 + 0 + + + + + 16777215 + 16777215 + + + + + + + + + 0 + 150 + 110 + + + + + + + + + 0 + 150 + 110 + + + + + + + + + 139 + 142 + 142 + + + + + + + + Complete Image + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 40 + 0 + + + + + 16777215 + 16777215 + + + + + + + + + 255 + 0 + 0 + + + + + + + + + 255 + 0 + 0 + + + + + + + + + 139 + 142 + 142 + + + + + + + + Missing Packets + + + Qt::AlignCenter + + + + + + + Qt::Horizontal + + + + 117 + 20 + + + + + @@ -241,7 +384,7 @@ 0 0 376 - 28 + 27 diff --git a/slsDetectorGui/forms/form_plot.ui b/slsDetectorGui/forms/form_plot.ui index 56247f700..d01b1dbdd 100644 --- a/slsDetectorGui/forms/form_plot.ui +++ b/slsDetectorGui/forms/form_plot.ui @@ -19,47 +19,8 @@ Form - - - 6 - - - 0 - - - - - - 0 - 0 - - - - - Sans Serif - 10 - - - - Sample Plot - - - Qt::AlignCenter - - - false - - - - 9 - - - 0 - - - - - + + @@ -86,73 +47,6 @@ 0 - - - - - 0 - 0 - - - - - 40 - 0 - - - - - 40 - 16777215 - - - - Sum: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - 0 - 0 - - - - - - - - - - - - - 0 - 0 - - - - - - - - @@ -181,8 +75,8 @@ - - + + 0 @@ -194,6 +88,19 @@ + + + + Qt::Horizontal + + + + 40 + 20 + + + + @@ -222,6 +129,32 @@ + + + + + 0 + 0 + + + + - + + + + + + + + 0 + 0 + + + + - + + + @@ -235,9 +168,213 @@ + + + + + 0 + 0 + + + + + 40 + 0 + + + + + 40 + 16777215 + + + + Sum: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Qt::Horizontal + + + + 419 + 20 + + + + + + + + + 0 + 0 + + + + + Sans Serif + 10 + + + + Sample Plot + + + Qt::AlignCenter + + + true + + + + 9 + + + 0 + + + + + + + + + 0 + 0 + + + + + 40 + 0 + + + + + 16777215 + 16777215 + + + + + + + + + 255 + 0 + 0 + + + + + + + + + 255 + 0 + 0 + + + + + + + + + 139 + 142 + 142 + + + + + + + + Missing Packets + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 40 + 0 + + + + + 16777215 + 16777215 + + + + + + + + + 0 + 150 + 110 + + + + + + + + + 0 + 150 + 110 + + + + + + + + + 139 + 142 + 142 + + + + + + + + Complete Image + + + Qt::AlignCenter + + + diff --git a/slsDetectorGui/include/qCloneWidget.h b/slsDetectorGui/include/qCloneWidget.h index f7f000fb6..831ac33e4 100644 --- a/slsDetectorGui/include/qCloneWidget.h +++ b/slsDetectorGui/include/qCloneWidget.h @@ -14,7 +14,7 @@ class qCloneWidget : public QMainWindow, private Ui::ClonePlotObject { qCloneWidget(QWidget *parent, SlsQt1DPlot *p1, SlsQt2DPlot *p2, SlsQt1DPlot *gp1, SlsQt2DPlot *gp, QString title, QString filePath, QString fileName, int64_t aIndex, - bool displayStats, QString min, QString max, QString sum); + bool displayStats, QString min, QString max, QString sum, bool completeImage); ~qCloneWidget(); diff --git a/slsDetectorGui/include/qDrawPlot.h b/slsDetectorGui/include/qDrawPlot.h index 1699c574a..b3898494a 100644 --- a/slsDetectorGui/include/qDrawPlot.h +++ b/slsDetectorGui/include/qDrawPlot.h @@ -114,6 +114,7 @@ class qDrawPlot : public QWidget, private Ui::PlotObject { QString zTitle2d{"Intensity"}; QString plotTitle{""}; QString indexTitle{""}; + bool completeImage{false}; bool xyRangeChanged{false}; double xyRange[4]{0, 0, 0, 0}; bool isXYRange[4]{false, false, false, false}; diff --git a/slsDetectorGui/src/qCloneWidget.cpp b/slsDetectorGui/src/qCloneWidget.cpp index 6789c3092..42b80439e 100644 --- a/slsDetectorGui/src/qCloneWidget.cpp +++ b/slsDetectorGui/src/qCloneWidget.cpp @@ -15,13 +15,20 @@ qCloneWidget::qCloneWidget(QWidget *parent, SlsQt1DPlot *p1, SlsQt2DPlot *p2, SlsQt1DPlot *gp1, SlsQt2DPlot *gp, QString title, QString fPath, QString fName, int64_t aIndex, bool displayStats, QString min, QString max, - QString sum) + QString sum, bool completeImage) : QMainWindow(parent), plot1d(p1), plot2d(p2), gainplot1d(gp1), gainplot2d(gp), filePath(fPath), fileName(fName), acqIndex(aIndex) { setupUi(this); id = qCloneWidget::NumClones++; SetupWidgetWindow(title); DisplayStats(displayStats, min, max, sum); + lblCompleteImage->hide(); + lblInCompleteImage->hide(); + if (completeImage) { + lblCompleteImage->show(); + } else { + lblInCompleteImage->show(); + } } qCloneWidget::~qCloneWidget() { diff --git a/slsDetectorGui/src/qDrawPlot.cpp b/slsDetectorGui/src/qDrawPlot.cpp index 3e79ba211..39103d78f 100644 --- a/slsDetectorGui/src/qDrawPlot.cpp +++ b/slsDetectorGui/src/qDrawPlot.cpp @@ -97,27 +97,13 @@ void qDrawPlot::SetupPlots() { slsDetectorDefs::xy res = det->getDetectorSize(); nPixelsX = res.x; nPixelsY = res.y; - switch (detType) { - case slsDetectorDefs::EIGER: - try { - if (det->getQuad().tsquash("Inconsistent values for quad type")) { - nPixelsX /= 2; - nPixelsY *= 2; - if (nPixelsX != nPixelsY) { - --nPixelsX; - } - } - } - CATCH_DISPLAY("Could not get quad.", "qDrawPlot::SetupPlots") - break; - default: - break; - } LOG(logINFO) << "nPixelsX:" << nPixelsX; LOG(logINFO) << "nPixelsY:" << nPixelsY; boxPlot->setFont(QFont("Sans Serif", qDefs::Q_FONT_SIZE, QFont::Normal)); widgetStatistics->hide(); + lblCompleteImage->hide(); + lblInCompleteImage->hide(); // setup 1d data @@ -586,7 +572,7 @@ void qDrawPlot::ClonePlot() { clonegainplot2D, boxPlot->title(), fileSavePath, fileSaveName, currentAcqIndex, displayStatistics, lblMinDisp->text(), lblMaxDisp->text(), - lblSumDisp->text()); + lblSumDisp->text(), completeImage); } void qDrawPlot::SavePlot() { @@ -756,6 +742,7 @@ void qDrawPlot::GetData(detectorData *data, uint64_t frameIndex, << " \t dynamic range: " << data->dynamicRange << std::endl << " \t file index: " << data->fileIndex << std::endl + << " \t complete image: " << data->completeImage << std::endl << " ]"; progress = (int)data->progressIndex; @@ -776,6 +763,11 @@ void qDrawPlot::GetData(detectorData *data, uint64_t frameIndex, delete[] data2d; data2d = new double[nPixelsY * nPixelsX]; std::fill(data2d, data2d + nPixelsX * nPixelsY, 0); + if (gainData) { + delete[] gainData; + gainData = new double[nPixelsY * nPixelsX]; + std::fill(gainData, gainData + nPixelsX * nPixelsY, 0); + } } // convert data to double @@ -798,6 +790,7 @@ void qDrawPlot::GetData(detectorData *data, uint64_t frameIndex, if ((int)subFrameIndex != -1) { indexTitle = QString("%1 %2").arg(frameIndex, subFrameIndex); } + completeImage = data->completeImage; // reset pedestal if (resetPedestal) { @@ -1118,6 +1111,16 @@ void qDrawPlot::UpdatePlot() { LOG(logDEBUG) << "Update Plot"; boxPlot->setTitle(plotTitle); + + // notify of incomplete images + lblCompleteImage->hide(); + lblInCompleteImage->hide(); + if(completeImage) { + lblCompleteImage->show(); + } else { + lblInCompleteImage->show(); + } + if (is1d) { Update1dPlot(); } else { diff --git a/slsDetectorGui/src/qTabPlot.cpp b/slsDetectorGui/src/qTabPlot.cpp index a9802f4bf..216f3cfe3 100644 --- a/slsDetectorGui/src/qTabPlot.cpp +++ b/slsDetectorGui/src/qTabPlot.cpp @@ -64,6 +64,7 @@ void qTabPlot::SetupWidgetWindow() { chkGapPixels->setEnabled(true); break; case slsDetectorDefs::JUNGFRAU: + chkGapPixels->setEnabled(true); chkGainPlot->setEnabled(true); chkGainPlot->setChecked(true); plot->EnableGainPlot(true); @@ -312,8 +313,7 @@ void qTabPlot::GetGapPixels() { disconnect(chkGapPixels, SIGNAL(toggled(bool)), this, SLOT(SetGapPixels(bool))); try { - auto retval = det->getRxAddGapPixels().tsquash( - "Inconsistent gap pixels enabled for all detectors."); + auto retval = det->getGapPixelsinCallback(); chkGapPixels->setChecked(retval); } CATCH_DISPLAY("Could not get gap pixels enable.", "qTabPlot::GetGapPixels") @@ -324,7 +324,7 @@ void qTabPlot::GetGapPixels() { void qTabPlot::SetGapPixels(bool enable) { LOG(logINFO) << "Setting Gap Pixels Enable to " << enable; try { - det->setRxAddGapPixels(enable); + det->setGapPixelsinCallback(enable); } CATCH_HANDLE("Could not set gap pixels enable.", "qTabPlot::SetGapPixels", this, &qTabPlot::GetGapPixels) @@ -672,6 +672,8 @@ void qTabPlot::Refresh() { break; case slsDetectorDefs::JUNGFRAU: chkGainPlot->setEnabled(true); + chkGapPixels->setEnabled(true); + GetGapPixels(); break; case slsDetectorDefs::GOTTHARD2: chkGainPlot1D->setEnabled(true); diff --git a/slsDetectorServers/ctbDetectorServer/bin/ctbDetectorServer_developer b/slsDetectorServers/ctbDetectorServer/bin/ctbDetectorServer_developer index e655906b9..cde789563 100755 Binary files a/slsDetectorServers/ctbDetectorServer/bin/ctbDetectorServer_developer and b/slsDetectorServers/ctbDetectorServer/bin/ctbDetectorServer_developer differ diff --git a/slsDetectorServers/eigerDetectorServer/CMakeLists.txt b/slsDetectorServers/eigerDetectorServer/CMakeLists.txt index d27f38252..912f21bbf 100644 --- a/slsDetectorServers/eigerDetectorServer/CMakeLists.txt +++ b/slsDetectorServers/eigerDetectorServer/CMakeLists.txt @@ -22,7 +22,7 @@ target_include_directories(eigerDetectorServerMaster_virtual target_compile_definitions(eigerDetectorServerMaster_virtual PUBLIC EIGERD PCCOMPILE STOP_SERVER - PUBLIC VIRTUAL DVIRTUAL_9M + PUBLIC VIRTUAL #VIRTUAL_9M PUBLIC VIRTUAL_MASTER ) @@ -38,27 +38,60 @@ install(TARGETS eigerDetectorServerMaster_virtual RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} ) -add_executable(eigerDetectorServerSlave_virtual + + + + +add_executable(eigerDetectorServerSlaveTop_virtual ${src} ) -target_include_directories(eigerDetectorServerSlave_virtual +target_include_directories(eigerDetectorServerSlaveTop_virtual PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} ) -target_compile_definitions(eigerDetectorServerSlave_virtual +target_compile_definitions(eigerDetectorServerSlaveTop_virtual PUBLIC EIGERD PCCOMPILE STOP_SERVER - PUBLIC VIRTUAL DVIRTUAL_9M + PUBLIC VIRTUAL #VIRTUAL_9M + PUBLIC VIRTUAL_TOP ) -target_link_libraries(eigerDetectorServerSlave_virtual +target_link_libraries(eigerDetectorServerSlaveTop_virtual PUBLIC pthread rt ) -set_target_properties(eigerDetectorServerSlave_virtual PROPERTIES +set_target_properties(eigerDetectorServerSlaveTop_virtual PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin ) -install(TARGETS eigerDetectorServerSlave_virtual +install(TARGETS eigerDetectorServerSlaveTop_virtual + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} +) + + + + +add_executable(eigerDetectorServerSlaveBottom_virtual + ${src} +) + +target_include_directories(eigerDetectorServerSlaveBottom_virtual + PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} +) + +target_compile_definitions(eigerDetectorServerSlaveBottom_virtual + PUBLIC EIGERD PCCOMPILE STOP_SERVER + PUBLIC VIRTUAL #VIRTUAL_9M +) + +target_link_libraries(eigerDetectorServerSlaveBottom_virtual + PUBLIC pthread rt +) + +set_target_properties(eigerDetectorServerSlaveBottom_virtual PROPERTIES + RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin +) + +install(TARGETS eigerDetectorServerSlaveBottom_virtual RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} ) diff --git a/slsDetectorServers/eigerDetectorServer/bin/eigerDetectorServer_developer b/slsDetectorServers/eigerDetectorServer/bin/eigerDetectorServer_developer index 1d48a328f..500446b97 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 c51deb81c..2a59ce9b4 100755 --- a/slsDetectorServers/eigerDetectorServer/slsDetectorFunctionList.c +++ b/slsDetectorServers/eigerDetectorServer/slsDetectorFunctionList.c @@ -20,6 +20,7 @@ // Global variable from slsDetectorServer_funcs extern int debugflag; extern udpStruct udpDetails; +extern const enum detectorType myDetectorType; // Global variable from communication_funcs.c extern int isControlServer; @@ -88,6 +89,8 @@ pthread_t eiger_virtual_tid; int eiger_virtual_stop = 0; uint64_t eiger_virtual_startingframenumber = 0; int eiger_virtual_detPos[2] = {0, 0}; +int eiger_virtual_test_mode = 0; +int eiger_virtual_quad_mode = 0; #endif @@ -179,8 +182,23 @@ void basictests() { LOG(logINFO, ("Compatibility - success\n")); } +#ifdef VIRTUAL +void setTestImageMode(int ival) { + if (ival >= 0) { + if (ival == 0) { + LOG(logINFO, ("Switching off Image Test Mode\n")); + eiger_virtual_test_mode = 0; + } else { + LOG(logINFO, ("Switching on Image Test Mode\n")); + eiger_virtual_test_mode = 1; + } + } +} - +int getTestImageMode() { + return eiger_virtual_test_mode; +} +#endif /* Ids */ @@ -361,7 +379,11 @@ void getModuleConfiguration() { top = 1; #else master = 0; +#ifdef VIRTUAL_TOP top = 1; +#else + top = 0; +#endif #endif #ifdef VIRTUAL_9M normal = 0; @@ -1291,13 +1313,15 @@ int setQuad(int value) { if (!Feb_Control_SetQuad(value)) { return FAIL; } +#else + eiger_virtual_quad_mode = value; #endif return OK; } int getQuad() { #ifdef VIRTUAL - return 0; + return eiger_virtual_quad_mode; #else return Beb_GetQuad(); #endif @@ -1779,95 +1803,144 @@ void* start_timer(void* arg) { int numPacketsPerFrame = (tgEnable ? 4 : 16) * dr; int npixelsx = 256 * 2 * bytesPerPixel; int databytes = 256 * 256 * 2 * bytesPerPixel; - LOG(logINFO, (" dr:%f\n bytesperpixel:%d\n tgenable:%d\n datasize:%d\n packetsize:%d\n numpackes:%d\n npixelsx:%d\n databytes:%d\n", - dr, bytesPerPixel, tgEnable, datasize, packetsize, numPacketsPerFrame, npixelsx, databytes)); + int row = eiger_virtual_detPos[0]; + int colLeft = top ? eiger_virtual_detPos[1] : eiger_virtual_detPos[1] + 1; + int colRight = top ? eiger_virtual_detPos[1] + 1 : eiger_virtual_detPos[1]; + int ntotpixels = 256 * 256 * 4; + LOG(logINFO, (" dr:%d\n bytesperpixel:%f\n tgenable:%d\n datasize:%d\n packetsize:%d\n numpackes:%d\n npixelsx:%d\n databytes:%d\n ntotpixels:%d\n", + dr, bytesPerPixel, tgEnable, datasize, packetsize, numPacketsPerFrame, npixelsx, databytes, ntotpixels)); - //TODO: Generate data - char imageData[databytes * 2]; - memset(imageData, 0, databytes * 2); - { - int i = 0; - for (i = 0; i < databytes * 2; i += sizeof(uint8_t)) { - *((uint8_t*)(imageData + i)) = i; - } - } - - //TODO: Send data - { - int frameNr = 1; - for(frameNr=1; frameNr <= numFrames; ++frameNr ) { - - //check if virtual_stop is high - if(eiger_virtual_stop == 1){ - break; + //TODO: Generate data + char imageData[databytes * 2]; + memset(imageData, 0, databytes * 2); + { + int i = 0; + switch (dr) { + case 4: + for (i = 0; i < ntotpixels/2; ++i) { + *((uint8_t*)(imageData + i)) = eiger_virtual_test_mode ? 0xEE : (uint8_t)(((2 * i & 0xF) << 4) | ((2 * i + 1) & 0xF)); } + break; + case 8: + for (i = 0; i < ntotpixels; ++i) { + *((uint8_t*)(imageData + i)) = eiger_virtual_test_mode ? 0xFE : (uint8_t)i; + } + break; + case 16: + for (i = 0; i < ntotpixels; ++i) { + *((uint16_t*)(imageData + i * sizeof(uint16_t))) = eiger_virtual_test_mode ? 0xFFE : (uint16_t)i; + } + break; + case 32: + for (i = 0; i < ntotpixels; ++i) { + *((uint32_t*)(imageData + i * sizeof(uint32_t))) = eiger_virtual_test_mode ? 0xFFFFFE : (uint32_t)i; + } + break; + default: + break; + } + } + + //TODO: Send data + { + int frameNr = 1; + for(frameNr=1; frameNr <= numFrames; ++frameNr ) { - int srcOffset = 0; - int srcOffset2 = npixelsx; + usleep(eiger_virtual_transmission_delay_frame); + + //check if virtual_stop is high + if(eiger_virtual_stop == 1){ + break; + } + + int srcOffset = 0; + int srcOffset2 = npixelsx; + + struct timespec begin, end; + clock_gettime(CLOCK_REALTIME, &begin); + usleep(exp_us); + char packetData[packetsize]; + memset(packetData, 0, packetsize); + char packetData2[packetsize]; + memset(packetData2, 0, packetsize); - struct timespec begin, end; - clock_gettime(CLOCK_REALTIME, &begin); - usleep(exp_us); - char packetData[packetsize]; - memset(packetData, 0, packetsize); - char packetData2[packetsize]; - memset(packetData2, 0, packetsize); - - // loop packet - { - int i = 0; - for(i = 0; i != numPacketsPerFrame; ++i) { - int dstOffset = sizeof(sls_detector_header); - int dstOffset2 = sizeof(sls_detector_header); - // set header - sls_detector_header* header = (sls_detector_header*)(packetData); - header->frameNumber = frameNr; - header->packetNumber = i; - header = (sls_detector_header*)(packetData2); - header->frameNumber = frameNr; - header->packetNumber = i; + // loop packet + { + int i = 0; + for(i = 0; i != numPacketsPerFrame; ++i) { + int dstOffset = sizeof(sls_detector_header); + int dstOffset2 = sizeof(sls_detector_header); + // set header + sls_detector_header* header = (sls_detector_header*)(packetData); + header->detType = 3;//(uint16_t)myDetectorType; updated when firmware updates + header->version = SLS_DETECTOR_HEADER_VERSION - 1; + header->frameNumber = frameNr; + header->packetNumber = i; + header->row = row; + header->column = colLeft; - // fill data - { - int psize = 0; - for (psize = 0; psize < datasize; psize += npixelsx) { + header = (sls_detector_header*)(packetData2); + header->detType = (uint16_t)myDetectorType; + header->version = SLS_DETECTOR_HEADER_VERSION - 1; + header->frameNumber = frameNr; + header->packetNumber = i; + header->row = row; + header->column = colRight; + if (eiger_virtual_quad_mode) { + header->row = 1; // right is next row + header->column = 0; // right same first column + } - if (dr == 32 && tgEnable == 0) { - memcpy(packetData + dstOffset, imageData + srcOffset, npixelsx/2); - memcpy(packetData2 + dstOffset2, imageData + srcOffset2, npixelsx/2); + // fill data + { + int psize = 0; + for (psize = 0; psize < datasize; psize += npixelsx) { + + if (dr == 32 && tgEnable == 0) { + memcpy(packetData + dstOffset, imageData + srcOffset, npixelsx/2); + memcpy(packetData2 + dstOffset2, imageData + srcOffset2, npixelsx/2); + if (srcOffset % npixelsx == 0) { + srcOffset += npixelsx/2; + srcOffset2 += npixelsx/2; + } + // skip the other half (2 packets in 1 line for 32 bit) + else { srcOffset += npixelsx; - srcOffset2 += npixelsx; - dstOffset += npixelsx/2; - dstOffset2 += npixelsx/2; - } else { - memcpy(packetData + dstOffset, imageData + srcOffset, npixelsx); - memcpy(packetData2 + dstOffset2, imageData + srcOffset2, npixelsx); - srcOffset += 2 * npixelsx; - srcOffset2 += 2 * npixelsx; - dstOffset += npixelsx; - dstOffset2 += npixelsx; + srcOffset2 += npixelsx; } + dstOffset += npixelsx/2; + dstOffset2 += npixelsx/2; + } else { + memcpy(packetData + dstOffset, imageData + srcOffset, npixelsx); + memcpy(packetData2 + dstOffset2, imageData + srcOffset2, npixelsx); + srcOffset += 2 * npixelsx; + srcOffset2 += 2 * npixelsx; + dstOffset += npixelsx; + dstOffset2 += npixelsx; } } - - sendUDPPacket(0, packetData, packetsize); - sendUDPPacket(1, packetData2, packetsize); } + usleep(eiger_virtual_transmission_delay_left); + sendUDPPacket(0, packetData, packetsize); + usleep(eiger_virtual_transmission_delay_right); + sendUDPPacket(1, packetData2, packetsize); } - LOG(logINFO, ("Sent frame: %d\n", frameNr)); - clock_gettime(CLOCK_REALTIME, &end); - int64_t time_ns = ((end.tv_sec - begin.tv_sec) * 1E9 + - (end.tv_nsec - begin.tv_nsec)); + } + LOG(logINFO, ("Sent frame: %d\n", frameNr)); + clock_gettime(CLOCK_REALTIME, &end); + int64_t time_ns = ((end.tv_sec - begin.tv_sec) * 1E9 + + (end.tv_nsec - begin.tv_nsec)); - // sleep for (period - exptime) - if (frameNr < numFrames) { // if there is a next frame - if (periodns > time_ns) { - usleep((periodns - time_ns)/ 1000); - } + // sleep for (period - exptime) + if (frameNr < numFrames) { // if there is a next frame + if (periodns > time_ns) { + usleep((periodns - time_ns)/ 1000); } } } + } + closeUDPSocket(0); closeUDPSocket(1); diff --git a/slsDetectorServers/gotthard2DetectorServer/bin/gotthard2DetectorServer_developer b/slsDetectorServers/gotthard2DetectorServer/bin/gotthard2DetectorServer_developer index b8b11d260..6d46a5b17 100755 Binary files a/slsDetectorServers/gotthard2DetectorServer/bin/gotthard2DetectorServer_developer and b/slsDetectorServers/gotthard2DetectorServer/bin/gotthard2DetectorServer_developer differ diff --git a/slsDetectorServers/gotthardDetectorServer/bin/gotthardDetectorServer_developer b/slsDetectorServers/gotthardDetectorServer/bin/gotthardDetectorServer_developer index 83c0ff984..945d56400 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 e9e7b568e..133879600 100755 --- a/slsDetectorServers/gotthardDetectorServer/slsDetectorFunctionList.c +++ b/slsDetectorServers/gotthardDetectorServer/slsDetectorFunctionList.c @@ -239,10 +239,10 @@ void setTestImageMode(int ival) { uint32_t addr = MULTI_PURPOSE_REG; if (ival >= 0) { if (ival == 0) { - LOG(logINFO, ("Switching on Image Test Mode\n")); + LOG(logINFO, ("Switching off Image Test Mode\n")); bus_w (addr, bus_r(addr) & ~DGTL_TST_MSK); } else { - LOG(logINFO, ("Switching off Image Test Mode\n")); + LOG(logINFO, ("Switching on Image Test Mode\n")); bus_w (addr, bus_r(addr) | DGTL_TST_MSK); } } @@ -915,8 +915,9 @@ int getModule(sls_detector_module *myMod){ if (dacValues[idac] >= 0) initialized = 1; } - if (initialized) + if (initialized) { return OK; + } return FAIL; } diff --git a/slsDetectorServers/jungfrauDetectorServer/bin/jungfrauDetectorServer_developer b/slsDetectorServers/jungfrauDetectorServer/bin/jungfrauDetectorServer_developer index 09b83a2be..7cf0b600d 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 de6dcfbf8..dba6bad05 100755 --- a/slsDetectorServers/jungfrauDetectorServer/slsDetectorFunctionList.c +++ b/slsDetectorServers/jungfrauDetectorServer/slsDetectorFunctionList.c @@ -31,6 +31,7 @@ char initErrorMessage[MAX_STR_LENGTH]; pthread_t pthread_virtual_tid; int virtual_status = 0; int virtual_stop = 0; +int virtual_image_test_mode = 0; #endif enum detectorSettings thisSettings = UNINITIALIZED; @@ -41,6 +42,7 @@ int detPos[4] = {}; int numUDPInterfaces = 1; + int isInitCheckDone() { return initCheckDone; } @@ -226,6 +228,23 @@ int testBus() { } +#ifdef VIRTUAL +void setTestImageMode(int ival) { + if (ival >= 0) { + if (ival == 0) { + LOG(logINFO, ("Switching off Image Test Mode\n")); + virtual_image_test_mode = 0; + } else { + LOG(logINFO, ("Switching on Image Test Mode\n")); + virtual_image_test_mode = 1; + } + } +} + +int getTestImageMode() { + return virtual_image_test_mode; +} +#endif /* Ids */ @@ -727,8 +746,9 @@ int getModule(sls_detector_module *myMod){ if (dacValues[idac] >= 0) initialized = 1; } - if (initialized) + if (initialized) { return OK; + } return FAIL; } @@ -1646,75 +1666,81 @@ void* start_timer(void* arg) { getNumTriggers() * (getNumAdditionalStorageCells() + 1)); int64_t exp_us = getExpTime() / 1000; + const int npixels = 256 * 256 * 8; + const int datasize = 8192; + const int packetsize = datasize + sizeof(sls_detector_header); + const int numPacketsPerFrame = 128; + int transmissionDelayUs = getTransmissionDelayFrame() * 1000; - //TODO: Generate data - char imageData[DATA_BYTES]; - memset(imageData, 0, DATA_BYTES); - { - int i = 0; - for (i = 0; i < DATA_BYTES; i += sizeof(uint16_t)) { - *((uint16_t*)(imageData + i)) = i; - } + //TODO: Generate data + char imageData[DATA_BYTES]; + memset(imageData, 0, DATA_BYTES); + { + int i = 0; + for (i = 0; i < npixels; ++i) { + // avoiding gain also being divided when gappixels enabled in call back + *((uint16_t*)(imageData + i * sizeof(uint16_t))) = virtual_image_test_mode ? 0x0FFE : (uint16_t)i; } - int datasize = 8192; - - - //TODO: Send data - { - int frameNr = 0; - for(frameNr=0; frameNr!= numFrames; ++frameNr ) { + } + + + //TODO: Send data + { + int frameNr = 0; + for(frameNr=0; frameNr!= numFrames; ++frameNr ) { - //check if virtual_stop is high - if(virtual_stop == 1){ - break; - } + usleep(transmissionDelayUs); - int srcOffset = 0; + //check if virtual_stop is high + if(virtual_stop == 1){ + break; + } + + int srcOffset = 0; + + struct timespec begin, end; + clock_gettime(CLOCK_REALTIME, &begin); + + usleep(exp_us); + + char packetData[packetsize]; + memset(packetData, 0, packetsize); - struct timespec begin, end; - clock_gettime(CLOCK_REALTIME, &begin); + // loop packet + { + int i = 0; + for(i = 0; i != numPacketsPerFrame; ++i) { + // set header + sls_detector_header* header = (sls_detector_header*)(packetData); + header->detType = (uint16_t)myDetectorType; + header->version = SLS_DETECTOR_HEADER_VERSION - 1; + header->frameNumber = frameNr; + header->packetNumber = i; + header->modId = 0; + header->row = detPos[X]; + header->column = detPos[Y]; - usleep(exp_us); - - const int size = datasize + sizeof(sls_detector_header); - char packetData[size]; - memset(packetData, 0, sizeof(sls_detector_header)); - - // loop packet - { - int i = 0; - for(i=0; i!=128; ++i) { - // set header - sls_detector_header* header = (sls_detector_header*)(packetData); - header->frameNumber = frameNr; - header->packetNumber = i; - header->modId = 0; - header->row = detPos[X]; - header->column = detPos[Y]; - header->detType = (uint16_t)myDetectorType; - header->version = SLS_DETECTOR_HEADER_VERSION - 1; - // fill data - memcpy(packetData + sizeof(sls_detector_header), imageData + srcOffset, datasize); - srcOffset += datasize; - - sendUDPPacket(0, packetData, size); - } + // fill data + memcpy(packetData + sizeof(sls_detector_header), imageData + srcOffset, datasize); + srcOffset += datasize; + + sendUDPPacket(0, packetData, packetsize); } - LOG(logINFO, ("Sent frame: %d\n", frameNr)); - clock_gettime(CLOCK_REALTIME, &end); - int64_t time_ns = ((end.tv_sec - begin.tv_sec) * 1E9 + - (end.tv_nsec - begin.tv_nsec)); - - // sleep for (period - exptime) - if (frameNr < numFrames) { // if there is a next frame - if (periodns > time_ns) { - usleep((periodns - time_ns)/ 1000); - } + } + LOG(logINFO, ("Sent frame: %d\n", frameNr)); + clock_gettime(CLOCK_REALTIME, &end); + int64_t time_ns = ((end.tv_sec - begin.tv_sec) * 1E9 + + (end.tv_nsec - begin.tv_nsec)); + + // sleep for (period - exptime) + if (frameNr < numFrames) { // if there is a next frame + if (periodns > time_ns) { + usleep((periodns - time_ns)/ 1000); } } } + } - // } closeUDPSocket(0); diff --git a/slsDetectorServers/moenchDetectorServer/bin/moenchDetectorServer_developer b/slsDetectorServers/moenchDetectorServer/bin/moenchDetectorServer_developer index f3756181a..43c46788c 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 1746ea4bd..4e1e22470 100755 --- a/slsDetectorServers/moenchDetectorServer/slsDetectorFunctionList.c +++ b/slsDetectorServers/moenchDetectorServer/slsDetectorFunctionList.c @@ -969,8 +969,9 @@ enum detectorSettings getSettings() { void setDAC(enum DACINDEX ind, int val, int mV) { - if (val < 0 && val != LTC2620_GetPowerDownValue()) + if (val < 0 && val != LTC2620_GetPowerDownValue()) { return; + } char* dac_names[] = {DAC_NAMES}; LOG(logINFO, ("Setting DAC %s\n", dac_names[ind])); diff --git a/slsDetectorServers/mythen3DetectorServer/bin/mythen3DetectorServer_developer b/slsDetectorServers/mythen3DetectorServer/bin/mythen3DetectorServer_developer index 140e67239..0c3b1e35f 100755 Binary files a/slsDetectorServers/mythen3DetectorServer/bin/mythen3DetectorServer_developer and b/slsDetectorServers/mythen3DetectorServer/bin/mythen3DetectorServer_developer differ diff --git a/slsDetectorServers/slsDetectorServer/include/slsDetectorFunctionList.h b/slsDetectorServers/slsDetectorServer/include/slsDetectorFunctionList.h index 4e7e0d9ff..b2337d03b 100755 --- a/slsDetectorServers/slsDetectorServer/include/slsDetectorFunctionList.h +++ b/slsDetectorServers/slsDetectorServer/include/slsDetectorFunctionList.h @@ -61,7 +61,7 @@ int testFpga(); int testBus(); #endif -#ifdef GOTTHARDD +#if defined(GOTTHARDD) || ((defined(EIGERD) || defined(JUNGFRAUD)) && defined(VIRTUAL)) void setTestImageMode(int ival); int getTestImageMode(); #endif diff --git a/slsDetectorServers/slsDetectorServer/src/ASIC_Driver.c b/slsDetectorServers/slsDetectorServer/src/ASIC_Driver.c index c5f5acc60..a83c29f3b 100755 --- a/slsDetectorServers/slsDetectorServer/src/ASIC_Driver.c +++ b/slsDetectorServers/slsDetectorServer/src/ASIC_Driver.c @@ -26,8 +26,12 @@ void ASIC_Driver_SetDefines(char* driverfname) { } int ASIC_Driver_Set (int index, int length, char* buffer) { + char temp[20]; + memset(temp, 0, sizeof(temp)); + sprintf(temp, "%d", index + 1); char fname[MAX_STR_LENGTH]; - sprintf(fname, "%s%d", ASIC_Driver_DriverFileName, index + 1); + strcpy(fname, ASIC_Driver_DriverFileName); + strcat(fname, temp); LOG(logDEBUG2, ("\t[chip index: %d, length: %d, fname: %s]\n", index, length, fname)); { LOG(logDEBUG2, ("\t[values: \n")); diff --git a/slsDetectorServers/slsDetectorServer/src/LTC2620_Driver.c b/slsDetectorServers/slsDetectorServer/src/LTC2620_Driver.c index 96ab3261e..26fc6b657 100755 --- a/slsDetectorServers/slsDetectorServer/src/LTC2620_Driver.c +++ b/slsDetectorServers/slsDetectorServer/src/LTC2620_Driver.c @@ -73,7 +73,11 @@ int LTC2620_D_SetDACValue (int dacnum, int val, int mV, char* dacname, int* dacv LOG(logINFO, ("Setting DAC %2d [%-12s] : %d dac (%d mV)\n",dacnum, dacname, *dacval, dacmV)); char fname[MAX_STR_LENGTH]; - sprintf(fname, "%s%d", LTC2620_D_DriverFileName, dacnum); + strcpy(fname, LTC2620_D_DriverFileName); + char temp[20]; + memset(temp, 0, sizeof(temp)); + sprintf(temp, "%d", dacnum); + strcat(fname, temp); LOG(logDEBUG1, ("fname %s\n",fname)); //open file diff --git a/slsDetectorServers/slsDetectorServer/src/slsDetectorServer.c b/slsDetectorServers/slsDetectorServer/src/slsDetectorServer.c index 76e5bc705..301b0e51b 100755 --- a/slsDetectorServers/slsDetectorServer/src/slsDetectorServer.c +++ b/slsDetectorServers/slsDetectorServer/src/slsDetectorServer.c @@ -101,17 +101,25 @@ int main(int argc, char *argv[]){ } #ifdef STOP_SERVER - char cmd[100]; - memset(cmd, 0, 100); + char cmd[MAX_STR_LENGTH]; + memset(cmd, 0, MAX_STR_LENGTH); #endif if (isControlServer) { LOG(logINFO, ("Opening control server on port %d \n", portno)); #ifdef STOP_SERVER { int i; - for (i = 0; i < argc; ++i) - sprintf(cmd, "%s %s", cmd, argv[i]); - sprintf(cmd,"%s -stopserver -port %d &", cmd, portno + 1); + for (i = 0; i < argc; ++i) { + if (i > 0) { + strcat(cmd, " "); + } + strcat(cmd, argv[i]); + } + char temp[50]; + memset(temp, 0, sizeof(temp)); + sprintf(temp, " -stopserver -port %d &", portno + 1); + strcat(cmd, temp); + LOG(logDEBUG1, ("Command to start stop server:%s\n", cmd)); system(cmd); } diff --git a/slsDetectorServers/slsDetectorServer/src/slsDetectorServer_funcs.c b/slsDetectorServers/slsDetectorServer/src/slsDetectorServer_funcs.c index fa3fb4ab8..c151d6d76 100755 --- a/slsDetectorServers/slsDetectorServer/src/slsDetectorServer_funcs.c +++ b/slsDetectorServers/slsDetectorServer/src/slsDetectorServer_funcs.c @@ -776,10 +776,10 @@ int set_image_test_mode(int file_des) { return printSocketReadError(); LOG(logDEBUG1, ("Setting image test mode to \n", arg)); -#ifndef GOTTHARDD - functionNotImplemented(); -#else +#if defined(GOTTHARDD) || ((defined(EIGERD) || defined(JUNGFRAUD)) && defined(VIRTUAL)) setTestImageMode(arg); +#else + functionNotImplemented(); #endif return Server_SendResult(file_des, INT32, UPDATE, NULL, 0); } @@ -790,11 +790,11 @@ int get_image_test_mode(int file_des) { int retval = -1; LOG(logDEBUG1, ("Getting image test mode\n")); -#ifndef GOTTHARDD - functionNotImplemented(); -#else +#if defined(GOTTHARDD) || ((defined(EIGERD) || defined(JUNGFRAUD)) && defined(VIRTUAL)) retval = getTestImageMode(); LOG(logDEBUG1, ("image test mode retval: %d\n", retval)); +#else + functionNotImplemented(); #endif return Server_SendResult(file_des, INT32, UPDATE, &retval, sizeof(retval)); } @@ -1844,7 +1844,8 @@ int start_acquisition(int file_des) { #endif if (configured == FAIL) { ret = FAIL; - sprintf(mess, "Could not start acquisition because %s\n", configureMessage); + strcpy(mess, "Could not start acquisition because "); + strcat(mess, configureMessage); LOG(logERROR,(mess)); } else { ret = startStateMachine(); @@ -1979,7 +1980,8 @@ int start_and_read_all(int file_des) { #endif if (configured == FAIL) { ret = FAIL; - sprintf(mess, "Could not start acquisition because %s\n", configureMessage); + strcpy(mess, "Could not start acquisition because "); + strcat(mess, configureMessage); LOG(logERROR,(mess)); } else { ret = startStateMachine(); @@ -4352,7 +4354,11 @@ int copy_detector_server(int file_des) { memset(cmd, 0, MAX_STR_LENGTH); // copy server - sprintf(cmd, "tftp %s -r %s -g", hostname, sname); + strcpy(cmd, "tftp "); + strcat(cmd, hostname); + strcat(cmd, " -r "); + strcat(cmd, sname); + strcat(cmd, " -g"); int success = executeCommand(cmd, retvals, logDEBUG1); if (success == FAIL) { ret = FAIL; @@ -4364,7 +4370,8 @@ int copy_detector_server(int file_des) { else { LOG(logINFO, ("Server copied successfully\n")); // give permissions - sprintf(cmd, "chmod 777 %s", sname); + strcpy(cmd, "chmod 777 "); + strcat(cmd, sname); executeCommand(cmd, retvals, logDEBUG1); // edit /etc/inittab @@ -4384,7 +4391,9 @@ int copy_detector_server(int file_des) { LOG(logINFO, ("Deleted all lines containing DetectorServer in /etc/inittab\n")); // append line - sprintf(cmd, "echo \"ttyS0::respawn:/./%s\" >> /etc/inittab", sname); + strcpy(cmd, "echo \"ttyS0::respawn:/./"); + strcat(cmd, sname); + strcat(cmd, "\" >> /etc/inittab"); executeCommand(cmd, retvals, logDEBUG1); LOG(logINFO, ("/etc/inittab modified to have %s\n", sname)); diff --git a/slsDetectorSoftware/include/Detector.h b/slsDetectorSoftware/include/Detector.h index cc08a6ff9..692711507 100644 --- a/slsDetectorSoftware/include/Detector.h +++ b/slsDetectorSoftware/include/Detector.h @@ -5,6 +5,7 @@ #include #include #include +#include class detectorData; @@ -137,6 +138,16 @@ class Detector { void *), void *pArg); + /**[Eiger][Jungfrau] */ + bool getGapPixelsinCallback() const; + + /** + * [Eiger][Jungfrau] + * Only in client data call back + * Fills in gap pixels in data + */ + void setGapPixelsinCallback(const bool enable); + /************************************************** * * * Acquisition Parameters * @@ -255,12 +266,6 @@ class Detector { Result getHighVoltage(Positions pos = {}) const; - /** [Jungfrau][Mythen3][Gotthard2][Moench] */ - Result getPowerChip(Positions pos = {}) const; - - /** [Jungfrau][Mythen3][Gotthard2][Moench] */ - void setPowerChip(bool on, Positions pos = {}); - /** * [Gotthard] Options: 0, 90, 110, 120, 150, 180, 200 * [Jungfrau][CTB][Moench] Options: 0, 60 - 200 @@ -268,6 +273,21 @@ class Detector { */ void setHighVoltage(int value, Positions pos = {}); + /** [Jungfrau][Mythen3][Gotthard2][Moench] */ + Result getPowerChip(Positions pos = {}) const; + + /** [Jungfrau][Mythen3][Gotthard2][Moench] */ + void setPowerChip(bool on, Positions pos = {}); + + /** [Gotthard][Eiger virtual] */ + Result getImageTestMode(Positions pos = {}); + + /** [Gotthard] If 1, adds channel intensity with precalculated values. + * Default is 0 + * [Eiger virtual] If 1, pixels are saturated. If 0, increasing intensity + * Only for virtual servers */ + void setImageTestMode(const int value, Positions pos = {}); + /** * (Degrees) * [Gotthard] Options: TEMPERATURE_ADC, TEMPERATURE_FPGA @@ -694,16 +714,6 @@ class Detector { /** [Eiger] */ void loadTrimbits(const std::string &fname, Positions pos = {}); - /**[Eiger] */ - Result getRxAddGapPixels(Positions pos = {}) const; - - /** - * [Eiger] - * 4 bit mode not implemented in Receiver, but in client data call back - * Fills in gap pixels in data - */ - void setRxAddGapPixels(bool enable); - /** [Eiger] */ Result getParallelMode(Positions pos = {}) const; @@ -905,12 +915,6 @@ class Detector { void setExternalSignalFlags(defs::externalSignalFlag value, Positions pos = {}); - /** [Gotthard] */ - Result getImageTestMode(Positions pos = {}); - - /** [Gotthard] If 1, adds channel intensity with precalculated values. - * Default is 0 */ - void setImageTestMode(const int value, Positions pos = {}); /************************************************** * * @@ -1196,10 +1200,10 @@ class Detector { * ************************************************/ /** [Moench] */ - Result getAdditionalJsonHeader(Positions pos = {}) const; + Result> getAdditionalJsonHeader(Positions pos = {}) const; - /** [Moench] */ - void setAdditionalJsonHeader(const std::string &jsonheader, + /** [Moench] If empty, reset additional json header. Max 20 characters for each key/value */ + void setAdditionalJsonHeader(const std::map &jsonHeader, Positions pos = {}); /** [Moench] */ @@ -1207,12 +1211,11 @@ class Detector { Positions pos = {}) const; /** * [Moench] - * Sets the value for additional json header parameter if found, + * Sets the value for additional json header parameters if found, * else appends the parameter key and value - * The value cannot be empty + * If empty, deletes parameter. Max 20 characters for each key/value */ - void setAdditionalJsonParameter(const std::string &key, - const std::string &value, + void setAdditionalJsonParameter(const std::string &key, const std::string &value, Positions pos = {}); /** [Moench] TODO! How do we do this best??? Can be refactored to something diff --git a/slsDetectorSoftware/include/detectorData.h b/slsDetectorSoftware/include/detectorData.h index 528def82d..6e6b912e3 100755 --- a/slsDetectorSoftware/include/detectorData.h +++ b/slsDetectorSoftware/include/detectorData.h @@ -16,9 +16,10 @@ class detectorData { * @param dbytes number of bytes of image pointed to by cval pointer * @param dr dynamic range or bits per pixel * @param fIndex file index + * @param complete true if complete image, else missing packets */ - detectorData(double progress, std::string fname, int x, int y, char *d, int dbytes, int dr, uint64_t fIndex) : - progressIndex(progress), fileName(fname), fileIndex(fIndex), nx(x), ny(y), data(d), databytes(dbytes), dynamicRange(dr) {}; + detectorData(double progress, std::string fname, int x, int y, char *d, int dbytes, int dr, uint64_t fIndex, bool complete) : + progressIndex(progress), fileName(fname), fileIndex(fIndex), nx(x), ny(y), data(d), databytes(dbytes), dynamicRange(dr), completeImage(complete) {}; /** * Destructor @@ -55,4 +56,5 @@ class detectorData { char* data; int databytes; int dynamicRange; + bool completeImage; }; diff --git a/slsDetectorSoftware/src/CmdProxy.cpp b/slsDetectorSoftware/src/CmdProxy.cpp index e9d0a0e75..65f5043fc 100644 --- a/slsDetectorSoftware/src/CmdProxy.cpp +++ b/slsDetectorSoftware/src/CmdProxy.cpp @@ -1001,24 +1001,27 @@ std::string CmdProxy::GapPixels(int action) { std::ostringstream os; os << cmd << ' '; if (action == defs::HELP_ACTION) { - os << "[0, 1]\n\t[Eiger] Include Gap pixels in data file or data call " - "back. 4 bit mode gap pixels only ind ata call back." + os << "[0, 1]\n\t[Eiger][Jungfrau] Include Gap pixels only in data call back." << '\n'; } else if (action == defs::GET_ACTION) { + if (det_id != -1) { + throw sls::RuntimeError( + "Cannot get gap pixels at module level"); + } if (!args.empty()) { WrongNumberOfParameters(0); } - auto t = det->getRxAddGapPixels({det_id}); - os << OutString(t) << '\n'; + auto t = det->getGapPixelsinCallback(); + os << t << '\n'; } else if (action == defs::PUT_ACTION) { if (det_id != -1) { throw sls::RuntimeError( - "Cannot execute dynamic range at module level"); + "Cannot add gap pixels at module level"); } if (args.size() != 1) { WrongNumberOfParameters(1); } - det->setRxAddGapPixels(StringTo(args[0])); + det->setGapPixelsinCallback(StringTo(args[0])); os << args.front() << '\n'; } else { throw sls::RuntimeError("Unknown action"); @@ -1224,7 +1227,7 @@ std::string CmdProxy::Quad(int action) { } else if (action == defs::PUT_ACTION) { if (det_id != -1) { throw sls::RuntimeError( - "Cannot execute dynamic range at module level"); + "Cannot execute quad at module level"); } if (args.size() != 1) { WrongNumberOfParameters(1); @@ -1879,13 +1882,47 @@ std::string CmdProxy::PatternWaitTime(int action) { /* Moench */ +std::string CmdProxy::AdditionalJsonHeader(int action) { + std::ostringstream os; + os << cmd << ' '; + if (action == defs::HELP_ACTION) { + os << "[key1] [value1] [key2] [value2]...[keyn] [valuen]" + "\n\tAdditional json header to be streamed out from receiver via zmq. " + "Default is empty. Use only if to be processed by an intermediate user process " + "listening to receiver zmq packets. Empty value deletes header. " + << '\n'; + } else if (action == defs::GET_ACTION) { + if (args.size() != 0) { + WrongNumberOfParameters(0); + } + auto t = det->getAdditionalJsonHeader({det_id}); + os << OutString(t) << '\n'; + } else if (action == defs::PUT_ACTION) { + // arguments can be empty + std::map json; + for (size_t i = 0; i < args.size(); i = i + 2) { + // last value is empty + if (i + 1 >= args.size()) { + json[args[i]] = ""; + } else { + json[args[i]] = args[i + 1]; + } + } + det->setAdditionalJsonHeader(json, {det_id}); + os << sls::ToString(json) << '\n'; + } else { + throw sls::RuntimeError("Unknown action"); + } + return os.str(); +} + std::string CmdProxy::JsonParameter(int action) { std::ostringstream os; os << cmd << ' '; if (action == defs::HELP_ACTION) { os << "[key1] [value1]\n\tAdditional json header parameter streamed " - "out from receiver. If empty in a get, then no parameter found. " - "This is same as calling rx_jsonaddheader \"key\":\"value1\"." + "out from receiver. If not found in header, the pair is appended. " + "An empty values deletes parameter." << '\n'; } else if (action == defs::GET_ACTION) { if (args.size() != 1) { @@ -1894,11 +1931,21 @@ std::string CmdProxy::JsonParameter(int action) { auto t = det->getAdditionalJsonParameter(args[0], {det_id}); os << OutString(t) << '\n'; } else if (action == defs::PUT_ACTION) { - if (args.size() != 2) { - WrongNumberOfParameters(2); + switch (args.size()) { + case 1: + det->setAdditionalJsonParameter(args[0], "", {det_id}); + break; + case 2: + det->setAdditionalJsonParameter(args[0], args[1], {det_id}); + break; + default: + WrongNumberOfParameters(1); + } + if (args.size() == 1) { + os << args[0] << " deleted" << '\n'; + } else { + os << "{" << args[0] << ": " << args[1] << "}" << '\n'; } - det->setAdditionalJsonParameter(args[0], args[1], {det_id}); - os << sls::ToString(args) << '\n'; } else { throw sls::RuntimeError("Unknown action"); } diff --git a/slsDetectorSoftware/src/CmdProxy.h b/slsDetectorSoftware/src/CmdProxy.h index ef35f0db2..fe063e294 100644 --- a/slsDetectorSoftware/src/CmdProxy.h +++ b/slsDetectorSoftware/src/CmdProxy.h @@ -477,6 +477,7 @@ class CmdProxy { {"cycles", "triggers"}, {"cyclesl", "triggersl"}, {"clkdivider", "speed"}, + {"digitest", "imagetest"}, /** temperature */ /** dacs */ @@ -527,8 +528,6 @@ class CmdProxy { /* Jungfrau Specific */ /* Gotthard Specific */ - {"digitest", "imagetest"}, - /* Gotthard2 Specific */ /* Mythen3 Specific */ /* CTB Specific */ @@ -591,6 +590,7 @@ class CmdProxy { {"clkdiv", &CmdProxy::ClockDivider}, {"vhighvoltage", &CmdProxy::vhighvoltage}, {"powerchip", &CmdProxy::powerchip}, + {"imagetest", &CmdProxy::imagetest}, /** temperature */ {"temp_adc", &CmdProxy::temp_adc}, @@ -789,7 +789,6 @@ class CmdProxy { {"clearroi", &CmdProxy::ClearROI}, {"exptimel", &CmdProxy::exptimel}, {"extsig", &CmdProxy::extsig}, - {"imagetest", &CmdProxy::imagetest}, /* Gotthard2 Specific */ {"bursts", &CmdProxy::bursts}, @@ -867,7 +866,7 @@ class CmdProxy { {"patsetbit", &CmdProxy::patsetbit}, /* Moench */ - {"rx_jsonaddheader", &CmdProxy::rx_jsonaddheader}, + {"rx_jsonaddheader", &CmdProxy::AdditionalJsonHeader}, {"rx_jsonpara", &CmdProxy::JsonParameter}, {"emin", &CmdProxy::MinMaxEnergyThreshold}, {"emax", &CmdProxy::MinMaxEnergyThreshold}, @@ -980,6 +979,7 @@ class CmdProxy { std::string PatternWaitAddress(int action); std::string PatternWaitTime(int action); /* Moench */ + std::string AdditionalJsonHeader(int action); std::string JsonParameter(int action); std::string MinMaxEnergyThreshold(int action); /* Advanced */ @@ -1088,6 +1088,10 @@ class CmdProxy { "\n\t[Mythen3] If module not connected or wrong module, 1 will fail. By default, not powered on" "\n\t[Gotthard2] If module not connected or wrong module, 1 will fail. By default, powered on at server start up."); + INTEGER_COMMAND(imagetest, getImageTestMode, setImageTestMode, StringTo, + "[0, 1]\n\t[Gotthard] 1 adds channel intensity with precalculated values when taking an acquisition. Default is 0." + "\n\t[Eiger][Jungfrau] Only for Virtual servers. If 0, each pixel intensity incremented by 1. If 1, all pixels almost saturated."); + /** temperature */ GET_IND_COMMAND(temp_adc, getTemperature, slsDetectorDefs::TEMPERATURE_ADC, " °C", @@ -1582,9 +1586,6 @@ class CmdProxy { INTEGER_COMMAND(extsig, getExternalSignalFlags, setExternalSignalFlags, sls::StringTo, "[trigger_in_rising_edge|trigger_in_falling_edge]\n\t[Gotthard] External signal mode for trigger timing mode."); - INTEGER_COMMAND(imagetest, getImageTestMode, setImageTestMode, StringTo, - "[0, 1]\n\t[Gotthard] 1 adds channel intensity with precalculated values when taking an acquisition. Default is 0."); - /* Gotthard2 Specific */ INTEGER_COMMAND_NOID(bursts, getNumberOfBursts, setNumberOfBursts, StringTo, @@ -1719,9 +1720,6 @@ class CmdProxy { /* Moench */ - STRING_COMMAND(rx_jsonaddheader, getAdditionalJsonHeader, setAdditionalJsonHeader, - "[\\\"label1\\\":\\\"value1\\\"], [\\\"label2\\\":\\\"value2\\\"]\n\tAdditional json header to be streamd out from receiver via zmq. Default is empty. Use only if to be processed by an intermediate user process listening to receiver zmq packets."); - INTEGER_COMMAND(framemode, getFrameMode, setFrameMode, sls::StringTo, "[pedestal|newpedestal|flatfield|newflatfield]\n\t[Moench] Frame mode (soft setting) in processor."); diff --git a/slsDetectorSoftware/src/Detector.cpp b/slsDetectorSoftware/src/Detector.cpp index e2f2088c5..92e58fd05 100644 --- a/slsDetectorSoftware/src/Detector.cpp +++ b/slsDetectorSoftware/src/Detector.cpp @@ -167,6 +167,14 @@ void Detector::registerDataCallback(void (*func)(detectorData *, uint64_t, pimpl->registerDataCallback(func, pArg); } +bool Detector::getGapPixelsinCallback() const { + return pimpl->getGapPixelsinCallback(); +} + +void Detector::setGapPixelsinCallback(bool enable) { + pimpl->setGapPixelsinCallback(enable); +} + // Acquisition Parameters Result Detector::getNumberOfFrames(Positions pos) const { @@ -359,6 +367,14 @@ void Detector::setPowerChip(bool on, Positions pos) { } } +Result Detector::getImageTestMode(Positions pos) { + return pimpl->Parallel(&Module::getImageTestMode, pos); +} + +void Detector::setImageTestMode(int value, Positions pos) { + pimpl->Parallel(&Module::setImageTestMode, pos, value); +} + Result Detector::getTemperature(defs::dacIndex index, Positions pos) const { switch (index) { @@ -953,14 +969,6 @@ void Detector::loadTrimbits(const std::string &fname, Positions pos) { pimpl->Parallel(&Module::loadSettingsFile, pos, fname); } -Result Detector::getRxAddGapPixels(Positions pos) const { - return pimpl->Parallel(&Module::enableGapPixels, pos, -1); -} - -void Detector::setRxAddGapPixels(bool enable) { - pimpl->setGapPixelsinReceiver(enable); -} - Result Detector::getParallelMode(Positions pos) const { return pimpl->Parallel(&Module::getParallelMode, pos); } @@ -1195,14 +1203,6 @@ void Detector::setExternalSignalFlags(defs::externalSignalFlag value, pimpl->Parallel(&Module::setExternalSignalFlags, pos, value); } -Result Detector::getImageTestMode(Positions pos) { - return pimpl->Parallel(&Module::getImageTestMode, pos); -} - -void Detector::setImageTestMode(int value, Positions pos) { - pimpl->Parallel(&Module::setImageTestMode, pos, value); -} - // Gotthard2 Specific Result Detector::getNumberOfBursts(Positions pos) const { @@ -1612,13 +1612,13 @@ void Detector::setPatternBitMask(uint64_t mask, Positions pos) { // Moench -Result Detector::getAdditionalJsonHeader(Positions pos) const { +Result> Detector::getAdditionalJsonHeader(Positions pos) const { return pimpl->Parallel(&Module::getAdditionalJsonHeader, pos); } -void Detector::setAdditionalJsonHeader(const std::string &jsonheader, +void Detector::setAdditionalJsonHeader(const std::map &jsonHeader, Positions pos) { - pimpl->Parallel(&Module::setAdditionalJsonHeader, pos, jsonheader); + pimpl->Parallel(&Module::setAdditionalJsonHeader, pos, jsonHeader); } Result Detector::getAdditionalJsonParameter(const std::string &key, @@ -1626,8 +1626,7 @@ Result Detector::getAdditionalJsonParameter(const std::string &key, return pimpl->Parallel(&Module::getAdditionalJsonParameter, pos, key); } -void Detector::setAdditionalJsonParameter(const std::string &key, - const std::string &value, +void Detector::setAdditionalJsonParameter(const std::string &key, const std::string &value, Positions pos) { pimpl->Parallel(&Module::setAdditionalJsonParameter, pos, key, value); } diff --git a/slsDetectorSoftware/src/DetectorImpl.cpp b/slsDetectorSoftware/src/DetectorImpl.cpp index 42d6713f5..af32236c0 100755 --- a/slsDetectorSoftware/src/DetectorImpl.cpp +++ b/slsDetectorSoftware/src/DetectorImpl.cpp @@ -157,6 +157,7 @@ void DetectorImpl::initializeDetectorStructure() { multi_shm()->numberOfChannels.y = 0; multi_shm()->acquiringFlag = false; multi_shm()->initialChecks = true; + multi_shm()->gapPixels = false; } void DetectorImpl::initializeMembers(bool verify) { @@ -339,17 +340,30 @@ void DetectorImpl::setNumberOfChannels(const slsDetectorDefs::xy c) { multi_shm()->numberOfChannels = c; } -void DetectorImpl::setGapPixelsinReceiver(bool enable) { - Parallel(&Module::enableGapPixels, {}, static_cast(enable)); - // update number of channels - Result res = - Parallel(&Module::getNumberOfChannels, {}); - multi_shm()->numberOfChannels.x = 0; - multi_shm()->numberOfChannels.y = 0; - for (auto &it : res) { - multi_shm()->numberOfChannels.x += it.x; - multi_shm()->numberOfChannels.y += it.y; +bool DetectorImpl::getGapPixelsinCallback() const { + return multi_shm()->gapPixels; +} + +void DetectorImpl::setGapPixelsinCallback(const bool enable) { + if (enable) { + switch (multi_shm()->multiDetectorType) { + case JUNGFRAU: + break; + case EIGER: + if (size() && detectors[0]->getQuad()) { + break; + } + if (multi_shm()->numberOfDetector.y % 2 != 0) { + throw RuntimeError("Gap pixels can only be used " + "for full modules."); + } + break; + default: + throw RuntimeError("Gap Pixels is not implemented for " + + multi_shm()->multiDetectorType); + } } + multi_shm()->gapPixels = enable; } int DetectorImpl::createReceivingDataSockets(const bool destroy) { @@ -406,11 +420,13 @@ int DetectorImpl::createReceivingDataSockets(const bool destroy) { void DetectorImpl::readFrameFromReceiver() { + bool gapPixels = multi_shm()->gapPixels; + LOG(logDEBUG) << "Gap pixels: " << gapPixels; + int nX = 0; int nY = 0; int nDetPixelsX = 0; int nDetPixelsY = 0; - bool gappixelsenable = false; bool quadEnable = false; bool eiger = false; bool numInterfaces = @@ -434,6 +450,7 @@ void DetectorImpl::readFrameFromReceiver() { } int numConnected = numRunning; bool data = false; + bool completeImage = false; char *image = nullptr; char *multiframe = nullptr; char *multigappixels = nullptr; @@ -461,6 +478,7 @@ void DetectorImpl::readFrameFromReceiver() { if (multiframe != nullptr) { memset(multiframe, 0xFF, multisize); } + completeImage = true; // get each frame for (unsigned int isocket = 0; isocket < zmqSocket.size(); ++isocket) { @@ -470,9 +488,9 @@ void DetectorImpl::readFrameFromReceiver() { // HEADER { - rapidjson::Document doc; + zmqHeader zHeader; if (zmqSocket[isocket]->ReceiveHeader( - isocket, doc, SLS_DETECTOR_JSON_HEADER_VERSION) == + isocket, zHeader, SLS_DETECTOR_JSON_HEADER_VERSION) == 0) { // parse error, version error or end of acquisition for // socket @@ -484,33 +502,29 @@ void DetectorImpl::readFrameFromReceiver() { // if first message, allocate (all one time stuff) if (image == nullptr) { // allocate - size = doc["size"].GetUint(); + size = zHeader.imageSize; multisize = size * zmqSocket.size(); image = new char[size]; multiframe = new char[multisize]; memset(multiframe, 0xFF, multisize); // dynamic range - dynamicRange = doc["bitmode"].GetUint(); + dynamicRange = zHeader.dynamicRange; bytesPerPixel = (float)dynamicRange / 8; // shape - nPixelsX = doc["shape"][0].GetUint(); - nPixelsY = doc["shape"][1].GetUint(); + nPixelsX = zHeader.npixelsx; + nPixelsY = zHeader.npixelsy; // detector shape - nX = doc["detshape"][0].GetUint(); - nY = doc["detshape"][1].GetUint(); + nX = zHeader.ndetx; + nY = zHeader.ndety; nY *= numInterfaces; nDetPixelsX = nX * nPixelsX; nDetPixelsY = nY * nPixelsY; // det type - eiger = - (doc["detType"].GetUint() == static_cast(3)) + eiger = (zHeader.detType == static_cast(3)) ? true : false; // to be changed to EIGER when firmware // updates its header data - gappixelsenable = - (doc["gappixels"].GetUint() == 0) ? false : true; - quadEnable = - (doc["quad"].GetUint() == 0) ? false : true; + quadEnable = (zHeader.quad == 0) ? false : true; LOG(logDEBUG1) << "One Time Header Info:" "\n\tsize: " @@ -520,21 +534,23 @@ void DetectorImpl::readFrameFromReceiver() { << "\n\tnPixelsX: " << nPixelsX << "\n\tnPixelsY: " << nPixelsY << "\n\tnX: " << nX << "\n\tnY: " << nY << "\n\teiger: " << eiger - << "\n\tgappixelsenable: " << gappixelsenable << "\n\tquadEnable: " << quadEnable; } // each time, parse rest of header - currentFileName = doc["fname"].GetString(); - currentAcquisitionIndex = doc["acqIndex"].GetUint64(); - currentFrameIndex = doc["fIndex"].GetUint64(); - currentFileIndex = doc["fileIndex"].GetUint64(); - currentSubFrameIndex = doc["expLength"].GetUint(); - coordY = doc["row"].GetUint(); - coordX = doc["column"].GetUint(); + currentFileName = zHeader.fname; + currentAcquisitionIndex = zHeader.acqIndex; + currentFrameIndex = zHeader.frameIndex; + currentFileIndex = zHeader.fileIndex; + currentSubFrameIndex = zHeader.expLength; + coordY = zHeader.row; + coordX = zHeader.column; if (eiger) { coordY = (nY - 1) - coordY; } - flippedDataX = doc["flippedDataX"].GetUint(); + flippedDataX = zHeader.flippedDataX; + if (zHeader.completeImage == 0) { + completeImage = false; + } LOG(logDEBUG1) << "Header Info:" "\n\tcurrentFileName: " @@ -544,12 +560,14 @@ void DetectorImpl::readFrameFromReceiver() { << "\n\tcurrentFileIndex: " << currentFileIndex << "\n\tcurrentSubFrameIndex: " << currentSubFrameIndex << "\n\tcoordX: " << coordX << "\n\tcoordY: " << coordY - << "\n\tflippedDataX: " << flippedDataX; + << "\n\tflippedDataX: " << flippedDataX + << "\n\tcompleteImage: " << completeImage; } // DATA data = true; zmqSocket[isocket]->ReceiveData(isocket, image, size); + // creating multi image { uint32_t xoffset = coordX * nPixelsX * bytesPerPixel; @@ -586,43 +604,36 @@ void DetectorImpl::readFrameFromReceiver() { } } } + LOG(logDEBUG)<< "Call Back Info:" << "\n\t nDetPixelsX: " << nDetPixelsX << "\n\t nDetPixelsY: " << nDetPixelsY << "\n\t databytes: " << multisize - << "\n\t dynamicRange: " << dynamicRange ; + << "\n\t dynamicRange: " << dynamicRange; // send data to callback if (data) { setCurrentProgress(currentFrameIndex + 1); - // 4bit gap pixels - if (dynamicRange == 4 && gappixelsenable) { - if (quadEnable) { - nDetPixelsX += 2; - nDetPixelsY += 2; - } else { - nDetPixelsX = nX * (nPixelsX + 3); - nDetPixelsY = nY * (nPixelsY + 1); - } - int n = processImageWithGapPixels(multiframe, multigappixels, - quadEnable); - LOG(logDEBUG) - << "Call Back Info Recalculated:" - << "\n\t nDetPixelsX: " << nDetPixelsX - << "\n\t nDetPixelsY: " << nDetPixelsY - << "\n\t databytes: " << n; - thisData = - new detectorData(getCurrentProgress(), currentFileName, - nDetPixelsX, nDetPixelsY, multigappixels, - n, dynamicRange, currentFileIndex); - } - // normal pixels - else { - thisData = - new detectorData(getCurrentProgress(), currentFileName, - nDetPixelsX, nDetPixelsY, multiframe, - multisize, dynamicRange, currentFileIndex); + char* image = multiframe; + int imagesize = multisize; + + if (gapPixels) { + int n = InsertGapPixels(multiframe, multigappixels, + quadEnable, dynamicRange, nDetPixelsX, nDetPixelsY); + image = multigappixels; + imagesize = n; } + LOG(logDEBUG) + << "Image Info:" + << "\n\tnDetPixelsX: " << nDetPixelsX + << "\n\tnDetPixelsY: " << nDetPixelsY + << "\n\timagesize: " << imagesize + << "\n\tdynamicRange: " << dynamicRange; + + thisData = new detectorData(getCurrentProgress(), + currentFileName, nDetPixelsX, nDetPixelsY, image, + imagesize, dynamicRange, currentFileIndex, completeImage); + dataReady( thisData, currentFrameIndex, ((dynamicRange == 32 && eiger) ? currentSubFrameIndex : -1), @@ -667,141 +678,301 @@ void DetectorImpl::readFrameFromReceiver() { delete[] multigappixels; } -int DetectorImpl::processImageWithGapPixels(char *image, char *&gpImage, - bool quadEnable) { - // eiger 4 bit mode - int nxb = - multi_shm()->numberOfDetector.x * (512 + 3); //(divided by 2 already) - int nyb = multi_shm()->numberOfDetector.y * (256 + 1); - int nchipInRow = 4; - int nxchip = multi_shm()->numberOfDetector.x * 4; - int nychip = multi_shm()->numberOfDetector.y * 1; +int DetectorImpl::InsertGapPixels(char *image, char *&gpImage, + bool quadEnable, int dr, int &nPixelsx, int &nPixelsy) { + + LOG(logDEBUG)<< "Insert Gap pixels:" + << "\n\t nPixelsx: " << nPixelsx + << "\n\t nPixelsy: " << nPixelsy + << "\n\t quadEnable: " << quadEnable + << "\n\t dr: " << dr; + + // inter module gap pixels + int modGapPixelsx = 8; + int modGapPixelsy = 36; + // inter chip gap pixels + int chipGapPixelsx = 2; + int chipGapPixelsy = 2; + // number of pixels in a chip + int nChipPixelsx = 256; + int nChipPixelsy = 256; + // 1 module + // number of chips in a module + int nMod1Chipx = 4; + int nMod1Chipy = 2; if (quadEnable) { - nxb = multi_shm()->numberOfDetector.x * - (256 + 1); //(divided by 2 already) - nyb = multi_shm()->numberOfDetector.y * (512 + 2); - nxchip /= 2; - nychip *= 2; - nchipInRow /= 2; + nMod1Chipx = 2; } - int gapdatabytes = nxb * nyb; + // number of pixels in a module + int nMod1Pixelsx = nChipPixelsx * nMod1Chipx; + int nMod1Pixelsy = nChipPixelsy * nMod1Chipy; + // number of gap pixels in a module + int nMod1GapPixelsx = (nMod1Chipx - 1) * chipGapPixelsx; + int nMod1GapPixelsy = (nMod1Chipy - 1) * chipGapPixelsy; + // total number of modules + int nModx = nPixelsx / nMod1Pixelsx; + int nMody = nPixelsy / nMod1Pixelsy; - // allocate - if (gpImage == nullptr) { - gpImage = new char[gapdatabytes]; + // check if not full modules + // (setting gap pixels and then adding half module or disabling quad) + if (nPixelsy / nMod1Pixelsy == 0) { + LOG(logERROR) << "Gap pixels can only be enabled with full modules. " + "Sending dummy data without gap pixels.\n"; + double bytesPerPixel = (double)dr / 8.00; + int imagesize = nPixelsy * nPixelsx * bytesPerPixel; + if (gpImage == NULL) { + gpImage = new char[imagesize]; + } + memset(gpImage, 0xFF, imagesize); + return imagesize; } - // fill value - memset(gpImage, 0xFF, gapdatabytes); - const int b1chipx = 128; - const int b1chipy = 256; + // total number of pixels + int nTotx = nPixelsx + (nMod1GapPixelsx * nModx) + (modGapPixelsx * (nModx - 1)); + int nToty = nPixelsy + (nMod1GapPixelsy * nMody) + (modGapPixelsy * (nMody - 1)); + // total number of chips + int nChipx = nPixelsx / nChipPixelsx; + int nChipy = nPixelsy / nChipPixelsy; + + double bytesPerPixel = (double)dr / 8.00; + int imagesize = nTotx * nToty * bytesPerPixel; + + int nChipBytesx = nChipPixelsx * bytesPerPixel; // 1 chip bytes in x + int nChipGapBytesx = chipGapPixelsx * bytesPerPixel; // 2 pixel bytes + int nModGapBytesx = modGapPixelsx * bytesPerPixel; // 8 pixel bytes + int nChipBytesy = nChipPixelsy * nTotx * bytesPerPixel; // 1 chip bytes in y + int nChipGapBytesy = chipGapPixelsy * nTotx * bytesPerPixel; // 2 lines + int nModGapBytesy = modGapPixelsy * nTotx * bytesPerPixel; // 36 lines + // 4 bit mode, its 1 byte (because for 4 bit mode, we handle 1 byte at a time) + int pixel1 = (int)(ceil(bytesPerPixel)); + int row1Bytes = nTotx * bytesPerPixel; + int nMod1TotPixelsx = nMod1Pixelsx + nMod1GapPixelsx; + if (dr == 4) { + nMod1TotPixelsx /= 2; + } + // eiger requires inter chip gap pixels are halved + // jungfrau prefers same inter chip gap pixels as the boundary pixels + int divisionValue = 2; + slsDetectorDefs::detectorType detType = multi_shm()->multiDetectorType; + if (detType == JUNGFRAU) { + divisionValue = 1; + } + LOG(logDEBUG) + << "Insert Gap pixels Calculations:\n\t" + << "nPixelsx: " << nPixelsx << "\n\t" + << "nPixelsy: " << nPixelsy << "\n\t" + << "nMod1Pixelsx: " << nMod1Pixelsx << "\n\t" + << "nMod1Pixelsy: " << nMod1Pixelsy << "\n\t" + << "nMod1GapPixelsx: " << nMod1GapPixelsx << "\n\t" + << "nMod1GapPixelsy: " << nMod1GapPixelsy << "\n\t" + << "nChipy: " << nChipy << "\n\t" + << "nChipx: " << nChipx << "\n\t" + << "nModx: " << nModx << "\n\t" + << "nMody: " << nMody << "\n\t" + << "nTotx: " << nTotx << "\n\t" + << "nToty: " << nToty << "\n\t" + << "bytesPerPixel: " << bytesPerPixel << "\n\t" + << "imagesize: " << imagesize << "\n\t" + << "nChipBytesx: " << nChipBytesx << "\n\t" + << "nChipGapBytesx: " << nChipGapBytesx << "\n\t" + << "nModGapBytesx: " << nModGapBytesx << "\n\t" + << "nChipBytesy: " << nChipBytesy << "\n\t" + << "nChipGapBytesy: " << nChipGapBytesy << "\n\t" + << "nModGapBytesy: " << nModGapBytesy << "\n\t" + << "pixel1: " << pixel1 << "\n\t" + << "row1Bytes: " << row1Bytes << "\n\t" + << "nMod1TotPixelsx: " << nMod1TotPixelsx << "\n\t" + << "divisionValue: " << divisionValue << "\n\n"; + + if (gpImage == NULL) { + gpImage = new char[imagesize]; + } + memset(gpImage, 0xFF, imagesize); + //memcpy(gpImage, image, imagesize); char *src = nullptr; char *dst = nullptr; // copying line by line src = image; dst = gpImage; - for (int row = 0; row < nychip; ++row) { // for each chip row - for (int ichipy = 0; ichipy < b1chipy; - ++ichipy) { // for each row in a chip - for (int col = 0; col < nxchip; ++col) { // for each chip in a row - memcpy(dst, src, b1chipx); - src += b1chipx; - dst += b1chipx; - if (((col + 1) % nchipInRow) != 0) { // skip gap pixels - ++dst; + // for each chip row in y + for (int iChipy = 0; iChipy < nChipy; ++iChipy) { + // for each row + for (int iy = 0; iy < nChipPixelsy; ++iy) { + // in each row, for every chip + for (int iChipx = 0; iChipx < nChipx; ++iChipx) { + // copy 1 chip line + memcpy(dst, src, nChipBytesx); + src += nChipBytesx; + dst += nChipBytesx; + // skip inter chip gap pixels in x + if (((iChipx + 1) % nMod1Chipx) != 0) { + dst += nChipGapBytesx; + } + // skip inter module gap pixels in x + else if (iChipx + 1 != nChipx) { + dst += nModGapBytesx; } } } - - dst += (2 * nxb); + // skip inter chip gap pixels in y + if (((iChipy + 1) % nMod1Chipy) != 0) { + dst += nChipGapBytesy; + } + // skip inter module gap pixels in y + else if (iChipy + 1 != nChipy) { + dst += nModGapBytesy; + } } - // vertical filling of values - { - uint8_t temp, g1, g2; - int mod; - dst = gpImage; - for (int row = 0; row < nychip; ++row) { // for each chip row - for (int ichipy = 0; ichipy < b1chipy; - ++ichipy) { // for each row in a chip - for (int col = 0; col < nxchip; - ++col) { // for each chip in a row - dst += b1chipx; - mod = (col + 1) % nchipInRow; // get gap pixels - // copy gap pixel(chip 0, 1, 2) - if (mod != 0) { + // iner chip gap pixel values is half of neighboring one + // (corners becomes divide by 4 automatically after horizontal filling) + + // vertical filling of inter chip gap pixels + dst = gpImage; + // for each chip row in y + for (int iChipy = 0; iChipy < nChipy; ++iChipy) { + // for each row + for (int iy = 0; iy < nChipPixelsy; ++iy) { + // in each row, for every chip + for (int iChipx = 0; iChipx < nChipx; ++iChipx) { + // go to gap pixels + dst += nChipBytesx; + // fix inter chip gap pixels in x + if (((iChipx + 1) % nMod1Chipx) != 0) { + uint8_t temp8 = 0; + uint16_t temp16 = 0; + uint32_t temp32 = 0; + uint8_t g1 = 0; + uint8_t g2 = 0; + switch (dr) { + case 4: // neighbouring gap pixels to left - temp = (*((uint8_t *)(dst - 1))); - g1 = ((temp & 0xF) / 2); - (*((uint8_t *)(dst - 1))) = (temp & 0xF0) + g1; - + temp8 = (*((uint8_t *)(dst - 1))); + g1 = ((temp8 & 0xF) / 2); + (*((uint8_t *)(dst - 1))) = (temp8 & 0xF0) + g1; // neighbouring gap pixels to right - temp = (*((uint8_t *)(dst + 1))); - g2 = ((temp >> 4) / 2); - (*((uint8_t *)(dst + 1))) = (g2 << 4) + (temp & 0x0F); - + temp8 = (*((uint8_t *)(dst + 1))); + g2 = ((temp8 >> 4) / 2); + (*((uint8_t *)(dst + 1))) = (g2 << 4) + (temp8 & 0x0F); // gap pixels - (*((uint8_t *)dst)) = (g1 << 4) + g2; - - // increment to point to proper chip destination - ++dst; - } + (*((uint8_t *)dst)) = (g1 << 4) + g2; + break; + case 8: + // neighbouring gap pixels to left + temp8 = (*((uint8_t *)(dst - pixel1))) / 2; + (*((uint8_t *)dst)) = temp8; + (*((uint8_t *)(dst - pixel1))) = temp8; + // neighbouring gap pixels to right + temp8 = (*((uint8_t *)(dst + 2 * pixel1))) / 2; + (*((uint8_t *)(dst + pixel1))) = temp8; + (*((uint8_t *)(dst + 2 * pixel1))) = temp8; + break; + case 16: + // neighbouring gap pixels to left + temp16 = (*((uint16_t *)(dst - pixel1))) / divisionValue; + (*((uint16_t *)dst)) = temp16; + (*((uint16_t *)(dst - pixel1))) = temp16; + // neighbouring gap pixels to right + temp16 = (*((uint16_t *)(dst + 2 * pixel1))) / divisionValue; + (*((uint16_t *)(dst + pixel1))) = temp16; + (*((uint16_t *)(dst + 2 * pixel1))) = temp16; + break; + default: + // neighbouring gap pixels to left + temp32 = (*((uint32_t *)(dst - pixel1))) / 2; + (*((uint32_t *)dst)) = temp32; + (*((uint32_t *)(dst - pixel1))) = temp32; + // neighbouring gap pixels to right + temp32 = (*((uint32_t *)(dst + 2 * pixel1))) / 2; + (*((uint32_t *)(dst + pixel1))) = temp32; + (*((uint32_t *)(dst + 2 * pixel1))) = temp32; + break; + } + dst += nChipGapBytesx; + } + // skip inter module gap pixels in x + else if (iChipx + 1 != nChipx) { + dst += nModGapBytesx; } } + } + // skip inter chip gap pixels in y + if (((iChipy + 1) % nMod1Chipy) != 0) { + dst += nChipGapBytesy; + } + // skip inter module gap pixels in y + else if (iChipy + 1 != nChipy) { + dst += nModGapBytesy; + } + } - dst += (2 * nxb); + // horizontal filling of inter chip gap pixels + // starting at bottom part (1 line below to copy from) + src = gpImage + (nChipBytesy - row1Bytes); + dst = gpImage + nChipBytesy; + // for each chip row in y + for (int iChipy = 0; iChipy < nChipy; ++iChipy) { + // for each module in x + for (int iModx = 0; iModx < nModx; ++iModx) { + // in each module, for every pixel in x + for (int iPixel = 0; iPixel < nMod1TotPixelsx; ++iPixel) { + uint8_t temp8 = 0, g1 = 0, g2 = 0; + uint16_t temp16 = 0; + uint32_t temp32 = 0; + switch (dr) { + case 4: + temp8 = (*((uint8_t *)src)); + g1 = ((temp8 >> 4) / 2); + g2 = ((temp8 & 0xF) / 2); + temp8 = (g1 << 4) + g2; + (*((uint8_t *)dst)) = temp8; + (*((uint8_t *)src)) = temp8; + break; + case 8: + temp8 = (*((uint8_t *)src)) / divisionValue; + (*((uint8_t *)dst)) = temp8; + (*((uint8_t *)src)) = temp8; + break; + case 16: + temp16 = (*((uint16_t *)src)) / divisionValue; + (*((uint16_t *)dst)) = temp16; + (*((uint16_t *)src)) = temp16; + break; + default: + temp32 = (*((uint32_t *)src)) / 2; + (*((uint32_t *)dst)) = temp32; + (*((uint32_t *)src)) = temp32; + break; + } + // every pixel (but 4 bit mode, every byte) + src += pixel1; + dst += pixel1; + } + // skip inter module gap pixels in x + if (iModx + 1 < nModx) { + src += nModGapBytesx; + dst += nModGapBytesx; + } + } + // bottom parts, skip inter chip gap pixels + if ((iChipy % nMod1Chipy) == 0) { + src += nChipGapBytesy; + } + // top parts, skip inter module gap pixels and two chips + else { + src += (nModGapBytesy + 2 * nChipBytesy - 2 * row1Bytes); + dst += (nModGapBytesy + 2 * nChipBytesy); } } - // return gapdatabytes; - // horizontal filling - { - uint8_t temp, g1, g2; - char *dst_prevline = nullptr; - dst = gpImage; - for (int row = 0; row < nychip; ++row) { // for each chip row - dst += (b1chipy * nxb); - // horizontal copying of gap pixels from neighboring past line - // (bottom parts) - if (row < nychip - 1) { - dst_prevline = dst - nxb; - for (int gapline = 0; gapline < nxb; ++gapline) { - temp = (*((uint8_t *)dst_prevline)); - g1 = ((temp >> 4) / 2); - g2 = ((temp & 0xF) / 2); - (*((uint8_t *)dst_prevline)) = (g1 << 4) + g2; - (*((uint8_t *)dst)) = (*((uint8_t *)dst_prevline)); - ++dst; - ++dst_prevline; - } - } - - // horizontal copying of gap pixels from neihboring future line (top - // part) - if (row > 0) { - dst -= ((b1chipy + 1) * nxb); - dst_prevline = dst + nxb; - for (int gapline = 0; gapline < nxb; ++gapline) { - temp = (*((uint8_t *)dst_prevline)); - g1 = ((temp >> 4) / 2); - g2 = ((temp & 0xF) / 2); - temp = (g1 << 4) + g2; - (*((uint8_t *)dst_prevline)) = temp; - (*((uint8_t *)dst)) = temp; - ++dst; - ++dst_prevline; - } - dst += ((b1chipy + 1) * nxb); - } - - dst += nxb; - } - } - - return gapdatabytes; + nPixelsx = nTotx; + nPixelsy = nToty; + return imagesize; } + + bool DetectorImpl::enableDataStreamingToClient(int enable) { if (enable >= 0) { // destroy data threads diff --git a/slsDetectorSoftware/src/DetectorImpl.h b/slsDetectorSoftware/src/DetectorImpl.h index 107aada8a..d39e95a34 100755 --- a/slsDetectorSoftware/src/DetectorImpl.h +++ b/slsDetectorSoftware/src/DetectorImpl.h @@ -16,7 +16,7 @@ class detectorData; #include #define MULTI_SHMAPIVERSION 0x190809 -#define MULTI_SHMVERSION 0x200131 +#define MULTI_SHMVERSION 0x200319 #define SHORT_STRING_LENGTH 50 #include @@ -47,10 +47,7 @@ struct sharedMultiSlsDetector { /** last time stamp when accessing the shared memory */ char lastDate[SHORT_STRING_LENGTH]; - /** number of sls detectors in shared memory */ int numberOfDetectors; - - /** multi detector type */ slsDetectorDefs::detectorType multiDetectorType; /** END OF FIXED PATTERN @@ -62,11 +59,9 @@ struct sharedMultiSlsDetector { /** max number of channels for complete detector*/ slsDetectorDefs::xy numberOfChannels; - /** flag for acquiring */ bool acquiringFlag; - - /** initial checks */ bool initialChecks; + bool gapPixels; }; class DetectorImpl : public virtual slsDetectorDefs { @@ -236,11 +231,10 @@ class DetectorImpl : public virtual slsDetectorDefs { * Sets maximum number of channels of all sls detectors */ void setNumberOfChannels(const slsDetectorDefs::xy c); - /** - * Enable gap pixels, only for Eiger and for 8,16 and 32 bit mode. (Eiger) - * 4 bit mode gap pixels only in gui call back - */ - void setGapPixelsinReceiver(bool enable); + /** [Eiger][Jungfrau] */ + bool getGapPixelsinCallback() const; + /** [Eiger][Jungfrau] */ + void setGapPixelsinCallback(const bool enable); /** * Enable data streaming to client @@ -347,15 +341,18 @@ class DetectorImpl : public virtual slsDetectorDefs { */ void readFrameFromReceiver(); - /** - * add gap pixels to the image (only for Eiger in 4 bit mode) + /** [Eiger][Jungfrau] + * add gap pixels to the imag * @param image pointer to image without gap pixels * @param gpImage poiner to image with gap pixels, if NULL, allocated - * inside function - * quadEnable quad enabled - * @returns number of data bytes of image with gap pixels + * @param quadEnable quad enabled + * @param dr dynamic range + * @param nPixelsx number of pixels in X axis (updated) + * @param nPixelsy number of pixels in Y axis (updated) + * @returns total data bytes for updated image */ - int processImageWithGapPixels(char *image, char *&gpImage, bool quadEnable); + int InsertGapPixels(char *image, char *&gpImage, bool quadEnable, int dr, + int &nPixelsx, int &nPixelsy); double setTotalProgress(); diff --git a/slsDetectorSoftware/src/Module.cpp b/slsDetectorSoftware/src/Module.cpp index 02018569d..0804e8f8d 100755 --- a/slsDetectorSoftware/src/Module.cpp +++ b/slsDetectorSoftware/src/Module.cpp @@ -410,7 +410,6 @@ void Module::initializeDetectorStructure(detectorType type) { shm()->zmqport = DEFAULT_ZMQ_CL_PORTNO + (detId * ((shm()->myDetectorType == EIGER) ? 2 : 1)); shm()->zmqip = IpAddr{}; - shm()->gappixels = 0U; shm()->numUDPInterfaces = 1; shm()->stoppedFlag = false; @@ -422,8 +421,6 @@ void Module::initializeDetectorStructure(detectorType type) { shm()->nChip.y = parameters.nChipY; shm()->nDacs = parameters.nDacs; shm()->dynamicRange = parameters.dynamicRange; - shm()->nGappixels.x = parameters.nGappixelsX; - shm()->nGappixels.y = parameters.nGappixelsY; } int Module::sendModule(sls_detector_module *myMod, @@ -582,10 +579,8 @@ void Module::updateNumberOfChannels() { slsDetectorDefs::xy Module::getNumberOfChannels() const { slsDetectorDefs::xy coord{}; - coord.x = (shm()->nChan.x * shm()->nChip.x + - shm()->gappixels * shm()->nGappixels.x); - coord.y = (shm()->nChan.y * shm()->nChip.y + - shm()->gappixels * shm()->nGappixels.y); + coord.x = (shm()->nChan.x * shm()->nChip.x); + coord.y = (shm()->nChan.y * shm()->nChip.y); return coord; } @@ -937,23 +932,17 @@ int Module::getThresholdEnergy() { return retval; } -int Module::setThresholdEnergy(int e_eV, detectorSettings isettings, +void Module::setThresholdEnergy(int e_eV, detectorSettings isettings, int tb) { // check as there is client processing if (shm()->myDetectorType == EIGER) { setThresholdEnergyAndSettings(e_eV, isettings, tb); - return e_eV; } // moench - send threshold energy to processor else if (shm()->myDetectorType == MOENCH) { - std::string result = - setAdditionalJsonParameter("threshold", std::to_string(e_eV)); - if (result == std::to_string(e_eV)) { - return e_eV; - } - return -1; + setAdditionalJsonParameter("threshold", std::to_string(e_eV)); } throw RuntimeError( "Set threshold energy not implemented for this detector"); @@ -1719,7 +1708,6 @@ std::string Module::setReceiverHostname(const std::string &receiverIP) { setSubDeadTime(getSubDeadTime()); setDynamicRange(shm()->dynamicRange); activate(-1); - enableGapPixels(shm()->gappixels); enableTenGigabitEthernet(-1); setQuad(getQuad()); break; @@ -2105,106 +2093,99 @@ void Module::setTransmissionDelayRight(int value) { } -void Module::setAdditionalJsonHeader(const std::string &jsonheader) { +void Module::setAdditionalJsonHeader(const std::map &jsonHeader) { if (!shm()->useReceiverFlag) { throw RuntimeError("Set rx_hostname first to use receiver parameters (zmq json header)"); } - char args[MAX_STR_LENGTH]{}; - sls::strcpy_safe(args, jsonheader.c_str()); - sendToReceiver(F_SET_ADDITIONAL_JSON_HEADER, args, nullptr); -} - -std::string Module::getAdditionalJsonHeader() { - if (!shm()->useReceiverFlag) { - throw RuntimeError("Set rx_hostname first to use receiver parameters (zmq json header)"); - } - char retvals[MAX_STR_LENGTH]{}; - sendToReceiver(F_GET_ADDITIONAL_JSON_HEADER, nullptr, retvals); - return std::string(retvals); -} - -std::string Module::setAdditionalJsonParameter(const std::string &key, - const std::string &value) { - if (key.empty() || value.empty()) { - throw RuntimeError( - "Could not set additional json header parameter as the key or " - "value is empty"); - } - - // validation (ignore if key or value has , : ") - if (key.find_first_of(",\":") != std::string::npos || - value.find_first_of(",\":") != std::string::npos) { - throw RuntimeError("Could not set additional json header parameter as " - "the key or value has " - "illegal characters (,\":)"); - } - - // create actual key to search for and actual value to put, (key has - // additional ':' as value could exist the same way) - std::string keyLiteral(std::string("\"") + key + std::string("\":")); - std::string valueLiteral(value); - // add quotations to value only if it is a string - try { - std::stoi(valueLiteral); - } catch (...) { - // add quotations if it failed to convert to integer, otherwise nothing - valueLiteral.insert(0, "\""); - valueLiteral.append("\""); - } - - std::string header = getAdditionalJsonHeader(); - size_t keyPos = header.find(keyLiteral); - - // if key found, replace value - if (keyPos != std::string::npos) { - size_t valueStartPos = header.find(std::string(":"), keyPos) + 1; - size_t valueEndPos = header.find(std::string(","), valueStartPos) - 1; - // if valueEndPos doesnt find comma (end of string), it goes anyway to - // end of line - header.replace(valueStartPos, valueEndPos - valueStartPos + 1, - valueLiteral); - } - - // key not found, append key value pair - else { - if (header.length() != 0U) { - header.append(","); + for (auto &it : jsonHeader) { + if (it.first.empty() || it.first.length() > SHORT_STR_LENGTH || + it.second.length() > SHORT_STR_LENGTH ) { + throw RuntimeError(it.first + " or " + it.second + " pair has invalid size. " + "Key cannot be empty. Both can have max 20 characters"); } - header.append(keyLiteral + valueLiteral); } + const int size = jsonHeader.size(); + int fnum = F_SET_ADDITIONAL_JSON_HEADER; + int ret = FAIL; + LOG(logDEBUG) << "Sending to receiver additional json header " << ToString(jsonHeader); + auto client = ReceiverSocket(shm()->rxHostname, shm()->rxTCPPort); + client.Send(&fnum, sizeof(fnum)); + client.Send(&size, sizeof(size)); + if (size > 0) { + char args[size * 2][SHORT_STR_LENGTH]; + memset(args, 0, sizeof(args)); + int iarg = 0; + for (auto &it : jsonHeader) { + sls::strcpy_safe(args[iarg], it.first.c_str()); + sls::strcpy_safe(args[iarg + 1], it.second.c_str()); + iarg += 2; + } + client.Send(args, sizeof(args)); + } + client.Receive(&ret, sizeof(ret)); + if (ret == FAIL) { + char mess[MAX_STR_LENGTH]{}; + client.Receive(mess, MAX_STR_LENGTH); + throw RuntimeError("Receiver " + std::to_string(detId) + + " returned error: " + std::string(mess)); + } +} - // update additional json header - setAdditionalJsonHeader(header); - return getAdditionalJsonParameter(key); +std::map Module::getAdditionalJsonHeader() { + if (!shm()->useReceiverFlag) { + throw RuntimeError("Set rx_hostname first to use receiver parameters (zmq json header)"); + } + int fnum = F_GET_ADDITIONAL_JSON_HEADER; + int ret = FAIL; + int size = 0; + auto client = ReceiverSocket(shm()->rxHostname, shm()->rxTCPPort); + client.Send(&fnum, sizeof(fnum)); + client.Receive(&ret, sizeof(ret)); + if (ret == FAIL) { + char mess[MAX_STR_LENGTH]{}; + client.Receive(mess, MAX_STR_LENGTH); + throw RuntimeError("Receiver " + std::to_string(detId) + + " returned error: " + std::string(mess)); + } else { + client.Receive(&size, sizeof(size)); + std::map retval; + if (size > 0) { + char retvals[size * 2][SHORT_STR_LENGTH]; + memset(retvals, 0, sizeof(retvals)); + client.Receive(retvals, sizeof(retvals)); + for (int i = 0; i < size; ++i) { + retval[retvals[2 * i]] = retvals[2 * i + 1]; + } + } + LOG(logDEBUG) << "Getting additional json header " << ToString(retval); + return retval; + } +} + +void Module::setAdditionalJsonParameter(const std::string &key, const std::string &value) { + if (!shm()->useReceiverFlag) { + throw RuntimeError("Set rx_hostname first to use receiver parameters (zmq json parameter)"); + } + if (key.empty() || key.length() > SHORT_STR_LENGTH || + value.length() > SHORT_STR_LENGTH ) { + throw RuntimeError(key + " or " + value + " pair has invalid size. " + "Key cannot be empty. Both can have max 2 characters"); + } + char args[2][SHORT_STR_LENGTH]{}; + sls::strcpy_safe(args[0], key.c_str()); + sls::strcpy_safe(args[1], value.c_str()); + sendToReceiver(F_SET_ADDITIONAL_JSON_PARAMETER, args, nullptr); } std::string Module::getAdditionalJsonParameter(const std::string &key) { - // additional json header is empty - std::string jsonheader = getAdditionalJsonHeader(); - if (jsonheader.empty()) - return jsonheader; - - // add quotations before and after the key value - std::string keyLiteral = key; - keyLiteral.insert(0, "\""); - keyLiteral.append("\""); - - // loop through the parameters - for (const auto ¶meter : - sls::split(jsonheader, ',')) { - // get a vector of key value pair for each parameter - const auto &pairs = sls::split(parameter, ':'); - // match for key - if (pairs[0] == keyLiteral) { - // return value without quotations (if it has any) - if (pairs[1][0] == '\"') - return pairs[1].substr(1, pairs[1].length() - 2); - else - return pairs[1]; - } + if (!shm()->useReceiverFlag) { + throw RuntimeError("Set rx_hostname first to use receiver parameters (zmq json parameter)"); } - // return empty string as no match found with key - return std::string(); + char arg[SHORT_STR_LENGTH]{}; + sls::strcpy_safe(arg, key.c_str()); + char retval[SHORT_STR_LENGTH]{}; + sendToReceiver(F_GET_ADDITIONAL_JSON_PARAMETER, arg, retval); + return retval; } int64_t Module::setReceiverUDPSocketBufferSize(int64_t udpsockbufsize) { @@ -2672,24 +2653,6 @@ int Module::setAllTrimbits(int val) { return retval; } -int Module::enableGapPixels(int val) { - if (val >= 0) { - if (shm()->myDetectorType != EIGER) { - throw NotImplementedError( - "Function (enableGapPixels) not implemented for this detector"); - } - int fnum = F_ENABLE_GAPPIXELS_IN_RECEIVER; - int retval = -1; - LOG(logDEBUG1) << "Sending gap pixels enable to receiver: " << val; - if (shm()->useReceiverFlag) { - sendToReceiver(fnum, val, retval); - LOG(logDEBUG1) << "Gap pixels enable to receiver:" << retval; - shm()->gappixels = retval; - } - } - return shm()->gappixels; -} - int Module::setTrimEn(const std::vector& energies) { if (shm()->myDetectorType != EIGER) { throw RuntimeError("setTrimEn not implemented for this detector."); @@ -3084,33 +3047,6 @@ void Module::execReceiverCommand(const std::string &cmd) { } } -void Module::updateCachedReceiverVariables() const { - int fnum = F_UPDATE_RECEIVER_CLIENT; - LOG(logDEBUG1) << "Sending update client to receiver server"; - - if (shm()->useReceiverFlag) { - auto receiver = - sls::ClientSocket("Receiver", shm()->rxHostname, shm()->rxTCPPort); - receiver.sendCommandThenRead(fnum, nullptr, 0, nullptr, 0); - int n = 0, i32 = 0; - IpAddr ip; - - n += receiver.Receive(&ip, sizeof(ip)); - LOG(logDEBUG1) - << "Updating receiver last modified by " << ip; - - // gap pixels - n += receiver.Receive(&i32, sizeof(i32)); - shm()->gappixels = i32; - - if (n == 0) { - throw RuntimeError( - "Could not update receiver: " + std::string(shm()->rxHostname) + - ", received 0 bytes\n"); - } - } -} - void Module::sendMultiDetectorSize() { int args[]{shm()->multiSize.x, shm()->multiSize.y}; int retval = -1; @@ -3317,9 +3253,6 @@ std::vector Module::getNumMissingPackets() const { throw RuntimeError("Receiver " + std::to_string(detId) + " returned error: " + std::string(mess)); } else { - if (ret == FORCE_UPDATE) { - updateCachedReceiverVariables(); - } int nports = -1; client.Receive(&nports, sizeof(nports)); uint64_t mp[nports]; diff --git a/slsDetectorSoftware/src/Module.h b/slsDetectorSoftware/src/Module.h index 1567c6165..873f43ebc 100755 --- a/slsDetectorSoftware/src/Module.h +++ b/slsDetectorSoftware/src/Module.h @@ -9,11 +9,12 @@ #include #include #include +#include class ServerInterface; #define SLS_SHMAPIVERSION 0x190726 -#define SLS_SHMVERSION 0x200318 +#define SLS_SHMVERSION 0x200324 namespace sls{ @@ -104,12 +105,6 @@ struct sharedSlsDetector { /** zmq tcp src ip address in client (only data) **/ sls::IpAddr zmqip; - /** gap pixels enable */ - int gappixels; - - /** gap pixels in each direction */ - slsDetectorDefs::xy nGappixels; - /** num udp interfaces */ int numUDPInterfaces; @@ -221,10 +216,7 @@ class Module : public virtual slsDetectorDefs { */ void updateNumberOfChannels(); - /** - * Returns the total number of channels including gap pixels - * @returns the total number of channels including gap pixels - */ + slsDetectorDefs::xy getNumberOfChannels() const; /** @@ -353,9 +345,8 @@ class Module : public virtual slsDetectorDefs { * @param e_eV threshold in eV * @param isettings ev. change settings * @param tb 1 to include trimbits, 0 to exclude - * @returns current threshold value in ev (-1 failed) */ - int setThresholdEnergy(int e_eV, detectorSettings isettings = GET_SETTINGS, + void setThresholdEnergy(int e_eV, detectorSettings isettings = GET_SETTINGS, int tb = 1); /** @@ -988,36 +979,14 @@ class Module : public virtual slsDetectorDefs { */ void setTransmissionDelayRight(int value); - /** - * Sets the additional json header\sa sharedSlsDetector - * @param jsonheader additional json header - */ - void setAdditionalJsonHeader(const std::string &jsonheader); + /** empty vector deletes entire additional json header */ + void setAdditionalJsonHeader(const std::map &jsonHeader); + std::map getAdditionalJsonHeader(); /** - * Returns the additional json header \sa sharedSlsDetector - * @returns the additional json header, returns "none" if default setting - * and no custom ip set - */ - std::string getAdditionalJsonHeader(); - - /** - * Sets the value for the additional json header parameter if found, else - * append it - * @param key additional json header parameter - * @param value additional json header parameter value (cannot be empty) - * @returns the additional json header parameter value, - * empty if no parameter found in additional json header - */ - std::string setAdditionalJsonParameter(const std::string &key, - const std::string &value); - - /** - * Returns the additional json header parameter value - * @param key additional json header parameter - * @returns the additional json header parameter value, - * empty if no parameter found in additional json header - */ + * Sets the value for the additional json header parameter key if found, else + * append it. If value empty, then deletes parameter */ + void setAdditionalJsonParameter(const std::string &key, const std::string &value); std::string getAdditionalJsonParameter(const std::string &key); /** @@ -1045,11 +1014,13 @@ class Module : public virtual slsDetectorDefs { /** [Gotthard][Jungfrau][CTB][Moench] */ void executeBusTest(); - /** [Gotthard] */ + /** [Gotthard][Eiger virtual] */ int getImageTestMode(); /** [Gotthard] If 1, adds channel intensity with precalculated values. - * Default is 0 */ + * Default is 0 + * [Eiger virtual] If 1, pixels are saturated. If 0, increasing intensity + * Only for virtual servers */ void setImageTestMode(const int value); @@ -1232,14 +1203,6 @@ class Module : public virtual slsDetectorDefs { */ int setAllTrimbits(int val); - /** - * Enable gap pixels, only for Eiger and for 8,16 and 32 bit mode. (Eiger) - * 4 bit mode gap pixels only in gui call back - * @param val 1 sets, 0 unsets, -1 gets - * @returns gap pixel enable or -1 for error - */ - int enableGapPixels(int val = -1); - /** * Sets the number of trim energies and their value (Eiger) * \sa sharedSlsDetector @@ -1436,11 +1399,6 @@ class Module : public virtual slsDetectorDefs { */ void execReceiverCommand(const std::string &cmd); - /** - * Updates the shared memory receiving the data from the detector - */ - void updateCachedReceiverVariables() const; - /** * Send the multi detector size to the detector * @param detx number of detectors in x dir diff --git a/slsDetectorSoftware/tests/test-CmdProxy-rx.cpp b/slsDetectorSoftware/tests/test-CmdProxy-rx.cpp index 05886e26f..767e646e2 100644 --- a/slsDetectorSoftware/tests/test-CmdProxy-rx.cpp +++ b/slsDetectorSoftware/tests/test-CmdProxy-rx.cpp @@ -680,7 +680,7 @@ TEST_CASE("rx_dbitlist", "[.cmd][.rx][.new]") { CmdProxy proxy(&det); auto det_type = det.getDetectorType().squash(); if (det_type == defs::CHIPTESTBOARD) { - auto previous = det.getRxDbitList(); + auto prev_val = det.getRxDbitList(); { std::ostringstream oss; proxy.Call("rx_dbitlist", {"0", "4", "5", "8", "9", "10", "52", "63"}, -1, PUT, oss); @@ -694,9 +694,8 @@ TEST_CASE("rx_dbitlist", "[.cmd][.rx][.new]") { REQUIRE_THROWS(proxy.Call("rx_dbitlist", {"67"}, -1, PUT)); REQUIRE_THROWS(proxy.Call("rx_dbitlist", {"-1"}, -1, PUT)); REQUIRE_NOTHROW(proxy.Call("rx_dbitlist", {"all"}, -1, PUT)); - // Reset to previous value for (int i = 0; i != det.size(); ++i) { - det.setRxDbitList(previous[i], {i}); + det.setRxDbitList(prev_val[i], {i}); } } else { REQUIRE_THROWS(proxy.Call("rx_dbitlist", {}, -1, GET)); @@ -708,7 +707,7 @@ TEST_CASE("rx_dbitoffset", "[.cmd][.rx][.new]") { CmdProxy proxy(&det); auto det_type = det.getDetectorType().squash(); if (det_type == defs::CHIPTESTBOARD) { - auto previous = det.getRxDbitOffset(); + auto prev_val = det.getRxDbitOffset(); { std::ostringstream oss; proxy.Call("rx_dbitoffset", {"1"}, -1, PUT, oss); @@ -729,9 +728,8 @@ TEST_CASE("rx_dbitoffset", "[.cmd][.rx][.new]") { proxy.Call("rx_dbitoffset", {}, -1, GET, oss); REQUIRE(oss.str() == "rx_dbitoffset 15\n"); } - // Reset to previous value for (int i = 0; i != det.size(); ++i) { - det.setRxDbitOffset(previous[i], {i}); + det.setRxDbitOffset(prev_val[i], {i}); } } else { REQUIRE_THROWS(proxy.Call("rx_dbitoffset", {}, -1, GET)); @@ -740,7 +738,60 @@ TEST_CASE("rx_dbitoffset", "[.cmd][.rx][.new]") { /* Moench */ -//FIXME: rx_jsonaddheader, rx_jsonpara +TEST_CASE("rx_jsonaddheader", "[.cmd][.rx][.new]") { + Detector det; + CmdProxy proxy(&det); + auto prev_val = det.getAdditionalJsonHeader(); + + { + std::ostringstream oss; + proxy.Call("rx_jsonaddheader", {"key1", "value1", "key2", "value2"}, -1, PUT, oss); + REQUIRE(oss.str() == "rx_jsonaddheader {key1: value1, key2: value2}\n"); + } + { + std::ostringstream oss; + proxy.Call("rx_jsonaddheader", {}, -1, GET, oss); + REQUIRE(oss.str() == "rx_jsonaddheader {key1: value1, key2: value2}\n"); + } + { + std::ostringstream oss; + proxy.Call("rx_jsonaddheader", {}, -1, PUT, oss); + REQUIRE(oss.str() == "rx_jsonaddheader {}\n"); + } + for (int i = 0; i != det.size(); ++i) { + det.setAdditionalJsonHeader(prev_val[i], {i}); + } +} + +TEST_CASE("rx_jsonpara", "[.cmd][.rx][.new]") { + Detector det; + CmdProxy proxy(&det); + auto prev_val = det.getAdditionalJsonHeader(); + { + std::ostringstream oss; + proxy.Call("rx_jsonpara", {"key1", "value1"}, -1, PUT, oss); + REQUIRE(oss.str() == "rx_jsonpara {key1: value1}\n"); + } + { + std::ostringstream oss; + proxy.Call("rx_jsonpara", {"key1", "value2"}, -1, PUT, oss); + REQUIRE(oss.str() == "rx_jsonpara {key1: value2}\n"); + } + { + std::ostringstream oss; + proxy.Call("rx_jsonpara", {"key1"}, -1, GET, oss); + REQUIRE(oss.str() == "rx_jsonpara value2\n"); + } + { + std::ostringstream oss; + proxy.Call("rx_jsonpara", {"key1"}, -1, PUT, oss); + REQUIRE(oss.str() == "rx_jsonpara key1 deleted\n"); + } + REQUIRE_THROWS(proxy.Call("rx_jsonpara", {"key1"}, -1, GET)); + for (int i = 0; i != det.size(); ++i) { + det.setAdditionalJsonHeader(prev_val[i], {i}); + } +} /* Insignificant */ diff --git a/slsDetectorSoftware/tests/test-CmdProxy.cpp b/slsDetectorSoftware/tests/test-CmdProxy.cpp index e0889d977..b802183da 100644 --- a/slsDetectorSoftware/tests/test-CmdProxy.cpp +++ b/slsDetectorSoftware/tests/test-CmdProxy.cpp @@ -715,33 +715,6 @@ TEST_CASE("stopport", "[.cmd]") { // REQUIRE_NOTHROW(multiSlsDetectorClient("rx_jsonaddheader \"\"", PUT)); // } -// TEST_CASE("rx_jsonpara", "[.cmd][.moench]") { -// REQUIRE_NOTHROW(multiSlsDetectorClient("rx_jsonaddheader -// \"key1\":\"value1\"", PUT)); -// { -// std::ostringstream oss; -// REQUIRE_NOTHROW(multiSlsDetectorClient("rx_jsonpara key1", GET, -// nullptr, oss)); REQUIRE(oss.str() == "rx_jsonpara value1\n"); -// } -// { -// std::ostringstream oss; -// REQUIRE_NOTHROW(multiSlsDetectorClient("rx_jsonpara key1 value2", -// PUT, nullptr, oss)); REQUIRE(oss.str() == "rx_jsonpara [key1, -// value2]\n"); -// } -// { -// std::ostringstream oss; -// REQUIRE_NOTHROW(multiSlsDetectorClient("rx_jsonpara key2 98", PUT, -// nullptr, oss)); REQUIRE(oss.str() == "rx_jsonpara [key2, 98]\n"); -// } -// { -// std::ostringstream oss; -// REQUIRE_NOTHROW(multiSlsDetectorClient("rx_jsonaddheader", GET, -// nullptr, oss)); REQUIRE(oss.str() == "rx_jsonaddheader -// \"key1\":\"value2\",\"key2\":98\n"); -// } -// REQUIRE_NOTHROW(multiSlsDetectorClient("rx_jsonaddheader \"\"", PUT)); -// } // TEST_CASE("patsetbit", "[.cmd][.ctb]") { // if (test::type == slsDetectorDefs::CHIPTESTBOARD) { diff --git a/slsReceiverSoftware/src/BinaryFileStatic.h b/slsReceiverSoftware/src/BinaryFileStatic.h index c6181eb53..80f86fbc2 100755 --- a/slsReceiverSoftware/src/BinaryFileStatic.h +++ b/slsReceiverSoftware/src/BinaryFileStatic.h @@ -128,7 +128,6 @@ class BinaryFileStatic { "SubExptime (ns) : %lld\n" "SubPeriod(ns) : %lld\n" "Period (ns) : %lld\n" - "Gap Pixels Enable : %d\n" "Quad Enable : %d\n" "Analog Flag : %d\n" "Digital Flag : %d\n" @@ -167,7 +166,6 @@ class BinaryFileStatic { (long long int)attr.subExptimeNs, (long long int)attr.subPeriodNs, (long long int)attr.periodNs, - attr.gapPixelsEnable, attr.quadEnable, attr.analogFlag, attr.digitalFlag, diff --git a/slsReceiverSoftware/src/ClientInterface.cpp b/slsReceiverSoftware/src/ClientInterface.cpp index 7563fe754..44e39f99a 100755 --- a/slsReceiverSoftware/src/ClientInterface.cpp +++ b/slsReceiverSoftware/src/ClientInterface.cpp @@ -16,6 +16,7 @@ #include #include #include +#include using sls::RuntimeError; using sls::SocketError; @@ -113,7 +114,6 @@ int ClientInterface::functionTable(){ flist[F_LOCK_RECEIVER] = &ClientInterface::lock_receiver; flist[F_GET_LAST_RECEIVER_CLIENT_IP] = &ClientInterface::get_last_client_ip; flist[F_SET_RECEIVER_PORT] = &ClientInterface::set_port; - flist[F_UPDATE_RECEIVER_CLIENT] = &ClientInterface::update_client; flist[F_GET_RECEIVER_VERSION] = &ClientInterface::get_version; flist[F_GET_RECEIVER_TYPE] = &ClientInterface::set_detector_type; flist[F_SEND_RECEIVER_DETHOSTNAME] = &ClientInterface::set_detector_hostname; @@ -163,7 +163,6 @@ int ClientInterface::functionTable(){ flist[F_GET_RECEIVER_STREAMING_SRC_IP] = &ClientInterface::get_streaming_source_ip; flist[F_SET_RECEIVER_SILENT_MODE] = &ClientInterface::set_silent_mode; flist[F_GET_RECEIVER_SILENT_MODE] = &ClientInterface::get_silent_mode; - flist[F_ENABLE_GAPPIXELS_IN_RECEIVER] = &ClientInterface::enable_gap_pixels; flist[F_RESTREAM_STOP_FROM_RECEIVER] = &ClientInterface::restream_stop; flist[F_SET_ADDITIONAL_JSON_HEADER] = &ClientInterface::set_additional_json_header; flist[F_GET_ADDITIONAL_JSON_HEADER] = &ClientInterface::get_additional_json_header; @@ -194,6 +193,8 @@ int ClientInterface::functionTable(){ flist[F_RECEIVER_SET_ADC_MASK_10G] = &ClientInterface::set_adc_mask_10g; flist[F_RECEIVER_SET_NUM_COUNTERS] = &ClientInterface::set_num_counters; flist[F_INCREMENT_FILE_INDEX] = &ClientInterface::increment_file_index; + flist[F_SET_ADDITIONAL_JSON_PARAMETER] = &ClientInterface::set_additional_json_parameter; + flist[F_GET_ADDITIONAL_JSON_PARAMETER] = &ClientInterface::get_additional_json_parameter; for (int i = NUM_DET_FUNCTIONS + 1; i < NUM_REC_FUNCTIONS ; i++) { LOG(logDEBUG1) << "function fnum: " << i << " (" << @@ -325,29 +326,6 @@ int ClientInterface::set_port(Interface &socket) { return OK; } -int ClientInterface::update_client(Interface &socket) { - if (receiver == nullptr) - throw sls::SocketError( - "Receiver not set up. Please use rx_hostname first.\n"); - socket.Send(OK); - return send_update(socket); -} - -int ClientInterface::send_update(Interface &socket) { - int n = 0; - int i32 = -1; - - sls::IpAddr ip; - ip = server->getLastClient(); - n += socket.Send(&ip, sizeof(ip)); - - // gap pixels - i32 = (int)receiver->getGapPixelsEnable(); - n += socket.Send(&i32, sizeof(i32)); - - return OK; -} - int ClientInterface::get_version(Interface &socket) { return socket.sendResult(getReceiverVersion()); } @@ -989,26 +967,6 @@ int ClientInterface::get_silent_mode(Interface &socket) { return socket.sendResult(retval); } -int ClientInterface::enable_gap_pixels(Interface &socket) { - auto enable = socket.Receive(); - if (myDetectorType != EIGER) - functionNotImplemented(); - - if (enable >= 0) { - verifyIdle(socket); - LOG(logDEBUG1) << "Setting gap pixels enable:" << enable; - try { - impl()->setGapPixelsEnable(static_cast(enable)); - } catch(const RuntimeError &e) { - throw RuntimeError("Could not set gap pixels enable to " + std::to_string(enable)); - } - } - auto retval = static_cast(impl()->getGapPixelsEnable()); - validate(enable, retval, "set gap pixels enable", DEC); - LOG(logDEBUG1) << "Gap Pixels Enable: " << retval; - return socket.sendResult(retval); -} - int ClientInterface::restream_stop(Interface &socket) { verifyIdle(socket); if (!impl()->getDataStreamEnable()) { @@ -1022,19 +980,39 @@ int ClientInterface::restream_stop(Interface &socket) { } int ClientInterface::set_additional_json_header(Interface &socket) { - char arg[MAX_STR_LENGTH]{}; - socket.Receive(arg); + std::map json; + int size = socket.Receive(); + if (size > 0) { + char args[size * 2][SHORT_STR_LENGTH]; + memset(args, 0, sizeof(args)); + socket.Receive(args, sizeof(args)); + for (int i = 0; i < size; ++i) { + json[args[2 * i]] = args[2 * i + 1]; + } + } verifyIdle(socket); - LOG(logDEBUG1) << "Setting additional json header: " << arg; - impl()->setAdditionalJsonHeader(arg); + LOG(logDEBUG1) << "Setting additional json header: " << sls::ToString(json); + impl()->setAdditionalJsonHeader(json); return socket.Send(OK); } int ClientInterface::get_additional_json_header(Interface &socket) { - char retval[MAX_STR_LENGTH]{}; - sls::strcpy_safe(retval, impl()->getAdditionalJsonHeader().c_str()); - LOG(logDEBUG1) << "additional json header:" << retval; - return socket.sendResult(retval); + std::map json = impl()->getAdditionalJsonHeader(); + LOG(logDEBUG1) << "additional json header:" << sls::ToString(json); + int size = json.size(); + socket.sendResult(size); + if (size > 0) { + char retvals[size * 2][SHORT_STR_LENGTH]; + memset(retvals, 0, sizeof(retvals)); + int iarg = 0; + for (auto & it : json) { + sls::strcpy_safe(retvals[iarg], it.first.c_str()); + sls::strcpy_safe(retvals[iarg + 1], it.second.c_str()); + iarg += 2; + } + socket.Send(retvals, sizeof(retvals)); + } + return OK; } int ClientInterface::set_udp_socket_buffer_size(Interface &socket) { @@ -1427,4 +1405,23 @@ int ClientInterface::increment_file_index(Interface &socket) { impl()->setFileIndex(impl()->getFileIndex() + 1); } return socket.Send(OK); -} \ No newline at end of file +} + + +int ClientInterface::set_additional_json_parameter(Interface &socket) { + char args[2][SHORT_STR_LENGTH]{}; + socket.Receive(args); + verifyIdle(socket); + LOG(logDEBUG1) << "Setting additional json parameter (" << args[0] << "): " << args[1]; + impl()->setAdditionalJsonParameter(args[0], args[1]); + return socket.Send(OK); +} + +int ClientInterface::get_additional_json_parameter(Interface &socket) { + char arg[SHORT_STR_LENGTH]{}; + socket.Receive(arg); + char retval[SHORT_STR_LENGTH]{}; + sls::strcpy_safe(retval, impl()->getAdditionalJsonParameter(arg).c_str()); + LOG(logDEBUG1) << "additional json parameter (" << arg << "):" << retval; + return socket.sendResult(retval); +} diff --git a/slsReceiverSoftware/src/ClientInterface.h b/slsReceiverSoftware/src/ClientInterface.h index 6e1f3bc39..47716e9e9 100755 --- a/slsReceiverSoftware/src/ClientInterface.h +++ b/slsReceiverSoftware/src/ClientInterface.h @@ -55,8 +55,6 @@ class ClientInterface : private virtual slsDetectorDefs { int lock_receiver(sls::ServerInterface &socket); int get_last_client_ip(sls::ServerInterface &socket); int set_port(sls::ServerInterface &socket); - int update_client(sls::ServerInterface &socket); - int send_update(sls::ServerInterface &socket); int get_version(sls::ServerInterface &socket); int set_detector_type(sls::ServerInterface &socket); int set_detector_hostname(sls::ServerInterface &socket); @@ -107,7 +105,6 @@ class ClientInterface : private virtual slsDetectorDefs { int get_streaming_source_ip(sls::ServerInterface &socket); int set_silent_mode(sls::ServerInterface &socket); int get_silent_mode(sls::ServerInterface &socket); - int enable_gap_pixels(sls::ServerInterface &socket); int restream_stop(sls::ServerInterface &socket); int set_additional_json_header(sls::ServerInterface &socket); int get_additional_json_header(sls::ServerInterface &socket); @@ -138,6 +135,8 @@ class ClientInterface : private virtual slsDetectorDefs { int set_adc_mask_10g(sls::ServerInterface &socket); int set_num_counters(sls::ServerInterface &socket); int increment_file_index(sls::ServerInterface &socket); + int set_additional_json_parameter(sls::ServerInterface &socket); + int get_additional_json_parameter(sls::ServerInterface &socket); Implementation *impl() { if (receiver != nullptr) { diff --git a/slsReceiverSoftware/src/DataProcessor.cpp b/slsReceiverSoftware/src/DataProcessor.cpp index ed4d42e25..ad8a89a77 100755 --- a/slsReceiverSoftware/src/DataProcessor.cpp +++ b/slsReceiverSoftware/src/DataProcessor.cpp @@ -25,7 +25,7 @@ const std::string DataProcessor::TypeName = "DataProcessor"; DataProcessor::DataProcessor(int ind, detectorType dtype, Fifo* f, fileFormat* ftype, bool fwenable, bool* mfwenable, - bool* dsEnable, bool* gpEnable, uint32_t* dr, + bool* dsEnable, uint32_t* dr, uint32_t* freq, uint32_t* timer, bool* fp, bool* act, bool* depaden, bool* sm, bool* qe, std::vector * cdl, int* cdo, int* cad) : @@ -40,12 +40,10 @@ DataProcessor::DataProcessor(int ind, detectorType dtype, Fifo* f, fileFormatType(ftype), fileWriteEnable(fwenable), masterFileWriteEnable(mfwenable), - gapPixelsEnable(gpEnable), dynamicRange(dr), streamingFrequency(freq), streamingTimerInMs(timer), currentFreqCount(0), - tempBuffer(nullptr), activated(act), deactivatedPaddingEnable(depaden), silentMode(sm), @@ -69,7 +67,6 @@ DataProcessor::DataProcessor(int ind, detectorType dtype, Fifo* f, DataProcessor::~DataProcessor() { delete file; - delete [] tempBuffer; } /** getters */ @@ -116,15 +113,6 @@ void DataProcessor::ResetParametersforNewAcquisition(){ numFramesCaught = 0; firstIndex = 0; currentFrameIndex = 0; - - if (tempBuffer != nullptr) { - delete [] tempBuffer; - tempBuffer = nullptr; - } - if (*gapPixelsEnable) { - tempBuffer = new char[generalData->imageSize]; - memset(tempBuffer, 0, generalData->imageSize); - } } @@ -296,11 +284,6 @@ void DataProcessor::ProcessAnImage(char* buf) { } } - if (*gapPixelsEnable && (*dynamicRange!=4)) - InsertGapPixels(buf + FIFO_HEADER_NUMBYTES + sizeof(sls_receiver_header), - *dynamicRange); - - // frame padding if (*activated && *framePadding && nump < generalData->packetsPerFrame) PadMissingPackets(buf); @@ -512,103 +495,3 @@ void DataProcessor::RearrangeDbitData(char* buf) { (*((uint32_t*)buf)) = numResult8Bits * sizeof(uint8_t); } -/** eiger specific */ -void DataProcessor::InsertGapPixels(char* buf, uint32_t dr) { - - memset(tempBuffer, 0xFF, generalData->imageSize); - - int rightChip = ((*quadEnable) ? 0 : index); // quad enable, then faking both to be left chips - const uint32_t nx = generalData->nPixelsX; - const uint32_t ny = generalData->nPixelsY; - const uint32_t npx = nx * ny; - bool group3 = (*quadEnable) ? false : true; // if quad enabled, no last line for left chips - char* srcptr = nullptr; - char* dstptr = nullptr; - - const uint32_t b1px = generalData->imageSize / (npx); // not double as not dealing with 4 bit mode - const uint32_t b2px = 2 * b1px; - const uint32_t b1pxofst = (rightChip == 0 ? 0 : b1px); // left fpga (rightChip 0) has no extra 1px offset, but right fpga has - const uint32_t b1chip = 256 * b1px; - const uint32_t b1line = (nx * b1px); - const uint32_t bgroup3chip = b1chip + (group3 ? b1px : 0); - - // copying line by line - srcptr = buf; - dstptr = tempBuffer + b1line + b1pxofst; // left fpga (rightChip 0) has no extra 1px offset, but right fpga has - for (uint32_t i = 0; i < (ny-1); ++i) { - memcpy(dstptr, srcptr, b1chip); - srcptr += b1chip; - dstptr += (b1chip + b2px); - memcpy(dstptr, srcptr, b1chip); - srcptr += b1chip; - dstptr += bgroup3chip; - } - - // vertical filling of values - { - char* srcgp1 = nullptr; char* srcgp2 = nullptr; char* srcgp3 = nullptr; - char* dstgp1 = nullptr; char* dstgp2 = nullptr; char* dstgp3 = nullptr; - const uint32_t b3px = 3 * b1px; - - srcptr = tempBuffer + b1line; - dstptr = tempBuffer + b1line; - - for (uint32_t i = 0; i < (ny-1); ++i) { - srcgp1 = srcptr + b1pxofst + b1chip - b1px; - dstgp1 = srcgp1 + b1px; - srcgp2 = srcgp1 + b3px; - dstgp2 = dstgp1 + b1px; - if (group3) { - if (rightChip == 0u) { - srcgp3 = srcptr + b1line - b2px; - dstgp3 = srcgp3 + b1px; - } else { - srcgp3 = srcptr + b1px; - dstgp3 = srcptr; - } - } - switch (dr) { - case 8: - (*((uint8_t*)srcgp1)) = (*((uint8_t*)srcgp1))/2; (*((uint8_t*)dstgp1)) = (*((uint8_t*)srcgp1)); - (*((uint8_t*)srcgp2)) = (*((uint8_t*)srcgp2))/2; (*((uint8_t*)dstgp2)) = (*((uint8_t*)srcgp2)); - if (group3) { - (*((uint8_t*)srcgp3)) = (*((uint8_t*)srcgp3))/2; (*((uint8_t*)dstgp3)) = (*((uint8_t*)srcgp3)); - } - break; - case 16: - (*((uint16_t*)srcgp1)) = (*((uint16_t*)srcgp1))/2; (*((uint16_t*)dstgp1)) = (*((uint16_t*)srcgp1)); - (*((uint16_t*)srcgp2)) = (*((uint16_t*)srcgp2))/2; (*((uint16_t*)dstgp2)) = (*((uint16_t*)srcgp2)); - if (group3) { - (*((uint16_t*)srcgp3)) = (*((uint16_t*)srcgp3))/2; (*((uint16_t*)dstgp3)) = (*((uint16_t*)srcgp3)); - } - break; - default: - (*((uint32_t*)srcgp1)) = (*((uint32_t*)srcgp1))/2; (*((uint32_t*)dstgp1)) = (*((uint32_t*)srcgp1)); - (*((uint32_t*)srcgp2)) = (*((uint32_t*)srcgp2))/2; (*((uint32_t*)dstgp2)) = (*((uint32_t*)srcgp2)); - if (group3) { - (*((uint32_t*)srcgp3)) = (*((uint32_t*)srcgp3))/2; (*((uint32_t*)dstgp3)) = (*((uint32_t*)srcgp3)); - } - break; - } - srcptr += b1line; - dstptr += b1line; - } - - } - - // horizontal filling of values - srcptr = tempBuffer + b1line; - dstptr = tempBuffer; - for (uint32_t i = 0; i < nx; ++i) { - switch (dr) { - case 8: (*((uint8_t*)srcptr)) = (*((uint8_t*)srcptr))/2; (*((uint8_t*)dstptr)) = (*((uint8_t*)srcptr)); break; - case 16:(*((uint16_t*)srcptr)) = (*((uint16_t*)srcptr))/2; (*((uint16_t*)dstptr)) = (*((uint16_t*)srcptr)); break; - default:(*((uint32_t*)srcptr)) = (*((uint32_t*)srcptr))/2; (*((uint32_t*)dstptr)) = (*((uint32_t*)srcptr)); break; - } - srcptr += b1px; - dstptr += b1px; - } - - memcpy(buf, tempBuffer, generalData->imageSize); - return; -} diff --git a/slsReceiverSoftware/src/DataProcessor.h b/slsReceiverSoftware/src/DataProcessor.h index 7dbce1eb1..b6cdbd21d 100755 --- a/slsReceiverSoftware/src/DataProcessor.h +++ b/slsReceiverSoftware/src/DataProcessor.h @@ -33,7 +33,6 @@ class DataProcessor : private virtual slsDetectorDefs, public ThreadObject { * @param fwenable file writer enable * @apram mfwenable pointer to master file write enable * @param dsEnable pointer to data stream enable - * @param gpEnable pointer to gap pixels enable * @param dr pointer to dynamic range * @param freq pointer to streaming frequency * @param timer pointer to timer if streaming frequency is random @@ -47,7 +46,7 @@ class DataProcessor : private virtual slsDetectorDefs, public ThreadObject { * @param cad pointer to ctb analog databytes */ DataProcessor(int ind, detectorType dtype, Fifo* f, fileFormat* ftype, - bool fwenable, bool* mfwenable, bool* dsEnable, bool* gpEnable, uint32_t* dr, + bool fwenable, bool* mfwenable, bool* dsEnable, uint32_t* dr, uint32_t* freq, uint32_t* timer, bool* fp, bool* act, bool* depaden, bool* sm, bool* qe, std::vector * cdl, int* cdo, int* cad); @@ -252,13 +251,6 @@ class DataProcessor : private virtual slsDetectorDefs, public ThreadObject { */ void RearrangeDbitData(char* buf); - /** - * Processing Function (inserting gap pixels) eiger specific - * @param buf pointer to image - * @param dr dynamic range - */ - void InsertGapPixels(char* buf, uint32_t dr); - /** type of thread */ static const std::string TypeName; @@ -291,10 +283,6 @@ class DataProcessor : private virtual slsDetectorDefs, public ThreadObject { /** Master File Write Enable */ bool* masterFileWriteEnable; - /** Gap Pixels Enable */ - bool* gapPixelsEnable; - - /** Dynamic Range */ uint32_t* dynamicRange; @@ -310,9 +298,6 @@ class DataProcessor : private virtual slsDetectorDefs, public ThreadObject { /** timer beginning stamp for random streaming */ struct timespec timerBegin; - /** temporary buffer for processing */ - char* tempBuffer; - /** Activated/Deactivated */ bool* activated; diff --git a/slsReceiverSoftware/src/DataStreamer.cpp b/slsReceiverSoftware/src/DataStreamer.cpp index 9c96692cc..fe9ba9176 100755 --- a/slsReceiverSoftware/src/DataStreamer.cpp +++ b/slsReceiverSoftware/src/DataStreamer.cpp @@ -17,7 +17,7 @@ const std::string DataStreamer::TypeName = "DataStreamer"; DataStreamer::DataStreamer(int ind, Fifo* f, uint32_t* dr, ROI* r, - uint64_t* fi, int fd, std::string* ajh, int* nd, bool* gpEnable, bool* qe) : + uint64_t* fi, int fd, int* nd, bool* qe) : ThreadObject(ind, TypeName), runningFlag(0), generalData(nullptr), @@ -28,11 +28,9 @@ DataStreamer::DataStreamer(int ind, Fifo* f, uint32_t* dr, ROI* r, adcConfigured(-1), fileIndex(fi), flippedDataX(fd), - additionJsonHeader(ajh), startedFlag(false), firstIndex(0), completeBuffer(nullptr), - gapPixelsEnable(gpEnable), quadEnable(qe) { numDet[0] = nd[0]; @@ -108,6 +106,10 @@ void DataStreamer::SetFlippedDataX(int fd) { flippedDataX = fd; } +void DataStreamer::SetAdditionalJsonHeader(const std::map &json) { + additionJsonHeader = json; +} + void DataStreamer::CreateZmqSockets(int* nunits, uint32_t port, const sls::IpAddr ip) { uint32_t portnum = port + index; std::string sip = ip.str(); @@ -217,31 +219,58 @@ void DataStreamer::ProcessAnImage(char* buf) { int DataStreamer::SendHeader(sls_receiver_header* rheader, uint32_t size, uint32_t nx, uint32_t ny, bool dummy) { - if (dummy) - return zmqSocket->SendHeaderData(index, dummy,SLS_DETECTOR_JSON_HEADER_VERSION); + zmqHeader zHeader; + zHeader.data = !dummy; + zHeader.jsonversion = SLS_DETECTOR_JSON_HEADER_VERSION; + + if (dummy) { + return zmqSocket->SendHeader(index, zHeader); + } sls_detector_header header = rheader->detHeader; uint64_t frameIndex = header.frameNumber - firstIndex; uint64_t acquisitionIndex = header.frameNumber; - return zmqSocket->SendHeaderData(index, dummy, SLS_DETECTOR_JSON_HEADER_VERSION, *dynamicRange, *fileIndex, - numDet[0], numDet[1], nx, ny, size, - acquisitionIndex, frameIndex, fileNametoStream, - header.frameNumber, header.expLength, header.packetNumber, header.bunchId, header.timestamp, - header.modId, header.row, header.column, header.reserved, - header.debug, header.roundRNumber, - header.detType, header.version, - *gapPixelsEnable ? 1 : 0, flippedDataX, *quadEnable, - additionJsonHeader - ); + zHeader.dynamicRange = *dynamicRange; + zHeader.fileIndex = *fileIndex; + zHeader.ndetx = numDet[0]; + zHeader.ndety = numDet[1]; + zHeader.npixelsx = nx; + zHeader.npixelsy = ny; + zHeader.imageSize = size; + zHeader.acqIndex = acquisitionIndex; + zHeader.frameIndex = frameIndex; + zHeader.fname = fileNametoStream; + zHeader.frameNumber = header.frameNumber; + zHeader.expLength = header.expLength; + zHeader.packetNumber = header.packetNumber; + zHeader.bunchId = header.bunchId; + zHeader.timestamp = header.timestamp; + zHeader.modId = header.modId; + zHeader.row = header.row; + zHeader.column = header.column; + zHeader.reserved = header.reserved; + zHeader.debug = header.debug; + zHeader.roundRNumber = header.roundRNumber; + zHeader.detType = header.detType; + zHeader.version = header.version; + zHeader.flippedDataX = flippedDataX; + zHeader.quad = *quadEnable; + zHeader.completeImage = (header.packetNumber < generalData->packetsPerFrame ? false : true); + zHeader.addJsonHeader = additionJsonHeader; + + return zmqSocket->SendHeader(index, zHeader); } void DataStreamer::RestreamStop() { //send dummy header - int ret = zmqSocket->SendHeaderData(index, true, SLS_DETECTOR_JSON_HEADER_VERSION); + zmqHeader zHeader; + zHeader.data = false; + zHeader.jsonversion = SLS_DETECTOR_JSON_HEADER_VERSION; + int ret = zmqSocket->SendHeader(index, zHeader); if (!ret) { throw sls::RuntimeError("Could not restream Dummy Header via ZMQ for port " + std::to_string(zmqSocket->GetPortNumber())); } diff --git a/slsReceiverSoftware/src/DataStreamer.h b/slsReceiverSoftware/src/DataStreamer.h index c3fdd8d22..c43579e2a 100755 --- a/slsReceiverSoftware/src/DataStreamer.h +++ b/slsReceiverSoftware/src/DataStreamer.h @@ -15,7 +15,7 @@ class Fifo; class DataStreamer; class ZmqSocket; -#include +#include class DataStreamer : private virtual slsDetectorDefs, public ThreadObject { @@ -29,13 +29,11 @@ class DataStreamer : private virtual slsDetectorDefs, public ThreadObject { * @param r roi * @param fi pointer to file index * @param fd flipped data enable for x dimension - * @param ajh additional json header * @param nd pointer to number of detectors in each dimension - * @param gpEnable pointer to gap pixels enable * @param qe pointer to quad Enable */ DataStreamer(int ind, Fifo* f, uint32_t* dr, ROI* r, - uint64_t* fi, int fd, std::string* ajh, int* nd, bool* gpEnable, bool* qe); + uint64_t* fi, int fd, int* nd, bool* qe); /** * Destructor @@ -90,6 +88,12 @@ class DataStreamer : private virtual slsDetectorDefs, public ThreadObject { * @param flipped data enable in x dimension */ void SetFlippedDataX(int fd); + + /** + * Set additional json header + * @param json additional json header + */ + void SetAdditionalJsonHeader(const std::map &json); /** * Creates Zmq Sockets @@ -183,7 +187,7 @@ class DataStreamer : private virtual slsDetectorDefs, public ThreadObject { int flippedDataX; /** additional json header */ - std::string* additionJsonHeader; + std::map additionJsonHeader; /** Aquisition Started flag */ bool startedFlag; @@ -200,9 +204,6 @@ class DataStreamer : private virtual slsDetectorDefs, public ThreadObject { /** Number of Detectors in X and Y dimension */ int numDet[2]; - /** Gap Pixels Enable */ - bool* gapPixelsEnable; - /** Quad Enable */ bool* quadEnable; diff --git a/slsReceiverSoftware/src/GeneralData.h b/slsReceiverSoftware/src/GeneralData.h index c51fc79d6..ba6778094 100755 --- a/slsReceiverSoftware/src/GeneralData.h +++ b/slsReceiverSoftware/src/GeneralData.h @@ -171,16 +171,6 @@ public: LOG(logERROR) << "SetTenGigaEnable is a generic function that should be overloaded by a derived class"; }; - /** - * Enable Gap Pixels changes member variables - * @param enable true if gap pixels enable, else false - * @param dr dynamic range - * @param q quad enable - */ - virtual void SetGapPixelsEnable(bool b, int dr, bool q) { - LOG(logERROR) << "SetGapPixelsEnable is a generic function that should be overloaded by a derived class"; - }; - /** * Set odd starting packet (gotthard) * @param index thread index for debugging purposes @@ -452,39 +442,6 @@ class EigerData : public GeneralData { imageSize = dataSize*packetsPerFrame; }; - /** - * Enable Gap Pixels changes member variables - * @param enable true if gap pixels enable, else false - * @param dr dynamic range - * @param q quad enable - */ - void SetGapPixelsEnable(bool b, int dr, bool q) { - if (dr == 4) - b = 0; - switch((int)b) { - case 1: - nPixelsX = (256 * 2) + 3; - if (q) { - nPixelsX = (256 * 2) + 2; - } - nPixelsY = 256 + 1; - imageSize = nPixelsX * nPixelsY * ((dr > 16) ? 4 : // 32 bit - ((dr > 8) ? 2 : // 16 bit - ((dr > 4) ? 1 : // 8 bit - 0.5))); // 4 bit - break; - default: - nPixelsX = (256*2); - nPixelsY = 256; - imageSize = nPixelsX * nPixelsY * ((dr > 16) ? 4 : // 32 bit - ((dr > 8) ? 2 : // 16 bit - ((dr > 4) ? 1 : // 8 bit - 0.5))); // 4 bit - break; - } - }; - - }; diff --git a/slsReceiverSoftware/src/HDF5FileStatic.h b/slsReceiverSoftware/src/HDF5FileStatic.h index cea07edd4..a2d4cb89a 100755 --- a/slsReceiverSoftware/src/HDF5FileStatic.h +++ b/slsReceiverSoftware/src/HDF5FileStatic.h @@ -383,41 +383,29 @@ public: attribute = dataset.createAttribute("unit",strdatatype, dataspace); attribute.write(strdatatype, std::string("ns")); - //Gap Pixels Enable - dataset = group5.createDataSet ( "gap pixels enable", PredType::NATIVE_INT, dataspace ); - dataset.write ( &(attr.gapPixelsEnable), PredType::NATIVE_INT); - - //Quad Enable - dataset = group5.createDataSet ( "quad enable", PredType::NATIVE_INT, dataspace ); - dataset.write ( &(attr.quadEnable), PredType::NATIVE_INT); - - //Gap Pixels Enable - dataset = group5.createDataSet ( "gap pixels enable", PredType::NATIVE_INT, dataspace ); - dataset.write ( &(attr.gapPixelsEnable), PredType::NATIVE_INT); - //Quad Enable dataset = group5.createDataSet ( "quad enable", PredType::NATIVE_INT, dataspace ); dataset.write ( &(attr.quadEnable), PredType::NATIVE_INT); //Analog Flag dataset = group5.createDataSet ( "analog flag", PredType::NATIVE_INT, dataspace ); - dataset.write ( &(attr.quadEnable), PredType::NATIVE_INT); + dataset.write ( &(attr.analogFlag), PredType::NATIVE_INT); //Digital Flag dataset = group5.createDataSet ( "digital flag", PredType::NATIVE_INT, dataspace ); - dataset.write ( &(attr.gapPixelsEnable), PredType::NATIVE_INT); + dataset.write ( &(attr.digitalFlag), PredType::NATIVE_INT); //ADC Mask dataset = group5.createDataSet ( "adc mask", PredType::NATIVE_INT, dataspace ); - dataset.write ( &(attr.quadEnable), PredType::NATIVE_INT); + dataset.write ( &(attr.adcmask), PredType::NATIVE_INT); //Dbit Offset dataset = group5.createDataSet ( "dbit offset", PredType::NATIVE_INT, dataspace ); - dataset.write ( &(attr.gapPixelsEnable), PredType::NATIVE_INT); + dataset.write ( &(attr.dbitoffset), PredType::NATIVE_INT); // Dbit List dataset = group5.createDataSet ( "dbit bitset list", PredType::STD_U64LE, dataspace ); - dataset.write ( &(attr.periodNs), PredType::STD_U64LE); + dataset.write ( &(attr.dbitlist), PredType::STD_U64LE); // Roi xmin dataset = group5.createDataSet ( "roi xmin", PredType::NATIVE_INT, dataspace ); diff --git a/slsReceiverSoftware/src/Implementation.cpp b/slsReceiverSoftware/src/Implementation.cpp index d5f323c4c..b2bfec79d 100755 --- a/slsReceiverSoftware/src/Implementation.cpp +++ b/slsReceiverSoftware/src/Implementation.cpp @@ -37,6 +37,7 @@ void Implementation::DeleteMembers() { generalData = nullptr; } + additionalJsonHeader.clear(); listener.clear(); dataProcessor.clear(); dataStreamer.clear(); @@ -92,7 +93,6 @@ void Implementation::InitializeMembers() { streamingTimerInMs = DEFAULT_STREAMING_TIMER_IN_MS; streamingPort = 0; streamingSrcIP = sls::IpAddr{}; - additionalJsonHeader = ""; // detector parameters numberOfFrames = 0; @@ -108,7 +108,6 @@ void Implementation::InitializeMembers() { roi.xmax = -1; tengigaEnable = false; flippedDataX = 0; - gapPixelsEnable = false; quadEnable = false; activated = true; deactivatedPaddingEnable = true; @@ -273,7 +272,7 @@ void Implementation::setDetectorType(const detectorType d) { &activated, &deactivatedPaddingEnable, &silentMode)); dataProcessor.push_back(sls::make_unique( i, myDetectorType, fifo_ptr, &fileFormatType, fileWriteEnable, - &masterFileWriteEnable, &dataStreamEnable, &gapPixelsEnable, + &masterFileWriteEnable, &dataStreamEnable, &dynamicRange, &streamingFrequency, &streamingTimerInMs, &framePadding, &activated, &deactivatedPaddingEnable, &silentMode, &quadEnable, &ctbDbitList, &ctbDbitOffset, @@ -848,7 +847,6 @@ void Implementation::SetupWriter() { attr.subExptimeNs = subExpTime; attr.subPeriodNs = subPeriod; attr.periodNs = acquisitionPeriod; - attr.gapPixelsEnable = gapPixelsEnable; attr.quadEnable = quadEnable; attr.analogFlag = (readoutType == ANALOG_ONLY || readoutType == ANALOG_AND_DIGITAL) ? 1 : 0; attr.digitalFlag = (readoutType == DIGITAL_ONLY || readoutType == ANALOG_AND_DIGITAL) ? 1 : 0; @@ -943,7 +941,7 @@ void Implementation::setNumberofUDPInterfaces(const int n) { dataProcessor.push_back(sls::make_unique( i, myDetectorType, fifo_ptr, &fileFormatType, fileWriteEnable, &masterFileWriteEnable, &dataStreamEnable, - &gapPixelsEnable, &dynamicRange, &streamingFrequency, + &dynamicRange, &streamingFrequency, &streamingTimerInMs, &framePadding, &activated, &deactivatedPaddingEnable, &silentMode, &quadEnable, &ctbDbitList, &ctbDbitOffset, &ctbAnalogDataBytes)); @@ -965,10 +963,11 @@ void Implementation::setNumberofUDPInterfaces(const int n) { } dataStreamer.push_back(sls::make_unique( i, fifo[i].get(), &dynamicRange, &roi, &fileIndex, - fd, &additionalJsonHeader, (int*)nd, &gapPixelsEnable, &quadEnable)); + fd, (int*)nd, &quadEnable)); dataStreamer[i]->SetGeneralData(generalData); dataStreamer[i]->CreateZmqSockets( &numThreads, streamingPort, streamingSrcIP); + dataStreamer[i]->SetAdditionalJsonHeader(additionalJsonHeader); } catch (...) { if (dataStreamEnable) { @@ -1108,10 +1107,11 @@ void Implementation::setDataStreamEnable(const bool enable) { } dataStreamer.push_back(sls::make_unique( i, fifo[i].get(), &dynamicRange, &roi, &fileIndex, - fd, &additionalJsonHeader, (int*)nd, &gapPixelsEnable, &quadEnable)); + fd, (int*)nd, &quadEnable)); dataStreamer[i]->SetGeneralData(generalData); dataStreamer[i]->CreateZmqSockets( &numThreads, streamingPort, streamingSrcIP); + dataStreamer[i]->SetAdditionalJsonHeader(additionalJsonHeader); } catch (...) { dataStreamer.clear(); dataStreamEnable = false; @@ -1170,17 +1170,55 @@ void Implementation::setStreamingSourceIP(const sls::IpAddr ip) { LOG(logINFO) << "Streaming Source IP: " << streamingSrcIP; } -std::string Implementation::getAdditionalJsonHeader() const { +std::map Implementation::getAdditionalJsonHeader() const { LOG(logDEBUG3) << __SHORT_AT__ << " called"; return additionalJsonHeader; } -void Implementation::setAdditionalJsonHeader(const std::string& c) { +void Implementation::setAdditionalJsonHeader(const std::map &c) { LOG(logDEBUG3) << __SHORT_AT__ << " called"; additionalJsonHeader = c; - LOG(logINFO) << "Additional JSON Header: " << additionalJsonHeader; + for (const auto &it : dataStreamer) { + it->SetAdditionalJsonHeader(c); + } + LOG(logINFO) << "Additional JSON Header: " << sls::ToString(additionalJsonHeader); } +std::string Implementation::getAdditionalJsonParameter(const std::string &key) const { + if (additionalJsonHeader.find(key) != additionalJsonHeader.end()) { + return additionalJsonHeader.at(key); + } + throw sls::RuntimeError("No key " + key + " found in additional json header"); +} + +void Implementation::setAdditionalJsonParameter(const std::string &key, const std::string &value) { + auto pos = additionalJsonHeader.find(key); + + // if value is empty, delete + if (value.empty()) { + // doesnt exist + if (pos == additionalJsonHeader.end()) { + LOG(logINFO) << "Additional json parameter (" << key << ") does not exist anyway"; + } else { + LOG(logINFO) << "Deleting additional json parameter (" << key << ")"; + additionalJsonHeader.erase(pos); + } + } + // if found, set it + else if (pos != additionalJsonHeader.end()) { + additionalJsonHeader[key] = value; + LOG(logINFO) << "Setting additional json parameter (" << key << ") to " << value; + } + // append if not found + else { + additionalJsonHeader[key] = value; + LOG(logINFO) << "Adding additional json parameter (" << key << ") to " << value; + } + for (const auto &it : dataStreamer) { + it->SetAdditionalJsonHeader(additionalJsonHeader); + } + LOG(logINFO) << "Additional JSON Header: " << sls::ToString(additionalJsonHeader); +} /************************************************** * * @@ -1330,9 +1368,6 @@ void Implementation::setDynamicRange(const uint32_t i) { if (myDetectorType == EIGER || myDetectorType == MYTHEN3) { generalData->SetDynamicRange(i, tengigaEnable); - if (myDetectorType == EIGER) { - generalData->SetGapPixelsEnable(gapPixelsEnable, dynamicRange, quadEnable); - } // to update npixelsx, npixelsy in file writer for (const auto &it : dataProcessor) it->SetPixelDimension(); @@ -1377,7 +1412,6 @@ void Implementation::setTenGigaEnable(const bool b) { switch (myDetectorType) { case EIGER: generalData->SetTenGigaEnable(b, dynamicRange); - generalData->SetGapPixelsEnable(gapPixelsEnable, dynamicRange, quadEnable); break; case MOENCH: case CHIPTESTBOARD: @@ -1421,24 +1455,6 @@ void Implementation::setFlippedDataX(int enable) { LOG(logINFO) << "Flipped Data X: " << flippedDataX; } -bool Implementation::getGapPixelsEnable() const { - LOG(logDEBUG3) << __SHORT_AT__ << " called"; - return gapPixelsEnable; -} - -void Implementation::setGapPixelsEnable(const bool b) { - if (gapPixelsEnable != b) { - gapPixelsEnable = b; - - // side effects - generalData->SetGapPixelsEnable(b, dynamicRange, quadEnable); - for (const auto &it : dataProcessor) - it->SetPixelDimension(); - SetupFifoStructure(); - } - LOG(logINFO) << "Gap Pixels Enable: " << gapPixelsEnable; -} - bool Implementation::getQuad() const { LOG(logDEBUG) << __AT__ << " starting"; return quadEnable; @@ -1448,12 +1464,6 @@ void Implementation::setQuad(const bool b) { if (quadEnable != b) { quadEnable = b; - generalData->SetGapPixelsEnable(gapPixelsEnable, dynamicRange, b); - // to update npixelsx, npixelsy in file writer - for (const auto &it : dataProcessor) - it->SetPixelDimension(); - SetupFifoStructure(); - if (!quadEnable) { for (const auto &it : dataStreamer) { it->SetNumberofDetectors(numDet); diff --git a/slsReceiverSoftware/src/Implementation.h b/slsReceiverSoftware/src/Implementation.h index a5206593e..76cdc7dd7 100755 --- a/slsReceiverSoftware/src/Implementation.h +++ b/slsReceiverSoftware/src/Implementation.h @@ -14,6 +14,7 @@ class slsDetectorDefs; #include #include #include +#include class Implementation : private virtual slsDetectorDefs { public: @@ -123,8 +124,10 @@ class Implementation : private virtual slsDetectorDefs { void setStreamingPort(const uint32_t i); sls::IpAddr getStreamingSourceIP() const; void setStreamingSourceIP(const sls::IpAddr ip); - std::string getAdditionalJsonHeader() const; - void setAdditionalJsonHeader(const std::string& c); + std::map getAdditionalJsonHeader() const; + void setAdditionalJsonHeader(const std::map &c); + std::string getAdditionalJsonParameter(const std::string &key) const; + void setAdditionalJsonParameter(const std::string &key, const std::string &value); /************************************************** * * @@ -161,9 +164,6 @@ class Implementation : private virtual slsDetectorDefs { void setTenGigaEnable(const bool b); int getFlippedDataX() const; void setFlippedDataX(int enable = -1); - bool getGapPixelsEnable() const; - /* [Eiger] */ - void setGapPixelsEnable(const bool b); bool getQuad() const; /* [Eiger] */ void setQuad(const bool b); @@ -263,7 +263,7 @@ class Implementation : private virtual slsDetectorDefs { uint32_t streamingTimerInMs; uint32_t streamingPort; sls::IpAddr streamingSrcIP; - std::string additionalJsonHeader; + std::map additionalJsonHeader; // detector parameters uint64_t numberOfFrames; @@ -278,7 +278,6 @@ class Implementation : private virtual slsDetectorDefs { ROI roi; bool tengigaEnable; int flippedDataX; - bool gapPixelsEnable; bool quadEnable; bool activated; bool deactivatedPaddingEnable; diff --git a/slsReceiverSoftware/src/receiver_defs.h b/slsReceiverSoftware/src/receiver_defs.h index 2880d28fb..41eaaae16 100755 --- a/slsReceiverSoftware/src/receiver_defs.h +++ b/slsReceiverSoftware/src/receiver_defs.h @@ -74,7 +74,6 @@ struct masterAttributes { uint64_t subExptimeNs; uint64_t subPeriodNs; uint64_t periodNs; - uint32_t gapPixelsEnable; uint32_t quadEnable; uint32_t analogFlag; uint32_t digitalFlag; diff --git a/slsSupportLib/include/ZmqSocket.h b/slsSupportLib/include/ZmqSocket.h index ff1efac43..dd111c1f3 100755 --- a/slsSupportLib/include/ZmqSocket.h +++ b/slsSupportLib/include/ZmqSocket.h @@ -17,9 +17,59 @@ class zmq_msg_t; +#include + +/** zmq header structure */ +struct zmqHeader { + /** true if incoming data, false if end of acquisition */ + bool data{true}; + uint32_t jsonversion{0}; + uint32_t dynamicRange{0}; + uint64_t fileIndex{0}; + /** number of detectors in x axis */ + uint32_t ndetx{0}; + /** number of detectors in y axis */ + uint32_t ndety{0}; + /** number of pixels/channels in x axis for this zmq socket */ + uint32_t npixelsx{0}; + /** number of pixels/channels in y axis for this zmq socket */ + uint32_t npixelsy{0}; + /** number of bytes for an image in this socket */ + uint32_t imageSize{0}; + /** frame number from detector */ + uint64_t acqIndex{0}; + /** frame index (starting at 0 for each acquisition) */ + uint64_t frameIndex{0}; + /** file name prefix */ + std::string fname{""}; + /** header from detector */ + uint64_t frameNumber{0}; + uint32_t expLength{0}; + uint32_t packetNumber{0}; + uint64_t bunchId{0}; + uint64_t timestamp{0}; + uint16_t modId{0}; + uint16_t row{0}; + uint16_t column{0}; + uint16_t reserved{0}; + uint32_t debug{0}; + uint16_t roundRNumber{0}; + uint8_t detType{0}; + uint8_t version{0}; + /** if image should be flipped across x axis */ + int flippedDataX{0}; + /** quad type (eiger hardware specific) */ + uint32_t quad{0}; + /** true if complete image, else missing packets */ + bool completeImage{false}; + /** additional json header */ + std::map addJsonHeader; +}; + class ZmqSocket { public: + // Socket Options for optimization // ZMQ_LINGER default is already -1 means no messages discarded. use this // options if optimizing required ZMQ_SNDHWM default is 0 means no limit. use @@ -110,47 +160,10 @@ class ZmqSocket { /** * Send Message Header * @param index self index for debugging - * @param dummy true if a dummy message for end of acquisition - * @param jsonversion json version - * @param dynamicrange dynamic range - * @param fileIndex file or acquisition index - * @param ndetx number of detectors in x axis - * @param ndety number of detectors in y axis - * @param npixelsx number of pixels/channels in x axis for this zmq socket - * @param npixelsy number of pixels/channels in y axis for this zmq socket - * @param imageSize number of bytes for an image in this socket - * @param frameNumber current frame number - * @param expLength exposure length or subframe index if eiger - * @param packetNumber number of packets caught for this frame - * @param bunchId bunch id - * @param timestamp time stamp - * @param modId module Id - * @param row row index in complete detector - * @param column column index in complete detector - * @param reserved reserved - * @param debug debug - * @param roundRNumber not used yet - * @param detType detector enum - * @param version detector header version - * @param gapPixelsEnable gap pixels enable (exception: if gap pixels enable - * for 4 bit mode, data is not yet gap pixel enabled in receiver) - * @param flippedDataX if it is flipped across x axis - * @param quadEnable if quad is enabled - * @param additionalJsonHeader additional json header + * @param header zmq header (from json) * @returns 0 if error, else 1 */ - int SendHeaderData( - int index, bool dummy, uint32_t jsonversion, uint32_t dynamicrange = 0, - uint64_t fileIndex = 0, uint32_t ndetx = 0, uint32_t ndety = 0, - uint32_t npixelsx = 0, uint32_t npixelsy = 0, uint32_t imageSize = 0, - uint64_t acqIndex = 0, uint64_t fIndex = 0, std::string fname = "", - uint64_t frameNumber = 0, uint32_t expLength = 0, - uint32_t packetNumber = 0, uint64_t bunchId = 0, uint64_t timestamp = 0, - uint16_t modId = 0, uint16_t row = 0, uint16_t column = 0, - uint16_t reserved = 0, uint32_t debug = 0, uint16_t roundRNumber = 0, - uint8_t detType = 0, uint8_t version = 0, int gapPixelsEnable = 0, - int flippedDataX = 0, uint32_t quadEnable = 0, - std::string *additionalJsonHeader = 0); + int SendHeader(int index, zmqHeader header); /** * Send Message Body @@ -159,39 +172,16 @@ class ZmqSocket { * @returns 0 if error, else 1 */ int SendData(char *buf, int length); - - - + /** - * Receive Header (Important to close message after parsing header) + * Receive Header * @param index self index for debugging - * @param document parsed document reference + * @param zHeader filled out zmqHeader structure (parsed from json header) * @param version version that has to match, -1 to not care * @returns 0 if error or end of acquisition, else 1 (call * CloseHeaderMessage after parsing header) */ - int ReceiveHeader(const int index, rapidjson::Document &document, uint32_t version); - - /** - * Close Header Message. Call this function if ReceiveHeader returned 1 - */ - // void CloseHeaderMessage() { - // if (headerMessage) - // zmq_msg_close(headerMessage); - // headerMessage = 0; - // }; - /** - * Parse Header - * @param index self index for debugging - * @param length length of message - * @param message message - * @param document parsed document reference - * @param dummy true if end of acqusition, else false, loaded upon parsing - * @param version version that has to match, -1 to not care - * @returns true if successful else false - */ - int ParseHeader(const int index, int length, char *buff, rapidjson::Document &document, - bool &dummy, uint32_t version); + int ReceiveHeader(const int index, zmqHeader& zHeader, uint32_t version); /** * Receive Data @@ -216,6 +206,19 @@ class ZmqSocket { * @returns length of message, -1 if error */ int ReceiveMessage(const int index, zmq_msg_t &message); + + /** + * Parse Header + * @param index self index for debugging + * @param length length of message + * @param message message + * @param zHeader filled out zmqHeader structure (parsed from json header) + * @param version version that has to match, -1 to not care + * @returns true if successful else false + */ + int ParseHeader(const int index, int length, char *buff, + zmqHeader& zHeader, uint32_t version); + /** * Class to close socket descriptors automatically * upon encountering exceptions in the ZmqSocket constructor @@ -246,4 +249,6 @@ class ZmqSocket { /** Socket descriptor */ mySocketDescriptors sockfd; + + }; diff --git a/slsSupportLib/include/sls_detector_defs.h b/slsSupportLib/include/sls_detector_defs.h index 7e88d989d..d2a8f6198 100755 --- a/slsSupportLib/include/sls_detector_defs.h +++ b/slsSupportLib/include/sls_detector_defs.h @@ -37,7 +37,7 @@ #define DEFAULT_ZMQ_RX_PORTNO 30001 #define SLS_DETECTOR_HEADER_VERSION 0x2 -#define SLS_DETECTOR_JSON_HEADER_VERSION 0x3 +#define SLS_DETECTOR_JSON_HEADER_VERSION 0x4 // ctb/ moench 1g udp (read from fifo) #define UDP_PACKET_DATA_BYTES (1344) @@ -61,6 +61,7 @@ /** default maximum string length */ #define MAX_STR_LENGTH 1000 +#define SHORT_STR_LENGTH 20 #define DEFAULT_STREAMING_TIMER_IN_MS 200 @@ -480,8 +481,6 @@ struct detParameters { int nChipY{0}; int nDacs{0}; int dynamicRange{0}; - int nGappixelsX{0}; - int nGappixelsY{0}; detParameters() = default; explicit detParameters(slsDetectorDefs::detectorType type) { @@ -493,8 +492,6 @@ struct detParameters { nChipY = 1; nDacs = 8; dynamicRange = 16; - nGappixelsX = 0; - nGappixelsY = 0; break; case slsDetectorDefs::detectorType::JUNGFRAU: nChanX = 256; @@ -503,8 +500,6 @@ struct detParameters { nChipY = 2; nDacs = 8; dynamicRange = 16; - nGappixelsX = 0; - nGappixelsY = 0; break; case slsDetectorDefs::detectorType::CHIPTESTBOARD: nChanX = 36; @@ -513,8 +508,6 @@ struct detParameters { nChipY = 1; nDacs = 24; dynamicRange = 16; - nGappixelsX = 0; - nGappixelsY = 0; break; case slsDetectorDefs::detectorType::MOENCH: nChanX = 32; @@ -523,8 +516,6 @@ struct detParameters { nChipY = 1; nDacs = 8; dynamicRange = 16; - nGappixelsX = 0; - nGappixelsY = 0; break; case slsDetectorDefs::detectorType::EIGER: nChanX = 256; @@ -533,8 +524,6 @@ struct detParameters { nChipY = 1; nDacs = 16; dynamicRange = 16; - nGappixelsX = 6; - nGappixelsY = 1; break; case slsDetectorDefs::detectorType::MYTHEN3: nChanX = 128 * 3; @@ -543,8 +532,6 @@ struct detParameters { nChipY = 1; nDacs = 16; dynamicRange = 32; - nGappixelsX = 0; - nGappixelsY = 0; break; case slsDetectorDefs::detectorType::GOTTHARD2: nChanX = 128; @@ -553,8 +540,6 @@ struct detParameters { nChipY = 1; nDacs = 14; dynamicRange = 16; - nGappixelsX = 0; - nGappixelsY = 0; break; default: throw sls::RuntimeError("Unknown detector type! " + std::to_string(type)); diff --git a/slsSupportLib/include/sls_detector_funcs.h b/slsSupportLib/include/sls_detector_funcs.h index f4a4bd941..c5f0ee1eb 100755 --- a/slsSupportLib/include/sls_detector_funcs.h +++ b/slsSupportLib/include/sls_detector_funcs.h @@ -206,7 +206,6 @@ enum detFuncs{ F_LOCK_RECEIVER, F_GET_LAST_RECEIVER_CLIENT_IP, F_SET_RECEIVER_PORT, - F_UPDATE_RECEIVER_CLIENT, F_GET_RECEIVER_VERSION, F_GET_RECEIVER_TYPE, F_SEND_RECEIVER_DETHOSTNAME, @@ -256,7 +255,6 @@ enum detFuncs{ F_GET_RECEIVER_STREAMING_SRC_IP, F_SET_RECEIVER_SILENT_MODE, F_GET_RECEIVER_SILENT_MODE, - F_ENABLE_GAPPIXELS_IN_RECEIVER, F_RESTREAM_STOP_FROM_RECEIVER, F_SET_ADDITIONAL_JSON_HEADER, F_GET_ADDITIONAL_JSON_HEADER, @@ -287,6 +285,8 @@ enum detFuncs{ F_RECEIVER_SET_ADC_MASK_10G, F_RECEIVER_SET_NUM_COUNTERS, F_INCREMENT_FILE_INDEX, + F_SET_ADDITIONAL_JSON_PARAMETER, + F_GET_ADDITIONAL_JSON_PARAMETER, NUM_REC_FUNCTIONS }; @@ -489,7 +489,6 @@ static const char* getFunctionNameFromEnum(enum detFuncs func) { case F_LOCK_RECEIVER: return "F_LOCK_RECEIVER"; case F_GET_LAST_RECEIVER_CLIENT_IP: return "F_GET_LAST_RECEIVER_CLIENT_IP"; case F_SET_RECEIVER_PORT: return "F_SET_RECEIVER_PORT"; - case F_UPDATE_RECEIVER_CLIENT: return "F_UPDATE_RECEIVER_CLIENT"; case F_GET_RECEIVER_VERSION: return "F_GET_RECEIVER_VERSION"; case F_GET_RECEIVER_TYPE: return "F_GET_RECEIVER_TYPE"; case F_SEND_RECEIVER_DETHOSTNAME: return "F_SEND_RECEIVER_DETHOSTNAME"; @@ -539,7 +538,6 @@ static const char* getFunctionNameFromEnum(enum detFuncs func) { case F_GET_RECEIVER_STREAMING_SRC_IP: return "F_GET_RECEIVER_STREAMING_SRC_IP"; case F_SET_RECEIVER_SILENT_MODE: return "F_SET_RECEIVER_SILENT_MODE"; case F_GET_RECEIVER_SILENT_MODE: return "F_GET_RECEIVER_SILENT_MODE"; - case F_ENABLE_GAPPIXELS_IN_RECEIVER: return "F_ENABLE_GAPPIXELS_IN_RECEIVER"; case F_RESTREAM_STOP_FROM_RECEIVER: return "F_RESTREAM_STOP_FROM_RECEIVER"; case F_SET_ADDITIONAL_JSON_HEADER: return "F_SET_ADDITIONAL_JSON_HEADER"; case F_GET_ADDITIONAL_JSON_HEADER: return "F_GET_ADDITIONAL_JSON_HEADER"; @@ -570,7 +568,8 @@ static const char* getFunctionNameFromEnum(enum detFuncs func) { case F_RECEIVER_SET_ADC_MASK_10G: return "F_RECEIVER_SET_ADC_MASK_10G"; case F_RECEIVER_SET_NUM_COUNTERS: return "F_RECEIVER_SET_NUM_COUNTERS"; case F_INCREMENT_FILE_INDEX: return "F_INCREMENT_FILE_INDEX"; - + case F_SET_ADDITIONAL_JSON_PARAMETER: return "F_SET_ADDITIONAL_JSON_PARAMETER"; + case F_GET_ADDITIONAL_JSON_PARAMETER: return "F_GET_ADDITIONAL_JSON_PARAMETER"; case NUM_REC_FUNCTIONS: return "NUM_REC_FUNCTIONS"; default: return "Unknown Function"; diff --git a/slsSupportLib/include/versionAPI.h b/slsSupportLib/include/versionAPI.h index 9067d6269..5b6504124 100644 --- a/slsSupportLib/include/versionAPI.h +++ b/slsSupportLib/include/versionAPI.h @@ -3,10 +3,10 @@ #define APILIB 0x200227 #define APIRECEIVER 0x200227 #define APIGUI 0x200227 -#define APICTB 0x200310 -#define APIGOTTHARD 0x200310 -#define APIJUNGFRAU 0x200310 -#define APIMYTHEN3 0x200310 -#define APIMOENCH 0x200310 -#define APIEIGER 0x200310 -#define APIGOTTHARD2 0x200313 +#define APICTB 0x200311 +#define APIGOTTHARD 0x200326 +#define APIGOTTHARD2 0x200326 +#define APIJUNGFRAU 0x200326 +#define APIMYTHEN3 0x200311 +#define APIMOENCH 0x200326 +#define APIEIGER 0x200326 diff --git a/slsSupportLib/src/ZmqSocket.cpp b/slsSupportLib/src/ZmqSocket.cpp index 3ef63f91d..3874e8b99 100644 --- a/slsSupportLib/src/ZmqSocket.cpp +++ b/slsSupportLib/src/ZmqSocket.cpp @@ -145,6 +145,244 @@ int ZmqSocket::ConvertInternetAddresstoIpString(struct addrinfo *res, char *ip, return 1; } +int ZmqSocket::SendHeader( + int index, zmqHeader header) { + + /** Json Header Format */ + const char jsonHeaderFormat[] = "{" + "\"jsonversion\":%u, " + "\"bitmode\":%u, " + "\"fileIndex\":%lu, " + "\"detshape\":[%u, %u], " + "\"shape\":[%u, %u], " + "\"size\":%u, " + "\"acqIndex\":%lu, " + "\"frameIndex\":%lu, " + "\"fname\":\"%s\", " + "\"data\": %d, " + "\"completeImage\": %d, " + + "\"frameNumber\":%lu, " + "\"expLength\":%u, " + "\"packetNumber\":%u, " + "\"bunchId\":%lu, " + "\"timestamp\":%lu, " + "\"modId\":%u, " + "\"row\":%u, " + "\"column\":%u, " + "\"reserved\":%u, " + "\"debug\":%u, " + "\"roundRNumber\":%u, " + "\"detType\":%u, " + "\"version\":%u, " + + // additional stuff + "\"flippedDataX\":%u, " + "\"quad\":%u" + + ; //"}\n"; + char buf[MAX_STR_LENGTH] = ""; + sprintf(buf, jsonHeaderFormat, + header.jsonversion, + header.dynamicRange, + header.fileIndex, + header.ndetx, + header.ndety, + header.npixelsx, + header.npixelsy, + header.imageSize, + header.acqIndex, + header.frameIndex, + header.fname.c_str(), + header.data ? 1 : 0, + header.completeImage ? 1 : 0, + + header.frameNumber, + header.expLength, + header.packetNumber, + header.bunchId, + header.timestamp, + header.modId, + header.row, + header.column, + header.reserved, + header.debug, + header.roundRNumber, + header.detType, + header.version, + + // additional stuff + header.flippedDataX, + header.quad); + + if (header.addJsonHeader.size() > 0) { + strcat(buf, ", "); + strcat(buf, "\"addJsonHeader\": {"); + for (auto it = header.addJsonHeader.begin(); it != header.addJsonHeader.end(); ++it) { + if (it != header.addJsonHeader.begin()) { + strcat(buf, ", "); + } + strcat(buf, "\""); + strcat(buf, it->first.c_str()); + strcat(buf, "\":\""); + strcat(buf, it->second.c_str()); + strcat(buf, "\""); + } + strcat(buf, " } "); + } + + strcat(buf, "}\n"); + int length = strlen(buf); + +#ifdef VERBOSE + // if(!index) + cprintf(BLUE, "%d : Streamer: buf: %s\n", index, buf); +#endif + + if (zmq_send(sockfd.socketDescriptor, buf, length, + header.data ? ZMQ_SNDMORE : 0) < 0) { + PrintError(); + return 0; + } +#ifdef VERBOSE + cprintf(GREEN, "[%u] send header data\n", portno); +#endif + return 1; +} + +int ZmqSocket::SendData(char *buf, int length) { + if (zmq_send(sockfd.socketDescriptor, buf, length, 0) < 0) { + PrintError(); + return 0; + } + return 1; +} + +int ZmqSocket::ReceiveHeader(const int index, zmqHeader& zHeader, + uint32_t version) { + std::vector buffer(MAX_STR_LENGTH); + int len = + zmq_recv(sockfd.socketDescriptor, buffer.data(), buffer.size(), 0); + if (len > 0) { +#ifdef ZMQ_DETAIL + cprintf(BLUE, "Header %d [%d] Length: %d Header:%s \n", index, portno, + len, buffer.data()); +#endif + if (ParseHeader(index, len, buffer.data(), zHeader, version)) { +#ifdef ZMQ_DETAIL + cprintf(RED, "Parsed Header %d [%d] Length: %d Header:%s \n", index, + portno, len, buffer.data()); +#endif + if (!zHeader.data) { +#ifdef ZMQ_DETAIL + cprintf(RED, "%d [%d] Received end of acquisition\n", index, + portno); +#endif + return 0; + } +#ifdef ZMQ_DETAIL + cprintf(GREEN, "%d [%d] data\n", index, portno); +#endif + return 1; + } + } + return 0; +}; + +int ZmqSocket::ParseHeader(const int index, int length, char *buff, + zmqHeader& zHeader, uint32_t version) { + Document document; + if (document.Parse(buff, length).HasParseError()) { + LOG(logERROR) << index << " Could not parse. len:" << length + << ": Message:" << buff; + fflush(stdout); + // char* buf = (char*) zmq_msg_data (&message); + for (int i = 0; i < length; ++i) { + cprintf(RED, "%02x ", buff[i]); + } + printf("\n"); + fflush(stdout); + return 0; + } + + // version check + zHeader.jsonversion = document["jsonversion"].GetUint(); + if (zHeader.jsonversion != version) { + LOG(logERROR) << "version mismatch. required " << version << ", got " + << zHeader.jsonversion; + return 0; + } + + // parse + zHeader.data = ((document["data"].GetUint()) == 0) ? false : true; + zHeader.dynamicRange = document["bitmode"].GetUint(); + zHeader.fileIndex = document["fileIndex"].GetUint64(); + zHeader.ndetx = document["detshape"][0].GetUint(); + zHeader.ndety = document["detshape"][1].GetUint(); + zHeader.npixelsx = document["shape"][0].GetUint(); + zHeader.npixelsy = document["shape"][1].GetUint(); + zHeader.imageSize = document["size"].GetUint(); + zHeader.acqIndex = document["acqIndex"].GetUint64(); + zHeader.frameIndex = document["frameIndex"].GetUint64(); + zHeader.fname = document["fname"].GetString(); + + zHeader.frameNumber = document["frameNumber"].GetUint64(); + zHeader.expLength = document["expLength"].GetUint(); + zHeader.packetNumber = document["packetNumber"].GetUint(); + zHeader.bunchId = document["bunchId"].GetUint64(); + zHeader.timestamp = document["timestamp"].GetUint64(); + zHeader.modId = document["modId"].GetUint(); + zHeader.row = document["row"].GetUint(); + zHeader.column = document["column"].GetUint(); + zHeader.reserved = document["reserved"].GetUint(); + zHeader.debug = document["debug"].GetUint(); + zHeader.roundRNumber = document["roundRNumber"].GetUint(); + zHeader.detType = document["detType"].GetUint(); + zHeader.version = document["version"].GetUint(); + + zHeader.flippedDataX = document["flippedDataX"].GetUint(); + zHeader.quad = document["quad"].GetUint(); + zHeader.completeImage = document["completeImage"].GetUint(); + + if (document.HasMember("addJsonHeader")) { + const Value& V = document["addJsonHeader"]; + zHeader.addJsonHeader.clear(); + for (Value::ConstMemberIterator iter = V.MemberBegin(); iter != V.MemberEnd(); ++iter){ + zHeader.addJsonHeader[iter->name.GetString()] = iter->value.GetString(); + } + } + + return 1; +} + +int ZmqSocket::ReceiveData(const int index, char *buf, const int size) { + zmq_msg_t message; + zmq_msg_init(&message); + int length = ReceiveMessage(index, message); + if (length == size) { + memcpy(buf, (char *)zmq_msg_data(&message), size); + } else if (length < size) { + memcpy(buf, (char *)zmq_msg_data(&message), length); + memset(buf + length, 0xFF, size - length); + } else { + LOG(logERROR) << "Received weird packet size " << length + << " for socket " << index; + memset(buf, 0xFF, size); + } + + zmq_msg_close(&message); + return length; +} + +int ZmqSocket::ReceiveMessage(const int index, zmq_msg_t &message) { + int length = zmq_msg_recv(&message, sockfd.socketDescriptor, 0); + if (length == -1) { + PrintError(); + LOG(logERROR) << "Could not read header for socket " << index; + } + return length; +} + void ZmqSocket::PrintError() { switch (errno) { case EINVAL: @@ -210,181 +448,6 @@ void ZmqSocket::PrintError() { } } -int ZmqSocket::ReceiveData(const int index, char *buf, const int size) { - zmq_msg_t message; - zmq_msg_init(&message); - int length = ReceiveMessage(index, message); - if (length == size) { - memcpy(buf, (char *)zmq_msg_data(&message), size); - } else if (length < size) { - memcpy(buf, (char *)zmq_msg_data(&message), length); - memset(buf + length, 0xFF, size - length); - } else { - LOG(logERROR) << "Received weird packet size " << length - << " for socket " << index; - memset(buf, 0xFF, size); - } - - zmq_msg_close(&message); - return length; -} - -int ZmqSocket::ParseHeader(const int index, int length, char *buff, - Document &document, bool &dummy, uint32_t version) { - if (document.Parse(buff, length).HasParseError()) { - LOG(logERROR) << index << " Could not parse. len:" << length - << ": Message:" << buff; - fflush(stdout); - // char* buf = (char*) zmq_msg_data (&message); - for (int i = 0; i < length; ++i) { - cprintf(RED, "%02x ", buff[i]); - } - printf("\n"); - fflush(stdout); - return 0; - } - - if (document["jsonversion"].GetUint() != version) { - LOG(logERROR) << "version mismatch. required " << version << ", got " - << document["jsonversion"].GetUint(); - return 0; - } - - dummy = false; - int temp = document["data"].GetUint(); - dummy = temp ? false : true; - - return 1; -} - -int ZmqSocket::ReceiveHeader(const int index, Document &document, - uint32_t version) { - std::vector buffer(MAX_STR_LENGTH); - int len = - zmq_recv(sockfd.socketDescriptor, buffer.data(), buffer.size(), 0); - if (len > 0) { - bool dummy = false; -#ifdef ZMQ_DETAIL - cprintf(BLUE, "Header %d [%d] Length: %d Header:%s \n", index, portno, - len, buffer.data()); -#endif - if (ParseHeader(index, len, buffer.data(), document, dummy, version)) { -#ifdef ZMQ_DETAIL - cprintf(RED, "Parsed Header %d [%d] Length: %d Header:%s \n", index, - portno, len, buffer.data()); -#endif - if (dummy) { -#ifdef ZMQ_DETAIL - cprintf(RED, "%d [%d] Received end of acquisition\n", index, - portno); -#endif - return 0; - } -#ifdef ZMQ_DETAIL - cprintf(GREEN, "%d [%d] data\n", index, portno); -#endif - return 1; - } - } - return 0; -}; - -int ZmqSocket::ReceiveMessage(const int index, zmq_msg_t &message) { - int length = zmq_msg_recv(&message, sockfd.socketDescriptor, 0); - if (length == -1) { - PrintError(); - LOG(logERROR) << "Could not read header for socket " << index; - } - return length; -} - -int ZmqSocket::SendData(char *buf, int length) { - if (zmq_send(sockfd.socketDescriptor, buf, length, 0) < 0) { - PrintError(); - return 0; - } - return 1; -} - -int ZmqSocket::SendHeaderData( - int index, bool dummy, uint32_t jsonversion, uint32_t dynamicrange, - uint64_t fileIndex, uint32_t ndetx, uint32_t ndety, uint32_t npixelsx, - uint32_t npixelsy, uint32_t imageSize, uint64_t acqIndex, uint64_t fIndex, - std::string fname, uint64_t frameNumber, uint32_t expLength, - uint32_t packetNumber, uint64_t bunchId, uint64_t timestamp, uint16_t modId, - uint16_t row, uint16_t column, uint16_t reserved, uint32_t debug, - uint16_t roundRNumber, uint8_t detType, uint8_t version, - int gapPixelsEnable, int flippedDataX, uint32_t quadEnable, - std::string *additionalJsonHeader) { - - /** Json Header Format */ - const char jsonHeaderFormat[] = "{" - "\"jsonversion\":%u, " - "\"bitmode\":%u, " - "\"fileIndex\":%lu, " - "\"detshape\":[%u, %u], " - "\"shape\":[%u, %u], " - "\"size\":%u, " - "\"acqIndex\":%lu, " - "\"fIndex\":%lu, " - "\"fname\":\"%s\", " - "\"data\": %d, " - - "\"frameNumber\":%lu, " - "\"expLength\":%u, " - "\"packetNumber\":%u, " - "\"bunchId\":%lu, " - "\"timestamp\":%lu, " - "\"modId\":%u, " - "\"row\":%u, " - "\"column\":%u, " - "\"reserved\":%u, " - "\"debug\":%u, " - "\"roundRNumber\":%u, " - "\"detType\":%u, " - "\"version\":%u, " - - // additional stuff - "\"gappixels\":%u, " - "\"flippedDataX\":%u, " - "\"quad\":%u" - - ; //"}\n"; - char buf[MAX_STR_LENGTH] = ""; - sprintf(buf, jsonHeaderFormat, jsonversion, dynamicrange, fileIndex, ndetx, - ndety, npixelsx, npixelsy, imageSize, acqIndex, fIndex, - fname.c_str(), dummy ? 0 : 1, - - frameNumber, expLength, packetNumber, bunchId, timestamp, modId, - row, column, reserved, debug, roundRNumber, detType, version, - - // additional stuff - gapPixelsEnable, flippedDataX, quadEnable); - - if (additionalJsonHeader && !((*additionalJsonHeader).empty())) { - strcat(buf, ", "); - strcat(buf, (*additionalJsonHeader).c_str()); - } - strcat(buf, "}\n"); - int length = strlen(buf); - -#ifdef VERBOSE - // if(!index) - cprintf(BLUE, "%d : Streamer: buf: %s\n", index, buf); -#endif - - if (zmq_send(sockfd.socketDescriptor, buf, length, - dummy ? 0 : ZMQ_SNDMORE) < 0) { - PrintError(); - return 0; - } -#ifdef VERBOSE - cprintf(GREEN, "[%u] send header data\n", portno); -#endif - return 1; -} - - //Nested class to do RAII handling of socket descriptors ZmqSocket::mySocketDescriptors::mySocketDescriptors() : server(false), contextDescriptor(0), socketDescriptor(0){};