diff --git a/device_support/national/AsyncStoreManager.cpp b/device_support/national/AsyncStoreManager.cpp index 62ce3f8df9..bea55b51b4 100644 --- a/device_support/national/AsyncStoreManager.cpp +++ b/device_support/national/AsyncStoreManager.cpp @@ -1,8 +1,12 @@ #include "AsyncStoreManager.h" +#include +#include pthread_mutex_t globalMutex = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_t segmentMutex = PTHREAD_MUTEX_INITIALIZER; +//#define DEBUG_QUEUE + SaveItem::SaveItem(void *buffer, int bufSize, int sampleToRead, char dataType, int segmentSize, int counter, int dataNid, int clockNid, float timeIdx0, void *treePtr, int shot, int streamFactor, @@ -31,235 +35,297 @@ SaveItem::SaveItem(void *buffer, int bufSize, int sampleToRead, char dataType, this->numCoeffs = numCoeffs; this->coeffs = coeffs; nxt = 0; + isUpdate = false; +} + +SaveItem::SaveItem(int dataNid, void *treePtr, MDSplus::Data *startPtr, +MDSplus::Data *endPtr, MDSplus::Data *dimPtr, MDSplus::Data *dimResPtr, int resampledNid){ + this->dataNid = dataNid; + this->treePtr = treePtr; + this->startPtr = startPtr; + this->endPtr = endPtr; + this->dimPtr = dimPtr; + this->dimResPtr = dimResPtr; + this->resampledNid = resampledNid; + nxt = 0; + isUpdate = true; } void SaveItem::save() { - Tree *tree = new Tree(((Tree *)treePtr)->getName(), ((Tree *)treePtr)->getShot()); - + // std::cout << "START SAVE" << std::endl; + //Tree *tree = new Tree(((Tree *)treePtr)->getName(), ((Tree *)treePtr)->getShot()); + Tree *tree = (Tree *)treePtr; + printf("-"); + fflush(stdout); dataNode = new TreeNode(dataNid, tree); - clockNode = new TreeNode(clockNid, tree); resampledNode = NULL; if (resampledNid > 0) resampledNode = new TreeNode(resampledNid, tree); - // Streaming stuff - - if (streamName && streamFactor > 0 && (counter % streamFactor) == 0) + if (isUpdate == true) { - - // Computation of value to be streamed - try - { - Data *nidData = new Int32(dataNid); - int sampleInterval = (int)(0.1 / period); - if (sampleInterval < 1) - sampleInterval = 1; - int numSamples = bufSize / sampleInterval; - if (numSamples < 1) - numSamples = 1; - // printf("NUM SAMPLES: %d SAMPLE INTERVAL: %d\n", numSamples, - // sampleInterval); - float *samples = new float[numSamples]; - float *times = new float[numSamples]; - int actSamples = 0; - for (int sampleIdx = 0; sampleIdx < numSamples; sampleIdx++) - { - if (sampleIdx * sampleInterval >= bufSize) - break; - float sample = - (float)((dataType == SHORT) - ? ((short *)buffer)[sampleIdx * sampleInterval] - : ((float *)buffer)[sampleIdx * sampleInterval]); - - float scaled = coeffs[numCoeffs - 1]; - for (int c = numCoeffs - 2; c >= 0; c--) - { - scaled *= sample; - scaled += coeffs[c]; - } - scaled /= gain; - - scaled = scaled * streamGain + streamOffset; - samples[actSamples] = scaled; - times[actSamples] = - period * (counter + actSamples * sampleInterval) + timeIdx0; - actSamples++; - } - EventStream::send(shot, streamName, false, actSamples, times, 1, &actSamples, samples); - delete[] samples; - delete[] times; - } - catch (MdsException &exc) - { - printf("Cannot convert stream sample: %s\n", exc.what()); - } + std::vector dims = dimPtr->getDoubleArray(); + std::cout << "RES: " << dims.data()[4] << ", " << dims.data()[5] << std::endl; + + pthread_mutex_lock(&segmentMutex); + dataNode->updateSegment(startPtr, endPtr, dimPtr); + resampledNode->updateSegment(startPtr, endPtr, dimResPtr); + pthread_mutex_unlock(&segmentMutex); + } - - ////////////////////// - // printf("Counter = %d Sample to read = %d\n", counter, sampleToRead ); - // if((counter % segmentSize) == 0 || ((int)(counter / segmentSize) * - // segmentSize) < counter + bufSize ) - if ((counter % segmentSize) == 0) + else { - // Create Segment - Data *startIdx = new Int32(counter); - Data *endIdx; - // In Transient Record acquisition mode must set - // the last segment with the correct size - if (sampleToRead > 0 && sampleToRead < segmentSize) - segmentSize = sampleToRead; - - endIdx = new Int32(counter + segmentSize - 1); - - Data *startTime; - Data *endTime; - Data *dim; - if (timeIdx0 != timeIdx0) // is a NaN float - { - // printf("Configuration for gclock\n"); - // printf("---------------- time at idx 0 NAN\n"); - startTime = - compileWithArgs("NIADCClockSegment($1, $2, $3, 0, 'start_time')", - tree, 3, clockNode, startIdx, endIdx); - endTime = - compileWithArgs("NIADCClockSegment($1, $2, $3, 0, 'end_time')", - tree, 3, clockNode, startIdx, endIdx); - dim = compileWithArgs("NIADCClockSegment($1, $2, $3, 0, 'dim')", - tree, 3, clockNode, startIdx, endIdx); - } - else - { - Data *timeAtIdx0 = new Float32(timeIdx0); - startTime = compileWithArgs( - "NIADCClockSegment($1, $2, $3, $4, 'start_time')", tree, 4, - clockNode, startIdx, endIdx, timeAtIdx0); - endTime = compileWithArgs("NIADCClockSegment($1, $2, $3, $4, 'end_time')", - tree, 4, clockNode, startIdx, endIdx, - timeAtIdx0); - dim = compileWithArgs("NIADCClockSegment($1, $2, $3, $4, 'dim')", - tree, 4, clockNode, startIdx, endIdx, - timeAtIdx0); - } - switch (dataType) - { - case SHORT: + int ofs = ceil(timeIdx0 + (counter)*period); + clockNode = new TreeNode(clockNid, tree); + + // Streaming stuff + if (streamName && streamFactor > 0 && (counter % streamFactor) == 0) { - short *fBuf = new short[segmentSize]; - memset(fBuf, 0, sizeof(short) * segmentSize); - Int16Array *fData = new Int16Array((short *)fBuf, segmentSize); - pthread_mutex_lock(&segmentMutex); + + // Computation of value to be streamed try { - if (resampledNode) - dataNode->beginSegmentMinMax(startTime, endTime, dim, fData, - resampledNode, 100); - else - dataNode->beginSegment(startTime, endTime, dim, fData); + Data *nidData = new Int32(dataNid); + int sampleInterval = (int)(0.1 / period); + if (sampleInterval < 1) + sampleInterval = 1; + int numSamples = bufSize / sampleInterval; + if (numSamples < 1) + numSamples = 1; + // printf("NUM SAMPLES: %d SAMPLE INTERVAL: %d\n", numSamples, + // sampleInterval); + float *samples = new float[numSamples]; + float *times = new float[numSamples]; + int actSamples = 0; + for (int sampleIdx = 0; sampleIdx < numSamples; sampleIdx++) + { + if (sampleIdx * sampleInterval >= bufSize) + break; + float sample = + (float)((dataType == SHORT) + ? ((short *)buffer)[sampleIdx * sampleInterval] + : ((float *)buffer)[sampleIdx * sampleInterval]); + + float scaled = coeffs[numCoeffs - 1]; + for (int c = numCoeffs - 2; c >= 0; c--) + { + scaled *= sample; + scaled += coeffs[c]; + } + scaled /= gain; + + scaled = scaled * streamGain + streamOffset; + samples[actSamples] = scaled; + times[actSamples] = + period * (counter + actSamples * sampleInterval) + timeIdx0; + actSamples++; + } + EventStream::send(shot, streamName, false, actSamples, times, 1, &actSamples, samples); + delete[] samples; + delete[] times; } catch (MdsException &exc) { - printf("BEGIN SEGMENT FAILED FOR NODE %s: %s\n", - dataNode->getFullPath(), exc.what()); + printf("Cannot convert stream sample: %s\n", exc.what()); } - pthread_mutex_unlock(&segmentMutex); - delete[] fBuf; - deleteData(fData); } - break; - case FLOAT: + // std::cout << "SAVE 1" << std::endl; + + ////////////////////// + // printf("Counter = %d Sample to read = %d SegmentSize = %d timeIdx0 = %f\n", counter, sampleToRead, segmentSize, timeIdx0 ); + // if((counter % segmentSize) == 0 || ((int)(counter / segmentSize) * + // segmentSize) < counter + bufSize ) + // if ((counter % segmentSize) == 0 || sampleToRead == 0) + if (sampleToRead >= segmentSize || counter == 0) { - float *fBuf = new float[segmentSize]; - memset(fBuf, 0, sizeof(float) * segmentSize); - Float32Array *fData = new Float32Array((float *)fBuf, segmentSize); - pthread_mutex_lock(&segmentMutex); - try + // std::cout << "SAVE 2" << std::endl; + // Create Segment + Data *startIdx = new Int32(counter); + Data *endIdx; + // In Transient Record acquisition mode must set + // the last segment with the correct size + if (sampleToRead > 0 && sampleToRead < segmentSize) + segmentSize = sampleToRead; + + endIdx = new Int32(counter + segmentSize - 1); + + Data *startTime; + Data *endTime; + Data *dim; + if (timeIdx0 != timeIdx0) // is a NaN float { - if (resampledNode) - dataNode->beginSegmentMinMax(startTime, endTime, dim, fData, - resampledNode, 100); - else - dataNode->beginSegment(startTime, endTime, dim, fData); + // printf("Configuration for gclock\n"); + // printf("---------------- time at idx 0 NAN\n"); + startTime = + compileWithArgs("NIADCClockSegment($1, $2, $3, 0, 'start_time')", + tree, 3, clockNode, startIdx, endIdx); + endTime = + compileWithArgs("NIADCClockSegment($1, $2, $3, 0, 'end_time')", + tree, 3, clockNode, startIdx, endIdx); + dim = compileWithArgs("NIADCClockSegment($1, $2, $3, 0, 'dim')", + tree, 3, clockNode, startIdx, endIdx); } - catch (MdsException &exc) + else { - printf("BEGIN SEGMENT FAILED FOR NODE %s: %s\n", - dataNode->getFullPath(), exc.what()); + // std::cout << "SAVE 3" << std::endl; + + Data *timeAtIdx0 = new Float32(timeIdx0); + Data *periodData = new Float64(period); + std::cout << "PERIOD: " << period << std::endl; + startTime = compileWithArgs( + "NIADCClockSegment($1, $2, $3, $4, 'start_time', $5)", tree, 5, + clockNode, startIdx, endIdx, timeAtIdx0, periodData); + endTime = compileWithArgs("NIADCClockSegment($1, $2, $3, $4, 'end_time', $5)", + tree, 5, clockNode, startIdx, endIdx, + timeAtIdx0, periodData); + dim = compileWithArgs("NIADCClockSegment($1, $2, $3, $4, 'dim', $5)", + tree, 5, clockNode, startIdx, endIdx, + timeAtIdx0, periodData); +// std::cout << "SAVE 4" << std::endl; + +/* + Data *timeAtIdx0 = new Float32(timeIdx0); + startTime = compileWithArgs( + "NIADCClockSegment($1, $2, $3, $4, 'start_time')", tree, 4, + clockNode, startIdx, endIdx, timeAtIdx0); +std::cout << "CHIAMO LA FUN.." << std::endl; + endTime = compileWithArgs("NIADCClockSegment($1, $2, $3, $4, 'end_time')", + tree, 4, clockNode, startIdx, endIdx, + timeAtIdx0); +std::cout << "CHIAMO LA FUN.." << std::endl; + dim = compileWithArgs("NIADCClockSegment($1, $2, $3, $4, 'dim')", + tree, 4, clockNode, startIdx, endIdx, + timeAtIdx0); +std::cout << "CHIAMO LA FUN.." << std::endl; +*/ } - pthread_mutex_unlock(&segmentMutex); - delete[] fBuf; - deleteData(fData); - } - break; - } - deleteData(startIdx); - deleteData(endIdx); - deleteData(startTime); - deleteData(endTime); - } - - try - { - switch (dataType) - { - case SHORT: - { - // printf("Short Save data %s counter %d\n", dataNode->getPath(), counter); - Int16Array *data = new Int16Array((short *)buffer, bufSize); +// std::cout << "SAVE 5" << std::endl; - pthread_mutex_lock(&segmentMutex); - try + // std::cout << "CURRENTLY SAVING START TIME: " << startTime->getFloat() << ", END TIME: " << endTime->getFloat() << std::endl; +// std::cout << "SAVE 6" << std::endl; + switch (dataType) { - if (resampledNode) - dataNode->putSegmentMinMax(data, -1, resampledNode, 100); - else - dataNode->putSegment(data, -1); + case SHORT: + { + short *fBuf = new short[segmentSize]; + memset(fBuf, 0, sizeof(short) * segmentSize); + Int16Array *fData = new Int16Array((short *)fBuf, segmentSize); + pthread_mutex_lock(&segmentMutex); + try + { + if (resampledNode) + dataNode->beginSegmentMinMax(startTime, endTime, dim, fData, + resampledNode, 100); + else + dataNode->beginSegment(startTime, endTime, dim, fData); + } + catch (MdsException &exc) + { + printf("BEGIN SEGMENT FAILED FOR NODE %s: %s\n", + dataNode->getFullPath(), exc.what()); + } + pthread_mutex_unlock(&segmentMutex); + delete[] fBuf; + deleteData(fData); } - catch (MdsException &exc) + break; + case FLOAT: { - printf("PUT SEGMENT FAILED FOR NODE: %s: %s\n", dataNode->getFullPath(), - exc.what()); + float *fBuf = new float[segmentSize]; + memset(fBuf, 0, sizeof(float) * segmentSize); + Float32Array *fData = new Float32Array((float *)fBuf, segmentSize); + pthread_mutex_lock(&segmentMutex); + try + { + if (resampledNode) + dataNode->beginSegmentMinMax(startTime, endTime, dim, fData, + resampledNode, 100); + else + dataNode->beginSegment(startTime, endTime, dim, fData); + } + catch (MdsException &exc) + { + printf("BEGIN SEGMENT FAILED FOR NODE %s: %s\n", + dataNode->getFullPath(), exc.what()); + } + pthread_mutex_unlock(&segmentMutex); + delete[] fBuf; + deleteData(fData); } - pthread_mutex_unlock(&segmentMutex); - deleteData(data); - delete[](short *) buffer; + break; + } + + deleteData(startIdx); + deleteData(endIdx); + deleteData(startTime); + deleteData(endTime); } - break; - case FLOAT: + + try { - // printf("Float Save data %s counter %d\n", dataNode->getPath(), counter); - Float32Array *data = new Float32Array((float *)buffer, bufSize); - pthread_mutex_lock(&segmentMutex); - try + switch (dataType) + { + case SHORT: { - if (resampledNode) - dataNode->putSegmentMinMax(data, -1, resampledNode, 100); - else - dataNode->putSegment(data, -1); + // printf("Short Save data %s counter %d\n", dataNode->getPath(), counter); + Int16Array *data = new Int16Array((short *)buffer, bufSize); + + pthread_mutex_lock(&segmentMutex); + try + { + if (resampledNode) + dataNode->putSegmentMinMax(data, -1, resampledNode, 100); + else + dataNode->putSegment(data, -1); + } + catch (MdsException &exc) + { + printf("PUT SEGMENT FAILED FOR NODE: %s: %s\n", dataNode->getFullPath(), + exc.what()); + } + pthread_mutex_unlock(&segmentMutex); + deleteData(data); + delete[](short *) buffer; } - catch (MdsException &exc) + break; + case FLOAT: { - printf("PUT SEGMENT FAILED FOR NODE: %s: %s\n", dataNode->getFullPath(), - exc.what()); + // printf("Float Save data %s counter %d\n", dataNode->getPath(), counter); + Float32Array *data = new Float32Array((float *)buffer, bufSize); + pthread_mutex_lock(&segmentMutex); + try + { + if (resampledNode) + dataNode->putSegmentMinMax(data, -1, resampledNode, 100); + else + dataNode->putSegment(data, -1); + } + catch (MdsException &exc) + { + printf("PUT SEGMENT FAILED FOR NODE: %s: %s\n", dataNode->getFullPath(), + exc.what()); + } + pthread_mutex_unlock(&segmentMutex); + deleteData(data); + delete[](float *) buffer; } - pthread_mutex_unlock(&segmentMutex); - deleteData(data); - delete[](float *) buffer; + break; + } + + /* Send Event on Segment update __CH*/ + // sendChannelSegmentPutEvent(dataNode); } - break; + catch (MdsException *exc) + { + printf("Cannot put segment: %s\n", exc->what()); } - - /* Send Event on Segment update __CH*/ - // sendChannelSegmentPutEvent(dataNode); - } - catch (MdsException *exc) - { - printf("Cannot put segment: %s\n", exc->what()); + delete clockNode; } + // std::cout << "DELETING DATANODE AND TREE" << std::endl; delete dataNode; - delete clockNode; - delete tree; + //delete tree; } SaveList::SaveList() @@ -279,20 +345,25 @@ void SaveList::addItem(void *buffer, int bufSize, int sampleToRead, float *coeffs, int numCoeffs, int resampledNid) { - SaveItem *newItem = new SaveItem( buffer, bufSize, sampleToRead, dataType, segmentSize, counter, dataNid, clockNid, trigTime, treePtr, shot, streamFactor, streamName, streamGain, streamOffset, period, gain, coeffs, numCoeffs, resampledNid); + + printf("+"); + fflush(stdout); + pthread_mutex_lock(&mutex); - if (saveHead == NULL) + if (saveHead == NULL){ saveHead = saveTail = newItem; + } else { saveTail->setNext(newItem); saveTail = newItem; } + pthread_cond_signal(&itemAvailable); pthread_mutex_unlock(&mutex); @@ -300,6 +371,38 @@ void SaveList::addItem(void *buffer, int bufSize, int sampleToRead, reportQueueLen(dataNid, treePtr, getQueueLen(), shot); #endif } + +void SaveList::addItem(int dataNid, void *treePtr, MDSplus::Data *startPtr, + MDSplus::Data *endPtr, MDSplus::Data *dimPtr, MDSplus::Data *dimResPtr, int resampledNid) + +{ + SaveItem *newItem = new SaveItem( + dataNid, treePtr, startPtr, endPtr, dimPtr, dimResPtr, resampledNid); + + printf("+"); + fflush(stdout); + + pthread_mutex_lock(&mutex); + + if (saveHead == NULL){ + saveHead = saveTail = newItem; + } + else + { + saveTail->setNext(newItem); + saveTail = newItem; + } + + pthread_cond_signal(&itemAvailable); + pthread_mutex_unlock(&mutex); + +#ifdef DEBUG_QUEUE + reportQueueLen(dataNid, treePtr, getQueueLen(), 1237); +#endif +} + + + void SaveList::executeItems() { while (true) @@ -338,10 +441,8 @@ void SaveList::executeItems() pthread_mutex_unlock(&mutex); #ifdef DEBUG_QUEUE - reportQueueLen(currItem->getDataNid(), currItem->getTree(), getQueueLen(), - currItem->getShot()); + reportQueueLen(currItem->getDataNid(), currItem->getTree(), getQueueLen(), currItem->getShot()); #endif - currItem->save(); delete currItem; } @@ -357,8 +458,17 @@ void SaveList::stop() pthread_cond_signal(&itemAvailable); if (threadCreated) { + struct timeval t1, t2; + double elapsedTime; + gettimeofday(&t1, NULL); + printf("WAITING SAVE THREAD TERMINATION ....\n"); + pthread_join(thread, NULL); - printf("SAVE THREAD TERMINATED\n"); + + gettimeofday(&t2, NULL); + elapsedTime = (t2.tv_sec - t1.tv_sec) * 1000.0; // sec to ms + elapsedTime += (t2.tv_usec - t1.tv_usec) / 1000.0; // us to ms + printf("SAVE THREAD TERMINATED termination time %f s\n", elapsedTime/1000); } } @@ -375,7 +485,7 @@ void reportQueueLen(int dataNid, void *treePtr, int len, int shot) clock_gettime(CLOCK_REALTIME, &retTime); currTimeMs = retTime.tv_sec * 1000 + retTime.tv_nsec / 1000000; - +/* pthread_mutex_lock(&globalMutex); if (shot != prevShot) { @@ -393,6 +503,10 @@ void reportQueueLen(int dataNid, void *treePtr, int len, int shot) pthread_mutex_unlock(&globalMutex); TreeNode *currNode = new TreeNode(dataNid, (Tree *)treePtr); + if (debug) + std::cout << "INFO: data node reportQueueLen " + << currNode->getPath() << " " << std::endl; + while (currNode->getNid() > 0 && strcmp(currNode->getUsage(), "DEVICE")) { TreeNode *prevNode = currNode; @@ -410,7 +524,7 @@ void reportQueueLen(int dataNid, void *treePtr, int len, int shot) if (tags->getSize() < 1) { if (debug) - std::cout << "WARNING: no tags for data node to reportQueueLen" + std::cout << "WARNING: no tags for data node " << currNode->getPath() << " to reportQueueLen" << std::endl; return; } @@ -420,10 +534,12 @@ void reportQueueLen(int dataNid, void *treePtr, int len, int shot) deleteData(tagData); char *buf = new char[strlen(tag) + 7]; sprintf(buf, "%s_QUEUE", tag); - delete[] tag; - EventStream::send(shot, buf, (float)((currTimeMs - startTimeMs) / 1000.), +*/ + //delete[] tag; + //EventStream::send(shot, buf, (float)((currTimeMs - startTimeMs) / 1000.), (float)len); + EventStream::send(shot, "NI6368_QUEUE", (float)((currTimeMs - startTimeMs) / 1000.), (float)len); - delete[] buf; + //delete[] buf; } void *handleSave(void *listPtr) diff --git a/device_support/national/AsyncStoreManager.h b/device_support/national/AsyncStoreManager.h index ef6357473f..b6e103e489 100644 --- a/device_support/national/AsyncStoreManager.h +++ b/device_support/national/AsyncStoreManager.h @@ -12,13 +12,16 @@ #include #include + using namespace MDSplus; using namespace std; + class SaveItem { private: + bool isUpdate; void *buffer; char dataType; int bufSize; @@ -44,6 +47,10 @@ class SaveItem int gain; int numCoeffs; float *coeffs; + Data *startPtr; + Data *endPtr; + Data *dimPtr; + Data * dimResPtr; vector split(const char *str, char c = ' ') { @@ -94,6 +101,9 @@ class SaveItem double period, float gain, float *coeffs, int numCoeffs, int resampledNid); + SaveItem(int dataNid, void *treePtr, MDSplus::Data *startPtr, + MDSplus::Data *endPtr, MDSplus::Data *dimPtr, MDSplus::Data *dimResPtr, int resampledNid); + void setNext(SaveItem *itm) { nxt = itm; } SaveItem *getNext() { return nxt; } @@ -137,6 +147,9 @@ class SaveList double period, float gain, float *coeffs, int numCoeffs, int resampledNid = -1); + void addItem(int dataNid, void *treePtr, MDSplus::Data *startPtr, + MDSplus::Data *endPtr, MDSplus::Data *dimPtr, MDSplus::Data *dimResPtr, int resampledNid); + void executeItems(); void start(); void stop(); diff --git a/device_support/national/Makefile b/device_support/national/Makefile index 468e39afba..4e0b8108a0 100644 --- a/device_support/national/Makefile +++ b/device_support/national/Makefile @@ -15,7 +15,7 @@ CFLAGS_RELEASE := -fPIC -O3 LDFLAGS_RELEASE = CFLAGS = -fPIC -O3 -I${MDSPLUS_DIR}/include -I${CODAC_ROOT}/include -std=c++11 -LDFLAGS = -fPIC -O0 -L${MDSPLUS_DIR}/lib -L${CODAC_ROOT}/lib/ -lm -lNiFpga -lpxi6259 -lnixseries -lpthread -lMdsObjectsCppShr -ltcn +LDFLAGS = -fPIC -O0 -L${MDSPLUS_DIR}/lib -L${CODAC_ROOT}/lib/ -lm -lNiFpga -lpxi6259 -lnixseries -lpthread -lMdsObjectsCppShr -ltcn -lnisync # Debug builds (make debug) diff --git a/device_support/national/NiInterface.cpp b/device_support/national/NiInterface.cpp index ced8b4189d..befb01c816 100644 --- a/device_support/national/NiInterface.cpp +++ b/device_support/national/NiInterface.cpp @@ -26,6 +26,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2019 05 14 Acquisition loop interruption when in Transient Recorder Mode is called the stop?store */ + +#include + #include #include #include @@ -35,6 +38,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include + #include #include @@ -45,7 +49,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include + #include "AsyncStoreManager.h" +#include + + /* using namespace MDSplus; @@ -60,6 +68,11 @@ extern "C" void pxi6259_ai_polynomial_scaler(int16_t *raw, float *scaled, extern "C" void pxi6259_create_ao_conf_ptr(void **confPtr); extern "C" void pxi6259_free_ao_conf_ptr(void *conf); + +extern "C" void nixseries_free_ai_conf_ptr(void *conf); +extern "C" void nixseries_create_ao_conf_ptr(void **confPtr, int wavePoints); +extern "C" int nixseries_load_ao_conf_ptr(int ao_fd, xseries_ao_conf_t *ao_conf_ptr); + extern "C" void xseries_create_ai_conf_ptr(void **confPtr, unsigned int pre_trig_smp, unsigned int post_trig_smp, @@ -99,7 +112,9 @@ extern "C" int pxi6368EV_readAndSaveAllChannels( int aiFd, int nChan, void *chanMapPtr, void *chanFdPtr, int *isBurst, int *f1Div, int *f2Div, double maxDelay, double baseFreq, double *preTimes, double *postTimes, double startTime, int bufSize, int segmentSize, char **eventNames, - void *dataNidPtr, void *treePtr, void *saveListPtr, void *stopAcq); + void *dataNidPtr, void *treePtr, void *saveListPtr, int clockNid, int shot, int *resNids, + void *coeffsNidPtr, void *gainsPtr, void *stopAcq); + extern "C" int pxi6259EV_readAndSaveAllChannels( int nChan, void *chanFdPtr, int *isBurst, int *f1Div, int *f2Div, double maxDelay, double baseFreq, double *preTimes, double *postTimes, @@ -107,6 +122,8 @@ extern "C" int pxi6259EV_readAndSaveAllChannels( void *dataNidPtr, void *treePtr, void *saveListPtr, void *stopAcq); extern "C" int64_t NI6683_get_TCN_time(); +extern "C" int NI6683_stop(int devFd, int* activeFds, int size); +extern "C" int NI6683_close(int devFd, int* Fds,int size); void pxi6259_create_ai_conf_ptr(void **confPtr) { @@ -128,6 +145,22 @@ void pxi6259_create_ao_conf_ptr(void **confPtr) *confPtr = (void *)conf; } +void nixseries_free_ai_conf_ptr(void *conf) { free((char *)conf); } + +void nixseries_create_ao_conf_ptr(void **confPtr, int wavePoints) +{ +printf("nixseries_create_ao_conf_ptr %d \n", wavePoints); + xseries_ao_conf_t *conf = + (xseries_ao_conf_t *) malloc(sizeof(xseries_ao_conf_t)); + *conf = xseries_continuous_regenerated_ao(wavePoints); + *confPtr = (void *)conf; +} + +int nixseries_load_ao_conf_ptr(int ao_fd, xseries_ao_conf_t *ao_conf_ptr) +{ + return xseries_load_ao_conf(ao_fd, *ao_conf_ptr); +} + void pxi6259_free_ao_conf_ptr(void *conf) { free((char *)conf); } int _xseries_get_device_info(int fd, void *cardInfo) @@ -398,6 +431,7 @@ int xseries_AI_scale(int16_t *raw, float *scaled, uint32_t num_samples, } // printf("ai sample scaled: %d %e \n", raw[i], scaled[i]); } + return 0; } /* @@ -486,7 +520,7 @@ int xseriesReadAndSaveAllChannels(int aiFd, int nChan, void *chanFdPtr, int *resampledNid = (int *)resampledNidPtr; // Channel node identifier int readCalls[nChan]; // For statistic number of read operation pe channel - unsigned short *buffers_s[nChan]; // Raw data buffer used when not converted data are read + short *buffers_s[nChan]; // Raw data buffer used when not converted data are read float *buffers_f[nChan]; // Converted data buffer uesed when converted dta are // read int readChanSmp[nChan]; // Numebr of samples to read from each channel @@ -529,7 +563,7 @@ int xseriesReadAndSaveAllChannels(int aiFd, int nChan, void *chanFdPtr, if (saveConv) buffers_f[chan] = new float[bufSize]; else - buffers_s[chan] = new unsigned short[bufSize]; + buffers_s[chan] = new short[bufSize]; // Check if resampling TreeNode *dataNode = new TreeNode(dataNid[chan], (Tree *)treePtr); @@ -590,6 +624,10 @@ int xseriesReadAndSaveAllChannels(int aiFd, int nChan, void *chanFdPtr, printf("dopo TreeNode\n"); ////////////////// + + //auto currReadTime = std::chrono::high_resolution_clock::now(); + //auto lastReadTime = std::chrono::high_resolution_clock::now(); + xseries_start_ai(aiFd); // Start main acquisition loop @@ -614,6 +652,8 @@ int xseriesReadAndSaveAllChannels(int aiFd, int nChan, void *chanFdPtr, // ATTENTION : why dinamic allocation of this buffer memset(bufReadChanSmp, 0, sizeof(int) * nChan); + + chan = 0; channelRead = 0; // Acquisition loop on each channel of numSamples values @@ -641,6 +681,12 @@ int xseriesReadAndSaveAllChannels(int aiFd, int nChan, void *chanFdPtr, else currDataToRead = bufSize; +/* + currReadTime = std::chrono::high_resolution_clock::now(); + auto duration = std::chrono::duration_cast(currReadTime - lastReadTime); + std::cout << duration.count() << std::endl; +*/ + // read data from device based on acquisition mode converted 1 raw data 0 // Functions waiting for data or timeout if (saveConv) @@ -653,6 +699,8 @@ int xseriesReadAndSaveAllChannels(int aiFd, int nChan, void *chanFdPtr, currReadSamples = read(chanFd[chan], &buffers_s[chan][bufReadChanSmp[chan]], (currDataToRead - bufReadChanSmp[chan]) << 1); + + //lastReadTime = currReadTime; readCalls[chan]++; @@ -679,7 +727,7 @@ int xseriesReadAndSaveAllChannels(int aiFd, int nChan, void *chanFdPtr, if (saveConv) delete (float *)buffers_f[chan]; else - delete (unsigned short *)buffers_s[chan]; + delete (short *)buffers_s[chan]; return -2; } } @@ -730,6 +778,8 @@ int xseriesReadAndSaveAllChannels(int aiFd, int nChan, void *chanFdPtr, streamFactor = (bufSize + 1) * (streamFactor / bufSize); } if (resampledNid) + { + // std::cout << "bufReadChanSmp[chan]: " << bufReadChanSmp[chan] << ", sampleToRead: " << sampleToRead << ", readChanSmp[chan]" << readChanSmp[chan] << std::endl; saveList->addItem( ((saveConv) ? (void *)buffers_f[chan] : (void *)buffers_s[chan]), @@ -739,7 +789,10 @@ int xseriesReadAndSaveAllChannels(int aiFd, int nChan, void *chanFdPtr, streamNames[chan], streamGains[chan], streamOffsets[chan], period, gains[chan], coeffs[chan], numCoeffs[chan], resampledNid[chan]); + } else + { + // std::cout << "bufReadChanSmp[chan]: " << bufReadChanSmp[chan] << std::endl; saveList->addItem( ((saveConv) ? (void *)buffers_f[chan] : (void *)buffers_s[chan]), @@ -748,12 +801,13 @@ int xseriesReadAndSaveAllChannels(int aiFd, int nChan, void *chanFdPtr, dataNid[chan], clockNid, timeIdx0, treePtr, shot, streamFactor, streamNames[chan], streamGains[chan], streamOffsets[chan], period, gains[chan], coeffs[chan], numCoeffs[chan]); + } // allocate new buffer to save the next segment if (saveConv) buffers_f[chan] = new float[bufSize]; else - buffers_s[chan] = new unsigned short[bufSize]; + buffers_s[chan] = new short[bufSize]; } // Update the number of samples read readChanSmp[chan] += bufReadChanSmp[chan]; @@ -834,7 +888,7 @@ int pxi6259_readAndSaveAllChannels( int readCalls[nChan]; - unsigned short *buffers_s[nChan]; + short *buffers_s[nChan]; float *buffers_f[nChan]; int readChanSmp[nChan]; int bufReadChanSmp[nChan]; @@ -919,7 +973,7 @@ int pxi6259_readAndSaveAllChannels( if (saveConv) buffers_f[chan] = new float[bufSize]; else - buffers_s[chan] = new unsigned short[bufSize]; + buffers_s[chan] = new short[bufSize]; triggered = 0; @@ -1003,7 +1057,7 @@ int pxi6259_readAndSaveAllChannels( if (saveConv) delete (float *)buffers_f[chan]; else - delete (unsigned short *)buffers_s[chan]; + delete (short *)buffers_s[chan]; return -2; } @@ -1077,7 +1131,7 @@ int pxi6259_readAndSaveAllChannels( if (saveConv) buffers_f[chan] = new float[bufSize]; else - buffers_s[chan] = new unsigned short[bufSize]; + buffers_s[chan] = new short[bufSize]; } // counters[chan] += bufReadChanSmp[chan]; @@ -1127,7 +1181,7 @@ int pxi6259_readAndSaveAllChannels( if (saveConv) delete (float *)buffers_f[chan]; else - delete (unsigned short *)buffers_s[chan]; + delete (short *)buffers_s[chan]; /* for (chan=0; chan < nChan; chan++) @@ -1898,6 +1952,7 @@ int temperatureProbeControl(uint32_t boardID, uint32_t *inChan, int numChan, if (sem_unlink("WakeControl") < 0) perror("Control sem_close"); + return 0; } /************************************************************************************** Software PXI chassis trigger via RTSI1 bus line. @@ -2609,6 +2664,8 @@ int stopWaveGeneration() ////////////////////////// LAZY TRIGGER STUFF ////////////////////////// //////////////////////////////////////////////////////////////////////////// + +#define SAVECONV 0 #define SEGMENT_OP_BEGIN 1 #define SEGMENT_OP_UPDATE 2 #define SEGMENT_OP_PUT 3 @@ -2843,50 +2900,93 @@ extern "C" void stopSaveEV(void *listPtr) class BufferHandler { + char saveConv = SAVECONV; // Acquisition format flags 0 raw data 1 converted data size_t bufSize; - float *buffer; + float *buffer_f; + short *buffer_s; + size_t bufferIdx, oldestBufferIdx; unsigned long sampleCount; protected: MDSplus::Tree *tree; MDSplus::TreeNode *rawNode; - SaveListEV *saveList; + int dataNid; + SaveList *saveList; public: - BufferHandler(MDSplus::Tree *tree, MDSplus::TreeNode *rawNode, + BufferHandler(MDSplus::Tree *tree, int dataNid, double maxDelay, double preTime, double baseFreq, - SaveListEV *saveList) + SaveList *saveList) { this->tree = tree; - this->rawNode = rawNode; + this->dataNid = dataNid; this->bufSize = (preTime + maxDelay) * baseFreq; //printf("==== BUFFER SIZE : %d =====", bufSize); - this->buffer = new float[this->bufSize]; + if (saveConv){ + this->buffer_f = new float[this->bufSize]; + } + else{ + this->buffer_s = new short[this->bufSize]; + } this->bufferIdx = this->oldestBufferIdx = 0; this->sampleCount = 0; this->saveList = saveList; } - ~BufferHandler() { delete[] buffer; } + ~BufferHandler() { + delete[] buffer_f; + delete[] buffer_s; + } void processSample(float sample) { - buffer[bufferIdx] = sample; + // std::cout << "CALLING FLOAT PROCESS SAMPLE" << std::endl; + buffer_f[bufferIdx] = sample; + sampleCount++; // fill the buffer before elaborating it + if (sampleCount >= bufSize - 1) + { + processSampleDelayed(buffer_f[oldestBufferIdx]); + oldestBufferIdx = (oldestBufferIdx + 1) % bufSize; + } + bufferIdx = (bufferIdx + 1) % bufSize; + } + + void processSample(void* sample) + { + void* ptr; + // std::cout << "PROCESS SHORT SAMPLE" << std::endl; + if (!saveConv) + buffer_s[bufferIdx] = *reinterpret_cast(sample); + else + buffer_f[bufferIdx] = *reinterpret_cast(sample); + sampleCount++; // fill the buffer before elaborating it if (sampleCount >= bufSize - 1) { - processSampleDelayed(buffer[oldestBufferIdx]); + if (!saveConv) + ptr = &buffer_s[oldestBufferIdx]; + else + ptr = &buffer_f[oldestBufferIdx]; + processSampleDelayed(ptr); oldestBufferIdx = (oldestBufferIdx + 1) % bufSize; } bufferIdx = (bufferIdx + 1) % bufSize; } + void terminate() { if (sampleCount > bufSize) { for (size_t i = 0; i < bufSize - 2; i++) { - processSampleDelayed(buffer[oldestBufferIdx]); + if (saveConv){ + // std::cout << "TERMINATING FLOAT SAMPLE DELAYED" << std::endl; + processSampleDelayed(&buffer_f[oldestBufferIdx]); + } + else{ + // std::cout << "TERMINATING SHORT SAMPLE DELAYED" << std::endl; + processSampleDelayed(&buffer_s[oldestBufferIdx]); + } oldestBufferIdx = (oldestBufferIdx + 1) % bufSize; } flushBuffer(); @@ -2897,22 +2997,24 @@ class BufferHandler { return; } + virtual void processSampleDelayed(void* sample) + { + return; + } virtual void trigger(double trigTime) = 0; virtual void flushBuffer() = 0; }; class ClockBufferHandler : public BufferHandler { - double *segBuffer; + double *segBuffer_f; + short *segBuffer_s; MDSplus::Array *initSegData; size_t bufIdx; - - int f12Div[2], currDivIdx; + char saveConv = SAVECONV; + int f12Div[2], currDivIdx, divSamples[2]; double baseFreq; - int segBufSize; - int segmentSize; - int numBuffersInSegment; - int bufferCount; + int segBufSize, segmentSize, numSegments, numBuffersInSegment, bufferCount, shotSampleCount, switchBufCount; double startTime; double preTime, postTime; long baseSampleCount, currBaseSampleCount, sampleCount; @@ -2923,24 +3025,38 @@ class ClockBufferHandler : public BufferHandler std::vector bufStartTimes; std::vector bufEndTimes; std::vector bufPeriods; + std::vector bufPeriodsResampled; std::vector switchTimes; bool freqSwitched; + int clockNid, resampleNid; + int shot, numCoeffs; + float curSampleDivider; + float *coeffs; + MDSplus::Data *startTimeData; + MDSplus::Data *endTimeData; + MDSplus::Data *dimData; + MDSplus::Data *dimDataResampled; public: - ClockBufferHandler(MDSplus::Tree *tree, MDSplus::TreeNode *rawNode, + ClockBufferHandler(MDSplus::Tree *tree, int dataNid, double maxDelay, int f1Div, int f2Div, double baseFreq, int segBufSize, int segmentSize, double startTime, - double preTime, double postTime, SaveListEV *saveList) - : BufferHandler(tree, rawNode, maxDelay, preTime, baseFreq, saveList) + double preTime, double postTime, SaveList *saveList, int clockNid, int shot, float *coeffs, + int numCoeffs, int resampleNid) + : BufferHandler(tree, dataNid, maxDelay, preTime, baseFreq, saveList) { this->basePeriod = 1. / baseFreq; this->baseFreq = baseFreq; this->segBufSize = segBufSize; - this->segBuffer = new double[segBufSize]; + this->segBuffer_f = new double[segBufSize]; + this->segBuffer_s = new short[segBufSize]; this->numBuffersInSegment = segmentSize / segBufSize; this->segmentSize = segBufSize * this->numBuffersInSegment; this->f12Div[0] = f1Div; this->f12Div[1] = f2Div; + this->divSamples[0] = 0; + this->divSamples[1] = 0; + this->f12Div[1] = f2Div; if (f1Div > f2Div) this->minPeriod = basePeriod * f2Div; else @@ -2956,70 +3072,87 @@ class ClockBufferHandler : public BufferHandler bufStartTimes.push_back(startTime); bufEndTimes.push_back(bufEndTime); bufPeriods.push_back(this->basePeriod * f12Div[0]); - // Prepare first segment - double *initSeg = new double[segmentSize]; - //memset(initSeg, 0, sizeof(short) * segmentSize); - memset(initSeg, 0, segmentSize); - initSegData = new MDSplus::Float64Array(initSeg, segmentSize); - delete[] initSeg; - MDSplus::Data *startSegData = new MDSplus::Float64(startTime); - MDSplus::Data *endSegData = new MDSplus::Float64(bufEndTime); - MDSplus::Data *periodData = new MDSplus::Float64(this->basePeriod * f12Div[0]); - MDSplus::Data *dimData = MDSplus::compileWithArgs( - "build_range($, $, $)", tree, 3, startSegData, endSegData, periodData); - rawNode->beginSegment(startSegData, endSegData, dimData, initSegData); - MDSplus::deleteData(startSegData); - MDSplus::deleteData(endSegData); - MDSplus::deleteData(periodData); - MDSplus::deleteData(dimData); this->bufferCount = 0; this->freqSwitched = false; + this->shotSampleCount = 0; + this->clockNid = clockNid; + this->shot = shot; + this->coeffs = coeffs; + this->resampleNid = resampleNid; + this->numCoeffs = numCoeffs; + this->numSegments = 0; + this->switchBufCount = 0; } ~ClockBufferHandler() { - delete[] segBuffer; + delete[] segBuffer_f; + delete[] segBuffer_s; MDSplus::deleteData(initSegData); } - void processSampleDelayed(float sample) + void processSampleDelayed(void* sample) { - - // Check whether frequency switched + // Check frequency switch double currTime = startTime + basePeriod * baseSampleCount; baseSampleCount++; currBaseSampleCount++; + // std::cout << "CurrBase Sample Count: " << currBaseSampleCount<< std::endl; if (currBaseSampleCount % f12Div[currDivIdx] == 0) { - segBuffer[segBufSampleCount] = sample; - segBufSampleCount++; + divSamples[currDivIdx]++; + if (!saveConv) + segBuffer_s[segBufSampleCount++] = *reinterpret_cast(sample); + else + segBuffer_f[segBufSampleCount++] = *reinterpret_cast(sample); + + + if (segBufSampleCount >= segBufSize) // buffer filled { - MDSplus::Array *bufferData = new Float64Array(segBuffer, segBufSize); - saveList->addItem(SEGMENT_OP_PUT, NULL, NULL, NULL, bufferData, rawNode); - segBufSampleCount = 0; + // std::cout << "STO SALVANDO BUFFER CON COUNTER: " << shotSampleCount << std::endl; + // std::cout << "BUFFER FILLED FOR: " << dataNid << std::endl; + + int sampleToRead = segmentSize - bufferCount * segBufSize; // how many samples can still be saved before filling the current segment + + if (!saveConv){ + saveList->addItem(segBuffer_s, segBufSize, sampleToRead, 1, segmentSize, + shotSampleCount, dataNid, clockNid, startTime, tree, shot, 0, nullptr, 0, 0, bufPeriods[bufPeriods.size()-1], 1., + coeffs, numCoeffs, resampleNid); + segBuffer_s = new short[segmentSize]; + } + else{ + saveList->addItem(segBuffer_f, segBufSize, sampleToRead, 2, segmentSize, + shotSampleCount, dataNid, clockNid, startTime, tree, shot, 0, nullptr, 0, 0, bufPeriods[bufPeriods.size()-1], 1., + coeffs, numCoeffs, resampleNid); + segBuffer_f = new double[segmentSize]; + } + + sampleCount = 0; // reinitializing the counter of the samples read in the current buffer bufferCount++; + segBufSampleCount = 0; + + if (freqSwitched == true){ + curSampleDivider = double(f12Div[currDivIdx]) / f12Div[(currDivIdx + 1) % 2]; + saveList->addItem(dataNid, tree, startTimeData, endTimeData, dimData, dimDataResampled, resampleNid); + // std:: cout << "switchBufCount: " << switchBufCount << ", curSampleDivider: " << curSampleDivider << ", primo termine: "<< (switchBufCount) * 1 / curSampleDivider << ", secodno termine" << (segBufSize - switchBufCount)* curSampleDivider << std::endl; +// std::cout << "SHOT SAMPLE COUNT PRIMA: " << shotSampleCount << std::endl; + shotSampleCount += (switchBufCount-1) * 1 / curSampleDivider + (segBufSize - switchBufCount); + bufPeriodsResampled.clear(); +// std::cout << "SHOT SAMPLE COUNT DOPO: " << shotSampleCount << std::endl; + + } + else + shotSampleCount += segBufSize; + if (bufferCount >= numBuffersInSegment) // Need to possibly adjust segment end and // dimension and create a new segment { - std::cout << "SEGMENT FILLED FOR:" << rawNode << std::endl; - // Prepare next segment + //std::cout << "SEGMENT FILLED FOR " << dataNid << std:: endl; + numSegments ++; bufStartTime = startTime + basePeriod * baseSampleCount; // std::cout << "BUF_START_TIME: " << bufStartTime << " startTime: " << startTime << " basePeriod: " << basePeriod << " f12Div[currDivIdx]: " << f12Div[currDivIdx] << " baseSampleCount: " << baseSampleCount << std::endl; double bufEndTime = bufStartTime + (segmentSize)*basePeriod * f12Div[currDivIdx]; - // std::cout << "BUF_END_TIME" << bufEndTime << std::endl; - MDSplus::Data *startSegData = new MDSplus::Float64(bufStartTime); - MDSplus::Data *endSegData = new MDSplus::Float64(bufEndTime); - MDSplus::Data *periodData = - new MDSplus::Float64(basePeriod * f12Div[currDivIdx]); - MDSplus::Data *dimData = - MDSplus::compileWithArgs("build_range($, $, $)", tree, 3, - startSegData, endSegData, periodData); - saveList->addItem(SEGMENT_OP_BEGIN, startSegData, endSegData, dimData, - initSegData, rawNode); - // rawNode->beginSegment(startSegData, endSegData, dimData, - // initSegData); - MDSplus::deleteData(periodData); bufferCount = 0; bufStartTimes.clear(); @@ -3028,16 +3161,27 @@ class ClockBufferHandler : public BufferHandler bufEndTimes.push_back(bufEndTime); bufPeriods.clear(); bufPeriods.push_back(basePeriod * f12Div[currDivIdx]); - freqSwitched = false; + } + freqSwitched = false; } } + + // std::cout << "NOT FILLED" << std::endl; if (switchTimes.size() > 0 && switchTimes[0] <= currTime) // frequencySwitched { - std::cout << "FREQUENCY SWITCH at:" << currTime << std::endl; + std::cout << "FREQUENCY SWITCH at:" << currTime << ", with segBufSampleCount: " << segBufSampleCount << std::endl; + + // Handling the counter for the Asynch store manager library + curSampleDivider = double(f12Div[currDivIdx]) / f12Div[(currDivIdx + 1) % 2]; + switchBufCount = segBufSampleCount; +// std::cout << "SHOT SAMPLE COUNT PRIMA" << shotSampleCount << std::endl; + shotSampleCount *= curSampleDivider; +// std::cout << "SHOT SAMPLE COUNT DOPO" << shotSampleCount << std::endl; currDivIdx = (currDivIdx + 1) % 2; + bufPeriods.push_back(basePeriod * f12Div[currDivIdx]); if (currBaseSampleCount % f12Div[currDivIdx] == 0) // A sample at previous frequency has been written at this time { @@ -3048,80 +3192,124 @@ class ClockBufferHandler : public BufferHandler else { currBaseSampleCount = -1; // Next sample is being written - bufStartTimes.push_back(switchTimes[0] + 2 * basePeriod * f12Div[currDivIdx]); // PROBLEMA PROBABILMENTE QUI!!!! + bufStartTimes.push_back(switchTimes[0] + 2 * basePeriod * f12Div[currDivIdx]); bufEndTimes[bufEndTimes.size() - 1] = switchTimes[0] - minPeriod / 2.; } + // std::cout << "STAMPONE!!! BUFFER COUNT: " << bufferCount << ", segBufSize: " << segBufSize << ", segBufSampleCount: " << segBufSampleCount << ", basePeriod: " << basePeriod << ", switchTimes[0]: " << switchTimes[0] << ", f12Div[currDivIdx]: " << f12Div[currDivIdx]<< std::endl; bufEndTimes.push_back( switchTimes[0] + (segmentSize - (bufferCount * segBufSize + segBufSampleCount) - 1) * (basePeriod * f12Div[currDivIdx]) - (basePeriod * f12Div[currDivIdx] / 2.)); freqSwitched = true; switchTimes.erase(switchTimes.begin()); - MDSplus::Data *startTimeData = new MDSplus::Float64(bufStartTimes[bufStartTimes.size() - 1]); - MDSplus::Data *endTimeData = + // USARE UPDATE MINMAX + + startTimeData = new MDSplus::Float64(bufStartTimes[bufStartTimes.size() - 1]); + endTimeData = new MDSplus::Float64(bufEndTimes[bufEndTimes.size() - 1]); + std::cout << "DEBUG -> END TIME DATA: " << bufEndTimes[bufEndTimes.size() - 1] << std::endl; MDSplus::Data *startTimesData = new MDSplus::Float64Array(bufStartTimes.data(), bufStartTimes.size()); MDSplus::Data *endTimesData = new MDSplus::Float64Array(bufEndTimes.data(), bufEndTimes.size()); MDSplus::Data *periodsData = new MDSplus::Float64Array(bufPeriods.data(), bufPeriods.size()); - MDSplus::Data *dimData = + dimData = MDSplus::compileWithArgs("build_range($, $, $)", tree, 3, startTimesData, endTimesData, periodsData); + + // Resampling handling + for (int z = 0; z < bufPeriods.size(); z++){ + bufPeriodsResampled.push_back(bufPeriods[z] * 50); + } + + // std::cout << "bufPeriods.size(): " <addItem(dataNid, tree, startTimeData, endTimeData, dimData, resampleNid); // std::cout << "UPDATE start: " << startTimesData << std::endl; // std::cout << "UPDATE end: " << endTimesData << std::endl; // std::cout << "UPDATE dim: " << dimData << std::endl; - saveList->addItem(SEGMENT_OP_UPDATE, startTimeData, endTimeData, dimData, - NULL, rawNode); MDSplus::deleteData(periodsData); MDSplus::deleteData(startTimesData); MDSplus::deleteData(endTimesData); } } + virtual void trigger(double trigTime) { std::cout << "TRIGGER AT: " << trigTime << std::endl; - double startTime = trigTime - preTime; - if (switchTimes.size() == 0 || - switchTimes[switchTimes.size() - 1] <= startTime) - switchTimes.push_back(startTime); + double startTime_trig = trigTime - preTime; + if (startTime_trig < startTime){ // checking if valid trigger + std::cout << "WARNING: TRIGGER WINDOW START VALUE IS IN THE PAST, SETTING IT TO EXPERIMENT START TIME" << std::endl; + startTime_trig = startTime; + } + if (switchTimes.size() == 0 || switchTimes[switchTimes.size() - 1] <= startTime_trig) + switchTimes.push_back(startTime_trig); else { size_t idx; for (idx = switchTimes.size() - 1; - idx > 0 && switchTimes[idx] >= startTime; idx--) + idx > 0 && switchTimes[idx] >= startTime_trig; idx--) ; - switchTimes.insert(switchTimes.begin() + idx, startTime); + switchTimes.insert(switchTimes.begin() + idx, startTime_trig); } - double endTime = trigTime + postTime; - if (switchTimes[switchTimes.size() - 1] <= endTime) - switchTimes.push_back(endTime); + + + double endTime_trig = trigTime + postTime; + if (switchTimes[switchTimes.size() - 1] <= endTime_trig) + switchTimes.push_back(endTime_trig); else { size_t idx; - for (idx = switchTimes.size() - 1; idx > 0 && switchTimes[idx] >= endTime; - idx--) + for (idx = switchTimes.size() - 1; idx > 0 && switchTimes[idx] >= endTime_trig; + idx--) ; - switchTimes.insert(switchTimes.begin() + idx, endTime); + switchTimes.insert(switchTimes.begin() + idx, endTime_trig); } } + virtual void flushBuffer() { - std::cout << "FLUSH BUFFER " << segBufSampleCount << std::endl; - MDSplus::Array *bufferData = new Float64Array(segBuffer, segBufSampleCount); - saveList->addItem(SEGMENT_OP_PUT, NULL, NULL, NULL, bufferData, rawNode); + + if (segBufSampleCount % 2 != 0) + segBufSampleCount -=1; + //std::cout << "FLUSH BUFFER with " << segBufSampleCount << " samples left" << std::endl; + if (this->saveConv){ + int sampleToRead = segmentSize - bufferCount*segBufSize - segBufSampleCount; + saveList->addItem(segBuffer_f, segBufSampleCount - 1 , sampleToRead, 2, segmentSize, + shotSampleCount, dataNid, clockNid, startTime, tree, shot, 0, nullptr, 0, 0, basePeriod, 1., + coeffs, numCoeffs); + } + else{ + int sampleToRead = segmentSize - bufferCount*segBufSize - segBufSampleCount; + saveList->addItem(segBuffer_s, segBufSampleCount -1 , sampleToRead, 1, segmentSize, + shotSampleCount, dataNid, clockNid, startTime, tree, shot, 0, nullptr, 0, 0, basePeriod, 1., + coeffs, numCoeffs); + } + } }; class BurstBufferHandler : public BufferHandler { - double *segBuffer; + int saveConv = SAVECONV; + double *segBuffer_f; + short *segBuffer_s; std::vector startTimes; - int freqDiv; + int freqDiv, clockNid, shot, numCoeffs, resampleNid; double baseFreq; - int segmentSize, burstCount, windowSize, windowCount; + int segmentSize, bufSize, bufCount, sampleCount, burstCount, windowSize, windowCount; double startTime; double basePeriod; double segStart; @@ -3129,13 +3317,16 @@ class BurstBufferHandler : public BufferHandler double postTime; bool inBurst; unsigned long baseSampleCount, currBaseSampleCount; + float *coeffs; + float trigTime; public: - BurstBufferHandler(MDSplus::Tree *tree, MDSplus::TreeNode *rawNode, + BurstBufferHandler(MDSplus::Tree *tree, int dataNid, double maxDelay, int freqDiv, double baseFreq, double startTime, double preTime, double postTime, - int segmentSize, SaveListEV *saveList) - : BufferHandler(tree, rawNode, maxDelay, preTime, baseFreq, saveList) + int segmentSize, int bufSize, SaveList *saveList, int clockNid, int shot, float *coeffs, + int numCoeffs, int resampleNid) + : BufferHandler(tree, dataNid, maxDelay, preTime, baseFreq, saveList) { this->preTime = preTime; this->postTime = postTime; @@ -3145,30 +3336,42 @@ class BurstBufferHandler : public BufferHandler this->segmentSize = segmentSize; if (this->segmentSize > this->windowSize) this->segmentSize = this->windowSize; - this->segBuffer = new double[this->segmentSize]; + this->bufSize = bufSize; + this->segBuffer_f = new double[this->segmentSize]; + this->segBuffer_s = new short[this->segmentSize]; this->freqDiv = freqDiv; this->startTime = startTime; this->inBurst = false; this->baseSampleCount = 0; + this->clockNid = clockNid; + this->shot = shot; + this->coeffs = coeffs; + this->numCoeffs = numCoeffs; + this->resampleNid = resampleNid; + this->sampleCount = 0; + this->bufCount = 0; } ~BurstBufferHandler() { std::cout << "DISTRUTTORE BURST" << std::endl; - delete[] segBuffer; + delete[] segBuffer_f; + delete[] segBuffer_s; std::cout << "DISTRUTTO" << std::endl; } - virtual void processSampleDelayed(float sample) + virtual void processSampleDelayed(void* sample) { - // Check whether frequency switched + // Check whether the burst window has been reached double currTime = startTime + basePeriod * baseSampleCount; - baseSampleCount++; + + // Updating timing counters + baseSampleCount++; currBaseSampleCount++; if (startTimes.size() > 0 && startTimes[0] <= currTime) { printf("\n\nprocessSampleDelayed startTimes[0] %f \n", startTimes[0]); - + if (currTime >= startTimes[0] + postTime) { printf("WARNING! Trigger time in the past -> Saving the current window data."); @@ -3178,66 +3381,82 @@ class BurstBufferHandler : public BufferHandler { inBurst = true; currBaseSampleCount = 0; - burstCount = 0; - windowCount = 0; - segStart = currTime; + burstCount = 0; // counts how many samples have been read in the burst + windowCount = 0; // traces the current position on the burst window + trigTime = startTimes[0]; } startTimes.erase(startTimes.begin()); } if (inBurst && (currBaseSampleCount % freqDiv == 0)) { - segBuffer[burstCount++] = sample; + if (!saveConv) + segBuffer_s[sampleCount++] = *reinterpret_cast(sample); + else + segBuffer_f[sampleCount++] = *reinterpret_cast(sample); windowCount++; - if (burstCount >= segmentSize) + + // BUFFER FILLED, NEED TO SAVE IT + if (sampleCount >= bufSize) { + //std::cout << "BUFFER FILLED FOR: " << dataNid << std::endl; - std::cout << "SEGMENT FILLED FOR:" << rawNode << std::endl; - - double segEnd = segStart + (segmentSize - 1) * basePeriod * freqDiv; - MDSplus::Data *startSegData = new MDSplus::Float64(segStart); - MDSplus::Data *endSegData = new MDSplus::Float64(segEnd); - MDSplus::Data *periodData = new MDSplus::Float64(basePeriod * freqDiv); - MDSplus::Data *dimData = - MDSplus::compileWithArgs("build_range($, $, $)", tree, 3, - startSegData, endSegData, periodData); - - MDSplus::Array *segData = - new MDSplus::Float64Array(segBuffer, segmentSize); - // std::cout << "SEG START: " << startSegData << " FOR NODE" << rawNode -> getPath() << std::endl; - // std::cout << "SEG END: " << endSegData << std::endl; - // std::cout << "SEG DIM: " << dimData << std::endl; - saveList->addItem(SEGMENT_OP_MAKE, startSegData, endSegData, dimData, - segData, rawNode); - MDSplus::deleteData(periodData); - if (windowCount >= windowSize) - inBurst = false; - else // There are still other segments to be stored for this burst - { - burstCount = 0; - segStart = currTime; + int sampleToRead = segmentSize - bufCount; // how many samples can still be saved before filling the current segment + // std::cout << "sampleToRead: " << sampleToRead << ", startTime: " << segStart << ", basePeriod: " << basePeriod << std::endl; + // std::cout << "SAVING SEGMENT FOR " << dataNid << std::endl; + + if (!saveConv){ + saveList->addItem(segBuffer_s, bufSize, sampleToRead, 1, segmentSize, + burstCount, dataNid, clockNid, trigTime, tree, shot, 0, nullptr, 0, 0, basePeriod * freqDiv, 1., + coeffs, numCoeffs, resampleNid); + segBuffer_s = new short[segmentSize]; // reinitializing the samples buffer to read the next data } + else{ + saveList->addItem(segBuffer_f, bufSize, sampleToRead, 2, segmentSize, + burstCount, dataNid, clockNid, trigTime, tree, shot, 0, nullptr, 0, 0, basePeriod * freqDiv, 1., + coeffs, numCoeffs, resampleNid); + segBuffer_f = new double[segmentSize]; // reinitializing the samples buffer to read the next data + } + + bufCount += bufSize; // updating the number of samples in the current segment + burstCount += bufSize; // updating the total number of samples read + sampleCount = 0; // reinitializing the counter of the samples read in the current buffer + + if (windowCount >= windowSize) // burst window finished + inBurst = false; + + else if (bufCount == segmentSize) // segment filled, reinitializing the counter of the samples in the current segment + bufCount = 0; } + + else if (windowCount > windowSize) // Last piece of burst { - double segEnd = segStart + (burstCount - 1) * basePeriod * freqDiv; - MDSplus::Data *startSegData = new MDSplus::Float64(segStart); - MDSplus::Data *endSegData = new MDSplus::Float64(segEnd); - MDSplus::Data *periodData = new MDSplus::Float64(basePeriod * freqDiv); - MDSplus::Data *dimData = - MDSplus::compileWithArgs("build_range($, $, $)", tree, 3, - startSegData, endSegData, periodData); - MDSplus::Array *segData = - new MDSplus::Float64Array(segBuffer, burstCount); - // std::cout << "LAST SEG START: " << startSegData << std::endl; - // std::cout << "LAST SEG END: " << endSegData << std::endl; - // std::cout << "LAST SEG DIM: " << dimData << std::endl; - saveList->addItem(SEGMENT_OP_MAKE, startSegData, endSegData, dimData, - segData, rawNode); - MDSplus::deleteData(periodData); + // std::cout << "inBurst False, windowCount: " << windowCount << ", windowSize: " << windowSize << std::endl; + int sampleToRead = segmentSize - sampleCount; + // std::cout << "sampleToRead: " << sampleToRead << ", startTime: " << segStart << ", basePeriod: " << basePeriod << std::endl; + std::cout << "SAVING LAST DATA FOR " << dataNid << std::endl; + + if (!saveConv){ + saveList->addItem(segBuffer_s, sampleCount, sampleToRead, 1, segmentSize, + burstCount, dataNid, clockNid, trigTime, tree, shot, 0, nullptr, 0, 0, basePeriod, 1., + coeffs, numCoeffs, resampleNid); + segBuffer_s = new short[segmentSize]; + } + else{ + saveList->addItem(segBuffer_f, sampleCount, sampleToRead, 2, segmentSize, + burstCount, dataNid, clockNid, trigTime, tree, shot, 0, nullptr, 0, 0, basePeriod, 1., + coeffs, numCoeffs, resampleNid); + segBuffer_f = new double[segmentSize]; + } + + inBurst = false; } } } + + + virtual void trigger(double trigTime) { double currTime = startTime + basePeriod * baseSampleCount; @@ -3320,16 +3539,16 @@ int pxi6259EV_readAndSaveAllChannels( memset(eventHandlers, 0, sizeof(EventHandler *) * nChan); for (chan = 0; chan < nChan; chan++) { - if (isBurst[chan]) - bufferHandlers[chan] = new BurstBufferHandler( - (MDSplus::Tree *)treePtr, treeNodes[chan], maxDelay, f1Div[chan], - baseFreq, startTime, preTimes[chan], postTimes[chan], segmentSize, - saveList); - else - bufferHandlers[chan] = new ClockBufferHandler( - (MDSplus::Tree *)treePtr, treeNodes[chan], maxDelay, f1Div[chan], - f2Div[chan], baseFreq, bufSize, segmentSize, startTime, - preTimes[chan], postTimes[chan], saveList); + // if (isBurst[chan]) + // bufferHandlers[chan] = new BurstBufferHandler( + // (MDSplus::Tree *)treePtr, treeNodes[chan], maxDelay, f1Div[chan], + // baseFreq, startTime, preTimes[chan], postTimes[chan], segmentSize, + // saveList); + // else + // bufferHandlers[chan] = new ClockBufferHandler( + // (MDSplus::Tree *)treePtr, treeNodes[chan], maxDelay, f1Div[chan], + // f2Div[chan], baseFreq, bufSize, segmentSize, startTime, + // preTimes[chan], postTimes[chan], saveList); if (eventNames[chan][0]) // Empty string is passed for no event { eventHandlers[chan] = @@ -3395,9 +3614,9 @@ int pxi6259EV_readAndSaveAllChannels( std::cout << "STOPPED" << std::endl; delete eventHandlers[chan]; } - std::cout << "TERMINATING BUFFER HANDLER...." << std::endl; + //std::cout << "TERMINATING BUFFER HANDLER...." << std::endl; bufferHandlers[chan]->terminate(); - std::cout << "TERMINATED" << std::endl; + //std::cout << "TERMINATED" << std::endl; } saveList->stop(); @@ -3415,10 +3634,23 @@ int pxi6368EV_readAndSaveAllChannels( int aiFd, int nChan, void *chanMapPtr, void *chanFdPtr, int *isBurst, int *f1Div, int *f2Div, double maxDelay, double baseFreq, double *preTimes, double *postTimes, double startTime, int bufSize, int segmentSize, char **eventNames, - void *dataNidPtr, void *treePtr, void *saveListPtr, void *stopAcq) + void *dataNidPtr, void *treePtr, void *saveListPtr, int clockNid, int shot, int *resNids, + void *coeffsNidPtr, void *gainsPtr, void *stopAcq) { + + char saveConv = SAVECONV; // Acquisition format flags 0 raw data 1 convrted data + + int sampleToRead = 0; // Number of sample to read + int currDataToRead = 0; // Number of current sample to read + int chan; - SaveListEV *saveList = (SaveListEV *)saveListPtr; + int currReadSamples; // Number of samples read + + + SaveList *saveList = (SaveList *)saveListPtr; + float *gains = (float *)gainsPtr; + int *coeffsNid = (int *)coeffsNidPtr; + int *resampledNid = (int *)resNids; // Channel node identifier int *chanMap = (int *)chanMapPtr; int *chanFd = (int *)chanFdPtr; int *dataNid = (int *)dataNidPtr; @@ -3426,6 +3658,9 @@ int pxi6368EV_readAndSaveAllChannels( EventHandler **eventHandlers; MDSplus::TreeNode **treeNodes; treeNodes = new MDSplus::TreeNode *[nChan]; + + float *coeffs[nChan]; + int numCoeffs[nChan]; // Delete first all data nids for (int i = 0; i < nChan; i++) { @@ -3438,29 +3673,46 @@ int pxi6368EV_readAndSaveAllChannels( { printf("Error deleting data nodes\n"); } + } - (*(int *)stopAcq) = 0; +// std::cout<< "READ AND SAVE 1 " << std::endl; + + + (*(int *)stopAcq) = 0; + // std::cout<< "READ AND SAVE 1.1 " << std::endl; bufferHandlers = new BufferHandler *[nChan]; memset(bufferHandlers, 0, sizeof(BufferHandler *) * nChan); eventHandlers = new EventHandler *[nChan]; memset(eventHandlers, 0, sizeof(EventHandler *) * nChan); - // Burst buffers for the channels indicating "BURST" + for (chan = 0; chan < nChan; chan++) { + try + { + TreeNode *rangeNode = + new TreeNode(coeffsNid[chan], (MDSplus::Tree *)treePtr); + Data *rangeData = rangeNode->getData(); + coeffs[chan] = rangeData->getFloatArray(&numCoeffs[chan]); + deleteData(rangeData); + } + catch (MdsException &exc) + { + printf("%s\n", exc.what()); + } if (isBurst[chan]) { bufferHandlers[chan] = new BurstBufferHandler( - (MDSplus::Tree *)treePtr, treeNodes[chan], maxDelay, f1Div[chan], - baseFreq, startTime, preTimes[chan], postTimes[chan], segmentSize, - saveList); + (MDSplus::Tree *)treePtr, dataNid[chan], maxDelay, f1Div[chan], + baseFreq, startTime, preTimes[chan], postTimes[chan], segmentSize, bufSize, + saveList, clockNid, shot, coeffs[chan], numCoeffs[chan], resampledNid[chan]); } else // Clock buffers for the channels indicating "CONTINUOUS" or "DUAL SPEED" bufferHandlers[chan] = new ClockBufferHandler( - (MDSplus::Tree *)treePtr, treeNodes[chan], maxDelay, f1Div[chan], + (MDSplus::Tree *)treePtr, dataNid[chan], maxDelay, f1Div[chan], f2Div[chan], baseFreq, bufSize, segmentSize, startTime, - preTimes[chan], postTimes[chan], saveList); + preTimes[chan], postTimes[chan], saveList, clockNid, shot, coeffs[chan], numCoeffs[chan], resampledNid[chan]); if (eventNames[chan][0]) // Empty string is passed for no event { eventHandlers[chan] = new EventHandler(eventNames[chan], bufferHandlers[chan]); @@ -3469,14 +3721,25 @@ int pxi6368EV_readAndSaveAllChannels( else eventHandlers[chan] = NULL; } +// std::cout<< "READ AND SAVE 2 " << std::endl; + xseries_start_ai(aiFd); while (!(*(int *)stopAcq)) { - float buffers[nChan][bufSize]; + short buffers_s[nChan][bufSize]; // Raw data buffer used when not converted data are read + float buffers_f[nChan][bufSize]; // Converted data buffer uesed when converted dta are + // float buffers[nChan][bufSize]; OCCHIO QUI, HO CAMBIATO RISPETTO A PRIMA *** + for (chan = 0; chan < nChan; chan++) { // Reading samples from the analog input channels - int currReadSamples = xseries_read_ai(chanFd[chan], buffers[chan], bufSize); + if (saveConv){ + currReadSamples = xseries_read_ai(chanFd[chan], buffers_f[chan], bufSize); + } + else{ + currReadSamples = read(chanFd[chan], buffers_s[chan], bufSize); + } + if (currReadSamples <= 0) { if (errno == EAGAIN || errno == ENODATA) @@ -3511,14 +3774,23 @@ int pxi6368EV_readAndSaveAllChannels( } else { - for (int sampleIdx = 0; sampleIdx < currReadSamples; sampleIdx++) - { - // Saving the sample in the associated buffer - bufferHandlers[chan]->processSample(buffers[chan][sampleIdx]); + // std::cout<< "READ AND SAVE 2.1 " << std::endl; + + if (saveConv){ + + for (int sampleIdx = 0; sampleIdx < currReadSamples; sampleIdx++){ + bufferHandlers[chan]->processSample(&buffers_f[chan][sampleIdx]); + } + } + else{ + for (int sampleIdx = 0; sampleIdx < currReadSamples/sizeof(short); sampleIdx++){ + bufferHandlers[chan]->processSample(&buffers_s[chan][sampleIdx]); + } } } } } +// std::cout<< "READ AND SAVE 3 " << std::endl; for (chan = 0; chan < nChan; chan++) { @@ -3529,9 +3801,9 @@ int pxi6368EV_readAndSaveAllChannels( std::cout << "STOPPED" << std::endl; delete eventHandlers[chan]; } - std::cout << "TERMINATING BUFFER HANDLER...." << std::endl; + //std::cout << "TERMINATING BUFFER HANDLER...." << std::endl; bufferHandlers[chan]->terminate(); - std::cout << "TERMINATED" << std::endl; + //std::cout << "TERMINATED" << std::endl; } saveList->stop(); @@ -3582,3 +3854,52 @@ int64_t NI6683_get_TCN_time() } return time; } + +int NI6683_stop(int devFd, int* activeFds, int size) +{ + printf("STOPPING NI6683...\n"); + + int status = 0; + uint32_t count; + + status = nisync_abort_all_ftes(devFd); + if (status == -1) return -1; + + for(int i = 0; i < size; i++){ + printf("Disabling future events for FD %i \n", activeFds[i]); + status = nisync_disable_future_time_events(activeFds[i]); + if (status == -1) { + printf("Disabling future events for FD %i failed with errno %s\n", activeFds[i], strerror(errno)); + return -1; + } + close(activeFds[i]); + } + + // status = nisync_get_num_pending_ftes(devFd, &count); + // printf("ACTIVE FDEs: %i\n", count); + + close(devFd); + +printf("STOPPED!\n"); +return 0; +} + +int NI6683_close(int devFd, int* Fds,int size) +{ + printf("CLOSING NI6683...\n"); + + int status = 0; + + for(int i = 0; i < size; ++i){ + printf("Closing FD %i\n", Fds[i]); + close(Fds[i]); + } + // printf("Closing FD %i\n", devFd); + + + printf("CLOSED!\n"); + return 0; +} + + + diff --git a/device_support/national/cRioMPAGfunction.cpp b/device_support/national/cRioMPAGfunction.cpp index 8195696426..38a73a5a33 100644 --- a/device_support/national/cRioMPAGfunction.cpp +++ b/device_support/national/cRioMPAGfunction.cpp @@ -31,6 +31,8 @@ NiFpga_Status crioMpagResetFifo(NiFpga_Session session, const char *fifoName, Ni size_t rElem; uint64_t dummy; uint64_t *dummyElem; + int numDmaRead; + int maxDmaRead = 1000; if (DEBUG == 1) return status; @@ -51,10 +53,14 @@ NiFpga_Status crioMpagResetFifo(NiFpga_Session session, const char *fifoName, Ni } printf("Num elements in %s %d\n", fifoName, nElem); - - while (nElem > 0) + + numDmaRead = 0; + while ( nElem > 0 ) { + if ( numDmaRead > maxDmaRead ) + break; + dummyElem = (uint64_t *)calloc(nElem, sizeof(uint64_t)); NiFpga_MergeStatus(&status, NiFpga_ReadFifoU64(session, @@ -70,13 +76,21 @@ NiFpga_Status crioMpagResetFifo(NiFpga_Session session, const char *fifoName, Ni return status; } - printf("Remaining elements in %s %d\n", fifoName, rElem); free(dummyElem); nElem = rElem; //fede 20210312 + numDmaRead++; + + //printf("Remaining elements in %s %d %d\n", fifoName, rElem, numDmaRead); //20221214 + } - return status; + if ( numDmaRead < maxDmaRead ) + { + return status; + } else { + return -1; + } } @@ -88,7 +102,7 @@ NiFpga_Status crioMpagInit(NiFpga_Session *session, const char *cRioId, size_t f return status; /* opens a session, downloads the bitstream, and runs the FPGA */ - printf("cRio %d Opening a session... %s \n", cRioId, NiFpga_MainFPGA_9159_Bitfile); + printf("cRio %s Opening a session... %s \n", cRioId, NiFpga_MainFPGA_9159_Bitfile); NiFpga_MergeStatus(&status, status = NiFpga_Open(NiFpga_MainFPGA_9159_Bitfile, NiFpga_MainFPGA_9159_Signature, @@ -347,6 +361,8 @@ void *acquisitionThreadFPGA(void *args) char **streamNames = fpgaAcq->streamNames; float *streamGains = fpgaAcq->streamGains; float *streamOffsets = fpgaAcq->streamOffsets; + uint8_t clockMode = fpgaAcq->clockMode; + NiFpga_Bool val; NiFpga_MergeStatus(&status, NiFpga_ReadBool(session, NiFpga_MainFPGA_9159_ControlBool_Start, @@ -374,6 +390,30 @@ void *acquisitionThreadFPGA(void *args) usleep(200000); status = crioMpagResetFifo(session, fifoName, fifoId); + status = NiFpga_Status_Success;//Test 14/02/2023 + if( status == -1 ) + { + printf("\n\nDMA buffer reset failed for slave index %d. This occurs when the acquisition clock\n is active during initialization. The clock must be active \nafter initialization. The acquisition system must be configured with a Gated Clock.\n", slaveIdx); + fpgaAcq->retStatus = status; + pthread_exit(NULL); + } + if ( NiFpga_IsError(status) ) + { + fpgaAcq->retStatus = status; + pthread_exit(NULL); + } + + //Configure clock mode + if (slaveIdx == SLAVE_A) + { + /* + Only one thread needs to configure the clock mode. + The clock mode is defined by default as external + */ + NiFpga_MergeStatus(&status, NiFpga_WriteBool(session, + NiFpga_MainFPGA_9159_ControlBool_Internal_ACQ_Trigger, + clockMode)); + } if (DEBUG) { @@ -399,11 +439,8 @@ void *acquisitionThreadFPGA(void *args) while ((!*(uint8_t *)stopAcq) == 1) { - readElem = readMpagFifoData(session, fifoName, fifoId, data, slaveDataSamples, stopAcq); - - //printf("Data Read from DMA %s OK\n", fifoName); - printf("."); + printf("*"); fflush(stdout); if (DEBUG) @@ -548,9 +585,27 @@ printf("Chan Idx %d %d %d \n",chanIdx, slaveCh, readChanSmp[slaveCh]); //numSamples = readChanSmp[0] + segmentSize; numSamples = bufSize + segmentSize; } + printf("\n"); + free(readChanSmp); free(bufReadChanSmp); + + //Set clock mode to external + if (slaveIdx == SLAVE_A) + { + /* + Clock mode is set to external to stop data stream + generation via DMA. NB the external clock source + must be a gated clock and with internal clock there + must not be an external clock + */ + NiFpga_MergeStatus(&status, NiFpga_WriteBool(session, + NiFpga_MainFPGA_9159_ControlBool_Internal_ACQ_Trigger, + CLOCK_MODE_EXTERNAL)); + } + fpgaAcq->retStatus = status; printf("EXIT thread %s\n", fifoName); + pthread_exit(NULL); } /******************************************************************************/ @@ -594,6 +649,7 @@ int mpag_readAndSaveAllChannels(NiFpga_Session session, int nChan, int *chanStat } //Delete first all data nids + printf("Delete all saved data if present\n"); TreeNode *currNode; for (int i = 0; i < nChan; i++) { @@ -645,6 +701,8 @@ int mpag_readAndSaveAllChannels(NiFpga_Session session, int nChan, int *chanStat printf("Error deleting data nodes %s : %s\n", currNode->getPath(), exc.what()); } } + printf("All saved data deleted\n"); + struct_FPGA structFpga[3]; struct_FPGA_ACQ structFpgaAcq; @@ -684,9 +742,11 @@ int mpag_readAndSaveAllChannels(NiFpga_Session session, int nChan, int *chanStat structFpgaAcq.streamGains = streamGains; structFpgaAcq.streamOffsets = streamOffsets; structFpgaAcq.streamFactor = streamFactor; + structFpgaAcq.clockMode = clockMode; // Clock mode must be passed to the acquisition threads to configure the clock source correctly + /* Enable DMA */ - + printf("Enable DMA link from slave\n"); status = generateMpagFpgaBoolPule(session, NiFpga_MainFPGA_9159_ControlBool_START_DMA, 0.1); if (NiFpga_IsError(status)) { @@ -694,10 +754,15 @@ int mpag_readAndSaveAllChannels(NiFpga_Session session, int nChan, int *chanStat return -1; } - /* Enable interna Externa clock mode*/ + /* + Force clock mode to External + Even if the clok mode is defined as internal during initialization + it is forced to be external. This is necessary to avoid in external + clock mode the system immediately starts receiving data via DMA. + */ NiFpga_MergeStatus(&status, NiFpga_WriteBool(session, NiFpga_MainFPGA_9159_ControlBool_Internal_ACQ_Trigger, - clockMode)); + CLOCK_MODE_EXTERNAL)); if (NiFpga_IsError(status)) { @@ -723,15 +788,19 @@ int mpag_readAndSaveAllChannels(NiFpga_Session session, int nChan, int *chanStat err[2] = pthread_create(&threadSlaveC, NULL, &acquisitionThreadFPGA, &structFpga[2]); errorBit |= err[2] ? 1 << 2 : 0; + printf("errorBit %d\n", errorBit); + if (errorBit) //error on one thread creation must be close other thread { - printf("Error on create thread\n"); + printf("Error on acquisition thread creation\n"); *(uint8_t *)stopAcq = 1; + return -1; } usleep(30000); - + startMpagFpga(session); + sem_post(&structFpga[0].semThreadStart); sem_post(&structFpga[1].semThreadStart); sem_post(&structFpga[2].semThreadStart); @@ -739,11 +808,24 @@ int mpag_readAndSaveAllChannels(NiFpga_Session session, int nChan, int *chanStat pthread_join(threadSlaveA, NULL); pthread_join(threadSlaveB, NULL); pthread_join(threadSlaveC, NULL); + sem_destroy(&structFpga[0].semThreadStart); sem_destroy(&structFpga[1].semThreadStart); sem_destroy(&structFpga[2].semThreadStart); - printf("EXIT from mpagQueuedAcqData %d \n", (!*(int *)stopAcq)); + printf("structFpga[0].structFpgaAcq->retStatus %d\n", structFpga[0].structFpgaAcq->retStatus); + printf("structFpga[1].structFpgaAcq->retStatus %d\n", structFpga[1].structFpgaAcq->retStatus); + printf("structFpga[2].structFpgaAcq->retStatus %d\n", structFpga[2].structFpgaAcq->retStatus); + + if( structFpga[0].structFpgaAcq->retStatus < 0 || + structFpga[1].structFpgaAcq->retStatus < 0 || + structFpga[2].structFpgaAcq->retStatus < 0 ) + { + return -1; + } + + + printf("----- EXIT from mpagQueuedAcqData %d \n", (!*(int *)stopAcq)); return 0; } diff --git a/device_support/national/cRioMPAGfunction.h b/device_support/national/cRioMPAGfunction.h index 4a2144d77d..047f2e8123 100644 --- a/device_support/national/cRioMPAGfunction.h +++ b/device_support/national/cRioMPAGfunction.h @@ -36,6 +36,10 @@ #define STOP_PLC_CMD 0 #define START_PLC_CMD 1 +#define CLOCK_MODE_INTERNAL 1 +#define CLOCK_MODE_EXTERNAL 0 + + static const char *simb = "|/-\\"; extern "C" @@ -83,6 +87,8 @@ typedef struct t_struct_FPGA_ACQ float *streamGains; float *streamOffsets; int streamFactor; + uint8_t clockMode; + NiFpga_Status retStatus; } struct_FPGA_ACQ; typedef struct t_struct_FPGA diff --git a/device_support/national/generateWave.cpp b/device_support/national/generateWave.cpp index 5bd1c9dbf2..c81cfd01ba 100644 --- a/device_support/national/generateWave.cpp +++ b/device_support/national/generateWave.cpp @@ -24,6 +24,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include +#include #include #include #include diff --git a/device_support/national/probeTermControl.cpp b/device_support/national/probeTermControl.cpp index 597c3775d5..03525ce320 100644 --- a/device_support/national/probeTermControl.cpp +++ b/device_support/national/probeTermControl.cpp @@ -140,8 +140,8 @@ int configureOutput(int *chanOutFD, uint32_t deviceNum, uint32_t outChanRef, int configureInput(int *chanInFd, uint32_t deviceNum, uint32_t inChan[], double frequency, int numChan) { - int diffMapChannel[16] = {-1, 0, 1, 2, 3, 4, 5, 6, - 7, 16, 17, 18, 19, 20.21, 22, 23}; + int diffMapChannel[17] = {-1, 0, 1, 2, 3, 4, 5, 6, + 7, 16, 17, 18, 19, 20, 21, 22, 23}; char filename[256]; int i; pxi6259_ai_conf_t aiConfig; diff --git a/java/jdevices/src/main/java/NI6683Setup.java b/java/jdevices/src/main/java/NI6683Setup.java index 70c75f814a..4d6ccd73df 100644 --- a/java/jdevices/src/main/java/NI6683Setup.java +++ b/java/jdevices/src/main/java/NI6683Setup.java @@ -39,6 +39,7 @@ private void initComponents() { jPanel76 = new javax.swing.JPanel(); deviceChoice24 = new DeviceChoice(); deviceField125 = new DeviceField(); + deviceField6 = new DeviceField(); jPanel77 = new javax.swing.JPanel(); deviceField120 = new DeviceField(); deviceField121 = new DeviceField(); @@ -50,6 +51,7 @@ private void initComponents() { jPanel80 = new javax.swing.JPanel(); deviceChoice25 = new DeviceChoice(); deviceField126 = new DeviceField(); + deviceField7 = new DeviceField(); jPanel81 = new javax.swing.JPanel(); deviceField127 = new DeviceField(); deviceField128 = new DeviceField(); @@ -61,6 +63,7 @@ private void initComponents() { jPanel84 = new javax.swing.JPanel(); deviceChoice26 = new DeviceChoice(); deviceField132 = new DeviceField(); + deviceField8 = new DeviceField(); jPanel85 = new javax.swing.JPanel(); deviceField133 = new DeviceField(); deviceField134 = new DeviceField(); @@ -215,6 +218,7 @@ private void initComponents() { jPanel140 = new javax.swing.JPanel(); deviceChoice40 = new DeviceChoice(); deviceField216 = new DeviceField(); + deviceField9 = new DeviceField(); jPanel141 = new javax.swing.JPanel(); deviceField217 = new DeviceField(); deviceField218 = new DeviceField(); @@ -226,6 +230,7 @@ private void initComponents() { jPanel144 = new javax.swing.JPanel(); deviceChoice41 = new DeviceChoice(); deviceField222 = new DeviceField(); + deviceField10 = new DeviceField(); jPanel145 = new javax.swing.JPanel(); deviceField223 = new DeviceField(); deviceField224 = new DeviceField(); @@ -237,6 +242,7 @@ private void initComponents() { jPanel148 = new javax.swing.JPanel(); deviceChoice42 = new DeviceChoice(); deviceField228 = new DeviceField(); + deviceField11 = new DeviceField(); jPanel149 = new javax.swing.JPanel(); deviceField229 = new DeviceField(); deviceField230 = new DeviceField(); @@ -248,6 +254,7 @@ private void initComponents() { jPanel152 = new javax.swing.JPanel(); deviceChoice43 = new DeviceChoice(); deviceField234 = new DeviceField(); + deviceField12 = new DeviceField(); jPanel153 = new javax.swing.JPanel(); deviceField235 = new DeviceField(); deviceField236 = new DeviceField(); @@ -259,6 +266,7 @@ private void initComponents() { jPanel156 = new javax.swing.JPanel(); deviceChoice44 = new DeviceChoice(); deviceField240 = new DeviceField(); + deviceField13 = new DeviceField(); jPanel157 = new javax.swing.JPanel(); deviceField241 = new DeviceField(); deviceField242 = new DeviceField(); @@ -270,6 +278,7 @@ private void initComponents() { jPanel160 = new javax.swing.JPanel(); deviceChoice45 = new DeviceChoice(); deviceField246 = new DeviceField(); + deviceField14 = new DeviceField(); jPanel161 = new javax.swing.JPanel(); deviceField247 = new DeviceField(); deviceField248 = new DeviceField(); @@ -281,6 +290,7 @@ private void initComponents() { jPanel164 = new javax.swing.JPanel(); deviceChoice46 = new DeviceChoice(); deviceField252 = new DeviceField(); + deviceField15 = new DeviceField(); jPanel165 = new javax.swing.JPanel(); deviceField253 = new DeviceField(); deviceField254 = new DeviceField(); @@ -292,6 +302,7 @@ private void initComponents() { jPanel168 = new javax.swing.JPanel(); deviceChoice47 = new DeviceChoice(); deviceField258 = new DeviceField(); + deviceField16 = new DeviceField(); jPanel169 = new javax.swing.JPanel(); deviceField259 = new DeviceField(); deviceField260 = new DeviceField(); @@ -306,16 +317,15 @@ private void initComponents() { deviceChoice1 = new DeviceChoice(); jPanel4 = new javax.swing.JPanel(); deviceField2 = new DeviceField(); - deviceField5 = new DeviceField(); jPanel5 = new javax.swing.JPanel(); deviceField3 = new DeviceField(); deviceField4 = new DeviceField(); - setDeviceProvider("localhost:8123"); + setDeviceProvider("mcpsl-pcf:8001"); setDeviceTitle("NI 6683 Timing Device"); setDeviceType("NI6683"); setHeight(400); - setWidth(800); + setWidth(1000); getContentPane().add(deviceButtons1, java.awt.BorderLayout.PAGE_END); jPanel1.setLayout(new java.awt.BorderLayout()); @@ -336,6 +346,13 @@ private void initComponents() { deviceField125.setTextOnly(true); jPanel76.add(deviceField125); + deviceField6.setIdentifier(""); + deviceField6.setLabelString("COMMENT"); + deviceField6.setNumCols(20); + deviceField6.setOffsetNid(250); + deviceField6.setTextOnly(true); + jPanel76.add(deviceField6); + jPanel75.add(jPanel76); deviceField120.setIdentifier(""); @@ -387,6 +404,13 @@ private void initComponents() { deviceField126.setTextOnly(true); jPanel80.add(deviceField126); + deviceField7.setIdentifier(""); + deviceField7.setLabelString("COMMENT"); + deviceField7.setNumCols(20); + deviceField7.setOffsetNid(251); + deviceField7.setTextOnly(true); + jPanel80.add(deviceField7); + jPanel79.add(jPanel80); deviceField127.setIdentifier(""); @@ -438,6 +462,13 @@ private void initComponents() { deviceField132.setTextOnly(true); jPanel84.add(deviceField132); + deviceField8.setIdentifier(""); + deviceField8.setLabelString("COMMENT"); + deviceField8.setNumCols(20); + deviceField8.setOffsetNid(252); + deviceField8.setTextOnly(true); + jPanel84.add(deviceField8); + jPanel83.add(jPanel84); deviceField133.setIdentifier(""); @@ -1152,6 +1183,13 @@ private void initComponents() { deviceField216.setTextOnly(true); jPanel140.add(deviceField216); + deviceField9.setIdentifier(""); + deviceField9.setLabelString("COMMENT"); + deviceField9.setNumCols(20); + deviceField9.setOffsetNid(266); + deviceField9.setTextOnly(true); + jPanel140.add(deviceField9); + jPanel139.add(jPanel140); deviceField217.setIdentifier(""); @@ -1203,6 +1241,13 @@ private void initComponents() { deviceField222.setTextOnly(true); jPanel144.add(deviceField222); + deviceField10.setIdentifier(""); + deviceField10.setLabelString("COMMENT"); + deviceField10.setNumCols(20); + deviceField10.setOffsetNid(267); + deviceField10.setTextOnly(true); + jPanel144.add(deviceField10); + jPanel143.add(jPanel144); deviceField223.setIdentifier(""); @@ -1254,6 +1299,13 @@ private void initComponents() { deviceField228.setTextOnly(true); jPanel148.add(deviceField228); + deviceField11.setIdentifier(""); + deviceField11.setLabelString("COMMENT"); + deviceField11.setNumCols(20); + deviceField11.setOffsetNid(268); + deviceField11.setTextOnly(true); + jPanel148.add(deviceField11); + jPanel147.add(jPanel148); deviceField229.setIdentifier(""); @@ -1305,6 +1357,13 @@ private void initComponents() { deviceField234.setTextOnly(true); jPanel152.add(deviceField234); + deviceField12.setIdentifier(""); + deviceField12.setLabelString("COMMENT"); + deviceField12.setNumCols(20); + deviceField12.setOffsetNid(269); + deviceField12.setTextOnly(true); + jPanel152.add(deviceField12); + jPanel151.add(jPanel152); deviceField235.setIdentifier(""); @@ -1356,6 +1415,13 @@ private void initComponents() { deviceField240.setTextOnly(true); jPanel156.add(deviceField240); + deviceField13.setIdentifier(""); + deviceField13.setLabelString("COMMENT"); + deviceField13.setNumCols(20); + deviceField13.setOffsetNid(270); + deviceField13.setTextOnly(true); + jPanel156.add(deviceField13); + jPanel155.add(jPanel156); deviceField241.setIdentifier(""); @@ -1407,6 +1473,13 @@ private void initComponents() { deviceField246.setTextOnly(true); jPanel160.add(deviceField246); + deviceField14.setIdentifier(""); + deviceField14.setLabelString("COMMENT"); + deviceField14.setNumCols(20); + deviceField14.setOffsetNid(271); + deviceField14.setTextOnly(true); + jPanel160.add(deviceField14); + jPanel159.add(jPanel160); deviceField247.setIdentifier(""); @@ -1458,6 +1531,13 @@ private void initComponents() { deviceField252.setTextOnly(true); jPanel164.add(deviceField252); + deviceField15.setIdentifier(""); + deviceField15.setLabelString("COMMENT"); + deviceField15.setNumCols(20); + deviceField15.setOffsetNid(272); + deviceField15.setTextOnly(true); + jPanel164.add(deviceField15); + jPanel163.add(jPanel164); deviceField253.setIdentifier(""); @@ -1509,6 +1589,13 @@ private void initComponents() { deviceField258.setTextOnly(true); jPanel168.add(deviceField258); + deviceField16.setIdentifier(""); + deviceField16.setLabelString("COMMENT"); + deviceField16.setNumCols(20); + deviceField16.setOffsetNid(273); + deviceField16.setTextOnly(true); + jPanel168.add(deviceField16); + jPanel167.add(jPanel168); deviceField259.setIdentifier(""); @@ -1572,13 +1659,6 @@ private void initComponents() { deviceField2.setTextOnly(true); jPanel4.add(deviceField2); - deviceField5.setIdentifier(""); - deviceField5.setLabelString("Trigger Event"); - deviceField5.setNumCols(15); - deviceField5.setOffsetNid(249); - deviceField5.setTextOnly(true); - jPanel4.add(deviceField5); - jPanel2.add(jPanel4); deviceField3.setIdentifier(""); @@ -1628,6 +1708,9 @@ private void initComponents() { private DeviceChoice deviceChoice47; private DeviceDispatch deviceDispatch1; private DeviceField deviceField1; + private DeviceField deviceField10; + private DeviceField deviceField11; + private DeviceField deviceField12; private DeviceField deviceField120; private DeviceField deviceField121; private DeviceField deviceField122; @@ -1638,6 +1721,7 @@ private void initComponents() { private DeviceField deviceField127; private DeviceField deviceField128; private DeviceField deviceField129; + private DeviceField deviceField13; private DeviceField deviceField130; private DeviceField deviceField131; private DeviceField deviceField132; @@ -1648,6 +1732,7 @@ private void initComponents() { private DeviceField deviceField137; private DeviceField deviceField138; private DeviceField deviceField139; + private DeviceField deviceField14; private DeviceField deviceField140; private DeviceField deviceField141; private DeviceField deviceField142; @@ -1658,6 +1743,7 @@ private void initComponents() { private DeviceField deviceField147; private DeviceField deviceField148; private DeviceField deviceField149; + private DeviceField deviceField15; private DeviceField deviceField150; private DeviceField deviceField151; private DeviceField deviceField152; @@ -1668,6 +1754,7 @@ private void initComponents() { private DeviceField deviceField157; private DeviceField deviceField158; private DeviceField deviceField159; + private DeviceField deviceField16; private DeviceField deviceField160; private DeviceField deviceField161; private DeviceField deviceField162; @@ -1775,7 +1862,10 @@ private void initComponents() { private DeviceField deviceField263; private DeviceField deviceField3; private DeviceField deviceField4; - private DeviceField deviceField5; + private DeviceField deviceField6; + private DeviceField deviceField7; + private DeviceField deviceField8; + private DeviceField deviceField9; private javax.swing.JPanel jPanel1; private javax.swing.JPanel jPanel100; private javax.swing.JPanel jPanel101; diff --git a/java/jdevices/src/main/resources/NI6683Setup.form b/java/jdevices/src/main/resources/NI6683Setup.form index cbc7e7d150..73a4ac4d56 100644 --- a/java/jdevices/src/main/resources/NI6683Setup.form +++ b/java/jdevices/src/main/resources/NI6683Setup.form @@ -2,11 +2,11 @@
- + - + @@ -24,7 +24,7 @@ - + @@ -102,6 +102,15 @@ + + + + + + + + + @@ -203,6 +212,15 @@ + + + + + + + + + @@ -304,6 +322,15 @@ + + + + + + + + + @@ -1718,6 +1745,15 @@ + + + + + + + + + @@ -1819,6 +1855,15 @@ + + + + + + + + + @@ -1920,6 +1965,15 @@ + + + + + + + + + @@ -2021,6 +2075,15 @@ + + + + + + + + + @@ -2122,6 +2185,15 @@ + + + + + + + + + @@ -2223,6 +2295,15 @@ + + + + + + + + + @@ -2324,6 +2405,15 @@ + + + + + + + + + @@ -2425,6 +2515,15 @@ + + + + + + + + + diff --git a/pydevices/RfxDevices/CRIO_MPAG.py b/pydevices/RfxDevices/CRIO_MPAG.py index aba9ef3424..928b59192c 100644 --- a/pydevices/RfxDevices/CRIO_MPAG.py +++ b/pydevices/RfxDevices/CRIO_MPAG.py @@ -1,10 +1,11 @@ -from MDSplus import mdsExceptions, Device, Data, Range, Dimension, Window, Int32, Float32, Float64 +from MDSplus import mdsExceptions, Device, Data, Range, Dimension, Window, Int32, Float32, Float64, Tree from MDSplus.mdsExceptions import DevBAD_PARAMETER from threading import Thread from ctypes import CDLL, byref, c_int, c_void_p, c_byte, c_float, c_char_p, c_uint, c_short, c_byte, c_double, c_uint8, c_int32, c_uint16 import os from time import sleep import sys, traceback +import datetime class CRIO_MPAG(Device): """NI Compact RIO MITICA AGPS analogue signals""" @@ -119,7 +120,7 @@ def initializeInfo(self, boardId, fifoDepthSize): CRIO_MPAG.niInterfaceLib = CDLL("libNiInterface.so") try: - status = CRIO_MPAG.niInterfaceLib.crioMpagInit( byref(self.session), c_char_p(boardId), c_uint(fifoDepthSize) ) + status = CRIO_MPAG.niInterfaceLib.crioMpagInit( byref(self.session), c_char_p(boardId.encode('utf-8')), c_uint(fifoDepthSize) ) if status < 0 : raise mdsExceptions.TclFAILED_ESSENTIAL except BaseException as e: @@ -156,6 +157,10 @@ def configure(self, device, treePtr): def run(self): + self.device.setTree( + Tree(self.device.getTree().name, self.device.getTree().shot)) + self.device = self.device.copy() + bufSize = self.device.buf_size.data() segmentSize = self.device.seg_length.data() trigSource = self.device.trig_source.data() @@ -163,7 +168,7 @@ def run(self): clockSource = self.device.clock_source.evaluate() period = float( clockSource.getDelta() ) timeAt0 = startTime - numSamples = -1 # continuous + numSamples = -1 # Forced to continuous acquisition clockMode = self.device.clockModeDict[self.device.clock_mode.data()] print ('startSave') @@ -243,9 +248,8 @@ def run(self): return def stop(self): - #self.stopAcq.value = 1; print (self.stopAcq) - CRIO_MPAG.niInterfaceLib.setStopAcqFlag(self.stopAcq); + CRIO_MPAG.niInterfaceLib.setStopAcqFlag(self.stopAcq) #############End Inner class AsynchStore @@ -405,7 +409,7 @@ def init(self): for slave in ['a','b','c']: for chan in range(1, self.NUM_SLAVE_CHANNEL+1): - #Empy the node which will contain the segmented data + #Empty the node which will contain the segmented data dataRawNode = getattr(self, 'slave_crio_%c_channel_%02d_data_raw'%(slave, chan)) dataRawNode.deleteData() dataRawNode.setCompressOnPut(False) @@ -415,7 +419,7 @@ def init(self): for adcIdx in ['1','2']: for chan in range(1, self.NUM_9220_CHANNEL+1): - #Empy the node which will contain the segmented data + #Empty the node which will contain the segmented data dataRawNode = getattr(self, 'ni_9220_%c_channel_%02d_data_raw'%(adcIdx, chan)) dataRawNode.deleteData() dataRawNode.setCompressOnPut(False) @@ -452,7 +456,7 @@ def start_store(self): treePtr = c_void_p(0) - CRIO_MPAG.niInterfaceLib.openTree(c_char_p(self.getTree().name), c_int(self.getTree().shot), byref(treePtr)) + CRIO_MPAG.niInterfaceLib.openTree(c_char_p((self.getTree().name).encode('utf-8')), c_int(self.getTree().shot), byref(treePtr)) self.worker = self.AsynchStore() self.worker.daemon = True @@ -517,7 +521,7 @@ def start_cmd(self): niLib = CDLL("libNiInterface.so") - status = niLib.executeMpagFpgaCommand( c_char_p(boardIdDev), CRIO_MPAG.START_PLC_COMMAND ) + status = niLib.executeMpagFpgaCommand( c_char_p(boardIdDev.encode('utf-8')), CRIO_MPAG.START_PLC_COMMAND ) if status < 0 : Data.execute('DevLogErr($1,$2)', self.getNid(), 'cRIO MPAG start command error.') return 0 @@ -537,7 +541,7 @@ def stop_cmd(self): niLib = CDLL("libNiInterface.so") - status = niLib.executeMpagFpgaCommand( c_char_p(boardIdDev), CRIO_MPAG.STOP_PLC_COMMAND ) + status = niLib.executeMpagFpgaCommand( c_char_p(boardIdDev.encode('utf-8')), CRIO_MPAG.STOP_PLC_COMMAND ) if status < 0 : Data.execute('DevLogErr($1,$2)', self.getNid(), 'cRIO MPAG stop command error.') return 0 diff --git a/pydevices/RfxDevices/NI6368AI.py b/pydevices/RfxDevices/NI6368AI.py index 0fb0f9e3a7..a963881e46 100644 --- a/pydevices/RfxDevices/NI6368AI.py +++ b/pydevices/RfxDevices/NI6368AI.py @@ -244,8 +244,6 @@ def configure(self, device, ai_fd, chanMap, hwChanMap, treePtr, stopAcq): def run(self): import os - self.device.setTree( - Tree(self.device.getTree().name, self.device.getTree().shot)) self.device = self.device.copy() bufSize = self.device.buf_size.data() @@ -464,7 +462,7 @@ def init(self): #self.debugPrint('Open ai_fd: ', self.ai_fd) device_info = self.XSERIES_DEV_INFO( - 0, "", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) + 0, "".encode('utf-8'), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) # get card info status = NI6368AI.niInterfaceLib._xseries_get_device_info( @@ -843,15 +841,13 @@ def start_store(self): print ('Tree opening') treePtr = c_void_p(0) - NI6368AI.niInterfaceLib.openTree( - c_char_p(self.getTree().name), c_int(self.getTree().shot), byref(treePtr)) + NI6368AI.niInterfaceLib.openTree(c_char_p(self.getTree().name.encode('utf-8')), c_int(self.getTree().shot), byref(treePtr)) print ('Tree opened') stopAcq = c_void_p(0) NI6368AI.niInterfaceLib.getStopAcqFlag(byref(stopAcq)) - self.worker.configure(self.copy(), self.ai_fd, - chanMap, self.diffChanMap, treePtr, stopAcq) + self.worker.configure(self, self.ai_fd, chanMap, self.diffChanMap, treePtr, stopAcq) self.saveWorker() self.worker.start() diff --git a/pydevices/RfxDevices/NI6368EV.py b/pydevices/RfxDevices/NI6368EV.py index 05cc756b5e..2df67ec61f 100644 --- a/pydevices/RfxDevices/NI6368EV.py +++ b/pydevices/RfxDevices/NI6368EV.py @@ -40,7 +40,7 @@ class NI6368EV(Device): {'path':'.CHANNEL_%d'%(i+1), 'type':'structure'}, {'path':'.CHANNEL_%d:STATE'%(i+1), 'type':'text', 'value':'BURST(FREQ1)'}, {'path':'.CHANNEL_%d:RANGE'%(i+1), 'type':'numeric', 'value':10}, - {'path':'.CHANNEL_%d:EVENT_NAME'%(i+1), 'type':'text', 'value':'disabled '}, # EVENTI CON SPAZIO ALLA FINE... NB!!! + {'path':'.CHANNEL_%d:EVENT_NAME'%(i+1), 'type':'text', 'value':'disabled '}, {'path':'.CHANNEL_%d:START_TIME'%(i+1), 'type':'numeric', 'value':0}, {'path':'.CHANNEL_%d:END_TIME'%(i+1), 'type':'numeric', 'value':2}, {'path':'.CHANNEL_%d:CALIB_PARAM'%(i+1), 'type':'numeric', 'options':('no_write_model')}, @@ -61,6 +61,10 @@ class NI6368EV(Device): 'options': ('no_write_shot',)} ]) + for i in range(0, 16): + parts.append({'path': '.CHANNEL_%d:RES_RAW' % ( + i+1), 'type': 'signal', 'options': ('no_write_model', 'no_compress_on_put')}) + DEV_IS_OPEN = 1 DEV_OPEN = 1 @@ -162,6 +166,8 @@ class XSERIES_DEV_INFO(Structure): ni6368chanPreTimes = {} ni6368chanPostTimes = {} + currShot = 0 + def debugPrint(self, msg='', obj=''): print (self.name + ':' + msg, obj) @@ -178,6 +184,14 @@ def restoreInfo(self): self.ai_fd = NI6368EV.ni6368EvFds[self.getNid()] return self.DEV_IS_OPEN # if present, already opened except: + + try: + NI6368EV.currShot = self.getTree().shot + print(NI6368EV.currShot) + except Exception as ex: + Data.execute('DevLogErr($1,$2)', self.getNid(), 'Missing shot number '+str(ex)) + raise mdsExceptions.TclFAILED_ESSENTIAL + try: boardId = self.board_id.data() #The boardId number refers to device number (/dev/pxie6368.N) @@ -249,6 +263,9 @@ def run(self): chanPostTimes = NI6368EV.ni6368chanPostTimes[nid] chanFd = [] chanNid = [] + coeffsNids = [] + gainDividers = [] + f1Div = self.device.freq1_div.data() f2Div = self.device.freq2_div.data() baseFreq = self.device.clock_freq.data() @@ -267,34 +284,35 @@ def run(self): preTimes_c = (c_double * numChans)() postTimes_c = (c_double * numChans)() eventNames_c = (c_char_p * numChans)() + resNids = [] for chan in range(numChans): #range(numChans) if chanModes[chan] == 'CONTINUOUS(FREQ1)': # continuous at a single frequence Freq1 isBurst_c[chan] = 0 # it is not a burst f1Divs_c[chan] = f1Div f2Divs_c[chan] = f1Div - eventNames_c[chan] = c_char_p('') # no events + eventNames_c[chan] = c_char_p(''.encode('utf-8')) # no events elif chanModes[chan] == 'CONTINUOUS(FREQ2)': # continuous at a single frequence Freq2 isBurst_c[chan] = 0 f1Divs_c[chan] = f2Div f2Divs_c[chan] = f2Div - eventNames_c[chan] = c_char_p('') + eventNames_c[chan] = c_char_p(''.encode('utf-8')) elif chanModes[chan] == 'BURST(FREQ1)': # burst at a single frequence Freq1 isBurst_c[chan] = 1 f1Divs_c[chan] = f1Div f2Divs_c[chan] = f1Div - eventNames_c[chan] = c_char_p(chanEvents[chan]) - print ("CHANEVENTS: " + eventNames_c[chan]) + eventNames_c[chan] = c_char_p(chanEvents[chan].encode()) + print ("CHANEVENTS: " + eventNames_c[chan].decode()) elif chanModes[chan] == 'BURST(FREQ2)': # burst at a single frequence Freq2 isBurst_c[chan] = 1 f1Divs_c[chan] = f2Div f2Divs_c[chan] = f2Div - eventNames_c[chan] = c_char_p(chanEvents[chan]) + eventNames_c[chan] = c_char_p(chanEvents[chan].encode()) elif chanModes[chan] == 'DUAL SPEED': # switching frequence from F1 to F2 on defined period isBurst_c[chan] = 0 f1Divs_c[chan] = f1Div f2Divs_c[chan] = f2Div - eventNames_c[chan] = c_char_p(chanEvents[chan]) + eventNames_c[chan] = c_char_p(chanEvents[chan].encode()) elif chanModes[chan] == 'DISABLED': continue else: @@ -320,13 +338,18 @@ def run(self): chanNid.append( getattr(self.device, 'channel_%d_data_raw'%(self.chanMap[chan]+1)).getNid() ) #self.device.debugPrint ('chanFd '+'channel_%d_data_raw'%(self.chanMap[chan]+1), chanFd[chan]) + resNids.append( getattr(self.device, 'channel_%d_res_raw'%(self.chanMap[chan]+1)).getNid() ) + coeffsNids.append(getattr(self.device, 'channel_%d_calib_param' % (self.chanMap[chan]+1)).getNid()) # getting gain gain = getattr(self.device, 'channel_%d_range'%(self.chanMap[chan]+1)).data() gain_code = self.device.gainDict[gain] + gainDividers.append(1.) + # reading calibration params status = NI6368EV.niInterfaceLib.getCalibrationParams(currFd, gain_code, coeff) + gainValue = 0 if( status < 0 ): errno = NI6368EV.niInterfaceLib.getErrno() msg = 'Error (%d) %s' % (errno, os.strerror( errno )) @@ -335,9 +358,9 @@ def run(self): gainValue = self.device.gainValueDict[gain] * 2. coeff[0] = coeff[2] = coeff[3] = 0 coeff[1] = c_float( gainValue / 32768. ) - print('SCRIVO CALIBRAZIONE', coeff) + #print('SCRIVO CALIBRAZIONE', coeff) getattr(self.device, 'channel_%d_calib_param'%(self.chanMap[chan]+1)).putData(Float32Array(coeff)) - print('SCRITTO') + #print('SCRITTO') # handling the buffer size for resampling if(bufSize > segmentSize): @@ -350,11 +373,14 @@ def run(self): # instantiating save list for mdsplus data saveList = c_void_p(0) - NI6368EV.niInterfaceLib.startSaveEV(byref(saveList), c_char_p(self.device.getTree().name.lower()), c_int(self.device.getTree().shot)) + NI6368EV.niInterfaceLib.startSave(byref(saveList)) chanNid_c = (c_int * len(chanNid) )(*chanNid) chanFd_c = (c_int * len(chanFd) )(*chanFd) chanMap_c = (c_int * len(chanFd) )(*self.chanMap) + resNids_c = (c_int * len(chanFd) )(*resNids) + coeffsNid_c = (c_int * len(coeffsNids))(*coeffsNids) + gainDividers_c = (c_float * len(gainDividers))(*gainDividers) print ("STARTING READ AND SAVE...") print ("numChans : " + str(numChans) + " chanFd: " + str(len(chanFd_c)) + " isBurst: " + str(len(isBurst_c)) + " fiDivs: " + str(len(f1Divs_c)) + " preTimes: " + str(len(preTimes_c)) + " EventNames: " + str(len(eventNames_c)) + " chanNid: " + str(len(chanNid_c))) @@ -364,8 +390,8 @@ def run(self): self.ai_fd, c_int(numChans), chanMap_c, chanFd_c, isBurst_c, f1Divs_c, f2Divs_c, c_double(maxDelay), c_double(baseFreq), preTimes_c, postTimes_c, c_double(baseStart), - c_int(bufSize), c_int(segmentSize), eventNames_c, - chanNid_c, self.treePtr, saveList, self.stopAcq) + c_int(bufSize), c_int(int(segmentSize)), eventNames_c, + chanNid_c, self.treePtr, saveList, self.device.clock_source.getNid(), NI6368EV.currShot, resNids_c, coeffsNid_c, gainDividers_c, self.stopAcq) except Exception as ex: self.device.debugPrint('Acquisition thread start error : %s'%(str(ex))) @@ -445,7 +471,7 @@ def init(self): fileName = '/dev/pxie-6368.'+str(self.boardId) dai_fd = os.open(fileName, os.O_RDWR) - device_info = self.XSERIES_DEV_INFO(0,"",0,0,0,0,0,0,0,0,0,0,0,0,0,0) + device_info = self.XSERIES_DEV_INFO(0,"".encode('utf-8'),0,0,0,0,0,0,0,0,0,0,0,0,0,0) # getting card info NI6368EV.niInterfaceLib.xseries_reset(self.ai_fd) @@ -596,6 +622,9 @@ def init(self): clockLineKey = self.clock_line.data() clockLine = self.clockLineDict[clockLineKey] # clockSource = self.clock_source.evaluate() + frequency = self.clock_freq.data() + clockSource = Range(None, None, Float64(1./frequency)) + self.clock_source.putData(clockSource) # self.debugPrint('PXI 6368 External CLOCK: ', clockSource) except: Data.execute('DevLogErr($1,$2)', self.getNid(),'Invalid clock definition') @@ -619,10 +648,7 @@ def init(self): # Program the convert to be the same as START. status = NI6368EV.niLib.xseries_set_ai_convert_clock(aiConf, clockLine, self.XSERIES_AI_POLARITY_ACTIVE_HIGH_OR_RISING_EDGE) self.debugPrint("xseries_set_ai_convert_clock ", clockLine) - # if(status == 0): - # # Program the sample and convert clock timing specifications - # status = NI6368EV.niLib.xseries_set_ai_scan_interval_counter(aiConf, self.XSERIES_SCAN_INTERVAL_COUNTER_TB3, self.XSERIES_SCAN_INTERVAL_COUNTER_POLARITY_RISING_EDGE, c_int(100000000/frequency), c_int(2)) - # self.debugPrint("xseries_set_ai_scan_interval_counter ", self.XSERIES_SCAN_INTERVAL_COUNTER_TB3) + if(status != 0): errno = NI6368EV.niInterfaceLib.getErrno() Data.execute('DevLogErr($1,$2)', self.getNid(), 'Cannot configure external device clock: (%d) %s' % (errno, os.strerror(errno))) @@ -650,7 +676,7 @@ def init(self): ################################### START STORE #################################### #################################################################################### def start_store(self): - self.debugPrint('================= PXI 6368 EV start store ===============') + self.debugPrint('================= PXI 6368 EV ===============') # retrieving the opened device info if self.restoreInfo() != self.DEV_IS_OPEN: @@ -664,7 +690,7 @@ def start_store(self): Data.execute('DevLogErr($1,$2)', self.getNid(), 'Module is in acquisition') return except: - pass + pass # worker initialization self.worker = self.AsynchStore() @@ -687,7 +713,7 @@ def start_store(self): print ('Tree opening') treePtr = c_void_p(0) - NI6368EV.niInterfaceLib.openTree(c_char_p(self.getTree().name), c_int(self.getTree().shot), byref(treePtr)) + NI6368EV.niInterfaceLib.openTree(c_char_p(self.getTree().name.encode('utf-8')), c_int(self.getTree().shot), byref(treePtr)) print ('Tree %s opened'%self.getTree().name) self.worker.configure(self.copy(), self.ai_fd, chanMap, self.diffChanMap, treePtr, stopAcq) diff --git a/pydevices/RfxDevices/NI6683.py b/pydevices/RfxDevices/NI6683.py index f966a7034f..ee21c1392f 100644 --- a/pydevices/RfxDevices/NI6683.py +++ b/pydevices/RfxDevices/NI6683.py @@ -28,21 +28,20 @@ """ RfxDevices ========== -@authors: Gabriele Manduchi (Consorzio RFX Padova) -@copyright: 2018 +@authors: Gabriele Manduchi & Luca Trevisan (Consorzio RFX Padova) +@copyright: 2023 @license: GNU GPL """ from MDSplus import Device, Data, Uint64, Event, Float64, Tree from MDSplus.mdsExceptions import DevCOMM_ERROR, DevBAD_PARAMETER from threading import Thread +import threading # from ctypes import CDLL, Structure, c_int, byref, c_int8, c_uint8, c_uint32, c_uint64, c from ctypes import * import os import sys import numpy as np import select -import time -import posix class NI6683(Device): """National Instrument 6683 device. Generation of clock and triggers and recording of events """ @@ -77,6 +76,9 @@ class NI6683(Device): 'options':('no_write_shot',)}) parts.append({'path':':TRIG_EVENT', 'type':'text'}) + for chanName in chanNames: + parts.append({'path':'.'+chanName+':COMMENT', 'type':'text'}) + del(chanName) DEV_IS_OPEN = 1 DEV_OPEN = 2 @@ -100,7 +102,7 @@ class NI6683(Device): ni6683TermEnds = {} ni6683PulseLengths = {} ni6683ModuleTriggerName = "" - ni6683RelTime = 0 #initialization + ni6683RelTime = 0 ni6683AbsTime = 0 @@ -117,6 +119,9 @@ class NI6683(Device): NISYNC_CLKOUT = 5 NISYNC_BOARD_CLK = 1 eventTime = None + device = None + deviceNID = 0 + useInternalReference = False class nisync_device_info(Structure): _fields_ = [("driver_version", c_char* 30), @@ -130,12 +135,39 @@ class nisync_device_info(Structure): ("oldest_compatible_revision", c_uint32), ("hardware_revision", c_uint32)] + + def reset_device(self): + enabled = c_int8() + activeEdge = c_int() + decimationCount = c_int() + + print("RESETTING DEVICE...") + + for termName in NI6683.termNameDict.keys(): + status = NI6683.niLib.nisync_abort_all_ftes(c_int(self.termDict[termName])) + self.checkStatus(status, "Cannot abort future time events when resetting the device ") + + status = NI6683.niLib.nisync_future_time_events_configuration(c_int(self.termDict[termName]), byref(enabled)) + self.checkStatus(status, 'Cannot inquire future events in "DISABLED" mode') + if enabled.value != 0: + print('DISABLE FUTURE EVENT for ' + termName + ' fd: '+ str(self.termDict[termName])) + status = NI6683.niLib.nisync_disable_future_time_events(c_int(self.termDict[termName])) + self.checkStatus(status, 'Cannot disable future events') + + status = NI6683.niLib.nisync_timestamp_trigger_configuration(c_int(self.termDict[termName]), + byref(enabled), byref(activeEdge), byref(decimationCount)) + self.checkStatus(status, 'Cannot inquire timestamp triggers') + if enabled.value != 0: + print('DISABLE TIMESTAMP for ' + termName + ' fd: '+ str(self.termDict[termName])) + status = NI6683.niLib.nisync_disable_timestamp_trigger(c_int(self.termDict[termName])) + self.checkStatus(status, 'Cannot disable timestamp triggers') def debugPrint(self, msg="", obj=""): print( self.name + ":" + msg, obj ) -#saveInfo and restoreInfo allow to handle open file descriptors +# saveInfo and restoreInfo allow to handle open file descriptors def saveInfo(self): + print("Saving " + str(self.fd)) NI6683.ni6683Fds[self.nid] = self.fd def restoreInfo(self): @@ -144,17 +176,17 @@ def restoreInfo(self): NI6683.termNameDict = {'PFI0': 0,'PFI1':1,'PFI2':2,'PXI_TRIG0': 11, 'PXI_TRIG1': 12,'PXI_TRIG2': 13,'PXI_TRIG3': 14,'PXI_TRIG4': 15,'PXI_TRIG5': 16, 'PXI_TRIG6': 17,'PXI_TRIG7': 18} -#'STAR0': 19,'STAR0': 19,'STAR1': 20, 'STAR2': 21,'STAR3': 22,'STAR4': 23,'STAR5': 24,'STAR6': 25,'STAR7': 26,'STAR8': 27,'STAR9': 28,'STAR10': 29,'STAR11': 30,'STAR12': 31} NI6683.typeDict = {'PXI6682': 0, 'PCI1588': 1,'PXI6683': 2,'PXI6683H': 3} +# loading the NiInterface library (/opt/mdsplus/device_support/national/NiInterface.cpp) if NI6683.niInterfaceLib is None: NI6683.niInterfaceLib = CDLL('libNiInterface.so') - +# investigating the file descriptors to check if the device is already opened if self.nid in NI6683.ni6683Fds.keys(): self.fd = NI6683.ni6683Fds[self.nid] self.termDict = NI6683.ni6683Dicts[self.nid] return self.DEV_IS_OPEN - else: + else: # if not opened, initialize the device by reading the information stored in the pulse file try: boardId = self.board_id.data() except: @@ -179,7 +211,11 @@ def restoreInfo(self): for termName in NI6683.termNameDict.keys(): try: self.termDict[termName] = NI6683.niLib.nisync_open_terminal(c_int(devType), c_int(boardId), c_int(NI6683.termNameDict[termName]), c_int(self.NISYNC_READ_NONBLOCKING)) - print(termName + ': '+str(self.termDict[termName])) + print('Opening ' + termName + ' with FD: '+str(self.termDict[termName])) + if (self.termDict[termName] == -1): # if terminal is busy, raise an exception + emsg = 'Cannot open terminal ' + termName + Data.execute('DevLogErr($1,$2)', self.getNid(), emsg) + raise DevCOMM_ERROR except Exception as e: emsg = 'Cannot open terminal %s : %s'%(termName, str(e)) Data.execute('DevLogErr($1,$2)', self.getNid(), emsg) @@ -188,72 +224,55 @@ def restoreInfo(self): NI6683.ni6683Dicts[self.nid] = self.termDict return self.DEV_OPEN - - def closeInfo(self): - self.termDict = NI6683.ni6683Dicts[self.nid] - if self.nid in NI6683.ni6683Fds.keys(): - self.fd = NI6683.ni6683Fds[self.nid] - del(NI6683.ni6683Fds[self.nid]) - for termName in NI6683.termNameDict.keys(): - try: - os.close(self.termDict[termName]) - except Exception as e: - emsg = 'Cannot close terminal %s : %s'%(termName, str(e)) - Data.execute('DevLogErr($1,$2)', self.getNid(), emsg) - raise DevCOMM_ERROR - try: - os.close(self.fd) - #self.fd.close() - except: - emsg = 'Cannot close device ' + str(self.fd) - Data.execute('DevLogErr($1,$2)', self.getNid(), emsg) - raise DevCOMM_ERROR - - +# getAbsTime converts the passed relative time in absolute time def getAbsTime(self, relTime): print ('DEBUG -> Abs time: ', NI6683.ni6683AbsTime, ' Reltime: ', relTime, ' RelStart: ', NI6683.ni6683RelTime) try: - result = long((relTime - NI6683.ni6683RelTime)*1000000000 + NI6683.ni6683AbsTime ) - print ('DEBUG -> Result: ', result) + result = ((relTime - NI6683.ni6683RelTime)*1000000000 + NI6683.ni6683AbsTime) + # print ('DEBUG -> Result: ', result) return result except: - emsg = 'Cannot convert relative time to absolute ' + str(self.fd) + emsg = 'Cannot convert relative to absolute time' + str(self.fd) Data.execute('DevLogErr($1,$2)', self.getNid(), emsg) raise DevBAD_PARAMETER + # returns the start and end times of the terminal in the absolute time reference def getStartEnd(self, termName): - termNameNid = termName+str(self.nid) try: start = NI6683.ni6683TermStarts[termNameNid] + # if the start time of the selected terminal is less than the shot relative time -> error if start < NI6683.ni6683RelTime: emsg = 'Start time less than relative time in ' + termName Data.execute('DevLogErr($1,$2)', self.getNid(), emsg) raise DevBAD_PARAMETER - # start = 0 # NISYNC_TIME_IMMEDIATE_NANOS in the API else: start = self.getAbsTime(start) except: print ("Exception in defining Start") start = self.getAbsTime(start) + + # retrieving the end time for the slected terminal try: end = NI6683.ni6683TermEnds[termNameNid] if end <= 0: - end = sys.maxint + end = sys.maxsize # maxint in python 2.* else: end = self.getAbsTime(end) except: - end = sys.maxint + end = sys.maxsize + if start >= end: emsg = 'End time less than start time in ' + termName Data.execute('DevLogErr($1,$2)', self.getNid(), emsg) raise DevBAD_PARAMETER return start, end + # returns startNs[] and endNs[] arrays containing the time slots of the programmed pulses def getStartPulse(self, termName): termNameNid = termName+str(self.nid) try: - print(NI6683.ni6683TermStarts) + # print(NI6683.ni6683TermStarts) start = NI6683.ni6683TermStarts[termNameNid] except: emsg = 'Error reading start time in ' + termName @@ -283,32 +302,50 @@ def getStartPulse(self, termName): def checkStatus(self, status, message): - if(status < 0): # OCCHIO!! CAMBIATO DA LUCA, PRIMA ERA != 0 + if(status < 0): Data.execute('DevLogErr($1,$2)', self.getNid(), message + 'status: %d'%(status)) raise DevCOMM_ERROR + # saves the information contained in the pulse file in the module variables def init(self): self.debugPrint('================= PXI 6683 init ===============') - self.restoreInfo() + self.reset_device() + NI6683.ni6683RecorderDict[self.nid] = [] + curr_nanos = c_uint64() + status = NI6683.niLib.nisync_get_time_ns(self.fd, byref(curr_nanos)) + + try: + NI6683.ni6683AbsStart = self.abs_start.data() # Trying to read the curr time from the ABS_START field + print ("ABS START RETRIEVED: %f, INTERNAL TIME: %f"%(NI6683.ni6683AbsStart, curr_nanos.value)) + if curr_nanos.value - NI6683.ni6683AbsStart < 0: + Data.execute('DevLogErr($1,$2)', self.getNid(), "CURRENT TIME SMALLER THAN ABSOLUTE TIME") + raise DevBAD_PARAMETER + elif abs(curr_nanos.value - NI6683.ni6683AbsStart) > 1000: + Data.execute('DevLogErr($1,$2)', self.getNid(), "ABSOLUTE TIME FAR FROM THE MODULE INTERNAL TIME, CHECK THE SYNCHRONIZATION STATUS") + raise DevBAD_PARAMETER + except: + print (" !!!!!!!!!!!!!!! PROBLEM IN RECOVERING ABSOLUTE TIME, CONTINUING WITH MODULE INTERNAL TIME !!!!!!!!!!!!!!!") + NI6683.useInternalReference = True - # Resetting the device (N.B. WIP) - print("RESETTING DEVICE...") - status = NI6683.niLib.nisync_reset(self.fd) - self.checkStatus(status, 'Cannot reset the device') - print("DONE") + # if the trigger event is defined, the module will wait for it to be triggered + try: + NI6683.ni6683ModuleTriggerName = self.trig_event.data() + except: + NI6683.ni6683ModuleTriggerName = None for termName in NI6683.termNameDict.keys(): - termNameNid = termName+str(self.nid) - + # reading the shot relative start time try: NI6683.relTime = self.rel_start.data() except: emsg = 'Invalid relative start' Data.execute('DevLogErr($1,$2)', self.getNid(), emsg) raise DevBAD_PARAMETER + + # retreaving the terminal behavior try: mode = getattr(self, termName.lower()+'_mode').data() except: @@ -317,9 +354,29 @@ def init(self): raise DevBAD_PARAMETER NI6683.ni6683Modes[termNameNid] = mode + # storing the terminal name in the ni6683RecorderDict if (mode == 'RECORDER RISING' or mode == 'RECORDER FALLING' or mode == 'RECORDER ANY'): NI6683.ni6683RecorderDict[self.nid].append(termName) + # LOW PULSE initialization at level high mode + if (mode == 'LOW PULSE'): + status = NI6683.niLib.nisync_abort_all_ftes(c_int(self.termDict[termName])) + self.checkStatus(status, "Cannot abort future time events for the LOW PULSE behavior ") + status = NI6683.niLib.nisync_enable_future_time_events(c_int(self.termDict[termName])) + self.checkStatus(status, "Cannot enable future time events ") + # setting the terminal level to 1 before the trigger + NI6683.niLib.nisync_set_terminal_level(c_int(self.termDict[termName]), c_int(self.NISYNC_LEVEL_HIGH)) + + # HIGH PULSE initialization at level high mode + if (mode == 'HIGH PULSE'): + status = NI6683.niLib.nisync_abort_all_ftes(c_int(self.termDict[termName])) + self.checkStatus(status, "Cannot abort future time events for the LOW PULSE behavior ") + status = NI6683.niLib.nisync_enable_future_time_events(c_int(self.termDict[termName])) + self.checkStatus(status, "Cannot enable future time events ") + # setting the terminal level to 0 before the trigger + NI6683.niLib.nisync_set_terminal_level(c_int(self.termDict[termName]), c_int(self.NISYNC_LEVEL_LOW)) + + # retrieving the terminal frequency try: freq = getattr(self, termName.lower()+'_frequency').data() except: @@ -328,7 +385,8 @@ def init(self): raise DevBAD_PARAMETER NI6683.ni6683Frequencies[termNameNid] = freq periodNs = int(1000000000./float(freq)) - + + # retrieving the terminal duty cycle try: dutyCycle = getattr(self, termName.lower()+'_duty_cycle').data() except: @@ -342,6 +400,7 @@ def init(self): dutyCycleNs = int(periodNs * dutyCycle/100.) NI6683.ni6683DutyCycles[termNameNid] = dutyCycleNs + # retrieving the terminal end time try: NI6683.ni6683TermEnds[termNameNid] = getattr(self, termName.lower()+'_end').data() except: @@ -349,6 +408,7 @@ def init(self): Data.execute('DevLogErr($1,$2)', self.getNid(), emsg) raise DevBAD_PARAMETER + # retrieving the terminal pulse length try: NI6683.ni6683PulseLengths[termNameNid] = getattr(self, termName.lower()+'_pulse_len').data() except: @@ -356,6 +416,7 @@ def init(self): Data.execute('DevLogErr($1,$2)', self.getNid(), emsg) raise DevBAD_PARAMETER + # retrieving the terminal start time try: NI6683.ni6683TermStarts[termNameNid] = getattr(self, termName.lower()+'_start').data() except: @@ -363,66 +424,44 @@ def init(self): Data.execute('DevLogErr($1,$2)', self.getNid(), emsg) raise DevBAD_PARAMETER - try: - NI6683.ni6683ModuleTriggerName = self.trig_event.data() - except: - NI6683.ni6683ModuleTriggerName = None - - try: - NI6683.ni6683AbsStart = self.abs_start.data() - except: - emsg = 'Invalid abs start ' + termName - Data.execute('DevLogErr($1,$2)', self.getNid(), emsg) - raise DevBAD_PARAMETER - + self.saveInfo() + + # By using the information gained in the init() phase, the NI6683 triggers the future events associated to each terminal def trigger(self): - - # MyEvent inner class, it saves the timestamp data passed by the event ( event type: , ) - class MyEvent(Event): - def run(self): - print("RECEIVED EVENT " + self.getName()) - print ('With data:' + self.getData()) - NI6683.eventTime = self.getData() - self.cancel() - self.debugPrint('================= PXI 6683 trigger ===============') - self.restoreInfo() - info = self.nisync_device_info("","","", 0, 0, 0, 0, 0, 0, 0) - - trigger_event = NI6683.ni6683ModuleTriggerName - if (trigger_event != None): # external time reference trigger - eventObj=MyEvent(trigger_event) - eventObj.start() - trigTime = c_uint64(self.eventTime) - self.abs_start.putData(Uint64(trigTime)) - else: # internal time reference + if (NI6683.useInternalReference): # if abs_start not found on the pulse file, puts the current module time in the abs_start field deltaT = 200 # ms - print ("MODULE TRIGGER NOT FOUND -> CONTINUING WITH ABS INTERNAL TIMING") curr_nanos = c_uint64() status = NI6683.niLib.nisync_get_time_ns(self.fd, byref(curr_nanos)) - self.abs_start.putData(Uint64(curr_nanos.value + deltaT * 1000000)) + self.abs_start.putData(Uint64(curr_nanos.value + deltaT * 1000000)) + curr_nanos = c_uint64() + status = NI6683.niLib.nisync_get_time_ns(self.fd, byref(curr_nanos)) + print ("DEBUG -> INTERNAL TIMING: ", curr_nanos.value) NI6683.ni6683AbsTime = self.abs_start.data() NI6683.ni6683RelTime = self.rel_start.data() - #NI6683.ni6683RecorderDict[self.nid] = [] + for termName in NI6683.termNameDict.keys(): - termNameNid = termName+str(self.nid) - mode = NI6683.ni6683Modes[termNameNid] freq = NI6683.ni6683Frequencies[termNameNid] - if mode == 'DISABLED':######################################################### + + # in the DISABLED mode: + # - the terminal future time evets are disabled + # - the terminal timestamp triggers are disabled + if mode == 'DISABLED': enabled = c_int8() + activeEdge = c_int() + decimationCount = c_int() + status = NI6683.niLib.nisync_future_time_events_configuration(c_int(self.termDict[termName]), byref(enabled)) - self.checkStatus(status, 'Cannot inquire future events') + self.checkStatus(status, 'Cannot inquire future events in "DISABLED" mode') if enabled.value != 0: print('DISABLE FUTURE EVENT for ' + termName + ' fd: '+ str(self.termDict[termName])) status = NI6683.niLib.nisync_disable_future_time_events(c_int(self.termDict[termName])) self.checkStatus(status, 'Cannot disable future events') - activeEdge = c_int() - decimationCount = c_int() status = NI6683.niLib.nisync_timestamp_trigger_configuration(c_int(self.termDict[termName]), byref(enabled), byref(activeEdge), byref(decimationCount)) self.checkStatus(status, 'Cannot inquire timestamp triggers') @@ -430,42 +469,48 @@ def run(self): print('DISABLE TIMESTAMP for ' + termName + ' fd: '+ str(self.termDict[termName])) status = NI6683.niLib.nisync_disable_timestamp_trigger(c_int(self.termDict[termName])) self.checkStatus(status, 'Cannot disable timestamp triggers') - elif mode == 'CLOCK':############################################################# + + # in the CLOCK mode: + # - the terminal future time evets are enabled + # - the terminal tries to generate a clok in the period [startNs, endNs] + # - if a clock is already present, the terminal tries to replace it + elif mode == 'CLOCK': enabled = c_int8() activeEdge = c_int() decimationCount = c_int() - # status = NI6683.niLib.nisync_timestamp_trigger_configuration(c_int(self.termDict[termName]), - # byref(enabled), byref(activeEdge), byref(decimationCount)) - # self.checkStatus(status, 'Cannot inquire timestamp triggers') - # if enabled.value != 0: - # print('DISABLE TIMESTAMP for ' + termName + ' fd: '+ str(self.termDict[termName])) - # status = NI6683.niLib.nisync_disable_timestamp_trigger(c_int(self.termDict[termName])) - # self.checkStatus(status, 'Cannot disable timestamp triggers') status = NI6683.niLib.nisync_future_time_events_configuration(c_int(self.termDict[termName]), byref(enabled)) - self.checkStatus(status, 'Cannot inquire future events') + self.checkStatus(status, 'Cannot inquire future events in "CLOCK" mode') if enabled.value == 0: print('ENABLE FUTURE EVENT for ' + termName + ' fd: '+ str(self.termDict[termName])) status = NI6683.niLib.nisync_enable_future_time_events(c_int(self.termDict[termName])) self.checkStatus(status, 'Cannot enable future events') - # status = NI6683.niLib.nisync_abort_all_ftes(c_int(self.termDict[termName])) - # self.checkStatus(status, 'Cannot abort FTEs') startNs, endNs = self.getStartEnd(termName) periodNs = int(1000000000./float(freq)) dutyCycle = NI6683.ni6683DutyCycles[termNameNid] - print('Generate Clock: '+ str(self.termDict[termName]) + ' ' + str(startNs) + ' '+str(endNs)+' ' + str(periodNs) + ' '+str(NI6683.ni6683DutyCycles[termNameNid])) - status = NI6683.niLib.nisync_generate_clock_ns(c_int(self.termDict[termName]), c_uint64(startNs), - c_uint64(endNs), c_uint64(periodNs), c_uint64(dutyCycle)) - print (os.strerror(get_errno())) + print('Generating Clock: '+ str(self.termDict[termName]) + ' ' + str(startNs) + ' '+str(endNs)+' ' + str(periodNs) + ' '+str(NI6683.ni6683DutyCycles[termNameNid])) + status = NI6683.niLib.nisync_generate_clock_ns(c_int(self.termDict[termName]), c_uint64(int(startNs)), + c_uint64(int(endNs)), c_uint64(periodNs), c_uint64(dutyCycle)) + print(os.strerror(get_errno())) + if status != 0: - emsg = 'Error in replace clock for %s status = %d '%(termName, status) - Data.execute('DevLogErr($1,$2)', self.getNid(), emsg) - raise DevCOMM_ERROR + print("Clock already present, replacing it...") + status = NI6683.niLib.nisync_replace_clock_ns(c_int(self.termDict[termName]), c_uint64(int(startNs)), + c_uint64(int(endNs)), c_uint64(periodNs), c_uint64(dutyCycle)) + if status != 0: + emsg = 'Error in replace clock for %s status = %d '%(termName, status) + Data.execute('DevLogErr($1,$2)', self.getNid(), emsg) + raise DevCOMM_ERROR + + # in the HIGH PULSE mode: + # - the terminal timestamp triggers are disabled (PERCHE? riguardare!!! TODO) + # - the terminal generates a pulse in the period [startNs, endNS] (QUI USA generateFTEs... provare con metodo pulse TODO) elif mode == 'HIGH PULSE':############################################################### enabled = c_int8() activeEdge = c_int() decimationCount = c_int() + status = NI6683.niLib.nisync_timestamp_trigger_configuration(c_int(self.termDict[termName]), byref(enabled), byref(activeEdge), byref(decimationCount)) self.checkStatus(status, 'Cannot inquire timestamp triggers') @@ -473,16 +518,7 @@ def run(self): print('DISABLE TIMESTAMP for ' + termName + ' fd: '+ str(self.termDict[termName])) status = NI6683.niLib.nisync_disable_timestamp_trigger(c_int(self.termDict[termName])) self.checkStatus(status, 'Cannot disable timestamp triggers') - status = NI6683.niLib.nisync_future_time_events_configuration(c_int(self.termDict[termName]), byref(enabled)) - self.checkStatus(status, 'Cannot inquire future events') - if enabled.value == 0: - print('ENABLE FUTURE EVENT for ' + termName + ' fd: '+ str(self.termDict[termName])) - status = NI6683.niLib.nisync_enable_future_time_events(c_int(self.termDict[termName])) - self.checkStatus(status, 'Cannot enable future events') - status = NI6683.niLib.nisync_abort_all_ftes(c_int(self.termDict[termName])) - self.checkStatus(status, 'Cannot abort FTEs') - status = NI6683.niLib.nisync_set_terminal_level(c_int(self.termDict[termName]), c_int(self.NISYNC_LEVEL_LOW)) - self.checkStatus(status, 'Cannot set terminal level') + startNs, endNs = self.getStartPulse(termName) for i in range(0,len(startNs)): if endNs[i] <= startNs[i]: @@ -490,14 +526,19 @@ def run(self): Data.execute('DevLogErr($1,$2)', self.getNid(), emsg) raise DevBAD_PARAMETER print ("DEBUG -> PULSE AT: ", startNs[i]) - status = NI6683.niLib.nisync_generate_fte_ns(c_int(self.termDict[termName]), c_uint64(startNs[i]), c_uint8(self.NISYNC_LEVEL_HIGH)) - self.checkStatus(status, 'Cannot generate future event') - status = NI6683.niLib.nisync_generate_fte_ns(c_int(self.termDict[termName]), c_uint64(endNs[i]), c_uint8(self.NISYNC_LEVEL_LOW)) - self.checkStatus(status, 'Cannot generate future event') + status = NI6683.niLib.nisync_generate_fte_ns(c_int(int(self.termDict[termName])), c_uint64(int(startNs[i])), c_uint8(self.NISYNC_LEVEL_HIGH)) + self.checkStatus(status, 'Cannot generate future event at pulse start') + status = NI6683.niLib.nisync_generate_fte_ns(c_int(int(self.termDict[termName])), c_uint64(int(endNs[i])), c_uint8(self.NISYNC_LEVEL_LOW)) + self.checkStatus(status, 'Cannot generate future event at pulse end') + + # in the LOW PULSE mode: + # - the terminal timestamp triggers are disabled (PERCHE? riguardare!!! TODO) + # - the terminal generates a pulse in the period [startNs, endNS] (QUI USA generateFTEs... provare con metodo pulse TODO) elif mode == 'LOW PULSE':################################################### enabled = c_int8() activeEdge = c_int() decimationCount = c_int() + status = NI6683.niLib.nisync_timestamp_trigger_configuration(c_int(self.termDict[termName]), byref(enabled), byref(activeEdge), byref(decimationCount)) self.checkStatus(status, 'Cannot inquire timestamp triggers') @@ -505,31 +546,28 @@ def run(self): print('DISABLE TIMESTAMP for ' + termName + ' fd: '+ str(self.termDict[termName])) status = NI6683.niLib.nisync_disable_timestamp_trigger(c_int(self.termDict[termName])) self.checkStatus(status, 'Cannot disable timestamp triggers') - status = NI6683.niLib.nisync_future_time_events_configuration(c_int(self.termDict[termName]), byref(enabled)) - self.checkStatus(status, 'Cannot inquire future events') - if enabled.value == 0: - print('ENABLE FUTURE EVENT for ' + termName + ' fd: '+ str(self.termDict[termName])) - status = NI6683.niLib.nisync_enable_future_time_events(c_int(self.termDict[termName])) - self.checkStatus(status, 'Cannot enable future events') - status = NI6683.niLib.nisync_abort_all_ftes(c_int(self.termDict[termName])) - self.checkStatus(status, 'Cannot abort FTEs') - status = NI6683.niLib.nisync_set_terminal_level(c_int(self.termDict[termName]), c_int(self.NISYNC_LEVEL_HIGH)) - self.checkStatus(status, 'Cannot set terminal level') + startNs, endNs = self.getStartPulse(termName) for i in range(0,len(startNs)): if endNs[i] <= startNs[i]: emsg = 'Start Time greater than End Time for ' + termName Data.execute('DevLogErr($1,$2)', self.getNid(), emsg) raise DevBAD_PARAMETER - status = NI6683.niLib.nisync_generate_fte_ns(c_int(self.termDict[termName]), c_uint64(startNs[i]), c_uint8(self.NISYNC_LEVEL_LOW)) - # print ("ERRORE" + NI6683.niLib.nisync_generate_fte_ns(c_int(self.termDict[termName]), c_uint64(startNs[i]), c_uint8(self.NISYNC_LEVEL_LOW))) - self.checkStatus(status, 'Cannot generate future event') - status = NI6683.niLib.nisync_generate_fte_ns(c_int(self.termDict[termName]), c_uint64(endNs[i]), c_uint8(self.NISYNC_LEVEL_HIGH)) - self.checkStatus(status, 'Cannot generate future event') - elif mode == 'HIGH':################################################################ + status = NI6683.niLib.nisync_generate_fte_ns(c_int(int(self.termDict[termName])), c_uint64(int(startNs[i])), c_uint8(self.NISYNC_LEVEL_LOW)) + self.checkStatus(status, 'Cannot generate future event at pulse start') + status = NI6683.niLib.nisync_generate_fte_ns(c_int(int(self.termDict[termName])), c_uint64(int(endNs[i])), c_uint8(self.NISYNC_LEVEL_HIGH)) + self.checkStatus(status, 'Cannot generate future event at pulse end') + + # in the HIGH mode: + # - the terminal timestamp triggers are disabled (PERCHE? riguardare!!! TODO) + # - the terminal future time events are enabled + # - the terminal FTEs are aborted (SICURI? TODO) + # - the terminal level is set to 1 + elif mode == 'HIGH': enabled = c_int8() activeEdge = c_int() decimationCount = c_int() + status = NI6683.niLib.nisync_timestamp_trigger_configuration(c_int(self.termDict[termName]), byref(enabled), byref(activeEdge), byref(decimationCount)) self.checkStatus(status, 'Cannot inquire timestamp triggers') @@ -537,20 +575,29 @@ def run(self): print('DISABLE TIMESTAMP for ' + termName + ' fd: '+ str(self.termDict[termName])) status = NI6683.niLib.nisync_disable_timestamp_trigger(c_int(self.termDict[termName])) self.checkStatus(status, 'Cannot disable timestamp triggers') + status = NI6683.niLib.nisync_future_time_events_configuration(c_int(self.termDict[termName]), byref(enabled)) - self.checkStatus(status, 'Cannot inquire future events') + self.checkStatus(status, 'Cannot inquire future events in "HIGH" mode') if enabled.value == 0: print('ENABLE FUTURE EVENT for ' + termName + ' fd: '+ str(self.termDict[termName])) status = NI6683.niLib.nisync_enable_future_time_events(c_int(self.termDict[termName])) self.checkStatus(status, 'Cannot enable future events') - status = NI6683.niLib.nisync_abort_all_ftes(c_int(self.termDict[termName])) - self.checkStatus(status, 'Cannot abort FTEs') + + # status = NI6683.niLib.nisync_abort_all_ftes(c_int(self.termDict[termName])) + # self.checkStatus(status, 'Cannot abort FTEs') status = NI6683.niLib.nisync_set_terminal_level(c_int(self.termDict[termName]), c_int(self.NISYNC_LEVEL_HIGH)) self.checkStatus(status, 'Cannot set terminal level') - elif mode == 'LOW':#################################################################### + + # in the LOW mode: + # - the terminal timestamp triggers are disabled (PERCHE? riguardare!!! TODO) + # - the terminal future time events are enabled + # - the terminal FTEs are aborted (SICURI? TODO) + # - the terminal level is set to 0 + elif mode == 'LOW': enabled = c_int8() activeEdge = c_int() decimationCount = c_int() + status = NI6683.niLib.nisync_timestamp_trigger_configuration(c_int(self.termDict[termName]), byref(enabled), byref(activeEdge), byref(decimationCount)) self.checkStatus(status, 'Cannot inquire timestamp triggers') @@ -558,26 +605,35 @@ def run(self): print('DISABLE TIMESTAMP for ' + termName + ' fd: '+ str(self.termDict[termName])) status = NI6683.niLib.nisync_disable_timestamp_trigger(c_int(self.termDict[termName])) self.checkStatus(status, 'Cannot disable timestamp triggers') + status = NI6683.niLib.nisync_future_time_events_configuration(c_int(self.termDict[termName]), byref(enabled)) - self.checkStatus(status, 'Cannot inquire future events') + self.checkStatus(status, 'Cannot inquire future events in "LOW" mode') if enabled.value == 0: print('ENABLE FUTURE EVENT for ' + termName + ' fd: '+ str(self.termDict[termName])) status = NI6683.niLib.nisync_enable_future_time_events(c_int(self.termDict[termName])) self.checkStatus(status, 'Cannot enable future events') - status = NI6683.niLib.nisync_abort_all_ftes(c_int(self.termDict[termName])) - self.checkStatus(status, 'Cannot abort FTEs') + + # status = NI6683.niLib.nisync_abort_all_ftes(c_int(self.termDict[termName])) + # self.checkStatus(status, 'Cannot abort FTEs') status = NI6683.niLib.nisync_set_terminal_level(c_int(self.termDict[termName]), c_int(self.NISYNC_LEVEL_LOW)) self.checkStatus(status, 'Cannot set terminal level') - elif mode == 'RECORDER RISING':############################################################# + + # in the RECORDER RISING mode: + # - the terminal future time events are disabled + # - the terminal timestamp triggers are disabled (AH FORSE PERCHE non si sa prima se erano falling o rising) + # - the terminal timestamp triggers are enabled on the rising edge + elif mode == 'RECORDER RISING': enabled = c_int8() activeEdge = c_int() decimationCount = c_int() + status = NI6683.niLib.nisync_future_time_events_configuration(c_int(self.termDict[termName]), byref(enabled)) - self.checkStatus(status, 'Cannot inquire future events') + self.checkStatus(status, 'Cannot inquire future events in "RECORDER RISING" mode') if enabled.value != 0: print('DISABLE FUTURE EVENT for ' + termName + ' fd: '+ str(self.termDict[termName])) status = NI6683.niLib.nisync_disable_future_time_events(c_int(self.termDict[termName])) self.checkStatus(status, 'Cannot disable future events') + status = NI6683.niLib.nisync_timestamp_trigger_configuration(c_int(self.termDict[termName]), byref(enabled), byref(activeEdge), byref(decimationCount)) self.checkStatus(status, 'Cannot inquire timestamp triggers') @@ -589,16 +645,23 @@ def run(self): status = NI6683.niLib.nisync_enable_timestamp_trigger(c_int(self.termDict[termName]), c_int(self.NISYNC_EDGE_RISING), c_int(1)) self.checkStatus(status, 'Cannot enable timestamp triggers') - elif mode == 'RECORDER FALLING':################################################################ + + # in the RECORDER FALLING mode: + # - the terminal future time events are disabled + # - the terminal timestamp triggers are disabled (AH FORSE PERCHE non si sa prima se erano falling o rising) + # - the terminal timestamp triggers are enabled on the falling edge + elif mode == 'RECORDER FALLING': enabled = c_int8() activeEdge = c_int() decimationCount = c_int() + status = NI6683.niLib.nisync_future_time_events_configuration(c_int(self.termDict[termName]), byref(enabled)) - self.checkStatus(status, 'Cannot inquire future events') + self.checkStatus(status, 'Cannot inquire future events in "RECORDER FALLING" mode') if enabled.value != 0: print('DISABLE FUTURE EVENT for ' + termName + ' fd: '+ str(self.termDict[termName])) status = NI6683.niLib.nisync_disable_future_time_events(c_int(self.termDict[termName])) self.checkStatus(status, 'Cannot disable future events') + status = NI6683.niLib.nisync_timestamp_trigger_configuration(c_int(self.termDict[termName]), byref(enabled), byref(activeEdge), byref(decimationCount)) self.checkStatus(status, 'Cannot inquire timestamp triggers') @@ -606,20 +669,28 @@ def run(self): print('DISABLE TIMESTAMP for ' + termName + ' fd: '+ str(self.termDict[termName])) status = NI6683.niLib.nisync_disable_timestamp_trigger(c_int(self.termDict[termName])) self.checkStatus(status, 'Cannot disable timestamp triggers') + print('ENABLE TIMESTAMP for ' + termName + ' fd: '+ str(self.termDict[termName])) status = NI6683.niLib.nisync_enable_timestamp_trigger(c_int(self.termDict[termName]), c_int(self.NISYNC_EDGE_FALLING), c_int(1)) self.checkStatus(status, 'Cannot enable timestamp triggers') - elif mode == 'RECORDER ANY': ############################################################## + + # in the RECORDER RISING mode: + # - the terminal future time events are disabled + # - the terminal timestamp triggers are disabled (AH FORSE PERCHE non si sa prima se erano falling o rising) + # - the terminal timestamp triggers are enabled for any edge + elif mode == 'RECORDER ANY': enabled = c_int8() activeEdge = c_int() decimationCount = c_int() + status = NI6683.niLib.nisync_future_time_events_configuration(c_int(self.termDict[termName]), byref(enabled)) - self.checkStatus(status, 'Cannot inquire future events') + self.checkStatus(status, 'Cannot inquire future events in "RECORDER ANY" mode') if enabled.value != 0: print('DISABLE FUTURE EVENT for ' + termName + ' fd: '+ str(self.termDict[termName])) status = NI6683.niLib.nisync_disable_future_time_events(c_int(self.termDict[termName])) self.checkStatus(status, 'Cannot disable future events') + status = NI6683.niLib.nisync_timestamp_trigger_configuration(c_int(self.termDict[termName]), byref(enabled), byref(activeEdge), byref(decimationCount)) self.checkStatus(status, 'Cannot inquire timestamp triggers') @@ -627,11 +698,14 @@ def run(self): print('DISABLE TIMESTAMP for ' + termName + ' fd: '+ str(self.termDict[termName])) status = NI6683.niLib.nisync_disable_timestamp_trigger(c_int(self.termDict[termName])) self.checkStatus(status, 'Cannot disable timestamp triggers') + print('ENABLE TIMESTAMP for ' + termName + ' fd: '+ str(self.termDict[termName])) status = NI6683.niLib.nisync_enable_timestamp_trigger(c_int(self.termDict[termName]), c_int(self.NISYNC_EDGE_ANY), c_int(1)) self.checkStatus(status, 'Cannot enable timestamp triggers') - + + + # starting the AsynchStore thread self.debugPrint('================= PXI 6683 start AsynchStore ===============') worker = self.AsynchStore() NI6683.ni6683WorkerDict[self.nid] = worker @@ -639,36 +713,65 @@ def run(self): worker.configure(self.copy()) worker.start() + # closes all the opened terminals (WITHOUT ERASING THE FUTURE TIME EVENTS) + def closeInfo(self): + self.debugPrint('================= PXI 6683 closing all terminals ================') + self.restoreInfo() + Fds = [] + + self.termDict = NI6683.ni6683Dicts[self.nid] + for termName in NI6683.termNameDict.keys(): + Fds.append(self.termDict[termName]) + c_Fds = (c_int * len(Fds))(*Fds) + status = NI6683.niInterfaceLib.NI6683_close(c_int(self.fd), c_Fds, len(Fds)) + if status == -1: + print("PROBLEM WHILE CLOSING...") + # opens the used terminals in the last session, stops their FTEs and closes them again def stop(self): self.debugPrint('================= PXI 6683 stop ================') + self.closeInfo() worker = NI6683.ni6683WorkerDict[self.nid] + self.fd = NI6683.ni6683Fds[self.nid] if worker.isAlive(): self.debugPrint("PXI 6683 stop_worker") worker.stop() worker.join() - self.debugPrint('================= PXI 6683 stop all terminals ================') + + if self.nid in NI6683.ni6683Fds.keys(): + self.fd = NI6683.ni6683Fds[self.nid] + del(NI6683.ni6683Fds[self.nid]) + + activeFds = [] + + try: + boardId = self.board_id.data() + except: + emsg = 'Missing Board Id' + Data.execute('DevLogErr($1,$2)', self.getNid(), emsg ) + raise DevBAD_PARAMETER + try: + devType = NI6683.typeDict[self.dev_type.data()] + except: + emsg = 'Missing Dev Type' + Data.execute('DevLogErr($1,$2)', self.getNid(), emsg ) + raise DevBAD_PARAMETER + self.termDict = NI6683.ni6683Dicts[self.nid] for termName in NI6683.termNameDict.keys(): mode = getattr(self, termName.lower()+'_mode').data() - freq = getattr(self, termName.lower()+'_frequency').data() - if mode != 'DISABLED':######################################################### - if mode == 'CLOCK': - print('DISABLE CLOCK for ' + termName + ' fd: '+ str(self.termDict[termName])) - status = NI6683.niLib.nisync_abort_clock(c_int(self.termDict[termName])) - self.checkStatus(status, 'Cannot disable the clock') - enabled = c_int8() - status = NI6683.niLib.nisync_future_time_events_configuration(c_int(self.termDict[termName]), byref(enabled)) - self.checkStatus(status, 'Cannot inquire future events') - if enabled.value != 0: - print('DISABLE FUTURE EVENT for ' + termName + ' fd: '+ str(self.termDict[termName])) - status = NI6683.niLib.nisync_disable_future_time_events(c_int(self.termDict[termName])) - self.checkStatus(status, 'Cannot disable future events') - self.closeInfo() + if mode != 'DISABLED': + term = NI6683.niLib.nisync_open_terminal(c_int(devType), c_int(boardId), c_int(NI6683.termNameDict[termName]), c_int(self.NISYNC_READ_NONBLOCKING)) + activeFds.append(term) + c_activeFds = (c_int * len(activeFds))(*activeFds) + + status = NI6683.niInterfaceLib.NI6683_stop(c_int(self.fd), c_activeFds, len(activeFds)) + if status == -1: + print("PROBLEM WHILE STOPPING...") + # AsynchStore inner class, it handles the MDSEvents geneneration triggered by hardware class AsynchStore(Thread): - class nisync_timestamp_nanos(Structure): _fields_ = [("edge", c_uint8), ("nanos", c_uint64)] @@ -678,7 +781,8 @@ def configure(self, device): self.device = device self.poll = select.poll() self.nameDict = {} - READ_ONLY = select.POLLIN | select.POLLPRI | select.POLLHUP | select.POLLERR + # READ_ONLY = select.POLLIN | select.POLLPRI | select.POLLHUP | select.POLLERR + READ_ONLY = select.POLLIN | select.POLLPRI | select.POLLHUP for name in NI6683.ni6683RecorderDict[self.device.nid]: self.poll.register(NI6683.ni6683Dicts[self.device.nid][name], READ_ONLY) @@ -687,8 +791,8 @@ def configure(self, device): def getRelTime(self, absTime): try: - #print("absTime: " + str(absTime) + " self.device.abs_start.data(): " + str(self.device.abs_start.data()) + " self.device.rel_start.data(): " +str(self.device.rel_start.data()) ) - return float((absTime - NI6683.ni6683AbsStart)/1E9 + NI6683.ni6683RelStart) + # print("absTime: " + str(absTime) + " self.device.abs_start.data(): " + str(self.device.abs_start.data()) + " self.device.rel_start.data(): " +str(self.device.rel_start.data()) ) + return float(absTime - self.device.abs_start.data())/1E9 + self.device.rel_start.data() except: emsg = 'Cannot convert absolute time to relative ' + str(self.device.fd) Data.execute('DevLogErr($1,$2)', self.device.getNid(), emsg) @@ -701,6 +805,7 @@ def run(self): while not self.stopReq: readyFds = self.poll.poll(1000) for fdTuple in readyFds: + print (readyFds) readyFd = fdTuple[0] event = fdTuple[1] print('EVENT: ', fdTuple, select.EPOLLIN) @@ -710,11 +815,14 @@ def run(self): print ('POLL ERROR!!') return timestamp = self.nisync_timestamp_nanos(0,0) + # nanos = c_uint64() + # status = NI6683.niLib.nisync_get_time_ns(NI6683.ni6683Fds[self.device.getNid()], byref(nanos)) status = NI6683.niLib.nisync_read_timestamps_ns(c_int(readyFd), byref(timestamp), c_int(1)) print ("TIMESTAMP: " , timestamp.nanos) self.device.checkStatus(status, 'Cannot get current time') termName = self.nameDict[readyFd] recorderNid = getattr(self.device, termName.lower()+'_raw_events') + # eventRelTime = self.getRelTime(nanos.value) eventRelTime = self.getRelTime(timestamp.nanos) recorderNid.putRow(10, Float64(eventRelTime), Float64(eventRelTime)) print ("DEBUG -> TIMESTAMP: " + str(timestamp.nanos)) @@ -725,5 +833,6 @@ def run(self): Event.setevent(eventName, Uint64(eventRelTime)) except: pass + def stop(self): self.stopReq = True diff --git a/tdi/RfxDevices/NIADCClockSegment.fun b/tdi/RfxDevices/NIADCClockSegment.fun index c15a8133ac..73c32075e9 100755 --- a/tdi/RfxDevices/NIADCClockSegment.fun +++ b/tdi/RfxDevices/NIADCClockSegment.fun @@ -1,12 +1,16 @@ -public fun NIADCClockSegment(in _clock, in _startIdx, in _endIdx, in _tAtIdx0, in _value) +public fun NIADCClockSegment(in _clock, in _startIdx, in _endIdx, in _tAtIdx0, in _value, optional in _period) { + _fact = 1; + if(present( _period )) + { + _fact = _period / _slope_of(_clock); + } - - _segSmp = ( end_of(_clock) - begin_of(_clock) )/slope_of(_clock); + _segSmp = ( end_of(_clock) - begin_of(_clock) )/slope_of(_clock) * _fact; if( size( _segSmp ) <= 1 ) { - _dt = slope_of(_clock); + _dt = slope_of(_clock) * _fact; _end = end_of(_clock); if( _end == * ) @@ -52,7 +56,7 @@ public fun NIADCClockSegment(in _clock, in _startIdx, in _endIdx, in _tAtIdx0, i } - _tStart = begin_of(_clock)[ _beginSegIdx ] + ( _startIdx - _prevStSeg ) * slope_of(_clock) + _tAtIdx0 ; + _tStart = begin_of(_clock)[ _beginSegIdx ] + ( _startIdx - _prevStSeg ) * slope_of(_clock) * _fact + _tAtIdx0 ; if( _value == 'start_time' ) { /*write(*, _clock[_startIdx] );*/ @@ -82,7 +86,7 @@ public fun NIADCClockSegment(in _clock, in _startIdx, in _endIdx, in _tAtIdx0, i _prevEndSeg = 0; } - _tEnd = begin_of(_clock)[ _endSegIdx ] + ( _endIdx - _prevEndSeg ) * slope_of(_clock) + _tAtIdx0; + _tEnd = begin_of(_clock)[ _endSegIdx ] + ( _endIdx - _prevEndSeg ) * slope_of(_clock) * _fact + _tAtIdx0; if( _value == 'end_time' ) { /*write(*, _clock[_endIdx] );*/ @@ -94,13 +98,13 @@ public fun NIADCClockSegment(in _clock, in _startIdx, in _endIdx, in _tAtIdx0, i if( _endSegIdx == _beginSegIdx ) { - return( make_range( _tStart + _tAtIdx0, _tEnd + _tAtIdx0, slope_of(_clock) ) ); + return( make_range( _tStart + _tAtIdx0, _tEnd + _tAtIdx0, slope_of(_clock) * _fact ) ); } else { /*write(*, _tStart, _tEnd, [ _beginSegIdx+1 : _endSegIdx-1 ]);*/ _begin = [_tStart, begin_of(_clock)[ _beginSegIdx+1 : _endSegIdx ]]; _end = [ end_of(_clock)[ _beginSegIdx : _endSegIdx - 1 ], _tEnd ]; - return( make_range( _begin + _tAtIdx0, _end + _tAtIdx0, slope_of(_clock) ) ); + return( make_range( _begin + _tAtIdx0, _end + _tAtIdx0, slope_of(_clock)*_fact ) ); } } }