summaryrefslogtreecommitdiff
path: root/macros/bilinear.sci
blob: 9030bfdf117522d12a5d2d92de105c9d0563026d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
// Copyright (C) 2018 - IIT Bombay - FOSSEE
//
// This file must be used under the terms of the CeCILL.
// This source file is licensed as described in the file COPYING, which
// you should have received as part of this distribution.  The terms
// are also available at
// http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
// Original Source : https://octave.sourceforge.io/signal/
// Modifieded by:Sonu Sharma, RGIT Mumbai
// Organization: FOSSEE, IIT Bombay
// Email: toolbox@scilab.in

function [Zz, Zp, Zg] = bilinear(Sz, Sp, Sg, T)

    //Transforms a s-plane filter (Analog) into a z-plane filter (Digital) using Bilinear transformation

    //Calling Sequence
    // [Zb, Za] = bilinear(Sb, Sa, T)
    // [Zb, Zb] = bilinear(Sz, Sp, Sg, T)
    // [Zz, Zp, Zg] = bilinear(...)

    //Prameters
    //Sb: Numerator coefficient vector in s-domain
    //Sa: denumerator coefficient vector s-domain
    //Sz: zeros in s-plane
    //Sp: poles in s-plane
    //Sg: gain in s-domain
    //T: Sampling period (double)
    //Zb: Numerator coefficient vector in z-domain
    //Za: denumerator coefficient vector z-domain
    //Zz: zeros in z-plane
    //Zp: poles in z-plane
    //Zg: gain in z-domain

    //Description:
    //a filter design can be transformed from the s-plane to the z-plane while maintaining the band edges by means of the bilinear transform. This maps the left hand side of the s-plane into the interior of the unit circle in z-plane. The mapping is highly non-linear, so you must design your filter with band edges in the s-plane positioned at 2/T tan(w*T/2) so that they will be positioned at w after the bilinear transform is complete.
    //It does following transformation from s-plane to z-plane
    //                      2  z-1
    //             s -> -  ----
    //                      T  z+1

    //Examples
    //[b a] = bilinear ([1 2 3], [4 5 6], 1, 1)
    //Output :
    // a  =
    //
    //    1.    7.3333333    17.666667    14.
    // b  =
    //
    //    0.  - 0.1666667  - 0.3333333    2.5

    funcprot(0);
    [nargout nargin] = argn();
    ieee(1);

    if nargin==3
        T = Sg;
        [Sz, Sp, Sg] = tf2zp(Sz, Sp);
    elseif nargin~=4
        error("bilinear: invalid number of inputs")
    end

    p = length(Sp);
    z = length(Sz);
    if z > p | p==0
        error("bilinear: must have at least as many poles as zeros in s-plane");
    end

    // ----------------  -------------------------  ------------------------
    // Bilinear          zero: (2+xT)/(2-xT)        pole: (2+xT)/(2-xT)
    //      2 z-1        pole: -1                   zero: -1
    // S -> - ---        gain: (2-xT)/T             gain: (2-xT)/T
    //      T z+1
    // ----------------  -------------------------  ------------------------
    Zg = real(Sg * prod((2-Sz*T)/T) / prod((2-Sp*T)/T));

    if Zg == 0 & nargout == 3 then
        error("bilinear: invalid value of gain due to zero(s) at infinity avoid z-p-g form and use tf form ")
    end



    Zp = (2+Sp*T)./(2-Sp*T);
    SZp = size(Zp);
    if isempty(Sz)
        Zz = -ones(SZp(1), SZp(2));
    else
        Zz = [(2+Sz*T)./(2-Sz*T)];
        Zz = postpad(Zz, p, -1);
    end


    if nargout==2
        // zero at infinity
        Zz1 = [];
        for i=1:length(Zz)
            if Zz(i) ~= %inf
                Zz1 = [Zz1 Zz(i)];
            end
        end
        Zz = Zz1;

        if Zg == 0
            z = %z;
            bi = (2*(z - 1))/(T*(z + 1));
            Hs = Sg * real(poly(Sz, "s"))/real(poly(Sp, "s"));
            Hz = horner(Hs, bi);
            b = coeff(Hz.num);
            a = coeff(Hz.den);
            Zg = b($)/a($);
        end

        [Zz, Zp] = zp2tf(Zz, Zp, Zg);
        Zz = prepad(Zz, length(Zp));
    end

endfunction