diff --git a/+adi/+AD9361/Base.m b/+adi/+AD9361/Base.m index c50b46a..5876a74 100644 --- a/+adi/+AD9361/Base.m +++ b/+adi/+AD9361/Base.m @@ -15,6 +15,19 @@ channelCount = 2; end + properties (Nontunable, Logical) + %EnableCustomFilter Enable Custom Filter + % Enable use of custom filter file to set SamplingRate, + % RFBandwidth, and FIR in datapaths + EnableCustomFilter = false; + end + + properties (Nontunable) + %CustomFilterFileName Custom Filter File Name + % Path to custom filter file created from filter wizard + CustomFilterFileName = ''; + end + properties (Abstract) %CenterFrequency Center Frequency % RF center frequency, specified in Hz as a scalar. The @@ -69,7 +82,23 @@ function delete(obj) end obj.channelCount = value; end - + % Check EnableCustomFilter + function set.EnableCustomFilter(obj, value) + validateattributes( value, { 'logical' }, ... + { }, ... + '', 'EnableCustomFilter'); + obj.EnableCustomFilter = value; + end + % Check CustomFilterFileName + function set.CustomFilterFileName(obj, value) + validateattributes( value, { 'char' }, ... + { }, ... + '', 'CustomFilterFileName'); + obj.CustomFilterFileName = value; + if obj.EnableCustomFilter && obj.ConnectedToDevice %#ok + writeFilterFile(obj); + end + end end %% API Functions @@ -101,6 +130,16 @@ function teardownLibad9361(~) end end + function writeFilterFile(obj) + fir_data_file = obj.CustomFilterFileName; + fir_data_str = fileread(fir_data_file); + obj.setAttributeRAW('voltage0','filter_fir_en','0',false); + obj.setAttributeRAW('voltage0','filter_fir_en','0',true); + obj.setDeviceAttributeRAW('filter_fir_config',fir_data_str); + obj.setAttributeRAW('voltage0','filter_fir_en','1',true); + obj.setAttributeRAW('voltage0','filter_fir_en','1',false); + end + end %% External Dependency Methods diff --git a/+adi/+AD9361/Rx.m b/+adi/+AD9361/Rx.m index 0a47bd0..a101310 100644 --- a/+adi/+AD9361/Rx.m +++ b/+adi/+AD9361/Rx.m @@ -189,7 +189,7 @@ '', 'RFBandwidth'); end obj.RFBandwidth = value; - if obj.ConnectedToDevice + if obj.ConnectedToDevice && ~obj.EnableCustomFilter id = 'voltage0'; obj.setAttributeLongLong(id,'rf_bandwidth',value,strcmp(obj.Type,'Tx'),30); end @@ -207,7 +207,7 @@ end obj.SamplingRate = value; - if obj.ConnectedToDevice + if obj.ConnectedToDevice && ~obj.EnableCustomFilter if libisloaded('libad9361') calllib('libad9361','ad9361_set_bb_rate',obj.iioDevPHY,int32(value)); else @@ -294,27 +294,36 @@ function setupInit(obj) % Do writes directly to hardware without using set methods. % This is required sine Simulink support doesn't support % modification to nontunable variables at SetupImpl + + % Gains obj.setAttributeRAW('voltage0','gain_control_mode',obj.GainControlModeChannel0,false); if obj.channelCount>2 obj.setAttributeRAW('voltage1','gain_control_mode',obj.GainControlModeChannel1,false); end + if strcmp(obj.GainControlModeChannel0,'manual') + obj.setAttributeLongLong('voltage0','hardwaregain',obj.GainChannel0,false); + end + if strcmp(obj.GainControlModeChannel1,'manual') && (obj.channelCount>2) + obj.setAttributeLongLong('voltage1','hardwaregain',obj.GainChannel1,false); + end + % Trackings obj.setAttributeBool('voltage0','quadrature_tracking_en',obj.EnableQuadratureTracking,false); obj.setAttributeBool('voltage0','rf_dc_offset_tracking_en',obj.EnableRFDCTracking,false); obj.setAttributeBool('voltage0','bb_dc_offset_tracking_en',obj.EnableBasebandDCTracking,false); id = sprintf('altvoltage%d',strcmp(obj.Type,'Tx')); obj.setAttributeLongLong(id,'frequency',obj.CenterFrequency ,true,4); - if libisloaded('libad9361') - calllib('libad9361','ad9361_set_bb_rate',obj.iioDevPHY,int32(obj.SamplingRate)); + % Sample rates and RF bandwidth + if ~obj.EnableCustomFilter + if libisloaded('libad9361') + calllib('libad9361','ad9361_set_bb_rate',obj.iioDevPHY,int32(obj.SamplingRate)); + else + obj.setAttributeLongLong('voltage0','sampling_frequency',obj.SamplingRate,true,4); + obj.setAttributeLongLong('voltage0','rf_bandwidth',obj.RFBandwidth ,strcmp(obj.Type,'Tx')); + end else - obj.setAttributeLongLong('voltage0','sampling_frequency',obj.SamplingRate,true,4); - obj.setAttributeLongLong('voltage0','rf_bandwidth',obj.RFBandwidth ,strcmp(obj.Type,'Tx')); - end - if strcmp(obj.GainControlModeChannel0,'manual') - obj.setAttributeLongLong('voltage0','hardwaregain',obj.GainChannel0,false); - end - if strcmp(obj.GainControlModeChannel1,'manual') && (obj.channelCount>2) - obj.setAttributeLongLong('voltage1','hardwaregain',obj.GainChannel1,false); + writeFilterFile(obj); end + end end diff --git a/+adi/+AD9361/Tx.m b/+adi/+AD9361/Tx.m index e0e6dca..ff292a4 100644 --- a/+adi/+AD9361/Tx.m +++ b/+adi/+AD9361/Tx.m @@ -109,7 +109,7 @@ end obj.RFBandwidth = value; - if obj.ConnectedToDevice + if obj.ConnectedToDevice && ~obj.EnableCustomFilter id = 'voltage0'; obj.setAttributeLongLong(id,'rf_bandwidth',value,strcmp(obj.Type,'Tx'),30); end @@ -127,7 +127,7 @@ end obj.SamplingRate = value; - if obj.ConnectedToDevice + if obj.ConnectedToDevice && ~obj.EnableCustomFilter if libisloaded('libad9361') calllib('libad9361','ad9361_set_bb_rate',obj.iioDevPHY,int32(value)); else diff --git a/+adi/+common/Attribute.m b/+adi/+common/Attribute.m index d5854d5..608014a 100644 --- a/+adi/+common/Attribute.m +++ b/+adi/+common/Attribute.m @@ -50,5 +50,14 @@ function setAttributeRAW(obj,id,attr,value,isOutput) end end + function setDeviceAttributeRAW(obj,attr,value) + phydev = getDev(obj, obj.phyDevName); + bytes = iio_device_attr_write(obj,phydev,attr,value); + if bytes <= 0 + status = -1; + cstatus(obj,status,['Attribute write failed for : ' attr ' with value ' value]); + end + end + end end diff --git a/+adi/+common/RxTx.m b/+adi/+common/RxTx.m index fa361a9..b859199 100644 --- a/+adi/+common/RxTx.m +++ b/+adi/+common/RxTx.m @@ -25,6 +25,14 @@ % Hide unused parameters when in specific modes function flag = isInactivePropertyImpl(obj, prop) flag = strcmpi(prop,'enIO'); + % TX/RX + if isprop(obj,'EnableCustomFilter') + flag = flag || strcmpi(prop,'CustomFilterFileName') && ~obj.EnableCustomFilter; + if obj.EnableCustomFilter + flag = flag || strcmpi(prop,'RFBandwidth'); + flag = flag || strcmpi(prop,'SamplingRate'); + end + end % TX if isprop(obj,'DataSource') flag = flag || strcmpi(prop,'DDSFrequencies') &&... diff --git a/test/AD9361Tests.m b/test/AD9361Tests.m index bf0978c..b69b0f6 100644 --- a/test/AD9361Tests.m +++ b/test/AD9361Tests.m @@ -25,6 +25,18 @@ function testAD9361Rx(testCase) testCase.verifyGreaterThan(sum(abs(double(out))),0); end + function testAD9361RxCustomFilter(testCase) + % Test Rx DMA data output + rx = adi.AD9361.Rx('uri',testCase.uri); + rx.channelCount = 2; + rx.EnableCustomFilter = true; + rx.CustomFilterFileName = 'customAD9361filter.ftr'; + [out, valid] = rx(); + rx.release(); + testCase.verifyTrue(valid); + testCase.verifyGreaterThan(sum(abs(double(out))),0); + end + function testAD9361RxWithTxDDS(testCase) % Test DDS output tx = adi.AD9361.Tx('uri',testCase.uri); diff --git a/test/customAD9361filter.ftr b/test/customAD9361filter.ftr new file mode 100644 index 0000000..beaf968 --- /dev/null +++ b/test/customAD9361filter.ftr @@ -0,0 +1,138 @@ +# Generated with AD9361 Filter Design Wizard 16.1.3-g22a2ace +# MATLAB 9.5.0.944444 (R2018b), 09-Jan-2019 20:50:49 +# Inputs: +# Data Sample Frequency = 3000000 Hz +TX 3 GAIN 0 INT 4 +RX 3 GAIN -12 DEC 4 +RTX 768000000 96000000 48000000 24000000 12000000 3000000 +RRX 768000000 96000000 48000000 24000000 12000000 3000000 +BWTX 2521541 +BWRX 2521551 +87,197 +-74,-92 +102,342 +-128,-41 +-63,253 +-302,-96 +-350,-12 +-568,-345 +-620,-369 +-718,-611 +-637,-571 +-533,-607 +-284,-397 +-41,-234 +237,63 +407,235 +490,392 +402,347 +211,226 +-78,-48 +-346,-301 +-544,-537 +-573,-596 +-437,-510 +-136,-224 +227,135 +565,512 +748,738 +718,768 +446,528 +7,104 +-489,-421 +-876,-854 +-1028,-1073 +-858,-952 +-396,-516 +255,154 +894,842 +1322,1345 +1365,1455 +970,1106 +204,337 +-723,-637 +-1537,-1533 +-1949,-2034 +-1776,-1930 +-987,-1159 +245,111 +1587,1544 +2611,2682 +2932,3107 +2317,2545 +798,1006 +-1310,-1200 +-3438,-3481 +-4892,-5104 +-5016,-5358 +-3375,-3766 +114,-214 +5115,4956 +10912,11001 +16547,16903 +21012,21595 +23479,24191 +23479,24191 +21012,21595 +16547,16903 +10912,11001 +5115,4956 +114,-214 +-3375,-3766 +-5016,-5358 +-4892,-5104 +-3438,-3481 +-1310,-1200 +798,1006 +2317,2545 +2932,3107 +2611,2682 +1587,1544 +245,111 +-987,-1159 +-1776,-1930 +-1949,-2034 +-1537,-1533 +-723,-637 +204,337 +970,1106 +1365,1455 +1322,1345 +894,842 +255,154 +-396,-516 +-858,-952 +-1028,-1073 +-876,-854 +-489,-421 +7,104 +446,528 +718,768 +748,738 +565,512 +227,135 +-136,-224 +-437,-510 +-573,-596 +-544,-537 +-346,-301 +-78,-48 +211,226 +402,347 +490,392 +407,235 +237,63 +-41,-234 +-284,-397 +-533,-607 +-637,-571 +-718,-611 +-620,-369 +-568,-345 +-350,-12 +-302,-96 +-63,253 +-128,-41 +102,342 +-74,-92 +87,197