Skip to content

Commit

Permalink
Move auto random seeding to hardware specific implementation files
Browse files Browse the repository at this point in the history
(This is expected to increase flash size, marginally, but the effect will mostly go
away once implementation and usage are once again in the same compilation unit.)
  • Loading branch information
tfry-git committed Jan 4, 2024
1 parent dc2428f commit 7eef203
Show file tree
Hide file tree
Showing 12 changed files with 143 additions and 83 deletions.
46 changes: 46 additions & 0 deletions MozziGuts_impl_AVR.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 ////////
8 changes: 8 additions & 0 deletions MozziGuts_impl_ESP32.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
10 changes: 10 additions & 0 deletions MozziGuts_impl_ESP8266.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 ////////
6 changes: 6 additions & 0 deletions MozziGuts_impl_MBED.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
6 changes: 6 additions & 0 deletions MozziGuts_impl_RENESAS.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 ////////
6 changes: 6 additions & 0 deletions MozziGuts_impl_RP2040.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
6 changes: 6 additions & 0 deletions MozziGuts_impl_SAMD.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 ////////
21 changes: 21 additions & 0 deletions MozziGuts_impl_STM32.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 ////////
6 changes: 6 additions & 0 deletions MozziGuts_impl_STM32duino.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 ////////
6 changes: 6 additions & 0 deletions MozziGuts_impl_TEENSY.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 ////////
12 changes: 12 additions & 0 deletions MozziGuts_impl_template.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 ////////
93 changes: 10 additions & 83 deletions mozzi_rand.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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.
Expand Down

0 comments on commit 7eef203

Please sign in to comment.