2 static const int fgkEmCalRows = 24; // number of rows per module for EMCAL
3 static const int fgkEmCalCols = 48; // number of columns per module for EMCAL
5 const int NRCU = 2; // per SM
6 const int NBranch = 2; // per RCU
7 const int NFEC = 9; // per branch, labelled 1..9
8 const int NCSP = 32; // per FEC
10 // conversion between DAC (0-0x3ff) and HV values (V):
11 // hv = hvmin + prop*DAC; values from PHOS manual, and used in Houston/Catania
12 const float hvmin = 209.9;
13 const float prop = 0.2022;
15 // some global variables
16 Float_t biasVoltage[NRCU][NBranch][NFEC][NCSP];
17 int towerCol[NRCU][NBranch][NFEC][NCSP];
18 int towerRow[NRCU][NBranch][NFEC][NCSP];
20 //__________________________________________________________
21 void Tower2FEEBiasInfo(const char *inputFileName)
23 ifstream inputFile(inputFileName);
26 int ircu, ibranch, card, icsp;
27 for (int icol=0; icol<fgkEmCalCols; icol++) {
28 for (int irow=0; irow<fgkEmCalRows; irow++) {
29 inputFile >> ic >> ir >> ival;
31 // could check here that ic && ir match with icol && irow, but should not be needed
33 // translate to FEE type indices
35 &ircu, &ibranch, &card, &icsp);
39 printf("ic %d ir %d ircu %d ibranch %d card %d icsp %d\n",
40 ic, ir, ircu, ibranch, card, icsp);
44 biasVoltage[ircu][ibranch][card][icsp] = ival;
45 towerCol[ircu][ibranch][card][icsp] = ic;
46 towerRow[ircu][ibranch][card][icsp] = ir;
55 //__________________________________________________________
56 void Tower2FEEMap(const int icol, const int irow,
57 int *ircu, int *ibranch, int *card, int *icsp)
59 If you are interested in where these magic numbers come from -
61 http://dsilverm.web.cern.ch/dsilverm/mapping/emcal_mapping.html
62 http://dsilverm.web.cern.ch/dsilverm/mapping/ppt/Coordinates_and_Mapping.pdf
65 // each FEC covers a 4x8 tower area
66 int C = irow/8; // Cable bundle
67 int FEC = C*12 + icol/4; // FEC in 0..35 range
69 *ircu = FEC / 18; // 18 FEC per RCU
70 *ibranch = (FEC%18) / 9;
73 // columns and rows within an FEC area
77 // The mapping to CSP is a bit complicated so I also define two more help variables here..
79 int TCard = tCol/2; // 0=Top (even StripModules), 1=Bottom (odd StripModules)
80 int locCol = tCol%2; // local column inside T-card
82 *icsp = (7 - tRow) + locCol*16 + TCard*8;
86 //__________________________________________________________
87 void DCSGenerateAPD(const char *inputFileName,
88 const char *outputDir,
90 const int RCUFWVersion=1, // default as of May 2009 is RCU FWv2
91 const int FEEBCVersion=1) // default as of May 2009 is PCM4
94 // set up which bias voltage should be applicable for which CSP..
95 Tower2FEEBiasInfo(inputFileName);
97 // general setup block: try to keep magic numbers/registers collected here
98 const char *branch_str[] = { "A", "B"};
100 const char *rcufw_str[] = { "v1", "v2"};
101 const int rcu_addr_start[nRCUFW] = {0x7000, 0x0000};
102 const int read_header[nRCUFW] = {0x520000, 0x020000};
103 const int write_header[nRCUFW] = {0x620000, 0x220000};
104 const int voltage_value_start[nRCUFW] = {0x700000, 0x200000};
105 const int rcu_endmem[nRCUFW] = {0x390000, 0x3F0000};
106 const int rcu_exeseq[nRCUFW] = {0x0, 0x5304};
107 const int rcu_result_reg[nRCUFW] = {0x6000, 0x2000};
109 const int nFEEBC = 2;
110 const char *feebc_str[] = { "PCM3", "PCM4"};
111 const int trailer_offset[nFEEBC] = {0x48, 0x68};
112 const int update_voltage_register = 0x1E;
113 const int max_dac_value = 0x3FF;
115 printf("DCSGenerateAPD: RCU FW %s, FEE BC %s\n",
116 rcufw_str[RCUFWVersion], feebc_str[FEEBCVersion]);
118 // resulting voltage settings should be good within a few volts
119 cout << " HV-DAC prop. constant = " << prop << endl;
120 char iv_dac_setting[100];
124 FILE* fout_setbias_card[NRCU][NBranch][NFEC];
125 FILE* fout_readbias_card[NRCU][NBranch][NFEC];
127 // end of setup, let's go..
129 int rcu_addr_card = rcu_addr_start[RCUFWVersion];
130 int csp_addr = trailer_offset[FEEBCVersion];
134 int rcu_addr_read = rcu_addr_start[RCUFWVersion]; // we'll also write the readbias file in the same loop, so
135 // need a separate index also
137 for (int rcu=0; rcu<NRCU; rcu++) {
138 for (int branch=0; branch<NBranch; branch++) {
139 for (int ifec=0; ifec<NFEC; ifec++) {
143 sprintf(cfile,"%s/set_rcu_%d_bias_branch_%s_FEC_%d.scr",
145 branch_str[branch], icard);
146 fout_setbias_card[rcu][branch][card] = fopen(cfile, "w");
148 sprintf(cfile,"%s/read_rcu_%d_bias_branch_%s_FEC_%d.scr",
150 branch_str[branch], icard);
151 fout_readbias_card[rcu][branch][card] = fopen(cfile, "w");
153 rcu_addr_card = rcu_addr_start[RCUFWVersion];
154 rcu_addr_read = rcu_addr_start[RCUFWVersion];
156 for (int icsp = 0; icsp<NCSP; icsp++) {
159 some funkiness to address the CSPs correctly follows here.
160 DS verified this with section 16.1 "Bias voltage programming", table 8
161 of H. Muller's PHOS manual (version from Jan 2007)
163 if (icsp<16) { csp_addr = trailer_offset[FEEBCVersion] + icsp; }
164 else { csp_addr = trailer_offset[FEEBCVersion] - 1 - (icsp%16); }
165 if (icsp >= 24) csp_addr += 0x20;
167 // what does the desired voltage (in V) correspond to in DAC?
168 int iv_dac = (int)( (biasVoltage[rcu][branch][card][icsp] - hvmin)/prop + 0.5); // round-off
169 if (iv_dac > max_dac_value) iv_dac = max_dac_value;
170 sprintf(iv_dac_setting,"%06X", voltage_value_start[RCUFWVersion] + iv_dac);
172 // set up instructions that should be written
173 word = write_header[RCUFWVersion] | (branch << 16) | (icard << 12) | (csp_addr);
175 // write a long comment with all info for this CSP
176 sprintf(comment, "# RCU %d, Branch %s, FEC %d, CSP %02d - Tower Col %02d, Row %02d ",
177 rcu, branch_str[branch], icard, icsp,
178 towerCol[rcu][branch][card][icsp],
179 towerRow[rcu][branch][card][icsp]
182 fprintf(fout_setbias_card[rcu][branch][card], "w 0x%04X 0x%6X %s\n",
183 rcu_addr_card, word, comment);
186 fprintf(fout_setbias_card[rcu][branch][card], "w 0x%04X 0x%s # Set Voltage: %4.1f V, DAC %d (hex: %03X)\n",
187 rcu_addr_card, iv_dac_setting,
188 biasVoltage[rcu][branch][card][icsp],
193 // slighly modified comment for read command - include voltage info
194 sprintf(comment, "# RCU %d, Branch %s, FEC %d, CSP %02d - Tower Col %02d, Row %02d : %4.1f V, DAC %d (hex: %03X)",
195 rcu, branch_str[branch], icard, icsp,
196 towerCol[rcu][branch][card][icsp],
197 towerRow[rcu][branch][card][icsp],
198 biasVoltage[rcu][branch][card][icsp],
202 word = read_header[RCUFWVersion] | (branch << 16) | (icard << 12) | (csp_addr);
203 fprintf(fout_readbias_card[rcu][branch][card], "w 0x%04X 0x%06X %s\n", rcu_addr_read, word, comment);
207 // after CSP per card; send update command
208 word = write_header[RCUFWVersion] | (branch << 16) | (icard << 12) | update_voltage_register;
209 fprintf(fout_setbias_card[rcu][branch][card],"w 0x%04X 0x%06X # Update Voltages\n",
210 rcu_addr_card, word);
212 fprintf(fout_setbias_card[rcu][branch][card],"w 0x%04X 0x%06X \n",
213 rcu_addr_card, voltage_value_start[RCUFWVersion]);
216 // also put ending for the individual card files:
217 fprintf(fout_setbias_card[rcu][branch][card],"w 0x%04X 0x%06X # End of the instruction memory\n",
218 rcu_addr_card, rcu_endmem[RCUFWVersion]);
221 fprintf(fout_setbias_card[rcu][branch][card],"wait 100 us\n");
222 fprintf(fout_setbias_card[rcu][branch][card],"w 0x%X 0x0 # execute and update registers\n",
223 rcu_exeseq[RCUFWVersion]);
224 if (RCUFWVersion == 0) { // specialty for old FW version
225 fprintf(fout_setbias_card[rcu][branch][card],"wait 100 us\n");
226 fprintf(fout_setbias_card[rcu][branch][card],"r 0x7800 # error checking\n");
227 fprintf(fout_setbias_card[rcu][branch][card],"w 0x6c01 0x 0 # clear registers\n");
230 // in case we want to check what was written
232 fprintf(fout_setbias_card[rcu][branch][card],"wait 100 us\n");
233 fprintf(fout_setbias_card[rcu][branch][card],"b %s # read-back the values also\n", cfile);
234 fprintf(fout_setbias_card[rcu][branch][card],"wait 100 us\n");
237 // close down output files (set)
238 fclose(fout_setbias_card[rcu][branch][card]);
241 fprintf(fout_readbias_card[rcu][branch][card],"w 0x%04X 0x%06X \n",
242 rcu_addr_read, rcu_endmem[RCUFWVersion]);
245 fprintf(fout_readbias_card[rcu][branch][card],"wait 1 us\n");
246 fprintf(fout_readbias_card[rcu][branch][card],"w 0x%X 0x0 # execute and update registers\n",
247 rcu_exeseq[RCUFWVersion]);
249 fprintf(fout_readbias_card[rcu][branch][card],"wait 1 us\n");
250 int nRead = NCSP*2; // new FW reads back i/o
251 if (RCUFWVersion == 0) { // specialty for old FW version
252 fprintf(fout_readbias_card[rcu][branch][card],"r 0x7800 # error checking\n");
253 fprintf(fout_readbias_card[rcu][branch][card],"wait 1 us\n");
256 fprintf(fout_readbias_card[rcu][branch][card],"r 0x%04X %d( \n", rcu_result_reg[RCUFWVersion], nRead);
257 if (RCUFWVersion == 0) { // specialty for old FW version
258 fprintf(fout_readbias_card[rcu][branch][card],"wait 1 us\n");
259 fprintf(fout_readbias_card[rcu][branch][card],"r 0x7800 # error checking\n");
260 fprintf(fout_readbias_card[rcu][branch][card],"w 0x6c01 0x 0 # clear registers\n");
263 // close down output files (read)
264 fclose(fout_readbias_card[rcu][branch][card]);