
/*********************	     MPU401.MM		   **************************/
/* Interrupt handler and data structures for the MPU401 interface */

/* Include Greg Hendershott's MPU 401 Interrupt Service Routines here */
#include "mpuisr.c" 

/* define interface routines from GH to MIDI Madhouse environment */
/*  low level = MPU to/from MM data buffers */

data_handler(data)  /* put data each byte from MPU into MPU_IN track */
uchar data;
{
 if(tracks[MPU_IN].tcount >= tracks[MPU_IN].tsize)  /* full already */
   {fputs("\nMPU input buffer overflow\n",stdout);
    return(-1); 
    }  /* error, do nothing */
 /* else put data byte in next input buffer location */
 *(tracks[MPU_IN].tloc + tracks[MPU_IN].tcount) = data;
 tracks[MPU_IN].tcount++;  /* increment counter by one */
 return(0);
 }  /* End data_handler */

play_handler(data)    /* Send data bytes from output buffers to MPU */
uchar data;	      /* when "play request" (F0-F7,F9) received. Must send */
{int trk, send;       /* complete MIDI event for track requested (1-4 bytes)*/
 uchar *play_ptr;
 static uchar running_status, rs_bytes;  /* save run status and # bytes */

 switch(data)  /* select output track based on request code "data" */
       {case 0xF0:  {trk = MPU_OUT_0;  break;}
	case 0xF1:  {trk = MPU_OUT_1;  break;}
	case 0xF2:  {trk = MPU_OUT_2;  break;}
	case 0xF3:  {trk = MPU_OUT_3;  break;}
	case 0xF4:  {trk = MPU_OUT_4;  break;}
	case 0xF5:  {trk = MPU_OUT_5;  break;}
	case 0xF6:  {trk = MPU_OUT_6;  break;}
	case 0xF7:  {trk = MPU_OUT_7;  break;}
	case 0xF9:  {trk = MPU_COND_OUT;  break;}
	default: return(-1);  /* bad code */
	}  /* play buffer selected */

 if(!tracks[trk].tcount)  /* if buffer is empty */
    return(0);		  /* assumes 0xFC (data end) was sent */

 /* play a complete MIDI event */
 play_ptr = tracks[trk].tloc;
 put_data(*play_ptr);	      /* always send first (timing) byte */
 tracks[trk].tcount--;	      /* decrement track counter */

 if(*play_ptr == 0xF8)	     /* timing overflow byte, no more to send */
   {movmem(++play_ptr,tracks[trk].tloc,tracks[trk].tcount);
    return(0);
    }
 /* else more bytes to send in event */
 play_ptr++;		 /* point to next track byte */

 if(*play_ptr >= 0xF0)	     /* MPU mark byte of some kind, no follow */
   {put_data(*play_ptr);     /* send it out */
    tracks[trk].tcount--;	 /* decrement track count */
    movmem(++play_ptr,tracks[trk].tloc,tracks[trk].tcount);
    return(0);
    }  

 if(*play_ptr > 0x7F)		 /* if byte is a MIDI command... */
   {running_status = *play_ptr;  /* save it as new running status */
    rs_bytes = lookup(running_status);	/* set # bytes in MIDI event */
    put_data(*play_ptr);     /* ship byte out */
    play_ptr++;
    tracks[trk].tcount--;	 /* decrement track count */
    }

 send = rs_bytes;  /* set event length based on running status */
 for(; send && tracks[trk].tcount; send--) /* send rest of event */
    {put_data(*play_ptr);
     play_ptr++;    tracks[trk].tcount--;
     }	/* all sent or track empty */

 /* shift remaining data in buffer to start address */
 movmem(play_ptr,tracks[trk].tloc,tracks[trk].tcount);
 return(send);	/* return # of unsent event bytes, if any */
 }  /* End play_handler */

/* dummy routines for now *****/
clock_handler()  {}
measure_handler()  {}
event_handler()  {}

/***** internal control functions ****/

extern ch_menu();   /* function in MM.C, used below */

stop_rec()
{
 if(!put_cmd(RECORD_STOP | REALTIME_STOP) || !put_cmd(METRO_OFF))
   {fputs("MPU has not acknowledged record-stop commands!\n",stdout);
    }
 strcpy(root[8].descrip,NO_D);	/* blank out F8 in root menu */
 root[8].doit = NULL;
 ch_menu(root);
 return(0);
 }  /* End of stop_rec */


start_rec()  /* send command to MPU to start; from page 44 of tech manual */
	     /* activated from root menu, F8 */
{
 if(!put_cmd(METRO_ON) || !put_cmd(RECORD_START | REALTIME_START))
   {fputs("MPU has not acknowledged record-start commands!\n",stdout);
    }
 /* MPU set to record - change root menu F8 */
 strcpy(root[8].descrip,"Stop recording     ");
 root[8].doit = stop_rec;
 ch_menu(root);
 return(0);
 }  /* End of start_rec */


stop_play()	  /* MPU manual page 45 */
{
 if(!put_cmd(PLAY_STOP | REALTIME_STOP))
   {fputs("MPU has not acknowledged play-stop commands!\n",stdout);
    }
 strcpy(root[9].descrip,NO_D);	/* blank out F9 in root menu */
 root[9].doit = NULL;           /* cut function pointer */
 root[9].doarg = 0;             /* zero out MPU "track select" byte */
 ch_menu(root);
 return(0);
 }  /* End of stop_play */


start_play(actracks)
uchar actracks;
{
 if(!put_cmd(0xEC) || !put_data(actracks) || !put_cmd(0xB8) || !put_cmd(0x0A))
   {fputs("MPU has not acknowledged play-start commands!\n",stdout);
    }
 /* MPU set to play - change root menu F9 */
 strcpy(root[9].descrip,"Stop all play      ");
 root[9].doit = stop_play;
 ch_menu(root);
 return(0);
 }  /* End of start_play */
