/**
 * \defgroup NCO 32bit NCO algorithm implementation
 * \ingroup libbfin32
 * \details
 * Implements the complex Numerically Controlled Oscillator. First, the TNCO32 variable
 * must be initialized by fr32_nco_init() function. And then, call fr32_nco() funciton
 * to generate the wave form.
 */
/*@{*/



/**
 * \file fr32_nco.h
 * \brief Numerically Controlled Oscillator
 * \details
 * Sine/Cosine algorithm by table lookup and approximation.
 *
 * \date 2014/Mar/22
 * \author takemasa
 */

#ifndef NCO_H_
#define NCO_H_

#ifdef __i386__
#include "fract_x86.h"
#else
#include <fract.h>
#endif

#include <limits.h>

/**
 * \brief NCO object type
 * \details
 * An object type of NCO. All NCO initialize parameter and internal state are packed into this object type.
 * Programmer should not read/write these values directory.
 *
 * Use fr32_nco_init to initialize this object.
 */
typedef struct {
	fract32 frequency;
	fract32 phase;
} TNCO32;

/**
 * \brief NCO object initialization
 * \param nco a pointer to the NCO management object variable to be initialized.
 * \param frequency the frequency
 * \details
 * initialize the given NCO object with parameter frequency.
 * This function have to be called once, before calling fr32_nco.
 * The internal phase is initialized as zero.
 *
 * The frequency parameter specify the incremental value for each sample output.
 * This normalized frequency can be obtained by following formula.
 *
 * \code
 * frequency_parameter = desired_frequency * 2^32 / Fs
 * where Fs is the sampling frequency.
 * \endcode
 *
 * For example, if the desired frequency is 1kHz and the Fs is 48kHz, the parameter is
 * 89478485 ( = 1000 * 2^32 / 48000 ).
 *
 * Note : The frequency parameter can be negative value. In this case, the
 * output signal represents the negative frequency.
 *
 *
 */
void fr32_nco_init ( TNCO32 * nco, fract32 frequency);

/**
 * \brief set up frequency of the NCO.
 * \param nco a pointer to the NCO management object variable.
 * \param frequency the new frequency to be set
 * \details
 * Change the frequency of the NCO. The change is effective immediately after this call.
 * While the frequency is changed, the phase is not changed. So, the wave forme is continuous
 * after changing frequency.
 *
 * The frequency parameter specify the incremental value for each sample output.
 * This normalized frequency can be obtained by following formula.
 *
 * \code
 * frequency_parameter = desired_frequency * 2^32 / Fs
 * where Fs is the sampling frequency.
 * \endcode
 *
 * For example, if the desired frequency is 1kHz and the Fs is 48kHz, the parameter is
 * 89478485 ( = 1000 * 2^32 / 48000 ).
 *
 * Note : The frequency parameter can be negative value. In this case, the
 * output signal represents the negative frequency.
 *
 */
void fr32_nco_set_freq( TNCO32 * nco, fract32 frequency);

/**
 * \brief get frequency of the NCO.
 * \param nco a pointer to the NCO management object variable.
 * \return NCO's running frequency
 * \details
 * Return the frequency setting of given NCO.
 * This normalized frequency can be obtained by following formula.
 *
 * \code
 * frequency = returned_value * Fs / 2^32
 * where Fs is the sampling frequency.
 * \endcode
 *
 * For example, if the returned value is 89478485, and the Fs is 48kHz, the frequency is
 * 1kHz ( = 89478485 * 48000 / 2^32 ).
 *
*/
fract32 fr32_nco_get_freq( TNCO32 * nco);

/**
 * \brief set up phase of the NCO.
 * \param nco a pointer to the NCO management object variable.
 * \param phase the new phase to be set
 * \details
 * The range of the parameter is [-(2^31) .. (2^31) -1 ) which represents  [-pi ... pi).
 *
 * There are no sommothing. So, the change of phase is always as step.
*/
void fr32_nco_set_phase( TNCO32 * nco, fract32 phase);

/**
 * \brief set phase of the NCO.
 * \param nco a pointer to the NCO management object variable.
 * \return internal phase.
 * \details
 * The range of the parameter is [-(2^31) .. (2^31) -1 ) which represents  [-pi ... pi).
*/

fract32 fr32_nco_get_phase( TNCO32 * nco);


/**
 * \brief Run the NCO
 * \param nco a pointer to the NCO management object variable.
 * \param c Output array. The value is based on the cosine function.
 * \param s Output array. The value is based on the sine function.
 * \param count number of the output. Both c[] and s[] will have count samples.
 * \details
 * The nco parameter have to be initialized by fr32_nco_init() funciton.
*/
void fr32_nco( TNCO32 *nco, fract32 c[], fract32 s[], int count );


#endif /* NCO_H_ */
/*@}*/
