' ========================================================================= ' File....... Faux_CandlesD4.BS1 ' Purpose.... Simulate eight candles with LEDs ' Author..... Dennis Griesser ' E-mail..... wolfstone@pobox.com ' 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