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 になっていることが確認できます。