A library which allows the playing of Wav files using the TLV320

Dependents:   RSALB_hbridge_helloworld RSALB_lobster WavPlayer_test AudioCODEC_HelloWorld

Committer:
p07gbar
Date:
Fri Sep 21 14:24:00 2012 +0000
Revision:
3:a7380cfc1987
Parent:
1:3eb96771bbee
Minor fix

Who changed what in which revision?

UserRevisionLine numberNew contents of line
p07gbar 1:3eb96771bbee 1 #include "I2S.h"
p07gbar 1:3eb96771bbee 2
p07gbar 1:3eb96771bbee 3 #define I2S_DF_WORDWIDTH 16
p07gbar 1:3eb96771bbee 4 #define I2S_DF_SAMPLERATE 32000
p07gbar 1:3eb96771bbee 5 #define I2S_DF_MASTERSLAVE I2S_SLAVE
p07gbar 1:3eb96771bbee 6 #define I2S_DF_STEREOMONO I2S_STEREO
p07gbar 1:3eb96771bbee 7 #define I2S_DF_MUTED I2S_UNMUTED
p07gbar 1:3eb96771bbee 8 #define I2S_DF_INTERRUPT_FIFO_LEVEL 4
p07gbar 1:3eb96771bbee 9
p07gbar 1:3eb96771bbee 10 #define I2S_MAX_DENOMINATOR 256
p07gbar 1:3eb96771bbee 11 #define I2S_MAX_NUMERATOR 256
p07gbar 1:3eb96771bbee 12 #define I2S_MAX_BITRATE_DIV 64
p07gbar 1:3eb96771bbee 13
p07gbar 1:3eb96771bbee 14 #define I2S_PCLK_RATE 24000000
p07gbar 1:3eb96771bbee 15
p07gbar 1:3eb96771bbee 16 FunctionPointer I2S::I2STXISR;
p07gbar 1:3eb96771bbee 17 FunctionPointer I2S::I2SRXISR;
p07gbar 1:3eb96771bbee 18
p07gbar 1:3eb96771bbee 19 bool I2S::txisr;
p07gbar 1:3eb96771bbee 20 bool I2S::rxisr;
p07gbar 1:3eb96771bbee 21
p07gbar 1:3eb96771bbee 22 I2S::I2S(bool rxtx, PinName sd, PinName ws, PinName clk)
p07gbar 1:3eb96771bbee 23 {
p07gbar 1:3eb96771bbee 24 NVIC_DisableIRQ (I2S_IRQn);
p07gbar 1:3eb96771bbee 25
p07gbar 1:3eb96771bbee 26 _sd = sd;
p07gbar 1:3eb96771bbee 27 _ws = ws;
p07gbar 1:3eb96771bbee 28 _clk = clk;
p07gbar 1:3eb96771bbee 29 _rxtx = rxtx;
p07gbar 1:3eb96771bbee 30
p07gbar 1:3eb96771bbee 31 ws_d = true;
p07gbar 1:3eb96771bbee 32 clk_d = true;
p07gbar 1:3eb96771bbee 33 mclk_d = false;
p07gbar 1:3eb96771bbee 34
p07gbar 1:3eb96771bbee 35 fourwire = false;
p07gbar 1:3eb96771bbee 36
p07gbar 1:3eb96771bbee 37 reg_write_err = 0;
p07gbar 1:3eb96771bbee 38
p07gbar 1:3eb96771bbee 39 pin_setup();
p07gbar 1:3eb96771bbee 40
p07gbar 1:3eb96771bbee 41 if (pin_setup_err != 0) {
p07gbar 1:3eb96771bbee 42 perror("I2S Pins incorrectly defined.");
p07gbar 1:3eb96771bbee 43 }
p07gbar 1:3eb96771bbee 44
p07gbar 1:3eb96771bbee 45 defaulter();
p07gbar 1:3eb96771bbee 46 }
p07gbar 1:3eb96771bbee 47
p07gbar 1:3eb96771bbee 48 I2S::I2S(bool rxtx, PinName sd)
p07gbar 1:3eb96771bbee 49 {
p07gbar 1:3eb96771bbee 50 NVIC_DisableIRQ (I2S_IRQn);
p07gbar 1:3eb96771bbee 51
p07gbar 1:3eb96771bbee 52 _sd = sd;
p07gbar 1:3eb96771bbee 53 _rxtx = rxtx;
p07gbar 1:3eb96771bbee 54
p07gbar 1:3eb96771bbee 55 ws_d = false;
p07gbar 1:3eb96771bbee 56 clk_d = false;
p07gbar 1:3eb96771bbee 57 mclk_d = false;
p07gbar 1:3eb96771bbee 58
p07gbar 1:3eb96771bbee 59 fourwire = false;
p07gbar 1:3eb96771bbee 60
p07gbar 1:3eb96771bbee 61 reg_write_err = 0;
p07gbar 1:3eb96771bbee 62
p07gbar 1:3eb96771bbee 63 pin_setup();
p07gbar 1:3eb96771bbee 64
p07gbar 1:3eb96771bbee 65 if (pin_setup_err != 0) {
p07gbar 1:3eb96771bbee 66 perror("I2S Pins incorrectly defined.");
p07gbar 1:3eb96771bbee 67 }
p07gbar 1:3eb96771bbee 68
p07gbar 1:3eb96771bbee 69 defaulter();
p07gbar 1:3eb96771bbee 70 }
p07gbar 1:3eb96771bbee 71
p07gbar 1:3eb96771bbee 72 I2S::I2S(bool rxtx, PinName sd, bool fourwiremode)
p07gbar 1:3eb96771bbee 73 {
p07gbar 1:3eb96771bbee 74 NVIC_DisableIRQ (I2S_IRQn);
p07gbar 1:3eb96771bbee 75
p07gbar 1:3eb96771bbee 76 _sd = sd;
p07gbar 1:3eb96771bbee 77 _rxtx = rxtx;
p07gbar 1:3eb96771bbee 78
p07gbar 1:3eb96771bbee 79 ws_d = false;
p07gbar 1:3eb96771bbee 80 clk_d = false;
p07gbar 1:3eb96771bbee 81 mclk_d = false;
p07gbar 1:3eb96771bbee 82
p07gbar 1:3eb96771bbee 83 reg_write_err = 0;
p07gbar 1:3eb96771bbee 84
p07gbar 1:3eb96771bbee 85 fourwire = fourwiremode;
p07gbar 1:3eb96771bbee 86
p07gbar 1:3eb96771bbee 87 pin_setup();
p07gbar 1:3eb96771bbee 88
p07gbar 1:3eb96771bbee 89 if (pin_setup_err != 0) {
p07gbar 1:3eb96771bbee 90 perror("I2S Pins incorrectly defined.");
p07gbar 1:3eb96771bbee 91 }
p07gbar 1:3eb96771bbee 92
p07gbar 1:3eb96771bbee 93 defaulter();
p07gbar 1:3eb96771bbee 94 }
p07gbar 1:3eb96771bbee 95
p07gbar 1:3eb96771bbee 96 I2S::I2S(bool rxtx, PinName sd, PinName ws, bool fourwiremode)
p07gbar 1:3eb96771bbee 97 {
p07gbar 1:3eb96771bbee 98 NVIC_DisableIRQ (I2S_IRQn);
p07gbar 1:3eb96771bbee 99
p07gbar 1:3eb96771bbee 100 _sd = sd;
p07gbar 1:3eb96771bbee 101 _ws = ws;
p07gbar 1:3eb96771bbee 102 _rxtx = rxtx;
p07gbar 1:3eb96771bbee 103
p07gbar 1:3eb96771bbee 104 ws_d = true;
p07gbar 1:3eb96771bbee 105 clk_d = false;
p07gbar 1:3eb96771bbee 106 mclk_d = false;
p07gbar 1:3eb96771bbee 107
p07gbar 1:3eb96771bbee 108 reg_write_err = 0;
p07gbar 1:3eb96771bbee 109
p07gbar 1:3eb96771bbee 110 fourwire = fourwiremode;
p07gbar 1:3eb96771bbee 111
p07gbar 1:3eb96771bbee 112 pin_setup();
p07gbar 1:3eb96771bbee 113
p07gbar 1:3eb96771bbee 114 if (pin_setup_err != 0) {
p07gbar 1:3eb96771bbee 115 perror("I2S Pins incorrectly defined.");
p07gbar 1:3eb96771bbee 116 }
p07gbar 1:3eb96771bbee 117
p07gbar 1:3eb96771bbee 118 defaulter();
p07gbar 1:3eb96771bbee 119 }
p07gbar 1:3eb96771bbee 120
p07gbar 1:3eb96771bbee 121 I2S::I2S(bool rxtx, PinName sd, PinName ws)
p07gbar 1:3eb96771bbee 122 {
p07gbar 1:3eb96771bbee 123 NVIC_DisableIRQ (I2S_IRQn);
p07gbar 1:3eb96771bbee 124
p07gbar 1:3eb96771bbee 125 _sd = sd;
p07gbar 1:3eb96771bbee 126 _ws = ws;
p07gbar 1:3eb96771bbee 127 _rxtx = rxtx;
p07gbar 1:3eb96771bbee 128
p07gbar 1:3eb96771bbee 129 ws_d = true;
p07gbar 1:3eb96771bbee 130 clk_d = false;
p07gbar 1:3eb96771bbee 131 mclk_d = false;
p07gbar 1:3eb96771bbee 132
p07gbar 1:3eb96771bbee 133 reg_write_err = 0;
p07gbar 1:3eb96771bbee 134
p07gbar 1:3eb96771bbee 135 fourwire = false;
p07gbar 1:3eb96771bbee 136
p07gbar 1:3eb96771bbee 137 pin_setup();
p07gbar 1:3eb96771bbee 138
p07gbar 1:3eb96771bbee 139 if (pin_setup_err != 0) {
p07gbar 1:3eb96771bbee 140 perror("I2S Pins incorrectly defined.");
p07gbar 1:3eb96771bbee 141 }
p07gbar 1:3eb96771bbee 142
p07gbar 1:3eb96771bbee 143 defaulter();
p07gbar 1:3eb96771bbee 144 }
p07gbar 1:3eb96771bbee 145
p07gbar 1:3eb96771bbee 146 I2S::~I2S()
p07gbar 1:3eb96771bbee 147 {
p07gbar 1:3eb96771bbee 148 NVIC_DisableIRQ (I2S_IRQn);
p07gbar 1:3eb96771bbee 149 deallocating = true;
p07gbar 1:3eb96771bbee 150 pin_setup();
p07gbar 1:3eb96771bbee 151 write_registers();
p07gbar 1:3eb96771bbee 152 }
p07gbar 1:3eb96771bbee 153
p07gbar 1:3eb96771bbee 154 void I2S::defaulter()
p07gbar 1:3eb96771bbee 155 {
p07gbar 1:3eb96771bbee 156 LPC_SC->PCONP |= (1 << 27);
p07gbar 1:3eb96771bbee 157
p07gbar 1:3eb96771bbee 158 stop();
p07gbar 1:3eb96771bbee 159 master = false;
p07gbar 1:3eb96771bbee 160 deallocating = false;
p07gbar 1:3eb96771bbee 161
p07gbar 1:3eb96771bbee 162 frequency(I2S_DF_SAMPLERATE);
p07gbar 1:3eb96771bbee 163 wordsize(I2S_DF_WORDWIDTH);
p07gbar 1:3eb96771bbee 164 masterslave (I2S_DF_MASTERSLAVE);
p07gbar 1:3eb96771bbee 165 stereomono (I2S_DF_STEREOMONO);
p07gbar 1:3eb96771bbee 166 set_interrupt_fifo_level(I2S_DF_INTERRUPT_FIFO_LEVEL);
p07gbar 1:3eb96771bbee 167 mute (I2S_DF_MUTED);
p07gbar 1:3eb96771bbee 168
p07gbar 1:3eb96771bbee 169 NVIC_SetVector(I2S_IRQn, (uint32_t) & _i2sisr);
p07gbar 1:3eb96771bbee 170 NVIC_EnableIRQ (I2S_IRQn);
p07gbar 1:3eb96771bbee 171 }
p07gbar 1:3eb96771bbee 172
p07gbar 1:3eb96771bbee 173 void I2S::write(char buf[], int len)
p07gbar 1:3eb96771bbee 174 {
p07gbar 1:3eb96771bbee 175 if (_rxtx == I2S_TRANSMIT) {
p07gbar 1:3eb96771bbee 176 if (len > max_fifo_points())
p07gbar 1:3eb96771bbee 177 len = max_fifo_points();
p07gbar 1:3eb96771bbee 178 if (len <= 0)
p07gbar 1:3eb96771bbee 179 return;
p07gbar 1:3eb96771bbee 180 int temp = 0;
p07gbar 1:3eb96771bbee 181 for (int i = 0; i < len; i += 4) {
p07gbar 1:3eb96771bbee 182 temp = 0;
p07gbar 1:3eb96771bbee 183 for (int j = 0; j < 4; j++) {
p07gbar 1:3eb96771bbee 184 temp |= int(buf[i + j]) << (j * 8);
p07gbar 1:3eb96771bbee 185 }
p07gbar 1:3eb96771bbee 186 LPC_I2S->I2STXFIFO = temp;
p07gbar 1:3eb96771bbee 187 }
p07gbar 1:3eb96771bbee 188 }
p07gbar 1:3eb96771bbee 189
p07gbar 1:3eb96771bbee 190 }
p07gbar 1:3eb96771bbee 191
p07gbar 1:3eb96771bbee 192 void I2S::write(int buf[], int len)
p07gbar 1:3eb96771bbee 193 {
p07gbar 1:3eb96771bbee 194 if (_rxtx == I2S_TRANSMIT && wordwidth > 0) {
p07gbar 1:3eb96771bbee 195 if (len > max_fifo_points()) {
p07gbar 1:3eb96771bbee 196 len = max_fifo_points();
p07gbar 1:3eb96771bbee 197 printf("Trying to write too much data!\n\r");
p07gbar 1:3eb96771bbee 198 }
p07gbar 1:3eb96771bbee 199 if (len <= 0)
p07gbar 1:3eb96771bbee 200 return;
p07gbar 1:3eb96771bbee 201 uint32_t temp = 0;
p07gbar 1:3eb96771bbee 202 int increment = 32 / wordwidth;
p07gbar 1:3eb96771bbee 203 unsigned char recast[] =
p07gbar 1:3eb96771bbee 204 { 0, 0, 0, 0 };
p07gbar 1:3eb96771bbee 205 for (int i = 0; i < len; i += increment) {
p07gbar 1:3eb96771bbee 206 temp = 0;
p07gbar 1:3eb96771bbee 207
p07gbar 1:3eb96771bbee 208 switch (wordwidth) {
p07gbar 1:3eb96771bbee 209
p07gbar 1:3eb96771bbee 210 case 8:
p07gbar 1:3eb96771bbee 211
p07gbar 1:3eb96771bbee 212 recast[0] = (int8_t) buf[i + 0];
p07gbar 1:3eb96771bbee 213 recast[1] = (int8_t) buf[i + 1];
p07gbar 1:3eb96771bbee 214 recast[2] = (int8_t) buf[i + 2];
p07gbar 1:3eb96771bbee 215 recast[3] = (int8_t) buf[i + 3];
p07gbar 1:3eb96771bbee 216 break;
p07gbar 1:3eb96771bbee 217 case 16:
p07gbar 1:3eb96771bbee 218 recast[0] = (((int16_t) buf[i + 0]) >> 0) & 0xFF;
p07gbar 1:3eb96771bbee 219 recast[1] = (((int16_t) buf[i + 0]) >> 8) & 0xFF;
p07gbar 1:3eb96771bbee 220 recast[2] = (((int16_t) buf[i + 1]) >> 0) & 0xFF;
p07gbar 1:3eb96771bbee 221 recast[3] = (((int16_t) buf[i + 1]) >> 8) & 0xFF;
p07gbar 1:3eb96771bbee 222 break;
p07gbar 1:3eb96771bbee 223 case 32:
p07gbar 1:3eb96771bbee 224 recast[0] = (((int32_t) buf[i + 0]) >> 0) & 0xFF;
p07gbar 1:3eb96771bbee 225 recast[1] = (((int32_t) buf[i + 0]) >> 8) & 0xFF;
p07gbar 1:3eb96771bbee 226 recast[2] = (((int32_t) buf[i + 0]) >> 16) & 0xFF;
p07gbar 1:3eb96771bbee 227 recast[3] = (((int32_t) buf[i + 0]) >> 24) & 0xFF;
p07gbar 1:3eb96771bbee 228 break;
p07gbar 1:3eb96771bbee 229
p07gbar 1:3eb96771bbee 230 }
p07gbar 1:3eb96771bbee 231 for (int j = 0; j < 4; j++) {
p07gbar 1:3eb96771bbee 232
p07gbar 1:3eb96771bbee 233 temp |= recast[j] << (j * 8);
p07gbar 1:3eb96771bbee 234 }
p07gbar 1:3eb96771bbee 235
p07gbar 1:3eb96771bbee 236 //if(((temp >> 16) & 0xFFFF) == 0xFFFF) printf("Hmmm %x %x %x\n\r",temp, increment,i); //|| temp &0xFFFF == 0xFFFF
p07gbar 1:3eb96771bbee 237 //if((buf[i]-buf[i+1])>5000 || (buf[i]-buf[i+1])<-5000) printf("J:%i,%i\n\r",buf[i],buf[i+1]);
p07gbar 1:3eb96771bbee 238 //printf("%x\n",temp);
p07gbar 1:3eb96771bbee 239 LPC_I2S->I2STXFIFO = temp;
p07gbar 1:3eb96771bbee 240 }
p07gbar 1:3eb96771bbee 241 }
p07gbar 1:3eb96771bbee 242 }
p07gbar 1:3eb96771bbee 243
p07gbar 1:3eb96771bbee 244 void I2S::write(int bufr[], int bufl[], int len)
p07gbar 1:3eb96771bbee 245 {
p07gbar 1:3eb96771bbee 246 //#TODO: Write this!
p07gbar 1:3eb96771bbee 247 }
p07gbar 1:3eb96771bbee 248
p07gbar 1:3eb96771bbee 249 int I2S::read()
p07gbar 1:3eb96771bbee 250 {
p07gbar 1:3eb96771bbee 251 return LPC_I2S->I2SRXFIFO;
p07gbar 1:3eb96771bbee 252 }
p07gbar 1:3eb96771bbee 253
p07gbar 1:3eb96771bbee 254 void I2S::read(char buf[], int len)
p07gbar 1:3eb96771bbee 255 {
p07gbar 1:3eb96771bbee 256 bool len_valid = true;
p07gbar 1:3eb96771bbee 257 if (len <= 0)
p07gbar 1:3eb96771bbee 258 return;
p07gbar 1:3eb96771bbee 259 if (len >= fifo_points())
p07gbar 1:3eb96771bbee 260 len = fifo_points();
p07gbar 1:3eb96771bbee 261 int temp[8];
p07gbar 1:3eb96771bbee 262 int counter = 0;
p07gbar 1:3eb96771bbee 263 int increment = 4; //32/wordwidth;
p07gbar 1:3eb96771bbee 264 int fifo_levl = fifo_level();
p07gbar 1:3eb96771bbee 265 while (counter < fifo_levl && len_valid) {
p07gbar 1:3eb96771bbee 266 temp[counter] = LPC_I2S->I2SRXFIFO;
p07gbar 1:3eb96771bbee 267 for (int j = 0; j < increment; j++) {
p07gbar 1:3eb96771bbee 268 if ((counter * 4) + j > len) {
p07gbar 1:3eb96771bbee 269 len_valid = false;
p07gbar 1:3eb96771bbee 270 break;
p07gbar 1:3eb96771bbee 271 }
p07gbar 1:3eb96771bbee 272 buf[counter + j] = temp[counter] >> (j * 8);
p07gbar 1:3eb96771bbee 273
p07gbar 1:3eb96771bbee 274 }
p07gbar 1:3eb96771bbee 275 counter++;
p07gbar 1:3eb96771bbee 276 }
p07gbar 1:3eb96771bbee 277 }
p07gbar 1:3eb96771bbee 278
p07gbar 1:3eb96771bbee 279 void I2S::read(int buf[], int len)
p07gbar 1:3eb96771bbee 280 {
p07gbar 1:3eb96771bbee 281 bool len_valid = true;
p07gbar 1:3eb96771bbee 282 if (len <= 0)
p07gbar 1:3eb96771bbee 283 return;
p07gbar 1:3eb96771bbee 284 if (len >= fifo_points())
p07gbar 1:3eb96771bbee 285 len = fifo_points();
p07gbar 1:3eb96771bbee 286 int temp[8];
p07gbar 1:3eb96771bbee 287 int counter = 0;
p07gbar 1:3eb96771bbee 288 int increment = 32 / wordwidth;
p07gbar 1:3eb96771bbee 289 int fifo_levl = fifo_level();
p07gbar 1:3eb96771bbee 290 while (counter < fifo_levl && len_valid) {
p07gbar 1:3eb96771bbee 291 temp[counter] = LPC_I2S->I2SRXFIFO;
p07gbar 1:3eb96771bbee 292 for (int j = 0; j < increment; j++) {
p07gbar 1:3eb96771bbee 293 if ((counter * increment) + j > len) {
p07gbar 1:3eb96771bbee 294 len_valid = false;
p07gbar 1:3eb96771bbee 295 break;
p07gbar 1:3eb96771bbee 296 }
p07gbar 1:3eb96771bbee 297 buf[counter + j] = temp[counter] >> (j * wordwidth);
p07gbar 1:3eb96771bbee 298
p07gbar 1:3eb96771bbee 299 }
p07gbar 1:3eb96771bbee 300 counter++;
p07gbar 1:3eb96771bbee 301 }
p07gbar 1:3eb96771bbee 302 }
p07gbar 1:3eb96771bbee 303
p07gbar 1:3eb96771bbee 304 void I2S::read(int bufr[], int bufl[], int len)
p07gbar 1:3eb96771bbee 305 {
p07gbar 1:3eb96771bbee 306 //#TODO: Write this
p07gbar 1:3eb96771bbee 307 }
p07gbar 1:3eb96771bbee 308
p07gbar 1:3eb96771bbee 309 int I2S::max_fifo_points()
p07gbar 1:3eb96771bbee 310 {
p07gbar 1:3eb96771bbee 311 switch (wordwidth) {
p07gbar 1:3eb96771bbee 312 case 8:
p07gbar 1:3eb96771bbee 313 return (4 * 8);
p07gbar 1:3eb96771bbee 314 case 16:
p07gbar 1:3eb96771bbee 315 return (2 * 8);
p07gbar 1:3eb96771bbee 316 case 32:
p07gbar 1:3eb96771bbee 317 return 8;
p07gbar 1:3eb96771bbee 318 default:
p07gbar 1:3eb96771bbee 319 return 0;
p07gbar 1:3eb96771bbee 320 }
p07gbar 1:3eb96771bbee 321 }
p07gbar 1:3eb96771bbee 322
p07gbar 1:3eb96771bbee 323 int I2S::fifo_points()
p07gbar 1:3eb96771bbee 324 {
p07gbar 1:3eb96771bbee 325 switch (wordwidth) {
p07gbar 1:3eb96771bbee 326 case 8:
p07gbar 1:3eb96771bbee 327 return (4 * fifo_level());
p07gbar 1:3eb96771bbee 328 case 16:
p07gbar 1:3eb96771bbee 329 return (2 * fifo_level());
p07gbar 1:3eb96771bbee 330 case 32:
p07gbar 1:3eb96771bbee 331 return fifo_level();
p07gbar 1:3eb96771bbee 332 default:
p07gbar 1:3eb96771bbee 333 return 0;
p07gbar 1:3eb96771bbee 334 }
p07gbar 1:3eb96771bbee 335 }
p07gbar 1:3eb96771bbee 336
p07gbar 1:3eb96771bbee 337 void I2S::power(bool pwr)
p07gbar 1:3eb96771bbee 338 {
p07gbar 1:3eb96771bbee 339 if (pwr) {
p07gbar 1:3eb96771bbee 340 stopped = false;
p07gbar 1:3eb96771bbee 341 } else {
p07gbar 1:3eb96771bbee 342 stopped = true;
p07gbar 1:3eb96771bbee 343 }
p07gbar 1:3eb96771bbee 344 write_registers();
p07gbar 1:3eb96771bbee 345 }
p07gbar 1:3eb96771bbee 346
p07gbar 1:3eb96771bbee 347 void I2S::masterslave(bool mastermode)
p07gbar 1:3eb96771bbee 348 {
p07gbar 1:3eb96771bbee 349 if (mastermode == I2S_MASTER) {
p07gbar 1:3eb96771bbee 350 master = true;
p07gbar 1:3eb96771bbee 351 } else {
p07gbar 1:3eb96771bbee 352 master = false;
p07gbar 1:3eb96771bbee 353 }
p07gbar 1:3eb96771bbee 354 write_registers();
p07gbar 1:3eb96771bbee 355 }
p07gbar 1:3eb96771bbee 356
p07gbar 1:3eb96771bbee 357 void I2S::wordsize(int words)
p07gbar 1:3eb96771bbee 358 {
p07gbar 1:3eb96771bbee 359 wordwidth = words;
p07gbar 1:3eb96771bbee 360 write_registers();
p07gbar 1:3eb96771bbee 361 }
p07gbar 1:3eb96771bbee 362
p07gbar 1:3eb96771bbee 363 void I2S::mclk_freq(int freq)
p07gbar 1:3eb96771bbee 364 {
p07gbar 1:3eb96771bbee 365 mclk_frequency = freq;
p07gbar 1:3eb96771bbee 366 write_registers();
p07gbar 1:3eb96771bbee 367 }
p07gbar 1:3eb96771bbee 368
p07gbar 1:3eb96771bbee 369 void I2S::frequency(int desired_freq)
p07gbar 1:3eb96771bbee 370 {
p07gbar 1:3eb96771bbee 371 freq = desired_freq;
p07gbar 1:3eb96771bbee 372 write_registers();
p07gbar 1:3eb96771bbee 373 }
p07gbar 1:3eb96771bbee 374
p07gbar 1:3eb96771bbee 375 int I2S::fifo_level()
p07gbar 1:3eb96771bbee 376 {
p07gbar 1:3eb96771bbee 377 int level = 0;
p07gbar 1:3eb96771bbee 378 if (_rxtx == I2S_TRANSMIT) {
p07gbar 1:3eb96771bbee 379 level = LPC_I2S->I2SSTATE;
p07gbar 1:3eb96771bbee 380 level >>= 16;
p07gbar 1:3eb96771bbee 381 level &= 0xF;
p07gbar 1:3eb96771bbee 382 } else {
p07gbar 1:3eb96771bbee 383 level = LPC_I2S->I2SSTATE;
p07gbar 1:3eb96771bbee 384 level >>= 8;
p07gbar 1:3eb96771bbee 385 level &= 0xF;
p07gbar 1:3eb96771bbee 386 }
p07gbar 1:3eb96771bbee 387 return level;
p07gbar 1:3eb96771bbee 388 }
p07gbar 1:3eb96771bbee 389
p07gbar 1:3eb96771bbee 390 void I2S::stereomono(bool stereomode)
p07gbar 1:3eb96771bbee 391 {
p07gbar 1:3eb96771bbee 392 if (stereomode == I2S_STEREO) {
p07gbar 1:3eb96771bbee 393 stereo = true;
p07gbar 1:3eb96771bbee 394 } else {
p07gbar 1:3eb96771bbee 395 stereo = false;
p07gbar 1:3eb96771bbee 396 }
p07gbar 1:3eb96771bbee 397 }
p07gbar 1:3eb96771bbee 398
p07gbar 1:3eb96771bbee 399 void I2S::mute()
p07gbar 1:3eb96771bbee 400 {
p07gbar 1:3eb96771bbee 401 muted = true;
p07gbar 1:3eb96771bbee 402 write_registers();
p07gbar 1:3eb96771bbee 403 }
p07gbar 1:3eb96771bbee 404
p07gbar 1:3eb96771bbee 405 void I2S::mute(bool mute_en)
p07gbar 1:3eb96771bbee 406 {
p07gbar 1:3eb96771bbee 407 muted = mute_en;
p07gbar 1:3eb96771bbee 408 write_registers();
p07gbar 1:3eb96771bbee 409 }
p07gbar 1:3eb96771bbee 410
p07gbar 1:3eb96771bbee 411 void I2S::stop()
p07gbar 1:3eb96771bbee 412 {
p07gbar 1:3eb96771bbee 413 stopped = true;
p07gbar 1:3eb96771bbee 414 write_registers();
p07gbar 1:3eb96771bbee 415 }
p07gbar 1:3eb96771bbee 416
p07gbar 1:3eb96771bbee 417 void I2S::set_interrupt_fifo_level(int level)
p07gbar 1:3eb96771bbee 418 {
p07gbar 1:3eb96771bbee 419 interrupt_fifo_level = level;
p07gbar 1:3eb96771bbee 420 write_registers();
p07gbar 1:3eb96771bbee 421 }
p07gbar 1:3eb96771bbee 422
p07gbar 1:3eb96771bbee 423 void I2S::start()
p07gbar 1:3eb96771bbee 424 {
p07gbar 1:3eb96771bbee 425 stopped = false;
p07gbar 1:3eb96771bbee 426 muted = false;
p07gbar 1:3eb96771bbee 427 write_registers();
p07gbar 1:3eb96771bbee 428 }
p07gbar 1:3eb96771bbee 429
p07gbar 1:3eb96771bbee 430 bool I2S::setup_ok()
p07gbar 1:3eb96771bbee 431 {
p07gbar 1:3eb96771bbee 432 if ((reg_write_err + pin_setup_err) > 0)
p07gbar 1:3eb96771bbee 433 return false;
p07gbar 1:3eb96771bbee 434 else
p07gbar 1:3eb96771bbee 435 return true;
p07gbar 1:3eb96771bbee 436 }
p07gbar 1:3eb96771bbee 437
p07gbar 1:3eb96771bbee 438 void I2S::pin_setup()
p07gbar 1:3eb96771bbee 439 {
p07gbar 1:3eb96771bbee 440 pin_setup_err = 0;
p07gbar 1:3eb96771bbee 441
p07gbar 1:3eb96771bbee 442 if (_rxtx == I2S_TRANSMIT) {
p07gbar 1:3eb96771bbee 443 printf("\n\rSetting up pins....\n\r");
p07gbar 1:3eb96771bbee 444 if (_sd != p5)
p07gbar 1:3eb96771bbee 445 pin_setup_err++;
p07gbar 1:3eb96771bbee 446 if (_ws != p6 && ws_d == true)
p07gbar 1:3eb96771bbee 447 pin_setup_err++;
p07gbar 1:3eb96771bbee 448 if (_clk != p7 && clk_d == true)
p07gbar 1:3eb96771bbee 449 pin_setup_err++;
p07gbar 1:3eb96771bbee 450 printf("Hmm....%i\n\r", pin_setup_err);
p07gbar 1:3eb96771bbee 451 } else {
p07gbar 1:3eb96771bbee 452 if (_sd != p17 && _sd != p8)
p07gbar 1:3eb96771bbee 453 pin_setup_err++;
p07gbar 1:3eb96771bbee 454 if (_ws != p16 && _ws != p29 && ws_d == true)
p07gbar 1:3eb96771bbee 455 pin_setup_err++;
p07gbar 1:3eb96771bbee 456 if (_clk != p15 && _clk != p30 && clk_d == true)
p07gbar 1:3eb96771bbee 457 pin_setup_err++;
p07gbar 1:3eb96771bbee 458 }
p07gbar 1:3eb96771bbee 459
p07gbar 1:3eb96771bbee 460 if (pin_setup_err == 0) {
p07gbar 1:3eb96771bbee 461 if (_rxtx == I2S_TRANSMIT) {
p07gbar 1:3eb96771bbee 462 int val1 = 1;
p07gbar 1:3eb96771bbee 463 if (deallocating) {
p07gbar 1:3eb96771bbee 464 val1 = 0;
p07gbar 1:3eb96771bbee 465 }
p07gbar 1:3eb96771bbee 466 LPC_PINCON->PINSEL0 |= (val1 << 18); //set p5 as transmit serial data line
p07gbar 1:3eb96771bbee 467 if (ws_d == true)
p07gbar 1:3eb96771bbee 468 LPC_PINCON->PINSEL0 |= (val1 << 14); //set p7 as transmit clock line
p07gbar 1:3eb96771bbee 469 if (clk_d == true)
p07gbar 1:3eb96771bbee 470 LPC_PINCON->PINSEL0 |= (val1 << 16); //set p6 as word select line
p07gbar 1:3eb96771bbee 471
p07gbar 1:3eb96771bbee 472 } else {
p07gbar 1:3eb96771bbee 473 int val1 = 1;
p07gbar 1:3eb96771bbee 474 int val2 = 2;
p07gbar 1:3eb96771bbee 475 if (deallocating) {
p07gbar 1:3eb96771bbee 476 val1 = 0;
p07gbar 1:3eb96771bbee 477 val2 = 0;
p07gbar 1:3eb96771bbee 478 }
p07gbar 1:3eb96771bbee 479
p07gbar 1:3eb96771bbee 480 if (_sd == p8)
p07gbar 1:3eb96771bbee 481 LPC_PINCON->PINSEL0 |= (val1 << 12);
p07gbar 1:3eb96771bbee 482 else
p07gbar 1:3eb96771bbee 483 LPC_PINCON->PINSEL1 |= (val2 << 18);
p07gbar 1:3eb96771bbee 484
p07gbar 1:3eb96771bbee 485 if (ws_d == true) {
p07gbar 1:3eb96771bbee 486 if (_ws == p29)
p07gbar 1:3eb96771bbee 487 LPC_PINCON->PINSEL0 |= (val1 << 10);
p07gbar 1:3eb96771bbee 488 else
p07gbar 1:3eb96771bbee 489 LPC_PINCON->PINSEL1 |= (val2 << 16);
p07gbar 1:3eb96771bbee 490 }
p07gbar 1:3eb96771bbee 491
p07gbar 1:3eb96771bbee 492 if (clk_d == true) {
p07gbar 1:3eb96771bbee 493 if (_clk == p15)
p07gbar 1:3eb96771bbee 494 LPC_PINCON->PINSEL0 |= (val1 << 8);
p07gbar 1:3eb96771bbee 495 else
p07gbar 1:3eb96771bbee 496 LPC_PINCON->PINSEL1 |= (val2 << 14);
p07gbar 1:3eb96771bbee 497 }
p07gbar 1:3eb96771bbee 498 }
p07gbar 1:3eb96771bbee 499 }
p07gbar 1:3eb96771bbee 500 }
p07gbar 1:3eb96771bbee 501
p07gbar 1:3eb96771bbee 502 void I2S::write_registers()
p07gbar 1:3eb96771bbee 503 {
p07gbar 1:3eb96771bbee 504 reg_write_err = 0;
p07gbar 1:3eb96771bbee 505 //Clock Multiplier Calculations
p07gbar 1:3eb96771bbee 506 float pre_mult = 0;
p07gbar 1:3eb96771bbee 507 int pre_num = 0;
p07gbar 1:3eb96771bbee 508 int pre_den = 0;
p07gbar 1:3eb96771bbee 509 int bitrate_div = 0;
p07gbar 1:3eb96771bbee 510 if (master == true) { // In the hope of not doing all this heavy lifting every configuration
p07gbar 1:3eb96771bbee 511 //printf("Doing some clock magic..\n\r");
p07gbar 1:3eb96771bbee 512 int bitrate = freq * 64;
p07gbar 1:3eb96771bbee 513 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
p07gbar 1:3eb96771bbee 514 if (mclk_frequency == 0) {
p07gbar 1:3eb96771bbee 515 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
p07gbar 1:3eb96771bbee 516 bitrate_div = int(target_div - rnd);
p07gbar 1:3eb96771bbee 517 while (bitrate_div > I2S_MAX_BITRATE_DIV) { // But this might be out of range, so we right shift it into focus
p07gbar 1:3eb96771bbee 518 bitrate_div >>= 1;
p07gbar 1:3eb96771bbee 519 }
p07gbar 1:3eb96771bbee 520 if (bitrate_div == 0) { // Could be zero, which would disable the the clock...
p07gbar 1:3eb96771bbee 521 bitrate_div = 1;
p07gbar 1:3eb96771bbee 522 }
p07gbar 1:3eb96771bbee 523 pre_mult = float(bitrate_div) / target_div; // Work out what we have left to correct
p07gbar 1:3eb96771bbee 524 pre_num = 0;
p07gbar 1:3eb96771bbee 525 pre_den = 0;
p07gbar 1:3eb96771bbee 526 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
p07gbar 1:3eb96771bbee 527
p07gbar 1:3eb96771bbee 528 } else {
p07gbar 1:3eb96771bbee 529 pre_mult = float(mclk_frequency * 2) / (I2S_PCLK_RATE);
p07gbar 1:3eb96771bbee 530 pre_num = 0;
p07gbar 1:3eb96771bbee 531 pre_den = 0;
p07gbar 1:3eb96771bbee 532 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
p07gbar 1:3eb96771bbee 533 bitrate_div = int(
p07gbar 1:3eb96771bbee 534 I2S_PCLK_RATE * float(pre_num) / float(pre_den)
p07gbar 1:3eb96771bbee 535 / float(bitrate));
p07gbar 1:3eb96771bbee 536 }
p07gbar 1:3eb96771bbee 537
p07gbar 1:3eb96771bbee 538 old_freq = freq;
p07gbar 1:3eb96771bbee 539 old_pre_num = pre_num;
p07gbar 1:3eb96771bbee 540 old_pre_den = pre_den;
p07gbar 1:3eb96771bbee 541 old_bitrate_div = bitrate_div;
p07gbar 1:3eb96771bbee 542 } else {
p07gbar 1:3eb96771bbee 543 pre_num = old_pre_num;
p07gbar 1:3eb96771bbee 544 pre_den = old_pre_den;
p07gbar 1:3eb96771bbee 545 bitrate_div = old_bitrate_div;
p07gbar 1:3eb96771bbee 546 }
p07gbar 1:3eb96771bbee 547
p07gbar 1:3eb96771bbee 548 //Clock Multiplier, MCLK setup
p07gbar 1:3eb96771bbee 549 if (_rxtx == I2S_TRANSMIT) {
p07gbar 1:3eb96771bbee 550 int regvals = ((pre_num << 8) & 0xFF00) | (pre_den & 0xFF);
p07gbar 1:3eb96771bbee 551 LPC_I2S->I2STXRATE = regvals; // Setting the X/Y fraction
p07gbar 1:3eb96771bbee 552 LPC_I2S->I2STXBITRATE = (bitrate_div - 1) & 0x3F;// Setting up the bitrate divider, the periferal adds one to this
p07gbar 1:3eb96771bbee 553
p07gbar 1:3eb96771bbee 554 LPC_I2S->I2STXMODE = fourwire << 2;
p07gbar 1:3eb96771bbee 555
p07gbar 1:3eb96771bbee 556 if (mclk_d == true) {
p07gbar 1:3eb96771bbee 557 LPC_I2S->I2STXMODE |= (1 << 3);
p07gbar 1:3eb96771bbee 558 }
p07gbar 1:3eb96771bbee 559 } else {
p07gbar 1:3eb96771bbee 560 int regvals = ((pre_num << 8) & 0xFF00) | (pre_den & 0xFF);
p07gbar 1:3eb96771bbee 561 LPC_I2S->I2SRXRATE = regvals; // Setting the X/Y fraction
p07gbar 1:3eb96771bbee 562 LPC_I2S->I2SRXBITRATE = (bitrate_div - 1) & 0x3F;// Setting up the bitrate divider, the periferal adds one to this
p07gbar 1:3eb96771bbee 563
p07gbar 1:3eb96771bbee 564 LPC_I2S->I2SRXMODE = fourwire << 2;
p07gbar 1:3eb96771bbee 565
p07gbar 1:3eb96771bbee 566 if (mclk_d == true) {
p07gbar 1:3eb96771bbee 567 LPC_I2S->I2SRXMODE |= (1 << 3);
p07gbar 1:3eb96771bbee 568 }
p07gbar 1:3eb96771bbee 569 }
p07gbar 1:3eb96771bbee 570
p07gbar 1:3eb96771bbee 571 switch (wordwidth) {
p07gbar 1:3eb96771bbee 572 case 8:
p07gbar 1:3eb96771bbee 573 wordwidth_code = 0;
p07gbar 1:3eb96771bbee 574 break;
p07gbar 1:3eb96771bbee 575 case 16:
p07gbar 1:3eb96771bbee 576 wordwidth_code = 1;
p07gbar 1:3eb96771bbee 577 break;
p07gbar 1:3eb96771bbee 578 case 32:
p07gbar 1:3eb96771bbee 579 wordwidth_code = 3;
p07gbar 1:3eb96771bbee 580 break;
p07gbar 1:3eb96771bbee 581 default:
p07gbar 1:3eb96771bbee 582 reg_write_err++;
p07gbar 1:3eb96771bbee 583 break;
p07gbar 1:3eb96771bbee 584 }
p07gbar 1:3eb96771bbee 585
p07gbar 1:3eb96771bbee 586 int I2SDA_reg = (wordwidth_code & 0x3);
p07gbar 1:3eb96771bbee 587 I2SDA_reg |= ((!stereo << 2) & 0x4);
p07gbar 1:3eb96771bbee 588 I2SDA_reg |= ((stopped << 3) & 0x8);
p07gbar 1:3eb96771bbee 589 I2SDA_reg |= ((!master << 5) & 0x20);
p07gbar 1:3eb96771bbee 590 I2SDA_reg |= (0x1F << 6);
p07gbar 1:3eb96771bbee 591 I2SDA_reg |= ((muted << 15) & 0x8000);
p07gbar 1:3eb96771bbee 592
p07gbar 1:3eb96771bbee 593 if (_rxtx == I2S_TRANSMIT) {
p07gbar 1:3eb96771bbee 594 LPC_I2S->I2SDAO = I2SDA_reg;
p07gbar 1:3eb96771bbee 595 } else {
p07gbar 1:3eb96771bbee 596 LPC_I2S->I2SDAI = I2SDA_reg;
p07gbar 1:3eb96771bbee 597 }
p07gbar 1:3eb96771bbee 598
p07gbar 1:3eb96771bbee 599 if (_rxtx == I2S_TRANSMIT) {
p07gbar 1:3eb96771bbee 600 if (txisr) {
p07gbar 1:3eb96771bbee 601 LPC_I2S->I2SIRQ = (LPC_I2S->I2SIRQ & 0xFF0FFFFF)
p07gbar 1:3eb96771bbee 602 | ((interrupt_fifo_level & 0xF) << 16);
p07gbar 1:3eb96771bbee 603 LPC_I2S->I2SIRQ |= 0x2;
p07gbar 1:3eb96771bbee 604 } else {
p07gbar 1:3eb96771bbee 605 LPC_I2S->I2SIRQ &= 0xFFFFFFFD;
p07gbar 1:3eb96771bbee 606 }
p07gbar 1:3eb96771bbee 607 } else {
p07gbar 1:3eb96771bbee 608 if (rxisr) {
p07gbar 1:3eb96771bbee 609 LPC_I2S->I2SIRQ = (LPC_I2S->I2SIRQ & 0xFFFFF0FF)
p07gbar 1:3eb96771bbee 610 | ((interrupt_fifo_level & 0xF) << 8);
p07gbar 1:3eb96771bbee 611 LPC_I2S->I2SIRQ |= 0x1;
p07gbar 1:3eb96771bbee 612 }
p07gbar 1:3eb96771bbee 613
p07gbar 1:3eb96771bbee 614 else {
p07gbar 1:3eb96771bbee 615 LPC_I2S->I2SIRQ &= 0xFFFFFFFE;
p07gbar 1:3eb96771bbee 616 }
p07gbar 1:3eb96771bbee 617 }
p07gbar 1:3eb96771bbee 618 }
p07gbar 1:3eb96771bbee 619
p07gbar 1:3eb96771bbee 620 void I2S::_i2sisr(void)
p07gbar 1:3eb96771bbee 621 {
p07gbar 1:3eb96771bbee 622 I2STXISR.call();
p07gbar 1:3eb96771bbee 623 I2SRXISR.call();
p07gbar 1:3eb96771bbee 624 }
p07gbar 1:3eb96771bbee 625
p07gbar 1:3eb96771bbee 626 // A function to find the nearest fraction to that put to it, with numerator and denomnator less than 256
p07gbar 1:3eb96771bbee 627 // This is used when trying to get the clocks correct
p07gbar 1:3eb96771bbee 628
p07gbar 1:3eb96771bbee 629 void I2S::fraction_estimator(float in, int * num, int * den)
p07gbar 1:3eb96771bbee 630 {
p07gbar 1:3eb96771bbee 631 int test_num = 0;
p07gbar 1:3eb96771bbee 632 int test_den = 0;
p07gbar 1:3eb96771bbee 633 float least_error = 1;
p07gbar 1:3eb96771bbee 634 int least_err_den = 0;
p07gbar 1:3eb96771bbee 635 float genval;
p07gbar 1:3eb96771bbee 636 float generr;
p07gbar 1:3eb96771bbee 637
p07gbar 1:3eb96771bbee 638 for (test_den = 1; test_den < I2S_MAX_DENOMINATOR; test_den++) {
p07gbar 1:3eb96771bbee 639 test_num = int(float(test_den) * in);
p07gbar 1:3eb96771bbee 640 if (test_num < I2S_MAX_NUMERATOR && test_num > 0) {
p07gbar 1:3eb96771bbee 641 genval = float(test_num) / float(test_den);
p07gbar 1:3eb96771bbee 642 generr = mod(genval - in);
p07gbar 1:3eb96771bbee 643 if (generr < least_error) {
p07gbar 1:3eb96771bbee 644 least_error = generr;
p07gbar 1:3eb96771bbee 645 least_err_den = test_den;
p07gbar 1:3eb96771bbee 646 }
p07gbar 1:3eb96771bbee 647 if (generr == 0) {
p07gbar 1:3eb96771bbee 648 break;
p07gbar 1:3eb96771bbee 649 }
p07gbar 1:3eb96771bbee 650 }
p07gbar 1:3eb96771bbee 651 }
p07gbar 1:3eb96771bbee 652
p07gbar 1:3eb96771bbee 653 test_num = int(float(least_err_den) * in);
p07gbar 1:3eb96771bbee 654 *num = test_num;
p07gbar 1:3eb96771bbee 655 *den = least_err_den;
p07gbar 1:3eb96771bbee 656
p07gbar 1:3eb96771bbee 657 }
p07gbar 1:3eb96771bbee 658
p07gbar 1:3eb96771bbee 659 float I2S::mod(float in)
p07gbar 1:3eb96771bbee 660 {
p07gbar 1:3eb96771bbee 661 if (in < 0)
p07gbar 1:3eb96771bbee 662 in *= -1;
p07gbar 1:3eb96771bbee 663
p07gbar 1:3eb96771bbee 664 return in;
p07gbar 1:3eb96771bbee 665 }