I've added some functionality to the MIDI2VC code. The problem that needed fixing was when multiple MIDI keys where pressed simultaneously, this could confuse the system. What I've added now is a priority system, where the lowest key pressed is the one the generates an output voltage. This is similar to what is used in the Mini Moog. In the future, I might implement a function for choosing one of several priority systems, but I'll need a PIC with more IO's to do that.
I can't test this functionality very well right now, since MIDI Ox only let's me play two simultaneous keys, and I haven't gotten my real MIDI keyboard to work with the MIDI2VC yet. I have tried sending manual MIDI keys, using UART, and that works as expected.
Here are the updated functions.
//***********************************************************
//**************Function processUARTBuffer*******************
//Interprets UARTBuffer, toggles LED and sends appropiate
//I2C data to DAC
//***********************************************************
void processUARTBuffer(int UARTBufferF[])
{
extern int i2cData[];
extern int MIDISimKeysPressed;
const int DACLookupTable[127] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x017, 0x072, 0x0C2, 0x116, 0x169, 0x1B9, 0x20C, 0x25F, 0x2B0, 0x305, 0x356, 0x3A9, 0x3FC, 0x44D, 0x4A2, 0x4F5, 0x547, 0x5C7, 0x5EF, 0x63E, 0x691, 0x6E7, 0x739, 0x78E};
int DACValue;
int DACValue;
//If UART symbol is MIDI "Note on", light LED and
//send lowest data in MIDI key bucket to DAC
if (((UARTBufferF[0] & 0xF0) == 0x90) && (UARTBufferF[2] != 0x00))
{
//Keeps track of number of keys simultaneously pressed
MIDISimKeysPressed++;
pushMIDISimKeysBucket(UARTBufferF[1]);
DACValue = DACLookupTable[isLowestInMIDISimKeysBucket()];
i2cData[1] = (DACValue & 0xFF);
i2cData[0] = ((DACValue & 0x0F00) >> 8);
lightLED();
i2cDataToBeSent = 1;
}
//If UART symbol is MIDI "Note off", check if there are
//other notes in bucket and send their lowest data to DAC, otherwise
//turn off LED and send zeros to DAC
else if (((UARTBufferF[0] & 0xF0) == 0x80) || (UARTBufferF[2] == 0x00))
{
MIDISimKeysPressed--;
popMIDISimKeysBucket(UARTBufferF[1]);
if (MIDISimKeysPressed == 0)
{
i2cData[0] = 0x00;
i2cData[1] = 0x00;
unlightLED();
i2cDataToBeSent = 1;
}
else if (MIDISimKeysPressed > 0)
{
DACValue = DACLookupTable[isLowestInMIDISimKeysBucket()];
i2cData[1] = (DACValue & 0xFF);
i2cData[0] = ((DACValue & 0x0F00) >> 8);
i2cDataToBeSent = 1;
}
}
return;
}
//***********************************************************
//**************Function pushMIDISimKeysBucket***************
//Function for pushing a MIDI key int into the MIDI bucket.
//The MIDI bucket is a data sctructure that holds a number
//of ints. The pushed int is placed in the first available
//empty array slot, in no other order. Empty slots are valued
//-1, since 0 is a valid key value.
//Each value in the bucket (except -1) is unique, if not, there
//is something wrong. No error checking for this is implemented.
//***********************************************************
void pushMIDISimKeysBucket(int midiKey)
{
extern int MIDISimKeysBucket[];
//place MIDI key value in first -1 (empty) instance
int i = 0;
while (i < MIDISimKeysBucketSize)
{
if (MIDISimKeysBucket[i] == -1)
{
MIDISimKeysBucket[i] = midiKey;
i = MIDISimKeysBucketSize;
}
else
{
i++;
}
}
return;
}
//***********************************************************
//**************Function popMIDISimKeysBucket***************
//Function for removing value from bucket.
//***********************************************************
void popMIDISimKeysBucket(int midiKey)
{
extern int MIDISimKeysBucket[];
//Find value in array and replace with -1
//If no value is found, do nothing
int i = 0;
while (i < MIDISimKeysBucketSize)
{
if (MIDISimKeysBucket[i] == midiKey)
{
MIDISimKeysBucket[i] = -1;
i = MIDISimKeysBucketSize;
}
else
{
i++;
}
}
return;
}
//***********************************************************
//**************Function isLowestInMIDISimKeysBucket*********
//Returns the lowest value in the bucket
//***********************************************************
int isLowestInMIDISimKeysBucket()
{
extern int MIDISimKeysBucket[];
int lowestKey = 0x7f; //Highest legal MIDI key
//Finds lowest key, that isn't -1, in bucket
int i = 0;
while (i < MIDISimKeysBucketSize)
{
if ((MIDISimKeysBucket[i] < lowestKey) && (MIDISimKeysBucket[i] > -1))
{
lowestKey = MIDISimKeysBucket[i];
}
else
{
i++;
}
}
return lowestKey;
}