First Publish. Works fine.
Dependents: unzen_sample_lpcxpresso_4337_callbacks
unzen_hal.cpp
00001 #include "unzen_hal.h" 00002 00003 namespace unzen 00004 { 00005 // Set up I2S peripheral to ready to start. 00006 // By this HAL, the I2S have to become : 00007 // - slave mode 00008 // - clock must be ready 00009 void hal_i2s_setup(void) 00010 { 00011 // Setup Audio Clock. Feed the core clock (PLL1, 204Mhz) to audio. 00012 LPC_CGU->BASE_CLK[CLK_BASE_APLL] = 00013 0 << 1 | // Power down. 1:Power Down, 0:Enabled 00014 1 <<11 | // Enable auto clocking. 1:Enable. 00015 9 <<24 ; // 9: PLL1 00016 00017 // Assert DAI reset 00018 LPC_I2S0->DAO |= 1 << 4; // I2S_DAI_RESET; 00019 LPC_I2S0->DAI |= 1 << 4; // I2S_DAI_RESET; 00020 // Deassert DAI reset 00021 LPC_I2S0->DAO &= ~ ( 1<<4 ); // I2S_DAI_RESET; 00022 LPC_I2S0->DAI &= ~ ( 1<<4 ); // I2S_DAI_RESET; 00023 // Assert DAI stop 00024 LPC_I2S0->DAO |= 1 << 3; // I2S_DAI_STOP; 00025 LPC_I2S0->DAI |= 1 << 3; // I2S_DAI_STOP; 00026 00027 // Kill all DMA 00028 LPC_I2S0->DMA2 = 0; 00029 LPC_I2S0->DMA1 = 0; 00030 // Kill all IRQ 00031 LPC_I2S0->IRQ = 0; 00032 // Kill all clocks 00033 LPC_I2S0->RXRATE = 0; 00034 LPC_I2S0->TXRATE = 0; 00035 // Bit rate must be 0 for slave mode. 00036 LPC_I2S0->RXBITRATE = 0; 00037 LPC_I2S0->TXBITRATE = 0; 00038 // Clear mode setting 00039 LPC_I2S0->TXMODE = 0; 00040 LPC_I2S0->RXMODE = 0; 00041 00042 00043 // Configure DA0 00044 LPC_I2S0->DAO = 00045 3 << 0 | // word width, 3:32bit mode 00046 0 << 2 | // Mono, 1:mono, 0:stereo 00047 1 << 3 | // STOP, 1:stop 00048 0 << 4 | // RESET, 1:reset 00049 1 << 5 | // WSEL, 1:Slave, 0:Master 00050 1 << 6 ; // MUTE, 1:mute, 0:normal 00051 00052 // Configure DAI 00053 LPC_I2S0->DAI = 00054 3 << 0 | // word width, 3:32bit mode 00055 0 << 2 | // Mono, 1:mono, 0:stereo 00056 1 << 3 | // STOP, 1:stop 00057 0 << 4 | // RESET, 1:reset 00058 1 << 5 | // WSEL, 1:Slave, 0:Master 00059 31 << 6; // WS halfperiod. Not sure what I shoud do when the slave mode. 00060 00061 // Configure IRQ At this moment, IRQ is disabled. 00062 LPC_I2S0->IRQ = 00063 0 << 0 | // RX IRQ Enable, 1:Enable, 0:Disable 00064 0 << 1 | // TX IRQ Enable, 1:Enable, 0:Disable 00065 2 << 8 | // RX DEPTH IRQ length for triggering interrupt 00066 0 << 16 ; // TX DEPTH IRQ length for triggering interrupt 00067 00068 // Set RX module as slave operation to the external signal 00069 LPC_I2S0->RXMODE = 00070 0 << 0 | // RXCLKSEL, 0:SCLK input. The reference manual says this is fractional devider, but in slave mode, it is SCLK. 00071 0 << 2 | // RX4PIN, 1:4pin mode, 0:Clock by RX block itself 00072 0 << 3 ; // RXMCENA, 1:Master clock output, 0:No output 00073 00074 // SEt TX module as slave operation to the RX module (4PIN mode ) 00075 LPC_I2S0->TXMODE = 00076 0 << 0 | // TXCLKSEL, 0:SCLK input. Ignored by 4 pin mode. 00077 1 << 2 | // TX4PIN, 1:4pin mode, 0:Clock by TX block itself 00078 0 << 3 ; // TXMCENA, 1:Master clock output, 0:No output 00079 00080 00081 // Fill up tx FIO by 3 stereo samples. 00082 hal_put_i2s_tx_data( 0 ); // left 00083 hal_put_i2s_tx_data( 0 ); // right 00084 hal_put_i2s_tx_data( 0 ); // left 00085 hal_put_i2s_tx_data( 0 ); // right 00086 hal_put_i2s_tx_data( 0 ); // left 00087 hal_put_i2s_tx_data( 0 ); // right 00088 00089 } 00090 00091 // Pin configuration and sync with WS signal 00092 void hal_i2s_pin_config_and_wait_ws(void) 00093 { 00094 // See UM10503 LPC4300 UM Rev 2.1 section 16.2.3, chapter 19 00095 // See https://developer.mbed.org/platforms/LPCXpresso4337/ 00096 // See mbed src lpc43xx.h http://preview.tinyurl.com/lpc43xxh 00097 00098 00099 // setup WS pin as GPIO input 00100 LPC_SCU->SFSP[6][1] = SCU_MODE_INBUFF_EN; // P6_1, function 0. GPIO3[0] 00101 00102 // if WS is 1, wait for WS (GPIO3_0) becomes 0 00103 while ( LPC_GPIO_PORT->B[3][0] == 1 ) 00104 ; 00105 00106 // and then, if WS is 0, wait for WS (GPIO3_0) becomes 1 00107 while ( LPC_GPIO_PORT->B[3][0] == 0 ) 00108 ; 00109 00110 // Now, we are at the rising edge of WS. 00111 // We can setup the I2S without worry of the TX/RX shift. 00112 00113 // setup I2S pin configuration. 00114 // for input, bit 6 have to be 1 ( input buffer enable ) 00115 LPC_SCU->SFSP[3][5] = 5; // P3_5, function 5. IS20_TX_SDA 00116 LPC_SCU->SFSP[6][0] = 4 | SCU_MODE_INBUFF_EN; // P6_0, function 4. IS20_RX_SCK 00117 LPC_SCU->SFSP[6][1] = 3 | SCU_MODE_INBUFF_EN; // P6_1, function 3. IS20_RX_WS 00118 LPC_SCU->SFSP[3][2] = 1 | SCU_MODE_INBUFF_EN; // P3_2, function 1. IS20_RX_SDA 00119 } 00120 00121 00122 // Start I2S transfer. Interrupt starts 00123 void hal_i2s_start(void) 00124 { 00125 //Clear STOP,RESET and MUTE bit 00126 LPC_I2S0->DAO &= ~(1 << 3); // release I2S_DAO_STOP; 00127 LPC_I2S0->DAI &= ~(1 << 3); // release I2S_DAI_STOP; 00128 00129 LPC_I2S0->DAO &= ~(1 << 6); // release I2S_DAO_MUTE; 00130 LPC_I2S0->IRQ |= 1 << 0; // set I2S RX IRQ enable 00131 } 00132 00133 IRQn_Type hal_get_i2s_irq_id(void) 00134 { 00135 return I2S0_IRQn; 00136 } 00137 00138 00139 IRQn_Type hal_get_process_irq_id(void) 00140 { 00141 return ( IRQn_Type )30; // LPC4300's unsed interrupt 00142 } 00143 00144 00145 // The returned value must be compatible with CMSIS NVIC_SetPriority() API. That mean, it is integer like 0, 1, 2... 00146 unsigned int hal_get_i2s_irq_priority_level(void) 00147 { 00148 // LPC4300 has 3 bits priority field. So, heighest is 0, lowest is 7. 00149 // But CMSIS NVIC_SetPriority() inverse the priority of the interupt ( F**k! ) 00150 // So, 7 is heighest, 0 is lowerest in CMSIS. 00151 // setting 6 as i2s irq priority allows, some other interrupts are higher 00152 // and some others are lower than i2s irq priority. 00153 return 6; 00154 } 00155 00156 00157 // The returned value must be compatible with CMSIS NVIC_SetPriority() API. That mean, it is integer like 0, 1, 2... 00158 unsigned int hal_get_process_irq_priority_level(void) 00159 { 00160 // LPC4300 has 3 bits priority field. So, heighest is 0, lowest is 7. 00161 // But CMSIS NVIC_SetPriority() inverse the priority of the interupt ( S**t! ) 00162 // So, 7 is heighest, 0 is lowerest in CMSIS. 00163 // setting 1 as process priority allows, some other interrupts are higher 00164 // and some other interrupts are lower then process priority. 00165 return 1; 00166 } 00167 00168 // LPC4337 transferes 2 workd ( left and right ) for each interrupt. 00169 unsigned int hal_data_per_sample(void) 00170 { 00171 return 2; 00172 } 00173 00174 // return true when the sample parameter is ready to read. 00175 // return false when the sample is not ready to read. 00176 void hal_get_i2s_rx_data( int & sample) 00177 { 00178 sample = LPC_I2S0->RXFIFO; 00179 } 00180 00181 // put a sample to I2S TX data regisger 00182 void hal_put_i2s_tx_data( int sample ) 00183 { 00184 LPC_I2S0->TXFIFO = sample; 00185 } 00186 } 00187 00188
Generated on Sun Jul 17 2022 19:07:46 by 1.7.2