In the datasheet of the E 510 Chip one velocitiy count is 250µs.
Maximum length for whole velocity is 125 x 250µs = 31,25ms.
Just spotted your earlier post... I'd not seen it when I looked up the same thing.
Follow along with the video below to see how to install our site as a web app on your home screen.
Note: This feature may not be available in some browsers.
In the datasheet of the E 510 Chip one velocitiy count is 250µs.
Maximum length for whole velocity is 125 x 250µs = 31,25ms.
I've implemented Your idea in my source code an that will work much better than mine.With enough memory, you could have a variable for each key and store the value from one of the timers as a key press is detected?
When the second contact is detected, read the timer again and calculate the time, plus setting a bit to show the key has been read.
That avoids having to count separately for every key.
Not practical on a small device but with a large RAM one, a full size integer array only takes a fraction of the RAM.
//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;
}
}
}
Like that solution, but the calculation , ? 1st down read say [004] 2nd read[003] ... has key been fast 001 or slow 128 ?When the second contact is detected, read the timer again and calculate the time,
That's why I suggested a 16 bit timer and 16 bit array integer for the time captures to be stored when the first key contact is detected.Like that solution, but the calculation , ? 1st down read say [004] 2nd read[003] ... has key been fast 001 or slow 128 ?
128 is not allowed, because the MSB bit is set in this case.has key been fast 001 or slow 128 ?
One 16 Bit Array + an 8 Bit Array for state with 56 elements is enough.( A) you need 3 8x8 arrays , (B) an 8(7) bit count for each key (C) an interrupt timer to start the scan regardless of how long the scan overhead took
Some errors have to be intercept:
Contact 1 closed and opened without closing contact 2.
Contact 2 closing opens and closes again without opening of contact 1.
Closing contact 2 without closing contact 1 would show an hardware error of keybed.
And not allowed values for the velocity parameter, of course.
my point was the timer has counted 128 steps between start and stop contacts .it started at 004 and finished at 003 . what is the velocity value ? don't think giving a explanation of Midi velocity bytes is under debate yet ..128 is not allowed, because the MSB bit is set in this case.
MJ Got all that ... i questioned wkrug post re a free running counter, so a negative number is possible , unless you always subtract the lowest value from the highest counter valueWhen the second contact closes the stored value of the key would be subtracted from the actual counter value and stored back into the 16 Bit Array.
Yes but any value over 7F will be 'wrong' if consider the 8 bit byte 0- 127 a positive velocity value .. so what if the result of the subtraction ( finish-start ) is say h' 8Byou cannot get a negative result, even if the timer overflows between the first and second captures.
So the pressing was very soft and a velocity of 1 will be generated.so what if the result of the subtraction ( finish-start ) is say h' 8B
So a overrun appears an a velocity of 1 was generated.Started 004 and finished at 003
Can be appear when the player touch a key, but don't pressing down complete.Contact 1 closed and opened without closing contact 2.
Can be appear when the player touch a key, but don't pressing down complete.
So no note on should be applied and the scanning for this key has go to idle.
I took this idea from the old E510.Contact 1 closed and opened without closing contact 2