PRNG RRCF LFSR_B_H, F ; Shift the 16+1 bit register
RRCF LFSR_B_L, F ; (Shifts through the CARRY bit)
BTFSS STATUS, 0 ; Test the output bit.
RETURN
MOVLW b'10010000' ; XOR bits 17 and 14 if bit 0 is set
XORWF LFSR_B_H, F ; store in LFSR high byte.
RETURN
First, i would use the Fibonnaci example not the Galois one, same maximal iterations but more logical to implement even though it is a bit longer in code.
1. your RRF leaves an unknown bit in bit15, it would be better to be zero at that point. You could CLRC before the 2 RRCFs.
PRNG_int movlw 0xAB ; Load arbitrary numbers to LFSR
movwf LFSR_B_H ;
movlw 0xCD ;
movwf LFSR_B_L ;
CLRF WREG ; Clear relevant registers
BCF STATUS, 0 ;
PRNG
SHIFT_H RRCF LFSR_B_H, F ; Shift the 16+1 bit register
SHIFT_L RRCF LFSR_B_L, F ; (Shifts through the CARRY bit)
BTFSS STATUS, 0 ; Test the output bit (bit 0).
RETURN
MOVLW b'10010000' ; XOR bits 17 and 14 if bit 0 is set
XORWF LFSR_B_H, F ; store in LFSR high byte.
RETURN
2. if the output bit is 1 you need to XOR bits 10, 12, 13 and then insert (not xor) the output bit into 15.
PRNG
BCF STATUS, 0; clear carry before shifting (will make a 0 in bit15)
RRCF LFSR_B_H, F; Shift the 16+1 bit register
RRCF LFSR_B_L, F; (Shifts through the CARRY bit)
BTFSS STATUS, 0; Test the output bit (bit 0, is now in carry).
RETURN
MOVLW b'00110100'; mask to XOR bits 13, 12 and 10 (re Wiki diagram) if bit 0 is set
XORWF LFSR_B_H, F; complete the XOR operation on the LFSR high byte.
BSF LFSR_B_H, 7; insert a 1 into bit15 of the LFSR
RETURN
Why are you only XORing two bits when the diagram shows 3 bits are XORed and one bit is stored?
You are still not storing the new bit into bit15, you are just doing XORs?
:code box:
PRNG
BCF STATUS, 0; clear carry before shifting, will make a 0 in top bit(s)
RRCF LFSR_B_U, F; Shift the 17 bit register (requires 3 bytes; U,H,L)
RRCF LFSR_B_H, F;
RRCF LFSR_B_L, F;
BTFSS STATUS, 0; Test the output bit (bit 0, is now in carry).
RETURN
MOVLW b'00100000'; mask to XOR bit 13 if bit 0 is set
XORWF LFSR_B_H, F; complete the XOR operation on the correct byte.
BSF LFSR_B_U, 0; insert a 1 into bit16 of the LFSR
RETURN
I really dislike your idea of keeping vital data in the carry bit, it's only an extra instruction or two to have the data always safe in the main buffer.
Code:
Also you probably saw I prefer to use the correct software bit names 0-16 for a 17 bit shift register. For some reason Wiki use the numbers 1-17 probably because they are more focused on a math polynomial discussion rather than a software implementation.
For large shift registers you can use better register byte names like;
LFSR_00
LFSR_01
I'm curious to learn more about why you want to do LFSRs with lots of different sizes, is this just a thought experiment or for some actual real world use?
... One question, at a glance it looks like I may have to use one extra byte per LFSR? Is there no relatively simple way to use one byte to store the bits for multiple LFSRs? That would certainly save some memory if I make many LFSRs.
...
Yes, I saw and was thinking about that. I don't agree with the wiki's way of doing it either. I was only using that designation as it is exactly what the Wiki was saying and I wasn't sure I should deviate from that. It would be nice to set a better common ground though. So from now on (if the thread goes on much longer) we can just use the microchip designations. It makes more sense to me anyway.
...
... As you know, more bits means longer periods, however single LFSRs have predictable patterns, and are thus not really random. The same number of bits, as smaller LFSRs has potential for more complex patterns with the same amount of memory. As for why LFSRs. I believe it was you that said "I think every one should build their own [pseudo] random number generator". It seemed like good advice. And LFSRs seem like good starts. LFSRs make good building blocks for quite a few things actually.
...
Ideas
First I'll tell you, I came up with something interesting while doing this project. I was thinking about how to save more memory, And I started to wonder if we couldn't simply overlap all the registers with each other? That is, an nBit LFSR can be broken down into smaller LFSRs, then operations are done on each, leaving the data there and allowing it to bleed over into and alter the other "virtual LFSRs". This should save memory while creating even more chaos in that memory. Even if the operations on one virtual LFSR accidentally create all 0/1 for any other virtual LFSR, there should be no problems with lock up because future operations will shift in an opposing bit, allowing that virtual LFSR to function again. I think the chaos should be really high with this configuration.
I don't think you would save much RAM trying to manually handle all the top bits and at first glance it looks like a coding nightmare.
[Your idea is] interesting and would be a cool experiment.
Generally modifying the data within a LFSR is considered bad form as the LFSR is a single maximal length repeating pattern, so to change any bit when it is working just skips it to a different part of the pattern, which in most cases gives a shortened repeat.
If you want to try that I would suggest XORing a bit from LFSR A with LFSR B, that gives better entropy than just eliminating and replacing a bit. Also it might be good to only do that process infrequently, not do it every bit. That gives time to build more entropy in the individual LFSRs before they "mash" a bit and affect each other, giving longer and more complex patterns in their interaction and disallowing short pattern locks. Building on that, if you can "randomly" select a time to mash the bits that is generally better than doing it at a fixed time, provided there is little predictability to when you randomly do the event.
And obviously, the old technique of generating the output bit by XORing a number of non-polynomial bits from different LFSRs will give a much better output than just outputting the last bit from the last LFSR in the line.
It's fun seeing someone making RNGs in software and hopefully someone else might speak up who has experience. My understanding is pretty rudimentary and I'm mainly a brute force kind of guy, ie big buffers and lots of data mashing based on unrelated things. LFSRs are more mathematical in nature and (to me) are best used as a single part of a RNG process, not form the entire process.
...
*** OFF TOPIC ***
By the way, I happened to be checking out Shift1 the other day and I realized that you can most likely get a significant speed up by putting a diode in parallel with each resistor. The idea is to shorten the wait time before sending the next command (charge time for CS and CT). You may also have to add a third resistor to lower charging current at least a little, but that is easy and probably won't be a problem anyway. It's a fairly straightforward mod and should give a significant performance boost. Over all it should bring the 15μs, 30μs, and 300μs charging times all down to 1~5μs instead.
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?