First Publish. Works fine.

Dependents:   unzen_sample_lpcxpresso_4337_callbacks

Committer:
shorie
Date:
Sat Jun 11 04:53:08 2016 +0000
Revision:
17:3db85c854f56
Parent:
3:707608830793
Child:
14:bdf11487a94b
Fixed comment for sample

Who changed what in which revision?

UserRevisionLine numberNew contents of line
shorie 0:5ac19c994288 1 #include "unzen_hal.h"
shorie 0:5ac19c994288 2
shorie 0:5ac19c994288 3 namespace unzen
shorie 0:5ac19c994288 4 {
shorie 0:5ac19c994288 5 // Set up I2S peripheral to ready to start.
shorie 0:5ac19c994288 6 // By this HAL, the I2S have to become :
shorie 0:5ac19c994288 7 // - slave mode
shorie 0:5ac19c994288 8 // - clock must be ready
shorie 2:6613e62da521 9 void hal_i2s_setup(void)
shorie 0:5ac19c994288 10 {
shorie 2:6613e62da521 11 // Setup Audio Clock. Feed the core clock (PLL1, 204Mhz) to audio.
shorie 2:6613e62da521 12 LPC_CGU->BASE_CLK[CLK_BASE_APLL] =
shorie 2:6613e62da521 13 0 << 1 | // Power down. 1:Power Down, 0:Enabled
shorie 2:6613e62da521 14 1 <<11 | // Enable auto clocking. 1:Enable.
shorie 2:6613e62da521 15 9 <<24 ; // 9: PLL1
shorie 2:6613e62da521 16
shorie 0:5ac19c994288 17 // Assert DAI reset
shorie 0:5ac19c994288 18 LPC_I2S0->DAO |= 1 << 4; // I2S_DAI_RESET;
shorie 0:5ac19c994288 19 LPC_I2S0->DAI |= 1 << 4; // I2S_DAI_RESET;
shorie 0:5ac19c994288 20 // Deassert DAI reset
shorie 0:5ac19c994288 21 LPC_I2S0->DAO &= ~ ( 1<<4 ); // I2S_DAI_RESET;
shorie 0:5ac19c994288 22 LPC_I2S0->DAI &= ~ ( 1<<4 ); // I2S_DAI_RESET;
shorie 0:5ac19c994288 23 // Assert DAI stop
shorie 0:5ac19c994288 24 LPC_I2S0->DAO |= 1 << 3; // I2S_DAI_STOP;
shorie 0:5ac19c994288 25 LPC_I2S0->DAI |= 1 << 3; // I2S_DAI_STOP;
shorie 0:5ac19c994288 26
shorie 0:5ac19c994288 27 // Kill all DMA
shorie 0:5ac19c994288 28 LPC_I2S0->DMA2 = 0;
shorie 0:5ac19c994288 29 LPC_I2S0->DMA1 = 0;
shorie 0:5ac19c994288 30 // Kill all IRQ
shorie 0:5ac19c994288 31 LPC_I2S0->IRQ = 0;
shorie 0:5ac19c994288 32 // Kill all clocks
shorie 0:5ac19c994288 33 LPC_I2S0->RXRATE = 0;
shorie 0:5ac19c994288 34 LPC_I2S0->TXRATE = 0;
shorie 0:5ac19c994288 35 // Bit rate must be 0 for slave mode.
shorie 0:5ac19c994288 36 LPC_I2S0->RXBITRATE = 0;
shorie 0:5ac19c994288 37 LPC_I2S0->TXBITRATE = 0;
shorie 0:5ac19c994288 38 // Clear mode setting
shorie 0:5ac19c994288 39 LPC_I2S0->TXMODE = 0;
shorie 0:5ac19c994288 40 LPC_I2S0->RXMODE = 0;
shorie 0:5ac19c994288 41
shorie 0:5ac19c994288 42
shorie 0:5ac19c994288 43 // Configure DA0
shorie 0:5ac19c994288 44 LPC_I2S0->DAO =
shorie 0:5ac19c994288 45 3 << 0 | // word width, 3:32bit mode
shorie 0:5ac19c994288 46 0 << 2 | // Mono, 1:mono, 0:stereo
shorie 0:5ac19c994288 47 1 << 3 | // STOP, 1:stop
shorie 0:5ac19c994288 48 0 << 4 | // RESET, 1:reset
shorie 0:5ac19c994288 49 1 << 5 | // WSEL, 1:Slave, 0:Master
shorie 0:5ac19c994288 50 1 << 6 ; // MUTE, 1:mute, 0:normal
shorie 0:5ac19c994288 51
shorie 0:5ac19c994288 52 // Configure DAI
shorie 0:5ac19c994288 53 LPC_I2S0->DAI =
shorie 0:5ac19c994288 54 3 << 0 | // word width, 3:32bit mode
shorie 0:5ac19c994288 55 0 << 2 | // Mono, 1:mono, 0:stereo
shorie 0:5ac19c994288 56 1 << 3 | // STOP, 1:stop
shorie 0:5ac19c994288 57 0 << 4 | // RESET, 1:reset
shorie 0:5ac19c994288 58 1 << 5 | // WSEL, 1:Slave, 0:Master
shorie 0:5ac19c994288 59 31 << 6; // WS halfperiod. Not sure what I shoud do when the slave mode.
shorie 0:5ac19c994288 60
shorie 0:5ac19c994288 61 // Configure IRQ At this moment, IRQ is disabled.
shorie 0:5ac19c994288 62 LPC_I2S0->IRQ =
shorie 0:5ac19c994288 63 0 << 0 | // RX IRQ Enable, 1:Enable, 0:Disable
shorie 0:5ac19c994288 64 0 << 1 | // TX IRQ Enable, 1:Enable, 0:Disable
shorie 0:5ac19c994288 65 2 << 8 | // RX DEPTH IRQ length for triggering interrupt
shorie 0:5ac19c994288 66 0 << 16 ; // TX DEPTH IRQ length for triggering interrupt
shorie 0:5ac19c994288 67
shorie 0:5ac19c994288 68 // Set RX module as slave operation to the external signal
shorie 0:5ac19c994288 69 LPC_I2S0->RXMODE =
shorie 0:5ac19c994288 70 0 << 0 | // RXCLKSEL, 0:SCLK input. The reference manual says this is fractional devider, but in slave mode, it is SCLK.
shorie 0:5ac19c994288 71 0 << 2 | // RX4PIN, 1:4pin mode, 0:Clock by RX block itself
shorie 0:5ac19c994288 72 0 << 3 ; // RXMCENA, 1:Master clock output, 0:No output
shorie 0:5ac19c994288 73
shorie 0:5ac19c994288 74 // SEt TX module as slave operation to the RX module (4PIN mode )
shorie 2:6613e62da521 75 LPC_I2S0->TXMODE =
shorie 0:5ac19c994288 76 0 << 0 | // TXCLKSEL, 0:SCLK input. Ignored by 4 pin mode.
shorie 0:5ac19c994288 77 1 << 2 | // TX4PIN, 1:4pin mode, 0:Clock by TX block itself
shorie 0:5ac19c994288 78 0 << 3 ; // TXMCENA, 1:Master clock output, 0:No output
shorie 0:5ac19c994288 79
shorie 0:5ac19c994288 80
shorie 2:6613e62da521 81 // Fill up tx FIO by 3 stereo samples.
shorie 2:6613e62da521 82 hal_put_i2s_tx_data( 0 ); // left
shorie 2:6613e62da521 83 hal_put_i2s_tx_data( 0 ); // right
shorie 2:6613e62da521 84 hal_put_i2s_tx_data( 0 ); // left
shorie 2:6613e62da521 85 hal_put_i2s_tx_data( 0 ); // right
shorie 2:6613e62da521 86 hal_put_i2s_tx_data( 0 ); // left
shorie 2:6613e62da521 87 hal_put_i2s_tx_data( 0 ); // right
shorie 0:5ac19c994288 88
shorie 0:5ac19c994288 89 }
shorie 0:5ac19c994288 90
shorie 2:6613e62da521 91 // Pin configuration and sync with WS signal
shorie 2:6613e62da521 92 void hal_i2s_pin_config_and_wait_ws(void)
shorie 1:9710fb328a08 93 {
shorie 2:6613e62da521 94 // See UM10503 LPC4300 UM Rev 2.1 section 16.2.3, chapter 19
shorie 2:6613e62da521 95 // See https://developer.mbed.org/platforms/LPCXpresso4337/
shorie 2:6613e62da521 96 // See mbed src lpc43xx.h http://preview.tinyurl.com/lpc43xxh
shorie 2:6613e62da521 97
shorie 2:6613e62da521 98
shorie 2:6613e62da521 99 // setup WS pin as GPIO input
shorie 2:6613e62da521 100 LPC_SCU->SFSP[6][1] = SCU_MODE_INBUFF_EN; // P6_1, function 0. GPIO3[0]
shorie 1:9710fb328a08 101
shorie 2:6613e62da521 102 // if WS is 1, wait for WS (GPIO3_0) becomes 0
shorie 2:6613e62da521 103 while ( LPC_GPIO_PORT->B[3][0] == 1 )
shorie 2:6613e62da521 104 ;
shorie 2:6613e62da521 105
shorie 2:6613e62da521 106 // and then, if WS is 0, wait for WS (GPIO3_0) becomes 1
shorie 2:6613e62da521 107 while ( LPC_GPIO_PORT->B[3][0] == 0 )
shorie 2:6613e62da521 108 ;
shorie 2:6613e62da521 109
shorie 2:6613e62da521 110 // Now, we are at the rising edge of WS.
shorie 2:6613e62da521 111 // We can setup the I2S without worry of the TX/RX shift.
shorie 2:6613e62da521 112
shorie 2:6613e62da521 113 // setup I2S pin configuration.
shorie 2:6613e62da521 114 // for input, bit 6 have to be 1 ( input buffer enable )
shorie 2:6613e62da521 115 LPC_SCU->SFSP[3][5] = 5; // P3_5, function 5. IS20_TX_SDA
shorie 2:6613e62da521 116 LPC_SCU->SFSP[6][0] = 4 | SCU_MODE_INBUFF_EN; // P6_0, function 4. IS20_RX_SCK
shorie 2:6613e62da521 117 LPC_SCU->SFSP[6][1] = 3 | SCU_MODE_INBUFF_EN; // P6_1, function 3. IS20_RX_WS
shorie 2:6613e62da521 118 LPC_SCU->SFSP[3][2] = 1 | SCU_MODE_INBUFF_EN; // P3_2, function 1. IS20_RX_SDA
shorie 1:9710fb328a08 119 }
shorie 1:9710fb328a08 120
shorie 1:9710fb328a08 121
shorie 0:5ac19c994288 122 // Start I2S transfer. Interrupt starts
shorie 2:6613e62da521 123 void hal_i2s_start(void)
shorie 0:5ac19c994288 124 {
shorie 0:5ac19c994288 125 //Clear STOP,RESET and MUTE bit
shorie 0:5ac19c994288 126 LPC_I2S0->DAO &= ~(1 << 3); // release I2S_DAO_STOP;
shorie 0:5ac19c994288 127 LPC_I2S0->DAI &= ~(1 << 3); // release I2S_DAI_STOP;
shorie 2:6613e62da521 128
shorie 0:5ac19c994288 129 LPC_I2S0->DAO &= ~(1 << 6); // release I2S_DAO_MUTE;
shorie 0:5ac19c994288 130 LPC_I2S0->IRQ |= 1 << 0; // set I2S RX IRQ enable
shorie 0:5ac19c994288 131 }
shorie 0:5ac19c994288 132
shorie 2:6613e62da521 133 IRQn_Type hal_get_i2s_irq_id(void)
shorie 0:5ac19c994288 134 {
shorie 0:5ac19c994288 135 return I2S0_IRQn;
shorie 0:5ac19c994288 136 }
shorie 0:5ac19c994288 137
shorie 0:5ac19c994288 138
shorie 2:6613e62da521 139 IRQn_Type hal_get_process_irq_id(void)
shorie 0:5ac19c994288 140 {
shorie 0:5ac19c994288 141 return ( IRQn_Type )30; // LPC4300's unsed interrupt
shorie 0:5ac19c994288 142 }
shorie 0:5ac19c994288 143
shorie 2:6613e62da521 144
shorie 2:6613e62da521 145 // The returned value must be compatible with CMSIS NVIC_SetPriority() API. That mean, it is integer like 0, 1, 2...
shorie 2:6613e62da521 146 unsigned int hal_get_i2s_irq_priority_level(void)
shorie 0:5ac19c994288 147 {
shorie 2:6613e62da521 148 // LPC4300 has 3 bits priority field. So, heighest is 0, lowest is 7.
shorie 3:707608830793 149 // But CMSIS NVIC_SetPriority() inverse the priority of the interupt ( F**k! )
shorie 3:707608830793 150 // So, 7 is heighest, 0 is lowerest in CMSIS.
shorie 3:707608830793 151 // setting 6 as i2s irq priority allows, some other interrupts are higher
shorie 2:6613e62da521 152 // and some others are lower than i2s irq priority.
shorie 3:707608830793 153 return 6;
shorie 2:6613e62da521 154 }
shorie 2:6613e62da521 155
shorie 2:6613e62da521 156
shorie 2:6613e62da521 157 // The returned value must be compatible with CMSIS NVIC_SetPriority() API. That mean, it is integer like 0, 1, 2...
shorie 2:6613e62da521 158 unsigned int hal_get_process_irq_priority_level(void)
shorie 2:6613e62da521 159 {
shorie 2:6613e62da521 160 // LPC4300 has 3 bits priority field. So, heighest is 0, lowest is 7.
shorie 3:707608830793 161 // But CMSIS NVIC_SetPriority() inverse the priority of the interupt ( S**t! )
shorie 3:707608830793 162 // So, 7 is heighest, 0 is lowerest in CMSIS.
shorie 3:707608830793 163 // setting 1 as process priority allows, some other interrupts are higher
shorie 2:6613e62da521 164 // and some other interrupts are lower then process priority.
shorie 3:707608830793 165 return 1;
shorie 0:5ac19c994288 166 }
shorie 0:5ac19c994288 167
shorie 0:5ac19c994288 168 // LPC4337 transferes 2 workd ( left and right ) for each interrupt.
shorie 2:6613e62da521 169 unsigned int hal_data_per_sample(void)
shorie 0:5ac19c994288 170 {
shorie 0:5ac19c994288 171 return 2;
shorie 0:5ac19c994288 172 }
shorie 0:5ac19c994288 173
shorie 0:5ac19c994288 174 // return true when the sample parameter is ready to read.
shorie 0:5ac19c994288 175 // return false when the sample is not ready to read.
shorie 2:6613e62da521 176 void hal_get_i2s_rx_data( int & sample)
shorie 0:5ac19c994288 177 {
shorie 0:5ac19c994288 178 sample = LPC_I2S0->RXFIFO;
shorie 0:5ac19c994288 179 }
shorie 0:5ac19c994288 180
shorie 0:5ac19c994288 181 // put a sample to I2S TX data regisger
shorie 2:6613e62da521 182 void hal_put_i2s_tx_data( int sample )
shorie 0:5ac19c994288 183 {
shorie 0:5ac19c994288 184 LPC_I2S0->TXFIFO = sample;
shorie 0:5ac19c994288 185 }
shorie 0:5ac19c994288 186 }
shorie 0:5ac19c994288 187
shorie 0:5ac19c994288 188