File: DETECUSE\detecmes.cpp

    1 /*
    2 $Header: /vol/baal-vol3/projekt98/quellen/XCTL_32/DETECUSE/detecmes.cpp,v 1.38 2004/07/08 21:14:33 reinecke Exp $
    3 
    4 Projekt   : XCTL
    5 Subsystem : Detektoren
    6 Autor     : Jan Picard <picard@informatik.hu-berlin.de> 2001-2002
    7           Institut fuer Informatik,
    8           Humboldt-Universitaet Berlin
    9 Inhalt    : Code fuer die Messadapterklassen
   10 */
   11 
   12 #include "utils\u_utils.h"
   13 #include "winresrc\rc_def.h" // Ressourcen-IDs
   14 #include <fstream.h>
   15 #include <strstrea.h>
   16 #include <ctype.h>
   17 #pragma hdrstop
   18 
   19 #include "motrstrg\motrstrg.h"
   20 
   21 #include "detecuse\detecmes.h"
   22 #include "detecuse\detecgui.h"
   23 #include "detecuse\detectorcontroller.h"
   24 
   25 //--||--\\--||--//--||--\\--||--//--||--\\--||--//--||--\\--||--//--||--\\--||--
   26 
   27 //Verwaltungsstrukturen (Treiber)
   28 extern DeviceList DetectorDrivers;
   29 extern ControllerList DetectorControllers;
   30 
   31 // time event handling
   32 extern int nEventsToCall;
   33 extern int nEvent;
   34 extern int nEventsCalled;
   35 extern float fEventIntensity;
   36 extern HWND hEventControlWnd;
   37 extern BOOL bEventDataValid;
   38 //! fuer Radicon bei Continuousscan von Diffr.gruppe eingefuehrt
   39 float fEventExposureCounts;
   40 
   41 //##############################################################################
   42 //######## Methoden fuer einen generischen Controller ##########################
   43 //########     fuer nulldimensionale Detektoren       ##########################
   44 //##############################################################################
   45 TGenericDetector::TGenericDetector(int id) : TZeroDimDetector(id)
   46 {
   47         char Ident[20];
   48 
   49         //Initialisieren des zugehörigen Controller-Objekts
   50         sprintf(Ident, "Device%i", GetId());
   51         LookUp(Ident);
   52         itoa(nBaseAddr,Ident,16);
   53     Hardware= dynamic_cast<TGenericController*>(GetController(GENERIC,Ident,&DetectorControllers,
   54                                                                        &DetectorDrivers));
   55 
   56         uAskTime= 70;
   57         exposure.TimeBounds.SetMin(0.01f);
   58 }
   59 
   60 TGenericDetector::~TGenericDetector()
   61 {
   62 }
   63 
   64 BOOL TGenericDetector::Initialize( void )
   65 {
   66         if ( Hardware->Init(fTimeCorrection) == FALSE )
   67         {
   68                 MessageBox( GetFocus( ), "Die Am9513-Controllerkarte "
   69                                         "konnte nicht initialisiert werden.",
   70                                         "Fehler bei der Hardwarekommunikation", MBINFO );
   71 
   72                 return FALSE;
   73         }
   74 
   75         DWORD param= 250;
   76 
   77         Hardware->IOCTL( iocConfigureAcustic, param );
   78 
   79         SetParameters( );
   80 
   81         return TRUE;
   82 }
   83 
   84 void TGenericDetector::LookUp(LPCSTR Section)
   85 {
   86   char buf[MaxString];
   87 
   88   ::GetPrivateProfileString( Section, "IOAddr", "0x230", buf, MaxString, GetHWFile());
   89   sscanf( buf, "%x", &nBaseAddr );
   90   ::GetPrivateProfileString( Section, "TimeCorrection", "1.0", buf, MaxString, GetHWFile());
   91   sscanf( buf, "%f", &fTimeCorrection );
   92 }
   93 
   94 BOOL TGenericDetector::_SetParameters( void )
   95 {
   96         DWORD exposureTicks= GetExposureSettings().GetExposureTime() * (DWORD)Hardware->GetTicksPerSecond();
   97         Hardware->IOCTL( iocSetTimeTicks, exposureTicks );
   98 
   99         DWORD exposureCounts= GetExposureSettings().GetExposureCounts();
  100         Hardware->IOCTL( iocSetCounts, exposureCounts );
  101 
  102         //ap - neu !!!
  103         Hardware->SetSound( GetSound() );
  104 
  105         return TRUE;
  106 }
  107 
  108 int TGenericDetector::MeasureStart( void )
  109 {
  110         MeasureStop( );
  111 
  112         if ( !GetControlWnd() && !GetCounterWnd() )
  113         {
  114                 // MessageBox(GetFocus(),"Kein Host.","Startfehler",MBSTOP);
  115                 return R_Failure;
  116         }
  117 
  118         // Messung starten
  119         Hardware->IOCTL( iocStartCounting );
  120         bActive= TRUE;
  121         SetTimer( hWndFrame, DetectorTimerIdStart + GetId( ), uAskTime, NULL );
  122 
  123         return R_MeasOk;
  124 }
  125 
  126 int TGenericDetector::MeasureStop( void )
  127 {
  128         if ( bActive )
  129         {
  130                 KillTimer( hWndFrame, DetectorTimerIdStart + GetId( ) );
  131                 Hardware->IOCTL( iocStopCounting );
  132         }
  133 
  134         bDataValid= FALSE;
  135         bActive= FALSE;
  136         return R_MeasOk;
  137 }
  138 
  139 int TGenericDetector::PollDetector( void )
  140 {
  141         float time;
  142         DWORD counts, ticks;
  143 
  144         KillTimer( hWndFrame, DetectorTimerIdStart + GetId( ) );
  145 
  146         if ( !bActive )
  147                 return R_Failure;
  148 
  149         TExposureSettings oExposureSettings= GetExposureSettings();
  150 
  151         switch ( Hardware->IOCTL( iocIsCountingReady ) )
  152         {
  153                 case 0:
  154                         SetTimer( hWndFrame, DetectorTimerIdStart + GetId( ), uAskTime, NULL );
  155                         return R_MeasInProcess;
  156 
  157                 case 1:      // time counter ready
  158                         Hardware->IOCTL( iocReadCounts, counts );
  159                         Hardware->IOCTL( iocReadTicks, ticks );
  160                         time= ( float ) ticks / Hardware->GetTicksPerSecond( );
  161 
  162                         if ( ticks != 0 )
  163                                 time= oExposureSettings.GetExposureTime() + time;
  164                         break;
  165 
  166                 case 2:      // impulse counter ready
  167                         Hardware->IOCTL( iocReadCounts, counts );
  168                         Hardware->IOCTL( iocReadTicks, ticks );
  169                         time= ( float ) ticks / Hardware->GetTicksPerSecond( );
  170 
  171                         if ( counts != 0 )
  172                                 counts= oExposureSettings.GetExposureCounts() + counts;
  173                         break;
  174 
  175                 case 3:      // both ready
  176                         counts= oExposureSettings.GetExposureCounts();
  177                         time= oExposureSettings.GetExposureTime();
  178                         SetStatus( "BothReady" );
  179                         break;
  180         }
  181 
  182         if ( time != 0.0 )
  183                 fIntensity= counts / time;
  184         else
  185         {
  186                 if ( IDYES == MessageBox( GetFocus( ), "Time= 0.0 \nNeustart ?",
  187                                                                   "GenericDetector", MBASK ) )
  188                         return R_Failure;
  189                 else
  190                         return 0;
  191         }
  192 
  193         bActive= FALSE;
  194         bDataValid= TRUE;
  195 
  196         UpdateViews();
  197 
  198         return R_MeasOk;
  199 }
  200 
  201 //##############################################################################
  202 //########## Methoden fuer einen Radicon-Detektor ##############################
  203 //##############################################################################
  204 
  205 const TRange<WORD> TRadicon::DacThreshLimits(0, 1024);
  206 const TRange<WORD> TRadicon::VoltageLimits(400, 900);
  207 TRadiconController* TRadicon::TheEventHardware= 0;
  208 
  209 TRadicon::TRadicon(int id) : DacThresh(150, 1023), TZeroDimDetector(id)
  210 {
  211         //Einlesen von Rdd, Rcc, ...
  212         LoadDetectorSettings();
  213         
  214         //Initialisieren des zugehörigen Controller-Objekts
  215         char szHardwareID[256];
  216         itoa(Rdd,szHardwareID,16);
  217         Hardware= dynamic_cast<TRadiconController*>(GetController(RADICON,szHardwareID,&DetectorControllers,&DetectorDrivers));
  218 }
  219 
  220 TRadicon::~TRadicon( void )
  221 {
  222         SaveDetectorSettings();
  223 }
  224 
  225 void TRadicon::LoadDetectorSettings()
  226 {
  227         char buf[MaxString];
  228 
  229         GetPrivateProfileString( "IOAddr", "0x100", buf);
  230         sscanf( buf, "%x", &Rdd );
  231         Rcc= Rdd + 1;
  232 
  233         GetPrivateProfileString( "UpperThresh", "950", buf);
  234         WORD wUpperThresh= DacThreshLimits.ForceIntoRange(atoi(buf));
  235 
  236         GetPrivateProfileString( "LowerThresh", "150", buf);
  237         WORD wLowerThresh= DacThreshLimits.ForceIntoRange(atoi(buf));
  238 
  239         DacThresh= TRange<WORD>(wLowerThresh, wUpperThresh);
  240 
  241         GetPrivateProfileString( "HighVoltage", "640", buf);
  242         wHighVoltage= VoltageLimits.ForceIntoRange(atoi( buf ));
  243 }
  244 
  245 void TRadicon::SaveDetectorSettings() const
  246 {
  247         char buf[ MaxString ];
  248 
  249         sprintf( buf, "%d", DacThresh.GetMax() );
  250         WritePrivateProfileString( "UpperThresh", buf);
  251         sprintf( buf, "%d", DacThresh.GetMin() );
  252         WritePrivateProfileString( "LowerThresh", buf);
  253         sprintf( buf, "%d", wHighVoltage );
  254         WritePrivateProfileString( "HighVoltage", buf);
  255 }
  256 
  257 BOOL TRadicon::Initialize( void )
  258 {
  259         if (bDebug)
  260                 SetInfo("Initialisieren des Radicon-Detektors");
  261 
  262         TZeroDimDetector::Initialize();
  263 
  264         Hardware->reset();
  265 
  266         if (Hardware->UploadFirmware() != 0 )
  267                 return FALSE;
  268 
  269         if ( SetParameters() == FALSE )
  270                 return FALSE;
  271 
  272         bActive= FALSE;
  273         return TRUE;
  274 }
  275 
  276 BOOL TRadicon::RunSpecificParametersDlg( HWND aParentWnd )
  277 {
  278         TModalDlg *dlg= new TScsParametersDlg( this );
  279         if ( dlg ) dlg->ExecuteDialog( aParentWnd );
  280         _FREEOBJ(dlg);
  281         return TRUE;
  282 }
  283 
  284 void TRadicon::SetHighVoltage(WORD param)
  285 {
  286         wHighVoltage= VoltageLimits.ForceIntoRange(param);
  287 }
  288 
  289 void TRadicon::SetDacThresh(WORD lower, WORD upper)
  290 {
  291         WORD newLower= DacThreshLimits.ForceIntoRange(lower);
  292         WORD newUpper= DacThreshLimits.ForceIntoRange(upper);
  293         DacThresh= TRange<WORD>(newLower, newUpper);
  294 }
  295 
  296 int TRadicon::MeasureStart( void )
  297 {
  298         MeasureStop();
  299 
  300         if ( !GetControlWnd() && !GetCounterWnd() )
  301                 return R_Failure;
  302 
  303         if ( Hardware->Execute( TRadiconController::fixedImpulseCounts ) != 0 )
  304                 return R_Failure;
  305 
  306         dwStartTime= timeGetTime( );
  307 
  308         uAskTime= 300;
  309         bDataValid= FALSE;
  310         bActive= TRUE;
  311 
  312         if ( bDebug )
  313                 SetInfo( "MStart" );
  314 
  315         SetTimer( GetFrameHandle( ), DetectorTimerIdStart + GetId( ), uAskTime, NULL );
  316 
  317         return R_MeasOk;
  318 }
  319 
  320 int TRadicon::MeasureStop( void )
  321 {
  322         if ( !bActive )
  323                 return R_MeasOk;
  324 
  325         KillTimer( GetFrameHandle( ), DetectorTimerIdStart + GetId( ) );
  326 
  327         if ( bDebug )
  328                 SetInfo( "MStop" );
  329 
  330         if ( Hardware->Execute( TRadiconController::stop ) != 0)
  331                 return R_Failure;
  332 
  333         bActive= FALSE;
  334         bDataValid= FALSE;
  335 
  336         return R_MeasOk;
  337 }
  338 
  339 int TRadicon::PollDetector( void )
  340 {
  341         DWORD counts;
  342         double time;
  343 
  344         KillTimer( GetFrameHandle( ), DetectorTimerIdStart + GetId( ) );
  345         bActive= FALSE;
  346 
  347         if ( bDebug )
  348         {
  349                 SetInfo( "MPoll" );
  350                 DelayTime( 10 );
  351         }
  352 
  353         switch ( Hardware->GetValues(TRadiconController::final, &time, &counts ) )
  354         {
  355                 case -4: // Zeit-Bedingung
  356                         dRealTime= MillisecondsToSeconds( timeGetTime( ) - dwStartTime );
  357                         Hardware->GetValues( TRadiconController::intermediate, &time, &counts );
  358 
  359                         if ( GetExposureSettings().GetExposureTime() > time )
  360                         {
  361                                 bActive= TRUE;
  362                                 SetTimer( GetFrameHandle( ), DetectorTimerIdStart + GetId( ), uAskTime, NULL );
  363                                 return R_MeasInProcess;
  364                         }
  365 
  366                         Hardware->Execute( TRadiconController::stop );
  367 
  368                         if ( time == 0.0 )
  369                         {
  370                                 if ( bDebug )
  371                                         SetInfo( "time==0" );
  372 
  373                                 return R_Failure;
  374                         }
  375 
  376                         fIntensity= ( GetExposureSettings().GetExposureCounts() - counts ) / time;
  377                         break;
  378 
  379                 case 0: // Impulse-Bedingung
  380                         if ( time == 0.0 )
  381                         {
  382                                 if ( bDebug )
  383                                         SetInfo( "time==0" );
  384 
  385                                 return R_Failure;
  386                         }
  387 
  388                         fIntensity= GetExposureSettings().GetExposureCounts() / time;
  389                         break;
  390 
  391                 default:
  392                         return R_Failure;
  393         }
  394 
  395         bDataValid= TRUE;
  396         bActive= FALSE;
  397         UpdateViews();
  398 
  399         return R_MeasOk;
  400 }
  401 
  402 BOOL TRadicon::_SetParameters( void )
  403 {
  404         if ( Hardware->SetParameters( DacThresh.GetMax(), DacThresh.GetMin(),
  405                                                                   wHighVoltage, GetExposureSettings().GetExposureTime(),
  406                                                                   GetExposureSettings().GetExposureCounts(), GetSound() ) != 0 )
  407                 return FALSE;
  408 
  409         DelayTime( 5 );
  410         return TRUE;
  411 }
  412 
  413 void CALLBACK TRadicon::EventHandler( UINT, UINT, DWORD, DWORD, DWORD )
  414 {
  415         nEventsCalled++;
  416 
  417         DWORD counts;
  418         double time;
  419         TheEventHardware->GetValues( TRadiconController::intermediate, &time, &counts);
  420 
  421         if ( time != 0.0 )
  422         {
  423                 fEventIntensity= (fEventExposureCounts - counts) / time;
  424                 bEventDataValid= TRUE;
  425         }
  426 
  427         TheEventHardware->Execute( TRadiconController::stop );
  428         PostMessage( hEventControlWnd, WM_COMMAND, cm_CounterSet, nEventsCalled );
  429 
  430         if ( nEventsCalled == nEventsToCall )
  431         {
  432                 timeKillEvent( nEvent );
  433                 PostMessage( hEventControlWnd, WM_COMMAND, cm_SteeringReady, 0l );
  434         }
  435         else
  436                 TheEventHardware->Execute( TRadiconController::fixedImpulseCounts );
  437 }
  438 
  439 BOOL TRadicon::InitializeEvent( HWND hwnd, int ec )
  440 {
  441         if (hwnd == NULL)
  442                 return FALSE;
  443 
  444         // check calltime
  445         int EventTime= 1000.0 * GetExposureSettings().GetExposureTime();
  446         if ( EventTime <= 100 )
  447         {
  448                 MessageBox( GetFocus( ), "Messzeit wurde zu klein gewählt !", "InitializeEvent", MBINFO );
  449                 return FALSE;
  450         }
  451 
  452         SetControlWnd(hwnd);
  453 
  454         nEventsCalled= 0;
  455         nEventsToCall= ec;
  456         fEventExposureCounts= GetExposureSettings().GetExposureCounts();
  457         bDataValid= FALSE;
  458 
  459         // Die Detektor-Hardware ueber eine globale Variable für die statische
  460         // EventHandler-Methode zugaengig machen, die sonst keine konkreten
  461         // Objekte kennt
  462         TheEventHardware= Hardware;
  463 
  464         if ( bActive )
  465                 Hardware->Execute( TRadiconController::stop );
  466 
  467         if ( Hardware->Execute( TRadiconController::fixedImpulseCounts ) != 0 )
  468                 return FALSE;
  469 
  470         //JP Woher sollten jetzt gueltige Daten kommen?
  471         bDataValid= TRUE;
  472 
  473         nEvent= timeSetEvent( EventTime, 1, ( LPTIMECALLBACK ) TRadicon::EventHandler, 0, TIME_PERIODIC );
  474 
  475         return TRUE;
  476 }
  477 
  478 //#############################################################################
  479 // Testdev
  480 //#############################################################################
  481 
  482 const int max_cc= 9;
  483 const int max_tl= 17;
  484 const int max_df= 601;
  485 
  486 //! Basis eines zweifach-indirekten Speicherblock-Zugriffs
  487 long*** Testdev::TestdevData::data= 0;
  488 
  489 //! Instanzenzaehler fuer die Klasse TestdevData
  490 //! Mit ihm wird festgestellt, wann das statische Klassenobjekt data zerstoert
  491 //! werden kann, weil es nicht mehr verwandt wird
  492 int Testdev::TestdevData::instanceCounter= 0;
  493 
  494 //! Der Konstruktor ist fuer das instance counting verantwortlich
  495 Testdev::TestdevData::TestdevData()
  496 {
  497         if (initData() == FALSE)
  498                 PostQuitMessage( 0 );
  499 
  500         instanceCounter++;
  501 }
  502 
  503 //! Der Detruktor gibt bei Bedarf dynamisch Speicher frei
  504 Testdev::TestdevData::~TestdevData()
  505 {
  506         instanceCounter--;
  507 
  508         // rekursives freigeben des Speichers
  509         if ( (instanceCounter == 0) && (data != 0) )
  510         {
  511                 for (int x= 0; x < max_cc; x++)
  512                 {
  513                         for (int y= 0; y < max_tl; y++)
  514                         {
  515                                 _FREELIST(data[x][y]);
  516                         }
  517                         _FREELIST(data[x]);
  518                 }
  519                 _FREELIST(data);
  520         }
  521 }
  522 
  523 //! bietet Zugriff auf die Simulationsdaten
  524 long Testdev::TestdevData::value(int x, int y, int z) const
  525 {
  526         return ( (data == 0) ? 0 : data[x][y][z] );
  527 }
  528 
  529 //! liest die Simulationsdaten aus der testdev.dat und erstellt damit eine
  530 //! Datenspeicherstruktur
  531 BOOL Testdev::TestdevData::initData()
  532 {
  533         if ( data == 0 )
  534         {
  535                 ifstream file( GetTestDevFile() );
  536 
  537                 if (!file.good())
  538                 {
  539                         MessageBox(NULL, "Kann die Datei 'testdev.dat' nicht oeffnen!",
  540                                            "Fehler beim Oeffnen einer Datei", MB_ICONSTOP );
  541                         return FALSE;
  542                 }
  543 
  544                 data= new long**[max_cc];
  545                 if (parseCC(file) == FALSE)
  546                 {
  547                         _FREELIST(data);
  548                         return FALSE;
  549                 }
  550         }
  551         return TRUE;
  552 }
  553 
  554 BOOL Testdev::TestdevData::parseCC(ifstream& file)
  555 {
  556         const int maxlen= 32;
  557         char line[maxlen];
  558 
  559         for (int i= 0; i < max_cc; i++)
  560         {
  561                 file.getline(line, maxlen);
  562                 if (line[0] != 'C')
  563                         return FALSE;
  564 
  565                 data[i]= parseTL(file);
  566                 if ( data[i] == 0 )
  567                         return FALSE;
  568         }
  569         return TRUE;
  570 }
  571 
  572 long** Testdev::TestdevData::parseTL(ifstream& file)
  573 {
  574         const int maxlen= 32;
  575         char line[maxlen];
  576 
  577         long** tl_array= new long * [max_tl];
  578 
  579         for (int i= 0; i < max_tl; i++)
  580         {
  581                 file.getline(line, maxlen);
  582                 if (line[0] != 'T')
  583                 {
  584                         _FREELIST(tl_array);
  585                         return 0;
  586                 }
  587 
  588                 tl_array[i]= parseDF(file);
  589                 if ( tl_array[i] == 0 )
  590                 {
  591                         _FREELIST(tl_array);
  592                         return 0;
  593                 }
  594         }
  595 
  596         return tl_array;
  597 }
  598 
  599 long* Testdev::TestdevData::parseDF(ifstream& file)
  600 {
  601         const int maxlen= 32;
  602         char line[maxlen];
  603 
  604         long* df_array= new long[max_df];
  605 
  606         for (int i= 0; i < max_df; i++)
  607         {
  608                 file.getline(line, maxlen);
  609                 if (line[0] != 'D')
  610                 {
  611                         _FREELIST(df_array);
  612                         return 0;
  613                 }
  614 
  615                 file.getline(line, maxlen);
  616                 if (line[0] != 'I')
  617                 {
  618                         _FREELIST(df_array);
  619                         return 0;
  620                 }
  621 
  622                 df_array[i]= (long)( atof(line + 2) + 0.5 );
  623         }
  624 
  625         return df_array;
  626 }
  627 
  628 //! Der Konstruktor erstellt das Objekt mit den Simulationsdaten
  629 Testdev::Testdev(int id) : TZeroDimDetector(id)
  630 {
  631         data= new TestdevData();
  632 }
  633 
  634 //! Der Destruktor löscht das Objekt mit den Simulationsdaten
  635 Testdev::~Testdev()
  636 {
  637         _FREEOBJ(data);
  638 }
  639 
  640 //! ermittelt den aktuellen Messwert und legt ihn in fIntensity ab
  641 int Testdev::PollDetector( void )
  642 {
  643         if (!bActive)
  644                 return R_Failure;
  645 
  646         KillTimer(hWndFrame, DetectorTimerIdStart + GetId());
  647 
  648         if (bDebug)
  649                 SetInfo("MPoll");
  650 
  651         fIntensity= CalculateIntensity();
  652         fSigma= 0.9f * CalculateSigma( fIntensity, 0.9f );
  653 
  654         bDataValid= TRUE;
  655         bActive= FALSE;
  656         UpdateViews();
  657 
  658         return R_MeasOk;
  659 }
  660 
  661 //! ermittelt die aktuellen Motorpositionen, berechnet die zugehoerige Intensitaet
  662 //! und fuegt Messfehler hinzu
  663 double Testdev::CalculateIntensity() const
  664 {
  665         // Aktuelle Motorpositionen ermitteln
  666         double actDF, actTL, actCC, retValue;
  667         mlGetDistance( mlGetIdByName( Omega ), actDF );
  668         mlGetDistance( mlGetIdByName( Psi ), actTL );
  669         mlGetDistance( mlGetIdByName( Collimator ), actCC );
  670 
  671         // Auf Integer-Werte runden
  672         int DFIndex= ( ( actDF < 0 ) ? actDF - 0.5 : actDF + 0.5 );
  673         int TLIndex= ( ( actTL < 0 ) ? actTL - 0.5 : actTL + 0.5 );
  674         int CCIndex= ( ( actCC < 0 ) ? actCC - 0.5 : actCC + 0.5 );
  675 
  676         // Eingrenzung auf das vermessene Gebiet (s. testdev.dat)
  677         DFIndex= TRange<int>( -300, 300).ForceIntoRange(DFIndex);
  678         TLIndex= TRange<int>( -40, 40).ForceIntoRange(TLIndex);
  679         CCIndex= TRange<int>( -280, 280).ForceIntoRange(CCIndex);
  680 
  681         // Vorbereitung der Interpolation
  682         int TLBias= (TLIndex + 40) % 5;
  683 
  684         // Umsetzung des Winkelwerts in den entsprechenden Feldindex
  685         DFIndex= DFIndex + 300;
  686         TLIndex= (TLIndex + 40) / 5;
  687         CCIndex= (CCIndex + 280) / 70;
  688 
  689         // Auslesen und u.U. Interpolation der korrespondierenden Intensitaet
  690         if ( TLBias )
  691                 retValue= InterPolate( CCIndex, TLIndex, DFIndex, TLBias );
  692         else
  693                 retValue= data->value(CCIndex, TLIndex, DFIndex);
  694 
  695         // Simulation "zufaelliger" Schwankungen (Messfehler)
  696         retValue += (rand() % 10 - 5);
  697 
  698         return retValue;
  699 }
  700 
  701 //! Interpolation zwischen zwei existierenden Messwerten
  702 double Testdev::InterPolate( int ccI, int tlI, int dfI, int tlB ) const
  703 {
  704         double lVal= data->value(ccI, tlI, dfI);
  705         double rVal= data->value(ccI, tlI + 1, dfI);
  706         return ((5 - tlB) * lVal + tlB * rVal) / 5.0;
  707 }
  708 
  709 //#############################################################################
  710 // TZeroDimSimpleTestDetector
  711 //#############################################################################
  712 
  713 TZeroDimSimpleTestDetector::TZeroDimSimpleTestDetector(int id)
  714                 : TZeroDimDetector(id)
  715 {}
  716 
  717 int TZeroDimSimpleTestDetector::PollDetector( void )
  718 {
  719         double angx, angy, angz= 0.0;
  720         //! static int driftcnt= 1; //im auskomm. Teil
  721         //! static BOOL dir= TRUE; //im auskomm. Teil
  722 
  723         if ( !bActive )
  724                 return R_Failure;
  725 
  726         KillTimer( hWndFrame, DetectorTimerIdStart + GetId( ) );
  727 
  728         if ( mlIsAxisValid( Omega ) )
  729         {
  730                 mlGetDistance( mlGetIdByName( Omega ), angx );
  731                 /*
  732                 // Driftsimulation
  733                 angx -= (driftcnt * 0.01104121);
  734                 if((driftcnt == 30) || (driftcnt == 0))
  735                 dir= !dir;
  736                 if(dir)
  737                 driftcnt++;
  738                 else
  739                 driftcnt--;
  740                 */
  741         }
  742         else
  743                 angx= 0.0;
  744 
  745         if ( mlIsAxisValid( Psi ) )
  746         {
  747                 mlGetDistance( mlGetIdByName( Psi ), angy );
  748                 angy += angx * 0.7 - 20.0;
  749         }
  750         else
  751                 angy= 0.0;
  752 
  753         angx= angx * angx / 11.3;
  754         angy= angy * angy / 19.1;
  755         // always zero !
  756         angz= angz * angz / 23.5;
  757 
  758         /*
  759         if(fabs(ang) > 1e5) ang= 10;
  760         // 0. Reflex
  761         fIntensity= 3.2 * 1/(1+pow(ang-2.0,2)*0.02);
  762         // 1. Reflex
  763         fIntensity += 3.2 * exp(-pow(ang-70,2)*0.03);
  764         // 2. Reflex
  765         // fIntensity += 1.0 * exp(-pow(ang+139,2)*0.007);
  766         */
  767         fIntensity= 1 / ( 1 + 1.8 * pow( angx, 2 ) + 0.001 * pow( angy, 2 ) + 
  768                                            0.001 * pow( angz, 2 ) );
  769 
  770         fIntensity *= 32000;
  771 
  772         fIntensity += ( rand( ) % 80 ) + 270;
  773 
  774         bActive= FALSE;
  775 
  776         fSigma= CalculateSigma( fIntensity, 0.9f );
  777 
  778         bDataValid= TRUE;
  779 
  780         UpdateViews();
  781 
  782         return R_MeasOk;
  783 }
  784 
  785 //#############################################################################
  786 // TOneDimTestDetector
  787 //#############################################################################
  788 
  789 TOneDimTestDetector::TOneDimTestDetector(int id) : TOneDimDetector(id)
  790 {}
  791 
  792 
  793 int TOneDimTestDetector::PsdReadOut( EHowReadOutPsd eReadType)
  794 {
  795         DWORD counts;
  796         double argum;
  797 
  798         LPDWORD lpdwCountBuf= (LPDWORD)hCountBuf;
  799         uMaximumChannel= 0;
  800         dwMaxCounts= 0;
  801         dwIntegratedCounts= 0;
  802 
  803         double argum2;
  804         mlGetDistance( mlGetIdByName( Theta ), argum2 );
  805         argum2 /= GetAngleStep();
  806 
  807         for ( int idx= 0; idx < GetChannelNumber(); idx++ )
  808         {
  809                 argum= idx - ( GetChannelNumber() / 2 ) + argum2;
  810                 argum= 1.0 / ( 1.0 + 7.2752e-3 * argum * argum );
  811                 counts= ( DWORD ) ( (rand() % 7) + argum * 200 * MillisecondsToSeconds(dwElapsedTime) );
  812                 //! neu akk
  813                 if ( eReadType != AccumulationRead )
  814                         lpdwCountBuf[idx]= 0; // akkumulierter Signalaufbau: AUS
  815                 //! abhaengigkeit der intens. von der bereits vergangenen Messzeit
  816                 lpdwCountBuf[idx]+= counts;
  817                 dwIntegratedCounts += counts;
  818 
  819                 // Kanal mit Maximum ermitteln
  820                 CheckMaximumChannel(idx, counts);
  821         }
  822         for ( idx; idx < GetBufferSize(); idx++ ) lpdwCountBuf[idx]= 0; // auch Rest der Liste initialisieren - falls GetChannelNumber() vor dem nächsten PsdReadOut() größer wird
  823 
  824         return R_OK;
  825 }
  826 
  827 //############################################################################
  828 // TStoePsd
  829 //############################################################################
  830 
  831 enum { IoWaitStoe= 42 };
  832 
  833 // Der Stoe_PSD wird ueber eine 16Bit PIO kontrolliert.
  834 // Zwei 8255 Chips werden parallel eingesetzt, um eine
  835 // 16bit Ausgabe ueber PORTA und Eingabe ueber PORTB zu realisieren.
  836 // Dabei verarbeitet Chip 1 das low-byte und Chip 2 das high-byte.
  837 enum {
  838         PIO_BASEADR= 0x300,
  839         PIO_PORTA= 0x300,     //= PIO_BASEADR
  840         PIO_PORTB= 0x302,     //= PIO_BASEADR+2
  841         PIO_PORTC= 0x304,     //= PIO_BASEADR+4
  842         PIO_CTRL= 0x306,     //= PIO_BASEADR+6
  843 
  844         // PORTC Bit-Definitionen zum Steuern des PSD
  845         PSD_STOP= 0x000,     // CSR0 & CSR1 =0 : stop PSD
  846         PSD_CSR0= 0x002,
  847         PSD_CSR1= 0x004,
  848         PSD_NDRDY= 0x008,     // New data ready
  849         PSD_DTRNS= 0x010,     // Data transition
  850         PSD_INIT= 0x020,     // Init PSD
  851         PSD_DVAL= 0x100,     // Data valid
  852         PSD_OVF= 0x200  // Overflow
  853 };
  854 
  855 TStoePsd::TStoePsd(int id) : TOneDimDetector(id), hStoeBuf(0) // 30.02.2004 MEMCORRECT (verwende hStoeBuf) , hReadBuf(0)
  856 {
  857         bLong= FALSE;
  858 
  859         LoadDetectorSettings();
  860 }
  861 
  862 TStoePsd::~TStoePsd( void )
  863 {
  864         /* 30.02.2004 MEMCORRECT if ( hReadBuf )
  865                 HeapFree(GetProcessHeap(),0,hReadBuf);
  866         hReadBuf= 0;*/
  867         _FREELIST(hStoeBuf);
  868 
  869         SaveDetectorSettings();
  870 }
  871 
  872 void TStoePsd::LoadDetectorSettings()
  873 {
  874         char buf[ MaxString ];
  875 
  876         GetPrivateProfileString( "BaseAddr", "0x300", buf);
  877         sscanf( buf, "%x", &nBaseAddr );
  878 }
  879 
  880 void TStoePsd::SaveDetectorSettings() const
  881 {
  882         char aBuf[ MaxString ];
  883 
  884         sprintf( aBuf, "0x%x", nBaseAddr ); // 29.01.2003 Kullmann+Reinecker: %d durch 0x%x ersetzt; entdeckt bei der Physik
  885         WritePrivateProfileString( "BaseAddr", aBuf);
  886 }
  887 
  888 int TStoePsd::Initialize( void )
  889 {
  890         if ( ! TOneDimDetector::Initialize( ) )
  891                 return FALSE;
  892 
  893 
  894         // 30.02.2004 MEMCORRECT hReadBuf= (HGLOBAL)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,(GetChannelNumber()+1) * sizeof(WORD));
  895         _FREELIST(hStoeBuf);
  896         hStoeBuf= new WORD[ GetChannelNumber()+1 ];
  897 
  898 
  899         return TRUE;
  900 }
  901 
  902 int TStoePsd::PollDetector( void )
  903 {
  904         char buf[ MaxString ];
  905         int retval= R_MeasOk;
  906 
  907         KillTimer( hWndFrame, DetectorTimerIdStart + GetId( ) );
  908 
  909         bDataValid= FALSE;
  910 
  911         if ( !bActive )
  912                 return R_Failure;
  913 
  914         bActive= FALSE;
  915 
  916         dwElapsedTime= timeGetTime( ) - dwStartTime;
  917 
  918         if ( MillisecondsToSeconds( dwElapsedTime ) < GetExposureSettings().GetExposureTime() )
  919         {
  920                 retval= R_MeasInProcess;
  921                 bActive= TRUE;
  922 
  923                 if ( !bSignalGrowUp )
  924                 {
  925                         //*** Kein stufenweiser Signalaufbau
  926                         SetTimer( hWndFrame, DetectorTimerIdStart + GetId( ), uAskTime, NULL );
  927                         return R_MeasInProcess;
  928                 }
  929 
  930                 //*** Stufenweiser Signalaufbau
  931                 dwElapsedTime= timeGetTime( ) - dwStartTime;
  932 
  933                 PsdStop( );
  934 
  935                 dRealTime= MillisecondsToSeconds( dwElapsedTime );
  936 
  937                 if ( bFirstReadOut )
  938                 {
  939                         PsdReadOut( FirstRead );
  940                         bFirstReadOut= FALSE;
  941                 }
  942 
  943                 else
  944                         PsdReadOut( AccumulationRead );
  945 
  946                 PsdStart( );
  947 
  948                 long lWaitTime= ( timeGetTime( ) - dwStartTime ) - dwElapsedTime;
  949 
  950                 dwStartTime += lWaitTime;
  951 
  952                 SetTimer( hWndFrame, DetectorTimerIdStart + GetId( ), uAskTime, NULL );
  953 
  954                 goto SendNotify;
  955         }
  956 
  957         //*** Messung ist beendet ***
  958         bDataValid= TRUE;
  959 
  960         PsdStop( );
  961 
  962         dRealTime= MillisecondsToSeconds( dwElapsedTime );
  963 
  964         PsdReadOut( AccumulationRead );
  965 
  966 SendNotify:      //*** Benachrichtigen der entsprechenden Fenster ***
  967         if ( bHardOverflow )
  968         {
  969                 strcpy( buf, "Überlauf Psd ( Hochspannung ? )" );
  970                 MessageBeep( 0 );
  971                 retval= R_HardOverflow;
  972         }
  973 
  974         if ( dRealTime == 0.0 )
  975         {
  976                 SetInfo( "dRealTime == 0.0 Fehler Psd" );
  977                 DelayTime( 300 );
  978                 dRealTime= 1.0;
  979                 PsdStop( );
  980                 return R_Failure;
  981         }
  982 
  983         UpdateViews();
  984 
  985         return retval;
  986 }
  987 
  988 int TStoePsd::PsdReadOut( EHowReadOutPsd eReadType )
  989 {
  990         LPDWORD lpdwCountBuf= (LPDWORD)hCountBuf;
  991 
  992         // 30.02.2004 MEMCORRECT (verwende hStoeBuf) LPWORD lpwReadBuf= (LPWORD)hReadBuf;
  993         LPWORD lpwReadBuf= (LPWORD)hStoeBuf;
  994 
  995         int retval= PsdRead( bLong, lpwReadBuf );
  996         if ( retval != R_OK)
  997                 return retval;
  998 
  999         uMaximumChannel= 0;
 1000         dwMaxCounts= 0;
 1001         dwIntegratedCounts= 0;
 1002 
 1003         for ( int idx= 0;idx < GetChannelNumber(); idx++ )
 1004         {
 1005                 if ( eReadType != AccumulationRead )
 1006                         lpdwCountBuf[idx]= 0; // akkumulierter Signalaufbau: AUS
 1007 
 1008                 lpdwCountBuf[ idx ] += lpwReadBuf[ GetChannelNumber() - idx - 1 ];
 1009                 dwIntegratedCounts += lpdwCountBuf[ idx ];
 1010 
 1011                 CheckMaximumChannel(idx, lpdwCountBuf[ idx ] );
 1012         }
 1013         for ( idx; idx < GetBufferSize(); idx++ ) lpdwCountBuf[idx]= 0; // auch Rest der Liste initialisieren - falls GetChannelNumber() vor dem nächsten PsdReadOut() größer wird
 1014 
 1015         return retval;
 1016 }
 1017 
 1018 int TStoePsd::PsdInit( void )
 1019 {
 1020         bReadyForRead= FALSE;
 1021         Delay( IoWaitStoe );
 1022         Hardware.Write(6,(WORD)0x8B82);
 1023         Delay( IoWaitStoe );
 1024         Hardware.Write(4,(WORD)PSD_STOP);
 1025         return R_OK;
 1026 }
 1027 
 1028 int TStoePsd::PsdStart( void )
 1029 {
 1030         bReadyForRead= FALSE;
 1031         Delay( IoWaitStoe );
 1032         Hardware.Write(4,(WORD)PSD_INIT);
 1033         Delay( IoWaitStoe );
 1034         Hardware.Write(4,(WORD)(PSD_CSR0 | PSD_CSR1));
 1035         return R_OK;
 1036 }
 1037 
 1038 int TStoePsd::PsdStop( void )
 1039 {
 1040         bReadyForRead= TRUE;
 1041         Delay( IoWaitStoe );
 1042 
 1043         if ( bDebug )
 1044                 return R_OK;
 1045 
 1046         Hardware.Write(4,(WORD)PSD_STOP);
 1047         Delay( IoWaitStoe );
 1048 
 1049         WORD wValue= 0;
 1050         Hardware.Read(4,&wValue);
 1051         if (wValue & PSD_OVF)
 1052         {
 1053                 bHardOverflow= TRUE;
 1054                 return R_HardOverflow;
 1055         }
 1056 
 1057         return R_OK;
 1058 }
 1059 
 1060 #ifndef _WIN32
