ATtiny10 用プログラム (1)
この「プログラム」は、ターゲット・マイコン上で走るプログラム自体のことで、それをフラッシュ・メモリに書き込む「プログラム」作業のことではありません。
以前に ATtiny13 用に m-系列ノイズを発生させるアセンブラ・プログラムを作成しましたが、それを一部修正して ATtiny10 用としました。
AVR Studio 4.19 でアセンブルして動作を確認したソースを下に示します。
; ; m_noise10: white noise generator using LFSR m-sequence ; (length = 2^31 - 1 = 2147483647) ; for Atmel AVR ATtiny10 ; ; chip rate = 666.7 kHz @ CPU_clock = 8 MHz ; period = 3221 sec @ CPU_clodk = 8 MHz ; ; 2011/12/09 modified for ATtiny10 ; 2010/08/16 created by pcm1723 ; ; .include "tn10def.inc" .nolist .include "tn10def.inc" .list ; registers for LFSR .def SR3 = r25 .def SR2 = r24 .def SR1 = r23 .def SR0 = r22 ; registers for g(x) tap pattern .def GX3 = r21 .def GX2 = r20 .def GX1 = r19 .def GX0 = r18 ; genarator polynomial g(x) ; ; g(x) = x^31 + x^29 + ... x^1 + 1 ; g(x) = [31, 29, 27, 25, 23, 21, 19, 17, ; 15, 13, 11, 9, 7, 6, 4, 1, 0] .equ GXTAP = 0x55555569 ; g(x) = x^31 + x^13 + 1 ; .equ GXTAP = 0x40001000 ; g(x) = x^31 + x^28 + 1 ; .equ GXTAP = 0x48000000 ; LFSR inital value .equ SRINIT = 0x00000001 ; ; select output port ; .set outport = PORTB0 ; PB0 (pin 1) ; .set outport = PORTB1 ; PB1 (pin 3) ; .set outport = PORTB2 ; PB2 (pin 4) ; .set outport = PORTB3 ; PB3 (pin 6) .cseg rjmp reset_entry reset_entry: ; ; setup clock prescaler to 1/1 (8 MHz) ; ldi SR0,0xD8 ; protect signature out CCP,SR0 ; CCP <-- 0xD8 ldi SR0,0x00 ; 0x00 = 1/1 out CLKPSR,SR0 ; set CLocK PreScaleR ; ; setup GPIO ; ldi SR0,0x0F out PORTB,SR0 ; enable pull up sbi DDRB,outport ; PBx = OUTPUT ; ; load generator polynomial ; ldi GX3,byte4(GXTAP) ldi GX2,byte3(GXTAP) ldi GX1,byte2(GXTAP) ldi GX0,low(GXTAP) ; ; LFSR initial value ; ldi SR3,byte3(SRINIT) ldi SR2,byte2(SRINIT) ldi SR1,byte1(SRINIT) ldi SR0,low(SRINIT) ; out_zero: ; ; output '0' to port ; (clk) cbi PORTB,outport ; #1, PBx = 0 nop ; #1, timing adjust nop ; #1, timing adjust nop ; #1, timing adjust nop ; #1, timing adjust nop ; #1, timing adjust ; ; 12 CPU clocks per loop ; loop_entry: ; ; shift right 1 bit ; (clk) lsr SR3 ; #1, ror SR2 ; #1, ror SR1 ; #1, ror SR0 ; #1, brcc out_zero ; #1(2), branch if C=0 out_one: ; ; output '1' to port and apply g(x) ; eor SR3,GX3 ; #1, sbi PORTB,outport ; #1, PBx = 1 eor SR2,GX2 ; #1, eor SR1,GX1 ; #1, eor SR0,GX0 ; #1, rjmp loop_entry ; #2, loop again ;
アセンブル後の HEX ファイルは下のようになります。
:020000020000FC :1000000000C068ED6CBF60E066BF6FE062B9089A3F :1000100055E545E535E529E690E080E071E061E0F1 :1000200010980000000000000000000096958795E1 :1000300077956795A8F79527109A842773276227E5 :02004000F5CFFA :00000001FF
ブログラム・サイズは 66 バイトで、RAM は 1 バイトも使っていません。
ATtiny10 では、クロックのプリスケール値を決めるフューズ・ビットはなく、プログラムの実行時に「自前」でクロック・プリスケール・レジスタの設定をしなければならないので、その部分の追加と、ノイズ出力のビットを選択可能にした部分だけが元の ATtiny13 用のプログラムから変更した部分です。
もともと ATtiny13 用のプログラムでは、R16 以上のレジスタしか使っていなかったので、レジスタ数が半減した AVR8L 命令セットの ATtiny10 でも、そのための修正は必要ありませんでした。
それに加え、ATtiny10 の AVR8L 命令セットでは、sbi/cbi 命令は 1 クロックで実行されるようになったので、ループの所要クロック数が 13 から 12 に減りました。
また、ATtiny10 の内部クロックはスペック上は 8 MHz ±10% で、手許の一個を実測すると約 7.77 MHz (-2.9%)でした。
出力は「チップ・レート」が約 600 kHz の 0/1 のディジタル信号であり、そのナイキスト周波数も約 300 kHz となり、実用的にはオーディオ帯域の LPF を掛けて使うことになります。
LPF 回路の例を下に示します。
これは、後日の記事で示す、サンプリング周波数 15.625 kHz の PWM に使用している約 6 kHz カットオフ周波数の 3 次バタワース LPF で、OP アンプ 1 個を使った 3 次 Sallen-Key 回路のアクティブ・フィルタです。
5 V 電源でも出力は 3 V 程度までしか振れない LM358/LM324/LM2902/LM2904 でも使用できるように、入力部で信号の減衰および DC オフセットを与えて、出力は約 1.9 V を中心に振幅 0.5 V (1 Vp-p) となるように設定してあります。
このフィルタを通して ATtiny10 出力 (m-系列ノイズ) を WaveSpectra で観測した結果を下に示します。
周波数特性は 300 回の FFT 結果の平均の値を示しています。
m-系列ノイズ出力は、理論上ナイキスト周波数の約 300 kHz まで平坦なスペクトルのはずですから、これは単につないだフィルタの周波数特性を見ているだけになります。
数 kHz 以上の阻止域の減衰スロープは 3 次 LPF の -18 dB/oct になっていることが確認できます。