From 22f30687ec3544cd7d27d49b05b2bf8953574385 Mon Sep 17 00:00:00 2001 From: Eric Kooistra <kooistra@astron.nl> Date: Wed, 10 Jan 2024 09:43:53 +0100 Subject: [PATCH] All pass IIR filter desing by F. Harris. --- applications/lofar2/model/harris/tony_des_2.m | 160 ++++++++++++++ applications/lofar2/model/harris/tonycxx.m | 201 ++++++++++++++++++ 2 files changed, 361 insertions(+) create mode 100644 applications/lofar2/model/harris/tony_des_2.m create mode 100644 applications/lofar2/model/harris/tonycxx.m diff --git a/applications/lofar2/model/harris/tony_des_2.m b/applications/lofar2/model/harris/tony_des_2.m new file mode 100644 index 0000000000..3789844d63 --- /dev/null +++ b/applications/lofar2/model/harris/tony_des_2.m @@ -0,0 +1,160 @@ +function tony_des_2(action) +% tony_des_2 forms coefficients of two path recursive polyphase filter +% filter can be halfband quadrature mirror, polynomials in Z^2 +% filter can be bandwidth tuned, Z^-1 => (1-b*z)/(z-b), b=(1-tan(bw))/(1+tan(bw)) +% filter can be center frequency tuned, z^-1 => (-1/z)*(1-cz)/(z-c), c=cos(theta_c) +% filter can be zero-packed Z^-1 -> z^-k, k even +% order of filter is odd (3,5,7.....) +% wo is normalized band edge frequency .5>wo>.25 +% +% %%%%%%%%% this program calls tonycxx.m %%%%%%%%%%%%% +% +% based on paper "Digital Signal Processing Schemes for Efficient Interpolation and Decimation" +% by Valenzuela and Constantinides, IEE Proceedings, Dec 1983 +% Script file written by fred harris of SDSU. Copyright 2002 + + +global N_ +global ws_ +global wb_ +global wc_ +global kk_ +if nargin<1 + +figure(1) +clf reset +set(1,'name',' Two-Path Allpass Filter Design by fred harris, SDSU','numbertitle','off'); + +responseplot=axes('units','normalized','position',[.05 .4 .9 .55]); + +N_=uicontrol('style','edit','units','normalized','position',[0.18 0.1 0.07 0.07],'string','5'); +Ntext=uicontrol('style','text','units','normalized','position',[0.04 0.1 0.13 0.065],'string','Prototype Order (Odd)'); + +ws_=uicontrol('style','edit','units','normalized','position',[0.18 0.17 0.07 0.07],'string','0.300'); +wstext=uicontrol('style','text','units','normalized','position',[0.04 0.17 0.13 0.065],'string','Stopband Edge (0.25-0.5)'); + +wb_=uicontrol('style','edit','units','normalized','position',[0.42 0.17 0.07 0.07],'string','0.250'); +wbtext=uicontrol('style','text','units','normalized','position',[0.28 0.17 0.13 0.065],'string','Passband Edge'); + +wc_=uicontrol('style','edit','units','normalized','position',[0.66 0.17 0.07 0.07],'string','0.000'); +wctext=uicontrol('style','text','units','normalized','position',[0.52 0.17 0.13 0.065],'string','Center Frequency'); + +kk_=uicontrol('style','edit','units','normalized','position',[0.90 0.17 0.07 0.07],'string','2'); +wctext=uicontrol('style','text','units','normalized','position',[0.76 0.17 0.13 0.065],'string','Order (even)'); + +half_=uicontrol('style','push','units','normalized','position',[0.04 0.25 0.21 0.07],'string','Half-Band Low-Pass','callback','tony_des_2(''start1'')'); + +tlow_=uicontrol('style','push','units','normalized','position',[0.28 0.25 0.21 0.07],'string','Tune Bandwidth','callback','tony_des_2(''start1'')'); + +tband_=uicontrol('style','push','units','normalized','position',[0.52 0.25 0.21 0.07],'string','Tune Center Freq','callback','tony_des_2(''start1'')'); + +fordr_=uicontrol('style','push','units','normalized','position',[0.76 0.25 0.21 0.07],'string','Polynomial Degree','callback','tony_des_2(''start1'')'); + +tprint=uicontrol('style','push','units','normalized','position',[0.30 0.1 0.65 0.05],'string','Print Coefficients','callback','tony_des_2(''start2'')'); + +readtext=uicontrol('style','text','units','normalized','position',[0.280 0.03 0.65 0.05],'string','(Highlight Parameter Value, Enter Desired Value, Depress Button)'); +action='start1'; +end + +if strcmp(action,'start1') + coef=0; +end +if strcmp(action,'start2') + coef=1; +end + + N=str2num(get(N_,'string')); + if rem(N,2)~=1 + N=N+1; + N_=uicontrol('style','edit','units','normalized','position',[0.18 0.1 0.07 0.07],'string',N); + end + ws=str2num(get(ws_,'string')); + if ws<0.25 + ws=0.300; + ws_=uicontrol('style','edit','units','normalized','position',[0.18 0.17 0.07 0.07],'string',ws); + end + if ws>0.5 + ws=0.300; + ws_=uicontrol('style','edit','units','normalized','position',[0.18 0.17 0.07 0.07],'string',ws); + end + wb=str2num(get(wb_,'string')); + if wb>0.5 + wb=0.25; + wb_=uicontrol('style','edit','units','normalized','position',[0.42 0.17 0.07 0.07],'string','0.250'); + end + wc=str2num(get(wc_,'string')); + if wc>0.5 + wc=0.0; + wc_=uicontrol('style','edit','units','normalized','position',[0.66 0.17 0.07 0.07],'string','0.000'); + end + + kk=str2num(get(kk_,'string')); + if rem(kk,2)~=0; + kk=2; + kk_=uicontrol('style','edit','units','normalized','position',[0.90 0.17 0.07 0.07],'string','2'); + end + + if wb==0.25 & wc==0 + mode=1; + else + mode=2; + end + + aa=1; + if wc==0; + aa=-aa; + end + +[rts1,rts2,coef0,coef1,ff1,ff2]=tonycxx(N,ws,wb,wc,kk,mode); + +figure(2) +plot(roots(rts1),'x','linewidth',2,'markersize',8); +hold on; +plot(roots(rts2),'x','linewidth',2,'markersize',8); +plot(roots(conv(rts1,fliplr(rts2))-aa*conv(fliplr(rts1),rts2)),'o','linewidth',2) +plot(exp(j*2*pi*[0:.01:1]),'r'); +plot([-1.1 1.1],[0 0],'k') +plot([0 0],[-1.1 1.1],'k') + +hold off; +grid +axis([-1.2 1.2 -1.2 1.2]); +axis('square') +title('Roots of Two-Path Filter (Sum of Paths)') + +figure(1) +plot(0:1/1024:.5-1/1024,20*log10(abs(ff1+0.0000001))); +hold +plot(0:1/1024:.5-1/1024,20*log10(abs(ff2+0.0000001)),'r--'); +axis([0 .5 -100 10]); + +hold + +grid; +title('Magnitude Response of Two Path Filter'); +xlabel('Normalized Frequency (f/fs)'); +ylabel('Log Magnitude (dB)'); + +% write out coefficients +format long +if coef==1 + disp(' ') + disp('Denominator Polynomials, path-0') + if wc==0 + disp(' (a0 Z^2 + a1 Z^1 + a2)') + else + disp(' (a0 Z^4 + a1 Z^3 + a2 Z^2 + a3 Z^1 + a4)') +end + disp(' ') + disp(coef0) + disp(' ') + + disp('Denominator Polynomials, path-1') + if wc==0 + disp(' (b0 Z^2 + b1 Z^1 + b2)') + else + disp(' (b0 Z^4 + b1 Z^3 + b2 Z^2 + b3 Z^1 + b4)') +end + disp(' ') + disp(coef1) +end diff --git a/applications/lofar2/model/harris/tonycxx.m b/applications/lofar2/model/harris/tonycxx.m new file mode 100644 index 0000000000..3d89ffd3e3 --- /dev/null +++ b/applications/lofar2/model/harris/tonycxx.m @@ -0,0 +1,201 @@ +function [rts1,rts2,coef0,coef1,ff1,ff2]=tonycxx(n_ord,wo,bw,fc,k_ordr, mode) +% mode = 1 for lowpass prototype +% mode = 2 to bandwidth and center frequency of prototype +% k_ordr for filter order +% function called by tony_des_2, +% computes paramters of two-path recursive all-pass filter +% also computes parameters when frequency transformed to two-path +% low-pass or band-pass filter +% Script file written by fred harris of SDSU. Copyright 2002 + +mode; +wt=4*pi*(wo-0.25); +k=tan(0.25*(pi-wt)); +k=k*k; + +kk=sqrt(1-k*k); + +e=0.5*(1-sqrt(kk))/(1+sqrt(kk)); + +q=e+2*(e^5)+15*(e^9)+150*(e^13); +ww=zeros(1,(n_ord-1)/2); +aa=ww; +cc=[ww 0]; +%step 2 + +for ii=1:(n_ord-1)/2 + +ww(ii)=2*(q^0.25)*(sin(pi*ii/n_ord)-(q^2)*sin(3*pi*ii/n_ord)); +ww(ii)=ww(ii)/(1-2*(q*cos(2*pi*ii/n_ord)-(q^4)*cos(4*pi*ii/n_ord))); + +wwsq=ww(ii)*ww(ii); +aa(ii)=sqrt(((1-wwsq*k)*(1-wwsq/k)))/(1+wwsq); +cc(ii)=(1-aa(ii))/(1+aa(ii)); +end + +ordr1=floor((n_ord-1)/4); +ordr2=ordr1; +if n_ord-1-4*ordr1 ~= 0 + ordr1=ordr1+1; +end + +coef0=zeros(ordr1,3); +coef1=zeros(ordr2,3); + +zz=zeros(1,k_ordr-1); + +for ii=1:ordr1 +den0(ii,:)=[1 zz cc(2*ii-1)]; +end +coef0=den0; + +for ii=1:ordr2 +den1(ii,:)=[1 zz cc(2*ii)]; +end +coef1=den1; + +h0=[1]; +for ii=1:ordr1 +h0=conv(h0,den0(ii,:)); +end + + +h1=[1]; +for ii=1:ordr2 +h1=conv(h1,den1(ii,:)); +end + +zz2=zeros(1,k_ordr/2); +h1=[h1 zz2]; + +g0=fliplr(h0); +g1=fliplr(h1); + +rts1=h0; +rts2=h1; + +[tp,ww]=freqz(g0,h0,512); +[bt,ww]=freqz(g1,h1,512); + +ff1=0.5*(tp+bt); +ff2=0.5*(tp-bt); + +if mode==1 +return + +else + +tt=tan(pi*bw); +b=(1-tt)/(1+tt); + +c=cos(2*pi*fc); + +if fc==0 + +den0=zeros(ordr1,k_ordr+1); +den1=zeros(ordr2,k_ordr+1); +zz=zeros(1,(k_ordr/2)-1); + for nn=1:ordr1 +c00=1+cc(2*nn-1)*b*b; +c01=-2*b*(1+cc(2*nn-1)); +c01=c01/c00; +c02=cc(2*nn-1)+b*b; +c02=c02/c00; +den0(nn,:)=[1 zz c01 zz c02]; + end +coef0=den0; + + for nn=1:ordr2 +c10=1+cc(2*nn)*b*b; +c11=-2*b*(1+cc(2*nn)); +c11=c11/c10; +c12=cc(2*nn)+b*b; +c12=c12/c10; +den1(nn,:)=[1 zz c11 zz c12]; +end +zz2=zeros(1,k_ordr/2-1); +den1(ordr2+1,1:1+k_ordr/2)=[1 zz2 -b]; +coef1=den1; + +h0=[1]; +for ii=1:ordr1 + h0=conv(h0,den0(ii,:)); +end + +h1=[1 zz2 -b]; +for ii=1:ordr2 + h1=conv(h1,den1(ii,:)); +end + +g0=fliplr(h0); +g1=fliplr(h1); +rts1=h0; +rts2=h1; + +[tp,ww]=freqz(g0,h0,512); +[bt,ww]=freqz(g1,h1,512); + +ff1=0.5*(tp+bt); +ff2=0.5*(tp-bt); + +else + +den0=zeros(ordr1,2*k_ordr+1); +den1=zeros(ordr2,2*k_ordr+1); + +zz=zeros(1,(k_ordr/2)-1); + +for nn=1:ordr1 +c00=1+cc(2*nn-1)*b*b; +c01=-2*c*(1+b)*(1+cc(2*nn-1)*b); +c01=c01/c00; +c02=(1+cc(2*nn-1))*(c*c*(1+b*b)+2*b*(1+c*c)); +c02=c02/c00; +c03=-2*c*(1+b)*(cc(2*nn-1)+b); +c03=c03/c00; +c04=cc(2*nn-1)+b*b; +c04=c04/c00; +den0(nn,:)=[1 zz c01 zz c02 zz c03 zz c04]; +end +coef0=den0; + +for nn=1:ordr2 +c10=1+cc(2*nn)*b*b; +c11=-2*c*(1+b)*(1+cc(2*nn)*b); +c11=c11/c10; +c12=(1+cc(2*nn))*(c*c*(1+b*b)+2*b*(1+c*c)); +c12=c12/c10; +c13=-2*c*(1+b)*(cc(2*nn)+b); +c13=c13/c10; +c14=cc(2*nn)+b*b; +c14=c14/c10; +den1(nn,:)=[1 zz c11 zz c12 zz c13 zz c14]; +end +zz2=zeros(1,k_ordr/2-1); +den1(ordr2+1,1:1+k_ordr)=[1 zz2 -c*(1+b) zz2 b]; +coef1=den1; + + +h0=[1]; +for ii=1:ordr1 + h0=conv(h0,den0(ii,:)); +end + +h1=[1 zz -c*(1+b) zz b]; +for ii=1:ordr2 + h1=conv(h1,den1(ii,:)); +end + +g0=fliplr(h0); +g1=fliplr(h1); +rts1=h0; +rts2=h1; + +[tp,ww]=freqz(g0,h0,512); +[bt,ww]=freqz(g1,h1,512); + +ff1=0.5*(tp-bt); +ff2=0.5*(tp+bt); +end + +end -- GitLab