/*
 * GLIB - a Generic LIBrarian and editor for synths
 *
 * D10 Tone Librarian Common Functions
 *
 * Code started 3 FEB 89 --  Michael R. Kesti mrk@gvgspd.GVG.TEK.COM
 */

#include "glib.h"

#define D10TONSIZE 246
#define TONBASEADDR 0x080000
#define RESERVESIZE 20

/*
 * d10tonnum
 *
 * Convert a voice number (0 to 63) to the string displayed in the
 * librarian (ie. 1 to 64).
 */

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

	if ( n < 0 || n > 63 )
		return("??");

	v[0] = (n+1)/10 + '0';
	v[1] = (n+1)%10 + '0';
	v[2] = '\0';
	return(v);
}

/*
 * d10numton
 *
 * Convert a display-style voice number (1 to 64) to internal
 * format (0 to 63).
 */

d10numton(n)
int n;
{
	int ld, rd;
	
	/* crack out the digits as decimal codes */
	ld = (n - 1) / 10; /* left digit */
	rd = (n - 1) % 10; /* right digit */

	if(ld < 0 || ld > 6 || rd < 0 || rd > 9) {
		return(-1);
	} else {
		return(n - 1);
	}
}
/*
 * d10tonsedit
 *
 * Send a single voice to the edit buffer of the D10.  This will be whatever
 * voice is currently selected.
 */

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

/*
 * d10tonnof
 *
 * Return a pointer to the voice name buried in library bank data.
 */
char *
d10tonnof(data)
char *data;
{
	static char currbuff[11];
	char *p;
	int m;

	p = currbuff;
	for ( m = 0 ; m < 10 ; m++ )
		*p++ = data[m + RESERVESIZE];
	*p = '\0';
	return(currbuff);
}

/*
 * d10tonsnof
 *
 * Set the voice name buried in data to name.
 */
d10tonsnof(data,name)
char *data;
char *name;
{
	char *p;
	int m;

	for ( p = name, m = 0 ; *p != '\0' && m < 10 ; p++, m++ )
		data[m + RESERVESIZE] = *p;
	for ( ; m < 10 ; m++ )
		data[m + RESERVESIZE] = ' ';
}

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

	curadd = TONBASEADDR;

	for(n = 0; n < iv; n++) {
		curadd += 0x200;
		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 < D10TONSIZE; n++) {
		sendmidi(data[n + RESERVESIZE] & 0x7f);
		cksum += data[n + RESERVESIZE] & 0x7f;
	}
	sendmidi((-cksum) & 0x7f);	/* checksum */
	sendmidi(EOX);

	return(0);
}

/* d10tongbulk - Request and read a bulk dump from the D10 */
d10tongbulk(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 = TONBASEADDR;

	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(0x01);		/* should be D10TONSIZE */
		cksum += 0x01;
		sendmidi(0x76);		/* length lsb */
		cksum += 0x76;

		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 < D10TONSIZE; ) {
			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 != D10TONSIZE ) {
			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 += 0x200;		/* D10TONSIZE */

		if((curadd & 0x8000) != 0) {
			curadd &= 0x7f7f7f;
			curadd += 0x10000;
		}

	} /* go back for another voice */

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

getout:
	return(ret);
}

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

	curadd = TONBASEADDR;
	curoff = 0;	
	sprintf(Buff,"\nA: ");
	windstr(Buff);

	for(v = 0; v <Nvoices ; v++) {
		if(v == 64) {
			sprintf(Buff,"\nB: ");
			windstr(Buff);
		}
		if((((v > 63) ? (v - 64) : v) % 10) != 0) {
			sprintf(Buff, ".");
		} else {
			sprintf(Buff,"%d", (((v > 63) ? (v - 64) : 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 < D10TONSIZE; n++) {
			databyte = data[curoff + n + RESERVESIZE] & 0x7f;
			sendmidi(databyte);
			cksum += databyte;
		}
		sendmidi((-cksum) & 0x7f);	/* checksum */
		sendmidi(EOX);

		curadd += 0x200;		/* D10TONSIZE */
		if((curadd & 0x8000) != 0) {
			curadd &= 0x7f7f7f;
			curadd += 0x10000;
		}
		curoff += (D10TONSIZE + RESERVESIZE);
	}
	return(0);
}
