From 182480dff23ee906c47421f534001a1ce40469a6 Mon Sep 17 00:00:00 2001 From: Bernardo Carvalho Date: Sun, 14 Apr 2024 17:21:58 +0100 Subject: [PATCH] Initial import Signed-off-by: Bernardo Carvalho --- Analysis/getMdsData.py | 47 + Analysis/pyqtPlotMds.py | 99 ++ Configurations/EPICS-isttok.db | 56 + Configurations/RTApp-AtcaIop.cfg | 1531 +++++++++++++++++ DataSources/AtcaIop/AtcaIopADC.cpp | 734 ++++++++ DataSources/AtcaIop/AtcaIopADC.h | 435 +++++ DataSources/AtcaIop/AtcaIopDAC.cpp | 374 ++++ DataSources/AtcaIop/AtcaIopDAC.h | 236 +++ DataSources/AtcaIop/Makefile.cov | 28 + DataSources/AtcaIop/Makefile.gcc | 27 + DataSources/AtcaIop/Makefile.inc | 54 + .../AtcaIop/include/atca-v6-iop-ioctl.h | 93 + Startup/AtcaIop.sh | 78 + Startup/ClearIsttokMDSTree.tcl | 4 + Startup/CreateIsttokMDSplusTree.tcl | 111 ++ 15 files changed, 3907 insertions(+) create mode 100644 Analysis/getMdsData.py create mode 100644 Analysis/pyqtPlotMds.py create mode 100644 Configurations/EPICS-isttok.db create mode 100644 Configurations/RTApp-AtcaIop.cfg create mode 100644 DataSources/AtcaIop/AtcaIopADC.cpp create mode 100644 DataSources/AtcaIop/AtcaIopADC.h create mode 100644 DataSources/AtcaIop/AtcaIopDAC.cpp create mode 100644 DataSources/AtcaIop/AtcaIopDAC.h create mode 100644 DataSources/AtcaIop/Makefile.cov create mode 100644 DataSources/AtcaIop/Makefile.gcc create mode 100644 DataSources/AtcaIop/Makefile.inc create mode 100644 DataSources/AtcaIop/include/atca-v6-iop-ioctl.h create mode 100755 Startup/AtcaIop.sh create mode 100644 Startup/ClearIsttokMDSTree.tcl create mode 100644 Startup/CreateIsttokMDSplusTree.tcl diff --git a/Analysis/getMdsData.py b/Analysis/getMdsData.py new file mode 100644 index 0000000..9282f77 --- /dev/null +++ b/Analysis/getMdsData.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python3 +""" +Extract data from MDSplus and plot +""" +import sys +import numpy as np +import matplotlib.pyplot as plt +from MDSplus import Tree + +mdsTreeName = 'rtappisttok' + +if len(sys.argv) > 1: + mdsPulseNumber = int(sys.argv[1]) +else: + mdsPulseNumber = 1 + #treename = '' + +try: + tree = Tree(mdsTreeName, mdsPulseNumber) +except: + print(f'Failed opening {mdsTreeName} for pulse number {mdsPulseNumber:d}') + exit() +""" +Available Channels + +ATCAIOP1.ADC0RAW +ATCAIOP1.ADC1RAW +ATCAIOP1.ADC2RAW +ATCAIOP1.ADC3RAW +ATCAIOP1.ADC4RAW +ATCAIOP1.ADC5RAW +ATCAIOP1.ADC6RAW +ATCAIOP1.ADC7RAW + +ATCAIOP1.ADC0INT +ATCAIOP1.ADC1INT + +""" + +if __name__ == '__main__': + mdsNode = tree.getNode("ATCAIOP1.ADC0RAW") + mdsNode = tree.getNode("ATCAIOP1.ADC1INT") + dataAdc = mdsNode.getData().data() + timeData = mdsNode.getDimensionAt(0).data() + + + diff --git a/Analysis/pyqtPlotMds.py b/Analysis/pyqtPlotMds.py new file mode 100644 index 0000000..c7fd579 --- /dev/null +++ b/Analysis/pyqtPlotMds.py @@ -0,0 +1,99 @@ +""" +This example demonstrates many of the 2D plotting capabilities +in pyqtgraph. All of the plots may be panned/scaled by dragging with +the left/right mouse buttons. Right click on any plot to show a context menu. +""" + +#import sys +import numpy as np + +import pyqtgraph as pg +from pyqtgraph.Qt import QtCore +from MDSplus import Tree +import argparse + +app = pg.mkQApp("Plotting MARTe2 Data") +#mw = QtWidgets.QMainWindow() +#mw.resize(800,800) + +MAX_SAMPLES = 50000 +ADC_CHANNELS = 4 +DECIM_RATE = 200 + +parser = argparse.ArgumentParser(description = 'Script to support the QA activities') + + #parser.add_argument('-l','--list', nargs='+', help=' Set flag', required=True) + #parser.add_argument('-l','--list', nargs='+') +parser.add_argument('-c', '--crange', nargs='+',type=int, help='Channel lines (0 4 )',default=[0, 4]) +parser.add_argument('-i', '--irange', nargs='+',type=int,default=[0, 4]) +#parser.add_argument('pulse','-', nargs='+', help=' Set flag', required=True) +parser.add_argument('-s', '--shot', type=int, help='Mds+ pulse Number ([0, ...])', default=100) +parser.add_argument('-m', '--maxsamples', type=int, help='Max samples to plot', default=50000) +parser.add_argument('-z', '--zero', action='store_true',help='Zero integral Lines') #, default='') + +args = parser.parse_args() +mdsPulseNumber = args.shot + +#if len(sys.argv) > 1: +# mdsPulseNumber = int(sys.argv[1]) +#else: +# mdsPulseNumber = 1 +# #treename = '' + +mdsTreeName = 'rtappisttok' + +try: + tree = Tree(mdsTreeName, mdsPulseNumber) +except: + print(f'Failed opening {mdsTreeName} for pulse number {mdsPulseNumber:d}') + exit() + +#time = dataCsv['#Time (uint32)[1]'] +#timeRel = time - time[0] +#x = DECIM_RATE * np.arange(len(vals)) + +win = pg.GraphicsLayoutWidget(show=True, title="Basic plotting examples") +win.resize(1000,600) +win.setWindowTitle('pyqtgraph example: Plotting') + +# Enable antialiasing for prettier plots +pg.setConfigOptions(antialias=True) + +p1 = win.addPlot(title="ATCA ADC raw decim") +# add plt.addLegend() BEFORE you create the curves. +mdsNode = tree.getNode("ATCAIOP1.ADC0RAW") +dataAdc = mdsNode.getData().data() +timeData = mdsNode.getDimensionAt(0).data() +p1.addLegend() +for i in range(args.crange[0], args.crange[1]): + mdsNode = tree.getNode(f"ATCAIOP1.ADC{i}RAW") + dataAdc = mdsNode.getData().data() + timeData = mdsNode.getDimensionAt(0).data() + #y = dataAdc[ :args.maxsamples, 0] + y = dataAdc[ :MAX_SAMPLES, 0] + x = DECIM_RATE * np.arange(len(y)) / 2.0e6 + p1.plot(x,y, pen=pg.mkPen(i, width=2), name=f"Ch {i}") +#p1.setLabel('bottom', "Y Axis", units='s') + +win.nextRow() +p4 = win.addPlot(title="ATCA Integral Channels") +p4.addLegend() +#for i in range(8,12): +for i in range(args.irange[0], args.irange[1]): + mdsNode = tree.getNode(f"ATCAIOP1.ADC{i}INT") + dataAdcInt = mdsNode.getData().data() + timeData = mdsNode.getDimensionAt(0).data() + y = dataAdcInt[ :args.maxsamples, 0] + if(args.zero): + y = y - dataAdcInt[0, 0] + #x = DECIM_RATE * np.arange(len(y)) + x = DECIM_RATE * np.arange(len(y)) / 2.0e6 + p4.plot(x,y, pen=pg.mkPen(i, width=2), name=f"Ch {i}") + +p4.setLabel('bottom', "Time", units='s') + +#updatePlot() + +if __name__ == '__main__': + pg.exec() +# vim: syntax=python ts=4 sw=4 sts=4 sr et diff --git a/Configurations/EPICS-isttok.db b/Configurations/EPICS-isttok.db new file mode 100644 index 0000000..2a167b4 --- /dev/null +++ b/Configurations/EPICS-isttok.db @@ -0,0 +1,56 @@ +#record( longin, "ISTTOK:marte2:STATUS") +#{ +# field(DTYP, "Soft Channel") +#} + +#record( longin, "ISTTOK:marte2:COMMAND") +#{ +# field(DTYP, "Soft Channel") +#} + +#record( longin, "ISTTOK:marte2:RESET") +#{ +# field(DTYP, "Soft Channel") +#} + +#record( ai, "ISTTOK:marte2:MEASUREMENT0") +#{ +# field(DTYP, "Soft Channel") +#} + +record( waveform, "ISTTOK:marte2:HIST-IDLE-CT") +{ + field(DTYP, "Soft Channel") + field(NELM, 10) + field(FTVL, "LONG") +} +record( waveform, "ISTTOK:marte2:HIST-RUN-CT") +{ + field(DTYP, "Soft Channel") + field(NELM, 10) + field(FTVL, "LONG") +} + +record( longin, "ISTTOK:marte2:TIME") +{ + field(DTYP, "Soft Channel") +} + +record( longin, "ISTTOK:marte2:COUNTER") +{ + field(DTYP, "Soft Channel") +} + +record( ai, "ISTTOK:marte2:ADC0S") +{ + field(DTYP, "Soft Channel") +} +record( ai, "ISTTOK:marte2:Adc0-Decim") +{ + field(DTYP, "Soft Channel") +} +record( ai, "ISTTOK:marte2:Adc1-Decim") +{ + field(DTYP, "Soft Channel") +} + diff --git a/Configurations/RTApp-AtcaIop.cfg b/Configurations/RTApp-AtcaIop.cfg new file mode 100644 index 0000000..b11851d --- /dev/null +++ b/Configurations/RTApp-AtcaIop.cfg @@ -0,0 +1,1531 @@ ++EPICSCAInterface = { + Class = "EPICS::EPICSCAClient" + StackSize = "1048576" + CPUs = "0x1" + AutoStart = "0" + +PV_STATUS = { + Class = "EPICS::EPICSPV" + PVName = "ISTTOK:central:MARTe2-Status" + PVType = "int32" + } + +PV_COMMAND = { + Class = "EPICS::EPICSPV" + PVName = "ISTTOK:central:MARTe2-Command" + PVType = "uint32" + Event = { + Destination = "StateMachine" + PVValue = "Function" + FunctionMap = {{"1" "GOTORUN"}{"0" "GOTOIDLE"}} + } + } + +PV_ERROR_RST = { + Class = "EPICS::EPICSPV" + PVName = "ISTTOK:central:MARTe2-Reset" + PVType = "uint32" + Event = { + Destination = "StateMachine" + PVValue = "Ignore" + Function = "RESET" + } + } +} ++WebRoot = { + Class = "HttpObjectBrowser" + Root = "." + +ObjectBrowse = { + Class = "HttpObjectBrowser" + Root = "/" + } + +ResourcesHtml = { + Class = "HttpDirectoryResource" + BaseDir = "/opt/marte/MARTe2/Resources/HTTP" + } + +HttpMessageInterface = { + Class = "HttpMessageInterface" + +GOTOIDLE = { + Class = "Message" + Destination = "StateMachine" + Function = "GOTOIDLE" + Mode = "ExpectsReply" + } + +GOTORUN = { + Class = "Message" + Destination = "StateMachine" + Function = "GOTORUN" + Mode = "ExpectsReply" + } + +GOTOERR = { + Class = "Message" + Destination = "StateMachineError" + Function = "GOTOERR" + Mode = "ExpectsReply" + } + } +} ++WebServer = { + Class = "HttpService" + Port = "8084" + WebRoot = "WebRoot" + Timeout = "0" + ListenMaxConnections = "255" + AcceptTimeout = "1000" + MaxNumberOfThreads = "8" + MinNumberOfThreads = "1" +} ++StateMachine = { + Class = "StateMachine" + +INITIAL = { + Class = "ReferenceContainer" + +START = { + Class = "StateMachineEvent" + NextState = "IDLE" + NextStateError = "ERROR" + Timeout = "0" + +StartHttpServer = { + Class = "Message" + Destination = "WebServer" + Mode = "ExpectsReply" + Function = "Start" + } + +StartEPICSCAInterface = { + Class = "Message" + Destination = "EPICSCAInterface" + Mode = "ExpectsReply" + Function = "Start" + } + +ChangeToStateIdleMsg = { + Class = "Message" + Destination = "IsttokApp" + Mode = "ExpectsReply" + Function = "PrepareNextState" + +Parameters = { + Class = "ConfigurationDatabase" + param1 = "Idle" + } + } + +StartNextStateExecutionMsg = { + Class = "Message" + Destination = "IsttokApp" + Function = "StartNextStateExecution" + Mode = "ExpectsReply" + } + } + } + +IDLE = { + Class = "ReferenceContainer" + +GOTORUN = { + Class = "StateMachineEvent" + NextState = "RUN" + NextStateError = "ERROR" + Timeout = "0" + +OpenTreeMsg = { + Class = "Message" + Destination = "IsttokApp.Data.SignalsWriter" + Function = "OpenTree" + Mode = "ExpectsReply" + +Parameters = { + Class = "ConfigurationDatabase" + param1 = "1" // param1 = "-1" Auto numer + } + } + +ChangeToRunMsg = { + Class = "Message" + Destination = "IsttokApp" + Mode = "ExpectsReply" + Function = "PrepareNextState" + +Parameters = { + Class = "ConfigurationDatabase" + param1 = "Run" + } + } + +StopCurrentStateExecutionMsg = { + Class = "Message" + Destination = "IsttokApp" + Function = "StopCurrentStateExecution" + Mode = "ExpectsReply" + } + +StartNextStateExecutionMsg = { + Class = "Message" + Destination = "IsttokApp" + Function = "StartNextStateExecution" + Mode = "ExpectsReply" + } + } + } + +RUN = { + Class = "ReferenceContainer" + +ENTER = { + Class = "ReferenceContainer" + +SetStatusPV = { + Class = "Message" + Destination = "EPICSCAInterface.PV_STATUS" + Function = "CAPut" + Mode = "ExpectsReply" + +Parameters = { + Class = "ConfigurationDatabase" + param1 = "1" + } + } + } + +GOTOIDLE = { + Class = "StateMachineEvent" + NextState = "IDLE" + NextStateError = "ERROR" + Timeout = "0" + +ChangeToIdleMsg = { + Class = "Message" + Destination = "IsttokApp" + Mode = "ExpectsReply" + Function = "PrepareNextState" + +Parameters = { + Class = "ConfigurationDatabase" + param1 = "Idle" + } + } + +StopCurrentStateExecutionMsg = { + Class = "Message" + Destination = "IsttokApp" + Function = "StopCurrentStateExecution" + Mode = "ExpectsReply" + } + +StartNextStateExecutionMsg = { + Class = "Message" + Destination = "IsttokApp" + Function = "StartNextStateExecution" + Mode = "ExpectsReply" + } + +SetStatusPV = { + Class = "Message" + Destination = "EPICSCAInterface.PV_STATUS" + Function = "CAPut" + Mode = "ExpectsReply" + +Parameters = { + Class = "ConfigurationDatabase" + param1 = "0" + } + } + } + } + +ERROR = { + Class = "ReferenceContainer" + +ENTER = { + Class = "ReferenceContainer" + +SetStatusPV = { + Class = "Message" + Destination = "EPICSCAInterface.PV_STATUS" + Function = "CAPut" + Mode = "ExpectsReply" + +Parameters = { + Class = "ConfigurationDatabase" + param1 = "2" + } + } + +ChangeToErrorMsg = { + Class = "Message" + Destination = "IsttokApp" + Mode = "ExpectsReply" + Function = "PrepareNextState" + +Parameters = { + Class = "ConfigurationDatabase" + param1 = "Error" + } + } + +StopCurrentStateExecutionMsg = { + Class = "Message" + Destination = "IsttokApp" + Function = "StopCurrentStateExecution" + Mode = "ExpectsReply" + } + +StartNextStateExecutionMsg = { + Class = "Message" + Destination = "IsttokApp" + Function = "StartNextStateExecution" + Mode = "ExpectsReply" + } + } + +RESET = { + Class = "StateMachineEvent" + NextState = "IDLE" + NextStateError = "ERROR" + Timeout = "0" + +ChangeToIdleMsg = { + Class = "Message" + Destination = "IsttokApp" + Mode = "ExpectsReply" + Function = "PrepareNextState" + +Parameters = { + Class = "ConfigurationDatabase" + param1 = "Idle" + } + } + +StopCurrentStateExecutionMsg = { + Class = "Message" + Destination = "IsttokApp" + Function = "StopCurrentStateExecution" + Mode = "ExpectsReply" + } + +StartNextStateExecutionMsg = { + Class = "Message" + Destination = "IsttokApp" + Function = "StartNextStateExecution" + Mode = "ExpectsReply" + } + +SetStatusPV = { + Class = "Message" + Destination = "EPICSCAInterface.PV_STATUS" + Function = "CAPut" + Mode = "ExpectsReply" + +Parameters = { + Class = "ConfigurationDatabase" + param1 = "0" + } + } + } + } +} +$IsttokApp = { + Class = "RealTimeApplication" + +Functions = { + Class = "ReferenceContainer" + +AtcaGAMInput = { + Class = "IOGAM" + InputSignals = { + Counter = { + DataSource = "AtcaIop_0_ADC" + Type = "uint32" + } + Time = { + Frequency = "10000" + DataSource = "AtcaIop_0_ADC" + Type = "uint32" + } + ADC0Decim = { + DataSource = "AtcaIop_0_ADC" + Type = "int32" + } + ADC1Decim = { + DataSource = "AtcaIop_0_ADC" + Type = "int32" + } + ADC2Decim = { + DataSource = "AtcaIop_0_ADC" + Type = "int32" + } + ADC3Decim = { + DataSource = "AtcaIop_0_ADC" + Type = "int32" + } + ADC4Decim = { + DataSource = "AtcaIop_0_ADC" + Type = "int32" + } + ADC5Decim = { + DataSource = "AtcaIop_0_ADC" + Type = "int32" + } + ADC6Decim = { + DataSource = "AtcaIop_0_ADC" + Type = "int32" + } + ADC7Decim = { + DataSource = "AtcaIop_0_ADC" + Type = "int32" + } + ADC8Decim = { + DataSource = "AtcaIop_0_ADC" + Type = "int32" + } + ADC9Decim = { + DataSource = "AtcaIop_0_ADC" + Type = "int32" + } + ADC10Decim = { + DataSource = "AtcaIop_0_ADC" + Type = "int32" + } + ADC11Decim = { + DataSource = "AtcaIop_0_ADC" + Type = "int32" + } + ADC0Integral = { + DataSource = "AtcaIop_0_ADC" + Type = "int64" + } + ADC1Integral = { + DataSource = "AtcaIop_0_ADC" + Type = "int64" + } + ADC2Integral = { + DataSource = "AtcaIop_0_ADC" + Type = "int64" + } + ADC3Integral = { + DataSource = "AtcaIop_0_ADC" + Type = "int64" + } + ADC4Integral = { + DataSource = "AtcaIop_0_ADC" + Type = "int64" + } + ADC5Integral = { + DataSource = "AtcaIop_0_ADC" + Type = "int64" + } + ADC6Integral = { + DataSource = "AtcaIop_0_ADC" + Type = "int64" + } + ADC7Integral = { + DataSource = "AtcaIop_0_ADC" + Type = "int64" + } + ADC8Integral = { + DataSource = "AtcaIop_0_ADC" + Type = "int64" + } + ADC9Integral = { + DataSource = "AtcaIop_0_ADC" + Type = "int64" + } + ADC10Integral = { + DataSource = "AtcaIop_0_ADC" + Type = "int64" + } + ADC11Integral = { + DataSource = "AtcaIop_0_ADC" + Type = "int64" + } + Idle_Thread1_CycleTime = { + DataSource = "Timings" + Alias = "Idle.Thread1_CycleTime" + Type = "uint32" + } + Run_Thread1_CycleTime = { + DataSource = "Timings" + Alias = "Run.Thread1_CycleTime" + Type = "uint32" + } + } + OutputSignals = { + Counter = { + DataSource = "DDB1" + Type = "uint32" + } + Time = { + DataSource = "DDB1" + Type = "uint32" + } + ADC0DRaw = { + DataSource = "DDB1" + Type = "int32" + } + ADC1DRaw = { + DataSource = "DDB1" + Type = "int32" + } + ADC2DRaw = { + DataSource = "DDB1" + Type = "int32" + } + ADC3DRaw = { + DataSource = "DDB1" + Type = "int32" + } + ADC4DRaw = { + DataSource = "DDB1" + Type = "int32" + } + ADC5DRaw = { + DataSource = "DDB1" + Type = "int32" + } + ADC6DRaw = { + DataSource = "DDB1" + Type = "int32" + } + ADC7DRaw = { + DataSource = "DDB1" + Type = "int32" + } + ADC8DRaw = { + DataSource = "DDB1" + Type = "int32" + } + ADC9DRaw = { + DataSource = "DDB1" + Type = "int32" + } + ADC10DRaw = { + DataSource = "DDB1" + Type = "int32" + } + ADC11DRaw = { + DataSource = "DDB1" + Type = "int32" + } + ADC0Integral = { + DataSource = "DDB1" + Type = "int64" + } + ADC1Integral = { + DataSource = "DDB1" + Type = "int64" + } + ADC2Integral = { + DataSource = "DDB1" + Type = "int64" + } + ADC3Integral = { + DataSource = "DDB1" + Type = "int64" + } + ADC4Integral = { + DataSource = "DDB1" + Type = "int64" + } + ADC5Integral = { + DataSource = "DDB1" + Type = "int64" + } + ADC6Integral = { + DataSource = "DDB1" + Type = "int64" + } + ADC7Integral = { + DataSource = "DDB1" + Type = "int64" + } + ADC8Integral = { + DataSource = "DDB1" + Type = "int64" + } + ADC9Integral = { + DataSource = "DDB1" + Type = "int64" + } + ADC10Integral = { + DataSource = "DDB1" + Type = "int64" + } + ADC11Integral = { + DataSource = "DDB1" + Type = "int64" + } + Idle_Thread1_CycleTime = { + DataSource = "DDB1" + Type = "uint32" + NumberOfDimensions = "1" + } + Run_Thread1_CycleTime = { + DataSource = "DDB1" + Type = "uint32" + } + } + } + +DacConstants = { + Class = ConstantGAM + OutputSignals = { + DacSignal0 = { + DataSource = "DDB1" + Type = float32 + Default = -1.0 + } + DacSignal1 = { + DataSource = "DDB1" + Type = float32 + Default = 2.0 + } + } + } + +AtcaGAMOutput = { + Class = "IOGAM" + InputSignals = { + //DacSignal0 = { + ADC1DecimV = { + DataSource = "DDB1" + Type = float32 + } + ADC2DecimV = { + DataSource = "DDB1" + Type = float32 + } + } + OutputSignals = { + DAC0 = { + DataSource = AtcaIop_0_DAC + Type = float32 + } + DAC1 = { + DataSource = AtcaIop_0_DAC + Type = float32 + Trigger = 1 + } + } + } + +GAMConvert2Volt = { + Class = "ConversionGAM" + InputSignals = { + ADC0DRaw = { + DataSource = "DDB1" + Type = "int32" + } + ADC1DRaw = { + DataSource = "DDB1" + Type = "int32" + } + ADC2DRaw = { + DataSource = "DDB1" + Type = "int32" + } + ADC3DRaw = { + DataSource = "DDB1" + Type = "int32" + } + } + OutputSignals = { + ADC0DecimV= { + DataSource = "DDB1" + Type = "float32" + Gain = 0.00007629 + //Gain = 0.0000762939453125 10.0 / 2 **17 + } + ADC1DecimV = { + DataSource = "DDB1" + Type = "float32" + Gain = 0.00007629 + } + ADC2DecimV = { + DataSource = "DDB1" + Type = "float32" + Gain = 0.00007629 + } + ADC3DecimV = { + DataSource = "DDB1" + Type = "float32" + Gain = 0.00007629 + } + } + } + +GAMConvert2Float = { + Class = "ConversionGAM" + InputSignals = { + ADC0DRaw = { + DataSource = "DDB1" + Type = "int32" + } + ADC1DRaw = { + DataSource = "DDB1" + Type = "int32" + } + ADC2DRaw = { + DataSource = "DDB1" + Type = "int32" + } + ADC3DRaw = { + DataSource = "DDB1" + Type = "int32" + } + ADC4DRaw = { + DataSource = "DDB1" + Type = "int32" + } + ADC5DRaw = { + DataSource = "DDB1" + Type = "int32" + } + ADC6DRaw = { + DataSource = "DDB1" + Type = "int32" + } + ADC7DRaw = { + DataSource = "DDB1" + Type = "int32" + } + ADC8DRaw = { + DataSource = "DDB1" + Type = "int32" + } + ADC9DRaw = { + DataSource = "DDB1" + Type = "int32" + } + ADC10DRaw = { + DataSource = "DDB1" + Type = "int32" + } + ADC11DRaw = { + DataSource = "DDB1" + Type = "int32" + } + ADC0Integral = { + DataSource = "DDB1" + Type = "int64" + } + ADC1Integral = { + DataSource = "DDB1" + Type = "int64" + } + ADC2Integral = { + DataSource = "DDB1" + Type = "int64" + } + ADC3Integral = { + DataSource = "DDB1" + Type = "int64" + } + ADC4Integral = { + DataSource = "DDB1" + Type = "int64" + } + ADC5Integral = { + DataSource = "DDB1" + Type = "int64" + } + ADC6Integral = { + DataSource = "DDB1" + Type = "int64" + } + ADC7Integral = { + DataSource = "DDB1" + Type = "int64" + } + ADC8Integral = { + DataSource = "DDB1" + Type = "int64" + } + ADC9Integral = { + DataSource = "DDB1" + Type = "int64" + } + ADC10Integral = { + DataSource = "DDB1" + Type = "int64" + } + ADC11Integral = { + DataSource = "DDB1" + Type = "int64" + } + } + OutputSignals = { + ADC0DecimS = { + DataSource = "DDB1" + Type = "float32" + } + ADC1DecimS = { + DataSource = "DDB1" + Type = "float32" + } + ADC2DecimS = { + DataSource = "DDB1" + Type = "float32" + } + ADC3DecimS = { + DataSource = "DDB1" + Type = "float32" + } + ADC4DecimS = { + DataSource = "DDB1" + Type = "float32" + } + ADC5DecimS = { + DataSource = "DDB1" + Type = "float32" + } + ADC6DecimS = { + DataSource = "DDB1" + Type = "float32" + } + ADC7DecimS = { + DataSource = "DDB1" + Type = "float32" + } + ADC8DecimS = { + DataSource = "DDB1" + Type = "float32" + } + ADC9DecimS = { + DataSource = "DDB1" + Type = "float32" + } + ADC10DecimS = { + DataSource = "DDB1" + Type = "float32" + } + ADC11DecimS = { + DataSource = "DDB1" + Type = "float32" + } + ADC0IntegS = { + DataSource = "DDB1" + Type = "float32" + } + ADC1IntegS = { + DataSource = "DDB1" + Type = "float32" + } + ADC2IntegS = { + DataSource = "DDB1" + Type = "float32" + } + ADC3IntegS = { + DataSource = "DDB1" + Type = "float32" + } + ADC4IntegS = { + DataSource = "DDB1" + Type = "float32" + } + ADC5IntegS = { + DataSource = "DDB1" + Type = "float32" + } + ADC6IntegS = { + DataSource = "DDB1" + Type = "float32" + } + ADC7IntegS = { + DataSource = "DDB1" + Type = "float32" + } + ADC8IntegS = { + DataSource = "DDB1" + Type = "float32" + } + ADC9IntegS = { + DataSource = "DDB1" + Type = "float32" + } + ADC10IntegS = { + DataSource = "DDB1" + Type = "float32" + } + ADC11IntegS = { + DataSource = "DDB1" + Type = "float32" + } + } + } + +GAMHistogramCycleTimes = { + Class = "HistogramGAM" + BeginCycleNumber = "10" + StateChangeResetName = "All" + InputSignals = { + Idle_Thread1_CycleTime = { + DataSource = "DDB1" + Type = "uint32" + MinLim = "80" + MaxLim = "120" + } + Run_Thread1_CycleTime = { + DataSource = "DDB1" + Type = "uint32" + MinLim = "50" + MaxLim = "150" + } + } + OutputSignals = { + Idle_Thread1_CycleTime_Stats = { + DataSource = "EPICSCAOutputHist" + NumberOfDimensions = "1" + NumberOfElements = "10" + Type = "uint32" + } + Run_Thread1_CycleTime_Stats = { + DataSource = "EPICSCAOutputHist" + NumberOfDimensions = "1" + NumberOfElements = "10" + Type = "uint32" + } + } + } + +GAMCAOutput = { + Class = "IOGAM" + InputSignals = { + Time = { + DataSource = "DDB1" + Type = "uint32" + } + Counter = { + DataSource = "DDB1" + Type = "uint32" + } + ADC0DecimV = { + DataSource = "DDB1" + Type = "float32" + } + ADC1DecimV = { + DataSource = "DDB1" + Type = "float32" + } + } + OutputSignals = { + Time = { + DataSource = "EPICSCAOutput" + Type = "uint32" + } + Counter = { + DataSource = "EPICSCAOutput" + Type = "uint32" + } + ADC0DecimAi = { + DataSource = "EPICSCAOutput" + Type = "float32" + } + ADC1DecimAi = { + DataSource = "EPICSCAOutput" + Type = "float32" + } + } + } + +GAMSignalsWriter = { + Class = "IOGAM" + InputSignals = { + Time = { + DataSource = "DDB1" + Type = "uint32" + } + ADC0DecimS = { + DataSource = "DDB1" + Type = "float32" + } + ADC1DecimS = { + DataSource = "DDB1" + Type = "float32" + } + ADC2DecimS = { + DataSource = "DDB1" + Type = "float32" + } + ADC3DecimS = { + DataSource = "DDB1" + Type = "float32" + } + ADC4DecimS = { + DataSource = "DDB1" + Type = "float32" + } + ADC5DecimS = { + DataSource = "DDB1" + Type = "float32" + } + ADC6DecimS = { + DataSource = "DDB1" + Type = "float32" + } + ADC7DecimS = { + DataSource = "DDB1" + Type = "float32" + } + ADC8DecimS = { + DataSource = "DDB1" + Type = "float32" + } + ADC9DecimS = { + DataSource = "DDB1" + Type = "float32" + } + ADC10DecimS = { + DataSource = "DDB1" + Type = "float32" + } + ADC11DecimS = { + DataSource = "DDB1" + Type = "float32" + } + ADC0IntegS = { + DataSource = "DDB1" + Type = "float32" + } + ADC1IntegS = { + DataSource = "DDB1" + Type = "float32" + } + ADC2IntegS = { + DataSource = "DDB1" + Type = "float32" + } + ADC3IntegS = { + DataSource = "DDB1" + Type = "float32" + } + ADC4IntegS = { + DataSource = "DDB1" + Type = "float32" + } + ADC5IntegS = { + DataSource = "DDB1" + Type = "float32" + } + ADC6IntegS = { + DataSource = "DDB1" + Type = "float32" + } + ADC7IntegS = { + DataSource = "DDB1" + Type = "float32" + } + ADC8IntegS = { + DataSource = "DDB1" + Type = "float32" + } + ADC9IntegS = { + DataSource = "DDB1" + Type = "float32" + } + ADC10IntegS = { + DataSource = "DDB1" + Type = "float32" + } + ADC11IntegS = { + DataSource = "DDB1" + Type = "float32" + } + } + OutputSignals = { + Time = { + DataSource = "SignalsWriter" + Type = "uint32" + } + AdcRawDecim0 = { + DataSource = "SignalsWriter" + Type = "float32" + } + AdcRawDecim1 = { + DataSource = "SignalsWriter" + Type = "float32" + } + AdcRawDecim2 = { + DataSource = "SignalsWriter" + Type = "float32" + } + AdcRawDecim3 = { + DataSource = "SignalsWriter" + Type = "float32" + } + AdcRawDecim4 = { + DataSource = "SignalsWriter" + Type = "float32" + } + AdcRawDecim5 = { + DataSource = "SignalsWriter" + Type = "float32" + } + AdcRawDecim6 = { + DataSource = "SignalsWriter" + Type = "float32" + } + AdcRawDecim7 = { + DataSource = "SignalsWriter" + Type = "float32" + } + AdcRawDecim8 = { + DataSource = "SignalsWriter" + Type = "float32" + } + AdcRawDecim9 = { + DataSource = "SignalsWriter" + Type = "float32" + } + AdcRawDecim10 = { + DataSource = "SignalsWriter" + Type = "float32" + } + AdcRawDecim11 = { + DataSource = "SignalsWriter" + Type = "float32" + } + AdcInteg0 = { + DataSource = "SignalsWriter" + Type = "float32" + } + AdcInteg1 = { + DataSource = "SignalsWriter" + Type = "float32" + } + AdcInteg2 = { + DataSource = "SignalsWriter" + Type = "float32" + } + AdcInteg3 = { + DataSource = "SignalsWriter" + Type = "float32" + } + AdcInteg4 = { + DataSource = "SignalsWriter" + Type = "float32" + } + AdcInteg5 = { + DataSource = "SignalsWriter" + Type = "float32" + } + AdcInteg6 = { + DataSource = "SignalsWriter" + Type = "float32" + } + AdcInteg7 = { + DataSource = "SignalsWriter" + Type = "float32" + } + AdcInteg8 = { + DataSource = "SignalsWriter" + Type = "float32" + } + AdcInteg9 = { + DataSource = "SignalsWriter" + Type = "float32" + } + AdcInteg10 = { + DataSource = "SignalsWriter" + Type = "float32" + } + AdcInteg11 = { + DataSource = "SignalsWriter" + Type = "float32" + } + } + } + } + +Data = { + Class = "ReferenceContainer" + DefaultDataSource = "DDB1" + +DDB1 = { + Class = "GAMDataSource" + } + +LoggerDataSource = { + Class = "LoggerDataSource" + } + +Timings = { + Class = "TimingDataSource" + } + +AtcaIop_0_DAC = { + Class = "AtcaIop::AtcaIopDAC" + //CPUMask = "0xC" + DeviceName = "/dev/atca_v6_dac_2" + //NumberOfChannels = 2 + Signals = { + DAC0 = { + Type = float32 + OutputRange = 15.0 + // OutputPolarity = Bipolar + } + DAC1 = { + Type = float32 + OutputRange = 15.0 + } + } + } + +AtcaIop_0_ADC = { + Class = "AtcaIop::AtcaIopADC" + CPUMask = "0xC" + DeviceName = "/dev/atca_v6_2" + DeviceDmaName = "/dev/atca_v6_dmart_2" + NumberOfChannels = "12" + IsMaster = "1" + SleepNature = "Busy" + SleepPercentage = "0" + ADCFrequency = "2000000" + RTDecimation = "200" + ChopperPeriod = "2000" + ElectricalOffsets = {"86150" "-142" "130" "-165" "-280" "-187" "-10" "194" "40" "-36" "260" "-770"} + WiringOffsets = {"33.0" "34.89" "26.0" "38.0" "39.0" "-75.0" "30.0" "11.0" "-100.0" "-87.0" "-110.0" "-55.0"} + Signals = { + Counter = { + Type = "uint32" + } + Time = { + Type = "uint32" + } + ADC0Decim = { + Type = "int32" + } + ADC1Decim = { + Type = "int32" + } + ADC2Decim = { + Type = "int32" + } + ADC3Decim = { + Type = "int32" + } + ADC4Decim = { + Type = "int32" + } + ADC5Decim = { + Type = "int32" + } + ADC6Decim = { + Type = "int32" + } + ADC7Decim = { + Type = "int32" + } + ADC8Decim = { + Type = "int32" + } + ADC9Decim = { + Type = "int32" + } + ADC10Decim = { + Type = "int32" + } + ADC11Decim = { + Type = "int32" + } + ADC0Integral = { + Type = "int64" + } + ADC1Integral = { + Type = "int64" + } + ADC2Integral = { + Type = "int64" + } + ADC3Integral = { + Type = "int64" + } + ADC4Integral = { + Type = "int64" + } + ADC5Integral = { + Type = "int64" + } + ADC6Integral = { + Type = "int64" + } + ADC7Integral = { + Type = "int64" + } + ADC8Integral = { + Type = "int64" + } + ADC9Integral = { + Type = "int64" + } + ADC10Integral = { + Type = "int64" + } + ADC11Integral = { + Type = "int64" + } + } + } + +SignalsWriter = { + Class = "MDSWriter::MDSWriter" + NumberOfBuffers = "120000" + CPUMask = "0x1" + StackSize = "10000000" + TreeName = "rtappisttok" + StoreOnTrigger = "0" + TimeRefresh = "5" + NumberOfPreTriggers = "0" + NumberOfPostTriggers = "0" + EventName = "IgnoreMe" + Signals = { + Time = { + SignalType = "uint32" + TimeSignal = "1" + } + AdcRawDecim0 = { + NodeName = "ATCAIOP1.ADC0RAW" + Period = "100e-6" + MakeSegmentAfterNWrites = "200" + DecimatedNodeName = "ATCAIOP1.ADC0RAWD" + MinMaxResampleFactor = "100" + SamplePhase = "0" + AutomaticSegmentation = "0" + } + AdcRawDecim1 = { + NodeName = "ATCAIOP1.ADC1RAW" + Period = "100e-6" + MakeSegmentAfterNWrites = "200" + DecimatedNodeName = "ATCAIOP1.ADC1RAWD" + MinMaxResampleFactor = "100" + SamplePhase = "0" + AutomaticSegmentation = "0" + } + AdcRawDecim2 = { + NodeName = "ATCAIOP1.ADC2RAW" + Period = "100e-6" + MakeSegmentAfterNWrites = "200" + DecimatedNodeName = "ATCAIOP1.ADC1RAWD" + MinMaxResampleFactor = "100" + SamplePhase = "0" + AutomaticSegmentation = "0" + } + AdcRawDecim3 = { + NodeName = "ATCAIOP1.ADC3RAW" + Period = "100e-6" + MakeSegmentAfterNWrites = "200" + DecimatedNodeName = "ATCAIOP1.ADC3RAWD" + MinMaxResampleFactor = "100" + SamplePhase = "0" + AutomaticSegmentation = "0" + } + AdcRawDecim4 = { + NodeName = "ATCAIOP1.ADC4RAW" + Period = "100e-6" + MakeSegmentAfterNWrites = "200" + DecimatedNodeName = "ATCAIOP1.ADC4RAWD" + MinMaxResampleFactor = "100" + SamplePhase = "0" + AutomaticSegmentation = "0" + } + AdcRawDecim5 = { + NodeName = "ATCAIOP1.ADC5RAW" + Period = "100e-6" + MakeSegmentAfterNWrites = "200" + DecimatedNodeName = "ATCAIOP1.ADC5RAWD" + MinMaxResampleFactor = "100" + SamplePhase = "0" + AutomaticSegmentation = "0" + } + AdcRawDecim6 = { + NodeName = "ATCAIOP1.ADC6RAW" + Period = "100e-6" + MakeSegmentAfterNWrites = "200" + DecimatedNodeName = "ATCAIOP1.ADC6RAWD" + MinMaxResampleFactor = "100" + SamplePhase = "0" + AutomaticSegmentation = "0" + } + AdcRawDecim7 = { + NodeName = "ATCAIOP1.ADC7RAW" + Period = "100e-6" + MakeSegmentAfterNWrites = "200" + DecimatedNodeName = "ATCAIOP1.ADC7RAWD" + MinMaxResampleFactor = "100" + SamplePhase = "0" + AutomaticSegmentation = "0" + } + AdcRawDecim8 = { + NodeName = "ATCAIOP1.ADC8RAW" + Period = "100e-6" + MakeSegmentAfterNWrites = "200" + DecimatedNodeName = "ATCAIOP1.ADC8RAWD" + MinMaxResampleFactor = "100" + SamplePhase = "0" + AutomaticSegmentation = "0" + } + AdcRawDecim9 = { + NodeName = "ATCAIOP1.ADC9RAW" + Period = "100e-6" + MakeSegmentAfterNWrites = "200" + DecimatedNodeName = "ATCAIOP1.ADC9RAWD" + MinMaxResampleFactor = "100" + SamplePhase = "0" + AutomaticSegmentation = "0" + } + AdcRawDecim10 = { + NodeName = "ATCAIOP1.ADC10RAW" + Period = "100e-6" + MakeSegmentAfterNWrites = "200" + DecimatedNodeName = "ATCAIOP1.ADC10RAWD" + MinMaxResampleFactor = "100" + SamplePhase = "0" + AutomaticSegmentation = "0" + } + AdcRawDecim11 = { + NodeName = "ATCAIOP1.ADC11RAW" + Period = "100e-6" + MakeSegmentAfterNWrites = "200" + DecimatedNodeName = "ATCAIOP1.ADC11RAWD" + MinMaxResampleFactor = "100" + SamplePhase = "0" + AutomaticSegmentation = "0" + } + AdcInteg0 = { + NodeName = "ATCAIOP1.ADC0INT" + Period = "100e-6" + MakeSegmentAfterNWrites = "200" + DecimatedNodeName = "ATCAIOP1.ADC0INTD" + MinMaxResampleFactor = "100" + SamplePhase = "0" + AutomaticSegmentation = "0" + } + AdcInteg1 = { + NodeName = "ATCAIOP1.ADC1INT" + Period = "100e-6" + MakeSegmentAfterNWrites = "200" + DecimatedNodeName = "ATCAIOP1.ADC1INTD" + MinMaxResampleFactor = "100" + SamplePhase = "0" + AutomaticSegmentation = "0" + } + AdcInteg2 = { + NodeName = "ATCAIOP1.ADC2INT" + Period = "100e-6" + MakeSegmentAfterNWrites = "200" + DecimatedNodeName = "ATCAIOP1.ADC2INTD" + MinMaxResampleFactor = "100" + SamplePhase = "0" + AutomaticSegmentation = "0" + } + AdcInteg3 = { + NodeName = "ATCAIOP1.ADC3INT" + Period = "100e-6" + MakeSegmentAfterNWrites = "200" + DecimatedNodeName = "ATCAIOP1.ADC3INTD" + MinMaxResampleFactor = "100" + SamplePhase = "0" + AutomaticSegmentation = "0" + } + AdcInteg4 = { + NodeName = "ATCAIOP1.ADC4INT" + Period = "100e-6" + MakeSegmentAfterNWrites = "200" + DecimatedNodeName = "ATCAIOP1.ADC4INTD" + MinMaxResampleFactor = "100" + SamplePhase = "0" + AutomaticSegmentation = "0" + } + AdcInteg5 = { + NodeName = "ATCAIOP1.ADC5INT" + Period = "100e-6" + MakeSegmentAfterNWrites = "200" + DecimatedNodeName = "ATCAIOP1.ADC5INTD" + MinMaxResampleFactor = "100" + SamplePhase = "0" + AutomaticSegmentation = "0" + } + AdcInteg6 = { + NodeName = "ATCAIOP1.ADC0INT" + Period = "100e-6" + MakeSegmentAfterNWrites = "200" + DecimatedNodeName = "ATCAIOP1.ADC0INTD" + MinMaxResampleFactor = "100" + SamplePhase = "0" + AutomaticSegmentation = "0" + } + AdcInteg7 = { + NodeName = "ATCAIOP1.ADC7INT" + Period = "100e-6" + MakeSegmentAfterNWrites = "200" + DecimatedNodeName = "ATCAIOP1.ADC7INTD" + MinMaxResampleFactor = "100" + SamplePhase = "0" + AutomaticSegmentation = "0" + } + AdcInteg8 = { + NodeName = "ATCAIOP1.ADC8INT" + Period = "100e-6" + MakeSegmentAfterNWrites = "200" + DecimatedNodeName = "ATCAIOP1.ADC8INTD" + MinMaxResampleFactor = "100" + SamplePhase = "0" + AutomaticSegmentation = "0" + } + AdcInteg9 = { + NodeName = "ATCAIOP1.ADC9INT" + Period = "100e-6" + MakeSegmentAfterNWrites = "200" + DecimatedNodeName = "ATCAIOP1.ADC9INTD" + MinMaxResampleFactor = "100" + SamplePhase = "0" + AutomaticSegmentation = "0" + } + AdcInteg10 = { + NodeName = "ATCAIOP1.ADC10INT" + Period = "100e-6" + MakeSegmentAfterNWrites = "200" + DecimatedNodeName = "ATCAIOP1.ADC10INTD" + MinMaxResampleFactor = "100" + SamplePhase = "0" + AutomaticSegmentation = "0" + } + AdcInteg11 = { + NodeName = "ATCAIOP1.ADC11INT" + Period = "100e-6" + MakeSegmentAfterNWrites = "200" + DecimatedNodeName = "ATCAIOP1.ADC11INTD" + MinMaxResampleFactor = "100" + SamplePhase = "0" + AutomaticSegmentation = "0" + } + } + } + +EPICSCAOutput = { + Class = "EPICSCA::EPICSCAOutput" + StackSize = "1048576" + CPUs = "0x1" + IgnoreBufferOverrun = "1" + NumberOfBuffers = "10" + Signals = { + Time = { + PVName = "ISTTOK:marte2:TIME" + Type = "uint32" + } + Counter = { + PVName = "ISTTOK:marte2:COUNTER" + Type = "uint32" + } + ADC0DecimAi = { + PVName = "ISTTOK:marte2:Adc0-Decim" + Type = "float32" + } + ADC1DecimAi = { + PVName = "ISTTOK:marte2:Adc1-Decim" + Type = "float32" + } + } + } + +EPICSCAOutputHist = { + Class = "EPICSCA::EPICSCAOutput" + StackSize = "1048576" + CPUs = "0x1" + IgnoreBufferOverrun = "1" + NumberOfBuffers = "10" + Signals = { + Idle_Thread1_CycleTime_Stats = { + PVName = "ISTTOK:marte2:HIST-IDLE-CT" + Type = "uint32" + } + Run_Thread1_CycleTime_Stats = { + PVName = "ISTTOK:marte2:HIST-RUN-CT" + Type = "uint32" + } + } + } + } + +States = { + Class = "ReferenceContainer" + +Idle = { + Class = "RealTimeState" + +Threads = { + Class = "ReferenceContainer" + +Thread1 = { + Class = "RealTimeThread" + CPUs = "0x4" + Functions = {"AtcaGAMInput" "DacConstants" "AtcaGAMOutput" "GAMConvert2Volt" "GAMConvert2Float" "GAMHistogramCycleTimes" "GAMCAOutput"} + + } + } + } + +Run = { + Class = "RealTimeState" + +Threads = { + Class = "ReferenceContainer" + +Thread1 = { + Class = "RealTimeThread" + CPUs = "0x4" + Functions = {"AtcaGAMInput" "DacConstants" "AtcaGAMOutput" "GAMConvert2Volt" "GAMConvert2Float" "GAMHistogramCycleTimes" "GAMCAOutput" "GAMSignalsWriter"} + } + } + } + +Error = { + Class = "RealTimeState" + +Threads = { + Class = "ReferenceContainer" + +Thread1 = { + Class = "RealTimeThread" + CPUs = "0x4" + Functions = {"AtcaGAMInput"} + } + } + } + } + +Scheduler = { + Class = "GAMScheduler" + TimingDataSource = "Timings" + } +} +// vim: syntax=cpp ts=2 sw=2 sts=2 sr et diff --git a/DataSources/AtcaIop/AtcaIopADC.cpp b/DataSources/AtcaIop/AtcaIopADC.cpp new file mode 100644 index 0000000..323f6ef --- /dev/null +++ b/DataSources/AtcaIop/AtcaIopADC.cpp @@ -0,0 +1,734 @@ +/** + * @file AtcaIopADC.cpp + * @brief Source file for class AtcaIopADC + * @date 19/09/2020 + * @author Andre Neto / Bernardo Carvalho + * + * @copyright Copyright 2015 F4E | European Joint Undertaking for ITER and + * the Development of Fusion Energy ('Fusion for Energy'). + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved + * by the European Commission - subsequent versions of the EUPL (the "Licence") + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: http://ec.europa.eu/idabc/eupl + * + * @warning Unless required by applicable law or agreed to in writing, + * software distributed under the Licence is distributed on an "AS IS" + * basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence permissions and limitations under the Licence. + + * @details This source file contains the definition of all the methods for + * the class AtcaIopADC (public, protected, and private). Be aware that some + * methods, such as those inline could be defined on the header file, instead. + */ + +//#define DLL_API + +/*---------------------------------------------------------------------------*/ +/* Standard header includes */ +/*---------------------------------------------------------------------------*/ +//#include +#include +#include // For mmap() + +#include // for close() + +/*---------------------------------------------------------------------------*/ +/* Project header includes */ +/*---------------------------------------------------------------------------*/ +#include "AdvancedErrorManagement.h" +#include "MemoryMapSynchronisedInputBroker.h" +#include "AtcaIopADC.h" +#include "atca-v6-iop-ioctl.h" + +/*---------------------------------------------------------------------------*/ +/* Static definitions */ +/*---------------------------------------------------------------------------*/ +namespace MARTe { + +//const float64 ADC_SIMULATOR_PI = 3.14159265359; +const uint32 IOP_ADC_OFFSET = 2u; // in DMA Data packet in 32b. First 2 are counter. +const uint32 IOP_ADC_INTEG_OFFSET = 16u; // in 64 bit words + +const uint32 RT_PCKT_SIZE = 1024u; +const uint32 RT_PCKT64_SIZE = 512u; // In 64 bit words + +/* 256 + 3840 = 4096 B (PAGE_SIZE) data packet*/ +typedef struct _DMA_CH1_PCKT { + uint32 head_time_cnt; + uint32 header; // h5431BACD + int32 channel[60]; // 24 56 + uint32 foot_time_cnt; + uint32 footer; // h9876ABDC + uint8 page_fill[3840]; +} DMA_CH1_PCKT; + +struct atca_eo_config { + int32_t offset[ATCA_IOP_MAX_CHANNELS]; +}; + +struct atca_wo_config { + int32_t offset[ATCA_IOP_MAX_CHANNELS]; +}; + +//} + +/*---------------------------------------------------------------------------*/ +/* Method definitions */ +/*---------------------------------------------------------------------------*/ +AtcaIopADC::AtcaIopADC() : + DataSourceI(), MessageI(), EmbeddedServiceMethodBinderI(), executor(*this) { + //boardId = 2u; + deviceName = ""; + deviceDmaName = ""; + boardFileDescriptor = -1; + boardDmaDescriptor = -1; + mappedDmaBase = NULL; + mappedDmaSize = 0u; + isMaster = 0u; + oldestBufferIdx = 0u; + lastTimeTicks = 0u; + sleepTimeTicks = 0u; + timerPeriodUsecTime = 0u; + counterAndTimer[0] = 0u; + counterAndTimer[1] = 0u; + sleepNature = Busy; + sleepPercentage = 0u; + adcPeriod = 0.; + uint32 k; + for (k=0u; k(static_cast(1000) * HighResolutionTimer::Period()); + //Sleep::NoMore(sleepTime); + if (boardDmaDescriptor != -1) { + close(boardDmaDescriptor); + REPORT_ERROR(ErrorManagement::Information, "Close device %d OK", boardDmaDescriptor); + } + uint32 k; +} + +bool AtcaIopADC::AllocateMemory() { + return true; +} + +bool AtcaIopADC::Initialise(StructuredDataI& data) { + bool ok = DataSourceI::Initialise(data); + if (ok) { + ok = data.Read("DeviceName", deviceName); + if (!ok) { + REPORT_ERROR(ErrorManagement::ParametersError, "The DeviceName shall be specified"); + } + } + if (ok) { + ok = data.Read("DeviceDmaName", deviceDmaName); + if (!ok) { + REPORT_ERROR(ErrorManagement::ParametersError, "The DeviceDmaName shall be specified"); + } + } + if (ok) { + ok = data.Read("NumberOfChannels", numberOfChannels); + if (!ok) { + REPORT_ERROR(ErrorManagement::ParametersError, "The NumberOfChannels shall be specified"); + } + if (numberOfChannels > ATCA_IOP_MAX_CHANNELS ) { + numberOfChannels = ATCA_IOP_MAX_CHANNELS; + } + } + if (ok) { + ok = data.Read("RTDecimation", rtDecimation); + if (!ok) { + REPORT_ERROR(ErrorManagement::ParametersError, "The RTDecimation shall be specified"); + } + if (rtDecimation > 2000000u) { + rtDecimation = 2000000u; + } + } + StreamString sleepNatureStr; + if (!data.Read("SleepNature", sleepNatureStr)) { + REPORT_ERROR(ErrorManagement::Information, "SleepNature was not set. Using Default."); + sleepNatureStr = "Default"; + } + if (sleepNatureStr == "Default") { + sleepNature = Default; + } + else if (sleepNatureStr == "Busy") { + sleepNature = Busy; + if (!data.Read("SleepPercentage", sleepPercentage)) { + sleepPercentage = 0u; + REPORT_ERROR(ErrorManagement::Information, "SleepPercentage was not set. Using Default %d.", sleepPercentage); + } + if (sleepPercentage > 100u) { + sleepPercentage = 100u; + } + } + else { + REPORT_ERROR(ErrorManagement::ParametersError, "Unsupported SleepNature."); + ok = false; + } + + + AnyType arrayDescription = data.GetType("ElectricalOffsets"); + uint32 numberOfElements = 0u; + if (ok) { + ok = arrayDescription.GetDataPointer() != NULL_PTR(void *); + } + if (ok) { + numberOfElements = arrayDescription.GetNumberOfElements(0u); + ok = (numberOfElements == ATCA_IOP_N_ADCs); + if (!ok) { + REPORT_ERROR(ErrorManagement::ParametersError, "Exactly %d elements shall be defined in the array ElectricalOffsets", ATCA_IOP_N_ADCs); + } + } + if (ok) { + Vector readVector(&electricalOffsets[0u], numberOfElements); + ok = data.Read("ElectricalOffsets", readVector); + } + + arrayDescription = data.GetType("WiringOffsets"); + numberOfElements = 0u; + if (ok) { + ok = arrayDescription.GetDataPointer() != NULL_PTR(void *); + } + if (ok) { + numberOfElements = arrayDescription.GetNumberOfElements(0u); + ok = (numberOfElements == ATCA_IOP_N_ADCs); + if (!ok) { + REPORT_ERROR(ErrorManagement::ParametersError, "Exactly %d elements shall be defined in the array WiringOffsets", ATCA_IOP_N_ADCs); + } + } + if (ok) { + Vector readVector(&wiringOffsets[0u], numberOfElements); + ok = data.Read("WiringOffsets", readVector); + } + + chopperPeriod = 1000; + if (!data.Read("ChopperPeriod", chopperPeriod)) { + REPORT_ERROR(ErrorManagement::Warning, "ChopperPeriod not specified. Using default: %d", chopperPeriod); + } + + if (!data.Read("IsMaster", isMaster)) { + REPORT_ERROR(ErrorManagement::Warning, "IsMaster not specified. Using default: %d", isMaster); + } + + adcFrequency = 2e5; + if (!data.Read("ADCFrequency", adcFrequency)) { + REPORT_ERROR(ErrorManagement::Warning, "ADCFrequency not specified. Using default: %d", adcFrequency); + } + adcPeriod = 1./adcFrequency; + + if (ok) { + uint32 cpuMaskIn; + if (!data.Read("CPUMask", cpuMaskIn)) { + cpuMaskIn = 0xFFu; + REPORT_ERROR(ErrorManagement::Warning, "CPUMask not specified using: %d", cpuMaskIn); + } + cpuMask = cpuMaskIn; + } + if (ok) { + if (!data.Read("StackSize", stackSize)) { + stackSize = THREADS_DEFAULT_STACKSIZE; + REPORT_ERROR(ErrorManagement::Warning, "StackSize not specified using: %d", stackSize); + } + } + if (ok) { + ok = (stackSize > 0u); + + if (!ok) { + REPORT_ERROR(ErrorManagement::ParametersError, "StackSize shall be > 0u"); + } + } + if (ok) { + executor.SetCPUMask(cpuMask); + executor.SetStackSize(stackSize); + } + return ok; +} + +bool AtcaIopADC::SetConfiguredDatabase(StructuredDataI& data) { + bool ok = DataSourceI::SetConfiguredDatabase(data); + struct atca_eo_config eo_conf; + struct atca_wo_config wo_conf; + //The DataSource shall have N signals. + //The first two are uint32 (counter and time) a + // + if (ok) { + ok = (GetNumberOfSignals() == ATCA_IOP_N_SIGNALS); + } + if (!ok) { + REPORT_ERROR(ErrorManagement::ParametersError, "Exactly %d signals shall be configured", ATCA_IOP_N_SIGNALS); + } + uint32 i, startPos, endPos; + startPos = 0u; + endPos = ATCA_IOP_N_TIMCNT; + for (i=startPos; (i < endPos) && (ok); i++) { + ok = (GetSignalType(i).type == UnsignedInteger); + if (!ok) { + REPORT_ERROR(ErrorManagement::ParametersError, "The signal %d shall be of type UnsignedInteger", i); + } + ok = (GetSignalType(i).numberOfBits == 32u); + if (!ok) { + REPORT_ERROR(ErrorManagement::ParametersError, "The signal in position %d shall have 32 bits and %d were specified", i, uint16(GetSignalType(i).numberOfBits)); + } + } + startPos = endPos; + endPos = startPos + ATCA_IOP_N_ADCs; + for (i=startPos; (i < endPos) && (ok); i++) { + ok = (GetSignalType(i).type == SignedInteger); + if (!ok) { + REPORT_ERROR(ErrorManagement::ParametersError, "The signal %d shall be of type SignedInteger", i); + } + ok = (GetSignalType(i).numberOfBits == 32u); + if (!ok) { + REPORT_ERROR(ErrorManagement::ParametersError, "The signal in position %d shall have 32 bits and %d were specified", i, uint16(GetSignalType(i).numberOfBits)); + } + } + startPos = endPos; + endPos = startPos + ATCA_IOP_N_INTEGRALS; + for (i=startPos; (i < endPos) && (ok); i++) { + ok = (GetSignalType(i).type == SignedInteger); + if (!ok) { + REPORT_ERROR(ErrorManagement::ParametersError, "The signal %d shall be of type SignedInteger", i); + } + ok = (GetSignalType(i).numberOfBits == 64u); + if (!ok) { + REPORT_ERROR(ErrorManagement::ParametersError, "The signal in position %d shall have 64 bits and %d were specified", i, uint16(GetSignalType(i).numberOfBits)); + } + } + startPos = endPos; + endPos = ATCA_IOP_N_SIGNALS; + for (i=startPos; (i < endPos) && (ok); i++) { + ok = (GetSignalType(i).type == SignedInteger); + if (!ok) { + REPORT_ERROR(ErrorManagement::ParametersError, "The signal %d shall be of type SignedInteger", i); + } + ok = (GetSignalType(i).numberOfBits == 32u); + if (!ok) { + REPORT_ERROR(ErrorManagement::ParametersError, "The signal in position %d shall have 32 bits and %d were specified", i, uint16(GetSignalType(i).numberOfBits)); + } + } + StreamString fullDeviceName; + //Configure the board + if (ok) { + ok = fullDeviceName.Printf("%s", deviceName.Buffer()); + } + if (ok) { + ok = fullDeviceName.Seek(0LLU); + } + if (ok) { + boardFileDescriptor = open(fullDeviceName.Buffer(), O_RDWR); + ok = (boardFileDescriptor > -1); + if (!ok) { + REPORT_ERROR_PARAMETERS(ErrorManagement::ParametersError, "Could not open device %s", fullDeviceName); + } + else + REPORT_ERROR(ErrorManagement::Information, "Open device %s OK", fullDeviceName); + } + ok = fullDeviceName.Seek(0LLU); + if (ok) { + ok = fullDeviceName.Printf("%s", deviceDmaName.Buffer()); + } + if (ok) { + ok = fullDeviceName.Seek(0LLU); + } + if (ok) { + boardDmaDescriptor = open(fullDeviceName.Buffer(), O_RDWR); + ok = (boardDmaDescriptor > -1); + if (!ok) { + REPORT_ERROR_PARAMETERS(ErrorManagement::ParametersError, "Could not open DMA device %s", fullDeviceName); + } + else + REPORT_ERROR(ErrorManagement::Information, "Open DMA device %s OK", fullDeviceName); + } + + //mappedDmaBase = (int32 *) mmap(0, getpagesize() * NUMBER_OF_BUFFERS, + mappedDmaBase = (int32 *) mmap(0, 4096u * NUMBER_OF_BUFFERS, + PROT_READ, MAP_SHARED, boardDmaDescriptor, 0); + if (mappedDmaBase == MAP_FAILED){ + ok = false; + REPORT_ERROR(ErrorManagement::FatalError, "Error Mapping DMA Memory Device %s", fullDeviceName); + } + mappedDmaSize = getpagesize(); + + uint32 statusReg = 0; + int rc = ioctl(boardFileDescriptor, ATCA_PCIE_IOPT_DMA_RESET); + //rc = ioctl(boardFileDescriptor, ATCA_PCIE_IOPT_STREAM_DISABLE); + if (chopperPeriod > 0) + { + uint32 chopCounter = (chopperPeriod) << 16; + chopCounter &= 0xFFFF0000; + chopCounter |= chopperPeriod / 2; + + rc = ioctl(boardFileDescriptor, ATCA_PCIE_IOPS_CHOP_COUNTERS, &chopCounter); + //read chopper + chopCounter = 0; + rc = ioctl(boardFileDescriptor, ATCA_PCIE_IOPG_CHOP_COUNTERS, &chopCounter); + + rc = ioctl(boardFileDescriptor, ATCA_PCIE_IOPT_CHOP_ON); + REPORT_ERROR(ErrorManagement::Information, "Chop ON 0x%x", chopCounter); + } + else + rc = ioctl(boardFileDescriptor, ATCA_PCIE_IOPT_CHOP_OFF); + + for (i=0u; i < ATCA_IOP_MAX_CHANNELS ; i++) { + eo_conf.offset[i] = 0u; + wo_conf.offset[i] = 0.0; + } + for (i=0u; i < ATCA_IOP_N_ADCs ; i++) { + eo_conf.offset[i] = electricalOffsets[i]; + wo_conf.offset[i] = wiringOffsets[i]; + } + rc = ioctl(boardFileDescriptor, ATCA_PCIE_IOPS_EO_OFFSETS, &eo_conf); + rc = ioctl(boardFileDescriptor, ATCA_PCIE_IOPS_WO_OFFSETS, &wo_conf); + + rc = ioctl(boardFileDescriptor, ATCA_PCIE_IOPG_STATUS, &statusReg); + if (rc) { + ok = false; + REPORT_ERROR(ErrorManagement::FatalError, "Device Status Reg %d, 0x%x", rc, statusReg); + } + rc = ioctl(boardFileDescriptor, ATCA_PCIE_IOPT_ACQ_ENABLE); + //rc = ioctl(boardFileDescriptor, ATCA_PCIE_IOPT_DMA_DISABLE); + Sleep::Busy(0.001); // in Sec + rc = ioctl(boardFileDescriptor, ATCA_PCIE_IOPT_ACQ_DISABLE); + + rc = ioctl(boardFileDescriptor, ATCA_PCIE_IOPT_IRQ_DISABLE); + rc = ioctl(boardFileDescriptor, ATCA_PCIE_IOPT_STREAM_ENABLE); + //rc = ioctl(boardFileDescriptor, ATCA_PCIE_IOPG_STATUS, &statusReg); + Sleep::Busy(0.0011); // in Sec + int32 currentDMA = 0u;// = CurrentBufferIndex(200); + for (i = 0u; i < 1; i++) { + oldestBufferIdx = GetOldestBufferIdx(); + currentDMA = PollDma(HighResolutionTimer::Counter() + 2000000u); // wait max 2ms + REPORT_ERROR(ErrorManagement::Information, "AtcaIopADC::CurrentBufferIndex: %d, Idx: %d", currentDMA, oldestBufferIdx); + } + REPORT_ERROR(ErrorManagement::Information, "AtcaIopADC::CurrentBufferIndex: %d", currentDMA); + //REPORT_ERROR(ErrorManagement::Warning, "SleepTime %d, count:0x%x", sleepTime, pdma[3].head_time_cnt); + uint32 nOfFunctions = GetNumberOfFunctions(); + float32 cycleFrequency = -1.0F; + bool frequencyFound = false; + uint32 functionIdx; + + //How many GAMs (functions) are interacting with this DataSource? + for (functionIdx = 0u; (functionIdx < nOfFunctions) && (ok); functionIdx++) { + uint32 nOfSignals = 0u; + ok = GetFunctionNumberOfSignals(InputSignals, functionIdx, nOfSignals); + uint32 i; + for (i = 0u; (i < nOfSignals) && (ok); i++) { + if (!frequencyFound) { + ok = GetFunctionSignalReadFrequency(InputSignals, functionIdx, i, cycleFrequency); + //Found a GAM that wants to synchronise on this DataSourceI. We need to have one and exactly one GAM asking to synchronise in this DataSource. + frequencyFound = (cycleFrequency > 0.F); + } + bool isCounter = false; + bool isTime = false; + bool isAdc = false; +// bool isAdcDecim = false; + //bool isAdcSim = false; + uint32 signalIdx = 0u; + uint32 nSamples = 0u; + uint32 nElements = 0u; + + ok = GetFunctionSignalSamples(InputSignals, functionIdx, i, nSamples); + + //Is the counter or the time signal? + StreamString signalAlias; + if (ok) { + ok = GetFunctionSignalAlias(InputSignals, functionIdx, i, signalAlias); + } + if (ok) { + ok = GetSignalIndex(signalIdx, signalAlias.Buffer()); + } + if (ok) { + isCounter = (signalIdx == 0u); + isTime = (signalIdx == 1u); + //isAdcDecim = (signalIdx == 2u); + isAdc= (signalIdx < ATCA_IOP_N_TIMCNT + ATCA_IOP_N_ADCs + ATCA_IOP_N_INTEGRALS); + //isAdcSim = (signalIdx < ATCA_IOP_N_SIGNALS); + if (isCounter) { + if (nSamples > 1u) { + ok = false; + REPORT_ERROR(ErrorManagement::ParametersError, "The first signal (counter) shall have one and only one sample"); + } + } + else if (isTime) { + if (nSamples > 1u) { + ok = false; + REPORT_ERROR(ErrorManagement::ParametersError, "The second signal (time) shall have one and only one sample"); + } + } + /* + else if (isAdcDecim) { + ok = GetSignalNumberOfElements(signalIdx, nElements); + REPORT_ERROR(ErrorManagement::Information, "The ADC decim Signal Elements %d", nElements); + // if (nSamples > 1u) { + // ok = false; + // REPORT_ERROR(ErrorManagement::ParametersError, "The second signal (time) shall have one and only one sample"); + //} + } + */ + else if (isAdc) { + if (nSamples > 1u) { + ok = false; + REPORT_ERROR(ErrorManagement::ParametersError, "The ATCA-IOP signals shall have one and only one sample"); + } + } + /* + else if (isAdcSim) { + //How many samples to read for each cycle? + if (adcSamplesPerCycle == 0u) { + adcSamplesPerCycle = nSamples; + } + else { + if (adcSamplesPerCycle != nSamples) { + ok = false; + REPORT_ERROR(ErrorManagement::ParametersError, "All the ADC signals shall have the same number of samples"); + } + } + + } + */ + else {} + } + } + } + if (ok) { + ok = frequencyFound; + if (!ok) { + REPORT_ERROR(ErrorManagement::ParametersError, "No frequency > 0 was set (i.e. no signal synchronises on this AtcaIopADC)."); + } + } + if (ok) { + REPORT_ERROR(ErrorManagement::Information, "The timer will be set using a cycle frequency of %f Hz", cycleFrequency); + + float64 periodUsec = (1e6 / cycleFrequency); + timerPeriodUsecTime = static_cast(periodUsec); + float64 sleepTimeT = (static_cast(HighResolutionTimer::Frequency()) / cycleFrequency); + sleepTimeTicks = static_cast(sleepTimeT); + REPORT_ERROR(ErrorManagement::Information, + "The timer will be set using a sleepTimeTicks of %d (ns)", sleepTimeTicks); + } + if (ok) { + //float32 totalNumberOfSamplesPerSecond = (static_cast(adcSamplesPerCycle) * cycleFrequency); + float32 totalNumberOfSamplesPerSecond = (static_cast(rtDecimation) * cycleFrequency); + ok = (adcFrequency == static_cast(totalNumberOfSamplesPerSecond)); + if (!ok) { + REPORT_ERROR(ErrorManagement::ParametersError, + "The adcSamplesPerCycle * cycleFrequency (%u) shall be equal to the ADCs acquisition frequency (%u)", + totalNumberOfSamplesPerSecond, adcFrequency); + } + } + return ok; +} + +uint32 AtcaIopADC::GetNumberOfMemoryBuffers() { + return 1u; +} + +/*lint -e{715} [MISRA C++ Rule 0-1-11], [MISRA C++ Rule 0-1-12]. Justification: The memory buffer is independent of the bufferIdx.*/ +bool AtcaIopADC::GetSignalMemoryBuffer(const uint32 signalIdx, const uint32 bufferIdx, void*& signalAddress) { + bool ok = true; + if (signalIdx == 0u) { + signalAddress = &counterAndTimer[0]; + } + else if (signalIdx == 1u) { + signalAddress = &counterAndTimer[1]; + } + else if (signalIdx < ATCA_IOP_N_TIMCNT + ATCA_IOP_N_ADCs ) { + signalAddress = &adcValues[signalIdx - ATCA_IOP_N_TIMCNT]; + } + else if (signalIdx < ATCA_IOP_N_TIMCNT + ATCA_IOP_N_ADCs + ATCA_IOP_N_INTEGRALS) { + signalAddress = &adcIntegralValues[signalIdx - + (ATCA_IOP_N_TIMCNT + ATCA_IOP_N_ADCs)]; + } + else { + ok = false; + } + return ok; +} + +const char8* AtcaIopADC::GetBrokerName(StructuredDataI& data, const SignalDirection direction) { + const char8 *brokerName = NULL_PTR(const char8 *); + if (direction == InputSignals) { + float32 frequency = 0.F; + if (!data.Read("Frequency", frequency)) { + frequency = -1.F; + } + if (frequency > 0.F) { + brokerName = "MemoryMapSynchronisedInputBroker"; + } + else { + brokerName = "MemoryMapInputBroker"; + } + } + else { + REPORT_ERROR(ErrorManagement::ParametersError, "DataSource not compatible with OutputSignals"); + } + return brokerName; +} + +bool AtcaIopADC::Synchronise() { + ErrorManagement::ErrorType err; + err = synchSem.ResetWait(TTInfiniteWait); + return err.ErrorsCleared(); +} + +/*lint -e{715} [MISRA C++ Rule 0-1-11], [MISRA C++ Rule 0-1-12]. Justification: the counter and the timer are always reset irrespectively of the states being changed.*/ +bool AtcaIopADC::PrepareNextState(const char8* const currentStateName, const char8* const nextStateName) { + bool ok = true; + if (executor.GetStatus() == EmbeddedThreadI::OffState) { + ok = executor.Start(); + REPORT_ERROR(ErrorManagement::Information, "Executor Start"); + } + counterAndTimer[0] = 0u; + //counterAndTimer[1] = 0u; + return ok; +} + +/*lint -e{715} [MISRA C++ Rule 0-1-11], [MISRA C++ Rule 0-1-12]. Justification: the method sleeps for the given period irrespectively of the input info.*/ +ErrorManagement::ErrorType AtcaIopADC::Execute(ExecutionInfo& info) { + if (lastTimeTicks == 0u) { + lastTimeTicks = HighResolutionTimer::Counter(); + } + + uint64 startTicks = HighResolutionTimer::Counter(); + //If we lose cycle, rephase to a multiple of the period. + uint32 nCycles = 0u; + while (lastTimeTicks < startTicks) { + lastTimeTicks += sleepTimeTicks; + nCycles++; + } + lastTimeTicks -= sleepTimeTicks; + + //Sleep until the next period. Cannot be < 0 due to while(lastTimeTicks < startTicks) above + uint64 sleepTicksCorrection = (startTicks - lastTimeTicks); + uint64 deltaTicks = sleepTimeTicks - sleepTicksCorrection; + //volatile int32 currentDMA = 0u; + oldestBufferIdx = GetOldestBufferIdx(); + if (sleepNature == Busy) { + if (sleepPercentage == 0u) { + //currentDMA = + PollDma(startTicks + deltaTicks + 100000u); // TODO check max wait + //while ((HighResolutionTimer::Counter() - startTicks) < deltaTicks) { + //} + } + else { + float32 totalSleepTime = static_cast(static_cast(deltaTicks) * HighResolutionTimer::Period()); + uint32 busyPercentage = (100u - sleepPercentage); + float32 busyTime = totalSleepTime * (static_cast(busyPercentage) / 100.F); + Sleep::SemiBusy(totalSleepTime, busyTime); + } + } + else { + float32 sleepTime = static_cast(static_cast(deltaTicks) * HighResolutionTimer::Period()); + Sleep::NoMore(sleepTime); + } + lastTimeTicks = HighResolutionTimer::Counter(); + + ErrorManagement::ErrorType err = synchSem.Post(); + counterAndTimer[0] += nCycles; + //counterAndTimer[1] = counterAndTimer[0] * timerPeriodUsecTime; + counterAndTimer[1] = mappedDmaBase[oldestBufferIdx * RT_PCKT_SIZE] * timerPeriodUsecTime; + // Get adc data from DMA packet + uint32 k; + uint32 s; + for (k=0u; k < ATCA_IOP_N_ADCs ; k++) { + adcValues[k] = (mappedDmaBase[oldestBufferIdx * RT_PCKT_SIZE + + IOP_ADC_OFFSET + k] ) / (1<<14); + } + int64 * mappedDmaBase64 = (int64 *) mappedDmaBase; + for (k=0u; k < ATCA_IOP_N_INTEGRALS ; k++) { + adcIntegralValues[k] = mappedDmaBase64[oldestBufferIdx * RT_PCKT64_SIZE + IOP_ADC_INTEG_OFFSET + k]; + } + + float64 t = counterAndTimer[1]; + t /= 1e6; + // Compute simulated Sinus Signals + return err; +} + +const ProcessorType& AtcaIopADC::GetCPUMask() const { + return cpuMask; +} + +uint32 AtcaIopADC::GetStackSize() const { + return stackSize; +} + +uint32 AtcaIopADC::GetSleepPercentage() const { + return sleepPercentage; +} + +int32 AtcaIopADC::PollDma(uint64 waitLimitTicks) const { + uint32 buffIdx = oldestBufferIdx; + uint32 oldBufferFooter = mappedDmaBase[buffIdx * RT_PCKT_SIZE + 62]; + uint32 freshBufferFooter = oldBufferFooter; + uint64 actualTime = HighResolutionTimer::Counter(); + while (freshBufferFooter == oldBufferFooter) { + if(actualTime > waitLimitTicks) { + return -1; + } + actualTime = HighResolutionTimer::Counter(); + freshBufferFooter = mappedDmaBase[buffIdx * RT_PCKT_SIZE + 62]; + } + uint32 headTimeMark = mappedDmaBase[buffIdx * RT_PCKT_SIZE]; + if(headTimeMark != freshBufferFooter) + { + //currentBufferIdx = buffIdx; + //currentMasterHeader = pdma[currentBufferIdx].head_time_cnt; + return -2; + } + return buffIdx; +} +uint32 AtcaIopADC::GetOldestBufferIdx() const { + volatile uint32 oldestBufferHeader = mappedDmaBase[0]; + uint32 buffIdx = 0u; + + volatile uint32 header = mappedDmaBase[0]; + for (uint32 dmaIndex = 1u; dmaIndex < NUMBER_OF_BUFFERS; dmaIndex++) { + header = mappedDmaBase[dmaIndex * RT_PCKT_SIZE]; + if (header < oldestBufferHeader) { + oldestBufferHeader = header; + buffIdx = dmaIndex; + } + } + return buffIdx; +} + +CLASS_REGISTER(AtcaIopADC, "1.0") + +} + +// vim: syntax=cpp ts=4 sw=4 sts=4 sr et diff --git a/DataSources/AtcaIop/AtcaIopADC.h b/DataSources/AtcaIop/AtcaIopADC.h new file mode 100644 index 0000000..790298d --- /dev/null +++ b/DataSources/AtcaIop/AtcaIopADC.h @@ -0,0 +1,435 @@ +/** + * @file AtcaIopADC.h + * @brief Header file for class AtcaIopADC + * @date 19/10/2023 + * @author Andre Neto / Bernardo Carvalho + * + * Based on Example: + * https://vcis-gitlab.f4e.europa.eu/aneto/MARTe2-demos-padova/-/tree/master/DataSources/ADCSimulator + * + * + * @copyright Copyright 2015 F4E | European Joint Undertaking for ITER and + * the Development of Fusion Energy ('Fusion for Energy'). + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved + * by the European Commission - subsequent versions of the EUPL (the "Licence") + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: http://ec.europa.eu/idabc/eupl + * + * @warning Unless required by applicable law or agreed to in writing, + * software distributed under the Licence is distributed on an "AS IS" + * basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence permissions and limitations under the Licence. + + * @details This header file contains the declaration of the class AtcaIopADC + * with all of its public, protected and private members. It may also include + * definitions for inline methods which need to be visible to the compiler. + */ + +#ifndef ATCA_IOP_ADC_H +#define ATCA_IOP_ADC_H + +/*---------------------------------------------------------------------------*/ +/* Standard header includes */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Project header includes */ +/*---------------------------------------------------------------------------*/ +#include "DataSourceI.h" +#include "EventSem.h" +#include "EmbeddedServiceMethodBinderI.h" +#include "SingleThreadService.h" +#include "MessageI.h" +#include "RegisteredMethodsMessageFilter.h" + +/*---------------------------------------------------------------------------*/ +/* Class declaration */ +/*---------------------------------------------------------------------------*/ +namespace MARTe { + + /** + * The number of signals (2 time signals + ). + */ + const uint32 ATCA_IOP_MAX_CHANNELS = 32u; + + const uint32 ATCA_IOP_N_TIMCNT = 2u; + const uint32 ATCA_IOP_N_ADCs = 12u; + const uint32 ATCA_IOP_N_INTEGRALS = ATCA_IOP_N_ADCs ; //12u; + //const uint32 ADC_SIMULATOR_N_ADCs = 2u; + const uint32 ATCA_IOP_N_SIGNALS = (ATCA_IOP_N_TIMCNT + ATCA_IOP_N_ADCs + + ATCA_IOP_N_INTEGRALS); + /** + * The number of buffers to synchronise with the DMA + */ + const uint32 NUMBER_OF_BUFFERS = 8u; + + /** + * @brief A DataSource that simulates an ADC board + * TODO + *
+     * +ADCSim = {
+     *     Class = ADCSimulator
+     *     DeviceName = "/dev/atca_v6" //Mandatory
+     *     BoardId = 0          //   Mandatory
+     *     ChopperPeriod = 2000
+     *     ElectricalOffsets = {1, 10, 20, -30, 1, 1, -10, 10}
+     *     WiringOffsets = {1, 10, 20, -30, 1, 1, -10, 10}
+     *     ADCFrequency = 2000000
+     *     Signals = {
+     *         Counter = {
+     *             Type = uint32 //int32 also supported
+     *         }
+     *         Time = {
+     *             Type = uint32 //int32 also supported
+     *             Frequency = 1000
+     *         }
+     *         ADC0 = {
+     *             Type = uint32
+     *         }
+     *         ADC1 = {
+     *             Type = uint32
+     *         }
+     *         ADC2 = {
+     *             Type = uint32
+     *         }
+     *         ADC3 = {
+     *             Type = uint32
+     *         }
+     *         ADC0Decim = {
+     *             Type = uint32
+     *         }
+     *         ADC1Decim = {
+     *             Type = uint32
+     *         }
+     *         ADC2Decim = {
+     *             Type = uint32
+     *         }
+     *         ...
+     *         ADC7Decim = {
+     *             Type = uint32
+     *         }
+     *     }
+     * }
+     * 
+ */ + class AtcaIopADC: public DataSourceI, public MessageI, public EmbeddedServiceMethodBinderI { + public: + CLASS_REGISTER_DECLARATION() + /** + * @brief Default constructor + * @post + * Counter = 0 + * Time = 0 + */ + AtcaIopADC (); + + /** + * @brief Destructor. Stops the EmbeddedThread. + */ + virtual ~AtcaIopADC(); + + /** + * @brief See DataSourceI::AllocateMemory. + */ + virtual bool AllocateMemory(); + + /** + gg* @brief See DataSourceI::GetNumberOfMemoryBuffers. + * @return 1. + */ + virtual uint32 GetNumberOfMemoryBuffers(); + + /** + * @brief See DataSourceI::GetNumberOfMemoryBuffers. + */ + virtual bool GetSignalMemoryBuffer(const uint32 signalIdx, + const uint32 bufferIdx, + void *&signalAddress); + + /** + * @brief See DataSourceI::GetNumberOfMemoryBuffers. + * @details Only InputSignals are supported. + * @return MemoryMapSynchronisedInputBroker if frequency > 0, MemoryMapInputBroker otherwise. + */ + virtual const char8 *GetBrokerName(StructuredDataI &data, + const SignalDirection direction); + + /** + * @brief Waits on an EventSem for the period given by 1/Frequency to elapse on Execute. + * @return true if the semaphore is successfully posted. + */ + virtual bool Synchronise(); + + /** + if (boardFileDescriptor != -1) { + close(boardFileDescriptor); + } + * @brief Callback function for an EmbeddedThread. + * @details Sleeps (Busy or Default) for the period given by 1/Frequency and post an EventSem which is waiting on + * the Synchronise method. + * @param[in] info not used. + * @return NoError if the EventSem can be successfully posted. + */ + virtual ErrorManagement::ErrorType Execute(ExecutionInfo & info); + + /** + * @brief Resets the counter and the timer to zero and starts the EmbeddedThread. + * @details See StatefulI::PrepareNextState. Starts the EmbeddedThread (if it was not already started) and loops + * on the ExecuteMethod. + * @return true if the EmbeddedThread can be successfully started. + */ + virtual bool PrepareNextState(const char8 * const currentStateName, + const char8 * const nextStateName); + + /** + * @brief Initialises the AtcaIopADC + * @param[in] data configuration in the form: + * +AtcaIopADC = { + * Class = AtcaIopADC + * Signals = { + * Counter = { + * Type = uint32 //int32 also supported + * } + * Time = { + * Type = uint32 //int32 also supported + * Frequency = 10000 + * } + * ADC0 = { + * Type = uint32 + * } + * ADC1 = { + * Type = uint32 + * } + * ADC2 = { + * Type = uint32 + * } + * ADC3 = { + * Type = uint32 + * } + * } + * } + * @return TODO + */ + virtual bool Initialise(StructuredDataI & data); + + /** + * @brief Verifies that two, and only two, signal are set with the correct type. + * @details Verifies that two, and only two, signal are set; that the signals are + * 32 bits in size with a SignedInteger or UnsignedInteger type and that a Frequency > 0 was set in one of the two signals. + * @param[in] data see DataSourceI::SetConfiguredDatabase + * @return true if the rules above are met. + */ + virtual bool SetConfiguredDatabase(StructuredDataI & data); + + /** + * @brief Gets the affinity of the thread which is going to be used to asynchronously wait for the time to elapse. + * @return the affinity of the thread which is going to be used to asynchronously wait for the time to elapse. + */ + const ProcessorType& GetCPUMask() const; + + /** + * @brief Gets the stack size of the thread which is going to be used to asynchronously wait for the time to elapse. + * @return the stack size of the thread which is going to be used to asynchronously wait for the time to elapse. + */ + uint32 GetStackSize() const; + + /** + * @brief Gets the percentage of the time to sleep using the OS sleep (i.e. the non-busy Sleep). + * @return the percentage of the time to sleep using the OS sleep (i.e. the non-busy Sleep). + */ + uint32 GetSleepPercentage() const; + + /** + * Find the currentDMABufferIndex and synchronize on data arrival + */ +// int32 CurrentBufferIndex(uint64 waitLimitUs) const; + + private: + /** + * The board identifier + */ + //uint32 boardId; + /** + * The numberOfChannels + */ + uint32 numberOfChannels; + /** + * The FPGA ADC Decimation factor from 2MSPS + */ + uint32 rtDecimation; + /** + * The board device name + */ + StreamString deviceName; + /** + * The board device name + */ + StreamString deviceDmaName; + /** + * The board file descriptor + */ + int32 boardFileDescriptor; + + /** + * The board Dma descriptor + */ + int32 boardDmaDescriptor; + + /** + * The two supported sleep natures. + */ + enum AtcaIopADCSleepNature { + Default = 0, + Busy = 1 + }; + + /** + * The non-busy sleep percentage. Valid if + * AtcaIopADCSleepNature == Busy + */ + uint32 sleepPercentage; + + /** + * The selected sleep nature. + */ + AtcaIopADCSleepNature sleepNature; + + /** + * Current counter and timer + */ + uint32 counterAndTimer[2]; + + /** + * ADC values + */ + int32 adcValues[ATCA_IOP_MAX_CHANNELS]; + + /** + * ADC Integral values + */ + int64 adcIntegralValues[ATCA_IOP_MAX_CHANNELS]; + + /** + * Number of samples to read on each cycle + */ + uint32 adcSamplesPerCycle; + + /** + * The semaphore for the synchronisation between the EmbeddedThread and the Synchronise method. + */ + EventSem synchSem; + + /** + * The EmbeddedThread where the Execute method waits for the period to elapse. + */ + SingleThreadService executor; + + /** + * HighResolutionTimer::Counter() value after the last Sleep. + */ + uint64 lastTimeTicks; + + /** + * Sleeping period in units of ticks. + */ + uint64 sleepTimeTicks; + + /** + * Sleeping period. + */ + uint32 timerPeriodUsecTime; + + /** + * Index of the function which has the signal that synchronises on this DataSourceI. + */ + uint32 synchronisingFunctionIdx; + + /** + * The affinity of the thread that asynchronously generates the time. + */ + ProcessorType cpuMask; + + /** + * The size of the stack of the thread that asynchronously generates the time. + */ + uint32 stackSize; + + /** + * The simulated signals frequencies. + */ + //float32 signalsFrequencies[4]; + + /** + * The simulated signals gains. + */ + + /** + * The Electrical Offset Parameters. + */ + int32 electricalOffsets[ATCA_IOP_MAX_CHANNELS]; + + /** + * The Wiring Offset Parameters. + */ + float32 wiringOffsets[ATCA_IOP_MAX_CHANNELS]; + + /** + * The ADC chopping period in samples + */ + uint16 chopperPeriod; + + /** + * The simulated ADC frequency + */ + uint32 adcFrequency; + + /** + * The simulated ADC period + */ + float64 adcPeriod; + + /** + * For the ATCA Master board + */ + uint32 isMaster; + /** + * Pointer to mapped memory + */ + int32 * mappedDmaBase; + uint32 mappedDmaSize; + /** + * The last written buffer + */ + uint8 currentBufferIdx; + + /** + * The oldest written DMA buffer index + */ + uint8 oldestBufferIdx; + /** + * The last read buffer index + */ + uint8 lastBufferIdx; + + /* + * Find the latest completed buffer without synchronization + */ + int32 GetLatestBufferIndex() const; + uint32 GetOldestBufferIdx() const; + int32 PollDma(uint64 waitLimitTicks) const; + + /** + * filter to receive the RPC which ... + */ + ReferenceT filter; + + }; +} + +/*---------------------------------------------------------------------------*/ +/* Inline method definitions */ +/*---------------------------------------------------------------------------*/ + +#endif /* ATCA_IOP_ADC_H */ + +// vim: syntax=cpp ts=4 sw=4 sts=4 sr et diff --git a/DataSources/AtcaIop/AtcaIopDAC.cpp b/DataSources/AtcaIop/AtcaIopDAC.cpp new file mode 100644 index 0000000..82bf70b --- /dev/null +++ b/DataSources/AtcaIop/AtcaIopDAC.cpp @@ -0,0 +1,374 @@ +/** + * @file AtcaIopDAC.cpp + * @brief Source file for class AtcaIopDAC + * @date 19/01/2024 + * @author Andre Neto / Bernardo Carvalho + * + * @copyright Copyright 2015 F4E | European Joint Undertaking for ITER and + * the Development of Fusion Energy ('Fusion for Energy'). + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved + * by the European Commission - subsequent versions of the EUPL (the "Licence") + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: http://ec.europa.eu/idabc/eupl + * + * @warning Unless required by applicable law or agreed to in writing, + * software distributed under the Licence is distributed on an "AS IS" + * basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence permissions and limitations under the Licence. + + * @details This source file contains the definition of all the methods for + * the class AtcaIopDAC (public, protected, and private). Be aware that some + * methods, such as those inline could be defined on the header file, instead. + * + * https://vcis-gitlab.f4e.europa.eu/aneto/MARTe2-components/-/blob/master/Source/Components/DataSources/NI6259/NI6259DAC.cpp + */ + +#define DLL_API + +/*---------------------------------------------------------------------------*/ +/* Standard header includes */ +/*---------------------------------------------------------------------------*/ +#include + +#include // for close() +#include + +/*---------------------------------------------------------------------------*/ +/* Project header includes */ +/*---------------------------------------------------------------------------*/ +#include "AdvancedErrorManagement.h" +#include "MemoryMapSynchronisedOutputBroker.h" +#include "AtcaIopDAC.h" + +/*---------------------------------------------------------------------------*/ +/* Static definitions */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Method definitions */ +/*---------------------------------------------------------------------------*/ +namespace MARTe { + const float32 DAC_RANGE = 20.0; + const float32 ATCA_IOP_MAX_DAC_RANGE = 20.0; + AtcaIopDAC::AtcaIopDAC() : + DataSourceI(), + MessageI() { + boardFileDescriptor = -1; + numberOfDACsEnabled = 0u; + //isMaster = 0u; + deviceName = ""; + triggerSet = false; + uint32 n; + for (n = 0u; n < ATCA_IOP_MAX_DAC_CHANNELS; n++) { + //dacEnabled[n] = false; + outputRange[n] = ATCA_IOP_MAX_DAC_RANGE; + } + + channelsMemory = NULL_PTR(float32 *); + + filter = ReferenceT(GlobalObjectsDatabase::Instance()->GetStandardHeap()); + filter->SetDestination(this); + ErrorManagement::ErrorType ret = MessageI::InstallMessageFilter(filter); + if (!ret.ErrorsCleared()) { + REPORT_ERROR(ErrorManagement::FatalError, "Failed to install message filters"); + } + } + + /*lint -e{1551} the destructor must guarantee that the Timer SingleThreadService is stopped.*/ + AtcaIopDAC::~AtcaIopDAC() { + if (boardFileDescriptor != -1) { + uint32 statusReg = 0; + //REPORT_ERROR(ErrorManagement::Information, " Close Device Status Reg %d, 0x%x", rc, statusReg); + close(boardFileDescriptor); + REPORT_ERROR(ErrorManagement::Information, "Close device %d OK. Status Reg 0x%x,", boardFileDescriptor, statusReg); + } + if (channelsMemory != NULL_PTR(float32 *)) { + delete[] channelsMemory; + } + } + + bool AtcaIopDAC::AllocateMemory() { + return true; + } + + uint32 AtcaIopDAC::GetNumberOfMemoryBuffers() { + return 1u; + } + + /*lint -e{715} [MISRA C++ Rule 0-1-11], [MISRA C++ Rule 0-1-12]. Justification: The memory buffer is independent of the bufferIdx.*/ + bool AtcaIopDAC::GetSignalMemoryBuffer(const uint32 signalIdx, const uint32 bufferIdx, void*& signalAddress) { + bool ok = (signalIdx < (ATCA_IOP_MAX_DAC_CHANNELS)); + if (ok) { + if (channelsMemory != NULL_PTR(float32 *)) { + signalAddress = &(channelsMemory[signalIdx]); + } + } + return ok; + } + + const char8* AtcaIopDAC::GetBrokerName(StructuredDataI& data, const SignalDirection direction) { + const char8 *brokerName = NULL_PTR(const char8 *); + if (direction == OutputSignals) { + uint32 trigger = 0u; + if (!data.Read("Trigger", trigger)) { + trigger = 0u; + } + + if (trigger == 1u) { + brokerName = "MemoryMapSynchronisedOutputBroker"; + triggerSet = true; + } + else { + brokerName = "MemoryMapOutputBroker"; + } + } + else { + REPORT_ERROR(ErrorManagement::ParametersError, "DataSource not compatible with InputSignals"); + } + return brokerName; + } + bool AtcaIopDAC::GetInputBrokers(ReferenceContainer& inputBrokers, const char8* const functionName, void* const gamMemPtr) { + return false; + } + + bool AtcaIopDAC::GetOutputBrokers(ReferenceContainer& outputBrokers, const char8* const functionName, void* const gamMemPtr) { + //Check if there is a Trigger signal for this function. + uint32 functionIdx = 0u; + uint32 nOfFunctionSignals = 0u; + uint32 i; + bool triggerGAM = false; + bool ok = GetFunctionIndex(functionIdx, functionName); + + if (ok) { + ok = GetFunctionNumberOfSignals(OutputSignals, functionIdx, nOfFunctionSignals); + } + uint32 trigger = 0u; + for (i = 0u; (i < nOfFunctionSignals) && (ok) && (!triggerGAM); i++) { + ok = GetFunctionSignalTrigger(OutputSignals, functionIdx, i, trigger); + triggerGAM = (trigger == 1u); + } + if ((ok) && (triggerGAM)) { + ReferenceT broker("MemoryMapSynchronisedOutputBroker"); + ok = broker.IsValid(); + + if (ok) { + ok = broker->Init(OutputSignals, *this, functionName, gamMemPtr); + } + if (ok) { + ok = outputBrokers.Insert(broker); + } + //Must also add the signals which are not triggering but that belong to the same GAM... + if (ok) { + if (nOfFunctionSignals > 1u) { + ReferenceT brokerNotSync("MemoryMapOutputBroker"); + ok = brokerNotSync.IsValid(); + if (ok) { + ok = brokerNotSync->Init(OutputSignals, *this, functionName, gamMemPtr); + } + if (ok) { + ok = outputBrokers.Insert(brokerNotSync); + } + } + } + } + else { + ReferenceT brokerNotSync("MemoryMapOutputBroker"); + ok = brokerNotSync.IsValid(); + if (ok) { + ok = brokerNotSync->Init(OutputSignals, *this, functionName, gamMemPtr); + } + if (ok) { + ok = outputBrokers.Insert(brokerNotSync); + } + } + return ok; + } + + /*lint -e{715} [MISRA C++ Rule 0-1-11], [MISRA C++ Rule 0-1-12]. Justification: the counter and the timer are always reset irrespectively of the states being changed.*/ + bool AtcaIopDAC::PrepareNextState(const char8* const currentStateName, const char8* const nextStateName) { + return true; + } + + bool AtcaIopDAC::Initialise(StructuredDataI& data) { + bool ok = DataSourceI::Initialise(data); + if (ok) { + ok = data.Read("DeviceName", deviceName); + if (!ok) { + REPORT_ERROR(ErrorManagement::ParametersError, "The DeviceName shall be specified"); + } + } + + //if (!data.Read("IsMaster", isMaster)) { + // REPORT_ERROR(ErrorManagement::Warning, "IsMaster not specified. Using default: %d", isMaster); + //} + + //Get individual signal parameters + uint32 i = 0u; + if (ok) { + ok = data.MoveRelative("Signals"); + if (!ok) { + REPORT_ERROR(ErrorManagement::ParametersError, "Could not move to the Signals section"); + } + //Do not allow to add signals in run-time + if (ok) { + ok = signalsDatabase.MoveRelative("Signals"); + } + if (ok) { + ok = signalsDatabase.Write("Locked", 1u); + } + if (ok) { + ok = signalsDatabase.MoveToAncestor(1u); + } + while ((i < ATCA_IOP_MAX_DAC_CHANNELS) && (ok)) { + if (data.MoveRelative(data.GetChildName(i))) { + //uint32 channelId; + float32 range; + ok = data.Read("OutputRange", range); + if (ok) { + //if (data.Read("OutputRange", range)) { + ok = (range > 0.0) && (range <= ATCA_IOP_MAX_DAC_RANGE); + if (!ok) { + REPORT_ERROR(ErrorManagement::ParametersError, "Invalid OutputRange specified."); + } + if (ok) { + outputRange[i] = range; + REPORT_ERROR(ErrorManagement::Information, " Parameter DAC %d Output Range %f", i, range); + //dacEnabled[i] = true; + numberOfDACsEnabled++; + } + } + else { + REPORT_ERROR(ErrorManagement::ParametersError, "The OutputRange shall be specified."); + } + if (ok) { + ok = data.MoveToAncestor(1u); + } + i++; + } + else { + break; + } + } + } + if (ok) { + ok = data.MoveToAncestor(1u); + if (!ok) { + REPORT_ERROR(ErrorManagement::ParametersError, "Could not move to the parent section"); + } + } + + REPORT_ERROR(ErrorManagement::Information, "numberOfDACsEnabled %d", numberOfDACsEnabled); + + return ok; + } + + bool AtcaIopDAC::SetConfiguredDatabase(StructuredDataI& data) { + uint32 i; + bool ok = DataSourceI::SetConfiguredDatabase(data); + + if (ok) { + ok = triggerSet; + } + if (!ok) { + REPORT_ERROR(ErrorManagement::ParametersError, "At least one Trigger signal shall be set."); + } + if (ok) { + for (i = 0u; (i < numberOfDACsEnabled) && (ok); i++) { + ok = (GetSignalType(i) == Float32Bit); + } + if (!ok) { + REPORT_ERROR(ErrorManagement::ParametersError, "All the DAC signals shall be of type Float32Bit"); + } + } + + uint32 nOfFunctions = GetNumberOfFunctions(); + uint32 functionIdx; + //Check that the number of samples for all the signals is one + for (functionIdx = 0u; (functionIdx < nOfFunctions) && (ok); functionIdx++) { + uint32 nOfSignals = 0u; + ok = GetFunctionNumberOfSignals(OutputSignals, functionIdx, nOfSignals); + + for (i = 0u; (i < nOfSignals) && (ok); i++) { + uint32 nSamples = 0u; + ok = GetFunctionSignalSamples(OutputSignals, functionIdx, i, nSamples); + if (ok) { + ok = (nSamples == 1u); + } + if (!ok) { + REPORT_ERROR(ErrorManagement::ParametersError, "The number of samples shall be exactly one"); + } + } + } + + StreamString fullDeviceName; + //Configure the board + if (ok) { + ok = fullDeviceName.Printf("%s", deviceName.Buffer()); + } + if (ok) { + ok = fullDeviceName.Seek(0LLU); + } + if (ok) { + boardFileDescriptor = open(fullDeviceName.Buffer(), O_RDWR); + ok = (boardFileDescriptor > -1); + if (!ok) { + REPORT_ERROR_PARAMETERS(ErrorManagement::ParametersError, "Could not open device %s", fullDeviceName); + } + else + REPORT_ERROR(ErrorManagement::Information, "Open device %s OK", fullDeviceName); + } + if (ok) { + //Allocate memory + channelsMemory = new float32[ATCA_IOP_MAX_DAC_CHANNELS]; + } + + return ok; + } + + + bool AtcaIopDAC::Synchronise() { + uint32 i; + int32 w; + bool ok = true; + if (channelsMemory != NULL_PTR(float32 *)) { + +// value = channelsMemory[0] / DAC_RANGE; + for (i = 0u; (i < 2u) && (ok); i++) { + //for (i = 0u; (i < numberOfDACsEnabled ) && (ok); i++) { + float32 value = channelsMemory[i] / outputRange[i]; + w = SetDacReg(i, value); + write(boardFileDescriptor, &w, 4); + // value = channelsMemory[1] / DAC_RANGE; + //value = channelsMemory[1] / DAC_RANGE * pow(2,17); + // w = SetDacReg(1, value); + //w = 0x000FFFFF & static_cast(value); + // write(boardFileDescriptor, &w, 4); + //REPORT_ERROR(ErrorManagement::Information, " Writing DAC 0 0x%x", w); + } + } + /* + + w = dacValues[i]; + } + */ + return ok; + } + + int32 AtcaIopDAC::SetDacReg(uint32 channel, float32 val) const { + if (val > 1.0) + val = 1.0; + if (val < -1.0) + val = -1.0; + int32 dacReg = static_cast(val * pow(2,17)); + if (dacReg > 0x1FFFF) // 131071 + dacReg = 0x1FFFF; + if (dacReg < -131072) // -0x20000 + dacReg = -131072; + dacReg &= 0x0003FFFF; // keep 18 lsb + dacReg |= (0xF & channel) << 28; + return dacReg; + } + + CLASS_REGISTER(AtcaIopDAC, "1.0") + } + // vim: syntax=cpp ts=4 sw=4 sts=4 sr et diff --git a/DataSources/AtcaIop/AtcaIopDAC.h b/DataSources/AtcaIop/AtcaIopDAC.h new file mode 100644 index 0000000..79b69c6 --- /dev/null +++ b/DataSources/AtcaIop/AtcaIopDAC.h @@ -0,0 +1,236 @@ +/** + * @file AtcaIopDAC.h + * @brief Header file for class AtcaIopDAC + * @date 19/01/2024 + * @author Andre Neto / Bernardo Carvalho + * + * Based on Example: + * https://vcis-gitlab.f4e.europa.eu/aneto/MARTe2-demos-padova/-/tree/master/DataSources/ADCSimulator + * + * + * @copyright Copyright 2015 F4E | European Joint Undertaking for ITER and + * the Development of Fusion Energy ('Fusion for Energy'). + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved + * by the European Commission - subsequent versions of the EUPL (the "Licence") + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: http://ec.europa.eu/idabc/eupl + * + * @warning Unless required by applicable law or agreed to in writing, + * software distributed under the Licence is distributed on an "AS IS" + * basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence permissions and limitations under the Licence. + + * @details This header file contains the declaration of the class AtcaIopDAC + * with all of its public, protected and private members. It may also include + * definitions for inline methods which need to be visible to the compiler. + */ + +#ifndef ATCA_IOP_DAC_H +#define ATCA_IOP_DAC_H + +/*---------------------------------------------------------------------------*/ +/* Standard header includes */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Project header includes */ +/*---------------------------------------------------------------------------*/ +#include "DataSourceI.h" +#include "EventSem.h" +#include "EmbeddedServiceMethodBinderI.h" +#include "SingleThreadService.h" +#include "MessageI.h" +#include "RegisteredMethodsMessageFilter.h" + +/*---------------------------------------------------------------------------*/ +/* Class declaration */ +/*---------------------------------------------------------------------------*/ +namespace MARTe { + + /** + * The number of signals + */ + + const uint32 ATCA_IOP_N_DACs = 2u; + const uint32 ATCA_IOP_MAX_DAC_CHANNELS = 16u; + +/** + * @brief A DataSource which provides an analogue output interface to the ATCA IOP boards. + * @details The configuration syntax is (names are only given as an example): + * + *
+ * +AtcaIop_0_DAC = {
+ *     Class = AtcaIop::AtcaIopDAC
+ *     DeviceName = "/dev/atca_v6_dac_2" //Mandatory
+ *     Signals = {
+ *         DAC0_0 = {
+ *             Type = float32 //Mandatory. Only type that is supported.
+ *             OutputRange = 10.0 //Mandatory. The channel Module Output Range in volt.
+ *             //OutputPolarity = Bipolar //Optional. Possible values: Bipolar, Unipolar. Default value Unipolar.
+ *         }
+ *     }
+ * }
+ * 
+ * Note that at least one of the GAMs writing to this DataSource must have set one of the signals with Trigger=1 (which forces the writing of all the signals to the DAC). + */ + class AtcaIopDAC: public DataSourceI, public MessageI { + public: + CLASS_REGISTER_DECLARATION() + /** + * @brief Default constructor + * @post + * Counter = 0 + * Time = 0 + */ + AtcaIopDAC (); + + /** + * @brief Destructor. Stops the EmbeddedThread. + */ + virtual ~AtcaIopDAC(); + + /** + * @brief See DataSourceI::AllocateMemory. + * * @return true. + */ + virtual bool AllocateMemory(); + + /** + gg* @brief See DataSourceI::GetNumberOfMemoryBuffers. + * @return 1. + */ + virtual uint32 GetNumberOfMemoryBuffers(); + + /** + * @brief See DataSourceI::GetSignalMemoryBuffer. + */ + virtual bool GetSignalMemoryBuffer(const uint32 signalIdx, + const uint32 bufferIdx, + void *&signalAddress); + + + /** + * @brief See DataSourceI::GetNumberOfMemoryBuffers. + * @details Only OutputSignals are supported. + * @return MemoryMapSynchronisedOutputBroker if Trigger == 1 for any of the signals, MemoryMapOutputBroker otherwise. + */ + virtual const char8 *GetBrokerName(StructuredDataI &data, const SignalDirection direction); + + /** + * @brief See DataSourceI::GetInputBrokers. + * @return false. + */ + virtual bool GetInputBrokers(ReferenceContainer &inputBrokers, + const char8* const functionName, + void * const gamMemPtr); + + /** + * @brief See DataSourceI::GetOutputBrokers. + * @details If the functionName is one of the functions which requested a Trigger, + * it adds a MemoryMapSynchronisedOutputBroker instance to the outputBrokers, + * otherwise it adds a MemoryMapOutputBroker instance to the outputBrokers. + * @param[out] outputBrokers where the BrokerI instances have to be added to. + * @param[in] functionName name of the function being queried. + * @param[in] gamMemPtr the GAM memory where the signals will be read from. + * @return true if the outputBrokers can be successfully configured. + */ + virtual bool GetOutputBrokers(ReferenceContainer &outputBrokers, + const char8* const functionName, + void * const gamMemPtr); + + + /** + * @brief See StatefulI::PrepareNextState. + * @details NOOP. + * @return true. + */ + virtual bool PrepareNextState(const char8 * const currentStateName, + const char8 * const nextStateName); + + + /** + * @brief Loads and verifies the configuration parameters detailed in the class description. + * @return true if all the mandatory parameters are correctly specified and if the specified optional parameters have valid values. + */ + + virtual bool Initialise(StructuredDataI & data); + + + /** + * @brief Final verification of all the parameters and setup of the board configuration. + * @details This method verifies that all the parameters (e.g. number of samples) requested by the GAMs interacting with this DataSource + * are valid and consistent with the board parameters set during the initialisation phase. + * In particular the following conditions shall be met: + * - At least one triggering signal was requested by a GAM (with the property Trigger = 1) + * - All the DAC channels have type float32. + * - The number of samples of all the DAC channels is exactly one. + * @return true if all the parameters are valid and consistent with the board parameters and if the board can be successfully configured with + * these parameters. + */ + virtual bool SetConfiguredDatabase(StructuredDataI & data); + + + /** + * @details Writes the value of all the DAC channels to the board. + * @return true if the writing of all the channels is successful. + */ + virtual bool Synchronise(); + + + private: + /** + * The board device name + */ + StreamString deviceName; + /** + * The board file descriptor + */ + int32 boardFileDescriptor; + + /** + * DAC values + */ + int32 dacValues[ATCA_IOP_N_DACs]; + + /** + * The signal memory + */ + float32 *channelsMemory; + + /** + * The DACs that are enabled + */ + // bool dacEnabled[ATCA_IOP_MAX_DAC_CHANNELS]; + + /** + * The board individual channel output ranges + */ + float32 outputRange[ATCA_IOP_MAX_DAC_CHANNELS]; + + /** + * The number of enabled DACs + */ + uint32 numberOfDACsEnabled; + + /** + * Filter to receive the RPC which allows to change the... + */ + ReferenceT filter; + + /** + * True if at least one trigger was set. + */ + bool triggerSet; + + int32 SetDacReg(uint32 channel, float32 val) const; + + }; +} + +/*---------------------------------------------------------------------------*/ +/* Inline method definitions */ +/*---------------------------------------------------------------------------*/ + +#endif /* ATCA_IOP_DAC_H */ + +// vim: syntax=cpp ts=4 sw=4 sts=4 sr et diff --git a/DataSources/AtcaIop/Makefile.cov b/DataSources/AtcaIop/Makefile.cov new file mode 100644 index 0000000..5e0ca6d --- /dev/null +++ b/DataSources/AtcaIop/Makefile.cov @@ -0,0 +1,28 @@ +############################################################# +# +# Copyright 2015 F4E | European Joint Undertaking for ITER +# and the Development of Fusion Energy ('Fusion for Energy') +# +# Licensed under the EUPL, Version 1.1 or - as soon they +# will be approved by the European Commission - subsequent +# versions of the EUPL (the "Licence"); +# You may not use this work except in compliance with the +# Licence. +# You may obtain a copy of the Licence at: +# +# http://ec.europa.eu/idabc/eupl +# +# Unless required by applicable law or agreed to in +# writing, software distributed under the Licence is +# distributed on an "AS IS" basis, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either +# express or implied. +# See the Licence for the specific language governing +# permissions and limitations under the Licence. +# +############################################################# + +TARGET=cov + +include Makefile.inc + diff --git a/DataSources/AtcaIop/Makefile.gcc b/DataSources/AtcaIop/Makefile.gcc new file mode 100644 index 0000000..a9d0599 --- /dev/null +++ b/DataSources/AtcaIop/Makefile.gcc @@ -0,0 +1,27 @@ +############################################################# +# +# Copyright 2015 F4E | European Joint Undertaking for ITER +# and the Development of Fusion Energy ('Fusion for Energy') +# +# Licensed under the EUPL, Version 1.1 or - as soon they +# will be approved by the European Commission - subsequent +# versions of the EUPL (the "Licence"); +# You may not use this work except in compliance with the +# Licence. +# You may obtain a copy of the Licence at: +# +# http://ec.europa.eu/idabc/eupl +# +# Unless required by applicable law or agreed to in +# writing, software distributed under the Licence is +# distributed on an "AS IS" basis, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either +# express or implied. +# See the Licence for the specific language governing +# permissions and limitations under the Licence. +# +############################################################# + + +include Makefile.inc + diff --git a/DataSources/AtcaIop/Makefile.inc b/DataSources/AtcaIop/Makefile.inc new file mode 100644 index 0000000..40d6a81 --- /dev/null +++ b/DataSources/AtcaIop/Makefile.inc @@ -0,0 +1,54 @@ +############################################################# +# +# Copyright 2015 F4E | European Joint Undertaking for ITER +# and the Development of Fusion Energy ('Fusion for Energy') +# +# Licensed under the EUPL, Version 1.1 or - as soon they +# will be approved by the European Commission - subsequent +# versions of the EUPL (the "Licence"); +# You may not use this work except in compliance with the +# Licence. +# You may obtain a copy of the Licence at: +# +# http://ec.europa.eu/idabc/eupl +# +# Unless required by applicable law or agreed to in +# writing, software distributed under the Licence is +# distributed on an "AS IS" basis, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either +# express or implied. +# See the Licence for the specific language governing +# permissions and limitations under the Licence. +# +############################################################# + +OBJSX=AtcaIopDAC.x AtcaIopADC.x + +PACKAGE=Components/DataSources + +ROOT_DIR=../.. +MAKEDEFAULTDIR=$(MARTe2_DIR)/MakeDefaults +include $(MAKEDEFAULTDIR)/MakeStdLibDefs.$(TARGET) + +INCLUDES += -I. +INCLUDES += -I./include +INCLUDES += -I$(MARTe2_DIR)/Source/Core/BareMetal/L0Types +INCLUDES += -I$(MARTe2_DIR)/Source/Core/BareMetal/L1Portability +INCLUDES += -I$(MARTe2_DIR)/Source/Core/BareMetal/L2Objects +INCLUDES += -I$(MARTe2_DIR)/Source/Core/BareMetal/L3Streams +INCLUDES += -I$(MARTe2_DIR)/Source/Core/BareMetal/L4Messages +INCLUDES += -I$(MARTe2_DIR)/Source/Core/BareMetal/L4Configuration +INCLUDES += -I$(MARTe2_DIR)/Source/Core/BareMetal/L5GAMs +INCLUDES += -I$(MARTe2_DIR)/Source/Core/Scheduler/L1Portability +INCLUDES += -I$(MARTe2_DIR)/Source/Core/Scheduler/L3Services +INCLUDES += -I$(MARTe2_DIR)/Source/Core/Scheduler/L4Messages + +all: $(OBJS) \ + $(BUILD_DIR)/AtcaIop$(LIBEXT) \ + $(BUILD_DIR)/AtcaIop$(DLLEXT) + echo $(OBJS) + +include depends.$(TARGET) + +include $(MAKEDEFAULTDIR)/MakeStdLibRules.$(TARGET) + diff --git a/DataSources/AtcaIop/include/atca-v6-iop-ioctl.h b/DataSources/AtcaIop/include/atca-v6-iop-ioctl.h new file mode 100644 index 0000000..964c5e2 --- /dev/null +++ b/DataSources/AtcaIop/include/atca-v6-iop-ioctl.h @@ -0,0 +1,93 @@ +/** + * IOCTL Definitions for the Linux Device Driver + * Should be synchronized with: + * https://github.com/bernardocarvalho/atca-iop-stream/blob/master/linux-software/include/atca-v6-pcie-ioctl.h + * + */ + +#ifndef _ATCA_IOP_IOPTL_H_ +#define _ATCA_IOP_IOPTL_H_ + +#include + +#define ADC_CHANNELS 16 +#define DMA_BUFFS 8 // Number of DMA ch0 buffs + +/* 256 + 3840 = 4096 B (PAGE_SIZE) data packet +typedef struct _DMA_CH1_PCKT { + volatile uint32_t head_time_cnt; + volatile uint32_t header; // h5431BACD + volatile int32_t channel[60]; // 24 56 + volatile uint32_t foot_time_cnt; + volatile uint32_t footer; // h5431BACD + uint8_t page_fill[3840]; +} DMA_CH1_PCKT; +*/ +struct atca_eo_config { + int32_t offset[ADC_CHANNELS]; +}; + +struct atca_wo_config { + int32_t offset[ADC_CHANNELS]; +}; + +/* + * IOCTL definitions + */ + +/* Please use a different 8-bit number in your code */ +/*See /Documentation/ioctl-number.txt*/ +#define ATCA_PCIE_IOP_MAGIC 'k' +/* S means "Set": thru a pointer + * T means "Tell": directly with the argument value + * G menas "Get": reply by setting thru a pointer + * Q means "Qry": response is on the return value + * X means "eXchange": G and S atomically + * H means "sHift": T and Q atomically + */ + +/********************************************************************** + * IOCTL FUNCTIONS * + *********************************************************************/ +#define ATCA_PCIE_IOPT_IRQ_ENABLE _IO(ATCA_PCIE_IOP_MAGIC, 1) +#define ATCA_PCIE_IOPT_IRQ_DISABLE _IO(ATCA_PCIE_IOP_MAGIC, 2) +#define ATCA_PCIE_IOPT_ACQ_ENABLE _IO(ATCA_PCIE_IOP_MAGIC, 3) +#define ATCA_PCIE_IOPT_ACQ_DISABLE _IO(ATCA_PCIE_IOP_MAGIC, 4) +#define ATCA_PCIE_IOPT_DMA_ENABLE _IO(ATCA_PCIE_IOP_MAGIC, 5) +#define ATCA_PCIE_IOPT_DMA_DISABLE _IO(ATCA_PCIE_IOP_MAGIC, 6) +#define ATCA_PCIE_IOPT_SOFT_TRIG _IO(ATCA_PCIE_IOP_MAGIC, 7) +#define ATCA_PCIE_IOPG_STATUS _IOR(ATCA_PCIE_IOP_MAGIC, 8, u_int32_t) +#define ATCA_PCIE_IOPS_RDTMOUT _IOW(ATCA_PCIE_IOP_MAGIC, 9, u_int32_t) +#define ATCA_PCIE_IOPS_DMA_SIZE _IOW(ATCA_PCIE_IOP_MAGIC, 10, u_int32_t) +#define ATCA_PCIE_IOPG_DMA_SIZE _IOR(ATCA_PCIE_IOP_MAGIC, 11, u_int32_t) +#define ATCA_PCIE_IOPT_DMA_RESET _IO(ATCA_PCIE_IOP_MAGIC, 12) +#define ATCA_PCIE_IOPT_STREAM_ENABLE _IO(ATCA_PCIE_IOP_MAGIC, 13) +#define ATCA_PCIE_IOPT_STREAM_DISABLE _IO(ATCA_PCIE_IOP_MAGIC, 14) +#define ATCA_PCIE_IOPT_CHOP_ON _IO(ATCA_PCIE_IOP_MAGIC, 15) +#define ATCA_PCIE_IOPT_CHOP_OFF _IO(ATCA_PCIE_IOP_MAGIC, 16) +#define ATCA_PCIE_IOPT_CHOP_DEFAULT_1 _IO(ATCA_PCIE_IOP_MAGIC, 17) +#define ATCA_PCIE_IOPT_CHOP_DEFAULT_0 _IO(ATCA_PCIE_IOP_MAGIC, 18) +#define ATCA_PCIE_IOPS_CHOP_COUNTERS _IOW(ATCA_PCIE_IOP_MAGIC, 19, u_int32_t) +#define ATCA_PCIE_IOPG_CHOP_COUNTERS _IOR(ATCA_PCIE_IOP_MAGIC, 20, u_int32_t) +#define ATCA_PCIE_IOPS_EO_OFFSETS \ + _IOW(ATCA_PCIE_IOP_MAGIC, 21, struct atca_eo_config) +#define ATCA_PCIE_IOPS_WO_OFFSETS \ + _IOW(ATCA_PCIE_IOP_MAGIC, 22, struct atca_wo_config) +#define ATCA_PCIE_IOPG_EO_OFFSETS \ + _IOR(ATCA_PCIE_IOP_MAGIC, 23, struct atca_eo_config) +#define ATCA_PCIE_IOPG_WO_OFFSETS \ + _IOR(ATCA_PCIE_IOP_MAGIC, 24, struct atca_wo_config) + +#define ATCA_PCIE_IOPS_CONTROL _IOW(ATCA_PCIE_IOP_MAGIC, 25, u_int32_t) +#define ATCA_PCIE_IOPG_CONTROL _IOR(ATCA_PCIE_IOP_MAGIC, 26, u_int32_t) + +#define ATCA_PCIE_IOPS_CHOP_DISABLE _IOW(ATCA_PCIE_IOP_MAGIC, 27, u_int32_t) +#define ATCA_PCIE_IOPG_CHOP_DISABLE _IOR(ATCA_PCIE_IOP_MAGIC, 28, u_int32_t) + +#define ATCA_PCIE_IOPG_DACS_REG _IOR(ATCA_PCIE_IOP_MAGIC, 29, u_int32_t) + +#define ATCA_PCIE_IOP_MAXNR 29 + +#endif /* _ATCA_IOP_IOPTL_H_ */ + +// vim: syntax=cpp ts=4 sw=4 sts=4 sr et diff --git a/Startup/AtcaIop.sh b/Startup/AtcaIop.sh new file mode 100755 index 0000000..f07f338 --- /dev/null +++ b/Startup/AtcaIop.sh @@ -0,0 +1,78 @@ +#!/bin/bash +#Arguments -f FILENAME -m MESSAGE | -s STATE [-d cgdb|strace] +# Must set MARTe2 instalation folders +#MARTe2_HOME= +# +#MARTe2_DIR=$MARTe2_HOME/MARTe2 +#MARTe2_Components_DIR=$MARTe2_HOME/MARTe2-components +#MARTe2_Demos_DIR=$MARTe2_HOME/MARTe2-demos-padova +#EPICS_BASE= + +MDS=0 +DEBUG="" +INPUT_ARGS=$* +while test $# -gt 0 +do + case "$1" in + -d|--debug) + DEBUG="$2" + ;; + -mds) + MDS=1 + ;; + esac + shift +done + +LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$MARTe2_DIR/Build/x86-linux/Core/ + +#LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$MARTe2_Demos_DIR/Build/x86-linux/Components/DataSources/AtcaIop/ +LD_LIBRARY_PATH=$LD_LIBRARY_PATH:../Build/x86-linux/Components/DataSources/AtcaIop/ + +LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$MARTe2_Components_DIR/Build/x86-linux/Components/DataSources/EPICSCA/ +LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$MARTe2_Components_DIR/Build/x86-linux/Components/DataSources/EPICSPVA/ +LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$MARTe2_Components_DIR/Build/x86-linux/Components/DataSources/LinuxTimer/ +LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$MARTe2_Components_DIR/Build/x86-linux/Components/DataSources/LoggerDataSource/ +#LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$MARTe2_Components_DIR/Build/x86-linux/Components/DataSources/DAN/ +LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$MARTe2_Components_DIR/Build/x86-linux/Components/DataSources/FileDataSource/ +LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$MARTe2_Components_DIR/Build/x86-linux/Components/DataSources/LinkDataSource/ +LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$MARTe2_Components_DIR/Build/x86-linux/Components/DataSources/UDP/ +#LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$MARTe2_Components_DIR/Build/x86-linux/Components/DataSources/MDSReader/ +LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$MARTe2_Components_DIR/Build/x86-linux/Components/DataSources/MDSWriter/ +LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$MARTe2_Components_DIR/Build/x86-linux/Components/DataSources/RealTimeThreadSynchronisation/ +LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$MARTe2_Components_DIR/Build/x86-linux/Components/DataSources/RealTimeThreadAsyncBridge/ +LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$MARTe2_Components_DIR/Build/x86-linux/Components/GAMs/ConstantGAM/ +LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$MARTe2_Components_DIR/Build/x86-linux/Components/GAMs/ConversionGAM/ +LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$MARTe2_Components_DIR/Build/x86-linux/Components/GAMs/IOGAM/ +LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$MARTe2_Components_DIR/Build/x86-linux/Components/GAMs/FilterGAM/ +LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$MARTe2_Components_DIR/Build/x86-linux/Components/GAMs/HistogramGAM/ +LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$MARTe2_Components_DIR/Build/x86-linux/Components/GAMs/SSMGAM/ +LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$MARTe2_Components_DIR/Build/x86-linux/Components/GAMs/TriggerOnChangeGAM/ +LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$MARTe2_Components_DIR/Build/x86-linux/Components/GAMs/WaveformGAM/ +LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$MARTe2_Components_DIR/Build/x86-linux/Components/Interfaces/BaseLib2Wrapper/ +LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$MARTe2_Components_DIR/Build/x86-linux/Components/Interfaces/EPICS/ +LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$MARTe2_Components_DIR/Build/x86-linux/Components/Interfaces/EPICSPVA/ +LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$MARTe2_Components_DIR/Build/x86-linux/Components/Interfaces/MemoryGate/ +#LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$MARTe2_Components_DIR/Build/x86-linux/Components/Interfaces/NI9157Device/ +#LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$MARTe2_Components_DIR/Build/x86-linux/Components/Interfaces/OPCUA/ +LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$MARTe2_Components_DIR/Build/x86-linux/Components/Interfaces/SysLogger/ + +LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$EPICS_BASE/lib/$EPICS_HOST_ARCH + +echo $LD_LIBRARY_PATH +export LD_LIBRARY_PATH=$LD_LIBRARY_PATH + +#if [ ${MDS} == 1 ]; then +#export rtappwriter_path=../Trees +#export rtappreader_path=../Trees +#export rtappdemo_path=../Trees +#mdstcl < CreateMDSTrees.tcl +#fi + +if [ "$DEBUG" = "cgdb" ] +then + cgdb --args $MARTe2_DIR/Build/x86-linux/App/MARTeApp.ex $INPUT_ARGS +else + $MARTe2_DIR/Build/x86-linux/App/MARTeApp.ex $INPUT_ARGS +fi + diff --git a/Startup/ClearIsttokMDSTree.tcl b/Startup/ClearIsttokMDSTree.tcl new file mode 100644 index 0000000..c8d39f2 --- /dev/null +++ b/Startup/ClearIsttokMDSTree.tcl @@ -0,0 +1,4 @@ +set tree rtappisttok +create pulse 1 +exit + diff --git a/Startup/CreateIsttokMDSplusTree.tcl b/Startup/CreateIsttokMDSplusTree.tcl new file mode 100644 index 0000000..775ea8f --- /dev/null +++ b/Startup/CreateIsttokMDSplusTree.tcl @@ -0,0 +1,111 @@ +edit rtappisttok/new + +add node .ATCAIOP1 +add node .INP +add node .REFS +add node .ERRORS +add node .CONTROLS +add node .STATES +add node .PERF +add node TIME/usage=signal +add node TIMED/usage=signal + +set def \RTAPPISTTOK::TOP.ATCAIOP1 +add node ADC0RAW/usage=signal +add node ADC0RAWD/usage=signal +add node ADC1RAW/usage=signal +add node ADC1RAWD/usage=signal +add node ADC2RAW/usage=signal +add node ADC2RAWD/usage=signal +add node ADC3RAW/usage=signal +add node ADC3RAWD/usage=signal +add node ADC4RAW/usage=signal +add node ADC4RAWD/usage=signal +add node ADC5RAW/usage=signal +add node ADC5RAWD/usage=signal +add node ADC6RAW/usage=signal +add node ADC6RAWD/usage=signal +add node ADC7RAW/usage=signal +add node ADC7RAWD/usage=signal +add node ADC8RAW/usage=signal +add node ADC8RAWD/usage=signal +add node ADC9RAW/usage=signal +add node ADC9RAWD/usage=signal +add node ADC10RAW/usage=signal +add node ADC10RAWD/usage=signal +add node ADC11RAW/usage=signal +add node ADC11RAWD/usage=signal + +add node ADC0INT/usage=signal +add node ADC0INTD/usage=signal +add node ADC1INT/usage=signal +add node ADC1INTD/usage=signal +add node ADC2INT/usage=signal +add node ADC2INTD/usage=signal +add node ADC3INT/usage=signal +add node ADC3INTD/usage=signal +add node ADC4INT/usage=signal +add node ADC4INTD/usage=signal +add node ADC5INT/usage=signal +add node ADC5INTD/usage=signal +add node ADC6INT/usage=signal +add node ADC6INTD/usage=signal +add node ADC7INT/usage=signal +add node ADC7INTD/usage=signal +add node ADC8INT/usage=signal +add node ADC8INTD/usage=signal +add node ADC9INT/usage=signal +add node ADC9INTD/usage=signal +add node ADC10INT/usage=signal +add node ADC10INTD/usage=signal +add node ADC11INT/usage=signal +add node ADC11INTD/usage=signal + +set def \RTAPPISTTOK::TOP.INP +add node MEAS0D/usage=signal +add node MEAS0/usage=signal +add node MEAS0D/usage=signal +add node MEAS0F/usage=signal +add node MEAS0FD/usage=signal +add node MEAS1/usage=signal +add node MEAS1D/usage=signal +add node MEAS1F/usage=signal +add node MEAS1FD/usage=signal + +set def \RTAPPISTTOK::TOP.REFS +add node REF0/usage=signal +add node REF0D/usage=signal +add node REF1/usage=signal +add node REF1D/usage=signal + +set def \RTAPPISTTOK::TOP.ERRORS +add node ERROR0/usage=signal +add node ERROR0D/usage=signal +add node ERROR1/usage=signal +add node ERROR1D/usage=signal + +set def \RTAPPISTTOK::TOP.CONTROLS +add node CONTROL0/usage=signal +add node CONTROL0D/usage=signal +add node CONTROL1/usage=signal +add node CONTROL1D/usage=signal + +set def \RTAPPISTTOK::TOP.STATES +add node STATE0/usage=signal +add node STATE0D/usage=signal +add node STATE1/usage=signal +add node STATE1D/usage=signal +add node STATE2/usage=signal +add node STATE2D/usage=signal +add node STATE3/usage=signal +add node STATE3D/usage=signal + +set def \RTAPPISTTOK::TOP.PERF +add node CYCLET/usage=signal +add node CYCLETD/usage=signal + +write +close +set tree rtappisttok +create pulse 1 +exit