Use the TLV320 with in-built I2S object to stream audio data from an SD Card and send it to the TLV320 CODEC for audio playback

Dependencies:   I2SSlave mbed TLV320

Committer:
d_worrall
Date:
Fri Aug 05 10:07:47 2011 +0000
Revision:
0:3d6892f6384f
version 2.0

Who changed what in which revision?

UserRevisionLine numberNew contents of line
d_worrall 0:3d6892f6384f 1 /******************************************************
d_worrall 0:3d6892f6384f 2 * I2SSlave.cpp: I2S port abstraction library cpp file for NXP LPC1768
d_worrall 0:3d6892f6384f 3 *
d_worrall 0:3d6892f6384f 4 * Written by:
d_worrall 0:3d6892f6384f 5 * mbed Team - 15th July 2011
d_worrall 0:3d6892f6384f 6 * Daniel Worrall
d_worrall 0:3d6892f6384f 7 *
d_worrall 0:3d6892f6384f 8 * History
d_worrall 0:3d6892f6384f 9 * version 1.31
d_worrall 0:3d6892f6384f 10 ******************************************************/
d_worrall 0:3d6892f6384f 11 #include "I2SSlave.h"
d_worrall 0:3d6892f6384f 12 /*Global Functions*/
d_worrall 0:3d6892f6384f 13 FunctionPointer akjnh3489v8ncv;
d_worrall 0:3d6892f6384f 14
d_worrall 0:3d6892f6384f 15 extern "C" void I2S_IRQHandler(void){ //this is a very special function so can remain outside
d_worrall 0:3d6892f6384f 16 akjnh3489v8ncv.call();
d_worrall 0:3d6892f6384f 17 }
d_worrall 0:3d6892f6384f 18 /******************************************************
d_worrall 0:3d6892f6384f 19 * Function name: I2SSlave
d_worrall 0:3d6892f6384f 20 *
d_worrall 0:3d6892f6384f 21 * Description: class constructor
d_worrall 0:3d6892f6384f 22 *
d_worrall 0:3d6892f6384f 23 * Parameters: PinName tx_sda, PinName tx_ws, PinName clk, PinName rx_sda, PinName rx_ws
d_worrall 0:3d6892f6384f 24 * Returns: none
d_worrall 0:3d6892f6384f 25 ******************************************************/
d_worrall 0:3d6892f6384f 26 //Constructor
d_worrall 0:3d6892f6384f 27 I2SSlave::I2SSlave(PinName tx_sda, PinName tx_ws, PinName clk, PinName rx_sda, PinName rx_ws){
d_worrall 0:3d6892f6384f 28 storePins_(tx_sda, tx_ws, clk, rx_sda, rx_ws);
d_worrall 0:3d6892f6384f 29 format(16, STEREO); //this also invokes initialize so no need to call it twice
d_worrall 0:3d6892f6384f 30 }
d_worrall 0:3d6892f6384f 31 //Public functions
d_worrall 0:3d6892f6384f 32 /******************************************************
d_worrall 0:3d6892f6384f 33 * Function name: format()
d_worrall 0:3d6892f6384f 34 *
d_worrall 0:3d6892f6384f 35 * Description: sets the bit length for writing and stereo or mono mode
d_worrall 0:3d6892f6384f 36 *
d_worrall 0:3d6892f6384f 37 * Parameters: int bit, bool mode
d_worrall 0:3d6892f6384f 38 * Returns: none
d_worrall 0:3d6892f6384f 39 ******************************************************/
d_worrall 0:3d6892f6384f 40 void I2SSlave::format(int bit, bool mode){
d_worrall 0:3d6892f6384f 41 bit_ = bit;
d_worrall 0:3d6892f6384f 42 mode_ = mode;
d_worrall 0:3d6892f6384f 43 initialize_(tx_sda_, tx_ws_, clk_, rx_sda_, rx_ws_);
d_worrall 0:3d6892f6384f 44 }
d_worrall 0:3d6892f6384f 45 /******************************************************
d_worrall 0:3d6892f6384f 46 * Function name: write()
d_worrall 0:3d6892f6384f 47 *
d_worrall 0:3d6892f6384f 48 * Description: load buffer to write to I2S port
d_worrall 0:3d6892f6384f 49 *
d_worrall 0:3d6892f6384f 50 * Parameters: long *buffer
d_worrall 0:3d6892f6384f 51 * Returns: none
d_worrall 0:3d6892f6384f 52 ******************************************************/
d_worrall 0:3d6892f6384f 53 void I2SSlave::write(int* buffer, int from, int length){
d_worrall 0:3d6892f6384f 54 int to = from + length;
d_worrall 0:3d6892f6384f 55 for(int i = from; i < to; ++i){
d_worrall 0:3d6892f6384f 56 LPC_I2S->I2STXFIFO = buffer[i];
d_worrall 0:3d6892f6384f 57 }
d_worrall 0:3d6892f6384f 58 }
d_worrall 0:3d6892f6384f 59 /******************************************************
d_worrall 0:3d6892f6384f 60 * Function name: start()
d_worrall 0:3d6892f6384f 61 *
d_worrall 0:3d6892f6384f 62 * Description: attach streamOut_ function to ticker interrupt
d_worrall 0:3d6892f6384f 63 *
d_worrall 0:3d6892f6384f 64 * Parameters: none
d_worrall 0:3d6892f6384f 65 * Returns: none
d_worrall 0:3d6892f6384f 66 ******************************************************/
d_worrall 0:3d6892f6384f 67 void I2SSlave::start(int mode){
d_worrall 0:3d6892f6384f 68 switch(mode){
d_worrall 0:3d6892f6384f 69 case(0):
d_worrall 0:3d6892f6384f 70 LPC_I2S->I2SIRQ |= (0 << 0); //disable receive interrupt
d_worrall 0:3d6892f6384f 71 LPC_I2S->I2SIRQ |= (0 << 1); //disable transmit interrupt
d_worrall 0:3d6892f6384f 72 break;
d_worrall 0:3d6892f6384f 73 case(1):
d_worrall 0:3d6892f6384f 74 LPC_I2S->I2SIRQ |= (0 << 0); //disable receive interrupt
d_worrall 0:3d6892f6384f 75 LPC_I2S->I2SIRQ |= (1 << 1); //enable transmit interrupt
d_worrall 0:3d6892f6384f 76 LPC_I2S->I2SIRQ |= (0 << 16); //set I2STXFIFO depth to 0 words
d_worrall 0:3d6892f6384f 77 break;
d_worrall 0:3d6892f6384f 78 case(2):
d_worrall 0:3d6892f6384f 79 LPC_I2S->I2SIRQ |= (1 << 0); //enable receive interrupt
d_worrall 0:3d6892f6384f 80 LPC_I2S->I2SIRQ |= (0 << 1); //disable transmit interrupt
d_worrall 0:3d6892f6384f 81 LPC_I2S->I2SIRQ |= (4 << 8); //set I2SRXFIFO depth to 4 words
d_worrall 0:3d6892f6384f 82 break;
d_worrall 0:3d6892f6384f 83 case(3):
d_worrall 0:3d6892f6384f 84 LPC_I2S->I2SIRQ |= (1 << 0); //enable receive interrupt
d_worrall 0:3d6892f6384f 85 LPC_I2S->I2SIRQ |= (4 << 8); //set I2SRXFIFO depth to 4 words
d_worrall 0:3d6892f6384f 86 LPC_I2S->I2SIRQ |= (1 << 1); //enable transmit interrupt
d_worrall 0:3d6892f6384f 87 LPC_I2S->I2SIRQ |= (0 << 16); //set I2STXFIFO depth to 0 words
d_worrall 0:3d6892f6384f 88 break;
d_worrall 0:3d6892f6384f 89 default:
d_worrall 0:3d6892f6384f 90 break;
d_worrall 0:3d6892f6384f 91 }
d_worrall 0:3d6892f6384f 92 NVIC_SetPriority(I2S_IRQn, 0);
d_worrall 0:3d6892f6384f 93 NVIC_EnableIRQ(I2S_IRQn); //enable I2S interrupt in the NVIC
d_worrall 0:3d6892f6384f 94 }
d_worrall 0:3d6892f6384f 95 /******************************************************
d_worrall 0:3d6892f6384f 96 * Function name: stop()
d_worrall 0:3d6892f6384f 97 *
d_worrall 0:3d6892f6384f 98 * Description: detach streamOut_ from ticker
d_worrall 0:3d6892f6384f 99 *
d_worrall 0:3d6892f6384f 100 * Parameters: none
d_worrall 0:3d6892f6384f 101 * Returns: none
d_worrall 0:3d6892f6384f 102 ******************************************************/
d_worrall 0:3d6892f6384f 103 void I2SSlave::stop(void){
d_worrall 0:3d6892f6384f 104 NVIC_DisableIRQ(I2S_IRQn);
d_worrall 0:3d6892f6384f 105 }
d_worrall 0:3d6892f6384f 106 /******************************************************
d_worrall 0:3d6892f6384f 107 * Function name: read()
d_worrall 0:3d6892f6384f 108 *
d_worrall 0:3d6892f6384f 109 * Description: reads FIFORX buffer into [int32_t rxBuffer[8]]
d_worrall 0:3d6892f6384f 110 *
d_worrall 0:3d6892f6384f 111 * Parameters: none
d_worrall 0:3d6892f6384f 112 * Returns: none
d_worrall 0:3d6892f6384f 113 ******************************************************/
d_worrall 0:3d6892f6384f 114 void I2SSlave::read(void){
d_worrall 0:3d6892f6384f 115 rxBuffer[0] = LPC_I2S->I2SRXFIFO;
d_worrall 0:3d6892f6384f 116 rxBuffer[1] = LPC_I2S->I2SRXFIFO;
d_worrall 0:3d6892f6384f 117 rxBuffer[2] = LPC_I2S->I2SRXFIFO;
d_worrall 0:3d6892f6384f 118 rxBuffer[3] = LPC_I2S->I2SRXFIFO;
d_worrall 0:3d6892f6384f 119 }
d_worrall 0:3d6892f6384f 120 /******************************************************
d_worrall 0:3d6892f6384f 121 * Function name: status_()
d_worrall 0:3d6892f6384f 122 *
d_worrall 0:3d6892f6384f 123 * Description: Read I2SSTATE register
d_worrall 0:3d6892f6384f 124 *
d_worrall 0:3d6892f6384f 125 * Parameters: none
d_worrall 0:3d6892f6384f 126 * Returns: int
d_worrall 0:3d6892f6384f 127 ******************************************************/
d_worrall 0:3d6892f6384f 128 int I2SSlave::status(void){
d_worrall 0:3d6892f6384f 129 return LPC_I2S->I2SSTATE;
d_worrall 0:3d6892f6384f 130 }
d_worrall 0:3d6892f6384f 131 //Private functions
d_worrall 0:3d6892f6384f 132 /******************************************************
d_worrall 0:3d6892f6384f 133 * Function name: initialize()
d_worrall 0:3d6892f6384f 134 *
d_worrall 0:3d6892f6384f 135 * Description: initialises I2S port
d_worrall 0:3d6892f6384f 136 *
d_worrall 0:3d6892f6384f 137 * Parameters: PinName tx_sda, PinName tx_ws, PinName clk, PinName rx_sda, PinName rx_ws
d_worrall 0:3d6892f6384f 138 * Returns: 0 = successful initialisation
d_worrall 0:3d6892f6384f 139 -1 = initialisation failure
d_worrall 0:3d6892f6384f 140 ******************************************************/
d_worrall 0:3d6892f6384f 141 int I2SSlave::initialize_(PinName tx_sda, PinName tx_ws, PinName clk, PinName rx_sda, PinName rx_ws){
d_worrall 0:3d6892f6384f 142 setPins_(tx_sda, tx_ws, clk, rx_sda, rx_ws); //designate pins
d_worrall 0:3d6892f6384f 143 LPC_SC->PCONP |= (1 << 27);
d_worrall 0:3d6892f6384f 144 //configure input/output register
d_worrall 0:3d6892f6384f 145 format_(bit_, mode_);
d_worrall 0:3d6892f6384f 146 //set mbed as SLAVE
d_worrall 0:3d6892f6384f 147 LPC_I2S->I2SDAO |= (1 << 5);
d_worrall 0:3d6892f6384f 148 LPC_I2S->I2SDAI |= (1 << 5);
d_worrall 0:3d6892f6384f 149 //clock mode
d_worrall 0:3d6892f6384f 150 setClocks_(4);
d_worrall 0:3d6892f6384f 151 //set slave mode
d_worrall 0:3d6892f6384f 152 modeConfig_();
d_worrall 0:3d6892f6384f 153 //set receiver mode
d_worrall 0:3d6892f6384f 154 LPC_I2S->I2SRXMODE |= (1 << 1);
d_worrall 0:3d6892f6384f 155 //slave mode
d_worrall 0:3d6892f6384f 156 LPC_I2S->I2STXRATE = 0;
d_worrall 0:3d6892f6384f 157 LPC_I2S->I2SRXRATE = 0;
d_worrall 0:3d6892f6384f 158 //Start
d_worrall 0:3d6892f6384f 159 LPC_I2S->I2SDAO |= (0 << 3);
d_worrall 0:3d6892f6384f 160 LPC_I2S->I2SDAI |= (0 << 3);
d_worrall 0:3d6892f6384f 161 LPC_I2S->I2SDAO |= (0 << 4);
d_worrall 0:3d6892f6384f 162 LPC_I2S->I2SDAI |= (0 << 4);
d_worrall 0:3d6892f6384f 163 LPC_I2S->I2SDAO |= (0 << 15);
d_worrall 0:3d6892f6384f 164 return 0;
d_worrall 0:3d6892f6384f 165 }
d_worrall 0:3d6892f6384f 166 /******************************************************
d_worrall 0:3d6892f6384f 167 * Function name: setClocks_()
d_worrall 0:3d6892f6384f 168 *
d_worrall 0:3d6892f6384f 169 * Description: Set the division setting on the internal clocks
d_worrall 0:3d6892f6384f 170 *
d_worrall 0:3d6892f6384f 171 * Parameters: int divideBy
d_worrall 0:3d6892f6384f 172 * Returns: nothing
d_worrall 0:3d6892f6384f 173 ******************************************************/
d_worrall 0:3d6892f6384f 174 void I2SSlave::setClocks_(int divideBy){
d_worrall 0:3d6892f6384f 175 switch(divideBy){
d_worrall 0:3d6892f6384f 176 case 1:
d_worrall 0:3d6892f6384f 177 LPC_SC->PCLKSEL1 |= (1 << 22);
d_worrall 0:3d6892f6384f 178 LPC_SC->PCLKSEL1 |= (0 << 23);
d_worrall 0:3d6892f6384f 179 break;
d_worrall 0:3d6892f6384f 180 case 2:
d_worrall 0:3d6892f6384f 181 LPC_SC->PCLKSEL1 |= (0 << 22);
d_worrall 0:3d6892f6384f 182 LPC_SC->PCLKSEL1 |= (1 << 23);
d_worrall 0:3d6892f6384f 183 break;
d_worrall 0:3d6892f6384f 184 case 4:
d_worrall 0:3d6892f6384f 185 LPC_SC->PCLKSEL1 |= (0 << 22);
d_worrall 0:3d6892f6384f 186 LPC_SC->PCLKSEL1 |= (0 << 23);
d_worrall 0:3d6892f6384f 187 break;
d_worrall 0:3d6892f6384f 188 case 8:
d_worrall 0:3d6892f6384f 189 LPC_SC->PCLKSEL1 |= (1 << 22);
d_worrall 0:3d6892f6384f 190 LPC_SC->PCLKSEL1 |= (1 << 23);
d_worrall 0:3d6892f6384f 191 break;
d_worrall 0:3d6892f6384f 192 default:
d_worrall 0:3d6892f6384f 193 break;
d_worrall 0:3d6892f6384f 194 }
d_worrall 0:3d6892f6384f 195 }
d_worrall 0:3d6892f6384f 196 /******************************************************
d_worrall 0:3d6892f6384f 197 * Function name: setPins_()
d_worrall 0:3d6892f6384f 198 *
d_worrall 0:3d6892f6384f 199 * Description: set external pin configuration
d_worrall 0:3d6892f6384f 200 *
d_worrall 0:3d6892f6384f 201 * Parameters: PinName tx_sda, PinName tx_ws, PinName clk, PinName rx_sda, PinName rx_ws
d_worrall 0:3d6892f6384f 202 * Returns: none
d_worrall 0:3d6892f6384f 203 ******************************************************/
d_worrall 0:3d6892f6384f 204 void I2SSlave::setPins_(PinName tx_sda, PinName tx_ws, PinName clk, PinName rx_sda, PinName rx_ws){
d_worrall 0:3d6892f6384f 205 if(rx_ws == p29){
d_worrall 0:3d6892f6384f 206 LPC_PINCON->PINSEL0 |= (1 << 10); //set p29 as receive word select line
d_worrall 0:3d6892f6384f 207 } else {
d_worrall 0:3d6892f6384f 208 LPC_PINCON->PINSEL1 |= (2 << 16); //set p16 as receive word select line
d_worrall 0:3d6892f6384f 209 }
d_worrall 0:3d6892f6384f 210 if(rx_sda == p8){
d_worrall 0:3d6892f6384f 211 LPC_PINCON->PINSEL0 |= (1 << 12); //set p8 as receive serial data line
d_worrall 0:3d6892f6384f 212 } else {
d_worrall 0:3d6892f6384f 213 LPC_PINCON->PINSEL1 |= (2 << 18); //set p17 as receive serial data line
d_worrall 0:3d6892f6384f 214 }
d_worrall 0:3d6892f6384f 215 LPC_PINCON->PINSEL0 |= (1 << 14); //set p7 as transmit clock line (only one of these)
d_worrall 0:3d6892f6384f 216 LPC_PINCON->PINSEL0 |= (1 << 16); //set p6 as word select line (only one of these)
d_worrall 0:3d6892f6384f 217 LPC_PINCON->PINSEL0 |= (1 << 18); //set p5 as transmit serial data line (only one of these)
d_worrall 0:3d6892f6384f 218 LPC_PINCON->PINSEL0 |= (0 << 8); //clear rx_clk
d_worrall 0:3d6892f6384f 219 }
d_worrall 0:3d6892f6384f 220 /******************************************************
d_worrall 0:3d6892f6384f 221 * Function name: format_()
d_worrall 0:3d6892f6384f 222 *
d_worrall 0:3d6892f6384f 223 * Description: sets the bit length for writing and stereo or mono mode
d_worrall 0:3d6892f6384f 224 *
d_worrall 0:3d6892f6384f 225 * Parameters: int bit, bool mode
d_worrall 0:3d6892f6384f 226 * Returns: none
d_worrall 0:3d6892f6384f 227 ******************************************************/
d_worrall 0:3d6892f6384f 228 void I2SSlave::format_(int bit, bool mode){
d_worrall 0:3d6892f6384f 229 uint32_t bps= ((bit+1)*8)-1;
d_worrall 0:3d6892f6384f 230 LPC_I2S->I2SDAO &= (0x00 << 6);
d_worrall 0:3d6892f6384f 231 LPC_I2S->I2SDAO |= (bps << 6);
d_worrall 0:3d6892f6384f 232 //set bit length
d_worrall 0:3d6892f6384f 233 switch(bit){
d_worrall 0:3d6892f6384f 234 case 8:
d_worrall 0:3d6892f6384f 235 LPC_I2S->I2SDAO &= 0xfffffffc;
d_worrall 0:3d6892f6384f 236 break;
d_worrall 0:3d6892f6384f 237 case 16:
d_worrall 0:3d6892f6384f 238 LPC_I2S->I2SDAO &= (0 << 1);
d_worrall 0:3d6892f6384f 239 LPC_I2S->I2SDAO |= (1 << 0);
d_worrall 0:3d6892f6384f 240 break;
d_worrall 0:3d6892f6384f 241 case 32:
d_worrall 0:3d6892f6384f 242 LPC_I2S->I2SDAO &= (0 << 1);
d_worrall 0:3d6892f6384f 243 LPC_I2S->I2SDAO |= (3 << 0);
d_worrall 0:3d6892f6384f 244 break;
d_worrall 0:3d6892f6384f 245 default:
d_worrall 0:3d6892f6384f 246 break;
d_worrall 0:3d6892f6384f 247 }
d_worrall 0:3d6892f6384f 248 //set audio mode
d_worrall 0:3d6892f6384f 249 if(mode == STEREO){
d_worrall 0:3d6892f6384f 250 LPC_I2S->I2SDAO |= (0 << 2);
d_worrall 0:3d6892f6384f 251 } else {
d_worrall 0:3d6892f6384f 252 LPC_I2S->I2SDAO |= (1 << 2);
d_worrall 0:3d6892f6384f 253 }
d_worrall 0:3d6892f6384f 254 //set transmitter and receiver setting to be the same
d_worrall 0:3d6892f6384f 255 LPC_I2S->I2SDAI &= (0x00 << 6);
d_worrall 0:3d6892f6384f 256 LPC_I2S->I2SDAI |= (bps << 6);
d_worrall 0:3d6892f6384f 257 //set bit length
d_worrall 0:3d6892f6384f 258 switch(bit){
d_worrall 0:3d6892f6384f 259 case 8:
d_worrall 0:3d6892f6384f 260 LPC_I2S->I2SDAI &= 0xfffffffc;
d_worrall 0:3d6892f6384f 261 break;
d_worrall 0:3d6892f6384f 262 case 16:
d_worrall 0:3d6892f6384f 263 LPC_I2S->I2SDAI &= (0 << 1);
d_worrall 0:3d6892f6384f 264 LPC_I2S->I2SDAI |= (1 << 0);
d_worrall 0:3d6892f6384f 265 break;
d_worrall 0:3d6892f6384f 266 case 32:
d_worrall 0:3d6892f6384f 267 LPC_I2S->I2SDAI &= (0 << 1);
d_worrall 0:3d6892f6384f 268 LPC_I2S->I2SDAI |= (3 << 0);
d_worrall 0:3d6892f6384f 269 break;
d_worrall 0:3d6892f6384f 270 default:
d_worrall 0:3d6892f6384f 271 break;
d_worrall 0:3d6892f6384f 272 }
d_worrall 0:3d6892f6384f 273 //set audio mode
d_worrall 0:3d6892f6384f 274 if(mode == STEREO){
d_worrall 0:3d6892f6384f 275 LPC_I2S->I2SDAI |= (0 << 2);
d_worrall 0:3d6892f6384f 276 } else {
d_worrall 0:3d6892f6384f 277 LPC_I2S->I2SDAI |= (1 << 2);
d_worrall 0:3d6892f6384f 278 }
d_worrall 0:3d6892f6384f 279 }
d_worrall 0:3d6892f6384f 280 /******************************************************
d_worrall 0:3d6892f6384f 281 * Function name: modeConfig_()
d_worrall 0:3d6892f6384f 282 *
d_worrall 0:3d6892f6384f 283 * Description: Set slave mode
d_worrall 0:3d6892f6384f 284 *
d_worrall 0:3d6892f6384f 285 * Parameters: none
d_worrall 0:3d6892f6384f 286 * Returns: none
d_worrall 0:3d6892f6384f 287 ******************************************************/
d_worrall 0:3d6892f6384f 288 void I2SSlave::modeConfig_(void){
d_worrall 0:3d6892f6384f 289 LPC_I2S->I2STXMODE |= (0x0 << 0);
d_worrall 0:3d6892f6384f 290 LPC_I2S->I2SRXMODE |= (0x0 << 0);
d_worrall 0:3d6892f6384f 291 }
d_worrall 0:3d6892f6384f 292 /******************************************************
d_worrall 0:3d6892f6384f 293 * Function name: storePins_()
d_worrall 0:3d6892f6384f 294 *
d_worrall 0:3d6892f6384f 295 * Description: set external pin configuration
d_worrall 0:3d6892f6384f 296 *
d_worrall 0:3d6892f6384f 297 * Parameters: PinName tx_sda, PinName tx_ws, PinName clk, PinName rx_sda, PinName rx_ws
d_worrall 0:3d6892f6384f 298 * Returns: none
d_worrall 0:3d6892f6384f 299 ******************************************************/
d_worrall 0:3d6892f6384f 300 void I2SSlave::storePins_(PinName tx_sda, PinName tx_ws, PinName clk, PinName rx_sda, PinName rx_ws){
d_worrall 0:3d6892f6384f 301 tx_sda_ = tx_sda;
d_worrall 0:3d6892f6384f 302 tx_ws_ = tx_ws;
d_worrall 0:3d6892f6384f 303 clk_ = clk;
d_worrall 0:3d6892f6384f 304 rx_sda_ = rx_sda;
d_worrall 0:3d6892f6384f 305 rx_ws_ = rx_ws;
d_worrall 0:3d6892f6384f 306 }