[ FORK ] I2S library for FRDM 64F, forked from p07gbar/I2S
Fork of I2S by
I2S.cpp@9:c045309c3929, 2016-03-29 (annotated)
- Committer:
- k4zuki
- Date:
- Tue Mar 29 09:04:14 2016 +0000
- Revision:
- 9:c045309c3929
- Parent:
- 7:3ebbee7aa339
set MCLK generator to match 120MHz case
Who changed what in which revision?
User | Revision | Line number | New 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 | //} |