/*
 * Task_FFT.c
 *
 *  Created on: 2017. 6. 7.
 *      Author: Mirae
 */




//Free RTOS

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


#define mainTASK_LED                        ( 0 )
#define MyFFT_TEST_BUFFER_LENGTH        MyFFT_INPUT_LENGTH

/* Declare array MyFFT_TestBuffer[] using the typedef MyFFT_Workspace_t and
with compiler directive __no_init.  With large arrays, this avoids a long
initialisation time that can cause problems with some debuggers. */
#ifdef __ICC430__
__no_init MyFFT_Workspace_t MyFFT_TestBuffer[MyFFT_TEST_BUFFER_LENGTH];
#else
MyFFT_Workspace_t MyFFT_TestBuffer[MyFFT_TEST_BUFFER_LENGTH];
#endif

void vTask_FFT(void)
{
    volatile static int ErrorCount=0; // Note. static used for easier debugging
        WDTCTL = WDTPW +WDTHOLD; // disable watchdog

        // Example 1.  Calculate a DFT using input data from MyFFT_TestBuffer[]

        /* First, array MyFFT_TestBuffer[] is filled with test data. In a typical
        application, this might be done using an interrupt service routine, for
        example, with ADC values being read at regular intervals using a timer.

        However, in this example, MyFFT_TEST_BUFFER_LENGTH = MyFFT_INPUT_LENGTH, so
        the buffer can be filled directly by copying data from the tables provided
        by MyFFT_TestHarness.c. The advantage of using the test tables is that once
        the DFT has been calculated, it can be checked against a known result. */

        int i;
        for(i=0; i<MyFFT_TEST_BUFFER_LENGTH; i++)
        {
            MyFFT_TestBuffer[i]=MyFFT_SampledR[i]; // fill with known data
        }

        /* Next, MyFFT_Init() is called with a pointer to MyFFT_TestBuffer[]
        along with the array length. This allows the FFT methods to detect when
        pointers increment past the end of MyFFT_TestBuffer[] and wrap them back to
        the start.

        The MyFFT_Init() method only needs to be called once after a reset, or when
        the address range of the input buffer supplying data to the FFT changes.

        In effect, this allows continuous writing to array MyFFT_TestBuffer[] in a
        circular fashion. At the same time it allows the FFT to be calculated at
        an arbitrary offset.

        Note. FFT sampling (copying data from the MyFFT_TestBuffer[] to the FFT
        workspace MyFFT_ResultR[] and MyFFT_ResultI[]) only takes around 3% of the
        overall FFT calculation time and is carried out in a forward direction
        beginning at the specified offset. Therefore, for moderate acquisition
        rates, a MyFFT_TestBuffer[] of equal length to the FFT input length may be
        sufficient to allow continuous acquisition. If higher data acquisition
        rates are required, the length of the MyFFT_TestBuffer[] can be extended
        as required until there are enough CPU cycles in-hand to overcome any
        latency in the FFT sampling process. */

        MyFFT_Init(MyFFT_TestBuffer, MyFFT_TEST_BUFFER_LENGTH); // setup FFT input range

        /* Only after MyFFT_Init() has been called may MyFFT_CalculateDft() be called.
        As mentioned, MyFFT_CalculateDft() can perform a DFT from an arbitrary point
        within MyFFT_TestBuffer[] by passing it the required start address.

        Data from the MyFFT_TestBuffer[] is then sampled, beginning at the specified
        start address and wrapping back through the buffer start as required.

        E.g.  If the length of MyFFT_TestBuffer[] is 128 samples and the FFT input
        length is 32 samples. Calling MyFFT_CalculateDft(MyFFT_TestBuffer+124) would
        cause the first 4 samples to be read from offsets 124, 125, 126 and 127.
        The MyFFT_Sample() method would then detect that it's internal copy pointer
        had reached the address pointed by MyFFT_input_buffer_end. The copy pointer
        would then be wrapped back to the address pointed by MyFFT_input_buffer_start
        and the remaining input samples would be read from offsets 0,1,2,3... etc
        with the last sample being read from offset 27.

        This system allows the data acquisition process to be asynchronous with
        respect to DFT calculation.  A DFT result can thus be obtained whenever
        and as often as required, allowing for efficient overlapping and averaging
        algorithms as well as improved compatibility with multi-task environments.

        In this example, a single DFT will be calculated at zero offset within the
        array MyFFT_TestBuffer[]. Calling MyFFT_CalculateDft() initiates all required
        processes according to the specified FFT design. */

        MyFFT_CalculateDft(MyFFT_TestBuffer+0); // Calculate DFT at zero buffer offset

        /* Alternatively, if an FFT is required from say half way along the buffer,
        the call to MyFFT_CalculateDft() would be as follows.

            MyFFT_CalculateDft(MyFFT_TestBuffer+MyFFT_TEST_BUFFER_LENGTH/2);

        When MyFFT_CalculateDft() has finished, the DFT output will be available in
        MyFFT_ResultR[] and MyFFT_ResultI[] corresponding to the Real and Imaginary
        parts of each complex result.

        In most cases the DFT result will need converting into a different format
        before use. E.g. Magnitude. This might also be done in-place, overwriting
        the complex DFT result, so no extra storage would be needed ....

            MyFFT_ResultR(k) = Sqrt( MyFFT_ResultR(k)^2 + MyFFT_ResultI(k)^2 )
            where k = 0, 1, 2, 3, ..... MyFFT_INPUT_LENGTH-1

            Note. If creating an audio spectrum-analyser type display, for example
            to be shown on a graphical LCD, only the first MyFFT_INPUT_LENGTH/2+1
            results need be calculated. These correspond to DC and all frequencies
            up to and including Nyquist, spaced SampleRate/MyFFT_INPUT_LENGTH Hz apart.

        On an integer processor, the final precision and dynamic range required by
        the application can drastically influence how result conversion can best
        be accomplished.  For example, in the above example it may not be necessary
        to calculate the square root if the intention is to later convert the result
        to a dB value using a lookup-table or when all that is required is a value
        proportional to signal power rather than an absolute result.

        To finish this example, the DFT result is checked against pre-calculated
        complex values by calling MyFFT_TestHarnessCompareTransformed(). This method
        returns the number of errors found. There should be none! */

        ErrorCount=MyFFT_TestHarnessCompareTransformed();
        if(ErrorCount)
        {
            ErrorCount=ErrorCount; // set a break point here to check for errors
        }

        // Example 2.  Calling individual methods to calculate the DFT step-by-step.
        MyFFT_TestHarnessLoadSampled(); // load FFT workspace with test data.
        MyFFT_Window();                     // apply specified windowing function.
        MyFFT_Reorder();                        // arrange data in bit-reverse format.
        MyFFT_Transform();                  // calculate an in-place DFT of data.
        // check the complex FFT result against the expected values.
        ErrorCount=MyFFT_TestHarnessCompareTransformed();
        if(ErrorCount)
        {
            ErrorCount=ErrorCount; // set a break point here to check for errors
        }
        while(1); // set a break point here to indicate the test is complete

}
