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を使う方はここから読み始めると良いでしょう。
Diff: unzen_hal.cpp
- Revision:
- 2:6613e62da521
- Parent:
- 1:9710fb328a08
- Child:
- 3:707608830793
--- a/unzen_hal.cpp Tue Apr 12 05:51:45 2016 +0000 +++ b/unzen_hal.cpp Tue May 03 01:10:32 2016 +0000 @@ -6,10 +6,14 @@ // By this HAL, the I2S have to become : // - slave mode // - clock must be ready - // - pins must be configured. - // - Interrupt enable. - void hal_i2s_setup() + void hal_i2s_setup(void) { + // Setup Audio Clock. Feed the core clock (PLL1, 204Mhz) to audio. + LPC_CGU->BASE_CLK[CLK_BASE_APLL] = + 0 << 1 | // Power down. 1:Power Down, 0:Enabled + 1 <<11 | // Enable auto clocking. 1:Enable. + 9 <<24 ; // 9: PLL1 + // Assert DAI reset LPC_I2S0->DAO |= 1 << 4; // I2S_DAI_RESET; LPC_I2S0->DAI |= 1 << 4; // I2S_DAI_RESET; @@ -68,78 +72,112 @@ 0 << 3 ; // RXMCENA, 1:Master clock output, 0:No output // SEt TX module as slave operation to the RX module (4PIN mode ) - LPC_I2S0->RXMODE = + LPC_I2S0->TXMODE = 0 << 0 | // TXCLKSEL, 0:SCLK input. Ignored by 4 pin mode. 1 << 2 | // TX4PIN, 1:4pin mode, 0:Clock by TX block itself 0 << 3 ; // TXMCENA, 1:Master clock output, 0:No output - // Fill up tx FIO by 3 samples. - hal_set_i2s_tx_data( 0 ); // left - hal_set_i2s_tx_data( 0 ); // right - hal_set_i2s_tx_data( 0 ); // left - hal_set_i2s_tx_data( 0 ); // right - hal_set_i2s_tx_data( 0 ); // left - hal_set_i2s_tx_data( 0 ); // right + // Fill up tx FIO by 3 stereo samples. + hal_put_i2s_tx_data( 0 ); // left + hal_put_i2s_tx_data( 0 ); // right + hal_put_i2s_tx_data( 0 ); // left + hal_put_i2s_tx_data( 0 ); // right + hal_put_i2s_tx_data( 0 ); // left + hal_put_i2s_tx_data( 0 ); // right } - void hal_i2s_pin_config_and_wait_ws() + // Pin configuration and sync with WS signal + void hal_i2s_pin_config_and_wait_ws(void) { + // See UM10503 LPC4300 UM Rev 2.1 section 16.2.3, chapter 19 + // See https://developer.mbed.org/platforms/LPCXpresso4337/ + // See mbed src lpc43xx.h http://preview.tinyurl.com/lpc43xxh + + + // setup WS pin as GPIO input + LPC_SCU->SFSP[6][1] = SCU_MODE_INBUFF_EN; // P6_1, function 0. GPIO3[0] + // if WS is 1, wait for WS (GPIO3_0) becomes 0 + while ( LPC_GPIO_PORT->B[3][0] == 1 ) + ; + + // and then, if WS is 0, wait for WS (GPIO3_0) becomes 1 + while ( LPC_GPIO_PORT->B[3][0] == 0 ) + ; + + // Now, we are at the rising edge of WS. + // We can setup the I2S without worry of the TX/RX shift. + + // setup I2S pin configuration. + // for input, bit 6 have to be 1 ( input buffer enable ) + LPC_SCU->SFSP[3][5] = 5; // P3_5, function 5. IS20_TX_SDA + LPC_SCU->SFSP[6][0] = 4 | SCU_MODE_INBUFF_EN; // P6_0, function 4. IS20_RX_SCK + LPC_SCU->SFSP[6][1] = 3 | SCU_MODE_INBUFF_EN; // P6_1, function 3. IS20_RX_WS + LPC_SCU->SFSP[3][2] = 1 | SCU_MODE_INBUFF_EN; // P3_2, function 1. IS20_RX_SDA } // Start I2S transfer. Interrupt starts - void hal_i2s_start() + void hal_i2s_start(void) { //Clear STOP,RESET and MUTE bit LPC_I2S0->DAO &= ~(1 << 3); // release I2S_DAO_STOP; LPC_I2S0->DAI &= ~(1 << 3); // release I2S_DAI_STOP; + LPC_I2S0->DAO &= ~(1 << 6); // release I2S_DAO_MUTE; LPC_I2S0->IRQ |= 1 << 0; // set I2S RX IRQ enable } - IRQn_Type hal_get_i2s_irq_id() + IRQn_Type hal_get_i2s_irq_id(void) { return I2S0_IRQn; } - IRQn_Type hal_get_process_irq_id() + IRQn_Type hal_get_process_irq_id(void) { return ( IRQn_Type )30; // LPC4300's unsed interrupt } - // The returned value must be compatible with CMSIS NVIC_SetPriority() API. - unsigned int hal_get_lowest_priority_level() + + // The returned value must be compatible with CMSIS NVIC_SetPriority() API. That mean, it is integer like 0, 1, 2... + unsigned int hal_get_i2s_irq_priority_level(void) { - return ( 7 ); // LPC4300 has 3 bits priority field. So, lowest is 7. + // LPC4300 has 3 bits priority field. So, heighest is 0, lowest is 7. + // setting 1 as i2s irq priority allows, some other interrupts are higher + // and some others are lower than i2s irq priority. + return 1; + } + + + // The returned value must be compatible with CMSIS NVIC_SetPriority() API. That mean, it is integer like 0, 1, 2... + unsigned int hal_get_process_irq_priority_level(void) + { + // LPC4300 has 3 bits priority field. So, heighest is 0, lowest is 7. + // setting 7 as process priority allows, some other interrupts are higher + // and some other interrupts are lower then process priority. + return 6; } // LPC4337 transferes 2 workd ( left and right ) for each interrupt. - unsigned int hal_data_per_sample() + unsigned int hal_data_per_sample(void) { return 2; } // return true when the sample parameter is ready to read. // return false when the sample is not ready to read. - bool hal_get_i2s_rx_data( int & sample) + void hal_get_i2s_rx_data( int & sample) { sample = LPC_I2S0->RXFIFO; - // always return true for LPC4337 - return ( true ); } // put a sample to I2S TX data regisger - // return true if the word is transmitted completely. - // return false if the word needs another call. In this case, next time same sample will be fed. - bool hal_set_i2s_tx_data( int sample ) + void hal_put_i2s_tx_data( int sample ) { LPC_I2S0->TXFIFO = sample; - // always return true for LPC4337 - return true; } }