I am writing a driver for the M-series NI PCI-6255 for QNX. I have downloaded the MHDDK and have all the examples working. I have also enhanced the examples to do interrupt handling (e.g. on AI_FIFO interrupt or DMA Ring Buffer interrupt). My ultimate goal is to write a driver that I can use for closed-loop control at 500 Hz using all 80 channels of the NI PCI-6255. I may also need to synchronize each scan with a NI PCIe-7841R card for which I've already written a driver. I want an interrupt-driven solution (be it programmed I/O on an interrupt or DMA that generates an interrupt) so that the CPU is available to other threads while the 80 analog inputs are being read (since it takes quite a while). I also want to minimize the number of interrupts. Basically, I will need to collect one sample from all 80 channels every 2 milliseconds.
There are many different options available to do so, but what is the recommended technique for the NI PCI-6255 card? I tried using the AI FIFO interrupt without DMA, but it seems to interrupt as soon as any data is in the AI FIFO (i.e. not empty condition), rather than when all 80 channels are in the FIFO, so more interrupts are generated than necessary. I tried using DMA in Ring Buffer mode to collect a single sample of 80 channels and interrupting on the DMA Ring Buffer interrupt, which appears to work better except that this technique runs into problems if I cannot copy all the data out of the DMA buffer before the next AI scan begins (because the DMA will start overwriting the buffer as it is in ring buffer mode). If the DMA is not in ring buffer mode or I make the ring buffer larger than one 80-channel sample then I don't have a way to generate an interrupt when one sample has been acquired (which I need, because I'm doing control).
I saw something in the documentation about a DMA Continue mode in which it looks like you can switch between two different buffers (by programming the Base Count/Address with a different address than the current address) automatically and thereby double-buffer the DMA but there is no real documentation or examples on this capability. However, I think it would work better than the Ring Buffer because I could interrupt on the DMA CONT flag presumably and be copying data out of one buffer while it is filling the other buffer.
Another option would be DMA chaining, but again, I cannot find any information on these features specific to the NI DAQs.
I tried interrupting on AI STOP figuring that I could get a single interrupt for each scan, but that doesn't appear to work as expected.
I know that DAQmx on Windows has the ability to do such single sample, multiple channel tasks at a fixed rate so the hardware must support it.
Any suggestions would be appreciated.
The interrupt that will happen nearest the times that you need is the AI_Start_Interrupt in the Interrupt_A group. This interrupt will occur with each sample clock. By the second time this interrupt fires, the AI FIFO should have the samples from the first conversion. If it is easier to use programmed IO, you can read the samples out of the FIFO until you get all 80.
Additionally, you can set the DMA to send samples as soon as the FIFO is no longer empty...instead of waiting for half full or full. This change will reduce latency for your control loop. You can set AI_FIFO_Mode in AI_Mode_3_Register to 0. By the second time this interrupt fires, you should be able to check how much data is in the DMA ring buffer and read the 80 samples when they are available. You can make the ring buffer larger than 80 samples if you see data getting overwritten.
There is no interrupt associated with 80 samples being available in the FIFO or 80 samples being available/transferred by DMA to the host. X Series has much more flexibility with these interrupts.
I hope this helps!
Does the AI Start interrupt not occur at the beginning of the scan? If so, then if I wait until the second Start signal to get the data from the first scan there will be a one sampling period delay in my control system, which is destabilizing. Ideally I would be using the data as soon as its sampled.
I already have the DMA configured to get a DMA request as soon as the FIFO is non-empty.
It sounds like the X-series is a better bet, but unfortunately I am constrained to use the NI PCI-6255.
Thanks for the ideas.
Thanks for the additional explanation.
Yes, the AI_Start interrupt occurs at the beginning of each group of channel scans. As soon as the non-empty fifo interrupt happens, you could start checking the amount of data in the DMA buffer and read when it is 80. This would minimize the amount of time spent polling. Since the processor would only be polling between receiving the first sample in the board fifo and the samples showing up in the DMA buffer, you may be able to perform your control at a reasonable rate.