mirror of
https://github.com/RobTillaart/Arduino.git
synced 2024-10-03 18:09:02 -04:00
0.2.0 DEVRANDOM
This commit is contained in:
parent
d4d2ed7e9f
commit
43049f375f
183
libraries/DEVRANDOM/DEVRANDOM.cpp
Normal file
183
libraries/DEVRANDOM/DEVRANDOM.cpp
Normal file
@ -0,0 +1,183 @@
|
||||
//
|
||||
// FILE: DEVRANDOM.cpp
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.2.0
|
||||
// PURPOSE: Arduino library for a /dev/random stream - useful for testing
|
||||
// URL: https://github.com/RobTillaart/DEVRANDOM
|
||||
//
|
||||
// HISTORY:
|
||||
// 0.1.0 2020-06-23 initial version
|
||||
// 0.1.1 2020-12-18 add Arduino-CI + unit tests
|
||||
// + getMode() + flush()
|
||||
// 0.1.2 2021-01-15 add constructors with seed.
|
||||
// 0.1.3 2021-12-15 update library.json, license, minor edits
|
||||
//
|
||||
// 0.2.0 2022-07-02 add Marsaglia PRNG, is portable over platforms
|
||||
// becomes mode 3
|
||||
// improved reseeding
|
||||
// split off .cpp file
|
||||
// add examples
|
||||
|
||||
|
||||
#include "DEVRANDOM.h"
|
||||
|
||||
|
||||
DEVRANDOM::DEVRANDOM()
|
||||
{
|
||||
_next = _rnd();
|
||||
};
|
||||
|
||||
|
||||
DEVRANDOM::DEVRANDOM(const char * str)
|
||||
{
|
||||
this->print(str);
|
||||
_next = _rnd();
|
||||
};
|
||||
|
||||
|
||||
DEVRANDOM::DEVRANDOM(const uint32_t value)
|
||||
{
|
||||
this->print(value);
|
||||
_next = _rnd();
|
||||
};
|
||||
|
||||
|
||||
DEVRANDOM::DEVRANDOM(const float value)
|
||||
{
|
||||
this->print(value, 6);
|
||||
_next = _rnd();
|
||||
};
|
||||
|
||||
|
||||
int DEVRANDOM::available()
|
||||
{
|
||||
return 1;
|
||||
};
|
||||
|
||||
|
||||
int DEVRANDOM::peek()
|
||||
{
|
||||
return _next;
|
||||
};
|
||||
|
||||
|
||||
int DEVRANDOM::read()
|
||||
{
|
||||
uint8_t x = _next;
|
||||
_next = _rnd();
|
||||
return x;
|
||||
};
|
||||
|
||||
|
||||
// keep CI happy as parent class flush is virtual.
|
||||
void DEVRANDOM::flush()
|
||||
{
|
||||
};
|
||||
|
||||
|
||||
size_t DEVRANDOM::write(const uint8_t data)
|
||||
{
|
||||
return write(&data, 1);
|
||||
};
|
||||
|
||||
|
||||
size_t DEVRANDOM::write(const uint8_t * buffer, size_t size)
|
||||
{
|
||||
uint32_t tmp = _seed;
|
||||
for (size_t i = 0; i < size; i++)
|
||||
{
|
||||
_seed = _seed * (_seed << 8) + buffer[i];
|
||||
}
|
||||
if (_mode == 0)
|
||||
{
|
||||
randomSeed(_seed);
|
||||
}
|
||||
if (_mode == 3)
|
||||
{
|
||||
_m_z = (_seed == 0) ? 1 : _seed;
|
||||
_m_w = ( tmp == 0) ? 2 : tmp;
|
||||
}
|
||||
return size;
|
||||
};
|
||||
|
||||
|
||||
void DEVRANDOM::useMarsaglia()
|
||||
{
|
||||
_mode = 3;
|
||||
};
|
||||
|
||||
|
||||
void DEVRANDOM::useAnalogRead(uint8_t pin)
|
||||
{
|
||||
_mode = 2;
|
||||
_pin = pin;
|
||||
};
|
||||
|
||||
|
||||
void DEVRANDOM::useDigitalRead(uint8_t pin)
|
||||
{
|
||||
_mode = 1;
|
||||
_pin = pin;
|
||||
pinMode(_pin, INPUT);
|
||||
};
|
||||
|
||||
|
||||
void DEVRANDOM::useRandom()
|
||||
{
|
||||
_mode = 0;
|
||||
};
|
||||
|
||||
|
||||
uint8_t DEVRANDOM::getMode()
|
||||
{
|
||||
return _mode;
|
||||
};
|
||||
|
||||
|
||||
int DEVRANDOM::_rnd()
|
||||
{
|
||||
if (_mode == 0 ) return random(256);
|
||||
if (_mode == 1 ) return _digitalRead();
|
||||
if (_mode == 2 ) return _analogRead();
|
||||
if (_mode == 3 ) return _marsaglia();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int DEVRANDOM::_digitalRead()
|
||||
{
|
||||
uint8_t value = 0;
|
||||
for (uint8_t i = 0; i < 8; i++)
|
||||
{
|
||||
value <<= 1;
|
||||
if (digitalRead(_pin)) value++;
|
||||
}
|
||||
return value ^ _seed;
|
||||
}
|
||||
|
||||
|
||||
int DEVRANDOM::_analogRead()
|
||||
{
|
||||
uint8_t value = 0;
|
||||
for (uint8_t i = 0; i < 8; i++)
|
||||
{
|
||||
value <<= 1;
|
||||
if (analogRead(_pin) & 1) value++;
|
||||
}
|
||||
return value ^ _seed;
|
||||
}
|
||||
|
||||
|
||||
// An example of a simple pseudo-random number generator is the
|
||||
// Multiply-with-carry method invented by George Marsaglia.
|
||||
// two initializers (not null)
|
||||
uint32_t DEVRANDOM::_marsaglia()
|
||||
{
|
||||
_m_z = 36969L * (_m_z & 65535L) + (_m_z >> 16);
|
||||
_m_w = 18000L * (_m_w & 65535L) + (_m_w >> 16);
|
||||
return (_m_z << 16) + _m_w; /* 32-bit result */
|
||||
}
|
||||
|
||||
|
||||
// -- END OF FILE --
|
||||
|
@ -2,145 +2,72 @@
|
||||
//
|
||||
// FILE: DEVRANDOM.h
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.1.3
|
||||
// VERSION: 0.2.0
|
||||
// PURPOSE: Arduino library for a /dev/random stream - useful for testing
|
||||
// URL: https://github.com/RobTillaart/DEVRANDOM
|
||||
//
|
||||
// HISTORY:
|
||||
// 0.1.0 2020-06-23 initial version
|
||||
// 0.1.1 2020-12-18 add Arduino-CI + unit tests
|
||||
// + getMode() + flush()
|
||||
// 0.1.2 2021-01-15 add constructors with seed.
|
||||
// 0.1.3 2021-12-15 update library.json, license, minor edits
|
||||
|
||||
|
||||
#include "Arduino.h"
|
||||
|
||||
|
||||
#define DEVRANDOM_LIB_VERSION (F("0.1.3"))
|
||||
#define DEVRANDOM_LIB_VERSION (F("0.2.0"))
|
||||
|
||||
|
||||
#define DEVRANDOM_MODE_SW 0
|
||||
#define DEVRANDOM_MODE_HW 1
|
||||
#define DEVRANDOM_MODE_AR 2
|
||||
#define DEVRANDOM_MODE_RANDOM 0
|
||||
#define DEVRANDOM_MODE_DIGITALREAD 1
|
||||
#define DEVRANDOM_MODE_ANALOGREAD 2
|
||||
#define DEVRANDOM_MODE_MARSAGLIA 3
|
||||
|
||||
|
||||
class DEVRANDOM : public Stream
|
||||
{
|
||||
public:
|
||||
DEVRANDOM()
|
||||
{
|
||||
_seed = 0;
|
||||
_next = random(256);
|
||||
_mode = 0;
|
||||
_pin = 0;
|
||||
};
|
||||
DEVRANDOM();
|
||||
DEVRANDOM(const char * str);
|
||||
DEVRANDOM(const uint32_t value);
|
||||
DEVRANDOM(const float value);
|
||||
|
||||
int available();
|
||||
int peek();
|
||||
int read();
|
||||
// keep CI happy as parent class flush is virtual.
|
||||
void flush();
|
||||
// for reseeding, including via print() and println().
|
||||
size_t write(const uint8_t data);
|
||||
size_t write(const uint8_t * buffer, size_t size);
|
||||
|
||||
// build in random is the default mode.
|
||||
void useRandom();
|
||||
void useDigitalRead(uint8_t pin);
|
||||
void useAnalogRead(uint8_t pin);
|
||||
void useMarsaglia();
|
||||
|
||||
uint8_t getMode();
|
||||
|
||||
|
||||
DEVRANDOM(const char * str)
|
||||
{
|
||||
this->print(str);
|
||||
_next = random(256);
|
||||
_mode = 0;
|
||||
_pin = 0;
|
||||
};
|
||||
|
||||
|
||||
DEVRANDOM(const uint32_t value)
|
||||
{
|
||||
this->print(value);
|
||||
_next = random(256);
|
||||
_mode = 0;
|
||||
_pin = 0;
|
||||
};
|
||||
|
||||
|
||||
DEVRANDOM(const float value)
|
||||
{
|
||||
this->print(value, 6);
|
||||
_next = random(256);
|
||||
_mode = 0;
|
||||
_pin = 0;
|
||||
};
|
||||
|
||||
|
||||
int available() { return 1; };
|
||||
|
||||
|
||||
int peek() { return _next; };
|
||||
|
||||
|
||||
int read()
|
||||
{
|
||||
uint8_t x = _next;
|
||||
_next = _rnd();
|
||||
return x;
|
||||
};
|
||||
|
||||
|
||||
// keep CI happy as parent class flush is virtual.
|
||||
void flush() {};
|
||||
|
||||
|
||||
size_t write(const uint8_t data)
|
||||
{
|
||||
_seed = (_seed << 8) + data;
|
||||
randomSeed(_seed);
|
||||
return 1;
|
||||
};
|
||||
|
||||
|
||||
void useAR(uint8_t pin) { _mode = 2; _pin = pin; };
|
||||
void useHW(uint8_t pin) { _mode = 1; _pin = pin; pinMode(_pin, INPUT); };
|
||||
void useSW() { _mode = 0; };
|
||||
|
||||
|
||||
uint8_t getMode() { return _mode; };
|
||||
// will be obsolete in future
|
||||
void useAR(uint8_t pin) { useAnalogRead(pin); };
|
||||
void useHW(uint8_t pin) { useDigitalRead(pin); };
|
||||
void useSW() { useRandom(); };
|
||||
|
||||
|
||||
private:
|
||||
uint8_t _next;
|
||||
uint32_t _seed;
|
||||
uint8_t _mode;
|
||||
uint8_t _pin;
|
||||
uint8_t _next = 0;
|
||||
uint32_t _seed = 0;
|
||||
uint8_t _mode = 0;
|
||||
uint8_t _pin = 0;
|
||||
// Marsaglia 'constants'
|
||||
uint32_t _m_w = 1;
|
||||
uint32_t _m_z = 2;
|
||||
|
||||
int _rnd();
|
||||
int _digitalRead();
|
||||
int _analogRead();
|
||||
uint32_t _marsaglia();
|
||||
|
||||
int _rnd()
|
||||
{
|
||||
if (_mode == 0 ) return random(256);
|
||||
if (_mode == 1 ) return _hardware();
|
||||
if (_mode == 2 ) return _analog();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int _hardware()
|
||||
{
|
||||
uint8_t value = 0;
|
||||
for (uint8_t i = 0; i < 8; i++)
|
||||
{
|
||||
value <<= 1;
|
||||
if (digitalRead(_pin)) value++;
|
||||
}
|
||||
return value ^ _seed;
|
||||
}
|
||||
|
||||
|
||||
int _analog()
|
||||
{
|
||||
uint8_t value = 0;
|
||||
for (uint8_t i = 0; i < 8; i++)
|
||||
{
|
||||
value <<= 1;
|
||||
if (analogRead(_pin) & 1) value++;
|
||||
}
|
||||
return value ^ _seed;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// TODO alternative random number generator so all platforms behave same.
|
||||
// Marsaglia ?
|
||||
|
||||
// -- END OF FILE --
|
||||
|
||||
|
@ -29,33 +29,61 @@ device of a Linux system. It can be used for testing with streams.
|
||||
|
||||
### Streeam interface
|
||||
|
||||
to read and to reseed the random generator.
|
||||
To read and to reseed the random generator.
|
||||
|
||||
- **available()** There is always 1 next byte available
|
||||
- **peek()** will give you next byte
|
||||
- **read()** will give you next byte and generate a new one.
|
||||
- **write()** data will be used for reseeding the random number generator (RNG)
|
||||
(SW mode only, in HW mode and AN mode the seed is used to XOR the value, so it
|
||||
does have some effect);
|
||||
- **flush()** to keep the CI happy.
|
||||
- **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
|
||||
|
||||
- **useSW()** use a software random number generator. This is the default.
|
||||
By default the build-in random number generator is used.
|
||||
This can be replaced by a RNG of your choice.
|
||||
- **useHW(uint8_t pin)** use digitalRead to read 8 bits from a defined pin.
|
||||
- **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.
|
||||
- **useAR(uint8_t pin)** use the analogRead to read 8 bits
|
||||
This can be fed with an analogue noise source.
|
||||
- **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.
|
||||
- **getMode()** returns the source of randomness => 0 = SW, 1 = HW, 2 = AR (see above).
|
||||
- **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.
|
||||
|
||||
As **write()** reseeds the RNG, printing to **DEVRANDOM** will also reseed the RNG.
|
||||
E.g. **dr.println("Hello world");** would reseed it too.
|
||||
| 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
|
||||
|
||||
To be obsolete in a next release.
|
||||
|
||||
- **useSW()** replaced by **useRandom()**.
|
||||
- **useHW(uint8_t pin)** replaced by **useDigitalRead()**.
|
||||
- **useAR(uint8_t pin)** replaced by **useAnalogRead()**.
|
||||
|
||||
|
||||
## Operation
|
||||
@ -79,6 +107,14 @@ So a password generator is a bit more difficult (and a good exercise).
|
||||
|
||||
## Future
|
||||
|
||||
- improve documentation
|
||||
- add Marsaglia PRG
|
||||
-
|
||||
- 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)
|
||||
|
||||
|
@ -0,0 +1,44 @@
|
||||
//
|
||||
// FILE: DEVRANDOM_compile_time_random_seed.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// PURPOSE: demo compile time random seed
|
||||
// DATE: 2020-06-23
|
||||
// (c) : MIT
|
||||
//
|
||||
|
||||
|
||||
#include "DEVRANDOM.h"
|
||||
|
||||
DEVRANDOM dr;
|
||||
|
||||
uint32_t i = 0, start, stop;
|
||||
volatile int x;
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.println(__FILE__);
|
||||
Serial.println();
|
||||
|
||||
// setup compile time random seed
|
||||
dr.print(__FILE__);
|
||||
dr.print(__DATE__);
|
||||
dr.print(__TIME__);
|
||||
}
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
i++;
|
||||
if (dr.available())
|
||||
{
|
||||
Serial.print("\t");
|
||||
Serial.print(dr.read());
|
||||
if ((i % 10) == 9 ) Serial.println();
|
||||
}
|
||||
delay(100);
|
||||
}
|
||||
|
||||
|
||||
// -- END OF FILE --
|
@ -1,10 +1,8 @@
|
||||
//
|
||||
// FILE: DEVRANDOM_demo.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.1.0
|
||||
// PURPOSE: demo
|
||||
// DATE: 2020-06-23
|
||||
// (c) : MIT
|
||||
//
|
||||
|
||||
|
||||
@ -22,68 +20,103 @@ void setup()
|
||||
Serial.println(__FILE__);
|
||||
Serial.println();
|
||||
|
||||
Serial.println("SOFTWARE:\t");
|
||||
dr.useSW();
|
||||
start = millis();
|
||||
while (millis() - start < 1000)
|
||||
{
|
||||
x = dr.read();
|
||||
i++;
|
||||
}
|
||||
Serial.print("nrs per second:");
|
||||
Serial.println(i);
|
||||
Serial.println(x);
|
||||
Serial.println("Reseeding compile time");
|
||||
start = micros();
|
||||
dr.print(__FILE__);
|
||||
dr.print(__DATE__);
|
||||
dr.print(__TIME__);
|
||||
dr.print(PI);
|
||||
stop = micros();
|
||||
Serial.print("reseeding: ");
|
||||
Serial.println(stop - start);
|
||||
Serial.println();
|
||||
delay(1000);
|
||||
|
||||
Serial.println("HW PULSES:\t");
|
||||
dr.useHW(4);
|
||||
start = millis();
|
||||
while (millis() - start < 1000)
|
||||
{
|
||||
x = dr.read();
|
||||
i++;
|
||||
}
|
||||
Serial.print("nrs per second: ");
|
||||
Serial.println(i);
|
||||
Serial.println(x);
|
||||
delay(1000);
|
||||
|
||||
Serial.println("ANALOG:\t");
|
||||
dr.useAR(A0);
|
||||
start = millis();
|
||||
while (millis() - start < 1000)
|
||||
{
|
||||
x = dr.read();
|
||||
i++;
|
||||
}
|
||||
Serial.print("nrs per second: ");
|
||||
Serial.println(i);
|
||||
Serial.println(x);
|
||||
delay(1000);
|
||||
|
||||
dr.useSW();
|
||||
Serial.println("Build in random");
|
||||
dr.useRandom();
|
||||
i = 0;
|
||||
start = millis();
|
||||
while (millis() - start < 1000)
|
||||
{
|
||||
x = dr.read();
|
||||
i++;
|
||||
}
|
||||
Serial.print("nrs per second: ");
|
||||
Serial.println(i);
|
||||
Serial.println(x);
|
||||
Serial.println();
|
||||
delay(1000);
|
||||
|
||||
Serial.println("DigitalRead");
|
||||
dr.useDigitalRead(4);
|
||||
i = 0;
|
||||
start = millis();
|
||||
while (millis() - start < 1000)
|
||||
{
|
||||
x = dr.read();
|
||||
i++;
|
||||
}
|
||||
Serial.print("nrs per second: ");
|
||||
Serial.println(i);
|
||||
Serial.println(x);
|
||||
Serial.println();
|
||||
delay(1000);
|
||||
|
||||
Serial.println("AnalogRead");
|
||||
dr.useAnalogRead(A0);
|
||||
i = 0;
|
||||
start = millis();
|
||||
while (millis() - start < 1000)
|
||||
{
|
||||
x = dr.read();
|
||||
i++;
|
||||
}
|
||||
Serial.print("nrs per second: ");
|
||||
Serial.println(i);
|
||||
Serial.println(x);
|
||||
Serial.println();
|
||||
delay(1000);
|
||||
|
||||
Serial.println("MARSAGLIA");
|
||||
dr.useMarsaglia();
|
||||
i = 0;
|
||||
start = millis();
|
||||
while (millis() - start < 1000)
|
||||
{
|
||||
x = dr.read();
|
||||
i++;
|
||||
}
|
||||
Serial.print("nrs per second: ");
|
||||
Serial.println(i);
|
||||
Serial.println(x);
|
||||
Serial.println();
|
||||
delay(1000);
|
||||
|
||||
uint32_t x;
|
||||
fscanf((FILE*)&dr, "%lu", &x);
|
||||
Serial.print("UINT32: ");
|
||||
Serial.println(x, HEX);
|
||||
|
||||
|
||||
uint16_t y;
|
||||
fscanf((FILE*)&dr, "%u", &y);
|
||||
Serial.print("UINT16: ");
|
||||
Serial.println(y, HEX);
|
||||
|
||||
// float f;
|
||||
// fscanf((FILE*)&dr, "%e", &f); // does not work on UNO.
|
||||
// Serial.print("FLOAT: ");
|
||||
// Serial.println(f, 4);
|
||||
//
|
||||
// char str[24];
|
||||
// fscanf((FILE*)&dr, "%20s", str); // "works, but unusable garbage"
|
||||
// Serial.print("STRING: ");
|
||||
// Serial.println(str);
|
||||
// float f;
|
||||
// fscanf((FILE*)&dr, "%e", &f); // does not work on UNO.
|
||||
// Serial.print("FLOAT: ");
|
||||
// Serial.println(f, 4);
|
||||
//
|
||||
// char str[24];
|
||||
// fscanf((FILE*)&dr, "%20s", str); // "works, but unusable garbage"
|
||||
// Serial.print("STRING: ");
|
||||
// Serial.println(str);
|
||||
|
||||
|
||||
// reset i counter for loop()
|
||||
Serial.println();
|
||||
i = 0;
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
|
21
libraries/DEVRANDOM/examples/DEVRANDOM_demo/output_0.2.0.txt
Normal file
21
libraries/DEVRANDOM/examples/DEVRANDOM_demo/output_0.2.0.txt
Normal file
@ -0,0 +1,21 @@
|
||||
...Arduino\libraries\DEVRANDOM\examples\DEVRANDOM_demo\DEVRANDOM_demo.ino
|
||||
|
||||
Build in random
|
||||
nrs per second: 10211
|
||||
0
|
||||
DigitalRead
|
||||
nrs per second: 31345
|
||||
0
|
||||
AnalogRead
|
||||
nrs per second: 1106
|
||||
0
|
||||
MARSAGLIA
|
||||
nrs per second: 53296
|
||||
57
|
||||
UINT32: D004D104
|
||||
UINT16: CF04
|
||||
124 7 188 97 60 33 242 214 29
|
||||
4 56 129 142 60 61 166 50 213 78
|
||||
14 60 251 237 162 77 59 178 119 79
|
||||
216 25 161 54 245 42 250 202 63 167
|
||||
137 65 38 81 8 247 150 207 60 215
|
@ -15,10 +15,9 @@
|
||||
#include "DEVRANDOM.h"
|
||||
|
||||
|
||||
#define PASSWORD_SIZE 8
|
||||
#define MAX_PASSWORD_SIZE 24
|
||||
|
||||
|
||||
char pw[PASSWORD_SIZE + 1];
|
||||
char pw[MAX_PASSWORD_SIZE + 1];
|
||||
|
||||
DEVRANDOM dr;
|
||||
|
||||
@ -37,9 +36,16 @@ void setup()
|
||||
Serial.println(__FILE__);
|
||||
Serial.println();
|
||||
|
||||
// dr.useDR(5);
|
||||
// dr.useAR(A0);
|
||||
dr.useSW(); // for proof of concept this is OK
|
||||
// compile time randomization
|
||||
// comment if you want same seed every time.
|
||||
dr.print(__FILE__);
|
||||
dr.print(__DATE__);
|
||||
dr.print(__TIME__);
|
||||
|
||||
// dr.useDigitalRead(5);
|
||||
// dr.useAnalogRead(A0);
|
||||
// dr.useMarsaglia(); // faster than build in random (UNO).
|
||||
dr.useRandom(); // for proof of concept this is OK
|
||||
}
|
||||
|
||||
|
||||
@ -48,7 +54,7 @@ void loop()
|
||||
Serial.print('\t');
|
||||
|
||||
uint32_t start = micros();
|
||||
int cnt = generatePassword();
|
||||
int cnt = generatePassword(12);
|
||||
uint32_t stop = micros();
|
||||
mx = max(cnt, mx);
|
||||
|
||||
@ -63,20 +69,22 @@ void loop()
|
||||
}
|
||||
|
||||
|
||||
int generatePassword()
|
||||
int generatePassword(int length)
|
||||
{
|
||||
int idx = 0;
|
||||
bool b[4] = { false, false, false, false };
|
||||
bool done = false;
|
||||
int count = 0;
|
||||
|
||||
if (length > MAX_PASSWORD_SIZE) length = MAX_PASSWORD_SIZE;
|
||||
|
||||
while (! done)
|
||||
{
|
||||
count++;
|
||||
idx = 0;
|
||||
b[0] = b[1] = b[2] = b[3] = false;
|
||||
|
||||
while (idx < PASSWORD_SIZE)
|
||||
while (idx < length)
|
||||
{
|
||||
uint8_t x = dr.read() % 4;
|
||||
switch (x)
|
||||
|
@ -1,10 +1,8 @@
|
||||
//
|
||||
// FILE: DEVRANDOM_demo.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.1.0
|
||||
// PURPOSE: demo
|
||||
// DATE: 2020-06-23
|
||||
// (c) : MIT
|
||||
//
|
||||
|
||||
// USE WITH SERIAL PLOTTER
|
||||
@ -14,7 +12,7 @@
|
||||
|
||||
DEVRANDOM dr;
|
||||
|
||||
volatile int x, y, z;
|
||||
volatile int a, b, c, d;
|
||||
|
||||
|
||||
void setup()
|
||||
@ -23,24 +21,32 @@ void setup()
|
||||
Serial.println(__FILE__);
|
||||
Serial.println();
|
||||
|
||||
Serial.println("SOFTWARE\tDIGITAL\tANALOG");
|
||||
Serial.println("SOFTWARE\tDIGITAL\tANALOG\tMARSAGLIA");
|
||||
}
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
dr.useSW();
|
||||
x = dr.read();
|
||||
dr.useHW(4);
|
||||
x = dr.read();
|
||||
dr.useAR(A0);
|
||||
x = dr.read();
|
||||
dr.useRandom();
|
||||
a = dr.read();
|
||||
a = dr.read();
|
||||
dr.useDigitalRead(4);
|
||||
b = dr.read();
|
||||
b = dr.read();
|
||||
dr.useAnalogRead(A0);
|
||||
c = dr.read();
|
||||
c = dr.read();
|
||||
dr.useMarsaglia();
|
||||
d = dr.read();
|
||||
d = dr.read();
|
||||
|
||||
Serial.print(x);
|
||||
Serial.print(a);
|
||||
Serial.print("\t");
|
||||
Serial.print(y);
|
||||
Serial.print(b);
|
||||
Serial.print("\t");
|
||||
Serial.print(z);
|
||||
Serial.print(c);
|
||||
Serial.print("\t");
|
||||
Serial.print(d);
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,57 @@
|
||||
//
|
||||
// FILE: DEVRANDOM_run_time_random_seed.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// PURPOSE: demo compile time random seed
|
||||
// DATE: 2020-06-23
|
||||
// (c) : MIT
|
||||
//
|
||||
|
||||
|
||||
#include "DEVRANDOM.h"
|
||||
|
||||
DEVRANDOM dr;
|
||||
|
||||
uint32_t i = 0, start, stop;
|
||||
volatile int x;
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.println();
|
||||
Serial.println(__FILE__);
|
||||
Serial.println();
|
||||
|
||||
// setup compile time random seed
|
||||
// dr.print(__FILE__);
|
||||
// dr.print(__DATE__);
|
||||
// dr.print(__TIME__);
|
||||
|
||||
// setup run time random seed
|
||||
Serial.println("send 8 chars");
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
while (Serial.available() == 0);
|
||||
dr.print(Serial.read(), HEX);
|
||||
dr.print(micros() * (micros() << 7));
|
||||
dr.read(); // flush intermediate results
|
||||
}
|
||||
// flush input
|
||||
while (Serial.available()) Serial.read();
|
||||
}
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
i++;
|
||||
if (dr.available())
|
||||
{
|
||||
Serial.print("\t");
|
||||
Serial.print(dr.read());
|
||||
if ((i % 10) == 0 ) Serial.println();
|
||||
}
|
||||
delay(100);
|
||||
}
|
||||
|
||||
|
||||
// -- END OF FILE --
|
@ -6,9 +6,16 @@ DEVRANDOM KEYWORD1
|
||||
|
||||
|
||||
# Methods and Functions (KEYWORD2)
|
||||
useAR KEYWORD2
|
||||
useHW KEYWORD2
|
||||
useSW KEYWORD2
|
||||
available KEYWORD2
|
||||
peek KEYWORD2
|
||||
read KEYWORD2
|
||||
flush KEYWORD2
|
||||
write KEYWORD2
|
||||
|
||||
useMarsaglia KEYWORD2
|
||||
useAnalogRead KEYWORD2
|
||||
useDigitalRead KEYWORD2
|
||||
useRandom KEYWORD2
|
||||
getMode KEYWORD2
|
||||
|
||||
|
||||
@ -18,7 +25,8 @@ getMode KEYWORD2
|
||||
# Constants (LITERAL1)
|
||||
#DEVRANDOM_LIB_VERSION LITERAL1
|
||||
|
||||
DEVRANDOM_MODE_SW LITERAL1
|
||||
DEVRANDOM_MODE_HW LITERAL1
|
||||
DEVRANDOM_MODE_AR LITERAL1
|
||||
DEVRANDOM_MODE_RANDOM LITERAL1
|
||||
DEVRANDOM_MODE_DIGITALREAD LITERAL1
|
||||
DEVRANDOM_MODE_ANALOGREAD LITERAL1
|
||||
DEVRANDOM_MODE_MARSAGLIA LITERAL1
|
||||
|
||||
|
@ -15,7 +15,7 @@
|
||||
"type": "git",
|
||||
"url": "https://github.com/RobTillaart/DEVRANDOM.git"
|
||||
},
|
||||
"version": "0.1.3",
|
||||
"version": "0.2.0",
|
||||
"license": "MIT",
|
||||
"frameworks": "arduino",
|
||||
"platforms": "*",
|
||||
|
@ -1,5 +1,5 @@
|
||||
name=DEVRANDOM
|
||||
version=0.1.3
|
||||
version=0.2.0
|
||||
author=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
sentence=Arduino library to wrap a random generator in a stream
|
||||
|
@ -40,50 +40,67 @@ unittest_teardown()
|
||||
|
||||
unittest(test_constants)
|
||||
{
|
||||
assertEqual(0, DEVRANDOM_MODE_SW);
|
||||
assertEqual(1, DEVRANDOM_MODE_HW);
|
||||
assertEqual(2, DEVRANDOM_MODE_AR);
|
||||
assertEqual(0, DEVRANDOM_MODE_RANDOM);
|
||||
assertEqual(1, DEVRANDOM_MODE_DIGITALREAD);
|
||||
assertEqual(2, DEVRANDOM_MODE_ANALOGREAD);
|
||||
assertEqual(3, DEVRANDOM_MODE_MARSAGLIA);
|
||||
}
|
||||
|
||||
|
||||
unittest(test_constructor)
|
||||
{
|
||||
DEVRANDOM dr;
|
||||
|
||||
assertEqual(DEVRANDOM_MODE_SW, dr.getMode());
|
||||
|
||||
dr.useHW(4);
|
||||
assertEqual(DEVRANDOM_MODE_HW, dr.getMode());
|
||||
|
||||
dr.useAR(0);
|
||||
assertEqual(DEVRANDOM_MODE_AR, dr.getMode());
|
||||
|
||||
dr.useSW();
|
||||
assertEqual(DEVRANDOM_MODE_SW, dr.getMode());
|
||||
|
||||
assertEqual(DEVRANDOM_MODE_RANDOM, dr.getMode());
|
||||
|
||||
dr.useDigitalRead(4);
|
||||
assertEqual(DEVRANDOM_MODE_DIGITALREAD, dr.getMode());
|
||||
|
||||
dr.useAnalogRead(0);
|
||||
assertEqual(DEVRANDOM_MODE_ANALOGREAD, dr.getMode());
|
||||
|
||||
dr.useMarsaglia();
|
||||
assertEqual(DEVRANDOM_MODE_MARSAGLIA, dr.getMode());
|
||||
|
||||
dr.useRandom();
|
||||
assertEqual(DEVRANDOM_MODE_RANDOM, dr.getMode());
|
||||
}
|
||||
|
||||
|
||||
unittest(test_constructor_seed)
|
||||
{
|
||||
DEVRANDOM dr_str("hello world");
|
||||
assertEqual(DEVRANDOM_MODE_SW, dr_str.getMode());
|
||||
assertEqual(DEVRANDOM_MODE_RANDOM, dr_str.getMode());
|
||||
|
||||
DEVRANDOM dr_int((uint32_t)123456789);
|
||||
assertEqual(DEVRANDOM_MODE_SW, dr_int.getMode());
|
||||
assertEqual(DEVRANDOM_MODE_RANDOM, dr_int.getMode());
|
||||
|
||||
DEVRANDOM dr_float((float)PI);
|
||||
assertEqual(DEVRANDOM_MODE_SW, dr_float.getMode());
|
||||
assertEqual(DEVRANDOM_MODE_RANDOM, dr_float.getMode());
|
||||
|
||||
}
|
||||
|
||||
|
||||
unittest(test_generator_mode)
|
||||
unittest(test_read)
|
||||
{
|
||||
DEVRANDOM dr;
|
||||
assertEqual(1, dr.available());
|
||||
|
||||
fprintf(stderr, "read() >= 0test\n");
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
assertLessOrEqual(0, dr.read());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
unittest(test_generator_mode_random)
|
||||
{
|
||||
DEVRANDOM dr;
|
||||
|
||||
assertEqual(1, dr.available());
|
||||
|
||||
fprintf(stderr, "peak == read test\n");
|
||||
fprintf(stderr, "peek() == read() test\n");
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
int n = dr.peek();
|
||||
@ -92,6 +109,24 @@ unittest(test_generator_mode)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
unittest(test_generator_mode_Marsaglia)
|
||||
{
|
||||
DEVRANDOM dr;
|
||||
dr.useMarsaglia();
|
||||
|
||||
assertEqual(1, dr.available());
|
||||
|
||||
fprintf(stderr, "peek() == read() test\n");
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
int n = dr.peek();
|
||||
fprintf(stderr,"\t%d\t%d\n", i, n);
|
||||
assertEqual(n, dr.read());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
unittest_main()
|
||||
|
||||
// --------
|
||||
|
Loading…
Reference in New Issue
Block a user