Initial import
Signed-off-by: Bernardo Carvalho <bernardo.carvalho@tecnico.ulisboa.pt>
This commit is contained in:
47
Analysis/getMdsData.py
Normal file
47
Analysis/getMdsData.py
Normal 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
99
Analysis/pyqtPlotMds.py
Normal 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
|
||||
56
Configurations/EPICS-isttok.db
Normal file
56
Configurations/EPICS-isttok.db
Normal 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")
|
||||
}
|
||||
|
||||
1531
Configurations/RTApp-AtcaIop.cfg
Normal file
1531
Configurations/RTApp-AtcaIop.cfg
Normal file
File diff suppressed because it is too large
Load Diff
734
DataSources/AtcaIop/AtcaIopADC.cpp
Normal file
734
DataSources/AtcaIop/AtcaIopADC.cpp
Normal 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
|
||||
435
DataSources/AtcaIop/AtcaIopADC.h
Normal file
435
DataSources/AtcaIop/AtcaIopADC.h
Normal 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
|
||||
374
DataSources/AtcaIop/AtcaIopDAC.cpp
Normal file
374
DataSources/AtcaIop/AtcaIopDAC.cpp
Normal 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
|
||||
236
DataSources/AtcaIop/AtcaIopDAC.h
Normal file
236
DataSources/AtcaIop/AtcaIopDAC.h
Normal 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
|
||||
28
DataSources/AtcaIop/Makefile.cov
Normal file
28
DataSources/AtcaIop/Makefile.cov
Normal 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
|
||||
|
||||
27
DataSources/AtcaIop/Makefile.gcc
Normal file
27
DataSources/AtcaIop/Makefile.gcc
Normal 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
|
||||
|
||||
54
DataSources/AtcaIop/Makefile.inc
Normal file
54
DataSources/AtcaIop/Makefile.inc
Normal 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)
|
||||
|
||||
93
DataSources/AtcaIop/include/atca-v6-iop-ioctl.h
Normal file
93
DataSources/AtcaIop/include/atca-v6-iop-ioctl.h
Normal 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
78
Startup/AtcaIop.sh
Executable 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
|
||||
|
||||
4
Startup/ClearIsttokMDSTree.tcl
Normal file
4
Startup/ClearIsttokMDSTree.tcl
Normal file
@@ -0,0 +1,4 @@
|
||||
set tree rtappisttok
|
||||
create pulse 1
|
||||
exit
|
||||
|
||||
111
Startup/CreateIsttokMDSplusTree.tcl
Normal file
111
Startup/CreateIsttokMDSplusTree.tcl
Normal 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
|
||||
Reference in New Issue
Block a user