From b6b13476fdfd6388da70bc2c89b26f8f831c6747 Mon Sep 17 00:00:00 2001
From: Pieter Donker <donker@astron.nl>
Date: Thu, 14 Oct 2010 12:40:08 +0000
Subject: [PATCH] Bug 1161: implemented XY swap

---
 LCS/Common/include/Common/LofarConstants.h    |   1 +
 MAC/APL/PIC/RSP_Driver/src/BWWrite.cc         |  80 +++++---
 MAC/APL/PIC/RSP_Driver/src/CMakeLists.txt     |   2 +
 MAC/APL/PIC/RSP_Driver/src/Cache.cc           |   1 +
 MAC/APL/PIC/RSP_Driver/src/Cache.h            |  11 +-
 MAC/APL/PIC/RSP_Driver/src/GetLatencyCmd.cc   |   2 +-
 MAC/APL/PIC/RSP_Driver/src/RSPDriver.cc       |  46 ++++-
 MAC/APL/PIC/RSP_Driver/src/RSPDriver.h        |   3 +
 MAC/APL/PIC/RSP_Driver/src/rspctl.cc          | 183 ++++++++++++++----
 MAC/APL/PIC/RSP_Driver/src/rspctl.h           |  54 +++++-
 .../PIC/RSP_Protocol/src/RSP_Protocol.prot    |  63 ++++++
 .../include/APL/RTCCommon/CMakeLists.txt      |   1 -
 .../src/TBBControl/TBBControlMain.cc          |   1 +
 13 files changed, 373 insertions(+), 75 deletions(-)

