silvermy@ornl.gov - SMcalib - directory with tools for SuperModule calibrations at...
[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 // some global variables
11 int biasVoltage[NRCU][NBranch][NFEC][NCSP]; 
12 int towerCol[NRCU][NBranch][NFEC][NCSP]; 
13 int towerRow[NRCU][NBranch][NFEC][NCSP]; 
14
15 //__________________________________________________________
16 void Tower2FEEBiasInfo(const char *inputFileName)
17 {
18   ifstream inputFile(inputFileName);
19   int ic, ir,ival;
20   int ircu, ibranch, card, icsp;
21   for (int icol=0; icol<fgkEmCalCols; icol++) {
22     for (int irow=0; irow<fgkEmCalRows; irow++) {
23       inputFile >> ic >> ir >> ival;
24
25       // could check here that ic && ir match with icol && irow, but should not be needed
26
27       // translate to FEE type indices
28       Tower2FEEMap(ic, ir, 
29                    &ircu, &ibranch, &card, &icsp);
30
31       // debug
32       /*
33       printf("ic %d ir %d ircu %d ibranch %d card %d icsp %d\n",
34              ic, ir, ircu, ibranch, card, icsp);
35       */
36
37       // store value
38       biasVoltage[ircu][ibranch][card][icsp] = ival;
39       towerCol[ircu][ibranch][card][icsp] = ic;
40       towerRow[ircu][ibranch][card][icsp] = ir;
41     }
42   }
43
44   inputFile.close();
45
46   return;
47 }
48
49 //__________________________________________________________
50 void Tower2FEEMap(const int icol, const int irow,
51                   int *ircu, int *ibranch, int *card, int *icsp)
52 { /*
53     If you are interested in where these magic numbers come from -
54     See mapping info on 
55     http://dsilverm.web.cern.ch/dsilverm/mapping/emcal_mapping.html
56     http://dsilverm.web.cern.ch/dsilverm/mapping/ppt/Coordinates_and_Mapping.pdf
57    */
58
59   // each FEC covers a 4x8 tower area
60   int C = irow/8; // Cable bundle
61   int FEC = C*12 + icol/4; // FEC in 0..35 range
62
63   *ircu = FEC / 18; // 18 FEC per RCU
64   *ibranch = (FEC%18) / 9;
65   *card = FEC % 9;  
66
67   // columns and rows within an FEC area
68   int tCol = icol%4;
69   int tRow = irow%8;
70
71   // The mapping to CSP is a bit complicated so I also define two more help variables here..
72   // which T-card?
73   int TCard = tCol/2; // 0=Top (even StripModules), 1=Bottom (odd StripModules)
74   int locCol = tCol%2;  // local column inside T-card 
75
76   *icsp = (7 - tRow) + locCol*16 + TCard*8;
77 }
78
79 /* Main method.. */
80 //__________________________________________________________
81 void DCSGenerateAPD(const char *inputFileName,
82                     const char *outputDir,
83                     const int readBack=0) 
84 {
85
86   // set up which bias voltage should be applicable for which CSP..
87   Tower2FEEBiasInfo(inputFileName);
88
89   // general setup block: note - for old RCU firmware (DS: hope this doesn't change with new firmware)
90   const char *branch_str[] = { "A", "B"};
91   const int trailer_offset = 0x48;
92   const int read_header = 0x520000; 
93   const int write_header = 0x620000; 
94   
95   // hv = hvmin + prop*DAC; values fitted/measured by ZhongBao; correction with David K at SPS beamtest
96   float hvmin = 207.9;
97   float prop = 0.2022; 
98   // resulting voltage settings should be good within a few volts 
99   cout << " HV-DAC prop. constant = " << prop << endl;
100   char iv_dac_setting[100]; 
101   
102   char cfile[200];
103
104   FILE* fout_setbias_card[NRCU][NBranch][NFEC];
105   FILE* fout_readbias_card[NRCU][NBranch][NFEC];
106   
107   // end of setup, let's go..
108   
109   int rcu_addr_card = 0x7000;
110   int csp_addr = trailer_offset;
111   int word = 0;
112   char comment[400];
113   
114   int rcu_addr_read = 0x7000; // we'll also write the readbias file in the same loop, so
115   // need a separate index also
116
117   for (int rcu=0; rcu<NRCU; rcu++) {
118     for (int branch=0; branch<NBranch; branch++) {
119       for (int ifec=0; ifec<NFEC; ifec++) {
120         int card = ifec;
121         int icard = ifec+1;
122
123         sprintf(cfile,"%s/set_rcu_%d_bias_branch_%s_FEC_%d.scr",
124                 outputDir, rcu, 
125                 branch_str[branch], icard);
126         fout_setbias_card[rcu][branch][card] = fopen(cfile, "w");
127
128         sprintf(cfile,"%s/read_rcu_%d_bias_branch_%s_FEC_%d.scr", 
129                 outputDir, rcu,
130                 branch_str[branch], icard);
131         fout_readbias_card[rcu][branch][card] = fopen(cfile, "w");
132
133         rcu_addr_card = 0x7000;
134         rcu_addr_read = 0x7000;
135
136         for (int icsp = 0; icsp<NCSP; icsp++) {
137           
138           /* 
139              some funkiness to address the CSPs correctly follows here. 
140              DS verified this with section 16.1 "Bias voltage programming", table 8
141              of H. Muller's PHOS manual (version from Jan 2007) 
142           */ 
143           if (icsp<16) { csp_addr = trailer_offset + icsp; }
144           else { csp_addr = trailer_offset - 1 - (icsp%16); }
145           if (icsp >= 24) csp_addr += 0x20;
146
147           // what does the desired voltage (in V) correspond to in DAC?
148           int iv_dac = (int)( (biasVoltage[rcu][branch][card][icsp] - hvmin)/prop );
149           if (iv_dac > 0x3FF) iv_dac = 0x3FF;
150           sprintf(iv_dac_setting,"700%03X",iv_dac);
151
152
153           // set up instructions that should be written
154           word = write_header | (branch << 16) | (icard << 12) | (csp_addr);
155
156           // write a long comment with all info for this CSP
157           sprintf(comment, "# RCU %d, Branch %s, FEC %d, CSP %d - Tower Col %d, Row %d ", 
158                   rcu, branch_str[branch], icard, icsp,
159                   towerCol[rcu][branch][card][icsp],
160                   towerRow[rcu][branch][card][icsp]
161                   );  
162         
163           fprintf(fout_setbias_card[rcu][branch][card], "w 0x%4X 0x%6X   %s\n",
164                   rcu_addr_card, word, comment);
165           rcu_addr_card++;
166
167           fprintf(fout_setbias_card[rcu][branch][card], "w 0x%4X 0x%s   # Set Voltage: %d V, DAC %d (hex: %03X)\n", 
168                   rcu_addr_card, iv_dac_setting, 
169                   biasVoltage[rcu][branch][card][icsp], 
170                   iv_dac, iv_dac
171                   );
172           rcu_addr_card++;
173
174           // slighly modified comment for read command - include voltage info
175           sprintf(comment, "# RCU %d, Branch %s, FEC %d, CSP %d - Tower Col %d, Row %d : %d V, DAC %d (hex: %03X)", 
176                   rcu, branch_str[branch], icard, icsp,
177                   towerCol[rcu][branch][card][icsp],
178                   towerRow[rcu][branch][card][icsp],
179                   biasVoltage[rcu][branch][card][icsp], 
180                   iv_dac, iv_dac
181                   );  
182
183           word = read_header | (branch << 16) | (icard << 12) | (csp_addr);
184           fprintf(fout_readbias_card[rcu][branch][card], "w 0x%4X 0x%06X  %s\n", rcu_addr_read, word, comment);
185           rcu_addr_read++;
186         } // csp loop
187         
188         // after CSP per card; send update command
189         word = write_header | (branch << 16) | (icard << 12) | 0x1e;
190         fprintf(fout_setbias_card[rcu][branch][card],"w 0x%4X 0x%06X   # Update Voltages\n", 
191                 rcu_addr_card, word); 
192         rcu_addr_card++;
193
194         // also put ending for the individual card files:
195         fprintf(fout_setbias_card[rcu][branch][card],"w 0x%4X 0x%06X \n", 
196                 rcu_addr_card, 0x700000);
197         rcu_addr_card++;
198         fprintf(fout_setbias_card[rcu][branch][card],"w 0x%4X 0x%06X \n", 
199                 rcu_addr_card, 0x390000);
200         rcu_addr_card++;
201       
202         fprintf(fout_setbias_card[rcu][branch][card],"wait 1 us\n");
203         fprintf(fout_setbias_card[rcu][branch][card],"w 0x0 0x0           # execute and update registers\n");
204         fprintf(fout_setbias_card[rcu][branch][card],"wait 1 us\n");
205         fprintf(fout_setbias_card[rcu][branch][card],"w 0x0 0x0           # execute and update registers again\n");
206         fprintf(fout_setbias_card[rcu][branch][card],"wait 1 us\n");
207         fprintf(fout_setbias_card[rcu][branch][card],"r 0x7800            # error checking\n");
208         fprintf(fout_setbias_card[rcu][branch][card],"w 0x6c01 0x 0       # clear registers\n");
209         
210
211         // in case we want to check what was written
212         if (readBack) {
213           fprintf(fout_setbias_card[rcu][branch][card],"wait 1 us\n");
214           fprintf(fout_setbias_card[rcu][branch][card],"b %s      # read-back the values also\n", cfile);
215           fprintf(fout_setbias_card[rcu][branch][card],"wait 1 us\n");
216         }
217
218
219         // close down output files (set)
220         fclose(fout_setbias_card[rcu][branch][card]);
221         
222         // readbias ending
223         fprintf(fout_readbias_card[rcu][branch][card],"w 0x%4X 0x%06X \n", 
224                 rcu_addr_read, 0x390000);
225         rcu_addr_read++;
226
227         fprintf(fout_readbias_card[rcu][branch][card],"wait 1 us\n");
228         fprintf(fout_readbias_card[rcu][branch][card],"w 0x0 0x0           # execute and update registers\n");
229
230         fprintf(fout_readbias_card[rcu][branch][card],"wait 1 us\n");
231         fprintf(fout_readbias_card[rcu][branch][card],"r 0x7800            # error checking\n");
232         fprintf(fout_readbias_card[rcu][branch][card],"wait 1 us\n");
233         fprintf(fout_readbias_card[rcu][branch][card],"r 0x6000 %d( \n", NCSP);
234         fprintf(fout_readbias_card[rcu][branch][card],"wait 1 us\n");
235         fprintf(fout_readbias_card[rcu][branch][card],"r 0x7800            # error checking\n");
236         fprintf(fout_readbias_card[rcu][branch][card],"w 0x6c01 0x 0       # clear registers\n");
237         
238         // close down output files (read)
239         fclose(fout_readbias_card[rcu][branch][card]);
240
241       } // card=FEC
242     } // branch
243   } // rcu
244
245 }