WavPlayer.h changed to circuit board
Dependents: WavPlayerSD WavPlayerUSB WavPlayerUSB WavPlayerSD_CB
I2S/I2S.cpp@1:3eb96771bbee, 2012-09-19 (annotated)
- Committer:
- p07gbar
- Date:
- Wed Sep 19 11:05:12 2012 +0000
- Revision:
- 1:3eb96771bbee
- Child:
- 4:b0186c8dca92
Working - Making it easier to publish
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
p07gbar | 1:3eb96771bbee | 1 | #include "I2S.h" |
p07gbar | 1:3eb96771bbee | 2 | |
p07gbar | 1:3eb96771bbee | 3 | #define I2S_DF_WORDWIDTH 16 |
p07gbar | 1:3eb96771bbee | 4 | #define I2S_DF_SAMPLERATE 32000 |
p07gbar | 1:3eb96771bbee | 5 | #define I2S_DF_MASTERSLAVE I2S_SLAVE |
p07gbar | 1:3eb96771bbee | 6 | #define I2S_DF_STEREOMONO I2S_STEREO |
p07gbar | 1:3eb96771bbee | 7 | #define I2S_DF_MUTED I2S_UNMUTED |
p07gbar | 1:3eb96771bbee | 8 | #define I2S_DF_INTERRUPT_FIFO_LEVEL 4 |
p07gbar | 1:3eb96771bbee | 9 | |
p07gbar | 1:3eb96771bbee | 10 | #define I2S_MAX_DENOMINATOR 256 |
p07gbar | 1:3eb96771bbee | 11 | #define I2S_MAX_NUMERATOR 256 |
p07gbar | 1:3eb96771bbee | 12 | #define I2S_MAX_BITRATE_DIV 64 |
p07gbar | 1:3eb96771bbee | 13 | |
p07gbar | 1:3eb96771bbee | 14 | #define I2S_PCLK_RATE 24000000 |
p07gbar | 1:3eb96771bbee | 15 | |
p07gbar | 1:3eb96771bbee | 16 | FunctionPointer I2S::I2STXISR; |
p07gbar | 1:3eb96771bbee | 17 | FunctionPointer I2S::I2SRXISR; |
p07gbar | 1:3eb96771bbee | 18 | |
p07gbar | 1:3eb96771bbee | 19 | bool I2S::txisr; |
p07gbar | 1:3eb96771bbee | 20 | bool I2S::rxisr; |
p07gbar | 1:3eb96771bbee | 21 | |
p07gbar | 1:3eb96771bbee | 22 | I2S::I2S(bool rxtx, PinName sd, PinName ws, PinName clk) |
p07gbar | 1:3eb96771bbee | 23 | { |
p07gbar | 1:3eb96771bbee | 24 | NVIC_DisableIRQ (I2S_IRQn); |
p07gbar | 1:3eb96771bbee | 25 | |
p07gbar | 1:3eb96771bbee | 26 | _sd = sd; |
p07gbar | 1:3eb96771bbee | 27 | _ws = ws; |
p07gbar | 1:3eb96771bbee | 28 | _clk = clk; |
p07gbar | 1:3eb96771bbee | 29 | _rxtx = rxtx; |
p07gbar | 1:3eb96771bbee | 30 | |
p07gbar | 1:3eb96771bbee | 31 | ws_d = true; |
p07gbar | 1:3eb96771bbee | 32 | clk_d = true; |
p07gbar | 1:3eb96771bbee | 33 | mclk_d = false; |
p07gbar | 1:3eb96771bbee | 34 | |
p07gbar | 1:3eb96771bbee | 35 | fourwire = false; |
p07gbar | 1:3eb96771bbee | 36 | |
p07gbar | 1:3eb96771bbee | 37 | reg_write_err = 0; |
p07gbar | 1:3eb96771bbee | 38 | |
p07gbar | 1:3eb96771bbee | 39 | pin_setup(); |
p07gbar | 1:3eb96771bbee | 40 | |
p07gbar | 1:3eb96771bbee | 41 | if (pin_setup_err != 0) { |
p07gbar | 1:3eb96771bbee | 42 | perror("I2S Pins incorrectly defined."); |
p07gbar | 1:3eb96771bbee | 43 | } |
p07gbar | 1:3eb96771bbee | 44 | |
p07gbar | 1:3eb96771bbee | 45 | defaulter(); |
p07gbar | 1:3eb96771bbee | 46 | } |
p07gbar | 1:3eb96771bbee | 47 | |
p07gbar | 1:3eb96771bbee | 48 | I2S::I2S(bool rxtx, PinName sd) |
p07gbar | 1:3eb96771bbee | 49 | { |
p07gbar | 1:3eb96771bbee | 50 | NVIC_DisableIRQ (I2S_IRQn); |
p07gbar | 1:3eb96771bbee | 51 | |
p07gbar | 1:3eb96771bbee | 52 | _sd = sd; |
p07gbar | 1:3eb96771bbee | 53 | _rxtx = rxtx; |
p07gbar | 1:3eb96771bbee | 54 | |
p07gbar | 1:3eb96771bbee | 55 | ws_d = false; |
p07gbar | 1:3eb96771bbee | 56 | clk_d = false; |
p07gbar | 1:3eb96771bbee | 57 | mclk_d = false; |
p07gbar | 1:3eb96771bbee | 58 | |
p07gbar | 1:3eb96771bbee | 59 | fourwire = false; |
p07gbar | 1:3eb96771bbee | 60 | |
p07gbar | 1:3eb96771bbee | 61 | reg_write_err = 0; |
p07gbar | 1:3eb96771bbee | 62 | |
p07gbar | 1:3eb96771bbee | 63 | pin_setup(); |
p07gbar | 1:3eb96771bbee | 64 | |
p07gbar | 1:3eb96771bbee | 65 | if (pin_setup_err != 0) { |
p07gbar | 1:3eb96771bbee | 66 | perror("I2S Pins incorrectly defined."); |
p07gbar | 1:3eb96771bbee | 67 | } |
p07gbar | 1:3eb96771bbee | 68 | |
p07gbar | 1:3eb96771bbee | 69 | defaulter(); |
p07gbar | 1:3eb96771bbee | 70 | } |
p07gbar | 1:3eb96771bbee | 71 | |
p07gbar | 1:3eb96771bbee | 72 | I2S::I2S(bool rxtx, PinName sd, bool fourwiremode) |
p07gbar | 1:3eb96771bbee | 73 | { |
p07gbar | 1:3eb96771bbee | 74 | NVIC_DisableIRQ (I2S_IRQn); |
p07gbar | 1:3eb96771bbee | 75 | |
p07gbar | 1:3eb96771bbee | 76 | _sd = sd; |
p07gbar | 1:3eb96771bbee | 77 | _rxtx = rxtx; |
p07gbar | 1:3eb96771bbee | 78 | |
p07gbar | 1:3eb96771bbee | 79 | ws_d = false; |
p07gbar | 1:3eb96771bbee | 80 | clk_d = false; |
p07gbar | 1:3eb96771bbee | 81 | mclk_d = false; |
p07gbar | 1:3eb96771bbee | 82 | |
p07gbar | 1:3eb96771bbee | 83 | reg_write_err = 0; |
p07gbar | 1:3eb96771bbee | 84 | |
p07gbar | 1:3eb96771bbee | 85 | fourwire = fourwiremode; |
p07gbar | 1:3eb96771bbee | 86 | |
p07gbar | 1:3eb96771bbee | 87 | pin_setup(); |
p07gbar | 1:3eb96771bbee | 88 | |
p07gbar | 1:3eb96771bbee | 89 | if (pin_setup_err != 0) { |
p07gbar | 1:3eb96771bbee | 90 | perror("I2S Pins incorrectly defined."); |
p07gbar | 1:3eb96771bbee | 91 | } |
p07gbar | 1:3eb96771bbee | 92 | |
p07gbar | 1:3eb96771bbee | 93 | defaulter(); |
p07gbar | 1:3eb96771bbee | 94 | } |
p07gbar | 1:3eb96771bbee | 95 | |
p07gbar | 1:3eb96771bbee | 96 | I2S::I2S(bool rxtx, PinName sd, PinName ws, bool fourwiremode) |
p07gbar | 1:3eb96771bbee | 97 | { |
p07gbar | 1:3eb96771bbee | 98 | NVIC_DisableIRQ (I2S_IRQn); |
p07gbar | 1:3eb96771bbee | 99 | |
p07gbar | 1:3eb96771bbee | 100 | _sd = sd; |
p07gbar | 1:3eb96771bbee | 101 | _ws = ws; |
p07gbar | 1:3eb96771bbee | 102 | _rxtx = rxtx; |
p07gbar | 1:3eb96771bbee | 103 | |
p07gbar | 1:3eb96771bbee | 104 | ws_d = true; |
p07gbar | 1:3eb96771bbee | 105 | clk_d = false; |
p07gbar | 1:3eb96771bbee | 106 | mclk_d = false; |
p07gbar | 1:3eb96771bbee | 107 | |
p07gbar | 1:3eb96771bbee | 108 | reg_write_err = 0; |
p07gbar | 1:3eb96771bbee | 109 | |
p07gbar | 1:3eb96771bbee | 110 | fourwire = fourwiremode; |
p07gbar | 1:3eb96771bbee | 111 | |
p07gbar | 1:3eb96771bbee | 112 | pin_setup(); |
p07gbar | 1:3eb96771bbee | 113 | |
p07gbar | 1:3eb96771bbee | 114 | if (pin_setup_err != 0) { |
p07gbar | 1:3eb96771bbee | 115 | perror("I2S Pins incorrectly defined."); |
p07gbar | 1:3eb96771bbee | 116 | } |
p07gbar | 1:3eb96771bbee | 117 | |
p07gbar | 1:3eb96771bbee | 118 | defaulter(); |
p07gbar | 1:3eb96771bbee | 119 | } |
p07gbar | 1:3eb96771bbee | 120 | |
p07gbar | 1:3eb96771bbee | 121 | I2S::I2S(bool rxtx, PinName sd, PinName ws) |
p07gbar | 1:3eb96771bbee | 122 | { |
p07gbar | 1:3eb96771bbee | 123 | NVIC_DisableIRQ (I2S_IRQn); |
p07gbar | 1:3eb96771bbee | 124 | |
p07gbar | 1:3eb96771bbee | 125 | _sd = sd; |
p07gbar | 1:3eb96771bbee | 126 | _ws = ws; |
p07gbar | 1:3eb96771bbee | 127 | _rxtx = rxtx; |
p07gbar | 1:3eb96771bbee | 128 | |
p07gbar | 1:3eb96771bbee | 129 | ws_d = true; |
p07gbar | 1:3eb96771bbee | 130 | clk_d = false; |
p07gbar | 1:3eb96771bbee | 131 | mclk_d = false; |
p07gbar | 1:3eb96771bbee | 132 | |
p07gbar | 1:3eb96771bbee | 133 | reg_write_err = 0; |
p07gbar | 1:3eb96771bbee | 134 | |
p07gbar | 1:3eb96771bbee | 135 | fourwire = false; |
p07gbar | 1:3eb96771bbee | 136 | |
p07gbar | 1:3eb96771bbee | 137 | pin_setup(); |
p07gbar | 1:3eb96771bbee | 138 | |
p07gbar | 1:3eb96771bbee | 139 | if (pin_setup_err != 0) { |
p07gbar | 1:3eb96771bbee | 140 | perror("I2S Pins incorrectly defined."); |
p07gbar | 1:3eb96771bbee | 141 | } |
p07gbar | 1:3eb96771bbee | 142 | |
p07gbar | 1:3eb96771bbee | 143 | defaulter(); |
p07gbar | 1:3eb96771bbee | 144 | } |
p07gbar | 1:3eb96771bbee | 145 | |
p07gbar | 1:3eb96771bbee | 146 | I2S::~I2S() |
p07gbar | 1:3eb96771bbee | 147 | { |
p07gbar | 1:3eb96771bbee | 148 | NVIC_DisableIRQ (I2S_IRQn); |
p07gbar | 1:3eb96771bbee | 149 | deallocating = true; |
p07gbar | 1:3eb96771bbee | 150 | pin_setup(); |
p07gbar | 1:3eb96771bbee | 151 | write_registers(); |
p07gbar | 1:3eb96771bbee | 152 | } |
p07gbar | 1:3eb96771bbee | 153 | |
p07gbar | 1:3eb96771bbee | 154 | void I2S::defaulter() |
p07gbar | 1:3eb96771bbee | 155 | { |
p07gbar | 1:3eb96771bbee | 156 | LPC_SC->PCONP |= (1 << 27); |
p07gbar | 1:3eb96771bbee | 157 | |
p07gbar | 1:3eb96771bbee | 158 | stop(); |
p07gbar | 1:3eb96771bbee | 159 | master = false; |
p07gbar | 1:3eb96771bbee | 160 | deallocating = false; |
p07gbar | 1:3eb96771bbee | 161 | |
p07gbar | 1:3eb96771bbee | 162 | frequency(I2S_DF_SAMPLERATE); |
p07gbar | 1:3eb96771bbee | 163 | wordsize(I2S_DF_WORDWIDTH); |
p07gbar | 1:3eb96771bbee | 164 | masterslave (I2S_DF_MASTERSLAVE); |
p07gbar | 1:3eb96771bbee | 165 | stereomono (I2S_DF_STEREOMONO); |
p07gbar | 1:3eb96771bbee | 166 | set_interrupt_fifo_level(I2S_DF_INTERRUPT_FIFO_LEVEL); |
p07gbar | 1:3eb96771bbee | 167 | mute (I2S_DF_MUTED); |
p07gbar | 1:3eb96771bbee | 168 | |
p07gbar | 1:3eb96771bbee | 169 | NVIC_SetVector(I2S_IRQn, (uint32_t) & _i2sisr); |
p07gbar | 1:3eb96771bbee | 170 | NVIC_EnableIRQ (I2S_IRQn); |
p07gbar | 1:3eb96771bbee | 171 | } |
p07gbar | 1:3eb96771bbee | 172 | |
p07gbar | 1:3eb96771bbee | 173 | void I2S::write(char buf[], int len) |
p07gbar | 1:3eb96771bbee | 174 | { |
p07gbar | 1:3eb96771bbee | 175 | if (_rxtx == I2S_TRANSMIT) { |
p07gbar | 1:3eb96771bbee | 176 | if (len > max_fifo_points()) |
p07gbar | 1:3eb96771bbee | 177 | len = max_fifo_points(); |
p07gbar | 1:3eb96771bbee | 178 | if (len <= 0) |
p07gbar | 1:3eb96771bbee | 179 | return; |
p07gbar | 1:3eb96771bbee | 180 | int temp = 0; |
p07gbar | 1:3eb96771bbee | 181 | for (int i = 0; i < len; i += 4) { |
p07gbar | 1:3eb96771bbee | 182 | temp = 0; |
p07gbar | 1:3eb96771bbee | 183 | for (int j = 0; j < 4; j++) { |
p07gbar | 1:3eb96771bbee | 184 | temp |= int(buf[i + j]) << (j * 8); |
p07gbar | 1:3eb96771bbee | 185 | } |
p07gbar | 1:3eb96771bbee | 186 | LPC_I2S->I2STXFIFO = temp; |
p07gbar | 1:3eb96771bbee | 187 | } |
p07gbar | 1:3eb96771bbee | 188 | } |
p07gbar | 1:3eb96771bbee | 189 | |
p07gbar | 1:3eb96771bbee | 190 | } |
p07gbar | 1:3eb96771bbee | 191 | |
p07gbar | 1:3eb96771bbee | 192 | void I2S::write(int buf[], int len) |
p07gbar | 1:3eb96771bbee | 193 | { |
p07gbar | 1:3eb96771bbee | 194 | if (_rxtx == I2S_TRANSMIT && wordwidth > 0) { |
p07gbar | 1:3eb96771bbee | 195 | if (len > max_fifo_points()) { |
p07gbar | 1:3eb96771bbee | 196 | len = max_fifo_points(); |
p07gbar | 1:3eb96771bbee | 197 | printf("Trying to write too much data!\n\r"); |
p07gbar | 1:3eb96771bbee | 198 | } |
p07gbar | 1:3eb96771bbee | 199 | if (len <= 0) |
p07gbar | 1:3eb96771bbee | 200 | return; |
p07gbar | 1:3eb96771bbee | 201 | uint32_t temp = 0; |
p07gbar | 1:3eb96771bbee | 202 | int increment = 32 / wordwidth; |
p07gbar | 1:3eb96771bbee | 203 | unsigned char recast[] = |
p07gbar | 1:3eb96771bbee | 204 | { 0, 0, 0, 0 }; |
p07gbar | 1:3eb96771bbee | 205 | for (int i = 0; i < len; i += increment) { |
p07gbar | 1:3eb96771bbee | 206 | temp = 0; |
p07gbar | 1:3eb96771bbee | 207 | |
p07gbar | 1:3eb96771bbee | 208 | switch (wordwidth) { |
p07gbar | 1:3eb96771bbee | 209 | |
p07gbar | 1:3eb96771bbee | 210 | case 8: |
p07gbar | 1:3eb96771bbee | 211 | |
p07gbar | 1:3eb96771bbee | 212 | recast[0] = (int8_t) buf[i + 0]; |
p07gbar | 1:3eb96771bbee | 213 | recast[1] = (int8_t) buf[i + 1]; |
p07gbar | 1:3eb96771bbee | 214 | recast[2] = (int8_t) buf[i + 2]; |
p07gbar | 1:3eb96771bbee | 215 | recast[3] = (int8_t) buf[i + 3]; |
p07gbar | 1:3eb96771bbee | 216 | break; |
p07gbar | 1:3eb96771bbee | 217 | case 16: |
p07gbar | 1:3eb96771bbee | 218 | recast[0] = (((int16_t) buf[i + 0]) >> 0) & 0xFF; |
p07gbar | 1:3eb96771bbee | 219 | recast[1] = (((int16_t) buf[i + 0]) >> 8) & 0xFF; |
p07gbar | 1:3eb96771bbee | 220 | recast[2] = (((int16_t) buf[i + 1]) >> 0) & 0xFF; |
p07gbar | 1:3eb96771bbee | 221 | recast[3] = (((int16_t) buf[i + 1]) >> 8) & 0xFF; |
p07gbar | 1:3eb96771bbee | 222 | break; |
p07gbar | 1:3eb96771bbee | 223 | case 32: |
p07gbar | 1:3eb96771bbee | 224 | recast[0] = (((int32_t) buf[i + 0]) >> 0) & 0xFF; |
p07gbar | 1:3eb96771bbee | 225 | recast[1] = (((int32_t) buf[i + 0]) >> 8) & 0xFF; |
p07gbar | 1:3eb96771bbee | 226 | recast[2] = (((int32_t) buf[i + 0]) >> 16) & 0xFF; |
p07gbar | 1:3eb96771bbee | 227 | recast[3] = (((int32_t) buf[i + 0]) >> 24) & 0xFF; |
p07gbar | 1:3eb96771bbee | 228 | break; |
p07gbar | 1:3eb96771bbee | 229 | |
p07gbar | 1:3eb96771bbee | 230 | } |
p07gbar | 1:3eb96771bbee | 231 | for (int j = 0; j < 4; j++) { |
p07gbar | 1:3eb96771bbee | 232 | |
p07gbar | 1:3eb96771bbee | 233 | temp |= recast[j] << (j * 8); |
p07gbar | 1:3eb96771bbee | 234 | } |
p07gbar | 1:3eb96771bbee | 235 | |
p07gbar | 1:3eb96771bbee | 236 | //if(((temp >> 16) & 0xFFFF) == 0xFFFF) printf("Hmmm %x %x %x\n\r",temp, increment,i); //|| temp &0xFFFF == 0xFFFF |
p07gbar | 1:3eb96771bbee | 237 | //if((buf[i]-buf[i+1])>5000 || (buf[i]-buf[i+1])<-5000) printf("J:%i,%i\n\r",buf[i],buf[i+1]); |
p07gbar | 1:3eb96771bbee | 238 | //printf("%x\n",temp); |
p07gbar | 1:3eb96771bbee | 239 | LPC_I2S->I2STXFIFO = temp; |
p07gbar | 1:3eb96771bbee | 240 | } |
p07gbar | 1:3eb96771bbee | 241 | } |
p07gbar | 1:3eb96771bbee | 242 | } |
p07gbar | 1:3eb96771bbee | 243 | |
p07gbar | 1:3eb96771bbee | 244 | void I2S::write(int bufr[], int bufl[], int len) |
p07gbar | 1:3eb96771bbee | 245 | { |
p07gbar | 1:3eb96771bbee | 246 | //#TODO: Write this! |
p07gbar | 1:3eb96771bbee | 247 | } |
p07gbar | 1:3eb96771bbee | 248 | |
p07gbar | 1:3eb96771bbee | 249 | int I2S::read() |
p07gbar | 1:3eb96771bbee | 250 | { |
p07gbar | 1:3eb96771bbee | 251 | return LPC_I2S->I2SRXFIFO; |
p07gbar | 1:3eb96771bbee | 252 | } |
p07gbar | 1:3eb96771bbee | 253 | |
p07gbar | 1:3eb96771bbee | 254 | void I2S::read(char buf[], int len) |
p07gbar | 1:3eb96771bbee | 255 | { |
p07gbar | 1:3eb96771bbee | 256 | bool len_valid = true; |
p07gbar | 1:3eb96771bbee | 257 | if (len <= 0) |
p07gbar | 1:3eb96771bbee | 258 | return; |
p07gbar | 1:3eb96771bbee | 259 | if (len >= fifo_points()) |
p07gbar | 1:3eb96771bbee | 260 | len = fifo_points(); |
p07gbar | 1:3eb96771bbee | 261 | int temp[8]; |
p07gbar | 1:3eb96771bbee | 262 | int counter = 0; |
p07gbar | 1:3eb96771bbee | 263 | int increment = 4; //32/wordwidth; |
p07gbar | 1:3eb96771bbee | 264 | int fifo_levl = fifo_level(); |
p07gbar | 1:3eb96771bbee | 265 | while (counter < fifo_levl && len_valid) { |
p07gbar | 1:3eb96771bbee | 266 | temp[counter] = LPC_I2S->I2SRXFIFO; |
p07gbar | 1:3eb96771bbee | 267 | for (int j = 0; j < increment; j++) { |
p07gbar | 1:3eb96771bbee | 268 | if ((counter * 4) + j > len) { |
p07gbar | 1:3eb96771bbee | 269 | len_valid = false; |
p07gbar | 1:3eb96771bbee | 270 | break; |
p07gbar | 1:3eb96771bbee | 271 | } |
p07gbar | 1:3eb96771bbee | 272 | buf[counter + j] = temp[counter] >> (j * 8); |
p07gbar | 1:3eb96771bbee | 273 | |
p07gbar | 1:3eb96771bbee | 274 | } |
p07gbar | 1:3eb96771bbee | 275 | counter++; |
p07gbar | 1:3eb96771bbee | 276 | } |
p07gbar | 1:3eb96771bbee | 277 | } |
p07gbar | 1:3eb96771bbee | 278 | |
p07gbar | 1:3eb96771bbee | 279 | void I2S::read(int buf[], int len) |
p07gbar | 1:3eb96771bbee | 280 | { |
p07gbar | 1:3eb96771bbee | 281 | bool len_valid = true; |
p07gbar | 1:3eb96771bbee | 282 | if (len <= 0) |
p07gbar | 1:3eb96771bbee | 283 | return; |
p07gbar | 1:3eb96771bbee | 284 | if (len >= fifo_points()) |
p07gbar | 1:3eb96771bbee | 285 | len = fifo_points(); |
p07gbar | 1:3eb96771bbee | 286 | int temp[8]; |
p07gbar | 1:3eb96771bbee | 287 | int counter = 0; |
p07gbar | 1:3eb96771bbee | 288 | int increment = 32 / wordwidth; |
p07gbar | 1:3eb96771bbee | 289 | int fifo_levl = fifo_level(); |
p07gbar | 1:3eb96771bbee | 290 | while (counter < fifo_levl && len_valid) { |
p07gbar | 1:3eb96771bbee | 291 | temp[counter] = LPC_I2S->I2SRXFIFO; |
p07gbar | 1:3eb96771bbee | 292 | for (int j = 0; j < increment; j++) { |
p07gbar | 1:3eb96771bbee | 293 | if ((counter * increment) + j > len) { |
p07gbar | 1:3eb96771bbee | 294 | len_valid = false; |
p07gbar | 1:3eb96771bbee | 295 | break; |
p07gbar | 1:3eb96771bbee | 296 | } |
p07gbar | 1:3eb96771bbee | 297 | buf[counter + j] = temp[counter] >> (j * wordwidth); |
p07gbar | 1:3eb96771bbee | 298 | |
p07gbar | 1:3eb96771bbee | 299 | } |
p07gbar | 1:3eb96771bbee | 300 | counter++; |
p07gbar | 1:3eb96771bbee | 301 | } |
p07gbar | 1:3eb96771bbee | 302 | } |
p07gbar | 1:3eb96771bbee | 303 | |
p07gbar | 1:3eb96771bbee | 304 | void I2S::read(int bufr[], int bufl[], int len) |
p07gbar | 1:3eb96771bbee | 305 | { |
p07gbar | 1:3eb96771bbee | 306 | //#TODO: Write this |
p07gbar | 1:3eb96771bbee | 307 | } |
p07gbar | 1:3eb96771bbee | 308 | |
p07gbar | 1:3eb96771bbee | 309 | int I2S::max_fifo_points() |
p07gbar | 1:3eb96771bbee | 310 | { |
p07gbar | 1:3eb96771bbee | 311 | switch (wordwidth) { |
p07gbar | 1:3eb96771bbee | 312 | case 8: |
p07gbar | 1:3eb96771bbee | 313 | return (4 * 8); |
p07gbar | 1:3eb96771bbee | 314 | case 16: |
p07gbar | 1:3eb96771bbee | 315 | return (2 * 8); |
p07gbar | 1:3eb96771bbee | 316 | case 32: |
p07gbar | 1:3eb96771bbee | 317 | return 8; |
p07gbar | 1:3eb96771bbee | 318 | default: |
p07gbar | 1:3eb96771bbee | 319 | return 0; |
p07gbar | 1:3eb96771bbee | 320 | } |
p07gbar | 1:3eb96771bbee | 321 | } |
p07gbar | 1:3eb96771bbee | 322 | |
p07gbar | 1:3eb96771bbee | 323 | int I2S::fifo_points() |
p07gbar | 1:3eb96771bbee | 324 | { |
p07gbar | 1:3eb96771bbee | 325 | switch (wordwidth) { |
p07gbar | 1:3eb96771bbee | 326 | case 8: |
p07gbar | 1:3eb96771bbee | 327 | return (4 * fifo_level()); |
p07gbar | 1:3eb96771bbee | 328 | case 16: |
p07gbar | 1:3eb96771bbee | 329 | return (2 * fifo_level()); |
p07gbar | 1:3eb96771bbee | 330 | case 32: |
p07gbar | 1:3eb96771bbee | 331 | return fifo_level(); |
p07gbar | 1:3eb96771bbee | 332 | default: |
p07gbar | 1:3eb96771bbee | 333 | return 0; |
p07gbar | 1:3eb96771bbee | 334 | } |
p07gbar | 1:3eb96771bbee | 335 | } |
p07gbar | 1:3eb96771bbee | 336 | |
p07gbar | 1:3eb96771bbee | 337 | void I2S::power(bool pwr) |
p07gbar | 1:3eb96771bbee | 338 | { |
p07gbar | 1:3eb96771bbee | 339 | if (pwr) { |
p07gbar | 1:3eb96771bbee | 340 | stopped = false; |
p07gbar | 1:3eb96771bbee | 341 | } else { |
p07gbar | 1:3eb96771bbee | 342 | stopped = true; |
p07gbar | 1:3eb96771bbee | 343 | } |
p07gbar | 1:3eb96771bbee | 344 | write_registers(); |
p07gbar | 1:3eb96771bbee | 345 | } |
p07gbar | 1:3eb96771bbee | 346 | |
p07gbar | 1:3eb96771bbee | 347 | void I2S::masterslave(bool mastermode) |
p07gbar | 1:3eb96771bbee | 348 | { |
p07gbar | 1:3eb96771bbee | 349 | if (mastermode == I2S_MASTER) { |
p07gbar | 1:3eb96771bbee | 350 | master = true; |
p07gbar | 1:3eb96771bbee | 351 | } else { |
p07gbar | 1:3eb96771bbee | 352 | master = false; |
p07gbar | 1:3eb96771bbee | 353 | } |
p07gbar | 1:3eb96771bbee | 354 | write_registers(); |
p07gbar | 1:3eb96771bbee | 355 | } |
p07gbar | 1:3eb96771bbee | 356 | |
p07gbar | 1:3eb96771bbee | 357 | void I2S::wordsize(int words) |
p07gbar | 1:3eb96771bbee | 358 | { |
p07gbar | 1:3eb96771bbee | 359 | wordwidth = words; |
p07gbar | 1:3eb96771bbee | 360 | write_registers(); |
p07gbar | 1:3eb96771bbee | 361 | } |
p07gbar | 1:3eb96771bbee | 362 | |
p07gbar | 1:3eb96771bbee | 363 | void I2S::mclk_freq(int freq) |
p07gbar | 1:3eb96771bbee | 364 | { |
p07gbar | 1:3eb96771bbee | 365 | mclk_frequency = freq; |
p07gbar | 1:3eb96771bbee | 366 | write_registers(); |
p07gbar | 1:3eb96771bbee | 367 | } |
p07gbar | 1:3eb96771bbee | 368 | |
p07gbar | 1:3eb96771bbee | 369 | void I2S::frequency(int desired_freq) |
p07gbar | 1:3eb96771bbee | 370 | { |
p07gbar | 1:3eb96771bbee | 371 | freq = desired_freq; |
p07gbar | 1:3eb96771bbee | 372 | write_registers(); |
p07gbar | 1:3eb96771bbee | 373 | } |
p07gbar | 1:3eb96771bbee | 374 | |
p07gbar | 1:3eb96771bbee | 375 | int I2S::fifo_level() |
p07gbar | 1:3eb96771bbee | 376 | { |
p07gbar | 1:3eb96771bbee | 377 | int level = 0; |
p07gbar | 1:3eb96771bbee | 378 | if (_rxtx == I2S_TRANSMIT) { |
p07gbar | 1:3eb96771bbee | 379 | level = LPC_I2S->I2SSTATE; |
p07gbar | 1:3eb96771bbee | 380 | level >>= 16; |
p07gbar | 1:3eb96771bbee | 381 | level &= 0xF; |
p07gbar | 1:3eb96771bbee | 382 | } else { |
p07gbar | 1:3eb96771bbee | 383 | level = LPC_I2S->I2SSTATE; |
p07gbar | 1:3eb96771bbee | 384 | level >>= 8; |
p07gbar | 1:3eb96771bbee | 385 | level &= 0xF; |
p07gbar | 1:3eb96771bbee | 386 | } |
p07gbar | 1:3eb96771bbee | 387 | return level; |
p07gbar | 1:3eb96771bbee | 388 | } |
p07gbar | 1:3eb96771bbee | 389 | |
p07gbar | 1:3eb96771bbee | 390 | void I2S::stereomono(bool stereomode) |
p07gbar | 1:3eb96771bbee | 391 | { |
p07gbar | 1:3eb96771bbee | 392 | if (stereomode == I2S_STEREO) { |
p07gbar | 1:3eb96771bbee | 393 | stereo = true; |
p07gbar | 1:3eb96771bbee | 394 | } else { |
p07gbar | 1:3eb96771bbee | 395 | stereo = false; |
p07gbar | 1:3eb96771bbee | 396 | } |
p07gbar | 1:3eb96771bbee | 397 | } |
p07gbar | 1:3eb96771bbee | 398 | |
p07gbar | 1:3eb96771bbee | 399 | void I2S::mute() |
p07gbar | 1:3eb96771bbee | 400 | { |
p07gbar | 1:3eb96771bbee | 401 | muted = true; |
p07gbar | 1:3eb96771bbee | 402 | write_registers(); |
p07gbar | 1:3eb96771bbee | 403 | } |
p07gbar | 1:3eb96771bbee | 404 | |
p07gbar | 1:3eb96771bbee | 405 | void I2S::mute(bool mute_en) |
p07gbar | 1:3eb96771bbee | 406 | { |
p07gbar | 1:3eb96771bbee | 407 | muted = mute_en; |
p07gbar | 1:3eb96771bbee | 408 | write_registers(); |
p07gbar | 1:3eb96771bbee | 409 | } |
p07gbar | 1:3eb96771bbee | 410 | |
p07gbar | 1:3eb96771bbee | 411 | void I2S::stop() |
p07gbar | 1:3eb96771bbee | 412 | { |
p07gbar | 1:3eb96771bbee | 413 | stopped = true; |
p07gbar | 1:3eb96771bbee | 414 | write_registers(); |
p07gbar | 1:3eb96771bbee | 415 | } |
p07gbar | 1:3eb96771bbee | 416 | |
p07gbar | 1:3eb96771bbee | 417 | void I2S::set_interrupt_fifo_level(int level) |
p07gbar | 1:3eb96771bbee | 418 | { |
p07gbar | 1:3eb96771bbee | 419 | interrupt_fifo_level = level; |
p07gbar | 1:3eb96771bbee | 420 | write_registers(); |
p07gbar | 1:3eb96771bbee | 421 | } |
p07gbar | 1:3eb96771bbee | 422 | |
p07gbar | 1:3eb96771bbee | 423 | void I2S::start() |
p07gbar | 1:3eb96771bbee | 424 | { |
p07gbar | 1:3eb96771bbee | 425 | stopped = false; |
p07gbar | 1:3eb96771bbee | 426 | muted = false; |
p07gbar | 1:3eb96771bbee | 427 | write_registers(); |
p07gbar | 1:3eb96771bbee | 428 | } |
p07gbar | 1:3eb96771bbee | 429 | |
p07gbar | 1:3eb96771bbee | 430 | bool I2S::setup_ok() |
p07gbar | 1:3eb96771bbee | 431 | { |
p07gbar | 1:3eb96771bbee | 432 | if ((reg_write_err + pin_setup_err) > 0) |
p07gbar | 1:3eb96771bbee | 433 | return false; |
p07gbar | 1:3eb96771bbee | 434 | else |
p07gbar | 1:3eb96771bbee | 435 | return true; |
p07gbar | 1:3eb96771bbee | 436 | } |
p07gbar | 1:3eb96771bbee | 437 | |
p07gbar | 1:3eb96771bbee | 438 | void I2S::pin_setup() |
p07gbar | 1:3eb96771bbee | 439 | { |
p07gbar | 1:3eb96771bbee | 440 | pin_setup_err = 0; |
p07gbar | 1:3eb96771bbee | 441 | |
p07gbar | 1:3eb96771bbee | 442 | if (_rxtx == I2S_TRANSMIT) { |
p07gbar | 1:3eb96771bbee | 443 | printf("\n\rSetting up pins....\n\r"); |
p07gbar | 1:3eb96771bbee | 444 | if (_sd != p5) |
p07gbar | 1:3eb96771bbee | 445 | pin_setup_err++; |
p07gbar | 1:3eb96771bbee | 446 | if (_ws != p6 && ws_d == true) |
p07gbar | 1:3eb96771bbee | 447 | pin_setup_err++; |
p07gbar | 1:3eb96771bbee | 448 | if (_clk != p7 && clk_d == true) |
p07gbar | 1:3eb96771bbee | 449 | pin_setup_err++; |
p07gbar | 1:3eb96771bbee | 450 | printf("Hmm....%i\n\r", pin_setup_err); |
p07gbar | 1:3eb96771bbee | 451 | } else { |
p07gbar | 1:3eb96771bbee | 452 | if (_sd != p17 && _sd != p8) |
p07gbar | 1:3eb96771bbee | 453 | pin_setup_err++; |
p07gbar | 1:3eb96771bbee | 454 | if (_ws != p16 && _ws != p29 && ws_d == true) |
p07gbar | 1:3eb96771bbee | 455 | pin_setup_err++; |
p07gbar | 1:3eb96771bbee | 456 | if (_clk != p15 && _clk != p30 && clk_d == true) |
p07gbar | 1:3eb96771bbee | 457 | pin_setup_err++; |
p07gbar | 1:3eb96771bbee | 458 | } |
p07gbar | 1:3eb96771bbee | 459 | |
p07gbar | 1:3eb96771bbee | 460 | if (pin_setup_err == 0) { |
p07gbar | 1:3eb96771bbee | 461 | if (_rxtx == I2S_TRANSMIT) { |
p07gbar | 1:3eb96771bbee | 462 | int val1 = 1; |
p07gbar | 1:3eb96771bbee | 463 | if (deallocating) { |
p07gbar | 1:3eb96771bbee | 464 | val1 = 0; |
p07gbar | 1:3eb96771bbee | 465 | } |
p07gbar | 1:3eb96771bbee | 466 | LPC_PINCON->PINSEL0 |= (val1 << 18); //set p5 as transmit serial data line |
p07gbar | 1:3eb96771bbee | 467 | if (ws_d == true) |
p07gbar | 1:3eb96771bbee | 468 | LPC_PINCON->PINSEL0 |= (val1 << 14); //set p7 as transmit clock line |
p07gbar | 1:3eb96771bbee | 469 | if (clk_d == true) |
p07gbar | 1:3eb96771bbee | 470 | LPC_PINCON->PINSEL0 |= (val1 << 16); //set p6 as word select line |
p07gbar | 1:3eb96771bbee | 471 | |
p07gbar | 1:3eb96771bbee | 472 | } else { |
p07gbar | 1:3eb96771bbee | 473 | int val1 = 1; |
p07gbar | 1:3eb96771bbee | 474 | int val2 = 2; |
p07gbar | 1:3eb96771bbee | 475 | if (deallocating) { |
p07gbar | 1:3eb96771bbee | 476 | val1 = 0; |
p07gbar | 1:3eb96771bbee | 477 | val2 = 0; |
p07gbar | 1:3eb96771bbee | 478 | } |
p07gbar | 1:3eb96771bbee | 479 | |
p07gbar | 1:3eb96771bbee | 480 | if (_sd == p8) |
p07gbar | 1:3eb96771bbee | 481 | LPC_PINCON->PINSEL0 |= (val1 << 12); |
p07gbar | 1:3eb96771bbee | 482 | else |
p07gbar | 1:3eb96771bbee | 483 | LPC_PINCON->PINSEL1 |= (val2 << 18); |
p07gbar | 1:3eb96771bbee | 484 | |
p07gbar | 1:3eb96771bbee | 485 | if (ws_d == true) { |
p07gbar | 1:3eb96771bbee | 486 | if (_ws == p29) |
p07gbar | 1:3eb96771bbee | 487 | LPC_PINCON->PINSEL0 |= (val1 << 10); |
p07gbar | 1:3eb96771bbee | 488 | else |
p07gbar | 1:3eb96771bbee | 489 | LPC_PINCON->PINSEL1 |= (val2 << 16); |
p07gbar | 1:3eb96771bbee | 490 | } |
p07gbar | 1:3eb96771bbee | 491 | |
p07gbar | 1:3eb96771bbee | 492 | if (clk_d == true) { |
p07gbar | 1:3eb96771bbee | 493 | if (_clk == p15) |
p07gbar | 1:3eb96771bbee | 494 | LPC_PINCON->PINSEL0 |= (val1 << 8); |
p07gbar | 1:3eb96771bbee | 495 | else |
p07gbar | 1:3eb96771bbee | 496 | LPC_PINCON->PINSEL1 |= (val2 << 14); |
p07gbar | 1:3eb96771bbee | 497 | } |
p07gbar | 1:3eb96771bbee | 498 | } |
p07gbar | 1:3eb96771bbee | 499 | } |
p07gbar | 1:3eb96771bbee | 500 | } |
p07gbar | 1:3eb96771bbee | 501 | |
p07gbar | 1:3eb96771bbee | 502 | void I2S::write_registers() |
p07gbar | 1:3eb96771bbee | 503 | { |
p07gbar | 1:3eb96771bbee | 504 | reg_write_err = 0; |
p07gbar | 1:3eb96771bbee | 505 | //Clock Multiplier Calculations |
p07gbar | 1:3eb96771bbee | 506 | float pre_mult = 0; |
p07gbar | 1:3eb96771bbee | 507 | int pre_num = 0; |
p07gbar | 1:3eb96771bbee | 508 | int pre_den = 0; |
p07gbar | 1:3eb96771bbee | 509 | int bitrate_div = 0; |
p07gbar | 1:3eb96771bbee | 510 | if (master == true) { // In the hope of not doing all this heavy lifting every configuration |
p07gbar | 1:3eb96771bbee | 511 | //printf("Doing some clock magic..\n\r"); |
p07gbar | 1:3eb96771bbee | 512 | int bitrate = freq * 64; |
p07gbar | 1:3eb96771bbee | 513 | float target_div = I2S_PCLK_RATE / float(bitrate * 2);// Work out what divider is needed in the end, including the halving of rates the smoother does |
p07gbar | 1:3eb96771bbee | 514 | if (mclk_frequency == 0) { |
p07gbar | 1:3eb96771bbee | 515 | float rnd = fmod(target_div,1);// To make the X/Y fraction closest to 1, we set the last divider to the nearest integer to the rate divider |
p07gbar | 1:3eb96771bbee | 516 | bitrate_div = int(target_div - rnd); |
p07gbar | 1:3eb96771bbee | 517 | while (bitrate_div > I2S_MAX_BITRATE_DIV) { // But this might be out of range, so we right shift it into focus |
p07gbar | 1:3eb96771bbee | 518 | bitrate_div >>= 1; |
p07gbar | 1:3eb96771bbee | 519 | } |
p07gbar | 1:3eb96771bbee | 520 | if (bitrate_div == 0) { // Could be zero, which would disable the the clock... |
p07gbar | 1:3eb96771bbee | 521 | bitrate_div = 1; |
p07gbar | 1:3eb96771bbee | 522 | } |
p07gbar | 1:3eb96771bbee | 523 | pre_mult = float(bitrate_div) / target_div; // Work out what we have left to correct |
p07gbar | 1:3eb96771bbee | 524 | pre_num = 0; |
p07gbar | 1:3eb96771bbee | 525 | pre_den = 0; |
p07gbar | 1:3eb96771bbee | 526 | fraction_estimator(pre_mult, &pre_num, &pre_den);// Get the function to work out the closest fraction, there might be some point in adding some possible multipliers of these values to add to the smoothing, the reference manual (UM10360 page 480) suggests this |
p07gbar | 1:3eb96771bbee | 527 | |
p07gbar | 1:3eb96771bbee | 528 | } else { |
p07gbar | 1:3eb96771bbee | 529 | pre_mult = float(mclk_frequency * 2) / (I2S_PCLK_RATE); |
p07gbar | 1:3eb96771bbee | 530 | pre_num = 0; |
p07gbar | 1:3eb96771bbee | 531 | pre_den = 0; |
p07gbar | 1:3eb96771bbee | 532 | fraction_estimator(pre_mult, &pre_num, &pre_den);// Get the function to work out the closest fraction, there might be some point in adding some possible multipliers of these values to add to the smoothing, the reference manual (UM10360 page 480) suggests this |
p07gbar | 1:3eb96771bbee | 533 | bitrate_div = int( |
p07gbar | 1:3eb96771bbee | 534 | I2S_PCLK_RATE * float(pre_num) / float(pre_den) |
p07gbar | 1:3eb96771bbee | 535 | / float(bitrate)); |
p07gbar | 1:3eb96771bbee | 536 | } |
p07gbar | 1:3eb96771bbee | 537 | |
p07gbar | 1:3eb96771bbee | 538 | old_freq = freq; |
p07gbar | 1:3eb96771bbee | 539 | old_pre_num = pre_num; |
p07gbar | 1:3eb96771bbee | 540 | old_pre_den = pre_den; |
p07gbar | 1:3eb96771bbee | 541 | old_bitrate_div = bitrate_div; |
p07gbar | 1:3eb96771bbee | 542 | } else { |
p07gbar | 1:3eb96771bbee | 543 | pre_num = old_pre_num; |
p07gbar | 1:3eb96771bbee | 544 | pre_den = old_pre_den; |
p07gbar | 1:3eb96771bbee | 545 | bitrate_div = old_bitrate_div; |
p07gbar | 1:3eb96771bbee | 546 | } |
p07gbar | 1:3eb96771bbee | 547 | |
p07gbar | 1:3eb96771bbee | 548 | //Clock Multiplier, MCLK setup |
p07gbar | 1:3eb96771bbee | 549 | if (_rxtx == I2S_TRANSMIT) { |
p07gbar | 1:3eb96771bbee | 550 | int regvals = ((pre_num << 8) & 0xFF00) | (pre_den & 0xFF); |
p07gbar | 1:3eb96771bbee | 551 | LPC_I2S->I2STXRATE = regvals; // Setting the X/Y fraction |
p07gbar | 1:3eb96771bbee | 552 | LPC_I2S->I2STXBITRATE = (bitrate_div - 1) & 0x3F;// Setting up the bitrate divider, the periferal adds one to this |
p07gbar | 1:3eb96771bbee | 553 | |
p07gbar | 1:3eb96771bbee | 554 | LPC_I2S->I2STXMODE = fourwire << 2; |
p07gbar | 1:3eb96771bbee | 555 | |
p07gbar | 1:3eb96771bbee | 556 | if (mclk_d == true) { |
p07gbar | 1:3eb96771bbee | 557 | LPC_I2S->I2STXMODE |= (1 << 3); |
p07gbar | 1:3eb96771bbee | 558 | } |
p07gbar | 1:3eb96771bbee | 559 | } else { |
p07gbar | 1:3eb96771bbee | 560 | int regvals = ((pre_num << 8) & 0xFF00) | (pre_den & 0xFF); |
p07gbar | 1:3eb96771bbee | 561 | LPC_I2S->I2SRXRATE = regvals; // Setting the X/Y fraction |
p07gbar | 1:3eb96771bbee | 562 | LPC_I2S->I2SRXBITRATE = (bitrate_div - 1) & 0x3F;// Setting up the bitrate divider, the periferal adds one to this |
p07gbar | 1:3eb96771bbee | 563 | |
p07gbar | 1:3eb96771bbee | 564 | LPC_I2S->I2SRXMODE = fourwire << 2; |
p07gbar | 1:3eb96771bbee | 565 | |
p07gbar | 1:3eb96771bbee | 566 | if (mclk_d == true) { |
p07gbar | 1:3eb96771bbee | 567 | LPC_I2S->I2SRXMODE |= (1 << 3); |
p07gbar | 1:3eb96771bbee | 568 | } |
p07gbar | 1:3eb96771bbee | 569 | } |
p07gbar | 1:3eb96771bbee | 570 | |
p07gbar | 1:3eb96771bbee | 571 | switch (wordwidth) { |
p07gbar | 1:3eb96771bbee | 572 | case 8: |
p07gbar | 1:3eb96771bbee | 573 | wordwidth_code = 0; |
p07gbar | 1:3eb96771bbee | 574 | break; |
p07gbar | 1:3eb96771bbee | 575 | case 16: |
p07gbar | 1:3eb96771bbee | 576 | wordwidth_code = 1; |
p07gbar | 1:3eb96771bbee | 577 | break; |
p07gbar | 1:3eb96771bbee | 578 | case 32: |
p07gbar | 1:3eb96771bbee | 579 | wordwidth_code = 3; |
p07gbar | 1:3eb96771bbee | 580 | break; |
p07gbar | 1:3eb96771bbee | 581 | default: |
p07gbar | 1:3eb96771bbee | 582 | reg_write_err++; |
p07gbar | 1:3eb96771bbee | 583 | break; |
p07gbar | 1:3eb96771bbee | 584 | } |
p07gbar | 1:3eb96771bbee | 585 | |
p07gbar | 1:3eb96771bbee | 586 | int I2SDA_reg = (wordwidth_code & 0x3); |
p07gbar | 1:3eb96771bbee | 587 | I2SDA_reg |= ((!stereo << 2) & 0x4); |
p07gbar | 1:3eb96771bbee | 588 | I2SDA_reg |= ((stopped << 3) & 0x8); |
p07gbar | 1:3eb96771bbee | 589 | I2SDA_reg |= ((!master << 5) & 0x20); |
p07gbar | 1:3eb96771bbee | 590 | I2SDA_reg |= (0x1F << 6); |
p07gbar | 1:3eb96771bbee | 591 | I2SDA_reg |= ((muted << 15) & 0x8000); |
p07gbar | 1:3eb96771bbee | 592 | |
p07gbar | 1:3eb96771bbee | 593 | if (_rxtx == I2S_TRANSMIT) { |
p07gbar | 1:3eb96771bbee | 594 | LPC_I2S->I2SDAO = I2SDA_reg; |
p07gbar | 1:3eb96771bbee | 595 | } else { |
p07gbar | 1:3eb96771bbee | 596 | LPC_I2S->I2SDAI = I2SDA_reg; |
p07gbar | 1:3eb96771bbee | 597 | } |
p07gbar | 1:3eb96771bbee | 598 | |
p07gbar | 1:3eb96771bbee | 599 | if (_rxtx == I2S_TRANSMIT) { |
p07gbar | 1:3eb96771bbee | 600 | if (txisr) { |
p07gbar | 1:3eb96771bbee | 601 | LPC_I2S->I2SIRQ = (LPC_I2S->I2SIRQ & 0xFF0FFFFF) |
p07gbar | 1:3eb96771bbee | 602 | | ((interrupt_fifo_level & 0xF) << 16); |
p07gbar | 1:3eb96771bbee | 603 | LPC_I2S->I2SIRQ |= 0x2; |
p07gbar | 1:3eb96771bbee | 604 | } else { |
p07gbar | 1:3eb96771bbee | 605 | LPC_I2S->I2SIRQ &= 0xFFFFFFFD; |
p07gbar | 1:3eb96771bbee | 606 | } |
p07gbar | 1:3eb96771bbee | 607 | } else { |
p07gbar | 1:3eb96771bbee | 608 | if (rxisr) { |
p07gbar | 1:3eb96771bbee | 609 | LPC_I2S->I2SIRQ = (LPC_I2S->I2SIRQ & 0xFFFFF0FF) |
p07gbar | 1:3eb96771bbee | 610 | | ((interrupt_fifo_level & 0xF) << 8); |
p07gbar | 1:3eb96771bbee | 611 | LPC_I2S->I2SIRQ |= 0x1; |
p07gbar | 1:3eb96771bbee | 612 | } |
p07gbar | 1:3eb96771bbee | 613 | |
p07gbar | 1:3eb96771bbee | 614 | else { |
p07gbar | 1:3eb96771bbee | 615 | LPC_I2S->I2SIRQ &= 0xFFFFFFFE; |
p07gbar | 1:3eb96771bbee | 616 | } |
p07gbar | 1:3eb96771bbee | 617 | } |
p07gbar | 1:3eb96771bbee | 618 | } |
p07gbar | 1:3eb96771bbee | 619 | |
p07gbar | 1:3eb96771bbee | 620 | void I2S::_i2sisr(void) |
p07gbar | 1:3eb96771bbee | 621 | { |
p07gbar | 1:3eb96771bbee | 622 | I2STXISR.call(); |
p07gbar | 1:3eb96771bbee | 623 | I2SRXISR.call(); |
p07gbar | 1:3eb96771bbee | 624 | } |
p07gbar | 1:3eb96771bbee | 625 | |
p07gbar | 1:3eb96771bbee | 626 | // A function to find the nearest fraction to that put to it, with numerator and denomnator less than 256 |
p07gbar | 1:3eb96771bbee | 627 | // This is used when trying to get the clocks correct |
p07gbar | 1:3eb96771bbee | 628 | |
p07gbar | 1:3eb96771bbee | 629 | void I2S::fraction_estimator(float in, int * num, int * den) |
p07gbar | 1:3eb96771bbee | 630 | { |
p07gbar | 1:3eb96771bbee | 631 | int test_num = 0; |
p07gbar | 1:3eb96771bbee | 632 | int test_den = 0; |
p07gbar | 1:3eb96771bbee | 633 | float least_error = 1; |
p07gbar | 1:3eb96771bbee | 634 | int least_err_den = 0; |
p07gbar | 1:3eb96771bbee | 635 | float genval; |
p07gbar | 1:3eb96771bbee | 636 | float generr; |
p07gbar | 1:3eb96771bbee | 637 | |
p07gbar | 1:3eb96771bbee | 638 | for (test_den = 1; test_den < I2S_MAX_DENOMINATOR; test_den++) { |
p07gbar | 1:3eb96771bbee | 639 | test_num = int(float(test_den) * in); |
p07gbar | 1:3eb96771bbee | 640 | if (test_num < I2S_MAX_NUMERATOR && test_num > 0) { |
p07gbar | 1:3eb96771bbee | 641 | genval = float(test_num) / float(test_den); |
p07gbar | 1:3eb96771bbee | 642 | generr = mod(genval - in); |
p07gbar | 1:3eb96771bbee | 643 | if (generr < least_error) { |
p07gbar | 1:3eb96771bbee | 644 | least_error = generr; |
p07gbar | 1:3eb96771bbee | 645 | least_err_den = test_den; |
p07gbar | 1:3eb96771bbee | 646 | } |
p07gbar | 1:3eb96771bbee | 647 | if (generr == 0) { |
p07gbar | 1:3eb96771bbee | 648 | break; |
p07gbar | 1:3eb96771bbee | 649 | } |
p07gbar | 1:3eb96771bbee | 650 | } |
p07gbar | 1:3eb96771bbee | 651 | } |
p07gbar | 1:3eb96771bbee | 652 | |
p07gbar | 1:3eb96771bbee | 653 | test_num = int(float(least_err_den) * in); |
p07gbar | 1:3eb96771bbee | 654 | *num = test_num; |
p07gbar | 1:3eb96771bbee | 655 | *den = least_err_den; |
p07gbar | 1:3eb96771bbee | 656 | |
p07gbar | 1:3eb96771bbee | 657 | } |
p07gbar | 1:3eb96771bbee | 658 | |
p07gbar | 1:3eb96771bbee | 659 | float I2S::mod(float in) |
p07gbar | 1:3eb96771bbee | 660 | { |
p07gbar | 1:3eb96771bbee | 661 | if (in < 0) |
p07gbar | 1:3eb96771bbee | 662 | in *= -1; |
p07gbar | 1:3eb96771bbee | 663 | |
p07gbar | 1:3eb96771bbee | 664 | return in; |
p07gbar | 1:3eb96771bbee | 665 | } |