/* Configure I2S for Audio Format input */ Status Chip_I2S_TxConfig(LPC_I2S_T *pI2S, I2S_AUDIO_FORMAT_T *format) { uint32_t temp; uint16_t xDiv, yDiv; uint32_t N; if (getClkDiv(pI2S, format, &xDiv, &yDiv, &N) == ERROR) { return ERROR; } temp = pI2S->DAO & (~(I2S_DAO_WORDWIDTH_MASK | I2S_DAO_MONO | I2S_DAO_SLAVE | I2S_DAO_WS_HALFPERIOD_MASK)); if (format->WordWidth <= 8) { temp |= I2S_WORDWIDTH_8; } else if (format->WordWidth <= 16) { temp |= I2S_WORDWIDTH_16; } else { temp |= I2S_WORDWIDTH_32; } temp |= (format->ChannelNumber) == 1 ? I2S_MONO : I2S_STEREO; temp |= I2S_MASTER_MODE; temp |= I2S_DAO_WS_HALFPERIOD(format->WordWidth - 1); pI2S->DAO = temp; pI2S->TXMODE = I2S_TXMODE_CLKSEL(0); pI2S->TXBITRATE = N - 1; pI2S->TXRATE = yDiv | (xDiv << 8); return SUCCESS; }
/* Configure I2S for Audio Format input */ Status Chip_I2S_Config(LPC_I2S_T *pI2S, uint8_t TRMode, Chip_I2S_Audio_Format_T *audio_format) { uint32_t pClk; uint32_t x, y; uint64_t divider; uint16_t dif; uint16_t x_divide = 0, y_divide = 0; uint32_t N; uint16_t err, ErrorOptimal = 0xFFFF; Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_I2S); #if defined(CHIP_LPC175X_6X) pClk = Chip_Clock_GetPeripheralClockRate(SYSCTL_PCLK_I2S); #else pClk = Chip_Clock_GetPeripheralClockRate(); #endif /* divider is a fixed point number with 16 fractional bits */ divider = (((uint64_t) (audio_format->SampleRate) * 2 * (audio_format->WordWidth) * 2) << 16) / pClk; /* find N that make x/y <= 1 -> divider <= 2^16 */ for (N = 64; N > 0; N--) { if ((divider * N) < (1 << 16)) { break; } } if (N == 0) { return ERROR; } divider *= N; for (y = 255; y > 0; y--) { x = y * divider; if (x & (0xFF000000)) { continue; } dif = x & 0xFFFF; if (dif > 0x8000) { err = 0x10000 - dif; } else { err = dif; } if (err == 0) { y_divide = y; break; } else if (err < ErrorOptimal) { ErrorOptimal = err; y_divide = y; } } x_divide = ((uint64_t) y_divide * (audio_format->SampleRate) * 2 * (audio_format->WordWidth) * N * 2) / pClk; if (x_divide >= 256) { x_divide = 0xFF; } if (x_divide == 0) { x_divide = 1; } if (audio_format->WordWidth <= 8) { IP_I2S_SetWordWidth(pI2S, TRMode, I2S_WORDWIDTH_8); } else if (audio_format->WordWidth <= 16) { IP_I2S_SetWordWidth(pI2S, TRMode, I2S_WORDWIDTH_16); } else { IP_I2S_SetWordWidth(pI2S, TRMode, I2S_WORDWIDTH_32); } IP_I2S_SetMono(pI2S, TRMode, (audio_format->ChannelNumber) == 1 ? I2S_MONO : I2S_STEREO); IP_I2S_SetMasterSlaveMode(pI2S, TRMode, I2S_MASTER_MODE); IP_I2S_SetWS_Halfperiod(pI2S, TRMode, audio_format->WordWidth - 1); IP_I2S_ModeConfig(pI2S, TRMode, I2S_TXMODE_CLKSEL(0), !I2S_TXMODE_4PIN_ENABLE, !I2S_TXMODE_MCENA); IP_I2S_SetBitRate(pI2S, TRMode, N - 1); IP_I2S_SetXYDivider(pI2S, TRMode, x_divide, y_divide); return SUCCESS; }