From b8558db3eb7cd58eb5919930d91b6a0c0c0dcf2f Mon Sep 17 00:00:00 2001 From: Ruud Overeem <overeem@astron.nl> Date: Fri, 8 Aug 2008 12:18:00 +0000 Subject: [PATCH] Bug 1156: Added commands for reading the SPU board and writing and reading raw blocks of data. --- MAC/APL/PIC/RSPDriver/src/Cache.cc | 84 +- MAC/APL/PIC/RSPDriver/src/Cache.h | 258 +++-- MAC/APL/PIC/RSPDriver/src/GetRawBlockCmd.cc | 157 +++ MAC/APL/PIC/RSPDriver/src/GetRawBlockCmd.h | 81 ++ MAC/APL/PIC/RSPDriver/src/GetSPUStatusCmd.cc | 142 +++ MAC/APL/PIC/RSPDriver/src/Makefile.am | 8 + MAC/APL/PIC/RSPDriver/src/RSPDriver.cc | 987 +++++++++--------- MAC/APL/PIC/RSPDriver/src/RSPDriver.h | 5 +- MAC/APL/PIC/RSPDriver/src/RawBlockRead.cc | 136 +++ MAC/APL/PIC/RSPDriver/src/RawBlockRead.h | 57 + MAC/APL/PIC/RSPDriver/src/RawBlockWrite.cc | 134 +++ MAC/APL/PIC/RSPDriver/src/RawBlockWrite.h | 57 + MAC/APL/PIC/RSPDriver/src/RawEvent.cc | 180 ++-- MAC/APL/PIC/RSPDriver/src/Scheduler.cc | 786 +++++++------- MAC/APL/PIC/RSPDriver/src/SetRawBlockCmd.cc | 158 +++ MAC/APL/PIC/RSPDriver/src/SetRawBlockCmd.h | 81 ++ MAC/APL/PIC/RSPDriver/src/SyncAction.cc | 84 +- MAC/APL/PIC/RSPDriver/src/rspctl.cc | 787 +++++++------- MAC/APL/PIC/RSPDriver/src/rspctl.h | 23 + .../APL/RSP_Protocol/AllRegisterState.h | 386 +++---- .../include/APL/RSP_Protocol/MEPData.h | 59 +- .../include/APL/RSP_Protocol/MEPHeader.h | 804 +++++++------- .../PIC/RSP_Protocol/src/AllRegisterState.cc | 108 +- .../PIC/RSP_Protocol/src/EPA_Protocol.prot | 2 + MAC/APL/PIC/RSP_Protocol/src/MEPData.cc | 5 + MAC/APL/PIC/RSP_Protocol/src/MEPHeader.cc | 3 + .../PIC/RSP_Protocol/src/RSP_Protocol.prot | 115 +- 27 files changed, 3459 insertions(+), 2228 deletions(-) create mode 100644 MAC/APL/PIC/RSPDriver/src/GetRawBlockCmd.cc create mode 100644 MAC/APL/PIC/RSPDriver/src/GetRawBlockCmd.h create mode 100644 MAC/APL/PIC/RSPDriver/src/GetSPUStatusCmd.cc create mode 100644 MAC/APL/PIC/RSPDriver/src/RawBlockRead.cc create mode 100644 MAC/APL/PIC/RSPDriver/src/RawBlockRead.h create mode 100644 MAC/APL/PIC/RSPDriver/src/RawBlockWrite.cc create mode 100644 MAC/APL/PIC/RSPDriver/src/RawBlockWrite.h create mode 100644 MAC/APL/PIC/RSPDriver/src/SetRawBlockCmd.cc create mode 100644 MAC/APL/PIC/RSPDriver/src/SetRawBlockCmd.h diff --git a/MAC/APL/PIC/RSPDriver/src/Cache.cc b/MAC/APL/PIC/RSPDriver/src/Cache.cc index df0da81f35f..292886ddabc 100644 --- a/MAC/APL/PIC/RSPDriver/src/Cache.cc +++ b/MAC/APL/PIC/RSPDriver/src/Cache.cc @@ -77,6 +77,7 @@ CacheBuffer::CacheBuffer(Cache* cache) : m_cache(cache) LOG_DEBUG_STR("m_spustatus.subrack().size() =" << m_spustatus.subrack().size() * sizeof(EPA_Protocol::SPUBoardStatus)); LOG_DEBUG_STR("m_tbbsettings().size() =" << m_tbbsettings().size() * sizeof(bitset<MEPHeader::N_SUBBANDS>)); LOG_DEBUG_STR("m_bypasssettings().size() =" << m_bypasssettings().size() * sizeof(EPA_Protocol::DIAGBypass)); + LOG_DEBUG_STR("m_rawDataBlock.size() =" << ETH_DATA_LEN + sizeof (uint16)); LOG_INFO_STR(formatString("CacheBuffer size = %d bytes", m_beamletweights().size() @@ -95,7 +96,8 @@ CacheBuffer::CacheBuffer(Cache* cache) : m_cache(cache) + m_tdstatus.board().size() + m_spustatus.subrack().size() + m_tbbsettings().size() - + m_bypasssettings().size())); + + m_bypasssettings().size() + + ETH_DATA_LEN + sizeof(uint16))); } CacheBuffer::~CacheBuffer() @@ -237,6 +239,12 @@ void CacheBuffer::reset(void) m_bypasssettings().resize(StationSettings::instance()->nrRcus() / MEPHeader::N_POL); BypassSettings::Control control; m_bypasssettings() = control; + + // clear rawdatablock + itsRawDataBlock.address = 0; + itsRawDataBlock.offset = 0; + itsRawDataBlock.dataLen = 0; + memset(itsRawDataBlock.data, 0, RSP_RAW_BLOCK_SIZE); } RTC::Timestamp CacheBuffer::getTimestamp() const @@ -329,75 +337,75 @@ BypassSettings& CacheBuffer::getBypassSettings() return m_bypasssettings; } +RawDataBlock_t& CacheBuffer::getRawDataBlock() +{ + return (itsRawDataBlock); +} + void CacheBuffer::setTimestamp(const RTC::Timestamp& timestamp) { m_timestamp = timestamp; } -/** - * Cache implementation - */ - +// +// Cache implementation +// Cache& Cache::getInstance() { - if (0 == m_instance) - { - m_instance = new Cache; - return *m_instance; - } - else return *m_instance; + if (!m_instance) { + m_instance = new Cache; + } + return (*m_instance); } Cache::Cache() : m_front(0), m_back(0) { - // - // initialize preset waveforms - // - WGSettings::initWaveformPresets(); + // initialize preset waveforms + WGSettings::initWaveformPresets(); - m_front = new CacheBuffer(this); ASSERT(m_front); - m_back = new CacheBuffer(this); ASSERT(m_back); + m_front = new CacheBuffer(this); ASSERT(m_front); + m_back = new CacheBuffer(this); ASSERT(m_back); - getState().init(StationSettings::instance()->nrRspBoards(), - StationSettings::instance()->nrBlps(), - StationSettings::instance()->nrRcus()); + getState().init(StationSettings::instance()->nrRspBoards(), + StationSettings::instance()->nrBlps(), + StationSettings::instance()->nrRcus()); - // start by writing the correct clock setting - Sequencer::getInstance().startSequence(Sequencer::SETCLOCK); + // start by writing the correct clock setting + Sequencer::getInstance().startSequence(Sequencer::SETCLOCK); } Cache::~Cache() { - if (m_front) delete m_front; - if (m_back) delete m_back; + if (m_front) delete m_front; + if (m_back) delete m_back; } void Cache::reset(void) { - m_front->reset(); - m_back->reset(); + m_front->reset(); + m_back->reset(); } void Cache::swapBuffers() { - if (GET_CONFIG("RSPDriver.XC_FILL", i)) { - // fill xcorr array by copying and taking complex conjugate of values mirrored in the diagonal - Array<complex<double>, 4> xc(m_back->getXCStats()()); - firstIndex i; secondIndex j; thirdIndex k; fourthIndex l; - xc = where(xc(i,j,k,l)==complex<double>(0,0), conj(xc(j,i,l,k)), xc(i,j,k,l)); - } - - CacheBuffer *tmp = m_front; - m_front = m_back; - m_back = tmp; + if (GET_CONFIG("RSPDriver.XC_FILL", i)) { + // fill xcorr array by copying and taking complex conjugate of values mirrored in the diagonal + Array<complex<double>, 4> xc(m_back->getXCStats()()); + firstIndex i; secondIndex j; thirdIndex k; fourthIndex l; + xc = where(xc(i,j,k,l)==complex<double>(0,0), conj(xc(j,i,l,k)), xc(i,j,k,l)); + } + + CacheBuffer *tmp = m_front; + m_front = m_back; + m_back = tmp; } CacheBuffer& Cache::getFront() { - return *m_front; + return *m_front; } CacheBuffer& Cache::getBack() { - return *m_back; + return *m_back; } diff --git a/MAC/APL/PIC/RSPDriver/src/Cache.h b/MAC/APL/PIC/RSPDriver/src/Cache.h index 5205c499541..264ce76dfde 100644 --- a/MAC/APL/PIC/RSPDriver/src/Cache.h +++ b/MAC/APL/PIC/RSPDriver/src/Cache.h @@ -33,59 +33,58 @@ namespace LOFAR { namespace RSP { - class Cache; // forward declaration - class CacheBuffer - { - public: - /** - * Constructors for a Cache object. - */ - CacheBuffer(Cache* cache); - - /* Destructor for Cache. */ - virtual ~CacheBuffer(); - - /* - * Reset cache to default values. - * Also called by constructor to initialize the cache. - */ - void reset(void); - - /*@{*/ - /** - * Data access methods. - */ - RTC::Timestamp getTimestamp() const; - RSP_Protocol::BeamletWeights& getBeamletWeights(); - RSP_Protocol::SubbandSelection& getSubbandSelection(); - RSP_Protocol::RCUSettings& getRCUSettings(); - RSP_Protocol::HBASettings& getHBASettings(); - RSP_Protocol::HBASettings& getHBAReadings(); - RSP_Protocol::RSUSettings& getRSUSettings(); - RSP_Protocol::WGSettings& getWGSettings(); - RSP_Protocol::SystemStatus& getSystemStatus(); - RSP_Protocol::Statistics& getSubbandStats(); - RSP_Protocol::Statistics& getBeamletStats(); - RSP_Protocol::XCStatistics& getXCStats(); - RSP_Protocol::Versions& getVersions(); - uint32& getClock(); - RSP_Protocol::TDStatus& getTDStatus(); - RSP_Protocol::SPUStatus& getSPUStatus(); - RSP_Protocol::TBBSettings& getTBBSettings(); - RSP_Protocol::BypassSettings& getBypassSettings(); - /*@}*/ - - /** - * update timestamp - */ - void setTimestamp(const RTC::Timestamp& timestamp); - - /** - * Get const pointer to parent cache. - */ - Cache& getCache() { return *m_cache; } - - private: +class Cache; // forward declaration + +typedef struct { + uint32 address; + uint16 offset; + uint16 dataLen; + uint8 data [RSP_RAW_BLOCK_SIZE]; +} RawDataBlock_t; + +class CacheBuffer +{ +public: + // Constructors for a Cache object. + CacheBuffer(Cache* cache); + + // Destructor for Cache. + virtual ~CacheBuffer(); + + // Reset cache to default values. + // Also called by constructor to initialize the cache. + void reset(void); + + /*@{*/ + // Data access methods. + RTC::Timestamp getTimestamp() const; + RSP_Protocol::BeamletWeights& getBeamletWeights(); + RSP_Protocol::SubbandSelection& getSubbandSelection(); + RSP_Protocol::RCUSettings& getRCUSettings(); + RSP_Protocol::HBASettings& getHBASettings(); + RSP_Protocol::HBASettings& getHBAReadings(); + RSP_Protocol::RSUSettings& getRSUSettings(); + RSP_Protocol::WGSettings& getWGSettings(); + RSP_Protocol::SystemStatus& getSystemStatus(); + RSP_Protocol::Statistics& getSubbandStats(); + RSP_Protocol::Statistics& getBeamletStats(); + RSP_Protocol::XCStatistics& getXCStats(); + RSP_Protocol::Versions& getVersions(); + uint32& getClock(); + RSP_Protocol::TDStatus& getTDStatus(); + RSP_Protocol::SPUStatus& getSPUStatus(); + RSP_Protocol::TBBSettings& getTBBSettings(); + RSP_Protocol::BypassSettings& getBypassSettings(); + RawDataBlock_t& getRawDataBlock(); + /*@}*/ + + // update timestamp + void setTimestamp(const RTC::Timestamp& timestamp); + + // Get const pointer to parent cache. + Cache& getCache() { return *m_cache; } + +private: // NOTE [reo]: The relation between the RSPprotocol classes, // the EPAProtocol classes and the cache is not implemented // in the right way. The Cache should consist of (blitz) @@ -97,92 +96,73 @@ namespace LOFAR { // indicates that the RSP class can contain many elements, // which is never the case. - CacheBuffer(); // prevent default construction - - RTC::Timestamp m_timestamp; - - RSP_Protocol::BeamletWeights m_beamletweights; - RSP_Protocol::SubbandSelection m_subbandselection; - RSP_Protocol::RCUSettings m_rcusettings; - RSP_Protocol::HBASettings m_hbasettings; - RSP_Protocol::HBASettings m_hbareadings; - RSP_Protocol::RSUSettings m_rsusettings; - RSP_Protocol::WGSettings m_wgsettings; - RSP_Protocol::Statistics m_subbandstats; - RSP_Protocol::Statistics m_beamletstats; - RSP_Protocol::XCStatistics m_xcstats; - RSP_Protocol::SystemStatus m_systemstatus; - RSP_Protocol::Versions m_versions; - uint32 m_clock; - RSP_Protocol::TDStatus m_tdstatus; - RSP_Protocol::SPUStatus m_spustatus; - RSP_Protocol::TBBSettings m_tbbsettings; - RSP_Protocol::BypassSettings m_bypasssettings; - - Cache* m_cache; - }; - - /** - * Singleton class containing the data caches. - */ - class Cache - { - public: - /*@{*/ - /** - * Constructor/destructor - */ - static Cache& getInstance(); - virtual ~Cache(); - /*@}*/ - - /* - * Reset cache front and back buffers. - */ - void reset(void); - - /** - * Swap the front and back buffers. - */ - void swapBuffers(); - - /** - * Get front/back buffers. - */ - CacheBuffer& getFront(); - CacheBuffer& getBack(); - - /** - * Get register states. - */ - AllRegisterState& getState() { return m_allstate; } - - private: - - /** - * Direct construction not allowed. - */ - Cache(); - - /** - * Keep register update state. - */ - AllRegisterState m_allstate; // communication status of all register - - /*@{*/ - /** - * Front and back buffers. - */ - CacheBuffer* m_front; - CacheBuffer* m_back; - /*@}*/ - - /** - * Singleton class. - */ - static Cache* m_instance; - }; - }; + CacheBuffer(); // prevent default construction + + // --- datamembers --- + RTC::Timestamp m_timestamp; + RSP_Protocol::BeamletWeights m_beamletweights; + RSP_Protocol::SubbandSelection m_subbandselection; + RSP_Protocol::RCUSettings m_rcusettings; + RSP_Protocol::HBASettings m_hbasettings; + RSP_Protocol::HBASettings m_hbareadings; + RSP_Protocol::RSUSettings m_rsusettings; + RSP_Protocol::WGSettings m_wgsettings; + RSP_Protocol::Statistics m_subbandstats; + RSP_Protocol::Statistics m_beamletstats; + RSP_Protocol::XCStatistics m_xcstats; + RSP_Protocol::SystemStatus m_systemstatus; + RSP_Protocol::Versions m_versions; + uint32 m_clock; + RSP_Protocol::TDStatus m_tdstatus; + RSP_Protocol::SPUStatus m_spustatus; + RSP_Protocol::TBBSettings m_tbbsettings; + RSP_Protocol::BypassSettings m_bypasssettings; + RawDataBlock_t itsRawDataBlock; + + Cache* m_cache; // pointer to container }; + +// Singleton class containing the data caches. +class Cache +{ +public: + /*@{*/ + // Constructor/destructor + static Cache& getInstance(); + virtual ~Cache(); + /*@}*/ + + // Reset cache front and back buffers. + void reset(void); + + // Swap the front and back buffers. + void swapBuffers(); + + // Get front/back buffers. + CacheBuffer& getFront(); + CacheBuffer& getBack(); + + // Get register states. + AllRegisterState& getState() { return m_allstate; } + +private: + // Direct construction not allowed. + Cache(); + + // Keep register update state. + AllRegisterState m_allstate; // communication status of all register + + /*@{*/ + // Front and back buffers. + CacheBuffer* m_front; + CacheBuffer* m_back; + /*@}*/ + + // Singleton class. + static Cache* m_instance; +}; + + }; // namespace +}; // namespace LOFAR #endif /* CACHE_H_ */ diff --git a/MAC/APL/PIC/RSPDriver/src/GetRawBlockCmd.cc b/MAC/APL/PIC/RSPDriver/src/GetRawBlockCmd.cc new file mode 100644 index 00000000000..aa10d9a1e5e --- /dev/null +++ b/MAC/APL/PIC/RSPDriver/src/GetRawBlockCmd.cc @@ -0,0 +1,157 @@ +//# GetRawBlockCmd.cc: implementation of the GetRawBlockCmd class +//# +//# Copyright (C) 2008 +//# 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 <Common/hexdump.h> + +#include <APL/RSP_Protocol/RSP_Protocol.ph> +#include <APL/RTCCommon/PSAccess.h> +#include <blitz/array.h> + +#include "StationSettings.h" +#include "GetRawBlockCmd.h" + +namespace LOFAR { + namespace RSP { +// using namespace blitz; + using namespace RSP_Protocol; + using namespace RTC; // Timestamp + +// +// GetRawBlockCmd(event, port, oper) +// +GetRawBlockCmd::GetRawBlockCmd(GCFEvent& event, GCFPortInterface& port, Operation oper) +{ + itsEvent = new RSPGetblockEvent(event); + + setOperation(oper); + setPeriod(0); + setPort(port); +} + +// +// ~GetRawBlockCmd() +// +GetRawBlockCmd::~GetRawBlockCmd() +{ + delete itsEvent; +} + +// +// ack(cache) +// +void GetRawBlockCmd::ack(CacheBuffer& cache) +{ + RSPGetblockackEvent ack; + RawDataBlock_t& rdb = cache.getRawDataBlock(); + ack.timestamp = getTimestamp(); + ack.boardID = itsEvent->boardID; + ack.status = SUCCESS; + ack.dataLen = rdb.dataLen; + memcpy(ack.data, rdb.data, ack.dataLen); + + getPort()->send(ack); +} + +// +// apply(cache, setModFlag) +// +void GetRawBlockCmd::apply(CacheBuffer& cache, bool setModFlag) +{ + // fill the cache with the request and tickle it. +// LOG_INFO(formatString("@@@GetRawBlockCmd::apply(%d,%0X,%d,%d)", +// itsEvent->boardID, itsEvent->address, itsEvent->offset, itsEvent->dataLen)); + + // NOTE: [REO] I expected that the next 4 lines could also be in the if(setModFlag) + // but it turned out that the info is than in the front cache when the RawDataBlockRead + // command needs it!!! + // Since only one command can be scheduled at the time, I write it in both caches. + + // copy information (always?) to the cache + RawDataBlock_t& rdb = cache.getRawDataBlock(); + rdb.address = itsEvent->address; + rdb.offset = itsEvent->offset; + rdb.dataLen = itsEvent->dataLen; + + if (setModFlag) { + // tell cache(status) that we expect a write(!) action. + cache.getCache().getState().rawdataread().write(itsEvent->boardID); + } +} + +// +// complete(cache) +// +void GetRawBlockCmd::complete(CacheBuffer& cache) +{ + ack(cache); +} + +// +// getTimeStamp() +// +const Timestamp& GetRawBlockCmd::getTimestamp() const +{ + return (itsEvent->timestamp); +} + +// +// setTimestamp(timestamp) +// +void GetRawBlockCmd::setTimestamp(const Timestamp& timestamp) +{ + itsEvent->timestamp = timestamp; +} + +// +// validate() +// +bool GetRawBlockCmd::validate() const +{ + return (true); +} + +// +// readFromCache() +// +bool GetRawBlockCmd::readFromCache() const +{ + return (false); +} + +// +// ack_fail() +// +void GetRawBlockCmd::ack_fail() +{ + RSPGetblockackEvent ack; + ack.timestamp = getTimestamp(); + ack.status = FAILURE; + ack.dataLen = 0; + LOG_INFO ("GetRawBlockCmd::ack_fail"); + + getPort()->send(ack); +} + + } // namepsace RSP +} // namespace LOFAR diff --git a/MAC/APL/PIC/RSPDriver/src/GetRawBlockCmd.h b/MAC/APL/PIC/RSPDriver/src/GetRawBlockCmd.h new file mode 100644 index 00000000000..c8d615683f9 --- /dev/null +++ b/MAC/APL/PIC/RSPDriver/src/GetRawBlockCmd.h @@ -0,0 +1,81 @@ +//# -*- mode: c++ -*- +//# +//# GetRawBlockCmd.h: Get system status command. +//# +//# Copyright (C) 2008 +//# 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 GET_RAWBLOCK_CMD_H +#define GET_RAWBLOCK_CMD_H + +#include "Command.h" +#include <APL/RSP_Protocol/RSP_Protocol.ph> + +#include <Common/LofarTypes.h> +#include <GCF/TM/GCF_Control.h> + +namespace LOFAR { + namespace RSP { + +class GetRawBlockCmd : public Command +{ +public: + // Constructors for a GetRawBlockCmd object. + GetRawBlockCmd(GCFEvent& event, GCFPortInterface& port, Operation oper); + + // Destructor for GetRawBlockCmd. */ + virtual ~GetRawBlockCmd(); + + // Acknowledge the command by sending the appropriate + // response on m_port. + virtual void ack(CacheBuffer& cache); + + // Make necessary changes to the cache for the next synchronization. + // Any changes will be sent to the RSP boards. + virtual void apply(CacheBuffer& cache, bool setModFlag = true); + + // Complete the command by sending the appropriate response on + // the m_answerport; + virtual void complete(CacheBuffer& cache); + + //@{ + // get timestamp of the event + virtual const RTC::Timestamp& getTimestamp() const; + virtual void setTimestamp(const RTC::Timestamp& timestamp); + //@} + + // Range check the parameters of the event. + virtual bool validate() const; + + // Return true if value should be read from cache. + bool readFromCache() const; + + // Send failure ack. + void ack_fail(); + +private: + GetRawBlockCmd(); // Default construction is not allowed. + RSPGetblockEvent* itsEvent; +}; + + } // namespace RSP +} // namespace LOFAR + +#endif /* GET_RAWBLOCK_CMD_H */ diff --git a/MAC/APL/PIC/RSPDriver/src/GetSPUStatusCmd.cc b/MAC/APL/PIC/RSPDriver/src/GetSPUStatusCmd.cc new file mode 100644 index 00000000000..5d621e5e1bf --- /dev/null +++ b/MAC/APL/PIC/RSPDriver/src/GetSPUStatusCmd.cc @@ -0,0 +1,142 @@ +//# GetSPUStatusCmd.cc: implementation of the GetSPUStatusCmd class +//# +//# Copyright (C) 2008 +//# 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 <APL/RSP_Protocol/RSP_Protocol.ph> +#include <APL/RTCCommon/PSAccess.h> +#include <blitz/array.h> + +#include "StationSettings.h" +#include "GetSPUStatusCmd.h" + +namespace LOFAR { + namespace RSP { +// using namespace blitz; + using namespace RSP_Protocol; + using namespace RTC; // Timestamp + +// +// GetSPUStatusCmd(event, port, oper) +// +GetSPUStatusCmd::GetSPUStatusCmd(GCFEvent& event, GCFPortInterface& port, Operation oper) +{ + itsEvent = new RSPGetspustatusEvent(event); + + setOperation(oper); + setPeriod(0); + setPort(port); +} + +// +// ~GetSPUStatusCmd() +// +GetSPUStatusCmd::~GetSPUStatusCmd() +{ + delete itsEvent; +} + +// +// ack(cache) +// +void GetSPUStatusCmd::ack(CacheBuffer& cache) +{ + RSPGetspustatusackEvent ack; + ack.timestamp = getTimestamp(); + ack.status = SUCCESS; + ack.spustatus.subrack().resize(cache.getSPUStatus().subrack().size()); + ack.spustatus = cache.getSPUStatus(); + + getPort()->send(ack); +} + +// +// apply(cache, setModFlag) +// +void GetSPUStatusCmd::apply(CacheBuffer& /*cache*/, bool /*setModFlag*/) +{ + // no-op +} + +// +// complete(cache) +// +void GetSPUStatusCmd::complete(CacheBuffer& cache) +{ + ack(cache); +} + +// +// getTimeStamp() +// +const Timestamp& GetSPUStatusCmd::getTimestamp() const +{ + return (itsEvent->timestamp); +} + +// +// setTimestamp(timestamp) +// +void GetSPUStatusCmd::setTimestamp(const Timestamp& timestamp) +{ + itsEvent->timestamp = timestamp; +} + +// +// validate() +// +bool GetSPUStatusCmd::validate() const +{ + return (true); +} + +// +// readFromCache() +// +bool GetSPUStatusCmd::readFromCache() const +{ + return (itsEvent->cache); +} + +// +// ack_fail() +// +void GetSPUStatusCmd::ack_fail() +{ + RSPGetspustatusackEvent ack; + + ack.timestamp = Timestamp(0,0); + ack.status = FAILURE; + + // send back dummy status array + ack.spustatus.subrack().resize(1); + SPUBoardStatus spustatusinit; + memset(&spustatusinit, 0, sizeof(SPUBoardStatus)); + + ack.spustatus.subrack()(0) = spustatusinit; + + getPort()->send(ack); +} + + } // namepsace RSP +} // namespace LOFAR diff --git a/MAC/APL/PIC/RSPDriver/src/Makefile.am b/MAC/APL/PIC/RSPDriver/src/Makefile.am index 995ca09b932..56f52e824b4 100644 --- a/MAC/APL/PIC/RSPDriver/src/Makefile.am +++ b/MAC/APL/PIC/RSPDriver/src/Makefile.am @@ -150,6 +150,10 @@ RSPDriverFiles = \ GetBypassCmd.cc \ GetSPUStatusCmd.h \ GetSPUStatusCmd.cc \ + GetRawBlockCmd.h \ + GetRawBlockCmd.cc \ + SetRawBlockCmd.h \ + SetRawBlockCmd.cc \ \ SyncAction.h \ SyncAction.cc \ @@ -175,6 +179,10 @@ RSPDriverFiles = \ RCUResultRead.cc \ RCURead.h \ RCURead.cc \ + RawBlockRead.h \ + RawBlockRead.cc \ + RawBlockWrite.h \ + RawBlockWrite.cc \ StatusRead.h \ StatusRead.cc \ SstRead.h \ diff --git a/MAC/APL/PIC/RSPDriver/src/RSPDriver.cc b/MAC/APL/PIC/RSPDriver/src/RSPDriver.cc index 730e5aa8bab..fe81c82b77d 100644 --- a/MAC/APL/PIC/RSPDriver/src/RSPDriver.cc +++ b/MAC/APL/PIC/RSPDriver/src/RSPDriver.cc @@ -82,6 +82,8 @@ #include "SetBypassCmd.h" #include "GetBypassCmd.h" #include "GetSPUStatusCmd.h" +#include "SetRawBlockCmd.h" +#include "GetRawBlockCmd.h" #include "RSUWrite.h" #include "BSWrite.h" @@ -116,6 +118,8 @@ #include "BypassRead.h" #include "BypassWrite.h" #include "RADWrite.h" +#include "RawBlockRead.h" +#include "RawBlockWrite.h" #include "TimestampWrite.h" #include "Cache.h" @@ -195,7 +199,7 @@ void parseOptions(int argc, // RSPDriver::RSPDriver(string name) : GCFTask((State)&RSPDriver::initial, name), - m_board (0), + m_boardPorts (0), m_scheduler (), m_update_counter(0), m_n_updates (0), @@ -253,8 +257,8 @@ RSPDriver::RSPDriver(string name) : // open port with RSP board LOG_DEBUG("Connecting to RSPboards"); - m_board = new GCFETHRawPort[StationSettings::instance()->nrRspBoards()]; - ASSERT(m_board); + m_boardPorts = new GCFETHRawPort[StationSettings::instance()->nrRspBoards()]; + ASSERT(m_boardPorts); // // Get MAC addresses of RSPBoards @@ -269,11 +273,11 @@ RSPDriver::RSPDriver(string name) : strncpy(macaddrstr, GET_CONFIG_STRING(paramname), 64); LOG_DEBUG_STR("initializing board " << boardname << ":" << macaddrstr); - m_board[boardid].init(*this, boardname, GCFPortInterface::SAP, EPA_PROTOCOL,true /*raw*/); - m_board[boardid].setAddr(GET_CONFIG_STRING("RSPDriver.IF_NAME"), macaddrstr); + m_boardPorts[boardid].init(*this, boardname, GCFPortInterface::SAP, EPA_PROTOCOL,true /*raw*/); + m_boardPorts[boardid].setAddr(GET_CONFIG_STRING("RSPDriver.IF_NAME"), macaddrstr); // set ethertype to 0x10FA so Ethereal can decode EPA messages - m_board[boardid].setEtherType(ETHERTYPE_EPA); + m_boardPorts[boardid].setEtherType(ETHERTYPE_EPA); } addAllSyncActions(); @@ -284,7 +288,7 @@ RSPDriver::RSPDriver(string name) : // RSPDriver::~RSPDriver() { - delete [] m_board; + delete [] m_boardPorts; } // @@ -294,7 +298,7 @@ bool RSPDriver::isEnabled() { bool enabled = true; for (int boardid = 0; boardid < StationSettings::instance()->nrRspBoards(); boardid++) { - if (!m_board[boardid].isConnected()) { + if (!m_boardPorts[boardid].isConnected()) { enabled = false; break; } @@ -337,348 +341,343 @@ bool RSPDriver::isEnabled() */ void RSPDriver::addAllSyncActions() { - /** - * For each board a separate BWSync instance is created which handles - * the synchronization of data between the board and the cache for that board. - */ - for (int boardid = 0; boardid < StationSettings::instance()->nrRspBoards(); boardid++) { - /* - * Always read status and version first. - */ - if (1 == GET_CONFIG("RSPDriver.READ_STATUS", i)) { - StatusRead* statusread = new StatusRead(m_board[boardid], boardid); - ASSERT(statusread); - m_scheduler.addSyncAction(statusread); - } - if (1 == GET_CONFIG("RSPDriver.READ_VERSION", i)) { - VersionsRead* versionread = new VersionsRead(m_board[boardid], boardid); - ASSERT(versionread); - m_scheduler.addSyncAction(versionread); - } + // For each board a separate BWSync instance is created which handles + // the synchronization of data between the board and the cache for that board. + for (int boardid = 0; boardid < StationSettings::instance()->nrRspBoards(); boardid++) { + // Always read status and version first. + if (1 == GET_CONFIG("RSPDriver.READ_STATUS", i)) { + StatusRead* statusread = new StatusRead(m_boardPorts[boardid], boardid); + ASSERT(statusread); + m_scheduler.addSyncAction(statusread); + } + if (1 == GET_CONFIG("RSPDriver.READ_VERSION", i)) { + VersionsRead* versionread = new VersionsRead(m_boardPorts[boardid], boardid); + ASSERT(versionread); + m_scheduler.addSyncAction(versionread); + } - /* - * Schedule register writes for soft PPS if configured. - * - * - This means disabling the external sync on all FPGA's - * by broadcasting a CR_CONTROL write. - * - Requesting a soft PPS by writing a 1 in the SYNC bit - * of the RSU_RESET register. - */ - if (1 == GET_CONFIG("RSPDriver.SOFTPPS", i)) { - WriteReg* writereg = 0; - - // Disable External Sync for all FPGA's - writereg = new WriteReg(m_board[boardid], boardid, - MEPHeader::DST_ALL, - MEPHeader::CR, - MEPHeader::CR_SYNCDISABLE, - MEPHeader::CR_CONTROL_SIZE); - ASSERT(writereg); - writereg->setSrcAddress((void*)&g_CR_SYNCDISABLE); - m_scheduler.addSyncAction(writereg); - - // Send PPS to BP which sends signal to configuration device - // which in turn sends a PPS to the AP's - writereg = new WriteReg(m_board[boardid], boardid, - MEPHeader::DST_RSP, - MEPHeader::RSU, - MEPHeader::RSU_RESET, - MEPHeader::RSU_RESET_SIZE); - ASSERT(writereg); - writereg->setSrcAddress((void*)&g_RSU_RESET_SYNC); - m_scheduler.addSyncAction(writereg); - } + // Schedule register writes for soft PPS if configured. + // + // - This means disabling the external sync on all FPGA's + // by broadcasting a CR_CONTROL write. + // - Requesting a soft PPS by writing a 1 in the SYNC bit + // of the RSU_RESET register. + if (1 == GET_CONFIG("RSPDriver.SOFTPPS", i)) { + WriteReg* writereg = 0; + + // Disable External Sync for all FPGA's + writereg = new WriteReg(m_boardPorts[boardid], boardid, + MEPHeader::DST_ALL, + MEPHeader::CR, + MEPHeader::CR_SYNCDISABLE, + MEPHeader::CR_CONTROL_SIZE); + ASSERT(writereg); + writereg->setSrcAddress((void*)&g_CR_SYNCDISABLE); + m_scheduler.addSyncAction(writereg); + + // Send PPS to BP which sends signal to configuration device + // which in turn sends a PPS to the AP's + writereg = new WriteReg(m_boardPorts[boardid], boardid, + MEPHeader::DST_RSP, + MEPHeader::RSU, + MEPHeader::RSU_RESET, + MEPHeader::RSU_RESET_SIZE); + ASSERT(writereg); + writereg->setSrcAddress((void*)&g_RSU_RESET_SYNC); + m_scheduler.addSyncAction(writereg); + } - // order is important; TDSResultRead should be added before TDSProtocolWrite - if (1 == GET_CONFIG("RSPDriver.READWRITE_TDS_PROTOCOL", i)) { - TDSResultWrite* tdsresultwrite = new TDSResultWrite(m_board[boardid], boardid); - ASSERT(tdsresultwrite); - m_scheduler.addSyncAction(tdsresultwrite); + // order is important; TDSResultRead should be added before TDSProtocolWrite + if (1 == GET_CONFIG("RSPDriver.READWRITE_TDS_PROTOCOL", i)) { + TDSResultWrite* tdsresultwrite = new TDSResultWrite(m_boardPorts[boardid], boardid); + ASSERT(tdsresultwrite); + m_scheduler.addSyncAction(tdsresultwrite); - TDSProtocolWrite* tdsprotocolwrite = new TDSProtocolWrite(m_board[boardid], boardid); - ASSERT(tdsprotocolwrite); - m_scheduler.addSyncAction(tdsprotocolwrite); + TDSProtocolWrite* tdsprotocolwrite = new TDSProtocolWrite(m_boardPorts[boardid], boardid); + ASSERT(tdsprotocolwrite); + m_scheduler.addSyncAction(tdsprotocolwrite); - TDSResultRead* tdsresultread = new TDSResultRead(m_board[boardid], boardid); - ASSERT(tdsresultread); - m_scheduler.addSyncAction(tdsresultread); - } + TDSResultRead* tdsresultread = new TDSResultRead(m_boardPorts[boardid], boardid); + ASSERT(tdsresultread); + m_scheduler.addSyncAction(tdsresultread); + } - if (1 == GET_CONFIG("RSPDriver.READWRITE_TDSSTATUS", i)) { - TDSStatusWrite* tdsstatuswrite = new TDSStatusWrite(m_board[boardid], boardid); - ASSERT(tdsstatuswrite); - m_scheduler.addSyncAction(tdsstatuswrite); - - TDSStatusRead* tdsstatusread = new TDSStatusRead(m_board[boardid], boardid); - ASSERT(tdsstatusread); - m_scheduler.addSyncAction(tdsstatusread); - } + if (1 == GET_CONFIG("RSPDriver.READWRITE_TDSSTATUS", i)) { + TDSStatusWrite* tdsstatuswrite = new TDSStatusWrite(m_boardPorts[boardid], boardid); + ASSERT(tdsstatuswrite); + m_scheduler.addSyncAction(tdsstatuswrite); - /* - * Clear the board if needed. - * This needs to be first after WRITE_TDS_PROTOCOL, but before - * WRITE_BS. - */ - if (1 == GET_CONFIG("RSPDriver.WRITE_RSU", i)) { - RSUWrite* rsuwrite = new RSUWrite(m_board[boardid], boardid, m_scheduler); - ASSERT(rsuwrite); - m_scheduler.addSyncAction(rsuwrite); - } + TDSStatusRead* tdsstatusread = new TDSStatusRead(m_boardPorts[boardid], boardid); + ASSERT(tdsstatusread); + m_scheduler.addSyncAction(tdsstatusread); + } - /* - * Set correct number of samples per interval - * This needs to be done before RCU and WG registers, - * but after WRITE_TDS_PROTOCOL - */ - if (1 == GET_CONFIG("RSPDriver.WRITE_BS", i)) { - for (int blp = 0; blp < StationSettings::instance()->nrBlpsPerBoard(); blp++) { - BSWrite* bswrite = new BSWrite(m_board[boardid], boardid, blp, m_scheduler); - ASSERT(bswrite); - m_scheduler.addSyncAction(bswrite); - } - } + // Clear the board if needed. + // This needs to be first after WRITE_TDS_PROTOCOL, but before + // WRITE_BS. + if (1 == GET_CONFIG("RSPDriver.WRITE_RSU", i)) { + RSUWrite* rsuwrite = new RSUWrite(m_boardPorts[boardid], boardid, m_scheduler); + ASSERT(rsuwrite); + m_scheduler.addSyncAction(rsuwrite); + } - if (1 == GET_CONFIG("RSPDriver.READ_BST", i)) { - BstRead* bstread = 0; + // Set correct number of samples per interval + // This needs to be done before RCU and WG registers, + // but after WRITE_TDS_PROTOCOL + if (1 == GET_CONFIG("RSPDriver.WRITE_BS", i)) { + for (int blp = 0; blp < StationSettings::instance()->nrBlpsPerBoard(); blp++) { + BSWrite* bswrite = new BSWrite(m_boardPorts[boardid], boardid, blp, m_scheduler); + ASSERT(bswrite); + m_scheduler.addSyncAction(bswrite); + } + } - bstread = new BstRead(m_board[boardid], boardid); - ASSERT(bstread); - m_scheduler.addSyncAction(bstread); - } + if (1 == GET_CONFIG("RSPDriver.READ_BST", i)) { + BstRead* bstread = 0; + bstread = new BstRead(m_boardPorts[boardid], boardid); + ASSERT(bstread); + m_scheduler.addSyncAction(bstread); + } - if (1 == GET_CONFIG("RSPDriver.READ_XST", i)) { - XstRead* xstread = 0; + if (1 == GET_CONFIG("RSPDriver.READ_XST", i)) { + XstRead* xstread = 0; - for (int regid = MEPHeader::XST_STATS; regid < MEPHeader::XST_NR_STATS; regid++) - { - xstread = new XstRead(m_board[boardid], boardid, regid); - ASSERT(xstread); - m_scheduler.addSyncAction(xstread); - } - } + for (int regid = MEPHeader::XST_STATS; regid < MEPHeader::XST_NR_STATS; regid++) { + xstread = new XstRead(m_boardPorts[boardid], boardid, regid); + ASSERT(xstread); + m_scheduler.addSyncAction(xstread); + } + } - if (1 == GET_CONFIG("RSPDriver.WRITE_CDO", i)) { - CDOWrite* cdowrite = new CDOWrite(m_board[boardid], boardid); + if (1 == GET_CONFIG("RSPDriver.WRITE_CDO", i)) { + CDOWrite* cdowrite = new CDOWrite(m_boardPorts[boardid], boardid); + m_scheduler.addSyncAction(cdowrite); + + if (1 == GET_CONFIG("RSPDriver.READ_CDO", i)) { + // Read back CDO header contents + ReadReg* readreg = new ReadReg(m_boardPorts[boardid], boardid, + MEPHeader::DST_RSP, + MEPHeader::CDO, + MEPHeader::CDO_HEADER, + MEPHeader::CDO_HEADER_SIZE); + ASSERT(readreg); + m_scheduler.addSyncAction(readreg); + } + } - m_scheduler.addSyncAction(cdowrite); + if (1 == GET_CONFIG("RSPDriver.WRITE_RAD", i)) { + RADWrite* radwrite = new RADWrite(m_boardPorts[boardid], boardid); + m_scheduler.addSyncAction(radwrite); + } - if (1 == GET_CONFIG("RSPDriver.READ_CDO", i)) { - // Read back CDO header contents - ReadReg* readreg = new ReadReg(m_board[boardid], boardid, - MEPHeader::DST_RSP, - MEPHeader::CDO, - MEPHeader::CDO_HEADER, - MEPHeader::CDO_HEADER_SIZE); - ASSERT(readreg); - m_scheduler.addSyncAction(readreg); - } - } + for (int action = 0; action < 2; action++) { + if (action == GET_CONFIG("RSPDriver.LOOPBACK_MODE", i)) { + if (1 == GET_CONFIG("RSPDriver.WRITE_WG", i)) { + WGWrite* wgwrite = new WGWrite(m_boardPorts[boardid], boardid); + ASSERT(wgwrite); + m_scheduler.addSyncAction(wgwrite); + } + } + else { + if (1 == GET_CONFIG("RSPDriver.READ_WG", i)) { + WGRead* wgread = new WGRead(m_boardPorts[boardid], boardid); + ASSERT(wgread); + m_scheduler.addSyncAction(wgread); + } + } + } - if (1 == GET_CONFIG("RSPDriver.WRITE_RAD", i)) { - RADWrite* radwrite = new RADWrite(m_board[boardid], boardid); - m_scheduler.addSyncAction(radwrite); - } + // write Spectral Invertion information + if (GET_CONFIG("RSPDriver.WRITE_SI", i)) { + for (int blp = 0; blp < StationSettings::instance()->nrBlpsPerBoard(); blp++) { + BypassWrite* bypasswrite = new BypassWrite(m_boardPorts[boardid], boardid, blp); + ASSERT(bypasswrite); + m_scheduler.addSyncAction(bypasswrite); + } + } - for (int action = 0; action < 2; action++) { - if (action == GET_CONFIG("RSPDriver.LOOPBACK_MODE", i)) { - if (1 == GET_CONFIG("RSPDriver.WRITE_WG", i)) { - WGWrite* wgwrite = new WGWrite(m_board[boardid], boardid); - ASSERT(wgwrite); - m_scheduler.addSyncAction(wgwrite); - } - } - else { - if (1 == GET_CONFIG("RSPDriver.READ_WG", i)) { - WGRead* wgread = new WGRead(m_board[boardid], boardid); - ASSERT(wgread); - m_scheduler.addSyncAction(wgread); - } - } - } + if (1 == GET_CONFIG("RSPDriver.WRITE_TBB", i)) { + TBBSettingsWrite* tbbsettingswrite = new TBBSettingsWrite(m_boardPorts[boardid], boardid); + ASSERT(tbbsettingswrite); + m_scheduler.addSyncAction(tbbsettingswrite); - // write Spectral Invertion information - if (GET_CONFIG("RSPDriver.WRITE_SI", i)) { - for (int blp = 0; blp < StationSettings::instance()->nrBlpsPerBoard(); blp++) { - BypassWrite* bypasswrite = new BypassWrite(m_board[boardid], boardid, blp); - ASSERT(bypasswrite); - m_scheduler.addSyncAction(bypasswrite); - } - } + TBBBandselWrite* tbbbandselwrite = new TBBBandselWrite(m_boardPorts[boardid], boardid); + ASSERT(tbbbandselwrite); + m_scheduler.addSyncAction(tbbbandselwrite); + } - if (1 == GET_CONFIG("RSPDriver.WRITE_TBB", i)) { - TBBSettingsWrite* tbbsettingswrite = new TBBSettingsWrite(m_board[boardid], boardid); - ASSERT(tbbsettingswrite); - m_scheduler.addSyncAction(tbbsettingswrite); + for (int action = 0; action < 2; action++) { + if (action == GET_CONFIG("RSPDriver.LOOPBACK_MODE", i)) { + if (1 == GET_CONFIG("RSPDriver.WRITE_SS", i)) { + SSWrite* sswrite = new SSWrite(m_boardPorts[boardid], boardid); + ASSERT(sswrite); + m_scheduler.addSyncAction(sswrite); + } + } + else { + if (1 == GET_CONFIG("RSPDriver.READ_SS", i)) { + SSRead* ssread = new SSRead(m_boardPorts[boardid], boardid); + ASSERT(ssread); + m_scheduler.addSyncAction(ssread); + } + } + } - TBBBandselWrite* tbbbandselwrite = new TBBBandselWrite(m_board[boardid], boardid); - ASSERT(tbbbandselwrite); - m_scheduler.addSyncAction(tbbbandselwrite); - } - - for (int action = 0; action < 2; action++) { - if (action == GET_CONFIG("RSPDriver.LOOPBACK_MODE", i)) { - if (1 == GET_CONFIG("RSPDriver.WRITE_SS", i)) { - SSWrite* sswrite = new SSWrite(m_board[boardid], boardid); - ASSERT(sswrite); - m_scheduler.addSyncAction(sswrite); - } - } - else { - if (1 == GET_CONFIG("RSPDriver.READ_SS", i)) { - SSRead* ssread = new SSRead(m_board[boardid], boardid); - ASSERT(ssread); - m_scheduler.addSyncAction(ssread); - } - } - } + // + // Depending on the value of RSPDriver.LOOPBACK_MODE either the + // WRITE is done first or the READ is done first. + // + // If LOOPBACK_MODE == 0, the WRITE is done first. + // In this mode you can check with Ethereal that what was + // written is correctly read back from the board. This can + // be used to check that the RSP hardware or the EPAStub + // function correctly. + // + // If LOOPBACK_MODE == 1, the READ is done first. + // In this mode you can check with Ethereal that what was + // read from the EPAStub is written back in the same way. + // This is used to check whether the RSPDriver stores the + // information at the correct location in its cache. + // + // This is done in the same way for all read/write registers. + // + for (int action = 0; action < 2; action++) { + if (action == GET_CONFIG("RSPDriver.LOOPBACK_MODE", i)) { + if (1 == GET_CONFIG("RSPDriver.WRITE_BF", i)) { + BWWrite* bwwrite = 0; + for (int blp = 0; blp < StationSettings::instance()->nrBlpsPerBoard(); blp++) { + bwwrite = new BWWrite(m_boardPorts[boardid], boardid, blp, MEPHeader::BF_XROUT); + ASSERT(bwwrite); + m_scheduler.addSyncAction(bwwrite); + bwwrite = new BWWrite(m_boardPorts[boardid], boardid, blp, MEPHeader::BF_XIOUT); + ASSERT(bwwrite); + m_scheduler.addSyncAction(bwwrite); + bwwrite = new BWWrite(m_boardPorts[boardid], boardid, blp, MEPHeader::BF_YROUT); + ASSERT(bwwrite); + m_scheduler.addSyncAction(bwwrite); + bwwrite = new BWWrite(m_boardPorts[boardid], boardid, blp, MEPHeader::BF_YIOUT); + ASSERT(bwwrite); + m_scheduler.addSyncAction(bwwrite); + } + } + + if (1 == GET_CONFIG("RSPDriver.WRITE_XBF", i)) { + XWWrite* xwwrite = 0; + for (int blp = 0; blp < StationSettings::instance()->nrBlpsPerBoard(); blp++) { + xwwrite = new XWWrite(m_boardPorts[boardid], boardid, blp, MEPHeader::BF_XROUT); + ASSERT(xwwrite); + m_scheduler.addSyncAction(xwwrite); + xwwrite = new XWWrite(m_boardPorts[boardid], boardid, blp, MEPHeader::BF_XIOUT); + ASSERT(xwwrite); + m_scheduler.addSyncAction(xwwrite); + xwwrite = new XWWrite(m_boardPorts[boardid], boardid, blp, MEPHeader::BF_YROUT); + ASSERT(xwwrite); + m_scheduler.addSyncAction(xwwrite); + xwwrite = new XWWrite(m_boardPorts[boardid], boardid, blp, MEPHeader::BF_YIOUT); + ASSERT(xwwrite); + m_scheduler.addSyncAction(xwwrite); + } + } + } + else { + if (1 == GET_CONFIG("RSPDriver.READ_BF", i)) { + BWRead* bwread = 0; + for (int blp = 0; blp < StationSettings::instance()->nrBlpsPerBoard(); blp++) { + bwread = new BWRead(m_boardPorts[boardid], boardid, blp, MEPHeader::BF_XROUT); + ASSERT(bwread); + m_scheduler.addSyncAction(bwread); + bwread = new BWRead(m_boardPorts[boardid], boardid, blp, MEPHeader::BF_XIOUT); + ASSERT(bwread); + m_scheduler.addSyncAction(bwread); + bwread = new BWRead(m_boardPorts[boardid], boardid, blp, MEPHeader::BF_YROUT); + ASSERT(bwread); + m_scheduler.addSyncAction(bwread); + bwread = new BWRead(m_boardPorts[boardid], boardid, blp, MEPHeader::BF_YIOUT); + ASSERT(bwread); + m_scheduler.addSyncAction(bwread); + } + } + } + } - // - // Depending on the value of RSPDriver.LOOPBACK_MODE either the - // WRITE is done first or the READ is done first. - // - // If LOOPBACK_MODE == 0, the WRITE is done first. - // In this mode you can check with Ethereal that what was - // written is correctly read back from the board. This can - // be used to check that the RSP hardware or the EPAStub - // function correctly. - // - // If LOOPBACK_MODE == 1, the READ is done first. - // In this mode you can check with Ethereal that what was - // read from the EPAStub is written back in the same way. - // This is used to check whether the RSPDriver stores the - // information at the correct location in its cache. - // - // This is done in the same way for all read/write registers. - // - for (int action = 0; action < 2; action++) { - if (action == GET_CONFIG("RSPDriver.LOOPBACK_MODE", i)) { - if (1 == GET_CONFIG("RSPDriver.WRITE_BF", i)) { - BWWrite* bwwrite = 0; - - for (int blp = 0; blp < StationSettings::instance()->nrBlpsPerBoard(); blp++) { - bwwrite = new BWWrite(m_board[boardid], boardid, blp, MEPHeader::BF_XROUT); - ASSERT(bwwrite); - m_scheduler.addSyncAction(bwwrite); - bwwrite = new BWWrite(m_board[boardid], boardid, blp, MEPHeader::BF_XIOUT); - ASSERT(bwwrite); - m_scheduler.addSyncAction(bwwrite); - bwwrite = new BWWrite(m_board[boardid], boardid, blp, MEPHeader::BF_YROUT); - ASSERT(bwwrite); - m_scheduler.addSyncAction(bwwrite); - bwwrite = new BWWrite(m_board[boardid], boardid, blp, MEPHeader::BF_YIOUT); - ASSERT(bwwrite); - m_scheduler.addSyncAction(bwwrite); - } - } - if (1 == GET_CONFIG("RSPDriver.WRITE_XBF", i)) { - XWWrite* xwwrite = 0; - - for (int blp = 0; blp < StationSettings::instance()->nrBlpsPerBoard(); blp++) { - xwwrite = new XWWrite(m_board[boardid], boardid, blp, MEPHeader::BF_XROUT); - ASSERT(xwwrite); - m_scheduler.addSyncAction(xwwrite); - xwwrite = new XWWrite(m_board[boardid], boardid, blp, MEPHeader::BF_XIOUT); - ASSERT(xwwrite); - m_scheduler.addSyncAction(xwwrite); - xwwrite = new XWWrite(m_board[boardid], boardid, blp, MEPHeader::BF_YROUT); - ASSERT(xwwrite); - m_scheduler.addSyncAction(xwwrite); - xwwrite = new XWWrite(m_board[boardid], boardid, blp, MEPHeader::BF_YIOUT); - ASSERT(xwwrite); - m_scheduler.addSyncAction(xwwrite); - } - } - } - else { - if (1 == GET_CONFIG("RSPDriver.READ_BF", i)) { - BWRead* bwread = 0; - - for (int blp = 0; blp < StationSettings::instance()->nrBlpsPerBoard(); blp++) { - bwread = new BWRead(m_board[boardid], boardid, blp, MEPHeader::BF_XROUT); - ASSERT(bwread); - m_scheduler.addSyncAction(bwread); - bwread = new BWRead(m_board[boardid], boardid, blp, MEPHeader::BF_XIOUT); - ASSERT(bwread); - m_scheduler.addSyncAction(bwread); - bwread = new BWRead(m_board[boardid], boardid, blp, MEPHeader::BF_YROUT); - ASSERT(bwread); - m_scheduler.addSyncAction(bwread); - bwread = new BWRead(m_board[boardid], boardid, blp, MEPHeader::BF_YIOUT); - ASSERT(bwread); - m_scheduler.addSyncAction(bwread); - } - } - } - } - - if (1 == GET_CONFIG("RSPDriver.READ_SST", i)) { - SstRead* sstread = 0; + if (1 == GET_CONFIG("RSPDriver.READ_SST", i)) { + SstRead* sstread = 0; + sstread = new SstRead(m_boardPorts[boardid], boardid); + ASSERT(sstread); + m_scheduler.addSyncAction(sstread); + } - sstread = new SstRead(m_board[boardid], boardid); - ASSERT(sstread); - m_scheduler.addSyncAction(sstread); + for (int action = 0; action < 2; action++) { + if (action == GET_CONFIG("RSPDriver.LOOPBACK_MODE", i)) { + if (1 == GET_CONFIG("RSPDriver.WRITE_RCU", i)) { + RCUWrite* rcuwrite = new RCUWrite(m_boardPorts[boardid], boardid); + ASSERT(rcuwrite); + m_scheduler.addSyncAction(rcuwrite); + } + } + else { + if (1 == GET_CONFIG("RSPDriver.READ_RCU", i)) { + RCURead* rcuread = new RCURead(m_boardPorts[boardid], boardid); + ASSERT(rcuread); + m_scheduler.addSyncAction(rcuread); + } + } + } - } + // order is important; RCUProtocolWrite should go before RCUResultRead + if (1 == GET_CONFIG("RSPDriver.WRITE_RCU_PROTOCOL", i)) { + RCUProtocolWrite* rcuprotocolwrite = new RCUProtocolWrite(m_boardPorts[boardid], boardid); + ASSERT(rcuprotocolwrite); + m_scheduler.addSyncAction(rcuprotocolwrite); + } - for (int action = 0; action < 2; action++) { - if (action == GET_CONFIG("RSPDriver.LOOPBACK_MODE", i)) { - if (1 == GET_CONFIG("RSPDriver.WRITE_RCU", i)) { - RCUWrite* rcuwrite = new RCUWrite(m_board[boardid], boardid); - ASSERT(rcuwrite); - m_scheduler.addSyncAction(rcuwrite); - } - } - else { - if (1 == GET_CONFIG("RSPDriver.READ_RCU", i)) { - RCURead* rcuread = new RCURead(m_board[boardid], boardid); - ASSERT(rcuread); - m_scheduler.addSyncAction(rcuread); - } - } - } + if (1 == GET_CONFIG("RSPDriver.READ_RCU_RESULT", i)) { + RCUResultRead* rcuresultread = new RCUResultRead(m_boardPorts[boardid], boardid); + ASSERT(rcuresultread); + m_scheduler.addSyncAction(rcuresultread); + } - // order is important; RCUProtocolWrite should go before RCUResultRead - if (1 == GET_CONFIG("RSPDriver.WRITE_RCU_PROTOCOL", i)) { - RCUProtocolWrite* rcuprotocolwrite = new RCUProtocolWrite(m_board[boardid], boardid); - ASSERT(rcuprotocolwrite); - m_scheduler.addSyncAction(rcuprotocolwrite); - } + // order is important; HBAProtocolWrite should go before HBAResultRead, + // these two should go before RCUProtocolWrite/RCUResultRead + if (1 == GET_CONFIG("RSPDriver.WRITE_HBA_PROTOCOL", i)) { + HBAProtocolWrite* hbaprotocolwrite = new HBAProtocolWrite(m_boardPorts[boardid], boardid); + ASSERT(hbaprotocolwrite); + m_scheduler.addSyncAction(hbaprotocolwrite); + } - if (1 == GET_CONFIG("RSPDriver.READ_RCU_RESULT", i)) { - RCUResultRead* rcuresultread = new RCUResultRead(m_board[boardid], boardid); - ASSERT(rcuresultread); - m_scheduler.addSyncAction(rcuresultread); - } + if (1 == GET_CONFIG("RSPDriver.READ_HBA_RESULT", i)) { + HBAResultRead* hbaresultread = new HBAResultRead(m_boardPorts[boardid], boardid); + ASSERT(hbaresultread); + m_scheduler.addSyncAction(hbaresultread); + } - // order is important; HBAProtocolWrite should go before HBAResultRead, - // these two should go before RCUProtocolWrite/RCUResultRead - if (1 == GET_CONFIG("RSPDriver.WRITE_HBA_PROTOCOL", i)) { - HBAProtocolWrite* hbaprotocolwrite = new HBAProtocolWrite(m_board[boardid], boardid); - ASSERT(hbaprotocolwrite); - m_scheduler.addSyncAction(hbaprotocolwrite); - } + // read Spectral Invertion information + // if (GET_CONFIG("RSPDriver.READ_SI", i)) { + // for (int blp = 0; blp < StationSettings::instance()->nrBlpsPerBoard(); blp++) { + // BypassRead* bypassread = new BypassRead(m_boardPorts[boardid], boardid, blp); + // ASSERT(bypassread); + // m_scheduler.addSyncAction(bypassread); + // } + // } + + if (GET_CONFIG("RSPDriver.READ_RAW_DATA", i) == 1) { + RawBlockRead* rawRead = new RawBlockRead(m_boardPorts[boardid], boardid); + ASSERT(rawRead); + m_scheduler.addSyncAction(rawRead); + } - if (1 == GET_CONFIG("RSPDriver.READ_HBA_RESULT", i)) { - HBAResultRead* hbaresultread = new HBAResultRead(m_board[boardid], boardid); - ASSERT(hbaresultread); - m_scheduler.addSyncAction(hbaresultread); - } + if (GET_CONFIG("RSPDriver.WRITE_RAW_DATA", i) == 1) { + RawBlockWrite* rawWrite = new RawBlockWrite(m_boardPorts[boardid], boardid); + ASSERT(rawWrite); + m_scheduler.addSyncAction(rawWrite); + } - // read Spectral Invertion information -// if (GET_CONFIG("RSPDriver.READ_SI", i)) { -// for (int blp = 0; blp < StationSettings::instance()->nrBlpsPerBoard(); blp++) { -// BypassRead* bypassread = new BypassRead(m_board[boardid], boardid, blp); -// ASSERT(bypassread); -// m_scheduler.addSyncAction(bypassread); -// } -// } - - if (1 == GET_CONFIG("RSPDriver.WRITE_TIMESTAMP", i)) { - TimestampWrite* timestampwrite = new TimestampWrite(m_board[boardid], boardid, m_scheduler); - ASSERT(timestampwrite); - m_scheduler.addSyncAction(timestampwrite); - } - } // for (boardid...) + if (1 == GET_CONFIG("RSPDriver.WRITE_TIMESTAMP", i)) { + TimestampWrite* timestampwrite = new TimestampWrite(m_boardPorts[boardid], boardid, m_scheduler); + ASSERT(timestampwrite); + m_scheduler.addSyncAction(timestampwrite); + } + } // for (boardid...) } // @@ -687,8 +686,8 @@ void RSPDriver::addAllSyncActions() void RSPDriver::openBoards() { for (int boardid = 0; boardid < StationSettings::instance()->nrRspBoards(); boardid++) { - if (!m_board[boardid].isConnected()) { - m_board[boardid].open(); + if (!m_boardPorts[boardid].isConnected()) { + m_boardPorts[boardid].open(); } } } @@ -698,17 +697,17 @@ void RSPDriver::openBoards() // int RSPDriver::fetchPPS() { - int result = 0; + int result = 0; #ifdef HAVE_SYS_TIMEPPS_H - do { - struct timespec timeout = PPS_FETCH_TIMEOUT; // prevent permanent lock - result = time_pps_fetch(m_ppshandle, PPS_TSFMT_TSPEC, &m_ppsinfo, &timeout); - } while ((result < 0) && (EINTR == errno || EAGAIN == errno)); + do { + struct timespec timeout = PPS_FETCH_TIMEOUT; // prevent permanent lock + result = time_pps_fetch(m_ppshandle, PPS_TSFMT_TSPEC, &m_ppsinfo, &timeout); + } while ((result < 0) && (EINTR == errno || EAGAIN == errno)); #else - LOG_FATAL("fetchPPS should not be called when HAVE_SYS_TIMEPPS_H is not defined"); - exit(EXIT_FAILURE); + LOG_FATAL("fetchPPS should not be called when HAVE_SYS_TIMEPPS_H is not defined"); + exit(EXIT_FAILURE); #endif - return result; + return result; } // @@ -716,137 +715,124 @@ int RSPDriver::fetchPPS() // GCFEvent::TResult RSPDriver::initial(GCFEvent& event, GCFPortInterface& port) { - GCFEvent::TResult status = GCFEvent::HANDLED; - - switch(event.signal) { - case F_INIT: - { - if (GET_CONFIG("RSPDriver.SYNC_MODE", i) == SYNC_PPS) { -#ifdef HAVE_SYS_TIMEPPS_H - pps_params_t parm; - - // standard time format and trigger on rising edge, API version 1 - memset(&parm, 0, sizeof(pps_params_t)); - parm.mode = PPS_TSFMT_TSPEC; - if (GET_CONFIG("RSPDriver.PPS_TRIGGER", i)) { - parm.mode |= PPS_CAPTUREASSERT; // trigger on ASSERT - } else { - parm.mode |= PPS_CAPTURECLEAR; // trigger on CLEAR - } - parm.api_version = PPS_API_VERS_1; - - if ((m_ppsfd = open(GET_CONFIG_STRING("RSPDriver.PPS_DEVICE"), O_RDWR)) < 0) { - LOG_FATAL_STR("Error opening '" << GET_CONFIG_STRING("RSPDriver.PPS_DEVICE") << "': " << strerror(errno)); - exit(EXIT_FAILURE); - } - - if (time_pps_create(m_ppsfd, &m_ppshandle) < 0) { - LOG_FATAL_STR("PPS device does not support PPS API?: " << strerror(errno)); - exit(EXIT_FAILURE); - } + GCFEvent::TResult status = GCFEvent::HANDLED; - int caps = 0; - if (time_pps_getcap(m_ppshandle, &caps) < 0) { - LOG_FATAL_STR("Cannot get PPS device capabilities:" << strerror(errno)); - exit(EXIT_FAILURE); - } - LOG_INFO(formatString("PPS device capabilities are 0x%x\n", caps)); + switch(event.signal) { + case F_INIT: { + if (GET_CONFIG("RSPDriver.SYNC_MODE", i) == SYNC_PPS) { +#ifdef HAVE_SYS_TIMEPPS_H + pps_params_t parm; + + // standard time format and trigger on rising edge, API version 1 + memset(&parm, 0, sizeof(pps_params_t)); + parm.mode = PPS_TSFMT_TSPEC; + if (GET_CONFIG("RSPDriver.PPS_TRIGGER", i)) { + parm.mode |= PPS_CAPTUREASSERT; // trigger on ASSERT + } else { + parm.mode |= PPS_CAPTURECLEAR; // trigger on CLEAR + } + parm.api_version = PPS_API_VERS_1; + + if ((m_ppsfd = open(GET_CONFIG_STRING("RSPDriver.PPS_DEVICE"), O_RDWR)) < 0) { + LOG_FATAL_STR("Error opening '" << GET_CONFIG_STRING("RSPDriver.PPS_DEVICE") << "': " << strerror(errno)); + exit(EXIT_FAILURE); + } + + if (time_pps_create(m_ppsfd, &m_ppshandle) < 0) { + LOG_FATAL_STR("PPS device does not support PPS API?: " << strerror(errno)); + exit(EXIT_FAILURE); + } + + int caps = 0; + if (time_pps_getcap(m_ppshandle, &caps) < 0) { + LOG_FATAL_STR("Cannot get PPS device capabilities:" << strerror(errno)); + exit(EXIT_FAILURE); + } + LOG_INFO(formatString("PPS device capabilities are 0x%x\n", caps)); #if 0 - if (!(caps & PPS_CANWAIT & PPS_CAPTUREASSERT)) { - LOG_FATAL("PPS device does not support PPS_CANWAIT & PPS_CAPTUREASSERT. PPS device unsuitable."); - exit(EXIT_FAILURE); - } + if (!(caps & PPS_CANWAIT & PPS_CAPTUREASSERT)) { + LOG_FATAL("PPS device does not support PPS_CANWAIT & PPS_CAPTUREASSERT. PPS device unsuitable."); + exit(EXIT_FAILURE); + } #endif - if (time_pps_setparams(m_ppshandle, &parm) < 0) { - LOG_FATAL_STR("Error settings parameters on PPS device:" << strerror(errno)); - exit(EXIT_FAILURE); - } + if (time_pps_setparams(m_ppshandle, &parm) < 0) { + LOG_FATAL_STR("Error settings parameters on PPS device:" << strerror(errno)); + exit(EXIT_FAILURE); + } - // now we're setup to use time_pps_fetch... + // now we're setup to use time_pps_fetch... #else - LOG_FATAL("HAVE_SYS_TIMEPPS_H not defined. Platform doesn't support PPSkit interface."); - exit(EXIT_FAILURE); + LOG_FATAL("HAVE_SYS_TIMEPPS_H not defined. Platform doesn't support PPSkit interface."); + exit(EXIT_FAILURE); #endif - } - } - break; + } // sync mode + } // F_INIT + break; - case F_ENTRY: - { + case F_ENTRY: { #if 0 - if (GET_CONFIG("RSPDriver.SYNC_MODE", i) == SYNC_PARALLEL) - { - if (!m_clock.isConnected()) m_clock.open(); - } + if (GET_CONFIG("RSPDriver.SYNC_MODE", i) == SYNC_PARALLEL) { + if (!m_clock.isConnected()) m_clock.open(); + } #endif - openBoards(); - } - break; + openBoards(); + } + break; - case F_CONNECTED: - { - LOG_INFO(formatString("CONNECTED: port '%s'", port.getName().c_str())); - if (isEnabled()) - { - TRAN(RSPDriver::enabled); - } - } - break; + case F_CONNECTED: { + LOG_INFO(formatString("CONNECTED: port '%s'", port.getName().c_str())); + if (isEnabled()) { + TRAN(RSPDriver::enabled); + } + } + break; - case F_DISCONNECTED: - { - port.setTimer((long)3); // try again in 3 seconds - LOG_WARN(formatString("port '%s' disconnected, retry in 3 seconds...", port.getName().c_str())); - port.close(); - } - break; + case F_DISCONNECTED: { + port.setTimer((long)3); // try again in 3 seconds + LOG_WARN(formatString("port '%s' disconnected, retry in 3 seconds...", port.getName().c_str())); + port.close(); + } + break; - case F_TIMER: - { - LOG_DEBUG(formatString("port '%s' retry of open...", port.getName().c_str())); - port.open(); - } - break; + case F_TIMER: { + LOG_DEBUG(formatString("port '%s' retry of open...", port.getName().c_str())); + port.open(); + } + break; - case F_DATAIN: - { + case F_DATAIN: { #if 0 - if (&port == &m_clock) - { - /** - * We don't need the clock here yet, simply read the value - * and ignore - */ - uint8 count = 0; - (void)port.recv(&count, sizeof(uint8)); - } - else - { + if (&port == &m_clock) { + // We don't need the clock here yet, simply read the value + // and ignore + uint8 count = 0; + (void)port.recv(&count, sizeof(uint8)); + } + else { #endif - // ignore in this state - static char buf[ETH_DATA_LEN]; - (void)port.recv(buf, ETH_DATA_LEN); + // ignore in this state + static char buf[ETH_DATA_LEN]; + (void)port.recv(buf, ETH_DATA_LEN); #if 0 - } + } #endif - } - break; + } + break; - case F_EXIT: - { - // cancel timers - m_board[0].cancelAllTimers(); - } - break; + case F_EXIT: { + // cancel timers + m_boardPorts[0].cancelAllTimers(); + } + break; - default: - status = GCFEvent::NOT_HANDLED; - break; - } + default: + status = GCFEvent::NOT_HANDLED; + break; + } - return status; + return status; } // @@ -854,12 +840,10 @@ GCFEvent::TResult RSPDriver::initial(GCFEvent& event, GCFPortInterface& port) // void RSPDriver::undertaker() { - for (list<GCFPortInterface*>::iterator it = m_dead_clients.begin(); - it != m_dead_clients.end(); - it++) { - delete (*it); - } - m_dead_clients.clear(); + for (list<GCFPortInterface*>::iterator it = m_dead_clients.begin(); it != m_dead_clients.end(); it++) { + delete (*it); + } + m_dead_clients.clear(); } // @@ -872,8 +856,7 @@ GCFEvent::TResult RSPDriver::enabled(GCFEvent& event, GCFPortInterface& port) undertaker(); // destroy dead clients switch (event.signal) { - case F_ENTRY: - { + case F_ENTRY: { // start waiting for clients if (!m_acceptor.isConnected()) { m_acceptor.open(); @@ -887,7 +870,7 @@ GCFEvent::TResult RSPDriver::enabled(GCFEvent& event, GCFPortInterface& port) struct timeval sysTime; gettimeofday(&sysTime, 0); usleep (1999000 - sysTime.tv_usec); // try to wait for a second passage - m_board[0].setTimer(1.0, syncItv); // Start the update timer after 1 second + m_boardPorts[0].setTimer(1.0, syncItv); // Start the update timer after 1 second LOG_INFO("Hopefully on whole second now"); } else if (GET_CONFIG("RSPDriver.SYNC_MODE", i) == SYNC_FAST) { @@ -895,7 +878,7 @@ GCFEvent::TResult RSPDriver::enabled(GCFEvent& event, GCFPortInterface& port) // single timeout after 1 second to set // off as-fast-as-possible update mode // - m_board[0].setTimer(1.0); + m_boardPorts[0].setTimer(1.0); // // periodic timeout on m_acceptor port @@ -923,10 +906,10 @@ GCFEvent::TResult RSPDriver::enabled(GCFEvent& event, GCFPortInterface& port) // start a single shot timer that is slightly shorter that 1 second // when the timer expires, wait for the true PPS using time_pps_fetch - m_board[0].setTimer(0.99); // 1st event after 1 second + m_boardPorts[0].setTimer(0.99); // 1st event after 1 second #else LOG_WARN("HAVE_SYS_TIMEPPS_H not defined. Platform doesn't support PPSkit interface. Using software timer."); - m_board[0].setTimer((long)1); // next event in one (software) second + m_boardPorts[0].setTimer((long)1); // next event in one (software) second #endif } } @@ -1008,9 +991,11 @@ GCFEvent::TResult RSPDriver::enabled(GCFEvent& event, GCFPortInterface& port) case RSP_SETTBB: rsp_settbb(event, port); break; case RSP_GETTBB: rsp_gettbb(event, port); break; case RSP_GETSPUSTATUS: rsp_getspustatus(event, port); break; + case RSP_SETBLOCK: rsp_setRawBlock(event, port); break; + case RSP_GETBLOCK: rsp_getRawBlock(event, port); break; case F_TIMER: { - if (&port == &m_board[0]) { + if (&port == &m_boardPorts[0]) { // // If SYNC_MODE == SOFTWARE|FAST then run the scheduler // directly on the software timer. @@ -1040,7 +1025,7 @@ GCFEvent::TResult RSPDriver::enabled(GCFEvent& event, GCFPortInterface& port) timer.id = 0; timer.arg = 0; - m_board[0].setTimer((long)1); // next event after exactly 1 second + m_boardPorts[0].setTimer((long)1); // next event after exactly 1 second } else { @@ -1064,9 +1049,9 @@ GCFEvent::TResult RSPDriver::enabled(GCFEvent& event, GCFPortInterface& port) LOG_WARN_STR("Missed " << m_ppsinfo.assert_sequence - prevppsinfo.assert_sequence - 1 << " PPS events."); } } - m_board[0].setTimer(0.95); // next event in just under 1 second + m_boardPorts[0].setTimer(0.95); // next event in just under 1 second #else - m_board[0].setTimer((long)1); // next event in one (software) second + m_boardPorts[0].setTimer((long)1); // next event in one (software) second #endif // delay the driver some number of microseconds after it receives the PPS tick @@ -1096,8 +1081,7 @@ GCFEvent::TResult RSPDriver::enabled(GCFEvent& event, GCFPortInterface& port) } break; - case F_DISCONNECTED: - { + case F_DISCONNECTED: { LOG_INFO(formatString("DISCONNECTED: port '%s'", port.getName().c_str())); port.close(); @@ -1105,7 +1089,7 @@ GCFEvent::TResult RSPDriver::enabled(GCFEvent& event, GCFPortInterface& port) LOG_FATAL("Failed to start listening for client connections."); exit(EXIT_FAILURE); } - else if (&port == &m_board[0] || &port == &m_board[1] || &port == &m_acceptor) { + else if (&port == &m_boardPorts[0] || &port == &m_boardPorts[1] || &port == &m_acceptor) { m_acceptor.close(); TRAN(RSPDriver::initial); } @@ -1119,11 +1103,10 @@ GCFEvent::TResult RSPDriver::enabled(GCFEvent& event, GCFPortInterface& port) } break; - case F_EXIT: - { + case F_EXIT: { // cancel timers m_acceptor.cancelAllTimers(); - m_board[0].cancelAllTimers(); + m_boardPorts[0].cancelAllTimers(); } break; @@ -1137,7 +1120,7 @@ GCFEvent::TResult RSPDriver::enabled(GCFEvent& event, GCFPortInterface& port) // if ((GET_CONFIG("RSPDriver.SYNC_MODE", i) == SYNC_FAST) && m_scheduler.syncHasCompleted()) { - m_board[0].setTimer(0.0); // immediate + m_boardPorts[0].setTimer(0.0); // immediate m_update_counter++; } } @@ -1153,13 +1136,13 @@ GCFEvent::TResult RSPDriver::enabled(GCFEvent& event, GCFPortInterface& port) bool RSPDriver::isBoardPort(GCFPortInterface& port) { /** - * The addresses of the elements of the m_board array + * The addresses of the elements of the m_boardPorts array * are consecutive in memory, therefor we can do a range * check on the address to determine whether it is a port * to a board. */ - if ( &port >= &m_board[0] - && &port <= &m_board[StationSettings::instance()->nrRspBoards()]) + if ( &port >= &m_boardPorts[0] + && &port <= &m_boardPorts[StationSettings::instance()->nrRspBoards()]) return true; return false; @@ -2433,8 +2416,7 @@ void RSPDriver::rsp_settbb(GCFEvent& event, GCFPortInterface& port) { Ptr<SetTBBCmd> command = new SetTBBCmd(event, port, Command::WRITE); - if (!command->validate()) - { + if (!command->validate()) { LOG_ERROR("SETTBB: invalid parameter"); RSPSettbbackEvent ack; @@ -2445,14 +2427,12 @@ void RSPDriver::rsp_settbb(GCFEvent& event, GCFPortInterface& port) } // if timestamp == Timestamp(0,0) apply changes immediately - if (Timestamp(0,0) == command->getTimestamp()) - { + if (Timestamp(0,0) == command->getTimestamp()) { LOG_INFO("applying TBB control immediately"); command->apply(Cache::getInstance().getFront(), true); command->apply(Cache::getInstance().getBack(), false); } - else - { + else { (void)m_scheduler.enter(Ptr<Command>(&(*command))); } command->ack(Cache::getInstance().getFront()); @@ -2465,8 +2445,7 @@ void RSPDriver::rsp_gettbb(GCFEvent& event, GCFPortInterface& port) { Ptr<GetTBBCmd> command = new GetTBBCmd(event, port, Command::READ); - if (!command->validate()) - { + if (!command->validate()) { LOG_ERROR("GETTBB: invalid parameter"); RSPGettbbackEvent ack; @@ -2480,13 +2459,11 @@ void RSPDriver::rsp_gettbb(GCFEvent& event, GCFPortInterface& port) // if null timestamp get value from the cache and acknowledge immediately if ( (Timestamp(0,0) == command->getTimestamp()) - && (true == command->readFromCache())) - { + && (true == command->readFromCache())) { command->setTimestamp(Cache::getInstance().getFront().getTimestamp()); command->ack(Cache::getInstance().getFront()); } - else - { + else { (void)m_scheduler.enter(Ptr<Command>(&(*command))); } } @@ -2513,6 +2490,58 @@ void RSPDriver::rsp_getspustatus(GCFEvent& event, GCFPortInterface& port) } } +// +// rsp_getRawBlock(event, port) +// +void RSPDriver::rsp_getRawBlock(GCFEvent& event, GCFPortInterface& port) +{ + Ptr<GetRawBlockCmd> command = new GetRawBlockCmd(event, port, Command::READ); + + if (!command->validate()) { + LOG_ERROR("GetRawBlock: invalid parameter"); + + RSPGetblockackEvent ack; + ack.timestamp = Timestamp(0,0); + ack.status = FAILURE; + port.send(ack); + return; + } + + // temp debugging TODO +// RSPGetblockEvent e(event); +// LOG_INFO(formatString("@@@Scheduling GetRawBlockCmd(%d,%x,%d,%d)", e.boardID, e.address, e.offset, e.dataLen)); + + // command is ok, schedule it. + (void)m_scheduler.enter(Ptr<Command>(&(*command))); + +} + +// +// rsp_setRawBlock(event, port) +// +void RSPDriver::rsp_setRawBlock(GCFEvent& event, GCFPortInterface& port) +{ + Ptr<SetRawBlockCmd> command = new SetRawBlockCmd(event, port, Command::WRITE); + + if (!command->validate()) { + LOG_ERROR("SetRawBlock: invalid parameter"); + + RSPSetblockackEvent ack; + ack.timestamp = Timestamp(0,0); + ack.status = FAILURE; + port.send(ack); + return; + } + + // temp debugging TODO +// RSPSetblockEvent e(event); +// LOG_INFO(formatString("@@@Scheduling SetRawBlockCmd(%d,%x,%d,%d)", e.boardID, e.address, e.offset, e.dataLen)); + + // command is ok, schedule it. + (void)m_scheduler.enter(Ptr<Command>(&(*command))); +} + + } // namespace RSP } // namespace LOFAR diff --git a/MAC/APL/PIC/RSPDriver/src/RSPDriver.h b/MAC/APL/PIC/RSPDriver/src/RSPDriver.h index 811bbfd4a09..09e49a68035 100644 --- a/MAC/APL/PIC/RSPDriver/src/RSPDriver.h +++ b/MAC/APL/PIC/RSPDriver/src/RSPDriver.h @@ -169,6 +169,9 @@ namespace LOFAR { void rsp_getbypass(GCFEvent& event, GCFPortInterface &port); void rsp_getspustatus(GCFEvent& event, GCFPortInterface &port); + + void rsp_getRawBlock(GCFEvent& event, GCFPortInterface &port); + void rsp_setRawBlock(GCFEvent& event, GCFPortInterface &port); /*@}*/ private: @@ -184,7 +187,7 @@ namespace LOFAR { // ports GCFTCPPort m_acceptor; // listen for clients on this port - GCFETHRawPort* m_board; // array of ports, one for each RSP board + GCFETHRawPort* m_boardPorts; // array of ports, one for each RSP board std::list<GCFPortInterface*> m_client_list; // list of clients std::list<GCFPortInterface*> m_dead_clients; // list of clients to cleanup diff --git a/MAC/APL/PIC/RSPDriver/src/RawBlockRead.cc b/MAC/APL/PIC/RSPDriver/src/RawBlockRead.cc new file mode 100644 index 00000000000..119181813ca --- /dev/null +++ b/MAC/APL/PIC/RSPDriver/src/RawBlockRead.cc @@ -0,0 +1,136 @@ +//# RawBlockRead.cc: implementation of the RawBlockRead class +//# +//# Copyright (C) 2002-2004 +//# 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 <Common/hexdump.h> +#include <APL/RSP_Protocol/EPA_Protocol.ph> + +#include <APL/RTCCommon/PSAccess.h> +#include <string.h> + +#include "StationSettings.h" +#include "HBAProtocolWrite.h" +#include "RawBlockRead.h" +#include "Cache.h" + +#include <netinet/in.h> + +using namespace LOFAR; +using namespace RSP; +using namespace EPA_Protocol; +using namespace blitz; + +// +// RawBlockRead(port, boardID) +// +RawBlockRead::RawBlockRead(GCFPortInterface& board_port, int board_id) + : SyncAction(board_port, board_id, 1) +{ + memset(&m_hdr, 0, sizeof(MEPHeader)); +} + +// +// ~RawBlockRead() +// +RawBlockRead::~RawBlockRead() +{ + /* TODO: delete event? */ +} + +// +// sendrequest() +// +void RawBlockRead::sendrequest() +{ + // skip update if nothing was modified + if (Cache::getInstance().getState().rawdataread().get(getBoardId()) != RTC::RegisterState::WRITE) { + Cache::getInstance().getState().rawdataread().unmodified(getBoardId()); + setContinue(true); +// LOG_INFO_STR("@@@RawBlockRead::sendrequest(" << getBoardId() << "):false"); + return; + } +// LOG_INFO_STR("@@@RawBlockRead::sendrequest(" << getBoardId() << "):true"); + + // Cache was modified, construct an EPA message and send it. + // Note that the buffer in the cache already contains the whole message, just copy the bytes + // to the right places in the message. + EPAReadEvent rawData; + RawDataBlock_t& rdb = Cache::getInstance().getBack().getRawDataBlock(); + rawData.hdr.set(MEPHeader::RSP_RAWDATA_READ, 0, MEPHeader::READ, rdb.dataLen, rdb.offset); + // overwrite complete address + memcpy((void*)&(rawData.hdr.m_fields.addr), (void*)&(rdb.address), sizeof(rdb.address)); + m_hdr = rawData.hdr; // remember header to match with ack + +// string hDump; // DEBUG +// hexdump(hDump, (void*)&m_hdr.m_fields, MEPHeader::SIZE); // DEBUG +// LOG_INFO (hDump); + + // finally send the message + getBoardPort().send(rawData); +} + +// +// sendrequest_status() +// +void RawBlockRead::sendrequest_status() +{ + // intentionally left empty +} + +// +// handleack(event, port) +// +GCFEvent::TResult RawBlockRead::handleack(GCFEvent& event, GCFPortInterface& /*port*/) +{ +// LOG_INFO_STR("@@@RawBlockRead::handleack(" << getBoardId() << ")"); + + // Note: we don't have to check the event.signal here because it is always safe to + // convert an event to a generic readackEvent. + // We can't even check it because the user made up the address and there for the response-type. + EPAReadackEvent ack(event); + +// string hDump; /// DEBUG +// hexdump(hDump, (void*)&(ack.hdr.m_fields), MEPHeader::SIZE); +// LOG_INFO (hDump); + + // check result + if (!ack.hdr.isValidAck(m_hdr)) { + LOG_ERROR("RawBlockRead::handleack: invalid ack"); + Cache::getInstance().getState().rawdataread().write_error(getBoardId()); + return GCFEvent::HANDLED; + } + + // Mark command ok. + Cache::getInstance().getState().rawdataread().write_ack(getBoardId()); + + // copy the stuff + RawDataBlock_t& rdb = Cache::getInstance().getBack().getRawDataBlock(); + rdb.dataLen = ack.hdr.m_fields.payload_length; + memcpy(rdb.data, ack.data, rdb.dataLen); + +// hDump.clear(); /// DEBUG +// hexdump(hDump, (void*)&(rdb.data), rdb.dataLen); +// LOG_INFO (hDump); + + return GCFEvent::HANDLED; +} diff --git a/MAC/APL/PIC/RSPDriver/src/RawBlockRead.h b/MAC/APL/PIC/RSPDriver/src/RawBlockRead.h new file mode 100644 index 00000000000..57e4d632f64 --- /dev/null +++ b/MAC/APL/PIC/RSPDriver/src/RawBlockRead.h @@ -0,0 +1,57 @@ +//# -*- mode: c++ -*- +//# +//# RawBlockRead.h: Synchronize HBA settings with HBA hardware via RCU interface. +//# +//# Copyright (C) 2002-2004 +//# 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 RSPRAWDATAREAD_H_ +#define RSPRAWDATAREAD_H_ + +#include <APL/RSP_Protocol/MEPHeader.h> + +#include "SyncAction.h" + +namespace LOFAR { + namespace RSP { + +class RawBlockRead : public SyncAction +{ +public: + // Constructors for a RawBlockRead object. + RawBlockRead(GCFPortInterface& board_port, int board_id); + virtual ~RawBlockRead(); + + // Send the write message. + virtual void sendrequest(); + + // Send the read request. + virtual void sendrequest_status(); + + // Handle the read result. + virtual GCFEvent::TResult handleack(GCFEvent& event, GCFPortInterface& port); + +private: + EPA_Protocol::MEPHeader m_hdr; +}; + }; // namespace RSP +}; // namespace LOFAR + +#endif /* RSPRAWDATAREAD_H_ */ diff --git a/MAC/APL/PIC/RSPDriver/src/RawBlockWrite.cc b/MAC/APL/PIC/RSPDriver/src/RawBlockWrite.cc new file mode 100644 index 00000000000..926776d4c33 --- /dev/null +++ b/MAC/APL/PIC/RSPDriver/src/RawBlockWrite.cc @@ -0,0 +1,134 @@ +//# RawBlockWrite.cc: implementation of the RawBlockWrite class +//# +//# Copyright (C) 2002-2004 +//# 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 <Common/hexdump.h> +#include <APL/RSP_Protocol/EPA_Protocol.ph> + +#include <APL/RTCCommon/PSAccess.h> +#include <string.h> + +#include "StationSettings.h" +#include "HBAProtocolWrite.h" +#include "RawBlockWrite.h" +#include "Cache.h" + +#include <netinet/in.h> + +using namespace LOFAR; +using namespace RSP; +using namespace EPA_Protocol; +using namespace blitz; + +// +// RawBlockWrite(port, boardID) +// +RawBlockWrite::RawBlockWrite(GCFPortInterface& board_port, int board_id) + : SyncAction(board_port, board_id, 1) +{ + memset(&m_hdr, 0, sizeof(MEPHeader)); +} + +// +// ~RawBlockWrite() +// +RawBlockWrite::~RawBlockWrite() +{ + /* TODO: delete event? */ +} + +// +// sendrequest() +// +void RawBlockWrite::sendrequest() +{ + // skip update if nothing was modified + if (Cache::getInstance().getState().rawdatawrite().get(getBoardId()) != RTC::RegisterState::WRITE) { + Cache::getInstance().getState().rawdatawrite().unmodified(getBoardId()); + setContinue(true); +// LOG_INFO_STR("@@@RawBlockWrite::sendrequest(" << getBoardId() << "):false"); + return; + } +// LOG_INFO_STR("@@@RawBlockWrite::sendrequest(" << getBoardId() << "):true"); + + // Cache was modified, construct an EPA message and send it. + EPAWriteEvent writeEvent; + RawDataBlock_t& rdb = Cache::getInstance().getBack().getRawDataBlock(); // pointer to info + // construct header, but overwrite complete address with address from user + writeEvent.hdr.set(MEPHeader::RSP_RAWDATA_WRITE, 0, MEPHeader::WRITE, rdb.dataLen, rdb.offset); + memcpy((void*)&(writeEvent.hdr.m_fields.addr), (void*)&(rdb.address), sizeof(rdb.address)); + // construct data part + writeEvent.payload.setBuffer(rdb.data, rdb.dataLen); + + m_hdr = writeEvent.hdr; // remember header to match with ack + +// string hDump; // DEBUG +// hexdump(hDump, (void*)&m_hdr.m_fields, MEPHeader::SIZE); // DEBUG +// LOG_INFO (hDump); +// hDump.clear(); +// hexdump(hDump, writeEvent.payload.getBuffer(), writeEvent.payload.getDataLen()); +// LOG_INFO (hDump); + + // finally send the message + getBoardPort().send(writeEvent); + + // we never want a rawBlock command to be repeated so mark it 'done' on forehand. + Cache::getInstance().getState().rawdatawrite().write_ack(getBoardId()); +} + +// +// sendrequest_status() +// +void RawBlockWrite::sendrequest_status() +{ + // intentionally left empty +} + +// +// handleack(event, port) +// +GCFEvent::TResult RawBlockWrite::handleack(GCFEvent& event, GCFPortInterface& /*port*/) +{ +// LOG_INFO_STR("@@@RawBlockWrite::handleack(" << getBoardId() << ")"); + + // Note: we don't have to check the event.signal here because it is always safe to + // convert an event to a generic readackEvent. + // We can't even check it because the user made up the address and therefor the response-type. + EPAWriteackEvent ack(event); + +// string hDump; /// DEBUG +// hexdump(hDump, (void*)&(ack.hdr.m_fields), MEPHeader::SIZE); +// LOG_INFO (hDump); + + // check result + if (!ack.hdr.isValidAck(m_hdr)) { + LOG_ERROR("RawBlockWrite::handleack: invalid ack"); + Cache::getInstance().getState().rawdatawrite().write_error(getBoardId()); + return GCFEvent::HANDLED; + } + + // Mark command ok. + Cache::getInstance().getState().rawdatawrite().write_ack(getBoardId()); + + return GCFEvent::HANDLED; +} diff --git a/MAC/APL/PIC/RSPDriver/src/RawBlockWrite.h b/MAC/APL/PIC/RSPDriver/src/RawBlockWrite.h new file mode 100644 index 00000000000..7df842637be --- /dev/null +++ b/MAC/APL/PIC/RSPDriver/src/RawBlockWrite.h @@ -0,0 +1,57 @@ +//# -*- mode: c++ -*- +//# +//# RawBlockWrite.h: Synchronize HBA settings with HBA hardware via RCU interface. +//# +//# Copyright (C) 2002-2004 +//# 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 RAWBLOCKWRITE_H_ +#define RAWBLOCKWRITE_H_ + +#include <APL/RSP_Protocol/MEPHeader.h> + +#include "SyncAction.h" + +namespace LOFAR { + namespace RSP { + +class RawBlockWrite : public SyncAction +{ +public: + // Constructors for a RawBlockWrite object. + RawBlockWrite(GCFPortInterface& board_port, int board_id); + virtual ~RawBlockWrite(); + + // Send the write message. + virtual void sendrequest(); + + // Send the read request. + virtual void sendrequest_status(); + + // Handle the read result. + virtual GCFEvent::TResult handleack(GCFEvent& event, GCFPortInterface& port); + +private: + EPA_Protocol::MEPHeader m_hdr; +}; + }; // namespace RSP +}; // namespace LOFAR + +#endif /* RAWBLOCKWRITE_H_ */ diff --git a/MAC/APL/PIC/RSPDriver/src/RawEvent.cc b/MAC/APL/PIC/RSPDriver/src/RawEvent.cc index 567f47b9ad3..314db3de62d 100644 --- a/MAC/APL/PIC/RSPDriver/src/RawEvent.cc +++ b/MAC/APL/PIC/RSPDriver/src/RawEvent.cc @@ -23,6 +23,7 @@ #include <lofar_config.h> #include <Common/LofarLogger.h> +#include <Common/hexdump.h> #include <GCF/TM/GCF_ETHRawPort.h> #include <APL/RSP_Protocol/EPA_Protocol.ph> @@ -709,103 +710,104 @@ GCFEvent::TResult RawEvent::dispatch(GCFTask& task, GCFPortInterface& port) { #if 0 - cout << " sizeof(RawFrame) =" << sizeof(RawFrame) << endl - << " sizeof(GCFEvent) =" << sizeof(GCFEvent) << endl - << " sizeof(MEPHeader::FieldsType) =" << sizeof(MEPHeader::FieldsType) << endl - << " sizeof(payload) =" << sizeof(buf.payload) << endl; + cout << " sizeof(RawFrame) =" << sizeof(RawFrame) << endl + << " sizeof(GCFEvent) =" << sizeof(GCFEvent) << endl + << " sizeof(MEPHeader::FieldsType) =" << sizeof(MEPHeader::FieldsType) << endl + << " sizeof(payload) =" << sizeof(buf.payload) << endl; #endif - GCFEvent::TResult status = GCFEvent::NOT_HANDLED; - - // Receive a raw packet - ssize_t size = port.recv(&buf.mephdr, ETH_DATA_LEN); - - if (size < (ssize_t)sizeof(buf.mephdr)) return GCFEvent::NOT_HANDLED; - - LOG_DEBUG(formatString("F_DATAIN: type=0x%02x, status=%d, frame_length=%d, " - "addr=(0x%04x 0x%02x 0x%02x), payload_length=%d, " - "seqnr=%d", - buf.mephdr.type, - buf.mephdr.status, - buf.mephdr.frame_length, - buf.mephdr.addr.dstid, - buf.mephdr.addr.pid, - buf.mephdr.addr.regid, - buf.mephdr.payload_length, - buf.mephdr.seqnr)); - - unsigned short signal = 0; // signal == 0 indicates unrecognised or invalid MEP message - - // - // Decode the header fields - // - if ( buf.mephdr.type >= MEPHeader::MIN_TYPE - && buf.mephdr.type <= MEPHeader::MAX_TYPE - && buf.mephdr.addr.pid >= MEPHeader::MIN_PID - && buf.mephdr.addr.pid <= MEPHeader::MAX_PID - && buf.mephdr.addr.regid <= MEPHeader::MAX_REGID) - /* always true due to limited range of datatype - && buf.mephdr.addr.regid >= MEPHeader::MIN_REGID */ - { - // - // If no error, lookup signal number, else assign ACK_ERROR signal number - // - if (0 == buf.mephdr.status) - { - signal = signal_lut[buf.mephdr.addr.pid - MEPHeader::MIN_PID][buf.mephdr.addr.regid][buf.mephdr.type]; - } - else - { - if (MEPHeader::READACK == buf.mephdr.type) signal = EPA_READACK_ERROR; - else if (MEPHeader::WRITEACK == buf.mephdr.type) signal = EPA_WRITEACK_ERROR; - else - { - LOG_WARN("Protocol violation: received message other than MEPHeader::READACK or MEPHeader::WRITEACK with error != 0 set."); - } - } - } else { - LOG_WARN("Received message with out-of-range header fields"); - } - - if (signal) // signal == 0 indicates unrecognised or invalid MEP message - { - (void)new((void*)&buf.event) GCFEvent(signal); // placement new does in place construction - - // set the event length - buf.event.length = sizeof(buf.mephdr) + buf.mephdr.payload_length; - - // check if there is more data than needed - if (size - (sizeof(GCFEvent) + sizeof(MEPHeader::FieldsType)) > 0) - { - LOG_DEBUG(formatString("discarding %d bytes", size - (sizeof(GCFEvent) + sizeof(MEPHeader::FieldsType)))); - } - - // - // Print debugging info - // + GCFEvent::TResult status = GCFEvent::NOT_HANDLED; + + // Receive a raw packet + ssize_t size = port.recv(&buf.mephdr, ETH_DATA_LEN); + + // always need at least header_size bytes. + if (size < (ssize_t)sizeof(buf.mephdr)) { + return GCFEvent::NOT_HANDLED; + } + + LOG_DEBUG(formatString("F_DATAIN: type=0x%02x, status=%d, frame_length=%d, " + "addr=(0x%04x 0x%02x 0x%02x), payload_length=%d, seqnr=%d", + buf.mephdr.type, + buf.mephdr.status, + buf.mephdr.frame_length, + buf.mephdr.addr.dstid, + buf.mephdr.addr.pid, + buf.mephdr.addr.regid, + buf.mephdr.payload_length, + buf.mephdr.seqnr)); + + unsigned short signal = 0; // signal == 0 indicates unrecognised or invalid MEP message + + // + // Decode the header fields + // + if ( buf.mephdr.type >= MEPHeader::MIN_TYPE + && buf.mephdr.type <= MEPHeader::MAX_TYPE + && buf.mephdr.addr.pid >= MEPHeader::MIN_PID + && buf.mephdr.addr.pid <= MEPHeader::MAX_PID + && buf.mephdr.addr.regid <= MEPHeader::MAX_REGID) { + /* always true due to limited range of datatype + && buf.mephdr.addr.regid >= MEPHeader::MIN_REGID */ + // + // If no error, lookup signal number, else assign ACK_ERROR signal number + // + if (buf.mephdr.status == 0) { + signal = signal_lut[buf.mephdr.addr.pid - MEPHeader::MIN_PID][buf.mephdr.addr.regid][buf.mephdr.type]; + } + else { + if (MEPHeader::READACK == buf.mephdr.type) { + signal = EPA_READACK_ERROR; + } + else if (MEPHeader::WRITEACK == buf.mephdr.type) { + signal = EPA_WRITEACK_ERROR; + } + else { + LOG_WARN("Protocol violation: received message other than MEPHeader::READACK or MEPHeader::WRITEACK with error != 0 set."); + } + } // status + } else { + LOG_WARN("Received message with out-of-range header fields"); + string hDump; + hexdump (hDump, (char*)&buf.mephdr, sizeof(buf.mephdr)); + LOG_INFO (hDump); + } + + if (signal) { // signal == 0 indicates unrecognised or invalid MEP message + (void)new((void*)&buf.event) GCFEvent(signal); // placement new does in place construction + + // set the event length + buf.event.length = sizeof(buf.mephdr) + buf.mephdr.payload_length; + + // check if there is more data than needed + if (size - (sizeof(GCFEvent) + sizeof(MEPHeader::FieldsType)) > 0) { + LOG_DEBUG(formatString("discarding %d bytes", size - (sizeof(GCFEvent) + sizeof(MEPHeader::FieldsType)))); + } + + // + // Print debugging info + // #if 0 - if ((F_DATAIN != buf.event.signal) && + if ((F_DATAIN != buf.event.signal) && (F_DATAOUT != buf.event.signal) && (F_EVT_PROTOCOL(buf.event) != F_FSM_PROTOCOL) && - (F_EVT_PROTOCOL(buf.event) != F_PORT_PROTOCOL)) - { - LOG_DEBUG(formatString("%s receives '%s' on port '%s'", - task.getName().c_str(), - task.evtstr(buf.event), port.getName().c_str())); - } + (F_EVT_PROTOCOL(buf.event) != F_PORT_PROTOCOL)) { + LOG_DEBUG(formatString("%s receives '%s' on port '%s'", + task.getName().c_str(), + task.evtstr(buf.event), port.getName().c_str())); + } #endif - // - // dispatch the MEP message as a GCFEvent (which it now is) - // - status = task.dispatch(buf.event, port); - } - else - { - LOG_WARN("F_DATAIN: Discarding unknown message."); - } + // + // dispatch the MEP message as a GCFEvent (which it now is) + // + status = task.dispatch(buf.event, port); + } + else { + LOG_WARN("F_DATAIN: Discarding unknown message."); + } - return status; + return (status); } diff --git a/MAC/APL/PIC/RSPDriver/src/Scheduler.cc b/MAC/APL/PIC/RSPDriver/src/Scheduler.cc index 465178f5d5a..72a2a8ff4a8 100644 --- a/MAC/APL/PIC/RSPDriver/src/Scheduler.cc +++ b/MAC/APL/PIC/RSPDriver/src/Scheduler.cc @@ -38,471 +38,473 @@ int Scheduler::SYNC_INTERVAL_INT = 1; // default Scheduler::Scheduler() { - SYNC_INTERVAL_INT = (int)trunc(GET_CONFIG("RSPDriver.SYNC_INTERVAL", f)+0.5); + SYNC_INTERVAL_INT = (int)trunc(GET_CONFIG("RSPDriver.SYNC_INTERVAL", f)+0.5); } Scheduler::~Scheduler() { - /* clear the various queues */ - while (!m_later_queue.empty()) m_later_queue.pop(); - while (!m_now_queue.empty()) m_now_queue.pop(); - while (!m_periodic_queue.empty()) m_periodic_queue.pop(); - while (!m_done_queue.empty()) m_done_queue.pop(); - - for (map< GCFPortInterface*, vector<SyncAction*> >::iterator port = m_syncactions.begin(); - port != m_syncactions.end(); - port++) - { - for (vector<SyncAction*>::iterator sa = (*port).second.begin(); - sa != (*port).second.end(); - sa++) - { - delete (*sa); - } - } + /* clear the various queues */ + while (!m_later_queue.empty()) m_later_queue.pop(); + while (!m_now_queue.empty()) m_now_queue.pop(); + while (!m_periodic_queue.empty()) m_periodic_queue.pop(); + while (!m_done_queue.empty()) m_done_queue.pop(); + + for (map< GCFPortInterface*, vector<SyncAction*> >::iterator port = m_syncactions.begin(); + port != m_syncactions.end(); port++) { + for (vector<SyncAction*>::iterator sa = (*port).second.begin(); + sa != (*port).second.end(); sa++) { + delete (*sa); + } + } } +// +// run(event, port) +// GCFEvent::TResult Scheduler::run(GCFEvent& event, GCFPortInterface& /*port*/) { - const GCFTimerEvent* timeout = static_cast<const GCFTimerEvent*>(&event); - - if (F_TIMER == event.signal) - { - LOG_DEBUG("Scheduler::run"); - - if (!syncHasCompleted()) - { - LOG_ERROR("previous sync has not yet completed!, skipping sync"); - for (map< GCFPortInterface*, bool >::iterator it = m_sync_completed.begin(); - it != m_sync_completed.end(); - it++) - { - if (!(*it).second) - { - LOG_WARN(formatString("port %s has not yet completed sync, trying to continue...", - (*it).first->getName().c_str())); + const GCFTimerEvent* timeout = static_cast<const GCFTimerEvent*>(&event); + + if (F_TIMER == event.signal) { + LOG_DEBUG("Scheduler::run"); + + if (!syncHasCompleted()) { + LOG_ERROR("previous sync has not yet completed!, skipping sync"); + for (map< GCFPortInterface*, bool >::iterator it = m_sync_completed.begin(); + it != m_sync_completed.end(); it++) { + if (!(*it).second) { + LOG_WARN(formatString("port %s has not yet completed sync, trying to continue...", + (*it).first->getName().c_str())); + } + + // reset the statemachines of all SyncActions for this port + resetSync(*(*it).first); + } + + // This is caused by a problem with the firmware + // or a loose cable, simply try to continue. + // + // In the future some more elaborate fault handling + // might be required. + completeSync(); + } + + // round to nearest second t, warn if time is too far off from top of second + // + // t-1 t t+1 + // XXXX|<--->|XXXX + unsigned long topofsecond = timeout->sec; + if (timeout->usec >= 1e6-1000) { + topofsecond++; // round to next whole second + } + if (timeout->usec > 1000 && timeout->usec < 1e6 - 1000) { + LOG_WARN_STR("Scheduler time too far off from top off second: usec=" << timeout->usec); + } + setCurrentTime(topofsecond, 0); + + scheduleCommands(); + processCommands(); + + initiateSync(event); // matched by completeSync + } + else { + LOG_ERROR("\nreceived invalid event != F_TIMER\n"); } - // - // reset the statemachines of all SyncActions for this port - // - resetSync(*(*it).first); - } - - // - // This is caused by a problem with the firmware - // or a loose cable, simply try to continue. - // - // In the future some more elaborate fault handling - // might be required. - // - completeSync(); - } - - // - // round to nearest second t, warn if time is too far off from top of second - // - // t-1 t t+1 - // XXXX|<--->|XXXX - // - unsigned long topofsecond = timeout->sec; - if (timeout->usec >= 1e6-1000) topofsecond++; // round to next whole second - if (timeout->usec > 1000 && timeout->usec < 1e6 - 1000) { - LOG_WARN_STR("Scheduler time too far off from top off second: usec=" << timeout->usec); - } - setCurrentTime(topofsecond, 0); - - scheduleCommands(); - processCommands(); - - initiateSync(event); // matched by completeSync - } - else - { - LOG_ERROR("\nreceived invalid event != F_TIMER\n"); - } - - return GCFEvent::HANDLED; + return GCFEvent::HANDLED; } +// +// dispatch (event, port) +// GCFEvent::TResult Scheduler::dispatch(GCFEvent& event, GCFPortInterface& port) { - GCFEvent::TResult status = GCFEvent::NOT_HANDLED; - GCFTimerEvent timer; - GCFEvent* current_event = &event; - bool sync_completed = true; - - /** - * Dispatch the event to the first SyncAction that - * has not yet reached its 'final' state. - */ - vector<SyncAction*>::iterator sa; - int i = 0; - for (sa = m_syncactions[&port].begin(); - sa != m_syncactions[&port].end(); - sa++, i++) - { - if (!(*sa)->hasCompleted()) - { - // stil busy - sync_completed = false; - - status = (*sa)->dispatch(*current_event, (*sa)->getBoardPort()); - - // - // if the syncaction has not yet been completed, break the loop - // it will receive another event to continue - // - if (!(*sa)->hasCompleted()) break; - else - { - sync_completed = true; - current_event = &timer; - } - } - } - - if (sync_completed) - { - m_sync_completed[&port] = true; - } - - if (syncHasCompleted()) - { - completeSync(); - } - - return status; + GCFEvent::TResult status = GCFEvent::NOT_HANDLED; + GCFTimerEvent timer; + GCFEvent* current_event = &event; + bool sync_completed = true; + + // Dispatch the event to the first SyncAction that + // has not yet reached its 'final' state. + vector<SyncAction*>::iterator sa; + int i = 0; + for (sa = m_syncactions[&port].begin(); sa != m_syncactions[&port].end(); sa++, i++) { + if (!(*sa)->hasCompleted()) { + // stil busy + sync_completed = false; + status = (*sa)->dispatch(*current_event, (*sa)->getBoardPort()); + + // if the syncaction has not yet been completed, break the loop + // it will receive another event to continue + if (!(*sa)->hasCompleted()) { + break; + } + else { + sync_completed = true; + current_event = &timer; + } + } + } + + if (sync_completed) { + m_sync_completed[&port] = true; + } + + if (syncHasCompleted()) { // all boards ready??? + completeSync(); + } + + return status; } +// +// syncHasCompleted +// +// Check if all boards have finished their sequence. +// bool Scheduler::syncHasCompleted() { - bool result = true; - - for (map< GCFPortInterface*, bool >::iterator it = m_sync_completed.begin(); - it != m_sync_completed.end(); - it++) - { - if (!(*it).second) { result = false; } - } - - return result; + for (map< GCFPortInterface*, bool >::iterator it = m_sync_completed.begin(); + it != m_sync_completed.end(); it++) { + if (!(*it).second) { + return(false); + } + } + + return (true); } -int Scheduler::pqueue_remove_commands(pqueue& pq, - GCFPortInterface& port, - memptr_t handle) +// +// pqueue_remove_commands(pqueue, port, memptr) +// +int Scheduler::pqueue_remove_commands(pqueue& pq, + GCFPortInterface& port, + memptr_t handle) { - int count = 0; - - // copy pq - pqueue tmp(pq); - - // clear pq, it will be filled again in the next loop - while (!pq.empty()) pq.pop(); - - while (!tmp.empty()) - { - // pop item from the queue - Ptr<Command> c = tmp.top(); - tmp.pop(); - - // if port matches, delete c, else push back onto pq - if ((c->getPort() == &port) && (0 == handle || &(*c) == (Command*)handle)) - { - count++; - // don't push back on pq, c will be deleted when it goes out of scope - } - else pq.push(c); - } - - return count; + int count = 0; + + // copy pq + pqueue tmp(pq); + + // clear pq, it will be filled again in the next loop + while (!pq.empty()) { + pq.pop(); + } + + while (!tmp.empty()) { + // pop item from the queue + Ptr<Command> c = tmp.top(); + tmp.pop(); + + // if port matches, delete c, else push back onto pq + if ((c->getPort() == &port) && (0 == handle || &(*c) == (Command*)handle)) { + count++; + // don't push back on pq, c will be deleted when it goes out of scope + } + else { + pq.push(c); + } + } + + return count; } +// +// cancel(port) +// int Scheduler::cancel(GCFPortInterface& port) { - int count = 0; - - // cancel all commands related to this port - // irrespective of the queue they are in - - count += pqueue_remove_commands(m_later_queue, port); - count += pqueue_remove_commands(m_now_queue, port); - count += pqueue_remove_commands(m_periodic_queue, port); - count += pqueue_remove_commands(m_done_queue, port); - - return count; + // cancel all commands related to this port + // irrespective of the queue they are in + int count = 0; + count += pqueue_remove_commands(m_later_queue, port); + count += pqueue_remove_commands(m_now_queue, port); + count += pqueue_remove_commands(m_periodic_queue, port); + count += pqueue_remove_commands(m_done_queue, port); + + return count; } +// +// remove_subscription(port, memptr) +// int Scheduler::remove_subscription(GCFPortInterface& port, memptr_t handle) { - int count = 0; + int count = 0; + count += pqueue_remove_commands(m_later_queue, port, handle); + count += pqueue_remove_commands(m_now_queue, port, handle); + count += pqueue_remove_commands(m_periodic_queue, port, handle); + count += pqueue_remove_commands(m_done_queue, port, handle); - count += pqueue_remove_commands(m_later_queue, port, handle); - count += pqueue_remove_commands(m_now_queue, port, handle); - count += pqueue_remove_commands(m_periodic_queue, port, handle); - count += pqueue_remove_commands(m_done_queue, port, handle); - - return count; + return count; } +// +// addSyncAction(action) +// void Scheduler::addSyncAction(SyncAction* action) { - m_syncactions[&(action->getBoardPort())].push_back(action); + m_syncactions[&(action->getBoardPort())].push_back(action); } +// +// enter(command, queue) +// Timestamp Scheduler::enter(Ptr<Command> command, QueueID queue) { - Timestamp scheduled_time = command->getTimestamp(); - - /* determine at which time the command can actually be carried out */ - if (scheduled_time.sec() < m_current_time.sec() + SCHEDULING_DELAY) - { - if (scheduled_time.sec() > 0) // filter Timestamp(0,0) case - { - LOG_WARN(formatString("command missed deadline by %d seconds", - m_current_time.sec() - scheduled_time.sec())); - } - - scheduled_time = m_current_time + (long)SCHEDULING_DELAY; - } - - // set the actual time at which the command is sent to the boards - command->setTimestamp(scheduled_time); - - // print time, ugly - char timestr[32]; - time_t sec = scheduled_time.sec(); - strftime(timestr, 32, "%T", gmtime(&sec)); - LOG_DEBUG(formatString("Scheduler::enter scheduled_time=%s.%d UTC", timestr, scheduled_time.usec())); - - // push the command on the appropriate queue - switch (queue) - { - case LATER: - m_later_queue.push(command); - break; - - case PERIODIC: - m_periodic_queue.push(command); - break; - - default: - LOG_FATAL("invalid QueueID"); - exit(EXIT_FAILURE); - break; - } - - return Timestamp(0,0); // this return value should not be used anymore + Timestamp scheduled_time = command->getTimestamp(); + + /* determine at which time the command can actually be carried out */ + if (scheduled_time.sec() < m_current_time.sec() + SCHEDULING_DELAY) { + if (scheduled_time.sec() > 0) { // filter Timestamp(0,0) case + LOG_WARN(formatString("command missed deadline by %d seconds", + m_current_time.sec() - scheduled_time.sec())); + } + + scheduled_time = m_current_time + (long)SCHEDULING_DELAY; + } + + // set the actual time at which the command is sent to the boards + command->setTimestamp(scheduled_time); + + // print time, ugly + char timestr[32]; + time_t sec = scheduled_time.sec(); + strftime(timestr, 32, "%T", gmtime(&sec)); + LOG_DEBUG(formatString("Scheduler::enter scheduled_time=%s.%d UTC", timestr, scheduled_time.usec())); + + // push the command on the appropriate queue + switch (queue) { + case LATER: + m_later_queue.push(command); + break; + + case PERIODIC: + m_periodic_queue.push(command); + break; + + default: + LOG_FATAL("invalid QueueID"); + exit(EXIT_FAILURE); + break; + } + + return Timestamp(0,0); // this return value should not be used anymore } +// +// setCurrentTime(sec, usec) +// void Scheduler::setCurrentTime(long sec, long usec) { - /* adjust the current time */ - m_current_time = Timestamp(sec, usec); + /* adjust the current time */ + m_current_time = Timestamp(sec, usec); } +// +// getCurrentTime() +// Timestamp Scheduler::getCurrentTime() const { - return m_current_time; + return m_current_time; } +// +// scheduleCommands() +// +// Schedule commands from later-queue and periodic-queue by setting them in the now-queue +// void Scheduler::scheduleCommands() { - int scheduling_offset = 0; - - /** - * All commands with a timestamp equal to the - * wall-clock time (m_current_time) plus one second - * should be scheduled now. - */ - while (!m_later_queue.empty()) - { - Ptr<Command> command = m_later_queue.top(); - - // write commands need to be scheduled on sync period ahead of time - // to be effective in the hardware at the specified timestamp - scheduling_offset = 0; - if (Command::WRITE == command->getOperation()) - { - scheduling_offset = SYNC_INTERVAL_INT; - } - - /* detect late commands, but just execute them */ - if (command->getTimestamp() <= m_current_time + (long)(scheduling_offset - SYNC_INTERVAL_INT)) - { - LOG_WARN_STR("command is late, timestamp=" << command->getTimestamp() - << ", current_time=" << m_current_time); - } - - if (command->getTimestamp() <= m_current_time + (long)scheduling_offset) - { - LOG_DEBUG_STR("scheduling command with time=" << command->getTimestamp()); - - m_now_queue.push(command); - m_later_queue.pop(); - } - else break; - } - - /* copy periodic commands to the now queue */ - pqueue pq = m_periodic_queue; - - while (!pq.empty()) - { - Ptr<Command> command = pq.top(); - - // read commands need to be scheduled on sync period ahead of time - // to be effective in the hardware at the specified timestamp - scheduling_offset = 0; - if (Command::WRITE == command->getOperation()) - { - scheduling_offset = SYNC_INTERVAL_INT; - } - - /* detect late commands, but just execute them */ - if (command->getTimestamp() <= m_current_time + (long)(scheduling_offset - SYNC_INTERVAL_INT)) - { - LOG_WARN_STR("periodic command is late, timestamp=" << command->getTimestamp() - << ", current_time=" << m_current_time); - } - - if (command->getTimestamp() <= m_current_time + (long)scheduling_offset) - { - LOG_DEBUG_STR("scheduling periodic command with time=" << command->getTimestamp()); - m_now_queue.push(command); - } - - pq.pop(); // next - } + int scheduling_offset = 0; + + // All commands with a timestamp equal to the + // wall-clock time (m_current_time) plus one second + // should be scheduled now. + while (!m_later_queue.empty()) { + Ptr<Command> command = m_later_queue.top(); + + // write commands need to be scheduled on sync period ahead of time + // to be effective in the hardware at the specified timestamp + scheduling_offset = 0; + if (Command::WRITE == command->getOperation()) { + scheduling_offset = SYNC_INTERVAL_INT; + } + + /* detect late commands, but just execute them */ + if (command->getTimestamp() <= m_current_time + (long)(scheduling_offset - SYNC_INTERVAL_INT)) { + LOG_WARN_STR("command is late, timestamp=" << command->getTimestamp() + << ", current_time=" << m_current_time); + } + + if (command->getTimestamp() <= m_current_time + (long)scheduling_offset) { + LOG_DEBUG_STR("scheduling command with time=" << command->getTimestamp()); + + m_now_queue.push(command); + m_later_queue.pop(); + } + else { + break; + } + } + + /* copy periodic commands to the now queue */ + pqueue pq = m_periodic_queue; + + while (!pq.empty()) { + Ptr<Command> command = pq.top(); + + // read commands need to be scheduled on sync period ahead of time + // to be effective in the hardware at the specified timestamp + scheduling_offset = 0; + if (Command::WRITE == command->getOperation()) { + scheduling_offset = SYNC_INTERVAL_INT; + } + + /* detect late commands, but just execute them */ + if (command->getTimestamp() <= m_current_time + (long)(scheduling_offset - SYNC_INTERVAL_INT)) { + LOG_WARN_STR("periodic command is late, timestamp=" << command->getTimestamp() + << ", current_time=" << m_current_time); + } + + if (command->getTimestamp() <= m_current_time + (long)scheduling_offset) { + LOG_DEBUG_STR("scheduling periodic command with time=" << command->getTimestamp()); + m_now_queue.push(command); + } + + pq.pop(); // next + } } +// +// processCommands() +// +// Call 'apply' on every command in the now_queue +// void Scheduler::processCommands() { - Cache::getInstance().getFront().setTimestamp(getCurrentTime()); - Cache::getInstance().getFront().setTimestamp(getCurrentTime()); - - while (!m_now_queue.empty()) - { - Ptr<Command> command = m_now_queue.top(); - - /* * - * Let the commands apply their changes to - * the front and back caches. - */ - command->apply(Cache::getInstance().getFront(), true); - command->apply(Cache::getInstance().getBack(), false); - - /* move from the now queue to the done queue */ - m_now_queue.pop(); - m_done_queue.push(command); - } + Cache::getInstance().getFront().setTimestamp(getCurrentTime()); + Cache::getInstance().getFront().setTimestamp(getCurrentTime()); + + while (!m_now_queue.empty()) { + Ptr<Command> command = m_now_queue.top(); + + // Let the commands apply their changes to + // the front and back caches. + command->apply(Cache::getInstance().getFront(), true); + command->apply(Cache::getInstance().getBack(), false); + + // move from the now queue to the done queue + m_now_queue.pop(); + m_done_queue.push(command); + } } +// +// initiateSync(event) +// void Scheduler::initiateSync(GCFEvent& event) { - m_sync_completed.clear(); - - /** - * Send the first syncaction for each board the timer - * event to set of the data communication to each board. - */ - for (map< GCFPortInterface*, vector<SyncAction*> >::iterator port = m_syncactions.begin(); - port != m_syncactions.end(); - port++) - { - // reset sync flag - m_sync_completed[(*port).first] = false; - - for (vector<SyncAction*>::iterator sa = (*port).second.begin(); - sa != (*port).second.end(); - sa++) - { - (*sa)->setCompleted(false); - } - - // dispatch F_TIMER event to first syncactions for each board - if (!(*port).second.empty()) - { - for (unsigned int i = 0; i < (*port).second.size(); i++) { - (*port).second[i]->dispatch(event, (*port).second[i]->getBoardPort()); - if (!(*port).second[i]->doContinue()) break; - } - } - } + m_sync_completed.clear(); + + // Send the first syncaction for each board the timer + // event to set of the data communication to each board. + for (map< GCFPortInterface*, vector<SyncAction*> >::iterator port = m_syncactions.begin(); + port != m_syncactions.end(); port++) { + // first reset our sync flag + m_sync_completed[(*port).first] = false; + + // also mark all commands as not completed yet. + for (vector<SyncAction*>::iterator sa = (*port).second.begin(); + sa != (*port).second.end(); sa++) { + (*sa)->setCompleted(false); + } + + // dispatch F_TIMER event to first syncactions for each board + if (!(*port).second.empty()) { + for (unsigned int i = 0; i < (*port).second.size(); i++) { + (*port).second[i]->dispatch(event, (*port).second[i]->getBoardPort()); + if (!(*port).second[i]->doContinue()) { + break; + } + } + } + } } +// +// resetSync(port) +// +// Reset the state machines of all Sync Actions +// for the port, to attempt another sync in the next +// update period. +// void Scheduler::resetSync(GCFPortInterface& port) { - /** - * Reset the state machines of all Sync Actions - * for the port, to attempt another sync in the next - * update period. - */ - vector<SyncAction*>::iterator sa; - int i = 0; - for (sa = m_syncactions[&port].begin(); - sa != m_syncactions[&port].end(); - sa++, i++) - { - (*sa)->reset(); - } + vector<SyncAction*>::iterator sa; + for (sa = m_syncactions[&port].begin(); sa != m_syncactions[&port].end(); sa++) { + (*sa)->reset(); + } } +// +//completeSync() +// void Scheduler::completeSync() { - // print current state for all registers - ostringstream logStream; - Cache::getInstance().getState().print(logStream); - LOG_DEBUG_STR(logStream); + // print current state for all registers + ostringstream logStream; + Cache::getInstance().getState().print(logStream); + LOG_DEBUG_STR(logStream); - // swap the buffers - // new data from the boards which was in the back buffers - // will end up in the front buffers. - Cache::getInstance().swapBuffers(); + // swap the buffers + // new data from the boards which was in the back buffers + // will end up in the front buffers. + Cache::getInstance().swapBuffers(); - // complete any outstanding commands - completeCommands(); + // complete any outstanding commands + completeCommands(); - // clear from DONE to IDLE state - Cache::getInstance().getState().clear(); + // clear from DONE to IDLE state + Cache::getInstance().getState().clear(); - // schedule next update - Cache::getInstance().getState().schedule(); // if IDLE transition to READ or CHECK + // schedule next update + Cache::getInstance().getState().schedule(); // if IDLE transition to READ or CHECK } +// +// completeCommands() +// void Scheduler::completeCommands() { - while (!m_done_queue.empty()) - { - Ptr<Command> command = m_done_queue.top(); - - command->complete(Cache::getInstance().getFront()); - - // re-timestamp periodic commands for the next period - if (command->getPeriod()) - { - // Set the next time at which the periodic command should be executed. - // - // This is not as simple as doing command->setTimestamp(command->getTimestamp() + (long)command->getPeriod()); - // because command->getTimestamp() returns the previous time at which the command - // was executed. In some cases (due to missed PPSes) the sum of the previous timestamp - // and the period will be in the past causing the periodic command to be logged as - // 'late' from that point onwards. - // - // To correctly compute the next time at which a periodic command should execute, take - // the absolute current time and add the period, but make sure the periodic command - // continues to be executed on the grid defined by the period. E.g. if a command is - // executed every 4 seconds starting on second 1, so 1,5,9, etc and some PPSes are missed - // lets say PPS 10,11,12,13 (and current time is 13) then it should continue at time 17. - // - Timestamp newtime = getCurrentTime() - + ((long)command->getPeriod() - - ((long)command->getTimestamp() % (long)command->getPeriod())); - command->setTimestamp(newtime); - } - - m_done_queue.pop(); - } + while (!m_done_queue.empty()) { + Ptr<Command> command = m_done_queue.top(); + + command->complete(Cache::getInstance().getFront()); + + // re-timestamp periodic commands for the next period + if (command->getPeriod()) { + // Set the next time at which the periodic command should be executed. + // + // This is not as simple as doing command->setTimestamp(command->getTimestamp() + command->getPeriod()); + // because command->getTimestamp() returns the previous time at which the command + // was executed. In some cases (due to missed PPSes) the sum of the previous timestamp + // and the period will be in the past causing the periodic command to be logged as + // 'late' from that point onwards. + // + // To correctly compute the next time at which a periodic command should execute, take + // the absolute current time and add the period, but make sure the periodic command + // continues to be executed on the grid defined by the period. E.g. if a command is + // executed every 4 seconds starting on second 1, so 1,5,9, etc and some PPSes are missed + // lets say PPS 10,11,12,13 (and current time is 13) then it should continue at time 17. + // + Timestamp newtime = getCurrentTime() + + ((long)command->getPeriod() + - ((long)command->getTimestamp() % (long)command->getPeriod())); + command->setTimestamp(newtime); + } + + m_done_queue.pop(); + } } diff --git a/MAC/APL/PIC/RSPDriver/src/SetRawBlockCmd.cc b/MAC/APL/PIC/RSPDriver/src/SetRawBlockCmd.cc new file mode 100644 index 00000000000..bc5d7aeeeb8 --- /dev/null +++ b/MAC/APL/PIC/RSPDriver/src/SetRawBlockCmd.cc @@ -0,0 +1,158 @@ +//# SetRawBlockCmd.cc: implementation of the SetRawBlockCmd class +//# +//# Copyright (C) 2008 +//# 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 <Common/hexdump.h> + +#include <APL/RSP_Protocol/RSP_Protocol.ph> +#include <APL/RTCCommon/PSAccess.h> +#include <blitz/array.h> + +#include "StationSettings.h" +#include "SetRawBlockCmd.h" + +namespace LOFAR { + namespace RSP { +// using namespace blitz; + using namespace RSP_Protocol; + using namespace RTC; // Timestamp + +// +// SetRawBlockCmd(event, port, oper) +// +SetRawBlockCmd::SetRawBlockCmd(GCFEvent& event, GCFPortInterface& port, Operation oper) +{ + itsEvent = new RSPSetblockEvent(event); + + setOperation(oper); + setPeriod(0); + setPort(port); +} + +// +// ~SetRawBlockCmd() +// +SetRawBlockCmd::~SetRawBlockCmd() +{ + delete itsEvent; +} + +// +// ack(cache) +// +void SetRawBlockCmd::ack(CacheBuffer& cache) +{ + RSPSetblockackEvent ack; + ack.timestamp = getTimestamp(); + ack.boardID = itsEvent->boardID; + ack.status = SUCCESS; + + getPort()->send(ack); +} + +// +// apply(cache, setModFlag) +// +void SetRawBlockCmd::apply(CacheBuffer& cache, bool setModFlag) +{ + // fill the cache with the request and tickle it. +// LOG_INFO(formatString("@@@SetRawBlockCmd::apply(%d,%0X,%d,%d)", +// itsEvent->boardID, itsEvent->address, itsEvent->offset, itsEvent->dataLen)); + + // NOTE: [REO] I expected that the next 4 lines could also be in the if(setModFlag) + // but it turned out that the info is than in the front cache when the RawDataBlockRead + // command needs it!!! + // Since only one command can be scheduled at the time, I write it in both caches. + + // copy information (always?) to the cache + RawDataBlock_t& rdb = cache.getRawDataBlock(); + rdb.address = itsEvent->address; + rdb.offset = itsEvent->offset; + rdb.dataLen = itsEvent->dataLen; + memcpy(rdb.data, itsEvent->data, rdb.dataLen); + +// string hDump; +// hexdump(hDump, rdb.data, rdb.dataLen); +// LOG_INFO(hDump); + + if (setModFlag) { + // tell cache(status) that we expect a write action. + cache.getCache().getState().rawdatawrite().write(itsEvent->boardID); + } +} + +// +// complete(cache) +// +void SetRawBlockCmd::complete(CacheBuffer& cache) +{ + ack(cache); +} + +// +// getTimeStamp() +// +const Timestamp& SetRawBlockCmd::getTimestamp() const +{ + return (itsEvent->timestamp); +} + +// +// setTimestamp(timestamp) +// +void SetRawBlockCmd::setTimestamp(const Timestamp& timestamp) +{ + itsEvent->timestamp = timestamp; +} + +// +// validate() +// +bool SetRawBlockCmd::validate() const +{ + return (true); +} + +// +// readFromCache() +// +bool SetRawBlockCmd::readFromCache() const +{ + return (false); +} + +// +// ack_fail() +// +void SetRawBlockCmd::ack_fail() +{ + RSPSetblockackEvent ack; + ack.timestamp = getTimestamp(); + ack.status = FAILURE; + LOG_INFO ("SetRawBlockCmd::ack_fail"); + + getPort()->send(ack); +} + + } // namepsace RSP +} // namespace LOFAR diff --git a/MAC/APL/PIC/RSPDriver/src/SetRawBlockCmd.h b/MAC/APL/PIC/RSPDriver/src/SetRawBlockCmd.h new file mode 100644 index 00000000000..898a3385d70 --- /dev/null +++ b/MAC/APL/PIC/RSPDriver/src/SetRawBlockCmd.h @@ -0,0 +1,81 @@ +//# -*- mode: c++ -*- +//# +//# SetRawBlockCmd.h: Get system status command. +//# +//# Copyright (C) 2008 +//# 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 SET_RAWBLOCK_CMD_H +#define SET_RAWBLOCK_CMD_H + +#include "Command.h" +#include <APL/RSP_Protocol/RSP_Protocol.ph> + +#include <Common/LofarTypes.h> +#include <GCF/TM/GCF_Control.h> + +namespace LOFAR { + namespace RSP { + +class SetRawBlockCmd : public Command +{ +public: + // Constructors for a SetRawBlockCmd object. + SetRawBlockCmd(GCFEvent& event, GCFPortInterface& port, Operation oper); + + // Destructor for SetRawBlockCmd. */ + virtual ~SetRawBlockCmd(); + + // Acknowledge the command by sending the appropriate + // response on m_port. + virtual void ack(CacheBuffer& cache); + + // Make necessary changes to the cache for the next synchronization. + // Any changes will be sent to the RSP boards. + virtual void apply(CacheBuffer& cache, bool setModFlag = true); + + // Complete the command by sending the appropriate response on + // the m_answerport; + virtual void complete(CacheBuffer& cache); + + //@{ + // get timestamp of the event + virtual const RTC::Timestamp& getTimestamp() const; + virtual void setTimestamp(const RTC::Timestamp& timestamp); + //@} + + // Range check the parameters of the event. + virtual bool validate() const; + + // Return true if value should be read from cache. + bool readFromCache() const; + + // Send failure ack. + void ack_fail(); + +private: + SetRawBlockCmd(); // Default construction is not allowed. + RSPSetblockEvent* itsEvent; +}; + + } // namespace RSP +} // namespace LOFAR + +#endif /* SET_RAWBLOCK_CMD_H */ diff --git a/MAC/APL/PIC/RSPDriver/src/SyncAction.cc b/MAC/APL/PIC/RSPDriver/src/SyncAction.cc index fdb30f937c8..230b03f942a 100644 --- a/MAC/APL/PIC/RSPDriver/src/SyncAction.cc +++ b/MAC/APL/PIC/RSPDriver/src/SyncAction.cc @@ -82,53 +82,53 @@ GCFEvent::TResult SyncAction::idle_state(GCFEvent& event, GCFPortInterface& /*po GCFEvent::TResult SyncAction::sendrequest_state(GCFEvent& event, GCFPortInterface& /*port*/) { - GCFEvent::TResult status = GCFEvent::HANDLED; - - switch (event.signal) { - case F_ENTRY: { - for (;;) { - if (!m_atinit && Sequencer::getInstance().isActive()) { - // skip this action and continue with the next - setContinue(true); // continue with next action - } else { - // send initial request - setContinue(false); // initialize on each entry - sendrequest(); + GCFEvent::TResult status = GCFEvent::HANDLED; + + switch (event.signal) { + case F_ENTRY: { + for (;;) { + if (!m_atinit && Sequencer::getInstance().isActive()) { + // skip this action and continue with the next + setContinue(true); // continue with next action + } else { + // send initial request + setContinue(false); // initialize on each entry + sendrequest(); + } + + // if sendrequest calls setContinue(true), then no event + // has been sent, move on to next index + if (doContinue()) { + // OK, move on to the next index + m_current_index++; + m_retries = 0; + if (m_current_index >= m_n_indices) { + // done + setCompleted(true); + TRAN(SyncAction::idle_state); + break; // break the loop + } + } + else { + TRAN(SyncAction::waitack_state); + break; // break the loop + } + } } + break; - // if sendrequest calls setContinue(true), then no event - // has been sent, move on to next index - if (doContinue()) { - // OK, move on to the next index - m_current_index++; - m_retries = 0; - if (m_current_index >= m_n_indices) { - // done - setCompleted(true); - TRAN(SyncAction::idle_state); - break; // break the loop - } - } - else { - TRAN(SyncAction::waitack_state); - break; // break the loop + case F_TIMER: { + LOG_FATAL("missed real-time deadline"); + exit(EXIT_FAILURE); } - } - } - break; - - case F_TIMER: { - LOG_FATAL("missed real-time deadline"); - exit(EXIT_FAILURE); - } - break; + break; - default: - status = GCFEvent::NOT_HANDLED; - break; - } + default: + status = GCFEvent::NOT_HANDLED; + break; + } - return GCFEvent::HANDLED; + return GCFEvent::HANDLED; } GCFEvent::TResult SyncAction::waitack_state(GCFEvent& event, GCFPortInterface& port) diff --git a/MAC/APL/PIC/RSPDriver/src/rspctl.cc b/MAC/APL/PIC/RSPDriver/src/rspctl.cc index 53a4810e5d5..c4401b6cb93 100644 --- a/MAC/APL/PIC/RSPDriver/src/rspctl.cc +++ b/MAC/APL/PIC/RSPDriver/src/rspctl.cc @@ -54,6 +54,9 @@ #include "rspctl.h" +#define xtod(c) ((c>='0' && c<='9') ? c-'0' : ((c>='A' && c<='F') ? \ + c-'A'+10 : ((c>='a' && c<='f') ? c-'a'+10 : 0))) + namespace LOFAR { namespace rspctl { using namespace std; @@ -67,7 +70,7 @@ namespace LOFAR { double WGCommand::AMPLITUDE_SCALE = (1.0 * ((uint32)(1 << 11)-1) / (uint32)(1 << 11)) * (uint32)(1 << 31); // local funtions -static void usage(); +static void usage(bool); // getting real or sent hba values static bool realDelays = false; @@ -108,33 +111,24 @@ inline complex<double> convert_to_amplphase(complex<double> val) double phase = 0.0; double amplitude = real(val)*real(val) + imag(val)*imag(val); - if (amplitude > 0.0) - { + if (amplitude > 0.0) { amplitude = 12 + 5*log10(amplitude); // adjust scaling to allow comparison to subband statistics } - if (0.0 == real(val)) - { - + if (0.0 == real(val)) { if (imag(val) > 0) phase = 90.0; else if (imag(val) < 0) phase = 270; - } - else - { - + else { phase = 45.0 * atan(imag(val)/real(val)) / atan(1.0); - - if (real(val) > 0.0) - { + if (real(val) > 0.0) { if (imag(val) < 0) phase += 360.0; } else phase += 180.0; - } return complex<double>(amplitude, phase); @@ -181,8 +175,7 @@ WeightsCommand::WeightsCommand(GCFPortInterface& port) : Command(port), m_type(W void WeightsCommand::send() { - switch (itsStage) - { + switch (itsStage) { //if (getMode()) //{ case 0: { @@ -236,10 +229,8 @@ GCFEvent::TResult WeightsCommand::ack(GCFEvent& e) { GCFEvent::TResult status = GCFEvent::HANDLED; - switch (e.signal) - { - case RSP_GETWEIGHTSACK: - { + switch (e.signal) { + case RSP_GETWEIGHTSACK: { RSPGetweightsackEvent ack(e); bitset<MEPHeader::MAX_N_RCUS> mask = getRCUMask(); itsWeights.resize(1, mask.count(), MEPHeader::N_BEAMLETS); @@ -315,8 +306,7 @@ SubbandsCommand::SubbandsCommand(GCFPortInterface& port) : Command(port), m_type void SubbandsCommand::send() { - if (getMode()) - { + if (getMode()) { // GET RSPGetsubbandsEvent getsubbands; @@ -327,8 +317,7 @@ void SubbandsCommand::send() m_rspport.send(getsubbands); } - else - { + else { // SET RSPSetsubbandsEvent setsubbands; setsubbands.timestamp = Timestamp(0,0); @@ -365,8 +354,7 @@ void SubbandsCommand::send() } break; - case SubbandSelection::XLET: - { + case SubbandSelection::XLET: { setsubbands.subbands().resize(1,1); std::list<int>::iterator it = m_subbandlist.begin(); setsubbands.subbands() = (*it); @@ -387,10 +375,8 @@ GCFEvent::TResult SubbandsCommand::ack(GCFEvent& e) { GCFEvent::TResult status = GCFEvent::HANDLED; - switch (e.signal) - { - case RSP_GETSUBBANDSACK: - { + switch (e.signal) { + case RSP_GETSUBBANDSACK: { RSPGetsubbandsackEvent ack(e); bitset<MEPHeader::MAX_N_RCUS> mask = getRCUMask(); @@ -398,14 +384,11 @@ GCFEvent::TResult SubbandsCommand::ack(GCFEvent& e) msg << "getsubbandsack.timestamp=" << ack.timestamp; logMessage(cout, msg.str()); - if (SUCCESS == ack.status) - { + if (SUCCESS == ack.status) { int rcuin = 0; - for (int rcuout = 0; rcuout < get_ndevices(); rcuout++) - { + for (int rcuout = 0; rcuout < get_ndevices(); rcuout++) { - if (mask[rcuout]) - { + if (mask[rcuout]) { std::ostringstream logStream; logStream << ack.subbands()(rcuin++, Range::all()); if (SubbandSelection::BEAMLET == m_type) { @@ -416,23 +399,20 @@ GCFEvent::TResult SubbandsCommand::ack(GCFEvent& e) } } } - else - { + else { logMessage(cerr,"Error: RSP_GETSUBBANDS command failed."); } } break; - case RSP_SETSUBBANDSACK: - { + case RSP_SETSUBBANDSACK: { RSPSetsubbandsackEvent ack(e); std::ostringstream msg; msg << "setsubbandsack.timestamp=" << ack.timestamp; logMessage(cout, msg.str()); - if (SUCCESS != ack.status) - { + if (SUCCESS != ack.status) { logMessage(cerr,"Error: RSP_SETSUBBANDS command failed."); } } @@ -454,8 +434,7 @@ RCUCommand::RCUCommand(GCFPortInterface& port) : Command(port) void RCUCommand::send() { - if (getMode()) - { + if (getMode()) { // GET RSPGetrcuEvent getrcu; @@ -465,8 +444,7 @@ void RCUCommand::send() m_rspport.send(getrcu); } - else - { + else { // SET RSPSetrcuEvent setrcu; setrcu.timestamp = Timestamp(0,0); @@ -486,38 +464,30 @@ void RCUCommand::send() GCFEvent::TResult RCUCommand::ack(GCFEvent& e) { - switch (e.signal) - { - case RSP_GETRCUACK: - { + switch (e.signal) { + case RSP_GETRCUACK: { RSPGetrcuackEvent ack(e); bitset<MEPHeader::MAX_N_RCUS> mask = getRCUMask(); - if (SUCCESS == ack.status) - { + if (SUCCESS == ack.status) { int rcuin = 0; - for (int rcuout = 0; rcuout < get_ndevices(); rcuout++) - { + for (int rcuout = 0; rcuout < get_ndevices(); rcuout++) { - if (mask[rcuout]) - { + if (mask[rcuout]) { logMessage(cout,formatString("RCU[%2d].control=0x%08x",rcuout, ack.settings()(rcuin++).getRaw())); } } } - else - { + else { logMessage(cerr,"Error: RSP_GETRCU command failed."); } } break; - case RSP_SETRCUACK: - { + case RSP_SETRCUACK: { RSPSetrcuackEvent ack(e); - if (SUCCESS != ack.status) - { + if (SUCCESS != ack.status) { logMessage(cerr,"Error: RSP_SETRCU command failed."); } } @@ -591,8 +561,7 @@ void HBACommand::send() GCFEvent::TResult HBACommand::ack(GCFEvent& e) { switch (e.signal) { - case RSP_GETHBAACK: - { + case RSP_GETHBAACK: { RSPGethbaackEvent ack(e); bitset<MEPHeader::MAX_N_RCUS> mask = getRCUMask(); @@ -617,8 +586,7 @@ GCFEvent::TResult HBACommand::ack(GCFEvent& e) } break; - case RSP_READHBAACK: - { + case RSP_READHBAACK: { RSPReadhbaackEvent ack(e); bitset<MEPHeader::MAX_N_RCUS> mask = getRCUMask(); @@ -648,8 +616,7 @@ GCFEvent::TResult HBACommand::ack(GCFEvent& e) } break; - case RSP_SETHBAACK: - { + case RSP_SETHBAACK: { RSPSethbaackEvent ack(e); if (SUCCESS != ack.status) { logMessage(cerr,"Error: RSP_SETHBA command failed."); @@ -740,8 +707,7 @@ ClockCommand::ClockCommand(GCFPortInterface& port) : Command(port) void ClockCommand::send() { - if (getMode()) - { + if (getMode()) { // GET RSPGetclockEvent getclock; @@ -754,8 +720,7 @@ void ClockCommand::send() m_rspport.send(getclock); } - else - { + else { // SET RSPSetclockEvent setclock; setclock.timestamp = Timestamp(0,0); @@ -768,10 +733,8 @@ void ClockCommand::send() GCFEvent::TResult ClockCommand::ack(GCFEvent& e) { - switch (e.signal) - { - case RSP_GETCLOCKACK: - { + switch (e.signal) { + case RSP_GETCLOCKACK: { /** * This signal is handled in SubClockCommand. * We should never end up here. @@ -781,12 +744,10 @@ GCFEvent::TResult ClockCommand::ack(GCFEvent& e) } break; - case RSP_SETCLOCKACK: - { + case RSP_SETCLOCKACK: { RSPSetclockackEvent ack(e); - if (SUCCESS != ack.status) - { + if (SUCCESS != ack.status) { logMessage(cerr,"Error: RSP_SETCLOCK command failed."); } } @@ -806,8 +767,7 @@ SubClockCommand::SubClockCommand(GCFPortInterface& port) : Command(port) void SubClockCommand::send() { - if (getMode()) - { + if (getMode()) { // Get current clock setting RSPGetclockEvent getclock; @@ -816,8 +776,7 @@ void SubClockCommand::send() m_rspport.send(getclock); } - else - { + else { // SET not supported logMessage(cerr, "SubClockCommand: SET not supported"); exit(EXIT_FAILURE); @@ -826,13 +785,10 @@ void SubClockCommand::send() GCFEvent::TResult SubClockCommand::ack(GCFEvent& e) { - switch (e.signal) - { - case RSP_GETCLOCKACK: - { + switch (e.signal) { + case RSP_GETCLOCKACK: { RSPGetclockackEvent ack(e); - if (SUCCESS == ack.status) - { + if (SUCCESS == ack.status) { g_sample_frequency = 1.0e6 * ack.clock; if (g_getclock) { @@ -853,35 +809,29 @@ GCFEvent::TResult SubClockCommand::ack(GCFEvent& e) m_rspport.send(subclock); } } - else - { + else { logMessage(cerr,"Error: RSP_GETCLOCK command failed."); } } break; - case RSP_SUBCLOCKACK: - { + case RSP_SUBCLOCKACK: { RSPSubclockackEvent ack(e); - if (SUCCESS != ack.status) - { + if (SUCCESS != ack.status) { logMessage(cerr,"Error: RSP_UPDCLOCK command failed."); exit(EXIT_FAILURE); } } break; - case RSP_UPDCLOCK: - { + case RSP_UPDCLOCK: { RSPUpdclockEvent upd(e); - if (SUCCESS == upd.status) - { + if (SUCCESS == upd.status) { logMessage(cout,formatString("Received new sample frequency: clock=%dMHz", upd.clock)); g_sample_frequency = 1.0e6 * upd.clock; } - else - { + else { logMessage(cerr,"Error: RSP_UPDCLOCK command failed."); } } @@ -971,8 +921,7 @@ TBBCommand::TBBCommand(GCFPortInterface& port) : Command(port), m_type(0) void TBBCommand::send() { - if (getMode()) - { + if (getMode()) { // GET RSPGettbbEvent gettbb; @@ -982,8 +931,7 @@ void TBBCommand::send() m_rspport.send(gettbb); } - else - { + else { // SET RSPSettbbEvent settbb; @@ -995,15 +943,13 @@ void TBBCommand::send() // if only 1 subband selected, apply selection to all switch (m_type) { - case TRANSIENT: - { + case TRANSIENT: { settbb.settings().resize(1); settbb.settings()(0).reset(); } break; - case SUBBANDS: - { + case SUBBANDS: { settbb.settings().resize(1); settbb.settings()(0).reset(); @@ -1030,10 +976,8 @@ GCFEvent::TResult TBBCommand::ack(GCFEvent& e) { GCFEvent::TResult status = GCFEvent::HANDLED; - switch (e.signal) - { - case RSP_GETTBBACK: - { + switch (e.signal) { + case RSP_GETTBBACK: { RSPGettbbackEvent ack(e); std::ostringstream msg; @@ -1048,10 +992,8 @@ GCFEvent::TResult TBBCommand::ack(GCFEvent& e) // print settings int rcuin = 0; - for (int rcuout = 0; rcuout < get_ndevices(); rcuout++) - { - if (getRCUMask()[rcuout]) - { + for (int rcuout = 0; rcuout < get_ndevices(); rcuout++) { + if (getRCUMask()[rcuout]) { cout << formatString("RCU[%02u].tbbsettings= ", rcuout); // for (unsigned int ilong = 0; ilong < ack.settings()(0).size()/(sizeof(unsigned long) * BITSOFBYTE); ilong++) { @@ -1069,16 +1011,14 @@ GCFEvent::TResult TBBCommand::ack(GCFEvent& e) } break; - case RSP_SETTBBACK: - { + case RSP_SETTBBACK: { RSPSettbbackEvent ack(e); std::ostringstream msg; msg << "settbback.timestamp=" << ack.timestamp; logMessage(cout, msg.str()); - if (SUCCESS != ack.status) - { + if (SUCCESS != ack.status) { logMessage(cerr, "Error: RSP_SETTBB command failed."); } } @@ -1216,8 +1156,7 @@ RegisterStateCommand::RegisterStateCommand(GCFPortInterface& port) : void RegisterStateCommand::send() { - if (getMode()) - { + if (getMode()) { // GET == SUBSCRIBE RSPSubregisterstateEvent subregstate; @@ -1226,8 +1165,7 @@ void RegisterStateCommand::send() m_rspport.send(subregstate); } - else - { + else { // SET not supported logMessage(cerr, "Error: RegisterStateCommand: SET not supported"); exit(EXIT_FAILURE); @@ -1236,11 +1174,9 @@ void RegisterStateCommand::send() GCFEvent::TResult RegisterStateCommand::ack(GCFEvent& e) { - if (RSP_SUBREGISTERSTATEACK == e.signal) - { + if (RSP_SUBREGISTERSTATEACK == e.signal) { RSPSubregisterstateackEvent ack(e); - if (SUCCESS != ack.status) - { + if (SUCCESS != ack.status) { logMessage(cerr,"Error: RSP_UPDREGISTERSTATE command failed."); exit(EXIT_FAILURE); } @@ -1250,15 +1186,13 @@ GCFEvent::TResult RegisterStateCommand::ack(GCFEvent& e) RSPUpdregisterstateEvent upd(e); - if (SUCCESS == upd.status) - { + if (SUCCESS == upd.status) { std::ostringstream logStream; logStream << "registerstate update at " << upd.timestamp << endl; upd.state.print(logStream); logMessage(cout,logStream.str()); } - else - { + else { logMessage(cerr, "Error: register state update failed."); } @@ -1267,8 +1201,7 @@ GCFEvent::TResult RegisterStateCommand::ack(GCFEvent& e) void RegisterStateCommand::stop() { - if (getMode()) - { + if (getMode()) { // UNSUBSCRIBE RSPUnsubregisterstateEvent unsubregstate; unsubregstate.handle = m_subscriptionhandle; @@ -1331,6 +1264,125 @@ GCFEvent::TResult SPUStatusCommand::ack(GCFEvent& event) GCFTask::stop(); return (GCFEvent::HANDLED); } +// +// RawBlock +// +RawBlockCommand::RawBlockCommand(GCFPortInterface& port): + Command(port), + itsRSPboard(0), + itsAddress(0), + itsOffset(0), + itsDataLen(0) +{ + memset (&itsData[0], 0, RSP_RAW_BLOCK_SIZE); +} + +// send() +void RawBlockCommand::send() +{ + // read mode? + if (getMode()) { + // construct message + RSPGetblockEvent rbCmd; + rbCmd.timestamp = Timestamp(0,0); + rbCmd.boardID = itsRSPboard; + rbCmd.address = itsAddress; + rbCmd.offset = itsOffset; + rbCmd.dataLen = itsDataLen; + // and send it. + m_rspport.send(rbCmd); + return; + } + + // write block + RSPSetblockEvent rbCmd; + rbCmd.timestamp = Timestamp(0,0); + rbCmd.boardID = itsRSPboard; + rbCmd.address = itsAddress; + rbCmd.offset = itsOffset; + rbCmd.dataLen = itsDataLen; + memcpy(rbCmd.data, itsData, itsDataLen); + // and send it. + m_rspport.send(rbCmd); + +} + +// ack(event) +GCFEvent::TResult RawBlockCommand::ack(GCFEvent& event) +{ + switch (event.signal) { + case RSP_GETBLOCKACK: { + RSPGetblockackEvent ack(event); + LOG_DEBUG(formatString("RAWBLOCKREAD:board=%d, status=%d, dataLen=%d", ack.boardID, ack.status, ack.dataLen)); + if (ack.status != SUCCESS) { + cerr << "Error: readBlock command failed, code = " << ack.status << endl; + } + else { + // show result to the user + hexdump (ack.data, ack.dataLen); + // TODO write to file + } + } + break; + + case RSP_SETBLOCKACK: { + RSPSetblockackEvent ack(event); + LOG_DEBUG(formatString("RAWBLOCKWRITE:board:%d, status=%d", ack.boardID, ack.status)); + if (ack.status != SUCCESS) { + cerr << "Error: writeBlock command failed, code = " << ack.status << endl; + } + } + break; + + default: + cerr << "Unknown answer return while reading or writing a datablock" << endl; + } + + GCFTask::stop(); + return (GCFEvent::HANDLED); +} + +// setAddressInfo(RSPboard, address, offset) +void RawBlockCommand::setAddressInfo(uint16 RSPboard, uint32 address, uint16 offset) +{ + itsRSPboard = RSPboard; + itsAddress = address; + itsOffset = offset; +} + +// setDataInfo(filename, datalen, dataPtr) +void RawBlockCommand::setDataInfo (const string& filename, uint16 dataLen, uint8* dataPtr) +{ + if (filename.empty()) { + itsDataLen = dataLen > RSP_RAW_BLOCK_SIZE ? RSP_RAW_BLOCK_SIZE : dataLen; + if (dataPtr) { // Note: for 'reads' the dataPtr = 0 + memcpy (&itsData[0], dataPtr, dataLen); + cout << dataLen << " bytes of data in command" << endl; + } + return; + } + + // TODO: add code for using a file +} + +// getAddressInfo(RSPboard, address, offset) +void RawBlockCommand::getAddressInfo(uint16* RSPboard, uint32* address, uint16* offset) +{ + *RSPboard = itsRSPboard; + *address = itsAddress; + *offset = itsOffset; +} + +// getDataInfo(filename, datalen, dataPtr) +void RawBlockCommand::getDataInfo(const string& filename, uint16* datalen, uint8** dataHandle) +{ + if (filename.empty()) { + *datalen = itsDataLen; + *dataHandle = &itsData[0]; + return; + } + // TODO: add code for using a file +} // // Weights @@ -1347,8 +1399,7 @@ WGCommand::WGCommand(GCFPortInterface& port) : void WGCommand::send() { - if (getMode()) - { + if (getMode()) { // GET RSPGetwgEvent wgget; wgget.timestamp = Timestamp(0,0); @@ -1356,8 +1407,7 @@ void WGCommand::send() wgget.cache = true; m_rspport.send(wgget); } - else - { + else { // SET RSPSetwgEvent wgset; @@ -1373,12 +1423,10 @@ void WGCommand::send() wgset.settings()(0).ampl = m_amplitude; wgset.settings()(0).nof_samples = MEPHeader::N_WAVE_SAMPLES; - if (m_frequency < 1e-6) - { + if (m_frequency < 1e-6) { wgset.settings()(0).mode = WGSettings::MODE_OFF; } - else /* frequency ok */ - { + else { /* frequency ok */ if (m_mode == 0) { /* forget to set mode? assume calc mode */ wgset.settings()(0).mode = WGSettings::MODE_CALC; wgset.settings()(0).nof_samples = MEPHeader::N_WAVE_SAMPLES; @@ -1398,23 +1446,18 @@ GCFEvent::TResult WGCommand::ack(GCFEvent& e) { GCFEvent::TResult status = GCFEvent::HANDLED; - switch (e.signal) - { - case RSP_GETWGACK: - { + switch (e.signal) { + case RSP_GETWGACK: { RSPGetwgackEvent ack(e); - if (SUCCESS == ack.status) - { + if (SUCCESS == ack.status) { // print settings bitset<MEPHeader::MAX_N_RCUS> mask = getRCUMask(); int rcuin = 0; - for (int rcuout = 0; rcuout < get_ndevices(); rcuout++) - { + for (int rcuout = 0; rcuout < get_ndevices(); rcuout++) { - if (mask[rcuout]) - { + if (mask[rcuout]) { logMessage(cout,formatString("RCU[%02u].wg=[freq=%11u, phase=%3u(%5.3f), ampl=%11u, nof_samples=%6u, mode=%3u]", rcuout, ack.settings()(rcuin).freq, @@ -1427,19 +1470,16 @@ GCFEvent::TResult WGCommand::ack(GCFEvent& e) } } } - else - { + else { logMessage(cerr,"Error: RSP_GETWG command failed."); } } break; - case RSP_SETWGACK: - { + case RSP_SETWGACK: { RSPSetwgackEvent ack(e); - if (SUCCESS != ack.status) - { + if (SUCCESS != ack.status) { logMessage(cerr,"Error: RSP_SETWG command failed."); } } @@ -1639,14 +1679,11 @@ StatisticsCommand::StatisticsCommand(GCFPortInterface& port) : StatisticsBaseCom void StatisticsCommand::send() { - if (getMode()) - { - if(m_directory.length()>0) - { + if (getMode()) { + if(m_directory.length()>0) { logMessage(cout,formatString("Dumping statistics in %s",m_directory.c_str())); } - else - { + else { char cwd[PATH_MAX]; logMessage(cout,formatString("Dumping statistics in %s",getcwd(cwd,PATH_MAX))); } @@ -1662,8 +1699,7 @@ void StatisticsCommand::send() m_rspport.send(substats); } - else - { + else { // SET logMessage(cerr,"Error: set mode not support for option '--statistics'"); GCFTask::stop(); @@ -1672,8 +1708,7 @@ void StatisticsCommand::send() void StatisticsCommand::stop() { - if (getMode()) - { + if (getMode()) { // UNSUBSCRIBE RSPUnsubstatsEvent unsubstats; unsubstats.handle = m_subscriptionhandle; @@ -1683,16 +1718,13 @@ void StatisticsCommand::stop() void StatisticsCommand::capture_statistics(Array<double, 2>& stats, const Timestamp& timestamp) { - if (0 == m_nseconds) - { + if (0 == m_nseconds) { // initialize values array m_stats.resize(stats.shape()); m_stats = 0.0; } - else - { - if ( sum(stats.shape()) != sum(m_stats.shape()) ) - { + else { + if ( sum(stats.shape()) != sum(m_stats.shape()) ) { logMessage(cerr, "Error: statistics shape mismatch"); exit(EXIT_FAILURE); } @@ -1705,27 +1737,22 @@ void StatisticsCommand::capture_statistics(Array<double, 2>& stats, const Timest } m_nseconds++; // advance to next second - if (0 == (int32)m_nseconds % m_integration) - { - if (m_integration > 0) - { + if (0 == (int32)m_nseconds % m_integration) { + if (m_integration > 0) { m_stats /= m_integration; } LOG_DEBUG_STR("statistics update at " << timestamp); - if(m_duration == 0) - { + if(m_duration == 0) { plot_statistics(m_stats, timestamp); } - else - { + else { dump_statistics(m_stats, timestamp); Timestamp timeNow; timeNow.setNow(); - if(timeNow >= m_endTime) - { + if(timeNow >= m_endTime) { logMessage(cout,"Statistics capturing successfully ended."); stop(); GCFTask::stop(); @@ -1745,8 +1772,7 @@ void StatisticsCommand::plot_statistics(Array<double, 2>& stats, const Timestamp // initialize the freq array firstIndex i; - if (!handle) - { + if (!handle) { handle = gnuplot_init(); if (!handle) return; @@ -1757,8 +1783,7 @@ void StatisticsCommand::plot_statistics(Array<double, 2>& stats, const Timestamp gnuplot_cmd(handle, "set ylabel \"dB\"\n"); gnuplot_cmd(handle, "set yrange [0:160]\n"); - switch (m_type) - { + switch (m_type) { case Statistics::SUBBAND_POWER: gnuplot_cmd(handle, "set xlabel \"Frequency (MHz)\"\n"); gnuplot_cmd(handle, "set xrange [0:%f]\n", g_sample_frequency / 2.0); @@ -1779,16 +1804,13 @@ void StatisticsCommand::plot_statistics(Array<double, 2>& stats, const Timestamp // splot devices int count = 0; - for (int rcuout = 0; rcuout < get_ndevices(); rcuout++) - { - if (mask[rcuout]) - { + for (int rcuout = 0; rcuout < get_ndevices(); rcuout++) { + if (mask[rcuout]) { if (count > 0) gnuplot_cmd(handle, ","); count++; - switch (m_type) - { + switch (m_type) { case Statistics::SUBBAND_POWER: gnuplot_cmd(handle, "\"-\" using (%.1f/%.1f*$1):(10*log10($2)) title \"(RCU=%d)\" with steps ", g_sample_frequency, n_freqbands*2.0, rcuout); @@ -1815,10 +1837,8 @@ void StatisticsCommand::dump_statistics(Array<double, 2>& stats, const Timestamp bitset<MEPHeader::MAX_N_RCUS> mask = getRCUMask(); int result_device=0; - for (int deviceout = 0; deviceout < get_ndevices(); deviceout++) - { - if (mask[deviceout]) - { + for (int deviceout = 0; deviceout < get_ndevices(); deviceout++) { + if (mask[deviceout]) { char timestring[256]; time_t seconds = timestamp.sec(); strftime(timestring, 255, "%Y%m%d_%H%M%S", gmtime(&seconds)); @@ -1826,8 +1846,7 @@ void StatisticsCommand::dump_statistics(Array<double, 2>& stats, const Timestamp LOG_INFO_STR("dumping statistics at " << timestring); - switch (m_type) - { + switch (m_type) { case Statistics::SUBBAND_POWER: snprintf(fileName, PATH_MAX, "%s%s_sst_rcu%03d.dat", m_directory.c_str(), timestring, deviceout); break; @@ -1845,8 +1864,7 @@ void StatisticsCommand::dump_statistics(Array<double, 2>& stats, const Timestamp FILE* file = getFile(deviceout,fileName); if (stats.extent(secondDim) - != (int)fwrite(stats(result_device, Range::all()).data(), sizeof(double), stats.extent(secondDim), file)) - { + != (int)fwrite(stats(result_device, Range::all()).data(), sizeof(double), stats.extent(secondDim), file)) { logMessage(cerr,formatString("Error: unable to write to file %s",fileName)); exit(EXIT_FAILURE); } @@ -1857,12 +1875,10 @@ void StatisticsCommand::dump_statistics(Array<double, 2>& stats, const Timestamp GCFEvent::TResult StatisticsCommand::ack(GCFEvent& e) { - if (e.signal == RSP_SUBSTATSACK) - { + if (e.signal == RSP_SUBSTATSACK) { RSPSubstatsackEvent ack(e); - if (SUCCESS != ack.status) - { + if (SUCCESS != ack.status) { logMessage(cerr,"Error: failed to subscribe to statistics"); exit(EXIT_FAILURE); } @@ -1875,12 +1891,10 @@ GCFEvent::TResult StatisticsCommand::ack(GCFEvent& e) RSPUpdstatsEvent upd(e); - if (SUCCESS == upd.status) - { + if (SUCCESS == upd.status) { capture_statistics(upd.stats(),upd.timestamp); } - else - { + else { logMessage(cerr,"Error: statistics update failed."); } @@ -1894,14 +1908,11 @@ XCStatisticsCommand::XCStatisticsCommand(GCFPortInterface& port) : StatisticsBas void XCStatisticsCommand::send() { - if (getMode()) - { - if(m_directory.length()>0) - { + if (getMode()) { + if(m_directory.length()>0) { logMessage(cout,formatString("Dumping statistics in %s",m_directory.c_str())); } - else - { + else { char cwd[PATH_MAX]; logMessage(cout,formatString("Dumping statistics in %s",getcwd(cwd,PATH_MAX))); } @@ -1917,8 +1928,7 @@ void XCStatisticsCommand::send() m_rspport.send(subxcstats); } - else - { + else { // SET logMessage(cerr,"Error: set mode not support for option '--xcstatistics'"); GCFTask::stop(); @@ -1927,8 +1937,7 @@ void XCStatisticsCommand::send() void XCStatisticsCommand::stop() { - if (getMode()) - { + if (getMode()) { // UNSUBSCRIBE RSPUnsubxcstatsEvent unsubxcstats; unsubxcstats.handle = m_subscriptionhandle; @@ -1938,16 +1947,13 @@ void XCStatisticsCommand::stop() void XCStatisticsCommand::capture_xcstatistics(Array<complex<double>, 4>& stats, const Timestamp& timestamp){ - if (0 == m_nseconds) - { + if (0 == m_nseconds) { // initialize values array m_stats.resize(stats.shape()); m_stats = 0.0; } - else - { - if ( sum(stats.shape()) != sum(m_stats.shape()) ) - { + else { + if ( sum(stats.shape()) != sum(m_stats.shape()) ) { logMessage(cerr, "Error: xcstatistics shape mismatch"); exit(EXIT_FAILURE); } @@ -1960,17 +1966,14 @@ void XCStatisticsCommand::capture_xcstatistics(Array<complex<double>, 4>& stats, } m_nseconds++; // advance to next second - if (0 == (int32)m_nseconds % m_integration) - { - if (m_integration > 0) - { + if (0 == (int32)m_nseconds % m_integration) { + if (m_integration > 0) { m_stats /= m_integration; } LOG_DEBUG_STR("xcstatistics update at " << timestamp); - if(m_duration == 0) - { + if(m_duration == 0) { blitz::Array<complex<double>, 4> pastats; pastats.resize(m_stats.shape()); pastats = convert_to_amplphase(m_stats); @@ -1988,14 +1991,12 @@ void XCStatisticsCommand::capture_xcstatistics(Array<complex<double>, 4>& stats, plot_xcstatistics(m_stats, timestamp); } - else - { + else { dump_xcstatistics(m_stats, timestamp); Timestamp timeNow; timeNow.setNow(); - if(timeNow >= m_endTime) - { + if(timeNow >= m_endTime) { logMessage(cout,"XCStatistics capturing successfully ended."); stop(); GCFTask::stop(); @@ -2074,8 +2075,7 @@ void XCStatisticsCommand::dump_xcstatistics(Array<complex<double>, 4>& stats, co if (thestats.size() != (int)fwrite(thestats.data(), sizeof(complex<double>), - thestats.size(), file)) - { + thestats.size(), file)) { logMessage(cerr,formatString("Error: unable to write to file %s",fileName)); exit(EXIT_FAILURE); } @@ -2083,17 +2083,14 @@ void XCStatisticsCommand::dump_xcstatistics(Array<complex<double>, 4>& stats, co GCFEvent::TResult XCStatisticsCommand::ack(GCFEvent& e) { - if (e.signal == RSP_SUBXCSTATSACK) - { + if (e.signal == RSP_SUBXCSTATSACK) { RSPSubxcstatsackEvent ack(e); - if (SUCCESS != ack.status) - { + if (SUCCESS != ack.status) { logMessage(cerr,"Error: failed to subscribe to xcstatistics"); exit(EXIT_FAILURE); } - else - { + else { m_subscriptionhandle = ack.handle; } @@ -2105,8 +2102,7 @@ GCFEvent::TResult XCStatisticsCommand::ack(GCFEvent& e) RSPUpdxcstatsEvent upd(e); - if (SUCCESS == upd.status) - { + if (SUCCESS == upd.status) { #if 0 Range r1, r2; if (!getRSPRange2(r1, r2)) { @@ -2141,10 +2137,8 @@ GCFEvent::TResult VersionCommand::ack(GCFEvent& e) { RSPGetversionackEvent ack(e); - if (SUCCESS == ack.status) - { - for (int rsp=0; rsp < get_ndevices(); rsp++) - { + if (SUCCESS == ack.status) { + for (int rsp=0; rsp < get_ndevices(); rsp++) { logMessage(cout,formatString("RSP[%2d] RSP version = %d, BP version = %d.%d, AP version = %d.%d", rsp, ack.versions.bp()(rsp).rsp_version, @@ -2154,8 +2148,7 @@ GCFEvent::TResult VersionCommand::ack(GCFEvent& e) ack.versions.ap()(rsp).fpga_min)); } } - else - { + else { logMessage(cerr,"Error: RSP_GETVERSION command failed."); } GCFTask::stop(); @@ -2211,13 +2204,11 @@ GCFEvent::TResult RSPCtl::initial(GCFEvent& e, GCFPortInterface& port) LOG_DEBUG_STR ("initial:" << eventName(e) << "@" << port.getName()); GCFEvent::TResult status = GCFEvent::HANDLED; - switch(e.signal) - { + switch(e.signal) { case F_INIT: break; - case F_ENTRY: - { + case F_ENTRY: { if (!m_server.isConnected()) if (!m_server.open()) { logMessage(cerr, "Error: failed to open port to RSPDriver"); @@ -2226,18 +2217,15 @@ GCFEvent::TResult RSPCtl::initial(GCFEvent& e, GCFPortInterface& port) } break; - case F_CONNECTED: - { - if (m_server.isConnected()) - { + case F_CONNECTED: { + if (m_server.isConnected()) { RSPGetconfigEvent getconfig; m_server.send(getconfig); } } break; - case RSP_GETCONFIGACK: - { + case RSP_GETCONFIGACK: { RSPGetconfigackEvent ack(e); m_nrcus = ack.n_rcus; m_nrspboards = ack.n_rspboards; @@ -2248,15 +2236,13 @@ GCFEvent::TResult RSPCtl::initial(GCFEvent& e, GCFPortInterface& port) } break; - case F_DISCONNECTED: - { + case F_DISCONNECTED: { port.setTimer((long)1); port.close(); } break; - case F_TIMER: - { + case F_TIMER: { // try again m_server.open(); } @@ -2277,15 +2263,13 @@ GCFEvent::TResult RSPCtl::docommand(GCFEvent& e, GCFPortInterface& port) GCFEvent::TResult status = GCFEvent::HANDLED; switch (e.signal) { - case F_ENTRY: - { + case F_ENTRY: { m_subclock.send(); // subscribe to clock updates // after receiving the clock update execute the actual requested command } break; - case F_CONNECTED: - { + case F_CONNECTED: { // connection with te frontend! send the command to the rsp driver FECommand* feCommand = dynamic_cast<FECommand*>(m_command); if(feCommand != 0) { @@ -2332,6 +2316,8 @@ GCFEvent::TResult RSPCtl::docommand(GCFEvent& e, GCFPortInterface& port) case RSP_GETBYPASSACK: case RSP_SETBYPASSACK: case RSP_GETSPUSTATUSACK: + case RSP_GETBLOCKACK: + case RSP_SETBLOCKACK: status = m_command->ack(e); // handle the acknowledgement break; @@ -2345,7 +2331,7 @@ GCFEvent::TResult RSPCtl::docommand(GCFEvent& e, GCFPortInterface& port) // reparse options if (0 == (m_command = parse_options(m_argc, m_argv))) { logMessage(cerr,"Warning: no command specified."); - usage(); +// usage(false); exit(EXIT_FAILURE); } // check if a connection must be made with a frontend. If so, connect first @@ -2389,7 +2375,7 @@ void RSPCtl::mainloop() GCFTask::run(); } -static void usage() +static void usage(bool exportMode) { cout << "rspctl usage:" << endl; cout << endl; @@ -2499,13 +2485,30 @@ static void usage() cout << "rspctl --rspclear [--select=<set>] # clear FPGA registers on RSPboard" << endl; cout << "rspctl --hbadelays[=<list>] [--select=<set>] # set or get the 16 delays of one or more HBA's" << endl; cout << "rspctl --tbbmode[=transient | =subbands,<set>] # set or get TBB mode, 'transient' or 'subbands', if subbands then specify subband set" << endl; + if (exportMode) { + cout << endl; + cout << "--- Raw register control -------------------------------------------------------------------------------------" << endl; + cout << " ### WARNING: to following commands may crash the RSPboard when used wrong! ###" << endl; + cout << "rspctl --readblock=RSPboard,hexAddress,offset,datalength # read datalength bytes from given address" << endl; +// cout << "rspctl --readblock=RSPboard,hexAddress,offset,filename # read datalength bytes from given address" << endl; +// cout << " Data is written to the file in binairy format." << endl; + cout << endl; + cout << "rspctl --writeblock=RSPboard,hexAddress,offset,hexData # write data to given address" << endl; +// cout << " HexData must start with '0x'." << endl; +// cout << "rspctl --writeblock=RSPboard,hexAddress,offset,filename # write data to given address" << endl; +// cout << " When filecontents starts with 0x is it read as hexdata," << endl; +// cout << " otherwise the file is treated as a binairy file." << endl; + cout << "In all cases the maximum number of databytes is " << RSP_RAW_BLOCK_SIZE << endl; + cout << "Address order: BLPID, RSP, PID, REGID" << endl; + cout << endl; + } } Command* RSPCtl::parse_options(int argc, char** argv) { - Command* command = 0; - RCUCommand* rcumodecommand = 0; - HBACommand* hbacommand = 0; + Command* command = 0; + RCUCommand* rcumodecommand = 0; + HBACommand* hbacommand = 0; list<int> select; list<int> beamlets; bool xcangle = false; @@ -2557,11 +2560,13 @@ Command* RSPCtl::parse_options(int argc, char** argv) { "specinv", optional_argument, 0, 'I' }, { "phase", required_argument, 0, 'P' }, { "tdstatus", no_argument, 0, 'Q' }, -// { "rspreset", optional_argument, 0, 'R' }, { "realdelays", optional_argument, 0, 'R' }, { "regstate", no_argument, 0, 'S' }, { "tbbmode", optional_argument, 0, 'T' }, { "spustate", no_argument, 0, 'V' }, + { "expert", no_argument, 0, 'X' }, + { "readblock", required_argument, 0, '1' }, + { "writeblock", required_argument, 0, '2' }, { 0, 0, 0, 0 }, }; @@ -2569,7 +2574,7 @@ Command* RSPCtl::parse_options(int argc, char** argv) realDelays = false; while (1) { int option_index = 0; - int c = getopt_long(argc, argv, "l:b:w::a::s::r::g::qQt::xz::vc::hf:d:i:I:", long_options, &option_index); + int c = getopt_long(argc, argv, "a::b:c::d:e::f:g::hi:l:m:n:p::qr::s::t::vw::xy:z::A:BC::D:E::G:H::I::P:QR::ST::VX1:2:", long_options, &option_index); if (c == -1) // end of argument list reached? break; @@ -3091,7 +3096,11 @@ Command* RSPCtl::parse_options(int argc, char** argv) break; case 'h': // --help - usage(); + usage(false); + break; + + case 'X': // --export help + usage(true); break; #ifdef ENABLE_RSPFE @@ -3177,6 +3186,85 @@ Command* RSPCtl::parse_options(int argc, char** argv) } break; + case '1': // readblock=RSPboard,hexAddress,offset,(datalen|filename) + case '2': { // writeblock=RSPboard,hexAddress,offset,(datalen|filename) + // allocate the right command + if (command) { + delete (command); + } + RawBlockCommand* rbCmd = new RawBlockCommand(m_server); + command = rbCmd; + rbCmd->setMode(c == '1'); + + // we definitely need arguments + if (!optarg) { + usage(false); + logMessage(cerr, "Need arguments for dataBlock"); + exit(EXIT_FAILURE); + } + + // try to parse the arguments + uint32 rspBoard; + uint32 address; + uint32 offset; + uint32 dataLen; + char dataStr[4096]; + char addrStr[1024]; + if (c == '1') { // read block + int numItems = sscanf(optarg, "%u,%[0-9A-Fa-f],%u,%u", &rspBoard, &addrStr[0], &offset, &dataLen); + if (numItems != 4) { + logMessage(cerr, "Need 4 arguments: rspBoardNr, hexAddress, offset, datalen"); + exit(EXIT_FAILURE); + } + } + else { // write block has different fourth parameter. + int numItems = sscanf(optarg, "%u,%[0-9A-Fa-f],%u,%s", &rspBoard, &addrStr[0], &offset, &dataStr[0]); + if (numItems != 4) { + logMessage(cerr, "Need 4 arguments: rspBoardNr, hexAddress, offset, hexData"); + exit(EXIT_FAILURE); + } + if (strlen(dataStr) % 1) { + logMessage(cerr, "Datastring must have an even number of characters"); + exit(EXIT_FAILURE); + } + dataLen = strlen(dataStr) / 2; + } + + // minor checking on the arguments. + if (rspBoard > (uint32)m_nrspboards || dataLen == 0 || dataLen > (uint32)RSP_RAW_BLOCK_SIZE) { + cerr << "Range error" << endl; + cerr << "RSPboard: 0.." << m_nrspboards << endl; + cerr << "Datalength: 1.." << RSP_RAW_BLOCK_SIZE << endl; + exit(EXIT_FAILURE); + } + + // convert addrString to address value (reverse order on intel) + if (strlen(addrStr) != 8) { + logMessage(cerr, "Address string must have 8 characters"); + exit(EXIT_FAILURE); + } + address = 0; + for (int i = 3; i >= 0; i--) { + address = (address << 8) + (uint8)(xtod(addrStr[i*2])<<4 | xtod(addrStr[i*2+1])); + } + + // write the usersetttings to the command. + rbCmd->setAddressInfo(rspBoard, address, offset); + if (c == '1') { // read block + rbCmd->setDataInfo("", dataLen, 0); + } + else { + // Transfer dataStr to databuffer + uint8 databuf[2048]; + for (uint16 i = 0; i < dataLen; i++) { + databuf[i] = (uint8)(xtod(dataStr[i*2])<<4 | xtod(dataStr[i*2+1])); + } + rbCmd->setDataInfo("", dataLen, &databuf[0]); + } + } + break; + + case '?': default: logMessage(cerr, "Error: invalid option"); @@ -3195,71 +3283,72 @@ Command* RSPCtl::parse_options(int argc, char** argv) std::list<int> RSPCtl::strtolist(const char* str, int max) { - string inputstring(str); - char* start = (char*)inputstring.c_str(); - char* end = 0; - bool range = false; - long prevval = 0; - list<int> resultset; - - resultset.clear(); - - while (start) { - long val = strtol(start, &end, 10); // read decimal numbers - start = (end ? (*end ? end + 1 : 0) : 0); // advance - if (val >= max || val < 0) { - logMessage(cerr,formatString("Error: value %ld out of range",val)); - resultset.clear(); - return resultset; - } + string inputstring(str); + char* start = (char*)inputstring.c_str(); + char* end = 0; + bool range = false; + long prevval = 0; + list<int> resultset; + + resultset.clear(); + + while (start) { + long val = strtol(start, &end, 10); // read decimal numbers + start = (end ? (*end ? end + 1 : 0) : 0); // advance + if (val >= max || val < 0) { + logMessage(cerr,formatString("Error: value %ld out of range",val)); + resultset.clear(); + return resultset; + } - if (end) { - switch (*end) { - case ',': - case 0: { - if (range) { - if (0 == prevval && 0 == val) - val = max - 1; - if (val < prevval) { - logMessage(cerr,"Error: invalid range specification"); - resultset.clear(); - return resultset; - } - for (long i = prevval; i <= val; i++) - resultset.push_back(i); - } - else { - resultset.push_back(val); - } - range=false; - } - break; + if (end) { + switch (*end) { + case ',': + case 0: { + if (range) { + if (0 == prevval && 0 == val) { + val = max - 1; + } + if (val < prevval) { + logMessage(cerr,"Error: invalid range specification"); + resultset.clear(); + return resultset; + } + for (long i = prevval; i <= val; i++) + resultset.push_back(i); + } + else { + resultset.push_back(val); + } + range=false; + } + break; - case ':': - range=true; - break; + case ':': + range=true; + break; - default: - logMessage(cerr,formatString("Error: invalid character %c",*end)); - resultset.clear(); - return resultset; - break; - } - } - prevval = val; - } + default: + logMessage(cerr,formatString("Error: invalid character %c",*end)); + resultset.clear(); + return resultset; + break; + } // switch + } // if (end) + prevval = val; + } // while - return resultset; + return (resultset); } void RSPCtl::logMessage(ostream& stream, const string& message) { - if(m_command != 0) { - m_command->logMessage(stream,message); - } - else { - stream << message << endl; - } + if(m_command != 0) { + m_command->logMessage(stream,message); + } + else { + stream << message << endl; + } } } // namespace rspctl @@ -3274,21 +3363,21 @@ using namespace LOFAR::rspctl; int main(int argc, char** argv) { - GCFTask::init(argc, argv, "rspctl"); + GCFTask::init(argc, argv, "rspctl"); - LOG_INFO(formatString("Program %s has started", argv[0])); + LOG_INFO(formatString("Program %s has started", argv[0])); - RSPCtl c("RSPCtl", argc, argv); + RSPCtl c("RSPCtl", argc, argv); - try { - c.mainloop(); - } - catch (Exception e) { - cerr << "Exception: " << e.text() << endl; - exit(EXIT_FAILURE); - } + try { + c.mainloop(); + } + catch (Exception e) { + cerr << "Exception: " << e.text() << endl; + exit(EXIT_FAILURE); + } - LOG_INFO("Normal termination of program"); + LOG_INFO("Normal termination of program"); - return 0; + return (0); } diff --git a/MAC/APL/PIC/RSPDriver/src/rspctl.h b/MAC/APL/PIC/RSPDriver/src/rspctl.h index f66c5f00577..46119d44685 100644 --- a/MAC/APL/PIC/RSPDriver/src/rspctl.h +++ b/MAC/APL/PIC/RSPDriver/src/rspctl.h @@ -644,6 +644,29 @@ private: blitz::Array<RSP_Protocol::SPUStatus, 1> itsSPUs; }; +// +// class RawBlockCommand +// +class RawBlockCommand : public Command +{ +public: + RawBlockCommand(GCFPortInterface& port); + virtual ~RawBlockCommand() {} + virtual void send(); + virtual GCFEvent::TResult ack(GCFEvent& e); + void setAddressInfo(uint16 RSPboard, uint32 address, uint16 offset); + void setDataInfo (const string& filename, uint16 dataLen, uint8* dataPtr); + void getAddressInfo(uint16* RSPboard, uint32* address, uint16* offset); + void getDataInfo (const string& filename, uint16* dataLen, uint8** dataHandle); +private: + uint16 itsRSPboard; + uint32 itsAddress; + uint16 itsOffset; + uint16 itsDataLen; + string itsFileName; + uint8 itsData[ETH_DATA_LEN]; +}; + // // class VersionCommand // diff --git a/MAC/APL/PIC/RSP_Protocol/include/APL/RSP_Protocol/AllRegisterState.h b/MAC/APL/PIC/RSP_Protocol/include/APL/RSP_Protocol/AllRegisterState.h index 6a5e5669910..5d87716f242 100644 --- a/MAC/APL/PIC/RSP_Protocol/include/APL/RSP_Protocol/AllRegisterState.h +++ b/MAC/APL/PIC/RSP_Protocol/include/APL/RSP_Protocol/AllRegisterState.h @@ -34,214 +34,225 @@ namespace LOFAR { namespace RSP_Protocol { - /** - * This class is used to contain the RegisterState of all registers. - * - * It is used in the following events: - * GETREGISTERSTATEACK - * UPDREGISTERSTATE - * - */ - class AllRegisterState - { - public: - - /** - * Constructors for a AllRegisterState object. - */ +// This class is used to contain the RegisterState of all registers. +// +// It is used in the following events: +// GETREGISTERSTATEACK +// UPDREGISTERSTATE +// +class AllRegisterState +{ +public: + // Constructors for a AllRegisterState object. AllRegisterState() : m_nrcus(0) {} - - /* Destructor for AllRegisterState. */ virtual ~AllRegisterState() {} - public: - + // + // init(nrRSP, nrBLP, nrRCU) + // void init(int nrRspBoards, int nrBlps, int nrRcus) { + m_nrcus = nrRcus; - m_nrcus = nrRcus; - - // - // resize to appropriate size and mark modified - // to force initial update - // - sys_state.resize(nrRspBoards); - bf_state.resize(nrRcus * EPA_Protocol::MEPHeader::N_PHASE); // XR, XI, YR, YI - ss_state.resize(nrBlps); - rcusettings_state.resize(nrRcus); - rcuprotocol_state.resize(nrRcus); - hbaprotocol_state.resize(nrRcus); - rsuclear_state.resize(nrRspBoards); - diagwgsettings_state.resize(nrRcus * EPA_Protocol::MEPHeader::N_DIAG_WG_REGISTERS); - sst_state.resize(nrBlps * EPA_Protocol::MEPHeader::SST_N_FRAGMENTS); - bst_state.resize(nrRspBoards); - xst_state.resize(nrRspBoards * EPA_Protocol::MEPHeader::XST_NR_STATS); - cdo_state.resize(nrRspBoards * EPA_Protocol::MEPHeader::N_CDO_REGISTERS); - bs_state.resize(nrBlps); - tdclear_state.resize(nrRspBoards); - tdwrite_state.resize(nrRspBoards); - tdread_state.resize(nrRspBoards); - rad_state.resize(nrRspBoards); - ts_state.resize(nrRspBoards); - tdstatuswrite_state.resize(nrRspBoards); - tdstatusread_state.resize(nrRspBoards); - tbbsettings_state.resize(nrRcus); - tbbbandsel_state.resize(nrRcus); - bypasssettings_state.resize(nrBlps); + // + // resize to appropriate size and mark modified + // to force initial update + // + sys_state.resize(nrRspBoards); + bf_state.resize(nrRcus * EPA_Protocol::MEPHeader::N_PHASE); // XR, XI, YR, YI + ss_state.resize(nrBlps); + rcusettings_state.resize(nrRcus); + rcuprotocol_state.resize(nrRcus); + hbaprotocol_state.resize(nrRcus); + rsuclear_state.resize(nrRspBoards); + diagwgsettings_state.resize(nrRcus * EPA_Protocol::MEPHeader::N_DIAG_WG_REGISTERS); + sst_state.resize(nrBlps * EPA_Protocol::MEPHeader::SST_N_FRAGMENTS); + bst_state.resize(nrRspBoards); + xst_state.resize(nrRspBoards * EPA_Protocol::MEPHeader::XST_NR_STATS); + cdo_state.resize(nrRspBoards * EPA_Protocol::MEPHeader::N_CDO_REGISTERS); + bs_state.resize(nrBlps); + tdclear_state.resize(nrRspBoards); + tdwrite_state.resize(nrRspBoards); + tdread_state.resize(nrRspBoards); + rad_state.resize(nrRspBoards); + ts_state.resize(nrRspBoards); + tdstatuswrite_state.resize(nrRspBoards); + tdstatusread_state.resize(nrRspBoards); + tbbsettings_state.resize(nrRcus); + tbbbandsel_state.resize(nrRcus); + bypasssettings_state.resize(nrBlps); + rawdatawrite_state.resize(nrRspBoards); + rawdataread_state.resize(nrRspBoards); } - /* - * Force update of some (not all) register. - * Register excluded from update are - * tds, bs, rsuclear - */ + // Force update of some (not all) register. + // Register excluded from update are + // tds, bs, rsuclear + // + // force() + // void force() { - sys_state.reset(); - bf_state.reset(); - ss_state.reset(); - rcusettings_state.reset(); - rcuprotocol_state.reset(); - hbaprotocol_state.reset(); - rsuclear_state.reset(); - diagwgsettings_state.reset(); - sst_state.reset(); - bst_state.reset(); - xst_state.reset(); - cdo_state.reset(); - bs_state.reset(); - tdclear_state.reset(); - tdwrite_state.reset(); - tdread_state.reset(); - rad_state.reset(); - ts_state.reset(); - tdstatuswrite_state.reset(); - tdstatusread_state.reset(); - tbbsettings_state.reset(); - tbbbandsel_state.reset(); - bypasssettings_state.reset(); + sys_state.reset(); + bf_state.reset(); + ss_state.reset(); + rcusettings_state.reset(); + rcuprotocol_state.reset(); + hbaprotocol_state.reset(); + rsuclear_state.reset(); + diagwgsettings_state.reset(); + sst_state.reset(); + bst_state.reset(); + xst_state.reset(); + cdo_state.reset(); + bs_state.reset(); + tdclear_state.reset(); + tdwrite_state.reset(); + tdread_state.reset(); + rad_state.reset(); + ts_state.reset(); + tdstatuswrite_state.reset(); + tdstatusread_state.reset(); + tbbsettings_state.reset(); + tbbbandsel_state.reset(); + bypasssettings_state.reset(); + rawdatawrite_state.reset(); + rawdataread_state.reset(); - sys_state.read(); - bf_state.write(); - ss_state.write(); - rcusettings_state.write(); - rcuprotocol_state.write(); - hbaprotocol_state.write(); - rsuclear_state.check(); - diagwgsettings_state.write(); - sst_state.read(); - bst_state.read(); - xst_state.read(); - cdo_state.check(); - bs_state.check(); - tdclear_state.check(); - tdwrite_state.check(); - tdread_state.check(); - rad_state.write(); - ts_state.write(); - tdstatuswrite_state.write(); - tdstatusread_state.read(); - tbbsettings_state.check(); - tbbbandsel_state.check(); - bypasssettings_state.write(); // REO: When is this function called??? + sys_state.read(); + bf_state.write(); + ss_state.write(); + rcusettings_state.write(); + rcuprotocol_state.write(); + hbaprotocol_state.write(); + rsuclear_state.check(); + diagwgsettings_state.write(); + sst_state.read(); + bst_state.read(); + xst_state.read(); + cdo_state.check(); + bs_state.check(); + tdclear_state.check(); + tdwrite_state.check(); + tdread_state.check(); + rad_state.write(); + ts_state.write(); + tdstatuswrite_state.write(); + tdstatusread_state.read(); + tbbsettings_state.check(); + tbbbandsel_state.check(); + bypasssettings_state.write(); // REO: When is this function called??? + rawdatawrite_state.check(); + rawdataread_state.check(); } + // + // schedule() + // void schedule() { - sys_state.read(); - bf_state.write(); // always write bf - ss_state.write(); // always write ss - rcusettings_state.check(); - rcuprotocol_state.check(); - hbaprotocol_state.check(); - rsuclear_state.check(); - diagwgsettings_state.check(); - sst_state.read(); - bst_state.read(); - xst_state.read(); - cdo_state.check(); - bs_state.check(); - tdclear_state.check(); - tdwrite_state.check(); - tdread_state.check(); - rad_state.check(); - ts_state.write(); // always write timestamp - tdstatuswrite_state.write(); - tdstatusread_state.read(); - tbbsettings_state.check(); - tbbbandsel_state.check(); - bypasssettings_state.check(); // REO ? + sys_state.read(); + bf_state.write(); // always write bf + ss_state.write(); // always write ss + rcusettings_state.check(); + rcuprotocol_state.check(); + hbaprotocol_state.check(); + rsuclear_state.check(); + diagwgsettings_state.check(); + sst_state.read(); + bst_state.read(); + xst_state.read(); + cdo_state.check(); + bs_state.check(); + tdclear_state.check(); + tdwrite_state.check(); + tdread_state.check(); + rad_state.check(); + ts_state.write(); // always write timestamp + tdstatuswrite_state.write(); + tdstatusread_state.read(); + tbbsettings_state.check(); + tbbbandsel_state.check(); + bypasssettings_state.check(); // REO ? + rawdatawrite_state.check(); + rawdataread_state.check(); } + // + // clear() + // void clear() { - sys_state.clear(); - bf_state.clear(); - ss_state.clear(); - rcusettings_state.clear(); - rcuprotocol_state.clear(); - hbaprotocol_state.clear(); - rsuclear_state.clear(); - diagwgsettings_state.clear(); - sst_state.clear(); - bst_state.clear(); - xst_state.clear(); - cdo_state.clear(); - bs_state.clear(); - tdclear_state.clear(); - tdwrite_state.clear(); - tdread_state.clear(); - rad_state.clear(); - ts_state.clear(); - tdstatuswrite_state.clear(); - tdstatusread_state.clear(); - tbbsettings_state.clear(); - tbbbandsel_state.clear(); - bypasssettings_state.clear(); + sys_state.clear(); + bf_state.clear(); + ss_state.clear(); + rcusettings_state.clear(); + rcuprotocol_state.clear(); + hbaprotocol_state.clear(); + rsuclear_state.clear(); + diagwgsettings_state.clear(); + sst_state.clear(); + bst_state.clear(); + xst_state.clear(); + cdo_state.clear(); + bs_state.clear(); + tdclear_state.clear(); + tdwrite_state.clear(); + tdread_state.clear(); + rad_state.clear(); + ts_state.clear(); + tdstatuswrite_state.clear(); + tdstatusread_state.clear(); + tbbsettings_state.clear(); + tbbbandsel_state.clear(); + bypasssettings_state.clear(); + rawdatawrite_state.clear(); + rawdataread_state.clear(); } + // + // print(os) + // void print(std::ostream& out) const { - out << " "; - for (int i = 0; i < m_nrcus * EPA_Protocol::MEPHeader::N_POL; i++) { - out << (i % 10) << " "; - } - out << endl; - out << "System Status "; sys_state.print(out); - out << "BF "; bf_state.print(out); - out << "Subband Selection "; ss_state.print(out); - out << "RCUSettings "; rcusettings_state.print(out); - out << "RCUProtocol "; rcuprotocol_state.print(out); - out << "HBAProtocol "; hbaprotocol_state.print(out); - out << "RSUClear "; rsuclear_state.print(out); - out << "DIAGWGSettings "; diagwgsettings_state.print(out); - out << "SubbandStats "; sst_state.print(out); - out << "BeamletStats "; bst_state.print(out); - out << "XCorrelationStats "; xst_state.print(out); - out << "CDO "; cdo_state.print(out); - out << "BS "; bs_state.print(out); - out << "TDSClear "; tdclear_state.print(out); - out << "TDSWrite "; tdwrite_state.print(out); - out << "TDSRead "; tdread_state.print(out); - out << "RAD "; rad_state.print(out); - out << "Timestamp "; ts_state.print(out); - out << "TDS Status (write)"; tdstatuswrite_state.print(out); - out << "TDS Status (read) "; tdstatusread_state.print(out); - out << "TBBSettings "; tbbsettings_state.print(out); - out << "TBBBandsel "; tbbbandsel_state.print(out); - out << "DIAGBypassSettings"; bypasssettings_state.print(out); - out << endl; + out << " "; + for (int i = 0; i < m_nrcus * EPA_Protocol::MEPHeader::N_POL; i++) { + out << (i % 10) << " "; + } + out << endl; + out << "System Status "; sys_state.print(out); + out << "BF "; bf_state.print(out); + out << "Subband Selection "; ss_state.print(out); + out << "RCUSettings "; rcusettings_state.print(out); + out << "RCUProtocol "; rcuprotocol_state.print(out); + out << "HBAProtocol "; hbaprotocol_state.print(out); + out << "RSUClear "; rsuclear_state.print(out); + out << "DIAGWGSettings "; diagwgsettings_state.print(out); + out << "SubbandStats "; sst_state.print(out); + out << "BeamletStats "; bst_state.print(out); + out << "XCorrelationStats "; xst_state.print(out); + out << "CDO "; cdo_state.print(out); + out << "BS "; bs_state.print(out); + out << "TDSClear "; tdclear_state.print(out); + out << "TDSWrite "; tdwrite_state.print(out); + out << "TDSRead "; tdread_state.print(out); + out << "RAD "; rad_state.print(out); + out << "Timestamp "; ts_state.print(out); + out << "TDS Status (write) "; tdstatuswrite_state.print(out); + out << "TDS Status (read) "; tdstatusread_state.print(out); + out << "TBBSettings "; tbbsettings_state.print(out); + out << "TBBBandsel "; tbbbandsel_state.print(out); + out << "DIAGBypassSettings "; bypasssettings_state.print(out); + out << "RawDataBlock(write) "; rawdatawrite_state.print(out); + out << "RawDataBlock(read) "; rawdataread_state.print(out); + out << endl; } /*@{*/ - /** - * marshalling methods - */ + // marshalling methods unsigned int getSize(); unsigned int pack (void* buffer); unsigned int unpack(void *buffer); /*@}*/ - public: +public: /*@{*/ - /** - * Accessor methods - */ + // Accessor methods RTC::RegisterState& sys() { return sys_state; } RTC::RegisterState& bf() { return bf_state; } RTC::RegisterState& ss() { return ss_state; } @@ -265,9 +276,13 @@ namespace LOFAR { RTC::RegisterState& tbbsettings() { return tbbsettings_state; } RTC::RegisterState& tbbbandsel() { return tbbbandsel_state; } RTC::RegisterState& bypasssettings() { return bypasssettings_state; } + RTC::RegisterState& rawdatawrite() { return rawdatawrite_state; } + RTC::RegisterState& rawdataread() { return rawdataread_state; } + /*@}*/ - private: +private: + // ----- data members ----- RTC::RegisterState sys_state; // RSR state RTC::RegisterState bf_state; // BF weights state RTC::RegisterState ss_state; // SS state @@ -291,10 +306,13 @@ namespace LOFAR { RTC::RegisterState tbbsettings_state; // TBB settings state RTC::RegisterState tbbbandsel_state; // TBB bandsel state RTC::RegisterState bypasssettings_state; // Bypass (specinv) state + RTC::RegisterState rawdatawrite_state; // Write userdefined datablock + RTC::RegisterState rawdataread_state; // Read userdefined datablock int m_nrcus; - }; - }; +}; + + }; // namespace RSP_Protocol }; // namespace LOFAR #endif /* ALLREGISTERSTATE_H_ */ diff --git a/MAC/APL/PIC/RSP_Protocol/include/APL/RSP_Protocol/MEPData.h b/MAC/APL/PIC/RSP_Protocol/include/APL/RSP_Protocol/MEPData.h index 041dedcce01..04201c6fb1d 100644 --- a/MAC/APL/PIC/RSP_Protocol/include/APL/RSP_Protocol/MEPData.h +++ b/MAC/APL/PIC/RSP_Protocol/include/APL/RSP_Protocol/MEPData.h @@ -28,43 +28,34 @@ #include <unistd.h> namespace LOFAR { -namespace EPA_Protocol + namespace EPA_Protocol { + +class MEPData { - class MEPData - { - public: - /** - * Constructors for a MEPData object. - */ - MEPData() : m_dataptr(0), m_count(0) { } - - /* Destructor for MEPData. */ - virtual ~MEPData() {} +public: + // Constructors for a MEPData object. + MEPData() : m_dataptr(0), m_count(0) { } + virtual ~MEPData() {} - public: - /** - * Member access. - */ - void setBuffer(void* buf, size_t size); - void* getBuffer() const; + // Member access. + void setBuffer(void* buf, size_t size); + void* getBuffer() const; + size_t getDataLen() const; - public: - /*@{*/ - /** - * marshalling methods - */ - unsigned int getSize(); - unsigned int pack (void* buffer); - unsigned int unpack(void *buffer); - /*@}*/ + /*@{*/ + // marshalling methods + unsigned int getSize(); + unsigned int pack (void* buffer); + unsigned int unpack(void *buffer); + /*@}*/ - private: - /** - * MEP Payload data - */ - void* m_dataptr; // pointer to user data, not owned by this class - size_t m_count; - }; -}; +private: + // MEP Payload data + void* m_dataptr; // pointer to user data, not owned by this class + size_t m_count; }; + + }; // namepsace EPA_Protocol +}; // namespace LOFAR + #endif /* MEPDATA_H_ */ diff --git a/MAC/APL/PIC/RSP_Protocol/include/APL/RSP_Protocol/MEPHeader.h b/MAC/APL/PIC/RSP_Protocol/include/APL/RSP_Protocol/MEPHeader.h index 2ed25e993a3..a338060cade 100644 --- a/MAC/APL/PIC/RSP_Protocol/include/APL/RSP_Protocol/MEPHeader.h +++ b/MAC/APL/PIC/RSP_Protocol/include/APL/RSP_Protocol/MEPHeader.h @@ -35,433 +35,383 @@ namespace LOFAR { namespace EPA_Protocol { - class MEPHeader - { - public: - /** - * Constructors for a MEPHeader object. - */ - MEPHeader() { } - - /* Destructor for MEPHeader. */ - virtual ~MEPHeader() {} - - /** - * Size of MEP header in bytes. - */ - static const unsigned int SIZE = 16; - - /*@{*/ - /** - * Message types. - */ - static const uint8 TYPE_UNSET = 0x00; - static const uint8 READ = 0x01; - static const uint8 WRITE = 0x02; - static const uint8 READACK = 0x03; - static const uint8 WRITEACK = 0x04; - - static const int MIN_TYPE = READ; - static const int MAX_TYPE = WRITEACK; /* counting from 0 */ - /*@}*/ - - /*@{*/ - /** - * Address constants - * - * Definition of the addr.dstid values. - * Any of DST_BLP* and DST_RSP may be or-ed together - * to multicast to those destinations. - */ - static const uint16 DST_BLP0 = 0x0001; /* BLP 0, byte 0, bit 0 */ - static const uint16 DST_BLP1 = 0x0002; /* BLP 1, byte 0, bit 1 */ - static const uint16 DST_BLP2 = 0x0004; /* BLP 2, byte 0, bit 2 */ - static const uint16 DST_BLP3 = 0x0008; /* BLP 3, byte 0, bit 3 */ - static const uint16 DST_RSP = 0x0100; /* RSP, byte 1, bit 0 */ - - /* multicast constants */ - static const uint16 DST_ALL_BLPS = DST_BLP0 | DST_BLP1 | DST_BLP2 | DST_BLP3; /* All BLP, but not the RSP */ - static const uint16 DST_ALL = DST_ALL_BLPS | DST_RSP; /* All FPGA's (including RSP) */ - /*@}*/ - - /*@{*/ - /** - * Process IDs - * - * Constants extracted from MEP VHDL - * - * CONSTANT c_mep_pid_rsr : NATURAL := 1; - * CONSTANT c_mep_pid_rsu : NATURAL := 2; - * CONSTANT c_mep_pid_diag : NATURAL := 3; - * CONSTANT c_mep_pid_ss : NATURAL := 4; - * CONSTANT c_mep_pid_bf : NATURAL := 5; - * CONSTANT c_mep_pid_bst : NATURAL := 6; - * CONSTANT c_mep_pid_sst : NATURAL := 7; - * CONSTANT c_mep_pid_rcuh : NATURAL := 8; - * CONSTANT c_mep_pid_cr : NATURAL := 9; - * CONSTANT c_mep_pid_xst : NATURAL := 10; - * CONSTANT c_mep_pid_cdo : NATURAL := 11; - * CONSTANT c_mep_pid_bs : NATURAL := 12; - * CONSTANT c_mep_pid_serdes : NATURAL := 13; - * CONSTANT c_mep_pid_tdsh : NATURAL := 14; - * CONSTANT c_mep_pid_tbb : NATURAL := 15; - * - */ - static const uint8 RSR = 0x01; /* Status overview [RSP/BLP] */ - static const uint8 RSU = 0x02; /* FPGA remote system update. [RSP ] */ - static const uint8 DIAG = 0x03; /* Diagnostics [RSP/BLP] */ - static const uint8 SS = 0x04; /* Subband select [ BLP] */ - static const uint8 BF = 0x05; /* Beamformer [ BLP] */ - static const uint8 BST = 0x06; /* Beamformer statistics [RSP ] */ - static const uint8 SST = 0x07; /* Subband statistics [ BLP] */ - static const uint8 RCU = 0x08; /* RCU control [ BLP] */ - static const uint8 CR = 0x09; /* Clock and reset [RSP/BLP] */ - static const uint8 XST = 0x0A; /* Clock and reset [RSP/BLP] */ - static const uint8 CDO = 0x0B; /* CEP Data Output [RSP ] */ - static const uint8 BS = 0x0C; /* Block Synchronization [ BLP] */ - static const uint8 SERDES = 0x0D; /* Reserved1 */ - static const uint8 TDS = 0x0E; /* Time distribution board [RSP ] */ - static const uint8 TBB = 0x0F; /* Transient Buffer Board [ BLP] */ /* Is this correct? Should it not be RSP? */ - static const uint8 CEP = 0x10; /* CEP management [RSP ] */ - static const uint8 LCU = 0x11; /* LCU management [RSP ] */ - static const uint8 RAD = 0x12; /* RAD management [RSP ] */ - - static const int MIN_PID = RSR; /* loops over PID should be from */ - static const int MAX_PID = RAD; /* pid = MIN_PID; pid <= MAX_PID */ - /*@}*/ - - /*@{*/ - /** - * Register IDs - */ - static const uint8 RSR_STATUS = 0x00; - static const uint8 RSR_VERSION = 0x01; - static const uint8 RSR_TIMESTAMP = 0x02; - - static const uint8 RSU_FLASHRW = 0x01; - static const uint8 RSU_FLASHERASE = 0x02; - static const uint8 RSU_RECONFIGURE = 0x03; - static const uint8 RSU_RESET = 0x04; - - static const uint8 DIAG_WGX = 0x00; - static const uint8 DIAG_WGY = 0x01; - static const uint8 DIAG_WGXWAVE = 0x02; - static const uint8 DIAG_WGYWAVE = 0x03; - static const uint8 DIAG_BYPASS = 0x04; - static const uint8 DIAG_RESULTS = 0x05; - static const uint8 DIAG_SELFTEST = 0x06; - - static const uint8 SS_SELECT = 0x00; - - static const uint8 BF_XROUT = 0x00; - static const uint8 BF_XIOUT = 0x01; - static const uint8 BF_YROUT = 0x02; - static const uint8 BF_YIOUT = 0x03; - - static const uint8 BST_POWER_LANE_0 = 0x00; - static const uint8 BST_POWER_LANE_1 = 0x01; - static const uint8 BST_POWER_LANE_2 = 0x02; - static const uint8 BST_POWER_LANE_3 = 0x03; - - static const uint8 SST_POWER = 0x00; - - static const uint8 RCU_SETTINGS = 0x00; - static const uint8 RCU_PROTOCOLX = 0x01; - static const uint8 RCU_RESULTX = 0x02; - static const uint8 RCU_PROTOCOLY = 0x03; - static const uint8 RCU_RESULTY = 0x04; - - static const uint8 CR_SOFTCLEAR = 0x00; - static const uint8 CR_SOFTSYNC = 0x01; - static const uint8 CR_SYNCDISABLE = 0x02; - - /* - * Cross correlation registers. - */ - - - static const uint8 XST_STATS = 0x00; - static const uint8 XST_NR_STATS = 32; - - /** - * The CDO register will be extended to - * allow setting the UDP/IP header and some - * settings to set interleaving of beamlets. - */ - static const uint8 CDO_SETTINGS = 0x00; - static const uint8 CDO_HEADER = 0x01; - - static const uint8 BS_NOF_SAMPLES_PER_SYNC = 0x00; - - static const uint8 TDS_PROTOCOL = 0x00; - static const uint8 TDS_RESULT = 0x01; - - /** - * Placeholder register for future TBB control via the RSP board. - */ - static const uint8 TBB_SETTINGSX = 0x00; - static const uint8 TBB_SETTINGSY = 0x01; - static const uint8 TBB_BANDSELX = 0x02; - static const uint8 TBB_BANDSELY = 0x03; - - /** - * RAD_BP register controls how local and remove crosslet and - * beamlet data from the SERDES lanes is combined on an RSP - * board. This can be used to define logical start and end-points - * for the cross-correlation and beamforming data travelling on the - * SERDES rings. - */ - static const uint8 RAD_BP = 0x00; - - static const int MIN_REGID = 0x00; - static const int MAX_REGID = XST_NR_STATS - 1; - - /*@}*/ - - /*@{*/ - /** - * Define the number of beamlets N_BEAMLETS - * supported by the EPA firmware. For FTS-1 - * the number of beamlets supported is 128. - * For the final LOFAR remote station - * 256 beamlets will be supported. - * - * Many register sizes are derived from - * the number of beamlets. - * - * The N_SUBBANDS(512) defines the number of - * subbands produced by the EPA digital filter. - * The N_BEAMLETS are a selection from this - * number of beamlets. - */ - static const uint16 N_POL = 2; // number of polarizations - static const uint16 N_PHASE = 2; // number of phases in a complex number - static const uint16 N_PHASEPOL = N_PHASE * N_POL; // number of phase polarizations - static const uint16 MAX_N_RCUS = 128 * MEPHeader::N_POL; - static const uint16 N_BLPS = 4; // number of BLP's per RSP board - static const uint16 N_SUBBANDS = 512; - static const uint16 N_REMOTE_XLETS = 54; - static const uint16 N_SERDES_LANES = 4; - static const uint16 N_TOTAL_XLETS = N_SERDES_LANES * N_REMOTE_XLETS; - static const uint16 N_LOCAL_XLETS = 4; - static const uint16 N_BEAMLETS = 216; - static const uint16 N_LOCAL_BEAMLETS = 54; // N_BEAMLETS / N_SERDES_LANES - static const uint16 XLET_SIZE = N_POL * sizeof(std::complex<uint32>); - static const uint16 WEIGHT_SIZE = N_POL * sizeof(std::complex<uint16>); - - static const uint16 N_HBA_DELAYS = 16; // number of High Band antenna delay elements - - // TBB related constants - static const uint16 TBB_MAXPAYLOADSIZE = 1948; // available TBB payload bytes - static const uint16 TBB_NTRANSIENTSAMPLES = 1024; // number of 12-bit transient samples per frame - static const uint16 TBB_SPECTRALSAMPLESIZE = sizeof(std::complex<uint16>); - /*@}*/ - - - /*@{*/ - /** - * Define size of each register. - */ - static const uint16 RSR_STATUS_SIZE = 200; - static const uint16 RSR_VERSION_SIZE = 2; - static const uint16 RSR_TIMESTAMP_SIZE = 4; - - static const uint16 RSU_FLASHRW_SIZE = 1024; - static const uint16 RSU_FLASHERASE_SIZE = 1; - static const uint16 RSU_RECONFIGURE_SIZE = 1; - static const uint16 RSU_RESET_SIZE = 1; - - static const uint16 DIAG_WGX_SIZE = 12; - static const uint16 DIAG_WGY_SIZE = 12; - static const uint16 DIAG_WGXWAVE_SIZE = 8192; - static const uint16 DIAG_WGYWAVE_SIZE = 8192; - static const uint16 DIAG_BYPASS_SIZE = 2; - static const uint16 DIAG_RESULTS_SIZE = 4096; // also 8192 ? - static const uint16 DIAG_SELFTEST_SIZE = 4; - - static const uint16 SS_SELECT_SIZE = (N_LOCAL_XLETS + N_BEAMLETS) * N_POL * sizeof(uint16); // = 960? - - static const uint16 BF_XROUT_SIZE = (N_LOCAL_XLETS + N_BEAMLETS) * WEIGHT_SIZE; - static const uint16 BF_XIOUT_SIZE = (N_LOCAL_XLETS + N_BEAMLETS) * WEIGHT_SIZE; - static const uint16 BF_YROUT_SIZE = (N_LOCAL_XLETS + N_BEAMLETS) * WEIGHT_SIZE; - static const uint16 BF_YIOUT_SIZE = (N_LOCAL_XLETS + N_BEAMLETS) * WEIGHT_SIZE; - - static const uint16 BST_POWER_SIZE = N_LOCAL_BEAMLETS * N_POL * sizeof(uint32); - - static const uint16 SST_POWER_SIZE = N_SUBBANDS * N_POL * sizeof(uint32); - - static const uint16 RCU_SETTINGS_SIZE = 2; - static const uint16 RCU_PROTOCOL_SIZE = 512; - static const uint16 RCU_RESULT_SIZE = 512; - - static const uint16 CR_CONTROL_SIZE = 1; - - // (N_LOCAL_XLETS + N_REMOTE_XLETS) * XLET_SIZE; // 928 (!= 3424?) - static const uint16 XST_STATS_SIZE = N_REMOTE_XLETS * XLET_SIZE; // 864 - - /** - * The CDO register will be extended to - * allow setting the UDP/IP header and some - * settings to set interleaving of beamlets. - */ - static const uint16 CDO_SETTINGS_SIZE = 30; - static const uint16 CDO_HEADER_SIZE = 32; - - static const uint16 BS_NOF_SAMPLES_PER_SYNC_SIZE = 4; - - static const uint16 TDS_PROTOCOL_SIZE = 4096; - static const uint16 TDS_RESULT_SIZE = 1024; - - /** - * Placeholder register for future TBB control via the RSP board. - */ - static const uint16 TBB_SETTINGS_SIZE = 8; - static const uint16 TBB_BANDSEL_SIZE = 64; - - /** - * Size of the RAD_BP register. - */ - static const uint16 RAD_BP_SIZE = 4; // four bytes = 32 bits, 8 bits per lane - - // - // Registers too large to send in a single ethernet frame - // (> 1500 bytes) will be sent in a number of fragments of this size. - // - static const uint16 FRAGMENT_SIZE = 1024; - static const uint16 N_AP = 4; - static const uint16 BF_N_FRAGMENTS = 2; - static const uint16 N_WAVE_SAMPLES = DIAG_WGXWAVE_SIZE / sizeof(int32); - static const uint16 SST_N_FRAGMENTS = SST_POWER_SIZE / FRAGMENT_SIZE; - static const uint16 N_SST_STATS = FRAGMENT_SIZE / sizeof(uint32); - static const uint16 N_DIAG_WG_REGISTERS = 2; - static const uint16 N_CDO_REGISTERS = 2; - static const uint16 N_RCUPROTOCOL_WRITES = 2; - static const uint16 N_HBAPROTOCOL_WRITES = 2; - - /*@}*/ - - public: - /*@{*/ - /** - * marshalling methods - */ - unsigned int getSize(); - unsigned int pack (void* buffer); - unsigned int unpack(void *buffer); - /*@}*/ - - public: - /** - * MEP 4.x header fields - */ - typedef struct - { - uint8 type; /* Message type */ - uint8 status; /* Error indicator */ - uint16 frame_length; /* Frame length */ - typedef struct - { - uint16 dstid; /* Beamlet processor and RSP ID */ - uint8 pid; /* Process ID */ - uint8 regid; /* Register ID */ - } AddrType; - AddrType addr; /* addr */ - uint16 offset; /* Offset address */ - uint16 payload_length; /* Payload length (size) */ - uint16 seqnr; /* Sequence number */ - uint16 _reserved; /* Do not use; future use */ - } FieldsType; - - FieldsType m_fields; - - public: - - /*@{*/ - /** - * Methods to set header fields. - */ - void set(uint8 type, - uint16 dstid, - uint8 pid, - uint8 regid, - uint16 payload_length, - uint16 offset = 0); - - void set(MEPHeader::FieldsType hdrtemplate, - uint16 dstid = DST_RSP, - uint8 type = MEPHeader::TYPE_UNSET, - uint16 payload_length = 0, - uint16 offset = 0); - /*@}*/ - - /** - * Method to check if this MEPHeader is a valid - * acknowledgement for a specific request. - */ - bool isValidAck(const MEPHeader& reqhdr); - - /*@{*/ - // - // The following static constants are templates - // to produce EPA message headers. This is done by - // copying the template and then make modifications - // to the appropriate parts of the header. - // - static const FieldsType RSR_STATUS_HDR; - static const FieldsType RSR_VERSION_HDR; - static const FieldsType RSR_TIMESTAMP_HDR; - - static const FieldsType RSU_FLASHRW_HDR; - static const FieldsType RSU_FLASHERASE_HDR; - static const FieldsType RSU_RECONFIGURE_HDR; - static const FieldsType RSU_RESET_HDR; - - static const FieldsType DIAG_WGX_HDR; - static const FieldsType DIAG_WGY_HDR; - static const FieldsType DIAG_WGXWAVE_HDR; - static const FieldsType DIAG_WGYWAVE_HDR; - static const FieldsType DIAG_BYPASS_HDR; - static const FieldsType DIAG_RESULTS_HDR; - static const FieldsType DIAG_SELFTEST_HDR; - - static const FieldsType SS_SELECT_HDR; - - static const FieldsType BF_XROUT_HDR; - static const FieldsType BF_XIOUT_HDR; - static const FieldsType BF_YROUT_HDR; - static const FieldsType BF_YIOUT_HDR; - - static const FieldsType BST_POWER_HDR; - - static const FieldsType SST_POWER_HDR; - - static const FieldsType RCU_SETTINGS_HDR; - static const FieldsType RCU_PROTOCOLX_HDR; - static const FieldsType RCU_RESULTX_HDR; - static const FieldsType RCU_PROTOCOLY_HDR; - static const FieldsType RCU_RESULTY_HDR; - - static const FieldsType CR_CONTROL_HDR; - - static const FieldsType XST_STATS_HDR; - - static const FieldsType CDO_SETTINGS_HDR; - static const FieldsType CDO_HEADER_HDR; - - static const FieldsType BS_NOF_SAMPLES_PER_SYNC_HDR; - - static const FieldsType TDS_PROTOCOL_HDR; - static const FieldsType TDS_RESULT_HDR; - - static const FieldsType TBB_SETTINGSX_HDR; - static const FieldsType TBB_SETTINGSY_HDR; - static const FieldsType TBB_BANDSELX_HDR; - static const FieldsType TBB_BANDSELY_HDR; - - static const FieldsType RAD_BP_HDR; - /*@}*/ - }; - }; +class MEPHeader +{ +public: + // Constructors for a MEPHeader object. + MEPHeader() { } + virtual ~MEPHeader() {} + + // Size of MEP header in bytes. + static const unsigned int SIZE = 16; + + /*@{*/ + // Message types. + static const uint8 TYPE_UNSET = 0x00; + static const uint8 READ = 0x01; + static const uint8 WRITE = 0x02; + static const uint8 READACK = 0x03; + static const uint8 WRITEACK = 0x04; + + static const int MIN_TYPE = READ; + static const int MAX_TYPE = WRITEACK; /* counting from 0 */ + /*@}*/ + + /*@{*/ + // Address constants + // + // Definition of the addr.dstid values. + // Any of DST_BLP* and DST_RSP may be or-ed together + // to multicast to those destinations. + static const uint16 DST_BLP0 = 0x0001; /* BLP 0, byte 0, bit 0 */ + static const uint16 DST_BLP1 = 0x0002; /* BLP 1, byte 0, bit 1 */ + static const uint16 DST_BLP2 = 0x0004; /* BLP 2, byte 0, bit 2 */ + static const uint16 DST_BLP3 = 0x0008; /* BLP 3, byte 0, bit 3 */ + static const uint16 DST_RSP = 0x0100; /* RSP, byte 1, bit 0 */ + + // multicast constants + static const uint16 DST_ALL_BLPS = DST_BLP0 | DST_BLP1 | DST_BLP2 | DST_BLP3; /* All BLP, but not the RSP */ + static const uint16 DST_ALL = DST_ALL_BLPS | DST_RSP; /* All FPGA's (including RSP) */ + /*@}*/ + + /*@{*/ + // Process IDs + // + // Constants extracted from MEP VHDL + // + // CONSTANT c_mep_pid_rsr : NATURAL := 1; + // CONSTANT c_mep_pid_rsu : NATURAL := 2; + // CONSTANT c_mep_pid_diag : NATURAL := 3; + // CONSTANT c_mep_pid_ss : NATURAL := 4; + // CONSTANT c_mep_pid_bf : NATURAL := 5; + // CONSTANT c_mep_pid_bst : NATURAL := 6; + // CONSTANT c_mep_pid_sst : NATURAL := 7; + // CONSTANT c_mep_pid_rcuh : NATURAL := 8; + // CONSTANT c_mep_pid_cr : NATURAL := 9; + // CONSTANT c_mep_pid_xst : NATURAL := 10; + // CONSTANT c_mep_pid_cdo : NATURAL := 11; + // CONSTANT c_mep_pid_bs : NATURAL := 12; + // CONSTANT c_mep_pid_serdes : NATURAL := 13; + // CONSTANT c_mep_pid_tdsh : NATURAL := 14; + // CONSTANT c_mep_pid_tbb : NATURAL := 15; + // + static const uint8 RSR = 0x01; /* Status overview [RSP/BLP] */ + static const uint8 RSU = 0x02; /* FPGA remote system update. [RSP ] */ + static const uint8 DIAG = 0x03; /* Diagnostics [RSP/BLP] */ + static const uint8 SS = 0x04; /* Subband select [ BLP] */ + static const uint8 BF = 0x05; /* Beamformer [ BLP] */ + static const uint8 BST = 0x06; /* Beamformer statistics [RSP ] */ + static const uint8 SST = 0x07; /* Subband statistics [ BLP] */ + static const uint8 RCU = 0x08; /* RCU control [ BLP] */ + static const uint8 CR = 0x09; /* Clock and reset [RSP/BLP] */ + static const uint8 XST = 0x0A; /* Clock and reset [RSP/BLP] */ + static const uint8 CDO = 0x0B; /* CEP Data Output [RSP ] */ + static const uint8 BS = 0x0C; /* Block Synchronization [ BLP] */ + static const uint8 SERDES = 0x0D; /* Reserved1 */ + static const uint8 TDS = 0x0E; /* Time distribution board [RSP ] */ + static const uint8 TBB = 0x0F; /* Transient Buffer Board [ BLP] */ /* Is this correct? Should it not be RSP? */ + static const uint8 CEP = 0x10; /* CEP management [RSP ] */ + static const uint8 LCU = 0x11; /* LCU management [RSP ] */ + static const uint8 RAD = 0x12; /* RAD management [RSP ] */ + + static const int MIN_PID = RSR; /* loops over PID should be from */ + static const int MAX_PID = RAD; /* pid = MIN_PID; pid <= MAX_PID */ + /*@}*/ + + /*@{*/ + // Register IDs + static const uint8 RSR_STATUS = 0x00; + static const uint8 RSR_VERSION = 0x01; + static const uint8 RSR_TIMESTAMP = 0x02; + + static const uint8 RSU_FLASHRW = 0x01; + static const uint8 RSU_FLASHERASE = 0x02; + static const uint8 RSU_RECONFIGURE = 0x03; + static const uint8 RSU_RESET = 0x04; + + static const uint8 DIAG_WGX = 0x00; + static const uint8 DIAG_WGY = 0x01; + static const uint8 DIAG_WGXWAVE = 0x02; + static const uint8 DIAG_WGYWAVE = 0x03; + static const uint8 DIAG_BYPASS = 0x04; + static const uint8 DIAG_RESULTS = 0x05; + static const uint8 DIAG_SELFTEST = 0x06; + + static const uint8 SS_SELECT = 0x00; + + static const uint8 BF_XROUT = 0x00; + static const uint8 BF_XIOUT = 0x01; + static const uint8 BF_YROUT = 0x02; + static const uint8 BF_YIOUT = 0x03; + + static const uint8 BST_POWER_LANE_0 = 0x00; + static const uint8 BST_POWER_LANE_1 = 0x01; + static const uint8 BST_POWER_LANE_2 = 0x02; + static const uint8 BST_POWER_LANE_3 = 0x03; + + static const uint8 SST_POWER = 0x00; + + static const uint8 RCU_SETTINGS = 0x00; + static const uint8 RCU_PROTOCOLX = 0x01; + static const uint8 RCU_RESULTX = 0x02; + static const uint8 RCU_PROTOCOLY = 0x03; + static const uint8 RCU_RESULTY = 0x04; + + static const uint8 CR_SOFTCLEAR = 0x00; + static const uint8 CR_SOFTSYNC = 0x01; + static const uint8 CR_SYNCDISABLE = 0x02; + + // Cross correlation registers. + static const uint8 XST_STATS = 0x00; + static const uint8 XST_NR_STATS = 32; + + // The CDO register will be extended to + // allow setting the UDP/IP header and some + // settings to set interleaving of beamlets. + static const uint8 CDO_SETTINGS = 0x00; + static const uint8 CDO_HEADER = 0x01; + + static const uint8 BS_NOF_SAMPLES_PER_SYNC = 0x00; + + static const uint8 TDS_PROTOCOL = 0x00; + static const uint8 TDS_RESULT = 0x01; + + // Placeholder register for future TBB control via the RSP board. + static const uint8 TBB_SETTINGSX = 0x00; + static const uint8 TBB_SETTINGSY = 0x01; + static const uint8 TBB_BANDSELX = 0x02; + static const uint8 TBB_BANDSELY = 0x03; + + // RAD_BP register controls how local and remove crosslet and + // beamlet data from the SERDES lanes is combined on an RSP + // board. This can be used to define logical start and end-points + // for the cross-correlation and beamforming data travelling on the + // SERDES rings. + static const uint8 RAD_BP = 0x00; + + static const int MIN_REGID = 0x00; + static const int MAX_REGID = XST_NR_STATS - 1; + /*@}*/ + + /*@{*/ + // Define the number of beamlets N_BEAMLETS + // supported by the EPA firmware. For FTS-1 + // the number of beamlets supported is 128. + // For the final LOFAR remote station + // 256 beamlets will be supported. + // + // Many register sizes are derived from + // the number of beamlets. + // + // The N_SUBBANDS(512) defines the number of + // subbands produced by the EPA digital filter. + // The N_BEAMLETS are a selection from this + // number of beamlets. + static const uint16 N_POL = 2; // number of polarizations + static const uint16 N_PHASE = 2; // number of phases in a complex number + static const uint16 N_PHASEPOL = N_PHASE * N_POL; // number of phase polarizations + static const uint16 MAX_N_RCUS = 128 * MEPHeader::N_POL; + static const uint16 N_BLPS = 4; // number of BLP's per RSP board + static const uint16 N_SUBBANDS = 512; + static const uint16 N_REMOTE_XLETS = 54; + static const uint16 N_SERDES_LANES = 4; + static const uint16 N_TOTAL_XLETS = N_SERDES_LANES * N_REMOTE_XLETS; + static const uint16 N_LOCAL_XLETS = 4; + static const uint16 N_BEAMLETS = 216; + static const uint16 N_LOCAL_BEAMLETS = 54; // N_BEAMLETS / N_SERDES_LANES + static const uint16 XLET_SIZE = N_POL * sizeof(std::complex<uint32>); + static const uint16 WEIGHT_SIZE = N_POL * sizeof(std::complex<uint16>); + + static const uint16 N_HBA_DELAYS = 16; // number of High Band antenna delay elements + + // TBB related constants + static const uint16 TBB_MAXPAYLOADSIZE = 1948; // available TBB payload bytes + static const uint16 TBB_NTRANSIENTSAMPLES = 1024; // number of 12-bit transient samples per frame + static const uint16 TBB_SPECTRALSAMPLESIZE = sizeof(std::complex<uint16>); + /*@}*/ + + + /*@{*/ + // Define size of each register. + static const uint16 RSR_STATUS_SIZE = 200; + static const uint16 RSR_VERSION_SIZE = 2; + static const uint16 RSR_TIMESTAMP_SIZE = 4; + + static const uint16 RSU_FLASHRW_SIZE = 1024; + static const uint16 RSU_FLASHERASE_SIZE = 1; + static const uint16 RSU_RECONFIGURE_SIZE = 1; + static const uint16 RSU_RESET_SIZE = 1; + + static const uint16 DIAG_WGX_SIZE = 12; + static const uint16 DIAG_WGY_SIZE = 12; + static const uint16 DIAG_WGXWAVE_SIZE = 8192; + static const uint16 DIAG_WGYWAVE_SIZE = 8192; + static const uint16 DIAG_BYPASS_SIZE = 2; + static const uint16 DIAG_RESULTS_SIZE = 4096; // also 8192 ? + static const uint16 DIAG_SELFTEST_SIZE = 4; + + static const uint16 SS_SELECT_SIZE = (N_LOCAL_XLETS + N_BEAMLETS) * N_POL * sizeof(uint16); // = 960? + + static const uint16 BF_XROUT_SIZE = (N_LOCAL_XLETS + N_BEAMLETS) * WEIGHT_SIZE; + static const uint16 BF_XIOUT_SIZE = (N_LOCAL_XLETS + N_BEAMLETS) * WEIGHT_SIZE; + static const uint16 BF_YROUT_SIZE = (N_LOCAL_XLETS + N_BEAMLETS) * WEIGHT_SIZE; + static const uint16 BF_YIOUT_SIZE = (N_LOCAL_XLETS + N_BEAMLETS) * WEIGHT_SIZE; + + static const uint16 BST_POWER_SIZE = N_LOCAL_BEAMLETS * N_POL * sizeof(uint32); + + static const uint16 SST_POWER_SIZE = N_SUBBANDS * N_POL * sizeof(uint32); + + static const uint16 RCU_SETTINGS_SIZE = 2; + static const uint16 RCU_PROTOCOL_SIZE = 512; + static const uint16 RCU_RESULT_SIZE = 512; + + static const uint16 CR_CONTROL_SIZE = 1; + + // (N_LOCAL_XLETS + N_REMOTE_XLETS) * XLET_SIZE; // 928 (!= 3424?) + static const uint16 XST_STATS_SIZE = N_REMOTE_XLETS * XLET_SIZE; // 864 + + // The CDO register will be extended to + // allow setting the UDP/IP header and some + // settings to set interleaving of beamlets. + static const uint16 CDO_SETTINGS_SIZE = 30; + static const uint16 CDO_HEADER_SIZE = 32; + + static const uint16 BS_NOF_SAMPLES_PER_SYNC_SIZE = 4; + + static const uint16 TDS_PROTOCOL_SIZE = 4096; + static const uint16 TDS_RESULT_SIZE = 1024; + + // Placeholder register for future TBB control via the RSP board. + static const uint16 TBB_SETTINGS_SIZE = 8; + static const uint16 TBB_BANDSEL_SIZE = 64; + + // Size of the RAD_BP register. + static const uint16 RAD_BP_SIZE = 4; // four bytes = 32 bits, 8 bits per lane + + // Registers too large to send in a single ethernet frame + // (> 1500 bytes) will be sent in a number of fragments of this size. + static const uint16 FRAGMENT_SIZE = 1024; + static const uint16 N_AP = 4; + static const uint16 BF_N_FRAGMENTS = 2; + static const uint16 N_WAVE_SAMPLES = DIAG_WGXWAVE_SIZE / sizeof(int32); + static const uint16 SST_N_FRAGMENTS = SST_POWER_SIZE / FRAGMENT_SIZE; + static const uint16 N_SST_STATS = FRAGMENT_SIZE / sizeof(uint32); + static const uint16 N_DIAG_WG_REGISTERS = 2; + static const uint16 N_CDO_REGISTERS = 2; + static const uint16 N_RCUPROTOCOL_WRITES = 2; + static const uint16 N_HBAPROTOCOL_WRITES = 2; + /*@}*/ + + /*@{*/ + // marshalling methods + unsigned int getSize(); + unsigned int pack (void* buffer); + unsigned int unpack(void *buffer); + /*@}*/ + + // MEP 4.x header fields + typedef struct { + uint8 type; /* Message type */ + uint8 status; /* Error indicator */ + uint16 frame_length; /* Frame length */ + typedef struct { + uint16 dstid; /* Beamlet processor and RSP ID */ + uint8 pid; /* Process ID */ + uint8 regid; /* Register ID */ + } AddrType; + AddrType addr; /* addr */ + uint16 offset; /* Offset address */ + uint16 payload_length; /* Payload length (size) */ + uint16 seqnr; /* Sequence number */ + uint16 _reserved; /* Do not use; future use */ + } FieldsType; + + FieldsType m_fields; + + /*@{*/ + // Methods to set header fields. + void set(uint8 type, + uint16 dstid, + uint8 pid, + uint8 regid, + uint16 payload_length, + uint16 offset = 0); + + void set(MEPHeader::FieldsType hdrtemplate, + uint16 dstid = DST_RSP, + uint8 type = MEPHeader::TYPE_UNSET, + uint16 payload_length = 0, + uint16 offset = 0); + /*@}*/ + + // Method to check if this MEPHeader is a valid + // acknowledgement for a specific request. + bool isValidAck(const MEPHeader& reqhdr); + + /*@{*/ + // The following static constants are templates + // to produce EPA message headers. This is done by + // copying the template and then make modifications + // to the appropriate parts of the header. + static const FieldsType RSR_STATUS_HDR; + static const FieldsType RSR_VERSION_HDR; + static const FieldsType RSR_TIMESTAMP_HDR; + + static const FieldsType RSU_FLASHRW_HDR; + static const FieldsType RSU_FLASHERASE_HDR; + static const FieldsType RSU_RECONFIGURE_HDR; + static const FieldsType RSU_RESET_HDR; + + static const FieldsType DIAG_WGX_HDR; + static const FieldsType DIAG_WGY_HDR; + static const FieldsType DIAG_WGXWAVE_HDR; + static const FieldsType DIAG_WGYWAVE_HDR; + static const FieldsType DIAG_BYPASS_HDR; + static const FieldsType DIAG_RESULTS_HDR; + static const FieldsType DIAG_SELFTEST_HDR; + + static const FieldsType SS_SELECT_HDR; + + static const FieldsType BF_XROUT_HDR; + static const FieldsType BF_XIOUT_HDR; + static const FieldsType BF_YROUT_HDR; + static const FieldsType BF_YIOUT_HDR; + + static const FieldsType BST_POWER_HDR; + + static const FieldsType SST_POWER_HDR; + + static const FieldsType RCU_SETTINGS_HDR; + static const FieldsType RCU_PROTOCOLX_HDR; + static const FieldsType RCU_RESULTX_HDR; + static const FieldsType RCU_PROTOCOLY_HDR; + static const FieldsType RCU_RESULTY_HDR; + + static const FieldsType CR_CONTROL_HDR; + + static const FieldsType XST_STATS_HDR; + + static const FieldsType CDO_SETTINGS_HDR; + static const FieldsType CDO_HEADER_HDR; + + static const FieldsType BS_NOF_SAMPLES_PER_SYNC_HDR; + + static const FieldsType TDS_PROTOCOL_HDR; + static const FieldsType TDS_RESULT_HDR; + + static const FieldsType TBB_SETTINGSX_HDR; + static const FieldsType TBB_SETTINGSY_HDR; + static const FieldsType TBB_BANDSELX_HDR; + static const FieldsType TBB_BANDSELY_HDR; + + static const FieldsType RAD_BP_HDR; + + static const FieldsType RSP_RAWDATA_WRITE; + static const FieldsType RSP_RAWDATA_READ; + /*@}*/ }; + }; // namespace EPA_PROTOCOL +}; // namespace LOFAR + #endif /* MEPHEADER_H_ */ diff --git a/MAC/APL/PIC/RSP_Protocol/src/AllRegisterState.cc b/MAC/APL/PIC/RSP_Protocol/src/AllRegisterState.cc index 1953560721e..a259f1746a2 100644 --- a/MAC/APL/PIC/RSP_Protocol/src/AllRegisterState.cc +++ b/MAC/APL/PIC/RSP_Protocol/src/AllRegisterState.cc @@ -56,67 +56,73 @@ unsigned int AllRegisterState::getSize() + tdstatusread_state.getSize() + tbbsettings_state.getSize() + tbbbandsel_state.getSize() - + bypasssettings_state.getSize(); + + bypasssettings_state.getSize() + + rawdatawrite_state.getSize() + + rawdataread_state.getSize(); } unsigned int AllRegisterState::pack (void* buffer) { - unsigned int offset = 0; + unsigned int offset = 0; - offset += sys_state.pack((char*)buffer + offset); - offset += bf_state.pack((char*)buffer + offset); - offset += ss_state.pack((char*)buffer + offset); - offset += rcusettings_state.pack((char*)buffer + offset); - offset += rcuprotocol_state.pack((char*)buffer + offset); - offset += hbaprotocol_state.pack((char*)buffer + offset); - offset += rsuclear_state.pack((char*)buffer + offset); - offset += diagwgsettings_state.pack((char*)buffer + offset); - offset += sst_state.pack((char*)buffer + offset); - offset += bst_state.pack((char*)buffer + offset); - offset += xst_state.pack((char*)buffer + offset); - offset += cdo_state.pack((char*)buffer + offset); - offset += bs_state.pack((char*)buffer + offset); - offset += tdclear_state.pack((char*)buffer + offset); - offset += tdwrite_state.pack((char*)buffer + offset); - offset += tdread_state.pack((char*)buffer + offset); - offset += rad_state.pack((char*)buffer + offset); - offset += ts_state.pack((char*)buffer + offset); - offset += tdstatuswrite_state.pack((char*)buffer + offset); - offset += tdstatusread_state.pack((char*)buffer + offset); - offset += tbbsettings_state.pack((char*)buffer + offset); - offset += tbbbandsel_state.pack((char*)buffer + offset); - offset += bypasssettings_state.pack((char*)buffer + offset); + offset += sys_state.pack((char*)buffer + offset); + offset += bf_state.pack((char*)buffer + offset); + offset += ss_state.pack((char*)buffer + offset); + offset += rcusettings_state.pack((char*)buffer + offset); + offset += rcuprotocol_state.pack((char*)buffer + offset); + offset += hbaprotocol_state.pack((char*)buffer + offset); + offset += rsuclear_state.pack((char*)buffer + offset); + offset += diagwgsettings_state.pack((char*)buffer + offset); + offset += sst_state.pack((char*)buffer + offset); + offset += bst_state.pack((char*)buffer + offset); + offset += xst_state.pack((char*)buffer + offset); + offset += cdo_state.pack((char*)buffer + offset); + offset += bs_state.pack((char*)buffer + offset); + offset += tdclear_state.pack((char*)buffer + offset); + offset += tdwrite_state.pack((char*)buffer + offset); + offset += tdread_state.pack((char*)buffer + offset); + offset += rad_state.pack((char*)buffer + offset); + offset += ts_state.pack((char*)buffer + offset); + offset += tdstatuswrite_state.pack((char*)buffer + offset); + offset += tdstatusread_state.pack((char*)buffer + offset); + offset += tbbsettings_state.pack((char*)buffer + offset); + offset += tbbbandsel_state.pack((char*)buffer + offset); + offset += bypasssettings_state.pack((char*)buffer + offset); + offset += rawdatawrite_state.pack((char*)buffer + offset); + offset += rawdataread_state.pack((char*)buffer + offset); - return offset; + return (offset); } unsigned int AllRegisterState::unpack(void *buffer) { - unsigned int offset = 0; + unsigned int offset = 0; - offset += sys_state.unpack((char*)buffer + offset); - offset += bf_state.unpack((char*)buffer + offset); - offset += ss_state.unpack((char*)buffer + offset); - offset += rcusettings_state.unpack((char*)buffer + offset); - offset += rcuprotocol_state.unpack((char*)buffer + offset); - offset += hbaprotocol_state.unpack((char*)buffer + offset); - offset += rsuclear_state.unpack((char*)buffer + offset); - offset += diagwgsettings_state.unpack((char*)buffer + offset); - offset += sst_state.unpack((char*)buffer + offset); - offset += bst_state.unpack((char*)buffer + offset); - offset += xst_state.unpack((char*)buffer + offset); - offset += cdo_state.unpack((char*)buffer + offset); - offset += bs_state.unpack((char*)buffer + offset); - offset += tdclear_state.unpack((char*)buffer + offset); - offset += tdwrite_state.unpack((char*)buffer + offset); - offset += tdread_state.unpack((char*)buffer + offset); - offset += rad_state.unpack((char*)buffer + offset); - offset += ts_state.unpack((char*)buffer + offset); - offset += tdstatuswrite_state.unpack((char*)buffer + offset); - offset += tdstatusread_state.unpack((char*)buffer + offset); - offset += tbbsettings_state.unpack((char*)buffer + offset); - offset += tbbbandsel_state.unpack((char*)buffer + offset); - offset += bypasssettings_state.unpack((char*)buffer + offset); + offset += sys_state.unpack((char*)buffer + offset); + offset += bf_state.unpack((char*)buffer + offset); + offset += ss_state.unpack((char*)buffer + offset); + offset += rcusettings_state.unpack((char*)buffer + offset); + offset += rcuprotocol_state.unpack((char*)buffer + offset); + offset += hbaprotocol_state.unpack((char*)buffer + offset); + offset += rsuclear_state.unpack((char*)buffer + offset); + offset += diagwgsettings_state.unpack((char*)buffer + offset); + offset += sst_state.unpack((char*)buffer + offset); + offset += bst_state.unpack((char*)buffer + offset); + offset += xst_state.unpack((char*)buffer + offset); + offset += cdo_state.unpack((char*)buffer + offset); + offset += bs_state.unpack((char*)buffer + offset); + offset += tdclear_state.unpack((char*)buffer + offset); + offset += tdwrite_state.unpack((char*)buffer + offset); + offset += tdread_state.unpack((char*)buffer + offset); + offset += rad_state.unpack((char*)buffer + offset); + offset += ts_state.unpack((char*)buffer + offset); + offset += tdstatuswrite_state.unpack((char*)buffer + offset); + offset += tdstatusread_state.unpack((char*)buffer + offset); + offset += tbbsettings_state.unpack((char*)buffer + offset); + offset += tbbbandsel_state.unpack((char*)buffer + offset); + offset += bypasssettings_state.unpack((char*)buffer + offset); + offset += rawdatawrite_state.unpack((char*)buffer + offset); + offset += rawdataread_state.unpack((char*)buffer + offset); - return offset; + return (offset); } diff --git a/MAC/APL/PIC/RSP_Protocol/src/EPA_Protocol.prot b/MAC/APL/PIC/RSP_Protocol/src/EPA_Protocol.prot index 91399441505..f15e652ce23 100644 --- a/MAC/APL/PIC/RSP_Protocol/src/EPA_Protocol.prot +++ b/MAC/APL/PIC/RSP_Protocol/src/EPA_Protocol.prot @@ -257,6 +257,8 @@ prelude = << PRELUDE_END uint8 temperature; }; +#define RSP_RAW_DATABLOCK_SIZE 1480 + PRELUDE_END; // diff --git a/MAC/APL/PIC/RSP_Protocol/src/MEPData.cc b/MAC/APL/PIC/RSP_Protocol/src/MEPData.cc index e6497c08c90..2bf7cb2bb17 100644 --- a/MAC/APL/PIC/RSP_Protocol/src/MEPData.cc +++ b/MAC/APL/PIC/RSP_Protocol/src/MEPData.cc @@ -62,3 +62,8 @@ void* MEPData::getBuffer() const return m_dataptr; } +size_t MEPData::getDataLen() const +{ + return m_count; +} + diff --git a/MAC/APL/PIC/RSP_Protocol/src/MEPHeader.cc b/MAC/APL/PIC/RSP_Protocol/src/MEPHeader.cc index 151a0fc5f51..1f8847ca44b 100644 --- a/MAC/APL/PIC/RSP_Protocol/src/MEPHeader.cc +++ b/MAC/APL/PIC/RSP_Protocol/src/MEPHeader.cc @@ -87,6 +87,9 @@ const MEPHeader::FieldsType MEPHeader::TBB_BANDSELY_HDR = { WRITE, 0, 0, { const MEPHeader::FieldsType MEPHeader::RAD_BP_HDR = { WRITE, 0, 0, { DST_RSP, RAD, RAD_BP }, 0, RAD_BP_SIZE, 0, 0 }; +const MEPHeader::FieldsType MEPHeader::RSP_RAWDATA_WRITE = { WRITE, 0, 0, { 0xABBA, 0xBB, 0xAA }, 0xEFFE, 0xEBBE, 0x3412, 0 }; +const MEPHeader::FieldsType MEPHeader::RSP_RAWDATA_READ = { READ , 0, 0, { 0xABBA, 0xBB, 0xAA }, 0xEFFE, 0xEBBE, 0x3412, 0 }; + unsigned int MEPHeader::getSize() { return MEPHeader::SIZE; diff --git a/MAC/APL/PIC/RSP_Protocol/src/RSP_Protocol.prot b/MAC/APL/PIC/RSP_Protocol/src/RSP_Protocol.prot index bc473e96b95..f3cc98882d1 100644 --- a/MAC/APL/PIC/RSP_Protocol/src/RSP_Protocol.prot +++ b/MAC/APL/PIC/RSP_Protocol/src/RSP_Protocol.prot @@ -36,9 +36,10 @@ prelude = << PRELUDE_END typedef void* memptr_t; -static const int MAX_N_RSPBOARDS = 24; -static const int SUCCESS = 1; -static const int FAILURE = 0; +static const int MAX_N_RSPBOARDS = 24; +static const int SUCCESS = 1; +static const int FAILURE = 0; +static const int RSP_RAW_BLOCK_SIZE = 1480; // The protocol implements the following messages. // SETWEIGHTS (timestamp, rcumask,weights) @@ -155,6 +156,11 @@ static const int FAILURE = 0; // GETSPUSTATUS (timestamp, cache) // GETSPUSTATUSACK (timestamp, status, spustatus) +// SETBLOCK (timestamp, boardID, address, offset, datalen, data) +// SETBLOCKACK (timestamp, boardID, status); +// GETBLOCK (timestamp, boardID, address, offset, datalen) +// GETBLOCKACK (timestamp, boardID, status, datalen, data); + PRELUDE_END; // @@ -1854,3 +1860,106 @@ event = { }; }; +// SETBLOCK (timestamp, boardID, procID, pid, regid, offset, datalen, data) +event = { + signal = SETBLOCK; + dir = IN; + param = { + name = "timestamp"; + type = "RTC::Timestamp"; + userdefined; + }; + param = { + name = "boardID"; + type = "uint16"; + }; + param = { + name = "address"; + type = "uint32"; + }; + param = { + name = "offset"; + type = "uint16"; + }; + param = { + name = "dataLen"; + type = "uint16"; + }; + param = { + name = "data"; + type = "uint8[RSP_RAW_BLOCK_SIZE]"; + }; +}; + +// SETBLOCKACK (timestamp, boardID, status); +event = { + signal = SETBLOCKACK; + dir = IN; + param = { + name = "timestamp"; + type = "RTC::Timestamp"; + userdefined; + }; + param = { + name = "boardID"; + type = "uint16"; + }; + param = { + name = "status"; + type = "uint16"; + }; +}; + +// GETBLOCK (timestamp, boardID, procID, pid, regid, offset, datalen) +event = { + signal = GETBLOCK; + dir = IN; + param = { + name = "timestamp"; + type = "RTC::Timestamp"; + userdefined; + }; + param = { + name = "boardID"; + type = "uint16"; + }; + param = { + name = "address"; + type = "uint32"; + }; + param = { + name = "offset"; + type = "uint16"; + }; + param = { + name = "dataLen"; + type = "uint16"; + }; +}; + +// GETBLOCKACK (timestamp, boardID, status, datalen, data); +event = { + signal = GETBLOCKACK; + dir = IN; + param = { + name = "timestamp"; + type = "RTC::Timestamp"; + userdefined; + }; + param = { + name = "boardID"; + type = "uint16"; + }; + param = { + name = "status"; + type = "uint16"; + }; + param = { + name = "dataLen"; + type = "uint16"; + }; + param = { + name = "data"; + type = "uint8[RSP_RAW_BLOCK_SIZE]"; + }; +}; -- GitLab