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.

Committer:
Pinski1
Date:
Mon Dec 06 00:05:39 2010 +0000
Revision:
0:0408d1e354e7
An initial release, not fully tested.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Pinski1 0:0408d1e354e7 1 #include "mbed.h"
Pinski1 0:0408d1e354e7 2 #include "LPC17xx.h"
Pinski1 0:0408d1e354e7 3 #include "core_cm3.h"
Pinski1 0:0408d1e354e7 4 #include "system_LPC17xx.h"
Pinski1 0:0408d1e354e7 5 #include "I2S.h"
Pinski1 0:0408d1e354e7 6
Pinski1 0:0408d1e354e7 7 I2S::I2S(PinName bitTx = p7, PinName wdTx = p6, PinName daTx = p5, PinName bitRx = p30, PinName wdRx = p29, PinName daRx = p8) {
Pinski1 0:0408d1e354e7 8 // assuming pins are correct
Pinski1 0:0408d1e354e7 9
Pinski1 0:0408d1e354e7 10 // assign pins - be nice to use mbed stuff for this
Pinski1 0:0408d1e354e7 11 LPC_PINCON->PINSEL0 |= ((0x01 << 14) | (0x01 << 16) | (0x01 << 18)); // set p5,p6,p7 as I2S
Pinski1 0:0408d1e354e7 12 LPC_PINCON->PINMODE0 |= ((0x02 << 14) | (0x02 << 16) | (0x02 << 18));
Pinski1 0:0408d1e354e7 13 if(bitRx == p30)
Pinski1 0:0408d1e354e7 14 {
Pinski1 0:0408d1e354e7 15 LPC_PINCON->PINSEL0 |= (0x01 << 8);
Pinski1 0:0408d1e354e7 16 LPC_PINCON->PINMODE0 |= (0x02 << 8);
Pinski1 0:0408d1e354e7 17 }
Pinski1 0:0408d1e354e7 18 else
Pinski1 0:0408d1e354e7 19 {
Pinski1 0:0408d1e354e7 20 LPC_PINCON->PINSEL1 |= (0x01 << 14);
Pinski1 0:0408d1e354e7 21 LPC_PINCON->PINMODE1 |= (0x02 << 14);
Pinski1 0:0408d1e354e7 22 }
Pinski1 0:0408d1e354e7 23 if(wdRx == p29)
Pinski1 0:0408d1e354e7 24 {
Pinski1 0:0408d1e354e7 25 LPC_PINCON->PINSEL0 |= (0x01 << 10);
Pinski1 0:0408d1e354e7 26 LPC_PINCON->PINMODE0 |= (0x02 << 10);
Pinski1 0:0408d1e354e7 27 }
Pinski1 0:0408d1e354e7 28 else
Pinski1 0:0408d1e354e7 29 {
Pinski1 0:0408d1e354e7 30 LPC_PINCON->PINSEL1 |= (0x01 << 16);
Pinski1 0:0408d1e354e7 31 LPC_PINCON->PINMODE1 |= (0x02 << 16);
Pinski1 0:0408d1e354e7 32 }
Pinski1 0:0408d1e354e7 33 if(daRx == p8)
Pinski1 0:0408d1e354e7 34 {
Pinski1 0:0408d1e354e7 35 LPC_PINCON->PINSEL0 |= (0x01 << 12);
Pinski1 0:0408d1e354e7 36 LPC_PINCON->PINMODE0 |= (0x02 << 12);
Pinski1 0:0408d1e354e7 37 }
Pinski1 0:0408d1e354e7 38 else
Pinski1 0:0408d1e354e7 39 {
Pinski1 0:0408d1e354e7 40 LPC_PINCON->PINSEL1 |= (0x01 << 18);
Pinski1 0:0408d1e354e7 41 LPC_PINCON->PINMODE1 |= (0x02 << 18);
Pinski1 0:0408d1e354e7 42 }
Pinski1 0:0408d1e354e7 43
Pinski1 0:0408d1e354e7 44 LPC_SC->PCONP |= (0x01 << 27); // turn on I2S periferal
Pinski1 0:0408d1e354e7 45 }
Pinski1 0:0408d1e354e7 46
Pinski1 0:0408d1e354e7 47 I2S::~I2S() {
Pinski1 0:0408d1e354e7 48 // release stuff
Pinski1 0:0408d1e354e7 49 LPC_SC->PCONP &= (0 << 27); // turn off I2S periferal
Pinski1 0:0408d1e354e7 50 }
Pinski1 0:0408d1e354e7 51
Pinski1 0:0408d1e354e7 52
Pinski1 0:0408d1e354e7 53 void I2S::setClocks(uint8_t x, uint8_t y, uint8_t divider) {
Pinski1 0:0408d1e354e7 54
Pinski1 0:0408d1e354e7 55 if(divider == 1) LPC_SC->PCLKSEL1 &= (0x01 << 22);
Pinski1 0:0408d1e354e7 56 else if(divider == 2) LPC_SC->PCLKSEL1 &= (0x02 << 22);
Pinski1 0:0408d1e354e7 57 else if(divider == 4) LPC_SC->PCLKSEL1 &= (0x00 << 22);
Pinski1 0:0408d1e354e7 58 else if(divider == 8) LPC_SC->PCLKSEL1 &= (0x03 << 22);
Pinski1 0:0408d1e354e7 59
Pinski1 0:0408d1e354e7 60 LPC_I2S->I2STXRATE = (x << 8) & y;
Pinski1 0:0408d1e354e7 61 LPC_I2S->I2SRXRATE = (x << 8) & y;
Pinski1 0:0408d1e354e7 62
Pinski1 0:0408d1e354e7 63 peripheralClock = SystemCoreClock/divider;
Pinski1 0:0408d1e354e7 64 masterClock = (x * peripheralClock)/(2 * y);
Pinski1 0:0408d1e354e7 65 }
Pinski1 0:0408d1e354e7 66
Pinski1 0:0408d1e354e7 67
Pinski1 0:0408d1e354e7 68 void I2S::setTx(uint16_t resolution, uint16_t rate, bool stereo) {
Pinski1 0:0408d1e354e7 69
Pinski1 0:0408d1e354e7 70 if(resolution == 8) LPC_I2S->I2SDAO &= (0x00 << 4); // set to 00
Pinski1 0:0408d1e354e7 71 else if(resolution == 16) LPC_I2S->I2SDAO |= (0x01 << 4); // set to 01
Pinski1 0:0408d1e354e7 72 else if(resolution == 32) LPC_I2S->I2SDAO |= (0x03 << 4);// set to 11
Pinski1 0:0408d1e354e7 73
Pinski1 0:0408d1e354e7 74 // rate limited to 16000, 22050, 32000, 44100, 48000 or 96000
Pinski1 0:0408d1e354e7 75
Pinski1 0:0408d1e354e7 76 uint32_t bitClock = resolution * rate;
Pinski1 0:0408d1e354e7 77 if(stereo == true) bitClock *= 2;
Pinski1 0:0408d1e354e7 78 uint8_t bitDivider = masterClock / bitClock;
Pinski1 0:0408d1e354e7 79 LPC_I2S->I2STXBITRATE = bitDivider - 1;
Pinski1 0:0408d1e354e7 80
Pinski1 0:0408d1e354e7 81 if(stereo == true) LPC_I2S->I2SDAO &= (0 << 2); // set to stereo
Pinski1 0:0408d1e354e7 82 else LPC_I2S->I2SDAO |= (1 << 2);
Pinski1 0:0408d1e354e7 83 }
Pinski1 0:0408d1e354e7 84
Pinski1 0:0408d1e354e7 85 void I2S::setRx(uint16_t resolution, uint16_t rate, bool stereo) {
Pinski1 0:0408d1e354e7 86
Pinski1 0:0408d1e354e7 87 if(resolution == 8) LPC_I2S->I2SDAI &= (0x00 << 4); // set to 00
Pinski1 0:0408d1e354e7 88 else if(resolution == 16) LPC_I2S->I2SDAI |= (0x01 << 4); // set to 01
Pinski1 0:0408d1e354e7 89 else if(resolution == 32) LPC_I2S->I2SDAI |= (0x03 << 4);// set to 11
Pinski1 0:0408d1e354e7 90
Pinski1 0:0408d1e354e7 91 // rate limited to 16000, 22050, 32000, 44100, 48000 or 96000
Pinski1 0:0408d1e354e7 92
Pinski1 0:0408d1e354e7 93 uint32_t bitClock = resolution * rate;
Pinski1 0:0408d1e354e7 94 if(stereo == true) bitClock *= 2;
Pinski1 0:0408d1e354e7 95 uint8_t bitDivider = masterClock / bitClock;
Pinski1 0:0408d1e354e7 96 LPC_I2S->I2SRXBITRATE = bitDivider - 1;
Pinski1 0:0408d1e354e7 97
Pinski1 0:0408d1e354e7 98 if(stereo == true) LPC_I2S->I2SDAI &= (0 << 2); // set to stereo
Pinski1 0:0408d1e354e7 99 else LPC_I2S->I2SDAI |= (1 << 2);
Pinski1 0:0408d1e354e7 100 }
Pinski1 0:0408d1e354e7 101
Pinski1 0:0408d1e354e7 102 void I2S::muteTx(void) {
Pinski1 0:0408d1e354e7 103 // sets the channel into "stop" mode, TX sends zeros
Pinski1 0:0408d1e354e7 104 if(LPC_I2S->I2SDAO & 0x08) LPC_I2S->I2SDAO |= (1 << 4);
Pinski1 0:0408d1e354e7 105 else LPC_I2S->I2SDAO &= (0 << 4);
Pinski1 0:0408d1e354e7 106 return;
Pinski1 0:0408d1e354e7 107 }
Pinski1 0:0408d1e354e7 108
Pinski1 0:0408d1e354e7 109 void I2S::muteRx(void) {
Pinski1 0:0408d1e354e7 110 // sets the channel into "stop" mode, TX sends zeros
Pinski1 0:0408d1e354e7 111 if(LPC_I2S->I2SDAI & 0x00008) LPC_I2S->I2SDAI |= (1 << 4);
Pinski1 0:0408d1e354e7 112 else LPC_I2S->I2SDAI &= (0 << 4);
Pinski1 0:0408d1e354e7 113 return;
Pinski1 0:0408d1e354e7 114 }
Pinski1 0:0408d1e354e7 115
Pinski1 0:0408d1e354e7 116 void I2S::resetTx(void) {
Pinski1 0:0408d1e354e7 117 // resets the channel
Pinski1 0:0408d1e354e7 118 LPC_I2S->I2SDAO |= (1 << 5);
Pinski1 0:0408d1e354e7 119 return;
Pinski1 0:0408d1e354e7 120 }
Pinski1 0:0408d1e354e7 121
Pinski1 0:0408d1e354e7 122 void I2S::resetRx(void) {
Pinski1 0:0408d1e354e7 123 // resets the channel
Pinski1 0:0408d1e354e7 124 LPC_I2S->I2SDAI |= (1 << 5);
Pinski1 0:0408d1e354e7 125 return;
Pinski1 0:0408d1e354e7 126 }
Pinski1 0:0408d1e354e7 127
Pinski1 0:0408d1e354e7 128 void setTxMode(uint8_t mode) {
Pinski1 0:0408d1e354e7 129 uint8_t modes[2][7] = {{0,0,0,0,1,1,1},{0,2,4,8,0,2,4}};
Pinski1 0:0408d1e354e7 130 /*
Pinski1 0:0408d1e354e7 131 0;0,0,0,0 // Typical transmitter master mode.
Pinski1 0:0408d1e354e7 132 0;0,0,1,0 // Transmitter master mode sharing the receiver reference clock.
Pinski1 0:0408d1e354e7 133 0;0,1,0,0 // 4-wire transmitter master mode sharing the receiver bit clock and WS.
Pinski1 0:0408d1e354e7 134 0;1,0,0,0 // Transmitter master mode with TX_MCLK output.
Pinski1 0:0408d1e354e7 135 1;0,0,0,0 // Typical transmitter slave mode.
Pinski1 0:0408d1e354e7 136 1;0,0,1,0 // Transmitter slave mode sharing the receiver reference clock.
Pinski1 0:0408d1e354e7 137 1;0,1,0,0 // 4-wire transmitter slave mode sharing the receiver bit clock and WS.
Pinski1 0:0408d1e354e7 138 */
Pinski1 0:0408d1e354e7 139 LPC_I2S->I2SDAO &= (modes[0][mode] << 5);
Pinski1 0:0408d1e354e7 140 LPC_I2S->I2STXMODE = modes[1][mode];
Pinski1 0:0408d1e354e7 141 }
Pinski1 0:0408d1e354e7 142
Pinski1 0:0408d1e354e7 143 void setRxMode(uint8_t mode) {
Pinski1 0:0408d1e354e7 144 uint8_t modes[2][7] = {{0,0,0,0,1,1,1},{0,2,4,8,0,2,4}};
Pinski1 0:0408d1e354e7 145 /*
Pinski1 0:0408d1e354e7 146 0;0,0,0,0 // Typical receiver master mode.
Pinski1 0:0408d1e354e7 147 0;0,0,1,0 // Receiver master mode sharing the transmitter reference clock.
Pinski1 0:0408d1e354e7 148 0;0,1,0,0 // 4-wire receiver master mode sharing the transmitter bit clock and WS.
Pinski1 0:0408d1e354e7 149 0;1,0,0,0 // Receiver master mode with RX_MCLK output.
Pinski1 0:0408d1e354e7 150 1;0,0,0,0 // Typical receiver slave mode.
Pinski1 0:0408d1e354e7 151 1;0,0,1,0 // Receiver slave mode sharing the transmitter reference clock.
Pinski1 0:0408d1e354e7 152 1;0,1,0,0 // 4-wire receiver slave mode sharing the transmitter bit clock and WS.
Pinski1 0:0408d1e354e7 153 */
Pinski1 0:0408d1e354e7 154 LPC_I2S->I2SDAI &= (modes[0][mode] << 5);
Pinski1 0:0408d1e354e7 155 LPC_I2S->I2SRXMODE = modes[1][mode];
Pinski1 0:0408d1e354e7 156 }
Pinski1 0:0408d1e354e7 157
Pinski1 0:0408d1e354e7 158 void setIRQ(bool rxInterrupt, bool txInterrupt, uint8_t rxDepth, uint8_t txDepth) {
Pinski1 0:0408d1e354e7 159 if(rxInterrupt == true)
Pinski1 0:0408d1e354e7 160 {
Pinski1 0:0408d1e354e7 161 LPC_I2S->I2SIRQ |= (0x01 << 0);
Pinski1 0:0408d1e354e7 162 LPC_I2S->I2SIRQ |= (rxDepth << 8);
Pinski1 0:0408d1e354e7 163 }
Pinski1 0:0408d1e354e7 164 else
Pinski1 0:0408d1e354e7 165 {
Pinski1 0:0408d1e354e7 166 LPC_I2S->I2SIRQ &= ~(0x01 << 0);
Pinski1 0:0408d1e354e7 167 LPC_I2S->I2SIRQ &= ~(0x0F << 8);
Pinski1 0:0408d1e354e7 168 }
Pinski1 0:0408d1e354e7 169
Pinski1 0:0408d1e354e7 170 if(rxInterrupt == true)
Pinski1 0:0408d1e354e7 171 {
Pinski1 0:0408d1e354e7 172 LPC_I2S->I2SIRQ |= (0x01 << 1);
Pinski1 0:0408d1e354e7 173 LPC_I2S->I2SIRQ |= (txDepth << 16);
Pinski1 0:0408d1e354e7 174 }
Pinski1 0:0408d1e354e7 175 else
Pinski1 0:0408d1e354e7 176 {
Pinski1 0:0408d1e354e7 177 LPC_I2S->I2SIRQ &= ~(0x01 << 1);
Pinski1 0:0408d1e354e7 178 LPC_I2S->I2SIRQ &= ~(0x0F << 16);
Pinski1 0:0408d1e354e7 179 }
Pinski1 0:0408d1e354e7 180 }
Pinski1 0:0408d1e354e7 181
Pinski1 0:0408d1e354e7 182 void setDMA1(bool rxDMA, bool txDMA, uint8_t rxDepth, uint8_t txDepth) {
Pinski1 0:0408d1e354e7 183 if(rxDMA == true)
Pinski1 0:0408d1e354e7 184 {
Pinski1 0:0408d1e354e7 185 LPC_I2S->I2SDMA1 |= (0x01 << 0);
Pinski1 0:0408d1e354e7 186 LPC_I2S->I2SDMA1 |= (rxDepth << 8);
Pinski1 0:0408d1e354e7 187 }
Pinski1 0:0408d1e354e7 188 else
Pinski1 0:0408d1e354e7 189 {
Pinski1 0:0408d1e354e7 190 LPC_I2S->I2SDMA1 &= ~(0x01 << 0);
Pinski1 0:0408d1e354e7 191 LPC_I2S->I2SDMA1 &= ~(0x0F << 8);
Pinski1 0:0408d1e354e7 192 }
Pinski1 0:0408d1e354e7 193
Pinski1 0:0408d1e354e7 194 if(txDMA == true)
Pinski1 0:0408d1e354e7 195 {
Pinski1 0:0408d1e354e7 196 LPC_I2S->I2SDMA1 |= (0x01 << 1);
Pinski1 0:0408d1e354e7 197 LPC_I2S->I2SDMA1 |= (txDepth << 16);
Pinski1 0:0408d1e354e7 198 }
Pinski1 0:0408d1e354e7 199 else
Pinski1 0:0408d1e354e7 200 {
Pinski1 0:0408d1e354e7 201 LPC_I2S->I2SDMA1 &= ~(0x01 << 1);
Pinski1 0:0408d1e354e7 202 LPC_I2S->I2SDMA1 &= ~(0x0F << 16);
Pinski1 0:0408d1e354e7 203 }
Pinski1 0:0408d1e354e7 204 }
Pinski1 0:0408d1e354e7 205
Pinski1 0:0408d1e354e7 206 void setDMA2(bool rxDMA, bool txDMA, uint8_t rxDepth, uint8_t txDepth) {
Pinski1 0:0408d1e354e7 207 if(rxDMA == true)
Pinski1 0:0408d1e354e7 208 {
Pinski1 0:0408d1e354e7 209 LPC_I2S->I2SDMA2 |= (0x01 << 0);
Pinski1 0:0408d1e354e7 210 LPC_I2S->I2SDMA2 |= (rxDepth << 8);
Pinski1 0:0408d1e354e7 211 }
Pinski1 0:0408d1e354e7 212 else
Pinski1 0:0408d1e354e7 213 {
Pinski1 0:0408d1e354e7 214 LPC_I2S->I2SDMA2 &= ~(0x01 << 0);
Pinski1 0:0408d1e354e7 215 LPC_I2S->I2SDMA2 &= ~(0x0F << 8);
Pinski1 0:0408d1e354e7 216 }
Pinski1 0:0408d1e354e7 217
Pinski1 0:0408d1e354e7 218 if(txDMA == true)
Pinski1 0:0408d1e354e7 219 {
Pinski1 0:0408d1e354e7 220 LPC_I2S->I2SDMA2 |= (0x01 << 1);
Pinski1 0:0408d1e354e7 221 LPC_I2S->I2SDMA2 |= (txDepth << 16);
Pinski1 0:0408d1e354e7 222 }
Pinski1 0:0408d1e354e7 223 else
Pinski1 0:0408d1e354e7 224 {
Pinski1 0:0408d1e354e7 225 LPC_I2S->I2SDMA2 &= ~(0x01 << 1);
Pinski1 0:0408d1e354e7 226 LPC_I2S->I2SDMA2 &= ~(0x0F << 16);
Pinski1 0:0408d1e354e7 227 }
Pinski1 0:0408d1e354e7 228 }