#include <exec/types.h>
#include <exec/ports.h>
#include <exec/devices.h>
#include <exec/memory.h>
#include <exec/interrupts.h>
#include <exec/nodes.h>
#include <exec/lists.h>
#include <exec/libraries.h>
#include <exec/tasks.h>
#include <exec/execbase.h>
#include <exec/io.h>
#include <exec/resident.h>
#include <exec/execname.h>
#include <exec/exec.h>
#include <exec/errors.h>
#include <exec/alerts.h>
#include <devices/serial.h>
#include <stdio.h>
#include <ctype.h> 


/* Resource allocation bits */

#define SERIAL_PORT	(1 << 0)
#define SERIAL_EXTIO	(1 << 1)
#define SERIAL_DEVICE	(1 << 2)
#define TIMER_PORT	(1 << 3)
#define TIMER_EXTIO	(1 << 4)
#define TIMER_DEVICE	(1 << 5)
#define ICR_VECTOR	(1 << 6)
#define ARRAY_ALLOCATED	(1 << 7)



/* MIDI end-system-exclusive byte */

#define END_SYSTEM_EXCLUSIVE	0xF7

#define MIDI_STATUS_MASK	0x80

/* Routine declarations */

extern struct MsgPort *CreatePort();
extern struct IORequest *CreateExtIO();

LONG ReadToneData();

/* Serial device structures */

struct IOExtSer *IORser;
struct MsgPort *serialport;

UBYTE tonedata[254];

int channel,patchg,patchn,parameter,address,timbre,resources=0;
int i,cort,channum,notenum;
char filename[80];

main(argc,argv)
int argc;
char *argv[];
{
int error,x,xx;

/* Create a message port for the serial device */

serialport = CreatePort(SERIALNAME,0);
if (serialport == NULL) Cleanup("Unable to CreatePort serial",100);


/* Create an I/O request block for the serial device */

IORser = (struct IOExtSer *)
	CreateExtIO(serialport, sizeof(struct IOExtSer));

if (IORser == NULL) Cleanup("Unable to CreateExtIO serial",200);

resources |= SERIAL_EXTIO;

/* Open the serial device */

if ((error = OpenDevice(SERIALNAME,0,IORser,0))!= 0)
	Cleanup("Unable to open serial device",error);

resources |= SERIAL_DEVICE;

/* Set serial device parameters for MIDI communications */

if ((error = SetParams(IORser)) != 0)
	Cleanup("Unable to set serial parameters",error);
	if (argc)   {
		for (x=0;x<argc-1;x++) {
			ReadToneData(argv[x+1]);
			SendToneData (tonedata,x);
			SendToneData (tonedata,x+argc-1);
			for(xx=0;xx<5000;xx++);
			ModifyPatchData(x+1,5,0,2);
			ModifyPatchData(x+1,5,1,x);
			ModifyPatchData(x+argc,5,0,2);
			ModifyPatchData(x+argc,5,1,x+argc-1);
			ModifyPatchData(x+argc,5,6,0);
			printf("Sending %s\n",tonedata);
		}
	}
	Cleanup ("", 0);
}

SendToneData (filedata,timbre)
UBYTE timbre,*filedata[];

{
/* Receive request 1 system exclusive */

static UBYTE receivearray [] = {0xF0,0x41,0x10,0x16,0x12};
UBYTE receive_request[265];    

UBYTE checksum=0;
UBYTE *ptr;

int i,addSB,addLSB;

/* Clear the serial buffer of any unread data */

IORser->IOSer.io_Command = CMD_CLEAR;
DoIO (IORser);

for (i=0;i<5;i++) receive_request[i]=receivearray[i];
i = timbre * 0x0200; 
addSB=(i>>8);    addLSB=((i<<4)>>4);
receive_request[5]=8;receive_request[6]=addSB;receive_request[7]=addLSB;
ptr = (UBYTE *) filedata;

for (i=8; i<254; i++)
	{
	receive_request[i] = *ptr;
	checksum += receive_request[i];
	ptr++;
	}
for (i=5;i<8;i++)  {
	checksum += receive_request[i];
		    }
   checksum=checksum%256;
   if (checksum<=128) checksum=128-checksum;	
   else if (checksum<256) checksum=256-checksum;
   
/* Add "end-system-exclusive" to tone data buffer */

receive_request[254] = checksum;
receive_request[255]= END_SYSTEM_EXCLUSIVE;

/* Send tone data to MT-32 */

IORser->IOSer.io_Data = (APTR) &receive_request;
IORser->IOSer.io_Length = 256;
IORser->IOSer.io_Command = CMD_WRITE;

DoIO (IORser);

}

