センサ→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分ほど悩むところを加藤さんにしっかり 目撃されましたが(^_^;)、基本的にはハードの配線からソフトまで ほぼノーバグで無事に完成しました。(^_^)