Imported CSS files
This commit is contained in:
942
epics/css/sys-mng-opi/CSS/MARTe/IOGAMs/ATCAadc/ATCAadcDrv.cpp
Normal file
942
epics/css/sys-mng-opi/CSS/MARTe/IOGAMs/ATCAadc/ATCAadcDrv.cpp
Normal file
@@ -0,0 +1,942 @@
|
||||
//******************************************************************************
|
||||
// MARTe Library
|
||||
// $Log: ATCAadcDrv.cpp,v $
|
||||
// Revision 1.48 2010/02/09 14:50:59 ppcc_dev
|
||||
// Significantly increased the PollSleepTimeWakeBeforeUs in order to disallow any
|
||||
// sleeping in online...
|
||||
//
|
||||
// Revision 1.47 2010/01/22 09:29:07 aneto
|
||||
// pollSleepTimeWakeBeforeUs was only being converted to us if not specified
|
||||
//
|
||||
// Revision 1.46 2009/12/15 12:16:51 aneto
|
||||
// Code cleaning
|
||||
//
|
||||
// Revision 1.45 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.44 2009/09/23 12:21:20 aneto
|
||||
// Cast the header to unsigned int 32 in order to avoid rollover problems
|
||||
// when it changes the bit sign
|
||||
//
|
||||
// Revision 1.43 2009/08/07 09:31:47 aneto
|
||||
// Allow the autoSoftwareTrigger to work even if the softwareTrigger flag
|
||||
// is set to false
|
||||
//
|
||||
// Revision 1.42 2009/06/23 13:44:19 aneto
|
||||
// In Linux wait sometime between header synchronisation
|
||||
//
|
||||
// Revision 1.41 2009/06/09 09:55:28 ppcc_dev
|
||||
// Time is read directly from the board header
|
||||
//
|
||||
// Revision 1.40 2009/05/21 15:18:34 ppcc_dev
|
||||
// DigIO does not have outputMap
|
||||
//
|
||||
// Revision 1.39 2009/04/21 08:48:42 aneto
|
||||
// Channel statistics variable weren't being initialised
|
||||
//
|
||||
// Revision 1.38 2009/04/14 09:06:10 aneto
|
||||
// Allow the system to auto-trigger after a specified amount of time
|
||||
//
|
||||
// Revision 1.37 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.36 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.35 2009/03/31 08:11:37 aneto
|
||||
// Support for multiple input
|
||||
//
|
||||
// Revision 1.34 2009/03/26 15:13:21 aneto
|
||||
// Automatic offset compensation
|
||||
//
|
||||
// Revision 1.33 2009/03/16 11:42:16 aneto
|
||||
// Corrected the polling mode in order to allow different acquisition frequencies
|
||||
//
|
||||
// Revision 1.32 2009/03/11 12:31:54 aneto
|
||||
// Support an html output with information about the driver
|
||||
//
|
||||
// Revision 1.31 2009/01/26 17:26:20 ppcc_dev
|
||||
// Small bugs solved
|
||||
//
|
||||
// Revision 1.30 2009/01/26 09:23:51 aneto
|
||||
// Removed printfs
|
||||
//
|
||||
// Revision 1.29 2009/01/26 09:20:38 aneto
|
||||
// linux support
|
||||
//
|
||||
// Revision 1.28 2009/01/22 13:59:18 aneto
|
||||
// Miror clean up
|
||||
//
|
||||
// Revision 1.27 2008/11/28 12:03:13 aneto
|
||||
// Added bufferNumber
|
||||
//
|
||||
// Revision 1.26 2008/11/21 14:16:42 ppcc_dev
|
||||
// This version works with the new firmware: jet clock+trigger
|
||||
//
|
||||
// Revision 1.24 2008/09/30 11:24:49 rvitelli
|
||||
// Added non-synchronous operating mode.
|
||||
//
|
||||
// Revision 1.23 2008/09/30 10:36:03 ppcc_dev
|
||||
// Minor modifications to both driver and low level module
|
||||
//
|
||||
// Revision 1.22 2008/09/16 13:06:57 fpiccolo
|
||||
// Modified SleepMsec to SleepNoMore to remove jitter on cycle time
|
||||
//
|
||||
// Revision 1.21 2008/09/15 16:51:45 ppcc_dev
|
||||
// Solved few bugs
|
||||
//
|
||||
// Revision 1.20 2008/09/09 11:10:36 fpiccolo
|
||||
// Patch to make it work only with two modules and old firmware
|
||||
//
|
||||
// Revision 1.19 2008/09/09 09:29:15 fpiccolo
|
||||
// Modified driver structure.
|
||||
// Added SingleATCAModule class
|
||||
// Added Writing facilities
|
||||
//
|
||||
// Revision 1.18 2008/09/04 11:48:52 ppcc_dev
|
||||
// Minor modifications to the GETData function.
|
||||
// Removed DisableAcquisition call from the ObjectLoadSetup function
|
||||
// since was causing a crash.
|
||||
//
|
||||
// Revision 1.17 2008/08/19 12:43:29 ppcc_dev
|
||||
// Corrected memory addresses in memcpy, added simulation code for SoftTrigger
|
||||
//
|
||||
// Revision 1.16 2008/08/15 10:41:35 fpiccolo
|
||||
// Minor stylish modifications.
|
||||
// Added TimeModule Interface
|
||||
//
|
||||
// Revision 1.15 2008/08/01 14:09:26 rvitelli
|
||||
// First working version
|
||||
//
|
||||
// Revision 1.14 2008/07/28 13:50:05 aneto
|
||||
// Added support for multiple boards.
|
||||
//
|
||||
//******************************************************************************
|
||||
|
||||
#include "ATCAadcDrv.h"
|
||||
#include "ConfigurationDataBase.h"
|
||||
#include "CDBExtended.h"
|
||||
#include "HRT.h"
|
||||
#include "Sleep.h"
|
||||
#include "Console.h"
|
||||
|
||||
int32 SingleATCAModule::currentDMABufferIndex = 0;
|
||||
int32 SingleATCAModule::currentMasterHeader = 0;
|
||||
|
||||
#ifdef _LINUX
|
||||
int32 ATCAadcDrv::pageSize = 0;
|
||||
int32 ATCAadcDrv::fileDescriptor = 0;
|
||||
#endif
|
||||
|
||||
SingleATCAModule::SingleATCAModule(){
|
||||
moduleIdentifier = 0;
|
||||
numberOfAnalogueInputChannels = 0;
|
||||
numberOfDigitalInputChannels = 0;
|
||||
numberOfAnalogueOutputChannels = 0;
|
||||
numberOfDigitalOutputChannels = 0;
|
||||
int i = 0;
|
||||
for(i = 0; i < 8; i++)outputMap[i] = 0;
|
||||
|
||||
// Input Section //
|
||||
isMaster = False;
|
||||
for(i = 0; i < 4; i++)dmaBuffers[i] = NULL;
|
||||
nextExpectedAcquisitionCPUTicks = 0;
|
||||
boardInternalCycleTicks = 0;
|
||||
datagramArrivalFastMonitorSecSleep = 0.0;
|
||||
boardInternalCycleTime = 0;
|
||||
|
||||
lastCycleUsecTime = 0;
|
||||
packetCounter = 0;
|
||||
synchronizing = False;
|
||||
channelStatistics = NULL;
|
||||
|
||||
allowPollSleeping = True;
|
||||
worstPollSleepJitter = 0;
|
||||
worstPollSleepJitterDecayRate = (1 - 5e-6);
|
||||
pollSleepTime = 0;
|
||||
pollSleepTimeWakeBeforeUs = 20;
|
||||
}
|
||||
|
||||
|
||||
bool SingleATCAModule::ObjectLoadSetup(ConfigurationDataBase &info,StreamInterface *err){
|
||||
|
||||
CDBExtended cdb(info);
|
||||
FString moduleName;
|
||||
cdb->NodeName(moduleName);
|
||||
if(!cdb.ReadInt32(moduleIdentifier, "ModuleIdentifier")){
|
||||
CStaticAssertErrorCondition(InitialisationError,"SingleATCAModule::ObjectLoadSetup: ModuleIdentifier has not been specified.");
|
||||
return False;
|
||||
}
|
||||
|
||||
int32 master = 0;
|
||||
cdb.ReadInt32(master, "IsMaster",0);
|
||||
isMaster = (master != 0);
|
||||
if(isMaster){
|
||||
CStaticAssertErrorCondition(Information,"SingleATCAModule::ObjectLoadSetup: Module with identifier %d has been specified as master.", moduleIdentifier);
|
||||
}
|
||||
|
||||
synchronizing = False;
|
||||
if (isMaster) {
|
||||
FString syncMethod;
|
||||
if(!cdb.ReadFString(syncMethod, "SynchronizationMethod")){
|
||||
CStaticAssertErrorCondition(InitialisationError,"SingleATCAModule::ObjectLoadSetup: SynchronizationMethod has not been specified.");
|
||||
return False;
|
||||
}
|
||||
if (syncMethod == "GetLatest") {
|
||||
synchronizing = False;
|
||||
CStaticAssertErrorCondition(Information,"SingleATCAModule::ObjectLoadSetup: synchronization method: GetLatest");
|
||||
} else {
|
||||
synchronizing = True;
|
||||
CStaticAssertErrorCondition(Information,"SingleATCAModule::ObjectLoadSetup: synchronization method: Synchronous on input");
|
||||
}
|
||||
}
|
||||
|
||||
if(!cdb.ReadInt32(numberOfAnalogueInputChannels, "NumberOfAnalogueInput")){
|
||||
CStaticAssertErrorCondition(InitialisationError,"SingleATCAModule::ObjectLoadSetup: NumberOfAnalogueInput has not been specified.");
|
||||
return False;
|
||||
}
|
||||
|
||||
if(!cdb.ReadInt32(numberOfDigitalInputChannels, "NumberOfDigitalInput")){
|
||||
CStaticAssertErrorCondition(InitialisationError,"SingleATCAModule::ObjectLoadSetup: NumberOfDigitalInput has not been specified.");
|
||||
return False;
|
||||
}
|
||||
|
||||
if(!cdb.ReadInt32(numberOfAnalogueOutputChannels, "NumberOfAnalogueOutput")){
|
||||
CStaticAssertErrorCondition(InitialisationError,"SingleATCAModule::ObjectLoadSetup: NumberOfAnalogueOutput has not been specified.");
|
||||
return False;
|
||||
}
|
||||
|
||||
if(!cdb.ReadInt32(numberOfDigitalOutputChannels, "NumberOfDigitalOutput")){
|
||||
CStaticAssertErrorCondition(InitialisationError,"SingleATCAModule::ObjectLoadSetup: NumberOfDigitalOutput has not been specified.");
|
||||
return False;
|
||||
}
|
||||
|
||||
int32 detectedNumberOfInputAnalogChannels = 0;
|
||||
#ifdef _RTAI
|
||||
detectedNumberOfInputAnalogChannels = GetNumberOfInputAnalogChannels(moduleIdentifier);
|
||||
#elif defined(_LINUX)
|
||||
int32 temp = moduleIdentifier;
|
||||
int32 ret = ioctl(ATCAadcDrv::fileDescriptor, PCIE_ATCA_ADC_IOCT_N_IN_ANA_CHANNELS, &temp);
|
||||
if(ret != 0){
|
||||
CStaticAssertErrorCondition(InitialisationError,"SingleATCAModule::ObjectLoadSetup: Could not query number of analog input channels. ioctl returned : %d", ret);
|
||||
return False;
|
||||
}
|
||||
detectedNumberOfInputAnalogChannels = temp;
|
||||
#endif
|
||||
if(numberOfAnalogueInputChannels > detectedNumberOfInputAnalogChannels){
|
||||
CStaticAssertErrorCondition(InitialisationError,"SingleATCAModule::ObjectLoadSetup: NumberOfAnalogueInputs is at most %d. Specified %d.", detectedNumberOfInputAnalogChannels, numberOfAnalogueInputChannels);
|
||||
return False;
|
||||
}
|
||||
|
||||
|
||||
int32 detectedNumberOfInputDigitalChannels = 0;
|
||||
#ifdef _RTAI
|
||||
detectedNumberOfInputDigitalChannels = GetNumberOfInputDigitalChannels(moduleIdentifier);
|
||||
#elif defined(_LINUX)
|
||||
temp = moduleIdentifier;
|
||||
ret = ioctl(ATCAadcDrv::fileDescriptor, PCIE_ATCA_ADC_IOCT_N_IN_DIG_CHANNELS, &temp);
|
||||
if(ret != 0){
|
||||
CStaticAssertErrorCondition(InitialisationError,"SingleATCAModule::ObjectLoadSetup: Could not query number of digital input channels. ioctl returned : %d", ret);
|
||||
return False;
|
||||
}
|
||||
detectedNumberOfInputDigitalChannels = temp;
|
||||
#endif
|
||||
if(numberOfDigitalInputChannels > detectedNumberOfInputDigitalChannels){
|
||||
CStaticAssertErrorCondition(InitialisationError,"SingleATCAModule::ObjectLoadSetup: NumberOfDigitalInputs is at most %d. Specified %d.", detectedNumberOfInputDigitalChannels, numberOfDigitalInputChannels);
|
||||
return False;
|
||||
}
|
||||
|
||||
int32 detectedNumberOfOutputAnalogChannels = 0;
|
||||
#ifdef _RTAI
|
||||
detectedNumberOfOutputAnalogChannels = GetNumberOfAnalogueOutputChannels(moduleIdentifier);
|
||||
#elif defined(_LINUX)
|
||||
temp = moduleIdentifier;
|
||||
ret = ioctl(ATCAadcDrv::fileDescriptor, PCIE_ATCA_ADC_IOCT_N_OUT_ANA_CHANNELS, &temp);
|
||||
if(ret != 0){
|
||||
CStaticAssertErrorCondition(InitialisationError,"SingleATCAModule::ObjectLoadSetup: Could not query number of analog output channels. ioctl returned : %d", ret);
|
||||
return False;
|
||||
}
|
||||
detectedNumberOfOutputAnalogChannels = temp;
|
||||
#endif
|
||||
if(numberOfAnalogueOutputChannels > detectedNumberOfOutputAnalogChannels){
|
||||
CStaticAssertErrorCondition(InitialisationError,"SingleATCAModule::ObjectLoadSetup: NumberOfAnalogueOutputs is at most %d. Specified %d.", detectedNumberOfOutputAnalogChannels, numberOfAnalogueOutputChannels);
|
||||
return False;
|
||||
}
|
||||
|
||||
int32 detectedNumberOfDigitalOutputChannels = 0;
|
||||
#ifdef _RTAI
|
||||
detectedNumberOfDigitalOutputChannels = GetNumberOfDigitalOutputChannels(moduleIdentifier);
|
||||
#elif defined(_LINUX)
|
||||
temp = moduleIdentifier;
|
||||
ret = ioctl(ATCAadcDrv::fileDescriptor, PCIE_ATCA_ADC_IOCT_N_OUT_DIG_CHANNELS, &temp);
|
||||
if(ret != 0){
|
||||
CStaticAssertErrorCondition(InitialisationError,"SingleATCAModule::ObjectLoadSetup: Could not query number of digital output channels. ioctl returned : %d", ret);
|
||||
return False;
|
||||
}
|
||||
detectedNumberOfDigitalOutputChannels = temp;
|
||||
#endif
|
||||
if(numberOfDigitalOutputChannels > detectedNumberOfDigitalOutputChannels){
|
||||
CStaticAssertErrorCondition(InitialisationError,"SingleATCAModule::ObjectLoadSetup: NumberOfAnalogueOutputs is at most %d. Specified %d.", detectedNumberOfDigitalOutputChannels, numberOfAnalogueOutputChannels);
|
||||
return False;
|
||||
}
|
||||
|
||||
if(numberOfAnalogueOutputChannels > 0){
|
||||
bool hasRTM = False;
|
||||
#ifdef _RTAI
|
||||
hasRTM = IsRTMPresent(moduleIdentifier);
|
||||
#elif defined(_LINUX)
|
||||
int rtm = moduleIdentifier;
|
||||
ret = ioctl(ATCAadcDrv::fileDescriptor, PCIE_ATCA_ADC_IOCT_IS_RTM_PRESENT, &rtm);
|
||||
if(ret != 0){
|
||||
CStaticAssertErrorCondition(InitialisationError,"SingleATCAModule::ObjectLoadSetup: Could not query IsRTMPresent. ioctl returned : %d", ret);
|
||||
return False;
|
||||
}
|
||||
hasRTM = (rtm == 1);
|
||||
#endif
|
||||
if(!hasRTM){
|
||||
CStaticAssertErrorCondition(Warning,"SingleATCAModule::ObjectLoadSetup: Module %d specifies %d outputs but does not have RTM module", moduleIdentifier, numberOfAnalogueOutputChannels);
|
||||
return False;
|
||||
}
|
||||
int dims = 1;
|
||||
int size[2] = {numberOfAnalogueOutputChannels,1};
|
||||
if(!cdb.ReadInt32Array(outputMap, size, dims, "OutputMap")){
|
||||
CStaticAssertErrorCondition(Warning,"SingleATCAModule::ObjectLoadSetup: OutputMap not specified. Assuming sequential order.");
|
||||
for(int i = 0; i < numberOfAnalogueOutputChannels; i++)
|
||||
outputMap[i] = i+1;
|
||||
}
|
||||
|
||||
// output order starts from 0 for convenience.
|
||||
for(int i = 0; i < numberOfAnalogueOutputChannels; i++) outputMap[i]--;
|
||||
}
|
||||
|
||||
if(channelStatistics != NULL){
|
||||
delete[] channelStatistics;
|
||||
channelStatistics = NULL;
|
||||
}
|
||||
|
||||
channelStatistics = new StatSignalInfo[NumberOfInputChannels()];
|
||||
if(channelStatistics == NULL){
|
||||
CStaticAssertErrorCondition(InitialisationError,"SingleATCAModule::ObjectLoadSetup: Could not create ChannelStatistics for %d channels", NumberOfInputChannels());
|
||||
return False;
|
||||
}
|
||||
|
||||
for(int i=0; i<NumberOfInputChannels(); i++){
|
||||
channelStatistics[i].Init();
|
||||
channelStatistics[i].decayRate = 0.999;
|
||||
}
|
||||
|
||||
if(isMaster){
|
||||
if(!cdb.ReadInt32(boardInternalCycleTime, "BoardInternalCycleTime",50)){
|
||||
CStaticAssertErrorCondition(Warning,"SingleATCAModule::ObjectLoadSetup: BoardInternalCycleTime has not been specified. Assuming %d usec triggering period", boardInternalCycleTime);
|
||||
}
|
||||
boardInternalCycleTicks = (int64)(boardInternalCycleTime * 1e-6 * HRT::HRTFrequency());
|
||||
|
||||
int32 temp = 0;
|
||||
if(!cdb.ReadInt32(temp, "DatagramMonitoringFastSleep",2)){
|
||||
CStaticAssertErrorCondition(Warning,"SingleATCAModule::ObjectLoadSetup: DataArrivalUsecSleep has not been specified. Assuming %d usec sleeping time.", temp);
|
||||
}
|
||||
datagramArrivalFastMonitorSecSleep = temp*1e-6;
|
||||
if(!cdb.ReadInt32(temp, "DataAcquisitionUsecTimeOut",1000)){
|
||||
CStaticAssertErrorCondition(Warning,"SingleATCAModule::ObjectLoadSetup: DataAcquisitionUsecTimeOut has not been specified. Assuming %d usec of timeout.", temp);
|
||||
}
|
||||
|
||||
double deltaT = temp*1e-6;
|
||||
dataAcquisitionUsecTimeOut = (int64)(deltaT*HRT::HRTFrequency());
|
||||
|
||||
if(!cdb.ReadInt32(temp, "AllowPollSleeping", 1)){
|
||||
CStaticAssertErrorCondition(Warning,"SingleATCAModule::ObjectLoadSetup: AllowPollSleeping has not been specified. Assuming %d ", allowPollSleeping);
|
||||
}
|
||||
allowPollSleeping = (temp == 1);
|
||||
|
||||
if(!cdb.ReadFloat(worstPollSleepJitterDecayRate, "WorstPollSleepJitterDecayRate", 5e-6)){
|
||||
CStaticAssertErrorCondition(Warning,"SingleATCAModule::ObjectLoadSetup: WorstPollSleepJitterDecayRate has not been specified. Assuming %f ", worstPollSleepJitterDecayRate);
|
||||
}
|
||||
worstPollSleepJitterDecayRate = 1 - worstPollSleepJitterDecayRate;
|
||||
if(!cdb.ReadFloat(pollSleepTimeWakeBeforeUs, "PollSleepTimeWakeBeforeUs", 20)){
|
||||
CStaticAssertErrorCondition(Warning,"SingleATCAModule::ObjectLoadSetup: PollSleepTimeWakeBeforeUs has not been specified. Assuming %f ", pollSleepTimeWakeBeforeUs);
|
||||
}
|
||||
pollSleepTimeWakeBeforeUs *= 1e-6;
|
||||
}
|
||||
return True;
|
||||
}
|
||||
|
||||
/** Copies the pointers to the DMA Buffers */
|
||||
#ifdef _LINUX
|
||||
bool SingleATCAModule::InstallDMABuffers(int32 *mappedDmaMemoryLocation){
|
||||
int32 boardSlotNums[12];
|
||||
int32 boardIdx = 0;
|
||||
int ret = ioctl(ATCAadcDrv::fileDescriptor, PCIE_ATCA_ADC_IOCT_GET_BOARD_SLOT_NS, boardSlotNums);
|
||||
if(ret != 0){
|
||||
CStaticAssertErrorCondition(InitialisationError,"SingleATCAModule::ObjectLoadSetup: Could not query the number of boards. ioctl returned : %d",ret);
|
||||
return False;
|
||||
}
|
||||
|
||||
for(boardIdx = 0; boardIdx < 12; boardIdx++){
|
||||
if(boardSlotNums[boardIdx] == moduleIdentifier){
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int32 pageInc = ATCAadcDrv::pageSize / sizeof(int32);
|
||||
for(int32 i = 0; i < DMA_BUFFS; i++){
|
||||
dmaBuffers[i] = mappedDmaMemoryLocation + pageInc * (DMA_BUFFS * boardIdx + i);
|
||||
CStaticAssertErrorCondition(Information,"SingleATCAModule::InstallDMABuffers: DMABuffer[%d] %p ",i, dmaBuffers[i]);
|
||||
}
|
||||
|
||||
CStaticAssertErrorCondition(Information,"SingleATCAModule::InstallDMABuffers: dmaBuffers: %p %p %p %p", dmaBuffers[0], dmaBuffers[1], dmaBuffers[2], dmaBuffers[3]);
|
||||
return True;
|
||||
}
|
||||
#else
|
||||
/** Copies the pointers to the DMA Buffers */
|
||||
bool SingleATCAModule::InstallDMABuffers(){
|
||||
int *boardDMABufferPointers = GetBoardBufferAddress(moduleIdentifier);
|
||||
if(boardDMABufferPointers == NULL) return False;
|
||||
for(int32 i = 0; i < DMA_BUFFS; i++){
|
||||
dmaBuffers[i] = (int32 *)boardDMABufferPointers[i];
|
||||
CStaticAssertErrorCondition(Information,"SingleATCAModule::InstallDMABuffers: DMABuffer[%d] %p ",i, dmaBuffers[i]);
|
||||
}
|
||||
|
||||
CStaticAssertErrorCondition(Information,"SingleATCAModule::InstallDMABuffers: dmaBuffers: %p %p %p %p", dmaBuffers[0], dmaBuffers[1], dmaBuffers[2], dmaBuffers[3]);
|
||||
return True;
|
||||
}
|
||||
#endif
|
||||
|
||||
int32 SingleATCAModule::GetLatestBufferIndex(){
|
||||
|
||||
uint32 *latestBufferHeader = (uint32 *)dmaBuffers[0];
|
||||
uint32 latestBufferIndex = 0;
|
||||
|
||||
// check which one is the oldest buffer
|
||||
for (int dmaIndex = 1; dmaIndex < DMA_BUFFS; dmaIndex++) {
|
||||
// Pointer to the header
|
||||
uint32 *header = (uint32 *)dmaBuffers[dmaIndex];
|
||||
//uint32 *footer = header + NumberOfInputChannels() + HEADER_LENGTH;
|
||||
|
||||
if ((*header > *latestBufferHeader)) {
|
||||
latestBufferHeader = header;
|
||||
latestBufferIndex = dmaIndex;
|
||||
}
|
||||
}
|
||||
return latestBufferIndex;
|
||||
}
|
||||
|
||||
|
||||
int32 SingleATCAModule::CurrentBufferIndex(){
|
||||
|
||||
uint32 *oldestBufferHeader = (uint32 *)dmaBuffers[0];
|
||||
uint32 oldestBufferIndex = 0;
|
||||
|
||||
int64 stopAcquisition = HRT::HRTCounter() + dataAcquisitionUsecTimeOut;
|
||||
|
||||
// check which one is the oldest buffer
|
||||
int dmaIndex = 0;
|
||||
for (dmaIndex = 1; dmaIndex < DMA_BUFFS; dmaIndex++) {
|
||||
// Pointer to the header
|
||||
uint32 *header = (uint32 *)dmaBuffers[dmaIndex];
|
||||
if (*header < *oldestBufferHeader) {
|
||||
oldestBufferHeader = header;
|
||||
oldestBufferIndex = dmaIndex;
|
||||
}
|
||||
}
|
||||
|
||||
uint32 *oldestBufferFooter = oldestBufferHeader + NumberOfInputChannels() + HEADER_LENGTH;
|
||||
uint32 oldestTimeMark = *oldestBufferFooter;
|
||||
|
||||
// If the data transfer is not in progress it means that the new data will
|
||||
// be stored in the oldest buffer.
|
||||
int64 actualTime = HRT::HRTCounter();
|
||||
while (oldestTimeMark == *oldestBufferFooter) {
|
||||
if(actualTime > stopAcquisition) {
|
||||
return -1;
|
||||
}
|
||||
actualTime = HRT::HRTCounter();
|
||||
}
|
||||
|
||||
if(*oldestBufferHeader == *oldestBufferFooter) return oldestBufferIndex;
|
||||
return -2;
|
||||
}
|
||||
|
||||
bool SingleATCAModule::WriteData(const int32 *&buffer){
|
||||
for(int i = 0; i < numberOfAnalogueOutputChannels; i++){
|
||||
#ifdef _LINUX
|
||||
int32 toWrite[4];
|
||||
toWrite[0] = moduleIdentifier;
|
||||
toWrite[1] = outputMap[i];
|
||||
toWrite[2] = *buffer++;
|
||||
toWrite[3] = 0;
|
||||
write(ATCAadcDrv::fileDescriptor, toWrite, 4 * sizeof(int32));
|
||||
#else
|
||||
WriteToDAC(moduleIdentifier, outputMap[i], *buffer++);
|
||||
#endif
|
||||
}
|
||||
for(int i = 0; i < numberOfDigitalOutputChannels; i++){
|
||||
#ifdef _LINUX
|
||||
int32 toWrite[4];
|
||||
toWrite[0] = moduleIdentifier;
|
||||
toWrite[1] = 0;
|
||||
toWrite[2] = *buffer++;
|
||||
toWrite[3] = 1;
|
||||
if(write(ATCAadcDrv::fileDescriptor, toWrite, 4 * sizeof(int32)) < 0){
|
||||
CStaticAssertErrorCondition(FatalError,"SingleATCAModule::WriteData: Could not write the value : %d to module %d", toWrite[2], toWrite[0]);
|
||||
return False;
|
||||
}
|
||||
#else
|
||||
WriteToDIO(moduleIdentifier, 0, *buffer++);
|
||||
#endif
|
||||
}
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
bool SingleATCAModule::Poll(){
|
||||
#ifdef _LINUX
|
||||
static int firstTime = 1;
|
||||
if(firstTime == 1){
|
||||
SleepSec(1e-3);
|
||||
firstTime = 0;
|
||||
}
|
||||
#endif
|
||||
if(isMaster){
|
||||
if (synchronizing) {
|
||||
if(allowPollSleeping) {
|
||||
//Allow the worstPollSleepJitter to decay -> 0
|
||||
worstPollSleepJitter *= worstPollSleepJitterDecayRate;
|
||||
int64 tStart = HRT::HRTCounter();
|
||||
pollSleepTime = (nextExpectedAcquisitionCPUTicks - tStart) * HRT::HRTPeriod() - pollSleepTimeWakeBeforeUs - worstPollSleepJitter;
|
||||
if(pollSleepTime > 0){
|
||||
SleepNoMore(pollSleepTime);
|
||||
float jitter = ((HRT::HRTCounter() - tStart) * HRT::HRTPeriod()) - pollSleepTime;
|
||||
if(jitter < 0) jitter = -jitter;
|
||||
|
||||
if(jitter > worstPollSleepJitter){
|
||||
worstPollSleepJitter = jitter;
|
||||
}
|
||||
}
|
||||
}
|
||||
int32 previousAcquisitionIndex = currentDMABufferIndex;
|
||||
int32 currentDMA = CurrentBufferIndex();
|
||||
if(currentDMA < 0){
|
||||
CStaticAssertErrorCondition(Warning,"SingleATCAModule::GetData: Returned -1");
|
||||
return False;
|
||||
}
|
||||
|
||||
currentDMABufferIndex = currentDMA;
|
||||
|
||||
// Update NextExecTime with a guess
|
||||
nextExpectedAcquisitionCPUTicks = HRT::HRTCounter() + boardInternalCycleTicks;
|
||||
int deltaBuffer = *dmaBuffers[currentDMABufferIndex] - *dmaBuffers[previousAcquisitionIndex];
|
||||
int nOfLostPackets = deltaBuffer - boardInternalCycleTime;
|
||||
|
||||
if( *dmaBuffers[currentDMABufferIndex] == 0){
|
||||
printf("dmaBuffers[currentDMABufferIndex]: %d, *dmaBuffers[previousAcquisitionIndex = %d\n", *dmaBuffers[currentDMABufferIndex], *dmaBuffers[previousAcquisitionIndex]);
|
||||
}
|
||||
|
||||
if (( nOfLostPackets > 0)){
|
||||
CStaticAssertErrorCondition(Warning,"SingleATCAModule::GetData: Lost %d Packets", nOfLostPackets / boardInternalCycleTime);
|
||||
CStaticAssertErrorCondition(Warning,"SingleATCAModule::GetData: boardInternalCycleTime %d, deltaBuffer: %d", boardInternalCycleTime, deltaBuffer);
|
||||
}
|
||||
currentMasterHeader = *(dmaBuffers[currentDMABufferIndex]);
|
||||
lastCycleUsecTime = (uint32)currentMasterHeader;
|
||||
}
|
||||
return True;
|
||||
}
|
||||
return False;
|
||||
}
|
||||
|
||||
bool SingleATCAModule::GetData(int32 *&buffer){
|
||||
|
||||
/** Perform synchronisation */
|
||||
if(isMaster){
|
||||
if (synchronizing) {
|
||||
buffer[0] = *dmaBuffers[currentDMABufferIndex];
|
||||
buffer[1] = buffer[0];
|
||||
|
||||
// Skip the packet sample number and sample time
|
||||
buffer += 2;
|
||||
currentMasterHeader = *(dmaBuffers[currentDMABufferIndex]);
|
||||
lastCycleUsecTime = (uint32)currentMasterHeader;
|
||||
} else {
|
||||
currentDMABufferIndex = GetLatestBufferIndex();
|
||||
}
|
||||
}else{
|
||||
int32 *header = dmaBuffers[currentDMABufferIndex];
|
||||
int32 *footer = header + NumberOfInputChannels() + HEADER_LENGTH;
|
||||
if(*header != currentMasterHeader){
|
||||
CStaticAssertErrorCondition(FatalError, "SingleATCAModule (slot=%d)::GetData: h (=%d) different from master h(=%d)", moduleIdentifier, *header, currentMasterHeader);
|
||||
return False;
|
||||
}
|
||||
if(*header != *footer){
|
||||
CStaticAssertErrorCondition(FatalError, "SingleATCAModule (slot=%d)::GetData: The header (=%d) is different from the footer(=%d)", moduleIdentifier, *header, *footer);
|
||||
return False;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Skip the Header in the DMA Buffer
|
||||
int32 *src = (int32 *)dmaBuffers[currentDMABufferIndex] + 1;
|
||||
int32 *dest = buffer;
|
||||
memcpy(dest, src, NumberOfInputChannels()*sizeof(int32));
|
||||
|
||||
//This is introducing a huge delay (~1.5us per board). To be solved.
|
||||
/*for(int i=0; i<NumberOfInputChannels(); i++){
|
||||
channelStatistics[i].Update((float)(buffer[i] * 1.49e-8));
|
||||
}*/
|
||||
buffer += NumberOfInputChannels();
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
bool SingleATCAModule::ProcessHttpMessage(HttpStream &hStream) {
|
||||
hStream.Printf("<table class=\"bltable\">\n");
|
||||
hStream.Printf("<tr>\n");
|
||||
hStream.Printf("<td>Module Identifier</td><td>%d</td>\n", moduleIdentifier);
|
||||
hStream.Printf("</tr>\n");
|
||||
hStream.Printf("<tr>\n");
|
||||
hStream.Printf("<td>Master</td><td>%s</td>\n", isMaster ? "True" : "False");
|
||||
hStream.Printf("</tr>\n");
|
||||
hStream.Printf("</table>\n");
|
||||
hStream.Printf("<table class=\"bltable\">\n");
|
||||
hStream.Printf("<tr><th>Channel</th><th>Last</th><th>Mean</th><th>Variance</th><th>Abs Max</th><th>Abs Min</th><th>Rel Max</th><th>Rel Min</th></tr>\n");
|
||||
int i=0;
|
||||
for(i=0; i<NumberOfInputChannels(); i++){
|
||||
hStream.Printf("<tr><td>%d</td><td>%.3e</td><td>%.3e</td><td>%.3e</td><td>%.3e</td><td>%.3e</td><td>%.3e</td><td>%.3e</td></tr>\n", i + 1, channelStatistics[i].LastValue(), channelStatistics[i].Mean(10), channelStatistics[i].Variance(10), channelStatistics[i].AbsMax(), channelStatistics[i].AbsMin(), channelStatistics[i].RelMax(), channelStatistics[i].RelMin());
|
||||
}
|
||||
hStream.Printf("</table>");
|
||||
return True;
|
||||
}
|
||||
|
||||
bool SingleATCAModule::ResetStatistics(){
|
||||
int i=0;
|
||||
for(i=0; i<NumberOfInputChannels(); i++){
|
||||
channelStatistics[i].Init();
|
||||
}
|
||||
return True;
|
||||
}
|
||||
|
||||
ATCAadcDrv::ATCAadcDrv(){
|
||||
numberOfBoards = 0;
|
||||
lastCycleUsecTime = 0;
|
||||
modules = NULL;
|
||||
synchronizing = False;
|
||||
softwareTrigger = 0;
|
||||
masterBoardIdx = -1;
|
||||
autoSoftwareTriggerAfterUs = -1;
|
||||
autoSoftwareTrigger = False;
|
||||
#ifdef _LINUX
|
||||
fileDescriptor = 0;
|
||||
pageSize = sysconf(_SC_PAGE_SIZE);
|
||||
#endif
|
||||
css = "table.bltable {"
|
||||
"margin: 1em 1em 1em 2em;"
|
||||
"background: whitesmoke;"
|
||||
"border-collapse: collapse;"
|
||||
"}"
|
||||
"table.bltable th, table.bltable td {"
|
||||
"border: 1px silver solid;"
|
||||
"padding: 0.2em;"
|
||||
"}"
|
||||
"table.bltable th {"
|
||||
"background: gainsboro;"
|
||||
"text-align: left;"
|
||||
"}"
|
||||
"table.bltable caption {"
|
||||
"margin-left: inherit;"
|
||||
"margin-right: inherit;"
|
||||
"}";
|
||||
}
|
||||
|
||||
bool ATCAadcDrv::EnableAcquisition(){
|
||||
if(modules == NULL) return False;
|
||||
#ifdef _RTAI
|
||||
return (EnableATCApcieAcquisition() == 0);
|
||||
#elif defined(_LINUX)
|
||||
int ret = ioctl(fileDescriptor, PCIE_ATCA_ADC_IOCT_ACQ_ENABLE);
|
||||
if(ret != 0){
|
||||
AssertErrorCondition(InitialisationError,"ATCAadcDrv::ObjectLoadSetup: %s: Could not enable acquisition. ioctl returned : %d",Name(), ret);
|
||||
return False;
|
||||
}
|
||||
#endif
|
||||
return True;
|
||||
}
|
||||
|
||||
bool ATCAadcDrv::DisableAcquisition(){
|
||||
if(modules == NULL) return False;
|
||||
#ifdef _RTAI
|
||||
return (DisableATCApcieAcquisition() == 0);
|
||||
#elif defined(_LINUX)
|
||||
int ret = ioctl(fileDescriptor, PCIE_ATCA_ADC_IOCT_ACQ_DISABLE);
|
||||
if(ret != 0){
|
||||
AssertErrorCondition(InitialisationError,"ATCAadcDrv::ObjectLoadSetup: %s: Could not disable acquisition. ioctl returned : %d",Name(), ret);
|
||||
return False;
|
||||
}
|
||||
#endif
|
||||
return True;
|
||||
}
|
||||
|
||||
bool ATCAadcDrv::ObjectLoadSetup(ConfigurationDataBase &info,StreamInterface *err){
|
||||
#ifdef _LINUX
|
||||
fileDescriptor = open("/dev/pcieATCAAdc0", O_RDWR);
|
||||
if(fileDescriptor < 1){
|
||||
AssertErrorCondition(InitialisationError,"ATCAadcDrv::ObjectLoadSetup: %s: Could not open device driver at: %s",Name(), "/dev/pcieATCAAdc0");
|
||||
return False;
|
||||
}
|
||||
#endif
|
||||
DisableAcquisition();
|
||||
|
||||
CDBExtended cdb(info);
|
||||
|
||||
if(!cdb.ReadInt32(softwareTrigger, "UseSoftwareTrigger",0)){
|
||||
CStaticAssertErrorCondition(Warning,"SingleATCAModule::ObjectLoadSetup: UseSoftwareTrigger has not been specified. Assuming hardware trigger");
|
||||
}
|
||||
|
||||
if(!GenericAcqModule::ObjectLoadSetup(cdb,err)){
|
||||
AssertErrorCondition(InitialisationError,"ATCAadcDrv::ObjectLoadSetup: %s: GenericAcqModule::ObjectLoadSetup failed",Name());
|
||||
return False;
|
||||
}
|
||||
|
||||
FString syncMethod;
|
||||
if(!cdb.ReadFString(syncMethod, "SynchronizationMethod")){
|
||||
CStaticAssertErrorCondition(InitialisationError,"ATCAAdcDrv::ObjectLoadSetup: SynchronizationMethod has not been specified.");
|
||||
return False;
|
||||
}
|
||||
if (syncMethod == "GetLatest") synchronizing = False;
|
||||
else synchronizing = True;
|
||||
|
||||
cdb.ReadInt32(autoSoftwareTriggerAfterUs, "AutoSoftwareTriggerAfterUs", -1);
|
||||
autoSoftwareTrigger = (autoSoftwareTriggerAfterUs > 0);
|
||||
if(autoSoftwareTrigger){
|
||||
CStaticAssertErrorCondition(Information, "ATCAadcDrv::ObjectLoadSetup: %s the system will be automatically triggered after %d us", Name(), autoSoftwareTriggerAfterUs);
|
||||
}
|
||||
|
||||
// Get buffer address from the driver exported function GetBufferAddress (only works in RTAI!)
|
||||
#ifdef _RTAI
|
||||
numberOfBoards = GetNumberOfBoards();
|
||||
#elif defined(_LINUX)
|
||||
int ret = ioctl(fileDescriptor, PCIE_ATCA_ADC_IOCT_NUM_BOARDS, &numberOfBoards);
|
||||
if(ret != 0){
|
||||
AssertErrorCondition(InitialisationError,"ATCAadcDrv::ObjectLoadSetup: %s: Could not query the number of boards. ioctl returned : %d",Name(), ret);
|
||||
return False;
|
||||
}
|
||||
|
||||
mappedDmaMemorySize = numberOfBoards * DMA_BUFFS * pageSize;
|
||||
mappedDmaMemoryLocation = (int32 *)mmap(0, mappedDmaMemorySize, PROT_READ, MAP_FILE | MAP_SHARED | MAP_LOCKED | MAP_POPULATE | MAP_NONBLOCK, fileDescriptor, 0);
|
||||
if(mappedDmaMemoryLocation == MAP_FAILED) {
|
||||
AssertErrorCondition(InitialisationError,"ATCAadcDrv::ObjectLoadSetup: %s: MAP_FAILED",Name());
|
||||
return False;
|
||||
}
|
||||
#else
|
||||
numberOfBoards = -1;
|
||||
#endif
|
||||
|
||||
if(!cdb->Move( "Modules")){
|
||||
AssertErrorCondition(InitialisationError,"ATCAadcDrv::ObjectLoadSetup: %s: No Module has been specified",Name());
|
||||
return False;
|
||||
}
|
||||
|
||||
int32 nOfATCAModules = cdb->NumberOfChildren();
|
||||
if(nOfATCAModules!= numberOfBoards){
|
||||
AssertErrorCondition(InitialisationError,"ATCAadcDrv::ObjectLoadSetup: %s: Number of installed boards [%d] differs from the number of specified boards [%d].",Name(),numberOfBoards,nOfATCAModules);
|
||||
return False;
|
||||
}
|
||||
|
||||
if(modules != NULL) delete[] modules;
|
||||
modules = new SingleATCAModule[nOfATCAModules];
|
||||
if(modules == NULL){
|
||||
AssertErrorCondition(InitialisationError,"ATCAadcDrv::ObjectLoadSetup: %s: Failed allocating space for %d modules.",Name(),nOfATCAModules);
|
||||
return False;
|
||||
}
|
||||
|
||||
masterBoardIdx = -1;
|
||||
for(int i = 0; i < nOfATCAModules; i++){
|
||||
cdb->MoveToChildren(i);
|
||||
cdb.WriteFString(syncMethod,"SynchronizationMethod");
|
||||
|
||||
if(!modules[i].ObjectLoadSetup(cdb,err)){
|
||||
AssertErrorCondition(InitialisationError,"ATCAadcDrv::ObjectLoadSetup: %s: Failed initialising module %d.",Name(),i);
|
||||
delete[] modules;
|
||||
return False;
|
||||
}
|
||||
|
||||
if(modules[i].isMaster){
|
||||
if(masterBoardIdx == -1){
|
||||
masterBoardIdx = i;
|
||||
}else{
|
||||
AssertErrorCondition(InitialisationError,"ATCAadcDrv::ObjectLoadSetup: %s: Failed initialising module %d. A master board was already specified at index: %d",Name(),i,masterBoardIdx);
|
||||
return False;
|
||||
}
|
||||
}
|
||||
cdb->MoveToFather();
|
||||
}
|
||||
|
||||
for(int i = 0; i < nOfATCAModules; i++){
|
||||
#ifdef _LINUX
|
||||
if(!modules[i].InstallDMABuffers(mappedDmaMemoryLocation)){
|
||||
#else
|
||||
if(!modules[i].InstallDMABuffers()){
|
||||
#endif
|
||||
AssertErrorCondition(InitialisationError,"ATCAadcDrv::ObjectLoadSetup: %s: Board %d failed to initialise DMA buffers",Name(), i);
|
||||
return False;
|
||||
}
|
||||
}
|
||||
|
||||
cdb->MoveToFather();
|
||||
|
||||
int32 extTriggerAndClock = 0;
|
||||
if(!cdb.ReadInt32(extTriggerAndClock, "ExtTriggerAndClock",1)){
|
||||
AssertErrorCondition(Warning,"ATCAadcDrv::ObjectLoadSetup: %s: ExtTriggerAndClock not specified, using default = %d",Name(), extTriggerAndClock);
|
||||
}
|
||||
|
||||
#ifdef _LINUX
|
||||
ret = ioctl(fileDescriptor, PCIE_ATCA_ADC_IOCT_SET_EXT_CLK_TRG, &extTriggerAndClock);
|
||||
if(ret != 0){
|
||||
AssertErrorCondition(InitialisationError,"ATCAadcDrv::ObjectLoadSetup: %s: Could not SetATCApcieExternalTriggerAndClock. ioctl returned : %d",Name(), ret);
|
||||
return False;
|
||||
}
|
||||
#else
|
||||
SetATCApcieExternalTriggerAndClock(extTriggerAndClock);
|
||||
#endif
|
||||
// Setup OK
|
||||
|
||||
AssertErrorCondition(Information,"ATCAadcDrv::ObjectLoadSetup: %s: initialized correctly ",Name());
|
||||
EnableAcquisition();
|
||||
return True;
|
||||
}
|
||||
|
||||
bool ATCAadcDrv::ObjectDescription(StreamInterface &s,bool full,StreamInterface *err){
|
||||
|
||||
s.Printf("%s %s\n",ClassName(),Version());
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
bool ATCAadcDrv::WriteData(uint32 usecTime, const int32 *buffer){
|
||||
if(buffer == NULL) return False;
|
||||
const int32 *lBuffer = buffer;
|
||||
for(int i = 0; i < numberOfBoards; i++){
|
||||
modules[i].WriteData(lBuffer);
|
||||
}
|
||||
return True;
|
||||
}
|
||||
|
||||
int32 ATCAadcDrv::GetData(uint32 usecTime, int32 *buffer, int32 bufferNum){
|
||||
|
||||
//Check buffer existence
|
||||
if(buffer == NULL){
|
||||
AssertErrorCondition(FatalError,"ATCAadcDrv::GetData: %s. The DDInterface buffer is NULL.",Name());
|
||||
return -1;
|
||||
}
|
||||
|
||||
int32 *lBuffer = buffer;
|
||||
for(int i = 0; i < numberOfBoards; i++){
|
||||
if(!modules[i].GetData(lBuffer)){
|
||||
AssertErrorCondition(FatalError,"ATCAadcDrv::GetData: %s. Module %d failed acquiring data",Name(),i);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool ATCAadcDrv::Poll(){
|
||||
if(autoSoftwareTrigger){
|
||||
if(lastCycleUsecTime > autoSoftwareTriggerAfterUs){
|
||||
SoftwareTrigger();
|
||||
}
|
||||
}
|
||||
bool ok = modules[masterBoardIdx].Poll();
|
||||
if(!ok){
|
||||
return ok;
|
||||
}
|
||||
// If the module is the timingATMDrv call the Trigger() method of
|
||||
// the time service object
|
||||
lastCycleUsecTime = modules[masterBoardIdx].lastCycleUsecTime;
|
||||
|
||||
for(int i = 0; i < nOfTriggeringServices; i++){
|
||||
triggerService[i].Trigger();
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool ATCAadcDrv::ProcessHttpMessage(HttpStream &hStream) {
|
||||
hStream.SSPrintf("OutputHttpOtions.Content-Type","text/html");
|
||||
hStream.keepAlive = False;
|
||||
//copy to the client
|
||||
hStream.Printf("<html><head><title>%s</title>", Name());
|
||||
hStream.Printf( "<style type=\"text/css\">\n" );
|
||||
hStream.Printf("%s\n", css);
|
||||
hStream.Printf( "</style></head><body>\n" );
|
||||
hStream.Printf("<table class=\"bltable\">\n");
|
||||
int i=0;
|
||||
hStream.Printf("<tr>\n");
|
||||
for(i=0; i<numberOfBoards; i++){
|
||||
hStream.Printf("<td>%d</td>\n", modules[i].BoardIdentifier());
|
||||
}
|
||||
hStream.Printf("</tr>\n");
|
||||
hStream.Printf("<tr>\n");
|
||||
for(i=0; i<numberOfBoards; i++){
|
||||
hStream.Printf("<td>%s</td>\n", modules[i].isMaster ? "M" : "");
|
||||
}
|
||||
hStream.Printf("</tr>\n");
|
||||
hStream.Printf("<tr>\n");
|
||||
for(i=0; i<numberOfBoards; i++){
|
||||
hStream.Printf("<td>%s</td>\n", modules[i].NumberOfOutputChannels() > 0 ? "R" : "");
|
||||
}
|
||||
hStream.Printf("</tr>\n");
|
||||
hStream.Printf("<tr>\n");
|
||||
hStream.Printf("<form>\n");
|
||||
for(i=0; i<numberOfBoards; i++){
|
||||
hStream.Printf("<td><button type=\"submit\" name=\"boardID\" value=\"%d\">.</button></td>\n", modules[i].BoardIdentifier());
|
||||
}
|
||||
hStream.Printf("</tr>\n");
|
||||
hStream.Printf("</form>\n");
|
||||
hStream.Printf("</table>\n");
|
||||
hStream.Printf("<form>\n");
|
||||
hStream.Printf("<td><button type=\"submit\" name=\"reset\" value=\"true\">Reset statistics</button></td>\n");
|
||||
hStream.Printf("</form>\n");
|
||||
|
||||
FString reqBoardID;
|
||||
reqBoardID.SetSize(0);
|
||||
if (hStream.Switch("InputCommands.boardID")){
|
||||
hStream.Seek(0);
|
||||
hStream.GetToken(reqBoardID, "");
|
||||
hStream.Switch((uint32)0);
|
||||
}
|
||||
FString reqReset;
|
||||
reqReset.SetSize(0);
|
||||
if (hStream.Switch("InputCommands.reset")){
|
||||
hStream.Seek(0);
|
||||
hStream.GetToken(reqReset, "");
|
||||
hStream.Switch((uint32)0);
|
||||
}
|
||||
if(reqReset.Size() > 0){
|
||||
for(i=0; i<numberOfBoards; i++){
|
||||
modules[i].ResetStatistics();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(reqBoardID.Size() > 0){
|
||||
int32 boardID = atoi(reqBoardID.Buffer());
|
||||
for(i=0; i<numberOfBoards; i++){
|
||||
if(modules[i].BoardIdentifier() == boardID){
|
||||
modules[i].ProcessHttpMessage(hStream);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
hStream.Printf("<p>Worst polling jitter (us): %f\n", modules[masterBoardIdx].worstPollSleepJitter * 1e6);
|
||||
hStream.Printf("<p>Last polling sleep time (us): %f", modules[masterBoardIdx].pollSleepTime * 1e6);
|
||||
hStream.Printf("</body></html>");
|
||||
hStream.WriteReplyHeader(True);
|
||||
return True;
|
||||
}
|
||||
|
||||
OBJECTLOADREGISTER(ATCAadcDrv,"$Id: ATCAadcDrv.cpp,v 1.48 2010/02/09 14:50:59 ppcc_dev Exp $")
|
||||
Reference in New Issue
Block a user