Skip to content

Instantly share code, notes, and snippets.

@wandrson
Last active February 2, 2024 05:37
Show Gist options
  • Select an option

  • Save wandrson/10000147 to your computer and use it in GitHub Desktop.

Select an option

Save wandrson/10000147 to your computer and use it in GitHub Desktop.

Revisions

  1. wandrson revised this gist Apr 11, 2014. 1 changed file with 52 additions and 40 deletions.
    92 changes: 52 additions & 40 deletions TrueRandomSeed.ino
    Original file line number Diff line number Diff line change
    @@ -1,58 +1,70 @@
    // TrueRandomSeed.ino
    // This example sketch shows how to provide a truly random seed value to the built in library pseudo random number generator. This ensures that your
    // sketch will be using a different sequence of random numbers every time it runs. Unlike the usually suggested randomSeed(analogRead(0)) this method
    // will provide a much more uniform and varied seed value. For more information about the basic technique used here to produce a random number or if
    // you need more than one such number you can find a library, Entropy from the following web site along with documentation of how the library has been
    // tested to provide TRUE random numbers on a variety of AVR chips and arduino environments.
    // http://code.google.com/p/avr-hardware-random-number-generation/wiki/WikiAVRentropy
    // This example sketch shows how to provide a truly random seed value to the built in
    // library pseudo random number generator. This ensures that your sketch will be
    // using a different sequence of random numbers every time it runs. Unlike the
    // usually suggested randomSeed(analogRead(0)) this method will provide a much more
    // uniform and varied seed value. For more information about the basic technique used
    // here to produce a random number or if you need more than one such number you can
    // find a library, Entropy from the following web site along with documentation of how
    // the library has been tested to provide TRUE random numbers on a variety of AVR
    // chips and arduino environments.
    //
    // Copyright 2014 by Walter Anderson, wandrson01 at gmail dot com
    // https://sites.google.com/site/astudyofentropy/project-definition/
    // timer-jitter-entropy-sources/entropy-library
    //

    // Copyright 2014 by Walter Anderson, wandrson01 at gmail dot com
    //

    #include <avr/interrupt.h>
    #include <avr/wdt.h>
    #include <util/atomic.h>
    // The following addresses a problem in version 1.0.5 and earlier of the Arduino IDE that prevents randomSeed from working
    // properly. https://github.com/arduino/Arduino/issues/575
    // The following addresses a problem in version 1.0.5 and earlier of the Arduino IDE
    // that prevents randomSeed from working properly.
    // https://github.com/arduino/Arduino/issues/575
    #define randomSeed(s) srandom(s)

    volatile uint32_t seed; // These two variables can be reused in your program after the function CreateTrulyRandomSeed()
    volatile int8_t nrot; // executes in the setup() function.


    volatile uint32_t seed; // These two variables can be reused in your program after the
    volatile int8_t nrot; // function CreateTrulyRandomSeed()executes in the setup()
    // function.

    void CreateTrulyRandomSeed()
    {
    seed = 0;
    nrot = 32; // Must be at least 4, but more increased the uniformity of the produced seeds entropy.
    cli(); // Temporarily turn off interrupts, until WDT interrupt turned on
    MCUSR = 0; // Use the MCU status register to reset flags for WDR, BOR, EXTR, and POWR
    _WD_CONTROL_REG |= (1<<_WD_CHANGE_BIT) | (1<<WDE); // WDT control register, This sets the Watchdog Change Enable (WDCE) flag, which is needed to set the
    _WD_CONTROL_REG = (1<<WDIE); // Watchdog system reset (WDE) enable and the Watchdog interrupt enable (WDIE)
    sei(); // Turn interupts on

    while (nrot > 0); // wait here until seed is created

    cli(); // Temporarily turn off interrupts, until WDT interrupt turned off
    MCUSR = 0; // Use the MCU status register to reset flags for WDR, BOR, EXTR, and POWR
    _WD_CONTROL_REG |= (1<<_WD_CHANGE_BIT) | (0<<WDE); // WDT control register, This sets the Watchdog Change Enable (WDCE) flag, which is needed to set the
    _WD_CONTROL_REG = (0<< WDIE); // Watchdog system reset (WDE) enable and the Watchdog interrupt enable (WDIE)
    sei(); // Turn interupts on
    seed = 0;
    nrot = 32; // Must be at least 4, but more increased the uniformity of the produced
    // seeds entropy.
    // The following five lines of code turn on the watch dog timer interrupt to create
    // the seed value
    cli();
    MCUSR = 0;
    _WD_CONTROL_REG |= (1<<_WD_CHANGE_BIT) | (1<<WDE);
    _WD_CONTROL_REG = (1<<WDIE);
    sei();

    while (nrot > 0); // wait here until seed is created

    // The following five lines turn off the watch dog timer interrupt
    cli();
    MCUSR = 0;
    _WD_CONTROL_REG |= (1<<_WD_CHANGE_BIT) | (0<<WDE);
    _WD_CONTROL_REG = (0<< WDIE);
    sei();
    }

    ISR(WDT_vect)
    {
    nrot--;
    seed = seed << 8;
    seed = seed ^ TCNT1L;
    nrot--;
    seed = seed << 8;
    seed = seed ^ TCNT1L;
    }

    void setup()
    {
    CreateTrulyRandomSeed();
    randomSeed(seed);
    // The preceeding two function calls will take approximately 0.5 second to execute if nrot is set to 32
    // ... the rest of your setup code should FOLLOW from here.
    CreateTrulyRandomSeed();
    randomSeed(seed);
    // The preceeding two function calls will take approximately 0.5 second to execute if
    // nrot is set to 32 ... the rest of your setup code should FOLLOW from here.
    }

    void loop()
    {
    }
    }
  2. wandrson revised this gist Apr 8, 2014. 1 changed file with 1 addition and 0 deletions.
    1 change: 1 addition & 0 deletions TrueRandomSeed.ino
    Original file line number Diff line number Diff line change
    @@ -50,6 +50,7 @@ void setup()
    CreateTrulyRandomSeed();
    randomSeed(seed);
    // The preceeding two function calls will take approximately 0.5 second to execute if nrot is set to 32
    // ... the rest of your setup code should FOLLOW from here.
    }

    void loop()
  3. wandrson revised this gist Apr 6, 2014. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion TrueRandomSeed.ino
    Original file line number Diff line number Diff line change
    @@ -17,7 +17,7 @@
    #define randomSeed(s) srandom(s)

    volatile uint32_t seed; // These two variables can be reused in your program after the function CreateTrulyRandomSeed()
    volatile uint8_t nrot; // executes in the setup() function.
    volatile int8_t nrot; // executes in the setup() function.

    void CreateTrulyRandomSeed()
    {
  4. wandrson revised this gist Apr 6, 2014. 1 changed file with 3 additions and 0 deletions.
    3 changes: 3 additions & 0 deletions TrueRandomSeed.ino
    Original file line number Diff line number Diff line change
    @@ -12,6 +12,9 @@
    #include <avr/interrupt.h>
    #include <avr/wdt.h>
    #include <util/atomic.h>
    // The following addresses a problem in version 1.0.5 and earlier of the Arduino IDE that prevents randomSeed from working
    // properly. https://github.com/arduino/Arduino/issues/575
    #define randomSeed(s) srandom(s)

    volatile uint32_t seed; // These two variables can be reused in your program after the function CreateTrulyRandomSeed()
    volatile uint8_t nrot; // executes in the setup() function.
  5. wandrson revised this gist Apr 6, 2014. 1 changed file with 21 additions and 19 deletions.
    40 changes: 21 additions & 19 deletions TrueRandomSeed.ino
    Original file line number Diff line number Diff line change
    @@ -1,26 +1,38 @@
    // TrueRandomSeed.ino
    // This example sketch shows how to provide a truly random seed value to the built in library pseudo random number generator. This ensures that your
    // sketch will be using a different sequence of random numbers every time it runs. Unlike the usually suggested randomSeed(analogRead(0)) this method
    // will provide a much more uniform and varied seed value. For more information about the basic technique used here to produce a random number or if
    // you need more than one such number you can find a library, Entropy from the following web site along with documentation of how the library has been
    // tested to provide TRUE random numbers on a variety of AVR chips and arduino environments.
    // http://code.google.com/p/avr-hardware-random-number-generation/wiki/WikiAVRentropy
    //
    // Copyright 2014 by Walter Anderson
    // Copyright 2014 by Walter Anderson, wandrson01 at gmail dot com
    //

    #include <stdint.h>
    #include <avr/interrupt.h>
    #include <avr/wdt.h>
    #include <util/atomic.h>
    #include <Arduino.h>

    volatile uint32_t seed;
    volatile uint8_t nrot;
    volatile uint32_t seed; // These two variables can be reused in your program after the function CreateTrulyRandomSeed()
    volatile uint8_t nrot; // executes in the setup() function.

    void CreateTrulyRandomSeed()
    {
    seed = 0;
    nrot = 32; // Must be at least 4, but more increased the uniformity of the produced seeds entropy.
    cli(); // Temporarily turn off interrupts, until WDT configured
    cli(); // Temporarily turn off interrupts, until WDT interrupt turned on
    MCUSR = 0; // Use the MCU status register to reset flags for WDR, BOR, EXTR, and POWR
    _WD_CONTROL_REG |= (1<<_WD_CHANGE_BIT) | (1<<WDE); // WDT control register, This sets the Watchdog Change Enable (WDCE) flag, which is needed to set the
    _WD_CONTROL_REG = _BV(WDIE); // Watchdog system reset (WDE) enable and the Watchdog interrupt enable (WDIE)
    _WD_CONTROL_REG = (1<<WDIE); // Watchdog system reset (WDE) enable and the Watchdog interrupt enable (WDIE)
    sei(); // Turn interupts on

    while (nrot > 0); // wait here until seed is created

    cli(); // Temporarily turn off interrupts, until WDT interrupt turned off
    MCUSR = 0; // Use the MCU status register to reset flags for WDR, BOR, EXTR, and POWR
    _WD_CONTROL_REG |= (1<<_WD_CHANGE_BIT) | (0<<WDE); // WDT control register, This sets the Watchdog Change Enable (WDCE) flag, which is needed to set the
    _WD_CONTROL_REG = (0<< WDIE); // Watchdog system reset (WDE) enable and the Watchdog interrupt enable (WDIE)
    sei(); // Turn interupts on
    while (nrot > 0);
    }

    ISR(WDT_vect)
    @@ -32,19 +44,9 @@ ISR(WDT_vect)

    void setup()
    {
    unsigned long start_time;
    unsigned long end_time;
    unsigned long elapsed_time;

    Serial.begin(9600);
    start_time = micros();
    CreateTrulyRandomSeed();
    randomSeed(seed);
    end_time = micros();
    elapsed_time = end_time - start_time;
    Serial.print("Completed seeding the PRNG in ");
    Serial.print(elapsed_time);
    Serial.println(" microseconds!");
    // The preceeding two function calls will take approximately 0.5 second to execute if nrot is set to 32
    }

    void loop()
  6. wandrson created this gist Apr 6, 2014.
    52 changes: 52 additions & 0 deletions TrueRandomSeed.ino
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,52 @@
    //
    // Copyright 2014 by Walter Anderson
    //

    #include <stdint.h>
    #include <avr/interrupt.h>
    #include <avr/wdt.h>
    #include <util/atomic.h>
    #include <Arduino.h>

    volatile uint32_t seed;
    volatile uint8_t nrot;

    void CreateTrulyRandomSeed()
    {
    seed = 0;
    nrot = 32; // Must be at least 4, but more increased the uniformity of the produced seeds entropy.
    cli(); // Temporarily turn off interrupts, until WDT configured
    MCUSR = 0; // Use the MCU status register to reset flags for WDR, BOR, EXTR, and POWR
    _WD_CONTROL_REG |= (1<<_WD_CHANGE_BIT) | (1<<WDE); // WDT control register, This sets the Watchdog Change Enable (WDCE) flag, which is needed to set the
    _WD_CONTROL_REG = _BV(WDIE); // Watchdog system reset (WDE) enable and the Watchdog interrupt enable (WDIE)
    sei(); // Turn interupts on
    while (nrot > 0);
    }

    ISR(WDT_vect)
    {
    nrot--;
    seed = seed << 8;
    seed = seed ^ TCNT1L;
    }

    void setup()
    {
    unsigned long start_time;
    unsigned long end_time;
    unsigned long elapsed_time;

    Serial.begin(9600);
    start_time = micros();
    CreateTrulyRandomSeed();
    randomSeed(seed);
    end_time = micros();
    elapsed_time = end_time - start_time;
    Serial.print("Completed seeding the PRNG in ");
    Serial.print(elapsed_time);
    Serial.println(" microseconds!");
    }

    void loop()
    {
    }