センサ→MIDIインターフェース
キーエンスの赤外線センサは、反射板までの赤外線ビームを遮断
する状態をON/OFFとしてリレー出力(スイッチのようなもの)しています。
そこで、この7個のスイッチ状態をMIDI化してMAXに送る
インターフェースを作りました。
センサ部分は、オブジェとして制作して、展示会場ではケーブルで
かなり長く伸ばすので、延長コードとしてRCAのピンケーブルを使用
することにしました。また、教育的な意図から、敢えてケースに入れずに
基板ムキ出しにして中身が見えるようにしました。そこで全体としては、
このように、8個のピンジャックとマイコン基板の並ぶ外見となりました。
使ったのは、いつも使い慣れた(^_^)、秋月電子のAKI-H8です。
回路図は例によって、まったく描かずにいきなり穴あけとハンダ付けを
開始しました。これは、あとから思い出して描いた回路図です。
いい子は真似しないように。(^_^;)
ケースの裏側はこんな感じで、電源モジュールとMIDI出力バッファが
あります。この電源は、秋月電子の店頭に積んでいた極安品。
MIDI出力は、ちゃんと74HC05で送っています。
何も見ないで、ここまでの制作に3時間ぐらいかかりました。そして、
あとはいよいよAKI-H8のソフトだけだ、という楽しい作業を残して
帰ろうとしたのですが、第1期虎の穴の加藤さんが、AKIのプログラミングを
見てみたい、というので、そのまま続けてソフト開発に進みました。
考えてみると、これまでのMIDIオリジナル機器は全てASLの実験室(自室)で
一人で黙々と開発してきたので、加藤さんは、「AKIものの誕生に立会った
最初の人」ということになりました。(^_^)
AKI-H8の開発環境とか開発手順とかは、
こちら
にあるので詳細は省略します。PowerBookでVirtualPCを走らせて、
そこにWindows95を走らせてその中でDOS窓を開きます。
ソースプログラムは秀丸エディタで編集し、あとは秋月のツール
でアセンブル、リンク、そしてフラッシュROMに書き込む、という
ループを回すだけです。
DOS窓の中で開発用に使ったオリジナルのバッチプログラム
は以下のようなものです。
a38h %1.src -cpu=300ha:20
l38h %1.obj -output=FlashROM.abs
c38h FlashROM
pause
del FlashROM.abs
del %1.obj
del %1.lis
flash
今回のAKI-H8のソースプログラムは以下のようなものです。
ちょっと詳しい解説をしている余裕がないので、省略です。
虎の穴には機会をみて、おいおい伝授していきましょう。(^_^;)
;-----------------------------------------------------------
;
; Shinkai : May 2000
;
;-----------------------------------------------------------
;##### Port Defines #####
smr .equ h'0fffb0
brr .equ h'0fffb1
scr .equ h'0fffb2
tdr .equ h'0fffb3
ssr .equ h'0fffb4
rdr .equ h'0fffb5
paddr .equ h'0fffd1
padr .equ h'0fffd3
pbddr .equ h'0fffd4
pbdr .equ h'0fffd6
iprb .equ h'0ffff8
;##### Vector Defines #####
.section vector,data,locate=h'000000
.data.l start
;##### Work RAM Data Defines #####
.section ram,data,locate=h'0fef10
timer1 .res.w 1
timer2 .res.w 1
tx_top .res.w 1
tx_end .res.w 1
counter .res.b 1
led .res.b 1
ad_data .res.b 1
old_sw .res.b 1
timer3 .res.b 1
.org h'0ff400
tx_fifo .res.b 1024
;***** Reset --> Initialize --> Main Loop *****
.section program,code,locate=h'002000
start:
mov.l #h'0fff0f,er7 ; stack pointer set
mov.l #h'0fef10,er2
mov.w #h'0fe0,r1
mov.b #0,r0l
_ram_clear:
mov.b r0l,@er2
inc.l #1,er2
dec.w #1,r1
bne _ram_clear
jsr @sci0_init ; SCI initialize
mov.b #b'00000000,r0l
mov.b r0l,@paddr ; set : Port[A] all input
mov.b #b'11111111,r0l
mov.b r0l,@pbddr ; set : Port[B] all output
mov.b #b'01110000,r0l ; tx/rx start !
mov.b r0l,@scr
mov.b #0,r0l
mov.b r0l,@pbdr
loop:
jsr @ad_check
jsr @timer_check
jsr @tx_midi_check
jmp @loop
;***** A/D Check Routine *****
ad_check:
mov.b @timer3,r1l
inc.b r1l
mov.b r1l,@timer3
cmp.b #100,r1l
beq _ad_1
rts
_ad_1:
mov.b #0,r1l
mov.b r1l,@timer3
jsr @sw_check
rts
sw_check:
mov.b @padr,r2l
mov.b @old_sw,r2h
cmp.b r2l,r2h
bne _sw_event
rts
_sw_event:
btst #0,r2l
beq _sw002 ; new=ON
btst #0,r2h
bne _sw002 ; old=OFF --> pass
mov.b #h'90,r0h
jsr @tx_fifo_set
mov.b #60,r0h
jsr @tx_fifo_set
mov.b #100,r0h
jsr @tx_fifo_set
mov.b #60,r0h
jsr @tx_fifo_set
mov.b #0,r0h
jsr @tx_fifo_set
_sw002:
btst #1,r2l
beq _sw102 ; new=ON
btst #1,r2h
bne _sw102 ; old=OFF --> pass
mov.b #h'90,r0h
jsr @tx_fifo_set
mov.b #62,r0h
jsr @tx_fifo_set
mov.b #100,r0h
jsr @tx_fifo_set
mov.b #62,r0h
jsr @tx_fifo_set
mov.b #0,r0h
jsr @tx_fifo_set
_sw102:
; jmp @exit_point
btst #2,r2l
beq _sw202 ; new=ON
btst #2,r2h
bne _sw202 ; old=OFF --> pass
mov.b #h'90,r0h
jsr @tx_fifo_set
mov.b #64,r0h
jsr @tx_fifo_set
mov.b #100,r0h
jsr @tx_fifo_set
mov.b #64,r0h
jsr @tx_fifo_set
mov.b #0,r0h
jsr @tx_fifo_set
_sw202:
btst #3,r2l
beq _sw302 ; new=ON
btst #3,r2h
bne _sw302 ; old=OFF --> pass
mov.b #h'90,r0h
jsr @tx_fifo_set
mov.b #65,r0h
jsr @tx_fifo_set
mov.b #100,r0h
jsr @tx_fifo_set
mov.b #65,r0h
jsr @tx_fifo_set
mov.b #0,r0h
jsr @tx_fifo_set
_sw302:
btst #4,r2l
beq _sw402 ; new=ON
btst #4,r2h
bne _sw402 ; old=OFF --> pass
mov.b #h'90,r0h
jsr @tx_fifo_set
mov.b #67,r0h
jsr @tx_fifo_set
mov.b #100,r0h
jsr @tx_fifo_set
mov.b #67,r0h
jsr @tx_fifo_set
mov.b #0,r0h
jsr @tx_fifo_set
_sw402:
btst #5,r2l
beq _sw502 ; new=ON
btst #5,r2h
bne _sw502 ; old=OFF --> pass
mov.b #h'90,r0h
jsr @tx_fifo_set
mov.b #69,r0h
jsr @tx_fifo_set
mov.b #100,r0h
jsr @tx_fifo_set
mov.b #69,r0h
jsr @tx_fifo_set
mov.b #0,r0h
jsr @tx_fifo_set
_sw502:
btst #6,r2l
beq _sw602 ; new=ON
btst #6,r2h
bne _sw602 ; old=OFF --> pass
mov.b #h'90,r0h
jsr @tx_fifo_set
mov.b #71,r0h
jsr @tx_fifo_set
mov.b #100,r0h
jsr @tx_fifo_set
mov.b #71,r0h
jsr @tx_fifo_set
mov.b #0,r0h
jsr @tx_fifo_set
_sw602:
btst #7,r2l
beq _sw702 ; new=ON
btst #7,r2h
bne _sw702 ; old=OFF --> pass
mov.b #h'90,r0h
jsr @tx_fifo_set
mov.b #72,r0h
jsr @tx_fifo_set
mov.b #100,r0h
jsr @tx_fifo_set
mov.b #72,r0h
jsr @tx_fifo_set
mov.b #0,r0h
jsr @tx_fifo_set
_sw702:
exit_point:
mov.b r2l,@old_sw
rts
;***** SCI init / MIDI Transmit Routines *****
sci0_init:
mov.b #b'00000000,r0l
mov.b r0l,@scr
mov.b #b'00000000,r0l
mov.b r0l,@smr
mov.b #15,r0l
mov.b r0l,@brr
mov.w #500,r0
_sci0_wait:
dec.w #1,r0
bne _sci0_wait
mov.b @ssr,r0l ; (dummy read)
mov.b #0,r0l
mov.b r0l,@ssr
mov.b #b'00001000,r0l
mov.b r0l,@iprb ; SCI0-int priority UP !
rts
tx_midi_check:
mov.w @tx_top,r1
mov.w @tx_end,r6
cmp.w r1,r6
bne _tx_exist
rts
_tx_exist:
btst #7,@ssr ; test TRDE
bne _tx_seq
rts
_tx_seq:
mov.w #0,e6
mov.b @(tx_fifo,er6),r0l
mov.b r0l,@tdr
bclr #7,@ssr ; Transmit !
inc.w #1,r6
bclr #2,r6h
mov.w r6,@tx_end
rts
tx_fifo_set:
mov.w @tx_top,r6
mov.w #0,e6
mov.b r0h,@(tx_fifo,er6) ; transmit data = [r0h]
inc.w #1,r6
bclr #2,r6h
mov.w r6,@tx_top
rts
;***** Timer / Counter Routines *****
wait_500msec:
mov.l #500,er1
_wait_1:
jsr @wait_1msec
sub.l #1,er1
bne _wait_1
rts
wait_1msec:
mov.l #2048,er2
_wait_2:
sub.l #1,er2
bne _wait_2
rts
timer_check:
mov.w @timer1,r1
inc.w #1,r1
mov.w r1,@timer1
beq _timer_1
rts
_timer_1:
mov.w @timer2,r1
inc.w #1,r1
mov.w r1,@timer2
cmp.w #128,r1
bne _timer_2
mov.w #0,r1
mov.w r1,@timer2
_timer_2:
mov.b @led,r0l
bnot #5,r0l
mov.b r0l,@led
mov.b r0l,@pbdr ; write to Port[B]
rts
.end
AKI-H8のフラッシュROMに送ったモトローラ形式の
オブジェクトは以下のようなものです。これだけあれば、
同一の回路についてはアセンブル不要で走ります。
S00E0000466C617368524F4D4D4F5426
S107000000002000D9
S11320007A07000FFF0F7A02000FEF1079010FE03C
S1132010F80068A80B721B5146F85E0021C0F80057
S113202038D1F8FF38D4F87038B2F80038D65E00EB
S1132030203E5E0022545E0021E05A00202E6A09F1
S1132040EF1C0A096A89EF1CA964587000025470D6
S1132050F9006A89EF1C5E00205C54702AD36A027F
S1132060EF1B1CA2586000025470730A58700024BE
S113207073025860001EF0905E002216F03C5E0072
S11320802216F0645E002216F03C5E002216F00079
S11320905E002216731A5870002473125860001ED3
S11320A0F0905E002216F03E5E002216F0645E00A1
S11320B02216F03E5E002216F0005E002216732AFE
S11320C05870002473225860001EF0905E002216A0
S11320D0F0405E002216F0645E002216F0405E00BF
S11320E02216F0005E002216733A587000247332F1
S10920F05860001EF09091
S11320F65E002216F0415E002216F0645E00221690
S1132106F0415E002216F0005E002216734A5870F4
S1132116002473425860001EF0905E002216F043BE
S11321265E002216F0645E002216F0435E0022165D
S1132136F0005E002216735A5870002473525860DA
S1132146001EF0905E002216F0455E002216F06433
S11321565E002216F0455E002216F0005E0022168F
S1132166736A5870002473625860001EF0905E0014
S11321762216F0475E002216F0645E002216F04730
S11321865E002216F0005E002216737A5870002451
S113219673725860001EF0905E002216F0485E00CF
S11321A62216F0645E002216F0485E002216F00046
S11321B65E0022166A8AEF1B5470F80038B2F800E4
S11321C638B0F80F38B1790001F41B5046FC28B437
S11321D6F80038B4F80838F854706B01EF146B063E
S10721E6EF161D16BA
S11321EA5860000254707EB47370586000025470D1
S11321FA790E000078606A28000FF40038B37FB4C0
S113220A72700B5672266B86EF1654706B06EF14B8
S113221A790E000078606AA0000FF4000B5672264C
S113222A6B86EF1454707A01000001F45E002244B5
S113223A7A310000000146F454707A020000080063
S113224A7A320000000146F854706B01EF100B510B
S113225A6B81EF105870000254706B01EF120B512F
S113226A6B81EF1279210080586000087901000020
S113227A6B81EF126A08EF1971586A88EF1938D619
S105228A54708B
S9032000DD
あまり美しくない単純なコピーですが、人体が赤外線を遮断する
というセンシングには、これでも十分なものでした。
途中、間抜けなミスに10分ほど悩むところを加藤さんにしっかり
目撃されましたが(^_^;)、基本的にはハードの配線からソフトまで
ほぼノーバグで無事に完成しました。(^_^)
|