ROOT logo
// constants
static const int fgkEmCalRows = 24; // number of rows per module for EMCAL
static const int fgkEmCalCols = 48; // number of columns per module for EMCAL

const int NRCU = 2; // per SM
const int NBranch = 2; // per RCU
const int NFEC = 9; // per branch, labelled 1..9
const int NCSP = 32; // per FEC

// conversion between DAC (0-0x3ff) and HV values (V):
// hv = hvmin + prop*DAC; values from PHOS manual, and used in Houston/Catania
const float hvmin = 209.9;
const float prop = 0.2022; 

// some global variables
Float_t biasVoltage[NRCU][NBranch][NFEC][NCSP]; 
int towerCol[NRCU][NBranch][NFEC][NCSP]; 
int towerRow[NRCU][NBranch][NFEC][NCSP]; 

//__________________________________________________________
void Tower2FEEBiasInfo(const char *inputFileName)
{
  ifstream inputFile(inputFileName);
  int ic, ir;
  Float_t ival;
  int ircu, ibranch, card, icsp;
  for (int icol=0; icol<fgkEmCalCols; icol++) {
    for (int irow=0; irow<fgkEmCalRows; irow++) {
      inputFile >> ic >> ir >> ival;

      // could check here that ic && ir match with icol && irow, but should not be needed

      // translate to FEE type indices
      Tower2FEEMap(ic, ir, 
		   &ircu, &ibranch, &card, &icsp);

      // debug
      /*
      printf("ic %d ir %d ircu %d ibranch %d card %d icsp %d\n",
	     ic, ir, ircu, ibranch, card, icsp);
      */

      // store value
      biasVoltage[ircu][ibranch][card][icsp] = ival;
      towerCol[ircu][ibranch][card][icsp] = ic;
      towerRow[ircu][ibranch][card][icsp] = ir;
    }
  }

  inputFile.close();

  return;
}

//__________________________________________________________
void Tower2FEEMap(const int icol, const int irow,
		  int *ircu, int *ibranch, int *card, int *icsp)
{ /*
    If you are interested in where these magic numbers come from -
    See mapping info on 
    http://dsilverm.web.cern.ch/dsilverm/mapping/emcal_mapping.html
    http://dsilverm.web.cern.ch/dsilverm/mapping/ppt/Coordinates_and_Mapping.pdf
   */

  // each FEC covers a 4x8 tower area
  int C = irow/8; // Cable bundle
  int FEC = C*12 + icol/4; // FEC in 0..35 range

  *ircu = FEC / 18; // 18 FEC per RCU
  *ibranch = (FEC%18) / 9;
  *card = FEC % 9;  

  // columns and rows within an FEC area
  int tCol = icol%4;
  int tRow = irow%8;

  // The mapping to CSP is a bit complicated so I also define two more help variables here..
  // which T-card?
  int TCard = tCol/2; // 0=Top (even StripModules), 1=Bottom (odd StripModules)
  int locCol = tCol%2;  // local column inside T-card 

  *icsp = (7 - tRow) + locCol*16 + TCard*8;
}

