//MIDI DAC V11 by Robin Price 2009
#define ENVELOPE 0 //Analog in on Arduino to test output of AD5668
#define ZEROIN 2 //Zero crossing interupt
#define DATAOUT 3 //MOSI, DIN Pin 15 on AD5668
#define SPICLK 4 //Serial Clock In, SCLK Pin 16
#define SLAVESELECT 5//SYNC Active Low Control Input, Pin 2
#define LDAC 6//LDAC, Pin 1, Pulse this pin low to update DAC registers, can be tied permanently low.
#define CLR 7
#define PWRLED 8
#define RXLED 9
#define GATE 0
#define CV 1
#define ACC 2
#define SLD 3
#define FILT 4
//AD5668 Command definitions
#define WRITE 0
#define UPDATE 1
#define WRITE_UPDATE_ALL 2
#define WRITE_UPDATE_N 3
#define POWER 4
#define LOAD_CC_REG 5
#define LOAD_LDAC_REG 6
#define RESET 7
#define SETUP_INTERNAL_REGISTER 8
byte incomingByte;
int action = 0; //0 not implemented/do nothing, 1 note on, 2 note off, 3 cc, 4 sysex
int note = -1;
int velocity = -1;
int extra1 = -1;
int extra2 = -1;
int RX = LOW; // previous value of the LED
unsigned long previousMillis = 0; // will store last time LED was updated
unsigned long interval = 100; // interval at which to blink (milliseconds)
volatile unsigned int count = 0;
extern volatile unsigned long timer0_millis;
unsigned long previous_clock = 0;
unsigned long start;
unsigned long finish;
int amp = 0;
float freq = 0;
volatile unsigned int period;
boolean note_on = false;
boolean sysex = false;
unsigned int voltage1 = 13400;
unsigned int voltage2 = 26500;
unsigned int voltage3 = 39550;
unsigned int voltage4 = 52625;
long voltage5 = 65735;
unsigned char timerLoadValue;
#define TIMER_CLOCK_FREQ 2000000.0 //2MHz for /8 prescale from 16MHz
unsigned int latency;
volatile unsigned long clock;
//This timer code is for to setup the interrupt from the pitch detection part of the circuit
//and is largely nicked from uchobby.com if you're only interested in the midi-cv stuff just
//ignore it.
//Setup Timer2.
//Configures the ATMega168 8-Bit Timer2 to generate an interrupt at the specified frequency.
//Returns the time load value which must be loaded into TCNT2 inside your ISR routine.
unsigned char SetupTimer2(float timeoutFrequency){
unsigned char result; //The value to load into the timer to control the timeout interval.
//Calculate the timer load value
result=(int)((257.0-(TIMER_CLOCK_FREQ/timeoutFrequency))+0.5); //the 0.5 is for rounding;
//The 257 really should be 256 but I get better results with 257, dont know why.
//Timer2 Settings: Timer Prescaler /8, mode 0
//Timmer clock = 16MHz/8 = 2Mhz or 0.5us
//The /8 prescale gives us a good range to work with so we just hard code this for now.
TCCR2A = 0;
TCCR2B = 0<<CS22 | 1<<CS21 | 0<<CS20;
//set our clock to zero
clock = 0;
//Timer2 Overflow Interrupt Enable
TIMSK2 = 1<<TOIE2;
//load the timer for its first cycle
TCNT2=result;
return(result);
}
//Timer2 overflow interrupt vector handler
ISR(TIMER2_OVF_vect) {
//Increment clock, at some point we're going to have to handle overflows
clock++;
//Capture the current timer value. This is how much error we have
//due to interrupt latency and the work in this function
latency=TCNT2; //consider getting rid of the latency stuff and allowing the clock to be reset to zero
//Reload the timer and correct for latency.
TCNT2=latency+timerLoadValue;
}
void setup() {
//set pin modes
pinMode(ENVELOPE, INPUT);
pinMode(ZEROIN, INPUT);
pinMode(DATAOUT, OUTPUT);
pinMode(SPICLK, OUTPUT);
pinMode(SLAVESELECT, OUTPUT);
pinMode(LDAC, OUTPUT);
pinMode(CLR, OUTPUT);
pinMode(PWRLED, OUTPUT);
pinMode(RXLED, OUTPUT);
//disable DAC to start with
digitalWrite(DATAOUT,LOW);
digitalWrite(SPICLK, LOW);
digitalWrite(SLAVESELECT, LOW);
digitalWrite(LDAC, HIGH);
digitalWrite(PWRLED, HIGH);
digitalWrite(RXLED, HIGH);
digitalWrite(CLR, LOW);
delay(500);
digitalWrite(CLR, HIGH);
delay(500);
delay(1000);
write_dac(SETUP_INTERNAL_REGISTER, 0, 1); //set up internal register on DAC
delay(1000);
write_dac(POWER, 0, 0);
delay(1000);
write_dac(RESET, 0, 0);
delay(1000);
digitalWrite(RXLED, LOW);
//Start the timer and get the timer reload value.
timerLoadValue=SetupTimer2(40000);
//set up interupt for zero crossing detector
attachInterrupt(0, zero, RISING);
Serial.begin(31250
) ; //change this when you want to graduate from usb midi to real midi
}
void zero() {
period = (clock - previous_clock); //how many 25 microsecond ticks have elapsed
previous_clock = clock;
}
void write_dac(byte command, byte address, unsigned int data) {
switch (command) {
case WRITE_UPDATE_N:
{
byte b1 = B11110000|command; //padding at beginning of byte
//Serial.print("b1 ");
//Serial.println(b1, BIN);
byte b2 = address << 4 | data >> 12; //4 address bits and 4 MSBs of data
//Serial.print("b2 ");
//Serial.println(b2, BIN);
byte b3 = (data << 4) >> 8; // middle 8 bits of data
//Serial.print("b3 ");
//Serial.println(b3, BIN);
byte b4 = (data << 12) >> 8 | B00001111;
//Serial.print("b4 ");
//Serial.println(b4, BIN);
//Serial.println();
digitalWrite(SLAVESELECT, LOW);
delayMicroseconds(1);
shiftOut(DATAOUT, SPICLK, MSBFIRST, b1);
shiftOut(DATAOUT, SPICLK, MSBFIRST, b2);
shiftOut(DATAOUT, SPICLK, MSBFIRST, b3);
shiftOut(DATAOUT, SPICLK, MSBFIRST, b4);
delayMicroseconds(1);
digitalWrite(LDAC, LOW);
delayMicroseconds(1);
digitalWrite(LDAC, HIGH);
delayMicroseconds(1);
digitalWrite(SLAVESELECT, HIGH);
break;
}
case SETUP_INTERNAL_REGISTER:
{
byte b1 = B11111000; //padding at beginning of byte
//Serial.print("b1 ");
//Serial.println(b1, BIN);
byte b2 = B00000000;
//Serial.print("b2 ");
//Serial.println(b2, BIN);
byte b3 = B00000000;
//Serial.print("b2 ");
//Serial.println(b3, BIN);
byte b4 = B00000000|data;
//Serial.print("b4 ");
//Serial.println(b4, BIN);
//Serial.println();
digitalWrite(SLAVESELECT, LOW);
delayMicroseconds(1);
shiftOut(DATAOUT, SPICLK, MSBFIRST, b1);
shiftOut(DATAOUT, SPICLK, MSBFIRST, b2);
shiftOut(DATAOUT, SPICLK, MSBFIRST, b3);
shiftOut(DATAOUT, SPICLK, MSBFIRST, b4);
delayMicroseconds(1);
digitalWrite(SLAVESELECT, HIGH);
break;
}
case RESET:
{
byte b1 = B11110111; //padding at beginning of byte
//Serial.print("b1 ");
//Serial.println(b1, BIN);
byte b2 = B00000000;
//Serial.print("b2 ");
//Serial.println(b2, BIN);
byte b3 = B00000000;
//Serial.print("b2 ");
//Serial.println(b3, BIN);
byte b4 = B00000000|data;
//Serial.print("b4 ");
//Serial.println(b4, BIN);
//Serial.println();
digitalWrite(SLAVESELECT, LOW);
delayMicroseconds(1);
shiftOut(DATAOUT, SPICLK, MSBFIRST, b1);
shiftOut(DATAOUT, SPICLK, MSBFIRST, b2);
shiftOut(DATAOUT, SPICLK, MSBFIRST, b3);
shiftOut(DATAOUT, SPICLK, MSBFIRST, b4);
delayMicroseconds(1);
digitalWrite(SLAVESELECT, HIGH);
break;
}
case POWER:
{
byte b1 = B11110100; //padding at beginning of byte
//Serial.print("b1 ");
//Serial.println(b1, BIN);
byte b2 = B00000000;
//Serial.print("b2 ");
//Serial.println(b2, BIN);
byte b3 = B00000000;
//Serial.print("b2 ");
//Serial.println(b3, BIN);
byte b4 = B11111111;
//Serial.print("b4 ");
//Serial.println(b4, BIN);
//Serial.println();
digitalWrite(SLAVESELECT, LOW);
delayMicroseconds(1);
shiftOut(DATAOUT, SPICLK, MSBFIRST, b1);
shiftOut(DATAOUT, SPICLK, MSBFIRST, b2);
shiftOut(DATAOUT, SPICLK, MSBFIRST, b3);
shiftOut(DATAOUT, SPICLK, MSBFIRST, b4);
delayMicroseconds(1);
digitalWrite(SLAVESELECT, HIGH);
break;
}
}
}
void playNote(int note_, int velocity) {
unsigned int note = note_;
unsigned int voltage = 0;
if ((note >= 12) && (note < 24)) {
//Serial.println("note >= 12 && note < 24");
voltage = (voltage1)*((note - 12)/12.0);
} else if ((note >= 24) && (note < 36)) {
//Serial.println("note >= 24 && note < 36");
voltage = (voltage2 - voltage1)*((note - 24)/12.0) + voltage1;
} else if ((note >= 36) && (note < 48)) {
//Serial.println("note >= 36 && note < 48");
voltage = (voltage3 - voltage2)*((note - 36)/12.0) + voltage2;
} else if ((note >= 48) && (note < 60)) {
//Serial.println("note >= 48 && note < 60");
voltage = (voltage4 - voltage3)*((note - 48)/12.0) + voltage3;
} else if ((note >= 60) && (note < 72)) {
//Serial.println("note >= 60 && note < 72");
voltage = (voltage5 - voltage4)*((note - 60)/12.0) + voltage4;
}
note_on = true;
if ((velocity >= 1) && (velocity < 64)) { //normal note
write_dac(WRITE_UPDATE_N, ACC, 0);
write_dac(WRITE_UPDATE_N, CV, voltage);
write_dac(WRITE_UPDATE_N, GATE, 65535);