00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "roc/UdpDevice.h"
00016
00017 #include <iostream>
00018 #include <fstream>
00019 #include <unistd.h>
00020
00021 #include "dabc/Manager.h"
00022 #include "dabc/Port.h"
00023
00024 #include "roc/defines_roc.h"
00025 #include "roc/defines_udp.h"
00026 #include "roc/Commands.h"
00027
00028 #include "roc/ReadoutModule.h"
00029 #include "roc/NxCalibrModule.h"
00030
00031
00032 const char* ReadoutModuleName = "RocReadout";
00033 const char* CalibrModuleName = "RocNxCalibr";
00034
00035
00036 roc::UdpControlSocket::UdpControlSocket(UdpDevice* dev, int fd) :
00037 dabc::SocketWorker(fd),
00038 fDev(dev),
00039 fUdpCmds(dabc::CommandsQueue::kindSubmit),
00040 fCtrlRuns(false),
00041 fControlSendSize(0),
00042 fPacketCounter(1),
00043 fSendLastOper()
00044 {
00045
00046 SetDoingInput(true);
00047
00048 SetLastSendTime();
00049 }
00050
00051
00052
00053 roc::UdpControlSocket::~UdpControlSocket()
00054 {
00055 fUdpCmds.Cleanup();
00056
00057 if (fDev) fDev->fCtrlCh = 0;
00058 fDev = 0;
00059 }
00060
00061
00062 void roc::UdpControlSocket::SetLastSendTime()
00063 {
00064 fSendLastOper.GetNow();
00065 }
00066
00067
00068
00069 void roc::UdpControlSocket::ProcessEvent(const dabc::EventId& evnt)
00070 {
00071 switch (evnt.GetCode()) {
00072
00073 case evntSendCtrl: {
00074 DOUT5(("Send requests of size %d tag %d", fControlSendSize, fControlSend.tag));
00075
00076 DoSendBuffer(&fControlSend, fControlSendSize);
00077 double tmout = fFastMode ? (fLoopCnt++ < 4 ? 0.01 : fLoopCnt*0.1) : 1.;
00078 fTotalTmoutSec -= tmout;
00079 SetLastSendTime();
00080 ActivateTimeout(tmout);
00081 break;
00082 }
00083
00084 case evntSocketRead: {
00085
00086
00087 SetDoingInput(true);
00088
00089 ssize_t len = DoRecvBuffer(&fControlRecv, sizeof(UdpMessageFull));
00090
00091
00092
00093 if (len<=0) return;
00094
00095 if (fCtrlRuns &&
00096 (fControlRecv.password == htonl(ROC_PASSWORD)) &&
00097 (fControlSend.id == fControlRecv.id) &&
00098 (fControlSend.tag == fControlRecv.tag)) {
00099 completeLoop(true, len);
00100 } else
00101 if (fDev)
00102 fDev->processCtrlMessage(&fControlRecv, len);
00103 break;
00104 }
00105
00106 case evntCheckCmd: {
00107 checkCommandsQueue();
00108 break;
00109 }
00110
00111 default:
00112 dabc::SocketWorker::ProcessEvent(evnt);
00113 break;
00114 }
00115 }
00116
00117
00118 void roc::UdpControlSocket::SendDisconnect()
00119 {
00120 fControlSend.tag = ROC_POKE;
00121 fControlSend.address = htonl(ROC_ETH_MASTER_LOGOUT);
00122 fControlSend.value = htonl(1);
00123 fControlSendSize = sizeof(UdpMessage);
00124
00125 DoSendBuffer(&fControlSend, fControlSendSize);
00126 }
00127
00128
00129
00130 double roc::UdpControlSocket::ProcessTimeout(double last_diff)
00131 {
00132 if (!fCtrlRuns) {
00133 if (fSendLastOper.Expired(2.))
00134 if (fUdpCmds.Size()==0) {
00135 Submit(CmdGet(ROC_ROCID, 1.));
00136
00137 }
00138
00139 return 1.;
00140 }
00141
00142 if (fTotalTmoutSec <= 0.) {
00143
00144 completeLoop(false);
00145 return 1.;
00146 }
00147
00148 if (fFastMode || (fTotalTmoutSec <=5.)) {
00149 FireEvent(evntSendCtrl);
00150 return 1.;
00151 }
00152
00153 fTotalTmoutSec -= 1.;
00154
00155 return 1.;
00156 }
00157
00158 void roc::UdpControlSocket::completeLoop(bool res, int)
00159 {
00160 bool finished = true;
00161 dabc::Command cmd = fUdpCmds.Front();
00162 if (cmd.null()) {
00163 EOUT(("Something wrong"));
00164 } else
00165 if (res) {
00166 if (cmd.IsName(CmdGet::CmdName())) {
00167 cmd.SetUInt(ValuePar, res ? ntohl(fControlRecv.value) : 0);
00168 cmd.SetUInt(ErrNoPar, res ? ntohl(fControlRecv.address) : roc::Board::kOperNetworkErr);
00169 } else
00170 if (cmd.IsName(CmdPut::CmdName()) ||
00171 cmd.IsName(roc::UdpDevice::CmdPutSuspendDaq()) ||
00172 cmd.IsName(roc::UdpDevice::CmdPutDisconnect()) ||
00173 cmd.IsName(CmdDLM::CmdName())) {
00174 unsigned errno = res ? ntohl(fControlRecv.value) : roc::Board::kOperNetworkErr;
00175 cmd.SetUInt(ErrNoPar, errno);
00176 if (cmd.GetBool("SwPut", false))
00177 fDev->completeSwPut(errno==0);
00178 } else
00179 if (cmd.IsName(CmdNOper::CmdName())) {
00180 uint32_t errcode = res ? ntohl(fControlRecv.value) : roc::Board::kOperNetworkErr;
00181
00182 base::OperList* lst = (base::OperList*) cmd.GetPtr(OperListPar, 0);
00183
00184 int first = cmd.GetInt("FirstIndx", 0);
00185 int nsend = lst->number() - first;
00186 int max = sizeof(fControlSend.rawdata) / 2 / sizeof(uint32_t);
00187 if (nsend>max) nsend = max;
00188
00189 if (nsend != (int) ntohl(fControlRecv.address))
00190 errcode = roc::Board::kOperNetworkErr;
00191 else {
00192 uint32_t* src = (uint32_t*) fControlRecv.rawdata;
00193 for (int n=first;n<first+nsend;n++) {
00194 uint32_t res_addr = ntohl(*src++);
00195 if (lst->oper(n).addr != (res_addr & NOPER_ADDR_MASK)) {
00196 if (errcode==0) {
00197 errcode = roc::Board::operErrBuild(roc::Board::kOperNetworkErr, n);
00198 EOUT(("Source %x and target %x address mismatch", lst->oper(n).addr, res_addr));
00199 }
00200 } else {
00201 uint32_t res_value = ntohl(*src++);
00202 if (!lst->oper(n).isput)
00203 lst->oper(n).value = res_value;
00204 else
00205 if (lst->oper(n).value != res_value) {
00206 EOUT(("Initial %x and obtained %x value mismatch", lst->oper(n).value, res_value));
00207 errcode = roc::Board::operErrBuild(roc::Board::kOperNetworkErr, n);
00208 }
00209 }
00210 }
00211 }
00212
00213
00214 if ((errcode==0) && (first+nsend<lst->number())) {
00215 finished = false;
00216 cmd.SetInt("FirstIndx", first+nsend);
00217 DOUT3(("Very long NOper list, continue with index %d", first+nsend));
00218 } else
00219 cmd.SetUInt(ErrNoPar, errcode);
00220
00221 if (errcode!=0) DOUT0(("NOper err = %d res = %s", errcode, DBOOL(res)));
00222 }
00223 }
00224
00225 if (finished) {
00226 fUdpCmds.Pop();
00227 cmd.ReplyBool(res);
00228 }
00229
00230 fCtrlRuns = false;
00231
00232
00233
00234 checkCommandsQueue();
00235 }
00236
00237
00238
00239 int roc::UdpControlSocket::ExecuteCommand(dabc::Command cmd)
00240 {
00241 fUdpCmds.Push(cmd);
00242 checkCommandsQueue();
00243 return dabc::cmd_postponed;
00244 }
00245
00246
00247
00248 void roc::UdpControlSocket::checkCommandsQueue()
00249 {
00250 if (fCtrlRuns) return;
00251
00252 if (fUdpCmds.Size()==0) return;
00253
00254 dabc::Command cmd = fUdpCmds.Front();
00255
00256 bool cmdfails = false;
00257 fTotalTmoutSec = cmd.GetDouble(TmoutPar, 5.0);
00258
00259 if (cmd.IsName(CmdPut::CmdName()) ||
00260 cmd.IsName(UdpDevice::CmdPutSuspendDaq()) ||
00261 cmd.IsName(UdpDevice::CmdPutDisconnect()) ||
00262 cmd.IsName(CmdDLM::CmdName())) {
00263
00264 uint32_t addr = cmd.GetUInt(AddrPar, 0);
00265 uint32_t value = cmd.GetUInt(ValuePar, 0);
00266
00267 if (cmd.IsName(CmdDLM::CmdName())) {
00268 value = addr;
00269 addr = ROC_ETH_DLM;
00270 DOUT3(("Activate SOFT-DLM %u", value));
00271 }
00272
00273 switch (addr) {
00274 case ROC_ETH_CFG_WRITE:
00275 case ROC_ETH_CFG_READ:
00276 case ROC_ETH_OVERWRITE_SD_FILE:
00277 case ROC_ETH_FLASH_KIBFILE_FROM_DDR:
00278 if (fTotalTmoutSec < 10) fTotalTmoutSec = 10.;
00279 break;
00280 }
00281
00282 fControlSend.tag = ROC_POKE;
00283 fControlSend.address = htonl(addr);
00284 fControlSend.value = htonl(value);
00285
00286 fControlSendSize = sizeof(UdpMessage);
00287
00288 void* ptr = cmd.GetPtr(RawDataPar, 0);
00289 if (ptr) {
00290 memcpy(fControlSend.rawdata, ptr, value);
00291 fControlSendSize += value;
00292 }
00293 } else
00294 if (cmd.IsName(CmdGet::CmdName())) {
00295 fControlSend.tag = ROC_PEEK;
00296 fControlSend.address = htonl(cmd.GetUInt(AddrPar, 0));
00297 fControlSendSize = sizeof(UdpMessage);
00298 } else
00299 if (cmd.IsName(CmdNOper::CmdName())) {
00300 fControlSend.tag = ROC_NOPER;
00301 fControlSend.address = 0;
00302 fControlSend.value = 0;
00303
00304 fControlSendSize = sizeof(UdpMessage);
00305
00306 base::OperList* lst = (base::OperList*) cmd.GetPtr(OperListPar, 0);
00307
00308 if (lst==0) {
00309 cmdfails = true;
00310 } else {
00311 int first = cmd.GetInt("FirstIndx", 0);
00312 int nsend = lst->number() - first;
00313 int max = sizeof(fControlSend.rawdata) / 2 / sizeof(uint32_t);
00314 if (nsend>max) {
00315 nsend = max;
00316 fControlSend.value = htonl(1);
00317 }
00318
00319 fControlSend.address = htonl(nsend);
00320 fControlSendSize += nsend * 2 * sizeof(uint32_t);
00321 uint32_t* tgt = (uint32_t*) fControlSend.rawdata;
00322
00323 for (int n=first;n<first+nsend;n++) {
00324 uint32_t mask = lst->oper(n).isput ? NOPER_PUT : NOPER_GET;
00325 *tgt++ = htonl(lst->oper(n).addr | mask);
00326 *tgt++ = htonl(lst->oper(n).value);
00327 }
00328
00329 DOUT3(("Sending NOper of num = %d, size = %d failes %s", nsend, fControlSendSize, DBOOL(cmdfails)));
00330 }
00331 } else {
00332 cmdfails = true;
00333 }
00334
00335 if (cmdfails) {
00336 fUdpCmds.Pop().ReplyFalse();
00337 FireEvent(evntCheckCmd);
00338 return;
00339 }
00340
00341 fControlSend.password = htonl(ROC_PASSWORD);
00342 fControlSend.id = htonl(fPacketCounter++);
00343
00344
00345
00346 while ((fControlSendSize < MAX_UDP_PAYLOAD) &&
00347 (fControlSendSize + UDP_PAYLOAD_OFFSET) % 4) fControlSendSize++;
00348
00349
00350 fFastMode = (fTotalTmoutSec < 10.);
00351 fLoopCnt = 0;
00352
00353 fCtrlRuns = true;
00354
00355 FireEvent(evntSendCtrl);
00356 }
00357
00358
00359
00360 roc::UdpDevice::UdpDevice(const char* name, const char* thrdname, dabc::Command cmd) :
00361 dabc::Device(name),
00362 roc::UdpBoard(),
00363 fConnected(false),
00364 fFormat(formatEth1),
00365 fRocIp(),
00366 fRocCtrlPort(ROC_DEFAULT_CTRLPORT),
00367 fRocDataPort(ROC_DEFAULT_DATAPORT),
00368 fCtrlPort(0),
00369 fCtrlCh(0),
00370 fDataPort(0),
00371 fDataFD(0),
00372 fDataCh(0),
00373 isBrdStat(false),
00374 displayConsoleOutput_(false),
00375 fSwMutex(),
00376 fSwCmdState(0)
00377 {
00378 fRocIp = Cfg(roc::xmlBoardAddr, cmd).AsStdStr();
00379 if (fRocIp.length()==0) return;
00380 size_t separ = fRocIp.find(':');
00381 if ((separ>0) && (separ!=std::string::npos)) {
00382 fRocCtrlPort = atoi(fRocIp.c_str()+separ+1);
00383 fRocIp.resize(separ);
00384 if (fRocCtrlPort==0)
00385 fRocCtrlPort = ROC_DEFAULT_CTRLPORT;
00386 else
00387 fRocDataPort = fRocCtrlPort - 1;
00388 }
00389
00390 if (!dabc::mgr()->MakeThreadFor(this, thrdname)) return;
00391
00392 int nport = 8725;
00393
00394 int fd = dabc::SocketThread::StartUdp(nport, nport, nport+1000);
00395
00396 fd = dabc::SocketThread::ConnectUdp(fd, fRocIp.c_str(), fRocCtrlPort);
00397
00398 if (fd<=0) return;
00399
00400 fCtrlCh = new UdpControlSocket(this, fd);
00401
00402 fCtrlCh->AssignToThread(thread());
00403
00404 DOUT2(("Create control socket %d for port %d connected to host %s", fd, nport, fRocIp.c_str()));
00405
00406 fCtrlPort = nport;
00407 fConnected = true;
00408
00409 std::string srole = Cfg(roc::xmlRole, cmd).AsStdStr(base::roleToString(base::roleDAQ));
00410
00411 base::ClientRole role = base::defineClientRole(srole.c_str(), base::roleDAQ);
00412
00413 if (role==base::roleNone) role = base::roleDAQ;
00414
00415 setRole(role);
00416
00417 if (!initUdp()) fConnected = false;
00418 }
00419
00420
00421
00422 roc::UdpDevice::~UdpDevice()
00423 {
00424 DOUT3(("Destroy roc::UdpDevice %s", GetName()));
00425
00426 if (fDataFD!=0) {
00427 close(fDataFD);
00428 fDataFD = 0;
00429 }
00430
00431 if (fDataCh) {
00432
00433 fDataCh->fDev = 0;
00434
00435
00436 fDataCh = 0;
00437 }
00438
00439 if (fCtrlCh) {
00440 if (fConnected && (getRole() != base::roleObserver)) fCtrlCh->SendDisconnect();
00441
00442 fCtrlCh->fDev = 0;
00443 dabc::Object::Destroy(fCtrlCh);
00444 fCtrlCh = 0;
00445 }
00446
00447 DOUT3(("Destroy roc::UdpDevice %s done", GetName()));
00448 }
00449
00450
00451
00452 int roc::UdpDevice::ExecuteCommand(dabc::Command cmd)
00453 {
00454 if (cmd.IsName(CmdGet::CmdName()) ||
00455 cmd.IsName(CmdPut::CmdName()) ||
00456 cmd.IsName(CmdNOper::CmdName()) ||
00457 cmd.IsName(CmdDLM::CmdName())) {
00458 if (fCtrlCh==0) return dabc::cmd_false;
00459 fCtrlCh->Submit(cmd);
00460 return dabc::cmd_postponed;
00461 } else
00462 if (cmd.IsName(roc::UdpDevice::CmdPutSuspendDaq())) {
00463 if ((fCtrlCh==0) || (fDataCh==0)) return dabc::cmd_false;
00464
00465 if (!fDataCh->prepareForSuspend()) return dabc::cmd_false;
00466
00467 cmd.SetUInt(AddrPar, ROC_ETH_SUSPEND_DAQ);
00468 cmd.SetUInt(ValuePar, 1);
00469 fCtrlCh->Submit(cmd);
00470
00471 return dabc::cmd_postponed;
00472 } else
00473 if (cmd.IsName(roc::UdpDevice::CmdPutDisconnect())) {
00474 if (fCtrlCh==0) return dabc::cmd_false;
00475
00476 if (getRole() == base::roleObserver) return dabc::cmd_true;
00477
00478 fConnected = false;
00479
00480 cmd.SetUInt(AddrPar, ROC_ETH_MASTER_LOGOUT);
00481 cmd.SetUInt(ValuePar, 1);
00482 fCtrlCh->Submit(cmd);
00483
00484 return dabc::cmd_postponed;
00485 } else
00486 if (cmd.IsName("SetFlushTimeout")) {
00487 if (fDataCh==0) {
00488 EOUT(("No data channel - cannot setup flush timeout"));
00489 return dabc::cmd_false;
00490 }
00491
00492 fDataCh->setFlushTimeout(cmd.GetDouble("Timeout", 0.1));
00493
00494 return dabc::cmd_true;
00495 } else
00496 if (cmd.IsName("enableCalibration")) {
00497 dabc::mgr.FindModule(CalibrModuleName).Submit(cmd);
00498 return dabc::cmd_postponed;
00499 } else
00500 if (cmd.IsName(CmdGetBoardPtr::CmdName())) {
00501 cmd.SetPtr(CmdGetBoardPtr::Board(), (roc::Board*)this);
00502 return dabc::cmd_true;
00503 } else
00504 if (cmd.IsName(CmdReturnBoardPtr::CmdName())) {
00505 return dabc::cmd_true;
00506 }
00507
00508 return dabc::Device::ExecuteCommand(cmd);
00509 }
00510
00511
00512
00513 bool roc::UdpDevice::initUdp()
00514 {
00515 DOUT2(("Starting UdpDevice::initialize"));
00516
00517 if (fCtrlCh==0) return false;
00518
00519 int logincode = 99;
00520 if (getRole() == base::roleDAQ) logincode = 0; else
00521 if (getRole() == base::roleControl) logincode = 1;
00522
00523 if (rawPut(ROC_ETH_MASTER_LOGIN, logincode)!=0) return false;
00524
00525 DOUT2(("Put login %d OK ",logincode));
00526
00527 if (getRole() == base::roleDAQ) {
00528
00529 int nport = fCtrlPort + 1;
00530
00531 int fd = dabc::SocketThread::StartUdp(nport, nport, nport+1000);
00532
00533 fd = dabc::SocketThread::ConnectUdp(fd, fRocIp.c_str(), fRocDataPort);
00534
00535 if (fd<=0) return false;
00536
00537 if (put(ROC_ETH_STOP_DAQ, 1)!=0) {
00538 EOUT(("Cannot stop daq"));
00539 close(fd);
00540 return false;
00541 }
00542
00543 if (put(ROC_ETH_MASTER_DATAPORT, nport)!=0) {
00544 EOUT(("Cannot assign to ROC data port number"));
00545 close(fd);
00546 return false;
00547 }
00548
00549 fDataPort = nport;
00550 fDataFD = fd;
00551
00552 DOUT2(("Create data socket %d for port %d connected to host %s", fd, nport, fRocIp.c_str()));
00553 }
00554
00555 uint32_t roc_hw_ver = initBoard("ROC", 0x2000000);
00556
00557 fFormat = (roc_hw_ver < 0x01090000) ? formatEth1 : formatEth2;
00558
00559 base::OperList lst;
00560 lst.addGet(ROC_ETH_HWV);
00561 lst.addGet(ROC_ETH_SWV);
00562 if (operGen(lst)!=0) return false;
00563 uint32_t eth_hw_ver = lst.oper(0).value;
00564 uint32_t eth_sw_ver = lst.oper(1).value;
00565
00566 DOUT0(("ROC%u Eth HW version: %s", boardNumber(), versionToString(eth_hw_ver)));
00567
00568 DOUT0(("ROC%u Eth SW version: %s", boardNumber(), versionToString(eth_sw_ver)));
00569
00570 if(eth_sw_ver < 0x02000000) {
00571 EOUT(("The ROC you want to access has software version 0x%08x", eth_sw_ver));
00572 EOUT(("This C++ access class only supports boards with major version 2.0 == 0x%08x", 0x02000000));
00573 }
00574
00575 if ((eth_sw_ver & 0xFFFF0000) != (roc_hw_ver & 0xFFFF0000))
00576 EOUT(("Mismatch of major number of hardware and software version"));
00577
00578 return (eth_sw_ver!=0) && (roc_hw_ver!=0);
00579 }
00580
00581
00582
00583 dabc::Transport* roc::UdpDevice::CreateTransport(dabc::Command cmd, dabc::Reference port)
00584 {
00585 DOUT3(("UdpDevice creates transport for port %p ch %p", port(), fDataCh));
00586
00587 if (fDataCh!=0) return 0;
00588
00589 fDataCh = new UdpDataSocket(this, port, cmd, fDataFD, fFormat);
00590 fDataFD = 0;
00591
00592 return fDataCh;
00593 }
00594
00595
00596
00597 void roc::UdpDevice::setFlushTimeout(double tmout)
00598 {
00599 dabc::Command cmd("SetFlushTimeout");
00600 cmd.SetDouble("Timeout", tmout);
00601 Execute(cmd);
00602 }
00603
00604
00605
00606 int roc::UdpDevice::operGen(base::OperList& lst, double tmout)
00607 {
00608 int res = kHostError;
00609
00610 if (fCtrlCh!=0) {
00611 if (tmout <= 0.) tmout = getDefaultTimeout();
00612
00613 CmdNOper cmd(&lst, tmout);
00614 cmd.SetTimeout(tmout + .1);
00615 if (fCtrlCh->Execute(cmd))
00616 res = cmd.GetInt(ErrNoPar, kHostError);
00617 }
00618
00619 traceOper(lst, res);
00620
00621 return res;
00622 }
00623
00624
00625
00626 void roc::UdpDevice::processCtrlMessage(UdpMessageFull* pkt, unsigned len)
00627 {
00628
00629
00630 if(pkt->tag == ROC_CONSOLE) {
00631 pkt->address = ntohl(pkt->address);
00632
00633 switch (pkt->address) {
00634 case ROC_ETH_STATBLOCK:
00635 setBoardStat(pkt->rawdata, displayConsoleOutput_);
00636 break;
00637
00638 case ROC_ETH_DEBUGMSG:
00639 if (displayConsoleOutput_)
00640 DOUT0(("\033[0;%dm Roc:%d %s \033[0m", 36, 0, (const char*) pkt->rawdata));
00641 break;
00642 default:
00643 if (displayConsoleOutput_)
00644 DOUT0(("Error addr 0x%04x in console message", pkt->address));
00645 break;
00646 }
00647 }
00648 }
00649
00650
00651
00652 void roc::UdpDevice::setBoardStat(void* rawdata, bool print)
00653 {
00654 BoardStatistic* src = (BoardStatistic*) rawdata;
00655
00656 if (src!=0) {
00657 brdStat.dataRate = ntohl(src->dataRate);
00658 brdStat.sendRate = ntohl(src->sendRate);
00659 brdStat.recvRate = ntohl(src->recvRate);
00660 brdStat.nopRate = ntohl(src->nopRate);
00661 brdStat.frameRate = ntohl(src->frameRate);
00662 brdStat.takePerf = ntohl(src->takePerf);
00663 brdStat.dispPerf = ntohl(src->dispPerf);
00664 brdStat.sendPerf = ntohl(src->sendPerf);
00665 brdStat.daqState = ntohl(src->daqState);
00666 isBrdStat = true;
00667 }
00668
00669 if (print && isBrdStat)
00670 DOUT0(("\033[0;%dm Roc:%u Data:%6.3f MB/s Send:%6.3f MB/s Recv:%6.3f MB/s NOPs:%2u Frames:%2u Data:%4.1f%s Disp:%4.1f%s Send:%4.1f%s \033[0m",
00671 36, 0, brdStat.dataRate*1e-6, brdStat.sendRate*1e-6, brdStat.recvRate*1e-6,
00672 brdStat.nopRate, brdStat.frameRate,
00673 brdStat.takePerf*1e-3,"%", brdStat.dispPerf*1e-3,"%", brdStat.sendPerf*1e-3,"%"));
00674 }
00675
00676
00677
00678 roc::BoardStatistic* roc::UdpDevice::takeStat(double tmout, bool print)
00679 {
00680 void *rawdata = 0;
00681
00682 if (tmout > 0.) {
00683
00684 CmdGet cmd(ROC_ETH_STATBLOCK, tmout);
00685 cmd.SetTimeout(tmout + 1.);
00686
00687 if (!fCtrlCh->Execute(cmd)) return 0;
00688
00689 rawdata = fCtrlCh->fControlRecv.rawdata;
00690 }
00691
00692 setBoardStat(rawdata, print);
00693
00694 return isBrdStat ? &brdStat : 0;
00695 }
00696
00697
00698
00699 int roc::UdpDevice::rawPut(uint32_t address, uint32_t value, const void* rawdata, double tmout)
00700 {
00701 if (fCtrlCh==0) return kHostError;
00702
00703 if (tmout <= 0.) tmout = getDefaultTimeout();
00704
00705 CmdPut cmd(address, value, tmout);
00706 cmd.SetPtr(RawDataPar, (void*) rawdata);
00707
00708 int res = kOperNetworkErr;
00709
00710 if (fCtrlCh->Execute(cmd, tmout + 1.))
00711 res = cmd.GetInt(ErrNoPar, kHostError);
00712
00713 DOUT2(("Roc:%s rawPut(0x%04x, 0x%04x) res = %d",
00714 GetName(), address, value, res));
00715
00716 return res;
00717 }
00718
00719
00720
00721 bool roc::UdpDevice::startDaq()
00722 {
00723 DOUT2(("Starting DAQ !!!!"));
00724
00725 dabc::ModuleRef m = dabc::mgr.FindModule(ReadoutModuleName);
00726
00727 if (m.null()) return false;
00728
00729 m.Start();
00730
00731 return true;
00732 }
00733
00734
00735
00736 bool roc::UdpDevice::suspendDaq()
00737 {
00738 DOUT2(("Suspend DAQ !!!!"));
00739
00740 if (!Execute(roc::UdpDevice::CmdPutSuspendDaq(), 5.)) return false;
00741
00742 return true;
00743 }
00744
00745
00746
00747 bool roc::UdpDevice::stopDaq()
00748 {
00749 DOUT2(("Stop DAQ !!!!"));
00750
00751 dabc::ModuleRef m = dabc::mgr.FindModule(ReadoutModuleName);
00752
00753 if (m.null()) return false;
00754
00755 m.Stop();
00756
00757 return true;
00758 }
00759
00760
00761
00762 bool roc::UdpDevice::getNextBuffer(void* &buf, unsigned& len, double tmout)
00763 {
00764 dabc::ModuleRef m = dabc::mgr.FindModule(ReadoutModuleName);
00765 if (m.null()) return false;
00766
00767 return ((ReadoutModule*) m())->getNextBuffer(buf, len, tmout);
00768 }
00769
00770 bool roc::UdpDevice::enableCalibration(double period, double calibr, int cnt)
00771 {
00772 dabc::ModuleRef m = dabc::mgr.FindModule(CalibrModuleName);
00773
00774 if ((period<0) && m.null()) return true;
00775
00776 if (m.null()) {
00777 DOUT0(("Create calibr module"));
00778 dabc::mgr.CreateModule("roc::NxCalibrModule", CalibrModuleName, "NxCalibrThrd");
00779 dabc::mgr.StartModule(CalibrModuleName);
00780 }
00781
00782 dabc::Command cmd("enableCalibration");
00783 if ((period<0.) || (calibr<0.)) cnt = 0;
00784 cmd.SetDouble("WorkPeriod", period);
00785 cmd.SetDouble("CalibrPeriod", calibr);
00786 cmd.SetInt("CalibrLoops", cnt);
00787 cmd.SetReceiver(CalibrModuleName);
00788
00789 return dabc::mgr.Execute(cmd);
00790 }
00791
00792
00793 bool roc::UdpDevice::InitAsBoard()
00794 {
00795
00796
00797 if (getRole() == base::roleDAQ) {
00798
00799 DOUT3(("Create readout module"));
00800
00801 dabc::mgr.CreateThread("ReadoutThrd", dabc::typeSocketThread);
00802
00803 dabc::mgr.CreateMemoryPool(roc::xmlRocPool, 16384, 100, 2);
00804
00805 dabc::mgr.CreateModule("roc::ReadoutModule", ReadoutModuleName, "ReadoutThrd");
00806
00807 DOUT3(("Connect readout module"));
00808
00809 if (!dabc::mgr.CreateTransport(dabc::format("%s/Input",ReadoutModuleName), ItemName(), "ReadoutThrd")) {
00810 EOUT(("Cannot connect readout module to device %s", ItemName().c_str()));
00811 dabc::mgr.DeleteModule(ReadoutModuleName);
00812 return false;
00813 }
00814 }
00815
00816 DOUT3(("InitAsBoard done"));
00817
00818 return true;
00819 }
00820
00821
00822 bool roc::UdpDevice::CloseAsBoard()
00823 {
00824
00825
00826 DOUT3(("UdpDevice::CloseAsBoard Close readout"));
00827
00828 dabc::mgr.StopModule(ReadoutModuleName);
00829 dabc::mgr.DeleteModule(ReadoutModuleName);
00830
00831 DOUT3(("UdpDevice::CloseAsBoard Close calibration"));
00832
00833 disableCalibration();
00834 dabc::mgr.StopModule(CalibrModuleName);
00835 dabc::mgr.DeleteModule(CalibrModuleName);
00836
00837 if (dabc::mgr()) dabc::mgr()->FindThread("ReadoutThrd").Destroy();
00838
00839 DOUT3(("UdpDevice::CloseAsBoard done"));
00840
00841 return true;
00842 }
00843
00844 bool roc::UdpDevice::submitSwPut(uint32_t address, uint32_t value, double tmout)
00845 {
00846 CmdPut cmd(address, value, tmout);
00847 cmd.SetBool("SwPut", true);
00848
00849 fCtrlCh->Submit(cmd);
00850
00851 dabc::LockGuard lock(fSwMutex);
00852 if (fSwCmdState!=0) EOUT(("Last command not completed!!!"));
00853
00854 fSwCmdState = 1;
00855
00856 return true;
00857 }
00858
00859 int roc::UdpDevice::checkSwPut()
00860 {
00861 dabc::LockGuard lock(fSwMutex);
00862
00863 int res = fSwCmdState;
00864 if (fSwCmdState!=1) fSwCmdState = 0;
00865 return res;
00866 }
00867
00868 void roc::UdpDevice::completeSwPut(bool res)
00869 {
00870 dabc::LockGuard lock(fSwMutex);
00871 fSwCmdState = res ? 2 : -1;
00872 }