1061 int TStoePsd::PsdRead( int bIsLong, LPWORD buf ) 1062 { 1063 /*---------------------------------------------------------------------------- 1064 Integer*2 Function PsdRead ( Long, BufPtr ) 1065 Reads collected data from PSD interface. 1066 integer*2 FirstChannel [ value ]; [bp+14] 1067 integer*2 LastChannel [ value ]; [bp+12] 1068 logical*2 Long [ value ]; [bp+10] 1069 integer*4 BufPtr [ value ]; [bp+6] 1070 Data transfer is initiated by setting the bits PSD_DTRNS and 1071 PSD_NDRDY, then the specified channels are read out and stored. 1072 'BufPtr' is a far pointer to the buffer used. 1073 'Long'= .false. : data are stored as integer*2 1074 = .true. : data are stored as integer*4 1075 Channel numbers range from 0 to 4095 ! 1076 The sequence to read one data word is : 1077 - set bits PSD_DTRNS ( data transition ), 1078 PSD_NDRDY ( new data ready ), 1079 PSD_CSR1 1080 - output inverted channel address to PORTA 1081 - clear bit PSD_NDRDY ( new data ready ) 1082 - wait until bit PSD_DVAL ( data valid ) is set 1083 - read data word from PORTB and store it in Buffer 1084 - clear bit PSD_DTRNS ( data transition ) 1085 When the data have been read the PSD interface is stopped. 1086 Returns:= 0 - no error 1087 > 0 - 'data valid' timeout 1088 returns current channel number + 1 1089 ----------------------------------------------------------------------------*/ 1090 // Symbolische Sprungmarken mit BC 3.1 nicht verfügbar 1091 int val1, val2; 1092 Delay( IoWaitStoe ); 1093 1094 // Altes Signal kann eventuell zur Bestimmung der Overflow- 1095 // Position genutzt werden 1096 if ( bHardOverflow ) 1097 return R_HardOverflow; 1098 1099 // Sichern, daß je Zyklus nur einmal ausgelesen wird 1100 if ( !bReadyForRead ) 1101 return 0; 1102 bReadyForRead= FALSE; 1103 1104 int FirstCh= GetFirstChannel(); 1105 int LastCh= GetLastChannel(); 1106 1107 _asm { 1108 // si,di retten 1109 push di 1110 push si 1111 // initiate data transfer 1112 mov dx, 0x304 // PC 1113 mov ax, PSD_DTRNS OR PSD_NDRDY 1114 out dx, ax 1115 mov bx, FirstCh 1116 mov cx, LastCh 1117 sub cx, bx 1118 inc cx 1119 mov si, bIsLong 1120 les di, buf 1121 next: 1122 xor ax, ax 1123 jcxz ready 1124 mov dx, 0x304 //PC 1125 mov ax, PSD_DTRNS OR PSD_NDRDY OR PSD_CSR1 1126 out dx, ax 1127 // jmp 0 1128 mov dx, 0x300 // PA 1129 mov ax, bx 1130 not ax 1131 and ax, 0x0FFF 1132 out dx, ax 1133 // clear PSD_NDRDY 1134 mov dx, 0x304 //PC 1135 mov ax, PSD_DTRNS OR PSD_CSR1 1136 out dx, ax 1137 mov val1, 0xFFFF 1138 mov val2, 15 1139 read1: 1140 mov dx, 0x304 //PC 1141 in ax, dx 1142 test ax, PSD_DVAL 1143 jnz read2 1144 dec val1 1145 jnz read1 1146 dec val2 1147 jnz read1 1148 mov ax, bx 1149 inc ax 1150 jmp short ready 1151 read2: 1152 mov dx, 0x302 // PB 1153 in ax, dx 1154 stosw 1155 or si, si 1156 jz read3 1157 xor ax, ax 1158 stosw 1159 read3: 1160 mov dx, 0x304 //PC 1161 mov ax, PSD_NDRDY OR PSD_CSR1 // delete PSD_DTRNS 1162 out dx, ax 1163 dec cx 1164 inc bx 1165 jmp short next 1166 ready: 1167 push ax 1168 mov dx, 0x304 // PC 1169 mov ax, PSD_STOP 1170 out dx, ax 1171 pop ax 1172 pop si 1173 pop di 1174 } 1175 1176 return R_OK; 1177 }
1178 #else 1179 int TStoePsd::PsdRead( int bIsLong, LPWORD buf ) 1180 { 1181 return R_OK; 1182 } 1183 #endif 1184 1185 //############################################################################## 1186 //******************* Methoden fuer den BraunPSD ****************************** 1187 //############################################################################## 1188 1189 union long_to_bytes 1190 { 1191 LONG LWert; 1192 WORD IWert[ 2 ]; 1193 BYTE SWert[ 4 ]; 1194 }; 1195 1196 struct MessDatenHeader 1197 { 1198 long HighADCCounts; 1199 long LowADCCounts; 1200 long HighEGYCounts; 1201 long LowEGYCounts; 1202 long HighPOSCounts; 1203 long LowPOSCounts; 1204 long HSumDetCounts; 1205 long LSumDetCounts; 1206 long RateADC; 1207 long RateEGY; 1208 long RatePOS; 1209 long RateDET; 1210 long Messzeit; 1211 long HVParameter; 1212 long EndLifeTime; 1213 long Ueberlauf; 1214 } 1215 Header; 1216 1217 const char* TBraunError[ 40 ][ 40 ] = { 1218 /* 0 */ {" Detektor 1. anwaehlen" }, 1219 /* 1 */ {" Messung abbrechen mit Shutter"}, 1220 /* 2 */ {" Messung abbrechen ohne Shutter"}, 1221 /* 3 */ {" Kein Datenfluss zum PC "}, 1222 /* 4 */ {"Energieskalierung "}, 1223 /* 5 */ {"Positionsskalierung "}, 1224 /* 6 */ {"obere Grenze fuer Energiefenster "}, 1225 /* 7 */ {"untere Grenze fuer Energiefenster "}, 1226 /* 8 */ {"Energie-Counts fuer Countstop "}, 1227 /* 9 */ {"Konstante f.Lifetimeberechnungen "}, 1228 /* 10 */ {"mindest notwendigen Impulsabstand "}, 1229 /* 11 */ {"externes Ratemeter selektieren "}, 1230 /* 12 */ {"Multiplexerzeit f. Detektor 1 "}, 1231 /* 13 */ {"HV-Regelung aus "}, 1232 /* 14 */ {"HV-Regelung starten "}, 1233 /* 15 */ {"Real/Lifetimestop "}, 1234 /* 16 */ {"Positions-Counts f. Countstop "}, 1235 /* 17 */ {"Messzeit einstellen "}, 1236 /* 18 */ {"AD-Counts loeschen "}, 1237 /* 19 */ {"Det. Counts loeschen"}, 1238 /* 20 */ {"Positionsdaten loeschen"}, 1239 /* 21 */ {"Messung starten"}, 1240 /* 22 */ {"Messung gestartet ?"}, 1241 /* 23 */ {"Messung gestoppt ?"}, 1242 /* 24 */ {"Positionsdaten loeschen"}, 1243 /* 25 */ {"Positions-Counts loeschen"}, 1244 /* 26 */ {"Energie-Counts loeschen"}, 1245 /* 27 */ {"Energiedaten senden"}, 1246 /* 28 */ {"Positionsdaten senden"}, 1247 /* 29 */ {"Multiplexerzeit f. Detektor 2 "}, 1248 /* 30 */ {"Headerlaenge pruefen"}, 1249 /* 31 */ {"Overflow d. Positionsdaten"}, 1250 /* 32 */ {"Positionsdaten lesen"}, 1251 /* 33 */ {"Hexfile synchronisieren "}, 1252 /* 34 */ {"Hexfile Test auf Hexziffer"}, 1253 /* 35 */ {"Hexfile suchen und öffnen"}, 1254 /* 36 */ {"Hexfile Echo lesen und vergleichen"}, 1255 /* 37 */ {"Hexfile laden mit Handshake"}, 1256 /* 38 */ {"Speicher allokieren "}, 1257 /* 39 */ {"Hardware nicht verfügbar"} 1258 }; 1259 1260 BYTE TBraunPsd::befehl[ 30 ][ 16 ]= { 1261 {3, 255, 59, 254}, // 0. Detektor1 angewaehlt 1262 {4, 255, 68, 36, 254}, // 1. Messung abbrechen Shutter schliessen 1263 {4, 255, 68, 37, 254}, // 2. Messung abbrechen ohne Shutter 1264 {3, 255, 48, 254}, // 3. no Data to PC 1265 {4, 255, 65, 0, 254}, // 4. Energieskalierung 1266 {4, 255, 66, 0, 254}, // 5. Positionsskalierung 1267 {5, 255, 80, 0, 0, 254}, // 6. obere Grenz. Energiefen. 1268 {5, 255, 81, 0, 0, 254}, // 7. untere " " 1269 {9, 255, 144, 255, 255, 255, 255, 255, 239, 254}, //8. E-Counts fuer Stop 1270 {5, 255, 87, 115, 5, 254}, // 9. Konstante 0573 hex 1271 {4, 255, 64, 0, 254}, // 10. notw. Impulsabstand 1272 //{4, 255, 69, 0, 254}, // 11. extern. Ratemeter - computed counts (hp) 1273 {4, 255, 69, 1, 254}, // 11. extern. Ratemeter - total counts (hp) 1274 {5, 255, 84, 100, 0, 254}, // 12. Muxzeit Det 1. 64 hex 1275 {6, 255, 103, 0, 4, 0, 254}, // 13. HV-Regelung aus 1276 {6, 255, 103, 0, 4, 4, 254}, // 14. HV-Regelung ein 1277 {4, 255, 70, 0, 254}, // 15. Real/Lifetimestop 1278 {9, 255, 145, 255, 255, 255, 255, 255, 239, 254}, //16. Positionsstop 1279 {6, 255, 96, 127, 150, 152, 254}, // 17. Messzeit =9999999 sec. 1280 {3, 255, 53, 254 }, // 18. AD-Counts loeschen 1281 {4, 255, 73, 0, 254}, // 19. Det. Counts loeschen 1282 {5, 255, 82, 81, 82, 254}, // 20. Energiedaten loeschen 1283 {3, 255, 49, 254}, // 21. Messung starten 1284 {3, 255, 51, 254}, // 22. Messung gestartet ja ? 1285 {3, 255, 51, 254}, // 23. Messung gestoppt ? 1286 {5, 255, 83, 81, 83, 254}, // 24. Positionsdaten loeschen 1287 {3, 255, 57, 254}, // 25. Positions-Counts loeschen 1288 {3, 255, 55, 254}, // 26. Energie-Counts loeschen 1289 {4, 255, 67, 0, 254}, // 27. Energiedaten senden 1290 {4, 255, 67, 1, 254}, // 28. Positionsdaten senden 1291 {5, 255, 85, 0, 0, 254} }; // 29. Muxzeit Det 2. 0 hex 1292 1293 BYTE TBraunPsd::echo[ 30 ][ 16 ]= { 1294 {2, 255, 59}, 1295 {2, 255, 68}, 1296 {2, 255, 68}, 1297 {2, 255, 48}, 1298 {4, 255, 65, 254, 0}, 1299 {4, 255, 66, 254, 0}, 1300 {6, 255, 80, 254, 0, 254, 0}, 1301 {6, 255, 81, 254, 0, 254, 0}, 1302 {14, 255, 144, 254, 255, 254, 255, 254, 255, 254, 255, 254, 255, 254, 239}, 1303 {6, 255, 87, 254, 115, 254, 5}, 1304 {4, 255, 64, 254, 0}, 1305 {4, 255, 69, 254, 0}, 1306 {6, 255, 84, 254, 100, 254, 0}, 1307 {7, 255, 103, 0, 254, 4, 254, 0}, 1308 {7, 255, 103, 0, 254, 4, 254, 4}, 1309 {4, 255, 70, 254, 0}, 1310 {14, 255, 145, 254, 255, 254, 255, 254, 255, 254, 255, 254, 255, 254, 239}, 1311 {7, 255, 96, 127, 254, 150, 254, 152}, 1312 {2, 255, 53}, 1313 {2, 255, 73}, 1314 {2, 255, 82}, 1315 {2, 255, 49}, 1316 {4, 255, 51, 254, 1}, 1317 {4, 255, 51, 254, 0}, 1318 {2, 255, 83}, 1319 {2, 255, 57}, 1320 {2, 255, 55}, 1321 {4, 255, 67, 254, 0}, 1322 {4, 255, 67, 254, 1}, 1323 {6, 255, 85, 254, 0, 254, 0}}; 1324 1325 typedef void (*TSetPort) ( WORD, WORD ); 1326 typedef BYTE (*TGetPort) ( WORD ); 1327 typedef void (*TSetTimeout) ( DWORD ); 1328 typedef int (*TGetData ) ( WORD, WORD, WORD, LPLONG, WORD, long& ); 1329 1330 TSetPort lpfnSetPort; 1331 TGetPort lpfnGetPort; 1332 TSetTimeout lpfnSetTimeout; 1333 TGetData lpfnGetData; 1334 1335 //******** Funktionen ********************************************************** 1336 TBraunPsd::TBraunPsd(int id) : TOneDimDetector(id), Hardware(0) // 31.06.2004 MEMCORRECT hReadBuf(0) 1337 { 1338 long_to_bytes transform; 1339 1340 LoadDetectorSettings(); 1341 1342 bSetError= FALSE; 1343 1344 transform.IWert[ 0 ]= ( WORD ) uMuxTimeDet1; 1345 befehl[ 12 ][ 3 ]= transform.SWert[ 0 ]; 1346 echo[ 12 ][ 4 ]= transform.SWert[ 0 ]; 1347 befehl[ 12 ][ 4 ]= transform.SWert[ 1 ]; 1348 echo[ 12 ][ 6 ]= transform.SWert[ 1 ]; 1349 1350 if(bRatemeter) 1351 { //Ratemeter=1 -> total counts 1352 befehl[ 11 ][ 3 ]= 1; 1353 echo[ 11 ][ 4 ]= 1; 1354 } 1355 else 1356 { //Ratemeter=0 -> computed counts 1357 befehl[ 11 ][ 3 ]= 0; 1358 echo[ 11 ][ 4 ]= 0; 1359 } 1360 1361 befehl[ 15 ][ 3 ]= ( WORD ) bRealLifeTime; 1362 echo[ 15 ][ 4 ]= ( WORD ) bRealLifeTime; 1363 1364 befehl[ 10 ][ 3 ]= ( WORD ) nDeathTime; 1365 echo[ 10 ][ 4 ]= ( WORD ) nDeathTime; 1366 1367 /* 31.06.2004 MEMCORRECT hReadBuf= (HGLOBAL)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,GetBufferSize() * sizeof(DWORD)); 1368 if ( NULL == hReadBuf ) 1369 { 1370 bSetError= TRUE; 1371 nErrorCode= 38; 1372 // Message 1373 return; 1374 }*/ 1375 } 1376 1377 TBraunPsd::~TBraunPsd( void ) 1378 { 1379 char HeadLine[]= "Braun-Psd: Destruktor"; 1380 int ExitList[ 3 ]= {2, 3, 13}; 1381 1382 bSetError= FALSE; 1383 1384 for ( int i= 0;i < 3;i++ ) 1385 if ( 0 != BuildOperation( &( befehl[ ExitList[ i ] ][ 0 ] ), &( echo[ ExitList[ i ] ][ 0 ] ), nDelayFast ) ) 1386 { 1387 nErrorCode= ExitList[ i ]; 1388 MessageBox( GetFocus( ), TBraunError[ nErrorCode ][ 0 ], HeadLine, MBFAILURE ); 1389 bSetError= TRUE; 1390 break; 1391 } 1392 1393 /* 31.06.2004 MEMCORRECT if (hReadBuf) 1394 HeapFree(GetProcessHeap(),0,hReadBuf); 1395 hReadBuf= 0;*/ 1396 1397 SaveDetectorSettings(); 1398 } 1399 1400 void TBraunPsd::LoadDetectorSettings() 1401 { 1402 char buf[ MaxString ]; 1403 1404 GetPrivateProfileString( "DelayFast", "2", buf); 1405 nDelayFast= atoi( buf ); 1406 1407 GetPrivateProfileString( "DelaySlow", "4", buf); 1408 nDelaySlow= atoi( buf ); 1409 1410 GetPrivateProfileString( "BaseAddr", "0x300", buf); 1411 sscanf( buf, "%x", &nBaseAddr ); 1412 1413 //Initialisieren des zugehörigen HardwareIo-Objekts 1414 char szHardwareID[256]; 1415 itoa(nBaseAddr,szHardwareID,16); 1416 Hardware= dynamic_cast<TBraunPsdController*>(GetController(BRAUN,szHardwareID,&DetectorControllers,&DetectorDrivers)); 1417 1418 GetPrivateProfileString( "AbbruchMitShutter", "0", buf); 1419 bAbbruchmitShutter= ( 0 < atoi( buf ) ); 1420 1421 GetPrivateProfileString( "EnergyLow", "526", buf); 1422 UINT lg= (UINT) atoi( buf ); 1423 1424 GetPrivateProfileString( "EnergyHigh", "870", buf); 1425 UINT hg= (UINT) atoi( buf ); 1426 // benötigt <uEnergyScale> und <nDelaySlow>, <nDelayFast> 1427 SetEnergyRange(lg, hg); 1428 1429 GetPrivateProfileString( "MuxTimeDet1", "40", buf); 1430 uMuxTimeDet1= atoi( buf ); 1431 if ( uMuxTimeDet1 > 0xEFFF ) 1432 uMuxTimeDet1= 0x64; 1433 1434 GetPrivateProfileString( "Ratemeter", "1", buf); 1435 bRatemeter= ( atoi( buf ) != 0 ); 1436 1437 GetPrivateProfileString( "RealLifeTime", "0", buf); 1438 bRealLifeTime= ( atoi( buf ) != 0); 1439 1440 GetPrivateProfileString( "DeathTime", "10", buf); 1441 nDeathTime= atoi( buf ); 1442 if ( nDeathTime > 99 ) 1443 nDeathTime= 10; 1444 } 1445 1446 void TBraunPsd::SaveDetectorSettings() const 1447 { 1448 char aBuf[ MaxString ]; 1449 1450 sprintf( aBuf, "0x%x", nBaseAddr ); // 29.01.2003 Kullmann+Reinecker: %d durch 0x%x ersetzt; entdeckt bei der Physik 1451 WritePrivateProfileString( "BaseAddr", aBuf); 1452 1453 UINT lg, hg; 1454 GetEnergyRange(lg, hg); 1455 sprintf( aBuf, "%u", lg ); // umrechnen auf Scale 1456 WritePrivateProfileString( "EnergyLow", aBuf); 1457 1458 sprintf( aBuf, "%u", hg ); // umrechnen auf Scale 1459 WritePrivateProfileString( "EnergyHigh", aBuf); 1460 } 1461 1462 BOOL TBraunPsd::Initialize( void ) 1463 { 1464 if ( ! TOneDimDetector::Initialize( ) ) 1465 return FALSE; 1466 1467 return TRUE; 1468 } 1469 1470 int TBraunPsd::PsdReadOut( EHowReadOutPsd eReadType ) 1471 { 1472 UINT wordstoread; 1473 char HeadLine[]= "Braun-Psd: PsdReadOut()"; 1474 int retval= R_OK; 1475 int idx, bid; 1476 int nDelay= nDelaySlow; 1477 char *lpdwReadBuf= 0; 1478 long_to_bytes HVTest; 1479 1480 bSetError= FALSE; 1481 1482 // Bei hoher Interrupt-Rate des Controllers ist eine größeres Delay zu verwenden 1483 if ( Header.HighADCCounts < 6000 ) nDelay += 1; 1484 else if ( Header.HighADCCounts < 8000 ) nDelay += 2; 1485 else if ( Header.HighADCCounts < 12000 ) nDelay += 3; 1486 else if ( Header.HighADCCounts < 15000 ) nDelay += 4; 1487 else nDelay= 5; 1488 1489 //DelayTime( 1 ); 1490 // sprintf(::buf,"Detektor-Rate: %ld", Header.HighADCCounts); 1491 // Main.SetInfoLine(::buf); 1492 1493 bid= ( ( eDataType == PsdEnergyData ) ? 27 : 28); 1494 1495 if ( BuildOperation( &( befehl ) [ bid ][ 0 ], &( echo ) [ bid ][ 0 ], nDelay ) ) 1496 { 1497 bSetError= TRUE; 1498 nErrorCode= bid; 1499 MessageBox(GetFocus(),TBraunError[nErrorCode][0],HeadLine, MBFAILURE); 1500 return R_Failure; 1501 } 1502 1503 // Daten vom Psd lesen 1504 IrpParamsGetData DataBuf; 1505 1506 //24.06.2004 if (eDataType == PsdEnergyData) wordstoread= ( 8192 >> uEnergyScale ); 1507 //24.06.2004 else wordstoread= ( 8192 >> uPositionScale ); 1508 // immer für Scale= 0 auslesen (Werte werden später zusammengefasst) 1509 wordstoread= GetBufferSize()/2; // Größe des reservierten Speichers (in Byte) umrechnen in Word (besteht aus zwei Bytes) 1510 1511 // 31.06.2003 MEMCORRECT lpdwReadBuf= (LPDWORD)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,wordstoread * 2); 1512 lpdwReadBuf= new char[GetBufferSize()+1]; // Speicher in Bytes (zwei Byte = ein Word) - GetBufferSize muss restfrei durch 4 teilbar sein! 1513 1514 if(!lpdwReadBuf) 1515 { 1516 bSetError= TRUE; 1517 nErrorCode= 1; 1518 return R_Failure; 1519 } 1520 for (idx= 0; idx<GetBufferSize()+1; idx++) lpdwReadBuf[idx]= 0; // sicherheitshalber initialisieren, falls nicht alle Messwerte gelesen werden können 1521 DataBuf.pBuffer= (PUCHAR)lpdwReadBuf; 1522 DataBuf.MaxCount= wordstoread; 1523 1524 //Daten vom PSD einlesen 1525 if ( Hardware ) Hardware->GetData(&DataBuf); 1526 1527 if ( !Hardware || DataBuf.MaxCount != wordstoread) 1528 { 1529 /* 31.06.2004 MEMCORRECT if(lpdwReadBuf) 1530 HeapFree(GetProcessHeap(),0,lpdwReadBuf); 1531 lpdwReadBuf= 0;*/ 1532 _FREELIST(lpdwReadBuf); 1533 1534 bSetError= TRUE; 1535 1536 if ( !Hardware ) nErrorCode= 39; 1537 else nErrorCode= 31; 1538 MessageBox(GetFocus(),TBraunError[nErrorCode][0],HeadLine, MBFAILURE); 1539 return R_Failure; 1540 } 1541 1542 // Überlauf aufgetreten ? 1543 memcpy((LPLONG)&Header, (LPLONG)lpdwReadBuf, sizeof(MessDatenHeader)); 1544 1545 if (Header.Ueberlauf & 0x80) 1546 { 1547 /* 31.06.2004 MEMCORRECT if(lpdwReadBuf) 1548 HeapFree(GetProcessHeap(),0,lpdwReadBuf); 1549 lpdwReadBuf= 0;*/ 1550 _FREELIST(lpdwReadBuf); 1551 1552 nErrorCode= 30; 1553 bSetError= TRUE; 1554 MessageBox( GetFocus( ), TBraunError[ nErrorCode ][ 0 ], HeadLine, MBFAILURE ); 1555 bHardOverflow= TRUE; 1556 return R_HardOverflow; 1557 }; 1558 1559 if (GetHVControl()) 1560 { 1561 float val; 1562 1563 HVTest.LWert= Header.HVParameter; 1564 val= ( float ) ( int ) ( HVTest.IWert[ 0 ] - HVTest.IWert[ 1 ] ) / HVTest.IWert[ 0 ] * 100.0; 1565 char buf[ MaxString ]; 1566 sprintf( buf, "dHV : %.1f %%", val ); 1567 SetStatus( buf ); 1568 nHVControl_OK= ( int ) val; 1569 } 1570 else 1571 nHVControl_OK= 0; 1572 1573 // Speicherreservierung übernehmen 1574 LPDWORD lpdwCountBuf= (LPDWORD)hCountBuf; 1575 1576 // 31.06.2004 MEMCORRECT LPSTR lpReadBufOffset= (LPSTR)( lpdwReadBuf + 16 ); 1577 1578 unsigned long *caster= (unsigned long*)( lpdwReadBuf + sizeof(MessDatenHeader) ); 1579 // Anzahl der Kanäle für GetData() setzen 1580 if ( eDataType != PsdEnergyData ) // Positionsspektrum (Energiespektrum hat immer volle Kanalanzahl) 1581 caster+= max(0, GetFirstChannel() << uPositionScale); 1582 1583 //die ersten 16 Kanäle (Sonderkanäle) sind schon ausgewertet und lpReadBufOffset entsprechend angepaßt 1584 //memcpy( (LPSTR) lpdwCountBuf, lpReadBufOffset,GetChannelNumber() * sizeof(long)); 1585 // 31.06.2004 MEMCORRECT memcpy( (LPSTR) lpdwCountBuf, lpReadBufOffset, (GetChannelNumber()-16) * sizeof(long)); 1586 1587 dwIntegratedCounts= 0l; 1588 uMaximumChannel= 0; 1589 dwMaxCounts= 0; 1590 if ( eDataType == PsdEnergyData ) // Energiespektrum 1591 { 1592 // ausgelesen wurden Messwerte für <MaxChannels>-Kanäle 1593 // hier: Überspringen von Kanälen, entsprechend <EnergyScale> 1594 // d.h. bei Scale= 0 wird jeder, bei Scale= 1 nur jeder zweite, bei Scale= 2 nur jeder vierte Messwert übernommen, usw. 1595 // ÄNDERUNG: Die Messwerte werden nicht übersprungen, es wird das Maximum aus den übersprungenen Messwerten gebildet. 1596 for ( idx= 0; idx < GetChannelNumber(); idx++ ) 1597 { 1598 // Umrechnung auf Messwert (ggf. Auslassung von Kanälen entsprechend Scale) 1599 int channel= idx << uEnergyScale; 1600 1601 // Intensität in diesem Kanalfenster 1602 unsigned long intens= caster[channel]; 1603 for ( int window= 1; window < (1<<uEnergyScale); window++ ) 1604 { 1605 intens= max( caster[channel+window], intens ); // nehme maximale Intensität in diesem Fenster 1606 } 1607 1608 // Werte permanent übernehmen, integrale Intensität berechnen und auf Maximalintensität (und -kanal) prüfen 1609 if ( eReadType != AccumulationRead ) 1610 lpdwCountBuf[idx]= 0; // akkumulierter Signalaufbau: AUS 1611 1612 lpdwCountBuf[idx]+= intens; 1613 dwIntegratedCounts+= intens; 1614 CheckMaximumChannel(idx, lpdwCountBuf[idx]); 1615 } 1616 } else { // Positionsspektrum 1617 // ausgelesen wurden Messwerte für <MaxChannels>-Kanäle 1618 // hier: Zusammenfassen von Kanälen, entsprechend <PositionScale> 1619 // d.h. bei Scale= 0 wird ein, bei Scale= 1 werden zwei, bei Scale= 2 werden vier Messwerte zusammengefasst (addiert), usw. 1620 for ( idx= 0; idx < GetChannelNumber(); idx++ ) 1621 { 1622 // Umrechnung auf Messwert (ggf. Auslassung von Kanälen entsprechend Scale) 1623 int channel= idx << uPositionScale; 1624 1625 // Intensität in diesem Kanalfenster 1626 unsigned long intens= caster[channel]; 1627 for ( int window= 1; window < (1<<uPositionScale); window++ ) 1628 { 1629 intens+= caster[channel+window]; // addiere Messwerte zu einem Gesamtwert 1630 } 1631 1632 // Werte permanent übernehmen, integrale Intensität berechnen und auf Maximalintensität (und -kanal) prüfen 1633 if ( eReadType != AccumulationRead ) 1634 lpdwCountBuf[idx]= 0; // akkumulierter Signalaufbau: AUSakkumulierter Signalaufbau: AUS 1635 lpdwCountBuf[idx]+= intens; 1636 dwIntegratedCounts+= intens; 1637 CheckMaximumChannel(idx, lpdwCountBuf[idx]); 1638 } 1639 } 1640 1641 for ( idx; idx < GetBufferSize(); idx++ ) lpdwCountBuf[idx]= 0; // auch Rest der Liste initialisieren - falls GetChannelNumber() vor dem nächsten PsdReadOut() größer wird 1642 1643 /* 31.06.2003 MEMCORRECT if ( lpdwReadBuf ) 1644 HeapFree(GetProcessHeap(), 0, lpdwReadBuf); 1645 lpdwReadBuf= 0;*/ 1646 _FREELIST(lpdwReadBuf); 1647 1648 return retval; 1649 } 1650 1651 int TBraunPsd::PsdInit( void ) 1652 { 1653 char HeadLine[ ]= "Braun-Psd: Init()"; 1654 int i; 1655 int nDelay= nDelayFast; 1656 const int CntLst= 21; 1657 //! BOOL FirstTime= FALSE; 1658 int InitList[ CntLst ]= {1, 2, 3, 0, 4, 5, 6, 7, 8, 16, 9, 20, 10, 11, 12, 13, 14, 15, 17, 26, 29}; 1659 1660 bSetError= FALSE; 1661 1662 if ( bDebug ) 1663 { 1664 SetInfo( "Debug BPsd" ); 1665 return R_OK; 1666 } 1667 1668 /*// FIX: PSD-INIT nur mit Scale= 0 möglich 1669 UINT realEnergyScale= SetEnergyScale(0); 1670 UINT realPositionScale= SetPositionScale(0);*/ 1671 1672 Hardware->SetTimeout(10000); 1673 ResetDelayTime( ); 1674 1675 if ( LoadHexFile( ) != R_OK ) 1676 { 1677 MessageBox( GetFocus( ), TBraunError[ nErrorCode ][ 0 ], HeadLine, MBFAILURE ); 1678 1679 /*// FIX: PSD-INIT nur mit Scale= 0 möglich 1680 SetEnergyScale(realEnergyScale); 1681 SetPositionScale(realPositionScale);*/ 1682 1683 return R_Failure; 1684 } 1685 1686 //warten, bis Hexfile im Controller verarbeitet 1687 Sleep(1000); 1688 1689 // entsprechend der Einstellungen im INI-File initialisieren 1690 for ( i= 0;i < CntLst;i++ ) 1691 { 1692 if ( ( ! GetHVControl() ) && ( InitList[ i ] == 14 ) ) 1693 continue; 1694 1695 if ( ( GetHVControl() ) && ( InitList[ i ] == 13 ) ) 1696 continue; 1697 1698 if ( ( !bAbbruchmitShutter ) && ( InitList[ i ] == 1 ) ) 1699 continue; 1700 1701 if ( ( bAbbruchmitShutter ) && ( InitList[ i ] == 2 ) ) 1702 continue; 1703 1704 if ( (InitList[i] == 3) || (InitList[i] == 4) ) 1705 nDelay += 1; 1706 1707 if ( 0 != BuildOperation( &( befehl ) [ InitList[ i ] ][ 0 ], &( echo ) [ InitList[ i ] ][ 0 ], nDelay ) ) 1708 { 1709 nErrorCode= InitList[ i ]; 1710 bSetError= TRUE; 1711 MessageBox( GetFocus( ), TBraunError[ nErrorCode ][ 0 ], HeadLine, MBFAILURE ); 1712 1713 /*// FIX: PSD-INIT nur mit Scale= 0 möglich 1714 SetEnergyScale(realEnergyScale); 1715 SetPositionScale(realPositionScale);*/ 1716 1717 return R_Failure; 1718 } 1719 } 1720 1721 // Initialisierung wie im ASA-Programm (nur an dieser Stelle!!!) 1722 { // ohne Fehlerabfrage aus PsdStart() übernommen 1723 int StartList[ 7 ]= { 18, 19, 21, 22, 24, 25, 26}; 1724 int CntLst= 7; // Anzahl der Kommandos 1725 int nDelay= nDelayFast; 1726 for (int i= 0; i < CntLst; i++ ) { 1727 if ( StartList[i]==22 || StartList[i]==24 ) nDelay += 1; 1728 BuildOperation( &( befehl ) [ StartList[i] ][ 0 ], &( echo ) [ StartList[i] ][ 0 ], nDelay ); 1729 } 1730 } 1731 1732 /*// FIX: PSD-INIT nur mit Scale= 0 möglich 1733 SetEnergyScale(realEnergyScale); 1734 SetPositionScale(realPositionScale);*/ 1735 1736 return R_OK; 1737 } 1738 1739 int TBraunPsd::PsdStart( void ) 1740 { 1741 char HeadLine[ ]= "Braun-Psd: PsdStart()"; 1742 int StartList[ 8 ]= { /* Konstanter Teil */ 18, 19, 21, 22, 1743 /* Variabler Teil */ 24, 25, 26, 20}; 1744 // old {0,18,19,20,24,25,26,21,22}; 1745 int CntLst= 7; // Anzahl der Kommandos 1746 int nDelay= nDelayFast; 1747 1748 // Regelung läuft wahrscheinlich ständig autark im Controller 1749 // Mode Energiedaten anzeigen 20 1750 // Mode Positionsdaten anzeigen 24 1751 // Regelung sollen Energiedaten nicht gelöscht werden 1752 1753 if ( eDataType == PsdEnergyData ) 1754 CntLst= 8; 1755 1756 bSetError= FALSE; 1757 1758 for ( int i= 0; i < CntLst; i++ ) 1759 { 1760 switch ( StartList[ i ] ) 1761 { 1762 case 24: 1763 case 20: 1764 case 22: 1765 nDelay += 1; 1766 break; 1767 } 1768 1769 if ( 0 != BuildOperation( &( befehl ) [ StartList[ i ] ][ 0 ], &( echo ) [ StartList[ i ] ][ 0 ], nDelay ) ) 1770 { 1771 nErrorCode= StartList[ i ]; 1772 bSetError= TRUE; 1773 MessageBox( GetFocus( ), TBraunError[ nErrorCode ][ 0 ], HeadLine, MBFAILURE ); 1774 return R_Failure; 1775 } 1776 } 1777 1778 return R_OK; 1779 } 1780 1781 int TBraunPsd::PsdStop( void ) 1782 { 1783 char HeadLine[ ]= "Braun-Psd: PsdStop"; 1784 int nDelay= nDelayFast; 1785 const int CntLst= 3; 1786 int StopList[ CntLst ]= {2, 1, 23}; // 2,1,23,28 1787 1788 bSetError= FALSE; 1789 1790 for ( int i= 0;i < CntLst;i++ ) 1791 { 1792 if ( StopList[i] == 23 ) 1793 nDelay += 1; 1794 1795 if ( ( !bAbbruchmitShutter ) && ( StopList[ i ] == 1 ) ) 1796 continue; 1797 1798 if ( ( bAbbruchmitShutter ) && ( StopList[ i ] == 2 ) ) 1799 continue; 1800 1801 if ( 0 != BuildOperation( &( befehl ) [ StopList[ i ] ][ 0 ], &( echo ) [ StopList[ i ] ][ 0 ], nDelay ) ) 1802 { 1803 nErrorCode= StopList[ i ]; 1804 bSetError= TRUE; 1805 MessageBox( GetFocus( ), TBraunError[ nErrorCode ][ 0 ], HeadLine, MBFAILURE ); 1806 return R_Failure; 1807 } 1808 } 1809 1810 return R_OK; 1811 } 1812 1813 /////////////////////////////////////////////////////////////////////////////// 1814 // GET-/ SET-Methoden 1815 /////////////////////////////////////////////////////////////////////////////// 1816 1817 UINT TBraunPsd::SetEnergyScale(UINT aEnergyScale) { 1818 UINT result= TOneDimDetector::SetEnergyScale(aEnergyScale); 1819 1820 // Werte immer für Scale= 0 auslesen (Werte werden am Ende von PsdReadOut zusammengefasst) 1821 befehl[ 4 ][ 3 ]= ( BYTE ) 0; 1822 echo[ 4 ][ 4 ]= ( BYTE ) 0; 1823 return result; 1824 }; 1825 1826 UINT TBraunPsd::SetPositionScale(UINT aPositionScale) { 1827 UINT result= TOneDimDetector::SetPositionScale(aPositionScale); 1828 1829 // Werte immer für Scale= 0 auslesen (Werte werden am Ende von PsdReadOut zusammengefasst) 1830 befehl[ 5 ][ 3 ]= ( BYTE ) 0; 1831 echo[ 5 ][ 4 ]= ( BYTE ) 0; 1832 return result; 1833 }; 1834 1835 1836 void TBraunPsd::GetEnergyRange( UINT& ler, UINT& her ) const 1837 { 1838 // auf Scale umrechnen 1839 ler= uEnergyLow >> uEnergyScale; 1840 her= uEnergyHigh >> uEnergyScale; 1841 } 1842 1843 BOOL TBraunPsd::SetEnergyRange( UINT uLowerRange, UINT uHigherRange ) 1844 { 1845 char HeadLine[ ]= "Braun-Psd: SetEnergieRange"; 1846 int nDelay= nDelayFast; 1847 long_to_bytes transform; 1848 const int CntLst= 2; 1849 int CmdList[ CntLst ]= {6, 7}; 1850 1851 // nochrechnen auf <MaxChannels>-Kanäle - siehe PsdReadOut 1852 TRange<int> limit(0, nMaxChannels-1); 1853 uLowerRange= limit.ForceIntoRange(uLowerRange << uEnergyScale); 1854 uHigherRange= limit.ForceIntoRange(uHigherRange << uEnergyScale); 1855 1856 uEnergyHigh= max( uLowerRange, uHigherRange ); 1857 transform.IWert[ 0 ]= ( WORD ) uEnergyHigh; 1858 befehl[ 6 ][ 3 ]= transform.SWert[ 0 ]; 1859 echo[ 6 ][ 4 ]= transform.SWert[ 0 ]; 1860 befehl[ 6 ][ 4 ]= transform.SWert[ 1 ]; 1861 echo[ 6 ][ 6 ]= transform.SWert[ 1 ]; 1862 1863 uEnergyLow= min( uLowerRange, uHigherRange ); 1864 transform.IWert[ 0 ]= ( WORD ) uEnergyLow; 1865 befehl[ 7 ][ 3 ]= transform.SWert[ 0 ]; 1866 echo[ 7 ][ 4 ]= transform.SWert[ 0 ]; 1867 befehl[ 7 ][ 4 ]= transform.SWert[ 1 ]; 1868 echo[ 7 ][ 6 ]= transform.SWert[ 1 ]; 1869 1870 bSetError= FALSE; 1871 1872 for ( int i= 0;i < CntLst;i++ ) 1873 { 1874 if ( 0 != BuildOperation( &( befehl ) [ CmdList[ i ] ][ 0 ], &( echo ) [ CmdList[ i ] ][ 0 ], nDelay ) ) 1875 { 1876 nErrorCode= CmdList[ i ]; 1877 bSetError= TRUE; 1878 MessageBox( GetFocus( ), TBraunError[ nErrorCode ][ 0 ], HeadLine, MBFAILURE ); 1879 return FALSE; 1880 } 1881 } 1882 1883 return TRUE; 1884 } 1885 1886 int TBraunPsd::GetBufferSize( void ) const { 1887 //return max( ( 4096 >> uPositionScale ) + 18, ( 4096 >> uEnergyScale ) + 18 ) + 1; // unabhängig von uPositionScale und uEnergyScale, weil diese nun veränderlich sind 1888 int result= sizeof(MessDatenHeader) + (nMaxChannels*sizeof(unsigned long)); // GetChannelNumber() nicht verwenden, weil sich dieser Wert vergrößern könnte ... dann ist nicht genügend Speicher reserviert 1889 if ( result%4==1 ) result+= 3; 1890 if ( result%4==2 ) result+= 2; 1891 if ( result%4==3 ) result+= 1; 1892 return result; // nur in 4er Schritten (ggf. aufrunden) - Grund siehe PsdReadOut 1893 } 1894 1895 /////////////////////////////////////////////////////////////////////////////// 1896 // Detektorsteuerung 1897 /////////////////////////////////////////////////////////////////////////////// 1898 1899 int TBraunPsd::BuildOperation( BYTE* zgrbefehl, BYTE* zgrecho, int delay ) 1900 { 1901 if ( bDebug ) 1902 { 1903 SetInfo( "Debug BPsd" ); 1904 return 0; 1905 } 1906 delay= max(0, delay); // keine negativen Wartezeiten 1907 1908 int j= ( int ) zgrbefehl[ 0 ]; 1909 1910 int i; 1911 for ( i= 1;i < j + 1;i++ ) 1912 { 1913 Hardware->Write(0,zgrbefehl[i]); 1914 Sleep(2); 1915 } 1916 1917 j= ( int ) zgrecho[ 0 ]; 1918 BYTE EchoRead[ 18 ]; 1919 1920 for ( i= 0;i < j;i++ ) 1921 { 1922 if ( Look_till_BaseAddr1( delay ) ) 1923 break; 1924 1925 Hardware->Read(2,&(EchoRead[i+2])); 1926 Hardware->Read(3,&(EchoRead[i+1])); 1927 1928 i++; 1929 1930 if ( ( i == 3 ) && ( j == 7 ) ) 1931 { 1932 EchoRead[ 3 ]= EchoRead[ 4 ]; 1933 i--; 1934 } 1935 } 1936 1937 EchoRead[ 0 ]= ( BYTE ) j; 1938 return strncmp( ( char* ) EchoRead, ( char* ) zgrecho, j + 1 ); 1939 } 1940 1941 void TBraunPsd::ResetDelayTime( void ) 1942 { 1943 if ( bDebug ) 1944 { 1945 SetInfo( "Debug BPsd" ); 1946 return; 1947 } 1948 1949 SYSTEMTIME t1, t2; 1950 GetLocalTime( &t1 ); 1951 1952 do 1953 { 1954 GetLocalTime( &t2 ); 1955 Hardware->Write(1,(BYTE)0x00); 1956 } 1957 while ( ( abs( t2.wSecond - t1.wSecond ) ) < 2 ); 1958 } 1959 1960 int TBraunPsd::Look_till_BaseAddr1( int Delay ) 1961 { 1962 if ( bDebug ) 1963 { 1964 SetInfo( "Debug BPsd" ); 1965 return 0; 1966 } 1967 1968 int k= 0; 1969 1970 BYTE Value= 0; 1971 Hardware->Read(1,&Value); 1972 while(Value > 0x7F) 1973 { 1974 Sleep(1); 1975 if ( k > Delay ) 1976 return 1; 1977 Hardware->Read(1,&Value); 1978 k++; 1979 } 1980 return 0; 1981 } 1982 1983 int TBraunPsd::SynchronHexFile( BYTE& W_String, BYTE& R_String ) 1984 { 1985 if ( bDebug ) 1986 { 1987 SetInfo( "Debug BPsd" ); 1988 return 0; 1989 } 1990 1991 W_String= 0x3A; 1992 1993 int zaehler= 0; 1994 do 1995 { 1996 Hardware->Write(0,(BYTE)0x3A); 1997 Look_till_BaseAddr1( 1 ); 1998 Hardware->Read(3,&R_String); 1999 Hardware->Read(2,&R_String); 2000 2001 if ( zaehler > 99 ) 2002 return 1; 2003 2004 zaehler++; 2005 } 2006 while ( R_String != 0x3A ); 2007 2008 return 0; 2009 } 2010 2011 BYTE TBraunPsd::konvert( char z ) 2012 { 2013 BYTE zb= static_cast<BYTE>(z); 2014 2015 if ( isdigit( zb ) ) 2016 return ( BYTE ) ( zb - 48 ); 2017 2018 if ( z <= 70 ) 2019 return ( BYTE ) ( zb - 55 ); 2020 2021 return ( BYTE ) ( zb - 87 ); 2022 } 2023 2024 int TBraunPsd::LoadHexFile( void ) 2025 { 2026 //! char HeadLine[]= "Braun-Psd: Load Hex-File"; 2027 BYTE zeichen, HighWert, LowWert; 2028 int laenge= 0, i; 2029 //! int k=0; 2030 int anzahl= 0; 2031 //! int l=0; 2032 BOOL ReadError= FALSE; 2033 BYTE Buffer[ 80 ]; 2034 BYTE ReadString[ 70 ]; 2035 BYTE WriteString[ 70 ]; 2036 float anzln= 350; 2037 int acln= 0; 2038 char Filename[ ]= "asa23.hex"; 2039 2040 bSetError= FALSE; 2041 2042 ifstream myfile( Filename, ios::in | ios::nocreate ); 2043 2044 if ( !myfile ) 2045 { 2046 bSetError= TRUE; 2047 nErrorCode= 35; 2048 return R_Failure; 2049 } 2050 2051 char buf[ MaxString ]; 2052 2053 do 2054 { 2055 if ( ReadError ) 2056 myfile.seekg( ( myfile.tellg( ) ) - ( laenge + 2 ) ); 2057 2058 myfile.getline ( Buffer, 80, '\n' ); 2059 2060 if ( !( ++acln % 40 ) ) 2061 { 2062 sprintf( buf, "HEX-File laden: %.1f %% sind geladen.", (float)(acln / anzln)*100); 2063 SetInfo( buf ); 2064 } 2065 2066 if ( myfile.eof( ) ) 2067 break; 2068 2069 laenge= strlen( ( char* ) Buffer ); 2070 istrstream mystream((char*)Buffer, laenge ); 2071 2072 if ( ( mystream.get( ) ) == 0x3A ) 2073 { 2074 if ( SynchronHexFile( WriteString[ 0 ], ReadString[ 0 ] ) ) 2075 { 2076 bSetError= TRUE; 2077 nErrorCode= 33; 2078 return R_Failure; 2079 }; 2080 2081 for ( i= 0;i < ( laenge - 1 ) / 2;i++ ) 2082 { 2083 mystream.get( HighWert ); 2084 2085 if ( !isxdigit( HighWert ) ) 2086 { 2087 bSetError= TRUE; 2088 nErrorCode= 34; 2089 return R_Failure; 2090 }; 2091 2092 mystream.get( LowWert ); 2093 2094 if ( !isxdigit( LowWert ) ) 2095 { 2096 bSetError= TRUE; 2097 nErrorCode= 34; 2098 return R_Failure; 2099 } 2100 2101 zeichen= ( BYTE ) ( ( konvert( HighWert ) << 4 ) + konvert( LowWert ) ); 2102 WriteString[ i + 1 ]= zeichen; 2103 2104 Hardware->Write(0,zeichen); 2105 2106 if ( Look_till_BaseAddr1( 1 ) ) 2107 { 2108 bSetError= TRUE; 2109 nErrorCode= 37; 2110 return R_Failure; 2111 } 2112 2113 BYTE Value= 0; 2114 Hardware->Read(3,&Value); //Einlesen, um Blockade zu verhindern, vermutlich 2115 Hardware->Read(2,&(ReadString[i+1])); 2116 } 2117 2118 if ( strncmp( ( char* ) WriteString, ( char* ) ReadString, i + 1 ) ) 2119 { 2120 ReadError= TRUE; 2121 anzahl++; 2122 2123 if ( anzahl >= 3 ) 2124 { 2125 bSetError= TRUE; 2126 nErrorCode= 36; 2127 return R_Failure; 2128 } 2129 } 2130 2131 else 2132 { 2133 ReadError= FALSE; 2134 anzahl= 0; 2135 } 2136 } 2137 2138 else 2139 { 2140 ReadError= TRUE; 2141 2142 if ( anzahl >= 3 ) 2143 { 2144 bSetError= TRUE; 2145 nErrorCode= 36; 2146 return R_Failure; 2147 } 2148 2149 anzahl++; 2150 } 2151 } 2152 while ( !myfile.eof( ) || ReadError ); 2153 2154 SetInfo( "HEX-File erfolgreich geladen." ); 2155 2156 return R_OK; 2157 } 2158 2159