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