Commit 2811a30b authored by legoc's avatar legoc
Browse files

Reviewed and generalised the structure of event to integrate new board

firmwares.
parent ffe3af9b
Version 1.1.0, 2016-?-?
-------------------------
- Integrated new boards
- New interface to access data
- Added columns to lstreader128
- Relative time is related to a board
Version 1.0.3, 2016-10-11
-------------------------
- Corrected missing jump when a bad event is read in EventArrayAlgorithm.
......@@ -5,10 +13,12 @@ Version 1.0.3, 2016-10-11
- Corrected using time base for calculating rates. Added the lstrates128 application.
- Corrected reading of the 1724 board (30bits of timestamp with 2 bits of zero)
Version 1.0.2, 2016-07-11
-------------------------
- Corrected boost dependencies.
Version 1.0.1, 2016-05-05
-------------------------
- Minor corrections.
......
......@@ -2,7 +2,7 @@
# This configure.ac script is free software; the Free Software Foundation
# gives unlimited permission to copy, distribute and modify it.
AC_INIT([lstdataprocess128], [1.0.3])
AC_INIT([lstdataprocess128], [1.1.0])
LIBRARY_VERSION=1:0:3
......
......@@ -7,6 +7,7 @@ nobase_include_HEADERS = \
lstdpp128/Reader.h \
lstdpp128/EventBlockArray.h \
lstdpp128/Event.h \
lstdpp128/EventData.h \
lstdpp128/BaseReader.h \
lstdpp128/EventArray.h \
lstdpp128/LiveReader.h \
......
......@@ -95,7 +95,7 @@ void Check::processBadEvent(Event const & event) {
void Check::processEvent(Event const & event) {
_numberOfGoodEvents++;
if (event.crate == 0 && event.channel == 0 && event.energy == 0) {
if (event.crate == 0 && event.channel == 0 && event.data[0] == 0 && event.data[1] == 0) {
if (_onZeroBlock) {
_zeroCounter++;
} else {
......
......@@ -37,13 +37,12 @@ std::ostream& operator<< (std::ostream& os, ListModeContext const & header) {
os << "#crates = " << header.crateBoard.nbCrates << endl << endl;
for (int c = 0; c < header.crateBoard.nbCrates; c++) {
os << "crate " << c << endl;
os << "\t#boards = " << header.crateBoard.crates[c].nbBoards << endl;
os << "crate " << c << " #boards = " << header.crateBoard.crates[c].nbBoards << endl << endl;
for (int b = 0; b < header.crateBoard.crates[c].nbBoards; b++) {
os << "\t" << "board " << b << endl;
os << "\ttype = " << (int)header.crateBoard.crates[c].boards[b].boardType << endl;
os << "\ttype name = " << BoardTypeName[header.crateBoard.crates[c].boards[b].boardType] << endl;
os << "\tevent type = " << header.crateBoard.crates[c].boards[b].eventType << endl;
os << "\tdata resolution = " << BoardDataResolution[header.crateBoard.crates[c].boards[b].boardType] << " bits" << endl;
os << "\ttime resolution = " << BoardTimeResolution[header.crateBoard.crates[c].boards[b].boardType] << " nanoseconds" << endl;
os << "\t#channels = " << header.crateBoard.crates[c].boards[b].nbChannels << endl << endl;
}
......
......@@ -35,27 +35,126 @@ static const int EVENT_SIZE_32 = 4;
*/
static const int EVENT_SIZE_8 = 16;
/**
* List of different available boards.
*/
enum BoardType {
CFD_BOARD_TYPE = 0, V1751_BOARD_TYPE = 1, V1724_BOARD_TYPE = 2, V1730_BOARD_TYPE = 3
CFD = 0,
C1751_PSD = 1,
C1724_PHA_RT = 2,
C1730_PSD_RT = 3,
C1730_PHA_RT = 4,
C1740_QDC = 5,
C1740_QDIV = 6,
GGPICKUP = 20,
MCC = 21,
CAMERA = 22,
C1751_WAVEFORM = 31,
C1724_WAVEFORM_RT = 32,
C1730_WAVEFORM_RT = 33,
C1740_WAVEFORM = 35,
C1740_QDIV_WAVEFORM = 36
};
/**
* The name of the boards.
*/
static const char* BoardTypeName[] = { "CFD", "V1751", "V1724", "V1730" };
static const char* BoardTypeName[] = {
"CFD", // 0
"1751 PSD", // 1
"1724 PHA RT", // 2
"1730 PSD RT", // 3
"1730 PHA RT", // 4
"1740 QDC", // 5
"1740 QDIV", // 6
// 7 ... 19
"7?", "8?", "9?", "10?", "11?", "12?", "13?", "14?", "15?", "16?", "17?", "18?", "19?",
"GGPICKUP", // 20
"MCC", // 21
"CAMERA", // 22
// 23 ... 30
"23?", "24?", "25?", "26?", "27?", "28?", "29?", "30?",
"1751 WAVEFORM", // 31
"1724 WAVEFORM RT", // 32
"1730 WAVEFORM RT", // 33
"34?", // 34
"1740 WAVEFORM", // 35
"1740 QDIV WAVEFORM" // 36
};
/**
* The data resolution of the boards (number of bits).
* The time relativity of the boards.
*/
static uint32_t BoardDataResolution[] = { 12, 10, 15, 15 };
static int BoardRelativeTime[] = {
0, // 0
0, // 1
1, // 2
1, // 3
1, // 4
0, // 5
0, // 6
// 7.. 19
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, // 20
0, // 21
0, // 22
// 23.. 30
0, 0, 0, 0, 0, 0, 0, 0,
0, // 31
1, // 32
1, // 33
0, // 34
0, // 35
0 // 36
};
/**
* The time resolution of the boards (nanoseconds).
*/
static uint32_t BoardTimeResolution[] = { 1, 1, 10, 2 };
static uint32_t BoardTimeResolution[] = {
1, // 0
1, // 1
10, // 2
2, // 3
2, // 4
16, // 5
16, // 6
// 7.. 19
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
10, // 20
10, // 21
0, // 22
// 23.. 30
0, 0, 0, 0, 0, 0, 0, 0,
1, // 31
10, // 32
2, // 33
0, // 34
16, // 35
16 // 36
};
/**
* The board structure. A board belongs to a unique crate.
......@@ -66,7 +165,7 @@ struct Board {
uint16_t nbChannels;
BoardType boardType;
Board() : eventType(0), crate(0), nbChannels(0), boardType(CFD_BOARD_TYPE) {}
Board() : eventType(0), crate(0), nbChannels(0), boardType(CFD) {}
};
/**
......
......@@ -37,9 +37,32 @@ void Event::setTime(time_type value) {
rollover = ((value >> 32) & 0xFFFF);
}
std::string eventColumnsToString(BoardType type) {
ostringstream os;
os << setw(10) << (int)type
<< setw(10) << "time"
<< setw(8) << "roll."
<< setw(12) << "timestamp"
<< setw(8) << "crate"
<< setw(8) << "board"
<< setw(8) << "channel"
<< setw(11) << "board type";
return os.str();
}
std::ostream& operator<< (std::ostream& os, Event const & e) {
return os << dec << setw(20) << e.time() << setw(12) << e.energy << setw(8) << (int)e.crate << ", " << (int)e.board << setw(8) << e.channel
<< setw(8) << e.data << setw(20) << e.rollover << setw(20) << e.timestamp;
return os << dec
<< setw(20) << e.time()
<< setw(8) << e.rollover
<< setw(12) << e.timestamp
<< setw(8) << (int)e.crate
<< setw(8) << (int)e.board
<< setw(8) << e.channel
<< setw(11) << (int)e.boardType();
}
std::string printBinary(int32_t * buffer) {
......@@ -88,16 +111,17 @@ std::ostream& operator<< (std::ostream& os, EventBlock const & b) {
bool readEvent(Event & event, int32_t * buffer) {
// Read crate, board, channel.
uint8_t crate = (uint8_t)((*buffer >> 28) & 0xF);
uint8_t board = (uint8_t)((*buffer >> 22) & 0x3F);
if (crate >= listModeContext.crateBoard.nbCrates) {
// No output because the log file can be very large
// No output because the log file can be very large.
return false;
}
if (board >= listModeContext.crateBoard.crates[event.crate].nbBoards) {
// No output because the log file can be very large
// No output because the log file can be very large.
return false;
}
......@@ -108,43 +132,28 @@ bool readEvent(Event & event, int32_t * buffer) {
BoardType boardType = event.boardType();
// The number of bits for timestamp.
int numberOfBitsOfTimestamp = 32;
if (boardType == CFD_BOARD_TYPE) {
event.timestamp = (uint32_t)(*(buffer + 1) & 0xFFFFFFFF);
event.energy = (uint16_t)(*(buffer + 2) & 0xFFF);
// Extra data if zero crossing
int32_t temp = (*(buffer + 3) & 0xFFFFFFFF);
memcpy(reinterpret_cast<void *>(&event.data), reinterpret_cast<const void *>(&temp), 4);
} else if (boardType == V1751_BOARD_TYPE) {
event.timestamp = (uint32_t)(*(buffer + 1) & 0xFFFFFFFF);
event.energy = (uint16_t)((*(buffer + 2) >> 16) & 0x7FFF);
// Extra data
event.data = (uint16_t)((*(buffer + 2)) & 0x7FFF);
} else if (boardType == V1724_BOARD_TYPE) {
// The timestamp is on 30bits
// In case of 1724 PHA, the number of bits for timestamp is 30.
if (boardType == C1724_PHA_RT) {
numberOfBitsOfTimestamp = 30;
event.timestamp = (uint32_t)(*(buffer + 1) & 0x3FFFFFFF);
event.energy = (uint16_t)(*(buffer + 2) & 0x7FFF);
} else if (boardType == V1730_BOARD_TYPE) {
}
else {
event.timestamp = (uint32_t)(*(buffer + 1) & 0xFFFFFFFF);
event.energy = (uint16_t)(*(buffer + 2) & 0x7FFF);
}
// Copy data.
memcpy(reinterpret_cast<void *>(event.data), reinterpret_cast<const void *>(buffer + 2), 8);
// Use printBinary(buffer) to debug if necessary.
// Calculate the absolute time.
time_type absoluteTime = (((int64_t)event.rollover << numberOfBitsOfTimestamp) | event.timestamp);
// In version == 1, the event time in the file is relative so that the time resolution is used to convert to absolute time.
// In version >= 2, the event time in the file is already absolute.
if (listModeContext.version == 1) {
// Testing if we must apply the time resolution or not in case of a board that has relative time.
if (BoardRelativeTime[boardType]) {
// Set the absolute time. Here the event is still in relative time.
absoluteTime = absoluteTime * event.timeResolution();
......@@ -167,13 +176,13 @@ void writeEvent(Event const & event, int32_t * buffer) {
Event relativeTimeEvent(event);
// See comment on versions in readEvent.
if (listModeContext.version == 1) {
// Testing if we must apply the time resolution or not in case of a board that has relative time.
if (BoardRelativeTime[event.boardType()]) {
// We reset the event time to the relative time because we do not want to change the header of the lsto.
time_type relativeTime = event.time() / event.timeResolution();
// We can set the realtive time that changes the rollover and timestamp.
// We can set the relative time that changes the rollover and timestamp.
relativeTimeEvent.setTime(relativeTime);
}
......@@ -184,24 +193,7 @@ void writeEvent(Event const & event, int32_t * buffer) {
BoardType boardType = relativeTimeEvent.boardType();
if (boardType == CFD_BOARD_TYPE) {
*buffer |= (relativeTimeEvent.rollover & 0xFFFF);
*(buffer + 1) = relativeTimeEvent.timestamp;
*(buffer + 2) = (relativeTimeEvent.energy & 0xFFF);
memcpy(buffer + 3, reinterpret_cast<const void *>(&relativeTimeEvent.data), 4);
} else if (boardType == V1751_BOARD_TYPE) {
*buffer |= (relativeTimeEvent.rollover & 0xFFFF);
// There is one bit that is not used: first bit of data (the buffer written may be different from the buffer read).
*(buffer + 1) = relativeTimeEvent.timestamp;
*(buffer + 2) = ((relativeTimeEvent.energy << 16)) | (event.data & 0x7FFF);
*(buffer + 3) = 0;
} else if (boardType == V1724_BOARD_TYPE) {
if (boardType == C1724_PHA_RT) {
// The card timestamp is on 30bits with 2 bits of zero.
// The rollover is calculated by taking the 2 bits of the actual timestamp (>> 30 for 32 bits = 2 bits).
......@@ -210,18 +202,16 @@ void writeEvent(Event const & event, int32_t * buffer) {
// Taking the 30 bits and setting 0 to the 2 first bits.
*(buffer + 1) = (relativeTimeEvent.timestamp & 0x3FFFFFFF);
*(buffer + 2) = (relativeTimeEvent.energy & 0x7FFF);
*(buffer + 3) = 0;
} else if (boardType == V1730_BOARD_TYPE) {
}
else {
*buffer |= (relativeTimeEvent.rollover & 0xFFFF);
*(buffer + 1) = (relativeTimeEvent.timestamp & 0xFFFFFFFF);
*(buffer + 2) = (relativeTimeEvent.energy & 0x7FFF);
*(buffer + 3) = 0;
*(buffer + 1) = relativeTimeEvent.timestamp;
}
// Copy data.
memcpy(buffer + 2, reinterpret_cast<const void *>(&relativeTimeEvent.data), 8);
// Use printBinary(buffer) to debug if necessary.
}
......
......@@ -36,8 +36,7 @@ struct Event {
uint16_t channel;
uint16_t rollover;
uint32_t timestamp;
uint16_t energy;
uint32_t data;
uint32_t data[2];
enum CleanType {CLEAN, NOT_CLEAN, ANTI_COMPTON, UNDEFINED};
CleanType status;
......@@ -48,9 +47,10 @@ struct Event {
channel(0),
rollover(0),
timestamp(0),
energy(0),
data(0),
status(UNDEFINED) {}
status(UNDEFINED) {
data[0] = 0;
data[1] = 0;
}
/**
* Returns the board type of the event in the current list mode context.
......@@ -75,53 +75,8 @@ struct Event {
* Sets the absolute time. The value is converted into rollover and timestamp.
*/
void setTime(time_type value);
/**
* Function provided for convenience to get the data as an int32 value.
*/
inline int32_t int32Data() const {
return *reinterpret_cast<const int32_t *>(&data);
}
/**
* Function provided for convenience to get the data as a float value.
*/
inline float floatData() const {
return *reinterpret_cast<const float *>(&data);
}
};
/**
* This function is only for CFD_BOARD_TYPE events.
*/
inline float zeroCrossing(Event const &event) {
return event.floatData();
}
/**
* This function is only for V1751_BOARD_TYPE events.
*/
inline uint16_t qLong(Event const & event) {
return event.energy;
}
/**
* This function is only for V1751_BOARD_TYPE events.
*/
inline uint16_t qShort(Event const & event) {
return event.data;
}
/**
* This function is only for V1751_BOARD_TYPE events.
*/
inline float qRatio(Event const & event) {
if (qLong(event) == 0) {
return 0.0;
}
return (float)(qLong(event) - qShort(event)) / (float)qLong(event);
}
/**
* Comparator to sort events with time.
*/
......@@ -132,6 +87,7 @@ struct CompareEvents {
}
};
std::string eventColumnsToString(BoardType type);
std::ostream& operator<< (std::ostream& os, Event const & e);
std::string printBinary(int32_t * buffer);
......
......@@ -173,39 +173,39 @@ EventBlockArrayIterator EventBlockArray::insertEvent(Event const & event) {
return EventBlockArrayIterator(array(), array().begin(), e);
}
void testIterator(EventBlockArray const & EventBlocks) {
EventBlockArrayIterator e = EventBlocks.begin();
while (e != EventBlocks.end()) {
cout << "event " << *e << endl;
++e;
--e;
++e;
}
while (e != EventBlocks.begin()) {
--e;
cout << "event " << *e << endl;
}
}
void testSplitBlocks(EventBlockArray const & EventBlocks) {
EventBlocks.array().front()->split();
}
void printBlocks(EventBlockArray const & EventBlocks, bool printEvents) {
for (EventBlockArray::array_type::const_iterator b = EventBlocks.array().begin(); b != EventBlocks.array().end(); ++b) {
cout << "block " << *(*b) << endl;
if (printEvents) {
for (multiset<Event, CompareEvents>::const_iterator e = (*b)->events.begin(); e != (*b)->events.end(); ++e) {
cout << " event " << *e << endl;
}
}
}
}
//void testIterator(EventBlockArray const & EventBlocks) {
//
// EventBlockArrayIterator e = EventBlocks.begin();
//
// while (e != EventBlocks.end()) {
// cout << "event " << *e << endl;
// ++e;
// --e;
// ++e;
// }
//
// while (e != EventBlocks.begin()) {
// --e;
// cout << "event " << *e << endl;
// }
//}
//
//void testSplitBlocks(EventBlockArray const & EventBlocks) {
//
// EventBlocks.array().front()->split();
//}
//
//void printBlocks(EventBlockArray const & EventBlocks, bool printEvents) {
//
// for (EventBlockArray::array_type::const_iterator b = EventBlocks.array().begin(); b != EventBlocks.array().end(); ++b) {
// cout << "block " << *(*b) << endl;
// if (printEvents) {
// for (multiset<Event, CompareEvents>::const_iterator e = (*b)->events.begin(); e != (*b)->events.end(); ++e) {
// cout << " event " << *e << endl;
// }
// }
// }
//}
void checkEvents(EventBlockArray const & EventBlocks) {
......
......@@ -149,9 +149,9 @@ private:
std::multiset<Event, CompareEvents>::iterator _e;
};
void testIterator(EventBlockArray const & EventBlocks);
void testSplitBlocks(EventBlockArray const & EventBlocks);
void printBlocks(EventBlockArray const & EventBlocks, bool printEvents);
//void testIterator(EventBlockArray const & EventBlocks);
//void testSplitBlocks(EventBlockArray const & EventBlocks);
//void printBlocks(EventBlockArray const & EventBlocks, bool printEvents);
void checkEvents(EventBlockArray const & EventBlocks);
}
......
/*
* Nomad Instrument Control Software
*
* Copyright 2011 Institut Laue-Langevin
*
* Licensed under the EUPL, Version 1.1 only (the "License");
* You may not use this work except in compliance with the Licence.
* You may obtain a copy of the Licence at:
*
* http://www.osor.eu/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 "EventData.h"
#include <iomanip>
using namespace std;
namespace lstdpp128 {
inline float floatData(Event const & event, int index) {
return *reinterpret_cast<const float *>(&event.data[index]);
}
uint32_t eventData(Event const & event) {
return event.data[0];
}
uint32_t eventDataPlus(Event const & event) {
return event.data[1];
}
///////////////////////////////////////////////////////////////////////////////
// Energy
bool boardHasEnergy(BoardType type) {
if (type == CFD
|| type == C1724_PHA_RT
|| type == C1730_PHA_RT
|| type == C1740_QDC) {
return true;
}
return false;
}
bool eventHasEnergy(Event const & event) {
return boardHasEnergy(event.boardType());
}
uint16_t boardEnergyResolution(BoardType type) {