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

Fork of I2S by Giles Barton-Owen

Committer:
k4zuki
Date:
Tue Mar 29 09:07:43 2016 +0000
Revision:
10:94430ea76fc4
Parent:
9:c045309c3929
merge

Who changed what in which revision?

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