Digital I/O

cancel
Showing results for 
Search instead for 
Did you mean: 

Generation Buffer Control

Hi Guys,

I need to generate a large buffer for pattern generation and do not want to duplicate the memory requires. It seems to me if I use:

DAQmxWriteDigitalU16(OutTaskHandle,OutBufPnt,0,0,DAQmx_Val_GroupByChannel,OutBuf,NULL,NULL)

I have to allocate space for the buffer
OutBuf (in this case), write my vectors to this buffer and then DAQmx will duplicate this buffer and copy it to another memory space, thus require two large buffers (which I do not have enough memory for).

1. Can I not just create the DAQmx buffer and write to it directly?

2. If so how do I do this?

My second part of this question is that I also need to alter some of the vectors in my buffer, recopy this vector buffer to DAQmx buffer and the rerun the entire set. I do this in the loop shown below:

   for (count1=0;count1<TotalSequencesInAquisition;count1++)
   {
/* Load vector buffer with correct DAC codes */
      InsertDACCodeToConvVectors(DACBuf,OutBuf,DACPointer,DACCodesPerSequence,count1);
 
/* DAQmx Start Pattern Generation */
       DAQmxErrChk (DAQmxWriteDigitalU16(OutTaskHandle,OutBufPnt,0,0,DAQmx_Val_GroupByChannel,OutBuf,NULL,NULL));
       DAQmxErrChk (DAQmxStartTask(InTaskHandle));
       DAQmxErrChk (DAQmxStartTask(OutTaskHandle));
       DAQmxErrChk (DAQmxWaitUntilTaskDone(InTaskHandle,10));
       DAQmxErrChk (DAQmxReadDigitalU16(InTaskHandle,DataPerSequence,0,DAQmx_Val_GroupByChannel,&DataBuf[DataPerSequence*count1],DataPerSequence,NULL,NULL));
       DAQmxErrChk (DAQmxWaitUntilTaskDone(OutTaskHandle,10));
       DAQmxErrChk (DAQmxStopTask(InTaskHandle));
       DAQmxErrChk (DAQmxStopTask(OutTaskHandle));
   }

The issue is that this runs correctly the first time through but the second time it does not seem that the updated OutBuf buffer is being copied to the DAQmx buffer and the first set of vectors are simply rerun.

1. What am I doing wrong?

I suppose if my first question is answered then the second is probably not relevant. However, I still am a little baffled as to why this does not work.

Thanks
0 Kudos
Message 1 of 17
(4,568 Views)
Sorry for not mentioning it but this is using a PCIe-6537.
0 Kudos
Message 2 of 17
(4,554 Views)
Hi Frustrated,

I have a few questions and a few suggestions that you might try.  How large is the pattern you are trying to generate?  Is it possible that you could break this large pattern down into smaller sections and "stream" them to the card with the DAQmxWriteDigitalU16?  This would eliminate your memory allocation issues by just allocation a smaller amount of memory for each chunk of data.   I also found a great article about streaming options for PCI Express that you might want to take a look at here.  I don't see any functionality directly create the DAQmx buffer.  The driver is setup to work with the DAQmxWriteDigitalU16 function call.  I also found another great article that articulates how pattern regeneration is done with your card.  It can be found here.

In regards to your second question,  I'm a little confused as to what your trying to accomplish.  What are you trying to do with the DAQmxReadDigitalU16?  If you are just trying to simply make modifications or write new pattern, you just need to rewrite the new pattern to the card with another DAQmxWrite.  This will update the onboard memory with the new pattern and stream it instead of regeneration the old data.

I hope this helps,
Paul C.

Message Edited by Paul C. on 09-26-2007 07:38 PM

0 Kudos
Message 3 of 17
(4,525 Views)
Paul,
 
Thanks for the response. The buffer size needs to be as large as I can make it. I am already breaking it up into smaller chunks (1024 to be more specific). What I am finding is DAQmxWriteDigitalU16 seems to fail if I attempt to make the buffer larger than 512Mbytes. My machine has 4Gbytes. I can live with 512Mbytes as long as I can get DAQmxWriteDigitalU16 to reload the buffer and run the new vectors each time through the loop. What it is currently doing after stopping the task and then recalling DAQmxWriteDigitalU16 is simply rerunning the vectors in the first call of DAQmxWriteDigitalU16.
 
