Newer
Older
TB_Chris / TbKernel / src / .svn / text-base / TbPixelSvc.cpp.svn-base
  1. #include <algorithm>
  2. #include <fstream>
  3. #include <sstream>
  4.  
  5. // Local
  6. #include "TbKernel/TbConstants.h"
  7. #include "TbKernel/TbCondFile.h"
  8. #include "TbKernel/ITbDataSvc.h"
  9. #include "TbPixelSvc.h"
  10.  
  11. DECLARE_SERVICE_FACTORY(TbPixelSvc)
  12.  
  13. //============================================================================
  14. // Constructor
  15. //============================================================================
  16. TbPixelSvc::TbPixelSvc(const std::string& name, ISvcLocator* svc)
  17. : base_class(name, svc), m_geomSvc(nullptr), m_msg(nullptr) {
  18. declareProperty("WriteTrimDACs", m_writeTrimDACs = false);
  19. }
  20.  
  21. //============================================================================
  22. // Destructor
  23. //============================================================================
  24. TbPixelSvc::~TbPixelSvc() {
  25.  
  26. // Delete the message service.
  27. if (m_msg) delete m_msg;
  28. }
  29.  
  30. //============================================================================
  31. // Initialisation
  32. //============================================================================
  33. StatusCode TbPixelSvc::initialize() {
  34.  
  35. StatusCode sc = Service::initialize();
  36. if (!sc.isSuccess()) return sc;
  37. // Get the number of chips.
  38. const unsigned int nDevices = geomSvc()->nDevices();
  39. m_pixelConfiguration.resize(nDevices);
  40.  
  41. m_protectPhase = std::vector<bool>(nDevices, 0);
  42. for (unsigned int i = 0; i < nDevices; ++i) {
  43. m_pixelConfiguration[i].resize(Tb::NPixels, PixelConfig());
  44. }
  45. // Retrieve the names of the configuration files to be parsed.
  46. ITbDataSvc* dataSvc = Gaudi::svcLocator()->service<ITbDataSvc>("TbDataSvc");
  47. std::vector<std::string> files = dataSvc->getPixelConfig();
  48. files.push_back(dataSvc->getTimingConfig());
  49. for (auto& f : files) {
  50. if (f == "") continue;
  51. msg() << MSG::INFO << "Importing pixel configuration from " << f << endmsg;
  52. // Import conditions from configuration file.
  53. if (!readConditions(f)) {
  54. msg() << MSG::ERROR << "Cannot import pixel configuration" << endmsg;
  55. return StatusCode::FAILURE;
  56. }
  57. }
  58. return StatusCode::SUCCESS;
  59. }
  60.  
  61. //============================================================================
  62. // Add a constant offset in time to a single super column
  63. //============================================================================
  64. void TbPixelSvc::addOffset(const int offset, const unsigned int device,
  65. const unsigned int dcol) {
  66.  
  67. for (unsigned int pix = 0; pix < 512; ++pix) {
  68. const unsigned int address = pix + (0xFE00 & (dcol << 9));
  69. m_pixelConfiguration[device][address].tOffset += offset;
  70. }
  71. }
  72.  
  73. //============================================================================
  74. // Export trim DACs and masked pixel flags to a text file
  75. //============================================================================
  76. void TbPixelSvc::writeTrimDAC(const unsigned int device) {
  77. std::ofstream trimdac;
  78. trimdac.open(("plane_" + std::to_string(device) + "_trimdac.txt").c_str());
  79. trimdac << "#col row trim mask tp_ena " << std::endl;
  80. for (unsigned int col = 0; col < Tb::NCols; ++col) {
  81. for (unsigned int row = 0; row < Tb::NRows; ++row) {
  82. const unsigned int pixel = address(col, row);
  83. trimdac << std::setw(3) << col << std::setw(4) << row << std::setw(4)
  84. << (int)(m_pixelConfiguration[device][pixel].trim) << std::setw(4)
  85. << m_pixelConfiguration[device][pixel].trimDac_isMasked
  86. << std::setw(4) << m_pixelConfiguration[device][pixel].tp_ena
  87. << std::endl;
  88. }
  89. }
  90. trimdac.close();
  91. }
  92.  
  93. //============================================================================
  94. // Set trim DACs for the entire pixel matrix of a chip
  95. //============================================================================
  96. void TbPixelSvc::setTrim(const unsigned int device, const char* data) {
  97. for (unsigned int col = 0; col < Tb::NCols; ++col) {
  98. for (unsigned int row = 0; row < Tb::NRows; ++row) {
  99. const unsigned int pixel = address(col, row);
  100. const uint8_t word = *(data + col + Tb::NRows * row);
  101. m_pixelConfiguration[device][pixel].trim = 0xF & (word >> 1);
  102. m_pixelConfiguration[device][pixel].tp_ena = 0x1 & (word >> 5);
  103. m_pixelConfiguration[device][pixel].trimDac_isMasked = 0x1 & word;
  104. }
  105. }
  106. if (m_writeTrimDACs) writeTrimDAC(device);
  107. }
  108.  
  109. void TbPixelSvc::resetClockPhase(const unsigned int device) {
  110.  
  111. for (unsigned int pixel = 0; pixel < Tb::NPixels; ++pixel) {
  112. m_pixelConfiguration[device][pixel].tOffset = 0;
  113. }
  114. }
  115.  
  116. //============================================================================
  117. // Calculate the clock phase correction.
  118. //============================================================================
  119. void TbPixelSvc::setPhase(const unsigned int device,
  120. const unsigned int pll_config = 1024,
  121. const int amplitude = 1) {
  122. if (m_protectPhase[device]) return;
  123. const unsigned int phase = pow(2, (pll_config & 0x1C0) >> 6);
  124. if (phase == 1) return;
  125.  
  126. for (unsigned int pixel = 0; pixel < Tb::NPixels; ++pixel) {
  127. // Decode the pixel address, first the double column.
  128. const unsigned int dcol = (0xFE00 & pixel) >> 9;
  129. // Get the pixel within the super pixel.
  130. const unsigned int pix = (0x0007 & pixel);
  131. // Calculate the column number.
  132. const unsigned int col = 2 * dcol + pix / 4;
  133. // col = col % 128;
  134. int dt = 0;
  135. if (phase == 16) {
  136. dt = (-((16 - ((col / 2) % 16)) % 16)) << 8;
  137. } else if (phase == 4) {
  138. dt = (-4 * ((4 - ((col / 2) % 4)) % 4)) << 8;
  139. } else if (phase == 2) {
  140. dt = (((col % 4) < 2) ? 8 : 0) << 8;
  141. }
  142. m_pixelConfiguration[device][pixel].tOffset += amplitude * dt;
  143. }
  144. m_protectPhase[device] = true;
  145. }
  146.  
  147. //============================================================================
  148. // Import pixel conditions from configuration file
  149. //============================================================================
  150. bool TbPixelSvc::readConditions(const std::string& filename) {
  151.  
  152. TbCondFile f(filename);
  153. if (!f.is_open()) {
  154. msg() << MSG::WARNING << "Cannot open " << filename << endmsg;
  155. return false;
  156. }
  157. std::string mode = "";
  158. std::string chip = "";
  159. int deviceIndex = -1;
  160. unsigned int col(0), row(0);
  161. std::vector<unsigned int> badPixels;
  162. while (!f.eof()) {
  163. std::string line = "";
  164. if (!f.getLine(line)) continue;
  165. if (line.find("Charge") != std::string::npos) {
  166. f.split(line, ' ', mode, chip);
  167. deviceIndex = geomSvc()->deviceIndex(chip);
  168. if (deviceIndex == 999) {
  169. msg() << MSG::ERROR << "Device " << chip
  170. << " is not in the alignment file" << endmsg;
  171. msg() << MSG::ERROR << "Stop parsing " << filename << endmsg;
  172. break;
  173. }
  174. } else if (line.find("Mask") != std::string::npos ||
  175. line.find("Offset") != std::string::npos ||
  176. line.find("Timing") != std::string::npos ||
  177. line.find("GlobalCharge") != std::string::npos ||
  178. line.find("PLL") != std::string::npos) {
  179. mode = line;
  180. } else if (mode == "Charge") {
  181. float a(0.), b(0.), c(0.), t(0.);
  182. f.split(line, ' ', col, row, a, b, c, t);
  183. const unsigned int pixel = address(col, row);
  184.  
  185. if( isnan(a) || isinf(a) || isnan(b) || isnan(c) || isnan(t) || isinf(b) || isinf(c) || isinf(t)){
  186. badPixels.push_back(pixel);
  187. }
  188. m_pixelConfiguration[deviceIndex][pixel].p0 = a;
  189. m_pixelConfiguration[deviceIndex][pixel].p1 = b;
  190. m_pixelConfiguration[deviceIndex][pixel].c = c;
  191. m_pixelConfiguration[deviceIndex][pixel].t = t;
  192. } else if (mode == "Mask") {
  193. f.split(line, ' ', chip, col, row);
  194. deviceIndex = geomSvc()->deviceIndex(chip);
  195. if (deviceIndex == 999) {
  196. msg() << MSG::ERROR << "Device " << chip
  197. << " is not in the alignment file" << endmsg;
  198. continue;
  199. }
  200. const unsigned int pixel = address(col, row);
  201. msg() << MSG::INFO << "Masking pixel " << format("0x%04x", pixel)
  202. << format(" (column %3d", col) << format(", row %3d)", row)
  203. << " on device " << chip << endmsg;
  204. m_pixelConfiguration[deviceIndex][pixel].isMasked = true;
  205. } else if (mode == "GlobalCharge") {
  206. double a(0.), b(0.), c(0.), t(0.);
  207. f.split(line, ' ', chip, a, b, c, t);
  208. // if( isnan(a) || isnan(b) || isnan(c) || isnan(d) )
  209.  
  210. deviceIndex = geomSvc()->deviceIndex(chip);
  211. if (deviceIndex == 999) {
  212. msg() << MSG::ERROR << "Device " << chip
  213. << " is not in the alignment file" << endmsg;
  214. continue;
  215. }
  216. for (auto& pixel : m_pixelConfiguration[deviceIndex]) {
  217. pixel.p0 = a;
  218. pixel.p1 = b;
  219. pixel.c = c;
  220. pixel.t = t;
  221. }
  222. msg() << MSG::INFO << "Applying global charge calibration on device "
  223. << chip << "(a = " << a << ", b = " << b << ", c = " << c
  224. << ", t = " << t << ")" << endmsg;
  225. } else if (mode == "Offset") {
  226. int offset = 0;
  227. f.split(line, ' ', chip, col, offset);
  228. deviceIndex = geomSvc()->deviceIndex(chip);
  229. if (deviceIndex == 999) {
  230. msg() << MSG::ERROR << "Device " << chip
  231. << " is not in the alignment file" << endmsg;
  232. continue;
  233. }
  234. msg() << MSG::INFO << "Adding time offset " << offset * 25 << " ns "
  235. << "to double column " << col << " on chip " << chip << endmsg;
  236. addOffset(offset * Tb::ToA, deviceIndex, col);
  237. } else if (mode == "Timing") {
  238. double dt = 0.;
  239. f.split(line, ' ', chip, dt);
  240. deviceIndex = geomSvc()->deviceIndex(chip);
  241. if (deviceIndex == 999) {
  242. msg() << MSG::ERROR << "Device " << chip
  243. << " is not in the alignment file" << endmsg;
  244. continue;
  245. }
  246. const int offset = static_cast<int>(std::round(dt * Tb::nanosecond));
  247. msg() << MSG::INFO << "Adding time offset " << dt << " ns (" << offset
  248. << " time units) to chip " << chip << endmsg;
  249. const unsigned int nDCols = Tb::NCols / 2;
  250. for (unsigned int col = 0; col < nDCols; ++col) {
  251. addOffset(offset, deviceIndex, col);
  252. }
  253. } else if (mode == "PLL") {
  254. int amplitude = 0.;
  255. unsigned int pll_mode;
  256. f.split(line, ' ', chip, pll_mode, amplitude);
  257. deviceIndex = geomSvc()->deviceIndex(chip);
  258. if (deviceIndex == 999) {
  259. msg() << MSG::ERROR << "Device " << chip
  260. << " is not in the alignment file" << endmsg;
  261. continue;
  262. }
  263. msg() << MSG::INFO << "Overwriting PLL CONFIG for chip " << chip
  264. << endmsg;
  265. m_protectPhase[deviceIndex] = false;
  266. resetClockPhase(deviceIndex);
  267. setPhase(deviceIndex, pll_mode, amplitude);
  268. }
  269. }
  270. for( auto& pixel : badPixels ){
  271. auto pos = posFromAddress(pixel);
  272. float avgt(0), avgc(0), avgp0(0), avgp1(0);
  273. unsigned int nPixels=0;
  274. if( pos.second != 255 ){
  275. unsigned int neighbour = address( pos.first, pos.second+1 );
  276. if( std::find( badPixels.begin(), badPixels.end(), neighbour) == badPixels.end() ){
  277. avgt += m_pixelConfiguration[deviceIndex][neighbour].t;
  278. avgc += m_pixelConfiguration[deviceIndex][neighbour].c;
  279. avgp0 += m_pixelConfiguration[deviceIndex][neighbour].p0;
  280. avgp1 += m_pixelConfiguration[deviceIndex][neighbour].p1;
  281. nPixels++;
  282. }
  283. }
  284. if( pos.second != 0 ){
  285. unsigned int neighbour = address( pos.first, pos.second-1 );
  286. if( std::find( badPixels.begin(), badPixels.end(), neighbour) == badPixels.end() ){
  287. avgt += m_pixelConfiguration[deviceIndex][neighbour].t;
  288. avgc += m_pixelConfiguration[deviceIndex][neighbour].c;
  289. avgp0 += m_pixelConfiguration[deviceIndex][neighbour].p0;
  290. avgp1 += m_pixelConfiguration[deviceIndex][neighbour].p1;
  291. nPixels++;
  292. }
  293. }
  294. if(nPixels==0){
  295. m_pixelConfiguration[deviceIndex][pixel].isMasked = true;
  296. // printConfig( deviceIndex, pixel ) ;
  297. continue;
  298. }
  299. m_pixelConfiguration[deviceIndex][pixel].t = avgt / (float)nPixels;
  300. m_pixelConfiguration[deviceIndex][pixel].p0 = avgp0 / (float)nPixels;
  301. m_pixelConfiguration[deviceIndex][pixel].p1 = avgp1 / (float)nPixels;
  302. m_pixelConfiguration[deviceIndex][pixel].c = avgc / (float)nPixels;
  303. //printConfig( deviceIndex, pixel ) ;
  304. }
  305. f.close();
  306. return true;
  307. }