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

Fork of I2S by Giles Barton-Owen

Committer:
k4zuki
Date:
Fri Mar 25 22:58:26 2016 +0900
Revision:
6:809d5af4a4c2
Parent:
5:d2062a747673
Child:
7:3ebbee7aa339
internal register access seems back on line

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