/* Write tone data to file */


/* Read tone data from file */

LONG ReadToneData (filename)
char *filename[];
{
FILE *fileptr;


do	{
	fileptr = fopen (filename, "r");
	}
while (fileptr == NULL);

/* Read tone data from file */

fread (tonedata, 2546, 1, fileptr);

fclose (fileptr);


return (TRUE);
}

/* Set serial device parameters */

SetParams (io)
struct IOExtSer *io;
{

/* Set serial port for MIDI communications */

io->io_SerFlags = SERF_RAD_BOOGIE;
io->io_Baud = 31250;
io->IOSer.io_Command = SDCMD_SETPARAMS;

return(DoIO(io));
}

/* Cleanup and exit routine */

Cleanup (str, n)
char *str;
int n;
{

if (strlen(str) != 0) printf ("%s", str);
if (n != 0) printf (", error = %ld", n);
if (strlen(str) != 0) printf ("\n"); 

/* Release all resources */

if (resources & SERIAL_DEVICE) {
	/* Reset the serial device and then close it */
	IORser->IOSer.io_Command = CMD_RESET;
	DoIO (IORser);
	CloseDevice (IORser); }
if (resources & SERIAL_EXTIO)
	DeleteExtIO(IORser, sizeof(struct IOExtSer));
if (resources & SERIAL_PORT) DeletePort (serialport);

exit(n);

}

	


ModifyPatchData (channel,address,parameter,patchn)
UBYTE channel,address,parameter,patchn;
{
UBYTE addSB,addLSB,checksum=0;

/* Send Request 1 system exclusive data */
UBYTE sendrequest[11];
static UBYTE sendarray[5] = {0xF0,0x41,0x10,0x16,0x12};

int i;
for (i=0;i<5;i++) sendrequest[i]=sendarray[i];
sendrequest[5]=address;
if (address==3) {
	i = (channel-1) * 0x10 + parameter; 
	}
if (address==5) {
	i = (channel-1) * 0x08 + parameter; 
	}
if (address==8)	i = (channel-1) * 0x0200 + parameter;
if (address==10) goto ten;

addSB=(i>>8);addLSB=((i<<4)>>4);
sendrequest[6]=addSB;sendrequest[7]=addLSB;
	
	ten:
		if (address==10) {
			sendrequest[5]=0x10;
			sendrequest[6]=0;
			sendrequest[7]=parameter;
		}
		
sendrequest[8]=patchn;
for (i=5;i<9;i++)  {
	checksum += sendrequest[i];
		    }  
   checksum = checksum%256;
   if (checksum<=128) checksum = 128-checksum;	
   else if (checksum<256) checksum = 256-checksum;
sendrequest[9]=checksum;
sendrequest[10]=0xF7;

/* Clear the serial buffer of any unread data */

IORser->IOSer.io_Command = CMD_CLEAR;
DoIO (IORser);

/* Send request to MT-32 */

IORser->IOSer.io_Data = (APTR) &sendrequest;
IORser->IOSer.io_Length = sizeof(sendrequest);
IORser->IOSer.io_Command = CMD_WRITE;

DoIO(IORser);
	
}

SendPatchData (channel,patchg,patchn)
UBYTE channel,patchg,patchn;
{
UBYTE checksum=0;

/* Send Request 1 system exclusive data */
UBYTE sendrequest[12];
static UBYTE sendarray[5] = {0xF0,0x41,0x10,0x16,0x12};

int i;
for (i=0;i<5;i++) sendrequest[i]=sendarray[i];
i = (channel-1) * 0x010;
sendrequest[5]=3;sendrequest[6]=0;sendrequest[7]=i;
sendrequest[8]=patchg;sendrequest[9]=patchn;
for (i=5;i<10;i++)  {
	checksum += sendrequest[i];
		    }  
   checksum = checksum%256;
   if (checksum<=128) checksum = 128-checksum;	
   else if (checksum<256) checksum = 256-checksum;
sendrequest[10]=checksum;
sendrequest[11]=0xF7;
	
/* Clear the serial buffer of any unread data */

IORser->IOSer.io_Command = CMD_CLEAR;
DoIO (IORser);

/* Send request to MT-32 */

IORser->IOSer.io_Data = (APTR) &sendrequest;
IORser->IOSer.io_Length = sizeof(sendrequest);
IORser->IOSer.io_Command = CMD_WRITE;

DoIO(IORser);
	
}
