00001 #include "ConfigurationUtility.h"
00002 #include "SctApiException.h"
00003 #include "primParams.h"
00004 
00005 namespace SctApi{
00006 #define fToInt(val) ((int)((val)+0.5))
00007 
00008 const static short tokens[20]={0x01, 0x03, 0x05, 0x07, 0x0b,
00009                                0x0d, 0x0f, 0x15, 0x17, 0x1b,
00010                                0x1d, 0x1f, 0x2b, 0x2d, 0x2f,
00011                                0x35, 0x37, 0x3b, 0x3d, 0x3f};
00012 
00013 const char *chipRoles[] = {"MISSING", "DEAD", "END", "MASTER", "SLAVE", "LONELY", "PARANOID"};
00014 
00015 void ConfigUtility::setToken(ABCDModule* module, unsigned token, int link0, int link1) {
00016   
00017   for(unsigned int theChip=0; theChip<N_SCT_CHIPS; theChip++){
00018        module->chip[theChip].basic.config.outputBypass = 0;
00019        module->chip[theChip].basic.config.inputBypass = 0;
00020        module->chip[theChip].basic.config.master = 1;        
00021        module->chip[theChip].basic.config.end = 0;           
00022        module->chip[theChip].basic.config.feedThrough  = 1;  
00023   }
00024 
00025   for(unsigned int theChip=0; theChip<N_SCT_CHIPS; theChip++){
00026     
00027     if( (token >> theChip) & 0x1 ) { 
00028 
00029       if(theChip==0) {
00030         if(link0) {
00031           if((token&0x003F)==0x0001) { 
00032             setChipRole(module,theChip,LONELY);
00033           } else {
00034             setChipRole(module,theChip,MASTER);
00035           }
00036         } else {
00037           setChipRole(module,theChip,END);
00038         }
00039 
00040       } else if(theChip==6) {
00041         if (link1) { 
00042           if((token&0x0FC0)==0x0040) { 
00043             setChipRole(module,theChip,LONELY);
00044           } else {
00045             setChipRole(module,theChip,MASTER);
00046           }
00047         } else {
00048           setChipRole(module,theChip,END);
00049         }
00050 
00051       } else if(theChip<6) {
00052         
00053         if( (link0<2) && (1<<(theChip+1)>(token&0x3F)) ) {
00054           setChipRole(module,theChip,END);
00055         } else {
00056           setChipRole(module,theChip,SLAVE);
00057         }
00058 
00059       } else {
00060         
00061         if( (link1<2) && (1<<(theChip+1)>token) ) {
00062           setChipRole(module,theChip,END);
00063         } else {
00064           setChipRole(module,theChip,SLAVE);
00065         }
00066       }
00067 
00068     } else {
00069       setChipRole(module,theChip,DEAD);
00070     }
00071   }
00072   return;
00073 }
00074 
00075 void ConfigUtility::modifyVar(ABCDModule* p_module, UINT32 typ, FLOAT32 val){
00076   ConfigVarType variable_type=variableType(typ);
00077   if ( !isModuleRegister(variable_type) ) return;
00078   if (!p_module) throw SctApiException("Null pointer exception in ConfigUtililty::modifyVar");
00079   ABCDModule &module = *p_module;
00080   
00081   switch (typ){
00082   case ST_TOKEN:
00083     {
00084       
00085 
00086 
00087 
00088 
00089 
00090 
00091 
00092 
00093 
00094 
00095 
00096 
00097 
00098 
00099 
00100 
00101 
00102 
00103 
00104 
00105 
00106 
00107 
00108 
00109 
00110 
00111 
00112 
00113 
00114 
00115 
00116  
00117       int myVal = fToInt(val);
00118       
00119       if(myVal<20) {              
00120     setToken(&module, (tokens[myVal] + (tokens[myVal] << 6)),1,1);
00121     
00122       } else if(myVal<36) {       
00123     if(!((int)myVal%2)) {
00124       setToken(&module, (tokens[(myVal-20)/2+12] + (0x1 << 7)),2,0);
00125     } else {                
00126       setToken(&module, (0x2 + (tokens[(myVal-21)/2+12] << 6)),0,2);
00127     }
00128       } else { 
00129     if(!(myVal%2)) {
00130       setToken(&module, (tokens[((myVal-36)/2+7)] + (1 << 6)),2,0);
00131     } else {
00132       setToken(&module, (0x1 + (tokens[((myVal-37)/2+7)] << 6)),0,2);
00133     }
00134       }
00135       break;
00136     }
00137   case MVAR_GROUP_ID:
00138     {
00139       module.groupId = fToInt(val);
00140       break;
00141     }
00142   case MVAR_ACTIVE:
00143     {
00144       module.active = fToInt(val);
00145       break;
00146     }
00147   case MVAR_SELECT:
00148     {
00149       module.select = fToInt(val);
00150       
00151       if(module.select) {
00152     for(int c=0; c<12; c++) {
00153       module.chip[c].address |= 0x10;
00154         }
00155       } else {
00156     for(int c=0; c<12; c++) {
00157       module.chip[c].address &= ~0x10;
00158     }
00159       }
00160       break;
00161     }
00162   default:
00163     if (variable_type==MODULE_CHIP_CONFIG_VAR) {
00164       for(int ichip=0; ichip<12; ichip++) {
00165         modifyVar(p_module, ichip, typ, val);
00166       }
00167       break;
00168     }else{
00169       std::cerr << "ERROR I don't know how to deal with variable " << typ << " of type " << variable_type << std::endl;
00170     }
00171   }
00172 }
00173 
00174 void ConfigUtility::modifyVar(ABCDModule* module, unsigned ichip, UINT32 typ, FLOAT32 val){
00175   if (ichip==ALL_CHIPS) {
00176     modifyVar(module, typ, val);
00177     return;
00178   }
00179   if (ichip>=12) {
00180     std::ostringstream oss;
00181     oss << "Chip ["<<ichip<<"] out of range in ConfigurationUtility::modifyVar\n";
00182     oss << "was expecting {0->12} or " << ALL_CHIPS;
00183     throw SctApiException(oss.str());
00184   }
00185   if (!module) throw SctApiException("Null pointer exception in ConfigUtililty::modifyVar");
00186   ABCDChip &chip = module->chip[ichip];
00187   ConfigVarType variable_type = variableType(typ);
00188   if (variable_type != MODULE_CHIP_CONFIG_VAR && variable_type != MODULE_CHANNEL_CONFIG_VAR) return;
00189   
00190   switch(typ) {
00191   case ST_ELAPSED: 
00192     
00193     break;
00194   case ST_VTHR: 
00195     chip.basic.vthr = (char) fToInt(val/2.5);
00196     break;
00197   case ST_VCAL:
00198     chip.basic.vcal = (char) fToInt(val/0.625);
00199     break;
00200   case ST_STROBE_DELAY:
00201     chip.basic.delay = (char) fToInt(val);
00202     break;
00203   case ST_PREAMP:
00204     chip.basic.preamp = (char) fToInt(val/9.2);
00205     break;
00206   case ST_SHAPER:
00207     chip.basic.shaper = (char) fToInt(val/1.2);
00208     break;
00209   case ST_TRIM:
00210     for(int i=0; i<128; i++) {
00211       chip.trim[i] = (char) fToInt(val);
00212     }
00213     break;
00214   case ST_MASK:
00215     {
00216       UINT32 myval = (UINT32) fToInt(val);
00217       UINT32 mask = myval;
00218       for(int i=0; i<16; i++) {
00219         mask = (mask << 2) + myval;
00220       }
00221 
00222       for(int i=0; i<4; i++) {
00223         chip.basic.mask[i] = mask;
00224       }
00225     }
00226     break;
00227   case ST_ROLE:
00228     switch(fToInt(val)) {
00229     case END:
00230       chip.basic.config.master = 1;  
00231       chip.basic.config.end = 1;     
00232       chip.basic.config.feedThrough = 1; 
00233       break;
00234     case MASTER:
00235       chip.basic.config.master = 0;  
00236       chip.basic.config.end = 0;     
00237       chip.basic.config.feedThrough = 1;
00238       break;
00239     case SLAVE:
00240       chip.basic.config.master = 1;  
00241       chip.basic.config.end = 0;     
00242       chip.basic.config.feedThrough = 1;
00243       break;
00244     case LONELY:
00245       chip.basic.config.master = 0;  
00246       chip.basic.config.end = 1;     
00247       chip.basic.config.feedThrough = 1;
00248       break;
00249     case PARANOID:
00250       chip.basic.config.master = 0;  
00251       chip.basic.config.end = 1;     
00252       chip.basic.config.feedThrough = 1;
00253     case DEAD:
00254     default:
00255       module->chip[(ichip+1)%12].basic.config.outputBypass = 1;
00256       module->chip[(ichip+11)%12].basic.config.inputBypass = 1;
00257     case MISSING:
00258       break;
00259     } 
00260 
00261   case ST_NMASK:
00262     {
00263       int channels = fToInt(val);
00264       if(channels > 128) channels = 128;
00265 
00266       for(int i=0; i<4; i++) {
00267         
00268         int chan = channels - i*32;
00269         if(chan >= 32) {
00270           chip.basic.mask[i] = 0x00000000;
00271         } else {
00272           int value = 0;
00273           for(int b=0; b<chan; b++) {
00274             value <<= 1;
00275             value ++;
00276           }
00277           chip.basic.mask[i] = ~value;
00278         }
00279       }
00280     }
00281     break;
00282   case ST_CAL_MODE:
00283     chip.basic.config.calibMode = fToInt(val);
00284     break;
00285   case ST_COMPRESSION:
00286     chip.basic.config.readoutMode = fToInt(val);
00287     break;
00288   case ST_TRIM_RANGE:
00289     chip.basic.config.trimRange = fToInt(val);
00290     break;
00291   case ST_EDGE_DETECT:
00292     chip.basic.config.edgeDetect = fToInt(val);
00293     break;
00294   case ST_SEND_MASK:
00295     chip.basic.config.mask = fToInt(val)?1:0;
00296     break;
00297   case ST_ACCUMULATE:
00298     chip.basic.config.accumulate = fToInt(val)?1:0;
00299     break;
00300   case ST_FEEDTHROUGH:
00301     chip.basic.config.feedThrough = fToInt(val)?1:0;
00302     break;
00303   case ST_ACTIVE:
00304     chip.active = fToInt(val)?1:0;
00305     break;
00306 
00307 #ifdef DO_TOKENS_BY_CHIP
00308   case ST_BYPASS:
00309     {
00310       
00311 
00312 
00313 
00314 
00315       UINT8 int_val = (UINT8)((val+0.5)/1.0);
00316       switch(int_val){
00317       case 0: 
00318         setToken(module, 0x03 +(0x03<<6),1,1);
00319         break;
00320       case 1: 
00321         setToken(module, 0x07 +(0x07<<6),1,1);
00322         break;
00323       case 2: 
00324         setToken(module, 0x0F +(0x0F<<6),1,1);
00325         break;
00326       case 3: 
00327         setToken(module, 0x1F +(0x1F<<6),1,1);
00328         break;
00329         
00330       case 5: 
00331         setToken(module, 0x05 +(0x05<<6),1,1);
00332         break;
00333       case 6: 
00334         setToken(module, 0x0b +(0x0b<<6),1,1);
00335         break;
00336       case 7: 
00337         setToken(module, 0x17 +(0x17<<6),1,1);
00338         break;
00339       case 8: 
00340         setToken(module, 0x2f +(0x2f<<6),1,1);
00341         break;
00342       case 9: 
00343         setToken(module, 0x3f +(0x3e<<6),2,0);
00344         break;
00345       case 10: 
00346         setToken(module, 0x3e +(0x3F<<6),0,2);
00347         break;
00348       case 11: 
00349         setToken(module, 0x3f +(0x3f<<6),2,0);
00350         break;
00351       case 12: 
00352         setToken(module, 0x3f +(0x3F<<6),0,2);
00353         break;
00354       default: 
00355         setToken(module, 0x3F +(0x3F<<6),1,1);
00356         break;
00357       }
00358       break;
00359     }
00360 
00361   case ST_TOKEN:
00362     {
00363       
00364 
00365 
00366 
00367 
00368 
00369 
00370 
00371 
00372 
00373 
00374 
00375 
00376 
00377 
00378 
00379 
00380 
00381 
00382 
00383 
00384 
00385 
00386 
00387 
00388 
00389 
00390 
00391 
00392 
00393 
00394 
00395 
00396 
00397       int myVal = fToInt(val);
00398 
00399       if(myVal<20) {              
00400         setToken(module, (tokens[(int)myVal] + (tokens[(int)myVal] << 6)),1,1);
00401       } else if(myVal<36) {       
00402         if(!((int)myVal%2)) {
00403           setToken(module, (tokens[(int)(myVal-20)/2+12] + (0x1 << 7)),2,0);
00404         } else {                
00405           setToken(module, (0x2 + (tokens[((int)myVal-21)/2+12] << 6)),0,2);
00406         }
00407       } else { 
00408         if(!((int)myVal%2)) {
00409           setToken(module, (tokens[(int)((myVal-36)/2+7)] + (1 << 6)),2,0);
00410         } else {
00411           setToken(module, (0x1 + (tokens[(int)((myVal-37)/2+7)] << 6)),0,2);
00412         }
00413       }
00414       break;
00415     }
00416 #endif
00417   case ST_QTHR: 
00418     {
00419       ABCDCaldata &calPtr = chip.caldata;
00420       float v, vv;
00421 
00422       switch(calPtr.rc_function){
00423       case 1: 
00424         v = calPtr.rc_params[0] + 
00425           val * (calPtr.rc_params[1] + 
00426                  (val * calPtr.rc_params[2]) );
00427         break; 
00428       case 2: 
00429         if((val==0)|| (calPtr.rc_params[1]==0))
00430           vv = 0;
00431         else
00432           vv = calPtr.rc_params[2] / 
00433             (calPtr.rc_params[1] *val);
00434         v  = calPtr.rc_params[0] + 
00435           calPtr.rc_params[2] / (float) sqrt(1+(vv*vv)); 
00436         break; 
00437       case 3: 
00438         if(calPtr.rc_params[1]==0)
00439           v = 0;
00440         else
00441           v = calPtr.rc_params[2] + 
00442             calPtr.rc_params[0]/(1+ (float)exp(-val/calPtr.rc_params[1]));
00443         break;  
00444       case 4: 
00445         v = calPtr.rc_params[0] + 
00446           (val * calPtr.rc_params[1]);
00447         break; 
00448       default:
00449         v = 0;
00450         break;
00451       }
00452 
00453       UINT8 int_val = ((UINT8)((v+1.25)/(float)2.5));  
00454       chip.basic.vthr = int_val;
00455       break;
00456     }
00457 
00458   case ST_QCAL:
00459     
00460 
00461 
00462 
00463 
00464     {
00465       FLOAT32 step = (float) 0.0625 * chip.caldata.c_factor;
00466       UINT8 int_val = (UINT8)((val+(step/2))/step);
00467       chip.basic.vcal = int_val;
00468       break;
00469     }
00470   case ST_TARGET:
00471     {
00472       
00473 
00474 
00475 
00476       UINT8 int_val = ((UINT8)((val+1.25)/(float)2.5));  
00477 
00478       
00479 
00480 
00481 
00482       chip.target = int_val;
00483       break;
00484     }
00485 
00486   case ST_TTHR:
00487     {
00488       
00489 
00490 
00491 
00492       UINT8 int_val = ((UINT8)((val+1.25)/(float)2.5));  
00493       int_val += chip.target;
00494 
00495       
00496 
00497 
00498 
00499       chip.basic.vthr = int_val;
00500       break;
00501     }
00502 
00503   default:
00504     break;
00505   } 
00506 
00507 }
00508 
00509 INT32 ConfigUtility::setChipRole(ABCDModule *module, UINT32 theChip, ABCD_ROLES role){
00510 
00511 
00512   ABCDChip*   chipPtr;
00513   ABCDConfig* configPtrLast;   
00514   ABCDConfig* configPtr;      
00515   ABCDConfig* configPtrNext;  
00516 
00517   UINT32 lastChip, nextChip;
00518 
00519   if(theChip>N_SCT_CHIPS-1) return -1;  
00520   if(module->active==0) return -2;  
00521 
00522   chipPtr = &module->chip[theChip];
00523   if(chipPtr->active==0) return -3; 
00524 
00525   lastChip = theChip-1;
00526   nextChip = theChip+1;
00527 
00528   if(theChip==0)  lastChip = 11;
00529   if(theChip==11) nextChip =  0;
00530 
00531   configPtrLast = &module->chip[lastChip].basic.config;
00532   configPtr     = &module->chip[theChip].basic.config;
00533   configPtrNext = &module->chip[nextChip].basic.config;
00534 
00535   switch(role){
00536     case MISSING:
00537       
00538       break;
00539     case DEAD:
00540       configPtrNext->outputBypass = 1;
00541       configPtrLast->inputBypass  = 1;
00542       break;
00543     case END:
00544       configPtr->master = 1;
00545       configPtr->end    = 1;
00546       configPtr->feedThrough = 1;
00547       break;
00548     case MASTER:
00549       configPtr->master = 0;
00550       configPtr->end    = 0;
00551       configPtr->feedThrough = 1;  
00552       break;
00553     case SLAVE:
00554       configPtr->master = 1;
00555       configPtr->end    = 0;
00556       configPtr->feedThrough = 1;
00557       break;
00558     case LONELY:
00559       configPtr->master = 0;
00560       configPtr->end    = 1;
00561       configPtr->feedThrough = 1;
00562       break;
00563     case PARANOID:
00564       configPtrNext->outputBypass = 1;
00565       configPtrLast->inputBypass  = 1;
00566       configPtr->master = 0;
00567       configPtr->end    = 1;
00568       configPtr->feedThrough = 1;
00569       break;
00570     default:
00571       break;
00572   }
00573 
00574   return 0;
00575 }
00576 
00577 ConfigUtility::ConfigVarType ConfigUtility::variableType(UINT32 typ){
00578   switch(typ) {
00579   case ST_RX_DELAY:
00580   case ST_RX_DELAY0:
00581   case ST_RX_DELAY1:
00582   case ST_RX_THRESHOLD:
00583   case ST_RX_THRESHOLD0:
00584   case ST_RX_THRESHOLD1:
00585   case ST_TX_CURRENT:
00586   case ST_TX_MARKSPACE:
00587   case ST_TX_DELAY:
00588   case ST_TX_COARSE:
00589   case ST_TX_FINE:
00590     return BOC_CHANNEL_CONFIG_VAR;
00591   case SCT_SCAN_BOC_BPM_PHASE:
00592   case SCT_SCAN_BOC_BREG_PHASE:
00593   case SCT_SCAN_BOC_V0_PHASE:
00594   case SCT_SCAN_BOC_V1_PHASE:
00595   case SCT_SCAN_BOC_V_PHASES:
00596   case SCT_SCAN_BOC_VRN_FINE:
00597   case SCT_SCAN_TX_CHANNELS:
00598   case SCT_SCAN_RAW_TX_CHANNELS:
00599     return BOC_GLOBAL_CONFIG_VAR;
00600   case ST_TOKEN:
00601     
00602   case MVAR_GROUP_ID:
00603   case MVAR_ACTIVE:
00604   case MVAR_SELECT:
00605     return MODULE_GLOBAL_CONFIG_VAR;
00606   case ST_VTHR: 
00607   case ST_VCAL:
00608   case ST_STROBE_DELAY:
00609   case ST_PREAMP:
00610   case ST_SHAPER:
00611   case ST_TRIM:
00612   case ST_MASK:
00613   case ST_ROLE:
00614   case ST_NMASK:
00615   case ST_CAL_MODE:
00616   case ST_COMPRESSION:
00617   case ST_TRIM_RANGE:
00618   case ST_EDGE_DETECT:
00619   case ST_SEND_MASK:
00620   case ST_ACCUMULATE:
00621   case ST_FEEDTHROUGH:
00622   case ST_ACTIVE:
00623 
00624   case ST_QTHR: 
00625   case ST_QCAL:
00626   case ST_TARGET:
00627   case ST_TTHR:
00628     return MODULE_CHIP_CONFIG_VAR;
00629     return MODULE_CHANNEL_CONFIG_VAR;
00630   case SCT_TIM_PRE_TRIGGER_DELAY:
00631   case SCT_TIM_CLOCK_DELAY:
00632     return TIM_CONFIG_VAR;
00633   case ST_TRIG_DELAY1:
00634   case ST_TRIG_DELAY2:
00635     return TRIGGER_VAR;
00636   default:
00637     return UNKNOWN_CONFIG_VAR;
00638   }
00639 }
00640 
00641 }