First Publish. Works fine.
Dependents: unzen_sample_lpcxpresso_4337_callbacks
Diff: unzen_hal.cpp
- Revision:
- 0:5ac19c994288
- Child:
- 1:9710fb328a08
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/unzen_hal.cpp Sun Apr 10 12:37:10 2016 +0000 @@ -0,0 +1,140 @@ +#include "unzen_hal.h" + +namespace unzen +{ + // Set up I2S peripheral to ready to start. + // By this HAL, the I2S have to become : + // - slave mode + // - clock must be ready + // - pins must be configured. + // - Interrupt enable. + void hal_i2s_setup() + { + // Assert DAI reset + LPC_I2S0->DAO |= 1 << 4; // I2S_DAI_RESET; + LPC_I2S0->DAI |= 1 << 4; // I2S_DAI_RESET; + // Deassert DAI reset + LPC_I2S0->DAO &= ~ ( 1<<4 ); // I2S_DAI_RESET; + LPC_I2S0->DAI &= ~ ( 1<<4 ); // I2S_DAI_RESET; + // Assert DAI stop + LPC_I2S0->DAO |= 1 << 3; // I2S_DAI_STOP; + LPC_I2S0->DAI |= 1 << 3; // I2S_DAI_STOP; + + // Kill all DMA + LPC_I2S0->DMA2 = 0; + LPC_I2S0->DMA1 = 0; + // Kill all IRQ + LPC_I2S0->IRQ = 0; + // Kill all clocks + LPC_I2S0->RXRATE = 0; + LPC_I2S0->TXRATE = 0; + // Bit rate must be 0 for slave mode. + LPC_I2S0->RXBITRATE = 0; + LPC_I2S0->TXBITRATE = 0; + // Clear mode setting + LPC_I2S0->TXMODE = 0; + LPC_I2S0->RXMODE = 0; + + + // Configure DA0 + LPC_I2S0->DAO = + 3 << 0 | // word width, 3:32bit mode + 0 << 2 | // Mono, 1:mono, 0:stereo + 1 << 3 | // STOP, 1:stop + 0 << 4 | // RESET, 1:reset + 1 << 5 | // WSEL, 1:Slave, 0:Master + 1 << 6 ; // MUTE, 1:mute, 0:normal + + // Configure DAI + LPC_I2S0->DAI = + 3 << 0 | // word width, 3:32bit mode + 0 << 2 | // Mono, 1:mono, 0:stereo + 1 << 3 | // STOP, 1:stop + 0 << 4 | // RESET, 1:reset + 1 << 5 | // WSEL, 1:Slave, 0:Master + 31 << 6; // WS halfperiod. Not sure what I shoud do when the slave mode. + + // Configure IRQ At this moment, IRQ is disabled. + LPC_I2S0->IRQ = + 0 << 0 | // RX IRQ Enable, 1:Enable, 0:Disable + 0 << 1 | // TX IRQ Enable, 1:Enable, 0:Disable + 2 << 8 | // RX DEPTH IRQ length for triggering interrupt + 0 << 16 ; // TX DEPTH IRQ length for triggering interrupt + + // Set RX module as slave operation to the external signal + LPC_I2S0->RXMODE = + 0 << 0 | // RXCLKSEL, 0:SCLK input. The reference manual says this is fractional devider, but in slave mode, it is SCLK. + 0 << 2 | // RX4PIN, 1:4pin mode, 0:Clock by RX block itself + 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 = + 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 + + } + + // Start I2S transfer. Interrupt starts + void hal_i2s_start() + { + //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() + { + return I2S0_IRQn; + } + + + IRQn_Type hal_get_process_irq_id() + { + 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() + { + return ( 7 ); // LPC4300 has 3 bits priority field. So, lowest is 7. + } + + // LPC4337 transferes 2 workd ( left and right ) for each interrupt. + unsigned int hal_data_per_sample() + { + 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) + { + 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 ) + { + LPC_I2S0->TXFIFO = sample; + // always return true for LPC4337 + return true; + } +} + +