First Publish. Works fine.
Dependents: unzen_sample_lpcxpresso_4337_callbacks
Diff: unzen.cpp
- 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