Cheers, guest.
Still no luck it seems, unfortunately. I've quadruple-checked all of my connections, and also delved into the atmega2560 vs atmega328P datasheets to verify that all of the register settings are consistent between timer1 vs timer 5 (they are). Unfortunately, I don't have direct access to an oscope, but should be able to track one down in to use in one of our labs later this week.
My current pin mappings are as follows - anything not listed is not connected:
3.3V Mega > 3.3V Shield (/Uno equiv pin)
5V Mega > 5V Shield (/Uno equiv pin)
GND (above Vin) Mega > GND (above Vin) Shield (/Uno equiv pin) - I don't have both grounds tied
A0 Mega > A0 Shield/Uno
A1 Mega > A1 Shield/Uno
20/SDA Mega > A4/SDA Shield/Uno
21/SCL Mega > A5/SCL Shield/Uno
D53/SS Mega > D10/SS Shield/Uno
D51/MOSI Mega > D11/MOSI Shield/Uno
D50/MISO Mega > D12/MISO Shield/Uno
D52/SCK Mega > D13/SCK Shield/Uno
Updated all the changes you suggested, and below is the code:
/*
microphone.pde
guest openmusiclabs 8.17.11
this program takes input from the MIC pins on the codecshield.
NOTE: you will have to do a few solder joints to connect
your microphone, a description of this is on the wiki:
http://wiki.openmusiclabs.com/wiki/CodecShieldMicMod
this can also be used with low level instruments, like guitars,
to boost the volume on the input.
*/
// setup codec parameters
// must be done before #includes
// see readme file in libraries folder for explanations
#define SAMPLE_RATE 44 // 44.1Khz
#define ADCS 0 // no ADCs are being used
#define MUTEMIC 0 // turn off the mute on the microphone
#define INSEL 1 // select the microphone input
#define MICBOOST 1 // enables the microphone +10dB amp
// set this to 0 if its too loud
// include necessary libraries
#include <Wire.h>
#include <SPI.h>
#include <AudioCodec.h>
// create data variables for audio transfer
int left_in = 0x0000;
int left_out = 0x0000;
int right_in = 0x0000;
int right_out = 0x0000;
void setup() {
AudioCodec_init(); // setup codec registers
// call this last if setting up other parts
}
void loop() {
while (1); // reduces clock jitter
}
// timer5 interrupt routine - all data processed here
ISR(TIMER5_COMPA_vect, ISR_NAKED) { // dont store any registers
// &'s are necessary on data_in variables
AudioCodec_data(&left_in, &right_in, left_out, right_out);
// pass data through
left_out = left_in;
right_out = right_in;
// dont forget to return from interrupt
reti();
}
// AudioCodec.h
// guest openmusiclabs 7.28.11
// this is the library file for ARDUINO -> there is a different
// file for Maple, make sure you are using the right one.
// place this file in the libraries file of your Arduino sketches folder
// e.g. C:\Documents and Settings\user\My Documents\Arduino\libraries\
// you may have to create the \libraries folder
//
// updated for arduino1.0 - i2c commands changed, and "Arduino.h" added 1.9.12
#ifndef AudioCodecMega_h // include guard
#define AudioCodecMega_h
//#include "WProgram.h"
#include "Arduino.h"
#include <avr/pgmspace.h>
#include "mult16x16.h"
#include "mult16x8.h"
#include "mult32x16.h"
#ifndef SAMPLE_RATE
#define SAMPLE_RATE 44
#elif (SAMPLE_RATE == 88)||(SAMPLE_RATE == 44)||(SAMPLE_RATE == 22)||(SAMPLE_RATE == 8)||(SAMPLE_RATE == 2)
#else
#error SAMPLE_RATE value not defined
#endif
#ifndef ADCHPD
#define ADCHPD 0
#elif (ADCHPD == 0)||(ADCHPD == 1)
#else
#error ADCHPD value not defined
#endif
#ifndef ADCS
#define ADCS 2
#elif (ADCS >=0)&&(ADCS <= 2)
#else
#error ADCS value not defined
#endif
#ifndef HYST
#define HYST 32
#elif (HYST >= 0)&&(HYST <= 255)
#else
#error HYST value not defined
#endif
#ifndef LINVOL
#define LINVOL 23
#elif (LINVOL >= 0) && (LINVOL <= 0x1f)
#else
#error LINVOL value not defined
#endif
#ifndef RINVOL
#define RINVOL 23
#elif (RINVOL >= 0) && (RINVOL <= 0x1f)
#else
#error RINVOL value not defined
#endif
#ifndef LHPVOL
#define LHPVOL 121
#elif (LHPVOL == 0) || ((LHPVOL >= 0x30) && (LHPVOL <= 0x7f))
#else
#error LHPVOL value not defined
#endif
#ifndef RHPVOL
#define RHPVOL 121
#elif (RHPVOL == 0) || ((RHPVOL >= 0x30) && (RHPVOL <= 0x7f))
#else
#error RHPVOL value not defined
#endif
#ifndef MICBOOST
#define MICBOOST 0
#elif (MICBOOST == 0)||(MICBOOST == 1)
#else
#error MICBOOST value not defined
#endif
#ifndef MUTEMIC
#define MUTEMIC 1
#elif (MUTEMIC == 0)||(MUTEMIC == 1)
#else
#error MUTEMIC value not defined
#endif
#ifndef INSEL
#define INSEL 0
#elif (INSEL == 0)||(INSEL == 1)
#else
#error INSEL value not defined
#endif
#ifndef BYPASS
#define BYPASS 0
#elif (BYPASS == 0)||(BYPASS == 1)
#else
#error BYPASS value not defined
#endif
#ifndef DACSEL
#define DACSEL 1
#elif (DACSEL == 0)||(DACSEL == 1)
#else
#error DACSEL value not defined
#endif
#ifndef SIDETONE
#define SIDETONE 0
#elif (SIDETONE == 0)||(SIDETONE == 1)
#else
#error SIDETONE value not defined
#endif
#ifndef SIDEATT
#define SIDEATT 0
#elif (SIDEATT >= 0)&&(SIDEATT <= 3)
#else
#error SIDEATT value not defined
#endif
// setup variables for ADC
#if ADCS == 0
// do nothing
#elif ADCS == 1
unsigned char _i = 64;
unsigned int _mod0temp = 0x0000;
#elif ADCS == 2
unsigned char _i = 130;
unsigned int _mod0temp = 0x0000;
unsigned int _mod1temp = 0x0000;
#endif
static inline void AudioCodec_init(void) {
// setup spi peripheral
pinMode (53, OUTPUT);
digitalWrite(53, LOW); // set ss pin to output low
SPI.begin();
SPI.setBitOrder(MSBFIRST);
SPI.setClockDivider(SPI_CLOCK_DIV2);
SPI.setDataMode(SPI_MODE0);
// setup i2c pins and configure codec
// the new Wire library has trouble with 0x00, so (uint8_t) is added
Wire.begin();
Wire.beginTransmission(0x1a);
Wire.write(0x0c); // power reduction register
Wire.write((uint8_t)0x00); // turn everything on
Wire.endTransmission();
Wire.beginTransmission(0x1a);
Wire.write(0x0e); // digital data format
Wire.write(0x03); // 16b SPI mode
Wire.endTransmission();
Wire.beginTransmission(0x1a);
Wire.write((uint8_t)0x00); // left in setup register
Wire.write((uint8_t)LINVOL);
Wire.endTransmission();
Wire.beginTransmission(0x1a);
Wire.write(0x02); // right in setup register
Wire.write((uint8_t)RINVOL);
Wire.endTransmission();
Wire.beginTransmission(0x1a);
Wire.write(0x04); // left headphone out register
Wire.write((uint8_t)LHPVOL);
Wire.endTransmission();
Wire.beginTransmission(0x1a);
Wire.write(0x06); // right headphone out register
Wire.write((uint8_t)RHPVOL);
Wire.endTransmission();
Wire.beginTransmission(0x1a);
Wire.write(0x0a); // digital audio path configuration
Wire.write((uint8_t)ADCHPD);
Wire.endTransmission();
Wire.beginTransmission(0x1a);
Wire.write(0x08); // analog audio pathway configuration
Wire.write((uint8_t)((SIDEATT << 6)|(SIDETONE << 5)|(DACSEL << 4)|(BYPASS << 3)|(INSEL << 2)|(MUTEMIC << 1)|(MICBOOST << 0)));
Wire.endTransmission();
Wire.beginTransmission(0x1a);
Wire.write(0x10); // clock configuration
#if SAMPLE_RATE == 88
Wire.write(0xbc);
#elif SAMPLE_RATE == 44
Wire.write(0xa0);
#elif SAMPLE_RATE == 22
Wire.write(0xe0);
#elif SAMPLE_RATE == 8
Wire.write(0xac);
#elif SAMPLE_RATE == 2
Wire.write(0xce);
#endif
Wire.endTransmission();
Wire.beginTransmission(0x1a);
Wire.write(0x12); // codec enable
Wire.write(0x01);
Wire.endTransmission();
// setup ADCs
#if ADCS == 0
DIDR0 = (1 << ADC1D)|(1 << ADC0D); // turn off digital inputs for ADC0 and ADC1
#elif (ADCS == 1) || (ADCS == 2)
ADMUX = 0x40; // start with ADC0 - internal VCC for Vref
ADCSRA = 0xe7; // ADC enable, autotrigger, ck/128
ADCSRB = 0x00; // free running mode
DIDR0 = (1 << ADC1D)|(1 << ADC0D); // turn off digital inputs for ADC0 and ADC1
#endif
// setup timer5 for codec clock division
TCCR5A = 0x00; // set to CTC mode
TCCR5B = 0x0f; // set to CTC mode, external clock
TCCR5C = 0x00; // not used
TCNT5H = 0x00; // clear the counter
TCNT5H = 0x00;
#if SAMPLE_RATE == 88
OCR5AH = 0x00; // set the counter top
OCR5AL = 0x3f;
#elif (SAMPLE_RATE == 44) || (SAMPLE_RATE == 22)
OCR5AH = 0x00; // set the counter top
OCR5AL = 0x7f;
#elif SAMPLE_RATE == 8
OCR5AH = 0x02; // set the counter top
OCR5AL = 0xbf;
#elif SAMPLE_RATE == 2
OCR5AH = 0x04; // set the counter top
OCR5AL = 0x7f;
#endif
TIMSK5 = 0x02; // turn on compare match interrupt
// turn off all enabled interrupts (delay and wire)
TIMSK0 = 0x00;
TWCR = 0x00;
sei(); // turn on interrupts
}
// adc sample routine
// this creates relatively low noise 16b values from adc samples
#if ADCS == 0
static inline void AudioCodec_ADC() {
// do nothing
}
#elif ADCS == 1
static inline void AudioCodec_ADC(unsigned int* _mod0value) {
if (ADCSRA & (1 << ADIF)) { // check if sample ready
_mod0temp += ADCL; // fetch ADCL first to freeze sample
_mod0temp += (ADCH << 8); // add to temp register
ADCSRA = 0xf7; // reset the interrupt flag
if (--_i == 0) { // check if enough samples have been averaged
// add in hysteresis to remove jitter
if (((_mod0temp - *_mod0value) < HYST) || ((*_mod0value - _mod0temp) < HYST)) {
}
else {
*_mod0value = _mod0temp; // move temp value
}
_mod0temp = 0x0000; // reset temp value
_i = 64; // reset counter
}
}
}
#elif ADCS == 2
static inline void AudioCodec_ADC(unsigned int* _mod0value, unsigned int* _mod1value) {
if (ADCSRA & (1 << ADIF)) { // check if sample ready
--_i; // check which sample we are on
if (_i == 129) { // do nothing, first sample after mux change
}
else if (_i >= 65) { // sample ADC0
_mod0temp += ADCL; // fetch ADCL first to freeze sample
_mod0temp += (ADCH << 8); // add to temp register
if (_i == 65) { // check if enough samples have been averaged
// add in hysteresis to remove jitter
if (((_mod0temp - *_mod0value) < HYST) || ((*_mod0value - _mod0temp) < HYST)) {
}
else {
*_mod0value = _mod0temp; // move temp value
}
_mod0temp = 0x0000; // reset temp value
ADMUX = 0x41; // switch to ADC1
}
}
else if (_i < 64) { // sample ADC1, first sample (64) after mux change ignored
_mod1temp += ADCL; // fetch ADCL first to freeze sample
_mod1temp += (ADCH << 8); // add to temp register
if (_i == 0) { // check if enough samples have been averaged
// add in hysteresis to remove jitter
if (((_mod1temp - *_mod1value) < HYST) || ((*_mod1value - _mod1temp) < HYST)) {
}
else {
*_mod1value = _mod1temp; // move temp value
}
_mod1temp = 0x0000; // reset temp value
ADMUX = 0x40; // switch to ADC0
_i = 130; // reset counter
}
}
ADCSRA = 0xf7; // reset the interrupt flag
}
}
#endif
// codec data transfer function
static inline void AudioCodec_data(int* _lin, int* _rin, int _lout, int _rout) {
int _out_temp = _lout;
PORTB |= (1<<PORTB0); // toggle ss pina
asm volatile ("out %0, %B1" : : "I" (_SFR_IO_ADDR(SPDR)), "r" (_out_temp) );
PORTB &= ~(1<<PORTB0); // toggle ss pin
while(!(SPSR & (1<<SPIF))){ // wait for data transfer to complete
}
asm volatile ("out %0, %A1" : : "I" (_SFR_IO_ADDR(SPDR)), "r" (_out_temp) );
asm volatile ("in r3, %0" : : "I" (_SFR_IO_ADDR(SPDR)) );
_out_temp = _rout;
while(!(SPSR & (1<<SPIF))){ // wait for data transfer to complete
}
asm volatile ("out %0, %B1" : : "I" (_SFR_IO_ADDR(SPDR)), "r" (_out_temp) );
asm volatile ("in r2, %0" : : "I" (_SFR_IO_ADDR(SPDR)) );
asm volatile ("movw %0, r2" : "=r" (*_lin) : );
while(!(SPSR & (1<<SPIF))){ // wait for data transfer to complete
}
asm volatile ("out %0, %A1" : : "I" (_SFR_IO_ADDR(SPDR)), "r" (_out_temp) );
asm volatile ("in r3, %0" : : "I" (_SFR_IO_ADDR(SPDR)) );
while(!(SPSR & (1<<SPIF))){ // wait for data transfer to complete
}
asm volatile ("in r2, %0" : : "I" (_SFR_IO_ADDR(SPDR)) );
asm volatile ("movw %0, r2" : "=r" (*_rin) : );
}
#endif // end include guard