目次

乱数発生器

 アクティブフィルタの実験に、乱数が必要になったので
 擬似乱数をシフトレジスタを利用する、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変換すれば、実験に利用できます。




目次

inserted by FC2 system