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

Fork of I2S by Giles Barton-Owen

Committer:
K4zuki
Date:
Thu Mar 24 01:47:36 2016 +0900
Revision:
4:19e26fafc029
Parent:
3:5bb7f0625fc9
Child:
5:d2062a747673
fix typo(wrong word conversion)

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