Adlink PCI-7250 eventcallback

1k views Asked by At

I just wrote a simple C# to get an eventcallback from PCI-7250 (Data Acquisition Card) when any of the digital inputs go high. Here is my code:

public delegate void ReadDelegate(uint value)
public void Form1_Load(object sender, EventArgs e)
 { 
    m_dev = DASK.Register_Card(DASK.PCI_7250,0);

    ReadDelegate ReadNow = new ReadDelegate(FunctionToCall) 
    DASK.DI_EventCallBack((ushort)m_dev,1,(short)DASK.DBEvent,ReadNow) 
} 
private void FunctionToCall(uint int_value) 
{
 MessageBox.Show(int_value) 
}

When run it just keep"s up throwing some random numbers during runtime and then finally crashes. I believe it has something to do with the EventType (DASK.DBEvent). I went through the manual but nothing more is mentioned about the DASK.DBEvent.

Kindly please advise.

1

There are 1 answers

1
Joe Friedrichsen On

Since the device doesn't have support for callbacks in its driver, you could adapt the driver's API from synchronous calls to callbacks by polling the device in a background thread.

First, create a class that polls the device for the physical event you're interested in responding to. Then, in your GUI code, put the polling work in the background and respond to the callback in the main thread.

I'm not familiar with the ADLink driver, so I'll just summarize a design approach and sketch some pseudocode that isn't threadsafe. This is a naive approach to using Tasks, but you could also update it to use continuations or async/await. Or, if you need more than one responder, make the callback raise an event that your other classes can subscribe to.

Polling class

public class EdgeDetector
{
  public delegate void OnRisingEdgeDetected(uint currentValue, uint linesThatAsserted);
  private bool m_shouldPoll;

  private void PollForRisingEdge(PCI_7250 device, OnRisingEdgeDetected onRisingEdgeDetected)
  {
    while (m_shouldPoll)
    {
      // Optional: sleep to avoid consuming CPU

      uint newPortValue = device.ReadAllDigitalLines();
      uint changedLines = m_currentPortValue ^ newPortValue;
      uint risingEdges = newPortValue & changedLines;
      m_currentPortValue = newPortValue;

      if (risingEdges != 0)
      {
        onRisingEdgeDetected(currentValue: newPortValue,
                             linesThatAsserted: risingEdges);
      }
  }

  public void Start(PCI_7250 device, OnRisingEdgeDetected onRisingEdgeDetected)
  {
      m_shouldPoll = true;
      PollForRisingEdge(device, onRisingEdgeDetected);
  }

  public void Stop()
  {
      m_shouldPoll = false;
  }
}

WinForm class

private void Initialize()
{
  m_dev = DASK.Register_Card(DASK.PCI_7250, 0);
  m_mainThreadScheduler = TaskScheduler.FromCurrentSynchronizationContext();
}

private void StartEdgeDetection()
{
  m_edgeDetectionTask = Task.Factory.StartNew( () =>
    {
      m_edgeDetector.Start(device: m_dev, onRisingEdgeDetected: RescheduleOnMainThread);
    });
}

private RescheduleOnMainThread(uint currentValue, uint linesThatAsserted)
{
  m_onEdgeDetectionTask = Task.Factory.StartNew(
    action: () =>
      {
        MessageBox.Show(currentValue);
      },
    cancellationToken: null,
    creationOptions: TaskCreationOptions.None,
    scheduler: m_mainThreadScheduler);
}

private void CleanUp()
{
  m_edgeDetector.Stop();
  m_edgeDetectionTask.Wait();
  m_onEdgeDetectionTask.Wait();
}

public void Form1_Load(object sender, EventArgs e)
{
  Initialize();
  StartEdgeDetection();
}

public void Form1_Closed(object sender, EventArgs e)
{
  CleanUp();
}