10 REM > MIDI-IN2
   20 REM Redirect incoming MIDI to SOUND
   30 :
   40 REM Note: Even though the MIDI port is being read in machine code,
   50 REM the BASIC code that calls it runs too slow, so after a while
   60 REM data bytes get dropped, and subsequent bytes are read in the
   70 REM wrong order, reading byte 2 of command 1 followed by byte 1 of
   80 REM then next command.
   90 :
  100 REM The conventional method of doing MIDI input like this is that
  110 REM the MIDI input is read by a background interupt handler that
  120 REM fills a buffer, and the foreground polls and reads from the
  130 REM buffer - similar to the serial input buffer.
  140 :
  150 REM Alternatively, a common method is that the MIDI input is read
  160 REM in a fast machine code loop in the /foreground/ and the input
  170 REM processing is done in the /background/ - the opposite way to 
  180 REM normal.
  190  :
  200  DIM mcode% 100
  210  mCtrl=&FCF0
  220  mData=mCtrl+1
  230  FOR I%=0 TO 1
  240    P%=mcode%
  250    [OPT I%*3
  260    LDY command                   :\ Y is current command
  270    .loop1
  280    BIT &FF:BMI esc
  290    LDA mCtrl:AND #1:BEQ loop1    :\ Wait for byte
  300    LDA mData                     :\ Get byte
  310    BPL TestCommand               :\ Data byte, use current command
  320    .readcommand
  330    CMP #&F0:BCS loop1            :\ Ignore system commands
  340    TAY                           :\ Make this the current command byte
  350    .waitfor1
  360    BIT &FF:BMI esc
  370    LDA mCtrl:AND #1:BEQ waitfor1 :\ Wait for first data byte
  380    LDA mData:BMI readcommand     :\ Another command, loop back
  390    .TestCommand
  400    TAX                           :\ First data byte
  410    CPY #&E0:BCS waitfor2         :\ &Ex has two data bytes
  420    CPY #&C0:BCS nomore           :\ &Cx-&Dx has one data byte
  430                                  :\ &8x-&Bx has two data bytes
  440    .waitfor2
  450    BIT &FF:BMI esc
  460    LDA mCtrl:AND #1:BEQ waitfor2 :\ Wait for a byte
  470    LDA mData:BMI readcommand     :\ Get second data byte
  480    \    Y=command, X=1st data byte, A=2nd data byte
  490    \ or Y=command, X=only data byte
  500    .nomore
  510    STA byte2
  520    STX byte1
  530    STY command
  540    TYA
  550    .esc
  560    RTS
  570    .command:BRK
  580    .byte1:BRK
  590    .byte2:BRK
  600    ]
  610  NEXT I%
  620  :
  630  REM Demo code
  640  ?mCtrl=&03:REM Reset
  650  ?mCtrl=&16:REM Set clock speed
  660  ?command=&90                  :REM Set current command to 'note on'
  670  REPEAT
  680    cmd%=(USR(mcode%))AND&F0      :REM Wait for command
  690    PRINT ?command, ?byte1, ?byte2
  700    IF cmd%=&90:SOUND &11,-10 AND (?byte2>0),?byte1*4-138,20 :REM Note On
  710    IF cmd%=&80:SOUND &11,0,0,0                              :REM Note Off
  720  UNTIL FALSE