This is an I2S library to allow people to take advantage of the I2S peripheral on the LPC1768. Ideally it will be included in future releases of the mbed.h file.

I2S.cpp

Committer:
Pinski1
Date:
2010-12-06
Revision:
0:0408d1e354e7

File content as of revision 0:0408d1e354e7:

#include "mbed.h"
#include "LPC17xx.h"
#include "core_cm3.h"
#include "system_LPC17xx.h"
#include "I2S.h"

I2S::I2S(PinName bitTx = p7, PinName wdTx = p6, PinName daTx = p5, PinName bitRx = p30, PinName wdRx = p29, PinName daRx = p8) {
    // assuming pins are correct

    // assign pins - be nice to use mbed stuff for this
	LPC_PINCON->PINSEL0 |= ((0x01 << 14) | (0x01 << 16) | (0x01 << 18)); // set p5,p6,p7 as I2S
	LPC_PINCON->PINMODE0 |= ((0x02 << 14) | (0x02 << 16) | (0x02 << 18));
	if(bitRx == p30)
	{
		LPC_PINCON->PINSEL0 |= (0x01 << 8);
		LPC_PINCON->PINMODE0 |= (0x02 << 8);
	}
	else
	{
		LPC_PINCON->PINSEL1 |= (0x01 << 14);
		LPC_PINCON->PINMODE1 |= (0x02 << 14);
	}
	if(wdRx == p29)
	{
		LPC_PINCON->PINSEL0 |= (0x01 << 10);
		LPC_PINCON->PINMODE0 |= (0x02 << 10);
	}
	else
	{
		LPC_PINCON->PINSEL1 |= (0x01 << 16);
		LPC_PINCON->PINMODE1 |= (0x02 << 16);
	}
	if(daRx == p8)
	{
		LPC_PINCON->PINSEL0 |= (0x01 << 12);
		LPC_PINCON->PINMODE0 |= (0x02 << 12);
	}
	else
	{
		LPC_PINCON->PINSEL1 |= (0x01 << 18);
		LPC_PINCON->PINMODE1 |= (0x02 << 18);
	}

    LPC_SC->PCONP |= (0x01 << 27); // turn on I2S periferal
}

I2S::~I2S() {
    // release stuff
    LPC_SC->PCONP &= (0 << 27); // turn off I2S periferal
}


void I2S::setClocks(uint8_t x, uint8_t y, uint8_t divider) {

	if(divider == 1) LPC_SC->PCLKSEL1 &= (0x01 << 22);
	else if(divider == 2) LPC_SC->PCLKSEL1 &= (0x02 << 22);
	else if(divider == 4) LPC_SC->PCLKSEL1 &= (0x00 << 22);
	else if(divider == 8) LPC_SC->PCLKSEL1 &= (0x03 << 22);

	LPC_I2S->I2STXRATE = (x << 8) & y;
	LPC_I2S->I2SRXRATE = (x << 8) & y;
	
	peripheralClock = SystemCoreClock/divider;
	masterClock = (x * peripheralClock)/(2 * y);
}


void I2S::setTx(uint16_t resolution, uint16_t rate, bool stereo) {

	if(resolution == 8) LPC_I2S->I2SDAO &= (0x00 << 4); // set to 00
	else if(resolution == 16) LPC_I2S->I2SDAO |= (0x01 << 4); // set to 01
	else if(resolution == 32) LPC_I2S->I2SDAO |= (0x03 << 4);// set to 11
	
    // rate limited to 16000, 22050, 32000, 44100, 48000 or 96000
	
	uint32_t bitClock = resolution * rate;
	if(stereo == true) bitClock *= 2;
	uint8_t bitDivider = masterClock / bitClock;	
	LPC_I2S->I2STXBITRATE = bitDivider - 1;
	
    if(stereo == true) LPC_I2S->I2SDAO &= (0 << 2); // set to stereo
	else LPC_I2S->I2SDAO |= (1 << 2);
}

void I2S::setRx(uint16_t resolution, uint16_t rate, bool stereo) {
    
	if(resolution == 8) LPC_I2S->I2SDAI &= (0x00 << 4); // set to 00
	else if(resolution == 16) LPC_I2S->I2SDAI |= (0x01 << 4); // set to 01
	else if(resolution == 32) LPC_I2S->I2SDAI |= (0x03 << 4);// set to 11
	
    // rate limited to 16000, 22050, 32000, 44100, 48000 or 96000
	
    uint32_t bitClock = resolution * rate;
	if(stereo == true) bitClock *= 2;
	uint8_t bitDivider = masterClock / bitClock;	
	LPC_I2S->I2SRXBITRATE = bitDivider - 1;
	
	if(stereo == true) LPC_I2S->I2SDAI &= (0 << 2); // set to stereo
	else LPC_I2S->I2SDAI |= (1 << 2);
}

void I2S::muteTx(void) {
    // sets the channel into "stop" mode, TX sends zeros
    if(LPC_I2S->I2SDAO & 0x08) LPC_I2S->I2SDAO |= (1 << 4);
	else  LPC_I2S->I2SDAO &= (0 << 4);
    return;
}

