Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
14 years ago

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

3 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    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')
    
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    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.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    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?