/*
 * GLIB - a Generic LIBrarian and editor for synths
 *
 * D10 Rhythm Setup Librarian
 *
 * Code started 1 FEB 89 --  Michael R. Kesti mrk@gvgspd.GVG.TEK.COM
 */

#include "glib.h"
#include "machdep.h"
#include "vis.h"

#define D10RSUSIZE 4
#define RSUBASEADDR 0x090000
#define RESERVESIZE 20

char *visnum(), *visonoff();


/* This array contains arbitrary screen labels */
struct labelinfo Ld10rsu[] = {
#MENU








                         Tone Select     %
                         Level           %
                         Pan             %
                         Reverb Switch   %











 Press SPACE BAR to sound note %   at volume %   for duration %  on channel % .
#END
-1,-1,NULL
};

struct paraminfo  Pd10rsu[] =  {
/*
NAME		TYPE		POS	MAX	OFFSET	MASK	SHIFT	ADHOC
 */
#O tone		rtone		%%	127	0
#O level	patchlevel	%%	100	1
#O pan		pan		%%	14	2
#O reverbsw	onoff		%%	1	3
#O autopitch	num		%%	127	-60
#O autovol	num		%%	127	-63
#O autodur	num		%%	20	-5	*5
#O autochan	num		%%	16	-1	*5
NULL,NULL,-1,-1,-1,-1,visnum,0,0,0,0
};

/*
 * d10rsunum
 *
 * Convert a voice number (0 to 84) to the string displayed in the
 * librarian (ie. 01 to 85).
 */

char *
d10rsunum(n)
{
	static char v[3];

	sprintf(v, "%02d", n + 1);
	return(v);
}

/*
 * d10numrsu
 *
 * Convert a display-style voice number (01 to 85) to internal
 * format (0 to 84).
 */

d10numrsu(n)
int n;
{
	return(n-1);
}

/*
 * d10rsudin
 *
 * Take library bank 'data' and stuff values in the P array, by using
 * the setval function.
 */

d10rsudin(data)
char *data;
{
	/* The first RESERVESIZE bytes are reserved (arbitrarily) for the voice name */
#SETVAL
}

/*
 * d10rsudout
 *
 * Take (possibly changed) parameters values out of the P array and
 * put them back into the library bank 'data'.
 */

d10rsudout(data)
char *data;
{
#GETVAL
}

/*
 * d10rsusedit
 *
 * Send a single voice to the edit buffer of the D10.  This will be whatever
 * voice is currently selected.
 */

d10rsusedit(data)
char *data;
{
	int n;
	int cksum;
	
	sendmidi(0xf0);
	sendmidi(0x41);
	sendmidi(0x10);
	sendmidi(0x16);
	sendmidi(0x12);		/* DT1 - Data set 1 command */
	sendmidi(0x03);		/* address msb */
	cksum = 0x03;
	sendmidi(0x01);
	cksum += 0x01;
	sendmidi(0x10);		/* address lsb */
	cksum += 0x10;
	for(n = 0; n < D10RSUSIZE; n++) {
		sendmidi(data[n + RESERVESIZE] & 0x7f);
		cksum += data[n + RESERVESIZE] & 0x7f;
	}
	sendmidi((-cksum) & 0x7f);	/* checksum */
	sendmidi(EOX);
}

/*
 * d10rsunof
 *
 * Return a pointer to the voice name buried in library bank data.
 */
char *
d10rsunof(data)
char *data;
{

	static char buf[4];
	int n;

	for(n = 0; n < D10RSUSIZE; n++)
		if ( data[n + RESERVESIZE] != 0 ) break;
	if ( n != D10RSUSIZE ) {
		strcpy(buf, visrtone(data[RESERVESIZE + 0]));
	} else
		strcpy(buf, "   ");

	return(buf);
}

/*
 * d10rsusnof
 *
 * Set the voice name buried in data to name.
 */
d10rsusnof(data,name)
char *data;
char *name;
{
}

/* d10rsusone - send a single voice to the D10 */
d10rsusone(iv, data)
int iv;
char *data;
{
	int n;
	int cksum;
	long curadd;
	int addbyte;

	curadd = RSUBASEADDR;

	for(n = 0; n < iv; n++) {
		curadd += D10RSUSIZE;
		if((curadd & 0x80) != 0) {
			curadd &= 0x7fff7f;
			curadd += 0x100;
		}
		if((curadd & 0x8000) != 0) {
			curadd &= 0x7f7f7f;
			curadd += 0x10000;
		}
	}

	sendmidi(0xf0);
	sendmidi(0x41);
	sendmidi(0x10);
	sendmidi(0x16);
	sendmidi(0x12);		/* DT1 - Data set 1 command */
	addbyte = ((curadd >> 16) & 0x7f);	/* address msb */
	sendmidi(addbyte);
	cksum = addbyte;
	addbyte = ((curadd >> 8) & 0x7f);
	sendmidi(addbyte);
	cksum += addbyte;
	addbyte = (curadd & 0x7f);		/* address lsb */
	sendmidi(addbyte);
	cksum += addbyte;
	for(n = 0; n < D10RSUSIZE; n++) {
		sendmidi(data[n + RESERVESIZE] & 0x7f);
		cksum += data[n + RESERVESIZE] & 0x7f;
	}
	sendmidi((-cksum) & 0x7f);	/* checksum */
	sendmidi(EOX);

	return(0);
}

