Continue to Site

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

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?

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

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.

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'
Filter
movf      seed,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

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.

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'

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.

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.

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:
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.