First Publish. Works fine.

Dependents:   unzen_sample_lpcxpresso_4337_callbacks

unzen.h

Committer:
shorie
Date:
2016-05-08
Revision:
8:63e098b779e9
Parent:
3:707608830793
Child:
9:2da6ce640691

File content as of revision 8:63e098b779e9:

/**
* \brief header file for the unzen audio frame work 
* \arthur SeiichiHorie
* \date 6/Apr/2016
*/

#ifndef _unzen_h_
#define _unzen_h_

#include "mbed.h"
/**
 \brief audio framework name space. 
*/
namespace unzen 
{
    /**
      \brief error status type.
    */
    enum error_type {
        no_error,
        memory_allocation_error
        };
    
    /**
      \brief singleton style audio frame work. Create a object and execute the \ref framework::start() method.
    */
    class framework 
    {
    private:
            /**
                \constructor
                \details
                initialize the internal variables and set up all interrrupt / I2S related peripheral. 
                If needed, power up the peripheral, assign the clock and pins. 
                At the end of this constructor, the audio framework is ready to run, but still paused. 
                To start the real processing, call the \ref start method.
                
                Note that this constructor set the block size ( interval count which audio processing
                call back is called )
                as 1. If it is needed to use other value, call \ref set_brock_size() method. 
            */
        framework(void);
    public:
            /**
                \brief getting the singleton object for processing.
                \returns a framework type object.
                \details
                TO call the object method, use this method to retrieve the singleton object.
            */
        static framework * get() { static framework singleton; return &singleton ; }
        
            /**
                \brief set the interval interrupt count for each time call back is called. 
                \param block_size An integer parameter > 1. If set to n, for each n interrupts, the audio call back is called. 
                \returns show the error status
                \details
                This method re-allocate the internal buffer. Then, the memory allocation error could occur. To detect the 
                memory allocation error, use \ref get_error() method.
            */
        error_type set_block_size(  unsigned int new_block_size );
        
            /**
                \brief  the real audio signal transfer. Trigger the I2S interrupt and call the call back.
                */
        void start(void);

            /**
                \brief Set the user call back for audio processing.
                \param cb The call back function
                \details
                Set the call back function. This function is called for each time the rx buffer is filled. The call back has 5 parameters.
                \li left_rx  Received data from I2S rx port. Left data only. 
                \li right_rx Received data from I2S rx port. Right data only.
                \li left_tx  Buffer to fill the transmission data. This buffer mus be filled by call back. Left data only
                \li right_tx Buffer to fill the transmission data. This buffer mus be filled by call back. Right data only
                \li length   length of above buffers.
                
                The call back is called for each time interrupt comes n times. Where n is the value which is specified by \ref set_block_size() 
                function. This n is also passed to call back as above length parameter. By default, n is 1.
                
                Note that the call back is called at interrupt context. Not the thread level context.
                That mean, it is better to avoid to call mbed API except the mbed-RTOS API for interrupt handler.
                 
            */
        void set_process_callback( void (* cb ) (float[], float[], float[], float[], unsigned int));
        
            /**
                \brief Debug hook for interrupt handler. 
                \param cb A call back which is called at the beggining of I2S interrupt.
                \details
                Parameter cb is call at the beggining of the I2S interrupt. This call back can be 
                used to mesure the timing of interrupt by toggling the GPIO pin.
                
                Passing 0 to cb parameter let the framwork ignore the callback.
            */
        void set_pre_interrupt_callback( void (* cb ) (void));
        
            /**
                \brief Debug hook for interrupt handler. 
                \param cb A call back which is called at the end of I2S interrupt.
                \details
                Parameter cb is call at the end of the I2S interrupt. This call back can be 
                used to mesure the timing of interrupt by toggling the GPIO pin.
                
                Passing 0 to cb parameter let the framwork ignore the callback.
            */
        void set_post_interrupt_callback( void (* cb ) (void));
        
            /**
                \brief Debug hook for processing handler. 
                \param cb A call back which is called at the beggining of processing.
                \details
                Parameter cb is call at the beggining of the signal processing. This call back can be 
                used to mesure the load of CPU by toggling the GPIO pin.
                
                Passing 0 to cb parameter let the framwork ignore the callback.
            */
        void set_pre_process_callback( void (* cb ) (void));

            /**
                \brief Debug hook for processing handler. 
                \param cb A call back which is called at the end of processing.
                \details
                Parameter cb is call at the end of the signal processing. This call back can be 
                used to mesure the load of CPU by toggling the GPIO pin.
                
                Passing 0 to cb parameter let the framwork ignore the callback.
            */
        void set_post_process_callback( void (* cb ) (void));
        
