??? 03/15/06 11:50 Read: times |
#112218 - Fibonacci/Galios Generator Responding to: ???'s previous message |
I take it that what you want to achieve is to have 16 LEDs that at least appear to flash at random. Is that right?
The algorithm you have seems to be some sort of 16-bit Fibonacci-type LFSR that you are only clocking once for each display cycle. In a Fibonacci-type generator, most of the bits simply shift one place with a new bit introduced based on some function of the states of the existing bits. If you clock such a generator only once, the resulting bit pattern will not look very random - you are only generating one pseudo-random bit. In general, an LFSR should be clocked a number of times equal to or greater than the number of new pseudo-random bits that you need - 16 times in this case. Also, you should take care that the number of clocks is not a factor of the run-length of the LFSR. The "randomness" of the LFSR is dependent upon the number of stages (bits) in the LFSR. More is better, but it depends upon what you are trying to achieve. The "apparent" pseudo-randomness of an LFSR is generally increased by having a large number of taps, up to half the number of stages in the LFSR. A Galois-type generator is simpler to implement in software and you can easily have as many taps as you like with little or no software overhead. In a Galois-type generator, all the bits are shifted and then if the bit that was shifted out is a '1' complement all the bits at the tap positions - a simple XOR with a mask value. If you want apparently flashing LEDs, I would recommend: * Use a Galois-type LFSR generator * You can probably make do with a 16-bit generator * Have at least half as many taps as stages (that is, 8 taps for a 16-bit generator. * You may be able to get away with just one clock per cycle, but more would be better and 16 clocks would be ideal because you are diplaying 16-bits at a time. If you want an off-the-shelf solution, use one of the 32-bit generators found at: http://www.programmersheaven.com/zone5/cat.../32219.htm Or just examine them for inspiration. e.g.: MOV R7,#16 ;Number of iterations. ; ?random_loop: ; ; CLR C ; MOV A,lfsr+0 ; RRC A ; MOV lfsr+0,A ; MOV A,lfsr+1 ; RRC A ; MOV lfsr+1,A ; MOV A,lfsr+2 ; RRC A ; MOV lfsr+2,A ; MOV A,lfsr+3 ; RRC A ; MOV lfsr+3,A ; ; JNC ?random_x ; ; XRL lfsr+0,#XMASK3 ; XRL lfsr+1,#XMASK2 ; XRL lfsr+2,#XMASK1 ; XRL lfsr+3,#XMASK0 ; ; ?random_x: ; ; DJNZ R7,?random_loop ; ; Where lfsr defines 4 bytes of immediate memory initialised to a non-zero value and the XMASKx constants define the taps, for example use the following values: XMASK3 0xCC XMASK2 0x4C XMASK1 0x4E XMASK0 0xCE Then all you have to do, is to copy 16-bits of lfsr to your ports - it does not matter which 16-bits you choose, so you could do: MOV P3,lfsr+0 MOV P1,lfsr+2 If performance is an issue, reduce the number of iterations, you may get acceptable results from a single iteration because the large number of taps makes the shifted relationship of the LEDs less obvious. Or, you could adapt the code to a simpler 24 or 16-bit generator - in which case you will have to work out your own values for the XMASKx constants. |