diff --git a/deploy/packaging/debian/idl.noarch b/deploy/packaging/debian/idl.noarch index b23bd0ca37..68c0aec910 100644 --- a/deploy/packaging/debian/idl.noarch +++ b/deploy/packaging/debian/idl.noarch @@ -26,6 +26,7 @@ ./usr/local/mdsplus/idl/cw_wvedit.pro ./usr/local/mdsplus/idl/dsql.pro ./usr/local/mdsplus/idl/evaluate.pro +./usr/local/mdsplus/idl/mds_keyword_set.pro ./usr/local/mdsplus/idl/mdscheckarg.pro ./usr/local/mdsplus/idl/mdsclose.pro ./usr/local/mdsplus/idl/mdsconnect.pro @@ -36,7 +37,6 @@ ./usr/local/mdsplus/idl/mdsevent.pro ./usr/local/mdsplus/idl/mdsgetmsg.pro ./usr/local/mdsplus/idl/mdsidlimage.pro -./usr/local/mdsplus/idl/mds_keyword_set.pro ./usr/local/mdsplus/idl/mdsisclient.pro ./usr/local/mdsplus/idl/mdslogin.pro ./usr/local/mdsplus/idl/mdsopen.pro diff --git a/deploy/packaging/debian/rfxdevices.noarch b/deploy/packaging/debian/rfxdevices.noarch index 034b61fb58..002f32e131 100644 --- a/deploy/packaging/debian/rfxdevices.noarch +++ b/deploy/packaging/debian/rfxdevices.noarch @@ -122,6 +122,7 @@ ./usr/local/mdsplus/pydevices/RfxDevices/RFX_RPADC.py ./usr/local/mdsplus/pydevices/RfxDevices/RFX_RPADC_SERIAL.py ./usr/local/mdsplus/pydevices/RfxDevices/RFX_RPDAC.py +./usr/local/mdsplus/pydevices/RfxDevices/RFX_TRIGUART.py ./usr/local/mdsplus/pydevices/RfxDevices/RGA.py ./usr/local/mdsplus/pydevices/RfxDevices/SIG_SNAPSHOT.py ./usr/local/mdsplus/pydevices/RfxDevices/SIS3820.py diff --git a/deploy/packaging/redhat/idl.noarch b/deploy/packaging/redhat/idl.noarch index 9d983c07fa..f21ddbdb29 100644 --- a/deploy/packaging/redhat/idl.noarch +++ b/deploy/packaging/redhat/idl.noarch @@ -29,6 +29,7 @@ ./usr/local/mdsplus/idl/cw_wvedit.pro ./usr/local/mdsplus/idl/dsql.pro ./usr/local/mdsplus/idl/evaluate.pro +./usr/local/mdsplus/idl/mds_keyword_set.pro ./usr/local/mdsplus/idl/mdscheckarg.pro ./usr/local/mdsplus/idl/mdsclose.pro ./usr/local/mdsplus/idl/mdsconnect.pro @@ -40,7 +41,6 @@ ./usr/local/mdsplus/idl/mdsgetmsg.pro ./usr/local/mdsplus/idl/mdsidlimage.pro ./usr/local/mdsplus/idl/mdsisclient.pro -./usr/local/mdsplus/idl/mds_keyword_set.pro ./usr/local/mdsplus/idl/mdslogin.pro ./usr/local/mdsplus/idl/mdsopen.pro ./usr/local/mdsplus/idl/mdsput.pro diff --git a/deploy/packaging/redhat/rfxdevices.noarch b/deploy/packaging/redhat/rfxdevices.noarch index 746e117535..e114a6eedf 100644 --- a/deploy/packaging/redhat/rfxdevices.noarch +++ b/deploy/packaging/redhat/rfxdevices.noarch @@ -123,6 +123,7 @@ ./usr/local/mdsplus/pydevices/RfxDevices/RFX_RPADC.py ./usr/local/mdsplus/pydevices/RfxDevices/RFX_RPADC_SERIAL.py ./usr/local/mdsplus/pydevices/RfxDevices/RFX_RPDAC.py +./usr/local/mdsplus/pydevices/RfxDevices/RFX_TRIGUART.py ./usr/local/mdsplus/pydevices/RfxDevices/RGA.py ./usr/local/mdsplus/pydevices/RfxDevices/SIG_SNAPSHOT.py ./usr/local/mdsplus/pydevices/RfxDevices/SIS3820.py diff --git a/device_support/redpitaya/AsyncStoreManager.cpp b/device_support/redpitaya/AsyncStoreManager.cpp index badd97906f..79efd06c47 100644 --- a/device_support/redpitaya/AsyncStoreManager.cpp +++ b/device_support/redpitaya/AsyncStoreManager.cpp @@ -3,10 +3,10 @@ pthread_mutex_t globalMutex = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_t segmentMutex = PTHREAD_MUTEX_INITIALIZER; -SaveItem::SaveItem(short *buffer, int segmentSamples, MDSplus::TreeNode *dataNode, +SaveItem::SaveItem(short *buffer, int segmentSamples, MDSplus::TreeNode *dataNode,MDSplus::TreeNode *trigRecvNode, MDSplus::Data *triggerTime, void *treePtr, double *startTimes, double *endTimes, double freq, int blocksInSegment, - MDSplus::TreeNode *resampledNode) + char *trigReceived, MDSplus::TreeNode *resampledNode) { this->buffer = buffer; this->segmentSamples = segmentSamples; @@ -23,11 +23,14 @@ SaveItem::SaveItem(short *buffer, int segmentSamples, MDSplus::TreeNode *dataNod } this->freq = freq; this->resampledNode = resampledNode; + this->trigReceived = trigReceived; + this->trigRecvNode = trigRecvNode; nxt = 0; } void SaveItem::save() { + MDSplus::Array *chanData = new MDSplus::Int16Array(buffer, segmentSamples); @@ -63,10 +66,28 @@ void SaveItem::save() std::cout << "MAKE SEGMENT SAMPLES:" << segmentSamples << std::endl; dataNode->makeSegment(startSegData, endSegData, timebase, chanData); } - catch (const MDSplus::MdsException &exc) + catch (MDSplus::MdsException &exc) { std::cout << "Error writing segment: " << exc.what() << std::endl; } + + + if(trigRecvNode) + { + MDSplus::Float64Array *trigFlagTimes = new MDSplus::Float64Array(startTimes, blocksInSegment); + MDSplus::Int8Array *trigFlags = new MDSplus::Int8Array(trigReceived, blocksInSegment); + + std::cout << "MAKE SEGMENT FLAGS:" << std::endl; + + trigRecvNode->makeSegment(startSegData, endSegData, trigFlagTimes, trigFlags); + MDSplus::deleteData(trigFlagTimes); + MDSplus::deleteData(trigFlags); + } + + + + + MDSplus::deleteData(chanData); MDSplus::deleteData(timebase); MDSplus::deleteData(startData); @@ -76,8 +97,15 @@ void SaveItem::save() delete[] buffer; delete[] startTimes; delete[] endTimes; + + } + + + + + SaveList::SaveList() { int status = pthread_mutex_init(&mutex, NULL); @@ -87,14 +115,14 @@ SaveList::SaveList() threadCreated = false; } -void SaveList::addItem(short *buffer, int segmentSamples, MDSplus::TreeNode *dataNode, +void SaveList::addItem(short *buffer, int segmentSamples, MDSplus::TreeNode *dataNode,MDSplus::TreeNode *trigRecvNode, MDSplus::Data *triggerTime, void *treePtr, double *startTimes, double *endTimes, double freq, int blocksInSegment, - MDSplus::TreeNode *resampledNode) + char *trigReceived, MDSplus::TreeNode *resampledNode) { SaveItem *newItem = new SaveItem( - buffer, segmentSamples, dataNode, triggerTime, treePtr, startTimes, endTimes, freq, blocksInSegment, resampledNode); + buffer, segmentSamples, dataNode, trigRecvNode, triggerTime, treePtr, startTimes, endTimes, freq, blocksInSegment, trigReceived, resampledNode); pthread_mutex_lock(&mutex); if (saveHead == NULL) diff --git a/device_support/redpitaya/AsyncStoreManager.h b/device_support/redpitaya/AsyncStoreManager.h index 529912d3ee..36f56f1b95 100644 --- a/device_support/redpitaya/AsyncStoreManager.h +++ b/device_support/redpitaya/AsyncStoreManager.h @@ -22,16 +22,18 @@ class SaveItem SaveItem *nxt; MDSplus::Data *triggerTime; MDSplus::TreeNode *dataNode; + MDSplus::TreeNode *trigRecvNode; MDSplus::TreeNode *resampledNode; double *startTimes, *endTimes; double freq; int blocksInSegment; + char *trigReceived; public: - SaveItem(short *buffer, int segmentSamples, MDSplus::TreeNode *dataNode, + SaveItem(short *buffer, int segmentSamples, MDSplus::TreeNode *dataNode, MDSplus::TreeNode *trigRecvNode, MDSplus::Data *triggerTime, void *treePtr, - double *startTimes, double *endTimes, double freq, int blocksInSegment, + double *startTimes, double *endTimes, double freq, int blocksInSegment, char *trigReceived, MDSplus::TreeNode *resampledNode = NULL); void setNext(SaveItem *itm) { nxt = itm; } @@ -69,9 +71,9 @@ class SaveList public: SaveList(); - void addItem(short *buffer, int segmentSamples, MDSplus::TreeNode *dataNode, + void addItem(short *buffer, int segmentSamples, MDSplus::TreeNode *dataNode, MDSplus::TreeNode *trigRecvNode, MDSplus::Data *triggerTime, void *treePtr, - double *startTimes, double *endTimes, double freq, int blocksInSegment, + double *startTimes, double *endTimes, double freq, int blocksInSegment, char *trigReceived, MDSplus::TreeNode *resampledNode = NULL); void executeItems(); diff --git a/device_support/redpitaya/Makefile b/device_support/redpitaya/Makefile index bd513d8736..2c9dcaac39 100755 --- a/device_support/redpitaya/Makefile +++ b/device_support/redpitaya/Makefile @@ -1,7 +1,7 @@ CC=g++ -CFLAGS = -fPIC -o2 -Wall -DLINUX -I${MDSPLUS_DIR}/include -I. -Wno-unused-variable -Wno-unused-but-set-variable -Wno-unused-function +CFLAGS = -std=c++11 -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 diff --git a/device_support/redpitaya/devicetree.dts b/device_support/redpitaya/devicetree.dts new file mode 100644 index 0000000000..6ff0983b2c --- /dev/null +++ b/device_support/redpitaya/devicetree.dts @@ -0,0 +1,644 @@ +/dts-v1/; + +/ { + #address-cells = <0x1>; + #size-cells = <0x1>; + compatible = "xlnx,zynq-7000"; + + cpus { + #address-cells = <0x1>; + #size-cells = <0x0>; + + cpu0: cpu@0 { + compatible = "arm,cortex-a9"; + device_type = "cpu"; + reg = <0x0>; + clocks = <0x1 0x3>; + clock-latency = <0x3e8>; + cpu0-supply = <0x2>; + operating-points = <0xa2c2a 0xf4240 0x51615 0xf4240>; + }; + + cpu1: cpu@1 { + compatible = "arm,cortex-a9"; + device_type = "cpu"; + reg = <0x1>; + clocks = <0x1 0x3>; + }; + }; + + fpga_full: fpga-full { + compatible = "fpga-region"; + fpga-mgr = <0x3>; + #address-cells = <0x1>; + #size-cells = <0x1>; + ranges; + }; + + pmu@f8891000 { + compatible = "arm,cortex-a9-pmu"; + interrupts = <0x0 0x5 0x4 0x0 0x6 0x4>; + interrupt-parent = <0x4>; + reg = <0xf8891000 0x1000 0xf8893000 0x1000>; + }; + + regulator_vccpint: fixedregulator { + compatible = "regulator-fixed"; + regulator-name = "VCCPINT"; + regulator-min-microvolt = <0xf4240>; + regulator-max-microvolt = <0xf4240>; + regulator-boot-on; + regulator-always-on; + linux,phandle = <0x2>; + phandle = <0x2>; + }; + + amba: amba { + u-boot,dm-pre-reloc; + compatible = "simple-bus"; + #address-cells = <0x1>; + #size-cells = <0x1>; + interrupt-parent = <0x4>; + ranges; + + adc: adc@f8007100 { + compatible = "xlnx,zynq-xadc-1.00.a"; + reg = <0xf8007100 0x20>; + interrupts = <0x0 0x7 0x4>; + interrupt-parent = <0x4>; + clocks = <0x1 0xc>; + }; + + can0: can@e0008000 { + compatible = "xlnx,zynq-can-1.0"; + status = "disabled"; + clocks = <0x1 0x13 0x1 0x24>; + clock-names = "can_clk", "pclk"; + reg = <0xe0008000 0x1000>; + interrupts = <0x0 0x1c 0x4>; + interrupt-parent = <0x4>; + tx-fifo-depth = <0x40>; + rx-fifo-depth = <0x40>; + }; + + can1: can@e0009000 { + compatible = "xlnx,zynq-can-1.0"; + status = "disabled"; + clocks = <0x1 0x14 0x1 0x25>; + clock-names = "can_clk", "pclk"; + reg = <0xe0009000 0x1000>; + interrupts = <0x0 0x33 0x4>; + interrupt-parent = <0x4>; + tx-fifo-depth = <0x40>; + rx-fifo-depth = <0x40>; + }; + + gpio0: gpio@e000a000 { + compatible = "xlnx,zynq-gpio-1.0"; + #gpio-cells = <0x2>; + clocks = <0x1 0x2a>; + gpio-controller; + interrupt-controller; + #interrupt-cells = <0x2>; + interrupt-parent = <0x4>; + interrupts = <0x0 0x14 0x4>; + reg = <0xe000a000 0x1000>; + emio-gpio-width = <0x40>; + gpio-mask-high = <0x0>; + gpio-mask-low = <0x5600>; + linux,phandle = <0x6>; + phandle = <0x6>; + }; + + i2c0: i2c@e0004000 { + compatible = "cdns,i2c-r1p10"; + status = "okay"; + clocks = <0x1 0x26>; + interrupt-parent = <0x4>; + interrupts = <0x0 0x19 0x4>; + reg = <0xe0004000 0x1000>; + #address-cells = <0x1>; + #size-cells = <0x0>; + clock-frequency = <0x61a80>; + }; + + i2c1: i2c@e0005000 { + compatible = "cdns,i2c-r1p10"; + status = "disabled"; + clocks = <0x1 0x27>; + interrupt-parent = <0x4>; + interrupts = <0x0 0x30 0x4>; + reg = <0xe0005000 0x1000>; + #address-cells = <0x1>; + #size-cells = <0x0>; + }; + + intc: interrupt-controller@f8f01000 { + compatible = "arm,cortex-a9-gic"; + #interrupt-cells = <0x3>; + interrupt-controller; + reg = <0xf8f01000 0x1000 0xf8f00100 0x100>; + num_cpus = <0x2>; + num_interrupts = <0x60>; + linux,phandle = <0x4>; + phandle = <0x4>; + }; + + L2: cache-controller@f8f02000 { + compatible = "arm,pl310-cache"; + reg = <0xf8f02000 0x1000>; + interrupts = <0x0 0x2 0x4>; + arm,data-latency = <0x3 0x2 0x2>; + arm,tag-latency = <0x2 0x2 0x2>; + cache-unified; + cache-level = <0x2>; + }; + + mc: memory-controller@f8006000 { + compatible = "xlnx,zynq-ddrc-a05"; + reg = <0xf8006000 0x1000>; + }; + + ocmc: ocmc@f800c000 { + compatible = "xlnx,zynq-ocmc-1.0"; + interrupt-parent = <0x4>; + interrupts = <0x0 0x3 0x4>; + reg = <0xf800c000 0x1000>; + }; + + uart0: serial@e0000000 { + compatible = "xlnx,xuartps", "cdns,uart-r1p8"; + status = "okay"; + clocks = <0x1 0x17 0x1 0x28>; + clock-names = "uart_clk", "pclk"; + reg = <0xe0000000 0x1000>; + interrupts = <0x0 0x1b 0x4>; + device_type = "serial"; + port-number = <0x0>; + }; + + uart1: serial@e0001000 { + compatible = "xlnx,xuartps", "cdns,uart-r1p8"; + status = "okay"; + clocks = <0x1 0x18 0x1 0x29>; + clock-names = "uart_clk", "pclk"; + reg = <0xe0001000 0x1000>; + interrupts = <0x0 0x32 0x4>; + device_type = "serial"; + port-number = <0x1>; + }; + + spi0: spi@e0006000 { + compatible = "xlnx,zynq-spi-r1p6"; + reg = <0xe0006000 0x1000>; + status = "disabled"; + interrupt-parent = <0x4>; + interrupts = <0x0 0x1a 0x4>; + clocks = <0x1 0x19 0x1 0x22>; + clock-names = "ref_clk", "pclk"; + #address-cells = <0x1>; + #size-cells = <0x0>; + }; + + spi1: spi@e0007000 { + compatible = "xlnx,zynq-spi-r1p6"; + reg = <0xe0007000 0x1000>; + status = "okay"; + interrupt-parent = <0x4>; + interrupts = <0x0 0x31 0x4>; + clocks = <0x1 0x1a 0x1 0x23>; + clock-names = "ref_clk", "pclk"; + #address-cells = <0x1>; + #size-cells = <0x0>; + is-decoded-cs = <0x0>; + num-cs = <0x1>; + }; + + qspi: spi@e000d000 { + clock-names = "ref_clk", "pclk"; + clocks = <0x1 0xa 0x1 0x2b>; + compatible = "xlnx,zynq-qspi-1.0"; + status = "okay"; + interrupt-parent = <0x4>; + interrupts = <0x0 0x13 0x4>; + reg = <0xe000d000 0x1000>; + #address-cells = <0x1>; + #size-cells = <0x0>; + is-dual = <0x0>; + num-cs = <0x1>; + spi-rx-bus-width = <0x4>; + spi-tx-bus-width = <0x4>; + }; + + smcc: memory-controller@e000e000 { + #address-cells = <0x1>; + #size-cells = <0x1>; + status = "disabled"; + clock-names = "memclk", "aclk"; + clocks = <0x1 0xb 0x1 0x2c>; + compatible = "arm,pl353-smc-r2p1"; + interrupt-parent = <0x4>; + interrupts = <0x0 0x12 0x4>; + ranges; + reg = <0xe000e000 0x1000>; + + nand0: flash@e1000000 { + status = "disabled"; + compatible = "arm,pl353-nand-r2p1"; + reg = <0xe1000000 0x1000000>; + #address-cells = <0x1>; + #size-cells = <0x1>; + }; + + nor0: flash@e2000000 { + status = "disabled"; + compatible = "cfi-flash"; + reg = <0xe2000000 0x2000000>; + #address-cells = <0x1>; + #size-cells = <0x1>; + }; + }; + + gem0: ethernet@e000b000 { + compatible = "cdns,zynq-gem", "cdns,gem"; + reg = <0xe000b000 0x1000>; + status = "okay"; + interrupts = <0x0 0x16 0x4>; + clocks = <0x1 0x1e 0x1 0x1e 0x1 0xd>; + clock-names = "pclk", "hclk", "tx_clk"; + #address-cells = <0x1>; + #size-cells = <0x0>; + phy-mode = "rgmii-id"; + xlnx,ptp-enet-clock = <0x69f6bcb>; + }; + + gem1: ethernet@e000c000 { + compatible = "cdns,zynq-gem", "cdns,gem"; + reg = <0xe000c000 0x1000>; + status = "disabled"; + interrupts = <0x0 0x2d 0x4>; + clocks = <0x1 0x1f 0x1 0x1f 0x1 0xe>; + clock-names = "pclk", "hclk", "tx_clk"; + #address-cells = <0x1>; + #size-cells = <0x0>; + }; + + sdhci0: sdhci@e0100000 { + compatible = "arasan,sdhci-8.9a"; + status = "okay"; + clock-names = "clk_xin", "clk_ahb"; + clocks = <0x1 0x15 0x1 0x20>; + interrupt-parent = <0x4>; + interrupts = <0x0 0x18 0x4>; + reg = <0xe0100000 0x1000>; + xlnx,has-cd = <0x1>; + xlnx,has-power = <0x0>; + xlnx,has-wp = <0x1>; + }; + + sdhci1: sdhci@e0101000 { + compatible = "arasan,sdhci-8.9a"; + status = "disabled"; + clock-names = "clk_xin", "clk_ahb"; + clocks = <0x1 0x16 0x1 0x21>; + interrupt-parent = <0x4>; + interrupts = <0x0 0x2f 0x4>; + reg = <0xe0101000 0x1000>; + }; + + slcr: slcr@f8000000 { + #address-cells = <0x1>; + #size-cells = <0x1>; + compatible = "xlnx,zynq-slcr", "syscon", "simple-mfd"; + reg = <0xf8000000 0x1000>; + ranges; + linux,phandle = <0x5>; + phandle = <0x5>; + + clkc: clkc@100 { + #clock-cells = <0x1>; + compatible = "xlnx,ps7-clkc"; + fclk-enable = <0x1>; + clock-output-names = "armpll", "ddrpll", "iopll", "cpu_6or4x", "cpu_3or2x", "cpu_2x", "cpu_1x", "ddr2x", "ddr3x", "dci", "lqspi", "smc", "pcap", "gem0", "gem1", "fclk0", "fclk1", "fclk2", "fclk3", "can0", "can1", "sdio0", "sdio1", "uart0", "uart1", "spi0", "spi1", "dma", "usb0_aper", "usb1_aper", "gem0_aper", "gem1_aper", "sdio0_aper", "sdio1_aper", "spi0_aper", "spi1_aper", "can0_aper", "can1_aper", "i2c0_aper", "i2c1_aper", "uart0_aper", "uart1_aper", "gpio_aper", "lqspi_aper", "smc_aper", "swdt", "dbg_trc", "dbg_apb"; + reg = <0x100 0x100>; + ps-clk-frequency = <0x1fca055>; + linux,phandle = <0x1>; + phandle = <0x1>; + }; + + rstc: rstc@200 { + compatible = "xlnx,zynq-reset"; + reg = <0x200 0x48>; + #reset-cells = <0x1>; + syscon = <0x5>; + }; + + pinctrl0: pinctrl@700 { + compatible = "xlnx,pinctrl-zynq"; + reg = <0x700 0x200>; + syscon = <0x5>; + }; + }; + + dmac_s: dmac@f8003000 { + compatible = "arm,pl330", "arm,primecell"; + reg = <0xf8003000 0x1000>; + interrupt-parent = <0x4>; + interrupt-names = "abort", "dma0", "dma1", "dma2", "dma3", "dma4", "dma5", "dma6", "dma7"; + interrupts = <0x0 0xd 0x4 0x0 0xe 0x4 0x0 0xf 0x4 0x0 0x10 0x4 0x0 0x11 0x4 0x0 0x28 0x4 0x0 0x29 0x4 0x0 0x2a 0x4 0x0 0x2b 0x4>; + #dma-cells = <0x1>; + #dma-channels = <0x8>; + #dma-requests = <0x4>; + clocks = <0x1 0x1b>; + clock-names = "apb_pclk"; + }; + + devcfg: devcfg@f8007000 { + compatible = "xlnx,zynq-devcfg-1.0"; + interrupt-parent = <0x4>; + interrupts = <0x0 0x8 0x4>; + reg = <0xf8007000 0x100>; + clocks = <0x1 0xc 0x1 0xf 0x1 0x10 0x1 0x11 0x1 0x12>; + clock-names = "ref_clk", "fclk0", "fclk1", "fclk2", "fclk3"; + syscon = <0x5>; + linux,phandle = <0x3>; + phandle = <0x3>; + }; + + efuse: efuse@f800d000 { + compatible = "xlnx,zynq-efuse"; + reg = <0xf800d000 0x20>; + }; + + global_timer: timer@f8f00200 { + compatible = "arm,cortex-a9-global-timer"; + reg = <0xf8f00200 0x20>; + interrupts = <0x1 0xb 0x301>; + interrupt-parent = <0x4>; + clocks = <0x1 0x4>; + }; + + ttc0: timer@f8001000 { + interrupt-parent = <0x4>; + interrupts = <0x0 0xa 0x4 0x0 0xb 0x4 0x0 0xc 0x4>; + compatible = "cdns,ttc"; + clocks = <0x1 0x6>; + reg = <0xf8001000 0x1000>; + }; + + ttc1: timer@f8002000 { + interrupt-parent = <0x4>; + interrupts = <0x0 0x25 0x4 0x0 0x26 0x4 0x0 0x27 0x4>; + compatible = "cdns,ttc"; + clocks = <0x1 0x6>; + reg = <0xf8002000 0x1000>; + }; + + scutimer: timer@f8f00600 { + interrupt-parent = <0x4>; + interrupts = <0x1 0xd 0x301>; + compatible = "arm,cortex-a9-twd-timer"; + reg = <0xf8f00600 0x20>; + clocks = <0x1 0x4>; + }; + + usb0: usb@e0002000 { + compatible = "xlnx,zynq-usb-2.20a", "chipidea,usb2"; + status = "okay"; + clocks = <0x1 0x1c>; + interrupt-parent = <0x4>; + interrupts = <0x0 0x15 0x4>; + reg = <0xe0002000 0x1000>; + phy_type = "ulpi"; + usb-reset = <0x6 0x30 0x0>; + }; + + usb1: usb@e0003000 { + compatible = "xlnx,zynq-usb-2.20a", "chipidea,usb2"; + status = "disabled"; + clocks = <0x1 0x1d>; + interrupt-parent = <0x4>; + interrupts = <0x0 0x2c 0x4>; + reg = <0xe0003000 0x1000>; + phy_type = "ulpi"; + }; + + watchdog0: watchdog@f8005000 { + clocks = <0x1 0x2d>; + compatible = "cdns,wdt-r1p2"; + interrupt-parent = <0x4>; + interrupts = <0x0 0x9 0x1>; + reg = <0xf8005000 0x1000>; + timeout-sec = <0xa>; + }; + }; + + amba_pl: amba_pl { + #address-cells = <0x1>; + #size-cells = <0x1>; + compatible = "simple-bus"; + ranges; + + cmd_reg: axi_cfg_register@54000000 { + compatible = "xlnx,axi-cfg-register-1.0"; + reg = <0x54000000 0x1000>; + }; + + command_register: axi_cfg_register@42000000 { + compatible = "xlnx,axi-cfg-register-1.0"; + reg = <0x42000000 0x1000>; + }; + + data_fifo: axi_fifo_mm_s@40440000 { + compatible = "xlnx,axi-fifo-mm-s-4.1"; + interrupt-parent = <0x4>; + interrupts = <0x0 0x1d 0x4>; + reg = <0x40440000 0x10000 0x40450000 0x10000>; + xlnx,axi-str-rxd-protocol = "XIL_AXI_STREAM_ETH_DATA"; + xlnx,axi-str-rxd-tdata-width = <0x20>; + xlnx,axi-str-txc-protocol = "XIL_AXI_STREAM_ETH_CTRL"; + xlnx,axi-str-txc-tdata-width = <0x20>; + xlnx,axi-str-txd-protocol = "XIL_AXI_STREAM_ETH_DATA"; + xlnx,axi-str-txd-tdata-width = <0x20>; + xlnx,axis-tdest-width = <0x4>; + xlnx,axis-tid-width = <0x4>; + xlnx,axis-tuser-width = <0x4>; + xlnx,data-interface-type = <0x1>; + xlnx,has-axis-tdest = <0x0>; + xlnx,has-axis-tid = <0x0>; + xlnx,has-axis-tkeep = <0x0>; + xlnx,has-axis-tstrb = <0x0>; + xlnx,has-axis-tuser = <0x0>; + xlnx,rx-fifo-depth = <0x4000>; + xlnx,rx-fifo-pe-threshold = <0x2>; + xlnx,rx-fifo-pf-threshold = <0x64>; + xlnx,s-axi-id-width = <0xc>; + xlnx,s-axi4-data-width = <0x20>; + xlnx,select-xpm = <0x0>; + xlnx,tx-fifo-depth = <0x200>; + xlnx,tx-fifo-pe-threshold = <0x2>; + xlnx,tx-fifo-pf-threshold = <0x1fb>; + xlnx,use-rx-cut-through = <0x0>; + xlnx,use-rx-data = <0x1>; + xlnx,use-tx-ctrl = <0x0>; + xlnx,use-tx-cut-through = <0x0>; + xlnx,use-tx-data = <0x0>; + }; + + deadtime_register: axi_cfg_register@58000000 { + compatible = "xlnx,axi-cfg-register-1.0"; + reg = <0x58000000 0x1000>; + }; + + decimator_register: axi_cfg_register@60000000 { + compatible = "xlnx,axi-cfg-register-1.0"; + reg = <0x60000000 0x1000>; + }; + + k1_reg: axi_cfg_register@5c000000 { + compatible = "xlnx,axi-cfg-register-1.0"; + reg = <0x5c000000 0x1000>; + }; + + k2_reg: axi_cfg_register@64000000 { + compatible = "xlnx,axi-cfg-register-1.0"; + reg = <0x64000000 0x1000>; + }; + + lev_trig_count: axi_cfg_register@68000000 { + compatible = "xlnx,axi-cfg-register-1.0"; + reg = <0x68000000 0x1000>; + }; + + mode_register: axi_cfg_register@44000000 { + compatible = "xlnx,axi-cfg-register-1.0"; + reg = <0x44000000 0x1000>; + }; + + offset_reg: axi_cfg_register@6c000000 { + compatible = "xlnx,axi-cfg-register-1.0"; + reg = <0x6c000000 0x1000>; + }; + + packetizer: axi_cfg_register@50000000 { + compatible = "xlnx,axi-cfg-register-1.0"; + reg = <0x50000000 0x1000>; + }; + + post_register: axi_cfg_register@41000000 { + compatible = "xlnx,axi-cfg-register-1.0"; + reg = <0x41000000 0x1000>; + }; + + pre_register: axi_cfg_register@48000000 { + compatible = "xlnx,axi-cfg-register-1.0"; + reg = <0x48000000 0x1000>; + }; + + step_hi_reg: axi_cfg_register@46000000 { + compatible = "xlnx,axi-cfg-register-1.0"; + reg = <0x46000000 0x1000>; + }; + + step_lo_reg: axi_cfg_register@4a000000 { + compatible = "xlnx,axi-cfg-register-1.0"; + reg = <0x4a000000 0x1000>; + }; + + time_fifo: axi_fifo_mm_s@40420000 { + compatible = "xlnx,axi-fifo-mm-s-4.1"; + reg = <0x40420000 0x10000 0x40430000 0x10000>; + xlnx,axi-str-rxd-protocol = "XIL_AXI_STREAM_ETH_DATA"; + xlnx,axi-str-rxd-tdata-width = <0x20>; + xlnx,axi-str-txc-protocol = "XIL_AXI_STREAM_ETH_CTRL"; + xlnx,axi-str-txc-tdata-width = <0x20>; + xlnx,axi-str-txd-protocol = "XIL_AXI_STREAM_ETH_DATA"; + xlnx,axi-str-txd-tdata-width = <0x20>; + xlnx,axis-tdest-width = <0x4>; + xlnx,axis-tid-width = <0x4>; + xlnx,axis-tuser-width = <0x4>; + xlnx,data-interface-type = <0x1>; + xlnx,has-axis-tdest = <0x0>; + xlnx,has-axis-tid = <0x0>; + xlnx,has-axis-tkeep = <0x0>; + xlnx,has-axis-tstrb = <0x0>; + xlnx,has-axis-tuser = <0x0>; + xlnx,rx-fifo-depth = <0x200>; + xlnx,rx-fifo-pe-threshold = <0x2>; + xlnx,rx-fifo-pf-threshold = <0x1fb>; + xlnx,s-axi-id-width = <0xc>; + xlnx,s-axi4-data-width = <0x20>; + xlnx,select-xpm = <0x0>; + xlnx,tx-fifo-depth = <0x200>; + xlnx,tx-fifo-pe-threshold = <0x2>; + xlnx,tx-fifo-pf-threshold = <0x1fb>; + xlnx,use-rx-cut-through = <0x0>; + xlnx,use-rx-data = <0x1>; + xlnx,use-tx-ctrl = <0x0>; + xlnx,use-tx-cut-through = <0x0>; + xlnx,use-tx-data = <0x0>; + }; + + time_ofs_hi_reg: axi_cfg_register@70000000 { + compatible = "xlnx,axi-cfg-register-1.0"; + reg = <0x70000000 0x1000>; + }; + + time_ofs_lo_reg: axi_cfg_register@4c000000 { + compatible = "xlnx,axi-cfg-register-1.0"; + reg = <0x4c000000 0x1000>; + }; + + times_fifo: axi_fifo_mm_s@43c00000 { + compatible = "xlnx,axi-fifo-mm-s-4.1"; + reg = <0x43c00000 0x10000 0x43c10000 0x10000>; + xlnx,axi-str-rxd-protocol = "XIL_AXI_STREAM_ETH_DATA"; + xlnx,axi-str-rxd-tdata-width = <0x20>; + xlnx,axi-str-txc-protocol = "XIL_AXI_STREAM_ETH_CTRL"; + xlnx,axi-str-txc-tdata-width = <0x20>; + xlnx,axi-str-txd-protocol = "XIL_AXI_STREAM_ETH_DATA"; + xlnx,axi-str-txd-tdata-width = <0x20>; + xlnx,axis-tdest-width = <0x4>; + xlnx,axis-tid-width = <0x4>; + xlnx,axis-tuser-width = <0x4>; + xlnx,data-interface-type = <0x1>; + xlnx,has-axis-tdest = <0x0>; + xlnx,has-axis-tid = <0x0>; + xlnx,has-axis-tkeep = <0x0>; + xlnx,has-axis-tstrb = <0x0>; + xlnx,has-axis-tuser = <0x0>; + xlnx,rx-fifo-depth = <0x200>; + xlnx,rx-fifo-pe-threshold = <0x2>; + xlnx,rx-fifo-pf-threshold = <0x1fb>; + xlnx,s-axi-id-width = <0xc>; + xlnx,s-axi4-data-width = <0x20>; + xlnx,select-xpm = <0x0>; + xlnx,tx-fifo-depth = <0x200>; + xlnx,tx-fifo-pe-threshold = <0x2>; + xlnx,tx-fifo-pf-threshold = <0x1fb>; + xlnx,use-rx-cut-through = <0x0>; + xlnx,use-rx-data = <0x1>; + xlnx,use-tx-ctrl = <0x0>; + xlnx,use-tx-cut-through = <0x0>; + xlnx,use-tx-data = <0x0>; + }; + }; + + chosen { + bootargs = "earlycon"; + stdout-path = "serial0:115200n8"; + }; + + aliases { + ethernet0 = "/amba/ethernet@e000b000"; + serial0 = "/amba/serial@e0000000"; + serial1 = "/amba/serial@e0001000"; + spi0 = "/amba/spi@e000d000"; + spi1 = "/amba/spi@e0007000"; + }; + + memory { + device_type = "memory"; + reg = <0x0 0x20000000>; + }; +}; diff --git a/device_support/redpitaya/prova b/device_support/redpitaya/prova deleted file mode 100755 index fcfe96da6f..0000000000 Binary files a/device_support/redpitaya/prova and /dev/null differ diff --git a/device_support/redpitaya/redpitaya.cpp b/device_support/redpitaya/redpitaya.cpp index b162d1eae5..2a2c597a6e 100644 --- a/device_support/redpitaya/redpitaya.cpp +++ b/device_support/redpitaya/redpitaya.cpp @@ -11,17 +11,18 @@ #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, + void rpadcStream(int fd, char *treeName, int shot, int chan1Nid, int chan2Nid, int trigRecvNid, int triggerNid, int preSamples, int postSamples, 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 deadtime); + int thresholdSamples, int decimation, int deadtime, int offsa, int offsb); int rpadcTrigger(int fd); void rpadcStop(int fd); void openTree(char *name, int shot, MDSplus::Tree **treePtr); @@ -42,9 +43,9 @@ enum rpadc_clock_mode { 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) + TRIG_SYNC, //Internal clock, but trigger timestamping from 1MHz clock internally generated + EXTERNAL, //External sampling clock, same clock used for trigger timestamping + SYNC //Synchronized 1MHz clock internally generated }; #define DMA_STREAMING_SAMPLES 1024 @@ -63,6 +64,7 @@ struct rpadc_configuration unsigned int post_samples; // Number of post-trigger samples 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 + unsigned int offset; // offset to be applied to both channels (16+16) }; static bool stopped = false; @@ -81,8 +83,7 @@ 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 auxVal = 0; - + if (config->mode == STREAMING) currVal |= 0x00000001; if (config->trig_from_chana) @@ -98,21 +99,19 @@ static void writeConfig(int fd, struct rpadc_configuration *config) 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; + case TRIG_SYNC: //Internal clock, but trigger timestamping from 1MHz clock internally generated trigger) + currVal |= 0x00000020; + currVal |= 0x00000080; 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) + case SYNC: //Synchronized 1MHz clock internally generated currVal |= 0x00000020; - currVal |= 0x00000040; - auxVal |= 0x00000001; + currVal |= 0x00000040; + currVal |= 0x00000080; break; } @@ -126,9 +125,7 @@ static void writeConfig(int fd, struct rpadc_configuration *config) 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; @@ -142,6 +139,11 @@ static void writeConfig(int fd, struct rpadc_configuration *config) regs.deadtime_register_enable = 1; regs.deadtime_register = config->deadtime; + +//AGGIUNTA OFFSET + regs.offset_reg_enable = 1; + regs.offset_reg = config->offset; + ioctl(fd, RFX_STREAM_SET_REGISTERS, ®s); usleep(10000); @@ -154,16 +156,15 @@ static void writeConfig(int fd, struct rpadc_configuration *config) ioctl(fd, RFX_STREAM_CLEAR_DATA_FIFO, NULL); // ioctl(fd, RFX_STREAM_FIFO_INT_HALF_SIZE, NULL); - ioctl(fd, RFX_STREAM_FIFO_INT_FIRST_SAMPLE, NULL); + ioctl(fd, RFX_STREAM_FIFO_INT_FIRST_SAMPLE, NULL); } static void readConfig(int fd, struct rpadc_configuration *config) { - unsigned int currVal, auxVal; + unsigned int currVal; 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 @@ -191,17 +192,11 @@ static void readConfig(int fd, struct rpadc_configuration *config) { if (currVal & 0x00000040) { - if (auxVal & 0x0000004) - config->clock_mode = EXTERNAL; - else - config->clock_mode = SYNC; + config->clock_mode = EXTERNAL; } else { - if (auxVal & 0x0000004) config->clock_mode = TRIG_EXTERNAL; - else - config->clock_mode = TRIG_ABS; } } @@ -222,8 +217,8 @@ static void readConfig(int fd, struct rpadc_configuration *config) config->pre_samples = regs.pre_register; config->decimation = regs.decimator_register + 1; config->deadtime = regs.deadtime_register; + config->offset = regs.offset_reg; - 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); } @@ -287,15 +282,15 @@ static void sigHandler(int signo) } static void writeSegment(MDSplus::Tree *t, MDSplus::TreeNode *chan1, - MDSplus::TreeNode *chan2, MDSplus::Data *triggerTime, + MDSplus::TreeNode *chan2, MDSplus::TreeNode *trigRecv, MDSplus::Data *triggerTime, unsigned int *dataSamples, double *startTimes, double *endTimes, int segmentSamples, - int blocksInSegment, double freq, SaveList *saveList) + int blocksInSegment, double freq, SaveList *saveList, char *trigReceived) { + if (segmentSamples == 0) return; short *chan1Samples, *chan2Samples; - //std::cout << "WRITE SEGMENT SAMPLES: " << segmentSamples << std::endl; chan1Samples = new short[segmentSamples]; chan2Samples = new short[segmentSamples]; @@ -305,20 +300,20 @@ static void writeSegment(MDSplus::Tree *t, MDSplus::TreeNode *chan1, chan2Samples[i] = (dataSamples[i] >> 16) & 0x0000ffff; } - saveList->addItem(chan1Samples, segmentSamples, chan1, triggerTime, t, - startTimes, endTimes, freq, blocksInSegment); + saveList->addItem(chan1Samples, segmentSamples, chan1, trigRecv, triggerTime, t, + startTimes, endTimes, freq, blocksInSegment, trigReceived); - saveList->addItem(chan2Samples, segmentSamples, chan2, triggerTime, t, - startTimes, endTimes, freq, blocksInSegment); + saveList->addItem(chan2Samples, segmentSamples, chan2, NULL, triggerTime, t, + startTimes, endTimes, freq, blocksInSegment, 0); } // Stop void rpadcStop(int fd) { + std::cout << "RPADC STOP" << std::endl; adcStop(fd); usleep(100000); fifoFlush(fd); stopped = true; - std::cout << "TIRATO SU STOP\n"; usleep(100000); usleep(100000); // dmaStop(fd); @@ -330,7 +325,7 @@ void rpadcStop(int fd) std::cout << "CLOSED\n"; } -void rpadcStream(int fd, char *treeName, int shot, int chan1Nid, int chan2Nid, +void rpadcStream(int fd, char *treeName, int shot, int chan1Nid, int chan2Nid, int trigRecvNid, int triggerNid, int preSamples, int postSamples, int inSegmentSamples, double freq, double freq1, int single, int absTriggerTimeFromFPGA, int absTriggerNid) { @@ -344,14 +339,15 @@ void rpadcStream(int fd, char *treeName, int shot, int chan1Nid, int chan2Nid, int blocksInSegment; // 1 fir cintinous streaming unsigned int *dataSamples; double *startTimes, *endTimes; + char *trigFlags; stopped = false; unsigned int trig_lev_count = 0; - unsigned long long firstAbsTriggerTime = 0; + long long firstAbsTriggerTime = -1; unsigned long long lastAbsTriggerTime = 0; unsigned long long currTime, savedTime; - std::cout << "rpadcStream freq1: " << freq1 << " FREQ: " << freq << std::endl; + fifoFlush(fd); @@ -361,9 +357,10 @@ void rpadcStream(int fd, char *treeName, int shot, int chan1Nid, int chan2Nid, 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 *trigRecv = new MDSplus::TreeNode(trigRecvNid, 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 { @@ -408,24 +405,58 @@ void rpadcStream(int fd, char *treeName, int shot, int chan1Nid, int chan2Nid, memset(dataSamples, 0, segmentSamples * sizeof(int)); startTimes = new double[blocksInSegment]; endTimes = new double[blocksInSegment]; + trigFlags = new char[blocksInSegment]; ioctl(fd, RFX_STREAM_START_READ, NULL); adcArm(fd); usleep(1000); int segmentIdx = 0; - SaveList *saveList = new SaveList; - saveList->start(); + + //SaveList *saveList = new SaveList(); + //saveList->start(); + SaveList *saveList = new SaveList(); + saveList->start(); + // START WITH A INITIAL VALUE FOR TRIG_LEV_COUNT 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); + + + //GABRIELE FEBR 2023: remove first two fake samples from data fifo +/* + { + int dummy[2]; + int leftBytes = 8; + while(leftBytes > 0) + { + int currRead = read(fd, dummy, leftBytes); + if(currRead < 0) + { + std::cout << "OHI OHI!\n"; + return; + } + leftBytes -= currRead; + } + } + + + */ + + + struct timeval selWaitTime; - while (true) + unsigned int prevTime = 0; + char trigReceived = 0; + while (!stopped) { - for (int currBlock = 0; currBlock < blocksInSegment; currBlock++) + for (int currBlock = 0; currBlock < blocksInSegment;currBlock++) { unsigned int currSample = 0; bool firstRead = true; + + +///////////////////// while (currSample < blockSamples) { //std::cout<<"Reading...\n"; @@ -474,9 +505,9 @@ void rpadcStream(int fd, char *treeName, int shot, int chan1Nid, int chan2Nid, endTimes[0] = ((segmentIdx + 1) * segmentSamples - preSamples) / freq; // ((segmentIdx + 1) * segmentSamples - preSamples) / freq1; Gabriele Dec 2021 - writeSegment(tree, chan1, chan2, trigger, dataSamples, + writeSegment(tree, chan1, chan2, NULL, trigger, dataSamples, startTimes, endTimes, - currBlock * blockSamples + currSample, 1, freq, saveList); + currBlock * blockSamples + currSample, 1, freq, saveList, NULL); // currBlock * blockSamples + currSample, 1, freq1, saveList); Gabriele Dec 2021 } else // Some data for new window have been read @@ -484,14 +515,20 @@ void rpadcStream(int fd, char *treeName, int shot, int chan1Nid, int chan2Nid, unsigned int time1, time2; ioctl(fd, RFX_STREAM_GET_TIME_FIFO_VAL, &time1); ioctl(fd, RFX_STREAM_GET_TIME_FIFO_VAL, &time2); + trigReceived = (time2 & 0x80000000)?1:0; + if(trigReceived) std::cout<< "TRIGGER RICEVUTO!\n"; + time2 &= 0x7FFFFFFF; currTime = (unsigned long long)time1 | (((unsigned long long)time2) << 32); + //if(currTime >= 2) Only when counter for trigger is internal data + // currTime -= 2; + + if(absTriggerTimeFromFPGA) { - std::cout << "TRIGGER TIME: " << currTime << std::endl; - if(firstAbsTriggerTime == 0) + if(firstAbsTriggerTime == -1) { firstAbsTriggerTime = lastAbsTriggerTime = currTime; currTime = 0; @@ -511,18 +548,21 @@ void rpadcStream(int fd, char *treeName, int shot, int chan1Nid, int chan2Nid, endTimes[currBlock] = currTime/freq1 + (postSamples - 1) / freq; // include last sample // (currTime + postSamples - 1) / freq; // include last sample Gabriele Dec 2021 - writeSegment(tree, chan1, chan2, trigger, dataSamples, + trigFlags[currBlock] = trigReceived; + writeSegment(tree, chan1, chan2, trigRecv, trigger, dataSamples, startTimes, endTimes, currBlock * blockSamples + currSample, - currBlock + 1, freq, saveList); + currBlock + 1, freq, saveList, trigFlags); +// currBlock + 1, freq1, saveList); Gabriele Dec 2021 } } else // Some windows have been read before and the segment is // partially filled { - writeSegment(tree, chan1, chan2, trigger, dataSamples, startTimes, + writeSegment(tree, chan1, chan2, trigRecv, trigger, dataSamples, startTimes, endTimes, currBlock * blockSamples + currSample, - currBlock, freq, saveList); + currBlock, freq, saveList, trigFlags); +// currBlock, freq1, saveList); Gabriele Dec 2021 } } deviceFd = 0; @@ -538,60 +578,75 @@ void rpadcStream(int fd, char *treeName, int shot, int chan1Nid, int chan2Nid, return; } } - // signal to FPGA that block has been 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); // Here the block been filled. It may refer to the same window // (isSingle)or to a different time window + if(stopped) return; + + 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) + unsigned int time1, time2, len; + + if (preSamples != 0 || postSamples != 0) // not continuous { - std::cout << "TRIGGER TIME: " << currTime << std::endl; - if(firstAbsTriggerTime == 0) + for(int i = 0; i < 10000; i++) + { + ioctl(fd, RFX_STREAM_GET_TIME_FIFO_LEN, &len); + if(len >= 2) break; + usleep(100); + } + if(len < 2) { - firstAbsTriggerTime = lastAbsTriggerTime = currTime; - currTime = 0; - MDSplus::Data *triggerData = new MDSplus::Uint64(firstAbsTriggerTime); - absTrigger->putData(triggerData); - MDSplus::deleteData(triggerData); + std::cout << "DOLORE!!!! TRIGGER TIME NOT FOUND IN FIFO\n"; + return; } - else + + ioctl(fd, RFX_STREAM_GET_TIME_FIFO_VAL, &time1); + ioctl(fd, RFX_STREAM_GET_TIME_FIFO_VAL, &time2); + trigReceived = (time2 & 0x80000000)?1:0; + if(trigReceived) std::cout << "TRIGGER RECEIVED\n"; + currTime =(unsigned long long)time1 | (((unsigned long long)(time2 & 0x7FFFFFFF)) << 32); + if(currTime < prevTime) + std::cout << "OHIBO! currTime: " << currTime << " PrevTime: " << prevTime << std::endl; + prevTime = currTime; + 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 { if (single) { 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 + trigFlags[0] = 0; } else // If referring to a new window, the time must be read { if (currBlock == 0) { - startTimes[currBlock] = ((long long)currTime)/freq1 - (preSamples - 1) / freq; -// ((long long)currTime - preSamples - 1) / freq; Gabriele Dec 2021 + startTimes[currBlock] = ((long long)currTime)/freq1 - (preSamples) / freq; } - else { 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 + trigFlags[currBlock] = trigReceived; } } } @@ -601,12 +656,12 @@ void rpadcStream(int fd, char *treeName, int shot, int chan1Nid, int chan2Nid, // endTimes[0] = (segmentIdx + 1) * segmentSamples / freq1; Gabriele Dec 2021 startTimes[0] = segmentIdx * segmentSamples / freq; endTimes[0] = (segmentIdx + 1) * segmentSamples / freq; + trigFlags[0] = 0; } segmentIdx++; - writeSegment(tree, chan1, chan2, trigger, dataSamples, startTimes, endTimes, - segmentSamples, blocksInSegment, freq, saveList); + writeSegment(tree, chan1, chan2, trigRecv, trigger, dataSamples, startTimes, endTimes, + segmentSamples, blocksInSegment, freq, saveList, trigFlags); } - std::cout << "ULTIMAO RPADCSTREAM\n"; } static void printConfig(struct rpadc_configuration *config) { @@ -637,8 +692,8 @@ 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"); + case TRIG_SYNC: + printf("\tclock_mode: TRIG_SYNC\n"); break; case EXTERNAL: printf("\tclock_mode: EXTERNAL\n"); @@ -664,12 +719,14 @@ static void printConfig(struct rpadc_configuration *config) printf("\tpost_samples: %d\n", config->post_samples); printf("\tdecimation: %d\n", config->decimation); printf("\tdeadtime: %d\n", config->deadtime); + printf("\toffsa: %d\n", config->offset & 0x0000ffff); + printf("\toffsb: %d\n", (config->offset >> 16) & 0x0000ffff); } // 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 deadtime) + int thresholdSamples, int decimation, int deadtime, int offsa, int offsb) { struct rpadc_configuration inConfig, outConfig; int fd = open("/dev/rfx_stream", O_RDWR | O_SYNC); @@ -695,7 +752,11 @@ int rpadcInit(int mode, int clock_mode, int preSamples, int postSamples, inConfig.pre_samples = preSamples; inConfig.post_samples = postSamples; // Watch!!!!! inConfig.decimation = decimation; - inConfig.deadtime = deadtime; + if(deadtime > preSamples) + inConfig.deadtime = deadtime; + else + inConfig.deadtime = preSamples; + inConfig.offset = (offsa & 0x0000FFFF)|((offsb << 16)&0xffff0000); printConfig(&inConfig); writeConfig(fd, &inConfig); memset(&outConfig, 0, sizeof(outConfig)); @@ -730,196 +791,9 @@ void openTree(char *name, int shot, MDSplus::Tree **treePtr) { *treePtr = new MDSplus::Tree(name, shot); } - catch (const MDSplus::MdsException &exc) + catch (MDSplus::MdsException &exc) { *treePtr = 0; } } -////////////////////Clock related stuff - - - - - - 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; -} - - -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, ®); -} - - - - -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; - } - else - { - *prevFreq = getFrequency(fd); - } - *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.c b/device_support/redpitaya/rfx_stream.c new file mode 100644 index 0000000000..fb181cad19 --- /dev/null +++ b/device_support/redpitaya/rfx_stream.c @@ -0,0 +1,1251 @@ +#define HAS_FIFO_INTERRUPT + + +#include +#include +#include +#include +#include + +#include +#include + +#include // put_user +#include + +#include + +#include + +#include +#include + +#include "rfx_stream.h" + +#include // dma api +#include // dma api +//#include // axi dma driver + + +#include +#include +#include +#include +#include +#include + +#define SUCCESS 0 +#define FIFO_LEN 16384 + +//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 MAX_DMA_BUFFERS 80 +#define DMA_BUFSIZE 1600000 + +struct rfx_stream_dev { + struct platform_device *pdev; + struct cdev cdev; + int busy; + int irq; + + void * iomap_cmd_reg; + void * iomap_command_register; + void * iomap_deadtime_register; + void * iomap_decimator_register; + void * iomap_k1_reg; + void * iomap_k2_reg; + void * iomap_lev_trig_count; + void * iomap_mode_register; + void * iomap_offset_reg; + void * iomap_packetizer; + void * iomap_post_register; + void * iomap_pre_register; + void * iomap_step_hi_reg; + void * iomap_step_lo_reg; + void * iomap_time_ofs_hi_reg; + void * iomap_time_ofs_lo_reg; + void * iomap_data_fifo; + void * iomap1_data_fifo; + void * iomap_time_fifo; + void * iomap1_time_fifo; + void * iomap_times_fifo; + void * iomap1_times_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 started; +#ifdef HAS_DMA + int dma_align; + struct dma_chan *dma_chan; + dma_addr_t dma_handles[MAX_DMA_BUFFERS]; + char *dma_buffers[MAX_DMA_BUFFERS]; + u32 dma_buf_sizes[MAX_DMA_BUFFERS]; + u32 num_dma_buffers; + u32 dma_tot_size; + u32 dma_allocated; + struct scatterlist dma_sg[MAX_DMA_BUFFERS]; + 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,TDFR,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 rfx_stream_dev *dev, struct dma_chan *chan, dma_addr_t *handles, size_t *lens, + struct scatterlist *sg, u32 num_dma_buffers, enum dma_transfer_direction dir) ; +static void dma_start_transfer(struct dma_chan *chan, struct completion *cmp, dma_cookie_t cookie); +#endif //HAS_DMA + +int writeBuf(struct rfx_stream_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 rfx_stream_dev *dev, u32 *buf, int nSamples, int check) +{ + int i; + spin_lock_irq(&dev->spinLock); + for(i = 0; i < nSamples; i++) + { + if(check && (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 rfx_stream_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 + +/* Handle a callback called when the DMA transfer is complete +*/ +static int dma_sync_callback(struct rfx_stream_dev *dev) +{ + int status, i; + struct task_struct *ts; + dma_cookie_t lastCookie; + printk("DMA SYNC CALLBACK %d \n", dev->num_dma_buffers); + + 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; + } + //Start a new DMA round if device still armed +/* printk("STATUS REGISTER: %d\n", *((u32 *)dev->iomap_status_register)); + if(*((u32 *)dev->iomap_status_register) == 0) //Always is!! + { + dev->dma_started = 0; + printk("DMA TERMINATED\n"); + return 0; + } */ + dev->dma_started = 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 rfx_stream_dev *dev, struct dma_chan *chan, dma_addr_t *handles, size_t *lens, + struct scatterlist *sg, u32 num_dma_buffers, enum dma_transfer_direction dir) +{ + int i; + //enum dma_ctrl_flags flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT; + enum dma_ctrl_flags flags = DMA_CTRL_ACK;// | DMA_PREP_INTERRUPT; + struct dma_async_tx_descriptor *chan_desc; + dma_cookie_t cookie; + set_user_nice(current, 10); + sg_init_table(sg, num_dma_buffers); + for(i = 0; i < num_dma_buffers; i++) + { + sg_dma_address(&sg[i]) = handles[i]; + sg_dma_len(&sg[i]) = lens[i]; + } +// chan_desc = dev->dma_chan->device->device_prep_slave_sg(chan, sg, num_dma_buffers, dir, flags, NULL); + chan_desc = dmaengine_prep_slave_sg(chan, sg, num_dma_buffers, 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; + 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) +{ + unsigned long timeout = msecs_to_jiffies(10000); + enum dma_status status; + + init_completion(cmp); + dma_async_issue_pending(chan); + +} +#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); +} + + +#ifdef HAS_FIFO_INTERRUPT + +static int checkFifo(struct rfx_stream_dev *dev) +{ + void* fifo = dev->iomap_data_fifo; + void* fifo1 = dev->iomap1_data_fifo; + + Write(dev->iomap_data_fifo,IER,0x00000000); //Disable FIFO interrupts + + u32 occ = Read(fifo,RDFO); + int i; + while(occ > 0) + { + u32 currSample = Read(fifo1,RDFD4); + if(writeBuf(dev, currSample) < 0) //In case of ADC FIFO overflow, abort data readout from FPGA + { + dev->fifoOverflow = 1; + return 0; + } + occ = Read(fifo,RDFO); + } + //Re-enable FIFO interrupts + if(dev->fifoHalfInterrupt) + Write(dev->iomap_data_fifo,IER,0x00100000); + else + Write(dev->iomap_data_fifo,IER,0x04000000); + return occ; +} + +#endif + + +// interrupt handler // +irqreturn_t IRQ_cb(int irq, void *dev_id, struct pt_regs *regs) { + struct rfx_stream_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++) + while(occ > 0) + { + 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; + } + occ = Read(fifo,RDFO); + } + 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 rfx_stream_dev *privateInfo = container_of(inode->i_cdev, struct rfx_stream_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 = FIFO_LEN; + privateInfo->fifoBuffer = (u32 *)kmalloc(privateInfo->bufSize * sizeof(u32), GFP_KERNEL); + privateInfo->dma_started = 0; +#ifdef HAS_FIFO_INTERRUPT + privateInfo->fifoOverflow = 0; + privateInfo->fifoHalfInterrupt = 0; +#endif + } + struct rfx_stream_dev *privateInfo = (struct rfx_stream_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 rfx_stream_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 rfx_stream_dev *dev = (struct rfx_stream_dev *)filp->private_data; + u32 *b32 = (u32*)buffer; +#ifdef HAS_FIFO_INTERRUPT + if(dev->fifoOverflow) + return -1; + checkFifo(dev); +#endif + while(dev->bufCount == 0) + { + if(filp->f_flags & O_NONBLOCK) + return -EAGAIN; + if(wait_event_interruptible(dev->readq, (dev->bufCount > 0 || dev->started == 0))) + return -ERESTARTSYS; + if(!dev->started) + return 0; + } + + 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 rfx_stream_dev *dev = file->private_data; + + switch (cmd) { +#ifdef HAS_DMA + case RFX_STREAM_ARM_DMA: + { + if(!dev->dma_allocated) + { + int i; + dma_addr_t currHandle; + for(i = 0; i < dev->num_dma_buffers; i++) + { + printk("ALLOC COHERENT %d\n", dev->dma_buf_sizes[i]); + dev->dma_buffers[i] = dma_alloc_coherent(dev->dma_chan->device->dev,dev->dma_buf_sizes[i],&dev->dma_handles[i],GFP_KERNEL); + printk("ALLOCATED COHERENT %p\n", dev->dma_buffers[i]); + printk("MAPPED %d\n", dev->dma_handles[i]); + } + dev->dma_allocated = 1; + } + return 0; + } + case RFX_STREAM_START_DMA: + { +//Start DMA if DMA buffer previusly allocated + if(!dev->dma_allocated) + return -1; + for(i = 0; i < dev->num_dma_buffers; i++) + { + memset(dev->dma_buffers[i], 0, dev->dma_buf_sizes[i]); + } + dev->dma_cookie = dma_prep_buffer(dev, dev->dma_chan, dev->dma_handles, dev->dma_buf_sizes, dev->dma_sg, + dev->num_dma_buffers, DMA_DEV_TO_MEM); + if (dma_submit_error(dev->dma_cookie) ) { + printk(KERN_ERR "dma_prep_buffer error\n"); + return -EIO; + } + printk(KERN_INFO "Starting DMA transfers. num dma buffers %d\n", dev->num_dma_buffers); + dma_start_transfer(dev->dma_chan, &dev->dma_cmp, dev->dma_cookie); + dev->dma_started = 1; + return 0; + } + case RFX_STREAM_STOP_DMA: + { + int status = dma_async_is_tx_complete(dev->dma_chan, dev->dma_cookie, + NULL, NULL); + if(status != DMA_COMPLETE) + printk("DMA ENGINE NOT STOPPED!!!!!!\n"); + dmaengine_terminate_all(dev->dma_chan); + dev->dma_started = 0; + return 0; + } + case RFX_STREAM_IS_DMA_RUNNING: + { + copy_to_user ((void __user *)arg, &dev->dma_started, sizeof(u32)); + return 0; + } + case RFX_STREAM_GET_DMA_BUFLEN: + { + copy_to_user ((void __user *)arg, &dev->dma_tot_size, sizeof(u32)); + return 0; + } + case RFX_STREAM_SET_DMA_BUFLEN: + { + u32 numDmaBuffers; + u32 dmaBuflen; + int i; + copy_from_user (&dmaBuflen, (void __user *)arg, sizeof(u32)); + if(dmaBuflen <= 0 || dmaBuflen > MAX_DMA_BUFFERS * DMA_BUFSIZE) + return -1; + if(dev->dma_tot_size != dmaBuflen) + { + if(dev->dma_allocated > 0) + { + for(i = 0; i < dev->num_dma_buffers; i++) + { + dma_free_coherent(dev->dma_chan->device->dev,dev->dma_buf_sizes[i],dev->dma_buffers[i],dev->dma_handles[i]); + } + dev->dma_allocated = 0; + } + } + dev->num_dma_buffers = dmaBuflen / DMA_BUFSIZE; + for(i = 0; i < dev->num_dma_buffers; i++) + dev->dma_buf_sizes[i] = DMA_BUFSIZE; + if(dmaBuflen % DMA_BUFSIZE) + { + dev->dma_buf_sizes[dev->num_dma_buffers] = dmaBuflen % DMA_BUFSIZE; + dev->num_dma_buffers++; + printk("LAST DMA SIZE: %d\n", dmaBuflen % DMA_BUFSIZE); + } + dev->dma_tot_size = dmaBuflen; + printk("NUM DMA BUFFERS: %d\n", dev->num_dma_buffers); + return 0; + } + case RFX_STREAM_GET_DMA_DATA: + { + int i; + if(!dev->dma_allocated) + return -1; + char *currPtr = (void __user *)arg; + for(i = 0; i < dev->num_dma_buffers; i++) + { + printk("COPYING %d %d\n", i, dev->dma_buf_sizes[i]); + copy_to_user ((void __user *)currPtr, dev->dma_buffers[i], dev->dma_buf_sizes[i]); + currPtr += dev->dma_buf_sizes[i]; + } + return 0; + } +#endif //HAS_DMA + + case RFX_STREAM_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 RFX_STREAM_GET_DRIVER_BUFLEN: + { + copy_to_user ((void __user *)arg, &dev->bufSize, sizeof(u32)); + return 0; + } + + case RFX_STREAM_GET_CMD_REG: + { + copy_to_user ((void __user *)arg, dev->iomap_cmd_reg, sizeof(u32)); + return 0; + } + case RFX_STREAM_SET_CMD_REG: + { + copy_from_user (dev->iomap_cmd_reg, (void __user *)arg, sizeof(u32)); + return 0; + } + case RFX_STREAM_GET_COMMAND_REGISTER: + { + copy_to_user ((void __user *)arg, dev->iomap_command_register, sizeof(u32)); + return 0; + } + case RFX_STREAM_SET_COMMAND_REGISTER: + { + copy_from_user (dev->iomap_command_register, (void __user *)arg, sizeof(u32)); + return 0; + } + case RFX_STREAM_GET_DEADTIME_REGISTER: + { + copy_to_user ((void __user *)arg, dev->iomap_deadtime_register, sizeof(u32)); + return 0; + } + case RFX_STREAM_SET_DEADTIME_REGISTER: + { + copy_from_user (dev->iomap_deadtime_register, (void __user *)arg, sizeof(u32)); + return 0; + } + case RFX_STREAM_GET_DECIMATOR_REGISTER: + { + copy_to_user ((void __user *)arg, dev->iomap_decimator_register, sizeof(u32)); + return 0; + } + case RFX_STREAM_SET_DECIMATOR_REGISTER: + { + copy_from_user (dev->iomap_decimator_register, (void __user *)arg, sizeof(u32)); + return 0; + } + case RFX_STREAM_GET_K1_REG: + { + copy_to_user ((void __user *)arg, dev->iomap_k1_reg, sizeof(u32)); + return 0; + } + case RFX_STREAM_SET_K1_REG: + { + copy_from_user (dev->iomap_k1_reg, (void __user *)arg, sizeof(u32)); + return 0; + } + case RFX_STREAM_GET_K2_REG: + { + copy_to_user ((void __user *)arg, dev->iomap_k2_reg, sizeof(u32)); + return 0; + } + case RFX_STREAM_SET_K2_REG: + { + copy_from_user (dev->iomap_k2_reg, (void __user *)arg, sizeof(u32)); + return 0; + } + case RFX_STREAM_GET_LEV_TRIG_COUNT: + { + copy_to_user ((void __user *)arg, dev->iomap_lev_trig_count, sizeof(u32)); + return 0; + } + case RFX_STREAM_SET_LEV_TRIG_COUNT: + { + copy_from_user (dev->iomap_lev_trig_count, (void __user *)arg, sizeof(u32)); + return 0; + } + case RFX_STREAM_GET_MODE_REGISTER: + { + copy_to_user ((void __user *)arg, dev->iomap_mode_register, sizeof(u32)); + return 0; + } + case RFX_STREAM_SET_MODE_REGISTER: + { + copy_from_user (dev->iomap_mode_register, (void __user *)arg, sizeof(u32)); + return 0; + } + case RFX_STREAM_GET_OFFSET_REG: + { + copy_to_user ((void __user *)arg, dev->iomap_offset_reg, sizeof(u32)); + return 0; + } + case RFX_STREAM_SET_OFFSET_REG: + { + copy_from_user (dev->iomap_offset_reg, (void __user *)arg, sizeof(u32)); + return 0; + } + case RFX_STREAM_GET_PACKETIZER: + { + copy_to_user ((void __user *)arg, dev->iomap_packetizer, sizeof(u32)); + return 0; + } + case RFX_STREAM_SET_PACKETIZER: + { + copy_from_user (dev->iomap_packetizer, (void __user *)arg, sizeof(u32)); + return 0; + } + case RFX_STREAM_GET_POST_REGISTER: + { + copy_to_user ((void __user *)arg, dev->iomap_post_register, sizeof(u32)); + return 0; + } + case RFX_STREAM_SET_POST_REGISTER: + { + copy_from_user (dev->iomap_post_register, (void __user *)arg, sizeof(u32)); + return 0; + } + case RFX_STREAM_GET_PRE_REGISTER: + { + copy_to_user ((void __user *)arg, dev->iomap_pre_register, sizeof(u32)); + return 0; + } + case RFX_STREAM_SET_PRE_REGISTER: + { + copy_from_user (dev->iomap_pre_register, (void __user *)arg, sizeof(u32)); + return 0; + } + case RFX_STREAM_GET_STEP_HI_REG: + { + copy_to_user ((void __user *)arg, dev->iomap_step_hi_reg, sizeof(u32)); + return 0; + } + case RFX_STREAM_SET_STEP_HI_REG: + { + copy_from_user (dev->iomap_step_hi_reg, (void __user *)arg, sizeof(u32)); + return 0; + } + case RFX_STREAM_GET_STEP_LO_REG: + { + copy_to_user ((void __user *)arg, dev->iomap_step_lo_reg, sizeof(u32)); + return 0; + } + case RFX_STREAM_SET_STEP_LO_REG: + { + copy_from_user (dev->iomap_step_lo_reg, (void __user *)arg, sizeof(u32)); + return 0; + } + case RFX_STREAM_GET_TIME_OFS_HI_REG: + { + copy_to_user ((void __user *)arg, dev->iomap_time_ofs_hi_reg, sizeof(u32)); + return 0; + } + case RFX_STREAM_SET_TIME_OFS_HI_REG: + { + copy_from_user (dev->iomap_time_ofs_hi_reg, (void __user *)arg, sizeof(u32)); + return 0; + } + case RFX_STREAM_GET_TIME_OFS_LO_REG: + { + copy_to_user ((void __user *)arg, dev->iomap_time_ofs_lo_reg, sizeof(u32)); + return 0; + } + case RFX_STREAM_SET_TIME_OFS_LO_REG: + { + copy_from_user (dev->iomap_time_ofs_lo_reg, (void __user *)arg, sizeof(u32)); + return 0; + } + case RFX_STREAM_GET_DATA_FIFO_LEN: + { + u32 val = readFifo(dev->iomap_data_fifo,RDFO); + copy_to_user ((void __user *)arg, &val, sizeof(u32)); + return 0; + } + case RFX_STREAM_GET_DATA_FIFO_VAL: + { + u32 val = readFifo(dev->iomap1_data_fifo,RDFD4); + copy_to_user ((void __user *)arg, &val, sizeof(u32)); + return 0; + } + case RFX_STREAM_SET_DATA_FIFO_VAL: + { + u32 val; + copy_from_user (&val, (void __user *)arg, sizeof(u32)); + writeFifo(dev->iomap1_data_fifo,0, val); + writeFifo(dev->iomap_data_fifo,TLR, 1); + return 0; + } + case RFX_STREAM_CLEAR_DATA_FIFO: + { + clearFifo(dev->iomap_data_fifo,dev->iomap1_data_fifo); + return 0; + } + case RFX_STREAM_GET_TIME_FIFO_LEN: + { + u32 val = readFifo(dev->iomap_time_fifo,RDFO); + copy_to_user ((void __user *)arg, &val, sizeof(u32)); + return 0; + } + case RFX_STREAM_GET_TIME_FIFO_VAL: + { + u32 val = readFifo(dev->iomap1_time_fifo,RDFD4); + copy_to_user ((void __user *)arg, &val, sizeof(u32)); + return 0; + } + case RFX_STREAM_SET_TIME_FIFO_VAL: + { + u32 val; + copy_from_user (&val, (void __user *)arg, sizeof(u32)); + writeFifo(dev->iomap1_time_fifo,0, val); + writeFifo(dev->iomap_time_fifo,TLR, 1); + return 0; + } + case RFX_STREAM_CLEAR_TIME_FIFO: + { + clearFifo(dev->iomap_time_fifo,dev->iomap1_time_fifo); + return 0; + } + case RFX_STREAM_GET_TIMES_FIFO_LEN: + { + u32 val = readFifo(dev->iomap_times_fifo,RDFO); + copy_to_user ((void __user *)arg, &val, sizeof(u32)); + return 0; + } + case RFX_STREAM_GET_TIMES_FIFO_VAL: + { + u32 val = readFifo(dev->iomap1_times_fifo,RDFD4); + copy_to_user ((void __user *)arg, &val, sizeof(u32)); + return 0; + } + case RFX_STREAM_SET_TIMES_FIFO_VAL: + { + u32 val; + copy_from_user (&val, (void __user *)arg, sizeof(u32)); + writeFifo(dev->iomap1_times_fifo,0, val); + writeFifo(dev->iomap_times_fifo,TLR, 1); + return 0; + } + case RFX_STREAM_CLEAR_TIMES_FIFO: + { + clearFifo(dev->iomap_times_fifo,dev->iomap1_times_fifo); + return 0; + } + case RFX_STREAM_GET_REGISTERS: + { + struct rfx_stream_registers currConf; + memset(&currConf, 0, sizeof(currConf)); + currConf.cmd_reg = *((u32 *)dev->iomap_cmd_reg); + currConf.command_register = *((u32 *)dev->iomap_command_register); + currConf.deadtime_register = *((u32 *)dev->iomap_deadtime_register); + currConf.decimator_register = *((u32 *)dev->iomap_decimator_register); + currConf.k1_reg = *((u32 *)dev->iomap_k1_reg); + currConf.k2_reg = *((u32 *)dev->iomap_k2_reg); + currConf.lev_trig_count = *((u32 *)dev->iomap_lev_trig_count); + currConf.mode_register = *((u32 *)dev->iomap_mode_register); + currConf.offset_reg = *((u32 *)dev->iomap_offset_reg); + currConf.packetizer = *((u32 *)dev->iomap_packetizer); + currConf.post_register = *((u32 *)dev->iomap_post_register); + currConf.pre_register = *((u32 *)dev->iomap_pre_register); + currConf.step_hi_reg = *((u32 *)dev->iomap_step_hi_reg); + currConf.step_lo_reg = *((u32 *)dev->iomap_step_lo_reg); + currConf.time_ofs_hi_reg = *((u32 *)dev->iomap_time_ofs_hi_reg); + currConf.time_ofs_lo_reg = *((u32 *)dev->iomap_time_ofs_lo_reg); + copy_to_user ((void __user *)arg, &currConf, sizeof(currConf)); + } + case RFX_STREAM_SET_REGISTERS: + { + struct rfx_stream_registers currConf; + copy_from_user (&currConf, (void __user *)arg, sizeof(currConf)); + if(currConf.cmd_reg_enable) + *((u32 *)dev->iomap_cmd_reg) = currConf.cmd_reg; + if(currConf.command_register_enable) + *((u32 *)dev->iomap_command_register) = currConf.command_register; + if(currConf.deadtime_register_enable) + *((u32 *)dev->iomap_deadtime_register) = currConf.deadtime_register; + if(currConf.decimator_register_enable) + *((u32 *)dev->iomap_decimator_register) = currConf.decimator_register; + if(currConf.k1_reg_enable) + *((u32 *)dev->iomap_k1_reg) = currConf.k1_reg; + if(currConf.k2_reg_enable) + *((u32 *)dev->iomap_k2_reg) = currConf.k2_reg; + if(currConf.lev_trig_count_enable) + *((u32 *)dev->iomap_lev_trig_count) = currConf.lev_trig_count; + if(currConf.mode_register_enable) + *((u32 *)dev->iomap_mode_register) = currConf.mode_register; + if(currConf.offset_reg_enable) + *((u32 *)dev->iomap_offset_reg) = currConf.offset_reg; + 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.step_hi_reg_enable) + *((u32 *)dev->iomap_step_hi_reg) = currConf.step_hi_reg; + if(currConf.step_lo_reg_enable) + *((u32 *)dev->iomap_step_lo_reg) = currConf.step_lo_reg; + if(currConf.time_ofs_hi_reg_enable) + *((u32 *)dev->iomap_time_ofs_hi_reg) = currConf.time_ofs_hi_reg; + if(currConf.time_ofs_lo_reg_enable) + *((u32 *)dev->iomap_time_ofs_lo_reg) = currConf.time_ofs_lo_reg; + } + + + #ifdef HAS_FIFO_INTERRUPT + + case RFX_STREAM_FIFO_INT_HALF_SIZE: + dev->fifoHalfInterrupt = 1; + Write(dev->iomap_data_fifo,IER,0x00100000); + return 0; + case RFX_STREAM_FIFO_INT_FIRST_SAMPLE: + dev->fifoHalfInterrupt = 0; + Write(dev->iomap_data_fifo,IER,0x04000000); + return 0; + case RFX_STREAM_FIFO_FLUSH: + IRQ_cb(0, dev, 0); + // Write(dev->iomap_data_fifo,IER,0x04000000); + case RFX_STREAM_START_READ: + dev->started = 1; + return 0; + case RFX_STREAM_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 rfx_stream_dev *dev = (struct rfx_stream_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 *rfx_stream_class; +static struct rfx_stream_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 ,"rfx_stream",&staticPrivateInfo); + if(res) + printk(KERN_INFO "rfx_stream: can't get IRQ %d assigned\n",staticPrivateInfo.irq); + else + printk(KERN_INFO "rfx_stream: got IRQ %d assigned\n",staticPrivateInfo.irq); +} +#endif + + + + + + +static int rfx_stream_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("rfx_stream_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); + + rfx_stream_class = class_create(THIS_MODULE, DEVICE_NAME); + if (IS_ERR(rfx_stream_class)) + return PTR_ERR(rfx_stream_class); + + device_create(rfx_stream_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_tot_size = 0; + staticPrivateInfo.dma_allocated = 0; + staticPrivateInfo.dma_chan = NULL; + //Declare DMA Channel + printk("REQUEST DMA\n"); + 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; + } + printk("GOT DMA %p\n", staticPrivateInfo.dma_chan); +#endif //HAS_DMA + r_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + off = r_mem->start & ~PAGE_MASK; + staticPrivateInfo.iomap_cmd_reg = devm_ioremap(&pdev->dev,r_mem->start+off,0xffff); + + + } + else //Further calls for memory resources + { + printk("FOLLOWING CALL TO rfx_rfx_stream_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 1: + 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); break; + case 2: + 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 3: + r_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + off = r_mem->start & ~PAGE_MASK; + staticPrivateInfo.iomap_deadtime_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_decimator_register = 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_k1_reg = 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_k2_reg = 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_lev_trig_count = 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_mode_register = devm_ioremap(&pdev->dev,r_mem->start+off,0xffff); break; + case 9: + r_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + off = r_mem->start & ~PAGE_MASK; + staticPrivateInfo.iomap_offset_reg = devm_ioremap(&pdev->dev,r_mem->start+off,0xffff); break; + case 10: + 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 11: + 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 12: + 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 13: + r_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + off = r_mem->start & ~PAGE_MASK; + staticPrivateInfo.iomap_step_hi_reg = devm_ioremap(&pdev->dev,r_mem->start+off,0xffff); break; + case 14: + r_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + off = r_mem->start & ~PAGE_MASK; + staticPrivateInfo.iomap_step_lo_reg = devm_ioremap(&pdev->dev,r_mem->start+off,0xffff); break; + case 15: + 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 16: + r_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + off = r_mem->start & ~PAGE_MASK; + staticPrivateInfo.iomap_time_ofs_hi_reg = devm_ioremap(&pdev->dev,r_mem->start+off,0xffff); break; + case 17: + r_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + off = r_mem->start & ~PAGE_MASK; + staticPrivateInfo.iomap_time_ofs_lo_reg = devm_ioremap(&pdev->dev,r_mem->start+off,0xffff); break; + case 18: + r_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + off = r_mem->start & ~PAGE_MASK; + staticPrivateInfo.iomap_times_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_times_fifo = devm_ioremap(&pdev->dev,r_mem->start+off,0xffff); + break; + + + default: printk("ERROR: Unexpected rfx_stream_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 rfx_stream_remove(struct platform_device *pdev) +{ + printk("PLATFORM DEVICE REMOVE...\n"); + if(rfx_stream_class) { + device_destroy(rfx_stream_class,MKDEV(id_major, 0)); + class_destroy(rfx_stream_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 rfx_stream_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 rfx_stream_driver = { + .driver = { + .name = MODULE_NAME, + .owner = THIS_MODULE, + .of_match_table = rfx_stream_of_ids, + }, + .probe = rfx_stream_probe, + .remove = rfx_stream_remove, +}; + +static int __init rfx_stream_init(void) +{ + printk(KERN_INFO "inizializing AXI module ...\n"); + deviceAllocated = 0; + return platform_driver_register(&rfx_stream_driver); +} + +static void __exit rfx_stream_exit(void) +{ + printk(KERN_INFO "exiting AXI module ...\n"); + platform_driver_unregister(&rfx_stream_driver); +} + +module_init(rfx_stream_init); +module_exit(rfx_stream_exit); +MODULE_LICENSE("GPL"); diff --git a/device_support/redpitaya/rfx_stream.h b/device_support/redpitaya/rfx_stream.h index c3edf68591..958efb9801 100644 --- a/device_support/redpitaya/rfx_stream.h +++ b/device_support/redpitaya/rfx_stream.h @@ -38,8 +38,8 @@ 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_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_CMD_REG _IO(RFX_STREAM_IOCTL_BASE, 20) +#define RFX_STREAM_SET_CMD_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_DEADTIME_REGISTER _IO(RFX_STREAM_IOCTL_BASE, 24) @@ -54,34 +54,34 @@ extern "C" { #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_OFFSET_REG _IO(RFX_STREAM_IOCTL_BASE, 36) +#define RFX_STREAM_SET_OFFSET_REG _IO(RFX_STREAM_IOCTL_BASE, 37) +#define RFX_STREAM_GET_PACKETIZER _IO(RFX_STREAM_IOCTL_BASE, 38) +#define RFX_STREAM_SET_PACKETIZER _IO(RFX_STREAM_IOCTL_BASE, 39) +#define RFX_STREAM_GET_POST_REGISTER _IO(RFX_STREAM_IOCTL_BASE, 40) +#define RFX_STREAM_SET_POST_REGISTER _IO(RFX_STREAM_IOCTL_BASE, 41) +#define RFX_STREAM_GET_PRE_REGISTER _IO(RFX_STREAM_IOCTL_BASE, 42) +#define RFX_STREAM_SET_PRE_REGISTER _IO(RFX_STREAM_IOCTL_BASE, 43) +#define RFX_STREAM_GET_STEP_HI_REG _IO(RFX_STREAM_IOCTL_BASE, 44) +#define RFX_STREAM_SET_STEP_HI_REG _IO(RFX_STREAM_IOCTL_BASE, 45) +#define RFX_STREAM_GET_STEP_LO_REG _IO(RFX_STREAM_IOCTL_BASE, 46) +#define RFX_STREAM_SET_STEP_LO_REG _IO(RFX_STREAM_IOCTL_BASE, 47) +#define RFX_STREAM_GET_TIME_OFS_HI_REG _IO(RFX_STREAM_IOCTL_BASE, 48) +#define RFX_STREAM_SET_TIME_OFS_HI_REG _IO(RFX_STREAM_IOCTL_BASE, 49) +#define RFX_STREAM_GET_TIME_OFS_LO_REG _IO(RFX_STREAM_IOCTL_BASE, 50) +#define RFX_STREAM_SET_TIME_OFS_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) +#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_SET_TIME_FIFO_VAL _IO(RFX_STREAM_IOCTL_BASE, 58) +#define RFX_STREAM_CLEAR_TIME_FIFO _IO(RFX_STREAM_IOCTL_BASE, 59) +#define RFX_STREAM_GET_TIMES_FIFO_LEN _IO(RFX_STREAM_IOCTL_BASE, 60) +#define RFX_STREAM_GET_TIMES_FIFO_VAL _IO(RFX_STREAM_IOCTL_BASE, 61) +#define RFX_STREAM_SET_TIMES_FIFO_VAL _IO(RFX_STREAM_IOCTL_BASE, 62) +#define RFX_STREAM_CLEAR_TIMES_FIFO _IO(RFX_STREAM_IOCTL_BASE, 63) #ifndef AXI_ENUMS_DEFINED @@ -141,8 +141,8 @@ enum RegisterIdx { struct rfx_stream_registers { - char aux_mode_reg_enable; - unsigned int aux_mode_reg; + char cmd_reg_enable; + unsigned int cmd_reg; char command_register_enable; unsigned int command_register; char deadtime_register_enable; @@ -157,6 +157,8 @@ struct rfx_stream_registers unsigned int lev_trig_count; char mode_register_enable; unsigned int mode_register; + char offset_reg_enable; + unsigned int offset_reg; char packetizer_enable; unsigned int packetizer; char post_register_enable; @@ -167,12 +169,10 @@ struct rfx_stream_registers unsigned int step_hi_reg; char step_lo_reg_enable; unsigned int step_lo_reg; - char time_command_reg_enable; - unsigned int time_command_reg; - char time_offset_hi_reg_enable; - unsigned int time_offset_hi_reg; - char time_offset_lo_reg_enable; - unsigned int time_offset_lo_reg; + char time_ofs_hi_reg_enable; + unsigned int time_ofs_hi_reg; + char time_ofs_lo_reg_enable; + unsigned int time_ofs_lo_reg; }; diff --git a/device_support/redpitaya/rfx_stream_0.1.bit b/device_support/redpitaya/rfx_stream_0.1.bit index fa48257f12..b1a5b98a39 100644 Binary files a/device_support/redpitaya/rfx_stream_0.1.bit and b/device_support/redpitaya/rfx_stream_0.1.bit differ diff --git a/device_support/redpitaya/sync_clock.c b/device_support/redpitaya/sync_clock.c index 8f430e0396..f1342cc2bf 100644 --- a/device_support/redpitaya/sync_clock.c +++ b/device_support/redpitaya/sync_clock.c @@ -69,12 +69,12 @@ static void setFrequency(int fd, double reqFreq) ioctl(fd, RFX_STREAM_SET_STEP_HI_REG, &stepHi); reg = 0; - ioctl(fd, RFX_STREAM_SET_TIME_COMMAND_REG, ®); + ioctl(fd, RFX_STREAM_SET_CMD_REG, ®); usleep(1000); reg = 1; - ioctl(fd, RFX_STREAM_SET_TIME_COMMAND_REG, ®); + ioctl(fd, RFX_STREAM_SET_CMD_REG, ®); reg = 0; - ioctl(fd, RFX_STREAM_SET_TIME_COMMAND_REG, ®); + ioctl(fd, RFX_STREAM_SET_CMD_REG, ®); } @@ -85,20 +85,20 @@ 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); + ioctl(fd, RFX_STREAM_CLEAR_TIMES_FIFO, 0); reg = 0; - ioctl(fd, RFX_STREAM_SET_TIME_COMMAND_REG, ®); + ioctl(fd, RFX_STREAM_SET_CMD_REG, ®); reg = 2; - ioctl(fd, RFX_STREAM_SET_TIME_COMMAND_REG, ®); + ioctl(fd, RFX_STREAM_SET_CMD_REG, ®); reg = 0; - ioctl(fd, RFX_STREAM_SET_TIME_COMMAND_REG, ®); + ioctl(fd, RFX_STREAM_SET_CMD_REG, ®); len = -1; usleep(10); - ioctl(fd, RFX_STREAM_GET_SYNC_FIFO_LEN, &len); + ioctl(fd, RFX_STREAM_GET_TIMES_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); + ioctl(fd, RFX_STREAM_GET_TIMES_FIFO_VAL, &lo); + ioctl(fd, RFX_STREAM_GET_TIMES_FIFO_VAL, &hi); @@ -118,18 +118,18 @@ static void setTime(int fd, unsigned long long timeUs, double actFreq) //Reset offset register reg = 0; - ioctl(fd, RFX_STREAM_SET_TIME_OFFSET_HI_REG, ®); - ioctl(fd, RFX_STREAM_SET_TIME_OFFSET_LO_REG, ®); + ioctl(fd, RFX_STREAM_SET_TIME_OFS_HI_REG, ®); + ioctl(fd, RFX_STREAM_SET_TIME_OFS_LO_REG, ®); fpgaTime = getTime(fd, actFreq); ofsTime = round((timeUs - fpgaTime)*actFreq / 1E6); reg = ofsTime & 0x00000000FFFFFFFFL; - ioctl(fd, RFX_STREAM_SET_TIME_OFFSET_LO_REG, ®); + ioctl(fd, RFX_STREAM_SET_TIME_OFS_LO_REG, ®); reg = (ofsTime >> 32) & 0x00000000FFFFFFFFL; - ioctl(fd, RFX_STREAM_SET_TIME_OFFSET_HI_REG, ®); + ioctl(fd, RFX_STREAM_SET_TIME_OFS_HI_REG, ®); - ioctl(fd, RFX_STREAM_GET_TIME_OFFSET_LO_REG, ®1); - ioctl(fd, RFX_STREAM_GET_TIME_OFFSET_HI_REG, ®2); + ioctl(fd, RFX_STREAM_GET_TIME_OFS_LO_REG, ®1); + ioctl(fd, RFX_STREAM_GET_TIME_OFS_HI_REG, ®2); diff --git a/java/jdevices/src/main/java/RFX_RPADCSetup.java b/java/jdevices/src/main/java/RFX_RPADCSetup.java index 79492a9b3b..3ad0b9cd92 100644 --- a/java/jdevices/src/main/java/RFX_RPADCSetup.java +++ b/java/jdevices/src/main/java/RFX_RPADCSetup.java @@ -62,7 +62,7 @@ private void initComponents() { jPanel5 = new javax.swing.JPanel(); deviceField5 = new DeviceField(); - setDeviceProvider("localhost:8000"); + setDeviceProvider("localhost:8100"); setDeviceTitle("RedPitaya ADC"); setDeviceType("RFX_RPADC"); setHeight(300); @@ -116,7 +116,7 @@ private void initComponents() { jPanel1.add(jPanel4); - deviceChoice4.setChoiceItems(new String[] {"INTERNAL", "TRIG_EXTERNAL", "EXTERNAL", "HIGHWAY"}); + deviceChoice4.setChoiceItems(new String[] {"INTERNAL", "TRIG_EXTERNAL", "EXTERNAL", "TRIG_SYNC", "SYNC"}); deviceChoice4.setIdentifier(""); deviceChoice4.setLabelString("Clock Mode:"); deviceChoice4.setOffsetNid(14); @@ -178,7 +178,7 @@ private void initComponents() { deviceField13.setIdentifier(""); deviceField13.setLabelString("Offset A (raw):"); deviceField13.setNumCols(6); - deviceField13.setOffsetNid(35); + deviceField13.setOffsetNid(21); jPanel9.add(deviceField13); deviceField14.setIdentifier(""); diff --git a/java/jdevices/src/main/resources/RFX_RPADCSetup.form b/java/jdevices/src/main/resources/RFX_RPADCSetup.form index 7614b2500a..5ce92f2268 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 @@ - + - + + diff --git a/pydevices/RfxDevices/RFX_RPADC.py b/pydevices/RfxDevices/RFX_RPADC.py index 5070884836..3876dd8804 100644 --- a/pydevices/RfxDevices/RFX_RPADC.py +++ b/pydevices/RfxDevices/RFX_RPADC.py @@ -199,17 +199,21 @@ def init(self): frequency = 125E6/decimation elif self.clock_mode.data() == 'SYNC': frequency = 1E6 / decimation - frequency1 = 1E6 + frequency1 = 1E6 / decimation elif self.clock_mode.data() == 'TRIG_EXTERNAL': period = Data.execute( 'slope_of($)', self.ext_clock) frequency1 = 1./period frequency = 125E6 / decimation - else: #EXTERNAL + elif self.clock_mode.data() == 'EXTERNAL': period = Data.execute( 'slope_of($)', self.ext_clock) frequency1 = 1./period frequency = frequency1 / decimation + else: + print('Invalid clock mode') + raise mdsExceptions.TclFAILED_ESSENTIAL + except: print('Cannot resolve external clock') raise mdsExceptions.TclFAILED_ESSENTIAL diff --git a/pydevices/RfxDevices/RFX_TRIGUART.py b/pydevices/RfxDevices/RFX_TRIGUART.py new file mode 100644 index 0000000000..bf625f72b8 --- /dev/null +++ b/pydevices/RfxDevices/RFX_TRIGUART.py @@ -0,0 +1,134 @@ +import MDSplus +import threading +import time +from ctypes import CDLL, c_int, c_double, c_char_p, byref, c_byte + + +class RFX_TRIGUART(MDSplus.Device): + parts = [{'path': ':COMMENT', 'type': 'text'}, + {'path': ':HI_DIV', 'type': 'numeric', 'value': 500}, + {'path': ':LO_DIV', 'type': 'numeric', 'value': 500}, + {'path': ':SEG_SIZE', 'type': 'numeric', 'value': 1000}, + {'path': ':TRIG_TIME', 'type': 'numeric', 'value': 0.}, + {'path': ':CHAN_1', 'type': 'signal'}, + {'path': ':CHAN_2', 'type': 'signal'}, + {'path': ':CHAN_3', 'type': 'signal'}, + {'path': ':CHAN_4', 'type': 'signal'}, + {'path': ':CHAN_5', 'type': 'signal'}] + + stopped = {} + workers = {} + fds = {} + + class AsynchStore(threading.Thread): + def configure(self, lib, nid, segLen, chanNodes, startTime, period): + self.nid = nid + self.lib = lib + self.segLen = segLen + self.startTime = startTime + self.period = period + self.chanNodes = [] + for chan in range(5): + self.chanNodes.append(chanNodes[chan].copy()) + + + + def run(self): + self.segmentCount = 0 + #When awakened, device has been triggered + fd = self.lib.rpuartStartStore() + DataArray = c_byte * self.segLen + rawChan = [] + rawChan.append(DataArray()) + rawChan.append(DataArray()) + rawChan.append(DataArray()) + rawChan.append(DataArray()) + rawChan.append(DataArray()) + + while not RFX_TRIGUART.stopped[self.nid]: + self.lib.rpuartGetSegment(c_int(fd), c_int(self.segLen), byref(rawChan[0]), byref(rawChan[1]), + byref(rawChan[2]), byref(rawChan[3]), byref(rawChan[4])) + startTime = MDSplus.Float64(self.startTime + self.segmentCount * self.segLen * self.period) + endTime = MDSplus.Float64(self.startTime + (self.segmentCount + 1) * self.segLen * self.period) + dim = MDSplus.Range(startTime, endTime, MDSplus.Float64(self.period)) + for chan in range(5): + data = MDSplus.Int8Array(rawChan[chan]) + self.chanNodes[chan].makeSegment(startTime, endTime, dim, data) + print('SEGMENT APPENDED') + self.segmentCount += 1 + self.lib.rpuartStopStore(c_int(fd)) + + def init(self): + print('================= RPUART Init ===============') + try: + lib = CDLL("libredpitaya.so") + print('library loaded') + except: + print('Cannot load redpitaya.so') + raise MDSplus.mdsExceptions.TclFAILED_ESSENTIAL + try: + hiDiv = self.hi_div.data() + except: + print('Cannot get high divisions') + raise MDSplus.mdsExceptions.TclFAILED_ESSENTIAL + try: + loDiv = self.lo_div.data() + except: + print('Cannot get low divisions') + raise MDSplus.mdsExceptions.TclFAILED_ESSENTIAL + + status = lib.rpuartInit(c_int(hiDiv), c_int(loDiv)) + if status < 0: + print("Error initializing device") + raise MDSplus.mdsExceptions.TclFAILED_ESSENTIAL + RFX_TRIGUART.fds[self.getNid()] = -1 + + def trigger(self): + lib = CDLL("libredpitaya.so") + try: + fd = RFX_TRIGUART.fds[self.nid] + except: + fd = -1 + if fd > 0: #Device already open by readout thread + lib.rpuartTriggerFd(c_int(fd)) + else: + lib.rpuartTrigger() + + def start_store(self): + worker = self.AsynchStore() + lib = CDLL("libredpitaya.so") + nid = self.getNid() + segLen = self.seg_size.data() + self.chan_1.deleteData() + self.chan_2.deleteData() + self.chan_3.deleteData() + self.chan_4.deleteData() + self.chan_5.deleteData() + chanNodes=[] + chanNodes.append(self.chan_1) + chanNodes.append(self.chan_2) + chanNodes.append(self.chan_3) + chanNodes.append(self.chan_4) + chanNodes.append(self.chan_5) + startTime = self.trig_time.data() + period = (self.hi_div.data() + self.lo_div.data()) * 1E-6 + worker.configure(lib, nid, segLen, chanNodes, startTime, period) + RFX_TRIGUART.workers[nid] = worker + RFX_TRIGUART.stopped[nid] = False + + worker.start() + + def stop_store(self): + try: + worker = RFX_TRIGUART.workers[self.getNid()] + RFX_TRIGUART.stopped[self.getNid()] = True + print('Waiting worker to stop....') + worker.join() + print('Worker done') + except: + print('Cannot get worker') + raise MDSplus.mdsExceptions.TclFAILED_ESSENTIAL + + + + \ No newline at end of file