Skip to content
Snippets Groups Projects
Select Git revision
  • 79e97f24fc90b02a0cb6c2df91319f465b7a2efd
  • main default protected
  • feat_dma230_dataio
  • feat_qspi_rom
  • feat_extio
  • feat_dmax4
  • feat_dma350
  • feat_nanosoc_regions
  • feat_accel_decouple
  • dev
  • feat_accel_hash_stream
  • nanosoc-2023
12 results

fpga_pinmap.xdc

Blame
  • firstOrderDma.m 6.69 KiB
    %% Calculate 1st order Directional Microphone Array output
    % --------------------------------------------------
    % Author: Achilles Kappis
    % e-mail: axilleaz@protonmail.com
    %
    % Date: 05/11/2024 (DD/MM/YYYY)
    %
    % Copyright: MIT
    % --------------------------------------------------
    % Functionality: Calculate the output of a first order Differential
    %                Microphone Array.
    % --------------------------------------------------
    % Input
    % 
    % input [numeric]: The input to the array. 3D array/matrix with dimensions
    %                  MxIxF, where M represents the number of microphones and
    %                  must be even, I is the number of measurments (or number
    %                  of sources), and F is the number of frequencies of
    %                  interest. Each microphone pair is treated as a first
    %                  order DMA.
    % 
    % freq [numeric]: The frequencies of interest. A vector with number of
    %                 elements matching the third dimension of the "input"
    %                 parameter.
    % 
    % d [numeric]: The inter-element distance of the microphone pairs. This
    %              must be a real scalar.
    % 
    % pPattern [string/char/numeric] (Optional): The sought out beam-pattern.
    %                                            It can be either a string (or
    %                                            character cell) from one of
    %                                            the following (not case
    %                                            sensitive):
    %                                            - Omni, Omnidirectional,
    %                                              Monopole
    %                                            - Dipole, Figure-of-Eight
    %                                            - Cardioid
    %                                            - Hypercardioid
    %                                            - Supercardioid
    %                                            It can also be a numeric value
    %                                            representing the angle for
    %                                            which the response is
    %                                            specified (input parameter
    %                                            "beta") in degrees.
    %                                            [Default: Dipole]
    % 
    % beta [numeric] (Optional): The (normalised to unity) response at the
    %                            angle specified with teh parameter "pPattern".
    %                            If "pPattern" is given as string/char the
    %                            appropriate value is automatically set, and
    %                            this argument is ignored. [Default: 0]
    % 
    % --------------------------------------------------
    % Output
    % 
    % h [numeric]: This 2xF filter is the filter that results in the
    %              beam-pattern of interest and F is the number of frequencies.
    % 
    % output [numeric]: The output of the array. It has the same dimensions as
    %                   the "input" parameter except for the second dimension
    %                   which is equal to M/2.
    % 
    % --------------------------------------------------
    % Notes
    % 
    % --------------------------------------------------
    function [h, output] = firstOrderDma(input, freq, d, pPattern, beta)
        % ====================================================
        % Check for number of arguments
        % ====================================================
        narginchk(3, 5);
        nargoutchk(0, 2);
    
    
        % ====================================================
        % Validate input arguments
        % ====================================================
        validateattributes(input, {'numeric'}, {'3d', 'nonnan', 'finite', 'nonempty'}, mfilename, 'Input', 1);
    
        if mod(size(input, 2), 2) ~= 0
            error("Second dimension of 'input' parameter must have even length.")
        end
    
        validateattributes(freq, {'numeric'}, {'real', 'nonnan', 'finite', 'nonempty', 'vector', 'numel', size(input, 3)}, mfilename, 'Frequencies', 2);
        validateattributes(d, {'numeric'}, {'scalar', 'real', 'nonnan', 'finite', 'nonempty'}, mfilename, 'Inter-element distance', 3);
    
        % Check beta
        if nargin > 4
            validateattributes(beta, {'numeric'}, {'scalar', 'real', 'finite', 'nonempty', 'nonnan', '<=', 1, '>=', 0}, mfilename, "Beta", 5)
        else
            beta = 0;
        end
    
        % Check alpha (angle of null)
        if nargin > 3
            if isstring(pPattern) || ischar(pPattern)
                validateattributes(pPattern, {'char', 'string'}, {'scalartext', 'nonempty'}, mfilename, 'Polar pattern', 4);
            elseif isnumeric(pPattern)
                validateattributes(pPattern, {'numeric'}, {'scalar', 'real', 'nonnan', 'finite', 'nonempty'}, mfilename, 'Angle of null', 4);
            end
        else
            pPattern = "dipole";
        end
        
    
        % ====================================================
        % "Condition" arguments
        % ====================================================
        % Make sure frequencies is a row vector
        if ~isrow(freq)
            freq = freq.';
        end
    
    
        % ====================================================
        % Calculate parameters
        % ====================================================
        % Calculate the correct "null" angles based on given polar pattern
        if ~isnumeric(pPattern)
            switch convertStringsToChars(lower(pPattern))
                case {'omni', 'omnidirectional', 'monopole'}
                    pPattern = pi;
                    beta = 1;
                case {'dipole', 'figure-of-eight'}
                    pPattern = pi/2;
                    beta = 0;
                case 'cardioid'
                    pPattern = pi;
                    beta = 0;
                case 'hypercardioid'
                    pPattern = (2 * pi/3);
                    beta = 0;
                case 'supercardioid'
                    pPattern = (3 * pi/4);
                    beta = 0;
                otherwise
                    error("Unsupported polar pattern");
            end
        else
            pPattern = deg2rad(pPattern);
        end
    
    
        % Calculate filter(s)
        for freqIdx = length(freq):-1:1
            arrManLocMtx = [arrManLoc(0, d, freq(freqIdx), 343), arrManLoc(pPattern, d, freq(freqIdx), 343)];
            h(:, freqIdx) = (arrManLocMtx')\[1; beta];
        end
    
    
        % ====================================================
        % Calculate array output
        % ====================================================
        if nargout > 1
            % Go through the frequencies
            for freqIdx = length(freq):-1:1
                for pairIdx = size(input, 1)/2:-1:1
                    % Multiply the array filter with the input
                    output(pairIdx, :, freqIdx) = h(:, freqIdx)' * input(pairIdx * 2 - 1:pairIdx * 2, :, freqIdx);
                end
            end
        end
    end
    
    
    %% Utility functions
    % Calculate the array manifold
    function am = arrManLoc(phi, d, freq, c)
        k = -2j * pi * freq * cos(phi)/c;
        am = [exp(k * (-d/2)); exp(k * (d/2))];
    end