• Main Page
  • Related Pages
  • Namespaces
  • Data Structures
  • Files
  • File List
  • Globals

plugin/src/UdpDevice.cxx (r4864/r4162)

Go to the documentation of this file.
00001 /********************************************************************
00002  * The Data Acquisition Backbone Core (DABC)
00003  ********************************************************************
00004  * Copyright (C) 2009-
00005  * GSI Helmholtzzentrum fuer Schwerionenforschung GmbH
00006  * Planckstr. 1
00007  * 64291 Darmstadt
00008  * Germany
00009  * Contact:  http://dabc.gsi.de
00010  ********************************************************************
00011  * This software can be used under the GPL license agreements as stated
00012  * in LICENSE.txt file which is part of the distribution.
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    // we will react on all input packets
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          // this is required for DABC 2.0 to let thread again generate socket-read event
00087          SetDoingInput(true);
00088 
00089          ssize_t len = DoRecvBuffer(&fControlRecv, sizeof(UdpMessageFull));
00090 
00091 //         DOUT0(("Get answer of size %d req %d answ %d", len, ntohl(fControlSend.id), ntohl(fControlRecv.id)));
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             // DOUT0(("Submit keep alive command"));
00137          }
00138 
00139       return 1.;
00140    }
00141 
00142    if (fTotalTmoutSec <= 0.) {
00143       // stop doing;
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          // if list was too large, send next buffer
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 //   ActivateTimeout(-1.);
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); // LOCK control channel for this node
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    // send aligned to 4 bytes packet to the ROC
00345 
00346    while ((fControlSendSize < MAX_UDP_PAYLOAD) &&
00347           (fControlSendSize + UDP_PAYLOAD_OFFSET) % 4) fControlSendSize++;
00348 
00349    // in fast mode we will try to resend as fast as possible
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       // EOUT(("Data channel not yet destroyed !!!"));
00433       fDataCh->fDev = 0;
00434       // transport should be destroyed by port
00435       // dabc::Object::Destroy(fDataCh);
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    // process PEEK or POKE reply messages from ROC
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    // called from main thread
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    // called from main thread
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 }

Generated on Tue Dec 10 2013 04:52:23 for ROCsoft by  doxygen 1.7.1