/***************************************************************************
 *                                                                         *
 *   FileName:  MPUDEMO1.BAS, MPUDEMO1.EXE - for IBM and ROLAND MPU-401    *
 *                                                                         *
 *      Demonstrates the speed of Borland's TURBO BASIC, and allows you    *
 *        to experiment with the ROLAND MPU-401 and MIDI synthesizers.     *
 *   MPUDEMO1 puts your MPU-401 into its "DUMB UART" mode and then plays   *
 *    a quick scale and some chords on MIDI Channel 1.  To run, connect    *
 *        your synth (on Chan.1) to MPU-401 OUT, type MPUDEMO1 <CR>        *
 *   WARNING:  If you don't HAVE an MPU-401 hooked up, program hangs up!   *
 *       Compile ONLY with TURBO BASIC V. 1.0 on IBM PC/XT or equiv.       *
 *         Please feel free to tinker around to learn about MIDI!          *
 *                                                                         *
 *               By Gino F. Silvestri 06/19/87 1700 Hrs.                   *
 *                                                                         *
 ***************************************************************************/

/***************************************************************************
 *                        D E F I N I T I O N S                            *
 ***************************************************************************/

#define WAIT( port, flag )	while ( (inp(port)&flag) != 0 )

#define	COMDPORT   0x331		/* MPU-401 Command Port on IBM */
#define	STATPORT   0x331		/* MPU-401 Status Port on IBM */
#define	DATAPORT   0x330		/* MPU-401 Data I/O Port on IBM */
#define	DRR        0x40			/* Mask for Data Read Reg. Bit */
#define	DSR        0x80			/* Mask for Data Set Ready Bit */
#define	ACK        0xFE			/* MPU-401 Acknowledge Response */
#define	MASKFLIP   0xFF			/* WAIT Function Bit Mask XOR */
#define	MPURESET   0xFF			/* MPU-401 Total Reset Command */
#define	UARTMODE   0x3F			/* MPU-401 "Dumb UART Mode" */
#define	NOTEON1    0x90			/* MIDI Note On for Channel 1 */
#define	VELOCITY   64			/* MIDI Medium Key Velocity */
#define	NOTEOFF    0			/* 0 Velocity = Note Off */
#define	FIRSTNOTE  36			/* First note synth can play */
#define	LASTNOTE   96			/* Last note synth can play */

/***************************************************************************
 *                       I N I T I A L I Z A T I O N                       *
 ***************************************************************************/

RstMPU()
{
	register char a;

	/* Clear Display */

	outp( COMDPORT, MPURESET );		/* Send MPU-401 RESET Command */
	a = inp( DATAPORT );			/* Dummy read to clear buffer */

	WAIT( STATPORT, DRR );			/* wait for port ready */

	outp( COMDPORT, UARTMODE );		/* Set MPU-401 "Dumb UART" Mode */
	a = inp(DATAPORT);				/* Dummy Read to clear buffer */

	WAIT( STATPORT, DSR );			/* Wait for "UART" port ready - */
			 						/*  Really crucial! */
}

/***************************************************************************
 *                         M A I N   P R O G R A M                         *
 ***************************************************************************/

main()
{
	register n;


	RstMPU();

	printf( "\n\n\n\n\n" );

	printf( "\tMPUDEMO1 now playing a fast scale on MIDI Channel 1\n" );

	for ( n = FIRSTNOTE; n <= LASTNOTE; n++ )
	{
		PlayIt( n );		/* Play note */
		Delay( 1 );			/* Duration of note ON */
		OffIt( n );			/* Stop note */
	}

	Delay( 1 );				/* Pause between scales */

	for ( n = LASTNOTE; n <= FIRSTNOTE; n-- )
	{
		PlayIt( n );		/* Play a note */
		Delay( 1 );			/* Duration of note OFF */
		OffIt( n );    		/* Stop that same note */
	}

	Delay( 1 );				/* Pause between demos */

	printf( "\n\n\n" );

	printf( "\tMPUDEMO1 now playing some chords on MIDI Channel 1\n" );

	for ( n = 1; n <= 3; n++ )
	{
		PlayIt( 65 );		/* Start a chord - F3 */
		PlayIt( 69 );		/* A3 */
		PlayIt( 72 );		/* C4 */

		Delay( 1 );			/* Duration of held chord */

		OffIt( 65 );		/* Stop the chord - F3 */
		OffIt( 69 );		/* A3 */
		OffIt( 72 );		/* C4 */

		Delay( 1 );			/* Duration of rest */
	}

	printf( "\n\n\n" );

	printf( "\tMPUDEMO1 is through - Tinker with it!\n" );
}

/***************************************************************************
 *                          S U B R O U T I N E S                          *
 ***************************************************************************/


/***************************** Playit SUBROUTINE ***************************/

PlayIt( n ) 			/* Play a MIDI Note */
int n;
{
	register char a;

	outp( DATAPORT, NOTEON1	);		/* Send Chan. 1 note ON code */
	a = inp( DATAPORT );			/* Dummy Read to clear buffer */
 	WAIT( STATPORT, DRR );			/* Wait for port ready */
	
	outp( DATAPORT, n );			/* Send note Number to turn ON */
	a = inp( DATAPORT );			/* Dummy Read to clear buffer */
	WAIT( STATPORT, DRR );	 		/* Wait for port ready */

	outp( DATAPORT, VELOCITY );		/* Send medium velocity */
	a = inp( DATAPORT );			/* Dummy Read to clear buffer */
	WAIT( STATPORT, DRR );	 		/* Wait for port ready */
}

/***************************** Offit SUBROUTINE ***************************/

OffIt( n )					/* Turn off a MIDI Note */
int n;
{
	register char a;

	outp( DATAPORT, NOTEON1	);		/* Send Chan. 1 note ON code */
	a = inp( DATAPORT );			/* Dummy Read to clear buffer */
	WAIT( STATPORT, DRR );			/* Wait for port ready */

	outp( DATAPORT, n );			/* Send note number to turn OFF */
	a = inp( DATAPORT );			/* Dummy Read to clear buffer */
 	WAIT( STATPORT, DRR );			/* Wait for port ready */

	outp( DATAPORT, NOTEOFF	);		/* Send 0 Velocity = Note Off */
	a = inp( DATAPORT );			/* Dummy Read to clear buffer */
 	WAIT( STATPORT, DRR );			/* Wait for port ready */
}

/**************************** Delay SUBROUTINE ****************************/

Delay( n )
int n;
{
	long x;

	while ( n-- > 0 )
		for ( x = 1; x < 10000; x++ );
}

/* Note: Read of DATAPORT prevents hang-up if MIDI IN from a keyboard is
    connected and played - WAIT would stay FOREVER if you hit any key once!
*/

/************************* Last Line of MPUDEMO1.C ************************
  Last Edited 07/1/87 2010 Hrs. M. D. Bratcher
 **************************************************************************/
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                