LIST 27 ============================================================================ ;##### RAM Map ##### org 8000h ; ← RAM領域に変数を定義 rx_fifo ds 2048 tx_fifo ds 2048 rx_top ds 2 rx_end ds 2 tx_top ds 2 tx_end ds 2 rsb ds 1 dcb ds 1 channel ds 1 keyno ds 1 ;##### I/O Map ##### sio_a equ 0018h sio_b equ 001ah ; ← 内蔵SIOのアドレス定義 ;##### RESET ##### org 0000h ; ← リセットするとここから始まる ld sp,09fffh ; ← スタックポインタをセット di ; ← 割り込みを禁止 jp main ; ← メインに飛ぶ ;##### INT / NMI ##### org 0020h ; ← MIDI受信割り込みルーチン dw _midi_ _midi_: ex af,af' exx ld de,(rx_top) ld a,10000000b or d ld h,a ld l,e in a,(sio_a+0) ; ← シリアルポートからデータ入力 ld (hl),a ; ← これを受信FIFOに積む inc de res 3,d ld (rx_top),de exx ex af,af' ei reti org 0066h retn ;##### Main ##### main: ld hl,08000h ld a,0a0h _ram_clear_loop: ld (hl),0 ; ← RAM領域をゼロクリア inc hl cp h jr nc,_ram_clear_loop ld a,00011000b ; Channel Reset B out (sio_b+1),a ld a,00000100b ; Resister Point = 4 out (sio_b+1),a ld a,11000100b ; Mode out (sio_b+1),a ld a,00000001b ; Resister Point = 1 out (sio_b+1),a ld a,00000000b ; Interrupt Mode out (sio_b+1),a ld a,00000010b ; Resister Point = 2 out (sio_b+1),a ld a,20h ; Vector Address out (sio_b+1),a ld a,00011000b ; Channel Reset A out (sio_a+1),a ld a,00000100b ; Resister Point = 4 out (sio_a+1),a ld a,11000100b ; Mode out (sio_a+1),a ld a,00000001b ; Resister Point = 1 out (sio_a+1),a ld a,00010000b ; Interrupt Mode out (sio_a+1),a ld a,00000101b ; Resister Point = 5 out (sio_a+1),a ld a,01101000b ; Transmit Start out (sio_a+1),a ld a,00000011b ; Resister Point = 3 out (sio_a+1),a ld a,11000001b ; Receive Start out (sio_a+1),a im 2 ei in a,(sio_a+0) ; dummy read im 2 ; 内部I/O割り込みモード ei ; 割り込み許可 loop: call tx_data_check call rx_data_check jr loop tx_data_check: ld de,(tx_end) ld hl,(tx_top) and a ; CY <-- 0 sbc hl,de ret z ; ← 新しい送信データがなければパス ld a,00000000b ; Resister Point = 0 out (sio_a+1),a in a,(sio_a+1) bit 2,a ret z ; ← 送信OKでなければパス ld a,10001000b or d ld h,a ld l,e ld a,(hl) ; 送信FIFOからデータを取り出して out (sio_a),a ; MIDIより送信する inc de res 3,d ld (tx_end),de ret tx_fifo_set: ld de,(tx_top) ld a,10001000b or d ld h,a ld l,e ld (hl),b ; [B]のデータを送信FIFOに積む inc de res 3,d ld (tx_top),de ret rx_data_check: ld de,(rx_end) ld hl,(rx_top) and a ; CY <-- 0 sbc hl,de ret z ; ← 受信FIFOが空ならパス ld a,10000000b or d ld h,a ld l,e ld b,(hl) inc de res 3,d ld (rx_end),de bit 7,b ; MSB=0 ならデータバイト jr z,running ; running ld a,b cp 0f8h ret nc cp 0f0h jr c,statusbyte xor a ld (rsb),a ; RSB = running status buffer ret statusbyte: ld a,b ; ステータスバイトは and 00001111b ld (channel),a ; チャンネルと ld a,b and 11110000b ld (rsb),a ; RSBに分離しておく xor a ld (dcb),a ; DCB = data count buffer ret running: ld a,(rsb) cp 0 ret z ; 無効ステータスの時のデータは無視 cp 0c0h jr z,_2byte cp 0d0h jr z,_2byte ; 2byte形式は[C*]と[D*]だけ ld a,(dcb) cp 0 jr nz,_3byte ; 3byte目なら処理に飛ぶ inc a ld (dcb),a ; 3byte形式の2byte目の場合はここ ld a,b ld (keyno),a ret _2byte: ld c,b ld a,(rsb) ld b,a ld a,(channel) or b call tx_fifo_set ; Status Byteを復元して送信FIFOに ld b,c call tx_fifo_set ; Data Byteを送信FIFOに積む ret _3byte: xor a ld (dcb),a ld c,b ld a,(rsb) ld b,a ld a,(channel) or b call tx_fifo_set ; Status Byteを復元して送信FIFOに ld a,(keyno) ld b,a call tx_fifo_set ; 2byte目のData Byteを送信FIFOに積む ld b,c call tx_fifo_set ; 3byte目のData Byteを送信FIFOに積む ret end ============================================================================