GY-63_MS5611/libraries/DEVRANDOM/DEVRANDOM.cpp
2022-07-03 20:27:42 +02:00

184 lines
2.9 KiB
C++

//
// 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 --