Commit 237632ac authored by Knut Aldrin's avatar Knut Aldrin

Merge branch 'running-status' into 'master'

Running status

Code to handle running status.

See merge request !1
parents fa93d619 0070f623
......@@ -3,7 +3,7 @@
*
* Created: 19.08.2014 23:32:07
* Author: Snorre
*/
*/
#include <inttypes.h>
......@@ -26,151 +26,205 @@ uint8_t midi_current_byte;
enum {
FREE,
NOTE_ON,
NOTE_OFF
FREE,
NOTE_ON,
NOTE_OFF,
IGNORE
} midi_state;
void midi_init(uint8_t channel, note_t* notes_struct, midi_channel_t* channel_struct)
{
midi_notes = notes_struct;
midi_channel = channel_struct;
midi_channel->active_notes = 0;
midi_channel->channel = channel;
midi_current_byte = 0;
for(uint8_t i = 0; i << TESLA_MAX_CHANNELS; i++){
midi_notes[i].age = 0;
midi_notes[i].change = 0;
midi_notes[i].update = 0;
midi_notes[i].on = 0;
midi_notes[i].tesla_channel = i;
}
midi_notes = notes_struct;
midi_channel = channel_struct;
midi_channel->active_notes = 0;
midi_channel->channel = channel;
midi_current_byte = 0;
for(uint8_t i = 0; i << TESLA_MAX_CHANNELS; i++){
midi_notes[i].age = 0;
midi_notes[i].change = 0;
midi_notes[i].update = 0;
midi_notes[i].on = 0;
midi_notes[i].tesla_channel = i;
}
}
uint8_t parse_status( char input ) {
// Status byte?
if( input & MIDI_STATUS_bm ) {
if( input == MIDI_clock_bm ) {
// TODO: Implement midi clock handling
}
// Check that they want to speak to us
else if( ( input & MIDI_CHANNEL_MASK ) == midi_channel->channel ) {
switch ( input & MIDI_STATUS_MASK ) {
case MIDI_note_off_gc:
midi_state = NOTE_OFF;
midi_current_byte = 0;
break;
case MIDI_note_on_gc:
midi_state = NOTE_ON;
midi_current_byte = 0;
break;
default:
// Not supported yet
midi_state = IGNORE;
midi_current_byte = 0;
break;
}
}
else {
// Not to us, ignore
midi_state = IGNORE;
midi_current_byte = 0;
}
// Return 1 cause we intercepted a status byte
return 1;
}
else {
// Not a status byte
return 0;
}
}
void parse_midi(char input)
{
switch (midi_state)
{
case FREE:
//check channel
if ((input & MIDI_CHANNEL_MASK) == (midi_channel->channel)){
switch (input & MIDI_STATUS_MASK){
case MIDI_note_off_gc:
midi_state = NOTE_OFF;
midi_current_byte = 0;
break;
case MIDI_note_on_gc:
midi_state = NOTE_ON;
midi_current_byte = 0;
break;
}
}
break;
case NOTE_ON:
if (!(input & MIDI_STATUS_bm)){
if (midi_current_byte == 1){
//store note
midi_buffer[midi_current_byte++] = input;
} else if (midi_current_byte == 2) {
//store velocity
midi_buffer[midi_current_byte++] = input;
//find free channel & update
midi_add_note(midi_buffer[0],midi_buffer[1]);
midi_state = FREE;
} else {
tesla_panic();
}
} else {
//evaluate if single-byte-interrupting package, else abort
}
break;
case NOTE_OFF:
if (!(input & MIDI_STATUS_bm)){
if (midi_current_byte == 1){
//store note
midi_buffer[midi_current_byte++] = input;
} else if (midi_current_byte == 2) {
//store velocity
midi_buffer[midi_current_byte++] = input;
midi_clear_note(midi_buffer[0],midi_buffer[1]);
midi_state = FREE;
} else {
tesla_panic();
}
} else {
//check for interrupting frame, panic otherwise
}
break;
}
}
switch (midi_state)
{
case FREE:
case IGNORE:
//check channel
parse_status( input );
break;
case NOTE_ON:
// Check for status bytes
if( parse_status( input ) ) {
break;
}
if (!(input & MIDI_STATUS_bm)){
if (midi_current_byte == 1){
//store note
midi_buffer[midi_current_byte++] = input;
} else if (midi_current_byte == 2) {
//store velocity
midi_buffer[midi_current_byte++] = input;
// Zero-velocity input == NOTE_OFF
if( input == 0 ) {
midi_clear_note( midi_buffer[0], 127 ); // Release with full force
}
else {
//find free channel & update
midi_add_note(midi_buffer[0],midi_buffer[1]);
}
// Get ready for next note
midi_current_byte = 0;
} else {
tesla_panic();
}
} else {
//evaluate if single-byte-interrupting package, else abort
}
break;
case NOTE_OFF:
// Check for status bytes
if( parse_status( input ) ) {
break;
}
if (!(input & MIDI_STATUS_bm)){
if (midi_current_byte == 1){
//store note
midi_buffer[midi_current_byte++] = input;
} else if (midi_current_byte == 2) {
//store velocity
midi_buffer[midi_current_byte++] = input;
midi_clear_note(midi_buffer[0],midi_buffer[1]);
// Get ready for next note
midi_current_byte = 0;
} else {
tesla_panic();
}
} else {
//check for interrupting frame, panic otherwise
}
break;
default:
// WTF? Unknown state
tesla_panic();
}
}
void midi_add_note(uint8_t note, uint8_t velocity){
uint8_t n, result = 0, max_age = 0;
//check if note already is on
for (n = 0; n < TESLA_MAX_CHANNELS; n++){
if ((midi_notes[n].note == note) && (midi_notes[n].on)){
midi_notes[n].velocity = velocity;
midi_notes[n].update = 1;
return;
}
}
//find free channel
for (n = 0; n < TESLA_MAX_CHANNELS; n++){
if (!(midi_notes[n].on)){
midi_notes[n].on = 1;
midi_notes[n].note = note;
midi_notes[n].velocity = velocity;
midi_notes[n].change = 1;
return;
}
}
//if no free channels, find oldest note and overwrite
for (n = 0; n < TESLA_MAX_CHANNELS; n++){
if (midi_notes[n].age > max_age){
result = n;
max_age = midi_notes[n].age;
}
}
midi_notes[result].on = 1;
midi_notes[result].note = note;
midi_notes[result].velocity = velocity;
midi_notes[result].change = 1;
uint8_t n, result = 0, max_age = 0;
//check if note already is on
for (n = 0; n < TESLA_MAX_CHANNELS; n++){
if ((midi_notes[n].note == note) && (midi_notes[n].on)){
midi_notes[n].velocity = velocity;
midi_notes[n].update = 1;
return;
}
}
//find free channel
for (n = 0; n < TESLA_MAX_CHANNELS; n++){
if (!(midi_notes[n].on)){
midi_notes[n].on = 1;
midi_notes[n].note = note;
midi_notes[n].velocity = velocity;
midi_notes[n].change = 1;
return;
}
}
//if no free channels, find oldest note and overwrite
for (n = 0; n < TESLA_MAX_CHANNELS; n++){
if (midi_notes[n].age > max_age){
result = n;
max_age = midi_notes[n].age;
}
}
midi_notes[result].on = 1;
midi_notes[result].note = note;
midi_notes[result].velocity = velocity;
midi_notes[result].change = 1;
}
void midi_clear_note(uint8_t note, uint8_t velocity){
uint8_t n;
//find note
for (n = 0; n < TESLA_MAX_CHANNELS; n++){
if ((midi_notes[n].note == note) && (midi_notes[n].on)){
midi_notes[n].on = 0;
midi_notes[n].velocity = velocity;
midi_notes[n].change = 1;
return;
}
}
}
\ No newline at end of file
uint8_t n;
//find note
for (n = 0; n < TESLA_MAX_CHANNELS; n++){
if ((midi_notes[n].note == note) && (midi_notes[n].on)){
midi_notes[n].on = 0;
midi_notes[n].velocity = velocity;
midi_notes[n].change = 1;
return;
}
}
}
......@@ -31,4 +31,6 @@ void midi_init(uint8_t channel, note_t* notes_struct, midi_channel_t* channel_st
void parse_midi(char input);
uint8_t parse_status( char input );
#endif /* MIDI_H_ */
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment