--- /dev/null
+/*
+ * File: lfsr.c
+ *
+ * Linear Feedback Shift Register (random number generator)
+ */
+
+/**
+ * This is a small, fast and efficient software implementation of a 16-bit
+ * Linear Feedback Shift Register (LFSR). It uses the Galois method to perform
+ * the exclusive OR operations in parallel for improved performance over the
+ * standard, or Fibonacci, method. The algorithm also skips the exlusive or
+ * operations if it doesn't need to do them, though on this uC the branch may
+ * not generate a net performance increase over doing the exclusive or
+ * operations every time.
+ *
+ * After rng returns, RNGLO and RNGHI contain the updated 16-bit random number.
+ * RNGLO will contain a value $01-$FF, RNGHI will contain $00-$FF.
+ *
+ * @author R. Steve McKown <rsmckown@gmail.com>
+ */
+
+
+#include "lfsr.h"
+
+static unsigned lfsr_val = 0x1aa1;
+
+void lfsr_init(unsigned seed)
+{
+ /* The seed cannot be zero */
+ if (seed)
+ lfsr_val = seed;
+}
+
+unsigned lfsr_get()
+{
+ lfsr_val = (lfsr_val >> 1) ^ (-(lfsr_val & 1) & 0xd008);
+ return lfsr_val;
+}
--- /dev/null
+/*
+ * File: lfsr.h
+ *
+ * Linear Feedback Shift Register (random number generator)
+ */
+
+
+#ifndef _LFSR_H
+#define _LFSR_H
+
+/* Initialize the LFSR generator */
+void lfsr_init(unsigned seed);
+
+/* Read the next LFSR value */
+unsigned lfsr_get();
+
+#endif
#include <stdlib.h>
#include "picinit.h"
#include "unused.h"
+#include "lfsr.h"
#include "btn.h"
#include "rgb.h"
#include "tmr.h"
STD_FADE = 16, /* Fade time in 32.768 ms units */
STD_INCOLOR = 29491, /* Time in color when MODE_CYCLE, in 32.768 ms units */
PARTY_MIN = 8, /* Min party fade and incolor units */
- PARTY_RANGE = 8, /* Party fade/incolor range mask for rand() */
+ PARTY_RANGE = 8, /* Party fade/incolor range mask for lfsr_get() */
/* ... see start_fade() */
CFG_MODE_ADDR = 0, /* EEPROM address of mode variable */
CFG_COLOR_ADDR, /* EEPROM address of color variable */
/* Select the destination color and fade-to time depending upon mode. */
fade_steps = STD_FADE;
if (mode == MODE_PARTY) {
- color = rand() % COLOR_COUNT;
- fade_steps = PARTY_MIN + (rand() % PARTY_RANGE);
+ color = lfsr_get() % COLOR_COUNT;
+ fade_steps = PARTY_MIN + (lfsr_get() % PARTY_RANGE);
} else if (mode == MODE_CYCLE) {
if (++color == COLOR_COUNT)
color = 0;
if (mode == MODE_CYCLE)
tmr_start(TMR_INCOLOR, STD_INCOLOR);
else if (mode == MODE_PARTY)
- tmr_start(TMR_INCOLOR, PARTY_MIN + (rand() % PARTY_RANGE));
+ tmr_start(TMR_INCOLOR, PARTY_MIN + (lfsr_get() % PARTY_RANGE));
}
leds_set();
}
void user_boot()
{
dbgpin_high();
- srand((adc_random() << 8) + adc_random());
+ lfsr_init((adc_random() << 8) + adc_random());
cfg_read(mode, color);
rs_task();
}