• Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Random Numbers - Assembly 16F

Status
Not open for further replies.

Suraj143

Active Member
I have 4 registers that needs to load random numbers.
Note: But there shouldn't be any adjuscent bits set. ex: eliminate numbers like this 11000000 00111000 00000001 10000000

The below numbers I manually entered by looking at a matrix effect.There isn't any adjascent bits set.

Does somebody have a small piece of code for this purpose?

Thanks

Code:
00000000 00000001 00000010 00000000
10001000 00010000 01000000 00000001
00000001 00000000 00000100 00100001
00000100 00001000 10010001 00000100
10000010 00010000 10100100 01000000
00010000 00010000 00100100 10001000
00000001 00000010 00000000 00000100
00001000 00100010 00101001 00010000
01000010 00100000 10101001 00010000
10000000 00001000 10000100 01000001
01001000 10001000 00000100 01010001
00000000 10010001 00100000 00010100
10000010 00010001 00100010 00100100
00100010 01000100 00000010 00100000
00100100 01000100 00001000 00001000
00000100 00000000 00100000 10000001
 

jpanhalt

Well-Known Member
Most Helpful Member
Check out this link: https://www.electro-tech-online.com/threads/how-to-create-an-lsfr-in-assembler.152554/#post-1311702 It is pseudorandom, of course. Check Pommie's most recent post (#15) for a good implementation.

I am a bit puzzled why you cannot allow any adjacent bits to be set. Doesn't that change the probability for each bit, i.e, if a bit is set, the next bit is determined?

I suspect developing a filter for adjacent bits within a byte would not be that hard. Then test for bits between bytes. The question is, why do it?
 

Suraj143

Active Member
Hi jpanhalt

Actually this is for a led matrix effect.I have a 16x32 (32 columns) matrix. The 32bit random number I feed into the 32 columns & make a shift to one row up.After a small delay I generate another 32 bit random number & feed into columns & make shift up. Likewise doing to all rows. Similar to the snow effect but moving from display bottom to top. (Actual name is galaxy effect, planets are moving randomly but never touching with each other :) .

