スポンサーサイト

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

変なこと思いついた

.26 2010 AVR-others comment(2) trackback(0)
AVRでLPM命令(プログラムメモリ読み出し)ってのがあります。こいつとSPI書き込み機能を使って自分自身の複製を作るAVRなんてものが作れそうだな~と漠然と考えてみました。

「自分自身のコードを接続先のデバイスにコピーしてそれからナイトライダーか何か適当なコードが走るプログラム」(①)ってのを用意したとします。

基板1にAVR1を配線し、基板2にAVR2を配線します。そんでAVR1の出力をAVR2のSPIピンに繋ぎます。

で、AVR1に①のコードを書き込むと…

あら不思議、AVR1, AVR2ともナイトライダーになってしまいました~みたいな^^

で、直列に繋ぐAVRの個数を増やしていくと
AVR1にコードが書き込まれる→AVR2にコードが書き込まれ、同時にAVR1がナイトライダーとして動作し始める→AVR3にコードが書き込まれ、同時にAVR2がナイトライダーになる…

で、終端のAVRの出力をAVR1に繋ぐと無限ループになるわけですね^^;

こんなもの絶対使い道ないよね
orz
スポンサーサイト

USBのCRCって…

.03 2010 AVR-others comment(0) trackback(0)
先日SUBのCRCの計算方法をを備忘録として書きましたが、どうもその計算方法では入力に1のビットがあったときに値が合わないようです。

普通に考えたらCRCの計算は入力値(CRC含めて)を生成多項式で割って剰余が0なら符号語、0じゃなければどっかのビットが狂ってると判断すればよさそうなものなのですが…

余りがx3 + x2なら符号語っていう時点で標準的なCRCとは違うみたいですね。

# 余りが0じゃないのが符号語ってことにすると巡回符号にならないんじゃないかと思ったり。どうなんだろ。

そんなことやってたらいつの間にか一日が終わってしまいました。明日はH/W構成法の試験みたいですねw…
せめてFPGAでDRAMを制御する方法でも考えてればよかったなと今更反省。

今日の備忘録。

AVRでは
「dec reg」と「subi reg, 1」は別物
はい。はまりました。orz
decはcarry flagが立たないんですね。したがって
dec		r24
brlo	retproc
は間違い。
subi	r24, 1
brlo	retproc
が正しい。
# ということは昨日の試験...やっちまったなw

I2C

.23 2009 AVR-others comment(0) trackback(0)
AVR(ATmega328p)にはTwi専用の回路が内蔵されています。
しかし!今回は専用回路を使わずにすべてソフトウェアで処理することにします。

専用回路を使う場合、I2Cのクロック線に出るクロックはsystem clk(今回は20M/8 = 2.5MHz)を16分したものが使われます。 従って1byte読み出しにかかる時間はおおよそ16 * 8 = 128clk分になります。
もちろんその間CPUは別の処理をしていてもいいわけですが、128clkごとの割り込み時にする内容はおおよそ次のようになります。
	push	r18
	push	r19
	push	r26	; Xreg(low)
	push	r27 ; Xreg(high)
	
	lds		r26, dest		; 下とあわせて出力先アドレス(VRAM上)をXregにコピー
	lds		r27, dest + 1
	lds		r18, cnt		; 下とあわせてこれまでにコピーしたバイト数の取得
	lds		r19, cnt + 1	; これによって読み出した値をVRAMのどこにコピーするかがわかる
	
	add		r26, r18		; 下とあわせてX += cnt;
	adc		r27, r19		; つまりX = dest + cnt;
	
	ld		r19, X			; コピー先の元のビットパターンと
	ld		r18, TWIreg		; TWIの受信レジスタの内容を
	and		r18, r19		; and演算して
	st		X, r18			; 元の場所にコピー
	
	pop		r27
	pop		r26
	pop		r19
	pop		r18
	reti

push, pop, lds, ld, stは2clk命令、retiは4clk命令、その他は1clk命令なので、合計37clk、割り込み時に割り込みベクタにジャンプする際、フェッチした命令を読み捨てるのでその分+1で38clkです。

よってEEPROMから1byte読む間にCPUが他のことをできるのは128 - 38 = 90clkです。

とここまで書いて気が付いたのですが、今回1画面描画する際にEEPROMからロードするビットパターンのサイズは
4 * 32 * 8 = 1kbyte
程度なのでもし専用回路で通信した場合、最低でも1024(byte) * 16(clk/bit) * 8(bit/byte) ~ 128kclk
clk = 2.5MHzなので128(clk) * 0.4(us/clk) ~ 50ms
かかります。
つまりどんなに効率よく受信と描画を並列化しても20fpsが限度になります。実際にはSRAMの内容をLCDに送信している間は描画はできないので確実にこれよりfpsは低くなります。
一方、すべてソフトウェアで処理した場合、次のようになります。
recv:
	; 0bit目
	out		PINC, 1 << SCK_PIN	; enable
	nop
	in		r20, PINC
	out		PINC, 1 << SCK_PIN	; disable
	ror		r20
	
	out		PINC, 1 << SCK_PIN	; enable
	ror		r21
	in		r20, PINC
	out		PINC, 1 << SCK_PIN	; disable
	ror		r20
	...
	
	; 7bit目
	out		PINC, 1 << SCK_PIN
	ror		r21
	in		r20, PINC
	ror		r20
	out		PINC, 1 << SCK_PIN
	
	ror		r21
	; 1byte受信完了
	
	; load and "and copy"
	ld		r20, X
	and		r21, r20
	st		X+, r21
	
	dec		r22
	brne	recv
ここで重要なのは、ror命令で第0bitの内容をキャリーに落として、つづくror命令でその値をr21につめているところです。
これを8回やるとあら不思議!PINCの0bit目から読んだ内容が順番にr21に入っていくんですね^^
この方法はAVRでUSBポートを制御している方のソースコードから学んだ方法です。早速活用させていただきました^^;

それからもう一つ注意しなくてはいけないのが、enableにした直後の値は信用できないという点です。
データシート(今回はAT24C256B)によるとクロックをLにしてからデータを吐いてくるまで最悪0.55us( > 0.4us)かかると書いてあります。
従って上記ソースではinがoutの直後に来ないように適当に調整しています。

さて、気になるのはこの方法を使ったときにかかる時間です。
1byte受信:5 * 8 + 4 + 3 = 47clkですが、実際には1byte受信ごとにNACKを返すので、+3clkくらいかかります。 すると1byte50clkで、1kbyte readなら50kclk ~ 20msです。

その他の描画処理等に30msくらいかかることを考えると1画面描画にかかる時間は大体50msです。
しかしこの20fpsを大きく下回る要因はないので大体この程度と考えられます。

結論:すべてソフトウェアで処理したほうがわずかに速い。

実際には、RAMを外付けにして、EEPROMアクセスはアプリケーション起動時に1回だけというのが理想なんでしょうけど今回はこれで我慢です^^;

ようやくこれでソフトですべて書くことが決まりました。これだけ決めるのに随分苦労してしまいましたが、次はタイミングチャートとにらめっこしながらそれっぽい波形を出すところに入ります。 こういう処理はこれまでにもかなりやってきたのでなんとかなりそうです。 それでは長くなりましたが今日はこの辺で♪
 HOME 
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。