/* 
 *	Program: DXFRIEND
 *	Filename:MIDIFUNC.C
 *
 *	Functions to call from midiparse() to cope with interesting
 *	things coming up the MIDI input.
 */

#include <osbind.h>	/* for midi.h */
#include "midi.h"
#include "dx7.h"

extern char voicebuf[];			/* 32-voice buffer from main.c */

active()
{
}

keyon(cmd, keyno, vel)
{
	disp_key(keyno, vel);
}

control(cmd, number, value)
{
	disp_control(number, value);
}

program(cmd, progno)
{
	disp_program(progno);
}

aftertouch(cmd, value)
{
	disp_after(value);
}

pitchbend(cmd, lsb, msb)
{
	disp_pb(lsb, msb);
}

sysexcl(buf, nbytes)
char *buf;
int nbytes;	/* number of bytes in message, including F0, excluding F7 */
{
	int substatus;
	int channel;
	int bytecount;
	int group, param;

	/* make sure we can access buf[0..3] */
	if (nbytes < 4) {
		error("Internal error: short sysexcl command of length %d", nbytes);
		return;
	}

	if (buf[1] != 67) {
		error("System exclusive ID number is not Yamaha");
		return;
	}

	substatus = buf[2] >> 4 & 7;	/* 3 bits */
	channel = buf[2] & 15;
	
	switch (substatus) {

	default:
		error("Unknown substatus %d received", substatus);
		return;

	case 0:
		bytecount = buf[4]<<7 | buf[5];
		switch (buf[3]) {	/* format number */

		default:
			error("Unknown voice dump format %d received", buf[3]);
			return;

		case 0:
			/* One 155-byte voice */
			if (bytecount != 155) {
				error(
			"Wrong data byte count of %d in single voice dump",
				bytecount);
				return;
			}

			m_str("155-byte voice dump format received and ignored");
			break;

		case 9:
			/* a 4096-byte, 32-voice dump */
			if (bytecount != 4096) {
error("Wrong data byte count of %d in single voice dump", bytecount);
				return;
			}

			if (nbytes != 6 + 4096 + 1) {
error("Bulk voice dump is wrong size (%d bytes)",
					nbytes);
				return;
			}

			m_str("4096-byte 32-voice dump received.");

			if (checksum(&buf[6], 4096) != buf[6+4096]) {
				error(
"Warning: Checksum error on bulk voice dump.  Voice data may be corrupted.");
				/* Give it to them anyway */
			}

			bcopy(voicebuf, &buf[6], 4096);

			disp_names(voicebuf);	/* Update if displayed */
			break;
		}
		break;
	
	case 1:
		if (nbytes != 6) {
			error("Wrong byte count of %d in parameter change",
				nbytes);
			return;
		}
		group = buf[3]>>2 & 0x1F;	/* 5 bits */
		param = (buf[3] & 03) << 7 | buf[4];
		switch (group) {
		default:
			error("Parameter change for unknown parameter group %d",
				group);
			return;
		case 0:
			m_printf("Common DX Voice parameter %d = %d",
				param, buf[5]);
			break;
		case 2:
			m_printf("DX7 Function parameter %d = %d",
				param, buf[5]);
			break;
		}
	}
}

/* Send a 4096-byte bulk voice bump to the DX7 */
send_dx7(buf)
char *buf;		/* pointer to 4096-byte voice dump buffer */
{
	register int i;
	register char *cp;	/* buffer grubber */
	register int csum;

	/* check for top bit set in data */
	for (i=0; i<4096; i++) {
		if (buf[i] & 0x80) {
			error("Dirty dump.  Cleaning top bits...");
			for ( ; i<4096; i++) buf[i] = buf[i] & 0x7F;
		}
	}

	/* do header */	
	Bconout(MIDI, 0xF0);		/* status */
	Bconout(MIDI, 0x43);		/* ID = YAMAHA (67 decimal) */
	Bconout(MIDI, 0x00);		/* subst & channel number=1 */
	Bconout(MIDI, 0x09);		/* 32-voice bulk dump */
	Bconout(MIDI, 4096>>7);		/* MSB of byte count = 4096 */
	Bconout(MIDI, 0x00);		/* LSB (7 bits each) */

	csum = 0;
	for (i=0, cp=buf; i<4096; cp++, i++) {
		Bconout(MIDI, *cp);
		csum += *cp;
	}
	/* need to output "the 2's complement of the sum of 4096 bytes" */
	Bconout(MIDI, (-csum) & 0x7F);		/* checksum */
	Bconout(MIDI, EOX);

	m_str("Transmission complete.");
}
