Subversion Repositories svn.mios32

Compare Revisions

Ignore whitespace Rev 1477 → Rev 1478

/trunk/apps/tutorials/029_keyboard_velocity/app.c
276,25 → 276,25
{
// determine pin number based on row/column
 
// each key has two contacts, I call them "early contact" and "final contact"
// each key has two contacts, I call them "break contact" and "make contact"
// the assignments can be determined by setting DEBUG_VERBOSE_LEVEL to 2
 
// default: linear addressing (e.g. Fatar Keyboards?)
// the final contacts are at row 0, 2, 4, 6, 8, 10, 12, 14
// the early contacts are at row 1, 3, 5, 7, 9, 11, 13, 15
// the make contacts are at row 0, 2, 4, 6, 8, 10, 12, 14
// the break contacts are at row 1, 3, 5, 7, 9, 11, 13, 15
 
// determine key number:
int key = 8*(row / 2) + column;
 
// check if key is assigned to an "early contact"
u8 early_contact = (row & 1); // odd numbers
// check if key is assigned to an "break contact"
u8 break_contact = (row & 1); // odd numbers
 
// determine note number (here we could insert an octave shift)
int note_number = key + 36;
 
// reference to early and final pin
int pin_final = (row)*8 + column;
int pin_early = (row+1)*8 + column;
// reference to break and make pin
int pin_make = (row)*8 + column;
int pin_break = (row+1)*8 + column;
 
// ensure valid note range
if( note_number > 127 )
303,8 → 303,8
note_number = 0;
 
#if DEBUG_VERBOSE_LEVEL >= 2
DEBUG_MSG("row=%d, column=%d, depressed=%d --> key=%d, early_contact:%d, note_number=%d\n",
row, column, depressed, key, early_contact, note_number);
DEBUG_MSG("row=%d, column=%d, depressed=%d --> key=%d, break_contact:%d, note_number=%d\n",
row, column, depressed, key, break_contact, note_number);
#endif
 
// determine key mask and pointers for access to combined arrays
313,9 → 313,9
u8 *note_off_sent = (u8 *)&din_note_off_sent[key / 8];
 
 
// early contacts don't send MIDI notes, but they are used for delay measurements,
// break contacts don't send MIDI notes, but they are used for delay measurements,
// and they release the Note On/Off debouncing mechanism
if( early_contact ) {
if( break_contact ) {
if( depressed ) {
*note_on_sent &= ~key_mask;
*note_off_sent &= ~key_mask;
340,11 → 340,11
if( !(*note_on_sent & key_mask) ) {
*note_on_sent |= key_mask;
 
// determine timestamps between early and final contact
u16 timestamp_early = din_activated_timestamp[pin_early];
u16 timestamp_final = din_activated_timestamp[pin_final];
// determine timestamps between break and make contact
u16 timestamp_break = din_activated_timestamp[pin_break];
u16 timestamp_make = din_activated_timestamp[pin_make];
// and the delta delay (IMPORTANT: delay variable needs same resolution like timestamps to handle overrun correctly!)
s16 delay = timestamp_final - timestamp_early;
s16 delay = timestamp_make - timestamp_break;
 
int velocity = 127;
if( delay > keyboard_delay_fastest ) {
/trunk/apps/tutorials/029_keyboard_velocity/README.txt
24,10 → 24,10
The keyboard of a Korg microKONTROL has been used for testing.
Each key has two contacts: one which closes early when you are starting to press
the key, and another contact which closes when the key is completely pressed.
(I call them "early" and "final" contact below)
They are called "break" and "make" contact below.
 
In order to determine the velocity, we've to measure the time between the closing
early and final contact. Via experiments I found out, that the minimum delay
break and make contact. Via experiments I found out, that the minimum delay
(key pressed fast) is ca. 1.2 mS, and the maximum delay is ca. 60 mS
 
Since a common SRIO scan is only performed each mS, which is too slow for high
82,17 → 82,17
number on each key press, the results were:
 
-------------------------------------------------------------------------------
// the early contacts are at row 0, 2, 4, 6, 8, 10, 12, 14
// the final contacts are at row 1, 3, 5, 7, 9, 11, 13, 15
// the make contacts are at row 0, 2, 4, 6, 8, 10, 12, 14
// the break contacts are at row 1, 3, 5, 7, 9, 11, 13, 15
-------------------------------------------------------------------------------
 
The "early contacts" don't lead to a note event, we only need them later
The "break contacts" don't lead to a note event, we only need them later
to calculate the delay:
 
-------------------------------------------------------------------------------
u8 early_contact = (row & 1); // odd numbers
// we ignore button changes on the early contacts:
if( early_contact )
u8 break_contact = (row & 1); // odd numbers
// we ignore button changes on the break contacts:
if( break_contact )
return;
-------------------------------------------------------------------------------
 
105,8 → 105,8
// determine key number:
int key = 8*(row / 2) + column;
 
// check if key is assigned to an "early contact"
u8 early_contact = !(row & 1); // even numbers
// check if key is assigned to an "break contact"
u8 break_contact = (row & 1); // odd numbers
 
// determine note number (here we could insert an octave shift)
int note_number = key + 36;
131,10 → 131,21
 
For debouncing the keys a note based locking mechanism has been implemented:
- whenever a key plays a Note On event, no additional Note On will be played
until the "early contact" has been released
until the "break contact" has been released
- whenever a key plays a Note Off event, no additional Note Off will be played
until the "early contact" has been released
until the "break contact" has been released
 
Enjoy your keyboard! :-)
 
===============================================================================
 
Please note: the MIDIbox KB application contains a more sophisticated
scanning routine which also considers different keyboard types (e.g. Fatar keyboards)
 
-> see http://www.ucapps.de/midibox_kb.html
Sources are located under $MIOS32_PATH/apps/controllers/midibox_kb_v1/src/keyboard.c
 
This scanning routine uses a special optimisation algorithm which allows to scan
a keyboard with 65 uS (as long as no key is pressed)
 
===============================================================================