[ FORK ] I2S library for FRDM 64F, forked from p07gbar/I2S

Fork of I2S by Giles Barton-Owen

Committer:
k4zuki
Date:
Wed Mar 16 09:45:18 2016 +0000
Revision:
1:89cea1a77092
Parent:
0:455d5826751b
Child:
2:dd2c3c0ec223
developing HAL layer for FRDM board(assuming 64F and _maybe_ 46 also?

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
p07gbar 0:455d5826751b 4 #define I2S_DF_SAMPLERATE 32000
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
p07gbar 0:455d5826751b 14 #define I2S_PCLK_RATE 24000000
p07gbar 0:455d5826751b 15
p07gbar 0:455d5826751b 16 FunctionPointer I2S::I2STXISR;
p07gbar 0:455d5826751b 17 FunctionPointer I2S::I2SRXISR;
p07gbar 0:455d5826751b 18
p07gbar 0:455d5826751b 19 bool I2S::txisr;
p07gbar 0:455d5826751b 20 bool I2S::rxisr;
p07gbar 0:455d5826751b 21
p07gbar 0:455d5826751b 22 I2S::I2S(bool rxtx, PinName sd, PinName ws, PinName clk)
p07gbar 0:455d5826751b 23 {
k4zuki 1:89cea1a77092 24 NVIC_DisableIRQ (I2S0_Tx_IRQn);
k4zuki 1:89cea1a77092 25 NVIC_DisableIRQ (I2S0_Rx_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 {
k4zuki 1:89cea1a77092 51 NVIC_DisableIRQ (I2S0_Tx_IRQn);
k4zuki 1:89cea1a77092 52 NVIC_DisableIRQ (I2S0_Rx_IRQn);
p07gbar 0:455d5826751b 53
p07gbar 0:455d5826751b 54 _sd = sd;
p07gbar 0:455d5826751b 55 _rxtx = rxtx;
p07gbar 0:455d5826751b 56
p07gbar 0:455d5826751b 57 ws_d = false;
p07gbar 0:455d5826751b 58 clk_d = false;
p07gbar 0:455d5826751b 59 mclk_d = false;
p07gbar 0:455d5826751b 60
p07gbar 0:455d5826751b 61 fourwire = false;
p07gbar 0:455d5826751b 62
p07gbar 0:455d5826751b 63 reg_write_err = 0;
p07gbar 0:455d5826751b 64
p07gbar 0:455d5826751b 65 pin_setup();
p07gbar 0:455d5826751b 66
p07gbar 0:455d5826751b 67 if (pin_setup_err != 0) {
p07gbar 0:455d5826751b 68 perror("I2S Pins incorrectly defined.");
p07gbar 0:455d5826751b 69 }
p07gbar 0:455d5826751b 70
p07gbar 0:455d5826751b 71 defaulter();
p07gbar 0:455d5826751b 72 }
p07gbar 0:455d5826751b 73
p07gbar 0:455d5826751b 74 I2S::I2S(bool rxtx, PinName sd, bool fourwiremode)
p07gbar 0:455d5826751b 75 {
k4zuki 1:89cea1a77092 76 NVIC_DisableIRQ (I2S0_Tx_IRQn);
k4zuki 1:89cea1a77092 77 NVIC_DisableIRQ (I2S0_Rx_IRQn);
p07gbar 0:455d5826751b 78
p07gbar 0:455d5826751b 79 _sd = sd;
p07gbar 0:455d5826751b 80 _rxtx = rxtx;
p07gbar 0:455d5826751b 81
p07gbar 0:455d5826751b 82 ws_d = false;
p07gbar 0:455d5826751b 83 clk_d = false;
p07gbar 0:455d5826751b 84 mclk_d = false;
p07gbar 0:455d5826751b 85
p07gbar 0:455d5826751b 86 reg_write_err = 0;
p07gbar 0:455d5826751b 87
p07gbar 0:455d5826751b 88 fourwire = fourwiremode;
p07gbar 0:455d5826751b 89
p07gbar 0:455d5826751b 90 pin_setup();
p07gbar 0:455d5826751b 91
p07gbar 0:455d5826751b 92 if (pin_setup_err != 0) {
p07gbar 0:455d5826751b 93 perror("I2S Pins incorrectly defined.");
p07gbar 0:455d5826751b 94 }
p07gbar 0:455d5826751b 95
p07gbar 0:455d5826751b 96 defaulter();
p07gbar 0:455d5826751b 97 }
p07gbar 0:455d5826751b 98
p07gbar 0:455d5826751b 99 I2S::I2S(bool rxtx, PinName sd, PinName ws, bool fourwiremode)
p07gbar 0:455d5826751b 100 {
k4zuki 1:89cea1a77092 101 NVIC_DisableIRQ (I2S0_Tx_IRQn);
k4zuki 1:89cea1a77092 102 NVIC_DisableIRQ (I2S0_Rx_IRQn);
p07gbar 0:455d5826751b 103
p07gbar 0:455d5826751b 104 _sd = sd;
p07gbar 0:455d5826751b 105 _ws = ws;
p07gbar 0:455d5826751b 106 _rxtx = rxtx;
p07gbar 0:455d5826751b 107
p07gbar 0:455d5826751b 108 ws_d = true;
p07gbar 0:455d5826751b 109 clk_d = false;
p07gbar 0:455d5826751b 110 mclk_d = false;
p07gbar 0:455d5826751b 111
p07gbar 0:455d5826751b 112 reg_write_err = 0;
p07gbar 0:455d5826751b 113
p07gbar 0:455d5826751b 114 fourwire = fourwiremode;
p07gbar 0:455d5826751b 115
p07gbar 0:455d5826751b 116 pin_setup();
p07gbar 0:455d5826751b 117
p07gbar 0:455d5826751b 118 if (pin_setup_err != 0) {
p07gbar 0:455d5826751b 119 perror("I2S Pins incorrectly defined.");
p07gbar 0:455d5826751b 120 }
p07gbar 0:455d5826751b 121
p07gbar 0:455d5826751b 122 defaulter();
p07gbar 0:455d5826751b 123 }
p07gbar 0:455d5826751b 124
p07gbar 0:455d5826751b 125 I2S::I2S(bool rxtx, PinName sd, PinName ws)
p07gbar 0:455d5826751b 126 {
k4zuki 1:89cea1a77092 127 NVIC_DisableIRQ (I2S0_Tx_IRQn);
k4zuki 1:89cea1a77092 128 NVIC_DisableIRQ (I2S0_Rx_IRQn);
p07gbar 0:455d5826751b 129
p07gbar 0:455d5826751b 130 _sd = sd;
p07gbar 0:455d5826751b 131 _ws = ws;
p07gbar 0:455d5826751b 132 _rxtx = rxtx;
p07gbar 0:455d5826751b 133
p07gbar 0:455d5826751b 134 ws_d = true;
p07gbar 0:455d5826751b 135 clk_d = false;
p07gbar 0:455d5826751b 136 mclk_d = false;
p07gbar 0:455d5826751b 137
p07gbar 0:455d5826751b 138 reg_write_err = 0;
p07gbar 0:455d5826751b 139
p07gbar 0:455d5826751b 140 fourwire = false;
p07gbar 0:455d5826751b 141
p07gbar 0:455d5826751b 142 pin_setup();
p07gbar 0:455d5826751b 143
p07gbar 0:455d5826751b 144 if (pin_setup_err != 0) {
p07gbar 0:455d5826751b 145 perror("I2S Pins incorrectly defined.");
p07gbar 0:455d5826751b 146 }
p07gbar 0:455d5826751b 147
p07gbar 0:455d5826751b 148 defaulter();
p07gbar 0:455d5826751b 149 }
p07gbar 0:455d5826751b 150
p07gbar 0:455d5826751b 151 I2S::~I2S()
p07gbar 0:455d5826751b 152 {
k4zuki 1:89cea1a77092 153 NVIC_DisableIRQ (I2S0_Tx_IRQn);
k4zuki 1:89cea1a77092 154 NVIC_DisableIRQ (I2S0_Rx_IRQn);
k4zuki 1:89cea1a77092 155
p07gbar 0:455d5826751b 156 deallocating = true;
p07gbar 0:455d5826751b 157 pin_setup();
p07gbar 0:455d5826751b 158 write_registers();
p07gbar 0:455d5826751b 159 }
p07gbar 0:455d5826751b 160
p07gbar 0:455d5826751b 161 void I2S::defaulter()
p07gbar 0:455d5826751b 162 {
k4zuki 1:89cea1a77092 163 I2S0_TCSR |= 1u<<31;
p07gbar 0:455d5826751b 164
p07gbar 0:455d5826751b 165 stop();
p07gbar 0:455d5826751b 166 master = false;
p07gbar 0:455d5826751b 167 deallocating = false;
p07gbar 0:455d5826751b 168
p07gbar 0:455d5826751b 169 frequency(I2S_DF_SAMPLERATE);
p07gbar 0:455d5826751b 170 wordsize(I2S_DF_WORDWIDTH);
p07gbar 0:455d5826751b 171 masterslave (I2S_DF_MASTERSLAVE);
p07gbar 0:455d5826751b 172 stereomono (I2S_DF_STEREOMONO);
p07gbar 0:455d5826751b 173 set_interrupt_fifo_level(I2S_DF_INTERRUPT_FIFO_LEVEL);
p07gbar 0:455d5826751b 174 mute (I2S_DF_MUTED);
p07gbar 0:455d5826751b 175
k4zuki 1:89cea1a77092 176 NVIC_SetVector(I2S0_Tx_IRQn, (uint32_t) & _i2sisr);
k4zuki 1:89cea1a77092 177 NVIC_EnableIRQ (I2S0_Tx_IRQn);
p07gbar 0:455d5826751b 178 }
p07gbar 0:455d5826751b 179
p07gbar 0:455d5826751b 180 void I2S::write(char buf[], int len)
p07gbar 0:455d5826751b 181 {
p07gbar 0:455d5826751b 182 if (_rxtx == I2S_TRANSMIT) {
p07gbar 0:455d5826751b 183 if (len > max_fifo_points())
p07gbar 0:455d5826751b 184 len = max_fifo_points();
p07gbar 0:455d5826751b 185 if (len <= 0)
p07gbar 0:455d5826751b 186 return;
p07gbar 0:455d5826751b 187 int temp = 0;
p07gbar 0:455d5826751b 188 for (int i = 0; i < len; i += 4) {
p07gbar 0:455d5826751b 189 temp = 0;
p07gbar 0:455d5826751b 190 for (int j = 0; j < 4; j++) {
p07gbar 0:455d5826751b 191 temp |= int(buf[i + j]) << (j * 8);
p07gbar 0:455d5826751b 192 }
k4zuki 1:89cea1a77092 193 I2S0_TDR0 = temp;
p07gbar 0:455d5826751b 194 }
p07gbar 0:455d5826751b 195 }
p07gbar 0:455d5826751b 196
p07gbar 0:455d5826751b 197 }
p07gbar 0:455d5826751b 198
p07gbar 0:455d5826751b 199 void I2S::write(int buf[], int len)
p07gbar 0:455d5826751b 200 {
p07gbar 0:455d5826751b 201 if (_rxtx == I2S_TRANSMIT && wordwidth > 0) {
p07gbar 0:455d5826751b 202 if (len > max_fifo_points()) {
p07gbar 0:455d5826751b 203 len = max_fifo_points();
p07gbar 0:455d5826751b 204 printf("Trying to write too much data!\n\r");
p07gbar 0:455d5826751b 205 }
p07gbar 0:455d5826751b 206 if (len <= 0)
p07gbar 0:455d5826751b 207 return;
p07gbar 0:455d5826751b 208 uint32_t temp = 0;
p07gbar 0:455d5826751b 209 int increment = 32 / wordwidth;
p07gbar 0:455d5826751b 210 unsigned char recast[] =
p07gbar 0:455d5826751b 211 { 0, 0, 0, 0 };
p07gbar 0:455d5826751b 212 for (int i = 0; i < len; i += increment) {
p07gbar 0:455d5826751b 213 temp = 0;
p07gbar 0:455d5826751b 214
p07gbar 0:455d5826751b 215 switch (wordwidth) {
p07gbar 0:455d5826751b 216
p07gbar 0:455d5826751b 217 case 8:
p07gbar 0:455d5826751b 218
p07gbar 0:455d5826751b 219 recast[0] = (int8_t) buf[i + 0];
p07gbar 0:455d5826751b 220 recast[1] = (int8_t) buf[i + 1];
p07gbar 0:455d5826751b 221 recast[2] = (int8_t) buf[i + 2];
p07gbar 0:455d5826751b 222 recast[3] = (int8_t) buf[i + 3];
p07gbar 0:455d5826751b 223 break;
p07gbar 0:455d5826751b 224 case 16:
p07gbar 0:455d5826751b 225 recast[0] = (((int16_t) buf[i + 0]) >> 0) & 0xFF;
p07gbar 0:455d5826751b 226 recast[1] = (((int16_t) buf[i + 0]) >> 8) & 0xFF;
p07gbar 0:455d5826751b 227 recast[2] = (((int16_t) buf[i + 1]) >> 0) & 0xFF;
p07gbar 0:455d5826751b 228 recast[3] = (((int16_t) buf[i + 1]) >> 8) & 0xFF;
p07gbar 0:455d5826751b 229 break;
p07gbar 0:455d5826751b 230 case 32:
p07gbar 0:455d5826751b 231 recast[0] = (((int32_t) buf[i + 0]) >> 0) & 0xFF;
p07gbar 0:455d5826751b 232 recast[1] = (((int32_t) buf[i + 0]) >> 8) & 0xFF;
p07gbar 0:455d5826751b 233 recast[2] = (((int32_t) buf[i + 0]) >> 16) & 0xFF;
p07gbar 0:455d5826751b 234 recast[3] = (((int32_t) buf[i + 0]) >> 24) & 0xFF;
p07gbar 0:455d5826751b 235 break;
p07gbar 0:455d5826751b 236
p07gbar 0:455d5826751b 237 }
p07gbar 0:455d5826751b 238 for (int j = 0; j < 4; j++) {
p07gbar 0:455d5826751b 239
p07gbar 0:455d5826751b 240 temp |= recast[j] << (j * 8);
p07gbar 0:455d5826751b 241 }
p07gbar 0:455d5826751b 242
p07gbar 0:455d5826751b 243 //if(((temp >> 16) & 0xFFFF) == 0xFFFF) printf("Hmmm %x %x %x\n\r",temp, increment,i); //|| temp &0xFFFF == 0xFFFF
p07gbar 0:455d5826751b 244 //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 245 //printf("%x\n",temp);
k4zuki 1:89cea1a77092 246 I2S0_TDR0 = temp;
p07gbar 0:455d5826751b 247 }
p07gbar 0:455d5826751b 248 }
p07gbar 0:455d5826751b 249 }
p07gbar 0:455d5826751b 250
p07gbar 0:455d5826751b 251 void I2S::write(int bufr[], int bufl[], int len)
p07gbar 0:455d5826751b 252 {
p07gbar 0:455d5826751b 253 //#TODO: Write this!
p07gbar 0:455d5826751b 254 }
p07gbar 0:455d5826751b 255
p07gbar 0:455d5826751b 256 int I2S::read()
p07gbar 0:455d5826751b 257 {
k4zuki 1:89cea1a77092 258 return I2S0_RDR0;
p07gbar 0:455d5826751b 259 }
p07gbar 0:455d5826751b 260
p07gbar 0:455d5826751b 261 void I2S::read(char buf[], int len)
p07gbar 0:455d5826751b 262 {
p07gbar 0:455d5826751b 263 bool len_valid = true;
p07gbar 0:455d5826751b 264 if (len <= 0)
p07gbar 0:455d5826751b 265 return;
p07gbar 0:455d5826751b 266 if (len >= fifo_points())
p07gbar 0:455d5826751b 267 len = fifo_points();
p07gbar 0:455d5826751b 268 int temp[8];
p07gbar 0:455d5826751b 269 int counter = 0;
p07gbar 0:455d5826751b 270 int increment = 4; //32/wordwidth;
p07gbar 0:455d5826751b 271 int fifo_levl = fifo_level();
p07gbar 0:455d5826751b 272 while (counter < fifo_levl && len_valid) {
k4zuki 1:89cea1a77092 273 temp[counter] = I2S0_RDR0;
p07gbar 0:455d5826751b 274 for (int j = 0; j < increment; j++) {
p07gbar 0:455d5826751b 275 if ((counter * 4) + j > len) {
p07gbar 0:455d5826751b 276 len_valid = false;
p07gbar 0:455d5826751b 277 break;
p07gbar 0:455d5826751b 278 }
p07gbar 0:455d5826751b 279 buf[counter + j] = temp[counter] >> (j * 8);
p07gbar 0:455d5826751b 280
p07gbar 0:455d5826751b 281 }
p07gbar 0:455d5826751b 282 counter++;
p07gbar 0:455d5826751b 283 }
p07gbar 0:455d5826751b 284 }
p07gbar 0:455d5826751b 285
p07gbar 0:455d5826751b 286 void I2S::read(int buf[], int len)
p07gbar 0:455d5826751b 287 {
p07gbar 0:455d5826751b 288 bool len_valid = true;
p07gbar 0:455d5826751b 289 if (len <= 0)
p07gbar 0:455d5826751b 290 return;
p07gbar 0:455d5826751b 291 if (len >= fifo_points())
p07gbar 0:455d5826751b 292 len = fifo_points();
p07gbar 0:455d5826751b 293 int temp[8];
p07gbar 0:455d5826751b 294 int counter = 0;
p07gbar 0:455d5826751b 295 int increment = 32 / wordwidth;
p07gbar 0:455d5826751b 296 int fifo_levl = fifo_level();
p07gbar 0:455d5826751b 297 while (counter < fifo_levl && len_valid) {
k4zuki 1:89cea1a77092 298 temp[counter] = I2S0_RDR0;
p07gbar 0:455d5826751b 299 for (int j = 0; j < increment; j++) {
p07gbar 0:455d5826751b 300 if ((counter * increment) + j > len) {
p07gbar 0:455d5826751b 301 len_valid = false;
p07gbar 0:455d5826751b 302 break;
p07gbar 0:455d5826751b 303 }
p07gbar 0:455d5826751b 304 buf[counter + j] = temp[counter] >> (j * wordwidth);
p07gbar 0:455d5826751b 305
p07gbar 0:455d5826751b 306 }
p07gbar 0:455d5826751b 307 counter++;
p07gbar 0:455d5826751b 308 }
p07gbar 0:455d5826751b 309 }
p07gbar 0:455d5826751b 310
p07gbar 0:455d5826751b 311 void I2S::read(int bufr[], int bufl[], int len)
p07gbar 0:455d5826751b 312 {
p07gbar 0:455d5826751b 313 //#TODO: Write this
p07gbar 0:455d5826751b 314 }
p07gbar 0:455d5826751b 315
p07gbar 0:455d5826751b 316 int I2S::max_fifo_points()
p07gbar 0:455d5826751b 317 {
p07gbar 0:455d5826751b 318 switch (wordwidth) {
p07gbar 0:455d5826751b 319 case 8:
p07gbar 0:455d5826751b 320 return (4 * 8);
p07gbar 0:455d5826751b 321 case 16:
p07gbar 0:455d5826751b 322 return (2 * 8);
p07gbar 0:455d5826751b 323 case 32:
p07gbar 0:455d5826751b 324 return 8;
p07gbar 0:455d5826751b 325 default:
p07gbar 0:455d5826751b 326 return 0;
p07gbar 0:455d5826751b 327 }
p07gbar 0:455d5826751b 328 }
p07gbar 0:455d5826751b 329
p07gbar 0:455d5826751b 330 int I2S::fifo_points()
p07gbar 0:455d5826751b 331 {
p07gbar 0:455d5826751b 332 switch (wordwidth) {
p07gbar 0:455d5826751b 333 case 8:
p07gbar 0:455d5826751b 334 return (4 * fifo_level());
p07gbar 0:455d5826751b 335 case 16:
p07gbar 0:455d5826751b 336 return (2 * fifo_level());
p07gbar 0:455d5826751b 337 case 32:
p07gbar 0:455d5826751b 338 return fifo_level();
p07gbar 0:455d5826751b 339 default:
p07gbar 0:455d5826751b 340 return 0;
p07gbar 0:455d5826751b 341 }
p07gbar 0:455d5826751b 342 }
p07gbar 0:455d5826751b 343
p07gbar 0:455d5826751b 344 void I2S::power(bool pwr)
p07gbar 0:455d5826751b 345 {
p07gbar 0:455d5826751b 346 if (pwr) {
p07gbar 0:455d5826751b 347 stopped = false;
p07gbar 0:455d5826751b 348 } else {
p07gbar 0:455d5826751b 349 stopped = true;
p07gbar 0:455d5826751b 350 }
p07gbar 0:455d5826751b 351 write_registers();
p07gbar 0:455d5826751b 352 }
p07gbar 0:455d5826751b 353
p07gbar 0:455d5826751b 354 void I2S::masterslave(bool mastermode)
p07gbar 0:455d5826751b 355 {
p07gbar 0:455d5826751b 356 if (mastermode == I2S_MASTER) {
p07gbar 0:455d5826751b 357 master = true;
p07gbar 0:455d5826751b 358 } else {
p07gbar 0:455d5826751b 359 master = false;
p07gbar 0:455d5826751b 360 }
p07gbar 0:455d5826751b 361 write_registers();
p07gbar 0:455d5826751b 362 }
p07gbar 0:455d5826751b 363
p07gbar 0:455d5826751b 364 void I2S::wordsize(int words)
p07gbar 0:455d5826751b 365 {
k4zuki 1:89cea1a77092 366 wordwidth = 16;
p07gbar 0:455d5826751b 367 write_registers();
p07gbar 0:455d5826751b 368 }
p07gbar 0:455d5826751b 369
p07gbar 0:455d5826751b 370 void I2S::mclk_freq(int freq)
p07gbar 0:455d5826751b 371 {
k4zuki 1:89cea1a77092 372 mclk_frequency = 12288000;
p07gbar 0:455d5826751b 373 write_registers();
p07gbar 0:455d5826751b 374 }
p07gbar 0:455d5826751b 375
p07gbar 0:455d5826751b 376 void I2S::frequency(int desired_freq)
p07gbar 0:455d5826751b 377 {
k4zuki 1:89cea1a77092 378 freq = 32000;
k4zuki 1:89cea1a77092 379 _i2s_set_rate(int smprate)
k4zuki 1:89cea1a77092 380 //write_registers();
p07gbar 0:455d5826751b 381 }
p07gbar 0:455d5826751b 382
p07gbar 0:455d5826751b 383 int I2S::fifo_level()
p07gbar 0:455d5826751b 384 {
p07gbar 0:455d5826751b 385 int level = 0;
p07gbar 0:455d5826751b 386 if (_rxtx == I2S_TRANSMIT) {
k4zuki 1:89cea1a77092 387 level = I2S0_TFR0;
p07gbar 0:455d5826751b 388 level >>= 16;
p07gbar 0:455d5826751b 389 level &= 0xF;
p07gbar 0:455d5826751b 390 } else {
k4zuki 1:89cea1a77092 391 level = I2S0_TFR0;
k4zuki 1:89cea1a77092 392 level >>= 0;
p07gbar 0:455d5826751b 393 level &= 0xF;
p07gbar 0:455d5826751b 394 }
p07gbar 0:455d5826751b 395 return level;
p07gbar 0:455d5826751b 396 }
p07gbar 0:455d5826751b 397
p07gbar 0:455d5826751b 398 void I2S::stereomono(bool stereomode)
p07gbar 0:455d5826751b 399 {
k4zuki 1:89cea1a77092 400 stereo = true;
k4zuki 1:89cea1a77092 401 /*
k4zuki 1:89cea1a77092 402 if (stereomode == I2S_STEREO) {
k4zuki 1:89cea1a77092 403 stereo = true;
k4zuki 1:89cea1a77092 404 } else {
k4zuki 1:89cea1a77092 405 stereo = false;
k4zuki 1:89cea1a77092 406 }
k4zuki 1:89cea1a77092 407 */
p07gbar 0:455d5826751b 408 }
p07gbar 0:455d5826751b 409
p07gbar 0:455d5826751b 410 void I2S::mute()
p07gbar 0:455d5826751b 411 {
p07gbar 0:455d5826751b 412 muted = true;
p07gbar 0:455d5826751b 413 write_registers();
p07gbar 0:455d5826751b 414 }
p07gbar 0:455d5826751b 415
p07gbar 0:455d5826751b 416 void I2S::mute(bool mute_en)
p07gbar 0:455d5826751b 417 {
p07gbar 0:455d5826751b 418 muted = mute_en;
p07gbar 0:455d5826751b 419 write_registers();
p07gbar 0:455d5826751b 420 }
p07gbar 0:455d5826751b 421
p07gbar 0:455d5826751b 422 void I2S::stop()
p07gbar 0:455d5826751b 423 {
p07gbar 0:455d5826751b 424 stopped = true;
p07gbar 0:455d5826751b 425 write_registers();
p07gbar 0:455d5826751b 426 }
p07gbar 0:455d5826751b 427
p07gbar 0:455d5826751b 428 void I2S::set_interrupt_fifo_level(int level)
p07gbar 0:455d5826751b 429 {
k4zuki 1:89cea1a77092 430 interrupt_fifo_level = 4;
p07gbar 0:455d5826751b 431 write_registers();
p07gbar 0:455d5826751b 432 }
p07gbar 0:455d5826751b 433
p07gbar 0:455d5826751b 434 void I2S::start()
p07gbar 0:455d5826751b 435 {
p07gbar 0:455d5826751b 436 stopped = false;
p07gbar 0:455d5826751b 437 muted = false;
p07gbar 0:455d5826751b 438 write_registers();
p07gbar 0:455d5826751b 439 }
p07gbar 0:455d5826751b 440
p07gbar 0:455d5826751b 441 bool I2S::setup_ok()
p07gbar 0:455d5826751b 442 {
p07gbar 0:455d5826751b 443 if ((reg_write_err + pin_setup_err) > 0)
p07gbar 0:455d5826751b 444 return false;
p07gbar 0:455d5826751b 445 else
p07gbar 0:455d5826751b 446 return true;
p07gbar 0:455d5826751b 447 }
p07gbar 0:455d5826751b 448
p07gbar 0:455d5826751b 449 void I2S::pin_setup()
p07gbar 0:455d5826751b 450 {
p07gbar 0:455d5826751b 451 pin_setup_err = 0;
p07gbar 0:455d5826751b 452
p07gbar 0:455d5826751b 453 if (_rxtx == I2S_TRANSMIT) {
p07gbar 0:455d5826751b 454 printf("\n\rSetting up pins....\n\r");
k4zuki 1:89cea1a77092 455 if (_sd != PTC1)
p07gbar 0:455d5826751b 456 pin_setup_err++;
k4zuki 1:89cea1a77092 457 if (_ws != PTB19 && ws_d == true)
p07gbar 0:455d5826751b 458 pin_setup_err++;
k4zuki 1:89cea1a77092 459 if (_clk != PTB18 && clk_d == true)
p07gbar 0:455d5826751b 460 pin_setup_err++;
p07gbar 0:455d5826751b 461 printf("Hmm....%i\n\r", pin_setup_err);
p07gbar 0:455d5826751b 462 } else {
k4zuki 1:89cea1a77092 463 if (_sd != PTC5)
p07gbar 0:455d5826751b 464 pin_setup_err++;
k4zuki 1:89cea1a77092 465 if (_ws != PTC7 && ws_d == true)
p07gbar 0:455d5826751b 466 pin_setup_err++;
k4zuki 1:89cea1a77092 467 if (_clk != PTC6 && clk_d == true)
p07gbar 0:455d5826751b 468 pin_setup_err++;
p07gbar 0:455d5826751b 469 }
k4zuki 1:89cea1a77092 470 /*
k4zuki 1:89cea1a77092 471 * @param sd The serial data pin
k4zuki 1:89cea1a77092 472 * @param ws The word select pin
k4zuki 1:89cea1a77092 473 * @param clk The clock pin
k4zuki 1:89cea1a77092 474 PORTC_PCR8 &= PORT_PCR_MUX_MASK;
k4zuki 1:89cea1a77092 475 PORTC_PCR8 |= PORT_PCR_MUX(0x04); // PTC8 I2S0_MCLK
k4zuki 1:89cea1a77092 476
k4zuki 1:89cea1a77092 477 PORTC_PCR5 &= PORT_PCR_MUX_MASK;
k4zuki 1:89cea1a77092 478 PORTC_PCR5 |= PORT_PCR_MUX(0x04); // PTC5 I2S0_RXD0
k4zuki 1:89cea1a77092 479
k4zuki 1:89cea1a77092 480 PORTC_PCR7 &= PORT_PCR_MUX_MASK;
k4zuki 1:89cea1a77092 481 PORTC_PCR7 |= PORT_PCR_MUX(0x04); // PTC7 I2S0_RX_FS
k4zuki 1:89cea1a77092 482
k4zuki 1:89cea1a77092 483 PORTC_PCR6 &= PORT_PCR_MUX_MASK;
k4zuki 1:89cea1a77092 484 PORTC_PCR6 |= PORT_PCR_MUX(0x04); // PTC6 I2S0_RX_BCLK
k4zuki 1:89cea1a77092 485
k4zuki 1:89cea1a77092 486 PORTC_PCR1 &= PORT_PCR_MUX_MASK;
k4zuki 1:89cea1a77092 487 PORTC_PCR1 |= PORT_PCR_MUX(0x04); // PTC1 I2S0_TXD0
k4zuki 1:89cea1a77092 488
k4zuki 1:89cea1a77092 489 PORTB_PCR19 &= PORT_PCR_MUX_MASK;
k4zuki 1:89cea1a77092 490 PORTB_PCR19 |= PORT_PCR_MUX(0x04); // PTB19 I2S0_TX_FS
k4zuki 1:89cea1a77092 491
k4zuki 1:89cea1a77092 492 PORTB_PCR18 &= PORT_PCR_MUX_MASK;
k4zuki 1:89cea1a77092 493 PORTB_PCR18 |= PORT_PCR_MUX(0x04); // PTB18 I2S0_TX_BCLK
k4zuki 1:89cea1a77092 494 */
k4zuki 1:89cea1a77092 495
p07gbar 0:455d5826751b 496
p07gbar 0:455d5826751b 497 if (pin_setup_err == 0) {
p07gbar 0:455d5826751b 498 if (_rxtx == I2S_TRANSMIT) {
p07gbar 0:455d5826751b 499 int val1 = 1;
p07gbar 0:455d5826751b 500 if (deallocating) {
p07gbar 0:455d5826751b 501 val1 = 0;
p07gbar 0:455d5826751b 502 }
k4zuki 1:89cea1a77092 503 PORTC_PCR1 &= PORT_PCR_MUX_MASK;
k4zuki 1:89cea1a77092 504 PORTC_PCR1 |= PORT_PCR_MUX(0x04); // PTC1 I2S0_TXD0
k4zuki 1:89cea1a77092 505 if (ws_d == true) {
k4zuki 1:89cea1a77092 506 PORTB_PCR18 &= PORT_PCR_MUX_MASK;
k4zuki 1:89cea1a77092 507 PORTB_PCR18 |= PORT_PCR_MUX(0x04); // PTB18 I2S0_TX_BCLK
k4zuki 1:89cea1a77092 508 }
k4zuki 1:89cea1a77092 509 if (clk_d == true) {
k4zuki 1:89cea1a77092 510 PORTB_PCR19 &= PORT_PCR_MUX_MASK;
k4zuki 1:89cea1a77092 511 PORTB_PCR19 |= PORT_PCR_MUX(0x04); // PTB19 I2S0_TX_FS
k4zuki 1:89cea1a77092 512 }
p07gbar 0:455d5826751b 513
p07gbar 0:455d5826751b 514 } else {
p07gbar 0:455d5826751b 515 int val1 = 1;
p07gbar 0:455d5826751b 516 int val2 = 2;
p07gbar 0:455d5826751b 517 if (deallocating) {
p07gbar 0:455d5826751b 518 val1 = 0;
p07gbar 0:455d5826751b 519 val2 = 0;
p07gbar 0:455d5826751b 520 }
p07gbar 0:455d5826751b 521
k4zuki 1:89cea1a77092 522 PORTC_PCR5 &= PORT_PCR_MUX_MASK;
k4zuki 1:89cea1a77092 523 PORTC_PCR5 |= PORT_PCR_MUX(0x04); // PTC5 I2S0_RXD0
p07gbar 0:455d5826751b 524
p07gbar 0:455d5826751b 525 if (ws_d == true) {
k4zuki 1:89cea1a77092 526 PORTB_PCR18 &= PORT_PCR_MUX_MASK;
k4zuki 1:89cea1a77092 527 PORTB_PCR18 |= PORT_PCR_MUX(0x04); // PTB18 I2S0_TX_BCLK
p07gbar 0:455d5826751b 528 }
p07gbar 0:455d5826751b 529
p07gbar 0:455d5826751b 530 if (clk_d == true) {
k4zuki 1:89cea1a77092 531 PORTC_PCR6 &= PORT_PCR_MUX_MASK;
k4zuki 1:89cea1a77092 532 PORTC_PCR6 |= PORT_PCR_MUX(0x04); // PTC6 I2S0_RX_BCLK
p07gbar 0:455d5826751b 533 }
p07gbar 0:455d5826751b 534 }
p07gbar 0:455d5826751b 535 }
p07gbar 0:455d5826751b 536 }
p07gbar 0:455d5826751b 537
k4zuki 1:89cea1a77092 538
k4zuki 1:89cea1a77092 539
k4zuki 1:89cea1a77092 540
k4zuki 1:89cea1a77092 541
k4zuki 1:89cea1a77092 542
k4zuki 1:89cea1a77092 543
k4zuki 1:89cea1a77092 544 void I2S::_set_clock_112896(void)
k4zuki 1:89cea1a77092 545 {
k4zuki 1:89cea1a77092 546 SIM_SCGC6 &= ~(SIM_SCGC6_I2S_MASK);
k4zuki 1:89cea1a77092 547
k4zuki 1:89cea1a77092 548 // output = input[(I2SFRAC+1) / (I2SDIV+1) ] = (48* (4/17))
k4zuki 1:89cea1a77092 549 // SIM_CLKDIV2 |= SIM_CLKDIV2_I2SDIV(16) | SIM_CLKDIV2_I2SFRAC(3);
k4zuki 1:89cea1a77092 550 I2S0_MDR = I2S_MDR_FRACT(3) | I2S_MDR_DIVIDE(16);
k4zuki 1:89cea1a77092 551 SIM_SCGC6 |= SIM_SCGC6_I2S_MASK;
k4zuki 1:89cea1a77092 552 }
k4zuki 1:89cea1a77092 553 void I2S::_set_clock_122800(void)
k4zuki 1:89cea1a77092 554 {
k4zuki 1:89cea1a77092 555 // output = input [(I2SFRAC+1) / (I2SDIV+1) ] = (48M* (32/125))
k4zuki 1:89cea1a77092 556 // SIM_CLKDIV2 |= SIM_CLKDIV2_I2SDIV(124) | SIM_CLKDIV2_I2SFRAC(31);
k4zuki 1:89cea1a77092 557 I2S0_MDR = I2S_MDR_FRACT(31) | I2S_MDR_DIVIDE(124);
k4zuki 1:89cea1a77092 558 }
k4zuki 1:89cea1a77092 559 void I2S::_i2s_init(void)
k4zuki 1:89cea1a77092 560 {
k4zuki 1:89cea1a77092 561 #define I2S_CONFIG_WORDS_IN_A_FRAME 2
k4zuki 1:89cea1a77092 562 #define I2S_CONFIG_BITS_IN_A_WORD 16
k4zuki 1:89cea1a77092 563
k4zuki 1:89cea1a77092 564 I2S0_TCR1 = 4;// 6; // water mark
k4zuki 1:89cea1a77092 565 I2S0_TCR2 |= (0<<30) | // master mode(Async mode)
k4zuki 1:89cea1a77092 566 (1<<26) | // MSEL = MCLK
k4zuki 1:89cea1a77092 567 (1<<25) | // CLK = drive on falling edge
k4zuki 1:89cea1a77092 568 (1<<24) ; // CLK = OUTPUT
k4zuki 1:89cea1a77092 569
k4zuki 1:89cea1a77092 570 I2S0_TCR3 = (1<<16); // enable channel 0
k4zuki 1:89cea1a77092 571
k4zuki 1:89cea1a77092 572 I2S0_TCR4 = ((I2S_CONFIG_WORDS_IN_A_FRAME-1)<<16) | // words in a frame
k4zuki 1:89cea1a77092 573 ((I2S_CONFIG_BITS_IN_A_WORD -1)<<8) | // bits in a word
k4zuki 1:89cea1a77092 574 (1<<4) | // MSB
k4zuki 1:89cea1a77092 575 (1<<3) | // one bit early
k4zuki 1:89cea1a77092 576 (1<<1) | // frame active low
k4zuki 1:89cea1a77092 577 (1<<0) ; // frame = output
k4zuki 1:89cea1a77092 578
k4zuki 1:89cea1a77092 579 I2S0_TCR5 = ((I2S_CONFIG_BITS_IN_A_WORD-1) <<24) | // word N width
k4zuki 1:89cea1a77092 580 ((I2S_CONFIG_BITS_IN_A_WORD-1) <<16) | // word 0 width
k4zuki 1:89cea1a77092 581 (0x17<<8); // right adjust, where the first bit starts
k4zuki 1:89cea1a77092 582
k4zuki 1:89cea1a77092 583 I2S0_TMR = 0;
k4zuki 1:89cea1a77092 584
k4zuki 1:89cea1a77092 585 // enable TX
k4zuki 1:89cea1a77092 586 I2S0_TCSR = (0<<31) | // enable tx
k4zuki 1:89cea1a77092 587 (1<<28) | // enable bit clock
k4zuki 1:89cea1a77092 588 (0<<0); // enable DMA request
k4zuki 1:89cea1a77092 589 }
k4zuki 1:89cea1a77092 590
k4zuki 1:89cea1a77092 591 void I2S::_i2s_set_rate(int smprate)
k4zuki 1:89cea1a77092 592 {
k4zuki 1:89cea1a77092 593 unsigned char div;
k4zuki 1:89cea1a77092 594 SIM_SCGC6 |= SIM_SCGC6_I2S_MASK;
k4zuki 1:89cea1a77092 595
k4zuki 1:89cea1a77092 596 // Select MCLK input source
k4zuki 1:89cea1a77092 597 I2S0_MCR = (1<<30)| // MCLK = output
k4zuki 1:89cea1a77092 598 (0<<24); // MCLK SRC = core clock = 48M
k4zuki 1:89cea1a77092 599
k4zuki 1:89cea1a77092 600 if((smprate == 11025)||(smprate == 22050)||(smprate == 44100)) {
k4zuki 1:89cea1a77092 601 _set_clock_112896();
k4zuki 1:89cea1a77092 602 mclk_frequency = 11289600;
k4zuki 1:89cea1a77092 603 }
k4zuki 1:89cea1a77092 604
k4zuki 1:89cea1a77092 605 if((smprate == 8000) || (smprate == 12000) || (smprate == 16000) ||
k4zuki 1:89cea1a77092 606 (smprate == 24000)|| (smprate == 32000) || (smprate == 48000) ) {
k4zuki 1:89cea1a77092 607 _set_clock_122800();
k4zuki 1:89cea1a77092 608 mclk_frequency = 12288000;
k4zuki 1:89cea1a77092 609 }
k4zuki 1:89cea1a77092 610
k4zuki 1:89cea1a77092 611 switch(smprate) {
k4zuki 1:89cea1a77092 612 case 32000:
k4zuki 1:89cea1a77092 613 div=3;
k4zuki 1:89cea1a77092 614 break; // 12.288M/(32K*48) = 8, 8 = (DIV+1)*2, DIV = 3
k4zuki 1:89cea1a77092 615 }
k4zuki 1:89cea1a77092 616
k4zuki 1:89cea1a77092 617 I2S0_TCR2 = div;
k4zuki 1:89cea1a77092 618 }
k4zuki 1:89cea1a77092 619
k4zuki 1:89cea1a77092 620
k4zuki 1:89cea1a77092 621
k4zuki 1:89cea1a77092 622
k4zuki 1:89cea1a77092 623
k4zuki 1:89cea1a77092 624
k4zuki 1:89cea1a77092 625
k4zuki 1:89cea1a77092 626
k4zuki 1:89cea1a77092 627
k4zuki 1:89cea1a77092 628
p07gbar 0:455d5826751b 629 void I2S::write_registers()
p07gbar 0:455d5826751b 630 {
p07gbar 0:455d5826751b 631 reg_write_err = 0;
p07gbar 0:455d5826751b 632 //Clock Multiplier Calculations
p07gbar 0:455d5826751b 633 float pre_mult = 0;
p07gbar 0:455d5826751b 634 int pre_num = 0;
p07gbar 0:455d5826751b 635 int pre_den = 0;
p07gbar 0:455d5826751b 636 int bitrate_div = 0;
p07gbar 0:455d5826751b 637 if (master == true) { // In the hope of not doing all this heavy lifting every configuration
p07gbar 0:455d5826751b 638 //printf("Doing some clock magic..\n\r");
p07gbar 0:455d5826751b 639 int bitrate = freq * 64;
p07gbar 0:455d5826751b 640 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 641 if (mclk_frequency == 0) {
p07gbar 0:455d5826751b 642 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 643 bitrate_div = int(target_div - rnd);
p07gbar 0:455d5826751b 644 while (bitrate_div > I2S_MAX_BITRATE_DIV) { // But this might be out of range, so we right shift it into focus
p07gbar 0:455d5826751b 645 bitrate_div >>= 1;
p07gbar 0:455d5826751b 646 }
p07gbar 0:455d5826751b 647 if (bitrate_div == 0) { // Could be zero, which would disable the the clock...
p07gbar 0:455d5826751b 648 bitrate_div = 1;
p07gbar 0:455d5826751b 649 }
p07gbar 0:455d5826751b 650 pre_mult = float(bitrate_div) / target_div; // Work out what we have left to correct
p07gbar 0:455d5826751b 651 pre_num = 0;
p07gbar 0:455d5826751b 652 pre_den = 0;
p07gbar 0:455d5826751b 653 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 654
p07gbar 0:455d5826751b 655 } else {
p07gbar 0:455d5826751b 656 pre_mult = float(mclk_frequency * 2) / (I2S_PCLK_RATE);
p07gbar 0:455d5826751b 657 pre_num = 0;
p07gbar 0:455d5826751b 658 pre_den = 0;
p07gbar 0:455d5826751b 659 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 660 bitrate_div = int(
p07gbar 0:455d5826751b 661 I2S_PCLK_RATE * float(pre_num) / float(pre_den)
p07gbar 0:455d5826751b 662 / float(bitrate));
p07gbar 0:455d5826751b 663 }
p07gbar 0:455d5826751b 664
p07gbar 0:455d5826751b 665 old_freq = freq;
p07gbar 0:455d5826751b 666 old_pre_num = pre_num;
p07gbar 0:455d5826751b 667 old_pre_den = pre_den;
p07gbar 0:455d5826751b 668 old_bitrate_div = bitrate_div;
p07gbar 0:455d5826751b 669 } else {
p07gbar 0:455d5826751b 670 pre_num = old_pre_num;
p07gbar 0:455d5826751b 671 pre_den = old_pre_den;
p07gbar 0:455d5826751b 672 bitrate_div = old_bitrate_div;
p07gbar 0:455d5826751b 673 }
p07gbar 0:455d5826751b 674
p07gbar 0:455d5826751b 675 //Clock Multiplier, MCLK setup
p07gbar 0:455d5826751b 676 if (_rxtx == I2S_TRANSMIT) {
p07gbar 0:455d5826751b 677 int regvals = ((pre_num << 8) & 0xFF00) | (pre_den & 0xFF);
p07gbar 0:455d5826751b 678 LPC_I2S->I2STXRATE = regvals; // Setting the X/Y fraction
p07gbar 0:455d5826751b 679 LPC_I2S->I2STXBITRATE = (bitrate_div - 1) & 0x3F;// Setting up the bitrate divider, the periferal adds one to this
p07gbar 0:455d5826751b 680
p07gbar 0:455d5826751b 681 LPC_I2S->I2STXMODE = fourwire << 2;
p07gbar 0:455d5826751b 682
p07gbar 0:455d5826751b 683 if (mclk_d == true) {
p07gbar 0:455d5826751b 684 LPC_I2S->I2STXMODE |= (1 << 3);
p07gbar 0:455d5826751b 685 }
p07gbar 0:455d5826751b 686 } else {
p07gbar 0:455d5826751b 687 int regvals = ((pre_num << 8) & 0xFF00) | (pre_den & 0xFF);
p07gbar 0:455d5826751b 688 LPC_I2S->I2SRXRATE = regvals; // Setting the X/Y fraction
p07gbar 0:455d5826751b 689 LPC_I2S->I2SRXBITRATE = (bitrate_div - 1) & 0x3F;// Setting up the bitrate divider, the periferal adds one to this
p07gbar 0:455d5826751b 690
p07gbar 0:455d5826751b 691 LPC_I2S->I2SRXMODE = fourwire << 2;
p07gbar 0:455d5826751b 692
p07gbar 0:455d5826751b 693 if (mclk_d == true) {
p07gbar 0:455d5826751b 694 LPC_I2S->I2SRXMODE |= (1 << 3);
p07gbar 0:455d5826751b 695 }
p07gbar 0:455d5826751b 696 }
p07gbar 0:455d5826751b 697
p07gbar 0:455d5826751b 698 switch (wordwidth) {
p07gbar 0:455d5826751b 699 case 8:
p07gbar 0:455d5826751b 700 wordwidth_code = 0;
p07gbar 0:455d5826751b 701 break;
p07gbar 0:455d5826751b 702 case 16:
p07gbar 0:455d5826751b 703 wordwidth_code = 1;
p07gbar 0:455d5826751b 704 break;
p07gbar 0:455d5826751b 705 case 32:
p07gbar 0:455d5826751b 706 wordwidth_code = 3;
p07gbar 0:455d5826751b 707 break;
p07gbar 0:455d5826751b 708 default:
p07gbar 0:455d5826751b 709 reg_write_err++;
p07gbar 0:455d5826751b 710 break;
p07gbar 0:455d5826751b 711 }
p07gbar 0:455d5826751b 712
p07gbar 0:455d5826751b 713 int I2SDA_reg = (wordwidth_code & 0x3);
p07gbar 0:455d5826751b 714 I2SDA_reg |= ((!stereo << 2) & 0x4);
p07gbar 0:455d5826751b 715 I2SDA_reg |= ((stopped << 3) & 0x8);
p07gbar 0:455d5826751b 716 I2SDA_reg |= ((!master << 5) & 0x20);
p07gbar 0:455d5826751b 717 I2SDA_reg |= (0x1F << 6);
p07gbar 0:455d5826751b 718 I2SDA_reg |= ((muted << 15) & 0x8000);
p07gbar 0:455d5826751b 719
p07gbar 0:455d5826751b 720 if (_rxtx == I2S_TRANSMIT) {
p07gbar 0:455d5826751b 721 LPC_I2S->I2SDAO = I2SDA_reg;
p07gbar 0:455d5826751b 722 } else {
p07gbar 0:455d5826751b 723 LPC_I2S->I2SDAI = I2SDA_reg;
p07gbar 0:455d5826751b 724 }
p07gbar 0:455d5826751b 725
p07gbar 0:455d5826751b 726 if (_rxtx == I2S_TRANSMIT) {
p07gbar 0:455d5826751b 727 if (txisr) {
p07gbar 0:455d5826751b 728 LPC_I2S->I2SIRQ = (LPC_I2S->I2SIRQ & 0xFF0FFFFF)
p07gbar 0:455d5826751b 729 | ((interrupt_fifo_level & 0xF) << 16);
p07gbar 0:455d5826751b 730 LPC_I2S->I2SIRQ |= 0x2;
p07gbar 0:455d5826751b 731 } else {
p07gbar 0:455d5826751b 732 LPC_I2S->I2SIRQ &= 0xFFFFFFFD;
p07gbar 0:455d5826751b 733 }
p07gbar 0:455d5826751b 734 } else {
p07gbar 0:455d5826751b 735 if (rxisr) {
p07gbar 0:455d5826751b 736 LPC_I2S->I2SIRQ = (LPC_I2S->I2SIRQ & 0xFFFFF0FF)
p07gbar 0:455d5826751b 737 | ((interrupt_fifo_level & 0xF) << 8);
p07gbar 0:455d5826751b 738 LPC_I2S->I2SIRQ |= 0x1;
p07gbar 0:455d5826751b 739 }
p07gbar 0:455d5826751b 740
p07gbar 0:455d5826751b 741 else {
p07gbar 0:455d5826751b 742 LPC_I2S->I2SIRQ &= 0xFFFFFFFE;
p07gbar 0:455d5826751b 743 }
p07gbar 0:455d5826751b 744 }
p07gbar 0:455d5826751b 745 }
p07gbar 0:455d5826751b 746
p07gbar 0:455d5826751b 747 void I2S::_i2sisr(void)
p07gbar 0:455d5826751b 748 {
p07gbar 0:455d5826751b 749 I2STXISR.call();
p07gbar 0:455d5826751b 750 I2SRXISR.call();
p07gbar 0:455d5826751b 751 }
p07gbar 0:455d5826751b 752
p07gbar 0:455d5826751b 753 // A function to find the nearest fraction to that put to it, with numerator and denomnator less than 256
p07gbar 0:455d5826751b 754 // This is used when trying to get the clocks correct
p07gbar 0:455d5826751b 755
p07gbar 0:455d5826751b 756 void I2S::fraction_estimator(float in, int * num, int * den)
p07gbar 0:455d5826751b 757 {
p07gbar 0:455d5826751b 758 int test_num = 0;
p07gbar 0:455d5826751b 759 int test_den = 0;
p07gbar 0:455d5826751b 760 float least_error = 1;
p07gbar 0:455d5826751b 761 int least_err_den = 0;
p07gbar 0:455d5826751b 762 float genval;
p07gbar 0:455d5826751b 763 float generr;
p07gbar 0:455d5826751b 764
p07gbar 0:455d5826751b 765 for (test_den = 1; test_den < I2S_MAX_DENOMINATOR; test_den++) {
p07gbar 0:455d5826751b 766 test_num = int(float(test_den) * in);
p07gbar 0:455d5826751b 767 if (test_num < I2S_MAX_NUMERATOR && test_num > 0) {
p07gbar 0:455d5826751b 768 genval = float(test_num) / float(test_den);
p07gbar 0:455d5826751b 769 generr = mod(genval - in);
p07gbar 0:455d5826751b 770 if (generr < least_error) {
p07gbar 0:455d5826751b 771 least_error = generr;
p07gbar 0:455d5826751b 772 least_err_den = test_den;
p07gbar 0:455d5826751b 773 }
p07gbar 0:455d5826751b 774 if (generr == 0) {
p07gbar 0:455d5826751b 775 break;
p07gbar 0:455d5826751b 776 }
p07gbar 0:455d5826751b 777 }
p07gbar 0:455d5826751b 778 }
p07gbar 0:455d5826751b 779
p07gbar 0:455d5826751b 780 test_num = int(float(least_err_den) * in);
p07gbar 0:455d5826751b 781 *num = test_num;
p07gbar 0:455d5826751b 782 *den = least_err_den;
p07gbar 0:455d5826751b 783
p07gbar 0:455d5826751b 784 }
p07gbar 0:455d5826751b 785
p07gbar 0:455d5826751b 786 float I2S::mod(float in)
p07gbar 0:455d5826751b 787 {
p07gbar 0:455d5826751b 788 if (in < 0)
p07gbar 0:455d5826751b 789 in *= -1;
p07gbar 0:455d5826751b 790
p07gbar 0:455d5826751b 791 return in;
p07gbar 0:455d5826751b 792 }