home *** CD-ROM | disk | FTP | other *** search
Text File | 1986-08-22 | 71.4 KB | 2,094 lines |
- ####################################################################
- The text following is six separate program files, three each for two
- separate programs. They are separated by a line of "###'s" and must
- be each culled out of this file before assembly or compilation. The
- first three files are "MPRIM.ASM", "MPU.H", and "TESTMPU.C". These
- comprise the beginning of an interrupt driven program using the
- Roland MPU-401 in its "intelligent" mode. This might be assumed to
- be the best mode for writing sequencer and recorder programs,
- especially if memory resources are limited. There is a drawback in
- this mode, in that any software written for it becomes chained to
- usage with the MPU. If you have an eye to transporting your work to
- such as the Arari/ST, this is not so good. Also, while the MPU is
- impressive, it was designed to be memory efficient when used as the
- foundation for a sequencer/recorder. If you are looking to set up
- musical phrases as, say LISP s-expressions, it might not be so great.
- For these two reasons, and for others I haven't thought of, you might
- want to put the MPU to sleep, and just use it as a dumb MIDI port.
- The second three program files do just that. They are "MIDI.ASM",
- "MIDI.H", and "TESTMIDI.C" All were written for the Microsoft
- Assembler version 3 or higher, and the Microsoft C compiler, version
- 4 (the new one). Both resulting programs do work on my Kaypro 286i
- (an AT-clone). They may or may not work on your machine. I have
- left the copyright notice intact because I wish to emphasize that
- these programs are suitable only for pointing other MPU programmers
- in the right direction. There are dead ends and (likely) errors.
- Used with caution as a guide to your own programs, they might be
- usefull. Used without thought or understanding, and I guarantee they
- will be more trouble than they are worth. With that cheery thought,
- I wish you good luck.
-
- John Dunn
- January, 1986
-
- ###############################################################
- PAGE 60,127
- TITLE MPU primitives
- NAME MPRIM
- .SALL
- ;==============================================================
- ; COPYRIGHT (C) 1986 John Dunn
- ;--------------------------------------------------------------
- ; date: 01/02/86
- ; update: 01/02/86
- ; last hacker: John Dunn
- ;==============================================================
- PRIM_TEXT SEGMENT BYTE PUBLIC 'CODE'
- PRIM_TEXT ENDS
- CONST SEGMENT WORD PUBLIC 'CONST'
- CONST ENDS
- _BSS SEGMENT WORD PUBLIC 'BSS'
- _BSS ENDS
- _DATA SEGMENT WORD PUBLIC 'DATA'
- _DATA ENDS
- DGROUP GROUP CONST, _BSS, _DATA
- ;==============================================================
- _DATA SEGMENT WORD PUBLIC 'DATA'
- ;--------------------------------------------------------------
- PUBLIC _indexp,_indext,_channel,_rtmsg,_pending
- PUBLIC _recording,_playing,_loading,_enderr
- ;--------------------------------------------------------------
- _channel dw 0 ; current midi channel
- _rtmsg dw 0 ; real time message flag
- _pending dw 0 ; number of sys excl pending
- _recording dw 0 ; nz when recording track data
- _playing dw 0 ; nz when playing track data
- _loading dw 0 ; nz when loading para data
- _enderr dw 0 ; nz if put index at limit
- _indext dw 0 ; index track buffer
- _indexp dw 0 ; index param buffer
- startt dw 0 ; start track buffer
- startp dw 0 ; start param buffer
- endtrk dw 0 ; end track buffer
- endpar dw 0 ; end param buffer
- limitt dw tbufx-_tbuf ; track buffer limit
- limitp dw pbufx-_pbuf ; param buffer limit
-
- icount dw 0 ; midi msg count index
- rcount dw 0 ; midi msg run count
- pcount dw 0 ; play track count
-
- clkblp dw 0 ; clock blip count
-
- intval dw 0 ; inte data value
- special dw 0 ; nz = special routine
- sptable dw dotimev,procsm,sysexc,songsel,songp1,songp2
-
- ;--------------------------------------------------------------
- _DATA ENDS
- ;==============================================================
- PBUF_DATA SEGMENT PARA MEMORY 'BUFFER'
- ;--------------------------------------------------------------
- PUBLIC _pbuf
- ;--------------------------------------------------------------
- _pbuf db 17000 dup(?) ; parameter buffer
- pbufx db 0
- ;--------------------------------------------------------------
- PBUF_DATA ENDS
- ;==============================================================
- TBUF_DATA SEGMENT PARA MEMORY 'BUFFER'
- ;--------------------------------------------------------------
- PUBLIC _tbuf
- ;--------------------------------------------------------------
- _tbuf db 16384 dup(?) ; parameter buffer
- tbufx db 0
- ;--------------------------------------------------------------
- TBUF_DATA ENDS
- ;==============================================================
- PRIM_TEXT SEGMENT
- ASSUME CS: PRIM_TEXT, DS: DGROUP, SS: DGROUP, ES: DGROUP
- ;==============================================================
- bpo equ 6 ; base pointer offset
- ; 6 = large model; 4 = small
- p1 equ bpo ; single word arg 1, use [bp+@1]
- p2 equ bpo+2 ; single word arg 2, use [bp+@2]
- ;--------------------------------------------------------------
- mdata equ 0330H ; mpu data port address
- mstat equ 0331H ; mpu status port address
- mcmd equ 0331H ; mpu command port address
- mdsr equ 80H ; mpu data set ready, active low
- mdrr equ 40H ; mpu data read ready, active low
- ;--------------------------------------------------------------
- ; initialize mpu, int vectors, etc.
- ; must be called once only on startup
- ;
- public _initm
- _initm proc far
- push es ; save current es
- mov ah,35h ; get current int 2
- mov al,0AH
- int 21H
- mov word ptr cs:orgint+3,es ; save it
- mov word ptr cs:orgint+1,bx
- pop es ; restore es
-
- push ds ; save current ds
- mov ah,25H ; set int vect
- mov al,0AH ; int 2 for MPU
- mov dx,seg mpuint
- mov ds,dx
- mov dx,offset mpuint
- int 21H ; set new int vect
- pop ds ; restore ds
-
- mov dx,mdata ; clear data port
- in al,dx
-
- in al,21H ; enable irq2
- jmp short $+2 ; delay for AT
- and al,0FBH
- out 21H,al
- sti ; enable ints
- ret
- _initm endp ; end of init mpu
-
- ;--------------------------------------------------------------
- ; shutdown mpu, restore int vectors, etc.
- ; must be called once only on exit
- ;
- public _exitm
- _exitm proc far
- in al,21H ; disable irq2
- jmp short $+2 ; delay for AT
- or al,4
- out 21H,al
-
- push ds
- mov ah,25h ; restore previous irq2
- mov al,0AH
- mov dx,word ptr cs:orgint+3
- mov ds,dx
- mov dx,word ptr cs:orgint+1
- int 21h
- pop ds
- ret
- _exitm endp
-
- ;--------------------------------------------------------------
- ; this routine is only called by int 2
- ; if it was not generated by the mpu, it vectors
- ; to the original int address, otherwise it saves
- ; registers, then calls the c routine _mpuint,
- ; after which it restores registers, clears nmi
- ; and returns from int.
- ;
- mpuint proc far
- push ax ; save ax
- push dx
- mov dx,mstat ; read mpu status
- mpui0: jmp short $+2
- in al,dx
- and al,mdsr ; generated by mpu?
- jz mpui1 ; yes, branch
- ; jmp mpui0
- pop dx ; no, restore cpu
- pop ax
- iret ; return from interrupt
- orgint: jmp far ptr intval ; dummy vector, filled by _initm
- dw 0
-
- mpui1:
- push bx ; save cpu state
- push cx
- push di
- push si
- push bp
- push ds
- push es
-
- mov ax,seg dgroup ; set up c seg regs
- mov ds,ax
- mov es,ax
-
- mov dx,mdata ; get mpu int data
- in al,dx
-
- call dompu ; do the mpu routine
-
- pop es ; restore seg regs
- pop ds
- pop bp ; restore cpu state
- pop si
- pop di
- pop cx
- pop bx
- pop dx
- mov al,20H ; send eoi to 8259
- out 20H,al
- pop ax
- iret ; return from interrupt
- mpuint endp
-
-
- ;--------------------------------------------------------------
- ; dompu
- ; process mpu inte
- ; local call
- ;
- dompu proc near
- mov byte ptr intval,al ; save as global variable
- mov bx,special
- or bx,bx ; special flag set?
- jz dompu1 ; no, branch
- dec bx ; yes, jump to special routine
- add bx,bx
- mov dx,sptable[bx]
- jmp dx
- dompu1: cmp al,0F0H ; < F0H
- jnb dompu2 ; no, branch
- jmp timev ; yes, do time value
- dompu2: cmp al,0F8H ; < F8H
- jnb dompu3 ; no, branch
- jmp trackd ; yes, do track data request
- dompu3: jnz dompu4 ; branch if not = F8H
- jmp timeo ; else do timing overflow
- dompu4: cmp al,0F9H ; = F9?
- jnz dompu5 ; no, branch
- jmp condr ; yes, do conductor request
- dompu5: cmp al,0FDH ; = FD?
- jnz dompu6 ; no, branch
- jmp clockh ; yes, do clock to host
- dompu6: cmp al,0FCH ; = FD?
- jnz dompu7 ; no, branch
- jmp allend ; yes, do all end
- dompu7: cmp al,0FFH ; = FF?
- jnz dompu8 ; no, branch
- jmp midism ; yes, do midi system message
- dompu8: ret
- dompu endp
-
- ;--------------------------------------------------------------
- ; mpuput(data)
- ; send data to mpu-401
- ; C call
- ;
- public _mpuput
- _mpuput proc far
- push bp
- mov bp,sp
-
- mov dx,mstat ; mpu status port
- mpup1: in al,dx ; get the status
- and al,mdrr ; test for Data Recieve Ready
- jnz mpup1 ; loop til ready
- mov dx,mdata ; mpu data port
- mov ax,[bp+p1] ; get the data
- out dx,al ; send to mpu
-
- mov sp,bp ; restore C sp
- pop bp
- ret ; exit
- _mpuput endp
-
- ;--------------------------------------------------------------
- ; mpuput
- ; send data in AL to mpu-401
- ; local call, AX is preserved
- ;
- mpuput proc near
- push ax
- mov dx,mstat ; mpu status port
- mpupa1: in al,dx ; get the status
- and al,mdrr ; test for Data Recieve Ready
- jnz mpupa1 ; loop til ready
- mov dx,mdata ; mpu data port
- pop ax ; get the data
- out dx,al ; send to mpu
- ret ; exit
- mpuput endp
-
- ;--------------------------------------------------------------
- ; data=mpuget()
- ; get data from mpu-401
- ; C call
- ;
- public _mpuget
- _mpuget proc far
-
- mov dx,mstat ; mpu status port
- mpug1: in al,dx ; get the status
- and al,mdsr ; test for Data Set Ready
- jnz mpug1 ; loop til ready
- mov dx,mdata ; mpu data port
- in al,dx ; get the data byte
- mov ah,0 ; zero out ms byte
- ret ; exit with ax = data
- _mpuget endp
-
- ;--------------------------------------------------------------
- ; mpuget
- ; get data from mpu-401 to AX
- ; local call
- ;
- mpuget proc near
- mov dx,mstat ; mpu status port
- mpuga1: in al,dx ; get the status
- and al,mdsr ; test for Data Set Ready
- jnz mpuga1 ; loop til ready
- mov dx,mdata ; mpu data port
- in al,dx ; get the data byte
- mov ah,0 ; zero out ms byte
- ret ; exit with ax = data
- mpuget endp
-
- ;--------------------------------------------------------------
- ; mpucmd(cmd)
- ; send a command to mpu-401
- ;
- public _mpucmd
- _mpucmd proc far
- push bp
- mov bp,sp
-
- mov dx,mstat ; mpu status port
- mpuc1: in al,dx ; get the status
- and al,mdrr ; test for Data Recieve Ready
- jnz mpuc1 ; loop til ready
- cli ; disable intes
- mov ax,[bp+p1] ; get the command
- out dx,al ; send to mpu
- mpuc2: in al,dx ; get the status
- and al,mdsr ; test for Data Set Ready
- jnz mpuc2 ; loop til ready
- mov dx,mdata ; mpu data port
- in al,dx ; read it
- cmp al,0FEH ; acknowledge?
- jz mpuc3 ; yes, branch
-
- push di ; save C registers
- push si
- call dompu ; do mpu routine
- pop si
- pop di
- mov dx,mstat ; mpu status port
- jmp short mpuc2 ; check again for ack
-
- mpuc3: sti ; enable ints
- mov sp,bp ; restore C sp
- pop bp
- ret ; exit
- _mpucmd endp
-
- ;--------------------------------------------------------------
- ; data = gett()
- ; get byte from track buffer
- ; C call
- ;
- public _gett
- _gett proc far
- mov bx,_indext ; get index
- mov dx,seg _tbuf
- push ds
- mov ds,dx ; fetch the data
- mov al,ds:[bx]
- xor ah,ah ; ax = data
- pop ds
- inc bx ; inc index
- cmp bx,endtrk ; reached end?
- jnz gett1 ; no, exit
- mov bx,startt ; yes, set index = start
- gett1: mov _indext,bx ; save index
- ret ; exit with ax = data
- _gett endp
-
- ;--------------------------------------------------------------
- ; gett
- ; get byte to AX from track buffer
- ; local call
- ;
- gett proc near
- mov bx,_indext ; get index
- mov dx,seg _tbuf
- push ds
- mov ds,dx ; fetch the data
- mov al,ds:[bx]
- xor ah,ah ; ax = data
- pop ds
- inc bx ; inc index
- cmp bx,endtrk ; reached end?
- jnz getta1 ; no, exit
- mov bx,startt ; yes, set index = start
- getta1: mov _indext,bx ; save index
- ret ; exit with ax = data
- gett endp
-
- ;--------------------------------------------------------------
- ; putt(track_data)
- ; put byte to track buffer
- ; C call
- ;
- public _putt
- _putt proc far
- push bp
- mov bp,sp
- mov bx,_indext ; get index
- mov dx,seg _tbuf
- mov al,[bp+p1] ; get the data
- push ds
- mov ds,dx ; store the data
- mov ds:[bx],al
- pop ds
- inc bx ; inc index
- cmp bx,limitt ; reached limit?
- mov ax,1 ; flag error
- jz putt0 ; yes, branch with err
- mov ax,0 ; no, flag no-error
- mov _indext,bx ; store index
- mov endtrk,bx ; end = index
- putt0: mov _enderr,ax ; save in _enderr
- mov sp,bp ; restore C sp
- pop bp
- ret ; exit
- _putt endp
-
- ;--------------------------------------------------------------
- ; putt
- ; put byte in AL to track buffer
- ; local call
- ;
- putt proc near
- mov bx,_indext ; get index
- mov dx,seg _tbuf
- push ds
- mov ds,dx ; store the data
- mov ds:[bx],al
- pop ds
- inc bx ; inc index
- cmp bx,limitt ; reached limit?
- mov ax,1 ; flag error
- jz putta0 ; yes, branch with err
- mov ax,0 ; no, flag no-error
- mov _indext,bx ; store index
- mov endtrk,bx ; end = index
- putta0: mov _enderr,ax ; save in _enderr
- ret ; exit
- putt endp
-
- ;--------------------------------------------------------------
- ; data = getp()
- ; get byte from parameter buffer
- ; C call
- ;
- public _getp
- _getp proc far
- mov bx,_indexp ; get index
- mov dx,seg _pbuf
- push ds
- mov ds,dx ; fetch the data
- mov al,ds:[bx]
- xor ah,ah ; ax = data
- pop ds
- inc bx ; inc index
- cmp bx,endpar ; reached end?
- jnz getp1 ; no, exit
- mov bx,startp ; yes, set index = start
- getp1: mov _indexp,bx ; save index
- ret ; exit with ax = data
- _getp endp
-
- ;--------------------------------------------------------------
- ; getp
- ; get byte to AX from param buffer
- ; local call
- ;
- getp proc near
- mov bx,_indexp ; get index
- mov dx,seg _pbuf
- push ds
- mov ds,dx ; fetch the data
- mov al,ds:[bx]
- xor ah,ah ; ax = data
- pop ds
- inc bx ; inc index
- cmp bx,endpar ; reached end?
- jnz getpa1 ; no, exit
- mov bx,startp ; yes, set index = start
- getpa1: mov _indexp,bx ; save index
- ret ; exit with ax = data
- getp endp
-
- ;--------------------------------------------------------------
- ; putp(param_data)
- ; put byte to param buffer
- ; C call
- ;
- public _putp
- _putp proc far
- push bp
- mov bp,sp
- mov bx,_indexp ; get index
- mov dx,seg _pbuf
- mov al,[bp+p1] ; get the data
- push ds
- mov ds,dx ; store the data
- mov ds:[bx],al
- pop ds
- inc bx ; inc index
- cmp bx,limitp ; reached limit?
- mov ax,1 ; flag error
- jz putp0 ; yes, branch with err
- mov ax,0 ; no, flag no-error
- mov _indexp,bx ; store index
- mov endpar,bx ; end = index
- putp0: mov _enderr,ax ; save in _enderr
- mov sp,bp ; restore C sp
- pop bp
- ret ; exit
- _putp endp
-
- ;--------------------------------------------------------------
- ; putp
- ; put byte in AL to param buffer
- ; local call
- ;
- putp proc near
- mov bx,_indexp ; get index
- mov dx,seg _pbuf
- push ds
- mov ds,dx ; store the data
- mov ds:[bx],al
- pop ds
- inc bx ; inc index
- cmp bx,limitp ; reached limit?
- mov ax,1 ; flag error
- jz putpa0 ; yes, branch with err
- mov ax,0 ; no, flag no-error
- mov _indexp,bx ; store index
- mov endpar,bx ; end = index
- putpa0: mov _enderr,ax ; save in _enderr
- ret ; exit
- putp endp
-
- ;--------------------------------------------------------------
- ; timeo
- ; process timing overflow on inte
- ; local call with intval in AL
- ;
- timeo proc near
- call putt
- ret
- timeo endp
-
- ;--------------------------------------------------------------
- ; condr
- ; process conductor request on inte
- ; local dummy routine, sends timing overflow byte
- ;
- condr proc near
- mov al,0F8H
- call putt
- ret
- condr endp
-
- ;--------------------------------------------------------------
- ; clockh
- ; process clock to host on inte
- ; local call
- ;
- clockh proc near
- mov ax,clkblp ; get blip flag
- inc ax ; count up
- and ax,1
- mov clkblp,ax ; put back
- inc ax ; 1,2 = happy face
- mov cx,ds
- mov dx,0B800H ; point to gx screen
- mov ds,dx
- mov byte ptr ds:9EH,al ; display blip
- mov ds,cx
- ret
- clockh endp
-
- ;--------------------------------------------------------------
- ; allend
- ; process all end on inte
- ; local call, clears playing flag
- ;
- allend proc near
- mov ax,0
- mov _playing,ax
- ret
- allend endp
-
- ;--------------------------------------------------------------
- ; timev
- ; process time value on inte
- ; local call with intval in AL
- ;
- timev proc near
- call putt
- mov ax,1 ; set special = 1
- mov special,ax ; dotimev on next inte
- ret
- timev endp
-
- ;--------------------------------------------------------------
- ; dotimev (special = 1 )
- ; next inte processing of time value
- ; local call with intval in AL
- ;
- dotimev proc near
- cmp al,0F8H ; mpu mark, no operation
- jz dotime1
- cmp al,0F9H ; mpu mark, measure end
- jz dotime2
- cmp al,0FCH ; mpu mark, data end
- jnz dotime3
- mov ax,0
- mov _recording,ax ; clr recording flag
- dotime2:call putt ; put in record buffer
- dotime1:mov ax,0
- mov special,ax ; done, clear special
- ret ; exit
- dotime3:mov ah,al ; get a copy
- and ah,0F0H ; zip channel data
- cmp ah,0C0H ; midi msg, program change
- jz dotime4
- cmp ah,0DH ; midi msg, channel pressure
- jnz dotime5
- dotime4:mov dx,1 ; set to recieve 1 more byte
- jmp short dotime6
- dotime5:cmp ah,80H ; midi msg, note off
- jz dotime7
- cmp ah,90H ; midi msg, note on
- jz dotime7
- cmp ah,0A0H ; midi msg, after touch
- jz dotime7
- cmp ah,0B0H ; midi msg, control change
- jz dotime7
- cmp ah,0E0H ; midi msg, pitch wheel
- jnz dotime8
- dotime7:mov dx,2 ; set to recieve 2 more bytes
- dotime6:mov rcount,dx
- mov icount,dx
- call putt ; put in record buffer
- ret ; exit
- dotime8:and ah,80H ; < 7FH ?
- jz dotime9 ; yes, branch
- mov ax,0 ; no, is error
- mov special,ax ; clear special
- call far ptr _beep ; signal error
- ret ; exit
- dotime9:mov ah,byte ptr icount ; get current count
- cmp ah,0 ; new one?
- jnz dotim10 ; no, branch
- mov ah,byte ptr rcount ; yes, icount <-- rcount
- dotim10:push ax ; save it
- call putt ; save the data byte in AL
- pop ax ; ah = icount
- dec ah ; dec icount
- mov byte ptr icount,ah ; save it
- jnz dotime11 ; branch if icount not 0
- mov ax,0 ; else clear special
- mov special,ax
- dotime11:ret ; exit
- dotimev endp
-
- ;--------------------------------------------------------------
- ; trackd
- ; process track play request on inte
- ; local call with intval in AL
- ;
- trackd proc near
- call gett ; get next track buffer byte
- nop ; fix midi channel
- call mpuput ; send it to mpu data port
- cmp al,0F8H ; midi timing overflow
- jnz trackd1
- ret ; just exit if it was timing overfow
- trackd1:call gett ; get next track buffer byte
- nop ; fix midi channel
- call mpuput ; send it to mpu data port
- and al,0F0H ; strip midi channel info
- cmp al,0F0H ; mpu mark
- jnz trackd2
- ret
- trackd2:test al,80H ; <= 7FH ?
- jnz trackd3 ; no, branch
- cmp pcount,1 ; pcount = 1 ?
- jnz trackd4 ; no, branch
- ret ; yes, exit
- trackd3:cmp al,0C0H ; one byte needed?
- jz trackd5
- cmp al,0D0H
- jnz trackd6
- trackd5:mov pcount,1 ; yes, set running pcount to 1
- jmp short trackd4 ; ... and get one more byte
- trackd6:mov pcount,2 ; else set running pcount to 2
- call gett ; get next track buffer byte
- nop ; fix midi channel
- call mpuput ; send it to mpu data port
- trackd4:call gett ; get next track buffer byte
- nop ; fix midi channel
- call mpuput ; send it to mpu data port
- ret
- trackd endp
-
- ;--------------------------------------------------------------
- ; midism
- ; process midi system message on inte
- ; local call
- ;
- midism proc near
- mov ax,2 ; flag special = 2
- mov special,ax ; procsm on next inte
- ret
- midism endp
-
- ;--------------------------------------------------------------
- ; procsm ( special = 2)
- ; continue to process midi system message in inte
- ; local call with intval in AL
- ;
- procsm proc near
- cmp al,0F0H ; midi exclusive
- jnz procsm1
- call putp ; save in para buffer
- mov ax,1 ; set loading flag
- mov _loading,ax
- mov ax,3 ; set special = 3
- mov special,ax ; continue on next inte
- ret
- procsm1:cmp al,0F3H ; song select
- jnz procsm2
- mov ax,4 ; set special = 4
- mov special,ax ; continue on next inte
- ret
- procsm2:cmp al,0F2H ; song position
- jnz procsm3
- mov ax,5 ; set special = 5
- mov special,ax ; continue on next inte
- ret
- procsm3:cmp al,0F6H ; tune request
- jnz procsm4
- nop ; insert routine here
- jmp short procsm0 ; clr special & exit
- procsm4:mov byte ptr _rtmsg,al ; flag real time message
- procsm0:mov ax,0 ; clear special
- mov special,ax
- ret ; exit
- procsm endp
-
- ;--------------------------------------------------------------
- ; sysexc (special = 3 )
- ; inte processing of system exclusive values
- ; local call with intval in AL
- ;
- sysexc proc near
- push ax ; save inte value
- call putp ; save in parameter buffer
- pop ax
- cmp al,0F7H ; was it EOX
- jnz sysexc0 ; no, just exit
- mov ax,0 ; yes,
- mov _loading,ax ; clear loading flag
- mov special,ax ; clear special
- inc word ptr _pending ; inc pending flag
- sysexc0:ret ; exit
- sysexc endp
-
- ;--------------------------------------------------------------
- ; songsel (special = 4)
- ; inte processing of song select
- ; local call with intval in AL
- ;
- songsel proc near
- nop ; dummy routine
- mov ax,0 ; clear special
- mov special,ax
- ret
- songsel endp
-
- ;--------------------------------------------------------------
- ; songp1 (special = 5)
- ; inte processing of song position 1st byte
- ; local call with intval in AL
- ;
- songp1 proc near
- nop ; dummy routine
- mov ax,6 ; special = 6
- mov special,ax ; songp2 on next int
- ret
- songp1 endp
-
- ;--------------------------------------------------------------
- ; songp2 (special = 6)
- ; inte processing of position 2nd byte
- ; local call with intval in AL
- ;
- songp2 proc near
- nop ; dummy routine
- mov ax,0 ; clear special
- mov special,ax
- ret
- songp2 endp
-
- ;--------------------------------------------------------------
- ; a little beep on the speaker
- ;
- public _beep
- _beep proc far
-
- mov al,0b6h
- out 043h,al ;write timer mode regester
- mov ax,1000 ;set divisor value to 1000
- out 042h,al ;write timer 1 count lsb
- mov al,ah
- out 042h,al ;write timer 2 count msb
- in al,061h ;get current port b setting
- mov ah,al ;save current setting.
- or al,3 ;turn speaker on
- out 061h,al
- mov cx,0a48h ;10 msec delay on ibm pc 4.7mh 8088
- delay:
- loop delay
- mov al,ah ;get old port b setting
- out 061h,al ;set it back the way you found it
- ret
-
- _beep endp
-
- ;--------------------------------------------------------------
- ; blip(char) -- sends char to upper right corner of screen
- ;
- public _blip
- _blip proc far
- push bp
- mov bp,sp
-
- mov ax,[bp+p1]
- add ax,'0'
- mov cx,ds
- mov dx,0B800H
- mov ds,dx
- mov byte ptr ds:9EH,al
- mov ds,cx
-
- mov sp,bp
- pop bp
- ret
- _blip endp
-
- ;--------------------------------------------------------------
- PRIM_TEXT ENDS
- END
-
- ###############################################################
-
- /**************************************************************
- * mpu.h
- *
- * equates for mpu & tx816
- *
- */
-
- /* mpu port addresses & flags
- */
- #define MDATA 0x330 /* mpu data port address */
- #define MSTAT 0x331 /* mpu status port address */
- #define MCMD 0x331 /* mpu command port address */
- #define MDSR 0x80 /* mpu data set ready, active low */
- #define MDRR 0x40 /* mpu data read ready, active low */
-
- /* mpu data codes
- */
- #define NULINT 0xFA /* null interrupt code */
- #define MPUACK 0xFE /* mpu acknowledge */
-
- /* mpu command codes
- */
- #define METRONOME_ON 0x83 /* metronome on with no accents */
- #define METRONOME_ACCENT 0x85 /* metronome on with accents */
- #define METRONOME_OFF 0x84 /* metronome off */
- #define RESET 0xFF /* reset mpuw */
- #define SEND_SYS 0xDF /* want to send system message */
- #define EXCL_ON 0x97 /* exclusive to host: on */
- #define EXCL_OFF 0x96 /* exclusive to host: off */
- #define CLOCK_ON 0x95 /* clock to host: on */
- #define CLOCK_OFF 0x94 /* clock to host: off */
-
- /* midi codes
- */
- #define EOX 0xF7 /* end of transmission */
-
- /* Yamaha specific codes
- */
- #define DUMP_1V 0 /* bulk dump 1 voice */
- #define DUMP_1P 1 /* bulk dump 1 performance setup */
- #define DUMP_64P 2 /* bulk dump 64 performance setups */
- #define DUMP_32V 9 /* bulk dump 32 voices */
- #define DUMP_CA 0 /* dump condition acknowledge */
-
- ###############################################################
-
- /**************************************************************
- * testmpu.c
- *
- * test program for mpu & TX816
- *
- */
-
- #include "stdio.h"
- #include "mpu.h"
-
- /**************************************************************
- * global values
- */
- extern unsigned char tbuf[]; /* track buffer */
- extern unsigned char pbuf[]; /* parameter buffer */
- extern unsigned int indext; /* track buf index */
- extern unsigned int indexp; /* para buf index */
- extern unsigned int channel; /* current midi channel */
- extern unsigned int rtmsg; /* real time message flag */
- extern unsigned int pending; /* number of sys excl pending */
- extern unsigned int recording; /* nz when recording track data */
- extern unsigned int playing; /* nz when playing track data */
- extern unsigned int loading; /* nz when loading para data */
- extern unsigned int enderr; /* nz if put index at limit */
-
- main(argc, argv)
- int argc;
- char *argv[];
- {
- int i;
-
- initm();
- mpucmd(RESET);
- mpucmd(EXCL_ON);
- mpucmd(CLOCK_ON);
-
- getchar();
- printf("dump in progress\n");
- dump_request(DUMP_1V);
- for(i = 0; i < 256; ++i)
- printf("%x ",pbuf[i]);
- printf("\n\n");
- mpucmd(RESET);
- printf("reset\n");
- getchar();
- mpucmd(CLOCK_OFF);
- exitm();
- exit(0);
- }
-
- /**************************************************************
- * issue a request to dump data
- * specific to Yamaha
- */
- dump_request(fmt)
- int fmt;
- {
- indexp = 0;
- mpucmd(SEND_SYS);
- mpuput(0xF0);
- mpuput(0x43);
- mpuput(0x20 | channel);
- mpuput(fmt);
- mpuput(EOX);
- while(!loading);
- beep();
- }
-
- ###############################################################
-
- PAGE 60,127
- TITLE MIDI primitives for dumb-MPU
- NAME MIDI
- .SALL
- ;==============================================================
- ; COPYRIGHT (C) 1986 John Dunn
- ;--------------------------------------------------------------
- ; date: 01/02/86
- ; update: 01/02/86
- ; last hacker: John Dunn
- ;==============================================================
- PRIM_TEXT SEGMENT BYTE PUBLIC 'CODE'
- PRIM_TEXT ENDS
- CONST SEGMENT WORD PUBLIC 'CONST'
- CONST ENDS
- _BSS SEGMENT WORD PUBLIC 'BSS'
- _BSS ENDS
- _DATA SEGMENT WORD PUBLIC 'DATA'
- _DATA ENDS
- DGROUP GROUP CONST, _BSS, _DATA
- ;==============================================================
- _DATA SEGMENT WORD PUBLIC 'DATA'
- ;--------------------------------------------------------------
- PUBLIC _indexp,_indext,_channel,_rtmsg,_pending
- PUBLIC _recording,_playing,_loading,_enderr
- ;--------------------------------------------------------------
- _channel dw 0 ; current midi channel
- _rtmsg dw 0 ; real time message flag
- _pending dw 0 ; number of sys excl pending
- _recording dw 0 ; nz when recording track data
- _playing dw 0 ; nz when playing track data
- _loading dw 0 ; nz when loading para data
- _enderr dw 0 ; nz if put index at limit
- _indext dw 0 ; index track buffer
- _indexp dw 0 ; index param buffer
- startt dw 0 ; start track buffer
- startp dw 0 ; start param buffer
- endtrk dw 0 ; end track buffer
- endpar dw 0 ; end param buffer
- limitt dw tbufx-_tbuf ; track buffer limit
- limitp dw pbufx-_pbuf ; param buffer limit
-
- icount dw 0 ; midi msg count index
- rcount dw 0 ; midi msg run count
- pcount dw 0 ; play track count
-
- clkblp dw 0 ; clock blip count
-
- intval dw 0 ; inte data value
- special dw 0 ; nz = special routine
- sptable dw dotimev,procsm,sysexc,songsel,songp1,songp2
-
- ;--------------------------------------------------------------
- _DATA ENDS
- ;==============================================================
- PBUF_DATA SEGMENT PARA MEMORY 'BUFFER'
- ;--------------------------------------------------------------
- PUBLIC _pbuf
- ;--------------------------------------------------------------
- _pbuf db 17000 dup(?) ; parameter buffer
- pbufx db 0
- ;--------------------------------------------------------------
- PBUF_DATA ENDS
- ;==============================================================
- TBUF_DATA SEGMENT PARA MEMORY 'BUFFER'
- ;--------------------------------------------------------------
- PUBLIC _tbuf
- ;--------------------------------------------------------------
- _tbuf db 16384 dup(?) ; parameter buffer
- tbufx db 0
- ;--------------------------------------------------------------
- TBUF_DATA ENDS
- ;==============================================================
- PRIM_TEXT SEGMENT
- ASSUME CS: PRIM_TEXT, DS: DGROUP, SS: DGROUP, ES: DGROUP
- ;==============================================================
- bpo equ 6 ; base pointer offset
- ; 6 = large model; 4 = small
- p1 equ bpo ; single word arg 1, use [bp+@1]
- p2 equ bpo+2 ; single word arg 2, use [bp+@2]
- ;--------------------------------------------------------------
- mdata equ 0330H ; mpu data port address
- mstat equ 0331H ; mpu status port address
- mcmd equ 0331H ; mpu command port address
- mdsr equ 80H ; mpu data set ready, active low
- mdrr equ 40H ; mpu data read ready, active low
- ;--------------------------------------------------------------
- ; initialize mpu, int vectors, etc.
- ; must be called once only on startup
- ;
- public _initm
- _initm proc far
- push es ; save current es
- mov ah,35h ; get current int 2
- mov al,0AH
- int 21H
- mov word ptr cs:orgint+3,es ; save it
- mov word ptr cs:orgint+1,bx
- pop es ; restore es
-
- push ds ; save current ds
- mov ah,25H ; set int vect
- mov al,0AH ; int 2 for MPU
- mov dx,seg mpuint
- mov ds,dx
- mov dx,offset mpuint
- int 21H ; set new int vect
- pop ds ; restore ds
-
- call mpurst ; reset mpu
- in al,21H ; enable irq2
- jmp short $+2 ; delay for AT
- and al,0FBH
- out 21H,al
- ret
- _initm endp ; end of init mpu
-
- ;--------------------------------------------------------------
- ; shutdown mpu, restore int vectors, etc.
- ; must be called once only on exit
- ;
- public _exitm
- _exitm proc far
- in al,21H ; disable irq2
- jmp short $+2 ; delay for AT
- or al,4
- out 21H,al
-
- push ds
- mov ah,25h ; restore previous irq2
- mov al,0AH
- mov dx,word ptr cs:orgint+3
- mov ds,dx
- mov dx,word ptr cs:orgint+1
- int 21h
- pop ds
- ret
- _exitm endp
-
- ;--------------------------------------------------------------
- ; mpurst
- ; reset the mpu
- ; local call
- ;
- mpurst proc near
- cli ; disable intes
- mov dx,mstat ; mpu status port
- mpurs1: in al,dx ; get the status
- and al,mdrr ; test for Data Recieve Ready
- jnz mpurs1 ; loop til ready
- mov ax,0FFH ; get the command
- out dx,al ; send to mpu
- mpurs2: in al,dx ; get the status
- and al,mdsr ; test for Data Set Ready
- jnz mpurs2 ; loop til ready
- mov dx,mdata ; read mpu data port
- mov dx,mdata ; read mpu data port
- mov dx,mdata ; read mpu data port
- sti ; enable intes
- ret ; exit
- mpurst endp
-
- ;--------------------------------------------------------------
- ; this routine is only called by int 2
- ; if it was not generated by the mpu, it vectors
- ; to the original int address, otherwise it saves
- ; registers, then calls the c routine _mpuint,
- ; after which it restores registers, clears nmi
- ; and returns from int.
- ;
- mpuint proc far
- push ax ; save ax
- push dx
- mov dx,mstat ; read mpu status
- mpui0: jmp short $+2
- in al,dx
- and al,mdsr ; generated by mpu?
- jz mpui1 ; yes, branch
- pop dx ; no, restore cpu
- pop ax
- iret ; return from interrupt
- orgint: jmp far ptr intval ; dummy vector, filled by _initm
- dw 0
-
- mpui1:
- push bx ; save cpu state
- push cx
- push di
- push si
- push bp
- push ds
- push es
-
- mov ax,seg dgroup ; set up c seg regs
- mov ds,ax
- mov es,ax
-
- mov dx,mdata ; get mpu int data
- in al,dx
-
- call dompu ; do the mpu routine
-
- pop es ; restore seg regs
- pop ds
- pop bp ; restore cpu state
- pop si
- pop di
- pop cx
- pop bx
- pop dx
- mov al,20H ; send eoi to 8259
- out 20H,al
- pop ax
- iret ; return from interrupt
- mpuint endp
-
-
- ;--------------------------------------------------------------
- ; dompu
- ; process mpu inte
- ; local call
- ;
- dompu proc near
- mov byte ptr intval,al ; save as global variable
- mov bx,special
- or bx,bx ; special flag set?
- jz dompu1 ; no, branch
- dec bx ; yes, jump to special routine
- add bx,bx
- mov dx,sptable[bx]
- jmp dx
- dompu1: cmp al,0F0H ; < F0H
- jnb dompu2 ; no, branch
- jmp timev ; yes, do time value
- dompu2: cmp al,0F8H ; < F8H
- jnb dompu3 ; no, branch
- jmp trackd ; yes, do track data request
- dompu3: jnz dompu4 ; branch if not = F8H
- jmp timeo ; else do timing overflow
- dompu4: cmp al,0F9H ; = F9?
- jnz dompu5 ; no, branch
- jmp condr ; yes, do conductor request
- dompu5: cmp al,0FDH ; = FD?
- jnz dompu6 ; no, branch
- jmp clockh ; yes, do clock to host
- dompu6: cmp al,0FCH ; = FD?
- jnz dompu7 ; no, branch
- jmp allend ; yes, do all end
- dompu7: cmp al,0FFH ; = FF?
- jnz dompu8 ; no, branch
- jmp midism ; yes, do midi system message
- dompu8: ret
- dompu endp
-
- ;--------------------------------------------------------------
- ; mpuput(data)
- ; send data to mpu-401
- ; C call
- ;
- public _mpuput
- _mpuput proc far
- push bp
- mov bp,sp
-
- mov dx,mstat ; mpu status port
- mpup1: in al,dx ; get the status
- and al,mdrr ; test for Data Recieve Ready
- jnz mpup1 ; loop til ready
- mov dx,mdata ; mpu data port
- mov ax,[bp+p1] ; get the data
- out dx,al ; send to mpu
-
- mov sp,bp ; restore C sp
- pop bp
- ret ; exit
- _mpuput endp
-
- ;--------------------------------------------------------------
- ; mpuput
- ; send data in AL to mpu-401
- ; local call, AX is preserved
- ;
- mpuput proc near
- push ax
- mov dx,mstat ; mpu status port
- mpupa1: in al,dx ; get the status
- and al,mdrr ; test for Data Recieve Ready
- jnz mpupa1 ; loop til ready
- mov dx,mdata ; mpu data port
- pop ax ; get the data
- out dx,al ; send to mpu
- ret ; exit
- mpuput endp
-
- ;--------------------------------------------------------------
- ; data=mpuget()
- ; get data from mpu-401
- ; C call
- ;
- public _mpuget
- _mpuget proc far
-
- mov dx,mstat ; mpu status port
- mpug1: in al,dx ; get the status
- and al,mdsr ; test for Data Set Ready
- jnz mpug1 ; loop til ready
- mov dx,mdata ; mpu data port
- in al,dx ; get the data byte
- mov ah,0 ; zero out ms byte
- ret ; exit with ax = data
- _mpuget endp
-
- ;--------------------------------------------------------------
- ; mpuget
- ; get data from mpu-401 to AX
- ; local call
- ;
- mpuget proc near
- mov dx,mstat ; mpu status port
- mpuga1: in al,dx ; get the status
- and al,mdsr ; test for Data Set Ready
- jnz mpuga1 ; loop til ready
- mov dx,mdata ; mpu data port
- in al,dx ; get the data byte
- mov ah,0 ; zero out ms byte
- ret ; exit with ax = data
- mpuget endp
-
- ;--------------------------------------------------------------
- ; mpucmd(cmd)
- ; send a command to mpu-401
- ;
- public _mpucmd
- _mpucmd proc far
- push bp
- mov bp,sp
-
- mov dx,mstat ; mpu status port
- mpuc1: in al,dx ; get the status
- and al,mdrr ; test for Data Recieve Ready
- jnz mpuc1 ; loop til ready
- cli ; disable intes
- mov ax,[bp+p1] ; get the command
- out dx,al ; send to mpu
- mpuc2: in al,dx ; get the status
- and al,mdsr ; test for Data Set Ready
- jnz mpuc2 ; loop til ready
- mov dx,mdata ; mpu data port
- in al,dx ; read it
- cmp al,0FEH ; acknowledge?
- jz mpuc3 ; yes, branch
-
- push di ; save C registers
- push si
- call dompu ; do mpu routine
- pop si
- pop di
- mov dx,mstat ; mpu status port
- jmp short mpuc2 ; check again for ack
-
- mpuc3: sti ; enable ints
- mov sp,bp ; restore C sp
- pop bp
- ret ; exit
- _mpucmd endp
-
- ;--------------------------------------------------------------
- ; data = gett()
- ; get byte from track buffer
- ; C call
- ;
- public _gett
- _gett proc far
- mov bx,_indext ; get index
- mov dx,seg _tbuf
- push ds
- mov ds,dx ; fetch the data
- mov al,ds:[bx]
- xor ah,ah ; ax = data
- pop ds
- inc bx ; inc index
- cmp bx,endtrk ; reached end?
- jnz gett1 ; no, exit
- mov bx,startt ; yes, set index = start
- gett1: mov _indext,bx ; save index
- ret ; exit with ax = data
- _gett endp
-
- ;--------------------------------------------------------------
- ; gett
- ; get byte to AX from track buffer
- ; local call
- ;
- gett proc near
- mov bx,_indext ; get index
- mov dx,seg _tbuf
- push ds
- mov ds,dx ; fetch the data
- mov al,ds:[bx]
- xor ah,ah ; ax = data
- pop ds
- inc bx ; inc index
- cmp bx,endtrk ; reached end?
- jnz getta1 ; no, exit
- mov bx,startt ; yes, set index = start
- getta1: mov _indext,bx ; save index
- ret ; exit with ax = data
- gett endp
-
- ;--------------------------------------------------------------
- ; putt(track_data)
- ; put byte to track buffer
- ; C call
- ;
- public _putt
- _putt proc far
- push bp
- mov bp,sp
- mov bx,_indext ; get index
- mov dx,seg _tbuf
- mov al,[bp+p1] ; get the data
- push ds
- mov ds,dx ; store the data
- mov ds:[bx],al
- pop ds
- inc bx ; inc index
- cmp bx,limitt ; reached limit?
- mov ax,1 ; flag error
- jz putt0 ; yes, branch with err
- mov ax,0 ; no, flag no-error
- mov _indext,bx ; store index
- mov endtrk,bx ; end = index
- putt0: mov _enderr,ax ; save in _enderr
- mov sp,bp ; restore C sp
- pop bp
- ret ; exit
- _putt endp
-
- ;--------------------------------------------------------------
- ; putt
- ; put byte in AL to track buffer
- ; local call
- ;
- putt proc near
- mov bx,_indext ; get index
- mov dx,seg _tbuf
- push ds
- mov ds,dx ; store the data
- mov ds:[bx],al
- pop ds
- inc bx ; inc index
- cmp bx,limitt ; reached limit?
- mov ax,1 ; flag error
- jz putta0 ; yes, branch with err
- mov ax,0 ; no, flag no-error
- mov _indext,bx ; store index
- mov endtrk,bx ; end = index
- putta0: mov _enderr,ax ; save in _enderr
- ret ; exit
- putt endp
-
- ;--------------------------------------------------------------
- ; data = getp()
- ; get byte from parameter buffer
- ; C call
- ;
- public _getp
- _getp proc far
- mov bx,_indexp ; get index
- mov dx,seg _pbuf
- push ds
- mov ds,dx ; fetch the data
- mov al,ds:[bx]
- xor ah,ah ; ax = data
- pop ds
- inc bx ; inc index
- cmp bx,endpar ; reached end?
- jnz getp1 ; no, exit
- mov bx,startp ; yes, set index = start
- getp1: mov _indexp,bx ; save index
- ret ; exit with ax = data
- _getp endp
-
- ;--------------------------------------------------------------
- ; getp
- ; get byte to AX from param buffer
- ; local call
- ;
- getp proc near
- mov bx,_indexp ; get index
- mov dx,seg _pbuf
- push ds
- mov ds,dx ; fetch the data
- mov al,ds:[bx]
- xor ah,ah ; ax = data
- pop ds
- inc bx ; inc index
- cmp bx,endpar ; reached end?
- jnz getpa1 ; no, exit
- mov bx,startp ; yes, set index = start
- getpa1: mov _indexp,bx ; save index
- ret ; exit with ax = data
- getp endp
-
- ;--------------------------------------------------------------
- ; putp(param_data)
- ; put byte to param buffer
- ; C call
- ;
- public _putp
- _putp proc far
- push bp
- mov bp,sp
- mov bx,_indexp ; get index
- mov dx,seg _pbuf
- mov al,[bp+p1] ; get the data
- push ds
- mov ds,dx ; store the data
- mov ds:[bx],al
- pop ds
- inc bx ; inc index
- cmp bx,limitp ; reached limit?
- mov ax,1 ; flag error
- jz putp0 ; yes, branch with err
- mov ax,0 ; no, flag no-error
- mov _indexp,bx ; store index
- mov endpar,bx ; end = index
- putp0: mov _enderr,ax ; save in _enderr
- mov sp,bp ; restore C sp
- pop bp
- ret ; exit
- _putp endp
-
- ;--------------------------------------------------------------
- ; putp
- ; put byte in AL to param buffer
- ; local call
- ;
- putp proc near
- mov bx,_indexp ; get index
- mov dx,seg _pbuf
- push ds
- mov ds,dx ; store the data
- mov ds:[bx],al
- pop ds
- inc bx ; inc index
- cmp bx,limitp ; reached limit?
- mov ax,1 ; flag error
- jz putpa0 ; yes, branch with err
- mov ax,0 ; no, flag no-error
- mov _indexp,bx ; store index
- mov endpar,bx ; end = index
- putpa0: mov _enderr,ax ; save in _enderr
- ret ; exit
- putp endp
-
- ;--------------------------------------------------------------
- ; timeo
- ; process timing overflow on inte
- ; local call with intval in AL
- ;
- timeo proc near
- call putt
- ret
- timeo endp
-
- ;--------------------------------------------------------------
- ; condr
- ; process conductor request on inte
- ; local dummy routine, sends timing overflow byte
- ;
- condr proc near
- mov al,0F8H
- call putt
- ret
- condr endp
-
- ;--------------------------------------------------------------
- ; clockh
- ; process clock to host on inte
- ; local call
- ;
- clockh proc near
- mov ax,clkblp ; get blip flag
- inc ax ; count up
- and ax,1
- mov clkblp,ax ; put back
- inc ax ; 1,2 = happy face
- mov cx,ds
- mov dx,0B800H ; point to gx screen
- mov ds,dx
- mov byte ptr ds:9EH,al ; display blip
- mov ds,cx
- ret
- clockh endp
-
- ;--------------------------------------------------------------
- ; allend
- ; process all end on inte
- ; local call, clears playing flag
- ;
- allend proc near
- mov ax,0
- mov _playing,ax
- ret
- allend endp
-
- ;--------------------------------------------------------------
- ; timev
- ; process time value on inte
- ; local call with intval in AL
- ;
- timev proc near
- call putt
- mov ax,1 ; set special = 1
- mov special,ax ; dotimev on next inte
- ret
- timev endp
-
- ;--------------------------------------------------------------
- ; dotimev (special = 1 )
- ; next inte processing of time value
- ; local call with intval in AL
- ;
- dotimev proc near
- cmp al,0F8H ; mpu mark, no operation
- jz dotime1
- cmp al,0F9H ; mpu mark, measure end
- jz dotime2
- cmp al,0FCH ; mpu mark, data end
- jnz dotime3
- mov ax,0
- mov _recording,ax ; clr recording flag
- dotime2:call putt ; put in record buffer
- dotime1:mov ax,0
- mov special,ax ; done, clear special
- ret ; exit
- dotime3:mov ah,al ; get a copy
- and ah,0F0H ; zip channel data
- cmp ah,0C0H ; midi msg, program change
- jz dotime4
- cmp ah,0DH ; midi msg, channel pressure
- jnz dotime5
- dotime4:mov dx,1 ; set to recieve 1 more byte
- jmp short dotime6
- dotime5:cmp ah,80H ; midi msg, note off
- jz dotime7
- cmp ah,90H ; midi msg, note on
- jz dotime7
- cmp ah,0A0H ; midi msg, after touch
- jz dotime7
- cmp ah,0B0H ; midi msg, control change
- jz dotime7
- cmp ah,0E0H ; midi msg, pitch wheel
- jnz dotime8
- dotime7:mov dx,2 ; set to recieve 2 more bytes
- dotime6:mov rcount,dx
- mov icount,dx
- call putt ; put in record buffer
- ret ; exit
- dotime8:and ah,80H ; < 7FH ?
- jz dotime9 ; yes, branch
- mov ax,0 ; no, is error
- mov special,ax ; clear special
- call far ptr _beep ; signal error
- ret ; exit
- dotime9:mov ah,byte ptr icount ; get current count
- cmp ah,0 ; new one?
- jnz dotim10 ; no, branch
- mov ah,byte ptr rcount ; yes, icount <-- rcount
- dotim10:push ax ; save it
- call putt ; save the data byte in AL
- pop ax ; ah = icount
- dec ah ; dec icount
- mov byte ptr icount,ah ; save it
- jnz dotime11 ; branch if icount not 0
- mov ax,0 ; else clear special
- mov special,ax
- dotime11:ret ; exit
- dotimev endp
-
- ;--------------------------------------------------------------
- ; trackd
- ; process track play request on inte
- ; local call with intval in AL
- ;
- trackd proc near
- call gett ; get next track buffer byte
- nop ; fix midi channel
- call mpuput ; send it to mpu data port
- cmp al,0F8H ; midi timing overflow
- jnz trackd1
- ret ; just exit if it was timing overfow
- trackd1:call gett ; get next track buffer byte
- nop ; fix midi channel
- call mpuput ; send it to mpu data port
- and al,0F0H ; strip midi channel info
- cmp al,0F0H ; mpu mark
- jnz trackd2
- ret
- trackd2:test al,80H ; <= 7FH ?
- jnz trackd3 ; no, branch
- cmp pcount,1 ; pcount = 1 ?
- jnz trackd4 ; no, branch
- ret ; yes, exit
- trackd3:cmp al,0C0H ; one byte needed?
- jz trackd5
- cmp al,0D0H
- jnz trackd6
- trackd5:mov pcount,1 ; yes, set running pcount to 1
- jmp short trackd4 ; ... and get one more byte
- trackd6:mov pcount,2 ; else set running pcount to 2
- call gett ; get next track buffer byte
- nop ; fix midi channel
- call mpuput ; send it to mpu data port
- trackd4:call gett ; get next track buffer byte
- nop ; fix midi channel
- call mpuput ; send it to mpu data port
- ret
- trackd endp
-
- ;--------------------------------------------------------------
- ; midism
- ; process midi system message on inte
- ; local call
- ;
- midism proc near
- mov ax,2 ; flag special = 2
- mov special,ax ; procsm on next inte
- ret
- midism endp
-
- ;--------------------------------------------------------------
- ; procsm ( special = 2)
- ; continue to process midi system message in inte
- ; local call with intval in AL
- ;
- procsm proc near
- cmp al,0F0H ; midi exclusive
- jnz procsm1
- call putp ; save in para buffer
- mov ax,1 ; set loading flag
- mov _loading,ax
- mov ax,3 ; set special = 3
- mov special,ax ; continue on next inte
- ret
- procsm1:cmp al,0F3H ; song select
- jnz procsm2
- mov ax,4 ; set special = 4
- mov special,ax ; continue on next inte
- ret
- procsm2:cmp al,0F2H ; song position
- jnz procsm3
- mov ax,5 ; set special = 5
- mov special,ax ; continue on next inte
- ret
- procsm3:cmp al,0F6H ; tune request
- jnz procsm4
- nop ; insert routine here
- jmp short procsm0 ; clr special & exit
- procsm4:mov byte ptr _rtmsg,al ; flag real time message
- procsm0:mov ax,0 ; clear special
- mov special,ax
- ret ; exit
- procsm endp
-
- ;--------------------------------------------------------------
- ; sysexc (special = 3 )
- ; inte processing of system exclusive values
- ; local call with intval in AL
- ;
- sysexc proc near
- push ax ; save inte value
- call putp ; save in parameter buffer
- pop ax
- cmp al,0F7H ; was it EOX
- jnz sysexc0 ; no, just exit
- mov ax,0 ; yes,
- mov _loading,ax ; clear loading flag
- mov special,ax ; clear special
- inc word ptr _pending ; inc pending flag
- sysexc0:ret ; exit
- sysexc endp
-
- ;--------------------------------------------------------------
- ; songsel (special = 4)
- ; inte processing of song select
- ; local call with intval in AL
- ;
- songsel proc near
- nop ; dummy routine
- mov ax,0 ; clear special
- mov special,ax
- ret
- songsel endp
-
- ;--------------------------------------------------------------
- ; songp1 (special = 5)
- ; inte processing of song position 1st byte
- ; local call with intval in AL
- ;
- songp1 proc near
- nop ; dummy routine
- mov ax,6 ; special = 6
- mov special,ax ; songp2 on next int
- ret
- songp1 endp
-
- ;--------------------------------------------------------------
- ; songp2 (special = 6)
- ; inte processing of position 2nd byte
- ; local call with intval in AL
- ;
- songp2 proc near
- nop ; dummy routine
- mov ax,0 ; clear special
- mov special,ax
- ret
- songp2 endp
-
- ;--------------------------------------------------------------
- ; a little beep on the speaker
- ;
- public _beep
- _beep proc far
-
- mov al,0b6h
- out 043h,al ;write timer mode regester
- mov ax,1000 ;set divisor value to 1000
- out 042h,al ;write timer 1 count lsb
- mov al,ah
- out 042h,al ;write timer 2 count msb
- in al,061h ;get current port b setting
- mov ah,al ;save current setting.
- or al,3 ;turn speaker on
- out 061h,al
- mov cx,0a48h ;10 msec delay on ibm pc 4.7mh 8088
- delay:
- loop delay
- mov al,ah ;get old port b setting
- out 061h,al ;set it back the way you found it
- ret
-
- _beep endp
-
- ;--------------------------------------------------------------
- ; blip(char) -- sends char to upper right corner of screen
- ;
- public _blip
- _blip proc far
- push bp
- mov bp,sp
-
- mov ax,[bp+p1]
- add ax,'0'
- mov cx,ds
- mov dx,0B800H
- mov ds,dx
- mov byte ptr ds:9EH,al
- mov ds,cx
-
- mov sp,bp
- pop bp
- ret
- _blip endp
-
- ;--------------------------------------------------------------
- PRIM_TEXT ENDS
- END
-
- ###############################################################
-
- /**************************************************************
- * midi.h
- *
- * equates for MPU-401 & MIDI
- *
- */
-
- /* mpu port addresses & flags
- */
- #define MDATA 0x330 /* mpu data port address */
- #define MSTAT 0x331 /* mpu status port address */
- #define MCMD 0x331 /* mpu command port address */
- #define MDSR 0x80 /* mpu data set ready, active low */
- #define MDRR 0x40 /* mpu data read ready, active low */
-
- /* general equates
- */
- #define TRUE 1
- #define FALSE 0
-
- /* midi codes
- */
- #define KEY_ON 0x90 /* +2, turn note on/off */
- #define KEY_OFF 0x80 /* +2, turn note off */
- #define EOX 0xF7 /* +0, end of transmission */
-
- /* Yamaha specific codes
- */
- #define DUMP_1V 0 /* bulk dump 1 voice */
- #define DUMP_1P 1 /* bulk dump 1 performance setup */
- #define DUMP_64P 2 /* bulk dump 64 performance setups */
- #define DUMP_32V 9 /* bulk dump 32 voices */
- #define DUMP_CA 125 /* dump condition acknowledge */
-
- ###############################################################
-
- /**************************************************************
- * testmidi.c 1/4/86 Copyright (c) 1986, John Dunn
- *
- * test program for MPU/MIDI and TX816
- *
- */
-
- #include "stdio.h"
- #include "midi.h"
-
- /**************************************************************
- * global values
- */
- extern unsigned char pbuf[]; /* play buffer */
- extern unsigned char rbuf[]; /* recording buffer */
- extern unsigned char sbuf[]; /* sysexc dump buffer */
- extern unsigned int indexp; /* play buf index */
- extern unsigned int indexr; /* recording buf index */
- extern unsigned int indexs; /* sysexc dump buf index */
- extern unsigned int channel; /* current midi channel */
- extern unsigned int pending; /* number of sys excl pending */
- extern unsigned int recording; /* nz when recording track data */
- extern unsigned int playing; /* nz when playing track data */
- extern unsigned int looping; /* nz when playing a loop */
- extern unsigned int loading; /* nz when loading sysexc dump data */
- extern unsigned int enderr; /* nz if put index at limit */
- extern unsigned long ticks; /* clock tick count */
- extern unsigned long nextt; /* timer tick count */
- extern unsigned char tocks[]; /* midi string tick representation */
- extern unsigned char packet[]; /* midi output packet */
-
- unsigned int gv = 64; /* global note velocity */
-
- main(argc, argv)
- int argc;
- char *argv[];
- {
- int i;
- initm();
- printf("starting\n");
- getchar();
- channel = 0;
- startt();
- dump_request(DUMP_1V);
- for(i = 0; i < 166; ++i)
- printf("%x ",sbuf[i]);
- printf("\n\n");
- for(i = 145+6; i < 155+6; ++i)
- printf("%c",sbuf[i]);
- printf("\n\n");
- dump_request(DUMP_1P);
- for(i = 0; i < 110; ++i)
- printf("%x ",sbuf[i]);
- printf("\n\n");
- for(i = 64+6; i < 94+6; ++i)
- printf("%c",sbuf[i]);
- printf("\n");
- foo();
- nextt = 0;
- ticks = 0;
- indexp = 0;
- playing = TRUE;
- getchar();
- looping = TRUE;
- playing = TRUE;
- getchar();
- while(!packet[2]);
- printf("ready to record\n");
- indexr = 0;
- recording = 1;
- getchar();
- indexr = 0;
- for(i = 0; i < 256; ++i)
- printf("%x ",rbuf[i]);
- printf("\n\n");
- stopt();
- exitm();
- getchar();
- exit(0);
- }
-
- /**************************************************************
- * issue a request to dump data
- * specific to Yamaha
- */
- dump_request(fmt)
- int fmt;
- {
- indexs = 0;
- midio(0xF0);
- midio(0x43);
- midio(0x20 | channel);
- midio(fmt);
- midio(EOX);
- while(!loading);
- }
-
- /**************************************************************
- * xlates(notes)
- * translate a character string to midi data in the play buffer
- * valid characters:
- * T,S,I,Q,H,W = notes
- * 0,1,2,3,4,5,6,7,8,9 = octaves
- * A,B,C,D,E,F,G = pitch
- * +,- = sharp, flat
- */
- xlate(notes)
- char *notes;
- {
- int time,oct,val;
- char c;
- playing = 0; /* disable playing */
- indexp = 0; /* reset play index */
- ticks = 0; /* reset clock */
- while (c = toupper(*notes++))
- {
- if(c > 'G')
- { switch(c)
- { case 'T': time = 1; break; /* 32nd note */
- case 'S': time = 2; break; /* 16th note */
- case 'I': time = 4; break; /* Eighth note */
- case 'Q': time = 8; break; /* quarter note */
- case 'H': time = 16; break; /* half note */
- case 'W': time = 32; break; /* whole note */
- }
- putp(KEY_ON); /* send MIDI note on */
- putptok(); /* send current time */
- ticks = ticks+time; /* add note time/2 */
- putp(oct+val); /* send note value */
- putp(gv); /* send global velocity */
- putp(KEY_ON); /* send MIDI note off */
- putptok();
- ticks = ticks+time; /* add note time/2 */
- putp(oct+val); /* send note value */
- putp(0); /* send velocity = 0 */
- }
- else
- if(c >= 'A')
- { switch(c)
- { case 'C': val = 0; break; /* key of C */
- case 'D': val = 2; break;
- case 'E': val = 4; break;
- case 'F': val = 5; break;
- case 'G': val = 7; break;
- case 'A': val = 9; break;
- case 'B': val = 11; break;
- }
- }
- else
- if(c >= '0')
- oct = 12*(c-'0');
- else
- switch(c)
- { case '+': val++; break; /* sharp */
- case '-': val--; break; /* flat */
- }
- }
- indexp = 0; /* reset play index */
- ticks = 0; /* reset clock */
- }
-
- /* translate ticks to tocks, then put tocks into the play buffer
- */
- putptok()
- {
- tictoc(); /* ticks --> tocks */
- putp(tocks[0]);
- putp(tocks[1]);
- putp(tocks[2]);
- putp(tocks[3]);
- }
-
- foo()
- {
- static char *this =
- "3CIESGS4CIESGS5CIESGS6CIESGS7CH";
- xlate(this);
- }
-
-
-
-