First Publish. Works fine.
Dependents: unzen_sample_nucleo_f746 unzen_delay_sample_nucleo_f746 skeleton_unzen_nucleo_f746 ifmag_noise_canceller ... more
Nucleo F746ZG用のオーディオ・フレームワークです。フレームワーク地震の詳細は『雲仙』オーディオ・フレームワークを参照してください。
参考リンク
- skeleton_unzen_nucleo_f746 Nucleo F746ZGおよびUI基板を使う場合のスケルトンプログラム。F746を使う方はここから読み始めると良いでしょう。
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(); } }