            /**
                \brief optional priority control for I2S IRQ. 
                \param pri Priority of IRQ.
                \details
                This is optional control. Usually, user doesn't need to call this method.
                In case the framework has serious irq priority contention with other software, 
                this API help programmer to change the priority of the Unzen framework.
                
                Value must be acceptable to CMSIS NVIC_SetPriority(). For LPC4337, it is range of 0..7. The 0 is highest priority.

                
                By default, the framework set this priority as +2 higher than the lowest.
                
                The priority set by this API must be higher than priority set by \ref set_process_irq_priority
            */
        void set_i2s_irq_priority( unsigned int pri );
        
            /**
                \brief optional priority control for Signal Processing IRQ. 
                \param pri Priority of IRQ.
                \details
                This is optional control. Usually, user doesn't need to call this method.
                In case the framework has serious irq priority contention with other software, 
                this API help programmer to change the priority of the Unzen framework

                Value must be acceptable to CMSIS NVIC_SetPriority(). For LPC4337, it is range of 0..7. The 0 is highest priority.
                
                By default, the framework set this priority as +2 higher than the lowest.

            */
        void set_process_irq_priority( unsigned int pri );
        
    private:
        void (* pre_interrupt_callback )(void);
        void (* post_interrupt_callback )(void);
        void (* pre_process_callback )(void);
        void (* post_process_callback )(void);
        
        void (* process_callback )( float left_in[], float right_in[], float left_out[], float right_out[], unsigned int length );
        
            // Size of the blocks ( interval of interrupt to call process_callback. 1 means every interrupt. 2 means every 2 interrupt )
        int block_size;
        
            // Index for indentifying the buffer for interrupt. 0 or 1. 
        int buffer_index;
        
            // Index for indentifying the buffer for processing. 0 or 1. 
        int process_index;
        
            // next transfer position in buffer
        int sample_index;
        
            // buffer for interrupt handler.
            // data format is LRLR... 
        int *tx_int_buffer[2];
        int *rx_int_buffer[2];
        
            // buffers for passing 
        float * tx_left_buffer, * tx_right_buffer;
        float * rx_left_buffer, * rx_right_buffer;
                
            // real processing method.
        void do_i2s_irq(void);
        void do_process_irq(void);
        
            // handler for NIVC
        static void i2s_irq_handler();
        static void process_irq_handler();        
    };

        // Sampling Frequency of the umb_adau1361
    enum Fs_Type 
    {
        Fs_32, Fs_441, Fs_48, Fs_96
    } ;


/**
* \brief abstract audio codec controller.
* \details
*   This class is template for all codec classes
*/
    class codec_class
    {
    public:
            /**
            * \brief constructor.
            * \param controler Pass the I2C controler object.
            * \param Fs Sampling frequency.
            * \param Addr I2C device address. value range is from 0 to 127
            * \details
            *   initialize the internal variables.
            */
        codec_class( I2C * controler, Fs_Type Fs, unsigned int Addr );
        
            /**
            * \brief Actual initializer. 
            * \details
            *   Initialize the codec itself and start the conversion process.
            *   and configure for given parameter. 
            *
            *   Finally, set the input gain to 0dB.
            */
        virtual void start(void)=0;
        
