4.4 KiB
DEVRANDOM
Arduino library to wrap a random generator in a stream.
Description
The library implements a stream class that mimics the /dev/random device of a Linux system. It can be used for testing with streams.
Interface
Constructor
- DEVRANDOM() Constructor.
- DEVRANDOM(char * str) Constructor, seeding with a string of characters.
- DEVRANDOM(uint32_t value) Constructor, seeding with a integer value.
- DEVRANDOM(float value) Constructor, seeding with a float value.
Streeam interface
To read and to reseed the random generator.
- int available() There is always 1 next byte available.
- int peek() will give you next byte.
- int read() will give you next byte and generate a new one.
- size_t write(uint8_t data) data will be used for reseeding the random number generator (RNG), mode 0 and 3. In digitalRead and analogRead mode the seed is used to XOR the value, so it does have some effect.
- size_t write(uint8_t * buffer, size_t size) speeds up reseeding for some print / println calls.
- void flush() to keep the CI happy.
As write() reseeds the RNG, printing to DEVRANDOM will also reseed the RNG. E.g. dr.println("Hello world"); or dr.println(3.45678); will reseed DEVRANDOM too. See examples.
If footprint is an issue one could remove the size_t write(uint8_t * buffer, size_t size) from the library and implement a stripped version in write(). Reseeding will become slower but as reseeding is not used that often this might be a good trade off.
Random generator selection
- void useRandom() use the build in software random number generator. This is the default, but platform dependant.
- void useDigitalRead(uint8_t pin) use digitalRead to read 8 bits from a defined pin. One can build a hardware RNG that flips between 0 and 1 very rapidly and unpredictably. Connect this signal to the pin and it will be read and generate a random byte. The seed value from the write is used as an XOR byte.
- void useAnalogRead(uint8_t pin) use the analogRead to read 8 bits This can be fed with any analogue noise source. The seed value from the write is used as a XOR byte.
- void useMarsaglia() uses the Marsaglia pseudo random generator. This one is quite fast and good, and more important portable.
- uint8_t getMode() returns the source of randomness.
Mode | DEVRANDOM_MODE | Type |
---|---|---|
0 | build in random | depends on platform |
1 | digitalRead | hardware external |
2 | analogRead | hardware external |
3 | Marsaglia | software portable PRNG |
There might be other RNG's in the future. If you have an interesting and fast PRNG to be included please let me know.
Obsolete
- useSW() replaced by useRandom().
- useHW(uint8_t pin) replaced by useDigitalRead().
- useAR(uint8_t pin) replaced by useAnalogRead().
Operation
See example sketches.
Example
As shown in the example one can use fscanf() to read larger data types,
DEVRANDOM dr;
uint32_t x;
fscanf((FILE*) &dr, "%lu", &x);
Serial.println(x);
However float is not supported standard in the fscanf() by UNO and strings (%s) generate garbage. So a password generator is a bit more difficult (and a good exercise).
Future
- improve documentation.
- add examples.
- add other (portable) PRNG.
- available() returns 1,
- should that be more e.g. INT_MAX
- a random number > 0 ?
- ?
- when changing mode should _next == peek() be reset?
- yes, think so
_next = _rnd();
- when already in that mode? (=> complex)
- yes, think so