' =========================================================================
' File....... Faux_CandlesD4.BS1
' Purpose.... Simulate eight candles with LEDs
' Author..... Dennis Griesser
' E-mail..... [EMAIL="wolfstone@pobox.com"]wolfstone@pobox.com[/EMAIL]
' Started.... 5 July 2005
' Updated.... 9 July 2005
' {$STAMP BS1}
' {$PBASIC 1.0}
' =========================================================================
' -----[ Program Description ]---------------------------------------------
' Simulates candle flicker by passing random values to the "candle" output
' pins (P0 - P7).
'
' Features:
' o Each LED has 75% chance of being lit.
' o A single call to RANDOM drives all LEDs, using 2 bits of entropy each.
' o Each set of 2 bits has a different distance between them to reduce visible
' "ripple".
' o The loop is unrolled for greater speed.
'
' We try to call RANDOM as infrequently as possible to keep things fast.
' We consume eight probabilities per iteration, but since we want the candles
' "mostly on", we can pick a percentage, like 75% and hard code that as using
' 2 bits of entropy. Thus a single call to RANDOM returns enough entropy to
' light all 8 candles, each one 75% of the time.
'
' RANDOM is documented as generating a sequence of 65535 pseudo-random numbers.
'
' Parallax does _not_ document the following:
' o RANDOM uses a linear feedback feedback shift register that is advanced
' once per call.
' o So we're not _really_ getting 16 bits of entropy. We get one fresh bit,
' and the other 15 bits are old, but shifted over one position to the left.
' o This may result in "ripple" of the lights.
'
' Note the way that the two bits are harvested per probability. Each candle
' uses two bits spread a different distance apart. This helps reduce ripple
' that would otherwise appear due to the use of a feedback shift register
' as the PRN generator.
' -----[ I/O Definitions ]-------------------------------------------------
' -----[ Constants ]-------------------------------------------------------
' -----[ Variables ]-------------------------------------------------------
SYMBOL RndNum = W0 ' 16-bit random number (and seed for next one)
SYMBOL RndProb = W1 ' 2/16-bit value of probability for this candle
SYMBOL LitBits = B4 ' composite bitmask of lit bits
' -----[ Initialization ]--------------------------------------------------
Reset:
PINS = %00000000 ' all candles off
DIRS = %11111111 ' make LED pins outputs
' -----[ Program Code ]----------------------------------------------------
Main:
' Top of the main loop.
RANDOM RndNum ' tumble random generator - 1 bit of entropy, 15 bits shifted
LitBits = %00000000 ' no lit bits so far
RndProb = RndNum & %1000000000000001 ' pick 2 bits that contain probability for this candle
IF RndProb = 0 THEN AfterBit7 ' 2/2 bits off = 25% of time -> leave candle off
LitBits = LitBits | %10000000 ' turn on this candle
AfterBit7:
RndProb = RndNum & %0100000000000010 ' pick 2 bits that contain probability for this candle
IF RndProb = 0 THEN AfterBit6 ' 2/2 bits off = 25% of time -> leave candle off
LitBits = LitBits | %01000000 ' turn on this candle
AfterBit6:
RndProb = RndNum & %0010000000000100 ' pick 2 bits that contain probability for this candle
IF RndProb = 0 THEN AfterBit5 ' 2/2 bits off = 25% of time -> leave candle off
LitBits = LitBits | %00100000 ' turn on this candle
AfterBit5:
RndProb = RndNum & %0001000000001000 ' pick 2 bits that contain probability for this candle
IF RndProb = 0 THEN AfterBit4 ' 2/2 bits off = 25% of time -> leave candle off
LitBits = LitBits | %00010000 ' turn on this candle
AfterBit4:
RndProb = RndNum & %0000100000010000 ' pick 2 bits that contain probability for this candle
IF RndProb = 0 THEN AfterBit3 ' 2/2 bits off = 25% of time -> leave candle off
LitBits = LitBits | %00001000 ' turn on this candle
AfterBit3:
RndProb = RndNum & %0000010000100000 ' pick 2 bits that contain probability for this candle
IF RndProb = 0 THEN AfterBit2 ' 2/2 bits off = 25% of time -> leave candle off
LitBits = LitBits | %00000100 ' turn on this candle
AfterBit2:
RndProb = RndNum & %0000001001000000 ' pick 2 bits that contain probability for this candle
IF RndProb = 0 THEN AfterBit1 ' 2/2 bits off = 25% of time -> leave candle off
LitBits = LitBits | %00000010 ' turn on this candle
AfterBit1:
RndProb = RndNum & %0000000110000000 ' pick 2 bits that contain probability for this candle
IF RndProb = 0 THEN AfterBit0 ' 2/2 bits off = 25% of time -> leave candle off
LitBits = LitBits | %00000001 ' turn on this candle
AfterBit0:
' We are done assembling the bitmask of bits to light up.
PINS = LitBits ' update LEDs
' If the flicker is too fast for you, you can put some delay here by un-commenting the PAUSE.
' Fiddle with different values for that "45" until you get something that you like.
' Larger values make it run slower. Smaller values make it go faster.
' PAUSE 45 ' delay between updates
' Update the candles again.
GOTO Main
END