Commit b1b08dbb authored by Snorre Nilssen Vestli's avatar Snorre Nilssen Vestli
Browse files

wipe and add tesla-midi-19

parent 1442109f
Loading
Loading
Loading
Loading

TeslaMidi.atsuo

deleted100644 → 0
−19 KiB

File deleted.

TeslaMidi/MIDI.c

deleted100644 → 0
+0 −230
Original line number Diff line number Diff line
/*
 * MIDI.c
 *
 * Created: 19.08.2014 23:32:07
 *  Author: Snorre
 */

#include <inttypes.h>

#include "MIDI.h"
#include "MIDIdefs.h"
#include "panic.h"
#include "tesladefs.h"

void midi_add_note(uint8_t note, uint8_t velocity);
void midi_clear_note(uint8_t note, uint8_t velocity);



note_t* midi_notes;
midi_channel_t* midi_channel;

char midi_buffer[3];
uint8_t midi_current_byte;



enum {
  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;
  }

}

uint8_t parse_status( char input ) {
  // Status byte?
  if( input & MIDI_STATUS_bm ) {

    if( input == MIDI_clock_gc ) {
      // 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:
    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;

}

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;
    }
  }

}

TeslaMidi/MIDI.h

deleted100644 → 0
+0 −36
Original line number Diff line number Diff line
/*
 * MIDI.h
 *
 * Created: 19.08.2014 23:34:37
 *  Author: Snorre
 */ 


#ifndef MIDI_H_
#define MIDI_H_


typedef struct note_struct{
	uint8_t change;
	uint8_t update;
	uint8_t note;
	uint8_t velocity;
	uint8_t on;
	uint8_t age;
	uint8_t tesla_channel;
} note_t;


typedef struct midi_channel_struct{
	uint8_t channel;
	uint8_t active_notes;
} midi_channel_t;


void midi_init(uint8_t channel, note_t* notes_struct, midi_channel_t* channel_struct);

void parse_midi(char input);

uint8_t parse_status( char input );

#endif /* MIDI_H_ */
 No newline at end of file

TeslaMidi/MIDIdefs.h

deleted100644 → 0
+0 −24
Original line number Diff line number Diff line
/*
 * MIDIdefs.h
 *
 * Created: 24.08.2014 22:52:23
 *  Author: Snorre
 */


#ifndef MIDIDEFS_H_
#define MIDIDEFS_H_

#define MIDI_STATUS_bm (1 << 7)

#define MIDI_STATUS_MASK (0b1111 << 4)
#define MIDI_CHANNEL_MASK (0b1111)

#define MIDI_note_on_gc (0b1001 << 4)
#define MIDI_note_off_gc (0b1000 << 4)
#define MIDI_aftertouch_gc ( 0b1010 << 4 )
#define MIDI_clock_gc (0xf8)



#endif /* MIDIDEFS_H_ */

TeslaMidi/TeslaMidi.c

deleted100644 → 0
+0 −93
Original line number Diff line number Diff line
/*
 * TeslaMidi.c
 *
 * Created: 18.08.2014 21:05:01
 *  Author: SNV
 */ 


#include <avr/io.h>

#include "MIDI.h"
#include "panel_io.h"
#include "watchdog.h"
#include "clock.h"
#include "uart.h"

#include "tesla_io.h"
#include "tesladefs.h"

int main(void)
{
	uint8_t error;
	char uartchar;
	
	note_t notes[TESLA_MAX_CHANNELS];
	midi_channel_t midi_channel;
	
	//TESLA IO SAFE
	tesla_init();
	
	
	clock_init();
	
	//PANEL IO INIT
	panel_init();
	
	//midi UART init
	uart_init();
	
	//WATCHDOG INIT
	error = watchdog_init();
	if (error){
		//watchdog tripped, set IO appropriately and hold.
		panel_set_led_on(PANEL_ERROR);
	}
	
	//MIDI INIT
	midi_init(1,notes,&midi_channel);
	
	//WAIT FOR READY
	panel_wait_run();
	
	//WATCHDOG_START
	watchdog_start();
	
	//CARRIER_START
	for (uint8_t i = 0; i < 2 ; i++){
		tesla_channel_enable(i);
	}
	tesla_carrier_enable();
	
    while(1)
    {
		//READ PANEL IO
		panel_update();
		
		if (uart_read(&uartchar)){
			//POLL MIDI USART 
			parse_midi(uartchar);
		
		
			//HANDLE WAVE IO
			for (uint8_t i = 0; i < TESLA_MAX_CHANNELS; i++){
				if (notes[i].change){
					notes[i].change = 0;
					if (notes[i].on){
						// turn on relevant channel
						tesla_channel_play(notes[i].tesla_channel, notes[i].note, panel_get_level());
					} else {
						//turn off relevant channel
						tesla_channel_stop(notes[i].tesla_channel);
					}
				
				} /*else if (notes[i].update){
					//TODO: Handle renewed velocity
				
				}*/
			}
		}
		// TODO: handle updated level pot
		watchdog_pet();
    }
}
 No newline at end of file
Loading