Dependents: playback FTSESpeech i2s_audio_echo i2s_audio_sampler ... more
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 LPC_I2S->I2STXFIFO = buffer[i]; 00076 } 00077 } 00078 /****************************************************** 00079 * Function name: start() 00080 * 00081 * Description: attach streamOut_ function to ticker interrupt 00082 * 00083 * Parameters: none 00084 * Returns: none 00085 ******************************************************/ 00086 void I2SSlave::start(int mode){ 00087 switch(mode){ 00088 case(0): 00089 LPC_I2S->I2SIRQ |= (0 << 0); //disable receive interrupt 00090 LPC_I2S->I2SIRQ |= (0 << 1); //disable transmit interrupt 00091 break; 00092 case(1): 00093 LPC_I2S->I2SIRQ |= (0 << 0); //disable receive interrupt 00094 LPC_I2S->I2SIRQ |= (1 << 1); //enable transmit interrupt 00095 LPC_I2S->I2SIRQ |= (0 << 16); //set I2STXFIFO depth to 0 words 00096 break; 00097 case(2): 00098 LPC_I2S->I2SIRQ |= (1 << 0); //enable receive interrupt 00099 LPC_I2S->I2SIRQ |= (0 << 1); //disable transmit interrupt 00100 LPC_I2S->I2SIRQ |= (4 << 8); //set I2SRXFIFO depth to 4 words 00101 break; 00102 case(3): 00103 LPC_I2S->I2SIRQ |= (1 << 0); //enable receive interrupt 00104 LPC_I2S->I2SIRQ |= (4 << 8); //set I2SRXFIFO depth to 4 words 00105 LPC_I2S->I2SIRQ |= (1 << 1); //enable transmit interrupt 00106 LPC_I2S->I2SIRQ |= (0 << 16); //set I2STXFIFO depth to 0 words 00107 break; 00108 default: 00109 break; 00110 } 00111 NVIC_SetPriority(I2S_IRQn, 0); 00112 NVIC_EnableIRQ(I2S_IRQn); //enable I2S interrupt in the NVIC 00113 } 00114 /****************************************************** 00115 * Function name: stop() 00116 * 00117 * Description: detach streamOut_ from ticker 00118 * 00119 * Parameters: none 00120 * Returns: none 00121 ******************************************************/ 00122 void I2SSlave::stop(void){ 00123 NVIC_DisableIRQ(I2S_IRQn); 00124 } 00125 /****************************************************** 00126 * Function name: read() 00127 * 00128 * Description: reads FIFORX buffer into [int32_t rxBuffer[8]] 00129 * 00130 * Parameters: none 00131 * Returns: none 00132 ******************************************************/ 00133 void I2SSlave::read(void){ 00134 rxBuffer[0] = LPC_I2S->I2SRXFIFO; 00135 rxBuffer[1] = LPC_I2S->I2SRXFIFO; 00136 rxBuffer[2] = LPC_I2S->I2SRXFIFO; 00137 rxBuffer[3] = LPC_I2S->I2SRXFIFO; 00138 } 00139 /****************************************************** 00140 * Function name: status_() 00141 * 00142 * Description: Read I2SSTATE register 00143 * 00144 * Parameters: none 00145 * Returns: int 00146 ******************************************************/ 00147 int I2SSlave::status(void){ 00148 return LPC_I2S->I2SSTATE; 00149 } 00150 //Private functions 00151 /****************************************************** 00152 * Function name: initialize() 00153 * 00154 * Description: initialises I2S port 00155 * 00156 * Parameters: PinName tx_sda, PinName tx_ws, PinName clk, PinName rx_sda, PinName rx_ws 00157 * Returns: 0 = successful initialisation 00158 -1 = initialisation failure 00159 ******************************************************/ 00160 int I2SSlave::initialize_(PinName tx_sda, PinName tx_ws, PinName clk, PinName rx_sda, PinName rx_ws){ 00161 setPins_(tx_sda, tx_ws, clk, rx_sda, rx_ws); //designate pins 00162 LPC_SC->PCONP |= (1 << 27); 00163 //configure input/output register 00164 format_(bit_, mode_); 00165 //set mbed as SLAVE 00166 LPC_I2S->I2SDAO |= (1 << 5); 00167 LPC_I2S->I2SDAI |= (1 << 5); 00168 //clock mode 00169 setClocks_(4); 00170 //set slave mode 00171 modeConfig_(); 00172 //set receiver mode 00173 LPC_I2S->I2SRXMODE |= (1 << 1); 00174 //slave mode 00175 LPC_I2S->I2STXRATE = 0; 00176 LPC_I2S->I2SRXRATE = 0; 00177 //Start 00178 LPC_I2S->I2SDAO |= (0 << 3); 00179 LPC_I2S->I2SDAI |= (0 << 3); 00180 LPC_I2S->I2SDAO |= (0 << 4); 00181 LPC_I2S->I2SDAI |= (0 << 4); 00182 LPC_I2S->I2SDAO |= (0 << 15); 00183 return 0; 00184 } 00185 /****************************************************** 00186 * Function name: setClocks_() 00187 * 00188 * Description: Set the division setting on the internal clocks 00189 * 00190 * Parameters: int divideBy 00191 * Returns: nothing 00192 ******************************************************/ 00193 void I2SSlave::setClocks_(int divideBy){ 00194 switch(divideBy){ 00195 case 1: 00196 LPC_SC->PCLKSEL1 |= (1 << 22); 00197 LPC_SC->PCLKSEL1 |= (0 << 23); 00198 break; 00199 case 2: 00200 LPC_SC->PCLKSEL1 |= (0 << 22); 00201 LPC_SC->PCLKSEL1 |= (1 << 23); 00202 break; 00203 case 4: 00204 LPC_SC->PCLKSEL1 |= (0 << 22); 00205 LPC_SC->PCLKSEL1 |= (0 << 23); 00206 break; 00207 case 8: 00208 LPC_SC->PCLKSEL1 |= (1 << 22); 00209 LPC_SC->PCLKSEL1 |= (1 << 23); 00210 break; 00211 default: 00212 break; 00213 } 00214 } 00215 /****************************************************** 00216 * Function name: setPins_() 00217 * 00218 * Description: set external pin configuration 00219 * 00220 * Parameters: PinName tx_sda, PinName tx_ws, PinName clk, PinName rx_sda, PinName rx_ws 00221 * Returns: none 00222 ******************************************************/ 00223 void I2SSlave::setPins_(PinName tx_sda, PinName tx_ws, PinName clk, PinName rx_sda, PinName rx_ws){ 00224 if(rx_ws == p29){ 00225 LPC_PINCON->PINSEL0 |= (1 << 10); //set p29 as receive word select line 00226 } else { 00227 LPC_PINCON->PINSEL1 |= (2 << 16); //set p16 as receive word select line 00228 } 00229 if(rx_sda == p8){ 00230 LPC_PINCON->PINSEL0 |= (1 << 12); //set p8 as receive serial data line 00231 } else { 00232 LPC_PINCON->PINSEL1 |= (2 << 18); //set p17 as receive serial data line 00233 } 00234 LPC_PINCON->PINSEL0 |= (1 << 14); //set p7 as transmit clock line (only one of these) 00235 LPC_PINCON->PINSEL0 |= (1 << 16); //set p6 as word select line (only one of these) 00236 LPC_PINCON->PINSEL0 |= (1 << 18); //set p5 as transmit serial data line (only one of these) 00237 LPC_PINCON->PINSEL0 |= (0 << 8); //clear rx_clk 00238 } 00239 /****************************************************** 00240 * Function name: format_() 00241 * 00242 * Description: sets the bit length for writing and stereo or mono mode 00243 * 00244 * Parameters: int bit, bool mode 00245 * Returns: none 00246 ******************************************************/ 00247 void I2SSlave::format_(int bit, bool mode){ 00248 uint32_t bps= ((bit+1)*8)-1; 00249 LPC_I2S->I2SDAO &= (0x00 << 6); 00250 LPC_I2S->I2SDAO |= (bps << 6); 00251 //set bit length 00252 switch(bit){ 00253 case 8: 00254 LPC_I2S->I2SDAO &= 0xfffffffc; 00255 break; 00256 case 16: 00257 LPC_I2S->I2SDAO &= (0 << 1); 00258 LPC_I2S->I2SDAO |= (1 << 0); 00259 break; 00260 case 32: 00261 LPC_I2S->I2SDAO &= (0 << 1); 00262 LPC_I2S->I2SDAO |= (3 << 0); 00263 break; 00264 default: 00265 break; 00266 } 00267 //set audio mode 00268 if(mode == STEREO){ 00269 LPC_I2S->I2SDAO |= (0 << 2); 00270 } else { 00271 LPC_I2S->I2SDAO |= (1 << 2); 00272 } 00273 //set transmitter and receiver setting to be the same 00274 LPC_I2S->I2SDAI &= (0x00 << 6); 00275 LPC_I2S->I2SDAI |= (bps << 6); 00276 //set bit length 00277 switch(bit){ 00278 case 8: 00279 LPC_I2S->I2SDAI &= 0xfffffffc; 00280 break; 00281 case 16: 00282 LPC_I2S->I2SDAI &= (0 << 1); 00283 LPC_I2S->I2SDAI |= (1 << 0); 00284 break; 00285 case 32: 00286 LPC_I2S->I2SDAI &= (0 << 1); 00287 LPC_I2S->I2SDAI |= (3 << 0); 00288 break; 00289 default: 00290 break; 00291 } 00292 //set audio mode 00293 if(mode == STEREO){ 00294 LPC_I2S->I2SDAI |= (0 << 2); 00295 } else { 00296 LPC_I2S->I2SDAI |= (1 << 2); 00297 } 00298 } 00299 /****************************************************** 00300 * Function name: modeConfig_() 00301 * 00302 * Description: Set slave mode 00303 * 00304 * Parameters: none 00305 * Returns: none 00306 ******************************************************/ 00307 void I2SSlave::modeConfig_(void){ 00308 LPC_I2S->I2STXMODE |= (0x0 << 0); 00309 LPC_I2S->I2SRXMODE |= (0x0 << 0); 00310 } 00311 /****************************************************** 00312 * Function name: storePins_() 00313 * 00314 * Description: set external pin configuration 00315 * 00316 * Parameters: PinName tx_sda, PinName tx_ws, PinName clk, PinName rx_sda, PinName rx_ws 00317 * Returns: none 00318 ******************************************************/ 00319 void I2SSlave::storePins_(PinName tx_sda, PinName tx_ws, PinName clk, PinName rx_sda, PinName rx_ws){ 00320 tx_sda_ = tx_sda; 00321 tx_ws_ = tx_ws; 00322 clk_ = clk; 00323 rx_sda_ = rx_sda; 00324 rx_ws_ = rx_ws; 00325 }
Generated on Tue Jul 12 2022 18:43:37 by 1.7.2