diff --git a/LCS/Common/include/Common/LofarConstants.h b/LCS/Common/include/Common/LofarConstants.h
index ed60df3bfae..ec417752872 100644
--- a/LCS/Common/include/Common/LofarConstants.h
+++ b/LCS/Common/include/Common/LofarConstants.h
@@ -35,6 +35,7 @@ namespace LOFAR {
 	static const int NR_RSPBOARDS_PER_SUBRACK = 4;
 	static const int NR_TBBOARDS_PER_RSPBOARD = 2;
 	static const int NR_RCUS_PER_RSPBOARD     = 8;
+	static const int NR_BLPS_PER_RSPBOARD     = 4;
 	static const int NR_ANTENNAS_PER_RSPBOARD = (NR_RCUS_PER_RSPBOARD / N_POL);
 	static const int NR_RCUS_PER_TBBOARD      = (NR_TBBOARDS_PER_RSPBOARD * NR_RCUS_PER_RSPBOARD);
 	static const int NR_RCUS_PER_SUBRACK      = (NR_RCUS_PER_RSPBOARD * NR_RSPBOARDS_PER_SUBRACK);
diff --git a/MAC/APL/PIC/RSP_Driver/src/BWWrite.cc b/MAC/APL/PIC/RSP_Driver/src/BWWrite.cc
index f2a673a94ab..3d794bcd04c 100644
--- a/MAC/APL/PIC/RSP_Driver/src/BWWrite.cc
+++ b/MAC/APL/PIC/RSP_Driver/src/BWWrite.cc
@@ -46,7 +46,7 @@ using namespace EPA_Protocol;
 
 BWWrite::BWWrite(GCFPortInterface& board_port, int board_id, int blp, int regid)
   : SyncAction(board_port, board_id, MEPHeader::BF_N_FRAGMENTS),
-    m_blp(blp), m_regid(regid), m_remaining(0), m_offset(0)
+	m_blp(blp), m_regid(regid), m_remaining(0), m_offset(0)
 {
   memset(&m_hdr, 0, sizeof(MEPHeader));
 }
@@ -84,20 +84,41 @@ void BWWrite::sendrequest()
 	// this code is only guaranteed to work under the following conditions
 	ASSERT(size < MEPHeader::FRAGMENT_SIZE);
 
-	switch (m_regid) {
-	case MEPHeader::BF_XROUT:
-		bfcoefs.hdr.set(MEPHeader::BF_XROUT_HDR, 1 << m_blp, MEPHeader::WRITE, size, m_offset);
-		break;
-	case MEPHeader::BF_XIOUT:
-		bfcoefs.hdr.set(MEPHeader::BF_XIOUT_HDR, 1 << m_blp, MEPHeader::WRITE, size, m_offset);
-		break;
-	case MEPHeader::BF_YROUT:
-		bfcoefs.hdr.set(MEPHeader::BF_YROUT_HDR, 1 << m_blp, MEPHeader::WRITE, size, m_offset);
-		break;
-	case MEPHeader::BF_YIOUT:
-		bfcoefs.hdr.set(MEPHeader::BF_YIOUT_HDR, 1 << m_blp, MEPHeader::WRITE, size, m_offset);
-		break;
-	}
+    // swap XY if needed
+    if (false == Cache::getInstance().getBack().isSwappedXY(global_blp)) {
+    	LOG_DEBUG_STR("XY= straight");
+    	switch (m_regid) {
+    	case MEPHeader::BF_XROUT:
+    		bfcoefs.hdr.set(MEPHeader::BF_XROUT_HDR, 1 << m_blp, MEPHeader::WRITE, size, m_offset);
+    		break;
+    	case MEPHeader::BF_XIOUT:
+    		bfcoefs.hdr.set(MEPHeader::BF_XIOUT_HDR, 1 << m_blp, MEPHeader::WRITE, size, m_offset);
+    		break;
+    	case MEPHeader::BF_YROUT:
+    		bfcoefs.hdr.set(MEPHeader::BF_YROUT_HDR, 1 << m_blp, MEPHeader::WRITE, size, m_offset);
+    		break;
+    	case MEPHeader::BF_YIOUT:
+    		bfcoefs.hdr.set(MEPHeader::BF_YIOUT_HDR, 1 << m_blp, MEPHeader::WRITE, size, m_offset);
+    		break;
+    	}
+    }
+    else {
+        LOG_DEBUG_STR("XY= swapped");
+    	switch (m_regid) {
+    	case MEPHeader::BF_XROUT:
+    		bfcoefs.hdr.set(MEPHeader::BF_YROUT_HDR, 1 << m_blp, MEPHeader::WRITE, size, m_offset);
+    		break;
+    	case MEPHeader::BF_XIOUT:
+    		bfcoefs.hdr.set(MEPHeader::BF_YIOUT_HDR, 1 << m_blp, MEPHeader::WRITE, size, m_offset);
+    		break;
+    	case MEPHeader::BF_YROUT:
+    		bfcoefs.hdr.set(MEPHeader::BF_XROUT_HDR, 1 << m_blp, MEPHeader::WRITE, size, m_offset);
+    		break;
+    	case MEPHeader::BF_YIOUT:
+    		bfcoefs.hdr.set(MEPHeader::BF_XIOUT_HDR, 1 << m_blp, MEPHeader::WRITE, size, m_offset);
+    		break;
+    	}
+    }
 
 	// create blitz view om the weights in the bfcoefs message to be sent to the RSP hardware
 	int nbeamlets_per_fragment = MEPHeader::N_BEAMLETS / MEPHeader::BF_N_FRAGMENTS;
@@ -130,11 +151,11 @@ void BWWrite::sendrequest()
 		LOG_DEBUG_STR("lane=" << lane);
 		LOG_DEBUG_STR("hw_range=" << hw_range);
 		LOG_DEBUG_STR("cache_range=" << cache_range);
-
-		// X
+		
+		// X = normal 0
 		weights(hw_range, 0) = Cache::getInstance().getBack().getBeamletWeights()()(0, global_blp * 2, cache_range);
 
-		// Y
+		// Y = normal 1
 		weights(hw_range, 1) = Cache::getInstance().getBack().getBeamletWeights()()(0, global_blp * 2 + 1, cache_range);
 
 #if 0
@@ -171,6 +192,7 @@ void BWWrite::sendrequest()
 	// for the x_our_r component and take the conjugate AND multiply by i
 	// the weight (a_r, a_i) to produce (a_i, a_r).
 	//
+
 	weights = conj(weights);
 
 	switch (m_regid) {
@@ -234,8 +256,8 @@ void BWWrite::sendrequest_status()
 GCFEvent::TResult BWWrite::handleack(GCFEvent& event, GCFPortInterface& /*port*/)
 {
   if (EPA_WRITEACK != event.signal) {
-    LOG_WARN("BWWrite::handleack: unexpected ack");
-    return GCFEvent::NOT_HANDLED;
+	LOG_WARN("BWWrite::handleack: unexpected ack");
+	return GCFEvent::NOT_HANDLED;
   }
   
   EPAWriteackEvent ack(event);
@@ -243,19 +265,19 @@ GCFEvent::TResult BWWrite::handleack(GCFEvent& event, GCFPortInterface& /*port*/
   uint8 global_blp = (getBoardId() * StationSettings::instance()->nrBlpsPerBoard()) + m_blp;
 
   if (!ack.hdr.isValidAck(m_hdr)) {
-    Cache::getInstance().getState().bf().write_error(global_blp * MEPHeader::N_PHASEPOL + m_regid);
+	Cache::getInstance().getState().bf().write_error(global_blp * MEPHeader::N_PHASEPOL + m_regid);
 
-    LOG_ERROR("BWWrite::handleack: invalid ack");
-    return GCFEvent::NOT_HANDLED;
+	LOG_ERROR("BWWrite::handleack: invalid ack");
+	return GCFEvent::NOT_HANDLED;
 
   } else {
 
-    //
-    // Last fragment signals completion
-    //
-    if (MEPHeader::MEPHeader::BF_N_FRAGMENTS - 1 == getCurrentIndex()) {
-      Cache::getInstance().getState().bf().write_ack(global_blp * MEPHeader::N_PHASEPOL + m_regid);
-    }
+	//
+	// Last fragment signals completion
+	//
+	if (MEPHeader::MEPHeader::BF_N_FRAGMENTS - 1 == getCurrentIndex()) {
+	  Cache::getInstance().getState().bf().write_ack(global_blp * MEPHeader::N_PHASEPOL + m_regid);
+	}
 
   }
 
diff --git a/MAC/APL/PIC/RSP_Driver/src/CMakeLists.txt b/MAC/APL/PIC/RSP_Driver/src/CMakeLists.txt
index 3bcd07aa076..295f1fdd70d 100644
--- a/MAC/APL/PIC/RSP_Driver/src/CMakeLists.txt
+++ b/MAC/APL/PIC/RSP_Driver/src/CMakeLists.txt
@@ -68,6 +68,8 @@ lofar_add_bin_program(RSPDriver
   GetLatencyCmd.cc
   SetDatastreamCmd.cc
   GetDatastreamCmd.cc
+  SetSwapxyCmd.cc
+  GetSwapxyCmd.cc
   SyncAction.cc
   WriteReg.cc
   ReadReg.cc
diff --git a/MAC/APL/PIC/RSP_Driver/src/Cache.cc b/MAC/APL/PIC/RSP_Driver/src/Cache.cc
index 060e7d86a3d..b119fb7a2b6 100644
--- a/MAC/APL/PIC/RSP_Driver/src/Cache.cc
+++ b/MAC/APL/PIC/RSP_Driver/src/Cache.cc
@@ -269,6 +269,7 @@ void CacheBuffer::reset(void)
 	RADLatency radlatencyinit;
 	memset(&radlatencyinit, 0, sizeof(RADLatency));
 	itsLatencys() = radlatencyinit;
+	itsSwappedXY.reset();
 }
 
 
diff --git a/MAC/APL/PIC/RSP_Driver/src/Cache.h b/MAC/APL/PIC/RSP_Driver/src/Cache.h
index d400bc121ee..90bcc3cf594 100644
--- a/MAC/APL/PIC/RSP_Driver/src/Cache.h
+++ b/MAC/APL/PIC/RSP_Driver/src/Cache.h
@@ -26,6 +26,7 @@
 #define CACHE_H_
 
 #include <Common/LofarTypes.h>
+#include <Common/LofarConstants.h>
 #include <Common/lofar_bitset.h>
 #include <blitz/array.h>
 #include <APL/RSP_Protocol/AllRegisterState.h>
@@ -88,13 +89,17 @@ public:
 	SerdesBuffer&			getSdsWriteBuffer() 	{ return (itsSdsWriteBuffer); }
 	SerdesBuffer&			getSdsReadBuffer(int rspBoardNr);
 	Latency&				getLatencys()			{ return (itsLatencys); }
-	
+		
 	bool isSplitterActive() { return(itsSplitterActive); }
 	void setSplitterActive(bool active) { itsSplitterActive = active; }
 
 	bool isCepEnabled() { return(itsCepEnabled); }
 	void setCepEnabled(bool enable) { itsCepEnabled = enable; }
 
+    bool isSwappedXY(int antenna){ return (itsSwappedXY.test(antenna)); }
+    void setSwappedXY(bitset<MAX_ANTENNAS> antennamask) { itsSwappedXY = antennamask; }
+    bitset<MAX_ANTENNAS> getSwappedXY() { return(itsSwappedXY); }
+
 	I2Cuser getI2Cuser() { return (itsI2Cuser); }
 	void setI2Cuser(I2Cuser user) { itsI2Cuser = user; }
 	/*@}*/
@@ -141,11 +146,11 @@ private:
 	RSP_Protocol::BypassSettings	m_bypasssettings;
 	RawDataBlock_t					itsRawDataBlock;
 	SerdesBuffer					itsSdsWriteBuffer;
-	SerdesBuffer					itsSdsReadBuffer[MAX_N_RSPBOARDS];
+	SerdesBuffer					itsSdsReadBuffer[MAX_RSPBOARDS];
 	bool							itsSplitterActive;
 	bool							itsCepEnabled;
 	RSP_Protocol::Latency			itsLatencys;
-	bitset<MAX_N_RSPBOARDS*8>       itsSwapXY;
+	bitset<MAX_ANTENNAS>            itsSwappedXY;
 	
 	Cache* m_cache;		// pointer to container
 };
diff --git a/MAC/APL/PIC/RSP_Driver/src/GetLatencyCmd.cc b/MAC/APL/PIC/RSP_Driver/src/GetLatencyCmd.cc
index 25050eb8084..36c656f93ea 100644
--- a/MAC/APL/PIC/RSP_Driver/src/GetLatencyCmd.cc
+++ b/MAC/APL/PIC/RSP_Driver/src/GetLatencyCmd.cc
@@ -36,7 +36,7 @@ using namespace RSP_Protocol;
 using namespace RTC;
 
 GetLatencyCmd::GetLatencyCmd(GCFEvent& event, GCFPortInterface& port, Operation oper) :
-	Command("GetVersion", port, oper)
+	Command("GetLatency", port, oper)
 {
   m_event = new RSPGetlatencyEvent(event);
 }
diff --git a/MAC/APL/PIC/RSP_Driver/src/RSPDriver.cc b/MAC/APL/PIC/RSP_Driver/src/RSPDriver.cc
index 8d108925799..5e30be0f61a 100644
--- a/MAC/APL/PIC/RSP_Driver/src/RSPDriver.cc
+++ b/MAC/APL/PIC/RSP_Driver/src/RSPDriver.cc
@@ -94,7 +94,8 @@
 #include "GetLatencyCmd.h"
 #include "SetDatastreamCmd.h"
 #include "GetDatastreamCmd.h"
-
+#include "SetSwapxyCmd.h"
+#include "GetSwapxyCmd.h"
 
 #include "RSUWrite.h"
 #include "BSWrite.h"
@@ -1040,6 +1041,8 @@ GCFEvent::TResult RSPDriver::enabled(GCFEvent& event, GCFPortInterface& port)
 	case RSP_GETLATENCY:			rsp_latencys(event,port);		    break;
 	case RSP_SETDATASTREAM:         rsp_setDatastream(event,port);      break;
 	case RSP_GETDATASTREAM:         rsp_getDatastream(event,port);      break;
+	case RSP_SETSWAPXY:             rsp_setswapxy(event,port);          break;
+	case RSP_GETSWAPXY:             rsp_getswapxy(event,port);          break;
 
     case F_TIMER: {
 		if (&port == &m_boardPorts[0]) {
@@ -2442,6 +2445,47 @@ void RSPDriver::rsp_latencys(GCFEvent& event, GCFPortInterface& port)
     return;
   }
 }
+
+//
+// rsp_setswapxy (event, port)
+//
+void RSPDriver::rsp_setswapxy(GCFEvent& event, GCFPortInterface& port)
+{
+  Ptr<SetSwapXYCmd> command = new SetSwapXYCmd(event, port, Command::WRITE);
+
+  if (!command->validate()) {
+    LOG_ERROR("SETSWAPXY: invalid parameter");
+    
+    RSPSetswapxyackEvent ack;
+    ack.timestamp = Timestamp(0,0);
+    ack.status = RSP_FAILURE;
+    port.send(ack);
+    return;
+  }
+  m_scheduler.enter(Ptr<Command>(&(*command)));
+}
+
+//
+// rsp_getswapxy (event, port)
+//
+void RSPDriver::rsp_getswapxy(GCFEvent& event, GCFPortInterface& port)
+{
+  Ptr<GetSwapXYCmd> command = new GetSwapXYCmd(event, port, Command::READ);
+
+  if (!command->validate()) {
+    LOG_ERROR("GETSWAPXY: invalid parameter");
+    
+    RSPGetswapxyackEvent ack;
+    ack.timestamp = Timestamp(0,0);
+    ack.status = RSP_FAILURE;
+    port.send(ack);
+    return;
+  }
+  m_scheduler.enter(Ptr<Command>(&(*command)));
+}
+
+
+  
   
 //
 // rsp_setDatastream(event, port)
diff --git a/MAC/APL/PIC/RSP_Driver/src/RSPDriver.h b/MAC/APL/PIC/RSP_Driver/src/RSPDriver.h
index 87ae1eeeb81..8d0787173c9 100644
--- a/MAC/APL/PIC/RSP_Driver/src/RSPDriver.h
+++ b/MAC/APL/PIC/RSP_Driver/src/RSPDriver.h
@@ -163,6 +163,9 @@ public:
 	
 	void rsp_setDatastream(GCFEvent& event, GCFPortInterface &port);
 	void rsp_getDatastream(GCFEvent& event, GCFPortInterface &port);
+	
+	void rsp_setswapxy(GCFEvent& event, GCFPortInterface& port);
+	void rsp_getswapxy(GCFEvent& event, GCFPortInterface& port);
 	/*@}*/
 
 private:
diff --git a/MAC/APL/PIC/RSP_Driver/src/rspctl.cc b/MAC/APL/PIC/RSP_Driver/src/rspctl.cc
index b27e9cd5d44..285b83eff89 100644
--- a/MAC/APL/PIC/RSP_Driver/src/rspctl.cc
+++ b/MAC/APL/PIC/RSP_Driver/src/rspctl.cc
@@ -191,18 +191,18 @@ void WeightsCommand::send()
 		setweights.rcumask   = getRCUMask();
 
 		logMessage(cerr,formatString("rcumask.count()=%d",setweights.rcumask.count()));
-		setweights.weights().resize(1, setweights.rcumask.count(), MEPHeader::N_BEAMLETS);
+		setweights.weights().resize(1, setweights.rcumask.count(), MAX_BEAMLETS);
 
-		bitset<MEPHeader::N_BEAMLETS> beamlet_mask = getBEAMLETSMask();
+		bitset<MAX_BEAMLETS> beamlet_mask = getBEAMLETSMask();
 
 		// -1 < m_value <= 1
 		complex<double> value = m_value;
 		value *= (1<<14); // -.99999 should become -16383 and 1 should become 16384
 		setweights.weights() = itsWeights;
 		int rcunr = 0;
-		for (int rcu = 0; rcu < MEPHeader::MAX_N_RCUS; rcu++) {
+		for (int rcu = 0; rcu < MAX_RCUS; rcu++) {
 			if (setweights.rcumask.test(rcu)) {
-				for (int beamlet = 0; beamlet < MEPHeader::N_BEAMLETS; beamlet++) {
+				for (int beamlet = 0; beamlet < MAX_BEAMLETS; beamlet++) {
 					if (beamlet_mask.test(beamlet)) {
 						setweights.weights()(0,rcunr,beamlet) = complex<int16>((int16)value.real(), (int16)value.imag()); // complex<int16>((int16)value,0);
 					}
@@ -226,8 +226,8 @@ GCFEvent::TResult WeightsCommand::ack(GCFEvent& e)
 	switch (e.signal) {
 		case RSP_GETWEIGHTSACK: {
 			RSPGetweightsackEvent ack(e);
-			bitset<MEPHeader::MAX_N_RCUS> mask = getRCUMask();
-			itsWeights.resize(1, mask.count(), MEPHeader::N_BEAMLETS);
+			bitset<MAX_RCUS> mask = getRCUMask();
+			itsWeights.resize(1, mask.count(), MAX_BEAMLETS);
 			itsWeights = complex<int16>(0,0);
 			itsWeights = ack.weights();
 
@@ -326,7 +326,7 @@ void SubbandsCommand::send()
 		case SubbandSelection::BEAMLET:
 			{
 	if (1 == m_subbandlist.size()) {
-		setsubbands.subbands().resize(1, MEPHeader::N_BEAMLETS);
+		setsubbands.subbands().resize(1, MAX_BEAMLETS);
 		std::list<int>::iterator it = m_subbandlist.begin();
 		setsubbands.subbands() = (*it);
 	} else {
@@ -336,11 +336,11 @@ void SubbandsCommand::send()
 		std::list<int>::iterator it;
 		for (it = m_subbandlist.begin(); it != m_subbandlist.end(); it++, i++)
 			{
-				if (i >= MEPHeader::N_BEAMLETS) break;
+				if (i >= MAX_BEAMLETS) break;
 				setsubbands.subbands()(0, i) = (*it);
 			}
 #if 0
-		for (; i < MEPHeader::N_BEAMLETS; i++) {
+		for (; i < MAX_BEAMLETS; i++) {
 			setsubbands.subbands()(0, i) = 0;
 		}
 #endif
@@ -372,7 +372,7 @@ GCFEvent::TResult SubbandsCommand::ack(GCFEvent& e)
 	switch (e.signal) {
 		case RSP_GETSUBBANDSACK: {
 			RSPGetsubbandsackEvent ack(e);
-			bitset<MEPHeader::MAX_N_RCUS> mask = getRCUMask();
+			bitset<MAX_RCUS> mask = getRCUMask();
 
 			std::ostringstream msg;
 			msg << "getsubbandsack.timestamp=" << ack.timestamp;
@@ -460,7 +460,7 @@ GCFEvent::TResult RCUCommand::ack(GCFEvent& e)
 	switch (e.signal) {
 		case RSP_GETRCUACK: {
 			RSPGetrcuackEvent ack(e);
-			bitset<MEPHeader::MAX_N_RCUS> mask = getRCUMask();
+			bitset<MAX_RCUS> mask = getRCUMask();
 
 			if (ack.status == RSP_SUCCESS) {
 				int rcuin = 0;
@@ -497,6 +497,94 @@ GCFEvent::TResult RCUCommand::ack(GCFEvent& e)
 	return GCFEvent::HANDLED;
 }
 
+
+// Swap X Y on RCU
+
+SWAPXYCommand::SWAPXYCommand(GCFPortInterface& port) : Command(port)
+{
+}
+
+void SWAPXYCommand::send()
+{
+	if (getMode()) {
+		// GET
+		RSPGetswapxyEvent   getswapxy;
+		getswapxy.timestamp = Timestamp(0,0);
+		getswapxy.cache     = true;
+
+		m_rspport.send(getswapxy);
+	}
+	else {
+		// SET
+		RSPSetswapxyEvent   setswapxy;
+		setswapxy.timestamp = Timestamp(0,0);
+		setswapxy.antennamask   = getANTENNAMask();
+		setswapxy.swapxy    = getSwapXY();
+
+		logMessage(cout,formatString("antennamask.count()=%d", setswapxy.antennamask.count()));
+		m_rspport.send(setswapxy);
+	}
+}
+
+GCFEvent::TResult SWAPXYCommand::ack(GCFEvent& e)
+{
+	GCFEvent::TResult status = GCFEvent::HANDLED;
+
+	switch (e.signal) {
+		case RSP_GETSWAPXYACK: {
+			RSPGetswapxyackEvent ack(e);
+
+			std::ostringstream msg;
+			msg << "setswapxyack.timestamp=" << ack.timestamp;
+			logMessage(cout, msg.str());
+			msg.seekp(0);
+
+			if (RSP_SUCCESS != ack.status) {
+				logMessage(cerr, "Error: RSP_GETSWAPXY command failed.");
+				break;
+			}
+
+			// print swap settings
+			for (int ant = 0; ant < get_ndevices(); ant++) {
+				if (getANTENNAMask().test(ant)) {
+					cout << formatString("ANTENNA[%02u].xy= ", ant);
+					// if antenna is set in mask, xy is swapped
+					if (ack.antennamask.test(ant)) {
+						cout << "swapped";
+					}
+					else {
+						cout << "straight";
+					}
+					cout << endl;
+				}
+			}
+		}
+		break;
+
+		case RSP_SETSWAPXYACK: {
+			RSPSetswapxyackEvent ack(e);
+
+			std::ostringstream msg;
+			msg << "setswapxyack.timestamp=" << ack.timestamp;
+			logMessage(cout, msg.str());
+
+			if (RSP_SUCCESS != ack.status) {
+				logMessage(cerr, "Error: RSP_SETSWAPXY command failed.");
+			}
+		}
+		break;
+
+		default:
+			status = GCFEvent::NOT_HANDLED;
+		break;
+	}
+
+	GCFScheduler::instance()->stop();
+
+	return status;
+}
+
+
 HBACommand::HBACommand(GCFPortInterface& port) : Command(port)
 {
 }
@@ -562,7 +650,7 @@ GCFEvent::TResult HBACommand::ack(GCFEvent& e)
 	switch (e.signal) {
 	case RSP_GETHBAACK: {
 		RSPGethbaackEvent ack(e);
-		bitset<MEPHeader::MAX_N_RCUS> mask = getRCUMask();
+		bitset<MAX_RCUS> mask = getRCUMask();
 
 		cout << "settings().shape()=" << ack.settings().shape() << endl;
 
@@ -587,7 +675,7 @@ GCFEvent::TResult HBACommand::ack(GCFEvent& e)
 
 	case RSP_READHBAACK: {
 		RSPReadhbaackEvent ack(e);
-		bitset<MEPHeader::MAX_N_RCUS> mask = getRCUMask();
+		bitset<MAX_RCUS> mask = getRCUMask();
 
 		cout << "settings().shape()=" << ack.settings().shape() << endl;
 
@@ -666,7 +754,7 @@ GCFEvent::TResult RSUCommand::ack(GCFEvent& e)
 #if 0
 		case RSP_GETRSUACK: {
 			RSPGetrsuackEvent ack(e);
-			bitset<MEPHeader::MAX_N_RCUS> mask = getRCUMask();
+			bitset<MAX_RCUS> mask = getRCUMask();
 
 			if (RSP_SUCCESS == ack.status) {
 				int boardin = 0;
@@ -938,7 +1026,7 @@ void TBBCommand::send()
 
 				std::list<int>::iterator it;
 				for (it = m_subbandlist.begin(); it != m_subbandlist.end(); it++) {
-					if ((*it) >= MEPHeader::N_SUBBANDS) {
+					if ((*it) >= MAX_SUBBANDS) {
 						continue;
 					}
 					settbb.settings()(0).set(*it);
@@ -985,7 +1073,7 @@ GCFEvent::TResult TBBCommand::ack(GCFEvent& e)
 					}
 					else {
 						for (unsigned int ilong = 0; ilong < ack.settings()(0).size()/(sizeof(uint32) * BITSOFBYTE); ilong++) {
-							cout << formatString("%08lx ", htonl((ack.settings()(rcuin) & bitset<MEPHeader::N_SUBBANDS>(0xFFFFFFFF)).to_uint32()));
+							cout << formatString("%08lx ", htonl((ack.settings()(rcuin) & bitset<MAX_SUBBANDS>(0xFFFFFFFF)).to_uint32()));
 							ack.settings()(rcuin) >>= sizeof(uint32)*BITSOFBYTE;
 						}
 					}
@@ -1583,7 +1671,7 @@ GCFEvent::TResult WGCommand::ack(GCFEvent& e)
 			if (RSP_SUCCESS == ack.status) {
 
 				// print settings
-				bitset<MEPHeader::MAX_N_RCUS> mask = getRCUMask();
+				bitset<MAX_RCUS> mask = getRCUMask();
 				int rcuin = 0;
 				for (int rcuout = 0; rcuout < get_ndevices(); rcuout++) {
 
@@ -1922,7 +2010,7 @@ void StatisticsCommand::plot_statistics(Array<double, 2>& stats, const Timestamp
 	
 	int n_freqbands = stats.extent(secondDim);
 	int n_firstIndex = stats.extent(firstDim);
-	bitset<MEPHeader::MAX_N_RCUS> mask = getRCUMask();
+	bitset<MAX_RCUS> mask = getRCUMask();
 
 	char plotcmd[256];
 	int startrcu;
@@ -1958,7 +2046,7 @@ void StatisticsCommand::plot_statistics(Array<double, 2>& stats, const Timestamp
 				break;
 			case Statistics::BEAMLET_POWER:
 				gnuplot_cmd(handle, "set xlabel \"Beamlet index\"\n");
-				gnuplot_cmd(handle, "set xrange [0:%d]\n", MEPHeader::N_BEAMLETS);
+				gnuplot_cmd(handle, "set xrange [0:%d]\n", MAX_BEAMLETS);
 				break;
 		}
 	}
@@ -2045,7 +2133,7 @@ void StatisticsCommand::plot_statistics(Array<double, 2>& stats, const Timestamp
 					break;
 				case Statistics::BEAMLET_POWER:
 					gnuplot_cmd(handle2, "set xlabel \"Beamlet index\"\n");
-					gnuplot_cmd(handle2, "set xrange [0:%d]\n", MEPHeader::N_BEAMLETS);
+					gnuplot_cmd(handle2, "set xrange [0:%d]\n", MAX_BEAMLETS);
 					break;
 			}
 		}
@@ -2097,7 +2185,7 @@ void StatisticsCommand::plot_statistics(Array<double, 2>& stats, const Timestamp
 
 void StatisticsCommand::dump_statistics(Array<double, 2>& stats, const Timestamp& timestamp)
 {
-	bitset<MEPHeader::MAX_N_RCUS> mask = getRCUMask();
+	bitset<MAX_RCUS> mask = getRCUMask();
 
 	int result_device=0;
 	for (int deviceout = 0; deviceout < get_ndevices(); deviceout++) {
@@ -2460,7 +2548,8 @@ RSPCtl::RSPCtl(string name, int argc, char** argv) :
 	GCFTask((State)&RSPCtl::initial, name), 
 	itsCommand  (0),
 	m_nrcus   (0), 
-	m_nrspboards (0), 
+	m_nrspboards (0),
+	itsNantennas (0), 
 	m_argc   (argc), 
 	m_argv   (argv), 
 	m_instancenr (-1),
@@ -2521,7 +2610,8 @@ GCFEvent::TResult RSPCtl::initial(GCFEvent& e, GCFPortInterface& port)
 
 	case RSP_GETCONFIGACK: {
 		RSPGetconfigackEvent ack(e);
-		m_nrcus     = ack.n_rcus;
+		m_nrcus        = ack.n_rcus;
+		itsNantennas   = ack.n_rcus / N_POL;
 		m_nrspboards   = ack.n_rspboards;
 		m_maxrspboards = ack.max_rspboards;
 		LOG_DEBUG_STR(formatString("n_rcus    =%d",m_nrcus));
@@ -2775,6 +2865,8 @@ GCFEvent::TResult RSPCtl::doCommand(GCFEvent& e, GCFPortInterface& port)
 	case RSP_GETLATENCYACK:
 	case RSP_SETDATASTREAMACK:
 	case RSP_GETDATASTREAMACK:
+	case RSP_SETSWAPXYACK:
+	case RSP_GETSWAPXYACK:
 					
 		status = itsCommand->ack(e); // handle the acknowledgement
 		gClockChanged = false;
@@ -2941,15 +3033,16 @@ Command* RSPCtl::parse_options(int argc, char** argv)
 	HBACommand*   hbacommand  = 0;
 	list<int> select;
 	list<int> beamlets;
+	
 	bool  xcangle = false;
 
 	// select all by default
 	select.clear();
-	for (int i = 0; i < MEPHeader::MAX_N_RCUS; ++i)
+	for (int i = 0; i < MAX_RCUS; ++i)
 		select.push_back(i);
 
 	beamlets.clear();
-	for (int i = 0; i < MEPHeader::N_BEAMLETS; ++i)
+	for (int i = 0; i < MAX_BEAMLETS; ++i)
 		beamlets.push_back(i);
 
 	optind = 0; // reset option parsing
@@ -2966,6 +3059,7 @@ Command* RSPCtl::parse_options(int argc, char** argv)
 		{ "select",         required_argument, 0, 'l' },
 		{ "rcumode",        required_argument, 0, 'm' },
 		{ "rcuattenuation", required_argument, 0, 'n' },
+		{ "swapxy",         optional_argument, 0, 'o' },
 		{ "rcuprsg",        optional_argument, 0, 'p' },
 		{ "status",         no_argument,       0, 'q' },
 		{ "rcu",            optional_argument, 0, 'r' },
@@ -3034,7 +3128,7 @@ Command* RSPCtl::parse_options(int argc, char** argv)
 					logMessage(cerr,"Error: 'command' argument should come before --beamlets argument");
 					exit(EXIT_FAILURE);
 				}
-				beamlets = strtolist(optarg, MEPHeader::N_BEAMLETS);
+				beamlets = strtolist(optarg, MAX_BEAMLETS);
 				if (beamlets.empty()) {
 					logMessage(cerr,"Error: invalid or missing '--beamlets' option");
 					exit(EXIT_FAILURE);
@@ -3112,7 +3206,7 @@ Command* RSPCtl::parse_options(int argc, char** argv)
 
 			if (optarg) {
 				subbandscommand->setMode(false);
-				list<int> subbandlist = strtolist(optarg, MEPHeader::N_SUBBANDS);
+				list<int> subbandlist = strtolist(optarg, MAX_SUBBANDS);
 				if (subbandlist.empty()) {
 					logMessage(cerr,"Error: invalid or empty '--subbands' option");
 					exit(EXIT_FAILURE);
@@ -3232,6 +3326,29 @@ Command* RSPCtl::parse_options(int argc, char** argv)
 		}
 		break;
 
+		case 'o': // swapxy
+		{
+			if (command)
+				delete command;
+			SWAPXYCommand* swapxycommand = new SWAPXYCommand(*itsRSPDriver);
+			command = swapxycommand;
+			
+			command->set_ndevices(itsNantennas);
+			select.clear();
+	        for (int i = 0; i < itsNantennas; ++i) {
+		        select.push_back(i);
+		    }
+		
+			if (optarg) {
+			    swapxycommand->setMode(false);
+    			if (!strncmp(optarg, "0", 1)) {
+    				swapxycommand->setSwapXY(false);
+    			} else {
+    				swapxycommand->setSwapXY(true);
+    			}
+    		}
+		} break;
+
 		case 'g': // --wg
 		{
 			if (command)
@@ -3360,7 +3477,7 @@ Command* RSPCtl::parse_options(int argc, char** argv)
 				if (!strcmp(optarg, "subband")) {
 					statscommand->setType(Statistics::SUBBAND_POWER);
 				} else if (!strcmp(optarg, "beamlet")) {
-					command->set_ndevices(m_nrspboards * MEPHeader::N_POL);
+					command->set_ndevices(m_nrspboards * N_POL);
 					statscommand->setType(Statistics::BEAMLET_POWER);
 					itsNeedSplitter = true;
 				} else {
@@ -3404,13 +3521,13 @@ Command* RSPCtl::parse_options(int argc, char** argv)
 
 				int subband = atoi(optarg);
 
-				if (subband < 0 || subband >= MEPHeader::N_SUBBANDS) {
-					logMessage(cerr,formatString("Error: argument to --xcsubband out of range, value must be >= 0 and < %d",MEPHeader::N_SUBBANDS));
+				if (subband < 0 || subband >= MAX_SUBBANDS) {
+					logMessage(cerr,formatString("Error: argument to --xcsubband out of range, value must be >= 0 and < %d",MAX_SUBBANDS));
 					exit(EXIT_FAILURE);
 				}
 
 				list<int> subbandlist;
-				for (int rcu = 0; rcu < m_nrcus / MEPHeader::N_POL; rcu++) {
+				for (int rcu = 0; rcu < m_nrcus / N_POL; rcu++) {
 					subbandlist.push_back(subband);
 				}
 				subbandscommand->setSubbandList(subbandlist);
@@ -3493,7 +3610,7 @@ Command* RSPCtl::parse_options(int argc, char** argv)
 		}
 		break;
 
-		case 'T': // --tbbmode
+		case 'T': // --tbbmode  .
 		{
 			if (command)
 				delete command;
@@ -3512,7 +3629,7 @@ Command* RSPCtl::parse_options(int argc, char** argv)
 					char* liststring = strchr(optarg, ',');
 					liststring++; // skip the ,
 					if (liststring && *liststring) {
-						list<int> subbandlist = strtolist(liststring, MEPHeader::N_SUBBANDS);
+						list<int> subbandlist = strtolist(liststring, MAX_SUBBANDS);
 						if (subbandlist.empty()) {
 							logMessage(cerr,"Error: missing or invalid subband set '--tbbmode=subbands' option");
 							exit(EXIT_FAILURE);
diff --git a/MAC/APL/PIC/RSP_Driver/src/rspctl.h b/MAC/APL/PIC/RSP_Driver/src/rspctl.h
index b2d990a985a..768e7a51899 100644
--- a/MAC/APL/PIC/RSP_Driver/src/rspctl.h
+++ b/MAC/APL/PIC/RSP_Driver/src/rspctl.h
@@ -27,6 +27,7 @@
 
 #include <Common/lofar_bitset.h>
 #include <Common/lofar_list.h>
+#include <Common/LofarConstants.h>
 
 #include <APL/RSP_Protocol/RSP_Protocol.ph>
 #include <APL/RSP_Protocol/EPA_Protocol.ph>
@@ -73,8 +74,8 @@ public:
 	}
 
 	// Get the mask (MAX_N_RCUS bits).
-	bitset<MEPHeader::MAX_N_RCUS> getRCUMask() const {
-		bitset<MEPHeader::MAX_N_RCUS> mask;
+	bitset<MAX_RCUS> getRCUMask() const {
+		bitset<MAX_RCUS> mask;
 
 		mask.reset();
 		std::list<int>::const_iterator it;
@@ -82,7 +83,7 @@ public:
 		for (it = m_select.begin(); it != m_select.end(); ++it, ++count) {
 			if (count >= get_ndevices())
 				break;
-			if (*it < MEPHeader::MAX_N_RCUS)
+			if (*it < MAX_RCUS)
 				mask.set(*it);
 		}
 		return mask;
@@ -105,20 +106,34 @@ public:
 	}
 
 	// Get the mask (N_BEAMLETS bits).
-	bitset<MEPHeader::N_BEAMLETS> getBEAMLETSMask() const {
-		bitset<MEPHeader::N_BEAMLETS> mask;
+	bitset<MAX_BEAMLETS> getBEAMLETSMask() const {
+		bitset<MAX_BEAMLETS> mask;
 
 		mask.reset();
 		std::list<int>::const_iterator it;
 		for (it = m_beamlets.begin(); it != m_beamlets.end(); ++it) {
-			if (*it < MEPHeader::N_BEAMLETS)
+			if (*it < MAX_BEAMLETS)
 				mask.set(*it);
 		}
 		return mask;
 	}
 
+    // Get the mask (MAX_N_RCUS/N_POL bits).
+	bitset<MAX_ANTENNAS> getANTENNAMask() const {
+		bitset<MAX_ANTENNAS> mask;
+
+		mask.reset();
+		std::list<int>::const_iterator it;
+		for (it = m_select.begin(); it != m_select.end(); ++it) {
+			if (*it < MAX_ANTENNAS)
+				mask.set(*it);
+		}
+		return mask;
+	}
+
+
 	// Distill two rectdomains from the selection list
-	bool getRSPRange2(blitz::Range& r1, blitz::Range& r2, int n_blps = MEPHeader::N_BLPS) const {
+	bool getRSPRange2(blitz::Range& r1, blitz::Range& r2, int n_blps = NR_BLPS_PER_RSPBOARD) const {
 		blitz::TinyVector<int, 2> lowerbounds(0,0), upperbounds(0,0);
 		std::list<int> select = m_select;
 
@@ -268,6 +283,30 @@ private:
 	std::list<int> 		m_delaylist;
 };
 
+
+//
+// class SWAPXYCommand
+//
+class SWAPXYCommand : public Command
+{
+public:
+	SWAPXYCommand(GCFPortInterface& port);
+	virtual ~SWAPXYCommand() {}
+	virtual void send();
+	virtual GCFEvent::TResult ack(GCFEvent& e);
+	void setSwapXY(bool swapxy) {
+		itsSwapXY = swapxy;
+	}
+	bool getSwapXY() {
+		return(itsSwapXY);
+	}
+private:
+	bool    itsSwapXY;
+};
+
+
+
+
 //
 // class RSUCommand
 //
@@ -715,6 +754,7 @@ private:
 	int 			m_nrcus;
 	int 			m_nrspboards;
 	int 			m_maxrspboards;
+	int             itsNantennas;
 
 	// commandline parameters
 	int    			m_argc;
diff --git a/MAC/APL/PIC/RSP_Protocol/src/RSP_Protocol.prot b/MAC/APL/PIC/RSP_Protocol/src/RSP_Protocol.prot
index f13b30482c8..0b8d64167e6 100644
--- a/MAC/APL/PIC/RSP_Protocol/src/RSP_Protocol.prot
+++ b/MAC/APL/PIC/RSP_Protocol/src/RSP_Protocol.prot
@@ -587,6 +587,69 @@ event = {
   };
 };
 
+event = {
+  signal = SETSWAPXY;
+  dir = IN;
+  param = {
+    name = "timestamp";
+    type = "RTC::Timestamp";
+    userdefined;
+  };
+  param = {
+    name = "antennamask";
+    type = "bitset<MEPHeader::MAX_N_RCUS/MEPHeader::N_POL>";
+  };
+  param = {
+    name = "swapxy";
+    type = "bool";
+  };
+};
+
+event = {
+  signal = SETSWAPXYACK;
+  dir = OUT;
+  param = {
+    name = "timestamp";
+    type = "RTC::Timestamp";
+    userdefined;
+  };
+  param = {
+    name = "status";
+    type = "int16";
+  };
+};
+event = {
+  signal = GETSWAPXY;
+  dir = IN;
+  param = {
+    name = "timestamp";
+    type = "RTC::Timestamp";
+    userdefined;
+  };
+  param = {
+    name = "cache";
+    type = "uint8";
+  };
+};
+
+event = {
+  signal = GETSWAPXYACK;
+  dir = OUT;
+  param = {
+    name = "timestamp";
+    type = "RTC::Timestamp";
+    userdefined;
+  };
+  param = {
+    name = "status";
+    type = "int16";
+  };
+  param = {
+    name = "antennamask";
+    type = "bitset<MEPHeader::MAX_N_RCUS/MEPHeader::N_POL>";
+  };
+};
+
 //
 // RSU Control
 //
diff --git a/MAC/APL/RTCCommon/include/APL/RTCCommon/CMakeLists.txt b/MAC/APL/RTCCommon/include/APL/RTCCommon/CMakeLists.txt
index a5dbaf0aad8..a9571bdbd41 100644
--- a/MAC/APL/RTCCommon/include/APL/RTCCommon/CMakeLists.txt
+++ b/MAC/APL/RTCCommon/include/APL/RTCCommon/CMakeLists.txt
@@ -6,7 +6,6 @@ set(inst_HEADERS
   MarshallBlitz.h
   Observer.h
   PSAccess.h
-  ResourceCache.h
   Subject.h
   TestSuite.h
   Timestamp.h
diff --git a/MAC/APL/StationCU/src/TBBControl/TBBControlMain.cc b/MAC/APL/StationCU/src/TBBControl/TBBControlMain.cc
index f0d63cd4df1..18fd7601624 100644
--- a/MAC/APL/StationCU/src/TBBControl/TBBControlMain.cc
+++ b/MAC/APL/StationCU/src/TBBControl/TBBControlMain.cc
@@ -32,6 +32,7 @@ int main(int argc, char* argv[])
 {
 	// args: cntlrname, parentHost, parentService
 	GCFScheduler::instance()->init(argc, argv, argv[0]);
+	GCFScheduler::instance()->disableQueue();  // run as fast as possible
 
 	ParentControl*	pc = ParentControl::instance();
 	pc->start();	// make initial transition
-- 
GitLab