Commit 91ecd0ea authored by Georg Auzinger's avatar Georg Auzinger
Browse files

merge commit after merging Dev into master

parents 52e58b81 3ef1ad2b
*.o
._*
*.un~
*~
Data
latex
html
html/
latex/
logs/
logs/*
*.bin
*.raw
Results/
......@@ -15,3 +18,5 @@ Calibrations
.run_number.txt
settings/connections_186.xml
.ycm_extra_conf.py
.ycm_extra_conf.pyc
src/test.cc
# This is a Dev version of a YAML script for CI of Ph2_ACF Middleware
# Author: Nikkie Deelen (CERN/KIT)
# A build is automatically triggered when a push is made to the remote repository
# CERN's shared runner is used which is configured for Docker with SL6
# sudo is not necessary in docker, every application used needs to be installed first
before_script:
- yum -y -q install wget
- wget -O /etc/yum.repos.d/slc6-devtoolset.repo http://linuxsoft.cern.ch/cern/devtoolset/slc6-devtoolset.repo
- yum -y -q install devtoolset-2
- ln -s /opt/rh/devtoolset-2/root/usr/bin/* /usr/local/bin/
- hash -r
- wget http://svnweb.cern.ch/trac/cactus/export/28265/tags/ipbus_sw/uhal_2_3_0/scripts/release/cactus.slc6.x86_64.repo
- cp cactus.slc6.x86_64.repo /etc/yum.repos.d/cactus.repo
- yum -y -q clean all
- yum -y -q groupinstall uhal
- yum -y -q install root
- yum -y -q install root-net-http root-montecarlo-eg root-graf3d-eve root-geom root-physics root-graf3d-gl
- yum -y -q install zeromq
build_Ph2_ACF:
script:
- source setup.sh
- make
only:
- Dev
after_script:
- source setup.sh
- miniDAQ --help && datatest --help && systemtest
#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 LOG (ERROR) << "Could not parse settings file " << pFilename << " - it is not .xml!";
}
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" ), os ) );
fAmc13->setTrigger ( parseTrigger ( cAmc13node.child ( "Trigger" ), os ) );
for (pugi::xml_node cBGOnode = cAmc13node.child ( "BGO" ); cBGOnode; cBGOnode = cBGOnode.next_sibling ("BGO") )
fAmc13->addBGO ( parseBGO ( cBGOnode, os ) );
//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 (convertAnyInt (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 );
void ConfigureAmc13 ( std::ostream& os );
void HaltAmc13 ( std::ostream& os );
public:
Amc13Interface* fAmc13Interface;
Amc13Description* fAmc13;
private:
// Private methods for parsing!
void parseAmc13xml (const std::string& pFilename, std::ostream& os);
// low level helpers to parse specific xml TAGS
std::vector<int> parseAMCMask (pugi::xml_node pNode, std::ostream& os);
BGO* parseBGO (pugi::xml_node pNode, std::ostream& os);
Trigger* parseTrigger ( pugi::xml_node pNode , std::ostream& os);
// 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 ) ) LOG (INFO) << "The AMC13 does not have a register " << pReg << " in the memory map for Tounge " << pTounge ;
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)
{
LOG (INFO) << "Warning, overwriting another Trigger object!" ;
delete fTrigger;
}
fTrigger = new Trigger (pLocal, pMode, pRate, pBurst, pRules);
}
void Amc13Description::setTrigger ( Trigger* pTrigger )
{
if ( fTrigger != nullptr )
{
LOG (INFO) << "Warning, overwriting another Trigger object!" ;
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) LOG (INFO) << "Warning, AMC13XG only supports 4 user-defined BGOs - adding this one will have no effect!" ;
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) LOG (INFO) << "Warning, AMC13XG only supports 4 user-defined BGOs - adding this one will have no effect!" ;
else
fBGOs.push_back ( pBGO );
}
BGO* Amc13Description::getBGO (int pPos)
{
if (pPos > 3)
{
LOG (INFO) << "AMC13XG only supports 4 custom BGOs, ID > 3 is not allowed!" ;
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>
#include "../Utils/easylogging++.h"
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()
{
fAMC13->initAMC13();
// first start with enabling AMCs!
uint32_t cMask = 0;
// first reset the 2 boards
LOG (INFO) << "Resetting T1, T2 & all counters!" ;
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
LOG (INFO) << "Enabling TTC links for the following AMCs: " ;
std::stringstream ss;
for (auto& cAMC : fDescription->fAMCMask)
{
setBit (cMask, cAMC, true);
ss << cAMC << ", ";
}
LOG (INFO) << ss.str() ;
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);
LOG (INFO) << "Configured & enabling BGO Channel " << cIndex << " : Command: " << cBGO->fCommand << " BX: " << cBGO->fBX << " Prescale: " << cBGO->fPrescale << " Repetetive: " << cBGO->fRepeat ;
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 );
//Edit GA: not sure if this is actually required
fAMC13->write (amc13::AMC13Simple::T1, "CONF.LOCAL_TRIG.FAKE_DATA_ENABLE", 1);
LOG (INFO) << "Configuring local L1A: Mode: " << fDescription->fTrigger->fMode << " Rate: " << fDescription->fTrigger->fRate << " Burst: " << fDescription->fTrigger->fBurst << " Rules: " << fDescription->fTrigger->fRules ;
}
// 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);
LOG (INFO) << RED << "AMC13 configured to use local TTC simulator - don't forget to plug the loopback fibre!" << RESET ;
}
//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);
LOG (INFO) << GREEN << "AMC13 successfully configured!" << RESET ;
}
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)