I tested Mikes code & it generates nice numbers but it has adjacent bits set :(

Code:
RND     ;xor bits 1,5,6 & 31
        movlw    8
        movwf    count
loop    movlw    0        ;use bit zero for xor
        btfsc    Rand,1
        xorlw    1        ;flip bit 0
        btfsc    Rand,5
        xorlw    1
        btfsc    Rand,6
        xorlw    1
        btfsc    Rand+3,7    ;bit 31
        xorlw    1
        addlw    0xff        ;move bit 0 to carry bit.
        rlf      Rand,f        ;rotate through 32 bits
        rlf      Rand+1,f
        rlf      Rand+2,f
        rlf      Rand+3,f
        decfsz   count,f
        goto     loop
        return
 

Pommie

Well-Known Member
Most Helpful Member
Here you go, the same code but with an addition which makes sure no adjacent bits are 1.
Code:
RND    ;xor bits 1,5,6 & 31
    movlw   32        ;make sure all bits are changed
    movwf   count
loop    movlw    0        ;use bit zero for xor
    btfsc    Rand,1
    xorlw    1        ;flip bit 0
    btfsc    Rand,5
    xorlw    1
    btfsc    Rand,6
    xorlw    1
    btfsc    Rand+3,7    ;bit 31
    xorlw    1
    addlw    0xff        ;move bit 0 to carry bit.
    rlf    Rand,f        ;rotate through 32 bits
    rlf    Rand+1,f
    rlf    Rand+2,f
    rlf    Rand+3,f
    decfsz    count,f
    goto    loop
    ;now make sure no adjacent bits are 1
    ;copy to Acc
    movfw    Rand
    movwf    Acc
    movfw    Rand+1
    movwf    Acc+1
    movfw    Rand+2
    movwf    Acc+2
    movfw    Rand+3
    movwf    Acc+3
    movlw    Acc
    movwf    FSR
    movlw    0x80
    movwf    count
    clrf    previous
oneloop    btfss    previous,0  ;if previous was zero we don't care
    goto    cont
    movfw    count
    andwf    INDF,W
    btfsc    STATUS,Z
    goto    cont
    ;previous and current bit are both 1
    movlw    0xff
    xorwf    count,w
    andwf    INDF,f
cont    clrf    previous
    movfw    count
    andwf    INDF,w
    btfss    STATUS,Z
    incf    previous,f
    rrf    count,f
    btfss    STATUS,C
    goto    oneloop
    rrf    count,f
    incf    FSR,f
    movlw    Acc+4
    xorwf    FSR,w
    btfss    STATUS,Z
    goto    oneloop
    return
edit, defines need to be,
Code:
    cblock 0x20
 Rand:4
 Acc:4
 count:1
 temp:1
 previous:1
    endc
The result is in Acc

Mike.
 

jpanhalt

Well-Known Member
Most Helpful Member
Pommie
You beat me to it. I took a slightly different approach and filtered a previously calculated random number for adjacent set bits. I figured the TS could do something similar to filter the bytes.

Here's my byte filter:
Code:
;Enter with random number in "seed".  Reject seeds with adjacent 
;set bits.  "Loop" is the routine to get another random number.

     movlw     0xC0           ;b'1100 0000'
     movwf     mask
Filter
     movf      seed,w
     andwf     mask,w
     xorwf     mask,w
     btfsc     STATUS,2
     bra       Loop           ;adjacent bits set, get another seed
     lsrf      mask,f         ;or use clrc + rrf
     btfss     STATUS,0       ;set when all pairs have been tested
     bra       Filter
     incf      counter,f      ;added to count "successes", not necessary
     bra       Loop           ;"seed" = filtered random number
     bra       Start          ;max period is in count & sequence repeats
 

Suraj143

Active Member
Here you go, the same code but with an addition which makes sure no adjacent bits are 1.
Code:
RND    ;xor bits 1,5,6 & 31
    movlw   32        ;make sure all bits are changed
    movwf   count
loop    movlw    0        ;use bit zero for xor
    btfsc    Rand,1
    xorlw    1        ;flip bit 0
    btfsc    Rand,5
    xorlw    1
    btfsc    Rand,6
    xorlw    1
    btfsc    Rand+3,7    ;bit 31
    xorlw    1
    addlw    0xff        ;move bit 0 to carry bit.
    rlf    Rand,f        ;rotate through 32 bits
    rlf    Rand+1,f
    rlf    Rand+2,f
    rlf    Rand+3,f
    decfsz    count,f
    goto    loop
    ;now make sure no adjacent bits are 1
    ;copy to Acc
    movfw    Rand
    movwf    Acc
    movfw    Rand+1
    movwf    Acc+1
    movfw    Rand+2
    movwf    Acc+2
    movfw    Rand+3
    movwf    Acc+3
    movlw    Acc
    movwf    FSR
    movlw    0x80
    movwf    count
    clrf    previous
oneloop    btfss    previous,0  ;if previous was zero we don't care
    goto    cont
    movfw    count
    andwf    INDF,W
    btfsc    STATUS,Z
    goto    cont
    ;previous and current bit are both 1
    movlw    0xff
    xorwf    count,w
    andwf    INDF,f
cont    clrf    previous
    movfw    count
    andwf    INDF,w
    btfss    STATUS,Z
    incf    previous,f
    rrf    count,f
    btfss    STATUS,C
    goto    oneloop
    rrf    count,f
    incf    FSR,f
    movlw    Acc+4
    xorwf    FSR,w
    btfss    STATUS,Z
    goto    oneloop
    return
edit, defines need to be,
Code:
    cblock 0x20
 Rand:4
 Acc:4
 count:1
 temp:1
 previous:1
    endc
The result is in Acc

Mike.
Wonderful piece of code.That will fulfill my requirement.Thank you very much for your effort.
 

Suraj143

Active Member
Hi jpanhalt

For a single byte your code is ok. I'm not sure are you checking adjacent bits between bytes...!!
Ex: b'0000001' b'10000000'
 

Pommie

Well-Known Member
Most Helpful Member
I've just realized I did that wrong but the result works out ok if you use it as big endian. So, Acc is the most significant byte and Acc+3 is the least.

I though it best not to mess with the random number generator but to just copy the 32 bit number and eliminate and adjacent ones.

Edit, John, your method would give more bits set which may be desirable.

Mike.
 

Pommie

Well-Known Member
Most Helpful Member
Suraj,

Johns approach will give numbers containing more ones which will result in a brighter display. If this is desirable then change the middle of the code to,
Code:
oneloop    btfss    previous,0  ;if previous was zero we don't care
    goto    cont
    movfw    count
    andwf    INDF,W
    btfsc    STATUS,Z
    goto    cont
    ;previous and current bit are both 1
    goto    RND        ;get another random number
cont    clrf    previous
Mike.
 

Suraj143

Active Member
Hi Mike, I got what you mean. Changed as suggested. Acc is the LSB & Acc+3 is the MSB.

Code:
;now make sure no adjacent bits are 1
;copy to Acc
            movfw        Rand
            movwf        Acc
            movfw        Rand+1
            movwf        Acc+1
            movfw        Rand+2
            movwf        Acc+2
            movfw        Rand+3
            movwf        Acc+3
            movlw        Acc
            movwf        FSR
            movlw        0x01
            movwf        count
            clrf        previous
oneloop        btfss        previous,0      ;if previous was zero we don't care
            goto        cont
            movfw        count
            andwf        INDF,W
            btfsc        STATUS,Z
            goto        cont
;previous and current bit are both 1
            movlw        0xff
            xorwf        count,w
            andwf        INDF,f
cont        clrf        previous
            movfw        count
            andwf        INDF,w
            btfss        STATUS,Z
            incf        previous,f
            rlf            count,f
            btfss        STATUS,C
            goto        oneloop
            rlf            count,f
            incf        FSR,f
            movlw        Acc+4
            xorwf        FSR,w
            btfss        STATUS,Z
            goto        oneloop
            return
Thanks
 
Last edited:

jpanhalt

Well-Known Member
Most Helpful Member
Hi jpanhalt

For a single byte your code is ok. I'm not sure are you checking adjacency bits between bytes...!!
Ex: b'0000001' b'10000000'
I didn't want you to miss all of the fun. There are probably a lot of ways to prevent that adjacent problem. Here are some ideas:
Code:
 1)  Test bit<0> of byte 1.   If clear, do nothing.  Just take the next byte.
 2)  If bit<0> of byte 1 is set, test bit<7> of the next byte. If clear, no problem.  If set, avoid/fix the problem:
      (a) Change bit<7> of byte 2 to 0
      (b) Change bit <0> of byte 1 to 0
      (c) Rotate a zero into bit<7> of byte 2 (set carry and right rotate)
      (d) Continue the random loop and filter until an acceptable byte with bit<7> clear is found
All of those conditions can be detected with simple btfss/btfsc instructions. Of that set of solutions, IMHO: (b) is the worst; (a) is not too bad as it doesn't change the odd/even ratio; (c) is almost as easy as (b) and may be better; and (d) is perhaps the best but is biased against largest values and will take much more time.

I would try (c) and see how it looks. As for your "random bytes" do you need to include "0?" Not all schemes will give you that.

Sorry for the late reply due to time zones.

John
 
Last edited:
Status
Not open for further replies.

Latest threads

EE World Online Articles

Loading
Top