DSPRelated.com

vectors_intr.asm - External Interruption Configuration

David Valencia February 2, 2011 Coded in ASM for the TI C67x
*Vectors_intr.asm Vector file for interrupt INT11 
   .global _vectors     ;global symbols 
   .global _c_int00 
   .global _vector1 
   .global _vector2 
   .global _vector3 
   .global _c_int04     ; símbolo para EXT_INT4 
   .global _vector5 
   .global _vector6 
   .global _vector7 
   .global _vector8 
   .global _vector9    
   .global _vector10  
   .global _c_int11        ;for INT11 
   .global _vector12   
   .global _vector13    
   .global _vector14 
   .global _vector15 
 
   .ref _c_int00        ;entry address 
 
VEC_ENTRY .macro addr      ;macro for ISR 
    STW   B0,*--B15 
    MVKL  addr,B0 
    MVKH  addr,B0 
    B     B0 
    LDW   *B15++,B0 
    NOP   2 
    NOP    
    NOP    
   .endm 
 
_vec_nmi: 
  B    NRP 
  NOP  5 
 
_vec_dummy: 
  B    IRP 
  NOP  5 
 
 .sect ".vecs"        ;aligned IST section 
 .align 1024 
_vectors: 
_vector0:   VEC_ENTRY _c_int00     ;RESET 
_vector1:   VEC_ENTRY _vec_nmi   ;NMI 
_vector2:   VEC_ENTRY _vec_dummy    ;RSVD 
_vector3:   VEC_ENTRY _vec_dummy 
_vector4:   VEC_ENTRY _c_int04    ;INT04 Externa 
_vector5:   VEC_ENTRY _vec_dummy 
_vector6:   VEC_ENTRY _vec_dummy 
_vector7:   VEC_ENTRY _vec_dummy 
_vector8:   VEC_ENTRY _vec_dummy 
_vector9:   VEC_ENTRY _vec_dummy 
_vector10:  VEC_ENTRY _vec_dummy 
_vector11:  VEC_ENTRY _c_int11      ;ISR address 
_vector12:  VEC_ENTRY _vec_dummy 
_vector13:  VEC_ENTRY _vec_dummy 
_vector14:  VEC_ENTRY _vec_dummy 
_vector15:  VEC_ENTRY _vec_dummy

Biquad bandpass filter bank

February 2, 2011 Coded in Mixed C and ASM for the SHARC
// Efficient implementation of biquad bandpass filter bank.
// This is the core computation for musical physical models ("modal models").
//
// This code takes 1.5 instructions to compute each floating-point bandpass filter;
// for a SHARC running at 3ns instruction cycle this is 4.5ns / biquad.
//
// Written by Lippold Haken of Haken Audio, 2010, using ADSP-21364 and VisualDSP++ C.
//
//  dmXmod - pointer to DM data memory
//  pmXmod - pointer to PM data memory
//  bfbXComputePairs - optimized computation of a bank of bandpass filters
//  bfbXCoef - coefficient computation for the bandpass filters

// CFDSP hardware-specific definitions.
#include "cfdsp21364.h"

// === Start of definitions for .h file
// The following structure definitions are shared by this code and by the calling code,
// so they should be moved to a common .h file.

// Data in dm.
typedef struct 
{
    #define bfb4FilterSections  64      // number of modes (number of bandpass filter sections)
    float bfb_Y[2][bfb4FilterSections];         // save state: y[n-1] and y[n-2]
} DmX_bfb;

// Data in pm.
typedef struct 
{
    // The bfb_C[] contains 3 coefficients for each biquad, with a pair of biquad's coefficients 
    // interleaved so that biquads can be processed in pairs by the optimized SIMD assembly loop.
    float bfb_C[ 3 * bfb4FilterSections ];      // bfb filter coefficients, see comment above
} PmX_bfb;

// Pointers to data, and a samples counter.
DmX_bfb *dmXmod;
PmX_bfb *pmXmod;
int sampInFrame;                    // sample counter

#define sr 48000                    // sample rate in Hz
#define Pi    (3.14159265)
#define ABS(x) ( ((x)>(0)) ? (x) : -(x) )
void sinCos( float fRadians, float *fSin, float *fCos ); // see Lippold Haken's sinCos code snippet 

