10-21-2009 01:45 PM
Solved! Go to Solution.
10-21-2009 01:46 PM
Here is the output from the PCIe-6363 and the simulated USB-6255 (the previous post wouldn't let me include it due to the 10,000 character restriction)
Using Dev1 : PCIe-6363
After commit spaceAvailable = 512
After write spaceAvailable = 512, samplesWritten=64
After write spaceAvailable = 512, samplesWritten=128
After write spaceAvailable = 512, samplesWritten=192
After write spaceAvailable = 512, samplesWritten=256
After write spaceAvailable = 512, samplesWritten=320
After write spaceAvailable = 512, samplesWritten=384
After write spaceAvailable = 512, samplesWritten=448
After write spaceAvailable = 512, samplesWritten=512
DAQmx Error: The generation is not yet started, and not enough space is available in the buffer.
Configure a larger buffer, or start the generation before writing more data than will fit in the buffer.
Property: DAQmx_Write_RelativeTo
Requested Value: DAQmx_Val_CurrWritePos
Property: DAQmx_Write_Offset
Requested Value: 0
Task Name: _unnamedTask<0>
Status Code: -200293
SIMULATED DEVICE:
Using Dev7 : USB-6255
After commit spaceAvailable = 512
After write spaceAvailable = 448, totalSamplesWritten=64
After write spaceAvailable = 384, totalSamplesWritten=128
After write spaceAvailable = 320, totalSamplesWritten=192
After write spaceAvailable = 256, totalSamplesWritten=256
After write spaceAvailable = 192, totalSamplesWritten=320
After write spaceAvailable = 128, totalSamplesWritten=384
After write spaceAvailable = 64, totalSamplesWritten=448
After write spaceAvailable = 0, totalSamplesWritten=512
Task started
SamplesGenerated = 0, totalSamplesWritten= 512, spaceAvailable = 0
SamplesGenerated = 96, totalSamplesWritten= 512, spaceAvailable = 96
SamplesGenerated = 192, totalSamplesWritten= 576, spaceAvailable = 128
SamplesGenerated = 300, totalSamplesWritten= 640, spaceAvailable = 172
SamplesGenerated = 396, totalSamplesWritten= 704, spaceAvailable = 204
SamplesGenerated = 493, totalSamplesWritten= 768, spaceAvailable = 237
SamplesGenerated = 600, totalSamplesWritten= 832, spaceAvailable = 280
SamplesGenerated = 696, totalSamplesWritten= 896, spaceAvailable = 312
SamplesGenerated = 793, totalSamplesWritten= 960, spaceAvailable = 345
SamplesGenerated = 900, totalSamplesWritten= 1024, spaceAvailable = 388
<snip>
SamplesGenerated = 2624, totalSamplesWritten= 2624, spaceAvailable = 512
SamplesGenerated = 2688, totalSamplesWritten= 2688, spaceAvailable = 512
SamplesGenerated = 2752, totalSamplesWritten= 2752, spaceAvailable = 512
SamplesGenerated = 2816, totalSamplesWritten= 2816, spaceAvailable = 512
SamplesGenerated = 2880, totalSamplesWritten= 2880, spaceAvailable = 512
10-22-2009 07:10 PM - edited 10-22-2009 07:11 PM
Hi Sherryl,
The X Series behavior is in fact a bug which was previously reported (link). It is currently being addressed under CAR #191661. It is specific to the X Series code and should be addressed in an upcoming DAQmx release.
Having said this, the other behavior you are seeing is actually expected. Let's start with a quick recap of your code:
1. Configure a continuous non-regeneration task at 1kHz with 512 sample buffer
2. Start Task
3. Query for SpaceAvail
4. If SpaceAvail > 64 samples write 64 samples
5. Wait 100 ms
6. Return to step 3
With this in mind, let's first examine the interesting part of the PCI (E and M Series) logs:
SamplesGenerated = 1, totalSamplesWritten= 512, spaceAvailable = 3
SamplesGenerated = 101, totalSamplesWritten= 512, spaceAvailable = 103
SamplesGenerated = 202, totalSamplesWritten= 576, spaceAvailable = 140
SamplesGenerated = 302, totalSamplesWritten= 640, spaceAvailable = 176
SamplesGenerated = 403, totalSamplesWritten= 704, spaceAvailable = 213
SamplesGenerated = 503, totalSamplesWritten= 768, spaceAvailable = 249
SamplesGenerated = 604, totalSamplesWritten= 832, spaceAvailable = 286
SamplesGenerated = 705, totalSamplesWritten= 896, spaceAvailable = 323
SamplesGenerated = 805, totalSamplesWritten= 960, spaceAvailable = 359
SamplesGenerated = 906, totalSamplesWritten= 1024, spaceAvailable = 396
SamplesGenerated = 1006, totalSamplesWritten= 1088, spaceAvailable = 432
SamplesGenerated = 1107, totalSamplesWritten= 1152, spaceAvailable = 469
SamplesGenerated = 1207, totalSamplesWritten= 1216, spaceAvailable = 505
SamplesGenerated = 1207, totalSamplesWritten= 1280, spaceAvailable = 0etc.
There are three important things to note here:
1. DMA transfers occur in 4 byte packets (2 samples). For non-regeneration tasks, the data is written as needed from the Buffer to the on-board FIFO. The driver is "smart" and transfers the data to the on-board FIFO as necessary so that we do not run out of data to generate. spaceAvailable refers to how much space is available in the PC Buffer2. The code is writing at most 64 samples every 100ms, but the board is generating 100 samples in the same amount of time. Eventually the task is going to run out of data and die. Actually given there are 512 samples to start it will happen around the 11th cycle (1100-1200 points generated) (512/(100-64)).
3. Even if a task "dies" querying for spaceAvailable will not throw an error. After all even if an error occurred it may be valid to ask if there is space available. IsTaskDone on the other hand would return an error.
Knowing these three things makes it a bit more clear what happened above. The 512 sample section of the FIFO alocated for the generation depleated by about 46 (100-64) samples each cycle, until the board ran out of data and it was no longer valid to transfer data to the task at around the 12th cycle when the board stopped generating new samples (i.e. spaceAvailable became 0).
Now, taking a look at the USB data:
SamplesGenerated = 2, totalSamplesWritten= 512, spaceAvailable = 512
SamplesGenerated = 103, totalSamplesWritten= 576, spaceAvailable = 512
SamplesGenerated = 204, totalSamplesWritten= 640, spaceAvailable = 512
SamplesGenerated = 306, totalSamplesWritten= 704, spaceAvailable = 512
SamplesGenerated = 407, totalSamplesWritten= 768, spaceAvailable = 512
SamplesGenerated = 509, totalSamplesWritten= 832, spaceAvailable = 512
SamplesGenerated = 611, totalSamplesWritten= 896, spaceAvailable = 512
SamplesGenerated = 712, totalSamplesWritten= 960, spaceAvailable = 512
SamplesGenerated = 814, totalSamplesWritten= 1024, spaceAvailable = 512
SamplesGenerated = 915, totalSamplesWritten= 1088, spaceAvailable = 512
SamplesGenerated = 1017, totalSamplesWritten= 1152, spaceAvailable = 512
SamplesGenerated = 1118, totalSamplesWritten= 1216, spaceAvailable = 512
SamplesGenerated = 1220, totalSamplesWritten= 1280, spaceAvailable = 512
SamplesGenerated = 1322, totalSamplesWritten= 1344, spaceAvailable = 512
SamplesGenerated = 1409, totalSamplesWritten= 1408, spaceAvailable = 0etc.
Here the story is much different because:
1. USB transfers can be in sizes much larger than 4 bytes and small transfers tend to be inefficient. As a result it makes sense to transfer much larger sets of data from RAM to the FIFO. Also, it makes sense to keep the on-board FIFO relatively full considering the high latency of USB transfers. Once again, this is all handled by the driver.
2. Given the 100 ms delay in your code between writes of 64 samples, by the time the next loop iteration runs all of the data has already transferred to the device, so spaceAvailable in the PC Buffer should still be 512.
3. Comparing the following lines from the above logs shows why the USB will run slightly longer before the underflow occurs:
USB:
SamplesGenerated = 2, totalSamplesWritten= 512, spaceAvailable = 512
SamplesGenerated = 103, totalSamplesWritten= 576, spaceAvailable = 512
PCI:
SamplesGenerated = 1, totalSamplesWritten= 512, spaceAvailable = 3
SamplesGenerated = 101, totalSamplesWritten= 512, spaceAvailable = 103
Due to the difference between the bulk transfers of USB vs. the 32-bit transfers of PCI, the PCI device does not actually write data to the buffer during the first 100 ms loop (since not enough data has been transferred over yet to the board, there is not enough room for 64 new samples in the PC buffer). The USB device essentially has a "head start" in this scenario.
I think this is consistent and correct behavior (considering the points made above). It may be confusing, but despite the application being seemingly simple the data communication between the computer and the device are anything but. For this reason, a simulated device isn't really going to tell you what will happen if your code depends on the timing of your data transfers.
I hope this was informative, please don't hesitate to post back if you have any questions.
Best Regards,
John