Skip to content

Commit 7bce9a0

Browse files
committed
Added multithreaded readout
1 parent 22a36be commit 7bce9a0

8 files changed

Lines changed: 261 additions & 79 deletions

File tree

DAQController.cc

Lines changed: 52 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
// 3-running
88
// 4-error
99

10-
DAQController::DAQController(MongoLog *log){
10+
DAQController::DAQController(MongoLog *log, std::string hostname){
1111
fLog=log;
1212
fHelper = new DAXHelpers();
1313
fOptions = NULL;
@@ -18,6 +18,7 @@ DAQController::DAQController(MongoLog *log){
1818
fRunStartController = NULL;
1919
fRawDataBuffer = NULL;
2020
fDatasize=0.;
21+
fHostname = hostname;
2122
}
2223

2324
DAQController::~DAQController(){
@@ -39,7 +40,7 @@ std::string DAQController::run_mode(){
3940
}
4041
}
4142

42-
int DAQController::InitializeElectronics(std::string opts, std::string override){
43+
int DAQController::InitializeElectronics(std::string opts, std::vector<int>&keys, std::string override){
4344

4445
// Load options including override if any
4546
if(fOptions != NULL)
@@ -51,14 +52,18 @@ int DAQController::InitializeElectronics(std::string opts, std::string override)
5152

5253
// Initialize digitizers
5354
fStatus = 1;
54-
for(auto d : fOptions->GetBoards("V1724")){
55+
for(auto d : fOptions->GetBoards("V1724", fHostname)){
5556

5657
V1724 *digi = new V1724(fLog);
57-
if(digi->Init(d.link, d.crate, d.board, d.vme_address)==0){
58-
fDigitizers.push_back(digi);
59-
std::stringstream mess;
60-
mess<<"Initialized digitizer "<<d.board;
61-
fLog->Entry(mess.str(), MongoLog::Debug);
58+
if(digi->Init(d.link, d.crate, d.board, d.vme_address)==0){
59+
fDigitizers[d.link].push_back(digi);
60+
if(std::find(keys.begin(), keys.end(), d.link) == keys.end()){
61+
std::cout<<"Defining new optical link "<<d.link<<std::endl;
62+
keys.push_back(d.link);
63+
}
64+
std::stringstream mess;
65+
mess<<"Initialized digitizer "<<d.board;
66+
fLog->Entry(mess.str(), MongoLog::Debug);
6267
}
6368
else{
6469
std::stringstream err;
@@ -70,25 +75,30 @@ int DAQController::InitializeElectronics(std::string opts, std::string override)
7075
}
7176

7277
// Load registers into digitizers
73-
for(auto digi : fDigitizers){
74-
int success=0;
75-
for(auto regi : fOptions->GetRegisters(digi->bid())){
76-
unsigned int reg = fHelper->StringToHex(regi.reg);
77-
unsigned int val = fHelper->StringToHex(regi.val);
78-
success+=digi->WriteRegister(reg, val);
79-
}
80-
if(success!=0){
81-
//LOG
82-
fStatus = 0;
78+
for( auto const& link : fDigitizers ) {
79+
for(auto digi : link.second){
80+
int success=0;
81+
for(auto regi : fOptions->GetRegisters(digi->bid())){
82+
unsigned int reg = fHelper->StringToHex(regi.reg);
83+
unsigned int val = fHelper->StringToHex(regi.val);
84+
success+=digi->WriteRegister(reg, val);
85+
}
86+
if(success!=0){
87+
//LOG
88+
fStatus = 0;
8389
fLog->Entry("Failed to write registers.", MongoLog::Warning);
8490
return -1;
91+
}
8592
}
8693
}
8794

8895
// Look at this later! This initializes all boards to SW controlled
8996
// and inactive. Will need option for HW control.
90-
for(unsigned int x=0;x<fDigitizers.size();x++)
91-
fDigitizers[x]->WriteRegister(0x8100, 0x0);
97+
for( auto const& link : fDigitizers ) {
98+
for(auto digi : link.second){
99+
digi->WriteRegister(0x8100, 0x0);
100+
}
101+
}
92102
fStatus = 2;
93103

94104
std::cout<<fOptions->ExportToString()<<std::endl;
@@ -97,8 +107,10 @@ int DAQController::InitializeElectronics(std::string opts, std::string override)
97107

98108
void DAQController::Start(){
99109
if(fRunStartController==NULL){
100-
for(unsigned int x=0;x<fDigitizers.size(); x++){
101-
fDigitizers[x]->WriteRegister(0x8100, 0x4);
110+
for( auto const& link : fDigitizers ){
111+
for(auto digi : link.second){
112+
digi->WriteRegister(0x8100, 0x4);
113+
}
102114
}
103115
}
104116
fStatus = 3;
@@ -108,8 +120,11 @@ void DAQController::Start(){
108120
void DAQController::Stop(){
109121

110122
if(fRunStartController==NULL){
111-
for(unsigned int x=0;x<fDigitizers.size();x++)
112-
fDigitizers[x]->WriteRegister(0x8100, 0x0);
123+
for( auto const& link : fDigitizers ){
124+
for(auto digi : link.second){
125+
digi->WriteRegister(0x8100, 0x0);
126+
}
127+
}
113128
}
114129
fLog->Entry("Stopped digitizers", MongoLog::Debug);
115130

@@ -119,10 +134,12 @@ void DAQController::Stop(){
119134
}
120135
void DAQController::End(){
121136
CloseProcessingThreads();
122-
for(unsigned int x=0; x<fDigitizers.size(); x++){
123-
fDigitizers[x]->End();
124-
delete fDigitizers[x];
125-
}
137+
for( auto const& link : fDigitizers ){
138+
for(auto digi : link.second){
139+
digi->End();
140+
delete digi;
141+
}
142+
}
126143
fDigitizers.clear();
127144
fStatus = 0;
128145

@@ -140,13 +157,13 @@ void DAQController::End(){
140157
}
141158
}
142159

143-
void* DAQController::ReadThreadWrapper(void* data){
160+
void* DAQController::ReadThreadWrapper(void* data, int link){
144161
DAQController *dc = static_cast<DAQController*>(data);
145-
dc->ReadData();
162+
dc->ReadData(link);
146163
return dc;
147164
}
148165

149-
void DAQController::ReadData(){
166+
void DAQController::ReadData(int link){
150167
fReadLoop = true;
151168
CloseProcessingThreads();
152169
OpenProcessingThreads();
@@ -170,12 +187,12 @@ void DAQController::ReadData(){
170187
//lastRead = 0;
171188

172189
vector<data_packet> local_buffer;
173-
for(unsigned int x=0; x<fDigitizers.size(); x++){
190+
for(unsigned int x=0; x<fDigitizers[link].size(); x++){
174191
data_packet d;
175192
d.buff=NULL;
176193
d.size=0;
177-
d.bid = fDigitizers[x]->bid();
178-
d.size = fDigitizers[x]->ReadMBLT(d.buff);
194+
d.bid = fDigitizers[link][x]->bid();
195+
d.size = fDigitizers[link][x]->ReadMBLT(d.buff);
179196

180197
// Here's the fancy part. We gotta grab the header of the first
181198
// event in the buffer and get the clock reset counter from the
@@ -184,7 +201,7 @@ void DAQController::ReadData(){
184201
while(idx < d.size/sizeof(u_int32_t)){
185202
if(d.buff[idx]>>20==0xA00){
186203
d.header_time = d.buff[idx+3]&0x7FFFFFFF;
187-
d.clock_counter = fDigitizers[x]->GetClockCounter(d.header_time);
204+
d.clock_counter = fDigitizers[link][x]->GetClockCounter(d.header_time);
188205
break;
189206
}
190207
idx++;

DAQController.hh

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,11 @@ class DAQController{
2222
*/
2323

2424
public:
25-
DAQController(MongoLog *log=NULL);
25+
DAQController(MongoLog *log=NULL, std::string hostname="DEFAULT");
2626
~DAQController();
2727

28-
int InitializeElectronics(std::string opts, std::string override = "");
28+
int InitializeElectronics(std::string opts, std::vector<int> &keys,
29+
std::string override = "");
2930

3031
// Get data (return new buffer and size)
3132
double data_rate(){
@@ -41,13 +42,13 @@ public:
4142

4243
void Start();
4344
void Stop();
44-
void ReadData();
45+
void ReadData(int link);
4546
void End();
4647

4748
int GetData(std::vector <data_packet> *&retVec);
4849

4950
// Statis wrapper so we can call ReadData in a std::thread
50-
static void* ReadThreadWrapper(void* data);
51+
static void* ReadThreadWrapper(void* data, int link);
5152
static void* ProcessingThreadWrapper(void* data);
5253

5354
u_int64_t GetDataSize(){ u_int64_t ds = fDatasize; fDatasize=0; return ds;};
@@ -61,7 +62,7 @@ private:
6162
void OpenProcessingThreads();
6263
void CloseProcessingThreads();
6364

64-
std::vector <V1724*> fDigitizers;
65+
std::map<int, std::vector <V1724*>> fDigitizers;
6566
std::mutex fBufferMutex;
6667
MongoLog *fLog;
6768

@@ -73,6 +74,7 @@ private:
7374
int fNProcessingThreads;
7475
u_int64_t fBufferLength;
7576
u_int64_t fDatasize;
77+
string fHostname;
7678

7779
V2718 *fRunStartController;
7880

Options.cc

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,13 +133,20 @@ std::string Options::GetString(std::string path, std::string default_value){
133133
return "";
134134
}
135135

136-
std::vector<BoardType> Options::GetBoards(std::string type){
136+
std::vector<BoardType> Options::GetBoards(std::string type, std::string hostname){
137137
std::vector<BoardType> ret;
138138
bsoncxx::array::view subarr = bson_options["boards"].get_array().value;
139139

140140
for(bsoncxx::array::element ele : subarr){
141141
if(type != "" && type != ele["type"].get_utf8().value.to_string())
142142
continue;
143+
try{
144+
if(ele["host"].get_utf8().value.to_string() != hostname)
145+
continue;
146+
}
147+
catch(const std::exception &e){
148+
// If there is no host field then no biggie. Assume we have just 1 host.
149+
};
143150
BoardType bt;
144151
bt.link = ele["link"].get_int32();
145152
bt.crate = ele["crate"].get_int32();

Options.hh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ public:
4343
int GetInt(std::string key, int default_value=-1);
4444
std::string GetString(std::string key, std::string default_value="");
4545

46-
std::vector<BoardType> GetBoards(std::string type="");
46+
std::vector<BoardType> GetBoards(std::string type="", std::string hostname="DEFAULT");
4747
std::vector<RegisterType> GetRegisters(int board=-1);
4848

4949
std::string ExportToString();

V1724.cc

Lines changed: 105 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,10 @@ V1724::~V1724(){
1010
}
1111

1212
int V1724::Init(int link, int crate, int bid, unsigned int address=0){
13-
if(CAENVME_Init(cvV2718, link, crate, &fBoardHandle)
14-
!= cvSuccess){
15-
cout<<"Failed to init board"<<endl;
13+
int a = CAENVME_Init(cvV2718, link, crate, &fBoardHandle);
14+
if(a != cvSuccess){
15+
cout<<"Failed to init board, error code: "<<a<<", handle: "<<fBoardHandle<<
16+
" at link "<<link<<" and bdnum "<<crate<<endl;
1617
fBoardHandle = -1;
1718
return -1;
1819
}
@@ -97,7 +98,7 @@ int V1724::GetClockCounter(u_int32_t timestamp){
9798
}
9899

99100
int V1724::WriteRegister(unsigned int reg, unsigned int value){
100-
std::cout<<"Writing reg:val: "<<hex<<reg<<":"<<value<<dec<<std::endl;
101+
//std::cout<<"Writing reg:val: "<<hex<<reg<<":"<<value<<dec<<std::endl;
101102
if(CAENVME_WriteCycle(fBoardHandle,fBaseAddress+reg,
102103
&value,cvA32_U_DATA,cvD32) != cvSuccess){
103104
std::stringstream err;
@@ -178,6 +179,106 @@ int V1724::ConfigureBaselines(int nominal_value,
178179
int ntries,
179180
vector <unsigned int> start_values,
180181
vector <unsigned int> &end_values){
182+
183+
// Baseline configuration routine. The V1724 has a DAC offset setting that
184+
// biases the ADC, allowing you to effectively move the 'zero level' of the
185+
// acquisition up or down. But keep in mind this is a bit limited. It's not
186+
// designed to correct large offsets O(~volts) (i.e. your detector ground very far
187+
// from ADC ground) but rather to move the baseline to the location best
188+
// suited to your acquisition (positive, negative, bipolar logic)
189+
190+
// n.b. hard-coding guess to 16000 for testing
191+
u_int32_t target_value = 16000;
192+
int max_deviation = 5;
193+
194+
// We can adjust a DAC offset register, which is 0xffff in range, is inversely
195+
// proportional to the baseline position, and has ~5% overshoot on either end.
196+
// So we use this information to get starting values:
197+
u_int32_t starting_value = u_int32_t( (0x3fff-target_value)*((0.9*0xffff)/0x3fff)) + 3277;
198+
int nChannels = 8;
199+
vector<u_int32_t> dac_values(nChannels, starting_value);
200+
vector<bool> channel_finished(nChannels, false);
201+
202+
// Now we need to load a simple configuration to the board in order to read
203+
// some data. try/catch cause CAENVMElib fails poorly (segfault) sometimes
204+
// in case the hardware has an issue.
205+
write_success = 0;
206+
try{
207+
write_success += WriteRegister(0x8000, 0x10); // Channel configuration
208+
write_success += WriteRegister(0x8080, 0x800000); // DPP
209+
write_success += WriteRegister(0x8100, 0x0); // Acq. control
210+
write_success += WriteRegister(0x810C, 0x80000000);// Trigger source
211+
write_success += WriteRegister(0xEF24, 0x1); // Global reset
212+
write_success += WriteRegister(0xEF1C, 0x1); // BERR
213+
write_success += WriteRegister(0xEF00, 0x10); // Channel memory
214+
write_success += WriteRegister(0x8120, 0xFF); // Channel mask
215+
}
216+
catch(const std::exception &e){
217+
std::stringstream error;
218+
error<<"Digitizer "<<fBID<<" CAEN fault during initial register adjustment in baseline routine";
219+
fLog->Entry(error.str(), MongoLog::Error);
220+
return -1;
221+
}
222+
223+
// Slightly more palatable error, at least CAENVMElib is recognizing a failure
224+
// and not just seg faulting
225+
if(write_success!=0){
226+
std::stringstream error;
227+
error<<"Digitizer "<<fBID<<" unable to load registers for baselines.";
228+
fLog->Entry(error.str(), MongoLog::Error);
229+
return -1;
230+
}
231+
232+
// Now we'll iterate for a while. It should be pretty quick since starting values
233+
// should be quite close to true.
234+
int currentIteration = 0;
235+
int maxIterations = 100;
236+
while(currentIteration < maxIterations){
237+
currentIteration++;
238+
bool breakout = true;
239+
240+
for(unsigned int channel=0; channel<nChannels; channel++){
241+
if(channel_finished[channel])
242+
continue;
243+
breakout = false;
244+
245+
// Load DAC for this channel
246+
if(LoadDAC(channel, dac_values[channel])!=0){
247+
std::stringstream error;
248+
error<<"Digitizer "<<fBID<<" channel "<<channel<<" failed to load DAC in baseline routine.";
249+
fLog->Entry(error.str(), MongoLog::Error);
250+
return -1;
251+
}
252+
253+
// Tell board to read out this channel only
254+
unsigned short channel_mask = 1 << channel;
255+
if(WriteRegister(0x8120, channel_mask)!=0){
256+
stringstream error;
257+
error<<"Digitizer "<<fBID<<" channel "<<channel<<" failed to set channel mask in baseline.";
258+
fLog->Entry(error.str(), MongoLog::Error);
259+
return -1;
260+
}
261+
262+
// Trigger the board with software trigger
263+
WriteRegister(CBV1724_AcquisitionControlReg,0x24);
264+
WriteRegister(CBV1724_SoftwareTriggerReg,0x1);
265+
usleep(50); // paranoia. Like, you need some time to acquire right?
266+
WriteRegister(CBV1724_AcquisitionControlReg,0x0);
267+
268+
269+
// Sample Samples
270+
// Good? then finish
271+
// Else twiddle DAC offset
272+
// Repeat
273+
}
274+
275+
if(breakout)
276+
break;
277+
}
278+
279+
280+
// 0x1n88 channel n DAC busy 0b001 (1 - yes)
281+
// 0x1n98, 0x8098 DAC value 0xffff
181282
cout<<"Not implemented"<<endl;
182283
return 0;
183284
}

0 commit comments

Comments
 (0)