First Publish. Works fine.
Dependents: unzen_sample_LPC4088_quickstart
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(); } }