/* d10rsugbulk - Request and read a bulk dump from the D10 */
d10rsugbulk(data)
char *data;
{
	static	char Buff[BUFSIZ];
	int c, n, v, b2, ret = 1;
	long begin, toolong, wait;
	long curadd;
	int addbyte;
	int cksum;
	
	sprintf(Buff,"\n");
	windstr(Buff);

	curadd = RSUBASEADDR;

	for(v = 0; v < Nvoices; v++) {

		flushmidi();

		if((v % 10) != 0) {
			sprintf(Buff, ".");
		} else {
			sprintf(Buff,"%d", (v / 10));
		}
		windstr(Buff);

	/* request the voice */
		sendmidi(0xf0);
		sendmidi(0x41);
		sendmidi(0x10);
		sendmidi(0x16);
		sendmidi(0x11);		/* RQ1 - Data request 1 command */

		addbyte = ((curadd >> 16) & 0x7f);	/* address msb */
		sendmidi(addbyte);
		cksum = addbyte;
		addbyte = ((curadd >> 8) & 0x7f);
		sendmidi(addbyte);
		cksum += addbyte;
		addbyte = (curadd & 0x7f);		/* address lsb */
		sendmidi(addbyte);
		cksum += addbyte;

		sendmidi(0x00);		/* length msb */
		cksum += 0x00;
		sendmidi(0x00);
		cksum += 0x00;
		sendmidi(D10RSUSIZE);	/* length lsb */
		cksum += D10RSUSIZE;

		sendmidi((-cksum) & 0x7f);	/* checksum */
		sendmidi(EOX);
	
	/* set up timeout */
		begin = milliclock();
		toolong = begin + (1000 * TIMEOUT);
	
	/* read header */
		for(n = 0; n < 8; ) {
			if ( STATMIDI ) {
				b2 = (getmidi() & 0xff);
				/* burn active sensing and timing clock */
				if((b2 != 0xfe) && (b2 != 0xf8))
					n++;
			} else {
				if ( milliclock() > toolong ) {
					Reason = "Timeout waiting for header";
					goto getout;
				}
			}
		}

	/* read data */
		for(n = 0; n < D10RSUSIZE; ) {
			if ( STATMIDI ) {
				b2 = (getmidi() & 0xff);
				/* burn active sensing and timing clock */
				if((b2 != 0xfe) && (b2 != 0xf8)) {
					VOICEBYTE(data,v,n + RESERVESIZE) = b2;
					n++;
				}
			} else {
				if ( milliclock() > toolong ) {
					Reason = "Timeout reading data";
					goto timeout;
				}
			}
		}

	timeout:
		if ( n != D10RSUSIZE ) {
			Reason = "Timeout reading data!";
			goto getout;
		}

	/* read checksum */
		for(n = 0; n < 1; ) {
			if ( STATMIDI ) {
				b2 = (getmidi() & 0xff);
				/* burn active sensing and timing clock */
				if((b2 != 0xfe) && (b2 != 0xf8))
					n++;
			} else {
				if ( milliclock() > toolong ) {
					Reason = "Timeout reading checksum";
					goto getout;
				}
			}
		}

	/* read EOX */
		for(n = 0; n < 1; ) {
			if ( STATMIDI ) {
				b2 = (getmidi() & 0xff);
				/* burn active sensing and timing clock */
				if((b2 != 0xfe) && (b2 != 0xf8))
					if ( b2 != EOX ) {
						sprintf(Buff,"EOX not received (%X)\n", b2);
						Reason = Buff;
						goto getout;
					}
					n++;
			} else {
				if ( milliclock() > toolong ) {
					Reason = "Timeout reading EOX";
					goto getout;
				}
			}
		}

		curadd += D10RSUSIZE;
		if((curadd & 0x80) != 0) {
			curadd &= 0x7fff7f;
			curadd += 0x100;
		}
		if((curadd & 0x8000) != 0) {
			curadd &= 0x7f7f7f;
			curadd += 0x10000;
		}


	} /* go back for another voice */

	Reason = "";
	ret = 0;	/* all's well */

getout:
	return(ret);
}

/* d10rsusbulk - send a bulk dump to the D10 */
d10rsusbulk(data)
char *data;
{
	static char Buff[BUFSIZ];
	int v, n;
	int cksum;
	long curadd;
	int addbyte, databyte;
	int curoff;

	curadd = RSUBASEADDR;
	curoff = 0;	
	sprintf(Buff,"\n");
	windstr(Buff);

	for(v = 0; v <Nvoices ; v++) {
		if((v % 10) != 0) {
			sprintf(Buff, ".");
		} else {
			sprintf(Buff,"%d", (v / 10));
		}

		windstr(Buff);
		sendmidi(0xf0);
		sendmidi(0x41);
		sendmidi(0x10);
		sendmidi(0x16);
		sendmidi(0x12);		/* DT1 - Data set 1 command */
		addbyte = ((curadd >> 16) & 0x7f);	/* address msb */
		sendmidi(addbyte);
		cksum = addbyte;
		addbyte = ((curadd >> 8) & 0x7f);
		sendmidi(addbyte);
		cksum += addbyte;
		addbyte = (curadd & 0x7f);		/* address lsb */
		sendmidi(addbyte);
		cksum += addbyte;

		for(n = 0; n < D10RSUSIZE; n++) {
			databyte = data[curoff + n + RESERVESIZE] & 0x7f;
			sendmidi(databyte);
			cksum += databyte;
		}
		sendmidi((-cksum) & 0x7f);	/* checksum */
		sendmidi(EOX);

		curadd += D10RSUSIZE;
		if((curadd & 0x80) != 0) {
			curadd &= 0x7fff7f;
			curadd += 0x100;
		}
		if((curadd & 0x8000) != 0) {
			curadd &= 0x7f7f7f;
			curadd += 0x10000;
		}
		curoff += (D10RSUSIZE + RESERVESIZE);
	}
	return(0);
}

/* end */
