自前の資料を基に作りました. 対象はネイティブの 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