//MiDi variables
#define noteon 0x90 //Note On Byte
#define noteoff 0x80 //Note Off Byte
#define bufferlengh 168 //Bufferlengh for MiDi messages
#define transpose 20 //Transpose of MiDi notes
uint8_t midibuffer [bufferlengh]; //Buffer for MiDi messages
uint8_t midiwrite = 0; //MiDi buffer writepointer
uint8_t midiread = 0; //MiDi buffer readpointer
//scan process variables
#define idle 0
#define notestart 1
#define midisend 2
#define midicomplete 3
#define midioff 4
volatile uint16_t velocitycount = 0; //Counter to built velocity
//Velocity counter for all keys
uint16_t note_velocity [56] =
{
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,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0
};
//State memory for all keys
uint8_t note_state [56] =
{
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,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0
};
//Velocity couter increments every 250µs
ISR (TIMER0_OVF_vect)
{
velocitycount++;
}
void scan_keyboard (void)
{
uint8_t buffer1 = 0, buffer2 = 0, scanloop = 0, zeiger = 0, i = 0;
uint16_t buffer3 = 0;
/* Outer loop - Pulls down the lines after the diodes */
for(scanloop=0;scanloop<8;scanloop++)
{
buffer1 = PINA;
buffer2 = PINC;
PORTB = ~(1<<(scanloop+1));
//Inner loop readout start velocity and end velocity lines and generate MiDi messages
for(i=0;i<7;i++)
{
//Pointer to actual note
zeiger = i*8 + scanloop;
//Scan velocity start first sample
if((buffer1 & (1<<i)) == 0)
{
if(note_state[zeiger] == idle) //Velocity counting begins
{
note_state[zeiger] = notestart;
note_velocity[zeiger] = velocitycount;
}
}
else
{
/*MiDi sent, back to idle or send note off
when key pressed a little and go back to off state
the mode go back to idle.
When a complete scan was processed a Note On velocity 0 was sent */
if(note_state[zeiger] == notestart)
{
note_state[zeiger] = idle;
note_velocity[zeiger] = 0;
}
if(note_state[zeiger] == midicomplete)
{
note_state[zeiger] = midioff;
note_velocity[zeiger] = 0;
}
}
//Velocity Stop second sample generate MiDi
if((buffer2 & (1<<i)) == 0)
{
if(note_state[zeiger] == notestart)
{
buffer3 = velocitycount - note_velocity[zeiger];
if(buffer3 > 127)
{
note_velocity[zeiger] = 1; //Timed out, velocity = 1
}
else
{
note_velocity[zeiger] = 128 - buffer3; //Otherwise calc velocity
}
note_state[zeiger] = midisend; //Send Note On frame
}
}
}
}
}
void make_midi (void)
{
uint8_t i = 0;
for(i=0;i<56;i++)
{
switch (note_state[i])
{
//Note on with velocity xyz is to send
case midisend:
midibuffer[midiwrite++] = noteon;
if(midiwrite>bufferlengh){ midiwrite=0; }
midibuffer[midiwrite++]= i+transpose;
if(midiwrite>bufferlengh){ midiwrite=0; }
midibuffer[midiwrite++]= note_velocity[i];
if(midiwrite>bufferlengh){ midiwrite=0; }
note_state[i]=midicomplete;
break;
//Note on with velocity 0 is to send = Note off
case midioff:
midibuffer[midiwrite++] = noteon;
if(midiwrite>bufferlengh){ midiwrite=0; }
midibuffer[midiwrite++]= i+transpose;
if(midiwrite>bufferlengh){ midiwrite=0; }
midibuffer[midiwrite++]= 0;
if(midiwrite>bufferlengh){ midiwrite=0; }
note_state[i]=idle;
break;
}
}
}