Tried liblxi with TCP RAW, and I don't know how to handle the transfers.
- it puts consecutive lxi_send() strings in the same data packet, which the oscilloscope won't understand. I don't know how to flush the transmit buffer after each lxi_send(), so as a workaround I'm adding an *OPC? at the end of each command.
- even so, when the oscilloscope sends the first 250 000 data bytes, the lxi_receive() returns only the payload of the first TCP packet, which is 1460 bytes, while the oscilloscope continues to send more packets. I was expecting for the lxi_receive() to concatenate the payload of all the incoming TCP packets, and to stop only when the whole 250000 requested bytes are received (or if a timeout occurs), but lxi_receive() returns after the first TCP packet. Not sure if this is a bug or it's the NO_BLOCKING setting of a TCP RAW connection.
I don't know how to send TCP_BLOCKING (or alike) to the socket, or if such a feature exists in a liblxi TCP RAW connection.
// liblxi git at https://github.com/lxi-tools/liblxi
// to install it from the ubuntu repository (lxilib-dev is in most of the Linux distros repos and in FreeBSD):
// sudo apt install liblxi-dev
// headers in /usr/include/lxi.h
// .so lib in /usr/lib/x86_64-linux-gnu/liblxi.so
// display all installed files with 'dpkg -L liblxi-dev' or
// sudo apt install apt-file
// sudo apt-file update
// (sudo???) apt-file list liblxi-dev
// no need to append LIBRRY_PATH or LD_LIBRARY_PATH
// man lxi_<TAB><TAB>
// lxi_connect lxi_discover lxi_init lxi_send lxi_disconnect lxi_discover_if lxi_receive
// compile and run this 'demo.c' from a Linux terminal (!!! -l options _must_ be positioned after the .c sources, not before)
// cd /home/muuu/wd8TB/2019/Z/_hobby/__Pnnn/221103___VNA_DG4102_DS1054Z_python/sw/C
// gcc -Werror -Wfatal-errors ./dl_24M_ADC_samples_ds1054z.c -llxi -ltirpc && time ./a.out
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <lxi.h>
int main()
{
printf("liblxi w DS1054Z using TCP mode RAW");
// 12 bytes preamble + max of 24 mil bytes of ADC samples + 1 byte for the end of string terminator
#define CHARS_BUFFER_MAX 24000000L // in specs max Rx in a single chunk is 250k chars for Rigol DS1054Z
char *rx24MB = NULL; // declare a pointer to char, and initialize it with NULL
rx24MB = malloc(CHARS_BUFFER_MAX * sizeof *rx24MB); // allocated memory on the heap for rx24MB[CHARS_BUFFER_MAX]
if (!rx24MB) { // !!! always check the memory was allocated successfully !!!
fputs ("ERROR: allocation memory failed for the 'rx24MB' buffer, exiting.", stderr);
exit (EXIT_FAILURE);
}
int device, length, timeout = 2000; // timeout is in ms
char response[1000]; // allocated on the stack, segmentation fault if too large, Linux max stack is 8MiB
//char *command = "*IDN?"; // with or without \n, the osc responded in a VXI11 connection
char *command = "*IDN?\n";
lxi_init(); // Initialize LXI library
//device = lxi_connect("192.168.1.3", 0, "inst0", timeout, VXI11); // instument responded to either *IDN? or *IDN?\n
// device = lxi_connect("192.168.1.3", 0, NULL, timeout, VXI11); // Connect to LXI device
device = lxi_connect("192.168.1.3", 5555, "inst0", timeout, RAW); // must end in \n, or else *IDN? timeout as incomplete
// device = lxi_connect("192.168.1.3", 5555, "TCP", timeout, RAW); // *IDN? Timeout err for timeout 2000
// device = lxi_connect("192.168.1.3", 0, "inst0", timeout, RAW); // NOPE
// device = lxi_connect("192.168.1.3", 5555, "inst0", timeout, HISLIP); // *IDN? garbled chars for timeout 2000
lxi_send(device, command, strlen(command), timeout); // Send SCPI command ("*IDN?")
lxi_receive(device, response, sizeof(response), timeout); // Rx until "\n", or sizeoff(response) chars, or timeout
printf("%s\n", response);
// exit if no DS1054Z
// exit(0);
// enable only ch1
command = ":CHAN1:DISP 1;*OPC?\n";
lxi_send(device, command, strlen(command), timeout);
lxi_receive(device, response, sizeof(response), timeout); // Rx until "\n"?, or sizeoff(response) chars, or timeout
command = ":CHAN2:DISP 0;*OPC?\n";
lxi_send(device, command, strlen(command), timeout);
lxi_receive(device, response, sizeof(response), timeout);
command = ":CHAN3:DISP 0;*OPC?\n";
lxi_send(device, command, strlen(command), timeout);
lxi_receive(device, response, sizeof(response), timeout);
command = ":CHAN4:DISP 0;*OPC?\n";
lxi_send(device, command, strlen(command), timeout);
lxi_receive(device, response, sizeof(response), timeout);
// ??? here to insert ":RUN""
// set acquisition mode to max 24_000_000 points memory depth
// "auto", 12K, 120K, 1.2M, 12M, 24M"
long mdep = 24000000L;
command = ":RUN;*OPC?\n";
lxi_send(device, command, strlen(command), timeout);
lxi_receive(device, response, sizeof(response), timeout);
// sprintf(command, ":ACQ:MDEP %li", mdep);
// sprintf(command, ":ACQ:MDEP %li%s", mdep, "\0");
command = ":ACQ:MDEP 24000000;*OPC?\n";
lxi_send(device, command, strlen(command), timeout);
lxi_receive(device, response, sizeof(response), timeout);
// wait for triggered
do {
command = ":TRIGger:STATus?\n";
lxi_send(device, command, strlen(command), timeout);
lxi_receive(device, response, sizeof(response), timeout);
} while (response[0] != 'T');
// then wait for ADC to aquire enough data
clock_t stop_time;
printf("wait %ld\n", clock());
stop_time = clock() + 30000; //30 seconds
printf("beep %ld\n", stop_time);
while (clock() < stop_time) ;
printf("go %ld\n", clock());
// go to stop mode and prepare to dl 24MSa
command = ":STOP;*OPC?\n";
lxi_send(device, command, strlen(command), timeout);
lxi_receive(device, response, sizeof(response), timeout);
command = ":WAV:SOUR CHAN1;*OPC?\n";
lxi_send(device, command, strlen(command), timeout);
lxi_receive(device, response, sizeof(response), timeout);
command = ":WAV:MODE RAW;*OPC?\n";
lxi_send(device, command, strlen(command), timeout);
lxi_receive(device, response, sizeof(response), timeout);
command = ":WAV:FORM BYTE;*OPC?\n";
lxi_send(device, command, strlen(command), timeout);
lxi_receive(device, response, sizeof(response), timeout);
// char c2[80] = {0};
char c2[80];
// loop to dl all samples in chunks of (max) 250_000 samples
// set start-stop indexes for next chunk
long rx_len, chunk_len;
// long chunk_start, chunk_stop, chunk_size = 125000L; //dl 24Msa/134s
long chunk_start, chunk_stop, chunk_size = 250000L; //dl 24Msa/86s max from specs
// long chunk_start, chunk_stop, chunk_size = 750000L; //dl 24Msa/65s
// long chunk_start, chunk_stop, chunk_size = 1000000L; //dl 24Msa/56s preferred ???
// long chunk_start, chunk_stop, chunk_size = 1175000L; //dl 24Msa/54s
long samples_to_dl = 24000000L;
if (samples_to_dl > mdep) {
samples_to_dl = mdep;
}
for(chunk_start = 1; chunk_start < samples_to_dl; chunk_start += chunk_size) {
sprintf(c2, ":WAV:STAR %li;*OPC?\n", chunk_start);
puts(c2);
rx_len = lxi_send(device, c2, strlen(c2), timeout);
printf("ack_len=%ld\n", rx_len);
lxi_receive(device, response, sizeof(response), timeout);
//at the last chunk, chunk_len might be shorter than chunk_size
if (chunk_start + chunk_size > samples_to_dl) {
chunk_len = samples_to_dl - chunk_start + 1;
chunk_stop = samples_to_dl;
} else {
chunk_len = chunk_size;
chunk_stop = chunk_start + chunk_size - 1;
}
sprintf(c2, ":WAV:STOP %li;*OPC?\n", chunk_stop);
puts(c2);
rx_len = lxi_send(device, c2, strlen(c2), timeout);
printf("ack_len=%ld\n", rx_len);
lxi_receive(device, response, sizeof(response), timeout);
command = ":WAV:DATA?\n";
puts(command);
rx_len = lxi_send(device, command, strlen(command), timeout);
printf("ack_len=%ld\n", rx_len);
rx_len = lxi_receive(device, (char *)(&rx24MB[chunk_start-1]), chunk_len, timeout);
printf("rx_data_bytes=%ld\n", rx_len);
int err = 0;
if(rx_len != chunk_len) {
printf("ERROR - received too few bytes: ");
err = 1;
}
printf("chunk_len=%li rx_len=%li\n", chunk_len, rx_len);
printf("\n");
if(err) exit(err);
}
// Disconnect
lxi_disconnect(device);
}
will output is this:
liblxi w DS1054Z using TCP mode RAWRIGOL TECHNOLOGIES,DS1104Z,DS1ZA164658712,00.04.05.SP2
wait 15947
beep 45970
go 45970
:WAV:STAR 1;*OPC?
ack_len=18
:WAV:STOP 250000;*OPC?
ack_len=23
:WAV:DATA?
ack_len=11
rx_data_bytes=1460
ERROR - received too few bytes: chunk_len=250000 rx_len=1460