// === End of definitions for .h file

// Parameter arrays for Biquad Filter Bank (modal physical modelling) synthesis.
//
// If P is the biquad pair number, and R=0/R=1 distinguishes the two biquads within the pair:
//  x[n]   coefficient for biquad k is at pmXmod->bfb_C[ 6*P + R + 0 ]; this is also -x[n-2] coefficient.
//  y[n-1] coefficient for biquad k is at pmXmod->bfb_C[ 6*P + R + 2 ]; this is scaled by 0.5 to avoid overflow
//  y[n-2] coefficient for biquad k is at pmXmod->bfb_C[ 6*P + R + 4 ]
// The first index to dmXmod->bfb_Y[] is based on lsbs of sample counter.
// The second index to dmXmod->bfb_Y[] is 2P+R.
// Note: R=0 always for even voices, R=1 always for odd voices.
#define bfb_Ynm1(P) &(dmXmod->bfb_Y[sampInFrame & 1][2*(P)])        // start in y[n-1][] array
#define bfb_Ynm2(P) &(dmXmod->bfb_Y[1-(sampInFrame & 1)][2*(P)])    // start in y[n-2][] array

void bfbXComputePairs(int biquadP, int pairs, 
            float inDiff0,          // x[n]-x[n-2] for even biquads
            float inDiff1,          // x[n]-x[n-2] for odd biquads
            float *fSum0,           // output for even biquad sum
            float *fSum1)           // output for odd biquad sum
