memory base driver for 6280 1/3

自前の資料を基に作りました. 対象はネイティブの IO port 経由です. 別の組み込み MCU を使う場合は設定条件をよくみて SPI 機能を使うとよいでしょう.

こういうシフトレジスタの処理だけならアセンブラで書くのはとても楽しいです.

送信ルーチン

serial_send:
send_bit_next:
	lsr	<$02
	ror	<$01
	ror	<$00
	cla
	rol	a
	sta	joypad
	ora	#1<<1
 rept 0
	nop
 endm
	sta	joypad
	dex
	bne	send_bit_next
	rts

解析したサブルーチンは最大 8 bits まで送れる作りでしたが、zero page を使って最大 24 bits送れるようにしました. また Carry flag を活用して分岐命令を減らしています.

rept 0 について. 送信に関しては nowait で送ってかまわないようです.

初期化ルーチン+簡単な受信

	ldx	#9
	lda	#$A8
	sta	<$00
	stz	<$01
	bsr	serial_send
	lda	joypad
	sta	<$00
	and	#$0f
	php
	ldx	#1
	stx	<$00
	bsr	serial_send
	plp
	bne	init_ng
	lda	joypad
	and	#$0f
	cmp	#1<<2
	bne	init_ng
	sec
	rts

既存のルーチンは 8bits 送信, 1 bit 送信+受信, 1bit 送信+受信でしたが、 9bits 送信+受信, 1bit 送信+受信にわけました. 送信後, IO port から受信するときは CLOCK 立ち上がりから出力まで遅いみたいです. この場合は dex; bne; rts と十分に時間が経過しているので待ち時間の挿入はいりません.

先日の解析でプログラムを読み間違えたので、間違いに従い 10bits の初期化コードを3度送ってしまいました. この場合はエラーがでるにもかかわらず、実際には初期化が成功していて input bit 0 の出力が memory data となるので上キーとIボタンが送信されなくなりました.

メモリデータの受信

	ldx	#1<<1
	cly
read_byte_next:
	lda	#1<<7
	sta	<$00
read_bit_next:
	stz	joypad
 rept 0
	nop
 endm
	stx	joypad
 rept 2 ;do not remove
	nop
 endm
	lda	joypad
	lsr	a
	ror	<$00
	bcc	read_bit_next
	lda	<$00
	sta	(<mb128_destsrc),y
;dest or src += 1; length -= val; length == 0
	bsr	rw_ptr_length_update
	bne	read_byte_next
	stz	joypad
	rts
  • zero page $00 を 8bits シフトレジスタにします.
  • bit7 = 1, bit6:0 = 7'h00 にすることでカウンタも兼ねます.
  • stz joypad (clock=0); stx joypad (clock=1)のあとの nop は必要でそのあと lda joypad です.
  • lda joypad; lsr a で取り込んだデータを Carry にいれ、シフトレジスタにいれます. lsr joypad だと予期しない書き込み処理も入るので lda 命令を使います.

最近の MCU でやる場合

  • 最近のシフトレジスタバイスは MSB->LSB がほとんどで LSB->MSB なのに注意が必要です.
  • メモリベースからのデータの更新条件はクロックの立ち下がりではなく立ち上がりのために立ち上がり直後に読み込むとデータが安定しません.
  • どこまで早いクロックでいけるのかを調べると楽しいと思います.