Community
cancel
Showing results for 
Search instead for 
Did you mean: 
Highlighted
Valued Contributor III
703 Views

DE4 simple socket server

Hello all, 

 

I implemented a data acquisition system on the DE4. In general, I grab a fixed number of samples (called A-line), store them on a RAM and then my SOPC reads the RAM contents (through PIO's) and then Nios sends data through ethernet to the PC (Matlab, with pnet http://www.mathworks.com/matlabcentral/fileexchange/345-tcpudpip-toolbox-2-0-6

I modified the example provided by Terasic, having 2 transfer modes: 

1. Slow transfer: I send a command (ASCII 65) to the socket server and it sends one A-line to PC. Works fine, but terribly slow (~4.85 lines/sec). 

2. Continuous transfer: I send another command (ASCII 67) and the socket server continuously sends A-lines (~1093 lines/sec), but they overlap each other. See attached picture. 

 

I wonder if anyone has an idea how to avoid data from overlapping :confused: 

 

I basically modified the function sss_exec_command in the code simple_socket_server.c: 

 

. . . /*sss_exec_command()*/ void sss_exec_command(SSSConn* conn) { int bytes_to_process = conn->rx_wr_pos - conn->rx_rd_pos; INT8U tx_buf; INT8U *tx_wr_pos = tx_buf; int pos_ini = tx_wr_pos; INT8U error_code; /* * "SSSCommand" is declared static so that the data will reside * in the BSS segment. This is done because a pointer to the data in * SSSCommand * will be passed via SSSLedCommandQ to the LEDManagementTask. * Therefore SSSCommand cannot be placed on the stack of the * SSSSimpleSocketServerTask, since the LEDManagementTask does not * have access to the stack of the SSSSimpleSocketServerTask. */ static INT32U SSSCommand; SSSCommand = CMD_LEDS_BIT_0_TOGGLE; while(bytes_to_process--) { SSSCommand = toupper(*(conn->rx_rd_pos++)); if(SSSCommand >= ' ' && SSSCommand <= '~') { tx_wr_pos += sprintf(tx_wr_pos, "--> Simple Socket Server Command %c.\n\r", (char)SSSCommand); if (SSSCommand == CMD_QUIT) { tx_wr_pos += sprintf(tx_wr_pos,"Terminating connection.\n\n\r"); conn->close = 1; } // END if (SSSCommand == CMD_QUIT) else { if (SSSCommand == 65) {// Read command A (ASCII code = 65) //printf("--> Acquiring single %c-line...\n",(char)SSSCommand); // Wait to finish writing acquired data to the RAM do { acq_busy_signal = IORD_ALTERA_AVALON_PIO_DATA(ACQ_BUSY_PIO_BASE); // look definitions in ..software\simple_socket_server\simple_socket_server_syslib\Debug\system_description\system.h } while (acq_busy_signal == 1); // Indicate that we are busy reading RAM contents read_RAM_busy = 1; IOWR_ALTERA_AVALON_PIO_DATA(READ_RAM_BUSY_PIO_BASE, read_RAM_busy); // Do the transfer buffer_position = 0; *tx_wr_pos = 0; tx_wr_pos = pos_ini; if (acq_busy_signal == 0)//acq_busy_signal == 0 { for (RAM_address = 1; RAM_address <= NSAMPLES; RAM_address++) { // Read data port (from RAM) ADC_data = IORD_ALTERA_AVALON_PIO_DATA(ADC_DATA_PIO_BASE); // Write address port (to RAM) IOWR_ALTERA_AVALON_PIO_DATA(READ_RAM_ADDRESS_BASE, RAM_address + 1); dataPointer = &ADC_data; // Send 16-bit data tx_buf = dataPointer; tx_buf = dataPointer; /* If ADC_data == 32bits tx_buf = dataPointer; tx_buf = dataPointer; tx_buf = dataPointer; tx_buf = dataPointer; tx_wr_pos += 4; // 4 bytes*/ tx_wr_pos += 2; // 2 bytes increment buffer_position += 2; // Send data every 500*2 bytes /* if (RAM_address % 500 == 0 && RAM_address != 0) { send(conn->fd, tx_buf, tx_wr_pos - tx_buf, 0); buffer_position = 0; *tx_wr_pos = 0; tx_wr_pos = pos_ini; } else { buffer_position = (RAM_address % 500) * 2; //2 bytes }*/ } // END for (RAM_address = 0; RAM_address <= NSAMPLES; RAM_address++) send(conn->fd, tx_buf, tx_wr_pos - tx_buf, 0); buffer_position = 0; *tx_wr_pos = 0; tx_wr_pos = pos_ini; //printf("--> A-line sent!\n"); } // END if (acq_busy_signal == 0) // Indicate that we are done reading RAM contents read_RAM_busy = 0; IOWR_ALTERA_AVALON_PIO_DATA(READ_RAM_BUSY_PIO_BASE, read_RAM_busy); } // END if (SSSCommand == 65) else { if (SSSCommand == 67) { printf("Continuous acquisition! \n"); while (SSSCommand != CMD_QUIT) { // Wait to finish writing acquired data to the RAM do { acq_busy_signal = IORD_ALTERA_AVALON_PIO_DATA(ACQ_BUSY_PIO_BASE); // look definitions in ..software\simple_socket_server\simple_socket_server_syslib\Debug\system_description\system.h } while (acq_busy_signal == 1); // Indicate that we are busy reading RAM contents read_RAM_busy = 1; IOWR_ALTERA_AVALON_PIO_DATA(READ_RAM_BUSY_PIO_BASE, read_RAM_busy); // Do the transfer buffer_position = 0; *tx_wr_pos = 0; tx_wr_pos = pos_ini; if (acq_busy_signal == 0)//acq_busy_signal == 0 { for (RAM_address = 1; RAM_address <= NSAMPLES; RAM_address++) { // Read data port (from RAM) ADC_data = IORD_ALTERA_AVALON_PIO_DATA(ADC_DATA_PIO_BASE); // Write address port (to RAM) IOWR_ALTERA_AVALON_PIO_DATA(READ_RAM_ADDRESS_BASE, RAM_address + 1); dataPointer = &ADC_data; // Send 16-bit data tx_buf = dataPointer; tx_buf = dataPointer; tx_wr_pos += 2; // 2 bytes increment buffer_position += 2; } // END for (RAM_address = 0; RAM_address <= NSAMPLES; RAM_address++) send(conn->fd, tx_buf, tx_wr_pos - tx_buf, 0); buffer_position = 0; *tx_wr_pos = 0; tx_wr_pos = pos_ini; } // END if (acq_busy_signal == 0) // Indicate that we are done reading RAM contents read_RAM_busy = 0; IOWR_ALTERA_AVALON_PIO_DATA(READ_RAM_BUSY_PIO_BASE, read_RAM_busy); } // END while (SSSCommand != CMD_QUIT) } // END if (SSSCommand == 67) else { error_code = OSQPost(SSSLEDCommandQ, (void *)SSSCommand); alt_SSSErrorHandler(error_code, 0); } // END else if (SSSCommand == 67) } // END else if (SSSCommand == 65) } // END else if(SSSCommand == CMD_QUIT) } // END if(SSSCommand >= ' ' && SSSCommand <= '~') } // END while(bytes_to_process--) // ORIGINAL POSITION OF SEND COMMAND!!! return; } // END void sss_exec_command(SSSConn* conn) . . . p.s. change .zip extension to .rar
0 Kudos
3 Replies
Highlighted
Valued Contributor III
7 Views

And this is the Matlab code: 

%% PNET EXAMPLE clear; clc; % Server machine (FPGA) serverAddress = '192.168.1.234'; portNumber = 30; NSAMPLES = 1170; BUFFERSIZE = 9000; % Creates tcp/ip connection to the specified 'hostname' and port tcpConn = pnet('tcpconnect',serverAddress,portNumber ); pause(0.1); % specifies how long read and listen commands blocks before it timeouts. pnet(tcpConn,'setreadtimeout',0.25); pnet(tcpConn,'setwritetimeout',0.1); disp('Connection established') %% Read elements at the beginning of connection to flush buffer flush = pnet(tcpConn,'read',BUFFERSIZE,'uint8'); % Show flushed data disp(char(flush)) %% Write commands '0\n\r' to '6\n\r' % for iComm = 0:6, % pnet(tcpConn,'write',uint8()); % % Receive 35+2 characters from FPGA % textReceived = uint8(swapbytes(pnet(tcpConn,'read',,'uint8'))); % disp(char(textReceived')) % end %% Write command to send A-line 'A\n\r' tic nLinesPerFrame = 400; nFrames = 1; nAcqSamples = nLinesPerFrame*nFrames; rawData = zeros(,'int16'); for iFrames = 1:nFrames, for iLines = 1:nLinesPerFrame, pnet(tcpConn,'write',uint8()); % Reads an array of NSAMPLES elements from a connection rawData(:,iLines,iFrames) = pnet(tcpConn,'read',,'int16'); end end elapsedTime = toc; disp() fprintf('Estimated speed %.2f lines/sec\n',nAcqSamples/elapsedTime) % Reads an array of elements from a connection % reception = uint32(swapbytes(pnet(tcpConn,'read',,'uint32'))); %% Display previously acquired data figure ylim() for iFrames = 1:size(rawData,3), for iLines = 1:size(rawData,2), plot(squeeze(rawData(:,iLines,iFrames))) ylim() title(sprintf('Slow Transfer. Frame %d. Line %d',iFrames,iLines)) pause(0.01); end end %% Continuous acquisition 'C\n\r' % DOES NOT WORK WELL!!!! CORRUPTED DATA!!! nLinesPerFrame = 400; nFrames = 25; nAcqSamples = nLinesPerFrame*nFrames; rawDataCont = zeros(,'int16'); pnet(tcpConn,'write',uint8()); tic for iFrames = 1:nFrames, for iLines = 1:nLinesPerFrame, % Reads an array of NSAMPLES elements from a connection % dataReceived = pnet(tcpConn,'read',,'int16'); rawDataCont(:,iLines,iFrames) = pnet(tcpConn,'read',,'int16'); end end elapsedTime = toc; disp() fprintf('Estimated speed: %.2f lines/sec\n',nAcqSamples/elapsedTime) %% Display data acquired continuously figure ylim() for iFrames = 1:size(rawDataCont,3), for iLines = 1:nLinesPerFrame, plot(squeeze(rawDataCont(:,iLines,iFrames))) title(sprintf('Continuous Transfer. Frame %d. Line %d',iFrames,iLines)) end end %% Closes a tcpconnection (send first a 'Q\n\r') pnet(tcpConn,'write',); % Receive 35+2 characters from FPGA textReceived = uint8(swapbytes(pnet(tcpConn,'read',,'uint8'))); disp(char(textReceived')) % pause(0.1); pnet(tcpConn,'close') disp('Connection closed')
0 Kudos
Highlighted
Valued Contributor III
7 Views

You need to be able to read the 'write pointer' of the capture hardware. 

Then you can loop until there is enough data to fill a frame. 

Probably means a capture/memory buffer that is a few 'A-line' buffers long.
0 Kudos
Highlighted
Valued Contributor III
7 Views

Thanks for the advice dsl, I changed my transmission buffer to 2340 bytes (just enough for a single buffer of 1170 samples). Had to add a small delay after the send command to make it work (~17 Mbits/sec), but it seems that my PC is not keeping up to the speed :cry: 

case 67: printf("Continuous acquisition! \n"); ////////////////////////////////////////////////////////// // Continuous acquisition loop (ASCII code = 67) ////////////////////////////////////////////////////////// //for (iLines = 1; iLines <= nLines; iLines++) while(1) { ////////////////////////////////////////////////////////// // Send single A-line ////////////////////////////////////////////////////////// // Wait to finish writing acquired data to the RAM do { acq_busy_signal = IORD_ALTERA_AVALON_PIO_DATA(ACQ_BUSY_PIO_BASE); // look definitions in ..software\simple_socket_server\simple_socket_server_syslib\Debug\system_description\system.h } while (acq_busy_signal == 1); // Indicate that we are busy reading RAM contents read_RAM_busy = 1; IOWR_ALTERA_AVALON_PIO_DATA(READ_RAM_BUSY_PIO_BASE, read_RAM_busy); // Begin the transfer tx_wr_pos = tx_buf; for (RAM_address = 1; RAM_address <= NSAMPLES; RAM_address++) { // Read data port (from RAM) ADC_data = IORD_ALTERA_AVALON_PIO_DATA(ADC_DATA_PIO_BASE); // Write address port (to RAM) IOWR_ALTERA_AVALON_PIO_DATA(READ_RAM_ADDRESS_BASE, RAM_address + 1); dataPointer = (unsigned char*)&ADC_data; // Send 16-bit data (swapped upper and lower bytes) *tx_wr_pos++ = dataPointer; *tx_wr_pos++ = dataPointer; } // END for (RAM_address = 0; RAM_address <= NSAMPLES; RAM_address++) bytes_sent = send(conn->fd, tx_buf, tx_wr_pos - tx_buf, 0); //printf("L:%d BS: %d\n",iLines,bytes_sent); // Indicate that we are done reading RAM contents read_RAM_busy = 0; IOWR_ALTERA_AVALON_PIO_DATA(READ_RAM_BUSY_PIO_BASE, read_RAM_busy); ////////////////////////////////////////////////////////// // single A-line transfer done! ////////////////////////////////////////////////////////// // Wait a little... Should know why... for (RAM_address = 1; RAM_address <= NSAMPLES; RAM_address++); } // END of continuous acquisition loop break; Any ideas how to know if the packet was received in the PC?
0 Kudos