First Publish. Works fine.

Dependents:   unzen_sample_LPC4088_quickstart

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers unzen.cpp Source File

unzen.cpp

00001 #include "algorithm"
00002 #include "limits.h"
00003 
00004 #include "unzen.h"
00005 #include "unzen_hal.h"
00006 
00007 namespace unzen 
00008 {
00009     Framework::Framework ()
00010     {
00011             // setup handle for the interrupt handler
00012         Framework::_fw = this;
00013 
00014             // Clear all buffers        
00015         _tx_int_buffer[0] = NULL;
00016         _tx_int_buffer[1] = NULL;
00017         _rx_int_buffer[0] = NULL;
00018         _rx_int_buffer[1] = NULL;
00019         
00020         _tx_left_buffer = NULL;
00021         _tx_right_buffer = NULL;
00022         _rx_left_buffer = NULL;
00023         _rx_right_buffer = NULL;
00024  
00025             // Initialize all buffer
00026         _buffer_index = 0;
00027         _sample_index = 0;
00028         
00029             // Clear all callbacks
00030         _pre_interrupt_callback = NULL;
00031         _post_interrupt_callback = NULL;
00032         _pre_process_callback = NULL;
00033         _post_process_callback = NULL;
00034         
00035         _process_callback = NULL;
00036 
00037         
00038             // Initialy block(buffer) size is 1.
00039         set_block_size( 1 );
00040         
00041             // Initialize I2S peripheral
00042         hal_i2s_setup();
00043 
00044             // Setup the interrupt for the I2S
00045         NVIC_SetVector(hal_get_i2s_irq_id(), (uint32_t)_i2s_irq_handler);
00046         set_i2s_irq_priority(hal_get_i2s_irq_priority_level());
00047         NVIC_EnableIRQ(hal_get_i2s_irq_id());
00048 
00049             // Setup the interrupt for the process
00050         NVIC_SetVector(hal_get_process_irq_id(), (uint32_t)_process_irq_handler);
00051         set_process_irq_priority(hal_get_process_irq_priority_level());
00052         NVIC_EnableIRQ(hal_get_process_irq_id());
00053         
00054     }
00055 
00056     error_type Framework::set_block_size(  unsigned int new_block_size )
00057     {
00058         
00059         delete [] _tx_int_buffer[0];
00060         delete [] _tx_int_buffer[1];
00061         delete [] _rx_int_buffer[0];
00062         delete [] _rx_int_buffer[1];
00063         
00064         delete [] _tx_left_buffer;
00065         delete [] _tx_right_buffer;
00066         delete [] _rx_left_buffer;
00067         delete [] _rx_right_buffer;
00068         
00069         _block_size = new_block_size;
00070 
00071         _tx_int_buffer[0] = new int[ 2 * _block_size ];
00072         _tx_int_buffer[1] = new int[ 2 * _block_size ];
00073         _rx_int_buffer[0] = new int[ 2 * _block_size ];
00074         _rx_int_buffer[1] = new int[ 2 * _block_size ];
00075         
00076         _tx_left_buffer = new float[ _block_size ];
00077         _tx_right_buffer = new float[ _block_size ];
00078         _rx_left_buffer = new float[ _block_size ];
00079         _rx_right_buffer = new float[ _block_size ];
00080  
00081             // error check
00082         if ( _rx_int_buffer[0] == NULL |
00083              _rx_int_buffer[1] == NULL |
00084              _tx_int_buffer[0] == NULL |
00085              _tx_int_buffer[1] == NULL |
00086              _rx_right_buffer == NULL |
00087              _tx_right_buffer == NULL |
00088              _rx_left_buffer == NULL |
00089              _tx_left_buffer == NULL )
00090         {   // if error, release all 
00091             delete [] _tx_int_buffer[0];
00092             delete [] _tx_int_buffer[1];
00093             delete [] _rx_int_buffer[0];
00094             delete [] _rx_int_buffer[1];
00095             
00096             delete [] _tx_left_buffer;
00097             delete [] _tx_right_buffer;
00098             delete [] _rx_left_buffer;
00099             delete [] _rx_right_buffer;
00100             
00101             _tx_int_buffer[0] = NULL;
00102             _tx_int_buffer[1] = NULL;
00103             _rx_int_buffer[0] = NULL;
00104             _rx_int_buffer[1] = NULL;
00105             
00106             _tx_left_buffer = NULL;
00107             _tx_right_buffer = NULL;
00108             _rx_left_buffer = NULL;
00109             _rx_right_buffer = NULL;
00110             
00111             return memory_allocation_error;
00112         }
00113 
00114             // clear blocks
00115         for ( int i=0; i<_block_size*2; i++ )
00116         {
00117 
00118             _tx_int_buffer[0][i] = 0;
00119             _tx_int_buffer[1][i] = 0;
00120             _rx_int_buffer[0][i] = 0;
00121             _rx_int_buffer[1][i] = 0;
00122             
00123         }
00124             // clear blocks
00125         for ( int i=0; i<_block_size ; i++ )
00126         {
00127 
00128             _tx_left_buffer[i] = 0;
00129             _tx_right_buffer[i] = 0;
00130             _rx_left_buffer[i] = 0;
00131             _rx_right_buffer[i] = 0;
00132 
00133         }
00134          
00135         return no_error;
00136     }
00137 
00138     void Framework::start(
00139                     void (* init_cb ) (unsigned int),
00140                     void (* process_cb ) (float[], float[], float[], float[], unsigned int)
00141                     )
00142     {
00143             // if needed, call the initializer
00144         if ( init_cb )
00145             init_cb( _block_size );
00146             
00147             // register the signal processing callback
00148         _process_callback = process_cb;
00149         
00150             // synchronize with Word select signal, to process RX/TX as atomic timing.
00151         hal_i2s_pin_config_and_wait_ws();
00152         hal_i2s_start();
00153     }
00154 
00155     void Framework::set_i2s_irq_priority( unsigned int pri )
00156     {
00157         NVIC_SetPriority(hal_get_process_irq_id(), pri);  // must be higher than PendSV of mbed-RTOS
00158     }
00159     
00160     void Framework::set_process_irq_priority( unsigned int pri )
00161     {
00162         NVIC_SetPriority(hal_get_i2s_irq_id(), pri);      // must be higher than process IRQ
00163     }
00164 
00165     void Framework::set_pre_interrupt_callback( void (* cb ) (void))
00166     { 
00167         _pre_interrupt_callback = cb;
00168     }
00169     
00170     void Framework::set_post_interrupt_callback( void (* cb ) (void))
00171     { 
00172         _post_interrupt_callback = cb;
00173     }
00174     
00175     void Framework::set_pre_process_callback( void (* cb ) (void))
00176     { 
00177         _pre_process_callback = cb;
00178     }
00179     
00180     void Framework::set_post_process_callback( void (* cb ) (void))
00181     { 
00182         _post_process_callback = cb;
00183     }
00184 
00185     void Framework::_do_i2s_irq(void)
00186     {
00187             // if needed, call pre-interrupt call back
00188         if ( _pre_interrupt_callback )
00189             _pre_interrupt_callback();
00190             
00191             // irq is handled only when the buffer is correctly allocated    
00192         if (_tx_left_buffer)
00193         {
00194             int sample;
00195             
00196                 // check how many data have to be transmimted per interrupt. 
00197             for ( int i=0; i<hal_data_per_sample(); i++ )
00198             {
00199                     // copy received data to buffer
00200                 hal_get_i2s_rx_data( sample );
00201                 _rx_int_buffer[_buffer_index][_sample_index] = sample;
00202                 
00203                     // copy buffer data to transmit register
00204                 sample = _tx_int_buffer[_buffer_index][_sample_index];
00205                 hal_put_i2s_tx_data( sample );
00206                 
00207                     // increment index
00208                 _sample_index ++;
00209             }
00210             
00211                 // Implementation of the double buffer algorithm.
00212                 // if buffer transfer is complete, swap the buffer
00213             if (_sample_index >= _block_size * 2)
00214             {
00215                     // index for the signal processing
00216                 _process_index = _buffer_index;
00217 
00218                     // swap buffer
00219                 if ( _buffer_index == 0 )
00220                     _buffer_index = 1;
00221                 else
00222                     _buffer_index = 0;
00223 
00224                     // rewind sample index
00225                 _sample_index = 0;
00226 
00227                     // Trigger interrupt for signal processing
00228                 NVIC->STIR = hal_get_process_irq_id();       
00229             }
00230         }
00231 
00232             // if needed, call post-interrupt call back
00233         if ( _post_interrupt_callback )
00234             _post_interrupt_callback();
00235             
00236     }
00237 
00238     void Framework::_do_process_irq(void)
00239     {
00240             // If needed, call the pre-process hook
00241         if ( _pre_process_callback )
00242             _pre_process_callback();
00243             
00244             // Only when the process_call back is registered.
00245         if ( _process_callback )
00246         {
00247             int j = 0;
00248                 
00249                 // Format conversion.
00250                 // -- premuted from LRLRLR... to LLL.., RRR...
00251                 // -- convert from fixed point to floating point
00252                 // -- scale down as range of [-1, 1)
00253             for ( int i=0; i<_block_size; i++ )
00254             {
00255                 _rx_left_buffer[i]  = _rx_int_buffer[_process_index][j++]/ -(float)INT_MIN;
00256                 _rx_right_buffer[i] = _rx_int_buffer[_process_index][j++]/ -(float)INT_MIN;
00257             }
00258                 
00259             _process_callback
00260                     (
00261                         _rx_left_buffer,
00262                         _rx_right_buffer,
00263                         _tx_left_buffer,
00264                         _tx_right_buffer,
00265                         _block_size
00266                     );
00267                 
00268                 // Format conversion.
00269                 // -- premuted from LLL.., RRR... to LRLRLR...
00270                 // -- convert from floating point to fixed point
00271                 // -- scale up from range of [-1, 1)
00272             j = 0;
00273             for ( int i=0; i<_block_size; i++ )
00274             {
00275                 _tx_int_buffer[_process_index][j++] = _tx_left_buffer[i]  * -(float)INT_MIN ;
00276                 _tx_int_buffer[_process_index][j++] = _tx_right_buffer[i] * -(float)INT_MIN ;
00277             }
00278     
00279         }
00280 
00281             // if needed, call post-process callback
00282         if ( _post_process_callback )
00283             _post_process_callback();
00284     }
00285     
00286     void Framework::_process_irq_handler()
00287     {
00288         Framework::_fw->_do_process_irq();
00289     }
00290     
00291     void Framework::_i2s_irq_handler()
00292     {
00293         Framework::_fw->_do_i2s_irq();
00294     }
00295      
00296      
00297     Framework * Framework::_fw; 
00298  
00299 }
00300