// Sum the output of a sequence of at least 2 biquad pairs.
// For each of the sequence of pairs, the first (even) biquad in each pair has a common input "input0",
// and the second (odd) biquad of each pair has a (possibly different) common input "input1". 
{
    // Assmebly-coded bfb filter loop using floating-point math.
    // The core loop takes 3 instructions for 2 biquads, or 4.5ns per biquad.
    // We use the even-numbered biquads for one voice, the odd-numbered biquads for a second voice.
    asm(
    "#include <def21364.h>                          \n"
    "BIT SET MODE1 SIMD;                            \n"

    // For each biquad k:  (k=6*biquadP for R=0)
    //   y[k](n) = C0[k] * (x[k](n) - x[k](n-2))
    //           + C1[k] * 2 * y[k](n-1) 
    //           + C2[k] * y[k](n-2)
    //
    // Register usage for biquad k (R==0):
    //   F0       = C0[k], C1[k], and C2[k]
    //   F4       = input0-old_input0 aka x[k](n)-x[k](n-2)
    //   F6       = y[k](n-1), y[k](n-2)
    //   F8       = scratch for computing y[k](n)
    //   F10      = sum of even biquad's y[](n) in each biquad pair
    //   F12      = scratch for computing y[k](n)
    //   F13      = final value of y[k-2](n)
    //   DM(I4)   = C0[k], C1[k], and C2[k]
    //   PM(I10)  = read y[k](n-2) write to y[k-2](n)
    //   PM(I12)  = read y[k](n-1)
    // Register usage for biquad k+1 (R==1):
    //   SF0      = C0[k+1], C1[k+1], and C2[k+1]
    //   SF4      = input1-old_input1 aka x[k+1](n)-x[k+1](n-2)
    //   SF6      = y[k+1](n-1), y[k+1](n-2)
    //   SF8      = scratch for computing y[k+1](n)
    //   SF10     = sum of odd biquad's y[](n) in each biquad pair
    //   SF12     = scratch for computing y[k+1](n)
    //   SF13     = final value of y[k-1](n)
    //   DM(I4+1) = C0[k+1], C1[k+1], and C2[k+1]
    //   PM(I10+1)= read y[k+1](n-2) write y[k-1](n)
    //   PM(I12+1)= read y[k+1](n-1)
    // Register usage for even and odd biquads:
    //   M4=M12=2
    //   M10=+4
    //   M11=-2
    //
    // The three instruction loop below computes two biquads simultaneously, for k and k+1,
    // in each SIMD loop execution.  The comments are written just for biquad k;
    // the biquad k+1 code and comments are implied by SIMD mode.

    // Set pointer increments.
    "      M4=2;M10=4;M11=-2;M12=2;                 \n"

    // Loop priming, with k=0 (and SIMD k=1).

        // Initialize F10=SF10=0                    fetch C0[k]         
    "      R10=R10-R10,                             F0=DM(I4,M4);                           \n"

        // C0[k]*(x(n)-x(n-2))                      fetch C1[k]         fetch y[k](n-1)
    "      F8=F0*F4,                                F0=DM(I4,M4),       F6=PM(I12,M12);     \n"
        // C1[k] * y[k](n-1)                        fetch C2[k]         fetch y[k](n-2)
    "      F12=F0*F6,                               F0=DM(I4,M4),       F6=PM(I10,M12);     \n"
        // C2[k] * y[k](n-2)    biquad k sum        fetch C0[k+2]
    "      F12=F0*F6,           F8=F8+F12,          F0=DM(I4,M4);                           \n"

    // Main loop, for k = 2..K-2 by 2 (and SIMD for k = 1..K-1 by 2).
    "DO (PC, endx) UNTIL LCE;   \n"  

        // C0[k]*(x(n)-x(n-2))  F13 is y[k-2](n)    fetch C1[k]         fetch y[k](n-1)
    "      F8=F0*F4,            F13=F8+F12,         F0=DM(I4,M4),       F6=PM(I12,M12);     \n"
        // C1[k] * y[k](n-1)    output sum          fetch C2[k]         fetch y[k](n-2)
    "      F12=F0*F6,           F10=F10+F13,        F0=DM(I4,M4),       F6=PM(I10,M11);     \n"
        // C2[k] * y[k](n-2)    biquad k sum        fetch C0[k+2]       save y[k-2](n)
    "endx: F12=F0*F6,           F8=F8+F12,          F0=DM(I4,M4),       PM(I10,M10)=F13;    \n"

        //                      F13 is y[k-2](n)                                     
    "                           F13=F8+F12,                             modify(I10,M11);    \n"
        //                      output sum                              save y[k-2](n)
    "                           F10=F10+F13,                            PM(I10,M10)=F13;    \n"

    "BIT CLR MODE1 SIMD;                            \n"     // disable SIMD
    "      NOP;                                     \n"     // wait for SIMD disable

    // Output register list, each element: "=rN" (varName)
            :   "=R10" (*fSum0),                    // F10 has floating sum of even & odd biquads
                "=S10" (*fSum1)                     // SF10 has floating sum of even & odd biquads
    // Input register list, each element: "rN" (varName)
            :   "lcntr" (pairs-1),
                "R4" (inDiff0),                     // x[n]-x[n-2] for even biquads
                "S4" (inDiff1),                     // x[n]-x[n-2] for odd biquads
                "I4" (&pmXmod->bfb_C[6 * biquadP]), // coefficients for all biquads
                "I10" (bfb_Ynm2(biquadP)),          // y[n-2] for all biquads, updated to y[n]
                "I12" (bfb_Ynm1(biquadP))           // y[n-1] for all biquads
    // Clobbered register list:  
    // We must avoid "do not use" regs, Compiler and Library Manual p.1-245.
    // We try to use mostly scratch regs, Compiler and Library Manual p.1-248.
            :   "r0", "r4", "r6", "r8", "r10", "r12", "r13", 
                "i4", "i10", "i12", 
                "m4", "m10", "m11", "m12" );
}

