Attachment 'AuidoCodecEx.h'
Download 1 // AudioCodec.h
2 // guest openmusiclabs 7.28.11
3 // this is the library file for ARDUINO -> there is a different
4 // file for Maple, make sure you are using the right one.
5 // place this file in the libraries file of your Arduino sketches folder
6 // e.g. C:\Documents and Settings\user\My Documents\Arduino\libraries\
7 // you may have to create the \libraries folder
8 // modded 4.15.12
9 // added better pot handling and more sample rates
10
11 #ifndef AudioCodec_h // include guard
12 #define AudioCodec_h
13
14 #include "WProgram.h"
15 #include <avr/pgmspace.h>
16 #include "mult16x16.h"
17 #include "mult16x8.h"
18 #include "mult32x16.h"
19
20
21 #ifndef SAMPLE_RATE
22 #define SAMPLE_RATE 44
23 #elif (SAMPLE_RATE == 88)||(SAMPLE_RATE == 44)||(SAMPLE_RATE == 22)||(SAMPLE_RATE == 8)||(SAMPLE_RATE == 2)
24 #else
25 #error SAMPLE_RATE value not defined
26 #endif
27
28 #ifndef ADCHPD
29 #define ADCHPD 0
30 #elif (ADCHPD == 0)||(ADCHPD == 1)
31 #else
32 #error ADCHPD value not defined
33 #endif
34
35 #ifndef ADCS
36 #define ADCS 2
37 #elif (ADCS >=0)&&(ADCS <= 4)
38 #else
39 #error ADCS value not defined
40 #endif
41
42 #ifndef HYST
43 #define HYST 32
44 #elif (HYST >= 0)&&(HYST <= 255)
45 #else
46 #error HYST value not defined
47 #endif
48
49 #ifndef LINVOL
50 #define LINVOL 23
51 #elif (LINVOL >= 0) && (LINVOL <= 0x1f)
52 #else
53 #error LINVOL value not defined
54 #endif
55
56 #ifndef RINVOL
57 #define RINVOL 23
58 #elif (RINVOL >= 0) && (RINVOL <= 0x1f)
59 #else
60 #error RINVOL value not defined
61 #endif
62
63 #ifndef LHPVOL
64 #define LHPVOL 121
65 #elif (LHPVOL == 0) || ((LHPVOL >= 0x30) && (LHPVOL <= 0x7f))
66 #else
67 #error LHPVOL value not defined
68 #endif
69
70 #ifndef RHPVOL
71 #define RHPVOL 121
72 #elif (RHPVOL == 0) || ((RHPVOL >= 0x30) && (RHPVOL <= 0x7f))
73 #else
74 #error RHPVOL value not defined
75 #endif
76
77 #ifndef MICBOOST
78 #define MICBOOST 0
79 #elif (MICBOOST == 0)||(MICBOOST == 1)
80 #else
81 #error MICBOOST value not defined
82 #endif
83
84 #ifndef MUTEMIC
85 #define MUTEMIC 1
86 #elif (MUTEMIC == 0)||(MUTEMIC == 1)
87 #else
88 #error MUTEMIC value not defined
89 #endif
90
91 #ifndef INSEL
92 #define INSEL 0
93 #elif (INSEL == 0)||(INSEL == 1)
94 #else
95 #error INSEL value not defined
96 #endif
97
98 #ifndef BYPASS
99 #define BYPASS 0
100 #elif (BYPASS == 0)||(BYPASS == 1)
101 #else
102 #error BYPASS value not defined
103 #endif
104
105 #ifndef DACSEL
106 #define DACSEL 1
107 #elif (DACSEL == 0)||(DACSEL == 1)
108 #else
109 #error DACSEL value not defined
110 #endif
111
112 #ifndef SIDETONE
113 #define SIDETONE 0
114 #elif (SIDETONE == 0)||(SIDETONE == 1)
115 #else
116 #error SIDETONE value not defined
117 #endif
118
119 #ifndef SIDEATT
120 #define SIDEATT 0
121 #elif (SIDEATT >= 0)&&(SIDEATT <= 3)
122 #else
123 #error SIDEATT value not defined
124 #endif
125
126 #ifndef OVERSAMPLE
127 #define OVERSAMPLE 64
128 #elif (OVERSAMPLE == 1)||(OVERSAMPLE == 2)||(OVERSAMPLE == 4)||(OVERSAMPLE == 8)||(OVERSAMPLE == 16)||(OVERSAMPLE == 32)||(OVERSAMPLE == 64)
129 #else
130 #error OVERSAMPLE value not defined
131 #endif
132
133
134 // setup variables for ADC
135 #if ADCS == 0
136 // do nothing
137 #else
138 unsigned char _t = OVERSAMPLE; // number of times to oversample
139 unsigned char _n = 0x00; // we start with mod0
140 unsigned int _modtemp = 0x0000;
141 #endif
142
143
144 static inline void AudioCodec_init(void) {
145
146 // setup spi peripheral
147 digitalWrite(10, LOW); // set ss pin to output low
148 pinMode (10, OUTPUT);
149 SPI.begin();
150 SPI.setBitOrder(MSBFIRST);
151 SPI.setClockDivider(SPI_CLOCK_DIV2);
152 SPI.setDataMode(SPI_MODE0);
153
154 // setup i2c pins and configure codec
155 Wire.begin();
156 Wire.beginTransmission(0x1a);
157 Wire.send(0x0c); // power reduction register
158 Wire.send(0x00); // turn everything on
159 Wire.endTransmission();
160
161 Wire.beginTransmission(0x1a);
162 Wire.send(0x0e); // digital data format
163 Wire.send(0x03); // 16b SPI mode
164 Wire.endTransmission();
165
166 Wire.beginTransmission(0x1a);
167 Wire.send(0x00); // left in setup register
168 Wire.send(LINVOL);
169 Wire.endTransmission();
170
171 Wire.beginTransmission(0x1a);
172 Wire.send(0x02); // right in setup register
173 Wire.send(RINVOL);
174 Wire.endTransmission();
175
176 Wire.beginTransmission(0x1a);
177 Wire.send(0x04); // left headphone out register
178 Wire.send(LHPVOL);
179 Wire.endTransmission();
180
181 Wire.beginTransmission(0x1a);
182 Wire.send(0x06); // right headphone out register
183 Wire.send(RHPVOL);
184 Wire.endTransmission();
185
186 Wire.beginTransmission(0x1a);
187 Wire.send(0x0a); // digital audio path configuration
188 Wire.send(ADCHPD);
189 Wire.endTransmission();
190
191 Wire.beginTransmission(0x1a);
192 Wire.send(0x08); // analog audio pathway configuration
193 Wire.send((SIDEATT << 6)|(SIDETONE << 5)|(DACSEL << 4)|(BYPASS << 3)|(INSEL << 2)|(MUTEMIC << 1)|(MICBOOST << 0));
194 Wire.endTransmission();
195
196 Wire.beginTransmission(0x1a);
197 Wire.send(0x10); // clock configuration
198 #if SAMPLE_RATE == 88
199 Wire.send(0xbc);
200 #elif SAMPLE_RATE == 44
201 Wire.send(0xa0);
202 #elif SAMPLE_RATE == 22
203 Wire.send(0xe0);
204 #elif SAMPLE_RATE == 8
205 Wire.send(0xac);
206 #elif SAMPLE_RATE == 2
207 Wire.send(0xce);
208 #endif
209 Wire.endTransmission();
210
211 Wire.beginTransmission(0x1a);
212 Wire.send(0x12); // codec enable
213 Wire.send(0x01);
214 Wire.endTransmission();
215
216 // setup ADCs
217 #if ADCS == 0
218 DIDR0 = (1 << ADC1D)|(1 << ADC0D); // turn off digital inputs for ADC0 and ADC1
219 #elif (ADCS == 1) || (ADCS == 2)
220 ADMUX = 0x40; // start with ADC0 - internal VCC for Vref
221 ADCSRA = 0xc7; // ADC enable, single sample, ck/128
222 ADCSRB = 0x00; // just in case
223 DIDR0 = (1 << ADC1D)|(1 << ADC0D); // turn off digital inputs for ADC0 and ADC1
224 #elif (ADCS == 3)
225 ADMUX = 0x40; // start with ADC0 - internal VCC for Vref
226 ADCSRA = 0xc7; // ADC enable, single sample, ck/128
227 ADCSRB = 0x00; // just in case
228 DIDR0 = (1<<ADC2D)|(1 << ADC1D)|(1 << ADC0D); // turn off digital inputs for ADC0:2
229 #elif (ADCS == 4)
230 ADMUX = 0x40; // start with ADC0 - internal VCC for Vref
231 ADCSRA = 0xc7; // ADC enable, single sample, ck/128
232 ADCSRB = 0x00; // just in case
233 DIDR0 = (1<<ADC3D)|(1<<ADC2D)|(1 << ADC1D)|(1 << ADC0D); // turn off digital inputs for ADC0:3
234 #endif
235
236 // setup timer1 for codec clock division
237 TCCR1A = 0x00; // set to CTC mode
238 TCCR1B = 0x0f; // set to CTC mode, external clock
239 TCCR1C = 0x00; // not used
240 TCNT1H = 0x00; // clear the counter
241 TCNT1H = 0x00;
242 #if SAMPLE_RATE == 88
243 OCR1AH = 0x00; // set the counter top
244 OCR1AL = 0x3f;
245 #elif (SAMPLE_RATE == 44) || (SAMPLE_RATE == 22)
246 OCR1AH = 0x00; // set the counter top
247 OCR1AL = 0x7f;
248 #elif SAMPLE_RATE == 8
249 OCR1AH = 0x02; // set the counter top
250 OCR1AL = 0xbf;
251 #elif SAMPLE_RATE == 2
252 OCR1AH = 0x04; // set the counter top
253 OCR1AL = 0x7f;
254 #endif
255 TIMSK1 = 0x02; // turn on compare match interrupt
256
257 // turn off all enabled interrupts (delay and wire)
258 TIMSK0 = 0x00;
259 TWCR = 0x00;
260
261 sei(); // turn on interrupts
262 }
263
264
265 // adc sample routine
266 // this creates relatively low noise 16b values from adc samples
267 #if ADCS == 0
268 static inline void AudioCodec_ADC() {
269 // do nothing
270 }
271 #elif ADCS == 1
272 static inline void AudioCodec_ADC(unsigned int* _mod0value) {
273 if (ADCSRA & (1 << ADIF)) { // check if sample ready
274 _modtemp += ADCL; // fetch ADCL first to freeze sample
275 _modtemp += (ADCH << 8); // add to temp register
276 ADCSRA = 0xd7; // reset the interrupt flag
277 --_t; // decrement sample counter
278 if (_t == 0) { // check if enough samples have been averaged
279 // shift value to make a 16b integer
280 unsigned char x = 0;
281 for (unsigned char y = OVERSAMPLE; y > 1; y >>= 1) {
282 x += 1;
283 }
284 _modtemp <<= 6 - x;
285 // add in hysteresis to remove jitter
286 if (((_modtemp - *_mod0value) < HYST) || ((*_mod0value - _modtemp) < HYST)) {
287 }
288 else {
289 *_mod0value = _modtemp; // move temp value
290 }
291 _modtemp = 0x0000; // reset temp value
292 _t = OVERSAMPLE; // reset counter
293 }
294 }
295 }
296 #elif ADCS == 2
297 static inline void AudioCodec_ADC(unsigned int* _mod0value, unsigned int* _mod1value) {
298 if (ADCSRA & (1 << ADIF)) { // check if sample ready
299 _modtemp += ADCL; // fetch ADCL first to freeze sample
300 _modtemp += (ADCH << 8); // add to temp register
301 --_t; // decrement sample counter
302 if (_t == 0) { // check if enough samples have been averaged
303 // shift value to make a 16b integer
304 unsigned char x = 0;
305 for (unsigned char y = OVERSAMPLE; y > 1; y >>= 1) {
306 x += 1;
307 }
308 _modtemp <<= 6 - x;
309 if (_n == 0) { // check if just finished with mod0
310 ADMUX = 0x41; // change mux to mod1
311 _n = 1; // index counter to mod1
312 // add in hysteresis to remove jitter
313 if (((_modtemp - *_mod0value) < HYST) || ((*_mod0value - _modtemp) < HYST)) {
314 }
315 else {
316 *_mod0value = _modtemp; // move temp value
317 }
318 }
319 else { // just finished with mod1
320 ADMUX = 0x40; // change mux to mod0
321 _n = 0; // set counter to mod0
322 // add in hysteresis to remove jitter
323 if (((_modtemp - *_mod1value) < HYST) || ((*_mod1value - _modtemp) < HYST)) {
324 }
325 else {
326 *_mod1value = _modtemp; // move temp value
327 }
328 }
329 _modtemp = 0x0000; // reset temp value
330 _t = OVERSAMPLE; // reset counter
331 }
332 ADCSRA = 0xd7; // reset the interrupt flag and start next conversion
333 }
334 }
335 #elif ADCS == 3
336 static inline void AudioCodec_ADC(unsigned int* _mod0value, unsigned int* _mod1value, unsigned int* _mod2value) {
337 if (ADCSRA & (1 << ADIF)) { // check if sample ready
338 _modtemp += ADCL; // fetch ADCL first to freeze sample
339 _modtemp += (ADCH << 8); // add to temp register
340 --_t; // decrement sample counter
341 if (_t == 0) { // check if enough samples have been averaged
342 // shift value to make a 16b integer
343 unsigned char x = 0;
344 for (unsigned char y = OVERSAMPLE; y > 1; y >>= 1) {
345 x += 1;
346 }
347 _modtemp <<= 6 - x;
348 if (_n == 0) { // check if just finished with mod0
349 ADMUX = 0x41; // change mux to mod1
350 _n = 1; // index counter to mod1
351 // add in hysteresis to remove jitter
352 if (((_modtemp - *_mod0value) < HYST) || ((*_mod0value - _modtemp) < HYST)) {
353 }
354 else {
355 *_mod0value = _modtemp; // move temp value
356 }
357 }
358 else if (_n == 1){ // just finished with mod1
359 ADMUX = 0x42; // change mux to mod2
360 _n = 2; // set counter to mod2
361 // add in hysteresis to remove jitter
362 if (((_modtemp - *_mod1value) < HYST) || ((*_mod1value - _modtemp) < HYST)) {
363 }
364 else {
365 *_mod1value = _modtemp; // move temp value
366 }
367 }
368 else { // just finished with mod2
369 ADMUX = 0x40; // change mux to mod0
370 _n = 0; // set counter to mod0
371 // add in hysteresis to remove jitter
372 if (((_modtemp - *_mod2value) < HYST) || ((*_mod2value - _modtemp) < HYST)) {
373 }
374 else {
375 *_mod2value = _modtemp; // move temp value
376 }
377 }
378 _modtemp = 0x0000; // reset temp value
379 _t = OVERSAMPLE; // reset counter
380 }
381 ADCSRA = 0xd7; // reset the interrupt flag and start next conversion
382 }
383 }
384 #elif ADCS == 4
385 static inline void AudioCodec_ADC(unsigned int* _mod0value, unsigned int* _mod1value, unsigned int* _mod2value, unsigned int* _mod3value) {
386 if (ADCSRA & (1 << ADIF)) { // check if sample ready
387 _modtemp += ADCL; // fetch ADCL first to freeze sample
388 _modtemp += (ADCH << 8); // add to temp register
389 --_t; // decrement sample counter
390 if (_t == 0) { // check if enough samples have been averaged
391 // shift value to make a 16b integer
392 unsigned char x = 0;
393 for (unsigned char y = OVERSAMPLE; y > 1; y >>= 1) {
394 x += 1;
395 }
396 _modtemp <<= 6 - x;
397 if (_n == 0) { // check if just finished with mod0
398 ADMUX = 0x41; // change mux to mod1
399 _n = 1; // index counter to mod1
400 // add in hysteresis to remove jitter
401 if (((_modtemp - *_mod0value) < HYST) || ((*_mod0value - _modtemp) < HYST)) {
402 }
403 else {
404 *_mod0value = _modtemp; // move temp value
405 }
406 }
407 else if (_n == 1){ // just finished with mod1
408 ADMUX = 0x42; // change mux to mod2
409 _n = 2; // set counter to mod2
410 // add in hysteresis to remove jitter
411 if (((_modtemp - *_mod1value) < HYST) || ((*_mod1value - _modtemp) < HYST)) {
412 }
413 else {
414 *_mod1value = _modtemp; // move temp value
415 }
416 }
417 else if (_n == 2) { // just finished with mod2
418 ADMUX = 0x43; // change mux to mod3
419 _n = 3; // set counter to mod3
420 // add in hysteresis to remove jitter
421 if (((_modtemp - *_mod2value) < HYST) || ((*_mod2value - _modtemp) < HYST)) {
422 }
423 else {
424 *_mod2value = _modtemp; // move temp value
425 }
426 }
427 else { // just finished with mod3
428 ADMUX = 0x40; // change mux to mod0
429 _n = 0; // set counter to mod0
430 // add in hysteresis to remove jitter
431 if (((_modtemp - *_mod3value) < HYST) || ((*_mod3value - _modtemp) < HYST)) {
432 }
433 else {
434 *_mod3value = _modtemp; // move temp value
435 }
436 }
437 _modtemp = 0x0000; // reset temp value
438 _t = OVERSAMPLE; // reset counter
439 }
440 ADCSRA = 0xd7; // reset the interrupt flag and start next conversion
441 }
442 }
443 #endif
444
445
446 // codec data transfer function
447 static inline void AudioCodec_data(int* _lin, int* _rin, int _lout, int _rout) {
448
449 int _out_temp = _lout;
450 PORTB |= (1<<PORTB2); // toggle ss pina
451 asm volatile ("out %0, %B1" : : "I" (_SFR_IO_ADDR(SPDR)), "r" (_out_temp) );
452 PORTB &= ~(1<<PORTB2); // toggle ss pin
453 while(!(SPSR & (1<<SPIF))){ // wait for data transfer to complete
454 }
455 asm volatile ("out %0, %A1" : : "I" (_SFR_IO_ADDR(SPDR)), "r" (_out_temp) );
456 asm volatile ("in r3, %0" : : "I" (_SFR_IO_ADDR(SPDR)) );
457 _out_temp = _rout;
458 while(!(SPSR & (1<<SPIF))){ // wait for data transfer to complete
459 }
460 asm volatile ("out %0, %B1" : : "I" (_SFR_IO_ADDR(SPDR)), "r" (_out_temp) );
461 asm volatile ("in r2, %0" : : "I" (_SFR_IO_ADDR(SPDR)) );
462 asm volatile ("movw %0, r2" : "=r" (*_lin) : );
463 while(!(SPSR & (1<<SPIF))){ // wait for data transfer to complete
464 }
465 asm volatile ("out %0, %A1" : : "I" (_SFR_IO_ADDR(SPDR)), "r" (_out_temp) );
466 asm volatile ("in r3, %0" : : "I" (_SFR_IO_ADDR(SPDR)) );
467 while(!(SPSR & (1<<SPIF))){ // wait for data transfer to complete
468 }
469 asm volatile ("in r2, %0" : : "I" (_SFR_IO_ADDR(SPDR)) );
470 asm volatile ("movw %0, r2" : "=r" (*_rin) : );
471 }
472
473
474 #endif // end include guard
475
Attached Files
To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.- [get | view] (2012-08-14 10:57:28, 26.4 KB) [[attachment:AudioCodec.zip]]
- [get | view] (2012-08-14 11:06:10, 25.8 KB) [[attachment:AudioCodecNew.zip]]
- [get | view] (2012-08-14 11:06:02, 26.5 KB) [[attachment:AudioCodecNew1.zip]]
- [get | view] (2015-04-08 13:34:31, 26.5 KB) [[attachment:AudioCodecNew2.zip]]
- [get | view] (2011-07-26 21:51:13, 28.5 KB) [[attachment:AudioCodec_Maple.zip]]
- [get | view] (2012-04-16 12:08:52, 14.8 KB) [[attachment:AuidoCodecEx.h]]
- [get | view] (2011-06-23 21:18:08, 751.7 KB) [[attachment:WM8731.pdf]]
- [get | view] (2011-06-23 21:15:11, 30.5 KB) [[attachment:codecshield.brd]]
- [get | view] (2011-06-22 01:51:07, 61.3 KB) [[attachment:codecshield.lbr]]
- [get | view] (2011-06-23 21:14:55, 40.5 KB) [[attachment:codecshield.sch]]
- [get | view] (2011-08-24 04:19:42, 79.4 KB) [[attachment:codecshield.zip]]
- [get | view] (2011-06-22 01:50:31, 184.1 KB) [[attachment:codecshield_board.png]]
- [get | view] (2011-07-04 19:25:52, 13.1 KB) [[attachment:codecshield_bom.ods]]
- [get | view] (2011-07-04 19:25:41, 29.3 KB) [[attachment:codecshield_bom.pdf]]
- [get | view] (2011-06-22 01:48:50, 105.4 KB) [[attachment:codecshield_schem.png]]
- [get | view] (2012-04-19 16:12:33, 16.7 KB) [[attachment:sample_rates.ods]]
You are not allowed to attach a file to this page.