- #ifndef TBPIXELSVC_H
- #define TBPIXELSVC_H
-
- // Gaudi
- #include "GaudiKernel/Service.h"
- #include "GaudiKernel/Bootstrap.h"
- #include "GaudiKernel/MsgStream.h"
-
- // Local
- #include "TbKernel/ITbPixelSvc.h"
- #include "TbKernel/ITbGeometrySvc.h"
-
- #include <stdint.h>
-
- // struct PixelConfig;
- template <class TYPE>
- class SvcFactory;
-
- /** @class TbPixelSvc TbPixelSvc.h
- *
- * Implementation of the Timepix3 pixel configuration service.
- *
- */
-
- class TbPixelSvc : public extends1<Service, ITbPixelSvc> {
-
- public:
- /// Constructor
- TbPixelSvc(const std::string& name, ISvcLocator* svc);
- /// Destructor
- virtual ~TbPixelSvc();
-
- virtual StatusCode initialize();
-
- /// Get the pixel address for a given column and row.
- virtual unsigned int address(const unsigned int col,
- const unsigned int row) const {
- // Get the double-column and super-pixel.
- const unsigned int dcol = col / 2;
- const unsigned int spix = row / 4;
- // Get the pixel number within the superpixel.
- unsigned int pix = row % 4;
- if (1 == col % 2) pix += 4;
- return (dcol << 9) + (spix << 3) + pix;
- }
- std::pair<unsigned int, unsigned int> posFromAddress( const unsigned int& address ) const {
- std::pair<unsigned int, unsigned int> pos;
- // Decode the pixel address, first get the double column.
- const unsigned int dcol = (0xFE00 & address) >> 8;
- // Get the super pixel address.
- const unsigned int spix = (0x01F8 & address) >> 1;
- // Get the address of the pixel within the super pixel.
- const unsigned int pix = (0x0007 & address);
- // Calculate the row and column numbers.
- pos.first = dcol + pix / 4;
- pos.second = spix + (pix & 0x3);
- return pos;
- }
-
- /// Return whether the pixel has been masked.
- virtual bool isMasked(const unsigned int address,
- const unsigned int device) const {
- return m_pixelConfiguration[device][address].isMasked ||
- m_pixelConfiguration[device][address].trimDac_isMasked;
- }
-
- /// Correct the timestamp of a given hit.
- virtual void applyPhaseCorrection(LHCb::TbHit* h) {
- h->setTime(h->time() +
- m_pixelConfiguration[h->device()][h->pixelAddress()].tOffset);
- }
-
- /// Set the clock phase correction.
- virtual void setPhase(const unsigned int device,
- const unsigned int pll_config, const int amplitude);
-
- /// Set trim DACs.
- virtual void setTrim(const unsigned int device, const char* data);
-
- /// Convert time-over-threshold to charge.
- virtual double charge(const unsigned int tot, const unsigned int address,
- const unsigned int device) const {
- const PixelConfig& conf = m_pixelConfiguration[device][address];
- double value=inverseSurrogate(tot, conf.p1, conf.p0, conf.c, conf.t);
- if( isnan(value) ){
- auto pos = posFromAddress( address );
- warning() << "Pixel " << device << "/0x"
- << std::hex << address << std::dec << " tot = " << tot
- << " (" << pos.first << ", " << pos.second
- << ")" << conf.p1 << " " << conf.p0 << " " << conf.c << " " << conf.t << endmsg;
- return 1;
- }
- return value;
- }
-
- private:
- /// Allow SvcFactory to instantiate the service.
- friend class SvcFactory<TbPixelSvc>;
-
- struct PixelConfig {
- PixelConfig()
- : isMasked(false),
- trimDac_isMasked(false),
- isDead(false),
- tp_ena(0),
- trim(4),
- tOffset(0),
- p0(0),
- p1(1),
- c(0),
- t(0) {};
- bool isMasked;
- bool trimDac_isMasked;
- bool isDead;
- bool tp_ena;
- uint8_t trim;
- int tOffset;
- /// Parameters of surrogate function
- float p0;
- float p1;
- float c;
- float t;
- };
-
-
- void resetClockPhase(const unsigned int device);
- /// Add a constant offset in time to a single super column.
- void addOffset(const int offset, const unsigned int device,
- const unsigned int dcol);
-
- /// Pixel configuration for each chip
- std::vector<std::vector<PixelConfig> > m_pixelConfiguration;
-
- void printConfig( const unsigned int& plane, const unsigned int& address){
- auto pos = posFromAddress(address);
- PixelConfig& conf = m_pixelConfiguration[plane][address];
- info() << std::hex << "0x" << address << std::dec << " = ("<<pos.first << ", " << pos.second << ") : " << conf.p0 << " " << conf.p1 << " " << conf.c << " " << conf.t << endmsg;
- }
- /// Functionality to write out the trim dacs written into the header
- bool m_writeTrimDACs;
- void writeTrimDAC(const unsigned int device);
-
- /// ignore PLL config
- std::vector<bool> m_protectPhase;
- /// Surrogate function, taken from http://arxiv.org/pdf/1103.2739v3.pdf
- double surrogate(const double& charge, const double& a, const double& b,
- const double& c, const double& t) const {
- double result = 0.;
- const double r = (b + a * t);
- const double d = r * r + 4 * a * c;
- if (d > 0.) {
- const double itcpt = ((t * a - b) + sqrt(d)) / (2 * a);
- if (charge > itcpt) {
- result = a * charge + b - c / (charge - t);
- }
- }
- return result;
- }
-
- double inverseSurrogate(const uint32_t tot, const double a, const double b,
- const double c, const double t) const {
- double result = 1.;
- const double r = (b + a * t - tot);
- const double d = r * r + 4. * a * c;
- if (d > 0.) {
- result = (a * t + tot - b + sqrt(d)) / (2. * a);
- }
- return result;
- }
-
- bool readConditions(const std::string& file);
-
- /// Pointer to geometry service
- mutable ITbGeometrySvc* m_geomSvc;
- /// Access geometry service on-demand
- ITbGeometrySvc* geomSvc() const {
- if (!m_geomSvc) {
- m_geomSvc = Gaudi::svcLocator()->service<ITbGeometrySvc>("TbGeometrySvc");
- }
- return m_geomSvc;
- }
- /// Pointer to message stream
- mutable MsgStream* m_msg;
- /// On-demand access to message stream
- MsgStream& msg() const {
- if (!m_msg) m_msg = new MsgStream(msgSvc(), name());
- return *m_msg;
- }
- };
-
- #endif