void bfbXCoef(int biquadP, int biquadR, float freq, float amp, float bw)
// Compute coefficients for a biquad filter section of the floating-point Biquad Filter Bank routine.
{
    int startingIndex = 6 * biquadP + biquadR;          // 6 * biquad pair number (+1 if second in pair)
    float *pC = &pmXmod->bfb_C[ startingIndex ];        // index biquad filter coefficients array
    float *y0 = &dmXmod->bfb_Y[0][2*biquadP+biquadR];   // filter memory for biquad
    float *y1 = &dmXmod->bfb_Y[1][2*biquadP+biquadR];   // filter memory for biquad

    // Is center frequency is below aliasing-cutoff limit?
    if (freq != 0.0 && freq < 0.5 * sr)
    {
        // Compute sin and cos of the mode frequency.
        float phase = freq * 2. * Pi / sr;
        float fSin, fCos;
        sinCos(phase, &fSin, &fCos); // efficient sine and cosine; see Lippold Haken's DSPrelated code snippet.

        // These formulas are adapted from Robert Bristow-Johnson BLT biquad web posting.
        // I use the BPF with "constant skirt gain, peak gain = Q", with amplitude scaling of input coefficients.
        // Compute intermediate parameters, alpha and beta.
        //      alpha = sin(w0)/(2*Q)
        //      beta  = 1/(1+alpha)
        //      y[n] = (beta * sin(w0)/2   )  *  (x[n] - x[n-2])
        //           + (beta * 2*cos(w0)   )  *  y[n-1]
        //           + (beta * (alpha - 1) )  *  y[n-2] 
        // In addition, the input x-coefficients are scaled by the amplitude of the biquad --
        // I use **twice** the amplitude value.
        float alpha = fSin * bw / 2.0;      // this is sin/(2*q)
        float beta = 1.0 / (1.0 + alpha); 
        pC[0] = amp * beta * fSin;          // x[n] coefficient, and -x[n-2] coefficient
        pC[2] = beta * 2. * fCos;           // y[n-1] coefficient
        pC[4] = beta * (alpha - 1.0);       // y[n-2] coefficient
    }
    else
    {
        // Frequency of bfb filter is beyond aliasing frequency,
        // or if we are about to start a new note.
        // Zero bfb filter coefficients and zero out the filter memory.
        pC[0] = pC[2] = pC[4] = 0;
        *y0 = *y1 = 0;
    }
}

2D IFFT

