0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

自作CPUAdvent Calendar 2022

Day 25

CalicoCPU でキースキャン (Pmod KYPD 読み取り)

Posted at

自作CPU「CalicoCPU」で、Pmod KYPD 上で押されたキーの認識をしてみた。

Pmod KYPD

Pmod KYPD は、列に対応する4本の入力端子と、行に対応する4本の出力端子を持つ。
そして、4×4で16個のキーがある。
出力端子はプルアップされており、LOWが入力された列のキーが押されるとLOWになる。
そのため、キーは一度に1個しか押されないと仮定すれば、1列ずつLOWを入力し、出力がLOWになる位置を探すことで、どのキーが押されたかを判定できる。

プログラム

ポート1に接続された Pmod KYPD で押されたキーの番号を、ポート0の下位4ビットに出力する。

以下のプログラムは、MikeAssembler でアセンブルできる。

target calico

; PORT0 lower : read result
; PORT1 : Pmod KYPD

	MOVI A, 0xf
	DRIVE 0, A
	DRIVE 1, A
main_loop:
	; スキャンを行うキーの番号
	MOVI A, 0
	; スキャンを行う列を表すビット
	MOVI B, 8
scan_loop:
	; 列のビットを反転して、出力する
	MOV C, B
	NOT C
	OUT 1, C
	NOP
	; 行のスキャン結果を読み込み、反転する
	IN C, 1
	NOT C
	SHR C, 4
	; 押されているボタンがあれば、判別処理に進む
	MOVI D, key_pressed
	JNZ C, D
	; 次の列のスキャンに進む
	ADDI A, 4
	SHR B, 1
	MOVI D, scan_loop
	JNZ B, D
	; 全ての列のスキャンが終わったので、最初に戻る
	MOVI D, main_loop
	JNZ D, D
	; 行のどのビットが1かを調べる
key_pressed:
	; 1のビットが無くなるまでシフトする
	SHR C, 1
	MOVI D, find_row_loop
	JNZ C, D
	MOVI D, key_concluded
	JNZ D, D
find_row_loop:
	; シフトした回数を数える
	ADDI A, 1
	MOVI D, key_pressed
	JNZ D, D
	; どのキーが押されたのかの調査が完了した
key_concluded:
	; テーブルを引いて押されたキーに対応する数値を求める
	MOVI3 C, key_table
	ADD C, A
	ADD C, A
	MOVI D, key_out
	JNZ C, C
key_table:
	MOVI C, 0
	JNZ D, D
	MOVI C, 7
	JNZ D, D
	MOVI C, 4
	JNZ D, D
	MOVI C, 1
	JNZ D, D

	MOVI C, 0xF
	JNZ D, D
	MOVI C, 8
	JNZ D, D
	MOVI C, 5
	JNZ D, D
	MOVI C, 2
	JNZ D, D

	MOVI C, 0xE
	JNZ D, D
	MOVI C, 9
	JNZ D, D
	MOVI C, 6
	JNZ D, D
	MOVI C, 3
	JNZ D, D

	MOVI C, 0xD
	JNZ D, D
	MOVI C, 0xC
	JNZ D, D
	MOVI C, 0xB
	JNZ D, D
	MOVI C, 0xA
	JNZ D, D

key_out:
	OUT 0, C
	MOVI D, main_loop
	JNZ D, D

以下は、このプログラムをHEX形式で表したものである。

:100000002F161E2068848A9A00988A8F8FEBCD9FC6
:10001000344BE55FE3DF8BE2C7FF9FE2C7F3DF31DD
:10002000EBCDDFAB83008181E5C7FC9BA0DFA7DFC1
:10003000A4DFA1DFAFDFA8DFA5DFA2DFAEDFA9DF8E
:0F004000A6DFA3DFADDFACDFABDFAADF92E3DF2C
:00000001FF

解説

Pmod KYPD の入力や出力は「1ビットをLOWにする」が基本であるが、
「0になったかどうか」でループの終了を判定するため1ビットをHIGHにする形でデータを持ち、入出力時に反転する形にした。
また、右シフトで下位へ抜けて0になるようにするため、上位ビットから下位ビットの順で判定する。

まず、キーの番号を4ずつ増やしながら、列のスキャンを行う。
よって、Pmod KYPD の列は左ほど上位のビットになっているので、左ほど若い番号になる。
なお、CalicoCPU では入力を一旦 D-FF で受けているため、OUT 命令の直後に IN 命令を実行すると、OUT 命令の結果が反映される前の状態が読み込まれてしまい、スキャンがうまくいかない。
そこで、OUTIN の間に NOP を挟んだ。
ある列についていずれかの行のキーが押されていることがわかったら、キーの番号を1ずつ増やしながら右シフトを行い、行のどのキーが押されているかを調べる。
このときは、下位ビットから先に抜けるので、同じ列の中では下位ビットほど若い番号になる。
すなわち、Pmod KYPD の行は下ほど下位のビットになってるので、下ほど若い番号になる。

まとめると、キーに対して以下のように番号を割り当てたことになる。

 3   7  11  15
 2   6  10  14
 1   5   9  13
 0   4   8  12

一方、Pmod KYPD のキーは以下のように配置されている。

 1   2   3   A
 4   5   6   B
 7   8   9   C
 0   F   E   D   

単純な計算式で変換するのは難しそうなので、変換テーブルを用意することにした。
変換テーブルの1項目は、「変換結果の値を格納する命令」と「次の処理に移るためのジャンプ命令」で構成する。
そして、「変換テーブルの最初の項目のアドレス」に「変換テーブルの1項目のサイズ×変換する値」を足したアドレスにジャンプすることで、テーブルを引く。

最後に、変換したキーの番号を出力し、次のスキャンに移る。

実行結果

ポート0の下位ビットに 1-Digit 7seg Board を、ポート1に Pmod KYPD を接続して実行した。

押したキーの番号が正しく表示に反映されている。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?