First Publish. Works fine.

Dependents:   unzen_sample_lpcxpresso_4337_callbacks

Revision:
0:5ac19c994288
Child:
1:9710fb328a08
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/unzen.cpp	Sun Apr 10 12:37:10 2016 +0000
@@ -0,0 +1,275 @@
+#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();
+    }
+        
+}
+    
\ No newline at end of file