Senthilkumar February 2, 2011 Coded in Scilab
function [a] =ifft2d(a2) 
//a2 = 2D-DFT of any real or complex 2D matrix
//a = 2D-IDFT of a2  
m=size(a2,1)
n=size(a2,2)
//Inverse Fourier transform along the rows
for i=1:n
a1(:,i)=exp(2*%i*%pi*(0:m-1)'.*.(0:m-1)/m)*a2(:,i) 
end
//Inverse fourier transform along the columns
for j=1:m
atemp=exp(2*%i*%pi*(0:n-1)'.*.(0:n-1)/n)*(a1(j,:)).' 
a(j,:)=atemp.'
end
a = a/(m*n)
a = real(a)
endfunction

2D FFT

Senthilkumar February 2, 2011 Coded in Scilab
function [a2] = fft2d(a) 
//a = any real or complex 2D matrix
//a2 = 2D-DFT of 2D matrix  'a'
m=size(a,1)
n=size(a,2)
// fourier transform along the rows
for i=1:n
a1(:,i)=exp(-2*%i*%pi*(0:m-1)'.*.(0:m-1)/m)*a(:,i) 
end
// fourier transform along the columns
for j=1:m
a2temp=exp(-2*%i*%pi*(0:n-1)'.*.(0:n-1)/n)*(a1(j,:)).' 
a2(j,:)=a2temp.'
end
for i = 1:m
    for j = 1:n
        if((abs(real(a2(i,j)))<0.0001)&(abs(imag(a2(i,j)))<0.0001))
            a2(i,j)=0;
        elseif(abs(real(a2(i,j)))<0.0001)
            a2(i,j)= 0+%i*imag(a2(i,j));
        elseif(abs(imag(a2(i,j)))<0.0001)
            a2(i,j)= real(a2(i,j))+0;
        end
    end
end

Circular Convolution Matrix

February 1, 2011 Coded in Matlab
function HC = convmtx_circ(h, N);
% CONVMTX_CIRC Circular Convolution Matrix.
%    CONVMTX_CIRC(h,N) returns the circular convolution matrix for vector h.
%    h must be a column vector. If X is a column vector of length N,
%    then CONVMTX_CIRC(h,N)*X is the same as the circular convolution h * X.
%
% by Danilo Zanatta - 01.02.2011

h = h(:);
Nh = length(h);
Nc = N + Nh - 1;

if N < Nh,
    error('The circular convolution matrix size must be greater or equal the channel length');
end

H = convmtx(h,N);

HC = H(1:N, 1:N);
HC(1:(Nh-1), 1:N) = HC(1:(Nh-1), 1:N) + H((N+1):Nc, 1:N);

return

This function helps in converting linear phase fir filter transfer function to min phase fir filter transfer function

January 31, 20111 comment Coded in Matlab
function [hn_min] = lp_fir_2_mp_fir(hn_lin)

% This function helps in converting the linear phase 
% FIR filter to minimum phase FIR filter. It essentially 
% brings all zeros which are outside the unit circle to 
% inside of unit circle.

r 	= roots(hn_lin);
k	= abs(r) > 1.01;
r1  	= r(k);		% roots outside of unit circle.
r2	= r(~k);% roots on or within the unit circle
s	= [1./r1; r2];
hn_min	= poly(s);
hn_min	= hn_min*sqrt(sum(hn_lin.^2))/sqrt(sum(hn_min.^2));

GPIO.c - Using the GPIO as output

David Valencia January 31, 20114 comments Coded in C for the TI C67x
// GPIO.c	UPIITA-IPN 
// JOSE DAVID VALENCIA PESQUEIRA
//
// THIS PROGRAM ALLOWS THE DSP TO SEND A BIT THROUGH A GPIO PIN (PIN 7 IN THIS EXAMPLE)
// TO TURN ON A LED ON

#include <stdio.h>
#include <stdlib.h>
#include <csl_gpio.h>
#include <csl_gpiohal.h>
#include <csl_irq.h>

// GLOBAL VARIABLES
volatile int flag = 1;
volatile int pulse_flag = 1;

// CODE TO DEFINE GPIO HANDLE
GPIO_Handle gpio_handle; 

// GPIO REGISTER CONFIGURATION
GPIO_Config gpio_config = {         
    0x00000000, // gpgc = Interruption passthrough mode
    0x0000FFFF, // gpen = All GPIO 0-15 pins enabled
    0x0000FFFF, // gdir = All GPIO pins as outputs
    0x00000000, // gpval = Saves the logical states of pins
    0x00000000, // gphm All interrupts disabled for IO pins
    0x00000000, // gplm All interrupts for CPU EDMA disabled
    0x00000000  // gppol -- default state */
};

// Function prototypes
void send_edge();
void delay();

// Function definitions
void delay()
{
	// Delay function
	int count, count2;
	for(count = 0; count < 200; count++)
	{
		for(count2 = 0; count2 < 50000; count2++);
	}
}

void send_edge()
{	
    DSK6713_init();  
    // Open and configure the GPIO
    gpio_handle = GPIO_open( GPIO_DEV0, GPIO_OPEN_RESET );
    GPIO_config(gpio_handle,&gpio_config);
    // Send values through the pins
	
    GPIO_pinWrite(gpio_handle,GPIO_PIN7,0);
    delay();
    GPIO_pinWrite(gpio_handle,GPIO_PIN7,1);
    delay();
    GPIO_pinWrite(gpio_handle,GPIO_PIN7,0);
}

main()
{     
	send_edge(); // Configures the pins and sends a rising edge
	printf(“ ¡Felicidades! ¡Has logrado encender el led! ”);
	
}
// End of program>>

Inverse Sqrt and Fourth Root approximations

January 31, 2011 Coded in C for the SHARC
// Fast InvSqrt approxumation, with an error of less than 4%. 
// This approximation is attributed to Greg Walsh.
inline void InvSqrt(float *x) {	*(int *)x = 0x5f3759df - (*(int *)x >> 1); } 
inline float SqrtSqrt(float x) { InvSqrt(&x); InvSqrt(&x); return x; }

Fourier Trigonometric Series Approximation

David Valencia January 31, 2011 Coded in Matlab
%Trigonometric Fourier Series Approximation
%José David Valencia Pesqueira - UPIITA-IPN
%As posted for Dsprelated.com
 
close all; clear all; clc;
syms t k;

fprintf('\n ### FOURIER TRIGONOMETRICAL SERIES###');

fprintf('\nSpecify the range (t1,t2) for the approximation:\n');
t1=input('t1= ');
t2=input('t2= ');

% Getting the period

fprintf('\nIs there a repeating patterin in this range? (Y/N): ');
resp1=input('','s');

switch resp1
    case 'Y'
        fprintf('\nWhat is the period for the function?\n');
        T=input('T= ');
        omega0=(2*pi)/T;
    case 'N'
        T=t2-t1;
        omega0=(2*pi)/T;
    otherwise
        fprintf('\nInvalid Option');
        fprintf('\nEnd of program>>>');
        return
end

fprintf('\nThe approximation will be generated in a trigonometrical series: \n\n');
fprintf('f(t)=a0+a1*cos(omega0*t)+a2*cos(2*omega0*t)+...+b1*sen(omega0*t)+b2*sen(2*omega0*t)');
 
fprintf('\n\nUntil what coefficient ak,bk should I compute? (positive integer) n= ');
n=input('');
if n<=0
    fprintf('Invalid n');
    fprintf('\nProgram Stop >>>');
    return
end

fprintf('\nIs the function defined by parts? (Y/N): ');
resp1=input('','s');

switch resp1
    case 'N'
        fprintf('\nWrite the function in terms of t\nf(t)= ');
        f=input('');
        
        faprox=0;

        a0=(1/T)*int(f,t,t1,(t1+T));
 
        faprox=a0;
 
        for k=1:n
            a(k)=(2/T)*int((f*cos(k*omega0*t)),t,t1,(t1+T));
            faprox=faprox+a(k)*cos(k*omega0*t);
        end
 
        for k=1:n
            b(k)=(2/T)*int((f*sin(k*omega0*t)),t,t1,(t1+T));
            faprox=faprox+b(k)*sin(k*omega0*t);
        end

    % If the function is defined in many parts
    case 'Y'
        fprintf('\nHow many ranges do you want to define (positive integer): ');
        numinterv=input('');
        numinterv=round(numinterv);
        for k=1:numinterv
            fprintf('\n## Range #%d definition',k);
            fprintf('\n Write the range in the form of t(%d)<t<t(%d) : ',k-1,k);
            fprintf('\nt(%d)= ',k-1);
            a(k,1)=input(''); %Initial limits vector
            fprintf('\nt(%d)= ',k);
            a(k,2)=input(''); %Final limit vector
            fprintf('\nThe range # %d has a start in %d and ends in %d',k,a(k),a(k+1));
            fprintf('\nPlease define f(t) for the %d th interval:\nf(t)= ',k);
            ft(k)=input('');
            fprintf('\nEnd of definition of the function f%d',k);
        end
        
        faprox=0;
        a0=0
        for j=1:numinterv
            a0=a0+(1/T)*int(ft(j),t,a(j,1),a(j,2));
        end
 
        faprox=a0;
 
        % ak coefficient
        ak=0;
        for j=1:numinterv
            acumulador=(2/T)*int((f(j)*cos(k*omega0*t)),t,a(j,1),a(j,2));
            ak=ak+acumulador;
        end

        return
        
        fprintf('\n## End of Debug Execution');
        return    
    otherwise
        fprintf('\nEND OF PROGRAM>>');
        return
end

%% Salida de datos
fprintf('\nThe resulting coeficcients are: ');
a0
a
b
 
fprintf('\n Do you wish to plot the graph of f(t) against the approximate series? (Y/N): ');
resp1=input('','s');
 
if resp1=='Y'
    ezplot(f,[t1,t2]);
    hold on
    ezplot(faprox,[t1,t2]);
    grid;
end
 
fprintf('\nEND OF PROGRAM');

Fast power-of-10 approximation, for 32-bit floats

January 31, 2011 Coded in C for the SHARC
// Fast power-of-10 approximation, with RMS error of 1.77%. 
// This approximation developed by Nicol Schraudolph (Neural Computation vol 11, 1999).  
// Adapted for 32-bit floats by Lippold Haken of Haken Audio, April 2010.
// Set float variable's bits to integer expression.
// f=b^f is approximated by
//   (int)f = f*0x00800000*log(b)/log(2) + 0x3F800000-60801*8
// f=10^f is approximated by
//   (int)f = f*27866352.6 + 1064866808.0
inline void Pow10(float *f) { *(int *)f = *f * 27866352.6 + 1064866808.0; };