#define PIN_D0 0
#define PIN_D1 1
#define PIN_D2 2
#define PIN_D3 3
#define HOW_MANY_MUXES 6
#define MUX_CHANNELS 16
int anMinReadData[HOW_MANY_MUXES * MUX_CHANNELS ] = { 0 };
int anMaxReadData[HOW_MANY_MUXES * MUX_CHANNELS ] = { 0 };
int anReadData[ HOW_MANY_MUXES * MUX_CHANNELS ];
int8_t anKeyStates[ HOW_MANY_MUXES * MUX_CHANNELS ] = { 0 };
void setup()
{
// D0..D3 to the mux address pins
pinMode( PIN_D0, OUTPUT ); // configure pings
pinMode( PIN_D1, OUTPUT );
pinMode( PIN_D2, OUTPUT );
pinMode( PIN_D3, OUTPUT );
// we want 12 bit resolution
analogReadResolution(12);
// and NO averaging because it is VERY slow with averaging
// this setting allows to go down to 6usec per analogRead()
analogReadAveraging(1);
// initially
// write some heuristic value to min/ max
// these will be adjusted later. in final product you might
// read those from non-volatile memory from previous runs
for( int i = 0; i < MUX_CHANNELS; i++ )
{
for( int j = 0; j < HOW_MANY_MUXES; j++ )
{
int index = i + j * MUX_CHANNELS ;
anMinReadData[ index ] = 2048 - 100; // middle of AD scale minus 100
anMaxReadData[ index ] = 2048 + 100; // middle of AD scale plus 100
}
}
}
void setMux( int addr )
{
digitalWriteFast( PIN_D0, ( addr & 1 ) ? HIGH : LOW );
digitalWriteFast( PIN_D1, ( addr & 2 ) ? HIGH : LOW );
digitalWriteFast( PIN_D2, ( addr & 4 ) ? HIGH : LOW );
digitalWriteFast( PIN_D3, ( addr & 8 ) ? HIGH : LOW );
}
// the code below assumes that you have muxes connected to
// consecutive analog inputs PIN_A0, A1, A2 and so on.
void loop()
{
// this reads ALL data from ALL muxes
for( int i = 0; i < MUX_CHANNELS; i++ )
{
setMux( i );
delayMicroseconds( 1 ); // settling time required for mux output to stabilize
for( int j = 0; j < HOW_MANY_MUXES; j++ )
{
int index = i + j * MUX_CHANNELS ;
anReadData[ index ] = analogRead( PIN_A0 + j );
// store minimums
if( anMinReadData[ index ] < anReadData[ index ] )
{
anMinReadData[ index ] = anReadData[ index ];
}
// store maximums
if( anMaxReadData[ index ] > anReadData[ index ] )
{
anMaxReadData[ index ] = anReadData[ index ];
}
int nMinMaxDistance = anMaxReadData[ index ] - anMinReadData[ index ];
// ON level is 2/3 of the maximum down key travel distance (i.e. 1/3 from min)
int nKeyOnLevel = anMinReadData[ index ] + nMinMaxDistance / 3;
// OFF level is 1/3 of the maximum down key travel distance (i.e. 1/3 from max)
int nKeyOffLevel = anMaxReadData[ index ] - nMinMaxDistance / 3;
if( anKeyStates[ index ] == 0 /* key off */ && anReadData[ index ] < nKeyOnLevel )
{
anKeyStates[ index ] = 1;
int8_t velocity = 100; //calculate velocify here (I leave it for the other time)
usbMIDI.sendNoteOn( index, velocity, 1 /*channel*/ );
}
else
if( anKeyStates[ index ] == 1 /* key on */ && anReadData[ index ] > nKeyOffLevel )
{
anKeyStates[ index ] = 0;
usbMIDI.sendNoteOff( index, 0, 1 /*channel*/ );
}
}
}
}