summaryrefslogtreecommitdiff
path: root/macros/rcosdesign.sci
blob: ba20ee22816e8cbcc688c349a647206d3d90f662 (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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
function h = rcosdesign(rollof_factor, num_of_symb, samp_per_symb, varargin)
// RCOSDESIGN computes the raised cosine FIR filter
// Inputs:
//      rollof_fact: roll-off factor of the designed filter
//      num_of_symb: filter truncated to these many number of symbols
//      samp_per_symb: each symbol represented by these many samples
//      shape: returns a normal raised-cosine FIR filter when set to 'normal'.
//             returns a square-root raised cosing filter when set to 'sqrt'.
// Output:
//      h: returned filter coefficients
//The output result for the input parameter of shape 'normal' is not equivalent to the matlab output because of the use of sinc function in the computation. Matlab and scilab sinc functions seem to not be equivalent.

////EXAMPLE:
//rolloff = 0.25;
//span = 3;
//sample per symbol=sps=2;
//b=rcosdesign(rolloff,span,sps);
//OUTPUT:
//b=- 0.1210006  - 0.0456421    0.4418023    0.7590604    0.4418023  - 0.0456421  - 0.1210006




// Check validity of number of inout arguments
    checkNArgin(3, 4, argn(2));

    // Check validity of input arguments
    valid_class_ROF = ['single', 'double'];
    properties_ROF = ['scalar', 'real', 'nonNegative'];
    checkIpValidity(rollof_factor, valid_class_ROF, properties_ROF);
    if rollof_factor > 1 then
        error('roll-off factor should be <= 1');
    end

    if rollof_factor == 0 then
        rollof_factor = number_peroperties("tiny");
    end

    valid_class_NOS = ['single', 'double'];
    properties_NOS = ['scalar', 'real', 'positive', 'finite'];
    checkIpValidity(num_of_symb, valid_class_NOS, properties_NOS);

    valid_class_SPS = ['single', 'double'];
    properties_SPS = ['scalar', 'real', 'positive', 'finite', 'integer'];
    checkIpValidity(samp_per_symb, valid_class_SPS, properties_SPS);

    if pmodulo((num_of_symb*samp_per_symb), 2) ~= 0 then
        error('product of number_of_symbols and samples_per_symbol should be even');
    end


    if argn(2) > 3 then
        shape = varargin(1);
    else
        shape = 'sqrt';
    end

    valid_string_shape = ['sqrt', 'normal'];
    checkStringValidity(shape, valid_string_shape);

    // Designing the raised cosine filter

    pr = (samp_per_symb*num_of_symb)/2;
    ax = (-pr:pr)/samp_per_symb;

    if ~strcmpi(shape, 'normal') then
        den = (1-(2*rollof_factor*ax).^2);
        id1 = find(abs(den) > sqrt(%eps));
        for idx = 1:length(id1)
            filt_resp(id1(idx)) = sinc(ax(id1(idx))).*(cos(%pi*rollof_factor*ax(id1(idx)))./den(id1(idx)))/samp_per_symb;
        end

        id2 = 1:length(ax);
        id2(id1) = [];
        for idx = 1:length(id2)
            filt_resp(id2(idx)) = rollof_factor*sin(%pi/(2*rollof_factor))/(samp_per_symb);
        end


    else
        id1 = find(ax == 0);
        if  ~isempty(id1) then
            filt_resp(id1) = (-1)./(%pi.*samp_per_symb).*(%pi.*(rollof_factor-1) - 4.*rollof_factor);
        end

        id2 = find(abs(abs(4.*rollof_factor.*ax) - 1.0) < sqrt(%eps));
        if ~isempty(id2) then
            filt_resp(id2) = 1 ./ (2.*%pi.*samp_per_symb) * (%pi.*(rollof_factor+1)  .* sin(%pi.*(rollof_factor+1)./(4.*rollof_factor)) - 4.*rollof_factor .* sin(%pi.*(rollof_factor-1)./(4.*rollof_factor)) + %pi.*(rollof_factor-1)   .* cos(%pi.*(rollof_factor-1)./(4.*rollof_factor)) );
        end

        id = 1:length(ax);
        id([id1 id2]) = [];
        nid = ax(id);
        a = (-4.*rollof_factor./samp_per_symb);
        b = ( cos((1+rollof_factor).*%pi.*nid) + sin((1-rollof_factor).*%pi.*nid) ./ (4.*rollof_factor.*nid) );
        c = (%pi .* ((4.*rollof_factor.*nid).^2 - 1));

        for idx = 1:length(id)
            filt_resp(id(idx)) = a*b(idx)/c(idx);
            idx
        end


    end

    filt_resp = filt_resp / sqrt(sum(filt_resp.^2));

    h = filt_resp';

endfunction

function checkNArgin(min_argin, max_argin, num_of_argin)
    if num_of_argin < min_argin then
        error('Not enough input arguments')
    end

    if num_of_argin > max_argin then
        error('Too many input arguments')
    end
endfunction


function checkIpValidity(variable, valid_class, properties)
// Function to check the validity of the input variable
// Inputs:
//      valid_class: vector of valid classes for the input variable
//      properties: vector of necessary properties of the input variable

    for idx = 1:length(length(valid_class))
        if ~strcmpi(valid_class(idx), 'double') | ~strcmpi(valid_class(idx), 'single')  then
            if type(variable) ~= 1 then
                error('input variable should be of type double ');
            end
        end

    end

    for jdx = 1:length(length(properties))
        if ~strcmpi(properties(jdx), 'scalar') then
            if length(variable) > 1 then
                error('Input variable should be of type scalar');
            end
        end

        if ~strcmpi(properties(jdx), 'nonempty') then
            if isempty(variable) then
                error('Input variable is empty. It is invalid');
            end
        end

        if ~strcmpi(properties(jdx), 'nonNan') then
            if isnan(variable) then
                error('Input variable is not a number (Nan). It is invalid');
            end
        end

        if ~strcmpi(properties(jdx), 'real') then
            if ~isreal(variable) then
                error('Input should be real');
            end
        end

        if ~strcmpi(properties(jdx), 'positive') then
            if variable <= 0 then
                error('Input should be positive');
            end
        end

        if ~strcmpi(properties(jdx), 'integer') then
            if (int(variable)-variable) ~= 0 then
                error('Input should be an integer');
            end
        end

        if ~strcmpi(properties(jdx), 'nonNegative') then
            if variable < 0 then
                error('Input should be non-negative');
            end
        end

        if ~strcmpi(properties(jdx), 'finite') then
            if ~(abs(variable) < %inf) then
                error('Input should be finite');
            end
        end

    end

endfunction


function checkStringValidity(variable, valid_strings)
        if ~strcmpi(valid_strings(1), variable) | ~strcmpi(valid_strings(2), variable) then

        else
            error('Input string is not recognized')
        end

endfunction