Initial import

Signed-off-by: Bernardo Carvalho <bernardo.carvalho@tecnico.ulisboa.pt>
This commit is contained in:
2024-04-14 17:21:58 +01:00
parent 6bc86c7c0b
commit 182480dff2
15 changed files with 3907 additions and 0 deletions

47
Analysis/getMdsData.py Normal file
View File

@@ -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()

99
Analysis/pyqtPlotMds.py Normal file
View File

@@ -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='<Required> 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='<Required> 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

View File

@@ -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")
}

File diff suppressed because it is too large Load Diff

View File

@@ -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 <math.h>
#include <fcntl.h>
#include <sys/mman.h> // For mmap()
#include <unistd.h> // 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<ATCA_IOP_N_ADCs; k++) {
adcValues[k] = 0u;
electricalOffsets[k] = 0u;
wiringOffsets[k] = 0.0;
}
for (k=0u; k<ATCA_IOP_N_INTEGRALS; k++) {
adcIntegralValues[k] = 0u;
}
if (!synchSem.Create()) {
REPORT_ERROR(ErrorManagement::FatalError, "Could not create EventSem.");
}
}
/*lint -e{1551} the destructor must guarantee that the Timer SingleThreadService is stopped.*/
AtcaIopADC::~AtcaIopADC() {
if (boardFileDescriptor != -1) {
// Synchronize DMA before accessing board registers
oldestBufferIdx = GetOldestBufferIdx();
PollDma(HighResolutionTimer::Counter() + 2000000); // wait max 2ms
ioctl(boardFileDescriptor, ATCA_PCIE_IOPT_STREAM_DISABLE);
ioctl(boardFileDescriptor, ATCA_PCIE_IOPT_DMA_DISABLE);
uint32 statusReg = 0;
ioctl(boardFileDescriptor, ATCA_PCIE_IOPG_STATUS, &statusReg);
//rc = ioctl(boardFileDescriptor, ATCA_PCIE_IOPT_DMA_RESET);
close(boardFileDescriptor);
REPORT_ERROR(ErrorManagement::Information, "Close device %d OK. Status Reg 0x%x,", boardFileDescriptor, statusReg);
}
if (!synchSem.Post()) {
REPORT_ERROR(ErrorManagement::Warning, "Could not post EventSem.");
}
if (!executor.Stop()) {
if (!executor.Stop()) {
REPORT_ERROR(ErrorManagement::Warning, "Could not stop SingleThreadService.");
}
}
// some waiting..
//float32 sleepTime = static_cast<float32>(static_cast<float64>(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<int32> 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<float32> 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<uint32>(periodUsec);
float64 sleepTimeT = (static_cast<float64>(HighResolutionTimer::Frequency()) / cycleFrequency);
sleepTimeTicks = static_cast<uint64>(sleepTimeT);
REPORT_ERROR(ErrorManagement::Information,
"The timer will be set using a sleepTimeTicks of %d (ns)", sleepTimeTicks);
}
if (ok) {
//float32 totalNumberOfSamplesPerSecond = (static_cast<float32>(adcSamplesPerCycle) * cycleFrequency);
float32 totalNumberOfSamplesPerSecond = (static_cast<float32>(rtDecimation) * cycleFrequency);
ok = (adcFrequency == static_cast<uint32>(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<float32>(static_cast<float64>(deltaTicks) * HighResolutionTimer::Period());
uint32 busyPercentage = (100u - sleepPercentage);
float32 busyTime = totalSleepTime * (static_cast<float32>(busyPercentage) / 100.F);
Sleep::SemiBusy(totalSleepTime, busyTime);
}
}
else {
float32 sleepTime = static_cast<float32>(static_cast<float64>(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

View File

@@ -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
* <pre>
* +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
* }
* }
* }
* </pre>
*/
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<RegisteredMethodsMessageFilter> filter;
};
}
/*---------------------------------------------------------------------------*/
/* Inline method definitions */
/*---------------------------------------------------------------------------*/
#endif /* ATCA_IOP_ADC_H */
// vim: syntax=cpp ts=4 sw=4 sts=4 sr et

View File

@@ -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 <fcntl.h>
#include <unistd.h> // for close()
#include <math.h>
/*---------------------------------------------------------------------------*/
/* 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<RegisteredMethodsMessageFilter>(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<MemoryMapSynchronisedOutputBroker> 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<MemoryMapOutputBroker> brokerNotSync("MemoryMapOutputBroker");
ok = brokerNotSync.IsValid();
if (ok) {
ok = brokerNotSync->Init(OutputSignals, *this, functionName, gamMemPtr);
}
if (ok) {
ok = outputBrokers.Insert(brokerNotSync);
}
}
}
}
else {
ReferenceT<MemoryMapOutputBroker> 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<uint32>(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<int32>(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

View File

@@ -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):
*
* <pre>
* +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.
* }
* }
* }
* </pre>
* 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<RegisteredMethodsMessageFilter> 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

View File

@@ -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

View File

@@ -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

View File

@@ -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)

View File

@@ -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 <sys/ioctl.h>
#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

78
Startup/AtcaIop.sh Executable file
View File

@@ -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

View File

@@ -0,0 +1,4 @@
set tree rtappisttok
create pulse 1
exit

View File

@@ -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