diff --git a/device_support/redpitaya/AsyncStoreManager.h b/device_support/redpitaya/AsyncStoreManager.h index 31380b7c55..529912d3ee 100644 --- a/device_support/redpitaya/AsyncStoreManager.h +++ b/device_support/redpitaya/AsyncStoreManager.h @@ -26,12 +26,13 @@ class SaveItem double *startTimes, *endTimes; double freq; int blocksInSegment; - + public: - SaveItem(short *buffer, int segmentSamples, MDSplus::TreeNode *dataNode, - MDSplus::Data *triggerTime, void *treePtr, - double *startTimes, double *endTimes, double freq, int blocksInSegment, - MDSplus::TreeNode *resampledNode = NULL); + + SaveItem(short *buffer, int segmentSamples, MDSplus::TreeNode *dataNode, + MDSplus::Data *triggerTime, void *treePtr, + double *startTimes, double *endTimes, double freq, int blocksInSegment, + MDSplus::TreeNode *resampledNode = NULL); void setNext(SaveItem *itm) { nxt = itm; } SaveItem *getNext() { return nxt; } @@ -69,7 +70,7 @@ class SaveList SaveList(); void addItem(short *buffer, int segmentSamples, MDSplus::TreeNode *dataNode, - MDSplus::Data *triggerTime, void *treePtr, + MDSplus::Data *triggerTime, void *treePtr, double *startTimes, double *endTimes, double freq, int blocksInSegment, MDSplus::TreeNode *resampledNode = NULL); diff --git a/device_support/redpitaya/Makefile b/device_support/redpitaya/Makefile index 37461390c1..bd513d8736 100755 --- a/device_support/redpitaya/Makefile +++ b/device_support/redpitaya/Makefile @@ -1,7 +1,7 @@ CC=g++ -CFLAGS = -fPIC -std=c++11 -o2 -Wall -DLINUX -I${MDSPLUS_DIR}/include -I. +CFLAGS = -fPIC -o2 -Wall -DLINUX -I${MDSPLUS_DIR}/include -I. -Wno-unused-variable -Wno-unused-but-set-variable -Wno-unused-function LDFLAGS = -L${MDSPLUS_DIR}/lib -lpthread -lMdsObjectsCppShr @@ -10,8 +10,13 @@ OBJECTS=$(SOURCES:.cpp=.o) SHAREDLIB=libredpitaya.so EXE=test +all: redpitaya sync_clock -all: $(SOURCES) $(EXE) +sync_clock: sync_clock.c + $(CC) $(CFLAGS) sync_clock.c -o sync_clock + +redpitaya: $(SOURCES) $(EXE) + $(EXE): $(OBJECTS) $(CC) $(OBJECTS) -o $(SHAREDLIB) -shared $(LDFLAGS) diff --git a/device_support/redpitaya/README b/device_support/redpitaya/README index 31a2a3d58b..e784a88bea 100644 --- a/device_support/redpitaya/README +++ b/device_support/redpitaya/README @@ -13,7 +13,7 @@ acquisition is started until method stop_store is called. The dimension of the s --TRIGGER_SINGLE: when initialized (method init) and armed (method start_store), upon reception of a trigger (HW - Digital input DIO1_P or SW - method do_trigger), the number of samples specified in fields "Pre Samples" and "Post Samples" is acquired. NOTE: the dimension of the used segments is computed internally, and it will be 10000 if (PreSamples+PostSamples) is a multiple of 10000 -else 1000 if (PreSamples+PostSamples) is a multiple of 1000 else (PreSamples+PostSamples) +else 1000 if (PreSamples+PostSamples) is a multiple of 1000 else (PreSamples+PostSamples). At most 8000 pre samples can be defined --TRIGGER_STREAMING: when initialized (method init) and armed (method start_store), upon reception of a trigger (HW - Digital input DIO1_P or SW - method do_trigger), the number of samples specified in fields "Pre Samples" and "Post Samples" is acquired and then the module @@ -21,34 +21,48 @@ is ready to accept a new trigger until method stop_store is called. The segment adjusted to be a multiple of (PreSamples+PostSamples) --EVENT_SINGLE ---EVENT_STREAMING: like TRIGGER_SINGLE and TRIGGER_STREAMING but in this case, after receiving a trigger signal, actuual data acquisition is +--EVENT_STREAMING: like TRIGGER_SINGLE and TRIGGER_STREAMING but in this case, after receiving a trigger signal, actual data acquisition is triggered by the input signal. The following fields specify how the trigger is derived: - Event Chan.: channel to consider for trigger generation (A or B) - Event Mode: Generation if above (UPPER) or below (LOWER) the specified threshond - Event Level: threshold (raw data) for trigger generation - Event Samples: number of samples that must satisfy the specified confition in order to generate trigger + The trigger derived from inpput signal is also available at pin DIO1_N -Clock can be internal or external and is specified by field Clock Mode that can be: +Clock can be internal, external or internal 1MHz, synchronized with system clock and is specified by field Clock Mode that can be: --INTERNAL: clock is derived from the internal 125MHz clock, decimated as specified in field "Decimation" --EXTERNAL: clock is derived from Digital input DIO3_P, decimated as specified in field "Decimation" --TRIG_EXTERNAL: meaningful for mode TRIGGER_STREAMING or EVENT_STREAMING and useful when using a sampling speed higher that the external clock in this case the external clock is used to measure event time, and internal clock (decimated as specified in field "Decimation") is used for sampling. ---HIGHWAY: takinh 1 MHz clock from the INCAA DIO4 timing highway. The highway is provided on the clock input +--SYNC: 1MHz clock is internally generated and kept in step with the system clock (see below). This clock is used for data sampling, decoimanted as + specified in field "Decimation" and for trigger timestamping. +--TRIGGER_SYNC: same as TRIG_EXTERNAL except for the fact that the clock uzsed to timestamp triggers is taken from the internal, synchronized 1MHz clock When EXTERNAL or TRIG_EXTERNAL clock mode specified, field Ext. Clock specifies the clock source (must be a range data type) When INTERNAL or TRIG_EXTERNAL clock mode specified, the 125MHz internal clock is divided by the value specified in field "Decimation" -When HIGHAY, the event code in Setup Event COde: field is recognized as trigger +When SYNC or TRIGGER_SYNC the absolute time of the (first) trigger is saved in field ABS_TRIGGER, as a usec counter since 1-JAN-1970. Field trigger time specifies the time of the initial trigger (valid for all modes) and is used to build signal timebases. +When in mode EVENT_SINGLE or EVENT_STREAMING (i.e. whe trigger is derived from input signal level) field "Dead Time" specifies the time during which, after +serving one trigger, the firmware is not sensible to further triggers. The default valie is 1 ms, and this feature is useful to avoid overrunning the +module when the input signal is contantly above the trigger threashold. + + +The FPGA firmware includes also the generation of an internal 1 MHz clock. Can be maintained in step with the system clock by running the daemon program +sync_clock. This program periodically check the FPGA register keeping the time based on this clock and compares it with the system clock. When the two times +differ, the (average) frequency of the 1MHz clock is slightly adjusted in order to align the FPGA time and system time. This feature is useful in particular +when the system clock is NTP synchronized, allowing the meaningful comparison of signals acquired in different devices with the precision that can be achieved +in NTP (~100ms). Normally the clock is stabilized by sync_clock in 2-3 minutes. The generated 1MHz clock is available at pin DIO5_P. + *************INSTALLATION*************** 1) Firmware upload. The bitstream is in file rfx_nioadc_dma_0. It must be copied on the redpitaya board and EVERY TIME the board is powered it must be installed with the comand: - cat rfx_nioadc_dma_0.1.bit /dev/xdevcfg + cat rfx_stream_0.1.bit /dev/xdevcfg 2) Device tree installation. Performed only once with the following commands, followed by a system reboot @@ -57,9 +71,13 @@ it must be installed with the comand: 3) Driver installation, performed every time the device is powered or rebooted, via the following command: - insmod rpadc_fifo_auto.ko + insmod rfx_stream.ko The python device implementation relies on a compiled program (redpitaya.cpp) in $MDSPLUS_DIR/device_support/redpitaya (containing also the -other files). Installation is done with commands make and make install. - \ No newline at end of file +other files). Installation is done with commands make and make install. The resulting libredpitaya.so shared library is used by RFX_RPADC python +module for the Redpitaya device. Makefile produces also syn_clock program to be launched in order to synchronize the 1 MHz clock. + + + + diff --git a/device_support/redpitaya/devicetree.dtb b/device_support/redpitaya/devicetree.dtb index 27ead8b76d..956076e5d6 100644 Binary files a/device_support/redpitaya/devicetree.dtb and b/device_support/redpitaya/devicetree.dtb differ diff --git a/device_support/redpitaya/redpitaya.cpp b/device_support/redpitaya/redpitaya.cpp index 42050d88d5..24fd5c24f6 100644 --- a/device_support/redpitaya/redpitaya.cpp +++ b/device_support/redpitaya/redpitaya.cpp @@ -1,4 +1,6 @@ #include +#include +#include #include #include #include @@ -9,18 +11,24 @@ #include #include +#define COUNT_SIZE 2000000 + +static void checkUpdateFreq(int fd); extern "C" { void rpadcStream(int fd, char *treeName, int shot, int chan1Nid, int chan2Nid, int triggerNid, int preSamples, int postSamples, - int inSegmentSamples, double freq, double freq1, int single); + int inSegmentSamples, double freq, double freq1, int single, int absTriggerTimeFromFPGA, int absTriggerNid); int rpadcInit(int mode, int clock_mode, int preSamples, int postSamples, int trigFromChanA, int trigAboveThreshold, int trigThreshold, - int thresholdSamples, int decimation, int event_code); + int thresholdSamples, int decimation, int deadtime); int rpadcTrigger(int fd); void rpadcStop(int fd); void openTree(char *name, int shot, MDSplus::Tree **treePtr); + void setTriggerTime(unsigned long long triggerTime); } + + enum rpadc_mode { STREAMING = 0, @@ -32,12 +40,11 @@ enum rpadc_mode enum rpadc_clock_mode { - INTERNAL = 0, - TRIG_EXTERNAL, - EXTERNAL, - TRIG_EVENT, - EXT_EVENT, - HIGHWAY + INTERNAL = 0, //Internal clock and trigger timestamping Sampling direct from ADC (125MHz divided for decimation) + TRIG_EXTERNAL, //Internal clock, but trigger timestamping from external clock + TRIG_ABS, //Internal clock, use absolute time for trigger timestamping (however use relative times in the saved signal, a separate node will contain the absolute time of the first trigger) + EXTERNAL, //External sampling clock, same clock used for trigger timestamping + SYNC //Synchronized (NTP) sampling clock, use absolute time for trigger timestamping (however use relative times in the saved signal, a separate node will contain the absolute time of the first trigger) }; #define DMA_STREAMING_SAMPLES 1024 @@ -54,21 +61,28 @@ struct rpadc_configuration // validating trigger unsigned short pre_samples; // Number of pre-trigger samples unsigned int post_samples; // Number of post-trigger samples - unsigned int decimation; // Decimation factor (base frequency: 125MHz) - unsigned int event_code; // Trigger event code (if HIGHWAY clock mode) + unsigned int decimation; // Decimation factor (base frequency: 125MHz if internal clock, 1 MHz if synch clock, Clock frequency if external clock) + unsigned int deadtime; // Deadtime count, valis when trigger on level, referred to sample count }; static bool stopped = false; static bool isStream = false; static int deviceFd = 0; +static unsigned long long absTriggerTime = 0; +static bool isFirstTrigger; +void setTriggerTime(unsigned long long triggerTime) +{ + absTriggerTime = triggerTime; +} static void writeConfig(int fd, struct rpadc_configuration *config) { struct rfx_stream_registers regs; memset(®s, 0, sizeof(regs)); unsigned int currVal = 0; - unsigned int dmaBufSize = 0; + unsigned int auxVal = 0; + if (config->mode == STREAMING) currVal |= 0x00000001; if (config->trig_from_chana) @@ -79,17 +93,41 @@ static void writeConfig(int fd, struct rpadc_configuration *config) currVal |= 0x00000008; if (config->mode == EVENT_STREAMING || config->mode == TRIGGER_STREAMING) currVal |= 0x00000010; - if (config->clock_mode == TRIG_EXTERNAL || config->clock_mode == EXTERNAL) - currVal |= 0x00000020; - if (config->clock_mode == EXTERNAL || config->clock_mode == HIGHWAY) - currVal |= 0x00000040; - if (config->clock_mode == HIGHWAY) - currVal |= 0x00000080; - + switch(config->clock_mode) { + case INTERNAL: //Internal clock and trigger timestamping Sampling direct from ADC (125MHz divided for decimation) + break; + case TRIG_EXTERNAL: //Internal clock, but trigger timestamping from external clock + currVal |= 0x00000020; + auxVal |= 4; + break; + case TRIG_ABS: //Internal clock, use absolute time for trigger timestamping (however use relative times in the saved signal, a separate node will contain the absolute time of the first trigger) + currVal |= 0x00000020; + auxVal |= 0x00000002; + break; + case EXTERNAL: //External sampling clock, same clock used for trigger timestamping + currVal |= 0x00000020; + currVal |= 0x00000040; + auxVal |= 0x00000004; + break; + case SYNC: //Synchronized (NTP) sampling clock, use absolute time for trigger timestamping (however use relative times in the saved signal, a separate node will contain the absolute time of the first trigger) + currVal |= 0x00000020; + currVal |= 0x00000040; + auxVal |= 0x00000001; + break; + } + +/* Aux Mode register bits: +-- 0: use ext_clock(synchronized) for resampling clock (0) or use sync_clk for resampling clock +-- 1: Use relative times (derived from internal counters) (0) or use absolute times(1) +-- 2: Resampler out_clk = sync_clock (0) or sync_ext_clock(1) +*/ + currVal |= ((config->trig_samples << 8) & 0x0000FF00); currVal |= ((config->trig_threshold << 16) & 0xFFFF0000); regs.mode_register_enable = 1; regs.mode_register = currVal; + regs.aux_mode_reg_enable = 1; + regs.aux_mode_reg = auxVal; regs.pre_register_enable = 1; regs.pre_register = config->pre_samples & 0x0000FFFF; @@ -97,15 +135,13 @@ static void writeConfig(int fd, struct rpadc_configuration *config) regs.post_register_enable = 1; regs.post_register = config->post_samples; - regs.decimator_register_enable = 1; - - // Decimator IP seems not to work properly is decimation set the firsttime to - // 1 regs.decimator_register = 10; regs.lev_trig_count = 1; // set first count higher than init in VHDL + regs.deadtime_register_enable = 1; + regs.deadtime_register = config->deadtime; ioctl(fd, RFX_STREAM_SET_REGISTERS, ®s); usleep(10000); @@ -113,16 +149,6 @@ static void writeConfig(int fd, struct rpadc_configuration *config) printf("MODE REGISTER:%x\n", regs.mode_register); ioctl(fd, RFX_STREAM_SET_REGISTERS, ®s); printf("REGISTRI SCRITTI:%x\n", regs.mode_register); - - /* - if(config->mode == STREAMING) - dmaBufSize = DMA_STREAMING_SAMPLES * sizeof(unsigned int); - else - dmaBufSize = (config->post_samples + config->pre_samples) * - sizeof(unsigned int); - - ioctl(fd, RPADC_DMA_AUTO_ARM_DMA, &dmaBufSize); - */ currVal = 1; ioctl(fd, RFX_STREAM_SET_PACKETIZER, &currVal); @@ -133,10 +159,11 @@ static void writeConfig(int fd, struct rpadc_configuration *config) static void readConfig(int fd, struct rpadc_configuration *config) { - unsigned int currVal; + unsigned int currVal, auxVal; struct rfx_stream_registers regs; ioctl(fd, RFX_STREAM_GET_REGISTERS, ®s); currVal = regs.mode_register; + auxVal = regs.aux_mode_reg; if (currVal & 0x00000001) config->mode = STREAMING; else @@ -156,16 +183,28 @@ static void readConfig(int fd, struct rpadc_configuration *config) config->mode = TRIGGER_SINGLE; } } - if (currVal & 0x00000020) + if (!(currVal & 0x00000020)) + { + config->clock_mode = INTERNAL; + } + else { if (currVal & 0x00000040) - config->clock_mode = EXTERNAL; + { + if (auxVal & 0x0000004) + config->clock_mode = EXTERNAL; + else + config->clock_mode = SYNC; + } else - config->clock_mode = TRIG_EXTERNAL; + { + if (auxVal & 0x0000004) + config->clock_mode = TRIG_EXTERNAL; + else + config->clock_mode = TRIG_ABS; + } } - else - config->clock_mode = INTERNAL; - + if (currVal & 0x00000002) config->trig_from_chana = 1; else @@ -182,6 +221,9 @@ static void readConfig(int fd, struct rpadc_configuration *config) config->post_samples = regs.post_register; config->pre_samples = regs.pre_register; config->decimation = regs.decimator_register + 1; + config->deadtime = regs.deadtime_register; + + printf("Mode Register: %x\t Aux Mode Register: %x\n", regs.mode_register, regs.aux_mode_reg); } static void fifoFlush(int fd) { ioctl(fd, RFX_STREAM_FIFO_FLUSH, NULL); } @@ -207,7 +249,6 @@ static void adcArm(int fd) std::cout << "ARM " << fd << std::endl; ioctl(fd, RFX_STREAM_GET_TIME_FIFO_LEN, &command); - std::cout << "TIME FIFO LEN: " << command << std::endl; ioctl(fd, RFX_STREAM_GET_TIME_FIFO_VAL, &command); command = 0x00000001; // Arm @@ -222,19 +263,13 @@ static void adcTrigger(int fd) ioctl(fd, RFX_STREAM_SET_COMMAND_REGISTER, &command); ioctl(fd, RFX_STREAM_GET_DRIVER_BUFLEN, &command); - std::cout << "DATA FIFO LEN: " << command << std::endl; // ioctl(fd, RFX_STREAM_GET_DATA_FIFO_VAL, &command); // ioctl(fd, RFX_STREAM_GET_TIME_FIFO_LEN, &command); // ioctl(fd, RFX_STREAM_GET_TIME_FIFO_VAL, &command); } static void adcClearFifo(int fd) { ioctl(fd, RFX_STREAM_CLEAR_TIME_FIFO, 0); } -/* -static void dmaStart(int fd, int cyclic) -{ - ioctl(fd, RFX_STREAM_START_DMA, &cyclic); -} -*/ + static void sigHandler(int signo) { if (signo == SIGINT) @@ -257,7 +292,6 @@ static void writeSegment(MDSplus::Tree *t, MDSplus::TreeNode *chan1, double *endTimes, int segmentSamples, int blocksInSegment, double freq, SaveList *saveList) { - std::cout << "WRITE SEGMENT " << segmentSamples; if (segmentSamples == 0) return; short *chan1Samples, *chan2Samples; @@ -292,27 +326,43 @@ void rpadcStop(int fd) usleep(100000); stopRead(fd); usleep(100000); - std::cout << "CLOSE "; - close(fd); + close(fd); std::cout << "CLOSED\n"; } void rpadcStream(int fd, char *treeName, int shot, int chan1Nid, int chan2Nid, int triggerNid, int preSamples, int postSamples, - int inSegmentSamples, double freq, double freq1, int single) + int inSegmentSamples, double freq, double freq1, int single, int absTriggerTimeFromFPGA, int absTriggerNid) { + +//freq: frequency of the sampling clock +//freq1: frequency used to timestamp triggers + int segmentSamples; // True segment dimension - int blockSamples; // post samples + pre samples for event streaming, + unsigned int blockSamples; // post samples + pre samples for event streaming, // segmentSize for continuous streaming int blocksInSegment; // 1 fir cintinous streaming unsigned int *dataSamples; double *startTimes, *endTimes; - unsigned long long prevTime = 0; stopped = false; unsigned int trig_lev_count = 0; + unsigned long long firstAbsTriggerTime = 0; + unsigned long long lastAbsTriggerTime = 0; + unsigned long long currTime, savedTime; + + std::cout << "rpadcStream freq1: " << freq1 << " FREQ: " << freq << std::endl; + + + + + absTriggerTime = 0; //It will be set by setTriggerTime() + isFirstTrigger = true; + MDSplus::Tree *tree = new MDSplus::Tree(treeName, shot); MDSplus::TreeNode *chan1 = new MDSplus::TreeNode(chan1Nid, tree); MDSplus::TreeNode *chan2 = new MDSplus::TreeNode(chan2Nid, tree); + MDSplus::TreeNode *absTrigger = new MDSplus::TreeNode(absTriggerNid, tree); + MDSplus::TreeNode *trigger = new MDSplus::TreeNode(triggerNid, tree); if ((preSamples == 0 && postSamples == 0)) // eventSamples == 0 means continuous streaming @@ -362,7 +412,6 @@ void rpadcStream(int fd, char *treeName, int shot, int chan1Nid, int chan2Nid, adcArm(fd); usleep(1000); int segmentIdx = 0; - prevTime = 0; SaveList *saveList = new SaveList; saveList->start(); // START WITH A INITIAL VALUE FOR TRIG_LEV_COUNT @@ -370,18 +419,33 @@ void rpadcStream(int fd, char *treeName, int shot, int chan1Nid, int chan2Nid, trig_lev_count++; ioctl(fd, RFX_STREAM_SET_LEV_TRIG_COUNT, &trig_lev_count); + struct timeval selWaitTime; while (true) { for (int currBlock = 0; currBlock < blocksInSegment; currBlock++) { unsigned int currSample = 0; + bool firstRead = true; while (currSample < blockSamples) { +//std::cout<<"Reading...\n"; int rb = read(fd, &dataSamples[currBlock * blockSamples + currSample], (blockSamples - currSample) * sizeof(int)); - //std::cout << "READ " << rb << std::endl; - currSample += rb / sizeof(int); - +//if(rb > 0) std::cout << "READ " << rb << std::endl; + if(rb < 0) + std::cout << "ULLALA!\n"; + else + { + currSample += rb / sizeof(int); + if(firstRead) + { + firstRead = false; + // signal to FPGA that block has been read -- In this way make sure that no more than 2 burst can be concurrenlty in read + ioctl(fd, RFX_STREAM_GET_LEV_TRIG_COUNT, &trig_lev_count); + trig_lev_count++; + ioctl(fd, RFX_STREAM_SET_LEV_TRIG_COUNT, &trig_lev_count); + } + } if (stopped) // May happen when block readout has terminated or in the // middle of readout { @@ -404,33 +468,53 @@ void rpadcStream(int fd, char *treeName, int shot, int chan1Nid, int chan2Nid, if (single) { - startTimes[0] = - (segmentIdx * segmentSamples - preSamples) / freq1; + startTimes[0] = + (segmentIdx * segmentSamples - preSamples) / freq; +// (segmentIdx * segmentSamples - preSamples) / freq1; Gabriele Dec 2021 endTimes[0] = - ((segmentIdx + 1) * segmentSamples - preSamples) / freq1; + ((segmentIdx + 1) * segmentSamples - preSamples) / freq; +// ((segmentIdx + 1) * segmentSamples - preSamples) / freq1; Gabriele Dec 2021 writeSegment(tree, chan1, chan2, trigger, dataSamples, startTimes, endTimes, - currBlock * blockSamples + currSample, 1, freq1, saveList); + currBlock * blockSamples + currSample, 1, freq, saveList); + // currBlock * blockSamples + currSample, 1, freq1, saveList); Gabriele Dec 2021 } else // Some data for new window have been read { - std::cout << "MULTIPLE 1\n"; - unsigned long long currTime; unsigned int time1, time2; ioctl(fd, RFX_STREAM_GET_TIME_FIFO_VAL, &time1); ioctl(fd, RFX_STREAM_GET_TIME_FIFO_VAL, &time2); currTime = (unsigned long long)time1 | (((unsigned long long)time2) << 32); - std::cout << "MULTIPLE 2 " << currBlock << std::endl; - startTimes[currBlock] = (currTime - preSamples) / freq; + + + if(absTriggerTimeFromFPGA) + { + std::cout << "TRIGGER TIME: " << currTime << std::endl; + if(firstAbsTriggerTime == 0) + { + firstAbsTriggerTime = lastAbsTriggerTime = currTime; + currTime = 0; + MDSplus::Data *triggerData = new MDSplus::Uint64(firstAbsTriggerTime); + absTrigger->putData(triggerData); + MDSplus::deleteData(triggerData); + } + else + { + savedTime = currTime; + currTime -= lastAbsTriggerTime; + lastAbsTriggerTime = savedTime; + } + } + startTimes[currBlock] = currTime/freq1 - preSamples/freq; +// startTimes[currBlock] = (currTime - preSamples) / freq; Gabriele Dec 2021 endTimes[currBlock] = - (currTime + postSamples - 1) / freq; // include last sample - // std::cout << "ULTIMO TIME: " << - //currTime << std::endl; + currTime/freq1 + (postSamples - 1) / freq; // include last sample +// (currTime + postSamples - 1) / freq; // include last sample Gabriele Dec 2021 writeSegment(tree, chan1, chan2, trigger, dataSamples, startTimes, endTimes, currBlock * blockSamples + currSample, - currBlock + 1, freq1, saveList); + currBlock + 1, freq, saveList); } } else // Some windows have been read before and the segment is @@ -438,18 +522,11 @@ void rpadcStream(int fd, char *treeName, int shot, int chan1Nid, int chan2Nid, { writeSegment(tree, chan1, chan2, trigger, dataSamples, startTimes, endTimes, currBlock * blockSamples + currSample, - currBlock, freq1, saveList); + currBlock, freq, saveList); } } - // adcStop(fd); - // usleep(100000); - // dmaStop(fd); - // usleep(100000); - // close(fd); deviceFd = 0; - std::cout << "CHIAMO STOP\n"; saveList->stop(); - std::cout << "CHIAMATO\n"; delete chan1; delete chan2; delete trigger; @@ -467,46 +544,67 @@ void rpadcStream(int fd, char *treeName, int shot, int chan1Nid, int chan2Nid, ioctl(fd, RFX_STREAM_SET_LEV_TRIG_COUNT, &trig_lev_count); // Here the block been filled. It may refer to the same window // (isSingle)or to a different time window + + unsigned long long currTime; + unsigned int time1, time2; + ioctl(fd, RFX_STREAM_GET_TIME_FIFO_VAL, &time1); + ioctl(fd, RFX_STREAM_GET_TIME_FIFO_VAL, &time2); + currTime =(unsigned long long)time1 | (((unsigned long long)time2) << 32); + std::cout << "TRIGGER TIME: " << currTime << std::endl; + if(absTriggerTimeFromFPGA) + { + std::cout << "TRIGGER TIME: " << currTime << std::endl; + if(firstAbsTriggerTime == 0) + { + firstAbsTriggerTime = lastAbsTriggerTime = currTime; + currTime = 0; + MDSplus::Data *triggerData = new MDSplus::Uint64(firstAbsTriggerTime); + absTrigger->putData(triggerData); + MDSplus::deleteData(triggerData); + } + else + { + currTime -= firstAbsTriggerTime; + } + } + if (preSamples != 0 || postSamples != 0) // not continuous { - unsigned long long currTime; - unsigned int time1, time2; if (single) { - startTimes[0] = (segmentIdx * segmentSamples - preSamples) / freq1; - endTimes[0] = - ((segmentIdx + 1) * segmentSamples - preSamples) / freq1; + startTimes[0] = (segmentIdx * segmentSamples - preSamples) / freq; +// startTimes[0] = (segmentIdx * segmentSamples - preSamples) / freq1; Gabriele Dec 2021 + endTimes[0] =((segmentIdx + 1) * segmentSamples - preSamples) / freq; +// ((segmentIdx + 1) * segmentSamples - preSamples) / freq1; Gabriele Dec 2021 } else // If referring to a new window, the time must be read { - ioctl(fd, RFX_STREAM_GET_TIME_FIFO_VAL, &time1); - ioctl(fd, RFX_STREAM_GET_TIME_FIFO_VAL, &time2); - currTime = - (unsigned long long)time1 | (((unsigned long long)time2) << 32); - // std::cout << "TIME1: " << time1 << " TIME2: " << time2 << " PREV - // TIME: " << prevTime << std::endl; std::cout << "TIME COUNTER: " << - // currTime << "DELTA: " << currTime - prevTime << " " << (currTime - // - prevTime)/freq << std::endl; - prevTime = currTime; + if (currBlock == 0) - startTimes[currBlock] = - ((long long)currTime - preSamples - 1) / freq; + { + startTimes[currBlock] = ((long long)currTime)/freq1 - (preSamples - 1) / freq; +// ((long long)currTime - preSamples - 1) / freq; Gabriele Dec 2021 + } else - startTimes[currBlock] = ((long long)currTime - preSamples) / freq; - endTimes[currBlock] = - (currTime + postSamples - 1 + 0.1) / freq; // include last sample + { + startTimes[currBlock] = (long long)currTime/freq1 - preSamples / freq; +// startTimes[currBlock] = ((long long)currTime - preSamples) / freq; Gabriele Dec 2021 + } + endTimes[currBlock] = currTime/freq1 + (postSamples - 1 + 0.1) / freq; + // (currTime + postSamples - 1 + 0.1) / freq; Gabriele Dec 2021 } } } if (preSamples == 0 && postSamples == 0) { - startTimes[0] = segmentIdx * segmentSamples / freq1; - endTimes[0] = (segmentIdx + 1) * segmentSamples / freq1; +// startTimes[0] = segmentIdx * segmentSamples / freq1; Gabriele Dec 2021 +// endTimes[0] = (segmentIdx + 1) * segmentSamples / freq1; Gabriele Dec 2021 + startTimes[0] = segmentIdx * segmentSamples / freq; + endTimes[0] = (segmentIdx + 1) * segmentSamples / freq; } segmentIdx++; - writeSegment(tree, chan1, chan2, trigger, dataSamples, startTimes, endTimes, - segmentSamples, blocksInSegment, freq1, saveList); + segmentSamples, blocksInSegment, freq, saveList); } std::cout << "ULTIMAO RPADCSTREAM\n"; } @@ -539,17 +637,14 @@ static void printConfig(struct rpadc_configuration *config) case TRIG_EXTERNAL: printf("\tclock_mode: TRIG_EXTERNAL\n"); break; + case TRIG_ABS: + printf("\tclock_mode: TRIG_ABS\n"); + break; case EXTERNAL: printf("\tclock_mode: EXTERNAL\n"); break; - case TRIG_EVENT: - printf("\tclock_mode: TRIG_EVENT\n"); - break; - case EXT_EVENT: - printf("\tclock_mode: EXT_EVENT\n"); - break; - case HIGHWAY: - printf("\tclock_mode: HIGHWAY\n"); + case SYNC: + printf("\tclock_mode: SYNC\n"); break; } @@ -568,13 +663,13 @@ static void printConfig(struct rpadc_configuration *config) printf("\tpre_samples: %d\n", config->pre_samples); printf("\tpost_samples: %d\n", config->post_samples); printf("\tdecimation: %d\n", config->decimation); - printf("\tevent_code: %d\n", config->event_code); + printf("\tdeadtime: %d\n", config->deadtime); } // return either NULL or an error string int rpadcInit(int mode, int clock_mode, int preSamples, int postSamples, int trigFromChanA, int trigAboveThreshold, int trigThreshold, - int thresholdSamples, int decimation, int event_code) + int thresholdSamples, int decimation, int deadtime) { struct rpadc_configuration inConfig, outConfig; int fd = open("/dev/rfx_stream", O_RDWR | O_SYNC); @@ -600,37 +695,31 @@ int rpadcInit(int mode, int clock_mode, int preSamples, int postSamples, inConfig.pre_samples = preSamples; inConfig.post_samples = postSamples; // Watch!!!!! inConfig.decimation = decimation; - inConfig.event_code = event_code; + inConfig.deadtime = deadtime; printConfig(&inConfig); writeConfig(fd, &inConfig); memset(&outConfig, 0, sizeof(outConfig)); readConfig(fd, &outConfig); printConfig(&outConfig); - // adcStop(fd); - // status = ioctl(fd, RFX_RPADC_STOP, 0); - // sleep(1); - // dmaStop(fd); - // sleep(1); adcClearFifo(fd); usleep(1000); - // adcArm(fd); - // usleep(1000); - /* - if(mode == 2 || mode == 4) //if single - dmaStart(fd, 1); - // dmaStart(fd, 0); - else - dmaStart(fd, 1); - usleep(1000); - */ return fd; } int rpadcTrigger(int fd) { + struct timeval currTime; + if(isFirstTrigger) + { + isFirstTrigger = false; + if(absTriggerTime == 0) + { + gettimeofday(&currTime, NULL); + absTriggerTime = (unsigned long long)currTime.tv_sec* 1000000L + currTime.tv_usec; + } + } adcTrigger(fd); - // int status = ioctl(fd, RFX_RPADC_TRIGGER, 0); usleep(10); return 0; } @@ -647,35 +736,190 @@ void openTree(char *name, int shot, MDSplus::Tree **treePtr) } } -int main(int argc, char *argv[]) +////////////////////Clock related stuff + + + + + + static double getFrequency(int fd) { - // int preSamples = 0, postSamples = 30; - // if (signal(SIGINT, sigHandler) == SIG_ERR) - // std::cout << "\ncan't catch SIGINT\n"; + double K, step, periodFPGA, period; + unsigned int Kr, C, stepLo, stepHi, reg, K1, K2; + unsigned long long stepR; + ioctl(fd, RFX_STREAM_GET_K1_REG, &K1); + + ioctl(fd, RFX_STREAM_GET_K2_REG, &K2); + + ioctl(fd, RFX_STREAM_GET_STEP_LO_REG, &stepLo); + + ioctl(fd, RFX_STREAM_GET_STEP_HI_REG, &stepHi); + + stepR = stepHi; + stepR = (stepR << 32)|stepLo; + step = (double)stepR/pow(2, 44); + + periodFPGA = 1./125E6; + period = (periodFPGA * K1)*step + (periodFPGA * K2)*(1.-step); + return 0.5/period; +} - int preSamples = 100, postSamples = 200; - int fd = - rpadcInit(0, 0, preSamples, postSamples, 1, 1, 5000, 2, atoi(argv[1]), 0); - try - { + +static void setFrequency(int fd, double reqFreq) +{ + double K, step; + unsigned int Kr, C, stepLo, stepHi, reg, K1, K2; + unsigned long long stepR; + + K = 0.25E7 * 25. /reqFreq; //125MHz clock + Kr = round(K); + if (Kr > K) + { + C = round(COUNT_SIZE*(1 - (Kr -K))); + K1 = Kr; + K2 = Kr - 1; + } + else if (Kr < K) + { + C = round(COUNT_SIZE*(1- (K - Kr))); + K1 = Kr; + K2 = Kr+1; + } + else + { + K1 = K2 = K; + C = COUNT_SIZE/2; + } + step = C/(double)COUNT_SIZE; + step *= pow(2, 44); + stepR = round(step); + stepLo = (unsigned int)(stepR & 0xFFFFFFFF); + stepHi = (unsigned int)((stepR >> 32) & 0xFFFFFFFF); + printf("K1: %d, K2: %d, C: %u, Step: %lld\n", K1, K2, C, stepR); + ioctl(fd, RFX_STREAM_SET_K1_REG, &K1); + + ioctl(fd, RFX_STREAM_SET_K2_REG, &K2); + + ioctl(fd, RFX_STREAM_SET_STEP_LO_REG, &stepLo); + + ioctl(fd, RFX_STREAM_SET_STEP_HI_REG, &stepHi); + + reg = 0; + ioctl(fd, RFX_STREAM_SET_TIME_COMMAND_REG, ®); + usleep(1000); + reg = 1; + ioctl(fd, RFX_STREAM_SET_TIME_COMMAND_REG, ®); + reg = 0; + ioctl(fd, RFX_STREAM_SET_TIME_COMMAND_REG, ®); +} + + - MDSplus::Tree *t = new MDSplus::Tree("redpitaya", -1); - t->createPulse(1); - t = new MDSplus::Tree("redpitaya", 1); - MDSplus::TreeNode *chan1 = t->getNode("rpadc:chan_a"); - MDSplus::TreeNode *chan2 = t->getNode("rpadc:chan_b"); - MDSplus::TreeNode *trigger = t->getNode("rpadc:trigger"); - rpadcTrigger(fd); - rpadcStream(fd, (char *)"redpitaya", 1, chan1->getNid(), chan2->getNid(), - trigger->getNid(), preSamples, postSamples, 1000, - 125E6 / atoi(argv[1]), 125E6 / atoi(argv[1]), 0); - - rpadcStop(fd); + +static unsigned long long getTime(int fd, double actFrequency) +{ + unsigned int reg, lo, hi = 0, len; + unsigned long long time; + reg = 0; + ioctl(fd, RFX_STREAM_SET_TIME_COMMAND_REG, ®); + reg = 2; + ioctl(fd, RFX_STREAM_SET_TIME_COMMAND_REG, ®); + reg = 0; + ioctl(fd, RFX_STREAM_SET_TIME_COMMAND_REG, ®); + len = -1; + ioctl(fd, RFX_STREAM_GET_SYNC_FIFO_LEN, &len); + if(len != 2) + printf("\n\nERRORE ERRORRISSIMO %d\n\n\n", len); + ioctl(fd, RFX_STREAM_GET_SYNC_FIFO_VAL, &lo); + ioctl(fd, RFX_STREAM_GET_SYNC_FIFO_VAL, &hi); + + + + time = hi; + time = (time << 32) | lo; + + time = round(1E6 * (double)time/actFrequency); + return time; +} + +static void setTime(int fd, unsigned long long timeUs, double actFreq) +{ + unsigned long long fpgaTime, ofsTime; + unsigned int reg = 0, reg1 = 0, reg2 = 0; + + + //Reset offset register + reg = 0; + ioctl(fd, RFX_STREAM_SET_TIME_OFFSET_HI_REG, ®); + ioctl(fd, RFX_STREAM_SET_TIME_OFFSET_LO_REG, ®); + + fpgaTime = getTime(fd, actFreq); + ofsTime = round((timeUs - fpgaTime)*actFreq / 1E6); + reg = ofsTime & 0x00000000FFFFFFFFL; + ioctl(fd, RFX_STREAM_SET_TIME_OFFSET_LO_REG, ®); + reg = (ofsTime >> 32) & 0x00000000FFFFFFFFL; + ioctl(fd, RFX_STREAM_SET_TIME_OFFSET_HI_REG, ®); + + ioctl(fd, RFX_STREAM_GET_TIME_OFFSET_LO_REG, ®1); + ioctl(fd, RFX_STREAM_GET_TIME_OFFSET_HI_REG, ®2); + + + +} + +static void updateFreq(int fd, unsigned long long *prevTimeUs, unsigned long long *prevFpgaTimeUs, double kp, double ki, double *prevFreq, double actFreq) +{ + struct timeval currTime; + unsigned long long timeUs, fpgaTimeUs; + double steps; + long long stepErr, totErr, elapsedSteps, elapsedStepsFpga; + double newFreq = *prevFreq; + gettimeofday(&currTime, NULL); + timeUs = (unsigned long long)currTime.tv_sec * 1000000L + currTime.tv_usec; + fpgaTimeUs = getTime(fd, actFreq); + totErr = fpgaTimeUs - timeUs; + + printf("TIME: %lld\tFPGA Time: %lld\n", timeUs, fpgaTimeUs); + + if(*prevTimeUs) //The first time only measurements performed, no correction + { + elapsedSteps = timeUs - *prevTimeUs; + elapsedStepsFpga = fpgaTimeUs - *prevFpgaTimeUs; + stepErr = elapsedStepsFpga - elapsedSteps; + + steps = kp*(double)stepErr + ki *(double) totErr; + //printf("STEPS: %e\n", steps); + //printf("ELAPSED STEP FPGA: %llu\tELAPSET STEPS: %llu\n", elapsedStepsFpga, elapsedSteps); + newFreq = 1./(1./ *prevFreq + (steps * 16 * 1E-9)/(2*1E6)); //Attuale conteggio fpga + printf("Step Err: %lld\t Tot err: %lld\tSteps: %d\n", stepErr, totErr, (int)steps); + setFrequency(fd, actFreq * newFreq/1E6); + *prevFreq = newFreq; } - catch (MDSplus::MdsException &exc) + else { - std::cout << exc.what() << std::endl; - return 0; + *prevFreq = getFrequency(fd); } - return 0; + *prevTimeUs = timeUs; + *prevFpgaTimeUs = fpgaTimeUs; } +// +#define UPDATE_SECS 1 +static unsigned long long prevTimeUs = 0; +static unsigned long long prevFpgaTimeUs = 0; +static double prevFreq = 1E6; + +void checkUpdateFreq(int fd) +{ + unsigned long long timeS; + struct timeval currTime; + double targetFreq = 1E6; + static unsigned long prevTimeS = 0; + gettimeofday(&currTime, NULL); + timeS = (unsigned long long)currTime.tv_sec; + if((timeS - prevTimeS) > UPDATE_SECS) + { + prevTimeS = timeS; + updateFreq(fd, &prevTimeUs, &prevFpgaTimeUs, 6., 5.,&prevFreq, targetFreq) ; + } +} + diff --git a/device_support/redpitaya/rfx_stream.h b/device_support/redpitaya/rfx_stream.h index 224c5b4d92..c3edf68591 100644 --- a/device_support/redpitaya/rfx_stream.h +++ b/device_support/redpitaya/rfx_stream.h @@ -38,45 +38,50 @@ extern "C" { #define RFX_STREAM_FIFO_FLUSH _IO(RFX_STREAM_IOCTL_BASE, 14) #define RFX_STREAM_START_READ _IO(RFX_STREAM_IOCTL_BASE, 15) #define RFX_STREAM_STOP_READ _IO(RFX_STREAM_IOCTL_BASE, 16) -#define RFX_STREAM_GET_AUX_CFG_REG _IO(RFX_STREAM_IOCTL_BASE, 20) -#define RFX_STREAM_SET_AUX_CFG_REG _IO(RFX_STREAM_IOCTL_BASE, 21) +#define RFX_STREAM_GET_AUX_MODE_REG _IO(RFX_STREAM_IOCTL_BASE, 20) +#define RFX_STREAM_SET_AUX_MODE_REG _IO(RFX_STREAM_IOCTL_BASE, 21) #define RFX_STREAM_GET_COMMAND_REGISTER _IO(RFX_STREAM_IOCTL_BASE, 22) #define RFX_STREAM_SET_COMMAND_REGISTER _IO(RFX_STREAM_IOCTL_BASE, 23) -#define RFX_STREAM_GET_DECIMATOR_REGISTER _IO(RFX_STREAM_IOCTL_BASE, 24) -#define RFX_STREAM_SET_DECIMATOR_REGISTER _IO(RFX_STREAM_IOCTL_BASE, 25) -#define RFX_STREAM_GET_K1_REG _IO(RFX_STREAM_IOCTL_BASE, 26) -#define RFX_STREAM_SET_K1_REG _IO(RFX_STREAM_IOCTL_BASE, 27) -#define RFX_STREAM_GET_K2_REG _IO(RFX_STREAM_IOCTL_BASE, 28) -#define RFX_STREAM_SET_K2_REG _IO(RFX_STREAM_IOCTL_BASE, 29) -#define RFX_STREAM_GET_LEV_TRIG_COUNT _IO(RFX_STREAM_IOCTL_BASE, 30) -#define RFX_STREAM_SET_LEV_TRIG_COUNT _IO(RFX_STREAM_IOCTL_BASE, 31) -#define RFX_STREAM_GET_MODE_REGISTER _IO(RFX_STREAM_IOCTL_BASE, 32) -#define RFX_STREAM_SET_MODE_REGISTER _IO(RFX_STREAM_IOCTL_BASE, 33) -#define RFX_STREAM_GET_PACKETIZER _IO(RFX_STREAM_IOCTL_BASE, 34) -#define RFX_STREAM_SET_PACKETIZER _IO(RFX_STREAM_IOCTL_BASE, 35) -#define RFX_STREAM_GET_POST_REGISTER _IO(RFX_STREAM_IOCTL_BASE, 36) -#define RFX_STREAM_SET_POST_REGISTER _IO(RFX_STREAM_IOCTL_BASE, 37) -#define RFX_STREAM_GET_PRE_REGISTER _IO(RFX_STREAM_IOCTL_BASE, 38) -#define RFX_STREAM_SET_PRE_REGISTER _IO(RFX_STREAM_IOCTL_BASE, 39) -#define RFX_STREAM_GET_STEP_HI_REG _IO(RFX_STREAM_IOCTL_BASE, 40) -#define RFX_STREAM_SET_STEP_HI_REG _IO(RFX_STREAM_IOCTL_BASE, 41) -#define RFX_STREAM_GET_STEP_LO_REG _IO(RFX_STREAM_IOCTL_BASE, 42) -#define RFX_STREAM_SET_STEP_LO_REG _IO(RFX_STREAM_IOCTL_BASE, 43) -#define RFX_STREAM_GET_TIME_COMMAND_REG _IO(RFX_STREAM_IOCTL_BASE, 44) -#define RFX_STREAM_SET_TIME_COMMAND_REG _IO(RFX_STREAM_IOCTL_BASE, 45) -#define RFX_STREAM_GET_TIME_OFFSET_HI_REG _IO(RFX_STREAM_IOCTL_BASE, 46) -#define RFX_STREAM_SET_TIME_OFFSET_HI_REG _IO(RFX_STREAM_IOCTL_BASE, 47) -#define RFX_STREAM_GET_TIME_OFFSET_LO_REG _IO(RFX_STREAM_IOCTL_BASE, 48) -#define RFX_STREAM_SET_TIME_OFFSET_LO_REG _IO(RFX_STREAM_IOCTL_BASE, 49) -#define RFX_STREAM_GET_DATA_FIFO_LEN _IO(RFX_STREAM_IOCTL_BASE, 50) -#define RFX_STREAM_GET_DATA_FIFO_VAL _IO(RFX_STREAM_IOCTL_BASE, 51) -#define RFX_STREAM_CLEAR_DATA_FIFO _IO(RFX_STREAM_IOCTL_BASE, 52) -#define RFX_STREAM_GET_SYNC_FIFO_LEN _IO(RFX_STREAM_IOCTL_BASE, 53) -#define RFX_STREAM_GET_SYNC_FIFO_VAL _IO(RFX_STREAM_IOCTL_BASE, 54) -#define RFX_STREAM_CLEAR_SYNC_FIFO _IO(RFX_STREAM_IOCTL_BASE, 55) -#define RFX_STREAM_GET_TIME_FIFO_LEN _IO(RFX_STREAM_IOCTL_BASE, 56) -#define RFX_STREAM_GET_TIME_FIFO_VAL _IO(RFX_STREAM_IOCTL_BASE, 57) -#define RFX_STREAM_CLEAR_TIME_FIFO _IO(RFX_STREAM_IOCTL_BASE, 58) +#define RFX_STREAM_GET_DEADTIME_REGISTER _IO(RFX_STREAM_IOCTL_BASE, 24) +#define RFX_STREAM_SET_DEADTIME_REGISTER _IO(RFX_STREAM_IOCTL_BASE, 25) +#define RFX_STREAM_GET_DECIMATOR_REGISTER _IO(RFX_STREAM_IOCTL_BASE, 26) +#define RFX_STREAM_SET_DECIMATOR_REGISTER _IO(RFX_STREAM_IOCTL_BASE, 27) +#define RFX_STREAM_GET_K1_REG _IO(RFX_STREAM_IOCTL_BASE, 28) +#define RFX_STREAM_SET_K1_REG _IO(RFX_STREAM_IOCTL_BASE, 29) +#define RFX_STREAM_GET_K2_REG _IO(RFX_STREAM_IOCTL_BASE, 30) +#define RFX_STREAM_SET_K2_REG _IO(RFX_STREAM_IOCTL_BASE, 31) +#define RFX_STREAM_GET_LEV_TRIG_COUNT _IO(RFX_STREAM_IOCTL_BASE, 32) +#define RFX_STREAM_SET_LEV_TRIG_COUNT _IO(RFX_STREAM_IOCTL_BASE, 33) +#define RFX_STREAM_GET_MODE_REGISTER _IO(RFX_STREAM_IOCTL_BASE, 34) +#define RFX_STREAM_SET_MODE_REGISTER _IO(RFX_STREAM_IOCTL_BASE, 35) +#define RFX_STREAM_GET_PACKETIZER _IO(RFX_STREAM_IOCTL_BASE, 36) +#define RFX_STREAM_SET_PACKETIZER _IO(RFX_STREAM_IOCTL_BASE, 37) +#define RFX_STREAM_GET_POST_REGISTER _IO(RFX_STREAM_IOCTL_BASE, 38) +#define RFX_STREAM_SET_POST_REGISTER _IO(RFX_STREAM_IOCTL_BASE, 39) +#define RFX_STREAM_GET_PRE_REGISTER _IO(RFX_STREAM_IOCTL_BASE, 40) +#define RFX_STREAM_SET_PRE_REGISTER _IO(RFX_STREAM_IOCTL_BASE, 41) +#define RFX_STREAM_GET_STEP_HI_REG _IO(RFX_STREAM_IOCTL_BASE, 42) +#define RFX_STREAM_SET_STEP_HI_REG _IO(RFX_STREAM_IOCTL_BASE, 43) +#define RFX_STREAM_GET_STEP_LO_REG _IO(RFX_STREAM_IOCTL_BASE, 44) +#define RFX_STREAM_SET_STEP_LO_REG _IO(RFX_STREAM_IOCTL_BASE, 45) +#define RFX_STREAM_GET_TIME_COMMAND_REG _IO(RFX_STREAM_IOCTL_BASE, 46) +#define RFX_STREAM_SET_TIME_COMMAND_REG _IO(RFX_STREAM_IOCTL_BASE, 47) +#define RFX_STREAM_GET_TIME_OFFSET_HI_REG _IO(RFX_STREAM_IOCTL_BASE, 48) +#define RFX_STREAM_SET_TIME_OFFSET_HI_REG _IO(RFX_STREAM_IOCTL_BASE, 49) +#define RFX_STREAM_GET_TIME_OFFSET_LO_REG _IO(RFX_STREAM_IOCTL_BASE, 50) +#define RFX_STREAM_SET_TIME_OFFSET_LO_REG _IO(RFX_STREAM_IOCTL_BASE, 51) +#define RFX_STREAM_GET_DATA_FIFO_LEN _IO(RFX_STREAM_IOCTL_BASE, 52) +#define RFX_STREAM_GET_DATA_FIFO_VAL _IO(RFX_STREAM_IOCTL_BASE, 53) +#define RFX_STREAM_SET_DATA_FIFO_VAL _IO(RFX_STREAM_IOCTL_BASE, 54) +#define RFX_STREAM_CLEAR_DATA_FIFO _IO(RFX_STREAM_IOCTL_BASE, 55) +#define RFX_STREAM_GET_SYNC_FIFO_LEN _IO(RFX_STREAM_IOCTL_BASE, 56) +#define RFX_STREAM_GET_SYNC_FIFO_VAL _IO(RFX_STREAM_IOCTL_BASE, 57) +#define RFX_STREAM_SET_SYNC_FIFO_VAL _IO(RFX_STREAM_IOCTL_BASE, 58) +#define RFX_STREAM_CLEAR_SYNC_FIFO _IO(RFX_STREAM_IOCTL_BASE, 59) +#define RFX_STREAM_GET_TIME_FIFO_LEN _IO(RFX_STREAM_IOCTL_BASE, 60) +#define RFX_STREAM_GET_TIME_FIFO_VAL _IO(RFX_STREAM_IOCTL_BASE, 61) +#define RFX_STREAM_SET_TIME_FIFO_VAL _IO(RFX_STREAM_IOCTL_BASE, 62) +#define RFX_STREAM_CLEAR_TIME_FIFO _IO(RFX_STREAM_IOCTL_BASE, 63) #ifndef AXI_ENUMS_DEFINED @@ -136,10 +141,12 @@ enum RegisterIdx { struct rfx_stream_registers { - char aux_cfg_reg_enable; - unsigned int aux_cfg_reg; + char aux_mode_reg_enable; + unsigned int aux_mode_reg; char command_register_enable; unsigned int command_register; + char deadtime_register_enable; + unsigned int deadtime_register; char decimator_register_enable; unsigned int decimator_register; char k1_reg_enable; diff --git a/device_support/redpitaya/rfx_stream.ko b/device_support/redpitaya/rfx_stream.ko new file mode 100644 index 0000000000..e04e81e05d Binary files /dev/null and b/device_support/redpitaya/rfx_stream.ko differ diff --git a/device_support/redpitaya/rfx_nioadc_dma_0.1.bit b/device_support/redpitaya/rfx_stream_0.1.bit similarity index 66% rename from device_support/redpitaya/rfx_nioadc_dma_0.1.bit rename to device_support/redpitaya/rfx_stream_0.1.bit index fdb167ddfa..fa48257f12 100644 Binary files a/device_support/redpitaya/rfx_nioadc_dma_0.1.bit and b/device_support/redpitaya/rfx_stream_0.1.bit differ diff --git a/device_support/redpitaya/rpadc_fifo_auto.c b/device_support/redpitaya/rpadc_fifo_auto.c deleted file mode 100644 index 56716c61e0..0000000000 --- a/device_support/redpitaya/rpadc_fifo_auto.c +++ /dev/null @@ -1,1066 +0,0 @@ -#define HAS_FIFO_INTERRUPT - -#include -#include -#include -#include -#include - -#include -#include - -#include -#include // put_user - -#include - -#include - -#include -#include - -#include "rpadc_fifo_auto.h" - -#include // axi dma driver -#include // dma api - -#include -#include -#include -#include -#include -#include - -#define SUCCESS 0 -#define FIFO_LEN 16384 - -#define DMA_STREAMING_SAMPLES 1024 -// static struct platform_device *s_pdev = 0; -// static int s_device_open = 0; -static int device_open(struct inode *, struct file *); -static int device_release(struct inode *, struct file *); -static ssize_t device_read(struct file *, char *, size_t, loff_t *); -static ssize_t device_write(struct file *, const char *, size_t, loff_t *); -static int device_mmap(struct file *filp, struct vm_area_struct *vma); -static loff_t memory_lseek(struct file *file, loff_t offset, int orig); -static long device_ioctl(struct file *file, unsigned int cmd, - unsigned long arg); -static unsigned int device_poll(struct file *file, struct poll_table_struct *p); - -static int deviceAllocated = 0; - -static struct file_operations fops = { - .read = device_read, - .write = device_write, - .open = device_open, - .release = device_release, - .mmap = device_mmap, - .llseek = memory_lseek, - .unlocked_ioctl = device_ioctl, - .poll = device_poll, -}; - -#define BUFSIZE 200000 - -struct rpadc_fifo_auto_dev -{ - struct platform_device *pdev; - struct cdev cdev; - int busy; - int irq; - - void *iomap_command_register; - void *iomap_decimator_register; - void *iomap_mode_register; - void *iomap_packetizer; - void *iomap_post_register; - void *iomap_pre_register; - void *iomap_trig_event_code; - void *iomap_event_code; - void *iomap_data_fifo; - void *iomap1_data_fifo; - void *iomap_time_fifo; - void *iomap1_time_fifo; - - struct semaphore sem; /* mutual exclusion semaphore */ - spinlock_t spinLock; /* spinlock */ - u32 *fifoBuffer; - u32 bufSize; - u32 rIdx, wIdx, bufCount; - wait_queue_head_t readq; /* read queue */ - int dma_started; - int dma_cyclic; - int started; -#ifdef HAS_DMA - struct dma_chan *dma_chan; - dma_addr_t dma_handle; - dma_addr_t rx_dma_handle; - char *dma_buffer; - u32 dma_buf_size; - dma_cookie_t dma_cookie; - struct completion dma_cmp; -#endif -#ifdef HAS_FIFO_INTERRUPT - int fifoHalfInterrupt; - int fifoOverflow; -#endif -}; - -//////////////////////////////////////////////////////////////////////////////// -// FIFO IO /////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////// - -void writeFifo(void *addr, enum AxiStreamFifo_Register op, u32 data) -{ - *(u32 *)(addr + op) = data; -} - -u32 readFifo(void *addr, enum AxiStreamFifo_Register op) -{ - return *(u32 *)(addr + op); -} - -static void clearFifo(void *dev, void *dev1) -{ - u32 occ, i; - writeFifo(dev, ISR, 0xFFFFFFFF); - writeFifo(dev, RDFR, 0xa5); - writeFifo(dev, IER, 0x04000000); - // occ = readFifo(dev,RDFO); - // for(i = 0; i < occ; i++) - // readFifo(dev,RDFD4); -} - -#ifdef HAS_DMA -static dma_cookie_t dma_prep_buffer(struct rpadc_fifo_auto_dev *dev, - struct dma_chan *chan, dma_addr_t buf, - size_t len, enum dma_transfer_direction dir, - struct completion *cmp); -static void dma_start_transfer(struct dma_chan *chan, struct completion *cmp, - dma_cookie_t cookie, int wait); -#endif // HAS_DMA - -int writeBuf(struct rpadc_fifo_auto_dev *dev, u32 sample) -{ - spin_lock_irq(&dev->spinLock); - if (dev->bufCount >= dev->bufSize) - { - printk(KERN_DEBUG "ADC FIFO BUFFER OVERFLOW!\n"); - spin_unlock_irq(&dev->spinLock); - return -1; - } - else - { - dev->fifoBuffer[dev->wIdx] = sample; - dev->wIdx = (dev->wIdx + 1) % dev->bufSize; - dev->bufCount++; - } - spin_unlock_irq(&dev->spinLock); - return 0; -} - -int writeBufSet(struct rpadc_fifo_auto_dev *dev, u32 *buf, int nSamples) -{ - int i; - spin_lock_irq(&dev->spinLock); - for (i = 0; i < nSamples; i++) - { - if (dev->bufCount >= dev->bufSize) - { - printk(KERN_DEBUG "ADC FIFO BUFFER OVERFLOW %d %d!\n", dev->bufCount, - dev->bufSize); - spin_unlock_irq(&dev->spinLock); - return -1; - } - else - { - dev->fifoBuffer[dev->wIdx] = buf[i]; - dev->wIdx = (dev->wIdx + 1) % dev->bufSize; - dev->bufCount++; - } - } - spin_unlock_irq(&dev->spinLock); - return 0; -} - -u32 readBuf(struct rpadc_fifo_auto_dev *dev) -{ - u32 data; - spin_lock_irq(&dev->spinLock); - if (dev->bufCount <= 0) - { - printk(KERN_DEBUG "ADC FIFO BUFFER UNDERFLOW!\n"); // Should never happen - data = 0; - } - else - { - data = dev->fifoBuffer[dev->rIdx]; - dev->rIdx = (dev->rIdx + 1) % dev->bufSize; - dev->bufCount--; - } - spin_unlock_irq(&dev->spinLock); - return data; -} - -//////////////////////////////////////////////////////////////////////////////// -// DMA Management ///////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////// - -#ifdef HAS_DMA -static void dma_buffer2fifo_buffer(struct rpadc_fifo_auto_dev *dev) -{ - int i; - int dmaSamples = dev->dma_buf_size / sizeof(u32); - writeBufSet(dev, dev->dma_buffer, dmaSamples); - wake_up(&dev->readq); -} - -/* Handle a callback called when the DMA transfer is complete to another - * thread of control - */ -static int dma_sync_callback(struct rpadc_fifo_auto_dev *dev) -{ - int status, i; - dma_cookie_t lastCookie; - // printk("DMA SYNC CALLBACK\n"); - status = dma_async_is_tx_complete(dev->dma_chan, dev->dma_cookie, &lastCookie, - NULL); - if (status != DMA_COMPLETE) - { - printk(KERN_ERR "DMA returned completion callback status of: %s\n", - status == DMA_ERROR ? "error" : "in progress"); - } - if (lastCookie != dev->dma_cookie) - { - printk("DMA NOT TERMINATED FOR THIS COOKIE %d %d\n", lastCookie, - dev->dma_cookie); - dmaengine_terminate_all(dev->dma_chan); - // return 0; - } - // else - { -#ifdef DMA_SOURCE - dma_buffer2fifo_buffer(dev); -#endif - } - // Start a new DMA round if device still armed - // if(!dev->dma_started) - if (!dev->dma_cyclic) - return 0; - for (i = 0; i < dev->dma_buf_size / sizeof(u32); i++) - ((u32 *)dev->dma_buffer)[i] = 0xffffffff; - - dev->dma_cookie = - dma_prep_buffer(dev, dev->dma_chan, dev->dma_handle, dev->dma_buf_size, - DMA_DEV_TO_MEM, &dev->dma_cmp); - if (dma_submit_error(dev->dma_cookie)) - { - printk(KERN_ERR "dma_prep_buffer error\n"); - return -EIO; - } - // printk(KERN_INFO "Starting NEW DMA transfers\n"); - dma_start_transfer(dev->dma_chan, &dev->dma_cmp, dev->dma_cookie, 0); - return 0; -} - -/* Prepare a DMA buffer to be used in a DMA transaction, submit it to the DMA - * engine to queued and return a cookie that can be used to track that status of - * the transaction - */ -static dma_cookie_t dma_prep_buffer(struct rpadc_fifo_auto_dev *dev, - struct dma_chan *chan, dma_addr_t buf, - size_t len, enum dma_transfer_direction dir, - struct completion *cmp) -{ - enum dma_ctrl_flags flags = /*DMA_CTRL_ACK | */ DMA_PREP_INTERRUPT; - struct dma_async_tx_descriptor *chan_desc; - dma_cookie_t cookie; - - chan_desc = dmaengine_prep_slave_single(chan, buf, len, dir, flags); - if (!chan_desc) - { - printk(KERN_ERR "dmaengine_prep_slave_single error\n"); - cookie = -EBUSY; - } - else - { - chan_desc->callback = dma_sync_callback; - chan_desc->callback_param = dev; - // printk("SUBMIT DMA \n"); - cookie = dmaengine_submit(chan_desc); - // printk("SUBMIT DMA cookie: %x\n", cookie); - } - return cookie; -} - -/* Start a DMA transfer that was previously submitted to the DMA engine and then - * wait for it complete, timeout or have an error - */ -static void dma_start_transfer(struct dma_chan *chan, struct completion *cmp, - dma_cookie_t cookie, int wait) -{ - unsigned long timeout = msecs_to_jiffies(10000); - enum dma_status status; - - init_completion(cmp); - dma_async_issue_pending(chan); - - if (wait) - { - timeout = wait_for_completion_timeout(cmp, timeout); - status = dma_async_is_tx_complete(chan, cookie, NULL, NULL); - if (timeout == 0) - { - printk(KERN_ERR "DMA timed out\n"); - } - else if (status != DMA_COMPLETE) - { - printk(KERN_ERR "DMA returned completion callback status of: %s\n", - status == DMA_ERROR ? "error" : "in progress"); - } - } -} -#endif // HAS_DMA - -#ifdef HAS_FIFO_INTERRUPT -//////////////////////////////////////////////////////////////////////////////// -// Interrupt Management for FIFO ////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////// -static void Write(void *addr, enum AxiStreamFifo_Register op, u32 data) -{ - *(u32 *)(addr + op) = data; -} - -static u32 Read(void *addr, enum AxiStreamFifo_Register op) -{ - return *(u32 *)(addr + op); -} - -// interrupt handler // -irqreturn_t IRQ_cb(int irq, void *dev_id, struct pt_regs *regs) -{ - struct rpadc_fifo_auto_dev *dev = dev_id; - // struct rpadc_fifo_dev *rpadc = dev_id; - static int isFirst = 1; - // Check whether he cause of interrupt has been reveive overrun - Write(dev->iomap_data_fifo, ISR, 0xFFFFFFFF); - Write(dev->iomap_data_fifo, IER, 0x00000000); - - void *fifo = dev->iomap_data_fifo; - void *fifo1 = dev->iomap1_data_fifo; - - static u32 prev1, prev2; - - u32 occ = Read(fifo, RDFO); - { - isFirst = 0; - } - - // printk("--INTERRUPT: Available samples: %d\n", occ); - - if (occ >= FIFO_LEN) - { - dev->fifoOverflow = 1; - wake_up(&dev->readq); - // When oveflow is detected, disable interrupts - } - - int i; - for (i = 0; i < occ; i++) - { - u32 currSample = Read(fifo1, RDFD4); - if (writeBuf(dev, currSample) < - 0) // In case of ADC FIFO overflow, abort data readout from FPGA - { - Write(dev->iomap_data_fifo, IER, 0x00000000); - return IRQ_HANDLED; - } - } - wake_up(&dev->readq); - - if (dev->fifoHalfInterrupt) - Write(dev->iomap_data_fifo, IER, 0x00100000); - else - Write(dev->iomap_data_fifo, IER, 0x04000000); - - // printk("--INTERRUPT: Done\n"); - return IRQ_HANDLED; -} - -#endif // HAS_FIFO_INTERRUPT - -// OPEN // -static int device_open(struct inode *inode, struct file *file) -{ - if (!file->private_data) - { - u32 off; - - struct rpadc_fifo_auto_dev *privateInfo = - container_of(inode->i_cdev, struct rpadc_fifo_auto_dev, cdev); - - printk(KERN_DEBUG "OPEN: privateInfo = %0x \n", privateInfo); - // struct resource *r_mem = platform_get_resource(s_pdev, IORESOURCE_MEM, - // 0); - file->private_data = privateInfo; - - privateInfo->busy = 0; - privateInfo->wIdx = 0; - privateInfo->rIdx = 0; - privateInfo->bufCount = 0; - if (privateInfo->bufSize > 0) - kfree(privateInfo->fifoBuffer); - privateInfo->bufSize = BUFSIZE; - privateInfo->fifoBuffer = - (u32 *)kmalloc(privateInfo->bufSize * sizeof(u32), GFP_KERNEL); - privateInfo->dma_started = 0; - privateInfo->dma_cyclic = 0; -#ifdef HAS_FIFO_INTERRUPT - privateInfo->fifoOverflow = 0; - privateInfo->fifoHalfInterrupt = 0; -#endif - } - struct rpadc_fifo_auto_dev *privateInfo = - (struct rpadc_fifo_auto_dev *)file->private_data; - if (!privateInfo) - return -EFAULT; - else if (privateInfo->busy) - return -EBUSY; - else - privateInfo->busy++; - privateInfo->started = 0; - return capable(CAP_SYS_RAWIO) ? 0 : -EPERM; -} - -// CLOSE // -static int device_release(struct inode *inode, struct file *file) -{ - struct rpadc_fifo_auto_dev *dev = file->private_data; - if (!dev) - return -EFAULT; - if (--dev->busy == 0) - { - printk(KERN_DEBUG "CLOSE\n"); - wake_up(&dev->readq); - } - return 0; -} - -static ssize_t device_read(struct file *filp, char *buffer, size_t length, - loff_t *offset) -{ - u32 i = 0; - struct rpadc_fifo_auto_dev *dev = - (struct rpadc_fifo_auto_dev *)filp->private_data; - u32 *b32 = (u32 *)buffer; -#ifdef HAS_FIFO_INTERRUPT - if (dev->fifoOverflow) - return -1; -#endif - while (dev->bufCount == 0) - { - if (filp->f_flags & O_NONBLOCK) - return -EAGAIN; -#ifdef HAS_DMA - if (wait_event_interruptible(dev->readq, - (dev->bufCount > 0 || dev->dma_started == 0))) - return -ERESTARTSYS; - if (!dev->dma_started) - return 0; -#else - if (wait_event_interruptible(dev->readq, - (dev->bufCount > 0 || dev->started == 0))) - return -ERESTARTSYS; - if (!dev->started) - return 0; -#endif - } - - u32 occ = dev->bufCount; - for (i = 0; i < min(length / sizeof(u32), occ); ++i) - { - u32 curr = readBuf(dev); - put_user(curr, b32++); - } - return i * sizeof(u32); -} - -// WRITE // -static ssize_t device_write(struct file *filp, const char *buff, size_t len, - loff_t *off) -{ - printk("<1>Sorry, this operation isn't supported yet.\n"); - return -EINVAL; -} - -// MMAP // -static int device_mmap(struct file *filp, struct vm_area_struct *vma) -{ - printk("<1>Sorry, this operation isn't supported.\n"); - return -EINVAL; -} - -// LSEEK // -static loff_t memory_lseek(struct file *file, loff_t offset, int orig) -{ - printk("<1>Sorry, this operation isn't supported.\n"); - return -EINVAL; -} - -// IOCTL // -static long device_ioctl(struct file *file, unsigned int cmd, - unsigned long arg) -{ - int i; - int status = 0; - struct rpadc_fifo_auto_dev *dev = file->private_data; - - switch (cmd) - { -#ifdef HAS_DMA - case RPADC_FIFO_AUTO_ARM_DMA: - { - u32 newDmaBufSize; - if (!arg) - { - if (dev->dma_buf_size > 0) - newDmaBufSize = dev->dma_buf_size; - else - newDmaBufSize = DMA_STREAMING_SAMPLES * sizeof(u32); - } - else - { - copy_from_user(&newDmaBufSize, (void __user *)arg, sizeof(u32)); - } - if (dev->dma_buf_size > 0 && dev->dma_buf_size != newDmaBufSize) - { - dma_free_coherent(dev->dma_chan->device->dev, dev->dma_buf_size, - dev->dma_buffer, dev->dma_handle); - } - if (newDmaBufSize != dev->dma_buf_size) - { - dev->dma_buf_size = newDmaBufSize; - dev->dma_buffer = - dma_alloc_coherent(dev->dma_chan->device->dev, dev->dma_buf_size, - &dev->dma_handle, GFP_KERNEL); - } - for (i = 0; i < 300; i++) // Just test - ((u32 *)dev->dma_buffer)[i] = 0xFFFFFFFF; - - // printk("DMA BUFFER ADDRESS: %x\n", dev->dma_buffer); - dev->rx_dma_handle = - dma_map_single(dev->dma_chan->device->dev, dev->dma_buffer, - dev->dma_buf_size, DMA_FROM_DEVICE); - return 0; - } - case RPADC_FIFO_AUTO_START_DMA: - { - // Start DMA if DMA buffer previusly allocated - int cyclic; - copy_from_user(&cyclic, (void __user *)arg, sizeof(u32)); - if (dev->dma_buf_size > 0) - { - dev->dma_cookie = - dma_prep_buffer(dev, dev->dma_chan, dev->dma_handle, - dev->dma_buf_size, DMA_DEV_TO_MEM, &dev->dma_cmp); - if (dma_submit_error(dev->dma_cookie)) - { - printk(KERN_ERR "dma_prep_buffer error\n"); - return -EIO; - } - // printk(KERN_INFO "Starting DMA transfers. DMA Buf size = %d\n", - // dev->dma_buf_size); - dma_start_transfer(dev->dma_chan, &dev->dma_cmp, dev->dma_cookie, 0); - dev->dma_started = 1; - dev->dma_cyclic = cyclic; - } - dev->wIdx = 0; - dev->rIdx = 0; - dev->bufCount = 0; - return 0; - } - case RPADC_FIFO_AUTO_STOP_DMA: - { - // dmaengine_terminate_all(dev->dma_chan); - dev->dma_started = 0; - dev->dma_cyclic = 0; - wake_up(&dev->readq); - return 0; - } - case RPADC_FIFO_AUTO_IS_DMA_RUNNING: - { - copy_to_user((void __user *)arg, &dev->dma_started, sizeof(u32)); - return 0; - } - case RPADC_FIFO_AUTO_GET_DMA_BUFLEN: - { - copy_to_user((void __user *)arg, &dev->dma_buf_size, sizeof(u32)); - return 0; - } - case RPADC_FIFO_AUTO_GET_DMA_DATA: - { - copy_to_user((void __user *)arg, dev->dma_buffer, dev->dma_buf_size); - return 0; - } - -#endif // HAS_DMA - - case RPADC_FIFO_AUTO_SET_DRIVER_BUFLEN: - { - if (dev->dma_started) - return 0; - dev->wIdx = 0; - dev->rIdx = 0; - dev->bufCount = 0; - if (dev->bufSize > 0) - kfree(dev->fifoBuffer); - copy_from_user(&dev->bufSize, (void __user *)arg, sizeof(u32)); - dev->fifoBuffer = (u32 *)kmalloc(dev->bufSize * sizeof(u32), GFP_KERNEL); - return 0; - } - case RPADC_FIFO_AUTO_GET_DRIVER_BUFLEN: - { - copy_to_user((void __user *)arg, &dev->bufSize, sizeof(u32)); - return 0; - } - - case RPADC_FIFO_AUTO_GET_COMMAND_REGISTER: - { - copy_to_user((void __user *)arg, dev->iomap_command_register, sizeof(u32)); - return 0; - } - case RPADC_FIFO_AUTO_SET_COMMAND_REGISTER: - { - copy_from_user(dev->iomap_command_register, (void __user *)arg, - sizeof(u32)); - return 0; - } - case RPADC_FIFO_AUTO_GET_DECIMATOR_REGISTER: - { - copy_to_user((void __user *)arg, dev->iomap_decimator_register, - sizeof(u32)); - return 0; - } - case RPADC_FIFO_AUTO_SET_DECIMATOR_REGISTER: - { - copy_from_user(dev->iomap_decimator_register, (void __user *)arg, - sizeof(u32)); - return 0; - } - case RPADC_FIFO_AUTO_GET_MODE_REGISTER: - { - copy_to_user((void __user *)arg, dev->iomap_mode_register, sizeof(u32)); - return 0; - } - case RPADC_FIFO_AUTO_SET_MODE_REGISTER: - { - copy_from_user(dev->iomap_mode_register, (void __user *)arg, sizeof(u32)); - return 0; - } - case RPADC_FIFO_AUTO_GET_PACKETIZER: - { - copy_to_user((void __user *)arg, dev->iomap_packetizer, sizeof(u32)); - return 0; - } - case RPADC_FIFO_AUTO_SET_PACKETIZER: - { - copy_from_user(dev->iomap_packetizer, (void __user *)arg, sizeof(u32)); - return 0; - } - case RPADC_FIFO_AUTO_GET_POST_REGISTER: - { - copy_to_user((void __user *)arg, dev->iomap_post_register, sizeof(u32)); - return 0; - } - case RPADC_FIFO_AUTO_SET_POST_REGISTER: - { - copy_from_user(dev->iomap_post_register, (void __user *)arg, sizeof(u32)); - return 0; - } - case RPADC_FIFO_AUTO_GET_PRE_REGISTER: - { - copy_to_user((void __user *)arg, dev->iomap_pre_register, sizeof(u32)); - return 0; - } - case RPADC_FIFO_AUTO_SET_PRE_REGISTER: - { - copy_from_user(dev->iomap_pre_register, (void __user *)arg, sizeof(u32)); - return 0; - } - case RPADC_FIFO_AUTO_GET_TRIG_EVENT_CODE: - { - copy_to_user((void __user *)arg, dev->iomap_trig_event_code, sizeof(u32)); - return 0; - } - case RPADC_FIFO_AUTO_SET_TRIG_EVENT_CODE: - { - copy_from_user(dev->iomap_trig_event_code, (void __user *)arg, sizeof(u32)); - return 0; - } - case RPADC_FIFO_AUTO_GET_EVENT_CODE: - { - copy_to_user((void __user *)arg, dev->iomap_event_code, sizeof(u32)); - return 0; - } - case RPADC_FIFO_AUTO_SET_EVENT_CODE: - { - copy_from_user(dev->iomap_event_code, (void __user *)arg, sizeof(u32)); - return 0; - } - case RPADC_FIFO_AUTO_GET_DATA_FIFO_LEN: - { - u32 val = readFifo(dev->iomap_data_fifo, RDFO); - copy_to_user((void __user *)arg, &val, sizeof(u32)); - return 0; - } - case RPADC_FIFO_AUTO_GET_DATA_FIFO_VAL: - { - u32 val = readFifo(dev->iomap1_data_fifo, RDFD4); - copy_to_user((void __user *)arg, &val, sizeof(u32)); - return 0; - } - case RPADC_FIFO_AUTO_CLEAR_DATA_FIFO: - { - clearFifo(dev->iomap_data_fifo, dev->iomap1_data_fifo); - return 0; - } - case RPADC_FIFO_AUTO_GET_TIME_FIFO_LEN: - { - u32 val = readFifo(dev->iomap_time_fifo, RDFO); - copy_to_user((void __user *)arg, &val, sizeof(u32)); - return 0; - } - case RPADC_FIFO_AUTO_GET_TIME_FIFO_VAL: - { - u32 val = readFifo(dev->iomap1_time_fifo, RDFD4); - copy_to_user((void __user *)arg, &val, sizeof(u32)); - return 0; - } - case RPADC_FIFO_AUTO_CLEAR_TIME_FIFO: - { - clearFifo(dev->iomap_time_fifo, dev->iomap1_time_fifo); - return 0; - } - case RPADC_FIFO_AUTO_GET_REGISTERS: - { - struct rpadc_fifo_auto_registers currConf; - memset(&currConf, 0, sizeof(currConf)); - currConf.command_register = *((u32 *)dev->iomap_command_register); - currConf.decimator_register = *((u32 *)dev->iomap_decimator_register); - currConf.mode_register = *((u32 *)dev->iomap_mode_register); - currConf.packetizer = *((u32 *)dev->iomap_packetizer); - currConf.post_register = *((u32 *)dev->iomap_post_register); - currConf.pre_register = *((u32 *)dev->iomap_pre_register); - currConf.trig_event_code = *((u32 *)dev->iomap_trig_event_code); - currConf.event_code = *((u32 *)dev->iomap_event_code); - copy_to_user((void __user *)arg, &currConf, sizeof(currConf)); - } - case RPADC_FIFO_AUTO_SET_REGISTERS: - { - struct rpadc_fifo_auto_registers currConf; - copy_from_user(&currConf, (void __user *)arg, sizeof(currConf)); - if (currConf.command_register_enable) - *((u32 *)dev->iomap_command_register) = currConf.command_register; - if (currConf.decimator_register_enable) - *((u32 *)dev->iomap_decimator_register) = currConf.decimator_register; - if (currConf.mode_register_enable) - *((u32 *)dev->iomap_mode_register) = currConf.mode_register; - if (currConf.packetizer_enable) - *((u32 *)dev->iomap_packetizer) = currConf.packetizer; - if (currConf.post_register_enable) - *((u32 *)dev->iomap_post_register) = currConf.post_register; - if (currConf.pre_register_enable) - *((u32 *)dev->iomap_pre_register) = currConf.pre_register; - if (currConf.trig_event_code_enable) - *((u32 *)dev->iomap_trig_event_code) = currConf.trig_event_code; - if (currConf.event_code_enable) - *((u32 *)dev->iomap_event_code) = currConf.event_code; - } - -#ifdef HAS_FIFO_INTERRUPT - - case RPADC_FIFO_AUTO_FIFO_INT_HALF_SIZE: - dev->fifoHalfInterrupt = 1; - // Write(dev->iomap_data_fifo,IER,0x00100000); - return 0; - case RPADC_FIFO_AUTO_FIFO_INT_FIRST_SAMPLE: - dev->fifoHalfInterrupt = 0; - // Write(dev->iomap_data_fifo,IER,0x04000000); - return 0; - case RPADC_FIFO_AUTO_FIFO_FLUSH: - IRQ_cb(0, dev, 0); - // Write(dev->iomap_data_fifo,IER,0x04000000); - case RPADC_FIFO_AUTO_START_READ: - dev->started = 1; - return 0; - case RPADC_FIFO_AUTO_STOP_READ: - dev->started = 0; - IRQ_cb(0, dev, 0); - return 0; - -#endif - - default: - return -EAGAIN; - break; - } - return status; -} - -static unsigned int device_poll(struct file *file, - struct poll_table_struct *p) -{ - unsigned int mask = 0; - struct rpadc_fifo_auto_dev *dev = - (struct rpadc_fifo_auto_dev *)file->private_data; - - down(&dev->sem); - poll_wait(file, &dev->readq, p); - if (dev->bufCount > 0) - mask |= POLLIN | POLLRDNORM; - up(&dev->sem); - return mask; -} - -//////////////////////////////////////////////////////////////////////////////// -// PROBE MANAGEMENT/////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////// - -static int id_major; -static struct class *rpadc_fifo_auto_class; -static struct rpadc_fifo_auto_dev staticPrivateInfo; - -#ifdef HAS_FIFO_INTERRUPT -static void setIrq(struct platform_device *pdev) -{ - staticPrivateInfo.irq = platform_get_irq(pdev, 0); - printk(KERN_DEBUG "IRQ: %x\n", staticPrivateInfo.irq); - int res = request_irq(staticPrivateInfo.irq, IRQ_cb, IRQF_TRIGGER_RISING, - "rpadc_fifo_auto", &staticPrivateInfo); - if (res) - printk(KERN_INFO "rpadc_fifo_auto: can't get IRQ %d assigned\n", - staticPrivateInfo.irq); - else - printk(KERN_INFO "rpadc_fifo_auto: got IRQ %d assigned\n", - staticPrivateInfo.irq); -} -#endif - -static int rpadc_fifo_auto_probe(struct platform_device *pdev) -{ - int i; - u32 off; - static int memIdx; - struct resource *r_mem; - struct device *dev = &pdev->dev; - - // s_pdev = pdev; - printk("rpadc_fifo_auto_probe %s\n", pdev->name); - - // CHAR DEV // - if (!deviceAllocated) - { - deviceAllocated = 1; - memIdx = 0; - printk("registering char dev %s ...\n", pdev->name); - printk("PLATFORM DEVICE PROBE...%x\n", &staticPrivateInfo); - - int err, devno; - dev_t newDev; - err = alloc_chrdev_region(&newDev, 0, 1, DEVICE_NAME); - id_major = MAJOR(newDev); - printk("MAJOR ID...%d\n", id_major); - if (err < 0) - { - printk("alloc_chrdev_region failed\n"); - return err; - } - cdev_init(&staticPrivateInfo.cdev, &fops); - staticPrivateInfo.cdev.owner = THIS_MODULE; - staticPrivateInfo.cdev.ops = &fops; - devno = MKDEV(id_major, 0); // Minor Id is 0 - err = cdev_add(&staticPrivateInfo.cdev, devno, 1); - if (err < 0) - { - printk("cdev_add failed\n"); - return err; - } - staticPrivateInfo.pdev = pdev; - - printk(KERN_NOTICE "mknod /dev/%s c %d 0\n", DEVICE_NAME, id_major); - - rpadc_fifo_auto_class = class_create(THIS_MODULE, DEVICE_NAME); - if (IS_ERR(rpadc_fifo_auto_class)) - return PTR_ERR(rpadc_fifo_auto_class); - - device_create(rpadc_fifo_auto_class, NULL, MKDEV(id_major, 0), NULL, - DEVICE_NAME); - - // Initialize semaphores and queues - sema_init(&staticPrivateInfo.sem, 1); - spin_lock_init(&staticPrivateInfo.spinLock); - init_waitqueue_head(&staticPrivateInfo.readq); - staticPrivateInfo.bufCount = 0; - staticPrivateInfo.rIdx = 0; - staticPrivateInfo.wIdx = 0; - staticPrivateInfo.bufSize = 0; -#ifdef HAS_DMA - staticPrivateInfo.dma_buf_size = 0; - staticPrivateInfo.dma_chan = NULL; - // Declare DMA Channel - staticPrivateInfo.dma_chan = dma_request_slave_channel(&pdev->dev, "dma0"); - if (IS_ERR(staticPrivateInfo.dma_chan)) - { - pr_err("xilinx_dmatest: No Tx channel\n"); - dma_release_channel(staticPrivateInfo.dma_chan); - return -EFAULT; - } -#endif // HAS_DMA - r_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - off = r_mem->start & ~PAGE_MASK; - staticPrivateInfo.iomap_command_register = - devm_ioremap(&pdev->dev, r_mem->start + off, 0xffff); - } - else // Further calls for memory resources - { - // printk("SUCCESSIVA CHIAMATA A rfx_rpadc_fifo_auto_probe: %s, memIdx: - // %d\n", pdev->name, memIdx); r_mem = platform_get_resource(pdev, - // IORESOURCE_MEM, 0); off = r_mem->start & ~PAGE_MASK; - switch (memIdx) - { - - case 0: - r_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - off = r_mem->start & ~PAGE_MASK; - staticPrivateInfo.iomap_data_fifo = - devm_ioremap(&pdev->dev, r_mem->start + off, 0xffff); - r_mem = platform_get_resource(pdev, IORESOURCE_MEM, 1); - off = r_mem->start & ~PAGE_MASK; - staticPrivateInfo.iomap1_data_fifo = - devm_ioremap(&pdev->dev, r_mem->start + off, 0xffff); - setIrq(pdev); - break; - case 1: - r_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - off = r_mem->start & ~PAGE_MASK; - staticPrivateInfo.iomap_decimator_register = - devm_ioremap(&pdev->dev, r_mem->start + off, 0xffff); - break; - case 2: - r_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - off = r_mem->start & ~PAGE_MASK; - staticPrivateInfo.iomap_event_code = - devm_ioremap(&pdev->dev, r_mem->start + off, 0xffff); - break; - case 3: - r_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - off = r_mem->start & ~PAGE_MASK; - staticPrivateInfo.iomap_mode_register = - devm_ioremap(&pdev->dev, r_mem->start + off, 0xffff); - break; - case 4: - r_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - off = r_mem->start & ~PAGE_MASK; - staticPrivateInfo.iomap_packetizer = - devm_ioremap(&pdev->dev, r_mem->start + off, 0xffff); - break; - case 5: - r_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - off = r_mem->start & ~PAGE_MASK; - staticPrivateInfo.iomap_post_register = - devm_ioremap(&pdev->dev, r_mem->start + off, 0xffff); - break; - case 6: - r_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - off = r_mem->start & ~PAGE_MASK; - staticPrivateInfo.iomap_pre_register = - devm_ioremap(&pdev->dev, r_mem->start + off, 0xffff); - break; - case 7: - r_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - off = r_mem->start & ~PAGE_MASK; - staticPrivateInfo.iomap_time_fifo = - devm_ioremap(&pdev->dev, r_mem->start + off, 0xffff); - r_mem = platform_get_resource(pdev, IORESOURCE_MEM, 1); - off = r_mem->start & ~PAGE_MASK; - staticPrivateInfo.iomap1_time_fifo = - devm_ioremap(&pdev->dev, r_mem->start + off, 0xffff); - break; - case 8: - r_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - off = r_mem->start & ~PAGE_MASK; - staticPrivateInfo.iomap_trig_event_code = - devm_ioremap(&pdev->dev, r_mem->start + off, 0xffff); - break; - - default: - printk("ERROR: Unexpected rpadc_fifo_auto_probe call\n"); - } - memIdx++; - printk(KERN_DEBUG "mem start: %x\n", r_mem->start); - printk(KERN_DEBUG "mem end: %x\n", r_mem->end); - printk(KERN_DEBUG "mem offset: %x\n", r_mem->start & ~PAGE_MASK); - } - return 0; -} - -static int rpadc_fifo_auto_remove(struct platform_device *pdev) -{ - printk("PLATFORM DEVICE REMOVE...\n"); - if (rpadc_fifo_auto_class) - { - device_destroy(rpadc_fifo_auto_class, MKDEV(id_major, 0)); - class_destroy(rpadc_fifo_auto_class); - } -#ifdef HAS_DMA - printk("PLATFORM DEVICE REMOVE dma_release_channel...%x \n", - staticPrivateInfo.dma_chan); - if (staticPrivateInfo.dma_chan) - dma_release_channel(staticPrivateInfo.dma_chan); -#endif // HAS_DMA - cdev_del(&staticPrivateInfo.cdev); - return 0; -} - -static const struct of_device_id rpadc_fifo_auto_of_ids[] = { - { - .compatible = "xlnx,axi-dma-test-1.00.a", - }, - { - .compatible = "xlnx,axi-cfg-register-1.0", - }, - { - .compatible = "xlnx,axi-sts-register-1.0", - }, - { - .compatible = "xlnx,axi-fifo-mm-s-4.1", - }, - {}}; - -static struct platform_driver rpadc_fifo_auto_driver = { - .driver = - { - .name = MODULE_NAME, - .owner = THIS_MODULE, - .of_match_table = rpadc_fifo_auto_of_ids, - }, - .probe = rpadc_fifo_auto_probe, - .remove = rpadc_fifo_auto_remove, -}; - -static int __init rpadc_fifo_auto_init(void) -{ - printk(KERN_INFO "inizializing AXI module ...\n"); - deviceAllocated = 0; - return platform_driver_register(&rpadc_fifo_auto_driver); -} - -static void __exit rpadc_fifo_auto_exit(void) -{ - printk(KERN_INFO "exiting AXI module ...\n"); - platform_driver_unregister(&rpadc_fifo_auto_driver); -} - -module_init(rpadc_fifo_auto_init); -module_exit(rpadc_fifo_auto_exit); -MODULE_LICENSE("GPL"); diff --git a/device_support/redpitaya/rpadc_fifo_auto.ko b/device_support/redpitaya/rpadc_fifo_auto.ko deleted file mode 100644 index 556f5f6659..0000000000 Binary files a/device_support/redpitaya/rpadc_fifo_auto.ko and /dev/null differ diff --git a/device_support/redpitaya/sync_clock.c b/device_support/redpitaya/sync_clock.c new file mode 100644 index 0000000000..8f430e0396 --- /dev/null +++ b/device_support/redpitaya/sync_clock.c @@ -0,0 +1,303 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define COUNT_SIZE 2000000 +int checkUpdateFreq(int fd); +void alignFreq(int fd, int iterations); +void alignClock(int fd); +#ifdef CXX +extern "C" { +#endif +void alignFreq(int fd, int iterations); +#ifdef CXX +} +#endif + +static void setFrequency(int fd, double reqFreq) +{ + double reqT, K, step; + unsigned int Kr, C, stepLo, stepHi, reg, K1, K2; + unsigned long long stepR; + + reqT = 1./reqFreq; + K = 0.25E7 * 25. /reqFreq; //125MHz clock +// K = 1E7 * 25. /reqFreq; + Kr = round(K); + if (Kr > K) + { + C = round(COUNT_SIZE*(1 - (Kr -K))); + K1 = Kr; + K2 = Kr - 1; + } + else if (Kr < K) + { + C = round(COUNT_SIZE*(1- (K - Kr))); + K1 = Kr; + K2 = Kr+1; + } + else + { + K1 = K2 = K; + C = COUNT_SIZE/2; + } + step = C/(double)COUNT_SIZE; + step *= pow(2, 44); + stepR = round(step); + stepLo = (unsigned int)(stepR & 0xFFFFFFFF); + stepHi = (unsigned int)((stepR >> 32) & 0xFFFFFFFF); + printf("K1: %d, K2: %d, C: %u\n", K1, K2, C); + ioctl(fd, RFX_STREAM_SET_K1_REG, &K1); + + ioctl(fd, RFX_STREAM_SET_K2_REG, &K2); + ioctl(fd, RFX_STREAM_GET_K1_REG, &K1); + + ioctl(fd, RFX_STREAM_GET_K2_REG, &K2); + printf("K1: %d, K2: %d\n", K1, K2); + + ioctl(fd, RFX_STREAM_SET_STEP_LO_REG, &stepLo); + + ioctl(fd, RFX_STREAM_SET_STEP_HI_REG, &stepHi); + + reg = 0; + ioctl(fd, RFX_STREAM_SET_TIME_COMMAND_REG, ®); + usleep(1000); + reg = 1; + ioctl(fd, RFX_STREAM_SET_TIME_COMMAND_REG, ®); + reg = 0; + ioctl(fd, RFX_STREAM_SET_TIME_COMMAND_REG, ®); +} + + + + +static unsigned long long getTime(int fd, double actFrequency) +{ + unsigned int reg, lo, hi = 0, rb, len; + unsigned long long time; + static unsigned long prevCount = 0; + ioctl(fd, RFX_STREAM_CLEAR_SYNC_FIFO, 0); + reg = 0; + ioctl(fd, RFX_STREAM_SET_TIME_COMMAND_REG, ®); + reg = 2; + ioctl(fd, RFX_STREAM_SET_TIME_COMMAND_REG, ®); + reg = 0; + ioctl(fd, RFX_STREAM_SET_TIME_COMMAND_REG, ®); + len = -1; + usleep(10); + ioctl(fd, RFX_STREAM_GET_SYNC_FIFO_LEN, &len); + if(len != 2) + printf("\n\nERRORE ERRORRISSIMO %d\n\n\n", len); + ioctl(fd, RFX_STREAM_GET_SYNC_FIFO_VAL, &lo); + ioctl(fd, RFX_STREAM_GET_SYNC_FIFO_VAL, &hi); + + + + time = hi; + time = (time << 32) | lo; + prevCount = lo; + + time = round(1E6 * (double)time/actFrequency); + return time; +} + +static void setTime(int fd, unsigned long long timeUs, double actFreq) +{ + unsigned long long fpgaTime, ofsTime, prevOfsTime; + unsigned int reg = 0, reg1 = 0, reg2 = 0; + + + //Reset offset register + reg = 0; + ioctl(fd, RFX_STREAM_SET_TIME_OFFSET_HI_REG, ®); + ioctl(fd, RFX_STREAM_SET_TIME_OFFSET_LO_REG, ®); + + fpgaTime = getTime(fd, actFreq); + ofsTime = round((timeUs - fpgaTime)*actFreq / 1E6); + reg = ofsTime & 0x00000000FFFFFFFFL; + ioctl(fd, RFX_STREAM_SET_TIME_OFFSET_LO_REG, ®); + reg = (ofsTime >> 32) & 0x00000000FFFFFFFFL; + ioctl(fd, RFX_STREAM_SET_TIME_OFFSET_HI_REG, ®); + + ioctl(fd, RFX_STREAM_GET_TIME_OFFSET_LO_REG, ®1); + ioctl(fd, RFX_STREAM_GET_TIME_OFFSET_HI_REG, ®2); + + + +} + +static int updateFreq(int fd, unsigned long long *prevTimeUs, unsigned long long *prevFpgaTimeUs, double kp, double ki, double *prevFreq, double actFreq) +{ + struct timeval currTime; + unsigned long long timeUs, fpgaTimeUs; + double steps; + long long stepErr, totErr, elapsedSteps, elapsedStepsFpga; + double newFreq = *prevFreq; + gettimeofday(&currTime, NULL); + timeUs = (unsigned long long)currTime.tv_sec * 1000000L + currTime.tv_usec; + fpgaTimeUs = getTime(fd, actFreq); + totErr = fpgaTimeUs - timeUs; + + if(*prevTimeUs) //The first time only measurements performed, no correction + { + elapsedSteps = timeUs - *prevTimeUs; + elapsedStepsFpga = fpgaTimeUs - *prevFpgaTimeUs; + stepErr = elapsedStepsFpga - elapsedSteps; + + steps = kp*(double)stepErr + ki *(double) totErr; + //printf("STEPS: %e\n", steps); + //printf("ELAPSED STEP FPGA: %llu\tELAPSET STEPS: %llu\n", elapsedStepsFpga, elapsedSteps); + newFreq = 1./(1./ *prevFreq + (steps * 16 * 1E-9)/(2*1E6)); //Attuale cvonteggio fpga + printf("Step Err: %lld\t Tot err: %lld\tSteps: %d\n", stepErr, totErr, (int)steps); + setFrequency(fd, actFreq * newFreq/1E6); + } + *prevTimeUs = timeUs; + *prevFpgaTimeUs = fpgaTimeUs; + *prevFreq = newFreq; + return 0; +} + + +static int openChecked() +{ + int fd; + fd = open("/dev/rfx_stream", O_RDWR | O_SYNC); + while(fd < 0) + { + sleep(1); + fd = open("/dev/rfx_stream", O_RDWR | O_SYNC); + } + return fd; +} + + + static double getFrequency(int fd) +{ + double K, step, periodFPGA, period; + unsigned int Kr, C, stepLo, stepHi, reg, K1, K2; + unsigned long long stepR; + ioctl(fd, RFX_STREAM_GET_K1_REG, &K1); + + ioctl(fd, RFX_STREAM_GET_K2_REG, &K2); + + ioctl(fd, RFX_STREAM_GET_STEP_LO_REG, &stepLo); + + ioctl(fd, RFX_STREAM_GET_STEP_HI_REG, &stepHi); + + stepR = stepHi; + stepR = (stepR << 32)|stepLo; + step = (double)stepR/pow(2, 44); + + periodFPGA = 1./125E6; + period = (periodFPGA * K1)*step + (periodFPGA * K2)*(1.-step); + return 0.5/period; +} + + +///////////////////////////////////To be called by device +static double prevFreq = 1E6; +static unsigned long long prevTimeUs = 0; +static unsigned long long prevFpgaTimeUs = 0; + + +int main(int argc, char *argv[]) +{ + int i; + int fd; + volatile unsigned int reg; + + unsigned long long step, timeUs, fpgaTimeUs; + struct timeval currTime; + unsigned long long prevTimeUs; + unsigned long long prevFpgaTimeUs; + double prevFreq ; + double targetFreq = 1E6; + + fd = openChecked(); + printf("FD: %d\n", fd); + printf("ALIGN FREQUENCY\n"); + prevFreq = 1E6; + prevTimeUs = 0; + prevFpgaTimeUs = 0; + alignFreq(fd, 60); + printf("ALIGNED\n"); + alignClock(fd); + //close(fd); + while(1) + { + checkUpdateFreq(fd); + sleep(1); + } + + return 0; +} + +static double prevTimeS = 0; +#define UPDATE_SECS 1 + +void alignFreq(int fd, int iterations) +{ + int i; + double targetFreq = 1E6; + struct timeval currTime; + unsigned long long timeUs, fpgaTimeUs; + setFrequency(fd, targetFreq); + gettimeofday(&currTime, NULL); + timeUs = (unsigned long long)currTime.tv_sec * 1000000L + currTime.tv_usec; + setTime(fd, timeUs, targetFreq); + gettimeofday(&currTime, NULL); + timeUs = (unsigned long long)currTime.tv_sec * 1000000L + currTime.tv_usec; + fpgaTimeUs = getTime(fd,targetFreq); + prevFreq = 1E6; + prevFpgaTimeUs = timeUs; + prevTimeUs = 0; + for(i = 0; i < iterations; i++) + { + sleep(1); + + updateFreq(fd, &prevTimeUs, &prevFpgaTimeUs, 10., 0,&prevFreq, targetFreq); + } +} + + + +int checkUpdateFreq(int fd) +{ + unsigned long long timeS; + struct timeval currTime; + double targetFreq = 1E6; + int status; + //int fd = openChecked(); + gettimeofday(&currTime, NULL); + timeS = (unsigned long long)currTime.tv_sec; + if((timeS - prevTimeS) > UPDATE_SECS) + { + prevTimeS = timeS; + prevFreq = getFrequency(fd); + status = updateFreq(fd, &prevTimeUs, &prevFpgaTimeUs, 6., 5.,&prevFreq, targetFreq); + printf("******PREV FREQ: %f %f\n", prevFreq, getFrequency(fd)); + if(status) return status; + } + // close(fd); + return 0; +} + +void alignClock(int fd) +{ + unsigned long long timeUs; + double targetFreq = 1E6; + struct timeval currTime; + gettimeofday(&currTime, NULL); + timeUs = (unsigned long long)currTime.tv_sec * 1000000L + currTime.tv_usec; + setTime(fd, timeUs, targetFreq); + prevFpgaTimeUs = prevTimeUs = 0; +} diff --git a/java/jdevices/src/main/java/RFX_RPADCSetup.java b/java/jdevices/src/main/java/RFX_RPADCSetup.java index b19b33ef14..6b0db7d65a 100644 --- a/java/jdevices/src/main/java/RFX_RPADCSetup.java +++ b/java/jdevices/src/main/java/RFX_RPADCSetup.java @@ -58,7 +58,7 @@ private void initComponents() { jPanel5 = new javax.swing.JPanel(); deviceField5 = new DeviceField(); - setDeviceProvider("spilds.rfx.local:8100"); + setDeviceProvider("ropc1.rfx.local:8100"); setDeviceTitle("RedPitaya ADC"); setDeviceType("RFX_RPADC"); setHeight(300); @@ -112,7 +112,7 @@ private void initComponents() { jPanel1.add(jPanel4); - deviceChoice4.setChoiceItems(new String[] {"INTERNAL", "TRIG_EXTERNAL", "EXTERNAL", "HIGHWAY"}); + deviceChoice4.setChoiceItems(new String[] {"INTERNAL", "EXTERNAL", "SYNC", "TRIG_EXTERNAL", "TRIG_SYNC"}); deviceChoice4.setIdentifier(""); deviceChoice4.setLabelString("Clock Mode:"); deviceChoice4.setOffsetNid(14); @@ -158,9 +158,9 @@ private void initComponents() { jPanel8.add(deviceField6); deviceField3.setIdentifier(""); - deviceField3.setLabelString("Timing Highway event code: "); - deviceField3.setNumCols(4); - deviceField3.setOffsetNid(23); + deviceField3.setLabelString("Dead time: "); + deviceField3.setNumCols(8); + deviceField3.setOffsetNid(34); jPanel8.add(deviceField3); jPanel1.add(jPanel8); diff --git a/java/jdevices/src/main/resources/RFX_RPADCSetup.form b/java/jdevices/src/main/resources/RFX_RPADCSetup.form index e0a29a5001..66722a6802 100644 --- a/java/jdevices/src/main/resources/RFX_RPADCSetup.form +++ b/java/jdevices/src/main/resources/RFX_RPADCSetup.form @@ -2,7 +2,7 @@
- + @@ -140,11 +140,12 @@ - + - - - + + + + @@ -214,9 +215,9 @@ - - - + + + diff --git a/pydevices/RfxDevices/RFX_RPADC.py b/pydevices/RfxDevices/RFX_RPADC.py index e0efdee3a6..b00e491ba3 100644 --- a/pydevices/RfxDevices/RFX_RPADC.py +++ b/pydevices/RfxDevices/RFX_RPADC.py @@ -52,7 +52,10 @@ class RFX_RPADC(Device): {'path': ':STOP_ACTION', 'type': 'action', 'valueExpr': "Action(Dispatch('PXI_SERVER','FINISH_SHOT',50,None),Method(None,'stop_store',head))", 'options': ('no_write_shot',)}, - {'path': ':START_TIME', 'type': 'numeric', 'value': 0}] + {'path': ':START_TIME', 'type': 'numeric', 'value': 0}, + {'path': ':ABS_TRIGGER', 'type': 'numeric', 'value': 0}, + {'path': ':DEAD_TIME', 'type': 'numeric', 'value': 1E-3} + ] class TriggerEvent(Event): def __init__(self, evName, device): @@ -64,7 +67,7 @@ def run(self): class Configuration: def configure(self, lib, fd, name, shot, chanANid, chanBNid, triggerNid, startTimeNid, preSamples, - postSamples, segmentSamples, frequency, frequency1, single): + postSamples, segmentSamples, frequency, frequency1, single, absTriggerTimeFromFPGA, absTriggerNid): self.lib = lib self.fd = fd self.name = name @@ -79,6 +82,8 @@ def configure(self, lib, fd, name, shot, chanANid, chanBNid, triggerNid, startTi self.frequency = frequency self.frequency1 = frequency1 self.single = single + self.absTriggerTimeFromFPGA = absTriggerTimeFromFPGA + self.absTriggerNid = absTriggerNid class AsynchStore(Thread): def configure(self, conf): @@ -96,16 +101,16 @@ def configure(self, conf): self.frequency = conf.frequency self.frequency1 = conf.frequency1 self.single = conf.single + self.absTriggerTimeFromFPGA = conf.absTriggerTimeFromFPGA + self.absTriggerNid = conf.absTriggerNid def run(self): print('START THREAD', self.name, self.shot) try: - self.lib.rpadcStream( - c_int(self.fd), c_char_p(self.name), c_int( - self.shot), c_int(self.chanANid), c_int(self.chanBNid), - c_int(self.triggerNid), c_int( - self.preSamples), c_int(self.postSamples), - c_int(self.segmentSamples), c_double(self.frequency), c_double(self.frequency1), c_int(self.single)) + self.lib.rpadcStream( + c_int(self.fd), c_char_p(self.name), c_int(self.shot), c_int(self.chanANid), c_int(self.chanBNid), + c_int(self.triggerNid), c_int(self.preSamples), c_int(self.postSamples), + c_int(self.segmentSamples), c_double(self.frequency), c_double(self.frequency1), c_int(self.single), c_int(self.absTriggerTimeFromFPGA), c_int(self.absTriggerNid)) except ValueError as e: print(e) raise mdsExceptions.TclFAILED_ESSENTIAL @@ -141,8 +146,8 @@ def init(self): isSingle = 1 else: isSingle = 0 - clockModeDict = {'INTERNAL': 0, 'TRIG_EXTERNAL': 1, - 'EXTERNAL': 2, 'TRIG_EVENT': 3, 'EXT_EVENT': 4, 'HIGHWAY': 5} + clockModeDict = {'INTERNAL': 0, 'TRIG_EXTERNAL': 1, 'TRIG_SYNC': 2, + 'EXTERNAL': 3, 'SYNC': 4} print('CLOCK MODE XXX') print(self.clock_mode.data()) print('ccc') @@ -152,6 +157,10 @@ def init(self): except: print('Invalid clock mode: ' + self.clock_mode.data()) raise mdsExceptions.TclFAILED_ESSENTIAL + if clockMode == 4 or clockMode == 2: + absTriggerTimeFromFPGA = 1 + else: + absTriggerTimeFromFPGA = 0 print(self.mode.data) if self.mode.data() == 'STREAMING': preSamples = 0 @@ -185,39 +194,42 @@ def init(self): raise mdsExceptions.TclFAILED_ESSENTIAL if self.clock_mode.data() != 'INTERNAL': try: - if self.clock_mode.data() == 'HIGHWAY': - period = 1E-6 * decimation - else: + if self.clock_mode.data() == 'TRIG_SYNC': + frequency1 = 1E6 + frequency = 125E6/decimation + elif self.clock_mode.data() == 'SYNC': + frequency = 1E6 / decimation + frequency1 = 1E6 + elif self.clock_mode.data() == 'TRIG_EXTERNAL': + period = Data.execute( + 'slope_of($)', self.ext_clock) + frequency1 = 1./period + frequency = 125E6 / decimation + else: #EXTERNAL period = Data.execute( - 'slope_of($)', self.ext_clock) * decimation - frequency = 1./period - if self.clock_mode.data() == 'EXTERNAL' or self.clock_mode.data() == 'HIGHWAY': - frequency1 = frequency + 'slope_of($)', self.ext_clock) + frequency1 = 1./period + frequency = frequency1 / decimation except: print('Cannot resolve external clock') raise mdsExceptions.TclFAILED_ESSENTIAL segSize = self.seg_size.data() - print('HIGHWAY') - if self.clock_mode.data() == 'HIGHWAY': - try: - event_code = self.event_code.data() - except: - print('Cannot resolve event code') - raise mdsExceptions.TclFAILED_ESSENTIAL - else: - event_code = 0 - + try: + deadTime = self.dead_time.data() + deadTime = int(deadTime * frequency) + except: + print('Cannot resolve dead time') + raise mdsExceptions.TclFAILED_ESSENTIAL print('opening device') self.fd = self.lib.rpadcInit(c_int(mode), c_int(clockMode), c_int(preSamples), c_int(postSamples), c_int(trigFromChanA), - c_int(trigAboveThreshold), c_int(evLevel), c_int(evSamples), c_int(decimation), c_int(event_code)) + c_int(trigAboveThreshold), c_int(evLevel), c_int(evSamples), c_int(decimation), c_int(deadTime)) if self.fd < 0: print("Error opening device") raise mdsExceptions.TclFAILED_ESSENTIAL print('device opened') self.conf.configure(self.lib, self.fd, self.getTree().name, self.getTree().shot, self.raw_a.getNid(), self.raw_b.getNid(), - self.trigger.getNid(), self.start_time.getNid( - ), preSamples, postSamples, segSize, frequency, - frequency1, isSingle) + self.trigger.getNid(), self.start_time.getNid(), preSamples, postSamples, segSize, frequency, + frequency1, isSingle, absTriggerTimeFromFPGA, self.abs_trigger.getNid()) print('configured') aChan = self.getTree().tdiCompile( '($1*$2/8192.)*$3 + $4', self.raw_a, self.range_a, self.gain_a, self.offset_a) @@ -229,7 +241,8 @@ def init(self): self.chan_b.putData(self.getTree().tdiCompile( '($1*$2/8192.)*$3 + $4', self.raw_b, self.range_b, self.gain_b, self.offset_b)) print('scritto') - except: + except Exception as e: + print(str(e)) raise mdsExceptions.TclFAILED_ESSENTIAL def start_store(self):