-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathADCUnpacker.cpp
More file actions
168 lines (138 loc) · 4.49 KB
/
ADCUnpacker.cpp
File metadata and controls
168 lines (138 loc) · 4.49 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
/*ADCUnpacker.cpp
*Class to parse through data coming from ADC
*Most of the program's structure borrowed from
*http://docs.nscl.msu.edu/daq/newsite/nscldaq-11.2/x5013.html
*Ken H. & Gordon M.
*Oct 2018
*
*This particular version is designed to work with SPSevt2root and uses 16-bit integer pointers
*to traverse, instead of the spectcl 32-bit translator pointers. Possible area for improvement?
*Gordon M. Feb 2019
*
*Updated to better handle errors and work with a more general version of evt2root
*Gordon M. April 2019
*
*NOTE: This version is specifically designed to unpack data that come in reverse!!
*/
#include "ADCUnpacker.h"
#include <string>
#include <iostream>
using namespace std;
//This is where most chagnes need to be made for each module; most else is just name changes
//useful masks and shifts for ADC:
static const uint16_t TYPE_MASK (0x0700);
static const uint16_t TYPE_HDR (0x0200);
static const uint16_t TYPE_DATA (0x0000);
static const uint16_t TYPE_TRAIL (0x0400);
static const unsigned GEO_SHIFT (11);
static const uint16_t GEO_MASK (0xf800);
//header-specific:
static const unsigned HDR_COUNT_SHIFT (8);
static const uint16_t HDR_COUNT_MASK (0x3f00);
static const unsigned HDR_CRATE_SHIFT (16);
static const uint16_t HDR_CRATE_MASK (0x00ff);
//data-specific:
static const unsigned DATA_CHANSHIFT (0);
static const uint16_t DATA_CHANMASK (0x001f);
static const uint16_t DATA_CONVMASK (0x3fff);
pair< uint16_t*, ParsedADCEvent> ADCUnpacker::parse( uint16_t* begin, uint16_t* end,
vector<int> geos) {
ParsedADCEvent event;
int bad_flag = 0;
int geo_flag = 0;
auto iter = begin;
unpackHeader(iter, event);
if (iter>end) {
bad_flag = 1;
}
iter+=2;
int nWords = event.s_count*2;
auto dataEnd = iter + nWords;
for(unsigned int i=0; i<geos.size(); i++) {
if(event.s_geo == geos[i]) {
geo_flag = 1;
break;
}
}
if (!geo_flag){//If unexpected geo, skip all data words; either bad event or bad stack
bad_flag = 1;
iter+=nWords;
//Error testing
//cout<<"Bad ADC geo: "<<event.s_geo<<endl;
} else {
iter = unpackData(iter, dataEnd, event);
}
if (iter>end || bad_flag || !isEOE(*(iter+1))){
//Error testing
//cout<<"ADCUnpacker::parse() ";
//cout<<"Unable to unpack event"<<endl;
}
iter+=2;
return make_pair(iter, event);
}
bool ADCUnpacker::isHeader(uint16_t word) {
return ((word&TYPE_MASK) == TYPE_HDR);
}
void ADCUnpacker::unpackHeader(uint16_t* word, ParsedADCEvent& event) {
//Error handling: if not valid header throw event to 0 at chan 0 at not real geo
try {
if (!isHeader(*(word+1))) {
string errmsg("ADCUnpacker::parseHeader() ");
errmsg += "Found non-header word when expecting header. ";
errmsg += "Word = ";
unsigned short w = *(word+1);
errmsg += to_string(w);
throw errmsg;
}
event.s_count = (*word&HDR_COUNT_MASK) >> HDR_COUNT_SHIFT;
++word;
event.s_geo = (*word&GEO_MASK)>>GEO_SHIFT;
event.s_crate = (*word&HDR_CRATE_MASK) >> HDR_CRATE_SHIFT;
} catch (string errmsg) {
event.s_count = 0;
event.s_geo = 99; //should NEVER match a valid geo
event.s_crate = 0;
uint16_t data = 0;
int channel = 0;
auto chanData = make_pair(channel, data);
event.s_data.push_back(chanData);
//cout<<errmsg<<endl; //only turn on during testing
}
}
bool ADCUnpacker::isData(uint16_t word) {
return ((word&TYPE_MASK) == TYPE_DATA);
}
void ADCUnpacker::unpackDatum(uint16_t* word, ParsedADCEvent& event) {
//Error testing
try {
if (!isData(*(word+1))) {
string errmsg("ADCUnpacker::unpackDatum() ");
errmsg += "Found non-data word when expecting data.";
throw errmsg;
}
uint16_t data = *word&DATA_CONVMASK;
++word;
int channel = (*word&DATA_CHANMASK) >> DATA_CHANSHIFT;
auto chanData = make_pair(channel, data);
event.s_data.push_back(chanData);
} catch(string errmsg) {
event.s_crate = 0;
uint16_t data = 0;
int channel = 0;
auto chanData = make_pair(channel, data);
event.s_data.push_back(chanData);
//cout<<errmsg<<endl; //only turn on during testing
}
}
uint16_t* ADCUnpacker::unpackData( uint16_t* begin,uint16_t* end, ParsedADCEvent& event) {
event.s_data.reserve(event.s_count); //memory allocation
auto iter = begin;
while (iter!=end) {
unpackDatum(iter, event);
iter = iter+2;
}
return iter;
}
bool ADCUnpacker::isEOE(uint16_t word) {
return ((word&TYPE_MASK) == TYPE_TRAIL);
}