void I2S::muteRx(void) {
    // sets the channel into "stop" mode, TX sends zeros
    if(LPC_I2S->I2SDAI & 0x00008) LPC_I2S->I2SDAI |= (1 << 4);
    else LPC_I2S->I2SDAI &= (0 << 4);
    return;
}

void I2S::resetTx(void) {
    // resets the channel
    LPC_I2S->I2SDAO |= (1 << 5);
    return;
}

void I2S::resetRx(void) {
    // resets the channel
    LPC_I2S->I2SDAI |= (1 << 5);
    return;
}

void setTxMode(uint8_t mode) {
	uint8_t modes[2][7] = {{0,0,0,0,1,1,1},{0,2,4,8,0,2,4}};
	/*
	0;0,0,0,0 // Typical transmitter master mode.
	0;0,0,1,0 // Transmitter master mode sharing the receiver reference clock.
	0;0,1,0,0 // 4-wire transmitter master mode sharing the receiver bit clock and WS.
	0;1,0,0,0 // Transmitter master mode with TX_MCLK output.
	1;0,0,0,0 // Typical transmitter slave mode.
	1;0,0,1,0 // Transmitter slave mode sharing the receiver reference clock.
	1;0,1,0,0 // 4-wire transmitter slave mode sharing the receiver bit clock and WS.
	*/
	LPC_I2S->I2SDAO &= (modes[0][mode] << 5);
	LPC_I2S->I2STXMODE = modes[1][mode];
}

void setRxMode(uint8_t mode) {
	uint8_t modes[2][7] = {{0,0,0,0,1,1,1},{0,2,4,8,0,2,4}};
	/*
	0;0,0,0,0 // Typical receiver master mode.
	0;0,0,1,0 // Receiver master mode sharing the transmitter reference clock.
	0;0,1,0,0 // 4-wire receiver master mode sharing the transmitter bit clock and WS.
	0;1,0,0,0 // Receiver master mode with RX_MCLK output.
	1;0,0,0,0 // Typical receiver slave mode.
	1;0,0,1,0 // Receiver slave mode sharing the transmitter reference clock.
	1;0,1,0,0 // 4-wire receiver slave mode sharing the transmitter bit clock and WS.
	*/
	LPC_I2S->I2SDAI &= (modes[0][mode] << 5);
	LPC_I2S->I2SRXMODE = modes[1][mode];
}

void setIRQ(bool rxInterrupt, bool txInterrupt, uint8_t rxDepth, uint8_t txDepth) {
	if(rxInterrupt == true)
	{
		LPC_I2S->I2SIRQ |= (0x01 << 0);
		LPC_I2S->I2SIRQ |= (rxDepth << 8);
	}
	else
	{
		LPC_I2S->I2SIRQ &= ~(0x01 << 0);
		LPC_I2S->I2SIRQ &= ~(0x0F << 8);
	}
	
	if(rxInterrupt == true)
	{
		LPC_I2S->I2SIRQ |= (0x01 << 1);
		LPC_I2S->I2SIRQ |= (txDepth << 16);
	}
	else
	{
		LPC_I2S->I2SIRQ &= ~(0x01 << 1);
		LPC_I2S->I2SIRQ &= ~(0x0F << 16);
	}
}

void setDMA1(bool rxDMA, bool txDMA, uint8_t rxDepth, uint8_t txDepth) {
	if(rxDMA == true)
	{
		LPC_I2S->I2SDMA1 |= (0x01 << 0);
		LPC_I2S->I2SDMA1 |= (rxDepth << 8);
	}
	else
	{
		LPC_I2S->I2SDMA1 &= ~(0x01 << 0);
		LPC_I2S->I2SDMA1 &= ~(0x0F << 8);
	}
	
	if(txDMA == true)
	{
		LPC_I2S->I2SDMA1 |= (0x01 << 1);
		LPC_I2S->I2SDMA1 |= (txDepth << 16);
	}
	else
	{
		LPC_I2S->I2SDMA1 &= ~(0x01 << 1);
		LPC_I2S->I2SDMA1 &= ~(0x0F << 16);
	}
}

void setDMA2(bool rxDMA, bool txDMA, uint8_t rxDepth, uint8_t txDepth) {
	if(rxDMA == true)
	{
		LPC_I2S->I2SDMA2 |= (0x01 << 0);
		LPC_I2S->I2SDMA2 |= (rxDepth << 8);
	}
	else
	{
		LPC_I2S->I2SDMA2 &= ~(0x01 << 0);
		LPC_I2S->I2SDMA2 &= ~(0x0F << 8);
	}
	
	if(txDMA == true)
	{
		LPC_I2S->I2SDMA2 |= (0x01 << 1);
		LPC_I2S->I2SDMA2 |= (txDepth << 16);
	}
	else
	{
		LPC_I2S->I2SDMA2 &= ~(0x01 << 1);
		LPC_I2S->I2SDMA2 &= ~(0x0F << 16);
	}
}