First Publish. Works fine.

Dependents:   unzen_sample_lpcxpresso_4337_callbacks

unzen.cpp

Committer:
shorie
Date:
2016-05-07
Revision:
6:df928d55613b
Parent:
5:1cbfb7a9cd0c
Child:
8:63e098b779e9

File content as of revision 6:df928d55613b:

#include "algorithm"
#include "limits.h"

#include "unzen.h"
#include "unzen_hal.h"

namespace unzen 
{
    framework::framework()
    {

            // Clear all buffers        
        tx_int_buffer[0] = NULL;
        tx_int_buffer[1] = NULL;
        rx_int_buffer[0] = NULL;
        rx_int_buffer[1] = NULL;
        
        tx_left_buffer = NULL;
        tx_right_buffer = NULL;
        rx_left_buffer = NULL;
        rx_right_buffer = NULL;
 
            // Initialize all buffer
        buffer_index = 0;
        sample_index = 0;
        
            // Clear all callbacks
        pre_interrupt_callback = NULL;
        post_interrupt_callback = NULL;
        pre_process_callback = NULL;
        post_process_callback = NULL;
        
        process_callback = NULL;
        
            // Initialy block(buffer) size is 1.
        set_block_size( 1 );
        
            // Initialize I2S peripheral
        hal_i2s_setup();

            // Setup the interrupt for the I2S
        NVIC_SetVector(hal_get_i2s_irq_id(), (uint32_t)i2s_irq_handler);
        set_i2s_irq_priority(hal_get_i2s_irq_priority_level());
        NVIC_EnableIRQ(hal_get_i2s_irq_id());

            // Setup the interrupt for the process
        NVIC_SetVector(hal_get_process_irq_id(), (uint32_t)process_irq_handler);
        set_process_irq_priority(hal_get_process_irq_priority_level());
        NVIC_EnableIRQ(hal_get_process_irq_id());
        
    }

    error_type framework::set_block_size(  unsigned int new_block_size )
    {
        
        delete [] tx_int_buffer[0];
        delete [] tx_int_buffer[1];
        delete [] rx_int_buffer[0];
        delete [] rx_int_buffer[1];
        
        delete [] tx_left_buffer;
        delete [] tx_right_buffer;
        delete [] rx_left_buffer;
        delete [] rx_right_buffer;
        
        block_size = new_block_size;

        tx_int_buffer[0] = new int[ 2 * block_size ];
        tx_int_buffer[1] = new int[ 2 * block_size ];
        rx_int_buffer[0] = new int[ 2 * block_size ];
        rx_int_buffer[1] = new int[ 2 * block_size ];
        
        tx_left_buffer = new float[ block_size ];
        tx_right_buffer = new float[ block_size ];
        rx_left_buffer = new float[ block_size ];
        rx_right_buffer = new float[ block_size ];
 
            // error check
        if ( rx_int_buffer[0] == NULL |
             rx_int_buffer[1] == NULL |
             tx_int_buffer[0] == NULL |
             tx_int_buffer[1] == NULL |
             rx_right_buffer == NULL |
             tx_right_buffer == NULL |
             rx_left_buffer == NULL |
             tx_left_buffer == NULL )
        {   // if error, release all 
            delete [] tx_int_buffer[0];
            delete [] tx_int_buffer[1];
            delete [] rx_int_buffer[0];
            delete [] rx_int_buffer[1];
            
            delete [] tx_left_buffer;
            delete [] tx_right_buffer;
            delete [] rx_left_buffer;
            delete [] rx_right_buffer;
            
            tx_int_buffer[0] = NULL;
            tx_int_buffer[1] = NULL;
            rx_int_buffer[0] = NULL;
            rx_int_buffer[1] = NULL;
            
            tx_left_buffer = NULL;
            tx_right_buffer = NULL;
            rx_left_buffer = NULL;
            rx_right_buffer = NULL;
            
            return memory_allocation_error;
        }

            // clear blocks
        for ( int i=0; i<block_size*2; i++ )
        {

            tx_int_buffer[0][i] = 0;
            tx_int_buffer[1][i] = 0;
            rx_int_buffer[0][i] = 0;
            rx_int_buffer[1][i] = 0;
            
        }
            // clear blocks
        for ( int i=0; i<block_size ; i++ )
        {

            tx_left_buffer[i] = 0;
            tx_right_buffer[i] = 0;
            rx_left_buffer[i] = 0;
            rx_right_buffer[i] = 0;

        }
         
        return no_error;
    }

