- Main Page
- Classes
- Files

- File List

# C:/Users/Andreas Schiffler/Desktop/SVN/NewGamePhysics/NewGamePhysics/Devices/AwareGeigerCounter.cs

    00001 ﻿
    00002 using System;
    00003 using System.IO;
    00004 using System.IO.Ports;
    00005 using System.Diagnostics;
    00006 using System.Reflection;
    00007 using System.Runtime.InteropServices;
    00008 using Microsoft.Win32.SafeHandles;
    00009
    00010 using NewGamePhysics.Utilities;
    00011
    00012 namespace NewGamePhysics.Devices
    00013 {
    00018     public delegate void GeigerCounterEvent(double relativeTime);
    00019
    00024     public class AwareGeigerCounter : IDisposable
    00025     {
    00029         private const UInt32 MS_RING_ON = 0x0040;
    00030
    00034         private GeigerCounterEvent eventHandler;
    00035
    00039         private SerialPort serialPort;
    00040
    00044         private IntPtr serialPortHandle;
    00045
    00050         private bool lastRingOn = false;
    00051
    00057         public AwareGeigerCounter(string portReference)
    00058         {
    00059             if (string.IsNullOrEmpty(portReference))
    00060             {
    00061                 throw new ArgumentNullException(
    00062                     "portReference",
    00063                     "The port reference cannot be null or empty");
    00064             }
    00065
    00066             string[] portNames = System.IO.Ports.SerialPort.GetPortNames();
    00067             string portName;
    00068
    00069             if ((portNames == null) || (portNames.Length == 0))
    00070             {
    00071                 throw new ApplicationException(
    00072                     "No serial ports are available on this system");
    00073             }
    00074
    00075             if (!Array.Exists(portNames, s => s.ToUpper().Contains(portReference.ToUpper())))
    00076             {
    00077                 try
    00078                 {
    00079                     int portIndex = Convert.ToInt32(portReference);
    00080
    00081                     if ((portIndex < 1) || (portIndex > portNames.Length))
    00082                     {
    00083                         SerialPortInfo(portNames);
    00084                         throw new ArgumentOutOfRangeException(
    00085                             "portIndex",
    00086                             "The port index must be in the range 1 to " + portNames.Length);
    00087                     }
    00088
    00089                     portName = portNames[portIndex - 1];
    00090                 }
    00091                 catch (Exception)
    00092                 {
    00093                     SerialPortInfo(portNames);
    00094                     throw;
    00095                 }
    00096             }
    00097             else
    00098             {
    00099                 portName = portReference;
    00100             }
    00101
    00102             this.InitializePort(portName);
    00103         }
    00104
    00109         public void Dispose()
    00110         {
    00111             if (this.serialPort != null)
    00112             {
    00113                 this.serialPortHandle = (IntPtr)0;
    00114                 this.serialPort.PinChanged -= new SerialPinChangedEventHandler(PinChanged);
    00115                 this.serialPort.Close();
    00116                 this.serialPort.Dispose();
    00117                 this.serialPort = null;
    00118             }
    00119         }
    00120
    00124         ~AwareGeigerCounter()
    00125         {
    00126             this.Dispose();
    00127         }
    00128
    00133         public GeigerCounterEvent EventHandler
    00134         {
    00135             set { eventHandler = value; }
    00136         }
    00140         private void SerialPortInfo(string[] portNames)
    00141         {
    00142             System.Console.WriteLine();
    00143             System.Console.WriteLine("Available Serial Ports:");
    00144             for (int i = 0; i < portNames.Length; i++)
    00145             {
    00146                 System.Console.WriteLine(" port #" + (i + 1) + " on: " + portNames[i]);
    00147             }
    00148             System.Console.WriteLine();
    00149         }
    00150
    00155         private void InitializePort(string portName)
    00156         {
    00157             // New serial port
    00158             this.serialPort = new SerialPort(portName, 2400);
    00159
    00160             // Power the device
    00161             this.serialPort.Open();
    00162             this.serialPort.DtrEnable = true;
    00163             this.serialPort.RtsEnable = false;
    00164
    00165             // Get a Win32 handle to serial port
    00166             FieldInfo internalStreamFieldInfo = typeof(SerialPort).GetField(
    00167                 "internalSerialStream",
    00168                 BindingFlags.NonPublic | BindingFlags.Instance);
    00169             object internalStream = internalStreamFieldInfo.GetValue(this.serialPort);
    00170             Type internalStreamType = internalStream.GetType();
    00171             FieldInfo handleFieldInfo = internalStreamType.GetField(
    00172                 "_handle",
    00173                 BindingFlags.NonPublic | BindingFlags.Instance);
    00174             object safeFileHandle = handleFieldInfo.GetValue(internalStream);
    00175             this.serialPortHandle = ((SafeFileHandle)safeFileHandle).DangerousGetHandle();
    00176
    00177             // Connect event to detect counts on RI pin
    00178             this.serialPort.PinChanged += new SerialPinChangedEventHandler(PinChanged);
    00179         }
    00180
    00187         [DllImport("kernel32.dll")]
    00188         private static extern Boolean GetCommModemStatus(IntPtr hFile, out UInt32 lpModemStat);
    00189
    00196         private void PinChanged(object sender, SerialPinChangedEventArgs e)
    00197         {
    00198             if (e.EventType == SerialPinChange.Ring)
    00199             {
    00200                 // Gate event by checking for down edge of ring bit change
    00201                 uint status;
    00202                 if (GetCommModemStatus(this.serialPortHandle, out status))
    00203                 {
    00204                     bool ringOn = (status & MS_RING_ON) != 0;
    00205                     if ((this.lastRingOn) && (!ringOn))
    00206                     {
    00207                         if (null != this.eventHandler)
    00208                         {
    00209                             this.eventHandler(HighResolutionTimer.Seconds());
    00210                         }
    00211                     }
    00212
    00213                     this.lastRingOn = ringOn;
    00214                 }
    00215                 else
    00216                 {
    00217                     string message = "GetCommModemStatus() error: " +
    00218                         Marshal.GetLastWin32Error().ToString();
    00219                     throw new ApplicationException(message);
    00220                 }
    00221             }
    00222         }
    00223     }
    00224 }