/***********************************************************************
 * midi.c
 *
 * Date: 910925
 *
 * (C) 1991 Steve Simpson
 *
 * Main module illustrating how the serial port resource is opened and
 * freed.  Includes calls to other MIDI routines sending some MIDI data
 * out onto the MIDI network
 *
 * Compile:  cc -bs -ps midi.c
 *		 (Manx Aztec v5.0d)
 * Link:     ln -g -t midi resource midiio midiio_intf -lc16
 ***********************************************************************/

#include <functions.h> 
#include <exec/types.h> 
#include <resources/misc.h>

/* external declarations */
extern struct MiscResource *AllocMIDIResource();
extern VOID FreeMIDIResource(struct MiscResource *);
extern VOID SetMIDIBaud();
extern VOID MIDISend(UBYTE *, USHORT);
extern VOID MIDIRead(UBYTE *, USHORT);


/* forward declarations	*/
VOID PerformMIDIOps();
VOID SendMIDIOp();
VOID ReadMIDIOp();
VOID MIDIAllOff();


struct MiscResource *pMIDIRes;
UBYTE buffer[200];

	/* MIDI note on/off structure */
struct MidiNote {
   UBYTE mn_Command,		/* channel number | note on or off */
	 mn_Note,		/* MIDI note number (12..127) */
	 mn_Velocity;		/* note velocity (0..127) */
};
#define SIZE_MIDINOTE	3	/* number bytes in MidiNote structure */

#define NOTE_ON		0x90	/* set note on bit */
#define NOTE_OFF	0x80	/* set note off bit */


/************************************************************************
 * main()
 ************************************************************************/
main()
{
	/* allocate the MIDI resource */
    pMIDIRes = AllocMIDIResource();

	/* check for valid return */
    if (pMIDIRes != NULL) 
    {
	printf("MIDI Resource allocated - pMIDIRes=%08x\n", pMIDIRes);
	SetMIDIBaud();
	PerformMIDIOps();
	FreeMIDIResource(pMIDIRes);
    }
    else
    {
	printf("Can't allocate MIDI Resource\n");
    }

} /* end main */


/***********************************************************************
 * PerformMIDIOps
 *
 * Do some MIDI operations and handle IO with user
 *
 **********************************************************************/
VOID PerformMIDIOps()
{
    UBYTE opchar;			/* user selected operation character */
    USHORT quitT;			/* TRUE when want to quit program */

    quitT = FALSE;

    while (quitT == FALSE) {
		/* show the operations menu on screen */	
	printf("\n\nSend to MIDI........S\n");
	printf("Read from MIDI......R\n");
	printf("Quit................Q\n\n? ");

		/* get the user selected operation */
	opchar = (UBYTE)getchar();
		/* change character to upper case */	
	opchar = (UBYTE)toupper(opchar);
		/* flush keyboard buffer */
	getchar();

		/* perform operation indicated */
	switch (opchar) {
	case 'S'	:   SendMIDIOp();
			    break;
	case 'R'	:   ReadMIDIOp();
			    break;
	case 'Q'	:   quitT = TRUE;
			    break;	
	default		:   printf("Unknown command\n");
			    break;
	}
    }

    MIDIAllOff();

} /* end PerformMIDIOps */


/*********************************************************************
 * SendMIDIOp
 *
 * Handles MIDI send operations
 *********************************************************************/
VOID SendMIDIOp()
{
    UBYTE onoffchar;		/* indicates note ON or OFF */
    USHORT channum,		/* channel number */
	   notenum,		/* number of note to send */
	   notevel;		/* velocity of note */
    struct MidiNote note;	/* note structure */

    printf("\nSend MIDI note on/off\n\n");

	/* get user input from note ON or OFF */
    do {
	printf("Note ON (T) or OFF (F) ? ");
		/* user says note ON or OFF */
	scanf("%c", &onoffchar);
	onoffchar = (UBYTE)toupper(onoffchar);
		/* flush keyboard buffer */	
	getchar();
    } while (onoffchar != 'T'  &&  onoffchar != 'F');

	/* get the channel number */
    do {
	printf("Channel Number (1..16) ? ");
		/* get the channel number from the user */
	scanf("%u", &channum);
		/* flush keyboard buffer */
	getchar();
    } while (channum < 1  ||  channum > 16);

	/* valid channel number is in range 0..15 */
    channum--;

	/* set note ON/OFF bit in command byte */
    if (onoffchar == 'T') 
    {
	note.mn_Command = (UBYTE)(channum | NOTE_ON);	
    }
    else
    {
	note.mn_Command = (UBYTE)(channum | NOTE_OFF);
    }

	/* get the note number */
    do {
	printf("MIDI Note Number (12..127) ? ");
		/* get the MIDI note number from the user */
	scanf("%u", &notenum);
		/* flush keyboard buffer */
	getchar();
    } while (notenum < 12  ||  notenum > 127);

    note.mn_Note = (UBYTE)notenum;

	/* get the note velocity number */
    do {
	printf("MIDI Note Velocity (0..127) ? ");
		/* get the MIDI note velocity from the user */
	scanf("%u", &notevel);
		/* flush keyboard buffer */
	getchar();
    } while (notevel < 0  ||  notevel > 127);

    note.mn_Velocity = (UBYTE)notevel;

	/* send the MIDI note data */
    MIDISend((UBYTE *)&note, SIZE_MIDINOTE);

} /* end SendMIDIOp */


/*********************************************************************
 * ReadMIDIOp
 *
 * Handles MIDI read operations
 *********************************************************************/
VOID ReadMIDIOp()
{
    USHORT sizebuff,	/* number bytes in buffer */
	   numbytes,	/* number of bytes to receive */
	   cnt;		/* buffer index counter */

    printf("Enter Number of Bytes to Read ");
	/* get the number of bytes from the user */
    scanf("%u", &numbytes);
	/* flush the keyboard buffer */
    getchar();

	/* number elements in the buffer  - we don't use hardcoded 
	 * buffer size so that ir is easy to change the sizeof the
	 * buffer and not have to change this line of code */
    sizebuff = sizeof(buffer) / sizeof(buffer[0]);
	/* check the input number bytes to get */
    if (numbytes > sizebuff)
    {
	numbytes = sizebuff;
    }
	
	/* go get the bytes from MIDI */
    MIDIRead((UBYTE *)&buffer[0], numbytes);

	/* now display the input data */
    for (cnt=0; cnt<numbytes; cnt++)
    {
	printf("%02x ", buffer[cnt]);
		/* put in a newline at end of line */
	if ((cnt+1) % 24 == 0)
	{
		printf("\n");
	}
    }
    printf("\n");

} /* end ReadMIDIOp */


/*********************************************************************
 * MIDIAllOff
 *
 * Turns off all notes on all channels
 *********************************************************************/
VOID MIDIAllOff()
{
    struct MidiNote note;	/* note structure */
    UBYTE channum,		/* channel number */
	  notenum;		/* note number counter */

    printf("Turning off all MIDI notes\n");

	/* scan through all the MIDI channels */
    for (channum=0; channum<=15; channum++)
    {
	note.mn_Command = channum | NOTE_OFF;
	note.mn_Velocity = 0;

		/* turn all the notes off */
	for (notenum=12; notenum<127; notenum++)
	{
		note.mn_Note = notenum;
		MIDISend((UBYTE *)&note, SIZE_MIDINOTE);
	}
    }

} /* end MIDIAllOff */
