Files
ISTTOK/epics/css/sys-mng-opi/CSS/MARTe/IOGAMs/ATCAadc/ATCAadcDrv.h
2019-10-21 16:02:55 +01:00

409 lines
12 KiB
C++

//******************************************************************************
// MARTe Library
// $Log: ATCAadcDrv.h,v $
// Revision 1.32 2009/12/03 14:52:13 ppcc_dev
// Sleeps, if time is available, before start busy polling.
// The time to sleep is given by the remaining time until the start of
// the next pulse minus the worst jitter from a sleep and minus the
// desired time, before the beginning of the next pulse, that we want to start
// busy polling.
// The worst jitter decays to zero in order to try to maintain a good performance
//
// Revision 1.31 2009/08/07 09:31:47 aneto
// Allow the autoSoftwareTrigger to work even if the softwareTrigger flag
// is set to false
//
// Revision 1.30 2009/05/21 15:18:37 ppcc_dev
// DigIO does not have outputMap
//
// Revision 1.29 2009/04/14 09:06:10 aneto
// Allow the system to auto-trigger after a specified amount of time
//
// Revision 1.28 2009/04/03 10:02:03 aneto
// lastCycleUsecTime now is true 64 bits.
// This uses the information from the headers to increment an internal counter
//
// Revision 1.27 2009/04/01 15:10:36 aneto
// Bug in the way the modulus was being calculated for the usec time. The bug was in converting from 64 to 32 bits of lastCycleUsecTime
//
// Revision 1.26 2009/03/16 11:42:16 aneto
// Corrected the polling mode in order to allow different acquisition frequencies
//
// Revision 1.25 2009/03/11 12:31:54 aneto
// Support an html output with information about the driver
//
// Revision 1.24 2009/01/26 17:26:20 ppcc_dev
// Small bugs solved
//
// Revision 1.23 2009/01/26 09:20:38 aneto
// linux support
//
// Revision 1.22 2008/11/28 12:03:13 aneto
// Added bufferNumber
//
// Revision 1.21 2008/11/21 14:16:52 ppcc_dev
// This version works with the new firmware: jet clock+trigger
//
// Revision 1.19 2008/09/30 11:24:49 rvitelli
// Added non-synchronous operating mode.
//
// Revision 1.18 2008/09/22 17:20:36 fpiccolo
// Solved minor bugs
//
// Revision 1.17 2008/09/15 16:51:45 ppcc_dev
// Solved few bugs
//
// Revision 1.16 2008/09/09 09:29:15 fpiccolo
// Modified driver structure.
// Added SingleATCAModule class
// Added Writing facilities
//
// Revision 1.15 2008/08/20 16:34:36 ppcc_dev
// Added PulseStart to reset the internal counter to 0 when using the SoftTrigger option
//
// Revision 1.14 2008/08/15 10:41:35 fpiccolo
// Minor stylish modifications.
// Added TimeModule Interface
//
// Revision 1.13 2008/08/01 14:09:28 rvitelli
// First working version
//
//******************************************************************************
#ifndef ATCAADCDRV_H_
#define ATCAADCDRV_H_
#include "System.h"
#include "GenericAcqModule.h"
#include "FString.h"
#include "pcieAdc.h"
#include "pcieAdc_ioctl.h"
#ifdef _LINUX
#include <sys/mman.h>
#endif
#include "WebStatisticGAM.h"
class SingleATCAModule{
private:
/** Module Identifier */
int32 moduleIdentifier;
/** Number of Analogue Input channels for this module (Maximum 32)*/
int32 numberOfAnalogueInputChannels;
/** Number of Digital Input channels for this module (1 or 0) */
int32 numberOfDigitalInputChannels;
/** Number of Analogue Output channels (Maximum 8) */
int32 numberOfAnalogueOutputChannels;
/** Number of Digital Output channels () */
int32 numberOfDigitalOutputChannels;
/** Output Map. Used to map the output to a specific physical
output channel. Channels are identified from 1 to 8. */
int32 outputMap[8];
////////////////////////////
// Analogue Input Section //
////////////////////////////
/** If true synchronize on data arrival, if false return latest completed buffer */
bool synchronizing;
/** Pointers to the DMA memory allocated for data acquisition.
The number of buffers is fixed to 4.
*/
int32 *dmaBuffers[DMA_BUFFS];
/** Current DMA buffer index [0-3]. */
static int32 currentDMABufferIndex;
/** The current master header (must be the same in all the boards) */
static int32 currentMasterHeader;
/** Estimated time of the next expected arrival in CPU Ticks of the acquired buffer.
It is computed by adding a delay specified @param periodUsecSleep to
the time of the previous completed acquisition. The system will sleep
till this time elapses.
*/
int64 nextExpectedAcquisitionCPUTicks;
/** Specifies how long to sleep between acquisitions. It is specified in microseconds
but it is internally converted in CPU ticks to avoid unecessary computations during
realtime activities.
*/
int64 boardInternalCycleTicks;
/** Amount of time in microseconds after which the data stops waiting for data arrival
and reports an acquisition error.
*/
int64 dataAcquisitionUsecTimeOut;
/** Length of a "Short Sleep" in seconds. It is used to monitor
the data arrival on the master board and specifies a sleep time
between checks of the data datagram arrival.
*/
float datagramArrivalFastMonitorSecSleep;
/** The number of micro seconds incremented by the board in each cycle. It gives the board acquisition frequency.
*/
int32 boardInternalCycleTime;
/**
* The statistics info for these channels
*/
StatSignalInfo *channelStatistics;
/** Find the currentDMABufferIndex and synchronize on data arrival
*/
int32 CurrentBufferIndex();
/** Find the latest completed buffer without synchronization*/
int32 GetLatestBufferIndex();
public:
SingleATCAModule();
/** Initialises the SingleModule Parameter*/
bool ObjectLoadSetup(ConfigurationDataBase &info,StreamInterface *err = NULL);
/** Reads NumberOfInputChannels() from the DMA Buffer.
The first module must be the master board to assure
correct data transfer.
*/
bool GetData(int32 *&buffer);
bool WriteData(const int32 *&buffer);
/** Copies the pointers to the DMA Buffers */
#ifdef _LINUX
bool InstallDMABuffers(int32 *mappedDmaMemoryLocation);
#else
/** Copies the pointers to the DMA Buffers */
bool InstallDMABuffers();
#endif
/////////////////
// Time Module //
/////////////////
int64 lastCycleUsecTime;
int32 packetCounter;
/** Is Master Board */
bool isMaster;
/** Returns the sum of analogue and digital input channels */
int32 NumberOfInputChannels(){
return numberOfDigitalInputChannels + numberOfAnalogueInputChannels;
}
/** Returns the sum of analogue and digital output channels */
int32 NumberOfOutputChannels(){
return numberOfDigitalOutputChannels + numberOfAnalogueOutputChannels;
}
/** Returns the module Identifier */
int32 BoardIdentifier(){return moduleIdentifier;}
/**
* Output an HTML table with the current value in mV of the acquired signals for this board
*/
virtual bool ProcessHttpMessage(HttpStream &hStream);
/**
* Resets the statistics
*/
bool ResetStatistics();
/**
* Polling method
*/
virtual bool Poll();
/**
* Allow sleeping, when enough time is available, before start polling
*/
bool allowPollSleeping;
/**
* Time to sleep before hard polling: pollSleepTime = CycleTime - time left to cycle time - pollSleepTimeWakeBeforeUs - worstPollSleepJitter;
*/
float pollSleepTime;
/**
* Actually we want to start polling some us before reaching the cycle time
*/
float pollSleepTimeWakeBeforeUs;
/**
* The worst jitter calculated in realtime of the actual time slept before polling and time meant to sleep
*/
float worstPollSleepJitter;
/**
* The worst jitter will try to be recovered with a certain rate
*/
float worstPollSleepJitterDecayRate;
};
OBJECT_DLL(ATCAadcDrv)
/** The high level driver for the ATCA ADC module */
class ATCAadcDrv:public GenericAcqModule{
private:
/** Number of boards in the crate. Read during Initialisation */
int32 numberOfBoards;
/** Pointers to the ATCA modules */
SingleATCAModule *modules;
/** Last cycle usec time */
int64 lastCycleUsecTime;
/** */
bool synchronizing;
/** Software triggered acquisition.
0, which is the default value, means hardware trigger.
*/
int32 softwareTrigger;
/** The master board index
*/
int32 masterBoardIdx;
/** If set to true the a software trigger will be sent every
* AutoSoftwareTriggerAfterUs microseconds. For this to be
* true the value of AutoSoftwareTriggerAfterUs in the configuration file
* must be > 1
*/
bool autoSoftwareTrigger;
int32 autoSoftwareTriggerAfterUs;
#ifdef _LINUX
/** Used only in Linux. The mmapped memory location.*/
int32 *mappedDmaMemoryLocation;
int32 mappedDmaMemorySize;
#endif
/** The css for this page
*/
const char *css;
public:
#ifdef _LINUX
/**The page size*/
static int32 pageSize;
/**The file descriptor to access the driver*/
static int32 fileDescriptor;
#endif
// (De)Constructor
ATCAadcDrv();
virtual ~ATCAadcDrv(){
if(modules != NULL) delete[] modules;
#ifdef _LINUX
munmap(mappedDmaMemoryLocation, mappedDmaMemorySize);
close(fileDescriptor);
#endif
}
// Standard GAM methods
/* Load setup from CDB.
This IOGAM peculiar parameters are PeriodSleep_usec and FastSleep_usec.
@param info: CDB from which load data
@param err: not used
@returns true if all ok*/
virtual bool ObjectLoadSetup(ConfigurationDataBase &info,StreamInterface *err);
/* Print internal GAM informations
@param s: StreamInterface in which print infos
@param full: not used
@param err: not used
@returns true if all ok*/
virtual bool ObjectDescription(StreamInterface &s,bool full = False, StreamInterface *err=NULL);
/* Saves the data into the DDB
@param usecTime: not used
@param buffer: pointer to the data buffer to be filled
@returns 1 if all ok*/
int32 GetData(uint32 usecTime, int32 *buffer, int32 bufferNum = 0);
bool WriteData(uint32 usecTime, const int32 *buffer);
// Set board used as input
virtual bool SetInputBoardInUse(bool on = False){
if(inputBoardInUse && on){
AssertErrorCondition(InitialisationError, "ATCAadcDrv::SetInputBoardInUse: Board %s is already in use", Name());
return False;
}
inputBoardInUse = on;
return True;
}
virtual bool SetOutputBoardInUse(bool on = False){
if(outputBoardInUse && on){
AssertErrorCondition(InitialisationError, "ATCAadcDrv::SetOutputBoardInUse: Board %s is already in use", Name());
return False;
}
outputBoardInUse = on;
return True;
}
virtual bool EnableAcquisition();
virtual bool DisableAcquisition();
//////////////////////
// From Time Module //
//////////////////////
// Get the Time
int64 GetUsecTime(){return lastCycleUsecTime;}
bool SoftwareTrigger(){
if(modules == NULL)return False;
#ifdef _RTAI
SendSoftwareTrigger();
#elif defined(_LINUX)
int ret = ioctl(fileDescriptor, PCIE_ATCA_ADC_IOCT_SEND_SOFT_TRG);
if(ret != 0){
AssertErrorCondition(InitialisationError,"ATCAadcDrv::PulseStart: Could send software trigger. ioctl returned : %d",ret);
return False;
}
#endif
return True;
}
//////////////////////////////////
// Simulation Purpose Functions //
//////////////////////////////////
bool PulseStart(){
if(modules == NULL)return False;
if(softwareTrigger == 1){
return SoftwareTrigger();
}
return True;
}
/**
* Output an HTML page with the current value in mV of the acquired signals
*/
virtual bool ProcessHttpMessage(HttpStream &hStream);
/**
* Polling method
*/
virtual bool Poll();
private:
OBJECT_DLL_STUFF(ATCAadcDrv);
};
#endif /*ATCAADCDRV_H_*/