    void framework::start()
    {
            // synchronize with Word select signal, to process RX/TX as atomic timing.
        hal_i2s_pin_config_and_wait_ws();
        hal_i2s_start();
    }

    void framework::set_i2s_irq_priority( unsigned int pri )
    {
        NVIC_SetPriority(hal_get_process_irq_id(), pri);  // must be higher than PendSV of mbed-RTOS
        
    }
    
    void framework::set_process_irq_priority( unsigned int pri )
    {
        NVIC_SetPriority(hal_get_i2s_irq_id(), pri);      // must be higher than process IRQ

    }

    void framework::set_process_callback( void (* cb ) (float[], float[], float[], float[], unsigned int))
    { 
        process_callback = cb;
    }

    void framework::set_pre_interrupt_callback( void (* cb ) (void))
    { 
        pre_interrupt_callback = cb;
    }
    
    void framework::set_post_interrupt_callback( void (* cb ) (void))
    { 
        post_interrupt_callback = cb;
    }
    
    void framework::set_pre_process_callback( void (* cb ) (void))
    { 
        pre_process_callback = cb;
    }
    
    void framework::set_post_process_callback( void (* cb ) (void))
    { 
        post_process_callback = cb;
    }

    void framework::do_i2s_irq(void)
    {
            // if needed, call pre-interrupt call back
        if ( pre_interrupt_callback )
            pre_interrupt_callback();
            
            // irq is handled only when the buffer is correctly allocated    
        if (tx_left_buffer)
        {
            int sample;
            
                // check how many data have to be transmimted per interrupt. 
            for ( int i=0; i<hal_data_per_sample(); i++ )
            {
                    // copy received data to buffer
                hal_get_i2s_rx_data( sample );
                rx_int_buffer[buffer_index][sample_index] = sample;
                
                    // copy buffer data to transmit register
                sample = tx_int_buffer[buffer_index][sample_index];
                hal_put_i2s_tx_data( sample );
                
                    // increment index
                sample_index ++;
            }
            
                // Implementation of the double buffer algorithm.
                // if buffer transfer is complete, swap the buffer
            if (sample_index >= block_size * 2)
            {
                    // index for the signal processing
                process_index = buffer_index;

                    // swap buffer
                if ( buffer_index == 0 )
                    buffer_index = 1;
                else
                    buffer_index = 0;

                    // rewind sample index
                sample_index = 0;

                    // Trigger interrupt for signal processing
                NVIC->STIR = hal_get_process_irq_id();       
            }
        }

            // if needed, call post-interrupt call back
        if ( post_interrupt_callback )
            post_interrupt_callback();
            
    }

    void framework::do_process_irq(void)
    {
            // If needed, call the pre-process hook
        if ( pre_process_callback )
            pre_process_callback();
            
            // Only when the process_call back is registered.
        if ( process_callback )
        {
            int j = 0;
                
                // Format conversion.
                // -- premuted from LRLRLR... to LLL.., RRR...
                // -- convert from fixed point to floating point
                // -- scale down as range of [-1, 1)
            for ( int i=0; i<block_size; i++ )
            {
                rx_left_buffer[i]  = rx_int_buffer[process_index][j++]/ -(float)INT_MIN;
                rx_right_buffer[i] = rx_int_buffer[process_index][j++]/ -(float)INT_MIN;
            }
                
            process_callback
            (
                rx_left_buffer,
                rx_right_buffer,
                tx_left_buffer,
                tx_right_buffer,
                block_size
            );
                
                // Format conversion.
                // -- premuted from LLL.., RRR... to LRLRLR...
                // -- convert from floating point to fixed point
                // -- scale up from range of [-1, 1)
            j = 0;
            for ( int i=0; i<block_size; i++ )
            {
                tx_int_buffer[process_index][j++] = tx_left_buffer[i]  * -(float)INT_MIN ;
                tx_int_buffer[process_index][j++] = tx_right_buffer[i] * -(float)INT_MIN ;
            }
    
        }

            // if needed, call post-process callback
        if ( post_process_callback )
            post_process_callback();
    }
    
    void framework::process_irq_handler()
    {
        framework::get()->do_process_irq();
    }
    
    void framework::i2s_irq_handler()
    {
        framework::get()->do_i2s_irq();
    }
     
     
     
     
     
 
}