Unfortunately, your suggestion didn't help. Here's what I tried, starting with the original NI-DAQmx Base function call sequence....
.....................................................................................................................................
// write output signal
DAQmxErrorCheck ( DAQmxBaseWriteAnalogF64( outputTaskHandle, samplesToWrite, 0, timeout, DAQmx_Val_GroupByScanNumber, outputData, &samplesWritten, NULL ) );
totalSamplesWritten += samplesWritten;
// trigger output when input starts
DAQmxErrorCheck ( DAQmxBaseCfgDigEdgeStartTrig( outputTaskHandle, outputTrigger, DAQmx_Val_Rising ) );
// initiate acquisition - must start output task first, as it will be triggered by the input task
DAQmxErrorCheck ( DAQmxBaseStartTask( outputTaskHandle ) );
DAQmxErrorCheck ( DAQmxBaseStartTask( inputTaskHandle ) );
.....................................................................................................................................
I first moved the 'Write' call to after the Trigger setup...
.....................................................................................................................................
// trigger output when input starts
DAQmxErrorCheck ( DAQmxBaseCfgDigEdgeStartTrig( outputTaskHandle, outputTrigger, DAQmx_Val_Rising ) );
// write output signal
DAQmxErrorCheck ( DAQmxBaseWriteAnalogF64( outputTaskHandle, samplesToWrite, 0, timeout, DAQmx_Val_GroupByScanNumber, outputData, &samplesWritten, NULL ) );
totalSamplesWritten += samplesWritten;
// initiate acquisition - must start output task first, as it will be triggered by the input task
DAQmxErrorCheck ( DAQmxBaseStartTask( outputTaskHandle ) );
DAQmxErrorCheck ( DAQmxBaseStartTask( inputTaskHandle ) );
.....................................................................................................................................
I next moved the 'Write' call to after the output Start...
.....................................................................................................................................
// trigger output when input starts
DAQmxErrorCheck ( DAQmxBaseCfgDigEdgeStartTrig( outputTaskHandle, outputTrigger, DAQmx_Val_Rising ) );
// initiate acquisition - must start output task first, as it will be triggered by the input task
DAQmxErrorCheck ( DAQmxBaseStartTask( outputTaskHandle ) );
// write output signal
DAQmxErrorCheck ( DAQmxBaseWriteAnalogF64( outputTaskHandle, samplesToWrite, 0, timeout, DAQmx_Val_GroupByScanNumber, outputData, &samplesWritten, NULL ) );
totalSamplesWritten += samplesWritten;
DAQmxErrorCheck ( DAQmxBaseStartTask( inputTaskHandle ) );
.....................................................................................................................................
I even tried moving it to after the input Start call, but this gave an error as expected.
In every case above, I observed exactly the same corrupt, incomplete output waveform.
To make it easier for you, or another engineer, to reproduce this problem, I will attach the complete XCode project (Mac OS X), not just the source code.
.........
In my own trial-and-error testing, I've found that almost filling the FIFO in the first Write call improves the output waveform under most, but not all conditions (see #define fillFIFO in the attached code). Even if I could get this approach working reliably in all circumstances, it seems like a fragile kludge. I had to figure out the size of the PCIe-6251 FIFO by trial and error, and have hard coded it. If an end-user had a different digitizer, my code would most likely break.
As you stated in your reply, the original sequence of NI-DAQmx Base function calls is very reasonable, and similar to that in the working LabVIEW program. The fact that it definitely doesn't work under Mac OS X / NI-DAQmx Base strongly suggests there is a bug in NI-DAQmx Base.
Thanks for your help with this,
John.
Dr John Clements
Lead Programmer
AxoGraph Scientific