            /**
            * \brief Set the line input gain and enable the relevant mixer.
            * \param left_gain Gain by dB. The gain value outside of the acceptable range will be saturated.
            * \param right_gain Gain by dB. The gain value outside of the acceptable range will be saturated.
            * \param mute set true to mute
            */
        virtual void set_line_input_gain(float left_gain, float right_gain, bool mute=false);
            /**
            * \brief Set the aux input gain and enable the relevant mixer.
            * \param left_gain Gain by dB. The gain value outside of the acceptable range will be saturated.
            * \param right_gain Gain by dB. The gain value outside of the acceptable range will be saturated.
            * \param mute set true to mute
            */
        virtual void set_aux_input_gain(float left_gain, float right_gain, bool mute=false);
            /**
            * \brief Set the mic input gain and enable the relevant mixer.
            * \param left_gain Gain by dB. The gain value outside of the acceptable range will be saturated.
            * \param right_gain Gain by dB. The gain value outside of the acceptable range will be saturated.
            * \param mute set true to mute
            */
        virtual void set_mic_input_gain(float left_gain, float right_gain, bool mute=false);
            /**
            * \brief Set the line output gain and enable the relevant mixer.
            * \param left_gain Gain by dB. The gain value outside of the acceptable range will be saturated.
            * \param right_gain Gain by dB. The gain value outside of the acceptable range will be saturated.
            * \param mute set true to mute
            */
        virtual void set_line_output_gain(float left_gain, float right_gain, bool mute=false);
            /**
            * \brief Set the headphone output gain and enable the relevant mixer.
            * \param left_gain Gain by dB. The gain value outside of the acceptable range will be saturated.
            * \param right_gain Gain by dB. The gain value outside of the acceptable range will be saturated.
            * \param mute set true to mute
            */
        virtual void set_hp_output_gain(float left_gain, float right_gain, bool mute=false);
    protected:
        I2C *i2c;
        unsigned int addr;
        Fs_Type fs;
    };


/**
* \brief ADAU1361 audio codec controller.
* \details
*   This class sends a set of command to control an ADAU1361 codec.
*   This class is template for all ADAU1361 based codec board.
*/
    class adau1361:public codec_class
    {
    public:
            /**
            * \brief constructor.
            * \param controler Pass the I2C controler object.
            * \param Fs Sampling frequency.
            * \param Addr I2C device address. value range is from 0 to 127
            * \details
            *   initialize the internal variables.
            */
        adau1361( I2C * controler, Fs_Type Fs, unsigned int Addr ):
            codec_class( controler, Fs, Addr ){};
        virtual void start(void);
            /**
            * \brief Set the line input gain and enable the relevant mixer.
            * \param left_gain Gain by dB. The gain value outside of the acceptable range will be saturated.
            * \param right_gain Gain by dB. The gain value outside of the acceptable range will be saturated.
            * \param mute set true to mute
            */
        virtual void set_line_input_gain(float left_gain, float right_gain, bool mute=false);
            /**
            * \brief Set the aux input gain and enable the relevant mixer.
            * \param left_gain Gain by dB. The gain value outside of the acceptable range will be saturated.
            * \param right_gain Gain by dB. The gain value outside of the acceptable range will be saturated.
            * \param mute set true to mute
            */
        virtual void set_aux_input_gain(float left_gain, float right_gain, bool mute=false);
            /**
            * \brief Set the line output gain and enable the relevant mixer.
            * \param left_gain Gain by dB. The gain value outside of the acceptable range will be saturated.
            * \param right_gain Gain by dB. The gain value outside of the acceptable range will be saturated.
            * \param mute set true to mute
            */
        virtual void set_line_output_gain(float left_gain, float right_gain, bool mute=false);
            /**
            * \brief Set the headphone output gain and enable the relevant mixer.
            * \param left_gain Gain by dB. The gain value outside of the acceptable range will be saturated.
            * \param right_gain Gain by dB. The gain value outside of the acceptable range will be saturated.
            * \param mute set true to mute
            */
        virtual void set_hp_output_gain(float left_gain, float right_gain, bool mute=false);
        
    protected:
        virtual void configure_pll(void)=0;
        virtual void configure_board(void)=0;
            /**
            *  Service function for the ADAu1361 board implementer.
            *
            * \brief send one command to ADAU1361.
            * \param command command data array. It have to have register addess of ADAU1361 in first two bytes. 
            * \param size number of bytes in the command, including the regsiter address. 
            * \details
            *   Send one complete command to ADAU3161 by I2C.
            */
        virtual void send_command( const char command[], int size );
            /**
            * \brief send one command to ADAU1361.
            * \param table command table. All commands are stored in one row. Each row has only 1 byte data after reg address.
            * \param rows number of the rows in the table.
            * \details
            *   Service function for the ADAu1361 board implementer.
            *
            *   Send a list of command to ADAU1361. All commands has 3 bytes length. That mean, after two byte register
            *   address, only 1 byte data payload is allowed. Commadns are sent by I2C
            */
        virtual void send_command_table( const char table[][3], int rows);
        
            /**
            * \brief wait until PLL locks.
            * \details
            *   Service function for the ADAu1361 board implementer.
            *
            *   Read the PLL status and repeat it until the PLL locks. 
            */
        virtual void wait_pll_lock(void);
    };

/**
* \brief UMB-ADAU1361-A audio codec board controller.
* \details
*   This class send a set of command to control an UMB-ADAU1361-A codec board.
*
*   The hardware desription is here. http://dsps.shop-pro.jp/?pid=82798273
*/
    class umb_adau1361a:public adau1361
    {
    public:
            /**
            * \brief constructor.
            * \param controler Pass the I2C controler object.
            * \param Fs Sampling frequency.
            * \param Addr I2C device address. value range is from 0 to 127
            * \details
            *   initialize the internal variables.
            */
        umb_adau1361a( I2C * controler, Fs_Type Fs = unzen::Fs_48, unsigned int Addr=0x38 ):
            adau1361( controler, Fs, Addr ){};
    protected:
            /**
            * \brief configuration of the PLL for the desired Fs.
            * \details
            *   Configure the PLL based on the given Fs and hardware clock configuration. 
            *   Fs is stored in fs member variable already. Hadrware clock have to be given
            *   from the circuit designer. For the UMB-ADAU1361-A, the clock is external 
            *   12MHz oscillator from the clock input. 
            */
        virtual void configure_pll(void);
            /**
            * \brief configuration of the the codec for UMB-ADAU1361-A
            * \details
            *   Configure Internal signal pass and parameters for UMB-ADAU1361.  
            *   The all pass-through signals are shut off. All cross channel signals are shut off. 
            *   Monoral output is disabled. 
            */
        virtual void configure_board(void);
    };



}

#endif