|
|
View previous topic :: View next topic |
Author |
Message |
Marco27293
Joined: 09 May 2020 Posts: 126
|
DSPIC33EP512GP502 and FFT issue extending FFT_LENGTH |
Posted: Mon Jul 24, 2023 9:04 am |
|
|
Hi,
I tried to allow FFT_LENGTH 2048 in fft.h library.
PCD compiles and programs my DSPic (48K RAM) without any problem.
But if I execute the code I note a strange behaviour like RAM issue.
During fft computation the device resets.
If FFT_LENGTH is 512 al works fine.
Why ? Can you adjust fft.h library to handle 2048 long array ?
Regards,
Marco
Code: |
///////////////////////////////////////////////////////////////////////////
//// ////
//// fft.h ////
//// ////
//// Library for performing FFT and IFFT on a dsPIC. dsPIC's ////
//// instruction set are utilized for maximum effeciency. ////
//// ////
//// ////
//// CONFIG ////
//// ----------------------------------------------------------------- ////
//// FFT_LENGTH ////
//// Must be #defined before loading this library. This defines ////
//// the maximum FFT size (in input samples, or FFT bins ////
//// multiplied by 2) that can be used by this library. This ////
//// must be a power of 2 (2, 4, 8, 16, 32, etc). Any length ////
//// sized used by this API must be a power of 2. ////
//// ////
//// ////
//// API ////
//// ----------------------------------------------------------------- ////
//// fft_init() ////
//// fft_init(fft_size) ////
//// fft_init(Complex* tw_y, fft_size) ////
//// If 'fft_size' isn't provided, FFT_LENGTH is used. Inits ////
//// the library and generates the FFT twiddle factors for a ////
//// an FFT size of 'fft_size'. If 'tw_y' isn't provided then it ////
//// uses a default internal buffer. 'tw_y' must be located ////
//// in the Y bank. ////
//// ////
//// build_twiddle(Complex* tw_y, fft_size) ////
//// Builds the FFT twiddle factors for an FFT of size 'fft_size'. ////
//// FFT twiddle factors saved to 'tw_y', which must be in the ////
//// Y bank. Twiddle factors only need to be built once. ////
//// Normally fft_init() will do this for you, but if you are ////
//// using this library to perform FFT operations on different ////
//// buffer sizes (instead of sticking with one buffer size for ////
//// the entirety of the program), then the user needs to generate ////
//// the build_twiddle() for the different sizes being used. ////
//// ////
//// unsigned int16 = cplx_magnitude(cplx_magnitude *c) ////
//// Calculates the magnitude of complex sample c. ////
//// ////
//// Complex* result = fft(cplx_input input) ////
//// Complex* result = fft(cplx_input input, fft_size) ////
//// Complex* result = fft(cplx_input input, Complex* tw_y, fft_size) ////
//// Calculates the FFT using 'fft_size' samples from 'input'. ////
//// Uses 'tw_y' for the twiddle factors, and must be located in ////
//// the Y bank. If 'fft_size' is not provided, it will use ////
//// FFT_LENGTH. If 'tw_y' is not provided, it will use the ////
//// default internal buffer used by fft_init() and ////
//// fft_init(fft_size). 'tw_y' should have been generated with ////
//// fft_init() or build_twiddle(). Returns a pointer to results. ////
//// 'input', 'result' and 'fft_size' cannot be larger than ////
//// FFT_LENGTH. ////
//// ////
//// Complex* result = ifft(cplx_input input) ////
//// Complex* result = ifft(cplx_input input, fft_size) ////
//// Complex* result = ifft(cplx_input input, Complex* tw_y, fft_size) ////
//// Calculates the inverse FFT (frequency domain to time domeain) ////
//// using 'fft_size' samples from 'input'. Uses 'tw_y' for the ////
//// twiddle factors, and must be located in the Y bank. If ////
//// 'fft_size' is not provided, it will use FFT_LENGTH. ////
//// If 'tw_y' is not provided, it will use the default internal ////
//// buffer used by fft_init() and fft_init(fft_size). 'tw_y' ////
//// should have been generated with fft_init() or ////
//// build_twiddle(). Returns a pointer to results. 'input', ////
//// 'result' and 'fft_size' cannot be larger than FFT_LENGTH. ////
//// ////
///////////////////////////////////////////////////////////////////////////
//// (C) Copyright 1996,2016 Custom Computer Services ////
//// This source code may only be used by licensed users of the CCS C ////
//// compiler. This source code may only be distributed to other ////
//// licensed users of the CCS C compiler. No other use, reproduction ////
//// or distribution is permitted without written permission. ////
//// Derivative programs created using this software in object code ////
//// form are not restricted in any way. ////
//// http://www.ccsinfo.com ////
///////////////////////////////////////////////////////////////////////////
#ifndef FFT_H
#define FFT_H 1
#ifndef FFT_LENGTH
#error FFT_LENGTH must be defined prior to including this header!
#endif
#if ((FFT_LENGTH != 2) && (FFT_LENGTH != 4) && (FFT_LENGTH != 8) && (FFT_LENGTH != 16) && (FFT_LENGTH != 32) && (FFT_LENGTH != 64) && (FFT_LENGTH != 128) && (FFT_LENGTH != 256) && (FFT_LENGTH != 512) && (FFT_LENGTH != 1024) && (FFT_LENGTH != 2048))
#error FFT LENGTH must be a power of two!
#endif
#include <math.h>
/* Core configuration registers. */
#word XBREV = 0x0050
#bit BREN = XBREV.15
#word MODCON = 0x0046
#word CORCON = 0x0044
#bit IF_EN = CORCON.0
#bit RND = CORCON.1
#bit ACCSAT = CORCON.4
#bit SATA = CORCON.7
#bit SATB = CORCON.6
#bit US = CORCON.12
#bit US1 = CORCON.13
/* Represent a complex number with both a real and imaginary part. */
#ifndef _complexnum
#define _complexnum
typedef signed int16 fft_int_t;
typedef struct _complex
{
fft_int_t re;
fft_int_t im;
} Complex;
#endif
#banky
Complex twiddle[FFT_LENGTH / 2];
// see documentation above
unsigned int16 cplx_magnitude(Complex* c)
{
unsigned int32 op;
unsigned int32 res;
unsigned int32 one;
signed int16 re;
signed int16 im;
/* Set the core configuration. */
US = 0;//unsigned
US1 = 0;
IF_EN = 1;//integer
SATB = 1;//enable saturation in the accumulators
ACCSAT = 1;
re = c->re;
im = c->im;
// op = re^2 + im^2;
#asm
MOV re, w4
MOV im, w6
MPY w4*w4,A
MPY w6*w6,B
ADD A
MOV 0x24,w5
MOV w5, op+2
MOV 0x22,w5
MOV w5, op
#endasm
US = 0;//signed
IF_EN = 0;//fractional
RND = 1; //convergent rounding
res = 0;
one = 1 << 30;
while(one > op)
one >>= 2;
while(one != 0)
{
if( op >= res + one)
{
op -= res + one;
res = (res >> 1) + one;
}
else
{
res >>= 1;
}
one >>= 2;
}
return (unsigned int16)res;
}
// see documentation above
void build_twiddle(Complex* tw, unsigned int16 fft_size)
{
unsigned int16 i = 0;
float32 theta = 0;
float32 d_theta = 0;
d_theta = 2 * PI / (fft_size);
for(i = 0;i < fft_size / 2;i++)
{
//e^(-j * theta) = cos(theta) - j * sin (theta)
tw[i].re = (signed int16) (32767.0 * cos(theta));//scale to full range (-32768 to 32767)
tw[i].im = (signed int16) (-32767.0 * sin(theta));
theta += d_theta;//increment to the next theta value
}
}
// see documentation above
void fft_init(void)
{
build_twiddle(twiddle, FFT_LENGTH);
}
// see documentation above
void fft_init(unsigned int16 fft_size)
{
build_twiddle(twiddle, fft_size);
}
// see documentation above
void fft_init(Complex* twid_y, unsigned int16 fft_size)
{
/* Setup the DSP core for signed fractional operation. */
US = 0;//signed
US1 = 0;
IF_EN = 0;//fractional
RND = 1; //convergent rounding
build_twiddle(twid_y, fft_size);
}
/* Copy data into a destination buffer in bit reversed order.
* The destination buffer must be aligned on x000 address for bit reverse
* addressing to work correctly, ie: 0x1000
* This location should also be located in the X-RAM.
* (Check your device datasheet for the addresses located within X-RAM)
*
* This function could be used to copy in order, sampled data from
* DMA RAM into a buffer that will be used by the FFT in X RAM.
* This function MUST be called before running the FFT on a dataset.
* The input will not be modified. The output must not overlap the input.
*/
void memcpy_brev(Complex* dest, Complex* source, unsigned int16 fft_size)
{
unsigned int16 xb;
xb = 0x8000 | (fft_size);
#asm
push MODCON //save the MODCON register
push XBREV //save the XBREV register
mov #0x01FF, W4
mov W4, MODCON
mov xb, W4
mov W4, XBREV
mov dest, W1 //W1 = cplx_output; (bit-reversed pointer)
mov source, W0 //W0 = cplx_input; (pointer)
mov #2, W5 //W5 = sizeof(signed int16*)
mov fft_size, W4 //W4 = FFT_LENGTH;
dec W4, W4 //W4 = FFT_LENGTH - 1;
do W4, END
mov [W0], [W1] //br[k].re = seq[i].re
mov [W0+W5], [W1+W5] //br[k].im = seq[i].im
add #4, W0 //i++
END:mov [W1], [W1++] //k = k_next
pop XBREV //restore XBREV
pop MODCON //restore MODCON
#endasm
}
/* x_data: fft data array used for the in-place, radix-2, DIT FFT. A pointer
* to this memory array is returned by all FFT and IFFT functions. This
* array must be as long as the largest data sample to be transformed (nominally
* 64 complex values). This array must be located at 0x1000 for bit reversing
* up to 2048 points, or at 0x0800 for bit reversing up to 1024 points.
*/
Complex x_data[2*FFT_LENGTH];
//#locate x_data = 0x0800 //old
#locate x_data = 0x1000 //fix for EP
/* FFT function:
* Transforms a series of time-domain samples into the
* frequency-domain. This algorithm uses a radix-2, DIT FFT.
*
* -This function requires operates on buffers that are exactly a power of 2.
* 16384 is the maximum possible number of samples, however,
* this much memory may not be available.
* -Input samples are expected in signed, Q.15-fractional form; natural order
* -The maximum value any sample should reach is .5 (0x4000)
* or overflow may occur.
* -Samples are output in natural order into frequency bins of size Fs / (2 * N)
* -This function returns a pointer to the Fourier Transform of cplx_input.
*
* cplx_tw are required twiddle factors as generated by build_twiddle().
* These factors need be generated only once, but must be located in Y RAM.
*/
static Complex* _fft(Complex* cplx_input, Complex* cplx_tw, unsigned int16 fft_size)
{
unsigned int16 fft_len_div2 = fft_size / 2;
/* Setup the DSP core for signed fractional operation. */
US = 0;//signed
US1 = 0;
IF_EN = 0;//fractional
RND = 1; //convergent rounding
/* Bit reverse copy into the correct buffer. */
memcpy_brev(x_data, cplx_input, fft_size);
#asm
/* Initialize. */
mov fft_len_div2, W2 //W2 = TWI = FFT_LENGTH / 2;
mov fft_size, W14 //W14 = FFT_LENGTH
SL W14, #2, W14 //W14 = fft_length * sizeof(complex)
mov #1, W3 //W3 = k_max = 1
mov #8, W9 //W9 = offset = 2 * sizeof(complex);
STAGE_LOOP:
clr W11 //for(k = 0;k < k_max;k++)
K_LOOP:
/* Get the twiddle factor for this k-group. */
mov cplx_tw, W10 //W10 = cplx_tw (pointer)
sl W2, #2, W0 //W0 = sizeof(Complex) * offset
mul.uu W0, W11, W0 //W0 = k * (sizeof(Complex) * offset)
add W10, W0, W10 //tw = (tw + 1) (pointer)
/* Reset the input pointer. */
mov x_data, W8 //W8 = cplx_input (pointer) (reset)
sl W11, #2, W0 //W0 = 4 * k
add W8, W0, W8 //W8 = (cplx_input + 2 * k) (pointer)
asr W9, #1, W13 //W13 = offset to lower leg of buttefly
dec W2, W12 //W12 = W2 - 1
do W12, END_BFLY //do (twi - 1 + 1) times
/* Clear the accumulators, prefetch lower-leg */
clr B, [W8]+=2, W4 //B = 0, W4 = a.re W8 = &a[i].im
asr W4, #1, W0 //W0 = a.re / 2 (This provides the 1 / N factor in the FFT definition)
clr B, [W8]-=2, W5 //B = 0, W5 = a.im W8 = a[i - 1].re
asr W5, #1, W1 //W1 = a.im / 2 (This provides the 1 / N factor in the FFT definition)
/* Fetch the Upper Leg & Calculate the (b * Wk) product. */
add W8, W13, W8 //cplx_input = (cplx_input + offset) (cplx_input = lowerleg)
clr A, [W8]+=2, W4, [W10]+=2, W6 //A = 0, W4 = b.re W6 = w.re
mpy W4*W6, A, [W8]-=2, W5, [W10]-=2, W7 //A = (b.re * w.re), W5 = b.im W7 = w.im
msc W5*W7, A //A = b.re * w.re - b.im * w.im = (B * Wk).re
mpy W5*W6, B //B = b.im * w.re
mac W4*W7, B //B = b.im * w.re + b.re * w.re = (B * Wk).im, W8 = &a[i + 1].im
sac.r A, #1, W6 //W6 = t.re / 2 (This provides the 1 / N factor in the FFT definition)
sac.r B, #1, W7 //W7 = t.im / 2 (This provides the 1 / N factor in the FFT definition)
/* Calculate output legs (X = a + (b * Wk), Y = a - (b * Wk)) */
/* Calculate Y */
push.s //save a.re & a.im
sub W0, W6, W0 //Y.re = .5 * a.re - .5 * t.re
sub W1, W7, W1 //Y.im = .5 * a.im - .5 * t.im
mov W0, [W8++] //*(cplx_input + offset / 2) = Y.re
mov W1, [W8--] //*(cplx_input + offset / 2 + 2) = Y.im
sub W8, W13, W8 //W8 -> A
/* Calculate X */
pop.s //restore a.re & a.im
add W0, W6, W0 //X.re = .5 * a.re + .5 * t.re
add W1, W7, W1 //X.im = .5 * a.im + .5 * t.im
mov W0, [W8++] //*(cplx_input) = X.re
mov W1, [W8--] //*(cplx_input + 2) = X.im
END_BFLY: add W8, W9, W8 //W8 -> next butterfly upper leg
inc W11, W11
cp W11, W3
bra n, K_LOOP //for(k = 0;k < k_max;k++)
sl W3, #1, W3 //k_max *= 2
sl W9, #1, W9 //offset *= 2
asr W2, #1, W2 //twi /= 2
cp W9, W14 //while(offset <= FFT_LENGTH)
bra LE, STAGE_LOOP
#endasm
/* Scale up FFT by 2
*
* This is purely for mathematical accuracy and can be commented out
* if a relative, rather than absolute, FFT scale is sufficient
**/
//! unsigned int16 fft_len_x2 = fft_size * 2;
//! #asm
//! mov x_data, W8 //W8 = cplx_input (pointer) (reset)
//! mov #2,w1 //multiplicand
//! mov fft_len_x2, w0 //w0 = 2 * FFT_LENGTH
//! dec w0,w0 //Decrement w0
//! do w0, mul2 //Do next 2 instructions 2 * FFT_LENGTH times
//! mul.us w1,[w8],w2 //w2,w3 = w1*[w8] (2 * x_data[i])
//! mul2: mov w2,[w8++] //[w8] = w2, w8++
//! #endasm
return x_data;
}
#if defined(__PCD_QUIRK_OVERLOAD__)
// see documentation above
Complex* fft(Complex* cplx_input, Complex* cplx_tw, unsigned int16 fft_size)
{
return _fft(cplx_input, cplx_tw, fft_size);
}
// see documentation above
Complex* fft(Complex* cplx_input, unsigned int16 fft_size)
{
return _fft(cplx_input, twiddle, fft_size);
}
// see documentation above
Complex* fft(Complex* cplx_input)
{
return _fft(cplx_input, twiddle, FFT_LENGTH);
}
#else
#define fft(pComplex,fftSize) _fft(pComplex, twiddle, fftSize)
#endif
/* IFFT function:
* Transforms a series of complex frequency-domain samples into the
* time-domain. This algorithm uses a radix-2, DIT IFFT.
*
* -This function requires operates on buffers that are exactly a power of 2.
* 16384 is the maximum possible number of samples, however,
* this much memory may not be available.
* -Input samples are expected in signed, Q.15-fractional form; natural order
* -The maximum value any sample should reach is .5 (0x4000)
* or overflow may occur.
* -Samples are output in natural-time order.
* -This function returns a pointer to the I-Fourier Transform of cplx_input.
*
* cplx_tw are required twiddle factors as generated by build_twiddle().
* These factors need be generated only once, but must be located in Y RAM.
*/
static Complex* _ifft(Complex* cplx_input, Complex* cplx_tw, unsigned int16 fft_size)
{
unsigned int16 fft_len_div2 = fft_size / 2;
/* Setup the DSP core for signed fractional operation. */
US = 0;//signed
US1 = 0;
IF_EN = 0;//fractional
RND = 1; //convergent rounding
/* Bit reverse copy into the correct buffer. */
memcpy_brev(x_data, cplx_input, fft_size);
#asm
/* Initialize. */
mov fft_len_div2, W2 //W2 = TWI = FFT_LENGTH / 2;
mov fft_size, W14 //W14 = FFT_LENGTH
SL W14, #2, W14 //W14 = fft_length * sizeof(complex)
mov #1, W3 //W3 = k_max = 1
mov #8, W9 //W9 = offset = 2 * sizeof(complex);
STAGE_LOOP:
clr W11 //for(k = 0;k < k_max;k++)
K_LOOP:
/* Get the twiddle factor for this k-group. */
mov cplx_tw, W10 //W10 = cplx_tw (pointer)
sl W2, #2, W0 //W0 = sizeof(Complex) * offset
mul.uu W0, W11, W0 //W0 = k * (sizeof(Complex) * offset)
add W10, W0, W10 //tw = (tw + 1) (pointer)
/* Reset the input pointer. */
mov x_data, W8 //W8 = cplx_input (pointer) (reset)
sl W11, #2, W0 //W0 = 4 * k
add W8, W0, W8 //W8 = (cplx_input + 2 * k) (pointer)
asr W9, #1, W13 //W13 = offset to lower leg of buttefly
dec W2, W12 //W12 = W2 - 1
do W12, END_BFLY //do (twi - 1 + 1) times
/* Prefetch lower-leg */
mov [W8++],W0 //W0 = b.re (no scaling)
mov [W8--],W1 //W1 = b.im (no scaling)
/* Fetch the Upper Leg & Calculate the (b * Wk) product. */
add W8, W13, W8 //cplx_input = (cplx_input + offset) (cplx_input = lowerleg)
clr A, [W8]+=2, W4, [W10]+=2, W6 //A = 0, W4 = b.re W6 = w.re
mpy W4*W6, A, [W8]-=2, W5, [W10]-=2, W7 //A = (b.re * w.re), W5 = b.im W7 = w.im
mac W5*W7, A //A = b.re * w.re + b.im * w.im = (B * Wk).re
mpy W5*W6, B //B = b.im * w.re
msc W4*W7, B //B = b.im * w.re - b.re * w.im = (B * Wk).im, W8 = &a[i + 1].im
sac.r A, #0, W6 //W6 = t.re (No Scaling)
sac.r B, #0, W7 //W7 = t.im (No Scaling)
/* Calculate output legs (X = a + (b * Wk), Y = a - (b * Wk)) */
/* Calculate Y */
push.s //save a.re & a.im
sub W0, W6, W0 //Y.re = .5 * a.re - .5 * t.re
sub W1, W7, W1 //Y.im = .5 * a.im - .5 * t.im
mov W0, [W8++] //*(cplx_input + offset / 2) = Y.re
mov W1, [W8--] //*(cplx_input + offset / 2 + 2) = Y.im
sub W8, W13, W8 //W8 -> A
/* Calculate X */
pop.s //restore a.re & a.im
add W0, W6, W0 //X.re = .5 * a.re + .5 * t.re
add W1, W7, W1 //X.im = .5 * a.im + .5 * t.im
mov W0, [W8++] //*(cplx_input) = X.re
mov W1, [W8--] //*(cplx_input + 2) = X.im
END_BFLY: add W8, W9, W8 //W8 -> next butterfly upper leg
inc W11, W11
cp W11, W3
bra n, K_LOOP //for(k = 0;k < k_max;k++)
sl W3, #1, W3 //k_max *= 2
sl W9, #1, W9 //offset *= 2
asr W2, #1, W2 //twi /= 2
cp W9, W14 //while(offset <= FFT_LENGTH)
bra LE, STAGE_LOOP
#endasm
/* Scale down IFFT by 2
*
* This is purely presented for mathematical accuracy and can be commented
* out if the scale up in the FFT function is also commented out.
**/
//! unsigned int16 fft_len_x2 = fft_size * 2;
//! #asm
//! mov x_data, W8 //W8 = cplx_input (pointer) (reset)
//! clr A, [w8],W6
//! mov #0x4000,W4
//! mov fft_len_x2, w0 //w0 = 2 * FFT_LENGTH
//! dec w0,w0 //Decrement w0
//! do w0, div2 //Do next 2 instructions 2 * FFT_LENGTH times
//! mpy w4*w6, A
//! sac.r A,[w8++]
//! div2: clr A, [w8],W6
//! #endasm
return x_data;
}
Complex* ifft(Complex* cplx_input)
{
return _ifft(cplx_input, twiddle, FFT_LENGTH);
}
// see documentation above
Complex* ifft(Complex* cplx_input, unsigned int16 fft_size)
{
return _ifft(cplx_input, twiddle, fft_size);
}
// see documentation above
Complex* ifft(Complex* cplx_input, Complex* cplx_tw, unsigned int16 fft_size)
{
return _ifft(cplx_input, cplx_tw, fft_size);
}
#endif
|
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19358
|
|
Posted: Mon Jul 24, 2023 9:45 am |
|
|
What compiler version?.
Where is the array located????.
The later is vital. Note the line in the code about where it has to be for
2048 entries.
Code: |
/* This array must be located at 0x1000 for bit reversing
* up to 2048 points, or at 0x0800 for bit reversing up to 1024 points.
*/
Complex x_data[2*FFT_LENGTH];
//#locate x_data = 0x0800 //old
#locate x_data = 0x1000 //fix for EP
|
|
|
|
Marco27293
Joined: 09 May 2020 Posts: 126
|
|
Posted: Mon Jul 24, 2023 9:57 am |
|
|
Compiler is PCD v5.115
I did not force array location..
What should I do and where ?
Do I need to modify library?
I defined these in my source code:
Code: |
Complex samples[FFT_LENGTH];
Complex *fft_result;
|
Should I allocate them ? Where ?
Marco |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19358
|
|
Posted: Mon Jul 24, 2023 11:05 am |
|
|
Yes, it needs a #locate putting it at 0x1000. |
|
|
Marco27293
Joined: 09 May 2020 Posts: 126
|
|
Posted: Tue Jul 25, 2023 2:11 am |
|
|
I put:
Code: |
#define FFT_LENGTH 2048
Complex samples[FFT_LENGTH];
Complex *fft_result;
#locate fft_result = 0x1000
|
However if I use FFT_LENGTH 512 and I comment #locate all works fine.
Else using the above code, I'm experimenting weird RESTART_MCLR before to perform fft computation...
What could the problem be ?
Could it be a firmware RAM issue ?
The hardware works fine with FFT_LENGTH 512...
Regards,
Marco |
|
|
Marco27293
Joined: 09 May 2020 Posts: 126
|
|
Posted: Tue Jul 25, 2023 2:24 am |
|
|
An additional tip:
Sometimes this strange reset seems due to RESTART_TRAP_CONFLICT.
What does it mean ? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19358
|
|
Posted: Tue Jul 25, 2023 2:36 am |
|
|
You have not answered what compiler version?.
Now modern compilers have the internal data table already located at 0x1000,
so you should not need to do anything for this.
However big key is the size of XRAM. The assembler requires that the
data buffer for the actual FFT must be in the XRAM space. Now each
entry is 4 bytes, and the XRAM space on your chip is just 0x800 in length.
So the largest array the compiler can handle on your chip is 512 entries.
So this is why it won't work for you above this.
The standard library will only allow values up to 512. What you post has
been modified for larger values, without realising the reason for the limit
at this size. |
|
|
Marco27293
Joined: 09 May 2020 Posts: 126
|
|
Posted: Tue Jul 25, 2023 2:40 am |
|
|
Compiler is PCD v5.115
Could you suggest me any work around to make 2048 FFT possible ?
Any suggestion ? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19358
|
|
Posted: Tue Jul 25, 2023 2:58 am |
|
|
Use a chip with more X RAM. Problem is that any other route will be
terribly slow. The actual assembler used to make the code fast requires
the operational array is in this area. On (for example) the
dsPIC33EV256GM106, this area is 4* the size, so 2048 samples can
be used. |
|
|
Marco27293
Joined: 09 May 2020 Posts: 126
|
|
|
Marco27293
Joined: 09 May 2020 Posts: 126
|
|
Posted: Tue Jul 25, 2023 3:07 am |
|
|
Maybe, the problem is Y RAM and twiddle factors:
Code: |
Builds the FFT twiddle factors for an FFT of size 'fft_size'.
FFT twiddle factors saved to 'tw_y', which must be in the Y bank.
|
Any suggestion about it ? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19358
|
|
Posted: Tue Jul 25, 2023 4:58 am |
|
|
The assembler here says it only supports arrays up to 512 entries.
The code around it tests and limits to this size.
Now their notes say the limit is based on the size of the X Data RAM area,
but does not explain whether the size can be expanded on chips where this
area is larger. One would have to take the assembler apart and see what
happens when the array is over 512 entries. Probably easiest to run it up
in the MPLAB simulator and see what happens when this is done.
Honestly though FFT with an array larger than 512 entries is going to
be very slow. Do you genuinely need this?. Normally you only use
sizes like 32, 64 or 128 entries to give good speed.
Now if you are not worried about speed, there are non assembler C
libraries to do the same functions. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19358
|
|
Posted: Tue Jul 25, 2023 5:21 am |
|
|
OK.
A quick glance at the assembler, shows it ought to work with the larger
buffer. The only thing it that since it uses the DSP maths instructions, you
will get the math error interrupt trigger if there is a div by zero. So add a
trap for this and see if this is triggering. The other interrupt that could
trigger would be an address error if the pointers are somehow not
pointing to the right area. I'd add traps for both of these and see if either
triggers. Suspect your data is leading to a maths error on the larger array.
The twiddle factors should be OK. They are only half the size of the
main array, and Y is 0x9000 up. |
|
|
Marco27293
Joined: 09 May 2020 Posts: 126
|
|
Posted: Tue Jul 25, 2023 6:24 am |
|
|
I included pcd_traps.c.
I successfully monitored a dummy math error placed intentionally in my code:
Code: |
int8 k=0;
int16 p=99/k;
////
MATH FAULT PC:2CFE W0:63F W1:0 W2:5 W3:0 W4:63 W5:1 W6:108 W7:FDAA W8:3FFC W9:4000 W10:9FFC W11:400 W12:0 W13:1000 W14:2000 W15:7F80 DSRPAG:1 DSWPAG:1 TBLPAG:0 INTCON2:8000 INTCON3:0 INTCON4:0 CORCON:12A
STACK (0)
////
|
|
|
|
Marco27293
Joined: 09 May 2020 Posts: 126
|
|
Posted: Tue Jul 25, 2023 7:04 am |
|
|
Now I'm tryng to detect fft issue, but PCD traps does NOT trigger any interrupt...
How can I investigate my issue? |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|