Nios® V/II Embedded Design Suite (EDS)
Support for Embedded Development Tools, Processors (SoCs and Nios® V/II processor), Embedded Development Suites (EDSs), Boot and Configuration, Operating Systems, C and C++

DE4 simple socket server

Altera_Forum
Honored Contributor II
899 Views

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
Altera_Forum
Honored Contributor II
203 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
Altera_Forum
Honored Contributor II
203 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
Altera_Forum
Honored Contributor II
203 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
Reply