home *** CD-ROM | disk | FTP | other *** search
/ Chestnut's Multimedia Mania / MM_MANIA.ISO / midi / cmtcmu / mpu.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-06-28  |  33.3 KB  |  1,163 lines

  1. /*****************************************************************************
  2. *        Change Log
  3. *  Date        | Change
  4. *-----------+-----------------------------------------------------------------
  5. * 31-Dec-85 | Created changelog
  6. * 31-Dec-85 | Add c:\ to include directives
  7. * 31-Dec-85 | Call setctl/clrctl to deal with ctrl-break intercept.  Note that
  8. *        | clrctl can be called several times, as might be the case during
  9. *        | a ctrl-break abort
  10. *  1-Jan-86 | <rgd/jmn> Added keyloud
  11. *        | Added initialized flag
  12. * 21-Jan-86 | Abort l_restuntil if Ctrl-C or Ctrl-Break is typed
  13. * 21-Jan-86 | Took out mpu_unknown, replaced with mpu_error_check
  14. *  3-Feb-86 | Fixed MIDI_PROGRAM and MIDI_CHANNEL to subtract one to account
  15. *        | for MIDI encodings, e.g. channel 1 is represented by 0
  16. *  8-Feb-86 | Added midi_exclusive to turn on/off flag in mpu-401.
  17. *        | Added midi_buffer function.
  18. * 18-Feb-86 | Changed midi_exclusive to exclusive.
  19. *        | Added midi_exclusive to send an exclusive message.
  20. * 19-Feb-86 | Changed MC_SEND_... to MC_SND_... to avoid name clash
  21. * 23-Feb-86 | Added midi_control, midi_bend, midi_touch routines
  22. * 24-Feb-86 | Added call to init_asm from musicinit.
  23. * 26-Mar-86 | Added midi_cont call to enable continuous control messages
  24. * 18-Apr-86 | Cleaned up documentation, renamed midi_control to midi_ctrl
  25. *  2-Jun-86 | Added tuning definition code.
  26. * 30-Jun-86 | Added switch to use timdif.asm instead of MPU-401 for timing
  27. * 18-Jul-86 | Added DEBUG switch in parallel with DEBUG in AINTR.ASM
  28. * 29-Jul-86 | Changed trace flag checking to first initialization only.
  29. *  5-Aug-86 | Minor changes for Lattice C Version 3.00
  30. *****************************************************************************/
  31.  
  32. /*
  33.  * Driver for MPU-401
  34.  *
  35.  * This module initializes things and then issues commands to the
  36.  * MPU-401 in response to higher-level operations like note( , , ).
  37.  * Unlike examples in the MPU-401 manual, these routines do not wait
  38.  * for Acks by polling the MPU-401.  Instead, Acks and all other
  39.  * input are handled by the interrupt routine (see aintr.asm), which
  40.  * sets a flag whenever it sees an Ack.     Therefore, these routines
  41.  * just poll the Ack flag rather than directly reading the MPU-401.
  42.  * This avoids the problem of the MPU-401 having data queued in front
  43.  * of the Ack message.
  44.  */
  45.  
  46. /*
  47.  * Interface Specifications for aintr.asm to mpu.c:
  48.  *
  49.  * aintr.asm is an interrupt handler that also parses midi data and
  50.  * queues it for receipt by mpu.c.  In this way, interrupts are hidden
  51.  * from C programmers and yet the mpu-401 never hangs trying to deliver
  52.  * data because the interrupt routine is always ready to read data.
  53.  * 
  54.  * Data is parsed by aintr.asm in order to know how much data to read.
  55.  * To avoid reparsing at the C level, the data is buffered in a
  56.  * queue of messages rather than a simple byte stream.    Each message
  57.  * is a 4-byte block.  The first byte is a status byte and the following
  58.  * bytes (one or two) are data bytes.
  59.  * 
  60.  * Note that timing is not specified.  Later, we may add a parallel
  61.  * buffer to store 4-byte timing blocks if it seems necessary.
  62.  * 
  63.  * System exclusive messages are handled by copying the midi exclusive
  64.  * data into a separate buffer provided by the application program
  65.  * through the midi_buffer call.
  66.  * 
  67.  */
  68.  
  69. /* define DEBUG to enable some extra debugging */
  70. /* #define DEBUG 1 */
  71.  
  72.  
  73. /* define TIMDIF to use the timdif.asm module */
  74. /* #define TIMDIF 1 */
  75.  
  76. #include "cext.h"
  77. #include "stdio.h"
  78. #include "atxt.h"
  79. #include "mpu.h"
  80. #include "midicode.h"
  81. #include "cmdline.h"
  82. #include "userio.h"
  83. #include "pitch.h"
  84. #include "cintr.h"
  85.  
  86. #ifdef TIMDIF
  87. #include "timdif.h"
  88. #endif
  89.  
  90. #define BREAKTEST    if (CBREAK) {    /* Ctrl-C or Ctrl-Break handler */ \
  91.         al_nt_off();\
  92.         printf("Exiting.\n");\
  93.         musicterm();\
  94.         exit(1);\
  95.     }
  96. #define num_voices 16
  97.  
  98. /****************************************************************************
  99. *
  100. * MPU 401 commands
  101. *
  102. ****************************************************************************/
  103.  
  104. #define MC_RESET        0xff
  105. #define MC_SET_TEMPO        0xe0
  106. #define MC_TIMEBASE_192        0xc8
  107. #define MC_START_RECORDING    0x22
  108. #define MC_RECORD_COUNTER    0xab
  109. #define MC_ON_METRONOME        0x85
  110. #define MC_VERSION        0xac
  111. #define MC_REVISION        0xad
  112. #define MC_NO_MEASURE_END    0x8c
  113. #define MC_SND_MIDI        0xd0
  114. #define MC_SND_EXCLUSIVE    0xdf
  115. #define MC_EXCLUSIVE        0x96
  116. #define MC_OFF_BEND        0x86
  117. #define MC_ON_BEND        0x87
  118. #define MC_OFF_THRU        0x88
  119. #define MC_ON_THRU        0x89
  120.  
  121. /****************************************************************************
  122. *
  123. * useful defines and macros
  124. *
  125. ****************************************************************************/
  126.  
  127. #define MD_BEATS_PER_MINUTE    125    /* to get 400 ticks per sec */
  128. #define TICKS_TO_HUNDREDTHS(t)    ((t) >> 2)
  129. #define HUNDREDTHS_TO_TICKS(h)    ((h) << 2)
  130. #define NONE            (-1)
  131.  
  132. /****************************************************************************
  133. *
  134. * MPU-401 interface to IBM-XT
  135. *
  136. ****************************************************************************/
  137.  
  138. #define DATAPORT    0x330        /* Input data port of MPU 401 */
  139. #define STATPORT    0x331        /* status and request port */
  140. #define COMPORT        0x331        /* Send MPU 401 commands to here */
  141. #define DSR        (1<<7)        /* This bit of STATPORT, when low,
  142.                        means the 401 has Data to send */
  143. #define DRR        (1<<6)        /* This bit of STATPORT, when low,
  144.                        means the 401 will take commands */
  145. #define ACK        0xfe        /* Acknowledgement data code */
  146. #define IRQ        2        /* Interrupt request line of 401 */
  147. #define MAX_ACK_WAIT 1000
  148.  
  149. /****************************************************************************
  150. *
  151. * exported flags
  152. *
  153. ****************************************************************************/
  154.  
  155. boolean musictrace = false;    /* enables printed trace of commands */
  156. boolean miditrace = false;    /* enables printed trace of MIDI output */
  157.  
  158. #define n_t_sw 2
  159. private char *t_switches[n_t_sw] = { "-t", "-trace" };
  160.  
  161. #define n_m_sw 2
  162. private char *m_switches[n_m_sw] = { "-m", "-miditrace" };
  163.  
  164. /****************************************************************************
  165. *
  166. * exported variables
  167. *
  168. ****************************************************************************/
  169.  
  170. int keyloud;    /* set to velocity of last getkey event */
  171.  
  172.  
  173. /****************************************************************************
  174. *
  175. * variables shared with aintr.asm
  176. *
  177. ****************************************************************************/
  178.  
  179. int    intnest = 0;    /* do not touch...read-only except by aintr.asm */
  180. int    rd_delay = 0;    /* do not touch...read-only except by aintr.asm */
  181.  
  182. int    Unknown = ACK;
  183. int    interror = 0;    /* reports errors from interrupt handler */
  184. int    timeerr = 0;    /* reports timeout errors */
  185.  
  186. #ifdef DEBUG
  187. int    intcnt = 0;    /* Count of interrupts taken */
  188. int    loop_cnt, loop_max;    /* iteration counts */
  189. #endif
  190.  
  191. long    Ticks;        /* Number of clock ticks since init */
  192. int    Ack;        /* True if command has been acknowledged */
  193. char    MidiTime, MidiStat = 0x90, Midi1, Midi2, Midi3; /* midi and time */
  194. char    exclflag = 0;    /* used by aintr,  DO NOT TOUCH */
  195. int    time_req = 0;    /* set to 1 when Ack will be followed by data */
  196. int    mpu_result;    /* the data following the Ack */
  197.  
  198.  
  199. /****************************************************************************
  200. *
  201. * Variable set by BREAK module
  202. *
  203. ****************************************************************************/
  204.  
  205. int CBREAK;
  206.  
  207.  
  208. /****************************************************************************
  209. *
  210. * variable imported from cintr.c
  211. *
  212. ****************************************************************************/
  213.  
  214. extern int enabled;
  215.  
  216.  
  217. /****************************************************************************
  218. *
  219. * local module variables
  220. *
  221. ****************************************************************************/
  222.  
  223. private int initialized = false;  /* set by musicinit, cleared by musicterm */
  224. private boolean tune_flag = false; /* set by musicinit, never cleared */
  225. private boolean metroflag = false; /* flag to turn on metronome */
  226. private boolean mpuflag = true;    /* true iff mpu401 present */
  227. private int len;        /* length of trace string */
  228. private int last_cmd = 0;    /* last mpu_command, used by trace */
  229. private int user_scale = false; /* true if user-defined scale */
  230. private int bend[num_voices];    /* current pitch bend on channel */
  231. private pitch_table pit_tab[128];    /* scale definition */
  232.  
  233. /* "temporary" instrumentation: how long should we wait? */
  234. private int max_ack_wait = 0;        /* maintained by mpu_wait */
  235.  
  236. /****************************************************************************
  237. *
  238. * functions declared in this module
  239. *
  240. ****************************************************************************/
  241.  
  242. private void    fixup();
  243. private void    mpu_command();
  244. private void    mpu_drr_wait();
  245. private int    mpu_read();
  246. private void    mpu_wait();
  247. private void    mpu_write();
  248. private void    trace_mpu_command();
  249. private void    wfa();
  250.  
  251.  
  252. /****************************************************************************
  253. *
  254. * Buffer 
  255. *    shares data with aintr.asm (the producer)
  256. *
  257. ****************************************************************************/
  258.  
  259. #define BUFFERSIZE 1024
  260. byte    buff[BUFFERSIZE];    /* data buffer */
  261. int    buffhead = 0;        /* buffer pointers */
  262. int    bufftail = 0;
  263.  
  264.  
  265. /****************************************************************************
  266. *
  267. * System exclusive buffer variables (shared with aintr.asm)
  268. *
  269. ****************************************************************************/
  270.  
  271. byte *xbuff = 0;    /* address of the user-supplied buffer */
  272. int xbuffmas;        /* mask for circular buffer address calculation */
  273. int xbuffhea = 0;    /* buffer pointers */
  274. int xbufftai = 0;
  275.  
  276. /****************************************************************************
  277. *                 exclusive
  278. * Inputs:
  279. *    boolean onflag -- set to true to receive midi exclusive data
  280. * Effect: 
  281. *    Tells MPU401 to read exclusive messages into buffer
  282. ****************************************************************************/
  283.  
  284. void exclusive(onflag)
  285.     boolean onflag; /* on or off? */
  286. {
  287.     if  (!initialized) fixup();
  288.     if (musictrace)
  289.         printf("exclusive: %d\n", onflag);
  290.     mpu_command(MC_EXCLUSIVE | (onflag ? 1 : 0));
  291. }
  292.  
  293. /****************************************************************************
  294. *                     fixup
  295. * Effect: 
  296. *    Print error message and call musicinit
  297. ****************************************************************************/
  298.  
  299. private void fixup()
  300. {
  301.     printf("You forgot to call musicinit.  I'll do it for you.\n");
  302.     musicinit();
  303. }
  304.  
  305. /****************************************************************************
  306. *                    getbuf
  307. * Inputs:
  308. *    boolean waitflag: true if routine should wait for data
  309. *    byte * p: Pointer to data destination
  310. * Result: boolean
  311. *    true if data was written to *p
  312. *    false if data not written to *p
  313. * Effect: 
  314. *    copies data from buffer to *p
  315. *    will wait for buffer to become nonempty if waitflag is true
  316. ****************************************************************************/
  317.  
  318. boolean getbuf(waitflag, p)
  319.    boolean waitflag;    /* true if routine should wait for data */
  320.    byte *p;    /* pointer to data destination */
  321. {
  322. /*    register int head;*/
  323.  
  324.     if (!initialized) fixup();
  325.     if (waitflag) while (buffhead == bufftail) /* wait */ ;
  326.     else if (buffhead == bufftail) return false;
  327.  
  328.     *(long *)p = *(long *)(buff+buffhead);
  329.     buffhead += 4;
  330.     if (buffhead >= BUFFERSIZE) buffhead = 0;
  331.  
  332. /* the previous three lines are an optimization of:
  333.  *    head = buffhead;
  334.  *    *p++ = buff[head++];
  335.  *    *p++ = buff[head++];
  336.  *    *p++ = buff[head++];
  337.  *    head++;
  338.  *
  339.  *    if (head >= BUFFERSIZE) head = 0;
  340.  *    buffhead = head;
  341.  */
  342.     return true;
  343. }
  344.  
  345. /****************************************************************************
  346. *                    getkey
  347. * Inputs:
  348. *    boolean waitflag: true if wait until key depression, false if
  349. *              return immediately
  350. * Result: int
  351. *    key number of key which has been depressed
  352. *    It returns -1 if waitflag is false and no key has been pressed
  353. *    If waitflag is true this routine will block until a key is pressed
  354. * Effect: 
  355. *    reads a key
  356. ****************************************************************************/
  357.  
  358. int getkey(waitflag)
  359. {
  360.     byte msg[4];
  361.     int k;
  362.  
  363.     if (!initialized) fixup();
  364.     while (true) {    /* process data until you find a note */
  365.     /* look for data and exit if none found */
  366.     /* NOTE: waitflag will force waiting until data arrives */
  367.     if (!getbuf(waitflag, msg)) { /* nothing there */
  368.         k = -1;
  369.         break;
  370.     } else if ((msg[0] & MIDI_CODE_MASK) == MIDI_ON_NOTE) {
  371.         if (msg[2] == 0) { /* velocity 0 -> note off */
  372.         keyloud = 0;
  373.         k = (msg[1]-12) + 128;
  374.         } else {
  375.         keyloud = msg[2];
  376.         k = (msg[1]-12);
  377.         }
  378.         break;
  379.     } else if ((msg[0] & MIDI_CODE_MASK) == MIDI_OFF_NOTE) {
  380.         keyloud = 0;
  381.         k = (msg[1]-12) + 128;
  382.         break;
  383.     }
  384.     }
  385.     if (musictrace) {
  386.     if (k != -1) printf("getkey got %d\n", k);
  387.     }
  388.     return k;
  389. }
  390.  
  391. /****************************************************************************
  392. *                    gettime
  393. * Result: long
  394. *    current timestamp from MPU-401
  395. *     Return the time in 100ths of seconds since the last call to
  396. *     musicinit or timereset
  397. * Effect: 
  398. *    Reads the MPU-401 time
  399. ****************************************************************************/
  400.  
  401. /* just to make sure we're using the timdif module: */
  402. long gettime()
  403. {
  404.     BREAKTEST    /* abort if user typed Ctrl Break */
  405.  
  406.     if    (!initialized) fixup();
  407. #ifndef TIMDIF
  408.     time_req = 1;    /* tell aintr.asm to read extra byte */
  409.     mpu_command(MC_RECORD_COUNTER);        /* Read counter */
  410.     return TICKS_TO_HUNDREDTHS(Ticks);
  411. #else
  412.     return ibm_time();
  413. #endif
  414. }
  415.  
  416. /****************************************************************************
  417. *                    l_rest
  418. * Inputs:
  419. *    long time: Amount of time to rest
  420. * Effect: 
  421. *    Waits until the amount of time specified has lapsed
  422. ****************************************************************************/
  423.  
  424. void l_rest(time)
  425.     long time;
  426. {
  427.     if (!initialized) fixup();
  428.     l_restuntil(time + gettime());    
  429. }
  430.  
  431. /****************************************************************************
  432. *                  l_restuntil
  433. * Inputs:
  434. *    long time: Event time to rest until
  435. * Effect: 
  436. *    Waits until the specified time has been reached (absolute time)
  437. ****************************************************************************/
  438.  
  439. void l_restuntil(time)
  440.     long time;
  441. {
  442.     while(time > gettime()) ;
  443. }
  444.  
  445. /****************************************************************************
  446. *                metronome
  447. * Inputs:
  448. *    int onflag: true or false
  449. * Effect:
  450. *    enables (true) or disables (false) MPU-401 metronome function.
  451. *    must be called before musicinit
  452. ****************************************************************************/
  453.  
  454. void metronome(onflag)
  455.     int onflag;
  456. {
  457.     metroflag = onflag;
  458. }
  459.  
  460. /****************************************************************************
  461. *                   midi_bend
  462. * Inputs:
  463. *    int channel: midi channel on which to send data
  464. *    int value: pitch bend value
  465. * Effect: 
  466. *    Sends a midi pitch bend message
  467. ****************************************************************************/
  468.  
  469. void midi_bend(channel, value)
  470.     int channel, value;
  471. {
  472.     if    (!initialized) fixup();
  473.     if (musictrace)
  474.     printf("midi_bend: ch %d, val %d\n", channel, value);
  475.     bend[MIDI_CHANNEL(channel)] = value;
  476.     mpu_command(MC_SND_MIDI);
  477.     mpu_write(MIDI_BEND | MIDI_CHANNEL(channel));
  478.     mpu_write(MIDI_DATA(value));
  479.     mpu_write(MIDI_DATA(value>>7));
  480. }
  481.  
  482. /****************************************************************************
  483. *                midi_buffer
  484. * Inputs:
  485. *    byte * buffer: the buffer address
  486. *    int size: number of bytes in buffer
  487. * Returns:
  488. *    false if size is less than 16 or buffer is NULL, otherwise true
  489. * Effect:
  490. *    tells interrupt routine to store system exclusive messages in
  491. *    buffer.     The largest power of 2 bytes less than size will be
  492. *    used.  xbuffhea and xbufftai will be initialized to zero,
  493. *    and xbufftai will be one greater than the index of the last
  494. *    system exclusive byte read from mpu401.
  495. ****************************************************************************/
  496.  
  497. int midi_buffer(buffer, size)
  498.     byte *buffer;
  499.     int size;
  500. {
  501.     int mask;
  502.     mask = 16 - 1;
  503.     if (size < 16 || buffer == NULL) return false;
  504.     while (mask < size && mask > 0) mask = (mask << 1) + 1;
  505.     xbuff = NULL;    /* turn off buffering */
  506.     xbuffmas = mask >> 1;
  507.     xbuffhea = xbufftai = 0;
  508.     xbuff = buffer;    /* set buffer, turn on buffering */
  509.     return true;
  510. }
  511.  
  512. /****************************************************************************
  513. *                midi_cont
  514. * Inputs:
  515. *    boolean onflag: true or false
  516. * Effect:
  517. *    enables (true) or disables (false) continuous control info from
  518. *    MPU-401 to host.
  519. ****************************************************************************/
  520.  
  521. void midi_cont(onflag)
  522.     boolean onflag;
  523. {
  524.     if (onflag) mpu_command(MC_ON_BEND);
  525.     else mpu_command(MC_OFF_BEND);
  526. }
  527.  
  528. /****************************************************************************
  529. *                   midi_ctrl
  530. * Inputs:
  531. *    int channel: midi channel on which to send data
  532. *    int control: control number
  533. *    int value: control value
  534. * Effect: 
  535. *    Sends a midi control change message
  536. ****************************************************************************/
  537.  
  538. void midi_ctrl(channel, control, value)
  539.     int channel, control, value;
  540. {
  541.     if (!initialized) fixup();
  542.     if (musictrace)
  543.     printf("midi_ctrl: ch %d, ctrl %d, val %d\n", 
  544.         channel, control, value);
  545.     mpu_command(MC_SND_MIDI);
  546.     mpu_write(MIDI_CTRL | MIDI_CHANNEL(channel));
  547.     mpu_write(MIDI_DATA(control));
  548.     mpu_write(MIDI_DATA(value));
  549. }
  550.  
  551. /****************************************************************************
  552. *                 midi_exclusive
  553. * Inputs:
  554. *    byte * msg: pointer to a midi exclusive message, terminated by 0xF7
  555. * Effect: 
  556. *    Sends a midi exclusive message
  557. ****************************************************************************/
  558.  
  559. void midi_exclusive(msg)
  560.     byte *msg;    /* the data to be sent */
  561. {
  562.     int i;    /* can DX7 keep up? */
  563.  
  564.     /* if user mistakenly called midi_exclusive instead of exclusive,
  565.      * the argument will be true or false, both of which are highly    
  566.      * unlikely valid arguments for midi_exclusive:
  567.      */
  568.     if (msg == (byte *) false || msg == (byte *) true) {
  569.     printf("midi_exclusive: invalid argument %d.\n", (int) msg);
  570.     if (initialized) musicterm();
  571.     exit(1);
  572.     }
  573.  
  574.     if    (!initialized) fixup();
  575.     if (musictrace) printf("midi_exclusive\n");
  576.     mpu_command(MC_SND_EXCLUSIVE);
  577.     while (*msg != MIDI_EOX) {
  578.     mpu_write(*msg);
  579.     msg++;
  580.     /* This is a delay loop.  Without it, your DX7 will crash. */
  581.     for (i = (ATXT() == ISAT ? 4 : 2); i > 0; i--) {
  582.         BREAKTEST
  583.     }
  584.     }
  585.     mpu_write(MIDI_EOX);
  586. }
  587.  
  588. /****************************************************************************
  589. *                   midi_note
  590. * Inputs:
  591. *    int channel: midi channel on which to send data
  592. *    int pitch: midi pitch code
  593. *    int velocity: velocity with which to sound it (0=> release)
  594. * Effect: 
  595. *    Sends a midi note-play request out
  596. ****************************************************************************/
  597.  
  598. void midi_note(channel, pitch, velocity)
  599.     int channel, pitch, velocity;
  600. {
  601.     if    (!initialized) fixup();
  602.     if (musictrace)
  603.     printf("midi_note: ch %d, key %d, vel %d\n",
  604.         channel, pitch, velocity);
  605.     if (user_scale) {
  606.     /* check for correct pitch bend */
  607.     if ((pit_tab[pitch+12].pbend != bend[MIDI_CHANNEL(channel)]) &&
  608.         (velocity != 0)) {
  609.         midi_bend(channel, pit_tab[pitch+12].pbend);
  610.         bend[channel] = pit_tab[pitch+12].pbend;
  611.     }
  612.     pitch = pit_tab[pitch+12].ppitch;
  613.     }
  614.     mpu_command(MC_SND_MIDI);
  615.     mpu_write(MIDI_ON_NOTE | MIDI_CHANNEL(channel));
  616.     mpu_write(MIDI_DATA(12 + pitch)); /* cmu standard to midi standard */
  617.     mpu_write(MIDI_DATA(velocity));
  618. }
  619.  
  620. /****************************************************************************
  621. *                 midi_program
  622. * Inputs:
  623. *    int channel: Channel on which to send midi program change request
  624. *    int program: Program number to send (decremented by 1 before
  625. *            being sent as midi data)
  626. * Effect: 
  627. *    Sends a program change request out the channel
  628. ****************************************************************************/
  629.  
  630. void midi_program(channel, program)
  631.     int channel;    /* midi channel */
  632.     int program;    /* the program number */
  633. {
  634.     if    (!initialized) fixup();
  635.     if (musictrace)
  636.     printf("midi_program: ch %d, prog %d\n",
  637.         channel, program);
  638.     mpu_command(MC_SND_MIDI);
  639.     mpu_write(MIDI_CH_PROGRAM | MIDI_CHANNEL(channel));
  640.     mpu_write(MIDI_PROGRAM(program));
  641. }
  642.  
  643. /****************************************************************************
  644. *                midi_thru
  645. * Inputs:
  646. *    boolean onflag: true or false
  647. * Effect:
  648. *    enables (true) or disables (false) midi thru info from
  649. *    MPU-401 to host.  (Default is set; reset with cmdline -block.)
  650. ****************************************************************************/
  651.  
  652. void midi_thru(onflag)
  653.     boolean onflag;
  654. {
  655.     if (onflag) mpu_command(MC_ON_THRU);
  656.     else mpu_command(MC_OFF_THRU);
  657. }
  658.  
  659. /****************************************************************************
  660. *                   midi_touch
  661. * Inputs:
  662. *    int channel: midi channel on which to send data
  663. *    int value: control value
  664. * Effect: 
  665. *    Sends a midi after touch message
  666. ****************************************************************************/
  667.  
  668. void midi_touch(channel, value)
  669.     int channel, value;
  670. {
  671.     if    (!initialized) fixup();
  672.     if (musictrace)
  673.     printf("midi_touch: ch %d, val %d\n", channel, value);
  674.     mpu_command(MC_SND_MIDI);
  675.     mpu_write(MIDI_TOUCH | MIDI_CHANNEL(channel));
  676.     mpu_write(MIDI_DATA(value));
  677. }
  678.  
  679. /****************************************************************************
  680. *                   mpu_command
  681. * Inputs:
  682. *    int c: Character to write to MPU-401 command port
  683. * Effect: 
  684. *    Writes the data to the MPU-401 command port
  685. ****************************************************************************/
  686.  
  687. private void mpu_command(c)
  688.     int c;
  689. {
  690.     if (!mpuflag) { /* simulated */
  691.     trace_mpu_command(c);
  692.     } else { /* real */
  693.     if (miditrace) trace_mpu_command(c);
  694.     mpu_drr_wait();
  695.     Ack = 0;
  696.     outp(COMPORT, c);
  697.     if (enabled) mpu_wait();
  698.     else wfa();
  699.     }
  700. }
  701.  
  702. /****************************************************************************
  703. *                 mpu_drr_wait
  704. * Effect: 
  705. *    Waits until the MPU-401 is ready to receive data
  706. ****************************************************************************/
  707.  
  708. #define MAX_TRIES    2000
  709.  
  710. private void mpu_drr_wait()
  711. {
  712.     int i;
  713.  
  714.     if (!mpuflag) return;    /* always ready if not there! */
  715.  
  716.     for (i = 0; i < MAX_TRIES; i++)
  717.     if ((inp(STATPORT) & DRR) == 0) break;
  718. #ifdef DEBUG
  719.     if (i == MAX_TRIES)
  720.     printf("mpu-401 not ready to receive; intcnt=%d\n",intcnt);
  721. #endif
  722. }
  723.  
  724. /****************************************************************************
  725. *                  mpu_error_check
  726. * Effect: 
  727. *    Reports any errors originating in the interrupt handler
  728. ****************************************************************************/
  729.  
  730. void mpu_error_check()
  731. {
  732.     if (Unknown != ACK) {
  733.     printf("Unknown command: %x\n", Unknown);
  734.     Unknown = ACK;
  735.     }
  736.     if (interror != 0) {
  737.     char *cause;
  738.     switch (interror) {
  739.         case NESTERR: cause = "nested interrupts";    break;
  740.         case BUFFERR: cause = "buffer overflow";    break;
  741.         case CMDERR:  cause = "unknown command";    break;
  742.         default: cause = "";           break;
  743.     }
  744.     printf("interror: %s\n", cause);
  745.     if (*cause == 0) printf("%d\n", interror);
  746.  
  747.     interror = 0;
  748.     }
  749.     if (timeerr != 0) {
  750.     if (timeerr == TIMEOUT) printf("timeerr: timeout error\n");
  751.     else printf("timeerr = %d\n", timeerr);
  752.     timeerr = 0;
  753.     }
  754. }
  755.  
  756. /****************************************************************************
  757. *                   mpu_read
  758. * Result: int
  759. *    character read from MPU-401
  760. * Effect: 
  761. *    Reads the MPU-401
  762. ****************************************************************************/
  763.  
  764. private int mpu_read()
  765. {
  766.     int delay;
  767.     for (delay = 0; delay < 2000; delay++) {
  768.     if ((inp(STATPORT) & DSR) == 0)
  769.         return inp(DATAPORT);
  770.     }
  771. #ifdef DEBUG
  772.     printf("mpu_read: DSR never went low, returning 0, intcnt=%d\n",intcnt);
  773. #endif
  774.     return 0;
  775. }
  776.  
  777. /****************************************************************************
  778. *                   mpu_wait
  779. * Effect: 
  780. *    Called when interrupts are enabled.  Polls the 'Ack' flag, which is
  781. *    set by the interrupt handler.  If more than MAX_ACK_WAIT iterations
  782. *    occur without 'Ack' being set, issues an error message.
  783. *    Ack is cleared when it is detected.
  784. ****************************************************************************/
  785.  
  786. private void mpu_wait()
  787. {
  788.     int ackcnt; /* delay counter */
  789.  
  790.     if (!mpuflag) return;
  791.  
  792.     for (ackcnt = 0; ackcnt < MAX_ACK_WAIT; ackcnt++) {
  793.     if (Ack) {
  794.         if (max_ack_wait < ackcnt) max_ack_wait = ackcnt;
  795.         Ack = 0;
  796.         return;
  797.     }
  798.     }
  799. #ifdef DEBUG
  800.     printf("mpu_wait: No ack; incnt = %d\n",intcnt);
  801. #endif
  802. }
  803.  
  804. /****************************************************************************
  805. *                   mpu_write
  806. * Inputs:
  807. *    int c: Character to write to MPU-401 data port
  808. * Effect: 
  809. *    Writes the data to the MPU-401 data port
  810. ****************************************************************************/
  811.  
  812. private void mpu_write(c)
  813.     int c;
  814. {
  815.     if (!mpuflag) { /* simulate */
  816.     printf("%02x",c);
  817.     len += 2;
  818.     } else { /* real */
  819.     if (miditrace) { /* trace */
  820.         printf("%02x",c);
  821.         len += 2;
  822.     } /* trace */
  823.     mpu_drr_wait();
  824.     outp(DATAPORT, c);
  825.     }
  826. }
  827.  
  828. /****************************************************************************
  829. *                mpuexists
  830. * Inputs:
  831. *    boolean flag: true or false
  832. * Effect:
  833. *    if argument is false, indicates no mpu is on the machine, so
  834. *    simulate mpu-401 (for debugging only)
  835. ****************************************************************************/
  836.  
  837. void mpuexists(flag)
  838.     boolean flag;
  839. {
  840.     mpuflag = flag;
  841. }
  842.  
  843. /*****************************************************************
  844. *            set_pitch_default
  845. *****************************************************************/
  846. private void set_pitch_default()
  847. {
  848.     int i;
  849.  
  850.     for (i = 0; i < 128; i++) {
  851.     pit_tab[i].pbend = 8192;
  852.     pit_tab[i].ppitch = i;
  853.     }
  854. }
  855.  
  856. /*****************************************************************
  857. *            read_tuning
  858. *****************************************************************/
  859.  
  860. void read_tuning(filename)
  861.     char *filename;
  862. {
  863.     int index, pit, lineno = 0;
  864.     float bend;
  865.     FILE *fpp;
  866.  
  867.     user_scale = true;
  868.     set_pitch_default();
  869.     fpp = fileopen(filename, "tun", "r", "Tuning definition file");
  870.     while ((fscanf(fpp, "%d %d %f\n", &index, &pit, &bend) > 2) &&
  871.        (lineno < 128)) {
  872.     lineno++;
  873.     if (index >= -12 && index <= 115) {
  874.         pit_tab[index+12].pbend = (int)(8192 * bend/100 + 8192);
  875.         pit_tab[index+12].ppitch = pit;
  876.     }
  877.     }
  878. }
  879.  
  880.  
  881. /****************************************************************************
  882. *                   musicinit
  883. * Effect: 
  884. * Initialize the mpu 401 device driver
  885. *    Initialize mpu 401
  886. *        Reset 401, change defaults
  887. *    Set up interrupts
  888. *    Start up mpu record clock
  889. ****************************************************************************/
  890.  
  891. void musicinit()
  892. {
  893.     int version, revision;
  894.     int i;
  895.     char *filename;
  896.  
  897.     if (!tune_flag) {    /* do this code only once */
  898.     miditrace = (cl_nswitch(m_switches, n_m_sw) != NULL);
  899.     musictrace = (cl_nswitch(t_switches, n_t_sw) != NULL);
  900.  
  901.         tune_flag = true;
  902.     filename = cl_option("-tune");
  903.     if (filename != NULL) {
  904.         read_tuning(filename);
  905.     }
  906.  
  907.     intr_init();
  908.     }
  909.  
  910.     last_cmd = 0;
  911.  
  912. #ifdef TIMDIF
  913.     if (!initialized) settime();
  914. #endif
  915.  
  916.     initialized = true;
  917.  
  918.     intr_disable(IRQ);        /* Turn off 401 interrupts */
  919.  
  920.     for (i = 0; i < 100; i++) { /* flush out buffer, ignore DSR */
  921.     inp(DATAPORT);
  922.     }
  923.  
  924.     mpu_command(MC_RESET);    /* Reset the device */
  925.  
  926.     mpu_command(MC_VERSION);
  927.     version = mpu_read();
  928.  
  929.     mpu_command(MC_REVISION);
  930.     revision = mpu_read();
  931.  
  932.     mpu_command(MC_SET_TEMPO);    /* Set tempo and timebase to get */
  933.     mpu_write(MD_BEATS_PER_MINUTE);    /* 400 ticks per second */
  934.  
  935.     mpu_command(MC_TIMEBASE_192);
  936.  
  937.     if (metroflag)
  938.     mpu_command(MC_ON_METRONOME);    /* Just for debugging */
  939.  
  940.     mpu_command(MC_NO_MEASURE_END);    /* Don't want measure end bytes */
  941.  
  942.     init_asm();            /* Do any asm init needed(aintr.asm)*/
  943.     intr_routine(IRQ);        /* Set up vector */ 
  944.  
  945.     CBREAK = false;
  946.     setctl();            /* Set up ctrl-break intercept */
  947.  
  948. #ifdef DEBUG
  949.     loop_max = 0;
  950. #endif
  951.     intr_enable(IRQ);        /* allow 401 interrupts */
  952.  
  953.     if (user_scale) {
  954.     for (i = 0; i < num_voices; i++) {
  955.         midi_bend(i, 8192);
  956.         bend[i] = 8192;
  957.     }
  958.     }
  959.     midi_thru(!(cl_switch("-block")));    /* set MIDI thru on MPU-401 */
  960.  
  961.     timereset();        /* Reset clock */
  962. }
  963.  
  964. /****************************************************************************
  965. *                   musicterm
  966. * Effect: 
  967. *    Cleans up; disables MPU-401 interrupts; resets MIDI devices
  968. ****************************************************************************/
  969.  
  970. void musicterm()
  971. {
  972.     if (initialized) {
  973. #ifdef TIMDIF
  974.     cletime();
  975. #endif
  976.     intr_disable(IRQ);    /* No more 401 interrupts */
  977. #ifdef DEBUG
  978.     printf("loop_max is %d\n", loop_max);
  979. #endif
  980.     clrctl();        /* reset ctrl-break handler */
  981.     intr_cleanup(IRQ);    /* Restore default vector */
  982.     mpu_command(MC_RESET);    /* Reset the device */
  983.     initialized = false;
  984.     }
  985. /*  printf("maximum successful wait for ack: %d\n", max_ack_wait);*/
  986. }
  987.  
  988. /****************************************************************************
  989. *                    random
  990. * Inputs:
  991. *    int lo: Lower limit of value
  992. *    int hi: Upper limit of value
  993. * Result: int
  994. *    random number (lo <= result <= hi)
  995. ****************************************************************************/
  996.  
  997. private long seed = 1534781;
  998.  
  999. int random(lo, hi)
  1000.     int lo, hi;
  1001. {
  1002.     seed *= 13;
  1003.     seed += 1874351;
  1004.     return (int) (lo + 
  1005.         (((hi + 1 - lo) * ((0x00ffff00 & seed) >> 8)) >> 16));
  1006. }
  1007.  
  1008. /****************************************************************************
  1009. *                   timereset
  1010. * Effect: 
  1011. *    Resets the time on the MPU-401.     Ticks is reset to 0
  1012. ****************************************************************************/
  1013.  
  1014. void timereset()
  1015. {
  1016.     if (!initialized) fixup();
  1017.     if (musictrace) printf("timereset()\n");
  1018.     Ticks = 0;                /* Reset clock */
  1019.     mpu_command(MC_START_RECORDING);    /* Starts up clock */
  1020. #ifdef TIMDIF
  1021.     cletime();
  1022.     settime();
  1023. #endif    
  1024. }
  1025.  
  1026. /****************************************************************************
  1027. *                   trace
  1028. * Inputs:
  1029. *    boolean flag: true for trace on
  1030. * Effect: 
  1031. *    turns tracing on (flag == true) or off (flag == false)
  1032. ****************************************************************************/
  1033. void trace(flag)
  1034.     boolean flag;
  1035. {
  1036.     musictrace = flag;
  1037. }
  1038.  
  1039. /****************************************************************************
  1040. *                   tracemidi
  1041. * Inputs:
  1042. *    boolean flag: true for trace on
  1043. * Effect: 
  1044. *    turns midi tracing on (flag == true) or off (flag == false)
  1045. ****************************************************************************/
  1046. void tracemidi(flag)
  1047.     boolean flag;
  1048. {
  1049.     miditrace = flag;
  1050. }
  1051.  
  1052. /****************************************************************************
  1053. *                   trace_mpu_command
  1054. * Inputs:
  1055. *    int c: Command
  1056. * Effect: 
  1057. *    Writes command to stdout
  1058. ****************************************************************************/
  1059.  
  1060. private void trace_mpu_command(c)
  1061.     int c;
  1062. {
  1063.     char * p;
  1064.     char buf[10];
  1065.  
  1066.     switch(c) { /* decode */
  1067.     case MC_RESET:
  1068.         p = " RESET:";
  1069.         break;
  1070.     case MC_ON_METRONOME:
  1071.         p =" MET-ON:";
  1072.         break;
  1073.     case MC_SET_TEMPO:
  1074.         p =" TEMPO:";
  1075.         break;
  1076.     case MC_TIMEBASE_192:
  1077.         p =" TIME-192:";
  1078.         break;
  1079.     case MC_START_RECORDING:
  1080.         p =" REC-ON:";
  1081.         break;
  1082.     case MC_VERSION:
  1083.         p =" VERSION:";
  1084.         break;
  1085.     case MC_REVISION:
  1086.         p =" REVISION:";
  1087.         break;
  1088.     case MC_NO_MEASURE_END:
  1089.         p =" NO-MEAS-END:";
  1090.           break;
  1091.     case MC_SND_MIDI:
  1092.         p =" MIDI:";
  1093.         break;
  1094.     case MC_RECORD_COUNTER:
  1095.         if (last_cmd == c) p = "#";
  1096.         else p = " COUNTER:";
  1097.         break;
  1098.     case MC_ON_BEND:
  1099.         p = "Bender:On";
  1100.         break;
  1101.     case MC_OFF_BEND:
  1102.         p = "Bender:Off";
  1103.         break;
  1104.     case MC_ON_THRU:
  1105.         p = "Thru:On";
  1106.         break;
  1107.     case MC_OFF_THRU:
  1108.         p = "Thru:Off";
  1109.         break;
  1110.     default:sprintf(buf," %02x",c);
  1111.         p = buf;
  1112.         break;
  1113.     } /* decode */
  1114.  
  1115.     last_cmd = c;
  1116.  
  1117.     if (len + strlen(p) > 70) { /* overflow */
  1118.     printf("\n");
  1119.     len = 0;
  1120.     } /* overflow */
  1121.     len += strlen(p);
  1122.     printf("%s",p);
  1123. }
  1124.  
  1125. /****************************************************************************
  1126. *                      wfa
  1127. * Effect: 
  1128. *    Waits for an acknowledgement from the MPU-401.    Will not wait more
  1129. *    than MAX_ACK_WAIT iterations thru its loop.
  1130. * Conditions:
  1131. *    Called only if interrupts are not enabled, and the MPU-401 is
  1132. *    being polled
  1133. ****************************************************************************/
  1134.  
  1135.  
  1136. private void wfa()
  1137. {
  1138.     int ackcnt;
  1139.     int x;
  1140.    
  1141.     if (!mpuflag) return;
  1142.  
  1143.     for (ackcnt = 0; ackcnt < MAX_ACK_WAIT; ackcnt++)
  1144.     if ((x = mpu_read()) == ACK) break;
  1145. #ifdef DEBUG
  1146.     else printf("wfa: got %x; intcnt = %d\n", x, intcnt);
  1147. #endif
  1148. }
  1149.  
  1150.  
  1151. /* From here my own routine begins */
  1152.  
  1153. al_nt_off()
  1154. {
  1155.     static    int    c;
  1156.     for (c = 0; c < 16; c++)    {
  1157.         mpu_write( 0xb0 + c);
  1158.         mpu_write(123);
  1159.         mpu_write(0);
  1160.     }
  1161. }
  1162.  
  1163.