[ FORK ] I2S library for FRDM 64F, forked from p07gbar/I2S

Fork of I2S by Giles Barton-Owen

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers I2S.cpp Source File

I2S.cpp

00001 #include "I2S.h"
00002 
00003 #define I2S_DF_WORDWIDTH                16
00004 #define I2S_DF_SAMPLERATE               32000
00005 #define I2S_DF_MASTERSLAVE              I2S_MASTER
00006 #define I2S_DF_STEREOMONO               I2S_STEREO
00007 #define I2S_DF_MUTED                    I2S_UNMUTED
00008 #define I2S_DF_INTERRUPT_FIFO_LEVEL     4
00009 
00010 #define I2S_MAX_DENOMINATOR             256
00011 #define I2S_MAX_NUMERATOR               256
00012 #define I2S_MAX_BITRATE_DIV             64
00013 
00014 #define I2S_PCLK_RATE                   12288000
00015 
00016 FunctionPointer I2S::I2STXISR;
00017 FunctionPointer I2S::I2SRXISR;
00018 
00019 bool I2S::txisr;
00020 bool I2S::rxisr;
00021 
00022 I2S::I2S(bool rxtx, PinName SerialData, PinName WordSelect, PinName BitClk)
00023 {
00024     SIM->SCGC6 &= ~(SIM_SCGC6_I2S_MASK);
00025     SIM->SCGC6 |= SIM_SCGC6_I2S_MASK;
00026 
00027     NVIC_DisableIRQ (I2S0_Tx_IRQn);
00028     NVIC_DisableIRQ (I2S0_Rx_IRQn);
00029 
00030     _SerialData = SerialData;
00031     _WordSelect = WordSelect;
00032     _BitClk = BitClk;
00033     _rxtx = rxtx;
00034 
00035     WordSelect_d = true;
00036     BitClk_d = true;
00037     MasterClk_d = false;
00038 
00039     fourwire = false;
00040 
00041     reg_write_err = 0;
00042 
00043     pin_setup();
00044 
00045     if (pin_setup_err != 0) {
00046         perror("I2S Pins incorrectly defined.");
00047     }
00048 
00049     defaulter();
00050     _i2s_init();
00051 }
00052 
00053 //I2S::I2S(bool rxtx, PinName SerialData)
00054 //{
00055 //    NVIC_DisableIRQ (I2S0_Tx_IRQn);
00056 //    NVIC_DisableIRQ (I2S0_Rx_IRQn);
00057 //
00058 //    _SerialData = SerialData;
00059 //    _rxtx = rxtx;
00060 //
00061 //    WordSelect_d = false;
00062 //    BitClk_d = false;
00063 //    MasterClk_d = false;
00064 //
00065 //    fourwire = false;
00066 //
00067 //    reg_write_err = 0;
00068 //
00069 //    pin_setup();
00070 //
00071 //    if (pin_setup_err != 0) {
00072 //        perror("I2S Pins incorrectly defined.");
00073 //    }
00074 //
00075 //    defaulter();
00076 //}
00077 //
00078 //I2S::I2S(bool rxtx, PinName SerialData, bool fourwiremode)
00079 //{
00080 //    NVIC_DisableIRQ (I2S0_Tx_IRQn);
00081 //    NVIC_DisableIRQ (I2S0_Rx_IRQn);
00082 //
00083 //    _SerialData = SerialData;
00084 //    _rxtx = rxtx;
00085 //
00086 //    WordSelect_d = false;
00087 //    BitClk_d = false;
00088 //    MasterClk_d = false;
00089 //
00090 //    reg_write_err = 0;
00091 //
00092 //    fourwire = fourwiremode;
00093 //
00094 //    pin_setup();
00095 //
00096 //    if (pin_setup_err != 0) {
00097 //        perror("I2S Pins incorrectly defined.");
00098 //    }
00099 //
00100 //    defaulter();
00101 //}
00102 //
00103 //I2S::I2S(bool rxtx, PinName SerialData, PinName WordSelect, bool fourwiremode)
00104 //{
00105 //    NVIC_DisableIRQ (I2S0_Tx_IRQn);
00106 //    NVIC_DisableIRQ (I2S0_Rx_IRQn);
00107 //
00108 //    _SerialData = SerialData;
00109 //    _WordSelect = WordSelect;
00110 //    _rxtx = rxtx;
00111 //
00112 //    WordSelect_d = true;
00113 //    BitClk_d = false;
00114 //    MasterClk_d = false;
00115 //
00116 //    reg_write_err = 0;
00117 //
00118 //    fourwire = fourwiremode;
00119 //
00120 //    pin_setup();
00121 //
00122 //    if (pin_setup_err != 0) {
00123 //        perror("I2S Pins incorrectly defined.");
00124 //    }
00125 //
00126 //    defaulter();
00127 //}
00128 //
00129 //I2S::I2S(bool rxtx, PinName SerialData, PinName WordSelect)
00130 //{
00131 //    NVIC_DisableIRQ (I2S0_Tx_IRQn);
00132 //    NVIC_DisableIRQ (I2S0_Rx_IRQn);
00133 //
00134 //    _SerialData = SerialData;
00135 //    _WordSelect = WordSelect;
00136 //    _rxtx = rxtx;
00137 //
00138 //    WordSelect_d = true;
00139 //    BitClk_d = false;
00140 //    MasterClk_d = false;
00141 //
00142 //    reg_write_err = 0;
00143 //
00144 //    fourwire = false;
00145 //
00146 //    pin_setup();
00147 //
00148 //    if (pin_setup_err != 0) {
00149 //        perror("I2S Pins incorrectly defined.");
00150 //    }
00151 //
00152 //    defaulter();
00153 //}
00154 
00155 I2S::~I2S()
00156 {
00157     NVIC_DisableIRQ (I2S0_Tx_IRQn);
00158     NVIC_DisableIRQ (I2S0_Rx_IRQn);
00159 
00160     deallocating = true;
00161     pin_setup();
00162     write_registers();
00163 }
00164 
00165 void I2S::defaulter()
00166 {
00167     I2S0->TCSR |= 1u<<31;
00168 
00169     stop();
00170     master = false;
00171     deallocating = false;
00172 
00173     frequency(I2S_DF_SAMPLERATE);
00174     wordsize(I2S_DF_WORDWIDTH);
00175     masterslave (I2S_DF_MASTERSLAVE);
00176     stereomono (I2S_DF_STEREOMONO);
00177     set_interrupt_fifo_level(I2S_DF_INTERRUPT_FIFO_LEVEL);
00178     mute (I2S_DF_MUTED);
00179 
00180     NVIC_SetVector(I2S0_Tx_IRQn, (uint32_t) & _i2sisr);
00181     NVIC_EnableIRQ (I2S0_Tx_IRQn);
00182 }
00183 
00184 void I2S::write(char buf[], int len)
00185 {
00186     if (_rxtx == I2S_TRANSMIT) {
00187         if (len > max_fifo_points())
00188             len = max_fifo_points();
00189         if (len <= 0)
00190             return;
00191         int temp = 0;
00192         for (int i = 0; i < len; i += 4) {
00193             temp = 0;
00194             for (int j = 0; j < 4; j++) {
00195                 temp |= int(buf[i + j]) << (j * 8);
00196             }
00197             I2S0->TDR[0] = temp;
00198         }
00199     }
00200 
00201 }
00202 
00203 void I2S::write(int buf[], int len)
00204 {
00205     if (_rxtx == I2S_TRANSMIT && wordwidth > 0) {
00206         if (len > max_fifo_points()) {
00207             len = max_fifo_points();
00208             printf("Trying to write too much data!\n\r");
00209         }
00210         if (len <= 0)
00211             return;
00212         uint32_t temp = 0;
00213         int increment = 32 / wordwidth;
00214         unsigned char recast[] =
00215         { 0, 0, 0, 0 };
00216         for (int i = 0; i < len; i += increment) {
00217             temp = 0;
00218 
00219             switch (wordwidth) {
00220 
00221                 case 8:
00222 
00223                     recast[0] = (int8_t) buf[i + 0];
00224                     recast[1] = (int8_t) buf[i + 1];
00225                     recast[2] = (int8_t) buf[i + 2];
00226                     recast[3] = (int8_t) buf[i + 3];
00227                     break;
00228                 case 16:
00229                     recast[0] = (((int16_t) buf[i + 0]) >> 0) & 0xFF;
00230                     recast[1] = (((int16_t) buf[i + 0]) >> 8) & 0xFF;
00231                     recast[2] = (((int16_t) buf[i + 1]) >> 0) & 0xFF;
00232                     recast[3] = (((int16_t) buf[i + 1]) >> 8) & 0xFF;
00233                     break;
00234                 case 32:
00235                     recast[0] = (((int32_t) buf[i + 0]) >> 0) & 0xFF;
00236                     recast[1] = (((int32_t) buf[i + 0]) >> 8) & 0xFF;
00237                     recast[2] = (((int32_t) buf[i + 0]) >> 16) & 0xFF;
00238                     recast[3] = (((int32_t) buf[i + 0]) >> 24) & 0xFF;
00239                     break;
00240 
00241             }
00242             for (int j = 0; j < 4; j++) {
00243 
00244                 temp |= recast[j] << (j * 8);
00245             }
00246 
00247             //if(((temp >> 16) & 0xFFFF) == 0xFFFF) printf("Hmmm %x %x %x\n\r",temp, increment,i); //|| temp &0xFFFF == 0xFFFF
00248             //if((buf[i]-buf[i+1])>5000 || (buf[i]-buf[i+1])<-5000) printf("J:%i,%i\n\r",buf[i],buf[i+1]);
00249             //printf("%x\n",temp);
00250             I2S0->TDR[0] = temp;
00251         }
00252     }
00253 }
00254 
00255 void I2S::write(int bufr[], int bufl[], int len)
00256 {
00257     //#TODO: Write this!
00258 }
00259 
00260 int I2S::read()
00261 {
00262     return I2S0->RDR[0];
00263 }
00264 
00265 void I2S::read(char buf[], int len)
00266 {
00267     bool len_valid = true;
00268     if (len <= 0)
00269         return;
00270     if (len >= fifo_points())
00271         len = fifo_points();
00272     int temp[8];
00273     int counter = 0;
00274     int increment = 4;            //32/wordwidth;
00275     int fifo_levl = fifo_level();
00276     while (counter < fifo_levl && len_valid) {
00277         temp[counter] = I2S0->RDR[0];
00278         for (int j = 0; j < increment; j++) {
00279             if ((counter * 4) + j > len) {
00280                 len_valid = false;
00281                 break;
00282             }
00283             buf[counter + j] = temp[counter] >> (j * 8);
00284 
00285         }
00286         counter++;
00287     }
00288 }
00289 
00290 void I2S::read(int buf[], int len)
00291 {
00292     bool len_valid = true;
00293     if (len <= 0)
00294         return;
00295     if (len >= fifo_points())
00296         len = fifo_points();
00297     int temp[8];
00298     int counter = 0;
00299     int increment = 32 / wordwidth;
00300     int fifo_levl = fifo_level();
00301     while (counter < fifo_levl && len_valid) {
00302         temp[counter] = I2S0->RDR[0];
00303         for (int j = 0; j < increment; j++) {
00304             if ((counter * increment) + j > len) {
00305                 len_valid = false;
00306                 break;
00307             }
00308             buf[counter + j] = temp[counter] >> (j * wordwidth);
00309 
00310         }
00311         counter++;
00312     }
00313 }
00314 
00315 void I2S::read(int bufr[], int bufl[], int len)
00316 {
00317     //#TODO: Write this
00318 }
00319 
00320 int I2S::max_fifo_points()
00321 {
00322     switch (wordwidth) {
00323         case 8:
00324             return (4 * 8);
00325         case 16:
00326             return (2 * 8);
00327         case 32:
00328             return 8;
00329         default:
00330             return 0;
00331     }
00332 }
00333 
00334 int I2S::fifo_points()
00335 {
00336     switch (wordwidth) {
00337         case 8:
00338             return (4 * fifo_level());
00339         case 16:
00340             return (2 * fifo_level());
00341         case 32:
00342             return fifo_level();
00343         default:
00344             return 0;
00345     }
00346 }
00347 
00348 void I2S::power(bool pwr)
00349 {
00350     if (pwr) {
00351         stopped = false;
00352     } else {
00353         stopped = true;
00354     }
00355     write_registers();
00356 }
00357 
00358 void I2S::masterslave(bool mastermode)
00359 {
00360     if (mastermode == I2S_MASTER) {
00361         master = true;
00362     } else {
00363         master = false;
00364     }
00365     write_registers();
00366 }
00367 
00368 void I2S::wordsize(int words)
00369 {
00370     wordwidth = 16;
00371 //    write_registers();
00372 }
00373 
00374 void I2S::mclk_freq(int freq)
00375 {
00376     mclk_frequency = 12288000;
00377 //    write_registers();
00378 }
00379 
00380 void I2S::frequency(int desired_freq)
00381 {
00382     freq = 32000;
00383     _i2s_set_rate(freq);
00384     //write_registers();
00385 }
00386 
00387 int I2S::fifo_level()
00388 {
00389     int level = 0;
00390     if (_rxtx == I2S_TRANSMIT) {
00391         level = I2S0->TFR[0];
00392         level >>= 16;
00393         level &= 0xF;
00394     } else {
00395         level = I2S0->TFR[0];
00396         level >>= 0;
00397         level &= 0xF;
00398     }
00399     return level;
00400 }
00401 
00402 void I2S::stereomono(bool stereomode)
00403 {
00404     stereo = true;
00405     /*
00406         if (stereomode == I2S_STEREO) {
00407             stereo = true;
00408         } else {
00409             stereo = false;
00410         }
00411     */
00412 }
00413 
00414 void I2S::mute()
00415 {
00416     muted = true;
00417 //    write_registers();
00418 }
00419 
00420 void I2S::mute(bool mute_en)
00421 {
00422     muted = mute_en;
00423 //    write_registers();
00424 }
00425 
00426 void I2S::stop()
00427 {
00428     stopped = true;
00429 //    write_registers();
00430 }
00431 
00432 void I2S::set_interrupt_fifo_level(int level)
00433 {
00434     interrupt_fifo_level = 4;
00435 //    write_registers();
00436 }
00437 
00438 void I2S::start()
00439 {
00440     stopped = false;
00441     muted = false;
00442 //    write_registers();
00443 }
00444 
00445 bool I2S::setup_ok()
00446 {
00447     if ((reg_write_err + pin_setup_err) > 0)
00448         return false;
00449     else
00450         return true;
00451 }
00452 
00453 void I2S::pin_setup()
00454 {
00455     pin_setup_err = 0;
00456 
00457     if (_rxtx == I2S_TRANSMIT) {
00458         printf("\n\rSetting up pins....\n\r");
00459         if (_SerialData != PTC1)
00460             pin_setup_err++;
00461         if (_WordSelect != PTB19 && WordSelect_d == true)
00462             pin_setup_err++;
00463         if (_BitClk != PTB18 && BitClk_d == true)
00464             pin_setup_err++;
00465         printf("Hmm....%i\n\r", pin_setup_err);
00466     } else {
00467         if (_SerialData != PTC5)
00468             pin_setup_err++;
00469         if (_WordSelect != PTC7 && WordSelect_d == true)
00470             pin_setup_err++;
00471         if (_BitClk != PTC6 && BitClk_d == true)
00472             pin_setup_err++;
00473     }
00474     /*
00475      * @param SerialData    The serial data pin
00476      * @param WordSelect    The word select pin
00477      * @param BitClk    The clock pin
00478     PORTC->PCR[8]  &= PORT_PCR_MUX_MASK;
00479     PORTC->PCR[8]  |= PORT_PCR_MUX(0x04); // PTC8 I2S0_MCLK
00480 
00481     PORTC->PCR[5]  &= PORT_PCR_MUX_MASK;
00482     PORTC->PCR[5]  |= PORT_PCR_MUX(0x04); // PTC5 I2S0_RXD0
00483 
00484     PORTC->PCR[7] &= PORT_PCR_MUX_MASK;
00485     PORTC->PCR[7] |= PORT_PCR_MUX(0x04); // PTC7 I2S0_RX_FS
00486 
00487     PORTC->PCR[6] &= PORT_PCR_MUX_MASK;
00488     PORTC->PCR[6] |= PORT_PCR_MUX(0x04); // PTC6 I2S0_RX_BCLK
00489 
00490     PORTC->PCR[1] &= PORT_PCR_MUX_MASK;
00491     PORTC->PCR[1] |= PORT_PCR_MUX(0x04); // PTC1 I2S0_TXD0
00492 
00493     PORTB->PCR[19] &= PORT_PCR_MUX_MASK;
00494     PORTB->PCR[19] |= PORT_PCR_MUX(0x04); // PTB19 I2S0_TX_FS
00495 
00496     PORTB->PCR[18] &= PORT_PCR_MUX_MASK;
00497     PORTB->PCR[18] |= PORT_PCR_MUX(0x04); // PTB18 I2S0_TX_BCLK
00498      */
00499 
00500     SIM_SCGC5 |= SIM_SCGC5_PORTB_MASK | SIM_SCGC5_PORTC_MASK;
00501     if (pin_setup_err == 0) {
00502 
00503         PORTC->PCR[8]  &= PORT_PCR_MUX_MASK;
00504         PORTC->PCR[8]  |= PORT_PCR_MUX(0x04); // PTC8 I2S0_MCLK
00505 
00506         if (_rxtx == I2S_TRANSMIT) {
00507             int val1 = 1;
00508             if (deallocating) {
00509                 val1 = 0;
00510             }
00511 
00512             PORTC->PCR[1] &= PORT_PCR_MUX_MASK;
00513             PORTC->PCR[1] |= PORT_PCR_MUX(0x04); // PTC1 I2S0_TXD0
00514 
00515             if (WordSelect_d == true) {
00516                 PORTB->PCR[18] &= PORT_PCR_MUX_MASK;
00517                 PORTB->PCR[18] |= PORT_PCR_MUX(0x04); // PTB18 I2S0_TX_BCLK
00518             }
00519             if (BitClk_d == true) {
00520                 PORTB->PCR[19] &= PORT_PCR_MUX_MASK;
00521                 PORTB->PCR[19] |= PORT_PCR_MUX(0x04); // PTB19 I2S0_TX_FS
00522             }
00523 
00524         } else {
00525             int val1 = 1;
00526             int val2 = 2;
00527             if (deallocating) {
00528                 val1 = 0;
00529                 val2 = 0;
00530             }
00531 
00532             PORTC->PCR[5]  &= PORT_PCR_MUX_MASK;
00533             PORTC->PCR[5]  |= PORT_PCR_MUX(0x04); // PTC5 I2S0_RXD0
00534 
00535             if (WordSelect_d == true) {
00536                 PORTB->PCR[18] &= PORT_PCR_MUX_MASK;
00537                 PORTB->PCR[18] |= PORT_PCR_MUX(0x04); // PTB18 I2S0_TX_BCLK
00538             }
00539 
00540             if (BitClk_d == true) {
00541                 PORTC->PCR[6] &= PORT_PCR_MUX_MASK;
00542                 PORTC->PCR[6] |= PORT_PCR_MUX(0x04); // PTC6 I2S0_RX_BCLK
00543             }
00544         }
00545     }
00546 }
00547 
00548 
00549 
00550 
00551 
00552 
00553 
00554 void I2S::_set_clock_112896(void)
00555 {
00556 //    SIM->SCGC6 &= ~(SIM_SCGC6_I2S_MASK);
00557 
00558     // output = input[(I2SFRAC+1) / (I2SDIV+1) ] = (48* (4/17))
00559     // SIM_CLKDIV2 |= SIM_CLKDIV2_I2SDIV(16) | SIM_CLKDIV2_I2SFRAC(3);
00560     I2S0->MDR = I2S_MDR_FRACT(3) | I2S_MDR_DIVIDE(16);
00561 //    SIM->SCGC6 |= SIM_SCGC6_I2S_MASK;
00562 }
00563 void I2S::_set_clock_122800(void)
00564 {
00565     // output = input [(I2SFRAC+1) / (I2SDIV+1) ] = (48M* (32/125))
00566     // SIM_CLKDIV2 |= SIM_CLKDIV2_I2SDIV(124) | SIM_CLKDIV2_I2SFRAC(31);
00567     I2S0->MDR = I2S_MDR_FRACT(63) | I2S_MDR_DIVIDE(624);
00568 }
00569 void I2S::_i2s_init(void)
00570 {
00571 #define I2S_CONFIG_WORDS_IN_A_FRAME 2
00572 #define I2S_CONFIG_BITS_IN_A_WORD   16
00573 
00574     I2S0->TCR1 = 4;// 6;    // water mark
00575     I2S0->TCR2 |= (0<<30) | // master mode(Async mode)
00576                  (1<<26) | // MSEL = MCLK
00577                  (1<<25) | // CLK = drive on falling edge
00578                  (1<<24) ; // CLK = OUTPUT
00579 
00580     I2S0->TCR3 = (1<<16); // enable channel 0
00581 
00582     I2S0->TCR4 = ((I2S_CONFIG_WORDS_IN_A_FRAME-1)<<16)  | // words in a frame
00583                 ((I2S_CONFIG_BITS_IN_A_WORD  -1)<<8)   | // bits in a word
00584                 (1<<4)                                | // MSB
00585                 (1<<3)                                | // one bit early
00586                 (1<<1)                                | // frame active low
00587                 (1<<0)                                ; // frame = output
00588 
00589     I2S0->TCR5 = ((I2S_CONFIG_BITS_IN_A_WORD-1) <<24) | // word N width
00590                 ((I2S_CONFIG_BITS_IN_A_WORD-1) <<16) | // word 0 width
00591                 (0x17<<8);                            // right adjust, where the first bit starts
00592 
00593     I2S0->TMR = 0;
00594 
00595     // enable TX
00596     I2S0->TCSR = (0<<31) | // enable tx
00597                 (1<<28) | // enable bit clock
00598                 (0<<0);   // enable DMA request
00599 }
00600 
00601 void I2S::_i2s_set_rate(int smprate)
00602 {
00603     unsigned char div;
00604 //    SIM->SCGC6 |= SIM_SCGC6_I2S_MASK;
00605 
00606     // Select MCLK input source
00607     I2S0->MCR = (1<<30)| // MCLK = output
00608                (0<<24); // MCLK SRC = core clock = 48M
00609 
00610     if((smprate == 11025)||(smprate == 22050)||(smprate == 44100)) {
00611         _set_clock_112896();
00612         mclk_frequency = 11289600;
00613     }
00614 
00615     if((smprate == 8000) || (smprate == 12000) || (smprate == 16000) ||
00616             (smprate == 24000)|| (smprate == 32000) || (smprate == 48000) ) {
00617         _set_clock_122800();
00618         mclk_frequency = 12288000;
00619     }
00620 
00621     switch(smprate) {
00622         case 32000:
00623             div=3;
00624             break; // 12.288M/(32K*48) = 8, 8 = (DIV+1)*2, DIV = 3
00625     }
00626 
00627     I2S0->TCR2 = div;
00628 }
00629 
00630 
00631 
00632 
00633 
00634 
00635 
00636 
00637 
00638 
00639 void I2S::write_registers()
00640 {
00641     reg_write_err = 0;
00642     //Clock Multiplier Calculations
00643     float pre_mult = 0;
00644     int pre_num = 0;
00645     int pre_den = 0;
00646     int bitrate_div = 0;
00647 //    if (master == true) { // In the hope of not doing all this heavy lifting every configuration
00648 //        //printf("Doing some clock magic..\n\r");
00649 //        int bitrate = freq * 64;
00650 //        float target_div = I2S_PCLK_RATE / float(bitrate * 2);// Work out what divider is needed in the end, including the halving of rates the smoother does
00651 //        if (mclk_frequency == 0) {
00652 //            float rnd = fmod(target_div,1);// To make the X/Y fraction closest to 1, we set the last divider to the nearest integer to the rate divider
00653 //            bitrate_div = int(target_div - rnd);
00654 //            while (bitrate_div > I2S_MAX_BITRATE_DIV) { // But this might be out of range, so we right shift it into focus
00655 //                bitrate_div >>= 1;
00656 //            }
00657 //            if (bitrate_div == 0) { // Could be zero, which would disable the the clock...
00658 //                bitrate_div = 1;
00659 //            }
00660 //            pre_mult = float(bitrate_div) / target_div;    // Work out what we have left to correct
00661 //            pre_num = 0;
00662 //            pre_den = 0;
00663 //            fraction_estimator(pre_mult, &pre_num, &pre_den);// Get the function to work out the closest fraction, there might be some point in adding some possible multipliers of these values to add to the smoothing, the reference manual (UM10360 page 480) suggests this
00664 //
00665 //        } else {
00666 //            pre_mult = float(mclk_frequency * 2) / (I2S_PCLK_RATE);
00667 //            pre_num = 0;
00668 //            pre_den = 0;
00669 //            fraction_estimator(pre_mult, &pre_num, &pre_den);// Get the function to work out the closest fraction, there might be some point in adding some possible multipliers of these values to add to the smoothing, the reference manual (UM10360 page 480) suggests this
00670 //            bitrate_div = int(
00671 //                              I2S_PCLK_RATE * float(pre_num) / float(pre_den)
00672 //                              / float(bitrate));
00673 //        }
00674 //
00675 //        old_freq = freq;
00676 //        old_pre_num = pre_num;
00677 //        old_pre_den = pre_den;
00678 //        old_bitrate_div = bitrate_div;
00679 //    } else {
00680 //        pre_num = old_pre_num;
00681 //        pre_den = old_pre_den;
00682 //        bitrate_div = old_bitrate_div;
00683 //    }
00684 
00685     //Clock Multiplier, MCLK setup
00686     if (_rxtx == I2S_TRANSMIT) {
00687         int regvals = ((pre_num << 8) & 0xFF00) | (pre_den & 0xFF);
00688 //        LPC_I2S->I2STXRATE = regvals;                // Setting the X/Y fraction
00689 //        LPC_I2S->I2STXBITRATE = (bitrate_div - 1) & 0x3F;// Setting up the bitrate divider, the periferal adds one to this
00690 
00691 //        LPC_I2S->I2STXMODE = fourwire << 2;
00692 
00693         if (MasterClk_d == true) {
00694 //            LPC_I2S->I2STXMODE |= (1 << 3);
00695         }
00696     } else {
00697         int regvals = ((pre_num << 8) & 0xFF00) | (pre_den & 0xFF);
00698 //        LPC_I2S->I2SRXRATE = regvals;                // Setting the X/Y fraction
00699 //        LPC_I2S->I2SRXBITRATE = (bitrate_div - 1) & 0x3F;// Setting up the bitrate divider, the periferal adds one to this
00700 
00701 //        LPC_I2S->I2SRXMODE = fourwire << 2;
00702 
00703         if (MasterClk_d == true) {
00704 //            LPC_I2S->I2SRXMODE |= (1 << 3);
00705         }
00706     }
00707 
00708     switch (wordwidth) {
00709         case 8:
00710             wordwidth_code = 0;
00711             break;
00712         case 16:
00713             wordwidth_code = 1;
00714             break;
00715         case 32:
00716             wordwidth_code = 3;
00717             break;
00718         default:
00719             reg_write_err++;
00720             break;
00721     }
00722 
00723     int I2SDA_reg = (wordwidth_code & 0x3);
00724     I2SDA_reg |= ((!stereo << 2) & 0x4);
00725     I2SDA_reg |= ((stopped << 3) & 0x8);
00726     I2SDA_reg |= ((!master << 5) & 0x20);
00727     I2SDA_reg |= (0x1F << 6);
00728     I2SDA_reg |= ((muted << 15) & 0x8000);
00729 
00730     if (_rxtx == I2S_TRANSMIT) {
00731         ;
00732 //        LPC_I2S->I2SDAO = I2SDA_reg;
00733     } else {
00734         ;
00735 //        LPC_I2S->I2SDAI = I2SDA_reg;
00736     }
00737 
00738     if (_rxtx == I2S_TRANSMIT) {
00739         if (txisr) {
00740 //            LPC_I2S->I2SIRQ = (LPC_I2S->I2SIRQ & 0xFF0FFFFF)
00741 //                              | ((interrupt_fifo_level & 0xF) << 16);
00742 //            LPC_I2S->I2SIRQ |= 0x2;
00743         } else {
00744             ;
00745 //            LPC_I2S->I2SIRQ &= 0xFFFFFFFD;
00746         }
00747     } else {
00748         if (rxisr) {
00749 //            LPC_I2S->I2SIRQ = (LPC_I2S->I2SIRQ & 0xFFFFF0FF)
00750 //                              | ((interrupt_fifo_level & 0xF) << 8);
00751 //            LPC_I2S->I2SIRQ |= 0x1;
00752         }
00753 
00754         else {
00755             ;
00756 //            LPC_I2S->I2SIRQ &= 0xFFFFFFFE;
00757         }
00758     }
00759 }
00760 
00761 void I2S::_i2sisr(void)
00762 {
00763     I2STXISR.call();
00764     I2SRXISR.call();
00765 }
00766 
00767 // A function to find the nearest fraction to that put to it, with numerator and denomnator less than 256
00768 // This is used when trying to get the clocks correct
00769 
00770 //void I2S::fraction_estimator(float in, int * num, int * den)
00771 //{
00772 //    int test_num = 0;
00773 //    int test_den = 0;
00774 //    float least_error = 1;
00775 //    int least_err_den = 0;
00776 //    float genval;
00777 //    float generr;
00778 //
00779 //    for (test_den = 1; test_den < I2S_MAX_DENOMINATOR; test_den++) {
00780 //        test_num = int(float(test_den) * in);
00781 //        if (test_num < I2S_MAX_NUMERATOR && test_num > 0) {
00782 //            genval = float(test_num) / float(test_den);
00783 //            generr = mod(genval - in);
00784 //            if (generr < least_error) {
00785 //                least_error = generr;
00786 //                least_err_den = test_den;
00787 //            }
00788 //            if (generr == 0) {
00789 //                break;
00790 //            }
00791 //        }
00792 //    }
00793 //
00794 //    test_num = int(float(least_err_den) * in);
00795 //    *num = test_num;
00796 //    *den = least_err_den;
00797 //
00798 //}
00799 //
00800 //float I2S::mod(float in)
00801 //{
00802 //    if (in < 0)
00803 //        in *= -1;
00804 //
00805 //    return in;
00806 //}