]> git.uio.no Git - u/mrichter/AliRoot.git/blob - EMCAL/SMcalib/DCSGenerateAPD.C
EbE q vector correlations
[u/mrichter/AliRoot.git] / EMCAL / SMcalib / DCSGenerateAPD.C
1 // constants
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
4
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
9
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; 
14
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]; 
19
20 //__________________________________________________________
21 void Tower2FEEBiasInfo(const char *inputFileName)
22 {
23   ifstream inputFile(inputFileName);
24   int ic, ir;
25   Float_t ival;
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;
30
31       // could check here that ic && ir match with icol && irow, but should not be needed
32
33       // translate to FEE type indices
34       Tower2FEEMap(ic, ir, 
35                    &ircu, &ibranch, &card, &icsp);
36
37       // debug
38       /*
39       printf("ic %d ir %d ircu %d ibranch %d card %d icsp %d\n",
40              ic, ir, ircu, ibranch, card, icsp);
41       */
42
43       // store value
44       biasVoltage[ircu][ibranch][card][icsp] = ival;
45       towerCol[ircu][ibranch][card][icsp] = ic;
46       towerRow[ircu][ibranch][card][icsp] = ir;
47     }
48   }
49
50   inputFile.close();
51
52   return;
53 }
54
55 //__________________________________________________________
56 void Tower2FEEMap(const int icol, const int irow,
57                   int *ircu, int *ibranch, int *card, int *icsp)
58 { /*
59     If you are interested in where these magic numbers come from -
60     See mapping info on 
61     http://dsilverm.web.cern.ch/dsilverm/mapping/emcal_mapping.html
62     http://dsilverm.web.cern.ch/dsilverm/mapping/ppt/Coordinates_and_Mapping.pdf
63    */
64
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
68
69   *ircu = FEC / 18; // 18 FEC per RCU
70   *ibranch = (FEC%18) / 9;
71   *card = FEC % 9;  
72
73   // columns and rows within an FEC area
74   int tCol = icol%4;
75   int tRow = irow%8;
76
77   // The mapping to CSP is a bit complicated so I also define two more help variables here..
78   // which T-card?
79   int TCard = tCol/2; // 0=Top (even StripModules), 1=Bottom (odd StripModules)
80   int locCol = tCol%2;  // local column inside T-card 
81
82   *icsp = (7 - tRow) + locCol*16 + TCard*8;
83 }
84
85 /* Main method.. */
86 //__________________________________________________________
87 void DCSGenerateAPD(const char *inputFileName,
88                     const char *outputDir,
89                     const int readBack=0,
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
92 {
93
94   // set up which bias voltage should be applicable for which CSP..
95   Tower2FEEBiasInfo(inputFileName);
96
97   // general setup block: try to keep magic numbers/registers collected here
98   const char *branch_str[] = { "A", "B"};
99   const int nRCUFW = 2;
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}; 
108
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;
114
115   printf("DCSGenerateAPD: RCU FW %s, FEE BC %s\n", 
116          rcufw_str[RCUFWVersion], feebc_str[FEEBCVersion]);
117
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]; 
121   
122   char cfile[200];
123
124   FILE* fout_setbias_card[NRCU][NBranch][NFEC];
125   FILE* fout_readbias_card[NRCU][NBranch][NFEC];
126   
127   // end of setup, let's go..
128   
129   int rcu_addr_card = rcu_addr_start[RCUFWVersion];
130   int csp_addr = trailer_offset[FEEBCVersion];
131   int word = 0;
132   char comment[400];
133   
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
136
137   for (int rcu=0; rcu<NRCU; rcu++) {
138     for (int branch=0; branch<NBranch; branch++) {
139       for (int ifec=0; ifec<NFEC; ifec++) {
140         int card = ifec;
141         int icard = ifec+1;
142
143         sprintf(cfile,"%s/set_rcu_%d_bias_branch_%s_FEC_%d.scr",
144                 outputDir, rcu, 
145                 branch_str[branch], icard);
146         fout_setbias_card[rcu][branch][card] = fopen(cfile, "w");
147
148         sprintf(cfile,"%s/read_rcu_%d_bias_branch_%s_FEC_%d.scr", 
149                 outputDir, rcu,
150                 branch_str[branch], icard);
151         fout_readbias_card[rcu][branch][card] = fopen(cfile, "w");
152
153         rcu_addr_card = rcu_addr_start[RCUFWVersion];
154         rcu_addr_read = rcu_addr_start[RCUFWVersion];
155
156         for (int icsp = 0; icsp<NCSP; icsp++) {
157           
158           /* 
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) 
162           */ 
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;
166
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);
171
172           // set up instructions that should be written
173           word = write_header[RCUFWVersion] | (branch << 16) | (icard << 12) | (csp_addr);
174
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]
180                   );  
181         
182           fprintf(fout_setbias_card[rcu][branch][card], "w 0x%04X 0x%6X   %s\n",
183                   rcu_addr_card, word, comment);
184           rcu_addr_card++;
185
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], 
189                   iv_dac, iv_dac
190                   );
191           rcu_addr_card++;
192
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], 
199                   iv_dac, iv_dac
200                   );  
201
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);
204           rcu_addr_read++;
205         } // csp loop
206         
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); 
211         rcu_addr_card++;
212         fprintf(fout_setbias_card[rcu][branch][card],"w 0x%04X 0x%06X   \n", 
213                 rcu_addr_card, voltage_value_start[RCUFWVersion]);
214         rcu_addr_card++;
215
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]);
219         rcu_addr_card++;
220       
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");
228         }
229
230         // in case we want to check what was written
231         if (readBack) {
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");
235         }
236
237         // close down output files (set)
238         fclose(fout_setbias_card[rcu][branch][card]);
239         
240         // readbias ending
241         fprintf(fout_readbias_card[rcu][branch][card],"w 0x%04X 0x%06X \n", 
242                 rcu_addr_read, rcu_endmem[RCUFWVersion]);
243         rcu_addr_read++;
244
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]);
248
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");
254           nRead = NCSP;
255         }
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");
261         }
262
263         // close down output files (read)
264         fclose(fout_readbias_card[rcu][branch][card]);
265
266       } // card=FEC
267     } // branch
268   } // rcu
269
270 }