diff --git a/MozziGuts_impl_AVR.hpp b/MozziGuts_impl_AVR.hpp index e877c87b0..635780e5f 100644 --- a/MozziGuts_impl_AVR.hpp +++ b/MozziGuts_impl_AVR.hpp @@ -377,3 +377,49 @@ void stopMozzi() { // Timer1.isrCallback(); // } //// END AUDIO OUTPUT code /////// + +//// BEGIN Random seeding //////// +#if defined (__AVR_ATmega644P__) + +// a less fancy version for gizduino (__AVR_ATmega644P__) which doesn't know INTERNAL +static long longRandom() +{ + return ((long)analogRead(0)+63)*(analogRead(1)+97); // added offsets in case analogRead is 0 +} + +#else + +/* +longRandom(), used as a seed generator, comes from: +http://arduino.cc/forum/index.php/topic,38091.0.html +// AUTHOR: Rob Tillaart +// PURPOSE: Simple Random functions based upon unreliable internal temp sensor +// VERSION: 0.1 +// DATE: 2011-05-01 +// +// Released to the public domain, use at own risk +// +*/ +static long longRandom() +{ + //analogReference(INTERNAL); + unsigned long rv = 0; + for (uint8_t i=0; i< 32; i++) rv |= ((analogRead(8)+1171) & 1L) << i; // added 1171 in case analogRead is 0 + return rv; +} +#endif + +void autoRandomSeeds(uint32_t *x, uint32_t *y, uint32_t *z) { + ADCSRA &= ~ (1 << ADIE); // adc Disable Interrupt, re-enable at end + // this attempt at remembering analog_reference stops it working + // maybe needs a delay after changing analog reference in longRandom (Arduino reference suggests this) + // because the analog reads return 0 + //uint8_t analog_reference_orig = ADMUX&192; // analog_reference is high 2 bits of ADMUX, store this because longRandom sets it to internal + *x = longRandom(); + *y = longRandom(); + *z = longRandom(); + //analogReference(analog_reference_orig); // change back to original + ADCSRA |= (1 << ADIE); // adc re-Enable Interrupt +} + +//// END Random seeding //////// diff --git a/MozziGuts_impl_ESP32.hpp b/MozziGuts_impl_ESP32.hpp index b20c92772..2991bdc5c 100644 --- a/MozziGuts_impl_ESP32.hpp +++ b/MozziGuts_impl_ESP32.hpp @@ -161,4 +161,12 @@ void stopMozzi() { } //// END AUDIO OUTPUT code /////// +//// BEGIN Random seeding //////// +void autoRandomSeeds(uint32_t *x, uint32_t *y, uint32_t *z) { + *x = esp_random(); + *y = esp_random(); + *z = esp_random(); +} +//// END Random seeding //////// + #undef ESP_SAMPLE_SIZE // only used inside this file diff --git a/MozziGuts_impl_ESP8266.hpp b/MozziGuts_impl_ESP8266.hpp index 3d4f3c11d..38a3aebb9 100644 --- a/MozziGuts_impl_ESP8266.hpp +++ b/MozziGuts_impl_ESP8266.hpp @@ -136,3 +136,13 @@ void stopMozzi() { #endif //// END AUDIO OUTPUT code /////// + +//// BEGIN Random seeding //////// +void autoRandomSeeds(uint32_t *x, uint32_t *y, uint32_t *z) { + *x = RANDOM_REG32; + // TODO: The XORs may not be needed, but for lack of documentation (that I could find), let's assume RANDOM_REG32 + // itself might not get updated on every read. NOTE: x, y, and z are initialized to non-zero, before this. + *y = *y ^ RANDOM_REG32; + *z = *z ^ RANDOM_REG32; +} +//// END Random seeding //////// diff --git a/MozziGuts_impl_MBED.hpp b/MozziGuts_impl_MBED.hpp index 5f612cc14..96f4a1008 100644 --- a/MozziGuts_impl_MBED.hpp +++ b/MozziGuts_impl_MBED.hpp @@ -221,5 +221,11 @@ void stopMozzi() { #endif ////// END audio output code ////// +//// BEGIN Random seeding //////// +void autoRandomSeeds(uint32_t *x, uint32_t *y, uint32_t *z) { +#warning Automatic random seedings is not implemented on this platform +} +//// END Random seeding //////// + #undef CHUNKSIZE #undef US_PER_AUDIO_TICK diff --git a/MozziGuts_impl_RENESAS.hpp b/MozziGuts_impl_RENESAS.hpp index ddc9edeaf..0fbaaecd1 100644 --- a/MozziGuts_impl_RENESAS.hpp +++ b/MozziGuts_impl_RENESAS.hpp @@ -168,3 +168,9 @@ void stopMozzi() { #endif } //// END AUDIO OUTPUT code /////// + +//// BEGIN Random seeding //////// +void autoRandomSeeds(uint32_t *x, uint32_t *y, uint32_t *z) { +#warning Automatic random seedings is not implemented on this platform +} +//// END Random seeding //////// diff --git a/MozziGuts_impl_RP2040.hpp b/MozziGuts_impl_RP2040.hpp index 1b2b87623..79daf4995 100644 --- a/MozziGuts_impl_RP2040.hpp +++ b/MozziGuts_impl_RP2040.hpp @@ -266,5 +266,11 @@ void stopMozzi() { } ////// END audio output code ////// +//// BEGIN Random seeding //////// +void autoRandomSeeds(uint32_t *x, uint32_t *y, uint32_t *z) { +#warning Automatic random seedings is not implemented on this platform +} +//// END Random seeding //////// + #undef MOZZI_RP2040_BUFFERS #undef MOZZI_RP2040_BUFFER_SIZE diff --git a/MozziGuts_impl_SAMD.hpp b/MozziGuts_impl_SAMD.hpp index b885a28fe..84adc833b 100644 --- a/MozziGuts_impl_SAMD.hpp +++ b/MozziGuts_impl_SAMD.hpp @@ -138,3 +138,9 @@ void stopMozzi() { interrupts(); } //// END AUDIO OUTPUT code /////// + +//// BEGIN Random seeding //////// +void autoRandomSeeds(uint32_t *x, uint32_t *y, uint32_t *z) { +#warning Automatic random seedings is not implemented on this platform +} +//// END Random seeding //////// diff --git a/MozziGuts_impl_STM32.hpp b/MozziGuts_impl_STM32.hpp index 3c5969ba0..e57956544 100644 --- a/MozziGuts_impl_STM32.hpp +++ b/MozziGuts_impl_STM32.hpp @@ -138,3 +138,24 @@ void stopMozzi() { } //// END AUDIO OUTPUT code /////// + +//// BEGIN Random seeding //////// +void autoRandomSeeds(uint32_t *x, uint32_t *y, uint32_t *z) { + // Unfortunately the internal temp sensor on STM32s does _not_ appear to create a lot of noise. + // Ironically, the calls to calibrate help induce some random noise. You're still fairly likely to produce two equal + // random seeds in two subsequent runs, however. + adc.enableInternalReading(); + union { + float cf; + uint32_t ci; + } conv; + conv.cf = adc.readTemp(); + *x=*x^conv.ci; + adc.calibrate(); + conv.cf = adc.readTemp(); + *y=*y^conv.ci; + adc.calibrate(); + conv.cf = adc.readTemp(); + *z=*z^conv.ci; +} +//// END Random seeding //////// diff --git a/MozziGuts_impl_STM32duino.hpp b/MozziGuts_impl_STM32duino.hpp index b24f5a749..8a56e0dcb 100644 --- a/MozziGuts_impl_STM32duino.hpp +++ b/MozziGuts_impl_STM32duino.hpp @@ -171,3 +171,9 @@ void stopMozzi() { } //// END AUDIO OUTPUT code /////// + +//// BEGIN Random seeding //////// +void autoRandomSeeds(uint32_t *x, uint32_t *y, uint32_t *z) { +#warning Automatic random seedings is not implemented on this platform +} +//// END Random seeding //////// diff --git a/MozziGuts_impl_TEENSY.hpp b/MozziGuts_impl_TEENSY.hpp index 04c18ac73..a8efc2199 100644 --- a/MozziGuts_impl_TEENSY.hpp +++ b/MozziGuts_impl_TEENSY.hpp @@ -112,3 +112,9 @@ void stopMozzi() { interrupts(); } //// END AUDIO OUTPUT code /////// + +//// BEGIN Random seeding //////// +void autoRandomSeeds(uint32_t *x, uint32_t *y, uint32_t *z) { +#warning Automatic random seedings is not implemented on this platform +} +//// END Random seeding //////// diff --git a/MozziGuts_impl_template.hpp b/MozziGuts_impl_template.hpp index 154c1ee29..544b1b2e2 100644 --- a/MozziGuts_impl_template.hpp +++ b/MozziGuts_impl_template.hpp @@ -156,3 +156,15 @@ void stopMozzi() { // Add here code to pause whatever mechanism moves audio samples to the output } ////// END audio output code ////// + +//// BEGIN Random seeding //////// +void autoRandomSeeds(uint32_t *x, uint32_t *y, uint32_t *z) { + // Add here code to initialize the values pointed to by x, y, and z to some random values + // This doesn't need to be crypographically safe. If nothing better is available, e.g. try reading an internal temperature sensor + // in order to get some noise. It also doesn't have to be fast. + // It *should* however ensure that rand() sequences will differ across reboots, after randSeed() has been called. + // x, y, and z are already initialized to non-zero, when this function is called. + // It's ok to leave this unimplemented, initially. +#warning Automatic random seedings is not implemented on this platform +} +//// END Random seeding //////// diff --git a/mozzi_rand.cpp b/mozzi_rand.cpp index f37b61a48..38595caf3 100644 --- a/mozzi_rand.cpp +++ b/mozzi_rand.cpp @@ -55,48 +55,8 @@ void randSeed(unsigned long seed) x=seed; } - -#if defined (__AVR_ATmega644P__) - -// a less fancy version for gizduino (__AVR_ATmega644P__) which doesn't know INTERNAL -static long longRandom() -{ - return ((long)analogRead(0)+63)*(analogRead(1)+97); // added offsets in case analogRead is 0 -} - -#elif defined (__AVR_ATmega2560__) -/* -longRandom(), used as a seed generator, comes from: -http://arduino.cc/forum/index.php/topic,38091.0.html -// AUTHOR: Rob Tillaart -// PURPOSE: Simple Random functions based upon unreliable internal temp sensor -// VERSION: 0.1 -// DATE: 2011-05-01 -// -// Released to the public domain, use at own risk -// -*/ -static long longRandom() -{ - //analogReference(INTERNAL2V56); - unsigned long rv = 0; - for (uint8_t i=0; i< 32; i++) rv |= ((analogRead(8)+2294) & 1L) << i; // added 2294 in case analogRead is 0 - return rv; -} - -#elif IS_AVR() - -static long longRandom() -{ - //analogReference(INTERNAL); - unsigned long rv = 0; - for (uint8_t i=0; i< 32; i++) rv |= ((analogRead(8)+1171) & 1L) << i; // added 1171 in case analogRead is 0 - return rv; -} - - -#endif - +// To be defined in hardware implementations +void autoRandomSeeds(uint32_t *x, uint32_t *y, uint32_t &*z); /** @ingroup random Initialises Mozzi's (pseudo)random number generator xorshift96(), which is used @@ -106,51 +66,18 @@ randSeed() called without a parameter uses noise from reading the Arduino's internal temperature as the seed, a technique discussed at http://arduino.cc/forum/index.php/topic,38091.0.html, borrowing code put there by Rob Tillaart. -@note It's not perfect, as discussed in the forum thread. -It might only work with some processors: (from the thread) -"...ATmega328P in DIP, possibly others but the duemilanove and uno will do it at least." -So far, gizduino's __AVR_ATmega644P__ chip doesn't like it, so we use (long)analogRead(0)*analogRead(1) for that instead. -It works to some degree on STM32 chips, but the produced seed is not very random at all. Again, using an appropriate -analogRead() (preferably on one or two floating input pins) is much more effective. -@todo add Teensy 3 code + +@note Intialization of the random seed is done differently on different MCUs, + but is nowhere near perfect for most (and for some it is not even implemented at all). + Many implementations (e.g. on AVR, STM32) simply rely on reading a (hopefully noisy) + internal temperature sensor. + You will often get better results by calling analogRead() - @em not mozziAnalogRead(0), in this case! - + on one or two floating (non-connected) analog pins. */ void randSeed() { -#if IS_AVR() - ADCSRA &= ~ (1 << ADIE); // adc Disable Interrupt, re-enable at end - // this attempt at remembering analog_reference stops it working - // maybe needs a delay after changing analog reference in longRandom (Arduino reference suggests this) - // because the analog reads return 0 - //uint8_t analog_reference_orig = ADMUX&192; // analog_reference is high 2 bits of ADMUX, store this because longRandom sets it to internal - x=longRandom(); - y=longRandom(); - z=longRandom(); - //analogReference(analog_reference_orig); // change back to original - ADCSRA |= (1 << ADIE); // adc re-Enable Interrupt -#elif IS_STM32MAPLE() - // Unfortunately the internal temp sensor on STM32s does _not_ appear to create a lot of noise. - // Ironically, the calls to calibrate help induce some random noise. You're still fairly likely to produce two equal - // random seeds in two subsequent runs, however. - adc.enableInternalReading(); - float dummy = adc.readTemp(); - int* dummy_int = (int*) &dummy; - x=*dummy_int; - adc.calibrate(); - dummy = adc.readTemp(); - y=*dummy_int; - adc.calibrate(); - dummy = adc.readTemp(); - z=*dummy_int; -#elif IS_ESP8266() - x = RANDOM_REG32; - y = random (0xFFFFFFFF) ^ RANDOM_REG32; - z = random (0xFFFFFFFF) ^ RANDOM_REG32; -#else -#warning Automatic random seeding not implemented on this platform -#endif + autoRandomSeeds(&x, &y, &z); } - - /** @ingroup random Initialises Mozzi's (pseudo)random number generator xorshift96() with a chosen seed number. @param seed a number to use as a seed.