目次
前
次
乱数発生器
アクティブフィルタの実験に、乱数が必要になったので
擬似乱数をシフトレジスタを利用する、LFSRを使っての
生成をしてみました。
LFSRは、Linear Feedback Shift Registerの略で
2のべき乗のレジスタの指定ビット間で、排他的
論理和を求め、レジスタのLSBとしていきます。
今回は、次の処理でQ30とQ27の排他的論理和を求めて
擬似乱数を生成しました。
32ビットのレジスタは、4バイトの配列を用意して対応。
typedef unsigned char UBYTE ;
UBYTE ranx[4] ;
初期化しておきます。
*(ranx+0) = 0xaf ;
*(ranx+1) = 0x50 ;
*(ranx+2) = 0x05 ;
*(ranx+3) = 0x34 ;
Q30とQ27の排他的論理和は、シフトとスワップ命令で求めます。
UBYTE q30 ;
UBYTE q27 ;
q30 = (*(ranx+0) << 1) & 0x80 ;
q27 = swap(*(ranx+0)) & 0x80 ;
排他的論理和を求めたなら、32ビットのレジスタ値を
シフトして、LSBに格納。
/* get value */
q30 = (*(ranx+0) << 1) & 0x80 ;
q27 = swap(*(ranx+0)) & 0x80 ;
/* exclusive OR */
tmp = q30 ^ q27 ;
/* shift */
*(rany+0) = (*(ranx+0) << 1) & 0xff ;
if ( tmp == 0x80 ) { *(rany+0) = *(rany+0) | ON ; }
*(rany+1) = (*(ranx+1) << 1) & 0xff ;
tmp = *(ranx+0) & 0x80 ;
if ( tmp == 0x80 ) { *(rany+1) = *(rany+1) | ON ; }
*(rany+2) = (*(ranx+2) << 1) & 0xff ;
tmp = *(ranx+1) & 0x80 ;
if ( tmp == 0x80 ) { *(rany+2) = *(rany+2) | ON ; }
*(rany+3) = (*(ranx+3) << 1) & 0xff ;
tmp = *(ranx+2) & 0x80 ;
if ( tmp == 0x80 ) { *(rany+3) = *(rany+3) | ON ; }
/* update */
*(ranx+0) = *(rany+0) ;
*(ranx+1) = *(rany+1) ;
*(ranx+2) = *(rany+2) ;
*(ranx+3) = *(rany+3) ;
配列を2種用意し、MSBの値をひとつ上に伝達。
まとめると、以下。
/* redefine data type */
typedef unsigned char UBYTE ;
#define OFF 0
#define ON OFF+1
volatile UBYTE ranx[4] ;
volatile UBYTE rany[4] ;
volatile UBYTE q30 ;
volatile UBYTE q27 ;
volatile UBYTE tmp ;
volatile UBYTE loop ;
/* function prototype */
void init_usr(void);
void main(void)
{
/* user initialize */
init_usr();
/* endless loop */
while ( ON ) {
/* get value */
q30 = (*(ranx+0) << 1) & 0x80 ;
q27 = swap(*(ranx+0)) & 0x80 ;
/* exclusive OR */
tmp = q30 ^ q27 ;
/* shift */
*(rany+0) = (*(ranx+0) << 1) & 0xff ;
if ( tmp == 0x80 ) { *(rany+0) = *(rany+0) | ON ; }
*(rany+1) = (*(ranx+1) << 1) & 0xff ;
tmp = *(ranx+0) & 0x80 ;
if ( tmp == 0x80 ) { *(rany+1) = *(rany+1) | ON ; }
*(rany+2) = (*(ranx+2) << 1) & 0xff ;
tmp = *(ranx+1) & 0x80 ;
if ( tmp == 0x80 ) { *(rany+2) = *(rany+2) | ON ; }
*(rany+3) = (*(ranx+3) << 1) & 0xff ;
tmp = *(ranx+2) & 0x80 ;
if ( tmp == 0x80 ) { *(rany+3) = *(rany+3) | ON ; }
/* update */
*(ranx+0) = *(rany+0) ;
*(ranx+1) = *(rany+1) ;
*(ranx+2) = *(rany+2) ;
*(ranx+3) = *(rany+3) ;
/* impress */
PORTA = *(ranx+0) & 7 ;
}
}
/* define function body */
void init_usr(void)
{
/* 8MHz */
OSCCON = (0x0c << 3) | 0x03 ;
/* disable A/D converter */
ADCON0.ADON = OFF ;
ADCON2 = 0 ;
/* disable D/A converter */
DACCON0.DACEN = OFF ;
/* disable compare module */
CM1CON0.C1ON = OFF ;
CM1CON0.C1OE = OFF ;
/* I/O state */
PORTA = 0x00 ;
/* I/O directions */
TRISA = 0xf8 ; /* bit0,1,2 as output , others as input */
/* pull-up */
WPUA = 0x30 ;
/* initialize */
*(ranx+0) = 0xaf ;
*(ranx+1) = 0x50 ;
*(ranx+2) = 0x05 ;
*(ranx+3) = 0x34 ;
*(rany+0) = *(ranx+0) ;
*(rany+1) = *(ranx+1) ;
*(rany+2) = *(ranx+2) ;
*(rany+3) = *(ranx+3) ;
PORTA = 0x00 ;
}
出力されてくる擬似乱数は、次の回路で
D/A変換すれば、実験に利用できます。
目次
前
次