/* Main method.. */
//__________________________________________________________
void DCSGenerateAPD(const char *inputFileName,
		    const char *outputDir,
		    const int readBack=0,
		    const int RCUFWVersion=1, // default as of May 2009 is RCU FWv2
		    const int FEEBCVersion=1) // default as of May 2009 is PCM4
{

  // set up which bias voltage should be applicable for which CSP..
  Tower2FEEBiasInfo(inputFileName);

  // general setup block: try to keep magic numbers/registers collected here
  const char *branch_str[] = { "A", "B"};
  const int nRCUFW = 2;
  const char *rcufw_str[] = { "v1", "v2"};
  const int rcu_addr_start[nRCUFW] = {0x7000, 0x0000}; 
  const int read_header[nRCUFW] = {0x520000, 0x020000}; 
  const int write_header[nRCUFW] = {0x620000, 0x220000}; 
  const int voltage_value_start[nRCUFW] = {0x700000, 0x200000}; 
  const int rcu_endmem[nRCUFW] = {0x390000, 0x3F0000}; 
  const int rcu_exeseq[nRCUFW] = {0x0, 0x5304}; 
  const int rcu_result_reg[nRCUFW] = {0x6000, 0x2000}; 

  const int nFEEBC = 2;
  const char *feebc_str[] = { "PCM3", "PCM4"};
  const int trailer_offset[nFEEBC] = {0x48, 0x68};
  const int update_voltage_register = 0x1E;
  const int max_dac_value = 0x3FF;

  printf("DCSGenerateAPD: RCU FW %s, FEE BC %s\n", 
	 rcufw_str[RCUFWVersion], feebc_str[FEEBCVersion]);

  // resulting voltage settings should be good within a few volts 
  cout << " HV-DAC prop. constant = " << prop << endl;
  char iv_dac_setting[100]; 
  
  char cfile[200];

  FILE* fout_setbias_card[NRCU][NBranch][NFEC];
  FILE* fout_readbias_card[NRCU][NBranch][NFEC];
  
  // end of setup, let's go..
  
  int rcu_addr_card = rcu_addr_start[RCUFWVersion];
  int csp_addr = trailer_offset[FEEBCVersion];
  int word = 0;
  char comment[400];
  
  int rcu_addr_read = rcu_addr_start[RCUFWVersion]; // we'll also write the readbias file in the same loop, so
  // need a separate index also

  for (int rcu=0; rcu<NRCU; rcu++) {
    for (int branch=0; branch<NBranch; branch++) {
      for (int ifec=0; ifec<NFEC; ifec++) {
	int card = ifec;
	int icard = ifec+1;

	sprintf(cfile,"%s/set_rcu_%d_bias_branch_%s_FEC_%d.scr",
		outputDir, rcu, 
		branch_str[branch], icard);
	fout_setbias_card[rcu][branch][card] = fopen(cfile, "w");

	sprintf(cfile,"%s/read_rcu_%d_bias_branch_%s_FEC_%d.scr", 
		outputDir, rcu,
		branch_str[branch], icard);
	fout_readbias_card[rcu][branch][card] = fopen(cfile, "w");

	rcu_addr_card = rcu_addr_start[RCUFWVersion];
	rcu_addr_read = rcu_addr_start[RCUFWVersion];

	for (int icsp = 0; icsp<NCSP; icsp++) {
	  
	  /* 
	     some funkiness to address the CSPs correctly follows here. 
	     DS verified this with section 16.1 "Bias voltage programming", table 8
	     of H. Muller's PHOS manual (version from Jan 2007) 
	  */ 
	  if (icsp<16) { csp_addr = trailer_offset[FEEBCVersion] + icsp; }
	  else { csp_addr = trailer_offset[FEEBCVersion] - 1 - (icsp%16); }
	  if (icsp >= 24) csp_addr += 0x20;

	  // what does the desired voltage (in V) correspond to in DAC?
	  int iv_dac = (int)( (biasVoltage[rcu][branch][card][icsp] - hvmin)/prop + 0.5); // round-off
	  if (iv_dac > max_dac_value) iv_dac = max_dac_value;
	  sprintf(iv_dac_setting,"%06X", voltage_value_start[RCUFWVersion] + iv_dac);

	  // set up instructions that should be written
	  word = write_header[RCUFWVersion] | (branch << 16) | (icard << 12) | (csp_addr);

	  // write a long comment with all info for this CSP
	  sprintf(comment, "# RCU %d, Branch %s, FEC %d, CSP %02d - Tower Col %02d, Row %02d ", 
		  rcu, branch_str[branch], icard, icsp,
		  towerCol[rcu][branch][card][icsp],
		  towerRow[rcu][branch][card][icsp]
		  );  
	
	  fprintf(fout_setbias_card[rcu][branch][card], "w 0x%04X 0x%6X   %s\n",
		  rcu_addr_card, word, comment);
	  rcu_addr_card++;

	  fprintf(fout_setbias_card[rcu][branch][card], "w 0x%04X 0x%s   # Set Voltage: %4.1f V, DAC %d (hex: %03X)\n", 
		  rcu_addr_card, iv_dac_setting, 
		  biasVoltage[rcu][branch][card][icsp], 
		  iv_dac, iv_dac
		  );
	  rcu_addr_card++;

	  // slighly modified comment for read command - include voltage info
	  sprintf(comment, "# RCU %d, Branch %s, FEC %d, CSP %02d - Tower Col %02d, Row %02d : %4.1f V, DAC %d (hex: %03X)", 
		  rcu, branch_str[branch], icard, icsp,
		  towerCol[rcu][branch][card][icsp],
		  towerRow[rcu][branch][card][icsp],
		  biasVoltage[rcu][branch][card][icsp], 
		  iv_dac, iv_dac
		  );  

	  word = read_header[RCUFWVersion] | (branch << 16) | (icard << 12) | (csp_addr);
	  fprintf(fout_readbias_card[rcu][branch][card], "w 0x%04X 0x%06X  %s\n", rcu_addr_read, word, comment);
	  rcu_addr_read++;
	} // csp loop
	
	// after CSP per card; send update command
	word = write_header[RCUFWVersion] | (branch << 16) | (icard << 12) | update_voltage_register;
	fprintf(fout_setbias_card[rcu][branch][card],"w 0x%04X 0x%06X   # Update Voltages\n", 
		rcu_addr_card, word); 
	rcu_addr_card++;
	fprintf(fout_setbias_card[rcu][branch][card],"w 0x%04X 0x%06X   \n", 
		rcu_addr_card, voltage_value_start[RCUFWVersion]);
	rcu_addr_card++;

	// also put ending for the individual card files:
	fprintf(fout_setbias_card[rcu][branch][card],"w 0x%04X 0x%06X   # End of the instruction memory\n", 
		rcu_addr_card, rcu_endmem[RCUFWVersion]);
	rcu_addr_card++;
      
	fprintf(fout_setbias_card[rcu][branch][card],"wait 100 us\n");
	fprintf(fout_setbias_card[rcu][branch][card],"w 0x%X 0x0           # execute and update registers\n",
		rcu_exeseq[RCUFWVersion]);
	if (RCUFWVersion == 0) { // specialty for old FW version
	  fprintf(fout_setbias_card[rcu][branch][card],"wait 100 us\n");
	  fprintf(fout_setbias_card[rcu][branch][card],"r 0x7800            # error checking\n");
	  fprintf(fout_setbias_card[rcu][branch][card],"w 0x6c01 0x 0       # clear registers\n");
	}

	// in case we want to check what was written
	if (readBack) {
	  fprintf(fout_setbias_card[rcu][branch][card],"wait 100 us\n");
	  fprintf(fout_setbias_card[rcu][branch][card],"b %s      # read-back the values also\n", cfile);
	  fprintf(fout_setbias_card[rcu][branch][card],"wait 100 us\n");
	}

	// close down output files (set)
	fclose(fout_setbias_card[rcu][branch][card]);
	
	// readbias ending
	fprintf(fout_readbias_card[rcu][branch][card],"w 0x%04X 0x%06X \n", 
		rcu_addr_read, rcu_endmem[RCUFWVersion]);
	rcu_addr_read++;

	fprintf(fout_readbias_card[rcu][branch][card],"wait 1 us\n");
	fprintf(fout_readbias_card[rcu][branch][card],"w 0x%X 0x0           # execute and update registers\n",
		rcu_exeseq[RCUFWVersion]);

	fprintf(fout_readbias_card[rcu][branch][card],"wait 1 us\n");
	int nRead = NCSP*2; // new FW reads back i/o 
	if (RCUFWVersion == 0) { // specialty for old FW version
	  fprintf(fout_readbias_card[rcu][branch][card],"r 0x7800            # error checking\n");
	  fprintf(fout_readbias_card[rcu][branch][card],"wait 1 us\n");
	  nRead = NCSP;
	}
	fprintf(fout_readbias_card[rcu][branch][card],"r 0x%04X %d( \n", rcu_result_reg[RCUFWVersion], nRead);
	if (RCUFWVersion == 0) { // specialty for old FW version
	  fprintf(fout_readbias_card[rcu][branch][card],"wait 1 us\n");
	  fprintf(fout_readbias_card[rcu][branch][card],"r 0x7800            # error checking\n");
	  fprintf(fout_readbias_card[rcu][branch][card],"w 0x6c01 0x 0       # clear registers\n");
	}

	// close down output files (read)
	fclose(fout_readbias_card[rcu][branch][card]);

      } // card=FEC
    } // branch
  } // rcu

}
 DCSGenerateAPD.C:1
 DCSGenerateAPD.C:2
 DCSGenerateAPD.C:3
 DCSGenerateAPD.C:4
 DCSGenerateAPD.C:5
 DCSGenerateAPD.C:6
 DCSGenerateAPD.C:7
 DCSGenerateAPD.C:8
 DCSGenerateAPD.C:9
 DCSGenerateAPD.C:10
 DCSGenerateAPD.C:11
 DCSGenerateAPD.C:12
 DCSGenerateAPD.C:13
 DCSGenerateAPD.C:14
 DCSGenerateAPD.C:15
 DCSGenerateAPD.C:16
 DCSGenerateAPD.C:17
 DCSGenerateAPD.C:18
 DCSGenerateAPD.C:19
 DCSGenerateAPD.C:20
 DCSGenerateAPD.C:21
 DCSGenerateAPD.C:22
 DCSGenerateAPD.C:23
 DCSGenerateAPD.C:24
 DCSGenerateAPD.C:25
 DCSGenerateAPD.C:26
 DCSGenerateAPD.C:27
 DCSGenerateAPD.C:28
 DCSGenerateAPD.C:29
 DCSGenerateAPD.C:30
 DCSGenerateAPD.C:31
 DCSGenerateAPD.C:32
 DCSGenerateAPD.C:33
 DCSGenerateAPD.C:34
 DCSGenerateAPD.C:35
 DCSGenerateAPD.C:36
 DCSGenerateAPD.C:37
 DCSGenerateAPD.C:38
 DCSGenerateAPD.C:39
 DCSGenerateAPD.C:40
 DCSGenerateAPD.C:41
 DCSGenerateAPD.C:42
 DCSGenerateAPD.C:43
 DCSGenerateAPD.C:44
 DCSGenerateAPD.C:45
 DCSGenerateAPD.C:46
 DCSGenerateAPD.C:47
 DCSGenerateAPD.C:48
 DCSGenerateAPD.C:49
 DCSGenerateAPD.C:50
 DCSGenerateAPD.C:51
 DCSGenerateAPD.C:52
 DCSGenerateAPD.C:53
 DCSGenerateAPD.C:54
 DCSGenerateAPD.C:55
 DCSGenerateAPD.C:56
 DCSGenerateAPD.C:57
 DCSGenerateAPD.C:58
 DCSGenerateAPD.C:59
 DCSGenerateAPD.C:60
 DCSGenerateAPD.C:61
 DCSGenerateAPD.C:62
 DCSGenerateAPD.C:63
 DCSGenerateAPD.C:64
 DCSGenerateAPD.C:65
 DCSGenerateAPD.C:66
 DCSGenerateAPD.C:67
 DCSGenerateAPD.C:68
 DCSGenerateAPD.C:69
 DCSGenerateAPD.C:70
 DCSGenerateAPD.C:71
 DCSGenerateAPD.C:72
 DCSGenerateAPD.C:73
 DCSGenerateAPD.C:74
 DCSGenerateAPD.C:75
 DCSGenerateAPD.C:76
 DCSGenerateAPD.C:77
 DCSGenerateAPD.C:78
 DCSGenerateAPD.C:79
 DCSGenerateAPD.C:80
 DCSGenerateAPD.C:81
 DCSGenerateAPD.C:82
 DCSGenerateAPD.C:83
 DCSGenerateAPD.C:84
 DCSGenerateAPD.C:85
 DCSGenerateAPD.C:86
 DCSGenerateAPD.C:87
 DCSGenerateAPD.C:88
 DCSGenerateAPD.C:89
 DCSGenerateAPD.C:90
 DCSGenerateAPD.C:91
 DCSGenerateAPD.C:92
 DCSGenerateAPD.C:93
 DCSGenerateAPD.C:94
 DCSGenerateAPD.C:95
 DCSGenerateAPD.C:96
 DCSGenerateAPD.C:97
 DCSGenerateAPD.C:98
 DCSGenerateAPD.C:99
 DCSGenerateAPD.C:100
 DCSGenerateAPD.C:101
 DCSGenerateAPD.C:102
 DCSGenerateAPD.C:103
 DCSGenerateAPD.C:104
 DCSGenerateAPD.C:105
 DCSGenerateAPD.C:106
 DCSGenerateAPD.C:107
 DCSGenerateAPD.C:108
 DCSGenerateAPD.C:109
 DCSGenerateAPD.C:110
 DCSGenerateAPD.C:111
 DCSGenerateAPD.C:112
 DCSGenerateAPD.C:113
 DCSGenerateAPD.C:114
 DCSGenerateAPD.C:115
 DCSGenerateAPD.C:116
 DCSGenerateAPD.C:117
 DCSGenerateAPD.C:118
 DCSGenerateAPD.C:119
 DCSGenerateAPD.C:120
 DCSGenerateAPD.C:121
 DCSGenerateAPD.C:122
 DCSGenerateAPD.C:123
 DCSGenerateAPD.C:124
 DCSGenerateAPD.C:125
 DCSGenerateAPD.C:126
 DCSGenerateAPD.C:127
 DCSGenerateAPD.C:128
 DCSGenerateAPD.C:129
 DCSGenerateAPD.C:130
 DCSGenerateAPD.C:131
 DCSGenerateAPD.C:132
 DCSGenerateAPD.C:133
 DCSGenerateAPD.C:134
 DCSGenerateAPD.C:135
 DCSGenerateAPD.C:136
 DCSGenerateAPD.C:137
 DCSGenerateAPD.C:138
 DCSGenerateAPD.C:139
 DCSGenerateAPD.C:140
 DCSGenerateAPD.C:141
 DCSGenerateAPD.C:142
 DCSGenerateAPD.C:143
 DCSGenerateAPD.C:144
 DCSGenerateAPD.C:145
 DCSGenerateAPD.C:146
 DCSGenerateAPD.C:147
 DCSGenerateAPD.C:148
 DCSGenerateAPD.C:149
 DCSGenerateAPD.C:150
 DCSGenerateAPD.C:151
 DCSGenerateAPD.C:152
 DCSGenerateAPD.C:153
 DCSGenerateAPD.C:154
 DCSGenerateAPD.C:155
 DCSGenerateAPD.C:156
 DCSGenerateAPD.C:157
 DCSGenerateAPD.C:158
 DCSGenerateAPD.C:159
 DCSGenerateAPD.C:160
 DCSGenerateAPD.C:161
 DCSGenerateAPD.C:162
 DCSGenerateAPD.C:163
 DCSGenerateAPD.C:164
 DCSGenerateAPD.C:165
 DCSGenerateAPD.C:166
 DCSGenerateAPD.C:167
 DCSGenerateAPD.C:168
 DCSGenerateAPD.C:169
 DCSGenerateAPD.C:170
 DCSGenerateAPD.C:171
 DCSGenerateAPD.C:172
 DCSGenerateAPD.C:173
 DCSGenerateAPD.C:174
 DCSGenerateAPD.C:175
 DCSGenerateAPD.C:176
 DCSGenerateAPD.C:177
 DCSGenerateAPD.C:178
 DCSGenerateAPD.C:179
 DCSGenerateAPD.C:180
 DCSGenerateAPD.C:181
 DCSGenerateAPD.C:182
 DCSGenerateAPD.C:183
 DCSGenerateAPD.C:184
 DCSGenerateAPD.C:185
 DCSGenerateAPD.C:186
 DCSGenerateAPD.C:187
 DCSGenerateAPD.C:188
 DCSGenerateAPD.C:189
 DCSGenerateAPD.C:190
 DCSGenerateAPD.C:191
 DCSGenerateAPD.C:192
 DCSGenerateAPD.C:193
 DCSGenerateAPD.C:194
 DCSGenerateAPD.C:195
 DCSGenerateAPD.C:196
 DCSGenerateAPD.C:197
 DCSGenerateAPD.C:198
 DCSGenerateAPD.C:199
 DCSGenerateAPD.C:200
 DCSGenerateAPD.C:201
 DCSGenerateAPD.C:202
 DCSGenerateAPD.C:203
 DCSGenerateAPD.C:204
 DCSGenerateAPD.C:205
 DCSGenerateAPD.C:206
 DCSGenerateAPD.C:207
 DCSGenerateAPD.C:208
 DCSGenerateAPD.C:209
 DCSGenerateAPD.C:210
 DCSGenerateAPD.C:211
 DCSGenerateAPD.C:212
 DCSGenerateAPD.C:213
 DCSGenerateAPD.C:214
 DCSGenerateAPD.C:215
 DCSGenerateAPD.C:216
 DCSGenerateAPD.C:217
 DCSGenerateAPD.C:218
 DCSGenerateAPD.C:219
 DCSGenerateAPD.C:220
 DCSGenerateAPD.C:221
 DCSGenerateAPD.C:222
 DCSGenerateAPD.C:223
 DCSGenerateAPD.C:224
 DCSGenerateAPD.C:225
 DCSGenerateAPD.C:226
 DCSGenerateAPD.C:227
 DCSGenerateAPD.C:228
 DCSGenerateAPD.C:229
 DCSGenerateAPD.C:230
 DCSGenerateAPD.C:231
 DCSGenerateAPD.C:232
 DCSGenerateAPD.C:233
 DCSGenerateAPD.C:234
 DCSGenerateAPD.C:235
 DCSGenerateAPD.C:236
 DCSGenerateAPD.C:237
 DCSGenerateAPD.C:238
 DCSGenerateAPD.C:239
 DCSGenerateAPD.C:240
 DCSGenerateAPD.C:241
 DCSGenerateAPD.C:242
 DCSGenerateAPD.C:243
 DCSGenerateAPD.C:244
 DCSGenerateAPD.C:245
 DCSGenerateAPD.C:246
 DCSGenerateAPD.C:247
 DCSGenerateAPD.C:248
 DCSGenerateAPD.C:249
 DCSGenerateAPD.C:250
 DCSGenerateAPD.C:251
 DCSGenerateAPD.C:252
 DCSGenerateAPD.C:253
 DCSGenerateAPD.C:254
 DCSGenerateAPD.C:255
 DCSGenerateAPD.C:256
 DCSGenerateAPD.C:257
 DCSGenerateAPD.C:258
 DCSGenerateAPD.C:259
 DCSGenerateAPD.C:260
 DCSGenerateAPD.C:261
 DCSGenerateAPD.C:262
 DCSGenerateAPD.C:263
 DCSGenerateAPD.C:264
 DCSGenerateAPD.C:265
 DCSGenerateAPD.C:266
 DCSGenerateAPD.C:267
 DCSGenerateAPD.C:268
 DCSGenerateAPD.C:269
 DCSGenerateAPD.C:270
 DCSGenerateAPD.C:271