First Publish. Works fine.

Dependents:   unzen_sample_lpcxpresso_4337_callbacks

unzen.cpp

Committer:
shorie
Date:
2016-04-10
Revision:
0:5ac19c994288
Child:
1:9710fb328a08

File content as of revision 0:5ac19c994288:

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

namespace unzen 
{
    framework::framework()
    {
        
        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;
 
        buffer_index = 0;
        tx_sample_index = 0;
        rx_sample_index = 0;
        
        pre_interrupt_callback = NULL;
        post_interrupt_callback = NULL;
        pre_process_callback = NULL;
        post_process_callback = NULL;
        
        process_callback = NULL;
        
        set_block_size( 1 );
        
        hal_i2s_setup();

        NVIC_SetVector(hal_get_i2s_irq_id(), (uint32_t)i2s_irq_handler);
        NVIC_EnableIRQ(hal_get_i2s_irq_id());

        NVIC_SetVector(hal_get_process_irq_id(), (uint32_t)process_irq_handler);
        NVIC_EnableIRQ(hal_get_process_irq_id());

            // to enable block processing, I2S IRQ priority must be higher than process IRQ
        set_i2s_irq_priority(hal_get_lowest_priority_level() - 1);
        set_process_irq_priority(hal_get_lowest_priority_level() - 2);
        
    }

    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()
    {
        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 ( 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 transmimt per interrupt. 
            if ( hal_data_per_sample() >0 )     // In case single or multiple word 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][rx_sample_index++] = sample;
                        // copy buffer data to transmit register
                    hal_set_i2s_tx_data( tx_int_buffer[buffer_index][rx_sample_index++] );
                }
            }
            else    // if the hal_data_per_smple() is 0, the data have to push multiple time.
            {
                if ( hal_get_i2s_rx_data( sample ) )
                {
                        // data have to be pushed to buffer only when the hal_get_i2s_rx_data() returns non-zero
                    rx_int_buffer[buffer_index][rx_sample_index++] = sample;
                }
                if ( hal_set_i2s_tx_data( tx_int_buffer[buffer_index][tx_sample_index] ))
                        // pointer can be updated only when hal_set_i2s_tx_data() returns non_zero. 
                    tx_sample_index ++;

            }
                // Implementation of the double buffer algorithm.
                // if buffer transfer is complete, swap the buffer
            if (rx_sample_index > block_size * 2 & rx_sample_index > block_size * 2)
            {
                    // index for the signal processing
                process_index = buffer_index;
                    // swap buffer
                buffer_index = 1 - buffer_index ; // reverse 1 <-> 0
                tx_sample_index = 0;
                rx_sample_index = 0;

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

        if ( post_interrupt_callback )
            post_interrupt_callback();
    }

    void framework::do_process_irq(void)
    {
        if ( pre_process_callback )
            pre_process_callback();
            
        if ( process_callback )
        {
            int j = 0;
                
                // convert from fixed point to floating point
                // also scale down
            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
                );
                
                // convert from floating point to fixed point
                // also scale up
            j = 0;
            for ( int i=0; i<block_size; i++ )
            {
                tx_int_buffer[process_index][j++] = - tx_left_buffer[i] * INT_MIN ;
                tx_int_buffer[process_index][j++] = - tx_right_buffer[i] * INT_MIN ;
            }
    
        }

        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();
    }
        
}