02-14-2017 12:11 AM
We've already discussed how to configure and pass the buf_data parameter, and it appears that the buf_headers parameter should be handled similarly. For the samples_added, headers_added, and header_status parameters, the C code shows a 4-element array of ints, so that's what you need to create in your LabVIEW code. No need to explicity create a pointer for them, just do "Initialize Array" and then pass the array as an array data pointer. Or, if you prefer, it would also work to create a 4-element cluster, and then pass it as Adapt to Type.
For clarity, I would wire the corresponding outputs from the buf_headers and buf_data parameters to the deallocate VI, instead of forking the wire.
02-14-2017 01:15 AM
Hi Nathand,
That we did try to just use the initialize array with correct size and then we got a bit stuck as the data out didn't seem to be correct. Would the outputs of the dll then be the actual data or pointers to the data? I guess the first, but are unable to get the data correctly from the header as we are a bit unclear on this typecast to struct that happens afterwards. I link just that part of the code again.
success = success && ADQ_GetDataStreaming(adq_cu, adq_num, buf_data, buf_headers, channelsmask, samples_added, headers_added, header_status);
if (success)
{
for (ch = 0; ch < 4; ch++)
{
headers_done = 0;
if (headers_added[ch] > 0)
{
if (header_status[ch])
{
headers_done = headers_added[ch];
}
else
{
// One incomplete header
headers_done = headers_added[ch]-1;
}
headers_completed[ch] += headers_done;
// Here we need to read out all header info as we potentially alter it soon
// Copy the finished headers to destination
memcpy(dest_headers, buf_headers, headers_done * sizeof(typeHeaderADQ14));
if (headers_done != headers_added[ch])
{
// Copy the incomplete header to the beginning of the buffer (will destroy info in buffer!)
memcpy((void*)buf_headers[ch], (void*)((typeHeaderADQ14*)buf_headers[ch]+headers_done-1), sizeof(typeHeaderADQ14));
}
}
// headers_done now contains the number of finished records available for this channel
// and dest_headers contain the headers for the finished records.
// Remains to copy the data for the finished records.
// Copy all data (for finished records) to destination (which will use the data).
// Save "extra data", contents from next unfinished record to next iteration
record_samples = headers_done * samples_per_record;
nofrecords[ch] += headers_done;
if ((channelsmask & (1 << ch)) && (nofrecords_masked < nofrecords[ch]))
nofrecords_masked = nofrecords[ch];
if (headers_done > 0)
{
unsigned int tocopy = 0;
memcpy(dest_data, buf_extradata[ch], buf_extradata_samples[ch]*sizeof(short));
record_samples -= buf_extradata_samples[ch];
tocopy = MIN(samples_added[ch], record_samples);
memcpy((void*)((short*)dest_data+buf_extradata_samples[ch]), buf_data[ch], tocopy*sizeof(short));
buf_extradata_samples[ch] = 0;
samples_added[ch] -= tocopy;
}
// Here, destination pointer contains record data for all records for this channel
// for instance call a separate function to handle data here
// HandleData(ch, headers_done, dest_data, dest_headers);
// HandleData(Channel, NumberOfRecords, data_ptr, header_ptr)
if (headers_done > 0)
printf("%02u records from channel %u retrieved (total on channel %05u records).\n", headers_done, ch, nofrecords[ch]);
// Are there still data left to store to next time (data for yet unfinished records)?
// We have to store both the data and the size of the data to know how to use it in
// next iteration.
if (samples_added[ch] > 0)
{
// Store data in slatt buffers
memcpy(buf_extradata[ch], buf_data[ch], samples_added[ch]*sizeof(short));
buf_extradata_samples[ch] = samples_added[ch];
}
}
}
02-14-2017 01:53 AM
I've attached an example that does what you said with init array. We have tried to do 3 init array but also just one and forking wires, we didn't know exactly how LV will create these blocks of memory this is why we try different things.
However the outputs of headers are zero all the time. are we thinking wrong here? how can we access the data in these headers arrays?
02-14-2017 06:26 AM
I've played around with CVI now and made a very simple DLL that would do some manipulation of the LV initialized array and this seem to work. But with the same calling convention I only get zeros from the headers out of the GetDataStreaming function posted before.
Any ideas?
02-14-2017 06:26 AM
I've played around with CVI now and made a very simple DLL that would do some manipulation of the LV initialized array and this seem to work. But with the same calling convention I only get zeros from the headers out of the GetDataStreaming function posted before.
Any ideas?
02-14-2017 08:35 AM - edited 02-14-2017 08:36 AM
Your obviously way over your head with this!
So your DLL requires arrays of "unsigned int" values for the samples_added, headers_added and header_status arrays. What makes you believe that an unsigned int is a 16 bit usigned integer value? That was true back in Windows 3.x days, but that is already more than 20 years ago!!!
Convienently you did use unsigned 32 bit values in the VI for your CVI sample, so that makes sense that it would work!
Besides if you ever intend to make this also work for 64 Bit (if the manufacturer supports that) ,make a habit of making every control in LabVIEW that has to transport a pointer value, such as your adq_cu_ptr to be a 64 bit (unsigned) integer. Saves you a lot of crash and trial when you ever will switch to 64 Bit LabVIEW and the 64 Bit DLL.
02-14-2017 08:51 AM
Completely true, I'm brushing up on my C skills was many years ago in school and with the cvi example I understood that this was due to operation system. So we changed that in the call to the driver dll. But our headers out are still just empty which they really shouldn't be.
Thanks about the tips of making it 64 bit safe. They actually have both a 64 bit dll 64 bit 32 bit compatible and 32 bit dll. So we should take that into consideration.
We are pretty sure that the dll call is setup correctly now as we get true on success out and according to documentation that means we have atleast 1 full buffer. But the header data doesn't seem to give this impression. I guess a loop back to the device manufacturer is needed.
We will continue with some other streaming examples which doesn't use this GetDataStreaming function and see if we are in better luck there.
02-15-2017 12:24 PM
The example C code you provided shows a lot of setup work before calling GetDataStreaming; did you duplicate all of that in LabVIEW, and if so, are you sure it all works?
02-15-2017 12:47 PM
Se are very confident that the setup part works as we use a lot of it for multirecord, which works. But there has to be some part not working surely. We Will discuss with device manufacturer next week probably and know better.
02-15-2017 12:57 PM
Do you want to post your LabVIEW code to see if someone here on the forum sees an error? I don't think I would rely on the DLL returning "success" as proof that you have configured the DLL call correctly.