標準TTLだけ(!)でCPUをつくろう!(組立てキットです!)
(ホントは74HC、CMOSなんだけど…)
[第653回]

●DEVICE DESCRIPTOR

前回は、GET DEVICE DESCRIPTORを検出したところまで説明をいたしました。
PICのプログラムは、それに応えて、DEVICE DESCRIPTORを送出する用意をします。
GET DEVICE DESCRIPTORを検出したあとのプログラムは次のようになっていました。

;(1)"GET DESCRIPTOR('80'+'06')" received
	movf db3,w
	sublw 1; 1 or 2? 1:dev.descriptor 2:config descreptor
	bnz sendconf
;send DEVice DSCRPTR
	movlw 12
	cpfseq db6
	call resetADDR
	call setbd2
	call setbd0
	call setbd1	
	goto looptop

DEVICE DESCRIPTORを送出する準備をしているのはsetbd2サブルーチンです。
下にsetbd2サブルーチンを示します。

;ep0(IN) data set
setbd2
	call devdset1
	call setbd2odd
	movlw 1
	movwf bd2mk;=1
	return
;
setbd2odd
	lfsr 1,20b
	movlw 02;address high
	movwf POSTDEC1
	movlw 30;address low
	movwf POSTDEC1
	movlw 8;bytes
	movwf POSTDEC1	
	movlw 0c8
	movwf INDF1
	return


devdset1サブルーチンがDEVICE DESCRIPTORをデータバッファにセットするサブルーチンです。このサブルーチンについてはあとで説明をします。
setbd2oddサブルーチンはsetbd2サブルーチンの下にあります。
EP0(IN)のBUFFER DESCRIPTORに必要な値をセットします。
BUFFER DESCRIPTORについては[第638回][第639回]で説明をしています。

EP0(IN)のBUFFER DESCRIPTORはアドレス208〜20Bの4バイトです。
アドレス208はBUFFER DESCRIPTORの第1バイトBD2STATです。
そのビット7を1にすると、SIEに制御が移ってしまいます。
ですから、まずdevdset1サブルーチンでEP0(IN)バッファにデータをセットし、それからBUFFERE DESCRIPTORの後ろのアドレスから値をセットしていって、最後にアドレス208のBD2STATをセットします。
setbd2oddサブルーチンがアドレス208からではなく、アドレス20bから値をセットしているのはその理由からです。

アドレス20bはデータバッファアドレスの上位バイト、20aは下位バイトを示す値をセットします。
EP0(IN)データバッファはアドレス230〜237の8バイトです。
アドレス209は送出するバイト数を示します。
USBホストコントローラからのコマンドやそれに応えて送るデバイスディスクリプタなどのデータはEP0を使ってコントロール転送モードで送信、受信します。
コントロール転送では1度に送信するバイト数は8バイトです。
8バイト以上あるデータは8バイトに区切って送ります。

EP0(IN)はUSBホストコントローラにデータを送出するパイプです。
IN、OUTはホストコントローラから見た向きですから、PICから見たときは入力、出力の動作はその名前の意味と逆になります。
EP0(OUT)はPing−Pong Bufferの設定にしましたので、EP0(OUT)のDATA0(EVEN)とEP0(OUT)のDATA1(ODD)の2つのパイプを使います。
しかし、EP0(IN)はPing−Pong Bufferではありませんから、1つだけです。
でもデータを送信するときは、DATA0とDATA1を交互に使い分けて送信しなければなりません。

USBホストコントローラから送られてくるGET DESCRIPTORなどのデータ送信要求コマンドはDATA0(EVEN)で送られてきます。
それに応えてPICが送信するDEVICE DESCRIPTORの最初の8バイトはDATA1(ODD)になります。
アドレス208のBD2STATの値はDATA0とDATA1のときとでビットの一部が異なります。
BDnSTATについては、[第651回]で説明をしました。
DATA0(EVEN)のときは、ビット6=0にします。
DATA1(ODD)のときはビット6=1にします。
今回はDATA1を送りますから、アドレス208の値はC8(ビット6=1)にします。

説明の順序が逆になってしまいましたが、下にDEVICE DESCRIPTORの最初の8バイトをデータバッファにセットするサブルーチン devdset1を示します。

;
;device descriptor data set
;
devdset1	
	lfsr 1,230
	movlw 12;size(bytes)
	movwf POSTINC1
	movlw 01;type(DEVUCE DESCRIPTOR)
	movwf POSTINC1
	movlw 00;USB version 02.00(Low)
	movwf POSTINC1
	movlw 02;(High)
	movwf POSTINC1
	movlw 00;HID class
	movwf POSTINC1
	movlw 00;SUB class
	movwf POSTINC1
	movlw 00;protocol code
	movwf POSTINC1
	movlw 08;max packet size of EP0
	movwf POSTINC1
	return


DEVICE DESCRIPTORの最初の8バイトの内容は、プログラムリストにコメントしている通りです。
第1バイトはDESCRIPTORのバイト数(16進数)です。
DEVICE DESCRIPTORは18バイトです。16進数に直すと12になります。
第2バイトはDESCRIPTORの種類を示します。
DEVICE DESCRIPTORは01です。
第3、第4バイトはUSBのバージョンを示します。
USBのバージョンは2.0です。
第5バイトはclassコードです。
HIDクラスは00にします。
第6、第7バイトも00にします。
第8バイトはEP0の最大パケットサイズを示します。
8バイトです。

以上のプログラムを実行するとあとはSIE(PIC内蔵のUSBコントローラ)が、セットした値を決められたフォーマットでUSBホストコントローラに向けて送出してくれます。

しかし。
待ってください。
DEVICE DESCRIPTORは18バイトあると書きました。
ここまでのところで、最初の8バイトはデータバッファにセットしましたから、それをSIEが送出してくれるところまではわかりますが、残りの10バイトはどうするのでしょう?

実はそのための仕掛けがさきほどお見せしたsetbd2サブルーチンに仕込んであるのです。

	movlw 1
	movwf bd2mk;=1
	return

という部分です。
bd2mkはその仕掛けのためのワークレジスタです。
2010.11.4upload

前へ
次へ
ホームページトップへ戻る