スポンサーサイト

.-- -- スポンサー広告 comment(-) trackback(-)
上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

AVR-USB(5)

.18 2010 AVR-USB comment(0) trackback(0)
recvLoopを書いてみた。NRZI変換をするので、一つ前のbitとex-orを取って順番に入れていく。

USB_PIN(0)がD-なのでこんな感じ:
recvLoop:
bit0:
	in		x1, USB_PIN		; x1に読み込む
	eor		x2, x1			; ex-or(大事なのは最下位ビット、x2に1clk前のUSB_PINが入っている)
	ror		x2				; x2の最下位ビットをcarryに転送
	ror		recvbuf			; 全体をシフトしつつ最上位にcarryが入る
	; あと4clkでbit-stuffing判定など
bit1:
	in		x2, USB_PIN
	eor		x1, x2
	ror		x1
	ror		recvbuf			; 最上位:(bit0 xor bit1)これが最終的に最下位までシフトされる
	; check bit-stuffing, etc
bit2:
	...
bit7:
	...
	rjmp	recvLoop

# いい加減AVR-ASM用のbrushを定義したほうがいいな。

1bit読み込むのに8clkしか使えないというのはなかなかきついです。読み込んでxor(本当はxnorとりたいがclk数の関係で最後にcomする)とるだけで4clk使っています。 いろいろ考えたけどこれより速い方法は思いつかないですね。

bit-stuffing判定はxorとった値が6回連続で0だったら次のbitは無視するというものですが、 6回数えるというのにこだわってカウンタを用意してcarryが1ならクリア、0ならインクリメントなんてやっていたら絶対4clkに収まりません。

ここで一日悩んで挫折して結局先人の知恵を拝借しました…

じーっと受信Loopっぽいところを睨んでいると
cpi shift, 4
がやたらと目に付きます。6回連続で0が入ったら上位6bitは0、つまり4未満という理屈です。これは思いつきませんでした。

でもbit-stuffingのときってそのbitは無視するので一回4未満になったら次のbitを読むときも4未満のままなんじゃ…??
と思ってさらにじっくり読むとbit-stuffingの処理のときに0だった上位6bitを全部1にしているんですねぇ。 どうせ最後に反転するんだから先にその分だけ反転しておくという発想です。これは感動しました。

各bitを受信するコードはどれも似たような処理なのでrcall-retで処理したいところですが、rcall-retは計7clk使うので今回はだめです。
でも書くときはラクしたいのでマクロを定義します。

AVRアセンブリのマクロの書き方:
.macro マクロ名 引数名1, 引数名2, ...
	処理内容(引数を使うときは\引数名のような書き方をする)
.endm

古いコンパイラでは終わりが.endmacroで引数が@0~@9になっていたりします。

とりあえず今回は
.macro recvbit new, old
	in		\new, USB_IN
	eor		\old, \new
	ror		\old
	ror		recvbuf
.endm

として4clkかかるマクロを用意しました。
次がstuffed-bitかどうかを判定するのに2clk必要なので残るは2clk。その2clkの配分を考えます。
bit7は全ビット読み込んだ状態なのでxorしてこれをSRAMに書き込みます。これに1+2clkかかり、1clkオーバーしますが、 その分6bit目の処理を1clkでできるもの(受信バイト数のinc)にすればよさそうです。
さらに、反転用レジスタはbit0受信直後に初期化します。
あとは適当にSE0状態になってないか確認したりLoopを閉じたり(bit5)すればよさそうです。
recvLoop:
recv_bit6:	; inc count
recv_bit7:	; eor, st
recv_bit0:	; ldi(serでもok)
recv_bit1:	; check se0
recv_bit2:	; check se0
recv_bit3:	; check se0
recv_bit4:	; check se0
recv_bit5:	; rjmp

recv_stuff0:
recv_stuff1:
...
recv_stuff7:

の順に書いていけばよさそうです。
# どうでもいいけど全bitを0にする時って
ldi reg, 0x00

eor reg, reg
がありますが前者はSREGのフラグを変化させないのに対して後者はZフラグを立てるんですね。はまりそうだから一応メモ。


気分転換にサンプルプロジェクトをビルドして書き込んでみると…なぜか認識されない><
一昨年作ったボードではちゃんと動いた…ということは今回のボードは配線がどこかおかしい…
で、いろいろ弄っているうちに外部発振子が逝っちゃったようです。というわけで今日の開発終了。
関連記事

  • comment
  • secret
  • 管理者にだけ表示を許可する

trackbackURL:http://yuranos.blog11.fc2.com/tb.php/33-a6dec391
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。