Adapted to work with the LPC4088 Experiment Base Board

Dependents:   lpc4088_ebb_ptp Algorithm-testing

Fork of I2S by Giles Barton-Owen

Committer:
embeddedartists
Date:
Mon Sep 08 11:33:30 2014 +0000
Revision:
1:af579d286498
Parent:
0:455d5826751b
Changed sample rate and pinning to work on the LPC4088 Experiment Base Board.

Who changed what in which revision?

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