As I understand what is currently happening is I create my own 512Mbyte buffer in which I generate the vectors, then DAQmx generates another 512Mbyt buffer and copies my buffer to its buffer and then run the vectors from its buffer. What I would prefer to do is create the DAQmx buffer with the buffer create command and then write my vectors directly to that buffer and then run them straight from this single buffer.
 
If this is not possible, then I can go ahead and do what I am currently doing but release my buffer after it is copied to the DAQmx buffer with DAQmxWriteDigitalU16 call and then I would like to directly manipulate the DAQmx buffer with my vector updates (I need to change only about 1% of the vectors each time through the loop). By releasing this redudant buffer, I have more space for the input data storage buffer, which needs to be even larger (at least 2Gbytes).
 
I am not sure I made sense here but I will read the links you have pointed me to and hopefully they will give me some clues on how to proceed.
 
Thanks
0 Kudos
Message 4 of 17
(4,521 Views)
Hi Frustrated,

Let me start off by explaining my thoughts on your application.  Basically, I see beginning your task by allocating a large amount of PC memory to be used as y our output buffer.  Lets say that this is 512MB.  If you have a chunk of data to be written to the card using the DAQmxWriteDigitalU16 it is going to allocate 512MB of memory and transfer this data to the PC Memory.  For the first example, lets say that you just want to output one array once and that is it.  As the card starts writing this data, the card will write the entire array and you can programmatically have the DAQmx write stop after it has written the entire array.   You can also have the card loop and continue writing the array over and over until you stop the application (By default, regeneration is on during a continuous generation).  This is done by "regeneration".  Essentially, the card will output whatever is in the buffer (in a circular fashion) until you say stop.  You also have the option to choose turn off this regeneration to force the card to not regeneration data.

 From what it sounds from your application, you want to generate new array's at some point.  You can use another DAQmxWriteDigitalU16 within the same task to use the same allocated memory and fill it up with new array information.  This new array information will be outputted in a sequence after the first array is fully outputted from the buffer.  As long as you write new information to the buffer faster than you are outputting, while watching that you don't overflow the buffer, you will be outputing one full array and then the new full array without regenerating the original array.

I think what you are wanting to do is just use the original 512MB array with possible slight modifications without having to write the same array to memory again.  I'm going to look into checking out this card and trying a few possible solutions.  In regards to the 512MB limit in terms of buffer allocation, I have tried allocating a buffer larger than that in a LabVIEW envirement and havn't had any errors or problems.  Specifically, what value to do you pass to the output buffer config function.  Could you post what enviroment you are working within?  Are you using LabWindows CVI?  What version of DAQmx are you using?  Also, if you have some code that I would be able to run on my end to duplicate these issues that you are talking about that might be helpful in finding you a solution. 

I hope this helps,
Paul C.
0 Kudos
Message 5 of 17
(4,483 Views)
Thanks Paul,
 
I am using BorlandC 5.02 and DAQmx 8.3. Attached is the main program (test.c) and the function of interest (runconversion.c) and the custom header (AC80TrimHeaders.h). There are 3 other subroutines needed but the system will only allow me to attach 3 files. If you send and email address I will forward the other functions.
 
Note that in the final application EndDAC=2^22, StartDAC=0, StepSize=1, ConvPerDACCode=32, thus MemoryInConvVectors=17408*2^22 and TotalSequencesInAquisition=72. More simply, I am running a 22-bit DAC over all codes sampling it 32 times per code (with some settling time)
Look at lines 142 to 173 in runconversion.c for the DAQmx setup and calling. Most likely I am just doing something stupid as the DAQmx C function reference manual is both woefully incomplete and obscure (thus the user name FrustratedWithDAQmxHelp). Please let me know if you see something wrong here. What this does is time I run DAQmxStartTask(OutTaskHandle), I seem to get the set of vectors copied by the first call to DAQmxWriteDigitalU16. Thus subsequent passes through the loop produces the same set of output vectors.
 
