// Default is to limit data to this Cycle
if(dataInfo.beyondPeriod || (dataInfo.cyclePeriod == CyclePeriodAll)){
eventEnd = eventStop;
}
#if DEBUG_DATA
printf("\n");
printf("CycleInfoTable Entry: %d\n", pupeCycleNumber & 0x03);
hd64(ocycleInfoTable, 4 * 16);
printf("\n");
printf("CyclePeriod: %d Found: %d\n", dataInfo.cyclePeriod, p);
printf("EventStart: %x Time: %d TimingAddress: %x DataAddress: %x\n", eventStart.event, eventStart.time, eventStart.timingAddress, eventStart.dataAddress);
printf("EventEnd: %x Time: %d TimingAddress: %x DataAddress: %x\n", eventEnd.event, eventEnd.time, eventEnd.timingAddress, eventEnd.dataAddress);
printf("EventStop: %x Time: %d TimingAddress: %x DataAddress: %x\n", eventStop.event, eventStop.time, eventStop.timingAddress, eventStop.dataAddress);
#endif
// Offset by Start time
timingAddress = (eventStart.timingAddress + dataInfo.startTime) & FpgaCycleTimingTableMask;
#ifdef ZAP_TIME
if(dataInfo.startTime)
dataAddress = ocycleTimingTable[timingAddress] >> 32;
else
dataAddress = eventStart.dataAddress;
#else
if(dataInfo.startTime){
uint32_t dataAddressOffset;
// Validate startTime
if(dataInfo.startTime > (eventEnd.time - eventStart.time)){
err.set(ErrorParam, getName() + "Start time beyond cycle period's end time: " + (eventEnd.time - eventStart.time) + "ms");
olock.unlock();
return err;
}
// Get appoximate data position within an orbits data
if((ocycleTimingTable[timingAddress] >> 32) > eventStart.dataAddress){
dataAddressOffset = (ocycleTimingTable[timingAddress] >> 32) - eventStart.dataAddress;
}
else {
dataAddressOffset = (ocycleTimingTable[timingAddress] >> 32) + (SDRAM_DATA_TOP / 8) - eventStart.dataAddress;
}
// Round down to the nearest orbit start
if(numBunches)
dataAddress = eventStart.dataAddress + (numBunches * (dataAddressOffset / numBunches));
else
dataAddress = eventStart.dataAddress + dataAddressOffset;
}
else {
dataAddress = eventStart.dataAddress;
}
#endif
// Offset by orbit number
if(numBunches){
dataAddress = sdramAddressAdd(dataAddress, numBunches * dataInfo.orbitNumber);
if(dataAddress > eventStart.dataAddress){
orbitNumber = (dataAddress - eventStart.dataAddress) / numBunches;
}
else {
orbitNumber = (dataAddress + (SDRAM_DATA_TOP / 8) - eventStart.dataAddress) / numBunches;
}
}
else {
dataAddress = sdramAddressAdd(dataAddress, dataInfo.orbitNumber);
if(dataAddress > eventStart.dataAddress){
orbitNumber = (dataAddress - eventStart.dataAddress);
}
else {
orbitNumber = (dataAddress + (SDRAM_DATA_TOP / 8) - eventStart.dataAddress);
}
}
// Make sure data is within cycle period
numValues = sdramAddressRange(dataAddress, eventEnd.dataAddress);
if(numValues > maxNumValues){
err.set(ErrorDataNotAvailable, getName() + "CycleTable Error: Data beyond cycle period or the amount of data for a period exceeds a maximum cycle period");
#ifndef ZAP
printf("CycleInfoTable Entry: %d\n", pupeCycleNumber & 0x03);
hd64(ocycleInfoTable, 4 * 16);
printf("\n");
printf("EventStart: %x Time: %d TimingAddress: %x DataAddress: %x\n", eventStart.event, eventStart.time, eventStart.timingAddress, eventStart.dataAddress);
printf("EventEnd: %x Time: %d TimingAddress: %x DataAddress: %x\n", eventEnd.event, eventEnd.time, eventEnd.timingAddress, eventEnd.dataAddress);
printf("EventStop: %x Time: %d TimingAddress: %x DataAddress: %x\n", eventStop.event, eventStop.time, eventStop.timingAddress, eventStop.dataAddress);
printf("NumValues: %d %d:%x %d:%x\n", numValues, dataAddress, dataAddress, eventEnd.dataAddress, eventEnd.dataAddress);
printf("Range: %d %d\n", SDRAM_DATA_TOP, SDRAM_DATA_TOP - dataAddress + eventEnd.dataAddress);
#endif
olock.unlock();
return err;
}
// Perform data access functions depending on type
if(dataInfo.function == DataFunctionRaw){
if((dataInfo.bunchNumber == 0) && (dataInfo.numValues < numBunches)){
err.set(ErrorParam, getName() + "NumValues to small for request");
olock.unlock();
return err;
}
if(dataInfo.bunchNumber){
if(numBunches)
numValues /= numBunches;
}
// Set up return data size
if(numValues < dataInfo.numValues){
dataInfo.numValues = numValues;
}
data.dataValues.resize(dataInfo.numValues);
data.numValues = dataInfo.numValues;
if(dataInfo.bunchNumber)
data.numBunches = 1;
else
data.numBunches = numBunches;
data.numChannels = 1;
#if DEBUG_DATA
printf("Data: TimingAddress: %d Orbits: %d DataStart: %d DataEnd: %d NumValues: %d\n", timingAddress, dataInfo.orbitNumber, dataAddress, eventEnd.dataAddress, numValues);
printf("BunchNumber: %d NumBunches: %d\n", dataInfo.bunchNumber, numBunches);
printf("CycleTimingAddress: %u(%x) CycleTime: %u CycleDataAddress: %u(%x)\n", timingAddress, timingAddress, uint32_t(ocycleTimingTable[timingAddress] & 0xFFFFFFFF), dataAddress, dataAddress);
printf("CycleTimingTable:\n");
hd64(&ocycleTimingTable[timingAddress], 16);
#endif
#if DEBUG_DATA_TIME
t4 = getTime();
#endif
if(dataInfo.bunchNumber && numBunches){
ofpga[MEM_RAO] = (dataAddress % numBunches) + dataInfo.bunchNumber - 1;
ofpga[MEM_RAS] = numBunches;
dataAddress = dataAddress / numBunches;
}
else {
ofpga[MEM_RAO] = 0;
ofpga[MEM_RAS] = 1;
}
// Read the Data
err = fpgaCopyData(puChannel.pupeChan, dataAddress * 8, dataInfo.numValues, data);
}
else if(dataInfo.function == DataFunctionMean){
if(dataInfo.bunchNumber > 24){
err.set(ErrorParam, getName() + "Can only return average for up to bunch 24");
olock.unlock();
return err;
}
if(dataInfo.orbitNumber != 0){
err.set(ErrorNotImplemented, getName() + "Cannot offset by orbit");
olock.unlock();
return err;
}
if((dataInfo.bunchNumber == 0) && (dataInfo.numValues < numBunches)){
err.set(ErrorParam, getName() + "NumValues to small for request");
olock.unlock();
return err;
}
numValues = (eventEnd.timingAddress - timingAddress) & FpgaCycleTimingTableMask;
if(dataInfo.bunchNumber == 0)
numValues *= numBunches;
// Set up return data size
if(numValues < dataInfo.numValues){
dataInfo.numValues = numValues;
}
data.dataValues.resize(dataInfo.numValues);
data.numValues = dataInfo.numValues;
data.numChannels = 1;
if(dataInfo.bunchNumber == 0){
data.numBunches = numBunches;
err = fpgaGetAverageDataAll(puChannel.pupeChan, eventStart.time, timingAddress, numBunches, data.numValues, data);
}
else {
data.numBunches = 1;
err = fpgaGetAverageData(puChannel.pupeChan, eventStart.time, timingAddress, dataInfo.bunchNumber, data.numValues, data);
}
}
else if(dataInfo.function == DataFunctionMeanAll){
if(dataInfo.bunchNumber != 0){
err.set(ErrorParam, getName() + "Can only return average for all bunches");
olock.unlock();
return err;
}
if(dataInfo.orbitNumber != 0){
err.set(ErrorNotImplemented, getName() + "Cannot offset by orbit");
olock.unlock();
return err;
}
numValues = (eventEnd.timingAddress - timingAddress) & FpgaCycleTimingTableMask;
// Set up return data size
if(numValues < dataInfo.numValues){
dataInfo.numValues = numValues;
}
data.dataValues.resize(dataInfo.numValues);
data.numValues = dataInfo.numValues;
data.numBunches = 0;
data.numChannels = 1;
err = fpgaGetAverageData(puChannel.pupeChan, eventStart.time, timingAddress, 0, data.numValues, data);
}
else if(dataInfo.function == DataFunctionMean0){
if(dataInfo.bunchNumber != 0){
err.set(ErrorNotImplemented, getName() + "Can only return average for all bunches");
olock.unlock();
return err;
}
if(dataInfo.orbitNumber != 0){
err.set(ErrorNotImplemented, getName() + "Cannot offset by orbit");
olock.unlock();
return err;
}
numValues = (eventEnd.timingAddress - timingAddress) & FpgaCycleTimingTableMask;
// Set up return data size
if(numValues < dataInfo.numValues){
dataInfo.numValues = numValues;
}
data.dataValues.resize(dataInfo.numValues);
data.numValues = dataInfo.numValues;
data.numBunches = 1;
data.numChannels = 1;
ofpga[IMEM_REG] = brBase + BRAM_BUNCH_MEAN0;
fpgaReadData64(timingAddress * sizeof(uint64_t), data.dataValues.data(), dataInfo.numValues * sizeof(uint64_t));
dataAverage(eventStart.time, data);
}
else if(dataInfo.function == DataFunctionMean1){
if(dataInfo.orbitNumber != 0){
err.set(ErrorNotImplemented, getName() + "Cannot offset by orbit");
olock.unlock();
return err;
}
numValues = (eventEnd.timingAddress - timingAddress) & FpgaCycleTimingTableMask;
// Set up return data size
if(numValues < dataInfo.numValues){
dataInfo.numValues = numValues;
}
data.dataValues.resize(dataInfo.numValues);
data.numValues = dataInfo.numValues;
data.numBunches = 1;
data.numChannels = 1;
ofpga[IMEM_REG] = brBase + BRAM_BUNCH_MEAN1;
fpgaReadData64(timingAddress * sizeof(uint64_t), data.dataValues.data(), dataInfo.numValues * sizeof(uint64_t));
dataAverage(eventStart.time, data);
}
else {
err.set(ErrorNotImplemented, getName() + "Data function: " + dataInfo.function + " has not been implemented");
}
#if DEBUG_DATA_TIME
t5 = getTime();
#endif
#if DEBUG_DATA
printf("CycleDataTable: %x %d\n", dataAddress, data.dataValues.size());
if(data.dataValues.size() >= 16)
hd64(data.dataValues.data(), 16);
#endif
if(!err){
// Need to check the FPGA has not overwritten the data while we were reading it.
diff = (timingAddress - ofpga[regBase + TIME_TBLADDR]) & FpgaCycleTimingTableMask;
if(diff < minTimingDiff){
err.set(ErrorDataGone, getName() + "Data has already gone: Difference: " + diff + " StartTimingAddress: " + timingAddress + " PupeWriteTimingAddress: " + ofpga[regBase + TIME_TBLADDR]);
#if DEBUG_DATA_ERROR
printf("Data has already gone: Difference: %d StartTimingAddress: %x PupeWriteTimingAddress: %x\n", diff, timingAddress, ofpga[regBase + TIME_TBLADDR]);
printf("PupeCycle: %d PupeTime: %d PupeTimingAddress: %x\n", ofpga[regBase + CYCLE], ofpga[regBase + TIME], ofpga[regBase + TIME_TBLADDR]);
printf("GetData: CycleWanted: %u CurrentCycle: %u Diff: %d PupeCycle: %u CurrentPupeCycle: %u Period: %d\n", dataInfo.cycleNumber, ocycleNumber, diff,pupeCycleNumber, ofpga[regBase + CYCLE], dataInfo.cyclePeriod);
printEventList(events);
printf("CycleInfoTable Entry: %d\n", pupeCycleNumber & 0x03);
hd64(ocycleInfoTable, 4 * 16);
#endif
}
}
}
olock.unlock();
#if DEBUG_DATA_TIME
printf("GetData: Times: %f, %f, %f, %f, %f Total: %f\n", t2 - t1, t3 - t2, t4 - t3, t5 - t4, t5 - t4, t5 - t1);
#endif