Skip to content
Snippets Groups Projects
Select Git revision
  • 9fec4cf021a75cf16cc024f4ce2fd515c5698d96
  • master default protected
  • optimize_workflow
  • poppy_integration_v50
  • poppy_integration
  • releases/v5.0 protected
  • use-versioned-releases
  • releases/v5.0rc2 protected
  • releases/v5.0rc1 protected
  • releases/ldv_v407_atdb protected
  • ldv_v407_debug
  • releases/ldv_v406_debug protected
  • releases/ldv_v405 protected
  • releases/ldv_v404 protected
  • v5.0
  • v5.0rc2
  • v5.0rc1
  • ldv_v406_debug
  • ldv_v405_debug
  • ldv_v404
  • ldv_v403
  • ldv_v402
  • v4.0
  • ldv_v401
  • ldv_v40
  • ldv_v031
  • ldv_v03
  • ldv_v01
28 results

Ateamclipper.cwl

Blame
  • Code owners
    Assign users and groups as approvers for specific file changes. Learn more.
    pfir_coeff_adjust.m 8.22 KiB
    %-----------------------------------------------------------------------------
    %
    % Copyright (C) 2016
    % ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
    % P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
    %
    % This program is free software: you can redistribute it and/or modify
    % it under the terms of the GNU General Public License as published by
    % the Free Software Foundation, either version 3 of the License, or
    % (at your option) any later version.
    %
    % This program is distributed in the hope that it will be useful,
    % but WITHOUT ANY WARRANTY; without even the implied warranty of
    % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    % GNU General Public License for more details.
    %
    % You should have received a copy of the GNU General Public License
    % along with this program.  If not, see <http://www.gnu.org/licenses/>.
    %
    %-----------------------------------------------------------------------------
    % Author: E. Kooistra, 2016
    %
    % pfir_coeff_adjust - Compute and adjust polyphase FIR filter coefficients
    %   Computes the coefficients using pfir_coeff.m and then adjusts the 
    %   coefficients dependent on:
    %
    %   config.hp_factor : = 1, is initial or default value for BWchan
    %     With config.hp_factor the BWchan can be set relative to fchan = 1/N.
    %     Default BWchan = config.hp_factor/N = 1/N = fchan. 
    %
    %   config.hp_adjust :
    %     when true then enable automatic channel half power bandwidth
    %     adjustment of config.hp_factor by iteration until the
    %     config.hp_factor has reached an accuracy of hp_resolution.
    %     For floating point nof_bits=0 the config.hp_factor can achieve an
    %     arbitrary accurate solution. For fixed point nof_bits>0 the solution
    %     can only be as good as possible, so then decreasing hp_resolution
    %     does not change the coeff anymore. The input BWchan is then ignored
    %     and the initial BWchan is then set to config.hp_factor/N.
    %
    %   config.dc_adjust :
    %     when true then after quantization the FIR coefficients are adjusted
    %     such that each of the N polyphase FIR sections with L taps each has
    %     the same DC response. This then ensures that for DC input the output
    %     of all N polyphases will also be DC. The FFT in a polyphase
    %     filterbank will then transform this DC to bin 0, and there will be
    %     no affect on the other bins.
    %     The DC adjustment algorithm first determines the median of the sums
    %     per polyphase. For each polyphase the L taps are then DC adjusted
    %     to this dc_polyphases_median. If the DC adjustment is > L then first
    %     an equal coarse adjustment is made to all L taps. The remining DC
    %     adjustment is then < L and applied by adjusting the outer taps by 1.
    %     
    %     The DC adjustment must not cause coefficient overflow. If it does
    %     then the script will rerun with coeff_q_max sufficiently smaller
    %     than the default 2^(nof_bits-1)-1 until it succeeds.
    %
    %   The run_pfir_coeff.m shows how this pfir_coeff_adjust.m and
    %   pfir_coeff.m can be used.
    %
    %   For more information see help of pfir_coeff.m.
    function coeff = pfir_coeff_adjust(N, L, BWchan, r_pass, r_stop, nof_bits, config, coeff_q_max)
    
    % Default options
    if ~exist('coeff_q_max', 'var'); coeff_q_max = 2^(nof_bits-1)-1; end;  % the quantization maps h_fir_max to coeff_q_max
    
    while true
        if config.hp_adjust==false
            % Calculate the FIR coefficients using the specified BWchan
            coeff = pfir_coeff(N, L, BWchan, r_pass, r_stop, nof_bits, config, coeff_q_max);
    
        else
            % Automatically adjust channel half power bandwidth, so need db(sqrt(2)) = -3 dB gain instead of half gain
            hp_radix = 2;  % choose 2 for binary search, or 10 for 'decimal' search
            hp_step = 1/hp_radix;
            hp_resolution = 0.000001;
            while true
                BWchan = config.hp_factor/N;
                coeff = pfir_coeff(N, L, BWchan, r_pass, r_stop, nof_bits, config, coeff_q_max);
                hf_abs = abs(fftshift(fft(coeff / sum(coeff), N*L))); 
                fi_0 = N*L/2+1;              % frequency index of center of channel, so 0 Hz
                fi_p = fi_0 + L/2;           % frequency index of edge of channel at +f_chan/2
                hf_abs_p = hf_abs(fi_p);     % gain edge of channel at +f_chan/2
                disp(sprintf('hp_factor = %10.8f, hf_abs_p = %10.8f, hp_step = %10.8f\n', config.hp_factor, hf_abs_p, hp_step));
                if hf_abs_p < sqrt(0.5)
                    config.hp_factor = config.hp_factor + hp_step;
                else
                    if hp_step <= hp_resolution, break; end
                    config.hp_factor = config.hp_factor - hp_step;
                    hp_step = hp_step/hp_radix;
                    config.hp_factor = config.hp_factor + hp_step;
                end
            end
        end
    
        if config.dc_adjust==true && nof_bits>0
            % Automatically equalize the DC response of the polyphases to have flat DC level at FFT input
            % Reshape the coefficients in N polyphases with L taps each.
            % Work with q_full_scale quantized coefficients to have q_bit unit quantization.
            q_bit = 1;
            q_full_scale = 2^(nof_bits-1);  % maximum amplitude, magnitude
            q_coeff = round(q_full_scale * reshape(coeff, N, L).');
            % The DC response is the sum of the FIR coefficients per polyphase.
            dc_polyphases = sum(q_coeff);
            % The median will be used as aim for the dc adjustment, because most polyphases are already
            % close to the median. For larger N the first and last polyphases deviate the most.
            dc_polyphases_median = median(dc_polyphases);
            % DC adjust each polyphase to the DC median
            for I = 1:N
                polyphase = q_coeff(:,I);
                dc_polyphase = sum(polyphase);
                dc_adjust = dc_polyphase - dc_polyphases_median;
                % First equally adjust all L coefficients by an equal amount of
                % dc_offset >= 0
                dc_offset = floor(abs(dc_adjust)/L);
                % Then adjust the dc_remainder < L, over dc_adjust number of
                % coefficients from the outer to the inner taps of the polyphase
                % by 1
                dc_remainder = abs(dc_adjust) - L*dc_offset;
                % Treat dc_adjust < 0, > 0 separately, nothing to do when dc_adjust = 0
                if dc_adjust > 0
                    polyphase = polyphase - dc_offset;
                    if dc_remainder > 0
                        for J = 1:dc_remainder
                            if mod(J,2)==0
                                polyphase(J) = polyphase(J) - 1;
                            else
                                polyphase(L+1-J) = polyphase(L+1-J) - 1;
                            end
                        end
                    end
                end
                if dc_adjust < 0
                    polyphase = polyphase + dc_offset;
                    if dc_remainder > 0
                        for J = 1:dc_remainder
                            if mod(J,2)==0
                                polyphase(J) = polyphase(J) + 1;
                            else
                                polyphase(L+1-J) = polyphase(L+1-J) + 1;
                            end
                        end
                    end
                end
                dc_polyphase = sum(polyphase);
                dc_adjusted = dc_polyphase - dc_polyphases_median;
                if dc_adjusted ~= 0
                    % Return with Error messages when dc_adjusted for a polyphase is not 0
                    disp(sprintf('Error polyphase %4d : dc_adjust = %4d, dc_offset= %4d, dc_remainder = %4d, dc_adjusted = %4d must be 0', I, dc_adjust, dc_offset, dc_remainder, dc_adjusted));
                    return
                end
                q_coeff(:,I) = polyphase / q_full_scale;  % back to normalized full scale coefficients
            end
            coeff = reshape(q_coeff.', 1, N*L);
            
            % Check whether the q_coeff are still in range q_min : q_max
            q_full_scale = 2^(nof_bits-1);
            q_max = q_full_scale-1;
            q_margin = q_max - max(q_coeff(:));
            if q_margin < 0
                coeff_q_max = coeff_q_max+q_margin;  % Recalculate pfir_coeff with more positive margin to fit DC adjustment
            else
                break;  % Finished DC adjustment of the coefficients
            end
        else
            break;  % No need to while loop
        end
    end
    
    end