// MyFFT.c (Created by FFTDesigner - Version 3.70)

/******************************************************************************

COPYRIGHT.  This software is Copyright ¨Ï 2011 RHDC Services Ltd.

        !  DO NOT EDIT THIS FILE AS IT MAY BE OVERWRITTEN BY
        THE DESIGNER RESULTING IN YOUR CHANGES BEING LOST  !

DISTRIBUTION.  This software may NOT be distributed to a third party without
prior written approval of the copyright holder. Please see the FFT Designer
End User Licence Agreement for details about distribution in object-code form.

DISCLAIMER.  This software is provided "AS IS", without express or implied
warranty.  In no event shall the copyright holder, author(s) or provider(s)
of this software be held liable for any damages arising from its use.

        FFTLength ................................ 8
        WindowType ............................... Kaiser
        WindowLoss (dB) .......................... 8.27
        Equivalent Noise Bandwidth ENBW (Bins) ... 2.052
        Incoherent Power Gain .................... 0.3056
        Coherent Power Gain ...................... 0.1489
        WindowAlpha .............................. 3
        Language ................................. MSP430 Extended C
        Algorithm ................................ Integer (16 Bit)
        Use Shift Division ....................... True
        Use Direct MPY32 Access .................. True

NOTE. When option "Use Direct MPY32 Access" is True, this software will make
direct use of the MPY32 hardware multiplier module including its configuration
registers as well as the operand and result registers.  Therefore, if any ISR
needs to be active whilst the FFT methods are in use, they must comply with
either (a) or (b) below.

   (a). They must not use the MPY32 hardware multiplier module.
   (b). They must perform a full MPY32 context save and restore.

Refer to section "32-Bit Hardware Multiplier", sub-section "Using Interrupts"
of the MSP430x5xx User Guide for more details.

******************************************************************************/

#include	<msp430.h>
#include "MyFFT.h"

#ifdef __ICC430__
__no_init MyFFT_Workspace_t MyFFT_ResultR[MyFFT_INPUT_LENGTH];
__no_init MyFFT_Workspace_t MyFFT_ResultI[MyFFT_INPUT_LENGTH];
#else
MyFFT_Workspace_t MyFFT_ResultR[MyFFT_INPUT_LENGTH];
MyFFT_Workspace_t MyFFT_ResultI[MyFFT_INPUT_LENGTH];
#endif
MyFFT_Workspace_t * MyFFT_input_buffer_start;
MyFFT_Workspace_t * MyFFT_input_buffer_end;

void MyFFT_Sample(MyFFT_Workspace_t * input_buffer)
{
	/* This method copies MyFFT_INPUT_LENGTH samples beginning at the address
	pointed by input_buffer to the MyFFT_ResultR[] array and also zeros array
	MyFFT_ResultI[].  The input data is assumed to be in Q15 format having an
	allowed physical range of +32767 to -32768 corresponding to an arithmetic
	range of +0.999969482421875 and -1 respectively.

	Do not call this method before calling MyFFT_Init().

	Provided MyFFT_Init() has been called correctly, this method is compatible
	with input data stored in a circular buffer. In this case, if the copying
	process reaches the address pointed by MyFFT_input_buffer_end, copying will
	continue from the address pointed by MyFFT_input_buffer_start. */

	MyFFT_PRIM00S(input_buffer); // Sample from address pointed by input_buffer
}

void MyFFT_Window(void)
{
	/* This method applies the mirrored windowing function held in MyFFT_win[]
	to the contents of MyFFT_ResultR[], saving the result back to MyFFT_ResultR[].

	MyFFT_ResultR[k] = MyFFT_ResultR[k] * MyFFT_win[k] when k<MyFFT_INPUT_LENGTH/2
	otherwise, MyFFT_ResultR[k] = MyFFT_ResultR[k] * MyFFT_win[MyFFT_INPUT_LENGTH-k-1]

	Note. Both operands are interpreted as Q15 format signed integers having an
	allowed physical range of +32767 to -32768 that corresponds to an arithmetic
	range of +0.999969482421875 and -1 respectively.
	
	Therefore, the multiplication result is not subject to overflow, even when
	a rectangular window function is applied to a full range input. In practice,
	the result will be subject to attenuation due to the inherent properties of
	any non-rectangular window function. */

	MyFFT_PRIM00W; // Apply pre-calculated windowing function to the data.
}

void MyFFT_Reorder(void)
{
	/* This method performs an in-place reordering of the FFT workspace from
	Natural-Order into Bit-Reversed order using the Gold-Rader algorithm. This
	method must be called before calling MyFFT_Transform() which requires input
	data to be in bit-reversed order. */

	MyFFT_PRIM00R; // Reorder data using the Gold-Rader Bit Reverse Algorithm.
}

#ifdef __ICC430__
#if (__VER__ >= 650 && __VER__ < 700)
#pragma message("Note. MyFFT_Transform() optimisation level for this compiler version has been set to medium")
#pragma optimize=medium // force optimization level for compiler versions 6.5 to 7.0
#endif
#endif

void MyFFT_Transform(void)
{
	/* This method calculates an in-place Discrete Fourier Transform using the
	Cooley-Tukey Decimation-In-Time (DIT) Radix-2 algorithm. Input data must be
	in bit-reversed order and may be Real or Complex. Output values are complex
	and are in Natural order. I.e.

	Frequency Bins 0(DC), 1, 2 ... etc = Result[0], Result[1], Result[2] ... etc

	In-Place computation means the input (stored in MyFFT_ResultR, MyFFT_ResultI)
	is overwritten during the calculation process.

	Note. Input values are interpreted as Q15 format signed integers having an
	allowed physical range of +32767 to -32768 corresponding to an arithmetic
	range of +0.999969482421875 and -1 respectively.  The DFT result is scaled
	by 1/MyFFT_INPUT_LENGTH during the calculation process to prevent saturation
	and to ensure the output fits within the original storage type.

	No post-processing other than the above scaling is applied by this method.
	The result is left in complex form and may subsequently be converted to
	Magnitude or Phase etc by application software. */

	MyFFT_PRIM00T; // Cooley-Tukey DIT Radix-2 Discrete Fourier Transform.
}

void MyFFT_CalculateDft(MyFFT_Workspace_t * input_buffer)
{
	/* This method performs all the required steps to calculate a Discrete
	Fourier Transform (DFT) including ...

	1.	Sampling data from the address specified by input_buffer to the FFT
		workspace, with buffer wrapping as required.
	2.	Applying the specified windowing function prior to DFT calculation.
	3.	Arranging the input samples into the required bit-reverse order.
	4.	Calculation of the DFT using a Cooley-Tukey DIT Radix-2 Algorithm. */

	MyFFT_Sample(input_buffer);
	MyFFT_Window();
	MyFFT_Reorder();
	MyFFT_Transform();
}

void MyFFT_Init(MyFFT_Workspace_t * input_buffer_start, int input_buffer_length)
{
	/* This method must be called (once) before MyFFT_Sample() or MyFFT_Calculate()
	so that MyFFT_input_buffer_start and MyFFT_input_buffer_end can be initialised.
	
	These pointers define the allowed range of addresses from which data can be
	copied into the FFT workspace. Once they have been initialised, MyFFT_Sample()
	can check that data is being copied from the allowed input address range and
	wrap the copy pointer back to the start as required.  This allows the use of
	a circular input buffer from which the input data for the FFT can be sampled
	at an arbitrary offset. */

	MyFFT_input_buffer_start = input_buffer_start;
	MyFFT_input_buffer_end = input_buffer_start + input_buffer_length;
}
