📄 intfft_brin.c
字号:
TempReA = ReArray[indexA];
TempReB = ReArray[indexB];
// Calculate new value for ReArray[indexA]
TempL.l = (long)TempReA + TempReB;
if ((TempL.l < 0)&&(0x01 & TempL.b[3]))
TempReA2 = (TempL.l >> 1) + 1;
else TempReA2 = TempL.l >> 1;
// Calculate new value for ReArray[indexB]
TempL.l = (long)TempReA - TempReB;
if ((TempL.l < 0)&&(0x01 & TempL.b[3]))
ReArray[indexB] = (TempL.l >> 1) + 1;
else ReArray[indexB] = TempL.l >> 1;
ReArray[indexA] = TempReA2;
ImArray[indexA] = 0; // set Imaginary locations to '0'
ImArray[indexB] = 0;
indexA = indexB + 1;
}
// END OF FIRST STAGE
while (stage <= NUM_FFT/2)
{
indexA = 0;
sin_index = 0;
for (g_cnt = 0; g_cnt < group; g_cnt++)
{
for (s_cnt = 0; s_cnt < stage; s_cnt++)
{
indexB = indexA + stage;
TempReA = ReArray[indexA];
TempReB = ReArray[indexB];
TempImA = ImArray[indexA];
TempImB = ImArray[indexB];
// The following first checks for the special cases when the angle "x" is
// equal to either 0 or pi/2 radians. In these cases, unnecessary
// multiplications have been removed to improve the processing speed.
if (sin_index == 0) // corresponds to "x" = 0 radians
{
// Calculate new value for ReArray[indexA]
TempL.l = (long)TempReA + TempReB;
if ((TempL.l < 0)&&(0x01 & TempL.b[3]))
TempReA2 = (TempL.l >> 1) + 1;
else TempReA2 = TempL.l >> 1;
// Calculate new value for ReArray[indexB]
TempL.l = (long)TempReA - TempReB;
if ((TempL.l < 0)&&(0x01 & TempL.b[3]))
TempReB2 = (TempL.l >> 1) + 1;
else TempReB2 = TempL.l >> 1;
// Calculate new value for ImArray[indexB]
TempL.l = (long)TempImA - TempImB;
if ((TempL.l < 0)&&(0x01 & TempL.b[3]))
TempImB = (TempL.l >> 1) + 1;
else TempImB = TempL.l >> 1;
// Calculate new value for ImArray[indexA]
TempL.l = (long)TempImA + TempImB;
if ((TempL.l < 0)&&(0x01 & TempL.b[3]))
TempImA = (TempL.l >> 1) + 1;
else TempImA = TempL.l >> 1;
}
else if (sin_index == NUM_FFT/4) // corresponds to "x" = pi/2 radians
{
// Calculate new value for ReArray[indexB]
TempL.l = (long)TempReA - TempImB;
if ((TempL.l < 0)&&(0x01 & TempL.b[3]))
TempReB2 = (TempL.l >> 1) + 1;
else TempReB2 = TempL.l >> 1;
// Calculate new value for ReArray[indexA]
TempL.l = (long)TempReA + TempImB;
if ((TempL.l < 0)&&(0x01 & TempL.b[3]))
TempReA2 = (TempL.l >> 1) + 1;
else TempReA2 = TempL.l >> 1;
// Calculate new value for ImArray[indexB]
TempL.l = (long)TempImA + TempReB;
if ((TempL.l < 0)&&(0x01 & TempL.b[3]))
TempImB = (TempL.l >> 1) + 1;
else TempImB = TempL.l >> 1;
// Calculate new value for ImArray[indexA]
TempL.l = (long)TempImA - TempReB;
if ((TempL.l < 0)&&(0x01 & TempL.b[3]))
TempImA = (TempL.l >> 1) + 1;
else TempImA = TempL.l >> 1;
}
else
{
// If no multiplication shortcuts can be taken, the SIN and COS
// values for the Butterfly calculation are fetched from the
// SinTable[] array.
if (sin_index > NUM_FFT/4)
{
SinVal = SinTable[(NUM_FFT/2) - sin_index];
CosVal = -SinTable[sin_index - (NUM_FFT/4)];
}
else
{
SinVal = SinTable[sin_index];
CosVal = SinTable[(NUM_FFT/4) - sin_index];
}
// The SIN and COS values are used here to calculate part of the
// Butterfly equation
ReTwid.l = ((long)TempReB * CosVal) +
((long)TempImB * SinVal);
ImTwid.l = ((long)TempImB * CosVal) -
((long)TempReB * SinVal);
// Using the values calculated above, the new variables
// are computed
// Calculate new value for ReArray[indexA]
TempL.i[1] = 0;
TempL.i[0] = TempReA;
TempL.l = TempL.l >> 1;
ReTwid.l += TempL.l;
if ((ReTwid.l < 0)&&(ReTwid.i[1]))
TempReA2 = ReTwid.i[0] + 1;
else TempReA2 = ReTwid.i[0];
// Calculate new value for ReArray[indexB]
TempL.l = TempL.l << 1;
TempL.l -= ReTwid.l;
if ((TempL.l < 0)&&(TempL.i[1]))
TempReB2 = TempL.i[0] + 1;
else TempReB2 = TempL.i[0];
// Calculate new value for ImArray[indexA]
TempL.i[1] = 0;
TempL.i[0] = TempImA;
TempL.l = TempL.l >> 1;
ImTwid.l += TempL.l;
if ((ImTwid.l < 0)&&(ImTwid.i[1]))
TempImA = ImTwid.i[0] + 1;
else TempImA = ImTwid.i[0];
// Calculate new value for ImArray[indexB]
TempL.l = TempL.l << 1;
TempL.l -= ImTwid.l;
if ((TempL.l < 0)&&(TempL.i[1]))
TempImB = TempL.i[0] + 1;
else TempImB = TempL.i[0];
}
ReArray[indexA] = TempReA2;
ReArray[indexB] = TempReB2;
ImArray[indexA] = TempImA;
ImArray[indexB] = TempImB;
indexA++;
sin_index += group;
} // END of stage FOR loop (s_cnt)
indexA = indexB + 1;
sin_index = 0;
} // END of group FOR loop (g_cnt)
group /= 2;
stage *= 2;
} // END of While loop
} // END Int_FFT
//-----------------------------------------------------------------------------
// Initialization Routines
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// PORT_Init
//-----------------------------------------------------------------------------
//
// Configure the Crossbar and GPIO ports
//
void PORT_Init (void)
{
char old_SFRPAGE = SFRPAGE; // Store current SFRPAGE
SFRPAGE = CONFIG_PAGE; // Switch to configuration page
XBR0 = 0x04; // Enable UART0 on crossbar
XBR1 = 0x00;
XBR2 = 0x40; // Enable crossbar and weak pull-ups
P0MDOUT |= 0x01; // Set TX0 pin to push-pull
SFRPAGE = old_SFRPAGE; // restore SFRPAGE
}
//-----------------------------------------------------------------------------
// UART0_Init
//-----------------------------------------------------------------------------
//
// Configure the UART0 using Timer1, for <baudrate> and 8-N-1. In order to
// increase the clocking flexibility of Timer0, Timer1 is configured to count
// SYSCLKs.
//
// To use this routine SYSCLK/BAUDRATE/16 must be less than 256. For example,
// if SYSCLK = 50 MHz, the lowest standard baud rate supported by this
// routine is 19,200 bps.
void UART0_Init (void)
{
char old_SFRPAGE = SFRPAGE; // Store current SFRPAGE
SFRPAGE = UART0_PAGE; // Switch to UART0 Page
SCON0 = 0x50; // SCON0: mode 0, 8-bit UART, enable RX
SSTA0 = 0x10; // Timer 1 generates UART0 baud rate and
// UART0 baud rate divide by two disabled
SFRPAGE = TIMER01_PAGE;
TMOD &= ~0xF0;
TMOD |= 0x20; // TMOD: timer 1, mode 2, 8-bit reload
TH1 = -(SYSCLK/BAUDRATE/16); // Set the Timer1 reload value
// When using a low baud rate, this
// equation should be checked to ensure
// that the reload value will fit in
// 8-bits.
CKCON |= 0x10; // T1M = 1; SCA1:0 = xx
TL1 = TH1; // initialize Timer1
TR1 = 1; // start Timer1
SFRPAGE = UART0_PAGE;
TI0 = 1; // Indicate TX0 ready
SFRPAGE = old_SFRPAGE; // restore SFRPAGE
}
//-----------------------------------------------------------------------------
// SYSCLK_Init
//-----------------------------------------------------------------------------
//
// This routine initializes the system clock to use an external 22.1184 MHz
// crystal oscillator multiplied by a factor of 9/4 using the PLL as its
// clock source. The resulting frequency is 22.1184 MHz * 9/4 = 49.7664 MHz
//
void SYSCLK_Init (void)
{
int i; // delay counter
char old_SFRPAGE = SFRPAGE; // Store current SFRPAGE
SFRPAGE = CONFIG_PAGE; // set SFR page
OSCXCN = 0x67; // start external oscillator with
// 22.1184MHz crystal
for (i=0; i < 256; i++) ; // Wait for osc. to start up
while (!(OSCXCN & 0x80)) ; // Wait for crystal osc. to settle
CLKSEL = 0x01; // Select the external osc. as
// the SYSCLK source
OSCICN = 0x00; // Disable the internal osc.
//Turn on the PLL and increase the system clock by a factor of M/N = 9/4
SFRPAGE = PLL0_PAGE;
PLL0CN = 0x04; // Set PLL source as external osc.
SFRPAGE = LEGACY_PAGE;
FLSCL = 0x10; // Set FLASH read time for 50MHz clk
// or less
SFRPAGE = PLL0_PAGE;
PLL0CN |= 0x01; // Enable Power to PLL
PLL0DIV = 0x04; // Set Pre-divide value to N (N = 4)
PLL0FLT = 0x01; // Set the PLL filter register for
// a reference clock from 19 - 30 MHz
// and an output clock from 45 - 80 MHz
PLL0MUL = 0x09; // Multiply SYSCLK by M (M = 9)
for (i=0; i < 256; i++) ; // Wait at least 5us
PLL0CN |= 0x02; // Enable the PLL
while(!(PLL0CN & 0x10)); // Wait until PLL frequency is locked
CLKSEL = 0x02; // Select PLL as SYSCLK source
SFRPAGE = old_SFRPAGE; // restore SFRPAGE
}
//-----------------------------------------------------------------------------
// ADC0_Init
//-----------------------------------------------------------------------------
//
// Configure ADC0 to use Timer3 overflows as conversion source, to
// generate an interrupt on conversion complete, and to use left-justified
// output mode. Enables ADC0 end of conversion interrupt. Enables ADC0.
//
void ADC0_Init (void)
{
char old_SFRPAGE = SFRPAGE; // Store current SFRPAGE
SFRPAGE = ADC0_PAGE; // Switch to ADC0 Setup Page
ADC0CN = 0x05; // ADC disabled; normal tracking
// mode; ADC conversions are initiated
// on overflow of Timer3, left-justify
REF0CN = 0x03; // enable on-chip VREF and output buffer
AMX0CF = 0x00; // Single-ended AIN0.0 input
AMX0SL = 0x00;
ADC0CF = (SYSCLK/(2*2500000)) << 3; // ADC conversion clock <= 2.5MHz
ADC0CF |= 0x00; // PGA gain = 1
AD0EN = 1; // enable ADC0
SFRPAGE = old_SFRPAGE; // restore SFRPAGE
}
//-----------------------------------------------------------------------------
// TIMER3_Init
//-----------------------------------------------------------------------------
//
// Configure Timer3 to auto-reload at interval specified by <counts> (no
// interrupt generated) using SYSCLK as its time base.
//
void TIMER3_Init (int counts)
{
char old_SFRPAGE = SFRPAGE; // Save Current SFR page
SFRPAGE = TMR3_PAGE; // Switch to Timer3 Setup Page
TMR3CN = 0x00; // Stop Timer3; Clear TF3
TMR3CF = 0x08; // use SYSCLK as timebase
RCAP3 = -counts; // Init reload values
TMR3 = 0xffff; // set to reload immediately
EIE2 &= ~0x01; // disable Timer3 interrupts
TR3 = 0x01; // start Timer3
SFRPAGE = old_SFRPAGE; // restore SFRPAGE
}
//-----------------------------------------------------------------------------
// Interrupt Service Routines
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// ADC0_ISR
//-----------------------------------------------------------------------------
//
// ADC end-of-conversion ISR
// The ADC sample is stored in memory, and an index variable is incremented.
// If enough samples have been taken to process the FFT, then a flag is set,
// and ADC interrupts are disabled until the next set is requested.
//
void ADC0_ISR (void) interrupt 15 using 3
{
AD0INT = 0; // clear ADC conversion complete
// flag
Real[ADC_Index] = ADC0; // store ADC value
ADC_Index++; // Increment the index into memory
if (ADC_Index >= NUM_FFT) // If enough samples have been collected
{
Conversion_Set_Complete = 1; // Tell the Main Routine and...
EIE2 &= ~0x02; // disable ADC interrupts
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -