00001 #include "spadic/SusiboInput.h"
00002
00003 #include "dabc/Port.h"
00004 #include "dabc/Pointer.h"
00005 #include "mbs/MbsTypeDefs.h"
00006 #include "spadic/Message.h"
00007
00008 #include "base/commons.h"
00009
00010 #include "spadiclib.h"
00011
00012
00013 #include <vector>
00014
00015 spadic::SusiboInput::SusiboInput(const char* name, uint32_t bufsize) :
00016 dabc::DataInput(),
00017 fBoardID(1),
00018 fBufferSize(bufsize),
00019 fMaxBufferEvents(1),
00020 fHitDelay(100),
00021 fFormatMbs(true),
00022 fTestTrigger(false),
00023 fTriggerPerSecond(10),
00024 fTimeout(0.1),
00025 fLib(0)
00026 {
00027 }
00028
00029 spadic::SusiboInput::~SusiboInput()
00030 {
00031 Close();
00032 }
00033
00034 bool spadic::SusiboInput::Read_Init(const dabc::WorkerRef& wrk, const dabc::Command& cmd)
00035 {
00036 fBoardID = wrk.Cfg(spadic::xmlSusiboDevID, cmd).AsInt(fBoardID);
00037 fBufferSize = wrk.Cfg(dabc::xmlBufferSize, cmd).AsInt(fBufferSize);
00038 fMaxBufferEvents = wrk.Cfg(spadic::xmlEventsPerBuffer, cmd).AsInt(fMaxBufferEvents);
00039 fHitDelay = wrk.Cfg(spadic::xmlHitDelay, cmd).AsInt(fHitDelay);
00040 fFormatMbs = wrk.Cfg(spadic::xmlFormatMbs, cmd).AsBool(fFormatMbs);
00041 fTimeout = wrk.Cfg(spadic::xmlTimeout, cmd).AsDouble(fTimeout);
00042 fTestTrigger = wrk.Cfg(spadic::xmlUseInternalTrigger, cmd).AsBool(fTestTrigger);
00043 fTriggerPerSecond = wrk.Cfg(spadic::xmlInternalTriggerFreq, cmd).AsDouble(fTriggerPerSecond);
00044 DOUT1(("SusiboInput for board %d - BufferSize = %d byte, Timeout = %3.2f s, Delay=%d, TestTrigger=%3.1f Hz",
00045 fBoardID, fBufferSize, fTimeout, fHitDelay, (fTestTrigger ? fTriggerPerSecond : -1.)));
00046
00047 return Init();
00048 }
00049
00050 bool spadic::SusiboInput::Init()
00051 {
00052 Close();
00053 if (fBufferSize==0) {
00054 EOUT(("Buffer size not specified !!!!"));
00055 return false;
00056 }
00057
00058 fLib = new SuS::SpadicLib();
00059
00060 if (!fLib->connectSpadic(SuS::SpadicIO::Ftdi, true, true, fBoardID, fHitDelay)) {
00061 EOUT(("Cannot connect to Susibo board %d",fBoardID));
00062 delete fLib;
00063 fLib = 0;
00064 return false;
00065 }
00066 DOUT1(("SusiboInput: connected to board id %d", fBoardID));
00067
00068 fLastTriggerTime.GetNow();
00069
00070 return true;
00071 }
00072
00073 bool spadic::SusiboInput::Close()
00074 {
00075 if(fLib) {
00076 fLib->disconnectSpadic();
00077 int timeout = 1000;
00078 while(!fLib->isReady() && timeout-- > 0) dabc::Sleep(0.001);
00079 if(timeout <= 0) EOUT(("could not disconnect SPADIC %d, timeout", fBoardID));
00080 if (timeout>900) dabc::Sleep(0.1);
00081 delete fLib;
00082 fLib = 0;
00083 }
00084
00085 return true;
00086 }
00087
00088 unsigned spadic::SusiboInput::Read_Size()
00089 {
00090 return fBufferSize;
00091 }
00092
00093 unsigned spadic::SusiboInput::Read_Complete(dabc::Buffer& buf)
00094 {
00095
00096
00097
00098 if (fTestTrigger && (fTriggerPerSecond > 0.)) {
00099 if (fLastTriggerTime.Expired(1./fTriggerPerSecond)) {
00100 DOUT3(("SusiboInput:: sending test trigger %d, thrshld= %d", trigcounter, thrshld));
00101 fLib->write(0x11, 0x01);
00102 fLib->write(0x11, 0x00);
00103 fLastTriggerTime.GetNow();
00104 }
00105 }
00106
00107 int nmax = buf.GetTotalSize() / (SUSIBO_PACKAGE_LENGTH + (fFormatMbs ? (sizeof(mbs::EventHeader) + sizeof(mbs::SubeventHeader)) : 0));
00108 if(fMaxBufferEvents>0 && fMaxBufferEvents<nmax)
00109 nmax=fMaxBufferEvents;
00110 std::list< std::vector<uint8_t> > packages;
00111 int numread = fLib->readPackages(packages, nmax);
00112
00113 if (numread != (int) packages.size()) {
00114 EOUT(("Size of list %u differs from return value %d", packages.size(), numread));
00115 }
00116
00117 std::vector<unsigned> msgs_ids;
00118 bool isbadmsg = false;
00119
00120 dabc::Pointer ptr = buf.GetPointer();
00121 unsigned totallen = 0;
00122 while (packages.size() > 0) {
00123 spadic::Message msg(&packages.front());
00124 if (msg.CheckMessage()) {
00125
00126
00127 msgs_ids.push_back(msg.GetEventIDNumber());
00128
00129
00130 if (fFormatMbs) {
00131
00132
00133 mbs::EventHeader* evhdr = (mbs::EventHeader*) ptr();
00134 evhdr->Init(msg.GetEventIDNumber());
00135 buf.Shift(ptr, sizeof(mbs::EventHeader));
00136 totallen += sizeof(mbs::EventHeader);
00137 mbs::SubeventHeader* subhdr = (mbs::SubeventHeader*) ptr();
00138 subhdr->Init();
00139 subhdr->iProcId = roc::proc_TRD_Spadic;
00140 subhdr->iSubcrate = fBoardID;
00141 subhdr->iControl = spadic::Message::packageStruct;
00142 buf.Shift(ptr, sizeof(mbs::SubeventHeader));
00143 totallen += sizeof(mbs::SubeventHeader);
00144 subhdr->SetRawDataSize(SUSIBO_PACKAGE_LENGTH);
00145 evhdr->SetSubEventsSize(sizeof(mbs::SubeventHeader) + SUSIBO_PACKAGE_LENGTH);
00146 buf.SetTypeId(mbs::mbt_MbsEvents);
00147 } else {
00148 buf.SetTypeId(spadic::bt_Spadic);
00149 }
00150
00151
00152
00153
00154
00155
00156
00157 for (unsigned nn = 0; nn < SUSIBO_PACKAGE_LENGTH; nn++) {
00158 *((uint8_t*) ptr()) = msg.Data(nn);
00159 buf.Shift(ptr, 1);
00160 }
00161
00162 totallen += SUSIBO_PACKAGE_LENGTH;
00163 } else {
00164 isbadmsg = true;
00165 }
00166
00167 packages.pop_front();
00168
00169 }
00170
00171 if (totallen==0) return dabc::di_RepeatTimeOut;
00172
00173 if (!fTestTrigger && isbadmsg && (msgs_ids.size()<3)) {
00174 EOUT(("Found bad messages, drop all other"));
00175 return dabc::di_RepeatTimeOut;
00176 }
00177
00178 if (!fTestTrigger && (msgs_ids.size()>2)) {
00179 isbadmsg = false;
00180 unsigned shift = (msgs_ids[1] - msgs_ids[0]) & 0xffffff;
00181 for (unsigned n=2;n<msgs_ids.size();n++)
00182 if (((msgs_ids[n] - msgs_ids[n-1]) & 0xffffff) != shift) isbadmsg = true;
00183 if (isbadmsg) {
00184 EOUT(("Found bad sequence in the messages, drop all of them"));
00185 return dabc::di_RepeatTimeOut;
00186 }
00187 }
00188
00189 DOUT3(("SusiboInput:: totallen = %d",totallen));
00190 buf.SetTotalSize(totallen);
00191
00192 return dabc::di_Ok;
00193 }