Thi s library works either for lpc1768 or lpc4088 QSB
Fork of I2SSlave by
I2SSlave.cpp
00001 /** 00002 * @author Daniel Worrall 00003 * 00004 * @section LICENSE 00005 * 00006 * Copyright (c) 2011 mbed 00007 * 00008 * Permission is hereby granted, free of charge, to any person obtaining a copy 00009 * of this software and associated documentation files (the "Software"), to deal 00010 * in the Software without restriction, including without limitation the rights 00011 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 00012 * copies of the Software, and to permit persons to whom the Software is 00013 * furnished to do so, subject to the following conditions: 00014 * 00015 * The above copyright notice and this permission notice shall be included in 00016 * all copies or substantial portions of the Software. 00017 * 00018 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00019 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00020 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 00021 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00022 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00023 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 00024 * THE SOFTWARE. 00025 * 00026 * @section DESCRIPTION 00027 * I2S port abstraction library cpp file for NXP LPC1768 00028 * 00029 */ 00030 #include "I2SSlave.h" 00031 /*Global Functions*/ 00032 FunctionPointer akjnh3489v8ncv; 00033 00034 extern "C" void I2S_IRQHandler(void){ //this is a very special function so can remain outside 00035 akjnh3489v8ncv.call(); 00036 } 00037 /****************************************************** 00038 * Function name: I2SSlave 00039 * 00040 * Description: class constructor 00041 * 00042 * Parameters: PinName tx_sda, PinName tx_ws, PinName clk, PinName rx_sda, PinName rx_ws 00043 * Returns: none 00044 ******************************************************/ 00045 //Constructor 00046 I2SSlave::I2SSlave(PinName tx_sda, PinName tx_ws, PinName clk, PinName rx_sda, PinName rx_ws){ 00047 storePins_(tx_sda, tx_ws, clk, rx_sda, rx_ws); 00048 format(16, STEREO); //this also invokes initialize so no need to call it twice 00049 } 00050 //Public functions 00051 /****************************************************** 00052 * Function name: format() 00053 * 00054 * Description: sets the bit length for writing and stereo or mono mode 00055 * 00056 * Parameters: int bit, bool mode 00057 * Returns: none 00058 ******************************************************/ 00059 void I2SSlave::format(int bit, bool mode){ 00060 bit_ = bit; 00061 mode_ = mode; 00062 initialize_(tx_sda_, tx_ws_, clk_, rx_sda_, rx_ws_); 00063 } 00064 /****************************************************** 00065 * Function name: write() 00066 * 00067 * Description: load buffer to write to I2S port 00068 * 00069 * Parameters: long *buffer 00070 * Returns: none 00071 ******************************************************/ 00072 void I2SSlave::write(int* buffer, int from, int length){ 00073 int to = from + length; 00074 for(int i = from; i < to; ++i){ 00075 #if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) 00076 LPC_I2S->I2STXFIFO = buffer[i]; 00077 #elif defined(TARGET_LPC4088) 00078 LPC_I2S->TXFIFO = buffer[i]; 00079 #endif 00080 } 00081 } 00082 /****************************************************** 00083 * Function name: start() 00084 * 00085 * Description: attach streamOut_ function to ticker interrupt 00086 * 00087 * Parameters: none 00088 * Returns: none 00089 ******************************************************/ 00090 void I2SSlave::start(int mode){ 00091 #if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) 00092 switch(mode){ 00093 case(0): 00094 LPC_I2S->I2SIRQ |= (0 << 0); //disable receive interrupt 00095 LPC_I2S->I2SIRQ |= (0 << 1); //disable transmit interrupt 00096 break; 00097 case(1): 00098 LPC_I2S->I2SIRQ |= (0 << 0); //disable receive interrupt 00099 LPC_I2S->I2SIRQ |= (1 << 1); //enable transmit interrupt 00100 LPC_I2S->I2SIRQ |= (0 << 16); //set I2STXFIFO depth to 0 words 00101 break; 00102 case(2): 00103 LPC_I2S->I2SIRQ |= (1 << 0); //enable receive interrupt 00104 LPC_I2S->I2SIRQ |= (0 << 1); //disable transmit interrupt 00105 LPC_I2S->I2SIRQ |= (4 << 8); //set I2SRXFIFO depth to 4 words 00106 break; 00107 case(3): 00108 LPC_I2S->I2SIRQ |= (1 << 0); //enable receive interrupt 00109 LPC_I2S->I2SIRQ |= (4 << 8); //set I2SRXFIFO depth to 4 words 00110 LPC_I2S->I2SIRQ |= (1 << 1); //enable transmit interrupt 00111 LPC_I2S->I2SIRQ |= (0 << 16); //set I2STXFIFO depth to 0 words 00112 break; 00113 default: 00114 break; 00115 #elif defined(TARGET_LPC4088) 00116 switch(mode){ 00117 case(0): 00118 LPC_I2S->IRQ |= (0 << 0); //disable receive interrupt 00119 LPC_I2S->IRQ |= (0 << 1); //disable transmit interrupt 00120 break; 00121 case(1): 00122 LPC_I2S->IRQ |= (0 << 0); //disable receive interrupt 00123 LPC_I2S->IRQ |= (1 << 1); //enable transmit interrupt 00124 LPC_I2S->IRQ |= (0 << 16); //set I2STXFIFO depth to 0 words 00125 break; 00126 case(2): 00127 LPC_I2S->IRQ |= (1 << 0); //enable receive interrupt 00128 LPC_I2S->IRQ |= (0 << 1); //disable transmit interrupt 00129 LPC_I2S->IRQ |= (4 << 8); //set I2SRXFIFO depth to 4 words 00130 break; 00131 case(3): 00132 LPC_I2S->IRQ |= (1 << 0); //enable receive interrupt 00133 LPC_I2S->IRQ |= (4 << 8); //set I2SRXFIFO depth to 4 words 00134 LPC_I2S->IRQ |= (1 << 1); //enable transmit interrupt 00135 LPC_I2S->IRQ |= (0 << 16); //set I2STXFIFO depth to 0 words 00136 break; 00137 default: 00138 break; 00139 } 00140 #endif 00141 NVIC_SetPriority(I2S_IRQn, 0); 00142 NVIC_EnableIRQ(I2S_IRQn); //enable I2S interrupt in the NVIC 00143 } 00144 /****************************************************** 00145 * Function name: stop() 00146 * 00147 * Description: detach streamOut_ from ticker 00148 * 00149 * Parameters: none 00150 * Returns: none 00151 ******************************************************/ 00152 void I2SSlave::stop(void){ 00153 NVIC_DisableIRQ(I2S_IRQn); 00154 } 00155 /****************************************************** 00156 * Function name: read() 00157 * 00158 * Description: reads FIFORX buffer into [int32_t rxBuffer[8]] 00159 * 00160 * Parameters: none 00161 * Returns: none 00162 ******************************************************/ 00163 void I2SSlave::read(void){ 00164 #if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) 00165 rxBuffer[0] = LPC_I2S->I2SRXFIFO; 00166 rxBuffer[1] = LPC_I2S->I2SRXFIFO; 00167 rxBuffer[2] = LPC_I2S->I2SRXFIFO; 00168 rxBuffer[3] = LPC_I2S->I2SRXFIFO; 00169 #elif defined(TARGET_LPC4088) 00170 rxBuffer[0] = LPC_I2S->RXFIFO; 00171 rxBuffer[1] = LPC_I2S->RXFIFO; 00172 rxBuffer[2] = LPC_I2S->RXFIFO; 00173 rxBuffer[3] = LPC_I2S->RXFIFO; 00174 #endif 00175 } 00176 /****************************************************** 00177 * Function name: status_() 00178 * 00179 * Description: Read I2SSTATE register 00180 * 00181 * Parameters: none 00182 * Returns: int 00183 ******************************************************/ 00184 int I2SSlave::status(void){ 00185 #if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) 00186 return LPC_I2S->I2SSTATE; 00187 #elif defined(TARGET_LPC4088) 00188 return LPC_I2S->STATE; 00189 #endif 00190 } 00191 //Private functions 00192 /****************************************************** 00193 * Function name: initialize() 00194 * 00195 * Description: initialises I2S port 00196 * 00197 * Parameters: PinName tx_sda, PinName tx_ws, PinName clk, PinName rx_sda, PinName rx_ws 00198 * Returns: 0 = successful initialisation 00199 -1 = initialisation failure 00200 ******************************************************/ 00201 int I2SSlave::initialize_(PinName tx_sda, PinName tx_ws, PinName clk, PinName rx_sda, PinName rx_ws){ 00202 setPins_(tx_sda, tx_ws, clk, rx_sda, rx_ws); //designate pins 00203 LPC_SC->PCONP |= (1 << 27); 00204 //configure input/output register 00205 format_(bit_, mode_); 00206 #if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) 00207 //set mbed as SLAVE 00208 LPC_I2S->I2SDAO |= (1 << 5); 00209 LPC_I2S->I2SDAI |= (1 << 5); 00210 //clock mode 00211 setClocks_(4); 00212 //set slave mode 00213 modeConfig_(); 00214 //set receiver mode 00215 LPC_I2S->I2SRXMODE |= (1 << 1); 00216 //slave mode 00217 LPC_I2S->I2STXRATE = 0; 00218 LPC_I2S->I2SRXRATE = 0; 00219 //Start 00220 LPC_I2S->I2SDAO |= (0 << 3); 00221 LPC_I2S->I2SDAI |= (0 << 3); 00222 LPC_I2S->I2SDAO |= (0 << 4); 00223 LPC_I2S->I2SDAI |= (0 << 4); 00224 LPC_I2S->I2SDAO |= (0 << 15); 00225 #elif defined(TARGET_LPC4088) 00226 //set mbed as SLAVE 00227 LPC_I2S->DAO |= (1 << 5); 00228 LPC_I2S->DAI |= (1 << 5); 00229 //clock mode 00230 setClocks_(4); 00231 //set slave mode 00232 modeConfig_(); 00233 //set receiver mode 00234 LPC_I2S->RXMODE |= (1 << 1); 00235 //slave mode 00236 LPC_I2S->TXRATE = 0; 00237 LPC_I2S->RXRATE = 0; 00238 //Start 00239 LPC_I2S->DAO |= (0 << 3); 00240 LPC_I2S->DAI |= (0 << 3); 00241 LPC_I2S->DAO |= (0 << 4); 00242 LPC_I2S->DAI |= (0 << 4); 00243 LPC_I2S->DAO |= (0 << 15); 00244 #endif 00245 return 0; 00246 } 00247 /****************************************************** 00248 * Function name: setClocks_() 00249 * 00250 * Description: Set the division setting on the internal clocks 00251 * 00252 * Parameters: int divideBy 00253 * Returns: nothing 00254 ******************************************************/ 00255 void I2SSlave::setClocks_(int divideBy){ 00256 #if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) 00257 switch(divideBy){ 00258 case 1: 00259 LPC_SC->PCLKSEL1 |= (1 << 22); 00260 LPC_SC->PCLKSEL1 |= (0 << 23); 00261 break; 00262 case 2: 00263 LPC_SC->PCLKSEL1 |= (0 << 22); 00264 LPC_SC->PCLKSEL1 |= (1 << 23); 00265 break; 00266 case 4: 00267 LPC_SC->PCLKSEL1 |= (0 << 22); 00268 LPC_SC->PCLKSEL1 |= (0 << 23); 00269 break; 00270 case 8: 00271 LPC_SC->PCLKSEL1 |= (1 << 22); 00272 LPC_SC->PCLKSEL1 |= (1 << 23); 00273 break; 00274 default: 00275 break; 00276 } 00277 #elif defined(TARGET_LPC4088) 00278 switch(divideBy){ 00279 case 1: 00280 LPC_SC->PCLKSEL |= (1 << 22); 00281 LPC_SC->PCLKSEL |= (0 << 23); 00282 break; 00283 case 2: 00284 LPC_SC->PCLKSEL |= (0 << 22); 00285 LPC_SC->PCLKSEL |= (1 << 23); 00286 break; 00287 case 4: 00288 LPC_SC->PCLKSEL |= (0 << 22); 00289 LPC_SC->PCLKSEL |= (0 << 23); 00290 break; 00291 case 8: 00292 LPC_SC->PCLKSEL |= (1 << 22); 00293 LPC_SC->PCLKSEL |= (1 << 23); 00294 break; 00295 default: 00296 break; 00297 } 00298 #endif 00299 } 00300 /****************************************************** 00301 * Function name: setPins_() 00302 * 00303 * Description: set external pin configuration 00304 * 00305 * Parameters: PinName tx_sda, PinName tx_ws, PinName clk, PinName rx_sda, PinName rx_ws 00306 * Returns: none 00307 ******************************************************/ 00308 void I2SSlave::setPins_(PinName tx_sda, PinName tx_ws, PinName clk, PinName rx_sda, PinName rx_ws){ 00309 #if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) 00310 00311 00312 printf(" *** TAGET LPC1768 || LPC2368 ***"); 00313 00314 00315 if(rx_ws == p29){ 00316 LPC_PINCON->PINSEL0 |= (1 << 10); //set p29 as receive word select line 00317 } else { 00318 LPC_PINCON->PINSEL1 |= (2 << 16); //set p16 as receive word select line 00319 } 00320 if(rx_sda == p8){ 00321 LPC_PINCON->PINSEL0 |= (1 << 12); //set p8 as receive serial data line 00322 } else { 00323 LPC_PINCON->PINSEL1 |= (2 << 18); //set p17 as receive serial data line 00324 } 00325 LPC_PINCON->PINSEL0 |= (1 << 14); //set p7 as transmit clock line (only one of these) 00326 LPC_PINCON->PINSEL0 |= (1 << 16); //set p6 as word select line (only one of these) 00327 LPC_PINCON->PINSEL0 |= (1 << 18); //set p5 as transmit serial data line (only one of these) 00328 LPC_PINCON->PINSEL0 |= (0 << 8); //clear rx_clk 00329 #elif defined(TARGET_LPC4088) 00330 00331 printf(" *** TAGET LPC4088 ***"); 00332 00333 if(rx_ws == p33){ 00334 LPC_IOCON->P0_5 = (LPC_IOCON->P0_5 & ~7) | 1; //set p33 as receive word select line 00335 } else { 00336 LPC_IOCON->P0_24 = (LPC_IOCON->P0_24 & ~7) | 2; //set p16 as receive word select line 00337 } 00338 if(rx_sda == p14){ 00339 LPC_IOCON->P0_6 = (LPC_IOCON->P0_6 & ~7) | 1; //set p14 as receive serial data line 00340 } else { 00341 LPC_IOCON->P0_25 = (LPC_IOCON->P0_25 & ~7) | 2; //set p17 as receive serial data line 00342 } 00343 LPC_IOCON->P0_7 = (LPC_IOCON->P0_7 & ~7) | 1; //set p13 as transmit clock line (only one of these) 00344 LPC_IOCON->P0_8 = (LPC_IOCON->P0_8 & ~7) | 1; //set p12 as word select line (only one of these) 00345 LPC_IOCON->P0_9 = (LPC_IOCON->P0_9 & ~7) | 1; //set p11 as transmit serial data line (only one of these) 00346 LPC_IOCON->P0_23 = (LPC_IOCON->P0_4 & ~7); // p15 clear rx_clk 00347 LPC_IOCON->P0_23 = (LPC_IOCON->P0_23 & ~7); // p15clear rx_clk 00348 #endif 00349 } 00350 /****************************************************** 00351 * Function name: format_() 00352 * 00353 * Description: sets the bit length for writing and stereo or mono mode 00354 * 00355 * Parameters: int bit, bool mode 00356 * Returns: none 00357 ******************************************************/ 00358 void I2SSlave::format_(int bit, bool mode){ 00359 uint32_t bps= ((bit+1)*8)-1; 00360 #if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) 00361 LPC_I2S->I2SDAO &= (0x00 << 6); 00362 LPC_I2S->I2SDAO |= (bps << 6); 00363 //set bit length 00364 switch(bit){ 00365 case 8: 00366 LPC_I2S->I2SDAO &= 0xfffffffc; 00367 break; 00368 case 16: 00369 LPC_I2S->I2SDAO &= (0 << 1); 00370 LPC_I2S->I2SDAO |= (1 << 0); 00371 break; 00372 case 32: 00373 LPC_I2S->I2SDAO &= (0 << 1); 00374 LPC_I2S->I2SDAO |= (3 << 0); 00375 break; 00376 default: 00377 break; 00378 } 00379 //set audio mode 00380 if(mode == STEREO){ 00381 LPC_I2S->I2SDAO |= (0 << 2); 00382 } else { 00383 LPC_I2S->I2SDAO |= (1 << 2); 00384 } 00385 //set transmitter and receiver setting to be the same 00386 LPC_I2S->I2SDAI &= (0x00 << 6); 00387 LPC_I2S->I2SDAI |= (bps << 6); 00388 //set bit length 00389 switch(bit){ 00390 case 8: 00391 LPC_I2S->I2SDAI &= 0xfffffffc; 00392 break; 00393 case 16: 00394 LPC_I2S->I2SDAI &= (0 << 1); 00395 LPC_I2S->I2SDAI |= (1 << 0); 00396 break; 00397 case 32: 00398 LPC_I2S->I2SDAI &= (0 << 1); 00399 LPC_I2S->I2SDAI |= (3 << 0); 00400 break; 00401 default: 00402 break; 00403 } 00404 //set audio mode 00405 if(mode == STEREO){ 00406 LPC_I2S->I2SDAI |= (0 << 2); 00407 } else { 00408 LPC_I2S->I2SDAI |= (1 << 2); 00409 } 00410 #elif defined(TARGET_LPC4088) 00411 LPC_I2S->DAO &= (0x00 << 6); 00412 LPC_I2S->DAO |= (bps << 6); 00413 //set bit length 00414 switch(bit){ 00415 case 8: 00416 LPC_I2S->DAO &= 0xfffffffc; 00417 break; 00418 case 16: 00419 LPC_I2S->DAO &= (0 << 1); 00420 LPC_I2S->DAO |= (1 << 0); 00421 break; 00422 case 32: 00423 LPC_I2S->DAO &= (0 << 1); 00424 LPC_I2S->DAO |= (3 << 0); 00425 break; 00426 default: 00427 break; 00428 } 00429 //set audio mode 00430 if(mode == STEREO){ 00431 LPC_I2S->DAO |= (0 << 2); 00432 } else { 00433 LPC_I2S->DAO |= (1 << 2); 00434 } 00435 //set transmitter and receiver setting to be the same 00436 LPC_I2S->DAI &= (0x00 << 6); 00437 LPC_I2S->DAI |= (bps << 6); 00438 //set bit length 00439 switch(bit){ 00440 case 8: 00441 LPC_I2S->DAI &= 0xfffffffc; 00442 break; 00443 case 16: 00444 LPC_I2S->DAI &= (0 << 1); 00445 LPC_I2S->DAI |= (1 << 0); 00446 break; 00447 case 32: 00448 LPC_I2S->DAI &= (0 << 1); 00449 LPC_I2S->DAI |= (3 << 0); 00450 break; 00451 default: 00452 break; 00453 } 00454 //set audio mode 00455 if(mode == STEREO){ 00456 LPC_I2S->DAI |= (0 << 2); 00457 } else { 00458 LPC_I2S->DAI |= (1 << 2); 00459 } 00460 #endif 00461 } 00462 /****************************************************** 00463 * Function name: modeConfig_() 00464 * 00465 * Description: Set slave mode 00466 * 00467 * Parameters: none 00468 * Returns: none 00469 ******************************************************/ 00470 void I2SSlave::modeConfig_(void){ 00471 #if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) 00472 LPC_I2S->I2STXMODE |= (0x0 << 0); 00473 LPC_I2S->I2SRXMODE |= (0x0 << 0); 00474 #elif defined(TARGET_LPC4088) 00475 LPC_I2S->TXMODE |= (0x0 << 0); 00476 LPC_I2S->RXMODE |= (0x0 << 0); 00477 #endif 00478 } 00479 /****************************************************** 00480 * Function name: storePins_() 00481 * 00482 * Description: set external pin configuration 00483 * 00484 * Parameters: PinName tx_sda, PinName tx_ws, PinName clk, PinName rx_sda, PinName rx_ws 00485 * Returns: none 00486 ******************************************************/ 00487 void I2SSlave::storePins_(PinName tx_sda, PinName tx_ws, PinName clk, PinName rx_sda, PinName rx_ws){ 00488 tx_sda_ = tx_sda; 00489 tx_ws_ = tx_ws; 00490 clk_ = clk; 00491 rx_sda_ = rx_sda; 00492 rx_ws_ = rx_ws; 00493 }
Generated on Mon Jul 18 2022 19:20:45 by 1.7.2