Commit 87872eae authored by Florian Aubin's avatar Florian Aubin
Browse files

Merge branch 'Dev' of https://gitlab.cern.ch:8443/faubin/Ph2_ACF into Dev

Conflicts:
	CHANGELOG
	System/SystemController.cc
	System/SystemController.h
	Utils/Event.cc
	tools/Tool.h
parents dfe4291f f2a9c24f
*.o
._*
*.un~
*~
Data
latex
......@@ -15,3 +16,4 @@ Calibrations
.run_number.txt
settings/connections_186.xml
.ycm_extra_conf.py
.ycm_extra_conf.pyc
#include "Amc13Controller.h"
Amc13Controller::Amc13Controller()
{
fAmc13Interface = nullptr;
fAmc13 = nullptr;
}
Amc13Controller::~Amc13Controller()
{
delete fAmc13;
delete fAmc13Interface;
}
void Amc13Controller::InitializeAmc13( const std::string& pFilename, std::ostream& os )
{
if ( pFilename.find( ".xml" ) != std::string::npos )
parseAmc13xml(pFilename, os);
else std::cerr << "Could not parse settings file " << pFilename << " - it is not .xml!" << std::endl;
}
void Amc13Controller::ConfigureAmc13( std::ostream& os )
{
os << BOLDGREEN << "Configuring Amc13!" << RESET << std::endl;
// no need to pass the Amc13 memory description as there is only 1, I just keep it for reference and update accordingly!
fAmc13Interface->ConfigureAmc13();
}
void Amc13Controller::HaltAmc13( std::ostream& os )
{
os << BOLDGREEN << "Halting Amc13!" << RESET << std::endl;
fAmc13Interface->HaltAMC13();
}
void Amc13Controller::parseAmc13xml(const std::string& pFilename, std::ostream& os)
{
pugi::xml_document doc;
int i, j;
pugi::xml_parse_result result = doc.load_file( pFilename.c_str() );
if ( !result )
{
os << "ERROR :\n Unable to open the file : " << pFilename << std::endl;
os << "Error description : " << result.description() << std::endl;
return;
}
os << "\n";
for ( i = 0; i < 80; i++ )
os << "*";
os << "\n";
for ( j = 0; j < 40; j++ )
os << " ";
os << BOLDRED << "AMC13 Settings " << RESET << std::endl;
for ( i = 0; i < 80; i++ )
os << "*";
os << "\n";
// no clue why I have to loop but that's what it is!
for ( pugi::xml_node cAmc13node = doc.child( "HwDescription" ).child( "AMC13" ); cAmc13node; cAmc13node = cAmc13node.next_sibling("AMC13") )
{
os << BOLDCYAN << cAmc13node.name() << RESET << std::endl;
// now create a new AMC13 Description Object
if ( fAmc13 != nullptr ) delete fAmc13;
fAmc13 = new Amc13Description();
std::string cUri1, cUri2;
std::string cAddressT1, cAddressT2;
// finally find the connection nodes and construct the proper Amc13FWInterface
for ( pugi::xml_node Amc13Connection = cAmc13node.child( "connection" ); Amc13Connection; Amc13Connection = Amc13Connection.next_sibling("connection") )
{
if ( std::string(Amc13Connection.attribute( "id" ).value()) == "T1")
{
cUri1 = std::string(Amc13Connection.attribute( "uri" ).value());
cAddressT1 = std::string(Amc13Connection.attribute( "address_table" ).value());
}
else if ( std::string(Amc13Connection.attribute( "id" ).value()) == "T2" )
{
cUri2 = std::string(Amc13Connection.attribute( "uri" ).value());
cAddressT2 = std::string(Amc13Connection.attribute( "address_table" ).value());
}
os << BOLDBLUE << "|" << "----" << "Board Id: " << BOLDYELLOW << Amc13Connection.attribute("id").value() << BOLDBLUE << " URI: " << BOLDYELLOW << Amc13Connection.attribute("uri").value() << BOLDBLUE << " Address Table: " << BOLDYELLOW << Amc13Connection.attribute("address_table").value() << RESET << std::endl;
}
// here loop over the Register nodes and add them to the AMC13Description object!
for ( pugi::xml_node Amc13RegNode = cAmc13node.child( "Register" ); Amc13RegNode; Amc13RegNode = Amc13RegNode.next_sibling("Register") )
{
std::string regname = std::string(Amc13RegNode.attribute( "name" ).value());
os << BOLDCYAN << "|" << "----" << Amc13RegNode.name() << " " << Amc13RegNode.attribute( "tounge" ).name() << " : " << Amc13RegNode.attribute( "tounge" ).value() << " - name: " << regname << " " << BOLDRED << convertAnyInt(Amc13RegNode.first_child().value()) << RESET << std:: endl;
if ( std::string(Amc13RegNode.attribute("tounge").value()) == "T1" )
fAmc13->setReg(1 , regname, convertAnyInt( Amc13RegNode.first_child().value() ) );
else if ( std::string(Amc13RegNode.attribute("tounge").value()) == "T2" )
fAmc13->setReg(2 , regname, convertAnyInt( Amc13RegNode.first_child().value() ) );
}
// now get all the properties and add to the Amc13Description object
fAmc13->setAMCMask( parseAMCMask( cAmc13node.child( "AMCmask" ), std::cout ) );
fAmc13->setTrigger( parseTrigger( cAmc13node.child( "Trigger" ), std::cout ) );
for (pugi::xml_node cBGOnode = cAmc13node.child( "BGO" ); cBGOnode; cBGOnode = cBGOnode.next_sibling("BGO"))
{
fAmc13->addBGO( parseBGO( cBGOnode, std::cout ) );
}
//now just parse the TTC Simulator Node!
for (pugi::xml_node cBGOnode = cAmc13node.child( "TTCSimulator" ); cBGOnode; cBGOnode = cBGOnode.next_sibling("TTCSimulator"))
{
int cTTCSimulator = convertAnyInt(cBGOnode.first_child().value());
bool cTTCSim;
if (cTTCSimulator == 0 ) cTTCSim = false;
else cTTCSim = true;
fAmc13->setTTCSimulator(cTTCSim);
os << BOLDCYAN << "|" << "----" << cBGOnode.name() << " " << cTTCSimulator << RESET << std::endl;
// now instantiate the AMC13Interface & provide it with the correct HWDescription object so I don't need to pass it around all the time!
if ( fAmc13Interface != nullptr ) delete fAmc13Interface;
fAmc13Interface = new Amc13Interface(cUri1, cAddressT1, cUri2, cAddressT2);
fAmc13Interface->setAmc13Description(fAmc13);
}
}
}
std::vector<int> Amc13Controller::parseAMCMask(pugi::xml_node pNode, std::ostream & os)
{
std::vector<int> cVec;
if (std::string(pNode.name()) == "AMCmask")
{
//for ( pugi::xml_node cNode = pNode.child( "AMCmask" ); cNode; cNode = cNode.next_sibling("AMCmask") )
//{
std::string cList = std::string(pNode.attribute("enable").value());
std::string ctoken;
std::stringstream cStr(cList);
os << BOLDCYAN << "|" << "----" << "List of Enabled AMCs: ";
while (std::getline(cStr, ctoken, ','))
{
cVec.push_back(convertAnyInt( ctoken.c_str() ));
os << GREEN << ctoken << BOLDCYAN << ", ";
}
os << RESET << std::endl;
}
return cVec;
}
BGO* Amc13Controller::parseBGO(pugi::xml_node pNode, std::ostream & os)
{
BGO* cBGO = nullptr;
if ( std::string(pNode.name()) == "BGO")
{
cBGO = new BGO( convertAnyInt(pNode.attribute( "command" ).value()), bool(pNode.attribute( "repeat" ).value()), convertAnyInt(pNode.attribute( "prescale" ).value() ), convertAnyInt(pNode.attribute( "bx" ).value()) );
os << BOLDCYAN << "|" << "----" << "BGO : command " << cBGO->fCommand << " repeat " << cBGO->fRepeat << " Prescale " << cBGO->fPrescale << " start BX " << cBGO->fBX << RESET << std::endl;
}
return cBGO;
}
Trigger* Amc13Controller::parseTrigger( pugi::xml_node pNode, std::ostream & os )
{
Trigger* cTrg = nullptr;
if ( std::string(pNode.name()) == "Trigger" )
{
cTrg = new Trigger(bool(pNode.attribute("local").value()), convertAnyInt(pNode.attribute( "mode" ).value()), convertAnyInt( pNode.attribute( "rate" ).value()), convertAnyInt( pNode.attribute( "burst" ).value()), convertAnyInt( pNode.attribute( "rules" ).value() ) );
os << BOLDGREEN << "|" << "----" << "Trigger Config : Local " << cTrg->fLocal << " Mode " << cTrg->fMode << " Rate " << cTrg->fRate << " Burst " << cTrg->fBurst << " Rules " << cTrg->fRules << RESET << std::endl;
}
return cTrg;
}
#ifndef _AMC13_CONTROLLER_H__
#define _AMC13_CONTROLLER_H__
#include "../Utils/pugixml.hpp"
#include "../Utils/ConsoleColor.h"
#include "Amc13Interface.h"
#include "Amc13Description.h"
#include <iostream>
#include <map>
#include <string>
class Amc13Controller
{
public:
Amc13Controller();
~Amc13Controller();
void InitializeAmc13( const std::string& pFilename, std::ostream& os = std::cout );
void ConfigureAmc13( std::ostream& os = std::cout );
void HaltAmc13( std::ostream& os = std::cout );
public:
Amc13Interface* fAmc13Interface;
Amc13Description* fAmc13;
private:
// Private methods for parsing!
void parseAmc13xml(const std::string& pFilename, std::ostream& os = std::cout);
// low level helpers to parse specific xml TAGS
std::vector<int> parseAMCMask(pugi::xml_node pNode, std::ostream& os = std::cout);
BGO* parseBGO(pugi::xml_node pNode, std::ostream& os = std::cout);
Trigger* parseTrigger( pugi::xml_node pNode , std::ostream& os = std::cout);
// a little helper to deal with strings
uint32_t convertAnyInt( const char* pRegValue )
{
if ( std::string( pRegValue ).find( "0x" ) != std::string::npos ) return static_cast<uint32_t>( strtoul( pRegValue , 0, 16 ) );
else return static_cast<uint32_t>( strtoul( pRegValue , 0, 10 ) );
}
};
#endif
#include "Amc13Description.h"
Amc13Description::Amc13Description()
{
fTrigger = nullptr;
fT1map.clear();
fT2map.clear();
fAMCMask.clear();
fBGOs.clear();
}
Amc13Description::~Amc13Description()
{
delete fTrigger;
for (auto& cBGO : fBGOs) delete cBGO;
fBGOs.clear();
fAMCMask.clear();
fT1map.clear();
fT2map.clear();
}
uint32_t Amc13Description::getReg( int pTounge, std::string& pReg )
{
RegMap cMap = (pTounge == 1) ? fT1map : fT2map;
auto cReg = cMap.find(pReg);
if (cReg == std::end( cMap )) std::cout << "The AMC13 does not have a register " << pReg << " in the memory map for Tounge " << pTounge << std::endl;
else return cReg->second;
}
void Amc13Description::setReg( int pTounge, std::string& pReg, uint32_t pValue)
{
RegMap cMap = (pTounge == 1) ? fT1map : fT2map;
auto cReg = cMap.find(pReg);
if ( cReg == std::end(cMap) ) cMap.insert( {pReg, pValue} );
else cReg->second = pValue;
}
void Amc13Description::setAMCMask(const std::vector<int>& pMask)
{
fAMCMask = pMask;
}
void Amc13Description::setTrigger(bool pLocal, int pMode, int pRate, int pBurst, int pRules)
{
if (fTrigger != nullptr)
{
std::cout << "Warning, overwriting another Trigger object!" << std::endl;
delete fTrigger;
}
fTrigger = new Trigger(pLocal, pMode, pRate, pBurst, pRules);
}
void Amc13Description::setTrigger( Trigger* pTrigger )
{
if ( fTrigger != nullptr )
{
std::cout << "Warning, overwriting another Trigger object!" << std::endl;
delete fTrigger;
}
fTrigger = pTrigger;
}
Trigger* Amc13Description::getTrigger()
{
return fTrigger;
}
void Amc13Description::setTTCSimulator(bool pSimulate)
{
fSimulate = pSimulate;
}
void Amc13Description::addBGO(int pCommand, bool pRepeat, int pPrescale, int pBX)
{
int cSize = fBGOs.size();
if (cSize > 4) std::cout << "Warning, AMC13XG only supports 4 user-defined BGOs - adding this one will have no effect!" << std::endl;
else
{
BGO* cBGO = new BGO(pCommand, pRepeat, pPrescale, pBX);
fBGOs.push_back(cBGO);
}
}
void Amc13Description::addBGO( BGO* pBGO)
{
int cSize = fBGOs.size();
if (cSize > 4) std::cout << "Warning, AMC13XG only supports 4 user-defined BGOs - adding this one will have no effect!" << std::endl;
else
{
fBGOs.push_back( pBGO );
}
}
BGO* Amc13Description::getBGO(int pPos)
{
if (pPos > 3)
{
std::cout << "AMC13XG only supports 4 custom BGOs, ID > 3 is not allowed!" << std::endl;
return nullptr;
}
else return fBGOs.at(pPos);
}
#ifndef _AMC13_DESCRIPTION_h__
#define _AMC13_DESCRIPTION_h__
#include <map>
#include <string>
#include <vector>
#include <stdint.h>
#include <iostream>
typedef std::map<std::string, uint32_t> RegMap;
// a little forward declaration!
struct Trigger;
struct BGO;
class Amc13Description
{
public:
Amc13Description();
~Amc13Description();
uint32_t getReg(int pTounge, std::string& pReg);
void setReg(int pTounge, std::string& pReg, uint32_t pValue);
RegMap getRegMap(int pTounge)
{
return (pTounge == 1) ? fT1map : fT2map;
}
int Id;
void setTrigger(bool pLocal, int pType, int pRate, int pBurst, int pRules);
void setTrigger( Trigger* pTrigger);
Trigger* getTrigger();
void addBGO( int pCommand, bool pRepeat, int pPrescale, int pBX );
void addBGO( BGO* pBGO );
BGO* getBGO( int pPos );
void setAMCMask(const std::vector<int>& pMask);
void setTTCSimulator(bool pSimulate);
public:
RegMap fT1map;
RegMap fT2map;
std::vector<int> fAMCMask;
std::vector<BGO*> fBGOs;
Trigger* fTrigger;
bool fSimulate;
};
struct BGO
{
BGO(int pCommand, bool pRepeat, int pPrescale, int pBX) : fCommand( pCommand ), fRepeat( pRepeat ), fPrescale( pPrescale ), fBX( pBX ) {}
int fCommand;
bool fRepeat;
int fPrescale;
int fBX;
};
struct Trigger
{
Trigger(bool pLocal, int pMode, int pRate, int pBurst, int pRules) : fLocal(pLocal), fMode( pMode ), fRate( pRate ), fBurst(pBurst), fRules( pRules ) {}
bool fLocal;
int fMode;
int fRate;
int fBurst;
int fRules;
//mode 0 = periodic trigger every rate orbits at BX=500
//mode 1 = periodic trigger every rate BX
//mode 2 = random trigger at rate Hz
};
#endif
#include "Amc13Interface.h"
Amc13Interface::Amc13Interface( const std::string& uriT1, const std::string& addressT1, const std::string& uriT2, const std::string& addressT2 )
{
// Log level
//uhal::disableLogging();
uhal::setLogLevelTo(uhal::Error());
// this is the way if i want to keep the syntax
uhal::ConnectionManager cm( "file://HWInterface/dummy.xml" );
uhal::HwInterface T1( cm.getDevice( "T1", uriT1, addressT1 ) );
uhal::HwInterface T2( cm.getDevice( "T2", uriT2, addressT2 ) );
fAMC13 = new amc13::AMC13(T1, T2);
//this would be the other way!
//fAMC13 = new amc13::AMC13(uriT1, addressT1, uriT2, addressT2);
//whatever else I need to do here!
}
Amc13Interface::~Amc13Interface()
{
delete fAMC13;
}
void Amc13Interface::ConfigureAmc13()
{
// first start with enabling AMCs!
uint32_t cMask = 0;
// first reset the 2 boards
std::cout << "Resetting T1, T2 & all counters!" << std::endl;
fAMC13->reset(amc13::AMC13Simple::T1);
fAMC13->reset(amc13::AMC13Simple::T2);
// now reset the counters
fAMC13->resetCounters();
// now enable the AMC inputs as specified in the config File
std::cout << "Enabling TTC links for the following AMCs: " << std::endl;
for (auto& cAMC : fDescription->fAMCMask)
{
setBit(cMask, cAMC, true);
std::cout << cAMC << ", ";
}
std::cout << std::endl;
fAMC13->AMCInputEnable( cMask );
//now configure the BGOs, loop through the list, get the properties and call the function
int cIndex = 0;
if (!fDescription->fBGOs.empty())
{
for (auto& cBGO : fDescription->fBGOs )
{
this->configureBGO(cIndex, uint8_t(cBGO->fCommand), uint16_t(cBGO->fBX), uint16_t(cBGO->fPrescale), cBGO->fRepeat);
this->enableBGO(cIndex);
std::cout << "Configured & enabling BGO Channel " << cIndex << " : Command: " << cBGO->fCommand << " BX: " << cBGO->fBX << " Prescale: " << cBGO->fPrescale << " Repetetive: " << cBGO->fRepeat << std::endl;
cIndex++;
}
}
// now configure the Trigger
if (fDescription->fTrigger != nullptr)
{
fAMC13->configureLocalL1A(fDescription->fTrigger->fLocal, fDescription->fTrigger->fMode, uint32_t(fDescription->fTrigger->fBurst), uint32_t(fDescription->fTrigger->fRate), fDescription->fTrigger->fRules );
fAMC13->write(amc13::AMC13Simple::T1,"CONF.LOCAL_TRIG.FAKE_DATA_ENABLE", 1);
std::cout << "Configuring local L1A: Mode: " << fDescription->fTrigger->fMode << " Rate: " << fDescription->fTrigger->fRate << " Burst: " << fDescription->fTrigger->fBurst << " Rules: " << fDescription->fTrigger->fRules << std::endl;
}
// if TTC simulator is enabled, the loopback fiber is required and no external TTC stream will be received, the Triggers are local by definition
if (fDescription->fSimulate)
{
fAMC13->localTtcSignalEnable(fDescription->fSimulate);
//fAMC13->enableLocalL1A(true);
std::cout << RED << "AMC13 configured to use local TTC simulator - don't forget to plug the loopback fibre!" << RESET << std::endl;
}
//now need to iterate the two maps of Registers and write them
for (auto& cReg : fDescription->fT1map)
fAMC13->write(amc13::AMC13Simple::T1, cReg.first, cReg.second);
for (auto& cReg : fDescription->fT2map)
fAMC13->write(amc13::AMC13Simple::T2, cReg.first, cReg.second);
std::cout << GREEN << "AMC13 successfully configured!" << RESET << std::endl;
}
void Amc13Interface::StartL1A()
{
fAMC13->startContinuousL1A();
}
void Amc13Interface::StopL1A()
{
fAMC13->stopContinuousL1A();
}
void Amc13Interface::BurstL1A()
{
fAMC13->sendL1ABurst();
}
void Amc13Interface::EnableBGO(int pChan)
{
this->enableBGO( pChan );
}
void Amc13Interface::DisableBGO(int pChan)
{
this->disableBGO( pChan );
}
void Amc13Interface::EnableTTCHistory()
{
fAMC13->setTTCHistoryEna(true);
}
void Amc13Interface::DisableTTCHistory()
{
fAMC13->setTTCHistoryEna(false);
}
void Amc13Interface::ConfigureTTCHistory(std::vector<std::pair<int, uint32_t>> pFilterConfig)
{
// n = int in the pair ... history item
// filterVal = uint32_t ... filter Value
for (auto& cPair : pFilterConfig)
fAMC13->setTTCHistoryFilter(cPair.first, cPair.second);
}
//void Amc13Interface::DumpHistory(int pNlastEntries)
//{
//fAMC13->setTTCHistoryEna(true);
//std::vector<uint32_t> cVec = fAMC13->getTTCHistory(pNlastEntries);
////now decode the Info in here!
//std::cout << BOLDRED << "TTC History showing the last " << pNlastEntries << " items!" << RESET << std::endl;
//for (int index = 0; index < cVec.size() / 4; index++)
//{
//// 4 32-bit words per command in the history
//uint32_t cCommand = cVec.at(index * 4 + 0);
//uint32_t cOrbit = cVec.at(index * 4 + 1);
//uint32_t cBX = cVec.at(index * 4 + 2);
//uint32_t cEvent = cVec.at(index * 4 + 3);
//std::cout << "Command: " << (cCommand & 0xFF) << " - Orbit: " << cOrbit << " - BX: " << (cBX & 0x7FF) << " - Event Nr: " << (cEvent & 0x00FFFFFF) << std::endl;
//}
//}
//void Amc13Interface::DumpTriggers(int pNlastEntries)
//{
//if ( pNlastEntries > 127 ) std::cerr << "Only last 128 Events available in L1A history buffer!" << std::endl;
//std::vector<uint32_t> cVec = fAMC13->getL1AHistory(pNlastEntries);
////now decode the Info in here!
//std::cout << BOLDRED << "L1A History showing the last " << pNlastEntries << " items!" << RESET << std::endl;
//for (int index = 0; index < cVec.size() / 4; index++)
//{
//// 4 32-bit words per command in the history
//uint32_t cOrbit = cVec.at(index * 4 + 0);
//uint32_t cBunch = cVec.at(index * 4 + 1);
//uint32_t cEventNr = cVec.at(index * 4 + 2);
//uint32_t cFlags = cVec.at(index * 4 + 3);
//std::cout << "Orbit: " << cOrbit << " - Bunch: " << (cBunch & 0xFFF) << " - Event Nr: " << (cEventNr & 0xFFFFFF) << " - Flags: " << cFlags << std::endl;
//}
//}
void Amc13Interface::HaltAMC13()
{
std::cout << "Resetting T1, T2 & all counters!" << std::endl;
fAMC13->reset(amc13::AMC13Simple::T1);
fAMC13->reset(amc13::AMC13Simple::T2);
// now reset the counters
fAMC13->resetCounters();
}
void Amc13Interface::ResetAMC13()
{
std::cout << "Resetting T1, T2 & all counters! - Remind Georg to add OC0 and EC0 when you read this!" << std::endl;
fAMC13->reset(amc13::AMC13Simple::T1);
fAMC13->reset(amc13::AMC13Simple::T2);
// now reset the counters
fAMC13->resetCounters();
}
void Amc13Interface::configureBGO(int pChan, uint8_t pCommand, uint16_t pBX, uint16_t pPrescale, bool pRepeat)
{
char tmp[32];
if ( pChan < 0 || pChan > 3)
{
amc13::Exception::UnexpectedRange e;
e.Append("AMC13::configureBGOShort() - channel must be in range 0 to 3");
throw e;
}
if ( pBX > 3563)
{
amc13::Exception::UnexpectedRange e;
e.Append("AMC13::configureBGOShort() - bx must be in range 0 to 3563");