File: DETECUSE\Detec_hw.cpp
1 /*
2 $Header: /vol/baal-vol3/projekt98/quellen/XCTL_32/DETECUSE/Detec_hw.cpp,v 1.17 2004/06/17 19:33:03 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 Hardwareklassen, die fuer die Messadapter
10 die Kommunikation mit der Detektoren-Hardware erledigen
11 */
12 #include "internls\evrythng.h"
13 #include "detecuse\detectorcontroller.h"
14
15 #include "utils\u_utils.h"
16 #include <fstream.h>
17 //ap #define STRICT
18
19
20 //--||--\\--||--//--||--\\--||--//--||--\\--||--//--||--\\--||--//--||--\\--||--
21
22 //Verwaltungsstrukturen (Treiber)
23 extern DeviceList DetectorDrivers;
24 extern ControllerList DetectorControllers;
25
26 //###########################################################################
27 // TRadiconController
28 //###########################################################################
29
30 // storage specifiations
31 const int LNGMSG= 25; // length of buffer receive/transmit message
32 const int LNGPRG= 0x7f0; // length of buffer program
33
34 // detector internals
35 // Timeout: Der urspruenglich verwendete Timeout-Wert war 3 'ticks',
36 // 1 tick= 1/18.2 sec= ca. 55 ms
37 const int TMOUT= 3*55;
38
39 const long KMGHZ= 500000L; // frequency base (affects exposure time)
40 const int NCYCL= 8; // number of retries for messaging
41
42 // unknown codes
43 const unsigned char MONIT= 0x93; // monitor controller???
44 const unsigned char PROGR= 0x6c; // program ready???
45
46 enum responseCode
47 {
48 ACK= 0x06, // acknowledged
49 NAK= 0x15, // not acknowledged
50 CAN= 0x18, // canceled (not acknowledged)
51 DLE= 0x10, // data link escape
52 EOT= 0x04, // end of transmission
53 };
54
55 //! controller function codes
56 enum EFunctionCode {
57 CF0= 0x00, // set parameters
58 CF1= 0x01, // count pulses during exposure time
59 CF2= 0x02, // count time when number of pulses is set
60 CF3= 0x03, // intensimeter
61 CF5= 0x05, // stop controller
62 CF9= 0x09, // receive result time and pulses
63 CFB= 0x0b, // receive current time and pulses
64 CFF= 0x0f // load program to card ???
65 };
66
67 /////////////////////////////////////////////////////////////////
68 TRadiconController::TRadiconController(EDeviceType _DeviceID, LPTSTR _HardwareID, DeviceList* Devices)
69 : Controller(_DeviceID,_HardwareID,1), dataPort(0), controlPort(1)
70 {
71 char* szDeviceName= Devices->GetFileName(DeviceID, HardwareID);
72 if(!szDeviceName)
73 {
74 Hardware= new DummyIo(DeviceID,HardwareID);
75 }
76 else
77 {
78 Hardware= new HardwareIo(szDeviceName);
79 }
80 }
81
82 TRadiconController::~TRadiconController()
83 {
84 _FREEOBJ(Hardware);
85 }
86
87 BOOL TRadiconController::Check()
88 {
89 //ap - noch zu implementieren!!!
90 return(TRUE);
91 }
92
93 /*******************************************************************************
94 procedure: SetParameters
95 purpose: upload parameters to controller
96 result: 0= operation successful
97 -1= communication error
98 -2= controller can't make this function to present time or error
99 code function
100 -3= parameter error
101 ******************************************************************************/
102 int TRadiconController::SetParameters( unsigned short upperThreshold,
103 unsigned short lowerThreshold,
104 int highvoltage, double exposureTime,
105 unsigned long impulseCount, BOOL bSound )
106 {
107 unsigned char bufmsg[LNGMSG]; // buffer receive/transmit message
108 memset(bufmsg, 0x0, LNGMSG);
109
110 // format energy integral
111 bufmsg[0]= 0x1;
112
113 // format sound
114 bufmsg[1]= (unsigned char) (bSound ? 7 : 8);
115
116 // format high voltage do bitshift to get next Byte
117 bufmsg[7]= (unsigned char) highvoltage;
118 highvoltage= (highvoltage >> 8) & 0xff;
119 bufmsg[8]= (unsigned char) highvoltage;
120
121 // format lower threshold do bitshift to get next Byte
122 bufmsg[9]= (unsigned char) lowerThreshold;
123 lowerThreshold= (lowerThreshold >> 8) & 0xff;
124 bufmsg[10]= (unsigned char) lowerThreshold;
125
126 // format upper threshold do bitshift to get next Byte
127 bufmsg[11]= (unsigned char) upperThreshold;
128 upperThreshold= (upperThreshold >> 8) & 0xff;
129 bufmsg[12]= (unsigned char) upperThreshold;
130
131 // determine and format total counts
132 // do bitshifts to get next bytes
133 unsigned long wtmr= (unsigned long)(exposureTime * KMGHZ); // !! Typkonvertierung !!
134 bufmsg[13]= (unsigned char)(wtmr & 0xff);
135 bufmsg[14]= (unsigned char)((wtmr >> 8) & 0xff);
136 bufmsg[15]= (unsigned char)(wtmr >> 16) & 0xff;
137 bufmsg[16]= (unsigned char)(wtmr >> 24) & 0xff;
138
139 // format impulse count
140 // do bitshifts to get next bytes
141 bufmsg[17]= (unsigned char)(impulseCount & 0xff);
142 bufmsg[18]= (unsigned char)((impulseCount >> 8) & 0xff);
143 bufmsg[19]= (unsigned char)(impulseCount >> 16) & 0xff;
144 bufmsg[20]= (unsigned char)(impulseCount >> 24) & 0xff;
145
146 // format interrupt
147 bufmsg[21]= 0;
148
149 // transmit message for NCYCL cycles or until return value is 0
150 int j;
151
152 for (int i= 0; i < NCYCL; i++ )
153 {
154 j= TransmitMessage( CF0, bufmsg, LNGMSG );
155
156 if (j == 0)
157 break;
158
159 if (j == -2)
160 return -2;
161 }
162
163 // if max number of cycles reached and return value is not 0
164 if (j != 0)
165 return -1;
166
167 return 0;
168 }
169
170 /*******************************************************************************
171 procedure: Execute
172 purpose: issue command to controller
173 result: 0= operation successful
174 -1= communication error
175 -2= controller can't make this function to present time or error
176 code function
177 -3= parameter error (unknown command)
178 *******************************************************************************/
179 int TRadiconController::Execute( EOperationMode fun )
180 {
181 register int i, j;
182 EFunctionCode eFunctionCode;
183
184 switch (fun)
185 { // depending on the command to issue... (function code filter)
186 case fixedExposureCounts: // count impulses during exposure time
187 eFunctionCode= CF1;
188 break;
189
190 case fixedImpulseCounts: // count time when number of impulses is set
191 eFunctionCode= CF2;
192 break;
193
194 case intensimeter: // intensimeter
195 eFunctionCode= CF3;
196 break;
197
198 case stop: // stop controller
199 eFunctionCode= CF5;
200 break;
201
202 default: // unknown command
203 return -3;
204 }
205
206 // transmit message NCYCL cycles or until return value is 0
207 for ( i= 0; i < NCYCL; i++ )
208 {
209 j= TransmitMessage( eFunctionCode);
210
211 if (j == 0)
212 break;
213
214 if (j == -2)
215 return -2;
216 }
217
218 if (j != 0)
219 return -1; // unknown return code
220
221 return 0;
222 }
223
224 /*******************************************************************************
225 procedure: GetValues
226 purpose: get information from controller
227 result: 0= operation successful
228 -1= communication error
229 -2= controller can't make this function to present time or error
230 code function
231 -3= parameter error
232 -4= data isn't ready
233 ******************************************************************************/
234 int TRadiconController::GetValues( EReadoutMode fun, double *ftmr, unsigned long *imp )
235 {
236 register int i, j;
237 double wftmr;
238 unsigned long wimp, wtmr, ww;
239 unsigned char * p;
240 int l;
241 /* buffer receive message */
242 unsigned char bufmsg[LNGMSG];
243
244 EFunctionCode eFunctionCode;
245
246 switch (fun)
247 {
248 case final: // receive result time and impulses
249 eFunctionCode= CF9;
250 break;
251
252 case intermediate: // receive current time and impulses
253 eFunctionCode= CFB;
254 break;
255
256 default: // parameter error
257 return -3;
258 }
259
260 for ( i= 0; i < NCYCL; i++ )
261 {
262 j= ReceiveMessage( eFunctionCode, bufmsg, LNGMSG, l );
263
264 if ( j == 0 )
265 break;
266
267 if ( (j == -2) || (j == -4) )
268 return j;
269 }
270
271 if ( j != 0 )
272 return -1;
273
274 // read number of counts do Bitshifts to cycle through
275 // the four Bytes of the bufmsg that represent the longint
276 p= bufmsg;
277
278 wtmr= 0;
279 ww= 0;
280 ww= *p;
281 wtmr= wtmr + ww;
282 p++;
283
284 ww= 0;
285 ww= *p;
286 ww= ww << 8;
287 wtmr= wtmr + ww;
288 p++;
289
290 ww= 0;
291 ww= *p;
292 ww= ww << 16;
293 wtmr= wtmr + ww;
294 p++;
295
296 ww= 0;
297 ww= *p;
298 ww= ww << 24;
299 wtmr= wtmr + ww;
300 p++;
301
302 // turn number of counts into exposure time do Bitshifts to cycle
303 // through the four Bytes of the bufmsg that represent the longint
304 wftmr= wtmr;
305 *ftmr= wftmr / (KMGHZ);
306
307 // read impulse count
308 wimp= 0;
309
310 ww= 0;
311 ww= *p;
312 wimp= wimp + ww;
313 p++;
314
315 ww= 0;
316 ww= *p;
317 ww= ww << 8;
318 wimp= wimp + ww;
319 p++;
320
321 ww= 0;
322 ww= *p;
323 ww= ww << 16;
324 wimp= wimp + ww;
325 p++;
326
327 ww= 0;
328 ww= *p;
329 ww= ww << 24;
330 wimp= wimp + ww;
331 *imp= wimp;
332
333 return 0;
334 }
335
336 /*******************************************************************************
337 procedure: reset
338 purpose: reset controller
339 synopsis: void CALLTYPE reset( )
340 result: nothing
341 *******************************************************************************/
342 void TRadiconController::reset()
343 {
344 /* first write state register (port address, that identifies controller) into
345 data register. then write lower byte of accumulator register to the data
346 register
347 _asm {
348 mov dx, rs;
349 out dx, al;
350 }
351 */
352
353 // JP!! Achtung, es ist voellig unklar, welcher Wert geschrieben werden soll,
354 // da AL nicht initialisiert wurde, schreibe ich hier (willkuerlich) eine 0
355 Write(controlPort,BYTE(0));
356 }
357
358 /******************************************************************************
359 * Funktionscode zum Controller uebertragen *
360 * *
361 * Rueckgabewert: 0 - OK *
362 * -1 - FEHLER *
363 * -2 - Controller kann die angeforderte Funktion zu diesem *
364 * Zeitpunkt nicht ausfuehren *
365 * oder unbekannter Funktionscode *
366 * -3 - Controller zum FirmwareUpload bereit *
367 * -4 - Controller hat Kommunikation abgebrochen *
368 ******************************************************************************/
369 int TRadiconController::TransmitFunctionCode(int nFunctionCode)
370 {
371 //Datenregister einlesen...zu welchem Zweck ???
372 //eingelesener Wert wird nicht weiter verwendet...
373 //dataPort.In8Bit(); ap
374 BYTE data;
375 Read(dataPort,&data);
376
377 //Funktionscode zum Controller uebertragen
378
379 if (out_byte(nFunctionCode) != TRUE)
380 return -1;
381
382 //Antwort des Controllers empfangen
383 unsigned char chControllerAnswer;
384
385 if (in_byte(chControllerAnswer) != TRUE)
386 return -1;
387
388 //Controllerantwort != ACK => Fehler spezifizieren...
389 if (chControllerAnswer != ACK)
390 {
391 //???
392 if (nFunctionCode == CFF && chControllerAnswer == PROGR)
393 return -3;
394
395 //Controllerantwort= CAN (Kommunikation abbrechen)
396 if (chControllerAnswer == CAN)
397 return -4;
398
399 //Controllerantwort= NAK (unbekannter Funktionscode)
400 if (chControllerAnswer == NAK)
401 return -2;
402
403 //unspezifische Controllerantwort
404 return -1;
405 }
406
407 return 0;
408 }
409
410 /******************************************************************************
411 * Nachricht (Funktionscode und Daten) zum Controller uebertragen *
412 * *
413 * Parameter: *
414 * int nFunctionCode - Funktionscode (Nachricht) *
415 * unsigned char* lpszMessage - Zeiger auf Datenpuffer *
416 * int nMessageLength - Anzahl der zu uebertragenden Bytes *
417 * *
418 * Rueckgabewert: 0 - OK *
419 * -1 - FEHLER *
420 * -2 - Controller kann die angeforderte Funktion zu diesem *
421 * Zeitpunkt nicht ausfuehren *
422 * oder unbekannter Funktionscode *
423 * -3 - Checksummenfehler *
424 ******************************************************************************/
425 int TRadiconController::TransmitMessage(int nFunctionCode, unsigned char* lpszMessage,
426 int nMessageLength)
427 {
428 int nRetCode= TransmitFunctionCode(nFunctionCode);
429
430 if ( nRetCode != 0)
431 {
432 if ( nRetCode == -3)
433 return 0;
434
435 return nRetCode;
436 }
437
438 int nChecksum= 0; //JP!! Test: Checksumme als UCHAR
439
440 //Datenpuffer byteweise zum Controller uebertragen...
441
442 for (int i= 0; i < nMessageLength; i++)
443 { //Byte aus dem Datenpuffer zum Controller uebertragen
444
445 if (out_byte(*lpszMessage) != TRUE)
446 return -1;
447
448 //gesendete Bytes aufsummieren (fuer Checksumme)
449 nChecksum += *lpszMessage;
450
451 //Wenn ein zu uebertragendes Byte den gleichen Wert wie der Steuercode DLE
452 //besitzt, so muß dieses Byte zweimal hintereinander uebertragen werden,
453 //um die Steuercodebedeutung aufzuheben
454 if (*lpszMessage == 0x10) //*p == DLE
455 { //zweites senden des Bytes
456
457 if (out_byte(*lpszMessage) != TRUE)
458 return -1;
459
460 //gesendete Bytes aufsummieren (fuer Checksumme)
461 nChecksum += *lpszMessage;
462 }
463
464 //Pufferzeiger inkrementieren
465 lpszMessage++;
466 }
467
468 //Nachricht DLE zum Controller uebertragen => Daten vollstaendig uebertragen
469 if (out_byte(DLE) != TRUE)
470 return -1;
471
472 //gesendet Bytes aufsummieren (fuer Checksumme)
473 nChecksum += DLE;
474
475 //Nachricht EOT zum Controller uebertragen
476 //=> Nachrichtenuebertragung abschliessen
477 if (out_byte(EOT) != TRUE)
478 return -1;
479
480 nChecksum += EOT; //gesendete Bytes aufsummieren (fuer Checksumme)
481 nChecksum= ~nChecksum; //bitweise Negation (1er-Komplement)
482 nChecksum++; //=> 2er-Komplement
483
484 //ermittelte Checksumme zum Controller uebertragen
485 if (out_byte(nChecksum) != TRUE)
486 return -1;
487
488 unsigned char chControllerAnswer;
489
490 if (in_byte(chControllerAnswer) != TRUE)
491 return -1;
492
493 if (chControllerAnswer == NAK)
494 return -3; // NAK= Checksummenfehler
495
496 return 0; //Funktion mit OK beenden
497 }
498
499 /******************************************************************************
500 * Nachricht vom Controller empfangen *
501 * (Funktionscode dem Controller uebermitteln und Ergebnisdaten empfangen) *
502 * *
503 * Parameter: *
504 * int nFunctionCode - Funktionscode (Nachricht) *
505 * unsigned char* lpszMessage - Zeiger auf Datenpuffer *
506 * int nMaxMessageLength - max. Laenge der zu empfangenden Daten *
507 * int& nRealMessageLength - Zeiger auf Anzahl der empfangenen Daten *
508 * *
509 * Rueckgabewert: 0 - OK *
510 * -1 - FEHLER *
511 * -2 - Controller kann die angeforderte Funktion zu diesem *
512 * Zeitpunkt nicht ausfuehren *
513 * oder unbekannter Funktionscode *
514 * -3 - Checksummenfehler *
515 * -4 - Daten stehen nicht bereit *
516 ******************************************************************************/
517 int TRadiconController::ReceiveMessage(int nFunctionCode, unsigned char* lpszMessage,
518 int nMaxMessageLength, int& nRealMessageLength)
519 {
520 int nRetCode= TransmitFunctionCode(nFunctionCode);
521
522 if ( nRetCode != 0)
523 {
524 if ( nRetCode == -3)
525 return 0;
526
527 return nRetCode;
528 }
529
530 int nChecksum= 0;
531 nRealMessageLength= 0; //Anzahl der empfangenen Daten mit 0 initialisieren
532
533 //Daten byteweise vom Controller empfangen bis die max. Anzahl erreicht ist
534 //oder die Datenuebertragung durch DLE vom Controller beendet wird
535 unsigned char chControllerAnswer1, chControllerAnswer2;
536
537 while (nRealMessageLength < nMaxMessageLength)
538 { //Byte vom Controller empfangen
539
540 if (in_byte(chControllerAnswer1) != TRUE)
541 return -1;
542
543 //empfangene Bytes aufsummieren (fuer Checksumme)
544 nChecksum += chControllerAnswer1;
545
546 //empfangenes Byte= DLE => testen ob Steuercode(DLE) oder Datenwert(10h)
547 if (chControllerAnswer1 == DLE)
548 { //Folgebyte vom Controller empfangen
549
550 if (in_byte(chControllerAnswer2) != TRUE)
551 return -1;
552
553 nChecksum += chControllerAnswer2;
554
555 //empfangenes Byte= EOT (Ende der Uebertragung) => vorheriges Byte
556 //war Steuercode DLE => Datenempfang vorzeitig abbrechen
557 if (chControllerAnswer2 == EOT)
558 break;
559
560 //empfangenes Byte != DLE => vorheriges Byte war weder Steuercode(DLE)
561 //noch Datenwert(10h) => Funktion mit FEHLER beenden
562 if (chControllerAnswer2 != DLE)
563 return -1;
564 }
565
566 //empfangenes Byte in den Datenpuffer uebernehmen
567 *lpszMessage= chControllerAnswer1;
568
569 //Pufferzeiger inkrementieren
570 lpszMessage++;
571
572 //Anzahl der empfangenen Daten inkrementieren
573 nRealMessageLength++;
574 }
575
576 //letztes Byte vom Controller empfangen (zur Ueberpruefung der Checksumme)
577 if (in_byte(chControllerAnswer1) != TRUE)
578 return -1;
579
580 //Checksumme pruefen
581 nChecksum= (nChecksum + chControllerAnswer1) & 0xff;
582
583 //Checksumme != 0 => NAK (wegen Checksummenfehler) an den Controller senden
584 if (nChecksum != 0)
585 { //Nachricht NAK (Checksummenfehler) an den Controller uebermitteln
586
587 if (out_byte(NAK) != TRUE)
588 return -1;
589
590 //Funktion mit Fehlercode -3 beenden
591 return -3;
592 }
593
594 //Nachricht ACK (Checksumme OK) an Controller uebermitteln
595 if (out_byte(ACK) != TRUE)
596 return -1;
597
598 return 0;
599 }
600
601 /******************************************************************************
602 * Datenbyte zum Controller uebertragen *
603 ******************************************************************************/
604 BOOL TRadiconController::out_byte(unsigned char d)
605 {
606 unsigned long dwStart, dwNow;
607
608 //(1) aktuelle Systemzeit ermitteln
609 dwStart= dwNow= CurrentTime();
610
611 //Warten auf 'Bereit-Zustand' des Controllers innerhalb einer bestimmten Zeit
612 //(TIMEOUT-Schleife)
613
614 while (( dwNow - dwStart ) < TMOUT)
615 {
616 //Controllerstatus ermitteln
617
618 if (IsReadyToWrite() == TRUE)
619 {
620 //Byte vom Controller empfangen (Datenregister lesen)
621 //dataPort.Out8Bit(d); ap
622 Write(dataPort,(BYTE)d);
623 return TRUE;
624 }
625
626 //(2) aktuelle Systemzeit ermitteln
627 dwNow= CurrentTime();
628
629 //Fehler: zuletzt gemessene Systemzeit(2) liegt vor der ersten gemessenen
630 //Systemzeit(1) => Anpassen der ersten Systemzeit(1)
631 //=> bisher verstrichene Zeit wird zurueckgesetzt => TIMEOUT beginnt erneut
632 if (dwNow < dwStart)
633 dwStart= dwNow;
634 }
635
636 //Daten stehen nicht bereit
637 return FALSE;
638 }
639
640 /******************************************************************************
641 * Datenbyte vom Controller empfangen *
642 ******************************************************************************/
643 BOOL TRadiconController::in_byte(unsigned char &d)
644 {
645 unsigned long dwStart, dwNow;
646
647 //(1) aktuelle Systemzeit ermitteln
648 dwStart= dwNow= CurrentTime();
649
650 //Warten auf 'Bereit-Zustand' des Controllers innerhalb einer bestimmten Zeit
651 //(TIMEOUT-Schleife)
652
653 while (( dwNow - dwStart ) < TMOUT)
654 {
655 //Controllerstatus ermitteln
656
657 if (IsReadyToRead() == TRUE)
658 {
659 //Byte vom Controller empfangen (Datenregister lesen)
660 //d= dataPort.In8Bit(); ap
661 Read(dataPort,&d);
662 return TRUE;
663 }
664
665 //(2) aktuelle Systemzeit ermitteln
666 dwNow= CurrentTime();
667
668 //Fehler: zuletzt gemessene Systemzeit(2) liegt vor der ersten gemessenen
669 //Systemzeit(1) => Anpassen der ersten Systemzeit(1)
670 //=> bisher verstrichene Zeit wird zurueckgesetzt => TIMEOUT beginnt erneut
671 if (dwNow < dwStart)
672 dwStart= dwNow;
673 }
674
675 //Daten stehen nicht bereit
676 return FALSE;
677 }
678
679 /******************************************************************************
680 * Testen ob Controller zur Datenuebergabe (senden) bereit *
681 * *
682 * Rueckgabewert: TRUE - Controller bereit (Datenregister nicht leer) *
683 * FALSE - Controller nicht bereit (Datenregister leer) *
684 ******************************************************************************/
685 BOOL TRadiconController::IsReadyToRead()
686 {
687 //Steuerregister lesen und auswerten...
688 //JP Achtung: Der Controller ist zum Auslesen bereit,
689 //JP wenn das Ergebnis != 0 ist. Beim Bereitschaftstest zum Senden ist der
690 //JP Controller bereit, wenn das Ergebnis == 0 ist
691 //return (( controlPort.In8Bit() & 0x02 ) != 0); ap
692 BYTE data;
693 Read(controlPort,&data);
694 return(( data & 0x02 ) != 0);
695 }
696
697 /******************************************************************************
698 * Testen ob Controller zur Datenuebernahme (empfangen) bereit *
699 * *
700 * Rueckgabewert: TRUE - Controller bereit (Datenregister nicht leer) *
701 * FALSE - Controller nicht bereit (Datenregister leer) *
702 ******************************************************************************/
703 BOOL TRadiconController::IsReadyToWrite()
704 {
705 //Steuerregister lesen und Status auswerten...
706 //return (( controlPort.In8Bit() & 0x01 ) == 0); ap
707 BYTE data;
708 Read(controlPort,&data);
709 //rh return(( data & 0x01 ) != 0);
710 return(( data & 0x01 ) == 0);
711
712 }
713
714 /*******************************************************************************
715 --- UploadFirmware ---
716 upload controller firmware
717
718 return values: 0= operation successful
719 -1= communication error
720 -2= controller rejects connect
721 -3= error using firmware file
722 -4= unspecified error
723 *******************************************************************************/
724 int TRadiconController::UploadFirmware(void)
725 {
726 // open firmware file
727 char szFileName[MaxString];
728 sprintf(szFileName, "%sscs.prg", GetDirectory());
729 ifstream ifile(szFileName, ios::in | ios::binary);
730
731 if ( ifile.fail() )
732 {
733 MessageBox(0, "Kann Radicon-Firmwaredatei scs.prg nicht oeffnen!",
734 "Error", MBINFO );
735 return -3;
736 }
737
738 // check file size
739 ifile.seekg (0, ios::end);
740
741 int nFileSize= ifile.tellg();
742
743 ifile.seekg (0, ios::beg);
744
745 if ( nFileSize != LNGPRG )
746 {
747 MessageBox(0, "Die Radicon-Firmwaredatei scs.prg hat nicht die korrekte Laenge!",
748 "Error", MBINFO );
749 return -3;
750 }
751
752 unsigned char* pBuf= new unsigned char[LNGPRG];
753
754 if ( pBuf == NULL )
755 {
756 MessageBox(0, "Nicht genug Speicher!",
757 "Error", MBINFO );
758 return -4;
759 }
760
761 // read content of file into memory
762 ifile.read(pBuf, LNGPRG);
763
764 ifile.close();
765
766 // This method reads bytes from controller multiple times, but can't
767 // say why. This behavior is preserved from the old C-sources, because
768 // I don't know the Radicon communication protocol.
769
770 unsigned char d;
771
772 in_byte(d); // read a byte from controller - why???
773
774 Execute(stop);
775
776 // send firmware to controller
777 int nRetCode;
778
779 int i;
780
781 for ( i= 0; i < NCYCL; i++ )
782 {
783 nRetCode= TransmitMessage( CFF, pBuf, LNGPRG );
784
785 if (nRetCode == -2)
786 {
787 _FREEOBJ(pBuf);
788 return -2;
789 }
790
791 if (nRetCode == 0)
792 break;
793 }
794
795 _FREEOBJ(pBuf);
796
797 if ( i == NCYCL )
798 return -1; // Timeout erreicht
799
800 if ( d == MONIT )
801 in_byte(d);
802
803 return 0;
804 }
805
806 /******************************************************************************
807 * Zeit seit dem Start des Systems in Millisekunden ermitteln *
808 * *
809 * Rueckgabewert: dword - Systemzeit in Millisekunden *
810 ******************************************************************************/
811 DWORD TRadiconController::CurrentTime()
812 {
813 return GetTickCount();
814 }
815
816
817 //###########################################################################
818 // TAm9513
819 //###########################################################################
820
821 const int IoWaiTAm9513= 43;
822 // Chip
823 const BYTE CHIP1= 0x0;
824 const BYTE CHIP2= 0x1;
825 const BYTE DIGITAL= 0x2;
826
827 const BYTE BIT= 0x4;
828 const BYTE CODE= 0x5;
829
830 // IO-Addressen Offset
831 const int DATA= 0x0;
832 const int CMD= 0x1;
833
834 // Gruppen
835 const BYTE CNT1= 0x01;
836 const BYTE CNT2= 0x02;
837 const BYTE CNT3= 0x03;
838 const BYTE CNT4= 0x04;
839 const BYTE CNT5= 0x05;
840 const BYTE CTRG= 0x07;
841
842 // Zaehler-Id Bit's
843 const BYTE CTB1= 0x01;
844 const BYTE CTB2= 0x02;
845 const BYTE CTB3= 0x04;
846 const BYTE CTB4= 0x08;
847 const BYTE CTB5= 0x10;
848
849 // Register der Gruppen
850 const BYTE CMR= 0x00; // Mode-Register
851 const BYTE CLR= 0x08; // Load-Register
852 const BYTE CHR= 0x10; // Hold-Register
853 const BYTE CHIR= 0x18; // Hold+Inc-Register
854 const BYTE ALM1= 0x00; // Alarm-Register 1
855 const BYTE ALM2= 0x08; // Alarm-Register 2
856 const BYTE MMR= 0x10; // Master-Mode-Register
857 const BYTE STS= 0x18; // Status-Register (8 Bit)
858 // Funktions-Bit fuer CMR
859 const WORD CB_UP= 3; // aufwaerts zaehlen
860 const WORD CB_BCD= 4; // BCD zaehlen
861 const WORD CB_REPEAT= 5; // automatisch neu starten
862 const WORD CB_RLorH= 6; // laden von L-Reg oder H-Reg
863 const WORD CB_ENGATE= 7; // special gate
864 const WORD CB_FALLEG= 12; // mit steigender Flanke zaehlen
865 // Funktions-Bit fuer MMR
866 const WORD MB_CMP1E= 2;
867 const WORD MB_CMP2E= 3;
868 const WORD MB_NFOUT= 12;
869 const WORD MB_16BIT= 13;
870 const WORD MB_DIS_INC= 14;
871 const WORD MB_BCD_DIV= 15;
872 // Funktions-Code fuer CMR (nur Setzen mit |)
873 const WORD CC_CNTM1= 0x0000;
874 const WORD CC_NOGATE= 0x0000;
875 const WORD CC_AHTCNM1= 0x2000;
876 const WORD CC_AHNP1= 0x4000;
877 const WORD CC_AHNM1= 0x6000;
878 const WORD CC_AHN= 0x8000;
879 const WORD CC_ALN= 0xA000;
880 const WORD CC_AHEGN= 0xC000;
881 const WORD CC_ALEGN= 0xE000;
882 // Output-Control
883 const WORD CC_I_OLow= 0x0000;
884 const WORD CC_A_HTCP= 0x0001;
885 const WORD CC_TCTOG= 0x0002;
886 const WORD CC_I_OTRI= 0x0004;
887 const WORD CC_A_LTCP= 0x0005;
888
889 // Quellen-Bezeichner fuer CMR und MMR
890 const WORD C_CNM1= 0x0; // F1 MMR
891 const WORD C_SRC1= 0x1;
892 const WORD C_SRC2= 0x2;
893 const WORD C_SRC3= 0x3;
894 const WORD C_SRC4= 0x4;
895 const WORD C_SRC5= 0x5;
896 const WORD C_GATE1= 0x6;
897 const WORD C_GATE2= 0x7;
898 const WORD C_GATE3= 0x8;
899 const WORD C_GATE4= 0x9;
900 const WORD C_GATE5= 0xA;
901 const WORD C_F1= 0xB;
902 const WORD C_F2= 0xC;
903 const WORD C_F3= 0xD;
904 const WORD C_F4= 0xE;
905 const WORD C_F5= 0xF;
906
907
908 //******** Methoden für den Zähler-IC Am9513A **********************************
909 //Wieviele Detektoren können an diesen Controller angeschlossen werden???
910 TGenericController::TGenericController(EDeviceType _DeviceID, LPTSTR _HardwareID, DeviceList* Devices)
911 : Controller(_DeviceID,_HardwareID,5),bIsStopped(FALSE),bIsLatched(FALSE),
912 wLowTicks(1000),wHighTicks(100),wLowCounts(1000),wHighCounts(100),
913 nbChipId(0)
914 {
915 char* szDeviceName= Devices->GetFileName(DeviceID, HardwareID);
916 if(!szDeviceName)
917 {
918 Hardware= new DummyIo(DeviceID,HardwareID);
919 }
920 else
921 {
922 Hardware= new HardwareIo(szDeviceName);
923 }
924 }
925
926 TGenericController::~TGenericController()
927 {
928 _FREEOBJ(Hardware)
929 }
930
931 BOOL TGenericController::Check()
932 {
933 //ap - noch zu implementieren!!!
934 return(TRUE);
935 }
936
937 int TGenericController::Init(float _fTimeCorrection)
938 {
939 //ap
940 fTimeCorrection= _fTimeCorrection;
941
942 // Kommunikations-Test
943 ChooseDataPtr( CNT1, CMR );
944 WriteData( 0xA121 );
945 ChooseDataPtr( CNT1, CMR );
946
947 if ( ReadData() != 0xA121 )
948 return FALSE;
949
950 // Zähler zurücksetzen
951 Reset();
952 WriteCmd( 0xF9 );
953
954 // Konfigurieren des Mastermode-Register
955 ChooseDataPtr( CTRG, MMR );
956 WriteData( 0xCA00 ); // F1 --> FOUT
957
958 // Konfigurieren des TimeTick-Zähler
959 ChooseDataPtr( CNT1, CMR );
960 WriteData( 0xA121 );
961
962 ChooseDataPtr( CNT2, CMR );
963 WriteData( 0x0202 );
964
965 // Konfigurieren des Impuls-Zähler
966 ChooseDataPtr( CNT3, CMR );
967 WriteData( 0xA321 );
968
969 ChooseDataPtr( CNT4, CMR );
970 WriteData( 0x0402 );
971
972 // Konfigurieren des Akustik-Zähler
973 ChooseDataPtr( CNT5, CMR );
974 WriteData( 0x0C21 );
975
976 return TRUE;
977 }
978
979 int TGenericController::IOCTL( EIOCCmd cmd )
980 {
981 DWORD dwData= 0;
982 return IOCTL( cmd, dwData );
983 }
984
985 int TGenericController::IOCTL( EIOCCmd cmd, DWORD& param )
986 {
987 WORD regH, regL;
988 WORD wValue;
989
990 switch ( cmd )
991 {
992 case iocSetTimeTicks:
993 // Zerlegung in ein Produkt;
994 param= ( DWORD ) ( ( double ) param * fTimeCorrection );
995 SplitNumber( param, wLowTicks, wHighTicks );
996 ChooseDataPtr( CNT1, CLR );
997 WriteData( wLowTicks );
998 ChooseDataPtr( CNT2, CLR );
999 WriteData( wHighTicks ); // TC Toggle
1000 param= ( DWORD ) wLowTicks * wHighTicks;
1001 param= ( DWORD ) ( ( double ) param / fTimeCorrection );
1002 break;
1003
1004 case iocSetCounts:
1005 SplitNumber( param, wLowCounts, wHighCounts );
1006 param= ( DWORD ) wLowCounts * wHighCounts;
1007 ChooseDataPtr( CNT3, CLR );
1008 WriteData( wLowCounts );
1009 ChooseDataPtr( CNT4, CLR );
1010 WriteData( wHighCounts ); // TC Toggle
1011 break;
1012
1013 case iocStopCCDTiming:
1014 DisarmC( CTB1 | CTB2 );
1015 SetToggleOut( CNT2 );
1016 bIsStopped= TRUE;
1017 break;
1018
1019 case iocStartCCDTiming:
1020 if ( !bIsStopped )
1021 DisarmC( CTB1 | CTB2 );
1022
1023 ChooseDataPtr( CNT1, CMR );
1024 // wValue= 0xA121;
1025 wValue= 0x0121;
1026 WriteData( wValue );
1027
1028 ChooseDataPtr( CNT2, CMR );
1029 // wValue= 0x0202;
1030 wValue= 0x0222;
1031 WriteData( wValue );
1032
1033 bIsStopped= FALSE;
1034 bIsLatched= FALSE;
1035
1036 LoadC( CTB1 | CTB2 );
1037 LoadC( CTB1 | CTB2 );
1038
1039 SetToggleOut( CNT2 );
1040 SetToggleOut( CNT4 );
1041
1042 ClearToggleOut( CNT1 );
1043 ClearToggleOut( CNT3 );
1044
1045 ArmC( CTB1 | CTB2 );
1046 break;
1047
1048 case iocStartCCDShot:
1049 if ( !bIsStopped )
1050 DisarmC( CTB1 | CTB2 );
1051
1052 bIsStopped= FALSE;
1053 bIsLatched= FALSE;
1054
1055 LoadC( CTB1 | CTB2 );
1056 LoadC( CTB1 | CTB2 );
1057
1058 SetToggleOut( CNT2 );
1059 SetToggleOut( CNT4 );
1060
1061 ClearToggleOut( CNT1 );
1062 ClearToggleOut( CNT3 );
1063
1064 ArmC( CTB1 | CTB2 );
1065 break;
1066
1067 case iocReadTicks:
1068 if ( !bIsLatched )
1069 {
1070 DisarmC( CTB1 | CTB2 | CTB3 | CTB4 );
1071 bIsStopped= TRUE;
1072 LatchToHoldC( CTB1 | CTB2 | CTB3 | CTB4 );
1073 bIsLatched= TRUE;
1074 }
1075 ChooseDataPtr( CNT1, CHR );
1076 regL= ReadData( );
1077 ChooseDataPtr( CNT2, CHR );
1078 regH= ReadData( );
1079 param= ( DWORD ) ( wHighTicks - regH ) * ( DWORD ) wLowTicks;
1080 param += ( DWORD ) ( wLowTicks - regL );
1081 param= ( DWORD ) ( ( double ) param / fTimeCorrection );
1082 break;
1083
1084 case iocReadCounts:
1085 if ( !bIsLatched )
1086 {
1087 DisarmC( CTB1 | CTB2 | CTB3 | CTB4 );
1088 bIsStopped= TRUE;
1089 LatchToHoldC( CTB1 | CTB2 | CTB3 | CTB4 );
1090 bIsLatched= TRUE;
1091 }
1092
1093 ChooseDataPtr( CNT3, CHR );
1094 regL= ReadData( );
1095 ChooseDataPtr( CNT4, CHR );
1096 regH= ReadData( );
1097 param= ( DWORD ) ( wHighCounts - regH ) * ( DWORD ) wLowCounts;
1098 param += ( DWORD ) ( wLowCounts - regL );
1099 break;
1100
1101 case iocConfigureAcustic:
1102 ChooseDataPtr( CNT5, CLR );
1103 WriteData( ( WORD ) param );
1104 LoadAndArmC( CTB5 );
1105 break;
1106
1107 case iocStartCounting:
1108 DisarmC( CTB1 | CTB2 | CTB3 | CTB4 );
1109 bIsStopped= FALSE;
1110 bIsLatched= FALSE;
1111 LoadC( CTB1 | CTB2 | CTB3 | CTB4 );
1112 DelayTime( 1 );
1113 LoadC( CTB1 | CTB2 | CTB3 | CTB4 );
1114 ClearToggleOut( CNT1 );
1115 ClearToggleOut( CNT3 );
1116 SetToggleOut( CNT2 );
1117 SetToggleOut( CNT4 );
1118 DelayTime( 1 );
1119 ArmC( CTB1 | CTB2 | CTB3 | CTB4 );
1120 break;
1121
1122 case iocIsCountingReady:
1123 switch ( 0x14 & ReadStatus( ) )
1124 {
1125 case 0x14:
1126 param= 0;
1127 break; // no counter ready
1128
1129 case 0x10:
1130 param= 1;
1131 break; // time counter ready
1132
1133 case 0x04:
1134 param= 2;
1135 break; // impulse counter ready
1136
1137 default:
1138 param= 3;
1139 }
1140 return (int)param;
1141
1142 case iocStopCounting:
1143 DisarmC( CTB1 | CTB2 | CTB3 | CTB4 );
1144 bIsStopped= TRUE;
1145 break;
1146 }
1147
1148 return TRUE;
1149 }
1150
1151 BOOL TGenericController::SplitNumber( DWORD value, WORD& low, WORD& high )
1152 {
1153 // in case of any changes notify the function IOCTL()
1154 if ( value < 0xF000 )
1155 {
1156 high= 1;
1157 low= ( WORD ) value;
1158 return TRUE;
1159 }
1160
1161 long f= value;
1162 long f1= 4;
1163 long f2= value / f1;
1164 int cnt= 1000;
1165 long fail;
1166
1167 while ( cnt-- )
1168 {
1169 fail= f - f1 * f2;
1170
1171 if ( ( f1 > 0xE000 ) || ( f2 > 0xE000 ) )
1172 {
1173 if ( f1 < f2 )
1174 {
1175 f1 *= 2;
1176 f2 /= 2;
1177 }
1178 else
1179 {
1180 f2 *= 2;
1181 f1 /= 2;
1182 }
1183 continue;
1184 }
1185 if ( fail == 0 )
1186 break;
1187
1188 if ( f1 < f2 )
1189 f2 += fail / f1;
1190 else
1191 f1 += fail / f2;
1192
1193 if ( ( f1 > fail ) && ( f2 > fail ) )
1194 break;
1195 } // end-while
1196
1197 if ( f1 < f2 )
1198 {
1199 // f1 und f2 vertauschen
1200 long swap= f1;
1201 f1= f2;
1202 f2= swap;
1203 }
1204
1205 if ( f1 < ( fail * 2 ) )
1206 f2++;
1207
1208 high= ( WORD ) f1;
1209 low= ( WORD ) f2;
1210
1211 if ( cnt == 0 )
1212 MessageBox( GetFocus( ), "Fehler beim Zerlegen !", "Am9513a", MBINFO );
1213
1214 return TRUE;
1215 }
1216
1217 DWORD TGenericController::GetTicksPerSecond(void)
1218 {
1219 return 100000L;
1220 }
1221
1222 void TGenericController::DigitalOut(BYTE data)
1223 {
1224 //Portzugriffe nur über Offsets zum Basisport im Treiber
1225 Hardware->Write(3,data);
1226 }
1227
1228 void TGenericController::DigitalIn( BYTE *data )
1229 {
1230 //Portzugriffe nur über Offsets zum Basisport im Treiber
1231 Hardware->Read(2,data);
1232 }
1233
1234 //ap - neu !!!
1235 void TGenericController::SetSound(BOOL param)
1236 {
1237 Hardware->Write(3, (BYTE)(param?1:0));
1238 }
1239
1240 BOOL TGenericController::SelectChip( /* BYTE */)
1241 {
1242 // Zähler zurücksetzen
1243 Reset();
1244 Delay( 50 );
1245 // Check IO
1246 ChooseDataPtr( CNT1, CLR );
1247 WriteData( 0xDAAB );
1248 ChooseDataPtr( CNT2, CLR );
1249 WriteData( 0x0000 );
1250 ChooseDataPtr( CNT1, CLR );
1251 WORD value= ReadData( );
1252
1253 if ( 0xDAAB != value )
1254 {
1255 char buf[ MaxString ];
1256 sprintf( buf, "SelectChip() gab %X zurueck", value );
1257 MessageBox( GetFocus( ), buf, "Detector-Fehler Am9513a", MBINFO );
1258 return FALSE;
1259 }
1260
1261 return TRUE;
1262 }
1263
1264 void TGenericController::ArmC( BYTE counter )
1265 {
1266 WriteCmd( counter | 0x20 );
1267 }
1268
1269 void TGenericController::LoadC( BYTE counter )
1270 {
1271 WriteCmd( counter | 0x40 );
1272 }
1273
1274 void TGenericController::LoadAndArmC( BYTE counter )
1275 {
1276 WriteCmd( counter | 0x60 );
1277 }
1278
1279 void TGenericController::DisarmAndSaveC( BYTE counter )
1280 {
1281 WriteCmd( counter | 0x80 );
1282 }
1283
1284 void TGenericController::LatchToHoldC( BYTE counter )
1285 {
1286 WriteCmd( counter | 0xA0 );
1287 }
1288
1289 void TGenericController::DisarmC( BYTE counter )
1290 {
1291 WriteCmd( counter | 0xC0 );
1292 }
1293
1294 void TGenericController::ClearToggleOut( BYTE counter )
1295 {
1296 WriteCmd( counter | 0xE0 );
1297 }
1298
1299 void TGenericController::SetToggleOut( BYTE counter )
1300 {
1301 WriteCmd( counter | 0xE8 );
1302 }
1303
1304 void TGenericController::Reset( void )
1305 {
1306 WriteCmd( 0xFF );
1307 }
1308
1309 void TGenericController::ChooseDataPtr( BYTE group, BYTE reg )
1310 {
1311 // Register adressieren
1312 WriteCmd( group | reg );
1313 }
1314
1315 WORD TGenericController::ReadStatus( void )
1316 {
1317 Delay( IoWaiTAm9513 );
1318
1319 //Portzugriffe nur über Offsets zum Basisport im Treiber
1320 BYTE data= 0;
1321 Hardware->Read(CMD,&data);
1322 return(data);
1323 }
1324
1325 void TGenericController::WriteCmd( BYTE cmd )
1326 {
1327 if ( nbChipId == DIGITAL )
1328 return;
1329
1330 Delay( IoWaiTAm9513 );
1331
1332 //Portzugriffe nur über Offsets zum Basisport im Treiber
1333 Hardware->Write(CMD,cmd);
1334 }
1335
1336 void TGenericController::WriteData( WORD daten )
1337 {
1338 // Erst niederwertiges, dann hoeherwertiges Byte auf Port addr ausgeben
1339
1340 //Portzugriffe nur über Offsets zum Basisport im Treiber
1341 Delay(IoWaiTAm9513);
1342 Hardware->Write(DATA,(BYTE)(daten & 0x00FF));
1343 Delay(IoWaiTAm9513);
1344 Hardware->Write(DATA,(BYTE)(((WORD)daten >> 8) & 0x00FF));
1345 Delay(IoWaiTAm9513);
1346 }
1347
1348 WORD TGenericController::ReadData( void )
1349 {
1350 // Erst niederwertiges, dann hoeherwertiges Byte von Port addr lesen
1351
1352 //Portzugriffe nur über Offsets zum Basisport im Treiber
1353 BYTE tmpL=0,tmpH=0;
1354 WORD value= 0;
1355
1356 Delay(IoWaiTAm9513);
1357 Hardware->Read(DATA,&tmpL);
1358 Delay(IoWaiTAm9513);
1359 Hardware->Read(DATA,&tmpH);
1360 value= tmpH;
1361 value= value << 8;
1362 value += tmpL;
1363 Delay( IoWaiTAm9513 );
1364 return value;
1365 }
1366
1367 //##############################################################################
1368 //******************* Methoden fuer den BraunPSD ******************************
1369 //##############################################################################
1370
1371 TBraunPsdController::TBraunPsdController(EDeviceType _DeviceID, LPTSTR _HardwareID, DeviceList* Devices)
1372 : Controller(_DeviceID,_HardwareID,1), SpecialHardware(0)
1373 {
1374 char* szDeviceName= Devices->GetFileName(DeviceID, HardwareID);
1375 if (!szDeviceName)
1376 {
1377 SpecialHardware= new BraunPsdDummyIo();
1378 Hardware= SpecialHardware;
1379 }
1380 else
1381 {
1382 SpecialHardware= new BraunPsdIo(szDeviceName);
1383 Hardware= SpecialHardware;
1384 }
1385 }
1386
1387 TBraunPsdController::~TBraunPsdController()
1388 {
1389 _FREEOBJ(Hardware);
1390 }
1391
1392 BOOL TBraunPsdController::Check()
1393 {
1394 //ap - noch zu implementieren!!!
1395 return TRUE;
1396 }
1397
1398 BOOL TBraunPsdController::SetTimeout(unsigned long Cycles)
1399 {
1400 if (!SpecialHardware)
1401 return FALSE;
1402
1403 return (SpecialHardware->SetTimeout(Cycles));
1404 }
1405
1406 BOOL TBraunPsdController::GetData(IrpParamsGetData *Params) // 31.06.2004 MEMCORRECT (IrpParamsGetData *Params)
1407 {
1408 if (!SpecialHardware)
1409 return FALSE;
1410
1411 return (SpecialHardware->GetData(Params));
1412 }
1413