source: ResearchApps/PHY/WARPLAB/WARPLab7/M_Code_Reference/classes/wl_transport_eth_udp_mex_bcast.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: 11.5 KB
Line 
1%-------------------------------------------------------------------------
2% WARPLab Framework
3%
4% Copyright 2013, Mango Communications. All rights reserved.
5%           Distributed under the WARP license  (http://warpproject.org/license)
6%
7% Chris Hunter (chunter [at] mangocomm.com)
8% Patrick Murphy (murphpo [at] mangocomm.com)
9% Erik Welsh (welsh [at] mangocomm.com)
10%-------------------------------------------------------------------------
11
12classdef wl_transport_eth_udp_mex_bcast < wl_transport & handle_light
13% Mex physical layer Ethernet UDP Transport for broadcast 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 = protected, Hidden = true)
20        sock;
21        status;
22        isopen;
23        maxSamples;          %Maximum number of samples able to be transmitted (based on maxPayload)
24        maxPayload;          %Maximum payload size (e.g. MTU - ETH/IP/UDP headers)
25    end
26
27    properties (SetAccess = public)
28        hdr;
29        address;
30        port;       
31        rxBufferSize;
32    end
33
34    properties(Hidden = true, Constant = true)
35        REQUIRED_MEX_VERSION           = '1.0.4a';         % Must match version in MEX transport
36    end
37   
38%********************************* Methods ************************************
39
40    methods
41        function obj = wl_transport_eth_udp_mex_bcast()
42            obj.hdr = wl_transport_header;
43           
44            % At the moment, a trigger is the only type of broadcast packet.
45            % In a future release this type will be exposed to objects that
46            % create the broadcast transport object.
47            obj.hdr.pktType = obj.hdr.PKTTYPE_TRIGGER;
48            obj.checkSetup();
49            obj.status = 0;
50
51            configFile = which('wl_config.ini');
52           
53            if(isempty(configFile))
54                error('cannot find wl_config.ini. please run wl_setup.m'); 
55            end
56           
57            readKeys = {'network','','host_address',''};
58            IP = inifile(configFile,'read',readKeys);
59            IP = IP{1};
60            IP = sscanf(IP,'%d.%d.%d.%d');
61
62            readKeys = {'network','','host_ID',[]};
63            hostID = inifile(configFile,'read',readKeys);
64            hostID = hostID{1};
65            hostID = sscanf(hostID,'%d');
66           
67            readKeys = {'network','','bcast_port',[]};
68            bcastport = inifile(configFile,'read',readKeys);
69            bcastport = bcastport{1};
70            bcastport = sscanf(bcastport,'%d');
71           
72            obj.address    = sprintf('%d.%d.%d.%d',IP(1),IP(2),IP(3),255);
73            obj.port       = bcastport;
74            obj.hdr.srcID  = hostID;
75            obj.hdr.destID = 65535;    % Changed from 255 in WARPLab 7.1.0           
76            obj.maxPayload = 1000;     % Default value;  Can explicitly set a different maxPayload if
77                                       % you are certain that all nodes support a larger packet size.
78        end
79       
80        function checkSetup(obj)
81            % Check to make sure wl_mex_udp_transport exists and is is configured
82            temp = which('wl_mex_udp_transport');
83           
84            if(isempty(temp))
85                error('wl_transport_eth_udp_mex:constructor','WARPLab Mex UDP transport not found in Matlab''s path');
86            elseif(strcmp(temp((end-length(mexext)+1):end),mexext) == 0)
87                error('wl_transport_eth_udp_mex:constructor','WARPLab Mex UDP transport found, but it is not a compiled mex file');
88            end
89           
90            version     = wl_mex_udp_transport('version');
91            version     = sscanf(version, '%d.%d.%d%c');
92            version_req = sscanf(obj.REQUIRED_MEX_VERSION, '%d.%d.%d%c');
93
94            % Version must match required version   
95            if(~(version(1) == version_req(1) && version(2) == version_req(2) && version(3) == version_req(3) && version(4) >= version_req(4)))
96                version     = wl_mex_udp_transport('version');
97                version_req = obj.REQUIRED_MEX_VERSION;
98               
99                error('wl_transport_eth_udp_mex:constructor', 'MEX transport version mismatch.\nRequires version %s, found version %s', version_req, version);
100            end
101        end
102
103        function setMaxPayload(obj,value)
104            obj.maxPayload = value;
105       
106            % Compute the maximum number of samples in each Ethernet packet
107            %   - Start with maxPayload is the max number of bytes per packet (nominally the Ethernet MTU)
108            %   - Subtract sizes of the transport header, command header and samples header
109            %   - Due to DMA alignment issues in the node, the max samples must be 4 sample aligned.
110            obj.maxSamples = double(bitand(((floor(double(obj.maxPayload)/4) - sizeof(obj.hdr)/4 - sizeof(wl_cmd)/4) - (sizeof(wl_samples)/4)), 4294967292));
111        end
112       
113        function out = getMaxPayload(obj)
114            out = double(obj.maxPayload);
115        end
116
117        function open(obj,varargin)
118            % varargin{1}: (optional) IP address
119            % varargin{2}: (optional) port
120            %
121            if(isempty(obj.isopen))
122                if(nargin==3)
123                   if(ischar(varargin{1}))
124                      obj.address = varargin{1}; 
125                   else
126                      obj.address = obj.int2IP(varargin{1});
127                   end
128                   obj.port = varargin{2};
129                end
130               
131                REQUESTED_BUF_SIZE = 2^22;
132               
133                % Call to 'init_sockets' will internally call setReuseAddress and setBroadcast
134                obj.sock = wl_mex_udp_transport('init_socket');
135                wl_mex_udp_transport('set_so_timeout', obj.sock, 2000);
136                wl_mex_udp_transport('set_send_buf_size', obj.sock, REQUESTED_BUF_SIZE);
137                wl_mex_udp_transport('set_rcvd_buf_size', obj.sock, REQUESTED_BUF_SIZE);
138                x = wl_mex_udp_transport('get_rcvd_buf_size', obj.sock);
139 
140                obj.rxBufferSize = x;
141                if(x < REQUESTED_BUF_SIZE)
142                    fprintf('OS reduced recv buffer size to %d\n', x);
143                end
144
145                obj.status = 1;
146                obj.isopen = 1;   
147            end
148        end
149                           
150        function close(obj)
151            try
152                wl_mex_udp_transport('close', obj.sock);
153            catch closeError
154                warning( 'Error closing socket; mex error was %s', closeError.message)
155            end
156           
157            obj.status=0;
158        end   
159       
160        function delete(obj)
161            obj.close();
162        end
163       
164        function flush(obj)
165            % Currently not implemented
166        end
167    end % methods
168   
169
170    methods (Hidden = true)   
171        function send(obj,type,varargin)
172            % varargin{1}: data   
173
174            switch(lower(type))
175                case 'trigger'
176                    bitset(obj.hdr.flags,1,0); %no response
177                    obj.hdr.pktType = obj.hdr.PKTTYPE_TRIGGER;
178                case 'message'
179                    obj.hdr.pktType = obj.hdr.PKTTYPE_HTON_MSG;
180            end
181           
182            data = uint32(varargin{1});
183           
184            obj.hdr.msgLength = (length(data))*4;          % Length in bytes
185            obj.hdr.flags     = bitset(obj.hdr.flags,1,0);
186            obj.hdr.increment;
187           
188            data  = [obj.hdr.serialize,data];   
189            data8 = [zeros(1,2,'uint8') typecast(swapbytes(uint32(data)),'uint8')];
190           
191            size = wl_mex_udp_transport('send', obj.sock, data8, length(data8), obj.address, obj.port);
192           
193        end
194       
195        function dottedIPout = int2IP(obj,intIn)
196            addrChars(4) = mod(intIn, 2^8);
197            addrChars(3) = mod(bitshift(intIn, -8), 2^8);
198            addrChars(2) = mod(bitshift(intIn, -16), 2^8);
199            addrChars(1) = mod(bitshift(intIn, -24), 2^8);
200            dottedIPout = sprintf('%d.%d.%d.%d', addrChars);
201        end
202
203        function intOut = IP2int(obj,dottedIP)
204            addrChars = sscanf(dottedIP, '%d.%d.%d.%d')';
205            intOut = 2^0 * addrChars(4) + 2^8 * addrChars(3) + 2^16 * addrChars(2) + 2^24 * addrChars(1);
206        end
207       
208        %-----------------------------------------------------------------
209        % write_buffers
210        %     Command to utilize additional functionality in the wl_mex_udp_transport C code in order to
211        %     speed up processing of 'writeIQ' commands
212        %
213        function reply = write_buffers(obj, func, num_samples, samples_I, samples_Q, buffer_ids, start_sample, hw_ver, wl_command, check_chksum)
214            % func           : Function within read_buffers to call
215            % number_samples : Number of samples requested
216            % samples_I      : Array of uint16 I samples
217            % samples_Q      : Array of uint16 Q samples
218            % buffer_ids     : Array of Buffer IDs
219            % start_sample   : Start sample
220            % hw_ver         : Hardware version of the Node
221            % wl_command     : Ethernet WARPLab command
222            % check_chksum   : Perform the WriteIQ checksum check inside the function
223           
224            %Calculate how many transport packets are required
225            numPktsRequired = ceil(double(num_samples)/double(obj.maxSamples));
226
227            % Construct the WARPLab command that will be used used to write the samples
228            payload           = uint32( wl_command.serialize() );        % Convert command to uint32
229            obj.hdr.flags     = bitset(obj.hdr.flags,1,0);                % We do not need a response for the sent command
230            obj.hdr.msgLength = ( length( payload ) ) * 4;                % Length in bytes
231            data              = [obj.hdr.serialize, payload];
232            data8             = [zeros(1,2,'uint8') typecast(swapbytes(uint32(data)),'uint8')];
233            num_write_iq      = length(buffer_ids);
234            reply             = zeros(num_write_iq);
235           
236            func = lower(func);
237            switch(func)
238                case 'iq'
239                    % Calls the MEX read_iq command
240                    %
241                    % Needs to handle all the array dimensionality; MEX will only process one buffer ID at a atime
242                   
243                    for index = 1:(num_write_iq)                   
244                        [cmds_used, checksum] = wl_mex_udp_transport('write_iq', obj.sock, data8, obj.getMaxPayload(), obj.address, obj.port, num_samples, samples_I(:,index), samples_Q(:,index), buffer_ids(index), start_sample, numPktsRequired, obj.maxSamples, hw_ver, check_chksum);
245                       
246                        % increment the transport header by cmds_used (ie number of commands used
247                        obj.hdr.increment(cmds_used);
248                       
249                        % Record the checksum for that Write IQ
250                        reply(index) = checksum;
251                    end
252                   
253                otherwise
254                    error('unknown command ''%s''',cmdStr);
255                   
256            end
257           
258            reply = checksum;
259        end
260
261    end
262end % classdef
Note: See TracBrowser for help on using the repository browser.