One thing you mentioned that I was hoping you would elaborate on (although I may just be misunderstanding you) is the idea of what use to be called double buffering in the older versions of DAQ. I could not see how to do this with DAQmx, however, I would like to do this with this application. With the present way I have written this, there is a delay between segments while the function InsertDACCodesToConvVectors copies new DAC codes to the buffer and then DAQmxWriteDigitalU16 recopies that buffer before the next segment runs. It would be nice if that delay did not exist.
 
Is there a way to use two buffers and while the first is being outputted, we generate a second and as soon as the first is completed, we start the second. Note that my clock speed is 40MHz.
 
Thanks again.
 
Download All
0 Kudos
Message 6 of 17
(4,465 Views)


@FrustratedwithDAQmxHelp wrote:

Is there a way to use two buffers and while the first is being outputted, we generate a second and as soon as the first is completed, we start the second. Note that my clock speed is 40MHz.
 
Thanks again.
 




Yes, there is.  Configure the DAQmx Buffer size to be smaller than your total generation size, before starting the task, write enough to fill the buffer, start the task, and then start writing.  DAQmx internally will double buffer for you.  Assuming that your application can compute the data fast enough for the buffer, you won't need a large working set for the generation side.

Changing the subject a little, but why does RunConversion.c configure the 6537 to allow regeneration and pause until data is available?

Jeff
0 Kudos
Message 7 of 17
(4,455 Views)
Jeff,
 
How is synchronization maintained? I do not see how what you are proposing will work. Can you give me an example code?
 
To answer your question, I have no idea what 95% of the DAQmx functions do because the documentation is so poor. Please do something to get better documentation because what I have (which I have been told by several NI employees is all that there is) is insufficient to actually compentently use this hardware. Thus I am left to a frustrating trial and error approach to writing the interface code to this board. I have attempted several combinations of allowing and dissallowing regeneration as well as states of pause data and have not been able to correllate the response of the card to either. Quit frankly I have no idea what these functions are suppose to do outside the vague implecations of their names.
 
The hardware I am attempting to test does not require pause control for pattern generation. It can run as fast as the card can feed it data. What is important to me is that there is no jitter. If I have to run a bit slower to not get jitter, that is fine.  I am providing and external clock (really a data valid input) to the InTaskHandle task to aquire states of port2 at certain times during the pattern generation.
 
I would like to use double buffering so I can generate 2^27 conversions in a continuous manner. Since I compute and write all of the vectors to memory prior to starting the pattern generation, I beleive the PC should be able to keep up as it only has to copy from one buffer to another. However, I would not know how to implement what you are suggesting. Any assistance you can provide (examples are most helpful) would be much appreciated.
 
Thanks again
 
Larry
0 Kudos
Message 8 of 17
(4,450 Views)
Hi Larry,

I would highly recommend taking a look at our ANSI C shipping examples.  The location of these examples can be found by using the article found here.  These examples help better document our functions by demonstrating the proper methods for using these functions.  In regards to what Jeff said, I believe the program flow he is suggesting would be as follows: set up the task including the output buffer size to smaller than the total generation size, use the DAQmx write to fill the buffer, start the task, use the DAQmx write function again to continue to fill the buffer with new data until your done, and then finally stop/clear the task.  This will allow you to keep the buffer filled with your new array information on the fly. 

I hope this helps,
Paul C.
0 Kudos
Message 9 of 17
(4,428 Views)

Paul,

I appreciate your reply. I have looked at all of the examples that you refer to. Without those I would certainly have gotten nowhere. However, they are limited. I can honestly tell you with what you have given me on the double buffering, I will not succeed. There are far too many options and subtile nuances involved and resolving each takes far longer than I have time. It would be much better for either better documentation on the each function to be provided or for you to give me more details (like an actual example). In the mean time do you have any idea why my exiting code keeps output the state of the first buffer call.

 

Thanks Larry

0 Kudos
Message 10 of 17
(4,430 Views)