First Publish. Works fine.

Dependents:   unzen_sample_LPC4088_quickstart

Committer:
shorie
Date:
Sat Jun 11 05:32:41 2016 +0000
Revision:
17:78be0725977b
Parent:
15:0db847496bb9
Must work

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 14:bdf11487a94b 11 // Setup Audio Power
shorie 14:bdf11487a94b 12 LPC_SC->PCONP |=( 1<<27 ); // set PCOMP.I2S
shorie 2:6613e62da521 13
shorie 0:5ac19c994288 14 // Assert DAI reset
shorie 14:bdf11487a94b 15 LPC_I2S->DAO |= 1 << 4; // I2S_DAI_RESET;
shorie 14:bdf11487a94b 16 LPC_I2S->DAI |= 1 << 4; // I2S_DAI_RESET;
shorie 0:5ac19c994288 17 // Deassert DAI reset
shorie 14:bdf11487a94b 18 LPC_I2S->DAO &= ~ ( 1<<4 ); // I2S_DAI_RESET;
shorie 14:bdf11487a94b 19 LPC_I2S->DAI &= ~ ( 1<<4 ); // I2S_DAI_RESET;
shorie 0:5ac19c994288 20 // Assert DAI stop
shorie 14:bdf11487a94b 21 LPC_I2S->DAO |= 1 << 3; // I2S_DAI_STOP;
shorie 14:bdf11487a94b 22 LPC_I2S->DAI |= 1 << 3; // I2S_DAI_STOP;
shorie 0:5ac19c994288 23
shorie 0:5ac19c994288 24 // Kill all DMA
shorie 14:bdf11487a94b 25 LPC_I2S->DMA2 = 0;
shorie 14:bdf11487a94b 26 LPC_I2S->DMA1 = 0;
shorie 0:5ac19c994288 27 // Kill all IRQ
shorie 14:bdf11487a94b 28 LPC_I2S->IRQ = 0;
shorie 0:5ac19c994288 29 // Kill all clocks
shorie 14:bdf11487a94b 30 LPC_I2S->RXRATE = 0;
shorie 14:bdf11487a94b 31 LPC_I2S->TXRATE = 0;
shorie 0:5ac19c994288 32 // Bit rate must be 0 for slave mode.
shorie 14:bdf11487a94b 33 LPC_I2S->RXBITRATE = 0;
shorie 14:bdf11487a94b 34 LPC_I2S->TXBITRATE = 0;
shorie 0:5ac19c994288 35 // Clear mode setting
shorie 14:bdf11487a94b 36 LPC_I2S->TXMODE = 0;
shorie 14:bdf11487a94b 37 LPC_I2S->RXMODE = 0;
shorie 0:5ac19c994288 38
shorie 0:5ac19c994288 39
shorie 0:5ac19c994288 40 // Configure DA0
shorie 14:bdf11487a94b 41 LPC_I2S->DAO =
shorie 0:5ac19c994288 42 3 << 0 | // word width, 3:32bit mode
shorie 0:5ac19c994288 43 0 << 2 | // Mono, 1:mono, 0:stereo
shorie 0:5ac19c994288 44 1 << 3 | // STOP, 1:stop
shorie 0:5ac19c994288 45 0 << 4 | // RESET, 1:reset
shorie 0:5ac19c994288 46 1 << 5 | // WSEL, 1:Slave, 0:Master
shorie 0:5ac19c994288 47 1 << 6 ; // MUTE, 1:mute, 0:normal
shorie 0:5ac19c994288 48
shorie 0:5ac19c994288 49 // Configure DAI
shorie 14:bdf11487a94b 50 LPC_I2S->DAI =
shorie 0:5ac19c994288 51 3 << 0 | // word width, 3:32bit mode
shorie 0:5ac19c994288 52 0 << 2 | // Mono, 1:mono, 0:stereo
shorie 0:5ac19c994288 53 1 << 3 | // STOP, 1:stop
shorie 0:5ac19c994288 54 0 << 4 | // RESET, 1:reset
shorie 0:5ac19c994288 55 1 << 5 | // WSEL, 1:Slave, 0:Master
shorie 0:5ac19c994288 56 31 << 6; // WS halfperiod. Not sure what I shoud do when the slave mode.
shorie 0:5ac19c994288 57
shorie 0:5ac19c994288 58 // Configure IRQ At this moment, IRQ is disabled.
shorie 14:bdf11487a94b 59 LPC_I2S->IRQ =
shorie 0:5ac19c994288 60 0 << 0 | // RX IRQ Enable, 1:Enable, 0:Disable
shorie 0:5ac19c994288 61 0 << 1 | // TX IRQ Enable, 1:Enable, 0:Disable
shorie 0:5ac19c994288 62 2 << 8 | // RX DEPTH IRQ length for triggering interrupt
shorie 0:5ac19c994288 63 0 << 16 ; // TX DEPTH IRQ length for triggering interrupt
shorie 0:5ac19c994288 64
shorie 0:5ac19c994288 65 // Set RX module as slave operation to the external signal
shorie 14:bdf11487a94b 66 LPC_I2S->RXMODE =
shorie 0:5ac19c994288 67 0 << 0 | // RXCLKSEL, 0:SCLK input. The reference manual says this is fractional devider, but in slave mode, it is SCLK.
shorie 0:5ac19c994288 68 0 << 2 | // RX4PIN, 1:4pin mode, 0:Clock by RX block itself
shorie 0:5ac19c994288 69 0 << 3 ; // RXMCENA, 1:Master clock output, 0:No output
shorie 0:5ac19c994288 70
shorie 0:5ac19c994288 71 // SEt TX module as slave operation to the RX module (4PIN mode )
shorie 14:bdf11487a94b 72 LPC_I2S->TXMODE =
shorie 0:5ac19c994288 73 0 << 0 | // TXCLKSEL, 0:SCLK input. Ignored by 4 pin mode.
shorie 0:5ac19c994288 74 1 << 2 | // TX4PIN, 1:4pin mode, 0:Clock by TX block itself
shorie 0:5ac19c994288 75 0 << 3 ; // TXMCENA, 1:Master clock output, 0:No output
shorie 0:5ac19c994288 76
shorie 0:5ac19c994288 77
shorie 2:6613e62da521 78 // Fill up tx FIO by 3 stereo samples.
shorie 2:6613e62da521 79 hal_put_i2s_tx_data( 0 ); // left
shorie 2:6613e62da521 80 hal_put_i2s_tx_data( 0 ); // right
shorie 2:6613e62da521 81 hal_put_i2s_tx_data( 0 ); // left
shorie 2:6613e62da521 82 hal_put_i2s_tx_data( 0 ); // right
shorie 2:6613e62da521 83 hal_put_i2s_tx_data( 0 ); // left
shorie 2:6613e62da521 84 hal_put_i2s_tx_data( 0 ); // right
shorie 0:5ac19c994288 85
shorie 0:5ac19c994288 86 }
shorie 0:5ac19c994288 87
shorie 2:6613e62da521 88 // Pin configuration and sync with WS signal
shorie 2:6613e62da521 89 void hal_i2s_pin_config_and_wait_ws(void)
shorie 1:9710fb328a08 90 {
shorie 14:bdf11487a94b 91 // See UM10562 LPC408x UM Rev 3 section 7.4.1
shorie 14:bdf11487a94b 92 // See https://developer.mbed.org/platforms/EA-LPC4088/#pinout
shorie 14:bdf11487a94b 93 // See mbed src lpc43xx.h http://preview.tinyurl.com/lpc408xh
shorie 14:bdf11487a94b 94
shorie 14:bdf11487a94b 95 // P0_4 RS_CLK ( P34 of QS LPC4088 )
shorie 14:bdf11487a94b 96 // P0_5 RX_WS ( P33 of QS LPC4088 )
shorie 14:bdf11487a94b 97 // P0_6 RX_SDA ( P14 of QS LPC4088 )
shorie 14:bdf11487a94b 98 // P0_9 TX_SDA ( P11 of QS LPC4088 )
shorie 2:6613e62da521 99
shorie 14:bdf11487a94b 100 unsigned int reserved_p0_mask;
shorie 14:bdf11487a94b 101
shorie 2:6613e62da521 102 // setup WS pin as GPIO input
shorie 14:bdf11487a94b 103 LPC_IOCON->P0_5 =
shorie 14:bdf11487a94b 104 0 << 0 | // FUNC : GPIO
shorie 14:bdf11487a94b 105 0 << 3 | // MODE : No pull up
shorie 14:bdf11487a94b 106 0 << 5 | // HYS : No hysterisys
shorie 14:bdf11487a94b 107 0 << 6 | // INV : Not invereted input
shorie 14:bdf11487a94b 108 0 << 9 | // SLEW : NORMA
shorie 14:bdf11487a94b 109 0 << 10 ; // OD : NO Open Drain
shorie 14:bdf11487a94b 110
shorie 14:bdf11487a94b 111 // save the mask register of GPIO 0
shorie 14:bdf11487a94b 112 reserved_p0_mask = LPC_GPIO0->MASK;
shorie 14:bdf11487a94b 113
shorie 14:bdf11487a94b 114 // set the P0_5 as input
shorie 14:bdf11487a94b 115 LPC_GPIO0->DIR &= ~(1<<5); // GPIO0.DIR.bit5 = 0
shorie 14:bdf11487a94b 116
shorie 14:bdf11487a94b 117 // set the mask register to mask out not relevant bits
shorie 14:bdf11487a94b 118 LPC_GPIO0->MASK = ~ ( 1<<5 ); // only bit 5 is enabled. P0_5 is I2S\RX_WS
shorie 1:9710fb328a08 119
shorie 2:6613e62da521 120 // if WS is 1, wait for WS (GPIO3_0) becomes 0
shorie 14:bdf11487a94b 121 while ( LPC_GPIO0->PIN )
shorie 2:6613e62da521 122 ;
shorie 2:6613e62da521 123
shorie 2:6613e62da521 124 // and then, if WS is 0, wait for WS (GPIO3_0) becomes 1
shorie 14:bdf11487a94b 125 while ( ! LPC_GPIO0->PIN )
shorie 2:6613e62da521 126 ;
shorie 14:bdf11487a94b 127
shorie 14:bdf11487a94b 128 // restore the mask register of GPIO 0
shorie 14:bdf11487a94b 129 LPC_GPIO0->MASK = reserved_p0_mask;
shorie 2:6613e62da521 130
shorie 2:6613e62da521 131 // Now, we are at the rising edge of WS.
shorie 2:6613e62da521 132 // We can setup the I2S without worry of the TX/RX shift.
shorie 2:6613e62da521 133
shorie 2:6613e62da521 134 // setup I2S pin configuration.
shorie 14:bdf11487a94b 135 LPC_IOCON->P0_4 =
shorie 14:bdf11487a94b 136 1 << 0 | // FUNC : I2S_RX_SCK
shorie 14:bdf11487a94b 137 0 << 3 | // MODE : No pull up
shorie 14:bdf11487a94b 138 0 << 5 | // HYS : No hysterisys
shorie 14:bdf11487a94b 139 0 << 6 | // INV : Not invereted input
shorie 14:bdf11487a94b 140 0 << 9 | // SLEW : NORMAL
shorie 14:bdf11487a94b 141 0 << 10 ; // OD : NO Open Drain
shorie 14:bdf11487a94b 142 LPC_IOCON->P0_5 =
shorie 14:bdf11487a94b 143 1 << 0 | // FUNC : I2S_RX_WS
shorie 14:bdf11487a94b 144 0 << 3 | // MODE : No pull up
shorie 14:bdf11487a94b 145 0 << 5 | // HYS : No hysterisys
shorie 14:bdf11487a94b 146 0 << 6 | // INV : Not invereted input
shorie 14:bdf11487a94b 147 0 << 9 | // SLEW : NORMAL
shorie 14:bdf11487a94b 148 0 << 10 ; // OD : NO Open Drain
shorie 14:bdf11487a94b 149 LPC_IOCON->P0_6 =
shorie 14:bdf11487a94b 150 1 << 0 | // FUNC : I2S_RX_SDA
shorie 14:bdf11487a94b 151 0 << 3 | // MODE : No pull up
shorie 14:bdf11487a94b 152 0 << 5 | // HYS : No hysterisys
shorie 14:bdf11487a94b 153 0 << 6 | // INV : Not invereted input
shorie 14:bdf11487a94b 154 0 << 9 | // SLEW : NORMAL
shorie 14:bdf11487a94b 155 0 << 10 ; // OD : NO Open Drain
shorie 14:bdf11487a94b 156 LPC_IOCON->P0_9 =
shorie 14:bdf11487a94b 157 1 << 0 | // FUNC : I2S_TX_SDA
shorie 14:bdf11487a94b 158 0 << 3 | // MODE : No pull up
shorie 14:bdf11487a94b 159 0 << 5 | // HYS : No hysterisys
shorie 14:bdf11487a94b 160 0 << 6 | // INV : Not invereted input
shorie 14:bdf11487a94b 161 1 << 7 | // AMODE : 1:Digital mode
shorie 14:bdf11487a94b 162 1 << 8 | // FILTER : 1:No filter
shorie 14:bdf11487a94b 163 0 << 9 | // SLEW : NORMAL
shorie 14:bdf11487a94b 164 0 << 10 ; // OD : NO Open Drain
shorie 14:bdf11487a94b 165
shorie 14:bdf11487a94b 166
shorie 1:9710fb328a08 167 }
shorie 1:9710fb328a08 168
shorie 1:9710fb328a08 169
shorie 0:5ac19c994288 170 // Start I2S transfer. Interrupt starts
shorie 2:6613e62da521 171 void hal_i2s_start(void)
shorie 0:5ac19c994288 172 {
shorie 0:5ac19c994288 173 //Clear STOP,RESET and MUTE bit
shorie 14:bdf11487a94b 174 LPC_I2S->DAO &= ~(1 << 3); // release I2S_DAO_STOP;
shorie 14:bdf11487a94b 175 LPC_I2S->DAI &= ~(1 << 3); // release I2S_DAI_STOP;
shorie 2:6613e62da521 176
shorie 14:bdf11487a94b 177 LPC_I2S->DAO &= ~(1 << 6); // release I2S_DAO_MUTE;
shorie 14:bdf11487a94b 178 LPC_I2S->IRQ |= 1 << 0; // set I2S RX IRQ enable
shorie 0:5ac19c994288 179 }
shorie 0:5ac19c994288 180
shorie 2:6613e62da521 181 IRQn_Type hal_get_i2s_irq_id(void)
shorie 0:5ac19c994288 182 {
shorie 14:bdf11487a94b 183 return I2S_IRQn;
shorie 0:5ac19c994288 184 }
shorie 0:5ac19c994288 185
shorie 0:5ac19c994288 186
shorie 2:6613e62da521 187 IRQn_Type hal_get_process_irq_id(void)
shorie 0:5ac19c994288 188 {
shorie 14:bdf11487a94b 189 return Reserved0_IRQn; // LPC4088's unsed interrupt
shorie 0:5ac19c994288 190 }
shorie 0:5ac19c994288 191
shorie 2:6613e62da521 192
shorie 2:6613e62da521 193 // The returned value must be compatible with CMSIS NVIC_SetPriority() API. That mean, it is integer like 0, 1, 2...
shorie 2:6613e62da521 194 unsigned int hal_get_i2s_irq_priority_level(void)
shorie 0:5ac19c994288 195 {
shorie 15:0db847496bb9 196 // LPC4300 has 3 bits priority field. So, heighest is 0, lowest is 31.
shorie 3:707608830793 197 // But CMSIS NVIC_SetPriority() inverse the priority of the interupt ( F**k! )
shorie 15:0db847496bb9 198 // So, 31 is heighest, 0 is lowerest in CMSIS.
shorie 15:0db847496bb9 199 // setting 24 as i2s irq priority allows, some other interrupts are higher
shorie 2:6613e62da521 200 // and some others are lower than i2s irq priority.
shorie 15:0db847496bb9 201 return 24;
shorie 2:6613e62da521 202 }
shorie 2:6613e62da521 203
shorie 2:6613e62da521 204
shorie 2:6613e62da521 205 // The returned value must be compatible with CMSIS NVIC_SetPriority() API. That mean, it is integer like 0, 1, 2...
shorie 2:6613e62da521 206 unsigned int hal_get_process_irq_priority_level(void)
shorie 2:6613e62da521 207 {
shorie 15:0db847496bb9 208 // LPC4300 has 5 bits priority field. So, heighest is 0, lowest is 31.
shorie 3:707608830793 209 // But CMSIS NVIC_SetPriority() inverse the priority of the interupt ( S**t! )
shorie 15:0db847496bb9 210 // So, 31 is heighest, 0 is lowerest in CMSIS.
shorie 15:0db847496bb9 211 // setting 8 as process priority allows, some other interrupts are higher
shorie 2:6613e62da521 212 // and some other interrupts are lower then process priority.
shorie 15:0db847496bb9 213 return 8;
shorie 0:5ac19c994288 214 }
shorie 0:5ac19c994288 215
shorie 0:5ac19c994288 216 // LPC4337 transferes 2 workd ( left and right ) for each interrupt.
shorie 2:6613e62da521 217 unsigned int hal_data_per_sample(void)
shorie 0:5ac19c994288 218 {
shorie 0:5ac19c994288 219 return 2;
shorie 0:5ac19c994288 220 }
shorie 0:5ac19c994288 221
shorie 0:5ac19c994288 222 // return true when the sample parameter is ready to read.
shorie 0:5ac19c994288 223 // return false when the sample is not ready to read.
shorie 2:6613e62da521 224 void hal_get_i2s_rx_data( int & sample)
shorie 0:5ac19c994288 225 {
shorie 14:bdf11487a94b 226 sample = LPC_I2S->RXFIFO;
shorie 0:5ac19c994288 227 }
shorie 0:5ac19c994288 228
shorie 0:5ac19c994288 229 // put a sample to I2S TX data regisger
shorie 2:6613e62da521 230 void hal_put_i2s_tx_data( int sample )
shorie 0:5ac19c994288 231 {
shorie 14:bdf11487a94b 232 LPC_I2S->TXFIFO = sample;
shorie 0:5ac19c994288 233 }
shorie 0:5ac19c994288 234 }
shorie 0:5ac19c994288 235
shorie 0:5ac19c994288 236