Full Version : Random Numbers for PIC16F876 (PIC ASM)
avr >>PIC 8051 ZILOG ARM TI H8 ETC >>Random Numbers for PIC16F876 (PIC ASM)


Admin3- 04-18-2006
Random number on at 16F876.

Used some sort of bit smashing algorithm, but also used timer 0 as input to randomize the output even more.

This particular routine is more toward the higher quality but slower speed end of things.

CODE


;   Random number generator.
;
        include "hal.inc"

        extern  lookofs    ;lookup at REG2,REG1 with offset REG3, REG3 incremented
;
;***********************************************************************
;
;   Configuration constants.
;
lbank    equ     0          ;register bank for the local state of this module
size1    equ     17         ;number of entries in RAND1 table
size2    equ     19         ;number of entries in RAND2 table
;
;   Derived constants.
;
lbankadr equ     bankadr(lbank);address within local state register bank
;
;***********************************************************************
;
;   Global state.  All this state is assumed to be in the GBANK register
;   bank by other modules.
;
.bank#v(gbank) udata

;
;***********************************************************************
;
;   Local state.
;
 if lbank != gbank
.bank#v(lbank) udata
   endif

ind1     res     1          ;0 to SIZE1-1 index into RAND1 table
ind2     res     1          ;0 to SIZE2-1 index into RAND2 table
hash     res     1          ;hash value for making random number

.rand    code
;
;***********************************************************************
;
;   Subroutine RAND_INIT
;
;   Initialize the hardware and software state managed by this module.
;
        glbsub  rand_init, noregs
;
;   Set up timer 0 to free run from the instruction clock.
;
        dbankif option_reg
        movf    option_reg, w;get current OPTION register value
        andlw   b'11000000';mask off all the timer 0 control bits
        iorlw   b'00001000'
               ; 00------  not timer 0 control bits, leave alone by ORing with 0
               ; --0-----  timer 0 source is instruction clock
               ; ---X----  external timer 0 source edge select
               ; ----1---  assign prescaler to watchdog timer, not timer 0
               ; -----XXX  prescaler setting
        movwf   option_reg
;
;   Initialize the local state managed by this module.
;
        dbankif tmr0
        movf    tmr0, w    ;get current timer 0 value into W

        dbtvoRf lbankadr
        movwf   hash       ;init hash mask
        clrf    ind1       ;init RAND1 table index
        clrf    ind2       ;init RAND2 table index

        leaverest
;
;***********************************************************************
;
;   Subroutine RAND
;
;   Return a random byte value in REG0.
;
        glbsub  rand, regf1 | regf2 | regf3
;
;   Update HASH with the random number from table 1.
;
        movlw   low rand1  ;pass table start address
        movwf   reg1
        movlw   high rand1
        movwf   reg2
        dbankif lbankadr
        movf    ind1, w    ;pass offset to look up entry at
        movwf   reg3
        gcallr  lookofs, reg0;get random number from table 1 into REG0
        movf    reg0, w    ;get the random value into W
        dbankif lbankadr
        xorwf   hash       ;update HASH with this random number
;
;   Update HASH with the random number from table 2.
;
        movlw   low rand2  ;pass table start address
        movwf   reg1
        movlw   high rand2
        movwf   reg2
        dbankif lbankadr
        movf    ind2, w    ;pass offset to look up entry at
        movwf   reg3
        gcallr  lookofs, reg0;get random number from table 1 into REG0
        movf    reg0, w    ;get the random value into W
        dbankif lbankadr
        addwf   hash       ;update HASH with this random number
;
;   Update HASH with the current timer 0 value.
;
        dbankif tmr0
        movf    tmr0, w    ;get timer 0 value
        addwf   hash       ;update HASH with the current timer 0 value
;
;   Update the random number table indicies.
;
        dbankif lbankadr

        incf    ind1       ;increment table 1 index
        movf    ind1, w    ;get the new index value
        sublw   size1-1    ;compare to last valid index
        skip_wle           ;new index is still within table ?
        clrf    ind1       ;no, wrap back to start of table

        incf    ind2       ;increment table 2 index
        movf    ind2, w    ;get the new index value
        sublw   size2-1    ;compare to last valid index
        skip_wle           ;new index is still within table ?
        clrf    ind2       ;no, wrap back to start of table
;
;   Pass back the final value.
;
        dbankif lbankadr
        movf    hash, w    ;get the updated hash value
        movwf   reg0       ;pass it back as the random number

        leaverest
;
;***********************************************************************
;
;   Tables RAND1 and RAND2
;
;   These tables contain random byte values.  The length of each of the
;   tables is SIZE1 and SIZE2, respectively.
;
rand1
        retlw   h'BD'
        retlw   h'66'
        retlw   h'C6'
        retlw   h'9A'
        retlw   h'79'
        retlw   h'E1'
        retlw   h'50'
        retlw   h'1A'
        retlw   h'59'
        retlw   h'A1'
        retlw   h'10'
        retlw   h'14'
        retlw   h'B0'
        retlw   h'FE'
        retlw   h'B1'
        retlw   h'C7'
        retlw   h'53'
rand2
        retlw   h'6D'
        retlw   h'82'
        retlw   h'2B'
        retlw   h'16'
        retlw   h'CE'
        retlw   h'90'
        retlw   h'9C'
        retlw   h'8A'
        retlw   h'A1'
        retlw   h'57'
        retlw   h'93'
        retlw   h'AF'
        retlw   h'26'
        retlw   h'C5'
        retlw   h'32'
        retlw   h'F0'
        retlw   h'45'
        retlw   h'97'
        retlw   h'99'
;
;***********************************************************************
;
;   Subroutine RAND_MAX
;
;   Returns a random number in REG0 from 0 thru REG1.  For example, if REG1
;   is 3, then REG0 will randomly be set to 0, 1, 2, or 3.
;
        glbsub  rand_max, regf2
;
;   Make the smallest 2**N-1 mask that will still mask in the max valid
;   random number.  This mask is used to mask off high bits of the random
;   value to reduce the number of rejections.  The mask will be left in
;   REG2.
;
        clrf    reg2       ;init to smallest possible mask (all bits off)
        movf    reg1, w    ;get max valid random value
        movwf   reg0       ;save corruptable copy of max value
rmax_loop_mask              ;back here each larger mask
        movf    reg0       ;set Z if all bits shifted out of max value
        skip_nz            ;all bits not yet shifted out, keep looping
        goto    rmax_mask  ;minimum mask all set in REG2

        bcf     status, c  ;shift max value one more bit right
        rrf     reg0
        bsf     status, c  ;shift mask one more bit left
        rlf     reg2
        goto    rmax_loop_mask;back to test REG0 value again
rmax_mask                   ;mask value in REG2 all set
;
;   Get a random number that is no larger than REG1.  REG2 is the smallest
;   possible mask that masks in the entire range from 0 thru REG1.  This mask
;   will be used to eliminate the upper bits of candidate random numbers.
;   This guarantees that at least half the masked random number will be
;   within the desired range.  Random numbers outside this range are discarded,
;   and another random number is tried until one is found within the desired
;   range.
;
rmax_loop                   ;back here until find valid random number
        mcall   rand       ;get random byte value into REG0
        movf    reg2, w    ;get mask for max valid value
        andwf   reg0       ;mask off bits that must be 0 anyway
        movf    reg0, w    ;get the masked random number
        subwf   reg1, w    ;compare to the max valid value
        skip_wle           ;this random value is within range ?
        goto    rmax_loop  ;this random value is out of range, try another

        leaverest

        end



Forumer™ is Voted #1 Free Forum Hosting provider
Build your own community today with the largest message board hosting company.