/* Copyright (C) 1986 by M. J. Shannon, Jr.
** Permission to distribute for non-commercial uses granted as long as this
** notice is retained.  Violators will be prosecuted.
*/

#include	"mpu.h"

/* midi_lengths[]:
**	lengths of the MIDI voice messages after reading the 2nd byte of the
**	message.
*/

static short midi_lengths[8] =
{
	1,	/* 80: Note Off */
	1,	/* 90: Note On */
	1,	/* A0: Note After Touch */
	1,	/* B0: Control Change */
	0,	/* C0: Program Change */
	0,	/* D0: Channel After Touch */
	1,	/* E0: Pitch Wheel */
	0	/* F0: "Can't Happen" */
};

/* mpu_read(char *):
**	read a response from a midi device.  The response is stored in the
**	passed character buffer, and the length of the response is returned.
**	The buffer must be large enough to hold the response.
*/

int
mpu_read(bp)
register unsigned char *bp;
{
	register int length = 0;
	register unsigned char data;

	if (mpu_dsr() && mpu_dsr())	/* timed out waiting for a response? */
		return (length);
	bp[length++] = data = mpu_dget();	/* store the input */
	if (data < 0xF0)			/* time followed by midi data */
	{
		static unsigned char midi_rs = 0; /* last rec'd running stat */
		static int mmlen;		/* and # of following bytes */
		register int i;
		unsigned char vm;

		vm = mpu_dget();		/* get midi voice message */
		if (vm < 0x80)			/* midi running status? */
			bp[length++] = midi_rs;	/* yes, store the old status */
		bp[length++] = vm;		/* store the data */
		if (vm <= 0xEF)			/* midi, not MPU mark */
		{
			if (vm >= 0x80)		/* new running status? */
			{
				midi_rs = vm;	/* yes, set the new status */
				mmlen = midi_lengths[(midi_rs >> 4) & 0x07];
				bp[length++] = mpu_dget(); /* get next byte */
			}
			for (i = 0; i < mmlen; ++i)
				bp[length++] = mpu_dget();
		}
	}
	else					/* These are all MPU msgs */
	switch (data)
	{
	case 0xF0:				/* track 1 request */
	case 0xF1:				/* track 2 request */
	case 0xF2:				/* track 3 request */
	case 0xF3:				/* track 4 request */
	case 0xF4:				/* track 5 request */
	case 0xF5:				/* track 6 request */
	case 0xF6:				/* track 7 request */
	case 0xF7:				/* track 8 request */
	case 0xF8:				/* timing overflow */
	case 0xF9:				/* conductor request */
	case 0xFC:				/* all end */
	case 0xFD:				/* clock to host */
		break;

	case 0xFF:				/* midi system message */
	{
		data = mpu_dget();
		bp[length++] = data;
		switch (data)
		{
		case 0xF0:			/* system exclusive */
			do
			{
				data = mpu_dget();
				bp[length++] = data;
			}
			while (data != MIDI_EOX);
			break;

		case 0xF2:			/* song position pointer */
			bp[length++] = mpu_dget();
			/* FALL THRU */

		case 0xF3:			/* song select */
			bp[length++] = mpu_dget();
			/* FALL THRU */

		case 0xF6:			/* tune request */
		case 0xFA:			/* start */
		case 0xFB:			/* stop */
		case 0xFC:			/* continue */
			break;

		default:
			printf("Bogus sys msg: %.2x\n", data);
		}
		break;
	}

	case CMD_ACK:				/* we're confused.... */
		printf("Spurious ACK!\n");
		break;

	default:				/* we're REALLY confused.... */
		printf("Bogus message: %.2x\n", data);
		break;
	}
	return (length);
}

