// MIDI Controller 
// Andrew Rogers
// Scott Stroupe

/********************************************
 *	MIDI Specifications
 *
 *	Status Byte:		0x80 - 0xFF
 *		- Voice Byte: 	0x80 - 0xEF
 *	Message Byte:	0x00 - 0x7F
 *
 *	MIDI serial data rate: 31.25 kHz +/- 1%
 *		- 1 start bit
 *		- 1 stop bit
 *		- 8 data bits
 *
 ********************************************/

#include 
#include 

// Upper 4-bit segment of status byte
// "COMMAND"
// (there are other, but we only use these)
#define NOTE_ON		0x90
#define NOTE_OFF	0x80

// Lower 4-bit segment of status byte
// "CHANNEL"
// (0-F correspond to 1-16)
#define CHANNEL_1	0x00
#define CHANNEL_2	0x01

// Other MIDI definitions
#define MIDI_MAX	0x7F	// 127
#define MIDI_MIN	0x00	// 0
#define MIDDLE_C	0x3C

// Boolean definitions
#define TRUE		1
#define FALSE		0

#define MSG_SIZE	3

// Global variables
unsigned char sendingMIDI;
unsigned char packet[MSG_SIZE];
unsigned char nextByte;

void serialDataHandler ( void ) interrupt 4 using 2 {
	// handle outgoing MIDI data -- never any incoming data
	if (TI) {
		sendingMIDI = TRUE;
		TI = FALSE;
		if (nextByte >= MSG_SIZE) {
			sendingMIDI = FALSE;
			return;
		}
		SBUF = packet[nextByte];
		nextByte++;
	} // else ignore the interrupt -- shouldn't be receiving
}

void startNote(unsigned char note, unsigned char channel, unsigned char velocity) {
	while (sendingMIDI) { /* loop */ }
	packet[0] = NOTE_ON | channel;
	packet[1] = note;
	packet[2] = velocity;
	nextByte = 0;
	TI = TRUE;	
}

void stopNote(unsigned char note, unsigned char channel, unsigned char release) {
	while (sendingMIDI) { /* loop */ }
	packet[0] = NOTE_OFF | channel;	
	packet[1] = note;
	packet[2] = release;
	nextByte = 0;
	TI = TRUE;
}


void initializeMIDI() {

	// set up RS-232 controller to handle MIDI output

	SCON |= 0x50;	// 0101 0000 b
	PCON |= 0x80;	// 1000 0000 b

	TMOD = 0x20;	// 0010 0000 b
	TH1  = 252;		// baud rate = 31.25 kHz; w/ext clk @ 24 MHz										
	TR1  = 1;		// run the timer

	IE   = 0x90;	// Enable serial interrupt (4)

	EA	= TRUE;

	sendingMIDI = FALSE;	
}


void main() {
	// play notes 0-127 in succession, then back down

	long i, note;

	initializeMIDI();

	while (1) {
		
		for(note = 0; note <= MIDI_MAX; note++){

			startNote(note, CHANNEL_1, MIDI_MAX);
			for (i = 0; i < 20000; i++);
			stopNote(note, CHANNEL_1, MIDI_MAX);	
			for (i = 0; i < 20000; i++);

		}
		for(note = MIDI_MAX - 1; note >=0; note--){

			startNote(note, CHANNEL_1, MIDI_MAX);
			for (i = 0; i < 20000; i++);
			stopNote(note, CHANNEL_1, MIDI_MAX);	
			for (i = 0; i < 20000; i++);

		}

	}
}