source: ResearchApps/PHY/WARPLAB/WARPLab7/M_Code_Reference/classes/wl_transport_eth_udp_mex.m

Last change on this file was 4818, checked in by welsh, 8 years ago

Added version checking for MEX transport; Added error checking to help with version errors.

File size: 30.3 KB
RevLine 
[4332]1%-------------------------------------------------------------------------
2% WARPLab Framework
[2084]3%
[4332]4% Copyright 2013, Mango Communications. All rights reserved.
5%           Distributed under the WARP license  (http://warpproject.org/license)
[2084]6%
[4332]7% Chris Hunter (chunter [at] mangocomm.com)
8% Patrick Murphy (murphpo [at] mangocomm.com)
9% Erik Welsh (welsh [at] mangocomm.com)
10%-------------------------------------------------------------------------
[2149]11
[2084]12classdef wl_transport_eth_udp_mex < wl_transport & handle_light
13% Mex physical layer Ethernet UDP Transport for unicast traffic
14% User code should not use this object directly-- the parent wl_node will
15% instantiate the appropriate transport object for the hardware in use
16
17%******************************** Properties **********************************
18
19    properties (SetAccess = public)
[4416]20        timeout;             % Maximum time spent waiting before retransmission
[2084]21    end
[2149]22
[2084]23    properties (SetAccess = protected, Hidden = true)
[4416]24        sock;                % UDP socket
25        status;              % Status of UDP socket
26        maxSamples;          % Maximum number of samples able to be transmitted (based on maxPayload)
27        maxPayload;          % Maximum payload size (e.g. MTU - ETH/IP/UDP headers)
[2084]28    end
[2149]29
[4416]30    properties (SetAccess = protected)
31        address;             % IP address of destination
32        port;                % Port of destination
33    end
34   
[2084]35    properties (SetAccess = public)
[4416]36        hdr;                 % Transport header object
37        rxBufferSize;        % OS's receive buffer size in bytes
[2084]38    end
[2149]39
[4332]40    properties(Hidden = true, Constant = true)
41        % These constants define specific command IDs used by this object.
42        % Their C counterparts are found in wl_transport.h
43        GRP                            = 'transport';
44        CMD_PING                       = 1;                % 0x000001
[4784]45        CMD_PAYLOADSIZETEST            = 2;                % 0x000002
46       
47        CMD_NODEGRPID_ADD              = 16;               % 0x000010
48        CMD_NODEGRPID_CLEAR            = 17;               % 0x000011
49       
50        TRANSPORT_NOT_READY_MAX_RETRY  = 50;
51        TRANSPORT_NOT_READY_WAIT_TIME  = 0.1;
[4818]52       
53        REQUIRED_MEX_VERSION           = '1.0.4a';         % Must match version in MEX transport
[2084]54    end
55
[4784]56
[2084]57%********************************* Methods ************************************
[2149]58
[2084]59    methods
60
61        function obj = wl_transport_eth_udp_mex()
[4332]62            obj.hdr         = wl_transport_header;
[2084]63            obj.hdr.pktType = obj.hdr.PKTTYPE_HTON_MSG;
[4332]64            obj.status      = 0;
65            obj.timeout     = 1;
[4416]66            obj.maxPayload  = 1000;    % Sane default. This gets overwritten by CMD_PAYLOADSIZETEST command.
67            obj.port        = 0;
68            obj.address     = '10.0.0.0';
[4332]69           
[2084]70            obj.checkSetup();
71        end
72       
73        function checkSetup(obj)
[4332]74            % Check to make sure wl_mex_udp_transport exists and is is configured
75            %
[2149]76            temp = which('wl_mex_udp_transport');
[4332]77           
[4818]78            if(isempty(temp))
79                error('wl_transport_eth_udp_mex:constructor', 'WARPLab Mex UDP transport not found in Matlab''s path');
80            elseif(strcmp(temp((end-length(mexext)+1):end ), mexext) == 0)
81                error('wl_transport_eth_udp_mex:constructor', 'WARPLab Mex UDP transport found, but it is not a compiled mex file');
82            end
83           
84            version     = wl_mex_udp_transport('version');
85            version     = sscanf(version, '%d.%d.%d%c');
86            version_req = sscanf(obj.REQUIRED_MEX_VERSION, '%d.%d.%d%c');
87
88            % Version must match required version   
89            if(~(version(1) == version_req(1) && version(2) == version_req(2) && version(3) == version_req(3) && version(4) >= version_req(4)))
90                version     = wl_mex_udp_transport('version');
91                version_req = obj.REQUIRED_MEX_VERSION;
92               
93                error('wl_transport_eth_udp_mex:constructor', 'MEX transport version mismatch.\nRequires version %s, found version %s', version_req, version);
94            end
[2084]95        end
96       
[4818]97        function setMaxPayload(obj, value)
[2149]98       
[4818]99            if (isempty(value))
100               error('wl_transport_eth_udp_mex:setMaxPayload', 'setMaxPayload requires a non-empty argument.');
101            else
102                obj.maxPayload = value;
[4332]103           
[4818]104                % Compute the maximum number of samples in each Ethernet packet
105                %   - Start with maxPayload is the max number of bytes per packet (nominally the Ethernet MTU)
106                %   - Subtract sizes of the transport header, command header and samples header
107                %   - Due to DMA alignment issues in the node, the max samples must be 4 sample aligned.
108                obj.maxSamples = double(bitand(((floor(double(obj.maxPayload)/4) - sizeof(obj.hdr)/4 - sizeof(wl_cmd)/4) - (sizeof(wl_samples)/4)), 4294967292));
109               
110                % fprintf('Max samples: %d\n', obj.maxSamples);
111            end
[2149]112        end
113       
114        function out = getMaxPayload(obj)
[2856]115            out = double(obj.maxPayload);
[2149]116        end
117
[4416]118        function setAddress(obj, value)
119            if(ischar(value))
120                obj.address = value;
121            else
122                obj.address = obj.int2IP(value);
123            end
124        end
125       
126        function out = getAddress(obj)
127            out = obj.address;
128        end
129       
130        function setPort(obj, value)
131            obj.port = value;
132        end
133       
134        function out = getPort(obj)
135            out = obj.port;
136        end
137
[2084]138        function open(obj,varargin)
[4332]139            % varargin{1}: (optional) IP address
140            % varargin{2}: (optional) port
141            %
[2084]142            if(nargin==3)
[4416]143               obj.setAddress(varargin{1});
[2084]144               obj.port = varargin{2};
145            end
146
147            REQUESTED_BUF_SIZE = 2^22;
[2124]148             
[4818]149            % Call to 'init_sockets' will internally call setReuseAddress and setBroadcast
[2149]150            obj.sock = wl_mex_udp_transport('init_socket');
151            wl_mex_udp_transport('set_so_timeout', obj.sock, 1);
152            wl_mex_udp_transport('set_send_buf_size', obj.sock, REQUESTED_BUF_SIZE);
153            wl_mex_udp_transport('set_rcvd_buf_size', obj.sock, REQUESTED_BUF_SIZE);
[2084]154
[2149]155            x = wl_mex_udp_transport('get_rcvd_buf_size', obj.sock);           
[2084]156            obj.rxBufferSize = x;
157
158            if(x < REQUESTED_BUF_SIZE)
159                fprintf('OS reduced recv buffer size to %d\n', x);
160            end
161           
162            obj.status = 1;
163        end
164       
165        function out = procCmd(obj,nodeInd,node,cmdStr,varargin)
[4332]166            % wl_node procCmd(obj, nodeInd, node, varargin)
167            %     obj:       Node object (when called using dot notation)
168            %     nodeInd:   Index of the current node, when wl_node is iterating over nodes
169            %     node:      Current node object
170            %     cmdStr:    Command string of the interface command
171            %     varargin:
172            %         [1:N}  Command arguments
173            %
174            out    = [];
175           
[2084]176            cmdStr = lower(cmdStr);
177            switch(cmdStr)
[4332]178           
179                %---------------------------------------------------------
[2084]180                case 'ping'
181                    % Test to make sure node can be accessed via this
182                    % transport
183                    %
184                    % Arguments: none
185                    % Returns: true if board responds; raises error otherwise
[4332]186                    %
[2084]187                    myCmd = wl_cmd(node.calcCmd(obj.GRP,obj.CMD_PING));
188                    node.sendCmd(myCmd);
[4332]189                    out = true;                            % sendCmd will timeout and raise error if board doesn't respond
[2084]190                   
[4332]191                %---------------------------------------------------------
[2084]192                case 'payload_size_test'
[4332]193                    % Determine objects maxPayload parameter
[2084]194                    %
195                    % Arguments: none
196                    % Returns: none
[4332]197                    %
[2084]198                    configFile = which('wl_config.ini');
[4332]199                   
[2084]200                    if(isempty(configFile))
[2865]201                       error('cannot find wl_config.ini. please run wl_setup.m'); 
[2084]202                    end
[4332]203                   
[4375]204                    readKeys = {'network', '', 'max_transport_payload_size', ''};
205                    max_transport_payload_size = inifile(configFile, 'read', readKeys);
206                    max_transport_payload_size = str2num(max_transport_payload_size{1});
[2084]207                   
[4375]208                    % Determine the payloads to test
209                    payloadTestSizes = [];
210
211                    for i = [1000 1470 5000 8966]
212                        if (i < max_transport_payload_size) 
213                            payloadTestSizes = [payloadTestSizes, i];
214                        end
[2084]215                    end
216                   
[4375]217                    payloadTestSizes = [payloadTestSizes, max_transport_payload_size];
218                                       
[4386]219                    % WARPLab Header is (see http://warpproject.org/trac/wiki/WARPLab/Reference/Architecture/WireFormat ):
220                    %   - 2 byte pad
221                    %   - Transport header
222                    %   - Command header
223                    payloadTestSizes = floor((payloadTestSizes - (sizeof(node.transport.hdr) + sizeof(wl_cmd) + 2)) / 4);
[4332]224                   
[2084]225                    for index = 1:length(payloadTestSizes)
226                        myCmd = wl_cmd(node.calcCmd(obj.GRP,obj.CMD_PAYLOADSIZETEST));
227                        myCmd.addArgs(1:payloadTestSizes(index));
228                        try                       
229                            resp = node.sendCmd(myCmd);
[4818]230                            obj.setMaxPayload(resp.getArgs);
[4375]231                            if(obj.getMaxPayload() < (payloadTestSizes(index) * 4))
[2084]232                               break; 
233                            end
234                        catch ME
235                            break 
236                        end
237                    end
238                   
[4332]239                %---------------------------------------------------------
[2084]240                case 'add_node_group_id'
241                    % Adds a Node Group ID to the node so that it can
242                    % process broadcast commands that are received from
243                    % that node group.
244                    %
245                    % Arguments: (uint32 NODE_GRP_ID)
246                    % Returns: none
247                    %
248                    % NODE_GRP_ID: ID provided by wl_node_grp
[4332]249                    %
250                    myCmd = wl_cmd(node.calcCmd(obj.GRP, obj.CMD_NODEGRPID_ADD));
251                    myCmd.addArgs(varargin{1});
[2084]252                    node.sendCmd(myCmd);
253                   
[4332]254                %---------------------------------------------------------
[2084]255                case 'clear_node_group_id'
256                    % Clears a Node Group ID from the node so it can ignore
257                    % broadcast commands that are received from that node
258                    % group.
259                    %
260                    % Arguments: (uint32 NODE_GRP_ID)
261                    % Returns: none
262                    %
263                    % NODE_GRP_ID: ID provided by wl_node_grp
[4332]264                    %
265                    myCmd = wl_cmd(node.calcCmd(obj.GRP, obj.CMD_NODEGRPID_CLEAR));
266                    myCmd.addArgs(varargin{1});
[2084]267                    node.sendCmd(myCmd);
268                   
[4332]269                %---------------------------------------------------------
[2084]270                otherwise
[2865]271                    error('unknown command ''%s''',cmdStr);
[2084]272            end
273           
[4332]274            if((iscell(out) == 0) && (numel(out) ~= 1))
[2084]275                out = {out}; 
276            end     
277        end
278       
[2124]279        function close(obj)           
[2084]280            if(~isempty(obj.sock))
281                try
[2149]282                    wl_mex_udp_transport('close', obj.sock);
[2084]283                catch closeError
[2865]284                    warning( 'Error closing socket; mex error was %s', closeError.message)
[2084]285                end
286            end
287            obj.status=0;
288        end
289       
290        function delete(obj)
291            obj.close();
292        end
293       
294        function flush(obj)
[4332]295            % Currently not implemented
[2084]296        end
[4332]297    end % methods
[2084]298
299   
300    methods (Hidden = true)
301
[4309]302        function reply = send(obj, send_data, response, varargin)
303            % send_data  : Data to be sent to the node
304            % response   : Does the transmission require a response from the node
305            % varargin{1}: (optional)
306            %     - increment the transport header; defaults to true if not specified
307            %
[2084]308
[4309]309            % Initialize variables
310            maxAttempts       = 2;                                   % Maximum times the transport will re-try a packet
311            payload           = uint32(send_data);                   % Change data to 32 bit unsigned integers for transmit
312            obj.hdr.msgLength = ((length(payload)) * 4);             % Length in bytes (4 bytes / sample)
313            reply             = [];                                  % Initialize array for response from the node
314            robust            = response;
315
316            % Process command line arguments
317            increment_hdr     = true;
318
319            if (nargin == 4)
320               increment_hdr  = varargin{1};
[2084]321            end
322           
[4309]323            % Set the appropriate flags in the header           
[2084]324            if(robust)
[4309]325               obj.hdr.flags = bitset(obj.hdr.flags, 1, 1);
[2084]326            else
[4309]327               obj.hdr.flags = bitset(obj.hdr.flags, 1, 0);
[2084]328            end
329
[4309]330            % Increment the header and serialize all the data into a uint32 array
331            if (increment_hdr)
332                obj.hdr.increment;
333            end
334                       
335            % Format the data / address arguments for transmission
336            data     = [obj.hdr.serialize, payload];                                      % Get a unified array with the header and data
337            data8    = [zeros(1,2,'uint8') typecast(swapbytes(uint32(data)), 'uint8')];   % Change to uint8 and pad by 2 bytes so payload is 32 bit aligned w/ Eth header
338
339            % Send the packet
[2149]340            size = wl_mex_udp_transport('send', obj.sock, data8, length(data8), obj.address, obj.port);
[2084]341
[4309]342            % Wait to receive reply from the board               
343            if(robust == 1)
344                MAX_PKT_LEN      = obj.getMaxPayload() + 100;
345                hdr_length       = obj.hdr.length;
346                currTx           = 1;
347                numWaitRetries   = 0;
[2084]348                receivedResponse = 0;
[4309]349                currTime         = tic;
[2084]350
351                while (receivedResponse == 0)
352                    try
[2149]353                        [recv_len, recv_data8] = wl_mex_udp_transport('receive', obj.sock, MAX_PKT_LEN);
[2084]354
355                    catch receiveError
[4818]356                        error('%s.m -- Failed to receive UDP packet.\nMEX transport error message follows:\n    %s\n', mfilename, receiveError.message);
[2084]357                    end
358                   
[4309]359                    % If we have a packet, then process the contents
[2084]360                    if(recv_len > 0)
[4818]361                        reply8     = [recv_data8(3:recv_len) zeros(mod(-(recv_len - 2), 4), 1, 'uint8')];
[2084]362                        reply      = swapbytes(typecast(reply8, 'uint32'));
[4309]363
364                        % Check the header to see if this was a valid reply                       
365                        if(obj.hdr.isReply(reply(1:hdr_length)))
[2084]366                       
[4309]367                            % Check the header to see if we need to wait for the node to be ready
[4818]368                            if (obj.hdr.isNodeReady(reply(1:hdr_length)))
[4309]369                           
370                                % Strip off transport header to give response to caller
371                                reply  = reply((hdr_length + 1):end);
372                               
373                                if(isempty(reply))
374                                    reply = []; 
375                                end
376                               
377                                receivedResponse = 1;
378                               
379                            else
380                                % Node is not ready; Wait and try again
[4818]381                                pause(obj.TRANSPORT_NOT_READY_WAIT_TIME);
[4309]382                                numWaitRetries = numWaitRetries + 1;
383
384                                % Send packet packet again
385                                obj.sock.send(pkt_send);
386
387                                % Check that we have not spent a "long time" waiting for samples to be ready               
[4818]388                                if (numWaitRetries > obj.TRANSPORT_NOT_READY_MAX_RETRY)
[4418]389                                    error('wl_transport_eth_mex:send:isReady', 'Error:  Timeout waiting for node to be ready.  Please check the node operation.');
[4309]390                                end
391                               
392                                reply = [];
[2084]393                            end
[4309]394                        end
[2084]395                    end
396                   
[4309]397                    % Look for timeout
398                    if ((toc(currTime) > obj.timeout) && (receivedResponse == 0))
[2084]399                        if(currTx == maxAttempts)
[4818]400                            error('wl_transport_eth_mex:send:noReply', 'maximum number of retransmissions met without reply from node'); 
[2084]401                        end
[4309]402                       
403                        % Retry the packet
[2149]404                        size = wl_mex_udp_transport('send', obj.sock, data8, length(data8), obj.address, obj.port);
[4309]405                        currTx   = currTx + 1;
[2084]406                        currTime = tic;
[4309]407                    end
[2084]408                end
409            end
410        end
411       
412        function resp = receive(obj)
[4309]413            % Receive all packets from the Ethernet interface and pass array
414            %     of valid responses to the caller.
415            %
416            % NOTE:  This function will strip off the transport header from the responses
417            % NOTE:  This function is non-blocking and will return an empty response if
418            %            there are no packets available.
419            %
420
421            % Initialize variables
[2149]422            MAX_PKT_LEN = obj.getMaxPayload() + 100;           
[4309]423            hdr_length  = obj.hdr.length;
[2124]424            done        = false;
425            resp        = [];
[2084]426           
427            while ~done
428                try
[2149]429                    [recv_len, recv_data8] = wl_mex_udp_transport('receive', obj.sock, MAX_PKT_LEN);
[2084]430
431                catch receiveError
[4818]432                    error('%s.m -- Failed to receive UDP packet.\nMEX transport error message follows:\n    %s\n', mfilename, receiveError.message);
[2084]433                end
434               
435                if(recv_len > 0)
[4818]436                    reply8 = [recv_data8(3:recv_len) zeros(mod(-(recv_len - 2), 4), 1, 'uint8')].';
[2124]437                    reply  = swapbytes(typecast(reply8, 'uint32'));
[2084]438
[4309]439                    if(obj.hdr.isReply(reply(1:hdr_length)))
440                        % Strip off transport header to give response to caller
441                        reply  = reply((hdr_length + 1):end);
442                       
[2084]443                        if(isempty(reply))
444                            reply = [];
445                        end
[4309]446                       
447                        resp = [resp, reply];                       
448
449                        done = true;
[2084]450                    end
451                else
452                    done = true;
453                end
454            end
455        end
456       
457        function dottedIPout = int2IP(obj,intIn)
458            addrChars(4) = mod(intIn, 2^8);
459            addrChars(3) = mod(bitshift(intIn, -8), 2^8);
460            addrChars(2) = mod(bitshift(intIn, -16), 2^8);
461            addrChars(1) = mod(bitshift(intIn, -24), 2^8);
462            dottedIPout = sprintf('%d.%d.%d.%d', addrChars);
463        end
464       
465        function intOut = IP2int(obj,dottedIP)
466            addrChars = sscanf(dottedIP, '%d.%d.%d.%d')';
467            intOut = 2^0 * addrChars(4) + 2^8 * addrChars(3) + 2^16 * addrChars(2) + 2^24 * addrChars(1);
468        end
[2124]469       
470        function reply = print_cmd(obj, type, num_samples, start_sample, buffer_ids, command)
471            fprintf('Command:  %s \n', type);
472            fprintf('    # samples  = %d    start sample = %d \n', num_samples, start_sample);
473            fprintf('    buffer IDs = ');
474            for index = 1:length(buffer_ids)
475                fprintf('%d    ', buffer_ids(index));
476            end
477            fprintf('\n    Command (%d bytes): ', length(command) );
478            for index = 1:length(command)
479                switch(index)
480                    case 1
481                        fprintf('\n        Padding  : ');
482                    case 3
483                        fprintf('\n        Dest ID  : ');
484                    case 5
485                        fprintf('\n        Src ID   : ');
486                    case 7
487                        fprintf('\n        Rsvd     : ');
488                    case 8
489                        fprintf('\n        Pkt Type : ');
490                    case 9
491                        fprintf('\n        Length   : ');
492                    case 11
493                        fprintf('\n        Seq Num  : ');
494                    case 13
495                        fprintf('\n        Flags    : ');
496                    case 15
497                        fprintf('\n        Command  : ');
498                    case 19
499                        fprintf('\n        Length   : ');
500                    case 21
501                        fprintf('\n        # Args   : ');
502                    case 23
503                        fprintf('\n        Args     : ');
504                    otherwise
505                        if ( index > 23 ) 
506                            if ( ( mod( index + 1, 4 ) == 0 ) && not( index == length(command) ) )
507                                fprintf('\n                   ');
508                            end
509                        end
510                end
511               fprintf('%2x ', command(index) );
512            end
513            fprintf('\n\n');
514           
515            reply = 0;
516        end
517
518        %-----------------------------------------------------------------
519        % read_buffers
[2149]520        %     Command to utilize additional functionality in the wl_mex_udp_transport C code in order to
[2124]521        %     speed up processing of 'readIQ' and 'readRSSI' commands
522        %
523        % Supports the following calling conventions:
524        %    - start_sample -> must be a single value
525        %    - num_samples  -> must be a single value
526        %    - buffer_ids   -> Can be a vector of single RF interfaces
527        %
[4815]528        function reply = read_buffers(obj, func, num_samples, buffer_ids, start_sample, seq_num_tracker, seq_num_match_severity, node_id_str, wl_command, input_type)
529            % func                     : Function within read_buffers to call
530            % number_samples           : Number of samples requested
531            % buffer_ids               : Array of Buffer IDs
532            % start_sample             : Start sample
533            % seq_num_tracker          : Sequence number tracker
534            % seq_num_match_severity   : Severity of message when sequence numbers match on reads
535            % node_id_str              : String representation of Node ID
536            % wl_command               : Ethernet WARPLab command
537            % input_type               : Type of sample array:
538            %                                0 ==> 'double'
539            %                                1 ==> 'single'
540            %                                2 ==> 'int16'
541            %                                3 ==> 'raw'
[2124]542
543            % Get the lowercase version of the function           
544            func = lower(func);
545
546            % Calculate how many transport packets are required
547            numPktsRequired = ceil(double(num_samples)/double(obj.maxSamples));
[4311]548
549            % Arguments for the command will be set in the MEX function since it is faster
550            %     wl_command.setArgs(buffer_id, start_sample, num_samples, obj.maxSamples * 4, numPktsRequired);
[2124]551           
[4311]552            % Construct the minimal WARPLab command that will be used used to get the samples
553            %   NOTE:  Since we did not add the arguments of the command thru setArgs, we need to pad the structure so that
554            %          the proper amount of memory is allocated to be available to the MEX
555            payload           = uint32( wl_command.serialize() );        % Convert command to uint32
556            cmd_args_pad      = uint32( zeros(1, 5) );                   % Padding for command args
557            obj.hdr.flags     = bitset(obj.hdr.flags,1,0);               % We do not need a response for the sent command
558            obj.hdr.msgLength = ( ( length( payload ) ) + 5) * 4;        % Length in bytes
559
560            data  = [obj.hdr.serialize, payload, cmd_args_pad];
[4393]561            data8 = [zeros(1,2,'uint8') typecast(swapbytes(uint32(data)), 'uint8')];
[4311]562
[4393]563            % Pass all of the command arguments down to MEX
564            switch(func)
565                case 'iq'
566                    % Calls the MEX read_iq command
567                    %
568                    % obj.print_cmd('READ_IQ', num_samples, start_sample, buffer_ids, data8);
[4311]569                   
[4815]570                    [num_rcvd_samples, cmds_used, rx_samples]  = wl_mex_udp_transport('read_iq', obj.sock, data8, length(data8), obj.address, obj.port, num_samples, buffer_ids, start_sample, obj.maxSamples * 4, numPktsRequired, input_type, seq_num_tracker, seq_num_match_severity, node_id_str);
[4311]571                   
[4393]572                    % Code to test higher level matlab code without invoking the MEX transport
573                    %
574                    % rx_samples = zeros( num_samples, 1 );
575                    % cmds_used  = 0;
[4311]576
[4393]577                case 'rssi'
578                    % Calls the MEX read_rssi command
579                    %                       
580                    % obj.print_cmd('READ_RSSI', num_samples, start_sample, buffer_ids, data8);
[4311]581
[4815]582                    [num_rcvd_samples, cmds_used, rx_samples]  = wl_mex_udp_transport('read_rssi', obj.sock, data8, length(data8), obj.address, obj.port, num_samples, buffer_ids, start_sample, obj.maxSamples * 4, numPktsRequired, input_type, seq_num_tracker, seq_num_match_severity, node_id_str);
[4311]583
[4393]584                    % Code to test higher level matlab code without invoking the MEX transport
585                    %
586                    % rx_samples = zeros( num_samples * 2, 1 );
587                    % cmds_used  = 0;
[4311]588
[4393]589                otherwise
[4815]590                    error('unknown command ''%s''', cmdStr);
[2124]591            end
592           
[4393]593            obj.hdr.increment(cmds_used);
594           
[2124]595            reply = rx_samples;
596        end
597 
598 
599        %-----------------------------------------------------------------
600        % write_buffers
[2149]601        %     Command to utilize additional functionality in the wl_mex_udp_transport C code in order to
[2124]602        %     speed up processing of 'writeIQ' commands
603        %
[4393]604        function reply = write_buffers(obj, func, num_samples, samples, buffer_ids, start_sample, hw_ver, wl_command, check_chksum, input_type)
[2124]605            % func           : Function within read_buffers to call
606            % number_samples : Number of samples requested
[4393]607            % samples        : Array of IQ samples
[2124]608            % buffer_ids     : Array of Buffer IDs
609            % start_sample   : Start sample
[2166]610            % hw_ver         : Hardware version of the Node
[2124]611            % wl_command     : Ethernet WARPLab command
[2919]612            % check_chksum   : Perform the WriteIQ checksum check inside the function
[4393]613            % input_type     : Type of sample array:
614            %                      0 ==> 'double'
615            %                      1 ==> 'single'
616            %                      2 ==> 'int16'
617            %                      3 ==> 'raw'
[2124]618           
[4393]619            % Calculate how many transport packets are required
620            num_pkts_required = ceil(double(num_samples)/double(obj.maxSamples));
[2124]621
622            % Construct the WARPLab command that will be used used to write the samples
623            payload           = uint32( wl_command.serialize() );        % Convert command to uint32
[4309]624            obj.hdr.flags     = bitset(obj.hdr.flags,1,0);               % We do not need a response for the sent command
625            obj.hdr.msgLength = ( length( payload ) ) * 4;               % Length in bytes
[4393]626           
[2124]627            data              = [obj.hdr.serialize, payload];
[4393]628            data8             = [zeros(1,2,'uint8') typecast(swapbytes(uint32(data)), 'uint8')];
[2124]629           
[4393]630            socket            = obj.sock;
631            address           = obj.address;
632            port              = obj.port;
633            max_payload       = obj.getMaxPayload();
634            max_samples       = obj.maxSamples;
635           
636
[2124]637            func = lower(func);
638            switch(func)
639                case 'iq'
640                    % Calls the MEX read_iq command
641                    %
[4393]642                    [cmds_used, checksum] = wl_mex_udp_transport('write_iq', socket, data8, max_payload, address, port, num_samples, samples, buffer_ids, start_sample, num_pkts_required, max_samples, hw_ver, check_chksum, input_type);
[2124]643                   
[4393]644                    % Increment the transport header by cmds_used (ie number of commands used
645                    obj.hdr.increment(cmds_used);
646                   
647                    % Record the checksum for that Write IQ
648                    reply = checksum;
649                   
[2124]650                otherwise
[2865]651                    error('unknown command ''%s''',cmdStr);
[2124]652            end
653           
[2919]654            reply = checksum;
[2124]655        end
[2084]656    end
[4332]657end % classdef
[2124]658
659
660
661
Note: See TracBrowser for help on using the repository browser.