diff --git a/MAC/APL/StationCU/configure.in b/MAC/APL/StationCU/configure.in index 1ec64241a2a7760cfdbb2eee1301cfb3c0c8d431..d0058c5bf7b6eb66c79312a8b037c641481081ca 100644 --- a/MAC/APL/StationCU/configure.in +++ b/MAC/APL/StationCU/configure.in @@ -55,6 +55,7 @@ dnl lofar_GENERAL lofar_COMPILETOOLS lofar_PVSS(1) +lofar_BLITZ lofar_INTERNAL(LCS/Common, common,, 1, Common/LofarTypes.h,,) lofar_INTERNAL(LCS/ACC/APS, aps,, 1, APS/ParameterSet.h,,) lofar_INTERNAL(SAS/OTDB, otdb,, 1, OTDB/OTDBconnection.h,,) @@ -62,17 +63,20 @@ lofar_INTERNAL(MAC/GCF/GCFCommon, gcfcommon,, 1, GCF/GCF_Defines.h,,) lofar_INTERNAL(MAC/GCF/TM, gcftm,, 1, GCF/TM/GCF_Task.h,,) lofar_INTERNAL(MAC/GCF/PAL, gcfpal,, 1, GCF/PAL/GCF_PVSSInfo.h,,) lofar_INTERNAL(MAC/APL/APLCommon, aplcommon,, 1, APL/APLCommon/APL_Defines.h,,) -lofar_INTERNAL(MAC/APL/PAC/BS_Protocol, BS_Protocol,, 1, APL/BS_Protocol/BS_Protocol.ph,,) -lofar_EXTERNAL(boost,1.32,boost/date_time/date.hpp, boost_date_time-gcc) -lofar_EXTERNAL(pqxx,2.5.5,pqxx/pqxx, pqxx) -lofar_EXTERNAL(pq,,libpq-fe.h, pq, /usr/local/pgsql) +dnl lofar_INTERNAL(MAC/APL/PAC/BS_Protocol, BS_Protocol,, 1, APL/BS_Protocol/BS_Protocol.ph,,) +lofar_INTERNAL(MAC/APL/PIC/RSP_Protocol, RSP_Protocol,, 1, APL/RSP_Protocol/RSP_Protocol.ph,,) +dnl lofar_EXTERNAL(boost,1.32,boost/date_time/date.hpp, boost_date_time-gcc) +dnl lofar_EXTERNAL(pqxx,2.5.5,pqxx/pqxx, pqxx) +dnl lofar_EXTERNAL(pq,,libpq-fe.h, pq, /usr/local/pgsql) dnl dnl Output Makefiles dnl AC_OUTPUT( src/Makefile +src/DigitalBoardControl/Makefile src/BeamControl/Makefile +src/CalibrationControl/Makefile Makefile StationCU.spec ) diff --git a/MAC/APL/StationCU/src/BeamControl/BeamControl.dpl b/MAC/APL/StationCU/src/BeamControl/BeamControl.dpl new file mode 100644 index 0000000000000000000000000000000000000000..b4a7bd01fafd76fd404c053206ccb45853464b60 --- /dev/null +++ b/MAC/APL/StationCU/src/BeamControl/BeamControl.dpl @@ -0,0 +1,11 @@ +# ascii dump of database + +# DpType +TypeName +BeamCntrl.BeamCntrl 1#1 + state 25#2 + error 25#3 + connected 23#4 + + + diff --git a/MAC/APL/StationCU/src/CalibrationControl/CalibrationControl.cc b/MAC/APL/StationCU/src/CalibrationControl/CalibrationControl.cc new file mode 100644 index 0000000000000000000000000000000000000000..5a5b48de31205290b6fbac475470d91782b5613a --- /dev/null +++ b/MAC/APL/StationCU/src/CalibrationControl/CalibrationControl.cc @@ -0,0 +1,654 @@ +//# CalibrationControl.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$ +#include <lofar_config.h> +#include <Common/LofarLogger.h> + +#include <boost/shared_array.hpp> +#include <APS/ParameterSet.h> +#include <GCF/GCF_PVTypes.h> +#include <GCF/PAL/GCF_PVSSInfo.h> +#include <GCF/Utils.h> +#include <GCF/GCF_ServiceInfo.h> +#include <GCF/Protocols/PA_Protocol.ph> +#include <APL/APLCommon/APL_Defines.h> +#include <APL/APLCommon/APLCommonExceptions.h> +#include <APL/APLCommon/Controller_Protocol.ph> +#include <APL/BS_Protocol/BS_Protocol.ph> + +#include "CalibrationControl.h" +#include "CalibrationControlDefines.h" + +using namespace LOFAR::GCF::Common; +using namespace LOFAR::GCF::TM; +using namespace LOFAR::GCF::PAL; +using namespace LOFAR::OTDB; +using namespace std; + +namespace LOFAR { + using namespace APLCommon; + using namespace ACC::APS; + namespace StationCU { + +// +// CalibrationControl() +// +CalibrationControl::CalibrationControl(const string& cntlrName) : + GCFTask ((State)&CalibrationControl::initial_state,cntlrName), + PropertySetAnswerHandlerInterface(), + itsPropertySetAnswer(*this), + itsPropertySet (), + itsPropertySetInitialized (false), + itsParentControl (0), + itsParentPort (0), + itsTimerPort (0), + itsCalServer (0), + itsState (CTState::NOSTATE) +{ + LOG_TRACE_OBJ_STR (cntlrName << " construction"); + + // Readin some parameters from the ParameterSet. + itsTreePrefix = globalParameterSet()->getString("prefix"); + itsInstanceNr = globalParameterSet()->getUint32(itsTreePrefix + ".instanceNr"); + itsStartTime = globalParameterSet()->getTime (itsTreePrefix + ".starttime"); + itsStopTime = globalParameterSet()->getTime (itsTreePrefix + ".stoptime"); + + // CalibrationControl specific parameters + // TODO: these values are delivered for every customer! + itsNyquistZone = globalParameterSet()->getInt16("nyquistZone"); + itsBandSelection = globalParameterSet()->getString("bandSelection"); + itsAntennaArray = globalParameterSet()->getString("antennaArray"); + itsRCUvector = globalParameterSet()->getUint16Vector("rcus"); + + // attach to child control task + itsChildControl = ChildControl::instance(); + itsChildPort = new GCFITCPort (*this, *itsChildControl, "childITCport", + GCFPortInterface::SAP, CONTROLLER_PROTOCOL); + ASSERTSTR(itsChildPort, "Cannot allocate ITCport for childcontrol"); + itsChildPort->open(); // will result in F_CONNECTED + + // attach to parent control task + itsParentControl = ParentControl::instance(); + itsParentPort = new GCFITCPort (*this, *itsParentControl, "ParentITCport", + GCFPortInterface::SAP, CONTROLLER_PROTOCOL); + ASSERTSTR(itsChildPort, "Cannot allocate ITCport for Parentcontrol"); + itsParentPort->open(); // will result in F_CONNECTED + + // need port for timers. + itsTimerPort = new GCFTimerPort(*this, "TimerPort"); + + // prepare TCP port to CalibrationServer. + itsCalServer = new GCFTCPPort (*this, MAC_SVCMASK_CALSERVER, + GCFPortInterface::SAP, CAL_PROTOCOL); + ASSERTSTR(itsCalServer, "Cannot allocate TCPport to CalServer"); + + // for debugging purposes + registerProtocol (CONTROLLER_PROTOCOL, CONTROLLER_PROTOCOL_signalnames); + registerProtocol (PA_PROTOCOL, PA_PROTOCOL_signalnames); + registerProtocol (CAL_PROTOCOL, CAL_PROTOCOL_signalnames); + + setState(CTState::CREATED); +} + + +// +// ~CalibrationControl() +// +CalibrationControl::~CalibrationControl() +{ + LOG_TRACE_OBJ_STR (getName() << " destruction"); + + if (itsPropertySet) { + itsPropertySet->setValue(string(PVSSNAME_FSM_STATE),GCFPVString("down")); + itsPropertySet->disable(); + } + + // ... +} + +// +// setState(CTstateNr) +// +void ObservationControl::setState(CTState::CTstateNr newState) +{ + itsState = newState; + + if (itsPropertySet) { + CTState cts; + itsPropertySet->setValue(string(PVSSNAME_FSM_STATE), + GCFPVString(cts.name(newState))); + } +} + + +// +// convertDirection(string) : int32 +// +int32 CalibrationControl::convertDirection(const string& typeName) +{ + if (typeName == "J2000") { return (1); } + if (typeName == "AZEL") { return (2); } + if (typeName == "LMN") { return (3); } + return (2); +} + +// +// convertBandSelection(string) : uint8 +// +uint8 CalibrationControl::convertBandSelection(const string& bandselection) +{ + if (bandselection == "LB_10_90") { + return(0xB9); + } + if (bandselection == "HB_110_190") { + return(0xC6); + } + if (bandselection == "HB_170_230") { + return(0xCE); + } + if (bandselection == "HB_210_250") { + return(0xD6); + } + + LOG_WARN_STR ("bandselection value '" << bandselection << + "' not recognized, using LB_10_90"); + return (0xB9); +} + +// +// propertySetsAvailable() +// +bool CalibrationControl::propertySetsAvailable() +{ + return (m_rcuFunctionalityMap.size() == m_n_rcus); +} + +// +// getRCUhardwareNr (propertyname) +// +int32 CalibrationControl::getRCUhardwareNr(const string& propName) +{ + // strip property and systemname, propertyset name remains + int posBegin = propName.find_first_of(":") + 1; + int posEnd = propName.find_last_of("."); + string propertySetName = propName.substr(posBegin,posEnd-posBegin); + + // search in property map. + TRCUMap::iterator it = m_rcuMap.begin(); + TRCUMap::iterator end = m_rcuMap.end(); + while (it != end) { + if (propertySetName == it->second->getScope()) { + return (it->first); + } + ++it; + } + + return (-1); +} + + +// +// handlePropertySetAnswer(answer) +// +void CalibrationControl::handlePropertySetAnswer(GCFEvent& answer) +{ + LOG_DEBUG_STR ("handlePropertySetAnswer:" << evtstr(answer)); + + switch(answer.signal) { + case F_MYPS_ENABLED: { + GCFPropSetAnswerEvent* pPropAnswer=static_cast<GCFPropSetAnswerEvent*>(&answer); + if (pPropAnswer->result != GCF_NO_ERROR) { + LOG_ERROR(formatString("%s : PropertySet %s NOT ENABLED", + getName().c_str(), pPropAnswer->pScope)); + } + // always let timer expire so main task will continue. + itsTimerPort->setTimer(0.0); + break; + } + + case F_VGETRESP: { + // check which property changed + GCFPropValueEvent* pPropAnswer=static_cast<GCFPropValueEvent*>(&answer); + + // check if it is a functionality + if(strstr(pPropAnswer->pPropName, PROPNAME_FUNCTIONALITY) != 0) { + // add the functionality state to the internal cache + int rcu = getRCUHardwareNr(pPropAnswer->pPropName); + if (rcu >= 0) { + bool functional = ((GCFPVBool*)pPropAnswer->pValue)->getValue(); + m_rcuFunctionalityMap[static_cast<uint16>(rcu)] = functional; + } + } + break; + } + + case F_VCHANGEMSG: { + GCFPropValueEvent* pPropAnswer=static_cast<GCFPropValueEvent*>(&answer); + + // check if it is a functionality + if (strstr(pPropAnswer->pPropName, PROPNAME_FUNCTIONALITY) != 0) { + LOG_DEBUG("functionality property changed"); + // add the functionality to the internal cache + int rcu = getRCUhardwareNr(pPropAnswer->pPropName); + if (rcu >= 0) { + bool functional = ((GCFPVBool*)pPropAnswer->pValue)->getValue(); + m_rcuFunctionalityMap[static_cast<uint16>(rcu)] = functional; + LOG_DEBUG(formatString("RCU %d functionality: %s", + rcu, (functional ? "true" : "false"))); + } + // TODO + if (getLogicalDeviceState() == LOGICALDEVICE_STATE_ACTIVE) { + // check functionality state of RCU's + if (!checkQuality()) { + suspend(LD_RESULT_LOW_QUALITY); + } + } + } + break; + } + +// case F_SUBSCRIBED: +// case F_UNSUBSCRIBED: +// case F_PS_CONFIGURED: +// case F_EXTPS_LOADED: +// case F_EXTPS_UNLOADED: +// case F_MYPS_ENABLED: +// case F_MYPS_DISABLED: +// case F_VGETRESP: +// case F_VCHANGEMSG: +// case F_SERVER_GONE: + + default: + break; + } +} + + +// +// initial_state(event, port) +// +// Setup all connections. +// +GCFEvent::TResult CalibrationControl::initial_state(GCFEvent& event, + GCFPortInterface& port) +{ + LOG_DEBUG_STR ("initial:" << evtstr(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 ("Activating my PropertySet"); + string propSetName = formatString(CS_PROPSET_NAME, itsInstanceNr); + itsPropertySet = GCFMyPropertySetPtr(new GCFMyPropertySet(propSetName.c_str(), + CS_PROPSET_TYPE, + PS_CAT_TEMPORARY, + &itsPropertySetAnswer)); + itsPropertySet->enable(); + // Wait for timer that is set in PropertySetAnswer on ENABLED event + } + break; + + case F_TIMER: + if (!itsPropertySetInitialized) { + itsPropertySetInitialized = true; + + // update PVSS. + LOG_TRACE_FLOW ("Updateing state to PVSS"); + itsPropertySet->setValue(string(PVSSNAME_FSM_STATE),GCFPVString("initial")); + itsPropertySet->setValue(string(PVSSNAME_FSM_ERROR),GCFPVString("")); + + // Start ParentControl task + LOG_DEBUG ("Enabling ParentControl task"); + itsParentPort = itsParentControl->registerTask(this); + + // Open connection with CalServer + LOG_DEBUG ("Trying to connect to CalibrationServer"); + itsCalServer->open(); // will result in F_CONN or F_DISCONN + } + else { + // its the disconnected timer + itsCalServer->open(); // will result in F_CONN or F_DISCONN + } + break; + + case F_CONNECTED: + ASSERTSTR (&port == itsCalServer, + "F_CONNECTED event from port " << port.getName()); + itsTimerPort->cancelAllTimers(); + LOG_DEBUG ("Connected with CalServer, going to operational state"); + TRAN(CalibrationControl::active_state); // go to next state. + break; + + case F_DISCONNECTED: + port.close(); + ASSERTSTR (&port == itsCalServer, + "F_DISCONNECTED event from port " << port.getName()); + LOG_DEBUG("Connection with CalServer failed, retry in 2 seconds"); + itsTimerPort.setTimer(2.0); + break; + + default: + LOG_DEBUG_STR ("initial, default"); + status = GCFEvent::NOT_HANDLED; + break; + } + return (status); +} + + +// +// active_state(event, port) +// +// Normal operation state. +// +GCFEvent::TResult CalibrationControl::active_state(GCFEvent& event, GCFPortInterface& port) +{ + LOG_DEBUG_STR ("active:" << evtstr(event) << "@" << port.getName()); + + GCFEvent::TResult status = GCFEvent::HANDLED; + + switch (event.signal) { + case F_INIT: + break; + + case F_ENTRY: { + // update PVSS + itsPropertySet->setValue(string(PVSSNAME_FSM_STATE),GCFPVString("active")); + itsPropertySet->setValue(string(PVSSNAME_FSM_ERROR),GCFPVString("")); + + loadPVSSpropertySets(); // of all RCU boards + // this taes a while so + itsPropAvailTimer = itsTimerPort.setTimer(3.0); // check over 3 seconds + break; + } + + case F_ACCEPT_REQ: + break; + + case F_CONNECTED: + ASSERTSTR (&port == itsCalServer, + "F_CONNECTED event from port " << port.getNam()); + itsTimerPort->cancelAllTimers(); + LOG_DEBUG ("Reconnected with CalServer"); + // TODO: resend all claimes. + break; + + case F_DISCONNECTED: + port.close(); + ASSERTSTR (&port == itsCalServer, + "F_DISCONNECTED event from port " << port.getNam()); + LOG_DEBUG("Connection with CalServer failed, retry in 2 seconds"); + itsTimerPort.setTimer(2.0); + break; + + case F_TIMER: { + GCFTimerEvent& timerEvent=static_cast<GCFTimerEvent&>(event); + if (timerEvent.id == itsPropSetAvailTimer) { + if (propertySetsAvailable()) { + LOG_DEBUG("PVSS propertySet are active."); + itsPropAvailTimer = 0; + } + else { + itsPropAvailTimer = itsTimerPort.setTimer(1.0); // check again later + } + } + else { + LOG_DEBUG ("Trying to reconnect to CalServer"); + itsCalServer->open(); // will result in F_CONN or F_DISCONN + } + break; + } + + // -------------------- EVENTS RECEIVED FROM PARENT CONTROL -------------------- + case CONTROL_CONNECT: { + CONTROLConnectEvent msg(event); + LOG_DEBUG_STR("Received CONNECT(" << msg.cntlrName << ")"); + setState(CTState::CONNECTED); + CONTROLConnectedEvent answer; + answer.cntlrName = msg.cntlrName; + port.send(answer); + break; + } + + case CONTROL_SCHEDULED: { + CONTROLScheduledEvent msg(event); + LOG_DEBUG_STR("Received SCHEDULED(" << msg.cntlrName << ")"); + // TODO: do something usefull with this information! + break; + } + + case CONTROL_CLAIM: { + CONTROLClaimEvent msg(event); + CONTROLClaimedEvent answer; + answer.cntlrName = msg.cntlrName; + LOG_DEBUG_STR("Received CLAIM(" << msg.cntlrName << ")"); + setState(CTState::CLAIM); + if (claimResources()) { + LOG_DEBUG_STR (msg.cntlrName << ":resources claimed successful"); + setState(CTState::CLAIMED); + answer.result = CT_RESULT_SUCCESS; + } + else { + LOG_ERROR_STR (msg.cntlrName << + ":failed to claim resources, staying in idle mode"); + setSTate(CTState::CONNECTED); + answer.result = CT_RESULT_CLAIM_FAILED; + } + itsParentPort.send(answer); + break; + } + + case CONTROL_PREPARE: { + CONTROLPrepareEvent msg(event); + LOG_DEBUG_STR("Received PREPARE(" << msg.cntlrName << ")"); + setState(CTState::PREPARE); + startCalServer(); // will result in CAL_STARTACK event + break; + } + + case CONTROL_RESUME: { + CONTROLResumeEvent msg(event); + LOG_DEBUG_STR("Received RESUME(" << msg.cntlrName << ")"); + setState(CTState::ACTIVE); + // TODO: do something here? + CONTROLResumedEvent answer; + answer.cntlrName = msg.cntlrName; + port.send(answer); + break; + } + + case CONTROL_SUSPEND: { + CONTROLSuspendEvent msg(event); + LOG_DEBUG_STR("Received SUSPEND(" << msg.cntlrName << ")"); + setState(CTState::SUSPENDED); + // TODO: do something here? + CONTROLSuspendedEvent answer; + answer.cntlrName = msg.cntlrName; + port.send(answer); + break; + } + + case CONTROL_RELEASE: { + CONTROLReleaseEvent msg(event); + LOG_DEBUG_STR("Received RELEASED(" << msg.cntlrName << ")"); + setState(CTState::RELEASE); + stopCalServer(event); // will result in CAL_STOPACK event + break; + } + + // -------------------- EVENTS RECEIVED FROM CALSERVER -------------------- + + case CAL_STARTACK: + CALStartEvent ack(event); + CONTROLPreparedEvent answer; + answer.cntlrName = ack.cntlrName; + if (ack.status == SUCCESS) { + LOG_DEBUG ("Start of CalServer was succesful"); + setState(CTState::PREPARED); + answer.result = CT_RESULT_SUCCESS; + } + else { + LOG_ERROR("Start of calibration failed, staying in CLAIMED mode"); + setState(CTState::CLAIMED); + answer.result = CT_RESULT_START_FAILED; + } + itsParentPort->send(); + break; + + case CAL_STOPACK: { + CALStopackEvent ack(event); + CONTROLReleasedEvent answer; + answer.cntlrName = msg.cntlrName; + if (ack.status == SUCCESS) { + LOG_DEBUG ("Calserver successfully stopped"); + setState(CTState::RELEASED); + answer.result = CT_RESULT_SUCCESS; + } + else { + LOG_ERROR("Stop of calibration failed, going to SUSPENDED mode"); + setState(CT::State::SUSPENDED); + answer.result = CT_RESULT_CALSTOP_FAILED; + } + itsParentPort->send(answer); + break; + } + + default: + LOG_DEBUG("active_state, default"); + status = GCFEvent::NOT_HANDLED; + break; + } + + return (status); +} + + +// +// claimResources() +// +bool CalibrationControl::claimResources() +{ + // claim the resources: + ResourceAllocator::TRcuSubset rcuSubset; + for (TRCUMap::iterator it = m_rcuMap.begin(); it != m_rcuMap.end(); ++it) { + rcuSubset.set(it->first); + } + uint8 rcuControl = getRcuControlValue(itsBandSelection); + + if(!_getResourceAllocator()->claimSRG(shared_from_this(), + _getPriority(), + rcuSubset, + nyquistZone, + rcuControl)) { + errorCode = LD_RESULT_LOW_PRIORITY; + return (false); + } + + _getResourceAllocator()->logSRGallocation(); + return (true); +} + +// +// loadPVSSpropertySets +// +void CalibrationControl::loadPVSSpropertySets() +{ + // load propertysets for the rcus + try { + for(vector<uint16>::iterator it = rcuVector.begin(); + it != rcuVector.end(); ++it) { + char scopeString[300]; + int rackRelNr,subRackRelNr,boardRelNr,apRelNr,rcuRelNr; + getRCURelNumbers((*it),rackRelNr,subRackRelNr,boardRelNr,apRelNr,rcuRelNr); + sprintf(scopeString,SCOPE_PIC_RackN_SubRackN_BoardN_APN_RCUN_LFA,rackRelNr,subRackRelNr,boardRelNr,apRelNr,rcuRelNr); + + boost::shared_ptr<GCFExtPropertySet> propSetPtr(new GCFExtPropertySet(scopeString,TYPE_LCU_PIC_LFA,&m_propertySetAnswer)); + propSetPtr->load(); + propSetPtr->subscribeProp(string(PROPNAME_FUNCTIONALITY)); + propSetPtr->requestValue(string(PROPNAME_FUNCTIONALITY)); + m_rcuMap[(*it)]=propSetPtr; + } + } + catch(Exception &e) { + LOG_FATAL(formatString("Error claiming SRG: %s",e.message().c_str())); + } +} + +// +// startCalServer +// +void CalibrationControl::startCalServer() +{ + // send CALStartEvent + LOG_DEBUG ("Sending CALSTART to CAL server"); + CALStartEvent calStartEvent; + calStartEvent.name = getName(); + calStartEvent.parent = itsAntennaArray; + calStartEvent.nyquist_zone = itsNyquistZone; + calStartEvent.rcucontrol.value = convertBandSelection(itsBandSelection); + + calStartEvent.subset.reset(); // reset every bit + for (TRCUMap::iterator it = m_rcuMap.begin(); it != m_rcuMap.end(); ++it) { + calStartEvent.subset.set(it->first); + } + + itsCalServer->send(calStartEvent); +} + + +// +// stopCalServer() +// +void CalibrationControl::stopCalServer() +{ + // send CALStopEvent + LOG_DEBUG ("Sending CALSTOP to CAL server"); + CALStopEvent calStopEvent; + calStopEvent.name = getName(); + itsCalServer->send(calStopEvent); + + itsResourceAllocator->releaseSRG(shared_from_this()); // TODO + itsResourceAllocator->logSRGallocation(); +} + +// +// _connectedHandler(port) +// +void CalibrationControl::_connectedHandler(GCFPortInterface& port) +{ +} + +// +// _disconnectedHandler(port) +// +void CalibrationControl::_disconnectedHandler(GCFPortInterface& port) +{ + port.close(); +} + + +}; // StationCU +}; // LOFAR diff --git a/MAC/APL/StationCU/src/CalibrationControl/CalibrationControl.conf.in b/MAC/APL/StationCU/src/CalibrationControl/CalibrationControl.conf.in new file mode 100644 index 0000000000000000000000000000000000000000..a92957c18ce62d80f87bec0b8500f109d6a9d311 --- /dev/null +++ b/MAC/APL/StationCU/src/CalibrationControl/CalibrationControl.conf.in @@ -0,0 +1,11 @@ +# new setup +prefix = Observation0 + +Observation0.instanceNr = 0 +Observation0.starttime = 0 +Observation0.stoptime = 1 + +# next parameters are optional, defaultvalues are shown +#ChildControl.StartupRetryInterval = 10s +#ChildControl.MaxStartupRetry = 5 + diff --git a/MAC/APL/StationCU/src/CalibrationControl/CalibrationControl.h b/MAC/APL/StationCU/src/CalibrationControl/CalibrationControl.h new file mode 100644 index 0000000000000000000000000000000000000000..127f407c16a0cd78ab94b9314aef66f297a15804 --- /dev/null +++ b/MAC/APL/StationCU/src/CalibrationControl/CalibrationControl.h @@ -0,0 +1,138 @@ +//# CalibrationControl.h: Controller for the CalServer +//# +//# 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$ + +#ifndef CALIBRATIONCONTROL_H +#define CALIBRATIONCONTROL_H + +//# Includes +#include <boost/shared_ptr.hpp> + +//# GCF Includes +#include <GCF/PAL/GCF_MyPropertySet.h> +#include <GCF/TM/GCF_Port.h> +#include <GCF/TM/GCF_ITCPort.h> +#include <GCF/TM/GCF_TimerPort.h> +#include <GCF/TM/GCF_Task.h> +#include <GCF/TM/GCF_Event.h> + +//# local includes +#include <APL/APLCommon/PropertySetAnswerHandlerInterface.h> +#include <APL/APLCommon/PropertySetAnswer.h> +#include <APL/APLCommon/APLCommonExceptions.h> +#include <APL/APLCommon/Controller_Protocol.ph> +#include <APL/APLCommon/ChildControl.h> +#include <APL/APLCommon/ParentControl.h> +#include <APL/APLCommon/CTState.h> + +//# Common Includes +#include <Common/lofar_string.h> +#include <Common/lofar_vector.h> +#include <Common/LofarLogger.h> + +//# ACC Includes +#include <APS/ParameterSet.h> + +// forward declaration + +namespace LOFAR { + namespace StationCU { + +using GCF::TM::GCFTimerPort; +using GCF::TM::GCFITCPort; +using GCF::TM::GCFPort; +using GCF::TM::GCFEvent; +using GCF::TM::GCFPortInterface; +using GCF::TM::GCFTask; + + +class CalibrationControl : public GCFTask, + APLCommon::PropertySetAnswerHandlerInterface +{ +public: + explicit CalibrationControl(const string& cntlrName); + ~CalibrationControl(); + + // PropertySetAnswerHandlerInterface method + virtual void handlePropertySetAnswer(GCFEvent& answer); + + // During the initial state all connections with the other programs are made. + GCFEvent::TResult initial_state (GCFEvent& e, + GCFPortInterface& p); + + // Normal control mode. + GCFEvent::TResult active_state (GCFEvent& e, + GCFPortInterface& p); + +private: + // avoid defaultconstruction and copying + CalibrationControl(); + CalibrationControl(const CalibrationControl&); + CalibrationControl& operator=(const CalibrationControl&); + + void _connectedHandler(GCFPortInterface& port); + void _disconnectedHandler(GCFPortInterface& port); + boost::shared_ptr<ACC::APS::ParameterSet> + readCalParameters (OTDB::treeIDType ObsTreeID); + + typedef boost::shared_ptr<GCF::PAL::GCFMyPropertySet> GCFMyPropertySetPtr; + + APLCommon::PropertySetAnswer itsPropertySetAnswer; + GCFMyPropertySetPtr itsPropertySet; + bool itsPropertySetInitialized; + +#if 0 + // Administration of the CalibrationControllers + typedef struct { + OTDB::treeIDType treeID; // tree in the OTDB + GCFTCPPort* port; // TCP connection with controller + uint16 state; // state the controller has + } ObsCntlr_t; + + // Map with all active CalibrationControllers. + map<GCFTCPPort*, ObsCntlr_t> itsObsCntlrMap; + vector<GCFTCPPort*> itsObsCntlrPorts; +#endif + + // pointer to parent control task + ParentControl* itsParentControl; + GCFITCPort* itsParentPort; + + GCFTimerPort* itsTimerPort; + + GCFTCPPort* itsCalServer; + + CTState::CTstateNr itsState; + + // ParameterSet variables + string itsTreePrefix; + uint32 itsInstanceNr; + time_t itsStartTime; + time_t itsStopTime; + + int16 itsNyquistZone; + string itsBandSelection; + vector<uint16> itsRCUvector; +}; + + };//StationCU +};//LOFAR +#endif diff --git a/MAC/APL/StationCU/src/CalibrationControl/CalibrationControl.log_prop.in b/MAC/APL/StationCU/src/CalibrationControl/CalibrationControl.log_prop.in new file mode 100644 index 0000000000000000000000000000000000000000..de2893d6d48d7510b293e3c7f0c1541e6591d831 --- /dev/null +++ b/MAC/APL/StationCU/src/CalibrationControl/CalibrationControl.log_prop.in @@ -0,0 +1,20 @@ +# add your custom loggers and appenders here +# + +log4cplus.rootLogger=DEBUG, STDOUT, FILE + +log4cplus.logger.TRC=TRACE2 +log4cplus.additivity.TRC=FALSE + +log4cplus.appender.STDOUT=log4cplus::ConsoleAppender +log4cplus.appender.STDOUT.layout=log4cplus::PatternLayout +log4cplus.appender.STDOUT.layout.ConversionPattern=%x %D{%d-%m-%y %H:%M:%S.%q} %-5p %c{9} - %m [%.25l]%n +log4cplus.appender.STDOUT.logToStdErr=true + +log4cplus.appender.FILE=log4cplus::RollingFileAppender +log4cplus.appender.FILE.File=../log/CalibrationControl.log +log4cplus.appender.FILE.MaxFileSize=5MB +log4cplus.appender.FILE.MaxBackupIndex=5 +log4cplus.appender.FILE.layout=log4cplus::PatternLayout +log4cplus.appender.FILE.layout.ConversionPattern=%x %D{%d-%m-%y %H:%M:%S.%q} %-5p %c{3} - %m [%.25l]%n + diff --git a/MAC/APL/StationCU/src/CalibrationControl/CalibrationControlDefines.h b/MAC/APL/StationCU/src/CalibrationControl/CalibrationControlDefines.h new file mode 100644 index 0000000000000000000000000000000000000000..47dc57bb18fb525c96cff1b71c3e2edbecdecfee --- /dev/null +++ b/MAC/APL/StationCU/src/CalibrationControl/CalibrationControlDefines.h @@ -0,0 +1,42 @@ +//# CalibrationControlDefines.h: preprocessor definitions of various constants +//# +//# Copyright (C) 2002-2003 +//# 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$ + +#ifndef CALIBRATIONCONTROLDEFINES_H +#define CALIBRATIONCONTROLDEFINES_H + +namespace LOFAR { + namespace StationCU { + +#define CC_TASKNAME "CalCtrl" + +#define CC_PROPSET_NAME "LOFAR_ObsSW_ObsCtrl%d_CalCtrl" +#define CC_PROPSET_TYPE "CalCtrl" + +// next lines should be defined somewhere in Common. +#define PVSSNAME_FSM_STATE "state" +#define PVSSNAME_FSM_ERROR "error" + + +}; // MCU +}; // LOFAR + +#endif diff --git a/MAC/APL/StationCU/src/CalibrationControl/CalibrationControlMain.cc b/MAC/APL/StationCU/src/CalibrationControl/CalibrationControlMain.cc new file mode 100644 index 0000000000000000000000000000000000000000..f2769b8e54752e388dcfc4d5241b3da1a178f0d0 --- /dev/null +++ b/MAC/APL/StationCU/src/CalibrationControl/CalibrationControlMain.cc @@ -0,0 +1,46 @@ +//# CalibrationControlMain.cc: Main entry for the CalibrationControl controller. +//# +//# 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$ +//# +#include <lofar_config.h> +#include <Common/LofarLogger.h> + +#include "CalibrationControl.h" + +using namespace LOFAR::GCF::TM; +using namespace LOFAR::StationCU; + +int main(int argc, char* argv[]) +{ + // args: cntlrname, parentHost, parentService + GCFTask::init(argc, argv); + + ParentControl* pc = ParentControl::instance(); + pc->start(); // make initial transition + + CalibrationControl cc(argv[1]); + cc.start(); // make initial transition + + GCFTask::run(); + + return 0; +} + diff --git a/MAC/APL/StationCU/src/CalibrationControl/Makefile.am b/MAC/APL/StationCU/src/CalibrationControl/Makefile.am new file mode 100644 index 0000000000000000000000000000000000000000..85281fa0386b4ee0a0d05cece57e0981652fb387 --- /dev/null +++ b/MAC/APL/StationCU/src/CalibrationControl/Makefile.am @@ -0,0 +1,46 @@ +bin_PROGRAMS = CalibrationControl + +CalibrationControl_CPPFLAGS = -Wno-deprecated \ + -fmessage-length=0 \ + -fdiagnostics-show-location=once + +CalibrationControl_SOURCES = ResourceAllocation.cc \ + CalibrationControl.cc \ + CalibrationControlMain.cc + +CalibrationControl_LDADD = $(LOFAR_DEPEND) +CalibrationControl_DEPENDENCIES = $(LOFAR_DEPEND) + +NOINSTHDRS = ResourceAllocation.h \ + CalibrationControl.h \ + CalibrationControlDefines.h + +INSTHDRS = + +pkginclude_HEADERS = $(NOINSTHDRS) $(INSTHDRS) + +DOCHDRS = $(pkginclude_HEADERS) $(BUILT_SOURCES) + +EXTRA_DIST = $(configfiles_DATA) $(sysconf_DATA) + +#in case of make install these files will be copied to the bindir beside the test apps +configfilesdir=$(bindir) +configfiles_DATA = +#customPrepPVSSDB.ctl + +sysconf_DATA = CalibrationControl.conf \ + CalibrationControl.log_prop + +%.log_prop: %.log_prop.in + cp $< $@ + +%.conf: %.conf.in + cp $< $@ + +%.ctl: %.ctl.in + cp $< $@ + +clean-local: + rm -f *.ph + +include $(top_srcdir)/Makefile.common diff --git a/MAC/APL/StationCU/src/DigitalBoardControl/DigitalBoardControl.cc b/MAC/APL/StationCU/src/DigitalBoardControl/DigitalBoardControl.cc new file mode 100644 index 0000000000000000000000000000000000000000..813fb3a59a4514729c3f732d7ce50e43bd608879 --- /dev/null +++ b/MAC/APL/StationCU/src/DigitalBoardControl/DigitalBoardControl.cc @@ -0,0 +1,593 @@ +//# DigitalBoardControl.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$ +#include <lofar_config.h> +#include <Common/LofarLogger.h> + +#include <boost/shared_array.hpp> +#include <APS/ParameterSet.h> +#include <GCF/GCF_PVTypes.h> +#include <GCF/PAL/GCF_PVSSInfo.h> +#include <GCF/Utils.h> +#include <GCF/GCF_ServiceInfo.h> +#include <GCF/Protocols/PA_Protocol.ph> +#include <APL/APLCommon/APL_Defines.h> +#include <APL/APLCommon/APLCommonExceptions.h> +#include <APL/APLCommon/Controller_Protocol.ph> +#include <APL/RSP_Protocol/RSP_Protocol.ph> + +#include "DigitalBoardControl.h" +#include "DigitalBoardControlDefines.h" + +using namespace LOFAR::GCF::Common; +using namespace LOFAR::GCF::TM; +using namespace LOFAR::GCF::PAL; +using namespace std; + +namespace LOFAR { + using namespace APLCommon; + using namespace ACC::APS; + namespace StationCU { + +// +// DigitalBoardControl() +// +DigitalBoardControl::DigitalBoardControl(const string& cntlrName) : + GCFTask ((State)&DigitalBoardControl::initial_state,cntlrName), + PropertySetAnswerHandlerInterface(), + itsPropertySetAnswer(*this), + itsPropertySet (), + itsPropertySetInitialized (false), +// itsParentControl (0), +// itsParentPort (0), + itsTimerPort (0), + itsRSPDriver (0) +{ + LOG_TRACE_OBJ_STR (cntlrName << " construction"); + + // Readin some parameters from the ParameterSet. + itsTreePrefix = globalParameterSet()->getString("prefix"); + itsInstanceNr = globalParameterSet()->getUint32(itsTreePrefix + ".instanceNr"); + + // attach to parent control task +// itsParentControl = ParentControl::instance(); +// itsParentPort = new GCFITCPort (*this, *itsParentControl, "ParentITCport", +// GCFPortInterface::SAP, CONTROLLER_PROTOCOL); +// ASSERTSTR(itsParentPort, "Cannot allocate ITCport for Parentcontrol"); +// itsParentPort->open(); // will result in F_CONNECTED + + // need port for timers. + itsTimerPort = new GCFTimerPort(*this, "TimerPort"); + + // prepare TCP port to BeamServer. + itsRSPDriver = new GCFTCPPort (*this, MAC_SVCMASK_RSPDRIVER, + GCFPortInterface::SAP, RSP_PROTOCOL); + ASSERTSTR(itsRSPDriver, "Cannot allocate TCPport to RSPDriver"); + itsRSPDriver->setInstanceNr(itsInstanceNr); + + // for debugging purposes + registerProtocol (CONTROLLER_PROTOCOL, CONTROLLER_PROTOCOL_signalnames); + registerProtocol (PA_PROTOCOL, PA_PROTOCOL_signalnames); + registerProtocol (RSP_PROTOCOL, RSP_PROTOCOL_signalnames); + +} + + +// +// ~DigitalBoardControl() +// +DigitalBoardControl::~DigitalBoardControl() +{ + LOG_TRACE_OBJ_STR (getName() << " destruction"); + + cancelSubscription(); // tell RSPdriver to stop sending updates. + + if (itsPropertySet) { + itsPropertySet->setValue(string(PVSSNAME_FSM_STATE),GCFPVString("down")); + itsPropertySet->disable(); + } + + // ... +} + + +// +// handlePropertySetAnswer(answer) +// +void DigitalBoardControl::handlePropertySetAnswer(GCFEvent& answer) +{ + LOG_DEBUG_STR ("handlePropertySetAnswer:" << evtstr(answer)); + + switch(answer.signal) { + case F_MYPS_ENABLED: { + GCFPropSetAnswerEvent* pPropAnswer=static_cast<GCFPropSetAnswerEvent*>(&answer); + if(pPropAnswer->result != GCF_NO_ERROR) { + LOG_ERROR(formatString("%s : PropertySet %s NOT ENABLED", + getName().c_str(), pPropAnswer->pScope)); + } + // always let timer expire so main task will continue. + itsTimerPort->setTimer(0.0); + break; + } + + case F_PS_CONFIGURED: { + GCFConfAnswerEvent* pConfAnswer=static_cast<GCFConfAnswerEvent*>(&answer); + if(pConfAnswer->result == GCF_NO_ERROR) { + LOG_DEBUG(formatString("%s : apc %s Loaded", + getName().c_str(), pConfAnswer->pApcName)); + //apcLoaded(); + } + else { + LOG_ERROR(formatString("%s : apc %s NOT LOADED", + getName().c_str(), pConfAnswer->pApcName)); + } + break; + } + + case F_VGETRESP: + case F_VCHANGEMSG: { + // check which property changed + GCFPropValueEvent* pPropAnswer=static_cast<GCFPropValueEvent*>(&answer); + if (strstr(pPropAnswer->pPropName, DB_PROP_CLOCK) != 0) { + itsClock = (static_cast<const GCFPVInteger*>(pPropAnswer->pValue))->getValue(); + sendClockSetting(); + } + break; + } + +// case F_SUBSCRIBED: +// case F_UNSUBSCRIBED: +// case F_PS_CONFIGURED: +// case F_EXTPS_LOADED: +// case F_EXTPS_UNLOADED: +// case F_MYPS_ENABLED: +// case F_MYPS_DISABLED: +// case F_VGETRESP: +// case F_VCHANGEMSG: +// case F_SERVER_GONE: + + default: + break; + } +} + + +// +// initial_state(event, port) +// +// Setup connection with PVSS +// +GCFEvent::TResult DigitalBoardControl::initial_state(GCFEvent& event, + GCFPortInterface& port) +{ + LOG_DEBUG_STR ("initial:" << evtstr(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 ("Activating PropertySets"); + string propSetName = formatString(DB_PROPSET_NAME, itsInstanceNr); + itsPropertySet = GCFMyPropertySetPtr(new GCFMyPropertySet(propSetName.c_str(), + DB_PROPSET_TYPE, + PS_CAT_PERM_AUTOLOAD, + &itsPropertySetAnswer)); + itsPropertySet->enable(); + + // TODO: load station property set containing the systemClock setting. + + // Wait for timer that is set in PropertySetAnswer on ENABLED event + } + break; + + case F_TIMER: + if (!itsPropertySetInitialized) { + itsPropertySetInitialized = true; + + // update PVSS. + LOG_TRACE_FLOW ("Updateing state to PVSS"); + itsPropertySet->setValue(PVSSNAME_FSM_STATE,GCFPVString("initial")); + itsPropertySet->setValue(PVSSNAME_FSM_ERROR,GCFPVString("")); + itsPropertySet->setValue(DB_PROP_CONNECTED, GCFPVBool(false)); + + // Start ParentControl task +// LOG_DEBUG ("Enabling ParentControl task"); +// itsParentPort = itsParentControl->registerTask(this); + + LOG_DEBUG ("Going to connect state"); + TRAN(DigitalBoardControl::connect_state); // go to next state. + } + break; + + case F_CONNECTED: + break; + + case F_DISCONNECTED: + break; + + default: + LOG_DEBUG_STR ("initial, default"); + status = GCFEvent::NOT_HANDLED; + break; + } + return (status); +} + + +// +// connect_state(event, port) +// +// Setup connection with RSPdriver +// +GCFEvent::TResult DigitalBoardControl::connect_state(GCFEvent& event, + GCFPortInterface& port) +{ + LOG_DEBUG_STR ("connect:" << evtstr(event) << "@" << port.getName()); + + GCFEvent::TResult status = GCFEvent::HANDLED; + + switch (event.signal) { + case F_INIT: + break; + + case F_ENTRY: + case F_TIMER: + itsPropertySet->setValue(PVSSNAME_FSM_STATE, GCFPVString("connecting")); + itsPropertySet->setValue(DB_PROP_CONNECTED, GCFPVBool(false)); + itsSubscription = 0; + itsRSPDriver->open(); // will result in F_CONN or F_DISCONN + break; + + case F_CONNECTED: + ASSERTSTR (&port == itsRSPDriver, + "F_CONNECTED event from port " << port.getName()); + + LOG_DEBUG ("Connected with RSPDriver, going to subscription state"); + itsPropertySet->setValue(PVSSNAME_FSM_ERROR, GCFPVString("")); + TRAN(DigitalBoardControl::subscribe_state); // 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"); + itsPropertySet->setValue(PVSSNAME_FSM_ERROR, GCFPVString("connection timeout")); + itsTimerPort->setTimer(2.0); + break; + + default: + LOG_DEBUG_STR ("connect, default"); + status = GCFEvent::NOT_HANDLED; + break; + } + + return (status); +} + +// +// subscribe_state(event, port) +// +// Take subscription on clock modifications +// +GCFEvent::TResult DigitalBoardControl::subscribe_state(GCFEvent& event, + GCFPortInterface& port) +{ + LOG_DEBUG_STR ("subscribe:" << evtstr(event) << "@" << port.getName()); + + GCFEvent::TResult status = GCFEvent::HANDLED; + + switch (event.signal) { + case F_INIT: + break; + + case F_ENTRY: + case F_TIMER: + itsPropertySet->setValue(PVSSNAME_FSM_STATE,GCFPVString("subscribe on clock")); + requestSubscription(); // will result in RSP_SUBCLOCKACK; + break; + + case F_DISCONNECTED: + _disconnectedHandler(port); // might result in transition to connect_state + break; + + case RSP_SUBCLOCKACK: { + RSPSubclockackEvent ack(event); + if (ack.status != SUCCESS) { + LOG_WARN ("Could not get subscribtion on clock, retry in 2 seconds"); + itsPropertySet->setValue(PVSSNAME_FSM_ERROR, GCFPVString("subscribe failed")); + itsTimerPort->setTimer(2.0); + break; + } + + itsSubscription = ack.handle; + + LOG_DEBUG ("Subscription successful, going to retrieve state"); + itsPropertySet->setValue(PVSSNAME_FSM_ERROR,GCFPVString("")); + TRAN(DigitalBoardControl::retrieve_state); // go to next state. + } + break; + + default: + LOG_DEBUG_STR ("subscribe, default"); + status = GCFEvent::NOT_HANDLED; + break; + } + + return (status); +} + + +// +// retrieve_state(event, port) +// +// Retrieve sampleclock from RSP driver +// +GCFEvent::TResult DigitalBoardControl::retrieve_state(GCFEvent& event, + GCFPortInterface& port) +{ + LOG_DEBUG_STR ("retrieve:" << evtstr(event) << "@" << port.getName()); + + GCFEvent::TResult status = GCFEvent::HANDLED; + + switch (event.signal) { + case F_INIT: + break; + + case F_ENTRY: + case F_TIMER: + itsPropertySet->setValue(PVSSNAME_FSM_STATE,GCFPVString("retrieve clock")); + requestClockSetting(); // will result in RSP_GETCLOCKACK; + break; + + case F_DISCONNECTED: + _disconnectedHandler(port); // might result in transition to connect_state + break; + + case RSP_GETCLOCKACK: { + RSPGetclockackEvent ack(event); + if (ack.status != SUCCESS) { + LOG_WARN ("Could not retrieve clocksetting of RSPDriver, retry in 2 seconds"); + itsPropertySet->setValue(PVSSNAME_FSM_ERROR, GCFPVString("getclock failed")); + itsTimerPort->setTimer(2.0); + break; + } + itsPropertySet->setValue(PVSSNAME_FSM_ERROR,GCFPVString("")); + + if (ack.clock != itsClock) { + LOG_INFO_STR ("StationClock is " << ack.clock << ", required clock is " << itsClock << ", changing StationClock"); + LOG_DEBUG ("Going to setClock state"); + TRAN(DigitalBoardControl::setClock_state); + } + else { + LOG_INFO_STR ("StationClock is " << ack.clock << ", required clock is " << itsClock << ", no action required"); + + LOG_DEBUG ("Going to operational state"); + TRAN(DigitalBoardControl::active_state); // go to next state. + } + break; + } + + default: + LOG_DEBUG_STR ("retrieve, default"); + status = GCFEvent::NOT_HANDLED; + break; + } + + return (status); +} + + +// +// setClock_state(event, port) +// +// Set sampleclock from RSP driver +// +GCFEvent::TResult DigitalBoardControl::setClock_state(GCFEvent& event, + GCFPortInterface& port) +{ + LOG_DEBUG_STR ("setClock:" << evtstr(event) << "@" << port.getName()); + + GCFEvent::TResult status = GCFEvent::HANDLED; + + switch (event.signal) { + case F_INIT: + break; + + case F_ENTRY: + case F_TIMER: + itsPropertySet->setValue(PVSSNAME_FSM_STATE,GCFPVString("set clock")); + sendClockSetting(); // will result in RSP_SETCLOCKACK; + break; + + case F_DISCONNECTED: + _disconnectedHandler(port); // might result in transition to connect_state + break; + + case RSP_SETCLOCKACK: { + RSPSetclockackEvent ack(event); + if (ack.status != SUCCESS) { + LOG_ERROR_STR ("Clock could not be set to " << itsClock << + ", retry in 5 seconds."); + itsPropertySet->setValue(PVSSNAME_FSM_ERROR,GCFPVString("clockset error")); + itsTimerPort->setTimer(5.0); + break; + } + LOG_INFO_STR ("StationClock is set to " << itsClock << ", going to operational state"); + itsPropertySet->setValue(PVSSNAME_FSM_ERROR,GCFPVString("")); + TRAN(DigitalBoardControl::active_state); // go to next state. + break; + } + + default: + LOG_DEBUG_STR ("setClock, default"); + status = GCFEvent::NOT_HANDLED; + break; + } + + return (status); +} + + +// +// active_state(event, port) +// +// Normal operation state. +// +GCFEvent::TResult DigitalBoardControl::active_state(GCFEvent& event, GCFPortInterface& port) +{ + LOG_DEBUG_STR ("active:" << evtstr(event) << "@" << port.getName()); + + GCFEvent::TResult status = GCFEvent::HANDLED; + + switch (event.signal) { + case F_INIT: + break; + + case F_ENTRY: { + // update PVSS + itsPropertySet->setValue(PVSSNAME_FSM_STATE,GCFPVString("active")); + itsPropertySet->setValue(PVSSNAME_FSM_ERROR,GCFPVString("")); + break; + } + + case F_ACCEPT_REQ: + break; + + case F_CONNECTED: + break; + + case F_DISCONNECTED: + _disconnectedHandler(port); // might result in transition to connect_state + break; + + case F_TIMER: + break; + + case RSP_UPDCLOCK: { + RSPUpdclockEvent updateEvent(event); + if (updateEvent.status != SUCCESS || updateEvent.clock == 0) { + LOG_ERROR_STR ("StationClock has stopped! Going to setClock state to try to solve the problem"); + itsPropertySet->setValue(PVSSNAME_FSM_ERROR,GCFPVString("Clock stopped")); + TRAN(DigitalBoardControl::setClock_state); + break; + } + + if (updateEvent.clock != itsClock) { + LOG_ERROR_STR ("CLOCK WAS CHANGED TO " << updateEvent.clock << " BY SOMEONE WHILE CLOCK SHOULD BE " << itsClock << ". CHANGING CLOCK BACK."); + itsPropertySet->setValue(PVSSNAME_FSM_ERROR,GCFPVString("Clock unallowed changed")); + TRAN (DigitalBoardControl::setClock_state); + } + + // when update.clock==itsClock ignore it, we probable caused it ourselves. + break; + } + + default: + LOG_DEBUG("active_state, default"); + status = GCFEvent::NOT_HANDLED; + break; + } + + return (status); +} + + +// +// _disconnectedHandler(port) +// +void DigitalBoardControl::_disconnectedHandler(GCFPortInterface& port) +{ + port.close(); + if (&port == itsRSPDriver) { + LOG_DEBUG("Connection with RSPDriver failed, going to reconnect state"); + itsPropertySet->setValue(PVSSNAME_FSM_ERROR,GCFPVString("connection lost")); + TRAN (DigitalBoardControl::connect_state); + } +} + +// +// requestSubscription() +// +void DigitalBoardControl::requestSubscription() +{ + LOG_INFO ("Taking subscription on clock settings"); + + RSPSubclockEvent msg; + + msg.timestamp.setNow(); + msg.period = 1; // let RSPdriver check every second + + itsRSPDriver->send(msg); +} + +// +// cancelSubscription() +// +void DigitalBoardControl::cancelSubscription() +{ + LOG_INFO ("Canceling subscription on clock settings"); + + RSPUnsubclockEvent msg; + + msg.handle = itsSubscription; + itsSubscription = 0; + + itsRSPDriver->send(msg); +} + +// +// requestClockSetting() +// +void DigitalBoardControl::requestClockSetting() +{ + LOG_INFO ("Asking RSPdriver current clock setting"); + + RSPGetclockEvent msg; + + msg.timestamp.setNow(); + msg.cache = 1; + + itsRSPDriver->send(msg); +} + + +// +// sendClockSetting() +// +void DigitalBoardControl::sendClockSetting() +{ + LOG_INFO_STR ("Setting stationClock to " << itsClock << " MHz"); + + RSPSetclockEvent msg; + + msg.timestamp.setNow(); + msg.clock = itsClock; + + itsRSPDriver->send(msg); +} + +}; // StationCU +}; // LOFAR diff --git a/MAC/APL/StationCU/src/DigitalBoardControl/DigitalBoardControl.conf.in b/MAC/APL/StationCU/src/DigitalBoardControl/DigitalBoardControl.conf.in new file mode 100644 index 0000000000000000000000000000000000000000..c75fee5a11a0ed30aa7203e3626b238c036bd936 --- /dev/null +++ b/MAC/APL/StationCU/src/DigitalBoardControl/DigitalBoardControl.conf.in @@ -0,0 +1,9 @@ +# new setup +prefix = LOFAR.PIC.Ring[1].Station[1].DigBoardCtrl. + +instanceNr = 0 + +# TODO: use sampleClock setting of PVSS +sampleClock = 160 + + diff --git a/MAC/APL/StationCU/src/DigitalBoardControl/DigitalBoardControl.dpl b/MAC/APL/StationCU/src/DigitalBoardControl/DigitalBoardControl.dpl new file mode 100644 index 0000000000000000000000000000000000000000..6f28de8c313d8dc757a9357e175baf58519d7e23 --- /dev/null +++ b/MAC/APL/StationCU/src/DigitalBoardControl/DigitalBoardControl.dpl @@ -0,0 +1,9 @@ +# ascii dump of database + +# DpType +TypeName +DigBoardCtrl.DigBoardCtrl 1#1 + state 25#2 + error 25#3 + connected 23#4 + diff --git a/MAC/APL/StationCU/src/DigitalBoardControl/DigitalBoardControl.h b/MAC/APL/StationCU/src/DigitalBoardControl/DigitalBoardControl.h new file mode 100644 index 0000000000000000000000000000000000000000..70435aa1183599f384c3384ef106fbeed2469de5 --- /dev/null +++ b/MAC/APL/StationCU/src/DigitalBoardControl/DigitalBoardControl.h @@ -0,0 +1,121 @@ +//# DigitalBoardControl.h: Controller for the BeamServer +//# +//# 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$ + +#ifndef DIGITALBOARDCONTROL_H +#define DIGITALBOARDCONTROL_H + +//# Includes +#include <boost/shared_ptr.hpp> + +//# GCF Includes +#include <GCF/PAL/GCF_MyPropertySet.h> +#include <GCF/TM/GCF_Port.h> +#include <GCF/TM/GCF_ITCPort.h> +#include <GCF/TM/GCF_TimerPort.h> +#include <GCF/TM/GCF_Task.h> +#include <GCF/TM/GCF_Event.h> + +//# local includes +#include <APL/APLCommon/PropertySetAnswerHandlerInterface.h> +#include <APL/APLCommon/PropertySetAnswer.h> +#include <APL/APLCommon/APLCommonExceptions.h> +#include <APL/APLCommon/Controller_Protocol.ph> +#include <APL/APLCommon/ParentControl.h> +#include <APL/APLCommon/CTState.h> + +//# Common Includes +#include <Common/lofar_string.h> +#include <Common/lofar_vector.h> +#include <Common/LofarLogger.h> + +//# ACC Includes +#include <APS/ParameterSet.h> + +// forward declaration + +namespace LOFAR { + namespace StationCU { + +using GCF::TM::GCFTimerPort; +using GCF::TM::GCFITCPort; +using GCF::TM::GCFPort; +using GCF::TM::GCFEvent; +using GCF::TM::GCFPortInterface; +using GCF::TM::GCFTask; + + +class DigitalBoardControl : public GCFTask, + APLCommon::PropertySetAnswerHandlerInterface +{ +public: + explicit DigitalBoardControl(const string& cntlrName); + ~DigitalBoardControl(); + + // PropertySetAnswerHandlerInterface method + virtual void handlePropertySetAnswer(GCFEvent& answer); + + // During the initial state all connections with the other programs are made. + GCFEvent::TResult initial_state (GCFEvent& e, GCFPortInterface& p); + GCFEvent::TResult connect_state (GCFEvent& e, GCFPortInterface& p); + GCFEvent::TResult subscribe_state (GCFEvent& e, GCFPortInterface& p); + GCFEvent::TResult retrieve_state (GCFEvent& e, GCFPortInterface& p); + GCFEvent::TResult setClock_state (GCFEvent& e, GCFPortInterface& p); + GCFEvent::TResult active_state (GCFEvent& e, GCFPortInterface& p); + +private: + // avoid defaultconstruction and copying + DigitalBoardControl(); + DigitalBoardControl(const DigitalBoardControl&); + DigitalBoardControl& operator=(const DigitalBoardControl&); + + void _disconnectedHandler(GCFPortInterface& port); + + typedef boost::shared_ptr<GCF::PAL::GCFMyPropertySet> GCFMyPropertySetPtr; + + APLCommon::PropertySetAnswer itsPropertySetAnswer; + GCFMyPropertySetPtr itsPropertySet; + bool itsPropertySetInitialized; + + void requestSubscription(); + void cancelSubscription(); + void requestClockSetting(); + void sendClockSetting(); + + // pointer to parent control task +// ParentControl* itsParentControl; +// GCFITCPort* itsParentPort; + + GCFTimerPort* itsTimerPort; + + GCFTCPPort* itsRSPDriver; + + // ParameterSet variables + string itsTreePrefix; + uint32 itsInstanceNr; + time_t itsStartTime; // timestamp the controller was started + uint32 itsClock; + uint32 itsSubscription; +}; + + };//StationCU +};//LOFAR +#endif diff --git a/MAC/APL/StationCU/src/DigitalBoardControl/DigitalBoardControl.log_prop.in b/MAC/APL/StationCU/src/DigitalBoardControl/DigitalBoardControl.log_prop.in new file mode 100644 index 0000000000000000000000000000000000000000..f086c0eb53cc6fbd8420c536a967ddc5caebf324 --- /dev/null +++ b/MAC/APL/StationCU/src/DigitalBoardControl/DigitalBoardControl.log_prop.in @@ -0,0 +1,20 @@ +# add your custom loggers and appenders here +# + +log4cplus.rootLogger=DEBUG, STDOUT, FILE + +log4cplus.logger.TRC=TRACE2 +log4cplus.additivity.TRC=FALSE + +log4cplus.appender.STDOUT=log4cplus::ConsoleAppender +log4cplus.appender.STDOUT.layout=log4cplus::PatternLayout +log4cplus.appender.STDOUT.layout.ConversionPattern=%x %D{%d-%m-%y %H:%M:%S.%q} %-5p %c{9} - %m [%.25l]%n +log4cplus.appender.STDOUT.logToStdErr=true + +log4cplus.appender.FILE=log4cplus::RollingFileAppender +log4cplus.appender.FILE.File=../log/DigitalBoard.log +log4cplus.appender.FILE.MaxFileSize=5MB +log4cplus.appender.FILE.MaxBackupIndex=5 +log4cplus.appender.FILE.layout=log4cplus::PatternLayout +log4cplus.appender.FILE.layout.ConversionPattern=%x %D{%d-%m-%y %H:%M:%S.%q} %-5p %c{3} - %m [%.25l]%n + diff --git a/MAC/APL/StationCU/src/DigitalBoardControl/DigitalBoardControlDefines.h b/MAC/APL/StationCU/src/DigitalBoardControl/DigitalBoardControlDefines.h new file mode 100644 index 0000000000000000000000000000000000000000..33fa60d184c1bd41a834a9e36be267d232a6d847 --- /dev/null +++ b/MAC/APL/StationCU/src/DigitalBoardControl/DigitalBoardControlDefines.h @@ -0,0 +1,44 @@ +//# DigitalBoardControlDefines.h: preprocessor definitions of various constants +//# +//# Copyright (C) 2002-2003 +//# 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$ + +#ifndef DIGITALBOARDCONTROLDEFINES_H +#define DIGITALBOARDCONTROLDEFINES_H + +namespace LOFAR { + namespace StationCU { + +#define DB_TASKNAME "DigitalBoardCtrl" + +#define DB_PROPSET_NAME "LOFAR_ObsSW_ObsCtrl%d_DigitalBoardCtrl" +#define DB_PROPSET_TYPE "DigBrdCtrl" +#define DB_PROP_CONNECTED "connected" +#define DB_PROP_CLOCK "sampleClock" + +// next lines should be defined somewhere in Common. +#define PVSSNAME_FSM_STATE "state" +#define PVSSNAME_FSM_ERROR "error" + + +}; // StationCU +}; // LOFAR + +#endif diff --git a/MAC/APL/StationCU/src/DigitalBoardControl/DigitalBoardControlMain.cc b/MAC/APL/StationCU/src/DigitalBoardControl/DigitalBoardControlMain.cc new file mode 100644 index 0000000000000000000000000000000000000000..a695219e3a9f90b8055c23b786309f6445a111db --- /dev/null +++ b/MAC/APL/StationCU/src/DigitalBoardControl/DigitalBoardControlMain.cc @@ -0,0 +1,46 @@ +//# DigitalBoardControlMain.cc: Main entry for the DigitalBoardControl controller. +//# +//# 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$ +//# +#include <lofar_config.h> +#include <Common/LofarLogger.h> + +#include "DigitalBoardControl.h" + +using namespace LOFAR::GCF::TM; +using namespace LOFAR::StationCU; + +int main(int argc, char* argv[]) +{ + // args: cntlrname, parentHost, parentService + GCFTask::init(argc, argv); + +// ParentControl* pc = ParentControl::instance(); +// pc->start(); // make initial transition + + DigitalBoardControl dbc(argv[1]); + dbc.start(); // make initial transition + + GCFTask::run(); + + return 0; +} + diff --git a/MAC/APL/StationCU/src/DigitalBoardControl/Makefile.am b/MAC/APL/StationCU/src/DigitalBoardControl/Makefile.am new file mode 100644 index 0000000000000000000000000000000000000000..5526ffda711ab651aefeac6e878f97c9813fe1a7 --- /dev/null +++ b/MAC/APL/StationCU/src/DigitalBoardControl/Makefile.am @@ -0,0 +1,44 @@ +bin_PROGRAMS = DigitalBoardControl + +DigitalBoardControl_CPPFLAGS = -Wno-deprecated \ + -fmessage-length=0 \ + -fdiagnostics-show-location=once + +DigitalBoardControl_SOURCES = DigitalBoardControl.cc \ + DigitalBoardControlMain.cc + +DigitalBoardControl_LDADD = $(LOFAR_DEPEND) +DigitalBoardControl_DEPENDENCIES = $(LOFAR_DEPEND) + +NOINSTHDRS = DigitalBoardControl.h \ + DigitalBoardControlDefines.h + +INSTHDRS = + +pkginclude_HEADERS = $(NOINSTHDRS) $(INSTHDRS) + +DOCHDRS = $(pkginclude_HEADERS) $(BUILT_SOURCES) + +EXTRA_DIST = $(configfiles_DATA) $(sysconf_DATA) + +#in case of make install these files will be copied to the bindir beside the test apps +configfilesdir=$(bindir) +configfiles_DATA = +#customPrepPVSSDB.ctl + +sysconf_DATA = DigitalBoardControl.conf \ + DigitalBoardControl.log_prop + +%.log_prop: %.log_prop.in + cp $< $@ + +%.conf: %.conf.in + cp $< $@ + +%.ctl: %.ctl.in + cp $< $@ + +clean-local: + rm -f *.ph + +include $(top_srcdir)/Makefile.common diff --git a/MAC/APL/StationCU/src/Makefile.am b/MAC/APL/StationCU/src/Makefile.am index 051d84dc12a0fd45b149877de5eaca672fff94a8..0aa0780253008df7c7ecb017c0437fcd684635ad 100644 --- a/MAC/APL/StationCU/src/Makefile.am +++ b/MAC/APL/StationCU/src/Makefile.am @@ -1,4 +1,4 @@ -SUBDIRS = BeamControl +SUBDIRS = BeamControl CalibrationControl DigitalBoardControl include $(top_srcdir)/Makefile.common