diff --git a/.gitattributes b/.gitattributes index a6ecbf12842f14b4cd6c196db248e6a0a274dd03..b6c07ba824dde0184026123a99b5e516d8fcea68 100644 --- a/.gitattributes +++ b/.gitattributes @@ -303,6 +303,12 @@ MAC/APL/RTDBCommon/src/RTDButilities.cc -text MAC/APL/RTDBCommon/test/Makefile.am -text MAC/APL/RTDBCommon/test/tRTDButilities.cc -text MAC/APL/RTDBCommon/test/tRTDButilities.h -text +MAC/APL/StationCU/src/HardwareMonitor/HardwareMonitor.conf -text +MAC/APL/StationCU/src/HardwareMonitor/RSPMonitor.cc -text +MAC/APL/StationCU/src/HardwareMonitor/RSPMonitor.h -text +MAC/APL/StationCU/src/HardwareMonitor/TBB.dpl -text +MAC/APL/StationCU/src/HardwareMonitor/TBBMonitor.cc -text +MAC/APL/StationCU/src/HardwareMonitor/TBBMonitor.h -text MAC/APL/_GSO/MACScheduler/Makefile.am -text svneol=native#application/octet-stream MAC/APL/_GSO/MACScheduler/bootstrap -text svneol=native#application/octet-stream MAC/APL/_GSO/MACScheduler/configure.in -text svneol=native#application/octet-stream diff --git a/MAC/APL/StationCU/src/HardwareMonitor/HardwareMonitor.conf b/MAC/APL/StationCU/src/HardwareMonitor/HardwareMonitor.conf new file mode 100644 index 0000000000000000000000000000000000000000..db6ab86375969b75650e6f04aa02ce22f3959369 --- /dev/null +++ b/MAC/APL/StationCU/src/HardwareMonitor/HardwareMonitor.conf @@ -0,0 +1,6 @@ +# +# HardwareMonitor.conf +# +WatchRSPboards = 1 +WatchTBboards = 1 +closingDelay = 2.0 diff --git a/MAC/APL/StationCU/src/HardwareMonitor/HardwareMonitorMain.cc b/MAC/APL/StationCU/src/HardwareMonitor/HardwareMonitorMain.cc index f10b759dacdb9aeced83ea0a8e361629adf587c1..6709dc0e56a2451201715b3d2d3c60bb5b0a1eab 100644 --- a/MAC/APL/StationCU/src/HardwareMonitor/HardwareMonitorMain.cc +++ b/MAC/APL/StationCU/src/HardwareMonitor/HardwareMonitorMain.cc @@ -23,8 +23,15 @@ #include <lofar_config.h> #include <Common/LofarLogger.h> -#include "HardwareMonitor.h" +#include <APS/ParameterSet.h> +#include <APL/RSP_Protocol/RSP_Protocol.ph> +#include <GCF/RTDB/DP_Protocol.ph> +#include "RSPMonitor.h" +#include "TBBMonitor.h" +using namespace LOFAR; +using namespace LOFAR::ACC::APS; +using namespace LOFAR::GCF; using namespace LOFAR::GCF::TM; using namespace LOFAR::StationCU; @@ -33,11 +40,52 @@ int main(int argc, char* argv[]) // args: cntlrname, parentHost, parentService GCFTask::init(argc, argv); - HardwareMonitor hm("HWmonitor"); - hm.start(); // make initial transition + // TODO + LOG_INFO("MACProcessScope: LOFAR.PermSW.HWmonitor"); - GCFTask::run(); + // for debugging purposes + registerProtocol (RSP_PROTOCOL, RSP_PROTOCOL_STRINGS); + registerProtocol (TBB_PROTOCOL, TBB_PROTOCOL_STRINGS); + registerProtocol (DP_PROTOCOL, DP_PROTOCOL_STRINGS); - return 0; + // Create tasks and call initial routines + RSPMonitor* rsp(0); + TBBMonitor* tbb(0); + // monitor RSP? + if (globalParameterSet()->getUint32("WatchRSPboards",0)) { + rsp = new RSPMonitor("RSPMonitor"); + rsp->start(); + LOG_INFO("Monitoring the RSP boards"); + } + + // monitor TBB? + if (globalParameterSet()->getUint32("WatchTBboards",0)) { + tbb = new TBBMonitor("TBBMonitor"); + tbb->start(); + LOG_INFO("Monitoring the TB boards"); + } + + // sanity check + if (!tbb && !rsp) { + LOG_FATAL_STR("Non of the monitortask (WatchRSPboards, WatchTBboards) was switched on " + "in the configfile, terminating program"); + return (0); + } + + // ok, we have something to do, do it. + GCFTask::setDelayedQuit(true); // we need a clean shutdown + GCFTask::run(); // until stop was called + + if (rsp) { + rsp->quit(); // let task quit nicely + } + if (tbb) { + tbb->quit(); // let task quit nicely + } + + double postRunTime = globalParameterSet()->getDouble("closingDelay", 1.5); + GCFTask::run(postRunTime); // let processes die. + + return (0); } diff --git a/MAC/APL/StationCU/src/HardwareMonitor/Makefile.am b/MAC/APL/StationCU/src/HardwareMonitor/Makefile.am index 321e45f925e6d1aaf6657cb25186b2ad6a655c79..cb5833da89e6cd295fcfcb1394f17b342f35b59e 100644 --- a/MAC/APL/StationCU/src/HardwareMonitor/Makefile.am +++ b/MAC/APL/StationCU/src/HardwareMonitor/Makefile.am @@ -4,13 +4,15 @@ HardwareMonitor_CPPFLAGS = -Wno-deprecated \ -fmessage-length=0 \ -fdiagnostics-show-location=once -HardwareMonitor_SOURCES = HardwareMonitor.cc \ - HardwareMonitorMain.cc +HardwareMonitor_SOURCES = HardwareMonitorMain.cc \ + RSPMonitor.cc \ + TBBMonitor.cc HardwareMonitor_LDADD = $(LOFAR_DEPEND) HardwareMonitor_DEPENDENCIES= $(LOFAR_DEPEND) -NOINSTHDRS = HardwareMonitor.h \ +NOINSTHDRS = RSPMonitor.h \ + TBBMonitor.h \ RCUConstants.h \ StationPermDatapointDefs.h diff --git a/MAC/APL/StationCU/src/HardwareMonitor/RCUConstants.h b/MAC/APL/StationCU/src/HardwareMonitor/RCUConstants.h index b3c9ea92c6df0a55911e8643dd97e2a84a00a114..66275bcbd8f322d9bef0da90c2b60a38d014b20e 100644 --- a/MAC/APL/StationCU/src/HardwareMonitor/RCUConstants.h +++ b/MAC/APL/StationCU/src/HardwareMonitor/RCUConstants.h @@ -47,11 +47,13 @@ static const uint32 ATT_OFFSET = 19; // NOTE: THESE CONSTANTS SHOULD BE SOMEWHERE AT A GLOBAL PLACE -static const uint32 NR_SUBRACKS_PER_CABINET = 2; -static const uint32 NR_RSPBOARDS_PER_SUBRACK= 4; -static const uint32 NR_RCUS_PER_RSPBOARD = 8; -static const uint32 NR_RCUS_PER_SUBRACK = (NR_RCUS_PER_RSPBOARD * NR_RSPBOARDS_PER_SUBRACK); -static const uint32 NR_RCUS_PER_CABINET = (NR_RCUS_PER_SUBRACK * NR_SUBRACKS_PER_CABINET); +static const uint32 NR_SUBRACKS_PER_CABINET = 2; +static const uint32 NR_RSPBOARDS_PER_SUBRACK = 4; +static const uint32 NR_TBBOARDS_PER_RSPBOARD = 2; +static const uint32 NR_RCUS_PER_RSPBOARD = 8; +static const uint32 NR_RCUS_PER_TBBOARD = (NR_TBBOARDS_PER_RSPBOARD * NR_RCUS_PER_RSPBOARD); +static const uint32 NR_RCUS_PER_SUBRACK = (NR_RCUS_PER_RSPBOARD * NR_RSPBOARDS_PER_SUBRACK); +static const uint32 NR_RCUS_PER_CABINET = (NR_RCUS_PER_SUBRACK * NR_SUBRACKS_PER_CABINET); #define PN_RSP_AP_VERSION_MASK "AP%d.version" diff --git a/MAC/APL/StationCU/src/HardwareMonitor/RSPMonitor.cc b/MAC/APL/StationCU/src/HardwareMonitor/RSPMonitor.cc new file mode 100644 index 0000000000000000000000000000000000000000..3db6468ca615cebd8dd21b3b8289d981606d40cd --- /dev/null +++ b/MAC/APL/StationCU/src/HardwareMonitor/RSPMonitor.cc @@ -0,0 +1,808 @@ +//# RSPMonitor.cc: Implementation of the MAC Scheduler task +//# +//# Copyright (C) 2006 +//# ASTRON (Netherlands Foundation for Research in Astronomy) +//# P.O.Box 2, 7990 AA Dwingeloo, The Netherlands, seg@astron.nl +//# +//# This program is free software; you can redistribute it and/or modify +//# it under the terms of the GNU General Public License as published by +//# the Free Software Foundation; either version 2 of the License, or +//# (at your option) any later version. +//# +//# This program is distributed in the hope that it will be useful, +//# but WITHOUT ANY WARRANTY; without even the implied warranty of +//# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +//# GNU General Public License for more details. +//# +//# You should have received a copy of the GNU General Public License +//# along with this program; if not, write to the Free Software +//# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +//# +//# $Id: RSPMonitor.cc 10505 2007-09-07 17:14:57Z overeem $ +#include <lofar_config.h> +#include <Common/LofarLogger.h> + +#include <GCF/GCF_PVTypes.h> +#include <GCF/GCF_ServiceInfo.h> +#include <APL/APLCommon/ControllerDefines.h> +#include <APL/RSP_Protocol/RSP_Protocol.ph> +#include <GCF/RTDB/DP_Protocol.ph> +//#include <APL/APLCommon/StationInfo.h> +#include <signal.h> + +#include "RSPMonitor.h" +#include "RCUConstants.h" +#include "StationPermDatapointDefs.h" + +using namespace LOFAR::GCF::Common; +using namespace LOFAR::GCF::TM; +using namespace LOFAR::GCF::RTDB; +using namespace std; + +namespace LOFAR { + using namespace APLCommon; + namespace StationCU { + +// +// RSPMonitor() +// +RSPMonitor::RSPMonitor(const string& cntlrName) : + GCFTask ((State)&RSPMonitor::initial_state,cntlrName), + itsOwnPropertySet (0), + itsTimerPort (0), + itsRSPDriver (0), + itsPollInterval (10), + itsNrRCUs (0), + itsNrRSPboards (0), + itsNrSubracks (0), + itsNrCabinets (0) +{ + LOG_TRACE_OBJ_STR (cntlrName << " construction"); + + // need port for timers. + itsTimerPort = new GCFTimerPort(*this, "TimerPort"); + + // prepare TCP port to RSPDriver. + itsRSPDriver = new GCFTCPPort (*this, MAC_SVCMASK_RSPDRIVER, + GCFPortInterface::SAP, RSP_PROTOCOL); + ASSERTSTR(itsRSPDriver, "Cannot allocate TCPport to RSPDriver"); + itsRSPDriver->setInstanceNr(0); + +} + + +// +// ~RSPMonitor() +// +RSPMonitor::~RSPMonitor() +{ + LOG_TRACE_OBJ_STR (getName() << " destruction"); + + if (itsRSPDriver) { + itsRSPDriver->close(); + } + + // ... +} + + +// +// initial_state(event, port) +// +// Setup connection with PVSS +// +GCFEvent::TResult RSPMonitor::initial_state(GCFEvent& event, + GCFPortInterface& port) +{ + LOG_DEBUG_STR ("initial:" << eventName(event) << "@" << port.getName()); + + GCFEvent::TResult status = GCFEvent::HANDLED; + + switch (event.signal) { + case F_INIT: + break; + + case F_ENTRY: { + // Get access to my own propertyset. + LOG_DEBUG_STR ("Activating PropertySet " << PSN_HARDWARE_MONITOR); + itsTimerPort->setTimer(2.0); + itsOwnPropertySet = new RTDBPropertySet(PSN_HARDWARE_MONITOR, + PST_HARDWARE_MONITOR, + PSAT_WO, + this); + + } + break; + + case DP_CREATED: { + // NOTE: this function may be called DURING the construction of the PropertySet. + // Always exit this event in a way that GCF can end the construction. + DPCreatedEvent dpEvent(event); + LOG_DEBUG_STR("Result of creating " << dpEvent.DPname << " = " << dpEvent.result); + itsTimerPort->cancelAllTimers(); + itsTimerPort->setTimer(0.0); + } + break; + + case F_TIMER: { + // update PVSS. + LOG_TRACE_FLOW ("Updateing state to PVSS"); + itsOwnPropertySet->setValue(PN_HWM_RSP_CURRENT_ACTION, GCFPVString("initial")); + itsOwnPropertySet->setValue(PN_HWM_RSP_ERROR, GCFPVString("")); + + LOG_DEBUG_STR("Going to connect to the RSPDriver."); + TRAN (RSPMonitor::connect2RSP); + } + + case DP_SET: + break; + + case F_QUIT: + TRAN (RSPMonitor::finish_state); + break; + + default: + LOG_DEBUG_STR ("initial, DEFAULT"); + break; + } + + return (status); +} + + +// +// connect2RSP(event, port) +// +// Setup connection with RSPdriver +// +GCFEvent::TResult RSPMonitor::connect2RSP(GCFEvent& event, + GCFPortInterface& port) +{ + LOG_DEBUG_STR ("connect2RSP:" << eventName(event) << "@" << port.getName()); + + GCFEvent::TResult status = GCFEvent::HANDLED; + + switch (event.signal) { + case F_ENTRY: + // update PVSS + itsOwnPropertySet->setValue(PN_HWM_RSP_CURRENT_ACTION, GCFPVString("connecting")); + itsOwnPropertySet->setValue(PN_HWM_RSP_CONNECTED,GCFPVBool(false)); + itsRSPDriver->open(); // will result in F_CONN or F_DISCONN + break; + + case F_CONNECTED: + if (&port == itsRSPDriver) { + LOG_DEBUG ("Connected with RSPDriver, going to get the configuration"); + itsOwnPropertySet->setValue(PN_HWM_RSP_ERROR, GCFPVString("")); + itsOwnPropertySet->setValue(PN_HWM_RSP_CONNECTED,GCFPVBool(true)); + TRAN(RSPMonitor::askConfiguration); // go to next state. + } + break; + + case F_DISCONNECTED: + port.close(); + ASSERTSTR (&port == itsRSPDriver, + "F_DISCONNECTED event from port " << port.getName()); + LOG_DEBUG("Connection with RSPDriver failed, retry in 2 seconds"); + itsOwnPropertySet->setValue(PN_HWM_RSP_ERROR, GCFPVString("connection timeout")); + itsTimerPort->setTimer(2.0); + break; + + case DP_SET: + break; + + case F_QUIT: + TRAN (RSPMonitor::finish_state); + break; + + default: + LOG_DEBUG_STR ("connect2RSP, DEFAULT"); + break; + } + + return (status); +} + +// +// askConfiguration(event, port) +// +// Take subscription on clock modifications +// +GCFEvent::TResult RSPMonitor::askConfiguration(GCFEvent& event, + GCFPortInterface& port) +{ + LOG_DEBUG_STR ("askConfiguration:" << eventName(event) << "@" << port.getName()); + + GCFEvent::TResult status = GCFEvent::HANDLED; + + switch (event.signal) { + case F_ENTRY: { + itsOwnPropertySet->setValue(PN_HWM_RSP_CURRENT_ACTION,GCFPVString("asking configuration")); + RSPGetconfigEvent getconfig; + itsRSPDriver->send(getconfig); + } + break; + + case F_DISCONNECTED: + _disconnectedHandler(port); // might result in transition to connect2RSP + break; + + case RSP_GETCONFIGACK: { + RSPGetconfigackEvent ack(event); + + // calc size of the propertyset vectors + itsNrRCUs = ack.n_rcus; + itsNrRSPboards = ack.n_rspboards; + itsNrSubracks = (itsNrRSPboards/NR_RSPBOARDS_PER_SUBRACK) + + ((itsNrRSPboards%NR_RSPBOARDS_PER_SUBRACK) ? 1 : 0); + itsNrCabinets = (itsNrSubracks /NR_SUBRACKS_PER_CABINET) + + ((itsNrSubracks%NR_SUBRACKS_PER_CABINET) ? 1 : 0); + + // inform user + LOG_DEBUG(formatString("nr RCUs = %d",ack.n_rcus)); + LOG_DEBUG(formatString("nr RSPboards = %d",ack.max_rspboards)); + LOG_DEBUG(formatString("nr Subracks = %d", itsNrSubracks)); + LOG_DEBUG(formatString("nr Cabinets = %d", itsNrCabinets)); + LOG_DEBUG_STR("("<<itsNrRSPboards<<"/"<<NR_RSPBOARDS_PER_SUBRACK<<") + (("<<itsNrRSPboards<<"%"<<NR_RSPBOARDS_PER_SUBRACK<<") ? 1 : 0)"); + LOG_DEBUG_STR("("<<itsNrRSPboards<<"/"<<NR_RSPBOARDS_PER_SUBRACK<<") = " << itsNrRSPboards/NR_RSPBOARDS_PER_SUBRACK); + LOG_DEBUG_STR("("<<itsNrRSPboards<<"%"<<NR_RSPBOARDS_PER_SUBRACK<<") = " << itsNrRSPboards%NR_RSPBOARDS_PER_SUBRACK); + + // do some checks + if (itsNrRSPboards != (uint32)ack.max_rspboards) { + LOG_WARN_STR("RSPdriver only controls " << itsNrRSPboards << " of " << ack.max_rspboards + << " RSPboards, cannot monitor full station"); + } + if (itsNrRSPboards * NR_RCUS_PER_RSPBOARD != itsNrRCUs) { + LOG_INFO_STR("Station not fully equiped, only " << itsNrRCUs << " of " + << itsNrRSPboards * NR_RCUS_PER_RSPBOARD << "RCUs"); + } + + LOG_DEBUG ("Going to allocate the property-sets"); + itsOwnPropertySet->setValue(PN_HWM_RSP_ERROR,GCFPVString("")); + TRAN(RSPMonitor::createPropertySets); // go to next state. + } + break; + + case DP_SET: + break; + + case F_QUIT: + TRAN (RSPMonitor::finish_state); + break; + + default: + LOG_DEBUG_STR ("askConfiguration, DEFAULT"); + break; + } + + return (status); +} + + +// +// createPropertySets(event, port) +// +// Retrieve sampleclock from RSP driver +// +GCFEvent::TResult RSPMonitor::createPropertySets(GCFEvent& event, + GCFPortInterface& port) +{ + LOG_DEBUG_STR ("createPropertySets:" << eventName(event) << "@" << port.getName()); + + GCFEvent::TResult status = GCFEvent::HANDLED; + + switch (event.signal) { + + case F_ENTRY: { + itsOwnPropertySet->setValue(PN_HWM_RSP_CURRENT_ACTION,GCFPVString("create PropertySets")); + // resize vectors. + itsCabinets.resize(itsNrCabinets, 0); + itsSubracks.resize(itsNrSubracks, 0); + itsRSPs.resize (itsNrRSPboards, 0); + itsRCUs.resize (itsNrRCUs, 0); + + int32 cabinet (-1); + int32 subrack (-1); + int32 RSP (-1); + string cabinetNameMask (createPropertySetName(PSN_CABINET, getName())); + string subrackNameMask (createPropertySetName(PSN_SUB_RACK, getName())); + string rspboardNameMask(createPropertySetName(PSN_RSP_BOARD, getName())); + string rcuNameMask (createPropertySetName(PSN_RCU, getName())); + for (uint32 rcu = 0; rcu < itsNrRCUs; rcu++) { + // new cabinet? + if (rcu % (NR_RCUS_PER_CABINET) == 0) { + cabinet++; + string PSname(formatString(cabinetNameMask.c_str(), cabinet)); + itsCabinets[cabinet] = new RTDBPropertySet(PSname, PST_CABINET, PSAT_WO, this); + } + + // new subrack? + if (rcu % (NR_RCUS_PER_SUBRACK) == 0) { + subrack++; + string PSname(formatString(subrackNameMask.c_str(), cabinet, subrack)); + itsSubracks[subrack] = new RTDBPropertySet(PSname, PST_SUB_RACK, PSAT_WO, this); + } + + // new RSPboard? + if (rcu % (NR_RCUS_PER_RSPBOARD) == 0) { + RSP++; + string PSname(formatString(rspboardNameMask.c_str(), cabinet, subrack, RSP)); + itsRSPs[RSP] = new RTDBPropertySet(PSname, PST_RSP_BOARD, PSAT_WO, this); + } + + // allocate RCU PS + string PSname(formatString(rcuNameMask.c_str(), cabinet, subrack, RSP, rcu)); + itsRCUs[rcu] = new RTDBPropertySet(PSname, PST_RCU, PSAT_WO, this); + } + itsTimerPort->setTimer(5.0); // give database some time to finish the job + } + break; + + case F_TIMER: { + // database should be ready by now, check if allocation was succesfull + for (uint32 cabinet = 0; cabinet < itsNrCabinets; cabinet++) { + ASSERTSTR(itsCabinets[cabinet], "Allocation of PS for cabinet " << cabinet << " failed."); + } + for (uint32 subrack = 0; subrack < itsNrSubracks; subrack++) { + ASSERTSTR(itsSubracks[subrack], "Allocation of PS for subrack " << subrack << " failed."); + } + for (uint32 rsp = 0; rsp < itsNrRSPboards; rsp++) { + ASSERTSTR(itsRSPs[rsp], "Allocation of PS for rsp " << rsp << " failed."); + } + for (uint32 rcu = 0; rcu < itsNrRCUs; rcu++) { + ASSERTSTR(itsRCUs[rcu], "Allocation of PS for rcu " << rcu << " failed."); + } + LOG_DEBUG_STR("Allocation of all propertySets successfull, going to operational mode"); + itsOwnPropertySet->setValue(PN_HWM_RSP_ERROR,GCFPVString("")); + TRAN(RSPMonitor::askVersion); + } + break; + + case F_DISCONNECTED: + _disconnectedHandler(port); // might result in transition to connect2RSP + break; + + case DP_SET: + break; + + case F_QUIT: + TRAN (RSPMonitor::finish_state); + break; + + default: + LOG_DEBUG_STR ("createPropertySets, DEFAULT"); + break; + } + + return (status); +} + + +// +// askVersion(event, port) +// +// Set sampleclock from RSP driver +// +GCFEvent::TResult RSPMonitor::askVersion(GCFEvent& event, + GCFPortInterface& port) +{ + LOG_DEBUG_STR ("askVersion:" << eventName(event) << "@" << port.getName()); + + GCFEvent::TResult status = GCFEvent::HANDLED; + + switch (event.signal) { + + case F_ENTRY: { + itsOwnPropertySet->setValue(PN_HWM_RSP_CURRENT_ACTION,GCFPVString("getting version info")); + itsOwnPropertySet->setValue(PN_HWM_RSP_ERROR,GCFPVString("")); + RSPGetversionEvent getVersion; + getVersion.timestamp.setNow(); + getVersion.cache = true; + itsRSPDriver->send(getVersion); + } + break; + + case RSP_GETVERSIONACK: { + RSPGetversionackEvent ack(event); + if (ack.status != SUCCESS) { + LOG_ERROR_STR ("Failed to get the version information, trying other information"); + itsOwnPropertySet->setValue(PN_HWM_RSP_ERROR,GCFPVString("getVersion error")); + TRAN(RSPMonitor::askRSPinfo); // go to next state. + break; + } + + // move the information to the database. + string versionStr; + string DPEname; + for (uint32 rsp = 0; rsp < itsNrRSPboards; rsp++) { + // RSP board version + versionStr = formatString("%d.%d", ack.versions.bp()(rsp).rsp_version >> 4, + ack.versions.bp()(rsp).rsp_version & 0xF); + itsRSPs[rsp]->setValue(PN_RSP_VERSION, GCFPVString(versionStr), double(ack.timestamp)); + + // BP version + versionStr = formatString("%d.%d", ack.versions.bp()(rsp).fpga_maj, + ack.versions.bp()(rsp).fpga_min); + itsRSPs[rsp]->setValue(PN_RSP_BP_VERSION, GCFPVString(versionStr), double(ack.timestamp)); + + // APx versions + for (int ap = 0; ap < MEPHeader::N_AP; ap++) { + versionStr = formatString("%d.%d", ack.versions.ap()(rsp * MEPHeader::N_AP + ap).fpga_maj, + ack.versions.ap()(rsp * MEPHeader::N_AP + ap).fpga_min); + DPEname = formatString (PN_RSP_AP_VERSION_MASK, ap); + itsRSPs[rsp]->setValue(DPEname, GCFPVString(versionStr), double(ack.timestamp)); + } + } + + LOG_DEBUG_STR ("Version information updated, going to status information"); + itsOwnPropertySet->setValue(PN_HWM_RSP_ERROR,GCFPVString("")); + TRAN(RSPMonitor::askRSPinfo); // go to next state. + break; + } + + case F_DISCONNECTED: + _disconnectedHandler(port); // might result in transition to connect2RSP + break; + + case DP_SET: + break; + + case F_QUIT: + TRAN (RSPMonitor::finish_state); + break; + + default: + LOG_DEBUG_STR ("askVersion, DEFAULT"); + break; + } + + return (status); +} + + +// +// askRSPinfo(event, port) +// +// Set sampleclock from RSP driver +// +GCFEvent::TResult RSPMonitor::askRSPinfo(GCFEvent& event, + GCFPortInterface& port) +{ + LOG_DEBUG_STR ("askRSPinfo:" << eventName(event) << "@" << port.getName()); + + GCFEvent::TResult status = GCFEvent::HANDLED; + + switch (event.signal) { + + case F_ENTRY: { + itsOwnPropertySet->setValue(PN_HWM_RSP_CURRENT_ACTION,GCFPVString("updating RSP info")); + itsOwnPropertySet->setValue(PN_HWM_RSP_ERROR,GCFPVString("")); + RSPGetstatusEvent getStatus; + getStatus.timestamp.setNow(); + getStatus.cache = true; + getStatus.rspmask = bitset<MAX_N_RSPBOARDS>((1<<itsNrRSPboards)-1); + itsRSPDriver->send(getStatus); + } + break; + + case RSP_GETSTATUSACK: { + RSPGetstatusackEvent ack(event); + if (ack.status != SUCCESS) { + LOG_ERROR_STR ("Failed to get the status information, trying other information"); + itsOwnPropertySet->setValue(PN_HWM_RSP_ERROR,GCFPVString("getStatus error")); +#if 0 + TRAN(RSPMonitor::askRCUinfo); // go to next state. +#else + LOG_WARN ("SKIPPING RCU INFO FOR A MOMENT"); + TRAN(RSPMonitor::waitForNextCycle); // go to next state. +#endif + break; + } + + // move the information to the database. + string versionStr; + string DPEname; + for (uint32 rsp = 0; rsp < itsNrRSPboards; rsp++) { + BoardStatus bStat = ack.sysstatus.board()(rsp); + // board voltages + itsRSPs[rsp]->setValue(PN_RSP_VOLTAGE12, GCFPVDouble(double(bStat.rsp.voltage_1_2)*(2.5/192.0)), + double(ack.timestamp)); + itsRSPs[rsp]->setValue(PN_RSP_VOLTAGE25, GCFPVDouble(double(bStat.rsp.voltage_2_5)*(3.3/192.0)), + double(ack.timestamp)); + itsRSPs[rsp]->setValue(PN_RSP_VOLTAGE33, GCFPVDouble(double(bStat.rsp.voltage_3_3)*(5.0/192.0)), + double(ack.timestamp)); + + // Ethernet status + itsRSPs[rsp]->setValue(PN_RSP_ETHERNET_PACKETS_RECEIVED, GCFPVUnsigned(bStat.eth.nof_frames), + double(ack.timestamp)); + itsRSPs[rsp]->setValue(PN_RSP_ETHERNET_PACKETS_ERROR, GCFPVUnsigned(bStat.eth.nof_errors), + double(ack.timestamp)); + itsRSPs[rsp]->setValue(PN_RSP_ETHERNET_LAST_ERROR, GCFPVUnsigned(bStat.eth.last_error), + double(ack.timestamp)); + + // MEP status + itsRSPs[rsp]->setValue(PN_RSP_MEP_SEQNR, GCFPVUnsigned(bStat.mep.seqnr), + double(ack.timestamp)); + itsRSPs[rsp]->setValue(PN_RSP_MEP_ERROR, GCFPVUnsigned(bStat.mep.error), + double(ack.timestamp)); + + // BP status + itsRSPs[rsp]->setValue(PN_RSP_BP_TEMPERATURE, GCFPVDouble(double(bStat.rsp.bp_temp)), + double(ack.timestamp)); + // AP0 + itsRSPs[rsp]->setValue(PN_RSP_AP0_TEMPERATURE, GCFPVDouble(double(bStat.rsp.ap0_temp)), + double(ack.timestamp)); + itsRSPs[rsp]->setValue(PN_RSP_AP0_SYNC_SAMPLE_COUNT, GCFPVUnsigned(bStat.ap0_sync.sample_offset), + double(ack.timestamp)); + itsRSPs[rsp]->setValue(PN_RSP_AP0_SYNC_SYNC_COUNT, GCFPVUnsigned(bStat.ap0_sync.sample_offset)), + double(ack.timestamp); + itsRSPs[rsp]->setValue(PN_RSP_AP0_SYNC_ERROR_COUNT, GCFPVUnsigned(bStat.ap0_sync.ext_count)), + double(ack.timestamp); + + // AP1 + itsRSPs[rsp]->setValue(PN_RSP_AP1_TEMPERATURE, GCFPVDouble(double(bStat.rsp.ap1_temp)), + double(ack.timestamp)); + itsRSPs[rsp]->setValue(PN_RSP_AP1_SYNC_SAMPLE_COUNT, GCFPVUnsigned(bStat.ap1_sync.sample_offset)), + double(ack.timestamp); + itsRSPs[rsp]->setValue(PN_RSP_AP1_SYNC_SYNC_COUNT, GCFPVUnsigned(bStat.ap1_sync.sample_offset)), + double(ack.timestamp); + itsRSPs[rsp]->setValue(PN_RSP_AP1_SYNC_ERROR_COUNT, GCFPVUnsigned(bStat.ap1_sync.ext_count)), + double(ack.timestamp); + + // AP2 + itsRSPs[rsp]->setValue(PN_RSP_AP2_TEMPERATURE, GCFPVDouble(double(bStat.rsp.ap2_temp)), + double(ack.timestamp)); + itsRSPs[rsp]->setValue(PN_RSP_AP2_SYNC_SAMPLE_COUNT, GCFPVUnsigned(bStat.ap2_sync.sample_offset)), + double(ack.timestamp); + itsRSPs[rsp]->setValue(PN_RSP_AP2_SYNC_SYNC_COUNT, GCFPVUnsigned(bStat.ap2_sync.sample_offset)), + double(ack.timestamp); + itsRSPs[rsp]->setValue(PN_RSP_AP2_SYNC_ERROR_COUNT, GCFPVUnsigned(bStat.ap2_sync.ext_count)), + double(ack.timestamp); + + // AP3 + itsRSPs[rsp]->setValue(PN_RSP_AP3_TEMPERATURE, GCFPVDouble(double(bStat.rsp.ap3_temp)), + double(ack.timestamp)); + itsRSPs[rsp]->setValue(PN_RSP_AP3_SYNC_SAMPLE_COUNT, GCFPVUnsigned(bStat.ap3_sync.sample_offset)), + double(ack.timestamp); + itsRSPs[rsp]->setValue(PN_RSP_AP3_SYNC_SYNC_COUNT, GCFPVUnsigned(bStat.ap3_sync.sample_offset)), + double(ack.timestamp); + itsRSPs[rsp]->setValue(PN_RSP_AP3_SYNC_ERROR_COUNT, GCFPVUnsigned(bStat.ap3_sync.ext_count)), + double(ack.timestamp); + } // for all boards + + LOG_DEBUG_STR ("RSPboard information updated, going to RCU information"); + itsOwnPropertySet->setValue(PN_HWM_RSP_ERROR,GCFPVString("")); +#if 0 + TRAN(RSPMonitor::askRCUinfo); // go to next state. +#else + LOG_WARN ("SKIPPING RCU INFO FOR A MOMENT"); + TRAN(RSPMonitor::waitForNextCycle); // go to next state. +#endif + break; + } + + case F_DISCONNECTED: + _disconnectedHandler(port); // might result in transition to connect2RSP + break; + + case DP_SET: + break; + + case F_QUIT: + TRAN (RSPMonitor::finish_state); + break; + + default: + LOG_DEBUG_STR ("askRSPinfo, DEFAULT"); + break; + } + + return (status); +} + + +// +// askRCUinfo(event, port) +// +// Normal operation state. +// +GCFEvent::TResult RSPMonitor::askRCUinfo(GCFEvent& event, GCFPortInterface& port) +{ + if (eventName(event) != "DP_SET") { + LOG_DEBUG_STR ("askRCUinfo:" << eventName(event) << "@" << port.getName()); + } + + GCFEvent::TResult status = GCFEvent::HANDLED; + + switch (event.signal) { + case F_INIT: + break; + + case F_ENTRY: { + // update PVSS + itsOwnPropertySet->setValue(PN_HWM_RSP_CURRENT_ACTION,GCFPVString("updating RSP info")); + itsOwnPropertySet->setValue(PN_HWM_RSP_ERROR,GCFPVString("")); + RSPGetrcuEvent getStatus; + getStatus.timestamp.setNow(); + getStatus.cache = true; + getStatus.rcumask = bitset<MEPHeader::MAX_N_RCUS>((1<<itsNrRCUs)-1); + itsRSPDriver->send(getStatus); + break; + } + + case RSP_GETRCUACK: { + RSPGetrcuackEvent ack(event); + if (ack.status != SUCCESS) { + LOG_ERROR_STR ("Failed to get the RCU information, trying other information"); + itsOwnPropertySet->setValue(PN_HWM_RSP_ERROR,GCFPVString("getRCU error")); + TRAN(RSPMonitor::waitForNextCycle); // go to next state. + break; + } + + // move the information to the database. + string versionStr; + string DPEname; + for (uint32 rcu = 0; rcu < itsNrRCUs; rcu++) { + LOG_DEBUG_STR("Updating rcu " << rcu); + uint32 rawValue = ack.settings()(rcu).getRaw(); + // update all RCU variables + itsRCUs[rcu]->setValue(PN_RCU_DELAY, + GCFPVUnsigned(uint32(rawValue & DELAY_MASK)), + double(ack.timestamp)); + itsRCUs[rcu]->setValue(PN_RCU_INPUT_ENABLE, + GCFPVBool(rawValue & INPUT_ENABLE_MASK), + double(ack.timestamp)); + itsRCUs[rcu]->setValue(PN_RCU_LBL_ENABLE, + GCFPVBool(rawValue & LBL_ANT_POWER_MASK), double(ack.timestamp)); + itsRCUs[rcu]->setValue(PN_RCU_LBH_ENABLE, + GCFPVBool(rawValue & LBH_ANT_POWER_MASK), double(ack.timestamp)); + itsRCUs[rcu]->setValue(PN_RCU_HBA_ENABLE, + GCFPVBool(rawValue & HBA_ANT_POWER_MASK), double(ack.timestamp)); + itsRCUs[rcu]->setValue(PN_RCU_BAND_SEL_LBA_HBA, + GCFPVBool(rawValue & USE_LB_MASK), + double(ack.timestamp)); + itsRCUs[rcu]->setValue(PN_RCU_HBA_FILTER_SEL, + GCFPVUnsigned((rawValue & HB_FILTER_MASK) >> HB_FILTER_OFFSET), + double(ack.timestamp)); + itsRCUs[rcu]->setValue(PN_RCU_VL_ENABLE, + GCFPVBool(rawValue & LB_POWER_MASK), double(ack.timestamp)); + itsRCUs[rcu]->setValue(PN_RCU_VH_ENABLE, + GCFPVBool(rawValue & HB_POWER_MASK), double(ack.timestamp)); + itsRCUs[rcu]->setValue(PN_RCU_VDD_VCC_ENABLE, + GCFPVBool(rawValue & ADC_POWER_MASK), double(ack.timestamp)); + itsRCUs[rcu]->setValue(PN_RCU_BAND_SEL_LBL_LBH, + GCFPVBool(rawValue & USE_LBH_MASK), + double(ack.timestamp)); + itsRCUs[rcu]->setValue(PN_RCU_LBA_FILTER_SEL, + GCFPVUnsigned((rawValue & LB_FILTER_MASK) >> LB_FILTER_OFFSET), + double(ack.timestamp)); + itsRCUs[rcu]->setValue(PN_RCU_ATTENUATION, + GCFPVUnsigned(uint32((rawValue & ATT_MASK) >> ATT_OFFSET)), + double(ack.timestamp)); + } // for all boards + + LOG_DEBUG ("Updated all RCU information, waiting for next cycle"); + itsOwnPropertySet->setValue(PN_HWM_RSP_ERROR,GCFPVString("")); + TRAN(RSPMonitor::waitForNextCycle); // go to next state. + } + break; + + case F_DISCONNECTED: + _disconnectedHandler(port); // might result in transition to connect2RSP + break; + + case DP_SET: + break; + + case F_QUIT: + TRAN (RSPMonitor::finish_state); + break; + + default: + LOG_DEBUG("askRCUinfo, DEFAULT"); + break; + } + + return (status); +} + +// +// waitForNextCycle(event, port) +// +// Take subscription on clock modifications +// +GCFEvent::TResult RSPMonitor::waitForNextCycle(GCFEvent& event, + GCFPortInterface& port) +{ + if (eventName(event) != "DP_SET") { + LOG_DEBUG_STR ("waitForNextCycle:" << eventName(event) << "@" << port.getName()); } + + GCFEvent::TResult status = GCFEvent::HANDLED; + + switch (event.signal) { + case F_ENTRY: { + itsOwnPropertySet->setValue(PN_HWM_RSP_CURRENT_ACTION,GCFPVString("wait for next cycle")); + int waitTime = itsPollInterval - (time(0) % itsPollInterval); + if (waitTime == 0) { + waitTime = itsPollInterval; + } + itsTimerPort->cancelAllTimers(); + itsTimerPort->setTimer(double(waitTime)); + LOG_DEBUG_STR("Waiting " << waitTime << " seconds for next cycle"); + } + break; + + case F_DISCONNECTED: + _disconnectedHandler(port); // might result in transition to connect2RSP + break; + + case F_TIMER: { + TRAN(RSPMonitor::askRSPinfo); + } + break; + + case DP_SET: + break; + + case F_QUIT: + TRAN (RSPMonitor::finish_state); + break; + + default: + LOG_DEBUG_STR ("waitForNextCycle, DEFAULT"); + break; + } + + return (status); +} + + +// +// _disconnectedHandler(port) +// +void RSPMonitor::_disconnectedHandler(GCFPortInterface& port) +{ + port.close(); + if (&port == itsRSPDriver) { + LOG_DEBUG("Connection with RSPDriver failed, going to reconnect state"); + itsOwnPropertySet->setValue(PN_HWM_RSP_ERROR,GCFPVString("connection lost")); + TRAN (RSPMonitor::connect2RSP); + } +} + +// +// finish_state(event, port) +// +// Write controller state to PVSS +// +GCFEvent::TResult RSPMonitor::finish_state(GCFEvent& event, GCFPortInterface& port) +{ + LOG_DEBUG_STR ("finish_state:" << eventName(event) << "@" << port.getName()); + + GCFEvent::TResult status = GCFEvent::HANDLED; + + switch (event.signal) { + case F_INIT: + break; + + case F_ENTRY: { + // update PVSS + itsOwnPropertySet->setValue(string(PN_HWM_RSP_CURRENT_ACTION),GCFPVString("finished")); + itsOwnPropertySet->setValue(string(PN_HWM_RSP_ERROR),GCFPVString("")); + break; + } + + case DP_SET: + break; + + default: + LOG_DEBUG("finishing_state, DEFAULT"); + status = GCFEvent::NOT_HANDLED; + break; + } + return (status); +} + + +}; // StationCU +}; // LOFAR diff --git a/MAC/APL/StationCU/src/HardwareMonitor/RSPMonitor.h b/MAC/APL/StationCU/src/HardwareMonitor/RSPMonitor.h new file mode 100644 index 0000000000000000000000000000000000000000..bace721f9113755ae823b30dbc7aeb245551f07c --- /dev/null +++ b/MAC/APL/StationCU/src/HardwareMonitor/RSPMonitor.h @@ -0,0 +1,99 @@ +//# RSPMonitor.h: Monitors the RSP hardware. +//# +//# Copyright (C) 2006 +//# ASTRON (Netherlands Foundation for Research in Astronomy) +//# P.O.Box 2, 7990 AA Dwingeloo, The Netherlands, seg@astron.nl +//# +//# This program is free software; you can redistribute it and/or modify +//# it under the terms of the GNU General Public License as published by +//# the Free Software Foundation; either version 2 of the License, or +//# (at your option) any later version. +//# +//# This program is distributed in the hope that it will be useful, +//# but WITHOUT ANY WARRANTY; without even the implied warranty of +//# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +//# GNU General Public License for more details. +//# +//# You should have received a copy of the GNU General Public License +//# along with this program; if not, write to the Free Software +//# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +//# +//# $Id: RSPMonitor.h 10461 2007-08-23 22:44:03Z overeem $ + +#ifndef STATIONCU_RSP_MONITOR_H +#define STATIONCU_RSP_MONITOR_H + +//# Common Includes +#include <Common/lofar_string.h> +#include <Common/lofar_vector.h> + +//# GCF Includes +#include <GCF/RTDB/RTDB_PropertySet.h> +#include <GCF/TM/GCF_TCPPort.h> +#include <GCF/TM/GCF_TimerPort.h> +#include <GCF/TM/GCF_Task.h> +#include <GCF/TM/GCF_Event.h> + +// forward declaration + +namespace LOFAR { + namespace StationCU { + +using GCF::TM::GCFTimerPort; +using GCF::TM::GCFTCPPort; +using GCF::TM::GCFEvent; +using GCF::TM::GCFPortInterface; +using GCF::TM::GCFTask; +using GCF::RTDB::RTDBPropertySet; + + +class RSPMonitor : public GCFTask +{ +public: + explicit RSPMonitor(const string& cntlrName); + ~RSPMonitor(); + +private: + // During the initial state all connections with the other programs are made. + GCFEvent::TResult initial_state (GCFEvent& e, GCFPortInterface& p); + GCFEvent::TResult connect2RSP (GCFEvent& e, GCFPortInterface& p); + GCFEvent::TResult askConfiguration (GCFEvent& e, GCFPortInterface& p); + GCFEvent::TResult createPropertySets (GCFEvent& e, GCFPortInterface& p); + + GCFEvent::TResult askVersion (GCFEvent& e, GCFPortInterface& p); + GCFEvent::TResult askRSPinfo (GCFEvent& e, GCFPortInterface& p); + GCFEvent::TResult askRCUinfo (GCFEvent& e, GCFPortInterface& p); + GCFEvent::TResult waitForNextCycle (GCFEvent& e, GCFPortInterface& p); + + GCFEvent::TResult finish_state (GCFEvent& e, GCFPortInterface& p); + + // avoid defaultconstruction and copying + RSPMonitor(); + RSPMonitor(const RSPMonitor&); + RSPMonitor& operator=(const RSPMonitor&); + + void _disconnectedHandler(GCFPortInterface& port); + + // Data members + RTDBPropertySet* itsOwnPropertySet; + + GCFTimerPort* itsTimerPort; + + GCFTCPPort* itsRSPDriver; + + uint32 itsPollInterval; + + uint32 itsNrRCUs; + uint32 itsNrRSPboards; + uint32 itsNrSubracks; + uint32 itsNrCabinets; + + vector<RTDBPropertySet*> itsCabinets; + vector<RTDBPropertySet*> itsSubracks; + vector<RTDBPropertySet*> itsRSPs; + vector<RTDBPropertySet*> itsRCUs; +}; + + };//StationCU +};//LOFAR +#endif diff --git a/MAC/APL/StationCU/src/HardwareMonitor/StationPermDatapointDefs.h b/MAC/APL/StationCU/src/HardwareMonitor/StationPermDatapointDefs.h index f0084af75cc59c1cf7c866ba52a6ffbfa59244af..8de85dddd274a609e8b4697eded8523eea53b61c 100644 --- a/MAC/APL/StationCU/src/HardwareMonitor/StationPermDatapointDefs.h +++ b/MAC/APL/StationCU/src/HardwareMonitor/StationPermDatapointDefs.h @@ -1,14 +1,16 @@ -// This file was generated by create_db_files v1.0 on Fri Aug 24 08:34:27 UTC 2007 +// This file was generated by create_db_files v1.0 on Wed Nov 14 15:49:57 UTC 2007 // Cabinet #define PSN_CABINET "LOFAR_PIC_@cabinet@" #define PST_CABINET "Cabinet" -#define PN_CAB_FRONT_DOOR "front.door" -#define PN_CAB_FRONT_FAN "front.fan" -#define PN_CAB_FRONT_TEMPERATURE "front.temperature" -#define PN_CAB_BACK_DOOR "back.door" -#define PN_CAB_BACK_FAN "back.fan" -#define PN_CAB_BACK_TEMPERATURE "back.temperature" +#define PN_CAB_DOOR_OPEN "doorOpen" +#define PN_CAB_FAN "fan" +#define PN_CAB_INLET_TEMP "inletTemp" +#define PN_CAB_FRONT_TEMP "frontTemp" +#define PN_CAB_BACK_TEMP "backTemp" +#define PN_CAB_SETPOINT_TEMP "setpointTemp" +#define PN_CAB_AMBIENT_TEMP "ambientTemp" +#define PN_CAB_CONTROL_MODE "controlMode" // SubRack #define PSN_SUB_RACK "LOFAR_PIC_@cabinet@_@subrack@" @@ -44,9 +46,6 @@ #define PN_RSP_BP_STATE "BP.state" #define PN_RSP_BP_TEMPERATURE "BP.temperature" #define PN_RSP_BP_VERSION "BP.version" -#define PN_RSP_BP_SYNC_SAMPLE_COUNT "BP.SYNC.sampleCount" -#define PN_RSP_BP_SYNC_SYNC_COUNT "BP.SYNC.syncCount" -#define PN_RSP_BP_SYNC_ERROR_COUNT "BP.SYNC.errorCount" #define PN_RSP_AP0_STATE "AP0.state" #define PN_RSP_AP0_TEMPERATURE "AP0.temperature" #define PN_RSP_AP0_VERSION "AP0.version" @@ -90,9 +89,45 @@ #define PN_RCU_ATTENUATION "Attenuation" #define PN_RCU_NOF_OVERFLOW "nofOverflow" #define PN_RCU_ADC_STATISTICS_OVERFLOW "ADCStatistics.overflow" -#define PN_RCU_LBL_STATE "LBL.state" -#define PN_RCU_LBH_STATE "LBH.state" -#define PN_RCU_HBA_STATE "HBA.state" +#define PN_RCU_TBB_ERROR "TBB.error" +#define PN_RCU_TBB_MODE "TBB.mode" +#define PN_RCU_TBB_START_ADDR "TBB.startAddr" +#define PN_RCU_TBB_BUF_SIZE "TBB.bufSize" +#define PN_RCU_TRIGGER_STARTLEVEL "Trigger.startlevel" +#define PN_RCU_TRIGGER_BASELEVEL "Trigger.baselevel" +#define PN_RCU_TRIGGER_STOPLEVEL "Trigger.stoplevel" +#define PN_RCU_TRIGGER_FILTER "Trigger.filter" +#define PN_RCU_TRIGGER_WINDOW "Trigger.window" +#define PN_RCU_TRIGGER_COEFF0 "Trigger.coeff0" +#define PN_RCU_TRIGGER_COEFF1 "Trigger.coeff1" +#define PN_RCU_TRIGGER_COEFF2 "Trigger.coeff2" +#define PN_RCU_TRIGGER_COEFF3 "Trigger.coeff3" + +// TBBoard +#define PSN_TB_BOARD "LOFAR_PIC_@cabinet@_@subrack@_@TBBoard@" +#define PST_TB_BOARD "TBBoard" +#define PN_TBB_BOARDID "boardID" +#define PN_TBB_RAM_SIZE "RAMSize" +#define PN_TBB_SW_VERSION "SWVersion" +#define PN_TBB_BOARD_VERSION "boardVersion" +#define PN_TBB_TP_VERSION "TPVersion" +#define PN_TBB_MP0_VERSION "MP0Version" +#define PN_TBB_MP1_VERSION "MP1Version" +#define PN_TBB_MP2_VERSION "MP2Version" +#define PN_TBB_MP3_VERSION "MP3Version" +#define PN_TBB_VOLTAGE12 "voltage12" +#define PN_TBB_VOLTAGE25 "voltage25" +#define PN_TBB_VOLTAGE33 "voltage33" +#define PN_TBB_TEMPPCB "tempPCB" +#define PN_TBB_TEMPTP "tempTP" +#define PN_TBB_TEMPMP0 "tempMP0" +#define PN_TBB_TEMPMP1 "tempMP1" +#define PN_TBB_TEMPMP2 "tempMP2" +#define PN_TBB_TEMPMP3 "tempMP3" +#define PN_TBB_IMAGE_INFO_VERSION "imageInfo.version" +#define PN_TBB_IMAGE_INFO_WRITE_DATE "imageInfo.writeDate" +#define PN_TBB_IMAGE_INFO_TP_FILE "imageInfo.TPFile" +#define PN_TBB_IMAGE_INFO_MP_FILE "imageInfo.MPFile" // StationClock #define PSN_STATION_CLOCK "LOFAR_PIC_StationClock" @@ -109,8 +144,22 @@ #define PSN_STATION_CTRL "LOFAR_PermSW_StationCtrl" #define PST_STATION_CTRL "StationCtrl" +// TempCtrl +#define PSN_TEMP_CTRL "LOFAR_PermSW_TempCtrl" +#define PST_TEMP_CTRL "TempCtrl" +#define PN_TC_SETPOINT "setpoint" +#define PN_TC_AMBIENT_LOWEST_TEMP "ambient.lowestTemp" +#define PN_TC_AMBIENT_HIGHEST_TEMP "ambient.highestTemp" + // HardwareMonitor #define PSN_HARDWARE_MONITOR "LOFAR_PermSW_HardwareMonitor" #define PST_HARDWARE_MONITOR "HardwareMonitor" -#define PN_HWM_RSP_CONNECTED "RSPConnected" +#define PN_HWM_RSP_CONNECTED "RSP.connected" +#define PN_HWM_RSP_CURRENT_ACTION "RSP.currentAction" +#define PN_HWM_RSP_ERROR "RSP.error" +#define PN_HWM_RSP_LOG_MSG "RSP.logMsg" +#define PN_HWM_TBB_CONNECTED "TBB.connected" +#define PN_HWM_TBB_CURRENT_ACTION "TBB.currentAction" +#define PN_HWM_TBB_ERROR "TBB.error" +#define PN_HWM_TBB_LOG_MSG "TBB.logMsg" diff --git a/MAC/APL/StationCU/src/HardwareMonitor/TBB.dpl b/MAC/APL/StationCU/src/HardwareMonitor/TBB.dpl new file mode 100644 index 0000000000000000000000000000000000000000..a7b080ca62a0892873fbe951c8813b39bc993eec --- /dev/null +++ b/MAC/APL/StationCU/src/HardwareMonitor/TBB.dpl @@ -0,0 +1,26 @@ +// TBBoard +#define PSN_TB_BOARD "LOFAR_PIC_@cabinet@_@subrack@_@TBBoard@" +#define PST_TB_BOARD "TBBoard" +#define PN_TBB_BOARDID "boardID" +#define PN_TBB_RAM_SIZE "RAMsize" +#define PN_TBB_SW_VERSION "SWversion" +#define PN_TBB_BOARD_VERSION "boardVersion" +#define PN_TBB_TP_VERSION "TPversion" +#define PN_TBB_MP0VERSION "MP0version" +#define PN_TBB_MP1VERSION "MP1version" +#define PN_TBB_MP2VERSION "MP2version" +#define PN_TBB_MP3VERSION "MP3version" +#define PN_TBB_VOLTAGE12 "voltage12" +#define PN_TBB_VOLTAGE25 "voltage25" +#define PN_TBB_VOLTAGE33 "voltage33" +#define PN_TBB_TEMPPCB "tempPCB" +#define PN_TBB_TEMPTP "tempTP" +#define PN_TBB_TEMPMP0 "tempMP0" +#define PN_TBB_TEMPMP1 "tempMP1" +#define PN_TBB_TEMPMP2 "tempMP2" +#define PN_TBB_TEMPMP3 "tempMP3" +#define PN_TBB_IMAGE_INFO_VERSION "imageInfo.version" +#define PN_TBB_IMAGE_INFO_WRITE_DATE "imageInfo.writeDate" +#define PN_TBB_IMAGE_INFO_TP_FILE "imageInfo.TPfile" +#define PN_TBB_IMAGE_INFO_MP_FILE "imageInfo.MPfile" + diff --git a/MAC/APL/StationCU/src/HardwareMonitor/TBBMonitor.cc b/MAC/APL/StationCU/src/HardwareMonitor/TBBMonitor.cc new file mode 100644 index 0000000000000000000000000000000000000000..e89ddede2bc14e8c5d2ce182ab59165d85015ab9 --- /dev/null +++ b/MAC/APL/StationCU/src/HardwareMonitor/TBBMonitor.cc @@ -0,0 +1,757 @@ +//# TBBMonitor.cc: Implementation of the MAC Scheduler task +//# +//# Copyright (C) 2006 +//# ASTRON (Netherlands Foundation for Research in Astronomy) +//# P.O.Box 2, 7990 AA Dwingeloo, The Netherlands, seg@astron.nl +//# +//# This program is free software; you can redistribute it and/or modify +//# it under the terms of the GNU General Public License as published by +//# the Free Software Foundation; either version 2 of the License, or +//# (at your option) any later version. +//# +//# This program is distributed in the hope that it will be useful, +//# but WITHOUT ANY WARRANTY; without even the implied warranty of +//# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +//# GNU General Public License for more details. +//# +//# You should have received a copy of the GNU General Public License +//# along with this program; if not, write to the Free Software +//# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +//# +//# $Id: TBBMonitor.cc 10505 2007-09-07 17:14:57Z overeem $ +#include <lofar_config.h> +#include <Common/LofarLogger.h> + +#include <GCF/GCF_PVTypes.h> +#include <GCF/GCF_ServiceInfo.h> +#include <APL/APLCommon/ControllerDefines.h> +#include <APL/APLCommon/APLUtilities.h> +#include <APL/TBB_Protocol/TBB_Protocol.ph> +#include <GCF/RTDB/DP_Protocol.ph> +//#include <APL/APLCommon/StationInfo.h> +#include <signal.h> + +#include "TBBMonitor.h" +#include "RCUConstants.h" +#include "StationPermDatapointDefs.h" + +using namespace LOFAR::GCF::Common; +using namespace LOFAR::GCF::TM; +using namespace LOFAR::GCF::RTDB; +using namespace std; + +namespace LOFAR { + using namespace APLCommon; + namespace StationCU { + +// +// TBBMonitor() +// +TBBMonitor::TBBMonitor(const string& cntlrName) : + GCFTask ((State)&TBBMonitor::initial_state,cntlrName), + itsOwnPropertySet (0), + itsTimerPort (0), + itsTBBDriver (0), + itsPollInterval (10), + itsNrRCUs (0), + itsNrTBboards (0) +{ + LOG_TRACE_OBJ_STR (cntlrName << " construction"); + + // need port for timers. + itsTimerPort = new GCFTimerPort(*this, "TimerPort"); + + // prepare TCP port to TBBDriver. + itsTBBDriver = new GCFTCPPort (*this, MAC_SVCMASK_TBBDRIVER, + GCFPortInterface::SAP, TBB_PROTOCOL); + ASSERTSTR(itsTBBDriver, "Cannot allocate TCPport to TBBDriver"); + itsTBBDriver->setInstanceNr(0); + +} + + +// +// ~TBBMonitor() +// +TBBMonitor::~TBBMonitor() +{ + LOG_TRACE_OBJ_STR (getName() << " destruction"); + + if (itsTBBDriver) { + itsTBBDriver->close(); + delete itsTBBDriver; + } + + if (itsTimerPort) { + delete itsTimerPort; + } + + // ... +} + + +// +// initial_state(event, port) +// +// Setup connection with PVSS +// +GCFEvent::TResult TBBMonitor::initial_state(GCFEvent& event, GCFPortInterface& port) +{ + LOG_DEBUG_STR ("initial:" << eventName(event) << "@" << port.getName()); + + GCFEvent::TResult status = GCFEvent::HANDLED; + + switch (event.signal) { + case F_INIT: + break; + + case F_ENTRY: { + // Get access to my own propertyset. + LOG_DEBUG_STR ("Activating PropertySet " << PSN_HARDWARE_MONITOR); + itsTimerPort->setTimer(2.0); + itsOwnPropertySet = new RTDBPropertySet(PSN_HARDWARE_MONITOR, + PST_HARDWARE_MONITOR, + PSAT_WO, + this); + + } + break; + + case DP_CREATED: { + // NOTE: this function may be called DURING the construction of the PropertySet. + // Always exit this event in a way that GCF can end the construction. + DPCreatedEvent dpEvent(event); + LOG_DEBUG_STR("Result of creating " << dpEvent.DPname << " = " << dpEvent.result); + itsTimerPort->cancelAllTimers(); + itsTimerPort->setTimer(0.0); + } + break; + + case F_TIMER: { + // update PVSS. + LOG_TRACE_FLOW ("Updateing state to PVSS"); + itsOwnPropertySet->setValue(PN_HWM_TBB_CURRENT_ACTION, GCFPVString("initial")); + itsOwnPropertySet->setValue(PN_HWM_TBB_ERROR, GCFPVString("")); + + LOG_DEBUG_STR("Going to connect to the TBBDriver."); + TRAN (TBBMonitor::connect2TBB); + } + + case DP_SET: + break; + + case F_QUIT: + TRAN (TBBMonitor::finish_state); + break; + + default: + LOG_DEBUG_STR ("initial, DEFAULT"); + break; + } + + return (status); +} + + +// +// connect2TBB(event, port) +// +// Setup connection with TBBdriver +// +GCFEvent::TResult TBBMonitor::connect2TBB(GCFEvent& event, GCFPortInterface& port) +{ + LOG_DEBUG_STR ("connect2TBB:" << eventName(event) << "@" << port.getName()); + + GCFEvent::TResult status = GCFEvent::HANDLED; + + switch (event.signal) { + case F_ENTRY: + // update PVSS + itsOwnPropertySet->setValue(PN_HWM_TBB_CURRENT_ACTION, GCFPVString("connecting")); + itsOwnPropertySet->setValue(PN_HWM_TBB_CONNECTED,GCFPVBool(false)); + itsTBBDriver->open(); // will result in F_CONN or F_DISCONN + break; + + case F_CONNECTED: + if (&port == itsTBBDriver) { + LOG_DEBUG ("Connected with TBBDriver, going to get the configuration"); + itsOwnPropertySet->setValue(PN_HWM_TBB_ERROR, GCFPVString("")); + itsOwnPropertySet->setValue(PN_HWM_TBB_CONNECTED,GCFPVBool(true)); + TRAN(TBBMonitor::askConfiguration); // go to next state. + } + break; + + case F_DISCONNECTED: + port.close(); + ASSERTSTR (&port == itsTBBDriver, + "F_DISCONNECTED event from port " << port.getName()); + LOG_DEBUG("Connection with TBBDriver failed, retry in 2 seconds"); + itsOwnPropertySet->setValue(PN_HWM_TBB_ERROR, GCFPVString("connection timeout")); + itsTimerPort->setTimer(2.0); + break; + + case DP_SET: + break; + + case F_QUIT: + TRAN (TBBMonitor::finish_state); + break; + + default: + LOG_DEBUG_STR ("connect2TBB, DEFAULT"); + break; + } + + return (status); +} + +// +// askConfiguration(event, port) +// +// Take subscription on clock modifications +// +GCFEvent::TResult TBBMonitor::askConfiguration(GCFEvent& event, GCFPortInterface& port) +{ + LOG_DEBUG_STR ("askConfiguration:" << eventName(event) << "@" << port.getName()); + + GCFEvent::TResult status = GCFEvent::HANDLED; + + switch (event.signal) { + case F_ENTRY: { + itsOwnPropertySet->setValue(PN_HWM_TBB_CURRENT_ACTION,GCFPVString("asking configuration")); + TBBGetConfigEvent getconfig; + itsTBBDriver->send(getconfig); + } + break; + + case F_DISCONNECTED: + _disconnectedHandler(port); // might result in transition to connect2TBB + break; + + case TBB_GET_CONFIG_ACK: { + TBBGetConfigAckEvent ack(event); + + // calc size of the propertyset vectors + itsBoardMask = bitset<MAX_N_TBBBOARDS>(ack.active_boards_mask); + itsNrTBboards = ack.max_boards; + itsNrRCUs = itsNrTBboards * NR_RCUS_PER_TBBOARD; + + // inform user + LOG_DEBUG_STR("Active boards = " << itsBoardMask); + LOG_DEBUG(formatString("nr TBboards = %d", itsNrTBboards)); + + // do some checks + if (itsNrTBboards != itsBoardMask.count()) { + LOG_WARN_STR("Only " << itsBoardMask.count() << " of " << itsNrTBboards + << " TBboards are available."); + } + + LOG_DEBUG ("Going to allocate the property-sets"); + itsOwnPropertySet->setValue(PN_HWM_TBB_ERROR,GCFPVString("")); + TRAN (TBBMonitor::finish_state); + TRAN(TBBMonitor::createPropertySets); // go to next state. + } + break; + + case DP_SET: + break; + + case F_QUIT: + TRAN (TBBMonitor::finish_state); + break; + + default: + LOG_DEBUG_STR ("askConfiguration, DEFAULT"); + break; + } + + return (status); +} + + +// +// createPropertySets(event, port) +// +// Retrieve sampleclock from TBB driver +// +GCFEvent::TResult TBBMonitor::createPropertySets(GCFEvent& event, GCFPortInterface& port) +{ + LOG_DEBUG_STR ("createPropertySets:" << eventName(event) << "@" << port.getName()); + + GCFEvent::TResult status = GCFEvent::HANDLED; + + switch (event.signal) { + + case F_ENTRY: { + itsOwnPropertySet->setValue(PN_HWM_TBB_CURRENT_ACTION,GCFPVString("create PropertySets")); + // resize vectors. + itsTBBs.resize (itsNrTBboards, 0); + itsRCUs.resize (itsNrRCUs, 0); + + int32 cabinet (-1); + int32 subrack (-1); + int32 RSP (-1); + int32 TBB (-1); + string tbboardNameMask(createPropertySetName(PSN_TB_BOARD, getName())); + string rcuNameMask (createPropertySetName(PSN_RCU, getName())); + for (uint32 rcu = 0; rcu < itsNrRCUs; rcu++) { + // new cabinet? + if (rcu % (NR_RCUS_PER_CABINET) == 0) { + cabinet++; + } + + // new subrack? + if (rcu % (NR_RCUS_PER_SUBRACK) == 0) { + subrack++; + } + + // new TBboard? + if (rcu % (NR_RCUS_PER_TBBOARD) == 0) { + TBB++; + string PSname(formatString(tbboardNameMask.c_str(), cabinet, subrack, TBB)); + itsTBBs[TBB] = new RTDBPropertySet(PSname, PST_TB_BOARD, PSAT_WO, this); + } + + // new RSPboard? + if (rcu % (NR_RCUS_PER_RSPBOARD) == 0) { + RSP++; + } + + // allocate RCU PS + string PSname(formatString(rcuNameMask.c_str(), cabinet, subrack, RSP, rcu)); + itsRCUs[rcu] = new RTDBPropertySet(PSname, PST_RCU, PSAT_WO, this); + } + itsTimerPort->setTimer(5.0); // give database some time to finish the job + } + break; + + case F_TIMER: { + // database should be ready by now, check if allocation was succesfull + for (uint32 tbb = 0; tbb < itsNrTBboards; tbb++) { + ASSERTSTR(itsTBBs[tbb], "Allocation of PS for tbb " << tbb << " failed."); + } + for (uint32 rcu = 0; rcu < itsNrRCUs; rcu++) { + ASSERTSTR(itsRCUs[rcu], "Allocation of PS for rcu " << rcu << " failed."); + } + LOG_DEBUG_STR("Allocation of all propertySets successfull, going to operational mode"); + itsOwnPropertySet->setValue(PN_HWM_TBB_ERROR,GCFPVString("")); + TRAN(TBBMonitor::askVersion); + } + break; + + case F_DISCONNECTED: + _disconnectedHandler(port); // might result in transition to connect2TBB + break; + + case DP_SET: + break; + + case F_QUIT: + TRAN (TBBMonitor::finish_state); + break; + + default: + LOG_DEBUG_STR ("createPropertySets, DEFAULT"); + break; + } + + return (status); +} + + +// +// askVersion(event, port) +// +// Set sampleclock from TBB driver +// +GCFEvent::TResult TBBMonitor::askVersion(GCFEvent& event, GCFPortInterface& port) +{ + LOG_DEBUG_STR ("askVersion:" << eventName(event) << "@" << port.getName()); + + GCFEvent::TResult status = GCFEvent::HANDLED; + + switch (event.signal) { + + case F_ENTRY: { + itsOwnPropertySet->setValue(PN_HWM_TBB_CURRENT_ACTION,GCFPVString("getting version info")); + itsOwnPropertySet->setValue(PN_HWM_TBB_ERROR,GCFPVString("")); + TBBVersionEvent getVersion; + getVersion.boardmask = itsBoardMask.to_uint32(); + itsTBBDriver->send(getVersion); + } + break; + + case TBB_VERSION_ACK: { + TBBVersionAckEvent ack(event); + // move the information to the database. + string versionStr; + string DPEname; + for (uint32 tbb = 0; tbb < itsNrTBboards; tbb++) { + if (ack.status_mask[tbb] & TBB_SUCCESS) { + // TBB board version + versionStr = formatString("%d.%d", ack.swversion[tbb] / 10, ack.swversion[tbb] % 10); + itsTBBs[tbb]->setValue(PN_TBB_SW_VERSION, GCFPVString(versionStr)); + versionStr = formatString("%d.%d", ack.boardversion[tbb] / 10, ack.boardversion[tbb] % 10); + itsTBBs[tbb]->setValue(PN_TBB_BOARD_VERSION, GCFPVString(versionStr)); + itsTBBs[tbb]->setValue(PN_TBB_BOARDID, GCFPVUnsigned(ack.boardid[tbb])); + + // BP version + versionStr = formatString("%d.%d", ack.tpversion[tbb] / 10, ack.tpversion[tbb] % 10); + itsTBBs[tbb]->setValue(PN_TBB_TP_VERSION, GCFPVString(versionStr)); + + // MPx versions + versionStr = formatString("%d.%d", ack.mp0version[tbb] / 10, ack.mp0version[tbb] % 10); + itsTBBs[tbb]->setValue(PN_TBB_MP0_VERSION, GCFPVString(versionStr)); + versionStr = formatString("%d.%d", ack.mp1version[tbb] / 10, ack.mp1version[tbb] % 10); + itsTBBs[tbb]->setValue(PN_TBB_MP1_VERSION, GCFPVString(versionStr)); + versionStr = formatString("%d.%d", ack.mp2version[tbb] / 10, ack.mp2version[tbb] % 10); + itsTBBs[tbb]->setValue(PN_TBB_MP2_VERSION, GCFPVString(versionStr)); + versionStr = formatString("%d.%d", ack.mp3version[tbb] / 10, ack.mp3version[tbb] % 10); + itsTBBs[tbb]->setValue(PN_TBB_MP3_VERSION, GCFPVString(versionStr)); + } + else { // board in error set ?.? + itsTBBs[tbb]->setValue(PN_TBB_BOARDID, GCFPVUnsigned(0)); + itsTBBs[tbb]->setValue(PN_TBB_BOARD_VERSION, GCFPVString("?.?")); + itsTBBs[tbb]->setValue(PN_TBB_TP_VERSION, GCFPVString("?.?")); + itsTBBs[tbb]->setValue(PN_TBB_MP0_VERSION, GCFPVString("?.?")); + itsTBBs[tbb]->setValue(PN_TBB_MP1_VERSION, GCFPVString("?.?")); + itsTBBs[tbb]->setValue(PN_TBB_MP2_VERSION, GCFPVString("?.?")); + itsTBBs[tbb]->setValue(PN_TBB_MP3_VERSION, GCFPVString("?.?")); + } + } + + LOG_DEBUG_STR ("Version information updated, going to status information"); + itsOwnPropertySet->setValue(PN_HWM_TBB_ERROR,GCFPVString("")); + TRAN(TBBMonitor::askSizeInfo); // go to next state. + break; + } + + case F_DISCONNECTED: + _disconnectedHandler(port); // might result in transition to connect2TBB + break; + + case DP_SET: + break; + + case F_QUIT: + TRAN (TBBMonitor::finish_state); + break; + + default: + LOG_DEBUG_STR ("askVersion, DEFAULT"); + break; + } + + return (status); +} + +// +// askSizeInfo(event, port) +// +// Set sampleclock from TBB driver +// +GCFEvent::TResult TBBMonitor::askSizeInfo(GCFEvent& event, GCFPortInterface& port) +{ + LOG_DEBUG_STR ("askSizeInfo:" << eventName(event) << "@" << port.getName()); + + GCFEvent::TResult status = GCFEvent::HANDLED; + + switch (event.signal) { + + case F_ENTRY: { + itsOwnPropertySet->setValue(PN_HWM_TBB_CURRENT_ACTION,GCFPVString("getting version info")); + itsOwnPropertySet->setValue(PN_HWM_TBB_ERROR,GCFPVString("")); + TBBSizeEvent getSize; + getSize.boardmask = itsBoardMask.to_uint32(); + itsTBBDriver->send(getSize); + } + break; + + case TBB_SIZE_ACK: { + TBBSizeAckEvent ack(event); + // move the information to the database. + for (uint32 tbb = 0; tbb < itsNrTBboards; tbb++) { + if (ack.status_mask[tbb] & TBB_SUCCESS) { + itsTBBs[tbb]->setValue(PN_TBB_RAM_SIZE, GCFPVString(byteSize(ack.npages[tbb]*2048))); + } + else { // board in error set ?.? + itsTBBs[tbb]->setValue(PN_TBB_RAM_SIZE, GCFPVString("")); + } + } + + LOG_DEBUG_STR ("Size information updated, going to status information"); + itsOwnPropertySet->setValue(PN_HWM_TBB_ERROR,GCFPVString("")); + TRAN(TBBMonitor::askTBBinfo); // go to next state. + break; + } + + case F_DISCONNECTED: + _disconnectedHandler(port); // might result in transition to connect2TBB + break; + + case DP_SET: + break; + + case F_QUIT: + TRAN (TBBMonitor::finish_state); + break; + + default: + LOG_DEBUG_STR ("askSizeInfo, DEFAULT"); + break; + } + + return (status); +} + + +// +// askTBBinfo(event, port) +// +// Ask info about the TBB boards +// +GCFEvent::TResult TBBMonitor::askTBBinfo(GCFEvent& event, GCFPortInterface& port) +{ + LOG_DEBUG_STR ("askTBBinfo:" << eventName(event) << "@" << port.getName()); + + GCFEvent::TResult status = GCFEvent::HANDLED; + + switch (event.signal) { + + case F_ENTRY: { + itsOwnPropertySet->setValue(PN_HWM_TBB_CURRENT_ACTION,GCFPVString("updating TBB info")); + itsOwnPropertySet->setValue(PN_HWM_TBB_ERROR,GCFPVString("")); + TBBStatusEvent getStatus; + getStatus.boardmask = itsBoardMask.to_uint32(); + itsTBBDriver->send(getStatus); + } + break; + + case TBB_STATUS_ACK: { + TBBStatusAckEvent ack(event); + // move the information to the database. + string versionStr; + string DPEname; + for (uint32 tbb = 0; tbb < itsNrTBboards; tbb++) { + if (ack.status_mask[tbb] & TBB_SUCCESS) { + // board voltages + itsTBBs[tbb]->setValue(PN_TBB_VOLTAGE12, GCFPVDouble(double(ack.V12[tbb])*(2.5/192.0))); + itsTBBs[tbb]->setValue(PN_TBB_VOLTAGE25, GCFPVDouble(double(ack.V25[tbb])*(3.3/192.0))); + itsTBBs[tbb]->setValue(PN_TBB_VOLTAGE33, GCFPVDouble(double(ack.V33[tbb])*(5.0/192.0))); + // all temperatures + itsTBBs[tbb]->setValue(PN_TBB_TEMPPCB, GCFPVDouble(double(ack.Tpcb[tbb]))); + itsTBBs[tbb]->setValue(PN_TBB_TEMPTP, GCFPVDouble(double(ack.Ttp [tbb]))); + itsTBBs[tbb]->setValue(PN_TBB_TEMPMP0, GCFPVDouble(double(ack.Tmp0[tbb]))); + itsTBBs[tbb]->setValue(PN_TBB_TEMPMP1, GCFPVDouble(double(ack.Tmp1[tbb]))); + itsTBBs[tbb]->setValue(PN_TBB_TEMPMP2, GCFPVDouble(double(ack.Tmp2[tbb]))); + itsTBBs[tbb]->setValue(PN_TBB_TEMPMP3, GCFPVDouble(double(ack.Tmp3[tbb]))); + } + } // for all boards + + LOG_DEBUG_STR ("TBboard information updated, going to RCU information"); + itsOwnPropertySet->setValue(PN_HWM_TBB_ERROR,GCFPVString("")); + TRAN(TBBMonitor::askRCUinfo); // go to next state. + break; + } + + case F_DISCONNECTED: + _disconnectedHandler(port); // might result in transition to connect2TBB + break; + + case DP_SET: + break; + + case F_QUIT: + TRAN (TBBMonitor::finish_state); + break; + + default: + LOG_DEBUG_STR ("askTBBinfo, DEFAULT"); + break; + } + + return (status); +} + + +// +// askRCUinfo(event, port) +// +// Normal operation state. +// +GCFEvent::TResult TBBMonitor::askRCUinfo(GCFEvent& event, GCFPortInterface& port) +{ + if (eventName(event) != "DP_SET") { + LOG_DEBUG_STR ("askRCUinfo:" << eventName(event) << "@" << port.getName()); + } + + GCFEvent::TResult status = GCFEvent::HANDLED; + + switch (event.signal) { + case F_INIT: + break; + + case F_ENTRY: { + // update PVSS + itsOwnPropertySet->setValue(PN_HWM_TBB_CURRENT_ACTION,GCFPVString("updating TBB info")); + itsOwnPropertySet->setValue(PN_HWM_TBB_ERROR,GCFPVString("")); + TBBRcuInfoEvent getStatus; + itsTBBDriver->send(getStatus); + break; + } + + case TBB_RCU_INFO_ACK: { + TBBRcuInfoAckEvent ack(event); + + // move the information to the database. + for (uint32 rcu = 0; rcu < itsNrRCUs; rcu++) { + LOG_DEBUG_STR("Updating rcu " << rcu); + if (ack.rcu_status[rcu] & TBB_SUCCESS) { + // update all RCU variables + itsRCUs[rcu]->setValue(PN_RCU_TBB_ERROR, GCFPVBool(ack.rcu_status[rcu])), + itsRCUs[rcu]->setValue(PN_RCU_TBB_MODE, GCFPVString(TBBRCUstate(ack.rcu_state[rcu]))); + itsRCUs[rcu]->setValue(PN_RCU_TBB_START_ADDR, GCFPVString(formatString("0x%08d",ack.rcu_start_addr[rcu]))); + itsRCUs[rcu]->setValue(PN_RCU_TBB_BUF_SIZE, GCFPVString(byteSize(ack.rcu_pages[rcu]*2048))); + } + } // for all boards + + LOG_DEBUG ("Updated all RCU information, waiting for next cycle"); + itsOwnPropertySet->setValue(PN_HWM_TBB_ERROR,GCFPVString("")); + TRAN(TBBMonitor::waitForNextCycle); // go to next state. + } + break; + + case F_DISCONNECTED: + _disconnectedHandler(port); // might result in transition to connect2TBB + break; + + case DP_SET: + break; + + case F_QUIT: + TRAN (TBBMonitor::finish_state); + break; + + default: + LOG_DEBUG("askRCUinfo, DEFAULT"); + break; + } + + return (status); +} + +// +// waitForNextCycle(event, port) +// +// Take subscription on clock modifications +// +GCFEvent::TResult TBBMonitor::waitForNextCycle(GCFEvent& event, + GCFPortInterface& port) +{ + if (eventName(event) != "DP_SET") { + LOG_DEBUG_STR ("waitForNextCycle:" << eventName(event) << "@" << port.getName()); } + + GCFEvent::TResult status = GCFEvent::HANDLED; + + switch (event.signal) { + case F_ENTRY: { + itsOwnPropertySet->setValue(PN_HWM_TBB_CURRENT_ACTION,GCFPVString("wait for next cycle")); + int waitTime = itsPollInterval - (time(0) % itsPollInterval); + if (waitTime == 0) { + waitTime = itsPollInterval; + } + itsTimerPort->cancelAllTimers(); + itsTimerPort->setTimer(double(waitTime)); + LOG_DEBUG_STR("Waiting " << waitTime << " seconds for next cycle"); + } + break; + + case F_DISCONNECTED: + _disconnectedHandler(port); // might result in transition to connect2TBB + break; + + case F_TIMER: { + TRAN(TBBMonitor::askTBBinfo); + } + break; + + case DP_SET: + break; + + case F_QUIT: + TRAN (TBBMonitor::finish_state); + break; + + default: + LOG_DEBUG_STR ("waitForNextCycle, DEFAULT"); + break; + } + + return (status); +} + + +// +// _disconnectedHandler(port) +// +void TBBMonitor::_disconnectedHandler(GCFPortInterface& port) +{ + port.close(); + if (&port == itsTBBDriver) { + LOG_DEBUG("Connection with TBBDriver failed, going to reconnect state"); + itsOwnPropertySet->setValue(PN_HWM_TBB_ERROR,GCFPVString("connection lost")); + TRAN (TBBMonitor::connect2TBB); + } +} + +// +// finish_state(event, port) +// +// Write controller state to PVSS +// +GCFEvent::TResult TBBMonitor::finish_state(GCFEvent& event, GCFPortInterface& port) +{ + LOG_DEBUG_STR ("finish_state:" << eventName(event) << "@" << port.getName()); + + GCFEvent::TResult status = GCFEvent::HANDLED; + + switch (event.signal) { + case F_INIT: + break; + + case F_ENTRY: { + // update PVSS + itsOwnPropertySet->setValue(PN_HWM_TBB_CURRENT_ACTION,GCFPVString("finished")); + itsOwnPropertySet->setValue(PN_HWM_TBB_CONNECTED,GCFPVBool(false)); + itsOwnPropertySet->setValue(PN_HWM_TBB_ERROR,GCFPVString("")); + break; + } + + case DP_SET: + break; + + default: + LOG_DEBUG("finishing_state, DEFAULT"); + status = GCFEvent::NOT_HANDLED; + break; + } + return (status); +} + +// +// TBBRCUstate(char) +// +string TBBMonitor::TBBRCUstate(char stateCode) +{ + switch (stateCode) { + case 'A': return ("Allocated"); + case 'E': return ("Error"); + case 'F': return ("Free"); + case 'R': return ("Recording"); + case 'S': return ("Stopped"); + default: return ("Unknown"); + } +} + +}; // StationCU +}; // LOFAR diff --git a/MAC/APL/StationCU/src/HardwareMonitor/TBBMonitor.h b/MAC/APL/StationCU/src/HardwareMonitor/TBBMonitor.h new file mode 100644 index 0000000000000000000000000000000000000000..807affbb82d5a583368020e3aeb28758c8387dad --- /dev/null +++ b/MAC/APL/StationCU/src/HardwareMonitor/TBBMonitor.h @@ -0,0 +1,100 @@ +//# TBBMonitor.h: Monitors the TBB hardware. +//# +//# Copyright (C) 2006 +//# ASTRON (Netherlands Foundation for Research in Astronomy) +//# P.O.Box 2, 7990 AA Dwingeloo, The Netherlands, seg@astron.nl +//# +//# This program is free software; you can redistribute it and/or modify +//# it under the terms of the GNU General Public License as published by +//# the Free Software Foundation; either version 2 of the License, or +//# (at your option) any later version. +//# +//# This program is distributed in the hope that it will be useful, +//# but WITHOUT ANY WARRANTY; without even the implied warranty of +//# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +//# GNU General Public License for more details. +//# +//# You should have received a copy of the GNU General Public License +//# along with this program; if not, write to the Free Software +//# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +//# +//# $Id: TBBMonitor.h 10461 2007-08-23 22:44:03Z overeem $ + +#ifndef STATIONCU_TBB_MONITOR_H +#define STATIONCU_TBB_MONITOR_H + +//# Common Includes +#include <Common/lofar_string.h> +#include <Common/lofar_vector.h> +#include <Common/lofar_bitset.h> + +//# GCF Includes +#include <GCF/RTDB/RTDB_PropertySet.h> +#include <GCF/TM/GCF_TCPPort.h> +#include <GCF/TM/GCF_TimerPort.h> +#include <GCF/TM/GCF_Task.h> +#include <GCF/TM/GCF_Event.h> +#include <APL/TBB_Protocol/TBB_Protocol.ph> + +// forward declaration + +namespace LOFAR { + namespace StationCU { + +using GCF::TM::GCFTimerPort; +using GCF::TM::GCFTCPPort; +using GCF::TM::GCFEvent; +using GCF::TM::GCFPortInterface; +using GCF::TM::GCFTask; +using GCF::RTDB::RTDBPropertySet; + + +class TBBMonitor : public GCFTask +{ +public: + explicit TBBMonitor(const string& cntlrName); + ~TBBMonitor(); + +private: + // During the initial state all connections with the other programs are made. + GCFEvent::TResult initial_state (GCFEvent& e, GCFPortInterface& p); + GCFEvent::TResult connect2TBB (GCFEvent& e, GCFPortInterface& p); + GCFEvent::TResult askConfiguration (GCFEvent& e, GCFPortInterface& p); + GCFEvent::TResult createPropertySets (GCFEvent& e, GCFPortInterface& p); + + GCFEvent::TResult askVersion (GCFEvent& e, GCFPortInterface& p); + GCFEvent::TResult askSizeInfo (GCFEvent& e, GCFPortInterface& p); + GCFEvent::TResult askTBBinfo (GCFEvent& e, GCFPortInterface& p); + GCFEvent::TResult askRCUinfo (GCFEvent& e, GCFPortInterface& p); + GCFEvent::TResult waitForNextCycle (GCFEvent& e, GCFPortInterface& p); + + GCFEvent::TResult finish_state (GCFEvent& e, GCFPortInterface& p); + + // avoid defaultconstruction and copying + TBBMonitor(); + TBBMonitor(const TBBMonitor&); + TBBMonitor& operator=(const TBBMonitor&); + + void _disconnectedHandler(GCFPortInterface& port); + string TBBRCUstate(char stateCode) ; + + // Data members + RTDBPropertySet* itsOwnPropertySet; + + GCFTimerPort* itsTimerPort; + + GCFTCPPort* itsTBBDriver; + + uint32 itsPollInterval; + + uint32 itsNrRCUs; + uint32 itsNrTBboards; + bitset<MAX_N_TBBBOARDS> itsBoardMask; + + vector<RTDBPropertySet*> itsTBBs; + vector<RTDBPropertySet*> itsRCUs; +}; + + };//StationCU +};//LOFAR +#endif