H8/300/Tinyを使ったMidi受信システムの製作例
by yasuski
H8/3664を使ったMotorMix専用のMIDI/Rxユニットのアセンブルコードです。MotorMixのLED点滅プロトコルを受信し、そのデータを復調、on/off の状態をPort5とPort8に反映します。点灯アドレスは、MotorMix上にある二段目以下32個のLED/スイッチマトリックスに準拠しています。点灯パターンの選択は、この32個のLEDを左右16個のマトリックスとして扱い、左右のマトリックスを切り替える形でデータを選択しています。

  □□□□□□□□  MotorMix上面中央からみて。この列のLEDは無視する
  ○○○○○○○○  これはロータリーエンコーダー。
この部分のデータも無視
  @ABCDEFG  この列からLEDのOn/Offのデータを受信する。最終的には
  @ABCDEFG  左右4段のLEDスイッチ毎にグループ分けを行う。従って
  @ABCDEFG  データは最終的にアドレス00〜03と04〜07に分離されるが、
  @ABCDEFG  
受信直後はひとまず列毎に個別 のレジスタに記憶される

データ選択の設定はポート1のBit#6で行います。レベル"H"で左バンク選択となります。ディテクター部分のコードを他のポート・アドレスに書き換えることで、色々と応用が出来ると思います。.incファイルは後半に掲載してあります。 H8/3052実装による使用例はこちら
(動画/約3mb

コードの複製、改変は自由に行って頂いて結構ですが、作者は使用により生じた如何なる障害に対してその責任を負いませんので、ご了承下さい。

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; AKI-H8 Control program
;;;; 2005/07/03 switch preset signal receiver
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

.include "yasuski3.inc"

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Interrupt Vector Defines
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


.section vector, data, locate=h'0000

.data.w start
.org h'002e
.data.w int_scr3


.section rom,data, locate=h'0034


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Variables in work RAM area
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

.section ram,data,locate=h'f780 ;for 3664

swtrig .res.b 1

outputs_1 .res.b 1
outputs_2 .res.b 1
outputs_3 .res.b 1
outputs_4 .res.b 1

preset .res.b 1


.org h'f790
rx_fifo .res.b 512


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; register allocation
;;; er0 : temporary (for midi tx buffer)
;;; er1 : temporary
;;; er2 : temporary
;;; er3 : temporary
;;; er4 : temporary
;;; er5 : receive buffer pointer (e5: end, r5: top)
;;; er6 : temporary
;;; er7 : stack pointer
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; Main
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

.section program,code,locate=h'0034

start:
 mov.l #h'ff7f,er7 ; stack pointer set
  jsr @memory_set ; Work RAM clear and FIFO pointer
  jsr @sci_init
  jsr @wait_500msec ; Wait

  jsr @input_enable ; Port init
  jsr @midi_start ; MIDI rx start

loop:
  jsr @rx_data_receive
  jsr @sw_preset_out

  jmp @loop


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; MIDI sw data Receive
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


rx_data_receive:
 cmp.w r5,e5     ;r5: rx1_top, e5: rx1_end
  bne initialize
rts

initialize:
  sub.l er1,er1
 mov.w e5,r1     ;rx data address

data_Read:
 mov.b @(rx_fifo,er1),r0h   ; rx data -> [r0h]
  inc.w #1,r1
 bclr #1,r1h     ; rx buffer 512
 mov.w r1,e5    ; reWrite rx data address

 cmp.b #h'F0,r0h  ; sysex data thru
  bls ditector
  rts

ditector:

 btst #3,r4h     ; detecting 4th data flag =>r4h
  bne data_store2

 btst #2,r4h     ; detecting 3rd data flag
  bne detector_2

 btst #1,r4h     ; detecting 2nd data flag
  bne data_store

 btst #0,r4h     ; detecting 1st data flag
  bne next_flag

 cmp.b #h'B0,r0h  ; data header reading from MotorMix
  beq data_set1

 btst #6,r4h     ; detecting second ping flag
  bne trigger_out

 btst #5,r4h     ; detecting first ping flag
  bne next_flag2

 cmp.b #h'90,r0h    ; ping header flag
  beq receive_flag1

  rts


receive_flag1:
  bset #5,r4h
  bra data_Read
  next_flag2:
 cmp.b #h'00,r0h     ; ping second flag
  beq receive_flag2
 sub.b r4h,r4h       ;flag clear
  rts
receive_flag2:
  bset #6,r4h
  bra data_Read



trigger_out:
  cmp.b #h'7F,r0h
  beq rx_trig_on
  bra next_trig
  rx_trig_on:
  bset #7,r4l
  mov.b r4l,@pdr1
 and.b #b'10011111,r4h    ; erase the flags
rts

next_trig:
  cmp.b #h'00,r0h
  beq rx_trig_off
  rts

rx_trig_off:
  bclr #7,r4l
  mov.b r4l,@pdr1
 and.b #b'10011111,r4h    ; erase the flags
  rts



data_set1:
  bset #0,r4h
  bra data_Read

next_flag:
 cmp.b #h'0C,r0h        ; second data detector
  beq data_set2
  sub.b r4h,r4h
  rts

data_set2:
  bset #1,r4h
  bra data_Read

data_store:
 cmp.b #h'08,r0h        ; detecting sw data
  blt data_set3
  sub.b r4h,r4h
  rts

data_set3:
 mov.b r0h,r6l         ; loading the sw line data
 bset #2,r4h          ; setting the 3rd flag
  bra data_Read

detector_2:
 cmp.b #h'2C,r0h       ; detecting the 4th flag
  beq data_set4
  sub.b r4h,r4h
  rts

data_set4:
  bset #3,r4h
  bra data_Read

data_store2:

 and.b #b'01100000,r4h   ; erase the flags

  cmp.b #h'45,r0h
  beq line_01_on
  cmp.b #h'05,r0h
  beq line_01_off

  cmp.b #h'44,r0h
  beq line_02_on
  cmp.b #h'04,r0h
  beq line_02_off

  cmp.b #h'43,r0h
  beq line_03_on
  cmp.b #h'03,r0h
  beq line_03_off

  cmp.b #h'42,r0h
  beq line_04_on
  cmp.b #h'02,r0h
  beq line_04_off

  rts

line_01_on:
  mov.b @outputs_1,r2l
  bset r6l,r2l
  mov.b r2l,@outputs_1
  rts
  line_02_on:
  mov.b @outputs_2,r2h
  bset r6l,r2h
  mov.b r2h,@outputs_2
  rts
  line_03_on:
  mov.b @outputs_3,r3l
  bset r6l,r3l
  mov.b r3l,@outputs_3
  rts
  line_04_on:
  mov.b @outputs_4,r3h
  bset r6l,r3h
  mov.b r3h,@outputs_4
  rts
  line_01_off:
  mov.b @outputs_1,r2l
  bclr r6l,r2l
  mov.b r2l,@outputs_1
  rts
  line_02_off:
  mov.b @outputs_2,r2h
  bclr r6l,r2h
  mov.b r2h,@outputs_2
  rts
  line_03_off:
  mov.b @outputs_3,r3l
  bclr r6l,r3l
  mov.b r3l,@outputs_3
  rts
  line_04_off:
  mov.b @outputs_4,r3h
  bclr r6l,r3h
  mov.b r3h,@outputs_4
  rts







;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;preset out
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

sw_preset_out:

 mov.b @pdr1,r6h ; reading the switch output status
  btst #6,r6h
  beq sw_preset_out2

 mov.b @outputs_1,r2l
  mov.b @outputs_2,r2h
  mov.b @outputs_3,r3l
  mov.b @outputs_4,r3h

  and.b #b'00001111,r2l
  and.b #b'00001111,r2h
  and.b #b'00001111,r3l
  and.b #b'00001111,r3h

  shll r2l
  shll r2l
  shll r2l
  shll r2l
  add.b r2h,r2l

  shll r3h
  shll r3h
  shll r3h
  shll r3h
  add.b r3h,r3l

  mov.b r2l,@pdr5
  mov.b r3l,@pdr8

  rts

sw_preset_out2:

 mov.b @outputs_1,r2l
 mov.b @outputs_2,r2h
 mov.b @outputs_3,r3l
 mov.b @outputs_4,r3h

 and.b #b'11110000,r2l
 and.b #b'11110000,r2h
 and.b #b'11110000,r3l
 and.b #b'11110000,r3h

 shlr r2h
 shlr r2h
 shlr r2h
 shlr r2h
 add.b r2h,r2l

 shlr r3l
 shlr r3l
 shlr r3l
 shlr r3l
 add.b r3h,r3l

 mov.b r2l,@pdr5
 mov.b r3l,@pdr8

 rts


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;SCI init
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

sci_init:
 mov.b #b'00000000,r0l
 mov.b r0l,@scr3
 mov.b #b'00000000,r0l
 mov.b r0l,@smr
 mov.b #15,r0l
 mov.b r0l,@brr       ; bitRateSet for 16MHz
 mov.w #500,r0

_sci_wait:
 dec.w #1,r0
 bne _sci_wait

 mov.b #b'00000010,r0l      ; TXD enable
 mov.b r0l,@pmr1

 rts


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;Stack and work RAM init
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

memory_set:

 mov.l #h'f780,er2     ; ram start addr for 3664
 mov.w #h'0400,r1      ; clear 1k bites

 mov.b #0,r0l

_ram_clear:
 mov.b r0l,@er2
 inc.l #1,er2
 dec.w #1,r1
 bne _ram_clear
 sub.l er4,er4
 sub.l er5,er5
 sub.l er6,er6
 rts


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; Input channels initialization
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

input_enable:

 mov.b #b'10000000,r0l
 mov.b r0l,@pcr1

 jsr @wait_500msec

 mov.b #b'11111111,r0l

 mov.b r0l,@pcr5
 mov.b r0l,@pcr8

 jsr @wait_500msec
 rts

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; MIDI rx start !
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

midi_start:
 mov.b #b'01010000,r0l     ; receive only 10100000 = Transmit Only
 mov.b r0l,@scr3

 
mov.b @ssr,r0l          ; (dummy read)
 mov.b #0,r0l
 mov.b r0l,@ssr


 andc #b'01111111,ccr     ; interrupt enable

 rts

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; Timer / Counter Routines
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

wait_500msec:
 push.l er1
 push.l er2
 mov.l #500,er1
_wait_1:
 jsr @wait_1msec
 sub.l #1,er1
 bne _wait_1
 pop.l er2
 pop.l er1
 rts

wait_100msec:
 push.l er1
 push.l er2
 mov.l #100,er1
_wait_2:
 jsr @wait_1msec
 sub.l #1,er1
 bne _wait_2
 pop.l er2
 pop.l er1
 rts

wait_10msec:
 push.l er1
 push.l er2
 mov.l #10,er1
_wait_3:
 jsr @wait_1msec
 sub.l #1,er1
 bne _wait_3
 pop.l er2
 pop.l er1
 rts

wait_1msec:
 mov.l #2048,er2
 _wait_4:
 sub.l #1,er2
 bne _wait_4
 rts


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; Exception handling routines
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

int_scr3:

 push.l er0
 bclr #6,@scr3        ;Desable Receive interrupt
 mov.b @rdr,r0h       ;get midi rx
 btst #5,@ssr
 bne rx_err          ;jump if error has occured

 mov.b r0h,@(rx_fifo,er5)  ;rx to fifo
 inc.w #1,r5
 bclr #1,r5h
 bra rx_ok

rx_err:

 mov.b @ssr,r0l
 mov.b #H'80,r0l
 mov.b r0l,@ssr ;clearing the error

rx_ok:
 bset #6,@scr3        ;enable receive int
 pop.l er0
 rte

.end



; yasuski.inc.v3 2004/04/17 by yasuski

;-------------------------------------------------
; AKI-H8 Control program for switch matrix
; Definitions of constants
;-------------------------------------------------

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Serial Port Registers
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

smr .equ h'ffa8 ; Serial Mode
brr .equ h'ffa9 ; Bit Rate
scr3 .equ h'ffaa ; Serial Control
tdr .equ h'ffab ; Transmit Data
ssr .equ h'ffac ; Serial Status
rdr .equ h'ffad ; Receive Data

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; I/O Port Registers
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

pdr1 .equ h'ffd4
pdr2 .equ h'ffd5
pdr5 .equ h'ffd8
pdr7 .equ h'ffda
pdr8 .equ h'ffdb
pdrB .equ h'ffdd
pmr1 .equ h'ffe0
pmr5 .equ h'ffe1

pcr1 .equ h'ffe4
pcr2 .equ h'ffe5
pcr5 .equ h'ffe8
pcr7 .equ h'ffea
pcr8 .equ h'ffeb

; A/D registers

adda .equ h'ffb0
addb .equ h'ffb2
addc .equ h'ffb4
addd .equ h'ffb6
adcsr .equ h'ffb8
adcr .equ h'ffb9


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Interrupt Control Registers
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

iegr1 .equ h'fff2
iegr2 .equ h'fff3
ienr1 .equ h'fff4
irr1 .equ h'fff6

tdre .bequ 7,ssr
rdrf .bequ 6,ssr
oer .bequ 5,ssr
fer .bequ 4,ssr
per .bequ 3,ssr

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; state machine flag
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

is_2byte .equ 7
is_3byte .equ 6
has_byte2 .equ 5