diff --git a/MAC/APL/PIC/TBBDriver/src/AllocCmd.cc b/MAC/APL/PIC/TBBDriver/src/AllocCmd.cc
index 638b671db1dbe9e8b1d1ec8cfcaa382678f38e1f..07c6a69ccd3e95aeeaaf9893c489957985d5bcc2 100644
--- a/MAC/APL/PIC/TBBDriver/src/AllocCmd.cc
+++ b/MAC/APL/PIC/TBBDriver/src/AllocCmd.cc
@@ -25,28 +25,27 @@
 #include <Common/LofarLogger.h>
 
 #include "AllocCmd.h"
-#include "DriverSettings.h"
 
+using namespace LOFAR;
+using namespace TBB_Protocol;
+using namespace TP_Protocol;
+using namespace TBB;
 
-namespace LOFAR {
-	using namespace TBB_Protocol;
-	using namespace TP_Protocol;
-	namespace TBB {
-
+	
 //--Constructors for a AllocCmd object.----------------------------------------
-AllocCmd::AllocCmd():
-		itsBoardMask(0),itsBoardsMask(0),itsChannel(0)
+AllocCmd::AllocCmd(): itsStage(0),itsRcuStatus(0)
 {
+	TS					= TbbSettings::instance();
 	itsTPE 			= new TPAllocEvent();
 	itsTPackE 	= 0;
 	itsTBBE 		= 0;
 	itsTBBackE	= new TBBAllocackEvent();
 	
-	for(int boardnr = 0;boardnr < DriverSettings::instance()->maxBoards();boardnr++) { 
-		itsTBBackE->status[boardnr]	= 0;
+	for(int boardnr = 0;boardnr < TS->maxBoards();boardnr++) { 
+		itsTBBackE->status_mask[boardnr]	= 0;
 		itsChannelMask[boardnr]	= 0;
 	}
-	LOG_DEBUG_STR(formatString("AllocCmd construct"));
+	setWaitAck(true);
 }
 	  
 //--Destructor for AllocCmd.---------------------------------------------------
@@ -59,7 +58,9 @@ AllocCmd::~AllocCmd()
 // ----------------------------------------------------------------------------
 bool AllocCmd::isValid(GCFEvent& event)
 {
-	if ((event.signal == TBB_ALLOC)||(event.signal == TP_ALLOCACK)) {
+	if ((event.signal == TBB_ALLOC)
+		|| (event.signal == TP_ALLOCACK)
+		|| (event.signal == TP_SIZEACK)) {
 		return(true);
 	}
 	return(false);
@@ -68,144 +69,203 @@ bool AllocCmd::isValid(GCFEvent& event)
 // ----------------------------------------------------------------------------
 void AllocCmd::saveTbbEvent(GCFEvent& event)
 {
-	LOG_DEBUG_STR(formatString("AllocCmd savetbb"));
 	itsTBBE	= new TBBAllocEvent(event);
 	
-	// mask for the installed boards
-	itsBoardsMask = DriverSettings::instance()->activeBoardsMask();
-		
-	for (int boardnr = 0; boardnr < DriverSettings::instance()->maxBoards(); boardnr++) {
-		//
-		if (!(itsBoardsMask & (1 << boardnr))) 
-			itsTBBackE->status[boardnr] |= NO_BOARD;
-		
-		itsChannelMask[boardnr] = itsTBBE->channelmask[boardnr];
-		
-		for (int ch = 0; ch < 16; ch++) {
-			if (itsChannelMask[boardnr] & (1 << ch)) {
-				if (DriverSettings::instance()->getChStatus((ch + (boardnr * 16))) != 'F') {
-					itsTBBackE->status[boardnr] |= ALLOC_ERROR;
-				}		
-				else	
-					DriverSettings::instance()->setChSelected((ch + (boardnr * 16)),true);
-			}
-		} 		
+	// convert rcu-bitmask to tbb-channelmask
+	int32 board;
+	int32 channel;
+	for (int rcunr = 0; rcunr < TS->maxChannels(); rcunr++) {
+		if(itsTBBE->rcu_mask.test(rcunr)) {
+			TS->convertRcu2Ch(rcunr,&board,&channel);	
+			itsChannelMask[board] |= (1 << channel);
+		}
+	} 
+	
+	uint32 boardmask = 0;	
+	for (int boardnr = 0; boardnr < TS->maxBoards(); boardnr++) {
+		if (itsChannelMask[board] != 0) boardmask |= (1 << boardnr); 
 		
-		if (itsChannelMask[boardnr] != 0)
-			itsBoardMask |= (1 << boardnr);
+		if (TS->isBoardActive(boardnr)) {
 			
-		if ((itsChannelMask[boardnr] & ~0xFFFF) != 0) 
-			itsTBBackE->status[boardnr] |= (SELECT_ERROR | CHANNEL_SEL_ERROR);
-				
-		if (!(itsBoardsMask & (1 << boardnr)) &&  (itsChannelMask[boardnr] != 0))
-			itsTBBackE->status[boardnr] |= (SELECT_ERROR | BOARD_SEL_ERROR);
+			if ((itsChannelMask[boardnr] & ~0xFFFF) != 0) 
+				itsTBBackE->status_mask[boardnr] |= (TBB_SELECT_ERROR | TBB_CHANNEL_SEL_ERROR);	
+			
+			for (int ch = 0; ch < 16; ch++) {
+				if (itsChannelMask[boardnr] & (1 << ch)) {
+					if (TS->getChState((ch + (boardnr * 16))) != 'F') {
+						itsTBBackE->status_mask[boardnr] |= TBB_ALLOC_ERROR;
+					}	else {	
+						TS->setChSelected((ch + (boardnr * 16)),true);
+						LOG_DEBUG_STR(formatString("Ch[%d] is selected",ch + (boardnr * 16)));
+					}
+				}
+			} 		
+		} else {
+			itsTBBackE->status_mask[boardnr] |= TBB_NO_BOARD;
+		}
 		
-		if ((itsBoardsMask & (1 << boardnr)) &&  (itsChannelMask[boardnr] != 0)) {
-			if (!devideChannels(boardnr)) // calculate allocations
-				itsTBBackE->status[boardnr] |= ALLOC_ERROR;
-		}	
-		LOG_DEBUG_STR(formatString("AllocCmd savetbb bnr[%d], status[0x%08X]",boardnr,itsTBBackE->status[boardnr]));
+		if (itsTBBackE->status_mask[boardnr] != 0) {
+			LOG_DEBUG_STR(formatString("AllocCmd savetbb bnr[%d], status[0x%08X], channelmask[%08X]",
+														boardnr, itsTBBackE->status_mask[boardnr], itsChannelMask[boardnr]));
+		}
 	}
+	
+	setBoardMask(boardmask);
 		
-	// Send only commands to boards installed
-	itsBoardMask = itsBoardMask & itsBoardsMask;
+	// select first board to handle
+	nextBoardNr();
 	
 	// initialize TP send frame
 	itsTPE->opcode			= TPALLOC;
 	itsTPE->status			=	0;
 		
 	delete itsTBBE;	
-	LOG_DEBUG_STR(formatString("AllocCmd savetbb done"));
 }
 
 // ----------------------------------------------------------------------------
-bool AllocCmd::sendTpEvent(int32 boardnr, int32 channelnr)
+void AllocCmd::sendTpEvent()
 {
-	bool sending = false;
-	DriverSettings*		ds = DriverSettings::instance();
-	
-	// fill in calculated allocations
-	itsTPE->channel = ds->getChInputNr(channelnr);
-	itsTPE->pageaddr = ds->getChStartAddr(channelnr);
-	itsTPE->pagelength =	ds->getChPageSize(channelnr);
-	itsChannel = channelnr; // set active channel
+	if (itsTBBackE->status_mask[getBoardNr()] == 0) {
 	
-	// send cmd if no errors
-	if 	(ds->boardPort(boardnr).isConnected() &&
-			(itsTBBackE->status[boardnr] == 0) && 
-			(ds->getChStatus(channelnr) == 'F')) {
+		switch (itsStage) {
+			// stage 1, get board memory size
+			case 0: {
+				TPSizeEvent *sizeEvent = new TPSizeEvent();
+				sizeEvent->opcode	= TPSIZE;
+				sizeEvent->status	=	0;
+				TS->boardPort(getBoardNr()).send(*sizeEvent);
+				delete sizeEvent;
+			} break;
+			
+			// stage 2, allocate memory
+			case 1: {
+				itsRcuStatus = 0;
+				
+				// fill in calculated allocations
+				itsTPE->channel = TS->getChInputNr(getChannelNr());
+				itsTPE->pageaddr = TS->getChStartAddr(getChannelNr());
+				itsTPE->pagelength = TS->getChPageSize(getChannelNr());
 		
-		ds->boardPort(boardnr).send(*itsTPE);
-		ds->boardPort(boardnr).setTimer(ds->timeout());
-		sending = true;
-		LOG_DEBUG_STR(formatString("Sending Alloc to boardnr[%d], channel[%d]", 
-																boardnr,channelnr));
-	}
-	else 
-		itsTBBackE->status[boardnr] |= CMD_ERROR;
-	
-	return(sending);
+				if (TS->getChState(getChannelNr()) != 'F')
+					itsRcuStatus |= TBB_RCU_NOT_FREE;
+		
+				// send cmd if no errors
+				if (itsRcuStatus == 0) {
+					TS->boardPort(getBoardNr()).send(*itsTPE);
+					LOG_DEBUG_STR(formatString("Sending Alloc to boardnr[%d], channel[%d]",getBoardNr(),getChannelNr()));
+				}
+			} break;
+			
+			default: {
+			} break;
+		}
+	}	
+	TS->boardPort(getBoardNr()).setTimer(TS->timeout());
 }
 
 // ----------------------------------------------------------------------------
-void AllocCmd::saveTpAckEvent(GCFEvent& event, int32 boardnr)
+void AllocCmd::saveTpAckEvent(GCFEvent& event)
 {
-	// in case of a time-out, set error mask
-	if (event.signal == F_TIMER) {
-		itsTBBackE->status[boardnr] |= COMM_ERROR;
-	}
-	else {
-		itsTPackE = new TPAllocackEvent(event);
+	switch (itsStage) {
+		// stage 1, get board memory size
+		case 0: {
+			// in case of a time-out, set error mask
+			if (event.signal == F_TIMER) {
+				itsTBBackE->status_mask[getBoardNr()] |= TBB_COMM_ERROR;
+			}	else {
+				TPSizeackEvent *sizeAckEvent = new TPSizeackEvent(event);
 		
-		if ((itsTPackE->status > 0x0) && (itsTPackE->status < 0x6)) 
-			itsTBBackE->status[boardnr] |= (1 << (23 + itsTPackE->status));
+				if ((sizeAckEvent->status >= 0xF0) && (sizeAckEvent->status <= 0xF6)) 
+					itsTBBackE->status_mask[getBoardNr()] |= (1 << (16 + (sizeAckEvent->status & 0x0F)));	
 		
-		if ((itsTPackE->status >= 0xF0) && (itsTPackE->status <= 0xF6)) 
-			itsTBBackE->status[boardnr] |= (1 << (16 + (itsTPackE->status & 0x0F)));	
+				TS->setMemorySize(getBoardNr(),sizeAckEvent->npages);
+				
+				if (!devideChannels(getBoardNr())) // calculate allocations
+					itsTBBackE->status_mask[getBoardNr()] |= TBB_ALLOC_ERROR;
+				
+				LOG_DEBUG_STR(formatString("Alloc-sizecmd: board[%d] status[0x%08X] pages[%u]", 
+											getBoardNr(), sizeAckEvent->status, sizeAckEvent->npages));
+				delete sizeAckEvent;
+			}
+			nextBoardNr();
 			
-		if(itsTPackE->status == 0) 
-			DriverSettings::instance()->setChStatus(itsChannel, 'A'); 	 
+			if (isDone()) {
+				setDone(false);
+				resetChannelNr(); 
+				nextChannelNr();
+				itsStage = 1;
+			}
+		} break;
+		
+		// stage 2, allocate memory
+		case 1: {
+			// in case of a time-out, set status mask
+			if (event.signal == F_TIMER) {
+				itsTBBackE->status_mask[getBoardNr()] |= TBB_RCU_COMM_ERROR;
+				itsRcuStatus |= TBB_TIMEOUT_ETH;
+				LOG_INFO_STR(formatString("F_TIMER AllocCmd DriverStatus[0x%08X], RcuStatus[0x%08X]",
+										 itsTBBackE->status_mask[getBoardNr()],itsRcuStatus));
+			}	else {
+				itsTPackE = new TPAllocackEvent(event);
+				
+				if (itsTPackE->status == 0) {
+					TS->setChState(getChannelNr(),'A');
+					//LOG_DEBUG_STR(formatString("channel %d is set to %c(A)",getChannelNr(),TS->getChState(getChannelNr())));
+				} else {
+					if ((itsTPackE->status > 0x0) && (itsTPackE->status < 0x6)) 
+						itsRcuStatus |= (1 << (23 + itsTPackE->status));
+		
+					if ((itsTPackE->status >= 0xF0) && (itsTPackE->status <= 0xF6)) 
+						itsRcuStatus |= (1 << (16 + (itsTPackE->status & 0x0F)));	
+				}	
 		
-		LOG_DEBUG_STR(formatString("Received AllocAck from boardnr[%d], status[0x%08X]", 
-																boardnr,itsTBBackE->status[boardnr]));
-		delete itsTPackE;
+				LOG_DEBUG_STR(formatString("Received AllocAck from boardnr[%d], status[0x%08X]", 
+											getBoardNr(),itsTPackE->status));
+				
+				delete itsTPackE;
+			}
+	
+			if (itsRcuStatus) TS->setChState(getChannelNr(), 'E');
+			TS->setChStatus(getChannelNr(),(uint16)(itsRcuStatus >> 16));
+	
+			if (itsRcuStatus || itsTBBackE->status_mask[getBoardNr()]) {
+				int32 rcu;
+				TS->convertCh2Rcu(getChannelNr(),&rcu);
+				LOG_INFO_STR(formatString("ERROR AllocCmd Rcu[%d], DriverStatus[0x%x], RcuStatus[0x%x]",
+										 rcu, itsTBBackE->status_mask[getBoardNr()],itsRcuStatus));
+			}
+	
+			itsTBBackE->status_mask[getBoardNr()] |= itsRcuStatus;
+			nextChannelNr();
+		} break;
+		
+		default: {
+		} break;
 	}
 }
+	
 
 // ----------------------------------------------------------------------------
 void AllocCmd::sendTbbAckEvent(GCFPortInterface* clientport)
 {
-	for (int32 boardnr = 0; boardnr < DriverSettings::instance()->maxBoards(); boardnr++) { 
-		if (itsTBBackE->status[boardnr] == 0)
-			itsTBBackE->status[boardnr] = SUCCESS;
-		//LOG_DEBUG_STR(formatString("AllocCmd sendtbb bnr[%d]st[0x%08X]",boardnr,itsTBBackE->status[boardnr]));
+	int32 rcunr;
+	
+	itsTBBackE->rcu_mask.reset();
+	for (int32 channelnr = 0; channelnr < TS->maxChannels(); channelnr++) {
+		if (TS->getChStatus(channelnr)) {
+			TS->convertCh2Rcu(channelnr,&rcunr);
+			itsTBBackE->rcu_mask.set(rcunr);
+		}
+		//LOG_DEBUG_STR(formatString("channel %d is set to %c",channelnr,TS->getChState(channelnr)));
+	}
+	
+	for (int32 boardnr = 0; boardnr < TS->maxBoards(); boardnr++) { 
+		if (itsTBBackE->status_mask[boardnr] == 0)
+			itsTBBackE->status_mask[boardnr] = TBB_SUCCESS;
 	}
 	
 	clientport->send(*itsTBBackE);
-}
-
-// ----------------------------------------------------------------------------
-uint32 AllocCmd::getBoardMask()
-{
-	return(itsBoardMask);
-}
-
-// ----------------------------------------------------------------------------
-uint32 AllocCmd::getChannelMask(int32 boardnr)
-{
-	return(itsChannelMask[boardnr]);
-}
-
-// ----------------------------------------------------------------------------
-bool AllocCmd::waitAck()
-{
-	return(true);
-}
-
-// ----------------------------------------------------------------------------
-CmdTypes AllocCmd::getCmdType()
-{
-	return(ChannelCmd);
+	
 }
 
 // ----------------------------------------------------------------------------
@@ -221,154 +281,127 @@ uint32 getNrOfBits(uint32 mask)
 // ----------------------------------------------------------------------------
 bool AllocCmd::devideChannels(int32 boardnr)
 {
-	bool board_free = true;
+	struct sMP {
+		uint32 addr;
+		uint32 channels;
+		uint32 usedSize;
+	};
+	
+	// for 400 MHz mode there is only one ring, for 800 MHz there are 2 rings
+	uint32 rings = 1; // usefull rings for dataflow between MP's
 	bool success = false;
-	uint32 channels;
-	uint32 memorysize;
-	uint32 channelsize;
-	uint32 channeladdr[16];
-	uint32 channelmask;
-	uint32 addr;
-	uint32 mp0ch;
-	uint32 mp1ch;
-	uint32 mp2ch;
-	uint32 mp3ch;
+	uint32 totalChannels;
+	uint32 totalMemorySize;
+	uint32 mpMemorySize;
+	uint32 channelMemorySize;
+	uint32 channelAddr[16];
+	uint32 channelMask;
+	sMP		mp[4];
 		
-	channelmask = itsChannelMask[boardnr];
-	memorysize = DriverSettings::instance()->getMemorySize(boardnr);
-	channels = getNrOfBits(channelmask);
-	channelsize = memorysize / channels;
-	mp0ch = getNrOfBits((itsChannelMask[boardnr] & 0x000F));
-	mp1ch = getNrOfBits((itsChannelMask[boardnr] & 0x00F0));
-	mp2ch = getNrOfBits((itsChannelMask[boardnr] & 0x0F00));
-	mp3ch = getNrOfBits((itsChannelMask[boardnr] & 0xF000));
-	addr = 0;
-	
+	channelMask = itsChannelMask[boardnr];
+	totalMemorySize = TS->getMemorySize(boardnr);
+	mpMemorySize = totalMemorySize / 4;
+	totalChannels = getNrOfBits(channelMask);
+
+	if (totalMemorySize == 0) return (false);
+		
+	// check if all board inputs are free, if not exit
+	for (int32 ch = 0; ch < TS->nrChannelsOnBoard(); ch++) {
+		if (TS->getChState(ch + (boardnr * 16)) != 'F')
+			return (false);
+	}
+
 	
-	// check if all board inputs are free
-	for (int32 ch = 0; ch < DriverSettings::instance()->nrChannelsPerBoard(); ch++) {
-		if (DriverSettings::instance()->getChStatus(ch + (boardnr * 16)) != 'F')
-			board_free = false;
+	// setup mp struct
+	for (int i = 0; i < 4; i++) {
+		mp[i].addr = i * mpMemorySize;
+		uint32 mpChannelMask = itsChannelMask[boardnr] & (0x000F << (i * 4));
+		mp[i].channels = getNrOfBits(mpChannelMask);
+		mp[i].usedSize = 0;
 	}
+
 	
-	if (board_free) {
-	success = true;
-	switch (channels) {
-		case 1: {
-			
-			for (int32 ch = 0; ch < 16; ch++) {
-				if (itsChannelMask[boardnr] & (1 << ch)) {
-					channeladdr[ch] = addr;
-					addr += channelsize;
-				}
-			}			
+	// check if channel request is valid
+	switch (totalChannels) {
+		case 1:
+		case 2:
+		case 16: 
+		{
+			success = true;
 		} break;
 		
-		case 2: {
-			for (int32 ch = 0; ch < 16; ch++) {
-				if (itsChannelMask[boardnr] & (1 << ch)) {
-					channeladdr[ch] = addr;
-					addr += channelsize;
-				}
+		case 4:
+		case 8:
+		{
+			if ((mp[0].channels <= 2) ||
+					(mp[1].channels <= 2) || 
+					(mp[2].channels <= 2) || 
+					(mp[3].channels <= 2)) {
+				success = true;
 			}
 		} break;
-		
-		case 4: {
-			//only 2 memory lane's, max 2 channels per Mp
-			if ((mp0ch > 2) || (mp1ch > 2) || (mp2ch > 2) || (mp3ch > 2)) {
-				success = false;
-				break;
-			}
-							
-			if (((mp0ch == 2) && (mp1ch == 2)) || ((mp2ch == 2) && (mp3ch == 2)) ||
-				   (mp0ch == 1) || (mp1ch == 1) || (mp2ch = 1) || (mp3ch == 1)){
-				// divide order mp0;mp1;mp0;mp1 || mp2;mp3;mp2;mp3 enz.
-				while (channelmask) {
-					for (int32 ch = 0; ch < 4; ch++) {
-						if (channelmask & (1 << ch)) {
-							channelmask &= ~(1 << ch);
-							channeladdr[ch] = addr;
-							addr += channelsize;
-							ch = 4; // break;								
-						}
-					}
-					for (int32 ch = 4; ch < 8; ch++) {
-						if (channelmask & (1 << ch)) {
-							channelmask &= ~(1 << ch);
-							channeladdr[ch] = addr;
-							addr += channelsize;
-							ch = 8;	// break;							
-						}
-					}
-					for (int32 ch = 8; ch < 12; ch++) {
-						if (channelmask & (1 << ch)) {
-							channelmask &= ~(1 << ch);
-							channeladdr[ch] = addr;
-							addr += channelsize;
-							ch = 12;	// break;							
-						}
-					}
-					for (int32 ch = 12; ch < 16; ch++) {
-						if (channelmask & (1 << ch)) {
-							channelmask &= ~(1 << ch);
-							channeladdr[ch] = addr;
-							addr += channelsize;
-							ch = 16;	// break;							
-						}
-					}
-				}
-			}
-			else {
-				// divide order firt mp; second mp	
-				for (int32 ch = 0; ch < 16; ch++) {
-					if (itsChannelMask[boardnr] & (1 << ch)) {
-						channeladdr[ch] = addr;
-						addr += channelsize;
-					}
-				}
+	
+		default : {
+			success = false;
+		} break;
+	}
+	// if not a valid request exit
+	if (!success) return (false);		
+
+
+	// calculate channelsize
+	switch (totalChannels) {
+		case 2: {
+			
+			if (rings == 2) {
+				channelMemorySize = totalMemorySize / 2;
+			} else {
+				channelMemorySize = totalMemorySize / 4; 
 			}
 		} break;
 		
-		case 8: {
-			if ((mp0ch > 2) || (mp1ch > 2) || (mp2ch > 2) || (mp3ch > 2)) {
-				success = false;
-				break;
-			}
-			for (int32 ch = 0; ch < 16; ch++) {
-				if (itsChannelMask[boardnr] & (1 << ch)) {
-					channeladdr[ch] = addr;
-					addr += channelsize;
-				}
+		case 4: {
+			if ((rings == 2) ||
+					(mp[0].channels == 1) || 
+					(mp[1].channels == 1) || 
+					(mp[2].channels == 1) || 
+					(mp[3].channels == 1)) {
+				channelMemorySize = totalMemorySize / 4;
+			} else {
+				channelMemorySize = totalMemorySize / 8; 
 			}
 		} break;
-		
+
+		case 1:
+		case 8:
 		case 16: {
-			for (int32 ch = 0; ch < 16; ch++) {
-				if (itsChannelMask[boardnr] & (1 << ch)) {
-					channeladdr[ch] = addr;
-					addr += channelsize;
-				}
-			}
+			channelMemorySize = totalMemorySize / totalChannels;
 		} break;
 		
 		default: {
-			success = false;
 		}	break;
 	}
 	
-	if (success) {	// save to DriverSettings
-		for (int32 ch = 0; ch < 16; ch++) {
-			if (DriverSettings::instance()->getChSelected(ch + (boardnr * 16))) {
-				DriverSettings::instance()->setChStartAddr((ch + (boardnr * 16)), channeladdr[ch]);
-				DriverSettings::instance()->setChPageSize((ch + (boardnr * 16)), channelsize);		
+	uint32 mpNr;
+	for (int32 ch = 0; ch < 16; ch++) {
+		if (itsChannelMask[boardnr] & (1 << ch)) {
+			mpNr = ch / 4;
+			while (mp[mpNr].usedSize == mpMemorySize) {
+				mpNr += rings;
+				if (mpNr >= 4) mpNr -= 4;
 			}
+			channelAddr[ch] = mp[mpNr].addr + mp[mpNr].usedSize;
+			mp[mpNr].usedSize += channelMemorySize;
 		}
-	}
+	}	
+	    	
+	for (int32 ch = 0; ch < 16; ch++) {
+		if (TS->isChSelected(ch + (boardnr * 16))) {
+			TS->setChStartAddr((ch + (boardnr * 16)), channelAddr[ch]);
+			TS->setChPageSize((ch + (boardnr * 16)), channelMemorySize);		
+		}
+		//LOG_DEBUG_STR(formatString("channel %d = addr[%d] size[%d]",ch,channelAddr[ch],channelMemorySize));
 	}
 	
-	return(success);
+	return(true);
 }
-
-
-	} // end TBB namespace
-} // end LOFAR namespace
diff --git a/MAC/APL/PIC/TBBDriver/src/AllocCmd.h b/MAC/APL/PIC/TBBDriver/src/AllocCmd.h
index e704e9e48c1aa7e7eeb2d75d1b89db923a83f7d9..e5b4215346ed98f5e1ffc44a27dca7e0cb165720 100644
--- a/MAC/APL/PIC/TBBDriver/src/AllocCmd.h
+++ b/MAC/APL/PIC/TBBDriver/src/AllocCmd.h
@@ -32,7 +32,7 @@
 #include "TP_Protocol.ph"
 
 #include "Command.h"
-
+#include "DriverSettings.h"
 
 namespace LOFAR {
 	using namespace TBB_Protocol;
@@ -51,27 +51,20 @@ namespace LOFAR {
 				
 				virtual void saveTbbEvent(GCFEvent& event);
 									
-				virtual bool sendTpEvent(int32 boardnr, int32 channelnr);
+				virtual void sendTpEvent();
 
-				virtual void saveTpAckEvent(GCFEvent& event, int32 boardnr);
+				virtual void saveTpAckEvent(GCFEvent& event);
 
 				virtual void sendTbbAckEvent(GCFPortInterface* clientport);
 				
-				virtual uint32 getBoardMask();
-				
-				virtual uint32 getChannelMask(int32 boardnr);
-				
-				virtual bool waitAck();
-				
-				virtual CmdTypes getCmdType();
-				
-								      
 			private:
 				bool devideChannels(int32 boardnr);
+								
+				TbbSettings *TS;
 				
-				uint32	itsBoardMask;  // mask indicates the boards to communicate with
-				uint32	itsBoardsMask;	// Installed boards mask
-				int32		itsChannel;
+				int32		itsStage;
+				//uint32	itsBoardMask;  // mask indicates the boards to communicate with
+				uint32	itsRcuStatus;
 				uint32	itsChannelMask[MAX_N_TBBBOARDS];
 								
 				TPAllocEvent			*itsTPE;
diff --git a/MAC/APL/PIC/TBBDriver/src/BoardCmdHandler.cc b/MAC/APL/PIC/TBBDriver/src/BoardCmdHandler.cc
index b9d2b1aa42eaeb7049997386028c139d4a42ab64..6a34ffd101eb6c6cc8e72ce7fcf4d9081264d068 100644
--- a/MAC/APL/PIC/TBBDriver/src/BoardCmdHandler.cc
+++ b/MAC/APL/PIC/TBBDriver/src/BoardCmdHandler.cc
@@ -25,92 +25,117 @@
 
 #include <APL/TBB_Protocol/TBB_Protocol.ph>
 #include "BoardCmdHandler.h"
-#include "DriverSettings.h"
 
-namespace LOFAR {
-	using namespace TBB_Protocol;
-	namespace TBB {
+using namespace LOFAR;
+using namespace TBB_Protocol;
+using	namespace TBB;
 
 BoardCmdHandler::BoardCmdHandler()
-  : GCFFsm((State)&BoardCmdHandler::send_state)
-{
-	itsMaxRetries = 10;
+  : GCFFsm((State)&BoardCmdHandler::idle_state)
+{		
+	TS	= TbbSettings::instance();
+	itsDone = true;
 	itsRetries = 0;
-	itsNrOfBoards	= 0;
-	itsNrOfChannels = 0;
-	itsCmdType = BoardCmd;
-	itsBoardNr = 0;
-	itsChannelNr = 0;
-	itsNextCmd = false;
 	itsClientPort	= 0;
 	itsCmd = 0;		
 }
 
 BoardCmdHandler::~BoardCmdHandler() {  }
 
-GCFEvent::TResult BoardCmdHandler::send_state(GCFEvent& event, GCFPortInterface& port)
+
+GCFEvent::TResult BoardCmdHandler::idle_state(GCFEvent& event, GCFPortInterface& port)
 {
   GCFEvent::TResult status = GCFEvent::HANDLED;
-				
   switch (event.signal)	{
   	
   	case F_INIT: {
   	} break;
   	
   	case F_ENTRY: {
-			if (itsCmd) {
-				sendCmd(); 
-				TRAN(BoardCmdHandler::waitack_state);
-			}
+			itsCmd = 0;
 		} break;			
 	  
+	  case F_TIMER: {
+	  } break;
+	  	
     case F_EXIT: {
   	} break;
 
 		default: {
-			
 			if (itsCmd && itsCmd->isValid(event)) { // isValid returns true if event is a valid cmd
+				LOG_DEBUG_STR("==== NEW CMD ==================================================");
 				itsClientPort = &port;
+				itsDone = false;
 				itsCmd->saveTbbEvent(event);
-				sendCmd();
-				TRAN(BoardCmdHandler::waitack_state);
-			}
-			else {
+				TRAN(BoardCmdHandler::send_state);
+			}	else {
 				status = GCFEvent::NOT_HANDLED;
 			}
     } break;
 	}
 	return(status);
 }
+
+GCFEvent::TResult BoardCmdHandler::send_state(GCFEvent& event, GCFPortInterface& /*port*/)
+{
+  GCFEvent::TResult status = GCFEvent::HANDLED;
+	switch (event.signal)	{
+  	
+  	case F_INIT: {
+  	} break;
+  	
+  	case F_ENTRY: {
+			if (itsCmd != 0) {
+				if (itsCmd->isDone()) {
+					itsDone = true;
+					itsCmd->sendTbbAckEvent(itsClientPort);
+					TRAN(BoardCmdHandler::idle_state);
+				} else {
+					itsRetries = 0;
+					itsCmd->sendTpEvent();
+					TRAN(BoardCmdHandler::waitack_state);
+				}
+			}
+		} break;
+		
+		case F_TIMER: {
+	  } break;			
+	  
+    case F_EXIT: {
+  	} break;
+
+		default: {
+    } break;
+	}
+	return(status);
+}
  
 
 GCFEvent::TResult BoardCmdHandler::waitack_state(GCFEvent& event, GCFPortInterface& port)
 {
   GCFEvent::TResult status = GCFEvent::HANDLED;
-	  
 	switch(event.signal) {
   	case F_INIT: {
 		}	break;
   	
   	case F_ENTRY: {
-			// if cmd returns no ack or board/channel is not selected or not responding return to send_stae		
-			if (!itsCmd->waitAck() || itsNextCmd) {
-				nextCmd();
+			// if cmd returns no ack or board/channel is not selected or not responding return to send_state		
+			if (!itsCmd->waitAck()) {
 				TRAN(BoardCmdHandler::send_state);
 			}
 		}	break;
 		    
 		case F_TIMER: {
-			// time-out, retry 
-			if (itsRetries < itsMaxRetries) {
-				sendCmd();
-				LOG_DEBUG_STR(formatString("itsRetries[%d] = %d", itsBoardNr, itsRetries));	
-			}
-			else {
-				itsCmd->saveTpAckEvent(event,itsBoardNr); // max retries, save zero's
-				nextCmd();
+			// time-out, retry
+			if ((itsRetries < TS->maxRetries()) && !itsCmd->isDone()) {
+				LOG_DEBUG("=TIME-OUT=");
+				itsCmd->sendTpEvent();
+				itsRetries++;
+				LOG_DEBUG_STR(formatString("itsRetries[%d] = %d", itsCmd->getBoardNr(), itsRetries));	
+			}	else {
+				itsCmd->saveTpAckEvent(event); // max retries or done, save zero's
+				TRAN(BoardCmdHandler::send_state);
 			}
-			TRAN(BoardCmdHandler::send_state);
 		}	break;
 		
     case F_EXIT: {
@@ -119,78 +144,23 @@ GCFEvent::TResult BoardCmdHandler::waitack_state(GCFEvent& event, GCFPortInterfa
     default: {
 			if (itsCmd->isValid(event)) {
 				port.cancelAllTimers();
-				itsCmd->saveTpAckEvent(event,itsBoardNr);
-				nextCmd();
+				itsCmd->saveTpAckEvent(event);
+				
 				TRAN(BoardCmdHandler::send_state);
-			}
-			else {
+			}	else {
 				status = GCFEvent::NOT_HANDLED;
 			}
 		}	break;
 	}
 	return(status);
 }
-
-void BoardCmdHandler::sendCmd()
-{
-	itsNextCmd = true; // if true, go to next board or channel
-	uint32 boardmask = (1 << itsBoardNr);
-	
-	if (boardmask & DriverSettings::instance()->activeBoardsMask()) {
-		if (itsCmd->getCmdType() == BoardCmd) {
-			if (boardmask & itsCmd->getBoardMask()) {
-				if (itsCmd->sendTpEvent(itsBoardNr, itsChannelNr)) {
-					itsRetries++;
-					itsNextCmd = false;
-				}
-			}	
-		}	
-		if (itsCmd->getCmdType() == ChannelCmd) {
-			if (DriverSettings::instance()->getChSelected(itsChannelNr)) {
-				if (itsCmd->sendTpEvent(itsBoardNr, itsChannelNr)) {
-					itsRetries++;
-					itsNextCmd = false;
-				}
-			}
-		}
-	}
-}
-
-void BoardCmdHandler::nextCmd()
-{
-	if (itsCmd->getCmdType() == BoardCmd) {
-		itsBoardNr++;
-	}
-	if (itsCmd->getCmdType() == ChannelCmd) {
-		itsChannelNr++;
-		itsBoardNr = DriverSettings::instance()->getChBoardNr(itsChannelNr);
-	}
-	// if all command done send ack meassage to client and clear all variables
-	if ((itsBoardNr == DriverSettings::instance()->maxBoards()) ||
-		  (itsChannelNr == DriverSettings::instance()->maxChannels())) {
-		itsCmd->sendTbbAckEvent(itsClientPort);
-		itsCmd = 0;
-		itsBoardNr = 0;
-		itsChannelNr = 0;
-		itsRetries = 0;	
-	}	
-}
 	
 void BoardCmdHandler::setTpCmd(Command *cmd)
 {
 	itsCmd = cmd;
 }
 
-void BoardCmdHandler::setTpRetries(int32 Retries)
-{
-	itsMaxRetries = Retries;
-}
-
 bool BoardCmdHandler::tpCmdDone()
 {
-	if (itsCmd == 0) return(true);
-	return(false);
+	return (itsDone);
 }
-
-	} // end namespace TBB
-} // end namespace LOFAR
diff --git a/MAC/APL/PIC/TBBDriver/src/BoardCmdHandler.h b/MAC/APL/PIC/TBBDriver/src/BoardCmdHandler.h
index c96bc0173cb03cc7499fabf6d18f7c92a8d423ac..79334bcdc4bcd56ca6b0350a32794d29f129cc8c 100644
--- a/MAC/APL/PIC/TBBDriver/src/BoardCmdHandler.h
+++ b/MAC/APL/PIC/TBBDriver/src/BoardCmdHandler.h
@@ -39,6 +39,7 @@
 #include <GCF/TM/GCF_Control.h>
 
 #include "Command.h"
+#include "DriverSettings.h"
 
 namespace LOFAR {
 	namespace TBB {
@@ -55,41 +56,23 @@ namespace LOFAR {
 				~BoardCmdHandler();
 
 				// The states of the statemachine.
+				GCFEvent::TResult idle_state(GCFEvent& event, GCFPortInterface& port);
 				GCFEvent::TResult send_state(GCFEvent& event, GCFPortInterface& port);
 				GCFEvent::TResult waitack_state(GCFEvent& event, GCFPortInterface& port);
 								
 				void setTpCmd(Command *cmd);
-				void setTpRetries(int32 Retries);
-				void setNrOfTbbBoards(int32 NrOfBoards);
-				//void setTpTimeOut(double TimeOut);
 				bool tpCmdDone();
 				
 			protected:
 
 			private:
-				// convert port to portnr, used in the port-array
-				//int portToBoardNr(GCFPortInterface& port);
-				void sendCmd();
-				void nextCmd();
-				
-			private:
-				
-				// constants
-				int32		itsMaxRetries;
+				TbbSettings 			*TS;
+				bool							itsDone;
+				bool							itsFlashMode;
 				// variables
-				int32		itsRetries;
-				int32		itsNrOfBoards;
-				int32		itsNrOfChannels;
-				
-				CmdTypes itsCmdType;
-				int32		itsBoardNr;
-				int32		itsChannelNr;
-				bool		itsNextCmd;
-				
-				GCFPortInterface*		itsClientPort; // return port of the actual commmand
-										
-				//int32								itsBoardRetries[MAX_N_TBBBOARDS];
-				Command*						itsCmd; // command to use			
+				int32							 itsRetries;
+				GCFPortInterface  *itsClientPort; // return port of the actual commmand
+				Command						*itsCmd; // command to use			
 				
 		};
 	} // end TBB namespace
diff --git a/MAC/APL/PIC/TBBDriver/src/ClearCmd.cc b/MAC/APL/PIC/TBBDriver/src/ClearCmd.cc
index 11a98f0c1019b712af353ec43f0db85022dc9e31..58bd038bd431f46965f3469053035e1ceb2fba8d 100644
--- a/MAC/APL/PIC/TBBDriver/src/ClearCmd.cc
+++ b/MAC/APL/PIC/TBBDriver/src/ClearCmd.cc
@@ -24,25 +24,25 @@
 #include <Common/LofarLogger.h>
 
 #include "ClearCmd.h"
-#include "DriverSettings.h"
 
-namespace LOFAR {
-	using namespace TBB_Protocol;
-	using namespace TP_Protocol;
-	namespace TBB {
+using namespace LOFAR;
+using namespace TBB_Protocol;
+using namespace TP_Protocol;
+using	namespace TBB;
 
 //--Constructors for a ClearCmd object.----------------------------------------
-ClearCmd::ClearCmd():
-		itsBoardMask(0),itsBoardsMask(0)
+ClearCmd::ClearCmd()
 {
+	TS					= TbbSettings::instance();
 	itsTPE 			= new TPClearEvent();
 	itsTPackE 	= 0;
 	itsTBBE 		= 0;
 	itsTBBackE 	= new TBBClearackEvent();
 	
 	for(int boardnr = 0;boardnr < MAX_N_TBBBOARDS;boardnr++) { 
-		itsTBBackE->status[boardnr]	= 0;
-	}		
+		itsTBBackE->status_mask[boardnr]	= 0;
+	}
+	setWaitAck(true);		
 }
 	  
 //--Destructor for ClearCmd.---------------------------------------------------
@@ -66,21 +66,15 @@ void ClearCmd::saveTbbEvent(GCFEvent& event)
 {
 	itsTBBE 			= new TBBClearEvent(event);
 		
-	// mask for the installed boards
-	itsBoardsMask = DriverSettings::instance()->activeBoardsMask();
-	itsBoardMask = itsTBBE->boardmask;
+	setBoardMask(itsTBBE->boardmask);
 	
-	for (int boardnr = 0; boardnr < DriverSettings::instance()->maxBoards(); boardnr++) {
-		
-		if (!(itsBoardsMask & (1 << boardnr)))
-			itsTBBackE->status[boardnr] |= NO_BOARD;
-		
-		if (!(itsBoardsMask & (1 << boardnr)) &&  (itsBoardMask & (1 << boardnr)))
-			itsTBBackE->status[boardnr] |= (SELECT_ERROR | BOARD_SEL_ERROR);
+	for (int boardnr = 0; boardnr < TS->maxBoards(); boardnr++) {
+		if (TS->isBoardActive(boardnr) == false)
+			itsTBBackE->status_mask[boardnr] |= TBB_NO_BOARD;
 	}
 	
-	// Send only commands to boards installed
-	itsBoardMask = itsBoardMask & itsBoardsMask;
+	// get first board
+	nextBoardNr();
 	
 	// initialize TP send frame
 	itsTPE->opcode			= TPCLEAR;
@@ -90,74 +84,46 @@ void ClearCmd::saveTbbEvent(GCFEvent& event)
 }
 
 // ----------------------------------------------------------------------------
-bool ClearCmd::sendTpEvent(int32 boardnr, int32)
+void ClearCmd::sendTpEvent()
 {
-	bool sending = false;
-	DriverSettings*		ds = DriverSettings::instance();
-	
-	if (ds->boardPort(boardnr).isConnected() && (itsTBBackE->status[boardnr] == 0)) {
-		ds->boardPort(boardnr).send(*itsTPE);
-		ds->boardPort(boardnr).setTimer(ds->timeout());
-		sending = true;
-		
-		// reset channel information for selected board	
-		for (int channelnr = (boardnr * 16); channelnr < ((boardnr * 16) + 16); channelnr++) {
-			DriverSettings::instance()->setChSelected(channelnr, false);
-			DriverSettings::instance()->setChStatus(channelnr, 'F');
-			DriverSettings::instance()->setChStartAddr(channelnr, 0);
-			DriverSettings::instance()->setChPageSize(channelnr, 0);				
-		}
-	}
-	
-	return(sending);
+	TS->boardPort(getBoardNr()).send(*itsTPE);
+	TS->boardPort(getBoardNr()).setTimer(TS->timeout());
 }
 
 // ----------------------------------------------------------------------------
-void ClearCmd::saveTpAckEvent(GCFEvent& event, int32 boardnr)
+void ClearCmd::saveTpAckEvent(GCFEvent& event)
 {
 	// in case of a time-out, set error mask
 	if (event.signal == F_TIMER) {
 		;
-	}
-	else {
+	}	else {
 		itsTPackE = new TPClearackEvent(event);
 		
 		if ((itsTPackE->status >= 0xF0) && (itsTPackE->status <= 0xF6)) 
-			itsTBBackE->status[boardnr] |= (1 << (16 + (itsTPackE->status & 0x0F)));	
+			itsTBBackE->status_mask[getBoardNr()] |= (1 << (16 + (itsTPackE->status & 0x0F)));	
 		
-		LOG_DEBUG_STR(formatString("Received ClearAck from boardnr[%d]", boardnr));
+		// reset channel-information for selected board	
+		if (itsTPackE->status == 0) {
+			for (int channelnr = (getBoardNr() * 16); channelnr < ((getBoardNr() * 16) + 16); channelnr++) {
+				TS->setChSelected(channelnr, false);
+				TS->setChState(channelnr, 'F');
+				TS->setChStartAddr(channelnr, 0);
+				TS->setChPageSize(channelnr, 0);				
+			}
+		}
+		LOG_DEBUG_STR(formatString("Received ClearAck from boardnr[%d]", getBoardNr()));
 		delete itsTPackE;
 	}
+	nextBoardNr();
 }
 
 // ----------------------------------------------------------------------------
 void ClearCmd::sendTbbAckEvent(GCFPortInterface* clientport)
 {
-	for (int32 boardnr = 0; boardnr < DriverSettings::instance()->maxBoards(); boardnr++) { 
-		if (itsTBBackE->status[boardnr] == 0)
-			itsTBBackE->status[boardnr] = SUCCESS;
+	for (int32 boardnr = 0; boardnr < TS->maxBoards(); boardnr++) { 
+		if (itsTBBackE->status_mask[boardnr] == 0)
+			itsTBBackE->status_mask[boardnr] = TBB_SUCCESS;
 	}
 	
 	clientport->send(*itsTBBackE);
 }
-
-// ----------------------------------------------------------------------------
-CmdTypes ClearCmd::getCmdType()
-{
-	return(BoardCmd);
-}
-
-// ----------------------------------------------------------------------------
-uint32 ClearCmd::getBoardMask()
-{
-	return(itsBoardMask);
-}
-
-// ----------------------------------------------------------------------------
-bool ClearCmd::waitAck()
-{
-	return(false);
-}
-
-	} // end TBB namespace
-} // end LOFAR namespace
diff --git a/MAC/APL/PIC/TBBDriver/src/ClearCmd.h b/MAC/APL/PIC/TBBDriver/src/ClearCmd.h
index 858608575a4c1da16f2c7b782378879935c8d918..9b33a07af0f9f13220a32ee303c0e40261dca296 100644
--- a/MAC/APL/PIC/TBBDriver/src/ClearCmd.h
+++ b/MAC/APL/PIC/TBBDriver/src/ClearCmd.h
@@ -32,6 +32,7 @@
 #include "TP_Protocol.ph"
 
 #include "Command.h"
+#include "DriverSettings.h"
 
 namespace LOFAR {
 	using namespace TBB_Protocol;
@@ -50,21 +51,14 @@ namespace LOFAR {
 				
 				virtual void saveTbbEvent(GCFEvent& event);
 									
-				virtual bool sendTpEvent(int32 boardnr, int32 channelnr);
+				virtual void sendTpEvent();
 
-				virtual void saveTpAckEvent(GCFEvent& event, int32 boardnr);
+				virtual void saveTpAckEvent(GCFEvent& event);
 
 				virtual void sendTbbAckEvent(GCFPortInterface* clientport);
 				
-				virtual uint32 getBoardMask();
-				
-				virtual bool waitAck();
-				
-				virtual CmdTypes getCmdType();
-      
 			private:
-				uint32	itsBoardMask;  // mask indicates the boards to communicate with
-				uint32	itsBoardsMask;	// Installed boards mask
+				TbbSettings *TS;
 				
 				TPClearEvent			*itsTPE;
 				TPClearackEvent		*itsTPackE;
diff --git a/MAC/APL/PIC/TBBDriver/src/Command.cc b/MAC/APL/PIC/TBBDriver/src/Command.cc
index 0755b51b7a907f5583784b2adcf0f5ec990f5ccd..693e7ac66d3d9d0424bfee7ee82c7b6f36f94dcc 100644
--- a/MAC/APL/PIC/TBBDriver/src/Command.cc
+++ b/MAC/APL/PIC/TBBDriver/src/Command.cc
@@ -25,55 +25,147 @@
 
 #include "Command.h"
 
-namespace LOFAR {
-	namespace TBB {
-
-Command::Command()
+using namespace LOFAR;
+using namespace TBB;
+			
+Command::Command() : 
+	itsWaitAck(false), itsDone(false), itsAllPorts(false), itsBoard(-1), itsChannel(-1), itsBoardMask(0)
 {
+	TS = TbbSettings::instance();
 }
 
 Command::~Command()
 {
 }
-			
-bool Command::isValid(GCFEvent& event)
+
+// ----------------------------------------------------------------------------
+int32 Command::getBoardNr()
 {
-	return false;
+	return(itsBoard);
 }
-				
-void Command::saveTbbEvent(GCFEvent& event)
+
+// ----------------------------------------------------------------------------
+int32 Command::getChannelNr()
 {
+	return(itsChannel);
 }
-				
-void Command::makeTpEvent()
+// ----------------------------------------------------------------------------
+void Command::setBoardNr(int32 boardnr)
 {
+	itsBoard = boardnr;
 }
-						
-void Command::sendTpEvent(GCFPortInterface& port)
+
+// ----------------------------------------------------------------------------
+void Command::setChannelNr(int32 channelnr)
 {
+	itsChannel = channelnr;
+	itsBoard = TS->getChBoardNr(itsChannel); 
 }
 
-void Command::saveTpAckEvent(GCFEvent& event, int boardnr)
+// ----------------------------------------------------------------------------
+void Command::setDone(bool done)
 {
+	itsDone = done;
+	if (itsDone) {
+		itsWaitAck = true;
+		itsBoard = -1;
+		itsChannel = -1;	
+	}
 }
 
-void Command::sendTbbAckEvent(GCFPortInterface* clientport)
+// ----------------------------------------------------------------------------
+void Command::resetBoardNr()
 {
+	itsBoard = -1;
 }
 
-uint32 Command::getSendMask()
+// ----------------------------------------------------------------------------
+void Command::resetChannelNr()
 {
-	return 0;
+	itsBoard = -1;
 }
 
-uint32 Command::getRecvMask()
+// ----------------------------------------------------------------------------
+bool Command::isDone()
 {
-	return 0;
+	return(itsDone);
 }
-			
-uint32 Command::done()
+
+// ----------------------------------------------------------------------------
+bool Command::waitAck()
+{
+	return(itsWaitAck);
+}
+
+// ----------------------------------------------------------------------------			
+void Command::setWaitAck(bool waitack)
 {
-	return 0;
+	itsWaitAck = waitack;
 }
-	} // end TBB namespace
-} // end LOFAR namespace
+
+// ----------------------------------------------------------------------------
+void Command::setBoardMask(uint32 mask)
+{
+	itsBoardMask = mask;
+}
+
+// ----------------------------------------------------------------------------
+void Command::nextBoardNr()
+{
+	bool validNr = false;
+	
+	do {
+		itsBoard++;
+		if (itsBoard < TS->maxBoards()) {
+			// see if board is active
+			if (TS->boardPort(itsBoard).isConnected() 
+						&& TS->isBoardActive(itsBoard) 
+						&& (itsBoardMask & (1 << itsBoard))) 
+			{
+				validNr = true;
+			}
+		} else {
+			break;	
+		}
+	} while (!validNr);
+		
+	// if all nr done send clear all variables
+	if (!validNr) {
+		itsDone = true;
+		itsBoard = -1;
+		itsBoardMask = 0;
+	}
+	LOG_DEBUG_STR(formatString("nextBoardNr() = %d",itsBoard));		
+}
+
+// ----------------------------------------------------------------------------
+void Command::nextChannelNr()
+{
+	bool validNr = false;
+	
+	do {
+		itsChannel++;
+		itsBoard = TS->getChBoardNr(itsChannel);
+		
+		if (itsBoard < TS->maxBoards()) {
+			// see if board is active and channel is selected
+			if (TS->boardPort(itsBoard).isConnected()
+						&& TS->isBoardActive(itsBoard) 
+						&& TS->isChSelected(itsChannel)) 
+			{
+				validNr = true;
+			}
+		} else {
+			break;	
+		}
+	} while (!validNr && (itsChannel < TS->maxChannels()));
+		
+	// if all nr done send clear all variables
+	if (!validNr) {
+		itsDone = true;
+		itsChannel = -1;
+	}
+	LOG_DEBUG_STR(formatString("nextChannelNr() = %d",itsChannel));	
+}
+
+
diff --git a/MAC/APL/PIC/TBBDriver/src/Command.h b/MAC/APL/PIC/TBBDriver/src/Command.h
index d30a124b28f4ad709b94102cbe67705ea0b1d38a..4d68e4176be63c326d907df3075ab77892093617 100644
--- a/MAC/APL/PIC/TBBDriver/src/Command.h
+++ b/MAC/APL/PIC/TBBDriver/src/Command.h
@@ -1,5 +1,3 @@
-//#  -*- mode: c++ -*-
-//#
 //#  Command.h: TBB Driver command class
 //#
 //#  Copyright (C) 2002-2004
@@ -20,7 +18,7 @@
 //#  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 COMMAND_H_
 #define COMMAND_H_
@@ -28,39 +26,66 @@
 #include <Common/LofarTypes.h>
 #include <GCF/TM/GCF_Control.h>
 
+#include "DriverSettings.h"
+
 namespace LOFAR {
   namespace TBB {
-		
-		enum CmdTypes {BoardCmd,ChannelCmd}; 
-				
+
 		class Command
     {
     public:
 						
 			// Constructor for Command
-			Command(){};
+			Command();
 	  
       // Destructor for Command.
-      virtual ~Command(){};
+      virtual ~Command();
 			
 			virtual bool isValid(GCFEvent& event) = 0;
 				
 			virtual void saveTbbEvent(GCFEvent& event) = 0;
 											
-			virtual bool sendTpEvent(int32 boardnr, int32 channelnr) = 0;
+			virtual void sendTpEvent() = 0;
 			
-			virtual void saveTpAckEvent(GCFEvent& event, int32 boardnr) = 0;
+			virtual void saveTpAckEvent(GCFEvent& event) = 0;
 
 			virtual void sendTbbAckEvent(GCFPortInterface* clientport) = 0;
 			
-			virtual uint32 getBoardMask() = 0;
+			bool waitAck();
+			
+			void setWaitAck(bool waitack);
+			
+			bool isDone();
+			
+			void setDone(bool done);
+			
+			void resetBoardNr();
+			
+			void resetChannelNr();
+			
+			int32 getBoardNr();
+			
+			int32 getChannelNr();
+			
+			void setBoardNr(int32 boardnr);
+			
+			void setChannelNr(int32 channelnr);
 				
-			virtual bool waitAck() = 0;
+			void nextBoardNr();
+			
+			void nextChannelNr();
 			
-			virtual CmdTypes getCmdType() = 0;
+			void setBoardMask(uint32 mask);
 			
     private:
-												
+    	TbbSettings *TS;
+    	
+    	bool		itsWaitAck;		// true if an ack is expected
+    	bool		itsDone;			// true if the command is completed
+    	bool		itsAllPorts;	// true if command must be send to all available ports
+    	int32		itsBoard;
+			int32		itsChannel;
+			uint32	itsBoardMask;
     };
 	} // end TBB namespace
 } // end LOFAR namespace
diff --git a/MAC/APL/PIC/TBBDriver/src/ConfigCmd.cc b/MAC/APL/PIC/TBBDriver/src/ConfigCmd.cc
index 9c42c8fafd6f3b6d31364c6112cd6512fb1e2f85..98bf9c82ddf55ca22f2905e24bbe185f66bf4ec7 100644
--- a/MAC/APL/PIC/TBBDriver/src/ConfigCmd.cc
+++ b/MAC/APL/PIC/TBBDriver/src/ConfigCmd.cc
@@ -24,25 +24,26 @@
 #include <Common/LofarLogger.h>
 
 #include "ConfigCmd.h"
-#include "DriverSettings.h"
 
-namespace LOFAR {
-	using namespace TBB_Protocol;
-	using namespace TP_Protocol;
-	namespace TBB {
+
+using namespace LOFAR;
+using namespace TBB_Protocol;
+using namespace TP_Protocol;
+using	namespace TBB;
 
 //--Constructors for a ConfigCmd object.----------------------------------------
-ConfigCmd::ConfigCmd():
-		itsBoardMask(0),itsBoardsMask(0)
+ConfigCmd::ConfigCmd()
 {
+	TS					= TbbSettings::instance();
 	itsTPE 			= new TPConfigEvent();
 	itsTPackE 	= 0;
 	itsTBBE 		= 0;
 	itsTBBackE 	= new TBBConfigackEvent();
 	
 	for(int boardnr = 0;boardnr < MAX_N_TBBBOARDS;boardnr++) { 
-		itsTBBackE->status[boardnr]	= 0;
-	}		
+		itsTBBackE->status_mask[boardnr]	= 0;
+	}
+	setWaitAck(true);		
 }
 	  
 //--Destructor for ConfigCmd.---------------------------------------------------
@@ -64,97 +65,59 @@ bool ConfigCmd::isValid(GCFEvent& event)
 // ----------------------------------------------------------------------------
 void ConfigCmd::saveTbbEvent(GCFEvent& event)
 {
-	itsTBBE 			= new TBBConfigEvent(event);
-		
-	// mask for the installed boards
-	itsBoardsMask = DriverSettings::instance()->activeBoardsMask();
-	itsBoardMask = itsTBBE->boardmask; // for some commands board-id is used ???
-	
-	for (int boardnr = 0; boardnr < DriverSettings::instance()->maxBoards(); boardnr++) {
+	itsTBBE = new TBBConfigEvent(event);
+	//TBBConfigEvent itsTBBE(event);
 		
-		if (!(itsBoardsMask & (1 << boardnr))) 
-			itsTBBackE->status[boardnr] |= NO_BOARD;
-		
-		if (!(itsBoardsMask & (1 << boardnr)) &&  (itsBoardMask & (1 << boardnr)))
-			itsTBBackE->status[boardnr] |= (SELECT_ERROR | BOARD_SEL_ERROR);
+	for (int boardnr = 0; boardnr < TS->maxBoards(); boardnr++) {
+		if (TS->isBoardActive(boardnr) == false) 
+			itsTBBackE->status_mask[boardnr] |= TBB_NO_BOARD;
 	}
 	
-	// Send only commands to boards installed
-	itsBoardMask = itsBoardMask & itsBoardsMask;
+	setBoardMask(itsTBBE->boardmask);
+	
+	// select first boards
+	nextBoardNr();
 	
 	// initialize TP send frame
 	itsTPE->opcode	= TPCONFIG;
 	itsTPE->status	=	0;
-	itsTPE->imagenr	 	= itsTBBE->imagenr;
+	itsTPE->imagenr	= static_cast<uint32>(itsTBBE->imagenr);
 	
 	delete itsTBBE;	
 }
 
 // ----------------------------------------------------------------------------
-bool ConfigCmd::sendTpEvent(int32 boardnr, int32)
+void ConfigCmd::sendTpEvent()
 {
-	bool sending = false;
-	DriverSettings*		ds = DriverSettings::instance();
-	
-	if 	(ds->boardPort(boardnr).isConnected() &&
-			(itsTBBackE->status[boardnr] == 0)) {
-		
-		ds->boardPort(boardnr).send(*itsTPE);
-		ds->boardPort(boardnr).setTimer(ds->timeout());
-		sending = true;
-	}
-	else 
-		itsTBBackE->status[boardnr] |= CMD_ERROR;
-		
-	return(sending);
+	TS->boardPort(getBoardNr()).send(*itsTPE);
+	TS->boardPort(getBoardNr()).setTimer(TS->timeout());
 }
 
 // ----------------------------------------------------------------------------
-void ConfigCmd::saveTpAckEvent(GCFEvent& event, int32 boardnr)
+void ConfigCmd::saveTpAckEvent(GCFEvent& event)
 {
 	// in case of a time-out, set error mask
 	if (event.signal == F_TIMER) {
-		itsTBBackE->status[boardnr] |= COMM_ERROR;
-	}
-	else {
+		itsTBBackE->status_mask[getBoardNr()] |= TBB_COMM_ERROR;
+	}	else {
 		itsTPackE = new TPConfigackEvent(event);
 		
 		if ((itsTPackE->status >= 0xF0) && (itsTPackE->status <= 0xF6)) 
-			itsTBBackE->status[boardnr] |= (1 << (16 + (itsTPackE->status & 0x0F)));	
+			itsTBBackE->status_mask[getBoardNr()] |= (1 << (16 + (itsTPackE->status & 0x0F)));	
 		
-		LOG_DEBUG_STR(formatString("Received ConfigAck from boardnr[%d]", boardnr));
+		LOG_DEBUG_STR(formatString("Received ConfigAck from boardnr[%d]", getBoardNr()));
 		delete itsTPackE;
 	}
+	nextBoardNr();
 }
 
 // ----------------------------------------------------------------------------
 void ConfigCmd::sendTbbAckEvent(GCFPortInterface* clientport)
 {
-	for (int32 boardnr = 0; boardnr < DriverSettings::instance()->maxBoards(); boardnr++) { 
-		if (itsTBBackE->status[boardnr] == 0)
-			itsTBBackE->status[boardnr] = SUCCESS;
+	for (int32 boardnr = 0; boardnr < TS->maxBoards(); boardnr++) { 
+		if (itsTBBackE->status_mask[boardnr] == 0)
+			itsTBBackE->status_mask[boardnr] = TBB_SUCCESS;
 	}
 	 
 	clientport->send(*itsTBBackE);
 }
-
-// ----------------------------------------------------------------------------
-CmdTypes ConfigCmd::getCmdType()
-{
-	return(BoardCmd);
-}
-
-// ----------------------------------------------------------------------------
-uint32 ConfigCmd::getBoardMask()
-{
-	return(itsBoardMask);
-}
-
-// ----------------------------------------------------------------------------
-bool ConfigCmd::waitAck()
-{
-	return(false);
-}
-
-	} // end TBB namespace
-} // end LOFAR namespace
diff --git a/MAC/APL/PIC/TBBDriver/src/ConfigCmd.h b/MAC/APL/PIC/TBBDriver/src/ConfigCmd.h
index 9ad6bc40dc4e6a1ce18ed2d6382cbc350c27eff2..30cc767a7c14f7b44509d9017c3e033c996b8883 100644
--- a/MAC/APL/PIC/TBBDriver/src/ConfigCmd.h
+++ b/MAC/APL/PIC/TBBDriver/src/ConfigCmd.h
@@ -32,6 +32,7 @@
 #include "TP_Protocol.ph"
 
 #include "Command.h"
+#include "DriverSettings.h"
 
 namespace LOFAR {
 	using namespace TBB_Protocol;
@@ -50,21 +51,14 @@ namespace LOFAR {
 				
 				virtual void saveTbbEvent(GCFEvent& event);
 									
-				virtual bool sendTpEvent(int32 boardnr, int32 channelnr);
+				virtual void sendTpEvent();
 
-				virtual void saveTpAckEvent(GCFEvent& event, int32 boardnr);
+				virtual void saveTpAckEvent(GCFEvent& event);
 
 				virtual void sendTbbAckEvent(GCFPortInterface* clientport);
 				
-				virtual uint32 getBoardMask();
-				
-				virtual bool waitAck();
-				
-				virtual CmdTypes getCmdType();
-      
 			private:
-				uint32	itsBoardMask;  // mask indicates the boards to communicate with
-				uint32	itsBoardsMask;	// Installed boards mask
+				TbbSettings *TS;
 				
 				TPConfigEvent			*itsTPE;
 				TPConfigackEvent	*itsTPackE;
diff --git a/MAC/APL/PIC/TBBDriver/src/DriverSettings.cc b/MAC/APL/PIC/TBBDriver/src/DriverSettings.cc
index 7ae114fb326caf169f84e9c02f1b78a6e0ca8754..02242567c26a22b9ff718e65e2e26f632799953c 100644
--- a/MAC/APL/PIC/TBBDriver/src/DriverSettings.cc
+++ b/MAC/APL/PIC/TBBDriver/src/DriverSettings.cc
@@ -1,4 +1,4 @@
-//#  DriverSettings.cc: Driver settings
+//#  TbbSettings.cc: Driver settings
 //#
 //#  Copyright (C) 2002-2004
 //#  ASTRON (Netherlands Foundation for Research in Astronomy)
@@ -22,104 +22,266 @@
 
 //# Always #include <lofar_config.h> first!
 #include <lofar_config.h>
-
-//# Includes
 #include <Common/LofarLogger.h>
+#include <Common/LofarLocators.h>
+#include <APS/ParameterSet.h>
+#include <GCF/GCF_ServiceInfo.h>
 #include <DriverSettings.h>
 
-namespace LOFAR {
-  namespace TBB {
+using namespace LOFAR;
+	//using namespace GCFCommon;
+using namespace ACC::APS;
+using namespace TBB;
+
 
 //
 // Initialize singleton
 //
-DriverSettings* DriverSettings::theirDriverSettings = 0;
+TbbSettings* TbbSettings::theirTbbSettings = 0;
 
-DriverSettings* DriverSettings::instance()
+TbbSettings* TbbSettings::instance()
 {
-	if (theirDriverSettings == 0) {
-		theirDriverSettings = new DriverSettings();
+	if (theirTbbSettings == 0) {
+		theirTbbSettings = new TbbSettings();
 	}
-	return(theirDriverSettings);
+	return(theirTbbSettings);
 }
 
 //
 // Default constructor
 //
-DriverSettings::DriverSettings() :
-	itsMaxBoards(0),
-	itsMaxChannels(0),
-	itsMpsPerBoard(4),
-	itsChannelsPerMp(4),
-	itsChannelsPerBoard(16),
-	itsTimeOut(0.1),
-	itsActiveBoardsMask(0),
-	itsChannel(0),
-	itsMemorySize(0)
+TbbSettings::TbbSettings() :
+	itsDriverVersion(10),				  // driver version 1.0
+	itsMaxBoards(0),							// max.number of boards on 1 driver 
+	itsMaxChannels(0),						// max.number of channels on 1 driver
+	itsMpsOnBoard(4),							// number of MPs on 1 board
+	itsChannelsOnMp(4),						// number of channels on 1 MP
+	itsChannelsOnBoard(16),				// number of channels on 1 board
+	itsFlashMaxPages(32),					// max.number of pages in flash on 1 board
+	itsFlashSectorsInPage(16),		// number of sectors in 1 page
+	itsFlashBlocksInPage(2048),		// number of blocks in 1 page
+	itsFlashPageSize(2097152),		// size of 1 page in bytes
+	itsFlashPageSectorSize(131072),// size of 1 sector in bytes
+	itsFlashPageBlockSize(1024),	// size of 1 block in bytes
+	itsMaxRetries(5),							// max.number of retries for each command
+	itsTimeOut(0.2),							// response timeout
+	itsActiveBoardsMask(0),				// mask with active boards
+	itsRcu2ChTable(0),						// conversion table Rcu-number to Channnel-number
+	itsCh2RcuTable(0),						// conversion table Channel-number to Rcu-number
+	itsBoardInfo(0),
+	itsChannelInfo(0) 								// Struct with channel info
 {
-
+	itsRcu2ChTable = new int32[itsChannelsOnBoard];
+	itsCh2RcuTable = new int32[itsChannelsOnBoard];
 }
 
-DriverSettings::~DriverSettings()
+TbbSettings::~TbbSettings()
 {
-	if (itsChannel) delete itsChannel;
-	if (itsMemorySize) delete itsMemorySize;			
+	if (itsRcu2ChTable) delete itsRcu2ChTable;
+	if (itsCh2RcuTable) delete itsCh2RcuTable;
+	if (itsBoardInfo) delete itsBoardInfo;
+	if (itsChannelInfo) delete itsChannelInfo;
 }
 
+//---- get Tbb settings loaded from config file ---
+void TbbSettings::getTbbSettings()
+{ 
+  bool configOK = true;
+  
+  // the conversion table must be set 1e
+  char chname[64];
+  for (int32 channelnr = 0; channelnr < itsChannelsOnBoard; channelnr++) {
+  	snprintf(chname, 64, "TBBDriver.TBB_CH_%d", channelnr);	
+  	try { setConversionTable(globalParameterSet()->getInt32(chname), channelnr); }
+  	catch (...) { LOG_INFO_STR(formatString("%s not found",chname)); configOK = false; } 
+  }
+  
+  // setMaxBoards() must be set 2e
+  setMaxBoards(MAX_N_TBBBOARDS);
+  
+  try { itsTimeOut = globalParameterSet()->getDouble("TBBDriver.TP_TIMEOUT"); }
+  catch (...) { LOG_INFO_STR(formatString("TBBDriver.TP_TIMEOUT not found")); configOK = false;}
+  
+  try { itsMaxRetries = globalParameterSet()->getInt32("TBBDriver.TP_RETRIES"); }
+  catch (...) { LOG_INFO_STR(formatString("TBBDriver.TP_RETRIES not found")); configOK = false; }
+    
+  try { itsIfName = globalParameterSet()->getString("TBBDriver.IF_NAME"); }
+  catch (...) { LOG_INFO_STR(formatString("TBBDriver.IF_NAME not found")); configOK = false; }
+    
+  char dstip[64];
+  char srcip[64];
+  char srcmac[64];
+  char dstmac[64];
+  for (int boardnr = 0; boardnr < itsMaxBoards; boardnr++) {
+  	snprintf(srcip,  64, "TBBDriver.SRC_IP_ADDR_%d", boardnr);
+  	snprintf(dstip,  64, "TBBDriver.DST_IP_ADDR_%d", boardnr);
+		snprintf(srcmac, 64, "TBBDriver.MAC_ADDR_%d", boardnr);
+		snprintf(dstmac, 64, "TBBDriver.DST_MAC_ADDR_%d", boardnr);
+		
+		try { itsBoardInfo[boardnr].srcIp = globalParameterSet()->getString(srcip); }
+  	catch (...) { LOG_INFO_STR(formatString("%s not found",srcip)); configOK = false; }
+		
+		try { itsBoardInfo[boardnr].dstIp = globalParameterSet()->getString(dstip); }
+  	catch (...) {	LOG_INFO_STR(formatString("%s not found",dstip)); configOK = false; }
+		
+		try { itsBoardInfo[boardnr].srcMac = globalParameterSet()->getString(srcmac); }
+  	catch (...) { LOG_INFO_STR(formatString("%s not found",srcmac)); }
+		
+		try { itsBoardInfo[boardnr].dstMac = globalParameterSet()->getString(dstmac); }
+  	catch (...) { LOG_INFO_STR(formatString("%s not found",dstmac)); }
+		
+		LOG_INFO_STR(formatString("Board %d:",boardnr));
+		LOG_INFO_STR(formatString("Control port: Mac = '%s'"
+															,itsBoardInfo[boardnr].srcMac.c_str()));
+		LOG_INFO_STR(formatString("CEP port    : Src Ip = '%s'"
+															,itsBoardInfo[boardnr].srcIp.c_str()));
+		LOG_INFO_STR(formatString("            : Dst Ip = '%s', Dst Mac = '%s'"
+															,itsBoardInfo[boardnr].dstIp.c_str()
+															,itsBoardInfo[boardnr].dstMac.c_str()));		
+  }
+}
+  
+  
 
-void DriverSettings::setBoardPorts(GCFPortInterface* board_ports)
+//---- setBoardPorts ------------------------------
+void TbbSettings::setBoardPorts(int board, GCFPortInterface* board_ports)
 {
-	itsBoardPorts	= board_ports; // save address of boards array		
+	itsBoardInfo[board].port = board_ports;
 }
 
 //---- setMaxBoards ------------------------------
-void DriverSettings::setMaxBoards (int32 maxboards)
+void TbbSettings::setMaxBoards (int32 maxboards)
 {
 	itsMaxBoards = maxboards;
-	itsMaxChannels = itsChannelsPerBoard * maxboards;
-	if (itsChannel) delete itsChannel;
-	itsChannel = new ChannelInfo[itsMaxChannels];
-		
+	itsMaxChannels = itsChannelsOnBoard * maxboards;
+	
+	if (itsChannelInfo) delete itsChannelInfo;
+	itsChannelInfo = new ChannelInfo[itsMaxChannels];
+				
 	int32 boardnr = 0;
 	int32 inputnr = 0;
 	int32 mpnr = 0;
 	
-	for (int nr = 0; nr < itsMaxChannels; nr++) {
-		itsChannel[nr].Status = 'F';
-		itsChannel[nr].Selected = false;
-		itsChannel[nr].BoardNr = boardnr;
-		itsChannel[nr].InputNr = inputnr;
-		itsChannel[nr].MpNr = mpnr;
-		itsChannel[nr].StartAddr = 0;
-		itsChannel[nr].PageSize = 0;
+	for (int32 ch = 0; ch < itsMaxChannels; ch++) {
+		itsChannelInfo[ch].Selected = false;
+		itsChannelInfo[ch].Status = 0;
+		itsChannelInfo[ch].State = 'F';
+		convertCh2Rcu(ch,&itsChannelInfo[ch].RcuNr);
+		itsChannelInfo[ch].BoardNr = boardnr;
+		itsChannelInfo[ch].InputNr = inputnr;
+		itsChannelInfo[ch].MpNr = mpnr;
+		itsChannelInfo[ch].StartAddr = 0;
+		itsChannelInfo[ch].PageSize = 0;
 		inputnr++;
-		if (inputnr == itsChannelsPerBoard) {
+		if (inputnr == itsChannelsOnBoard) {
 			inputnr = 0;
 			boardnr++;
 		}
 		mpnr = (int32)(inputnr / 4);
 	}
 	
-	if (itsMemorySize) delete itsMemorySize;
-	itsMemorySize = new uint32[itsMaxBoards];
+	if (itsBoardInfo) delete itsBoardInfo;
+	itsBoardInfo = new BoardInfo[itsMaxBoards];
 	
 	for (int nr = 0;nr < itsMaxBoards; nr++) {
-		itsMemorySize[nr] = 0;
+		itsBoardInfo[nr].memorySize = 0;
+		itsBoardInfo[nr].srcIp = "";
+		itsBoardInfo[nr].dstIp = "";
+		itsBoardInfo[nr].srcMac = "";
+		itsBoardInfo[nr].dstMac = "";
 	}
 }
 
 //---- setActiveBoards ---------------------------
-void DriverSettings::setActiveBoards (uint32 activeboardsmask)
+void TbbSettings::setActiveBoards (uint32 activeboardsmask)
 {
+	// clear rcu setting for boards not active anymore
+	uint32 mask;
+	mask = (~activeboardsmask) & itsActiveBoardsMask;
+	for (int bn = 0; bn < itsMaxBoards; bn++) {
+		if (mask & (1 << bn)) {
+			clearRcuSettings(bn);	
+		}
+	}
 	itsActiveBoardsMask = activeboardsmask;
 }
+
+//---- set Communication retries ----------------
+void TbbSettings::setMaxRetries(int32 retries)
+{
+	itsMaxRetries = retries;
+}
+
 //---- set Communication time-out ----------------
-void DriverSettings::setTimeOut(double timeout)
+void TbbSettings::setTimeOut(double timeout)
 {
 	itsTimeOut = timeout;
 }
 
+//---- set RCU2CH conversion table ----------------
+void TbbSettings::setConversionTable(int32 rcu, int32 channel)
+{
+	itsRcu2ChTable[rcu] = channel;
+	itsCh2RcuTable[channel] = rcu;
+	//LOG_INFO_STR(formatString("table rcu.%d = chan.%d",rcu, channel));
+}
+
+void TbbSettings::convertRcu2Ch(int32 rcunr, int32 *boardnr, int32 *channelnr)
+{
+	int32 board;
+	int32 channel;
+	
+	board = (int32)(rcunr / itsChannelsOnBoard);
+	channel = itsRcu2ChTable[rcunr - (board * itsChannelsOnBoard)];
+	*boardnr = board;
+	*channelnr = channel;	
+}
+
+void TbbSettings::convertCh2Rcu(int32 channelnr, int32 *rcunr)
+{
+	int32 boardnr;
+	int32 rcu;
+	
+	boardnr = (int32)(channelnr / itsChannelsOnBoard);
+	rcu = itsCh2RcuTable[(channelnr - (boardnr * itsChannelsOnBoard))] + (boardnr * itsChannelsOnBoard);
+	*rcunr = rcu;
+}
+
+bool TbbSettings::isBoardActive(int32 boardnr)
+{
+	if (itsActiveBoardsMask & (1 << boardnr)) return (true);
+	return (false);
+}
+
+bool TbbSettings::isBoardSelected(int32 boardnr)
+{
+	bool active = false;
+	
+	for (int cn = 0; cn < itsChannelsOnBoard; cn++) {
+		if (itsChannelInfo[(boardnr * itsChannelsOnBoard) + cn].Selected) active = true;		
+	}
+	return (active);
+}
 
 
-  } // namespace PACKAGE
-} // namespace LOFAR
+void TbbSettings::clearRcuSettings(int32 boardnr)
+{
+	for (int cn = 0; cn < itsChannelsOnBoard; cn++) {
+		itsChannelInfo[(boardnr * 16) + cn].Selected = false;
+		itsChannelInfo[(boardnr * 16) + cn].Status = 0;
+		itsChannelInfo[(boardnr * 16) + cn].State = 'F';
+		itsChannelInfo[(boardnr * 16) + cn].StartAddr = 0;
+		itsChannelInfo[(boardnr * 16) + cn].PageSize = 0;	
+	}		
+}
+
+void TbbSettings::logChannelInfo(int32 channel)
+{
+		LOG_DEBUG_STR(formatString("Channel %d ,Rcu %d = status[0x%04X] state[%c] addr[%u] pages[%u]"
+					, channel
+					, itsChannelInfo[channel].RcuNr
+					, itsChannelInfo[channel].Status
+					, itsChannelInfo[channel].State
+					, itsChannelInfo[channel].StartAddr
+					, itsChannelInfo[channel].PageSize));
+}
diff --git a/MAC/APL/PIC/TBBDriver/src/DriverSettings.h b/MAC/APL/PIC/TBBDriver/src/DriverSettings.h
index 0e81e06627af39c676ffe48c9cfd5f7120e99587..4999d1c9d907c4615ced085bcb89899332b4259b 100644
--- a/MAC/APL/PIC/TBBDriver/src/DriverSettings.h
+++ b/MAC/APL/PIC/TBBDriver/src/DriverSettings.h
@@ -1,4 +1,4 @@
-//#  DriverSettings.h: Global station settings
+//#  TbbSettings.h: Global station settings
 //#
 //#  Copyright (C) 2002-2004
 //#  ASTRON (Netherlands Foundation for Research in Astronomy)
@@ -23,126 +23,193 @@
 #ifndef LOFAR_RSP_STATIONSETTINGS_H
 #define LOFAR_RSP_STATIONSETTINGS_H
 
+#include <APL/TBB_Protocol/TBB_Protocol.ph>
+#include "TP_Protocol.ph"
 #include <GCF/TM/GCF_Control.h>
-//# Includes
-//#include <Common/LofarTypes.h>
+//#include <GCF/TM/GCF_ETHRawPort.h>
+//#include <GCF/TM/GCF_DevicePort.h>
+#include <Common/LofarTypes.h>
+
 
 
 namespace LOFAR {
   namespace TBB {
 
+// info for all channels
 struct ChannelInfo
 {
 	bool		Selected;
-	char		Status;
+	uint32	Status;
+	char		State;
+	int32		RcuNr;
 	int32		BoardNr;
 	int32		InputNr;
 	int32		MpNr;
 	uint32	StartAddr;
 	uint32	PageSize;
 };
-		
-		
+
+struct BoardInfo
+{
+	GCFPortInterface* port;
+	uint32	memorySize;
+	string	srcIp;
+	string	dstIp;
+	string	srcMac;
+	string	dstMac; 	
+};
+
 // forward declaration
 class TBBDriver;
 
-// class_description
-// ...
-class DriverSettings
+
+class TbbSettings
 {
 public:
-	DriverSettings ();
-	~DriverSettings();
-
-	static DriverSettings* instance();
+	TbbSettings ();
+	~TbbSettings();
 
+	static TbbSettings* instance();
+	
+	int32 driverVersion();
 	int32 maxBoards();
 	int32 maxChannels();
-	int32 nrMpsPerBoard();
-	int32 nrChannelsPerMp();
-	int32 nrChannelsPerBoard();
-	//uint32 channelMask(int32 boardnr);
+	int32 nrMpsOnBoard();
+	int32 nrChannelsOnMp();
+	int32 nrChannelsOnBoard();
+	int32 flashMaxPages();
+	int32 flashSectorsInPage();
+	int32 flashBlocksInPage();
+	int32 flashPageSize();
+	int32 flashPageSectorSize();
+	int32 flashPageBlockSize();
 	uint32 activeBoardsMask();
+	int32 maxRetries();
 	double timeout();
 	GCFPortInterface& boardPort(int32 boardnr);
-	
-	//void setChannelMask(int32 boardnr, uint32 channelmask);
 
-	char getChStatus(int32 channelnr);
-	bool getChSelected(int32 channelnr);
+	uint32 getChStatus(int32 channelnr);
+	char getChState(int32 channelnr);
+	bool isChSelected(int32 channelnr);
+	int32 getChRcuNr(int32 channelnr);
 	int32 getChBoardNr(int32 channelnr);
 	int32 getChInputNr(int32 channelnr);
 	int32 getChMpNr(int32 channelnr);
 	uint32 getChStartAddr(int32 channelnr);
 	uint32 getChPageSize(int32 channelnr);
+	
+	string getIfName();
+	string getSrcIp(int32 boardnr);
+	string getDstIp(int32 boardnr);
+	string getSrcMac(int32 boardnr);
+	string getDstMac(int32 boardnr);
 
 	void setChSelected(int32 channelnr, bool selected);
-	void setChStatus(int32 channelnr, char state);
+	void setChStatus(int32 channelnr, uint32 status);
+	void setChState(int32 channelnr, char state);
 	void setChStartAddr(int32 channelnr, uint32 startaddr);
 	void setChPageSize(int32 channelnr, uint32 pagesize);
 	
+	void convertRcu2Ch(int32 rcunr, int32 *boardnr, int32 *channelnr);
+	void convertCh2Rcu(int32 channelnr, int32 *rcunr);
+	bool isBoardActive(int32 boardnr);
+	bool isBoardSelected(int32 boardnr);
+	void logChannelInfo(int32 channel);
+		
 	uint32 getMemorySize(int32 boardnr);
 	void setMemorySize(int32 boardnr,uint32 pages);
 	
 	friend class TBBDriver;
 
 protected:	// note TBBDriver must be able to set them
+	void getTbbSettings();
+	void setConversionTable(int32 rcu, int32 channel); 
 	void setMaxBoards (int32 maxboards);
 	void setActiveBoards (uint32 activeboardsmask);
+	void setMaxRetries(int32 retries);
 	void setTimeOut(double timeout);
-	void setBoardPorts(GCFPortInterface* board_ports);
+	void setBoardPorts(int board, GCFPortInterface* board_ports);
+	void clearRcuSettings(int32 boardnr);
 	
 private:
 	// Copying is not allowed
-	DriverSettings(const DriverSettings&	that);
-	DriverSettings& operator=(const DriverSettings& that);
+	TbbSettings(const TbbSettings&	that);
+	TbbSettings& operator=(const TbbSettings& that);
 
-	//# --- Datamembers ---
+	// --- Datamembers ---
+	int32	itsDriverVersion;
 	int32	itsMaxBoards;	// constants
 	int32	itsMaxChannels;
-	int32	itsMpsPerBoard;
-	int32	itsChannelsPerMp;
-	int32 itsChannelsPerBoard;
+	int32	itsMpsOnBoard;
+	int32	itsChannelsOnMp;
+	int32 itsChannelsOnBoard;
+	int32 itsFlashMaxPages;
+	int32 itsFlashSectorsInPage;
+	int32 itsFlashBlocksInPage;
+	int32 itsFlashPageSize;
+	int32 itsFlashPageSectorSize;
+	int32 itsFlashPageBlockSize;
+	int32	itsMaxRetries;
 	double	itsTimeOut;
 
-	uint32	itsActiveBoardsMask;		// values depend on OPERATION_MODE
+	// mask with active boards
+	uint32	itsActiveBoardsMask;
 	
-	//uint32			*itsChannelMask;
-	ChannelInfo	*itsChannel;
-	uint32	*itsMemorySize;
-		
-	GCFPortInterface*		itsBoardPorts; // array of tbb board ports
-				
-	static DriverSettings* theirDriverSettings;
+	int32				*itsRcu2ChTable;
+	int32				*itsCh2RcuTable;
+	BoardInfo		*itsBoardInfo;
+	ChannelInfo	*itsChannelInfo;
+	string			itsIfName;
+	
+	static TbbSettings	*theirTbbSettings;
 };
+
+
 	
 //# --- inline functions ---
-inline	int32 DriverSettings::maxBoards()	{ return (itsMaxBoards);   }
-inline	int32 DriverSettings::maxChannels()	{ return (itsMaxChannels);   }
-inline	int32 DriverSettings::nrMpsPerBoard()	{ return (itsMpsPerBoard);   }
-inline	int32 DriverSettings::nrChannelsPerMp()	{ return (itsChannelsPerMp);   }
-inline	int32 DriverSettings::nrChannelsPerBoard()	{ return (itsChannelsPerBoard);   }
-inline	uint32 DriverSettings::activeBoardsMask()	{ return (itsActiveBoardsMask);   }
-inline	double DriverSettings::timeout()	{ return (itsTimeOut);   }
-inline	GCFPortInterface& DriverSettings::boardPort(int32 boardnr)	{ return (itsBoardPorts[boardnr]); }
+inline	int32 TbbSettings::driverVersion() { return (itsDriverVersion); }
+inline	int32 TbbSettings::maxBoards() { return (itsMaxBoards); }
+inline	int32 TbbSettings::maxChannels() { return (itsMaxChannels); }
+inline	int32 TbbSettings::nrMpsOnBoard() { return (itsMpsOnBoard); }
+inline	int32 TbbSettings::nrChannelsOnMp() { return (itsChannelsOnMp); }
+inline	int32 TbbSettings::nrChannelsOnBoard() { return (itsChannelsOnBoard); }
+inline	int32 TbbSettings::flashMaxPages() { return (itsFlashMaxPages); }
+inline	int32 TbbSettings::flashSectorsInPage() { return (itsFlashSectorsInPage); }
+inline	int32 TbbSettings::flashBlocksInPage() { return (itsFlashBlocksInPage); }
+inline	int32 TbbSettings::flashPageSize() { return (itsFlashPageSize); }
+inline	int32 TbbSettings::flashPageSectorSize() { return (itsFlashPageSectorSize); }
+inline	int32 TbbSettings::flashPageBlockSize() { return (itsFlashPageBlockSize); }
+inline	uint32 TbbSettings::activeBoardsMask()	{ return (itsActiveBoardsMask);   }
+inline	int32 TbbSettings::maxRetries()	{ return (itsMaxRetries);   }
+inline	double TbbSettings::timeout()	{ return (itsTimeOut);   }
+//inline	GCFPortInterface& TbbSettings::boardPort(int32 boardnr)	{ return (itsBoardPorts[boardnr]); }
+inline	GCFPortInterface& TbbSettings::boardPort(int32 boardnr)	{ return (*itsBoardInfo[boardnr].port); }
 
 //---- inline functions for channel information ------------
-inline	char DriverSettings::getChStatus(int32 channelnr) { return (itsChannel[channelnr].Status); }
-inline	bool DriverSettings::getChSelected(int32 channelnr) { return (itsChannel[channelnr].Selected); }
-inline	int32 DriverSettings::getChBoardNr(int32 channelnr) { return (itsChannel[channelnr].BoardNr); }
-inline	int32 DriverSettings::getChInputNr(int32 channelnr) { return (itsChannel[channelnr].InputNr); }
-inline	int32 DriverSettings::getChMpNr(int32 channelnr) { return (itsChannel[channelnr].MpNr); }
-inline	uint32 DriverSettings::getChStartAddr(int32 channelnr) { return (itsChannel[channelnr].StartAddr); }
-inline	uint32 DriverSettings::getChPageSize(int32 channelnr) { return (itsChannel[channelnr].PageSize); }
-
-inline	void DriverSettings::setChSelected(int32 channelnr, bool selected) { itsChannel[channelnr].Selected = selected; }
-inline	void DriverSettings::setChStatus(int32 channelnr, char state){ itsChannel[channelnr].Status = state; }
-inline	void DriverSettings::setChStartAddr(int32 channelnr, uint32 startaddr){ itsChannel[channelnr].StartAddr = startaddr; }
-inline	void DriverSettings::setChPageSize(int32 channelnr, uint32 pagesize){ itsChannel[channelnr].PageSize = pagesize; }
+inline	bool TbbSettings::isChSelected(int32 channelnr) { return (itsChannelInfo[channelnr].Selected); }
+inline	uint32 TbbSettings::getChStatus(int32 channelnr) { return (itsChannelInfo[channelnr].Status); }
+inline	char TbbSettings::getChState(int32 channelnr) { return (itsChannelInfo[channelnr].State); }
+inline	int32 TbbSettings::getChRcuNr(int32 channelnr) { return (itsChannelInfo[channelnr].RcuNr); }
+inline	int32 TbbSettings::getChBoardNr(int32 channelnr) { return (itsChannelInfo[channelnr].BoardNr); }
+inline	int32 TbbSettings::getChInputNr(int32 channelnr) { return (itsChannelInfo[channelnr].InputNr); }
+inline	int32 TbbSettings::getChMpNr(int32 channelnr) { return (itsChannelInfo[channelnr].MpNr); }
+inline	uint32 TbbSettings::getChStartAddr(int32 channelnr) { return (itsChannelInfo[channelnr].StartAddr); }
+inline	uint32 TbbSettings::getChPageSize(int32 channelnr) { return (itsChannelInfo[channelnr].PageSize); }
+inline	string TbbSettings::getIfName() { return(itsIfName); }
+inline	string TbbSettings::getSrcIp(int32 boardnr) { return(itsBoardInfo[boardnr].srcIp); }
+inline	string TbbSettings::getDstIp(int32 boardnr) { return(itsBoardInfo[boardnr].dstIp); }
+inline	string TbbSettings::getSrcMac(int32 boardnr) { return(itsBoardInfo[boardnr].srcMac); }
+inline	string TbbSettings::getDstMac(int32 boardnr) { return(itsBoardInfo[boardnr].dstMac); }
+
+inline	void TbbSettings::setChSelected(int32 channelnr, bool selected) { itsChannelInfo[channelnr].Selected = selected; }
+inline	void TbbSettings::setChStatus(int32 channelnr, uint32 status){ itsChannelInfo[channelnr].Status = status; }
+inline	void TbbSettings::setChState(int32 channelnr, char state){ itsChannelInfo[channelnr].State = state; }
+inline	void TbbSettings::setChStartAddr(int32 channelnr, uint32 startaddr){ itsChannelInfo[channelnr].StartAddr = startaddr; }
+inline	void TbbSettings::setChPageSize(int32 channelnr, uint32 pagesize){ itsChannelInfo[channelnr].PageSize = pagesize; }
 
 //---- inline functions for board information ------------
-inline	uint32 DriverSettings::getMemorySize(int32 boardnr) { return (itsMemorySize[boardnr]); }
-inline	void DriverSettings::setMemorySize(int32 boardnr,uint32 pages) { itsMemorySize[boardnr] = pages; }
+inline	uint32 TbbSettings::getMemorySize(int32 boardnr) { return (itsBoardInfo[boardnr].memorySize); }
+inline	void TbbSettings::setMemorySize(int32 boardnr,uint32 pages) { itsBoardInfo[boardnr].memorySize = pages; }
 
   } // namespace TBB
 } // namespace LOFAR
diff --git a/MAC/APL/PIC/TBBDriver/src/ErasefCmd.cc b/MAC/APL/PIC/TBBDriver/src/ErasefCmd.cc
index b30fe8376cdda71779baa2e4c757eff45ef92e07..fd1ce20de5880ed0e12d2f7695df24919184fa50 100644
--- a/MAC/APL/PIC/TBBDriver/src/ErasefCmd.cc
+++ b/MAC/APL/PIC/TBBDriver/src/ErasefCmd.cc
@@ -24,21 +24,38 @@
 #include <Common/LofarLogger.h>
 
 #include "ErasefCmd.h"
-#include "DriverSettings.h"
 
-namespace LOFAR {
-	using namespace TBB_Protocol;
-	using namespace TP_Protocol;
-	namespace TBB {
+
+using namespace LOFAR;
+using namespace TBB_Protocol;
+using namespace TP_Protocol;
+using	namespace TBB;
+
+// information about the flash memory
+static const int FL_SIZE 						= 64 * 1024 *1024; // 64 MB in bytes
+static const int FL_N_PAGES 				= 32; // 32 pages in flash
+static const int FL_N_SECTORS				= 512; // 512 sectors in flash
+static const int FL_N_BLOCKS				= 65536; // 65336 blocks in flash
+
+static const int FL_PAGE_SIZE 			= FL_SIZE / FL_N_PAGES; // 2.097.152 bytes  
+static const int FL_SECTOR_SIZE			= FL_SIZE / FL_N_SECTORS; // 131.072 bytes
+static const int FL_BLOCK_SIZE 			= FL_SIZE / FL_N_BLOCKS; // 1.024 bytes
+
+static const int FL_SECTORS_IN_PAGE	= FL_PAGE_SIZE / FL_SECTOR_SIZE; // 16 sectors per page
+static const int FL_BLOCKS_IN_SECTOR= FL_SECTOR_SIZE / FL_BLOCK_SIZE; // 128 blocks per sector
+static const int FL_BLOCKS_IN_PAGE	= FL_PAGE_SIZE / FL_BLOCK_SIZE; // 2048 blocks per page
 
 //--Constructors for a ErasefCmd object.----------------------------------------
 ErasefCmd::ErasefCmd():
-		itsBoardMask(0),itsBoardsMask(0),itsBoardStatus(0)
+		itsImage(0),itsSector(0),itsBoardStatus(0)
 {
+	TS					= TbbSettings::instance();
 	itsTPE 			= new TPErasefEvent();
 	itsTPackE 	= 0;
 	itsTBBE 		= 0;
-	itsTBBackE 	= new TBBErasefackEvent();
+	itsTBBackE 	= new TBBEraseImageAckEvent();
+	
+	setWaitAck(true);
 }
 	  
 //--Destructor for ErasefCmd.---------------------------------------------------
@@ -51,7 +68,7 @@ ErasefCmd::~ErasefCmd()
 // ----------------------------------------------------------------------------
 bool ErasefCmd::isValid(GCFEvent& event)
 {
-	if ((event.signal == TBB_ERASEF)||(event.signal == TP_ERASEFACK)) {
+	if ((event.signal == TBB_ERASE_IMAGE)||(event.signal == TP_ERASEFACK)) {
 		return(true);
 	}
 	return(false);
@@ -60,86 +77,63 @@ bool ErasefCmd::isValid(GCFEvent& event)
 // ----------------------------------------------------------------------------
 void ErasefCmd::saveTbbEvent(GCFEvent& event)
 {
-	itsTBBE 			= new TBBErasefEvent(event);
+	itsTBBE = new TBBEraseImageEvent(event);
 		
-	itsBoardMask = (1 << itsTBBE->board);
-	
-	// mask for the installed boards
-	itsBoardsMask = DriverSettings::instance()->activeBoardsMask();
+	setBoardNr(itsTBBE->board);
 	
-	// Send only commands to boards installed
-	itsBoardMask = itsBoardMask & itsBoardsMask;
+	itsTBBackE->status_mask = 0;
 	
-	itsTBBackE->status = 0;
+	itsImage = itsTBBE->image;
+	itsSector = (itsImage * FL_SECTORS_IN_PAGE);
 	
 	// initialize TP send frame
 	itsTPE->opcode	= TPERASEF;
 	itsTPE->status	=	0;
-	itsTPE->addr		= itsTBBE->addr;
 	
 	delete itsTBBE;	
 }
 
 // ----------------------------------------------------------------------------
-bool ErasefCmd::sendTpEvent(int32 boardnr, int32)
+void ErasefCmd::sendTpEvent()
 {
-	bool sending = false;
-	DriverSettings*		ds = DriverSettings::instance();
-	
-	if (ds->boardPort(boardnr).isConnected()) {
-		ds->boardPort(boardnr).send(*itsTPE);
-		ds->boardPort(boardnr).setTimer(ds->timeout());
-		sending = true;
-	}
-	else 
-		itsTBBackE->status |= CMD_ERROR;
-	
-	return(sending);
+	itsTPE->addr = static_cast<uint32>(itsSector * FL_SECTOR_SIZE);
+	TS->boardPort(getBoardNr()).send(*itsTPE);
+	TS->boardPort(getBoardNr()).setTimer((long)1); // erase time of sector = 500 mSec
 }
 
 // ----------------------------------------------------------------------------
-void ErasefCmd::saveTpAckEvent(GCFEvent& event, int32 boardnr)
+void ErasefCmd::saveTpAckEvent(GCFEvent& event)
 {
+	LOG_DEBUG_STR(formatString("Received ErasefAck from boardnr[%d]", getBoardNr()));
+	
 	// in case of a time-out, set error mask
 	if (event.signal == F_TIMER) {
-		itsTBBackE->status |= COMM_ERROR;
-	}
-	else {
+		itsTBBackE->status_mask |= TBB_COMM_ERROR;
+	} else {
 		itsTPackE = new TPErasefackEvent(event);
 		
 		itsBoardStatus	= itsTPackE->status;
-		
-		LOG_DEBUG_STR(formatString("Received ErasefAck from boardnr[%d]", boardnr));
+		if (itsBoardStatus == 0) {
+			itsSector++; 
+			
+			if (itsSector == ((itsImage + 1) * FL_SECTORS_IN_PAGE)) {
+				setDone(true);
+			}
+		}
 		delete itsTPackE;
 	}
+	
+	if (itsBoardStatus != 0) {
+		LOG_DEBUG_STR("Received status > 0  (ErasefCmd)");
+		setDone(true);
+	}
 }
 
 // ----------------------------------------------------------------------------
 void ErasefCmd::sendTbbAckEvent(GCFPortInterface* clientport)
 {
-	if (itsTBBackE->status == 0)
-			itsTBBackE->status = SUCCESS;
-
+	if (itsTBBackE->status_mask == 0) {
+		itsTBBackE->status_mask = TBB_SUCCESS;
+	}
 	clientport->send(*itsTBBackE);
 }
-
-// ----------------------------------------------------------------------------
-CmdTypes ErasefCmd::getCmdType()
-{
-	return(BoardCmd);
-}
-
-// ----------------------------------------------------------------------------
-uint32 ErasefCmd::getBoardMask()
-{
-	return(itsBoardMask);
-}
-
-// ----------------------------------------------------------------------------
-bool ErasefCmd::waitAck()
-{
-	return(true);
-}
-
-	} // end TBB namespace
-} // end LOFAR namespace
diff --git a/MAC/APL/PIC/TBBDriver/src/ErasefCmd.h b/MAC/APL/PIC/TBBDriver/src/ErasefCmd.h
index 938db8c7a78901bd53dd3d15fa9ff6067b592f39..899c40e0e433ad78029653ec0e1a6e60e68d0f25 100644
--- a/MAC/APL/PIC/TBBDriver/src/ErasefCmd.h
+++ b/MAC/APL/PIC/TBBDriver/src/ErasefCmd.h
@@ -32,6 +32,7 @@
 #include "TP_Protocol.ph"
 
 #include "Command.h"
+#include "DriverSettings.h"
 
 namespace LOFAR {
 	using namespace TBB_Protocol;
@@ -50,26 +51,22 @@ namespace LOFAR {
 				
 				virtual void saveTbbEvent(GCFEvent& event);
 									
-				virtual bool sendTpEvent(int32 boardnr, int32 channelnr);
+				virtual void sendTpEvent();
 
-				virtual void saveTpAckEvent(GCFEvent& event, int32 boardnr);
+				virtual void saveTpAckEvent(GCFEvent& event);
 
 				virtual void sendTbbAckEvent(GCFPortInterface* clientport);
-				
-				virtual uint32 getBoardMask();
-				
-				virtual bool waitAck();
-				
-				virtual CmdTypes getCmdType();
-      
+				      
 			private:
-				uint32	itsBoardMask;  // mask indicates the boards to communicate with
-				uint32	itsBoardsMask;	// Installed boards mask
+				TbbSettings *TS;
+
+				TPErasefEvent					*itsTPE;
+				TPErasefackEvent			*itsTPackE;
+				TBBEraseImageEvent		*itsTBBE;
+				TBBEraseImageAckEvent	*itsTBBackE;
 				
-				TPErasefEvent			*itsTPE;
-				TPErasefackEvent	*itsTPackE;
-				TBBErasefEvent		*itsTBBE;
-				TBBErasefackEvent	*itsTBBackE;
+				int32				itsImage;
+				int32				itsSector;
 				
 				// variables holding data from tp cmd
 				uint32	itsBoardStatus;
diff --git a/MAC/APL/PIC/TBBDriver/src/FreeCmd.cc b/MAC/APL/PIC/TBBDriver/src/FreeCmd.cc
index 77320ac954bb2e68c8994cf58356ba582e6be12c..82e66a0053955c748eb5cbd92904f74bea62a612 100644
--- a/MAC/APL/PIC/TBBDriver/src/FreeCmd.cc
+++ b/MAC/APL/PIC/TBBDriver/src/FreeCmd.cc
@@ -24,26 +24,27 @@
 #include <Common/LofarLogger.h>
 
 #include "FreeCmd.h"
-#include "DriverSettings.h"
 
-namespace LOFAR {
-	using namespace TBB_Protocol;
-	using namespace TP_Protocol;
-	namespace TBB {
+using namespace LOFAR;
+using namespace TBB_Protocol;
+using namespace TP_Protocol;
+using	namespace TBB;
 
 //--Constructors for a FreeCmd object.----------------------------------------
 FreeCmd::FreeCmd():
-		itsBoardMask(0),itsBoardsMask(0),itsChannel(0)
+		itsBoardNr(0),itsBoardFreeAll(0),itsRcuStatus(0)
 {
+	TS					= TbbSettings::instance();
 	itsTPE 			= new TPFreeEvent();
 	itsTPackE 	= 0;
 	itsTBBE 		= 0;
 	itsTBBackE 	= new TBBFreeackEvent();
 	
 	for(int boardnr = 0;boardnr < MAX_N_TBBBOARDS;boardnr++) { 
-		itsTBBackE->status[boardnr]	= 0;
+		itsTBBackE->status_mask[boardnr]	= 0;
 		itsChannelMask[boardnr]	= 0;
 	}
+	setWaitAck(true);
 }
 	  
 //--Destructor for FreeCmd.---------------------------------------------------
@@ -65,115 +66,143 @@ bool FreeCmd::isValid(GCFEvent& event)
 // ----------------------------------------------------------------------------
 void FreeCmd::saveTbbEvent(GCFEvent& event)
 {
-	itsTBBE 			= new TBBFreeEvent(event);
-
-	// mask for the installed boards
-	itsBoardsMask = DriverSettings::instance()->activeBoardsMask();
-		
-	for (int boardnr = 0; boardnr < DriverSettings::instance()->maxBoards(); boardnr++) {
-		
-		if (!(itsBoardsMask & (1 << boardnr))) 
-			itsTBBackE->status[boardnr] |= NO_BOARD;
-		
-		itsChannelMask[boardnr] = itsTBBE->channelmask[boardnr];
-		
-		if (itsChannelMask[boardnr] != 0)
-			itsBoardMask |= (1 << boardnr);
+	itsTBBE = new TBBFreeEvent(event);
+	
+	// convert rcu-bitmask to tbb-channelmask
+	int boardnr;
+	int channelnr;
+	for (int rcunr = 0; rcunr < TS->maxChannels(); rcunr++) {
+		if(itsTBBE->rcu_mask.test(rcunr)) {
+			TS->convertRcu2Ch(rcunr,&boardnr,&channelnr);	
+			itsChannelMask[boardnr] |= (1 << channelnr);
+			TS->setChSelected(((boardnr * 16) + channelnr),true);
+		}
+		//else
+		//	TS->setChSelected(((boardnr * 16) + channelnr),false);
+	} 
+	
+	uint32 boardmask = 0;		
+	for (int boardnr = 0; boardnr < TS->maxBoards(); boardnr++) {
+		if (itsChannelMask[boardnr] != 0) boardmask |= (1 << boardnr); 
 			
+		if (!TS->isBoardActive(boardnr)) 
+			itsTBBackE->status_mask[boardnr] |= TBB_NO_BOARD;
+		
 		if ((itsChannelMask[boardnr] & ~0xFFFF) != 0) 
-			itsTBBackE->status[boardnr] |= (SELECT_ERROR | CHANNEL_SEL_ERROR);
+			itsTBBackE->status_mask[boardnr] |= (TBB_SELECT_ERROR | TBB_CHANNEL_SEL_ERROR);
 				
-		if (!(itsBoardsMask & (1 << boardnr)) &&  (itsChannelMask[boardnr] != 0))
-			itsTBBackE->status[boardnr] |= (SELECT_ERROR | BOARD_SEL_ERROR);
-		LOG_DEBUG_STR(formatString("FreeCmd savetbb status board[%d]= 0x%08X",boardnr,itsTBBackE->status[boardnr]));
+		if (!TS->isBoardActive(boardnr) &&  (itsChannelMask[boardnr] != 0))
+			itsTBBackE->status_mask[boardnr] |= (TBB_SELECT_ERROR | TBB_BOARD_SEL_ERROR);
+		LOG_DEBUG_STR(formatString("FreeCmd savetbb status board[%d] = 0x%08X",boardnr,itsTBBackE->status_mask[boardnr]));
 	}
 	
-	// Send only commands to boards installed
-	itsBoardMask = itsBoardMask & itsBoardsMask;
+	setBoardMask(boardmask);
+	
+	// select firt channel to handle
+	nextChannelNr();
 	
 	// initialize TP send frame
 	itsTPE->opcode			= TPFREE;
 	itsTPE->status			= 0;
-		
+	
+	itsBoardFreeAll = false;	
 	delete itsTBBE;
 }
 
 // ----------------------------------------------------------------------------
-bool FreeCmd::sendTpEvent(int32 boardnr, int32 channelnr)
+void FreeCmd::sendTpEvent()
 {
-	bool sending = false;
-	DriverSettings*		ds = DriverSettings::instance();
-
-	itsTPE->channel = ds->getChInputNr(channelnr); 
-	itsChannel = channelnr;
+	itsRcuStatus = 0;
+	
+	if (itsBoardNr != getBoardNr()) itsBoardFreeAll = false; // new board
+	itsBoardNr = getBoardNr();
 	
-	if 	(ds->boardPort(boardnr).isConnected() && 
-			(itsTBBackE->status[boardnr] == 0)) {
+	if (!itsBoardFreeAll) {
 		
-		ds->boardPort(boardnr).send(*itsTPE);
-		ds->boardPort(boardnr).setTimer(ds->timeout());
-		sending = true;
-		LOG_DEBUG_STR(formatString("Sending FreeCmd to boardnr[%d], channel[%d]", boardnr, channelnr));
+		if ((itsChannelMask[getBoardNr()] == 0xFFFF) && ((getChannelNr()% 16) == 0)) {
+			itsTPE->channel = 0xFFFFFFFF; // uint32 -> -1 to free all
+			itsBoardFreeAll = true;
+		} else {
+			itsTPE->channel = TS->getChInputNr(getChannelNr()); 
+		}
+				
+		if (itsTBBackE->status_mask[getBoardNr()] == 0) {
+			TS->boardPort(getBoardNr()).send(*itsTPE);
+			
+			LOG_DEBUG_STR(formatString("Sending FreeCmd to boardnr[%d], channel[%08X]", getBoardNr(), itsTPE->channel));
+		} 
 	}
-	else
-		itsTBBackE->status[boardnr] |= CMD_ERROR;
-	
-	return(sending);
+	TS->boardPort(getBoardNr()).setTimer(TS->timeout());
 }
 
 // ----------------------------------------------------------------------------
-void FreeCmd::saveTpAckEvent(GCFEvent& event, int32 boardnr)
+void FreeCmd::saveTpAckEvent(GCFEvent& event)
 {
+	int32 channels = 1;
+	
+	if (itsBoardFreeAll) channels = 16;
+	
 	// in case of a time-out, set error mask
 	if (event.signal == F_TIMER) {
-		itsTBBackE->status[boardnr] |= COMM_ERROR;
+		itsTBBackE->status_mask[getBoardNr()] |= TBB_RCU_COMM_ERROR;
+		itsRcuStatus |= TBB_TIMEOUT_ETH;
 	}
 	else {
 		itsTPackE = new TPFreeackEvent(event);
 		
 		if ((itsTPackE->status >= 0xF0) && (itsTPackE->status <= 0xF6)) 
-			itsTBBackE->status[boardnr] |= (1 << (16 + (itsTPackE->status & 0x0F)));
-		
-		if (itsTPackE->status == 0) {
-			DriverSettings::instance()->setChSelected(itsChannel, false); 	
-			DriverSettings::instance()->setChStatus(itsChannel, 'F'); 	
-			DriverSettings::instance()->setChStartAddr(itsChannel, 0);
-			DriverSettings::instance()->setChPageSize(itsChannel, 0); 	
-		}
+			itsRcuStatus |= (1 << (16 + (itsTPackE->status & 0x0F)));
+				
+		if ((itsTPackE->status == 0) && (itsRcuStatus == 0)) {
+			for (int ch = getChannelNr(); ch < (getChannelNr() + channels); ch++) {
+				TS->setChSelected(ch, false); 	
+				TS->setChState(ch, 'F'); 	
+				TS->setChStartAddr(ch, 0);
+				TS->setChPageSize(ch, 0); 
+			}
+		} 
 			
-		LOG_DEBUG_STR(formatString("Received FreeAck from boardnr[%d]", boardnr));
+		LOG_DEBUG_STR(formatString("Received FreeAck from boardnr[%d]", getBoardNr()));
 		delete itsTPackE;
 	}
+	
+	for (int ch = getChannelNr(); ch < (getChannelNr() + channels); ch++) {
+		if (itsRcuStatus) TS->setChState(ch, 'E');
+		TS->setChStatus(ch,(uint16)(itsRcuStatus >> 16));
+	}
+	
+	if (itsRcuStatus || itsTBBackE->status_mask[getBoardNr()]) {
+		int32 rcu;
+		TS->convertCh2Rcu(getChannelNr(),&rcu);
+		if (channels == 1)
+			LOG_INFO_STR(formatString("ERROR FreeCmd Rcu[%d], DriverStatus[0x%x], RcuStatus[0x%x]",
+				rcu, itsTBBackE->status_mask[getBoardNr()],itsRcuStatus));
+		else
+			LOG_INFO_STR(formatString("ERROR FreeCmd Rcu[%d .. %d], DriverStatus[0x%x], RcuStatus[0x%x]",
+				(getBoardNr() * 16),((getBoardNr() + 1) * 16), itsTBBackE->status_mask[getBoardNr()],itsRcuStatus));
+	}
+	itsTBBackE->status_mask[getBoardNr()] |= itsRcuStatus;
+	
+	nextChannelNr();
 }
 
 // ----------------------------------------------------------------------------
 void FreeCmd::sendTbbAckEvent(GCFPortInterface* clientport)
 {
-	for (int32 boardnr = 0; boardnr < DriverSettings::instance()->maxBoards(); boardnr++) { 
-		if (itsTBBackE->status[boardnr] == 0)
-			itsTBBackE->status[boardnr] = SUCCESS;
+	int32 rcunr;
+	
+	itsTBBackE->rcu_mask.reset();
+	for (int32 channelnr = 0; channelnr < TS->maxChannels(); channelnr++) {
+		if (TS->getChStatus(channelnr)) {
+			TS->convertCh2Rcu(channelnr,&rcunr);
+			itsTBBackE->rcu_mask.set(rcunr);
+		}
+	}
+	
+	for (int32 boardnr = 0; boardnr < TS->maxBoards(); boardnr++) { 
+		if (itsTBBackE->status_mask[boardnr] == 0)
+			itsTBBackE->status_mask[boardnr] = TBB_SUCCESS;
 	}
  
 	clientport->send(*itsTBBackE);
 }
-
-// ----------------------------------------------------------------------------
-CmdTypes FreeCmd::getCmdType()
-{
-	return(ChannelCmd);
-}
-
-// ----------------------------------------------------------------------------
-uint32 FreeCmd::getBoardMask()
-{
-	return(itsBoardMask);
-}
-
-// ----------------------------------------------------------------------------
-bool FreeCmd::waitAck()
-{
-	return(true);
-}
-
-	} // end TBB namespace
-} // end LOFAR namespace
diff --git a/MAC/APL/PIC/TBBDriver/src/FreeCmd.h b/MAC/APL/PIC/TBBDriver/src/FreeCmd.h
index b5de203f33ab6f3a2e54900d5320fbc4089869ad..39237391cceac75622c91d47dda6f3b93ee1c044 100644
--- a/MAC/APL/PIC/TBBDriver/src/FreeCmd.h
+++ b/MAC/APL/PIC/TBBDriver/src/FreeCmd.h
@@ -32,6 +32,7 @@
 #include "TP_Protocol.ph"
 
 #include "Command.h"
+#include "DriverSettings.h"
 
 namespace LOFAR {
 	using namespace TBB_Protocol;
@@ -50,23 +51,19 @@ namespace LOFAR {
 				
 				virtual void saveTbbEvent(GCFEvent& event);
 									
-				virtual bool sendTpEvent(int32 boardnr, int32 channelnr);
+				virtual void sendTpEvent();
 
-				virtual void saveTpAckEvent(GCFEvent& event, int32 boardnr);
+				virtual void saveTpAckEvent(GCFEvent& event);
 
 				virtual void sendTbbAckEvent(GCFPortInterface* clientport);
 				
-				virtual uint32 getBoardMask();
-				
-				virtual bool waitAck();
-				
-				virtual CmdTypes getCmdType();
-      
 			private:
-				uint32	itsBoardMask;  // mask indicates the boards to communicate with
-				uint32	itsBoardsMask;	// Installed boards mask
+				TbbSettings *TS;
+				
+				int32		itsBoardNr;
 				uint32	itsChannelMask[MAX_N_TBBBOARDS];
-				int32		itsChannel;
+				bool		itsBoardFreeAll;
+				uint32	itsRcuStatus;
 				
 				TPFreeEvent			*itsTPE;
 				TPFreeackEvent	*itsTPackE;
diff --git a/MAC/APL/PIC/TBBDriver/src/ImageInfoCmd.cc b/MAC/APL/PIC/TBBDriver/src/ImageInfoCmd.cc
new file mode 100644
index 0000000000000000000000000000000000000000..62ff78f2641f11744bfbcd05949c14382dc76b40
--- /dev/null
+++ b/MAC/APL/PIC/TBBDriver/src/ImageInfoCmd.cc
@@ -0,0 +1,136 @@
+//#  ImageInfoCmd.cc: implementation of the ImageInfoCmd 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 "ImageInfoCmd.h"
+
+using namespace LOFAR;
+using namespace TBB_Protocol;
+using namespace TP_Protocol;
+using	namespace TBB;
+
+// information about the flash memory
+static const int FL_SIZE 						= 64 * 1024 *1024; // 64 MB in bytes
+static const int FL_N_PAGES 				= 32; // 32 pages in flash
+static const int FL_N_SECTORS				= 512; // 512 sectors in flash
+static const int FL_N_BLOCKS				= 65536; // 65336 blocks in flash
+
+static const int FL_PAGE_SIZE 			= FL_SIZE / FL_N_PAGES; // 2.097.152 bytes  
+static const int FL_SECTOR_SIZE			= FL_SIZE / FL_N_SECTORS; // 131.072 bytes
+static const int FL_BLOCK_SIZE 			= FL_SIZE / FL_N_BLOCKS; // 1.024 bytes
+
+static const int FL_SECTORS_IN_PAGE	= FL_PAGE_SIZE / FL_SECTOR_SIZE; // 16 sectors per page
+static const int FL_BLOCKS_IN_SECTOR= FL_SECTOR_SIZE / FL_BLOCK_SIZE; // 128 blocks per sector
+static const int FL_BLOCKS_IN_PAGE	= FL_PAGE_SIZE / FL_BLOCK_SIZE; // 2048 blocks per page
+
+static const int IMAGE_SIZE					= 977489; // 977489 bytes in 1 image 
+static const int IMAGE_BLOCKS				= IMAGE_SIZE / FL_BLOCK_SIZE; // 977489 bytes in 1 image 
+
+
+//--Constructors for a ImageInfoCmd object.----------------------------------------
+ImageInfoCmd::ImageInfoCmd():
+		itsImage(0),itsBlock(0),itsBoardStatus(0)
+{
+	TS					= TbbSettings::instance();
+	itsTPE 			= new TPReadfEvent();
+	itsTPackE 	= 0;
+	itsTBBE 		= 0;
+	itsTBBackE 	= new TBBImageInfoAckEvent();
+	setWaitAck(true);
+}
+	  
+//--Destructor for ImageInfoCmd.---------------------------------------------------
+ImageInfoCmd::~ImageInfoCmd()
+{
+	delete itsTPE;
+	delete itsTBBackE;
+}
+
+// ----------------------------------------------------------------------------
+bool ImageInfoCmd::isValid(GCFEvent& event)
+{
+	if ((event.signal == TBB_IMAGE_INFO)||(event.signal == TP_READFACK)) {
+		return(true);
+	}
+	return(false);
+}
+
+// ----------------------------------------------------------------------------
+void ImageInfoCmd::saveTbbEvent(GCFEvent& event)
+{
+	itsTBBE = new TBBImageInfoEvent(event);
+	
+	setBoardNr(itsTBBE->board);	
+	
+	itsTBBackE->status_mask = 0;
+	
+	itsImage = 0;
+		
+	// initialize TP send frame
+	itsTPE->opcode	= TPREADF;
+	itsTPE->status	=	0;
+	
+	delete itsTBBE;	
+}
+
+// ----------------------------------------------------------------------------
+void ImageInfoCmd::sendTpEvent()
+{
+	itsBlock = (itsImage * FL_BLOCKS_IN_PAGE) + (FL_BLOCKS_IN_PAGE - 1);
+	itsTPE->addr		= static_cast<uint32>(itsBlock * FL_BLOCK_SIZE);
+	TS->boardPort(getBoardNr()).send(*itsTPE);
+	TS->boardPort(getBoardNr()).setTimer(0.5);
+}
+
+// ----------------------------------------------------------------------------
+void ImageInfoCmd::saveTpAckEvent(GCFEvent& event)
+{
+	// in case of a time-out, set error mask
+	if (event.signal == F_TIMER) {
+		itsTBBackE->status_mask |= TBB_COMM_ERROR;
+		setDone(true);	
+	} else {
+		itsTPackE = new TPReadfackEvent(event);
+		
+		if (itsTPackE->status == 0) {
+			itsTBBackE->image_version[itsImage]= itsTPackE->data[0];	  
+			itsTBBackE->write_date[itsImage] = itsTPackE->data[1];		  		
+		
+			itsImage++;
+			if (itsImage == 32) {
+				setDone(true);
+			}
+		}
+		delete itsTPackE;
+	}
+}
+
+// ----------------------------------------------------------------------------
+void ImageInfoCmd::sendTbbAckEvent(GCFPortInterface* clientport)
+{
+	if (itsTBBackE->status_mask == 0)
+			itsTBBackE->status_mask = TBB_SUCCESS;
+	
+	clientport->send(*itsTBBackE);
+}
diff --git a/MAC/APL/PIC/TBBDriver/src/ImageInfoCmd.h b/MAC/APL/PIC/TBBDriver/src/ImageInfoCmd.h
new file mode 100644
index 0000000000000000000000000000000000000000..2a98972dfc49b9d939db39e898b7a0c913b44d87
--- /dev/null
+++ b/MAC/APL/PIC/TBBDriver/src/ImageInfoCmd.h
@@ -0,0 +1,77 @@
+//#  -*- mode: c++ -*-
+//#
+//#  ImageInfoCmd.h: III
+//#
+//#  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 IMAGEINFOCMD_H_
+#define IMAGEINFOCMD_H_
+
+#include <Common/LofarTypes.h>
+#include <GCF/TM/GCF_Control.h>
+
+#include <APL/TBB_Protocol/TBB_Protocol.ph>
+#include "TP_Protocol.ph"
+
+#include "Command.h"
+#include "DriverSettings.h"
+
+namespace LOFAR {
+	using namespace TBB_Protocol;
+  namespace TBB {
+
+		class ImageInfoCmd : public Command 
+		{
+			public:
+				// Constructors for a ImageInfoCmd object.
+				ImageInfoCmd();
+	  
+				// Destructor for ImageInfoCmd.
+				virtual ~ImageInfoCmd();
+				
+				virtual bool isValid(GCFEvent& event);
+				
+				virtual void saveTbbEvent(GCFEvent& event);
+									
+				virtual void sendTpEvent();
+
+				virtual void saveTpAckEvent(GCFEvent& event);
+
+				virtual void sendTbbAckEvent(GCFPortInterface* clientport);
+				
+			private:
+				TbbSettings *TS;
+				
+				TPReadfEvent					*itsTPE;
+				TPReadfackEvent				*itsTPackE;
+				TBBImageInfoEvent			*itsTBBE;
+				TBBImageInfoAckEvent	*itsTBBackE;
+				
+				int32				itsImage;
+				int32				itsBlock;
+				
+				// variables holding data from tp cmd
+				uint32	itsBoardStatus;
+		};
+	} // end TBB namespace
+} // end LOFAR namespace
+
+#endif /* IMAGEINFOCMD_H_ */
diff --git a/MAC/APL/PIC/TBBDriver/src/Makefile.am b/MAC/APL/PIC/TBBDriver/src/Makefile.am
index 199d49c48ae2546f5442238c62c519664887e48d..19eaa38c010d6b0148a056e0c62b0301ec999ea7 100644
--- a/MAC/APL/PIC/TBBDriver/src/Makefile.am
+++ b/MAC/APL/PIC/TBBDriver/src/Makefile.am
@@ -53,9 +53,10 @@ libtp_protocol_la_SOURCES = \
 libtbbdriver_la_SOURCES = \
 	$(noinst_HEADERS) \
 	DriverSettings.cc \
+	Command.cc \
+	AllocCmd.cc \
 	BoardCmdHandler.cc \
 	MsgHandler.cc \
-	AllocCmd.cc \
 	FreeCmd.cc \
 	RecordCmd.cc \
 	StopCmd.cc \
@@ -72,6 +73,7 @@ libtbbdriver_la_SOURCES = \
 	ErasefCmd.cc \
 	ReadfCmd.cc \
 	WritefCmd.cc \
+	ImageInfoCmd.cc \
 	ReadwCmd.cc \
 	WritewCmd.cc \
 	ReadrCmd.cc \
@@ -80,10 +82,10 @@ libtbbdriver_la_SOURCES = \
 
 noinst_HEADERS = \
 	DriverSettings.h \
-	BoardCmdHandler.h \
-	MsgHandler.h \
 	Command.h \
 	AllocCmd.h \
+	BoardCmdHandler.h \
+	MsgHandler.h \
 	FreeCmd.h \
 	RecordCmd.h \
 	StopCmd.h \
@@ -100,6 +102,7 @@ noinst_HEADERS = \
 	ErasefCmd.h \
 	ReadfCmd.h \
 	WritefCmd.h	\
+	ImageInfoCmd.h \
 	ReadwCmd.h \
 	WritewCmd.h	\
 	ReadrCmd.h \
diff --git a/MAC/APL/PIC/TBBDriver/src/PageperiodCmd.cc b/MAC/APL/PIC/TBBDriver/src/PageperiodCmd.cc
index b6c875cb384f972d1e7b52e75f2071e455c475e7..b5a61474827d9e816cf7a7b47a6b45464d5a37c8 100644
--- a/MAC/APL/PIC/TBBDriver/src/PageperiodCmd.cc
+++ b/MAC/APL/PIC/TBBDriver/src/PageperiodCmd.cc
@@ -24,21 +24,22 @@
 #include <Common/LofarLogger.h>
 
 #include "PageperiodCmd.h"
-#include "DriverSettings.h"
 
-namespace LOFAR {
-	using namespace TBB_Protocol;
-	using namespace TP_Protocol;
-	namespace TBB {
+using namespace LOFAR;
+using namespace TBB_Protocol;
+using namespace TP_Protocol;
+using namespace TBB;
 
 //--Constructors for a PageperiodCmd object.----------------------------------------
 PageperiodCmd::PageperiodCmd():
-		itsBoardMask(0),itsBoardsMask(0),itsBoardStatus(0)
+		itsBoardStatus(0)
 {
+	TS					= TbbSettings::instance();
 	itsTPE 			= new TPPageperiodEvent();
 	itsTPackE 	= 0;
 	itsTBBE 		= 0;
 	itsTBBackE 	= new TBBPageperiodackEvent();
+	setWaitAck(true);
 }
 	  
 //--Destructor for PageperiodCmd.---------------------------------------------------
@@ -60,48 +61,37 @@ bool PageperiodCmd::isValid(GCFEvent& event)
 // ----------------------------------------------------------------------------
 void PageperiodCmd::saveTbbEvent(GCFEvent& event)
 {
-	itsTBBE 			= new TBBPageperiodEvent(event);
-		
-	itsBoardMask = (1 << DriverSettings::instance()->getChBoardNr((int32)itsTBBE->channel));
+	itsTBBE = new TBBPageperiodEvent(event);
 	
-	itsBoardsMask = DriverSettings::instance()->activeBoardsMask();
+	int32 boardnr;
+	int32 channelnr;
+	TS->convertRcu2Ch(itsTBBE->channel,&boardnr,&channelnr);
 		
-	// Send only commands to boards installed
-	itsBoardMask = itsBoardMask & itsBoardsMask;
-	
-	itsTBBackE->status = 0;
+	setBoardNr(boardnr);
+			
+	itsTBBackE->status_mask = 0;
 	
 	// initialize TP send frame
 	itsTPE->opcode			= TPPAGEPERIOD;
 	itsTPE->status			=	0;
-	itsTPE->channel 		= itsTBBE->channel; 
+	itsTPE->channel 		= channelnr; 
 	
 	delete itsTBBE;	
 }
 
 // ----------------------------------------------------------------------------
-bool PageperiodCmd::sendTpEvent(int32 boardnr, int32)
+void PageperiodCmd::sendTpEvent()
 {
-	bool sending = false;
-	DriverSettings*		ds = DriverSettings::instance();
-	
-	if (ds->boardPort(boardnr).isConnected()) {
-		ds->boardPort(boardnr).send(*itsTPE);
-		ds->boardPort(boardnr).setTimer(ds->timeout());
-		sending = true;
-	}
-	else 
-		itsTBBackE->status |= CMD_ERROR;
-	
-	return(sending);
+	TS->boardPort(getBoardNr()).send(*itsTPE);
+	TS->boardPort(getBoardNr()).setTimer(TS->timeout());
 }
 
 // ----------------------------------------------------------------------------
-void PageperiodCmd::saveTpAckEvent(GCFEvent& event, int32 boardnr)
+void PageperiodCmd::saveTpAckEvent(GCFEvent& event)
 {
 	// in case of a time-out, set error mask
 	if (event.signal == F_TIMER) {
-		itsTBBackE->status |= COMM_ERROR;
+		itsTBBackE->status_mask |= TBB_COMM_ERROR;
 	}
 	else {
 		itsTPackE = new TPPageperiodackEvent(event);
@@ -109,37 +99,17 @@ void PageperiodCmd::saveTpAckEvent(GCFEvent& event, int32 boardnr)
 		itsBoardStatus 					= itsTPackE->status;
 		itsTBBackE->pageperiod	= itsTPackE->pageperiod;
 		
-		LOG_DEBUG_STR(formatString("Received PageperiodAck from boardnr[%d]", boardnr));
+		LOG_DEBUG_STR(formatString("Received PageperiodAck from boardnr[%d]", getBoardNr()));
 		delete itsTPackE;
 	}
+	setDone(true);
 }
 
 // ----------------------------------------------------------------------------
 void PageperiodCmd::sendTbbAckEvent(GCFPortInterface* clientport)
 {
-	if (itsTBBackE->status == 0)
-			itsTBBackE->status = SUCCESS;
+	if (itsTBBackE->status_mask == 0)
+			itsTBBackE->status_mask = TBB_SUCCESS;
 	 
 	clientport->send(*itsTBBackE);
 }
-
-// ----------------------------------------------------------------------------
-CmdTypes PageperiodCmd::getCmdType()
-{
-	return(ChannelCmd);
-}
-
-// ----------------------------------------------------------------------------
-uint32 PageperiodCmd::getBoardMask()
-{
-	return(itsBoardMask);
-}
-
-// ----------------------------------------------------------------------------
-bool PageperiodCmd::waitAck()
-{
-	return(true);
-}
-
-	} // end TBB namespace
-} // end LOFAR namespace
diff --git a/MAC/APL/PIC/TBBDriver/src/PageperiodCmd.h b/MAC/APL/PIC/TBBDriver/src/PageperiodCmd.h
index 0eec446076cc08a9aa9bab374e989c9eee857961..7307f6ea3c0606743ab25f473ffe52c9ef8a3d8e 100644
--- a/MAC/APL/PIC/TBBDriver/src/PageperiodCmd.h
+++ b/MAC/APL/PIC/TBBDriver/src/PageperiodCmd.h
@@ -32,6 +32,7 @@
 #include "TP_Protocol.ph"
 
 #include "Command.h"
+#include "DriverSettings.h"
 
 namespace LOFAR {
 	using namespace TBB_Protocol;
@@ -50,21 +51,14 @@ namespace LOFAR {
 				
 				virtual void saveTbbEvent(GCFEvent& event);
 									
-				virtual bool sendTpEvent(int32 boardnr, int32 channelnr);
+				virtual void sendTpEvent();
 
-				virtual void saveTpAckEvent(GCFEvent& event, int32 boardnr);
+				virtual void saveTpAckEvent(GCFEvent& event);
 
 				virtual void sendTbbAckEvent(GCFPortInterface* clientport);
-				
-				virtual uint32 getBoardMask();
-				
-				virtual bool waitAck();
-				
-				virtual CmdTypes getCmdType();
       
 			private:
-				uint32	itsBoardMask;  // mask indicates the boards to communicate with
-				uint32	itsBoardsMask;	// Installed boards mask
+				TbbSettings *TS;
 				
 				TPPageperiodEvent			*itsTPE;
 				TPPageperiodackEvent	*itsTPackE;
diff --git a/MAC/APL/PIC/TBBDriver/src/RawEvent.cc b/MAC/APL/PIC/TBBDriver/src/RawEvent.cc
index 2581c805ca039e6ad16b4fe91e2992c1aac56963..b2d753efbbda68d8398f59d52987022d7b926482 100644
--- a/MAC/APL/PIC/TBBDriver/src/RawEvent.cc
+++ b/MAC/APL/PIC/TBBDriver/src/RawEvent.cc
@@ -60,7 +60,7 @@ GCFEvent::TResult RawEvent::dispatch(GCFTask& task, GCFPortInterface& port)
   if (size < OPCODE_LEN) return(GCFEvent::NOT_HANDLED);
   
 	
-  LOG_DEBUG(formatString("in RawEvent::F_DATAIN: Opcode=0x%08x",buf.opcode));
+  //LOG_DEBUG(formatString("in RawEvent::F_DATAIN: Opcode=0x%08x",buf.opcode));
  
   //
   // If no error, lookup buf.opcode number, else assign ACK_ERROR buf.event.signal number
@@ -81,7 +81,7 @@ GCFEvent::TResult RawEvent::dispatch(GCFTask& task, GCFPortInterface& port)
   		buf.event.length = 8;
   		break;
 	 case TPSTOP:
-  		buf.event.signal = TP_RECORDACK;
+  		buf.event.signal = TP_STOPACK;
   		buf.event.length = 8;
   		break;
 	 case TPTRIGGER:
diff --git a/MAC/APL/PIC/TBBDriver/src/ReadCmd.cc b/MAC/APL/PIC/TBBDriver/src/ReadCmd.cc
index 7874c5875f64f5e5504f9be11b83b9198016d461..4f53da285b8ffee05f72235c07fe0b3cf89d3ef7 100644
--- a/MAC/APL/PIC/TBBDriver/src/ReadCmd.cc
+++ b/MAC/APL/PIC/TBBDriver/src/ReadCmd.cc
@@ -24,23 +24,25 @@
 #include <Common/LofarLogger.h>
 
 #include "ReadCmd.h"
-#include "DriverSettings.h"
 
-namespace LOFAR {
-	using namespace TBB_Protocol;
-	using namespace TP_Protocol;
-	namespace TBB {
+
+using namespace LOFAR;
+using namespace TBB_Protocol;
+using namespace TP_Protocol;
+using	namespace TBB;
+
 
 //--Constructors for a ReadCmd object.----------------------------------------
-ReadCmd::ReadCmd():
-		itsBoardMask(0),itsBoardsMask(0), itsChannel(0)
+ReadCmd::ReadCmd()
 {
+	TS					= TbbSettings::instance();
 	itsTPE 			= new TPReadEvent();
 	itsTPackE 	= 0;
 	itsTBBE 		= 0;
 	itsTBBackE 	= new TBBReadackEvent();
 	
-	itsTBBackE->status = 0;
+	itsTBBackE->status_mask = 0;
+	setWaitAck(true);
 }
 	  
 //--Destructor for ReadCmd.---------------------------------------------------
@@ -62,20 +64,18 @@ bool ReadCmd::isValid(GCFEvent& event)
 // ----------------------------------------------------------------------------
 void ReadCmd::saveTbbEvent(GCFEvent& event)
 {
-	itsTBBE 			= new TBBReadEvent(event);
+	itsTBBE = new TBBReadEvent(event);
 	
-	itsBoardMask = (1 << DriverSettings::instance()->getChBoardNr((int32)itsTBBE->channel));
+	int32 boardnr;
+	int32 channelnr;
+	TS->convertRcu2Ch(itsTBBE->channel,&boardnr,&channelnr);
+		
+	setChannelNr(channelnr);
 				
-	// mask for the installed boards
-	itsBoardsMask = DriverSettings::instance()->activeBoardsMask();
-	
-	// Send only commands to boards installed
-	itsBoardMask = itsBoardMask & itsBoardsMask;
-	
 	// initialize TP send frame
 	itsTPE->opcode			= TPREAD;
 	itsTPE->status			=	0;
-	itsTPE->channel			= itsTBBE->channel;
+	itsTPE->channel			= getChannelNr();
 	itsTPE->secondstime	= itsTBBE->secondstime;
 	itsTPE->sampletime	= itsTBBE->sampletime;
 	itsTPE->prepages		= itsTBBE->prepages;
@@ -85,63 +85,32 @@ void ReadCmd::saveTbbEvent(GCFEvent& event)
 }
 
 // ----------------------------------------------------------------------------
-bool ReadCmd::sendTpEvent(int32 boardnr, int32)
+void ReadCmd::sendTpEvent()
 {
-	bool sending = false;
-	DriverSettings*		ds = DriverSettings::instance();
-	
-	if (ds->boardPort(boardnr).isConnected()) {
-		ds->boardPort(boardnr).send(*itsTPE);
-		ds->boardPort(boardnr).setTimer(ds->timeout());
-		sending = true;
-	}
-	else 
-		itsTBBackE->status |= CMD_ERROR;
-	
-	return(sending);
+	TS->boardPort(getBoardNr()).send(*itsTPE);
+	TS->boardPort(getBoardNr()).setTimer(TS->timeout());
 }
 
 // ----------------------------------------------------------------------------
-void ReadCmd::saveTpAckEvent(GCFEvent& event, int32 boardnr)
+void ReadCmd::saveTpAckEvent(GCFEvent& event)
 {
 	// in case of a time-out, set error mask
 	if (event.signal == F_TIMER) {
-		itsTBBackE->status |= COMM_ERROR;
-	}
-	else {
+		itsTBBackE->status_mask |= TBB_COMM_ERROR;
+	}	else {
 		itsTPackE = new TPReadackEvent(event);
 		
-		LOG_DEBUG_STR(formatString("Received ReadAck from boardnr[%d]", boardnr));
+		LOG_DEBUG_STR(formatString("Received ReadAck from boardnr[%d]", getBoardNr()));
 		delete itsTPackE;
 	}
+	setDone(true);
 }
 
 // ----------------------------------------------------------------------------
 void ReadCmd::sendTbbAckEvent(GCFPortInterface* clientport)
 {
-	if (itsTBBackE->status == 0)
-			itsTBBackE->status = SUCCESS;
+	if (itsTBBackE->status_mask == 0)
+			itsTBBackE->status_mask = TBB_SUCCESS;
 	 
 	clientport->send(*itsTBBackE);
 }
-
-// ----------------------------------------------------------------------------
-uint32 ReadCmd::getBoardMask()
-{
-	return(itsBoardMask);
-}
-
-// ----------------------------------------------------------------------------
-CmdTypes ReadCmd::getCmdType()
-{
-	return(ChannelCmd);
-}
-
-// ----------------------------------------------------------------------------
-bool ReadCmd::waitAck()
-{
-	return(true);
-}
-
-	} // end TBB namespace
-} // end LOFAR namespace
diff --git a/MAC/APL/PIC/TBBDriver/src/ReadCmd.h b/MAC/APL/PIC/TBBDriver/src/ReadCmd.h
index a12f7aefce893a05a16f7f51522ff9b940e480d4..7c9fe6def0a82067c77cfd2b918980bffc443692 100644
--- a/MAC/APL/PIC/TBBDriver/src/ReadCmd.h
+++ b/MAC/APL/PIC/TBBDriver/src/ReadCmd.h
@@ -32,6 +32,7 @@
 #include "TP_Protocol.ph"
 
 #include "Command.h"
+#include "DriverSettings.h"
 
 namespace LOFAR {
 	using namespace TBB_Protocol;
@@ -50,22 +51,14 @@ namespace LOFAR {
 				
 				virtual void saveTbbEvent(GCFEvent& event);
 									
-				virtual bool sendTpEvent(int32 boardnr, int32 channelnr);
+				virtual void sendTpEvent();
 
-				virtual void saveTpAckEvent(GCFEvent& event, int32 boardnr);
+				virtual void saveTpAckEvent(GCFEvent& event);
 
 				virtual void sendTbbAckEvent(GCFPortInterface* clientport);
-				
-				virtual uint32 getBoardMask();
-				
-				virtual bool waitAck();
-				
-				virtual CmdTypes getCmdType();
       
 			private:
-				uint32	itsBoardMask;  // mask indicates the boards to communicate with
-				uint32	itsBoardsMask;	// Installed boards mask
-				uint32	itsChannel;
+				TbbSettings *TS;
 				
 				TPReadEvent			*itsTPE;
 				TPReadackEvent	*itsTPackE;
diff --git a/MAC/APL/PIC/TBBDriver/src/ReadfCmd.cc b/MAC/APL/PIC/TBBDriver/src/ReadfCmd.cc
index f435e56f3668aa01bbb48144dd37007792766289..2c235cb47b389d413a7f738b66d46634bab8d91b 100644
--- a/MAC/APL/PIC/TBBDriver/src/ReadfCmd.cc
+++ b/MAC/APL/PIC/TBBDriver/src/ReadfCmd.cc
@@ -24,21 +24,40 @@
 #include <Common/LofarLogger.h>
 
 #include "ReadfCmd.h"
-#include "DriverSettings.h"
 
-namespace LOFAR {
-	using namespace TBB_Protocol;
-	using namespace TP_Protocol;
-	namespace TBB {
+using namespace LOFAR;
+using namespace TBB_Protocol;
+using namespace TP_Protocol;
+using	namespace TBB;
+
+// information about the flash memory
+static const int FL_SIZE 						= 64 * 1024 *1024; // 64 MB in bytes
+static const int FL_N_PAGES 				= 32; // 32 pages in flash
+static const int FL_N_SECTORS				= 512; // 512 sectors in flash
+static const int FL_N_BLOCKS				= 65536; // 65336 blocks in flash
+
+static const int FL_PAGE_SIZE 			= FL_SIZE / FL_N_PAGES; // 2.097.152 bytes  
+static const int FL_SECTOR_SIZE			= FL_SIZE / FL_N_SECTORS; // 131.072 bytes
+static const int FL_BLOCK_SIZE 			= FL_SIZE / FL_N_BLOCKS; // 1.024 bytes
+
+static const int FL_SECTORS_IN_PAGE	= FL_PAGE_SIZE / FL_SECTOR_SIZE; // 16 sectors per page
+static const int FL_BLOCKS_IN_SECTOR= FL_SECTOR_SIZE / FL_BLOCK_SIZE; // 128 blocks per sector
+static const int FL_BLOCKS_IN_PAGE	= FL_PAGE_SIZE / FL_BLOCK_SIZE; // 2048 blocks per page
+
+static const int IMAGE_SIZE					= 977489; // 977489 bytes in 1 image 
+static const int IMAGE_BLOCKS				= IMAGE_SIZE / FL_BLOCK_SIZE; // 977489 bytes in 1 image 
+
 
 //--Constructors for a ReadfCmd object.----------------------------------------
 ReadfCmd::ReadfCmd():
-		itsBoardMask(0),itsBoardsMask(0),itsBoardStatus(0)
+		itsFile(0),itsImage(0),itsBlock(0),itsBoardStatus(0)
 {
+	TS					= TbbSettings::instance();
 	itsTPE 			= new TPReadfEvent();
 	itsTPackE 	= 0;
 	itsTBBE 		= 0;
-	itsTBBackE 	= new TBBReadfackEvent();
+	itsTBBackE 	= new TBBReadImageAckEvent();
+	setWaitAck(true);
 }
 	  
 //--Destructor for ReadfCmd.---------------------------------------------------
@@ -51,7 +70,7 @@ ReadfCmd::~ReadfCmd()
 // ----------------------------------------------------------------------------
 bool ReadfCmd::isValid(GCFEvent& event)
 {
-	if ((event.signal == TBB_READF)||(event.signal == TP_READFACK)) {
+	if ((event.signal == TBB_READ_IMAGE)||(event.signal == TP_READFACK)) {
 		return(true);
 	}
 	return(false);
@@ -60,59 +79,77 @@ bool ReadfCmd::isValid(GCFEvent& event)
 // ----------------------------------------------------------------------------
 void ReadfCmd::saveTbbEvent(GCFEvent& event)
 {
-	itsTBBE 			= new TBBReadfEvent(event);
-		
-	itsBoardMask = (1 << itsTBBE->board);
+	itsTBBE = new TBBReadImageEvent(event);
 	
-	// mask for the installed boards
-	itsBoardsMask = DriverSettings::instance()->activeBoardsMask();
-
-	// Send only commands to boards installed
-	itsBoardMask = itsBoardMask & itsBoardsMask;
+	setBoardNr(itsTBBE->board);	
 	
-	itsTBBackE->status = 0;
+	itsTBBackE->status_mask = 0;
+	
+	itsImage = itsTBBE->image;
+	itsBlock = (itsImage * FL_BLOCKS_IN_PAGE);
 	
 	// initialize TP send frame
 	itsTPE->opcode	= TPREADF;
 	itsTPE->status	=	0;
-	itsTPE->addr		= itsTBBE->addr;
 	
+	itsFile = fopen("test.hex","wb");
 	delete itsTBBE;	
 }
 
 // ----------------------------------------------------------------------------
-bool ReadfCmd::sendTpEvent(int32 boardnr, int32)
+void ReadfCmd::sendTpEvent()
 {
-	bool sending = false;
-	DriverSettings*		ds = DriverSettings::instance();
-	
-	if (ds->boardPort(boardnr).isConnected()) {
-		ds->boardPort(boardnr).send(*itsTPE);
-		ds->boardPort(boardnr).setTimer(ds->timeout());
-		sending = true;
-	}
-	else 
-		itsTBBackE->status |= CMD_ERROR;
-		
-	return(sending);
+	itsTPE->addr		= static_cast<uint32>(itsBlock * FL_BLOCK_SIZE);
+	TS->boardPort(getBoardNr()).send(*itsTPE);
+	TS->boardPort(getBoardNr()).setTimer(TS->timeout());
 }
 
 // ----------------------------------------------------------------------------
-void ReadfCmd::saveTpAckEvent(GCFEvent& event, int32 boardnr)
+void ReadfCmd::saveTpAckEvent(GCFEvent& event)
 {
 	// in case of a time-out, set error mask
 	if (event.signal == F_TIMER) {
-		itsTBBackE->status |= COMM_ERROR;
-	}
-	else {
+		itsTBBackE->status_mask |= TBB_COMM_ERROR;
+		setDone(true);	
+	} else {
 		itsTPackE = new TPReadfackEvent(event);
 		
 		itsBoardStatus	= itsTPackE->status;
-		for(int an=0; an < 256; an++) {
-			itsTBBackE->data[an]	= itsTPackE->data[an];
+		  
+		int byte_val;
+		int nible_val;
+		if (itsBoardStatus == 0) { 
+			for (int dp = 0; dp < 256; dp++) {	// there are 256 words in 1 message
+				for (int bn = 0; bn < 4; bn++) {
+					byte_val = (itsTPackE->data[dp] >> (bn * 8)) & 0xFF; // take 1 byte
+				
+					nible_val = ((byte_val & 0xF0) >> 4);
+					if (nible_val < 10) {
+						nible_val += 48;
+					}	else {
+						nible_val += 87;	
+					}
+					putc(nible_val,itsFile);
+					
+					nible_val = (byte_val & 0x0F);
+					if (nible_val < 10) {
+						nible_val += 48;
+					}	else {
+						nible_val += 87;	
+					}
+					putc(nible_val,itsFile);
+				}
+			}
+			
+			itsBlock++;
+			if (itsBlock >= ((itsImage + 1) * FL_BLOCKS_IN_PAGE)) {
+				setDone(true);
+			}
+		} else {
+			LOG_DEBUG_STR(formatString("Block %d received status = 0x%08X (ReadfCmd)", itsBlock, itsBoardStatus));
+			setDone(true);
 		}
 		
-		LOG_DEBUG_STR(formatString("Received ReadfAck from boardnr[%d]", boardnr));
 		delete itsTPackE;
 	}
 }
@@ -120,29 +157,9 @@ void ReadfCmd::saveTpAckEvent(GCFEvent& event, int32 boardnr)
 // ----------------------------------------------------------------------------
 void ReadfCmd::sendTbbAckEvent(GCFPortInterface* clientport)
 {
-	if (itsTBBackE->status == 0)
-			itsTBBackE->status = SUCCESS;
+	fclose(itsFile);
+	if (itsTBBackE->status_mask == 0)
+			itsTBBackE->status_mask = TBB_SUCCESS;
 	
 	clientport->send(*itsTBBackE);
 }
-
-// ----------------------------------------------------------------------------
-CmdTypes ReadfCmd::getCmdType()
-{
-	return(BoardCmd);
-}
-
-// ----------------------------------------------------------------------------
-uint32 ReadfCmd::getBoardMask()
-{
-	return(itsBoardMask);
-}
-
-// ----------------------------------------------------------------------------
-bool ReadfCmd::waitAck()
-{
-	return(true);
-}
-
-	} // end TBB namespace
-} // end LOFAR namespace
diff --git a/MAC/APL/PIC/TBBDriver/src/ReadfCmd.h b/MAC/APL/PIC/TBBDriver/src/ReadfCmd.h
index 8e13983aa767bb4c76bec7a72b9c86022fef214f..5740e86e7a22747d274537c00730ce312c570396 100644
--- a/MAC/APL/PIC/TBBDriver/src/ReadfCmd.h
+++ b/MAC/APL/PIC/TBBDriver/src/ReadfCmd.h
@@ -32,6 +32,7 @@
 #include "TP_Protocol.ph"
 
 #include "Command.h"
+#include "DriverSettings.h"
 
 namespace LOFAR {
 	using namespace TBB_Protocol;
@@ -50,26 +51,23 @@ namespace LOFAR {
 				
 				virtual void saveTbbEvent(GCFEvent& event);
 									
-				virtual bool sendTpEvent(int32 boardnr, int32 channelnr);
+				virtual void sendTpEvent();
 
-				virtual void saveTpAckEvent(GCFEvent& event, int32 boardnr);
+				virtual void saveTpAckEvent(GCFEvent& event);
 
 				virtual void sendTbbAckEvent(GCFPortInterface* clientport);
 				
-				virtual uint32 getBoardMask();
-				
-				virtual bool waitAck();
-				
-				virtual CmdTypes getCmdType();
-      
 			private:
-				uint32	itsBoardMask;  // mask indicates the boards to communicate with
-				uint32	itsBoardsMask;	// Installed boards mask
+				TbbSettings *TS;
+				
+				TPReadfEvent					*itsTPE;
+				TPReadfackEvent				*itsTPackE;
+				TBBReadImageEvent			*itsTBBE;
+				TBBReadImageAckEvent	*itsTBBackE;
+				FILE 									*itsFile;
 				
-				TPReadfEvent			*itsTPE;
-				TPReadfackEvent		*itsTPackE;
-				TBBReadfEvent			*itsTBBE;
-				TBBReadfackEvent	*itsTBBackE;
+				int32				itsImage;
+				int32				itsBlock;
 				
 				// variables holding data from tp cmd
 				uint32	itsBoardStatus;
diff --git a/MAC/APL/PIC/TBBDriver/src/ReadwCmd.cc b/MAC/APL/PIC/TBBDriver/src/ReadwCmd.cc
index 3135b5e3401cd3a400a46864c45b7e7a7e74d79f..e37a5e7f8dcdfdbe47f81bd548371becebc30a4b 100644
--- a/MAC/APL/PIC/TBBDriver/src/ReadwCmd.cc
+++ b/MAC/APL/PIC/TBBDriver/src/ReadwCmd.cc
@@ -24,22 +24,22 @@
 #include <Common/LofarLogger.h>
 
 #include "ReadwCmd.h"
-#include "DriverSettings.h"
 
-namespace LOFAR {
-	using namespace TBB_Protocol;
-	using namespace TP_Protocol;
-	namespace TBB {
+using namespace LOFAR;
+using namespace TBB_Protocol;
+using namespace TP_Protocol;
+using	namespace TBB;
 
 //--Constructors for a ReadwCmd object.----------------------------------------
 ReadwCmd::ReadwCmd():
-		itsBoardMask(0),itsBoardsMask(0),itsBoardStatus(0)
-		//itsMp(0),itsAddr(0),itsWordLo(0),itsWordHi(0)
+		itsBoardStatus(0)
 {
+	TS					= TbbSettings::instance();
 	itsTPE 			= new TPReadwEvent();
 	itsTPackE 	= 0;
 	itsTBBE 		= 0;
 	itsTBBackE 	= new TBBReadwackEvent();
+	setWaitAck(true);
 }
 	  
 //--Destructor for ReadwCmd.---------------------------------------------------
@@ -61,51 +61,33 @@ bool ReadwCmd::isValid(GCFEvent& event)
 // ----------------------------------------------------------------------------
 void ReadwCmd::saveTbbEvent(GCFEvent& event)
 {
-	itsTBBE 			= new TBBReadwEvent(event);
-		
-	itsBoardMask = (1 << itsTBBE->board);
-
-	// mask for the installed boards
-	itsBoardsMask = DriverSettings::instance()->activeBoardsMask();
+	itsTBBE	= new TBBReadwEvent(event);
 	
-	// Send only commands to boards installed
-	itsBoardMask = itsBoardMask & itsBoardsMask;
+	setBoardNr(itsTBBE->board);	
 	
-	itsTBBackE->status = 0;
+	itsTBBackE->status_mask = 0;
 	
 	// initialize TP send frame
 	itsTPE->opcode	= TPREADW;
 	itsTPE->status	= 0;
-	itsTPE->mp			=	itsTBBE->mp;
+	itsTPE->mp			=	static_cast<uint32>(itsTBBE->mp);
 	itsTPE->addr		=	itsTBBE->addr;
-	//itsMp						= itsTBBE->mp;
-	//itsAddr					= itsTBBE->addr;
 	delete itsTBBE;	
 }
 
 // ----------------------------------------------------------------------------
-bool ReadwCmd::sendTpEvent(int32 boardnr, int32)
+void ReadwCmd::sendTpEvent()
 {
-	bool sending = false;
-	DriverSettings*		ds = DriverSettings::instance();
-	
-	if (ds->boardPort(boardnr).isConnected()) {
-		ds->boardPort(boardnr).send(*itsTPE);
-		ds->boardPort(boardnr).setTimer(ds->timeout());
-		sending = true;
-	}
-	else 
-		itsTBBackE->status |= CMD_ERROR;
-
-	return(sending);
+	TS->boardPort(getBoardNr()).send(*itsTPE);
+	TS->boardPort(getBoardNr()).setTimer(TS->timeout());
 }
 
 // ----------------------------------------------------------------------------
-void ReadwCmd::saveTpAckEvent(GCFEvent& event, int32 boardnr)
+void ReadwCmd::saveTpAckEvent(GCFEvent& event)
 {
 	// in case of a time-out, set error mask
 	if (event.signal == F_TIMER) {
-		itsTBBackE->status |= COMM_ERROR;
+		itsTBBackE->status_mask |= TBB_COMM_ERROR;
 	}
 	else {
 		itsTPackE = new TPReadwackEvent(event);
@@ -114,37 +96,17 @@ void ReadwCmd::saveTpAckEvent(GCFEvent& event, int32 boardnr)
 		itsTBBackE->wordlo	= itsTPackE->wordlo;
 		itsTBBackE->wordhi	= itsTPackE->wordhi;
 		
-		LOG_DEBUG_STR(formatString("Received ReadwAck from boardnr[%d]", boardnr));
+		LOG_DEBUG_STR(formatString("Received ReadwAck from boardnr[%d]", getBoardNr()));
 		delete itsTPackE;
 	}
+	setDone(true);
 }
 
 // ----------------------------------------------------------------------------
 void ReadwCmd::sendTbbAckEvent(GCFPortInterface* clientport)
 {
-	if (itsTBBackE->status == 0)
-			itsTBBackE->status = SUCCESS;	
+	if (itsTBBackE->status_mask == 0)
+			itsTBBackE->status_mask = TBB_SUCCESS;	
 	
 	clientport->send(*itsTBBackE);
 }
-
-// ----------------------------------------------------------------------------
-CmdTypes ReadwCmd::getCmdType()
-{
-	return(BoardCmd);
-}
-
-// ----------------------------------------------------------------------------
-uint32 ReadwCmd::getBoardMask()
-{
-	return(itsBoardMask);
-}
-
-// ----------------------------------------------------------------------------
-bool ReadwCmd::waitAck()
-{
-	return(true);
-}
-
-	} // end TBB namespace
-} // end LOFAR namespace
diff --git a/MAC/APL/PIC/TBBDriver/src/ReadwCmd.h b/MAC/APL/PIC/TBBDriver/src/ReadwCmd.h
index 5405cd04e801856a926b9f1cffdf54db71a3a856..883873c0131b8b3b1f184d8ad94a660224366860 100644
--- a/MAC/APL/PIC/TBBDriver/src/ReadwCmd.h
+++ b/MAC/APL/PIC/TBBDriver/src/ReadwCmd.h
@@ -32,6 +32,7 @@
 #include "TP_Protocol.ph"
 
 #include "Command.h"
+#include "DriverSettings.h"
 
 namespace LOFAR {
 	using namespace TBB_Protocol;
@@ -50,21 +51,14 @@ namespace LOFAR {
 				
 				virtual void saveTbbEvent(GCFEvent& event);
 									
-				virtual bool sendTpEvent(int32 boardnr, int32 channelnr);
+				virtual void sendTpEvent();
 
-				virtual void saveTpAckEvent(GCFEvent& event, int32 boardnr);
+				virtual void saveTpAckEvent(GCFEvent& event);
 
 				virtual void sendTbbAckEvent(GCFPortInterface* clientport);
-				
-				virtual uint32 getBoardMask();
-				
-				virtual bool waitAck();
-				
-				virtual CmdTypes getCmdType();
-      
+				      
 			private:
-				uint32	itsBoardMask;  // mask indicates the boards to communicate with
-				uint32	itsBoardsMask;	// Installed boards mask
+				TbbSettings *TS;
 				
 				TPReadwEvent			*itsTPE;
 				TPReadwackEvent		*itsTPackE;
@@ -73,10 +67,6 @@ namespace LOFAR {
 				
 				// variables holding data from tp cmd
 				uint32	itsBoardStatus;
-				//uint32	itsMp;
-				//uint32	itsAddr;
-				//uint32	itsWordLo;
-				//uint32	itsWordHi;
 		};
 	} // end TBB namespace
 } // end LOFAR namespace
diff --git a/MAC/APL/PIC/TBBDriver/src/RecordCmd.cc b/MAC/APL/PIC/TBBDriver/src/RecordCmd.cc
index 45122b9fe193d7b7eb6022f63108812ca695eb12..c440aaa1c2b52edb440ff86117ffab3c709c250d 100644
--- a/MAC/APL/PIC/TBBDriver/src/RecordCmd.cc
+++ b/MAC/APL/PIC/TBBDriver/src/RecordCmd.cc
@@ -24,26 +24,27 @@
 #include <Common/LofarLogger.h>
 
 #include "RecordCmd.h"
-#include "DriverSettings.h"
 
-namespace LOFAR {
-	using namespace TBB_Protocol;
-	using namespace TP_Protocol;
-	namespace TBB {
+using namespace LOFAR;
+using namespace TBB_Protocol;
+using namespace TP_Protocol;
+using	namespace TBB;
 
 //--Constructors for a RecordCmd object.----------------------------------------
 RecordCmd::RecordCmd():
-		itsBoardMask(0), itsBoardsMask(0),itsChannel(0)
+		itsRcuStatus(0)
 {
+	TS					= TbbSettings::instance();
 	itsTPE 			= new TPRecordEvent();
 	itsTPackE 	= 0;
 	itsTBBE 		= 0;
 	itsTBBackE 	= new TBBRecordackEvent();
 	
 	for(int boardnr = 0;boardnr < MAX_N_TBBBOARDS;boardnr++) { 
-		itsTBBackE->status[boardnr]	= 0;
+		itsTBBackE->status_mask[boardnr]	= 0;
 		itsChannelMask[boardnr] = 0;
-	}		
+	}
+	setWaitAck(true);		
 }
 	  
 //--Destructor for RecordCmd.---------------------------------------------------
@@ -65,110 +66,117 @@ bool RecordCmd::isValid(GCFEvent& event)
 // ----------------------------------------------------------------------------
 void RecordCmd::saveTbbEvent(GCFEvent& event)
 {
-	itsTBBE 			= new TBBRecordEvent(event);
-		
-	// mask for the installed boards
-	itsBoardsMask = DriverSettings::instance()->activeBoardsMask();
+	itsTBBE	= new TBBRecordEvent(event);
 		
-	for (int boardnr = 0; boardnr < DriverSettings::instance()->maxBoards(); boardnr++) {
-		
-		if (!(itsBoardsMask & (1 << boardnr))) 
-			itsTBBackE->status[boardnr] |= NO_BOARD;
+	// convert rcu-bitmask to tbb-channelmask
+	int boardnr;
+	int channelnr;
+	for (int rcunr = 0; rcunr < TS->maxChannels(); rcunr++) {
+		if(itsTBBE->rcu_mask.test(rcunr)) {
+			TS->convertRcu2Ch(rcunr,&boardnr,&channelnr);	
+			itsChannelMask[boardnr] |= (1 << channelnr);
+		}
+	} 
+	
+	uint32 boardmask = 0;		
+	for (int boardnr = 0; boardnr < TS->maxBoards(); boardnr++) {
+		if (itsChannelMask[boardnr] != 0) boardmask |= (1 << boardnr); 
+			
+		if (!TS->isBoardActive(boardnr)) {
+			itsTBBackE->status_mask[boardnr] |= TBB_NO_BOARD;
+		}
 		
-		itsChannelMask[boardnr] = itsTBBE->channelmask[boardnr]; 		
+		if ((itsChannelMask[boardnr] & ~0xFFFF) != 0) {
+			itsTBBackE->status_mask[boardnr] |= (TBB_SELECT_ERROR | TBB_CHANNEL_SEL_ERROR);
+		}		
 		
-		if (itsChannelMask[boardnr] != 0)
-			itsBoardMask |= (1 << boardnr);
-			
-		if ((itsChannelMask[boardnr] & ~0xFFFF) != 0) 
-			itsTBBackE->status[boardnr] |= (SELECT_ERROR | CHANNEL_SEL_ERROR);
-				
-		if (!(itsBoardsMask & (1 << boardnr)) &&  (itsChannelMask[boardnr] != 0))
-			itsTBBackE->status[boardnr] |= (SELECT_ERROR | BOARD_SEL_ERROR);
+		if (!TS->isBoardActive(boardnr) &&  (itsChannelMask[boardnr] != 0)) {
+			itsTBBackE->status_mask[boardnr] |= (TBB_SELECT_ERROR | TBB_BOARD_SEL_ERROR);
+		}
 	}
+	setBoardMask(boardmask);
 	
-	// Send only commands to boards installed
-	itsBoardMask = itsBoardMask & itsBoardsMask;
+	// select firt channel to handle
+	nextChannelNr();
 	
 	// initialize TP send frame
 	itsTPE->opcode	= TPRECORD;
 	itsTPE->status	=	0;
 	
-	delete itsTBBE;	
+	delete itsTBBE;
 }
 
 // ----------------------------------------------------------------------------
-bool RecordCmd::sendTpEvent(int32 boardnr, int32 channelnr)
+void RecordCmd::sendTpEvent()
 {
-	bool sending = false;
-	DriverSettings*		ds = DriverSettings::instance();
+	itsRcuStatus = 0;
 	
-	itsTPE->channel = DriverSettings::instance()->getChInputNr(channelnr);
-	itsChannel = channelnr;
+	itsTPE->channel = TS->getChInputNr(getChannelNr());
 	
-	if 	(ds->boardPort(boardnr).isConnected() && 
-			(itsTBBackE->status[boardnr] == 0) &&
-			(DriverSettings::instance()->getChStatus(channelnr) == 'A')) {
-		
-		ds->boardPort(boardnr).send(*itsTPE);
-		ds->boardPort(boardnr).setTimer(ds->timeout());
-		sending = true;
-	}
-	else
-		itsTBBackE->status[boardnr] |= CMD_ERROR;
+	if ((TS->getChState(getChannelNr()) != 'A') && (TS->getChState(getChannelNr()) != 'S'))
+		itsRcuStatus |= TBB_RCU_NOT_ALLOCATED;
 	
-	return(sending);
+	if (itsTBBackE->status_mask[getBoardNr()] == 0) {
+		if (itsRcuStatus == 0) {
+			TS->boardPort(getBoardNr()).send(*itsTPE);
+			LOG_DEBUG_STR(formatString("Sending RecordCmd to boardnr[%d], channel[%08X]", getBoardNr(), itsTPE->channel));
+		}
+	}
+	TS->boardPort(getBoardNr()).setTimer(TS->timeout());
 }
 
 // ----------------------------------------------------------------------------
-void RecordCmd::saveTpAckEvent(GCFEvent& event, int32 boardnr)
+void RecordCmd::saveTpAckEvent(GCFEvent& event)
 {
 	// in case of a time-out, set error mask
 	if (event.signal == F_TIMER) {
-		itsTBBackE->status[boardnr] |= COMM_ERROR;
+		itsTBBackE->status_mask[getBoardNr()] |= TBB_RCU_COMM_ERROR;
+		itsRcuStatus |= TBB_TIMEOUT_ETH;
 	}
 	else {
 		itsTPackE = new TPRecordackEvent(event);
 		
 		if ((itsTPackE->status >= 0xF0) && (itsTPackE->status <= 0xF6)) 
-			itsTBBackE->status[boardnr] |= (1 << (16 + (itsTPackE->status & 0x0F)));
+			itsRcuStatus |= (1 << (16 + (itsTPackE->status & 0x0F)));
 		
-		if (itsTPackE->status == 0)
-			DriverSettings::instance()->setChStatus((itsChannel + (boardnr * 16)), 'R');	
-		
-		LOG_DEBUG_STR(formatString("Received RecordAck from boardnr[%d]", boardnr));
+		if ((itsTPackE->status == 0) && (itsRcuStatus == 0))
+			//TS->setChState((getChannelNr() + (getBoardNr() * 16)), 'R');	
+			TS->setChState(getChannelNr(), 'R');	
+		LOG_DEBUG_STR(formatString("Received RecordAck from boardnr[%d]", getBoardNr()));
 		delete itsTPackE;
 	}
+	
+	if (itsRcuStatus) TS->setChState(getChannelNr(), 'E');
+	TS->setChStatus(getChannelNr(),(uint16)(itsRcuStatus >> 16));
+	
+	if (itsRcuStatus || itsTBBackE->status_mask[getBoardNr()]) {
+		int32 rcu;
+		TS->convertCh2Rcu(getChannelNr(),&rcu);
+		LOG_INFO_STR(formatString("ERROR RecordCmd Rcu[%d], DriverStatus[0x%x], RcuStatus[0x%x]",
+			rcu, itsTBBackE->status_mask[getBoardNr()],itsRcuStatus));
+	}
+	itsTBBackE->status_mask[getBoardNr()] |= itsRcuStatus;
+	nextChannelNr();
 }
 
 // ----------------------------------------------------------------------------
 void RecordCmd::sendTbbAckEvent(GCFPortInterface* clientport)
 {
-	for (int32 boardnr = 0; boardnr < DriverSettings::instance()->maxBoards(); boardnr++) { 
-		if (itsTBBackE->status[boardnr] == 0)
-			itsTBBackE->status[boardnr] = SUCCESS;
+	int32 rcunr;
+	
+	itsTBBackE->rcu_mask.reset();
+	for (int32 channelnr = 0; channelnr < TS->maxChannels(); channelnr++) {
+		if (TS->getChStatus(channelnr)) {
+			TS->convertCh2Rcu(channelnr,&rcunr);
+			itsTBBackE->rcu_mask.set(rcunr);
+		}
+	}
+	
+	for (int32 boardnr = 0; boardnr < TS->maxBoards(); boardnr++) { 
+		if (itsTBBackE->status_mask[boardnr] == 0)
+			itsTBBackE->status_mask[boardnr] = TBB_SUCCESS;
 	}
 	
 	clientport->send(*itsTBBackE);
 }
 
-// ----------------------------------------------------------------------------
-uint32 RecordCmd::getBoardMask()
-{
-	return(itsBoardMask);
-}
-
-// ----------------------------------------------------------------------------
-bool RecordCmd::waitAck()
-{
-	return(true);
-}
-
-// ----------------------------------------------------------------------------
-CmdTypes RecordCmd::getCmdType()
-{
-	return(ChannelCmd);
-}
-
-	} // end TBB namespace
-} // end LOFAR namespace
diff --git a/MAC/APL/PIC/TBBDriver/src/RecordCmd.h b/MAC/APL/PIC/TBBDriver/src/RecordCmd.h
index 2439e9945878d6a7f9ed7724ab2e164677a1d153..97dd914c46afd56469661bda9189423186961c90 100644
--- a/MAC/APL/PIC/TBBDriver/src/RecordCmd.h
+++ b/MAC/APL/PIC/TBBDriver/src/RecordCmd.h
@@ -32,6 +32,7 @@
 #include "TP_Protocol.ph"
 
 #include "Command.h"
+#include "DriverSettings.h"
 
 namespace LOFAR {
 	using namespace TBB_Protocol;
@@ -50,23 +51,17 @@ namespace LOFAR {
 				
 				virtual void saveTbbEvent(GCFEvent& event);
 									
-				virtual bool sendTpEvent(int32 boardnr, int32 channelnr);
+				virtual void sendTpEvent();
 
-				virtual void saveTpAckEvent(GCFEvent& event, int32 boardnr);
+				virtual void saveTpAckEvent(GCFEvent& event);
 
 				virtual void sendTbbAckEvent(GCFPortInterface* clientport);
-				
-				virtual uint32 getBoardMask();
-				
-				virtual bool waitAck();
-				
-				virtual CmdTypes getCmdType();
       
 			private:
-				uint32	itsBoardMask;  // mask indicates the boards to communicate with
-				uint32	itsBoardsMask;	// Installed boards mask
+				TbbSettings *TS;
+				
 				uint32	itsChannelMask[MAX_N_TBBBOARDS];
-				uint32	itsChannel;
+				uint32	itsRcuStatus;
 				
 				TPRecordEvent			*itsTPE;
 				TPRecordackEvent	*itsTPackE;
diff --git a/MAC/APL/PIC/TBBDriver/src/ResetCmd.cc b/MAC/APL/PIC/TBBDriver/src/ResetCmd.cc
index e180e82c1e795ba123e8fca3ed71d2f80f03f6f1..2a1b22b6e311dc4da0fe185e5e77f32b87ab3bf4 100644
--- a/MAC/APL/PIC/TBBDriver/src/ResetCmd.cc
+++ b/MAC/APL/PIC/TBBDriver/src/ResetCmd.cc
@@ -24,25 +24,25 @@
 #include <Common/LofarLogger.h>
 
 #include "ResetCmd.h"
-#include "DriverSettings.h"
 
-namespace LOFAR {
-	using namespace TBB_Protocol;
-	using namespace TP_Protocol;
-	namespace TBB {
+using namespace LOFAR;
+using namespace TBB_Protocol;
+using namespace TP_Protocol;
+using	namespace TBB;
 
 //--Constructors for a ResetCmd object.----------------------------------------
-ResetCmd::ResetCmd():
-		itsBoardMask(0),itsBoardsMask(0)
+ResetCmd::ResetCmd()
 {
+	TS					= TbbSettings::instance();
 	itsTPE 			= new TPResetEvent();
 	itsTPackE 	= 0;
 	itsTBBE 		= 0;
 	itsTBBackE 	= new TBBResetackEvent();
 	
 	for(int boardnr = 0;boardnr < MAX_N_TBBBOARDS;boardnr++) { 
-		itsTBBackE->status[boardnr]	= 0;
-	}		
+		itsTBBackE->status_mask[boardnr]	= 0;
+	}
+	setWaitAck(false);		
 }
 	  
 //--Destructor for ResetCmd.---------------------------------------------------
@@ -64,42 +64,37 @@ bool ResetCmd::isValid(GCFEvent& event)
 // ----------------------------------------------------------------------------
 void ResetCmd::saveTbbEvent(GCFEvent& event)
 {
-	DriverSettings*		ds = DriverSettings::instance();
-	itsTBBE 			= new TBBResetEvent(event);
+	itsTBBE	= new TBBResetEvent(event);
 	itsTPE->opcode			= TPRESET;
 	itsTPE->status			=	0;
 		
-	itsBoardMask = itsTBBE->boardmask;
-	
-	for (int boardnr = 0; boardnr < DriverSettings::instance()->maxBoards(); boardnr++) {
-		if (itsBoardMask & (1 << boardnr)) {
-			if (ds->boardPort(boardnr).isConnected())
-				ds->boardPort(boardnr).send(*itsTPE);
+	for (int boardnr = 0; boardnr < TS->maxBoards(); boardnr++) {
+		if (itsTBBE->boardmask & (1 << boardnr)) {
+			if (TS->boardPort(boardnr).isConnected())
+				TS->boardPort(boardnr).send(*itsTPE);
 			
 			// reset channel information for selected board	
 			for (int channelnr = (boardnr * 16); channelnr < ((boardnr * 16) + 16); channelnr++) {
-				DriverSettings::instance()->setChSelected(channelnr, false);
-				DriverSettings::instance()->setChStatus(channelnr, 'F');
-				DriverSettings::instance()->setChStartAddr(channelnr, 0);
-				DriverSettings::instance()->setChPageSize(channelnr, 0);				
+				TS->setChSelected(channelnr, false);
+				TS->setChState(channelnr, 'F');
+				TS->setChStartAddr(channelnr, 0);
+				TS->setChPageSize(channelnr, 0);				
 			}
 		} 
 	}
-	
 	delete itsTBBE;	
+	setDone(true);
 }
 
 // ----------------------------------------------------------------------------
-bool ResetCmd::sendTpEvent(int32 boardnr, int32)
+void ResetCmd::sendTpEvent()
 {
-	bool sending = false;
 	// sending reset is done in saveTbbEvent()
 	// because sendTpEvent() is only posible for active boards
-	return(sending);
 }
 
 // ----------------------------------------------------------------------------
-void ResetCmd::saveTpAckEvent(GCFEvent& event, int32 boardnr)
+void ResetCmd::saveTpAckEvent(GCFEvent& event)
 {
 	// in case of a time-out, set error mask
 	if (event.signal == F_TIMER) {
@@ -108,10 +103,6 @@ void ResetCmd::saveTpAckEvent(GCFEvent& event, int32 boardnr)
 	else {
 		itsTPackE = new TPResetackEvent(event);
 		
-		if ((itsTPackE->status >= 0xF0) && (itsTPackE->status <= 0xF6)) 
-			itsTBBackE->status[boardnr] |= (1 << (16 + (itsTPackE->status & 0x0F)));	
-		
-		LOG_DEBUG_STR(formatString("Received ResetAck from boardnr[%d]", boardnr));
 		delete itsTPackE;
 	}
 }
@@ -119,31 +110,10 @@ void ResetCmd::saveTpAckEvent(GCFEvent& event, int32 boardnr)
 // ----------------------------------------------------------------------------
 void ResetCmd::sendTbbAckEvent(GCFPortInterface* clientport)
 {
-	for (int32 boardnr = 0; boardnr < DriverSettings::instance()->maxBoards(); boardnr++) { 
-		if (itsTBBackE->status[boardnr] == 0)
-			itsTBBackE->status[boardnr] = SUCCESS;
+	for (int32 boardnr = 0; boardnr < TS->maxBoards(); boardnr++) { 
+		if (itsTBBackE->status_mask[boardnr] == 0)
+			itsTBBackE->status_mask[boardnr] = TBB_SUCCESS;
 	}
 	
 	clientport->send(*itsTBBackE);
 }
-
-// ----------------------------------------------------------------------------
-CmdTypes ResetCmd::getCmdType()
-{
-	return(BoardCmd);
-}
-
-// ----------------------------------------------------------------------------
-uint32 ResetCmd::getBoardMask()
-{
-	return(itsBoardMask);
-}
-
-// ----------------------------------------------------------------------------
-bool ResetCmd::waitAck()
-{
-	return(false);
-}
-
-	} // end TBB namespace
-} // end LOFAR namespace
diff --git a/MAC/APL/PIC/TBBDriver/src/ResetCmd.h b/MAC/APL/PIC/TBBDriver/src/ResetCmd.h
index 5d325b4bb532e1747a07c54ef5904edcb2cba2e4..b25c4f183d364c051c74afb6d86ac490c67ca14c 100644
--- a/MAC/APL/PIC/TBBDriver/src/ResetCmd.h
+++ b/MAC/APL/PIC/TBBDriver/src/ResetCmd.h
@@ -32,6 +32,7 @@
 #include "TP_Protocol.ph"
 
 #include "Command.h"
+#include "DriverSettings.h"
 
 namespace LOFAR {
 	using namespace TBB_Protocol;
@@ -50,21 +51,14 @@ namespace LOFAR {
 				
 				virtual void saveTbbEvent(GCFEvent& event);
 									
-				virtual bool sendTpEvent(int32 boardnr, int32 channelnr);
+				virtual void sendTpEvent();
 
-				virtual void saveTpAckEvent(GCFEvent& event, int32 boardnr);
+				virtual void saveTpAckEvent(GCFEvent& event);
 
 				virtual void sendTbbAckEvent(GCFPortInterface* clientport);
 				
-				virtual uint32 getBoardMask();
-				
-				virtual bool waitAck();
-				
-				virtual CmdTypes getCmdType();
-      
 			private:
-				uint32	itsBoardMask;  // mask indicates the boards to communicate with
-				uint32	itsBoardsMask;	// Installed boards mask
+				TbbSettings *TS;
 				
 				TPResetEvent			*itsTPE;
 				TPResetackEvent		*itsTPackE;
diff --git a/MAC/APL/PIC/TBBDriver/src/SizeCmd.cc b/MAC/APL/PIC/TBBDriver/src/SizeCmd.cc
index 8f78b8bb37afaf7c06a4cf2083561e6e3a9af53c..ef99c0fbca6fa975465c2bccc7e2fac91b0ad8af 100644
--- a/MAC/APL/PIC/TBBDriver/src/SizeCmd.cc
+++ b/MAC/APL/PIC/TBBDriver/src/SizeCmd.cc
@@ -24,25 +24,25 @@
 #include <Common/LofarLogger.h>
 
 #include "SizeCmd.h"
-#include "DriverSettings.h"
 
-namespace LOFAR {
-	using namespace TBB_Protocol;
-	using namespace TP_Protocol;
-	namespace TBB {
+using namespace LOFAR;
+using namespace TBB_Protocol;
+using namespace TP_Protocol;
+using	namespace TBB;
 
 //--Constructors for a SizeCmd object.----------------------------------------
-SizeCmd::SizeCmd():
-		itsBoardMask(0),itsBoardsMask(0)
+SizeCmd::SizeCmd()
 {
+	TS					= TbbSettings::instance();
 	itsTPE 			= new TPSizeEvent();
 	itsTPackE 	= 0;
 	itsTBBE 		= 0;
 	itsTBBackE 	= new TBBSizeackEvent();
 	
 	for(int boardnr = 0;boardnr < MAX_N_TBBBOARDS;boardnr++) { 
-		itsTBBackE->status[boardnr]	= 0;
-	}		
+		itsTBBackE->status_mask[boardnr]	= 0;
+	}
+	setWaitAck(true);		
 }
 	  
 //--Destructor for SizeCmd.---------------------------------------------------
@@ -64,23 +64,17 @@ bool SizeCmd::isValid(GCFEvent& event)
 // ----------------------------------------------------------------------------
 void SizeCmd::saveTbbEvent(GCFEvent& event)
 {
-	itsTBBE 			= new TBBSizeEvent(event);
+	itsTBBE	= new TBBSizeEvent(event);
 	
-	// mask for the installed boards
-	itsBoardsMask = DriverSettings::instance()->activeBoardsMask();	
-	itsBoardMask = itsTBBE->boardmask; // for some commands board-id is used ???
+	setBoardMask(itsTBBE->boardmask);
 	
-	for (int boardnr = 0; boardnr < DriverSettings::instance()->maxBoards(); boardnr++) {
-		
-		if (!(itsBoardsMask & (1 << boardnr)))
-			itsTBBackE->status[boardnr] |= NO_BOARD;
-						
-		if (!(itsBoardsMask & (1 << boardnr)) &&  (itsBoardMask & (1 << boardnr)))
-			itsTBBackE->status[boardnr] |= (SELECT_ERROR | BOARD_SEL_ERROR);
-	}
+	for (int boardnr = 0; boardnr < TS->maxBoards(); boardnr++) {
+		if (!TS->isBoardActive(boardnr))
+			itsTBBackE->status_mask[boardnr] |= TBB_NO_BOARD;
+	}						
 		
-	// Send only commands to boards installed
-	itsBoardMask = itsBoardMask & itsBoardsMask;
+	// get first board
+	nextBoardNr();
 	
 	// initialize TP send frame
 	itsTPE->opcode	= TPSIZE;
@@ -90,71 +84,42 @@ void SizeCmd::saveTbbEvent(GCFEvent& event)
 }
 
 // ----------------------------------------------------------------------------
-bool SizeCmd::sendTpEvent(int32 boardnr, int32)
+void SizeCmd::sendTpEvent()
 {
-	bool sending = false;
-	DriverSettings*		ds = DriverSettings::instance();
-	
-	if (ds->boardPort(boardnr).isConnected() && (itsTBBackE->status[boardnr] == 0)) {
-		ds->boardPort(boardnr).send(*itsTPE);
-		ds->boardPort(boardnr).setTimer(ds->timeout());
-		sending = true;
-	}
-	else
-		itsTBBackE->status[boardnr] |= CMD_ERROR;
-		
-	return(sending);
+	TS->boardPort(getBoardNr()).send(*itsTPE);
+	TS->boardPort(getBoardNr()).setTimer(TS->timeout());
 }
 
 // ----------------------------------------------------------------------------
-void SizeCmd::saveTpAckEvent(GCFEvent& event, int32 boardnr)
+void SizeCmd::saveTpAckEvent(GCFEvent& event)
 {
 	// in case of a time-out, set error mask
 	if (event.signal == F_TIMER) {
-		itsTBBackE->status[boardnr] |= COMM_ERROR;
-	}
-	else {
+		itsTBBackE->status_mask[getBoardNr()] |= TBB_COMM_ERROR;
+	} else {
 		itsTPackE = new TPSizeackEvent(event);
 		
 		if ((itsTPackE->status >= 0xF0) && (itsTPackE->status <= 0xF6)) 
-			itsTBBackE->status[boardnr] |= (1 << (16 + (itsTPackE->status & 0x0F)));	
+			itsTBBackE->status_mask[getBoardNr()] |= (1 << (16 + (itsTPackE->status & 0x0F)));	
 		
-		itsTBBackE->npages[boardnr]	= itsTPackE->npages;
+		LOG_DEBUG_STR(formatString("SizeCmd: board[%d] status[0x%08X] pages[%u]", 
+																getBoardNr(), itsTPackE->status, itsTPackE->npages));
+																
+		TS->setMemorySize(getBoardNr(),itsTPackE->npages);
+		itsTBBackE->npages[getBoardNr()]	= itsTPackE->npages;
 		
-		LOG_DEBUG_STR(formatString("SizeCmd: board[%d] %u;%u", 
-																boardnr, itsTPackE->status, itsTPackE->npages));
 		delete itsTPackE;
 	}
+	nextBoardNr();
 }
 
 // ----------------------------------------------------------------------------
 void SizeCmd::sendTbbAckEvent(GCFPortInterface* clientport)
 {
-	for (int32 boardnr = 0; boardnr < DriverSettings::instance()->maxBoards(); boardnr++) { 
-		if (itsTBBackE->status[boardnr] == 0)
-			itsTBBackE->status[boardnr] = SUCCESS;
+	for (int32 boardnr = 0; boardnr < TS->maxBoards(); boardnr++) { 
+		if (itsTBBackE->status_mask[boardnr] == 0)
+			itsTBBackE->status_mask[boardnr] = TBB_SUCCESS;
 	}
 	
 	clientport->send(*itsTBBackE);
 }
-
-// ----------------------------------------------------------------------------
-CmdTypes SizeCmd::getCmdType()
-{
-	return(BoardCmd);
-}
-
-// ----------------------------------------------------------------------------
-uint32 SizeCmd::getBoardMask()
-{
-	return(itsBoardMask);
-}
-
-// ----------------------------------------------------------------------------
-bool SizeCmd::waitAck()
-{
-	return(true);
-}
-
-	} // end TBB namespace
-} // end LOFAR namespace
diff --git a/MAC/APL/PIC/TBBDriver/src/SizeCmd.h b/MAC/APL/PIC/TBBDriver/src/SizeCmd.h
index d5693fdc524c574ef6de2dd89c44a23fc4afe2c5..26bb995ef931502638b0ffe9b10f8b92525833f7 100644
--- a/MAC/APL/PIC/TBBDriver/src/SizeCmd.h
+++ b/MAC/APL/PIC/TBBDriver/src/SizeCmd.h
@@ -32,6 +32,7 @@
 #include "TP_Protocol.ph"
 
 #include "Command.h"
+#include "DriverSettings.h"
 
 namespace LOFAR {
 	using namespace TBB_Protocol;
@@ -50,21 +51,14 @@ namespace LOFAR {
 				
 				virtual void saveTbbEvent(GCFEvent& event);
 									
-				virtual bool sendTpEvent(int32 boardnr, int32 channelnr);
+				virtual void sendTpEvent();
 
-				virtual void saveTpAckEvent(GCFEvent& event, int32 boardnr);
+				virtual void saveTpAckEvent(GCFEvent& event);
 
 				virtual void sendTbbAckEvent(GCFPortInterface* clientport);
 				
-				virtual uint32 getBoardMask();
-				
-				virtual bool waitAck();
-				
-				virtual CmdTypes getCmdType();
-      
 			private:
-				uint32	itsBoardMask;  // mask indicates the boards to communicate with
-				uint32	itsBoardsMask;	// Installed boards mask
+				TbbSettings *TS;
 				
 				TPSizeEvent			*itsTPE;
 				TPSizeackEvent	*itsTPackE;
diff --git a/MAC/APL/PIC/TBBDriver/src/StatusCmd.cc b/MAC/APL/PIC/TBBDriver/src/StatusCmd.cc
index f57bdceee11131e9be9cb7492cb3540441ebeb7a..08c2c553712381af8a90f25eef6eccf289208955 100644
--- a/MAC/APL/PIC/TBBDriver/src/StatusCmd.cc
+++ b/MAC/APL/PIC/TBBDriver/src/StatusCmd.cc
@@ -23,25 +23,25 @@
 #include <Common/LofarLogger.h>
 
 #include "StatusCmd.h"
-#include "DriverSettings.h"
 
-namespace LOFAR {
-	using namespace TBB_Protocol;
-	using namespace TP_Protocol;
-	namespace TBB {
+using namespace LOFAR;
+using namespace TBB_Protocol;
+using namespace TP_Protocol;
+using	namespace TBB;
 
 //--Constructors for a StatusCmd object.----------------------------------------
-StatusCmd::StatusCmd():
-		itsBoardMask(0),itsBoardsMask(0)
+StatusCmd::StatusCmd()
 {
+	TS					= TbbSettings::instance();
 	itsTPE 			= new TPStatusEvent();
 	itsTPackE 	= 0;
 	itsTBBE 		= 0;
 	itsTBBackE 	= new TBBStatusackEvent();
 	
 	for(int boardnr = 0;boardnr < MAX_N_TBBBOARDS;boardnr++) { 
-		itsTBBackE->status[boardnr]	= 0;
-	}		
+		itsTBBackE->status_mask[boardnr]	= 0;
+	}
+	setWaitAck(true);		
 }
 	  
 //--Destructor for StatusCmd.---------------------------------------------------
@@ -63,22 +63,17 @@ bool StatusCmd::isValid(GCFEvent& event)
 // ----------------------------------------------------------------------------
 void StatusCmd::saveTbbEvent(GCFEvent& event)
 {
-	itsTBBE 			= new TBBStatusEvent(event);
+	itsTBBE	= new TBBStatusEvent(event);
 	
-	itsBoardsMask = DriverSettings::instance()->activeBoardsMask();	
-	itsBoardMask = itsTBBE->boardmask; // for some commands board-id is used ???
+	setBoardMask(itsTBBE->boardmask);
 	
-	for (int boardnr = 0; boardnr < DriverSettings::instance()->maxBoards(); boardnr++) {
-		
-		if (!(itsBoardsMask & (1 << boardnr))) 
-			itsTBBackE->status[boardnr] |= NO_BOARD;
-		
-		if (!(itsBoardsMask & (1 << boardnr)) &&  (itsBoardMask & (1 << boardnr)))
-			itsTBBackE->status[boardnr] |= (SELECT_ERROR | BOARD_SEL_ERROR);
+	for (int boardnr = 0; boardnr < TS->maxBoards(); boardnr++) {
+		if (!TS->isBoardActive(boardnr)) 
+			itsTBBackE->status_mask[boardnr] |= TBB_NO_BOARD;
 	}	
 		
-	// Send only commands to boards installed
-	itsBoardMask = itsBoardMask & itsBoardsMask;
+	// select first boards
+	nextBoardNr();
 	
 	// initialize TP send frame
 	itsTPE->opcode	= TPSTATUS;
@@ -88,78 +83,47 @@ void StatusCmd::saveTbbEvent(GCFEvent& event)
 }
 
 // ----------------------------------------------------------------------------
-bool StatusCmd::sendTpEvent(int32 boardnr, int32)
+void StatusCmd::sendTpEvent()
 {
-	bool sending = false;
-	DriverSettings*		ds = DriverSettings::instance();
-	
-	if (ds->boardPort(boardnr).isConnected() && (itsTBBackE->status[boardnr] == 0)) {
-		ds->boardPort(boardnr).send(*itsTPE);
-		ds->boardPort(boardnr).setTimer(ds->timeout());
-		sending = true;
-	}
-	else
-		itsTBBackE->status[boardnr] |= CMD_ERROR;
-		
-	return(sending);
+		TS->boardPort(getBoardNr()).send(*itsTPE);
+		TS->boardPort(getBoardNr()).setTimer(TS->timeout());
 }
 
 // ----------------------------------------------------------------------------
-void StatusCmd::saveTpAckEvent(GCFEvent& event, int32 boardnr)
+void StatusCmd::saveTpAckEvent(GCFEvent& event)
 {
 	// in case of a time-out, set error mask
 	if (event.signal == F_TIMER) {
-		itsTBBackE->status[boardnr] |= COMM_ERROR;
-	}
-	else {
+		itsTBBackE->status_mask[getBoardNr()] |= TBB_COMM_ERROR;
+	}	else {
 		itsTPackE = new TPStatusackEvent(event);
 		
 		if ((itsTPackE->status >= 0xF0) && (itsTPackE->status <= 0xF6)) 
-			itsTBBackE->status[boardnr] |= (1 << (16 + (itsTPackE->status & 0x0F)));	
+			itsTBBackE->status_mask[getBoardNr()] |= (1 << (16 + (itsTPackE->status & 0x0F)));	
 		
-		itsTBBackE->V12[boardnr]	= itsTPackE->V12;
-		itsTBBackE->V25[boardnr]	= itsTPackE->V25;
-		itsTBBackE->V33[boardnr]	= itsTPackE->V33;
-		itsTBBackE->Tpcb[boardnr]	= itsTPackE->Tpcb;
-		itsTBBackE->Ttp[boardnr]	= itsTPackE->Ttp;
-		itsTBBackE->Tmp0[boardnr]	= itsTPackE->Tmp0;
-		itsTBBackE->Tmp1[boardnr]	= itsTPackE->Tmp1;
-		itsTBBackE->Tmp2[boardnr]	= itsTPackE->Tmp2;
-		itsTBBackE->Tmp3[boardnr]	= itsTPackE->Tmp3;
+		itsTBBackE->V12[getBoardNr()]	= itsTPackE->V12;
+		itsTBBackE->V25[getBoardNr()]	= itsTPackE->V25;
+		itsTBBackE->V33[getBoardNr()]	= itsTPackE->V33;
+		itsTBBackE->Tpcb[getBoardNr()]	= itsTPackE->Tpcb;
+		itsTBBackE->Ttp[getBoardNr()]	= itsTPackE->Ttp;
+		itsTBBackE->Tmp0[getBoardNr()]	= itsTPackE->Tmp0;
+		itsTBBackE->Tmp1[getBoardNr()]	= itsTPackE->Tmp1;
+		itsTBBackE->Tmp2[getBoardNr()]	= itsTPackE->Tmp2;
+		itsTBBackE->Tmp3[getBoardNr()]	= itsTPackE->Tmp3;
 		
-		LOG_DEBUG_STR(formatString("Received StatusAck from boardnr[%d]", boardnr));
+		LOG_DEBUG_STR(formatString("Received StatusAck from boardnr[%d]", getBoardNr()));
 		delete itsTPackE;
 	}
+	nextBoardNr();
 }
 
 // ----------------------------------------------------------------------------
 void StatusCmd::sendTbbAckEvent(GCFPortInterface* clientport)
 {
-	for (int32 boardnr = 0; boardnr < DriverSettings::instance()->maxBoards(); boardnr++) { 
-		if (itsTBBackE->status[boardnr] == 0)
-			itsTBBackE->status[boardnr] = SUCCESS;
+	for (int32 boardnr = 0; boardnr < TS->maxBoards(); boardnr++) { 
+		if (itsTBBackE->status_mask[boardnr] == 0)
+			itsTBBackE->status_mask[boardnr] = TBB_SUCCESS;
 	}
 	
 	clientport->send(*itsTBBackE);
 }
-
-// ----------------------------------------------------------------------------
-CmdTypes StatusCmd::getCmdType()
-{
-	return(BoardCmd);
-}
-
-// ----------------------------------------------------------------------------
-uint32 StatusCmd::getBoardMask()
-{
-	return(itsBoardMask);
-}
-
-// ----------------------------------------------------------------------------
-bool StatusCmd::waitAck()
-{
-	return(true);
-}
-
-	} // end TBB namespace
-} // end LOFAR namespace
diff --git a/MAC/APL/PIC/TBBDriver/src/StatusCmd.h b/MAC/APL/PIC/TBBDriver/src/StatusCmd.h
index ef612d925b7b7c149812dc114c793624b22761b9..c96b9dc7b94a6b22c4bfdebee7d87ea779234333 100644
--- a/MAC/APL/PIC/TBBDriver/src/StatusCmd.h
+++ b/MAC/APL/PIC/TBBDriver/src/StatusCmd.h
@@ -32,6 +32,7 @@
 #include "TP_Protocol.ph"
 
 #include "Command.h"
+#include "DriverSettings.h"
 
 namespace LOFAR {
 	using namespace TBB_Protocol;
@@ -50,21 +51,14 @@ namespace LOFAR {
 				
 				virtual void saveTbbEvent(GCFEvent& event);
 									
-				virtual bool sendTpEvent(int32 boardnr, int32 channelnr);
+				virtual void sendTpEvent();
 
-				virtual void saveTpAckEvent(GCFEvent& event, int32 boardnr);
+				virtual void saveTpAckEvent(GCFEvent& event);
 
 				virtual void sendTbbAckEvent(GCFPortInterface* clientport);
-				
-				virtual uint32 getBoardMask();
-				
-				virtual bool waitAck();
-				
-				virtual CmdTypes getCmdType();
-      
+				      
 			private:
-				uint32	itsBoardMask;  // mask indicates the boards to communicate with
-				uint32	itsBoardsMask;	// Installed boards mask
+				TbbSettings *TS;
 				
 				TPStatusEvent			*itsTPE;
 				TPStatusackEvent	*itsTPackE;
diff --git a/MAC/APL/PIC/TBBDriver/src/StopCmd.cc b/MAC/APL/PIC/TBBDriver/src/StopCmd.cc
index 804b66ae96d6db78150149bd8fcf929ad3154497..571b29d92e91e03187ef6e6c82236a3a64794f5c 100644
--- a/MAC/APL/PIC/TBBDriver/src/StopCmd.cc
+++ b/MAC/APL/PIC/TBBDriver/src/StopCmd.cc
@@ -24,26 +24,27 @@
 #include <Common/LofarLogger.h>
 
 #include "StopCmd.h"
-#include "DriverSettings.h"
 
-namespace LOFAR {
-	using namespace TBB_Protocol;
-	using namespace TP_Protocol;
-	namespace TBB {
+using namespace LOFAR;
+using namespace TBB_Protocol;
+using namespace TP_Protocol;
+using	namespace TBB;
 
 //--Constructors for a StopCmd object.----------------------------------------
 StopCmd::StopCmd():
-		itsBoardMask(0),itsBoardsMask(0),itsChannel(0)
+		itsRcuStatus(0)
 {
+	TS					= TbbSettings::instance();
 	itsTPE 			= new TPStopEvent();
 	itsTPackE 	= 0;
 	itsTBBE 		= 0;
 	itsTBBackE 	= new TBBStopackEvent();
 	
 	for(int boardnr = 0;boardnr < MAX_N_TBBBOARDS;boardnr++) { 
-		itsTBBackE->status[boardnr]	= 0;
+		itsTBBackE->status_mask[boardnr]	= 0;
 		itsChannelMask[boardnr]	= 0;
-	}		
+	}
+	setWaitAck(true);		
 }
 	  
 //--Destructor for StopCmd.---------------------------------------------------
@@ -65,31 +66,40 @@ bool StopCmd::isValid(GCFEvent& event)
 // ----------------------------------------------------------------------------
 void StopCmd::saveTbbEvent(GCFEvent& event)
 {
-	itsTBBE 			= new TBBStopEvent(event);
-		
-	// mask for the installed boards
-	itsBoardsMask = DriverSettings::instance()->activeBoardsMask();
+	itsTBBE	= new TBBStopEvent(event);
 		
-	for (int boardnr = 0; boardnr < DriverSettings::instance()->maxBoards(); boardnr++) {
-		
-		if (!(itsBoardsMask & (1 << boardnr))) 
-			itsTBBackE->status[boardnr] |= NO_BOARD;
+	// convert rcu-bitmask to tbb-channelmask
+	int boardnr;
+	int channelnr;
+	for (int rcunr = 0; rcunr < TS->maxChannels(); rcunr++) {
+		if(itsTBBE->rcu_mask.test(rcunr)) {
+			TS->convertRcu2Ch(rcunr,&boardnr,&channelnr);	
+			itsChannelMask[boardnr] |= (1 << channelnr);
+		}
+	} 
+	
+	uint32 boardmask = 0;		
+	for (int boardnr = 0; boardnr < TS->maxBoards(); boardnr++) {
+		if (itsChannelMask[boardnr] != 0) boardmask |= (1 << boardnr); 
+			
+		if (!TS->isBoardActive(boardnr)) { 
+			itsTBBackE->status_mask[boardnr] |= TBB_NO_BOARD;
+		}
 		
-		itsChannelMask[boardnr] = itsTBBE->channelmask[boardnr]; 		
+		if ((itsChannelMask[boardnr] & ~0xFFFF) != 0) {
+			itsTBBackE->status_mask[boardnr] |= (TBB_SELECT_ERROR | TBB_CHANNEL_SEL_ERROR);
+		}
 		
-		if (itsChannelMask[boardnr] != 0)
-			itsBoardMask |= (1 << boardnr);
-			
-		if ((itsChannelMask[boardnr] & ~0xFFFF) != 0) 
-			itsTBBackE->status[boardnr] |= (SELECT_ERROR | CHANNEL_SEL_ERROR);
-				
-		if (!(itsBoardsMask & (1 << boardnr)) &&  (itsChannelMask[boardnr] != 0))
-			itsTBBackE->status[boardnr] |= (SELECT_ERROR | BOARD_SEL_ERROR);
-		LOG_DEBUG_STR(formatString("StopCmd savetbb boardnr[%d], status[0x%x]",boardnr, itsTBBackE->status[boardnr]));
+		if (!TS->isBoardActive(boardnr) &&  (itsChannelMask[boardnr] != 0)) {
+			itsTBBackE->status_mask[boardnr] |= (TBB_SELECT_ERROR | TBB_BOARD_SEL_ERROR);
+		}
+		LOG_DEBUG_STR(formatString("StopCmd savetbb boardnr[%d], status[0x%x]",boardnr, itsTBBackE->status_mask[boardnr]));
 	}
+		
+	setBoardMask(boardmask);
 	
-	// Send only commands to boards installed
-	itsBoardMask = itsBoardMask & itsBoardsMask;
+	// select firt channel to handle
+	nextChannelNr();
 	
 	// initialize TP send frame
 	itsTPE->opcode			= TPSTOP;
@@ -99,80 +109,77 @@ void StopCmd::saveTbbEvent(GCFEvent& event)
 }
 
 // ----------------------------------------------------------------------------
-bool StopCmd::sendTpEvent(int32 boardnr, int32 channelnr)
+void StopCmd::sendTpEvent()
 {
-	bool sending = false;
-	DriverSettings*		ds = DriverSettings::instance();
+	itsRcuStatus = 0;
+		
+	itsTPE->channel = TS->getChInputNr(getChannelNr());
 	
-	itsTPE->channel = DriverSettings::instance()->getChInputNr(channelnr);
-	itsChannel = channelnr;
+	if (TS->getChState(getChannelNr()) != 'R') {
+		itsRcuStatus |= TBB_RCU_NOT_RECORDING;
+	}
 	
-	if	(ds->boardPort(boardnr).isConnected() &&
-			(itsTBBackE->status[boardnr] == 0) &&
-			(DriverSettings::instance()->getChStatus(channelnr) == 'R')) {
-		
-		ds->boardPort(boardnr).send(*itsTPE);
-		ds->boardPort(boardnr).setTimer(ds->timeout());
-		sending = true;
+	if ((itsTBBackE->status_mask[getBoardNr()] == 0) && (itsRcuStatus == 0)) {
+		TS->boardPort(getBoardNr()).send(*itsTPE);
+		TS->boardPort(getBoardNr()).setTimer(TS->timeout());
+		LOG_DEBUG_STR(formatString("Sending StopCmd to boardnr[%d], channel[%08X]", getBoardNr(), itsTPE->channel));
 	}
-	else
-		itsTBBackE->status[boardnr] |= CMD_ERROR;
-		
-	LOG_DEBUG_STR(formatString("StopCmd sendtp boardnr[%d], status[0x%x]",boardnr, itsTBBackE->status[boardnr]));
-	return(sending);
 }
 
 // ----------------------------------------------------------------------------
-void StopCmd::saveTpAckEvent(GCFEvent& event, int32 boardnr)
+void StopCmd::saveTpAckEvent(GCFEvent& event)
 {
 	// in case of a time-out, set error mask
 	if (event.signal == F_TIMER) {
-		itsTBBackE->status[boardnr] |= COMM_ERROR;
+		itsTBBackE->status_mask[getBoardNr()] |= TBB_RCU_COMM_ERROR;
+		itsRcuStatus |= TBB_TIMEOUT_ETH;
 	}
 	else {
 		itsTPackE = new TPStopackEvent(event);
 		
 		if ((itsTPackE->status >= 0xF0) && (itsTPackE->status <= 0xF6)) 
-			itsTBBackE->status[boardnr] |= (1 << (16 + (itsTPackE->status & 0x0F)));
+			itsRcuStatus |= (1 << (16 + (itsTPackE->status & 0x0F)));
 		
-		if (itsTPackE->status == 0)
-			DriverSettings::instance()->setChStatus(itsChannel, 'S'); 	
+		if ((itsTPackE->status == 0) && (itsRcuStatus == 0))
+			TS->setChState(getChannelNr(), 'S'); 	
 		
-		LOG_DEBUG_STR(formatString("StopCmd savetp boardnr[%d], status[0x%x]",boardnr, itsTBBackE->status[boardnr]));
-		LOG_DEBUG_STR(formatString("Received StopAck from boardnr[%d]", boardnr));
+		LOG_DEBUG_STR(formatString("Received StopCmd savetp boardnr[%d], status[0x%x]",
+			getBoardNr(), itsTBBackE->status_mask[getBoardNr()]));
 		delete itsTPackE;
 	}
+	
+	if (itsRcuStatus) TS->setChState(getChannelNr(), 'E');
+	TS->setChStatus(getChannelNr(),(uint16)(itsRcuStatus >> 16));
+	
+	if (itsRcuStatus || itsTBBackE->status_mask[getBoardNr()]) {
+		int32 rcu;
+		TS->convertCh2Rcu(getChannelNr(),&rcu);
+		LOG_INFO_STR(formatString("ERROR StopCmd Rcu[%d], DriverStatus[0x%x], RcuStatus[0x%x]",
+			rcu, itsTBBackE->status_mask[getBoardNr()],itsRcuStatus));
+	}
+	itsTBBackE->status_mask[getBoardNr()] |= itsRcuStatus;
+	nextChannelNr();
 }
 
 // ----------------------------------------------------------------------------
 void StopCmd::sendTbbAckEvent(GCFPortInterface* clientport)
 {
-	for (int32 boardnr = 0; boardnr < DriverSettings::instance()->maxBoards(); boardnr++) { 
-		if (itsTBBackE->status[boardnr] == 0)
-			itsTBBackE->status[boardnr] = SUCCESS;
-		LOG_DEBUG_STR(formatString("StopCmd sendtbb status[0x%x]", itsTBBackE->status[boardnr]));		
+	int32 rcunr;
+	
+	itsTBBackE->rcu_mask.reset();
+	for (int32 channelnr = 0; channelnr < TS->maxChannels(); channelnr++) {
+		if (TS->getChStatus(channelnr)) {
+			TS->convertCh2Rcu(channelnr,&rcunr);
+			itsTBBackE->rcu_mask.set(rcunr);
+		}
+	}
+	
+	for (int32 boardnr = 0; boardnr < TS->maxBoards(); boardnr++) { 
+		if (itsTBBackE->status_mask[boardnr] == 0)
+			itsTBBackE->status_mask[boardnr] = TBB_SUCCESS;
+		LOG_DEBUG_STR(formatString("StopCmd sendtbb status[0x%x]", itsTBBackE->status_mask[boardnr]));		
 	}
 	
 	clientport->send(*itsTBBackE);
 }
 
-// ----------------------------------------------------------------------------
-uint32 StopCmd::getBoardMask()
-{
-	return(itsBoardMask);
-}
-
-// ----------------------------------------------------------------------------
-CmdTypes StopCmd::getCmdType()
-{
-	return(ChannelCmd);
-}
-
-// ----------------------------------------------------------------------------
-bool StopCmd::waitAck()
-{
-	return(true);
-}
-
-	} // end TBB namespace
-} // end LOFAR namespace
diff --git a/MAC/APL/PIC/TBBDriver/src/StopCmd.h b/MAC/APL/PIC/TBBDriver/src/StopCmd.h
index 312745be44042a5675eec0d3bd60b03f28dac9c1..daeed824935ffadad46367c0a098c1aae142c6af 100644
--- a/MAC/APL/PIC/TBBDriver/src/StopCmd.h
+++ b/MAC/APL/PIC/TBBDriver/src/StopCmd.h
@@ -32,6 +32,7 @@
 #include "TP_Protocol.ph"
 
 #include "Command.h"
+#include "DriverSettings.h"
 
 namespace LOFAR {
 	using namespace TBB_Protocol;
@@ -50,24 +51,17 @@ namespace LOFAR {
 				
 				virtual void saveTbbEvent(GCFEvent& event);
 									
-				virtual bool sendTpEvent(int32 boardnr, int32 channelnr);
+				virtual void sendTpEvent();
 
-				virtual void saveTpAckEvent(GCFEvent& event, int32 boardnr);
+				virtual void saveTpAckEvent(GCFEvent& event);
 
 				virtual void sendTbbAckEvent(GCFPortInterface* clientport);
-				
-				virtual uint32 getBoardMask();
-				
-				virtual bool waitAck();
-				
-				virtual CmdTypes getCmdType();
-				
 				      
 			private:
-				uint32	itsBoardMask;  // mask indicates the boards to communicate with
-				uint32	itsBoardsMask;	// Installed boards mask
+				TbbSettings *TS;
+				
 				uint32	itsChannelMask[MAX_N_TBBBOARDS];
-				uint32	itsChannel;
+				uint32	itsRcuStatus;
 				
 				TPStopEvent			*itsTPE;
 				TPStopackEvent	*itsTPackE;
diff --git a/MAC/APL/PIC/TBBDriver/src/TBBDriver.cc b/MAC/APL/PIC/TBBDriver/src/TBBDriver.cc
index 487d3a06604165e393485d35ca0f9f5f00052c59..f5ee675f8210e2755ab39571d9350237e5c06675 100644
--- a/MAC/APL/PIC/TBBDriver/src/TBBDriver.cc
+++ b/MAC/APL/PIC/TBBDriver/src/TBBDriver.cc
@@ -26,9 +26,9 @@
 #include <Common/LofarLocators.h>
 #include <APS/ParameterSet.h>
 #include <GCF/GCF_ServiceInfo.h>
+//#include <string>
 
 #include "TBBDriver.h"
-#include "DriverSettings.h"
 #include "RawEvent.h" 
 
 // include all cmd and msg classes
@@ -49,6 +49,7 @@
 #include "ErasefCmd.h"
 #include "ReadfCmd.h"
 #include "WritefCmd.h"
+#include "ImageInfoCmd.h"
 #include "ReadwCmd.h"
 #include "WritewCmd.h"
 #include "ReadrCmd.h"
@@ -65,7 +66,7 @@ using namespace TBB;
 
 static int32    g_instancenr = -1;
 
-static const double ALIVECHECKTIME = 60.0;
+static const long ALIVECHECKTIME = 60;
 
 /*
 //
@@ -112,16 +113,19 @@ void parseOptions(int argc, char** argv)
 TBBDriver::TBBDriver(string name)
   : GCFTask((State)&TBBDriver::init_state, name)
 {
+	// use TS->getXXX() tot get settings of the driver
+	TS	= TbbSettings::instance();
+	
+	// get settings adopted from config file
+  TS->getTbbSettings();
+  
 	cmd = 0;
-	itsActiveBoards = 0xFF000000;
+	itsActiveBoards = 0x00000000;
 	itsAliveCheck = false;
+	itsSizeCheck = false;
 	itsActiveBoardsChange = false;
-	
-  // setting up driver settings
-  DriverSettings*		tbb_ds = DriverSettings::instance();
-  tbb_ds->setMaxBoards(MAX_N_TBBBOARDS);
-	tbb_ds->setTimeOut(globalParameterSet()->getDouble("TBBDriver.TP_TIMEOUT"));  
-    
+	itsResetCount = 0;
+  
   // tell broker we are here
   LOG_DEBUG("Registering protocols");
   registerProtocol(TBB_PROTOCOL, TBB_PROTOCOL_signalnames);
@@ -137,55 +141,34 @@ TBBDriver::TBBDriver(string name)
 
   // open port with TBB board
   LOG_DEBUG("Connecting to TBB boards");
-	itsBoard = new GCFETHRawPort[tbb_ds->maxBoards()];
+	itsBoard = new GCFETHRawPort[TS->maxBoards()];
   ASSERT(itsBoard);
 	
-	tbb_ds->setBoardPorts(itsBoard);
-	
-	itsMsgPort.init(*this, "MsgPort", GCFPortInterface::SAP, TBB_PROTOCOL);
-
-  // Attempt access of TBBDriver.MAC_BASE, if it fails use the TBBDriver.ADDR0
-  // parameters.
-  //
-  bool bUseMAC_BASE = true;
-  try {
-		(void)globalParameterSet()->getInt32("TBBDriver.MAC_BASE"); 
-	}
-  catch (...) {
-		bUseMAC_BASE = false;
-	}
-
   char boardname[64];
-  char paramname[64];
-  char macaddrstr[64];
+	for (int boardnr = 0; boardnr < TS->maxBoards(); boardnr++) {
+		snprintf(boardname, 64, "board%d", boardnr);
 
-	for (int boardid = 0; boardid < tbb_ds->maxBoards(); boardid++) {
-		snprintf(boardname, 64, "board%d", boardid);
+		LOG_DEBUG_STR("initializing board " << boardname << ":" << TS->getSrcMac(boardnr).c_str());
+		itsBoard[boardnr].init(*this, boardname, GCFPortInterface::SAP, TP_PROTOCOL,true /*raw*/);
 		
-		if (bUseMAC_BASE) {
-			snprintf(macaddrstr, 64, "10:FA:00:00:%02x:02", boardid + globalParameterSet()->getInt32("TBBDriver.MAC_BASE"));
-		}
-		else {
-			snprintf(paramname, 64, "TBBDriver.MAC_ADDR_%d", boardid);
-			strcpy(macaddrstr, globalParameterSet()->getString(paramname).c_str());
-		}
-
-		LOG_DEBUG_STR("initializing board " << boardname << ":" << macaddrstr);
-		itsBoard[boardid].init(*this, boardname, GCFPortInterface::SAP, TP_PROTOCOL,true /*raw*/);
-		LOG_DEBUG_STR("setAddr " << boardname << ":" << macaddrstr);
-		itsBoard[boardid].setAddr(globalParameterSet()->getString("TBBDriver.IF_NAME").c_str(), macaddrstr);
+		LOG_DEBUG_STR("setAddr " << boardname << ":" << TS->getSrcMac(boardnr).c_str());
+		itsBoard[boardnr].setAddr(TS->getIfName().c_str(), TS->getSrcMac(boardnr).c_str());
 		
 		// set ethertype to 0x7BB0 so Ethereal can decode TBB messages
-		itsBoard[boardid].setEtherType(ETHERTYPE_TP);
+		itsBoard[boardnr].setEtherType(ETHERTYPE_TP);
 	}
-	 
+	
+	for (int bn = 0; bn < TS->maxBoards();bn++) {
+		TS->setBoardPorts(bn,&itsBoard[bn]);	
+	}
+	
 	 // create cmd & msg handler
 	LOG_DEBUG_STR("initializing handlers");
 	cmdhandler = new BoardCmdHandler();
 	msghandler = new MsgHandler();
-		
-	cmdhandler->setTpRetries(globalParameterSet()->getInt32("TBBDriver.TP_RETRIES"));
 	
+	itsResetCount = new int32[TS->maxBoards()];
+	memset(itsResetCount,0,sizeof(int32)*TS->maxBoards());
 	 	 	 
 	// set Tbb queue
 	LOG_DEBUG_STR("initializing TbbQueue");
@@ -227,21 +210,32 @@ GCFEvent::TResult TBBDriver::init_state(GCFEvent& event, GCFPortInterface& port)
 		}	break;
 		
 		case F_CONNECTED: {
-      LOG_INFO(formatString("CONNECTED: port '%s'", port.getName().c_str()));
+      LOG_INFO_STR(formatString("CONNECTED: port '%s'", port.getName().c_str()));
 			
-			if (isEnabled()) {
-				TPClearEvent clear;
-				clear.opcode = TPCLEAR;
-				clear.status = 0;
-				for (int32 bnr = 0; bnr < DriverSettings::instance()->maxBoards(); bnr++) {
-					itsBoard[bnr].send(clear);	
-					LOG_DEBUG(formatString("CLEAR: board on port '%s'", itsBoard[bnr].getName().c_str()));
-				} 
+			if (isEnabled() && !itsAcceptor.isConnected()) {
+ 				// free all inputs on all boards
+ 				TPFreeEvent free;
+ 				free.opcode = TPFREE;
+ 				free.status = 0;
+ 				free.channel = 0xFFFFFFFF;  // send channel = -1 to free all inputs
+ 				for (int32 bnr = 0; bnr < TS->maxBoards(); bnr++) {
+ 					itsBoard[bnr].send(free);	
+ 					LOG_DEBUG(formatString("FREE -1 is send to port '%s'", itsBoard[bnr].getName().c_str()));
+ 				}  
+// 				// clear all boards(FPGA register are set to 0 and firmware is maintained)
+// 				TPClearEvent clear;
+// 				clear.opcode = TPCLEAR;
+// 				clear.status = 0;
+// 				for (int32 bnr = 0; bnr < TS->maxBoards(); bnr++) {
+// 					itsBoard[bnr].send(clear);	
+// 					LOG_DEBUG(formatString("CLEAR is send to port '%s'", itsBoard[bnr].getName().c_str()));
+// 				}
 				itsAcceptor.open();
 			}	      			
 			if (itsAcceptor.isConnected()) {
-      	itsAcceptor.setTimer((long)4);
-      	TRAN(TBBDriver::idle_state);
+				
+				TRAN(TBBDriver::idle_state);
+				itsAcceptor.setTimer((long)0);
       }
     } break;
 		
@@ -273,14 +267,11 @@ GCFEvent::TResult TBBDriver::idle_state(GCFEvent& event, GCFPortInterface& port)
         
 		case F_ENTRY:	{
 			// look if there is an Tbb command in queue
-			
 			if (!itsTbbQueue->empty()) {
-				GCFEvent e;
-				
-				e.signal = itsTbbQueue->front().signal; //tbbevent->signal;
-				
-				SetTbbCommand(itsTbbQueue->front().signal);
+				LOG_DEBUG_STR("The queue is NOT empty");
 				
+				GCFEvent e(itsTbbQueue->front().signal);
+				SetTbbCommand(e.signal);
 				status = cmdhandler->dispatch(e,*itsTbbQueue->front().port);
 				
 				itsTbbQueue->pop_front();
@@ -289,19 +280,18 @@ GCFEvent::TResult TBBDriver::idle_state(GCFEvent& event, GCFPortInterface& port)
 		}	break;
         
 		case F_CONNECTED:	{
-			LOG_INFO(formatString("CONNECTED: port '%s'", port.getName().c_str()));
+			LOG_DEBUG_STR(formatString("CONNECTED: port '%s'", port.getName().c_str()));
 		}	break;
 		
 		case F_DISCONNECTED: {
 			
-			LOG_INFO(formatString("DISCONNECTED: port '%s'", port.getName().c_str()));
+			LOG_DEBUG_STR(formatString("DISCONNECTED: port '%s'", port.getName().c_str()));
       port.close();
       		
 			if (&port == &itsAcceptor) {
         LOG_FATAL("Failed to start listening for client connections.");
         exit(EXIT_FAILURE);
-      }
-      else {
+      } else {
 				itsClientList.remove(&port);
         itsDeadClients.push_back(&port);
       }
@@ -313,7 +303,7 @@ GCFEvent::TResult TBBDriver::idle_state(GCFEvent& event, GCFPortInterface& port)
       itsAcceptor.accept(*client);
       itsClientList.push_back(client);
 
-      LOG_INFO(formatString("NEW CLIENT CONNECTED: %d clients connected", itsClientList.size()));
+      LOG_DEBUG_STR(formatString("NEW CLIENT CONNECTED: %d clients connected", itsClientList.size()));
 		} break;
 		
 		case F_DATAIN: {
@@ -321,7 +311,6 @@ GCFEvent::TResult TBBDriver::idle_state(GCFEvent& event, GCFPortInterface& port)
 		}	break;
 		
 		case F_TIMER: {
-			LOG_DEBUG("F_TIMER in idle_state");
 			if (&port == &itsAcceptor) {
 				CheckAlive(event, port);
 				TRAN(TBBDriver::busy_state);
@@ -330,33 +319,26 @@ GCFEvent::TResult TBBDriver::idle_state(GCFEvent& event, GCFPortInterface& port)
 				
 		case TBB_GETCONFIG: {
 			TBBGetconfigackEvent ack;
-			ack.max_boards = DriverSettings::instance()->maxBoards();
-			ack.active_boards = DriverSettings::instance()->activeBoardsMask();
+			ack.max_boards = TS->maxBoards();
+			ack.active_boards_mask = TS->activeBoardsMask();
 			port.send(ack); 
 		} break;
 		
-		case TBB_SIZE: {
-			TBBSizeackEvent ack;
-			for (int32 boardnr = 0; boardnr < DriverSettings::instance()->maxBoards(); boardnr++) {
-				ack.status[boardnr] = 0;
-			}
-			for (int32 boardnr = 0; boardnr < DriverSettings::instance()->maxBoards(); boardnr++) {
-				if (!(DriverSettings::instance()->activeBoardsMask() & (1 << boardnr)))
-					ack.status[boardnr] |= NO_BOARD; 
-				if (ack.status[boardnr] == 0) ack.status[boardnr] = SUCCESS; 
-				ack.npages[boardnr] = DriverSettings::instance()->getMemorySize(boardnr);
-			}
-			port.send(ack); 
-		} break;
-		
-		case TBB_CHANNELINFO: {
-			TBBChannelinfoackEvent ack;
-			for (int32 ch = 0; ch < DriverSettings::instance()->maxChannels(); ch++) {
-				ack.channelstatus[ch] = (uint32)DriverSettings::instance()->getChStatus(ch);
-				ack.channelstartaddr[ch] = DriverSettings::instance()->getChStartAddr(ch);
-				ack.channelsize[ch] = DriverSettings::instance()->getChPageSize(ch);
-				ack.channelplace[ch] = ((DriverSettings::instance()->getChBoardNr(ch) << 16) |
-														(DriverSettings::instance()->getChInputNr(ch) & 0xFFFF));
+		case TBB_RCUINFO: {
+			TBBRcuinfoackEvent ack;
+			int rcu;
+			for (int32 ch = 0; ch < TS->maxChannels(); ch++) {
+				rcu = TS->getChRcuNr(ch);
+				//LOG_INFO(formatString("info for ch %d rcu.%d", ch, rcu));
+				ack.rcu_status[rcu] = (uint16)TS->getChStatus(ch);
+				ack.rcu_state[rcu] = TS->getChState(ch);
+				ack.rcu_start_addr[rcu] = TS->getChStartAddr(ch);
+				ack.rcu_pages[rcu] = TS->getChPageSize(ch);
+				ack.rcu_on_board[rcu] = (uint8)TS->getChBoardNr(ch);
+				ack.rcu_on_input[rcu] = (uint8)TS->getChInputNr(ch);
+				
+				//LOG_DEBUG_STR(formatString("Channel %d ,Rcu %d = status[0x%04X] state[%c] addr[%u] pages[%u]"
+				//	,ch,TS->getChRcuNr(ch), TS->getChStatus(ch), TS->getChState(ch),TS->getChStartAddr(ch),TS->getChPageSize(ch)));
 			}
 			port.send(ack); 
 		} break;
@@ -380,12 +362,13 @@ GCFEvent::TResult TBBDriver::idle_state(GCFEvent& event, GCFPortInterface& port)
 		default: {
 			// look if the event is a Tbb event
 			if (SetTbbCommand(event.signal)) {
+				//itsAcceptor.cancelAllTimers();
 				status = cmdhandler->dispatch(event,port);
 				TRAN(TBBDriver::busy_state);
-			}
+			} else {
 			// if not a Tbb event, return not-handled 
-			else
 				status = GCFEvent::NOT_HANDLED;
+			}
 		}	break;
 	}
 	return(status);
@@ -398,7 +381,7 @@ GCFEvent::TResult TBBDriver::busy_state(GCFEvent& event, GCFPortInterface& port)
 {
 	GCFEvent::TResult status = GCFEvent::HANDLED;    
 	
-	LOG_INFO_STR(formatString("event.signal = [%d]",event.signal));
+	//LOG_INFO_STR(formatString("event.signal = [%d]",event.signal));
 	switch(event.signal) {
 		case F_INIT: {
 		} break;
@@ -413,16 +396,18 @@ GCFEvent::TResult TBBDriver::busy_state(GCFEvent& event, GCFPortInterface& port)
 		}	break;
 		
 		case F_TIMER: {
-			LOG_DEBUG("F_TIMER in busy_state");
 			if (itsAliveCheck) {
 				if (CheckAlive(event, port))
 					TRAN(TBBDriver::idle_state);
 			}
-			if (&port != &itsAcceptor) 
+			if (&port != &itsAcceptor) { 
 				status = cmdhandler->dispatch(event,port); // dispatch time-out event	
+			}
 		} break;
 		
 		case F_DISCONNECTED: {
+			LOG_DEBUG("done_0");
+			itsAcceptor.setTimer((long)1);
 			TRAN(TBBDriver::idle_state);	
 		}	break;
 		
@@ -434,14 +419,7 @@ GCFEvent::TResult TBBDriver::busy_state(GCFEvent& event, GCFPortInterface& port)
 		}	break;
 		
 		case TP_ALIVEACK: {
-			if (CheckAlive(event, port)) {
-				//cmdhandler->setActiveBoards(itsActiveBoards); 
-				TRAN(TBBDriver::idle_state);
-			}
-		} break;
-		
-		case TP_SIZEACK: {
-			LOG_DEBUG("TP_SIZEACK");
+			LOG_DEBUG("TP_ALIVEACK received");
 			if (CheckAlive(event, port)) {
 				TRAN(TBBDriver::idle_state);
 			}
@@ -449,8 +427,8 @@ GCFEvent::TResult TBBDriver::busy_state(GCFEvent& event, GCFPortInterface& port)
 		
 		case TBB_GETCONFIG: {
 			TBBGetconfigackEvent ack;
-			ack.max_boards = DriverSettings::instance()->maxBoards();
-			ack.active_boards = itsActiveBoards;
+			ack.max_boards = TS->maxBoards();
+			ack.active_boards_mask = itsActiveBoards;
 			port.send(ack); 
 		
 		} break;
@@ -480,9 +458,9 @@ GCFEvent::TResult TBBDriver::busy_state(GCFEvent& event, GCFPortInterface& port)
 		case TP_UDPACK:
 		case TP_PAGEPERIODACK:	
 		case TP_VERSIONACK:
-		//case TP_SIZEACK:
 		case TP_STATUSACK:
 		case TP_CLEARACK:
+		case TP_SIZEACK:	
 		case TP_RESETACK:
 		case TP_CONFIGACK:
 		case TP_ERASEFACK:
@@ -495,15 +473,20 @@ GCFEvent::TResult TBBDriver::busy_state(GCFEvent& event, GCFPortInterface& port)
 		case TP_READXACK:	
 		{
 			status = cmdhandler->dispatch(event,port); // dispatch ack from boards
-			if (cmdhandler->tpCmdDone()){
+			if (cmdhandler->tpCmdDone() == true){
+				// set ALIVE timer
+				LOG_DEBUG("done_1");
+				itsAcceptor.setTimer((long)1);
 				TRAN(TBBDriver::idle_state);
 			}
 		}	break;	
-		
-								
+										
 		default: {
 			LOG_DEBUG("DEFAULT");
-			if (cmdhandler->tpCmdDone()){
+			if (cmdhandler->tpCmdDone() == true){
+				// set ALIVE timer
+				LOG_DEBUG("done_2");
+				itsAcceptor.setTimer((long)1);
 				TRAN(TBBDriver::idle_state);
 			}
 			// put event on the queue
@@ -535,7 +518,7 @@ void TBBDriver::undertaker()
 void TBBDriver::openBoards()
 {
 	LOG_DEBUG_STR("opening boards");
-	for (int boardnr = 0; boardnr < DriverSettings::instance()->maxBoards(); boardnr++) {
+	for (int boardnr = 0; boardnr < TS->maxBoards(); boardnr++) {
 		if (itsBoard[boardnr].isConnected())
 			itsBoard[boardnr].close();
 		itsBoard[boardnr].open();
@@ -548,7 +531,7 @@ void TBBDriver::openBoards()
 bool TBBDriver::isEnabled()
 {
   bool enabled = true;
-	for (int boardnr = 0; boardnr < DriverSettings::instance()->maxBoards(); boardnr++)
+	for (int boardnr = 0; boardnr < TS->maxBoards(); boardnr++)
 	{
     if (!itsBoard[boardnr].isConnected())
     {
@@ -569,50 +552,66 @@ bool TBBDriver::CheckAlive(GCFEvent& event, GCFPortInterface& port)
 	
 	if (!itsAliveCheck) {
 		itsAliveCheck	= true;
-		boardnr = 0;
+		boardnr				= 0;
 		checkmask			= 0;
 		activeboards	= 0;
 		
-		for(int nr = 0; nr < DriverSettings::instance()->maxBoards(); nr++) {
-			//itsBoard[boardnr].send(*itsAlive);
-			//itsBoard[boardnr].send(*itsSize);
-			//itsBoard[boardnr].setTimer(0.5);
+		for(int nr = 0; nr < TS->maxBoards(); nr++) {
 			checkmask |= (1 << nr);
 		}
-		itsBoard[boardnr].send(*itsSize);
-		itsBoard[boardnr].setTimer(DriverSettings::instance()->timeout());
-	}
-	else {
-		//port.cancelAllTimers();
+		itsBoard[boardnr].send(*itsAlive);
+		itsBoard[boardnr].setTimer(TS->timeout());
+	} else {
 		itsBoard[boardnr].cancelAllTimers();
 		checkmask &= ~(1 << boardnr);
-		//LOG_DEBUG_STR(formatString("Received SizeAck from boardnr[%d]",boardnr));
-		DriverSettings::instance()->setMemorySize(boardnr,0);
-		if ((event.signal == TP_SIZEACK) && (&port == &itsBoard[boardnr])){
+		if ((event.signal == TP_ALIVEACK) && (&port == &itsBoard[boardnr])){
 			activeboards |= (1 << boardnr);
-			TPSizeackEvent ack(event);
-			LOG_DEBUG_STR(formatString("Received SizeAck from boardnr[%d][%u]",boardnr,ack.npages));
-			DriverSettings::instance()->setMemorySize(boardnr,ack.npages);
+			TPAliveackEvent ack(event);
+			if (ack.resetflag == 0){
+				itsResetCount[boardnr]++;
+				TS->clearRcuSettings(boardnr);
+				LOG_INFO_STR(formatString("=BOARD-RESET=, TBB board %d has been reset %d times",boardnr,itsResetCount[boardnr]));
+			}
 		}
 		boardnr++;
-		if (boardnr < DriverSettings::instance()->maxBoards()) {
-			itsBoard[boardnr].send(*itsSize);
-			itsBoard[boardnr].setTimer(DriverSettings::instance()->timeout());
+		if (boardnr < TS->maxBoards()) {
+			itsBoard[boardnr].send(*itsAlive);
+			itsBoard[boardnr].setTimer(TS->timeout());
 		}
-		
 	}
+	
 	if (checkmask == 0) {
 		if (activeboards != itsActiveBoards) {
 			itsActiveBoards = activeboards;
-			DriverSettings::instance()->setActiveBoards(itsActiveBoards);
+			TS->setActiveBoards(itsActiveBoards);
 			itsActiveBoardsChange = true;
+		
+			string boardstr;
+			for (int i = 0; i < 12; i++) {
+				boardstr += " ";
+				if (activeboards & (1 << i)) {
+					if (i >= 9) {
+						boardstr += "1";
+						boardstr += i+38;
+					} else {			
+						boardstr += i+48;
+					}
+				} else {
+					boardstr += ".";
+				}
+			}
+			LOG_INFO_STR("Available TBB boards changed:" + boardstr);	
+		}
+		LOG_DEBUG_STR("Active TBB boards check");
+		if (itsActiveBoards == 0) {
+			itsAcceptor.setTimer((long)5);
+		} else {
+			itsAcceptor.setTimer(ALIVECHECKTIME);
 		}
-		LOG_INFO_STR(formatString("Active boards: [0x%03X]",itsActiveBoards));
 		itsAliveCheck = false;
-		itsAcceptor.setTimer(ALIVECHECKTIME);
 		done = true;
 	}
-	return(done);
+	return(!itsAliveCheck);
 }
 
 //-----------------------------------------------------------------------------
@@ -658,7 +657,7 @@ bool TBBDriver::SetTbbCommand(unsigned short signal)
 			cmdhandler->setTpCmd(cmd);
 		} break;
 		
-		case TBB_UDP: {
+		case TBB_MODE: {
 			UdpCmd *cmd;
 			cmd = new UdpCmd();
 			cmdhandler->setTpCmd(cmd);
@@ -706,25 +705,32 @@ bool TBBDriver::SetTbbCommand(unsigned short signal)
 			cmdhandler->setTpCmd(cmd);
 		} break;
 		
-		case TBB_ERASEF:	{
+		case TBB_ERASE_IMAGE:	{
 			ErasefCmd *cmd;
 			cmd = new ErasefCmd();
 			cmdhandler->setTpCmd(cmd);
 		} break;
 		
-		case TBB_READF:	{
+		case TBB_READ_IMAGE:	{
 			ReadfCmd *cmd;
 			cmd = new ReadfCmd();
 			cmdhandler->setTpCmd(cmd);
 		} break;
 		
-		case TBB_WRITEF:
+		case TBB_WRITE_IMAGE:
 		{
 			WritefCmd *cmd;
 			cmd = new WritefCmd();
 			cmdhandler->setTpCmd(cmd);
 		} break;
-
+		
+		case TBB_IMAGE_INFO:
+		{
+			ImageInfoCmd *cmd;
+			cmd = new ImageInfoCmd();
+			cmdhandler->setTpCmd(cmd);
+		} break;
+		
 		case TBB_READW: {
 			ReadwCmd *cmd;
 			cmd = new ReadwCmd();
@@ -756,10 +762,12 @@ bool TBBDriver::SetTbbCommand(unsigned short signal)
 		} break;
 		
 		default: {
-			return(false);
-		}
+			return (false);		
+		} break;
 	}
-	return(true);
+	
+	itsAcceptor.cancelAllTimers();
+	return (true);
 }
 
   //} // end namespace TBB
@@ -791,7 +799,7 @@ int main(int argc, char** argv)
   LOG_DEBUG ("Reading configuration files");
   try {
   	LOFAR::ConfigLocator cl;
-		LOFAR::ACC::APS::globalParameterSet()->adoptFile(cl.locate("RemoteStation.conf"));
+		//LOFAR::ACC::APS::globalParameterSet()->adoptFile(cl.locate("RemoteStation.conf"));
 		LOFAR::ACC::APS::globalParameterSet()->adoptFile(cl.locate("TBBDriver.conf"));
 	}
 	catch (LOFAR::Exception e) {
@@ -801,7 +809,7 @@ int main(int argc, char** argv)
   
 	LOFAR::TBB::TBBDriver tbb("TBBDriver");
   
-	tbb.start(); // make initial transition
+	tbb.start(); // make initialsition
   
   try {
 		LOFAR::GCF::TM::GCFTask::run();
diff --git a/MAC/APL/PIC/TBBDriver/src/TBBDriver.conf.in b/MAC/APL/PIC/TBBDriver/src/TBBDriver.conf.in
index f1506969c4d2a093bdc4c7c2527a6792d8a2b3e2..4d7bd99dbb4e2299829a07e6f9f598449ec2bea8 100644
--- a/MAC/APL/PIC/TBBDriver/src/TBBDriver.conf.in
+++ b/MAC/APL/PIC/TBBDriver/src/TBBDriver.conf.in
@@ -2,6 +2,18 @@
 # Configuration of the TBBDriver
 #
 
+#
+# Ethernet interface on which to contact the TBB boards.
+# This interface would normally be connected to the switch.
+#
+TBBDriver.IF_NAME=eth1
+
+#
+# Communication settings for TBB boards
+#
+TBBDriver.TP_RETRIES=5
+TBBDriver.TP_TIMEOUT=0.2
+
 #
 # Specify the MAC addresses of all TBB boards
 #
@@ -18,16 +30,108 @@ TBBDriver.MAC_ADDR_8=10:FA:00:00:08:02
 TBBDriver.MAC_ADDR_9=10:FA:00:00:09:02
 TBBDriver.MAC_ADDR_10=10:FA:00:00:0A:02
 TBBDriver.MAC_ADDR_11=10:FA:00:00:0B:02
+#
+# End of TBB-board MAC address configuration
+
 
 #
-# Ethernet interface on which to contact the TBB boards.
-# This interface would normally be connected to the switch.
+# Destination MAC addresses configuration
+# for output TBB boards
+# Must match with MAC addresses of CEP input nodes
+#
+# Uncomment only the lines for the specific station
+# on which the configuration file is used.
 #
-TBBDriver.IF_NAME=eth1
 
+# FTS-1
+#TBBDriver.DST_MAC_ADDR_0=00:E0:81:31:DE:8A
+#TBBDriver.DST_MAC_ADDR_1=00:E0:81:31:DF:D4
+
+# CS01:
+#TBBDriver.DST_MAC_ADDR_0=00:E0:81:34:8C:D1
+#TBBDriver.DST_MAC_ADDR_1=00:E0:81:34:8C:D1
+#TBBDriver.DST_MAC_ADDR_2=00:E0:81:34:9B:87
+#TBBDriver.DST_MAC_ADDR_3=00:E0:81:31:B3:27
+
+# CS08:
+#TBBDriver.DST_MAC_ADDR_0=00:E0:81:31:DE:8B
+#TBBDriver.DST_MAC_ADDR_1=00:E0:81:31:DE:8B
+#TBBDriver.DST_MAC_ADDR_2=00:E0:81:29:20:37
+#TBBDriver.DST_MAC_ADDR_3=00:E0:81:31:DE:9B
+
+# CS16:
+#TBBDriver.DST_MAC_ADDR_0=00:E0:81:31:DF:D5
+#TBBDriver.DST_MAC_ADDR_1=00:E0:81:31:DF:D5
+#TBBDriver.DST_MAC_ADDR_2=00:E0:81:34:92:11
+#TBBDriver.DST_MAC_ADDR_3=00:E0:81:31:B2:15
+
+# CS10:
+TBBDriver.DST_MAC_ADDR_0=00:0A:5E:56:1B:A8
+#TBBDriver.DST_MAC_ADDR_0=00:E0:81:34:93:3B
+TBBDriver.DST_MAC_ADDR_1=00:E0:81:34:93:3B
+TBBDriver.DST_MAC_ADDR_2=00:E0:81:31:B0:E1
+TBBDriver.DST_MAC_ADDR_3=00:E0:81:31:B2:F5
 #
+# End of Destination MAC address configuration
+
+
+# Source IP address in UDP header for each RSP board
 #
+TBBDriver.SRC_IP_ADDR_0=10.10.0.1
+TBBDriver.SRC_IP_ADDR_1=10.10.0.2
+TBBDriver.SRC_IP_ADDR_2=10.10.0.3
+TBBDriver.SRC_IP_ADDR_3=10.10.0.4
+TBBDriver.SRC_IP_ADDR_4=10.10.0.5
+TBBDriver.SRC_IP_ADDR_5=10.10.0.6
+TBBDriver.SRC_IP_ADDR_6=10.10.0.7
+TBBDriver.SRC_IP_ADDR_7=10.10.0.8
+TBBDriver.SRC_IP_ADDR_8=10.10.0.9
+TBBDriver.SRC_IP_ADDR_9=10.10.0.10
+TBBDriver.SRC_IP_ADDR_10=10.10.0.11
+TBBDriver.SRC_IP_ADDR_11=10.10.0.12
 #
+# End of Source IP address configuration
+
+
+# Destination IP adress in UDP header for each TBB board
 #
-TBBDriver.TP_RETRIES=5
-TBBDriver.TP_TIMEOUT=0.02
+TBBDriver.DST_IP_ADDR_0=0.0.0.0
+#TBBDriver.DST_IP_ADDR_0=10.170.0.1
+TBBDriver.DST_IP_ADDR_1=10.170.0.2
+TBBDriver.DST_IP_ADDR_2=10.170.0.3
+TBBDriver.DST_IP_ADDR_3=10.170.0.4
+TBBDriver.DST_IP_ADDR_4=10.170.0.5
+TBBDriver.DST_IP_ADDR_5=10.170.0.6
+TBBDriver.DST_IP_ADDR_6=10.170.0.7
+TBBDriver.DST_IP_ADDR_7=10.170.0.8
+TBBDriver.DST_IP_ADDR_8=10.170.0.9
+TBBDriver.DST_IP_ADDR_9=10.170.0.10
+TBBDriver.DST_IP_ADDR_10=10.170.0.11
+TBBDriver.DST_IP_ADDR_11=10.170.0.12
+#
+# End of Destination IP address configuration
+
+
+#
+# RCU to TBB_channel conversion for the first tbbboard
+# all other channels can be calculated with this info
+# TBB_CH = RCU_CH
+#
+TBBDriver.TBB_CH_0=8
+TBBDriver.TBB_CH_1=9
+TBBDriver.TBB_CH_2=0
+TBBDriver.TBB_CH_3=1
+TBBDriver.TBB_CH_4=10
+TBBDriver.TBB_CH_5=11
+TBBDriver.TBB_CH_6=2
+TBBDriver.TBB_CH_7=3
+TBBDriver.TBB_CH_8=12
+TBBDriver.TBB_CH_9=13
+TBBDriver.TBB_CH_10=4
+TBBDriver.TBB_CH_11=5
+TBBDriver.TBB_CH_12=14
+TBBDriver.TBB_CH_13=15
+TBBDriver.TBB_CH_14=6
+TBBDriver.TBB_CH_15=7
+#
+# End of the conversion table
\ No newline at end of file
diff --git a/MAC/APL/PIC/TBBDriver/src/TBBDriver.h b/MAC/APL/PIC/TBBDriver/src/TBBDriver.h
index f56aa36d5cbb5d72ba257e86ba689bddbde4af5c..b06fa55cbcbe2312fd81556833c0176ed5af0ed7 100644
--- a/MAC/APL/PIC/TBBDriver/src/TBBDriver.h
+++ b/MAC/APL/PIC/TBBDriver/src/TBBDriver.h
@@ -34,12 +34,13 @@
 
 #include "BoardCmdHandler.h"
 #include "MsgHandler.h"
+#include "DriverSettings.h"
 
 //# Never #include <config.h> or #include <lofar_config.h> in a header file!
 
 namespace LOFAR{
   namespace TBB{
-	 
+
     // Description of class.
     class TBBDriver : public GCFTask
     {
@@ -90,8 +91,11 @@ namespace LOFAR{
 			
 			void sendMessage(GCFEvent& event);
 			bool CheckAlive(GCFEvent& event, GCFPortInterface& port);
+			bool CheckSize(GCFEvent& event, GCFPortInterface& port);
 			bool SetTbbCommand(unsigned short signal);
 			
+			TbbSettings *TS;
+			
 			// define some variables
 			TPAliveEvent			*itsAlive;
 			TPSizeEvent				*itsSize;
@@ -99,18 +103,19 @@ namespace LOFAR{
 			MsgHandler				*msghandler;
 			Command 					*cmd;
 			bool							itsAliveCheck;
+			bool							itsSizeCheck;
 			uint32						itsActiveBoards;
 			bool							itsActiveBoardsChange;
+			int32 						*itsResetCount;
 			
 			struct TbbEvent{
 				unsigned short		signal;
 				GCFPortInterface	*port;
 			};
 			
-			deque<TbbEvent> *itsTbbQueue;
+			std::deque<TbbEvent> *itsTbbQueue;
 			
 			GCFTCPPort      itsAcceptor;     // listen for clients on this port
-			GCFTCPPort      itsMsgPort;     // send messages to this port
 			GCFETHRawPort   *itsBoard;        // array of ports, one for each TBB board
 			
 			std::list<GCFPortInterface*> itsClientList;  // list of clients
diff --git a/MAC/APL/PIC/TBBDriver/src/TP_Protocol.prot b/MAC/APL/PIC/TBBDriver/src/TP_Protocol.prot
index 04467e6807ca05ae6e1ff3d070c314c9492ad373..12667ecd45dc0800aba0ec66cbd5cbd1fec6dcaf 100644
--- a/MAC/APL/PIC/TBBDriver/src/TP_Protocol.prot
+++ b/MAC/APL/PIC/TBBDriver/src/TP_Protocol.prot
@@ -332,7 +332,7 @@ event = {
 	};
   param = {
 		name = "ip";
-		type = "uint32[5]";
+		type = "uint32[6]";
 	};
 	param = {
     name = "udp";
@@ -528,19 +528,19 @@ event = {
     type = "uint32";
   };
   param = {
-    name = "V12";
+    name = "Tmp3";
     type = "uint32";
   };
   param = {
-    name = "V25";
+    name = "Tmp2";
     type = "uint32";
   };
   param = {
-    name = "V33";
+    name = "Tmp1";
     type = "uint32";
   };
   param = {
-    name = "Tpcb";
+    name = "Tmp0";
     type = "uint32";
   };
   param = {
@@ -548,19 +548,19 @@ event = {
     type = "uint32";
   };
   param = {
-    name = "Tmp0";
+    name = "Tpcb";
     type = "uint32";
   };
   param = {
-    name = "Tmp1";
+    name = "V33";
     type = "uint32";
   };
   param = {
-    name = "Tmp2";
+    name = "V25";
     type = "uint32";
   };
   param = {
-    name = "Tmp3";
+    name = "V12";
     type = "uint32";
   };
 };
diff --git a/MAC/APL/PIC/TBBDriver/src/TrigclrCmd.cc b/MAC/APL/PIC/TBBDriver/src/TrigclrCmd.cc
index a2ffb622989e19d65e1199528ac146c828f150bb..487ed3ee6f71d330d5346def25be734ba8f14e17 100644
--- a/MAC/APL/PIC/TBBDriver/src/TrigclrCmd.cc
+++ b/MAC/APL/PIC/TBBDriver/src/TrigclrCmd.cc
@@ -24,23 +24,24 @@
 #include <Common/LofarLogger.h>
 
 #include "TrigclrCmd.h"
-#include "DriverSettings.h"
 
-namespace LOFAR {
-	using namespace TBB_Protocol;
-	using namespace TP_Protocol;
-	namespace TBB {
+
+using namespace LOFAR;
+using namespace TBB_Protocol;
+using namespace TP_Protocol;
+using	namespace TBB;
 
 //--Constructors for a TrigclrCmd object.----------------------------------------
-TrigclrCmd::TrigclrCmd():
-		itsBoardMask(0),itsBoardsMask(0),itsChannel(0)
+TrigclrCmd::TrigclrCmd()
 {
+	TS					= TbbSettings::instance();
 	itsTPE 			= new TPTrigclrEvent();
 	itsTPackE 	= 0;
 	itsTBBE 		= 0;
 	itsTBBackE 	= new TBBTrigclrackEvent();
 	
-	itsTBBackE->status = 0;
+	itsTBBackE->status_mask = 0;
+	setWaitAck(true);
 }
 	  
 //--Destructor for TrigclrCmd.---------------------------------------------------
@@ -62,82 +63,50 @@ bool TrigclrCmd::isValid(GCFEvent& event)
 // ----------------------------------------------------------------------------
 void TrigclrCmd::saveTbbEvent(GCFEvent& event)
 {
-	itsTBBE 			= new TBBTrigclrEvent(event);
+	itsTBBE	= new TBBTrigclrEvent(event);
 		
-	itsBoardMask = (1 << DriverSettings::instance()->getChBoardNr((int32)itsTBBE->channel));
+	int32 boardnr;
+	int32 channelnr;
+	TS->convertRcu2Ch(itsTBBE->channel,&boardnr,&channelnr);
+		
+	setBoardNr(boardnr);
 		
-	// mask for the installed boards
-	itsBoardsMask = DriverSettings::instance()->activeBoardsMask();
-	
-	// Send only commands to boards installed
-	itsBoardMask = itsBoardMask & itsBoardsMask;
-	
 	// initialize TP send frame
 	itsTPE->opcode	= TPTRIGCLR;
 	itsTPE->status	=	0;
-	itsTPE->channel = itsTBBE->channel;
+	itsTPE->channel = channelnr;
 	
 	delete itsTBBE;	
 }
 
 // ----------------------------------------------------------------------------
-bool TrigclrCmd::sendTpEvent(int32 boardnr, int32)
+void TrigclrCmd::sendTpEvent()
 {
-	bool sending = false;
-	DriverSettings*		ds = DriverSettings::instance();
-	
-	if (ds->boardPort(boardnr).isConnected()) {
-		ds->boardPort(boardnr).send(*itsTPE);
-		ds->boardPort(boardnr).setTimer(ds->timeout());
-		sending = true;
-	}
-	else
-		itsTBBackE->status |= CMD_ERROR;
-		
-	return(sending);
+		TS->boardPort(getBoardNr()).send(*itsTPE);
+		TS->boardPort(getBoardNr()).setTimer(TS->timeout());
 }
 
 // ----------------------------------------------------------------------------
-void TrigclrCmd::saveTpAckEvent(GCFEvent& event, int32 boardnr)
+void TrigclrCmd::saveTpAckEvent(GCFEvent& event)
 {
 	// in case of a time-out, set error mask
 	if (event.signal == F_TIMER) {
-		itsTBBackE->status |= COMM_ERROR;
+		itsTBBackE->status_mask |= TBB_COMM_ERROR;
 	}
 	else {
 		itsTPackE = new TPTrigclrackEvent(event);
 		
-		LOG_DEBUG_STR(formatString("Received TrigclrAck from boardnr[%d]", boardnr));
+		LOG_DEBUG_STR(formatString("Received TrigclrAck from boardnr[%d]", getBoardNr()));
 		delete itsTPackE;
 	}
+	setDone(true);
 }
 
 // ----------------------------------------------------------------------------
 void TrigclrCmd::sendTbbAckEvent(GCFPortInterface* clientport)
 {
-	if (itsTBBackE->status == 0)
-			itsTBBackE->status = SUCCESS;
+	if (itsTBBackE->status_mask == 0)
+			itsTBBackE->status_mask = TBB_SUCCESS;
 		
 	clientport->send(*itsTBBackE);
 }
-
-// ----------------------------------------------------------------------------
-uint32 TrigclrCmd::getBoardMask()
-{
-	return(itsBoardMask);
-}
-
-// ----------------------------------------------------------------------------
-bool TrigclrCmd::waitAck()
-{
-	return(true);
-}
-
-// ----------------------------------------------------------------------------
-CmdTypes TrigclrCmd::getCmdType()
-{
-	return(ChannelCmd);
-}
-
-	} // end TBB namespace
-} // end LOFAR namespace
diff --git a/MAC/APL/PIC/TBBDriver/src/TrigclrCmd.h b/MAC/APL/PIC/TBBDriver/src/TrigclrCmd.h
index bbc9fa6b5483dc1e680576bd26303e16d6daa94b..27f6a3c4f9629fdd3848f420a29bd1cbf9e09b2b 100644
--- a/MAC/APL/PIC/TBBDriver/src/TrigclrCmd.h
+++ b/MAC/APL/PIC/TBBDriver/src/TrigclrCmd.h
@@ -32,6 +32,7 @@
 #include "TP_Protocol.ph"
 
 #include "Command.h"
+#include "DriverSettings.h"
 
 namespace LOFAR {
 	using namespace TBB_Protocol;
@@ -50,22 +51,14 @@ namespace LOFAR {
 				
 				virtual void saveTbbEvent(GCFEvent& event);
 									
-				virtual bool sendTpEvent(int32 boardnr, int32 channelnr);
+				virtual void sendTpEvent();
 
-				virtual void saveTpAckEvent(GCFEvent& event, int32 boardnr);
+				virtual void saveTpAckEvent(GCFEvent& event);
 
 				virtual void sendTbbAckEvent(GCFPortInterface* clientport);
 				
-				virtual uint32 getBoardMask();
-				
-				virtual bool waitAck();
-				
-				virtual CmdTypes getCmdType();
-      
 			private:
-				uint32	itsBoardMask;  // mask indicates the boards to communicate with
-				uint32	itsBoardsMask;	// Installed boards mask
-				uint32	itsChannel;
+				TbbSettings *TS;
 				
 				TPTrigclrEvent			*itsTPE;
 				TPTrigclrackEvent		*itsTPackE;
diff --git a/MAC/APL/PIC/TBBDriver/src/UdpCmd.cc b/MAC/APL/PIC/TBBDriver/src/UdpCmd.cc
index 80a7f5d463d8a70dbd18c7c6cd2a185012728a33..de817013cd928b69557167a7c1169fa452b43d8a 100644
--- a/MAC/APL/PIC/TBBDriver/src/UdpCmd.cc
+++ b/MAC/APL/PIC/TBBDriver/src/UdpCmd.cc
@@ -22,27 +22,152 @@
 
 #include <lofar_config.h>
 #include <Common/LofarLogger.h>
+#include <netinet/in.h>
+#include <net/ethernet.h>
 
 #include "UdpCmd.h"
-#include "DriverSettings.h"
 
-namespace LOFAR {
-	using namespace TBB_Protocol;
-	using namespace TP_Protocol;
-	namespace TBB {
+using namespace LOFAR;
+using namespace TBB_Protocol;
+using namespace TP_Protocol;
+using namespace TBB;
+
+static const uint16 BASEUDPPORT = 0x10FA; // (=4346) start numbering src and dst UDP ports at this number (4346)
+static const uint16 TRANSIENT_FRAME_SIZE = 2140; // bytes, header(88) + payload(2048) + CRC(4)
+static const uint16 SUBBANDS_FRAME_SIZE = 2012;  // bytes, header(88) + payload(1920) + CRC(4)
+
+void UdpCmd::string2mac(const char* macstring, uint32 mac[2])
+{
+  unsigned int hx[ETH_ALEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+  sscanf(macstring, "%x:%x:%x:%x:%x:%x", &hx[5], &hx[4], &hx[3], &hx[2], &hx[1], &hx[0]);
+   
+  mac[0]	= ((hx[0] & 0xFF))
+  				+ ((hx[1] & 0xFF) << 8)
+  				+ ((hx[2] & 0xFF) << 16)
+  				+ ((hx[3] & 0xFF) << 24);  
+  
+  mac[1] 	= ((hx[4] & 0xFF)) 
+  				+ ((hx[5] & 0xFF) << 8);
+}
+
+uint32 UdpCmd::string2ip(const char* ipstring)
+{
+  uint32 result;
+  unsigned int hx[sizeof(uint32)] = { 0x00, 0x00, 0x00, 0x00 };
+
+  sscanf(ipstring, "%d.%d.%d.%d", &hx[3], &hx[2], &hx[1], &hx[0]);
+
+  result	= ((hx[0] & 0xFF))
+    			+ ((hx[1] & 0xFF) << 8)
+    			+ ((hx[2] & 0xFF) << 16) 
+    			+ ((hx[3] & 0xFF) << 24);
+
+  return result;
+}
+
+void UdpCmd::setup_udpip_header(uint32 boardnr, uint32 ip_hdr[6], uint32 udp_hdr[2])
+{
+  uint32 iphdr[6];
+  uint32 udphdr[2];
+  
+  uint32 ip_hdr_size = sizeof(iphdr); // bytes
+  uint32 udp_hdr_size = sizeof(udphdr); // bytes
+   
+  uint32 data_size = 0;
+  
+  if (itsMode == TBB_MODE_TRANSIENT) data_size = TRANSIENT_FRAME_SIZE;
+  if (itsMode == TBB_MODE_SUBBANDS) data_size = SUBBANDS_FRAME_SIZE;	
+    
+  // IP header values
+  uint32 version 					= 4; // IPv4
+  uint32 ihl 							= 6; // 6 x uint32
+  uint32 tos							= 0;
+  uint32 total_length			= ip_hdr_size + udp_hdr_size + data_size;
+  uint32 identification		= 0;	
+  uint32 flags_offset			= 0x2 << 13;
+  uint32 ttl							= 128;
+  uint32 protocol					= 0x11;
+  uint32 header_checksum	= 0; // set to zero for checksum calculation
+  uint32 src_ip_address		= string2ip(TS->getSrcIp(boardnr).c_str());
+  uint32 dst_ip_address 	= string2ip(TS->getDstIp(boardnr).c_str());   
+  uint32 options					= 0; // no options
+  // UDP header values  	
+  uint32 src_udp_port			= BASEUDPPORT + boardnr;
+  uint32 dst_udp_port			= BASEUDPPORT + boardnr;
+  uint32 length						= udp_hdr_size + data_size;
+	uint32 checksum					= 0; // disable checksum
+
+	// put all ip settings on the correct place
+	iphdr[0] = ((version & 0xF) << 28)
+						+ ((ihl & 0xF) << 24) 
+						+ ((tos & 0xFF) << 16) 
+						+ (total_length & 0xFFFF);
+	iphdr[1] = ((identification & 0xFFFF) << 16) 
+						+ (flags_offset & 0xFFFF);
+	iphdr[2] = ((ttl & 0xFF) << 24) 
+						+ ((protocol & 0xFF) << 16) 
+						+ (header_checksum & 0xFFFF);
+	iphdr[3] = src_ip_address;
+	iphdr[4] = dst_ip_address;
+	iphdr[5] = options;
+	
+	// compute header checksum
+  header_checksum = compute_ip_checksum(&iphdr, 24); //sizeof(ip_hdr));
+	iphdr[2] += (uint32)(header_checksum & 0xFFFF); // add checksum
+	//LOG_DEBUG_STR(formatString("Checksum = 0x%08X", header_checksum));
+		
+	// put all udp settings on the correct place
+	udphdr[0] 	= ((src_udp_port & 0xFFFF) << 16) 
+							+  (dst_udp_port & 0XFFFF);
+	udphdr[1] 	= ((length & 0xFFFF) << 16) 
+							+  (checksum & 0xFFFF);
+	
+	for (int i = 0; i < 6; i++) { 
+		ip_hdr[i] = iphdr[i];
+	}
+	for (int i = 0; i < 2; i++) { 
+		udp_hdr[i] = udphdr[i];
+	}
+}
+
+uint16 UdpCmd::compute_ip_checksum(void* addr, int count)
+{
+  // Compute Internet Checksum for "count" bytes
+  // beginning at location "addr".
+  
+  register long sum = 0;
+
+  uint16* addr16 = (uint16*)addr;
+  while( count > 1 )  {
+    //  This is the inner loop 
+    sum += *addr16++;
+    count -= 2;
+  }
+
+  //  Add left-over byte, if any 
+  if( count > 0 )
+    sum += * (uint8 *) addr16;
+
+  //  Fold 32-bit sum to 16 bits 
+  while (sum>>16)
+    sum = (sum & 0xffff) + (sum >> 16);
+
+  return ~sum;
+}
 
 //--Constructors for a UdpCmd object.----------------------------------------
 UdpCmd::UdpCmd():
-		itsBoardMask(0),itsBoardsMask(0)
+		itsMode(0)
 {
+	TS					= TbbSettings::instance();
 	itsTPE 			= new TPUdpEvent();
 	itsTPackE 	= 0;
 	itsTBBE 		= 0;
-	itsTBBackE 	= new TBBUdpackEvent();
+	itsTBBackE 	= new TBBModeackEvent();
 	
-	for(int boardnr = 0;boardnr < MAX_N_TBBBOARDS;boardnr++) { 
-		itsTBBackE->status[boardnr]	= 0;
-	}		
+	itsTBBackE->status_mask	= 0;
+	setWaitAck(true);	
 }
 	  
 //--Destructor for UdpCmd.---------------------------------------------------
@@ -55,7 +180,7 @@ UdpCmd::~UdpCmd()
 // ----------------------------------------------------------------------------
 bool UdpCmd::isValid(GCFEvent& event)
 {
-	if ((event.signal == TBB_UDP)||(event.signal == TP_UDPACK)) {
+	if ((event.signal == TBB_MODE)||(event.signal == TP_UDPACK)) {
 		return(true);
 	}
 	return(false);
@@ -64,103 +189,74 @@ bool UdpCmd::isValid(GCFEvent& event)
 // ----------------------------------------------------------------------------
 void UdpCmd::saveTbbEvent(GCFEvent& event)
 {
-	itsTBBE 			= new TBBUdpEvent(event);
+	itsTBBE	= new TBBModeEvent(event);
 	
-	// mask for the installed boards
-	itsBoardsMask = DriverSettings::instance()->activeBoardsMask();
-	itsBoardMask = itsTBBE->boardmask; 
-		
-	for (int boardnr = 0; boardnr < DriverSettings::instance()->maxBoards(); boardnr++) {
+	setBoardNr(itsTBBE->board);
 		
-		if (!(itsBoardsMask & (1 << boardnr))) 
-			itsTBBackE->status[boardnr] |= NO_BOARD;
-				
-		if (!(itsBoardsMask & (1 << boardnr)) &&  (itsBoardMask & (1 << boardnr)))
-			itsTBBackE->status[boardnr] |= (SELECT_ERROR | BOARD_SEL_ERROR);
-	}
+	if (TS->isBoardActive(getBoardNr()) == false)
+		itsTBBackE->status_mask |= TBB_NO_BOARD;
 
-	// Send only commands to boards installed
-	itsBoardMask = itsBoardMask & itsBoardsMask;
+	itsMode = itsTBBE->rec_mode;
 	
 	// initialize TP send frame
 	itsTPE->opcode	= TPUDP;
 	itsTPE->status	=	0;
-	itsTPE->udp[0]	= itsTBBE->udp[0];
-	itsTPE->udp[1]	= itsTBBE->udp[1];
-	itsTPE->ip[0]		= itsTBBE->ip[0];
-	itsTPE->ip[1]		= itsTBBE->ip[1];
-	itsTPE->ip[2]	 	= itsTBBE->ip[2];
-	itsTPE->ip[3]	 	= itsTBBE->ip[3];
-	itsTPE->ip[4]	 	= itsTBBE->ip[4];
-	itsTPE->mac[0]	= itsTBBE->mac[0];
-	itsTPE->mac[1]	= itsTBBE->mac[1];
-	
+		
 	delete itsTBBE;	
 }
 
 // ----------------------------------------------------------------------------
-bool UdpCmd::sendTpEvent(int32 boardnr, int32)
+void UdpCmd::sendTpEvent()
 {
-	bool sending = false;
-	DriverSettings*		ds = DriverSettings::instance();
-	
-	if (ds->boardPort(boardnr).isConnected() && (itsTBBackE->status[boardnr] == 0)) {
-		ds->boardPort(boardnr).send(*itsTPE);
-		ds->boardPort(boardnr).setTimer(ds->timeout());
-		sending = true;
+	// fill in destination mac address
+	string2mac(TS->getDstMac(getBoardNr()).c_str(),itsTPE->mac);
+	for ( int i = 0; i < 2; i++) {
+		LOG_DEBUG_STR(formatString("MAC[%d]= 0x%08X", i, itsTPE->mac[i]));
+	}		
+	// fill in udp-ip header
+	setup_udpip_header(getBoardNr(), itsTPE->ip, itsTPE->udp);
+	for ( int i = 0; i < 6; i++) {
+		LOG_DEBUG_STR(formatString("IP[%d]= 0x%08X", i, itsTPE->ip[i]));
+	}
+	for ( int i = 0; i < 2; i++) {
+		LOG_DEBUG_STR(formatString("UDP[%d]= 0x%08X", i, itsTPE->udp[i]));
 	}
-	else
-		itsTBBackE->status[boardnr] |= CMD_ERROR;
 	
-	return(sending);
+	TS->boardPort(getBoardNr()).send(*itsTPE);
+	TS->boardPort(getBoardNr()).setTimer(TS->timeout());
 }
 
 // ----------------------------------------------------------------------------
-void UdpCmd::saveTpAckEvent(GCFEvent& event, int32 boardnr)
+void UdpCmd::saveTpAckEvent(GCFEvent& event)
 {
 	// in case of a time-out, set error mask
 	if (event.signal == F_TIMER) {
-		itsTBBackE->status[boardnr] |= COMM_ERROR;
+		itsTBBackE->status_mask |= TBB_COMM_ERROR;
 	}
 	else {
 		itsTPackE = new TPUdpackEvent(event);
 		
 		if ((itsTPackE->status >= 0xF0) && (itsTPackE->status <= 0xF6)) 
-			itsTBBackE->status[boardnr] |= (1 << (16 + (itsTPackE->status & 0x0F)));
+			itsTBBackE->status_mask |= (1 << (16 + (itsTPackE->status & 0x0F)));
 		
-		LOG_DEBUG_STR(formatString("Received UdpAck from boardnr[%d]", boardnr));
+		LOG_DEBUG_STR(formatString("Received UdpAck from boardnr[%d], status[0x%08X]", 
+									getBoardNr(), itsTPackE->status));
 		delete itsTPackE;
 	}
+	setDone(true);
 }
 
 // ----------------------------------------------------------------------------
 void UdpCmd::sendTbbAckEvent(GCFPortInterface* clientport)
 {
-	for (int32 boardnr = 0; boardnr < DriverSettings::instance()->maxBoards(); boardnr++) { 
-		if (itsTBBackE->status[boardnr] == 0)
-			itsTBBackE->status[boardnr] = SUCCESS;
-	}
+	if (itsTBBackE->status_mask == 0)
+		itsTBBackE->status_mask = TBB_SUCCESS;
 
 	clientport->send(*itsTBBackE);
 }
 
-// ----------------------------------------------------------------------------
-CmdTypes UdpCmd::getCmdType()
-{
-	return(BoardCmd);
-}
-
-// ----------------------------------------------------------------------------
-uint32 UdpCmd::getBoardMask()
-{
-	return(itsBoardMask);
-}
-
 // ----------------------------------------------------------------------------
 bool UdpCmd::waitAck()
 {
 	return(true);
 }
-
-	} // end TBB namespace
-} // end LOFAR namespace
diff --git a/MAC/APL/PIC/TBBDriver/src/UdpCmd.h b/MAC/APL/PIC/TBBDriver/src/UdpCmd.h
index 6ac96c92c2d6b4767bd42180253f2766f10540bf..2c24c2190384744bc84264f8e072674b6a04d43d 100644
--- a/MAC/APL/PIC/TBBDriver/src/UdpCmd.h
+++ b/MAC/APL/PIC/TBBDriver/src/UdpCmd.h
@@ -27,11 +27,13 @@
 
 #include <Common/LofarTypes.h>
 #include <GCF/TM/GCF_Control.h>
+#include <net/ethernet.h>
 
 #include <APL/TBB_Protocol/TBB_Protocol.ph>
 #include "TP_Protocol.ph"
 
 #include "Command.h"
+#include "DriverSettings.h"
 
 namespace LOFAR {
 	using namespace TBB_Protocol;
@@ -50,26 +52,40 @@ namespace LOFAR {
 				
 				virtual void saveTbbEvent(GCFEvent& event);
 									
-				virtual bool sendTpEvent(int32 boardnr, int32 channelnr);
+				virtual void sendTpEvent();
 
-				virtual void saveTpAckEvent(GCFEvent& event, int32 boardnr);
+				virtual void saveTpAckEvent(GCFEvent& event);
 
 				virtual void sendTbbAckEvent(GCFPortInterface* clientport);
 				
-				virtual uint32 getBoardMask();
-				
 				virtual bool waitAck();
-				
-				virtual CmdTypes getCmdType();
       
+      private:
+      //private methods
+
+      // Convert a string containing a Ethernet MAC address
+      // to an array of 6 bytes.
+      void string2mac(const char* macstring, uint32 mac[2]);
+
+      // Convert a string containing an IP address
+      // to an array of 6 bytes.
+      uint32 string2ip(const char* ipstring);
+
+      // Setup an appropriate UDP/IP header
+      void setup_udpip_header(uint32 boardnr, uint32 ip_hdr[6], uint32 udp_hdr[2]);
+
+      // Compute the 16-bit 1-complements checksum for the IP header.
+      uint16 compute_ip_checksum(void* addr, int count);
+			
 			private:
-				uint32	itsBoardMask;  // mask indicates the boards to communicate with
-				uint32	itsBoardsMask;	// Installed boards mask
+				TbbSettings *TS;
+				
+				uint32	itsMode; // Transient or subbands
 				
 				TPUdpEvent			*itsTPE;
 				TPUdpackEvent		*itsTPackE;
-				TBBUdpEvent			*itsTBBE;
-				TBBUdpackEvent	*itsTBBackE;
+				TBBModeEvent		*itsTBBE;
+				TBBModeackEvent	*itsTBBackE;
 		};
 	} // end TBB namespace
 } // end LOFAR namespace
diff --git a/MAC/APL/PIC/TBBDriver/src/VersionCmd.cc b/MAC/APL/PIC/TBBDriver/src/VersionCmd.cc
index 3d842610c7e6c046b3d7bbcc5b0bbd75be99966e..4a6a06461b1856e3f029d305f03d78a50cb6527c 100644
--- a/MAC/APL/PIC/TBBDriver/src/VersionCmd.cc
+++ b/MAC/APL/PIC/TBBDriver/src/VersionCmd.cc
@@ -24,25 +24,26 @@
 #include <Common/LofarLogger.h>
 
 #include "VersionCmd.h"
-#include "DriverSettings.h"
 
-namespace LOFAR {
-	using namespace TBB_Protocol;
-	using namespace TP_Protocol;	
-	namespace TBB {
+
+using namespace LOFAR;
+using namespace TBB_Protocol;
+using namespace TP_Protocol;	
+using namespace TBB;
 
 //--Constructors for a VersionCmd object.--------------------------------------
-VersionCmd::VersionCmd():
-		itsBoardMask(0),itsBoardsMask(0)
+VersionCmd::VersionCmd()
 {
+	TS					= TbbSettings::instance();
 	itsTPE 			= new TPVersionEvent();
 	itsTPackE 	= 0;
 	itsTBBE 		= 0;
 	itsTBBackE 	= new TBBVersionackEvent();
 	
 	for(int boardnr = 0;boardnr < MAX_N_TBBBOARDS;boardnr++) { 
-		itsTBBackE->status[boardnr]		= 0;
+		itsTBBackE->status_mask[boardnr]		= 0;
 	}
+	setWaitAck(true);
 }
   
 //--Destructor for GetVersions.------------------------------------------------
@@ -64,22 +65,18 @@ bool VersionCmd::isValid(GCFEvent& event)
 // ----------------------------------------------------------------------------
 void VersionCmd::saveTbbEvent(GCFEvent& event)
 {
-	itsTBBE 			= new TBBVersionEvent(event);
+	itsTBBE	= new TBBVersionEvent(event);
 	
-	// mask for the installed boards
-	itsBoardsMask = DriverSettings::instance()->activeBoardsMask();	
-	itsBoardMask = itsTBBE->boardmask;
+	setBoardMask(itsTBBE->boardmask);
 	
-	for (int boardnr = 0; boardnr < DriverSettings::instance()->maxBoards(); boardnr++) {
-		if (!(itsBoardsMask & (1 << boardnr))) 
-			itsTBBackE->status[boardnr] |= NO_BOARD;
-		
-		if (!(itsBoardsMask & (1 << boardnr)) &&  (itsBoardMask & (1 << boardnr)))
-			itsTBBackE->status[boardnr] |= (SELECT_ERROR | BOARD_SEL_ERROR);
+	for (int boardnr = 0; boardnr < TS->maxBoards(); boardnr++) {
+		if (!TS->isBoardActive(boardnr)) 
+			itsTBBackE->status_mask[boardnr] |= TBB_NO_BOARD;
 	}
 	
-	// Send only commands to boards installed
-	itsBoardMask = itsBoardMask & itsBoardsMask;
+	itsTBBackE->driverversion = TS->driverVersion();
+	// select firt board
+	nextBoardNr();
 	
 	// fill TP command, to send
 	itsTPE->opcode 			  = TPVERSION;
@@ -89,81 +86,51 @@ void VersionCmd::saveTbbEvent(GCFEvent& event)
 }
 
 // ----------------------------------------------------------------------------
-bool VersionCmd::sendTpEvent(int32 boardnr, int32)
+void VersionCmd::sendTpEvent()
 {
-	bool sending = false;
-	DriverSettings*		ds = DriverSettings::instance();
-	
-	if (ds->boardPort(boardnr).isConnected() && (itsTBBackE->status[boardnr] == 0)) {
-		ds->boardPort(boardnr).send(*itsTPE);
-		ds->boardPort(boardnr).setTimer(ds->timeout());
-		sending = true;
-	}
-	else
-		itsTBBackE->status[boardnr] |= CMD_ERROR;
-	
-	return(sending);
+		TS->boardPort(getBoardNr()).send(*itsTPE);
+		TS->boardPort(getBoardNr()).setTimer(TS->timeout());
 }
 
 // ----------------------------------------------------------------------------
-void VersionCmd::saveTpAckEvent(GCFEvent& event, int32 boardnr)
+void VersionCmd::saveTpAckEvent(GCFEvent& event)
 {
 	// in case of a time-out, set error mask
 	if (event.signal == F_TIMER) {
-		itsTBBackE->status[boardnr] |= COMM_ERROR;
+		itsTBBackE->status_mask[getBoardNr()] |= TBB_COMM_ERROR;
 	}
 	else {
 		//TPVersionEvent tpe(event);
 		itsTPackE = new TPVersionackEvent(event);
 		
 		if ((itsTPackE->status >= 0xF0) && (itsTPackE->status <= 0xF6)) 
-			itsTBBackE->status[boardnr] |= (1 << (16 + (itsTPackE->status & 0x0F)));	
+			itsTBBackE->status_mask[getBoardNr()] |= (1 << (16 + (itsTPackE->status & 0x0F)));	
 		
-		itsTBBackE->boardid[boardnr] 			= itsTPackE->boardid;
-		itsTBBackE->swversion[boardnr]  	= itsTPackE->swversion;
-		itsTBBackE->boardversion[boardnr]	= itsTPackE->boardversion;
-		itsTBBackE->tpversion[boardnr]		= itsTPackE->tpversion;
-		itsTBBackE->mp0version[boardnr] 	= itsTPackE->mp0version;
-		itsTBBackE->mp1version[boardnr] 	= itsTPackE->mp1version;
-		itsTBBackE->mp2version[boardnr] 	= itsTPackE->mp2version;
-		itsTBBackE->mp3version[boardnr] 	= itsTPackE->mp3version;
+		itsTBBackE->boardid[getBoardNr()] 			= itsTPackE->boardid;
+		itsTBBackE->swversion[getBoardNr()]  	= itsTPackE->swversion;
+		itsTBBackE->boardversion[getBoardNr()]	= itsTPackE->boardversion;
+		itsTBBackE->tpversion[getBoardNr()]		= itsTPackE->tpversion;
+		itsTBBackE->mp0version[getBoardNr()] 	= itsTPackE->mp0version;
+		itsTBBackE->mp1version[getBoardNr()] 	= itsTPackE->mp1version;
+		itsTBBackE->mp2version[getBoardNr()] 	= itsTPackE->mp2version;
+		itsTBBackE->mp3version[getBoardNr()] 	= itsTPackE->mp3version;
 		
 		LOG_DEBUG_STR(formatString("VersionCmd: board[%d] %08X;%u;%u;%u;%u;%u;%u;%u;%u",
-				boardnr,itsTBBackE->status[boardnr],itsTPackE->boardid,itsTPackE->swversion,itsTPackE->boardversion,
+				getBoardNr(),itsTBBackE->status_mask[getBoardNr()],itsTPackE->boardid,itsTPackE->swversion,itsTPackE->boardversion,
 				itsTPackE->tpversion,itsTPackE->mp0version,itsTPackE->mp1version,itsTPackE->mp2version,itsTPackE->mp3version));
 		
 		delete itsTPackE;
 	}
+	nextBoardNr();
 }
 
 // ----------------------------------------------------------------------------
 void VersionCmd::sendTbbAckEvent(GCFPortInterface* clientport)
 {
-	for (int32 boardnr = 0; boardnr < DriverSettings::instance()->maxBoards(); boardnr++) { 
-		if (itsTBBackE->status[boardnr] == 0)
-			itsTBBackE->status[boardnr] = SUCCESS;
+	for (int32 boardnr = 0; boardnr < TS->maxBoards(); boardnr++) { 
+		if (itsTBBackE->status_mask[boardnr] == 0)
+			itsTBBackE->status_mask[boardnr] = TBB_SUCCESS;
 	}
 
 	clientport->send(*itsTBBackE);
 }
-
-// ----------------------------------------------------------------------------
-CmdTypes VersionCmd::getCmdType()
-{
-	return(BoardCmd);
-}
-
-// ----------------------------------------------------------------------------
-uint32 VersionCmd::getBoardMask()
-{
-	return(itsBoardMask);
-}
-
-// ----------------------------------------------------------------------------
-bool VersionCmd::waitAck()
-{
-	return(true);
-}
-
-	} // end namespace TBB
-} // end namespace LOFAR
diff --git a/MAC/APL/PIC/TBBDriver/src/VersionCmd.h b/MAC/APL/PIC/TBBDriver/src/VersionCmd.h
index f47cc1ab59d36db4c2902d939772cc4d20f1bb80..21d2ea0b543ee1465848e002ed22a3db450f6bca 100644
--- a/MAC/APL/PIC/TBBDriver/src/VersionCmd.h
+++ b/MAC/APL/PIC/TBBDriver/src/VersionCmd.h
@@ -32,6 +32,7 @@
 #include "TP_Protocol.ph"
 
 #include "Command.h"
+#include "DriverSettings.h"
 
 namespace LOFAR {
 	using namespace TBB_Protocol;
@@ -50,21 +51,14 @@ namespace LOFAR {
 				
 				virtual void saveTbbEvent(GCFEvent& event);
 									
-				virtual bool sendTpEvent(int32 boardnr, int32 channelnr);
+				virtual void sendTpEvent();
 
-				virtual void saveTpAckEvent(GCFEvent& event, int32 boardnr);
+				virtual void saveTpAckEvent(GCFEvent& event);
 
 				virtual void sendTbbAckEvent(GCFPortInterface* clientport);
-				
-				virtual uint32 getBoardMask();
-				
-				virtual bool waitAck();
-				
-				virtual CmdTypes getCmdType();
       
 			private:
-				uint32	itsBoardMask;  // mask indicates the boards to communicate with
-				uint32	itsBoardsMask;	// Installed boards mask
+				TbbSettings *TS;
 				
 				TPVersionEvent			*itsTPE;
 				TPVersionackEvent		*itsTPackE;
diff --git a/MAC/APL/PIC/TBBDriver/src/WritefCmd.cc b/MAC/APL/PIC/TBBDriver/src/WritefCmd.cc
index 88a699179afff0e4b3706fbd38a939666609faef..084b2a9500a8133655d9186773108eec98f7c59c 100644
--- a/MAC/APL/PIC/TBBDriver/src/WritefCmd.cc
+++ b/MAC/APL/PIC/TBBDriver/src/WritefCmd.cc
@@ -22,23 +22,43 @@
 
 #include <lofar_config.h>
 #include <Common/LofarLogger.h>
+#include <time.h>
 
 #include "WritefCmd.h"
-#include "DriverSettings.h"
 
-namespace LOFAR {
-	using namespace TBB_Protocol;
-	using namespace TP_Protocol;
-	namespace TBB {
+
+using namespace LOFAR;
+using namespace TBB_Protocol;
+using namespace TP_Protocol;
+using	namespace TBB;
+
+// information about the flash memory
+static const int FL_SIZE 						= 64 * 1024 *1024; // 64 MB in bytes
+static const int FL_N_PAGES 				= 32; // 32 pages in flash
+static const int FL_N_SECTORS				= 512; // 512 sectors in flash
+static const int FL_N_BLOCKS				= 65536; // 65336 blocks in flash
+
+static const int FL_PAGE_SIZE 			= FL_SIZE / FL_N_PAGES; // 2.097.152 bytes  
+static const int FL_SECTOR_SIZE			= FL_SIZE / FL_N_SECTORS; // 131.072 bytes
+static const int FL_BLOCK_SIZE 			= FL_SIZE / FL_N_BLOCKS; // 1.024 bytes
+
+static const int FL_SECTORS_IN_PAGE	= FL_PAGE_SIZE / FL_SECTOR_SIZE; // 16 sectors per page
+static const int FL_BLOCKS_IN_SECTOR= FL_SECTOR_SIZE / FL_BLOCK_SIZE; // 128 blocks per sector
+static const int FL_BLOCKS_IN_PAGE	= FL_PAGE_SIZE / FL_BLOCK_SIZE; // 2048 blocks per page
+
+
 
 //--Constructors for a WritefCmd object.----------------------------------------
 WritefCmd::WritefCmd():
-		itsBoardMask(0),itsBoardsMask(0),itsBoardStatus(0)
+		itsStage(idle),itsImage(0),itsSector(0),itsBlock(0),itsImageSize(0),itsBoardStatus(0)
 {
+	TS					= TbbSettings::instance();
 	itsTPE 			= new TPWritefEvent();
 	itsTPackE 	= 0;
 	itsTBBE 		= 0;
-	itsTBBackE 	= new TBBWritefackEvent();
+	itsTBBackE 	= new TBBWriteImageAckEvent();
+	itsImageData= 0;
+	setWaitAck(true);
 }
 	  
 //--Destructor for WritefCmd.---------------------------------------------------
@@ -46,12 +66,17 @@ WritefCmd::~WritefCmd()
 {
 	delete itsTPE;
 	delete itsTBBackE;
+	if (itsTBBE) delete itsTBBE;
+	if (itsImageData) delete itsImageData;
 }
 
 // ----------------------------------------------------------------------------
 bool WritefCmd::isValid(GCFEvent& event)
 {
-	if ((event.signal == TBB_WRITEF)||(event.signal == TP_WRITEFACK)) {
+	if ((event.signal == TBB_WRITE_IMAGE) 
+		|| (event.signal == TP_ERASEFACK)
+		|| (event.signal == TP_WRITEFACK)
+		|| (event.signal == TP_READFACK)) {
 		return(true);
 	}
 	return(false);
@@ -60,90 +85,283 @@ bool WritefCmd::isValid(GCFEvent& event)
 // ----------------------------------------------------------------------------
 void WritefCmd::saveTbbEvent(GCFEvent& event)
 {
-	itsTBBE 			= new TBBWritefEvent(event);
-		
-	itsBoardMask = (1 << itsTBBE->board);
+	itsTBBE	= new TBBWriteImageEvent(event);
+	
+	setBoardNr(itsTBBE->board);	
 	
-	// mask for the installed boards
-	itsBoardsMask = DriverSettings::instance()->activeBoardsMask();
+	memcpy(itsFileNameTp,itsTBBE->filename_tp,sizeof(char) * 64);
+	memcpy(itsFileNameMp,itsTBBE->filename_mp,sizeof(char) * 64);
 	
-	// Send only commands to boards installed
-	itsBoardMask = itsBoardMask & itsBoardsMask;
+	LOG_DEBUG_STR(formatString("TP file: %s",itsFileNameTp));
+	LOG_DEBUG_STR(formatString("MP file: %s",itsFileNameMp));
 	
-	itsTBBackE->status = 0;
+	itsImageData = new uint8[1966080];
+			
+	readFiles();
+	
+	itsTBBackE->status_mask = 0;
+	
+	itsImage 	= itsTBBE->image;
+	itsSector	= (itsImage * FL_SECTORS_IN_PAGE);
+	itsBlock	= (itsImage * FL_BLOCKS_IN_PAGE); 
 	
 	// initialize TP send frame
 	itsTPE->opcode			= TPWRITEF;
 	itsTPE->status			=	0;
-	itsTPE->addr	 			= itsTBBE->addr;
 	
-	for(int an = 0; an < 256;an++) {
-		itsTPE->data[an] = itsTBBE->data[an];
-	}
-
-	delete itsTBBE;	
+	itsStage = erase_flash;
 }
 
 // ----------------------------------------------------------------------------
-bool WritefCmd::sendTpEvent(int32 boardnr, int32)
+void WritefCmd::sendTpEvent()
 {
-	bool sending = false;
-	DriverSettings*		ds = DriverSettings::instance();
-	
-	if (ds->boardPort(boardnr).isConnected()) {
-		ds->boardPort(boardnr).send(*itsTPE);
-		ds->boardPort(boardnr).setTimer(ds->timeout());
-		sending = true;
-	}
-	else
-		itsTBBackE->status |= CMD_ERROR;
-		
-	return(sending);
+		switch (itsStage) {
+			
+			// stage 1, erase flash
+			case erase_flash: {
+				TPErasefEvent *erasefEvent = new TPErasefEvent();
+				erasefEvent->opcode	= TPERASEF;
+				erasefEvent->status	=	0;
+				erasefEvent->addr = static_cast<uint32>(itsSector * FL_SECTOR_SIZE);
+				TS->boardPort(getBoardNr()).send(*erasefEvent);
+				TS->boardPort(getBoardNr()).setTimer((long)1); // erase time sector is 500 mSec
+				delete erasefEvent;
+			} break;
+			
+			// stage 2, write flash
+			case write_flash: {
+				// fill event with data and send
+				itsTPE->addr = static_cast<uint32>(itsBlock * FL_BLOCK_SIZE);
+				
+				int ptr = itsBlock - (itsImage * FL_BLOCKS_IN_PAGE);
+				for (int tp_an=0; tp_an < 256; tp_an++) {
+					itsTPE->data[tp_an]  = itsImageData[ptr]; ptr++;
+					itsTPE->data[tp_an] |= (itsImageData[ptr] << 8); ptr++; 
+					itsTPE->data[tp_an] |= (itsImageData[ptr] << 16); ptr++; 
+					itsTPE->data[tp_an] |= (itsImageData[ptr] << 24); ptr++; 		
+				}
+				
+				TS->boardPort(getBoardNr()).send(*itsTPE);
+				TS->boardPort(getBoardNr()).setTimer(0.2);
+			} break;
+			
+			// stage 3, verify flash
+			case verify_flash: {
+				TPReadfEvent *readfEvent = new TPReadfEvent();
+				readfEvent->opcode	= TPREADF;
+				readfEvent->status	=	0;
+				readfEvent->addr = static_cast<uint32>(itsBlock * FL_BLOCK_SIZE);
+				TS->boardPort(getBoardNr()).send(*readfEvent);
+				TS->boardPort(getBoardNr()).setTimer(0.2);
+				delete readfEvent;
+			} break;
+			
+			case write_info: {
+				// save Image info in last block
+				itsBlock = (itsImage * FL_BLOCKS_IN_PAGE) + (FL_BLOCKS_IN_PAGE - 1);
+				itsTPE->addr = static_cast<uint32>(itsBlock * FL_BLOCK_SIZE);
+				for (int i = 0; i < 256; i++) {
+					itsTPE->data[i]  = 0;
+				}
+				time_t write_time;
+				time(&write_time);
+				itsTPE->data[0] = static_cast<uint32>(itsTBBE->version);
+				itsTPE->data[1] = static_cast<uint32>(write_time);
+				itsTPE->data[2] = 300;
+				itsTPE->data[3] = 400;
+				itsTPE->data[4] = 500;
+				itsTPE->data[5] = 600;
+				itsTPE->data[6] = 700;
+				itsTPE->data[7] = 800;
+				itsTPE->data[8] = 900;
+				itsTPE->data[9] = 1000;
+				TS->boardPort(getBoardNr()).send(*itsTPE);
+				TS->boardPort(getBoardNr()).setTimer(0.2);
+				LOG_DEBUG_STR("Writing image info");
+				LOG_DEBUG_STR(formatString("%u %u",itsTPE->data[0],itsTPE->data[1]));
+			} break;
+			
+			case verify_info: {
+				TPReadfEvent *readfEvent = new TPReadfEvent();
+				readfEvent->opcode	= TPREADF;
+				readfEvent->status	=	0;
+				itsBlock = (itsImage * FL_BLOCKS_IN_PAGE) + (FL_BLOCKS_IN_PAGE - 1);
+				readfEvent->addr = static_cast<uint32>(itsBlock * FL_BLOCK_SIZE);
+				TS->boardPort(getBoardNr()).send(*readfEvent);
+				TS->boardPort(getBoardNr()).setTimer(0.2);
+				LOG_DEBUG_STR("Verifying image info");
+				delete readfEvent;
+			} break;
+			
+			default : {
+			} break;
+		}
 }
 
 // ----------------------------------------------------------------------------
-void WritefCmd::saveTpAckEvent(GCFEvent& event, int32 boardnr)
+void WritefCmd::saveTpAckEvent(GCFEvent& event)
 {
-	// in case of a time-out, set error mask
 	if (event.signal == F_TIMER) {
-		itsTBBackE->status |= COMM_ERROR;
-	}
-	else {
-		itsTPackE = new TPWritefackEvent(event);
+				itsTBBackE->status_mask |= TBB_COMM_ERROR;
+				setDone(true);
+	}	else {
 		
-		itsBoardStatus	= itsTPackE->status;
-		
-		LOG_DEBUG_STR(formatString("Received WritefAck from boardnr[%d]", boardnr));
-		delete itsTPackE;
+		switch (itsStage) {
+			
+			case erase_flash: {
+				TPErasefackEvent *erasefAckEvent = new TPErasefackEvent(event);
+				
+				if (erasefAckEvent->status == 0) {
+					itsSector++;
+					if (itsSector == ((itsImage + 1) * FL_SECTORS_IN_PAGE)) {
+						itsStage = write_flash;
+					}		
+				} else {
+					LOG_DEBUG_STR("Received status > 0 (WritefCmd(erase_flash stage))");
+					setDone(true);
+				}
+				delete erasefAckEvent;
+			} break;
+			
+			case write_flash: {
+				itsTPackE = new TPWritefackEvent(event);
+					
+					if (itsTPackE->status == 0) {
+						itsStage = verify_flash;		
+					} else {
+						LOG_DEBUG_STR("Received status > 0 (WritefCmd(write_flash stage))");
+						setDone(true);
+					}
+					delete itsTPackE;
+			} break;
+			
+			case verify_flash: {
+				// check if write-data is read-data
+				bool same = true;
+				
+				TPReadfackEvent *readfAckEvent = new TPReadfackEvent(event);
+				
+				if (readfAckEvent->status == 0) {
+					for (int i = 0; i < (FL_BLOCK_SIZE / 4); i++) {
+						if (readfAckEvent->data[i] != itsTPE->data[i]) {
+							LOG_DEBUG_STR(formatString("data (%d) %d not same 0x%08X 0x%08X (WritefCmd(verify_flash stage))",itsBlock,i,readfAckEvent->data[i],itsTPE->data[i]));
+							same = false;	
+						}
+					}
+					if (same) {
+						itsBlock++;
+						itsStage = write_flash;
+					} else {
+						setDone(true);
+					}
+					
+					int nextByte = ((itsBlock - (itsImage * FL_BLOCKS_IN_PAGE)) * FL_BLOCK_SIZE); 
+					if (nextByte > itsImageSize) {
+						//setDone(true);
+						itsStage = write_info;
+					}
+				} else {
+					LOG_DEBUG_STR("Received status > 0 (WritefCmd(verify_flash stage))");
+					setDone(true);
+				}				
+				delete readfAckEvent;
+			} break;
+			
+			case write_info: {
+				itsTPackE = new TPWritefackEvent(event);
+					
+				if (itsTPackE->status == 0) {
+					itsStage = verify_info;		
+				} else {
+					LOG_DEBUG_STR(formatString("Received status > 0 (0x%08X) (WritefCmd(write_info stage))",itsTPackE->status));
+					setDone(true);
+				}
+				delete itsTPackE;
+			} break;
+			
+			case verify_info: {
+			// check if write-data is read-data
+				bool same = true;
+				
+				TPReadfackEvent *readfAckEvent = new TPReadfackEvent(event);
+				
+				if (readfAckEvent->status == 0) {
+					for (int i = 0; i < 10; i++) {
+						if (readfAckEvent->data[i] != itsTPE->data[i]) {
+							LOG_DEBUG_STR(formatString("image info %d not same 0x%08X 0x%08X (WritefCmd(verify_info stage))",i,readfAckEvent->data[i],itsTPE->data[i]));
+							same = false;	
+						}
+					}
+					if (!same) {
+						itsTBBackE->status_mask |= TBB_FLASH_ERROR; 
+					}
+				} else {
+					LOG_DEBUG_STR(formatString("Received status > 0 (0x%08X) (WritefCmd(verify_info stage))",readfAckEvent->status));
+				}				
+				delete readfAckEvent;
+				setDone(true);
+			} break;
+			
+			default : {
+			} break;
+		}
 	}
 }
 
 // ----------------------------------------------------------------------------
 void WritefCmd::sendTbbAckEvent(GCFPortInterface* clientport)
 {
-	if (itsTBBackE->status == 0)
-			itsTBBackE->status = SUCCESS;
+	if (itsTBBackE->status_mask == 0)
+			itsTBBackE->status_mask = TBB_SUCCESS;
 	
 	clientport->send(*itsTBBackE);
 }
 
-// ----------------------------------------------------------------------------
-CmdTypes WritefCmd::getCmdType()
+void WritefCmd::readFiles()
 {
-	return(BoardCmd);
+	FILE 	*itsFile;
+	int dataPtr = 0;
+	int ch_h, ch_l;
+	
+	// load Tp hex file
+	itsFile = fopen(itsFileNameTp,"r");
+	
+	ch_h = getc(itsFile);
+	ch_l = getc(itsFile);
+	while (ch_l != EOF) {
+		itsImageData[dataPtr] = (charToHex(ch_h) << 4) + charToHex(ch_l);
+		dataPtr++;
+		ch_h = getc(itsFile);
+		ch_l = getc(itsFile);
+	}
+	fclose(itsFile);
+	
+	// load Mp hex file
+	itsFile = fopen(itsFileNameMp,"r");
+	
+	ch_h = getc(itsFile);
+	ch_l = getc(itsFile);
+	while (ch_l != EOF) {
+		itsImageData[dataPtr] = (charToHex(ch_h) << 4) + charToHex(ch_l);
+		dataPtr++;
+		ch_h = getc(itsFile);
+		ch_l = getc(itsFile);
+	}
+	fclose(itsFile);
+	
+	itsImageSize = dataPtr;
 }
 
-// ----------------------------------------------------------------------------
-uint32 WritefCmd::getBoardMask()
-{
-	return(itsBoardMask);
-}
 
-// ----------------------------------------------------------------------------
-bool WritefCmd::waitAck()
+uint8 WritefCmd::charToHex(int ch)
 {
-	return(true);
+	if ((ch >= '0') && (ch <= '9')) {
+		return (ch & 0x0F);
+	} 
+	
+	if (((ch >= 'A') && (ch <= 'F')) || ((ch >= 'a') && (ch <= 'f')))	{
+		return ((ch & 0x0F) + 9);
+	}
+	return (0);
 }
 
-	} // end TBB namespace
-} // end LOFAR namespace
diff --git a/MAC/APL/PIC/TBBDriver/src/WritefCmd.h b/MAC/APL/PIC/TBBDriver/src/WritefCmd.h
index f26bb3d71aa3ec6bc8d2ea1bc136b0e636bf03a3..cf111729317ea30f88160b8deafcf3f689e30e87 100644
--- a/MAC/APL/PIC/TBBDriver/src/WritefCmd.h
+++ b/MAC/APL/PIC/TBBDriver/src/WritefCmd.h
@@ -32,11 +32,14 @@
 #include "TP_Protocol.ph"
 
 #include "Command.h"
+#include "DriverSettings.h"
 
 namespace LOFAR {
 	using namespace TBB_Protocol;
   namespace TBB {
-
+		
+		enum flashStage {idle, erase_flash, write_flash, verify_flash, write_info, verify_info};
+		
 		class WritefCmd : public Command 
 		{
 			public:
@@ -50,26 +53,35 @@ namespace LOFAR {
 				
 				virtual void saveTbbEvent(GCFEvent& event);
 									
-				virtual bool sendTpEvent(int32 boardnr, int32 channelnr);
+				virtual void sendTpEvent();
 
-				virtual void saveTpAckEvent(GCFEvent& event, int32 boardnr);
+				virtual void saveTpAckEvent(GCFEvent& event);
 
 				virtual void sendTbbAckEvent(GCFPortInterface* clientport);
+	
+				void readFiles();
+							
+				uint8 charToHex(int ch);
+				      
+			private:
+				TbbSettings *TS;
 				
-				virtual uint32 getBoardMask();
+				flashStage	itsStage;
 				
-				virtual bool waitAck();
+				int32		itsImage;
+				int32		itsSector;
+				int32		itsBlock;
+				int32		itsImageSize;
+				char		itsFileNameTp[64];
+				char		itsFileNameMp[64];
 				
-				virtual CmdTypes getCmdType();
-      
-			private:
-				uint32	itsBoardMask;  // mask indicates the boards to communicate with
-				uint32	itsBoardsMask;	// Installed boards mask
+								
+				TPWritefEvent					*itsTPE;
+				TPWritefackEvent			*itsTPackE;
+				TBBWriteImageEvent		*itsTBBE;
+				TBBWriteImageAckEvent	*itsTBBackE;
+				uint8									*itsImageData;
 				
-				TPWritefEvent			*itsTPE;
-				TPWritefackEvent	*itsTPackE;
-				TBBWritefEvent		*itsTBBE;
-				TBBWritefackEvent	*itsTBBackE;
 				
 				// variables holding data from tp cmd
 				uint32	itsBoardStatus;
diff --git a/MAC/APL/PIC/TBBDriver/src/WritewCmd.cc b/MAC/APL/PIC/TBBDriver/src/WritewCmd.cc
index 5c004c6dc72608d6a98ed991750c9a88c7bbdc3d..90e498189a6ade7e022ef7ec2ebe57775d0e65d2 100644
--- a/MAC/APL/PIC/TBBDriver/src/WritewCmd.cc
+++ b/MAC/APL/PIC/TBBDriver/src/WritewCmd.cc
@@ -24,22 +24,22 @@
 #include <Common/LofarLogger.h>
 
 #include "WritewCmd.h"
-#include "DriverSettings.h"
 
-namespace LOFAR {
-	using namespace TBB_Protocol;
-	using namespace TP_Protocol;
-	namespace TBB {
+using namespace LOFAR;
+using namespace TBB_Protocol;
+using namespace TP_Protocol;
+using	namespace TBB;
 
 //--Constructors for a WritewCmd object.----------------------------------------
 WritewCmd::WritewCmd():
-		itsBoardMask(0),itsBoardsMask(0),itsBoardStatus(0),
-		itsMp(0),itsAddr(0),itsWordLo(0),itsWordHi(0)
+		itsBoardStatus(0)		
 {
+	TS					= TbbSettings::instance();
 	itsTPE 			= new TPWritewEvent();
 	itsTPackE 	= 0;
 	itsTBBE 		= 0;
 	itsTBBackE 	= new TBBWritewackEvent();
+	setWaitAck(true);
 }
 	  
 //--Destructor for WritewCmd.---------------------------------------------------
@@ -61,22 +61,16 @@ bool WritewCmd::isValid(GCFEvent& event)
 // ----------------------------------------------------------------------------
 void WritewCmd::saveTbbEvent(GCFEvent& event)
 {
-	itsTBBE 			= new TBBWritewEvent(event);
+	itsTBBE	= new TBBWritewEvent(event);
 		
-	itsBoardMask = (1 << itsTBBE->board);
+	setBoardNr(itsTBBE->board);
 	
-	// mask for the installed boards
-	itsBoardsMask = DriverSettings::instance()->activeBoardsMask();
-	
-	// Send only commands to boards installed
-	itsBoardMask = itsBoardMask & itsBoardsMask;
-	
-	itsTBBackE->status = 0;
+	itsTBBackE->status_mask = 0;
 	
 	// initialize TP send frame
 	itsTPE->opcode	= TPWRITEW;
 	itsTPE->status	= 0;
-	itsTPE->mp			=	itsTBBE->mp;
+	itsTPE->mp			=	static_cast<uint32>(itsTBBE->mp);
 	itsTPE->addr		=	itsTBBE->addr;
 	itsTPE->wordlo	= itsTBBE->wordlo;
 	itsTPE->wordhi	= itsTBBE->wordhi;
@@ -85,65 +79,35 @@ void WritewCmd::saveTbbEvent(GCFEvent& event)
 }
 
 // ----------------------------------------------------------------------------
-bool WritewCmd::sendTpEvent(int32 boardnr, int32)
+void WritewCmd::sendTpEvent()
 {
-	bool sending = false;
-	DriverSettings*		ds = DriverSettings::instance();
-	
-	if (ds->boardPort(boardnr).isConnected()) {
-		ds->boardPort(boardnr).send(*itsTPE);
-		ds->boardPort(boardnr).setTimer(ds->timeout());
-		sending = true;
-	}
-	else
-		itsTBBackE->status |= CMD_ERROR;
-		
-	return(sending);
+	TS->boardPort(getBoardNr()).send(*itsTPE);
+	TS->boardPort(getBoardNr()).setTimer(TS->timeout());
 }
 
 // ----------------------------------------------------------------------------
-void WritewCmd::saveTpAckEvent(GCFEvent& event, int32 boardnr)
+void WritewCmd::saveTpAckEvent(GCFEvent& event)
 {
 	// in case of a time-out, set error mask
 	if (event.signal == F_TIMER) {
-		itsTBBackE->status |= COMM_ERROR;
+		itsTBBackE->status_mask |= TBB_COMM_ERROR;
 	}
 	else {
 		itsTPackE = new TPWritewackEvent(event);
 		
 		itsBoardStatus	= itsTPackE->status;
 				
-		LOG_DEBUG_STR(formatString("Received WritewAck from boardnr[%d]", boardnr));
+		LOG_DEBUG_STR(formatString("Received WritewAck from boardnr[%d]", getBoardNr()));
 		delete itsTPackE;
 	}
+	setDone(true);
 }
 
 // ----------------------------------------------------------------------------
 void WritewCmd::sendTbbAckEvent(GCFPortInterface* clientport)
 {
-	if (itsTBBackE->status == 0)
-			itsTBBackE->status = SUCCESS;
+	if (itsTBBackE->status_mask == 0)
+			itsTBBackE->status_mask = TBB_SUCCESS;
 
 	clientport->send(*itsTBBackE);
 }
-
-// ----------------------------------------------------------------------------
-CmdTypes WritewCmd::getCmdType()
-{
-	return(BoardCmd);
-}
-
-// ----------------------------------------------------------------------------
-uint32 WritewCmd::getBoardMask()
-{
-	return(itsBoardMask);
-}
-
-// ----------------------------------------------------------------------------
-bool WritewCmd::waitAck()
-{
-	return(true);
-}
-
-	} // end TBB namespace
-} // end LOFAR namespace
diff --git a/MAC/APL/PIC/TBBDriver/src/WritewCmd.h b/MAC/APL/PIC/TBBDriver/src/WritewCmd.h
index 1e22ae8f7b8549b3d5e645ac5ba9f18a9c047d16..82db77fb1c3c90d4440fa47196cc79ae6939cf02 100644
--- a/MAC/APL/PIC/TBBDriver/src/WritewCmd.h
+++ b/MAC/APL/PIC/TBBDriver/src/WritewCmd.h
@@ -32,6 +32,7 @@
 #include "TP_Protocol.ph"
 
 #include "Command.h"
+#include "DriverSettings.h"
 
 namespace LOFAR {
 	using namespace TBB_Protocol;
@@ -50,21 +51,14 @@ namespace LOFAR {
 				
 				virtual void saveTbbEvent(GCFEvent& event);
 									
-				virtual bool sendTpEvent(int32 boardnr, int32 channelnr);
+				virtual void sendTpEvent();
 
-				virtual void saveTpAckEvent(GCFEvent& event, int32 boardnr);
+				virtual void saveTpAckEvent(GCFEvent& event);
 
 				virtual void sendTbbAckEvent(GCFPortInterface* clientport);
 				
-				virtual uint32 getBoardMask();
-				
-				virtual bool waitAck();
-				
-				virtual CmdTypes getCmdType();
-      
 			private:
-				uint32	itsBoardMask;  // mask indicates the boards to communicate with
-				uint32	itsBoardsMask;	// Installed boards mask
+				TbbSettings *TS;
 				
 				TPWritewEvent			*itsTPE;
 				TPWritewackEvent	*itsTPackE;
@@ -73,10 +67,6 @@ namespace LOFAR {
 				
 				// variables holding data from tp cmd
 				uint32	itsBoardStatus;
-				uint32	itsMp;
-				uint32	itsAddr;
-				uint32	itsWordLo;
-				uint32	itsWordHi;
 		};
 	} // end TBB namespace
 } // end LOFAR namespace
diff --git a/MAC/APL/PIC/TBBDriver/src/tbbctl.cc b/MAC/APL/PIC/TBBDriver/src/tbbctl.cc
index ca0769d89da0f1d9a800cfd7d0a9597cacc726ce..e82ff4c13d805644c6bf451b4f94674580beb0da 100644
--- a/MAC/APL/PIC/TBBDriver/src/tbbctl.cc
+++ b/MAC/APL/PIC/TBBDriver/src/tbbctl.cc
@@ -34,10 +34,16 @@
 #include <Common/lofar_sstream.h>
 #include <getopt.h>
 
+#include <string.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <ctype.h>
 #include <Common/lofar_set.h>
+#include <time.h>
+
+#include <netinet/in.h>    
+#include <net/ethernet.h>  
+
 
 #include "tbbctl.h"
 
@@ -50,7 +56,7 @@ using namespace TbbCtl;
 //---- ALLOC  ----------------------------------------------------------------
 AllocCmd::AllocCmd(GCFPortInterface& port) : Command(port)
 {
-	logMessage(cout,formatString("\n== TBB ================================================== allocate memory ====\n"));	
+	logMessage(cout,"\n== TBB ================================================== allocate memory ====\n");	
 }
 
 //-----------------------------------------------------------------------------
@@ -58,10 +64,8 @@ void AllocCmd::send()
 {
 	TBBAllocEvent event;
 	
-	for(int boardnr = 0; boardnr < MAX_N_TBBBOARDS; boardnr++) {
-		if (getSelected()) event.channelmask[boardnr] = getChannelMask(boardnr); // if select cmd is used
-		else event.channelmask[boardnr] = 0xFFFF; // otherwise select all 
-	}
+	if (getSelected()) event.rcu_mask = getRcuMask(); // if select cmd is used
+	
 	itsPort.send(event);
 }
 
@@ -69,25 +73,33 @@ void AllocCmd::send()
 GCFEvent::TResult AllocCmd::ack(GCFEvent& e)
 {
 	TBBAllocackEvent ack(e);
-	
+	logMessage(cout,"TBB  Info");
+	logMessage(cout,"---  -------------------------------------------------------");
 	int32 bnr = 0;
-	for (int cnr=0; cnr < getMax(); cnr++) {
-			bnr = (int32)(cnr / 16);
-			if (ack.status[bnr] & SUCCESS) {
-				if (isSelected(cnr) ) {
-					logMessage(cout,formatString(
-							"Board %2d:  Channel %d: memory allocated",
-							bnr, cnr));
-				}
+	int32 oldbnr = -1;
+	for (int cnr=0; cnr < getMaxSelections(); cnr++) {
+		bnr = (int32)(cnr / 16);
+		
+		if (bnr != oldbnr) {
+			if ((ack.status_mask[bnr] & TBB_SUCCESS) || (ack.status_mask[bnr] & TBB_RCU_COMM_ERROR)) {
+				logMessage(cout,formatString(" %2d memory allocated for selected rcu's", bnr));
+			}	else {
+				logMessage(cout,formatString(" %2d %s", bnr, getDriverErrorStr(ack.status_mask[bnr]).c_str()));
 			}
-			
-			else {	
-				if (!(ack.status[bnr] & NO_BOARD))
-					logMessage(cout,formatString("Board %2d: %s",bnr, getErrorStr(ack.status[bnr]).c_str()));
+		}
+		
+		if (isSelected(cnr) && !(ack.status_mask[bnr] & TBB_NO_BOARD) ) {
+			if (ack.rcu_mask.test(cnr)) {
+				if (ack.status_mask[bnr] & TBB_SUCCESS) {
+					logMessage(cout,formatString("     ERROR, Rcu-%d NOT in correct state\n",cnr));
+				} else {
+					logMessage(cout,formatString("     ERROR, Rcu-%d  %s\n",cnr,getDriverErrorStr(ack.status_mask[bnr] & 0xFFFF0000).c_str()));
+				}
 			}
-			
+		}
+		oldbnr = bnr;
 	}
-	logMessage(cout,formatString("=============================================================================="));
+	
 	setCmdDone(true);
 
 	return(GCFEvent::HANDLED);
@@ -96,40 +108,42 @@ GCFEvent::TResult AllocCmd::ack(GCFEvent& e)
 //---- CHANNELINFO --------------------------------------------------------------
 ChannelInfoCmd::ChannelInfoCmd(GCFPortInterface& port) : Command(port)
 {
-	logMessage(cout,formatString("\n== TBB ===================================================== channel info ====\n"));
+	logMessage(cout,"\n== TBB ===================================================== rcu info =======\n");
 }
 
 //-----------------------------------------------------------------------------
 void ChannelInfoCmd::send()
 {
-	TBBChannelinfoEvent event;
+	TBBRcuinfoEvent event;
 	itsPort.send(event);
 }
 
 //-----------------------------------------------------------------------------
 GCFEvent::TResult ChannelInfoCmd::ack(GCFEvent& e)
 {
-	TBBChannelinfoackEvent ack(e);
+	TBBRcuinfoackEvent ack(e);
 	
 	int32 bnr = 0;
 	int32 oldbnr = -1;
-	for (int cnr=0; cnr < getMax(); cnr++) {
-			bnr = (int32)(cnr / 16);
-			if (ack.channelsize[cnr] != 0) {
-				if (isSelected(cnr) ) {
-					logMessage(cout,formatString(
-							"Board %2d:  Input %2d:  Status: %c  Start address: 0x%08X  Size: %u pages",
-							bnr, (cnr - (bnr * 16)), (char)ack.channelstatus[cnr], ack.channelstartaddr[cnr], ack.channelsize[cnr]));
+	for (int rcu=0; rcu < getMaxSelections(); rcu++) {
+	 		bnr = (int32)(rcu / 16);
+			if (ack.rcu_state[rcu] != 'F') {
+				if (isSelected(rcu) ) {
+					if (bnr != oldbnr) {
+						logMessage(cout,"Rcu  Board  Input  State  Start-address  Size[pages]");
+						logMessage(cout,"---  -----  -----  -----  -------------  -----------");
+					}
+					logMessage(cout,formatString(" %2d    %2d     %2d      %c     0x%08X  %11u %s",
+							rcu, ack.rcu_on_board[rcu], ack.rcu_on_input[rcu],
+							(char)ack.rcu_state[rcu],	ack.rcu_start_addr[rcu], ack.rcu_pages[rcu],
+							getBoardErrorStr(ack.rcu_status[rcu]).c_str()));
 				}
 			}
-			
-			else {	
-					//logMessage(cout,formatString("Board %2d:  input %2d: not allocated",bnr, (cnr - (bnr * 16))));
-			}
-			
 			oldbnr = bnr;
 	}
-	logMessage(cout,formatString("=============================================================================="));
+	logMessage(cout,"\n *State:  F = Free, A = Allocated, R = Recording, S = Stopped, E = Error");
+	logMessage(cout," *Only NOT Free rcu's are listed ");
+	
 	setCmdDone(true);
 
 	return(GCFEvent::HANDLED);
@@ -138,16 +152,16 @@ GCFEvent::TResult ChannelInfoCmd::ack(GCFEvent& e)
 //---- FREE ----------------------------------------------------------------
 FreeCmd::FreeCmd(GCFPortInterface& port) : Command(port)
 {
-	logMessage(cout,formatString("\n== TBB =================== discard buffer allocation and disable channels ====\n"));
+	logMessage(cout,"\n== TBB =================== discard buffer allocation and disable channels ====\n");
 }
 
 //-----------------------------------------------------------------------------
 void FreeCmd::send()
 {
 	TBBFreeEvent event;
-	for(int boardnr = 0; boardnr < MAX_N_TBBBOARDS; boardnr++) {
-		event.channelmask[boardnr] = getChannelMask(boardnr);
-	}
+	
+	if (getSelected()) event.rcu_mask = getRcuMask(); // if select cmd is used
+	
 	itsPort.send(event);
 }
 
@@ -155,23 +169,32 @@ void FreeCmd::send()
 GCFEvent::TResult FreeCmd::ack(GCFEvent& e)
 {
 	TBBFreeackEvent ack(e);
-	  
-	for (int bnr=0; bnr < MAX_N_TBBBOARDS; bnr++) {
-		if (isSelected(bnr) ) {
-			if (ack.status[bnr] & SUCCESS) {
-				logMessage(cout,formatString(
-						"Board %2d:  buffers discard and channels disabled",
-						bnr ));
+	logMessage(cout,"TBB  Info");
+	logMessage(cout,"---  -------------------------------------------------------");
+	int32 bnr = 0;
+	int32 oldbnr = -1;
+	for (int cnr=0; cnr < getMaxSelections(); cnr++) {
+		bnr = (int32)(cnr / 16);
+		
+		if (bnr != oldbnr) {
+			if (ack.status_mask[bnr] & TBB_SUCCESS) {
+				logMessage(cout,formatString(" %2d  buffer dischard and channel disabled for selected rcu's", bnr));
+			} else {
+				logMessage(cout,formatString(" %2d  %s", bnr, getDriverErrorStr(ack.status_mask[bnr]).c_str()));
 			}
-			
-			else {	
-				if (!(ack.status[bnr] & NO_BOARD))
-					logMessage(cout,formatString("Board %2d: %s",bnr, getErrorStr(ack.status[bnr]).c_str()));
+		}
+		if (isSelected(cnr) && !(ack.status_mask[bnr] & TBB_NO_BOARD) ) {
+			if (ack.rcu_mask.test(cnr)) {
+				if (ack.status_mask[bnr] & TBB_SUCCESS) {
+					logMessage(cout,formatString("     ERROR, Rcu-%d NOT in correct state\n",cnr));
+				} else {
+					logMessage(cout,formatString("     ERROR, Rcu-%d  %s\n",cnr,getDriverErrorStr(ack.status_mask[bnr]).c_str()));
+				}
 			}
-			
 		}
+		oldbnr = bnr;
 	}
-	logMessage(cout,formatString("=============================================================================="));
+	
 	setCmdDone(true);
 
 	return(GCFEvent::HANDLED);
@@ -180,16 +203,16 @@ GCFEvent::TResult FreeCmd::ack(GCFEvent& e)
 //---- RECORD ----------------------------------------------------------------
 RecordCmd::RecordCmd(GCFPortInterface& port) : Command(port)
 {
-	logMessage(cout,formatString("\n== TBB ============================= start recording on selected channels ====\n"));
+	logMessage(cout,"\n== TBB ============================= start recording on selected channels ====\n");
 }
 
 //-----------------------------------------------------------------------------
 void RecordCmd::send()
 {
 	TBBRecordEvent event;
-	for(int boardnr = 0; boardnr < MAX_N_TBBBOARDS; boardnr++) {
-		event.channelmask[boardnr] = getChannelMask(boardnr);
-	}
+	
+	if (getSelected()) event.rcu_mask = getRcuMask(); // if select cmd is used
+	
 	itsPort.send(event);
 }
 
@@ -197,21 +220,34 @@ void RecordCmd::send()
 GCFEvent::TResult RecordCmd::ack(GCFEvent& e)
 {
 	TBBRecordackEvent ack(e);
+	logMessage(cout,"TBB  Info");
+	logMessage(cout,"---  -------------------------------------------------------");
+	int32 bnr = 0;
+	int32 oldbnr = -1;
+	for (int cnr=0; cnr < getMaxSelections(); cnr++) {
+		bnr = (int32)(cnr / 16);
 		
-	for (int bnr=0; bnr < MAX_N_TBBBOARDS; bnr++) {
-		if (isSelected(bnr) ) {
-			if (ack.status[bnr] & SUCCESS) {
-				logMessage(cout,formatString(
-						"Board %2d:  start recording",
-						bnr ));
+		if (bnr != oldbnr) {
+			if (ack.status_mask[bnr] & TBB_SUCCESS) {
+				logMessage(cout,formatString(" %2d  recording started for selected rcu's", bnr));
+			} else {
+				logMessage(cout,formatString(" %2d  %s", bnr, getDriverErrorStr(ack.status_mask[bnr]).c_str()));
 			}
-			else {	
-				if (!(ack.status[bnr] & NO_BOARD))
-				logMessage(cout,formatString("Board %2d: %s",bnr, getErrorStr(ack.status[bnr]).c_str()));
+		}
+		
+		if (isSelected(cnr) && !(ack.status_mask[bnr] & TBB_NO_BOARD) ) {
+			if (ack.rcu_mask.test(cnr)) {
+				if (ack.status_mask[bnr] & TBB_SUCCESS) {
+					logMessage(cout,formatString("      ERROR, Rcu-%d NOT in correct state\n",cnr));
+				} else {
+					logMessage(cout,formatString("      ERROR, Rcu-%d  %s\n",cnr,getDriverErrorStr(ack.status_mask[bnr]).c_str()));
+				}
 			}
 		}
+		oldbnr = bnr;
 	}
-	logMessage(cout,formatString("=============================================================================="));
+	
+	
 	setCmdDone(true);
 
 	return(GCFEvent::HANDLED);
@@ -220,16 +256,16 @@ GCFEvent::TResult RecordCmd::ack(GCFEvent& e)
 //---- STOP -------------------------------------------------------------------
 StopCmd::StopCmd(GCFPortInterface& port) : Command(port)
 {
-	logMessage(cout,formatString("\n== TBB ============================== stop recording on selected channels ====\n"));	
+	logMessage(cout,"\n== TBB ============================== stop recording on selected channels ====\n");	
 }
 
 //-----------------------------------------------------------------------------
 void StopCmd::send()
 {
 	TBBStopEvent event;
-	for(int boardnr = 0; boardnr < MAX_N_TBBBOARDS; boardnr++) {
-		event.channelmask[boardnr] = getChannelMask(boardnr);
-	}
+	
+	if (getSelected()) event.rcu_mask = getRcuMask(); // if select cmd is used
+	
 	itsPort.send(event);
 }
 
@@ -237,21 +273,34 @@ void StopCmd::send()
 GCFEvent::TResult StopCmd::ack(GCFEvent& e)
 {
 	TBBStopackEvent ack(e);
-	  
-	for (int bnr=0; bnr < MAX_N_TBBBOARDS; bnr++) {
-		if (isSelected(bnr) ) {
-			if (ack.status[bnr] & SUCCESS) {
-				logMessage(cout,formatString(
-						"Board %2d:  stop recording",
-						bnr ));
+	logMessage(cout,"TBB  Info");
+	logMessage(cout,"---  -------------------------------------------------------");
+	int32 bnr = 0;
+	int32 oldbnr = -1;
+	for (int cnr=0; cnr < getMaxSelections(); cnr++) {
+		bnr = (int32)(cnr / 16);
+		
+		if (bnr != oldbnr) {
+			if (ack.status_mask[bnr] & TBB_SUCCESS) {
+				logMessage(cout,formatString(" %2d  recording stopped for selected rcu's", bnr));
+			} else {
+				logMessage(cout,formatString(" %2d  %s", bnr, getDriverErrorStr(ack.status_mask[bnr]).c_str()));
 			}
-			else {			
-				if (!(ack.status[bnr] & NO_BOARD))
-					logMessage(cout,formatString("Board %2d: %s",bnr, getErrorStr(ack.status[bnr]).c_str()));
+		}
+		
+		if (isSelected(cnr) && !(ack.status_mask[bnr] & TBB_NO_BOARD) ) {
+			if (ack.rcu_mask.test(cnr)) {
+				if (ack.status_mask[bnr] & TBB_SUCCESS) {
+					logMessage(cout,formatString("      ERROR, Rcu-%d NOT in correct state\n",cnr));
+				} else {
+				  logMessage(cout,formatString("      ERROR, Rcu-%d  %s\n",cnr,getDriverErrorStr(ack.status_mask[bnr]).c_str()));
+				}
 			}
 		}
+		oldbnr = bnr;
 	}
-	logMessage(cout,formatString("=============================================================================="));
+	
+	
 	setCmdDone(true);
 
 	return(GCFEvent::HANDLED);
@@ -260,14 +309,14 @@ GCFEvent::TResult StopCmd::ack(GCFEvent& e)
 //---- TRIGCLR ----------------------------------------------------------------
 TrigclrCmd::TrigclrCmd(GCFPortInterface& port) : Command(port)
 {
-	logMessage(cout,formatString("\n== TBB =========================== clear trigger on all selected channels ====\n"));
+	logMessage(cout,"\n== TBB ============================ clear trigger on selected channel ====\n");
 }
 
 //-----------------------------------------------------------------------------
 void TrigclrCmd::send()
 {
 	TBBTrigclrEvent event;
-	event.channel = (uint32)getChannel();
+	event.channel = (uint32)getRcu();
 	itsPort.send(event);
 }
 
@@ -275,36 +324,39 @@ void TrigclrCmd::send()
 GCFEvent::TResult TrigclrCmd::ack(GCFEvent& e)
 {
 	TBBTrigclrackEvent ack(e);
-	  
-	for (int bnr=0; bnr < getMax(); bnr++) {
+	logMessage(cout,"TBB  Info");
+	logMessage(cout,"---  -------------------------------------------------------");  
+	for (int bnr=0; bnr < getMaxSelections(); bnr++) {
 		if (isSelected(bnr) ) {
-			if (ack.status & SUCCESS) {
-				logMessage(cout,formatString(
-						"Board %2d:  clear trigger message",
-						bnr ));
-			}
-			else {	
-				logMessage(cout,formatString("Board %2d: %s",bnr, getErrorStr(ack.status).c_str()));
+			if (ack.status_mask & TBB_SUCCESS) {
+				logMessage(cout,formatString(" %2d  clear trigger message",bnr ));
+			}	else {	
+				logMessage(cout,formatString(" %2d  %s",bnr, getDriverErrorStr(ack.status_mask).c_str()));
 			}
 		}
 	}
-	logMessage(cout,formatString("=============================================================================="));
+	
 	setCmdDone(true);
 
 	return(GCFEvent::HANDLED);
 }
 
 //---- READ -------------------------------------------------------------------
-ReadCmd::ReadCmd(GCFPortInterface& port) : Command(port)
+ReadCmd::ReadCmd(GCFPortInterface& port) : Command(port),
+	itsSecondsTime(0),itsSampleTime(0),itsPrePages(0),itsPostPages(0)
 {
-	logMessage(cout,formatString("\n== TBB ==============  transfer data to CEP for all selected channels ====\n"));	
+	logMessage(cout,"\n== TBB ==============  transfer data to CEP for all selected channels ====\n");	
 }
 
 //-----------------------------------------------------------------------------
 void ReadCmd::send()
 {
 	TBBReadEvent event;
-	event.channel = (uint32)getChannel();
+	event.channel = (uint32)getRcu();
+	event.secondstime = itsSecondsTime;
+	event.sampletime = itsSampleTime;
+	event.prepages = itsPrePages;
+	event.postpages = itsPostPages;
 	itsPort.send(event);
 }
 
@@ -312,57 +364,51 @@ void ReadCmd::send()
 GCFEvent::TResult ReadCmd::ack(GCFEvent& e)
 {
 	TBBReadackEvent ack(e);
-	  
-	for (int bnr=0; bnr < getMax(); bnr++) {
-		if (isSelected(bnr) ) {
-			if (ack.status & SUCCESS) {
-				logMessage(cout,formatString(
-						"Board %2d:  tranfering data to CEP",
-						bnr ));
-			}
-			else {			
-				logMessage(cout,formatString("Board %2d: %s",bnr, getErrorStr(ack.status).c_str()));
+	logMessage(cout,"RCU  Info");
+	logMessage(cout,"---  -------------------------------------------------------");  
+	for (int cnr=0; cnr < getMaxSelections(); cnr++) {
+		if (isSelected(cnr) ) {
+			if (ack.status_mask & TBB_SUCCESS) {
+				logMessage(cout,formatString(" %2d  tranfering data to CEP",cnr ));
+			}	else {			
+				logMessage(cout,formatString(" %2d  %s",cnr, getDriverErrorStr(ack.status_mask).c_str()));
 			}
 		}
 	}
-	logMessage(cout,formatString("=============================================================================="));
+	
 	setCmdDone(true);
 
 	return(GCFEvent::HANDLED);
 }
 
-//---- UDP --------------------------------------------------------------------
-UdpCmd::UdpCmd(GCFPortInterface& port) : Command(port)
+//---- MODE --------------------------------------------------------------------
+ModeCmd::ModeCmd(GCFPortInterface& port) : Command(port)
+	,itsRecMode(0)
 {
-	logMessage(cout,formatString("\n== TBB ===================================== udp configure UDP/IP header ====\n"));
+	logMessage(cout,"\n== TBB ===================================== set mode command ===============\n");
 }
 
 //-----------------------------------------------------------------------------
-void UdpCmd::send()
+void ModeCmd::send()
 {
-	TBBUdpEvent event;
-	event.boardmask = getMask();
+	TBBModeEvent event;
+	event.board = (uint32)getBoard();
+	event.rec_mode = itsRecMode;
 	itsPort.send(event);
 }
 
 //-----------------------------------------------------------------------------
-GCFEvent::TResult UdpCmd::ack(GCFEvent& e)
-{
-	TBBUdpackEvent ack(e);
-	  
-	for (int bnr=0; bnr < getMax(); bnr++) {
-		if (isSelected(bnr) ) {
-			if (ack.status[bnr] & SUCCESS) {
-				logMessage(cout,formatString(
-						"Board %2d:  UDP/IP configured",
-						bnr ));
-			}
-			else {			
-				logMessage(cout,formatString("Board %2d: %s",bnr, getErrorStr(ack.status[bnr]).c_str()));
-			}
-		}
+GCFEvent::TResult ModeCmd::ack(GCFEvent& e)
+{
+	TBBModeackEvent ack(e);
+	logMessage(cout,"TBB  Info");
+	logMessage(cout,"---  -------------------------------------------------------");  
+	if (ack.status_mask & TBB_SUCCESS) {
+		logMessage(cout,formatString(" %2d  mode set and UDP/IP configured", getBoard()));
+	}	else {			
+		logMessage(cout,formatString(" %2d  %s",getBoard(), getDriverErrorStr(ack.status_mask).c_str()));
 	}
-	logMessage(cout,formatString("=============================================================================="));
+	
 	setCmdDone(true);
 
 	return(GCFEvent::HANDLED);
@@ -371,14 +417,14 @@ GCFEvent::TResult UdpCmd::ack(GCFEvent& e)
 //---- VERSION ----------------------------------------------------------------
 VersionCmd::VersionCmd(GCFPortInterface& port) : Command(port)
 {
-	logMessage(cout,formatString("\n== TBB ====================================== ID and version information ====\n"));
+	logMessage(cout,"\n== TBB ====================================== ID and version information ====\n");
 }
 
 //-----------------------------------------------------------------------------
 void VersionCmd::send()
 {
   TBBVersionEvent event;
-  event.boardmask = getMask();
+  event.boardmask = getBoardMask();
   itsPort.send(event);
 }
 
@@ -387,27 +433,28 @@ GCFEvent::TResult VersionCmd::ack(GCFEvent& e)
 {
   TBBVersionackEvent ack(e);
 	
-	for (int bnr=0; bnr < getMax(); bnr++) {
+	logMessage(cout,formatString("TBBDriver software version %3.1f\n",(ack.driverversion / 10.)));
+	logMessage(cout,"TBB  ID  Software   Board    TP0      MP0      MP1      MP2      TP3");
+	logMessage(cout,"---  --  --------  -------  -------  -------  -------  -------  -------");
+	for (int bnr=0; bnr < getMaxSelections(); bnr++) {
 		if (isSelected(bnr) ) {
-			if (ack.status[bnr] & SUCCESS) {
-				logMessage(cout,formatString(
-						"Board %2u:  ID=%u ; SW=V%u ; board=V%u ; TP=V%u ; MP0=V%u ; MP1=V%u ; MP2=V%u ; MP3=V%u",
+			if (ack.status_mask[bnr] & TBB_SUCCESS) {
+				logMessage(cout,formatString(" %2u  %2u   V%5.1f    V%4.1f    V%4.1f    V%4.1f    V%4.1f    V%4.1f    V%4.1f",
 	          bnr,
 	          ack.boardid[bnr],
-	         	ack.swversion[bnr],
-	          ack.boardversion[bnr],
-	          ack.tpversion[bnr],
-	          ack.mp0version[bnr],
-	          ack.mp1version[bnr],
-	         	ack.mp2version[bnr],
-	         	ack.mp3version[bnr] ));
-			}
-			else {
-					logMessage(cout,formatString("Board %2d: %s",bnr, getErrorStr(ack.status[bnr]).c_str()));	
+						(ack.swversion[bnr] / 10.),
+						(ack.boardversion[bnr] / 10.),
+						(ack.tpversion[bnr] / 10.),
+						(ack.mp0version[bnr] / 10.),
+						(ack.mp1version[bnr] / 10.),
+						(ack.mp2version[bnr] / 10.),
+						(ack.mp3version[bnr] / 10.)));
+			}	else {
+					logMessage(cout,formatString(" %2u  %s",bnr, getDriverErrorStr(ack.status_mask[bnr]).c_str()));	
       }
   	}
 	}
-	logMessage(cout,formatString("=============================================================================="));
+	
   setCmdDone(true);
 
   return(GCFEvent::HANDLED);
@@ -416,14 +463,14 @@ GCFEvent::TResult VersionCmd::ack(GCFEvent& e)
 //---- SIZE -------------------------------------------------------------------
 SizeCmd::SizeCmd(GCFPortInterface& port) : Command(port)
 {
-  logMessage(cout,formatString("\n== TBB ==================================== installed memory information ====\n"));	
+  logMessage(cout,"\n== TBB ==================================== installed memory information ====\n");	
 }
 
 //-----------------------------------------------------------------------------
 void SizeCmd::send()
 {
   TBBSizeEvent event;
-  event.boardmask = getMask();
+  event.boardmask = getBoardMask();
   itsPort.send(event);
 }
 
@@ -431,22 +478,20 @@ void SizeCmd::send()
 GCFEvent::TResult SizeCmd::ack(GCFEvent& e)
 {
   TBBSizeackEvent ack(e);
-    
-	for (int bnr=0; bnr < getMax(); bnr++) {
+	logMessage(cout,"TBB  pages     Total memory ");
+	logMessage(cout,"---  --------  ------------"); 
+	for (int bnr=0; bnr < getMaxSelections(); bnr++) {
 		if (isSelected(bnr) ) {
-			if (ack.status[bnr] & SUCCESS) {
-				logMessage(cout,formatString(
-						"Board %2u:  %d pages of 2048 bytes ; Total= %6.3f GByte",
-						bnr,
-						ack.npages[bnr],
-						(((double)ack.npages[bnr] * 2048.) / (1024. * 1024. * 1024.)) ));
-			}
-    	else {	
-				logMessage(cout,formatString("Board %2d: %s",bnr, getErrorStr(ack.status[bnr]).c_str()));
+			if (ack.status_mask[bnr] & TBB_SUCCESS) {
+				double gbyte = ((double)ack.npages[bnr] * 2048.) / (1024. * 1024. * 1024.); 
+				logMessage(cout,formatString(" %2d  %8d  %6.3f GByte",bnr,ack.npages[bnr],gbyte));
+			}	else {	
+				logMessage(cout,formatString(" %2d  %s",bnr, getDriverErrorStr(ack.status_mask[bnr]).c_str()));
       }
   	}
 	}
-	logMessage(cout,formatString("=============================================================================="));
+	logMessage(cout,"\n1 page = 2048 Bytes");
+	
   setCmdDone(true);
 
   return(GCFEvent::HANDLED);
@@ -455,14 +500,14 @@ GCFEvent::TResult SizeCmd::ack(GCFEvent& e)
 //---- STATUS -----------------------------------------------------------------
 StatusCmd::StatusCmd(GCFPortInterface& port) : Command(port)
 {
-  logMessage(cout,formatString("\n== TBB ============================= voltage and temperature information ====\n"));	
+  logMessage(cout,"\n== TBB ============================= voltage and temperature information ====\n");	
 }
 
 //-----------------------------------------------------------------------------
 void StatusCmd::send()
 {
   TBBStatusEvent event;
-  event.boardmask = getMask();
+  event.boardmask = getBoardMask();
   itsPort.send(event);
 }
 
@@ -471,31 +516,29 @@ GCFEvent::TResult StatusCmd::ack(GCFEvent& e)
 {
   TBBStatusackEvent ack(e);
     
-	for (int bnr=0; bnr < getMax(); bnr++) {
+	logMessage(cout,"TBB  Voltage 1.2  Voltage 2.5  Voltage 3.3  Temp PCB  Temp TP   Temp MP0  Temp MP1  Temp MP2  Temp MP3");
+	logMessage(cout,"---  -----------  -----------  -----------  --------  --------  --------  --------  --------  --------");
+	for (int bnr=0; bnr < getMaxSelections(); bnr++) {
 		if (isSelected(bnr) ) {
-			if (ack.status[bnr] & SUCCESS) {
-				logMessage(cout,formatString(
-						"Board %2d:  P1.2= %4.2fV ; P2.5= %4.2fV ; P5.0= %4.2fV ; Tpcb= %uC ; Ttp= %uC ; Tmp0= %uC ; Tmp1= %uC ; Tmp2= %uC ; Tmp3= %uC",
+			if (ack.status_mask[bnr] & TBB_SUCCESS) {
+				
+				logMessage(cout,formatString(" %2d     %4.2f V       %4.2f V       %4.2f V    %3u 'C    %3u 'C    %3u 'C    %3u 'C    %3u 'C    %3u 'C",
 						bnr,
-						//(double)ack.V25[bnr],	
-						//(double)ack.V33[bnr],	
-						//(double)ack.V12[bnr],	
-						((double)ack.V25[bnr] * (2.5 / 192.)),	// MAX6652 pin-2:  2.5 / 192	= 0.0130 / count
-						((double)ack.V33[bnr] * (3.3 / 192.)),	// MAX6652 pin-3:  3.3 / 192	= 0.0172 / count
-						((double)ack.V12[bnr] * (12. / 192.)),	// MAX6652 pin-1: 12.0 / 192	= 0.0625 / count
+						((double)ack.V12[bnr] * (2.5 / 192.)),	// MAX6652 pin-2:  2.5 / 192	= 0.0130 / count
+						((double)ack.V25[bnr] * (3.3 / 192.)),	// MAX6652 pin-3:  3.3 / 192	= 0.0172 / count
+						((double)ack.V33[bnr] * (5.0 / 192.)),	// MAX6652 pin-1:  5.0 / 192	= 0.0625 / count
 						ack.Tpcb[bnr],
 						ack.Ttp[bnr],
 						ack.Tmp0[bnr],
 						ack.Tmp1[bnr],
 						ack.Tmp2[bnr],
 						ack.Tmp3[bnr] ));
-			}
-    	else {	
-				logMessage(cout,formatString("Board %2d: %s",bnr, getErrorStr(ack.status[bnr]).c_str()));
+			}	else {	
+				logMessage(cout,formatString(" %2d  %s",bnr, getDriverErrorStr(ack.status_mask[bnr]).c_str()));
       }
   	}
 	}
-	logMessage(cout,formatString("=============================================================================="));
+	
   setCmdDone(true);
 
   return(GCFEvent::HANDLED);
@@ -504,14 +547,14 @@ GCFEvent::TResult StatusCmd::ack(GCFEvent& e)
 //---- CLEAR -------------------------------------------------------------------
 ClearCmd::ClearCmd(GCFPortInterface& port) : Command(port)
 {
-	logMessage(cout,formatString("\n== TBB =============================================== clear in progress ====\n"));
+	logMessage(cout,"\n== TBB =============================================== clear in progress ====\n");
 }
 
 //-----------------------------------------------------------------------------
 void ClearCmd::send()
 {
 	TBBClearEvent event;
-	event.boardmask = getMask();
+	event.boardmask = getBoardMask();
 	itsPort.send(event);
 }
 
@@ -519,20 +562,18 @@ void ClearCmd::send()
 GCFEvent::TResult ClearCmd::ack(GCFEvent& e)
 {
 	TBBClearackEvent ack(e);
-    
-	for (int bnr=0; bnr < getMax(); bnr++) {
+	logMessage(cout,"TBB  Info");
+	logMessage(cout,"---  -------------------------------------------------------");    
+	for (int bnr=0; bnr < getMaxSelections(); bnr++) {
 		if (isSelected(bnr) ) {
-			if (ack.status[bnr] & SUCCESS) {
-				logMessage(cout,formatString(
-						"Board %2d:  board is cleared",
-						bnr ));
-			}
-			else {	
-				logMessage(cout,formatString("Board %2d: %s",bnr, getErrorStr(ack.status[bnr]).c_str()));
+			if (ack.status_mask[bnr] & TBB_SUCCESS) {
+				logMessage(cout,formatString(" %2d  board is cleared",bnr ));
+			}	else {	
+				logMessage(cout,formatString(" %2d  %s",bnr, getDriverErrorStr(ack.status_mask[bnr]).c_str()));
 			}
 		}
 	}
-	logMessage(cout,formatString("=============================================================================="));
+	
 	setCmdDone(true);
 
 	return(GCFEvent::HANDLED);
@@ -541,14 +582,14 @@ GCFEvent::TResult ClearCmd::ack(GCFEvent& e)
 //---- RESET -------------------------------------------------------------------
 ResetCmd::ResetCmd(GCFPortInterface& port) : Command(port)
 {
-	logMessage(cout,formatString("\n== TBB =============================================== reset in progress ====\n"));
+	logMessage(cout,"\n== TBB =============================================== reset in progress ====\n");
 }
 
 //-----------------------------------------------------------------------------
 void ResetCmd::send()
 {
 	TBBResetEvent event;
-	event.boardmask = getMask();
+	event.boardmask = getBoardMask();
 	itsPort.send(event);
 }
 
@@ -556,20 +597,18 @@ void ResetCmd::send()
 GCFEvent::TResult ResetCmd::ack(GCFEvent& e)
 {
 	TBBResetackEvent ack(e);
-    
-	for (int bnr=0; bnr < getMax(); bnr++) {
+	logMessage(cout,"TBB  Info");
+	logMessage(cout,"---  -------------------------------------------------------");    
+	for (int bnr=0; bnr < getMaxSelections(); bnr++) {
 		if (isSelected(bnr) ) {
-			if (ack.status[bnr] & SUCCESS) {
-				logMessage(cout,formatString(
-						"Board %2d:  board is reset",
-						bnr ));
-			}
-			else {	
-				logMessage(cout,formatString("Board %2d: %s",bnr, getErrorStr(ack.status[bnr]).c_str()));
+			if (ack.status_mask[bnr] & TBB_SUCCESS) {
+				logMessage(cout,formatString(" %2d  board is reset",bnr ));
+			}	else {	
+				logMessage(cout,formatString(" %2d  %s",bnr, getDriverErrorStr(ack.status_mask[bnr]).c_str()));
 			}
 		}
 	}
-	logMessage(cout,formatString("=============================================================================="));
+	
 	setCmdDone(true);
 
 	return(GCFEvent::HANDLED);
@@ -578,14 +617,14 @@ GCFEvent::TResult ResetCmd::ack(GCFEvent& e)
 //---- CONFIG -------------------------------------------------------------------
 ConfigCmd::ConfigCmd(GCFPortInterface& port) : Command(port)
 {
-	logMessage(cout,formatString("\n== TBB ========================================= reconfigure TP and MP's ====\n"));
+	logMessage(cout,"\n== TBB ========================================= reconfigure TP and MP's ====\n");
 }
 
 //-----------------------------------------------------------------------------
 void ConfigCmd::send()
 {
 	TBBConfigEvent event;
-	event.boardmask = getMask();
+	event.boardmask = getBoardMask();
 	event.imagenr = itsImage;
 	itsPort.send(event);
 }
@@ -594,149 +633,201 @@ void ConfigCmd::send()
 GCFEvent::TResult ConfigCmd::ack(GCFEvent& e)
 {
 	TBBConfigackEvent ack(e);
-    
-	for (int bnr=0; bnr < getMax(); bnr++) {
+	logMessage(cout,"TBB  Info");
+	logMessage(cout,"---  -------------------------------------------------------");    
+	for (int bnr=0; bnr < getMaxSelections(); bnr++) {
 		if (isSelected(bnr) ) {
-			if (ack.status[bnr] & SUCCESS) {
-				logMessage(cout,formatString(
-						"Board %2d:  reconfigured TP and MP's",
-						bnr ));
-			}
-			else {	
-				logMessage(cout,formatString("Board %2d: %s",bnr, getErrorStr(ack.status[bnr]).c_str()));
+			if (ack.status_mask[bnr] & TBB_SUCCESS) {
+				logMessage(cout,formatString(" %2d  reconfigured TP and MP's",bnr ));
+			}	else {	
+				logMessage(cout,formatString(" %2d  %s",bnr, getDriverErrorStr(ack.status_mask[bnr]).c_str()));
 			}
 		}
 	}
-	logMessage(cout,formatString("=============================================================================="));
+	
 	setCmdDone(true);
 
 	return(GCFEvent::HANDLED);
 }
 
-//---- ERASEF -------------------------------------------------------------------
+//---- ERASE IMAGE --------------------------------------------------------------
 ErasefCmd::ErasefCmd(GCFPortInterface& port) : Command(port)
+	,itsPage(0)
 {
-	logMessage(cout,formatString("\n== TBB ===================================================== erase flash ====\n"));	
+	logMessage(cout,"\n== TBB ===================================================== erase flash ====\n");
+	logMessage(cout,"TBB  Info");
+	logMessage(cout,"---  -------------------------------------------------------");  
+
 }
 
 //-----------------------------------------------------------------------------
 void ErasefCmd::send()
 {
-	TBBErasefEvent event;
-	event.board = (uint32)getBoard();
+	TBBEraseImageEvent event;
+	event.board = getBoard();
+	event.image = itsPage;
+	logMessage(cout,formatString(" %2d  erasing flash memory of image %d\n", getBoard(), itsPage));
+	logMessage(cout,"     erasing will take about 8 seconds");	
 	itsPort.send(event);
 }
 
 //-----------------------------------------------------------------------------
 GCFEvent::TResult ErasefCmd::ack(GCFEvent& e)
 {
-	TBBErasefackEvent ack(e);
-		
-
-    
-	for (int bnr=0; bnr < getMax(); bnr++) {
-		if (isSelected(bnr) ) {
-			if (ack.status & SUCCESS) {
-				logMessage(cout,formatString(
-						"Board %2d:  flash is erased",
-						bnr ));
-			}
-			else {	
-				logMessage(cout,formatString("Board %2d: %s",bnr, getErrorStr(ack.status).c_str()));
-			}
-		}
+	TBBEraseImageAckEvent ack(e);
+	  
+	if (ack.status_mask & TBB_SUCCESS) {
+		logMessage(cout,formatString(" %2d  image is erased",getBoard()));
+	}	else {	
+		logMessage(cout,formatString(" %2d  %s",getBoard(), getDriverErrorStr(ack.status_mask).c_str()));
 	}
-	logMessage(cout,formatString("=============================================================================="));
+	
 	setCmdDone(true);
 
 	return(GCFEvent::HANDLED);
 }
 
-//---- READF -------------------------------------------------------------------
+//---- READ IMAGE --------------------------------------------------------------
 ReadfCmd::ReadfCmd(GCFPortInterface& port) : Command(port)
+	,itsPage(0)
 {
-	logMessage(cout,formatString("\n== TBB ====================================================== read flash ====\n"));
+	//memset(itsFileName,'\0',sizeof(itsFileName));
+	//memset(itsPageData,0,sizeof(itsPageData));
+	logMessage(cout,"\n== TBB ====================================================== read flash ====\n");
+	logMessage(cout,"TBB  Info");
+	logMessage(cout,"---  -------------------------------------------------------");  
 }
 
 //-----------------------------------------------------------------------------
 void ReadfCmd::send()
 {
-	TBBReadfEvent event;
-	event.board = (uint32)getBoard();
+	TBBReadImageEvent event;
+	event.board = getBoard();
+	event.image = itsPage;
+	logMessage(cout,formatString(" %2d  reading flash memory of image %d\n", getBoard(), itsPage));
+	logMessage(cout,"     reading will take about 12 seconds");	
 	itsPort.send(event);
 }
 
 //-----------------------------------------------------------------------------
 GCFEvent::TResult ReadfCmd::ack(GCFEvent& e)
 {
-	TBBReadfackEvent ack(e);
-    
-	for (int bnr=0; bnr < getMax(); bnr++) {
-		if (isSelected(bnr) ) {
-			if (ack.status & SUCCESS) {
-				logMessage(cout,formatString(
-						"Board %2d:  flash is read",
-						bnr ));
-			}
-			else {	
-				logMessage(cout,formatString("Board %2d: %s",bnr, getErrorStr(ack.status).c_str()));
-			}
+	TBBReadImageAckEvent ack(e);
+
+		if (ack.status_mask & TBB_SUCCESS) {
+			logMessage(cout,formatString(" %2d  image is read",getBoard()));
+		}	else {	
+			logMessage(cout,formatString(" %2d  %s",getBoard(), getDriverErrorStr(ack.status_mask).c_str()));
 		}
-	}
-	logMessage(cout,formatString("=============================================================================="));
-	setCmdDone(true);
+
+		
+		setCmdDone(true);
+	
 
 	return(GCFEvent::HANDLED);
 }
 
-//---- WRITEF -------------------------------------------------------------------
+//---- WRITE IMAGE -----------------------------------------------------------
 WritefCmd::WritefCmd(GCFPortInterface& port) : Command(port)
+	,itsPage(0)
 {
-	logMessage(cout,formatString("\n== TBB ===================================================== write flash ====\n"));
+	memset(itsFileNameTp,'\0',sizeof(itsFileNameTp));
+	memset(itsFileNameMp,'\0',sizeof(itsFileNameMp));
+	logMessage(cout,"\n== TBB ===================================================== write flash ====\n");
+	logMessage(cout,"TBB  Info");
+	logMessage(cout,"---  -------------------------------------------------------");  
 }
 
 //-----------------------------------------------------------------------------
 void WritefCmd::send()
 {
-	TBBWritefEvent event;
-	event.board = (uint32)getBoard();
+	TBBWriteImageEvent event;
+	event.board = getBoard();
+	event.image = itsPage;
+	event.version = static_cast<int32>(round(itsVersion * 10.));
+	memcpy(event.filename_tp,itsFileNameTp,sizeof(itsFileNameTp));
+	memcpy(event.filename_mp,itsFileNameMp,sizeof(itsFileNameMp));
+	logMessage(cout,formatString(" %2d  writing flash memory of image %d\n", getBoard(), itsPage));
+	logMessage(cout,"     writing will take about 25 seconds");	
 	itsPort.send(event);
 }
 
 //-----------------------------------------------------------------------------
 GCFEvent::TResult WritefCmd::ack(GCFEvent& e)
 {
-	TBBWritefackEvent ack(e);
-    
-	for (int bnr=0; bnr < getMax(); bnr++) {
-		if (isSelected(bnr) ) {
-			if (ack.status & SUCCESS) {
-				logMessage(cout,formatString(
-						"Board %2d:  write flash",
-						bnr ));
-			}
-			else {	
-				logMessage(cout,formatString("Board %2d: %s",bnr, getErrorStr(ack.status).c_str()));
+	TBBWriteImageAckEvent ack(e);
+	if (ack.status_mask & TBB_SUCCESS) {
+		logMessage(cout,formatString(" %2d  image is written",getBoard()));
+	}	else {	
+		logMessage(cout,formatString(" %2d  %s",getBoard(), getDriverErrorStr(ack.status_mask).c_str()));
+	}
+	
+	setCmdDone(true);
+
+	return(GCFEvent::HANDLED);
+}
+
+//---- IMAGE INFO -------------------------------------------------------------
+ImageInfoCmd::ImageInfoCmd(GCFPortInterface& port) : Command(port)
+{
+	logMessage(cout,"\n== TBB ===================================================== image info ====\n");
+}
+
+//-----------------------------------------------------------------------------
+void ImageInfoCmd::send()
+{
+	TBBImageInfoEvent event;
+	event.board = getBoard();
+	itsPort.send(event);
+}
+
+//-----------------------------------------------------------------------------
+GCFEvent::TResult ImageInfoCmd::ack(GCFEvent& e)
+{
+	TBBImageInfoAckEvent ack(e);
+	logMessage(cout,formatString("Reading image information from TBB %d\n", getBoard()));
+	logMessage(cout,"IMAGE  Version  Flash date");
+	logMessage(cout,"-----  -------  -------------------");  
+	if (ack.status_mask & TBB_SUCCESS) {
+		for (int image = 0; image < 32; image++) {	
+			if (ack.image_version[image] > 0xF0000000) {
+				logMessage(cout,formatString("  %2d      -          -                 no image information",image));
+			} else {
+				time_t write_time;
+				struct tm t;
+				double version;
+				
+				write_time = static_cast<time_t>(ack.write_date[image]);
+				t = *gmtime(&write_time);
+				version = static_cast<double>(ack.image_version[image] / 10.);
+				logMessage(cout,formatString("  %2d   %5.1f    %d-%d-%d  %d:%02d:%02d",image, version, 
+									 t.tm_mday,t.tm_mon,t.tm_year+1900,t.tm_hour,t.tm_min,t.tm_sec));
 			}
 		}
+	}	else {	
+		logMessage(cout,formatString("TBB %2d  %s",getBoard(), getDriverErrorStr(ack.status_mask).c_str()));
 	}
-	logMessage(cout,formatString("=============================================================================="));
+	
 	setCmdDone(true);
 
 	return(GCFEvent::HANDLED);
 }
 
+
+
 //---- READW -------------------------------------------------------------------
 ReadwCmd::ReadwCmd(GCFPortInterface& port) : Command(port)
 {
-	logMessage(cout,formatString("\n== TBB ======================================================= read DDR2 ====\n"));
+	logMessage(cout,"\n== TBB ======================================================= read DDR2 ====\n");
+	logMessage(cout,"TBB  Info");
+	logMessage(cout,"---  -------------------------------------------------------");  
 }
 
 //-----------------------------------------------------------------------------
 void ReadwCmd::send()
 {
 	TBBReadwEvent event;
-	event.board = (uint32)getBoard();
+	event.board = getBoard();
 	event.mp = itsMp;
 	event.addr = itsAddr;
 	itsPort.send(event);
@@ -746,40 +837,41 @@ void ReadwCmd::send()
 GCFEvent::TResult ReadwCmd::ack(GCFEvent& e)
 {
 	TBBReadwackEvent ack(e);
-    
-	for (int bnr=0; bnr < getMax(); bnr++) {
+	for (int bnr=0; bnr < getMaxSelections(); bnr++) {
 		if (isSelected(bnr) ) {
-			if (ack.status & SUCCESS) {
-				logMessage(cout,formatString(
-						"Board %2d:  MP[%u] Addr[0x%08X]  [0x%08X] [0x%08X]",
-						bnr, itsMp, itsAddr, ack.wordlo, ack.wordhi ));
-			}
-			else {	
-				logMessage(cout,formatString("Board %2d: %s",bnr, getErrorStr(ack.status).c_str()));
+			if (ack.status_mask & TBB_SUCCESS) {
+				logMessage(cout,formatString(" %2d  MP[%u] Addr[0x%08X]  [0x%08X] [0x%08X]"
+						,bnr, itsMp, itsAddr, ack.wordlo, ack.wordhi ));
+			}	else {	
+				logMessage(cout,formatString(" %2d  %s"
+						,bnr, getDriverErrorStr(ack.status_mask).c_str()));
 				itsAddr = itsStopAddr - 1;
 			}
 		}
 	}
 	if (itsAddr == (itsStopAddr - 1))
-	logMessage(cout,formatString("=============================================================================="));
+	
 	
 	itsAddr++;
-	if (itsAddr >= itsStopAddr) { setCmdDone(true); }
-	else { itsPort.setTimer(0.01); }
+	if (itsAddr >= itsStopAddr) { 
+		setCmdDone(true); 
+	}	else { 
+		itsPort.setTimer(0.01);
+	}
 	return(GCFEvent::HANDLED);
 }
 
 //---- WRITEW -------------------------------------------------------------------
 WritewCmd::WritewCmd(GCFPortInterface& port) : Command(port)
 {
-	logMessage(cout,formatString("\n== TBB ====================================================== write DDR2 ====\n"));
+	logMessage(cout,"\n== TBB ====================================================== write DDR2 ====\n");
 }
 
 //-----------------------------------------------------------------------------
 void WritewCmd::send()
 {
 	TBBWritewEvent event;
-	event.board = (uint32)getBoard();
+	event.board = getBoard();
 	event.mp = itsMp;
 	event.addr = itsAddr;
 	event.wordlo = itsWordLo;
@@ -791,21 +883,19 @@ void WritewCmd::send()
 GCFEvent::TResult WritewCmd::ack(GCFEvent& e)
 {
 	TBBWritewackEvent ack(e);
-    
-	for (int bnr=0; bnr < getMax(); bnr++) {
+	logMessage(cout,"TBB  Info");
+	logMessage(cout,"---  -------------------------------------------------------");    
+	for (int bnr=0; bnr < getMaxSelections(); bnr++) {
 		if (isSelected(bnr) ) {
-			if (ack.status & SUCCESS) {
-				logMessage(cout,formatString(
-						"Board %2d:  DDR2 write SUCCESS",
-						bnr ));
-			}
-			else {	
-				logMessage(cout,formatString("Board %2d: %s",bnr, getErrorStr(ack.status).c_str()));
+			if (ack.status_mask & TBB_SUCCESS) {
+				logMessage(cout,formatString(" %2d  DDR2 write TBB_SUCCESS",bnr ));
+			}	else {	
+				logMessage(cout,formatString(" %2d  %s",bnr, getDriverErrorStr(ack.status_mask).c_str()));
 			}
 		}
 	}
 	
-	logMessage(cout,formatString("=============================================================================="));
+	
 	setCmdDone(true);
 
 	return(GCFEvent::HANDLED);
@@ -814,7 +904,7 @@ GCFEvent::TResult WritewCmd::ack(GCFEvent& e)
 //---- READR -------------------------------------------------------------------
 ReadrCmd::ReadrCmd(GCFPortInterface& port) : Command(port)
 {
-	logMessage(cout,formatString("\n==== TBB-board, read register ================================================\n"));	
+	logMessage(cout,"\n==== TBB-board, read register ================================================\n");	
 }
 
 //-----------------------------------------------------------------------------
@@ -829,20 +919,18 @@ void ReadrCmd::send()
 GCFEvent::TResult ReadrCmd::ack(GCFEvent& e)
 {
 	TBBReadrackEvent ack(e);
-    
-	for (int bnr=0; bnr < getMax(); bnr++) {
+	logMessage(cout,"TBB  Info");
+	logMessage(cout,"---  -------------------------------------------------------");    
+	for (int bnr=0; bnr < getMaxSelections(); bnr++) {
 		if (isSelected(bnr) ) {
-			if (ack.status & SUCCESS) {
-				logMessage(cout,formatString(
-						"Board %2d:  read register",
-						bnr ));
-			}
-			else {	
-				logMessage(cout,formatString("Board %2d: %s",bnr, getErrorStr(ack.status).c_str()));
+			if (ack.status_mask & TBB_SUCCESS) {
+				logMessage(cout,formatString(" %2d  read register",bnr ));
+			}	else {	
+				logMessage(cout,formatString(" %2d  %s",bnr, getDriverErrorStr(ack.status_mask).c_str()));
 			}
 		}
 	}
-	logMessage(cout,formatString("=============================================================================="));
+	
 	setCmdDone(true);
 
 	return(GCFEvent::HANDLED);
@@ -851,7 +939,7 @@ GCFEvent::TResult ReadrCmd::ack(GCFEvent& e)
 //---- WRITER -------------------------------------------------------------------
 WriterCmd::WriterCmd(GCFPortInterface& port) : Command(port)
 {
-	logMessage(cout,formatString("\n==== TBB-board, write register ===============================================\n"));	
+	logMessage(cout,"\n==== TBB-board, write register ===============================================\n");	
 }
 
 //-----------------------------------------------------------------------------
@@ -866,20 +954,19 @@ void WriterCmd::send()
 GCFEvent::TResult WriterCmd::ack(GCFEvent& e)
 {
 	TBBWriterackEvent ack(e);
-    
-	for (int bnr=0; bnr < getMax(); bnr++) {
+	logMessage(cout,"TBB  Info");
+	logMessage(cout,"---  -------------------------------------------------------");    
+	for (int bnr=0; bnr < getMaxSelections(); bnr++) {
 		if (isSelected(bnr) ) {
-			if (ack.status & SUCCESS) {
-				logMessage(cout,formatString(
-						"Board %2d:  write register",
+			if (ack.status_mask & TBB_SUCCESS) {
+				logMessage(cout,formatString(" %2d  write register",
 						bnr ));
-			}
-			else {	
-				logMessage(cout,formatString("Board %2d: %s",bnr, getErrorStr(ack.status).c_str()));
+			}	else {	
+				logMessage(cout,formatString(" %2d  %s",bnr, getDriverErrorStr(ack.status_mask).c_str()));
 			}
 		}
 	}
-	logMessage(cout,formatString("=============================================================================="));
+	
 	setCmdDone(true);
 
 	return(GCFEvent::HANDLED);
@@ -887,10 +974,12 @@ GCFEvent::TResult WriterCmd::ack(GCFEvent& e)
 
 //---- READPAGE ------------------------------------------------------------------
 ReadPageCmd::ReadPageCmd(GCFPortInterface& port) : Command(port),
-	itsCmdStage(0),itsPage(0),itsMp(0),itsAddr(0),itsPages(1),itsStationId(0),itsRspId(0),itsRcuId(0),itsSampleFreq(0),
-	itsTime(0),itsSampleNr(0),itsSamplesPerFrame(0),itsFreqBands(0),itsTotalSamples(0),itsTotalBands(0)
+	itsRcu(0),itsPages(1),itsCmdStage(0),itsPage(0),itsAddr(0),itsStartAddr(0),itsSize(0),itsBoard(0),itsMp(0),
+	itsStationId(0),itsRspId(0),itsRcuId(0),itsSampleFreq(0),itsTime(0),itsSampleNr(0),itsSamplesPerFrame(0),
+	itsFreqBands(0),itsTotalSamples(0),itsTotalBands(0)
 {
-	logMessage(cout,formatString("\n==== TBB-board, readx register ================================================\n"));
+	for (int i = 0; i < 512; i++) itsData[i] = 0;
+	logMessage(cout,"\n==== TBB-board, readx register ================================================\n");
 }
 //-----------------------------------------------------------------------------
 void ReadPageCmd::send()
@@ -898,61 +987,66 @@ void ReadPageCmd::send()
 	
 	switch (itsCmdStage) {
 		case 0: {
-			TBBWriterEvent event0;
-			event0.board = (uint32)getBoard();
-			event0.mp = itsMp;
-			event0.pid = PID6;
-			event0.regid = REGID1;
-			event0.data[0] = itsAddr;
-			event0.data[1] = 0; 
-			event0.data[2] = 0;
-			itsPort.send(event0);
-			
-			LOG_DEBUG_STR(formatString("Writer[%x][%x][%x][%x]", 
-				event0.mp,event0.pid,event0.regid,event0.data[0]));
+			TBBRcuinfoEvent send;
+			itsPort.send(send);
 		} break;
 		
 		case 1: {
-			TBBWriterEvent event1;
-			event1.board = (uint32)getBoard();
-			event1.mp = itsMp;
-			event1.pid = PID6;
-			event1.regid = REGID0;
-			event1.data[0] = PAGEREAD;
-			event1.data[1] = 0; 
-			event1.data[2] = 0;
-			itsPort.send(event1);
+			TBBWriterEvent send;
+			send.board = itsBoard;
+			send.mp = itsMp;
+			send.pid = PID6;
+			send.regid = REGID1;
+			send.data[0] = itsAddr;
+			send.data[1] = 0; 
+			send.data[2] = 0;
+			itsPort.send(send);
 			
 			LOG_DEBUG_STR(formatString("Writer[%x][%x][%x][%x]", 
-				event1.mp,event1.pid,event1.regid,event1.data[0]));
+				send.mp,send.pid,send.regid,send.data[0]));
 		} break;
 		
 		case 2: {
-			TBBReadxEvent event2;
-			event2.board = (uint32)getBoard();	
-			event2.mp = itsMp;
-			event2.pid = PID6;
-			event2.regid = REGID2;
-			event2.pagelength = 256;
-			event2.pageaddr = 0;
+			TBBWriterEvent send;
+			send.board = itsBoard;
+			send.mp = itsMp;
+			send.pid = PID6;
+			send.regid = REGID0;
+			send.data[0] = PAGEREAD;
+			send.data[1] = 0; 
+			send.data[2] = 0;
+			itsPort.send(send);
 			
-			itsPort.send(event2);
-			LOG_DEBUG_STR(formatString("Readx[%x][%x][%x][%x][%x]", 
-				event2.mp,event2.pid,event2.regid,event2.pagelength,event2.pageaddr));
+			LOG_DEBUG_STR(formatString("Writer[%x][%x][%x][%x]", 
+				send.mp,send.pid,send.regid,send.data[0]));
 		} break;
 		
 		case 3: {
-			TBBReadxEvent event3;
-			event3.board = (uint32)getBoard();	
-			event3.mp = itsMp;
-			event3.pid = PID6;
-			event3.regid = REGID2;
-			event3.pagelength = 256;
-			event3.pageaddr = 256;
+			TBBReadxEvent send;
+			send.board = itsBoard;	
+			send.mp = itsMp;
+			send.pid = PID6;
+			send.regid = REGID2;
+			send.pagelength = 256;
+			send.pageaddr = 0;
+			
+			itsPort.send(send);
+			LOG_DEBUG_STR(formatString("Readx[%x][%x][%x][%x][%x]", 
+				send.mp,send.pid,send.regid,send.pagelength,send.pageaddr));
+		} break;
+		
+		case 4: {
+			TBBReadxEvent send;
+			send.board = itsBoard;	
+			send.mp = itsMp;
+			send.pid = PID6;
+			send.regid = REGID2;
+			send.pagelength = 256;
+			send.pageaddr = 256;
 			
-			itsPort.send(event3);
+			itsPort.send(send);
 			LOG_DEBUG_STR(formatString("Readx[%x][%x][%x][%x][%x]", 
-				event3.mp,event3.pid,event3.regid,event3.pagelength,event3.pageaddr));
+				send.mp,send.pid,send.regid,send.pagelength,send.pageaddr));
 		} break;
 		
 		default:{
@@ -963,41 +1057,60 @@ void ReadPageCmd::send()
 //-----------------------------------------------------------------------------
 GCFEvent::TResult ReadPageCmd::ack(GCFEvent& e)
 {
-	uint errorMask = 0;
 	int16 val[1400];
 		
 	switch (itsCmdStage) {
 		case 0: {
-			TBBWriterackEvent ack(e);
-			if (!(ack.status & SUCCESS)) {
-				logMessage(cout,formatString("%s",getErrorStr(ack.status).c_str()));
+			int rcu;
+			rcu = getRcu();
+			TBBRcuinfoackEvent ack(e);
+			itsState = ack.rcu_state[rcu];
+			itsStartAddr = ack.rcu_start_addr[rcu];
+			itsSize = ack.rcu_pages[rcu];
+			itsBoard = ack.rcu_on_board[rcu];
+			itsMp = (int32)((int32)ack.rcu_on_input[rcu] / 4);
+			logMessage(cout,formatString("Rcu-%d Board[%d] Mp[%d]",rcu,itsBoard,itsMp));
+			
+			itsAddr = itsStartAddr;
+			if (itsState == 'F') {
+				logMessage(cout,"Rcu not allocated");
 				itsCmdStage = 10;
 			}
 		} break;
-		
+				
 		case 1: {
 			TBBWriterackEvent ack(e);
-			if (!(ack.status & SUCCESS)) {
-				logMessage(cout,formatString("%s",getErrorStr(ack.status).c_str()));
+			if (!(ack.status_mask & TBB_SUCCESS)) {
+				logMessage(cout,formatString("%s",getDriverErrorStr(ack.status_mask).c_str()));
 				itsCmdStage = 10;
 			}
 		} break;
 		
 		case 2: {
+			TBBWriterackEvent ack(e);
+			if (!(ack.status_mask & TBB_SUCCESS)) {
+				logMessage(cout,formatString("%s",getDriverErrorStr(ack.status_mask).c_str()));
+				itsCmdStage = 10;
+			}
+		} break;
+		
+		case 3: {
 			TBBReadxackEvent ack(e);
-			if (!(ack.status & SUCCESS)) {
-				logMessage(cout,formatString("%s", getErrorStr(ack.status).c_str()));
+			if (!(ack.status_mask & TBB_SUCCESS)) {
+				logMessage(cout,formatString("%s", getDriverErrorStr(ack.status_mask).c_str()));
 				itsCmdStage = 10;
 		  }
+		  
+		  // memcpy(itsData, ack.pagedata, sizeof(ack.pagedata));
 			for (int32 dn = 0; dn < 256; dn++) { 
 				itsData[dn] = ack.pagedata[dn];
 			}
 		} break;
 		
-		case 3: {
+		case 4: {
 			TBBReadxackEvent ack(e);
-			if (!(ack.status & SUCCESS)) {
-				logMessage(cout,formatString("%s", getErrorStr(ack.status).c_str()));
+			if (!(ack.status_mask & TBB_SUCCESS)) {
+				logMessage(cout,formatString("%s", getDriverErrorStr(ack.status_mask).c_str()));
 				itsCmdStage = 10;
 		  }
 			for (int32 dn = 0; dn < 256; dn++) { 
@@ -1013,132 +1126,139 @@ GCFEvent::TResult ReadPageCmd::ack(GCFEvent& e)
 	}
 	
 	itsCmdStage++;
-	if (itsCmdStage < 4) {
+	if (itsCmdStage < 5) {
 		itsPort.setTimer(0.01);
-	}
-	else { 
-		//logMessage(cout,formatString("=============================================================================="));
+	} else { 
+		
 				
 		if (itsPage == 0) {
 			itsStationId = (int)(itsData[0] & 0xFF);
 			itsRspId = (int)((itsData[0] >> 8) & 0xFF);
 			itsRcuId = (int)((itsData[0] >> 16) & 0xFF);
 			itsSampleFreq = (int)((itsData[0] >> 24) & 0xFF);
-			itsTime = (time_t)itsData[2];
+			itsTime = (time_t)itsData[2]-1;
 			itsSampleNr = (int)itsData[3];
 		}
 		itsSamplesPerFrame = (int)(itsData[4] & 0xFFFF);
 		itsFreqBands = (int)((itsData[4] >> 16) & 0xFFFF);
-		itsTotalSamples += itsSamplesPerFrame;
-		itsTotalBands += itsFreqBands; 
-		
-				
+						
 		int sample_cnt = 0;
 		int val_cnt = 0;
 		int data_cnt = 22; // 22 = startadress of data in frame
-				
+		
+		
 		if (itsFreqBands > 0) {
 			// its SPECTRAL data
-
-			// convert uint32 to complex int16
-			while (sample_cnt < itsSamplesPerFrame) {
-				// get complex sample
-				val[val_cnt++] = (int16) (itsData[data_cnt] & 0xFFFF);	// re part
-				val[val_cnt++] = (int16)((itsData[data_cnt++] >> 16) & 0xFFFF);	// im part
-				sample_cnt++;
+			if (itsSamplesPerFrame < 975) {		
+				itsTotalSamples += itsSamplesPerFrame;
+				itsTotalBands += itsFreqBands;
+				logMessage(cout,formatString("Samples[%d] Bands[%d]",itsTotalSamples,itsTotalBands));
+				// convert uint32 to complex int16
+				while (sample_cnt < itsSamplesPerFrame) {
+					// get complex sample
+					val[val_cnt++] = (int16) (itsData[data_cnt] & 0xFFFF);	// re part
+					val[val_cnt++] = (int16)((itsData[data_cnt++] >> 16) & 0xFFFF);	// im part
+					sample_cnt++;
+				}
 			}
-		}
-		else {
+		}	else {
 			// its RAW data
-
-			// convert uint32 to int12
-			uint32 data[3];
-			while (sample_cnt < itsSamplesPerFrame) {
-				// get 96 bits from received data
-				data[0] = itsData[data_cnt++];
-				data[1] = itsData[data_cnt++];
-				data[2] = itsData[data_cnt++];
+			if (itsSamplesPerFrame < 1299) {		
+				itsTotalSamples += itsSamplesPerFrame;
+				itsTotalBands += itsFreqBands;
+				logMessage(cout,formatString("Samples[%d] Bands[%d]",itsTotalSamples,itsTotalBands));
+				// convert uint32 to int12
+				uint32 data[3];
 				
-				// extract 8 values of 12 bit
-				val[val_cnt++] = (int16)  (data[0] & 0x00000FFF);
-				val[val_cnt++] = (int16) ((data[0] & 0x00FFF000) >> 12);
-				val[val_cnt++] = (int16)(((data[0] & 0xFF000000) >> 24) | ((data[1] & 0x0000000F) << 8));
-				val[val_cnt++] = (int16) ((data[1] & 0x0000FFF0) >> 4 );
-				val[val_cnt++] = (int16) ((data[1] & 0x0FFF0000) >> 16);
-				val[val_cnt++] = (int16)(((data[1] & 0xF0000000) >> 28) | ((data[2] & 0x000000FF) << 4));
-				val[val_cnt++] = (int16) ((data[2] & 0x000FFF00) >> 8);
-				val[val_cnt++] = (int16) ((data[2] & 0xFFF00000) >> 20);
+				while (sample_cnt < itsSamplesPerFrame) {
+					// get 96 bits from received data
+					data[0] = itsData[data_cnt++];
+					data[1] = itsData[data_cnt++];
+					data[2] = itsData[data_cnt++];
+					
+					// extract 8 values of 12 bit
+					val[val_cnt++] = (int16)  (data[0] & 0x00000FFF);
+					val[val_cnt++] = (int16) ((data[0] & 0x00FFF000) >> 12);
+					val[val_cnt++] = (int16)(((data[0] & 0xFF000000) >> 24) | ((data[1] & 0x0000000F) << 8));
+					val[val_cnt++] = (int16) ((data[1] & 0x0000FFF0) >> 4 );
+					val[val_cnt++] = (int16) ((data[1] & 0x0FFF0000) >> 16);
+					val[val_cnt++] = (int16)(((data[1] & 0xF0000000) >> 28) | ((data[2] & 0x000000FF) << 4));
+					val[val_cnt++] = (int16) ((data[2] & 0x000FFF00) >> 8);
+					val[val_cnt++] = (int16) ((data[2] & 0xFFF00000) >> 20);
+					
+					sample_cnt += 8;
+				}
 				
-				sample_cnt += 8;
-			}
-			
-			// convert all received samples from signed 12bit to signed 16bit
-			for (int cnt = 0; cnt < val_cnt; cnt++) {
-				if (val[cnt] & 0x0800) val[cnt] |= 0xF000;
+				// convert all received samples from signed 12bit to signed 16bit
+				for (int cnt = 0; cnt < val_cnt; cnt++) {
+					if (val[cnt] & 0x0800) val[cnt] |= 0xF000;
+				}
 			}
 		}
-		
-		// write all data to file
-		FILE* file;
-		char line[10][256];
-		char basefilename[PATH_MAX];
-		char filename[PATH_MAX];
-		char timestring[256];
-		
-		strftime(timestring, 255, "%Y%m%d_%H%M%S", gmtime(&itsTime));
-		snprintf(basefilename, PATH_MAX, "%s_%02d%02d", timestring,itsStationId,itsRcuId);
-		
-		snprintf(filename, PATH_MAX, "%s.dat",basefilename);
-		file = fopen(filename,"a");
-		fwrite(val,sizeof(int16),val_cnt,file);
-		fclose(file);
-		
-		itsPage++;
-		if ((itsCmdStage == 4) && (itsPage < itsPages)) {
-			itsCmdStage = 0;
-			itsAddr++;
-			itsPort.setTimer(0.01);
-		}
-		else {
-			// print page information
-			strftime(timestring, 255, "%Y-%m-%d  %H:%M:%S", gmtime(&itsTime));
-			
-			sprintf(line[0],"Station ID      : %d",itsStationId);
-			sprintf(line[1],"RSP ID          : %d",itsRspId);
-			sprintf(line[2],"RCU ID          : %d",itsRcuId);
-			sprintf(line[3],"Sample freq     : %d MHz",itsSampleFreq);
-			if (itsTime < 0)
-				sprintf(line[4],"Time            : invalid");
-			else
-				sprintf(line[4],"Time            : %s",timestring);
-			sprintf(line[5],"SampleNr        : %u",itsSampleNr);
-			if (itsTotalBands) {
-				sprintf(line[6],"FreqBands       : %u",itsTotalBands);
-				sprintf(line[7],"Data file format: binary complex(int16 Re, int16 Im)");
-			}
-			else	 {
-				sprintf(line[6],"Samples         : %u",itsTotalSamples);
-				sprintf(line[7],"Data file format: binary  int16");
-			}
-			sprintf(line[8],"Filename        : %s.nfo",basefilename);
-			sprintf(line[9],"                : %s.dat",basefilename);
-						
-			snprintf(filename, PATH_MAX, "%s.nfo",basefilename);
-			file = fopen(filename,"w");		
-									
-			for (int32 lnr = 0;lnr < 10; lnr++) {
-				logMessage(cout,line[lnr]);
-				fprintf(file,line[lnr]);
-				fprintf(file,"\n");
-			}
-			
+		if (val_cnt > 0) {
+			// write all data to file
+			FILE* file;
+			char line[10][256];
+			char basefilename[PATH_MAX];
+			char filename[PATH_MAX];
+			char timestring[256];
 			
-			logMessage(cout,formatString("=============================================================================="));
+			strftime(timestring, 255, "%Y%m%d_%H%M%S", gmtime(&itsTime));
+			snprintf(basefilename, PATH_MAX, "%s_%02d%02d", timestring,itsStationId,itsRcuId);
 			
+			snprintf(filename, PATH_MAX, "%s.dat",basefilename);
+			file = fopen(filename,"a");
+			fwrite(val,sizeof(int16),val_cnt,file);
 			fclose(file);
-			setCmdDone(true);
-		}                                                                                               
+			
+			itsPage++;
+			if (itsPage < itsPages) {
+				itsCmdStage = 1;
+				itsAddr = itsStartAddr + itsPage;
+				itsPort.setTimer(0.05);
+			}	else {
+				// print page information
+				strftime(timestring, 255, "%Y-%m-%d  %H:%M:%S", gmtime(&itsTime));
+				
+				sprintf(line[0],"Station ID      : %d",itsStationId);
+				sprintf(line[1],"RSP ID          : %d",itsRspId);
+				sprintf(line[2],"RCU ID          : %d",itsRcuId);
+				sprintf(line[3],"Sample freq     : %d MHz",itsSampleFreq);
+				if (itsTime < 0) {
+					sprintf(line[4],"Time            : invalid");
+				} else {
+					sprintf(line[4],"Time            : %s (%u)",timestring,(uint32)itsTime);
+				}
+				sprintf(line[5],"SampleNr        : %u",itsSampleNr);
+				if (itsTotalBands) {
+					sprintf(line[6],"FreqBands       : %u",itsTotalBands);
+					sprintf(line[7],"Data file format: binary complex(int16 Re, int16 Im)");
+				}	else {
+					sprintf(line[6],"Samples         : %u",itsTotalSamples);
+					sprintf(line[7],"Data file format: binary  int16");
+				}
+				sprintf(line[8],"Filename        : %s.nfo",basefilename);
+				sprintf(line[9],"                : %s.dat",basefilename);
+							
+				snprintf(filename, PATH_MAX, "%s.nfo",basefilename);
+				file = fopen(filename,"w");		
+										
+				for (int32 lnr = 0;lnr < 10; lnr++) {
+					logMessage(cout,line[lnr]);
+					fprintf(file,line[lnr]);
+					fprintf(file,"\n");
+				}
+				fclose(file);	
+			}
+		}	else {
+			logMessage(cout,"No data in Frame");
+		}
 	}
+	if (itsPage == itsPages) {
+		
+		setCmdDone(true);
+	}
+
 	return(GCFEvent::HANDLED);
 }
 
@@ -1148,32 +1268,38 @@ GCFEvent::TResult ReadPageCmd::ack(GCFEvent& e)
 //---- HELP --------------------------------------------------------------------
 void TBBCtl::help()
 {
-	logMessage(cout,"\n==== tbbctl command usage ===================================================================\n");
+	logMessage(cout,"\n==== tbbctl command usage =========================================================================================\n");
 	
-	logMessage(cout,"# --command          : all boards or channels are selected, and will be displayed");
-	logMessage(cout,"# --command --select : information for all selected boards is displayed\n"
+	logMessage(cout,"#  --command                : all boards or active rcu's are selected, and will be displayed");
+	logMessage(cout,"#  --command --select=<set> : only information for all selected boards or rcu's is displayed\n"
 									"#    Example: --select=0,1,4  or  --select=0:6  or  --select=0,1,2,8:11\n");
-	logMessage(cout,"tbbctl --alloc [--select=]                  # allocate memmory locations for selected channels");
-	logMessage(cout,"tbbctl --free [--select=]                   # free memmory locationsfor selected channels");
-	logMessage(cout,"tbbctl --record [--select=]                 # start recording on selected channels");
-	logMessage(cout,"tbbctl --stop [--select=]                   # stop recording on all selected channels");
-	logMessage(cout,"tbbctl --trigclr=channel                    # clear tigger message for all selected channel");
-	//logMessage(cout,"tbbctl --read=channel                       # transfer recorded data to CEP");
-	logMessage(cout,"tbbctl --udp [--select=]                    # configure UDP/IP header for Data transport to CEP");
-	logMessage(cout,"tbbctl --version [--select=]                # get version information");
-	logMessage(cout,"tbbctl --status [--select=]                 # get board status");	
-	logMessage(cout,"tbbctl --size [--select=]                   # get installed memory size");
-	//logMessage(cout,"tbbctl --eraseflash=addr                    # erase flash page starting on addr");
-	//logMessage(cout,"tbbctl --readflash=addr                     # read flash page starting on addr");
-	//logMessage(cout,"tbbctl --writeflash=addr                    # write flash page starting on addr");
-	logMessage(cout,"tbbctl --readddr=board,mp,addr,size         # read 2 words from DDR2 memory");
-	logMessage(cout,"tbbctl --writeddr=board,mp,addr,wordL,wordH # write 2 words to DDR2 memory at addr");
-	logMessage(cout,"tbbctl --readpage=board,mp,addr,pages       # read n pages from DDR2 memory starting at addr");
-	logMessage(cout,"tbbctl --clear [--select=]                  # clear board");
-	logMessage(cout,"tbbctl --reset [--select=]                  # reset factory images");
-	logMessage(cout,"tbbctl --config=imagenr [--select=]         # reconfigure TP and MP's with imagenr [0 .. 31]");
-	logMessage(cout,"tbbctl --help                               # this help screen");
-	logMessage(cout,"=============================================================================================");
+	logMessage(cout,"tbbctl --alloc [--select=<set>]                                    # allocate memmory locations for selected rcu's");
+	logMessage(cout,"tbbctl --free [--select=<set>]                                     # free memmory locationsfor selected rcu's");
+	logMessage(cout,"tbbctl --record [--select=<set>]                                   # start recording on selected rcu's");
+	logMessage(cout,"tbbctl --stop [--select=<set>]                                     # stop recording on all selected rcu's");
+	logMessage(cout,"tbbctl --rcuinfo [--select=<set>]                                  # list rcu info for all allocated rcu's\n");
+	
+	logMessage(cout,"tbbctl --trigclr=channel                                           # clear tigger message for all selected channel");
+	logMessage(cout,"tbbctl --read=rcunr,secondstime,sampletime,prepages,postpages      # transfer recorded data from rcunr to CEP");
+	logMessage(cout,"tbbctl --mode=board,[transient | subbands]                         # set mode to configure UDP/IP header for CEP"); 
+	logMessage(cout,"tbbctl --version [--select=<set>]                                  # get version information from selected boards");
+	logMessage(cout,"tbbctl --status [--select=<set>]                                   # get status information from selected boards");	
+	logMessage(cout,"tbbctl --size [--select=<set>]                                     # get installed memory size from selected boards\n");
+	
+	logMessage(cout,"tbbctl --eraseimage=board,image                                    # erase image from flash");
+	logMessage(cout,"tbbctl --readimage=board,image                                     # read image from flash to file");
+	logMessage(cout,"tbbctl --writeimage=boardnr,imagenr,version,tpfilename,mpfilename  # write tp and mp file to imagenr on boardnr");
+	logMessage(cout,"                                                                   # version is the version of the image stored");
+	logMessage(cout,"tbbctl --imageinfo=board                                           # read info from all images on board");
+	logMessage(cout,"tbbctl --readddr=board,mp,addr,size                                # read 2 words from DDR2 memory");
+	logMessage(cout,"tbbctl --writeddr=board,mp,addr,wordL,wordH                        # write 2 words to DDR2 memory at addr");
+	logMessage(cout,"tbbctl --readpage=board,mp,addr,pages                              # read n pages from DDR2 memory starting at addr");
+	logMessage(cout,"tbbctl --clear [--select=<set>]                                    # clear selected board");
+	logMessage(cout,"tbbctl --reset [--select=<set>]                                    # reset to factory images on selected boards");
+	logMessage(cout,"tbbctl --config=imagenr [--select=<set>]                           # reconfigure TP and MP's with imagenr [0..31] on ");
+	logMessage(cout,"                                                                   # selected boards");
+	logMessage(cout,"tbbctl --help                                                      # this help screen\n");
+	logMessage(cout,"===================================================================================================================");
 }
 //-----------------------------------------------------------------------------
 
@@ -1224,7 +1350,7 @@ GCFEvent::TResult TBBCtl::initial(GCFEvent& e, GCFPortInterface& port)
     case TBB_GETCONFIGACK: {
       TBBGetconfigackEvent ack(e);
       itsMaxBoards		= ack.max_boards;
-      itsActiveBoards	= ack.active_boards;
+      itsActiveBoards	= ack.active_boards_mask;
 			itsMaxChannels = itsMaxBoards * 16;
       //logMessage(cout,formatString("\nMax nr of TBB boards = %d",itsMaxBoards));
 			//logMessage(cout,formatString("Max nr of Channels   = %d\n",itsMaxChannels));
@@ -1288,22 +1414,23 @@ GCFEvent::TResult TBBCtl::docommand(GCFEvent& e, GCFPortInterface& port)
 		} break;
     
     case TBB_ALLOCACK:
-    case TBB_CHANNELINFOACK:
+    case TBB_RCUINFOACK:
     case TBB_FREEACK:
     case TBB_RECORDACK:
     case TBB_STOPACK:
     case TBB_TRIGCLRACK:
     case TBB_READACK:
-    case TBB_UDPACK:
+    case TBB_MODEACK:
     case TBB_VERSIONACK:
     case TBB_SIZEACK:
     case TBB_STATUSACK: 
     case TBB_CLEARACK:
     case TBB_RESETACK:
     case TBB_CONFIGACK:
-    case TBB_ERASEFACK:
-    case TBB_READFACK:
-    case TBB_WRITEFACK:
+    case TBB_ERASE_IMAGE_ACK:
+    case TBB_READ_IMAGE_ACK:
+    case TBB_WRITE_IMAGE_ACK:
+		case TBB_IMAGE_INFO_ACK:
     case TBB_READWACK:
     case TBB_WRITEWACK:
     case TBB_READRACK:
@@ -1313,9 +1440,6 @@ GCFEvent::TResult TBBCtl::docommand(GCFEvent& e, GCFPortInterface& port)
     	if (itsCommand->isCmdDone()) {
     		GCFTask::stop();
     	}
-    	//else {
-    	//	port.setTimer(0.02);	
-    	//}
     } break;
 
     default: {
@@ -1332,7 +1456,7 @@ GCFEvent::TResult TBBCtl::docommand(GCFEvent& e, GCFPortInterface& port)
 Command* TBBCtl::parse_options(int argc, char** argv)
 {
   Command*	command = 0;
-  list<int> select;
+  std::list<int> select;
   
   optind = 0; // reset option parsing
   //opterr = 0; // no error reporting to stderr
@@ -1341,13 +1465,13 @@ Command* TBBCtl::parse_options(int argc, char** argv)
   	static struct option long_options[] = {
 			{ "select",			required_argument,	0,	'l' }, //ok
 			{ "alloc",			no_argument,				0,	'a' }, //ok ??
-			{ "channelinfo",no_argument,				0,	'i' }, //ok ??
+			{ "rcuinfo",		no_argument,				0,	'i' }, //ok ??
 			{ "free",				no_argument,				0,	'f' }, //ok ??
 		  { "record",			no_argument,				0,	'r' }, //ok ??
 		  { "stop",				no_argument,				0,	's' }, //ok ??
 		  { "trigclr",		required_argument,	0,	't' }, //ok ??
 			{ "read",				required_argument,	0,	'R' }, //ok ??
-			{ "udp",				required_argument,	0,	'u' }, //ok ??
+			{ "mode",				required_argument,	0,	'm' }, //ok ??
 			{ "version",		no_argument,				0,	'v' }, //ok
 			{ "size",				no_argument,				0,	'z' }, //ok
 			{ "status",			no_argument,				0,	'A' }, //ok
@@ -1355,9 +1479,10 @@ Command* TBBCtl::parse_options(int argc, char** argv)
 			{ "clear",			no_argument,				0,	'C' }, //ok ??
 			{ "reset",			no_argument,				0,	'Z' }, //ok ??
 			{ "config",			required_argument,	0,	'S' }, //ok ??
-		  { "eraseflash",	required_argument,	0,	'1' }, //ok
-		  { "readflash",	required_argument,	0,	'2' }, //ok
-		  { "writeflash",	required_argument,	0,	'3' }, //ok
+		  { "eraseimage",	required_argument,	0,	'1' }, //ok
+		  { "readimage",	required_argument,	0,	'2' }, //ok
+		  { "writeimage",	required_argument,	0,	'3' }, //ok
+			{ "imageinfo",	required_argument,	0,	'8' }, //ok
 		  { "readddr",		required_argument,	0,	'4' }, //ok
 		  { "writeddr",		required_argument,	0,	'5' }, //ok
 		  { "readreg",		required_argument,	0,	'6' }, //ok not in help
@@ -1368,7 +1493,7 @@ Command* TBBCtl::parse_options(int argc, char** argv)
 
     int option_index = 0;
     int c = getopt_long(argc, argv,
-				"l:afrst:R:u:vzAp:CZS:1:2:3:4:5:6:7:h",
+												"l:afrst:R:m:vzAp:CZS:1:2:3:8:4:5:6:7:h",
 				long_options, &option_index);
 
     if (c == -1)
@@ -1383,58 +1508,56 @@ Command* TBBCtl::parse_options(int argc, char** argv)
   		  			logMessage(cerr,"Error: 'command' argument should come before --select argument");
   		  			exit(EXIT_FAILURE);
   					}
-  					select = strtolist(optarg, command->getMax());
+  					select = strtolist(optarg, command->getMaxSelections());
   											
   	      	if (select.empty()) {
   		  			logMessage(cerr,"Error: invalid or missing '--select' option");
   		  			exit(EXIT_FAILURE);
-  					}
-  					else {
+  					}	else {
   						command->setSelected(true);
   					}
-  	    	}
-  	  		else {
+  	    	}	else {
   	      	logMessage(cerr,"Error: option '--select' requires an argument");
   	      	exit(EXIT_FAILURE);
   	      }
-	      }
-	      else
+				} else {
 	      	logMessage(cerr,"Error: channels already selected");
+				}
 	    } break;
 	    
 	    case 'a': { 	// --alloc
 				if (command) delete command;
 				AllocCmd* alloccmd = new AllocCmd(itsServerPort);
 				command = alloccmd;
-				command->setMax(itsMaxChannels);
+				command->setCmdType(RCUCMD);
 			}	break;
 			
 			case 'i': { 	// --channelinfo
 				if (command) delete command;
 				ChannelInfoCmd* channelinfocmd = new ChannelInfoCmd(itsServerPort);
 				command = channelinfocmd;
-				command->setMax(itsMaxChannels);
+				command->setCmdType(RCUCMD);
 			}	break;
 			
 			case 'f': { 	// --free
 				if (command) delete command;
 				FreeCmd* freecmd = new FreeCmd(itsServerPort);
 				command = freecmd;
-				command->setMax(itsMaxChannels);
+				command->setCmdType(RCUCMD);
 			}	break;
 			
 			case 'r': { 	// --record
 				if (command) delete command;
 				RecordCmd* recordcmd = new RecordCmd(itsServerPort);
 				command = recordcmd;
-				command->setMax(itsMaxChannels);
+				command->setCmdType(RCUCMD);
 			}	break;
 			
 			case 's': { 	// --stop
 				if (command) delete command;
 				StopCmd* stopcmd = new StopCmd(itsServerPort);
 				command = stopcmd;
-				command->setMax(itsMaxChannels);
+				command->setCmdType(RCUCMD);
 			}	break;
 			
 			case 't': { 	// --trigclear
@@ -1446,7 +1569,7 @@ Command* TBBCtl::parse_options(int argc, char** argv)
 					int numitems = sscanf(optarg, "%d",&channel);
 					if (numitems == 0 || numitems == EOF) {
 						logMessage(cerr,"Error: invalid number of arguments. Should be of the format "
-								"'--trigclr=channel]' ");  
+								"'--trigclr=rcu' ");  
 						exit(EXIT_FAILURE);
 					}
 					select.clear();
@@ -1454,68 +1577,99 @@ Command* TBBCtl::parse_options(int argc, char** argv)
 					command->setSelected(true);
 				}
 				
-				command->setMax(itsMaxChannels);
+				command->setCmdType(RCUCMD);
 			}	break;
 			
 			case 'R': { 	// --read
 				if (command) delete command;
 				ReadCmd* readcmd = new ReadCmd(itsServerPort);
 				command = readcmd;
-				command->setMax(itsMaxChannels);
+				
+				if (optarg) {
+					int channel = 0;
+					uint32 secondstime = 0;
+					uint32 sampletime = 0;
+					uint32 prepages = 0;
+					uint32 postpages = 0;
+					int numitems = sscanf(optarg, "%d,%u,%u,%u,%u",
+						&channel, &secondstime, &sampletime, &prepages, &postpages);
+					if (numitems < 5 || numitems == EOF) {
+						logMessage(cerr,"Error: invalid number of arguments. Should be of the format "
+								"'--read=rcu,secondstime,sampletime,prepages,postpages' ");  
+						exit(EXIT_FAILURE);
+					}
+					readcmd->setSecondsTime(secondstime);
+					readcmd->setSampleTime(sampletime);
+					readcmd->setPrePages(prepages);
+					readcmd->setPostPages(postpages);
+					
+					select.clear();
+		  		select.push_back(channel);
+					command->setSelected(true);
+				}
+				command->setCmdType(RCUCMD);
 			}	break;
 			
-			case 'u': { 	// --udp
+			case 'm': { 	// --mode
 				if (command) delete command;
-				UdpCmd* udpcmd = new UdpCmd(itsServerPort);
-				command = udpcmd;
-				/*
+				ModeCmd* modecmd = new ModeCmd(itsServerPort);
+				command = modecmd;
 				if (optarg) {
-					uint32 imagenr = 0;
-					int numitems = sscanf(optarg, "%u", &imagenr);
-					if (numitems == 0 || numitems == EOF || imagenr < 0 || imagenr > 31) {
-						logMessage(cerr,"Error: invalid image value. Should be of the format "
-								"'--config=value' where value is a int value in the range [0,10].");  //TODO value range
+					int board = 0;
+					char rec_mode[64];
+					int numitems = sscanf(optarg, "%d,%s",
+						&board, rec_mode);
+					if (numitems < 2 || numitems == EOF) {
+						logMessage(cerr,"Error: invalid number of arguments. Should be of the format "
+								"'--udp=board,rec_mode' ");  
 						exit(EXIT_FAILURE);
 					}
-					udpcmd->setImage(imagenr);
+					
+					if (strcmp(rec_mode,"transient") == 0)
+						modecmd->setRecMode(TBB_MODE_TRANSIENT);
+					if (strcmp(rec_mode,"subbands") == 0)
+						modecmd->setRecMode(TBB_MODE_SUBBANDS);
+							
+					select.clear();
+		  		select.push_back(board);
+					command->setSelected(true);
 				}
-				*/
-				command->setMax(itsMaxChannels);
+				command->setCmdType(BOARDCMD);
 			}	break;									
 						
 			case 'v': { 	// --version
 	  		if (command) delete command;
 	    	VersionCmd* versioncmd = new VersionCmd(itsServerPort);
 	  		command = versioncmd;
-				command->setMax(itsMaxBoards);
+				command->setCmdType(BOARDCMD);
 	  	}	break;	
 	  	
 	  	case 'z': { 	// --size
 	  		if (command) delete command;
 	    	SizeCmd* sizecmd = new SizeCmd(itsServerPort);
 	  		command = sizecmd;
-				command->setMax(itsMaxBoards);
+				command->setCmdType(BOARDCMD);
 	  	}	break;
 	  	
 	  	case 'A': { 	// --status
 	  		if (command) delete command;
 	    	StatusCmd* statuscmd = new StatusCmd(itsServerPort);
 	  		command = statuscmd;
-				command->setMax(itsMaxBoards);
+				command->setCmdType(BOARDCMD);
 	  	}	break;
 			
 			case 'C': { 	// --clear
 				if (command) delete command;
 				ClearCmd* clearcmd = new ClearCmd(itsServerPort);
 				command = clearcmd;
-				command->setMax(itsMaxBoards);
+				command->setCmdType(BOARDCMD);
 			}	break;
 			
 			case 'Z': { 	// --reset
 				if (command) delete command;
 				ResetCmd* resetcmd = new ResetCmd(itsServerPort);
 				command = resetcmd;
-				command->setMax(itsMaxBoards);
+				command->setCmdType(BOARDCMD);
 			}	break;
 			
 			case 'S': { 	// --config
@@ -1533,7 +1687,7 @@ Command* TBBCtl::parse_options(int argc, char** argv)
 					}
 					configcmd->setImage((uint32)imagenr);
 				}
-				command->setMax(itsMaxBoards);
+				command->setCmdType(BOARDCMD);
 			}	break;
 			
 			case 'p': { 	// --readpage
@@ -1542,61 +1696,135 @@ Command* TBBCtl::parse_options(int argc, char** argv)
 				command = readddrcmd;
 				
 				if (optarg) {
-					int32 board = 0;
-					uint32 mp = 0;
-					uint32 addr = 0;
+					int32 rcu = 0;
 					uint32 pages = 0;
 					
-					int numitems = sscanf(optarg, "%d,%u,%u,%u", &board,&mp,&addr,&pages);
+					int numitems = sscanf(optarg, "%d,%u", &rcu,&pages);
 					
-					if (numitems < 3 || numitems == EOF || board < 0 || board > 11 || mp > 3) {
+					if (numitems < 2 || numitems == EOF || rcu < 0 || rcu >= MAX_N_RCUS) {
 						logMessage(cerr,"Error: invalid read ddr value. Should be of the format "
-								"'--readw=board,mp,addr' where board= 0..11, mp= 0..3 and addr= 0x..");  
+								"'--readw=board,mp,addr' where rcu= 0..191");  
 						exit(EXIT_FAILURE);
 					}
-					readddrcmd->setMp(mp);
-					readddrcmd->setAddr(addr);
 					readddrcmd->setPages(pages);
 					select.clear();
-		  		select.push_back(board);
+		  		select.push_back(rcu);
 		  		command->setSelected(true);
-				}
-				else {
+				}	else {
 					logMessage(cerr,"Error: invalid read ddr value. Should be of the format "
 								"'--readw=board,mp,addr' where board= 0..11, mp= 0..3 and addr= 0x..");  
 						exit(EXIT_FAILURE);
 				}
-				command->setMax(itsMaxBoards);
+				command->setCmdType(BOARDCMD);
 			}	break;			
 						
 			case '1': { 	// --erasef
 				if (command) delete command;
 				ErasefCmd* erasefcmd = new ErasefCmd(itsServerPort);
 				command = erasefcmd;
-				command->setMax(itsMaxBoards);
+				if (optarg) {
+					int board = 0;
+					int page = 0;
+					int numitems = sscanf(optarg, "%d,%d", &board, &page);
+					
+					if (numitems < 2 || numitems == EOF 
+							|| page < 0 || page >= FL_N_PAGES 
+							|| board < 0 || board >= MAX_N_TBBBOARDS) {
+						logMessage(cerr,"Error: invalid page value. Should be of the format "
+								"'--eraseimage=board,page' where board= 0 .. 11, image= 0..31");  
+						exit(EXIT_FAILURE);
+					}
+					erasefcmd->setPage(page);
+					select.clear();
+					select.push_back(board);
+					command->setSelected(true);
+				}
+				command->setCmdType(BOARDCMD);
 			}	break;
 			
 			case '2': { 	// --readf
 				if (command) delete command;
 				ReadfCmd* readfcmd = new ReadfCmd(itsServerPort);
 				command = readfcmd;
-				command->setMax(itsMaxBoards);
+				if (optarg) {
+					int board = 0;
+					int page = 0;
+					int numitems = sscanf(optarg, "%d,%d", &board, &page);
+					
+					if (numitems < 2 || numitems == EOF 
+							|| page < 0 || page >= FL_N_PAGES 
+							|| board < 0 || board >= MAX_N_TBBBOARDS) {
+						logMessage(cerr,"Error: invalid page value. Should be of the format "
+								"'--readimage=board,page' where board= 0 .. 11, image= 0..31");  
+						exit(EXIT_FAILURE);
+					}
+					readfcmd->setPage(page);
+					select.clear();
+					select.push_back(board);
+					command->setSelected(true);
+				}
+				command->setCmdType(BOARDCMD);
 			}	break;
 			
 			case '3': { 	// --writef
 				if (command) delete command;
 				WritefCmd* writefcmd = new WritefCmd(itsServerPort);
 				command = writefcmd;
-				command->setMax(itsMaxBoards);
+				if (optarg) {
+					int board = 0;
+					int page = 0;
+					double version = 0;
+					char filename_tp[64];
+					char filename_mp[64];
+					memset(filename_tp,0,64);
+					memset(filename_mp,0,64);
+					
+					int numitems = sscanf(optarg, "%d,%d,%lf,%63[^,],%63[^,]", &board, &page, &version, filename_tp, filename_mp);
+					if (numitems < 5 || numitems == EOF 
+							|| page < 0 || page >= FL_N_PAGES 
+							|| board < 0 || board >= MAX_N_TBBBOARDS) {
+						logMessage(cerr,"Error: invalid values. Should be of the format "
+								"'--writeimage=board,page,filename tp,filename mp' where board= 0 .. 11, image= 0..31");  
+						exit(EXIT_FAILURE);
+					}
+					writefcmd->setPage(page);
+					writefcmd->setVersion(version);
+					writefcmd->setFileNameTp(filename_tp);
+					writefcmd->setFileNameMp(filename_mp);
+
+					select.clear();
+					select.push_back(board);
+					command->setSelected(true);
+				}
+				command->setCmdType(BOARDCMD);
 			}	break;
 			
+			case '8': { // --imageinfo
+				if (command) delete command;
+				ImageInfoCmd* imageinfocmd = new ImageInfoCmd(itsServerPort);
+				command = imageinfocmd;
+				if (optarg) {
+					int board = 0;
+					int numitems = sscanf(optarg, "%d", &board);
+					if (numitems < 1 || numitems == EOF || board < 0 || board >= MAX_N_TBBBOARDS) {
+						logMessage(cerr,"Error: invalid values. Should be of the format "
+								"'--imageinfo=board' where board= 0 .. 11");  
+						exit(EXIT_FAILURE);
+					}
+					select.clear();
+					select.push_back(board);
+					command->setSelected(true);
+				}
+				command->setCmdType(BOARDCMD);
+			} break;
+			
 			case '4': { 	// --readw
 				if (command) delete command;
 				ReadwCmd* readwcmd = new ReadwCmd(itsServerPort);
 				command = readwcmd;
 				
 				if (optarg) {
-					int32 board = 0;
+					int board = 0;
 					uint32 mp = 0;
 					uint32 startaddr = 0;
 					uint32 size = 0;
@@ -1614,13 +1842,12 @@ Command* TBBCtl::parse_options(int argc, char** argv)
 					select.clear();
 		  		select.push_back(board);
 		  		command->setSelected(true);
-				}
-				else {
+				} else {
 					logMessage(cerr,"Error: invalid read ddr value. Should be of the format "
 								"'--readw=board,mp,addr' where board= 0..11, mp= 0..3 and addr= 0x..");  
 						exit(EXIT_FAILURE);
 				}
-				command->setMax(itsMaxBoards);
+				command->setCmdType(BOARDCMD);
 			}	break;
 			
 			case '5': { 	// --writew
@@ -1648,27 +1875,26 @@ Command* TBBCtl::parse_options(int argc, char** argv)
 					select.clear();
 		  		select.push_back(board);
 		  		command->setSelected(true);
-				}
-				else {
+				}	else {
 					logMessage(cerr,"Error: invalid write ddr value. Should be of the format "
 								"'--writew=board,mp,addr,wordlo,wordhi' where board= 0..11, mp= 0..3 and addr= 0..x.");  
 						exit(EXIT_FAILURE);
 				}
-				command->setMax(itsMaxBoards);
+				command->setCmdType(BOARDCMD);
 			}	break;
 			/*
 			case '6': { 	// --readr
 				if (command) delete command;
 				ReadrCmd* readrcmd = new ReadrCmd(itsServerPort);
 				command = readrcmd;
-				command->setMax(itsMaxBoards);
+				command->setCmdType(BOARDCMD);
 			}	break;
 			
 			case '7': { 	// --writer
 				if (command) delete command;
 				WriterCmd* writercmd = new WriterCmd(itsServerPort);
 				command = writercmd;
-				command->setMax(itsMaxBoards);
+				command->setCmdType(BOARDCMD);
 			}	break;
 			*/			
 			case 'h': {
@@ -1685,10 +1911,11 @@ Command* TBBCtl::parse_options(int argc, char** argv)
 
 	if (command) {
 		if (!command->getSelected()) {	// --select not used, select all
-		  select.clear();
-			for (int i = 0; i < command->getMax(); ++i) {
-		  	select.push_back(i);
+			select.clear();
+			for (int i = 0; i < command->getMaxSelections(); i++) {
+				select.push_back(i);	
 			}
+			command->setSelected(true);
 		}
 	  command->setSelect(select);
 	}
@@ -1703,16 +1930,16 @@ std::list<int> TBBCtl::strtolist(const char* str, int max)
   char* end   = 0;
   bool  range = false;
   long prevval = 0;
-  list<int> resultset;
-
-  resultset.clear();
+	std::list<int> resultset;
+			
+	resultset.clear();
 
   while(start) {
     long val = strtol(start, &end, 10); // read decimal numbers
     start = (end ? (*end ? end + 1 : 0) : 0); // determine next start
     if (val >= max || val < 0) {
       logMessage(cerr,formatString("Error: value %ld out of range",val));
-      resultset.clear();
+			resultset.clear();
       return(resultset);
     }
 
@@ -1727,14 +1954,13 @@ std::list<int> TBBCtl::strtolist(const char* str, int max)
             }
             if (val < prevval) {
               logMessage(cerr,"Error: invalid range specification");
-              resultset.clear();
-              return(resultset);
-            }
+							resultset.clear();
+							return(resultset);
+						}
             for(long i = prevval; i <= val; i++)
               resultset.push_back(i);
-          }
-          else {
-            resultset.push_back(val);
+          } else {
+						resultset.push_back(val);
           }
           range = false;
         } break;
@@ -1745,9 +1971,9 @@ std::list<int> TBBCtl::strtolist(const char* str, int max)
 
         default: {
           logMessage(cerr,formatString("Error: invalid character %c",*end));
-          resultset.clear();
-          return(resultset);
-        } break;
+					resultset.clear();
+					return(resultset);
+				} break;
       }
     }
     prevval = val;
@@ -1761,8 +1987,7 @@ void TBBCtl::logMessage(ostream& stream, const string& message)
 {
   if (itsCommand != 0) {
     itsCommand->logMessage(stream,message);
-  }
-  else {
+  } else {
     stream << message << endl;
   }
 }
diff --git a/MAC/APL/PIC/TBBDriver/src/tbbctl.h b/MAC/APL/PIC/TBBDriver/src/tbbctl.h
index ffe4de61286db9aa791d91ef1055a2debe345b29..98f504ce58c6d13f11af168bc8fa4a0ededce4db 100644
--- a/MAC/APL/PIC/TBBDriver/src/tbbctl.h
+++ b/MAC/APL/PIC/TBBDriver/src/tbbctl.h
@@ -37,6 +37,25 @@
 namespace LOFAR {
   namespace TbbCtl {
   	
+// MAX_N_TBBBOARDS and MAX_N_RCUS come from TBB_protocol.ph
+
+static const int BOARDCMD = 1;
+static const int RCUCMD = 2;
+
+// information about the flash memory
+static const int FL_SIZE 						= 64 * 1024 *1024; // 64 MB in bytes
+static const int FL_N_PAGES 				= 32; // 32 pages in flash
+static const int FL_N_SECTORS				= 512; // 512 sectors in flash
+static const int FL_N_BLOCKS				= 65536; // 65336 blocks in flash
+
+static const int FL_PAGE_SIZE 			= FL_SIZE / FL_N_PAGES; // 2.097.152 bytes  
+static const int FL_SECTOR_SIZE			= FL_SIZE / FL_N_SECTORS; // 131.072 bytes
+static const int FL_BLOCK_SIZE 			= FL_SIZE / FL_N_BLOCKS; // 1.024 bytes
+
+static const int FL_SECTORS_IN_PAGE	= FL_PAGE_SIZE / FL_SECTOR_SIZE; // 16 sectors per page
+static const int FL_BLOCKS_IN_PAGE	= FL_PAGE_SIZE / FL_BLOCK_SIZE; // 2048 blocks per page
+
+  	
 //-----------------------------------------------------------------------------
 // class Command :base class for control commands towards the TBBDriver.
 //
@@ -62,151 +81,172 @@ public:
 	}
 	
 	//-----------------------------------------------------------------------------
-	virtual string getErrorStr(uint32 status)
+	virtual string getDriverErrorStr(uint32 status)
 	{
 		string str;
 		
 		str.clear();
-		str.append("=ERROR= ");
-		if (status & NO_BOARD)				str.append(";Board not available ");
-		if (status & COMM_ERROR)			str.append(";Comm. time-out ");			
-		if (status & SELECT_ERROR)		str.append(";Not selectable ");
-		if (status & CMD_ERROR)				str.append(";Command failed ");
-		if (status & ALLOC_ERROR)			str.append(";Alloc error ");
-		if (status & CHANNEL_IN_USE)	str.append(";Channel In Use ");
-		if (status & INPUT_IN_USE) 		str.append(";Input In Use ");
-		if (status & BUFFER_TO_LARGE) str.append(";Buffer To Large ");
-		if (status & NO_MP_WRITER)		str.append(";No Mp Writer ");
-		if (status & RING_FULL)				str.append(";Ring Full ");
-		if (status & CRC_ERROR_MP0)		str.append(";CRC error MP0 ");
-		if (status & CRC_ERROR_MP1)		str.append(";CRC error MP1 ");
-		if (status & CRC_ERROR_MP2)		str.append(";CRC error MP2 ");
-		if (status & CRC_ERROR_MP3)		str.append(";CRC error MP3 ");
-		if (status & CRC_ERROR_TP)		str.append(";CRC error TP ");
-		if (status & ACK_ERROR_TP)		str.append(";ACK error TP ");
-		if (status & TIMEOUT_TP_MP)		str.append(";TIMEOUT TP-MP ");
-		return str;
+		
+		// all TBB_XXX constants come from TBB_Protocol.ph
+		
+		if (!(status & TBB_SUCCESS)) {		
+			if (status & TBB_NO_BOARD) {
+				str.append("board not available ");
+				return(str);
+			}
+			
+			if (status & TBB_COMM_ERROR)				str.append(",comm. time-out ");			
+			if (status & TBB_SELECT_ERROR)			str.append(",not selectable ");
+			if (status & TBB_FLASH_ERROR)				str.append(",flash error ");
+			if (status & TBB_ALLOC_ERROR)				str.append(",alloc error ");
+			if (status & TBB_RCU_COMM_ERROR)		str.append(",rcu error ");
+			
+			if (status & TBB_CHANNEL_IN_USE)		str.append(",channel in use ");
+			if (status & TBB_INPUT_IN_USE) 			str.append(",input in use ");
+			if (status & TBB_BUFFER_TO_LARGE) 	str.append(",buffer to large ");
+			if (status & TBB_NO_MP_WRITER)			str.append(",no mp writer ");
+			if (status & TBB_RING_FULL)					str.append(",ring full ");
+			if (status & TBB_RCU_NOT_FREE)			str.append(",rcu not free ");
+			if (status & TBB_RCU_NOT_ALLOCATED)	str.append(",rcu not allocated ");		
+			if (status & TBB_RCU_NOT_RECORDING)	str.append(",rcu not recording ");						
+							
+			if (status & TBB_CRC_ERROR_MP0)			str.append(",crc error mp0 ");
+			if (status & TBB_CRC_ERROR_MP1)			str.append(",crc error mp1 ");
+			if (status & TBB_CRC_ERROR_MP2)			str.append(",crc error mp2 ");
+			if (status & TBB_CRC_ERROR_MP3)			str.append(",crc error mp3 ");
+			if (status & TBB_CRC_ERROR_TP)			str.append(",crc error tp ");
+			if (status & TBB_ACK_ERROR_TP)			str.append(",ack error tp ");
+			if (status & TBB_TIMEOUT_TP_MP)			str.append(",timeout tp-mp ");
+			if (status & TBB_TIMEOUT_ETH)				str.append(",timeout eth ");
+			
+			char statusstr[64];
+			sprintf(statusstr,"unknown ERROR, 0x%08X",status);
+			if (str.empty() && status) str.append(statusstr);
+		}
+		return(str);
+	}
+	
+	//-----------------------------------------------------------------------------
+	virtual string getBoardErrorStr(uint16 status)
+	{
+		string str;
+		
+		str = getDriverErrorStr(((uint32)status << 16));
+				
+		return(str);
+	}
+		
+	//--------------------------------------------------------
+  void setCmdType(int type)
+	{
+		itsCmdType = type;	
 	}
 	
+	//--------------------------------------------------------
+	int getMaxSelections(void) const
+	{
+		int maxbits = 0;
+		if (itsCmdType == BOARDCMD) maxbits = MAX_N_TBBBOARDS; 
+		if (itsCmdType == RCUCMD)   maxbits = MAX_N_RCUS;
+		return(maxbits);	
+	}
 	
 	//--------------------------------------------------------
-  void setMax(int max)
+	void setCmdDone(bool done)
 	{
-		itsMax = max;	
+		itsCmdDone = done;
 	}
 	
 	//--------------------------------------------------------
-	int getMax(void) const
+	bool isCmdDone() const
 	{
-		return itsMax;	
+		return(itsCmdDone);
 	}
 	
-	//--------------------------------------------------------	
+	//--selection is done-------------------------------------	
 	void setSelected(bool select)
 	{
 		itsSelected = select;	
 	}
 	
-	//--------------------------------------------------------
+	//--check if selection is done----------------------------
 	bool getSelected(void) const
 	{
 		return itsSelected;	
 	}
 	
-	//--------------------------------------------------------
+	//--set selection-----------------------------------------
 	void setSelect(std::list<int> select)
 	{
-		itsSelect = select;
-		
-		int32 boardnr = 0;
-		int32 channelnr = 0;
-		std::list<int>::const_iterator it;
-		for (it = itsSelect.begin(); it != itsSelect.end(); ++it) {
-			channelnr = *it;
-			boardnr = (int32)(channelnr / 16.);
-			channelnr -= boardnr * 16; 
-			itsChannelMask[boardnr] |= (1 << *it);	
-		}
+		itsSelection = select;
 	}
 	
-	
-	//--------------------------------------------------------
+	//--return true if board or rcu nr is selected------------
 	bool isSelected(int nr) const
 	{
 		bool inList = false;
-		
 		std::list<int>::const_iterator it;
-		for (it = itsSelect.begin(); it != itsSelect.end(); ++it) {
-			if(*it == nr) {
-				inList = true;	
-				break;
-			}
-		}	
-		return inList;	
+		
+		for (it = itsSelection.begin(); it != itsSelection.end(); it++) {
+			if (*it == nr) inList = true;
+		}
+		return(inList);	
 	}
 	
-	int32 getChannel()
+	//--return selected board---------------------------------
+	int getBoard() const
 	{
-		return itsSelect.front();
+		return(itsSelection.front());
 	}
 	
-	int32 getBoard()
+	//--return selected rcu-------------------------------	
+	int getRcu() const
 	{
-		return itsSelect.front();
+		return(itsSelection.front());
 	}
 	
-	//--------------------------------------------------------
-	uint32 getMask()
+	//--return selected boards in a mask----------------------
+	uint32 getBoardMask() const
 	{
-		uint32 mask = 0;
+		uint32 boardmask = 0;
 		std::list<int>::const_iterator it;
-		for (it = itsSelect.begin(); it != itsSelect.end(); ++it) {
-			mask |= (1 << *it);	
-		}
-		return mask;
-	}
 		
-	//--------------------------------------------------------
-	uint32 getChannelMask(int32 boardnr)
-	{
-		return itsChannelMask[boardnr];
-	}
-	
-	//--------------------------------------------------------
-	void setCmdDone(bool done)
-	{
-			itsCmdDone = done;
+		for (it = itsSelection.begin(); it != itsSelection.end(); it++) {
+			boardmask |= (1 << *it);		
+		}
+		return(boardmask);	
 	}
 	
-	//--------------------------------------------------------
-	bool isCmdDone()
+	//--return selected rcus in a mask----------------------
+	std::bitset<MAX_N_RCUS> getRcuMask() const
 	{
-			return itsCmdDone;
-	}
+		std::bitset<MAX_N_RCUS> rcus;
+		std::list<int>::const_iterator it;
 		
+		rcus.reset();
+		for (it = itsSelection.begin(); it != itsSelection.end(); it++) {
+			rcus.set(*it);		
+		}
+		return(rcus);	
+	}	
 	
 protected:
 	explicit Command(GCFPortInterface& port) : 
   	itsPort(port),
-  	itsMax(0),
-		itsSelected(false),
-  	itsSelect(0),
-  	itsCmdDone(false)
+  	itsSelected(false),
+  	itsCmdDone(false),
+		itsCmdType(0)
 	{
-		for(int32 nr = 0; nr < MAX_N_TBBBOARDS;nr++)
-			itsChannelMask[nr] = 0; 
 	}
 	
 	Command(); // no default construction allowed
 
 protected:
-	GCFPortInterface& itsPort;
-	int								itsMax;
-	bool							itsSelected;
-	std::list<int>		itsSelect; 
-	uint32						itsChannelMask[MAX_N_TBBBOARDS];
-	bool							itsCmdDone;
-	
+	GCFPortInterface& 			itsPort;
+	bool		itsSelected;
+	bool		itsCmdDone;
+	int			itsCmdType;
+	std::list<int>	itsSelection;
 		
 private:
 
@@ -291,18 +331,28 @@ class ReadCmd : public Command
 		virtual ~ReadCmd() { }
 		virtual void send();
 		virtual GCFEvent::TResult ack(GCFEvent& e);
+		void setSecondsTime(uint32 secondstime) { itsSecondsTime = secondstime; }
+		void setSampleTime(uint32 sampletime) { itsSampleTime = sampletime; }
+		void setPrePages(uint32 prepages) { itsPrePages = prepages; }
+		void setPostPages(uint32 postpages) { itsPostPages = postpages; }
 	private:
+		uint32 itsSecondsTime;
+		uint32 itsSampleTime;
+		uint32 itsPrePages;
+		uint32 itsPostPages;
 };
 
 //-----------------------------------------------------------------------------
-class UdpCmd : public Command
+class ModeCmd : public Command
 {
 	public:
-		UdpCmd(GCFPortInterface& port);
-		virtual ~UdpCmd() { }
+		ModeCmd(GCFPortInterface& port);
+		virtual ~ModeCmd() { }
 		virtual void send();
 		virtual GCFEvent::TResult ack(GCFEvent& e);
+		void setRecMode(uint32 recmode) { itsRecMode = recmode; }	
 	private:
+		uint32 itsRecMode;
 };
 
 //-----------------------------------------------------------------------------
@@ -381,7 +431,9 @@ class ErasefCmd : public Command
 		virtual ~ErasefCmd() { }
 		virtual void send();
 		virtual GCFEvent::TResult ack(GCFEvent& e);
+		void setPage(int page)  {	itsPage = page;	}
 	private:
+		int itsPage;
 };
 
 //-----------------------------------------------------------------------------
@@ -392,7 +444,9 @@ class ReadfCmd : public Command
 		virtual ~ReadfCmd() { }
 		virtual void send();
 		virtual GCFEvent::TResult ack(GCFEvent& e);
+		void setPage(int page)  {	itsPage = page;	}	
 	private:
+		int		itsPage;
 };
 
 //-----------------------------------------------------------------------------
@@ -403,6 +457,25 @@ class WritefCmd : public Command
 		virtual ~WritefCmd() { }
 		virtual void send();
 		virtual GCFEvent::TResult ack(GCFEvent& e);
+		void setPage(int page)  {	itsPage = page;	}	
+		void setVersion(double version)  {	itsVersion = version;	}	
+		void setFileNameTp(char *filename)  {	strcpy(itsFileNameTp,filename);	}
+		void setFileNameMp(char *filename)  {	strcpy(itsFileNameMp,filename);	}
+	private:
+		int itsPage;
+		double itsVersion;
+		char itsFileNameTp[64];
+		char itsFileNameMp[64];
+};
+
+//-----------------------------------------------------------------------------
+class ImageInfoCmd : public Command
+{
+	public:
+		ImageInfoCmd(GCFPortInterface& port);
+		virtual ~ImageInfoCmd() { }
+		virtual void send();
+		virtual GCFEvent::TResult ack(GCFEvent& e);
 	private:
 };
 
@@ -473,7 +546,7 @@ class ReadPageCmd : public Command
 		virtual ~ReadPageCmd() { }
 		virtual void send();
 		virtual GCFEvent::TResult ack(GCFEvent& e);
-		void setMp(uint32 mp)		{	itsMp = mp;	}
+		void setMp(int32 mp)		{	itsMp = mp;	}
 		void setAddr(uint32 addr)  { itsAddr = addr; }
 		void setPages(uint32 pages)  { itsPages = pages; }
 		static const uint32 PID6 = 6;
@@ -485,13 +558,22 @@ class ReadPageCmd : public Command
 		static const uint32 DATA1POS = 0;
 		static const uint32 DATA2POS = 256;
 	private:
-		int32 itsCmdStage;
-		uint32 itsPage;
-		uint32 itsMp;
-		uint32 itsAddr;
-		uint32 itsPages;
+		// values given by user
+		int32		itsRcu;
+		uint32	itsPages;
+		// values used in program
+		int32		itsCmdStage;
+		uint32	itsPage;
+		uint32	itsAddr;
+		// data from channelInfoCmd
+		char		itsState;		
+		uint32	itsStartAddr;
+		uint32	itsSize;
+		int32		itsBoard;
+		int32		itsMp;
+		// data from ReadxCmd
 		uint32 itsData[512];
-		
+		// extracted data from itsData[512]
 		int itsStationId;
 		int itsRspId;
 		int itsRcuId;
@@ -547,7 +629,7 @@ public:
 private:
   // private methods
   Command* parse_options(int argc, char** argv);
-  std::list<int> strtolist(const char* str, int max);
+	std::list<int> strtolist(const char* str, int max);
   void logMessage(ostream& stream, const string& message);
 	
 	void help();
@@ -558,7 +640,6 @@ private:
   // the command to execute
   Command* 	itsCommand;
 	
-	
   // dimensions of the connected hardware
 	uint32	itsActiveBoards;	// mask b0 = board0, b1 = board1 ....
 	int			itsMemory[MAX_N_TBBBOARDS];