MIDIコントローラ

;;MIDI シリアルドライバ
;;MIDIのnoteONコマンドを送る
;;タイマー割込みを利用する
;;MIDI出力端子 RB1
LIST P=16F648A, ST=OFF, R=DEC, F=INHX8M
INCLUDE P16F648A.INC
;
__CONFIG _INTRC_OSC_NOCLKOUT & _MCLRE_OFF & _WDT_OFF & _PWRTE_ON
;;; 定数
;WAIT_CNT equ 0x20 ; 100usのwaitカウント
bitDelay equ 0x20 ; 31.25Kbit/s タイマーWait値(bit間隔 32us)
;FileRegi
msg_len equ 0x22
bit_cnt equ 0x23 ;割込み処理するビット数
wsave equ 0x24
stsave equ 0x25
CNT1 equ 0x26
CNT2 equ 0x27
CNT3 equ 0x28
sendByte equ 0x29
midi_cmd equ 0x30 ; MIDIコマンド
midi_note equ 0x31
midi_vel equ 0x32
org 0
goto main
org 4
goto intproc
main
movlw 0x6 ;初期設定
movwf PORTB
bsf STATUS,RP0 ;bank1
movlw 0xF0
movwf TRISB
bcf OPTION_REG,T0CS ;内部クロックを利用
bsf OPTION_REG,T0SE ;タイマオーバーフロー割込み設定
bsf OPTION_REG,PSA ;プリスケーラを利用しない
movlw 0x80
movf bit_cnt,F
bcf STATUS,RP0 ;bank0
bsf INTCON,T0IE ;タイマ0割り込み許可、
;bsf PORTB,1 ;MIDI出力H
;bsf PORTB,2
;BSF INTCON,GIE
loop call note_on
bcf PORTB,2 ;Check LED
call TIM100
bsf PORTB,2
call T1SEC
goto loop
;;;;;;;;;;; note_on ;;;;;;;;;;;;;
note_on
movlw 0x91
movwf midi_cmd
movlw 0x3c ;note 3c
movwf midi_note
movlw 0x64 ;velocity
movwf midi_vel
movlw 0x3 ;message長
movwf msg_len
call send_midi_msg ;midiメッセージ送信
return
;;;;;;;;;;; send_midi_msg ;;;;;;;;;;;;;
;; midi_msgをMIDI OUTに送信する
send_midi_msg
movlw midi_cmd
movwf FSR
movlw 0xff - bitDelay
movwf TMR0
bsf INTCON,GIE ;割込み可
send_loop
movf INDF,W
movwf sendByte
incf FSR,F
movlw 0x9
movwf bit_cnt
send_wait
btfss bit_cnt,7 ;送信完了を待つ
goto send_wait
decfsz msg_len,f ;メッセージ長繰り返す
goto send_loop
bcf INTCON,GIE ;割込み停止
return
;;;;;;;;;;;; 割り込み処理 intproc ;;;;;;;;;;;;
intproc ; 割り込み処理(MIDIバイトの送信処理)
;movwf wsave ; Wレジスタ退避
;swapf STATUS,W
;movwf stsave ; STATUS退避
bcf INTCON,T0IF ;割込み要求クリア
movlw 0x9 ;スタートビット
subwf bit_cnt,w
btfsc STATUS,Z
goto send_start
movlw 0x0 ;ストップビット
subwf bit_cnt,w
btfsc STATUS,Z
goto send_stop
movlw 0x80 ;ストップビット
subwf bit_cnt,w
btfsc STATUS,Z
goto send_stop
;cje bit_cnt,#9,send_strt
;cje bit_cnt,#0,send_stop
;cje bit_cnt,#0ffh,int_end
rrf sendByte,f ; データ部(8bit)送信
btfss STATUS,C
bcf PORTB,1
btfsc STATUS,C
bsf PORTB,1
decf bit_cnt,F
goto int_end
send_start
bcf PORTB,1 ; Start bit
decf bit_cnt,F ; bit_cnt = 8
goto int_end
send_stop
bsf PORTB,1 ; Stop bit
movlw 0x80
movwf bit_cnt ;send over
int_end ;; ----- 割り込み終了処理 -----
movlw 0xff-bitDelay
movwf TMR0 ; tmr0再設定(32us間隔)
;swapf stsave,W ; STATUSを戻す
;movwf STATUS
;swapf wsave,F ; Wを戻す
;swapf wsave,W
retfie ; 復帰
;0.4msec Timer Subroutine
TIM10
MOVLW 0F9H ;249回
MOVWF CNT1 ;ここまでで2サイクル
TIMLP1 NOP
DECFSZ CNT1,F ;このループは4サイクル
GOTO TIMLP1 ;2+4*249-1=997
RETURN ;997+1=998*0.4usec=0.4msec
; 100msec Timer Subroutine
TIM100
MOVLW 0F9H ;249回
MOVWF CNT2
TIMLP2
CALL TIM10 ;2+(1000+3)*249-1=249748
DECFSZ CNT2,F ;このループは1回1003サイクル
GOTO TIMLP2
RETURN ;+1=249749サイクル
;
; 1Sec Timer Subroutine
;
T1SEC
MOVLW 0AH ;10回
MOVWF CNT3 ;100msec * 10
T1LP
CALL TIM100
DECFSZ CNT3,F ;このループは100msec
GOTO T1LP
RETURN
END